UNPKG

@avalanche-sdk/interchain

Version:
311 lines 15.2 kB
import { createPublicClient, http } from "viem"; import { tokenHomeABI } from "../abis/tokenHomeABI"; import { tokenRemoteABI } from "../abis/tokenRemoteABI"; import { DEFAULT_TELEPORTER_ADDRESS } from "../icm/consts"; import { Telemetry } from "../telemetry/telemetry"; import { approveToken } from "./utils/approveToken"; import { deployERC20Token } from "./utils/deployERC20Token"; import { getERC20TokenInfo } from "./utils/getERC20TokenInfo"; import { getInfoFromTokenHomeContract } from "./utils/getInfoFromTokenHome"; export class ICTT { sourceChain; destinationChain; gasLimit; telemetry; constructor(sourceChain, destinationChain, gasLimit, enableTelemetry) { this.sourceChain = sourceChain; this.destinationChain = destinationChain; this.gasLimit = gasLimit ?? BigInt(250000); this.telemetry = new Telemetry(enableTelemetry); } /** * Deploys a new ERC20 token on the source chain. * @param params - The parameters for deploying the ERC20 token. * @param params.walletClient - The wallet client to use for deploying the ERC20 token. * @param params.sourceChain - The source chain to deploy the ERC20 token on. * @param params.name - The name of the token. * @param params.symbol - The symbol of the token. * @param params.initialSupply - The initial supply of the token. * @param params.recipient - The recipient of the newly minted tokens. * @returns The transaction hash and the contract address of the deployed ERC20 token. */ async deployERC20Token(params) { const sourceChain = params.sourceChain ?? this.sourceChain; if (!sourceChain) { throw new Error("Source chain not set."); } this.telemetry.captureEvent("ictt_deployERC20Token", { sourceChain: sourceChain.id, }); const recipient = params.recipient ?? params.walletClient.account?.address; if (!recipient) { throw new Error("Recipient not set or not present in wallet client."); } return deployERC20Token(params.walletClient, sourceChain, params.name, params.symbol, params.initialSupply, recipient); } /** * Approves the token for the token home contract on the source chain. * @param params - The parameters for approving the token. * @param params.walletClient - The wallet client to use for approving the token. * @param params.sourceChain - The source chain to approve the token on. * @param params.tokenHomeContract - The address of the token home contract to approve the token for. * @param params.tokenAddress - The address of the token to approve. * @param params.amountInBaseUnit - The amount of the token to approve. * @returns The transaction hash of the approval. */ async approveToken(params) { const sourceChain = params.sourceChain ?? this.sourceChain; if (!sourceChain) { throw new Error("Source chain not set."); } this.telemetry.captureEvent("ictt_approveToken", { sourceChain: sourceChain.id, }); return approveToken({ walletClient: params.walletClient, chain: sourceChain, spenderAddress: params.tokenHomeContract, tokenAddress: params.tokenAddress, amountInBaseUnit: params.amountInBaseUnit, }); } /** * Deploy a token home contract on the source chain. * @param params - The parameters for deploying the token home contract. * @param params.walletClient - The wallet client to use for deploying the token home contract. * @param params.sourceChain - The source chain to deploy the token home contract on. * @param params.erc20TokenAddress - The address of the ERC20 token to be used as the token home contract. * @param params.minimumTeleporterVersion - The minimum teleporter version required for the token home contract. * @param params.tokenHomeCustomByteCode - Optional. The customized bytecode for the token home contract. * @param params.tokenHomeCustomABI - Optional. The customized ABI for the token home contract. * @returns The transaction hash and the contract address of the deployed token home contract. */ async deployTokenHomeContract(params) { const sourceChain = params.sourceChain ?? this.sourceChain; if (!sourceChain) { throw new Error("Source chain not set."); } this.telemetry.captureEvent("ictt_deployTokenHomeContract", { sourceChain: sourceChain.id, }); const publicClient = createPublicClient({ chain: sourceChain, transport: http(), }); const { tokenDecimals } = await getERC20TokenInfo(sourceChain, params.erc20TokenAddress); const txHash = await params.walletClient.deployContract({ abi: params.tokenHomeCustomABI ?? tokenHomeABI.abi, bytecode: params.tokenHomeCustomByteCode ?? tokenHomeABI.bytecode, args: [ sourceChain.interchainContracts.teleporterRegistry, DEFAULT_TELEPORTER_ADDRESS, BigInt(params.minimumTeleporterVersion), params.erc20TokenAddress, tokenDecimals, ], chain: sourceChain, account: params.walletClient.account ?? null, }); const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash, }); if (receipt.status === "success" && receipt.contractAddress) { return { txHash, contractAddress: receipt.contractAddress, }; } else { throw new Error("Failed to deploy token home contract.", { cause: receipt, }); } } /** * Deploy a token remote contract on the destination chain. * @param params - The parameters for deploying the token remote contract. * @param params.walletClient - The wallet client to use for deploying the token remote contract. * @param params.sourceChain - The source chain to deploy the token remote contract on. * @param params.destinationChain - The destination chain to deploy the token remote contract on. * @param params.tokenHomeContract - The address of the token home contract to be used as the token remote contract. * @param params.tokenRemoteCustomByteCode - Optional. The customized bytecode for the token remote contract. * @param params.tokenRemoteCustomABI - Optional. The customized ABI for the token remote contract. * @returns The transaction hash and the contract address of the deployed token remote contract. */ async deployTokenRemoteContract(params) { const sourceChain = params.sourceChain ?? this.sourceChain; if (!sourceChain) { throw new Error("Source chain not set."); } const destinationChain = params.destinationChain ?? this.destinationChain; if (!destinationChain) { throw new Error("Destination chain not set."); } this.telemetry.captureEvent("ictt_deployTokenRemoteContract", { sourceChain: sourceChain.id, destinationChain: destinationChain.id, }); const publicClient = createPublicClient({ chain: destinationChain, transport: http(), }); const { tokenName, tokenSymbol, tokenDecimals, minTeleporterVersion } = await getInfoFromTokenHomeContract(sourceChain, params.tokenHomeContract); const txHash = await params.walletClient.deployContract({ abi: params.tokenRemoteCustomABI ?? tokenRemoteABI.abi, bytecode: params.tokenRemoteCustomByteCode ?? tokenRemoteABI.bytecode, args: [ { teleporterRegistryAddress: destinationChain.interchainContracts.teleporterRegistry, teleporterManager: DEFAULT_TELEPORTER_ADDRESS, minTeleporterVersion: BigInt(minTeleporterVersion), tokenHomeBlockchainID: sourceChain.blockchainId, tokenHomeAddress: params.tokenHomeContract, tokenHomeDecimals: Number(tokenDecimals), }, tokenName, tokenSymbol, Number(tokenDecimals), ], chain: destinationChain, account: params.walletClient.account ?? null, }); const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash, }); if (receipt.status === "success" && receipt.contractAddress) { return { txHash, contractAddress: receipt.contractAddress, }; } else { throw new Error("Failed to deploy token remote contract.", { cause: receipt, }); } } /** * Emits event from the TokenRemote contract to get it registered with the TokenHome contract on the source chain. * @param params - The parameters for registering the token remote contract with the token home contract. * @param params.walletClient - The wallet client to use for registering the token remote contract with the token home contract. * @param params.sourceChain - The source chain to register the token remote contract with the token home contract on. * @param params.destinationChain - The destination chain to register the token remote contract with the token home contract on. * @param params.tokenRemoteContract - The address of the token remote contract to be registered with the token home contract. * @param params.feeTokenAddress - Optional. The address of the fee token to be used for the registration. * @param params.feeAmount - Optional. The amount of the fee to be used for the registration. * @returns The transaction hash of the registration. */ async registerRemoteWithHome(params) { const sourceChain = params.sourceChain ?? this.sourceChain; if (!sourceChain) { throw new Error("Source chain not set."); } const destinationChain = params.destinationChain ?? this.destinationChain; if (!destinationChain) { throw new Error("Destination chain not set."); } this.telemetry.captureEvent("ictt_registerRemoteWithHome", { sourceChain: sourceChain.id, destinationChain: destinationChain.id, }); const publicClient = createPublicClient({ chain: destinationChain, transport: http(), }); const feeInfo = [ params.feeTokenAddress ?? "0x0000000000000000000000000000000000000000", params.feeAmount ?? 0, ]; const txHash = await params.walletClient.writeContract({ address: params.tokenRemoteContract, abi: tokenRemoteABI.abi, functionName: "registerWithHome", args: [feeInfo], chain: destinationChain, account: params.walletClient.account ?? null, }); const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash, }); if (receipt.status === "success") { return { txHash }; } else { throw new Error("Failed to register token remote contract with token home contract.", { cause: receipt }); } } /** * Sends tokens from the TokenHome contract on the source chain to the TokenRemote contract on the destination chain. * @param params - The parameters for sending the tokens. * @param params.walletClient - The wallet client to use for sending the tokens. * @param params.sourceChain - The source chain to send the tokens from. * @param params.destinationChain - The destination chain to send the tokens to. * @param params.tokenHomeContract - The address of the token home contract to send the tokens from. * @param params.tokenRemoteContract - The address of the token remote contract to send the tokens to. * @param params.recipient - The address of the recipient of the tokens. * @param params.amountInBaseUnit - The amount of the tokens to be sent. * @param params.feeTokenAddress - Optional. The address of the fee token to be used for the transfer. * @param params.feeAmount - Optional. The amount of the fee to be used for the transfer. * @returns The transaction hash of the transfer. */ async sendToken(params) { const sourceChain = params.sourceChain ?? this.sourceChain; if (!sourceChain) { throw new Error("Source chain not set."); } const destinationChain = params.destinationChain ?? this.destinationChain; if (!destinationChain) { throw new Error("Destination chain not set."); } this.telemetry.captureEvent("ictt_sendToken", { sourceChain: sourceChain.id, destinationChain: destinationChain.id, }); const publicClient = createPublicClient({ chain: sourceChain, transport: http(), }); const { tokenContractAddress, tokenDecimals } = await getInfoFromTokenHomeContract(sourceChain, params.tokenHomeContract); const amountInWei = BigInt(params.amountInBaseUnit) * BigInt(10 ** tokenDecimals); const sendTokensInput = { destinationBlockchainID: destinationChain.blockchainId, destinationTokenTransferrerAddress: params.tokenRemoteContract, recipient: params.recipient, primaryFeeTokenAddress: tokenContractAddress ?? "0x0000000000000000000000000000000000000000", primaryFee: params.feeAmount ?? 0, secondaryFee: 0, requiredGasLimit: this.gasLimit, multiHopFallback: "0x0000000000000000000000000000000000000000", }; const txHash = await params.walletClient.writeContract({ address: params.tokenHomeContract, abi: tokenHomeABI.abi, functionName: "send", args: [sendTokensInput, amountInWei], chain: sourceChain, account: params.walletClient.account ?? null, }); const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash, }); if (receipt.status === "success") { return { txHash }; } else { throw new Error("Failed to send tokens.", { cause: receipt }); } } } /** * Creates a new ICTT client. * @param sourceChain - The default source chain to use for the client. * @param destinationChain - The default destination chain to use for the client. * @param gasLimit - The default gas limit to use for the client. * @returns A new ICTT client. */ export function createICTTClient(sourceChain, destinationChain, gasLimit) { return new ICTT(sourceChain, destinationChain, gasLimit); } //# sourceMappingURL=ictt.js.map