UNPKG

@ledgerhq/coin-filecoin

Version:
115 lines 4.38 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.estimateFees = estimateFees; const logs_1 = require("@ledgerhq/logs"); const tokenAccounts_1 = require("../../erc20/tokenAccounts"); const addresses_1 = require("../../network/addresses"); const types_1 = require("../../types"); const api_1 = require("../../network/api"); // 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; // Default fallback fee used when token simulation fails due to zero native balance. // This is a best-effort estimate; the actual fee will be validated at sign time. const DEFAULT_FEE_FALLBACK = { value: 100000000000n, parameters: { gasFeeCap: "100000", gasLimit: "1000000", gasPremium: "1000", }, }; // Resolves the ERC-20 recipient to its Ethereum-compatible (0x) form. function resolveTokenRecipient(recipient) { if (recipient?.startsWith("0x")) { return recipient; } try { return (0, addresses_1.convertAddressFilToEth)(recipient ?? ""); } catch { throw new Error(`Invalid token recipient: ${recipient}`); } } // Builds the fee-estimation request for an ERC-20 transfer. // Returns null when token params cannot be encoded (caller falls back to a default estimate). function buildErc20FeeRequest(intent) { 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}`); } const recipientEth = resolveTokenRecipient(intent.recipient); try { const abiEncoded = (0, tokenAccounts_1.abiEncodeTransferParams)(recipientEth, intent.amount.toString()); return { to: contractValidation.parsedAddress.toString(), methodNum: METHOD_INVOKE_EVM, value: "0", params: (0, tokenAccounts_1.encodeTxnParams)(abiEncoded), }; } catch (e) { (0, logs_1.log)("debug", "[estimateFees] failed to encode token params, using fallback", e); return null; } } // Builds the fee-estimation request for a native FIL transfer. function buildNativeFeeRequest(intent) { const recipientValidation = (0, addresses_1.validateAddress)(intent.recipient ?? ""); return { to: recipientValidation.isValid ? recipientValidation.parsedAddress.toString() : undefined, methodNum: METHOD_TRANSFER, value: intent.amount.toString(), }; } async function estimateFees(intent, _customFeesParameters) { 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 assetType = intent.asset.type; let request; if (assetType === "native") { request = buildNativeFeeRequest(intent); } else if (assetType === "erc20") { const erc20Request = buildErc20FeeRequest(intent); if (!erc20Request) { return DEFAULT_FEE_FALLBACK; } request = erc20Request; } else { throw new Error(`Unsupported asset type: ${String(assetType)}`); } const { to, methodNum, value, params } = request; try { const fees = await (0, api_1.fetchEstimatedFees)({ from, ...(to ? { to } : {}), methodNum, blockIncl: types_1.BroadcastBlockIncl, value, ...(params ? { params } : {}), }); const gasFeeCap = BigInt(fees.gas_fee_cap); const gasLimit = BigInt(fees.gas_limit); return { value: gasFeeCap * gasLimit, parameters: { gasFeeCap: fees.gas_fee_cap, gasLimit: String(fees.gas_limit), gasPremium: fees.gas_premium, }, }; } catch (e) { (0, logs_1.log)("debug", "[estimateFees] fee estimation failed, returning fallback", e); return DEFAULT_FEE_FALLBACK; } } //# sourceMappingURL=estimateFees.js.map