UNPKG

near-ca

Version:

An SDK for controlling Ethereum Accounts from a Near Account.

131 lines (130 loc) 4.28 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.toPayload = toPayload; exports.fromPayload = fromPayload; exports.buildTxPayload = buildTxPayload; exports.populateTx = populateTx; exports.addSignature = addSignature; exports.relaySignedTransaction = relaySignedTransaction; exports.broadcastSignedTransaction = broadcastSignedTransaction; const viem_1 = require("viem"); const network_1 = require("../network"); /** * Converts a message hash to a payload array * * @param msgHash - The message hash to convert * @returns Array of numbers representing the payload * @throws Error if the payload length is not 32 bytes */ function toPayload(msgHash) { const bytes = (0, viem_1.isBytes)(msgHash) ? msgHash : (0, viem_1.toBytes)(msgHash); if (bytes.length !== 32) { throw new Error(`Payload must have 32 bytes: ${msgHash}`); } return Array.from(bytes); } /** * Converts a payload array back to a hexadecimal string * * @param payload - The payload array to convert * @returns Hexadecimal string representation * @throws Error if the payload length is not 32 bytes */ function fromPayload(payload) { if (payload.length !== 32) { throw new Error(`Payload must have 32 bytes: ${payload}`); } // Convert number[] back to Uint8Array return (0, viem_1.toHex)(new Uint8Array(payload)); } /** * Builds a transaction payload from a serialized transaction * * @param serializedTx - The serialized transaction * @returns Array of numbers representing the transaction payload */ function buildTxPayload(serializedTx) { return toPayload((0, viem_1.keccak256)(serializedTx)); } /** * Populates a transaction with necessary data * * @param tx - The base transaction data * @param from - The sender's address * @param client - Optional public client * @returns Complete transaction data * @throws Error if chain IDs don't match */ async function populateTx(tx, from, client) { const provider = client || network_1.Network.fromChainId(tx.chainId).client; const chainId = await provider.getChainId(); if (chainId !== tx.chainId) { // Can only happen when client is provided. throw new Error(`client chainId=${chainId} mismatch with tx.chainId=${tx.chainId}`); } const transactionData = { nonce: tx.nonce ?? (await provider.getTransactionCount({ address: from })), account: from, to: tx.to, value: tx.value ?? 0n, data: tx.data ?? "0x", }; const [estimatedGas, { maxFeePerGas, maxPriorityFeePerGas }] = await Promise.all([ // Only estimate gas if not provided. tx.gas || provider.estimateGas(transactionData), provider.estimateFeesPerGas(), ]); return { ...transactionData, gas: estimatedGas, maxFeePerGas, maxPriorityFeePerGas, chainId, }; } /** * Adds a signature to a transaction * * @param params - Object containing transaction and signature * @returns Serialized signed transaction */ function addSignature({ transaction, signature, }) { const txData = (0, viem_1.parseTransaction)(transaction); const signedTx = { ...signature, ...txData, }; return (0, viem_1.serializeTransaction)(signedTx); } /** * Relays a signed transaction to the Ethereum mempool * * @param serializedTransaction - The signed transaction to relay * @param wait - Whether to wait for confirmation * @returns Transaction hash */ async function relaySignedTransaction(serializedTransaction, wait = true) { const tx = (0, viem_1.parseTransaction)(serializedTransaction); const network = network_1.Network.fromChainId(tx.chainId); if (wait) { return network.client.sendRawTransaction({ serializedTransaction, }); } else { network.client.sendRawTransaction({ serializedTransaction, }); return (0, viem_1.keccak256)(serializedTransaction); } } /** * Broadcasts a signed transaction to the Ethereum mempool * * @param tx - The signed transaction to broadcast * @returns Transaction hash */ async function broadcastSignedTransaction(tx) { const signedTx = addSignature(tx); return relaySignedTransaction(signedTx); }