diff --git a/packages/builder/src/mrl/providers/wormhole/extrinsic/polkadotXcm/polkadotXcm.ts b/packages/builder/src/mrl/providers/wormhole/extrinsic/polkadotXcm/polkadotXcm.ts index 8f72998c..79839830 100644 --- a/packages/builder/src/mrl/providers/wormhole/extrinsic/polkadotXcm/polkadotXcm.ts +++ b/packages/builder/src/mrl/providers/wormhole/extrinsic/polkadotXcm/polkadotXcm.ts @@ -4,9 +4,9 @@ import { ExtrinsicBuilder } from '../../../../../extrinsic/ExtrinsicBuilder'; import { ExtrinsicConfig } from '../../../../../types/substrate/ExtrinsicConfig'; import type { MrlConfigBuilder } from '../../../../MrlBuilder.interfaces'; -// TODO: Can we move them somewhere? -const BUY_EXECUTION_FEE = 100_000_000_000_000_000n; -const CROSS_CHAIN_FEE = 100_000_000_000_000_000n; +// TODO: these have to come from the configs +const BUY_EXECUTION_FEE = 100_000_000_000_000_000n; // moonChainFee +const CROSS_CHAIN_FEE = 100_000_000_000_000_000n; // fee for processing the xcm message in moon chain export function polkadotXcm() { return { diff --git a/packages/config/src/ConfigService/ConfigService.ts b/packages/config/src/ConfigService/ConfigService.ts index 837e672f..3f82e59d 100644 --- a/packages/config/src/ConfigService/ConfigService.ts +++ b/packages/config/src/ConfigService/ConfigService.ts @@ -9,11 +9,13 @@ import { chainsMap } from '../chains'; import { getKey } from '../config.utils'; import type { AssetRoute } from '../types/AssetRoute'; import type { ChainRoutes } from '../types/ChainRoutes'; +import type { MrlAssetRoute } from '../types/MrlAssetRoute'; +import type { MrlChainRoutes } from '../types/MrlChainRoutes'; export interface ConfigServiceOptions { assets?: Map; chains?: Map; - routes: Map; + routes: Map; } export class ConfigService { @@ -21,7 +23,7 @@ export class ConfigService { protected chains: Map; - protected routes: Map; + protected routes: Map; constructor(options: ConfigServiceOptions) { this.assets = options.assets ?? assetsMap; @@ -67,7 +69,7 @@ export class ConfigService { return chain; } - getChainRoutes(keyOrChain: string | AnyChain): ChainRoutes { + getChainRoutes(keyOrChain: string | AnyChain): ChainRoutes | MrlChainRoutes { const key = getKey(keyOrChain); const route = this.routes.get(key); @@ -126,7 +128,7 @@ export class ConfigService { asset: string | AnyAsset; source: string | AnyChain; destination: string | AnyChain; - }): AssetRoute { + }): AssetRoute | MrlAssetRoute { const routes = this.getChainRoutes(source); return routes.getAssetRoute(asset, destination); diff --git a/packages/config/src/index.ts b/packages/config/src/index.ts index 4c3ab860..8a93a615 100644 --- a/packages/config/src/index.ts +++ b/packages/config/src/index.ts @@ -4,5 +4,7 @@ export * from './chains'; export * from './config.utils'; export * from './mrl-configs'; export * from './types/AssetRoute'; +export * from './types/MrlAssetRoute'; export * from './types/ChainRoutes'; +export * from './types/MrlChainRoutes'; export * from './xcm-configs'; diff --git a/packages/config/src/mrl-configs/fantomTestnet.ts b/packages/config/src/mrl-configs/fantomTestnet.ts index 3b742504..1f9f8739 100644 --- a/packages/config/src/mrl-configs/fantomTestnet.ts +++ b/packages/config/src/mrl-configs/fantomTestnet.ts @@ -6,9 +6,9 @@ import { moonbaseBeta, peaqAlphanet, } from '../chains'; -import { ChainRoutes } from '../types/ChainRoutes'; +import { MrlChainRoutes } from '../types/MrlChainRoutes'; -export const fantomTestnetRoutes = new ChainRoutes({ +export const fantomTestnetRoutes = new MrlChainRoutes({ chain: fantomTestnet, routes: [ { diff --git a/packages/config/src/mrl-configs/index.ts b/packages/config/src/mrl-configs/index.ts index fdfb929e..cb3baec5 100644 --- a/packages/config/src/mrl-configs/index.ts +++ b/packages/config/src/mrl-configs/index.ts @@ -1,16 +1,18 @@ -import type { ChainRoutes } from '../types/ChainRoutes'; +import type { MrlChainRoutes } from '../types/MrlChainRoutes'; import { fantomTestnetRoutes } from './fantomTestnet'; import { moonbaseAlphaRoutes } from './moonbaseAlpha'; import { moonbaseBetaRoutes } from './moonbaseBeta'; import { peaqAlphanetRoutes } from './peaqAlphanet'; +import { peaqEvmAlphanetRoutes } from './peaqEvmAlphanet'; -export const mrlRoutesList: ChainRoutes[] = [ +export const mrlRoutesList: MrlChainRoutes[] = [ fantomTestnetRoutes, moonbaseAlphaRoutes, moonbaseBetaRoutes, peaqAlphanetRoutes, + peaqEvmAlphanetRoutes, ]; -export const mrlRoutesMap = new Map( +export const mrlRoutesMap = new Map( mrlRoutesList.map((config) => [config.chain.key, config]), ); diff --git a/packages/config/src/mrl-configs/moonbaseAlpha.ts b/packages/config/src/mrl-configs/moonbaseAlpha.ts index fcd61d07..9538185e 100644 --- a/packages/config/src/mrl-configs/moonbaseAlpha.ts +++ b/packages/config/src/mrl-configs/moonbaseAlpha.ts @@ -1,9 +1,9 @@ import { BalanceBuilder, MrlBuilder } from '@moonbeam-network/xcm-builder'; import { dev, ftm, ftmwh } from '../assets'; import { fantomTestnet, moonbaseAlpha } from '../chains'; -import { ChainRoutes } from '../types/ChainRoutes'; +import { MrlChainRoutes } from '../types/MrlChainRoutes'; -export const moonbaseAlphaRoutes = new ChainRoutes({ +export const moonbaseAlphaRoutes = new MrlChainRoutes({ chain: moonbaseAlpha, routes: [ { diff --git a/packages/config/src/mrl-configs/moonbaseBeta.ts b/packages/config/src/mrl-configs/moonbaseBeta.ts index c32e5bb4..00d5b2df 100644 --- a/packages/config/src/mrl-configs/moonbaseBeta.ts +++ b/packages/config/src/mrl-configs/moonbaseBeta.ts @@ -1,9 +1,9 @@ import { BalanceBuilder, MrlBuilder } from '@moonbeam-network/xcm-builder'; import { betaDEV, dev, ftm, ftmwh } from '../assets'; import { fantomTestnet, moonbaseBeta } from '../chains'; -import { ChainRoutes } from '../types/ChainRoutes'; +import { MrlChainRoutes } from '../types/MrlChainRoutes'; -export const moonbaseBetaRoutes = new ChainRoutes({ +export const moonbaseBetaRoutes = new MrlChainRoutes({ chain: moonbaseBeta, routes: [ { diff --git a/packages/config/src/mrl-configs/peaqAlphanet.ts b/packages/config/src/mrl-configs/peaqAlphanet.ts index 4795c67a..a9bd5dc7 100644 --- a/packages/config/src/mrl-configs/peaqAlphanet.ts +++ b/packages/config/src/mrl-configs/peaqAlphanet.ts @@ -1,9 +1,9 @@ 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'; +import { MrlChainRoutes } from '../types/MrlChainRoutes'; -export const peaqAlphanetRoutes = new ChainRoutes({ +export const peaqAlphanetRoutes = new MrlChainRoutes({ chain: peaqAlphanet, routes: [ { @@ -14,6 +14,10 @@ export const peaqAlphanetRoutes = new ChainRoutes({ asset: ftmwh, balance: BalanceBuilder().substrate().assets().account(), }, + moonChainFee: { + asset: dev, + balance: BalanceBuilder().substrate().assets().account(), + }, fee: { asset: agng, balance: BalanceBuilder().substrate().system().account(), @@ -49,6 +53,10 @@ export const peaqAlphanetRoutes = new ChainRoutes({ asset: ftmwh, balance: BalanceBuilder().substrate().assets().account(), }, + moonChainFee: { + asset: dev, + balance: BalanceBuilder().substrate().assets().account(), + }, }, destination: { asset: agng, diff --git a/packages/config/src/mrl-configs/peaqEvmAlphanet.ts b/packages/config/src/mrl-configs/peaqEvmAlphanet.ts new file mode 100644 index 00000000..3c25fbca --- /dev/null +++ b/packages/config/src/mrl-configs/peaqEvmAlphanet.ts @@ -0,0 +1,53 @@ +import { BalanceBuilder, MrlBuilder } from '@moonbeam-network/xcm-builder'; +import { agng, dev, ftm, ftmwh } from '../assets'; +import { fantomTestnet, peaqEvmAlphanet } from '../chains'; +import { MrlChainRoutes } from '../types/MrlChainRoutes'; + +export const peaqEvmAlphanetRoutes = new MrlChainRoutes({ + chain: peaqEvmAlphanet, + routes: [ + { + source: { + asset: ftmwh, + balance: BalanceBuilder().evm().erc20(), + destinationFee: { + asset: ftmwh, + balance: BalanceBuilder().evm().erc20(), + }, + moonChainFee: { + asset: dev, + balance: BalanceBuilder().evm().erc20(), + }, + fee: { + asset: agng, + balance: BalanceBuilder().substrate().system().accountEvmTo32(), + }, + }, + destination: { + asset: ftm, + chain: fantomTestnet, + balance: BalanceBuilder().evm().native(), + fee: { + asset: ftm, + amount: 0, + }, + }, + mrl: { + isAutomaticPossible: true, + transfer: MrlBuilder() + .wormhole() + .contract() + .TokenBridgeRelayer() + .transferTokensWithRelay(), + moonChain: { + asset: ftmwh, + fee: { + asset: dev, + amount: 0.1, + balance: BalanceBuilder().substrate().system().account(), + }, + }, + }, + }, + ], +}); diff --git a/packages/config/src/types/MrlAssetRoute.ts b/packages/config/src/types/MrlAssetRoute.ts new file mode 100644 index 00000000..f23d05a0 --- /dev/null +++ b/packages/config/src/types/MrlAssetRoute.ts @@ -0,0 +1,34 @@ +import type { BalanceConfigBuilder } from '@moonbeam-network/xcm-builder'; +import type { Asset } from '@moonbeam-network/xcm-types'; +import { + AssetRoute, + type AssetRouteConstructorParams, + type SourceConfig, +} from './AssetRoute'; + +export interface MrlAssetRouteConstructorParams + extends AssetRouteConstructorParams { + source: MrlSourceConfig; +} + +export interface MrlSourceConfig extends SourceConfig { + moonChainFee?: { + asset: Asset; + balance: BalanceConfigBuilder; + }; +} + +export class MrlAssetRoute extends AssetRoute { + readonly source: MrlSourceConfig; + + constructor({ + source, + destination, + contract, + extrinsic, + mrl, + }: MrlAssetRouteConstructorParams & { source: MrlSourceConfig }) { + super({ source, destination, contract, extrinsic, mrl }); + this.source = source; + } +} diff --git a/packages/config/src/types/MrlChainRoutes.ts b/packages/config/src/types/MrlChainRoutes.ts new file mode 100644 index 00000000..4aa9b88d --- /dev/null +++ b/packages/config/src/types/MrlChainRoutes.ts @@ -0,0 +1,40 @@ +import { ChainRoutes, type ChainRoutesConstructorParams } from './ChainRoutes'; +import { + MrlAssetRoute, + type MrlAssetRouteConstructorParams, + type MrlSourceConfig, +} from './MrlAssetRoute'; + +export interface MrlChainRoutesConstructorParams + extends ChainRoutesConstructorParams { + routes: MrlRoutesParam[]; +} + +interface MrlRoutesParam + extends Omit { + source: Omit; +} + +export class MrlChainRoutes extends ChainRoutes { + readonly #routes: Map; + + constructor({ chain, routes }: MrlChainRoutesConstructorParams) { + super({ chain, routes }); + this.#routes = new Map( + routes.map(({ source, destination, contract, extrinsic, mrl }) => [ + `${source.asset.key}-${destination.chain.key}`, + new MrlAssetRoute({ + source: { ...source, chain }, + destination, + contract, + extrinsic, + mrl, + }), + ]), + ); + } + + getRoutes(): MrlAssetRoute[] { + return Array.from(this.#routes.values()); + } +} diff --git a/packages/mrl/src/getTransferData/getMoonChainData.ts b/packages/mrl/src/getTransferData/getMoonChainData.ts index e162057d..a93d3a38 100644 --- a/packages/mrl/src/getTransferData/getMoonChainData.ts +++ b/packages/mrl/src/getTransferData/getMoonChainData.ts @@ -1,4 +1,4 @@ -import { type AssetRoute, getMoonChain } from '@moonbeam-network/xcm-config'; +import { type MrlAssetRoute, getMoonChain } from '@moonbeam-network/xcm-config'; import { getBalance, getDestinationFee } from '@moonbeam-network/xcm-sdk'; import { Parachain } from '@moonbeam-network/xcm-types'; import { getMultilocationDerivedAddresses } from '@moonbeam-network/xcm-utils'; @@ -9,7 +9,7 @@ import type { export interface GetMoonChainDataParams { destinationData: DestinationTransferData; - route: AssetRoute; + route: MrlAssetRoute; sourceAddress: string; } diff --git a/packages/mrl/src/getTransferData/getSourceData.ts b/packages/mrl/src/getTransferData/getSourceData.ts index d1a8f29b..7d1d1407 100644 --- a/packages/mrl/src/getTransferData/getSourceData.ts +++ b/packages/mrl/src/getTransferData/getSourceData.ts @@ -4,7 +4,7 @@ import { MrlBuilder, WormholeConfig, } from '@moonbeam-network/xcm-builder'; -import type { AssetRoute, FeeConfig } from '@moonbeam-network/xcm-config'; +import type { FeeConfig, MrlAssetRoute } from '@moonbeam-network/xcm-config'; import { getAssetMin, getBalance, @@ -30,7 +30,7 @@ import { } from './getTransferData.utils'; export interface GetSourceDataParams { - route: AssetRoute; + route: MrlAssetRoute; destinationAddress: string; destinationFee: AssetAmount; sourceAddress: string; @@ -68,6 +68,7 @@ export async function getSourceData({ chain: source, }) : balance; + const destinationFeeBalance = await getDestinationFeeBalance({ balance, feeBalance, @@ -75,6 +76,13 @@ export async function getSourceData({ sourceAddress, }); + const moonChainFeeBalance = await getMoonChainFeeBalance({ + balance, + feeBalance, + route, + sourceAddress, + }); + const existentialDeposit = await getExistentialDeposit(source); const min = await getAssetMin({ asset, @@ -121,6 +129,7 @@ export async function getSourceData({ balance, chain: source, destinationFeeBalance, + moonChainFeeBalance, existentialDeposit, fee, feeBalance, @@ -235,3 +244,42 @@ async function getWormholeFee({ return; } + +export interface GetMoonChainFeeBalanceParams { + balance: AssetAmount; + feeBalance: AssetAmount; + route: MrlAssetRoute; + sourceAddress: string; +} + +export async function getMoonChainFeeBalance({ + balance, + feeBalance, + route, + sourceAddress, +}: GetMoonChainFeeBalanceParams): Promise { + if (!route.source.moonChainFee) { + return undefined; + } + + if (route.mrl?.moonChain.fee.asset.isEqual(balance)) { + return balance; + } + + if (route.mrl?.moonChain.fee.asset.isEqual(feeBalance)) { + return feeBalance; + } + + if (!route.source.moonChainFee.balance) { + throw new Error( + 'BalanceBuilder must be defined for source.moonChainFee.balance for MrlAssetRoute', + ); + } + + return getBalance({ + address: sourceAddress, + asset: route.source.chain.getChainAsset(route.source.moonChainFee.asset), + builder: route.source.moonChainFee.balance, + chain: route.source.chain, + }); +} diff --git a/packages/mrl/src/getTransferData/getTransferData.ts b/packages/mrl/src/getTransferData/getTransferData.ts index 1072c43a..3c5189ed 100644 --- a/packages/mrl/src/getTransferData/getTransferData.ts +++ b/packages/mrl/src/getTransferData/getTransferData.ts @@ -3,7 +3,7 @@ import { ExtrinsicConfig, WormholeConfig, } from '@moonbeam-network/xcm-builder'; -import type { AssetRoute } from '@moonbeam-network/xcm-config'; +import type { MrlAssetRoute } from '@moonbeam-network/xcm-config'; import { EvmService, PolkadotService, @@ -29,7 +29,7 @@ import { } from './getTransferData.utils'; export interface GetTransferDataParams { - route: AssetRoute; + route: MrlAssetRoute; sourceAddress: string; destinationAddress: string; } diff --git a/packages/mrl/src/mrl.interfaces.ts b/packages/mrl/src/mrl.interfaces.ts index f8de15d3..4413a283 100644 --- a/packages/mrl/src/mrl.interfaces.ts +++ b/packages/mrl/src/mrl.interfaces.ts @@ -24,6 +24,7 @@ export interface TransferData { export interface SourceTransferData extends SourceChainTransferData { destinationFeeBalance: AssetAmount; + moonChainFeeBalance?: AssetAmount; relayerFee?: AssetAmount; feeBalance: AssetAmount; max: AssetAmount;