diff options
Diffstat (limited to 'ui/app/components/send_/send.utils.js')
-rw-r--r-- | ui/app/components/send_/send.utils.js | 312 |
1 files changed, 0 insertions, 312 deletions
diff --git a/ui/app/components/send_/send.utils.js b/ui/app/components/send_/send.utils.js deleted file mode 100644 index aa255c3d4..000000000 --- a/ui/app/components/send_/send.utils.js +++ /dev/null @@ -1,312 +0,0 @@ -const { - addCurrencies, - conversionUtil, - conversionGTE, - multiplyCurrencies, - conversionGreaterThan, - conversionLessThan, -} = require('../../conversion-util') -const { - calcTokenAmount, -} = require('../../token-util') -const { - BASE_TOKEN_GAS_COST, - INSUFFICIENT_FUNDS_ERROR, - INSUFFICIENT_TOKENS_ERROR, - NEGATIVE_ETH_ERROR, - ONE_GWEI_IN_WEI_HEX, - SIMPLE_GAS_COST, - TOKEN_TRANSFER_FUNCTION_SIGNATURE, -} = require('./send.constants') -const abi = require('ethereumjs-abi') -const ethUtil = require('ethereumjs-util') - -module.exports = { - addGasBuffer, - calcGasTotal, - calcTokenBalance, - doesAmountErrorRequireUpdate, - estimateGas, - estimateGasPriceFromRecentBlocks, - generateTokenTransferData, - getAmountErrorObject, - getGasFeeErrorObject, - getToAddressForGasUpdate, - isBalanceSufficient, - isTokenBalanceSufficient, - removeLeadingZeroes, -} - -function calcGasTotal (gasLimit = '0', gasPrice = '0') { - return multiplyCurrencies(gasLimit, gasPrice, { - toNumericBase: 'hex', - multiplicandBase: 16, - multiplierBase: 16, - }) -} - -function isBalanceSufficient ({ - amount = '0x0', - amountConversionRate = 1, - balance = '0x0', - conversionRate = 1, - gasTotal = '0x0', - primaryCurrency, -}) { - const totalAmount = addCurrencies(amount, gasTotal, { - aBase: 16, - bBase: 16, - toNumericBase: 'hex', - }) - - const balanceIsSufficient = conversionGTE( - { - value: balance, - fromNumericBase: 'hex', - fromCurrency: primaryCurrency, - conversionRate, - }, - { - value: totalAmount, - fromNumericBase: 'hex', - conversionRate: Number(amountConversionRate) || conversionRate, - fromCurrency: primaryCurrency, - }, - ) - - return balanceIsSufficient -} - -function isTokenBalanceSufficient ({ - amount = '0x0', - tokenBalance, - decimals, -}) { - const amountInDec = conversionUtil(amount, { - fromNumericBase: 'hex', - }) - - const tokenBalanceIsSufficient = conversionGTE( - { - value: tokenBalance, - fromNumericBase: 'dec', - }, - { - value: calcTokenAmount(amountInDec, decimals), - fromNumericBase: 'dec', - }, - ) - - return tokenBalanceIsSufficient -} - -function getAmountErrorObject ({ - amount, - amountConversionRate, - balance, - conversionRate, - gasTotal, - primaryCurrency, - selectedToken, - tokenBalance, -}) { - let insufficientFunds = false - if (gasTotal && conversionRate && !selectedToken) { - insufficientFunds = !isBalanceSufficient({ - amount, - amountConversionRate, - balance, - conversionRate, - gasTotal, - primaryCurrency, - }) - } - - let inSufficientTokens = false - if (selectedToken && tokenBalance !== null) { - const { decimals } = selectedToken - inSufficientTokens = !isTokenBalanceSufficient({ - tokenBalance, - amount, - decimals, - }) - } - - const amountLessThanZero = conversionGreaterThan( - { value: 0, fromNumericBase: 'dec' }, - { value: amount, fromNumericBase: 'hex' }, - ) - - let amountError = null - - if (insufficientFunds) { - amountError = INSUFFICIENT_FUNDS_ERROR - } else if (inSufficientTokens) { - amountError = INSUFFICIENT_TOKENS_ERROR - } else if (amountLessThanZero) { - amountError = NEGATIVE_ETH_ERROR - } - - return { amount: amountError } -} - -function getGasFeeErrorObject ({ - amount, - amountConversionRate, - balance, - conversionRate, - gasTotal, - primaryCurrency, -}) { - let gasFeeError = null - - if (gasTotal && conversionRate) { - const insufficientFunds = !isBalanceSufficient({ - amount: '0x0', - amountConversionRate, - balance, - conversionRate, - gasTotal, - primaryCurrency, - }) - - if (insufficientFunds) { - gasFeeError = INSUFFICIENT_FUNDS_ERROR - } - } - - return { gasFee: gasFeeError } -} - -function calcTokenBalance ({ selectedToken, usersToken }) { - const { decimals } = selectedToken || {} - return calcTokenAmount(usersToken.balance.toString(), decimals) + '' -} - -function doesAmountErrorRequireUpdate ({ - balance, - gasTotal, - prevBalance, - prevGasTotal, - prevTokenBalance, - selectedToken, - tokenBalance, -}) { - const balanceHasChanged = balance !== prevBalance - const gasTotalHasChange = gasTotal !== prevGasTotal - const tokenBalanceHasChanged = selectedToken && tokenBalance !== prevTokenBalance - const amountErrorRequiresUpdate = balanceHasChanged || gasTotalHasChange || tokenBalanceHasChanged - - return amountErrorRequiresUpdate -} - -async function estimateGas ({ selectedAddress, selectedToken, blockGasLimit, to, value, gasPrice, estimateGasMethod }) { - const paramsForGasEstimate = { from: selectedAddress, value, gasPrice } - - if (selectedToken) { - paramsForGasEstimate.value = '0x0' - paramsForGasEstimate.data = generateTokenTransferData({ toAddress: to, amount: value, selectedToken }) - } - - // if recipient has no code, gas is 21k max: - if (!selectedToken) { - const code = Boolean(to) && await global.eth.getCode(to) - if (!code || code === '0x') { - return SIMPLE_GAS_COST - } - } else if (selectedToken && !to) { - return BASE_TOKEN_GAS_COST - } - - paramsForGasEstimate.to = selectedToken ? selectedToken.address : to - - // if not, fall back to block gasLimit - paramsForGasEstimate.gas = ethUtil.addHexPrefix(multiplyCurrencies(blockGasLimit, 0.95, { - multiplicandBase: 16, - multiplierBase: 10, - roundDown: '0', - toNumericBase: 'hex', - })) - // run tx - return new Promise((resolve, reject) => { - return estimateGasMethod(paramsForGasEstimate, (err, estimatedGas) => { - if (err) { - const simulationFailed = ( - err.message.includes('Transaction execution error.') || - err.message.includes('gas required exceeds allowance or always failing transaction') - ) - if (simulationFailed) { - const estimateWithBuffer = addGasBuffer(paramsForGasEstimate.gas, blockGasLimit, 1.5) - return resolve(ethUtil.addHexPrefix(estimateWithBuffer)) - } else { - return reject(err) - } - } - const estimateWithBuffer = addGasBuffer(estimatedGas.toString(16), blockGasLimit, 1.5) - return resolve(ethUtil.addHexPrefix(estimateWithBuffer)) - }) - }) -} - -function addGasBuffer (initialGasLimitHex, blockGasLimitHex, bufferMultiplier = 1.5) { - const upperGasLimit = multiplyCurrencies(blockGasLimitHex, 0.9, { - toNumericBase: 'hex', - multiplicandBase: 16, - multiplierBase: 10, - numberOfDecimals: '0', - }) - const bufferedGasLimit = multiplyCurrencies(initialGasLimitHex, bufferMultiplier, { - toNumericBase: 'hex', - multiplicandBase: 16, - multiplierBase: 10, - numberOfDecimals: '0', - }) - - // if initialGasLimit is above blockGasLimit, dont modify it - if (conversionGreaterThan( - { value: initialGasLimitHex, fromNumericBase: 'hex' }, - { value: upperGasLimit, fromNumericBase: 'hex' }, - )) return initialGasLimitHex - // if bufferedGasLimit is below blockGasLimit, use bufferedGasLimit - if (conversionLessThan( - { value: bufferedGasLimit, fromNumericBase: 'hex' }, - { value: upperGasLimit, fromNumericBase: 'hex' }, - )) return bufferedGasLimit - // otherwise use blockGasLimit - return upperGasLimit -} - -function generateTokenTransferData ({ toAddress = '0x0', amount = '0x0', selectedToken }) { - if (!selectedToken) return - return TOKEN_TRANSFER_FUNCTION_SIGNATURE + Array.prototype.map.call( - abi.rawEncode(['address', 'uint256'], [toAddress, ethUtil.addHexPrefix(amount)]), - x => ('00' + x.toString(16)).slice(-2) - ).join('') -} - -function estimateGasPriceFromRecentBlocks (recentBlocks) { - // Return 1 gwei if no blocks have been observed: - if (!recentBlocks || recentBlocks.length === 0) { - return ONE_GWEI_IN_WEI_HEX - } - - const lowestPrices = recentBlocks.map((block) => { - if (!block.gasPrices || block.gasPrices.length < 1) { - return ONE_GWEI_IN_WEI_HEX - } - return block.gasPrices.reduce((currentLowest, next) => { - return parseInt(next, 16) < parseInt(currentLowest, 16) ? next : currentLowest - }) - }) - .sort((a, b) => parseInt(a, 16) > parseInt(b, 16) ? 1 : -1) - - return lowestPrices[Math.floor(lowestPrices.length / 2)] -} - -function getToAddressForGasUpdate (...addresses) { - return [...addresses, ''].find(str => str !== undefined && str !== null).toLowerCase() -} - -function removeLeadingZeroes (str) { - return str.replace(/^0*(?=\d)/, '') -} |