Skip to main content

ic_query/icrc/model/contracts/reports/
ledger.rs

1//! Module: icrc::model::contracts::reports::ledger
2//!
3//! Responsibility: serialized ICRC ledger metadata, capability, and history contracts.
4//! Does not own: account-index history, requests, live transport, archive following, or rendering.
5//! Boundary: preserves raw ledger, block, archive, certificate, and capability fields.
6
7use crate::icrc::{IcrcTokenData, IcrcTokenStandardRow};
8use serde::Serialize;
9use serde_json::Value as JsonValue;
10
11///
12/// IcrcTokenReport
13///
14/// Serializable report for generic ICRC ledger token metadata.
15///
16
17#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
18pub struct IcrcTokenReport {
19    /// Shared record, flattened in serialized output.
20    #[serde(flatten)]
21    pub provenance: super::IcrcReportProvenance,
22    /// Raw ledger metadata shared with token source capabilities.
23    #[serde(flatten)]
24    pub token: IcrcTokenData,
25}
26
27///
28/// IcrcIndexReport
29///
30/// Serializable report for one generic ICRC-106 index discovery lookup.
31///
32
33#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
34pub struct IcrcIndexReport {
35    /// Shared record, flattened in serialized output.
36    #[serde(flatten)]
37    pub provenance: super::IcrcReportProvenance,
38    pub index_canister_id: Option<String>,
39    pub index_error: Option<String>,
40}
41
42///
43/// IcrcTransactionsData
44///
45/// Source-layer ICRC-3 block history result from a ledger canister.
46///
47
48#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
49pub struct IcrcTransactionsData {
50    /// Total number of blocks as a decimal natural, or unknown for custom sources.
51    /// Returned blocks and archive ranges must stay below this length when known.
52    pub log_length: Option<String>,
53    /// Blocks returned directly by the ledger.
54    pub blocks: Vec<IcrcTransactionBlockRow>,
55    /// Archive referrals returned for the requested page.
56    pub archived_blocks: Vec<IcrcArchivedBlocksRow>,
57    /// Blocks retained from successful archive callbacks.
58    pub followed_archive_blocks: Vec<IcrcFollowedArchiveBlockRow>,
59    /// Bounded failures retained while following archive callbacks.
60    pub archive_follow_errors: Vec<IcrcArchiveFollowErrorRow>,
61}
62
63///
64/// IcrcTransactionsReport
65///
66/// Serializable report for a generic ICRC ledger transaction/block history page.
67///
68
69#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
70pub struct IcrcTransactionsReport {
71    /// Shared record, flattened in serialized output.
72    #[serde(flatten)]
73    pub provenance: super::IcrcReportProvenance,
74    pub requested_start: String,
75    pub requested_limit: u32,
76    pub follow_archives: bool,
77    /// Canonical history payload.
78    #[serde(flatten)]
79    pub transactions: IcrcTransactionsData,
80}
81
82///
83/// IcrcBlockTypesReport
84///
85/// Serializable report for generic ICRC-3 supported block type discovery.
86///
87
88#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
89pub struct IcrcBlockTypesReport {
90    /// Shared record, flattened in serialized output.
91    #[serde(flatten)]
92    pub provenance: super::IcrcReportProvenance,
93    pub block_types: Vec<IcrcBlockTypeRow>,
94}
95
96///
97/// IcrcArchivesReport
98///
99/// Serializable report for generic ICRC-3 archive range discovery.
100///
101
102#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
103pub struct IcrcArchivesReport {
104    /// Shared record, flattened in serialized output.
105    #[serde(flatten)]
106    pub provenance: super::IcrcReportProvenance,
107    pub from_canister_id: Option<String>,
108    pub archives: Vec<IcrcArchiveRow>,
109}
110
111///
112/// IcrcTipCertificateReport
113///
114/// Serializable report for a generic ICRC-3 ledger tip certificate.
115///
116
117#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
118pub struct IcrcTipCertificateReport {
119    /// Shared record, flattened in serialized output.
120    #[serde(flatten)]
121    pub provenance: super::IcrcReportProvenance,
122    pub certificate_present: bool,
123    pub certificate_hex: Option<String>,
124    pub certificate_bytes: Option<usize>,
125    pub hash_tree_hex: Option<String>,
126    pub hash_tree_bytes: Option<usize>,
127}
128
129///
130/// IcrcCapabilitiesReport
131///
132/// Serializable report for generic ICRC ledger endpoint capabilities.
133///
134
135#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
136pub struct IcrcCapabilitiesReport {
137    /// Shared record, flattened in serialized output.
138    #[serde(flatten)]
139    pub provenance: super::IcrcReportProvenance,
140    pub supported_standards: Vec<IcrcTokenStandardRow>,
141    pub capabilities: Vec<IcrcCapabilityRow>,
142}
143
144///
145/// IcrcCapabilityRow
146///
147/// Serializable row for one probed generic ICRC ledger capability.
148///
149
150#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
151pub struct IcrcCapabilityRow {
152    pub capability: String,
153    pub method: String,
154    pub status: IcrcCapabilityStatus,
155    pub details: Option<String>,
156    pub error: Option<String>,
157}
158
159///
160/// IcrcCapabilityStatus
161///
162/// Result of probing one optional ICRC ledger capability.
163///
164
165#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize)]
166#[serde(rename_all = "snake_case")]
167pub enum IcrcCapabilityStatus {
168    /// The target answered the capability query successfully.
169    Available,
170    /// The target does not export the probed query method.
171    Unsupported,
172    /// The target exports the method but the query failed.
173    Error,
174}
175
176impl IcrcCapabilityStatus {
177    /// Return the stable JSON and text label.
178    #[must_use]
179    pub const fn as_str(self) -> &'static str {
180        match self {
181            Self::Available => "available",
182            Self::Unsupported => "unsupported",
183            Self::Error => "error",
184        }
185    }
186}
187
188///
189/// IcrcTransactionBlockRow
190///
191/// Serializable row for one ICRC-3 block returned by a ledger canister.
192///
193
194#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
195pub struct IcrcTransactionBlockRow {
196    pub index: String,
197    pub block_type: Option<String>,
198    pub transaction_kind: Option<String>,
199    pub timestamp_unix_nanos: Option<String>,
200    pub amount_base_units: Option<String>,
201    pub raw_block: JsonValue,
202}
203
204///
205/// IcrcArchivedBlocksRow
206///
207/// Serializable row for one ICRC-3 archive callback returned by a ledger canister.
208///
209
210#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
211pub struct IcrcArchivedBlocksRow {
212    pub callback_canister_id: String,
213    pub callback_method: String,
214    pub ranges: Vec<IcrcArchivedRangeRow>,
215}
216
217///
218/// IcrcArchivedRangeRow
219///
220/// Serializable row for one ICRC-3 archived block range.
221///
222
223#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
224pub struct IcrcArchivedRangeRow {
225    pub start: String,
226    pub length: String,
227}
228
229///
230/// IcrcFollowedArchiveBlockRow
231///
232/// Serializable row for one ICRC-3 block fetched from an archive callback.
233///
234
235#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
236pub struct IcrcFollowedArchiveBlockRow {
237    pub archive_canister_id: String,
238    pub callback_method: String,
239    /// Canonical block summary and raw evidence.
240    #[serde(flatten)]
241    pub block: IcrcTransactionBlockRow,
242}
243
244#[cfg(test)]
245mod tests {
246    use super::*;
247
248    #[test]
249    fn capability_status_labels_are_stable() {
250        for (status, label) in [
251            (IcrcCapabilityStatus::Available, "available"),
252            (IcrcCapabilityStatus::Unsupported, "unsupported"),
253            (IcrcCapabilityStatus::Error, "error"),
254        ] {
255            assert_eq!(
256                serde_json::to_string(&status).unwrap(),
257                format!("\"{label}\"")
258            );
259            assert_eq!(status.as_str(), label);
260        }
261    }
262}
263
264///
265/// IcrcArchiveFollowErrorRow
266///
267/// Serializable row for one archive callback that could not be followed.
268///
269
270#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
271pub struct IcrcArchiveFollowErrorRow {
272    pub callback_canister_id: String,
273    pub callback_method: String,
274    pub ranges: Vec<IcrcArchivedRangeRow>,
275    pub error: String,
276}
277
278///
279/// IcrcBlockTypeRow
280///
281/// Serializable row for one supported ICRC-3 block type.
282///
283
284#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
285pub struct IcrcBlockTypeRow {
286    pub block_type: String,
287    pub url: String,
288}
289
290///
291/// IcrcArchiveRow
292///
293/// Serializable row for one ICRC-3 archive range.
294///
295
296#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
297pub struct IcrcArchiveRow {
298    pub canister_id: String,
299    pub start: String,
300    pub end: String,
301}