Skip to main content

ic_query/icrc/model/
contracts.rs

1//! Module: icrc::model::contracts
2//!
3//! Responsibility: public ICRC request, report, and serializable row contracts.
4//! Does not own: errors, source-layer data, subaccount validation, live transport, or rendering.
5//! Boundary: preserves the public request API and raw JSON report fields.
6
7use serde::Serialize;
8use serde_json::Value as JsonValue;
9
10///
11/// IcrcTokenRequest
12///
13/// Request accepted by the generic ICRC token metadata report builder.
14///
15#[derive(Clone, Debug, Eq, PartialEq)]
16pub struct IcrcTokenRequest {
17    pub source_endpoint: String,
18    pub now_unix_secs: u64,
19    pub ledger_canister_id: String,
20}
21
22impl IcrcTokenRequest {
23    #[must_use]
24    pub fn new(
25        source_endpoint: impl Into<String>,
26        now_unix_secs: u64,
27        ledger_canister_id: impl Into<String>,
28    ) -> Self {
29        Self {
30            source_endpoint: source_endpoint.into(),
31            now_unix_secs,
32            ledger_canister_id: ledger_canister_id.into(),
33        }
34    }
35}
36
37///
38/// IcrcBalanceRequest
39///
40/// Request accepted by the generic ICRC account balance report builder.
41///
42#[derive(Clone, Debug, Eq, PartialEq)]
43pub struct IcrcBalanceRequest {
44    pub source_endpoint: String,
45    pub now_unix_secs: u64,
46    pub ledger_canister_id: String,
47    pub account_owner: String,
48    pub subaccount_hex: Option<String>,
49}
50
51impl IcrcBalanceRequest {
52    #[must_use]
53    pub fn new(
54        source_endpoint: impl Into<String>,
55        now_unix_secs: u64,
56        ledger_canister_id: impl Into<String>,
57        account_owner: impl Into<String>,
58    ) -> Self {
59        Self {
60            source_endpoint: source_endpoint.into(),
61            now_unix_secs,
62            ledger_canister_id: ledger_canister_id.into(),
63            account_owner: account_owner.into(),
64            subaccount_hex: None,
65        }
66    }
67
68    #[must_use]
69    pub fn with_subaccount_hex(mut self, subaccount_hex: impl Into<String>) -> Self {
70        self.subaccount_hex = Some(subaccount_hex.into());
71        self
72    }
73}
74
75///
76/// IcrcAllowanceRequest
77///
78/// Request accepted by the generic ICRC allowance report builder.
79///
80#[derive(Clone, Debug, Eq, PartialEq)]
81pub struct IcrcAllowanceRequest {
82    pub source_endpoint: String,
83    pub now_unix_secs: u64,
84    pub ledger_canister_id: String,
85    pub account_owner: String,
86    pub account_subaccount_hex: Option<String>,
87    pub spender_owner: String,
88    pub spender_subaccount_hex: Option<String>,
89}
90
91impl IcrcAllowanceRequest {
92    #[must_use]
93    pub fn new(
94        source_endpoint: impl Into<String>,
95        now_unix_secs: u64,
96        ledger_canister_id: impl Into<String>,
97        account_owner: impl Into<String>,
98        spender_owner: impl Into<String>,
99    ) -> Self {
100        Self {
101            source_endpoint: source_endpoint.into(),
102            now_unix_secs,
103            ledger_canister_id: ledger_canister_id.into(),
104            account_owner: account_owner.into(),
105            account_subaccount_hex: None,
106            spender_owner: spender_owner.into(),
107            spender_subaccount_hex: None,
108        }
109    }
110
111    #[must_use]
112    pub fn with_account_subaccount_hex(
113        mut self,
114        account_subaccount_hex: impl Into<String>,
115    ) -> Self {
116        self.account_subaccount_hex = Some(account_subaccount_hex.into());
117        self
118    }
119
120    #[must_use]
121    pub fn with_spender_subaccount_hex(
122        mut self,
123        spender_subaccount_hex: impl Into<String>,
124    ) -> Self {
125        self.spender_subaccount_hex = Some(spender_subaccount_hex.into());
126        self
127    }
128}
129
130///
131/// IcrcIndexRequest
132///
133/// Request accepted by the generic ICRC index discovery report builder.
134///
135#[derive(Clone, Debug, Eq, PartialEq)]
136pub struct IcrcIndexRequest {
137    pub source_endpoint: String,
138    pub now_unix_secs: u64,
139    pub ledger_canister_id: String,
140}
141
142impl IcrcIndexRequest {
143    #[must_use]
144    pub fn new(
145        source_endpoint: impl Into<String>,
146        now_unix_secs: u64,
147        ledger_canister_id: impl Into<String>,
148    ) -> Self {
149        Self {
150            source_endpoint: source_endpoint.into(),
151            now_unix_secs,
152            ledger_canister_id: ledger_canister_id.into(),
153        }
154    }
155}
156
157///
158/// IcrcTransactionsRequest
159///
160/// Request accepted by the generic ICRC transaction history report builder.
161///
162#[derive(Clone, Debug, Eq, PartialEq)]
163pub struct IcrcTransactionsRequest {
164    pub source_endpoint: String,
165    pub now_unix_secs: u64,
166    pub ledger_canister_id: String,
167    pub start: u64,
168    pub limit: u32,
169    pub follow_archives: bool,
170}
171
172impl IcrcTransactionsRequest {
173    #[must_use]
174    pub fn new(
175        source_endpoint: impl Into<String>,
176        now_unix_secs: u64,
177        ledger_canister_id: impl Into<String>,
178        start: u64,
179        limit: u32,
180    ) -> Self {
181        Self {
182            source_endpoint: source_endpoint.into(),
183            now_unix_secs,
184            ledger_canister_id: ledger_canister_id.into(),
185            start,
186            limit,
187            follow_archives: false,
188        }
189    }
190
191    #[must_use]
192    pub const fn with_follow_archives(mut self, follow_archives: bool) -> Self {
193        self.follow_archives = follow_archives;
194        self
195    }
196}
197
198///
199/// IcrcBlockTypesRequest
200///
201/// Request accepted by the generic ICRC supported block types report builder.
202///
203#[derive(Clone, Debug, Eq, PartialEq)]
204pub struct IcrcBlockTypesRequest {
205    pub source_endpoint: String,
206    pub now_unix_secs: u64,
207    pub ledger_canister_id: String,
208}
209
210impl IcrcBlockTypesRequest {
211    #[must_use]
212    pub fn new(
213        source_endpoint: impl Into<String>,
214        now_unix_secs: u64,
215        ledger_canister_id: impl Into<String>,
216    ) -> Self {
217        Self {
218            source_endpoint: source_endpoint.into(),
219            now_unix_secs,
220            ledger_canister_id: ledger_canister_id.into(),
221        }
222    }
223}
224
225///
226/// IcrcArchivesRequest
227///
228/// Request accepted by the generic ICRC archives report builder.
229///
230#[derive(Clone, Debug, Eq, PartialEq)]
231pub struct IcrcArchivesRequest {
232    pub source_endpoint: String,
233    pub now_unix_secs: u64,
234    pub ledger_canister_id: String,
235    pub from_canister_id: Option<String>,
236}
237
238impl IcrcArchivesRequest {
239    #[must_use]
240    pub fn new(
241        source_endpoint: impl Into<String>,
242        now_unix_secs: u64,
243        ledger_canister_id: impl Into<String>,
244    ) -> Self {
245        Self {
246            source_endpoint: source_endpoint.into(),
247            now_unix_secs,
248            ledger_canister_id: ledger_canister_id.into(),
249            from_canister_id: None,
250        }
251    }
252
253    #[must_use]
254    pub fn with_from_canister_id(mut self, from_canister_id: impl Into<String>) -> Self {
255        self.from_canister_id = Some(from_canister_id.into());
256        self
257    }
258}
259
260///
261/// IcrcTipCertificateRequest
262///
263/// Request accepted by the generic ICRC-3 tip certificate report builder.
264///
265#[derive(Clone, Debug, Eq, PartialEq)]
266pub struct IcrcTipCertificateRequest {
267    pub source_endpoint: String,
268    pub now_unix_secs: u64,
269    pub ledger_canister_id: String,
270}
271
272impl IcrcTipCertificateRequest {
273    #[must_use]
274    pub fn new(
275        source_endpoint: impl Into<String>,
276        now_unix_secs: u64,
277        ledger_canister_id: impl Into<String>,
278    ) -> Self {
279        Self {
280            source_endpoint: source_endpoint.into(),
281            now_unix_secs,
282            ledger_canister_id: ledger_canister_id.into(),
283        }
284    }
285}
286
287///
288/// IcrcCapabilitiesRequest
289///
290/// Request accepted by the generic ICRC ledger capabilities report builder.
291///
292#[derive(Clone, Debug, Eq, PartialEq)]
293pub struct IcrcCapabilitiesRequest {
294    pub source_endpoint: String,
295    pub now_unix_secs: u64,
296    pub ledger_canister_id: String,
297}
298
299impl IcrcCapabilitiesRequest {
300    #[must_use]
301    pub fn new(
302        source_endpoint: impl Into<String>,
303        now_unix_secs: u64,
304        ledger_canister_id: impl Into<String>,
305    ) -> Self {
306        Self {
307            source_endpoint: source_endpoint.into(),
308            now_unix_secs,
309            ledger_canister_id: ledger_canister_id.into(),
310        }
311    }
312}
313
314///
315/// IcrcTokenReport
316///
317/// Serializable report for generic ICRC ledger token metadata.
318///
319#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
320pub struct IcrcTokenReport {
321    pub schema_version: u32,
322    pub ledger_canister_id: String,
323    pub fetched_at: String,
324    pub source_endpoint: String,
325    pub fetched_by: String,
326    pub token_name: String,
327    pub token_symbol: String,
328    pub decimals: u8,
329    pub transfer_fee: String,
330    pub total_supply: String,
331    pub minting_account_owner: Option<String>,
332    pub minting_account_subaccount_hex: Option<String>,
333    pub supported_standards: Vec<IcrcTokenStandardRow>,
334    pub metadata: Vec<IcrcTokenMetadataRow>,
335}
336
337///
338/// IcrcBalanceReport
339///
340/// Serializable report for one generic ICRC account balance lookup.
341///
342#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
343pub struct IcrcBalanceReport {
344    pub schema_version: u32,
345    pub ledger_canister_id: String,
346    pub account_owner: String,
347    pub subaccount_hex: Option<String>,
348    pub fetched_at: String,
349    pub source_endpoint: String,
350    pub fetched_by: String,
351    pub token_symbol: String,
352    pub decimals: u8,
353    pub balance: String,
354}
355
356///
357/// IcrcAllowanceReport
358///
359/// Serializable report for one generic ICRC allowance lookup.
360///
361#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
362pub struct IcrcAllowanceReport {
363    pub schema_version: u32,
364    pub ledger_canister_id: String,
365    pub account_owner: String,
366    pub account_subaccount_hex: Option<String>,
367    pub spender_owner: String,
368    pub spender_subaccount_hex: Option<String>,
369    pub fetched_at: String,
370    pub source_endpoint: String,
371    pub fetched_by: String,
372    pub token_symbol: String,
373    pub decimals: u8,
374    pub allowance: String,
375    pub expires_at_unix_nanos: Option<String>,
376}
377
378///
379/// IcrcIndexReport
380///
381/// Serializable report for one generic ICRC-106 index discovery lookup.
382///
383#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
384pub struct IcrcIndexReport {
385    pub schema_version: u32,
386    pub ledger_canister_id: String,
387    pub fetched_at: String,
388    pub source_endpoint: String,
389    pub fetched_by: String,
390    pub index_canister_id: Option<String>,
391    pub index_error: Option<String>,
392}
393
394///
395/// IcrcTransactionsReport
396///
397/// Serializable report for a generic ICRC ledger transaction/block history page.
398///
399#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
400pub struct IcrcTransactionsReport {
401    pub schema_version: u32,
402    pub ledger_canister_id: String,
403    pub fetched_at: String,
404    pub source_endpoint: String,
405    pub fetched_by: String,
406    pub requested_start: String,
407    pub requested_limit: u32,
408    pub follow_archives: bool,
409    pub log_length: Option<String>,
410    pub blocks: Vec<IcrcTransactionBlockRow>,
411    pub archived_blocks: Vec<IcrcArchivedBlocksRow>,
412    pub followed_archive_blocks: Vec<IcrcFollowedArchiveBlockRow>,
413    pub archive_follow_errors: Vec<IcrcArchiveFollowErrorRow>,
414}
415
416///
417/// IcrcBlockTypesReport
418///
419/// Serializable report for generic ICRC-3 supported block type discovery.
420///
421#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
422pub struct IcrcBlockTypesReport {
423    pub schema_version: u32,
424    pub ledger_canister_id: String,
425    pub fetched_at: String,
426    pub source_endpoint: String,
427    pub fetched_by: String,
428    pub block_types: Vec<IcrcBlockTypeRow>,
429}
430
431///
432/// IcrcArchivesReport
433///
434/// Serializable report for generic ICRC-3 archive range discovery.
435///
436#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
437pub struct IcrcArchivesReport {
438    pub schema_version: u32,
439    pub ledger_canister_id: String,
440    pub from_canister_id: Option<String>,
441    pub fetched_at: String,
442    pub source_endpoint: String,
443    pub fetched_by: String,
444    pub archives: Vec<IcrcArchiveRow>,
445}
446
447///
448/// IcrcTipCertificateReport
449///
450/// Serializable report for a generic ICRC-3 ledger tip certificate.
451///
452#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
453pub struct IcrcTipCertificateReport {
454    pub schema_version: u32,
455    pub ledger_canister_id: String,
456    pub fetched_at: String,
457    pub source_endpoint: String,
458    pub fetched_by: String,
459    pub certificate_present: bool,
460    pub certificate_hex: Option<String>,
461    pub certificate_bytes: Option<usize>,
462    pub hash_tree_hex: Option<String>,
463    pub hash_tree_bytes: Option<usize>,
464}
465
466///
467/// IcrcCapabilitiesReport
468///
469/// Serializable report for generic ICRC ledger endpoint capabilities.
470///
471#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
472pub struct IcrcCapabilitiesReport {
473    pub schema_version: u32,
474    pub ledger_canister_id: String,
475    pub fetched_at: String,
476    pub source_endpoint: String,
477    pub fetched_by: String,
478    pub supported_standards: Vec<IcrcTokenStandardRow>,
479    pub capabilities: Vec<IcrcCapabilityRow>,
480}
481
482///
483/// IcrcCapabilityRow
484///
485/// Serializable row for one probed generic ICRC ledger capability.
486///
487#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
488pub struct IcrcCapabilityRow {
489    pub capability: String,
490    pub method: String,
491    pub status: String,
492    pub details: Option<String>,
493    pub error: Option<String>,
494}
495
496///
497/// IcrcTokenStandardRow
498///
499/// Serializable row for one ICRC standard supported by a ledger.
500///
501#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
502pub struct IcrcTokenStandardRow {
503    pub name: String,
504    pub url: String,
505}
506
507///
508/// IcrcTokenMetadataRow
509///
510/// Serializable row for one raw ICRC ledger metadata entry.
511///
512#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
513pub struct IcrcTokenMetadataRow {
514    pub key: String,
515    pub value_type: String,
516    pub value: JsonValue,
517}
518
519///
520/// IcrcTransactionBlockRow
521///
522/// Serializable row for one ICRC-3 block returned by a ledger canister.
523///
524#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
525pub struct IcrcTransactionBlockRow {
526    pub index: String,
527    pub block_type: Option<String>,
528    pub transaction_kind: Option<String>,
529    pub timestamp_unix_nanos: Option<String>,
530    pub amount_base_units: Option<String>,
531    pub raw_block: JsonValue,
532}
533
534///
535/// IcrcArchivedBlocksRow
536///
537/// Serializable row for one ICRC-3 archive callback returned by a ledger canister.
538///
539#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
540pub struct IcrcArchivedBlocksRow {
541    pub callback_canister_id: String,
542    pub callback_method: String,
543    pub ranges: Vec<IcrcArchivedRangeRow>,
544}
545
546///
547/// IcrcArchivedRangeRow
548///
549/// Serializable row for one ICRC-3 archived block range.
550///
551#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
552pub struct IcrcArchivedRangeRow {
553    pub start: String,
554    pub length: String,
555}
556
557///
558/// IcrcFollowedArchiveBlockRow
559///
560/// Serializable row for one ICRC-3 block fetched from an archive callback.
561///
562#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
563pub struct IcrcFollowedArchiveBlockRow {
564    pub archive_canister_id: String,
565    pub callback_method: String,
566    pub index: String,
567    pub block_type: Option<String>,
568    pub transaction_kind: Option<String>,
569    pub timestamp_unix_nanos: Option<String>,
570    pub amount_base_units: Option<String>,
571    pub raw_block: JsonValue,
572}
573
574///
575/// IcrcArchiveFollowErrorRow
576///
577/// Serializable row for one archive callback that could not be followed.
578///
579#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
580pub struct IcrcArchiveFollowErrorRow {
581    pub callback_canister_id: String,
582    pub callback_method: String,
583    pub ranges: Vec<IcrcArchivedRangeRow>,
584    pub error: String,
585}
586
587///
588/// IcrcBlockTypeRow
589///
590/// Serializable row for one supported ICRC-3 block type.
591///
592#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
593pub struct IcrcBlockTypeRow {
594    pub block_type: String,
595    pub url: String,
596}
597
598///
599/// IcrcArchiveRow
600///
601/// Serializable row for one ICRC-3 archive range.
602///
603#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
604pub struct IcrcArchiveRow {
605    pub canister_id: String,
606    pub start: String,
607    pub end: String,
608}