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::{Deserialize as SerdeDeserialize, Serialize};
8use serde_json::Value as JsonValue;
9use std::path::PathBuf;
10
11///
12/// IcrcTokenRequest
13///
14/// Request accepted by the generic ICRC token metadata report builder.
15///
16
17#[derive(Clone, Debug, Eq, PartialEq)]
18pub struct IcrcTokenRequest {
19    pub source_endpoint: String,
20    pub now_unix_secs: u64,
21    pub ledger_canister_id: String,
22}
23
24impl IcrcTokenRequest {
25    #[must_use]
26    pub fn new(
27        source_endpoint: impl Into<String>,
28        now_unix_secs: u64,
29        ledger_canister_id: impl Into<String>,
30    ) -> Self {
31        Self {
32            source_endpoint: source_endpoint.into(),
33            now_unix_secs,
34            ledger_canister_id: ledger_canister_id.into(),
35        }
36    }
37}
38
39///
40/// IcrcBalanceRequest
41///
42/// Request accepted by the generic ICRC account balance report builder.
43///
44
45#[derive(Clone, Debug, Eq, PartialEq)]
46pub struct IcrcBalanceRequest {
47    pub source_endpoint: String,
48    pub now_unix_secs: u64,
49    pub ledger_canister_id: String,
50    pub account_owner: String,
51    pub subaccount_hex: Option<String>,
52}
53
54impl IcrcBalanceRequest {
55    #[must_use]
56    pub fn new(
57        source_endpoint: impl Into<String>,
58        now_unix_secs: u64,
59        ledger_canister_id: impl Into<String>,
60        account_owner: impl Into<String>,
61    ) -> Self {
62        Self {
63            source_endpoint: source_endpoint.into(),
64            now_unix_secs,
65            ledger_canister_id: ledger_canister_id.into(),
66            account_owner: account_owner.into(),
67            subaccount_hex: None,
68        }
69    }
70
71    #[must_use]
72    pub fn with_subaccount_hex(mut self, subaccount_hex: impl Into<String>) -> Self {
73        self.subaccount_hex = Some(subaccount_hex.into());
74        self
75    }
76}
77
78///
79/// IcrcAllowanceRequest
80///
81/// Request accepted by the generic ICRC allowance report builder.
82///
83
84#[derive(Clone, Debug, Eq, PartialEq)]
85pub struct IcrcAllowanceRequest {
86    pub source_endpoint: String,
87    pub now_unix_secs: u64,
88    pub ledger_canister_id: String,
89    pub account_owner: String,
90    pub account_subaccount_hex: Option<String>,
91    pub spender_owner: String,
92    pub spender_subaccount_hex: Option<String>,
93}
94
95impl IcrcAllowanceRequest {
96    #[must_use]
97    pub fn new(
98        source_endpoint: impl Into<String>,
99        now_unix_secs: u64,
100        ledger_canister_id: impl Into<String>,
101        account_owner: impl Into<String>,
102        spender_owner: impl Into<String>,
103    ) -> Self {
104        Self {
105            source_endpoint: source_endpoint.into(),
106            now_unix_secs,
107            ledger_canister_id: ledger_canister_id.into(),
108            account_owner: account_owner.into(),
109            account_subaccount_hex: None,
110            spender_owner: spender_owner.into(),
111            spender_subaccount_hex: None,
112        }
113    }
114
115    #[must_use]
116    pub fn with_account_subaccount_hex(
117        mut self,
118        account_subaccount_hex: impl Into<String>,
119    ) -> Self {
120        self.account_subaccount_hex = Some(account_subaccount_hex.into());
121        self
122    }
123
124    #[must_use]
125    pub fn with_spender_subaccount_hex(
126        mut self,
127        spender_subaccount_hex: impl Into<String>,
128    ) -> Self {
129        self.spender_subaccount_hex = Some(spender_subaccount_hex.into());
130        self
131    }
132}
133
134///
135/// IcrcAccountTransactionPageRequest
136///
137/// Request accepted by the live ICRC index account-transaction page builder.
138///
139
140#[derive(Clone, Debug, Eq, PartialEq)]
141pub struct IcrcAccountTransactionPageRequest {
142    /// IC API endpoint used for ledger and index queries.
143    pub source_endpoint: String,
144    /// Collection time as Unix seconds.
145    pub now_unix_secs: u64,
146    /// Ledger canister whose account history is requested.
147    pub ledger_canister_id: String,
148    /// Optional explicit index canister; otherwise ICRC-106 discovery is used.
149    pub index_canister_id: Option<String>,
150    /// Account owner principal.
151    pub account_owner: String,
152    /// Optional normalized 32-byte subaccount hex.
153    pub subaccount_hex: Option<String>,
154    /// Optional exclusive block-index cursor for backward pagination.
155    pub start: Option<String>,
156    /// Maximum number of account transactions to request.
157    pub limit: u32,
158}
159
160impl IcrcAccountTransactionPageRequest {
161    /// Constructs an account-history request that discovers the index through the ledger.
162    #[must_use]
163    pub fn new(
164        source_endpoint: impl Into<String>,
165        now_unix_secs: u64,
166        ledger_canister_id: impl Into<String>,
167        account_owner: impl Into<String>,
168        limit: u32,
169    ) -> Self {
170        Self {
171            source_endpoint: source_endpoint.into(),
172            now_unix_secs,
173            ledger_canister_id: ledger_canister_id.into(),
174            index_canister_id: None,
175            account_owner: account_owner.into(),
176            subaccount_hex: None,
177            start: None,
178            limit,
179        }
180    }
181
182    /// Uses an explicit index canister instead of ICRC-106 discovery.
183    #[must_use]
184    pub fn with_index_canister_id(mut self, index_canister_id: impl Into<String>) -> Self {
185        self.index_canister_id = Some(index_canister_id.into());
186        self
187    }
188
189    /// Selects a 32-byte ICRC subaccount encoded as hex.
190    #[must_use]
191    pub fn with_subaccount_hex(mut self, subaccount_hex: impl Into<String>) -> Self {
192        self.subaccount_hex = Some(subaccount_hex.into());
193        self
194    }
195
196    /// Starts after the given transaction block index when paginating backward.
197    #[must_use]
198    pub fn with_start(mut self, start: impl Into<String>) -> Self {
199        self.start = Some(start.into());
200        self
201    }
202}
203
204///
205/// IcrcAccountTransactionCacheRequest
206///
207/// Stable account-history cache identity independent of page and view options.
208///
209
210#[derive(Clone, Debug, Eq, PartialEq)]
211pub struct IcrcAccountTransactionCacheRequest {
212    /// Project root containing the `.icq` cache directory.
213    pub icp_root: PathBuf,
214    /// IC API endpoint whose indexed history is cached.
215    pub source_endpoint: String,
216    /// Ledger canister whose account history is cached.
217    pub ledger_canister_id: String,
218    /// Account owner principal.
219    pub account_owner: String,
220    /// Optional normalized 32-byte subaccount hex.
221    pub subaccount_hex: Option<String>,
222}
223
224impl IcrcAccountTransactionCacheRequest {
225    /// Constructs a cache identity for the default subaccount.
226    #[must_use]
227    pub fn new(
228        icp_root: impl Into<PathBuf>,
229        source_endpoint: impl Into<String>,
230        ledger_canister_id: impl Into<String>,
231        account_owner: impl Into<String>,
232    ) -> Self {
233        Self {
234            icp_root: icp_root.into(),
235            source_endpoint: source_endpoint.into(),
236            ledger_canister_id: ledger_canister_id.into(),
237            account_owner: account_owner.into(),
238            subaccount_hex: None,
239        }
240    }
241
242    /// Selects a 32-byte ICRC subaccount encoded as hex.
243    #[must_use]
244    pub fn with_subaccount_hex(mut self, subaccount_hex: impl Into<String>) -> Self {
245        self.subaccount_hex = Some(subaccount_hex.into());
246        self
247    }
248}
249
250///
251/// IcrcAccountTransactionRefreshRequest
252///
253/// Request for a forced complete account-history refresh.
254///
255
256#[derive(Clone, Debug, Eq, PartialEq)]
257pub struct IcrcAccountTransactionRefreshRequest {
258    /// Stable cache identity.
259    pub cache: IcrcAccountTransactionCacheRequest,
260    /// Collection start time as Unix seconds.
261    pub now_unix_secs: u64,
262    /// Optional explicit index canister; otherwise ICRC-106 discovery is used.
263    pub index_canister_id: Option<String>,
264    /// Maximum transactions requested per index page.
265    pub page_size: u32,
266    /// Optional diagnostic bound that fails rather than publishing a partial cache.
267    pub max_pages: Option<u32>,
268    /// Age after which an abandoned refresh lock is reported as stale.
269    pub lock_stale_after_seconds: u64,
270}
271
272impl IcrcAccountTransactionRefreshRequest {
273    /// Constructs a complete refresh request.
274    #[must_use]
275    pub const fn new(
276        cache: IcrcAccountTransactionCacheRequest,
277        now_unix_secs: u64,
278        page_size: u32,
279        lock_stale_after_seconds: u64,
280    ) -> Self {
281        Self {
282            cache,
283            now_unix_secs,
284            index_canister_id: None,
285            page_size,
286            max_pages: None,
287            lock_stale_after_seconds,
288        }
289    }
290
291    /// Uses an explicit index canister instead of ICRC-106 discovery.
292    #[must_use]
293    pub fn with_index_canister_id(mut self, index_canister_id: impl Into<String>) -> Self {
294        self.index_canister_id = Some(index_canister_id.into());
295        self
296    }
297
298    /// Bounds pages for diagnostics; reaching the bound never publishes a cache.
299    #[must_use]
300    pub const fn with_max_pages(mut self, max_pages: Option<u32>) -> Self {
301        self.max_pages = max_pages;
302        self
303    }
304}
305
306///
307/// IcrcAccountTransactionSort
308///
309/// Supported cached account-history ordering.
310///
311
312#[derive(Clone, Copy, Debug, Eq, PartialEq)]
313pub enum IcrcAccountTransactionSort {
314    /// Highest transaction id first.
315    Newest,
316    /// Lowest transaction id first.
317    Oldest,
318}
319
320impl IcrcAccountTransactionSort {
321    /// Stable JSON/text name for this ordering.
322    #[must_use]
323    pub const fn as_str(self) -> &'static str {
324        match self {
325            Self::Newest => "newest",
326            Self::Oldest => "oldest",
327        }
328    }
329}
330
331///
332/// IcrcAccountTransactionListRequest
333///
334/// Cache-only account-history list view.
335///
336
337#[derive(Clone, Debug, Eq, PartialEq)]
338pub struct IcrcAccountTransactionListRequest {
339    /// Stable cache identity.
340    pub cache: IcrcAccountTransactionCacheRequest,
341    /// Maximum cached rows returned by this view.
342    pub limit: u32,
343    /// Requested cached-row ordering.
344    pub sort: IcrcAccountTransactionSort,
345}
346
347impl IcrcAccountTransactionListRequest {
348    /// Constructs a newest-first cached list view.
349    #[must_use]
350    pub const fn new(cache: IcrcAccountTransactionCacheRequest, limit: u32) -> Self {
351        Self {
352            cache,
353            limit,
354            sort: IcrcAccountTransactionSort::Newest,
355        }
356    }
357
358    /// Selects cached-row ordering.
359    #[must_use]
360    pub const fn with_sort(mut self, sort: IcrcAccountTransactionSort) -> Self {
361        self.sort = sort;
362        self
363    }
364}
365
366///
367/// IcrcIndexRequest
368///
369/// Request accepted by the generic ICRC index discovery report builder.
370///
371
372#[derive(Clone, Debug, Eq, PartialEq)]
373pub struct IcrcIndexRequest {
374    pub source_endpoint: String,
375    pub now_unix_secs: u64,
376    pub ledger_canister_id: String,
377}
378
379impl IcrcIndexRequest {
380    #[must_use]
381    pub fn new(
382        source_endpoint: impl Into<String>,
383        now_unix_secs: u64,
384        ledger_canister_id: impl Into<String>,
385    ) -> Self {
386        Self {
387            source_endpoint: source_endpoint.into(),
388            now_unix_secs,
389            ledger_canister_id: ledger_canister_id.into(),
390        }
391    }
392}
393
394///
395/// IcrcTransactionsRequest
396///
397/// Request accepted by the generic ICRC transaction history report builder.
398///
399
400#[derive(Clone, Debug, Eq, PartialEq)]
401pub struct IcrcTransactionsRequest {
402    pub source_endpoint: String,
403    pub now_unix_secs: u64,
404    pub ledger_canister_id: String,
405    pub start: u64,
406    pub limit: u32,
407    pub follow_archives: bool,
408}
409
410impl IcrcTransactionsRequest {
411    #[must_use]
412    pub fn new(
413        source_endpoint: impl Into<String>,
414        now_unix_secs: u64,
415        ledger_canister_id: impl Into<String>,
416        start: u64,
417        limit: u32,
418    ) -> Self {
419        Self {
420            source_endpoint: source_endpoint.into(),
421            now_unix_secs,
422            ledger_canister_id: ledger_canister_id.into(),
423            start,
424            limit,
425            follow_archives: false,
426        }
427    }
428
429    #[must_use]
430    pub const fn with_follow_archives(mut self, follow_archives: bool) -> Self {
431        self.follow_archives = follow_archives;
432        self
433    }
434}
435
436///
437/// IcrcBlockTypesRequest
438///
439/// Request accepted by the generic ICRC supported block types report builder.
440///
441
442#[derive(Clone, Debug, Eq, PartialEq)]
443pub struct IcrcBlockTypesRequest {
444    pub source_endpoint: String,
445    pub now_unix_secs: u64,
446    pub ledger_canister_id: String,
447}
448
449impl IcrcBlockTypesRequest {
450    #[must_use]
451    pub fn new(
452        source_endpoint: impl Into<String>,
453        now_unix_secs: u64,
454        ledger_canister_id: impl Into<String>,
455    ) -> Self {
456        Self {
457            source_endpoint: source_endpoint.into(),
458            now_unix_secs,
459            ledger_canister_id: ledger_canister_id.into(),
460        }
461    }
462}
463
464///
465/// IcrcArchivesRequest
466///
467/// Request accepted by the generic ICRC archives report builder.
468///
469
470#[derive(Clone, Debug, Eq, PartialEq)]
471pub struct IcrcArchivesRequest {
472    pub source_endpoint: String,
473    pub now_unix_secs: u64,
474    pub ledger_canister_id: String,
475    pub from_canister_id: Option<String>,
476}
477
478impl IcrcArchivesRequest {
479    #[must_use]
480    pub fn new(
481        source_endpoint: impl Into<String>,
482        now_unix_secs: u64,
483        ledger_canister_id: impl Into<String>,
484    ) -> Self {
485        Self {
486            source_endpoint: source_endpoint.into(),
487            now_unix_secs,
488            ledger_canister_id: ledger_canister_id.into(),
489            from_canister_id: None,
490        }
491    }
492
493    #[must_use]
494    pub fn with_from_canister_id(mut self, from_canister_id: impl Into<String>) -> Self {
495        self.from_canister_id = Some(from_canister_id.into());
496        self
497    }
498}
499
500///
501/// IcrcTipCertificateRequest
502///
503/// Request accepted by the generic ICRC-3 tip certificate report builder.
504///
505
506#[derive(Clone, Debug, Eq, PartialEq)]
507pub struct IcrcTipCertificateRequest {
508    pub source_endpoint: String,
509    pub now_unix_secs: u64,
510    pub ledger_canister_id: String,
511}
512
513impl IcrcTipCertificateRequest {
514    #[must_use]
515    pub fn new(
516        source_endpoint: impl Into<String>,
517        now_unix_secs: u64,
518        ledger_canister_id: impl Into<String>,
519    ) -> Self {
520        Self {
521            source_endpoint: source_endpoint.into(),
522            now_unix_secs,
523            ledger_canister_id: ledger_canister_id.into(),
524        }
525    }
526}
527
528///
529/// IcrcCapabilitiesRequest
530///
531/// Request accepted by the generic ICRC ledger capabilities report builder.
532///
533
534#[derive(Clone, Debug, Eq, PartialEq)]
535pub struct IcrcCapabilitiesRequest {
536    pub source_endpoint: String,
537    pub now_unix_secs: u64,
538    pub ledger_canister_id: String,
539}
540
541impl IcrcCapabilitiesRequest {
542    #[must_use]
543    pub fn new(
544        source_endpoint: impl Into<String>,
545        now_unix_secs: u64,
546        ledger_canister_id: impl Into<String>,
547    ) -> Self {
548        Self {
549            source_endpoint: source_endpoint.into(),
550            now_unix_secs,
551            ledger_canister_id: ledger_canister_id.into(),
552        }
553    }
554}
555
556///
557/// IcrcTokenReport
558///
559/// Serializable report for generic ICRC ledger token metadata.
560///
561
562#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
563pub struct IcrcTokenReport {
564    pub schema_version: u32,
565    pub ledger_canister_id: String,
566    pub fetched_at: String,
567    pub source_endpoint: String,
568    pub fetched_by: String,
569    pub token_name: String,
570    pub token_symbol: String,
571    pub decimals: u8,
572    pub transfer_fee: String,
573    pub total_supply: String,
574    pub minting_account_owner: Option<String>,
575    pub minting_account_subaccount_hex: Option<String>,
576    pub supported_standards: Vec<IcrcTokenStandardRow>,
577    pub metadata: Vec<IcrcTokenMetadataRow>,
578}
579
580///
581/// IcrcBalanceReport
582///
583/// Serializable report for one generic ICRC account balance lookup.
584///
585
586#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
587pub struct IcrcBalanceReport {
588    pub schema_version: u32,
589    pub ledger_canister_id: String,
590    pub account_owner: String,
591    pub subaccount_hex: Option<String>,
592    pub fetched_at: String,
593    pub source_endpoint: String,
594    pub fetched_by: String,
595    pub token_symbol: String,
596    pub decimals: u8,
597    pub balance: String,
598}
599
600///
601/// IcrcAllowanceReport
602///
603/// Serializable report for one generic ICRC allowance lookup.
604///
605
606#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
607pub struct IcrcAllowanceReport {
608    pub schema_version: u32,
609    pub ledger_canister_id: String,
610    pub account_owner: String,
611    pub account_subaccount_hex: Option<String>,
612    pub spender_owner: String,
613    pub spender_subaccount_hex: Option<String>,
614    pub fetched_at: String,
615    pub source_endpoint: String,
616    pub fetched_by: String,
617    pub token_symbol: String,
618    pub decimals: u8,
619    pub allowance: String,
620    pub expires_at_unix_nanos: Option<String>,
621}
622
623///
624/// IcrcAccountTransactionPageReport
625///
626/// Serializable report for a backward page of ICRC index account transactions.
627///
628
629#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
630pub struct IcrcAccountTransactionPageReport {
631    /// Report schema version.
632    pub schema_version: u32,
633    /// Ledger canister whose transactions were indexed.
634    pub ledger_canister_id: String,
635    /// Index canister that answered the account-history query.
636    pub index_canister_id: String,
637    /// Queried account owner principal.
638    pub account_owner: String,
639    /// Queried subaccount as normalized hex.
640    pub subaccount_hex: Option<String>,
641    /// Exclusive block-index cursor supplied by the caller.
642    pub requested_start: Option<String>,
643    /// Maximum number of transactions requested.
644    pub requested_limit: u32,
645    /// Cursor to pass as `start` to request the next older page.
646    pub next_start: Option<String>,
647    /// Oldest transaction id known for this account.
648    pub oldest_transaction_id: Option<String>,
649    /// Account balance reported by the index at its synchronized tip.
650    pub balance: String,
651    /// Ledger token symbol used for text rendering.
652    pub token_symbol: String,
653    /// Ledger token decimals used for text rendering.
654    pub decimals: u8,
655    /// Collection timestamp in UTC text form.
656    pub fetched_at: String,
657    /// IC API endpoint used for ledger and index calls.
658    pub source_endpoint: String,
659    /// Collector identity.
660    pub fetched_by: String,
661    /// Transactions returned by the index in its native page order.
662    pub transactions: Vec<IcrcAccountTransactionRow>,
663}
664
665///
666/// IcrcAccountTransactionCompleteness
667///
668/// Evidence that a persisted account-history snapshot exhausted the index API.
669///
670
671#[derive(Clone, Debug, Eq, PartialEq, SerdeDeserialize, Serialize)]
672pub struct IcrcAccountTransactionCompleteness {
673    /// Stable completeness classification; complete snapshots use `api_exhausted`.
674    pub status: String,
675    /// Maximum transactions requested per source page.
676    pub page_size: u32,
677    /// Number of source pages collected.
678    pub page_count: u32,
679    /// Number of unique persisted transaction rows.
680    pub row_count: usize,
681    /// Whether the source guarantees every page belongs to one point in time.
682    pub point_in_time_guaranteed: bool,
683}
684
685///
686/// IcrcAccountTransactionSnapshot
687///
688/// Complete persisted account-history snapshot collected by exhausting the index API.
689///
690
691#[derive(Clone, Debug, Eq, PartialEq, SerdeDeserialize, Serialize)]
692pub struct IcrcAccountTransactionSnapshot {
693    /// Cache schema version.
694    pub schema_version: u32,
695    /// IC API endpoint used for ledger and index calls.
696    pub source_endpoint: String,
697    /// Collection start timestamp.
698    pub collection_started_at: String,
699    /// Collection completion timestamp.
700    pub collection_completed_at: String,
701    /// Collector identity.
702    pub fetched_by: String,
703    /// Ledger canister whose transactions were indexed.
704    pub ledger_canister_id: String,
705    /// Verified index canister used for every page.
706    pub index_canister_id: String,
707    /// Queried account owner principal.
708    pub account_owner: String,
709    /// Queried subaccount as normalized hex.
710    pub subaccount_hex: Option<String>,
711    /// Account balance reported by the first index page.
712    pub balance: String,
713    /// Ledger token symbol used for text rendering.
714    pub token_symbol: String,
715    /// Ledger token decimals used for text rendering.
716    pub decimals: u8,
717    /// Highest collected transaction id.
718    pub newest_transaction_id: Option<String>,
719    /// Lowest collected transaction id.
720    pub oldest_transaction_id: Option<String>,
721    /// Complete-collection evidence.
722    pub completeness: IcrcAccountTransactionCompleteness,
723    /// Canonical newest-first account transactions.
724    pub transactions: Vec<IcrcAccountTransactionRow>,
725}
726
727///
728/// IcrcAccountTransactionRefreshReport
729///
730/// Serializable forced-refresh outcome for one complete account-history cache.
731///
732
733#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
734pub struct IcrcAccountTransactionRefreshReport {
735    /// Report schema version.
736    pub schema_version: u32,
737    /// Ledger canister whose account history was collected.
738    pub ledger_canister_id: String,
739    /// Verified index canister used for every page.
740    pub index_canister_id: String,
741    /// Queried account owner principal.
742    pub account_owner: String,
743    /// Queried subaccount as normalized hex.
744    pub subaccount_hex: Option<String>,
745    /// Number of unique transactions published.
746    pub transaction_count: usize,
747    /// Highest published transaction id.
748    pub newest_transaction_id: Option<String>,
749    /// Lowest published transaction id.
750    pub oldest_transaction_id: Option<String>,
751    /// Maximum transactions requested per source page.
752    pub page_size: u32,
753    /// Number of source pages collected.
754    pub page_count: u32,
755    /// Whether the source guarantees one point-in-time snapshot.
756    pub point_in_time_guaranteed: bool,
757    /// Whether a prior complete cache existed.
758    pub replaced_existing_cache: bool,
759    /// Non-fatal error encountered finalizing the refresh-attempt sidecar.
760    pub attempt_finalization_error: Option<String>,
761    /// Collection start timestamp.
762    pub collection_started_at: String,
763    /// Collection completion timestamp.
764    pub collection_completed_at: String,
765    /// IC API endpoint used for ledger and index calls.
766    pub source_endpoint: String,
767    /// Collector identity.
768    pub fetched_by: String,
769    /// Published complete-cache path.
770    pub cache_path: String,
771    /// Refresh-attempt sidecar path.
772    pub refresh_attempt_path: String,
773    /// Refresh lock path.
774    pub refresh_lock_path: String,
775}
776
777///
778/// IcrcAccountTransactionListReport
779///
780/// Serializable cache-only view over a complete account-history snapshot.
781///
782
783#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
784pub struct IcrcAccountTransactionListReport {
785    /// Report schema version.
786    pub schema_version: u32,
787    /// Ledger canister whose cached history is shown.
788    pub ledger_canister_id: String,
789    /// Verified index canister used to collect the cache.
790    pub index_canister_id: String,
791    /// Cached account owner principal.
792    pub account_owner: String,
793    /// Cached subaccount as normalized hex.
794    pub subaccount_hex: Option<String>,
795    /// Maximum cached rows requested by this view.
796    pub requested_limit: u32,
797    /// Stable requested ordering name.
798    pub sort: String,
799    /// Total rows in the complete cache.
800    pub total_transaction_count: usize,
801    /// Rows returned by this view.
802    pub returned_transaction_count: usize,
803    /// Highest transaction id in the complete cache.
804    pub newest_transaction_id: Option<String>,
805    /// Lowest transaction id in the complete cache.
806    pub oldest_transaction_id: Option<String>,
807    /// Account balance captured from the first index page.
808    pub balance: String,
809    /// Ledger token symbol used for text rendering.
810    pub token_symbol: String,
811    /// Ledger token decimals used for text rendering.
812    pub decimals: u8,
813    /// Complete collection start timestamp.
814    pub collection_started_at: String,
815    /// Complete collection finish timestamp.
816    pub collection_completed_at: String,
817    /// IC API endpoint represented by the cache.
818    pub source_endpoint: String,
819    /// Collector identity.
820    pub fetched_by: String,
821    /// Whether source exhaustion was proven.
822    pub complete: bool,
823    /// Whether the source guaranteed one point-in-time snapshot.
824    pub point_in_time_guaranteed: bool,
825    /// Maximum transactions requested per source page.
826    pub page_size: u32,
827    /// Number of source pages collected.
828    pub page_count: u32,
829    /// Complete-cache path read by this view.
830    pub cache_path: String,
831    /// Selected cached rows in requested order.
832    pub transactions: Vec<IcrcAccountTransactionRow>,
833}
834
835///
836/// IcrcAccountTransactionCacheStatusReport
837///
838/// Serializable local cache and latest-refresh status.
839///
840
841#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
842pub struct IcrcAccountTransactionCacheStatusReport {
843    /// Report schema version.
844    pub schema_version: u32,
845    /// Ledger canister in the requested cache identity.
846    pub ledger_canister_id: String,
847    /// Account owner in the requested cache identity.
848    pub account_owner: String,
849    /// Subaccount in the requested cache identity.
850    pub subaccount_hex: Option<String>,
851    /// IC API endpoint in the requested cache identity.
852    pub source_endpoint: String,
853    /// Whether a cache file exists at the expected path.
854    pub found: bool,
855    /// Validation summary when a cache file exists.
856    pub cache: Option<IcrcAccountTransactionCacheSummary>,
857    /// Expected complete-cache path.
858    pub expected_cache_path: String,
859    /// Refresh-attempt sidecar path.
860    pub refresh_attempt_path: String,
861    /// Refresh lock path.
862    pub refresh_lock_path: String,
863    /// Latest refresh-attempt state when present.
864    pub latest_attempt: Option<IcrcAccountTransactionRefreshAttemptStatus>,
865}
866
867///
868/// IcrcAccountTransactionCacheSummary
869///
870/// Serializable validation summary for one complete account-history cache.
871///
872
873#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
874pub struct IcrcAccountTransactionCacheSummary {
875    /// Stable cache validation status.
876    pub cache_status: String,
877    /// Validation error when the existing cache is invalid.
878    pub cache_error: Option<String>,
879    /// Verified index canister when the cache is valid.
880    pub index_canister_id: Option<String>,
881    /// Number of cached transaction rows.
882    pub transaction_count: usize,
883    /// Highest cached transaction id.
884    pub newest_transaction_id: Option<String>,
885    /// Lowest cached transaction id.
886    pub oldest_transaction_id: Option<String>,
887    /// Maximum transactions requested per source page.
888    pub page_size: u32,
889    /// Number of source pages collected.
890    pub page_count: u32,
891    /// Whether source exhaustion was proven.
892    pub complete: bool,
893    /// Whether the source guaranteed one point-in-time snapshot.
894    pub point_in_time_guaranteed: bool,
895    /// Complete collection start timestamp.
896    pub collection_started_at: String,
897    /// Complete collection finish timestamp.
898    pub collection_completed_at: String,
899    /// Complete-cache path.
900    pub cache_path: String,
901}
902
903///
904/// IcrcAccountTransactionRefreshAttemptStatus
905///
906/// Serializable status of the latest complete-history refresh attempt.
907///
908
909#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
910pub struct IcrcAccountTransactionRefreshAttemptStatus {
911    /// Stable attempt lifecycle status.
912    pub status: String,
913    /// Attempt start timestamp.
914    pub started_at: String,
915    /// Last attempt update timestamp.
916    pub updated_at: String,
917    /// Explicit or resolved index canister recorded by the attempt.
918    pub index_canister_id: Option<String>,
919    /// Maximum transactions requested per source page.
920    pub page_size: u32,
921    /// Successfully collected pages.
922    pub pages_fetched: u32,
923    /// Unique rows collected before the latest update.
924    pub rows_fetched: usize,
925    /// Last exclusive cursor when present.
926    pub last_cursor: Option<String>,
927    /// Final failure text when the attempt failed.
928    pub last_error: Option<String>,
929}
930
931///
932/// IcrcIndexReport
933///
934/// Serializable report for one generic ICRC-106 index discovery lookup.
935///
936
937#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
938pub struct IcrcIndexReport {
939    pub schema_version: u32,
940    pub ledger_canister_id: String,
941    pub fetched_at: String,
942    pub source_endpoint: String,
943    pub fetched_by: String,
944    pub index_canister_id: Option<String>,
945    pub index_error: Option<String>,
946}
947
948///
949/// IcrcTransactionsReport
950///
951/// Serializable report for a generic ICRC ledger transaction/block history page.
952///
953
954#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
955pub struct IcrcTransactionsReport {
956    pub schema_version: u32,
957    pub ledger_canister_id: String,
958    pub fetched_at: String,
959    pub source_endpoint: String,
960    pub fetched_by: String,
961    pub requested_start: String,
962    pub requested_limit: u32,
963    pub follow_archives: bool,
964    pub log_length: Option<String>,
965    pub blocks: Vec<IcrcTransactionBlockRow>,
966    pub archived_blocks: Vec<IcrcArchivedBlocksRow>,
967    pub followed_archive_blocks: Vec<IcrcFollowedArchiveBlockRow>,
968    pub archive_follow_errors: Vec<IcrcArchiveFollowErrorRow>,
969}
970
971///
972/// IcrcBlockTypesReport
973///
974/// Serializable report for generic ICRC-3 supported block type discovery.
975///
976
977#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
978pub struct IcrcBlockTypesReport {
979    pub schema_version: u32,
980    pub ledger_canister_id: String,
981    pub fetched_at: String,
982    pub source_endpoint: String,
983    pub fetched_by: String,
984    pub block_types: Vec<IcrcBlockTypeRow>,
985}
986
987///
988/// IcrcArchivesReport
989///
990/// Serializable report for generic ICRC-3 archive range discovery.
991///
992
993#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
994pub struct IcrcArchivesReport {
995    pub schema_version: u32,
996    pub ledger_canister_id: String,
997    pub from_canister_id: Option<String>,
998    pub fetched_at: String,
999    pub source_endpoint: String,
1000    pub fetched_by: String,
1001    pub archives: Vec<IcrcArchiveRow>,
1002}
1003
1004///
1005/// IcrcTipCertificateReport
1006///
1007/// Serializable report for a generic ICRC-3 ledger tip certificate.
1008///
1009
1010#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1011pub struct IcrcTipCertificateReport {
1012    pub schema_version: u32,
1013    pub ledger_canister_id: String,
1014    pub fetched_at: String,
1015    pub source_endpoint: String,
1016    pub fetched_by: String,
1017    pub certificate_present: bool,
1018    pub certificate_hex: Option<String>,
1019    pub certificate_bytes: Option<usize>,
1020    pub hash_tree_hex: Option<String>,
1021    pub hash_tree_bytes: Option<usize>,
1022}
1023
1024///
1025/// IcrcCapabilitiesReport
1026///
1027/// Serializable report for generic ICRC ledger endpoint capabilities.
1028///
1029
1030#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1031pub struct IcrcCapabilitiesReport {
1032    pub schema_version: u32,
1033    pub ledger_canister_id: String,
1034    pub fetched_at: String,
1035    pub source_endpoint: String,
1036    pub fetched_by: String,
1037    pub supported_standards: Vec<IcrcTokenStandardRow>,
1038    pub capabilities: Vec<IcrcCapabilityRow>,
1039}
1040
1041///
1042/// IcrcCapabilityRow
1043///
1044/// Serializable row for one probed generic ICRC ledger capability.
1045///
1046
1047#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1048pub struct IcrcCapabilityRow {
1049    pub capability: String,
1050    pub method: String,
1051    pub status: String,
1052    pub details: Option<String>,
1053    pub error: Option<String>,
1054}
1055
1056///
1057/// IcrcTokenStandardRow
1058///
1059/// Serializable row for one ICRC standard supported by a ledger.
1060///
1061
1062#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1063pub struct IcrcTokenStandardRow {
1064    pub name: String,
1065    pub url: String,
1066}
1067
1068///
1069/// IcrcTokenMetadataRow
1070///
1071/// Serializable row for one raw ICRC ledger metadata entry.
1072///
1073
1074#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1075pub struct IcrcTokenMetadataRow {
1076    pub key: String,
1077    pub value_type: String,
1078    pub value: JsonValue,
1079}
1080
1081///
1082/// IcrcAccountRow
1083///
1084/// Serializable ICRC account identity used in account-transaction rows.
1085///
1086
1087#[derive(Clone, Debug, Eq, PartialEq, SerdeDeserialize, Serialize)]
1088pub struct IcrcAccountRow {
1089    /// ICRC account owner principal when the index uses structured accounts.
1090    pub owner: Option<String>,
1091    /// Optional 32-byte subaccount as lowercase hex.
1092    pub subaccount_hex: Option<String>,
1093    /// Legacy ICP account identifier when the index returns identifier text.
1094    pub account_identifier: Option<String>,
1095}
1096
1097///
1098/// IcrcAccountTransactionRow
1099///
1100/// Serializable projected and lossless JSON representation of one index transaction.
1101///
1102
1103#[derive(Clone, Debug, Eq, PartialEq, SerdeDeserialize, Serialize)]
1104pub struct IcrcAccountTransactionRow {
1105    /// Ledger block index of the transaction.
1106    pub id: String,
1107    /// Index-reported transaction kind.
1108    pub kind: String,
1109    /// Ledger transaction timestamp as Unix nanoseconds when present.
1110    pub timestamp_unix_nanos: Option<String>,
1111    /// Operation amount in ledger base units when the operation carries one.
1112    pub amount_base_units: Option<String>,
1113    /// Operation fee in ledger base units when the operation carries one.
1114    pub fee_base_units: Option<String>,
1115    /// Source account when present.
1116    pub from: Option<IcrcAccountRow>,
1117    /// Destination account when present.
1118    pub to: Option<IcrcAccountRow>,
1119    /// Spender account when present.
1120    pub spender: Option<IcrcAccountRow>,
1121    /// Operation memo as lowercase hex when present.
1122    pub memo_hex: Option<String>,
1123    /// Caller-supplied creation time as Unix nanoseconds when present.
1124    pub created_at_time_unix_nanos: Option<String>,
1125    /// Approval expiry as Unix nanoseconds when present.
1126    pub expires_at_unix_nanos: Option<String>,
1127    /// Expected prior allowance in base units when present.
1128    pub expected_allowance_base_units: Option<String>,
1129    /// Lossless JSON projection of every typed transaction field returned by the index.
1130    pub raw_transaction: JsonValue,
1131}
1132
1133///
1134/// IcrcTransactionBlockRow
1135///
1136/// Serializable row for one ICRC-3 block returned by a ledger canister.
1137///
1138
1139#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1140pub struct IcrcTransactionBlockRow {
1141    pub index: String,
1142    pub block_type: Option<String>,
1143    pub transaction_kind: Option<String>,
1144    pub timestamp_unix_nanos: Option<String>,
1145    pub amount_base_units: Option<String>,
1146    pub raw_block: JsonValue,
1147}
1148
1149///
1150/// IcrcArchivedBlocksRow
1151///
1152/// Serializable row for one ICRC-3 archive callback returned by a ledger canister.
1153///
1154
1155#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1156pub struct IcrcArchivedBlocksRow {
1157    pub callback_canister_id: String,
1158    pub callback_method: String,
1159    pub ranges: Vec<IcrcArchivedRangeRow>,
1160}
1161
1162///
1163/// IcrcArchivedRangeRow
1164///
1165/// Serializable row for one ICRC-3 archived block range.
1166///
1167
1168#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1169pub struct IcrcArchivedRangeRow {
1170    pub start: String,
1171    pub length: String,
1172}
1173
1174///
1175/// IcrcFollowedArchiveBlockRow
1176///
1177/// Serializable row for one ICRC-3 block fetched from an archive callback.
1178///
1179
1180#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1181pub struct IcrcFollowedArchiveBlockRow {
1182    pub archive_canister_id: String,
1183    pub callback_method: String,
1184    pub index: String,
1185    pub block_type: Option<String>,
1186    pub transaction_kind: Option<String>,
1187    pub timestamp_unix_nanos: Option<String>,
1188    pub amount_base_units: Option<String>,
1189    pub raw_block: JsonValue,
1190}
1191
1192///
1193/// IcrcArchiveFollowErrorRow
1194///
1195/// Serializable row for one archive callback that could not be followed.
1196///
1197
1198#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1199pub struct IcrcArchiveFollowErrorRow {
1200    pub callback_canister_id: String,
1201    pub callback_method: String,
1202    pub ranges: Vec<IcrcArchivedRangeRow>,
1203    pub error: String,
1204}
1205
1206///
1207/// IcrcBlockTypeRow
1208///
1209/// Serializable row for one supported ICRC-3 block type.
1210///
1211
1212#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1213pub struct IcrcBlockTypeRow {
1214    pub block_type: String,
1215    pub url: String,
1216}
1217
1218///
1219/// IcrcArchiveRow
1220///
1221/// Serializable row for one ICRC-3 archive range.
1222///
1223
1224#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1225pub struct IcrcArchiveRow {
1226    pub canister_id: String,
1227    pub start: String,
1228    pub end: String,
1229}