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
parent
c2b7690119
commit
6e13524bcd
@ -1,7 +1,27 @@ |
||||
import getFirstPreferredLangCode from '../../../app/scripts/lib/get-first-preferred-lang-code'; |
||||
import { setupLocale } from '../..'; |
||||
import { memoize } from 'lodash'; |
||||
import getFirstPreferredLangCode from '../../app/scripts/lib/get-first-preferred-lang-code'; |
||||
import { |
||||
fetchLocale, |
||||
loadRelativeTimeFormatLocaleData, |
||||
} from '../../ui/helpers/utils/i18n-helper'; |
||||
import switchDirection from './switch-direction'; |
||||
|
||||
const _setupLocale = async (currentLocale) => { |
||||
const currentLocaleMessages = currentLocale |
||||
? await fetchLocale(currentLocale) |
||||
: {}; |
||||
const enLocaleMessages = await fetchLocale('en'); |
||||
|
||||
await loadRelativeTimeFormatLocaleData('en'); |
||||
if (currentLocale) { |
||||
await loadRelativeTimeFormatLocaleData(currentLocale); |
||||
} |
||||
|
||||
return { currentLocaleMessages, enLocaleMessages }; |
||||
}; |
||||
|
||||
export const setupLocale = memoize(_setupLocale); |
||||
|
||||
const getLocaleContext = (currentLocaleMessages, enLocaleMessages) => { |
||||
return (key) => { |
||||
let message = currentLocaleMessages[key]?.message; |
@ -1,14 +1,14 @@ |
||||
import { SUPPORT_LINK } from '../constants/common'; |
||||
import { fetchLocale } from '../../ui/helpers/utils/i18n-helper'; |
||||
import { SUPPORT_LINK } from './ui-utils'; |
||||
import { getErrorHtml } from './error-utils'; |
||||
import { fetchLocale } from './i18n-helper'; |
||||
|
||||
jest.mock('./i18n-helper', () => ({ |
||||
jest.mock('../../ui/helpers/utils/i18n-helper', () => ({ |
||||
fetchLocale: jest.fn(), |
||||
loadRelativeTimeFormatLocaleData: jest.fn(), |
||||
})); |
||||
|
||||
describe('Error utils Tests', () => { |
||||
it('should get error html', async () => { |
||||
describe('Error utils Tests', function () { |
||||
it('should get error html', async function () { |
||||
const mockStore = { |
||||
localeMessages: { |
||||
current: { |
@ -1,5 +1,5 @@ |
||||
import { MINUTE, SECOND } from '../../../shared/constants/time'; |
||||
import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout'; |
||||
import { MINUTE, SECOND } from '../constants/time'; |
||||
import getFetchWithTimeout from '../modules/fetch-with-timeout'; |
||||
import { getStorageItem, setStorageItem } from './storage-helpers'; |
||||
|
||||
const fetchWithCache = async ( |
@ -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; |
@ -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(); |
||||
}); |
||||
}); |
@ -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(); |
||||
}); |
||||
}); |
@ -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(); |
||||
}); |
||||
}); |
@ -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 +0,0 @@ |
||||
export const TEN_SECONDS_IN_MILLISECONDS = 10_000; |
@ -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(); |
||||
}); |
||||
}); |
Loading…
Reference in new issue