aboutsummaryrefslogtreecommitdiffstats
path: root/ui/app/components/send/send.utils.js
diff options
context:
space:
mode:
Diffstat (limited to 'ui/app/components/send/send.utils.js')
-rw-r--r--ui/app/components/send/send.utils.js332
1 files changed, 0 insertions, 332 deletions
diff --git a/ui/app/components/send/send.utils.js b/ui/app/components/send/send.utils.js
deleted file mode 100644
index d78b7736f..000000000
--- a/ui/app/components/send/send.utils.js
+++ /dev/null
@@ -1,332 +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: 'hex',
- },
- {
- value: calcTokenAmount(amountInDec, decimals),
- },
- )
-
- 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 ({
- 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).toString(16)
-}
-
-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,
- data,
- gasPrice,
- estimateGasMethod,
-}) {
- const paramsForGasEstimate = { from: selectedAddress, value, gasPrice }
-
- // if recipient has no code, gas is 21k max:
- if (!selectedToken && !data) {
- const code = Boolean(to) && await global.eth.getCode(to)
- // Geth will return '0x', and ganache-core v2.2.1 will return '0x0'
- const codeIsEmpty = !code || code === '0x' || code === '0x0'
- if (codeIsEmpty) {
- return SIMPLE_GAS_COST
- }
- } else if (selectedToken && !to) {
- return BASE_TOKEN_GAS_COST
- }
-
- if (selectedToken) {
- paramsForGasEstimate.value = '0x0'
- paramsForGasEstimate.data = generateTokenTransferData({ toAddress: to, amount: value, selectedToken })
- paramsForGasEstimate.to = selectedToken.address
- } else {
- if (data) {
- paramsForGasEstimate.data = data
- }
-
- if (to) {
- paramsForGasEstimate.to = to
- }
-
- if (!value || value === '0') {
- paramsForGasEstimate.value = '0xff'
- }
- }
-
- // if not, fall back to block gasLimit
- paramsForGasEstimate.gas = ethUtil.addHexPrefix(multiplyCurrencies(blockGasLimit || '0x5208', 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)/, '')
-}