From ce0ce07a90e71888d87ab11a45d26c27059acafa Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Wed, 5 Nov 2025 10:31:29 +0100 Subject: [PATCH 1/6] feat: Include versions in snap_getClientStatus --- .../src/permitted/getClientStatus.test.ts | 10 +++++++++- .../src/permitted/getClientStatus.ts | 17 +++++++++++++++-- .../src/types/methods/get-client-status.ts | 7 ++++++- 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/packages/snaps-rpc-methods/src/permitted/getClientStatus.test.ts b/packages/snaps-rpc-methods/src/permitted/getClientStatus.test.ts index 501d2e86aa..d9cc55fc62 100644 --- a/packages/snaps-rpc-methods/src/permitted/getClientStatus.test.ts +++ b/packages/snaps-rpc-methods/src/permitted/getClientStatus.test.ts @@ -1,5 +1,6 @@ import { JsonRpcEngine } from '@metamask/json-rpc-engine'; import type { GetClientStatusResult } from '@metamask/snaps-sdk'; +import { getPlatformVersion } from '@metamask/snaps-utils'; import type { PendingJsonRpcResponse } from '@metamask/utils'; import { getClientStatusHandler } from './getClientStatus'; @@ -24,9 +25,11 @@ describe('snap_getClientStatus', () => { const getIsLocked = jest.fn().mockReturnValue(true); const getIsActive = jest.fn().mockReturnValue(false); + const getVersion = jest.fn().mockReturnValue('13.9.0'); const hooks = { getIsLocked, getIsActive, + getVersion, }; const engine = new JsonRpcEngine(); @@ -51,7 +54,12 @@ describe('snap_getClientStatus', () => { expect(response).toStrictEqual({ jsonrpc: '2.0', id: 1, - result: { locked: true, active: false }, + result: { + clientVersion: '13.9.0', + platformVersion: getPlatformVersion(), + locked: true, + active: false, + }, }); }); }); diff --git a/packages/snaps-rpc-methods/src/permitted/getClientStatus.ts b/packages/snaps-rpc-methods/src/permitted/getClientStatus.ts index 48e0bc5641..f922119ce0 100644 --- a/packages/snaps-rpc-methods/src/permitted/getClientStatus.ts +++ b/packages/snaps-rpc-methods/src/permitted/getClientStatus.ts @@ -1,6 +1,7 @@ import type { JsonRpcEngineEndCallback } from '@metamask/json-rpc-engine'; import type { PermittedHandlerExport } from '@metamask/permission-controller'; import type { GetClientStatusResult } from '@metamask/snaps-sdk'; +import { getPlatformVersion } from '@metamask/snaps-utils'; import type { JsonRpcParams, JsonRpcRequest, @@ -12,6 +13,7 @@ import type { MethodHooksObject } from '../utils'; const hookNames: MethodHooksObject = { getIsLocked: true, getIsActive: true, + getVersion: true, }; /** @@ -37,6 +39,11 @@ export type GetClientStatusHooks = { * @returns Whether the client is active or not. */ getIsActive: () => boolean; + + /** + * @returns The version string for the client. + */ + getVersion: () => string; }; /** @@ -51,6 +58,7 @@ export type GetClientStatusHooks = { * @param hooks - The RPC method hooks. * @param hooks.getIsLocked - A function that returns whether the client is locked or not. * @param hooks.getIsActive - A function that returns whether the client is opened or not. + * @param hooks.getVersion - A function that returns the client version. * @returns Nothing. */ async function getClientStatusImplementation( @@ -58,8 +66,13 @@ async function getClientStatusImplementation( response: PendingJsonRpcResponse, _next: unknown, end: JsonRpcEngineEndCallback, - { getIsLocked, getIsActive }: GetClientStatusHooks, + { getIsLocked, getIsActive, getVersion }: GetClientStatusHooks, ): Promise { - response.result = { locked: getIsLocked(), active: getIsActive() }; + response.result = { + locked: getIsLocked(), + active: getIsActive(), + clientVersion: getVersion(), + platformVersion: getPlatformVersion(), + }; return end(); } diff --git a/packages/snaps-sdk/src/types/methods/get-client-status.ts b/packages/snaps-sdk/src/types/methods/get-client-status.ts index 8470d41196..910537f2c0 100644 --- a/packages/snaps-sdk/src/types/methods/get-client-status.ts +++ b/packages/snaps-sdk/src/types/methods/get-client-status.ts @@ -10,4 +10,9 @@ export type GetClientStatusParams = never; * * It returns an object containing useful information about the client. */ -export type GetClientStatusResult = { locked: boolean; active: boolean }; +export type GetClientStatusResult = { + clientVersion: string; + platformVersion: string; + locked: boolean; + active: boolean; +}; From 9a5421aeee8143b3b085ac72c9a89361c2cd2c74 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Wed, 5 Nov 2025 10:53:32 +0100 Subject: [PATCH 2/6] Add hook for simulation --- .../snaps-simulation/src/simulation.test.ts | 23 +++++++++++++++++++ packages/snaps-simulation/src/simulation.ts | 8 +++++++ 2 files changed, 31 insertions(+) diff --git a/packages/snaps-simulation/src/simulation.test.ts b/packages/snaps-simulation/src/simulation.test.ts index b263416c74..c18ebc1516 100644 --- a/packages/snaps-simulation/src/simulation.test.ts +++ b/packages/snaps-simulation/src/simulation.test.ts @@ -334,6 +334,29 @@ describe('getPermittedHooks', () => { await close(); }); + it('returns the `getVersion` hook', async () => { + const { snapId, close } = await getMockServer({ + manifest: getSnapManifest(), + }); + + const location = detectSnapLocation(snapId, { + allowLocal: true, + }); + + const snapFiles = await fetchSnap(snapId, location); + + const { getVersion } = getPermittedHooks( + snapId, + snapFiles, + controllerMessenger, + runSaga, + ); + + expect(getVersion()).toBe('13.9.0'); + + await close(); + }); + it('returns the `getSnapFile` hook', async () => { const value = JSON.stringify({ bar: 'baz' }); const { snapId, close } = await getMockServer({ diff --git a/packages/snaps-simulation/src/simulation.ts b/packages/snaps-simulation/src/simulation.ts index e6e49328dd..3f95e2fc26 100644 --- a/packages/snaps-simulation/src/simulation.ts +++ b/packages/snaps-simulation/src/simulation.ts @@ -195,6 +195,13 @@ export type PermittedMiddlewareHooks = { */ getIsActive: () => boolean; + /** + * A hook that returns the client version. + * + * @returns A string that corresponds to the client version. + */ + getVersion: () => string; + /** * A hook that returns the Snap's auxiliary file for the given path. This hook * is bound to the Snap ID. @@ -486,6 +493,7 @@ export function getPermittedHooks( getUnlockPromise: asyncResolve(), getIsLocked: () => false, getIsActive: () => true, + getVersion: () => '13.9.0', getSnapFile: async (path: string, encoding: AuxiliaryFileEncoding) => await getSnapFile(snapFiles.auxiliaryFiles, path, encoding), From b4ca7349a1aee9f2f34131c96b3611fb20f24ec4 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Wed, 5 Nov 2025 11:26:49 +0100 Subject: [PATCH 3/6] Fix E2E --- packages/examples/packages/client-status/package.json | 1 + packages/examples/packages/client-status/src/index.test.ts | 3 +++ yarn.lock | 1 + 3 files changed, 5 insertions(+) diff --git a/packages/examples/packages/client-status/package.json b/packages/examples/packages/client-status/package.json index 6fd26ee6a2..ea1909448b 100644 --- a/packages/examples/packages/client-status/package.json +++ b/packages/examples/packages/client-status/package.json @@ -51,6 +51,7 @@ "@metamask/auto-changelog": "^5.0.2", "@metamask/snaps-cli": "workspace:^", "@metamask/snaps-jest": "workspace:^", + "@metamask/snaps-utils": "workspace:^", "@swc/core": "1.11.31", "@swc/jest": "^0.2.38", "@types/node": "18.14.2", diff --git a/packages/examples/packages/client-status/src/index.test.ts b/packages/examples/packages/client-status/src/index.test.ts index 59980d34a7..d3503021e9 100644 --- a/packages/examples/packages/client-status/src/index.test.ts +++ b/packages/examples/packages/client-status/src/index.test.ts @@ -1,5 +1,6 @@ import { expect } from '@jest/globals'; import { installSnap } from '@metamask/snaps-jest'; +import { getPlatformVersion } from '@metamask/snaps-utils'; describe('onRpcRequest', () => { it('throws an error if the requested method does not exist', async () => { @@ -31,6 +32,8 @@ describe('onRpcRequest', () => { expect(response).toRespondWith({ locked: false, active: true, + clientVersion: '13.9.0', + platformVersion: getPlatformVersion(), }); }); }); diff --git a/yarn.lock b/yarn.lock index 9ea126c958..8c3bab372f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2971,6 +2971,7 @@ __metadata: "@metamask/snaps-cli": "workspace:^" "@metamask/snaps-jest": "workspace:^" "@metamask/snaps-sdk": "workspace:^" + "@metamask/snaps-utils": "workspace:^" "@swc/core": "npm:1.11.31" "@swc/jest": "npm:^0.2.38" "@types/node": "npm:18.14.2" From 7c610fbcfaa6b5ea86b70e2a85ebf7239b64bdfc Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Wed, 5 Nov 2025 11:33:38 +0100 Subject: [PATCH 4/6] Use 13.6.0-flask.0 as the mock version --- packages/examples/packages/client-status/src/index.test.ts | 2 +- .../snaps-rpc-methods/src/permitted/getClientStatus.test.ts | 4 ++-- packages/snaps-simulation/src/simulation.test.ts | 2 +- packages/snaps-simulation/src/simulation.ts | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/examples/packages/client-status/src/index.test.ts b/packages/examples/packages/client-status/src/index.test.ts index d3503021e9..d81fb9802b 100644 --- a/packages/examples/packages/client-status/src/index.test.ts +++ b/packages/examples/packages/client-status/src/index.test.ts @@ -32,7 +32,7 @@ describe('onRpcRequest', () => { expect(response).toRespondWith({ locked: false, active: true, - clientVersion: '13.9.0', + clientVersion: '13.6.0-flask.0', platformVersion: getPlatformVersion(), }); }); diff --git a/packages/snaps-rpc-methods/src/permitted/getClientStatus.test.ts b/packages/snaps-rpc-methods/src/permitted/getClientStatus.test.ts index d9cc55fc62..9c85c80f89 100644 --- a/packages/snaps-rpc-methods/src/permitted/getClientStatus.test.ts +++ b/packages/snaps-rpc-methods/src/permitted/getClientStatus.test.ts @@ -25,7 +25,7 @@ describe('snap_getClientStatus', () => { const getIsLocked = jest.fn().mockReturnValue(true); const getIsActive = jest.fn().mockReturnValue(false); - const getVersion = jest.fn().mockReturnValue('13.9.0'); + const getVersion = jest.fn().mockReturnValue('13.6.0-flask.0'); const hooks = { getIsLocked, getIsActive, @@ -55,7 +55,7 @@ describe('snap_getClientStatus', () => { jsonrpc: '2.0', id: 1, result: { - clientVersion: '13.9.0', + clientVersion: '13.6.0-flask.0', platformVersion: getPlatformVersion(), locked: true, active: false, diff --git a/packages/snaps-simulation/src/simulation.test.ts b/packages/snaps-simulation/src/simulation.test.ts index c18ebc1516..995eceb548 100644 --- a/packages/snaps-simulation/src/simulation.test.ts +++ b/packages/snaps-simulation/src/simulation.test.ts @@ -352,7 +352,7 @@ describe('getPermittedHooks', () => { runSaga, ); - expect(getVersion()).toBe('13.9.0'); + expect(getVersion()).toBe('13.6.0-flask.0'); await close(); }); diff --git a/packages/snaps-simulation/src/simulation.ts b/packages/snaps-simulation/src/simulation.ts index 3f95e2fc26..7cdec6dba3 100644 --- a/packages/snaps-simulation/src/simulation.ts +++ b/packages/snaps-simulation/src/simulation.ts @@ -493,7 +493,7 @@ export function getPermittedHooks( getUnlockPromise: asyncResolve(), getIsLocked: () => false, getIsActive: () => true, - getVersion: () => '13.9.0', + getVersion: () => '13.6.0-flask.0', getSnapFile: async (path: string, encoding: AuxiliaryFileEncoding) => await getSnapFile(snapFiles.auxiliaryFiles, path, encoding), From c76bb9c78cc848767790825a1cee9a305bb92112 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Wed, 5 Nov 2025 12:21:43 +0100 Subject: [PATCH 5/6] Add JSDoc for each property --- .../snaps-sdk/src/types/methods/get-client-status.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/snaps-sdk/src/types/methods/get-client-status.ts b/packages/snaps-sdk/src/types/methods/get-client-status.ts index 910537f2c0..8ffed94706 100644 --- a/packages/snaps-sdk/src/types/methods/get-client-status.ts +++ b/packages/snaps-sdk/src/types/methods/get-client-status.ts @@ -11,8 +11,20 @@ export type GetClientStatusParams = never; * It returns an object containing useful information about the client. */ export type GetClientStatusResult = { + /** + * The semantic version of the client that the Snap is running in. + */ clientVersion: string; + /** + * The Snaps Platform version that the client is running. + */ platformVersion: string; + /** + * A boolean flag that indicates whether the client is locked or not. + */ locked: boolean; + /** + * A boolean flag that indicates whether the client is active or not. + */ active: boolean; }; From ed97239af206ab939584f8d9c238eddea7d21a37 Mon Sep 17 00:00:00 2001 From: Frederik Bolding Date: Wed, 5 Nov 2025 12:26:10 +0100 Subject: [PATCH 6/6] Improve assertion --- packages/snaps-rpc-methods/src/permitted/getClientStatus.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/snaps-rpc-methods/src/permitted/getClientStatus.test.ts b/packages/snaps-rpc-methods/src/permitted/getClientStatus.test.ts index 9c85c80f89..863c862655 100644 --- a/packages/snaps-rpc-methods/src/permitted/getClientStatus.test.ts +++ b/packages/snaps-rpc-methods/src/permitted/getClientStatus.test.ts @@ -14,6 +14,7 @@ describe('snap_getClientStatus', () => { hookNames: { getIsLocked: true, getIsActive: true, + getVersion: true, }, }); });