UNPKG

@ledgerhq/coin-near

Version:
143 lines 6.03 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getStakingFees = exports.getYoctoThreshold = exports.canWithdraw = exports.canUnstake = exports.canStake = exports.mapStakingPositions = exports.getTotalSpent = exports.getMaxAmount = exports.getStakingGas = exports.isImplicitAccount = exports.isValidAddress = void 0; const bignumber_js_1 = require("bignumber.js"); const near_api_js_1 = require("near-api-js"); const index_1 = require("@ledgerhq/coin-framework/currencies/index"); const createTransaction_1 = require("./createTransaction"); const jsHelpers_1 = require("@ledgerhq/coin-framework/bridge/jsHelpers"); const preload_1 = require("./preload"); const constants_1 = require("./constants"); const isValidAddress = (address) => { const readableAddressRegex = /^(([a-z\d]+[-_])*[a-z\d]+\.)*([a-z\d]+[-_])*[a-z\d]+$/; const hexAddressRegex = /^[a-f0-9]{64}$/; if ((0, exports.isImplicitAccount)(address)) { return hexAddressRegex.test(address); } return readableAddressRegex.test(address); }; exports.isValidAddress = isValidAddress; const isImplicitAccount = (address) => { return !address.includes("."); }; exports.isImplicitAccount = isImplicitAccount; const getStakingGas = (t, multiplier = 5) => { const stakingGasBase = new bignumber_js_1.BigNumber(constants_1.STAKING_GAS_BASE); if (t?.mode === "withdraw" && t?.useAllAmount) { multiplier = 7; } return stakingGasBase.multipliedBy(multiplier); }; exports.getStakingGas = getStakingGas; /* * Get the max amount that can be spent, taking into account tx type and pending operations. */ const getMaxAmount = (account, transaction, fees) => { let maxAmount; const selectedValidator = account.nearResources?.stakingPositions.find(({ validatorId }) => validatorId === transaction.recipient); let pendingUnstakingAmount = new bignumber_js_1.BigNumber(0); let pendingWithdrawingAmount = new bignumber_js_1.BigNumber(0); account.pendingOperations.forEach(({ type, value, recipients }) => { const recipient = recipients[0]; if (recipient === selectedValidator?.validatorId) { if (type === "UNSTAKE") { pendingUnstakingAmount = pendingUnstakingAmount.plus(value); } else if (type === "WITHDRAW_UNSTAKED") { pendingWithdrawingAmount = pendingWithdrawingAmount.plus(value); } } }); switch (transaction.mode) { case "unstake": maxAmount = selectedValidator?.staked.minus(pendingUnstakingAmount); break; case "withdraw": maxAmount = selectedValidator?.available.minus(pendingWithdrawingAmount); break; default: maxAmount = account.spendableBalance; if (fees) { maxAmount = maxAmount.minus(fees); } } if (maxAmount === undefined || maxAmount.lt(0)) { return new bignumber_js_1.BigNumber(0); } return maxAmount; }; exports.getMaxAmount = getMaxAmount; const getTotalSpent = (a, t, fees) => { if (["unstake", "withdraw"].includes(t.mode)) { return fees; } if (t.useAllAmount) { return a.spendableBalance; } return new bignumber_js_1.BigNumber(t.amount).plus(fees); }; exports.getTotalSpent = getTotalSpent; const mapStakingPositions = (stakingPositions, validators, unit) => { return stakingPositions.map(sp => { const rank = validators.findIndex(v => v.validatorAddress === sp.validatorId); const validator = validators[rank] ?? sp; const formatConfig = { disableRounding: false, alwaysShowSign: false, showCode: true, }; return { ...sp, formattedAmount: (0, index_1.formatCurrencyUnit)(unit, sp.staked, formatConfig), formattedPending: (0, index_1.formatCurrencyUnit)(unit, sp.pending, formatConfig), formattedAvailable: (0, index_1.formatCurrencyUnit)(unit, sp.available, formatConfig), rank, validator, }; }); }; exports.mapStakingPositions = mapStakingPositions; /* * Make sure that an account has enough funds to stake, unstake, AND withdraw before staking. */ const canStake = (account) => { let transaction = (0, createTransaction_1.createTransaction)(account); transaction = (0, jsHelpers_1.updateTransaction)(transaction, { mode: "stake", }); const { gasPrice } = (0, preload_1.getCurrentNearPreloadData)(); const fees = (0, exports.getStakingFees)(transaction, gasPrice).multipliedBy(3); return (0, exports.getMaxAmount)(account, transaction, fees).gt(0); }; exports.canStake = canStake; const canUnstake = (stakingPosition) => { return stakingPosition.staked.gte((0, exports.getYoctoThreshold)()); }; exports.canUnstake = canUnstake; const canWithdraw = (stakingPosition) => { return stakingPosition.available.gte((0, exports.getYoctoThreshold)()); }; exports.canWithdraw = canWithdraw; /* * The threshold that the NEAR wallet uses for staking, unstaking, and withdrawing. * A "1" is subtracted due to the value from the node being 1 yoctoNEAR less than what was staked. */ const getYoctoThreshold = () => { return new bignumber_js_1.BigNumber(10) .pow(new bignumber_js_1.BigNumber(near_api_js_1.utils.format.NEAR_NOMINATION_EXP - constants_1.FRACTIONAL_DIGITS)) .minus(constants_1.YOCTO_THRESHOLD_VARIATION); }; exports.getYoctoThreshold = getYoctoThreshold; /* * An estimation for the fee by using the staking gas and scaling accordingly. * Buffer added so that the transaction never fails - we'll always overestimate. */ const getStakingFees = (t, gasPrice) => { const stakingGas = (0, exports.getStakingGas)(t); return stakingGas .plus(constants_1.STAKING_GAS_BASE) // Buffer .multipliedBy(gasPrice) .dividedBy(10); }; exports.getStakingFees = getStakingFees; //# sourceMappingURL=logic.js.map