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