UNPKG

@0xfacet/sdk

Version:

A toolkit for Facet blockchain integration.

103 lines (102 loc) 4.34 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.sendRawFacetTransaction = void 0; const viem_1 = require("viem"); const chains_1 = require("viem/chains"); const addresses_1 = require("../constants/addresses"); const viem_2 = require("../viem"); const calculateInputGasCost_1 = require("./calculateInputGasCost"); const computeFacetTransactionHash_1 = require("./computeFacetTransactionHash"); const getFctMintRate_1 = require("./getFctMintRate"); /** * Sends a raw Facet transaction by preparing the transaction data and submitting it to L1. * * @param l1ChainId - The chain ID of the L1 network (1 for mainnet, 11155111 for Sepolia) * @param account - The address of the account initiating the transaction * @param params - Transaction parameters including to, value, and data * @param sendL1Transaction - Function to send the L1 transaction and return the transaction hash * @param l1RpcUrl - Optional L1 RPC URL * @returns Object containing the L1 transaction hash, Facet transaction hash, FCT mint amount, and FCT mint rate * @throws Error if L1 chain is invalid, account is missing, or L2 chain is not configured */ const sendRawFacetTransaction = async (l1ChainId, account, params, sendL1Transaction, l1RpcUrl) => { if (l1ChainId !== 1 && l1ChainId !== 11_155_111) { throw new Error("Invalid L1 chain"); } if (!account) { throw new Error("No account"); } const facetPublicClient = (0, viem_1.createPublicClient)({ chain: l1ChainId === 1 ? viem_2.facetMainnet : viem_2.facetSepolia, transport: (0, viem_1.http)(), }); if (!facetPublicClient.chain) { throw new Error("L2 chain not configured"); } const [estimateGasRes, fctBalance, fctMintRate] = await Promise.all([ facetPublicClient.estimateGas({ account, to: params.to, value: params.value, data: params.data, stateOverride: [{ address: account, balance: viem_1.maxUint256 }], }), facetPublicClient.getBalance({ address: account, }), (0, getFctMintRate_1.getFctMintRate)(l1ChainId), ]); const gasLimit = estimateGasRes; const transactionData = [ (0, viem_1.toHex)(facetPublicClient.chain.id), params.to ?? "0x", params.value ? (0, viem_1.toHex)(params.value) : "0x", gasLimit ? (0, viem_1.toHex)(gasLimit) : "0x", params.data ?? "0x", params.mineBoost ?? "0x", ]; const encodedTransaction = (0, viem_1.concatHex)([(0, viem_1.toHex)(70), (0, viem_1.toRlp)(transactionData)]); const inputCost = (0, calculateInputGasCost_1.calculateInputGasCost)((0, viem_1.toBytes)(encodedTransaction)); const fctMintAmount = inputCost * fctMintRate; // Call estimateGas again but with an accurate future balance // This will allow it to correctly revert when necessary await facetPublicClient.estimateGas({ account, to: params.to, value: params.value, data: params.data, stateOverride: [ { address: account, balance: fctBalance + fctMintAmount, }, ], }); const l1Transaction = { account, to: addresses_1.FACET_INBOX_ADDRESS, value: 0n, data: encodedTransaction, chainId: l1ChainId, }; const l1TransportUrl = l1ChainId === 1 ? "https://ethereum-rpc.publicnode.com" : "https://ethereum-sepolia-rpc.publicnode.com"; const l1PublicClient = (0, viem_1.createPublicClient)({ chain: l1ChainId === 1 ? chains_1.mainnet : chains_1.sepolia, transport: (0, viem_1.http)(l1RpcUrl || l1TransportUrl), }); const estimateL1Gas = await l1PublicClient.estimateGas(l1Transaction); const l1TransactionHash = await sendL1Transaction({ ...l1Transaction, gas: estimateL1Gas, }); const facetTransactionHash = (0, computeFacetTransactionHash_1.computeFacetTransactionHash)(l1TransactionHash, account, params.to ?? "0x", params.value ?? 0n, params.data ?? "0x", gasLimit, fctMintAmount); return { l1TransactionHash, facetTransactionHash, fctMintAmount, fctMintRate, }; }; exports.sendRawFacetTransaction = sendRawFacetTransaction;