diff --git a/packages/builder/src/extrinsic/mrl/wormhole/ethereumXcm/ethereumXcm.ts b/packages/builder/src/extrinsic/mrl/wormhole/ethereumXcm/ethereumXcm.ts index b27923bd..62b02ec4 100644 --- a/packages/builder/src/extrinsic/mrl/wormhole/ethereumXcm/ethereumXcm.ts +++ b/packages/builder/src/extrinsic/mrl/wormhole/ethereumXcm/ethereumXcm.ts @@ -1,13 +1,12 @@ import { convertAddressTo32Bytes } from '@moonbeam-network/xcm-utils'; import { Address, encodeFunctionData } from 'viem'; -import { Wormhole } from '@wormhole-foundation/sdk-connect'; -import { EvmPlatform } from '@wormhole-foundation/sdk-evm'; import { MrlExtrinsicConfigBuilder } from '../../../ExtrinsicBuilder.interfaces'; import { ExtrinsicConfig } from '../../../ExtrinsicConfig'; import { BATCH_CONTRACT_ABI } from './BatchContractAbi'; import { ERC20_ABI } from './Erc20Abi'; import { TOKEN_BRIDGE_ABI } from './TokenBridgeAbi'; import { TOKEN_BRIDGE_RELAYER_ABI } from './TokenBridgeRelayerAbi'; +import { wormholeFactory } from '../../../../wormhole'; export const BATCH_CONTRACT_ADDRESS = '0x0000000000000000000000000000000000000808'; @@ -26,16 +25,8 @@ export function ethereumXcm() { moonChain, moonGasLimit, }) => { - if (!destination.wh?.name) { - throw new Error( - `Destination chain ${destination.name} does not have a wormhole name`, - ); - } - - const wh = new Wormhole(moonChain.isTestChain ? 'Testnet' : 'Mainnet', [ - EvmPlatform, - ]); - const whDestinationChain = wh.getChain(destination.wh.name).config + const wh = wormholeFactory(moonChain); + const whDestination = wh.getChain(destination.getWormholeName()).config .chainId; const whContractAddress = ( isAutomatic @@ -72,7 +63,7 @@ export function ethereumXcm() { tokenAddressOnMoonChain, tokenAmountOnMoonChain, 0, - whDestinationChain, + whDestination, destinationAddress32bytes, 0, ], @@ -83,7 +74,7 @@ export function ethereumXcm() { args: [ tokenAddressOnMoonChain, tokenAmountOnMoonChain, - whDestinationChain, + whDestination, destinationAddress32bytes, 0n, 0, diff --git a/packages/builder/src/wormhole/Wormhole.ts b/packages/builder/src/wormhole/Wormhole.ts new file mode 100644 index 00000000..b0644ea7 --- /dev/null +++ b/packages/builder/src/wormhole/Wormhole.ts @@ -0,0 +1,53 @@ +import { Wormhole } from '@wormhole-foundation/sdk-connect'; +import { WormholeConfigBuilder } from './WormholeBuilder.interfaces'; +import { WormholeConfig } from './WormholeConfig'; +import { wormholeFactory } from './wormholeFactory'; + +export function WormholeBuilder() { + return { + tokenTransfer: ({ + isAutomatic, + }: { + isAutomatic: boolean; + }): WormholeConfigBuilder => ({ + build: ({ + asset, + destination, + destinationAddress, + payload, + source, + sourceAddress, + }) => { + const wh = wormholeFactory(source); + const whSource = wh.getChain(source.getWormholeName()); + const whDestination = wh.getChain(destination.getWormholeName()); + + if (!asset.address) { + throw new Error('Asset address is required'); + } + + const whAsset = Wormhole.tokenId(whSource.chain, asset.address); + const whSourceAddress = Wormhole.chainAddress( + whSource.chain, + sourceAddress, + ); + const whDestinationAddress = Wormhole.chainAddress( + whDestination.chain, + destinationAddress, + ); + + return new WormholeConfig({ + args: [ + whAsset, + asset.amount, + whSourceAddress, + whDestinationAddress, + isAutomatic, + payload, + ], + func: 'transfer', + }); + }, + }), + }; +} diff --git a/packages/builder/src/wormhole/WormholeBuilder.interfaces.ts b/packages/builder/src/wormhole/WormholeBuilder.interfaces.ts new file mode 100644 index 00000000..45cf4b7a --- /dev/null +++ b/packages/builder/src/wormhole/WormholeBuilder.interfaces.ts @@ -0,0 +1,15 @@ +import { AnyChain, AssetAmount } from '@moonbeam-network/xcm-types'; +import { WormholeConfig } from './WormholeConfig'; + +export interface WormholeConfigBuilder { + build: (params: WormholeConfigBuilderPrams) => WormholeConfig; +} + +export interface WormholeConfigBuilderPrams { + asset: AssetAmount; + destination: AnyChain; + destinationAddress: string; + source: AnyChain; + sourceAddress: string; + payload?: Uint8Array; +} diff --git a/packages/builder/src/wormhole/WormholeConfig.ts b/packages/builder/src/wormhole/WormholeConfig.ts new file mode 100644 index 00000000..8a3def8c --- /dev/null +++ b/packages/builder/src/wormhole/WormholeConfig.ts @@ -0,0 +1,15 @@ +export interface WormholeConfigConstructorParams { + args: unknown[]; + func: string; +} + +export class WormholeConfig { + readonly args: unknown[]; + + readonly func: string; + + constructor({ args, func }: WormholeConfigConstructorParams) { + this.args = args; + this.func = func; + } +} diff --git a/packages/builder/src/wormhole/index.ts b/packages/builder/src/wormhole/index.ts new file mode 100644 index 00000000..3826f127 --- /dev/null +++ b/packages/builder/src/wormhole/index.ts @@ -0,0 +1,4 @@ +export * from './Wormhole'; +export * from './WormholeBuilder.interfaces'; +export * from './WormholeConfig'; +export * from './wormholeFactory'; diff --git a/packages/builder/src/wormhole/wormholeFactory.ts b/packages/builder/src/wormhole/wormholeFactory.ts new file mode 100644 index 00000000..2f617153 --- /dev/null +++ b/packages/builder/src/wormhole/wormholeFactory.ts @@ -0,0 +1,7 @@ +import { AnyChain } from '@moonbeam-network/xcm-types'; +import { Wormhole } from '@wormhole-foundation/sdk-connect'; +import { EvmPlatform } from '@wormhole-foundation/sdk-evm'; + +export function wormholeFactory(chain: AnyChain) { + return new Wormhole(chain.isTestChain ? 'Testnet' : 'Mainnet', [EvmPlatform]); +} diff --git a/packages/types/src/chain/Chain.ts b/packages/types/src/chain/Chain.ts index 9fa30ab8..23418507 100644 --- a/packages/types/src/chain/Chain.ts +++ b/packages/types/src/chain/Chain.ts @@ -1,3 +1,4 @@ +import type { Chain as WhChain } from '@wormhole-foundation/sdk-connect'; import { Asset, AssetAmount, ChainAsset } from '../asset'; import { Ecosystem, WormholeConfig } from './Chain.interfaces'; @@ -68,4 +69,12 @@ export abstract class Chain { return chainAsset; } + + getWormholeName(): WhChain { + if (!this.wh?.name) { + throw new Error(`Chain ${this.name} does not have a wormhole name`); + } + + return this.wh.name; + } }