UNPKG

@ledgerhq/coin-stellar

Version:
159 lines 7.21 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getTransactionStatus = void 0; const errors_1 = require("@ledgerhq/errors"); const bignumber_js_1 = require("bignumber.js"); const index_1 = require("@ledgerhq/coin-framework/account/index"); const index_2 = require("@ledgerhq/coin-framework/currencies/index"); const logic_1 = require("./logic"); const network_1 = require("../network"); const types_1 = require("../types"); const getTransactionStatus = async (account, transaction) => { const errors = {}; const warnings = {}; const useAllAmount = !!transaction.useAllAmount; const destinationNotExistMessage = new errors_1.NotEnoughBalanceBecauseDestinationNotCreated("", { minimalAmount: `${network_1.MIN_BALANCE} XLM`, }); if (account.pendingOperations.length > 0) { throw new errors_1.AccountAwaitingSendPendingOperations(); } if (!transaction.fees || !transaction.baseReserve) { errors.fees = new errors_1.FeeNotLoaded(); } const estimatedFees = !transaction.fees ? new bignumber_js_1.BigNumber(0) : transaction.fees; const baseReserve = !transaction.baseReserve ? new bignumber_js_1.BigNumber(0) : transaction.baseReserve; const isAssetPayment = transaction.subAccountId && transaction.assetCode && transaction.assetIssuer; const nativeBalance = account.balance; const nativeAmountAvailable = account.spendableBalance.minus(estimatedFees); let amount = new bignumber_js_1.BigNumber(0); let maxAmount = new bignumber_js_1.BigNumber(0); let totalSpent = new bignumber_js_1.BigNumber(0); // Enough native balance to cover transaction (with required reserve + fees) if (!errors.amount && nativeAmountAvailable.lt(0)) { errors.amount = new types_1.StellarNotEnoughNativeBalance(); } // Entered fee is smaller than base fee if (estimatedFees.lt(transaction.networkInfo?.baseFee || 0)) { errors.transaction = new types_1.StellarFeeSmallerThanBase(); // Entered fee is smaller than recommended } else if (estimatedFees.lt(transaction.networkInfo?.fees || 0)) { warnings.transaction = new types_1.StellarFeeSmallerThanRecommended(); } // Operation specific checks if (transaction.mode === "changeTrust") { // Check asset provided if (!transaction.assetCode || !transaction.assetIssuer) { // This is unlikely errors.transaction = new types_1.StellarAssetRequired(""); } // Has enough native balance to add new trustline if (nativeAmountAvailable.minus(network_1.BASE_RESERVE).lt(0)) { errors.amount = new types_1.StellarNotEnoughNativeBalanceToAddTrustline(); } } else { // Payment // Check recipient address if (!transaction.recipient) { errors.recipient = new errors_1.RecipientRequired(""); } else if (!(0, logic_1.isAddressValid)(transaction.recipient)) { errors.recipient = new errors_1.InvalidAddress("", { currencyName: account.currency.name, }); } else if (account.freshAddress === transaction.recipient) { errors.recipient = new errors_1.InvalidAddressBecauseDestinationIsAlsoSource(); } const recipientAccount = await (0, network_1.getRecipientAccount)({ recipient: transaction.recipient, }); // Check recipient account if (!recipientAccount?.id && !errors.recipient && !warnings.recipient) { if (recipientAccount?.isMuxedAccount) { errors.recipient = new types_1.StellarMuxedAccountNotExist(); } else { if (isAssetPayment) { errors.recipient = destinationNotExistMessage; } else { warnings.recipient = destinationNotExistMessage; } } } // Asset payment if (isAssetPayment) { const asset = (0, index_1.findSubAccountById)(account, transaction.subAccountId || ""); if (asset === null) { // This is unlikely throw new types_1.StellarAssetNotFound(); } // Check recipient account accepts asset if (recipientAccount?.id && !errors.recipient && !warnings.recipient && !recipientAccount.assetIds.includes(`${transaction.assetCode}:${transaction.assetIssuer}`)) { errors.recipient = new types_1.StellarAssetNotAccepted("", { assetCode: transaction.assetCode, }); } const assetBalance = asset?.balance || new bignumber_js_1.BigNumber(0); maxAmount = asset?.spendableBalance || assetBalance; amount = useAllAmount ? maxAmount : transaction.amount; totalSpent = amount; if (!errors.amount && amount.gt(assetBalance)) { errors.amount = new errors_1.NotEnoughBalance(); } } else { // Native payment maxAmount = nativeAmountAvailable; amount = useAllAmount ? maxAmount : transaction.amount || 0; if (amount.gt(maxAmount)) { errors.amount = new errors_1.NotEnoughBalance(); } totalSpent = useAllAmount ? nativeAmountAvailable : transaction.amount.plus(estimatedFees); // Need to send at least 1 XLM to create an account if (!errors.recipient && !recipientAccount?.id && !errors.amount && amount.lt(10000000)) { errors.amount = destinationNotExistMessage; } if (totalSpent.gt(nativeBalance.minus(baseReserve))) { errors.amount = new errors_1.NotEnoughSpendableBalance(undefined, { minimumAmount: (0, index_2.formatCurrencyUnit)(account.currency.units[0], baseReserve, { disableRounding: true, showCode: true, }), }); } if (!errors.recipient && !errors.amount && (amount.lt(0) || totalSpent.gt(nativeBalance))) { errors.amount = new errors_1.NotEnoughBalance(); totalSpent = new bignumber_js_1.BigNumber(0); amount = new bignumber_js_1.BigNumber(0); } } if (!errors.amount && amount.eq(0)) { errors.amount = new errors_1.AmountRequired(); } } if (await (0, logic_1.isAccountMultiSign)(account)) { errors.recipient = new types_1.StellarSourceHasMultiSign(); } if (transaction.memoType && transaction.memoValue && !(0, logic_1.isMemoValid)(transaction.memoType, transaction.memoValue)) { errors.transaction = new types_1.StellarWrongMemoFormat(); } return { errors, warnings, estimatedFees, amount, totalSpent, }; }; exports.getTransactionStatus = getTransactionStatus; exports.default = exports.getTransactionStatus; //# sourceMappingURL=getTransactionStatus.js.map