mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 01:47:00 +01:00
Remove related UI code from the app dir (#15384)
Co-authored-by: metamaskbot <metamaskbot@users.noreply.github.com> Co-authored-by: Brad Decker <bhdecker84@gmail.com> Co-authored-by: Akintayo A. Olusegun <akintayo.segun@gmail.com>
This commit is contained in:
parent
c2b7690119
commit
6e13524bcd
@ -269,6 +269,7 @@ module.exports = {
|
||||
'test/jest/*.js',
|
||||
'ui/**/*.test.js',
|
||||
'ui/__mocks__/*.js',
|
||||
'shared/lib/error-utils.test.js',
|
||||
],
|
||||
extends: ['@metamask/eslint-config-jest'],
|
||||
parserOptions: {
|
||||
|
@ -7,6 +7,7 @@ module.exports = {
|
||||
'./app/scripts/platforms/*.test.js',
|
||||
'./app/scripts/controllers/network/**/*.test.js',
|
||||
'./app/scripts/controllers/permissions/**/*.test.js',
|
||||
'./app/scripts/constants/error-utils.test.js',
|
||||
],
|
||||
recursive: true,
|
||||
require: ['test/env.js', 'test/setup.js'],
|
||||
|
@ -4,8 +4,6 @@ import BigNumber from 'bignumber.js';
|
||||
import { ObservableStore } from '@metamask/obs-store';
|
||||
import { mapValues, cloneDeep } from 'lodash';
|
||||
import abi from 'human-standard-token-abi';
|
||||
import { calcTokenAmount } from '../../../ui/helpers/utils/token-util';
|
||||
import { calcGasTotal } from '../../../ui/pages/send/send.utils';
|
||||
import {
|
||||
conversionUtil,
|
||||
decGWEIToHexWEI,
|
||||
@ -30,10 +28,15 @@ import { isSwapsDefaultTokenAddress } from '../../../shared/modules/swaps.utils'
|
||||
import {
|
||||
fetchTradesInfo as defaultFetchTradesInfo,
|
||||
getBaseApi,
|
||||
} from '../../../ui/pages/swaps/swaps.util';
|
||||
import fetchWithCache from '../../../ui/helpers/utils/fetch-with-cache';
|
||||
} from '../../../shared/lib/swaps-utils';
|
||||
import fetchWithCache from '../../../shared/lib/fetch-with-cache';
|
||||
import { MINUTE, SECOND } from '../../../shared/constants/time';
|
||||
import { isEqualCaseInsensitive } from '../../../shared/modules/string-utils';
|
||||
import {
|
||||
calcGasTotal,
|
||||
calcTokenAmount,
|
||||
} from '../../../shared/lib/transactions-controller-utils';
|
||||
|
||||
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
|
||||
|
@ -17,13 +17,6 @@ import {
|
||||
addHexPrefix,
|
||||
getChainType,
|
||||
} from '../../lib/util';
|
||||
import { calcGasTotal } from '../../../../ui/pages/send/send.utils';
|
||||
import { getSwapsTokensReceivedFromTxMeta } from '../../../../ui/pages/swaps/swaps.util';
|
||||
import {
|
||||
hexWEIToDecGWEI,
|
||||
decimalToHex,
|
||||
hexWEIToDecETH,
|
||||
} from '../../../../ui/helpers/utils/conversions.util';
|
||||
import {
|
||||
TRANSACTION_STATUSES,
|
||||
TRANSACTION_TYPES,
|
||||
@ -32,7 +25,6 @@ import {
|
||||
TRANSACTION_ENVELOPE_TYPES,
|
||||
TRANSACTION_EVENTS,
|
||||
} from '../../../../shared/constants/transaction';
|
||||
import { TRANSACTION_ENVELOPE_TYPE_NAMES } from '../../../../ui/helpers/constants/transactions';
|
||||
import { METAMASK_CONTROLLER_EVENTS } from '../../metamask-controller';
|
||||
import {
|
||||
GAS_LIMITS,
|
||||
@ -56,6 +48,14 @@ import {
|
||||
isEIP1559Transaction,
|
||||
} from '../../../../shared/modules/transaction.utils';
|
||||
import { ORIGIN_METAMASK } from '../../../../shared/constants/app';
|
||||
import {
|
||||
calcGasTotal,
|
||||
decimalToHex,
|
||||
getSwapsTokensReceivedFromTxMeta,
|
||||
hexWEIToDecETH,
|
||||
hexWEIToDecGWEI,
|
||||
TRANSACTION_ENVELOPE_TYPE_NAMES,
|
||||
} from '../../../../shared/lib/transactions-controller-utils';
|
||||
import TransactionStateManager from './tx-state-manager';
|
||||
import TxGasUtil from './tx-gas-utils';
|
||||
import PendingTransactionTracker from './pending-tx-tracker';
|
||||
|
@ -25,9 +25,9 @@ import {
|
||||
GAS_ESTIMATE_TYPES,
|
||||
GAS_RECOMMENDATIONS,
|
||||
} from '../../../../shared/constants/gas';
|
||||
import { TRANSACTION_ENVELOPE_TYPE_NAMES } from '../../../../ui/helpers/constants/transactions';
|
||||
import { METAMASK_CONTROLLER_EVENTS } from '../../metamask-controller';
|
||||
import { ORIGIN_METAMASK } from '../../../../shared/constants/app';
|
||||
import { TRANSACTION_ENVELOPE_TYPE_NAMES } from '../../../../shared/lib/transactions-controller-utils';
|
||||
import TransactionController from '.';
|
||||
|
||||
const noop = () => true;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { EthereumRpcError } from 'eth-rpc-errors';
|
||||
import SafeEventEmitter from 'safe-event-emitter';
|
||||
import createRandomId from '../../../shared/modules/random-id';
|
||||
import { TEN_SECONDS_IN_MILLISECONDS } from '../../../ui/helpers/constants/critical-error';
|
||||
import { TEN_SECONDS_IN_MILLISECONDS } from '../../../shared/lib/transactions-controller-utils';
|
||||
|
||||
class DisconnectError extends Error {}
|
||||
|
||||
|
@ -90,14 +90,14 @@ import {
|
||||
} from '../../shared/constants/app';
|
||||
import { EVENT, EVENT_NAMES } from '../../shared/constants/metametrics';
|
||||
|
||||
import { hexToDecimal } from '../../ui/helpers/utils/conversions.util';
|
||||
import {
|
||||
getTokenIdParam,
|
||||
getTokenValueParam,
|
||||
} from '../../ui/helpers/utils/token-util';
|
||||
import { getTokenIdParam } from '../../ui/helpers/utils/token-util';
|
||||
import { isEqualCaseInsensitive } from '../../shared/modules/string-utils';
|
||||
import { parseStandardTokenTransactionData } from '../../shared/modules/transaction.utils';
|
||||
import { STATIC_MAINNET_TOKEN_LIST } from '../../shared/constants/tokens';
|
||||
import {
|
||||
getTokenValueParam,
|
||||
hexToDecimal,
|
||||
} from '../../shared/lib/metamask-controller-utils';
|
||||
import {
|
||||
onMessageReceived,
|
||||
checkForMultipleVersionsRunning,
|
||||
|
@ -17,8 +17,8 @@ import {
|
||||
ENVIRONMENT_TYPE_POPUP,
|
||||
} from '../../shared/constants/app';
|
||||
import { isManifestV3 } from '../../shared/modules/mv3.utils';
|
||||
import { SUPPORT_LINK } from '../../ui/helpers/constants/common';
|
||||
import { getErrorHtml } from '../../ui/helpers/utils/error-utils';
|
||||
import { SUPPORT_LINK } from '../../shared/lib/ui-utils';
|
||||
import { getErrorHtml } from '../../shared/lib/error-utils';
|
||||
import ExtensionPlatform from './platforms/extension';
|
||||
import { setupMultiplex } from './lib/stream-utils';
|
||||
import { getEnvironmentType } from './lib/util';
|
||||
|
@ -177,9 +177,12 @@ async function verifyEnglishLocale() {
|
||||
'ui/pages/confirmation/templates/*.js',
|
||||
];
|
||||
const testGlob = '**/*.test.js';
|
||||
const javascriptFiles = await glob(['ui/**/*.js', 'shared/**/*.js'], {
|
||||
const javascriptFiles = await glob(
|
||||
['ui/**/*.js', 'shared/**/*.js', 'app/scripts/constants/**/*.js'],
|
||||
{
|
||||
ignore: [...globsToStrictSearch, testGlob],
|
||||
});
|
||||
},
|
||||
);
|
||||
const javascriptFilesToStrictSearch = await glob(globsToStrictSearch, {
|
||||
ignore: [testGlob],
|
||||
});
|
||||
|
@ -42,6 +42,7 @@ module.exports = {
|
||||
'<rootDir>app/scripts/controllers/network/**/*.test.js',
|
||||
'<rootDir>/app/scripts/controllers/permissions/**/*.test.js',
|
||||
'<rootDir>/app/scripts/lib/createRPCMethodTrackingMiddleware.test.js',
|
||||
'<rootDir>/app/scripts/constants/error-utils.test.js',
|
||||
],
|
||||
testTimeout: 2500,
|
||||
// We have to specify the environment we are running in, which is jsdom. The
|
||||
|
@ -1,7 +1,27 @@
|
||||
import getFirstPreferredLangCode from '../../../app/scripts/lib/get-first-preferred-lang-code';
|
||||
import { setupLocale } from '../..';
|
||||
import { memoize } from 'lodash';
|
||||
import getFirstPreferredLangCode from '../../app/scripts/lib/get-first-preferred-lang-code';
|
||||
import {
|
||||
fetchLocale,
|
||||
loadRelativeTimeFormatLocaleData,
|
||||
} from '../../ui/helpers/utils/i18n-helper';
|
||||
import switchDirection from './switch-direction';
|
||||
|
||||
const _setupLocale = async (currentLocale) => {
|
||||
const currentLocaleMessages = currentLocale
|
||||
? await fetchLocale(currentLocale)
|
||||
: {};
|
||||
const enLocaleMessages = await fetchLocale('en');
|
||||
|
||||
await loadRelativeTimeFormatLocaleData('en');
|
||||
if (currentLocale) {
|
||||
await loadRelativeTimeFormatLocaleData(currentLocale);
|
||||
}
|
||||
|
||||
return { currentLocaleMessages, enLocaleMessages };
|
||||
};
|
||||
|
||||
export const setupLocale = memoize(_setupLocale);
|
||||
|
||||
const getLocaleContext = (currentLocaleMessages, enLocaleMessages) => {
|
||||
return (key) => {
|
||||
let message = currentLocaleMessages[key]?.message;
|
@ -1,14 +1,14 @@
|
||||
import { SUPPORT_LINK } from '../constants/common';
|
||||
import { fetchLocale } from '../../ui/helpers/utils/i18n-helper';
|
||||
import { SUPPORT_LINK } from './ui-utils';
|
||||
import { getErrorHtml } from './error-utils';
|
||||
import { fetchLocale } from './i18n-helper';
|
||||
|
||||
jest.mock('./i18n-helper', () => ({
|
||||
jest.mock('../../ui/helpers/utils/i18n-helper', () => ({
|
||||
fetchLocale: jest.fn(),
|
||||
loadRelativeTimeFormatLocaleData: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('Error utils Tests', () => {
|
||||
it('should get error html', async () => {
|
||||
describe('Error utils Tests', function () {
|
||||
it('should get error html', async function () {
|
||||
const mockStore = {
|
||||
localeMessages: {
|
||||
current: {
|
@ -1,5 +1,5 @@
|
||||
import { MINUTE, SECOND } from '../../../shared/constants/time';
|
||||
import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout';
|
||||
import { MINUTE, SECOND } from '../constants/time';
|
||||
import getFetchWithTimeout from '../modules/fetch-with-timeout';
|
||||
import { getStorageItem, setStorageItem } from './storage-helpers';
|
||||
|
||||
const fetchWithCache = async (
|
@ -3,7 +3,7 @@ import sinon from 'sinon';
|
||||
|
||||
import { getStorageItem, setStorageItem } from './storage-helpers';
|
||||
|
||||
jest.mock('./storage-helpers.js', () => ({
|
||||
jest.mock('./storage-helpers', () => ({
|
||||
getStorageItem: jest.fn(),
|
||||
setStorageItem: jest.fn(),
|
||||
}));
|
12
shared/lib/metamask-controller-utils.js
Normal file
12
shared/lib/metamask-controller-utils.js
Normal file
@ -0,0 +1,12 @@
|
||||
import { conversionUtil } from '../modules/conversion.utils';
|
||||
|
||||
export function hexToDecimal(hexValue) {
|
||||
return conversionUtil(hexValue, {
|
||||
fromNumericBase: 'hex',
|
||||
toNumericBase: 'dec',
|
||||
});
|
||||
}
|
||||
|
||||
export function getTokenValueParam(tokenData = {}) {
|
||||
return tokenData?.args?._value?.toString();
|
||||
}
|
320
shared/lib/swaps-utils.js
Normal file
320
shared/lib/swaps-utils.js
Normal file
@ -0,0 +1,320 @@
|
||||
import BigNumber from 'bignumber.js';
|
||||
import log from 'loglevel';
|
||||
import { CHAIN_IDS } from '../constants/network';
|
||||
import {
|
||||
GAS_API_BASE_URL,
|
||||
GAS_DEV_API_BASE_URL,
|
||||
SWAPS_API_V2_BASE_URL,
|
||||
SWAPS_CHAINID_DEFAULT_TOKEN_MAP,
|
||||
SWAPS_CLIENT_ID,
|
||||
SWAPS_DEV_API_V2_BASE_URL,
|
||||
SWAPS_WRAPPED_TOKENS_ADDRESSES,
|
||||
} from '../constants/swaps';
|
||||
import { SECOND } from '../constants/time';
|
||||
import { isValidHexAddress } from '../modules/hexstring-utils';
|
||||
import { addHexPrefix } from '../../app/scripts/lib/util';
|
||||
import fetchWithCache from './fetch-with-cache';
|
||||
import { decimalToHex } from './transactions-controller-utils';
|
||||
|
||||
const TEST_CHAIN_IDS = [CHAIN_IDS.GOERLI, CHAIN_IDS.LOCALHOST];
|
||||
|
||||
const clientIdHeader = { 'X-Client-Id': SWAPS_CLIENT_ID };
|
||||
|
||||
export const validHex = (string) => Boolean(string?.match(/^0x[a-f0-9]+$/u));
|
||||
export const truthyString = (string) => Boolean(string?.length);
|
||||
export const truthyDigitString = (string) =>
|
||||
truthyString(string) && Boolean(string.match(/^\d+$/u));
|
||||
|
||||
export function validateData(validators, object, urlUsed, logError = true) {
|
||||
return validators.every(({ property, type, validator }) => {
|
||||
const types = type.split('|');
|
||||
|
||||
const valid =
|
||||
types.some((_type) => typeof object[property] === _type) &&
|
||||
(!validator || validator(object[property]));
|
||||
if (!valid && logError) {
|
||||
log.error(
|
||||
`response to GET ${urlUsed} invalid for property ${property}; value was:`,
|
||||
object[property],
|
||||
'| type was: ',
|
||||
typeof object[property],
|
||||
);
|
||||
}
|
||||
return valid;
|
||||
});
|
||||
}
|
||||
|
||||
export const QUOTE_VALIDATORS = [
|
||||
{
|
||||
property: 'trade',
|
||||
type: 'object',
|
||||
validator: (trade) =>
|
||||
trade &&
|
||||
validHex(trade.data) &&
|
||||
isValidHexAddress(trade.to, { allowNonPrefixed: false }) &&
|
||||
isValidHexAddress(trade.from, { allowNonPrefixed: false }) &&
|
||||
truthyString(trade.value),
|
||||
},
|
||||
{
|
||||
property: 'approvalNeeded',
|
||||
type: 'object',
|
||||
validator: (approvalTx) =>
|
||||
approvalTx === null ||
|
||||
(approvalTx &&
|
||||
validHex(approvalTx.data) &&
|
||||
isValidHexAddress(approvalTx.to, { allowNonPrefixed: false }) &&
|
||||
isValidHexAddress(approvalTx.from, { allowNonPrefixed: false })),
|
||||
},
|
||||
{
|
||||
property: 'sourceAmount',
|
||||
type: 'string',
|
||||
validator: truthyDigitString,
|
||||
},
|
||||
{
|
||||
property: 'destinationAmount',
|
||||
type: 'string',
|
||||
validator: truthyDigitString,
|
||||
},
|
||||
{
|
||||
property: 'sourceToken',
|
||||
type: 'string',
|
||||
validator: (input) => isValidHexAddress(input, { allowNonPrefixed: false }),
|
||||
},
|
||||
{
|
||||
property: 'destinationToken',
|
||||
type: 'string',
|
||||
validator: (input) => isValidHexAddress(input, { allowNonPrefixed: false }),
|
||||
},
|
||||
{
|
||||
property: 'aggregator',
|
||||
type: 'string',
|
||||
validator: truthyString,
|
||||
},
|
||||
{
|
||||
property: 'aggType',
|
||||
type: 'string',
|
||||
validator: truthyString,
|
||||
},
|
||||
{
|
||||
property: 'error',
|
||||
type: 'object',
|
||||
validator: (error) => error === null || typeof error === 'object',
|
||||
},
|
||||
{
|
||||
property: 'averageGas',
|
||||
type: 'number',
|
||||
},
|
||||
{
|
||||
property: 'maxGas',
|
||||
type: 'number',
|
||||
},
|
||||
{
|
||||
property: 'gasEstimate',
|
||||
type: 'number|undefined',
|
||||
validator: (gasEstimate) => gasEstimate === undefined || gasEstimate > 0,
|
||||
},
|
||||
{
|
||||
property: 'fee',
|
||||
type: 'number',
|
||||
},
|
||||
];
|
||||
|
||||
/**
|
||||
* @param {string} type - Type of an API call, e.g. "tokens"
|
||||
* @param {string} chainId
|
||||
* @returns string
|
||||
*/
|
||||
const getBaseUrlForNewSwapsApi = (type, chainId) => {
|
||||
const useDevApis = process.env.SWAPS_USE_DEV_APIS;
|
||||
const v2ApiBaseUrl = useDevApis
|
||||
? SWAPS_DEV_API_V2_BASE_URL
|
||||
: SWAPS_API_V2_BASE_URL;
|
||||
const gasApiBaseUrl = useDevApis ? GAS_DEV_API_BASE_URL : GAS_API_BASE_URL;
|
||||
const noNetworkSpecificTypes = ['refreshTime']; // These types don't need network info in the URL.
|
||||
if (noNetworkSpecificTypes.includes(type)) {
|
||||
return v2ApiBaseUrl;
|
||||
}
|
||||
const chainIdDecimal = chainId && parseInt(chainId, 16);
|
||||
const gasApiTypes = ['gasPrices'];
|
||||
if (gasApiTypes.includes(type)) {
|
||||
return `${gasApiBaseUrl}/networks/${chainIdDecimal}`; // Gas calculations are in its own repo.
|
||||
}
|
||||
return `${v2ApiBaseUrl}/networks/${chainIdDecimal}`;
|
||||
};
|
||||
|
||||
export const getBaseApi = function (type, chainId = CHAIN_IDS.MAINNET) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
chainId = TEST_CHAIN_IDS.includes(chainId) ? CHAIN_IDS.MAINNET : chainId;
|
||||
const baseUrl = getBaseUrlForNewSwapsApi(type, chainId);
|
||||
const chainIdDecimal = chainId && parseInt(chainId, 16);
|
||||
if (!baseUrl) {
|
||||
throw new Error(`Swaps API calls are disabled for chainId: ${chainId}`);
|
||||
}
|
||||
switch (type) {
|
||||
case 'trade':
|
||||
return `${baseUrl}/trades?`;
|
||||
case 'tokens':
|
||||
return `${baseUrl}/tokens`;
|
||||
case 'token':
|
||||
return `${baseUrl}/token`;
|
||||
case 'topAssets':
|
||||
return `${baseUrl}/topAssets`;
|
||||
case 'aggregatorMetadata':
|
||||
return `${baseUrl}/aggregatorMetadata`;
|
||||
case 'gasPrices':
|
||||
return `${baseUrl}/gasPrices`;
|
||||
case 'network':
|
||||
// Only use v2 for this endpoint.
|
||||
return `${SWAPS_API_V2_BASE_URL}/networks/${chainIdDecimal}`;
|
||||
default:
|
||||
throw new Error('getBaseApi requires an api call type');
|
||||
}
|
||||
};
|
||||
|
||||
export function calcTokenValue(value, decimals) {
|
||||
const multiplier = Math.pow(10, Number(decimals || 0));
|
||||
return new BigNumber(String(value)).times(multiplier);
|
||||
}
|
||||
|
||||
export const shouldEnableDirectWrapping = (
|
||||
chainId,
|
||||
sourceToken,
|
||||
destinationToken,
|
||||
) => {
|
||||
if (!sourceToken || !destinationToken) {
|
||||
return false;
|
||||
}
|
||||
const wrappedToken = SWAPS_WRAPPED_TOKENS_ADDRESSES[chainId];
|
||||
const nativeToken = SWAPS_CHAINID_DEFAULT_TOKEN_MAP[chainId]?.address;
|
||||
const sourceTokenLowerCase = sourceToken.toLowerCase();
|
||||
const destinationTokenLowerCase = destinationToken.toLowerCase();
|
||||
return (
|
||||
(sourceTokenLowerCase === wrappedToken &&
|
||||
destinationTokenLowerCase === nativeToken) ||
|
||||
(sourceTokenLowerCase === nativeToken &&
|
||||
destinationTokenLowerCase === wrappedToken)
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Given and object where all values are strings, returns the same object with all values
|
||||
* now prefixed with '0x'
|
||||
*
|
||||
* @param obj
|
||||
*/
|
||||
export function addHexPrefixToObjectValues(obj) {
|
||||
return Object.keys(obj).reduce((newObj, key) => {
|
||||
return { ...newObj, [key]: addHexPrefix(obj[key]) };
|
||||
}, {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the standard set of information about a transaction, returns a transaction properly formatted for
|
||||
* publishing via JSON RPC and web3
|
||||
*
|
||||
* @param {object} options
|
||||
* @param {boolean} [options.sendToken] - Indicates whether or not the transaciton is a token transaction
|
||||
* @param {string} options.data - A hex string containing the data to include in the transaction
|
||||
* @param {string} options.to - A hex address of the tx recipient address
|
||||
* @param options.amount
|
||||
* @param {string} options.from - A hex address of the tx sender address
|
||||
* @param {string} options.gas - A hex representation of the gas value for the transaction
|
||||
* @param {string} options.gasPrice - A hex representation of the gas price for the transaction
|
||||
* @returns {object} An object ready for submission to the blockchain, with all values appropriately hex prefixed
|
||||
*/
|
||||
export function constructTxParams({
|
||||
sendToken,
|
||||
data,
|
||||
to,
|
||||
amount,
|
||||
from,
|
||||
gas,
|
||||
gasPrice,
|
||||
}) {
|
||||
const txParams = {
|
||||
data,
|
||||
from,
|
||||
value: '0',
|
||||
gas,
|
||||
gasPrice,
|
||||
};
|
||||
|
||||
if (!sendToken) {
|
||||
txParams.value = amount;
|
||||
txParams.to = to;
|
||||
}
|
||||
return addHexPrefixToObjectValues(txParams);
|
||||
}
|
||||
|
||||
export async function fetchTradesInfo(
|
||||
{
|
||||
slippage,
|
||||
sourceToken,
|
||||
sourceDecimals,
|
||||
destinationToken,
|
||||
value,
|
||||
fromAddress,
|
||||
exchangeList,
|
||||
},
|
||||
{ chainId },
|
||||
) {
|
||||
const urlParams = {
|
||||
destinationToken,
|
||||
sourceToken,
|
||||
sourceAmount: calcTokenValue(value, sourceDecimals).toString(10),
|
||||
slippage,
|
||||
timeout: SECOND * 10,
|
||||
walletAddress: fromAddress,
|
||||
};
|
||||
|
||||
if (exchangeList) {
|
||||
urlParams.exchangeList = exchangeList;
|
||||
}
|
||||
if (shouldEnableDirectWrapping(chainId, sourceToken, destinationToken)) {
|
||||
urlParams.enableDirectWrapping = true;
|
||||
}
|
||||
|
||||
const queryString = new URLSearchParams(urlParams).toString();
|
||||
const tradeURL = `${getBaseApi('trade', chainId)}${queryString}`;
|
||||
const tradesResponse = await fetchWithCache(
|
||||
tradeURL,
|
||||
{ method: 'GET', headers: clientIdHeader },
|
||||
{ cacheRefreshTime: 0, timeout: SECOND * 15 },
|
||||
);
|
||||
const newQuotes = tradesResponse.reduce((aggIdTradeMap, quote) => {
|
||||
if (
|
||||
quote.trade &&
|
||||
!quote.error &&
|
||||
validateData(QUOTE_VALIDATORS, quote, tradeURL)
|
||||
) {
|
||||
const constructedTrade = constructTxParams({
|
||||
to: quote.trade.to,
|
||||
from: quote.trade.from,
|
||||
data: quote.trade.data,
|
||||
amount: decimalToHex(quote.trade.value),
|
||||
gas: decimalToHex(quote.maxGas),
|
||||
});
|
||||
|
||||
let { approvalNeeded } = quote;
|
||||
|
||||
if (approvalNeeded) {
|
||||
approvalNeeded = constructTxParams({
|
||||
...approvalNeeded,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
...aggIdTradeMap,
|
||||
[quote.aggregator]: {
|
||||
...quote,
|
||||
slippage,
|
||||
trade: constructedTrade,
|
||||
approvalNeeded,
|
||||
},
|
||||
};
|
||||
}
|
||||
return aggIdTradeMap;
|
||||
}, {});
|
||||
|
||||
return newQuotes;
|
||||
}
|
20
shared/lib/token-util.js
Normal file
20
shared/lib/token-util.js
Normal file
@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Gets the '_value' parameter of the given token transaction data
|
||||
* (i.e function call) per the Human Standard Token ABI, if present.
|
||||
*
|
||||
* @param {object} tokenData - ethers Interface token data.
|
||||
* @returns {string | undefined} A decimal string value.
|
||||
*/
|
||||
/**
|
||||
* Gets either the '_tokenId' parameter or the 'id' param of the passed token transaction data.,
|
||||
* These are the parsed tokenId values returned by `parseStandardTokenTransactionData` as defined
|
||||
* in the ERC721 and ERC1155 ABIs from metamask-eth-abis (https://github.com/MetaMask/metamask-eth-abis/tree/main/src/abis)
|
||||
*
|
||||
* @param {object} tokenData - ethers Interface token data.
|
||||
* @returns {string | undefined} A decimal string value.
|
||||
*/
|
||||
export function getTokenIdParam(tokenData = {}) {
|
||||
return (
|
||||
tokenData?.args?._tokenId?.toString() ?? tokenData?.args?.id?.toString()
|
||||
);
|
||||
}
|
172
shared/lib/transactions-controller-utils.js
Normal file
172
shared/lib/transactions-controller-utils.js
Normal file
@ -0,0 +1,172 @@
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { TRANSACTION_ENVELOPE_TYPES } from '../constants/transaction';
|
||||
import {
|
||||
conversionUtil,
|
||||
multiplyCurrencies,
|
||||
subtractCurrencies,
|
||||
} from '../modules/conversion.utils';
|
||||
import { isSwapsDefaultTokenSymbol } from '../modules/swaps.utils';
|
||||
|
||||
const TOKEN_TRANSFER_LOG_TOPIC_HASH =
|
||||
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef';
|
||||
|
||||
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,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a number and specified precision, returns that number in base 10 with a maximum of precision
|
||||
* significant digits, but without any trailing zeros after the decimal point To be used when wishing
|
||||
* to display only as much digits to the user as necessary
|
||||
*
|
||||
* @param {string | number | BigNumber} n - The number to format
|
||||
* @param {number} precision - The maximum number of significant digits in the return value
|
||||
* @returns {string} The number in decimal form, with <= precision significant digits and no decimal trailing zeros
|
||||
*/
|
||||
export function toPrecisionWithoutTrailingZeros(n, precision) {
|
||||
return new BigNumber(n)
|
||||
.toPrecision(precision)
|
||||
.replace(/(\.[0-9]*[1-9])0*|(\.0*)/u, '$1');
|
||||
}
|
||||
|
||||
export function calcTokenAmount(value, decimals) {
|
||||
const multiplier = Math.pow(10, Number(decimals || 0));
|
||||
return new BigNumber(String(value)).div(multiplier);
|
||||
}
|
||||
|
||||
export function getSwapsTokensReceivedFromTxMeta(
|
||||
tokenSymbol,
|
||||
txMeta,
|
||||
tokenAddress,
|
||||
accountAddress,
|
||||
tokenDecimals,
|
||||
approvalTxMeta,
|
||||
chainId,
|
||||
) {
|
||||
const txReceipt = txMeta?.txReceipt;
|
||||
const networkAndAccountSupports1559 =
|
||||
txMeta?.txReceipt?.type === TRANSACTION_ENVELOPE_TYPES.FEE_MARKET;
|
||||
if (isSwapsDefaultTokenSymbol(tokenSymbol, chainId)) {
|
||||
if (
|
||||
!txReceipt ||
|
||||
!txMeta ||
|
||||
!txMeta.postTxBalance ||
|
||||
!txMeta.preTxBalance
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (txMeta.swapMetaData && txMeta.preTxBalance === txMeta.postTxBalance) {
|
||||
// If preTxBalance and postTxBalance are equal, postTxBalance hasn't been updated on time
|
||||
// because of the RPC provider delay, so we return an estimated receiving amount instead.
|
||||
return txMeta.swapMetaData.token_to_amount;
|
||||
}
|
||||
|
||||
let approvalTxGasCost = '0x0';
|
||||
if (approvalTxMeta && approvalTxMeta.txReceipt) {
|
||||
approvalTxGasCost = calcGasTotal(
|
||||
approvalTxMeta.txReceipt.gasUsed,
|
||||
networkAndAccountSupports1559
|
||||
? approvalTxMeta.txReceipt.effectiveGasPrice // Base fee + priority fee.
|
||||
: approvalTxMeta.txParams.gasPrice,
|
||||
);
|
||||
}
|
||||
|
||||
const gasCost = calcGasTotal(
|
||||
txReceipt.gasUsed,
|
||||
networkAndAccountSupports1559
|
||||
? txReceipt.effectiveGasPrice
|
||||
: txMeta.txParams.gasPrice,
|
||||
);
|
||||
const totalGasCost = new BigNumber(gasCost, 16)
|
||||
.plus(approvalTxGasCost, 16)
|
||||
.toString(16);
|
||||
|
||||
const preTxBalanceLessGasCost = subtractCurrencies(
|
||||
txMeta.preTxBalance,
|
||||
totalGasCost,
|
||||
{
|
||||
aBase: 16,
|
||||
bBase: 16,
|
||||
toNumericBase: 'hex',
|
||||
},
|
||||
);
|
||||
|
||||
const ethReceived = subtractCurrencies(
|
||||
txMeta.postTxBalance,
|
||||
preTxBalanceLessGasCost,
|
||||
{
|
||||
aBase: 16,
|
||||
bBase: 16,
|
||||
fromDenomination: 'WEI',
|
||||
toDenomination: 'ETH',
|
||||
toNumericBase: 'dec',
|
||||
numberOfDecimals: 6,
|
||||
},
|
||||
);
|
||||
return ethReceived;
|
||||
}
|
||||
const txReceiptLogs = txReceipt?.logs;
|
||||
if (txReceiptLogs && txReceipt?.status !== '0x0') {
|
||||
const tokenTransferLog = txReceiptLogs.find((txReceiptLog) => {
|
||||
const isTokenTransfer =
|
||||
txReceiptLog.topics &&
|
||||
txReceiptLog.topics[0] === TOKEN_TRANSFER_LOG_TOPIC_HASH;
|
||||
const isTransferFromGivenToken = txReceiptLog.address === tokenAddress;
|
||||
const isTransferFromGivenAddress =
|
||||
txReceiptLog.topics &&
|
||||
txReceiptLog.topics[2] &&
|
||||
txReceiptLog.topics[2].match(accountAddress.slice(2));
|
||||
return (
|
||||
isTokenTransfer &&
|
||||
isTransferFromGivenToken &&
|
||||
isTransferFromGivenAddress
|
||||
);
|
||||
});
|
||||
return tokenTransferLog
|
||||
? toPrecisionWithoutTrailingZeros(
|
||||
calcTokenAmount(tokenTransferLog.data, tokenDecimals).toString(10),
|
||||
6,
|
||||
)
|
||||
: '';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export const TRANSACTION_ENVELOPE_TYPE_NAMES = {
|
||||
FEE_MARKET: 'fee-market',
|
||||
LEGACY: 'legacy',
|
||||
};
|
||||
|
||||
export function hexWEIToDecGWEI(decGWEI) {
|
||||
return conversionUtil(decGWEI, {
|
||||
fromNumericBase: 'hex',
|
||||
toNumericBase: 'dec',
|
||||
fromDenomination: 'WEI',
|
||||
toDenomination: 'GWEI',
|
||||
});
|
||||
}
|
||||
|
||||
export function decimalToHex(decimal) {
|
||||
return conversionUtil(decimal, {
|
||||
fromNumericBase: 'dec',
|
||||
toNumericBase: 'hex',
|
||||
});
|
||||
}
|
||||
|
||||
export function hexWEIToDecETH(hexWEI) {
|
||||
return conversionUtil(hexWEI, {
|
||||
fromNumericBase: 'hex',
|
||||
toNumericBase: 'dec',
|
||||
fromDenomination: 'WEI',
|
||||
toDenomination: 'ETH',
|
||||
});
|
||||
}
|
7
shared/lib/ui-utils.js
Normal file
7
shared/lib/ui-utils.js
Normal file
@ -0,0 +1,7 @@
|
||||
let _supportLink = 'https://support.metamask.io';
|
||||
|
||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||
_supportLink = 'https://metamask-flask.zendesk.com/hc';
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
export const SUPPORT_LINK = _supportLink;
|
@ -16,7 +16,6 @@ import SiteIcon from '../../ui/site-icon';
|
||||
import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display';
|
||||
import {
|
||||
PRIMARY,
|
||||
SUPPORT_LINK,
|
||||
///: BEGIN:ONLY_INCLUDE_IN(beta,flask)
|
||||
SUPPORT_REQUEST_LINK,
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
@ -41,6 +40,7 @@ import IconImport from '../../ui/icon/icon-import';
|
||||
|
||||
import Button from '../../ui/button';
|
||||
import SearchIcon from '../../ui/icon/search-icon';
|
||||
import { SUPPORT_LINK } from '../../../../shared/lib/ui-utils';
|
||||
import KeyRingLabel from './keyring-label';
|
||||
|
||||
export function AccountMenuItem(props) {
|
||||
|
22
ui/components/app/asset-list/asset-list.test.js
Normal file
22
ui/components/app/asset-list/asset-list.test.js
Normal file
@ -0,0 +1,22 @@
|
||||
import React from 'react';
|
||||
import { screen } from '@testing-library/react';
|
||||
import { renderWithProvider } from '../../../../test/jest';
|
||||
import configureStore from '../../../store/store';
|
||||
import mockState from '../../../../test/data/mock-state.json';
|
||||
import AssetList from './asset-list';
|
||||
|
||||
const render = () => {
|
||||
const store = configureStore({
|
||||
metamask: {
|
||||
...mockState.metamask,
|
||||
},
|
||||
});
|
||||
return renderWithProvider(<AssetList />, store);
|
||||
};
|
||||
|
||||
describe('AssetList', () => {
|
||||
it('renders AssetList component and shows Refresh List text', () => {
|
||||
render();
|
||||
expect(screen.getByText('Refresh list')).toBeInTheDocument();
|
||||
});
|
||||
});
|
@ -11,12 +11,9 @@ import mockEstimates from '../../../../test/data/mock-estimates.json';
|
||||
import mockState from '../../../../test/data/mock-state.json';
|
||||
import { GasFeeContextProvider } from '../../../contexts/gasFee';
|
||||
import configureStore from '../../../store/store';
|
||||
import {
|
||||
hexWEIToDecETH,
|
||||
decGWEIToHexWEI,
|
||||
} from '../../../helpers/utils/conversions.util';
|
||||
import { decGWEIToHexWEI } from '../../../helpers/utils/conversions.util';
|
||||
import InfoTooltip from '../../ui/info-tooltip';
|
||||
|
||||
import { hexWEIToDecETH } from '../../../../shared/lib/transactions-controller-utils';
|
||||
import CancelSpeedupPopover from './cancel-speedup-popover';
|
||||
|
||||
const MAXFEEPERGAS_ABOVE_MOCK_MEDIUM_HEX = '0x174876e800';
|
||||
|
31
ui/components/app/create-new-vault/create-new-vault.test.js
Normal file
31
ui/components/app/create-new-vault/create-new-vault.test.js
Normal file
@ -0,0 +1,31 @@
|
||||
import React from 'react';
|
||||
import { screen } from '@testing-library/react';
|
||||
import { renderWithProvider } from '../../../../test/jest';
|
||||
import configureStore from '../../../store/store';
|
||||
import mockState from '../../../../test/data/mock-state.json';
|
||||
import CreateNewVault from './create-new-vault';
|
||||
|
||||
const store = configureStore({
|
||||
metamask: {
|
||||
...mockState.metamask,
|
||||
},
|
||||
});
|
||||
|
||||
describe('CreateNewVault', () => {
|
||||
it('renders CreateNewVault component and shows Secret Recovery Phrase text', () => {
|
||||
renderWithProvider(<CreateNewVault submitText="Import" />, store);
|
||||
expect(screen.getByText('Secret Recovery Phrase')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders CreateNewVault component and shows You can paste... text', () => {
|
||||
renderWithProvider(
|
||||
<CreateNewVault submitText="Import" includeTerms />,
|
||||
store,
|
||||
);
|
||||
expect(
|
||||
screen.getByText(
|
||||
'You can paste your entire secret recovery phrase into any field',
|
||||
),
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
@ -6,17 +6,17 @@ import {
|
||||
PRIORITY_LEVELS,
|
||||
} from '../../../../../shared/constants/gas';
|
||||
import { getMaximumGasTotalInHexWei } from '../../../../../shared/modules/gas.utils';
|
||||
import {
|
||||
decGWEIToHexWEI,
|
||||
decimalToHex,
|
||||
hexWEIToDecGWEI,
|
||||
} from '../../../../helpers/utils/conversions.util';
|
||||
import { decGWEIToHexWEI } from '../../../../helpers/utils/conversions.util';
|
||||
import {
|
||||
addTenPercentAndRound,
|
||||
gasEstimateGreaterThanGasUsedPlusTenPercent,
|
||||
} from '../../../../helpers/utils/gas';
|
||||
import { getAdvancedGasFeeValues } from '../../../../selectors';
|
||||
import { useGasFeeContext } from '../../../../contexts/gasFee';
|
||||
import {
|
||||
decimalToHex,
|
||||
hexWEIToDecGWEI,
|
||||
} from '../../../../../shared/lib/transactions-controller-utils';
|
||||
import { useCustomTimeEstimate } from './useCustomTimeEstimate';
|
||||
|
||||
export const useGasItemFeeDetails = (priorityLevel) => {
|
||||
|
@ -11,11 +11,7 @@ import {
|
||||
CUSTOM_GAS_ESTIMATE,
|
||||
} from '../../../../shared/constants/gas';
|
||||
|
||||
import {
|
||||
decGWEIToHexWEI,
|
||||
decimalToHex,
|
||||
hexToDecimal,
|
||||
} from '../../../helpers/utils/conversions.util';
|
||||
import { decGWEIToHexWEI } from '../../../helpers/utils/conversions.util';
|
||||
|
||||
import Popover from '../../ui/popover';
|
||||
import Button from '../../ui/button';
|
||||
@ -37,6 +33,8 @@ import LoadingHeartBeat from '../../ui/loading-heartbeat';
|
||||
import { checkNetworkAndAccountSupports1559 } from '../../../selectors';
|
||||
import { useIncrementedGasFees } from '../../../hooks/useIncrementedGasFees';
|
||||
import { isLegacyTransaction } from '../../../helpers/utils/transactions.util';
|
||||
import { hexToDecimal } from '../../../../shared/lib/metamask-controller-utils';
|
||||
import { decimalToHex } from '../../../../shared/lib/transactions-controller-utils';
|
||||
|
||||
export default function EditGasPopover({
|
||||
popoverTitle = '',
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { connect } from 'react-redux';
|
||||
import {
|
||||
decGWEIToHexWEI,
|
||||
decimalToHex,
|
||||
hexWEIToDecGWEI,
|
||||
} from '../../../../helpers/utils/conversions.util';
|
||||
import { decGWEIToHexWEI } from '../../../../helpers/utils/conversions.util';
|
||||
import { getNetworkSupportsSettingGasFees } from '../../../../selectors/selectors';
|
||||
import { MIN_GAS_LIMIT_DEC } from '../../../../pages/send/send.constants';
|
||||
import {
|
||||
decimalToHex,
|
||||
hexWEIToDecGWEI,
|
||||
} from '../../../../../shared/lib/transactions-controller-utils';
|
||||
import AdvancedGasInputs from './advanced-gas-inputs.component';
|
||||
|
||||
function convertGasPriceForInputs(gasPriceInHexWEI) {
|
||||
|
@ -43,15 +43,11 @@ import {
|
||||
import {
|
||||
addHexes,
|
||||
subtractHexWEIsToDec,
|
||||
hexWEIToDecGWEI,
|
||||
getValueFromWeiHex,
|
||||
sumHexWEIsToRenderableFiat,
|
||||
} from '../../../../helpers/utils/conversions.util';
|
||||
import { formatETHFee } from '../../../../helpers/utils/formatters';
|
||||
import {
|
||||
calcGasTotal,
|
||||
isBalanceSufficient,
|
||||
} from '../../../../pages/send/send.utils';
|
||||
import { isBalanceSufficient } from '../../../../pages/send/send.utils';
|
||||
import { MIN_GAS_LIMIT_DEC } from '../../../../pages/send/send.constants';
|
||||
import {
|
||||
ASSET_TYPES,
|
||||
@ -59,6 +55,10 @@ import {
|
||||
} from '../../../../../shared/constants/transaction';
|
||||
import { GAS_LIMITS } from '../../../../../shared/constants/gas';
|
||||
import { updateGasFees } from '../../../../ducks/metamask/metamask';
|
||||
import {
|
||||
calcGasTotal,
|
||||
hexWEIToDecGWEI,
|
||||
} from '../../../../../shared/lib/transactions-controller-utils';
|
||||
import GasModalPageContainer from './gas-modal-page-container.component';
|
||||
|
||||
const mapStateToProps = (state, ownProps) => {
|
||||
|
@ -6,7 +6,7 @@ import BigNumber from 'bignumber.js';
|
||||
import Modal from '../../modal';
|
||||
import Identicon from '../../../ui/identicon';
|
||||
import TextField from '../../../ui/text-field';
|
||||
import { calcTokenAmount } from '../../../../helpers/utils/token-util';
|
||||
import { calcTokenAmount } from '../../../../../shared/lib/transactions-controller-utils';
|
||||
|
||||
const MAX_UNSIGNED_256_INT = new BigNumber(2).pow(256).minus(1).toString(10);
|
||||
|
||||
|
@ -6,11 +6,11 @@ import { useSelector } from 'react-redux';
|
||||
import * as Codec from '@truffle/codec';
|
||||
import Spinner from '../../ui/spinner';
|
||||
import ErrorMessage from '../../ui/error-message';
|
||||
import fetchWithCache from '../../../helpers/utils/fetch-with-cache';
|
||||
import fetchWithCache from '../../../../shared/lib/fetch-with-cache';
|
||||
import { getSelectedAccount, getCurrentChainId } from '../../../selectors';
|
||||
import { hexToDecimal } from '../../../helpers/utils/conversions.util';
|
||||
import { I18nContext } from '../../../contexts/i18n';
|
||||
import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils';
|
||||
import { hexToDecimal } from '../../../../shared/lib/metamask-controller-utils';
|
||||
import { transformTxDecoding } from './transaction-decoding.util';
|
||||
import {
|
||||
FETCH_PROJECT_INFO_URI,
|
||||
|
22
ui/components/app/transaction-list/transaction-list.test.js
Normal file
22
ui/components/app/transaction-list/transaction-list.test.js
Normal file
@ -0,0 +1,22 @@
|
||||
import React from 'react';
|
||||
import { screen } from '@testing-library/react';
|
||||
import { renderWithProvider } from '../../../../test/jest';
|
||||
import configureStore from '../../../store/store';
|
||||
import mockState from '../../../../test/data/mock-state.json';
|
||||
import TransactionList from './transaction-list.component';
|
||||
|
||||
const render = () => {
|
||||
const store = configureStore({
|
||||
metamask: {
|
||||
...mockState.metamask,
|
||||
},
|
||||
});
|
||||
return renderWithProvider(<TransactionList />, store);
|
||||
};
|
||||
|
||||
describe('TransactionList', () => {
|
||||
it('renders TransactionList component and shows You have no transactions text', () => {
|
||||
render();
|
||||
expect(screen.getByText('You have no transactions')).toBeInTheDocument();
|
||||
});
|
||||
});
|
121
ui/components/app/whats-new-popup/whats-new-popup.test.js
Normal file
121
ui/components/app/whats-new-popup/whats-new-popup.test.js
Normal file
@ -0,0 +1,121 @@
|
||||
import React from 'react';
|
||||
import { screen } from '@testing-library/react';
|
||||
import { renderWithProvider } from '../../../../test/jest';
|
||||
import configureStore from '../../../store/store';
|
||||
import mockState from '../../../../test/data/mock-state.json';
|
||||
import WhatsNewPopup from './whats-new-popup';
|
||||
|
||||
const render = () => {
|
||||
const store = configureStore({
|
||||
metamask: {
|
||||
...mockState.metamask,
|
||||
announcements: {
|
||||
1: {
|
||||
date: '2021-03-17',
|
||||
id: 1,
|
||||
image: {
|
||||
height: '230px',
|
||||
placeImageBelowDescription: true,
|
||||
src: 'images/mobile-link-qr.svg',
|
||||
width: '230px',
|
||||
},
|
||||
isShown: false,
|
||||
},
|
||||
3: {
|
||||
date: '2021-03-08',
|
||||
id: 3,
|
||||
isShown: false,
|
||||
},
|
||||
4: {
|
||||
date: '2021-05-11',
|
||||
id: 4,
|
||||
image: {
|
||||
src: 'images/source-logos-bsc.svg',
|
||||
width: '100%',
|
||||
},
|
||||
isShown: false,
|
||||
},
|
||||
5: {
|
||||
date: '2021-06-09',
|
||||
id: 5,
|
||||
isShown: false,
|
||||
},
|
||||
6: {
|
||||
date: '2021-05-26',
|
||||
id: 6,
|
||||
isShown: false,
|
||||
},
|
||||
7: {
|
||||
date: '2021-09-17',
|
||||
id: 7,
|
||||
isShown: false,
|
||||
},
|
||||
8: {
|
||||
date: '2021-11-01',
|
||||
id: 8,
|
||||
isShown: false,
|
||||
},
|
||||
9: {
|
||||
date: '2021-12-07',
|
||||
id: 9,
|
||||
image: {
|
||||
src: 'images/txinsights.png',
|
||||
width: '80%',
|
||||
},
|
||||
isShown: false,
|
||||
},
|
||||
10: {
|
||||
date: '2022-04-18',
|
||||
id: 10,
|
||||
image: {
|
||||
src: 'images/token-detection.svg',
|
||||
width: '100%',
|
||||
},
|
||||
isShown: true,
|
||||
},
|
||||
11: {
|
||||
date: '2022-04-18',
|
||||
id: 11,
|
||||
isShown: true,
|
||||
},
|
||||
12: {
|
||||
date: '2022-05-18',
|
||||
id: 12,
|
||||
image: {
|
||||
src: 'images/darkmode-banner.png',
|
||||
width: '100%',
|
||||
},
|
||||
isShown: false,
|
||||
},
|
||||
13: {
|
||||
date: '2022-07-12',
|
||||
id: 13,
|
||||
isShown: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
return renderWithProvider(<WhatsNewPopup />, store);
|
||||
};
|
||||
|
||||
describe('WhatsNewPopup', () => {
|
||||
beforeEach(() => {
|
||||
const mockIntersectionObserver = jest.fn();
|
||||
mockIntersectionObserver.mockReturnValue({
|
||||
observe: () => null,
|
||||
unobserve: () => null,
|
||||
disconnect: () => null,
|
||||
});
|
||||
window.IntersectionObserver = mockIntersectionObserver;
|
||||
});
|
||||
|
||||
it("renders WhatsNewPopup component and shows What's new text", () => {
|
||||
render();
|
||||
expect(screen.getByText("What's new")).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders WhatsNewPopup component and shows close button', () => {
|
||||
render();
|
||||
expect(screen.getByTestId('popover-close')).toBeInTheDocument();
|
||||
});
|
||||
});
|
60
ui/components/ui/account-list/account-list.test.js
Normal file
60
ui/components/ui/account-list/account-list.test.js
Normal file
@ -0,0 +1,60 @@
|
||||
import React from 'react';
|
||||
import { screen } from '@testing-library/react';
|
||||
import { renderWithProvider } from '../../../../test/jest';
|
||||
import configureStore from '../../../store/store';
|
||||
import mockState from '../../../../test/data/mock-state.json';
|
||||
import AccountList from './account-list';
|
||||
|
||||
const render = () => {
|
||||
const store = configureStore({
|
||||
metamask: {
|
||||
...mockState.metamask,
|
||||
},
|
||||
});
|
||||
|
||||
const args = {
|
||||
accounts: [
|
||||
{
|
||||
address: '0x64a845a5b02460acf8a3d84503b0d68d028b4bb4',
|
||||
addressLabel: 'Account 1',
|
||||
lastConnectedDate: 'Feb-22-2022',
|
||||
balance: '8.7a73149c048545a3fe58',
|
||||
has: () => {
|
||||
/** nothing to do */
|
||||
},
|
||||
},
|
||||
],
|
||||
selectedAccounts: {
|
||||
address: '0x64a845a5b02460acf8a3d84503b0d68d028b4bb4',
|
||||
addressLabel: 'Account 2',
|
||||
lastConnectedDate: 'Feb-22-2022',
|
||||
balance: '8.7a73149c048545a3fe58',
|
||||
has: () => {
|
||||
/** nothing to do */
|
||||
},
|
||||
},
|
||||
addressLastConnectedMap: {
|
||||
'0x64a845a5b02460acf8a3d84503b0d68d028b4bb4': 'Feb-22-2022',
|
||||
},
|
||||
allAreSelected: () => true,
|
||||
nativeCurrency: 'USD',
|
||||
};
|
||||
return renderWithProvider(<AccountList {...args} />, store);
|
||||
};
|
||||
|
||||
describe('AccountList', () => {
|
||||
it('renders AccountList component and shows New account text', () => {
|
||||
render();
|
||||
expect(screen.getByText('New account')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders AccountList component and shows Account 1 text', () => {
|
||||
render();
|
||||
expect(screen.getByText('Account 1')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders AccountList component and shows ETH text', () => {
|
||||
render();
|
||||
expect(screen.getByText('ETH')).toBeInTheDocument();
|
||||
});
|
||||
});
|
@ -1,6 +1,6 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { hexToDecimal } from '../../../helpers/utils/conversions.util';
|
||||
import { hexToDecimal } from '../../../../shared/lib/metamask-controller-utils';
|
||||
|
||||
export default class HexToDecimal extends PureComponent {
|
||||
static propTypes = {
|
||||
|
@ -16,7 +16,7 @@ import {
|
||||
} from '../../../helpers/constants/design-system';
|
||||
import Typography from '../typography';
|
||||
import { TOKEN_API_METASWAP_CODEFI_URL } from '../../../../shared/constants/tokens';
|
||||
import fetchWithCache from '../../../helpers/utils/fetch-with-cache';
|
||||
import fetchWithCache from '../../../../shared/lib/fetch-with-cache';
|
||||
import {
|
||||
getNativeCurrencyImage,
|
||||
getProvider,
|
||||
|
@ -5,7 +5,7 @@ import { renderWithProvider } from '../../../../test/lib/render-helpers';
|
||||
import NewNetworkInfo from './new-network-info';
|
||||
|
||||
const fetchWithCache =
|
||||
require('../../../helpers/utils/fetch-with-cache').default;
|
||||
require('../../../../shared/lib/fetch-with-cache').default;
|
||||
|
||||
const state = {
|
||||
metamask: {
|
||||
|
35
ui/components/ui/nickname-popover/nickname-popover.test.js
Normal file
35
ui/components/ui/nickname-popover/nickname-popover.test.js
Normal file
@ -0,0 +1,35 @@
|
||||
import React from 'react';
|
||||
import { screen } from '@testing-library/react';
|
||||
import { renderWithProvider } from '../../../../test/jest';
|
||||
import configureStore from '../../../store/store';
|
||||
import mockState from '../../../../test/data/mock-state.json';
|
||||
import NicknamePopover from './nickname-popover.component';
|
||||
|
||||
const store = configureStore({
|
||||
metamask: {
|
||||
...mockState.metamask,
|
||||
},
|
||||
});
|
||||
|
||||
describe('NicknamePopover', () => {
|
||||
it('renders NicknamePopover component and shows Add a nickname text', () => {
|
||||
renderWithProvider(
|
||||
<NicknamePopover address="0x5e6DaAD1BE117e26590F9eEcD509336ABFBe5966" />,
|
||||
store,
|
||||
);
|
||||
|
||||
expect(screen.getByText('Add a nickname')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders NicknamePopover component and shows Edit nickname text', () => {
|
||||
renderWithProvider(
|
||||
<NicknamePopover
|
||||
address="0x5e6DaAD1BE117e26590F9eEcD509336ABFBe5966"
|
||||
nickname="John Doe"
|
||||
/>,
|
||||
store,
|
||||
);
|
||||
|
||||
expect(screen.getByText('Edit nickname')).toBeInTheDocument();
|
||||
});
|
||||
});
|
@ -0,0 +1,29 @@
|
||||
import React from 'react';
|
||||
import { screen } from '@testing-library/react';
|
||||
import { renderWithProvider } from '../../../../test/jest';
|
||||
import configureStore from '../../../store/store';
|
||||
import mockState from '../../../../test/data/mock-state.json';
|
||||
import UpdateNicknamePopover from './update-nickname-popover';
|
||||
|
||||
const render = () => {
|
||||
const store = configureStore({
|
||||
metamask: {
|
||||
...mockState.metamask,
|
||||
},
|
||||
});
|
||||
return renderWithProvider(
|
||||
<UpdateNicknamePopover
|
||||
nickname="user_nickname"
|
||||
memo="This is a memo"
|
||||
address="0xdeDbcA0156308960E3bBa2f5a273E72179940788"
|
||||
/>,
|
||||
store,
|
||||
);
|
||||
};
|
||||
|
||||
describe('UpdateNicknamePopover', () => {
|
||||
it('renders UpdateNicknamePopover component and shows This is a memo text', () => {
|
||||
render();
|
||||
expect(screen.getByText('This is a memo')).toBeInTheDocument();
|
||||
});
|
||||
});
|
@ -1,6 +1,7 @@
|
||||
import { addHexPrefix } from 'ethereumjs-util';
|
||||
import abi from 'human-standard-token-abi';
|
||||
import { GAS_LIMITS, MIN_GAS_LIMIT_HEX } from '../../../shared/constants/gas';
|
||||
import { calcTokenAmount } from '../../../shared/lib/transactions-controller-utils';
|
||||
import { CHAIN_ID_TO_GAS_LIMIT_BUFFER_MAP } from '../../../shared/constants/network';
|
||||
import {
|
||||
ASSET_TYPES,
|
||||
@ -12,7 +13,6 @@ import {
|
||||
multiplyCurrencies,
|
||||
} from '../../../shared/modules/conversion.utils';
|
||||
import { ETH, GWEI } from '../../helpers/constants/common';
|
||||
import { calcTokenAmount } from '../../helpers/utils/token-util';
|
||||
import {
|
||||
addGasBuffer,
|
||||
generateERC20TransferData,
|
||||
|
@ -22,7 +22,6 @@ import {
|
||||
} from '../../pages/send/send.constants';
|
||||
|
||||
import {
|
||||
calcGasTotal,
|
||||
isBalanceSufficient,
|
||||
isTokenBalanceSufficient,
|
||||
} from '../../pages/send/send.utils';
|
||||
@ -67,9 +66,7 @@ import {
|
||||
GAS_FEE_ESTIMATES_UPDATED,
|
||||
} from '../../store/actionConstants';
|
||||
import {
|
||||
calcTokenAmount,
|
||||
getTokenAddressParam,
|
||||
getTokenValueParam,
|
||||
getTokenMetadata,
|
||||
getTokenIdParam,
|
||||
} from '../../helpers/utils/token-util';
|
||||
@ -108,6 +105,11 @@ import { INVALID_ASSET_TYPE } from '../../helpers/constants/error-keys';
|
||||
import { isEqualCaseInsensitive } from '../../../shared/modules/string-utils';
|
||||
import { getValueFromWeiHex } from '../../helpers/utils/confirm-tx.util';
|
||||
import { parseStandardTokenTransactionData } from '../../../shared/modules/transaction.utils';
|
||||
import { getTokenValueParam } from '../../../shared/lib/metamask-controller-utils';
|
||||
import {
|
||||
calcGasTotal,
|
||||
calcTokenAmount,
|
||||
} from '../../../shared/lib/transactions-controller-utils';
|
||||
import {
|
||||
estimateGasLimitForSend,
|
||||
generateTransactionParams,
|
||||
|
@ -51,16 +51,12 @@ import {
|
||||
parseSmartTransactionsError,
|
||||
stxErrorTypes,
|
||||
} from '../../pages/swaps/swaps.util';
|
||||
import { calcGasTotal } from '../../pages/send/send.utils';
|
||||
import {
|
||||
decimalToHex,
|
||||
getValueFromWeiHex,
|
||||
decGWEIToHexWEI,
|
||||
hexWEIToDecGWEI,
|
||||
addHexes,
|
||||
} from '../../helpers/utils/conversions.util';
|
||||
import { conversionLessThan } from '../../../shared/modules/conversion.utils';
|
||||
import { calcTokenAmount } from '../../helpers/utils/token-util';
|
||||
import {
|
||||
getSelectedAccount,
|
||||
getTokenExchangeRates,
|
||||
@ -89,6 +85,12 @@ import {
|
||||
} from '../../../shared/constants/transaction';
|
||||
import { getGasFeeEstimates } from '../metamask/metamask';
|
||||
import { ORIGIN_METAMASK } from '../../../shared/constants/app';
|
||||
import {
|
||||
calcGasTotal,
|
||||
calcTokenAmount,
|
||||
decimalToHex,
|
||||
hexWEIToDecGWEI,
|
||||
} from '../../../shared/lib/transactions-controller-utils';
|
||||
|
||||
const GAS_PRICES_LOADING_STATES = {
|
||||
INITIAL: 'INITIAL',
|
||||
|
@ -2,8 +2,8 @@ import nock from 'nock';
|
||||
|
||||
import { MOCKS, createSwapsMockStore } from '../../../test/jest';
|
||||
import { setSwapsLiveness, setSwapsFeatureFlags } from '../../store/actions';
|
||||
import { setStorageItem } from '../../helpers/utils/storage-helpers';
|
||||
import { CHAIN_IDS } from '../../../shared/constants/network';
|
||||
import { setStorageItem } from '../../../shared/lib/storage-helpers';
|
||||
import * as swaps from './swaps';
|
||||
|
||||
jest.mock('../../store/actions.js', () => ({
|
||||
|
@ -12,17 +12,14 @@ export const GAS_ESTIMATE_TYPES = {
|
||||
FASTEST: 'FASTEST',
|
||||
};
|
||||
|
||||
let _supportLink = 'https://support.metamask.io';
|
||||
let _supportRequestLink = 'https://metamask.zendesk.com/hc/en-us';
|
||||
const _contractAddressLink =
|
||||
'https://metamask.zendesk.com/hc/en-us/articles/360020028092-What-is-the-known-contract-address-warning-';
|
||||
|
||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||
_supportLink = 'https://metamask-flask.zendesk.com/hc';
|
||||
_supportRequestLink =
|
||||
'https://metamask-flask.zendesk.com/hc/en-us/requests/new';
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
export const SUPPORT_LINK = _supportLink;
|
||||
export const SUPPORT_REQUEST_LINK = _supportRequestLink;
|
||||
export const CONTRACT_ADDRESS_LINK = _contractAddressLink;
|
||||
|
@ -1 +0,0 @@
|
||||
export const TEN_SECONDS_IN_MILLISECONDS = 10_000;
|
@ -1,7 +1,6 @@
|
||||
export const INSUFFICIENT_FUNDS_ERROR_KEY = 'insufficientFunds';
|
||||
export const GAS_LIMIT_TOO_LOW_ERROR_KEY = 'gasLimitTooLow';
|
||||
export const TRANSACTION_ERROR_KEY = 'transactionError';
|
||||
export const TRANSACTION_NO_CONTRACT_ERROR_KEY = 'transactionErrorNoContract';
|
||||
export const ETH_GAS_PRICE_FETCH_WARNING_KEY = 'ethGasPriceFetchWarning';
|
||||
export const GAS_PRICE_FETCH_FAILURE_ERROR_KEY = 'gasPriceFetchFailed';
|
||||
export const GAS_PRICE_EXCESSIVE_ERROR_KEY = 'gasPriceExcessive';
|
||||
|
@ -21,8 +21,3 @@ export const TOKEN_CATEGORY_HASH = {
|
||||
[TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER]: true,
|
||||
[TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER_FROM]: true,
|
||||
};
|
||||
|
||||
export const TRANSACTION_ENVELOPE_TYPE_NAMES = {
|
||||
FEE_MARKET: 'fee-market',
|
||||
LEGACY: 'legacy',
|
||||
};
|
||||
|
@ -11,20 +11,6 @@ export function bnToHex(inputBn) {
|
||||
return addHexPrefix(inputBn.toString(16));
|
||||
}
|
||||
|
||||
export function hexToDecimal(hexValue) {
|
||||
return conversionUtil(hexValue, {
|
||||
fromNumericBase: 'hex',
|
||||
toNumericBase: 'dec',
|
||||
});
|
||||
}
|
||||
|
||||
export function decimalToHex(decimal) {
|
||||
return conversionUtil(decimal, {
|
||||
fromNumericBase: 'dec',
|
||||
toNumericBase: 'hex',
|
||||
});
|
||||
}
|
||||
|
||||
export function getEthConversionFromWeiHex({
|
||||
value,
|
||||
fromCurrency = ETH,
|
||||
@ -135,15 +121,6 @@ export function decGWEIToHexWEI(decGWEI) {
|
||||
});
|
||||
}
|
||||
|
||||
export function hexWEIToDecGWEI(decGWEI) {
|
||||
return conversionUtil(decGWEI, {
|
||||
fromNumericBase: 'hex',
|
||||
toNumericBase: 'dec',
|
||||
fromDenomination: 'WEI',
|
||||
toDenomination: 'GWEI',
|
||||
});
|
||||
}
|
||||
|
||||
export function decETHToDecWEI(decEth) {
|
||||
return conversionUtil(decEth, {
|
||||
fromNumericBase: 'dec',
|
||||
|
@ -6,12 +6,12 @@ import {
|
||||
EDIT_GAS_MODES,
|
||||
} from '../../../shared/constants/gas';
|
||||
import { multiplyCurrencies } from '../../../shared/modules/conversion.utils';
|
||||
import { hexWEIToDecGWEI } from '../../../shared/lib/transactions-controller-utils';
|
||||
import {
|
||||
bnGreaterThan,
|
||||
isNullish,
|
||||
roundToDecimalPlacesRemovingExtraZeroes,
|
||||
} from './util';
|
||||
import { hexWEIToDecGWEI } from './conversions.util';
|
||||
|
||||
export const gasEstimateGreaterThanGasUsedPlusTenPercent = (
|
||||
gasUsed,
|
||||
|
@ -2,7 +2,6 @@
|
||||
import React from 'react';
|
||||
import log from 'loglevel';
|
||||
import * as Sentry from '@sentry/browser';
|
||||
|
||||
import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout';
|
||||
|
||||
const fetchWithTimeout = getFetchWithTimeout();
|
||||
|
@ -1,5 +1,4 @@
|
||||
import log from 'loglevel';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import {
|
||||
conversionUtil,
|
||||
multiplyCurrencies,
|
||||
@ -8,6 +7,8 @@ import { getTokenStandardAndDetails } from '../../store/actions';
|
||||
import { isEqualCaseInsensitive } from '../../../shared/modules/string-utils';
|
||||
import { parseStandardTokenTransactionData } from '../../../shared/modules/transaction.utils';
|
||||
import { ERC20 } from '../../../shared/constants/transaction';
|
||||
import { getTokenValueParam } from '../../../shared/lib/metamask-controller-utils';
|
||||
import { calcTokenAmount } from '../../../shared/lib/transactions-controller-utils';
|
||||
import * as util from './util';
|
||||
import { formatCurrency } from './confirm-tx.util';
|
||||
|
||||
@ -108,16 +109,6 @@ export function tokenInfoGetter() {
|
||||
};
|
||||
}
|
||||
|
||||
export function calcTokenAmount(value, decimals) {
|
||||
const multiplier = Math.pow(10, Number(decimals || 0));
|
||||
return new BigNumber(String(value)).div(multiplier);
|
||||
}
|
||||
|
||||
export function calcTokenValue(value, decimals) {
|
||||
const multiplier = Math.pow(10, Number(decimals || 0));
|
||||
return new BigNumber(String(value)).times(multiplier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to get the address parameter of the given token transaction data
|
||||
* (i.e. function call) per the Human Standard Token ABI, in the following
|
||||
@ -141,10 +132,6 @@ export function getTokenAddressParam(tokenData = {}) {
|
||||
* @param {object} tokenData - ethers Interface token data.
|
||||
* @returns {string | undefined} A decimal string value.
|
||||
*/
|
||||
export function getTokenValueParam(tokenData = {}) {
|
||||
return tokenData?.args?._value?.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets either the '_tokenId' parameter or the 'id' param of the passed token transaction data.,
|
||||
* These are the parsed tokenId values returned by `parseStandardTokenTransactionData` as defined
|
||||
|
@ -10,7 +10,7 @@ import {
|
||||
} from '../../../shared/constants/transaction';
|
||||
import { addCurrencies } from '../../../shared/modules/conversion.utils';
|
||||
import { readAddressAsContract } from '../../../shared/modules/contract-utils';
|
||||
import fetchWithCache from './fetch-with-cache';
|
||||
import fetchWithCache from '../../../shared/lib/fetch-with-cache';
|
||||
|
||||
/**
|
||||
* @typedef EthersContractCall
|
||||
|
@ -5,7 +5,6 @@ import * as ethUtil from 'ethereumjs-util';
|
||||
import { DateTime } from 'luxon';
|
||||
import { getFormattedIpfsUrl } from '@metamask/controllers/dist/util';
|
||||
import slip44 from '@metamask/slip44';
|
||||
import { addHexPrefix } from '../../../app/scripts/lib/util';
|
||||
import { CHAIN_IDS } from '../../../shared/constants/network';
|
||||
import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils';
|
||||
import {
|
||||
@ -293,71 +292,6 @@ export function checkExistingAddresses(address, list = []) {
|
||||
return list.some(matchesAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a number and specified precision, returns that number in base 10 with a maximum of precision
|
||||
* significant digits, but without any trailing zeros after the decimal point To be used when wishing
|
||||
* to display only as much digits to the user as necessary
|
||||
*
|
||||
* @param {string | number | BigNumber} n - The number to format
|
||||
* @param {number} precision - The maximum number of significant digits in the return value
|
||||
* @returns {string} The number in decimal form, with <= precision significant digits and no decimal trailing zeros
|
||||
*/
|
||||
export function toPrecisionWithoutTrailingZeros(n, precision) {
|
||||
return new BigNumber(n)
|
||||
.toPrecision(precision)
|
||||
.replace(/(\.[0-9]*[1-9])0*|(\.0*)/u, '$1');
|
||||
}
|
||||
|
||||
/**
|
||||
* Given and object where all values are strings, returns the same object with all values
|
||||
* now prefixed with '0x'
|
||||
*
|
||||
* @param obj
|
||||
*/
|
||||
export function addHexPrefixToObjectValues(obj) {
|
||||
return Object.keys(obj).reduce((newObj, key) => {
|
||||
return { ...newObj, [key]: addHexPrefix(obj[key]) };
|
||||
}, {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the standard set of information about a transaction, returns a transaction properly formatted for
|
||||
* publishing via JSON RPC and web3
|
||||
*
|
||||
* @param {object} options
|
||||
* @param {boolean} [options.sendToken] - Indicates whether or not the transaciton is a token transaction
|
||||
* @param {string} options.data - A hex string containing the data to include in the transaction
|
||||
* @param {string} options.to - A hex address of the tx recipient address
|
||||
* @param options.amount
|
||||
* @param {string} options.from - A hex address of the tx sender address
|
||||
* @param {string} options.gas - A hex representation of the gas value for the transaction
|
||||
* @param {string} options.gasPrice - A hex representation of the gas price for the transaction
|
||||
* @returns {object} An object ready for submission to the blockchain, with all values appropriately hex prefixed
|
||||
*/
|
||||
export function constructTxParams({
|
||||
sendToken,
|
||||
data,
|
||||
to,
|
||||
amount,
|
||||
from,
|
||||
gas,
|
||||
gasPrice,
|
||||
}) {
|
||||
const txParams = {
|
||||
data,
|
||||
from,
|
||||
value: '0',
|
||||
gas,
|
||||
gasPrice,
|
||||
};
|
||||
|
||||
if (!sendToken) {
|
||||
txParams.value = amount;
|
||||
txParams.to = to;
|
||||
}
|
||||
return addHexPrefixToObjectValues(txParams);
|
||||
}
|
||||
|
||||
export function bnGreaterThan(a, b) {
|
||||
if (a === null || a === undefined || b === null || b === undefined) {
|
||||
return null;
|
||||
|
@ -1,4 +1,6 @@
|
||||
import { BN } from 'ethereumjs-util';
|
||||
import { addHexPrefixToObjectValues } from '../../../shared/lib/swaps-utils';
|
||||
import { toPrecisionWithoutTrailingZeros } from '../../../shared/lib/transactions-controller-utils';
|
||||
import * as util from './util';
|
||||
|
||||
describe('util', () => {
|
||||
@ -279,9 +281,7 @@ describe('util', () => {
|
||||
|
||||
testData.forEach(({ args, result }) => {
|
||||
it(`should return ${result} when passed number ${args[0]} and precision ${args[1]}`, () => {
|
||||
expect(util.toPrecisionWithoutTrailingZeros(...args)).toStrictEqual(
|
||||
result,
|
||||
);
|
||||
expect(toPrecisionWithoutTrailingZeros(...args)).toStrictEqual(result);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -289,7 +289,7 @@ describe('util', () => {
|
||||
describe('addHexPrefixToObjectValues()', () => {
|
||||
it('should return a new object with the same properties with a 0x prefix', () => {
|
||||
expect(
|
||||
util.addHexPrefixToObjectValues({
|
||||
addHexPrefixToObjectValues({
|
||||
prop1: '0x123',
|
||||
prop2: '456',
|
||||
prop3: 'x',
|
||||
|
@ -14,14 +14,12 @@ import {
|
||||
checkNetworkAndAccountSupports1559,
|
||||
getShouldShowFiat,
|
||||
} from '../../selectors';
|
||||
import {
|
||||
decGWEIToHexWEI,
|
||||
decimalToHex,
|
||||
} from '../../helpers/utils/conversions.util';
|
||||
import { decGWEIToHexWEI } from '../../helpers/utils/conversions.util';
|
||||
import { isLegacyTransaction } from '../../helpers/utils/transactions.util';
|
||||
|
||||
import { useCurrencyDisplay } from '../useCurrencyDisplay';
|
||||
import { useUserPreferencedCurrency } from '../useUserPreferencedCurrency';
|
||||
import { decimalToHex } from '../../../shared/lib/transactions-controller-utils';
|
||||
|
||||
/**
|
||||
* @typedef {object} GasEstimatesReturnType
|
||||
|
@ -4,11 +4,8 @@ import {
|
||||
getMaximumGasTotalInHexWei,
|
||||
getMinimumGasTotalInHexWei,
|
||||
} from '../../../shared/modules/gas.utils';
|
||||
import {
|
||||
decGWEIToHexWEI,
|
||||
decimalToHex,
|
||||
} from '../../helpers/utils/conversions.util';
|
||||
|
||||
import { decGWEIToHexWEI } from '../../helpers/utils/conversions.util';
|
||||
import { decimalToHex } from '../../../shared/lib/transactions-controller-utils';
|
||||
import {
|
||||
FEE_MARKET_ESTIMATE_RETURN_VALUE,
|
||||
LEGACY_GAS_ESTIMATE_RETURN_VALUE,
|
||||
|
@ -13,11 +13,11 @@ import {
|
||||
getAdvancedInlineGasShown,
|
||||
getEIP1559V2Enabled,
|
||||
} from '../../selectors';
|
||||
import { hexToDecimal } from '../../helpers/utils/conversions.util';
|
||||
import { isLegacyTransaction } from '../../helpers/utils/transactions.util';
|
||||
import { useGasFeeEstimates } from '../useGasFeeEstimates';
|
||||
|
||||
import { editGasModeIsSpeedUpOrCancel } from '../../helpers/utils/gas';
|
||||
import { hexToDecimal } from '../../../shared/lib/metamask-controller-utils';
|
||||
import { useGasFeeErrors } from './useGasFeeErrors';
|
||||
import { useGasPriceInput } from './useGasPriceInput';
|
||||
import { useMaxFeePerGasInput } from './useMaxFeePerGasInput';
|
||||
|
@ -5,9 +5,9 @@ import {
|
||||
GAS_ESTIMATE_TYPES,
|
||||
CUSTOM_GAS_ESTIMATE,
|
||||
} from '../../../shared/constants/gas';
|
||||
import { hexWEIToDecGWEI } from '../../helpers/utils/conversions.util';
|
||||
import { isLegacyTransaction } from '../../helpers/utils/transactions.util';
|
||||
|
||||
import { hexWEIToDecGWEI } from '../../../shared/lib/transactions-controller-utils';
|
||||
import { feeParamsAreCustom } from './utils';
|
||||
|
||||
function getGasPriceEstimate(gasFeeEstimates, gasEstimateType, estimateToUse) {
|
||||
|
@ -4,11 +4,7 @@ import { useSelector } from 'react-redux';
|
||||
import { GAS_ESTIMATE_TYPES } from '../../../shared/constants/gas';
|
||||
import { SECONDARY } from '../../helpers/constants/common';
|
||||
import { getMaximumGasTotalInHexWei } from '../../../shared/modules/gas.utils';
|
||||
import {
|
||||
decGWEIToHexWEI,
|
||||
decimalToHex,
|
||||
hexWEIToDecGWEI,
|
||||
} from '../../helpers/utils/conversions.util';
|
||||
import { decGWEIToHexWEI } from '../../helpers/utils/conversions.util';
|
||||
import {
|
||||
checkNetworkAndAccountSupports1559,
|
||||
getShouldShowFiat,
|
||||
@ -17,6 +13,10 @@ import { isLegacyTransaction } from '../../helpers/utils/transactions.util';
|
||||
|
||||
import { useCurrencyDisplay } from '../useCurrencyDisplay';
|
||||
import { useUserPreferencedCurrency } from '../useUserPreferencedCurrency';
|
||||
import {
|
||||
decimalToHex,
|
||||
hexWEIToDecGWEI,
|
||||
} from '../../../shared/lib/transactions-controller-utils';
|
||||
import { feeParamsAreCustom, getGasFeeEstimate } from './utils';
|
||||
|
||||
const getMaxFeePerGasFromTransaction = (transaction, gasFeeEstimates) => {
|
||||
|
@ -2,12 +2,12 @@ import { useSelector } from 'react-redux';
|
||||
import { act, renderHook } from '@testing-library/react-hooks';
|
||||
|
||||
import { getMaximumGasTotalInHexWei } from '../../../shared/modules/gas.utils';
|
||||
import { decimalToHex } from '../../helpers/utils/conversions.util';
|
||||
import {
|
||||
GAS_RECOMMENDATIONS,
|
||||
CUSTOM_GAS_ESTIMATE,
|
||||
} from '../../../shared/constants/gas';
|
||||
|
||||
import { decimalToHex } from '../../../shared/lib/transactions-controller-utils';
|
||||
import {
|
||||
FEE_MARKET_ESTIMATE_RETURN_VALUE,
|
||||
LEGACY_GAS_ESTIMATE_RETURN_VALUE,
|
||||
|
@ -4,7 +4,6 @@ import { useEffect, useState } from 'react';
|
||||
import { addHexPrefix } from 'ethereumjs-util';
|
||||
|
||||
import { SECONDARY } from '../../helpers/constants/common';
|
||||
import { hexWEIToDecGWEI } from '../../helpers/utils/conversions.util';
|
||||
import {
|
||||
checkNetworkAndAccountSupports1559,
|
||||
getShouldShowFiat,
|
||||
@ -14,6 +13,7 @@ import { multiplyCurrencies } from '../../../shared/modules/conversion.utils';
|
||||
|
||||
import { useCurrencyDisplay } from '../useCurrencyDisplay';
|
||||
import { useUserPreferencedCurrency } from '../useUserPreferencedCurrency';
|
||||
import { hexWEIToDecGWEI } from '../../../shared/lib/transactions-controller-utils';
|
||||
import { feeParamsAreCustom, getGasFeeEstimate } from './utils';
|
||||
|
||||
const getMaxPriorityFeePerGasFromTransaction = (
|
||||
|
@ -1,11 +1,9 @@
|
||||
import { useCallback } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { decimalToHex } from '../../../shared/lib/transactions-controller-utils';
|
||||
|
||||
import { EDIT_GAS_MODES, PRIORITY_LEVELS } from '../../../shared/constants/gas';
|
||||
import {
|
||||
decimalToHex,
|
||||
decGWEIToHexWEI,
|
||||
} from '../../helpers/utils/conversions.util';
|
||||
import { decGWEIToHexWEI } from '../../helpers/utils/conversions.util';
|
||||
import {
|
||||
addTenPercentAndRound,
|
||||
editGasModeIsSpeedUpOrCancel,
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { useSelector } from 'react-redux';
|
||||
import { getSwapsTokensReceivedFromTxMeta } from '../../shared/lib/transactions-controller-utils';
|
||||
import { TRANSACTION_TYPES } from '../../shared/constants/transaction';
|
||||
import {
|
||||
isSwapsDefaultTokenAddress,
|
||||
isSwapsDefaultTokenSymbol,
|
||||
} from '../../shared/modules/swaps.utils';
|
||||
import { getSwapsTokensReceivedFromTxMeta } from '../pages/swaps/swaps.util';
|
||||
import { getCurrentChainId } from '../selectors';
|
||||
import { useTokenFiatAmount } from './useTokenFiatAmount';
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
import { useMemo } from 'react';
|
||||
import {
|
||||
getTokenValueParam,
|
||||
calcTokenAmount,
|
||||
} from '../helpers/utils/token-util';
|
||||
import { getTokenValueParam } from '../../shared/lib/metamask-controller-utils';
|
||||
import { calcTokenAmount } from '../../shared/lib/transactions-controller-utils';
|
||||
import { useTokenData } from './useTokenData';
|
||||
|
||||
/**
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { renderHook } from '@testing-library/react-hooks';
|
||||
import sinon from 'sinon';
|
||||
import * as tokenUtil from '../helpers/utils/token-util';
|
||||
import * as txUtil from '../../shared/modules/transaction.utils';
|
||||
import * as metamaskControllerUtils from '../../shared/lib/metamask-controller-utils';
|
||||
import { useTokenDisplayValue } from './useTokenDisplayValue';
|
||||
|
||||
const tests = [
|
||||
@ -121,7 +121,10 @@ describe('useTokenDisplayValue', () => {
|
||||
tests.forEach(({ displayValue, token, tokenData, tokenValue }, idx) => {
|
||||
describe(`when input is decimals: ${token.decimals} and value: ${tokenValue}`, () => {
|
||||
it(`should return ${displayValue} as displayValue`, () => {
|
||||
const getTokenValueStub = sinon.stub(tokenUtil, 'getTokenValueParam');
|
||||
const getTokenValueStub = sinon.stub(
|
||||
metamaskControllerUtils,
|
||||
'getTokenValueParam',
|
||||
);
|
||||
const parseStandardTokenTransactionDataStub = sinon.stub(
|
||||
txUtil,
|
||||
'parseStandardTokenTransactionData',
|
||||
|
@ -9,7 +9,6 @@ import { PRIMARY, SECONDARY } from '../helpers/constants/common';
|
||||
import {
|
||||
getTokenAddressParam,
|
||||
getTokenIdParam,
|
||||
getTokenValueParam,
|
||||
} from '../helpers/utils/token-util';
|
||||
import {
|
||||
formatDateWithYearContext,
|
||||
@ -29,6 +28,7 @@ import {
|
||||
} from '../../shared/constants/transaction';
|
||||
import { captureSingleException } from '../store/actions';
|
||||
import { isEqualCaseInsensitive } from '../../shared/modules/string-utils';
|
||||
import { getTokenValueParam } from '../../shared/lib/metamask-controller-utils';
|
||||
import { useI18nContext } from './useI18nContext';
|
||||
import { useTokenFiatAmount } from './useTokenFiatAmount';
|
||||
import { useUserPreferencedCurrency } from './useUserPreferencedCurrency';
|
||||
|
25
ui/index.js
25
ui/index.js
@ -1,6 +1,6 @@
|
||||
import copyToClipboard from 'copy-to-clipboard';
|
||||
import log from 'loglevel';
|
||||
import { clone, memoize } from 'lodash';
|
||||
import { clone } from 'lodash';
|
||||
import React from 'react';
|
||||
import { render } from 'react-dom';
|
||||
import browser from 'webextension-polyfill';
|
||||
@ -10,13 +10,10 @@ import { ALERT_TYPES } from '../shared/constants/alerts';
|
||||
import { maskObject } from '../shared/modules/object.utils';
|
||||
import { SENTRY_STATE } from '../app/scripts/lib/setupSentry';
|
||||
import { ENVIRONMENT_TYPE_POPUP } from '../shared/constants/app';
|
||||
import switchDirection from '../shared/lib/switch-direction';
|
||||
import { setupLocale } from '../shared/lib/error-utils';
|
||||
import * as actions from './store/actions';
|
||||
import configureStore from './store/store';
|
||||
import {
|
||||
fetchLocale,
|
||||
loadRelativeTimeFormatLocaleData,
|
||||
} from './helpers/utils/i18n-helper';
|
||||
import switchDirection from './helpers/utils/switch-direction';
|
||||
import {
|
||||
getPermittedAccountsForCurrentTab,
|
||||
getSelectedAddress,
|
||||
@ -69,22 +66,6 @@ export default function launchMetamaskUi(opts, cb) {
|
||||
});
|
||||
}
|
||||
|
||||
const _setupLocale = async (currentLocale) => {
|
||||
const currentLocaleMessages = currentLocale
|
||||
? await fetchLocale(currentLocale)
|
||||
: {};
|
||||
const enLocaleMessages = await fetchLocale('en');
|
||||
|
||||
await loadRelativeTimeFormatLocaleData('en');
|
||||
if (currentLocale) {
|
||||
await loadRelativeTimeFormatLocaleData(currentLocale);
|
||||
}
|
||||
|
||||
return { currentLocaleMessages, enLocaleMessages };
|
||||
};
|
||||
|
||||
export const setupLocale = memoize(_setupLocale);
|
||||
|
||||
async function startApp(metamaskState, backgroundConnection, opts) {
|
||||
// parse opts
|
||||
if (!metamaskState.featureFlags) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { setupLocale } from '.';
|
||||
import { setupLocale } from '../shared/lib/error-utils';
|
||||
|
||||
const enMessages = {
|
||||
troubleStarting: {
|
||||
|
@ -8,10 +8,7 @@ import {
|
||||
updateCustomNonce,
|
||||
getNextNonce,
|
||||
} from '../../store/actions';
|
||||
import {
|
||||
calcTokenAmount,
|
||||
getTokenApprovedParam,
|
||||
} from '../../helpers/utils/token-util';
|
||||
import { getTokenApprovedParam } from '../../helpers/utils/token-util';
|
||||
import { readAddressAsContract } from '../../../shared/modules/contract-utils';
|
||||
import { GasFeeContextProvider } from '../../contexts/gasFee';
|
||||
import { TransactionModalContextProvider } from '../../contexts/transaction-modal';
|
||||
@ -38,6 +35,7 @@ import EditGasPopover from '../../components/app/edit-gas-popover/edit-gas-popov
|
||||
import Loading from '../../components/ui/loading-screen';
|
||||
import { parseStandardTokenTransactionData } from '../../../shared/modules/transaction.utils';
|
||||
import { ERC1155, ERC20, ERC721 } from '../../../shared/constants/transaction';
|
||||
import { calcTokenAmount } from '../../../shared/lib/transactions-controller-utils';
|
||||
import { getCustomTxParamsData } from './confirm-approve.util';
|
||||
import ConfirmApproveContent from './confirm-approve-content';
|
||||
|
||||
|
@ -1,10 +1,8 @@
|
||||
import { calcTokenValue } from '../../../shared/lib/swaps-utils';
|
||||
import { decimalToHex } from '../../../shared/lib/transactions-controller-utils';
|
||||
import { TRANSACTION_TYPES } from '../../../shared/constants/transaction';
|
||||
import { parseStandardTokenTransactionData } from '../../../shared/modules/transaction.utils';
|
||||
import { decimalToHex } from '../../helpers/utils/conversions.util';
|
||||
import {
|
||||
calcTokenValue,
|
||||
getTokenAddressParam,
|
||||
} from '../../helpers/utils/token-util';
|
||||
import { getTokenAddressParam } from '../../helpers/utils/token-util';
|
||||
|
||||
export function getCustomTxParamsData(
|
||||
data,
|
||||
|
@ -11,11 +11,8 @@ import {
|
||||
addFiat,
|
||||
roundExponential,
|
||||
} from '../../helpers/utils/confirm-tx.util';
|
||||
import {
|
||||
getWeiHexFromDecimalValue,
|
||||
hexWEIToDecETH,
|
||||
} from '../../helpers/utils/conversions.util';
|
||||
import { ETH, PRIMARY } from '../../helpers/constants/common';
|
||||
import { getWeiHexFromDecimalValue } from '../../helpers/utils/conversions.util';
|
||||
import {
|
||||
contractExchangeRateSelector,
|
||||
getCurrentCurrency,
|
||||
@ -25,6 +22,7 @@ import {
|
||||
getNativeCurrency,
|
||||
} from '../../ducks/metamask/metamask';
|
||||
import { ERC1155, ERC20, ERC721 } from '../../../shared/constants/transaction';
|
||||
import { hexWEIToDecETH } from '../../../shared/lib/transactions-controller-utils';
|
||||
|
||||
export default function ConfirmTokenTransactionBase({
|
||||
image = '',
|
||||
|
@ -3,11 +3,7 @@ import PropTypes from 'prop-types';
|
||||
import ConfirmPageContainer from '../../components/app/confirm-page-container';
|
||||
import TransactionDecoding from '../../components/app/transaction-decoding';
|
||||
import { isBalanceSufficient } from '../send/send.utils';
|
||||
import {
|
||||
addHexes,
|
||||
hexToDecimal,
|
||||
hexWEIToDecGWEI,
|
||||
} from '../../helpers/utils/conversions.util';
|
||||
import { addHexes } from '../../helpers/utils/conversions.util';
|
||||
import {
|
||||
CONFIRM_TRANSACTION_ROUTE,
|
||||
DEFAULT_ROUTE,
|
||||
@ -63,6 +59,8 @@ import Typography from '../../components/ui/typography/typography';
|
||||
import { MIN_GAS_LIMIT_DEC } from '../send/send.constants';
|
||||
import { NETWORK_TO_NAME_MAP } from '../../../shared/constants/network';
|
||||
|
||||
import { hexToDecimal } from '../../../shared/lib/metamask-controller-utils';
|
||||
import { hexWEIToDecGWEI } from '../../../shared/lib/transactions-controller-utils';
|
||||
import TransactionAlerts from './transaction-alerts';
|
||||
|
||||
const renderHeartBeatIfNotInTest = () =>
|
||||
|
@ -14,7 +14,7 @@ import {
|
||||
tryReverseResolveAddress,
|
||||
setDefaultHomeActiveTabName,
|
||||
} from '../../store/actions';
|
||||
import { isBalanceSufficient, calcGasTotal } from '../send/send.utils';
|
||||
import { isBalanceSufficient } from '../send/send.utils';
|
||||
import { shortenAddress, valuesFor } from '../../helpers/utils/util';
|
||||
import {
|
||||
getAdvancedInlineGasShown,
|
||||
@ -57,6 +57,7 @@ import { CUSTOM_GAS_ESTIMATE } from '../../../shared/constants/gas';
|
||||
import { TRANSACTION_TYPES } from '../../../shared/constants/transaction';
|
||||
import { isEqualCaseInsensitive } from '../../../shared/modules/string-utils';
|
||||
import { getTokenAddressParam } from '../../helpers/utils/token-util';
|
||||
import { calcGasTotal } from '../../../shared/lib/transactions-controller-utils';
|
||||
import ConfirmTransactionBase from './confirm-transaction-base.component';
|
||||
|
||||
let customNonceValue = '';
|
||||
|
@ -12,9 +12,8 @@ import {
|
||||
ALIGN_ITEMS,
|
||||
} from '../../../helpers/constants/design-system';
|
||||
import { DEFAULT_ROUTE } from '../../../helpers/constants/routes';
|
||||
|
||||
import fetchWithCache from '../../../helpers/utils/fetch-with-cache';
|
||||
import ZENDESK_URLS from '../../../helpers/constants/zendesk-url';
|
||||
import fetchWithCache from '../../../../shared/lib/fetch-with-cache';
|
||||
|
||||
const UNRECOGNIZED_CHAIN = {
|
||||
id: 'UNRECOGNIZED_CHAIN',
|
||||
|
@ -1,9 +1,6 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Redirect, Route } from 'react-router-dom';
|
||||
///: BEGIN:ONLY_INCLUDE_IN(main)
|
||||
import { SUPPORT_LINK } from '../../helpers/constants/common';
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
import {
|
||||
EVENT,
|
||||
EVENT_NAMES,
|
||||
@ -52,6 +49,9 @@ import {
|
||||
} from '../../helpers/constants/routes';
|
||||
import ZENDESK_URLS from '../../helpers/constants/zendesk-url';
|
||||
import Tooltip from '../../components/ui/tooltip';
|
||||
///: BEGIN:ONLY_INCLUDE_IN(main)
|
||||
import { SUPPORT_LINK } from '../../../shared/lib/ui-utils';
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
///: BEGIN:ONLY_INCLUDE_IN(beta)
|
||||
import BetaHomeFooter from './beta/beta-home-footer.component';
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
@ -24,7 +24,7 @@ import {
|
||||
setCustomGasLimit,
|
||||
} from '../../../../ducks/gas/gas.duck';
|
||||
import { showModal } from '../../../../store/actions';
|
||||
import { hexToDecimal } from '../../../../helpers/utils/conversions.util';
|
||||
import { hexToDecimal } from '../../../../../shared/lib/metamask-controller-utils';
|
||||
import SendGasRow from './send-gas-row.component';
|
||||
|
||||
export default connect(
|
||||
|
@ -3,10 +3,10 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
import testData from '../../../../../.storybook/test-data';
|
||||
import { calcGasTotal } from '../../../../../shared/lib/transactions-controller-utils';
|
||||
import { GAS_INPUT_MODES } from '../../../../ducks/send';
|
||||
import { updateMetamaskState } from '../../../../store/actions';
|
||||
import configureStore from '../../../../store/store';
|
||||
import { calcGasTotal } from '../../send.utils';
|
||||
import README from './README.mdx';
|
||||
import SendGasRow from './send-gas-row.component';
|
||||
|
||||
|
@ -8,9 +8,9 @@ import {
|
||||
conversionLessThan,
|
||||
} from '../../../shared/modules/conversion.utils';
|
||||
|
||||
import { calcTokenAmount } from '../../helpers/utils/token-util';
|
||||
import { addHexPrefix } from '../../../app/scripts/lib/util';
|
||||
import { ERC20, ERC721 } from '../../../shared/constants/transaction';
|
||||
import { calcTokenAmount } from '../../../shared/lib/transactions-controller-utils';
|
||||
import {
|
||||
TOKEN_TRANSFER_FUNCTION_SIGNATURE,
|
||||
COLLECTIBLE_TRANSFER_FROM_FUNCTION_SIGNATURE,
|
||||
@ -18,7 +18,6 @@ import {
|
||||
|
||||
export {
|
||||
addGasBuffer,
|
||||
calcGasTotal,
|
||||
getAssetTransferData,
|
||||
generateERC20TransferData,
|
||||
generateERC721TransferData,
|
||||
@ -27,14 +26,6 @@ export {
|
||||
ellipsify,
|
||||
};
|
||||
|
||||
function calcGasTotal(gasLimit = '0', gasPrice = '0') {
|
||||
return multiplyCurrencies(gasLimit, gasPrice, {
|
||||
toNumericBase: 'hex',
|
||||
multiplicandBase: 16,
|
||||
multiplierBase: 16,
|
||||
});
|
||||
}
|
||||
|
||||
function isBalanceSufficient({
|
||||
amount = '0x0',
|
||||
balance = '0x0',
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { rawEncode } from 'ethereumjs-abi';
|
||||
import { calcGasTotal } from '../../../shared/lib/transactions-controller-utils';
|
||||
|
||||
import {
|
||||
multiplyCurrencies,
|
||||
@ -8,7 +9,6 @@ import {
|
||||
} from '../../../shared/modules/conversion.utils';
|
||||
|
||||
import {
|
||||
calcGasTotal,
|
||||
generateERC20TransferData,
|
||||
isBalanceSufficient,
|
||||
isTokenBalanceSufficient,
|
||||
@ -32,9 +32,16 @@ jest.mock('../../../shared/modules/conversion.utils', () => ({
|
||||
conversionLessThan: (obj1, obj2) => obj1.value < obj2.value,
|
||||
}));
|
||||
|
||||
jest.mock('../../helpers/utils/token-util', () => ({
|
||||
jest.mock('../../../shared/lib/transactions-controller-utils', () => {
|
||||
const originalModule = jest.requireActual(
|
||||
'../../../shared/lib/transactions-controller-utils',
|
||||
);
|
||||
|
||||
return {
|
||||
...originalModule,
|
||||
calcTokenAmount: (a, d) => `calc:${a}${d}`,
|
||||
}));
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('ethereumjs-abi', () => ({
|
||||
rawEncode: jest.fn().mockReturnValue(16, 1100),
|
||||
|
22
ui/pages/settings/experimental-tab/experimental-tab.test.js
Normal file
22
ui/pages/settings/experimental-tab/experimental-tab.test.js
Normal file
@ -0,0 +1,22 @@
|
||||
import React from 'react';
|
||||
import { screen } from '@testing-library/react';
|
||||
import { renderWithProvider } from '../../../../test/jest';
|
||||
import configureStore from '../../../store/store';
|
||||
import mockState from '../../../../test/data/mock-state.json';
|
||||
import ExperimentalTab from './experimental-tab.component';
|
||||
|
||||
const render = () => {
|
||||
const store = configureStore({
|
||||
metamask: {
|
||||
...mockState.metamask,
|
||||
},
|
||||
});
|
||||
return renderWithProvider(<ExperimentalTab />, store);
|
||||
};
|
||||
|
||||
describe('ExperimentalTab', () => {
|
||||
it('renders ExperimentalTab component and shows Enable enhanced gas fee UI text', () => {
|
||||
render();
|
||||
expect(screen.getByText('Enable enhanced gas fee UI')).toBeInTheDocument();
|
||||
});
|
||||
});
|
@ -2,10 +2,7 @@ import React, { PureComponent } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Button from '../../../components/ui/button';
|
||||
import {
|
||||
SUPPORT_LINK,
|
||||
SUPPORT_REQUEST_LINK,
|
||||
} from '../../../helpers/constants/common';
|
||||
import { SUPPORT_REQUEST_LINK } from '../../../helpers/constants/common';
|
||||
import { isBeta } from '../../../helpers/utils/build-types';
|
||||
import {
|
||||
getNumberOfSettingsInSection,
|
||||
@ -16,6 +13,7 @@ import {
|
||||
EVENT_NAMES,
|
||||
CONTEXT_PROPS,
|
||||
} from '../../../../shared/constants/metametrics';
|
||||
import { SUPPORT_LINK } from '../../../../shared/lib/ui-utils';
|
||||
|
||||
export default class InfoTab extends PureComponent {
|
||||
state = {
|
||||
|
@ -22,7 +22,6 @@ import { jsonRpcRequest } from '../../../../../shared/modules/rpc.utils';
|
||||
import ActionableMessage from '../../../../components/ui/actionable-message';
|
||||
import Button from '../../../../components/ui/button';
|
||||
import FormField from '../../../../components/ui/form-field';
|
||||
import { decimalToHex } from '../../../../helpers/utils/conversions.util';
|
||||
import {
|
||||
setSelectedSettingsRpcUrl,
|
||||
updateAndSetCustomRpc,
|
||||
@ -34,7 +33,7 @@ import {
|
||||
DEFAULT_ROUTE,
|
||||
NETWORKS_ROUTE,
|
||||
} from '../../../../helpers/constants/routes';
|
||||
import fetchWithCache from '../../../../helpers/utils/fetch-with-cache';
|
||||
import fetchWithCache from '../../../../../shared/lib/fetch-with-cache';
|
||||
import { usePrevious } from '../../../../hooks/usePrevious';
|
||||
import { MetaMetricsContext } from '../../../../contexts/metametrics';
|
||||
import { EVENT } from '../../../../../shared/constants/metametrics';
|
||||
@ -42,6 +41,7 @@ import {
|
||||
infuraProjectId,
|
||||
FEATURED_RPCS,
|
||||
} from '../../../../../shared/constants/network';
|
||||
import { decimalToHex } from '../../../../../shared/lib/transactions-controller-utils';
|
||||
|
||||
/**
|
||||
* Attempts to convert the given chainId to a decimal string, for display
|
||||
|
@ -6,7 +6,6 @@ import { useHistory } from 'react-router-dom';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import { getBlockExplorerLink } from '@metamask/etherscan-link';
|
||||
import { I18nContext } from '../../../contexts/i18n';
|
||||
import { SUPPORT_LINK } from '../../../helpers/constants/common';
|
||||
import { MetaMetricsContext } from '../../../contexts/metametrics';
|
||||
import {
|
||||
EVENT,
|
||||
@ -62,6 +61,7 @@ import SwapsFooter from '../swaps-footer';
|
||||
|
||||
import CreateNewSwap from '../create-new-swap';
|
||||
import ViewOnBlockExplorer from '../view-on-block-explorer';
|
||||
import { SUPPORT_LINK } from '../../../../shared/lib/ui-utils';
|
||||
import SwapFailureIcon from './swap-failure-icon';
|
||||
import SwapSuccessIcon from './swap-success-icon';
|
||||
import QuotesTimeoutIcon from './quotes-timeout-icon';
|
||||
|
@ -71,11 +71,7 @@ import {
|
||||
getHardwareWalletType,
|
||||
} from '../../../selectors';
|
||||
|
||||
import {
|
||||
getValueFromWeiHex,
|
||||
hexToDecimal,
|
||||
} from '../../../helpers/utils/conversions.util';
|
||||
import { calcTokenAmount } from '../../../helpers/utils/token-util';
|
||||
import { getValueFromWeiHex } from '../../../helpers/utils/conversions.util';
|
||||
import { getURLHostName } from '../../../helpers/utils/util';
|
||||
import { usePrevious } from '../../../hooks/usePrevious';
|
||||
import { useTokenTracker } from '../../../hooks/useTokenTracker';
|
||||
@ -106,10 +102,12 @@ import {
|
||||
countDecimals,
|
||||
fetchTokenPrice,
|
||||
fetchTokenBalance,
|
||||
shouldEnableDirectWrapping,
|
||||
} from '../swaps.util';
|
||||
import SwapsFooter from '../swaps-footer';
|
||||
import { isEqualCaseInsensitive } from '../../../../shared/modules/string-utils';
|
||||
import { hexToDecimal } from '../../../../shared/lib/metamask-controller-utils';
|
||||
import { calcTokenAmount } from '../../../../shared/lib/transactions-controller-utils';
|
||||
import { shouldEnableDirectWrapping } from '../../../../shared/lib/swaps-utils';
|
||||
|
||||
const fuseSearchKeys = [
|
||||
{ name: 'name', weight: 0.499 },
|
||||
|
@ -2,8 +2,8 @@ import React, { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import classnames from 'classnames';
|
||||
import { calcTokenAmount } from '../../../helpers/utils/token-util';
|
||||
import { formatSwapsValueForDisplay } from '../swaps.util';
|
||||
import { calcTokenAmount } from '../../../../shared/lib/transactions-controller-utils';
|
||||
|
||||
export default function ExchangeRateDisplay({
|
||||
primaryTokenValue,
|
||||
|
@ -87,10 +87,10 @@ import { EVENT } from '../../../shared/constants/metametrics';
|
||||
import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction';
|
||||
import ActionableMessage from '../../components/ui/actionable-message';
|
||||
import { MetaMetricsContext } from '../../contexts/metametrics';
|
||||
import { getSwapsTokensReceivedFromTxMeta } from '../../../shared/lib/transactions-controller-utils';
|
||||
import {
|
||||
fetchTokens,
|
||||
fetchTopAssets,
|
||||
getSwapsTokensReceivedFromTxMeta,
|
||||
fetchAggregatorMetadata,
|
||||
stxErrorTypes,
|
||||
} from './swaps.util';
|
||||
|
@ -1,12 +1,14 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { calcTokenAmount } from '../../../helpers/utils/token-util';
|
||||
import { toPrecisionWithoutTrailingZeros } from '../../../helpers/utils/util';
|
||||
import Tooltip from '../../../components/ui/tooltip';
|
||||
import UrlIcon from '../../../components/ui/url-icon';
|
||||
import ExchangeRateDisplay from '../exchange-rate-display';
|
||||
import { formatSwapsValueForDisplay } from '../swaps.util';
|
||||
import {
|
||||
calcTokenAmount,
|
||||
toPrecisionWithoutTrailingZeros,
|
||||
} from '../../../../shared/lib/transactions-controller-utils';
|
||||
|
||||
function getFontSizesAndLineHeights(fontSizeScore) {
|
||||
if (fontSizeScore <= 9) {
|
||||
|
@ -52,7 +52,6 @@ import { EVENT } from '../../../../shared/constants/metametrics';
|
||||
import { SMART_TRANSACTION_STATUSES } from '../../../../shared/constants/transaction';
|
||||
|
||||
import SwapsFooter from '../swaps-footer';
|
||||
import { calcTokenAmount } from '../../../helpers/utils/token-util';
|
||||
import {
|
||||
showRemainingTimeInMinAndSec,
|
||||
getFeeForSmartTransaction,
|
||||
@ -60,6 +59,7 @@ import {
|
||||
import { MetaMetricsContext } from '../../../contexts/metametrics';
|
||||
import CreateNewSwap from '../create-new-swap';
|
||||
import ViewOnBlockExplorer from '../view-on-block-explorer';
|
||||
import { calcTokenAmount } from '../../../../shared/lib/transactions-controller-utils';
|
||||
import SuccessIcon from './success-icon';
|
||||
import RevertedIcon from './reverted-icon';
|
||||
import CanceledIcon from './canceled-icon';
|
||||
|
@ -1,10 +1,8 @@
|
||||
import log from 'loglevel';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import abi from 'human-standard-token-abi';
|
||||
import {
|
||||
SWAPS_CHAINID_DEFAULT_TOKEN_MAP,
|
||||
ALLOWED_CONTRACT_ADDRESSES,
|
||||
SWAPS_WRAPPED_TOKENS_ADDRESSES,
|
||||
ETHEREUM,
|
||||
POLYGON,
|
||||
BSC,
|
||||
@ -12,179 +10,40 @@ import {
|
||||
AVALANCHE,
|
||||
SWAPS_API_V2_BASE_URL,
|
||||
SWAPS_DEV_API_V2_BASE_URL,
|
||||
GAS_API_BASE_URL,
|
||||
GAS_DEV_API_BASE_URL,
|
||||
SWAPS_CLIENT_ID,
|
||||
SWAPS_WRAPPED_TOKENS_ADDRESSES,
|
||||
} from '../../../shared/constants/swaps';
|
||||
import { TRANSACTION_ENVELOPE_TYPES } from '../../../shared/constants/transaction';
|
||||
import {
|
||||
isSwapsDefaultTokenAddress,
|
||||
isSwapsDefaultTokenSymbol,
|
||||
} from '../../../shared/modules/swaps.utils';
|
||||
import { CHAIN_IDS, CURRENCY_SYMBOLS } from '../../../shared/constants/network';
|
||||
import { SECOND } from '../../../shared/constants/time';
|
||||
import { getValueFromWeiHex } from '../../helpers/utils/conversions.util';
|
||||
import { formatCurrency } from '../../helpers/utils/confirm-tx.util';
|
||||
import fetchWithCache from '../../../shared/lib/fetch-with-cache';
|
||||
|
||||
import { isValidHexAddress } from '../../../shared/modules/hexstring-utils';
|
||||
import {
|
||||
calcGasTotal,
|
||||
calcTokenAmount,
|
||||
decimalToHex,
|
||||
toPrecisionWithoutTrailingZeros,
|
||||
} from '../../../shared/lib/transactions-controller-utils';
|
||||
import {
|
||||
calcTokenValue,
|
||||
calcTokenAmount,
|
||||
} from '../../helpers/utils/token-util';
|
||||
import {
|
||||
constructTxParams,
|
||||
toPrecisionWithoutTrailingZeros,
|
||||
} from '../../helpers/utils/util';
|
||||
import {
|
||||
decimalToHex,
|
||||
getValueFromWeiHex,
|
||||
} from '../../helpers/utils/conversions.util';
|
||||
|
||||
import { subtractCurrencies } from '../../../shared/modules/conversion.utils';
|
||||
import { formatCurrency } from '../../helpers/utils/confirm-tx.util';
|
||||
import fetchWithCache from '../../helpers/utils/fetch-with-cache';
|
||||
|
||||
import { calcGasTotal } from '../send/send.utils';
|
||||
import { isValidHexAddress } from '../../../shared/modules/hexstring-utils';
|
||||
|
||||
const TOKEN_TRANSFER_LOG_TOPIC_HASH =
|
||||
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef';
|
||||
getBaseApi,
|
||||
QUOTE_VALIDATORS,
|
||||
truthyString,
|
||||
validateData,
|
||||
} from '../../../shared/lib/swaps-utils';
|
||||
import { SECOND } from '../../../shared/constants/time';
|
||||
|
||||
const CACHE_REFRESH_FIVE_MINUTES = 300000;
|
||||
const USD_CURRENCY_CODE = 'usd';
|
||||
|
||||
const clientIdHeader = { 'X-Client-Id': SWAPS_CLIENT_ID };
|
||||
|
||||
/**
|
||||
* @param {string} type - Type of an API call, e.g. "tokens"
|
||||
* @param {string} chainId
|
||||
* @returns string
|
||||
*/
|
||||
const getBaseUrlForNewSwapsApi = (type, chainId) => {
|
||||
const useDevApis = process.env.SWAPS_USE_DEV_APIS;
|
||||
const v2ApiBaseUrl = useDevApis
|
||||
? SWAPS_DEV_API_V2_BASE_URL
|
||||
: SWAPS_API_V2_BASE_URL;
|
||||
const gasApiBaseUrl = useDevApis ? GAS_DEV_API_BASE_URL : GAS_API_BASE_URL;
|
||||
const noNetworkSpecificTypes = ['refreshTime']; // These types don't need network info in the URL.
|
||||
if (noNetworkSpecificTypes.includes(type)) {
|
||||
return v2ApiBaseUrl;
|
||||
}
|
||||
const chainIdDecimal = chainId && parseInt(chainId, 16);
|
||||
const gasApiTypes = ['gasPrices'];
|
||||
if (gasApiTypes.includes(type)) {
|
||||
return `${gasApiBaseUrl}/networks/${chainIdDecimal}`; // Gas calculations are in its own repo.
|
||||
}
|
||||
return `${v2ApiBaseUrl}/networks/${chainIdDecimal}`;
|
||||
};
|
||||
|
||||
const TEST_CHAIN_IDS = [CHAIN_IDS.GOERLI, CHAIN_IDS.LOCALHOST];
|
||||
|
||||
export const getBaseApi = function (type, chainId = CHAIN_IDS.MAINNET) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
chainId = TEST_CHAIN_IDS.includes(chainId) ? CHAIN_IDS.MAINNET : chainId;
|
||||
const baseUrl = getBaseUrlForNewSwapsApi(type, chainId);
|
||||
const chainIdDecimal = chainId && parseInt(chainId, 16);
|
||||
if (!baseUrl) {
|
||||
throw new Error(`Swaps API calls are disabled for chainId: ${chainId}`);
|
||||
}
|
||||
switch (type) {
|
||||
case 'trade':
|
||||
return `${baseUrl}/trades?`;
|
||||
case 'tokens':
|
||||
return `${baseUrl}/tokens`;
|
||||
case 'token':
|
||||
return `${baseUrl}/token`;
|
||||
case 'topAssets':
|
||||
return `${baseUrl}/topAssets`;
|
||||
case 'aggregatorMetadata':
|
||||
return `${baseUrl}/aggregatorMetadata`;
|
||||
case 'gasPrices':
|
||||
return `${baseUrl}/gasPrices`;
|
||||
case 'network':
|
||||
// Only use v2 for this endpoint.
|
||||
return `${SWAPS_API_V2_BASE_URL}/networks/${chainIdDecimal}`;
|
||||
default:
|
||||
throw new Error('getBaseApi requires an api call type');
|
||||
}
|
||||
};
|
||||
|
||||
const validHex = (string) => Boolean(string?.match(/^0x[a-f0-9]+$/u));
|
||||
const truthyString = (string) => Boolean(string?.length);
|
||||
const truthyDigitString = (string) =>
|
||||
truthyString(string) && Boolean(string.match(/^\d+$/u));
|
||||
|
||||
const QUOTE_VALIDATORS = [
|
||||
{
|
||||
property: 'trade',
|
||||
type: 'object',
|
||||
validator: (trade) =>
|
||||
trade &&
|
||||
validHex(trade.data) &&
|
||||
isValidHexAddress(trade.to, { allowNonPrefixed: false }) &&
|
||||
isValidHexAddress(trade.from, { allowNonPrefixed: false }) &&
|
||||
truthyString(trade.value),
|
||||
},
|
||||
{
|
||||
property: 'approvalNeeded',
|
||||
type: 'object',
|
||||
validator: (approvalTx) =>
|
||||
approvalTx === null ||
|
||||
(approvalTx &&
|
||||
validHex(approvalTx.data) &&
|
||||
isValidHexAddress(approvalTx.to, { allowNonPrefixed: false }) &&
|
||||
isValidHexAddress(approvalTx.from, { allowNonPrefixed: false })),
|
||||
},
|
||||
{
|
||||
property: 'sourceAmount',
|
||||
type: 'string',
|
||||
validator: truthyDigitString,
|
||||
},
|
||||
{
|
||||
property: 'destinationAmount',
|
||||
type: 'string',
|
||||
validator: truthyDigitString,
|
||||
},
|
||||
{
|
||||
property: 'sourceToken',
|
||||
type: 'string',
|
||||
validator: (input) => isValidHexAddress(input, { allowNonPrefixed: false }),
|
||||
},
|
||||
{
|
||||
property: 'destinationToken',
|
||||
type: 'string',
|
||||
validator: (input) => isValidHexAddress(input, { allowNonPrefixed: false }),
|
||||
},
|
||||
{
|
||||
property: 'aggregator',
|
||||
type: 'string',
|
||||
validator: truthyString,
|
||||
},
|
||||
{
|
||||
property: 'aggType',
|
||||
type: 'string',
|
||||
validator: truthyString,
|
||||
},
|
||||
{
|
||||
property: 'error',
|
||||
type: 'object',
|
||||
validator: (error) => error === null || typeof error === 'object',
|
||||
},
|
||||
{
|
||||
property: 'averageGas',
|
||||
type: 'number',
|
||||
},
|
||||
{
|
||||
property: 'maxGas',
|
||||
type: 'number',
|
||||
},
|
||||
{
|
||||
property: 'gasEstimate',
|
||||
type: 'number|undefined',
|
||||
validator: (gasEstimate) => gasEstimate === undefined || gasEstimate > 0,
|
||||
},
|
||||
{
|
||||
property: 'fee',
|
||||
type: 'number',
|
||||
},
|
||||
];
|
||||
|
||||
const TOKEN_VALIDATORS = [
|
||||
{
|
||||
property: 'address',
|
||||
@ -244,25 +103,6 @@ const SWAP_GAS_PRICE_VALIDATOR = [
|
||||
},
|
||||
];
|
||||
|
||||
function validateData(validators, object, urlUsed, logError = true) {
|
||||
return validators.every(({ property, type, validator }) => {
|
||||
const types = type.split('|');
|
||||
|
||||
const valid =
|
||||
types.some((_type) => typeof object[property] === _type) &&
|
||||
(!validator || validator(object[property]));
|
||||
if (!valid && logError) {
|
||||
log.error(
|
||||
`response to GET ${urlUsed} invalid for property ${property}; value was:`,
|
||||
object[property],
|
||||
'| type was: ',
|
||||
typeof object[property],
|
||||
);
|
||||
}
|
||||
return valid;
|
||||
});
|
||||
}
|
||||
|
||||
export const shouldEnableDirectWrapping = (
|
||||
chainId,
|
||||
sourceToken,
|
||||
@ -725,105 +565,6 @@ export function quotesToRenderableData(
|
||||
});
|
||||
}
|
||||
|
||||
export function getSwapsTokensReceivedFromTxMeta(
|
||||
tokenSymbol,
|
||||
txMeta,
|
||||
tokenAddress,
|
||||
accountAddress,
|
||||
tokenDecimals,
|
||||
approvalTxMeta,
|
||||
chainId,
|
||||
) {
|
||||
const txReceipt = txMeta?.txReceipt;
|
||||
const networkAndAccountSupports1559 =
|
||||
txMeta?.txReceipt?.type === TRANSACTION_ENVELOPE_TYPES.FEE_MARKET;
|
||||
if (isSwapsDefaultTokenSymbol(tokenSymbol, chainId)) {
|
||||
if (
|
||||
!txReceipt ||
|
||||
!txMeta ||
|
||||
!txMeta.postTxBalance ||
|
||||
!txMeta.preTxBalance
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (txMeta.swapMetaData && txMeta.preTxBalance === txMeta.postTxBalance) {
|
||||
// If preTxBalance and postTxBalance are equal, postTxBalance hasn't been updated on time
|
||||
// because of the RPC provider delay, so we return an estimated receiving amount instead.
|
||||
return txMeta.swapMetaData.token_to_amount;
|
||||
}
|
||||
|
||||
let approvalTxGasCost = '0x0';
|
||||
if (approvalTxMeta && approvalTxMeta.txReceipt) {
|
||||
approvalTxGasCost = calcGasTotal(
|
||||
approvalTxMeta.txReceipt.gasUsed,
|
||||
networkAndAccountSupports1559
|
||||
? approvalTxMeta.txReceipt.effectiveGasPrice // Base fee + priority fee.
|
||||
: approvalTxMeta.txParams.gasPrice,
|
||||
);
|
||||
}
|
||||
|
||||
const gasCost = calcGasTotal(
|
||||
txReceipt.gasUsed,
|
||||
networkAndAccountSupports1559
|
||||
? txReceipt.effectiveGasPrice
|
||||
: txMeta.txParams.gasPrice,
|
||||
);
|
||||
const totalGasCost = new BigNumber(gasCost, 16)
|
||||
.plus(approvalTxGasCost, 16)
|
||||
.toString(16);
|
||||
|
||||
const preTxBalanceLessGasCost = subtractCurrencies(
|
||||
txMeta.preTxBalance,
|
||||
totalGasCost,
|
||||
{
|
||||
aBase: 16,
|
||||
bBase: 16,
|
||||
toNumericBase: 'hex',
|
||||
},
|
||||
);
|
||||
|
||||
const ethReceived = subtractCurrencies(
|
||||
txMeta.postTxBalance,
|
||||
preTxBalanceLessGasCost,
|
||||
{
|
||||
aBase: 16,
|
||||
bBase: 16,
|
||||
fromDenomination: 'WEI',
|
||||
toDenomination: 'ETH',
|
||||
toNumericBase: 'dec',
|
||||
numberOfDecimals: 6,
|
||||
},
|
||||
);
|
||||
return ethReceived;
|
||||
}
|
||||
const txReceiptLogs = txReceipt?.logs;
|
||||
if (txReceiptLogs && txReceipt?.status !== '0x0') {
|
||||
const tokenTransferLog = txReceiptLogs.find((txReceiptLog) => {
|
||||
const isTokenTransfer =
|
||||
txReceiptLog.topics &&
|
||||
txReceiptLog.topics[0] === TOKEN_TRANSFER_LOG_TOPIC_HASH;
|
||||
const isTransferFromGivenToken = txReceiptLog.address === tokenAddress;
|
||||
const isTransferFromGivenAddress =
|
||||
txReceiptLog.topics &&
|
||||
txReceiptLog.topics[2] &&
|
||||
txReceiptLog.topics[2].match(accountAddress.slice(2));
|
||||
return (
|
||||
isTokenTransfer &&
|
||||
isTransferFromGivenToken &&
|
||||
isTransferFromGivenAddress
|
||||
);
|
||||
});
|
||||
return tokenTransferLog
|
||||
? toPrecisionWithoutTrailingZeros(
|
||||
calcTokenAmount(tokenTransferLog.data, tokenDecimals).toString(10),
|
||||
6,
|
||||
)
|
||||
: '';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function formatSwapsValueForDisplay(destinationAmount) {
|
||||
let amountToDisplay = toPrecisionWithoutTrailingZeros(destinationAmount, 12);
|
||||
if (amountToDisplay.match(/e[+-]/u)) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import nock from 'nock';
|
||||
import { MOCKS } from '../../../test/jest';
|
||||
import { CHAIN_IDS, CURRENCY_SYMBOLS } from '../../../shared/constants/network';
|
||||
import { getSwapsTokensReceivedFromTxMeta } from '../../../shared/lib/transactions-controller-utils';
|
||||
import {
|
||||
SWAPS_CHAINID_CONTRACT_ADDRESS_MAP,
|
||||
SWAPS_CHAINID_DEFAULT_TOKEN_MAP,
|
||||
@ -13,6 +14,10 @@ import {
|
||||
GOERLI,
|
||||
AVALANCHE,
|
||||
} from '../../../shared/constants/swaps';
|
||||
import {
|
||||
fetchTradesInfo,
|
||||
shouldEnableDirectWrapping,
|
||||
} from '../../../shared/lib/swaps-utils';
|
||||
import {
|
||||
TOKENS,
|
||||
EXPECTED_TOKENS_RESULT,
|
||||
@ -21,7 +26,6 @@ import {
|
||||
TOP_ASSETS,
|
||||
} from './swaps-util-test-constants';
|
||||
import {
|
||||
fetchTradesInfo,
|
||||
fetchTokens,
|
||||
fetchAggregatorMetadata,
|
||||
fetchTopAssets,
|
||||
@ -29,12 +33,10 @@ import {
|
||||
getNetworkNameByChainId,
|
||||
getSwapsLivenessForNetwork,
|
||||
countDecimals,
|
||||
shouldEnableDirectWrapping,
|
||||
showRemainingTimeInMinAndSec,
|
||||
getSwapsTokensReceivedFromTxMeta,
|
||||
} from './swaps.util';
|
||||
|
||||
jest.mock('../../helpers/utils/storage-helpers.js', () => ({
|
||||
jest.mock('../../../shared/lib/storage-helpers', () => ({
|
||||
getStorageItem: jest.fn(),
|
||||
setStorageItem: jest.fn(),
|
||||
}));
|
||||
|
@ -66,8 +66,6 @@ import {
|
||||
} from '../../../selectors';
|
||||
import { getNativeCurrency, getTokens } from '../../../ducks/metamask/metamask';
|
||||
|
||||
import { toPrecisionWithoutTrailingZeros } from '../../../helpers/utils/util';
|
||||
|
||||
import {
|
||||
safeRefetchQuotes,
|
||||
setCustomApproveTxData,
|
||||
@ -84,19 +82,11 @@ import {
|
||||
AWAITING_SWAP_ROUTE,
|
||||
} from '../../../helpers/constants/routes';
|
||||
import {
|
||||
calcTokenAmount,
|
||||
calcTokenValue,
|
||||
getTokenValueParam,
|
||||
} from '../../../helpers/utils/token-util';
|
||||
import {
|
||||
decimalToHex,
|
||||
decGWEIToHexWEI,
|
||||
hexWEIToDecGWEI,
|
||||
addHexes,
|
||||
decWEIToDecETH,
|
||||
} from '../../../helpers/utils/conversions.util';
|
||||
import MainQuoteSummary from '../main-quote-summary';
|
||||
import { calcGasTotal } from '../../send/send.utils';
|
||||
import { getCustomTxParamsData } from '../../confirm-approve/confirm-approve.util';
|
||||
import ActionableMessage from '../../../components/ui/actionable-message/actionable-message';
|
||||
import {
|
||||
@ -114,6 +104,15 @@ import Box from '../../../components/ui/box';
|
||||
import { EVENT } from '../../../../shared/constants/metametrics';
|
||||
import { isEqualCaseInsensitive } from '../../../../shared/modules/string-utils';
|
||||
import { parseStandardTokenTransactionData } from '../../../../shared/modules/transaction.utils';
|
||||
import { getTokenValueParam } from '../../../../shared/lib/metamask-controller-utils';
|
||||
import {
|
||||
calcGasTotal,
|
||||
calcTokenAmount,
|
||||
decimalToHex,
|
||||
hexWEIToDecGWEI,
|
||||
toPrecisionWithoutTrailingZeros,
|
||||
} from '../../../../shared/lib/transactions-controller-utils';
|
||||
import { calcTokenValue } from '../../../../shared/lib/swaps-utils';
|
||||
import ViewQuotePriceDifference from './view-quote-price-difference';
|
||||
|
||||
let intervalId;
|
||||
|
@ -5,13 +5,13 @@ import getCaretCoordinates from 'textarea-caret';
|
||||
import Button from '../../components/ui/button';
|
||||
import TextField from '../../components/ui/text-field';
|
||||
import Mascot from '../../components/ui/mascot';
|
||||
import { SUPPORT_LINK } from '../../helpers/constants/common';
|
||||
import { DEFAULT_ROUTE } from '../../helpers/constants/routes';
|
||||
import {
|
||||
EVENT,
|
||||
EVENT_NAMES,
|
||||
CONTEXT_PROPS,
|
||||
} from '../../../shared/constants/metametrics';
|
||||
import { SUPPORT_LINK } from '../../../shared/lib/ui-utils';
|
||||
|
||||
export default class UnlockPage extends Component {
|
||||
static contextTypes = {
|
||||
|
@ -1,6 +1,5 @@
|
||||
import { createSelector } from 'reselect';
|
||||
import txHelper from '../helpers/utils/tx-helper';
|
||||
import { calcTokenAmount } from '../helpers/utils/token-util';
|
||||
import {
|
||||
roundExponential,
|
||||
getValueFromWeiHex,
|
||||
@ -26,6 +25,7 @@ import {
|
||||
getMinimumGasTotalInHexWei,
|
||||
} from '../../shared/modules/gas.utils';
|
||||
import { isEqualCaseInsensitive } from '../../shared/modules/string-utils';
|
||||
import { calcTokenAmount } from '../../shared/lib/transactions-controller-utils';
|
||||
import { getAveragePriceEstimateInHexWEI } from './custom-gas';
|
||||
import { getCurrentChainId, deprecatedGetCurrentNetworkId } from './selectors';
|
||||
import { checkNetworkAndAccountSupports1559 } from '.';
|
||||
|
@ -6,7 +6,6 @@ import {
|
||||
import { formatCurrency } from '../helpers/utils/confirm-tx.util';
|
||||
import { decEthToConvertedCurrency as ethTotalToConvertedCurrency } from '../helpers/utils/conversions.util';
|
||||
import { formatETHFee } from '../helpers/utils/formatters';
|
||||
import { calcGasTotal } from '../pages/send/send.utils';
|
||||
|
||||
import { getGasLimit, getGasPrice } from '../ducks/send';
|
||||
import {
|
||||
@ -19,6 +18,7 @@ import {
|
||||
isEIP1559Network,
|
||||
} from '../ducks/metamask/metamask';
|
||||
import { GAS_ESTIMATE_TYPES } from '../helpers/constants/common';
|
||||
import { calcGasTotal } from '../../shared/lib/transactions-controller-utils';
|
||||
import { getCurrentCurrency, getIsMainnet, getShouldShowFiat } from '.';
|
||||
|
||||
const NUMBER_OF_DECIMALS_SM_BTNS = 5;
|
||||
|
@ -42,10 +42,7 @@ import {
|
||||
getAccountByAddress,
|
||||
getURLHostName,
|
||||
} from '../helpers/utils/util';
|
||||
import {
|
||||
getValueFromWeiHex,
|
||||
hexToDecimal,
|
||||
} from '../helpers/utils/conversions.util';
|
||||
import { getValueFromWeiHex } from '../helpers/utils/conversions.util';
|
||||
|
||||
import { TEMPLATED_CONFIRMATION_MESSAGE_TYPES } from '../pages/confirmation/templates';
|
||||
import { STATIC_MAINNET_TOKEN_LIST } from '../../shared/constants/tokens';
|
||||
@ -68,6 +65,7 @@ import { isEqualCaseInsensitive } from '../../shared/modules/string-utils';
|
||||
///: BEGIN:ONLY_INCLUDE_IN(flask)
|
||||
import { SNAPS_VIEW_ROUTE } from '../helpers/constants/routes';
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
import { hexToDecimal } from '../../shared/lib/metamask-controller-utils';
|
||||
|
||||
/**
|
||||
* One of the only remaining valid uses of selecting the network subkey of the
|
||||
|
@ -3,7 +3,6 @@ import {
|
||||
PRIORITY_STATUS_HASH,
|
||||
PENDING_STATUS_HASH,
|
||||
} from '../helpers/constants/transactions';
|
||||
import { hexToDecimal } from '../helpers/utils/conversions.util';
|
||||
import txHelper from '../helpers/utils/tx-helper';
|
||||
import {
|
||||
TRANSACTION_STATUSES,
|
||||
@ -11,6 +10,7 @@ import {
|
||||
SMART_TRANSACTION_STATUSES,
|
||||
} from '../../shared/constants/transaction';
|
||||
import { transactionMatchesNetwork } from '../../shared/modules/transaction.utils';
|
||||
import { hexToDecimal } from '../../shared/lib/metamask-controller-utils';
|
||||
import {
|
||||
getCurrentChainId,
|
||||
deprecatedGetCurrentNetworkId,
|
||||
|
@ -2,12 +2,8 @@ import log from 'loglevel';
|
||||
import { captureException } from '@sentry/browser';
|
||||
import { capitalize, isEqual } from 'lodash';
|
||||
import getBuyUrl from '../../app/scripts/lib/buy-url';
|
||||
import {
|
||||
fetchLocale,
|
||||
loadRelativeTimeFormatLocaleData,
|
||||
} from '../helpers/utils/i18n-helper';
|
||||
import { getMethodDataAsync } from '../helpers/utils/transactions.util';
|
||||
import switchDirection from '../helpers/utils/switch-direction';
|
||||
import switchDirection from '../../shared/lib/switch-direction';
|
||||
import {
|
||||
ENVIRONMENT_TYPE_NOTIFICATION,
|
||||
ORIGIN_METAMASK,
|
||||
@ -17,7 +13,6 @@ import {
|
||||
import { hasUnconfirmedTransactions } from '../helpers/utils/confirm-tx.util';
|
||||
import txHelper from '../helpers/utils/tx-helper';
|
||||
import { getEnvironmentType, addHexPrefix } from '../../app/scripts/lib/util';
|
||||
import { decimalToHex } from '../helpers/utils/conversions.util';
|
||||
import {
|
||||
getMetaMaskAccounts,
|
||||
getPermittedAccountsForCurrentTab,
|
||||
@ -46,6 +41,11 @@ import { isEqualCaseInsensitive } from '../../shared/modules/string-utils';
|
||||
import { NOTIFICATIONS_EXPIRATION_DELAY } from '../helpers/constants/notifications';
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
import { setNewCustomNetworkAdded } from '../ducks/app/app';
|
||||
import { decimalToHex } from '../../shared/lib/transactions-controller-utils';
|
||||
import {
|
||||
fetchLocale,
|
||||
loadRelativeTimeFormatLocaleData,
|
||||
} from '../helpers/utils/i18n-helper';
|
||||
import * as actionConstants from './actionConstants';
|
||||
import {
|
||||
generateActionId,
|
||||
|
Loading…
Reference in New Issue
Block a user