From 77ca1eb5951400da4c9abbeb0b4731b717dbaae8 Mon Sep 17 00:00:00 2001 From: Mario J Maurello Date: Fri, 4 Oct 2024 17:53:25 +0200 Subject: [PATCH] revert change in extrinsic builder and add relay fee calculation in source data withj provider checking --- .../builder/src/mrl/MrlBuilder.constants.ts | 4 + .../builder/src/mrl/MrlBuilder.interfaces.ts | 16 ++-- .../contract/TokenBridge/TokenBridge.ts | 2 + .../TokenBridgeRelayer/TokenBridgeRelayer.ts | 2 + .../extrinsic/ethereumXcm/ethereumXcm.ts | 6 +- .../extrinsic/polkadotXcm/polkadotXcm.ts | 12 +-- .../providers/wormhole/wormhole/wormhole.ts | 7 +- .../mrl/src/getTransferData/getSourceData.ts | 83 ++++++++++++------- .../getTransferData/getTransferData.utils.ts | 31 ++++--- 9 files changed, 99 insertions(+), 64 deletions(-) diff --git a/packages/builder/src/mrl/MrlBuilder.constants.ts b/packages/builder/src/mrl/MrlBuilder.constants.ts index a9e9fc33..bbc56813 100644 --- a/packages/builder/src/mrl/MrlBuilder.constants.ts +++ b/packages/builder/src/mrl/MrlBuilder.constants.ts @@ -1,2 +1,6 @@ export const BATCH_CONTRACT_ADDRESS = '0x0000000000000000000000000000000000000808'; + +export enum Provider { + WORMHOLE = 'Wormhole', +} diff --git a/packages/builder/src/mrl/MrlBuilder.interfaces.ts b/packages/builder/src/mrl/MrlBuilder.interfaces.ts index ff2b1d29..c6bc9e5d 100644 --- a/packages/builder/src/mrl/MrlBuilder.interfaces.ts +++ b/packages/builder/src/mrl/MrlBuilder.interfaces.ts @@ -8,17 +8,15 @@ import type { HexString } from '@polkadot/util/types'; import type { BuilderPrams, ConfigBuilder } from '../builder.interfaces'; import type { ContractConfig } from '../contract'; import type { ExtrinsicConfig } from '../extrinsic'; +import type { Provider } from './MrlBuilder.constants'; import type { WormholeConfig } from './providers/wormhole/wormhole'; -export type MrlConfigBuilder = ConfigBuilder< - ContractConfig | ExtrinsicConfig | ExtrinsicWormholeConfig | WormholeConfig, - MrlBuilderParams ->; - -// TODO review this -export interface ExtrinsicWormholeConfig { - extrinsic: ExtrinsicConfig; - wormholeConfig: WormholeConfig; +export interface MrlConfigBuilder + extends ConfigBuilder< + ContractConfig | ExtrinsicConfig | WormholeConfig, + MrlBuilderParams + > { + provider: Provider; } export interface MrlBuilderParams extends BuilderPrams { diff --git a/packages/builder/src/mrl/providers/wormhole/contract/TokenBridge/TokenBridge.ts b/packages/builder/src/mrl/providers/wormhole/contract/TokenBridge/TokenBridge.ts index 780c3a9a..e2740d74 100644 --- a/packages/builder/src/mrl/providers/wormhole/contract/TokenBridge/TokenBridge.ts +++ b/packages/builder/src/mrl/providers/wormhole/contract/TokenBridge/TokenBridge.ts @@ -1,6 +1,7 @@ import { convertAddressTo32Bytes } from '@moonbeam-network/xcm-utils'; import type { Address } from 'viem'; import { ContractConfig } from '../../../../../contract'; +import { Provider } from '../../../../MrlBuilder.constants'; import type { MrlConfigBuilder } from '../../../../MrlBuilder.interfaces'; import { wormholeFactory } from '../../wormhole'; import { TOKEN_BRIDGE_ABI } from './TokenBridgeAbi'; @@ -10,6 +11,7 @@ const module = 'TokenBridge'; export function TokenBridge() { return { transferTokens: (): MrlConfigBuilder => ({ + provider: Provider.WORMHOLE, build: ({ asset, destination, destinationAddress, moonChain }) => { const wh = wormholeFactory(moonChain); const whDestination = wh.getChain(destination.getWormholeName()).config diff --git a/packages/builder/src/mrl/providers/wormhole/contract/TokenBridgeRelayer/TokenBridgeRelayer.ts b/packages/builder/src/mrl/providers/wormhole/contract/TokenBridgeRelayer/TokenBridgeRelayer.ts index ec92a86e..8aa0fcf6 100644 --- a/packages/builder/src/mrl/providers/wormhole/contract/TokenBridgeRelayer/TokenBridgeRelayer.ts +++ b/packages/builder/src/mrl/providers/wormhole/contract/TokenBridgeRelayer/TokenBridgeRelayer.ts @@ -1,6 +1,7 @@ import { convertAddressTo32Bytes } from '@moonbeam-network/xcm-utils'; import type { Address } from 'viem'; import { ContractConfig } from '../../../../../contract'; +import { Provider } from '../../../../MrlBuilder.constants'; import type { MrlConfigBuilder } from '../../../../MrlBuilder.interfaces'; import { wormholeFactory } from '../../wormhole'; import { TOKEN_BRIDGE_RELAYER_ABI } from './TokenBridgeRelayerAbi'; @@ -10,6 +11,7 @@ const module = 'TokenBridgeRelayer'; export function TokenBridgeRelayer() { return { transferTokensWithRelay: (): MrlConfigBuilder => ({ + provider: Provider.WORMHOLE, build: ({ asset, destination, destinationAddress, moonChain }) => { const wh = wormholeFactory(moonChain); const whDestination = wh.getChain(destination.getWormholeName()).config diff --git a/packages/builder/src/mrl/providers/wormhole/extrinsic/ethereumXcm/ethereumXcm.ts b/packages/builder/src/mrl/providers/wormhole/extrinsic/ethereumXcm/ethereumXcm.ts index 88b28fe1..a8b15dfc 100644 --- a/packages/builder/src/mrl/providers/wormhole/extrinsic/ethereumXcm/ethereumXcm.ts +++ b/packages/builder/src/mrl/providers/wormhole/extrinsic/ethereumXcm/ethereumXcm.ts @@ -2,7 +2,10 @@ import { type Address, encodeFunctionData } from 'viem'; import { ERC20_ABI } from '../../../../../balance/Erc20Abi'; import type { ContractConfig } from '../../../../../types/evm/ContractConfig'; import { ExtrinsicConfig } from '../../../../../types/substrate/ExtrinsicConfig'; -import { BATCH_CONTRACT_ADDRESS } from '../../../../MrlBuilder.constants'; +import { + BATCH_CONTRACT_ADDRESS, + Provider, +} from '../../../../MrlBuilder.constants'; import type { MrlConfigBuilder } from '../../../../MrlBuilder.interfaces'; import { contract as ContractBuilder } from '../../contract'; import { BATCH_CONTRACT_ABI } from './BatchContractAbi'; @@ -10,6 +13,7 @@ import { BATCH_CONTRACT_ABI } from './BatchContractAbi'; export function ethereumXcm() { return { transact: (): MrlConfigBuilder => ({ + provider: Provider.WORMHOLE, build: (params) => { const { asset, isAutomatic, moonChain, moonGasLimit } = params; 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 9167b84b..785a2a2f 100644 --- a/packages/builder/src/mrl/providers/wormhole/extrinsic/polkadotXcm/polkadotXcm.ts +++ b/packages/builder/src/mrl/providers/wormhole/extrinsic/polkadotXcm/polkadotXcm.ts @@ -3,6 +3,7 @@ import { getMultilocationDerivedAddresses } from '@moonbeam-network/xcm-utils'; import { ExtrinsicBuilder } from '../../../../../extrinsic/ExtrinsicBuilder'; import { ExtrinsicConfig } from '../../../../../types/substrate/ExtrinsicConfig'; import { MrlBuilder } from '../../../../MrlBuilder'; +import { Provider } from '../../../../MrlBuilder.constants'; import type { MrlConfigBuilder } from '../../../../MrlBuilder.interfaces'; import type { WormholeConfig } from '../../wormhole'; @@ -13,6 +14,7 @@ const CROSS_CHAIN_FEE = 100_000_000_000_000_000n; export function polkadotXcm() { return { send: (): MrlConfigBuilder => ({ + provider: Provider.WORMHOLE, build: (params) => { const { asset, @@ -167,19 +169,11 @@ export function polkadotXcm() { ); // TODO add here ability to only send the remote execution (only `send`) - const extrinsic = new ExtrinsicConfig({ + return new ExtrinsicConfig({ module: 'utility', func: 'batchAll', getArgs: () => [[assetTransferTx, feeAssetTransferTx, send]], }); - - const wormholeConfig = MrlBuilder() - .wormhole() - .wormhole() - .tokenTransfer() - .build(params) as WormholeConfig; // TODO make wormhole build to return this? - - return { extrinsic, wormholeConfig }; }, }), }; diff --git a/packages/builder/src/mrl/providers/wormhole/wormhole/wormhole.ts b/packages/builder/src/mrl/providers/wormhole/wormhole/wormhole.ts index cf3b6f75..5f4321d2 100644 --- a/packages/builder/src/mrl/providers/wormhole/wormhole/wormhole.ts +++ b/packages/builder/src/mrl/providers/wormhole/wormhole/wormhole.ts @@ -3,6 +3,7 @@ import { getMultilocationDerivedAddresses } from '@moonbeam-network/xcm-utils'; import { evmToAddress } from '@polkadot/util-crypto/address'; import { Wormhole } from '@wormhole-foundation/sdk-connect'; import { getExtrinsicAccount } from '../../../../extrinsic/ExtrinsicBuilder.utils'; +import { Provider } from '../../../MrlBuilder.constants'; import type { MrlBuilderParams, MrlConfigBuilder, @@ -16,8 +17,10 @@ export const GMP_CONTRACT_ADDRESS = export function wormhole() { return { tokenTransfer: (): MrlConfigBuilder => ({ + provider: Provider.WORMHOLE, build: (params): WormholeConfig => { - const args = generateWormholeArgs(params); + // TODO not needed to be extracted anymore + const args = getWormholeArgs(params); return new WormholeConfig({ args, @@ -28,7 +31,7 @@ export function wormhole() { }; } -export function generateWormholeArgs({ +export function getWormholeArgs({ asset, destination, destinationAddress, diff --git a/packages/mrl/src/getTransferData/getSourceData.ts b/packages/mrl/src/getTransferData/getSourceData.ts index fe69a9aa..0cda6363 100644 --- a/packages/mrl/src/getTransferData/getSourceData.ts +++ b/packages/mrl/src/getTransferData/getSourceData.ts @@ -1,7 +1,8 @@ import { ContractConfig, - ExtrinsicConfig, - type ExtrinsicWormholeConfig, + type ExtrinsicConfig, + MrlBuilder, + Provider, WormholeConfig, } from '@moonbeam-network/xcm-builder'; import type { AssetRoute, FeeConfig } from '@moonbeam-network/xcm-config'; @@ -23,7 +24,11 @@ import { } from '@moonbeam-network/xcm-types'; import type { SourceTransferData } from '../mrl.interfaces'; import { WormholeService } from '../services/wormhole'; -import { buildTransfer } from './getTransferData.utils'; +import { + type BuildTransferParams, + buildTransfer, + getMrlBuilderParams, +} from './getTransferData.utils'; export interface GetSourceDataParams { route: AssetRoute; @@ -97,9 +102,13 @@ export async function getSourceData({ }); const relayFee = await getRelayFee({ - balance, chain: source, transfer, + asset: balance, + destinationAddress, + destinationFee, + route, + sourceAddress, }); const max = getMax({ @@ -129,21 +138,12 @@ export interface GetFeeParams { feeBalance: AssetAmount; feeConfig?: FeeConfig; sourceAddress: string; - transfer: - | ContractConfig - | ExtrinsicConfig - | ExtrinsicWormholeConfig - | WormholeConfig; + transfer: ContractConfig | ExtrinsicConfig | WormholeConfig; } -export interface GetRelayFeeParams { - balance: AssetAmount; +export interface GetRelayFeeParams extends BuildTransferParams { chain: AnyChain; - transfer: - | ContractConfig - | ExtrinsicConfig - | ExtrinsicWormholeConfig - | WormholeConfig; + transfer: ContractConfig | ExtrinsicConfig | WormholeConfig; } export async function getFee({ @@ -173,37 +173,56 @@ export async function getFee({ }); } - const extrinsic = ExtrinsicConfig.is(transfer) - ? transfer - : transfer.extrinsic; - return getExtrinsicFee({ address: sourceAddress, balance, chain: chain as AnyParachain, - extrinsic, + extrinsic: transfer, feeBalance, feeConfig, }); } export async function getRelayFee({ - balance, + asset, chain, + destinationAddress, + destinationFee, + route, + sourceAddress, transfer, }: GetRelayFeeParams): Promise { - if (ExtrinsicConfig.is(transfer) || ContractConfig.is(transfer)) { - return undefined; + if (WormholeConfig.is(transfer)) { + const wh = WormholeService.create(chain as EvmChain | EvmParachain); + const fee = await wh.getFee(transfer); + + return AssetAmount.fromChainAsset(chain.getChainAsset(asset), { + amount: fee.relayFee?.amount || 0n, + }); } - const wormholeConfig = WormholeConfig.is(transfer) - ? transfer - : transfer.wormholeConfig; + if (route?.mrl?.transfer.provider === Provider.WORMHOLE) { + const builderParams = await getMrlBuilderParams({ + asset, + destinationAddress, + destinationFee, + route, + sourceAddress, + }); + + const wormholeConfig = MrlBuilder() + .wormhole() + .wormhole() + .tokenTransfer() + .build(builderParams) as WormholeConfig; // TODO specify in the build function? - const wh = WormholeService.create(chain as EvmChain | EvmParachain); - const fee = await wh.getFee(wormholeConfig); + const wh = WormholeService.create(chain as EvmChain | EvmParachain); + const fee = await wh.getFee(wormholeConfig); - return AssetAmount.fromChainAsset(chain.getChainAsset(balance), { - amount: fee.relayFee?.amount || 0n, - }); + return AssetAmount.fromChainAsset(chain.getChainAsset(asset), { + amount: fee.relayFee?.amount || 0n, + }); + } + + return; } diff --git a/packages/mrl/src/getTransferData/getTransferData.utils.ts b/packages/mrl/src/getTransferData/getTransferData.utils.ts index ef82e655..7aab9fee 100644 --- a/packages/mrl/src/getTransferData/getTransferData.utils.ts +++ b/packages/mrl/src/getTransferData/getTransferData.utils.ts @@ -93,19 +93,35 @@ export interface BuildTransferParams { sourceAddress: string; } -export async function buildTransfer({ +export async function buildTransfer(params: BuildTransferParams) { + // TODO mjm unify with check below + if (!params.route.mrl) { + throw new Error( + `MrlConfigBuilder is not defined for source chain ${params.route.source.chain.name} and asset ${params.route.source.asset.originSymbol}`, + ); + } + const builderParams = await getMrlBuilderParams(params); + + return params.route.mrl.transfer.build({ + ...builderParams, + transact: EvmParachain.isAnyParachain(params.route.source.chain) // TODO deconstruct? + ? await getTransact(builderParams) + : undefined, + }); +} + +export async function getMrlBuilderParams({ asset, destinationAddress, destinationFee, route, sourceAddress, -}: BuildTransferParams) { +}: BuildTransferParams): Promise { if (!route.mrl) { throw new Error( `MrlConfigBuilder is not defined for source chain ${route.source.chain.name} and asset ${route.source.asset.originSymbol}`, ); } - const source = route.source.chain; const destination = route.destination.chain; @@ -118,7 +134,7 @@ export async function buildTransfer({ getPolkadotApi(moonChain.ws), ]); - const params: MrlBuilderParams = { + return { asset, destination, destinationAddress, @@ -132,13 +148,6 @@ export async function buildTransfer({ sourceAddress, sourceApi, }; - - return route.mrl.transfer.build({ - ...params, - transact: EvmParachain.isAnyParachain(source) - ? await getTransact(params) - : undefined, - }); } export async function getTransact(params: MrlBuilderParams): Promise {