diff --git a/app/scripts/lib/rpc-method-middleware/handlers/get-provider-state.js b/app/scripts/lib/rpc-method-middleware/handlers/get-provider-state.js deleted file mode 100644 index 70dbb7b16cfa..000000000000 --- a/app/scripts/lib/rpc-method-middleware/handlers/get-provider-state.js +++ /dev/null @@ -1,49 +0,0 @@ -import { MESSAGE_TYPE } from '../../../../../shared/constants/app'; - -/** - * This RPC method gets background state relevant to the provider. - * The background sends RPC notifications on state changes, but the provider - * first requests state on initialization. - */ - -const getProviderState = { - methodNames: [MESSAGE_TYPE.GET_PROVIDER_STATE], - implementation: getProviderStateHandler, - hookNames: { - getProviderState: true, - }, -}; -export default getProviderState; - -/** - * @typedef {object} ProviderStateHandlerResult - * @property {string} chainId - The current chain ID. - * @property {boolean} isUnlocked - Whether the extension is unlocked or not. - * @property {string} networkVersion - The current network ID. - */ - -/** - * @typedef {object} ProviderStateHandlerOptions - * @property {() => ProviderStateHandlerResult} getProviderState - A function that - * gets the current provider state. - */ - -/** - * @param {import('json-rpc-engine').JsonRpcRequest<[]>} req - The JSON-RPC request object. - * @param {import('json-rpc-engine').JsonRpcResponse} res - The JSON-RPC response object. - * @param {Function} _next - The json-rpc-engine 'next' callback. - * @param {Function} end - The json-rpc-engine 'end' callback. - * @param {ProviderStateHandlerOptions} options - */ -async function getProviderStateHandler( - req, - res, - _next, - end, - { getProviderState: _getProviderState }, -) { - res.result = { - ...(await _getProviderState(req.origin)), - }; - return end(); -} diff --git a/app/scripts/lib/rpc-method-middleware/handlers/get-provider-state.test.ts b/app/scripts/lib/rpc-method-middleware/handlers/get-provider-state.test.ts new file mode 100644 index 000000000000..f3d76a09f5fc --- /dev/null +++ b/app/scripts/lib/rpc-method-middleware/handlers/get-provider-state.test.ts @@ -0,0 +1,56 @@ +import { PendingJsonRpcResponse } from '@metamask/utils'; +import { JsonRpcEngineEndCallback } from 'json-rpc-engine'; +import getProviderState, { + GetProviderState, + ProviderStateHandlerResult, +} from './get-provider-state'; +import { HandlerRequestType } from './types'; + +describe('getProviderState', () => { + let mockEnd: JsonRpcEngineEndCallback; + let mockGetProviderState: GetProviderState; + + beforeEach(() => { + mockEnd = jest.fn(); + mockGetProviderState = jest.fn().mockResolvedValue({ + chainId: '0x539', + isUnlocked: true, + networkVersion: '', + accounts: [], + }); + }); + + it('should call getProviderState when the handler is invoked', async () => { + const req: HandlerRequestType = { + origin: 'testOrigin', + params: [], + id: '22', + jsonrpc: '2.0', + method: 'metamask_getProviderState', + }; + + const res: PendingJsonRpcResponse = { + id: '22', + jsonrpc: '2.0', + result: { + chainId: '0x539', + isUnlocked: true, + networkVersion: '', + accounts: [], + }, + }; + + await getProviderState.implementation(req, res, jest.fn(), mockEnd, { + getProviderState: mockGetProviderState, + }); + + expect(mockGetProviderState).toHaveBeenCalledWith(req.origin); + expect(res.result).toStrictEqual({ + chainId: '0x539', + isUnlocked: true, + networkVersion: '', + accounts: [], + }); + expect(mockEnd).toHaveBeenCalled(); + }); +}); diff --git a/app/scripts/lib/rpc-method-middleware/handlers/get-provider-state.ts b/app/scripts/lib/rpc-method-middleware/handlers/get-provider-state.ts new file mode 100644 index 000000000000..530b48b25164 --- /dev/null +++ b/app/scripts/lib/rpc-method-middleware/handlers/get-provider-state.ts @@ -0,0 +1,81 @@ +import type { + JsonRpcEngineNextCallback, + JsonRpcEngineEndCallback, +} from 'json-rpc-engine'; +import type { + PendingJsonRpcResponse, + JsonRpcParams, + Hex, +} from '@metamask/utils'; +import { OriginString } from '@metamask/permission-controller'; +import { MESSAGE_TYPE } from '../../../../../shared/constants/app'; +import { + HandlerWrapper, + HandlerRequestType as ProviderStateHandlerRequest, +} from './types'; + +/** + * @property chainId - The current chain ID. + * @property isUnlocked - Whether the extension is unlocked or not. + * @property networkVersion - The current network ID. + * @property accounts - List of permitted accounts for the specified origin. + */ +export type ProviderStateHandlerResult = { + chainId: Hex; + isUnlocked: boolean; + networkVersion: string; + accounts: string[]; +}; + +export type GetProviderState = ( + origin: OriginString, +) => Promise; + +type GetProviderStateConstraint = + { + implementation: ( + _req: ProviderStateHandlerRequest, + res: PendingJsonRpcResponse, + _next: JsonRpcEngineNextCallback, + end: JsonRpcEngineEndCallback, + { _getProviderState }: Record, + ) => Promise; + } & HandlerWrapper; + +/** + * This RPC method gets background state relevant to the provider. + * The background sends RPC notifications on state changes, but the provider + * first requests state on initialization. + */ +const getProviderState = { + methodNames: [MESSAGE_TYPE.GET_PROVIDER_STATE], + implementation: getProviderStateHandler, + hookNames: { + getProviderState: true, + }, +} satisfies GetProviderStateConstraint; + +export default getProviderState; + +/** + * @param req - The JSON-RPC request object. + * @param res - The JSON-RPC response object. + * @param _next - The json-rpc-engine 'next' callback. + * @param end - The json-rpc-engine 'end' callback. + * @param options + * @param options.getProviderState - An async function that gets the current provider state. + */ +async function getProviderStateHandler< + Params extends JsonRpcParams = JsonRpcParams, +>( + req: ProviderStateHandlerRequest, + res: PendingJsonRpcResponse, + _next: JsonRpcEngineNextCallback, + end: JsonRpcEngineEndCallback, + { getProviderState: _getProviderState }: Record, +): Promise { + res.result = { + ...(await _getProviderState(req.origin)), + }; + return end(); +} diff --git a/app/scripts/lib/rpc-method-middleware/handlers/types.ts b/app/scripts/lib/rpc-method-middleware/handlers/types.ts index 5b7a2a7494d4..46ceef442ec2 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/types.ts +++ b/app/scripts/lib/rpc-method-middleware/handlers/types.ts @@ -1,6 +1,13 @@ +import { OriginString } from '@metamask/permission-controller'; +import { JsonRpcParams, JsonRpcRequest } from '@metamask/utils'; import { MessageType } from '../../../../../shared/constants/app'; export type HandlerWrapper = { methodNames: [MessageType] | MessageType[]; hookNames: Record; }; + +export type HandlerRequestType = + Required> & { + origin: OriginString; + };