1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-22 01:47:00 +01:00

Refactor usages of conversion util in the app folder and shared folder in favor of Numeric (#17331)

This commit is contained in:
Brad Decker 2023-01-23 11:41:01 -06:00 committed by GitHub
parent 213240349d
commit ead1446c98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 95 additions and 139 deletions

View File

@ -5,9 +5,7 @@ import { ObservableStore } from '@metamask/obs-store';
import { mapValues, cloneDeep } from 'lodash';
import abi from 'human-standard-token-abi';
import {
conversionUtil,
decGWEIToHexWEI,
addCurrencies,
sumHexes,
} from '../../../shared/modules/conversion.utils';
import {
@ -40,6 +38,8 @@ import {
} from '../../../shared/lib/transactions-controller-utils';
import fetchEstimatedL1Fee from '../../../ui/helpers/utils/optimism/fetchEstimatedL1Fee';
import { Numeric } from '../../../shared/modules/Numeric';
import { EtherDenomination } from '../../../shared/constants/common';
import { NETWORK_EVENTS } from './network';
// The MAX_GAS_LIMIT is a number that is higher than the maximum gas costs we have observed on any aggregator
@ -687,17 +687,22 @@ export default class SwapsController {
estimatedBaseFee,
} = gasFeeEstimates;
usedGasPrice = addCurrencies(
customMaxPriorityFeePerGas || // Is already in hex WEI.
decGWEIToHexWEI(suggestedMaxPriorityFeePerGas),
decGWEIToHexWEI(estimatedBaseFee),
{
aBase: 16,
bBase: 16,
toNumericBase: 'hex',
numberOfDecimals: 6,
},
const suggestedMaxPriorityFeePerGasInHexWEI = decGWEIToHexWEI(
suggestedMaxPriorityFeePerGas,
);
const estimatedBaseFeeNumeric = new Numeric(
estimatedBaseFee,
10,
EtherDenomination.GWEI,
).toDenomination(EtherDenomination.WEI);
usedGasPrice = new Numeric(
customMaxPriorityFeePerGas || suggestedMaxPriorityFeePerGasInHexWEI,
16,
)
.add(estimatedBaseFeeNumeric)
.round(6)
.toString();
} else if (gasEstimateType === GAS_ESTIMATE_TYPES.LEGACY) {
usedGasPrice = customGasPrice || decGWEIToHexWEI(gasFeeEstimates.high);
} else if (gasEstimateType === GAS_ESTIMATE_TYPES.ETH_GASPRICE) {
@ -747,34 +752,25 @@ export default class SwapsController {
// It always includes any external fees charged by the quote source. In
// addition, if the source asset is the selected chain's default token, trade.value
// includes the amount of that token.
const totalWeiCost = new BigNumber(gasTotalInWeiHex, 16).plus(
trade.value,
const totalWeiCost = new Numeric(
gasTotalInWeiHex,
16,
);
EtherDenomination.WEI,
).add(new Numeric(trade.value, 16, EtherDenomination.WEI));
const totalEthCost = conversionUtil(totalWeiCost, {
fromCurrency: 'ETH',
fromDenomination: 'WEI',
toDenomination: 'ETH',
fromNumericBase: 'BN',
numberOfDecimals: 6,
});
const totalEthCost = totalWeiCost
.toDenomination(EtherDenomination.ETH)
.round(6).value;
// The total fee is aggregator/exchange fees plus gas fees.
// If the swap is from the selected chain's default token, subtract
// the sourceAmount from the total cost. Otherwise, the total fee
// is simply trade.value plus gas fees.
const ethFee = isSwapsDefaultTokenAddress(sourceToken, chainId)
? conversionUtil(
totalWeiCost.minus(sourceAmount, 10), // sourceAmount is in wei
{
fromCurrency: 'ETH',
fromDenomination: 'WEI',
toDenomination: 'ETH',
fromNumericBase: 'BN',
numberOfDecimals: 6,
},
)
? totalWeiCost
.minus(new Numeric(sourceAmount, 10))
.toDenomination(EtherDenomination.ETH)
.round(6).value
: totalEthCost;
const decimalAdjustedDestinationAmount = calcTokenAmount(

View File

@ -35,7 +35,6 @@ import {
import {
bnToHex,
decGWEIToHexWEI,
decimalToHex,
hexWEIToDecETH,
hexWEIToDecGWEI,
} from '../../../../shared/modules/conversion.utils';
@ -58,6 +57,7 @@ import {
getSwapsTokensReceivedFromTxMeta,
TRANSACTION_ENVELOPE_TYPE_NAMES,
} from '../../../../shared/lib/transactions-controller-utils';
import { Numeric } from '../../../../shared/modules/Numeric';
import TransactionStateManager from './tx-state-manager';
import TxGasUtil from './tx-gas-utils';
import PendingTransactionTracker from './pending-tx-tracker';
@ -1463,7 +1463,7 @@ export default class TransactionController extends EventEmitter {
...normalizedTxParams,
type,
gasLimit: normalizedTxParams.gas,
chainId: addHexPrefix(decimalToHex(chainId)),
chainId: new Numeric(chainId, 10).toPrefixedHexString(),
};
// sign tx
const fromAddress = txParams.from;

View File

@ -0,0 +1,8 @@
import { calcGasTotal } from './transactions-controller-utils';
describe('calcGasTotal()', () => {
it('should correctly compute gasTotal', () => {
const result = calcGasTotal(12, 15);
expect(result).toStrictEqual('17a');
});
});

View File

@ -1,9 +1,7 @@
import BigNumber from 'bignumber.js';
import { EtherDenomination } from '../constants/common';
import { TransactionEnvelopeType } from '../constants/transaction';
import {
multiplyCurrencies,
subtractCurrencies,
} from '../modules/conversion.utils';
import { Numeric } from '../modules/Numeric';
import { isSwapsDefaultTokenSymbol } from '../modules/swaps.utils';
const TOKEN_TRANSFER_LOG_TOPIC_HASH =
@ -14,11 +12,7 @@ export const TRANSACTION_NO_CONTRACT_ERROR_KEY = 'transactionErrorNoContract';
export const TEN_SECONDS_IN_MILLISECONDS = 10_000;
export function calcGasTotal(gasLimit = '0', gasPrice = '0') {
return multiplyCurrencies(gasLimit, gasPrice, {
toNumericBase: 'hex',
multiplicandBase: 16,
multiplierBase: 16,
});
return new Numeric(gasLimit, 16).times(new Numeric(gasPrice, 16)).toString();
}
/**
@ -69,13 +63,16 @@ export function getSwapsTokensReceivedFromTxMeta(
return txMeta.swapMetaData.token_to_amount;
}
let approvalTxGasCost = '0x0';
let approvalTxGasCost = new Numeric('0x0', 16);
if (approvalTxMeta && approvalTxMeta.txReceipt) {
approvalTxGasCost = calcGasTotal(
approvalTxGasCost = new Numeric(
calcGasTotal(
approvalTxMeta.txReceipt.gasUsed,
networkAndAccountSupports1559
? approvalTxMeta.txReceipt.effectiveGasPrice // Base fee + priority fee.
: approvalTxMeta.txParams.gasPrice,
),
16,
);
}
@ -85,33 +82,22 @@ export function getSwapsTokensReceivedFromTxMeta(
? txReceipt.effectiveGasPrice
: txMeta.txParams.gasPrice,
);
const totalGasCost = new BigNumber(gasCost, 16)
.plus(approvalTxGasCost, 16)
.toString(16);
const totalGasCost = new Numeric(gasCost, 16).plus(approvalTxGasCost);
const preTxBalanceLessGasCost = subtractCurrencies(
txMeta.preTxBalance,
const preTxBalanceLessGasCost = new Numeric(txMeta.preTxBalance, 16).minus(
totalGasCost,
{
aBase: 16,
bBase: 16,
toNumericBase: 'hex',
},
);
const ethReceived = subtractCurrencies(
const ethReceived = new Numeric(
txMeta.postTxBalance,
preTxBalanceLessGasCost,
{
aBase: 16,
bBase: 16,
fromDenomination: 'WEI',
toDenomination: 'ETH',
toNumericBase: 'dec',
numberOfDecimals: 6,
},
);
return ethReceived;
16,
EtherDenomination.WEI,
)
.subtract(preTxBalanceLessGasCost)
.toDenomination(EtherDenomination.ETH)
.toBase(10)
.round(6);
return ethReceived.toString();
}
const txReceiptLogs = txReceipt?.logs;
if (txReceiptLogs && txReceipt?.status !== '0x0') {

View File

@ -1,9 +1,4 @@
import { addHexPrefix } from 'ethereumjs-util';
import {
addCurrencies,
conversionGreaterThan,
multiplyCurrencies,
} from './conversion.utils';
import { Numeric } from './Numeric';
/**
* Accepts an options bag containing gas fee parameters in hex format and
@ -27,26 +22,19 @@ export function getMaximumGasTotalInHexWei({
maxFeePerGas,
} = {}) {
if (maxFeePerGas) {
return addHexPrefix(
multiplyCurrencies(gasLimit, maxFeePerGas, {
toNumericBase: 'hex',
multiplicandBase: 16,
multiplierBase: 16,
}),
);
return new Numeric(gasLimit, 16)
.times(new Numeric(maxFeePerGas, 16))
.toPrefixedHexString();
}
if (!gasPrice) {
throw new Error(
'getMaximumGasTotalInHexWei requires gasPrice be provided to calculate legacy gas total',
);
}
return addHexPrefix(
multiplyCurrencies(gasLimit, gasPrice, {
toNumericBase: 'hex',
multiplicandBase: 16,
multiplierBase: 16,
}),
);
return new Numeric(gasLimit, 16)
.times(new Numeric(gasPrice, 16))
.toPrefixedHexString();
}
/**
@ -105,25 +93,14 @@ export function getMinimumGasTotalInHexWei({
if (isEIP1559Estimate === false) {
return getMaximumGasTotalInHexWei({ gasLimit, gasPrice });
}
const minimumFeePerGas = addCurrencies(baseFeePerGas, maxPriorityFeePerGas, {
toNumericBase: 'hex',
aBase: 16,
bBase: 16,
});
const minimumFeePerGas = new Numeric(baseFeePerGas, 16)
.add(new Numeric(maxPriorityFeePerGas, 16))
.toString();
if (
conversionGreaterThan(
{ value: minimumFeePerGas, fromNumericBase: 'hex' },
{ value: maxFeePerGas, fromNumericBase: 'hex' },
)
) {
if (new Numeric(minimumFeePerGas, 16).greaterThan(maxFeePerGas, 16)) {
return getMaximumGasTotalInHexWei({ gasLimit, maxFeePerGas });
}
return addHexPrefix(
multiplyCurrencies(gasLimit, minimumFeePerGas, {
toNumericBase: 'hex',
multiplicandBase: 16,
multiplierBase: 16,
}),
);
return new Numeric(gasLimit, 16)
.times(new Numeric(minimumFeePerGas, 16))
.toPrefixedHexString();
}

View File

@ -1,9 +1,9 @@
const { addHexPrefix } = require('ethereumjs-util');
const { conversionUtil } = require('./conversion.utils');
const {
getMaximumGasTotalInHexWei,
getMinimumGasTotalInHexWei,
} = require('./gas.utils');
const { Numeric } = require('./Numeric');
const feesToTest = [10, 24, 90];
const tipsToTest = [2, 10, 50];
@ -18,15 +18,17 @@ describe('gas utils', () => {
gasLimitsToTest.forEach((gasLimit) => {
const expectedResult = (gasLimit * maxFeePerGas).toString();
const gasLimitHex = addHexPrefix(gasLimit.toString(16));
const result = conversionUtil(
const result = new Numeric(
getMaximumGasTotalInHexWei({
gasLimit: gasLimitHex,
maxFeePerGas: addHexPrefix(maxFeePerGas.toString(16)),
}),
{ fromNumericBase: 'hex', toNumericBase: 'dec' },
16,
);
it(`returns ${expectedResult} when provided gasLimit: ${gasLimit}`, () => {
expect(result).toStrictEqual(expectedResult);
expect(result.toBase(10).toString()).toStrictEqual(
expectedResult,
);
});
});
});
@ -44,7 +46,7 @@ describe('gas utils', () => {
minimum < maximum ? minimum : maximum;
const results = gasLimitsToTest.map((gasLimit) => {
const gasLimitHex = addHexPrefix(gasLimit.toString(16));
const result = conversionUtil(
const result = new Numeric(
getMinimumGasTotalInHexWei({
gasLimit: gasLimitHex,
maxFeePerGas: addHexPrefix(maxFeePerGas.toString(16)),
@ -53,9 +55,9 @@ describe('gas utils', () => {
),
baseFeePerGas: addHexPrefix(baseFeePerGas.toString(16)),
}),
{ fromNumericBase: 'hex', toNumericBase: 'dec' },
16,
);
return { result, gasLimit };
return { result: result.toBase(10).toString(), gasLimit };
});
it(`should use an effective gasPrice of ${expectedEffectiveGasPrice}`, () => {
expect(
@ -89,13 +91,15 @@ describe('gas utils', () => {
const gasLimitHex = addHexPrefix(gasLimit.toString(16));
it(`returns ${expectedResult} when provided gasLimit of ${gasLimit}`, () => {
expect(
conversionUtil(
new Numeric(
getMaximumGasTotalInHexWei({
gasLimit: gasLimitHex,
gasPrice: addHexPrefix(gasPrice.toString(16)),
}),
{ fromNumericBase: 'hex', toNumericBase: 'dec' },
),
16,
)
.toBase(10)
.toString(),
).toStrictEqual(expectedResult);
});
});
@ -111,16 +115,15 @@ describe('gas utils', () => {
const gasLimitHex = addHexPrefix(gasLimit.toString(16));
it(`returns ${expectedResult} when provided gasLimit of ${gasLimit}`, () => {
expect(
conversionUtil(
new Numeric(
getMinimumGasTotalInHexWei({
gasLimit: gasLimitHex,
gasPrice: addHexPrefix(gasPrice.toString(16)),
}),
{
fromNumericBase: 'hex',
toNumericBase: 'dec',
},
),
16,
)
.toBase(10)
.toString(),
).toStrictEqual(expectedResult);
});
});

View File

@ -1,8 +1,6 @@
import { rawEncode } from 'ethereumjs-abi';
import { calcGasTotal } from '../../../shared/lib/transactions-controller-utils';
import {
multiplyCurrencies,
addCurrencies,
conversionGTE,
conversionUtil,
@ -49,18 +47,6 @@ jest.mock('ethereumjs-abi', () => ({
}));
describe('send utils', () => {
describe('calcGasTotal()', () => {
it('should call multiplyCurrencies with the correct params and return the multiplyCurrencies return', () => {
const result = calcGasTotal(12, 15);
expect(result).toStrictEqual('12x15');
expect(multiplyCurrencies).toHaveBeenCalledWith(12, 15, {
multiplicandBase: 16,
multiplierBase: 16,
toNumericBase: 'hex',
});
});
});
describe('generateERC20TransferData()', () => {
it('should return undefined if not passed a send token', () => {
expect(