canton_token/lib.rs
1//! Canton Network token-standard workflows (CIP-56 and CIP-0112).
2//!
3//! The token-standard **types** are generated from the Splice DARs and live in
4//! the `canton-splice-api-token-*` crates. This crate is the *workflow* over
5//! them: resolving a factory, asking a registry for a choice context,
6//! attaching the contracts it says to disclose, and exercising the choice.
7//!
8//! Nothing here re-declares a Daml type. That would duplicate the code
9//! generator and go stale on the next Splice release; the `Holding` this crate
10//! names is the same Rust type an application reads out of the ledger.
11//!
12//! # Why a registry is involved at all
13//!
14//! A transfer is exercised through an interface, and only the registry knows
15//! what reference data that choice needs — its own configuration contracts,
16//! the rules for an instrument, the current round. So the client asks for a
17//! choice context and gets back both the data to pass in and the contracts the
18//! participant must be shown. Those contracts are usually invisible to the
19//! submitting party, which is exactly what explicit disclosure is for.
20//!
21//! The registry's API is off-ledger HTTP, specified by the token standard's
22//! OpenAPI documents.
23
24#![forbid(unsafe_code)]
25
26pub mod allocation;
27mod context;
28pub mod holdings;
29mod registry;
30pub mod transfer;
31pub mod v2;
32
33pub use context::{ChoiceContext, ChoiceContextRequest, WireChoiceContext, WireDisclosedContract};
34pub use registry::{
35 AllocationChoice, AllocationInstructionChoice, FactoryWithContext, Instrument, RegistryClient,
36 RegistryInfo, TransferInstructionChoice, TransferKind,
37};
38/// The V1 (CIP-56) workflow, re-exported at the root because it is the one most
39/// networks run today. The V2 (CIP-0112) workflow keeps the same names and so
40/// stays behind [`v2`] — `token::transfer` and `token::v2::transfer` are
41/// different standards, and the path is what says which you meant.
42pub use transfer::{TokenCommand, accept, reject, transfer, withdraw};
43
44pub mod types {
45 //! The generated token-standard types this crate's API is written in terms
46 //! of, re-exported so they can be named without depending on each
47 //! generated crate directly.
48 //!
49 //! This is not a convenience. `transfer` takes a
50 //! [`Transfer`](v1::transfer_instruction::Transfer) and `v2::transfer`
51 //! takes a [`Transfer`](v2::transfer_instruction::Transfer) — so without
52 //! these a `cargo add canton` user could reach the *functions* through the
53 //! facade and be unable to name their arguments. The whole token
54 //! deliverable was unreachable that way, which is the same defect the
55 //! crate's own conformance suite states the rule against: a capability
56 //! that works only via a member crate is not one `cargo add canton`
57 //! delivers.
58 //!
59 //! Whole modules rather than a hand-listed set of types, because a list
60 //! goes stale the first time the standard adds a record and nothing
61 //! notices.
62
63 /// Metadata — `ExtraArgs`, `ChoiceContext`, `Metadata`. Shared by both
64 /// standards: there is no `metadata-v2`.
65 pub use canton_splice_api_token_metadata_v1::splice_api_token_metadata_v1::Splice_Api_Token_MetadataV1 as metadata;
66
67 /// CIP-56 — the V1 token standard.
68 pub mod v1 {
69 pub use canton_splice_api_token_allocation_instruction_v1::splice_api_token_allocation_instruction_v1::Splice_Api_Token_AllocationInstructionV1 as allocation_instruction;
70 pub use canton_splice_api_token_allocation_v1::splice_api_token_allocation_v1::Splice_Api_Token_AllocationV1 as allocation;
71 pub use canton_splice_api_token_holding_v1::splice_api_token_holding_v1::Splice_Api_Token_HoldingV1 as holding;
72 pub use canton_splice_api_token_transfer_instruction_v1::splice_api_token_transfer_instruction_v1::Splice_Api_Token_TransferInstructionV1 as transfer_instruction;
73 }
74
75 /// CIP-0112 — the V2 token standard.
76 pub mod v2 {
77 pub use canton_splice_api_token_allocation_instruction_v2::splice_api_token_allocation_instruction_v2::Splice_Api_Token_AllocationInstructionV2 as allocation_instruction;
78 pub use canton_splice_api_token_allocation_v2::splice_api_token_allocation_v2::Splice_Api_Token_AllocationV2 as allocation;
79 pub use canton_splice_api_token_holding_v2::splice_api_token_holding_v2::Splice_Api_Token_HoldingV2 as holding;
80 pub use canton_splice_api_token_transfer_events_v2::splice_api_token_transfer_events_v2::Splice_Api_Token_TransferEventsV2 as transfer_events;
81 pub use canton_splice_api_token_transfer_instruction_v2::splice_api_token_transfer_instruction_v2::Splice_Api_Token_TransferInstructionV2 as transfer_instruction;
82 }
83}
84
85/// The V1 `Holding` interface, at the root because it is the type a caller
86/// reaches for first. Everything else is under [`types`].
87pub use canton_splice_api_token_holding_v1::splice_api_token_holding_v1::Splice_Api_Token_HoldingV1::Holding;