diff --git a/.yarn/patches/@metamask-rpc-methods-npm-0.38.1-flask.1-081e1eb5b3.patch b/.yarn/patches/@metamask-rpc-methods-npm-0.38.1-flask.1-081e1eb5b3.patch new file mode 100644 index 0000000000..01ab02aa93 --- /dev/null +++ b/.yarn/patches/@metamask-rpc-methods-npm-0.38.1-flask.1-081e1eb5b3.patch @@ -0,0 +1,19 @@ +diff --git a/dist/types/restricted/getLocale.d.ts b/dist/types/restricted/getLocale.d.ts +index 2941d2733042664c341776c7bc840ba0813994ca..0188bbd4de0cd013159a36b736ad9baf94c18c92 100644 +--- a/dist/types/restricted/getLocale.d.ts ++++ b/dist/types/restricted/getLocale.d.ts +@@ -1,6 +1,6 @@ + import type { PermissionSpecificationBuilder, ValidPermissionSpecification, RestrictedMethodOptions } from '@metamask/permission-controller'; + import { PermissionType } from '@metamask/permission-controller'; +-import type { NonEmptyArray } from '@metamask/utils'; ++import type { Json, NonEmptyArray } from '@metamask/utils'; + import type { MethodHooksObject } from '../utils'; + declare const methodName = "snap_getLocale"; + export declare type GetLocaleMethodHooks = { +@@ -43,5 +43,5 @@ export declare const getLocaleBuilder: Readonly<{ + * @param hooks.getLocale - A function that returns the user selected locale. + * @returns The user selected locale. + */ +-export declare function getImplementation({ getLocale }: GetLocaleMethodHooks): (_args: RestrictedMethodOptions) => Promise; ++export declare function getImplementation({ getLocale }: GetLocaleMethodHooks): (_args: RestrictedMethodOptions | Json[]>) => Promise; + export {}; diff --git a/package.json b/package.json index 27d57c51f3..7432babc2a 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,10 @@ "simple-git-hooks": { "pre-push": "yarn lint" }, + "resolutions": { + "@metamask/rpc-methods@^0.38.1-flask.1": "patch:@metamask/rpc-methods@npm%3A0.38.1-flask.1#./.yarn/patches/@metamask-rpc-methods-npm-0.38.1-flask.1-081e1eb5b3.patch", + "@metamask/rpc-methods@^1.0.1": "patch:@metamask/rpc-methods@npm%3A0.38.1-flask.1#./.yarn/patches/@metamask-rpc-methods-npm-0.38.1-flask.1-081e1eb5b3.patch" + }, "devDependencies": { "@lavamoat/allow-scripts": "^2.3.1", "@metamask/create-release-branch": "^1.1.0", @@ -40,7 +44,7 @@ "@metamask/eslint-config-nodejs": "^12.0.0", "@metamask/eslint-config-typescript": "^12.0.0", "@metamask/eth-json-rpc-provider": "^1.0.0", - "@metamask/utils": "^6.2.0", + "@metamask/utils": "^8.1.0", "@types/node": "^16.18.24", "@typescript-eslint/eslint-plugin": "^5.30.7", "@typescript-eslint/parser": "^5.30.7", diff --git a/packages/accounts-controller/package.json b/packages/accounts-controller/package.json index 24191d9ba3..8442387438 100644 --- a/packages/accounts-controller/package.json +++ b/packages/accounts-controller/package.json @@ -32,7 +32,7 @@ "@metamask/eth-snap-keyring": "^0.2.2", "@metamask/keyring-api": "^0.2.5", "@metamask/snaps-utils": "^1.0.1", - "@metamask/utils": "^6.2.0", + "@metamask/utils": "^8.1.0", "deepmerge": "^4.2.2", "eth-rpc-errors": "^4.0.2", "ethereumjs-util": "^7.0.10", diff --git a/packages/address-book-controller/package.json b/packages/address-book-controller/package.json index a3e4afe7d2..9364550f58 100644 --- a/packages/address-book-controller/package.json +++ b/packages/address-book-controller/package.json @@ -30,7 +30,7 @@ "dependencies": { "@metamask/base-controller": "^3.2.1", "@metamask/controller-utils": "^5.0.0", - "@metamask/utils": "^6.2.0" + "@metamask/utils": "^8.1.0" }, "devDependencies": { "@metamask/auto-changelog": "^3.1.0", diff --git a/packages/approval-controller/package.json b/packages/approval-controller/package.json index 27657d4ed4..fc1f74a4b7 100644 --- a/packages/approval-controller/package.json +++ b/packages/approval-controller/package.json @@ -29,8 +29,8 @@ }, "dependencies": { "@metamask/base-controller": "^3.2.1", - "@metamask/utils": "^6.2.0", - "eth-rpc-errors": "^4.0.2", + "@metamask/rpc-errors": "^6.0.0", + "@metamask/utils": "^8.1.0", "immer": "^9.0.6", "nanoid": "^3.1.31" }, diff --git a/packages/approval-controller/src/ApprovalController.test.ts b/packages/approval-controller/src/ApprovalController.test.ts index 94db8cbc8b..d990140615 100644 --- a/packages/approval-controller/src/ApprovalController.test.ts +++ b/packages/approval-controller/src/ApprovalController.test.ts @@ -1,7 +1,7 @@ /* eslint-disable jest/expect-expect */ import { ControllerMessenger } from '@metamask/base-controller'; -import { errorCodes, EthereumRpcError } from 'eth-rpc-errors'; +import { errorCodes, JsonRpcError } from '@metamask/rpc-errors'; import type { ApprovalControllerActions, @@ -642,7 +642,7 @@ describe('approval controller', () => { approvalController.reject('2', new Error('foo')); expect(approvalController.getTotalApprovalCount()).toBe(2); - approvalController.clear(new EthereumRpcError(1, 'clear')); + approvalController.clear(new JsonRpcError(1, 'clear')); expect(approvalController.getTotalApprovalCount()).toBe(0); }); @@ -666,7 +666,7 @@ describe('approval controller', () => { approvalController.reject('2', new Error('foo')); expect(approvalController.getTotalApprovalCount()).toBe(1); - approvalController.clear(new EthereumRpcError(1, 'clear')); + approvalController.clear(new JsonRpcError(1, 'clear')); expect(approvalController.getTotalApprovalCount()).toBe(0); }); }); @@ -1025,7 +1025,7 @@ describe('approval controller', () => { describe('clear', () => { it('does nothing if state is already empty', () => { expect(() => - approvalController.clear(new EthereumRpcError(1, 'clear')), + approvalController.clear(new JsonRpcError(1, 'clear')), ).not.toThrow(); }); @@ -1040,7 +1040,7 @@ describe('approval controller', () => { .add({ id: 'foo3', origin: 'fizz.buzz', type: 'myType' }) .catch((_error) => undefined); - approvalController.clear(new EthereumRpcError(1, 'clear')); + approvalController.clear(new JsonRpcError(1, 'clear')); expect( approvalController.state[PENDING_APPROVALS_STORE_KEY], @@ -1055,16 +1055,16 @@ describe('approval controller', () => { type: 'myType', }); - approvalController.clear(new EthereumRpcError(1000, 'foo')); + approvalController.clear(new JsonRpcError(1000, 'foo')); await expect(rejectPromise).rejects.toThrow( - new EthereumRpcError(1000, 'foo'), + new JsonRpcError(1000, 'foo'), ); }); it('does not clear approval flows', async () => { approvalController.startFlow(); - approvalController.clear(new EthereumRpcError(1, 'clear')); + approvalController.clear(new JsonRpcError(1, 'clear')); expect(approvalController.state[APPROVAL_FLOWS_STORE_KEY]).toHaveLength( 1, diff --git a/packages/approval-controller/src/ApprovalController.ts b/packages/approval-controller/src/ApprovalController.ts index 1c2096164f..4e3259e892 100644 --- a/packages/approval-controller/src/ApprovalController.ts +++ b/packages/approval-controller/src/ApprovalController.ts @@ -1,8 +1,8 @@ import type { RestrictedControllerMessenger } from '@metamask/base-controller'; import { BaseControllerV2 } from '@metamask/base-controller'; +import type { JsonRpcError, DataWithOptionalCause } from '@metamask/rpc-errors'; +import { rpcErrors } from '@metamask/rpc-errors'; import type { Json, OptionalField } from '@metamask/utils'; -import type { EthereumRpcError } from 'eth-rpc-errors'; -import { ethErrors } from 'eth-rpc-errors'; import type { Patch } from 'immer'; import { nanoid } from 'nanoid'; @@ -256,7 +256,7 @@ export type GetApprovalsState = { export type ClearApprovalRequests = { type: `${typeof controllerName}:clearRequests`; - handler: (error: EthereumRpcError) => void; + handler: (error: JsonRpcError) => void; }; export type AddApprovalRequest = { @@ -719,10 +719,10 @@ export class ApprovalController extends BaseControllerV2< /** * Rejects and deletes all approval requests. * - * @param rejectionError - The EthereumRpcError to reject the approval + * @param rejectionError - The JsonRpcError to reject the approval * requests with. */ - clear(rejectionError: EthereumRpcError): void { + clear(rejectionError: JsonRpcError): void { for (const id of this.#approvals.keys()) { this.reject(id, rejectionError); } @@ -878,7 +878,7 @@ export class ApprovalController extends BaseControllerV2< !this.#typesExcludedFromRateLimiting.includes(type) && this.has({ origin, type }) ) { - throw ethErrors.rpc.resourceUnavailable( + throw rpcErrors.resourceUnavailable( getAlreadyPendingMessage(origin, type), ); } @@ -937,7 +937,7 @@ export class ApprovalController extends BaseControllerV2< } if (errorMessage) { - throw ethErrors.rpc.internal(errorMessage); + throw rpcErrors.internal(errorMessage); } } diff --git a/packages/assets-controllers/package.json b/packages/assets-controllers/package.json index ea014ec3cb..40073f0584 100644 --- a/packages/assets-controllers/package.json +++ b/packages/assets-controllers/package.json @@ -41,8 +41,8 @@ "@metamask/metamask-eth-abis": "3.0.0", "@metamask/network-controller": "^13.0.0", "@metamask/preferences-controller": "^4.4.1", - "@metamask/rpc-errors": "^5.1.1", - "@metamask/utils": "^6.2.0", + "@metamask/rpc-errors": "^6.0.0", + "@metamask/utils": "^8.1.0", "@types/uuid": "^8.3.0", "async-mutex": "^0.2.6", "ethereumjs-util": "^7.0.10", diff --git a/packages/base-controller/package.json b/packages/base-controller/package.json index 9d67bb3ff5..82c07cfc0a 100644 --- a/packages/base-controller/package.json +++ b/packages/base-controller/package.json @@ -28,7 +28,7 @@ "test:watch": "jest --watch" }, "dependencies": { - "@metamask/utils": "^6.2.0", + "@metamask/utils": "^8.1.0", "immer": "^9.0.6" }, "devDependencies": { diff --git a/packages/controller-utils/package.json b/packages/controller-utils/package.json index 6090468771..33c48d0b00 100644 --- a/packages/controller-utils/package.json +++ b/packages/controller-utils/package.json @@ -29,10 +29,9 @@ }, "dependencies": { "@metamask/eth-query": "^3.0.1", - "@metamask/utils": "^6.2.0", + "@metamask/utils": "^8.1.0", "@spruceid/siwe-parser": "1.1.3", "eth-ens-namehash": "^2.0.8", - "eth-rpc-errors": "^4.0.2", "ethereumjs-util": "^7.0.10", "ethjs-unit": "^0.1.6", "fast-deep-equal": "^3.1.3" diff --git a/packages/ens-controller/package.json b/packages/ens-controller/package.json index 3edbe15d70..4f72422a7e 100644 --- a/packages/ens-controller/package.json +++ b/packages/ens-controller/package.json @@ -32,7 +32,7 @@ "@metamask/base-controller": "^3.2.1", "@metamask/controller-utils": "^5.0.0", "@metamask/network-controller": "^13.0.0", - "@metamask/utils": "^6.2.0", + "@metamask/utils": "^8.1.0", "ethereum-ens-network-map": "^1.0.2", "punycode": "^2.1.1" }, diff --git a/packages/gas-fee-controller/package.json b/packages/gas-fee-controller/package.json index e5d2de0a0c..105a9dd743 100644 --- a/packages/gas-fee-controller/package.json +++ b/packages/gas-fee-controller/package.json @@ -32,7 +32,7 @@ "@metamask/controller-utils": "^5.0.0", "@metamask/eth-query": "^3.0.1", "@metamask/network-controller": "^13.0.0", - "@metamask/utils": "^6.2.0", + "@metamask/utils": "^8.1.0", "@types/uuid": "^8.3.0", "ethereumjs-util": "^7.0.10", "ethjs-unit": "^0.1.6", diff --git a/packages/keyring-controller/package.json b/packages/keyring-controller/package.json index d2b33d2a8b..96ccfebacf 100644 --- a/packages/keyring-controller/package.json +++ b/packages/keyring-controller/package.json @@ -33,7 +33,7 @@ "@metamask/eth-keyring-controller": "^13.0.1", "@metamask/message-manager": "^7.3.3", "@metamask/preferences-controller": "^4.4.1", - "@metamask/utils": "^6.2.0", + "@metamask/utils": "^8.1.0", "async-mutex": "^0.2.6", "ethereumjs-util": "^7.0.10", "ethereumjs-wallet": "^1.0.1", diff --git a/packages/message-manager/package.json b/packages/message-manager/package.json index ac55fe711b..f60ea399e3 100644 --- a/packages/message-manager/package.json +++ b/packages/message-manager/package.json @@ -31,7 +31,7 @@ "@metamask/base-controller": "^3.2.1", "@metamask/controller-utils": "^5.0.0", "@metamask/eth-sig-util": "^7.0.0", - "@metamask/utils": "^6.2.0", + "@metamask/utils": "^8.1.0", "@types/uuid": "^8.3.0", "ethereumjs-util": "^7.0.10", "jsonschema": "^1.2.4", diff --git a/packages/name-controller/package.json b/packages/name-controller/package.json index 38a0f99f0f..a8cc3e9f6d 100644 --- a/packages/name-controller/package.json +++ b/packages/name-controller/package.json @@ -30,7 +30,7 @@ }, "dependencies": { "@metamask/base-controller": "^3.2.1", - "@metamask/utils": "^6.2.0", + "@metamask/utils": "^8.1.0", "async-mutex": "^0.2.6", "immer": "^9.0.6" }, diff --git a/packages/network-controller/package.json b/packages/network-controller/package.json index 2ad3570d8b..ebdd2a9a62 100644 --- a/packages/network-controller/package.json +++ b/packages/network-controller/package.json @@ -35,7 +35,7 @@ "@metamask/eth-json-rpc-provider": "^1.0.0", "@metamask/eth-query": "^3.0.1", "@metamask/swappable-obj-proxy": "^2.1.0", - "@metamask/utils": "^6.2.0", + "@metamask/utils": "^8.1.0", "async-mutex": "^0.2.6", "eth-block-tracker": "^7.0.1", "eth-rpc-errors": "^4.0.2", diff --git a/packages/notification-controller/package.json b/packages/notification-controller/package.json index fea9e4f35c..32cabd5c1a 100644 --- a/packages/notification-controller/package.json +++ b/packages/notification-controller/package.json @@ -29,7 +29,7 @@ }, "dependencies": { "@metamask/base-controller": "^3.2.1", - "@metamask/utils": "^6.2.0", + "@metamask/utils": "^8.1.0", "immer": "^9.0.6", "nanoid": "^3.1.31" }, diff --git a/packages/permission-controller/README.md b/packages/permission-controller/README.md index b05c224007..9d3e8f0edd 100644 --- a/packages/permission-controller/README.md +++ b/packages/permission-controller/README.md @@ -1,6 +1,6 @@ # `@metamask/permission-controller` -Mediates access to JSON-RPC methods, used to interact with pieces of the MetaMask stack, via middleware for `json-rpc-engine`. +Mediates access to JSON-RPC methods, used to interact with pieces of the MetaMask stack, via middleware for `@metamask/json-rpc-engine`. ## Installation diff --git a/packages/permission-controller/package.json b/packages/permission-controller/package.json index 28ac47acca..93532f5611 100644 --- a/packages/permission-controller/package.json +++ b/packages/permission-controller/package.json @@ -31,12 +31,12 @@ "@metamask/approval-controller": "^3.5.1", "@metamask/base-controller": "^3.2.1", "@metamask/controller-utils": "^5.0.0", - "@metamask/utils": "^6.2.0", + "@metamask/json-rpc-engine": "^7.1.1", + "@metamask/rpc-errors": "^6.0.0", + "@metamask/utils": "^8.1.0", "@types/deep-freeze-strict": "^1.1.0", "deep-freeze-strict": "^1.1.1", - "eth-rpc-errors": "^4.0.2", "immer": "^9.0.6", - "json-rpc-engine": "^6.1.0", "nanoid": "^3.1.31" }, "devDependencies": { diff --git a/packages/permission-controller/src/Permission.ts b/packages/permission-controller/src/Permission.ts index c6e033d2fb..c9951630f0 100644 --- a/packages/permission-controller/src/Permission.ts +++ b/packages/permission-controller/src/Permission.ts @@ -210,19 +210,20 @@ type RestrictedMethodContext = Readonly<{ [key: string]: any; }>; -export type RestrictedMethodParameters = Json[] | Record | void; +export type RestrictedMethodParameters = Json[] | Record; /** * The arguments passed to a restricted method implementation. * * @template Params - The JSON-RPC parameters of the restricted method. */ -export type RestrictedMethodOptions = - { - method: TargetName; - params?: Params; - context: RestrictedMethodContext; - }; +export type RestrictedMethodOptions< + Params extends RestrictedMethodParameters | null, +> = { + method: TargetName; + params?: Params; + context: RestrictedMethodContext; +}; /** * A synchronous restricted method implementation. diff --git a/packages/permission-controller/src/PermissionController.test.ts b/packages/permission-controller/src/PermissionController.test.ts index c20e3cb71c..d32f3fd22a 100644 --- a/packages/permission-controller/src/PermissionController.test.ts +++ b/packages/permission-controller/src/PermissionController.test.ts @@ -6,11 +6,10 @@ import type { } from '@metamask/approval-controller'; import { ControllerMessenger } from '@metamask/base-controller'; import { isPlainObject } from '@metamask/controller-utils'; -import type { Json } from '@metamask/utils'; +import { JsonRpcEngine } from '@metamask/json-rpc-engine'; +import type { Json, PendingJsonRpcResponse } from '@metamask/utils'; import { hasProperty } from '@metamask/utils'; import assert from 'assert'; -import { JsonRpcEngine } from 'json-rpc-engine'; -import type { PendingJsonRpcResponse } from 'json-rpc-engine'; import type { AsyncRestrictedMethod, @@ -251,7 +250,7 @@ function getDefaultPermissionSpecifications() { CaveatTypes.filterArrayResponse, CaveatTypes.reverseArrayResponse, ], - methodImplementation: (_args: RestrictedMethodOptions) => { + methodImplementation: (_args: RestrictedMethodOptions) => { return ['a', 'b', 'c']; }, }, @@ -262,7 +261,9 @@ function getDefaultPermissionSpecifications() { CaveatTypes.filterObjectResponse, CaveatTypes.noopCaveat, ], - methodImplementation: (_args: RestrictedMethodOptions) => { + methodImplementation: ( + _args: RestrictedMethodOptions>, + ) => { return { a: 'x', b: 'y', c: 'z' }; }, validator: (permission: PermissionConstraint) => { @@ -292,7 +293,7 @@ function getDefaultPermissionSpecifications() { permissionType: PermissionType.RestrictedMethod, targetName: PermissionKeys.wallet_noop, allowedCaveats: null, - methodImplementation: (_args: RestrictedMethodOptions) => { + methodImplementation: (_args: RestrictedMethodOptions) => { return null; }, }, @@ -300,7 +301,7 @@ function getDefaultPermissionSpecifications() { permissionType: PermissionType.RestrictedMethod, targetName: PermissionKeys.wallet_noopWithPermittedAndFailureSideEffects, allowedCaveats: null, - methodImplementation: (_args: RestrictedMethodOptions) => { + methodImplementation: (_args: RestrictedMethodOptions) => { return null; }, sideEffect: { @@ -312,7 +313,7 @@ function getDefaultPermissionSpecifications() { permissionType: PermissionType.RestrictedMethod, targetName: PermissionKeys.wallet_noopWithPermittedAndFailureSideEffects2, allowedCaveats: null, - methodImplementation: (_args: RestrictedMethodOptions) => { + methodImplementation: (_args: RestrictedMethodOptions) => { return null; }, sideEffect: { @@ -324,7 +325,7 @@ function getDefaultPermissionSpecifications() { permissionType: PermissionType.RestrictedMethod, targetName: PermissionKeys.wallet_noopWithPermittedSideEffects, allowedCaveats: null, - methodImplementation: (_args: RestrictedMethodOptions) => { + methodImplementation: (_args: RestrictedMethodOptions) => { return null; }, sideEffect: { @@ -335,7 +336,7 @@ function getDefaultPermissionSpecifications() { [PermissionKeys.wallet_noopWithValidator]: { permissionType: PermissionType.RestrictedMethod, targetName: PermissionKeys.wallet_noopWithValidator, - methodImplementation: (_args: RestrictedMethodOptions) => { + methodImplementation: (_args: RestrictedMethodOptions) => { return null; }, allowedCaveats: [CaveatTypes.noopCaveat, CaveatTypes.filterArrayResponse], @@ -352,7 +353,7 @@ function getDefaultPermissionSpecifications() { [PermissionKeys.wallet_noopWithRequiredCaveat]: { permissionType: PermissionType.RestrictedMethod, targetName: PermissionKeys.wallet_noopWithRequiredCaveat, - methodImplementation: (_args: RestrictedMethodOptions) => { + methodImplementation: (_args: RestrictedMethodOptions) => { return null; }, allowedCaveats: [CaveatTypes.noopCaveat], @@ -388,7 +389,7 @@ function getDefaultPermissionSpecifications() { [PermissionKeys.wallet_noopWithFactory]: { permissionType: PermissionType.RestrictedMethod, targetName: PermissionKeys.wallet_noopWithFactory, - methodImplementation: (_args: RestrictedMethodOptions) => { + methodImplementation: (_args: RestrictedMethodOptions) => { return null; }, allowedCaveats: [CaveatTypes.filterArrayResponse], @@ -415,7 +416,7 @@ function getDefaultPermissionSpecifications() { permissionType: PermissionType.RestrictedMethod, targetName: PermissionKeys.snap_foo, allowedCaveats: null, - methodImplementation: (_args: RestrictedMethodOptions) => { + methodImplementation: (_args: RestrictedMethodOptions) => { return null; }, subjectTypes: [SubjectType.Snap], @@ -1850,7 +1851,7 @@ describe('PermissionController', () => { expect(() => controller.removeCaveat( origin, - PermissionNames.wallet_noopWithRequiredCaveat, + PermissionNames.wallet_noopWithRequiredCaveat as any, CaveatTypes.noopCaveat, ), ).toThrow( @@ -5270,7 +5271,13 @@ describe('PermissionController', () => { }; const expectedError = errors.unauthorized({ - data: { origin, method: PermissionNames.wallet_getSecretArray }, + data: { + origin, + method: PermissionNames.wallet_getSecretArray, + cause: null, + }, + message: + 'Unauthorized to perform action. Try requesting the required permission(s) first. For more information, see: https://docs.metamask.io/guide/rpc-api.html#permissions', }); const { error }: any = await engine.handle(request); @@ -5293,6 +5300,11 @@ describe('PermissionController', () => { const expectedError = errors.methodNotFound('wallet_foo', { origin }); const { error }: any = await engine.handle(request); + + expect(error.message).toStrictEqual(expectedError.message); + expect(error.data.cause).toBeNull(); + delete error.message; + delete error.data.cause; expect(error).toMatchObject(expect.objectContaining(expectedError)); }); @@ -5334,6 +5346,10 @@ describe('PermissionController', () => { ); const { error }: any = await engine.handle(request); + expect(error.message).toStrictEqual(expectedError.message); + expect(error.data.cause).toBeNull(); + delete error.message; + delete error.data.cause; expect(error).toMatchObject(expect.objectContaining(expectedError)); }); }); diff --git a/packages/permission-controller/src/PermissionController.ts b/packages/permission-controller/src/PermissionController.ts index db282cda67..5bebdb970a 100644 --- a/packages/permission-controller/src/PermissionController.ts +++ b/packages/permission-controller/src/PermissionController.ts @@ -18,10 +18,10 @@ import { isPlainObject, isValidJson, } from '@metamask/controller-utils'; +import { JsonRpcError } from '@metamask/rpc-errors'; import { hasProperty } from '@metamask/utils'; import type { Json, Mutable } from '@metamask/utils'; import deepFreeze from 'deep-freeze-strict'; -import { EthereumRpcError } from 'eth-rpc-errors'; import { castDraft } from 'immer'; import type { Draft, Patch } from 'immer'; import { nanoid } from 'nanoid'; @@ -1802,6 +1802,7 @@ export class PermissionController< target: string, ): void { if (!isPlainObject(caveat)) { + // eslint-disable-next-line @typescript-eslint/no-throw-literal throw new InvalidCaveatError(caveat, origin, target); } @@ -2149,7 +2150,7 @@ export class PermissionController< try { this.validateRequestedPermissions(origin, permissions); } catch (error) { - if (error instanceof EthereumRpcError) { + if (error instanceof JsonRpcError) { // Re-throw as an internal error; we should never receive invalid approved // permissions. throw internalError( diff --git a/packages/permission-controller/src/errors.ts b/packages/permission-controller/src/errors.ts index 04a41ba053..43a80b7d87 100644 --- a/packages/permission-controller/src/errors.ts +++ b/packages/permission-controller/src/errors.ts @@ -1,9 +1,16 @@ -import { errorCodes, ethErrors, EthereumRpcError } from 'eth-rpc-errors'; +import type { DataWithOptionalCause } from '@metamask/rpc-errors'; +import { + errorCodes, + providerErrors, + rpcErrors, + JsonRpcError, +} from '@metamask/rpc-errors'; import type { PermissionType } from './Permission'; type UnauthorizedArg = { data?: Record; + message?: string; }; /** @@ -13,7 +20,7 @@ type UnauthorizedArg = { * @returns The built error */ export function unauthorized(opts: UnauthorizedArg) { - return ethErrors.provider.unauthorized({ + return providerErrors.unauthorized({ message: 'Unauthorized to perform action. Try requesting the required permission(s) first. For more information, see: https://docs.metamask.io/guide/rpc-api.html#permissions', data: opts.data, @@ -27,19 +34,19 @@ export function unauthorized(opts: UnauthorizedArg) { * @param data - Optional data for context. * @returns The built error */ -export function methodNotFound(method: string, data?: unknown) { +export function methodNotFound(method: string, data?: DataWithOptionalCause) { const message = `The method "${method}" does not exist / is not available.`; - const opts: Parameters[0] = { message }; + const opts: Parameters[0] = { message }; if (data !== undefined) { opts.data = data; } - return ethErrors.rpc.methodNotFound(opts); + return rpcErrors.methodNotFound(opts); } type InvalidParamsArg = { message?: string; - data?: unknown; + data?: DataWithOptionalCause; }; /** @@ -49,7 +56,7 @@ type InvalidParamsArg = { * @returns The built error */ export function invalidParams(opts: InvalidParamsArg) { - return ethErrors.rpc.invalidParams({ + return rpcErrors.invalidParams({ data: opts.data, message: opts.message, }); @@ -63,8 +70,8 @@ export function invalidParams(opts: InvalidParamsArg) { */ export function userRejectedRequest>( data?: Data, -): EthereumRpcError { - return ethErrors.provider.userRejectedRequest({ data }); +): JsonRpcError { + return providerErrors.userRejectedRequest({ data }); } /** @@ -77,8 +84,8 @@ export function userRejectedRequest>( export function internalError>( message: string, data?: Data, -): EthereumRpcError { - return ethErrors.rpc.internal({ message, data }); +): JsonRpcError { + return rpcErrors.internal({ message, data }); } export class InvalidSubjectIdentifierError extends Error { @@ -183,7 +190,9 @@ export class CaveatAlreadyExistsError extends Error { } } -export class InvalidCaveatError extends EthereumRpcError { +export class InvalidCaveatError extends JsonRpcError< + DataWithOptionalCause | undefined +> { public override data: { origin: string; target: string }; constructor(receivedCaveat: unknown, origin: string, target: string) { diff --git a/packages/permission-controller/src/permission-middleware.ts b/packages/permission-controller/src/permission-middleware.ts index c79437fdc5..c18b90c622 100644 --- a/packages/permission-controller/src/permission-middleware.ts +++ b/packages/permission-controller/src/permission-middleware.ts @@ -1,13 +1,15 @@ -import type { Json } from '@metamask/utils'; -import { createAsyncMiddleware } from 'json-rpc-engine'; +import { createAsyncMiddleware } from '@metamask/json-rpc-engine'; import type { // eslint-disable-next-line @typescript-eslint/no-unused-vars JsonRpcEngine, JsonRpcMiddleware, AsyncJsonRpcEngineNextCallback, +} from '@metamask/json-rpc-engine'; +import type { + Json, PendingJsonRpcResponse, JsonRpcRequest, -} from 'json-rpc-engine'; +} from '@metamask/utils'; import type { GenericPermissionController, diff --git a/packages/permission-controller/src/rpc-methods/getPermissions.test.ts b/packages/permission-controller/src/rpc-methods/getPermissions.test.ts index fd97a59e51..7ebbe4a04f 100644 --- a/packages/permission-controller/src/rpc-methods/getPermissions.test.ts +++ b/packages/permission-controller/src/rpc-methods/getPermissions.test.ts @@ -1,4 +1,4 @@ -import { JsonRpcEngine } from 'json-rpc-engine'; +import { JsonRpcEngine } from '@metamask/json-rpc-engine'; import { getPermissionsHandler } from './getPermissions'; diff --git a/packages/permission-controller/src/rpc-methods/getPermissions.ts b/packages/permission-controller/src/rpc-methods/getPermissions.ts index 7a11734e15..6debc06c84 100644 --- a/packages/permission-controller/src/rpc-methods/getPermissions.ts +++ b/packages/permission-controller/src/rpc-methods/getPermissions.ts @@ -1,5 +1,5 @@ +import type { JsonRpcEngineEndCallback } from '@metamask/json-rpc-engine'; import type { PendingJsonRpcResponse } from '@metamask/utils'; -import type { JsonRpcEngineEndCallback } from 'json-rpc-engine'; import type { PermissionConstraint } from '../Permission'; import type { SubjectPermissions } from '../PermissionController'; @@ -8,7 +8,7 @@ import { MethodNames } from '../utils'; export const getPermissionsHandler: PermittedHandlerExport< GetPermissionsHooks, - undefined, + any, PermissionConstraint[] > = { methodNames: [MethodNames.getPermissions], diff --git a/packages/permission-controller/src/rpc-methods/requestPermissions.test.ts b/packages/permission-controller/src/rpc-methods/requestPermissions.test.ts index b657286e8a..dfa18ef953 100644 --- a/packages/permission-controller/src/rpc-methods/requestPermissions.test.ts +++ b/packages/permission-controller/src/rpc-methods/requestPermissions.test.ts @@ -1,5 +1,8 @@ -import { ethErrors, serializeError } from 'eth-rpc-errors'; -import { JsonRpcEngine, createAsyncMiddleware } from 'json-rpc-engine'; +import { + JsonRpcEngine, + createAsyncMiddleware, +} from '@metamask/json-rpc-engine'; +import { rpcErrors, serializeError } from '@metamask/rpc-errors'; import { requestPermissionsHandler } from './requestPermissions'; @@ -67,7 +70,13 @@ describe('requestPermissions RPC method', () => { }); expect(response.result).toBeUndefined(); - expect(response.error).toStrictEqual(serializeError(new Error('foo'))); + delete response.error.stack; + delete response.error.data.cause.stack; + const expectedError = new Error('foo'); + delete expectedError.stack; + expect(response.error).toStrictEqual( + serializeError(expectedError, { shouldIncludeStack: false }), + ); expect(mockRequestPermissionsForOrigin).toHaveBeenCalledTimes(1); expect(mockRequestPermissionsForOrigin).toHaveBeenCalledWith({}, '1'); }); @@ -91,7 +100,7 @@ describe('requestPermissions RPC method', () => { params: [], // doesn't matter }; - const expectedError = ethErrors.rpc + const expectedError = rpcErrors .invalidRequest({ message: 'Invalid request: Must specify a valid id.', data: { request: { ...req } }, @@ -125,7 +134,7 @@ describe('requestPermissions RPC method', () => { params: invalidParams, }; - const expectedError = ethErrors.rpc + const expectedError = rpcErrors .invalidParams({ data: { request: { ...req } }, }) diff --git a/packages/permission-controller/src/rpc-methods/requestPermissions.ts b/packages/permission-controller/src/rpc-methods/requestPermissions.ts index 5792e4fbe7..1976eb2934 100644 --- a/packages/permission-controller/src/rpc-methods/requestPermissions.ts +++ b/packages/permission-controller/src/rpc-methods/requestPermissions.ts @@ -1,7 +1,7 @@ import { isPlainObject } from '@metamask/controller-utils'; +import type { JsonRpcEngineEndCallback } from '@metamask/json-rpc-engine'; +import { rpcErrors } from '@metamask/rpc-errors'; import type { JsonRpcRequest, PendingJsonRpcResponse } from '@metamask/utils'; -import { ethErrors } from 'eth-rpc-errors'; -import type { JsonRpcEngineEndCallback } from 'json-rpc-engine'; import { invalidParams } from '../errors'; import type { PermissionConstraint, RequestedPermissions } from '../Permission'; @@ -56,7 +56,7 @@ async function requestPermissionsImplementation( (typeof id === 'string' && !id) ) { return end( - ethErrors.rpc.invalidRequest({ + rpcErrors.invalidRequest({ message: 'Invalid request: Must specify a valid id.', data: { request: req }, }), diff --git a/packages/permission-controller/src/utils.ts b/packages/permission-controller/src/utils.ts index 660160a656..a031cf4199 100644 --- a/packages/permission-controller/src/utils.ts +++ b/packages/permission-controller/src/utils.ts @@ -1,13 +1,13 @@ +import type { + JsonRpcEngineEndCallback, + JsonRpcEngineNextCallback, +} from '@metamask/json-rpc-engine'; import type { Json, JsonRpcParams, JsonRpcRequest, PendingJsonRpcResponse, } from '@metamask/utils'; -import type { - JsonRpcEngineEndCallback, - JsonRpcEngineNextCallback, -} from 'json-rpc-engine'; import type { CaveatSpecificationConstraint, diff --git a/packages/polling-controller/package.json b/packages/polling-controller/package.json index 40eb086809..ab1be76a78 100644 --- a/packages/polling-controller/package.json +++ b/packages/polling-controller/package.json @@ -31,7 +31,7 @@ "@metamask/base-controller": "^3.2.1", "@metamask/controller-utils": "^5.0.0", "@metamask/network-controller": "^13.0.0", - "@metamask/utils": "^6.2.0", + "@metamask/utils": "^8.1.0", "@types/uuid": "^8.3.0", "uuid": "^8.3.2" }, diff --git a/packages/signature-controller/package.json b/packages/signature-controller/package.json index dbd7553ad1..16bda55af6 100644 --- a/packages/signature-controller/package.json +++ b/packages/signature-controller/package.json @@ -33,7 +33,7 @@ "@metamask/controller-utils": "^5.0.0", "@metamask/logging-controller": "^1.0.2", "@metamask/message-manager": "^7.3.3", - "@metamask/utils": "^6.2.0", + "@metamask/utils": "^8.1.0", "eth-rpc-errors": "^4.0.2", "ethereumjs-util": "^7.0.10", "immer": "^9.0.6", diff --git a/packages/transaction-controller/package.json b/packages/transaction-controller/package.json index 252e897550..9b8812b90b 100644 --- a/packages/transaction-controller/package.json +++ b/packages/transaction-controller/package.json @@ -37,7 +37,7 @@ "@metamask/eth-query": "^3.0.1", "@metamask/metamask-eth-abis": "^3.0.0", "@metamask/network-controller": "^13.0.0", - "@metamask/utils": "^6.2.0", + "@metamask/utils": "^8.1.0", "async-mutex": "^0.2.6", "eth-method-registry": "1.1.0", "eth-rpc-errors": "^4.0.2", diff --git a/yarn.lock b/yarn.lock index bb678fa816..45dbc1826b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1298,7 +1298,7 @@ __metadata: "@metamask/keyring-controller": ^8.0.0 "@metamask/snaps-controllers": ^1.0.1 "@metamask/snaps-utils": ^1.0.1 - "@metamask/utils": ^6.2.0 + "@metamask/utils": ^8.1.0 "@types/jest": ^27.4.1 "@types/readable-stream": ^2.3.0 deepmerge: ^4.2.2 @@ -1335,7 +1335,7 @@ __metadata: "@metamask/auto-changelog": ^3.1.0 "@metamask/base-controller": ^3.2.1 "@metamask/controller-utils": ^5.0.0 - "@metamask/utils": ^6.2.0 + "@metamask/utils": ^8.1.0 "@types/jest": ^27.4.1 deepmerge: ^4.2.2 jest: ^27.5.1 @@ -1369,10 +1369,10 @@ __metadata: dependencies: "@metamask/auto-changelog": ^3.1.0 "@metamask/base-controller": ^3.2.1 - "@metamask/utils": ^6.2.0 + "@metamask/rpc-errors": ^6.0.0 + "@metamask/utils": ^8.1.0 "@types/jest": ^27.4.1 deepmerge: ^4.2.2 - eth-rpc-errors: ^4.0.2 immer: ^9.0.6 jest: ^27.5.1 nanoid: ^3.1.31 @@ -1402,8 +1402,8 @@ __metadata: "@metamask/metamask-eth-abis": 3.0.0 "@metamask/network-controller": ^13.0.0 "@metamask/preferences-controller": ^4.4.1 - "@metamask/rpc-errors": ^5.1.1 - "@metamask/utils": ^6.2.0 + "@metamask/rpc-errors": ^6.0.0 + "@metamask/utils": ^8.1.0 "@types/jest": ^27.4.1 "@types/node": ^16.18.24 "@types/uuid": ^8.3.0 @@ -1449,7 +1449,7 @@ __metadata: resolution: "@metamask/base-controller@workspace:packages/base-controller" dependencies: "@metamask/auto-changelog": ^3.1.0 - "@metamask/utils": ^6.2.0 + "@metamask/utils": ^8.1.0 "@types/jest": ^27.4.1 "@types/sinon": ^9.0.10 deepmerge: ^4.2.2 @@ -1463,7 +1463,7 @@ __metadata: languageName: unknown linkType: soft -"@metamask/browser-passworder@npm:^4.0.2, @metamask/browser-passworder@npm:^4.1.0": +"@metamask/browser-passworder@npm:^4.1.0": version: 4.1.0 resolution: "@metamask/browser-passworder@npm:4.1.0" checksum: f1edb3b75594b8e8d075b3134c9ce6c73573160eb48184ef722b9d96a5763db1e2e9acb166fc5c66c7c82936e134a02a3fb4c0022ca9a948857a30181cb84d7e @@ -1501,12 +1501,11 @@ __metadata: dependencies: "@metamask/auto-changelog": ^3.1.0 "@metamask/eth-query": ^3.0.1 - "@metamask/utils": ^6.2.0 + "@metamask/utils": ^8.1.0 "@spruceid/siwe-parser": 1.1.3 "@types/jest": ^27.4.1 deepmerge: ^4.2.2 eth-ens-namehash: ^2.0.8 - eth-rpc-errors: ^4.0.2 ethereumjs-util: ^7.0.10 ethjs-unit: ^0.1.6 fast-deep-equal: ^3.1.3 @@ -1530,7 +1529,7 @@ __metadata: "@metamask/eslint-config-nodejs": ^12.0.0 "@metamask/eslint-config-typescript": ^12.0.0 "@metamask/eth-json-rpc-provider": ^1.0.0 - "@metamask/utils": ^6.2.0 + "@metamask/utils": ^8.1.0 "@types/node": ^16.18.24 "@typescript-eslint/eslint-plugin": ^5.30.7 "@typescript-eslint/parser": ^5.30.7 @@ -1586,7 +1585,7 @@ __metadata: "@metamask/base-controller": ^3.2.1 "@metamask/controller-utils": ^5.0.0 "@metamask/network-controller": ^13.0.0 - "@metamask/utils": ^6.2.0 + "@metamask/utils": ^8.1.0 "@types/jest": ^27.4.1 deepmerge: ^4.2.2 ethereum-ens-network-map: ^1.0.2 @@ -1808,7 +1807,7 @@ __metadata: "@metamask/controller-utils": ^5.0.0 "@metamask/eth-query": ^3.0.1 "@metamask/network-controller": ^13.0.0 - "@metamask/utils": ^6.2.0 + "@metamask/utils": ^8.1.0 "@types/jest": ^27.4.1 "@types/jest-when": ^2.7.3 "@types/uuid": ^8.3.0 @@ -1900,7 +1899,7 @@ __metadata: "@metamask/message-manager": ^7.3.3 "@metamask/preferences-controller": ^4.4.1 "@metamask/scure-bip39": ^2.1.0 - "@metamask/utils": ^6.2.0 + "@metamask/utils": ^8.1.0 "@types/jest": ^27.4.1 async-mutex: ^0.2.6 deepmerge: ^4.2.2 @@ -1945,7 +1944,7 @@ __metadata: "@metamask/base-controller": ^3.2.1 "@metamask/controller-utils": ^5.0.0 "@metamask/eth-sig-util": ^7.0.0 - "@metamask/utils": ^6.2.0 + "@metamask/utils": ^8.1.0 "@types/jest": ^27.4.1 "@types/uuid": ^8.3.0 deepmerge: ^4.2.2 @@ -1973,7 +1972,7 @@ __metadata: dependencies: "@metamask/auto-changelog": ^3.1.0 "@metamask/base-controller": ^3.2.1 - "@metamask/utils": ^6.2.0 + "@metamask/utils": ^8.1.0 "@types/jest": ^27.4.1 async-mutex: ^0.2.6 deepmerge: ^4.2.2 @@ -1999,7 +1998,7 @@ __metadata: "@metamask/eth-json-rpc-provider": ^1.0.0 "@metamask/eth-query": ^3.0.1 "@metamask/swappable-obj-proxy": ^2.1.0 - "@metamask/utils": ^6.2.0 + "@metamask/utils": ^8.1.0 "@types/jest": ^27.4.1 "@types/jest-when": ^2.7.3 "@types/lodash": ^4.14.191 @@ -2028,7 +2027,7 @@ __metadata: dependencies: "@metamask/auto-changelog": ^3.1.0 "@metamask/base-controller": ^3.2.1 - "@metamask/utils": ^6.2.0 + "@metamask/utils": ^8.1.0 "@types/jest": ^27.4.1 deepmerge: ^4.2.2 immer: ^9.0.6 @@ -2080,15 +2079,15 @@ __metadata: "@metamask/auto-changelog": ^3.1.0 "@metamask/base-controller": ^3.2.1 "@metamask/controller-utils": ^5.0.0 - "@metamask/utils": ^6.2.0 + "@metamask/json-rpc-engine": ^7.1.1 + "@metamask/rpc-errors": ^6.0.0 + "@metamask/utils": ^8.1.0 "@types/deep-freeze-strict": ^1.1.0 "@types/jest": ^27.4.1 deep-freeze-strict: ^1.1.1 deepmerge: ^4.2.2 - eth-rpc-errors: ^4.0.2 immer: ^9.0.6 jest: ^27.5.1 - json-rpc-engine: ^6.1.0 nanoid: ^3.1.31 ts-jest: ^27.1.4 typedoc: ^0.23.15 @@ -2129,7 +2128,7 @@ __metadata: "@metamask/base-controller": ^3.2.1 "@metamask/controller-utils": ^5.0.0 "@metamask/network-controller": ^13.0.0 - "@metamask/utils": ^6.2.0 + "@metamask/utils": ^8.1.0 "@types/jest": ^27.4.1 "@types/uuid": ^8.3.0 deepmerge: ^4.2.2 @@ -2247,16 +2246,6 @@ __metadata: languageName: unknown linkType: soft -"@metamask/rpc-errors@npm:^5.1.1": - version: 5.1.1 - resolution: "@metamask/rpc-errors@npm:5.1.1" - dependencies: - "@metamask/utils": ^5.0.0 - fast-safe-stringify: ^2.0.6 - checksum: ccd1b24da66af3ae63960b79c04b86efb8b96acb89ca6f7e0bbfe636d23ba5cddeba533c0692eafb87c44ec6f840085372d0f21b39e05df9a80700ff61538a30 - languageName: node - linkType: hard - "@metamask/rpc-errors@npm:^6.0.0": version: 6.0.0 resolution: "@metamask/rpc-errors@npm:6.0.0" @@ -2267,7 +2256,7 @@ __metadata: languageName: node linkType: hard -"@metamask/rpc-methods@npm:^0.38.1-flask.1": +"@metamask/rpc-methods@npm:0.38.1-flask.1": version: 0.38.1-flask.1 resolution: "@metamask/rpc-methods@npm:0.38.1-flask.1" dependencies: @@ -2284,22 +2273,20 @@ __metadata: languageName: node linkType: hard -"@metamask/rpc-methods@npm:^1.0.1": - version: 1.0.1 - resolution: "@metamask/rpc-methods@npm:1.0.1" +"@metamask/rpc-methods@patch:@metamask/rpc-methods@npm%3A0.38.1-flask.1#./.yarn/patches/@metamask-rpc-methods-npm-0.38.1-flask.1-081e1eb5b3.patch::locator=%40metamask%2Fcore-monorepo%40workspace%3A.": + version: 0.38.1-flask.1 + resolution: "@metamask/rpc-methods@patch:@metamask/rpc-methods@npm%3A0.38.1-flask.1#./.yarn/patches/@metamask-rpc-methods-npm-0.38.1-flask.1-081e1eb5b3.patch::version=0.38.1-flask.1&hash=2abe25&locator=%40metamask%2Fcore-monorepo%40workspace%3A." dependencies: - "@metamask/browser-passworder": ^4.0.2 - "@metamask/key-tree": ^7.1.1 - "@metamask/permission-controller": ^4.0.0 - "@metamask/snaps-ui": ^1.0.1 - "@metamask/snaps-utils": ^1.0.1 + "@metamask/key-tree": ^9.0.0 + "@metamask/permission-controller": ^4.1.0 + "@metamask/snaps-ui": ^0.37.4-flask.1 + "@metamask/snaps-utils": ^0.38.2-flask.1 "@metamask/types": ^1.1.0 "@metamask/utils": ^6.0.1 - "@noble/hashes": ^1.1.3 - eth-rpc-errors: ^4.0.2 - nanoid: ^3.1.31 + "@noble/hashes": ^1.3.1 + eth-rpc-errors: ^4.0.3 superstruct: ^1.0.3 - checksum: 9d5c91f7af7c66b5f7afe23ce08a1d959bec1c7423063e955ae30ca41ed048e793a4e075b0fd23b9a8e54ff3a3fee018994e8d2fa494adebcc236f0bdd484340 + checksum: 61829b70d80b7d3ad40e3916a303c26b4545f61b74ea776063c9803dce7ffa4c8882fef0189803a07250e125dc3818cbd9a4e6891d1041da23bb2a9c26f85441 languageName: node linkType: hard @@ -2362,7 +2349,7 @@ __metadata: "@metamask/keyring-controller": ^8.0.0 "@metamask/logging-controller": ^1.0.2 "@metamask/message-manager": ^7.3.3 - "@metamask/utils": ^6.2.0 + "@metamask/utils": ^8.1.0 "@types/jest": ^27.4.1 deepmerge: ^4.2.2 eth-rpc-errors: ^4.0.2 @@ -2587,7 +2574,7 @@ __metadata: "@metamask/eth-query": ^3.0.1 "@metamask/metamask-eth-abis": ^3.0.0 "@metamask/network-controller": ^13.0.0 - "@metamask/utils": ^6.2.0 + "@metamask/utils": ^8.1.0 "@types/jest": ^27.4.1 "@types/node": ^16.18.24 async-mutex: ^0.2.6 @@ -2646,7 +2633,7 @@ __metadata: languageName: node linkType: hard -"@metamask/utils@npm:^6.0.1, @metamask/utils@npm:^6.2.0": +"@metamask/utils@npm:^6.0.1": version: 6.2.0 resolution: "@metamask/utils@npm:6.2.0" dependencies: