diff --git a/packages/stellar-wallet-snap/src/handlers/clientRequest/confirmSend.test.ts b/packages/stellar-wallet-snap/src/handlers/clientRequest/confirmSend.test.ts index 08bf5b91..b1dd3435 100644 --- a/packages/stellar-wallet-snap/src/handlers/clientRequest/confirmSend.test.ts +++ b/packages/stellar-wallet-snap/src/handlers/clientRequest/confirmSend.test.ts @@ -49,6 +49,7 @@ import { WalletService } from '../../services/wallet'; import { getTestWallet } from '../../services/wallet/__mocks__/wallet.fixtures'; import { ConfirmationInterfaceKey } from '../../ui/confirmation/api'; import { ConfirmationUXController } from '../../ui/confirmation/controller'; +import * as errorsUtils from '../../utils/errors'; import { logger } from '../../utils/logger'; import * as snapUtils from '../../utils/snap'; import { AccountResolver } from '../accountResolver'; @@ -543,7 +544,7 @@ describe('ConfirmSendHandler', () => { ); createValidatedSendTransaction.mockRejectedValueOnce(xdrParseError); const trackErrorSpy = jest - .spyOn(snapUtils, 'trackError') + .spyOn(errorsUtils, 'trackError') .mockResolvedValue(undefined); expect(await handler.handle(baseRequest())).toStrictEqual({ @@ -558,7 +559,7 @@ describe('ConfirmSendHandler', () => { const unexpectedError = new Error('unexpected'); createValidatedSendTransaction.mockRejectedValueOnce(unexpectedError); const trackErrorSpy = jest - .spyOn(snapUtils, 'trackError') + .spyOn(errorsUtils, 'trackError') .mockResolvedValue(undefined); expect(await handler.handle(baseRequest())).toStrictEqual({ @@ -574,7 +575,7 @@ describe('ConfirmSendHandler', () => { new TransactionValidationException('x'), ); const trackErrorSpy = jest - .spyOn(snapUtils, 'trackError') + .spyOn(errorsUtils, 'trackError') .mockResolvedValue(undefined); expect(await handler.handle(baseRequest())).toStrictEqual({ diff --git a/packages/stellar-wallet-snap/src/handlers/keyring/base.ts b/packages/stellar-wallet-snap/src/handlers/keyring/base.ts index f701bcbc..6650a5cb 100644 --- a/packages/stellar-wallet-snap/src/handlers/keyring/base.ts +++ b/packages/stellar-wallet-snap/src/handlers/keyring/base.ts @@ -3,8 +3,8 @@ import type { Struct } from '@metamask/superstruct'; import type { Json } from '@metamask/utils'; import type { KnownCaip2ChainId } from '../../api'; +import { trackError } from '../../utils/errors'; import { validateRequest, validateResponse } from '../../utils/requestResponse'; -import { trackError } from '../../utils/snap'; import type { AccountResolver, ResolvedKeyringAndWalletOnly, diff --git a/packages/stellar-wallet-snap/src/services/on-chain-account/OnChainAccountSynchronizeService.test.ts b/packages/stellar-wallet-snap/src/services/on-chain-account/OnChainAccountSynchronizeService.test.ts index 1bfc3592..26f1efa8 100644 --- a/packages/stellar-wallet-snap/src/services/on-chain-account/OnChainAccountSynchronizeService.test.ts +++ b/packages/stellar-wallet-snap/src/services/on-chain-account/OnChainAccountSynchronizeService.test.ts @@ -10,8 +10,8 @@ import type { KnownCaip19Sep41AssetId } from '../../api'; import { KnownCaip2ChainId } from '../../api'; import { NATIVE_ASSET_SYMBOL, STELLAR_DECIMAL_PLACES } from '../../constants'; import { bufferToUint8Array } from '../../utils/buffer'; +import * as errorsUtils from '../../utils/errors'; import { logger } from '../../utils/logger'; -import * as snapUtils from '../../utils/snap'; import type { StellarKeyringAccount } from '../account'; import { generateStellarKeyringAccount } from '../account/__mocks__/account.fixtures'; import { @@ -200,7 +200,7 @@ describe('OnChainAccountSynchronizeService', () => { const setupTest = () => { jest.mocked(emitSnapKeyringEvent).mockResolvedValue(undefined); - jest.spyOn(snapUtils, 'trackError').mockResolvedValue(undefined); + jest.spyOn(errorsUtils, 'trackError').mockResolvedValue(undefined); }; const buildActivatedAccountPair = ( @@ -974,7 +974,7 @@ describe('OnChainAccountSynchronizeService', () => { mockSep41Assets, ); - expect(snapUtils.trackError).toHaveBeenCalledWith( + expect(errorsUtils.trackError).toHaveBeenCalledWith( expect.objectContaining({ message: 'sep41 fetch temporarily unavailable', }), @@ -1144,7 +1144,7 @@ describe('OnChainAccountSynchronizeService', () => { ); expect(saveManySpy).toHaveBeenCalled(); - expect(snapUtils.trackError).toHaveBeenCalledWith(emitError); + expect(errorsUtils.trackError).toHaveBeenCalledWith(emitError); expect(logger.warn).toHaveBeenCalledWith( '[💼 OnChainAccountSynchronizeService]', 'Failed to emit keyring events after synchronize', diff --git a/packages/stellar-wallet-snap/src/utils/__mocks__/snap.ts b/packages/stellar-wallet-snap/src/utils/__mocks__/snap.ts index 77705e26..c4a9be6c 100644 --- a/packages/stellar-wallet-snap/src/utils/__mocks__/snap.ts +++ b/packages/stellar-wallet-snap/src/utils/__mocks__/snap.ts @@ -35,5 +35,4 @@ export const { trackTransactionFinalized, trackSecurityAlertDetected, trackSecurityScanCompleted, - trackError, } = actual; diff --git a/packages/stellar-wallet-snap/src/utils/errors.ts b/packages/stellar-wallet-snap/src/utils/errors.ts index 622340f7..9e878ef0 100644 --- a/packages/stellar-wallet-snap/src/utils/errors.ts +++ b/packages/stellar-wallet-snap/src/utils/errors.ts @@ -1,9 +1,9 @@ -import { createWithCatchAndThrowSnapError } from '@metamask/snap-networks-utils'; +import { createSnapErrorHandling } from '@metamask/snap-networks-utils'; import type { Struct } from '@metamask/superstruct'; import { assert, enums, object, type } from '@metamask/superstruct'; import { logger } from './logger'; -import { trackError } from './snap'; +import { getSnapProvider } from './snap'; export { isSnapRpcError } from '@metamask/snap-networks-utils'; export type { SnapRpcError } from '@metamask/snap-networks-utils'; @@ -252,7 +252,8 @@ export function isStellarSnapException( return error instanceof StellarSnapException; } -export const withCatchAndThrowSnapError = createWithCatchAndThrowSnapError({ - logError: logger.error.bind(logger), - trackError, -}); +export const { trackError, withCatchAndThrowSnapError } = + createSnapErrorHandling({ + getSnapProvider, + logError: logger.error.bind(logger), + }); diff --git a/packages/stellar-wallet-snap/src/utils/snap.ts b/packages/stellar-wallet-snap/src/utils/snap.ts index 22f1d477..8e1e3b01 100644 --- a/packages/stellar-wallet-snap/src/utils/snap.ts +++ b/packages/stellar-wallet-snap/src/utils/snap.ts @@ -1,8 +1,7 @@ import type { JsonSLIP10Node } from '@metamask/key-tree'; import type { EntropySourceId } from '@metamask/keyring-api'; -import { deserialize, serialize } from '@metamask/snap-networks-utils'; import type { Serializable } from '@metamask/snap-networks-utils'; -import { getJsonError, UserRejectedRequestError } from '@metamask/snaps-sdk'; +import { deserialize, serialize } from '@metamask/snap-networks-utils'; import type { ComponentOrElement, DialogResult, @@ -14,7 +13,6 @@ import type { SnapsProvider, UpdateInterfaceResult, } from '@metamask/snaps-sdk'; -import { ensureError } from '@metamask/utils'; import { StellarSnapException } from './errors'; import { logger } from './logger'; @@ -631,36 +629,3 @@ export async function trackSecurityScanCompleted(properties: { has_security_alerts: properties.hasSecurityAlerts, }); } - -/** - * Track an error in MetaMask via Sentry (`snap_trackError`). - * - * RPC failures are caught and logged but never rethrown, so this is - * safe to call from already-failing error-handling paths without risk - * of masking the original failure. - * - * @param error - The error to report to Sentry. - * @returns The Sentry event ID on success, or `undefined` on failure or if the error is skipped. - */ -export async function trackError( - error: Error | unknown, -): Promise { - if (error instanceof UserRejectedRequestError) { - return undefined; - } - - try { - let errorToTrack = error; - - if (!(error instanceof Error)) { - errorToTrack = ensureError(error); - } - return await getSnapProvider().request({ - method: 'snap_trackError', - params: { error: getJsonError(errorToTrack) }, - }); - } catch (rpcError) { - logger.warn({ rpcError }, 'Failed to track error via snap_trackError'); - return undefined; - } -}