diff --git a/packages/snaps-utils/coverage.json b/packages/snaps-utils/coverage.json index 36a5b2b72a..c2971ffb2f 100644 --- a/packages/snaps-utils/coverage.json +++ b/packages/snaps-utils/coverage.json @@ -2,5 +2,5 @@ "branches": 99.76, "functions": 99.02, "lines": 98.66, - "statements": 97.25 + "statements": 97.26 } diff --git a/packages/snaps-utils/src/errors.test.ts b/packages/snaps-utils/src/errors.test.ts index 177e708bf2..e9eca22d14 100644 --- a/packages/snaps-utils/src/errors.test.ts +++ b/packages/snaps-utils/src/errors.test.ts @@ -277,4 +277,36 @@ describe('unwrapError', () => { expect(unwrappedError.stack).toBeDefined(); expect(handled).toBe(false); }); + + it('unwraps double wrapped JSON-RPC errors', () => { + const error = new JsonRpcError(-31001, 'Wrapped Snap Error', { + cause: { + code: -32603, + message: 'Invalid URL: Unable to parse URL.', + data: { + cause: { + message: 'Invalid URL: Unable to parse URL.', + stack: `Error: Invalid URL: Unable to parse URL. + at validateLink (chrome-extension://oghgfmogdanabdcdccbeoodiboikbejn/common-4.js:11793:15) + at chrome-extension://oghgfmogdanabdcdccbeoodiboikbejn/common-4.js:11842:17 + at walkJsx (chrome-extension://oghgfmogdanabdcdccbeoodiboikbejn/common-4.js:11936:20) + at walkJsx (chrome-extension://oghgfmogdanabdcdccbeoodiboikbejn/common-4.js:11946:37) + at validateJsxElements (chrome-extension://oghgfmogdanabdcdccbeoodiboikbejn/common-4.js:11839:5) + at SnapInterfaceController._SnapInterfaceController_validateContent (chrome-extension://oghgfmogdanabdcdccbeoodiboikbejn/background-5.js:21741:43) + at SnapInterfaceController.createInterface (chrome-extension://oghgfmogdanabdcdccbeoodiboikbejn/background-5.js:21585:127) + at Messenger.call (chrome-extension://oghgfmogdanabdcdccbeoodiboikbejn/common-1.js:14706:16) + at dialogImplementation (chrome-extension://oghgfmogdanabdcdccbeoodiboikbejn/common-4.js:1988:30) + at PermissionController._executeRestrictedMethod (chrome-extension://oghgfmogdanabdcdccbeoodiboikbejn/common-3.js:23611:111)`, + }, + }, + }, + }); + + const [unwrappedError, handled] = unwrapError(error); + expect(handled).toBe(false); + expect(unwrappedError.message).toBe('Invalid URL: Unable to parse URL.'); + expect(unwrappedError.stack).toStrictEqual( + expect.stringContaining('PermissionController._executeRestrictedMethod'), + ); + }); }); diff --git a/packages/snaps-utils/src/errors.ts b/packages/snaps-utils/src/errors.ts index 7c647c4e8b..529ea10802 100644 --- a/packages/snaps-utils/src/errors.ts +++ b/packages/snaps-utils/src/errors.ts @@ -197,6 +197,20 @@ export function unwrapError( return [getJsonRpcError(code, message, stack, data), true]; } + // If the JSON-RPC error is double wrapped, unwrap it further to provide the stack. + if ( + isObject(error.data.cause.data) && + isObject(error.data.cause.data.cause) && + error.data.cause.message === error.data.cause.data.cause.message + ) { + const nestedCause = error.data.cause.data.cause; + const { code, message } = error.data.cause; + return [ + getJsonRpcError(code, message, getErrorStack(nestedCause)), + false, + ]; + } + // Otherwise, we use the original JSON-RPC error. const { code, message, stack, data } = error.data.cause; return [getJsonRpcError(code, message, stack, data), false];