Skip to main content

JsonClient

Struct JsonClient 

Source
pub struct JsonClient { /* private fields */ }
Expand description

A client for the Canton JSON Ledger API over HTTP.

Implementations§

Source§

impl JsonClient

Source

pub fn new(base_url: impl Into<String>) -> Self

Create a JSON client for base_url (e.g. http://localhost:3975), with no authentication. A trailing slash on base_url is tolerated.

Source

pub fn from_env() -> Result<Self>

Build a client from a local development network exported into the environment — the JSON counterpart to Config::from_env.

eval "$(canton-devkit localnet env demo)"

reads CANTON_JSON_LEDGER_API_URL and the default participant’s JWT. See canton_core::localnet for the full contract.

§Errors

Returns Error::InvalidRequest when no JSON endpoint is exported, naming the variable and the command that produces it. A missing token is not an error: an unauthenticated LocalNet is a normal target.

Source

pub fn from_env_for(role: &str) -> Result<Self>

The same, for a participant other than the default: "app-user", "sv", or any role the exporter knows.

§Errors

As Self::from_env, naming that role’s variable.

Source

pub fn with_timeout(self, timeout: Duration) -> Self

How long one HTTP attempt may take (default 30s), the JSON lane’s counterpart to Config::with_timeout.

reqwest imposes no timeout of its own, so without this a request to a participant that accepts the connection and then goes quiet never returns. Applied per attempt: under Self::with_retry each try gets the full budget, matching how the gRPC channel’s timeout composes with its retries.

The clock covers the whole exchange — connecting, sending, and reading the response body — so it is a real bound rather than a bound on the first byte.

Source

pub fn with_max_decoding_message_size(self, bytes: usize) -> Self

The largest WebSocket message this client will accept, in bytes — the JSON lane’s counterpart to Config::with_max_decoding_message_size, and the same default.

A WS stream carries the same payloads the gRPC one does, so it needs the same ceiling. Left alone, tungstenite applies its own: 64 MiB per message and 16 MiB per frame, the second of which is the one a large update meets first. Both are set from this value, so a frame is capped only by what the caller asked for.

Does not affect the HTTP (POST) lane, which has no ceiling to raise.

Source

pub fn with_retry(self, retry: RetryConfig) -> Self

Retry requests on retriable errors (category-first classification of the participant’s error body, transient HTTP statuses, connection failures) with exponential backoff, honouring a server-recommended retry delay — the same policy as the gRPC client’s unary retries. Off by default. Safe for command submission too: the command id in the body stays fixed across attempts, so the participant de-duplicates. Streaming (the WS lane) resumes via its own reconnect policy instead.

Source

pub fn with_tls(self, tls: &TlsConfig) -> Result<Self>

Use TLS for the HTTP connection: a custom CA (server-side TLS against a private/self-signed server) and/or a client identity (mutual TLS). This is a terminal builder step — call it last, after Self::with_token / Self::with_oidc.

An http:// base URL is normalised to https:// so TLS is never silently downgraded: reqwest selects TLS from the URL scheme (not from the configured certificates), and the WebSocket lane maps httpws / httpswss the same way, so an http:// base URL with with_tls would otherwise send plaintext HTTP and open a ws:// socket with the certificates unused. Detection is case-insensitive, mirroring the gRPC channel builder (canton-core’s resolve_endpoint).

TlsConfig::domain_name is not applied here: reqwest derives SNI from the request URL (it is a gRPC/tonic knob).

§Errors

Returns Error::InvalidRequest if a certificate/identity PEM is invalid or the HTTPS client cannot be built.

Source

pub fn with_token(self, token: impl Into<String>) -> Self

Authenticate with a fixed bearer token.

Source

pub fn with_oidc(self, provider: TokenProvider) -> Self

Authenticate with an OIDC token provider (client-credentials, auto-refresh).

Source

pub async fn version(&self) -> Result<String>

The participant’s Ledger API version (GET /v2/version, unauthenticated).

§Errors

Returns an Error if the request fails or the response is malformed.

Source

pub async fn ledger_end(&self) -> Result<i64>

The current ledger end offset (GET /v2/state/ledger-end, authenticated).

§Errors

Returns an Error if authentication or the request fails.

Source

pub async fn submit_and_wait_for_transaction( &self, commands: &JsonCommands, ) -> Result<JsonSubmitResponse>

Submit commands and wait for the resulting transaction (POST /v2/commands/submit-and-wait-for-transaction).

§Errors

Returns an Error if authentication fails, the command is rejected (surfaced as Error::Http carrying the participant’s error body), or the response is malformed.

Source

pub async fn submit(&self, commands: &JsonCommands) -> Result<()>

Submit without waiting (POST /v2/commands/async/submit): the participant accepts the command and the outcome arrives on the completion stream.

The gRPC lane has had this since M1. Note what a failure here means: the command may still have committed, so reach for Self::submission rather than this method when losing the outcome is not acceptable.

§Errors

Returns an Error if authentication fails or the participant rejects the submission (Error::Http with its error body).

Source

pub async fn submit_and_wait( &self, commands: &JsonCommands, ) -> Result<JsonSubmitAndWaitResponse>

Submit and wait for the completion (POST /v2/commands/submit-and-wait) without fetching the transaction — the update id and completion offset.

§Errors

Returns an Error if authentication fails or the command is rejected.

Source

pub async fn events_by_contract_id( &self, contract_id: impl Into<String>, parties: Vec<String>, ) -> Result<Value>

The create and consuming-exercise events of one contract (POST /v2/events/events-by-contract-id), as seen by parties.

Returns the raw response object; a contract that has been pruned or is invisible to parties comes back as a CONTRACT_EVENTS_NOT_FOUND error rather than an empty result.

§Errors

Returns an Error if authentication or the request fails, or the contract has no events visible to parties.

Source

pub fn submission(&self, commands: JsonCommands) -> JsonSubmission

Fix a submission’s identity before sending it, returning a JsonSubmission that carries its ChangeId — the JSON lane’s CantonClient::submission.

Source

pub async fn active_contracts( &self, parties: Vec<String>, active_at_offset: i64, limit: Option<i64>, ) -> Result<Vec<Value>>

The active contract set snapshot at active_at_offset, wildcard-filtered to parties (POST /v2/state/active-contracts).

This is a bounded read: the node caps results at http-list-max-elements-limit and returns Error::Http 413 past it, so pass a limit for large sets (or use the streaming transport). Each element is raw JSON ({"workflowId": …, "contractEntry": …}).

§Errors

Returns an Error if authentication or the request fails, or the result set exceeds the node limit (413).

Source

pub async fn active_contracts_with( &self, request: &ActiveContractsRequest, limit: Option<i64>, ) -> Result<Vec<Value>>

Like Self::active_contracts, with the full request surface of an ActiveContractsRequest (template/interface filters, created-event blobs, non-verbose records) — the same builder the gRPC lane takes.

§Errors

Returns an Error if authentication or the request fails, or the result set exceeds the node limit (413).

Source

pub async fn updates( &self, parties: Vec<String>, begin_exclusive: i64, end_inclusive: Option<i64>, limit: Option<i64>, ) -> Result<Vec<Value>>

Updates (transactions/reassignments) for parties in the offset range (begin_exclusive, end_inclusive] (POST /v2/updates).

A bounded read like Self::active_contracts: bound it with end_inclusive and/or limit, or the node returns Error::Http 413. Each element is raw JSON ({"update": …}), including OffsetCheckpoint heartbeats.

§Errors

Returns an Error if authentication or the request fails, or the result set exceeds the node limit (413).

Source

pub async fn updates_with( &self, request: &UpdatesRequest, limit: Option<i64>, ) -> Result<Vec<Value>>

Like Self::updates, with the full request surface of an UpdatesRequest (bounds, template/ interface filters, transaction shape, created-event blobs, topology events, non-verbose records) — the same builder the gRPC lane takes.

§Errors

Returns an Error if authentication or the request fails, or the result set exceeds the node limit (413).

Source§

impl JsonClient

Source

pub async fn ws_updates( &self, parties: Vec<String>, begin_exclusive: i64, end_inclusive: Option<i64>, ) -> Result<impl Stream<Item = Result<Value>> + Send + use<>>

Available on crate feature ws only.

Stream updates over WebSocket (feature ws) for parties, starting after begin_exclusive. With end_inclusive the stream is bounded and closes once the range is exhausted; without it the stream tails live. Each item is a raw JSON update ({"update": …}); OffsetCheckpoint heartbeats are filtered out (as in the gRPC CantonClient::updates).

Unlike Self::updates, this is not capped by the node’s list limit. For automatic reconnection use Self::ws_updates_resumable.

§Errors

Returns an Error if the handshake fails; the stream yields Err on a participant error frame or a transport failure.

Source

pub async fn ws_updates_with( &self, request: &UpdatesRequest, ) -> Result<impl Stream<Item = Result<Value>> + Send + use<>>

Available on crate feature ws only.

Like Self::ws_updates, with the full request surface of an UpdatesRequest — the same builder the gRPC lane takes (bounds, filters, shape, blobs, topology events, non-verbose records).

§Errors

Returns an Error if the handshake fails; the stream yields Err on a participant error frame or a transport failure.

Source

pub async fn ws_active_contracts( &self, parties: Vec<String>, active_at_offset: i64, ) -> Result<impl Stream<Item = Result<Value>> + Send + use<>>

Available on crate feature ws only.

Stream the active contract set snapshot at active_at_offset over WebSocket (feature ws), wildcard-filtered to parties. The stream closes when the snapshot is fully delivered. Each item is raw JSON ({"workflowId": …, "contractEntry": …}).

Unlike Self::active_contracts, this is not capped by the node’s list limit.

§Errors

Returns an Error if the handshake fails; the stream yields Err on a participant error frame or a transport failure.

Source

pub async fn ws_active_contracts_with( &self, request: &ActiveContractsRequest, ) -> Result<impl Stream<Item = Result<Value>> + Send + use<>>

Available on crate feature ws only.

Like Self::ws_active_contracts, with the full request surface of an ActiveContractsRequest — the same builder the gRPC lane takes.

§Errors

Returns an Error if the handshake fails; the stream yields Err on a participant error frame or a transport failure.

Source

pub async fn ws_completions( &self, parties: Vec<String>, begin_exclusive: i64, ) -> Result<impl Stream<Item = Result<Value>> + Send + use<>>

Available on crate feature ws only.

Stream command completions over WebSocket (feature ws) for parties, starting after begin_exclusive. Each item is a raw JSON completion; OffsetCheckpoint heartbeats are filtered out.

§Errors

Returns an Error if the handshake fails; the stream yields Err on a participant error frame or a transport failure.

Source

pub async fn ws_completions_with( &self, request: &CompletionsRequest, ) -> Result<impl Stream<Item = Result<Value>> + Send + use<>>

Available on crate feature ws only.

Like Self::ws_completions, with the full request surface of a CompletionsRequest — including the submitting user_id to scope the stream to (the same builder the gRPC lane takes).

§Errors

Returns an Error if the handshake fails; the stream yields Err on a participant error frame or a transport failure.

Source

pub fn ws_active_contracts_resumable( &self, parties: Vec<String>, active_at_offset: i64, ) -> impl Stream<Item = Result<Value>> + Send + use<>

Available on crate feature ws only.

Like Self::ws_active_contracts, but resumable: on a retriable disconnect it resubscribes from the last continuation token the participant sent, rather than starting the snapshot again.

An ACS snapshot has no offsets to resume from — it is a position in a stream of entries, which is what streamContinuationToken names. The gRPC lane has had a resumable ACS read since M1; this is its counterpart, and without it a WebSocket consumer of a large snapshot had to start over on any blip.

The token is only valid against the same participant, the same active_at_offset and the same filters — all of which are fixed for the life of this stream — and while the snapshot’s offset has not been pruned.

Source

pub fn ws_updates_resumable( &self, parties: Vec<String>, begin_exclusive: i64, ) -> impl Stream<Item = Result<Value>> + Send + use<>

Available on crate feature ws only.

Like Self::ws_updates (unbounded tail), but resumable: on a retriable disconnect it reconnects from the last offset it observed (tracked via OffsetCheckpoint heartbeats and update offsets), with a short backoff and a bounded number of consecutive reconnects. Mirrors the gRPC CantonClient::updates_resumable. Checkpoints are consumed for position tracking and not yielded.

Trait Implementations§

Source§

impl Clone for JsonClient

Source§

fn clone(&self) -> JsonClient

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for JsonClient

Hand-written for the same reason Config’s is: a base URL can carry credentials in its userinfo (https://user:secret@host), and the derived Debug printed them verbatim — one tracing field holding a client, or one {:?} in a log line, was enough.

The reqwest client is left out entirely — finish_non_exhaustive says so rather than pretending otherwise — because its internals describe a connection pool, not this client.

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<T> FutureExt for T

Source§

fn with_context(self, otel_cx: Context) -> WithContext<Self>

Attaches the provided Context to this type, returning a WithContext wrapper. Read more
Source§

fn with_current_context(self) -> WithContext<Self>

Attaches the current Context to this type, returning a WithContext wrapper. Read more
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoRequest<T> for T

Source§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
Source§

impl<T> IntoRequest<T> for T

Source§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
Source§

impl<L> LayerExt<L> for L

Source§

fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>
where L: Layer<S>,

Applies the layer to a service and wraps it in Layered.
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more