UNPKG

ox

Version:

Ethereum Standard Library

142 lines 4.61 kB
import * as Errors from '../core/Errors.js'; import * as eth from './internal/rpcSchemas/Eth.js'; import { from as fromItem } from './internal/rpcSchemas/from.js'; import * as wallet from './internal/rpcSchemas/Wallet.js'; import * as z from 'zod/mini'; // eslint-disable-next-line jsdoc-js/require-jsdoc export function from(input) { if (typeof input.method === 'string') return fromItem(input); return Object.fromEntries(Object.entries(input).map(([method, item]) => [ method, fromItem({ method, params: item.params, returns: item.returns }), ])); } /** JSON-RPC method schemas for the `eth_` namespace. */ export const Eth = eth; /** JSON-RPC method schemas for the `wallet_` namespace. */ export const Wallet = wallet; /** JSON-RPC method schemas for the `eth_` and `wallet_` namespaces. */ export const Default = { ...eth, ...wallet }; const requestCache = new WeakMap(); // Builds (and caches) the discriminated-union request schema for a namespace. function requestSchema(namespace) { const cached = requestCache.get(namespace); if (cached) return cached; const schema = z.discriminatedUnion('method', Object.values(namespace).map((item) => item.request)); requestCache.set(namespace, schema); return schema; } /** * Looks up the `RpcSchema.Item` for a method on a namespace. Resolve a method * once and pass the item to the `decode*`/`encode*` codecs to encode params and * decode returns without repeating the namespace and method name. * * @example * ```ts twoslash * import { z } from 'ox/zod' * * const item = z.RpcSchema.parseItem( * z.RpcSchema.Eth, * 'eth_getBlockTransactionCountByNumber' * ) * * const params = z.RpcSchema.encodeParams(item, [1n]) * const count = z.RpcSchema.decodeReturns(item, '0x1') * ``` * * @throws `RpcSchema.MethodNotFoundError` if the method does not exist. */ export function parseItem(namespace, method) { const item = namespace[method]; if (!item) throw new MethodNotFoundError({ method }); return item; } // Resolves a codec function's arguments into `[item, value]`, accepting either // `(item, value)` or `(namespace, method, value)`. function resolveItem(args) { if (args.length === 2) return [args[0], args[1]]; return [parseItem(args[0], args[1]), args[2]]; } // eslint-disable-next-line jsdoc-js/require-jsdoc export function decodeParams(...args) { const [item, params] = resolveItem(args); return z.decode(item.params, params); } // eslint-disable-next-line jsdoc-js/require-jsdoc export function encodeParams(...args) { const [item, params] = resolveItem(args); return z.encode(item.params, params); } // eslint-disable-next-line jsdoc-js/require-jsdoc export function decodeReturns(...args) { const [item, returns] = resolveItem(args); return z.decode(item.returns, returns); } // eslint-disable-next-line jsdoc-js/require-jsdoc export function encodeReturns(...args) { const [item, returns] = resolveItem(args); return z.encode(item.returns, returns); } /** * Decodes (wire → native) a full JSON-RPC request (`{ method, params }`) * against a namespace, dispatching on `method`. * * @example * ```ts twoslash * import { z } from 'ox/zod' * * const request = z.RpcSchema.decodeRequest(z.RpcSchema.Eth, { * method: 'eth_getBlockByNumber', * params: ['0x1', true] * }) * ``` */ export function decodeRequest(namespace, request) { return z.decode(requestSchema(namespace), request); } /** * Encodes (native → wire) a full JSON-RPC request (`{ method, params }`) * against a namespace, dispatching on `method`. * * @example * ```ts twoslash * import { z } from 'ox/zod' * * const request = z.RpcSchema.encodeRequest(z.RpcSchema.Eth, { * method: 'eth_getBlockByNumber', * params: [1n, true] * }) * ``` */ export function encodeRequest(namespace, request) { return z.encode(requestSchema(namespace), request); } /** * Alias for `RpcSchema.decodeRequest`. * * @example * ```ts twoslash * import { z } from 'ox/zod' * * const request = z.RpcSchema.parse(z.RpcSchema.Eth, { * method: 'eth_getBalance', * params: [ * '0x0000000000000000000000000000000000000000', * 'latest' * ] * }) * ``` */ export const parse = decodeRequest; /** Thrown when a method does not exist on a namespace. */ export class MethodNotFoundError extends Errors.BaseError { name = 'RpcSchema.MethodNotFoundError'; constructor({ method }) { super(`Method \`${method}\` does not exist on the schema.`); } } //# sourceMappingURL=RpcSchema.js.map