Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Parachains/Moonbase to Evm Routes #361

Merged
merged 7 commits into from
Oct 3, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
@@ -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
Loading