Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | import type { Infer, Struct } from '@metamask/superstruct';
import type { JsonRpcParams, Json } from '@metamask/utils';
// Client-side types
export type MethodSignature<
Method extends string,
Params extends JsonRpcParams,
Result extends Json | Promise<Json>,
> = (method: Method, params: Params) => Result;
export type MethodSpec<
Method extends string,
Params extends JsonRpcParams,
Result extends Json | Promise<Json> | void | Promise<void>,
> = Result extends void | Promise<void>
? { method: Method; params: Struct<Params>; result?: undefined }
: {
method: Method;
params: Struct<Params>;
result: Struct<UnwrapPromise<Result>>;
};
// `any` can safely be used in constraints.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type SpecConstraint = MethodSpec<string, any, any>;
export type MethodSpecRecord<Methods extends SpecConstraint> = {
[Key in Methods['method']]: Extract<Methods, { method: Key }>;
};
type SpecRecordConstraint = MethodSpecRecord<SpecConstraint>;
export type ExtractMethodSignature<Spec extends SpecConstraint> =
Spec extends ((
method: infer Method extends string,
params: infer Params extends JsonRpcParams,
) => infer Result extends Json | Promise<Json>)
? MethodSignature<Method, Params, Result>
: never;
export type ExtractMethodSpec<
Specs extends SpecRecordConstraint,
Key extends keyof Specs = keyof Specs,
> = Specs[Key];
export type ExtractMethod<Specs extends SpecRecordConstraint> =
ExtractMethodSpec<Specs>['method'];
export type ExtractRequest<Specs extends SpecRecordConstraint> =
// Safe to use `any` in constraints.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
Extract<ExtractMethodSpec<Specs>, { result: Struct<any> }>['method'];
export type ExtractNotification<Specs extends SpecRecordConstraint> = Extract<
ExtractMethodSpec<Specs>,
{ result?: undefined }
>['method'];
export type ExtractParams<
Method extends string,
Specs extends SpecRecordConstraint,
> = Infer<ExtractMethodSpec<Specs, Method>['params']>;
export type ExtractResult<
Method extends string,
Specs extends SpecRecordConstraint,
> =
// Safe to use `any` in constraints.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
ExtractMethodSpec<Specs, Method> extends MethodSpec<any, any, infer Result>
? UnwrapPromise<Result>
: never;
export type HandlerFunction<
Params extends JsonRpcParams,
Result extends Json | Promise<Json> | void | Promise<void>,
Hooks extends Record<string, unknown>,
> = (hooks: Hooks, params: Params) => Result;
// Service-side types
export type Handler<
Method extends string,
Params extends JsonRpcParams,
Result extends Json | Promise<Json> | void | Promise<void>,
Hooks extends Record<string, unknown>,
> = MethodSpec<Method, Params, Result> & {
hooks: { [Key in keyof Hooks]: true };
implementation: HandlerFunction<Params, Result, Hooks>;
};
// `any` can safely be used in constraints.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type HandlerConstraint = Handler<string, any, any, any>;
export type HandlerRecord<Handlers extends HandlerConstraint> = {
[Key in Handlers['method']]: Extract<Handlers, { method: Key }>;
};
// Utils
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
export type MethodRequest<Method extends SpecConstraint> = {
id: string | number | null;
jsonrpc: '2.0';
method: Method['method'];
params: Infer<Method['params']>;
};
|