UNPKG

@ledgerhq/coin-hedera

Version:
263 lines 11.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.getTransactionStatus = void 0; const errors_1 = require("@ledgerhq/errors"); const account_1 = require("@ledgerhq/ledger-wallet-framework/account"); const live_env_1 = require("@ledgerhq/live-env"); const bignumber_js_1 = __importDefault(require("bignumber.js")); const invariant_1 = __importDefault(require("invariant")); const constants_1 = require("../constants"); const errors_2 = require("../errors"); const estimateFees_1 = require("../logic/estimateFees"); const utils_1 = require("../logic/utils"); const validateMemo_1 = require("../logic/validateMemo"); const preload_data_1 = require("../preload-data"); const utils_2 = require("./utils"); async function validateRecipient(account, recipient) { if (!recipient || recipient.length === 0) { return new errors_1.RecipientRequired(); } const [parsingError, parsingResult] = await (0, utils_1.safeParseAccountId)(recipient); if (parsingError) { return parsingError; } const recipientWithoutChecksum = parsingResult.accountId; if (account.freshAddress === recipientWithoutChecksum) { return new errors_1.InvalidAddressBecauseDestinationIsAlsoSource(); } return null; } async function handleTokenAssociateTransaction(account, transaction) { const errors = {}; const warnings = {}; const [usdRate, estimatedFees] = await Promise.all([ (0, utils_1.getCurrencyToUSDRate)(account.currency), (0, estimateFees_1.estimateFees)({ currency: account.currency, operationType: constants_1.HEDERA_OPERATION_TYPES.TokenAssociate, }), ]); const amount = (0, bignumber_js_1.default)(0); const totalSpent = amount.plus(estimatedFees.tinybars); const isAssociationFlow = (0, utils_1.isTokenAssociationRequired)(account, transaction.properties.token); if (!(0, validateMemo_1.validateMemo)(transaction.memo)) { errors.transaction = new errors_2.HederaMemoExceededSizeError(); } if (isAssociationFlow) { const hbarBalance = account.balance.dividedBy(10 ** account.currency.units[0].magnitude); const currentWorthInUSD = usdRate ? hbarBalance.multipliedBy(usdRate) : new bignumber_js_1.default(0); const requiredWorthInUSD = (0, live_env_1.getEnv)("HEDERA_TOKEN_ASSOCIATION_MIN_USD"); if (currentWorthInUSD.isLessThan(requiredWorthInUSD)) { errors.insufficientAssociateBalance = new errors_2.HederaInsufficientFundsForAssociation("", { requiredWorthInUSD, }); } } return { amount, totalSpent, estimatedFees: estimatedFees.tinybars, errors, warnings, }; } async function handleHTSTokenTransaction(account, subAccount, transaction) { const errors = {}; const warnings = {}; const [calculatedAmount, estimatedFees] = await Promise.all([ (0, utils_2.calculateAmount)({ transaction, account }), (0, estimateFees_1.estimateFees)({ currency: account.currency, operationType: constants_1.HEDERA_OPERATION_TYPES.TokenTransfer, }), ]); const recipientError = await validateRecipient(account, transaction.recipient); if (recipientError) { errors.recipient = recipientError; } if (!(0, validateMemo_1.validateMemo)(transaction.memo)) { errors.transaction = new errors_2.HederaMemoExceededSizeError(); } if (!errors.recipient) { try { const hasRecipientTokenAssociated = await (0, utils_1.checkAccountTokenAssociationStatus)(transaction.recipient, subAccount.token); if (!hasRecipientTokenAssociated) { warnings.missingAssociation = new errors_2.HederaRecipientTokenAssociationRequired(); } } catch { warnings.unverifiedAssociation = new errors_2.HederaRecipientTokenAssociationUnverified(); } } if (transaction.amount.eq(0)) { errors.amount = new errors_1.AmountRequired(); } if (subAccount.balance.isLessThan(calculatedAmount.totalSpent)) { errors.amount = new errors_1.NotEnoughBalance(); } if (account.balance.isLessThan(estimatedFees.tinybars)) { errors.amount = new errors_1.NotEnoughBalance(); } return { amount: calculatedAmount.amount, totalSpent: calculatedAmount.totalSpent, estimatedFees: estimatedFees.tinybars, errors, warnings, }; } async function handleERC20TokenTransaction(account, subAccount, transaction) { const errors = {}; const warnings = { unverifiedEvmAddress: new errors_2.HederaRecipientEvmAddressVerificationRequired(), }; const [calculatedAmount, estimatedFees] = await Promise.all([ (0, utils_2.calculateAmount)({ transaction, account }), (0, estimateFees_1.estimateFees)({ operationType: constants_1.HEDERA_OPERATION_TYPES.ContractCall, txIntent: { intentType: "transaction", type: constants_1.HEDERA_TRANSACTION_MODES.Send, asset: { type: "erc20", assetReference: subAccount.token.contractAddress, assetOwner: account.freshAddress, }, amount: BigInt(transaction.amount.toString()), sender: account.freshAddress, recipient: transaction.recipient, }, }), ]); const recipientError = await validateRecipient(account, transaction.recipient); if (recipientError) { errors.recipient = recipientError; } if (!(0, validateMemo_1.validateMemo)(transaction.memo)) { errors.transaction = new errors_2.HederaMemoExceededSizeError(); } if (transaction.amount.eq(0)) { errors.amount = new errors_1.AmountRequired(); } if (subAccount.balance.isLessThan(calculatedAmount.totalSpent)) { errors.amount = new errors_1.NotEnoughBalance(); } if (account.balance.isLessThan(estimatedFees.tinybars)) { errors.amount = new errors_1.NotEnoughBalance(); } return { amount: calculatedAmount.amount, totalSpent: calculatedAmount.totalSpent, estimatedFees: estimatedFees.tinybars, errors, warnings, }; } async function handleCoinTransaction(account, transaction) { const errors = {}; const warnings = {}; const [calculatedAmount, estimatedFees] = await Promise.all([ (0, utils_2.calculateAmount)({ transaction, account }), (0, estimateFees_1.estimateFees)({ currency: account.currency, operationType: constants_1.HEDERA_OPERATION_TYPES.CryptoTransfer, }), ]); const recipientError = await validateRecipient(account, transaction.recipient); if (recipientError) { errors.recipient = recipientError; } if (transaction.amount.eq(0) && !transaction.useAllAmount) { errors.amount = new errors_1.AmountRequired(); } if (account.balance.isLessThan(calculatedAmount.totalSpent)) { errors.amount = new errors_1.NotEnoughBalance(""); } if (!(0, validateMemo_1.validateMemo)(transaction.memo)) { errors.transaction = new errors_2.HederaMemoExceededSizeError(); } return { amount: calculatedAmount.amount, totalSpent: calculatedAmount.totalSpent, estimatedFees: estimatedFees.tinybars, errors, warnings, }; } async function handleStakingTransaction(account, transaction) { (0, invariant_1.default)((0, utils_1.isStakingTransaction)(transaction), "invalid transaction properties"); const errors = {}; const warnings = {}; const { validators } = (0, preload_data_1.getCurrentHederaPreloadData)(account.currency); const estimatedFees = await (0, estimateFees_1.estimateFees)({ operationType: constants_1.HEDERA_OPERATION_TYPES.CryptoUpdate, currency: account.currency, }); const amount = (0, bignumber_js_1.default)(0); const totalSpent = amount.plus(estimatedFees.tinybars); if (!(0, validateMemo_1.validateMemo)(transaction.memo)) { errors.transaction = new errors_2.HederaMemoExceededSizeError(); } if (transaction.mode === constants_1.HEDERA_TRANSACTION_MODES.Delegate || transaction.mode === constants_1.HEDERA_TRANSACTION_MODES.Redelegate) { if (typeof transaction.properties?.stakingNodeId === "number") { const isValid = validators.some(validator => { return validator.nodeId === transaction.properties?.stakingNodeId; }); if (!isValid) { errors.stakingNodeId = new errors_2.HederaInvalidStakingNodeIdError(); } } else { errors.missingStakingNodeId = new errors_2.HederaInvalidStakingNodeIdError("Validator must be set"); } if (account.hederaResources?.delegation?.nodeId === transaction.properties?.stakingNodeId) { errors.stakingNodeId = new errors_2.HederaRedundantStakingNodeIdError(); } } if (transaction.mode === constants_1.HEDERA_TRANSACTION_MODES.ClaimRewards) { const rewardsToClaim = account.hederaResources?.delegation?.pendingReward || new bignumber_js_1.default(0); const transactionFee = transaction.maxFee ?? new bignumber_js_1.default(0); if (rewardsToClaim.lte(0)) { errors.noRewardsToClaim = new errors_2.HederaNoStakingRewardsError(); } if (transactionFee.gt(rewardsToClaim)) { warnings.claimRewardsFee = new errors_1.ClaimRewardsFeesWarning(); } } if (account.balance.isLessThan(totalSpent)) { errors.fee = new errors_1.NotEnoughBalance(""); } return { amount: new bignumber_js_1.default(0), estimatedFees: estimatedFees.tinybars, totalSpent, errors, warnings, }; } const getTransactionStatus = async (account, transaction) => { const subAccount = (0, account_1.findSubAccountById)(account, transaction?.subAccountId || ""); const isHTSTokenTransaction = transaction.mode === constants_1.HEDERA_TRANSACTION_MODES.Send && subAccount?.token.tokenType === "hts"; const isERC20TokenTransaction = transaction.mode === constants_1.HEDERA_TRANSACTION_MODES.Send && subAccount?.token.tokenType === "erc20"; if ((0, utils_1.isTokenAssociateTransaction)(transaction)) { return handleTokenAssociateTransaction(account, transaction); } else if (isHTSTokenTransaction) { return handleHTSTokenTransaction(account, subAccount, transaction); } else if (isERC20TokenTransaction) { return handleERC20TokenTransaction(account, subAccount, transaction); } else if ((0, utils_1.isStakingTransaction)(transaction)) { return handleStakingTransaction(account, transaction); } else { return handleCoinTransaction(account, transaction); } }; exports.getTransactionStatus = getTransactionStatus; //# sourceMappingURL=getTransactionStatus.js.map