Skip to main content
The ledgerApi method lets your dApp read ledger state on behalf of the connected user. It forwards a Canton JSON Ledger API request through Walley’s authenticated, read-only proxy and returns the upstream response. This implements the CIP-0103 ledgerApi provider method. Unlike prepareExecute, ledgerApi does not open a popup and does not submit transactions — it’s a read path that runs against the user’s existing session token.

Making a request

const { response } = await provider.request({
  method: "ledgerApi",
  params: {
    requestMethod: "GET",
    resource: "/v2/state/active-contracts",
  },
});

const data = JSON.parse(response);

Parameters

FieldTypeDescription
requestMethodstringThe HTTP method for the upstream Ledger API call, e.g. "GET" or "POST".
resourcestringThe Ledger API path, e.g. /v2/state/active-contracts. A leading slash is optional.
bodystring  (optional)A JSON string request body. When present, the proxy sends Content-Type: application/json.

Result

// { response: string }
The response is the raw upstream body as a string. Parse it with JSON.parse for JSON endpoints.

Example with a body

const { response } = await provider.request({
  method: "ledgerApi",
  params: {
    requestMethod: "POST",
    resource: "/v2/state/active-contracts",
    body: JSON.stringify({ filter: { filtersByParty: {} }, verbose: false }),
  },
});

Authentication & tokens

The proxy authenticates with the short-lived access token issued when the user connected. You don’t manage the token directly — the SDK attaches it automatically — but you do need to handle expiry.
Access tokens are short-lived. When a token has expired, a ledgerApi call throws providerErrors.unauthorized. Recover by calling connect again to refresh the session, then retry the request.
import { providerErrors } from "@canton-network/core-rpc-errors";

async function readLedger(params) {
  try {
    return await provider.request({ method: "ledgerApi", params });
  } catch (err) {
    if (err.code === providerErrors.unauthorized().code) {
      await provider.request({ method: "connect" }); // refresh session
      return provider.request({ method: "ledgerApi", params });
    }
    throw err;
  }
}

Errors

ConditionError
Not connected / no access token in sessionrpcErrors.internal
Session token expired (HTTP 401)providerErrors.unauthorized — reconnect and retry
Transport failure reaching the proxyrpcErrors.internal
Upstream returns a non-2xx statusrpcErrors.internal, with the status and body in the message

When to use it