RpcNode

WalletAPIServer extends the abstract class RpcNode, which implements the JSON-RPC 2.0 plumbing shared between the server and the client. Knowing what RpcNode provides is useful when you implement a custom transport or read stack traces.

Class diagram overview

Class diagram showing RpcNode with its transport, requestHandlers, and ongoingRequests properties, and the request/notify/handleMessage flow into onRequest

Type parameters

abstract class RpcNode<TSHandlers, TCHandlers>
ParameterMeaning
TSHandlersThe handlers exposed to the other side for this node. For the server, these are the request handlers.
TCHandlersThe handlers available on the other side, used to type the request / notify calls this node emits.

Properties

PropertyVisibilitySet viaPurpose
transportprivateconstructorThe transport used to read and write JSON-RPC messages.
requestHandlersprotectedconstructorThe handlers that fulfil incoming requests.
ongoingRequestsprivatepopulated by _requestPending request promises keyed by request ID. The resolver is called when a matching response arrives.

The constructor sets transport.onMessage to its own handleMessage so any incoming string is routed through RpcNode.

Methods

Public

request<K>(method: K, params: P): Promise<R | undefined>
notify<K>(method: K, params: P): void
MethodUse it toNotes
requestSend a JSON-RPC request and await the response.Generates a UUID v4 for the request id, stores a resolver in ongoingRequests, sends { jsonrpc: "2.0", id, method, params } over the transport, and resolves with the response’s result (or rejects with the error).
notifySend a JSON-RPC notification (no response expected).No id is generated; the receiver does not reply.

Internal flow

MethodVisibilityRole
handleMessageprivateRoutes an incoming message to handleRpcRequest (when it has a method) or handleRpcResponse (when it has a result/error).
handleRpcRequestprivateCalls onRequest(request), builds the response, and writes it to the transport. Translates exceptions into RpcErrors (see below).
handleRpcResponseprivateLooks up the resolver in ongoingRequests by ID and resolves it. Throws if no matching request is found.
onRequestabstract, protectedSubclasses must implement this. WalletAPIServer.onRequest looks up requestHandlers[method], checks the permissions, and invokes the handler.

Error handling

RpcNode translates thrown exceptions into JSON-RPC error responses with the following codes (defined in packages/core/src/JSONRPC/types.ts):

CodeNameRaised when
-32700PARSE_ERRORInvalid JSON received.
-32600INVALID_REQUESTMessage is not a valid JSON-RPC request.
-32601METHOD_NOT_FOUNDrequestHandlers has no entry for the method ID.
-32602INVALID_PARAMSZod validation of params fails (error.flatten() is attached as data).
-32603INTERNAL_ERRORInternal JSON-RPC error.
-32000SERVER_ERRORA ServerError (for example the wallet not implementing a handler) was thrown. The original error data is wrapped in data.

On the requesting side, _request re-hydrates these errors: SERVER_ERRORs with code UNKNOWN_ERROR are deserialized via @ledgerhq/errors and rejected as the original error class; everything else is rejected as a RpcError.

RPC request and response types

packages/core/src/JSONRPC/types.ts
type RpcRequest<MParam = string, TParam = unknown> = {
  jsonrpc: "2.0";
  method: MParam;
  params?: TParam;
  id?: string | number | null;
};
 
type RpcResponse<TResult = unknown, TErrorData = unknown> =
  | { jsonrpc: "2.0"; id: string | number | null; result?: TResult }
  | { jsonrpc: "2.0"; id: string | number | null; error: RpcResponseError<TErrorData> };

A request without an id is a notification: no response is sent.

See also

Ledger
Copyright © Ledger SAS. All rights reserved. Ledger, Ledger Stax, Ledger Flex, Ledger Nano, Ledger Nano S, Ledger OS, Ledger Wallet, [LEDGER] (logo), [L] (logo) are trademarks owned by Ledger SAS.