From 110ef8aaa872e8fcbef3f6d4c254969d17909b79 Mon Sep 17 00:00:00 2001 From: Shane Jonas Date: Fri, 11 Oct 2024 10:20:32 -0400 Subject: [PATCH 1/9] fix: typescript + linting --- packages/multichain/package.json | 1 + ...ip-permission-adapter-eth-accounts.test.ts | 2 +- .../caip-permission-adapter-eth-accounts.ts | 15 +++--- ...caip-permission-adapter-middleware.test.ts | 16 ++++-- .../caip-permission-adapter-middleware.ts | 45 +++++++++++++--- ...permission-adapter-permittedChains.test.ts | 2 +- ...caip-permission-adapter-permittedChains.ts | 9 ++-- .../multichain/src/caip25Permission.test.ts | 9 ++-- packages/multichain/src/caip25Permission.ts | 37 +++++++++---- .../src/handlers/wallet-getSession.test.ts | 17 ++++-- .../src/handlers/wallet-getSession.ts | 32 ++++++++++-- .../src/handlers/wallet-invokeMethod.test.ts | 4 +- .../src/handlers/wallet-invokeMethod.ts | 43 ++++++++++++--- .../src/handlers/wallet-revokeSession.test.ts | 29 ++++++++--- .../src/handlers/wallet-revokeSession.ts | 27 +++++++--- .../MultichainMiddlewareManager.test.ts | 8 +-- .../MultichainMiddlewareManager.ts | 15 ++++-- .../MultichainSubscriptionManager.test.ts | 9 ++-- .../MultichainSubscriptionManager.ts | 12 +++-- .../multichainMethodCallValidator.ts | 14 ++--- packages/multichain/src/scope/assert.test.ts | 12 ++--- packages/multichain/src/scope/assert.ts | 10 ++-- .../src/scope/authorization.test.ts | 11 ++-- .../multichain/src/scope/authorization.ts | 9 ++-- packages/multichain/src/scope/filter.ts | 5 +- packages/multichain/src/scope/scope.test.ts | 2 +- packages/multichain/src/scope/scope.ts | 10 ++-- .../multichain/src/scope/supported.test.ts | 52 ++++++++----------- packages/multichain/src/scope/supported.ts | 23 ++++---- .../multichain/src/scope/transform.test.ts | 2 +- packages/multichain/src/scope/transform.ts | 15 ++++-- .../multichain/src/scope/validation.test.ts | 11 ++-- packages/multichain/src/scope/validation.ts | 5 +- yarn.lock | 18 +++++++ 34 files changed, 349 insertions(+), 182 deletions(-) diff --git a/packages/multichain/package.json b/packages/multichain/package.json index bfb1d8dd296..face18630ff 100644 --- a/packages/multichain/package.json +++ b/packages/multichain/package.json @@ -44,6 +44,7 @@ "@metamask/eth-json-rpc-filters": "^7.0.0", "@metamask/json-rpc-engine": "^9.0.3", "@metamask/rpc-errors": "^6.3.1", + "@metamask/utils": "^9.3.0", "@open-rpc/schema-utils-js": "^2.0.5", "lodash": "^4.17.21" }, diff --git a/packages/multichain/src/adapters/caip-permission-adapter-eth-accounts.test.ts b/packages/multichain/src/adapters/caip-permission-adapter-eth-accounts.test.ts index 04aba6a3301..9434fab81d9 100644 --- a/packages/multichain/src/adapters/caip-permission-adapter-eth-accounts.test.ts +++ b/packages/multichain/src/adapters/caip-permission-adapter-eth-accounts.test.ts @@ -1,4 +1,4 @@ -import { Caip25CaveatValue } from '../caip25Permission'; +import type { Caip25CaveatValue } from '../caip25Permission'; import { getEthAccounts, setEthAccounts, diff --git a/packages/multichain/src/adapters/caip-permission-adapter-eth-accounts.ts b/packages/multichain/src/adapters/caip-permission-adapter-eth-accounts.ts index d7291f42b87..95cb5dd0ec7 100644 --- a/packages/multichain/src/adapters/caip-permission-adapter-eth-accounts.ts +++ b/packages/multichain/src/adapters/caip-permission-adapter-eth-accounts.ts @@ -1,16 +1,13 @@ import { - CaipAccountId, - Hex, + type CaipAccountId, + type Hex, KnownCaipNamespace, parseCaipAccountId, } from '@metamask/utils'; -import { Caip25CaveatValue } from '../caip25Permission'; -import { - mergeScopes, - parseScopeString, - ScopesObject, - ScopeString, -} from '../scope'; + +import type { Caip25CaveatValue } from '../caip25Permission'; +import type { ScopesObject } from '../scope'; +import { mergeScopes, parseScopeString, type ScopeString } from '../scope'; const isEip155ScopeString = (scopeString: ScopeString) => { const { namespace, reference } = parseScopeString(scopeString); diff --git a/packages/multichain/src/adapters/caip-permission-adapter-middleware.test.ts b/packages/multichain/src/adapters/caip-permission-adapter-middleware.test.ts index f8c0f981371..ba34560346c 100644 --- a/packages/multichain/src/adapters/caip-permission-adapter-middleware.test.ts +++ b/packages/multichain/src/adapters/caip-permission-adapter-middleware.test.ts @@ -1,11 +1,17 @@ import { providerErrors } from '@metamask/rpc-errors'; + import { Caip25CaveatType, Caip25EndowmentPermissionName, -} from '../caip25permissions'; -import { CaipPermissionAdapterMiddleware } from './caip-permission-adapter-middleware'; +} from '../caip25Permission'; +import { + caipPermissionAdapterMiddleware, + type JsonRpcRequestWithNetworkClientIdAndOrigin, +} from './caip-permission-adapter-middleware'; const baseRequest = { + id: 1, + jsonrpc: '2.0' as const, origin: 'http://test.com', networkClientId: 'mainnet', method: 'eth_call', @@ -48,7 +54,7 @@ const createMockedHandler = () => { }); const getNetworkConfigurationByNetworkClientId = jest .fn() - .mockImplementation((networkClientId) => { + .mockImplementation((networkClientId: string) => { const chainId = { mainnet: '0x1', @@ -58,8 +64,8 @@ const createMockedHandler = () => { chainId, }; }); - const handler = (request) => - CaipPermissionAdapterMiddleware(request, {}, next, end, { + const handler = (request: JsonRpcRequestWithNetworkClientIdAndOrigin) => + caipPermissionAdapterMiddleware(request, {}, next, end, { getCaveat, getNetworkConfigurationByNetworkClientId, }); diff --git a/packages/multichain/src/adapters/caip-permission-adapter-middleware.ts b/packages/multichain/src/adapters/caip-permission-adapter-middleware.ts index 867288eb95a..fcdbc18e5eb 100644 --- a/packages/multichain/src/adapters/caip-permission-adapter-middleware.ts +++ b/packages/multichain/src/adapters/caip-permission-adapter-middleware.ts @@ -1,16 +1,45 @@ +import type { NetworkConfiguration } from '@metamask/network-controller'; +import type { Caveat } from '@metamask/permission-controller'; import { providerErrors } from '@metamask/rpc-errors'; +import type { JsonRpcRequest } from '@metamask/utils'; + +import type { Caip25CaveatValue } from '../caip25Permission'; import { Caip25CaveatType, Caip25EndowmentPermissionName, -} from '../caip25permissions'; +} from '../caip25Permission'; +import type { ScopeString } from '../scope'; import { mergeScopes } from '../scope'; -export async function CaipPermissionAdapterMiddleware( - request, - _response, - next, - end, - hooks, +export type JsonRpcRequestWithNetworkClientIdAndOrigin = JsonRpcRequest & { + networkClientId: string; + origin: string; +}; + +/** + * Middleware to handle CAIP-25 permission requests. + * + * @param request - The request object. + * @param _response - The response object. + * @param next - The next middleware function. + * @param end - The end function. + * @param hooks - The hooks object. + * @param hooks.getCaveat - Function to retrieve a caveat. + * @param hooks.getNetworkConfigurationByNetworkClientId - Function to retrieve a network configuration. + */ +export async function caipPermissionAdapterMiddleware( + request: JsonRpcRequestWithNetworkClientIdAndOrigin, + _response: unknown, + next: () => Promise, + end: (error?: Error) => void, + hooks: { + getCaveat: ( + ...args: unknown[] + ) => Caveat; + getNetworkConfigurationByNetworkClientId: ( + networkClientId: string, + ) => NetworkConfiguration; + }, ) { const { networkClientId, method } = request; @@ -31,7 +60,7 @@ export async function CaipPermissionAdapterMiddleware( const { chainId } = hooks.getNetworkConfigurationByNetworkClientId(networkClientId); - const scope = `eip155:${parseInt(chainId, 16)}`; + const scope: ScopeString = `eip155:${parseInt(chainId, 16)}`; const scopesObject = mergeScopes( caveat.value.requiredScopes, diff --git a/packages/multichain/src/adapters/caip-permission-adapter-permittedChains.test.ts b/packages/multichain/src/adapters/caip-permission-adapter-permittedChains.test.ts index e83562f7dcb..a7402078079 100644 --- a/packages/multichain/src/adapters/caip-permission-adapter-permittedChains.test.ts +++ b/packages/multichain/src/adapters/caip-permission-adapter-permittedChains.test.ts @@ -1,4 +1,4 @@ -import { Caip25CaveatValue } from '../caip25Permission'; +import type { Caip25CaveatValue } from '../caip25Permission'; import { KnownNotifications, KnownRpcMethods } from '../scope'; import { addPermittedEthChainId, diff --git a/packages/multichain/src/adapters/caip-permission-adapter-permittedChains.ts b/packages/multichain/src/adapters/caip-permission-adapter-permittedChains.ts index 39b2b86bea3..cfbbdedd298 100644 --- a/packages/multichain/src/adapters/caip-permission-adapter-permittedChains.ts +++ b/packages/multichain/src/adapters/caip-permission-adapter-permittedChains.ts @@ -1,13 +1,14 @@ -import { Hex, KnownCaipNamespace } from '@metamask/utils'; import { toHex } from '@metamask/controller-utils'; -import { Caip25CaveatValue } from '../caip25Permission'; +import type { Hex } from '@metamask/utils'; +import { KnownCaipNamespace } from '@metamask/utils'; + +import type { Caip25CaveatValue } from '../caip25Permission'; +import type { ScopesObject, ScopeString } from '../scope'; import { KnownNotifications, KnownRpcMethods, mergeScopes, parseScopeString, - ScopesObject, - ScopeString, } from '../scope'; export const getPermittedEthChainIds = ( diff --git a/packages/multichain/src/caip25Permission.test.ts b/packages/multichain/src/caip25Permission.test.ts index cf63cf0a0c2..ace4068d89d 100644 --- a/packages/multichain/src/caip25Permission.test.ts +++ b/packages/multichain/src/caip25Permission.test.ts @@ -1,19 +1,20 @@ +import type { NonEmptyArray } from '@metamask/controller-utils'; +import type { CaveatConstraint } from '@metamask/permission-controller'; import { - CaveatConstraint, CaveatMutatorOperation, PermissionType, SubjectType, } from '@metamask/permission-controller'; -import { NonEmptyArray } from '@metamask/controller-utils'; -import * as Scope from './scope'; + +import type { Caip25CaveatValue } from './caip25Permission'; import { Caip25CaveatType, - Caip25CaveatValue, caip25EndowmentBuilder, Caip25EndowmentPermissionName, Caip25CaveatMutatorFactories, removeScope, } from './caip25Permission'; +import * as Scope from './scope'; jest.mock('./scope', () => ({ validateAndFlattenScopes: jest.fn(), diff --git a/packages/multichain/src/caip25Permission.ts b/packages/multichain/src/caip25Permission.ts index 35312b2e11f..b4e0a1ead45 100644 --- a/packages/multichain/src/caip25Permission.ts +++ b/packages/multichain/src/caip25Permission.ts @@ -1,4 +1,4 @@ -import { strict as assert } from 'assert'; +import type { NetworkClientId } from '@metamask/network-controller'; import type { PermissionSpecificationBuilder, EndowmentGetterParams, @@ -11,22 +11,17 @@ import { PermissionType, SubjectType, } from '@metamask/permission-controller'; +import type { CaipAccountId, Json } from '@metamask/utils'; import { - CaipAccountId, - Json, parseCaipAccountId, type Hex, type NonEmptyArray, } from '@metamask/utils'; -import { NetworkClientId } from '@metamask/network-controller'; +import { strict as assert } from 'assert'; import { cloneDeep, isEqual } from 'lodash'; -import { - ExternalScopeString, - validateAndFlattenScopes, - ScopesObject, - ScopeObject, - assertScopesSupported, -} from './scope'; + +import type { ExternalScopeString, ScopesObject, ScopeObject } from './scope'; +import { validateAndFlattenScopes, assertScopesSupported } from './scope'; export type Caip25CaveatValue = { requiredScopes: ScopesObject; @@ -155,6 +150,12 @@ const reduceKeysHelper = ( }; }; +/** + * Removes the account from the scope object. + * + * @param targetAddress - The address to remove from the scope object. + * @returns A function that removes the account from the scope object. + */ function removeAccountFilterFn(targetAddress: string) { return (account: CaipAccountId) => { const parsed = parseCaipAccountId(account); @@ -162,6 +163,12 @@ function removeAccountFilterFn(targetAddress: string) { }; } +/** + * Removes the account from the scope object. + * + * @param targetAddress - The address to remove from the scope object. + * @param scopeObject - The scope object to remove the account from. + */ function removeAccountOnScope(targetAddress: string, scopeObject: ScopeObject) { if (scopeObject.accounts) { scopeObject.accounts = scopeObject.accounts.filter( @@ -170,6 +177,13 @@ function removeAccountOnScope(targetAddress: string, scopeObject: ScopeObject) { } } +/** + * Removes the target account from the scope object. + * + * @param targetAddress - The address to remove from the scope object. + * @param existingScopes - The scope object to remove the account from. + * @returns The updated scope object. + */ function removeAccount( targetAddress: string, // non caip-10 formatted address existingScopes: Caip25CaveatValue, @@ -208,6 +222,7 @@ function removeAccount( * * @param targetScopeString - The scope that is being removed. * @param caip25CaveatValue - The CAIP-25 permission caveat value to remove the scope from. + * @returns The updated CAIP-25 permission caveat value. */ export function removeScope( targetScopeString: ExternalScopeString, diff --git a/packages/multichain/src/handlers/wallet-getSession.test.ts b/packages/multichain/src/handlers/wallet-getSession.test.ts index bbbad820a20..742719eae1d 100644 --- a/packages/multichain/src/handlers/wallet-getSession.test.ts +++ b/packages/multichain/src/handlers/wallet-getSession.test.ts @@ -1,12 +1,17 @@ +import { JsonRpcRequestWithNetworkClientIdAndOrigin } from 'src/adapters/caip-permission-adapter-middleware'; import { Caip25CaveatType, Caip25EndowmentPermissionName, } from '../caip25Permission'; import { walletGetSessionHandler } from './wallet-getSession'; -const baseRequest = { +const baseRequest: JsonRpcRequestWithNetworkClientIdAndOrigin = { origin: 'http://test.com', + jsonrpc: '2.0' as const, + method: 'wallet_getSession', params: {}, + id: 1, + networkClientId: 'mainnet', }; const createMockedHandler = () => { @@ -36,8 +41,14 @@ const createMockedHandler = () => { }, }, }); - const response = {}; - const handler = (request) => + const response = { + result: { + sessionScopes: {}, + }, + id: 1, + jsonrpc: '2.0' as const, + }; + const handler = (request: JsonRpcRequestWithNetworkClientIdAndOrigin) => walletGetSessionHandler(request, response, next, end, { getCaveat, }); diff --git a/packages/multichain/src/handlers/wallet-getSession.ts b/packages/multichain/src/handlers/wallet-getSession.ts index 5bcefe07059..f80275d4e4a 100644 --- a/packages/multichain/src/handlers/wallet-getSession.ts +++ b/packages/multichain/src/handlers/wallet-getSession.ts @@ -1,15 +1,37 @@ +import type { Caveat } from '@metamask/permission-controller'; +import type { JsonRpcSuccess } from '@metamask/utils'; +import type { JsonRpcRequestWithNetworkClientIdAndOrigin } from 'src/adapters/caip-permission-adapter-middleware'; + +import type { Caip25CaveatValue } from '../caip25Permission'; import { Caip25CaveatType, Caip25EndowmentPermissionName, } from '../caip25Permission'; +import type { ScopesObject } from '../scope'; import { mergeScopes } from '../scope'; +/** + * Handler for the `wallet_getSession` RPC method. + * + * @param request - The request object. + * @param response - The response object. + * @param _next - The next middleware function. + * @param end - The end function. + * @param hooks - The hooks object. + * @param hooks.getCaveat - Function to retrieve a caveat. + */ export async function walletGetSessionHandler( - request, - response, - _next, - end, - hooks, + request: JsonRpcRequestWithNetworkClientIdAndOrigin, + response: JsonRpcSuccess<{ sessionScopes: ScopesObject }>, + _next: () => void, + end: () => void, + hooks: { + getCaveat: ( + origin: string, + endowmentPermissionName: string, + caveatType: string, + ) => Caveat; + }, ) { let caveat; try { diff --git a/packages/multichain/src/handlers/wallet-invokeMethod.test.ts b/packages/multichain/src/handlers/wallet-invokeMethod.test.ts index 56d46d1c024..1705e0b40de 100644 --- a/packages/multichain/src/handlers/wallet-invokeMethod.test.ts +++ b/packages/multichain/src/handlers/wallet-invokeMethod.test.ts @@ -1,9 +1,11 @@ import { providerErrors, rpcErrors } from '@metamask/rpc-errors'; + import { Caip25CaveatType, Caip25EndowmentPermissionName, } from '../caip25Permission'; import { walletInvokeMethodHandler } from './wallet-invokeMethod'; +import { JsonRpcRequestWithNetworkClientIdAndOrigin } from 'src/adapters/caip-permission-adapter-middleware'; const createMockedRequest = () => ({ origin: 'http://test.com', @@ -54,7 +56,7 @@ const createMockedHandler = () => { const getSelectedNetworkClientId = jest .fn() .mockReturnValue('selectedNetworkClientId'); - const handler = (request) => + const handler = (request: JsonRpcRequestWithNetworkClientIdAndOrigin) => walletInvokeMethodHandler(request, {}, next, end, { getCaveat, findNetworkClientIdByChainId, diff --git a/packages/multichain/src/handlers/wallet-invokeMethod.ts b/packages/multichain/src/handlers/wallet-invokeMethod.ts index 1ca8ff5b1ea..bd5b1f09d6a 100644 --- a/packages/multichain/src/handlers/wallet-invokeMethod.ts +++ b/packages/multichain/src/handlers/wallet-invokeMethod.ts @@ -1,19 +1,48 @@ -import { numberToHex } from '@metamask/utils'; +import type { Caveat } from '@metamask/permission-controller'; import { providerErrors, rpcErrors } from '@metamask/rpc-errors'; +import type { JsonRpcSuccess, Json, JsonRpcRequest } from '@metamask/utils'; +import { numberToHex } from '@metamask/utils'; +import type { JsonRpcRequestWithNetworkClientIdAndOrigin } from 'src/adapters/caip-permission-adapter-middleware'; + +import type { Caip25CaveatValue } from '../caip25Permission'; import { Caip25CaveatType, Caip25EndowmentPermissionName, } from '../caip25Permission'; +import type { ScopeString } from '../scope'; import { mergeScopes, parseScopeString } from '../scope'; +/** + * Handler for the `wallet_invokeMethod` RPC method. + * + * @param request - The request object. + * @param _response - The response object. + * @param next - The next middleware function. + * @param end - The end function. + * @param hooks - The hooks object. + * @param hooks.getCaveat + * @param hooks.findNetworkClientIdByChainId + * @param hooks.getSelectedNetworkClientId + */ export async function walletInvokeMethodHandler( - request, - _response, - next, - end, - hooks, + request: JsonRpcRequestWithNetworkClientIdAndOrigin, + _response: JsonRpcSuccess, + next: () => void, + end: (error: Error) => void, + hooks: { + getCaveat: ( + origin: string, + endowmentPermissionName: string, + caveatType: string, + ) => Caveat; + findNetworkClientIdByChainId: (chainId: string) => string | undefined; + getSelectedNetworkClientId: () => string; + }, ) { - const { scope, request: wrappedRequest } = request.params; + const { scope, request: wrappedRequest } = request.params as { + scope: ScopeString; + request: JsonRpcRequest; + }; let caveat; try { diff --git a/packages/multichain/src/handlers/wallet-revokeSession.test.ts b/packages/multichain/src/handlers/wallet-revokeSession.test.ts index 6a6add80232..0713f2bf3ef 100644 --- a/packages/multichain/src/handlers/wallet-revokeSession.test.ts +++ b/packages/multichain/src/handlers/wallet-revokeSession.test.ts @@ -3,20 +3,30 @@ import { UnrecognizedSubjectError, } from '@metamask/permission-controller'; import { rpcErrors } from '@metamask/rpc-errors'; +import type { JsonRpcRequestWithNetworkClientIdAndOrigin } from 'src/adapters/caip-permission-adapter-middleware'; + import { Caip25EndowmentPermissionName } from '../caip25Permission'; import { walletRevokeSessionHandler } from './wallet-revokeSession'; -const baseRequest = { +const baseRequest: JsonRpcRequestWithNetworkClientIdAndOrigin = { origin: 'http://test.com', params: {}, + jsonrpc: '2.0' as const, + id: 1, + networkClientId: 'mainnet', + method: 'wallet_revokeSession', }; const createMockedHandler = () => { const next = jest.fn(); const end = jest.fn(); const revokePermission = jest.fn(); - const response = {}; - const handler = (request) => + const response = { + result: true, + id: 1, + jsonrpc: '2.0' as const, + }; + const handler = (request: JsonRpcRequestWithNetworkClientIdAndOrigin) => walletRevokeSessionHandler(request, response, next, end, { revokePermission, }); @@ -44,21 +54,24 @@ describe('wallet_revokeSession', () => { it('returns true if the CAIP-25 endowment permission does not exist', async () => { const { handler, response, revokePermission } = createMockedHandler(); revokePermission.mockImplementation(() => { - throw new PermissionDoesNotExistError(); + throw new PermissionDoesNotExistError( + 'foo.com', + Caip25EndowmentPermissionName, + ); }); await handler(baseRequest); - expect(response.result).toStrictEqual(true); + expect(response.result).toBe(true); }); it('returns true if the subject does not exist', async () => { const { handler, response, revokePermission } = createMockedHandler(); revokePermission.mockImplementation(() => { - throw new UnrecognizedSubjectError(); + throw new UnrecognizedSubjectError('foo.com'); }); await handler(baseRequest); - expect(response.result).toStrictEqual(true); + expect(response.result).toBe(true); }); it('throws an internal RPC error if something unexpected goes wrong with revoking the permission', async () => { @@ -75,6 +88,6 @@ describe('wallet_revokeSession', () => { const { handler, response } = createMockedHandler(); await handler(baseRequest); - expect(response.result).toStrictEqual(true); + expect(response.result).toBe(true); }); }); diff --git a/packages/multichain/src/handlers/wallet-revokeSession.ts b/packages/multichain/src/handlers/wallet-revokeSession.ts index d76994de901..3e52f43d73a 100644 --- a/packages/multichain/src/handlers/wallet-revokeSession.ts +++ b/packages/multichain/src/handlers/wallet-revokeSession.ts @@ -1,20 +1,35 @@ -import type { JsonRpcEngineNextCallback, JsonRpcEngineEndCallback } from '@metamask/json-rpc-engine'; +import type { + JsonRpcEngineNextCallback, + JsonRpcEngineEndCallback, +} from '@metamask/json-rpc-engine'; +import type { PermissionController } from '@metamask/permission-controller'; import { PermissionDoesNotExistError, UnrecognizedSubjectError, - PermissionController } from '@metamask/permission-controller'; import { rpcErrors } from '@metamask/rpc-errors'; +import type { JsonRpcSuccess, Json } from '@metamask/utils'; +import type { JsonRpcRequestWithNetworkClientIdAndOrigin } from 'src/adapters/caip-permission-adapter-middleware'; + import { Caip25EndowmentPermissionName } from '../caip25Permission'; -import { JsonRpcRequest, JsonRpcResponse } from '@metamask/utils'; +/** + * Handles the `wallet_revokeSession` RPC method. + * + * @param request - The JSON-RPC request object. + * @param response - The JSON-RPC response object. + * @param _next - The next middleware function. + * @param end - The end callback function. + * @param hooks - The hooks object. + * @param hooks.revokePermission - The revokePermission function. + */ export async function walletRevokeSessionHandler( - request: JsonRpcRequest, - response: JsonRpcResponse, + request: JsonRpcRequestWithNetworkClientIdAndOrigin, + response: JsonRpcSuccess, _next: JsonRpcEngineNextCallback, end: JsonRpcEngineEndCallback, hooks: { - revokePermission: PermissionController['revokePermission'] + revokePermission: (origin: string, permissionName: string) => void; }, ) { try { diff --git a/packages/multichain/src/middlewares/MultichainMiddlewareManager.test.ts b/packages/multichain/src/middlewares/MultichainMiddlewareManager.test.ts index b00cd7ab4ed..2c42ec49bd6 100644 --- a/packages/multichain/src/middlewares/MultichainMiddlewareManager.test.ts +++ b/packages/multichain/src/middlewares/MultichainMiddlewareManager.test.ts @@ -1,7 +1,7 @@ -import { JsonRpcRequest } from '@metamask/utils'; -import MultichainMiddlewareManager, { - ExtendedJsonRpcMiddleware, -} from './MultichainMiddlewareManager'; +import type { JsonRpcRequest } from '@metamask/utils'; + +import type { ExtendedJsonRpcMiddleware } from './MultichainMiddlewareManager'; +import MultichainMiddlewareManager from './MultichainMiddlewareManager'; const scope = 'eip155:1'; const origin = 'example.com'; diff --git a/packages/multichain/src/middlewares/MultichainMiddlewareManager.ts b/packages/multichain/src/middlewares/MultichainMiddlewareManager.ts index e4c2663099b..0c92816630b 100644 --- a/packages/multichain/src/middlewares/MultichainMiddlewareManager.ts +++ b/packages/multichain/src/middlewares/MultichainMiddlewareManager.ts @@ -1,10 +1,14 @@ -import { JsonRpcMiddleware } from '@metamask/json-rpc-engine'; -import { ExternalScopeString } from '../scope'; -import { Json, JsonRpcParams } from '@metamask/utils'; +import type { JsonRpcMiddleware } from '@metamask/json-rpc-engine'; +import type { Json, JsonRpcParams } from '@metamask/utils'; + +import type { ExternalScopeString } from '../scope'; // Extend JsonRpcMiddleware to include the destroy method // this was introduced in 7.0.0 of json-rpc-engine: https://github.com/MetaMask/json-rpc-engine/blob/v7.0.0/src/JsonRpcEngine.ts#L29-L40 -export type ExtendedJsonRpcMiddleware = JsonRpcMiddleware & { +export type ExtendedJsonRpcMiddleware = JsonRpcMiddleware< + JsonRpcParams, + Json +> & { destroy?: () => void; }; @@ -110,8 +114,9 @@ export default class MultichainMiddlewareManager { if (middlewareEntry) { middlewareEntry.middleware(req, res, next, end); } else { - next(); + return next(); } + return undefined; }; middleware.destroy = this.removeMiddlewareByOriginAndTabId.bind( this, diff --git a/packages/multichain/src/middlewares/MultichainSubscriptionManager.test.ts b/packages/multichain/src/middlewares/MultichainSubscriptionManager.test.ts index 86fda171cec..c951b711af7 100644 --- a/packages/multichain/src/middlewares/MultichainSubscriptionManager.test.ts +++ b/packages/multichain/src/middlewares/MultichainSubscriptionManager.test.ts @@ -1,4 +1,5 @@ import createSubscriptionManager from '@metamask/eth-json-rpc-filters/subscriptionManager'; + import MultichainSubscriptionManager from './MultichainSubscriptionManager'; jest.mock('@metamask/eth-json-rpc-filters/subscriptionManager', () => @@ -63,7 +64,7 @@ describe('MultichainSubscriptionManager', () => { }); it('should subscribe to a scope, origin, and tabId', () => { - const { multichainSubscriptionManager} = + const { multichainSubscriptionManager } = createMultichainSubscriptionManager(); multichainSubscriptionManager.subscribe({ scope, origin, tabId }); const onNotificationSpy = jest.fn(); @@ -83,7 +84,7 @@ describe('MultichainSubscriptionManager', () => { }); it('should unsubscribe from a scope', () => { - const { multichainSubscriptionManager} = + const { multichainSubscriptionManager } = createMultichainSubscriptionManager(); multichainSubscriptionManager.subscribe({ scope, origin, tabId }); multichainSubscriptionManager.unsubscribeByScope(scope); @@ -92,7 +93,7 @@ describe('MultichainSubscriptionManager', () => { }); it('should unsubscribe from a scope and origin', () => { - const { multichainSubscriptionManager} = + const { multichainSubscriptionManager } = createMultichainSubscriptionManager(); multichainSubscriptionManager.subscribe({ scope, origin, tabId }); multichainSubscriptionManager.unsubscribeByScopeAndOrigin(scope, origin); @@ -105,7 +106,7 @@ describe('MultichainSubscriptionManager', () => { }); it('should unsubscribe from a origin and tabId', () => { - const { multichainSubscriptionManager} = + const { multichainSubscriptionManager } = createMultichainSubscriptionManager(); multichainSubscriptionManager.subscribe({ scope, origin, tabId }); multichainSubscriptionManager.unsubscribeByOriginAndTabId(origin, tabId); diff --git a/packages/multichain/src/middlewares/MultichainSubscriptionManager.ts b/packages/multichain/src/middlewares/MultichainSubscriptionManager.ts index 668aa431aa6..7ffb75b7230 100644 --- a/packages/multichain/src/middlewares/MultichainSubscriptionManager.ts +++ b/packages/multichain/src/middlewares/MultichainSubscriptionManager.ts @@ -1,9 +1,11 @@ -import EventEmitter from 'events'; -import { NetworkController } from '@metamask/network-controller'; -import SafeEventEmitter from '@metamask/safe-event-emitter'; -import { CaipChainId, Hex, parseCaipChainId } from '@metamask/utils'; import { toHex } from '@metamask/controller-utils'; -import { ExternalScopeString } from '../scope'; +import type { NetworkController } from '@metamask/network-controller'; +import SafeEventEmitter from '@metamask/safe-event-emitter'; +import type { CaipChainId, Hex } from '@metamask/utils'; +import { parseCaipChainId } from '@metamask/utils'; +import type EventEmitter from 'events'; + +import type { ExternalScopeString } from '../scope'; export type SubscriptionManager = { events: EventEmitter; diff --git a/packages/multichain/src/middlewares/multichainMethodCallValidator.ts b/packages/multichain/src/middlewares/multichainMethodCallValidator.ts index 7c68c56b916..a57ac7835a6 100644 --- a/packages/multichain/src/middlewares/multichainMethodCallValidator.ts +++ b/packages/multichain/src/middlewares/multichainMethodCallValidator.ts @@ -1,21 +1,22 @@ import { MultiChainOpenRPCDocument } from '@metamask/api-specs'; +import type { JsonRpcMiddleware } from '@metamask/json-rpc-engine'; import { rpcErrors } from '@metamask/rpc-errors'; -import { +import { isObject } from '@metamask/utils'; +import type { + Json, JsonRpcError, JsonRpcParams, JsonRpcRequest, - isObject, } from '@metamask/utils'; -import { +import type { ContentDescriptorObject, MethodObject, OpenrpcDocument, } from '@open-rpc/meta-schema'; import dereferenceDocument from '@open-rpc/schema-utils-js/build/dereference-document'; import { makeCustomResolver } from '@open-rpc/schema-utils-js/build/parse-open-rpc-document'; -import { JsonRpcMiddleware } from '@metamask/json-rpc-engine'; -import { Json } from '@metamask/utils'; -import { Schema, ValidationError, Validator } from 'jsonschema'; +import type { Schema, ValidationError } from 'jsonschema'; +import { Validator } from 'jsonschema'; const transformError = ( error: ValidationError, @@ -88,6 +89,7 @@ export const multichainMethodCallValidatorMiddleware: JsonRpcMiddleware< JsonRpcRequest, Json > = function (request, _response, next, end) { + // eslint-disable-next-line @typescript-eslint/no-floating-promises multichainMethodCallValidator(request.method, request.params).then( (errors) => { if (errors) { diff --git a/packages/multichain/src/scope/assert.test.ts b/packages/multichain/src/scope/assert.test.ts index 919b6e6a388..5ba9bdec8d8 100644 --- a/packages/multichain/src/scope/assert.test.ts +++ b/packages/multichain/src/scope/assert.test.ts @@ -1,6 +1,7 @@ import { JsonRpcError } from '@metamask/rpc-errors'; + import { assertScopeSupported, assertScopesSupported } from './assert'; -import { ScopeObject } from './scope'; +import type { ScopeObject } from './scope'; import * as Supported from './supported'; jest.mock('./supported', () => ({ @@ -133,10 +134,7 @@ describe('Scope Assert', () => { }, ); }).toThrow( - new JsonRpcError( - 5102, - 'Requested notifications are not supported', - ), + new JsonRpcError(5102, 'Requested notifications are not supported'), ); }); @@ -185,9 +183,7 @@ describe('Scope Assert', () => { isChainIdSupported, }, ); - }).toThrow( - new JsonRpcError(5100, 'Requested chains are not supported'), - ); + }).toThrow(new JsonRpcError(5100, 'Requested chains are not supported')); }); it('does not throw an error if all scopes are valid', () => { diff --git a/packages/multichain/src/scope/assert.ts b/packages/multichain/src/scope/assert.ts index 2724ecd2214..ea436fb9091 100644 --- a/packages/multichain/src/scope/assert.ts +++ b/packages/multichain/src/scope/assert.ts @@ -1,11 +1,12 @@ -import { Hex } from '@metamask/utils'; import { JsonRpcError } from '@metamask/rpc-errors'; +import type { Hex } from '@metamask/utils'; + +import type { ScopeObject, ScopesObject } from './scope'; import { isSupportedMethod, isSupportedNotification, isSupportedScopeString, } from './supported'; -import { ScopeObject, ScopesObject } from './scope'; export const assertScopeSupported = ( scopeString: string, @@ -50,10 +51,7 @@ export const assertScopeSupported = ( // When provider does not recognize one or more requested notification(s) // code = 5202 // message = "Unknown notification(s) requested" - throw new JsonRpcError( - 5102, - 'Requested notifications are not supported', - ); + throw new JsonRpcError(5102, 'Requested notifications are not supported'); } }; diff --git a/packages/multichain/src/scope/authorization.test.ts b/packages/multichain/src/scope/authorization.test.ts index 69e57dc32ca..318718133d3 100644 --- a/packages/multichain/src/scope/authorization.test.ts +++ b/packages/multichain/src/scope/authorization.test.ts @@ -1,11 +1,8 @@ -import * as Validation from './validation'; -import * as Transform from './transform'; +import { bucketScopes, validateAndFlattenScopes } from './authorization'; import * as Filter from './filter'; -import { - bucketScopes, - validateAndFlattenScopes, -} from './authorization'; -import { ExternalScopeObject } from './scope'; +import type { ExternalScopeObject } from './scope'; +import * as Transform from './transform'; +import * as Validation from './validation'; jest.mock('./validation', () => ({ validateScopes: jest.fn(), diff --git a/packages/multichain/src/scope/authorization.ts b/packages/multichain/src/scope/authorization.ts index b6c83cb1cf6..3b4f5e06199 100644 --- a/packages/multichain/src/scope/authorization.ts +++ b/packages/multichain/src/scope/authorization.ts @@ -1,8 +1,9 @@ -import { validateScopes } from './validation'; -import { ExternalScopesObject, ScopesObject, ScopedProperties } from './scope'; -import { flattenMergeScopes } from './transform'; +import type { Hex } from '@metamask/utils'; + import { bucketScopesBySupport } from './filter'; -import { Hex } from '@metamask/utils'; +import type { ExternalScopesObject, ScopesObject } from './scope'; +import { flattenMergeScopes } from './transform'; +import { validateScopes } from './validation'; export type Caip25Authorization = | { diff --git a/packages/multichain/src/scope/filter.ts b/packages/multichain/src/scope/filter.ts index 06b9795c497..ab5e889af17 100644 --- a/packages/multichain/src/scope/filter.ts +++ b/packages/multichain/src/scope/filter.ts @@ -1,6 +1,7 @@ -import { CaipChainId, Hex } from '@metamask/utils'; -import { ScopesObject } from './scope'; +import type { CaipChainId, Hex } from '@metamask/utils'; + import { assertScopeSupported } from './assert'; +import type { ScopesObject } from './scope'; export const bucketScopesBySupport = ( scopes: ScopesObject, diff --git a/packages/multichain/src/scope/scope.test.ts b/packages/multichain/src/scope/scope.test.ts index 2441c41c348..d3a58b3221a 100644 --- a/packages/multichain/src/scope/scope.test.ts +++ b/packages/multichain/src/scope/scope.test.ts @@ -6,7 +6,7 @@ describe('Scope', () => { expect(parseScopeString('abc')).toStrictEqual({ namespace: 'abc' }); }); - it('returns the namespace and reference if scopeString is a CAIP chain ID ', () => { + it('returns the namespace and reference if scopeString is a CAIP chain ID', () => { expect(parseScopeString('abc:foo')).toStrictEqual({ namespace: 'abc', reference: 'foo', diff --git a/packages/multichain/src/scope/scope.ts b/packages/multichain/src/scope/scope.ts index ae452ee6536..703b0d48f7f 100644 --- a/packages/multichain/src/scope/scope.ts +++ b/packages/multichain/src/scope/scope.ts @@ -1,13 +1,15 @@ import MetaMaskOpenRPCDocument from '@metamask/api-specs'; -import { +import type { CaipChainId, CaipReference, CaipAccountId, + KnownCaipNamespace, + CaipNamespace, +} from '@metamask/utils'; +import { isCaipNamespace, isCaipChainId, parseCaipChainId, - KnownCaipNamespace, - CaipNamespace, } from '@metamask/utils'; export type NonWalletKnownCaipNamespace = Exclude< @@ -22,7 +24,7 @@ export const KnownWalletRpcMethods: string[] = [ const WalletEip155Methods = ['wallet_addEthereumChain']; const Eip155Methods = MetaMaskOpenRPCDocument.methods - .map(({ name }: { name: string}) => name) + .map(({ name }: { name: string }) => name) .filter((method: string) => !WalletEip155Methods.includes(method)) .filter((method: string) => !KnownWalletRpcMethods.includes(method)); diff --git a/packages/multichain/src/scope/supported.test.ts b/packages/multichain/src/scope/supported.test.ts index 30b85491079..b8146ebd157 100644 --- a/packages/multichain/src/scope/supported.test.ts +++ b/packages/multichain/src/scope/supported.test.ts @@ -1,14 +1,14 @@ -import { - isSupportedMethod, - isSupportedNotification, - isSupportedScopeString, -} from './supported'; import { KnownNotifications, KnownRpcMethods, KnownWalletNamespaceRpcMethods, KnownWalletRpcMethods, } from './scope'; +import { + isSupportedMethod, + isSupportedNotification, + isSupportedScopeString, +} from './supported'; describe('Scope Support', () => { describe('isSupportedNotification', () => { @@ -16,18 +16,14 @@ describe('Scope Support', () => { 'returns true for each %s scope method', (scopeString: string, notifications: string[]) => { notifications.forEach((notification) => { - expect( - isSupportedNotification(scopeString, notification), - ).toStrictEqual(true); + expect(isSupportedNotification(scopeString, notification)).toBe(true); }); }, ); it('returns false otherwise', () => { - expect(isSupportedNotification('eip155', 'anything else')).toStrictEqual( - false, - ); - expect(isSupportedNotification('', '')).toStrictEqual(false); + expect(isSupportedNotification('eip155', 'anything else')).toBe(false); + expect(isSupportedNotification('', '')).toBe(false); }); }); @@ -36,14 +32,14 @@ describe('Scope Support', () => { 'returns true for each %s scoped method', (scopeString: string, methods: string[]) => { methods.forEach((method) => { - expect(isSupportedMethod(scopeString, method)).toStrictEqual(true); + expect(isSupportedMethod(scopeString, method)).toBe(true); }); }, ); it('returns true for each wallet scoped method', () => { KnownWalletRpcMethods.forEach((method) => { - expect(isSupportedMethod('wallet', method)).toStrictEqual(true); + expect(isSupportedMethod('wallet', method)).toBe(true); }); }); @@ -51,46 +47,42 @@ describe('Scope Support', () => { 'returns true for each wallet:%s scoped method', (scopeString: string, methods: string[]) => { methods.forEach((method) => { - expect( - isSupportedMethod(`wallet:${scopeString}`, method), - ).toStrictEqual(true); + expect(isSupportedMethod(`wallet:${scopeString}`, method)).toBe(true); }); }, ); it('returns false otherwise', () => { - expect(isSupportedMethod('eip155', 'anything else')).toStrictEqual(false); - expect(isSupportedMethod('', '')).toStrictEqual(false); + expect(isSupportedMethod('eip155', 'anything else')).toBe(false); + expect(isSupportedMethod('', '')).toBe(false); }); }); describe('isSupportedScopeString', () => { it('returns true for the wallet namespace', () => { - expect(isSupportedScopeString('wallet', jest.fn())).toStrictEqual(true); + expect(isSupportedScopeString('wallet', jest.fn())).toBe(true); }); it('returns false for the wallet namespace when a reference is included', () => { - expect(isSupportedScopeString('wallet:someref', jest.fn())).toStrictEqual( - false, - ); + expect(isSupportedScopeString('wallet:someref', jest.fn())).toBe(false); }); it('returns true for the ethereum namespace', () => { - expect(isSupportedScopeString('eip155', jest.fn())).toStrictEqual(true); + expect(isSupportedScopeString('eip155', jest.fn())).toBe(true); }); it('returns true for the ethereum namespace when a network client exists for the reference', () => { const isChainIdSupportedMock = jest.fn().mockReturnValue(true); - expect( - isSupportedScopeString('eip155:1', isChainIdSupportedMock), - ).toStrictEqual(true); + expect(isSupportedScopeString('eip155:1', isChainIdSupportedMock)).toBe( + true, + ); }); it('returns false for the ethereum namespace when a network client does not exist for the reference', () => { const isChainIdSupportedMock = jest.fn().mockReturnValue(false); - expect( - isSupportedScopeString('eip155:1', isChainIdSupportedMock), - ).toStrictEqual(false); + expect(isSupportedScopeString('eip155:1', isChainIdSupportedMock)).toBe( + false, + ); }); }); }); diff --git a/packages/multichain/src/scope/supported.ts b/packages/multichain/src/scope/supported.ts index 9ca98be6e23..6c4fd4cf765 100644 --- a/packages/multichain/src/scope/supported.ts +++ b/packages/multichain/src/scope/supported.ts @@ -1,29 +1,32 @@ +import { toHex } from '@metamask/controller-utils'; +import type { InternalAccount } from '@metamask/keyring-api'; +import type { CaipAccountId, Hex } from '@metamask/utils'; import { - CaipAccountId, - Hex, isCaipChainId, isCaipNamespace, KnownCaipNamespace, parseCaipAccountId, parseCaipChainId, } from '@metamask/utils'; -import { toHex } from '@metamask/controller-utils'; -import { InternalAccount } from '@metamask/keyring-api'; + +import type { NonWalletKnownCaipNamespace, ExternalScopeString } from './scope'; import { KnownNotifications, KnownRpcMethods, KnownWalletNamespaceRpcMethods, KnownWalletRpcMethods, - NonWalletKnownCaipNamespace, parseScopeString, - ExternalScopeString, } from './scope'; // TODO Maybe this gets DRY'ed into utils?.. It's used in TokenDetectionController too -function isEqualCaseInsensitive( - value1: string, - value2: string, -): boolean { +/** + * Checks if two strings are equal, ignoring case. + * + * @param value1 - The first string to compare. + * @param value2 - The second string to compare. + * @returns `true` if the strings are equal, ignoring case; otherwise, `false`. + */ +function isEqualCaseInsensitive(value1: string, value2: string): boolean { if (typeof value1 !== 'string' || typeof value2 !== 'string') { return false; } diff --git a/packages/multichain/src/scope/transform.test.ts b/packages/multichain/src/scope/transform.test.ts index df0b529822f..d092735eb67 100644 --- a/packages/multichain/src/scope/transform.test.ts +++ b/packages/multichain/src/scope/transform.test.ts @@ -1,4 +1,4 @@ -import { ExternalScopeObject } from './scope'; +import type { ExternalScopeObject } from './scope'; import { flattenScope, mergeScopes, diff --git a/packages/multichain/src/scope/transform.ts b/packages/multichain/src/scope/transform.ts index a31faf2d34c..e0811795056 100644 --- a/packages/multichain/src/scope/transform.ts +++ b/packages/multichain/src/scope/transform.ts @@ -1,15 +1,22 @@ -import { CaipReference } from '@metamask/utils'; +import type { CaipReference } from '@metamask/utils'; import { cloneDeep } from 'lodash'; -import { + +import type { ExternalScopeObject, ExternalScopesObject, ScopeString, ScopeObject, ScopesObject, - parseScopeString, } from './scope'; +import { parseScopeString } from './scope'; -// DRY THIS +// TODO: DRY THIS +/** + * Returns a list of unique items + * + * @param list - The list of items to filter + * @returns A list of unique items + */ function unique(list: T[]): T[] { return Array.from(new Set(list)); } diff --git a/packages/multichain/src/scope/validation.test.ts b/packages/multichain/src/scope/validation.test.ts index 507f24b328b..1c3f5653b17 100644 --- a/packages/multichain/src/scope/validation.test.ts +++ b/packages/multichain/src/scope/validation.test.ts @@ -1,8 +1,5 @@ -import { ExternalScopeObject } from './scope'; -import { - isValidScope, - validateScopes, -} from './validation'; +import type { ExternalScopeObject } from './scope'; +import { isValidScope, validateScopes } from './validation'; const validScopeString = 'eip155:1'; const validScopeObject: ExternalScopeObject = { @@ -128,7 +125,9 @@ describe('Scope Validation', () => { scopeString: string, scopeObject: unknown, ) => { - expect(isValidScope(scopeString, scopeObject as ExternalScopeObject)).toStrictEqual(expected); + expect( + isValidScope(scopeString, scopeObject as ExternalScopeObject), + ).toStrictEqual(expected); }, ); }); diff --git a/packages/multichain/src/scope/validation.ts b/packages/multichain/src/scope/validation.ts index 8a5ab1a1cdf..69bc3e1bb9c 100644 --- a/packages/multichain/src/scope/validation.ts +++ b/packages/multichain/src/scope/validation.ts @@ -1,10 +1,11 @@ import { isCaipReference } from '@metamask/utils'; -import { + +import type { ExternalScopeString, - parseScopeString, ExternalScopeObject, ExternalScopesObject, } from './scope'; +import { parseScopeString } from './scope'; export const isValidScope = ( scopeString: ExternalScopeString, diff --git a/yarn.lock b/yarn.lock index b43e7ce698f..90c0f15a0cd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3094,6 +3094,7 @@ __metadata: "@metamask/network-controller": "npm:^21.0.1" "@metamask/permission-controller": "npm:^11.0.2" "@metamask/rpc-errors": "npm:^6.3.1" + "@metamask/utils": "npm:^9.3.0" "@open-rpc/meta-schema": "npm:^1.14.6" "@open-rpc/schema-utils-js": "npm:^2.0.5" "@types/jest": "npm:^27.4.1" @@ -3867,6 +3868,23 @@ __metadata: languageName: node linkType: hard +"@metamask/utils@npm:^9.3.0": + version: 9.3.0 + resolution: "@metamask/utils@npm:9.3.0" + dependencies: + "@ethereumjs/tx": "npm:^4.2.0" + "@metamask/superstruct": "npm:^3.1.0" + "@noble/hashes": "npm:^1.3.1" + "@scure/base": "npm:^1.1.3" + "@types/debug": "npm:^4.1.7" + debug: "npm:^4.3.4" + pony-cause: "npm:^2.1.10" + semver: "npm:^7.5.4" + uuid: "npm:^9.0.1" + checksum: 10/ed6648cd973bbf3b4eb0e862903b795a99d27784c820e19f62f0bc0ddf353e98c2858d7e9aaebc0249a586391b344e35b9249d13c08e3ea0c74b23dc1c6b1558 + languageName: node + linkType: hard + "@ngraveio/bc-ur@npm:^1.1.5": version: 1.1.13 resolution: "@ngraveio/bc-ur@npm:1.1.13" From 06f68d15e60b1db70ace74ddbe485eb9913f7833 Mon Sep 17 00:00:00 2001 From: Jiexi Luan Date: Fri, 11 Oct 2024 09:22:14 -0700 Subject: [PATCH 2/9] Fix JsonRPCRequest typing --- ...caip-permission-adapter-middleware.test.ts | 13 ++++--- .../caip-permission-adapter-middleware.ts | 10 +++--- .../src/handlers/wallet-getSession.test.ts | 8 ++--- .../src/handlers/wallet-getSession.ts | 5 ++- .../src/handlers/wallet-invokeMethod.test.ts | 13 +++++-- .../src/handlers/wallet-invokeMethod.ts | 17 +++++---- .../src/handlers/wallet-revokeSession.test.ts | 7 ++-- .../src/handlers/wallet-revokeSession.ts | 6 ++-- .../MultichainMiddlewareManager.test.ts | 18 +++++----- .../MultichainMiddlewareManager.ts | 36 +++++++++++-------- 10 files changed, 73 insertions(+), 60 deletions(-) diff --git a/packages/multichain/src/adapters/caip-permission-adapter-middleware.test.ts b/packages/multichain/src/adapters/caip-permission-adapter-middleware.test.ts index ba34560346c..ea6318074ab 100644 --- a/packages/multichain/src/adapters/caip-permission-adapter-middleware.test.ts +++ b/packages/multichain/src/adapters/caip-permission-adapter-middleware.test.ts @@ -1,13 +1,11 @@ import { providerErrors } from '@metamask/rpc-errors'; +import type { JsonRpcRequest } from '@metamask/utils'; import { Caip25CaveatType, Caip25EndowmentPermissionName, } from '../caip25Permission'; -import { - caipPermissionAdapterMiddleware, - type JsonRpcRequestWithNetworkClientIdAndOrigin, -} from './caip-permission-adapter-middleware'; +import { caipPermissionAdapterMiddleware } from './caip-permission-adapter-middleware'; const baseRequest = { id: 1, @@ -64,7 +62,12 @@ const createMockedHandler = () => { chainId, }; }); - const handler = (request: JsonRpcRequestWithNetworkClientIdAndOrigin) => + const handler = ( + request: JsonRpcRequest & { + networkClientId: string; + origin: string; + }, + ) => caipPermissionAdapterMiddleware(request, {}, next, end, { getCaveat, getNetworkConfigurationByNetworkClientId, diff --git a/packages/multichain/src/adapters/caip-permission-adapter-middleware.ts b/packages/multichain/src/adapters/caip-permission-adapter-middleware.ts index fcdbc18e5eb..d92e0292e22 100644 --- a/packages/multichain/src/adapters/caip-permission-adapter-middleware.ts +++ b/packages/multichain/src/adapters/caip-permission-adapter-middleware.ts @@ -11,11 +11,6 @@ import { import type { ScopeString } from '../scope'; import { mergeScopes } from '../scope'; -export type JsonRpcRequestWithNetworkClientIdAndOrigin = JsonRpcRequest & { - networkClientId: string; - origin: string; -}; - /** * Middleware to handle CAIP-25 permission requests. * @@ -28,7 +23,10 @@ export type JsonRpcRequestWithNetworkClientIdAndOrigin = JsonRpcRequest & { * @param hooks.getNetworkConfigurationByNetworkClientId - Function to retrieve a network configuration. */ export async function caipPermissionAdapterMiddleware( - request: JsonRpcRequestWithNetworkClientIdAndOrigin, + request: JsonRpcRequest & { + networkClientId: string; + origin: string; + }, _response: unknown, next: () => Promise, end: (error?: Error) => void, diff --git a/packages/multichain/src/handlers/wallet-getSession.test.ts b/packages/multichain/src/handlers/wallet-getSession.test.ts index 742719eae1d..ebee666967b 100644 --- a/packages/multichain/src/handlers/wallet-getSession.test.ts +++ b/packages/multichain/src/handlers/wallet-getSession.test.ts @@ -1,17 +1,17 @@ -import { JsonRpcRequestWithNetworkClientIdAndOrigin } from 'src/adapters/caip-permission-adapter-middleware'; +import type { JsonRpcRequest } from '@metamask/utils'; + import { Caip25CaveatType, Caip25EndowmentPermissionName, } from '../caip25Permission'; import { walletGetSessionHandler } from './wallet-getSession'; -const baseRequest: JsonRpcRequestWithNetworkClientIdAndOrigin = { +const baseRequest: JsonRpcRequest & { origin: string } = { origin: 'http://test.com', jsonrpc: '2.0' as const, method: 'wallet_getSession', params: {}, id: 1, - networkClientId: 'mainnet', }; const createMockedHandler = () => { @@ -48,7 +48,7 @@ const createMockedHandler = () => { id: 1, jsonrpc: '2.0' as const, }; - const handler = (request: JsonRpcRequestWithNetworkClientIdAndOrigin) => + const handler = (request: JsonRpcRequest & { origin: string }) => walletGetSessionHandler(request, response, next, end, { getCaveat, }); diff --git a/packages/multichain/src/handlers/wallet-getSession.ts b/packages/multichain/src/handlers/wallet-getSession.ts index f80275d4e4a..7f0032d00d7 100644 --- a/packages/multichain/src/handlers/wallet-getSession.ts +++ b/packages/multichain/src/handlers/wallet-getSession.ts @@ -1,6 +1,5 @@ import type { Caveat } from '@metamask/permission-controller'; -import type { JsonRpcSuccess } from '@metamask/utils'; -import type { JsonRpcRequestWithNetworkClientIdAndOrigin } from 'src/adapters/caip-permission-adapter-middleware'; +import type { JsonRpcRequest, JsonRpcSuccess } from '@metamask/utils'; import type { Caip25CaveatValue } from '../caip25Permission'; import { @@ -21,7 +20,7 @@ import { mergeScopes } from '../scope'; * @param hooks.getCaveat - Function to retrieve a caveat. */ export async function walletGetSessionHandler( - request: JsonRpcRequestWithNetworkClientIdAndOrigin, + request: JsonRpcRequest & { origin: string }, response: JsonRpcSuccess<{ sessionScopes: ScopesObject }>, _next: () => void, end: () => void, diff --git a/packages/multichain/src/handlers/wallet-invokeMethod.test.ts b/packages/multichain/src/handlers/wallet-invokeMethod.test.ts index 1705e0b40de..ebffb0ece8b 100644 --- a/packages/multichain/src/handlers/wallet-invokeMethod.test.ts +++ b/packages/multichain/src/handlers/wallet-invokeMethod.test.ts @@ -1,14 +1,17 @@ import { providerErrors, rpcErrors } from '@metamask/rpc-errors'; +import type { JsonRpcRequest } from '@metamask/utils'; import { Caip25CaveatType, Caip25EndowmentPermissionName, } from '../caip25Permission'; import { walletInvokeMethodHandler } from './wallet-invokeMethod'; -import { JsonRpcRequestWithNetworkClientIdAndOrigin } from 'src/adapters/caip-permission-adapter-middleware'; const createMockedRequest = () => ({ + jsonrpc: '2.0' as const, + id: 0, origin: 'http://test.com', + method: 'wallet_invokeMethod', params: { scope: 'eip155:1', request: { @@ -56,8 +59,8 @@ const createMockedHandler = () => { const getSelectedNetworkClientId = jest .fn() .mockReturnValue('selectedNetworkClientId'); - const handler = (request: JsonRpcRequestWithNetworkClientIdAndOrigin) => - walletInvokeMethodHandler(request, {}, next, end, { + const handler = (request: JsonRpcRequest & { origin: string }) => + walletInvokeMethodHandler(request, { jsonrpc: '2.0', id: 1 }, next, end, { getCaveat, findNetworkClientIdByChainId, getSelectedNetworkClientId, @@ -182,6 +185,8 @@ describe('wallet_invokeMethod', () => { await handler(request); expect(request).toStrictEqual({ + jsonrpc: '2.0' as const, + id: 0, scope: 'eip155:1', origin: 'http://test.com', networkClientId: 'mainnet', @@ -250,6 +255,8 @@ describe('wallet_invokeMethod', () => { }; await handler(walletRequest); expect(walletRequest).toStrictEqual({ + jsonrpc: '2.0' as const, + id: 0, scope: 'wallet', origin: 'http://test.com', networkClientId: 'selectedNetworkClientId', diff --git a/packages/multichain/src/handlers/wallet-invokeMethod.ts b/packages/multichain/src/handlers/wallet-invokeMethod.ts index bd5b1f09d6a..55f60060831 100644 --- a/packages/multichain/src/handlers/wallet-invokeMethod.ts +++ b/packages/multichain/src/handlers/wallet-invokeMethod.ts @@ -1,8 +1,11 @@ import type { Caveat } from '@metamask/permission-controller'; import { providerErrors, rpcErrors } from '@metamask/rpc-errors'; -import type { JsonRpcSuccess, Json, JsonRpcRequest } from '@metamask/utils'; +import type { + Json, + JsonRpcRequest, + PendingJsonRpcResponse, +} from '@metamask/utils'; import { numberToHex } from '@metamask/utils'; -import type { JsonRpcRequestWithNetworkClientIdAndOrigin } from 'src/adapters/caip-permission-adapter-middleware'; import type { Caip25CaveatValue } from '../caip25Permission'; import { @@ -20,13 +23,13 @@ import { mergeScopes, parseScopeString } from '../scope'; * @param next - The next middleware function. * @param end - The end function. * @param hooks - The hooks object. - * @param hooks.getCaveat - * @param hooks.findNetworkClientIdByChainId - * @param hooks.getSelectedNetworkClientId + * @param hooks.getCaveat - the hook for getting a caveat from a permission for an origin. + * @param hooks.findNetworkClientIdByChainId - the hook for finding the networkClientId for a chainId. + * @param hooks.getSelectedNetworkClientId - the hook for getting the current globally selected networkClientId. */ export async function walletInvokeMethodHandler( - request: JsonRpcRequestWithNetworkClientIdAndOrigin, - _response: JsonRpcSuccess, + request: JsonRpcRequest & { origin: string }, + _response: PendingJsonRpcResponse, next: () => void, end: (error: Error) => void, hooks: { diff --git a/packages/multichain/src/handlers/wallet-revokeSession.test.ts b/packages/multichain/src/handlers/wallet-revokeSession.test.ts index 0713f2bf3ef..695d0eb4304 100644 --- a/packages/multichain/src/handlers/wallet-revokeSession.test.ts +++ b/packages/multichain/src/handlers/wallet-revokeSession.test.ts @@ -3,17 +3,16 @@ import { UnrecognizedSubjectError, } from '@metamask/permission-controller'; import { rpcErrors } from '@metamask/rpc-errors'; -import type { JsonRpcRequestWithNetworkClientIdAndOrigin } from 'src/adapters/caip-permission-adapter-middleware'; +import type { JsonRpcRequest } from '@metamask/utils'; import { Caip25EndowmentPermissionName } from '../caip25Permission'; import { walletRevokeSessionHandler } from './wallet-revokeSession'; -const baseRequest: JsonRpcRequestWithNetworkClientIdAndOrigin = { +const baseRequest: JsonRpcRequest & { origin: string } = { origin: 'http://test.com', params: {}, jsonrpc: '2.0' as const, id: 1, - networkClientId: 'mainnet', method: 'wallet_revokeSession', }; @@ -26,7 +25,7 @@ const createMockedHandler = () => { id: 1, jsonrpc: '2.0' as const, }; - const handler = (request: JsonRpcRequestWithNetworkClientIdAndOrigin) => + const handler = (request: JsonRpcRequest & { origin: string }) => walletRevokeSessionHandler(request, response, next, end, { revokePermission, }); diff --git a/packages/multichain/src/handlers/wallet-revokeSession.ts b/packages/multichain/src/handlers/wallet-revokeSession.ts index 3e52f43d73a..1aec0b7245b 100644 --- a/packages/multichain/src/handlers/wallet-revokeSession.ts +++ b/packages/multichain/src/handlers/wallet-revokeSession.ts @@ -2,14 +2,12 @@ import type { JsonRpcEngineNextCallback, JsonRpcEngineEndCallback, } from '@metamask/json-rpc-engine'; -import type { PermissionController } from '@metamask/permission-controller'; import { PermissionDoesNotExistError, UnrecognizedSubjectError, } from '@metamask/permission-controller'; import { rpcErrors } from '@metamask/rpc-errors'; -import type { JsonRpcSuccess, Json } from '@metamask/utils'; -import type { JsonRpcRequestWithNetworkClientIdAndOrigin } from 'src/adapters/caip-permission-adapter-middleware'; +import type { JsonRpcSuccess, Json, JsonRpcRequest } from '@metamask/utils'; import { Caip25EndowmentPermissionName } from '../caip25Permission'; @@ -24,7 +22,7 @@ import { Caip25EndowmentPermissionName } from '../caip25Permission'; * @param hooks.revokePermission - The revokePermission function. */ export async function walletRevokeSessionHandler( - request: JsonRpcRequestWithNetworkClientIdAndOrigin, + request: JsonRpcRequest & { origin: string }, response: JsonRpcSuccess, _next: JsonRpcEngineNextCallback, end: JsonRpcEngineEndCallback, diff --git a/packages/multichain/src/middlewares/MultichainMiddlewareManager.test.ts b/packages/multichain/src/middlewares/MultichainMiddlewareManager.test.ts index 2c42ec49bd6..c6097529946 100644 --- a/packages/multichain/src/middlewares/MultichainMiddlewareManager.test.ts +++ b/packages/multichain/src/middlewares/MultichainMiddlewareManager.test.ts @@ -1,5 +1,3 @@ -import type { JsonRpcRequest } from '@metamask/utils'; - import type { ExtendedJsonRpcMiddleware } from './MultichainMiddlewareManager'; import MultichainMiddlewareManager from './MultichainMiddlewareManager'; @@ -28,13 +26,13 @@ describe('MultichainMiddlewareManager', () => { const endSpy = jest.fn(); middleware( - { scope } as unknown as JsonRpcRequest, + { jsonrpc: '2.0' as const, id: 0, method: 'method', scope }, { jsonrpc: '2.0', id: 0 }, nextSpy, endSpy, ); expect(middlewareSpy).toHaveBeenCalledWith( - { scope } as unknown as JsonRpcRequest, + { jsonrpc: '2.0' as const, id: 0, method: 'method', scope }, { jsonrpc: '2.0', id: 0 }, nextSpy, endSpy, @@ -43,7 +41,7 @@ describe('MultichainMiddlewareManager', () => { expect(endSpy).not.toHaveBeenCalled(); }); - it('should remove middleware by origin and tabId when the multiplexing middleware is destroyed', () => { + it('should remove middleware by origin and tabId when the multiplexing middleware is destroyed', async () => { const multichainMiddlewareManager = new MultichainMiddlewareManager(); const middlewareSpy = jest.fn() as unknown as ExtendedJsonRpcMiddleware; multichainMiddlewareManager.addMiddleware({ @@ -59,13 +57,13 @@ describe('MultichainMiddlewareManager', () => { 123, ); - middleware.destroy?.(); + await middleware.destroy?.(); const nextSpy = jest.fn(); const endSpy = jest.fn(); middleware( - { scope } as unknown as JsonRpcRequest, + { jsonrpc: '2.0' as const, id: 0, method: 'method', scope }, { jsonrpc: '2.0', id: 0 }, nextSpy, endSpy, @@ -97,7 +95,7 @@ describe('MultichainMiddlewareManager', () => { const endSpy = jest.fn(); middleware( - { scope } as unknown as JsonRpcRequest, + { jsonrpc: '2.0' as const, id: 0, method: 'method', scope }, { jsonrpc: '2.0', id: 0 }, nextSpy, endSpy, @@ -129,7 +127,7 @@ describe('MultichainMiddlewareManager', () => { const endSpy = jest.fn(); middleware( - { scope } as unknown as JsonRpcRequest, + { jsonrpc: '2.0' as const, id: 0, method: 'method', scope }, { jsonrpc: '2.0', id: 0 }, nextSpy, endSpy, @@ -161,7 +159,7 @@ describe('MultichainMiddlewareManager', () => { const endSpy = jest.fn(); middleware( - { scope } as unknown as JsonRpcRequest, + { jsonrpc: '2.0' as const, id: 0, method: 'method', scope }, { jsonrpc: '2.0', id: 0 }, nextSpy, endSpy, diff --git a/packages/multichain/src/middlewares/MultichainMiddlewareManager.ts b/packages/multichain/src/middlewares/MultichainMiddlewareManager.ts index 0c92816630b..205c6a67518 100644 --- a/packages/multichain/src/middlewares/MultichainMiddlewareManager.ts +++ b/packages/multichain/src/middlewares/MultichainMiddlewareManager.ts @@ -1,15 +1,23 @@ -import type { JsonRpcMiddleware } from '@metamask/json-rpc-engine'; -import type { Json, JsonRpcParams } from '@metamask/utils'; +import type { + JsonRpcEngineEndCallback, + JsonRpcEngineNextCallback, +} from '@metamask/json-rpc-engine'; +import type { + Json, + JsonRpcRequest, + PendingJsonRpcResponse, +} from '@metamask/utils'; import type { ExternalScopeString } from '../scope'; -// Extend JsonRpcMiddleware to include the destroy method -// this was introduced in 7.0.0 of json-rpc-engine: https://github.com/MetaMask/json-rpc-engine/blob/v7.0.0/src/JsonRpcEngine.ts#L29-L40 -export type ExtendedJsonRpcMiddleware = JsonRpcMiddleware< - JsonRpcParams, - Json -> & { - destroy?: () => void; +export type ExtendedJsonRpcMiddleware = { + ( + req: JsonRpcRequest & { scope: string }, + res: PendingJsonRpcResponse, + next: JsonRpcEngineNextCallback, + end: JsonRpcEngineEndCallback, + ): void; + destroy?: () => void | Promise; }; type MiddlewareKey = { @@ -61,7 +69,10 @@ export default class MultichainMiddlewareManager { return; } - existingMiddlewareEntry.middleware.destroy?.(); + // When the destroy function on the middleware is async, + // we don't need to wait for it complete + // eslint-disable-next-line no-void + void existingMiddlewareEntry.middleware.destroy?.(); this.#removeMiddlewareEntry(middlewareKey); } @@ -101,10 +112,7 @@ export default class MultichainMiddlewareManager { tabId?: number, ) { const middleware: ExtendedJsonRpcMiddleware = (req, res, next, end) => { - const r = req as unknown as { - scope: string; - }; - const { scope } = r; + const { scope } = req; const middlewareEntry = this.#getMiddlewareEntry({ scope, origin, From 76151d9e5ba6e241bec0eabcf3b99e5208462811 Mon Sep 17 00:00:00 2001 From: Jiexi Luan Date: Fri, 11 Oct 2024 09:22:35 -0700 Subject: [PATCH 3/9] Fix scope typing --- packages/multichain/src/scope/assert.test.ts | 14 ++++++++------ packages/multichain/src/scope/scope.ts | 4 ++-- packages/multichain/src/scope/supported.ts | 3 +-- packages/multichain/src/scope/transform.ts | 4 ++-- .../multichain/src/scope/validation.test.ts | 18 +++++++++++------- 5 files changed, 24 insertions(+), 19 deletions(-) diff --git a/packages/multichain/src/scope/assert.test.ts b/packages/multichain/src/scope/assert.test.ts index 5ba9bdec8d8..75485352bac 100644 --- a/packages/multichain/src/scope/assert.test.ts +++ b/packages/multichain/src/scope/assert.test.ts @@ -163,12 +163,14 @@ describe('Scope Assert', () => { const isChainIdSupported = jest.fn(); it('does not throw an error if no scopes are defined', () => { - assertScopesSupported( - {}, - { - isChainIdSupported, - }, - ); + expect( + assertScopesSupported( + {}, + { + isChainIdSupported, + }, + ), + ).toBeUndefined(); }); it('throws an error if any scope is invalid', () => { diff --git a/packages/multichain/src/scope/scope.ts b/packages/multichain/src/scope/scope.ts index 703b0d48f7f..c899fa8a40e 100644 --- a/packages/multichain/src/scope/scope.ts +++ b/packages/multichain/src/scope/scope.ts @@ -12,9 +12,9 @@ import { parseCaipChainId, } from '@metamask/utils'; -export type NonWalletKnownCaipNamespace = Exclude< +export type NonWalletKnownCaipNamespace = Extract< KnownCaipNamespace, - KnownCaipNamespace.Wallet + KnownCaipNamespace.Eip155 >; export const KnownWalletRpcMethods: string[] = [ diff --git a/packages/multichain/src/scope/supported.ts b/packages/multichain/src/scope/supported.ts index 6c4fd4cf765..80ceb961f4d 100644 --- a/packages/multichain/src/scope/supported.ts +++ b/packages/multichain/src/scope/supported.ts @@ -1,5 +1,4 @@ import { toHex } from '@metamask/controller-utils'; -import type { InternalAccount } from '@metamask/keyring-api'; import type { CaipAccountId, Hex } from '@metamask/utils'; import { isCaipChainId, @@ -71,7 +70,7 @@ export const isSupportedScopeString = ( export const isSupportedAccount = ( account: CaipAccountId, - getInternalAccounts: () => InternalAccount[], + getInternalAccounts: () => { type: string; address: string }[], ) => { const { address, diff --git a/packages/multichain/src/scope/transform.ts b/packages/multichain/src/scope/transform.ts index e0811795056..097ad725d89 100644 --- a/packages/multichain/src/scope/transform.ts +++ b/packages/multichain/src/scope/transform.ts @@ -17,7 +17,7 @@ import { parseScopeString } from './scope'; * @param list - The list of items to filter * @returns A list of unique items */ -function unique(list: T[]): T[] { +function unique(list: Value[]): Value[] { return Array.from(new Set(list)); } @@ -39,7 +39,7 @@ export const flattenScope = ( const { namespace, reference } = parseScopeString(scopeString); // Scope is already a CAIP-2 ID and has no references to flatten - if (reference || !references) { + if (!namespace || reference || !references) { return { [scopeString]: scopeObject }; } diff --git a/packages/multichain/src/scope/validation.test.ts b/packages/multichain/src/scope/validation.test.ts index 1c3f5653b17..861ee542952 100644 --- a/packages/multichain/src/scope/validation.test.ts +++ b/packages/multichain/src/scope/validation.test.ts @@ -139,16 +139,20 @@ describe('Scope Validation', () => { }; it('does not throw an error if required scopes are defined but none are valid', () => { - validateScopes( - { 'eip155:1': {} as unknown as ExternalScopeObject }, - undefined, - ); + expect( + validateScopes( + { 'eip155:1': {} as unknown as ExternalScopeObject }, + undefined, + ), + ).toBeTruthy(); }); it('does not throw an error if optional scopes are defined but none are valid', () => { - validateScopes(undefined, { - 'eip155:1': {} as unknown as ExternalScopeObject, - }); + expect( + validateScopes(undefined, { + 'eip155:1': {} as unknown as ExternalScopeObject, + }), + ).toBeTruthy(); }); it('returns the valid required and optional scopes', () => { From b76a86d0be99bafcb27a9617e6659790fac48165 Mon Sep 17 00:00:00 2001 From: Jiexi Luan Date: Fri, 11 Oct 2024 09:22:46 -0700 Subject: [PATCH 4/9] rest --- packages/multichain/package.json | 27 ++++++---- .../multichain/src/caip25Permission.test.ts | 50 ++++++++++--------- packages/multichain/src/caip25Permission.ts | 8 +-- yarn.lock | 3 ++ 4 files changed, 51 insertions(+), 37 deletions(-) diff --git a/packages/multichain/package.json b/packages/multichain/package.json index face18630ff..fe3d48076da 100644 --- a/packages/multichain/package.json +++ b/packages/multichain/package.json @@ -18,14 +18,19 @@ "sideEffects": false, "exports": { ".": { - "import": "./dist/index.mjs", - "require": "./dist/index.js", - "types": "./dist/types/index.d.ts" + "import": { + "types": "./dist/index.d.mts", + "default": "./dist/index.mjs" + }, + "require": { + "types": "./dist/index.d.cts", + "default": "./dist/index.cjs" + } }, "./package.json": "./package.json" }, - "main": "./dist/index.js", - "types": "./dist/types/index.d.ts", + "main": "./dist/index.cjs", + "types": "./dist/index.d.cts", "files": [ "dist/" ], @@ -34,18 +39,22 @@ "build:docs": "typedoc", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/multichain", "publish:preview": "yarn npm publish --tag preview", - "test": "jest --reporters=jest-silent-reporter", - "test:clean": "jest --clearCache", - "test:verbose": "jest --verbose", - "test:watch": "jest --watch" + "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", + "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", + "test:verbose": "NODE_OPTIONS=--experimental-vm-modules jest --verbose", + "test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch", + "since-latest-release": "../../scripts/since-latest-release.sh" }, "dependencies": { "@metamask/api-specs": "^0.10.12", + "@metamask/controller-utils": "^11.3.0", "@metamask/eth-json-rpc-filters": "^7.0.0", "@metamask/json-rpc-engine": "^9.0.3", "@metamask/rpc-errors": "^6.3.1", + "@metamask/safe-event-emitter": "^3.0.0", "@metamask/utils": "^9.3.0", "@open-rpc/schema-utils-js": "^2.0.5", + "jsonschema": "^1.2.4", "lodash": "^4.17.21" }, "devDependencies": { diff --git a/packages/multichain/src/caip25Permission.test.ts b/packages/multichain/src/caip25Permission.test.ts index ace4068d89d..7e6d6f243d7 100644 --- a/packages/multichain/src/caip25Permission.test.ts +++ b/packages/multichain/src/caip25Permission.test.ts @@ -656,34 +656,36 @@ describe('endowment:caip25', () => { }, }, }); - validator({ - caveats: [ - { - type: Caip25CaveatType, - value: { - requiredScopes: { - 'eip155:1': { - methods: ['eth_chainId'], - notifications: [], - accounts: ['eip155:1:0xdead'], + expect( + validator({ + caveats: [ + { + type: Caip25CaveatType, + value: { + requiredScopes: { + 'eip155:1': { + methods: ['eth_chainId'], + notifications: [], + accounts: ['eip155:1:0xdead'], + }, }, - }, - optionalScopes: { - 'eip155:5': { - methods: [], - notifications: [], - accounts: ['eip155:5:0xbeef'], + optionalScopes: { + 'eip155:5': { + methods: [], + notifications: [], + accounts: ['eip155:5:0xbeef'], + }, }, + isMultichainOrigin: true, }, - isMultichainOrigin: true, }, - }, - ], - date: 1234, - id: '1', - invoker: 'test.com', - parentCapability: Caip25EndowmentPermissionName, - }); + ], + date: 1234, + id: '1', + invoker: 'test.com', + parentCapability: Caip25EndowmentPermissionName, + }), + ).toBeUndefined(); }); }); }); diff --git a/packages/multichain/src/caip25Permission.ts b/packages/multichain/src/caip25Permission.ts index b4e0a1ead45..d4cb66428cd 100644 --- a/packages/multichain/src/caip25Permission.ts +++ b/packages/multichain/src/caip25Permission.ts @@ -53,7 +53,7 @@ type Caip25EndowmentSpecification = ValidPermissionSpecification<{ * `endowment:caip25` returns nothing atm; * * @param builderOptions - The specification builder options. - * @param builderOptions.findNetworkClientIdByChainId + * @param builderOptions.findNetworkClientIdByChainId - The hook to find the networkClientId for a chainId. * @returns The specification for the `caip25` endowment. */ const specificationBuilder: PermissionSpecificationBuilder< @@ -140,9 +140,9 @@ export const Caip25CaveatMutatorFactories = { }, }; -const reduceKeysHelper = ( - acc: Record, - [key, value]: [K, V], +const reduceKeysHelper = ( + acc: Record, + [key, value]: [Key, Value], ) => { return { ...acc, diff --git a/yarn.lock b/yarn.lock index 90c0f15a0cd..4eb020e15de 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3089,17 +3089,20 @@ __metadata: dependencies: "@metamask/api-specs": "npm:^0.10.12" "@metamask/auto-changelog": "npm:^3.4.4" + "@metamask/controller-utils": "npm:^11.3.0" "@metamask/eth-json-rpc-filters": "npm:^7.0.0" "@metamask/json-rpc-engine": "npm:^9.0.3" "@metamask/network-controller": "npm:^21.0.1" "@metamask/permission-controller": "npm:^11.0.2" "@metamask/rpc-errors": "npm:^6.3.1" + "@metamask/safe-event-emitter": "npm:^3.0.0" "@metamask/utils": "npm:^9.3.0" "@open-rpc/meta-schema": "npm:^1.14.6" "@open-rpc/schema-utils-js": "npm:^2.0.5" "@types/jest": "npm:^27.4.1" deepmerge: "npm:^4.2.2" jest: "npm:^27.5.1" + jsonschema: "npm:^1.2.4" lodash: "npm:^4.17.21" ts-jest: "npm:^27.1.4" typedoc: "npm:^0.24.8" From 330a6f4cd605d53d2e5e6d50f1a1263334b0a28b Mon Sep 17 00:00:00 2001 From: Jiexi Luan Date: Fri, 11 Oct 2024 09:29:47 -0700 Subject: [PATCH 5/9] fix toBeTruthy --- packages/multichain/package.json | 4 ++-- packages/multichain/src/scope/validation.test.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/multichain/package.json b/packages/multichain/package.json index fe3d48076da..d1d332a5162 100644 --- a/packages/multichain/package.json +++ b/packages/multichain/package.json @@ -39,11 +39,11 @@ "build:docs": "typedoc", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/multichain", "publish:preview": "yarn npm publish --tag preview", + "since-latest-release": "../../scripts/since-latest-release.sh", "test": "NODE_OPTIONS=--experimental-vm-modules jest --reporters=jest-silent-reporter", "test:clean": "NODE_OPTIONS=--experimental-vm-modules jest --clearCache", "test:verbose": "NODE_OPTIONS=--experimental-vm-modules jest --verbose", - "test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch", - "since-latest-release": "../../scripts/since-latest-release.sh" + "test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch" }, "dependencies": { "@metamask/api-specs": "^0.10.12", diff --git a/packages/multichain/src/scope/validation.test.ts b/packages/multichain/src/scope/validation.test.ts index 861ee542952..f4f4ae63e34 100644 --- a/packages/multichain/src/scope/validation.test.ts +++ b/packages/multichain/src/scope/validation.test.ts @@ -144,7 +144,7 @@ describe('Scope Validation', () => { { 'eip155:1': {} as unknown as ExternalScopeObject }, undefined, ), - ).toBeTruthy(); + ).toStrictEqual({ validRequiredScopes: {}, validOptionalScopes: {} }); }); it('does not throw an error if optional scopes are defined but none are valid', () => { @@ -152,7 +152,7 @@ describe('Scope Validation', () => { validateScopes(undefined, { 'eip155:1': {} as unknown as ExternalScopeObject, }), - ).toBeTruthy(); + ).toStrictEqual({ validRequiredScopes: {}, validOptionalScopes: {} }); }); it('returns the valid required and optional scopes', () => { From e381430d3341156763b88a15182aca50a1dfe6cc Mon Sep 17 00:00:00 2001 From: Jiexi Luan Date: Fri, 11 Oct 2024 09:36:10 -0700 Subject: [PATCH 6/9] fix package.json --- packages/multichain/package.json | 3 +-- yarn.lock | 19 +------------------ 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/packages/multichain/package.json b/packages/multichain/package.json index d1d332a5162..d8ed672508a 100644 --- a/packages/multichain/package.json +++ b/packages/multichain/package.json @@ -49,10 +49,9 @@ "@metamask/api-specs": "^0.10.12", "@metamask/controller-utils": "^11.3.0", "@metamask/eth-json-rpc-filters": "^7.0.0", - "@metamask/json-rpc-engine": "^9.0.3", "@metamask/rpc-errors": "^6.3.1", "@metamask/safe-event-emitter": "^3.0.0", - "@metamask/utils": "^9.3.0", + "@metamask/utils": "^9.1.0", "@open-rpc/schema-utils-js": "^2.0.5", "jsonschema": "^1.2.4", "lodash": "^4.17.21" diff --git a/yarn.lock b/yarn.lock index 4eb020e15de..88a64433d35 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3096,7 +3096,7 @@ __metadata: "@metamask/permission-controller": "npm:^11.0.2" "@metamask/rpc-errors": "npm:^6.3.1" "@metamask/safe-event-emitter": "npm:^3.0.0" - "@metamask/utils": "npm:^9.3.0" + "@metamask/utils": "npm:^9.1.0" "@open-rpc/meta-schema": "npm:^1.14.6" "@open-rpc/schema-utils-js": "npm:^2.0.5" "@types/jest": "npm:^27.4.1" @@ -3871,23 +3871,6 @@ __metadata: languageName: node linkType: hard -"@metamask/utils@npm:^9.3.0": - version: 9.3.0 - resolution: "@metamask/utils@npm:9.3.0" - dependencies: - "@ethereumjs/tx": "npm:^4.2.0" - "@metamask/superstruct": "npm:^3.1.0" - "@noble/hashes": "npm:^1.3.1" - "@scure/base": "npm:^1.1.3" - "@types/debug": "npm:^4.1.7" - debug: "npm:^4.3.4" - pony-cause: "npm:^2.1.10" - semver: "npm:^7.5.4" - uuid: "npm:^9.0.1" - checksum: 10/ed6648cd973bbf3b4eb0e862903b795a99d27784c820e19f62f0bc0ddf353e98c2858d7e9aaebc0249a586391b344e35b9249d13c08e3ea0c74b23dc1c6b1558 - languageName: node - linkType: hard - "@ngraveio/bc-ur@npm:^1.1.5": version: 1.1.13 resolution: "@ngraveio/bc-ur@npm:1.1.13" From 25438fdfa70c0a969889968bc77da77beee89512 Mon Sep 17 00:00:00 2001 From: Jiexi Luan Date: Fri, 11 Oct 2024 09:41:13 -0700 Subject: [PATCH 7/9] add missing changelog:update script --- packages/multichain/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/multichain/package.json b/packages/multichain/package.json index d8ed672508a..e633a1bb2b7 100644 --- a/packages/multichain/package.json +++ b/packages/multichain/package.json @@ -37,6 +37,7 @@ "scripts": { "build": "ts-bridge --project tsconfig.build.json --verbose --clean --no-references", "build:docs": "typedoc", + "changelog:update": "../../scripts/update-changelog.sh @metamask/multichain", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/multichain", "publish:preview": "yarn npm publish --tag preview", "since-latest-release": "../../scripts/since-latest-release.sh", From 8a06a697bba1b7de62e9472d4fe6d21ac57435af Mon Sep 17 00:00:00 2001 From: Jiexi Luan Date: Fri, 11 Oct 2024 09:44:58 -0700 Subject: [PATCH 8/9] jest thresholds --- packages/multichain/jest.config.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/multichain/jest.config.js b/packages/multichain/jest.config.js index ca084133399..f8be8cb30ee 100644 --- a/packages/multichain/jest.config.js +++ b/packages/multichain/jest.config.js @@ -17,10 +17,10 @@ module.exports = merge(baseConfig, { // An object that configures minimum threshold enforcement for coverage results coverageThreshold: { global: { - branches: 100, - functions: 100, - lines: 100, - statements: 100, + branches: 83.05, + functions: 87.37, + lines: 86.73, + statements: 87.17, }, }, }); From a259924bea2b8cea9eb84f02d87663725c1dcecb Mon Sep 17 00:00:00 2001 From: Jiexi Luan Date: Fri, 11 Oct 2024 09:56:25 -0700 Subject: [PATCH 9/9] Fix build --- packages/multichain/tsconfig.build.json | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/multichain/tsconfig.build.json b/packages/multichain/tsconfig.build.json index 02a0eea03fe..f2108df2764 100644 --- a/packages/multichain/tsconfig.build.json +++ b/packages/multichain/tsconfig.build.json @@ -3,8 +3,16 @@ "compilerOptions": { "baseUrl": "./", "outDir": "./dist", - "rootDir": "./src" + "rootDir": "./src", + "resolveJsonModule": true }, - "references": [], + "references": [ + { + "path": "../network-controller/tsconfig.build.json" + }, + { + "path": "../permission-controller/tsconfig.build.json" + } + ], "include": ["../../types", "./src"] }