-
Notifications
You must be signed in to change notification settings - Fork 564
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add
snap_getInterfaceContext
(#2902)
Expose a new RPC method `snap_getInterfaceContext` that makes the `context` easily accessible outside `onUserInput`. Also adds the necessary wiring to make this RPC method work in the simulation environment. This feature will require the addition of a `getInterfaceContext` method hook in the clients. Progresses #2901
- Loading branch information
1 parent
126990b
commit 45db6e7
Showing
13 changed files
with
294 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
105 changes: 105 additions & 0 deletions
105
packages/snaps-rpc-methods/src/permitted/getInterfaceContext.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
import { JsonRpcEngine } from '@metamask/json-rpc-engine'; | ||
import { type GetInterfaceContextResult } from '@metamask/snaps-sdk'; | ||
import type { JsonRpcRequest, PendingJsonRpcResponse } from '@metamask/utils'; | ||
|
||
import type { GetInterfaceContextParameters } from './getInterfaceContext'; | ||
import { getInterfaceContextHandler } from './getInterfaceContext'; | ||
|
||
describe('snap_getInterfaceContext', () => { | ||
describe('getInterfaceContextHandler', () => { | ||
it('has the expected shape', () => { | ||
expect(getInterfaceContextHandler).toMatchObject({ | ||
methodNames: ['snap_getInterfaceContext'], | ||
implementation: expect.any(Function), | ||
hookNames: { | ||
getInterfaceContext: true, | ||
}, | ||
}); | ||
}); | ||
}); | ||
|
||
describe('implementation', () => { | ||
it('returns the result from the `getInterfaceContext` hook', async () => { | ||
const { implementation } = getInterfaceContextHandler; | ||
|
||
const getInterfaceContext = jest.fn().mockReturnValue({ foo: 'bar' }); | ||
|
||
const hooks = { | ||
getInterfaceContext, | ||
}; | ||
|
||
const engine = new JsonRpcEngine(); | ||
|
||
engine.push((request, response, next, end) => { | ||
const result = implementation( | ||
request as JsonRpcRequest<GetInterfaceContextParameters>, | ||
response as PendingJsonRpcResponse<GetInterfaceContextResult>, | ||
next, | ||
end, | ||
hooks, | ||
); | ||
|
||
result?.catch(end); | ||
}); | ||
|
||
const response = await engine.handle({ | ||
jsonrpc: '2.0', | ||
id: 1, | ||
method: 'snap_getInterfaceContext', | ||
params: { | ||
id: 'foo', | ||
}, | ||
}); | ||
|
||
expect(response).toStrictEqual({ | ||
jsonrpc: '2.0', | ||
id: 1, | ||
result: { foo: 'bar' }, | ||
}); | ||
}); | ||
|
||
it('throws on invalid params', async () => { | ||
const { implementation } = getInterfaceContextHandler; | ||
|
||
const getInterfaceContext = jest.fn().mockReturnValue({ foo: 'bar' }); | ||
|
||
const hooks = { | ||
getInterfaceContext, | ||
}; | ||
|
||
const engine = new JsonRpcEngine(); | ||
|
||
engine.push((request, response, next, end) => { | ||
const result = implementation( | ||
request as JsonRpcRequest<GetInterfaceContextParameters>, | ||
response as PendingJsonRpcResponse<GetInterfaceContextResult>, | ||
next, | ||
end, | ||
hooks, | ||
); | ||
|
||
result?.catch(end); | ||
}); | ||
|
||
const response = await engine.handle({ | ||
jsonrpc: '2.0', | ||
id: 1, | ||
method: 'snap_getInterfaceContext', | ||
params: { | ||
id: 42, | ||
}, | ||
}); | ||
|
||
expect(response).toStrictEqual({ | ||
error: { | ||
code: -32602, | ||
message: | ||
'Invalid params: At path: id -- Expected a string, but received: 42.', | ||
stack: expect.any(String), | ||
}, | ||
id: 1, | ||
jsonrpc: '2.0', | ||
}); | ||
}); | ||
}); | ||
}); |
100 changes: 100 additions & 0 deletions
100
packages/snaps-rpc-methods/src/permitted/getInterfaceContext.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
import type { JsonRpcEngineEndCallback } from '@metamask/json-rpc-engine'; | ||
import type { PermittedHandlerExport } from '@metamask/permission-controller'; | ||
import { rpcErrors } from '@metamask/rpc-errors'; | ||
import type { | ||
GetInterfaceContextParams, | ||
GetInterfaceContextResult, | ||
InterfaceContext, | ||
JsonRpcRequest, | ||
} from '@metamask/snaps-sdk'; | ||
import { type InferMatching } from '@metamask/snaps-utils'; | ||
import { StructError, create, object, string } from '@metamask/superstruct'; | ||
import type { PendingJsonRpcResponse } from '@metamask/utils'; | ||
|
||
import type { MethodHooksObject } from '../utils'; | ||
|
||
const hookNames: MethodHooksObject<GetInterfaceContextMethodHooks> = { | ||
getInterfaceContext: true, | ||
}; | ||
|
||
export type GetInterfaceContextMethodHooks = { | ||
/** | ||
* @param id - The interface ID. | ||
* @returns The interface context. | ||
*/ | ||
getInterfaceContext: (id: string) => InterfaceContext | null; | ||
}; | ||
|
||
export const getInterfaceContextHandler: PermittedHandlerExport< | ||
GetInterfaceContextMethodHooks, | ||
GetInterfaceContextParameters, | ||
GetInterfaceContextResult | ||
> = { | ||
methodNames: ['snap_getInterfaceContext'], | ||
implementation: getInterfaceContextImplementation, | ||
hookNames, | ||
}; | ||
|
||
const GetInterfaceContextParametersStruct = object({ | ||
id: string(), | ||
}); | ||
|
||
export type GetInterfaceContextParameters = InferMatching< | ||
typeof GetInterfaceContextParametersStruct, | ||
GetInterfaceContextParams | ||
>; | ||
|
||
/** | ||
* The `snap_getInterfaceContext` method implementation. | ||
* | ||
* @param req - The JSON-RPC request object. | ||
* @param res - The JSON-RPC response object. | ||
* @param _next - The `json-rpc-engine` "next" callback. Not used by this | ||
* function. | ||
* @param end - The `json-rpc-engine` "end" callback. | ||
* @param hooks - The RPC method hooks. | ||
* @param hooks.getInterfaceContext - The function to get the interface context. | ||
* @returns Noting. | ||
*/ | ||
function getInterfaceContextImplementation( | ||
req: JsonRpcRequest<GetInterfaceContextParameters>, | ||
res: PendingJsonRpcResponse<GetInterfaceContextResult>, | ||
_next: unknown, | ||
end: JsonRpcEngineEndCallback, | ||
{ getInterfaceContext }: GetInterfaceContextMethodHooks, | ||
): void { | ||
const { params } = req; | ||
|
||
try { | ||
const validatedParams = getValidatedParams(params); | ||
|
||
const { id } = validatedParams; | ||
|
||
res.result = getInterfaceContext(id); | ||
} catch (error) { | ||
return end(error); | ||
} | ||
|
||
return end(); | ||
} | ||
|
||
/** | ||
* Validate the getInterfaceContext method `params` and returns them cast to the correct | ||
* type. Throws if validation fails. | ||
* | ||
* @param params - The unvalidated params object from the method request. | ||
* @returns The validated getInterfaceContext method parameter object. | ||
*/ | ||
function getValidatedParams(params: unknown): GetInterfaceContextParameters { | ||
try { | ||
return create(params, GetInterfaceContextParametersStruct); | ||
} catch (error) { | ||
if (error instanceof StructError) { | ||
throw rpcErrors.invalidParams({ | ||
message: `Invalid params: ${error.message}.`, | ||
}); | ||
} | ||
/* istanbul ignore next */ | ||
throw rpcErrors.internal(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
15 changes: 15 additions & 0 deletions
15
packages/snaps-sdk/src/types/methods/get-interface-context.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import type { InterfaceContext } from '../interface'; | ||
|
||
/** | ||
* The request parameters for the `snap_getInterfaceContext` method. | ||
* | ||
* @property id - The interface id. | ||
*/ | ||
export type GetInterfaceContextParams = { | ||
id: string; | ||
}; | ||
|
||
/** | ||
* The result returned by the `snap_getInterfaceContext` method, which is the context for a given interface. | ||
*/ | ||
export type GetInterfaceContextResult = InterfaceContext | null; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.