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>
feature/default_network_editable
Filip Sekulic 2 years ago committed by GitHub
parent c2b7690119
commit 6e13524bcd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      .eslintrc.js
  2. 1
      .mocharc.js
  3. 11
      app/scripts/controllers/swaps.js
  4. 16
      app/scripts/controllers/transactions/index.js
  5. 2
      app/scripts/controllers/transactions/index.test.js
  6. 2
      app/scripts/lib/metaRPCClientFactory.js
  7. 10
      app/scripts/metamask-controller.js
  8. 4
      app/scripts/ui.js
  9. 7
      development/verify-locale-strings.js
  10. 1
      jest.config.js
  11. 24
      shared/lib/error-utils.js
  12. 10
      shared/lib/error-utils.test.js
  13. 4
      shared/lib/fetch-with-cache.js
  14. 2
      shared/lib/fetch-with-cache.test.js
  15. 12
      shared/lib/metamask-controller-utils.js
  16. 0
      shared/lib/storage-helpers.js
  17. 320
      shared/lib/swaps-utils.js
  18. 0
      shared/lib/switch-direction.js
  19. 20
      shared/lib/token-util.js
  20. 172
      shared/lib/transactions-controller-utils.js
  21. 7
      shared/lib/ui-utils.js
  22. 2
      ui/components/app/account-menu/account-menu.component.js
  23. 22
      ui/components/app/asset-list/asset-list.test.js
  24. 7
      ui/components/app/cancel-speedup-popover/cancel-speedup-popover.test.js
  25. 31
      ui/components/app/create-new-vault/create-new-vault.test.js
  26. 10
      ui/components/app/edit-gas-fee-popover/edit-gas-item/useGasItemFeeDetails.js
  27. 8
      ui/components/app/edit-gas-popover/edit-gas-popover.component.js
  28. 8
      ui/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.container.js
  29. 10
      ui/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js
  30. 2
      ui/components/app/modals/edit-approval-permission/edit-approval-permission.component.js
  31. 4
      ui/components/app/transaction-decoding/transaction-decoding.component.js
  32. 22
      ui/components/app/transaction-list/transaction-list.test.js
  33. 121
      ui/components/app/whats-new-popup/whats-new-popup.test.js
  34. 60
      ui/components/ui/account-list/account-list.test.js
  35. 2
      ui/components/ui/hex-to-decimal/hex-to-decimal.component.js
  36. 2
      ui/components/ui/new-network-info/new-network-info.js
  37. 2
      ui/components/ui/new-network-info/new-network-info.test.js
  38. 35
      ui/components/ui/nickname-popover/nickname-popover.test.js
  39. 29
      ui/components/ui/update-nickname-popover/update-nickname-popover.test.js
  40. 2
      ui/ducks/send/helpers.js
  41. 8
      ui/ducks/send/send.js
  42. 10
      ui/ducks/swaps/swaps.js
  43. 2
      ui/ducks/swaps/swaps.test.js
  44. 3
      ui/helpers/constants/common.js
  45. 1
      ui/helpers/constants/critical-error.js
  46. 1
      ui/helpers/constants/error-keys.js
  47. 5
      ui/helpers/constants/transactions.js
  48. 23
      ui/helpers/utils/conversions.util.js
  49. 2
      ui/helpers/utils/gas.js
  50. 1
      ui/helpers/utils/i18n-helper.js
  51. 17
      ui/helpers/utils/token-util.js
  52. 2
      ui/helpers/utils/transactions.util.js
  53. 66
      ui/helpers/utils/util.js
  54. 8
      ui/helpers/utils/util.test.js
  55. 6
      ui/hooks/gasFeeInput/useGasEstimates.js
  56. 7
      ui/hooks/gasFeeInput/useGasEstimates.test.js
  57. 2
      ui/hooks/gasFeeInput/useGasFeeInputs.js
  58. 2
      ui/hooks/gasFeeInput/useGasPriceInput.js
  59. 10
      ui/hooks/gasFeeInput/useMaxFeePerGasInput.js
  60. 2
      ui/hooks/gasFeeInput/useMaxFeePerGasInput.test.js
  61. 2
      ui/hooks/gasFeeInput/useMaxPriorityFeePerGasInput.js
  62. 6
      ui/hooks/gasFeeInput/useTransactionFunctions.js
  63. 2
      ui/hooks/useSwappedTokenValue.js
  64. 6
      ui/hooks/useTokenDisplayValue.js
  65. 7
      ui/hooks/useTokenDisplayValue.test.js
  66. 2
      ui/hooks/useTransactionDisplayData.js
  67. 25
      ui/index.js
  68. 2
      ui/index.test.js
  69. 6
      ui/pages/confirm-approve/confirm-approve.js
  70. 8
      ui/pages/confirm-approve/confirm-approve.util.js
  71. 6
      ui/pages/confirm-token-transaction-base/confirm-token-transaction-base.js
  72. 8
      ui/pages/confirm-transaction-base/confirm-transaction-base.component.js
  73. 3
      ui/pages/confirm-transaction-base/confirm-transaction-base.container.js
  74. 3
      ui/pages/confirmation/templates/add-ethereum-chain.js
  75. 6
      ui/pages/home/home.component.js
  76. 2
      ui/pages/send/send-content/send-gas-row/send-gas-row.container.js
  77. 2
      ui/pages/send/send-content/send-gas-row/send-gas-row.stories.js
  78. 11
      ui/pages/send/send.utils.js
  79. 13
      ui/pages/send/send.utils.test.js
  80. 22
      ui/pages/settings/experimental-tab/experimental-tab.test.js
  81. 6
      ui/pages/settings/info-tab/info-tab.component.js
  82. 4
      ui/pages/settings/networks-tab/networks-form/networks-form.js
  83. 2
      ui/pages/swaps/awaiting-swap/awaiting-swap.js
  84. 10
      ui/pages/swaps/build-quote/build-quote.js
  85. 2
      ui/pages/swaps/exchange-rate-display/exchange-rate-display.js
  86. 2
      ui/pages/swaps/index.js
  87. 6
      ui/pages/swaps/main-quote-summary/main-quote-summary.js
  88. 2
      ui/pages/swaps/smart-transaction-status/smart-transaction-status.js
  89. 293
      ui/pages/swaps/swaps.util.js
  90. 10
      ui/pages/swaps/swaps.util.test.js
  91. 19
      ui/pages/swaps/view-quote/view-quote.js
  92. 2
      ui/pages/unlock-page/unlock-page.component.js
  93. 2
      ui/selectors/confirm-transaction.js
  94. 2
      ui/selectors/custom-gas.js
  95. 6
      ui/selectors/selectors.js
  96. 2
      ui/selectors/transactions.js
  97. 12
      ui/store/actions.js

@ -269,6 +269,7 @@ module.exports = {
'test/jest/*.js', 'test/jest/*.js',
'ui/**/*.test.js', 'ui/**/*.test.js',
'ui/__mocks__/*.js', 'ui/__mocks__/*.js',
'shared/lib/error-utils.test.js',
], ],
extends: ['@metamask/eslint-config-jest'], extends: ['@metamask/eslint-config-jest'],
parserOptions: { parserOptions: {

@ -7,6 +7,7 @@ module.exports = {
'./app/scripts/platforms/*.test.js', './app/scripts/platforms/*.test.js',
'./app/scripts/controllers/network/**/*.test.js', './app/scripts/controllers/network/**/*.test.js',
'./app/scripts/controllers/permissions/**/*.test.js', './app/scripts/controllers/permissions/**/*.test.js',
'./app/scripts/constants/error-utils.test.js',
], ],
recursive: true, recursive: true,
require: ['test/env.js', 'test/setup.js'], require: ['test/env.js', 'test/setup.js'],

@ -4,8 +4,6 @@ import BigNumber from 'bignumber.js';
import { ObservableStore } from '@metamask/obs-store'; import { ObservableStore } from '@metamask/obs-store';
import { mapValues, cloneDeep } from 'lodash'; import { mapValues, cloneDeep } from 'lodash';
import abi from 'human-standard-token-abi'; import abi from 'human-standard-token-abi';
import { calcTokenAmount } from '../../../ui/helpers/utils/token-util';
import { calcGasTotal } from '../../../ui/pages/send/send.utils';
import { import {
conversionUtil, conversionUtil,
decGWEIToHexWEI, decGWEIToHexWEI,
@ -30,10 +28,15 @@ import { isSwapsDefaultTokenAddress } from '../../../shared/modules/swaps.utils'
import { import {
fetchTradesInfo as defaultFetchTradesInfo, fetchTradesInfo as defaultFetchTradesInfo,
getBaseApi, getBaseApi,
} from '../../../ui/pages/swaps/swaps.util'; } from '../../../shared/lib/swaps-utils';
import fetchWithCache from '../../../ui/helpers/utils/fetch-with-cache'; import fetchWithCache from '../../../shared/lib/fetch-with-cache';
import { MINUTE, SECOND } from '../../../shared/constants/time'; import { MINUTE, SECOND } from '../../../shared/constants/time';
import { isEqualCaseInsensitive } from '../../../shared/modules/string-utils'; import { isEqualCaseInsensitive } from '../../../shared/modules/string-utils';
import {
calcGasTotal,
calcTokenAmount,
} from '../../../shared/lib/transactions-controller-utils';
import { NETWORK_EVENTS } from './network'; 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 // 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, addHexPrefix,
getChainType, getChainType,
} from '../../lib/util'; } 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 { import {
TRANSACTION_STATUSES, TRANSACTION_STATUSES,
TRANSACTION_TYPES, TRANSACTION_TYPES,
@ -32,7 +25,6 @@ import {
TRANSACTION_ENVELOPE_TYPES, TRANSACTION_ENVELOPE_TYPES,
TRANSACTION_EVENTS, TRANSACTION_EVENTS,
} from '../../../../shared/constants/transaction'; } from '../../../../shared/constants/transaction';
import { TRANSACTION_ENVELOPE_TYPE_NAMES } from '../../../../ui/helpers/constants/transactions';
import { METAMASK_CONTROLLER_EVENTS } from '../../metamask-controller'; import { METAMASK_CONTROLLER_EVENTS } from '../../metamask-controller';
import { import {
GAS_LIMITS, GAS_LIMITS,
@ -56,6 +48,14 @@ import {
isEIP1559Transaction, isEIP1559Transaction,
} from '../../../../shared/modules/transaction.utils'; } from '../../../../shared/modules/transaction.utils';
import { ORIGIN_METAMASK } from '../../../../shared/constants/app'; 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 TransactionStateManager from './tx-state-manager';
import TxGasUtil from './tx-gas-utils'; import TxGasUtil from './tx-gas-utils';
import PendingTransactionTracker from './pending-tx-tracker'; import PendingTransactionTracker from './pending-tx-tracker';

@ -25,9 +25,9 @@ import {
GAS_ESTIMATE_TYPES, GAS_ESTIMATE_TYPES,
GAS_RECOMMENDATIONS, GAS_RECOMMENDATIONS,
} from '../../../../shared/constants/gas'; } from '../../../../shared/constants/gas';
import { TRANSACTION_ENVELOPE_TYPE_NAMES } from '../../../../ui/helpers/constants/transactions';
import { METAMASK_CONTROLLER_EVENTS } from '../../metamask-controller'; import { METAMASK_CONTROLLER_EVENTS } from '../../metamask-controller';
import { ORIGIN_METAMASK } from '../../../../shared/constants/app'; import { ORIGIN_METAMASK } from '../../../../shared/constants/app';
import { TRANSACTION_ENVELOPE_TYPE_NAMES } from '../../../../shared/lib/transactions-controller-utils';
import TransactionController from '.'; import TransactionController from '.';
const noop = () => true; const noop = () => true;

@ -1,7 +1,7 @@
import { EthereumRpcError } from 'eth-rpc-errors'; import { EthereumRpcError } from 'eth-rpc-errors';
import SafeEventEmitter from 'safe-event-emitter'; import SafeEventEmitter from 'safe-event-emitter';
import createRandomId from '../../../shared/modules/random-id'; 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 {} class DisconnectError extends Error {}

@ -90,14 +90,14 @@ import {
} from '../../shared/constants/app'; } from '../../shared/constants/app';
import { EVENT, EVENT_NAMES } from '../../shared/constants/metametrics'; import { EVENT, EVENT_NAMES } from '../../shared/constants/metametrics';
import { hexToDecimal } from '../../ui/helpers/utils/conversions.util'; import { getTokenIdParam } from '../../ui/helpers/utils/token-util';
import {
getTokenIdParam,
getTokenValueParam,
} from '../../ui/helpers/utils/token-util';
import { isEqualCaseInsensitive } from '../../shared/modules/string-utils'; import { isEqualCaseInsensitive } from '../../shared/modules/string-utils';
import { parseStandardTokenTransactionData } from '../../shared/modules/transaction.utils'; import { parseStandardTokenTransactionData } from '../../shared/modules/transaction.utils';
import { STATIC_MAINNET_TOKEN_LIST } from '../../shared/constants/tokens'; import { STATIC_MAINNET_TOKEN_LIST } from '../../shared/constants/tokens';
import {
getTokenValueParam,
hexToDecimal,
} from '../../shared/lib/metamask-controller-utils';
import { import {
onMessageReceived, onMessageReceived,
checkForMultipleVersionsRunning, checkForMultipleVersionsRunning,

@ -17,8 +17,8 @@ import {
ENVIRONMENT_TYPE_POPUP, ENVIRONMENT_TYPE_POPUP,
} from '../../shared/constants/app'; } from '../../shared/constants/app';
import { isManifestV3 } from '../../shared/modules/mv3.utils'; import { isManifestV3 } from '../../shared/modules/mv3.utils';
import { SUPPORT_LINK } from '../../ui/helpers/constants/common'; import { SUPPORT_LINK } from '../../shared/lib/ui-utils';
import { getErrorHtml } from '../../ui/helpers/utils/error-utils'; import { getErrorHtml } from '../../shared/lib/error-utils';
import ExtensionPlatform from './platforms/extension'; import ExtensionPlatform from './platforms/extension';
import { setupMultiplex } from './lib/stream-utils'; import { setupMultiplex } from './lib/stream-utils';
import { getEnvironmentType } from './lib/util'; import { getEnvironmentType } from './lib/util';

@ -177,9 +177,12 @@ async function verifyEnglishLocale() {
'ui/pages/confirmation/templates/*.js', 'ui/pages/confirmation/templates/*.js',
]; ];
const testGlob = '**/*.test.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], ignore: [...globsToStrictSearch, testGlob],
}); },
);
const javascriptFilesToStrictSearch = await glob(globsToStrictSearch, { const javascriptFilesToStrictSearch = await glob(globsToStrictSearch, {
ignore: [testGlob], ignore: [testGlob],
}); });

@ -42,6 +42,7 @@ module.exports = {
'<rootDir>app/scripts/controllers/network/**/*.test.js', '<rootDir>app/scripts/controllers/network/**/*.test.js',
'<rootDir>/app/scripts/controllers/permissions/**/*.test.js', '<rootDir>/app/scripts/controllers/permissions/**/*.test.js',
'<rootDir>/app/scripts/lib/createRPCMethodTrackingMiddleware.test.js', '<rootDir>/app/scripts/lib/createRPCMethodTrackingMiddleware.test.js',
'<rootDir>/app/scripts/constants/error-utils.test.js',
], ],
testTimeout: 2500, testTimeout: 2500,
// We have to specify the environment we are running in, which is jsdom. The // 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 { memoize } from 'lodash';
import { setupLocale } from '../..'; 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'; 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) => { const getLocaleContext = (currentLocaleMessages, enLocaleMessages) => {
return (key) => { return (key) => {
let message = currentLocaleMessages[key]?.message; 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 { getErrorHtml } from './error-utils';
import { fetchLocale } from './i18n-helper';
jest.mock('./i18n-helper', () => ({ jest.mock('../../ui/helpers/utils/i18n-helper', () => ({
fetchLocale: jest.fn(), fetchLocale: jest.fn(),
loadRelativeTimeFormatLocaleData: jest.fn(), loadRelativeTimeFormatLocaleData: jest.fn(),
})); }));
describe('Error utils Tests', () => { describe('Error utils Tests', function () {
it('should get error html', async () => { it('should get error html', async function () {
const mockStore = { const mockStore = {
localeMessages: { localeMessages: {
current: { current: {

@ -1,5 +1,5 @@
import { MINUTE, SECOND } from '../../../shared/constants/time'; import { MINUTE, SECOND } from '../constants/time';
import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout'; import getFetchWithTimeout from '../modules/fetch-with-timeout';
import { getStorageItem, setStorageItem } from './storage-helpers'; import { getStorageItem, setStorageItem } from './storage-helpers';
const fetchWithCache = async ( const fetchWithCache = async (

@ -3,7 +3,7 @@ import sinon from 'sinon';
import { getStorageItem, setStorageItem } from './storage-helpers'; import { getStorageItem, setStorageItem } from './storage-helpers';
jest.mock('./storage-helpers.js', () => ({ jest.mock('./storage-helpers', () => ({
getStorageItem: jest.fn(), getStorageItem: jest.fn(),
setStorageItem: jest.fn(), setStorageItem: jest.fn(),
})); }));

@ -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();
}

@ -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;
}

@ -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()
);
}

@ -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',
});
}

@ -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 UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display';
import { import {
PRIMARY, PRIMARY,
SUPPORT_LINK,
///: BEGIN:ONLY_INCLUDE_IN(beta,flask) ///: BEGIN:ONLY_INCLUDE_IN(beta,flask)
SUPPORT_REQUEST_LINK, SUPPORT_REQUEST_LINK,
///: END:ONLY_INCLUDE_IN ///: END:ONLY_INCLUDE_IN
@ -41,6 +40,7 @@ import IconImport from '../../ui/icon/icon-import';
import Button from '../../ui/button'; import Button from '../../ui/button';
import SearchIcon from '../../ui/icon/search-icon'; import SearchIcon from '../../ui/icon/search-icon';
import { SUPPORT_LINK } from '../../../../shared/lib/ui-utils';
import KeyRingLabel from './keyring-label'; import KeyRingLabel from './keyring-label';
export function AccountMenuItem(props) { export function AccountMenuItem(props) {

@ -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 mockState from '../../../../test/data/mock-state.json';
import { GasFeeContextProvider } from '../../../contexts/gasFee'; import { GasFeeContextProvider } from '../../../contexts/gasFee';
import configureStore from '../../../store/store'; import configureStore from '../../../store/store';
import { import { decGWEIToHexWEI } from '../../../helpers/utils/conversions.util';
hexWEIToDecETH,
decGWEIToHexWEI,
} from '../../../helpers/utils/conversions.util';
import InfoTooltip from '../../ui/info-tooltip'; import InfoTooltip from '../../ui/info-tooltip';
import { hexWEIToDecETH } from '../../../../shared/lib/transactions-controller-utils';
import CancelSpeedupPopover from './cancel-speedup-popover'; import CancelSpeedupPopover from './cancel-speedup-popover';
const MAXFEEPERGAS_ABOVE_MOCK_MEDIUM_HEX = '0x174876e800'; const MAXFEEPERGAS_ABOVE_MOCK_MEDIUM_HEX = '0x174876e800';

@ -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, PRIORITY_LEVELS,
} from '../../../../../shared/constants/gas'; } from '../../../../../shared/constants/gas';
import { getMaximumGasTotalInHexWei } from '../../../../../shared/modules/gas.utils'; import { getMaximumGasTotalInHexWei } from '../../../../../shared/modules/gas.utils';
import { import { decGWEIToHexWEI } from '../../../../helpers/utils/conversions.util';
decGWEIToHexWEI,
decimalToHex,
hexWEIToDecGWEI,
} from '../../../../helpers/utils/conversions.util';
import { import {
addTenPercentAndRound, addTenPercentAndRound,
gasEstimateGreaterThanGasUsedPlusTenPercent, gasEstimateGreaterThanGasUsedPlusTenPercent,
} from '../../../../helpers/utils/gas'; } from '../../../../helpers/utils/gas';
import { getAdvancedGasFeeValues } from '../../../../selectors'; import { getAdvancedGasFeeValues } from '../../../../selectors';
import { useGasFeeContext } from '../../../../contexts/gasFee'; import { useGasFeeContext } from '../../../../contexts/gasFee';
import {
decimalToHex,
hexWEIToDecGWEI,
} from '../../../../../shared/lib/transactions-controller-utils';
import { useCustomTimeEstimate } from './useCustomTimeEstimate'; import { useCustomTimeEstimate } from './useCustomTimeEstimate';
export const useGasItemFeeDetails = (priorityLevel) => { export const useGasItemFeeDetails = (priorityLevel) => {

@ -11,11 +11,7 @@ import {
CUSTOM_GAS_ESTIMATE, CUSTOM_GAS_ESTIMATE,
} from '../../../../shared/constants/gas'; } from '../../../../shared/constants/gas';
import { import { decGWEIToHexWEI } from '../../../helpers/utils/conversions.util';
decGWEIToHexWEI,
decimalToHex,
hexToDecimal,
} from '../../../helpers/utils/conversions.util';
import Popover from '../../ui/popover'; import Popover from '../../ui/popover';
import Button from '../../ui/button'; import Button from '../../ui/button';
@ -37,6 +33,8 @@ import LoadingHeartBeat from '../../ui/loading-heartbeat';
import { checkNetworkAndAccountSupports1559 } from '../../../selectors'; import { checkNetworkAndAccountSupports1559 } from '../../../selectors';
import { useIncrementedGasFees } from '../../../hooks/useIncrementedGasFees'; import { useIncrementedGasFees } from '../../../hooks/useIncrementedGasFees';
import { isLegacyTransaction } from '../../../helpers/utils/transactions.util'; 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({ export default function EditGasPopover({
popoverTitle = '', popoverTitle = '',

@ -1,11 +1,11 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { decGWEIToHexWEI } from '../../../../helpers/utils/conversions.util';
import { getNetworkSupportsSettingGasFees } from '../../../../selectors/selectors';
import { MIN_GAS_LIMIT_DEC } from '../../../../pages/send/send.constants';
import { import {
decGWEIToHexWEI,
decimalToHex, decimalToHex,
hexWEIToDecGWEI, hexWEIToDecGWEI,
} from '../../../../helpers/utils/conversions.util'; } from '../../../../../shared/lib/transactions-controller-utils';
import { getNetworkSupportsSettingGasFees } from '../../../../selectors/selectors';
import { MIN_GAS_LIMIT_DEC } from '../../../../pages/send/send.constants';
import AdvancedGasInputs from './advanced-gas-inputs.component'; import AdvancedGasInputs from './advanced-gas-inputs.component';
function convertGasPriceForInputs(gasPriceInHexWEI) { function convertGasPriceForInputs(gasPriceInHexWEI) {

@ -43,15 +43,11 @@ import {
import { import {
addHexes, addHexes,
subtractHexWEIsToDec, subtractHexWEIsToDec,
hexWEIToDecGWEI,
getValueFromWeiHex, getValueFromWeiHex,
sumHexWEIsToRenderableFiat, sumHexWEIsToRenderableFiat,
} from '../../../../helpers/utils/conversions.util'; } from '../../../../helpers/utils/conversions.util';
import { formatETHFee } from '../../../../helpers/utils/formatters'; import { formatETHFee } from '../../../../helpers/utils/formatters';
import { import { isBalanceSufficient } from '../../../../pages/send/send.utils';
calcGasTotal,
isBalanceSufficient,
} from '../../../../pages/send/send.utils';
import { MIN_GAS_LIMIT_DEC } from '../../../../pages/send/send.constants'; import { MIN_GAS_LIMIT_DEC } from '../../../../pages/send/send.constants';
import { import {
ASSET_TYPES, ASSET_TYPES,
@ -59,6 +55,10 @@ import {
} from '../../../../../shared/constants/transaction'; } from '../../../../../shared/constants/transaction';
import { GAS_LIMITS } from '../../../../../shared/constants/gas'; import { GAS_LIMITS } from '../../../../../shared/constants/gas';
import { updateGasFees } from '../../../../ducks/metamask/metamask'; import { updateGasFees } from '../../../../ducks/metamask/metamask';
import {
calcGasTotal,
hexWEIToDecGWEI,
} from '../../../../../shared/lib/transactions-controller-utils';
import GasModalPageContainer from './gas-modal-page-container.component'; import GasModalPageContainer from './gas-modal-page-container.component';
const mapStateToProps = (state, ownProps) => { const mapStateToProps = (state, ownProps) => {

@ -6,7 +6,7 @@ import BigNumber from 'bignumber.js';
import Modal from '../../modal'; import Modal from '../../modal';
import Identicon from '../../../ui/identicon'; import Identicon from '../../../ui/identicon';
import TextField from '../../../ui/text-field'; 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); 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 * as Codec from '@truffle/codec';
import Spinner from '../../ui/spinner'; import Spinner from '../../ui/spinner';
import ErrorMessage from '../../ui/error-message'; 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 { getSelectedAccount, getCurrentChainId } from '../../../selectors';
import { hexToDecimal } from '../../../helpers/utils/conversions.util';
import { I18nContext } from '../../../contexts/i18n'; import { I18nContext } from '../../../contexts/i18n';
import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils';
import { hexToDecimal } from '../../../../shared/lib/metamask-controller-utils';
import { transformTxDecoding } from './transaction-decoding.util'; import { transformTxDecoding } from './transaction-decoding.util';
import { import {
FETCH_PROJECT_INFO_URI, FETCH_PROJECT_INFO_URI,

@ -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();
});
});

@ -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();
});
});

@ -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 React, { PureComponent } from 'react';
import PropTypes from 'prop-types'; 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 { export default class HexToDecimal extends PureComponent {
static propTypes = { static propTypes = {

@ -16,7 +16,7 @@ import {
} from '../../../helpers/constants/design-system'; } from '../../../helpers/constants/design-system';
import Typography from '../typography'; import Typography from '../typography';
import { TOKEN_API_METASWAP_CODEFI_URL } from '../../../../shared/constants/tokens'; 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 { import {
getNativeCurrencyImage, getNativeCurrencyImage,
getProvider, getProvider,

@ -5,7 +5,7 @@ import { renderWithProvider } from '../../../../test/lib/render-helpers';
import NewNetworkInfo from './new-network-info'; import NewNetworkInfo from './new-network-info';
const fetchWithCache = const fetchWithCache =
require('../../../helpers/utils/fetch-with-cache').default; require('../../../../shared/lib/fetch-with-cache').default;
const state = { const state = {
metamask: { metamask: {

@ -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 { addHexPrefix } from 'ethereumjs-util';
import abi from 'human-standard-token-abi'; import abi from 'human-standard-token-abi';
import { GAS_LIMITS, MIN_GAS_LIMIT_HEX } from '../../../shared/constants/gas'; 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 { CHAIN_ID_TO_GAS_LIMIT_BUFFER_MAP } from '../../../shared/constants/network';
import { import {
ASSET_TYPES, ASSET_TYPES,
@ -12,7 +13,6 @@ import {
multiplyCurrencies, multiplyCurrencies,
} from '../../../shared/modules/conversion.utils'; } from '../../../shared/modules/conversion.utils';
import { ETH, GWEI } from '../../helpers/constants/common'; import { ETH, GWEI } from '../../helpers/constants/common';
import { calcTokenAmount } from '../../helpers/utils/token-util';
import { import {
addGasBuffer, addGasBuffer,
generateERC20TransferData, generateERC20TransferData,

@ -22,7 +22,6 @@ import {
} from '../../pages/send/send.constants'; } from '../../pages/send/send.constants';
import { import {
calcGasTotal,
isBalanceSufficient, isBalanceSufficient,
isTokenBalanceSufficient, isTokenBalanceSufficient,
} from '../../pages/send/send.utils'; } from '../../pages/send/send.utils';
@ -67,9 +66,7 @@ import {
GAS_FEE_ESTIMATES_UPDATED, GAS_FEE_ESTIMATES_UPDATED,
} from '../../store/actionConstants'; } from '../../store/actionConstants';
import { import {
calcTokenAmount,
getTokenAddressParam, getTokenAddressParam,
getTokenValueParam,
getTokenMetadata, getTokenMetadata,
getTokenIdParam, getTokenIdParam,
} from '../../helpers/utils/token-util'; } 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 { isEqualCaseInsensitive } from '../../../shared/modules/string-utils';
import { getValueFromWeiHex } from '../../helpers/utils/confirm-tx.util'; import { getValueFromWeiHex } from '../../helpers/utils/confirm-tx.util';
import { parseStandardTokenTransactionData } from '../../../shared/modules/transaction.utils'; 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 { import {
estimateGasLimitForSend, estimateGasLimitForSend,
generateTransactionParams, generateTransactionParams,

@ -51,16 +51,12 @@ import {
parseSmartTransactionsError, parseSmartTransactionsError,
stxErrorTypes, stxErrorTypes,
} from '../../pages/swaps/swaps.util'; } from '../../pages/swaps/swaps.util';
import { calcGasTotal } from '../../pages/send/send.utils';
import { import {
decimalToHex,
getValueFromWeiHex, getValueFromWeiHex,
decGWEIToHexWEI, decGWEIToHexWEI,
hexWEIToDecGWEI,
addHexes, addHexes,
} from '../../helpers/utils/conversions.util'; } from '../../helpers/utils/conversions.util';
import { conversionLessThan } from '../../../shared/modules/conversion.utils'; import { conversionLessThan } from '../../../shared/modules/conversion.utils';
import { calcTokenAmount } from '../../helpers/utils/token-util';
import { import {
getSelectedAccount, getSelectedAccount,
getTokenExchangeRates, getTokenExchangeRates,
@ -89,6 +85,12 @@ import {
} from '../../../shared/constants/transaction'; } from '../../../shared/constants/transaction';
import { getGasFeeEstimates } from '../metamask/metamask'; import { getGasFeeEstimates } from '../metamask/metamask';
import { ORIGIN_METAMASK } from '../../../shared/constants/app'; import { ORIGIN_METAMASK } from '../../../shared/constants/app';
import {
calcGasTotal,
calcTokenAmount,
decimalToHex,
hexWEIToDecGWEI,
} from '../../../shared/lib/transactions-controller-utils';
const GAS_PRICES_LOADING_STATES = { const GAS_PRICES_LOADING_STATES = {
INITIAL: 'INITIAL', INITIAL: 'INITIAL',

@ -2,8 +2,8 @@ import nock from 'nock';
import { MOCKS, createSwapsMockStore } from '../../../test/jest'; import { MOCKS, createSwapsMockStore } from '../../../test/jest';
import { setSwapsLiveness, setSwapsFeatureFlags } from '../../store/actions'; import { setSwapsLiveness, setSwapsFeatureFlags } from '../../store/actions';
import { setStorageItem } from '../../helpers/utils/storage-helpers';
import { CHAIN_IDS } from '../../../shared/constants/network'; import { CHAIN_IDS } from '../../../shared/constants/network';
import { setStorageItem } from '../../../shared/lib/storage-helpers';
import * as swaps from './swaps'; import * as swaps from './swaps';
jest.mock('../../store/actions.js', () => ({ jest.mock('../../store/actions.js', () => ({

@ -12,17 +12,14 @@ export const GAS_ESTIMATE_TYPES = {
FASTEST: 'FASTEST', FASTEST: 'FASTEST',
}; };
let _supportLink = 'https://support.metamask.io';
let _supportRequestLink = 'https://metamask.zendesk.com/hc/en-us'; let _supportRequestLink = 'https://metamask.zendesk.com/hc/en-us';
const _contractAddressLink = const _contractAddressLink =
'https://metamask.zendesk.com/hc/en-us/articles/360020028092-What-is-the-known-contract-address-warning-'; 'https://metamask.zendesk.com/hc/en-us/articles/360020028092-What-is-the-known-contract-address-warning-';
///: BEGIN:ONLY_INCLUDE_IN(flask) ///: BEGIN:ONLY_INCLUDE_IN(flask)
_supportLink = 'https://metamask-flask.zendesk.com/hc';
_supportRequestLink = _supportRequestLink =
'https://metamask-flask.zendesk.com/hc/en-us/requests/new'; 'https://metamask-flask.zendesk.com/hc/en-us/requests/new';
///: END:ONLY_INCLUDE_IN ///: END:ONLY_INCLUDE_IN
export const SUPPORT_LINK = _supportLink;
export const SUPPORT_REQUEST_LINK = _supportRequestLink; export const SUPPORT_REQUEST_LINK = _supportRequestLink;
export const CONTRACT_ADDRESS_LINK = _contractAddressLink; 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 INSUFFICIENT_FUNDS_ERROR_KEY = 'insufficientFunds';
export const GAS_LIMIT_TOO_LOW_ERROR_KEY = 'gasLimitTooLow'; export const GAS_LIMIT_TOO_LOW_ERROR_KEY = 'gasLimitTooLow';
export const TRANSACTION_ERROR_KEY = 'transactionError'; 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 ETH_GAS_PRICE_FETCH_WARNING_KEY = 'ethGasPriceFetchWarning';
export const GAS_PRICE_FETCH_FAILURE_ERROR_KEY = 'gasPriceFetchFailed'; export const GAS_PRICE_FETCH_FAILURE_ERROR_KEY = 'gasPriceFetchFailed';
export const GAS_PRICE_EXCESSIVE_ERROR_KEY = 'gasPriceExcessive'; 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]: true,
[TRANSACTION_TYPES.TOKEN_METHOD_TRANSFER_FROM]: 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)); 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({ export function getEthConversionFromWeiHex({
value, value,
fromCurrency = ETH, 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) { export function decETHToDecWEI(decEth) {
return conversionUtil(decEth, { return conversionUtil(decEth, {
fromNumericBase: 'dec', fromNumericBase: 'dec',

@ -6,12 +6,12 @@ import {
EDIT_GAS_MODES, EDIT_GAS_MODES,
} from '../../../shared/constants/gas'; } from '../../../shared/constants/gas';
import { multiplyCurrencies } from '../../../shared/modules/conversion.utils'; import { multiplyCurrencies } from '../../../shared/modules/conversion.utils';
import { hexWEIToDecGWEI } from '../../../shared/lib/transactions-controller-utils';
import { import {
bnGreaterThan, bnGreaterThan,
isNullish, isNullish,
roundToDecimalPlacesRemovingExtraZeroes, roundToDecimalPlacesRemovingExtraZeroes,
} from './util'; } from './util';
import { hexWEIToDecGWEI } from './conversions.util';
export const gasEstimateGreaterThanGasUsedPlusTenPercent = ( export const gasEstimateGreaterThanGasUsedPlusTenPercent = (
gasUsed, gasUsed,

@ -2,7 +2,6 @@
import React from 'react'; import React from 'react';
import log from 'loglevel'; import log from 'loglevel';
import * as Sentry from '@sentry/browser'; import * as Sentry from '@sentry/browser';
import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout'; import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout';
const fetchWithTimeout = getFetchWithTimeout(); const fetchWithTimeout = getFetchWithTimeout();

@ -1,5 +1,4 @@
import log from 'loglevel'; import log from 'loglevel';
import BigNumber from 'bignumber.js';
import { import {
conversionUtil, conversionUtil,
multiplyCurrencies, multiplyCurrencies,
@ -8,6 +7,8 @@ import { getTokenStandardAndDetails } from '../../store/actions';
import { isEqualCaseInsensitive } from '../../../shared/modules/string-utils'; import { isEqualCaseInsensitive } from '../../../shared/modules/string-utils';
import { parseStandardTokenTransactionData } from '../../../shared/modules/transaction.utils'; import { parseStandardTokenTransactionData } from '../../../shared/modules/transaction.utils';
import { ERC20 } from '../../../shared/constants/transaction'; 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 * as util from './util';
import { formatCurrency } from './confirm-tx.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 * 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 * (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. * @param {object} tokenData - ethers Interface token data.
* @returns {string | undefined} A decimal string value. * @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., * 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 * These are the parsed tokenId values returned by `parseStandardTokenTransactionData` as defined

@ -10,7 +10,7 @@ import {
} from '../../../shared/constants/transaction'; } from '../../../shared/constants/transaction';
import { addCurrencies } from '../../../shared/modules/conversion.utils'; import { addCurrencies } from '../../../shared/modules/conversion.utils';
import { readAddressAsContract } from '../../../shared/modules/contract-utils'; import { readAddressAsContract } from '../../../shared/modules/contract-utils';
import fetchWithCache from './fetch-with-cache'; import fetchWithCache from '../../../shared/lib/fetch-with-cache';
/** /**
* @typedef EthersContractCall * @typedef EthersContractCall

@ -5,7 +5,6 @@ import * as ethUtil from 'ethereumjs-util';
import { DateTime } from 'luxon'; import { DateTime } from 'luxon';
import { getFormattedIpfsUrl } from '@metamask/controllers/dist/util'; import { getFormattedIpfsUrl } from '@metamask/controllers/dist/util';
import slip44 from '@metamask/slip44'; import slip44 from '@metamask/slip44';
import { addHexPrefix } from '../../../app/scripts/lib/util';
import { CHAIN_IDS } from '../../../shared/constants/network'; import { CHAIN_IDS } from '../../../shared/constants/network';
import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils'; import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils';
import { import {
@ -293,71 +292,6 @@ export function checkExistingAddresses(address, list = []) {
return list.some(matchesAddress); 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) { export function bnGreaterThan(a, b) {
if (a === null || a === undefined || b === null || b === undefined) { if (a === null || a === undefined || b === null || b === undefined) {
return null; return null;

@ -1,4 +1,6 @@
import { BN } from 'ethereumjs-util'; 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'; import * as util from './util';
describe('util', () => { describe('util', () => {
@ -279,9 +281,7 @@ describe('util', () => {
testData.forEach(({ args, result }) => { testData.forEach(({ args, result }) => {
it(`should return ${result} when passed number ${args[0]} and precision ${args[1]}`, () => { it(`should return ${result} when passed number ${args[0]} and precision ${args[1]}`, () => {
expect(util.toPrecisionWithoutTrailingZeros(...args)).toStrictEqual( expect(toPrecisionWithoutTrailingZeros(...args)).toStrictEqual(result);
result,
);
}); });
}); });
}); });
@ -289,7 +289,7 @@ describe('util', () => {
describe('addHexPrefixToObjectValues()', () => { describe('addHexPrefixToObjectValues()', () => {
it('should return a new object with the same properties with a 0x prefix', () => { it('should return a new object with the same properties with a 0x prefix', () => {
expect( expect(
util.addHexPrefixToObjectValues({ addHexPrefixToObjectValues({
prop1: '0x123', prop1: '0x123',
prop2: '456', prop2: '456',
prop3: 'x', prop3: 'x',

@ -14,14 +14,12 @@ import {
checkNetworkAndAccountSupports1559, checkNetworkAndAccountSupports1559,
getShouldShowFiat, getShouldShowFiat,
} from '../../selectors'; } from '../../selectors';
import { import { decGWEIToHexWEI } from '../../helpers/utils/conversions.util';
decGWEIToHexWEI,
decimalToHex,
} from '../../helpers/utils/conversions.util';
import { isLegacyTransaction } from '../../helpers/utils/transactions.util'; import { isLegacyTransaction } from '../../helpers/utils/transactions.util';
import { useCurrencyDisplay } from '../useCurrencyDisplay'; import { useCurrencyDisplay } from '../useCurrencyDisplay';
import { useUserPreferencedCurrency } from '../useUserPreferencedCurrency'; import { useUserPreferencedCurrency } from '../useUserPreferencedCurrency';
import { decimalToHex } from '../../../shared/lib/transactions-controller-utils';
/** /**
* @typedef {object} GasEstimatesReturnType * @typedef {object} GasEstimatesReturnType

@ -4,11 +4,8 @@ import {
getMaximumGasTotalInHexWei, getMaximumGasTotalInHexWei,
getMinimumGasTotalInHexWei, getMinimumGasTotalInHexWei,
} from '../../../shared/modules/gas.utils'; } from '../../../shared/modules/gas.utils';
import { import { decGWEIToHexWEI } from '../../helpers/utils/conversions.util';
decGWEIToHexWEI, import { decimalToHex } from '../../../shared/lib/transactions-controller-utils';
decimalToHex,
} from '../../helpers/utils/conversions.util';
import { import {
FEE_MARKET_ESTIMATE_RETURN_VALUE, FEE_MARKET_ESTIMATE_RETURN_VALUE,
LEGACY_GAS_ESTIMATE_RETURN_VALUE, LEGACY_GAS_ESTIMATE_RETURN_VALUE,

@ -13,11 +13,11 @@ import {
getAdvancedInlineGasShown, getAdvancedInlineGasShown,
getEIP1559V2Enabled, getEIP1559V2Enabled,
} from '../../selectors'; } from '../../selectors';
import { hexToDecimal } from '../../helpers/utils/conversions.util';
import { isLegacyTransaction } from '../../helpers/utils/transactions.util'; import { isLegacyTransaction } from '../../helpers/utils/transactions.util';
import { useGasFeeEstimates } from '../useGasFeeEstimates'; import { useGasFeeEstimates } from '../useGasFeeEstimates';
import { editGasModeIsSpeedUpOrCancel } from '../../helpers/utils/gas'; import { editGasModeIsSpeedUpOrCancel } from '../../helpers/utils/gas';
import { hexToDecimal } from '../../../shared/lib/metamask-controller-utils';
import { useGasFeeErrors } from './useGasFeeErrors'; import { useGasFeeErrors } from './useGasFeeErrors';
import { useGasPriceInput } from './useGasPriceInput'; import { useGasPriceInput } from './useGasPriceInput';
import { useMaxFeePerGasInput } from './useMaxFeePerGasInput'; import { useMaxFeePerGasInput } from './useMaxFeePerGasInput';

@ -5,9 +5,9 @@ import {
GAS_ESTIMATE_TYPES, GAS_ESTIMATE_TYPES,
CUSTOM_GAS_ESTIMATE, CUSTOM_GAS_ESTIMATE,
} from '../../../shared/constants/gas'; } from '../../../shared/constants/gas';
import { hexWEIToDecGWEI } from '../../helpers/utils/conversions.util';
import { isLegacyTransaction } from '../../helpers/utils/transactions.util'; import { isLegacyTransaction } from '../../helpers/utils/transactions.util';
import { hexWEIToDecGWEI } from '../../../shared/lib/transactions-controller-utils';
import { feeParamsAreCustom } from './utils'; import { feeParamsAreCustom } from './utils';
function getGasPriceEstimate(gasFeeEstimates, gasEstimateType, estimateToUse) { function getGasPriceEstimate(gasFeeEstimates, gasEstimateType, estimateToUse) {

@ -4,11 +4,7 @@ import { useSelector } from 'react-redux';
import { GAS_ESTIMATE_TYPES } from '../../../shared/constants/gas'; import { GAS_ESTIMATE_TYPES } from '../../../shared/constants/gas';
import { SECONDARY } from '../../helpers/constants/common'; import { SECONDARY } from '../../helpers/constants/common';
import { getMaximumGasTotalInHexWei } from '../../../shared/modules/gas.utils'; import { getMaximumGasTotalInHexWei } from '../../../shared/modules/gas.utils';
import { import { decGWEIToHexWEI } from '../../helpers/utils/conversions.util';
decGWEIToHexWEI,
decimalToHex,
hexWEIToDecGWEI,
} from '../../helpers/utils/conversions.util';
import { import {
checkNetworkAndAccountSupports1559, checkNetworkAndAccountSupports1559,
getShouldShowFiat, getShouldShowFiat,
@ -17,6 +13,10 @@ import { isLegacyTransaction } from '../../helpers/utils/transactions.util';
import { useCurrencyDisplay } from '../useCurrencyDisplay'; import { useCurrencyDisplay } from '../useCurrencyDisplay';
import { useUserPreferencedCurrency } from '../useUserPreferencedCurrency'; import { useUserPreferencedCurrency } from '../useUserPreferencedCurrency';
import {
decimalToHex,
hexWEIToDecGWEI,
} from '../../../shared/lib/transactions-controller-utils';
import { feeParamsAreCustom, getGasFeeEstimate } from './utils'; import { feeParamsAreCustom, getGasFeeEstimate } from './utils';
const getMaxFeePerGasFromTransaction = (transaction, gasFeeEstimates) => { const getMaxFeePerGasFromTransaction = (transaction, gasFeeEstimates) => {

@ -2,12 +2,12 @@ import { useSelector } from 'react-redux';
import { act, renderHook } from '@testing-library/react-hooks'; import { act, renderHook } from '@testing-library/react-hooks';
import { getMaximumGasTotalInHexWei } from '../../../shared/modules/gas.utils'; import { getMaximumGasTotalInHexWei } from '../../../shared/modules/gas.utils';
import { decimalToHex } from '../../helpers/utils/conversions.util';
import { import {
GAS_RECOMMENDATIONS, GAS_RECOMMENDATIONS,
CUSTOM_GAS_ESTIMATE, CUSTOM_GAS_ESTIMATE,
} from '../../../shared/constants/gas'; } from '../../../shared/constants/gas';
import { decimalToHex } from '../../../shared/lib/transactions-controller-utils';
import { import {
FEE_MARKET_ESTIMATE_RETURN_VALUE, FEE_MARKET_ESTIMATE_RETURN_VALUE,
LEGACY_GAS_ESTIMATE_RETURN_VALUE, LEGACY_GAS_ESTIMATE_RETURN_VALUE,

@ -4,7 +4,6 @@ import { useEffect, useState } from 'react';
import { addHexPrefix } from 'ethereumjs-util'; import { addHexPrefix } from 'ethereumjs-util';
import { SECONDARY } from '../../helpers/constants/common'; import { SECONDARY } from '../../helpers/constants/common';
import { hexWEIToDecGWEI } from '../../helpers/utils/conversions.util';
import { import {
checkNetworkAndAccountSupports1559, checkNetworkAndAccountSupports1559,
getShouldShowFiat, getShouldShowFiat,
@ -14,6 +13,7 @@ import { multiplyCurrencies } from '../../../shared/modules/conversion.utils';
import { useCurrencyDisplay } from '../useCurrencyDisplay'; import { useCurrencyDisplay } from '../useCurrencyDisplay';
import { useUserPreferencedCurrency } from '../useUserPreferencedCurrency'; import { useUserPreferencedCurrency } from '../useUserPreferencedCurrency';
import { hexWEIToDecGWEI } from '../../../shared/lib/transactions-controller-utils';
import { feeParamsAreCustom, getGasFeeEstimate } from './utils'; import { feeParamsAreCustom, getGasFeeEstimate } from './utils';
const getMaxPriorityFeePerGasFromTransaction = ( const getMaxPriorityFeePerGasFromTransaction = (

@ -1,11 +1,9 @@
import { useCallback } from 'react'; import { useCallback } from 'react';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { decimalToHex } from '../../../shared/lib/transactions-controller-utils';
import { EDIT_GAS_MODES, PRIORITY_LEVELS } from '../../../shared/constants/gas'; import { EDIT_GAS_MODES, PRIORITY_LEVELS } from '../../../shared/constants/gas';
import { import { decGWEIToHexWEI } from '../../helpers/utils/conversions.util';
decimalToHex,
decGWEIToHexWEI,
} from '../../helpers/utils/conversions.util';
import { import {
addTenPercentAndRound, addTenPercentAndRound,
editGasModeIsSpeedUpOrCancel, editGasModeIsSpeedUpOrCancel,

@ -1,10 +1,10 @@
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { getSwapsTokensReceivedFromTxMeta } from '../../shared/lib/transactions-controller-utils';
import { TRANSACTION_TYPES } from '../../shared/constants/transaction'; import { TRANSACTION_TYPES } from '../../shared/constants/transaction';
import { import {
isSwapsDefaultTokenAddress, isSwapsDefaultTokenAddress,
isSwapsDefaultTokenSymbol, isSwapsDefaultTokenSymbol,
} from '../../shared/modules/swaps.utils'; } from '../../shared/modules/swaps.utils';
import { getSwapsTokensReceivedFromTxMeta } from '../pages/swaps/swaps.util';
import { getCurrentChainId } from '../selectors'; import { getCurrentChainId } from '../selectors';
import { useTokenFiatAmount } from './useTokenFiatAmount'; import { useTokenFiatAmount } from './useTokenFiatAmount';

@ -1,8 +1,6 @@
import { useMemo } from 'react'; import { useMemo } from 'react';
import { import { getTokenValueParam } from '../../shared/lib/metamask-controller-utils';
getTokenValueParam, import { calcTokenAmount } from '../../shared/lib/transactions-controller-utils';
calcTokenAmount,
} from '../helpers/utils/token-util';
import { useTokenData } from './useTokenData'; import { useTokenData } from './useTokenData';
/** /**

@ -1,7 +1,7 @@
import { renderHook } from '@testing-library/react-hooks'; import { renderHook } from '@testing-library/react-hooks';
import sinon from 'sinon'; import sinon from 'sinon';
import * as tokenUtil from '../helpers/utils/token-util';
import * as txUtil from '../../shared/modules/transaction.utils'; import * as txUtil from '../../shared/modules/transaction.utils';
import * as metamaskControllerUtils from '../../shared/lib/metamask-controller-utils';
import { useTokenDisplayValue } from './useTokenDisplayValue'; import { useTokenDisplayValue } from './useTokenDisplayValue';
const tests = [ const tests = [
@ -121,7 +121,10 @@ describe('useTokenDisplayValue', () => {
tests.forEach(({ displayValue, token, tokenData, tokenValue }, idx) => { tests.forEach(({ displayValue, token, tokenData, tokenValue }, idx) => {
describe(`when input is decimals: ${token.decimals} and value: ${tokenValue}`, () => { describe(`when input is decimals: ${token.decimals} and value: ${tokenValue}`, () => {
it(`should return ${displayValue} as displayValue`, () => { it(`should return ${displayValue} as displayValue`, () => {
const getTokenValueStub = sinon.stub(tokenUtil, 'getTokenValueParam'); const getTokenValueStub = sinon.stub(
metamaskControllerUtils,
'getTokenValueParam',
);
const parseStandardTokenTransactionDataStub = sinon.stub( const parseStandardTokenTransactionDataStub = sinon.stub(
txUtil, txUtil,
'parseStandardTokenTransactionData', 'parseStandardTokenTransactionData',

@ -9,7 +9,6 @@ import { PRIMARY, SECONDARY } from '../helpers/constants/common';
import { import {
getTokenAddressParam, getTokenAddressParam,
getTokenIdParam, getTokenIdParam,
getTokenValueParam,
} from '../helpers/utils/token-util'; } from '../helpers/utils/token-util';
import { import {
formatDateWithYearContext, formatDateWithYearContext,
@ -29,6 +28,7 @@ import {
} from '../../shared/constants/transaction'; } from '../../shared/constants/transaction';
import { captureSingleException } from '../store/actions'; import { captureSingleException } from '../store/actions';
import { isEqualCaseInsensitive } from '../../shared/modules/string-utils'; import { isEqualCaseInsensitive } from '../../shared/modules/string-utils';
import { getTokenValueParam } from '../../shared/lib/metamask-controller-utils';
import { useI18nContext } from './useI18nContext'; import { useI18nContext } from './useI18nContext';
import { useTokenFiatAmount } from './useTokenFiatAmount'; import { useTokenFiatAmount } from './useTokenFiatAmount';
import { useUserPreferencedCurrency } from './useUserPreferencedCurrency'; import { useUserPreferencedCurrency } from './useUserPreferencedCurrency';

@ -1,6 +1,6 @@
import copyToClipboard from 'copy-to-clipboard'; import copyToClipboard from 'copy-to-clipboard';
import log from 'loglevel'; import log from 'loglevel';
import { clone, memoize } from 'lodash'; import { clone } from 'lodash';
import React from 'react'; import React from 'react';
import { render } from 'react-dom'; import { render } from 'react-dom';
import browser from 'webextension-polyfill'; import browser from 'webextension-polyfill';
@ -10,13 +10,10 @@ import { ALERT_TYPES } from '../shared/constants/alerts';
import { maskObject } from '../shared/modules/object.utils'; import { maskObject } from '../shared/modules/object.utils';
import { SENTRY_STATE } from '../app/scripts/lib/setupSentry'; import { SENTRY_STATE } from '../app/scripts/lib/setupSentry';
import { ENVIRONMENT_TYPE_POPUP } from '../shared/constants/app'; 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 * as actions from './store/actions';
import configureStore from './store/store'; import configureStore from './store/store';
import {
fetchLocale,
loadRelativeTimeFormatLocaleData,
} from './helpers/utils/i18n-helper';
import switchDirection from './helpers/utils/switch-direction';
import { import {
getPermittedAccountsForCurrentTab, getPermittedAccountsForCurrentTab,
getSelectedAddress, 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) { async function startApp(metamaskState, backgroundConnection, opts) {
// parse opts // parse opts
if (!metamaskState.featureFlags) { if (!metamaskState.featureFlags) {

@ -1,4 +1,4 @@
import { setupLocale } from '.'; import { setupLocale } from '../shared/lib/error-utils';
const enMessages = { const enMessages = {
troubleStarting: { troubleStarting: {

@ -8,10 +8,7 @@ import {
updateCustomNonce, updateCustomNonce,
getNextNonce, getNextNonce,
} from '../../store/actions'; } from '../../store/actions';
import { import { getTokenApprovedParam } from '../../helpers/utils/token-util';
calcTokenAmount,
getTokenApprovedParam,
} from '../../helpers/utils/token-util';
import { readAddressAsContract } from '../../../shared/modules/contract-utils'; import { readAddressAsContract } from '../../../shared/modules/contract-utils';
import { GasFeeContextProvider } from '../../contexts/gasFee'; import { GasFeeContextProvider } from '../../contexts/gasFee';
import { TransactionModalContextProvider } from '../../contexts/transaction-modal'; 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 Loading from '../../components/ui/loading-screen';
import { parseStandardTokenTransactionData } from '../../../shared/modules/transaction.utils'; import { parseStandardTokenTransactionData } from '../../../shared/modules/transaction.utils';
import { ERC1155, ERC20, ERC721 } from '../../../shared/constants/transaction'; import { ERC1155, ERC20, ERC721 } from '../../../shared/constants/transaction';
import { calcTokenAmount } from '../../../shared/lib/transactions-controller-utils';
import { getCustomTxParamsData } from './confirm-approve.util'; import { getCustomTxParamsData } from './confirm-approve.util';
import ConfirmApproveContent from './confirm-approve-content'; 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 { TRANSACTION_TYPES } from '../../../shared/constants/transaction';
import { parseStandardTokenTransactionData } from '../../../shared/modules/transaction.utils'; import { parseStandardTokenTransactionData } from '../../../shared/modules/transaction.utils';
import { decimalToHex } from '../../helpers/utils/conversions.util'; import { getTokenAddressParam } from '../../helpers/utils/token-util';
import {
calcTokenValue,
getTokenAddressParam,
} from '../../helpers/utils/token-util';
export function getCustomTxParamsData( export function getCustomTxParamsData(
data, data,

@ -11,11 +11,8 @@ import {
addFiat, addFiat,
roundExponential, roundExponential,
} from '../../helpers/utils/confirm-tx.util'; } from '../../helpers/utils/confirm-tx.util';
import {
getWeiHexFromDecimalValue,
hexWEIToDecETH,
} from '../../helpers/utils/conversions.util';
import { ETH, PRIMARY } from '../../helpers/constants/common'; import { ETH, PRIMARY } from '../../helpers/constants/common';
import { getWeiHexFromDecimalValue } from '../../helpers/utils/conversions.util';
import { import {
contractExchangeRateSelector, contractExchangeRateSelector,
getCurrentCurrency, getCurrentCurrency,
@ -25,6 +22,7 @@ import {
getNativeCurrency, getNativeCurrency,
} from '../../ducks/metamask/metamask'; } from '../../ducks/metamask/metamask';
import { ERC1155, ERC20, ERC721 } from '../../../shared/constants/transaction'; import { ERC1155, ERC20, ERC721 } from '../../../shared/constants/transaction';
import { hexWEIToDecETH } from '../../../shared/lib/transactions-controller-utils';
export default function ConfirmTokenTransactionBase({ export default function ConfirmTokenTransactionBase({
image = '', image = '',

@ -3,11 +3,7 @@ import PropTypes from 'prop-types';
import ConfirmPageContainer from '../../components/app/confirm-page-container'; import ConfirmPageContainer from '../../components/app/confirm-page-container';
import TransactionDecoding from '../../components/app/transaction-decoding'; import TransactionDecoding from '../../components/app/transaction-decoding';
import { isBalanceSufficient } from '../send/send.utils'; import { isBalanceSufficient } from '../send/send.utils';
import { import { addHexes } from '../../helpers/utils/conversions.util';
addHexes,
hexToDecimal,
hexWEIToDecGWEI,
} from '../../helpers/utils/conversions.util';
import { import {
CONFIRM_TRANSACTION_ROUTE, CONFIRM_TRANSACTION_ROUTE,
DEFAULT_ROUTE, DEFAULT_ROUTE,
@ -63,6 +59,8 @@ import Typography from '../../components/ui/typography/typography';
import { MIN_GAS_LIMIT_DEC } from '../send/send.constants'; import { MIN_GAS_LIMIT_DEC } from '../send/send.constants';
import { NETWORK_TO_NAME_MAP } from '../../../shared/constants/network'; 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'; import TransactionAlerts from './transaction-alerts';
const renderHeartBeatIfNotInTest = () => const renderHeartBeatIfNotInTest = () =>

@ -14,7 +14,7 @@ import {
tryReverseResolveAddress, tryReverseResolveAddress,
setDefaultHomeActiveTabName, setDefaultHomeActiveTabName,
} from '../../store/actions'; } from '../../store/actions';
import { isBalanceSufficient, calcGasTotal } from '../send/send.utils'; import { isBalanceSufficient } from '../send/send.utils';
import { shortenAddress, valuesFor } from '../../helpers/utils/util'; import { shortenAddress, valuesFor } from '../../helpers/utils/util';
import { import {
getAdvancedInlineGasShown, getAdvancedInlineGasShown,
@ -57,6 +57,7 @@ import { CUSTOM_GAS_ESTIMATE } from '../../../shared/constants/gas';
import { TRANSACTION_TYPES } from '../../../shared/constants/transaction'; import { TRANSACTION_TYPES } from '../../../shared/constants/transaction';
import { isEqualCaseInsensitive } from '../../../shared/modules/string-utils'; import { isEqualCaseInsensitive } from '../../../shared/modules/string-utils';
import { getTokenAddressParam } from '../../helpers/utils/token-util'; import { getTokenAddressParam } from '../../helpers/utils/token-util';
import { calcGasTotal } from '../../../shared/lib/transactions-controller-utils';
import ConfirmTransactionBase from './confirm-transaction-base.component'; import ConfirmTransactionBase from './confirm-transaction-base.component';
let customNonceValue = ''; let customNonceValue = '';

@ -12,9 +12,8 @@ import {
ALIGN_ITEMS, ALIGN_ITEMS,
} from '../../../helpers/constants/design-system'; } from '../../../helpers/constants/design-system';
import { DEFAULT_ROUTE } from '../../../helpers/constants/routes'; import { DEFAULT_ROUTE } from '../../../helpers/constants/routes';
import fetchWithCache from '../../../helpers/utils/fetch-with-cache';
import ZENDESK_URLS from '../../../helpers/constants/zendesk-url'; import ZENDESK_URLS from '../../../helpers/constants/zendesk-url';
import fetchWithCache from '../../../../shared/lib/fetch-with-cache';
const UNRECOGNIZED_CHAIN = { const UNRECOGNIZED_CHAIN = {
id: 'UNRECOGNIZED_CHAIN', id: 'UNRECOGNIZED_CHAIN',

@ -1,9 +1,6 @@
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Redirect, Route } from 'react-router-dom'; import { Redirect, Route } from 'react-router-dom';
///: BEGIN:ONLY_INCLUDE_IN(main)
import { SUPPORT_LINK } from '../../helpers/constants/common';
///: END:ONLY_INCLUDE_IN
import { import {
EVENT, EVENT,
EVENT_NAMES, EVENT_NAMES,
@ -52,6 +49,9 @@ import {
} from '../../helpers/constants/routes'; } from '../../helpers/constants/routes';
import ZENDESK_URLS from '../../helpers/constants/zendesk-url'; import ZENDESK_URLS from '../../helpers/constants/zendesk-url';
import Tooltip from '../../components/ui/tooltip'; 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) ///: BEGIN:ONLY_INCLUDE_IN(beta)
import BetaHomeFooter from './beta/beta-home-footer.component'; import BetaHomeFooter from './beta/beta-home-footer.component';
///: END:ONLY_INCLUDE_IN ///: END:ONLY_INCLUDE_IN

@ -24,7 +24,7 @@ import {
setCustomGasLimit, setCustomGasLimit,
} from '../../../../ducks/gas/gas.duck'; } from '../../../../ducks/gas/gas.duck';
import { showModal } from '../../../../store/actions'; 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'; import SendGasRow from './send-gas-row.component';
export default connect( export default connect(

@ -3,10 +3,10 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
import testData from '../../../../../.storybook/test-data'; import testData from '../../../../../.storybook/test-data';
import { calcGasTotal } from '../../../../../shared/lib/transactions-controller-utils';
import { GAS_INPUT_MODES } from '../../../../ducks/send'; import { GAS_INPUT_MODES } from '../../../../ducks/send';
import { updateMetamaskState } from '../../../../store/actions'; import { updateMetamaskState } from '../../../../store/actions';
import configureStore from '../../../../store/store'; import configureStore from '../../../../store/store';
import { calcGasTotal } from '../../send.utils';
import README from './README.mdx'; import README from './README.mdx';
import SendGasRow from './send-gas-row.component'; import SendGasRow from './send-gas-row.component';

@ -8,9 +8,9 @@ import {
conversionLessThan, conversionLessThan,
} from '../../../shared/modules/conversion.utils'; } from '../../../shared/modules/conversion.utils';
import { calcTokenAmount } from '../../helpers/utils/token-util';
import { addHexPrefix } from '../../../app/scripts/lib/util'; import { addHexPrefix } from '../../../app/scripts/lib/util';
import { ERC20, ERC721 } from '../../../shared/constants/transaction'; import { ERC20, ERC721 } from '../../../shared/constants/transaction';
import { calcTokenAmount } from '../../../shared/lib/transactions-controller-utils';
import { import {
TOKEN_TRANSFER_FUNCTION_SIGNATURE, TOKEN_TRANSFER_FUNCTION_SIGNATURE,
COLLECTIBLE_TRANSFER_FROM_FUNCTION_SIGNATURE, COLLECTIBLE_TRANSFER_FROM_FUNCTION_SIGNATURE,
@ -18,7 +18,6 @@ import {
export { export {
addGasBuffer, addGasBuffer,
calcGasTotal,
getAssetTransferData, getAssetTransferData,
generateERC20TransferData, generateERC20TransferData,
generateERC721TransferData, generateERC721TransferData,
@ -27,14 +26,6 @@ export {
ellipsify, ellipsify,
}; };
function calcGasTotal(gasLimit = '0', gasPrice = '0') {
return multiplyCurrencies(gasLimit, gasPrice, {
toNumericBase: 'hex',
multiplicandBase: 16,
multiplierBase: 16,
});
}
function isBalanceSufficient({ function isBalanceSufficient({
amount = '0x0', amount = '0x0',
balance = '0x0', balance = '0x0',

@ -1,4 +1,5 @@
import { rawEncode } from 'ethereumjs-abi'; import { rawEncode } from 'ethereumjs-abi';
import { calcGasTotal } from '../../../shared/lib/transactions-controller-utils';
import { import {
multiplyCurrencies, multiplyCurrencies,
@ -8,7 +9,6 @@ import {
} from '../../../shared/modules/conversion.utils'; } from '../../../shared/modules/conversion.utils';
import { import {
calcGasTotal,
generateERC20TransferData, generateERC20TransferData,
isBalanceSufficient, isBalanceSufficient,
isTokenBalanceSufficient, isTokenBalanceSufficient,
@ -32,9 +32,16 @@ jest.mock('../../../shared/modules/conversion.utils', () => ({
conversionLessThan: (obj1, obj2) => obj1.value < obj2.value, 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}`, calcTokenAmount: (a, d) => `calc:${a}${d}`,
})); };
});
jest.mock('ethereumjs-abi', () => ({ jest.mock('ethereumjs-abi', () => ({
rawEncode: jest.fn().mockReturnValue(16, 1100), rawEncode: jest.fn().mockReturnValue(16, 1100),

@ -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 PropTypes from 'prop-types';
import Button from '../../../components/ui/button'; import Button from '../../../components/ui/button';
import { import { SUPPORT_REQUEST_LINK } from '../../../helpers/constants/common';
SUPPORT_LINK,
SUPPORT_REQUEST_LINK,
} from '../../../helpers/constants/common';
import { isBeta } from '../../../helpers/utils/build-types'; import { isBeta } from '../../../helpers/utils/build-types';
import { import {
getNumberOfSettingsInSection, getNumberOfSettingsInSection,
@ -16,6 +13,7 @@ import {
EVENT_NAMES, EVENT_NAMES,
CONTEXT_PROPS, CONTEXT_PROPS,
} from '../../../../shared/constants/metametrics'; } from '../../../../shared/constants/metametrics';
import { SUPPORT_LINK } from '../../../../shared/lib/ui-utils';
export default class InfoTab extends PureComponent { export default class InfoTab extends PureComponent {
state = { state = {

@ -22,7 +22,6 @@ import { jsonRpcRequest } from '../../../../../shared/modules/rpc.utils';
import ActionableMessage from '../../../../components/ui/actionable-message'; import ActionableMessage from '../../../../components/ui/actionable-message';
import Button from '../../../../components/ui/button'; import Button from '../../../../components/ui/button';
import FormField from '../../../../components/ui/form-field'; import FormField from '../../../../components/ui/form-field';
import { decimalToHex } from '../../../../helpers/utils/conversions.util';
import { import {
setSelectedSettingsRpcUrl, setSelectedSettingsRpcUrl,
updateAndSetCustomRpc, updateAndSetCustomRpc,
@ -34,7 +33,7 @@ import {
DEFAULT_ROUTE, DEFAULT_ROUTE,
NETWORKS_ROUTE, NETWORKS_ROUTE,
} from '../../../../helpers/constants/routes'; } 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 { usePrevious } from '../../../../hooks/usePrevious';
import { MetaMetricsContext } from '../../../../contexts/metametrics'; import { MetaMetricsContext } from '../../../../contexts/metametrics';
import { EVENT } from '../../../../../shared/constants/metametrics'; import { EVENT } from '../../../../../shared/constants/metametrics';
@ -42,6 +41,7 @@ import {
infuraProjectId, infuraProjectId,
FEATURED_RPCS, FEATURED_RPCS,
} from '../../../../../shared/constants/network'; } from '../../../../../shared/constants/network';
import { decimalToHex } from '../../../../../shared/lib/transactions-controller-utils';
/** /**
* Attempts to convert the given chainId to a decimal string, for display * 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 isEqual from 'lodash/isEqual';
import { getBlockExplorerLink } from '@metamask/etherscan-link'; import { getBlockExplorerLink } from '@metamask/etherscan-link';
import { I18nContext } from '../../../contexts/i18n'; import { I18nContext } from '../../../contexts/i18n';
import { SUPPORT_LINK } from '../../../helpers/constants/common';
import { MetaMetricsContext } from '../../../contexts/metametrics'; import { MetaMetricsContext } from '../../../contexts/metametrics';
import { import {
EVENT, EVENT,
@ -62,6 +61,7 @@ import SwapsFooter from '../swaps-footer';
import CreateNewSwap from '../create-new-swap'; import CreateNewSwap from '../create-new-swap';
import ViewOnBlockExplorer from '../view-on-block-explorer'; import ViewOnBlockExplorer from '../view-on-block-explorer';
import { SUPPORT_LINK } from '../../../../shared/lib/ui-utils';
import SwapFailureIcon from './swap-failure-icon'; import SwapFailureIcon from './swap-failure-icon';
import SwapSuccessIcon from './swap-success-icon'; import SwapSuccessIcon from './swap-success-icon';
import QuotesTimeoutIcon from './quotes-timeout-icon'; import QuotesTimeoutIcon from './quotes-timeout-icon';

@ -71,11 +71,7 @@ import {
getHardwareWalletType, getHardwareWalletType,
} from '../../../selectors'; } from '../../../selectors';
import { import { getValueFromWeiHex } from '../../../helpers/utils/conversions.util';
getValueFromWeiHex,
hexToDecimal,
} from '../../../helpers/utils/conversions.util';
import { calcTokenAmount } from '../../../helpers/utils/token-util';
import { getURLHostName } from '../../../helpers/utils/util'; import { getURLHostName } from '../../../helpers/utils/util';
import { usePrevious } from '../../../hooks/usePrevious'; import { usePrevious } from '../../../hooks/usePrevious';
import { useTokenTracker } from '../../../hooks/useTokenTracker'; import { useTokenTracker } from '../../../hooks/useTokenTracker';
@ -106,10 +102,12 @@ import {
countDecimals, countDecimals,
fetchTokenPrice, fetchTokenPrice,
fetchTokenBalance, fetchTokenBalance,
shouldEnableDirectWrapping,
} from '../swaps.util'; } from '../swaps.util';
import SwapsFooter from '../swaps-footer'; import SwapsFooter from '../swaps-footer';
import { isEqualCaseInsensitive } from '../../../../shared/modules/string-utils'; 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 = [ const fuseSearchKeys = [
{ name: 'name', weight: 0.499 }, { name: 'name', weight: 0.499 },

@ -2,8 +2,8 @@ import React, { useState } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import classnames from 'classnames'; import classnames from 'classnames';
import { calcTokenAmount } from '../../../helpers/utils/token-util';
import { formatSwapsValueForDisplay } from '../swaps.util'; import { formatSwapsValueForDisplay } from '../swaps.util';
import { calcTokenAmount } from '../../../../shared/lib/transactions-controller-utils';
export default function ExchangeRateDisplay({ export default function ExchangeRateDisplay({
primaryTokenValue, primaryTokenValue,

@ -87,10 +87,10 @@ import { EVENT } from '../../../shared/constants/metametrics';
import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction';
import ActionableMessage from '../../components/ui/actionable-message'; import ActionableMessage from '../../components/ui/actionable-message';
import { MetaMetricsContext } from '../../contexts/metametrics'; import { MetaMetricsContext } from '../../contexts/metametrics';
import { getSwapsTokensReceivedFromTxMeta } from '../../../shared/lib/transactions-controller-utils';
import { import {
fetchTokens, fetchTokens,
fetchTopAssets, fetchTopAssets,
getSwapsTokensReceivedFromTxMeta,
fetchAggregatorMetadata, fetchAggregatorMetadata,
stxErrorTypes, stxErrorTypes,
} from './swaps.util'; } from './swaps.util';

@ -1,12 +1,14 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import BigNumber from 'bignumber.js'; 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 Tooltip from '../../../components/ui/tooltip';
import UrlIcon from '../../../components/ui/url-icon'; import UrlIcon from '../../../components/ui/url-icon';
import ExchangeRateDisplay from '../exchange-rate-display'; import ExchangeRateDisplay from '../exchange-rate-display';
import { formatSwapsValueForDisplay } from '../swaps.util'; import { formatSwapsValueForDisplay } from '../swaps.util';
import {
calcTokenAmount,
toPrecisionWithoutTrailingZeros,
} from '../../../../shared/lib/transactions-controller-utils';
function getFontSizesAndLineHeights(fontSizeScore) { function getFontSizesAndLineHeights(fontSizeScore) {
if (fontSizeScore <= 9) { if (fontSizeScore <= 9) {

@ -52,7 +52,6 @@ import { EVENT } from '../../../../shared/constants/metametrics';
import { SMART_TRANSACTION_STATUSES } from '../../../../shared/constants/transaction'; import { SMART_TRANSACTION_STATUSES } from '../../../../shared/constants/transaction';
import SwapsFooter from '../swaps-footer'; import SwapsFooter from '../swaps-footer';
import { calcTokenAmount } from '../../../helpers/utils/token-util';
import { import {
showRemainingTimeInMinAndSec, showRemainingTimeInMinAndSec,
getFeeForSmartTransaction, getFeeForSmartTransaction,
@ -60,6 +59,7 @@ import {
import { MetaMetricsContext } from '../../../contexts/metametrics'; import { MetaMetricsContext } from '../../../contexts/metametrics';
import CreateNewSwap from '../create-new-swap'; import CreateNewSwap from '../create-new-swap';
import ViewOnBlockExplorer from '../view-on-block-explorer'; import ViewOnBlockExplorer from '../view-on-block-explorer';
import { calcTokenAmount } from '../../../../shared/lib/transactions-controller-utils';
import SuccessIcon from './success-icon'; import SuccessIcon from './success-icon';
import RevertedIcon from './reverted-icon'; import RevertedIcon from './reverted-icon';
import CanceledIcon from './canceled-icon'; import CanceledIcon from './canceled-icon';

@ -1,10 +1,8 @@
import log from 'loglevel';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import abi from 'human-standard-token-abi'; import abi from 'human-standard-token-abi';
import { import {
SWAPS_CHAINID_DEFAULT_TOKEN_MAP, SWAPS_CHAINID_DEFAULT_TOKEN_MAP,
ALLOWED_CONTRACT_ADDRESSES, ALLOWED_CONTRACT_ADDRESSES,
SWAPS_WRAPPED_TOKENS_ADDRESSES,
ETHEREUM, ETHEREUM,
POLYGON, POLYGON,
BSC, BSC,
@ -12,179 +10,40 @@ import {
AVALANCHE, AVALANCHE,
SWAPS_API_V2_BASE_URL, SWAPS_API_V2_BASE_URL,
SWAPS_DEV_API_V2_BASE_URL, SWAPS_DEV_API_V2_BASE_URL,
GAS_API_BASE_URL,
GAS_DEV_API_BASE_URL,
SWAPS_CLIENT_ID, SWAPS_CLIENT_ID,
SWAPS_WRAPPED_TOKENS_ADDRESSES,
} from '../../../shared/constants/swaps'; } from '../../../shared/constants/swaps';
import { TRANSACTION_ENVELOPE_TYPES } from '../../../shared/constants/transaction';
import { import {
isSwapsDefaultTokenAddress, isSwapsDefaultTokenAddress,
isSwapsDefaultTokenSymbol, isSwapsDefaultTokenSymbol,
} from '../../../shared/modules/swaps.utils'; } from '../../../shared/modules/swaps.utils';
import { CHAIN_IDS, CURRENCY_SYMBOLS } from '../../../shared/constants/network'; 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 { import {
calcTokenValue, calcGasTotal,
calcTokenAmount, calcTokenAmount,
} from '../../helpers/utils/token-util'; decimalToHex,
import {
constructTxParams,
toPrecisionWithoutTrailingZeros, toPrecisionWithoutTrailingZeros,
} from '../../helpers/utils/util'; } from '../../../shared/lib/transactions-controller-utils';
import { import {
decimalToHex, calcTokenValue,
getValueFromWeiHex, constructTxParams,
} from '../../helpers/utils/conversions.util'; getBaseApi,
QUOTE_VALIDATORS,
import { subtractCurrencies } from '../../../shared/modules/conversion.utils'; truthyString,
import { formatCurrency } from '../../helpers/utils/confirm-tx.util'; validateData,
import fetchWithCache from '../../helpers/utils/fetch-with-cache'; } from '../../../shared/lib/swaps-utils';
import { SECOND } from '../../../shared/constants/time';
import { calcGasTotal } from '../send/send.utils';
import { isValidHexAddress } from '../../../shared/modules/hexstring-utils';
const TOKEN_TRANSFER_LOG_TOPIC_HASH =
'0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef';
const CACHE_REFRESH_FIVE_MINUTES = 300000; const CACHE_REFRESH_FIVE_MINUTES = 300000;
const USD_CURRENCY_CODE = 'usd'; const USD_CURRENCY_CODE = 'usd';
const clientIdHeader = { 'X-Client-Id': SWAPS_CLIENT_ID }; 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 = [ const TOKEN_VALIDATORS = [
{ {
property: 'address', 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 = ( export const shouldEnableDirectWrapping = (
chainId, chainId,
sourceToken, 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) { export function formatSwapsValueForDisplay(destinationAmount) {
let amountToDisplay = toPrecisionWithoutTrailingZeros(destinationAmount, 12); let amountToDisplay = toPrecisionWithoutTrailingZeros(destinationAmount, 12);
if (amountToDisplay.match(/e[+-]/u)) { if (amountToDisplay.match(/e[+-]/u)) {

@ -1,6 +1,7 @@
import nock from 'nock'; import nock from 'nock';
import { MOCKS } from '../../../test/jest'; import { MOCKS } from '../../../test/jest';
import { CHAIN_IDS, CURRENCY_SYMBOLS } from '../../../shared/constants/network'; import { CHAIN_IDS, CURRENCY_SYMBOLS } from '../../../shared/constants/network';
import { getSwapsTokensReceivedFromTxMeta } from '../../../shared/lib/transactions-controller-utils';
import { import {
SWAPS_CHAINID_CONTRACT_ADDRESS_MAP, SWAPS_CHAINID_CONTRACT_ADDRESS_MAP,
SWAPS_CHAINID_DEFAULT_TOKEN_MAP, SWAPS_CHAINID_DEFAULT_TOKEN_MAP,
@ -13,6 +14,10 @@ import {
GOERLI, GOERLI,
AVALANCHE, AVALANCHE,
} from '../../../shared/constants/swaps'; } from '../../../shared/constants/swaps';
import {
fetchTradesInfo,
shouldEnableDirectWrapping,
} from '../../../shared/lib/swaps-utils';
import { import {
TOKENS, TOKENS,
EXPECTED_TOKENS_RESULT, EXPECTED_TOKENS_RESULT,
@ -21,7 +26,6 @@ import {
TOP_ASSETS, TOP_ASSETS,
} from './swaps-util-test-constants'; } from './swaps-util-test-constants';
import { import {
fetchTradesInfo,
fetchTokens, fetchTokens,
fetchAggregatorMetadata, fetchAggregatorMetadata,
fetchTopAssets, fetchTopAssets,
@ -29,12 +33,10 @@ import {
getNetworkNameByChainId, getNetworkNameByChainId,
getSwapsLivenessForNetwork, getSwapsLivenessForNetwork,
countDecimals, countDecimals,
shouldEnableDirectWrapping,
showRemainingTimeInMinAndSec, showRemainingTimeInMinAndSec,
getSwapsTokensReceivedFromTxMeta,
} from './swaps.util'; } from './swaps.util';
jest.mock('../../helpers/utils/storage-helpers.js', () => ({ jest.mock('../../../shared/lib/storage-helpers', () => ({
getStorageItem: jest.fn(), getStorageItem: jest.fn(),
setStorageItem: jest.fn(), setStorageItem: jest.fn(),
})); }));

@ -66,8 +66,6 @@ import {
} from '../../../selectors'; } from '../../../selectors';
import { getNativeCurrency, getTokens } from '../../../ducks/metamask/metamask'; import { getNativeCurrency, getTokens } from '../../../ducks/metamask/metamask';
import { toPrecisionWithoutTrailingZeros } from '../../../helpers/utils/util';
import { import {
safeRefetchQuotes, safeRefetchQuotes,
setCustomApproveTxData, setCustomApproveTxData,
@ -84,19 +82,11 @@ import {
AWAITING_SWAP_ROUTE, AWAITING_SWAP_ROUTE,
} from '../../../helpers/constants/routes'; } from '../../../helpers/constants/routes';
import { import {
calcTokenAmount,
calcTokenValue,
getTokenValueParam,
} from '../../../helpers/utils/token-util';
import {
decimalToHex,
decGWEIToHexWEI, decGWEIToHexWEI,
hexWEIToDecGWEI,
addHexes, addHexes,
decWEIToDecETH, decWEIToDecETH,
} from '../../../helpers/utils/conversions.util'; } from '../../../helpers/utils/conversions.util';
import MainQuoteSummary from '../main-quote-summary'; import MainQuoteSummary from '../main-quote-summary';
import { calcGasTotal } from '../../send/send.utils';
import { getCustomTxParamsData } from '../../confirm-approve/confirm-approve.util'; import { getCustomTxParamsData } from '../../confirm-approve/confirm-approve.util';
import ActionableMessage from '../../../components/ui/actionable-message/actionable-message'; import ActionableMessage from '../../../components/ui/actionable-message/actionable-message';
import { import {
@ -114,6 +104,15 @@ import Box from '../../../components/ui/box';
import { EVENT } from '../../../../shared/constants/metametrics'; import { EVENT } from '../../../../shared/constants/metametrics';
import { isEqualCaseInsensitive } from '../../../../shared/modules/string-utils'; import { isEqualCaseInsensitive } from '../../../../shared/modules/string-utils';
import { parseStandardTokenTransactionData } from '../../../../shared/modules/transaction.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'; import ViewQuotePriceDifference from './view-quote-price-difference';
let intervalId; let intervalId;

@ -5,13 +5,13 @@ import getCaretCoordinates from 'textarea-caret';
import Button from '../../components/ui/button'; import Button from '../../components/ui/button';
import TextField from '../../components/ui/text-field'; import TextField from '../../components/ui/text-field';
import Mascot from '../../components/ui/mascot'; import Mascot from '../../components/ui/mascot';
import { SUPPORT_LINK } from '../../helpers/constants/common';
import { DEFAULT_ROUTE } from '../../helpers/constants/routes'; import { DEFAULT_ROUTE } from '../../helpers/constants/routes';
import { import {
EVENT, EVENT,
EVENT_NAMES, EVENT_NAMES,
CONTEXT_PROPS, CONTEXT_PROPS,
} from '../../../shared/constants/metametrics'; } from '../../../shared/constants/metametrics';
import { SUPPORT_LINK } from '../../../shared/lib/ui-utils';
export default class UnlockPage extends Component { export default class UnlockPage extends Component {
static contextTypes = { static contextTypes = {

@ -1,6 +1,5 @@
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import txHelper from '../helpers/utils/tx-helper'; import txHelper from '../helpers/utils/tx-helper';
import { calcTokenAmount } from '../helpers/utils/token-util';
import { import {
roundExponential, roundExponential,
getValueFromWeiHex, getValueFromWeiHex,
@ -26,6 +25,7 @@ import {
getMinimumGasTotalInHexWei, getMinimumGasTotalInHexWei,
} from '../../shared/modules/gas.utils'; } from '../../shared/modules/gas.utils';
import { isEqualCaseInsensitive } from '../../shared/modules/string-utils'; import { isEqualCaseInsensitive } from '../../shared/modules/string-utils';
import { calcTokenAmount } from '../../shared/lib/transactions-controller-utils';
import { getAveragePriceEstimateInHexWEI } from './custom-gas'; import { getAveragePriceEstimateInHexWEI } from './custom-gas';
import { getCurrentChainId, deprecatedGetCurrentNetworkId } from './selectors'; import { getCurrentChainId, deprecatedGetCurrentNetworkId } from './selectors';
import { checkNetworkAndAccountSupports1559 } from '.'; import { checkNetworkAndAccountSupports1559 } from '.';

@ -6,7 +6,6 @@ import {
import { formatCurrency } from '../helpers/utils/confirm-tx.util'; import { formatCurrency } from '../helpers/utils/confirm-tx.util';
import { decEthToConvertedCurrency as ethTotalToConvertedCurrency } from '../helpers/utils/conversions.util'; import { decEthToConvertedCurrency as ethTotalToConvertedCurrency } from '../helpers/utils/conversions.util';
import { formatETHFee } from '../helpers/utils/formatters'; import { formatETHFee } from '../helpers/utils/formatters';
import { calcGasTotal } from '../pages/send/send.utils';
import { getGasLimit, getGasPrice } from '../ducks/send'; import { getGasLimit, getGasPrice } from '../ducks/send';
import { import {
@ -19,6 +18,7 @@ import {
isEIP1559Network, isEIP1559Network,
} from '../ducks/metamask/metamask'; } from '../ducks/metamask/metamask';
import { GAS_ESTIMATE_TYPES } from '../helpers/constants/common'; import { GAS_ESTIMATE_TYPES } from '../helpers/constants/common';
import { calcGasTotal } from '../../shared/lib/transactions-controller-utils';
import { getCurrentCurrency, getIsMainnet, getShouldShowFiat } from '.'; import { getCurrentCurrency, getIsMainnet, getShouldShowFiat } from '.';
const NUMBER_OF_DECIMALS_SM_BTNS = 5; const NUMBER_OF_DECIMALS_SM_BTNS = 5;

@ -42,10 +42,7 @@ import {
getAccountByAddress, getAccountByAddress,
getURLHostName, getURLHostName,
} from '../helpers/utils/util'; } from '../helpers/utils/util';
import { import { getValueFromWeiHex } from '../helpers/utils/conversions.util';
getValueFromWeiHex,
hexToDecimal,
} from '../helpers/utils/conversions.util';
import { TEMPLATED_CONFIRMATION_MESSAGE_TYPES } from '../pages/confirmation/templates'; import { TEMPLATED_CONFIRMATION_MESSAGE_TYPES } from '../pages/confirmation/templates';
import { STATIC_MAINNET_TOKEN_LIST } from '../../shared/constants/tokens'; 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) ///: BEGIN:ONLY_INCLUDE_IN(flask)
import { SNAPS_VIEW_ROUTE } from '../helpers/constants/routes'; import { SNAPS_VIEW_ROUTE } from '../helpers/constants/routes';
///: END:ONLY_INCLUDE_IN ///: 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 * One of the only remaining valid uses of selecting the network subkey of the

@ -3,7 +3,6 @@ import {
PRIORITY_STATUS_HASH, PRIORITY_STATUS_HASH,
PENDING_STATUS_HASH, PENDING_STATUS_HASH,
} from '../helpers/constants/transactions'; } from '../helpers/constants/transactions';
import { hexToDecimal } from '../helpers/utils/conversions.util';
import txHelper from '../helpers/utils/tx-helper'; import txHelper from '../helpers/utils/tx-helper';
import { import {
TRANSACTION_STATUSES, TRANSACTION_STATUSES,
@ -11,6 +10,7 @@ import {
SMART_TRANSACTION_STATUSES, SMART_TRANSACTION_STATUSES,
} from '../../shared/constants/transaction'; } from '../../shared/constants/transaction';
import { transactionMatchesNetwork } from '../../shared/modules/transaction.utils'; import { transactionMatchesNetwork } from '../../shared/modules/transaction.utils';
import { hexToDecimal } from '../../shared/lib/metamask-controller-utils';
import { import {
getCurrentChainId, getCurrentChainId,
deprecatedGetCurrentNetworkId, deprecatedGetCurrentNetworkId,

@ -2,12 +2,8 @@ import log from 'loglevel';
import { captureException } from '@sentry/browser'; import { captureException } from '@sentry/browser';
import { capitalize, isEqual } from 'lodash'; import { capitalize, isEqual } from 'lodash';
import getBuyUrl from '../../app/scripts/lib/buy-url'; import getBuyUrl from '../../app/scripts/lib/buy-url';
import {
fetchLocale,
loadRelativeTimeFormatLocaleData,
} from '../helpers/utils/i18n-helper';
import { getMethodDataAsync } from '../helpers/utils/transactions.util'; import { getMethodDataAsync } from '../helpers/utils/transactions.util';
import switchDirection from '../helpers/utils/switch-direction'; import switchDirection from '../../shared/lib/switch-direction';
import { import {
ENVIRONMENT_TYPE_NOTIFICATION, ENVIRONMENT_TYPE_NOTIFICATION,
ORIGIN_METAMASK, ORIGIN_METAMASK,
@ -17,7 +13,6 @@ import {
import { hasUnconfirmedTransactions } from '../helpers/utils/confirm-tx.util'; import { hasUnconfirmedTransactions } from '../helpers/utils/confirm-tx.util';
import txHelper from '../helpers/utils/tx-helper'; import txHelper from '../helpers/utils/tx-helper';
import { getEnvironmentType, addHexPrefix } from '../../app/scripts/lib/util'; import { getEnvironmentType, addHexPrefix } from '../../app/scripts/lib/util';
import { decimalToHex } from '../helpers/utils/conversions.util';
import { import {
getMetaMaskAccounts, getMetaMaskAccounts,
getPermittedAccountsForCurrentTab, getPermittedAccountsForCurrentTab,
@ -46,6 +41,11 @@ import { isEqualCaseInsensitive } from '../../shared/modules/string-utils';
import { NOTIFICATIONS_EXPIRATION_DELAY } from '../helpers/constants/notifications'; import { NOTIFICATIONS_EXPIRATION_DELAY } from '../helpers/constants/notifications';
///: END:ONLY_INCLUDE_IN ///: END:ONLY_INCLUDE_IN
import { setNewCustomNetworkAdded } from '../ducks/app/app'; 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 * as actionConstants from './actionConstants';
import { import {
generateActionId, generateActionId,

Loading…
Cancel
Save