UNPKG

@ledgerhq/coin-filecoin

Version:
118 lines 4.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.craftTransaction = craftTransaction; const message_1 = require("iso-filecoin/message"); const tokenAccounts_1 = require("../../erc20/tokenAccounts"); const addresses_1 = require("../../network/addresses"); const types_1 = require("../../types"); const api_1 = require("../../network/api"); const getNextSequence_1 = require("../account/getNextSequence"); // Inline method numbers from Filecoin spec (mirrors src/bridge/utils.ts Methods enum). // logic/ must not import from bridge/, so we inline the relevant constants here. const METHOD_TRANSFER = 0; const METHOD_INVOKE_EVM = 3844450837; // Serialisation format (symmetric with combine.ts): // Output `transaction` field = JSON.stringify({ cbor, message }) where // - cbor: base64-encoded CBOR of the Filecoin Message (what the signer signs) // - message: the message fields in Lotus shape (what combine uses to rebuild // the BroadcastTransactionRequest without re-deserialising CBOR — iso-filecoin // v4 exposes Message.serialize() but no static deserialize equivalent). async function craftTransaction(intent, customFees) { const senderValidation = (0, addresses_1.validateAddress)(intent.sender); if (!senderValidation.isValid) { throw new Error(`Invalid sender address: ${intent.sender}`); } const from = senderValidation.parsedAddress.toString(); const nonce = await (0, getNextSequence_1.getNextSequence)(from); let to; let value; let method; let params; const assetType = intent.asset.type; if (assetType === "native") { const recipientValidation = (0, addresses_1.validateAddress)(intent.recipient ?? ""); if (!recipientValidation.isValid) { throw new Error(`Invalid recipient address: ${intent.recipient}`); } to = recipientValidation.parsedAddress.toString(); value = intent.amount.toString(); method = METHOD_TRANSFER; } else if (assetType === "erc20") { const asset = intent.asset; const contractAddr = asset.assetReference.toLowerCase(); const contractValidation = (0, addresses_1.validateAddress)(contractAddr); if (!contractValidation.isValid) { throw new Error(`Invalid ERC-20 contract address: ${contractAddr}`); } to = contractValidation.parsedAddress.toString(); value = "0"; method = METHOD_INVOKE_EVM; const recipientEth = intent.recipient?.startsWith("0x") ? intent.recipient : (() => { try { return (0, addresses_1.convertAddressFilToEth)(intent.recipient ?? ""); } catch { throw new Error(`Invalid token recipient: ${intent.recipient}`); } })(); const abiEncoded = (0, tokenAccounts_1.abiEncodeTransferParams)(recipientEth, intent.amount.toString()); params = (0, tokenAccounts_1.encodeTxnParams)(abiEncoded); } else { throw new Error(`Unsupported asset type: ${String(assetType)}`); } // Fetch gas estimates (or use custom fees if provided) let gasFeeCap; let gasLimit; let gasPremium; if (customFees?.parameters) { gasFeeCap = String(customFees.parameters["gasFeeCap"] ?? "0"); gasLimit = Number(customFees.parameters["gasLimit"] ?? 0); gasPremium = String(customFees.parameters["gasPremium"] ?? "0"); } else { const fees = await (0, api_1.fetchEstimatedFees)({ from, to, methodNum: method, blockIncl: types_1.BroadcastBlockIncl, value, ...(params ? { params } : {}), }); gasFeeCap = fees.gas_fee_cap; gasLimit = fees.gas_limit; gasPremium = fees.gas_premium; } const message = new message_1.Message({ to, from, nonce: Number(nonce), value, gasFeeCap, gasLimit, gasPremium, method, params, version: 0, }); const cbor = Buffer.from(message.serialize()).toString("base64"); const messageJson = { version: message.version ?? 0, to: message.to, from: message.from, nonce: message.nonce, value: message.value, gasLimit: message.gasLimit, gasFeeCap: message.gasFeeCap, gasPremium: message.gasPremium, method: message.method, params: message.params ?? "", }; return { transaction: JSON.stringify({ cbor, message: messageJson }), }; } //# sourceMappingURL=craftTransaction.js.map