ScanApiClient exposes read-mostly Canton Network observability and indexer endpoints (health, DSO metadata, rounds, wallets, updates, events). Requests use no bearer token — endpoints are public but rate-limited and may return transient failures.
The hand-written subclass adds endpoint rotation: when one SV-hosted Scan base URL fails with retry-worthy errors, the client advances through a configured list (typically every Super Validator Scan URL for your network).
Construction
You normally obtain the client from Canton:
import { Canton } from '@fairmint/canton-node-sdk';
const canton = new Canton({
network: 'NETWORK_NAME',
provider: 'PROVIDER_HINT',
});
const scan = canton.scan;
You may also construct ScanApiClient directly with a CantonRuntime if you only need Scan.
Endpoint URLs and helpers
Scan routes live under each SV host’s /api/scan base (full URL includes /api/scan; rotation compares paths relative to that root).
Module scan-endpoints exports:
| Export | Role |
|---|---|
ScanSvEndpoint | Describes one SV row (svName, hostUrl, version). |
getScanSvEndpoints(network) | Known SV hosts for 'devnet' or 'mainnet' (empty for 'localnet' and other networks). |
toScanApiUrl(hostUrl) | Appends /api/scan (normalized trailing slash). |
resolveScanApiUrls(network, provider?) | Ordered base URLs for retries: preferred SV matching provider first (normalized name), then the rest. |
resolveScanApiUrls uses provider hints such as '5n' mapped to SV names like Five-North-1. Lists originate from published Canton SV status pages.
If no SV list applies (for example localnet) and runtime config supplies SCAN_API.apiUrl, that single URL is used; otherwise construction throws ConfigurationError with guidance to pass scanApiUrls explicitly.
Rotation behavior (ScanApiClient.ts)
Options:
| Field | Meaning |
|---|---|
scanApiUrls | Override the full rotation list. Each entry must be a complete /api/scan base URL. |
maxEndpointAttempts | Cap how many distinct bases are tried per logical request (defaults to full list length). |
Rotation triggers on NetworkError, ApiError with unknown status, 408, 429, or status >= 500. Client 4xx responses other than those codes do not rotate — fix inputs instead.
Per-request HTTP retries inside the transport are disabled (maxRetries: 0) so failures move quickly to the next SV base.
Successful responses update activeBaseUrlIndex so subsequent calls prefer the SV that worked.
Minimal example — network summary
const info = await canton.scan.getDsoInfo();
console.log(info);
Auth and party
No OAuth party identity is required for Scan. Validator-only queries such as wallet-specific Scan routes still expect whatever identifiers each route defines (for example domain and member IDs).
Errors
| Situation | Typical outcome |
|---|---|
| No Scan URL for network | ConfigurationError at construct time |
| All bases fail transiently | Last thrown network or API error |
| Invalid route arguments | Non-rotating ApiError (for example 404) |
See also
- ScanApiClient.ts — method list wired to operations.
scan.tsoperations — paths and HTTP verbs.Canton— constructingcanton.scan.