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 serde::Serialize;
8use serde_json::Value as JsonValue;
9
10///
11/// IcrcTokenReport
12///
13/// Serializable report for generic ICRC ledger token metadata.
14///
15
16#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
17pub struct IcrcTokenReport {
18    pub schema_version: u32,
19    pub ledger_canister_id: String,
20    pub fetched_at: String,
21    pub source_endpoint: String,
22    pub fetched_by: String,
23    pub token_name: String,
24    pub token_symbol: String,
25    pub decimals: u8,
26    pub transfer_fee: String,
27    pub total_supply: String,
28    pub minting_account_owner: Option<String>,
29    pub minting_account_subaccount_hex: Option<String>,
30    pub supported_standards: Vec<IcrcTokenStandardRow>,
31    pub metadata: Vec<IcrcTokenMetadataRow>,
32}
33
34///
35/// IcrcIndexReport
36///
37/// Serializable report for one generic ICRC-106 index discovery lookup.
38///
39
40#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
41pub struct IcrcIndexReport {
42    pub schema_version: u32,
43    pub ledger_canister_id: String,
44    pub fetched_at: String,
45    pub source_endpoint: String,
46    pub fetched_by: String,
47    pub index_canister_id: Option<String>,
48    pub index_error: Option<String>,
49}
50
51///
52/// IcrcTransactionsReport
53///
54/// Serializable report for a generic ICRC ledger transaction/block history page.
55///
56
57#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
58pub struct IcrcTransactionsReport {
59    pub schema_version: u32,
60    pub ledger_canister_id: String,
61    pub fetched_at: String,
62    pub source_endpoint: String,
63    pub fetched_by: String,
64    pub requested_start: String,
65    pub requested_limit: u32,
66    pub follow_archives: bool,
67    pub log_length: Option<String>,
68    pub blocks: Vec<IcrcTransactionBlockRow>,
69    pub archived_blocks: Vec<IcrcArchivedBlocksRow>,
70    pub followed_archive_blocks: Vec<IcrcFollowedArchiveBlockRow>,
71    pub archive_follow_errors: Vec<IcrcArchiveFollowErrorRow>,
72}
73
74///
75/// IcrcBlockTypesReport
76///
77/// Serializable report for generic ICRC-3 supported block type discovery.
78///
79
80#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
81pub struct IcrcBlockTypesReport {
82    pub schema_version: u32,
83    pub ledger_canister_id: String,
84    pub fetched_at: String,
85    pub source_endpoint: String,
86    pub fetched_by: String,
87    pub block_types: Vec<IcrcBlockTypeRow>,
88}
89
90///
91/// IcrcArchivesReport
92///
93/// Serializable report for generic ICRC-3 archive range discovery.
94///
95
96#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
97pub struct IcrcArchivesReport {
98    pub schema_version: u32,
99    pub ledger_canister_id: String,
100    pub from_canister_id: Option<String>,
101    pub fetched_at: String,
102    pub source_endpoint: String,
103    pub fetched_by: String,
104    pub archives: Vec<IcrcArchiveRow>,
105}
106
107///
108/// IcrcTipCertificateReport
109///
110/// Serializable report for a generic ICRC-3 ledger tip certificate.
111///
112
113#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
114pub struct IcrcTipCertificateReport {
115    pub schema_version: u32,
116    pub ledger_canister_id: String,
117    pub fetched_at: String,
118    pub source_endpoint: String,
119    pub fetched_by: String,
120    pub certificate_present: bool,
121    pub certificate_hex: Option<String>,
122    pub certificate_bytes: Option<usize>,
123    pub hash_tree_hex: Option<String>,
124    pub hash_tree_bytes: Option<usize>,
125}
126
127///
128/// IcrcCapabilitiesReport
129///
130/// Serializable report for generic ICRC ledger endpoint capabilities.
131///
132
133#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
134pub struct IcrcCapabilitiesReport {
135    pub schema_version: u32,
136    pub ledger_canister_id: String,
137    pub fetched_at: String,
138    pub source_endpoint: String,
139    pub fetched_by: String,
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/// IcrcTokenStandardRow
190///
191/// Serializable row for one ICRC standard supported by a ledger.
192///
193
194#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
195pub struct IcrcTokenStandardRow {
196    pub name: String,
197    pub url: String,
198}
199
200///
201/// IcrcTokenMetadataRow
202///
203/// Serializable row for one raw ICRC ledger metadata entry.
204///
205
206#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
207pub struct IcrcTokenMetadataRow {
208    pub key: String,
209    pub value_type: String,
210    pub value: JsonValue,
211}
212
213///
214/// IcrcTransactionBlockRow
215///
216/// Serializable row for one ICRC-3 block returned by a ledger canister.
217///
218
219#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
220pub struct IcrcTransactionBlockRow {
221    pub index: String,
222    pub block_type: Option<String>,
223    pub transaction_kind: Option<String>,
224    pub timestamp_unix_nanos: Option<String>,
225    pub amount_base_units: Option<String>,
226    pub raw_block: JsonValue,
227}
228
229///
230/// IcrcArchivedBlocksRow
231///
232/// Serializable row for one ICRC-3 archive callback returned by a ledger canister.
233///
234
235#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
236pub struct IcrcArchivedBlocksRow {
237    pub callback_canister_id: String,
238    pub callback_method: String,
239    pub ranges: Vec<IcrcArchivedRangeRow>,
240}
241
242///
243/// IcrcArchivedRangeRow
244///
245/// Serializable row for one ICRC-3 archived block range.
246///
247
248#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
249pub struct IcrcArchivedRangeRow {
250    pub start: String,
251    pub length: String,
252}
253
254///
255/// IcrcFollowedArchiveBlockRow
256///
257/// Serializable row for one ICRC-3 block fetched from an archive callback.
258///
259
260#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
261pub struct IcrcFollowedArchiveBlockRow {
262    pub archive_canister_id: String,
263    pub callback_method: String,
264    pub index: String,
265    pub block_type: Option<String>,
266    pub transaction_kind: Option<String>,
267    pub timestamp_unix_nanos: Option<String>,
268    pub amount_base_units: Option<String>,
269    pub raw_block: JsonValue,
270}
271
272#[cfg(test)]
273mod tests {
274    use super::*;
275
276    #[test]
277    fn capability_status_labels_are_stable() {
278        for (status, label) in [
279            (IcrcCapabilityStatus::Available, "available"),
280            (IcrcCapabilityStatus::Unsupported, "unsupported"),
281            (IcrcCapabilityStatus::Error, "error"),
282        ] {
283            assert_eq!(
284                serde_json::to_string(&status).unwrap(),
285                format!("\"{label}\"")
286            );
287            assert_eq!(status.as_str(), label);
288        }
289    }
290}
291
292///
293/// IcrcArchiveFollowErrorRow
294///
295/// Serializable row for one archive callback that could not be followed.
296///
297
298#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
299pub struct IcrcArchiveFollowErrorRow {
300    pub callback_canister_id: String,
301    pub callback_method: String,
302    pub ranges: Vec<IcrcArchivedRangeRow>,
303    pub error: String,
304}
305
306///
307/// IcrcBlockTypeRow
308///
309/// Serializable row for one supported ICRC-3 block type.
310///
311
312#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
313pub struct IcrcBlockTypeRow {
314    pub block_type: String,
315    pub url: String,
316}
317
318///
319/// IcrcArchiveRow
320///
321/// Serializable row for one ICRC-3 archive range.
322///
323
324#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
325pub struct IcrcArchiveRow {
326    pub canister_id: String,
327    pub start: String,
328    pub end: String,
329}