mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-21 17:37:01 +01:00
feat(mme-17214): migrate L33 files to typescript (#17372)
This commit is contained in:
parent
8a7c897a1c
commit
2958d68af8
@ -4,6 +4,9 @@ import { SWAPS_API_V2_BASE_URL } from '../../../shared/constants/swaps';
|
||||
import {
|
||||
BUYABLE_CHAINS_MAP,
|
||||
CHAIN_IDS,
|
||||
WyreChainSettings,
|
||||
CurrencySymbol,
|
||||
ChainId,
|
||||
} from '../../../shared/constants/network';
|
||||
import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout';
|
||||
import {
|
||||
@ -18,13 +21,17 @@ const fetchWithTimeout = getFetchWithTimeout();
|
||||
/**
|
||||
* Create a Wyre purchase URL.
|
||||
*
|
||||
* @param {string} walletAddress - Ethereum destination address
|
||||
* @param {string} chainId - Current chain ID
|
||||
* @param {string|undefined} symbol - Token symbol to buy
|
||||
* @param walletAddress - Ethereum destination address
|
||||
* @param chainId - Current chain ID
|
||||
* @param symbol - Token symbol to buy
|
||||
* @returns String
|
||||
*/
|
||||
const createWyrePurchaseUrl = async (walletAddress, chainId, symbol) => {
|
||||
const { wyre = {} } = BUYABLE_CHAINS_MAP[chainId];
|
||||
const createWyrePurchaseUrl = async (
|
||||
walletAddress: string,
|
||||
chainId: keyof typeof BUYABLE_CHAINS_MAP,
|
||||
symbol: CurrencySymbol,
|
||||
): Promise<any> => {
|
||||
const { wyre = {} as WyreChainSettings } = BUYABLE_CHAINS_MAP[chainId];
|
||||
const { srn, currencyCode } = wyre;
|
||||
|
||||
const networkId = parseInt(chainId, 16);
|
||||
@ -57,12 +64,16 @@ const createWyrePurchaseUrl = async (walletAddress, chainId, symbol) => {
|
||||
* Create a Transak Checkout URL.
|
||||
* API docs here: https://www.notion.so/Query-Parameters-9ec523df3b874ec58cef4fa3a906f238
|
||||
*
|
||||
* @param {string} walletAddress - Ethereum destination address
|
||||
* @param {string} chainId - Current chain ID
|
||||
* @param {string|undefined} symbol - Token symbol to buy
|
||||
* @param walletAddress - Ethereum destination address
|
||||
* @param chainId - Current chain ID
|
||||
* @param symbol - Token symbol to buy
|
||||
* @returns String
|
||||
*/
|
||||
const createTransakUrl = (walletAddress, chainId, symbol) => {
|
||||
const createTransakUrl = (
|
||||
walletAddress: string,
|
||||
chainId: keyof typeof BUYABLE_CHAINS_MAP,
|
||||
symbol: CurrencySymbol,
|
||||
): string => {
|
||||
const { nativeCurrency, network } = BUYABLE_CHAINS_MAP[chainId];
|
||||
|
||||
const queryParams = new URLSearchParams({
|
||||
@ -79,13 +90,17 @@ const createTransakUrl = (walletAddress, chainId, symbol) => {
|
||||
/**
|
||||
* Create a MoonPay Checkout URL.
|
||||
*
|
||||
* @param {string} walletAddress - Destination address
|
||||
* @param {string} chainId - Current chain ID
|
||||
* @param {string|undefined} symbol - Token symbol to buy
|
||||
* @param walletAddress - Destination address
|
||||
* @param chainId - Current chain ID
|
||||
* @param symbol - Token symbol to buy
|
||||
* @returns String
|
||||
*/
|
||||
const createMoonPayUrl = async (walletAddress, chainId, symbol) => {
|
||||
const { moonPay: { defaultCurrencyCode, showOnlyCurrencies } = {} } =
|
||||
const createMoonPayUrl = async (
|
||||
walletAddress: string,
|
||||
chainId: keyof typeof BUYABLE_CHAINS_MAP,
|
||||
symbol: CurrencySymbol,
|
||||
): Promise<string> => {
|
||||
const { moonPay: { defaultCurrencyCode, showOnlyCurrencies } = {} as any } =
|
||||
BUYABLE_CHAINS_MAP[chainId];
|
||||
const moonPayQueryParams = new URLSearchParams({
|
||||
apiKey: MOONPAY_API_KEY,
|
||||
@ -121,12 +136,16 @@ const createMoonPayUrl = async (walletAddress, chainId, symbol) => {
|
||||
/**
|
||||
* Create a Coinbase Pay Checkout URL.
|
||||
*
|
||||
* @param {string} walletAddress - Ethereum destination address
|
||||
* @param {string} chainId - Current chain ID
|
||||
* @param {string|undefined} symbol - Token symbol to buy
|
||||
* @param walletAddress - Ethereum destination address
|
||||
* @param chainId - Current chain ID
|
||||
* @param symbol - Token symbol to buy
|
||||
* @returns String
|
||||
*/
|
||||
const createCoinbasePayUrl = (walletAddress, chainId, symbol) => {
|
||||
const createCoinbasePayUrl = (
|
||||
walletAddress: string,
|
||||
chainId: keyof typeof BUYABLE_CHAINS_MAP,
|
||||
symbol: CurrencySymbol,
|
||||
): string => {
|
||||
// since coinbasePayCurrencies is going to be extended to include all tokens supported
|
||||
// we now default to nativeCurrency instead of the 2 previous tokens + eth that we had before
|
||||
const { nativeCurrency } = BUYABLE_CHAINS_MAP[chainId];
|
||||
@ -146,15 +165,25 @@ const createCoinbasePayUrl = (walletAddress, chainId, symbol) => {
|
||||
/**
|
||||
* Gives the caller a url at which the user can acquire eth, depending on the network they are in
|
||||
*
|
||||
* @param {object} opts - Options required to determine the correct url
|
||||
* @param {string} opts.chainId - The chainId for which to return a url
|
||||
* @param {string} opts.address - The address the bought ETH should be sent to. Only relevant if chainId === '0x1'.
|
||||
* @param opts - Options required to determine the correct url
|
||||
* @param opts.chainId - The chainId for which to return a url
|
||||
* @param opts.address - The address the bought ETH should be sent to. Only relevant if chainId === '0x1'.
|
||||
* @param opts.service
|
||||
* @param {string|undefined} opts.symbol - The symbol of the token to buy. Only relevant if buying a token.
|
||||
* @returns {string|undefined} The url at which the user can access ETH, while in the given chain. If the passed
|
||||
* @param opts.symbol - The symbol of the token to buy. Only relevant if buying a token.
|
||||
* @returns The url at which the user can access ETH, while in the given chain. If the passed
|
||||
* chainId does not match any of the specified cases, or if no chainId is given, returns undefined.
|
||||
*/
|
||||
export default async function getBuyUrl({ chainId, address, service, symbol }) {
|
||||
export default async function getBuyUrl({
|
||||
chainId,
|
||||
address,
|
||||
service,
|
||||
symbol,
|
||||
}: {
|
||||
chainId: keyof typeof BUYABLE_CHAINS_MAP;
|
||||
address: string;
|
||||
service: string;
|
||||
symbol: CurrencySymbol;
|
||||
}): Promise<string> {
|
||||
// default service by network if not specified
|
||||
if (!service) {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
@ -183,7 +212,7 @@ export default async function getBuyUrl({ chainId, address, service, symbol }) {
|
||||
}
|
||||
}
|
||||
|
||||
function getDefaultServiceForChain(chainId) {
|
||||
function getDefaultServiceForChain(chainId: ChainId): string {
|
||||
switch (chainId) {
|
||||
case CHAIN_IDS.MAINNET:
|
||||
return 'wyre';
|
@ -174,15 +174,19 @@ async function verifyEnglishLocale() {
|
||||
// and gradually phase out the key based search
|
||||
const globsToStrictSearch = [
|
||||
'ui/components/app/metamask-translation/*.js',
|
||||
'ui/components/app/metamask-translation/*.ts',
|
||||
'ui/pages/confirmation/templates/*.js',
|
||||
'ui/pages/confirmation/templates/*.ts',
|
||||
];
|
||||
const testGlob = '**/*.test.js';
|
||||
const javascriptFiles = await glob(
|
||||
[
|
||||
'ui/**/*.js',
|
||||
'ui/**/*.ts',
|
||||
'shared/**/*.js',
|
||||
'shared/**/*.ts',
|
||||
'app/scripts/constants/**/*.js',
|
||||
'app/scripts/constants/**/*.ts',
|
||||
],
|
||||
{
|
||||
ignore: [...globsToStrictSearch, testGlob],
|
||||
|
@ -306,7 +306,7 @@
|
||||
"labeled-stream-splicer": "^2.0.2",
|
||||
"localforage": "^1.9.0",
|
||||
"lodash": "^4.17.21",
|
||||
"loglevel": "^1.4.1",
|
||||
"loglevel": "^1.8.1",
|
||||
"luxon": "^3.2.1",
|
||||
"nanoid": "^2.1.6",
|
||||
"nonce-tracker": "^1.0.0",
|
||||
|
@ -17,7 +17,8 @@ export type ChainId = typeof CHAIN_IDS[keyof typeof CHAIN_IDS];
|
||||
* This type is non-exhaustive, and cannot be used for areas where the user
|
||||
* or dapp may supply their own symbol.
|
||||
*/
|
||||
type CurrencySymbol = typeof CURRENCY_SYMBOLS[keyof typeof CURRENCY_SYMBOLS];
|
||||
export type CurrencySymbol =
|
||||
typeof CURRENCY_SYMBOLS[keyof typeof CURRENCY_SYMBOLS];
|
||||
/**
|
||||
* A type that is a union type for the supported symbols on different onramp providers.
|
||||
*/
|
||||
@ -41,7 +42,7 @@ type MoonPayNetworkAbbreviation = 'BSC' | 'CCHAIN' | 'POLYGON';
|
||||
* MoonPay requires some settings that are configured per network that it is
|
||||
* enabled on. This type describes those settings.
|
||||
*/
|
||||
type MoonPayChainSettings = {
|
||||
export type MoonPayChainSettings = {
|
||||
/**
|
||||
* What should the default onramp currency be, for example 'eth' on 'mainnet'
|
||||
* This type matches a single SupportedCurrencySymbol or a
|
||||
@ -77,7 +78,7 @@ type RPCPreferences = {
|
||||
/**
|
||||
* An object that describes a network to be used inside of MetaMask
|
||||
*/
|
||||
type RPCDefinition = {
|
||||
export type RPCDefinition = {
|
||||
/**
|
||||
* The hex encoded ChainId for the network
|
||||
*/
|
||||
@ -104,7 +105,7 @@ type RPCDefinition = {
|
||||
* Wyre is a fiat onramp provider. We must provide some settings for networks
|
||||
* that support Wyre.
|
||||
*/
|
||||
type WyreChainSettings = {
|
||||
export type WyreChainSettings = {
|
||||
/**
|
||||
* The network name
|
||||
*/
|
||||
|
@ -20,7 +20,7 @@ export const SWAPS_FETCH_ORDER_CONFLICT = 'swaps-fetch-order-conflict';
|
||||
// in place of the token address that ERC-20 tokens have
|
||||
const DEFAULT_TOKEN_ADDRESS = '0x0000000000000000000000000000000000000000';
|
||||
|
||||
interface SwapsTokenObject {
|
||||
export interface SwapsTokenObject {
|
||||
/**
|
||||
* The symbol of token object
|
||||
*/
|
||||
|
@ -143,12 +143,13 @@ const getBaseUrlForNewSwapsApi = (type, chainId) => {
|
||||
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);
|
||||
export const getBaseApi = function (type, chainId) {
|
||||
const _chainId = TEST_CHAIN_IDS.includes(chainId)
|
||||
? CHAIN_IDS.MAINNET
|
||||
: chainId;
|
||||
const baseUrl = getBaseUrlForNewSwapsApi(type, _chainId);
|
||||
if (!baseUrl) {
|
||||
throw new Error(`Swaps API calls are disabled for chainId: ${chainId}`);
|
||||
throw new Error(`Swaps API calls are disabled for chainId: ${_chainId}`);
|
||||
}
|
||||
switch (type) {
|
||||
case 'trade':
|
||||
|
1
shared/modules/declare-modules.d.ts
vendored
Normal file
1
shared/modules/declare-modules.d.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
declare module 'human-standard-token-abi';
|
@ -49,7 +49,7 @@ import {
|
||||
isContractAddressValid,
|
||||
getSwapsLivenessForNetwork,
|
||||
parseSmartTransactionsError,
|
||||
stxErrorTypes,
|
||||
StxErrorTypes,
|
||||
} from '../../pages/swaps/swaps.util';
|
||||
import {
|
||||
addHexes,
|
||||
@ -206,9 +206,9 @@ const slice = createSlice({
|
||||
state.customGas.fallBackPrice = action.payload;
|
||||
},
|
||||
setCurrentSmartTransactionsError: (state, action) => {
|
||||
const errorType = Object.values(stxErrorTypes).includes(action.payload)
|
||||
const errorType = Object.values(StxErrorTypes).includes(action.payload)
|
||||
? action.payload
|
||||
: stxErrorTypes.UNAVAILABLE;
|
||||
: StxErrorTypes.UNAVAILABLE;
|
||||
state.currentSmartTransactionsError = errorType;
|
||||
},
|
||||
setSwapsSTXSubmitLoading: (state, action) => {
|
||||
@ -554,7 +554,7 @@ const disableStxIfRegularTxInProgress = (dispatch, transactions) => {
|
||||
for (const transaction of transactions) {
|
||||
if (IN_PROGRESS_TRANSACTION_STATUSES.includes(transaction.status)) {
|
||||
dispatch(
|
||||
setCurrentSmartTransactionsError(stxErrorTypes.REGULAR_TX_IN_PROGRESS),
|
||||
setCurrentSmartTransactionsError(StxErrorTypes.REGULAR_TX_IN_PROGRESS),
|
||||
);
|
||||
break;
|
||||
}
|
||||
@ -581,8 +581,8 @@ export const fetchSwapsLivenessAndFeatureFlags = () => {
|
||||
disableStxIfRegularTxInProgress(dispatch, transactions);
|
||||
}
|
||||
swapsLivenessForNetwork = getSwapsLivenessForNetwork(
|
||||
swapsFeatureFlags,
|
||||
chainId,
|
||||
swapsFeatureFlags,
|
||||
);
|
||||
} catch (error) {
|
||||
log.error(
|
||||
@ -621,8 +621,8 @@ export const fetchQuotesAndSetQuoteState = (
|
||||
try {
|
||||
const swapsFeatureFlags = await fetchSwapsFeatureFlags();
|
||||
swapsLivenessForNetwork = getSwapsLivenessForNetwork(
|
||||
swapsFeatureFlags,
|
||||
chainId,
|
||||
swapsFeatureFlags,
|
||||
);
|
||||
} catch (error) {
|
||||
log.error('Failed to fetch Swaps liveness, defaulting to false.', error);
|
||||
@ -939,7 +939,7 @@ export const signAndSendSwapsSmartTransaction = ({
|
||||
if (!fees) {
|
||||
log.error('"fetchSwapsSmartTransactionFees" failed');
|
||||
dispatch(setSwapsSTXSubmitLoading(false));
|
||||
dispatch(setCurrentSmartTransactionsError(stxErrorTypes.UNAVAILABLE));
|
||||
dispatch(setCurrentSmartTransactionsError(StxErrorTypes.UNAVAILABLE));
|
||||
return;
|
||||
}
|
||||
if (approveTxParams) {
|
||||
@ -1020,8 +1020,8 @@ export const signAndSendTransactions = (
|
||||
try {
|
||||
const swapsFeatureFlags = await fetchSwapsFeatureFlags();
|
||||
swapsLivenessForNetwork = getSwapsLivenessForNetwork(
|
||||
swapsFeatureFlags,
|
||||
chainId,
|
||||
swapsFeatureFlags,
|
||||
);
|
||||
} catch (error) {
|
||||
log.error('Failed to fetch Swaps liveness, defaulting to false.', error);
|
||||
@ -1329,7 +1329,7 @@ export function fetchSwapsSmartTransactionFees({
|
||||
const errorObj = parseSmartTransactionsError(e.message);
|
||||
if (
|
||||
fallbackOnNotEnoughFunds ||
|
||||
errorObj?.error !== stxErrorTypes.NOT_ENOUGH_FUNDS
|
||||
errorObj?.error !== StxErrorTypes.NOT_ENOUGH_FUNDS
|
||||
) {
|
||||
dispatch(setCurrentSmartTransactionsError(errorObj?.error));
|
||||
}
|
||||
|
@ -129,7 +129,7 @@ describe('i18n helper', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should correctly render falsey substitutions', () => {
|
||||
it('should correctly render falsy substitutions', () => {
|
||||
const result = t(TEST_KEY_4, [0, -0, '', false, NaN]);
|
||||
expect(result).toStrictEqual('0 - 0 - - false - NaN');
|
||||
});
|
||||
|
@ -1,25 +1,60 @@
|
||||
// cross-browser connection to extension i18n API
|
||||
import React from 'react';
|
||||
import log from 'loglevel';
|
||||
import { Json } from '@metamask/utils';
|
||||
import * as Sentry from '@sentry/browser';
|
||||
import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout';
|
||||
|
||||
const fetchWithTimeout = getFetchWithTimeout();
|
||||
|
||||
const warned = {};
|
||||
const missingMessageErrors = {};
|
||||
const missingSubstitutionErrors = {};
|
||||
// From app/_locales folders there is a messages.json file such as app/_locales/en, comes with key and translated results
|
||||
// and we use as t('reject') to get the translated message in the codebase
|
||||
// and in i18n lib, the translated message is an object (I18NMessage) with message & description -
|
||||
// message is the string that will replace the translationKey, and that message may contain replacement variables such as $1, $2, etc.
|
||||
// Description is key describing the usage of the message.
|
||||
interface I18NMessage {
|
||||
message: string;
|
||||
description?: string;
|
||||
}
|
||||
|
||||
// The overall translation file is made of same entries
|
||||
// translationKey (string) and the I18NMessage as the value.
|
||||
interface I18NMessageDict {
|
||||
[translationKey: string]: I18NMessage;
|
||||
}
|
||||
|
||||
// A parameterized type (or generic type) of maps that use the same structure (translationKey) key
|
||||
interface I18NMessageDictMap<R> {
|
||||
[translationKey: string]: R;
|
||||
}
|
||||
|
||||
const warned: { [localeCode: string]: I18NMessageDictMap<boolean> } = {};
|
||||
const missingMessageErrors: I18NMessageDictMap<Error> = {};
|
||||
const missingSubstitutionErrors: {
|
||||
[localeCode: string]: I18NMessageDictMap<boolean>;
|
||||
} = {};
|
||||
|
||||
function getHasSubstitutions(
|
||||
substitutions?: string[],
|
||||
): substitutions is string[] {
|
||||
return (substitutions?.length ?? 0) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a localized message for the given key
|
||||
*
|
||||
* @param {string} localeCode - The code for the current locale
|
||||
* @param {object} localeMessages - The map of messages for the current locale
|
||||
* @param {string} key - The message key
|
||||
* @param {string[]} substitutions - A list of message substitution replacements
|
||||
* @returns {null|string} The localized message
|
||||
* @param localeCode - The code for the current locale
|
||||
* @param localeMessages - The map of messages for the current locale
|
||||
* @param key - The message key
|
||||
* @param substitutions - A list of message substitution replacements can replace $n in given message
|
||||
* @returns The localized message
|
||||
*/
|
||||
export const getMessage = (localeCode, localeMessages, key, substitutions) => {
|
||||
export const getMessage = (
|
||||
localeCode: string,
|
||||
localeMessages: I18NMessageDict,
|
||||
key: string,
|
||||
substitutions?: string[],
|
||||
): JSX.Element | string | null => {
|
||||
if (!localeMessages) {
|
||||
return null;
|
||||
}
|
||||
@ -46,23 +81,22 @@ export const getMessage = (localeCode, localeMessages, key, substitutions) => {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
const entry = localeMessages[key];
|
||||
let phrase = entry.message;
|
||||
|
||||
const hasSubstitutions = Boolean(substitutions && substitutions.length);
|
||||
const hasSubstitutions = getHasSubstitutions(substitutions);
|
||||
const hasReactSubstitutions =
|
||||
hasSubstitutions &&
|
||||
substitutions.some(
|
||||
substitutions?.some(
|
||||
(element) =>
|
||||
element !== null &&
|
||||
(typeof element === 'function' || typeof element === 'object'),
|
||||
);
|
||||
|
||||
const entry = localeMessages[key];
|
||||
const phrase = entry.message;
|
||||
// perform substitutions
|
||||
if (hasSubstitutions) {
|
||||
const parts = phrase.split(/(\$\d)/gu);
|
||||
|
||||
const substitutedParts = parts.map((part) => {
|
||||
const substitutedParts = parts.map((part: string) => {
|
||||
const subMatch = part.match(/\$(\d)/u);
|
||||
if (!subMatch) {
|
||||
return part;
|
||||
@ -83,20 +117,21 @@ export const getMessage = (localeCode, localeMessages, key, substitutions) => {
|
||||
log.error(error);
|
||||
Sentry.captureException(error);
|
||||
}
|
||||
return substitutions[substituteIndex];
|
||||
return substitutions?.[substituteIndex];
|
||||
});
|
||||
|
||||
phrase = hasReactSubstitutions ? (
|
||||
return hasReactSubstitutions ? (
|
||||
<span> {substitutedParts} </span>
|
||||
) : (
|
||||
substitutedParts.join('')
|
||||
);
|
||||
}
|
||||
|
||||
return phrase;
|
||||
};
|
||||
|
||||
export async function fetchLocale(localeCode) {
|
||||
export async function fetchLocale(
|
||||
localeCode: string,
|
||||
): Promise<I18NMessageDict> {
|
||||
try {
|
||||
const response = await fetchWithTimeout(
|
||||
`./_locales/${localeCode}/messages.json`,
|
||||
@ -110,19 +145,21 @@ export async function fetchLocale(localeCode) {
|
||||
|
||||
const relativeTimeFormatLocaleData = new Set();
|
||||
|
||||
export async function loadRelativeTimeFormatLocaleData(localeCode) {
|
||||
export async function loadRelativeTimeFormatLocaleData(
|
||||
localeCode: string,
|
||||
): Promise<void> {
|
||||
const languageTag = localeCode.split('_')[0];
|
||||
if (
|
||||
Intl.RelativeTimeFormat &&
|
||||
typeof Intl.RelativeTimeFormat.__addLocaleData === 'function' &&
|
||||
typeof (Intl.RelativeTimeFormat as any).__addLocaleData === 'function' &&
|
||||
!relativeTimeFormatLocaleData.has(languageTag)
|
||||
) {
|
||||
const localeData = await fetchRelativeTimeFormatData(languageTag);
|
||||
Intl.RelativeTimeFormat.__addLocaleData(localeData);
|
||||
(Intl.RelativeTimeFormat as any).__addLocaleData(localeData);
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchRelativeTimeFormatData(languageTag) {
|
||||
async function fetchRelativeTimeFormatData(languageTag: string): Promise<Json> {
|
||||
const response = await fetchWithTimeout(
|
||||
`./intl/${languageTag}/relative-time-format-data.json`,
|
||||
);
|
@ -3,7 +3,10 @@ import {
|
||||
CHAIN_IDS,
|
||||
} from '../../../shared/constants/network';
|
||||
|
||||
export const formatMoonpaySymbol = (symbol, chainId = CHAIN_IDS.MAINNET) => {
|
||||
export const formatMoonpaySymbol = (
|
||||
symbol: string | null,
|
||||
chainId: keyof typeof BUYABLE_CHAINS_MAP,
|
||||
): string | null => {
|
||||
if (!symbol) {
|
||||
return symbol;
|
||||
}
|
@ -11,7 +11,16 @@ describe('txHelper', () => {
|
||||
c: { metamaskNetworkId, time: 2 },
|
||||
};
|
||||
|
||||
const sorted = txHelper(txs, null, null, metamaskNetworkId, chainId);
|
||||
const sorted = txHelper(
|
||||
txs,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
metamaskNetworkId,
|
||||
chainId,
|
||||
);
|
||||
expect(sorted[0].time).toStrictEqual(1);
|
||||
expect(sorted[2].time).toStrictEqual(3);
|
||||
});
|
||||
|
@ -3,15 +3,15 @@ import { transactionMatchesNetwork } from '../../../shared/modules/transaction.u
|
||||
import { valuesFor } from './util';
|
||||
|
||||
export default function txHelper(
|
||||
unapprovedTxs,
|
||||
unapprovedMsgs,
|
||||
personalMsgs,
|
||||
decryptMsgs,
|
||||
encryptionPublicKeyMsgs,
|
||||
typedMessages,
|
||||
network,
|
||||
chainId,
|
||||
) {
|
||||
unapprovedTxs: Record<string, any> | null,
|
||||
unapprovedMsgs: Record<string, any> | null,
|
||||
personalMsgs: Record<string, any> | null,
|
||||
decryptMsgs: Record<string, any> | null,
|
||||
encryptionPublicKeyMsgs: Record<string, any> | null,
|
||||
typedMessages: Record<string, any> | null,
|
||||
network: string,
|
||||
chainId: string,
|
||||
): Record<string, any> {
|
||||
log.debug('tx-helper called with params:');
|
||||
log.debug({
|
||||
unapprovedTxs,
|
@ -173,6 +173,7 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
setRecoveryPhraseReminderLastShown: (lastShown) =>
|
||||
dispatch(setRecoveryPhraseReminderLastShown(lastShown)),
|
||||
setNewNetworkAdded: (newNetwork) => {
|
||||
console.log({ newNetwork });
|
||||
dispatch(setNewNetworkAdded(newNetwork));
|
||||
},
|
||||
setNewCollectibleAddedMessage: (message) => {
|
||||
|
@ -267,8 +267,8 @@ describe('Swaps Util', () => {
|
||||
};
|
||||
expect(
|
||||
getSwapsLivenessForNetwork(
|
||||
MOCKS.createFeatureFlagsResponse(),
|
||||
CHAIN_IDS.LOCALHOST,
|
||||
MOCKS.createFeatureFlagsResponse(),
|
||||
),
|
||||
).toMatchObject(expectedSwapsLiveness);
|
||||
});
|
||||
@ -279,8 +279,8 @@ describe('Swaps Util', () => {
|
||||
};
|
||||
expect(
|
||||
getSwapsLivenessForNetwork(
|
||||
MOCKS.createFeatureFlagsResponse(),
|
||||
CHAIN_IDS.GOERLI,
|
||||
MOCKS.createFeatureFlagsResponse(),
|
||||
),
|
||||
).toMatchObject(expectedSwapsLiveness);
|
||||
});
|
||||
@ -291,8 +291,8 @@ describe('Swaps Util', () => {
|
||||
};
|
||||
expect(
|
||||
getSwapsLivenessForNetwork(
|
||||
MOCKS.createFeatureFlagsResponse(),
|
||||
CHAIN_IDS.SEPOLIA,
|
||||
MOCKS.createFeatureFlagsResponse(),
|
||||
),
|
||||
).toMatchObject(expectedSwapsLiveness);
|
||||
});
|
||||
@ -303,8 +303,8 @@ describe('Swaps Util', () => {
|
||||
};
|
||||
expect(
|
||||
getSwapsLivenessForNetwork(
|
||||
MOCKS.createFeatureFlagsResponse(),
|
||||
CHAIN_IDS.MAINNET,
|
||||
MOCKS.createFeatureFlagsResponse(),
|
||||
),
|
||||
).toMatchObject(expectedSwapsLiveness);
|
||||
});
|
||||
@ -316,7 +316,7 @@ describe('Swaps Util', () => {
|
||||
const swapsFeatureFlags = MOCKS.createFeatureFlagsResponse();
|
||||
swapsFeatureFlags[ETHEREUM].extensionActive = false;
|
||||
expect(
|
||||
getSwapsLivenessForNetwork(swapsFeatureFlags, CHAIN_IDS.MAINNET),
|
||||
getSwapsLivenessForNetwork(CHAIN_IDS.MAINNET, swapsFeatureFlags),
|
||||
).toMatchObject(expectedSwapsLiveness);
|
||||
});
|
||||
});
|
||||
|
@ -1,24 +1,27 @@
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { BigNumber } from 'bignumber.js';
|
||||
import abi from 'human-standard-token-abi';
|
||||
import { Json } from '@metamask/controller-utils';
|
||||
import { IndividualTxFees } from '@metamask/smart-transactions-controller/dist/types';
|
||||
import {
|
||||
SWAPS_CHAINID_DEFAULT_TOKEN_MAP,
|
||||
ALLOWED_CONTRACT_ADDRESSES,
|
||||
ETHEREUM,
|
||||
POLYGON,
|
||||
BSC,
|
||||
GOERLI,
|
||||
AVALANCHE,
|
||||
OPTIMISM,
|
||||
ARBITRUM,
|
||||
AVALANCHE,
|
||||
BSC,
|
||||
ETHEREUM,
|
||||
GOERLI,
|
||||
OPTIMISM,
|
||||
POLYGON,
|
||||
SWAPS_API_V2_BASE_URL,
|
||||
SWAPS_DEV_API_V2_BASE_URL,
|
||||
SWAPS_CHAINID_DEFAULT_TOKEN_MAP,
|
||||
SWAPS_CLIENT_ID,
|
||||
SWAPS_DEV_API_V2_BASE_URL,
|
||||
SwapsTokenObject,
|
||||
} from '../../../shared/constants/swaps';
|
||||
import {
|
||||
isSwapsDefaultTokenAddress,
|
||||
isSwapsDefaultTokenSymbol,
|
||||
} from '../../../shared/modules/swaps.utils';
|
||||
import { CHAIN_IDS, CURRENCY_SYMBOLS } from '../../../shared/constants/network';
|
||||
import { CHAIN_IDS } from '../../../shared/constants/network';
|
||||
import { formatCurrency } from '../../helpers/utils/confirm-tx.util';
|
||||
import fetchWithCache from '../../../shared/lib/fetch-with-cache';
|
||||
|
||||
@ -38,13 +41,20 @@ import {
|
||||
getValueFromWeiHex,
|
||||
sumHexes,
|
||||
} from '../../../shared/modules/conversion.utils';
|
||||
import { EtherDenomination } from '../../../shared/constants/common';
|
||||
|
||||
const CACHE_REFRESH_FIVE_MINUTES = 300000;
|
||||
const USD_CURRENCY_CODE = 'usd';
|
||||
|
||||
const clientIdHeader = { 'X-Client-Id': SWAPS_CLIENT_ID };
|
||||
|
||||
const TOKEN_VALIDATORS = [
|
||||
interface Validator {
|
||||
property: string;
|
||||
type: string;
|
||||
validator: (a: string) => boolean;
|
||||
}
|
||||
|
||||
const TOKEN_VALIDATORS: Validator[] = [
|
||||
{
|
||||
property: 'address',
|
||||
type: 'string',
|
||||
@ -64,7 +74,7 @@ const TOKEN_VALIDATORS = [
|
||||
|
||||
const TOP_ASSET_VALIDATORS = TOKEN_VALIDATORS.slice(0, 2);
|
||||
|
||||
const AGGREGATOR_METADATA_VALIDATORS = [
|
||||
const AGGREGATOR_METADATA_VALIDATORS: Validator[] = [
|
||||
{
|
||||
property: 'color',
|
||||
type: 'string',
|
||||
@ -82,10 +92,10 @@ const AGGREGATOR_METADATA_VALIDATORS = [
|
||||
},
|
||||
];
|
||||
|
||||
const isValidDecimalNumber = (string) =>
|
||||
const isValidDecimalNumber = (string: any): boolean =>
|
||||
!isNaN(string) && string.match(/^[.0-9]+$/u) && !isNaN(parseFloat(string));
|
||||
|
||||
const SWAP_GAS_PRICE_VALIDATOR = [
|
||||
const SWAP_GAS_PRICE_VALIDATOR: Validator[] = [
|
||||
{
|
||||
property: 'SafeGasPrice',
|
||||
type: 'string',
|
||||
@ -103,17 +113,22 @@ const SWAP_GAS_PRICE_VALIDATOR = [
|
||||
},
|
||||
];
|
||||
|
||||
export async function fetchToken(contractAddress, chainId) {
|
||||
export async function fetchToken(
|
||||
contractAddress: string,
|
||||
chainId: any,
|
||||
): Promise<Json> {
|
||||
const tokenUrl = getBaseApi('token', chainId);
|
||||
const token = await fetchWithCache(
|
||||
return await fetchWithCache(
|
||||
`${tokenUrl}?address=${contractAddress}`,
|
||||
{ method: 'GET', headers: clientIdHeader },
|
||||
{ cacheRefreshTime: CACHE_REFRESH_FIVE_MINUTES },
|
||||
);
|
||||
return token;
|
||||
}
|
||||
|
||||
export async function fetchTokens(chainId) {
|
||||
type Token = { symbol: string; address: string };
|
||||
export async function fetchTokens(
|
||||
chainId: keyof typeof SWAPS_CHAINID_DEFAULT_TOKEN_MAP,
|
||||
): Promise<SwapsTokenObject[]> {
|
||||
const tokensUrl = getBaseApi('tokens', chainId);
|
||||
const tokens = await fetchWithCache(
|
||||
tokensUrl,
|
||||
@ -121,9 +136,10 @@ export async function fetchTokens(chainId) {
|
||||
{ cacheRefreshTime: CACHE_REFRESH_FIVE_MINUTES },
|
||||
);
|
||||
const logError = false;
|
||||
const filteredTokens = [
|
||||
SWAPS_CHAINID_DEFAULT_TOKEN_MAP[chainId],
|
||||
...tokens.filter((token) => {
|
||||
const tokenObject = SWAPS_CHAINID_DEFAULT_TOKEN_MAP[chainId] || null;
|
||||
return [
|
||||
tokenObject,
|
||||
...tokens.filter((token: Token) => {
|
||||
return (
|
||||
validateData(TOKEN_VALIDATORS, token, tokensUrl, logError) &&
|
||||
!(
|
||||
@ -133,17 +149,16 @@ export async function fetchTokens(chainId) {
|
||||
);
|
||||
}),
|
||||
];
|
||||
return filteredTokens;
|
||||
}
|
||||
|
||||
export async function fetchAggregatorMetadata(chainId) {
|
||||
export async function fetchAggregatorMetadata(chainId: any): Promise<object> {
|
||||
const aggregatorMetadataUrl = getBaseApi('aggregatorMetadata', chainId);
|
||||
const aggregators = await fetchWithCache(
|
||||
aggregatorMetadataUrl,
|
||||
{ method: 'GET', headers: clientIdHeader },
|
||||
{ cacheRefreshTime: CACHE_REFRESH_FIVE_MINUTES },
|
||||
);
|
||||
const filteredAggregators = {};
|
||||
const filteredAggregators = {} as any;
|
||||
for (const aggKey in aggregators) {
|
||||
if (
|
||||
validateData(
|
||||
@ -158,7 +173,7 @@ export async function fetchAggregatorMetadata(chainId) {
|
||||
return filteredAggregators;
|
||||
}
|
||||
|
||||
export async function fetchTopAssets(chainId) {
|
||||
export async function fetchTopAssets(chainId: any): Promise<object> {
|
||||
const topAssetsUrl = getBaseApi('topAssets', chainId);
|
||||
const response =
|
||||
(await fetchWithCache(
|
||||
@ -166,28 +181,30 @@ export async function fetchTopAssets(chainId) {
|
||||
{ method: 'GET', headers: clientIdHeader },
|
||||
{ cacheRefreshTime: CACHE_REFRESH_FIVE_MINUTES },
|
||||
)) || [];
|
||||
const topAssetsMap = response.reduce((_topAssetsMap, asset, index) => {
|
||||
if (validateData(TOP_ASSET_VALIDATORS, asset, topAssetsUrl)) {
|
||||
return { ..._topAssetsMap, [asset.address]: { index: String(index) } };
|
||||
}
|
||||
return _topAssetsMap;
|
||||
}, {});
|
||||
const topAssetsMap = response.reduce(
|
||||
(_topAssetsMap: any, asset: { address: string }, index: number) => {
|
||||
if (validateData(TOP_ASSET_VALIDATORS, asset, topAssetsUrl)) {
|
||||
return { ..._topAssetsMap, [asset.address]: { index: String(index) } };
|
||||
}
|
||||
return _topAssetsMap;
|
||||
},
|
||||
{},
|
||||
);
|
||||
return topAssetsMap;
|
||||
}
|
||||
|
||||
export async function fetchSwapsFeatureFlags() {
|
||||
export async function fetchSwapsFeatureFlags(): Promise<any> {
|
||||
const v2ApiBaseUrl = process.env.SWAPS_USE_DEV_APIS
|
||||
? SWAPS_DEV_API_V2_BASE_URL
|
||||
: SWAPS_API_V2_BASE_URL;
|
||||
const response = await fetchWithCache(
|
||||
return await fetchWithCache(
|
||||
`${v2ApiBaseUrl}/featureFlags`,
|
||||
{ method: 'GET', headers: clientIdHeader },
|
||||
{ cacheRefreshTime: 600000 },
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
||||
export async function fetchTokenPrice(address) {
|
||||
export async function fetchTokenPrice(address: string): Promise<any> {
|
||||
const query = `contract_addresses=${address}&vs_currencies=eth`;
|
||||
|
||||
const prices = await fetchWithCache(
|
||||
@ -195,19 +212,28 @@ export async function fetchTokenPrice(address) {
|
||||
{ method: 'GET' },
|
||||
{ cacheRefreshTime: 60000 },
|
||||
);
|
||||
return prices && prices[address]?.eth;
|
||||
return prices?.[address]?.eth;
|
||||
}
|
||||
|
||||
export async function fetchTokenBalance(address, userAddress) {
|
||||
const tokenContract = global.eth.contract(abi).at(address);
|
||||
export async function fetchTokenBalance(
|
||||
address: string,
|
||||
userAddress: string,
|
||||
): Promise<any> {
|
||||
const tokenContract = (global as any).eth.contract(abi).at(address);
|
||||
const tokenBalancePromise = tokenContract
|
||||
? tokenContract.balanceOf(userAddress)
|
||||
: Promise.resolve();
|
||||
const usersToken = await tokenBalancePromise;
|
||||
return usersToken;
|
||||
return await tokenBalancePromise;
|
||||
}
|
||||
|
||||
export async function fetchSwapsGasPrices(chainId) {
|
||||
export async function fetchSwapsGasPrices(chainId: any): Promise<
|
||||
| any
|
||||
| {
|
||||
safeLow: string;
|
||||
average: string;
|
||||
fast: string;
|
||||
}
|
||||
> {
|
||||
const gasPricesUrl = getBaseApi('gasPrices', chainId);
|
||||
const response = await fetchWithCache(
|
||||
gasPricesUrl,
|
||||
@ -244,11 +270,18 @@ export const getFeeForSmartTransaction = ({
|
||||
USDConversionRate,
|
||||
nativeCurrencySymbol,
|
||||
feeInWeiDec,
|
||||
}: {
|
||||
chainId: keyof typeof SWAPS_CHAINID_DEFAULT_TOKEN_MAP;
|
||||
currentCurrency: string;
|
||||
conversionRate: number;
|
||||
USDConversionRate?: number;
|
||||
nativeCurrencySymbol: string;
|
||||
feeInWeiDec: number;
|
||||
}) => {
|
||||
const feeInWeiHex = decimalToHex(feeInWeiDec);
|
||||
const ethFee = getValueFromWeiHex({
|
||||
value: feeInWeiHex,
|
||||
toDenomination: CURRENCY_SYMBOLS.ETH,
|
||||
toDenomination: EtherDenomination.ETH,
|
||||
numberOfDecimals: 5,
|
||||
});
|
||||
const rawNetworkFees = getValueFromWeiHex({
|
||||
@ -270,7 +303,7 @@ export const getFeeForSmartTransaction = ({
|
||||
}
|
||||
const formattedNetworkFee = formatCurrency(rawNetworkFees, currentCurrency);
|
||||
const chainCurrencySymbolToUse =
|
||||
nativeCurrencySymbol || SWAPS_CHAINID_DEFAULT_TOKEN_MAP[chainId].symbol;
|
||||
nativeCurrencySymbol || SWAPS_CHAINID_DEFAULT_TOKEN_MAP[chainId]?.symbol;
|
||||
return {
|
||||
feeInUsd,
|
||||
feeInFiat: formattedNetworkFee,
|
||||
@ -292,7 +325,27 @@ export function getRenderableNetworkFeesForQuote({
|
||||
chainId,
|
||||
nativeCurrencySymbol,
|
||||
multiLayerL1FeeTotal,
|
||||
}) {
|
||||
}: {
|
||||
tradeGas: string;
|
||||
approveGas: string;
|
||||
gasPrice: string;
|
||||
currentCurrency: string;
|
||||
conversionRate: number;
|
||||
USDConversionRate?: number;
|
||||
tradeValue: number;
|
||||
sourceSymbol: string;
|
||||
sourceAmount: number;
|
||||
chainId: keyof typeof SWAPS_CHAINID_DEFAULT_TOKEN_MAP;
|
||||
nativeCurrencySymbol?: string;
|
||||
multiLayerL1FeeTotal: string | null;
|
||||
}): {
|
||||
rawNetworkFees: string | number | BigNumber;
|
||||
feeInUsd: string | number | BigNumber;
|
||||
rawEthFee: string | number | BigNumber;
|
||||
feeInFiat: string;
|
||||
feeInEth: string;
|
||||
nonGasFee: string;
|
||||
} {
|
||||
const totalGasLimitForCalculation = new BigNumber(tradeGas || '0x0', 16)
|
||||
.plus(approveGas || '0x0', 16)
|
||||
.toString(16);
|
||||
@ -314,10 +367,9 @@ export function getRenderableNetworkFeesForQuote({
|
||||
const totalWeiCost = new BigNumber(gasTotalInWeiHex, 16)
|
||||
.plus(nonGasFee, 16)
|
||||
.toString(16);
|
||||
|
||||
const ethFee = getValueFromWeiHex({
|
||||
value: totalWeiCost,
|
||||
toDenomination: 'ETH',
|
||||
toDenomination: EtherDenomination.ETH,
|
||||
numberOfDecimals: 5,
|
||||
});
|
||||
const rawNetworkFees = getValueFromWeiHex({
|
||||
@ -353,7 +405,7 @@ export function getRenderableNetworkFeesForQuote({
|
||||
};
|
||||
}
|
||||
|
||||
export function quotesToRenderableData(
|
||||
export function quotesToRenderableData({
|
||||
quotes,
|
||||
gasPrice,
|
||||
conversionRate,
|
||||
@ -364,7 +416,18 @@ export function quotesToRenderableData(
|
||||
smartTransactionEstimatedGas,
|
||||
nativeCurrencySymbol,
|
||||
multiLayerL1ApprovalFeeTotal,
|
||||
) {
|
||||
}: {
|
||||
quotes: object;
|
||||
gasPrice: string;
|
||||
conversionRate: number;
|
||||
currentCurrency: string;
|
||||
approveGas: string;
|
||||
tokenConversionRates: Record<string, any>;
|
||||
chainId: keyof typeof SWAPS_CHAINID_DEFAULT_TOKEN_MAP;
|
||||
smartTransactionEstimatedGas: IndividualTxFees;
|
||||
nativeCurrencySymbol: string;
|
||||
multiLayerL1ApprovalFeeTotal: string | null;
|
||||
}): Record<string, any> {
|
||||
return Object.values(quotes).map((quote) => {
|
||||
const {
|
||||
destinationAmount = 0,
|
||||
@ -426,7 +489,7 @@ export function quotesToRenderableData(
|
||||
currentCurrency,
|
||||
conversionRate,
|
||||
nativeCurrencySymbol,
|
||||
estimatedFeeInWeiDec: smartTransactionEstimatedGas.feeEstimate,
|
||||
feeInWeiDec: smartTransactionEstimatedGas.feeEstimate,
|
||||
}));
|
||||
}
|
||||
|
||||
@ -494,7 +557,7 @@ export function quotesToRenderableData(
|
||||
});
|
||||
}
|
||||
|
||||
export function formatSwapsValueForDisplay(destinationAmount) {
|
||||
export function formatSwapsValueForDisplay(destinationAmount: string): string {
|
||||
let amountToDisplay = toPrecisionWithoutTrailingZeros(destinationAmount, 12);
|
||||
if (amountToDisplay.match(/e[+-]/u)) {
|
||||
amountToDisplay = new BigNumber(amountToDisplay).toFixed();
|
||||
@ -505,30 +568,30 @@ export function formatSwapsValueForDisplay(destinationAmount) {
|
||||
/**
|
||||
* Checks whether a contract address is valid before swapping tokens.
|
||||
*
|
||||
* @param {string} contractAddress - E.g. "0x881d40237659c251811cec9c364ef91dc08d300c" for mainnet
|
||||
* @param {string} chainId - The hex encoded chain ID to check
|
||||
* @returns {boolean} Whether a contract address is valid or not
|
||||
* @param contractAddress - E.g. "0x881d40237659c251811cec9c364ef91dc08d300c" for mainnet
|
||||
* @param chainId - The hex encoded chain ID to check
|
||||
* @returns Whether a contract address is valid or not
|
||||
*/
|
||||
export const isContractAddressValid = (
|
||||
contractAddress,
|
||||
chainId = CHAIN_IDS.MAINNET,
|
||||
) => {
|
||||
contractAddress: string,
|
||||
chainId: keyof typeof ALLOWED_CONTRACT_ADDRESSES,
|
||||
): boolean => {
|
||||
if (!contractAddress || !ALLOWED_CONTRACT_ADDRESSES[chainId]) {
|
||||
return false;
|
||||
}
|
||||
return ALLOWED_CONTRACT_ADDRESSES[chainId].some(
|
||||
// Sometimes we get a contract address with a few upper-case chars and since addresses are
|
||||
// case-insensitive, we compare lowercase versions for validity.
|
||||
(allowedContractAddress) =>
|
||||
(allowedContractAddress: string) =>
|
||||
contractAddress.toLowerCase() === allowedContractAddress.toLowerCase(),
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {string} chainId
|
||||
* @param chainId
|
||||
* @returns string e.g. ethereum, bsc or polygon
|
||||
*/
|
||||
export const getNetworkNameByChainId = (chainId) => {
|
||||
export const getNetworkNameByChainId = (chainId: string): string => {
|
||||
switch (chainId) {
|
||||
case CHAIN_IDS.MAINNET:
|
||||
return ETHEREUM;
|
||||
@ -552,11 +615,14 @@ export const getNetworkNameByChainId = (chainId) => {
|
||||
/**
|
||||
* It returns info about if Swaps are enabled and if we should use our new APIs for it.
|
||||
*
|
||||
* @param {object} swapsFeatureFlags
|
||||
* @param {string} chainId
|
||||
* @param chainId
|
||||
* @param swapsFeatureFlags
|
||||
* @returns object with 2 items: "swapsFeatureIsLive"
|
||||
*/
|
||||
export const getSwapsLivenessForNetwork = (swapsFeatureFlags = {}, chainId) => {
|
||||
export const getSwapsLivenessForNetwork = (
|
||||
chainId: any,
|
||||
swapsFeatureFlags: any = {},
|
||||
) => {
|
||||
const networkName = getNetworkNameByChainId(chainId);
|
||||
// Use old APIs for testnet and Goerli.
|
||||
if ([CHAIN_IDS.LOCALHOST, CHAIN_IDS.GOERLI].includes(chainId)) {
|
||||
@ -583,17 +649,19 @@ export const getSwapsLivenessForNetwork = (swapsFeatureFlags = {}, chainId) => {
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} value
|
||||
* @param value
|
||||
* @returns number
|
||||
*/
|
||||
export const countDecimals = (value) => {
|
||||
export const countDecimals = (value: any): number => {
|
||||
if (!value || Math.floor(value) === value) {
|
||||
return 0;
|
||||
}
|
||||
return value.toString().split('.')[1]?.length || 0;
|
||||
};
|
||||
|
||||
export const showRemainingTimeInMinAndSec = (remainingTimeInSec) => {
|
||||
export const showRemainingTimeInMinAndSec = (
|
||||
remainingTimeInSec: any,
|
||||
): string => {
|
||||
if (!Number.isInteger(remainingTimeInSec)) {
|
||||
return '0:00';
|
||||
}
|
||||
@ -602,25 +670,28 @@ export const showRemainingTimeInMinAndSec = (remainingTimeInSec) => {
|
||||
return `${minutes}:${seconds.toString().padStart(2, '0')}`;
|
||||
};
|
||||
|
||||
export const stxErrorTypes = {
|
||||
UNAVAILABLE: 'unavailable',
|
||||
NOT_ENOUGH_FUNDS: 'not_enough_funds',
|
||||
REGULAR_TX_IN_PROGRESS: 'regular_tx_pending',
|
||||
};
|
||||
export enum StxErrorTypes {
|
||||
unavailable = 'unavailable',
|
||||
notEnoughFunds = 'not_enough_funds',
|
||||
regularTxPending = 'regular_tx_pending',
|
||||
}
|
||||
|
||||
export const getTranslatedStxErrorMessage = (errorType, t) => {
|
||||
export const getTranslatedStxErrorMessage = (
|
||||
errorType: StxErrorTypes,
|
||||
t: (...args: any[]) => string,
|
||||
): string => {
|
||||
switch (errorType) {
|
||||
case stxErrorTypes.UNAVAILABLE:
|
||||
case stxErrorTypes.REGULAR_TX_IN_PROGRESS:
|
||||
case StxErrorTypes.unavailable:
|
||||
case StxErrorTypes.regularTxPending:
|
||||
return t('stxErrorUnavailable');
|
||||
case stxErrorTypes.NOT_ENOUGH_FUNDS:
|
||||
case StxErrorTypes.notEnoughFunds:
|
||||
return t('stxErrorNotEnoughFunds');
|
||||
default:
|
||||
return t('stxErrorUnavailable');
|
||||
}
|
||||
};
|
||||
|
||||
export const parseSmartTransactionsError = (errorMessage) => {
|
||||
export const parseSmartTransactionsError = (errorMessage: string): string => {
|
||||
const errorJson = errorMessage.slice(12);
|
||||
return JSON.parse(errorJson.trim());
|
||||
};
|
@ -297,20 +297,23 @@ export default function ViewQuote() {
|
||||
const approveGas = approveTxParams?.gas;
|
||||
|
||||
const renderablePopoverData = useMemo(() => {
|
||||
return quotesToRenderableData(
|
||||
return quotesToRenderableData({
|
||||
quotes,
|
||||
networkAndAccountSupports1559 ? baseAndPriorityFeePerGas : gasPrice,
|
||||
gasPrice: networkAndAccountSupports1559
|
||||
? baseAndPriorityFeePerGas
|
||||
: gasPrice,
|
||||
conversionRate,
|
||||
currentCurrency,
|
||||
approveGas,
|
||||
memoizedTokenConversionRates,
|
||||
tokenConversionRates: memoizedTokenConversionRates,
|
||||
chainId,
|
||||
smartTransactionsEnabled &&
|
||||
smartTransactionEstimatedGas:
|
||||
smartTransactionsEnabled &&
|
||||
smartTransactionsOptInStatus &&
|
||||
smartTransactionFees?.tradeTxFees,
|
||||
nativeCurrencySymbol,
|
||||
multiLayerL1ApprovalFeeTotal,
|
||||
);
|
||||
});
|
||||
}, [
|
||||
quotes,
|
||||
gasPrice,
|
||||
|
10
yarn.lock
10
yarn.lock
@ -23360,10 +23360,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"loglevel@npm:^1.4.1":
|
||||
version: 1.6.0
|
||||
resolution: "loglevel@npm:1.6.0"
|
||||
checksum: 85e59bde900d8c7ddb6bd8f4ac466ca59fab54239e9bbf99193181c316fe49b067e3ed5945524894404c77db1a3a4d17f5fe272a808f05a8a8914a527628dea4
|
||||
"loglevel@npm:^1.8.1":
|
||||
version: 1.8.1
|
||||
resolution: "loglevel@npm:1.8.1"
|
||||
checksum: a1a62db40291aaeaef2f612334c49e531bff71cc1d01a2acab689ab80d59e092f852ab164a5aedc1a752fdc46b7b162cb097d8a9eb2cf0b299511106c29af61d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@ -24305,7 +24305,7 @@ __metadata:
|
||||
localforage: ^1.9.0
|
||||
lockfile-lint: ^4.9.6
|
||||
lodash: ^4.17.21
|
||||
loglevel: ^1.4.1
|
||||
loglevel: ^1.8.1
|
||||
loose-envify: ^1.4.0
|
||||
luxon: ^3.2.1
|
||||
madge: ^5.0.1
|
||||
|
Loading…
Reference in New Issue
Block a user