From e0eb84adc8b5eed201bd04c1e244778b5175313e Mon Sep 17 00:00:00 2001 From: Chid Gilovitz Date: Mon, 13 Nov 2023 11:35:01 +0800 Subject: [PATCH] Some more sentry noise fixes (#1151) * chore: add regex patterns for errors to ignore in sentry config * fix: handle unhandled promise rejection in substrate connections * fix: revert last and make throwAfter reject with a real Error object * fix: catch and emit error in websocket connection, when response is not JSON * chore: changeset * fix: handle error states arising from change to throwAfter function * fix: improve error handling in Websocket * chore: changeset --- .changeset/long-toys-act.md | 5 +++++ .changeset/quiet-papayas-cheat.md | 6 ++++++ apps/extension/src/core/config/sentry.ts | 4 ++++ .../src/core/domains/ethereum/handler.tabs.ts | 1 + .../transactions/watchEthereumTransaction.ts | 2 ++ .../src/ui/hooks/ledger/useLedgerEthereum.ts | 1 + packages/chain-connector/src/Websocket.ts | 13 ++++++++----- packages/util/src/throwAfter.ts | 2 +- 8 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 .changeset/long-toys-act.md create mode 100644 .changeset/quiet-papayas-cheat.md diff --git a/.changeset/long-toys-act.md b/.changeset/long-toys-act.md new file mode 100644 index 0000000000..4ca3635e0e --- /dev/null +++ b/.changeset/long-toys-act.md @@ -0,0 +1,5 @@ +--- +"@talismn/chain-connector": patch +--- + +Improved error handling in Websocket connector diff --git a/.changeset/quiet-papayas-cheat.md b/.changeset/quiet-papayas-cheat.md new file mode 100644 index 0000000000..92db0c3a8e --- /dev/null +++ b/.changeset/quiet-papayas-cheat.md @@ -0,0 +1,6 @@ +--- +"@talismn/chain-connector": patch +"@talismn/util": patch +--- + +Error handling improvements diff --git a/apps/extension/src/core/config/sentry.ts b/apps/extension/src/core/config/sentry.ts index 9f3e7d0582..33c883b3d1 100644 --- a/apps/extension/src/core/config/sentry.ts +++ b/apps/extension/src/core/config/sentry.ts @@ -22,6 +22,10 @@ export const initSentry = (sentry: typeof SentryBrowser | typeof SentryReact) => release: process.env.RELEASE, sampleRate: 1, maxBreadcrumbs: 20, + ignoreErrors: [ + /(No window with id: )(\d+).?/, + /(disconnected from wss)[(]?:\/\/[\w./:-]+: \d+:: Normal Closure[)]?/, + ], // prevents sending the event if user has disabled error tracking beforeSend: async (event) => ((await firstValueFrom(useErrorTracking)) ? event : null), // eslint-disable-next-line @typescript-eslint/no-unused-vars diff --git a/apps/extension/src/core/domains/ethereum/handler.tabs.ts b/apps/extension/src/core/domains/ethereum/handler.tabs.ts index ab7f563845..56e1a049b3 100644 --- a/apps/extension/src/core/domains/ethereum/handler.tabs.ts +++ b/apps/extension/src/core/domains/ethereum/handler.tabs.ts @@ -337,6 +337,7 @@ export class EthTabsHandler extends TabsHandler { client.request({ method: "eth_chainId" }), throwAfter(10_000, "timeout"), // 10 sec timeout ]) + assert(!!rpcChainIdHex, `No chainId returned for ${rpcUrl}`) const rpcChainId = hexToNumber(rpcChainIdHex) assert(rpcChainId === chainId, "chainId mismatch") diff --git a/apps/extension/src/core/domains/transactions/watchEthereumTransaction.ts b/apps/extension/src/core/domains/transactions/watchEthereumTransaction.ts index 74df0264ae..8454a2bba4 100644 --- a/apps/extension/src/core/domains/transactions/watchEthereumTransaction.ts +++ b/apps/extension/src/core/domains/transactions/watchEthereumTransaction.ts @@ -4,6 +4,7 @@ import { log } from "@core/log" import { createNotification } from "@core/notifications" import { chainConnectorEvm } from "@core/rpcs/chain-connector-evm" import { chaindataProvider } from "@core/rpcs/chaindata" +import { assert } from "@polkadot/util" import * as Sentry from "@sentry/browser" import { EvmNetworkId } from "@talismn/chaindata-provider" import { sleep, throwAfter } from "@talismn/util" @@ -57,6 +58,7 @@ export const watchEthereumTransaction = async ( throwAfter(5 * 60_000, "Transaction not found"), ]) + assert(receipt, "Transaction to watch not found") // check hash which may be incorrect for cancelled tx, in which case receipt includes the replacement tx hash if (receipt.transactionHash === hash) { // to test failing transactions, swap on busy AMM pools with a 0.05% slippage limit diff --git a/apps/extension/src/ui/hooks/ledger/useLedgerEthereum.ts b/apps/extension/src/ui/hooks/ledger/useLedgerEthereum.ts index 7cbc40910d..b3ad363599 100644 --- a/apps/extension/src/ui/hooks/ledger/useLedgerEthereum.ts +++ b/apps/extension/src/ui/hooks/ledger/useLedgerEthereum.ts @@ -53,6 +53,7 @@ export const useLedgerEthereum = (persist = false) => { ledger.getAddress(getEthLedgerDerivationPath("LedgerLive")), throwAfter(5_000, "Timeout"), ]) + const { version } = await ledger.getAppConfiguration() if (!gte(version, LEDGER_ETHEREUM_MIN_VERSION)) throw new LedgerError("Unsupported version", "UnsupportedVersion") diff --git a/packages/chain-connector/src/Websocket.ts b/packages/chain-connector/src/Websocket.ts index 0c2aae812d..d72739daa0 100644 --- a/packages/chain-connector/src/Websocket.ts +++ b/packages/chain-connector/src/Websocket.ts @@ -460,12 +460,15 @@ export class Websocket implements ProviderInterface { #onSocketMessage = (message: MessageEvent): void => { // log.debug(() => ["received", message.data]) + try { + const response = JSON.parse(message.data) as UnknownJsonRpcResponse - const response = JSON.parse(message.data) as UnknownJsonRpcResponse - - return isUndefined(response.method) - ? this.#onSocketMessageResult(response) - : this.#onSocketMessageSubscribe(response) + return isUndefined(response.method) + ? this.#onSocketMessageResult(response) + : this.#onSocketMessageSubscribe(response) + } catch (e) { + this.#emit("error", new Error("Invalid websocket message received", { cause: e })) + } } #onSocketMessageResult = (response: UnknownJsonRpcResponse): void => { diff --git a/packages/util/src/throwAfter.ts b/packages/util/src/throwAfter.ts index 8e97741f9c..a21b8a2412 100644 --- a/packages/util/src/throwAfter.ts +++ b/packages/util/src/throwAfter.ts @@ -1,2 +1,2 @@ export const throwAfter = (ms: number, reason: string) => - new Promise((_, reject) => setTimeout(() => reject(reason), ms)) + new Promise((_, reject) => setTimeout(() => reject(new Error(reason)), ms))