A Metamask fork with Infura removed and default networks editable
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
ciphermask/app/scripts/controllers/swaps.js

905 lines
29 KiB

import { ethers } from 'ethers';
import log from 'loglevel';
import BigNumber from 'bignumber.js';
import { ObservableStore } from '@metamask/obs-store';
import { mapValues, cloneDeep } from 'lodash';
import abi from 'human-standard-token-abi';
import { calcTokenAmount } from '../../../ui/app/helpers/utils/token-util';
import { calcGasTotal } from '../../../ui/app/pages/send/send.utils';
import { conversionUtil } from '../../../ui/app/helpers/utils/conversion-util';
import {
DEFAULT_ERC20_APPROVE_GAS,
QUOTES_EXPIRED_ERROR,
QUOTES_NOT_AVAILABLE_ERROR,
SWAPS_FETCH_ORDER_CONFLICT,
Version v9.3.0 RC (#10739) * Replace logic for eth swap token in fetchQuotesAndSetQuoteState with getSwapsEthToken call (#10624) * Move swaps constants to the shared constants directory (#10614) * Fix: ETH 'token' now only appears once in the swaps to and from dropdowns. (#10650) * Swaps support for local testnet (#10658) * Swaps support for local testnet * Create util method for comparison of token addresses/symbols to default swaps token * Get chainId from txMeta in _trackSwapsMetrics of transaction controller * Add comment to document purpose of getTransactionGroupRecipientAddressFilter * Use isSwapsDefaultTokenSymbol in place of repeated defaultTokenSymbol comparisons in build-quote.js * Additional swaps network support (#10721) * Add swaps support for bnc chain * Use single default token address in shared/constants/swaps * Ensure swaps gas prices are fetched from the correct chain specific endpoint (#10744) * Ensure swaps gas prices are fetched from the correct chain specific endpoint * Just rely on fetchWithCache to cache swaps gas prices, instead of directly using storage in getSwapsPriceEstimatesLastRetrieved * Empty commit * update @metamask/etherscan-link to v2.0.0 (#10747) * Use correct block explorer name and link in swaps when on custom network (#10743) * Use correct block explorer name and link in swaps when on custom network. * Fix up custom etherscan link code in build-quote.js * Use blockExplorerUrl hostname instead of 'blockExplorerBaseUrl' * Use correct etherscan-link method for token links in build-quote * Create correct token link in build-quote for mainnet AND custom networks * Block explorer url improvements in awaiting-swap.js and build-quote.js * Use swapVerifyTokenExplanation message with substitutable block explorer for all applicable locales * Ensure that block explorer links are not shown in awaiting-swap if no url is available * Ensure that the correct default currency symbols are used for fees on the view quote screen (#10753) * Updating y18n and netmask to resolve dependency issues (#10765) netmask@1.0.6 -> 2.0.1, y18n@3.2.1 -> 3.2.2, y18n@4.0.0 -> 4.0.1 * Ensure that priceSlippage fiat amounts are always shown in view-quote.js (#10762) * Ensure that the approval fee in the swaps custom gas modal is in network specific currency (#10763) * Use network specific swaps contract address when checking swap contract token approval (#10774) * Set the BSC_CONTRACT_ADDRESS to lowercase (#10800) * Ensure correct primary currency image is displayed on home screen and token list (#10777) * [skip e2e] Update changelog for v9.3.0 (#10740) * Version v9.3.0 * [skip e2e] Update changelog for v9.3.0 (#10803) Co-authored-by: Dan J Miller <danjm.com@gmail.com> Co-authored-by: ryanml <ryanlanese@gmail.com> Co-authored-by: David Walsh <davidwalsh83@gmail.com> Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
4 years ago
SWAPS_CHAINID_CONTRACT_ADDRESS_MAP,
} from '../../../shared/constants/swaps';
import { isSwapsDefaultTokenAddress } from '../../../shared/modules/swaps.utils';
import {
fetchTradesInfo as defaultFetchTradesInfo,
fetchSwapsFeatureLiveness as defaultFetchSwapsFeatureLiveness,
fetchSwapsQuoteRefreshTime as defaultFetchSwapsQuoteRefreshTime,
} from '../../../ui/app/pages/swaps/swaps.util';
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
const MAX_GAS_LIMIT = 2500000;
// To ensure that our serves are not spammed if MetaMask is left idle, we limit the number of fetches for quotes that are made on timed intervals.
// 3 seems to be an appropriate balance of giving users the time they need when MetaMask is not left idle, and turning polling off when it is.
const POLL_COUNT_LIMIT = 3;
// If for any reason the MetaSwap API fails to provide a refresh time,
// provide a reasonable fallback to avoid further errors
const FALLBACK_QUOTE_REFRESH_TIME = 60000;
// This is the amount of time to wait, after successfully fetching quotes
// and their gas estimates, before fetching for new quotes
const QUOTE_POLLING_DIFFERENCE_INTERVAL = 10 * 1000;
function calculateGasEstimateWithRefund(
maxGas = MAX_GAS_LIMIT,
estimatedRefund = 0,
estimatedGas = 0,
) {
const maxGasMinusRefund = new BigNumber(maxGas, 10).minus(
estimatedRefund,
10,
);
const gasEstimateWithRefund = maxGasMinusRefund.lt(estimatedGas, 16)
? maxGasMinusRefund.toString(16)
: estimatedGas;
return gasEstimateWithRefund;
}
const initialState = {
swapsState: {
quotes: {},
fetchParams: null,
tokens: null,
tradeTxId: null,
approveTxId: null,
quotesLastFetched: null,
customMaxGas: '',
customGasPrice: null,
selectedAggId: null,
customApproveTxData: '',
errorKey: '',
topAggId: null,
routeState: '',
swapsFeatureIsLive: false,
swapsQuoteRefreshTime: FALLBACK_QUOTE_REFRESH_TIME,
},
};
export default class SwapsController {
constructor({
getBufferedGasLimit,
networkController,
provider,
getProviderConfig,
tokenRatesStore,
fetchTradesInfo = defaultFetchTradesInfo,
fetchSwapsFeatureLiveness = defaultFetchSwapsFeatureLiveness,
fetchSwapsQuoteRefreshTime = defaultFetchSwapsQuoteRefreshTime,
Version v9.3.0 RC (#10739) * Replace logic for eth swap token in fetchQuotesAndSetQuoteState with getSwapsEthToken call (#10624) * Move swaps constants to the shared constants directory (#10614) * Fix: ETH 'token' now only appears once in the swaps to and from dropdowns. (#10650) * Swaps support for local testnet (#10658) * Swaps support for local testnet * Create util method for comparison of token addresses/symbols to default swaps token * Get chainId from txMeta in _trackSwapsMetrics of transaction controller * Add comment to document purpose of getTransactionGroupRecipientAddressFilter * Use isSwapsDefaultTokenSymbol in place of repeated defaultTokenSymbol comparisons in build-quote.js * Additional swaps network support (#10721) * Add swaps support for bnc chain * Use single default token address in shared/constants/swaps * Ensure swaps gas prices are fetched from the correct chain specific endpoint (#10744) * Ensure swaps gas prices are fetched from the correct chain specific endpoint * Just rely on fetchWithCache to cache swaps gas prices, instead of directly using storage in getSwapsPriceEstimatesLastRetrieved * Empty commit * update @metamask/etherscan-link to v2.0.0 (#10747) * Use correct block explorer name and link in swaps when on custom network (#10743) * Use correct block explorer name and link in swaps when on custom network. * Fix up custom etherscan link code in build-quote.js * Use blockExplorerUrl hostname instead of 'blockExplorerBaseUrl' * Use correct etherscan-link method for token links in build-quote * Create correct token link in build-quote for mainnet AND custom networks * Block explorer url improvements in awaiting-swap.js and build-quote.js * Use swapVerifyTokenExplanation message with substitutable block explorer for all applicable locales * Ensure that block explorer links are not shown in awaiting-swap if no url is available * Ensure that the correct default currency symbols are used for fees on the view quote screen (#10753) * Updating y18n and netmask to resolve dependency issues (#10765) netmask@1.0.6 -> 2.0.1, y18n@3.2.1 -> 3.2.2, y18n@4.0.0 -> 4.0.1 * Ensure that priceSlippage fiat amounts are always shown in view-quote.js (#10762) * Ensure that the approval fee in the swaps custom gas modal is in network specific currency (#10763) * Use network specific swaps contract address when checking swap contract token approval (#10774) * Set the BSC_CONTRACT_ADDRESS to lowercase (#10800) * Ensure correct primary currency image is displayed on home screen and token list (#10777) * [skip e2e] Update changelog for v9.3.0 (#10740) * Version v9.3.0 * [skip e2e] Update changelog for v9.3.0 (#10803) Co-authored-by: Dan J Miller <danjm.com@gmail.com> Co-authored-by: ryanml <ryanlanese@gmail.com> Co-authored-by: David Walsh <davidwalsh83@gmail.com> Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
4 years ago
getCurrentChainId,
}) {
this.store = new ObservableStore({
swapsState: { ...initialState.swapsState },
});
this._fetchTradesInfo = fetchTradesInfo;
this._fetchSwapsFeatureLiveness = fetchSwapsFeatureLiveness;
this._fetchSwapsQuoteRefreshTime = fetchSwapsQuoteRefreshTime;
Version v9.3.0 RC (#10739) * Replace logic for eth swap token in fetchQuotesAndSetQuoteState with getSwapsEthToken call (#10624) * Move swaps constants to the shared constants directory (#10614) * Fix: ETH 'token' now only appears once in the swaps to and from dropdowns. (#10650) * Swaps support for local testnet (#10658) * Swaps support for local testnet * Create util method for comparison of token addresses/symbols to default swaps token * Get chainId from txMeta in _trackSwapsMetrics of transaction controller * Add comment to document purpose of getTransactionGroupRecipientAddressFilter * Use isSwapsDefaultTokenSymbol in place of repeated defaultTokenSymbol comparisons in build-quote.js * Additional swaps network support (#10721) * Add swaps support for bnc chain * Use single default token address in shared/constants/swaps * Ensure swaps gas prices are fetched from the correct chain specific endpoint (#10744) * Ensure swaps gas prices are fetched from the correct chain specific endpoint * Just rely on fetchWithCache to cache swaps gas prices, instead of directly using storage in getSwapsPriceEstimatesLastRetrieved * Empty commit * update @metamask/etherscan-link to v2.0.0 (#10747) * Use correct block explorer name and link in swaps when on custom network (#10743) * Use correct block explorer name and link in swaps when on custom network. * Fix up custom etherscan link code in build-quote.js * Use blockExplorerUrl hostname instead of 'blockExplorerBaseUrl' * Use correct etherscan-link method for token links in build-quote * Create correct token link in build-quote for mainnet AND custom networks * Block explorer url improvements in awaiting-swap.js and build-quote.js * Use swapVerifyTokenExplanation message with substitutable block explorer for all applicable locales * Ensure that block explorer links are not shown in awaiting-swap if no url is available * Ensure that the correct default currency symbols are used for fees on the view quote screen (#10753) * Updating y18n and netmask to resolve dependency issues (#10765) netmask@1.0.6 -> 2.0.1, y18n@3.2.1 -> 3.2.2, y18n@4.0.0 -> 4.0.1 * Ensure that priceSlippage fiat amounts are always shown in view-quote.js (#10762) * Ensure that the approval fee in the swaps custom gas modal is in network specific currency (#10763) * Use network specific swaps contract address when checking swap contract token approval (#10774) * Set the BSC_CONTRACT_ADDRESS to lowercase (#10800) * Ensure correct primary currency image is displayed on home screen and token list (#10777) * [skip e2e] Update changelog for v9.3.0 (#10740) * Version v9.3.0 * [skip e2e] Update changelog for v9.3.0 (#10803) Co-authored-by: Dan J Miller <danjm.com@gmail.com> Co-authored-by: ryanml <ryanlanese@gmail.com> Co-authored-by: David Walsh <davidwalsh83@gmail.com> Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
4 years ago
this._getCurrentChainId = getCurrentChainId;
this.getBufferedGasLimit = getBufferedGasLimit;
this.tokenRatesStore = tokenRatesStore;
this.pollCount = 0;
this.getProviderConfig = getProviderConfig;
this.indexOfNewestCallInFlight = 0;
this.ethersProvider = new ethers.providers.Web3Provider(provider);
this._currentNetwork = networkController.store.getState().network;
networkController.on(NETWORK_EVENTS.NETWORK_DID_CHANGE, (network) => {
if (network !== 'loading' && network !== this._currentNetwork) {
this._currentNetwork = network;
this.ethersProvider = new ethers.providers.Web3Provider(provider);
}
});
this._setupSwapsLivenessFetching();
}
// Sets the refresh rate for quote updates from the MetaSwap API
async _setSwapsQuoteRefreshTime() {
Version v9.3.0 RC (#10739) * Replace logic for eth swap token in fetchQuotesAndSetQuoteState with getSwapsEthToken call (#10624) * Move swaps constants to the shared constants directory (#10614) * Fix: ETH 'token' now only appears once in the swaps to and from dropdowns. (#10650) * Swaps support for local testnet (#10658) * Swaps support for local testnet * Create util method for comparison of token addresses/symbols to default swaps token * Get chainId from txMeta in _trackSwapsMetrics of transaction controller * Add comment to document purpose of getTransactionGroupRecipientAddressFilter * Use isSwapsDefaultTokenSymbol in place of repeated defaultTokenSymbol comparisons in build-quote.js * Additional swaps network support (#10721) * Add swaps support for bnc chain * Use single default token address in shared/constants/swaps * Ensure swaps gas prices are fetched from the correct chain specific endpoint (#10744) * Ensure swaps gas prices are fetched from the correct chain specific endpoint * Just rely on fetchWithCache to cache swaps gas prices, instead of directly using storage in getSwapsPriceEstimatesLastRetrieved * Empty commit * update @metamask/etherscan-link to v2.0.0 (#10747) * Use correct block explorer name and link in swaps when on custom network (#10743) * Use correct block explorer name and link in swaps when on custom network. * Fix up custom etherscan link code in build-quote.js * Use blockExplorerUrl hostname instead of 'blockExplorerBaseUrl' * Use correct etherscan-link method for token links in build-quote * Create correct token link in build-quote for mainnet AND custom networks * Block explorer url improvements in awaiting-swap.js and build-quote.js * Use swapVerifyTokenExplanation message with substitutable block explorer for all applicable locales * Ensure that block explorer links are not shown in awaiting-swap if no url is available * Ensure that the correct default currency symbols are used for fees on the view quote screen (#10753) * Updating y18n and netmask to resolve dependency issues (#10765) netmask@1.0.6 -> 2.0.1, y18n@3.2.1 -> 3.2.2, y18n@4.0.0 -> 4.0.1 * Ensure that priceSlippage fiat amounts are always shown in view-quote.js (#10762) * Ensure that the approval fee in the swaps custom gas modal is in network specific currency (#10763) * Use network specific swaps contract address when checking swap contract token approval (#10774) * Set the BSC_CONTRACT_ADDRESS to lowercase (#10800) * Ensure correct primary currency image is displayed on home screen and token list (#10777) * [skip e2e] Update changelog for v9.3.0 (#10740) * Version v9.3.0 * [skip e2e] Update changelog for v9.3.0 (#10803) Co-authored-by: Dan J Miller <danjm.com@gmail.com> Co-authored-by: ryanml <ryanlanese@gmail.com> Co-authored-by: David Walsh <davidwalsh83@gmail.com> Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
4 years ago
const chainId = this._getCurrentChainId();
// Default to fallback time unless API returns valid response
let swapsQuoteRefreshTime = FALLBACK_QUOTE_REFRESH_TIME;
try {
Version v9.3.0 RC (#10739) * Replace logic for eth swap token in fetchQuotesAndSetQuoteState with getSwapsEthToken call (#10624) * Move swaps constants to the shared constants directory (#10614) * Fix: ETH 'token' now only appears once in the swaps to and from dropdowns. (#10650) * Swaps support for local testnet (#10658) * Swaps support for local testnet * Create util method for comparison of token addresses/symbols to default swaps token * Get chainId from txMeta in _trackSwapsMetrics of transaction controller * Add comment to document purpose of getTransactionGroupRecipientAddressFilter * Use isSwapsDefaultTokenSymbol in place of repeated defaultTokenSymbol comparisons in build-quote.js * Additional swaps network support (#10721) * Add swaps support for bnc chain * Use single default token address in shared/constants/swaps * Ensure swaps gas prices are fetched from the correct chain specific endpoint (#10744) * Ensure swaps gas prices are fetched from the correct chain specific endpoint * Just rely on fetchWithCache to cache swaps gas prices, instead of directly using storage in getSwapsPriceEstimatesLastRetrieved * Empty commit * update @metamask/etherscan-link to v2.0.0 (#10747) * Use correct block explorer name and link in swaps when on custom network (#10743) * Use correct block explorer name and link in swaps when on custom network. * Fix up custom etherscan link code in build-quote.js * Use blockExplorerUrl hostname instead of 'blockExplorerBaseUrl' * Use correct etherscan-link method for token links in build-quote * Create correct token link in build-quote for mainnet AND custom networks * Block explorer url improvements in awaiting-swap.js and build-quote.js * Use swapVerifyTokenExplanation message with substitutable block explorer for all applicable locales * Ensure that block explorer links are not shown in awaiting-swap if no url is available * Ensure that the correct default currency symbols are used for fees on the view quote screen (#10753) * Updating y18n and netmask to resolve dependency issues (#10765) netmask@1.0.6 -> 2.0.1, y18n@3.2.1 -> 3.2.2, y18n@4.0.0 -> 4.0.1 * Ensure that priceSlippage fiat amounts are always shown in view-quote.js (#10762) * Ensure that the approval fee in the swaps custom gas modal is in network specific currency (#10763) * Use network specific swaps contract address when checking swap contract token approval (#10774) * Set the BSC_CONTRACT_ADDRESS to lowercase (#10800) * Ensure correct primary currency image is displayed on home screen and token list (#10777) * [skip e2e] Update changelog for v9.3.0 (#10740) * Version v9.3.0 * [skip e2e] Update changelog for v9.3.0 (#10803) Co-authored-by: Dan J Miller <danjm.com@gmail.com> Co-authored-by: ryanml <ryanlanese@gmail.com> Co-authored-by: David Walsh <davidwalsh83@gmail.com> Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
4 years ago
swapsQuoteRefreshTime = await this._fetchSwapsQuoteRefreshTime(chainId);
} catch (e) {
console.error('Request for swaps quote refresh time failed: ', e);
}
const { swapsState } = this.store.getState();
this.store.updateState({
swapsState: { ...swapsState, swapsQuoteRefreshTime },
});
}
// Once quotes are fetched, we poll for new ones to keep the quotes up to date. Market and aggregator contract conditions can change fast enough
// that quotes will no longer be available after 1 or 2 minutes. When fetchAndSetQuotes is first called it, receives fetch that parameters are stored in
// state. These stored parameters are used on subsequent calls made during polling.
// Note: we stop polling after 3 requests, until new quotes are explicitly asked for. The logic that enforces that maximum is in the body of fetchAndSetQuotes
pollForNewQuotes() {
const {
swapsState: { swapsQuoteRefreshTime },
} = this.store.getState();
this.pollingTimeout = setTimeout(() => {
const { swapsState } = this.store.getState();
this.fetchAndSetQuotes(
swapsState.fetchParams,
swapsState.fetchParams?.metaData,
true,
);
}, swapsQuoteRefreshTime - QUOTE_POLLING_DIFFERENCE_INTERVAL);
}
stopPollingForQuotes() {
clearTimeout(this.pollingTimeout);
}
async fetchAndSetQuotes(
fetchParams,
fetchParamsMetaData = {},
isPolledRequest,
) {
Version v9.3.0 RC (#10739) * Replace logic for eth swap token in fetchQuotesAndSetQuoteState with getSwapsEthToken call (#10624) * Move swaps constants to the shared constants directory (#10614) * Fix: ETH 'token' now only appears once in the swaps to and from dropdowns. (#10650) * Swaps support for local testnet (#10658) * Swaps support for local testnet * Create util method for comparison of token addresses/symbols to default swaps token * Get chainId from txMeta in _trackSwapsMetrics of transaction controller * Add comment to document purpose of getTransactionGroupRecipientAddressFilter * Use isSwapsDefaultTokenSymbol in place of repeated defaultTokenSymbol comparisons in build-quote.js * Additional swaps network support (#10721) * Add swaps support for bnc chain * Use single default token address in shared/constants/swaps * Ensure swaps gas prices are fetched from the correct chain specific endpoint (#10744) * Ensure swaps gas prices are fetched from the correct chain specific endpoint * Just rely on fetchWithCache to cache swaps gas prices, instead of directly using storage in getSwapsPriceEstimatesLastRetrieved * Empty commit * update @metamask/etherscan-link to v2.0.0 (#10747) * Use correct block explorer name and link in swaps when on custom network (#10743) * Use correct block explorer name and link in swaps when on custom network. * Fix up custom etherscan link code in build-quote.js * Use blockExplorerUrl hostname instead of 'blockExplorerBaseUrl' * Use correct etherscan-link method for token links in build-quote * Create correct token link in build-quote for mainnet AND custom networks * Block explorer url improvements in awaiting-swap.js and build-quote.js * Use swapVerifyTokenExplanation message with substitutable block explorer for all applicable locales * Ensure that block explorer links are not shown in awaiting-swap if no url is available * Ensure that the correct default currency symbols are used for fees on the view quote screen (#10753) * Updating y18n and netmask to resolve dependency issues (#10765) netmask@1.0.6 -> 2.0.1, y18n@3.2.1 -> 3.2.2, y18n@4.0.0 -> 4.0.1 * Ensure that priceSlippage fiat amounts are always shown in view-quote.js (#10762) * Ensure that the approval fee in the swaps custom gas modal is in network specific currency (#10763) * Use network specific swaps contract address when checking swap contract token approval (#10774) * Set the BSC_CONTRACT_ADDRESS to lowercase (#10800) * Ensure correct primary currency image is displayed on home screen and token list (#10777) * [skip e2e] Update changelog for v9.3.0 (#10740) * Version v9.3.0 * [skip e2e] Update changelog for v9.3.0 (#10803) Co-authored-by: Dan J Miller <danjm.com@gmail.com> Co-authored-by: ryanml <ryanlanese@gmail.com> Co-authored-by: David Walsh <davidwalsh83@gmail.com> Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
4 years ago
const { chainId } = fetchParamsMetaData;
if (!fetchParams) {
return null;
}
// Every time we get a new request that is not from the polling, we reset the poll count so we can poll for up to three more sets of quotes with these new params.
if (!isPolledRequest) {
this.pollCount = 0;
}
// If there are any pending poll requests, clear them so that they don't get call while this new fetch is in process
clearTimeout(this.pollingTimeout);
if (!isPolledRequest) {
this.setSwapsErrorKey('');
}
const indexOfCurrentCall = this.indexOfNewestCallInFlight + 1;
this.indexOfNewestCallInFlight = indexOfCurrentCall;
let [newQuotes] = await Promise.all([
Version v9.3.0 RC (#10739) * Replace logic for eth swap token in fetchQuotesAndSetQuoteState with getSwapsEthToken call (#10624) * Move swaps constants to the shared constants directory (#10614) * Fix: ETH 'token' now only appears once in the swaps to and from dropdowns. (#10650) * Swaps support for local testnet (#10658) * Swaps support for local testnet * Create util method for comparison of token addresses/symbols to default swaps token * Get chainId from txMeta in _trackSwapsMetrics of transaction controller * Add comment to document purpose of getTransactionGroupRecipientAddressFilter * Use isSwapsDefaultTokenSymbol in place of repeated defaultTokenSymbol comparisons in build-quote.js * Additional swaps network support (#10721) * Add swaps support for bnc chain * Use single default token address in shared/constants/swaps * Ensure swaps gas prices are fetched from the correct chain specific endpoint (#10744) * Ensure swaps gas prices are fetched from the correct chain specific endpoint * Just rely on fetchWithCache to cache swaps gas prices, instead of directly using storage in getSwapsPriceEstimatesLastRetrieved * Empty commit * update @metamask/etherscan-link to v2.0.0 (#10747) * Use correct block explorer name and link in swaps when on custom network (#10743) * Use correct block explorer name and link in swaps when on custom network. * Fix up custom etherscan link code in build-quote.js * Use blockExplorerUrl hostname instead of 'blockExplorerBaseUrl' * Use correct etherscan-link method for token links in build-quote * Create correct token link in build-quote for mainnet AND custom networks * Block explorer url improvements in awaiting-swap.js and build-quote.js * Use swapVerifyTokenExplanation message with substitutable block explorer for all applicable locales * Ensure that block explorer links are not shown in awaiting-swap if no url is available * Ensure that the correct default currency symbols are used for fees on the view quote screen (#10753) * Updating y18n and netmask to resolve dependency issues (#10765) netmask@1.0.6 -> 2.0.1, y18n@3.2.1 -> 3.2.2, y18n@4.0.0 -> 4.0.1 * Ensure that priceSlippage fiat amounts are always shown in view-quote.js (#10762) * Ensure that the approval fee in the swaps custom gas modal is in network specific currency (#10763) * Use network specific swaps contract address when checking swap contract token approval (#10774) * Set the BSC_CONTRACT_ADDRESS to lowercase (#10800) * Ensure correct primary currency image is displayed on home screen and token list (#10777) * [skip e2e] Update changelog for v9.3.0 (#10740) * Version v9.3.0 * [skip e2e] Update changelog for v9.3.0 (#10803) Co-authored-by: Dan J Miller <danjm.com@gmail.com> Co-authored-by: ryanml <ryanlanese@gmail.com> Co-authored-by: David Walsh <davidwalsh83@gmail.com> Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
4 years ago
this._fetchTradesInfo(fetchParams, fetchParamsMetaData),
this._setSwapsQuoteRefreshTime(),
]);
newQuotes = mapValues(newQuotes, (quote) => ({
...quote,
sourceTokenInfo: fetchParamsMetaData.sourceTokenInfo,
destinationTokenInfo: fetchParamsMetaData.destinationTokenInfo,
}));
const quotesLastFetched = Date.now();
let approvalRequired = false;
if (
Version v9.3.0 RC (#10739) * Replace logic for eth swap token in fetchQuotesAndSetQuoteState with getSwapsEthToken call (#10624) * Move swaps constants to the shared constants directory (#10614) * Fix: ETH 'token' now only appears once in the swaps to and from dropdowns. (#10650) * Swaps support for local testnet (#10658) * Swaps support for local testnet * Create util method for comparison of token addresses/symbols to default swaps token * Get chainId from txMeta in _trackSwapsMetrics of transaction controller * Add comment to document purpose of getTransactionGroupRecipientAddressFilter * Use isSwapsDefaultTokenSymbol in place of repeated defaultTokenSymbol comparisons in build-quote.js * Additional swaps network support (#10721) * Add swaps support for bnc chain * Use single default token address in shared/constants/swaps * Ensure swaps gas prices are fetched from the correct chain specific endpoint (#10744) * Ensure swaps gas prices are fetched from the correct chain specific endpoint * Just rely on fetchWithCache to cache swaps gas prices, instead of directly using storage in getSwapsPriceEstimatesLastRetrieved * Empty commit * update @metamask/etherscan-link to v2.0.0 (#10747) * Use correct block explorer name and link in swaps when on custom network (#10743) * Use correct block explorer name and link in swaps when on custom network. * Fix up custom etherscan link code in build-quote.js * Use blockExplorerUrl hostname instead of 'blockExplorerBaseUrl' * Use correct etherscan-link method for token links in build-quote * Create correct token link in build-quote for mainnet AND custom networks * Block explorer url improvements in awaiting-swap.js and build-quote.js * Use swapVerifyTokenExplanation message with substitutable block explorer for all applicable locales * Ensure that block explorer links are not shown in awaiting-swap if no url is available * Ensure that the correct default currency symbols are used for fees on the view quote screen (#10753) * Updating y18n and netmask to resolve dependency issues (#10765) netmask@1.0.6 -> 2.0.1, y18n@3.2.1 -> 3.2.2, y18n@4.0.0 -> 4.0.1 * Ensure that priceSlippage fiat amounts are always shown in view-quote.js (#10762) * Ensure that the approval fee in the swaps custom gas modal is in network specific currency (#10763) * Use network specific swaps contract address when checking swap contract token approval (#10774) * Set the BSC_CONTRACT_ADDRESS to lowercase (#10800) * Ensure correct primary currency image is displayed on home screen and token list (#10777) * [skip e2e] Update changelog for v9.3.0 (#10740) * Version v9.3.0 * [skip e2e] Update changelog for v9.3.0 (#10803) Co-authored-by: Dan J Miller <danjm.com@gmail.com> Co-authored-by: ryanml <ryanlanese@gmail.com> Co-authored-by: David Walsh <davidwalsh83@gmail.com> Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
4 years ago
!isSwapsDefaultTokenAddress(fetchParams.sourceToken, chainId) &&
Object.values(newQuotes).length
) {
const allowance = await this._getERC20Allowance(
fetchParams.sourceToken,
fetchParams.fromAddress,
Version v9.3.0 RC (#10739) * Replace logic for eth swap token in fetchQuotesAndSetQuoteState with getSwapsEthToken call (#10624) * Move swaps constants to the shared constants directory (#10614) * Fix: ETH 'token' now only appears once in the swaps to and from dropdowns. (#10650) * Swaps support for local testnet (#10658) * Swaps support for local testnet * Create util method for comparison of token addresses/symbols to default swaps token * Get chainId from txMeta in _trackSwapsMetrics of transaction controller * Add comment to document purpose of getTransactionGroupRecipientAddressFilter * Use isSwapsDefaultTokenSymbol in place of repeated defaultTokenSymbol comparisons in build-quote.js * Additional swaps network support (#10721) * Add swaps support for bnc chain * Use single default token address in shared/constants/swaps * Ensure swaps gas prices are fetched from the correct chain specific endpoint (#10744) * Ensure swaps gas prices are fetched from the correct chain specific endpoint * Just rely on fetchWithCache to cache swaps gas prices, instead of directly using storage in getSwapsPriceEstimatesLastRetrieved * Empty commit * update @metamask/etherscan-link to v2.0.0 (#10747) * Use correct block explorer name and link in swaps when on custom network (#10743) * Use correct block explorer name and link in swaps when on custom network. * Fix up custom etherscan link code in build-quote.js * Use blockExplorerUrl hostname instead of 'blockExplorerBaseUrl' * Use correct etherscan-link method for token links in build-quote * Create correct token link in build-quote for mainnet AND custom networks * Block explorer url improvements in awaiting-swap.js and build-quote.js * Use swapVerifyTokenExplanation message with substitutable block explorer for all applicable locales * Ensure that block explorer links are not shown in awaiting-swap if no url is available * Ensure that the correct default currency symbols are used for fees on the view quote screen (#10753) * Updating y18n and netmask to resolve dependency issues (#10765) netmask@1.0.6 -> 2.0.1, y18n@3.2.1 -> 3.2.2, y18n@4.0.0 -> 4.0.1 * Ensure that priceSlippage fiat amounts are always shown in view-quote.js (#10762) * Ensure that the approval fee in the swaps custom gas modal is in network specific currency (#10763) * Use network specific swaps contract address when checking swap contract token approval (#10774) * Set the BSC_CONTRACT_ADDRESS to lowercase (#10800) * Ensure correct primary currency image is displayed on home screen and token list (#10777) * [skip e2e] Update changelog for v9.3.0 (#10740) * Version v9.3.0 * [skip e2e] Update changelog for v9.3.0 (#10803) Co-authored-by: Dan J Miller <danjm.com@gmail.com> Co-authored-by: ryanml <ryanlanese@gmail.com> Co-authored-by: David Walsh <davidwalsh83@gmail.com> Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
4 years ago
chainId,
);
// For a user to be able to swap a token, they need to have approved the MetaSwap contract to withdraw that token.
// _getERC20Allowance() returns the amount of the token they have approved for withdrawal. If that amount is greater
// than 0, it means that approval has already occured and is not needed. Otherwise, for tokens to be swapped, a new
// call of the ERC-20 approve method is required.
approvalRequired = allowance.eq(0);
if (!approvalRequired) {
newQuotes = mapValues(newQuotes, (quote) => ({
...quote,
approvalNeeded: null,
}));
} else if (!isPolledRequest) {
const { gasLimit: approvalGas } = await this.timedoutGasReturn(
Object.values(newQuotes)[0].approvalNeeded,
);
newQuotes = mapValues(newQuotes, (quote) => ({
...quote,
approvalNeeded: {
...quote.approvalNeeded,
gas: approvalGas || DEFAULT_ERC20_APPROVE_GAS,
},
}));
}
}
let topAggId = null;
// We can reduce time on the loading screen by only doing this after the
// loading screen and best quote have rendered.
if (!approvalRequired && !fetchParams?.balanceError) {
newQuotes = await this.getAllQuotesWithGasEstimates(newQuotes);
}
if (Object.values(newQuotes).length === 0) {
this.setSwapsErrorKey(QUOTES_NOT_AVAILABLE_ERROR);
} else {
const [
_topAggId,
quotesWithSavingsAndFeeData,
] = await this._findTopQuoteAndCalculateSavings(newQuotes);
topAggId = _topAggId;
newQuotes = quotesWithSavingsAndFeeData;
}
// If a newer call has been made, don't update state with old information
// Prevents timing conflicts between fetches
if (this.indexOfNewestCallInFlight !== indexOfCurrentCall) {
throw new Error(SWAPS_FETCH_ORDER_CONFLICT);
}
const { swapsState } = this.store.getState();
let { selectedAggId } = swapsState;
if (!newQuotes[selectedAggId]) {
selectedAggId = null;
}
this.store.updateState({
swapsState: {
...swapsState,
quotes: newQuotes,
fetchParams: { ...fetchParams, metaData: fetchParamsMetaData },
quotesLastFetched,
selectedAggId,
topAggId,
},
});
// We only want to do up to a maximum of three requests from polling.
this.pollCount += 1;
if (this.pollCount < POLL_COUNT_LIMIT + 1) {
this.pollForNewQuotes();
} else {
this.resetPostFetchState();
this.setSwapsErrorKey(QUOTES_EXPIRED_ERROR);
return null;
}
return [newQuotes, topAggId];
}
safeRefetchQuotes() {
const { swapsState } = this.store.getState();
if (!this.pollingTimeout && swapsState.fetchParams) {
this.fetchAndSetQuotes(swapsState.fetchParams);
}
}
setSelectedQuoteAggId(selectedAggId) {
const { swapsState } = this.store.getState();
this.store.updateState({ swapsState: { ...swapsState, selectedAggId } });
}
setSwapsTokens(tokens) {
const { swapsState } = this.store.getState();
this.store.updateState({ swapsState: { ...swapsState, tokens } });
}
setSwapsErrorKey(errorKey) {
const { swapsState } = this.store.getState();
this.store.updateState({ swapsState: { ...swapsState, errorKey } });
}
async getAllQuotesWithGasEstimates(quotes) {
const quoteGasData = await Promise.all(
Object.values(quotes).map(async (quote) => {
const { gasLimit, simulationFails } = await this.timedoutGasReturn(
quote.trade,
);
return [gasLimit, simulationFails, quote.aggregator];
}),
);
const newQuotes = {};
quoteGasData.forEach(([gasLimit, simulationFails, aggId]) => {
if (gasLimit && !simulationFails) {
const gasEstimateWithRefund = calculateGasEstimateWithRefund(
quotes[aggId].maxGas,
quotes[aggId].estimatedRefund,
gasLimit,
);
newQuotes[aggId] = {
...quotes[aggId],
gasEstimate: gasLimit,
gasEstimateWithRefund,
};
} else if (quotes[aggId].approvalNeeded) {
// If gas estimation fails, but an ERC-20 approve is needed, then we do not add any estimate property to the quote object
// Such quotes will rely on the maxGas and averageGas properties from the api
newQuotes[aggId] = quotes[aggId];
}
// If gas estimation fails and no approval is needed, then we filter that quote out, so that it is not shown to the user
});
return newQuotes;
}
timedoutGasReturn(tradeTxParams) {
return new Promise((resolve) => {
let gasTimedOut = false;
const gasTimeout = setTimeout(() => {
gasTimedOut = true;
resolve({ gasLimit: null, simulationFails: true });
}, 5000);
// Remove gas from params that will be passed to the `estimateGas` call
// Including it can cause the estimate to fail if the actual gas needed
// exceeds the passed gas
const tradeTxParamsForGasEstimate = {
data: tradeTxParams.data,
from: tradeTxParams.from,
to: tradeTxParams.to,
value: tradeTxParams.value,
};
this.getBufferedGasLimit({ txParams: tradeTxParamsForGasEstimate }, 1)
.then(({ gasLimit, simulationFails }) => {
if (!gasTimedOut) {
clearTimeout(gasTimeout);
resolve({ gasLimit, simulationFails });
}
})
.catch((e) => {
log.error(e);
if (!gasTimedOut) {
clearTimeout(gasTimeout);
resolve({ gasLimit: null, simulationFails: true });
}
});
});
}
async setInitialGasEstimate(initialAggId) {
const { swapsState } = this.store.getState();
const quoteToUpdate = { ...swapsState.quotes[initialAggId] };
const {
gasLimit: newGasEstimate,
simulationFails,
} = await this.timedoutGasReturn(quoteToUpdate.trade);
if (newGasEstimate && !simulationFails) {
const gasEstimateWithRefund = calculateGasEstimateWithRefund(
quoteToUpdate.maxGas,
quoteToUpdate.estimatedRefund,
newGasEstimate,
);
quoteToUpdate.gasEstimate = newGasEstimate;
quoteToUpdate.gasEstimateWithRefund = gasEstimateWithRefund;
}
this.store.updateState({
swapsState: {
...swapsState,
quotes: { ...swapsState.quotes, [initialAggId]: quoteToUpdate },
},
});
}
setApproveTxId(approveTxId) {
const { swapsState } = this.store.getState();
this.store.updateState({ swapsState: { ...swapsState, approveTxId } });
}
setTradeTxId(tradeTxId) {
const { swapsState } = this.store.getState();
this.store.updateState({ swapsState: { ...swapsState, tradeTxId } });
}
setQuotesLastFetched(quotesLastFetched) {
const { swapsState } = this.store.getState();
this.store.updateState({
swapsState: { ...swapsState, quotesLastFetched },
});
}
setSwapsTxGasPrice(gasPrice) {
const { swapsState } = this.store.getState();
this.store.updateState({
swapsState: { ...swapsState, customGasPrice: gasPrice },
});
}
setSwapsTxGasLimit(gasLimit) {
const { swapsState } = this.store.getState();
this.store.updateState({
swapsState: { ...swapsState, customMaxGas: gasLimit },
});
}
setCustomApproveTxData(data) {
const { swapsState } = this.store.getState();
this.store.updateState({
swapsState: { ...swapsState, customApproveTxData: data },
});
}
setBackgroundSwapRouteState(routeState) {
const { swapsState } = this.store.getState();
this.store.updateState({ swapsState: { ...swapsState, routeState } });
}
setSwapsLiveness(swapsFeatureIsLive) {
const { swapsState } = this.store.getState();
this.store.updateState({
swapsState: { ...swapsState, swapsFeatureIsLive },
});
}
resetPostFetchState() {
const { swapsState } = this.store.getState();
this.store.updateState({
swapsState: {
...initialState.swapsState,
tokens: swapsState.tokens,
fetchParams: swapsState.fetchParams,
swapsFeatureIsLive: swapsState.swapsFeatureIsLive,
swapsQuoteRefreshTime: swapsState.swapsQuoteRefreshTime,
},
});
clearTimeout(this.pollingTimeout);
}
resetSwapsState() {
const { swapsState } = this.store.getState();
this.store.updateState({
swapsState: {
...initialState.swapsState,
tokens: swapsState.tokens,
swapsFeatureIsLive: swapsState.swapsFeatureIsLive,
swapsQuoteRefreshTime: swapsState.swapsQuoteRefreshTime,
},
});
clearTimeout(this.pollingTimeout);
}
async _getEthersGasPrice() {
const ethersGasPrice = await this.ethersProvider.getGasPrice();
return ethersGasPrice.toHexString();
}
async _findTopQuoteAndCalculateSavings(quotes = {}) {
const tokenConversionRates = this.tokenRatesStore.getState()
.contractExchangeRates;
const {
swapsState: { customGasPrice },
} = this.store.getState();
Version v9.3.0 RC (#10739) * Replace logic for eth swap token in fetchQuotesAndSetQuoteState with getSwapsEthToken call (#10624) * Move swaps constants to the shared constants directory (#10614) * Fix: ETH 'token' now only appears once in the swaps to and from dropdowns. (#10650) * Swaps support for local testnet (#10658) * Swaps support for local testnet * Create util method for comparison of token addresses/symbols to default swaps token * Get chainId from txMeta in _trackSwapsMetrics of transaction controller * Add comment to document purpose of getTransactionGroupRecipientAddressFilter * Use isSwapsDefaultTokenSymbol in place of repeated defaultTokenSymbol comparisons in build-quote.js * Additional swaps network support (#10721) * Add swaps support for bnc chain * Use single default token address in shared/constants/swaps * Ensure swaps gas prices are fetched from the correct chain specific endpoint (#10744) * Ensure swaps gas prices are fetched from the correct chain specific endpoint * Just rely on fetchWithCache to cache swaps gas prices, instead of directly using storage in getSwapsPriceEstimatesLastRetrieved * Empty commit * update @metamask/etherscan-link to v2.0.0 (#10747) * Use correct block explorer name and link in swaps when on custom network (#10743) * Use correct block explorer name and link in swaps when on custom network. * Fix up custom etherscan link code in build-quote.js * Use blockExplorerUrl hostname instead of 'blockExplorerBaseUrl' * Use correct etherscan-link method for token links in build-quote * Create correct token link in build-quote for mainnet AND custom networks * Block explorer url improvements in awaiting-swap.js and build-quote.js * Use swapVerifyTokenExplanation message with substitutable block explorer for all applicable locales * Ensure that block explorer links are not shown in awaiting-swap if no url is available * Ensure that the correct default currency symbols are used for fees on the view quote screen (#10753) * Updating y18n and netmask to resolve dependency issues (#10765) netmask@1.0.6 -> 2.0.1, y18n@3.2.1 -> 3.2.2, y18n@4.0.0 -> 4.0.1 * Ensure that priceSlippage fiat amounts are always shown in view-quote.js (#10762) * Ensure that the approval fee in the swaps custom gas modal is in network specific currency (#10763) * Use network specific swaps contract address when checking swap contract token approval (#10774) * Set the BSC_CONTRACT_ADDRESS to lowercase (#10800) * Ensure correct primary currency image is displayed on home screen and token list (#10777) * [skip e2e] Update changelog for v9.3.0 (#10740) * Version v9.3.0 * [skip e2e] Update changelog for v9.3.0 (#10803) Co-authored-by: Dan J Miller <danjm.com@gmail.com> Co-authored-by: ryanml <ryanlanese@gmail.com> Co-authored-by: David Walsh <davidwalsh83@gmail.com> Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
4 years ago
const chainId = this._getCurrentChainId();
const numQuotes = Object.keys(quotes).length;
if (!numQuotes) {
return {};
}
const newQuotes = cloneDeep(quotes);
const usedGasPrice = customGasPrice || (await this._getEthersGasPrice());
let topAggId = null;
let overallValueOfBestQuoteForSorting = null;
Object.values(newQuotes).forEach((quote) => {
const {
aggregator,
approvalNeeded,
averageGas,
destinationAmount = 0,
destinationToken,
destinationTokenInfo,
gasEstimate,
sourceAmount,
sourceToken,
trade,
fee: metaMaskFee,
} = quote;
const tradeGasLimitForCalculation = gasEstimate
? new BigNumber(gasEstimate, 16)
: new BigNumber(averageGas || MAX_GAS_LIMIT, 10);
const totalGasLimitForCalculation = tradeGasLimitForCalculation
.plus(approvalNeeded?.gas || '0x0', 16)
.toString(16);
const gasTotalInWeiHex = calcGasTotal(
totalGasLimitForCalculation,
usedGasPrice,
);
// trade.value is a sum of different values depending on the transaction.
// It always includes any external fees charged by the quote source. In
Version v9.3.0 RC (#10739) * Replace logic for eth swap token in fetchQuotesAndSetQuoteState with getSwapsEthToken call (#10624) * Move swaps constants to the shared constants directory (#10614) * Fix: ETH 'token' now only appears once in the swaps to and from dropdowns. (#10650) * Swaps support for local testnet (#10658) * Swaps support for local testnet * Create util method for comparison of token addresses/symbols to default swaps token * Get chainId from txMeta in _trackSwapsMetrics of transaction controller * Add comment to document purpose of getTransactionGroupRecipientAddressFilter * Use isSwapsDefaultTokenSymbol in place of repeated defaultTokenSymbol comparisons in build-quote.js * Additional swaps network support (#10721) * Add swaps support for bnc chain * Use single default token address in shared/constants/swaps * Ensure swaps gas prices are fetched from the correct chain specific endpoint (#10744) * Ensure swaps gas prices are fetched from the correct chain specific endpoint * Just rely on fetchWithCache to cache swaps gas prices, instead of directly using storage in getSwapsPriceEstimatesLastRetrieved * Empty commit * update @metamask/etherscan-link to v2.0.0 (#10747) * Use correct block explorer name and link in swaps when on custom network (#10743) * Use correct block explorer name and link in swaps when on custom network. * Fix up custom etherscan link code in build-quote.js * Use blockExplorerUrl hostname instead of 'blockExplorerBaseUrl' * Use correct etherscan-link method for token links in build-quote * Create correct token link in build-quote for mainnet AND custom networks * Block explorer url improvements in awaiting-swap.js and build-quote.js * Use swapVerifyTokenExplanation message with substitutable block explorer for all applicable locales * Ensure that block explorer links are not shown in awaiting-swap if no url is available * Ensure that the correct default currency symbols are used for fees on the view quote screen (#10753) * Updating y18n and netmask to resolve dependency issues (#10765) netmask@1.0.6 -> 2.0.1, y18n@3.2.1 -> 3.2.2, y18n@4.0.0 -> 4.0.1 * Ensure that priceSlippage fiat amounts are always shown in view-quote.js (#10762) * Ensure that the approval fee in the swaps custom gas modal is in network specific currency (#10763) * Use network specific swaps contract address when checking swap contract token approval (#10774) * Set the BSC_CONTRACT_ADDRESS to lowercase (#10800) * Ensure correct primary currency image is displayed on home screen and token list (#10777) * [skip e2e] Update changelog for v9.3.0 (#10740) * Version v9.3.0 * [skip e2e] Update changelog for v9.3.0 (#10803) Co-authored-by: Dan J Miller <danjm.com@gmail.com> Co-authored-by: ryanml <ryanlanese@gmail.com> Co-authored-by: David Walsh <davidwalsh83@gmail.com> Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
4 years ago
// addition, if the source asset is the selected chain's default token, trade.value
// includes the amount of that token.
const totalWeiCost = new BigNumber(gasTotalInWeiHex, 16).plus(
trade.value,
16,
);
const totalEthCost = conversionUtil(totalWeiCost, {
fromCurrency: 'ETH',
fromDenomination: 'WEI',
toDenomination: 'ETH',
fromNumericBase: 'BN',
numberOfDecimals: 6,
});
// The total fee is aggregator/exchange fees plus gas fees.
Version v9.3.0 RC (#10739) * Replace logic for eth swap token in fetchQuotesAndSetQuoteState with getSwapsEthToken call (#10624) * Move swaps constants to the shared constants directory (#10614) * Fix: ETH 'token' now only appears once in the swaps to and from dropdowns. (#10650) * Swaps support for local testnet (#10658) * Swaps support for local testnet * Create util method for comparison of token addresses/symbols to default swaps token * Get chainId from txMeta in _trackSwapsMetrics of transaction controller * Add comment to document purpose of getTransactionGroupRecipientAddressFilter * Use isSwapsDefaultTokenSymbol in place of repeated defaultTokenSymbol comparisons in build-quote.js * Additional swaps network support (#10721) * Add swaps support for bnc chain * Use single default token address in shared/constants/swaps * Ensure swaps gas prices are fetched from the correct chain specific endpoint (#10744) * Ensure swaps gas prices are fetched from the correct chain specific endpoint * Just rely on fetchWithCache to cache swaps gas prices, instead of directly using storage in getSwapsPriceEstimatesLastRetrieved * Empty commit * update @metamask/etherscan-link to v2.0.0 (#10747) * Use correct block explorer name and link in swaps when on custom network (#10743) * Use correct block explorer name and link in swaps when on custom network. * Fix up custom etherscan link code in build-quote.js * Use blockExplorerUrl hostname instead of 'blockExplorerBaseUrl' * Use correct etherscan-link method for token links in build-quote * Create correct token link in build-quote for mainnet AND custom networks * Block explorer url improvements in awaiting-swap.js and build-quote.js * Use swapVerifyTokenExplanation message with substitutable block explorer for all applicable locales * Ensure that block explorer links are not shown in awaiting-swap if no url is available * Ensure that the correct default currency symbols are used for fees on the view quote screen (#10753) * Updating y18n and netmask to resolve dependency issues (#10765) netmask@1.0.6 -> 2.0.1, y18n@3.2.1 -> 3.2.2, y18n@4.0.0 -> 4.0.1 * Ensure that priceSlippage fiat amounts are always shown in view-quote.js (#10762) * Ensure that the approval fee in the swaps custom gas modal is in network specific currency (#10763) * Use network specific swaps contract address when checking swap contract token approval (#10774) * Set the BSC_CONTRACT_ADDRESS to lowercase (#10800) * Ensure correct primary currency image is displayed on home screen and token list (#10777) * [skip e2e] Update changelog for v9.3.0 (#10740) * Version v9.3.0 * [skip e2e] Update changelog for v9.3.0 (#10803) Co-authored-by: Dan J Miller <danjm.com@gmail.com> Co-authored-by: ryanml <ryanlanese@gmail.com> Co-authored-by: David Walsh <davidwalsh83@gmail.com> Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
4 years ago
// If the swap is from the selected chain's default token, subtract
// the sourceAmount from the total cost. Otherwise, the total fee
// is simply trade.value plus gas fees.
const ethFee = isSwapsDefaultTokenAddress(sourceToken, chainId)
? conversionUtil(
totalWeiCost.minus(sourceAmount, 10), // sourceAmount is in wei
{
fromCurrency: 'ETH',
fromDenomination: 'WEI',
toDenomination: 'ETH',
fromNumericBase: 'BN',
numberOfDecimals: 6,
},
)
: totalEthCost;
const decimalAdjustedDestinationAmount = calcTokenAmount(
destinationAmount,
destinationTokenInfo.decimals,
);
const tokenPercentageOfPreFeeDestAmount = new BigNumber(100, 10)
.minus(metaMaskFee, 10)
.div(100);
const destinationAmountBeforeMetaMaskFee = decimalAdjustedDestinationAmount.div(
tokenPercentageOfPreFeeDestAmount,
);
const metaMaskFeeInTokens = destinationAmountBeforeMetaMaskFee.minus(
decimalAdjustedDestinationAmount,
);
const tokenConversionRate = tokenConversionRates[destinationToken];
const conversionRateForSorting = tokenConversionRate || 1;
const ethValueOfTokens = decimalAdjustedDestinationAmount.times(
conversionRateForSorting,
10,
);
Version v9.3.0 RC (#10739) * Replace logic for eth swap token in fetchQuotesAndSetQuoteState with getSwapsEthToken call (#10624) * Move swaps constants to the shared constants directory (#10614) * Fix: ETH 'token' now only appears once in the swaps to and from dropdowns. (#10650) * Swaps support for local testnet (#10658) * Swaps support for local testnet * Create util method for comparison of token addresses/symbols to default swaps token * Get chainId from txMeta in _trackSwapsMetrics of transaction controller * Add comment to document purpose of getTransactionGroupRecipientAddressFilter * Use isSwapsDefaultTokenSymbol in place of repeated defaultTokenSymbol comparisons in build-quote.js * Additional swaps network support (#10721) * Add swaps support for bnc chain * Use single default token address in shared/constants/swaps * Ensure swaps gas prices are fetched from the correct chain specific endpoint (#10744) * Ensure swaps gas prices are fetched from the correct chain specific endpoint * Just rely on fetchWithCache to cache swaps gas prices, instead of directly using storage in getSwapsPriceEstimatesLastRetrieved * Empty commit * update @metamask/etherscan-link to v2.0.0 (#10747) * Use correct block explorer name and link in swaps when on custom network (#10743) * Use correct block explorer name and link in swaps when on custom network. * Fix up custom etherscan link code in build-quote.js * Use blockExplorerUrl hostname instead of 'blockExplorerBaseUrl' * Use correct etherscan-link method for token links in build-quote * Create correct token link in build-quote for mainnet AND custom networks * Block explorer url improvements in awaiting-swap.js and build-quote.js * Use swapVerifyTokenExplanation message with substitutable block explorer for all applicable locales * Ensure that block explorer links are not shown in awaiting-swap if no url is available * Ensure that the correct default currency symbols are used for fees on the view quote screen (#10753) * Updating y18n and netmask to resolve dependency issues (#10765) netmask@1.0.6 -> 2.0.1, y18n@3.2.1 -> 3.2.2, y18n@4.0.0 -> 4.0.1 * Ensure that priceSlippage fiat amounts are always shown in view-quote.js (#10762) * Ensure that the approval fee in the swaps custom gas modal is in network specific currency (#10763) * Use network specific swaps contract address when checking swap contract token approval (#10774) * Set the BSC_CONTRACT_ADDRESS to lowercase (#10800) * Ensure correct primary currency image is displayed on home screen and token list (#10777) * [skip e2e] Update changelog for v9.3.0 (#10740) * Version v9.3.0 * [skip e2e] Update changelog for v9.3.0 (#10803) Co-authored-by: Dan J Miller <danjm.com@gmail.com> Co-authored-by: ryanml <ryanlanese@gmail.com> Co-authored-by: David Walsh <davidwalsh83@gmail.com> Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
4 years ago
const conversionRateForCalculations = isSwapsDefaultTokenAddress(
destinationToken,
chainId,
)
? 1
: tokenConversionRate;
const overallValueOfQuoteForSorting =
conversionRateForCalculations === undefined
? ethValueOfTokens
: ethValueOfTokens.minus(ethFee, 10);
quote.ethFee = ethFee.toString(10);
if (conversionRateForCalculations !== undefined) {
quote.ethValueOfTokens = ethValueOfTokens.toString(10);
quote.overallValueOfQuote = overallValueOfQuoteForSorting.toString(10);
quote.metaMaskFeeInEth = metaMaskFeeInTokens
.times(conversionRateForCalculations)
.toString(10);
}
if (
overallValueOfBestQuoteForSorting === null ||
overallValueOfQuoteForSorting.gt(overallValueOfBestQuoteForSorting)
) {
topAggId = aggregator;
overallValueOfBestQuoteForSorting = overallValueOfQuoteForSorting;
}
});
const isBest =
Version v9.3.0 RC (#10739) * Replace logic for eth swap token in fetchQuotesAndSetQuoteState with getSwapsEthToken call (#10624) * Move swaps constants to the shared constants directory (#10614) * Fix: ETH 'token' now only appears once in the swaps to and from dropdowns. (#10650) * Swaps support for local testnet (#10658) * Swaps support for local testnet * Create util method for comparison of token addresses/symbols to default swaps token * Get chainId from txMeta in _trackSwapsMetrics of transaction controller * Add comment to document purpose of getTransactionGroupRecipientAddressFilter * Use isSwapsDefaultTokenSymbol in place of repeated defaultTokenSymbol comparisons in build-quote.js * Additional swaps network support (#10721) * Add swaps support for bnc chain * Use single default token address in shared/constants/swaps * Ensure swaps gas prices are fetched from the correct chain specific endpoint (#10744) * Ensure swaps gas prices are fetched from the correct chain specific endpoint * Just rely on fetchWithCache to cache swaps gas prices, instead of directly using storage in getSwapsPriceEstimatesLastRetrieved * Empty commit * update @metamask/etherscan-link to v2.0.0 (#10747) * Use correct block explorer name and link in swaps when on custom network (#10743) * Use correct block explorer name and link in swaps when on custom network. * Fix up custom etherscan link code in build-quote.js * Use blockExplorerUrl hostname instead of 'blockExplorerBaseUrl' * Use correct etherscan-link method for token links in build-quote * Create correct token link in build-quote for mainnet AND custom networks * Block explorer url improvements in awaiting-swap.js and build-quote.js * Use swapVerifyTokenExplanation message with substitutable block explorer for all applicable locales * Ensure that block explorer links are not shown in awaiting-swap if no url is available * Ensure that the correct default currency symbols are used for fees on the view quote screen (#10753) * Updating y18n and netmask to resolve dependency issues (#10765) netmask@1.0.6 -> 2.0.1, y18n@3.2.1 -> 3.2.2, y18n@4.0.0 -> 4.0.1 * Ensure that priceSlippage fiat amounts are always shown in view-quote.js (#10762) * Ensure that the approval fee in the swaps custom gas modal is in network specific currency (#10763) * Use network specific swaps contract address when checking swap contract token approval (#10774) * Set the BSC_CONTRACT_ADDRESS to lowercase (#10800) * Ensure correct primary currency image is displayed on home screen and token list (#10777) * [skip e2e] Update changelog for v9.3.0 (#10740) * Version v9.3.0 * [skip e2e] Update changelog for v9.3.0 (#10803) Co-authored-by: Dan J Miller <danjm.com@gmail.com> Co-authored-by: ryanml <ryanlanese@gmail.com> Co-authored-by: David Walsh <davidwalsh83@gmail.com> Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
4 years ago
isSwapsDefaultTokenAddress(
newQuotes[topAggId].destinationToken,
chainId,
) || Boolean(tokenConversionRates[newQuotes[topAggId]?.destinationToken]);
let savings = null;
if (isBest) {
const bestQuote = newQuotes[topAggId];
savings = {};
const {
ethFee: medianEthFee,
metaMaskFeeInEth: medianMetaMaskFee,
ethValueOfTokens: medianEthValueOfTokens,
} = getMedianEthValueQuote(Object.values(newQuotes));
// Performance savings are calculated as:
// (ethValueOfTokens for the best trade) - (ethValueOfTokens for the media trade)
savings.performance = new BigNumber(bestQuote.ethValueOfTokens, 10).minus(
medianEthValueOfTokens,
10,
);
// Fee savings are calculated as:
// (fee for the median trade) - (fee for the best trade)
savings.fee = new BigNumber(medianEthFee).minus(bestQuote.ethFee, 10);
savings.metaMaskFee = bestQuote.metaMaskFeeInEth;
// Total savings are calculated as:
// performance savings + fee savings - metamask fee
savings.total = savings.performance
.plus(savings.fee)
.minus(savings.metaMaskFee)
.toString(10);
savings.performance = savings.performance.toString(10);
savings.fee = savings.fee.toString(10);
savings.medianMetaMaskFee = medianMetaMaskFee;
newQuotes[topAggId].isBestQuote = true;
newQuotes[topAggId].savings = savings;
}
return [topAggId, newQuotes];
}
Version v9.3.0 RC (#10739) * Replace logic for eth swap token in fetchQuotesAndSetQuoteState with getSwapsEthToken call (#10624) * Move swaps constants to the shared constants directory (#10614) * Fix: ETH 'token' now only appears once in the swaps to and from dropdowns. (#10650) * Swaps support for local testnet (#10658) * Swaps support for local testnet * Create util method for comparison of token addresses/symbols to default swaps token * Get chainId from txMeta in _trackSwapsMetrics of transaction controller * Add comment to document purpose of getTransactionGroupRecipientAddressFilter * Use isSwapsDefaultTokenSymbol in place of repeated defaultTokenSymbol comparisons in build-quote.js * Additional swaps network support (#10721) * Add swaps support for bnc chain * Use single default token address in shared/constants/swaps * Ensure swaps gas prices are fetched from the correct chain specific endpoint (#10744) * Ensure swaps gas prices are fetched from the correct chain specific endpoint * Just rely on fetchWithCache to cache swaps gas prices, instead of directly using storage in getSwapsPriceEstimatesLastRetrieved * Empty commit * update @metamask/etherscan-link to v2.0.0 (#10747) * Use correct block explorer name and link in swaps when on custom network (#10743) * Use correct block explorer name and link in swaps when on custom network. * Fix up custom etherscan link code in build-quote.js * Use blockExplorerUrl hostname instead of 'blockExplorerBaseUrl' * Use correct etherscan-link method for token links in build-quote * Create correct token link in build-quote for mainnet AND custom networks * Block explorer url improvements in awaiting-swap.js and build-quote.js * Use swapVerifyTokenExplanation message with substitutable block explorer for all applicable locales * Ensure that block explorer links are not shown in awaiting-swap if no url is available * Ensure that the correct default currency symbols are used for fees on the view quote screen (#10753) * Updating y18n and netmask to resolve dependency issues (#10765) netmask@1.0.6 -> 2.0.1, y18n@3.2.1 -> 3.2.2, y18n@4.0.0 -> 4.0.1 * Ensure that priceSlippage fiat amounts are always shown in view-quote.js (#10762) * Ensure that the approval fee in the swaps custom gas modal is in network specific currency (#10763) * Use network specific swaps contract address when checking swap contract token approval (#10774) * Set the BSC_CONTRACT_ADDRESS to lowercase (#10800) * Ensure correct primary currency image is displayed on home screen and token list (#10777) * [skip e2e] Update changelog for v9.3.0 (#10740) * Version v9.3.0 * [skip e2e] Update changelog for v9.3.0 (#10803) Co-authored-by: Dan J Miller <danjm.com@gmail.com> Co-authored-by: ryanml <ryanlanese@gmail.com> Co-authored-by: David Walsh <davidwalsh83@gmail.com> Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
4 years ago
async _getERC20Allowance(contractAddress, walletAddress, chainId) {
const contract = new ethers.Contract(
contractAddress,
abi,
this.ethersProvider,
);
Version v9.3.0 RC (#10739) * Replace logic for eth swap token in fetchQuotesAndSetQuoteState with getSwapsEthToken call (#10624) * Move swaps constants to the shared constants directory (#10614) * Fix: ETH 'token' now only appears once in the swaps to and from dropdowns. (#10650) * Swaps support for local testnet (#10658) * Swaps support for local testnet * Create util method for comparison of token addresses/symbols to default swaps token * Get chainId from txMeta in _trackSwapsMetrics of transaction controller * Add comment to document purpose of getTransactionGroupRecipientAddressFilter * Use isSwapsDefaultTokenSymbol in place of repeated defaultTokenSymbol comparisons in build-quote.js * Additional swaps network support (#10721) * Add swaps support for bnc chain * Use single default token address in shared/constants/swaps * Ensure swaps gas prices are fetched from the correct chain specific endpoint (#10744) * Ensure swaps gas prices are fetched from the correct chain specific endpoint * Just rely on fetchWithCache to cache swaps gas prices, instead of directly using storage in getSwapsPriceEstimatesLastRetrieved * Empty commit * update @metamask/etherscan-link to v2.0.0 (#10747) * Use correct block explorer name and link in swaps when on custom network (#10743) * Use correct block explorer name and link in swaps when on custom network. * Fix up custom etherscan link code in build-quote.js * Use blockExplorerUrl hostname instead of 'blockExplorerBaseUrl' * Use correct etherscan-link method for token links in build-quote * Create correct token link in build-quote for mainnet AND custom networks * Block explorer url improvements in awaiting-swap.js and build-quote.js * Use swapVerifyTokenExplanation message with substitutable block explorer for all applicable locales * Ensure that block explorer links are not shown in awaiting-swap if no url is available * Ensure that the correct default currency symbols are used for fees on the view quote screen (#10753) * Updating y18n and netmask to resolve dependency issues (#10765) netmask@1.0.6 -> 2.0.1, y18n@3.2.1 -> 3.2.2, y18n@4.0.0 -> 4.0.1 * Ensure that priceSlippage fiat amounts are always shown in view-quote.js (#10762) * Ensure that the approval fee in the swaps custom gas modal is in network specific currency (#10763) * Use network specific swaps contract address when checking swap contract token approval (#10774) * Set the BSC_CONTRACT_ADDRESS to lowercase (#10800) * Ensure correct primary currency image is displayed on home screen and token list (#10777) * [skip e2e] Update changelog for v9.3.0 (#10740) * Version v9.3.0 * [skip e2e] Update changelog for v9.3.0 (#10803) Co-authored-by: Dan J Miller <danjm.com@gmail.com> Co-authored-by: ryanml <ryanlanese@gmail.com> Co-authored-by: David Walsh <davidwalsh83@gmail.com> Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
4 years ago
return await contract.allowance(
walletAddress,
SWAPS_CHAINID_CONTRACT_ADDRESS_MAP[chainId],
);
}
/**
* Sets up the fetching of the swaps feature liveness flag from our API.
* Performs an initial fetch when called, then fetches on a 10-minute
* interval.
*
* If the browser goes offline, the interval is cleared and swaps are disabled
* until the value can be fetched again.
*/
_setupSwapsLivenessFetching() {
const TEN_MINUTES_MS = 10 * 60 * 1000;
let intervalId = null;
const fetchAndSetupInterval = () => {
if (window.navigator.onLine && intervalId === null) {
// Set the interval first to prevent race condition between listener and
// initial call to this function.
intervalId = setInterval(
this._fetchAndSetSwapsLiveness.bind(this),
TEN_MINUTES_MS,
);
this._fetchAndSetSwapsLiveness();
}
};
window.addEventListener('online', fetchAndSetupInterval);
window.addEventListener('offline', () => {
if (intervalId !== null) {
clearInterval(intervalId);
intervalId = null;
const { swapsState } = this.store.getState();
if (swapsState.swapsFeatureIsLive) {
this.setSwapsLiveness(false);
}
}
});
fetchAndSetupInterval();
}
/**
* This function should only be called via _setupSwapsLivenessFetching.
*
* Attempts to fetch the swaps feature liveness flag from our API. Tries
* to fetch three times at 5-second intervals before giving up, in which
* case the value defaults to 'false'.
*
* Only updates state if the fetched/computed flag value differs from current
* state.
*/
async _fetchAndSetSwapsLiveness() {
const { swapsState } = this.store.getState();
const { swapsFeatureIsLive: oldSwapsFeatureIsLive } = swapsState;
Version v9.3.0 RC (#10739) * Replace logic for eth swap token in fetchQuotesAndSetQuoteState with getSwapsEthToken call (#10624) * Move swaps constants to the shared constants directory (#10614) * Fix: ETH 'token' now only appears once in the swaps to and from dropdowns. (#10650) * Swaps support for local testnet (#10658) * Swaps support for local testnet * Create util method for comparison of token addresses/symbols to default swaps token * Get chainId from txMeta in _trackSwapsMetrics of transaction controller * Add comment to document purpose of getTransactionGroupRecipientAddressFilter * Use isSwapsDefaultTokenSymbol in place of repeated defaultTokenSymbol comparisons in build-quote.js * Additional swaps network support (#10721) * Add swaps support for bnc chain * Use single default token address in shared/constants/swaps * Ensure swaps gas prices are fetched from the correct chain specific endpoint (#10744) * Ensure swaps gas prices are fetched from the correct chain specific endpoint * Just rely on fetchWithCache to cache swaps gas prices, instead of directly using storage in getSwapsPriceEstimatesLastRetrieved * Empty commit * update @metamask/etherscan-link to v2.0.0 (#10747) * Use correct block explorer name and link in swaps when on custom network (#10743) * Use correct block explorer name and link in swaps when on custom network. * Fix up custom etherscan link code in build-quote.js * Use blockExplorerUrl hostname instead of 'blockExplorerBaseUrl' * Use correct etherscan-link method for token links in build-quote * Create correct token link in build-quote for mainnet AND custom networks * Block explorer url improvements in awaiting-swap.js and build-quote.js * Use swapVerifyTokenExplanation message with substitutable block explorer for all applicable locales * Ensure that block explorer links are not shown in awaiting-swap if no url is available * Ensure that the correct default currency symbols are used for fees on the view quote screen (#10753) * Updating y18n and netmask to resolve dependency issues (#10765) netmask@1.0.6 -> 2.0.1, y18n@3.2.1 -> 3.2.2, y18n@4.0.0 -> 4.0.1 * Ensure that priceSlippage fiat amounts are always shown in view-quote.js (#10762) * Ensure that the approval fee in the swaps custom gas modal is in network specific currency (#10763) * Use network specific swaps contract address when checking swap contract token approval (#10774) * Set the BSC_CONTRACT_ADDRESS to lowercase (#10800) * Ensure correct primary currency image is displayed on home screen and token list (#10777) * [skip e2e] Update changelog for v9.3.0 (#10740) * Version v9.3.0 * [skip e2e] Update changelog for v9.3.0 (#10803) Co-authored-by: Dan J Miller <danjm.com@gmail.com> Co-authored-by: ryanml <ryanlanese@gmail.com> Co-authored-by: David Walsh <davidwalsh83@gmail.com> Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
4 years ago
const chainId = this._getCurrentChainId();
let swapsFeatureIsLive = false;
let successfullyFetched = false;
let numAttempts = 0;
const fetchAndIncrementNumAttempts = async () => {
try {
Version v9.3.0 RC (#10739) * Replace logic for eth swap token in fetchQuotesAndSetQuoteState with getSwapsEthToken call (#10624) * Move swaps constants to the shared constants directory (#10614) * Fix: ETH 'token' now only appears once in the swaps to and from dropdowns. (#10650) * Swaps support for local testnet (#10658) * Swaps support for local testnet * Create util method for comparison of token addresses/symbols to default swaps token * Get chainId from txMeta in _trackSwapsMetrics of transaction controller * Add comment to document purpose of getTransactionGroupRecipientAddressFilter * Use isSwapsDefaultTokenSymbol in place of repeated defaultTokenSymbol comparisons in build-quote.js * Additional swaps network support (#10721) * Add swaps support for bnc chain * Use single default token address in shared/constants/swaps * Ensure swaps gas prices are fetched from the correct chain specific endpoint (#10744) * Ensure swaps gas prices are fetched from the correct chain specific endpoint * Just rely on fetchWithCache to cache swaps gas prices, instead of directly using storage in getSwapsPriceEstimatesLastRetrieved * Empty commit * update @metamask/etherscan-link to v2.0.0 (#10747) * Use correct block explorer name and link in swaps when on custom network (#10743) * Use correct block explorer name and link in swaps when on custom network. * Fix up custom etherscan link code in build-quote.js * Use blockExplorerUrl hostname instead of 'blockExplorerBaseUrl' * Use correct etherscan-link method for token links in build-quote * Create correct token link in build-quote for mainnet AND custom networks * Block explorer url improvements in awaiting-swap.js and build-quote.js * Use swapVerifyTokenExplanation message with substitutable block explorer for all applicable locales * Ensure that block explorer links are not shown in awaiting-swap if no url is available * Ensure that the correct default currency symbols are used for fees on the view quote screen (#10753) * Updating y18n and netmask to resolve dependency issues (#10765) netmask@1.0.6 -> 2.0.1, y18n@3.2.1 -> 3.2.2, y18n@4.0.0 -> 4.0.1 * Ensure that priceSlippage fiat amounts are always shown in view-quote.js (#10762) * Ensure that the approval fee in the swaps custom gas modal is in network specific currency (#10763) * Use network specific swaps contract address when checking swap contract token approval (#10774) * Set the BSC_CONTRACT_ADDRESS to lowercase (#10800) * Ensure correct primary currency image is displayed on home screen and token list (#10777) * [skip e2e] Update changelog for v9.3.0 (#10740) * Version v9.3.0 * [skip e2e] Update changelog for v9.3.0 (#10803) Co-authored-by: Dan J Miller <danjm.com@gmail.com> Co-authored-by: ryanml <ryanlanese@gmail.com> Co-authored-by: David Walsh <davidwalsh83@gmail.com> Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
4 years ago
swapsFeatureIsLive = Boolean(
await this._fetchSwapsFeatureLiveness(chainId),
);
successfullyFetched = true;
} catch (err) {
log.error(err);
numAttempts += 1;
}
};
await fetchAndIncrementNumAttempts();
// The loop conditions are modified by fetchAndIncrementNumAttempts.
// eslint-disable-next-line no-unmodified-loop-condition
while (!successfullyFetched && numAttempts < 3) {
await new Promise((resolve) => {
setTimeout(resolve, 5000); // 5 seconds
});
await fetchAndIncrementNumAttempts();
}
if (!successfullyFetched) {
log.error(
'Failed to fetch swaps feature flag 3 times. Setting to false and trying again next interval.',
);
}
if (swapsFeatureIsLive !== oldSwapsFeatureIsLive) {
this.setSwapsLiveness(swapsFeatureIsLive);
}
}
}
/**
* Calculates the median overallValueOfQuote of a sample of quotes.
*
* @param {Array} quotes - A sample of quote objects with overallValueOfQuote, ethFee, metaMaskFeeInEth, and ethValueOfTokens properties
* @returns {Object} An object with the ethValueOfTokens, ethFee, and metaMaskFeeInEth of the quote with the median overallValueOfQuote
*/
function getMedianEthValueQuote(_quotes) {
if (!Array.isArray(_quotes) || _quotes.length === 0) {
throw new Error('Expected non-empty array param.');
}
const quotes = [..._quotes];
quotes.sort((quoteA, quoteB) => {
const overallValueOfQuoteA = new BigNumber(quoteA.overallValueOfQuote, 10);
const overallValueOfQuoteB = new BigNumber(quoteB.overallValueOfQuote, 10);
if (overallValueOfQuoteA.equals(overallValueOfQuoteB)) {
return 0;
}
return overallValueOfQuoteA.lessThan(overallValueOfQuoteB) ? -1 : 1;
});
if (quotes.length % 2 === 1) {
// return middle values
const medianOverallValue =
quotes[(quotes.length - 1) / 2].overallValueOfQuote;
const quotesMatchingMedianQuoteValue = quotes.filter(
(quote) => medianOverallValue === quote.overallValueOfQuote,
);
return meansOfQuotesFeesAndValue(quotesMatchingMedianQuoteValue);
}
// return mean of middle two values
const upperIndex = quotes.length / 2;
const lowerIndex = upperIndex - 1;
const overallValueAtUpperIndex = quotes[upperIndex].overallValueOfQuote;
const overallValueAtLowerIndex = quotes[lowerIndex].overallValueOfQuote;
const quotesMatchingUpperIndexValue = quotes.filter(
(quote) => overallValueAtUpperIndex === quote.overallValueOfQuote,
);
const quotesMatchingLowerIndexValue = quotes.filter(
(quote) => overallValueAtLowerIndex === quote.overallValueOfQuote,
);
const feesAndValueAtUpperIndex = meansOfQuotesFeesAndValue(
quotesMatchingUpperIndexValue,
);
const feesAndValueAtLowerIndex = meansOfQuotesFeesAndValue(
quotesMatchingLowerIndexValue,
);
return {
ethFee: new BigNumber(feesAndValueAtUpperIndex.ethFee, 10)
.plus(feesAndValueAtLowerIndex.ethFee, 10)
.dividedBy(2)
.toString(10),
metaMaskFeeInEth: new BigNumber(
feesAndValueAtUpperIndex.metaMaskFeeInEth,
10,
)
.plus(feesAndValueAtLowerIndex.metaMaskFeeInEth, 10)
.dividedBy(2)
.toString(10),
ethValueOfTokens: new BigNumber(
feesAndValueAtUpperIndex.ethValueOfTokens,
10,
)
.plus(feesAndValueAtLowerIndex.ethValueOfTokens, 10)
.dividedBy(2)
.toString(10),
};
}
/**
* Calculates the arithmetic mean for each of three properties - ethFee, metaMaskFeeInEth and ethValueOfTokens - across
* an array of objects containing those properties.
*
* @param {Array} quotes - A sample of quote objects with overallValueOfQuote, ethFee, metaMaskFeeInEth and
* ethValueOfTokens properties
* @returns {Object} An object with the arithmetic mean each of the ethFee, metaMaskFeeInEth and ethValueOfTokens of
* the passed quote objects
*/
function meansOfQuotesFeesAndValue(quotes) {
const feeAndValueSumsAsBigNumbers = quotes.reduce(
(feeAndValueSums, quote) => ({
ethFee: feeAndValueSums.ethFee.plus(quote.ethFee, 10),
metaMaskFeeInEth: feeAndValueSums.metaMaskFeeInEth.plus(
quote.metaMaskFeeInEth,
10,
),
ethValueOfTokens: feeAndValueSums.ethValueOfTokens.plus(
quote.ethValueOfTokens,
10,
),
}),
{
ethFee: new BigNumber(0, 10),
metaMaskFeeInEth: new BigNumber(0, 10),
ethValueOfTokens: new BigNumber(0, 10),
},
);
return {
ethFee: feeAndValueSumsAsBigNumbers.ethFee
.div(quotes.length, 10)
.toString(10),
metaMaskFeeInEth: feeAndValueSumsAsBigNumbers.metaMaskFeeInEth
.div(quotes.length, 10)
.toString(10),
ethValueOfTokens: feeAndValueSumsAsBigNumbers.ethValueOfTokens
.div(quotes.length, 10)
.toString(10),
};
}
export const utils = {
getMedianEthValueQuote,
meansOfQuotesFeesAndValue,
};