pub struct CantonClient { /* private fields */ }Expand description
An async client for the Canton Ledger API over gRPC.
The client owns a lazily-connected Channel; cloning it is cheap and
clones share the underlying connection pool, so it is safe to hand a clone
to each task.
Implementations§
Source§impl CantonClient
impl CantonClient
Sourcepub fn connect_lazy(config: Config) -> Result<Self>
pub fn connect_lazy(config: Config) -> Result<Self>
Build a lazily-connected client. Returns immediately; the TCP/TLS handshake happens on the first RPC.
§Errors
Returns Error::InvalidRequest if the endpoint is not a valid URI.
Sourcepub async fn health_check(&self) -> Result<ServingStatus>
pub async fn health_check(&self) -> Result<ServingStatus>
Probe the participant’s overall serving status via the standard
grpc.health.v1.Health service (served on the Ledger API port).
Poll this to react to intermittent or permanent node failure: a healthy
participant answers ServingStatus::Serving; an unreachable one
surfaces a transport Error (see Error::is_retriable).
§Errors
Returns an Error if the health RPC fails (e.g. the node is down).
Sourcepub async fn submit(&self, submit: Submit) -> Result<String>
pub async fn submit(&self, submit: Submit) -> Result<String>
Submit commands fire-and-forget (CommandSubmissionService.Submit):
hand the commands to the participant and return promptly without waiting
for the transaction. Returns the change-ID command_id used, so the
caller can recover the outcome later with Self::await_completion (or
the Self::completions stream).
A fresh UUID command_id is generated when the caller did not set one,
so ledger-side de-duplication behaves correctly across retries.
§Errors
Returns an Error if authentication fails or the participant rejects
the submission synchronously (e.g. a preprocessing error).
Sourcepub fn submission(&self, submit: Submit) -> Submission
pub fn submission(&self, submit: Submit) -> Submission
Fix a submission’s identity before sending it, returning a
Submission that carries its
ChangeId.
This is the handle to reach for when losing the outcome is not an option. A submission whose response is lost — a dropped connection, a timeout, a retry the participant de-duplicated — may well have committed, and the only way back to the answer is the change ID. If the SDK generated the command id inside the call that failed, there is no change ID to go back with.
use std::time::Duration;
// Where to start reading completions from, taken before submitting.
let offset = client.ledger_end().await?;
let submission = client.submission(submit);
if submission.submit_and_wait().await.is_err() {
// Ambiguous: ask the ledger what actually happened.
let completion = submission.recover(offset, Duration::from_secs(30)).await?;
println!("committed after all: {}", completion.update_id);
}Sourcepub async fn submit_and_wait(
&self,
submit: Submit,
) -> Result<SubmitAndWaitResponse>
pub async fn submit_and_wait( &self, submit: Submit, ) -> Result<SubmitAndWaitResponse>
Submit commands and wait for the result without fetching the
transaction (CommandService.SubmitAndWait): blocks until the command
commits (or is rejected) and returns the update_id and completion
offset. Lighter than Self::submit_and_wait_for_transaction when the
caller does not need the event payload.
§Errors
Returns an Error if authentication fails or the command is rejected.
The retry caveat on Self::submit_and_wait_for_transaction applies.
Sourcepub async fn submit_and_wait_for_transaction(
&self,
submit: Submit,
) -> Result<Transaction>
pub async fn submit_and_wait_for_transaction( &self, submit: Submit, ) -> Result<Transaction>
Submit commands and wait for the resulting transaction.
Fills the change ID’s command_id with a fresh UUID when the caller did
not set one, so ledger-side de-duplication behaves correctly. The
returned transaction is shaped as LEDGER_EFFECTS and filtered to the
acting party (wildcard), so created events are visible in the response.
§Errors
Returns an Error if authentication fails, the command is rejected, or
the response contains no transaction.
§Example
use canton_ledger::{Submit, create, identifier, record};
let tx = client
.submit_and_wait_for_transaction(
Submit::new(party)
.add_command(create(identifier(pkg, "M", "T"), record(vec![]))),
)
.await?;
println!("committed {} at offset {}", tx.update_id, tx.offset);§Retry caveat (exactly-once)
With retry enabled (Config::with_retry), a submission that commits
on the ledger but whose response is lost to a retriable error is re-sent
with the same command_id and de-duplicated by the participant.
Self::submit can answer that on its own: a duplicate rejection of a
retry it made itself means its earlier attempt was accepted, which is
success, so it reports success. This method cannot. Its result is
the committed transaction, and a de-duplicated retry does not carry one
— so the duplicate rejection reaches the caller, and the transaction has
to be read back rather than invented.
Take a Submission from Self::submission
before submitting, and on any error recover the outcome with
Submission::recover — it knows the
change ID, which is the only way back to a command whose response was
lost. See the recover_a_submission example.
Sourcepub async fn completions(
&self,
parties: Vec<String>,
begin_offset: i64,
) -> Result<impl Stream<Item = Result<Completion>> + Send + use<>>
pub async fn completions( &self, parties: Vec<String>, begin_offset: i64, ) -> Result<impl Stream<Item = Result<Completion>> + Send + use<>>
Subscribe to the command-completion stream for parties, starting after
begin_offset (exclusive). Offset checkpoints are filtered out, so the
stream yields only pb::Completions.
§Errors
Returns an Error if authentication or opening the stream fails.
Sourcepub async fn completions_with(
&self,
request: CompletionsRequest,
) -> Result<impl Stream<Item = Result<Completion>> + Send + use<>>
pub async fn completions_with( &self, request: CompletionsRequest, ) -> Result<impl Stream<Item = Result<Completion>> + Send + use<>>
Like Self::completions, with the full request surface: a
CompletionsRequest additionally
selects the user_id whose command completions to stream (pair it with
Submit::with_user_id).
§Errors
Returns an Error if authentication or opening the stream fails.
Sourcepub async fn await_completion(
&self,
change_id: &ChangeId,
begin_offset: i64,
timeout: Duration,
) -> Result<Completion>
pub async fn await_completion( &self, change_id: &ChangeId, begin_offset: i64, timeout: Duration, ) -> Result<Completion>
Recover the completion for a specific command by scanning the completion
stream from begin_offset, up to timeout.
This is the command-recovery path: after a crash, lost connection, or
timeout, the outcome of a pending command is read back from the
completion endpoint instead of blindly re-submitting. If the command’s
completion reports a non-OK status, this returns Error::CommandRejected.
Matching is on the whole ChangeId — user, acting
parties and command id — because that is what identifies a command to
Canton. A command id on its own is not unique across the users of a
participant, and answering with somebody else’s completion is worse
than answering with none.
The completion stream is a live subscription that does not self-terminate,
so timeout bounds how long to wait for the target completion.
§Errors
Returns Error::Timeout if the completion is not seen within timeout,
Error::CommandRejected if the ledger rejected the command, or another
Error if the stream fails.
Sourcepub async fn ledger_end(&self) -> Result<i64>
pub async fn ledger_end(&self) -> Result<i64>
Sourcepub async fn events_by_contract_id(
&self,
contract_id: impl Into<String>,
parties: Vec<String>,
) -> Result<GetEventsByContractIdResponse>
pub async fn events_by_contract_id( &self, contract_id: impl Into<String>, parties: Vec<String>, ) -> Result<GetEventsByContractIdResponse>
Fetch the created and/or archived events for a contract by id
(EventQueryService.GetEventsByContractId), with verbose records and
no created-event blob. To obtain a contract’s created_event_blob
(for disclosure), use a template-filtered
Self::active_contracts_with read with
ActiveContractsRequest::with_created_event_blobs.
§Errors
Returns an Error if authentication or the RPC fails.
Sourcepub async fn active_contracts_page(
&self,
parties: Vec<String>,
active_at_offset: i64,
max_page_size: i32,
page_token: Option<Vec<u8>>,
) -> Result<(Vec<ActiveContract>, Option<Vec<u8>>)>
pub async fn active_contracts_page( &self, parties: Vec<String>, active_at_offset: i64, max_page_size: i32, page_token: Option<Vec<u8>>, ) -> Result<(Vec<ActiveContract>, Option<Vec<u8>>)>
Sourcepub async fn active_contracts_page_with(
&self,
request: &ActiveContractsRequest,
max_page_size: i32,
page_token: Option<Vec<u8>>,
) -> Result<(Vec<ActiveContract>, Option<Vec<u8>>)>
pub async fn active_contracts_page_with( &self, request: &ActiveContractsRequest, max_page_size: i32, page_token: Option<Vec<u8>>, ) -> Result<(Vec<ActiveContract>, Option<Vec<u8>>)>
Like Self::active_contracts_page, with the full request surface of
an ActiveContractsRequest
(template/interface filters, created-event blobs, non-verbose records).
§Errors
Returns an Error if authentication or the RPC fails.
Sourcepub async fn acs_page(
&self,
parties: Vec<String>,
active_at_offset: i64,
max_page_size: i32,
page_token: Option<Vec<u8>>,
) -> Result<(Vec<AcsEntry>, Option<Vec<u8>>)>
pub async fn acs_page( &self, parties: Vec<String>, active_at_offset: i64, max_page_size: i32, page_token: Option<Vec<u8>>, ) -> Result<(Vec<AcsEntry>, Option<Vec<u8>>)>
Sourcepub async fn acs_page_with(
&self,
request: &ActiveContractsRequest,
max_page_size: i32,
page_token: Option<Vec<u8>>,
) -> Result<(Vec<AcsEntry>, Option<Vec<u8>>)>
pub async fn acs_page_with( &self, request: &ActiveContractsRequest, max_page_size: i32, page_token: Option<Vec<u8>>, ) -> Result<(Vec<AcsEntry>, Option<Vec<u8>>)>
Like Self::acs_page, with the full request surface of an
ActiveContractsRequest.
§Errors
Returns an Error if authentication or the RPC fails.
Sourcepub async fn updates_page(
&self,
parties: Vec<String>,
begin_offset_exclusive: i64,
end_offset_inclusive: i64,
max_page_size: i32,
descending: bool,
page_token: Option<Vec<u8>>,
) -> Result<(Vec<GetUpdateResponse>, Option<Vec<u8>>)>
pub async fn updates_page( &self, parties: Vec<String>, begin_offset_exclusive: i64, end_offset_inclusive: i64, max_page_size: i32, descending: bool, page_token: Option<Vec<u8>>, ) -> Result<(Vec<GetUpdateResponse>, Option<Vec<u8>>)>
Sourcepub async fn updates_page_with(
&self,
request: &UpdatesRequest,
max_page_size: i32,
page_token: Option<Vec<u8>>,
) -> Result<(Vec<GetUpdateResponse>, Option<Vec<u8>>)>
pub async fn updates_page_with( &self, request: &UpdatesRequest, max_page_size: i32, page_token: Option<Vec<u8>>, ) -> Result<(Vec<GetUpdateResponse>, Option<Vec<u8>>)>
Like Self::updates_page, with the full request surface of an
UpdatesRequest (template/interface
filters, transaction shape, descending order, created-event blobs,
topology events, non-verbose records). The request’s bounds supply the
page range, so
UpdatesRequest::until is
required here — the paged read is inherently bounded.
§Errors
Returns Error::InvalidRequest if the request has no end offset, or
another Error if authentication or the RPC fails.
Sourcepub async fn active_contracts(
&self,
parties: Vec<String>,
active_at_offset: i64,
) -> Result<impl Stream<Item = Result<ActiveContract>> + Send + use<>>
pub async fn active_contracts( &self, parties: Vec<String>, active_at_offset: i64, ) -> Result<impl Stream<Item = Result<ActiveContract>> + Send + use<>>
Sourcepub async fn active_contracts_with(
&self,
request: ActiveContractsRequest,
) -> Result<impl Stream<Item = Result<ActiveContract>> + Send + use<>>
pub async fn active_contracts_with( &self, request: ActiveContractsRequest, ) -> Result<impl Stream<Item = Result<ActiveContract>> + Send + use<>>
Like Self::active_contracts, with the full request surface: an
ActiveContractsRequest
additionally filters by template or interface, includes created-event
blobs, and drops record labels.
§Errors
Returns an Error if authentication or opening the stream fails.
Sourcepub async fn acs_entries(
&self,
parties: Vec<String>,
active_at_offset: i64,
) -> Result<impl Stream<Item = Result<AcsEntry>> + Send + use<>>
pub async fn acs_entries( &self, parties: Vec<String>, active_at_offset: i64, ) -> Result<impl Stream<Item = Result<AcsEntry>> + Send + use<>>
Sourcepub async fn acs_entries_with(
&self,
request: ActiveContractsRequest,
) -> Result<impl Stream<Item = Result<AcsEntry>> + Send + use<>>
pub async fn acs_entries_with( &self, request: ActiveContractsRequest, ) -> Result<impl Stream<Item = Result<AcsEntry>> + Send + use<>>
Like Self::acs_entries, with the full request surface of an
ActiveContractsRequest.
§Errors
Returns an Error if authentication or opening the stream fails.
Sourcepub fn active_contracts_resumable(
&self,
parties: Vec<String>,
active_at_offset: i64,
max_page_size: i32,
) -> impl Stream<Item = Result<ActiveContract>> + Send + use<>
pub fn active_contracts_resumable( &self, parties: Vec<String>, active_at_offset: i64, max_page_size: i32, ) -> impl Stream<Item = Result<ActiveContract>> + Send + use<>
Like Self::active_contracts, but resumable: reads the ACS
snapshot page-by-page (continuation tokens), retrying a failed page on
retriable errors from the last token instead of restarting the snapshot
from zero. max_page_size bounds each page RPC.
Sourcepub fn active_contracts_resumable_with(
&self,
request: ActiveContractsRequest,
max_page_size: i32,
) -> impl Stream<Item = Result<ActiveContract>> + Send + use<>
pub fn active_contracts_resumable_with( &self, request: ActiveContractsRequest, max_page_size: i32, ) -> impl Stream<Item = Result<ActiveContract>> + Send + use<>
Like Self::active_contracts_resumable, with the full request
surface of an
ActiveContractsRequest.
Sourcepub fn acs_entries_resumable(
&self,
parties: Vec<String>,
active_at_offset: i64,
max_page_size: i32,
) -> impl Stream<Item = Result<AcsEntry>> + Send + use<>
pub fn acs_entries_resumable( &self, parties: Vec<String>, active_at_offset: i64, max_page_size: i32, ) -> impl Stream<Item = Result<AcsEntry>> + Send + use<>
Like Self::acs_entries, but resumable and page-based: reads the
snapshot page by page and retries a failed page from the last
continuation token instead of restarting from zero. Every entry the
participant sent is yielded (see AcsEntry).
Sourcepub fn acs_entries_resumable_with(
&self,
request: ActiveContractsRequest,
max_page_size: i32,
) -> impl Stream<Item = Result<AcsEntry>> + Send + use<>
pub fn acs_entries_resumable_with( &self, request: ActiveContractsRequest, max_page_size: i32, ) -> impl Stream<Item = Result<AcsEntry>> + Send + use<>
Like Self::acs_entries_resumable, with the full request surface of
an ActiveContractsRequest.
Sourcepub async fn updates(
&self,
parties: Vec<String>,
begin_offset: i64,
) -> Result<impl Stream<Item = Result<Update>> + Send + use<>>
pub async fn updates( &self, parties: Vec<String>, begin_offset: i64, ) -> Result<impl Stream<Item = Result<Update>> + Send + use<>>
Stream ledger updates — transactions and reassignments — for parties,
starting after begin_offset (exclusive). Offset checkpoints are
filtered out. Reassignments are surfaced as their own case (each
carrying the distinct Unassigned/Assigned events). Topology events
are not included; ask for them with
UpdatesRequest::with_topology_events
on Self::updates_with.
§Errors
Returns an Error if authentication or opening the stream fails.
Sourcepub async fn updates_with(
&self,
request: UpdatesRequest,
) -> Result<impl Stream<Item = Result<Update>> + Send + use<>>
pub async fn updates_with( &self, request: UpdatesRequest, ) -> Result<impl Stream<Item = Result<Update>> + Send + use<>>
Like Self::updates, with the full request surface: an
UpdatesRequest additionally bounds
the stream at an end offset (until — the catch-up/sync form, after
which the stream terminates), filters by template or interface, selects
the ACS-delta shape, includes created-event blobs or topology events,
and drops reassignments or record labels.
§Errors
Returns an Error if authentication or opening the stream fails.
Sourcepub fn updates_resumable(
&self,
parties: Vec<String>,
begin_offset: i64,
) -> impl Stream<Item = Result<Update>> + Send + use<>
pub fn updates_resumable( &self, parties: Vec<String>, begin_offset: i64, ) -> impl Stream<Item = Result<Update>> + Send + use<>
Like Self::updates, but resumable: on a retriable stream error it
reconnects from the last offset it observed (rather than restarting
from begin_offset or losing position), with a short backoff and a
bounded number of consecutive reconnects (see the client’s
RetryConfig).
Observed includes the participant’s OffsetCheckpoint frames, which are
filtered out of what this yields but are the only thing that advances the
resume point on a stream where nothing is happening. Once the reconnect
budget is spent the stream yields the failure that caused it — the
participant’s status, details and retriable classification intact —
rather than an error of the SDK’s own.
§Example
use tokio_stream::StreamExt as _;
let stream = client.updates_resumable(vec![party], 0);
tokio::pin!(stream);
while let Some(update) = stream.next().await {
println!("update: {:?}", update?);
}Sourcepub fn updates_resumable_with(
&self,
request: UpdatesRequest,
) -> impl Stream<Item = Result<Update>> + Send + use<>
pub fn updates_resumable_with( &self, request: UpdatesRequest, ) -> impl Stream<Item = Result<Update>> + Send + use<>
Like Self::updates_resumable, with the full request surface of an
UpdatesRequest. A bounded request
(until) makes this a resilient catch-up read: reconnects resume
from the last observed offset, and the stream ends once the participant
closes it at the end offset.
Trait Implementations§
Source§impl Clone for CantonClient
impl Clone for CantonClient
Source§fn clone(&self) -> CantonClient
fn clone(&self) -> CantonClient
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl !RefUnwindSafe for CantonClient
impl !UnwindSafe for CantonClient
impl Freeze for CantonClient
impl Send for CantonClient
impl Sync for CantonClient
impl Unpin for CantonClient
impl UnsafeUnpin for CantonClient
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> FutureExt for T
impl<T> FutureExt for T
Source§fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
Source§fn with_current_context(self) -> WithContext<Self> ⓘ
fn with_current_context(self) -> WithContext<Self> ⓘ
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::RequestSource§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
Source§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a tonic::Request