UNPKG

@wormhole-foundation/sdk-evm-tokenbridge

Version:

SDK for EVM chains, used in conjunction with @wormhole-foundation/sdk

140 lines 8.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.EvmExecutorTokenBridge = void 0; const sdk_connect_1 = require("@wormhole-foundation/sdk-connect"); const sdk_evm_1 = require("@wormhole-foundation/sdk-evm"); const ethers_1 = require("ethers"); require("@wormhole-foundation/sdk-evm-core"); const sdk_evm_core_1 = require("@wormhole-foundation/sdk-evm-core"); const sdk_definitions_1 = require("@wormhole-foundation/sdk-definitions"); const ethers_2 = require("ethers"); const RELAYER_ABI = [ 'function transferTokensWithRelay(address token, uint256 amount, uint16 targetChain, bytes32 targetRecipient, uint32 nonce, bytes32 dstTransferRecipient, bytes32 dstExecutionAddress, uint256 executionAmount, address refundAddr, bytes calldata signedQuoteBytes, bytes calldata relayInstructions) payable returns (uint64)', 'function wrapAndTransferEthWithRelay(uint16 targetChain, bytes32 targetRecipient, uint32 nonce, bytes32 dstTransferRecipient, bytes32 dstExecutionAddress, uint256 executionAmount, address refundAddr, bytes calldata signedQuoteBytes, bytes calldata relayInstructions) payable returns (uint64)', 'function executeVAAv1(bytes calldata encodedTransferMessage) payable', ]; const RELAYER_WITH_REFERRER_ABI = [ 'function transferTokensWithRelay(address tokenBridgeRelayer, address token, uint256 amount, uint16 targetChain, bytes32 targetRecipient, uint32 nonce, bytes32 dstTransferRecipient, bytes32 dstExecutionAddress, uint256 executionAmount, address refundAddr, bytes calldata signedQuoteBytes, bytes calldata relayInstructions, tuple(uint16 dbps, address payee) feeArgs) payable returns (uint64)', 'function wrapAndTransferEthWithRelay(address tokenBridgeRelayer, uint256 amount, uint16 targetChain, bytes32 targetRecipient, uint32 nonce, bytes32 dstTransferRecipient, bytes32 dstExecutionAddress, uint256 executionAmount, address refundAddr, bytes calldata signedQuoteBytes, bytes calldata relayInstructions, tuple(uint16 dbps, address payee) feeArgs) payable returns (uint64)', ]; class EvmExecutorTokenBridge { network; chain; provider; contracts; chainId; relayerAddress; relayerWithReferrerAddress; relayerWithReferrerContract; core; constructor(network, chain, provider, contracts) { this.network = network; this.chain = chain; this.provider = provider; this.contracts = contracts; this.chainId = sdk_connect_1.nativeChainIds.networkChainToNativeChainId.get(network, chain); const executorTokenBridge = this.contracts.executorTokenBridge; if (!executorTokenBridge) throw new Error(`Wormhole Executor Token Bridge contracts for domain ${chain} not found`); this.relayerAddress = executorTokenBridge.relayer; const relayerWithReferrerAddress = executorTokenBridge.relayerWithReferrer; if (!relayerWithReferrerAddress) throw new Error(`Wormhole Token Bridge Relayer With Referrer contract for domain ${chain} not found`); this.relayerWithReferrerAddress = relayerWithReferrerAddress; this.relayerWithReferrerContract = new ethers_1.Contract(this.relayerWithReferrerAddress, RELAYER_WITH_REFERRER_ABI, provider); this.core = new sdk_evm_core_1.EvmWormholeCore(network, chain, provider, contracts); } static async fromRpc(provider, config) { const [network, chain] = await sdk_evm_1.EvmPlatform.chainFromRpc(provider); const conf = config[chain]; if (conf.network !== network) throw new Error(`Network mismatch: ${conf.network} != ${network}`); return new EvmExecutorTokenBridge(network, chain, provider, conf.contracts); } async *transfer(sender, recipient, token, amount, executorQuote, referrerFee) { const dstContracts = sdk_connect_1.contracts.executorTokenBridge.get(this.network, recipient.chain); if (!dstContracts || !dstContracts.relayer) { throw new Error(`Token Bridge Executor Relayer contract for domain ${recipient.chain} not found`); } const dstRelayer = dstContracts.relayer; const senderAddr = new sdk_evm_1.EvmAddress(sender).unwrap(); const targetChain = (0, sdk_connect_1.toChainId)(recipient.chain); const targetRecipient = recipient.address.toUniversalAddress(); const { estimatedCost, signedQuote, relayInstructions } = executorQuote; const signedQuoteBytes = (0, sdk_connect_1.serializeLayout)(sdk_connect_1.signedQuoteLayout, signedQuote); const relayInstructionsBytes = (0, sdk_connect_1.serializeLayout)(sdk_definitions_1.relayInstructionsLayout, relayInstructions); const wormholeFee = await this.core.getMessageFee(); const nonce = 0; const dstTransferRecipient = (0, sdk_definitions_1.toUniversal)(recipient.chain, dstRelayer); const dstExecutionAddress = dstTransferRecipient; const executionAmount = estimatedCost; const refundAddr = senderAddr; let txReq; // TODO: this could be optimized to use the non-referrer contract if referrerFee is not provided const feeArgs = referrerFee ? { dbps: referrerFee.feeDbps, payee: referrerFee.referrer.address.toString(), } : { dbps: 0n, payee: ethers_2.ZeroAddress, }; if ((0, sdk_connect_1.isNative)(token)) { txReq = await this.relayerWithReferrerContract .getFunction('wrapAndTransferEthWithRelay') .populateTransaction(this.relayerAddress, amount, targetChain, targetRecipient.toUint8Array(), nonce, dstTransferRecipient.toUint8Array(), dstExecutionAddress.toUint8Array(), executionAmount, refundAddr, signedQuoteBytes, relayInstructionsBytes, feeArgs, { value: amount + wormholeFee + executionAmount, }); } else { const tokenContract = sdk_evm_1.EvmPlatform.getTokenImplementation(this.provider, token.toString()); const allowance = await tokenContract.allowance(senderAddr, this.relayerWithReferrerAddress); if (allowance < amount) { const txReq = await tokenContract.approve.populateTransaction(this.relayerWithReferrerAddress, amount); yield this.createUnsignedTx(txReq, 'approve'); } txReq = await this.relayerWithReferrerContract .getFunction('transferTokensWithRelay') .populateTransaction(this.relayerAddress, token.toString(), amount, targetChain, targetRecipient.toUint8Array(), nonce, dstTransferRecipient.toUint8Array(), dstExecutionAddress.toUint8Array(), executionAmount, refundAddr, signedQuoteBytes, relayInstructionsBytes, feeArgs, { value: wormholeFee + executionAmount, }); } yield this.createUnsignedTx((0, sdk_evm_1.addFrom)(txReq, senderAddr), (0, sdk_connect_1.isNative)(token) ? 'wrapAndTransferEthWithRelay' : 'transferTokensWithRelay'); } async *redeem(sender, vaa) { const senderAddr = new sdk_evm_1.EvmAddress(sender).toString(); const encodedTransferMessage = (0, sdk_connect_1.serialize)(vaa); const dstRelayerAddress = new sdk_evm_1.EvmAddress(vaa.payload.to.address).toString(); const dstRelayerContract = new ethers_1.Contract(dstRelayerAddress, RELAYER_ABI, this.provider); const txReq = await dstRelayerContract .getFunction('executeVAAv1') .populateTransaction(encodedTransferMessage, { value: 0n, }); yield this.createUnsignedTx((0, sdk_evm_1.addFrom)(txReq, senderAddr), 'ExecutorTokenBridge.executeVAAv1'); } async estimateMsgValueAndGasLimit(receivedToken, recipient) { let gasLimit; switch (receivedToken.chain) { case 'Arbitrum': case 'Moonbeam': gasLimit = 800000n; break; default: gasLimit = 425000n; break; } return { msgValue: 0n, gasLimit, }; } createUnsignedTx(txReq, description) { return new sdk_evm_1.EvmUnsignedTransaction((0, sdk_evm_1.addChainId)(txReq, this.chainId), this.network, this.chain, description); } } exports.EvmExecutorTokenBridge = EvmExecutorTokenBridge; //# sourceMappingURL=executorTokenBridge.js.map