|
|
|
import abi from 'ethereumjs-abi';
|
|
|
|
import {
|
|
|
|
addCurrencies,
|
|
|
|
conversionUtil,
|
|
|
|
conversionGTE,
|
|
|
|
multiplyCurrencies,
|
|
|
|
conversionGreaterThan,
|
|
|
|
conversionLessThan,
|
|
|
|
} from '../../../shared/modules/conversion.utils';
|
|
|
|
|
|
|
|
import { calcTokenAmount } from '../../helpers/utils/token-util';
|
|
|
|
import { addHexPrefix } from '../../../app/scripts/lib/util';
|
|
|
|
import { ERC20, ERC721 } from '../../helpers/constants/common';
|
|
|
|
import {
|
|
|
|
TOKEN_TRANSFER_FUNCTION_SIGNATURE,
|
|
|
|
COLLECTIBLE_TRANSFER_FROM_FUNCTION_SIGNATURE,
|
|
|
|
} from './send.constants';
|
|
|
|
|
|
|
|
export {
|
|
|
|
addGasBuffer,
|
|
|
|
calcGasTotal,
|
|
|
|
getAssetTransferData,
|
|
|
|
generateERC20TransferData,
|
|
|
|
generateERC721TransferData,
|
|
|
|
isBalanceSufficient,
|
|
|
|
isTokenBalanceSufficient,
|
|
|
|
ellipsify,
|
|
|
|
};
|
|
|
|
|
|
|
|
function calcGasTotal(gasLimit = '0', gasPrice = '0') {
|
|
|
|
return multiplyCurrencies(gasLimit, gasPrice, {
|
|
|
|
toNumericBase: 'hex',
|
|
|
|
multiplicandBase: 16,
|
|
|
|
multiplierBase: 16,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function isBalanceSufficient({
|
|
|
|
amount = '0x0',
|
|
|
|
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,
|
|
|
|
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 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 generateERC20TransferData({
|
|
|
|
toAddress = '0x0',
|
|
|
|
amount = '0x0',
|
|
|
|
sendToken,
|
|
|
|
}) {
|
|
|
|
if (!sendToken) {
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
return (
|
|
|
|
TOKEN_TRANSFER_FUNCTION_SIGNATURE +
|
|
|
|
Array.prototype.map
|
|
|
|
.call(
|
|
|
|
abi.rawEncode(
|
|
|
|
['address', 'uint256'],
|
|
|
|
[addHexPrefix(toAddress), addHexPrefix(amount)],
|
|
|
|
),
|
|
|
|
(x) => `00${x.toString(16)}`.slice(-2),
|
|
|
|
)
|
|
|
|
.join('')
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function generateERC721TransferData({
|
|
|
|
toAddress = '0x0',
|
|
|
|
fromAddress = '0x0',
|
|
|
|
tokenId,
|
|
|
|
}) {
|
|
|
|
if (!tokenId) {
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
return (
|
|
|
|
COLLECTIBLE_TRANSFER_FROM_FUNCTION_SIGNATURE +
|
|
|
|
Array.prototype.map
|
|
|
|
.call(
|
|
|
|
abi.rawEncode(
|
|
|
|
['address', 'address', 'uint256'],
|
|
|
|
[addHexPrefix(fromAddress), addHexPrefix(toAddress), tokenId],
|
|
|
|
),
|
|
|
|
(x) => `00${x.toString(16)}`.slice(-2),
|
|
|
|
)
|
|
|
|
.join('')
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function getAssetTransferData({ sendToken, fromAddress, toAddress, amount }) {
|
|
|
|
switch (sendToken.standard) {
|
|
|
|
case ERC721:
|
|
|
|
return generateERC721TransferData({
|
|
|
|
toAddress,
|
|
|
|
fromAddress,
|
|
|
|
tokenId: sendToken.tokenId,
|
|
|
|
});
|
|
|
|
case ERC20:
|
|
|
|
default:
|
|
|
|
return generateERC20TransferData({
|
|
|
|
toAddress,
|
|
|
|
amount,
|
|
|
|
sendToken,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function ellipsify(text, first = 6, last = 4) {
|
|
|
|
return `${text.slice(0, first)}...${text.slice(-last)}`;
|
|
|
|
}
|