Skip to content

Commit

Permalink
Allow Parachains/Moonbase to Evm Routes (#361)
Browse files Browse the repository at this point in the history
* add moonbase to fantom routes and fix configuration accordingly to consider moonChain as source

* add peaqAlphanet routes

* fix moonAsset retrieval

* fix asset in relayer fee

* remove comment

* udpate snap
  • Loading branch information
mmaurello authored Oct 3, 2024
1 parent 9f08b2c commit 7531461
Show file tree
Hide file tree
Showing 13 changed files with 217 additions and 57 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"darwiniacrab",
"derivated",
"dwellir",
"extrinsics",
"foucoco",
"ftmwh",
"fullnode",
Expand Down
1 change: 1 addition & 0 deletions cspell.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module.exports = {
'**/*.ts.snap',
'**/*.sol',
'pnpm-lock.yaml',
'CHANGELOG.md',
],
words: vscodeConfig['cSpell.words'],
};
2 changes: 1 addition & 1 deletion mkdocs/docs/reference/interfaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -829,7 +829,7 @@ Defines the fees for a particular asset on the destination chain.
</div>

```js title="Example"
// The Desintation Fee Asset Config object
// The Destination Fee Asset Config object
// For configuring USDT to be sent from
// the Polkadot Asset Hub to Moonbeam
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ ExtrinsicConfig {

exports[`polkadotXcm > send > should get correct arguments 1`] = `
[
"xTokens.transfer => RESULT",
"xTokens.transfer => RESULT",
"polkadotXcm.send => RESULT",
[
"xTokens.transfer => RESULT",
"xTokens.transfer => RESULT",
"polkadotXcm.send => RESULT",
],
]
`;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import {
type AnyParachain,
AssetAmount,
EvmParachain,
} from '@moonbeam-network/xcm-types';
import { type AnyParachain, AssetAmount } from '@moonbeam-network/xcm-types';
import { getMultilocationDerivedAddresses } from '@moonbeam-network/xcm-utils';
import { ExtrinsicBuilder } from '../../../../../extrinsic/ExtrinsicBuilder';
import { ExtrinsicConfig } from '../../../../../types/substrate/ExtrinsicConfig';
Expand All @@ -23,6 +19,7 @@ export function polkadotXcm() {
fee,
moonAsset,
moonChain,
moonApi,
source,
sourceAddress,
sourceApi,
Expand All @@ -32,12 +29,6 @@ export function polkadotXcm() {
throw new Error('Destination chain does not have a wormhole name');
}

if (!EvmParachain.isAnyParachain(destination)) {
throw new Error(
`Destination ${destination.name} is not a Parachain or EvmParachain`,
);
}

if (!transact) {
throw new Error('Transact params are required');
}
Expand All @@ -46,16 +37,23 @@ export function polkadotXcm() {
throw new Error('Source API needs to be defined');
}

const { address20: computedOriginAccount } =
getMultilocationDerivedAddresses({
address: sourceAddress,
paraId: moonChain.parachainId,
isParents: true,
});

const { transfer } = sourceApi.tx.xTokens;
const builder = ExtrinsicBuilder().xTokens().transfer();

const assetTransferTx = transfer(
builder
...builder
.build({
asset,
destination,
destinationAddress,
destinationApi,
destination: moonChain,
destinationAddress: computedOriginAccount,
destinationApi: moonApi,
fee,
// TODO: This is a workaround. xTokens.transfer doesn't need source chain but the interfaces requires it.
// In this case we know that a source chain is not a Parachain.
Expand All @@ -71,14 +69,17 @@ export function polkadotXcm() {
* Also we need to move fees to AssetRoute.
*/
const feeAssetTransferTx = transfer(
builder
...builder
.build({
asset: AssetAmount.fromChainAsset(moonAsset, {
amount: CROSS_CHAIN_FEE + BUY_EXECUTION_FEE,
}),
destination,
destinationAddress,
destinationApi,
asset: AssetAmount.fromChainAsset(
source.getChainAsset(moonAsset),
{
amount: CROSS_CHAIN_FEE + BUY_EXECUTION_FEE,
},
),
destination: moonChain,
destinationAddress: computedOriginAccount,
destinationApi: moonApi,
fee,
source: source as AnyParachain,
sourceAddress,
Expand All @@ -87,12 +88,6 @@ export function polkadotXcm() {
.getArgs(transfer),
);

const { address20 } = getMultilocationDerivedAddresses({
address: sourceAddress,
paraId: moonChain.parachainId,
isParents: true,
});

const send = sourceApi.tx.polkadotXcm.send(
{
V3: {
Expand Down Expand Up @@ -158,7 +153,7 @@ export function polkadotXcm() {
beneficiary: {
parents: 0,
interior: {
X1: { AccountKey20: { key: address20 } },
X1: { AccountKey20: { key: computedOriginAccount } },
},
},
},
Expand All @@ -169,10 +164,11 @@ export function polkadotXcm() {
},
);

// TODO add here ability to only send the remote execution (only `send`)
return new ExtrinsicConfig({
module: 'utility',
func: 'batchAll',
getArgs: () => [assetTransferTx, feeAssetTransferTx, send],
getArgs: () => [[assetTransferTx, feeAssetTransferTx, send]],
});
},
}),
Expand Down
19 changes: 12 additions & 7 deletions packages/builder/src/mrl/providers/wormhole/wormhole/wormhole.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { EvmParachain } from '@moonbeam-network/xcm-types';
import { EvmChain, EvmParachain } from '@moonbeam-network/xcm-types';
import { evmToAddress } from '@polkadot/util-crypto/address';
import { Wormhole } from '@wormhole-foundation/sdk-connect';
import { getExtrinsicAccount } from '../../../../extrinsic/ExtrinsicBuilder.utils';
Expand Down Expand Up @@ -27,6 +27,7 @@ export function wormhole() {
}) => {
const isNativeAsset = asset.isSame(source.nativeAsset);
const isDestinationMoonChain = destination.isEqual(moonChain);
const isDestinationEvmChain = EvmChain.is(destination);
const tokenAddress = isNativeAsset ? 'native' : asset.address;

if (!tokenAddress) {
Expand All @@ -35,25 +36,29 @@ export function wormhole() {

const wh = wormholeFactory(source);
const whSource = wh.getChain(source.getWormholeName());
const whMoonChain = wh.getChain(moonChain.getWormholeName());
const whDestination = isDestinationEvmChain
? wh.getChain(destination.getWormholeName())
: wh.getChain(moonChain.getWormholeName());
const whAsset = Wormhole.tokenId(whSource.chain, tokenAddress);
const whSourceAddress = Wormhole.chainAddress(
whSource.chain,
sourceAddress,
);
const whMoonChainAddress = Wormhole.chainAddress(
whMoonChain.chain,
isDestinationMoonChain ? destinationAddress : GMP_CONTRACT_ADDRESS,
const whDestinationAddress = Wormhole.chainAddress(
whDestination.chain,
isDestinationMoonChain || isDestinationEvmChain
? destinationAddress
: GMP_CONTRACT_ADDRESS,
);

return new WormholeConfig({
args: [
whAsset,
asset.amount,
whSourceAddress,
whMoonChainAddress,
whDestinationAddress,
isAutomatic,
isDestinationMoonChain
isDestinationMoonChain || isDestinationEvmChain
? undefined
: getPayload({ destination, destinationAddress, moonApi }),
],
Expand Down
2 changes: 1 addition & 1 deletion packages/config/src/mrl-configs/fantomTestnet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export const fantomTestnetRoutes = new ChainRoutes({
},
},
mrl: {
isAutomatic: false,
isAutomatic: true,
transfer: MrlBuilder().wormhole().wormhole().tokenTransfer(),
moonChain: {
asset: ftmwh,
Expand Down
8 changes: 7 additions & 1 deletion packages/config/src/mrl-configs/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import type { ChainRoutes } from '../types/ChainRoutes';
import { fantomTestnetRoutes } from './fantomTestnet';
import { moonbaseAlphaRoutes } from './moonbaseAlpha';
import { peaqAlphanetRoutes } from './peaqAlphanet';

export const mrlRoutesList: ChainRoutes[] = [fantomTestnetRoutes];
export const mrlRoutesList: ChainRoutes[] = [
fantomTestnetRoutes,
moonbaseAlphaRoutes,
peaqAlphanetRoutes,
];

export const mrlRoutesMap = new Map<string, ChainRoutes>(
mrlRoutesList.map((config) => [config.chain.key, config]),
Expand Down
72 changes: 72 additions & 0 deletions packages/config/src/mrl-configs/moonbaseAlpha.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { BalanceBuilder, MrlBuilder } from '@moonbeam-network/xcm-builder';
import { dev, ftm, ftmwh } from '../assets';
import { fantomTestnet, moonbaseAlpha } from '../chains';
import { ChainRoutes } from '../types/ChainRoutes';

export const moonbaseAlphaRoutes = new ChainRoutes({
chain: moonbaseAlpha,
routes: [
{
source: {
asset: ftmwh,
balance: BalanceBuilder().evm().erc20(),
destinationFee: {
asset: ftmwh,
balance: BalanceBuilder().evm().erc20(),
},
},
destination: {
asset: ftm,
chain: fantomTestnet,
balance: BalanceBuilder().evm().native(),
fee: {
asset: ftm,
amount: 0,
},
},
mrl: {
isAutomatic: true,
transfer: MrlBuilder().wormhole().wormhole().tokenTransfer(),
moonChain: {
asset: ftmwh,
fee: {
asset: dev,
amount: 0.1, // TODO not really, it would be the source fee as source is moonChain
balance: BalanceBuilder().substrate().system().account(),
},
},
},
},
{
source: {
asset: dev,
balance: BalanceBuilder().substrate().system().account(),
destinationFee: {
asset: dev,
balance: BalanceBuilder().substrate().system().account(),
},
},
destination: {
asset: dev,
chain: fantomTestnet,
balance: BalanceBuilder().evm().erc20(),
fee: {
asset: dev,
amount: 0,
},
},
mrl: {
isAutomatic: true,
transfer: MrlBuilder().wormhole().wormhole().tokenTransfer(),
moonChain: {
asset: dev,
fee: {
asset: dev,
amount: 0.1,
balance: BalanceBuilder().substrate().system().account(),
},
},
},
},
],
});
76 changes: 76 additions & 0 deletions packages/config/src/mrl-configs/peaqAlphanet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { BalanceBuilder, MrlBuilder } from '@moonbeam-network/xcm-builder';
import { agng, dev, ftm, ftmwh } from '../assets';
import { fantomTestnet, peaqAlphanet } from '../chains';
import { ChainRoutes } from '../types/ChainRoutes';

export const peaqAlphanetRoutes = new ChainRoutes({
chain: peaqAlphanet,
routes: [
{
source: {
asset: ftmwh,
balance: BalanceBuilder().substrate().assets().account(),
destinationFee: {
asset: ftmwh,
balance: BalanceBuilder().substrate().assets().account(),
},
fee: {
asset: agng,
balance: BalanceBuilder().substrate().system().account(),
},
},
destination: {
asset: ftm,
chain: fantomTestnet,
balance: BalanceBuilder().evm().native(),
fee: {
asset: ftm,
amount: 0,
},
},
mrl: {
isAutomatic: true,
transfer: MrlBuilder().wormhole().extrinsic().polkadotXcm().send(),
moonChain: {
asset: ftmwh,
fee: {
asset: dev,
amount: 0.1,
balance: BalanceBuilder().substrate().system().account(),
},
},
},
},
{
source: {
asset: agng,
balance: BalanceBuilder().substrate().system().account(),
destinationFee: {
asset: ftmwh,
balance: BalanceBuilder().substrate().assets().account(),
},
},
destination: {
asset: ftm,
chain: fantomTestnet,
balance: BalanceBuilder().evm().native(),
fee: {
asset: ftm,
amount: 0,
},
},
mrl: {
isAutomatic: true,
transfer: MrlBuilder().wormhole().extrinsic().polkadotXcm().send(),
moonChain: {
asset: ftmwh,
fee: {
asset: dev,
amount: 0.1,
balance: BalanceBuilder().substrate().system().account(),
},
},
},
},
],
});
4 changes: 2 additions & 2 deletions packages/mrl/src/getTransferData/getMoonChainData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ export async function getMoonChainData({

const fee = await getDestinationFee({
address: sourceAddress, // TODO not correct
asset: route.destination.fee.asset,
chain: moonChain,
asset: route.mrl.moonChain.fee.asset,
destination: moonChain,
fee: route.mrl.moonChain.fee.amount,
transferAsset: route.source.asset,
});
Expand Down
Loading

0 comments on commit 7531461

Please sign in to comment.