UNPKG

@ledgerhq/coin-tezos

Version:
124 lines (113 loc) 4.11 kB
import { AmountRequired, FeeTooHigh, InvalidAddressBecauseDestinationIsAlsoSource, NotEnoughBalance, NotEnoughBalanceBecauseDestinationNotCreated, NotEnoughBalanceToDelegate, RecommendUndelegation, } from "@ledgerhq/errors"; import { log } from "@ledgerhq/logs"; import BigNumber from "bignumber.js"; import { AccountBridge } from "@ledgerhq/types-live"; import { InvalidAddressBecauseAlreadyDelegated } from "../types/errors"; import { validateRecipient } from "../logic"; import { isAccountDelegating } from "../network/bakers"; import api from "../network/tzkt"; import { Transaction } from "../types"; const EXISTENTIAL_DEPOSIT = new BigNumber(275000); export const getTransactionStatus: AccountBridge<Transaction>["getTransactionStatus"] = async ( account, transaction, ) => { const errors: Record<string, Error> = {}; const warnings: Record<string, Error> = {}; let resetTotalSpent = false; // Recipient validation logic if (transaction.mode !== "undelegate") { if (account.freshAddress === transaction.recipient) { errors.recipient = new InvalidAddressBecauseDestinationIsAlsoSource(); } else { const { recipientError, recipientWarning } = await validateRecipient(transaction.recipient); if (recipientError) { errors.recipient = recipientError; } if (recipientWarning) { warnings.recipient = recipientWarning; } } } // Pre validation of amount field const estimatedFees = transaction.estimatedFees || new BigNumber(0); if (transaction.mode === "send") { if (!errors.amount && transaction.amount.eq(0) && !transaction.useAllAmount) { resetTotalSpent = true; errors.amount = new AmountRequired(); } else if (transaction.amount.gt(0) && estimatedFees.times(10).gt(transaction.amount)) { warnings.feeTooHigh = new FeeTooHigh(); } const thresholdWarning = 0.5 * 10 ** account.currency.units[0].magnitude; if ( !errors.amount && account.balance.minus(transaction.amount).minus(estimatedFees).lt(thresholdWarning) ) { if (isAccountDelegating(account)) { if (transaction.useAllAmount) { errors.amount = new RecommendUndelegation(); } else { warnings.amount = new RecommendUndelegation(); } } } } // effective amount // if we also have taquitoError, we interprete them and they override the previously inferred errors if (transaction.taquitoError) { log("taquitoerror", String(transaction.taquitoError)); // remap taquito errors if ( transaction.taquitoError.endsWith("balance_too_low") || transaction.taquitoError.endsWith("subtraction_underflow") ) { if (transaction.mode === "send") { resetTotalSpent = true; errors.amount = new NotEnoughBalance(); } else { errors.amount = new NotEnoughBalanceToDelegate(); } } else if (transaction.taquitoError.endsWith("delegate.unchanged")) { errors.recipient = new InvalidAddressBecauseAlreadyDelegated(); } else if (!errors.amount) { // unidentified error case errors.amount = new Error(transaction.taquitoError); resetTotalSpent = true; } } if (!errors.amount && account.balance.lte(0)) { resetTotalSpent = true; errors.amount = new NotEnoughBalance(); } if (!errors.amount && transaction.mode === "delegate" && account.balance.lte(estimatedFees)) { resetTotalSpent = true; errors.amount = new NotEnoughBalance(); } // Catch a specific case that requires a minimum amount if ( !errors.amount && transaction.mode === "send" && transaction.amount.lt(EXISTENTIAL_DEPOSIT) && (await api.getAccountByAddress(transaction.recipient)).type === "empty" ) { resetTotalSpent = true; errors.amount = new NotEnoughBalanceBecauseDestinationNotCreated("", { minimalAmount: "0.275 XTZ", }); } return { errors, warnings, estimatedFees, amount: transaction.amount, totalSpent: resetTotalSpent ? new BigNumber(0) : transaction.amount.plus(estimatedFees), }; };