UNPKG

@avalanche-sdk/client

Version:

A TypeScript SDK for interacting with the Avalanche network through JSON-RPC APIs. This SDK provides a comprehensive set of tools to interact with all Avalanche chains (P-Chain, X-Chain, C-Chain) and various APIs, including wallet functionality for transa

159 lines (143 loc) 5.09 kB
import { evm, pvm, utils } from "@avalabs/avalanchejs"; import { formatEther } from "viem"; import { getBalance, getTransactionCount } from "viem/actions"; import { AvalancheWalletCoreClient } from "../../../clients/createAvalancheWalletCoreClient.js"; import { P_CHAIN_ALIAS } from "../../consts.js"; import { getFeeState } from "../../pChain/getFeeState.js"; import { baseFee as getBaseFee } from "../../public/baseFee.js"; import { prepareExportTxn as prepareExportTxnCChain } from "../cChain/prepareExportTxn.js"; import { getContextFromURI } from "../getContextFromURI.js"; import { prepareImportTxn as prepareImportTxnPChain } from "../pChain/prepareImportTxn.js"; import { sendXPTransaction } from "../sendXPTransaction.js"; import { SendParameters, SendReturnType } from "../types/send.js"; import { avaxToNanoAvax, bech32AddressToBytes, getBech32AddressFromAccountOrClient, getChainIdFromAlias, getEVMAddressFromAccountOrClient, nanoAvaxToAvax, } from "../utils.js"; import { waitForTxn } from "../waitForTxn.js"; export type TransferCtoPChainParameters = SendParameters; export type TransferCtoPChainReturnType = SendReturnType; export async function transferCtoPChain( client: AvalancheWalletCoreClient, params: TransferCtoPChainParameters ): Promise<TransferCtoPChainReturnType> { const context = params.context || (await getContextFromURI(client)); // Get current account evm address const currentAccountEVMAddress = params.from || (await getEVMAddressFromAccountOrClient(client, params.account)); // Get the current account P chain address const currentAccountPChainBech32Address = await getBech32AddressFromAccountOrClient( client, params.account, P_CHAIN_ALIAS, context.networkID === 5 ? "fuji" : "avax" ); // Validate the P chain address if (!params.to.startsWith("P-")) { throw new Error("Invalid P chain address, it should start with P-"); } // Prepare the C chain export txn and get the fee for each const [cChainExportTxnRequest, pChainFeeState, baseFee, txCount, balance] = await Promise.all([ prepareExportTxnCChain(client, { destinationChain: "P", fromAddress: currentAccountEVMAddress, exportedOutput: { addresses: [currentAccountPChainBech32Address], amount: params.amount, }, context, }), getFeeState(client.pChainClient), getBaseFee(client), getTransactionCount(client, { address: `0x${utils.strip0x(currentAccountEVMAddress)}`, }), formatEther( await getBalance(client, { address: `0x${utils.strip0x(currentAccountEVMAddress)}`, }) ), ]); // Check if user has enough balance if (Number(balance) < params.amount) { throw new Error( `Insufficient balance: ${params.amount} AVAX is required, but only ${balance} AVAX is available` ); } // Calculate the fee for the C chain export txn const cChainExportTxnFee = evm.estimateExportCost( context, BigInt(baseFee), avaxToNanoAvax(params.amount), getChainIdFromAlias("P", context.networkID), utils.hexToBuffer(currentAccountEVMAddress), [bech32AddressToBytes(params.to)], BigInt(txCount) ); // Check if the fee for the C chain export txn is too high if (cChainExportTxnFee > avaxToNanoAvax(params.amount)) { throw new Error( `Transfer amount is too low: ${nanoAvaxToAvax( cChainExportTxnFee )} AVAX Fee is required for C chain export txn, but only ${ params.amount } AVAX is being transferred, try sending a higher amount.` ); } // Sign and send the C chain export txn and wait for it. const sendCChainExportTxn = await sendXPTransaction( client, cChainExportTxnRequest ); await waitForTxn(client, sendCChainExportTxn); // Prepare the P chain import txn const pChainImportTxnRequest = await prepareImportTxnPChain(client, { sourceChain: "C", importedOutput: { addresses: [params.to], }, context, }); // Calculate the fee for the P chain import txn const pChainImportTxnFee = pvm.calculateFee( pChainImportTxnRequest.tx.getTx(), context.platformFeeConfig.weights, pChainFeeState.price ); // Calculate the total fee const totalFee = pChainImportTxnFee + cChainExportTxnFee; if (totalFee > avaxToNanoAvax(params.amount)) { throw new Error( `Transfer amount is too low: ${nanoAvaxToAvax( pChainImportTxnFee )} AVAX Fee is required for P chain import txn, try sending a higher amount. C chain export txn hash: ${sendCChainExportTxn.txHash}` ); } // Sign and send the P chain import txn and wait for it. const sendPChainImportTxn = await sendXPTransaction( client, pChainImportTxnRequest ); await waitForTxn(client, sendPChainImportTxn); return { txHashes: [ { txHash: sendCChainExportTxn.txHash, chainAlias: "C", }, { txHash: sendPChainImportTxn.txHash, chainAlias: "P", }, ], }; }