diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b72ff11f..a42139678 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,18 @@ ## Current Develop Branch +## 8.1.1 Tue Oct 13 2020 +- [#9586](https://github.com/MetaMask/metamask-extension/pull/9586): Prevent build quote crash when swapping from non-tracked token with balance (#9586) +- [#9592](https://github.com/MetaMask/metamask-extension/pull/9592): Remove commitment to maintain a public metrics dashboard (#9592) +- [#9596](https://github.com/MetaMask/metamask-extension/pull/9596): Fix TypeError when `signTypedData` throws (#9596) +- [#9591](https://github.com/MetaMask/metamask-extension/pull/9591): Fix Firefox overflow on transaction items with long amounts (#9591) +- [#9601](https://github.com/MetaMask/metamask-extension/pull/9601): Update text content of invalid custom network alert (#9601) +- [#9575](https://github.com/MetaMask/metamask-extension/pull/9575): Ensure proper hover display for accounts in main menu (#9575) +- [#9576](https://github.com/MetaMask/metamask-extension/pull/9576): Autofocus the appropriate text fields in the Create/Import/Hardware screen (#9576) +- [#9581](https://github.com/MetaMask/metamask-extension/pull/9581): AutoFocus the from input on swaps screen (#9581) +- [#9602](https://github.com/MetaMask/metamask-extension/pull/9602): Prevent swap button from being focused when disabled (#9602) +- [#9609](https://github.com/MetaMask/metamask-extension/pull/9609): Ensure swaps customize gas modal values are set correctly (#9609) + ## 8.1.0 Tue Oct 13 2020 - [#9565](https://github.com/MetaMask/metamask-extension/pull/9565): Ensure address book entries are shared between networks with the same chain ID - [#9552](https://github.com/MetaMask/metamask-extension/pull/9552): Fix `eth_signTypedData_v4` chain ID validation for non-default networks diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index e7439db82..3188d7894 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -842,7 +842,7 @@ "message": "Invalid Block Explorer URL" }, "invalidCustomNetworkAlertContent1": { - "message": "The custom network '$1' is missing its chain ID.", + "message": "The chain ID for custom network '$1' has to be re-entered.", "description": "$1 is the name/identifier of the network." }, "invalidCustomNetworkAlertContent2": { @@ -967,6 +967,37 @@ "metamaskVersion": { "message": "MetaMask Version" }, + "metametricsCommitmentsAllowOptOut": { + "message": "Always allow you to opt-out via Settings" + }, + "metametricsCommitmentsBoldNever": { + "message": "Never", + "description": "This string is localized separately from some of the commitments so that we can bold it" + }, + "metametricsCommitmentsIntro": { + "message": "MetaMask will.." + }, + "metametricsCommitmentsNeverCollectIP": { + "message": "$1 collect your full IP address", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsNeverCollectKeysEtc": { + "message": "$1 collect keys, addresses, transactions, balances, hashes, or any personal information", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsNeverSellDataForProfit": { + "message": "$1 sell data for profit. Ever!", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsSendAnonymizedEvents": { + "message": "Send anonymized click & pageview events" + }, + "metametricsHelpImproveMetaMask": { + "message": "Help Us Improve MetaMask" + }, + "metametricsOptInDescription": { + "message": "MetaMask would like to gather usage data to better understand how our users interact with the extension. This data will be used to continually improve the usability and user experience of our product and the Ethereum ecosystem." + }, "mobileSyncText": { "message": "Please enter your password to confirm it's you!" }, @@ -1753,6 +1784,9 @@ "swapSelectAQuote": { "message": "Select a quote" }, + "swapSelectAToken": { + "message": "Select a token" + }, "swapSelectQuotePopoverDescription": { "message": "Below are all the quotes gathered from multiple liquidity sources." }, diff --git a/app/manifest/_base.json b/app/manifest/_base.json index 77a564e82..09bb58e6d 100644 --- a/app/manifest/_base.json +++ b/app/manifest/_base.json @@ -68,6 +68,6 @@ "notifications" ], "short_name": "__MSG_appName__", - "version": "8.1.0", + "version": "8.1.1", "web_accessible_resources": ["inpage.js", "phishing.html"] } diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js index d469cfa1b..4406672b2 100644 --- a/app/scripts/controllers/transactions/index.js +++ b/app/scripts/controllers/transactions/index.js @@ -858,6 +858,13 @@ export default class TransactionController extends EventEmitter { .round(2) }%` + const estimatedVsUsedGasRatio = `${ + (new BigNumber(txMeta.txReceipt.gasUsed, 16)) + .div(txMeta.swapMetaData.estimated_gas, 16) + .times(100) + .round(2) + }%` + this._trackSegmentEvent({ event: 'Swap Completed', category: 'swaps', @@ -871,6 +878,7 @@ export default class TransactionController extends EventEmitter { ...txMeta.swapMetaData, token_to_amount_received: tokensReceived, quote_vs_executionRatio: quoteVsExecutionRatio, + estimated_vs_used_gasRatio: estimatedVsUsedGasRatio, }, excludeMetaMetricsId: true, }) diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index f46e437fc..b4166bde5 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -1414,7 +1414,7 @@ export default class MetamaskController extends EventEmitter { } catch (error) { log.info('MetaMaskController - eth_signTypedData failed.', error) this.typedMessageManager.errorMessage(msgId, error) - return undefined + throw error } } @@ -1864,12 +1864,8 @@ export default class MetamaskController extends EventEmitter { * @returns {Promise} */ async getNextNonce (address) { - let nonceLock - try { - nonceLock = await this.txController.nonceTracker.getNonceLock(address) - } finally { - nonceLock.releaseLock() - } + const nonceLock = await this.txController.nonceTracker.getNonceLock(address) + nonceLock.releaseLock() return nonceLock.nextNonce } diff --git a/package.json b/package.json index 77067a0bf..2ed8e593a 100644 --- a/package.json +++ b/package.json @@ -81,8 +81,8 @@ "@metamask/logo": "^2.5.0", "@popperjs/core": "^2.4.0", "@reduxjs/toolkit": "^1.3.2", - "@sentry/browser": "^5.11.1", - "@sentry/integrations": "^5.11.1", + "@sentry/browser": "^5.26.0", + "@sentry/integrations": "^5.26.0", "@zxing/library": "^0.8.0", "abortcontroller-polyfill": "^1.4.0", "analytics-node": "^3.4.0-beta.2", @@ -187,7 +187,7 @@ "@metamask/eslint-config": "^3.2.0", "@metamask/forwarder": "^1.1.0", "@metamask/test-dapp": "^3.1.0", - "@sentry/cli": "^1.49.0", + "@sentry/cli": "^1.58.0", "@storybook/addon-actions": "^5.3.14", "@storybook/addon-backgrounds": "^5.3.14", "@storybook/addon-knobs": "^5.3.14", diff --git a/ui/app/components/app/account-menu/account-menu.component.js b/ui/app/components/app/account-menu/account-menu.component.js index ec3f3f7a9..b4f5a2b32 100644 --- a/ui/app/components/app/account-menu/account-menu.component.js +++ b/ui/app/components/app/account-menu/account-menu.component.js @@ -179,7 +179,7 @@ export default class AccountMenu extends Component { return (
{ this.context.metricsEvent({ eventOpts: { diff --git a/ui/app/components/app/account-menu/tests/account-menu.test.js b/ui/app/components/app/account-menu/tests/account-menu.test.js index e0166dd08..6c4fd3a72 100644 --- a/ui/app/components/app/account-menu/tests/account-menu.test.js +++ b/ui/app/components/app/account-menu/tests/account-menu.test.js @@ -88,7 +88,7 @@ describe('Account Menu', function () { }) it('simulate click', function () { - const click = wrapper.find('.account-menu__account.menu__item--clickable') + const click = wrapper.find('.account-menu__account.account-menu__item--clickable') click.first().simulate('click') assert(props.showAccountDetail.calledOnce) diff --git a/ui/app/components/app/dropdowns/network-dropdown.js b/ui/app/components/app/dropdowns/network-dropdown.js index 0f566671f..0bd9aed86 100644 --- a/ui/app/components/app/dropdowns/network-dropdown.js +++ b/ui/app/components/app/dropdowns/network-dropdown.js @@ -34,8 +34,8 @@ function mapDispatchToProps (dispatch) { setProviderType: (type) => { dispatch(actions.setProviderType(type)) }, - setRpcTarget: (target, network, ticker, nickname) => { - dispatch(actions.setRpcTarget(target, network, ticker, nickname)) + setRpcTarget: (target, chainId, ticker, nickname) => { + dispatch(actions.setRpcTarget(target, chainId, ticker, nickname)) }, delRpcTarget: (target) => { dispatch(actions.delRpcTarget(target)) diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js b/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js index 9c8969085..061f43a95 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js @@ -51,9 +51,9 @@ export default class GasModalPageContainer extends Component { isEthereumNetwork: PropTypes.bool, customGasLimitMessage: PropTypes.string, customTotalSupplement: PropTypes.string, - isSwap: PropTypes.boolean, + isSwap: PropTypes.bool, value: PropTypes.string, - conversionRate: PropTypes.string, + conversionRate: PropTypes.number, } state = { diff --git a/ui/app/components/app/wallet-overview/token-overview.js b/ui/app/components/app/wallet-overview/token-overview.js index af765409e..1d499e1b4 100644 --- a/ui/app/components/app/wallet-overview/token-overview.js +++ b/ui/app/components/app/wallet-overview/token-overview.js @@ -38,8 +38,9 @@ const TokenOverview = ({ className, token }) => { const keyring = useSelector(getCurrentKeyring) const usingHardwareWallet = keyring.type.search('Hardware') !== -1 const { tokensWithBalances } = useTokenTracker([token]) - const balance = tokensWithBalances[0]?.string - const formattedFiatBalance = useTokenFiatAmount(token.address, balance, token.symbol) + const balanceToRender = tokensWithBalances[0]?.string + const balance = tokensWithBalances[0]?.balance + const formattedFiatBalance = useTokenFiatAmount(token.address, balanceToRender, token.symbol) const networkId = useSelector(getCurrentNetworkId) const enteredSwapsEvent = useNewMetricEvent({ event: 'Swaps Opened', properties: { source: 'Token View', active_currency: token.symbol }, category: 'swaps' }) const swapsEnabled = useSelector(getSwapsFeatureLiveness) @@ -50,7 +51,7 @@ const TokenOverview = ({ className, token }) => {
{ @@ -87,7 +88,12 @@ const TokenOverview = ({ className, token }) => { onClick={() => { if (networkId === MAINNET_NETWORK_ID) { enteredSwapsEvent() - dispatch(setSwapsFromToken({ ...token, iconUrl: assetImages[token.address] })) + dispatch(setSwapsFromToken({ + ...token, + iconUrl: assetImages[token.address], + balance, + string: balanceToRender, + })) if (usingHardwareWallet) { global.platform.openExtensionInBrowser(BUILD_QUOTE_ROUTE) } else { diff --git a/ui/app/components/ui/icon-button/icon-button.js b/ui/app/components/ui/icon-button/icon-button.js index 4b19d1471..16767bf5e 100644 --- a/ui/app/components/ui/icon-button/icon-button.js +++ b/ui/app/components/ui/icon-button/icon-button.js @@ -11,6 +11,7 @@ export default function IconButton ({ onClick, Icon, disabled, label, tooltipRen className={classNames('icon-button', className, { 'icon-button--disabled': disabled })} data-testid={props['data-testid'] ?? undefined} onClick={onClick} + disabled={disabled} > {renderWrapper( <> diff --git a/ui/app/components/ui/list-item/index.scss b/ui/app/components/ui/list-item/index.scss index feed0eb4a..0838521ec 100644 --- a/ui/app/components/ui/list-item/index.scss +++ b/ui/app/components/ui/list-item/index.scss @@ -85,6 +85,8 @@ grid-area: right; text-align: right; align-items: flex-end; + overflow: hidden; + white-space: nowrap; } @media (max-width: 575px) { diff --git a/ui/app/contexts/metametrics.new.js b/ui/app/contexts/metametrics.new.js index 3afcc9bfa..1d5587ebb 100644 --- a/ui/app/contexts/metametrics.new.js +++ b/ui/app/contexts/metametrics.new.js @@ -92,16 +92,26 @@ export function MetaMetricsProvider ({ children }) { const idTrait = metaMetricsId ? 'userId' : 'anonymousId' const idValue = metaMetricsId ?? METAMETRICS_ANONYMOUS_ID const match = matchPath(location.pathname, { path: PATHS_TO_CHECK, exact: true, strict: true }) - if ( - match && + // Start by checking for a missing match route. If this falls through to the else if, then we know we + // have a matched route for tracking. + if (!match) { + // We have more specific pages for each type of transaction confirmation + // The user lands on /confirm-transaction first, then is redirected based on + // the contents of state. + if (location.pathname !== '/confirm-transaction') { + // Otherwise we are legitimately missing a matching route + captureMessage(`Segment page tracking found unmatched route`, { + previousMatch, + currentPath: location.pathname, + }) + } + } else if ( previousMatch.current !== match.path && - // If we're in a popup or notification we don't want the initial home route to track - !( - (environmentType === 'popup' || environmentType === 'notification') && - match.path === '/' && - previousMatch.current === undefined - ) + !(environmentType === 'notification' && match.path === '/' && previousMatch.current === undefined) ) { + // When a notification window is open by a Dapp we do not want to track the initial home route load that can + // sometimes happen. To handle this we keep track of the previousMatch, and we skip the event track in the event + // that we are dealing with the initial load of the homepage const { path, params } = match const name = PATH_NAME_MAP[path] segment.page({ @@ -116,11 +126,6 @@ export function MetaMetricsProvider ({ children }) { }, context, }) - } else if (location.pathname !== '/confirm-transaction') { - // We have more specific pages for each type of transaction confirmation - // The user lands on /confirm-transaction first, then is redirected based on - // the contents of state. - captureMessage(`${location.pathname} would have issued a page track event to segment, but no route match was found`) } previousMatch.current = match?.path } diff --git a/ui/app/ducks/swaps/swaps.js b/ui/app/ducks/swaps/swaps.js index 840b4bfe2..60f6ab9d0 100644 --- a/ui/app/ducks/swaps/swaps.js +++ b/ui/app/ducks/swaps/swaps.js @@ -38,7 +38,7 @@ import { SWAP_FAILED_ERROR, } from '../../helpers/constants/swaps' import { SWAP, SWAP_APPROVAL } from '../../helpers/constants/transactions' -import { fetchBasicGasAndTimeEstimates, fetchGasEstimates, resetCustomData } from '../gas/gas.duck' +import { fetchBasicGasAndTimeEstimates, fetchGasEstimates, resetCustomGasState } from '../gas/gas.duck' import { formatCurrency } from '../../helpers/utils/confirm-tx.util' const initialState = { @@ -235,7 +235,7 @@ export const prepareForRetryGetQuotes = () => { export const prepareToLeaveSwaps = () => { return async (dispatch) => { - dispatch(resetCustomData()) + dispatch(resetCustomGasState()) dispatch(clearSwapsState()) await dispatch(resetBackgroundSwapsState()) @@ -474,6 +474,7 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => { other_quote_selected: usedQuote.aggregator !== getTopQuote(state)?.aggregator, other_quote_selected_source: usedQuote.aggregator === getTopQuote(state)?.aggregator ? '' : usedQuote.aggregator, gas_fees: formatCurrency(gasEstimateTotalInEth, 'usd')?.slice(1), + estimated_gas: estimatedGasLimit.toString(16), } const metaMetricsConfig = { diff --git a/ui/app/pages/create-account/import-account/private-key.js b/ui/app/pages/create-account/import-account/private-key.js index cbc155f81..d3c4240f8 100644 --- a/ui/app/pages/create-account/import-account/private-key.js +++ b/ui/app/pages/create-account/import-account/private-key.js @@ -91,6 +91,7 @@ class PrivateKeyImportView extends Component { onKeyPress={(e) => this.createKeyringOnEnter(e)} onChange={() => this.checkInputEmpty()} ref={this.inputRef} + autoFocus />
diff --git a/ui/app/pages/create-account/new-account.component.js b/ui/app/pages/create-account/new-account.component.js index ef811a84f..9995b28ab 100644 --- a/ui/app/pages/create-account/new-account.component.js +++ b/ui/app/pages/create-account/new-account.component.js @@ -54,6 +54,7 @@ export default class NewAccountCreateForm extends Component { value={newAccountName} placeholder={defaultAccountName} onChange={(event) => this.setState({ newAccountName: event.target.value })} + autoFocus />
-
Help Us Improve MetaMask
+
{t('metametricsHelpImproveMetaMask')}
- MetaMask would like to gather usage data to better understand how our users interact with the extension. This data - will be used to continually improve the usability and user experience of our product and the Ethereum ecosystem. + {t('metametricsOptInDescription')}
- MetaMask will.. + {t('metametricsCommitmentsIntro')}
- Always allow you to opt-out via Settings + {t('metametricsCommitmentsAllowOptOut')}
- Send anonymized click & pageview events -
-
-
- -
- Maintain a public aggregate dashboard to educate the community + {t('metametricsCommitmentsSendAnonymizedEvents')}
- Never collect keys, addresses, transactions, balances, hashes, or any personal information + { + t( + 'metametricsCommitmentsNeverCollectKeysEtc', + [( + + {t('metametricsCommitmentsBoldNever')} + + )], + ) + }
- Never collect your full IP address + { + t( + 'metametricsCommitmentsNeverCollectIP', + [( + + {t('metametricsCommitmentsBoldNever')} + + )], + ) + }
- Never sell data for profit. Ever! + { + t( + 'metametricsCommitmentsNeverSellDataForProfit', + [( + + {t('metametricsCommitmentsBoldNever')} + + )], + ) + }
diff --git a/ui/app/pages/send/send.utils.js b/ui/app/pages/send/send.utils.js index 32dc1939a..ab30f0374 100644 --- a/ui/app/pages/send/send.utils.js +++ b/ui/app/pages/send/send.utils.js @@ -26,7 +26,7 @@ export { calcGasTotal, calcTokenBalance, doesAmountErrorRequireUpdate, - estimateGas, + estimateGasForSend, generateTokenTransferData, getAmountErrorObject, getGasFeeErrorObject, @@ -193,7 +193,7 @@ function doesAmountErrorRequireUpdate ({ return amountErrorRequiresUpdate } -async function estimateGas ({ +async function estimateGasForSend ({ selectedAddress, sendToken, blockGasLimit = MIN_GAS_LIMIT_HEX, diff --git a/ui/app/pages/send/tests/send-utils.test.js b/ui/app/pages/send/tests/send-utils.test.js index 0d23947ff..e3a98ea0c 100644 --- a/ui/app/pages/send/tests/send-utils.test.js +++ b/ui/app/pages/send/tests/send-utils.test.js @@ -45,7 +45,7 @@ const sendUtils = proxyquire('../send.utils.js', { const { calcGasTotal, - estimateGas, + estimateGasForSend, doesAmountErrorRequireUpdate, generateTokenTransferData, getAmountErrorObject, @@ -288,7 +288,7 @@ describe('send utils', function () { }) }) - describe('estimateGas', function () { + describe('estimateGasForSend', function () { const baseMockParams = { blockGasLimit: '0x64', selectedAddress: 'mockAddress', @@ -322,8 +322,8 @@ describe('send utils', function () { global.eth.getCode.resetHistory() }) - it('should call ethQuery.estimateGas with the expected params', async function () { - const result = await sendUtils.estimateGas(baseMockParams) + it('should call ethQuery.estimateGasForSend with the expected params', async function () { + const result = await estimateGasForSend(baseMockParams) assert.equal(baseMockParams.estimateGasMethod.callCount, 1) assert.deepEqual( baseMockParams.estimateGasMethod.getCall(0).args[0], @@ -332,8 +332,8 @@ describe('send utils', function () { assert.equal(result, '0xabc16') }) - it('should call ethQuery.estimateGas with the expected params when initialGasLimitHex is lower than the upperGasLimit', async function () { - const result = await estimateGas({ ...baseMockParams, blockGasLimit: '0xbcd' }) + it('should call ethQuery.estimateGasForSend with the expected params when initialGasLimitHex is lower than the upperGasLimit', async function () { + const result = await estimateGasForSend({ ...baseMockParams, blockGasLimit: '0xbcd' }) assert.equal(baseMockParams.estimateGasMethod.callCount, 1) assert.deepEqual( baseMockParams.estimateGasMethod.getCall(0).args[0], @@ -342,8 +342,8 @@ describe('send utils', function () { assert.equal(result, '0xabc16x1.5') }) - it('should call ethQuery.estimateGas with a value of 0x0 and the expected data and to if passed a sendToken', async function () { - const result = await estimateGas({ data: 'mockData', sendToken: { address: 'mockAddress' }, ...baseMockParams }) + it('should call ethQuery.estimateGasForSend with a value of 0x0 and the expected data and to if passed a sendToken', async function () { + const result = await estimateGasForSend({ data: 'mockData', sendToken: { address: 'mockAddress' }, ...baseMockParams }) assert.equal(baseMockParams.estimateGasMethod.callCount, 1) assert.deepEqual( baseMockParams.estimateGasMethod.getCall(0).args[0], @@ -357,10 +357,10 @@ describe('send utils', function () { assert.equal(result, '0xabc16') }) - it('should call ethQuery.estimateGas without a recipient if the recipient is empty and data passed', async function () { + it('should call ethQuery.estimateGasForSend without a recipient if the recipient is empty and data passed', async function () { const data = 'mockData' const to = '' - const result = await estimateGas({ ...baseMockParams, data, to }) + const result = await estimateGasForSend({ ...baseMockParams, data, to }) assert.equal(baseMockParams.estimateGasMethod.callCount, 1) assert.deepEqual( baseMockParams.estimateGasMethod.getCall(0).args[0], @@ -371,40 +371,40 @@ describe('send utils', function () { it(`should return ${SIMPLE_GAS_COST} if ethQuery.getCode does not return '0x'`, async function () { assert.equal(baseMockParams.estimateGasMethod.callCount, 0) - const result = await estimateGas({ ...baseMockParams, to: '0x123' }) + const result = await estimateGasForSend({ ...baseMockParams, to: '0x123' }) assert.equal(result, SIMPLE_GAS_COST) }) it(`should return ${SIMPLE_GAS_COST} if not passed a sendToken or truthy to address`, async function () { assert.equal(baseMockParams.estimateGasMethod.callCount, 0) - const result = await estimateGas({ ...baseMockParams, to: null }) + const result = await estimateGasForSend({ ...baseMockParams, to: null }) assert.equal(result, SIMPLE_GAS_COST) }) it(`should not return ${SIMPLE_GAS_COST} if passed a sendToken`, async function () { assert.equal(baseMockParams.estimateGasMethod.callCount, 0) - const result = await estimateGas({ ...baseMockParams, to: '0x123', sendToken: { address: '0x0' } }) + const result = await estimateGasForSend({ ...baseMockParams, to: '0x123', sendToken: { address: '0x0' } }) assert.notEqual(result, SIMPLE_GAS_COST) }) it(`should return ${BASE_TOKEN_GAS_COST} if passed a sendToken but no to address`, async function () { - const result = await estimateGas({ ...baseMockParams, to: null, sendToken: { address: '0x0' } }) + const result = await estimateGasForSend({ ...baseMockParams, to: null, sendToken: { address: '0x0' } }) assert.equal(result, BASE_TOKEN_GAS_COST) }) it(`should return the adjusted blockGasLimit if it fails with a 'Transaction execution error.'`, async function () { - const result = await estimateGas({ ...baseMockParams, to: 'isContract willFailBecauseOf:Transaction execution error.' }) + const result = await estimateGasForSend({ ...baseMockParams, to: 'isContract willFailBecauseOf:Transaction execution error.' }) assert.equal(result, '0x64x0.95') }) it(`should return the adjusted blockGasLimit if it fails with a 'gas required exceeds allowance or always failing transaction.'`, async function () { - const result = await estimateGas({ ...baseMockParams, to: 'isContract willFailBecauseOf:gas required exceeds allowance or always failing transaction.' }) + const result = await estimateGasForSend({ ...baseMockParams, to: 'isContract willFailBecauseOf:gas required exceeds allowance or always failing transaction.' }) assert.equal(result, '0x64x0.95') }) it(`should reject other errors`, async function () { try { - await estimateGas({ ...baseMockParams, to: 'isContract willFailBecauseOf:some other error' }) + await estimateGasForSend({ ...baseMockParams, to: 'isContract willFailBecauseOf:some other error' }) } catch (err) { assert.equal(err.message, 'some other error') } diff --git a/ui/app/pages/swaps/build-quote/build-quote.js b/ui/app/pages/swaps/build-quote/build-quote.js index 6074801ee..8ca56c3af 100644 --- a/ui/app/pages/swaps/build-quote/build-quote.js +++ b/ui/app/pages/swaps/build-quote/build-quote.js @@ -24,7 +24,7 @@ import { getTopAssets, getFetchParams, } from '../../../ducks/swaps/swaps' -import { getValueFromWeiHex } from '../../../helpers/utils/conversions.util' +import { getValueFromWeiHex, hexToDecimal } from '../../../helpers/utils/conversions.util' import { calcTokenAmount } from '../../../helpers/utils/token-util' import { usePrevious } from '../../../hooks/usePrevious' import { useTokenTracker } from '../../../hooks/useTokenTracker' @@ -132,9 +132,8 @@ export default function BuildQuote ({ .then((fetchedBalance) => { if (fetchedBalance?.balance) { const balanceAsDecString = fetchedBalance.balance.toString(10) - const balanceAsHexString = fetchedBalance.balance.toString(16) const userTokenBalance = calcTokenAmount(balanceAsDecString, token.decimals) - dispatch(setSwapsFromToken({ ...token, string: userTokenBalance.toString(10), balance: balanceAsHexString })) + dispatch(setSwapsFromToken({ ...token, string: userTokenBalance.toString(10), balance: balanceAsDecString })) } }) } @@ -167,8 +166,12 @@ export default function BuildQuote ({ // If the eth balance changes while on build quote, we update the selected from token useEffect(() => { - if (fromToken?.address === ETH_SWAPS_TOKEN_OBJECT.address && (fromToken?.balance !== ethBalance)) { - dispatch(setSwapsFromToken({ ...fromToken, balance: ethBalance, string: getValueFromWeiHex({ value: ethBalance, numberOfDecimals: 4, toDenomination: 'ETH' }) })) + if (fromToken?.address === ETH_SWAPS_TOKEN_OBJECT.address && (fromToken?.balance !== hexToDecimal(ethBalance))) { + dispatch(setSwapsFromToken({ + ...fromToken, + balance: hexToDecimal(ethBalance), + string: getValueFromWeiHex({ value: ethBalance, numberOfDecimals: 4, toDenomination: 'ETH' }), + })) } }, [dispatch, fromToken, ethBalance]) @@ -206,9 +209,10 @@ export default function BuildQuote ({ selectedItem={selectedFromToken} maxListItems={30} loading={loading && (!tokensToSearch?.length || !topAssets || !Object.keys(topAssets).length)} - selectPlaceHolderText="Select" + selectPlaceHolderText={t('swapSelect')} hideItemIf={(item) => item.address === selectedToToken?.address} listContainerClassName="build-quote__open-dropdown" + autoFocus />
setIsOpen(true) @@ -91,7 +92,8 @@ export default function DropdownInputPair ({ onChange={onTextFieldChange} fullWidth margin="dense" - value={ inputValue } + value={inputValue} + autoFocus={autoFocus} /> )} { @@ -123,4 +125,5 @@ DropdownInputPair.propTypes = { loading: PropTypes.bool, hideItemIf: PropTypes.func, listContainerClassName: PropTypes.string, + autoFocus: PropTypes.bool, } diff --git a/ui/app/pages/swaps/fee-card/fee-card.js b/ui/app/pages/swaps/fee-card/fee-card.js index d8caf51ad..61c173015 100644 --- a/ui/app/pages/swaps/fee-card/fee-card.js +++ b/ui/app/pages/swaps/fee-card/fee-card.js @@ -1,21 +1,26 @@ -import React from 'react' +import React, { useContext } from 'react' import PropTypes from 'prop-types' +import { I18nContext } from '../../../contexts/i18n' import InfoTooltip from '../../../components/ui/info-tooltip' export default function FeeCard ({ - feeRowText, primaryFee, secondaryFee, - thirdRow, - maxFeeRow, + hideTokenApprovalRow, + onFeeCardMaxRowClick, + tokenApprovalTextComponent, + tokenApprovalSourceTokenSymbol, + onTokenApprovalClick, }) { + const t = useContext(I18nContext) + return (
- {feeRowText} + {t('swapEstimatedNetworkFee')}
@@ -29,18 +34,18 @@ export default function FeeCard ({ )}
-
maxFeeRow.onClick()}> +
onFeeCardMaxRowClick()}>
- {maxFeeRow.text} + {t('swapMaxNetworkFees')}
- {maxFeeRow.linkText} + {t('edit')}
@@ -55,18 +60,18 @@ export default function FeeCard ({ )}
- {thirdRow && !thirdRow.hide && ( + {!hideTokenApprovalRow && (
- {thirdRow.text} + {t('swapThisWillAllowApprove', [tokenApprovalTextComponent])}
-
thirdRow.onClick()}> - {thirdRow.linkText} +
onTokenApprovalClick()}> + {t('swapEditLimit')}
@@ -77,7 +82,6 @@ export default function FeeCard ({ } FeeCard.propTypes = { - feeRowText: PropTypes.string.isRequired, primaryFee: PropTypes.shape({ fee: PropTypes.string.isRequired, maxFee: PropTypes.string.isRequired, @@ -86,23 +90,9 @@ FeeCard.propTypes = { fee: PropTypes.string.isRequired, maxFee: PropTypes.string.isRequired, }), - maxFeeRow: PropTypes.shape({ - text: PropTypes.string.isRequired, - linkText: PropTypes.string.isRequired, - tooltipText: PropTypes.string.isRequired, - onClick: PropTypes.func.isRequired, - }).isRequired, - thirdRow: PropTypes.shape({ - text: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.node, - ]).isRequired, - linkText: PropTypes.string.isRequired, - tooltipText: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.node, - ]).isRequired, - onClick: PropTypes.func.isRequired, - hide: PropTypes.bool.isRequired, - }), + onFeeCardMaxRowClick: PropTypes.func.isRequired, + hideTokenApprovalRow: PropTypes.bool.isRequired, + tokenApprovalTextComponent: PropTypes.node, + tokenApprovalSourceTokenSymbol: PropTypes.string, + onTokenApprovalClick: PropTypes.func, } diff --git a/ui/app/pages/swaps/index.js b/ui/app/pages/swaps/index.js index 206489b8c..ea38f53b7 100644 --- a/ui/app/pages/swaps/index.js +++ b/ui/app/pages/swaps/index.js @@ -25,6 +25,7 @@ import { prepareToLeaveSwaps, fetchAndSetSwapsGasPriceInfo, } from '../../ducks/swaps/swaps' +import { resetCustomGasState } from '../../ducks/gas/gas.duck' import { AWAITING_SWAP_ROUTE, BUILD_QUOTE_ROUTE, @@ -159,6 +160,7 @@ export default function Swap () { dispatch(setMetamaskFeeAmount(metaMaskFeeAmount)) }) + dispatch(resetCustomGasState()) dispatch(fetchAndSetSwapsGasPriceInfo()) return () => { diff --git a/ui/app/pages/swaps/select-quote-popover/select-quote-popover-constants.js b/ui/app/pages/swaps/select-quote-popover/select-quote-popover-constants.js index 2812b68d5..27f99be04 100644 --- a/ui/app/pages/swaps/select-quote-popover/select-quote-popover-constants.js +++ b/ui/app/pages/swaps/select-quote-popover/select-quote-popover-constants.js @@ -6,7 +6,7 @@ export const QUOTE_DATA_ROWS_PROPTYPES_SHAPE = PropTypes.shape({ destinationTokenDecimals: PropTypes.number.isRequired, destinationTokenSymbol: PropTypes.string.isRequired, destinationTokenValue: PropTypes.string.isRequired, - isBestQuote: PropTypes.bool.isRequired, + isBestQuote: PropTypes.bool, liquiditySource: PropTypes.string.isRequired, metaMaskFee: PropTypes.string.isRequired, networkFees: PropTypes.string.isRequired, diff --git a/ui/app/pages/swaps/swaps.util.test.js b/ui/app/pages/swaps/swaps.util.test.js index bf5b166da..527fee29f 100644 --- a/ui/app/pages/swaps/swaps.util.test.js +++ b/ui/app/pages/swaps/swaps.util.test.js @@ -12,9 +12,6 @@ import { } from './swaps-util-test-constants' const swapsUtils = proxyquire('./swaps.util.js', { - '../../store/actions': { - estimateGasFromTxParams: () => Promise.resolve('0x8888'), - }, '../../helpers/utils/fetch-with-cache': { default: (url, fetchObject) => { assert.equal(fetchObject.method, 'GET') diff --git a/ui/app/pages/swaps/view-quote/view-quote.js b/ui/app/pages/swaps/view-quote/view-quote.js index 19a19125f..a94b2319b 100644 --- a/ui/app/pages/swaps/view-quote/view-quote.js +++ b/ui/app/pages/swaps/view-quote/view-quote.js @@ -340,7 +340,7 @@ export default function ViewQuote () { } }, [sourceTokenSymbol, sourceTokenValue, destinationTokenSymbol, destinationTokenValue, fetchParams, topQuote, numberOfQuotes, feeInFiat, bestQuoteReviewedEvent, anonymousBestQuoteReviewedEvent]) - const onFeeCardThirdRowClickHandler = () => { + const onFeeCardTokenApprovalClick = () => { anonymousEditSpendLimitOpened() editSpendLimitOpened() dispatch(showModal({ @@ -375,7 +375,7 @@ export default function ViewQuote () { })) } - const onFeeCardMaxRowClickHandler = () => dispatch(showModal({ + const onFeeCardMaxRowClick = () => dispatch(showModal({ name: 'CUSTOMIZE_GAS', txData: { txParams: { ...tradeTxParams, gas: maxGasLimit } }, isSwap: true, @@ -396,7 +396,7 @@ export default function ViewQuote () { useFastestButtons: true, })) - const thirdRowTextComponent = ( + const tokenApprovalTextComponent = (
diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index c65ad0368..91dadc4eb 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -5,7 +5,7 @@ import log from 'loglevel' import { capitalize } from 'lodash' import getBuyEthUrl from '../../../app/scripts/lib/buy-eth-url' import { checksumAddress } from '../helpers/utils/util' -import { calcTokenBalance, estimateGas } from '../pages/send/send.utils' +import { calcTokenBalance, estimateGasForSend } from '../pages/send/send.utils' import { fetchLocale, loadRelativeTimeFormatLocaleData } from '../helpers/utils/i18n-helper' import { getMethodDataAsync } from '../helpers/utils/transactions.util' import { fetchSymbolAndDecimals } from '../helpers/utils/token-util' @@ -626,7 +626,7 @@ export function updateGasData ({ }) { return (dispatch) => { dispatch(gasLoadingStarted()) - return estimateGas({ + return estimateGasForSend({ estimateGasMethod: promisifiedBackground.estimateGas, blockGasLimit, selectedAddress, @@ -796,37 +796,6 @@ const updateMetamaskStateFromBackground = () => { }) } -export function estimateGasMethod ({ - gasPrice, - blockGasLimit, - selectedAddress, - sendToken, - to, - value, - data, -}) { - return estimateGas({ - estimateGasMethod: promisifiedBackground.estimateGas, - blockGasLimit, - selectedAddress, - sendToken, - to, - value, - gasPrice, - data, - }) -} - -export async function estimateGasFromTxParams (txParams) { - const backgroundState = await updateMetamaskStateFromBackground() - const blockGasLimit = backgroundState.currentBlockGasLimit - return estimateGasMethod({ - ...txParams, - selectedAddress: txParams.from, - blockGasLimit, - }) -} - export function updateTransaction (txData, dontShowLoadingIndicator) { return (dispatch) => { !dontShowLoadingIndicator && dispatch(showLoadingIndication()) diff --git a/yarn.lock b/yarn.lock index 2b38c6715..c6dc9e22f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2239,77 +2239,77 @@ component-type "^1.2.1" join-component "^1.1.0" -"@sentry/browser@^5.11.1": - version "5.11.1" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.11.1.tgz#337ffcb52711b23064c847a07629e966f54a5ebb" - integrity sha512-oqOX/otmuP92DEGRyZeBuQokXdeT9HQRxH73oqIURXXNLMP3PWJALSb4HtT4AftEt/2ROGobZLuA4TaID6My/Q== - dependencies: - "@sentry/core" "5.11.1" - "@sentry/types" "5.11.0" - "@sentry/utils" "5.11.1" +"@sentry/browser@^5.26.0": + version "5.26.0" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.26.0.tgz#e90a197fb94c5f26c8e05d6a539c118f33c7d598" + integrity sha512-52kNVpy10Zd3gJRGFkhnOQvr80WJg7+XBqjMOE0//Akh4PfvEK3IqmAjVqysz6aHdruwTTivKF4ZoAxL/pA7Rg== + dependencies: + "@sentry/core" "5.26.0" + "@sentry/types" "5.26.0" + "@sentry/utils" "5.26.0" tslib "^1.9.3" -"@sentry/cli@^1.49.0": - version "1.49.0" - resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-1.49.0.tgz#174152978acbe6023986a8fb0b247cf58b4653d8" - integrity sha512-Augz7c42Cxz/xWQ/NOVjUGePKVA370quvskWbCICMUwxcTvKnCLI+7KDdzEoCexj4MSuxFfBzLnrrn4w2+c9TQ== +"@sentry/cli@^1.58.0": + version "1.58.0" + resolved "https://registry.yarnpkg.com/@sentry/cli/-/cli-1.58.0.tgz#b1609f10e71539951499866502b13bf3a270fe79" + integrity sha512-bUBKBYyKVzjNhQpAfPJ3XAvAyNNvrD2Rtpo6B0MR3Okw3prdLFgv9Ta8TN19IXT7u9w13B2EdMnNA6dQDtrD4g== dependencies: - fs-copy-file-sync "^1.1.1" - https-proxy-agent "^3.0.0" - mkdirp "^0.5.1" - node-fetch "^2.1.2" - progress "2.0.0" - proxy-from-env "^1.0.0" + https-proxy-agent "^5.0.0" + mkdirp "^0.5.5" + node-fetch "^2.6.0" + progress "^2.0.3" + proxy-from-env "^1.1.0" -"@sentry/core@5.11.1": - version "5.11.1" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.11.1.tgz#9e2da485e196ae32971545c1c49ee6fe719930e2" - integrity sha512-BpvPosVNT20Xso4gAV54Lu3KqDmD20vO63HYwbNdST5LUi8oYV4JhvOkoBraPEM2cbBwQvwVcFdeEYKk4tin9A== +"@sentry/core@5.26.0": + version "5.26.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.26.0.tgz#9b5fe4de8a869d733ebcc77f5ec9c619f8717a51" + integrity sha512-Ubrw7K52orTVsaxpz8Su40FPXugKipoQC+zPrXcH+JIMB+o18kutF81Ae4WzuUqLfP7YB91eAlRrP608zw0EXA== dependencies: - "@sentry/hub" "5.11.1" - "@sentry/minimal" "5.11.1" - "@sentry/types" "5.11.0" - "@sentry/utils" "5.11.1" + "@sentry/hub" "5.26.0" + "@sentry/minimal" "5.26.0" + "@sentry/types" "5.26.0" + "@sentry/utils" "5.26.0" tslib "^1.9.3" -"@sentry/hub@5.11.1": - version "5.11.1" - resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.11.1.tgz#ddcb865563fae53852d405885c46b4c6de68a91b" - integrity sha512-ucKprYCbGGLLjVz4hWUqHN9KH0WKUkGf5ZYfD8LUhksuobRkYVyig0ZGbshECZxW5jcDTzip4Q9Qimq/PkkXBg== +"@sentry/hub@5.26.0": + version "5.26.0" + resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.26.0.tgz#b2bbd8128cd5915f2ee59cbc29fff30272d74ec5" + integrity sha512-lAYeWvvhGYS6eQ5d0VEojw0juxGc3v4aAu8VLvMKWcZ1jXD13Bhc46u9Nvf4qAY6BAQsJDQcpEZLpzJu1bk1Qw== dependencies: - "@sentry/types" "5.11.0" - "@sentry/utils" "5.11.1" + "@sentry/types" "5.26.0" + "@sentry/utils" "5.26.0" tslib "^1.9.3" -"@sentry/integrations@^5.11.1": - version "5.11.1" - resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-5.11.1.tgz#6612efc620c187ba85a57c6e70e69d9474af7fb6" - integrity sha512-zubOE9zQ4qSutS0ZTnAteDnzbVcHSI2bXD/0nTD3t3ljY+OWgcluBXYCAeAp8vOv2qCoef5ySdQa1DBCW7NQ3Q== +"@sentry/integrations@^5.26.0": + version "5.26.0" + resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-5.26.0.tgz#cf90005359862c5b1df4df0f1ce8be5e56c9e1ad" + integrity sha512-XBMPm3wWW+3EJvWFHdVcl0PSWjjNEzmQxjjWeMv9vLWAC1zhS8gcpk/LyDIFWojJBzhASD8f1mLv2ZdKZtA1ZQ== dependencies: - "@sentry/types" "5.11.0" - "@sentry/utils" "5.11.1" + "@sentry/types" "5.26.0" + "@sentry/utils" "5.26.0" + localforage "1.8.1" tslib "^1.9.3" -"@sentry/minimal@5.11.1": - version "5.11.1" - resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.11.1.tgz#0e705d01a567282d8fbbda2aed848b4974cc3cec" - integrity sha512-HK8zs7Pgdq7DsbZQTThrhQPrJsVWzz7MaluAbQA0rTIAJ3TvHKQpsVRu17xDpjZXypqWcKCRsthDrC4LxDM1Bg== +"@sentry/minimal@5.26.0": + version "5.26.0" + resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.26.0.tgz#851dea3644153ed3ac4837fa8ed5661d94e7a313" + integrity sha512-mdFo3FYaI1W3KEd8EHATYx8mDOZIxeoUhcBLlH7Iej6rKvdM7p8GoECrmHPU1l6sCCPtBuz66QT5YeXc7WILsA== dependencies: - "@sentry/hub" "5.11.1" - "@sentry/types" "5.11.0" + "@sentry/hub" "5.26.0" + "@sentry/types" "5.26.0" tslib "^1.9.3" -"@sentry/types@5.11.0": - version "5.11.0" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.11.0.tgz#40f0f3174362928e033ddd9725d55e7c5cb7c5b6" - integrity sha512-1Uhycpmeo1ZK2GLvrtwZhTwIodJHcyIS6bn+t4IMkN9MFoo6ktbAfhvexBDW/IDtdLlCGJbfm8nIZerxy0QUpg== +"@sentry/types@5.26.0": + version "5.26.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.26.0.tgz#b0cbacb0b24cd86620fb296b46cf7277bb004a3e" + integrity sha512-ugpa1ePOhK55pjsyutAsa2tiJVQEyGYCaOXzaheg/3+EvhMdoW+owiZ8wupfvPhtZFIU3+FPOVz0d5k9K5d1rw== -"@sentry/utils@5.11.1": - version "5.11.1" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.11.1.tgz#aa19fcc234cf632257b2281261651d2fac967607" - integrity sha512-O0Zl4R2JJh8cTkQ8ZL2cDqGCmQdpA5VeXpuBbEl1v78LQPkBDISi35wH4mKmLwMsLBtTVpx2UeUHBj0KO5aLlA== +"@sentry/utils@5.26.0": + version "5.26.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.26.0.tgz#09a3d01d91747f38f796cafeb24f8fd86e4fa05f" + integrity sha512-F2gnHIAWbjiowcAgxz3VpKxY/NQ39NTujEd/NPnRTWlRynLFg3bAV+UvZFXljhYJeN3b/zRlScNDcpCWTrtZGw== dependencies: - "@sentry/types" "5.11.0" + "@sentry/types" "5.26.0" tslib "^1.9.3" "@sindresorhus/is@^0.14.0": @@ -3633,6 +3633,13 @@ agent-base@4, agent-base@^4.2.0: dependencies: es6-promisify "^5.0.0" +agent-base@6: + version "6.0.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.1.tgz#808007e4e5867decb0ab6ab2f928fbdb5a596db4" + integrity sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg== + dependencies: + debug "4" + agent-base@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" @@ -12195,11 +12202,6 @@ fs-constants@^1.0.0: resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== -fs-copy-file-sync@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/fs-copy-file-sync/-/fs-copy-file-sync-1.1.1.tgz#11bf32c096c10d126e5f6b36d06eece776062918" - integrity sha512-2QY5eeqVv4m2PfyMiEuy9adxNP+ajf+8AR05cEi+OAzPcOj90hvFImeZhTmKLBgSd9EvG33jsD7ZRxsx9dThkQ== - fs-extra@6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-6.0.1.tgz#8abc128f7946e310135ddc93b98bddb410e7a34b" @@ -13894,6 +13896,14 @@ https-proxy-agent@3.0.0, https-proxy-agent@^3.0.0: agent-base "^4.3.0" debug "^3.1.0" +https-proxy-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz#e2a90542abb68a762e0a0850f6c9edadfd8506b2" + integrity sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA== + dependencies: + agent-base "6" + debug "4" + human-standard-collectible-abi@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/human-standard-collectible-abi/-/human-standard-collectible-abi-1.0.2.tgz#077bae9ed1b0b0b82bc46932104b4b499c941aa0" @@ -17269,6 +17279,13 @@ libp2p@~0.25.3: peer-info "^0.15.1" superstruct "^0.6.0" +lie@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e" + integrity sha1-mkNrLMd0bKWd56QfpGmz77dr2H4= + dependencies: + immediate "~3.0.5" + lie@~3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a" @@ -17382,6 +17399,13 @@ locale-currency@0.0.1: resolved "https://registry.yarnpkg.com/locale-currency/-/locale-currency-0.0.1.tgz#c9e15a22ff575b4b4bb947a4bf92ac236bd1fe9b" integrity sha1-yeFaIv9XW0tLuUekv5KsI2vR/ps= +localforage@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/localforage/-/localforage-1.8.1.tgz#f6c0a24b41ab33b10e4dc84342dd696f6f3e3433" + integrity sha512-azSSJJfc7h4bVpi0PGi+SmLQKJl2/8NErI+LhJsrORNikMZnhaQ7rv9fHj+ofwgSHrKRlsDCL/639a6nECIKuQ== + dependencies: + lie "3.1.1" + localstorage-down@^0.6.7: version "0.6.7" resolved "https://registry.yarnpkg.com/localstorage-down/-/localstorage-down-0.6.7.tgz#d0799a93b31e6c5fa5188ec06242eb1cce9d6d15" @@ -18557,7 +18581,7 @@ mkdirp-promise@^5.0.1: dependencies: mkdirp "*" -mkdirp@*, mkdirp@0.5.5, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.4, mkdirp@~0.5.1: +mkdirp@*, mkdirp@0.5.5, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.4, mkdirp@^0.5.5, mkdirp@~0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -19091,7 +19115,7 @@ node-fetch@^1.0.1, node-fetch@~1.7.1: encoding "^0.1.11" is-stream "^1.0.1" -node-fetch@^2.1.2, node-fetch@^2.3.0, node-fetch@^2.6.0, node-fetch@^2.6.1: +node-fetch@^2.3.0, node-fetch@^2.6.0, node-fetch@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== @@ -21384,16 +21408,16 @@ process@~0.5.1: resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" integrity sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8= -progress@2.0.0, progress@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" - integrity sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8= - progress@^1.1.8: version "1.1.8" resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" integrity sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74= +progress@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" + integrity sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8= + progress@^2.0.1, progress@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" @@ -21577,6 +21601,11 @@ proxy-from-env@^1.0.0: resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.0.0.tgz#33c50398f70ea7eb96d21f7b817630a55791c7ee" integrity sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4= +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + proxyquire@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/proxyquire/-/proxyquire-2.1.3.tgz#2049a7eefa10a9a953346a18e54aab2b4268df39"