1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-22 01:47:00 +01:00

Capture exceptions (#20562)

This commit is contained in:
Daniel 2023-08-29 15:15:33 +02:00 committed by GitHub
parent 4e14e179c8
commit bf1c087275
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 42 additions and 6 deletions

View File

@ -1,10 +1,11 @@
import { Web3Provider } from '@ethersproject/providers'; import { Web3Provider } from '@ethersproject/providers';
import { Contract } from '@ethersproject/contracts'; import { Contract } from '@ethersproject/contracts';
import log from 'loglevel';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import { ObservableStore } from '@metamask/obs-store'; import { ObservableStore } from '@metamask/obs-store';
import { mapValues, cloneDeep } from 'lodash'; import { mapValues, cloneDeep } from 'lodash';
import abi from 'human-standard-token-abi'; import abi from 'human-standard-token-abi';
import { captureException } from '@sentry/browser';
import { import {
decGWEIToHexWEI, decGWEIToHexWEI,
sumHexes, sumHexes,
@ -18,6 +19,11 @@ import {
} from '../../../shared/constants/swaps'; } from '../../../shared/constants/swaps';
import { GasEstimateTypes } from '../../../shared/constants/gas'; import { GasEstimateTypes } from '../../../shared/constants/gas';
import { CHAIN_IDS, NetworkStatus } from '../../../shared/constants/network'; import { CHAIN_IDS, NetworkStatus } from '../../../shared/constants/network';
import {
MetaMetricsEventCategory,
MetaMetricsEventName,
MetaMetricsEventErrorType,
} from '../../../shared/constants/metametrics';
import { import {
FALLBACK_SMART_TRANSACTIONS_REFRESH_TIME, FALLBACK_SMART_TRANSACTIONS_REFRESH_TIME,
FALLBACK_SMART_TRANSACTIONS_DEADLINE, FALLBACK_SMART_TRANSACTIONS_DEADLINE,
@ -115,6 +121,7 @@ export default class SwapsController {
getCurrentChainId, getCurrentChainId,
getEIP1559GasFeeEstimates, getEIP1559GasFeeEstimates,
onNetworkStateChange, onNetworkStateChange,
trackMetaMetricsEvent,
}, },
state, state,
) { ) {
@ -140,6 +147,7 @@ export default class SwapsController {
this.getBufferedGasLimit = getBufferedGasLimit; this.getBufferedGasLimit = getBufferedGasLimit;
this.getTokenRatesState = getTokenRatesState; this.getTokenRatesState = getTokenRatesState;
this.trackMetaMetricsEvent = trackMetaMetricsEvent;
this.pollCount = 0; this.pollCount = 0;
this.getProviderConfig = getProviderConfig; this.getProviderConfig = getProviderConfig;
@ -362,6 +370,7 @@ export default class SwapsController {
} else if (!isPolledRequest) { } else if (!isPolledRequest) {
const { gasLimit: approvalGas } = await this.timedoutGasReturn( const { gasLimit: approvalGas } = await this.timedoutGasReturn(
firstQuote.approvalNeeded, firstQuote.approvalNeeded,
firstQuote.aggregator,
); );
newQuotes = mapValues(newQuotes, (quote) => ({ newQuotes = mapValues(newQuotes, (quote) => ({
@ -463,6 +472,7 @@ export default class SwapsController {
Object.values(quotes).map(async (quote) => { Object.values(quotes).map(async (quote) => {
const { gasLimit, simulationFails } = await this.timedoutGasReturn( const { gasLimit, simulationFails } = await this.timedoutGasReturn(
quote.trade, quote.trade,
quote.aggregator,
); );
return [gasLimit, simulationFails, quote.aggregator]; return [gasLimit, simulationFails, quote.aggregator];
}), }),
@ -492,13 +502,24 @@ export default class SwapsController {
return newQuotes; return newQuotes;
} }
timedoutGasReturn(tradeTxParams) { timedoutGasReturn(tradeTxParams, aggregator = '') {
return new Promise((resolve) => { return new Promise((resolve) => {
let gasTimedOut = false; let gasTimedOut = false;
const gasTimeout = setTimeout(() => { const gasTimeout = setTimeout(() => {
gasTimedOut = true; gasTimedOut = true;
resolve({ gasLimit: null, simulationFails: true }); this.trackMetaMetricsEvent({
event: MetaMetricsEventName.QuoteError,
category: MetaMetricsEventCategory.Swaps,
properties: {
error_type: MetaMetricsEventErrorType.GasTimeout,
aggregator,
},
});
resolve({
gasLimit: null,
simulationFails: true,
});
}, SECOND * 5); }, SECOND * 5);
// Remove gas from params that will be passed to the `estimateGas` call // Remove gas from params that will be passed to the `estimateGas` call
@ -519,7 +540,11 @@ export default class SwapsController {
} }
}) })
.catch((e) => { .catch((e) => {
log.error(e); captureException(e, {
extra: {
aggregator,
},
});
if (!gasTimedOut) { if (!gasTimedOut) {
clearTimeout(gasTimeout); clearTimeout(gasTimeout);
resolve({ gasLimit: null, simulationFails: true }); resolve({ gasLimit: null, simulationFails: true });
@ -534,7 +559,10 @@ export default class SwapsController {
const quoteToUpdate = { ...swapsState.quotes[initialAggId] }; const quoteToUpdate = { ...swapsState.quotes[initialAggId] };
const { gasLimit: newGasEstimate, simulationFails } = const { gasLimit: newGasEstimate, simulationFails } =
await this.timedoutGasReturn(quoteToUpdate.trade); await this.timedoutGasReturn(
quoteToUpdate.trade,
quoteToUpdate.aggregator,
);
if (newGasEstimate && !simulationFails) { if (newGasEstimate && !simulationFails) {
const gasEstimateWithRefund = calculateGasEstimateWithRefund( const gasEstimateWithRefund = calculateGasEstimateWithRefund(

View File

@ -860,7 +860,10 @@ describe('SwapsController', function () {
// Mocked quotes approvalNeeded is null, so it will only be called with the gas // Mocked quotes approvalNeeded is null, so it will only be called with the gas
assert.strictEqual( assert.strictEqual(
timedoutGasReturnStub.calledOnceWithExactly(MOCK_APPROVAL_NEEDED), timedoutGasReturnStub.calledOnceWithExactly(
MOCK_APPROVAL_NEEDED,
TEST_AGG_ID_APPROVAL,
),
true, true,
); );
}); });

View File

@ -1445,6 +1445,9 @@ export default class MetamaskController extends EventEmitter {
this.gasFeeController.fetchGasFeeEstimates.bind( this.gasFeeController.fetchGasFeeEstimates.bind(
this.gasFeeController, this.gasFeeController,
), ),
trackMetaMetricsEvent: this.metaMetricsController.trackEvent.bind(
this.metaMetricsController,
),
}, },
initState.SwapsController, initState.SwapsController,
); );

View File

@ -550,6 +550,7 @@ export enum MetaMetricsEventName {
PortfolioLinkClicked = 'Portfolio Link Clicked', PortfolioLinkClicked = 'Portfolio Link Clicked',
ProviderMethodCalled = 'Provider Method Called', ProviderMethodCalled = 'Provider Method Called',
PublicAddressCopied = 'Public Address Copied', PublicAddressCopied = 'Public Address Copied',
QuoteError = 'Quote Error',
ServiceWorkerRestarted = 'Service Worker Restarted', ServiceWorkerRestarted = 'Service Worker Restarted',
SignatureApproved = 'Signature Approved', SignatureApproved = 'Signature Approved',
SignatureFailed = 'Signature Failed', SignatureFailed = 'Signature Failed',
@ -690,6 +691,7 @@ export enum MetaMetricsEventKeyType {
export enum MetaMetricsEventErrorType { export enum MetaMetricsEventErrorType {
InsufficientGas = 'insufficient_gas', InsufficientGas = 'insufficient_gas',
GasTimeout = 'gas_timeout',
} }
export enum MetaMetricsNetworkEventSource { export enum MetaMetricsNetworkEventSource {