---
title: RpcNode
category: reference
---

# 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](../assets/server-rpc-node-classdiagram.png)

## Type parameters

```ts
abstract class RpcNode<TSHandlers, TCHandlers>
```

| Parameter    | Meaning                                                                                                                                   |
| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `TSHandlers` | The handlers exposed to the **other side** for this node. For the server, these are the [request handlers](../reference#requesthandlers). |
| `TCHandlers` | The handlers available on the **other side**, used to type the `request` / `notify` calls this node emits.                                |

## Properties

| Property          | Visibility | Set via                 | Purpose                                                                                                |
| ----------------- | ---------- | ----------------------- | ------------------------------------------------------------------------------------------------------ |
| `transport`       | private    | constructor             | The [transport](../reference#transport) used to read and write JSON-RPC messages.                      |
| `requestHandlers` | protected  | constructor             | The handlers that fulfil incoming requests.                                                            |
| `ongoingRequests` | private    | populated by `_request` | Pending 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

```ts
request<K>(method: K, params: P): Promise<R | undefined>
notify<K>(method: K, params: P): void
```

| Method    | Use it to                                                | Notes                                                                                                                                                                                                                       |
| --------- | -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `request` | Send 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). |
| `notify`  | Send a JSON-RPC **notification** (no response expected). | No `id` is generated; the receiver does not reply.                                                                                                                                                                          |

### Internal flow

| Method              | Visibility          | Role                                                                                                                                                                         |
| ------------------- | ------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `handleMessage`     | private             | Routes an incoming message to `handleRpcRequest` (when it has a `method`) or `handleRpcResponse` (when it has a `result`/`error`).                                           |
| `handleRpcRequest`  | private             | Calls `onRequest(request)`, builds the response, and writes it to the transport. Translates exceptions into `RpcError`s (see below).                                         |
| `handleRpcResponse` | private             | Looks up the resolver in `ongoingRequests` by ID and resolves it. Throws if no matching request is found.                                                                    |
| `onRequest`         | abstract, protected | Subclasses must implement this. `WalletAPIServer.onRequest` looks up `requestHandlers[method]`, checks the [permissions](../reference#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`](https://github.com/LedgerHQ/wallet-api/blob/main/packages/core/src/JSONRPC/types.ts)):

| Code     | Name               | Raised when                                                                                                                   |
| -------- | ------------------ | ----------------------------------------------------------------------------------------------------------------------------- |
| `-32700` | `PARSE_ERROR`      | Invalid JSON received.                                                                                                        |
| `-32600` | `INVALID_REQUEST`  | Message is not a valid JSON-RPC request.                                                                                      |
| `-32601` | `METHOD_NOT_FOUND` | `requestHandlers` has no entry for the method ID.                                                                             |
| `-32602` | `INVALID_PARAMS`   | Zod validation of `params` fails (`error.flatten()` is attached as `data`).                                                   |
| `-32603` | `INTERNAL_ERROR`   | Internal JSON-RPC error.                                                                                                      |
| `-32000` | `SERVER_ERROR`     | A `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_ERROR`s 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

```ts filename="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

- [Server reference](../reference): `requestHandlers`, `walletHandlers`, and permissions.
- [`RpcNode` source](https://github.com/LedgerHQ/wallet-api/blob/main/packages/core/src/JSONRPC/RpcNode.ts).
- [JSON-RPC 2.0 specification](https://www.jsonrpc.org/specification).
