UNPKG

@ledgerhq/live-common

Version:
138 lines 6.3 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.genericPrepareTransaction = genericPrepareTransaction; exports.getAssetInfos = getAssetInfos; const alpaca_1 = require("./alpaca"); const bridge_1 = require("./bridge"); const utils_1 = require("./utils"); const bignumber_js_1 = __importDefault(require("bignumber.js")); const index_1 = require("@ledgerhq/ledger-wallet-framework/account/index"); function bnEq(a, b) { return !a && !b ? true : !a || !b ? false : a.eq(b); } function assetInfosFallback(transaction) { return { assetReference: transaction.assetReference ?? "", assetOwner: transaction.assetOwner ?? "", }; } function propagateField(estimation, field, dest) { const value = estimation?.parameters?.[field]; if (typeof value !== "bigint" && typeof value !== "number" && typeof value !== "string") return; switch (field) { case "type": dest[field] = Number(value.toString()); return; case "storageLimit": case "gasLimit": case "gasPrice": case "maxFeePerGas": case "maxPriorityFeePerGas": case "additionalFees": dest[field] = new bignumber_js_1.default(value.toString()); return; default: return; } } function genericPrepareTransaction(network, kind) { return async (account, transaction) => { const { computeIntentType, estimateFees, validateIntent } = (0, alpaca_1.getAlpacaApi)(account.currency.id, kind); const bridgeApi = (0, bridge_1.getBridgeApi)(account.currency, network); const getAssetFromTokenForCurrency = bridgeApi.getAssetFromToken; const { assetReference, assetOwner } = getAssetFromTokenForCurrency ? await getAssetInfos(transaction, account.freshAddress, getAssetFromTokenForCurrency) : assetInfosFallback(transaction); const customParametersFees = transaction.customFees?.parameters?.fees; /** * Ticking `useAllAmount` constantly resets the amount to 0. This is problematic * because some Blockchain need the actual transaction amount to compute the fees * (Example with EVM and ERC20 transactions) * In case of `useAllAmount` and token transaction, we read the token account spendable * balance instead. */ let amount = transaction.amount; if (transaction.useAllAmount && transaction.subAccountId) { const subAccount = account.subAccounts?.find(acc => acc.id === transaction.subAccountId); amount = subAccount?.spendableBalance ?? amount; } // Pass any parameters that help estimating fees // This includes `assetOwner` and `assetReference` that are not used by some apps that only rely on `subAccountId` // TODO Remove `assetOwner` and `assetReference` in order to maintain one unique way of identifying the type of asset // https://ledgerhq.atlassian.net/browse/LIVE-24044 const intent = (0, utils_1.transactionToIntent)(account, { ...transaction, assetOwner, assetReference, amount, }, computeIntentType); const customFeesParameters = (0, utils_1.bigNumberToBigIntDeep)({ gasPrice: transaction.gasPrice, maxFeePerGas: transaction.maxFeePerGas, maxPriorityFeePerGas: transaction.maxPriorityFeePerGas, gasLimit: transaction.customGasLimit, gasOptions: transaction.gasOptions, }); const estimation = customParametersFees ? { value: BigInt(customParametersFees.toFixed()) } : await estimateFees(intent, customFeesParameters); const fees = new bignumber_js_1.default(estimation.value.toString()); if (!bnEq(transaction.fees, fees)) { const next = { ...transaction, fees, assetReference, assetOwner, customFees: { parameters: { fees: customParametersFees ? new bignumber_js_1.default(customParametersFees.toString()) : undefined, }, }, }; // Propagate needed fields const fieldsToPropagate = [ "type", "storageLimit", "gasPrice", // gas limit must not change in case it is custom ...(transaction.customGasLimit ? [] : ["gasLimit"]), "maxFeePerGas", "maxPriorityFeePerGas", "additionalFees", ]; for (const field of fieldsToPropagate) { propagateField(estimation, field, next); } // align with stellar/xrp: when send max (or staking intents), reflect validated amount in UI if (transaction.useAllAmount || ["stake", "unstake"].includes(transaction.mode ?? "")) { // TODO Remove the call to `validateIntent` https://ledgerhq.atlassian.net/browse/LIVE-22228 const { amount } = await validateIntent((0, utils_1.transactionToIntent)(account, { ...transaction, assetOwner, assetReference, }, computeIntentType), (0, utils_1.extractBalances)(account, getAssetFromTokenForCurrency)); next.amount = new bignumber_js_1.default(amount.toString()); } return next; } return transaction; }; } async function getAssetInfos(tr, owner, getAssetFromToken) { if (tr.subAccountId) { const { token } = await (0, index_1.decodeTokenAccountId)(tr.subAccountId); if (!token) return assetInfosFallback(tr); const asset = getAssetFromToken(token, owner); return { assetOwner: ("assetOwner" in asset && asset.assetOwner) || "", assetReference: ("assetReference" in asset && asset.assetReference) || "", }; } return assetInfosFallback(tr); } //# sourceMappingURL=prepareTransaction.js.map