@ledgerhq/coin-stellar
Version:
Ledger Stellar Coin integration
159 lines • 7.21 kB
JavaScript
"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