Skip to main content

ic_query/icrc/model/contracts/requests/
account_history.rs

1//! Module: icrc::model::contracts::requests::account_history
2//!
3//! Responsibility: ICRC account-history page, cache, refresh, and list requests.
4//! Does not own: ledger-wide history, live transport, cache mechanics, or reports.
5//! Boundary: separates stable collection identity from pagination and local view options.
6
7use super::IcrcLedgerRequest;
8
9use std::path::PathBuf;
10
11///
12/// IcrcAccountTransactionPageRequest
13///
14/// Request accepted by the live ICRC index account-transaction page builder.
15///
16
17#[derive(Clone, Debug, Eq, PartialEq)]
18pub struct IcrcAccountTransactionPageRequest {
19    /// Shared ledger identity, explicit endpoint and caller collection clock.
20    pub ledger: IcrcLedgerRequest,
21    /// Optional explicit index canister; otherwise ICRC-106 discovery is used.
22    pub index_canister_id: Option<String>,
23    /// Account owner principal.
24    pub account_owner: String,
25    /// Optional normalized 32-byte subaccount hex.
26    pub subaccount_hex: Option<String>,
27    /// Optional exclusive block-index cursor for backward pagination.
28    pub start: Option<String>,
29    /// Maximum number of account transactions to request.
30    pub limit: u32,
31}
32
33impl IcrcAccountTransactionPageRequest {
34    /// Constructs an account-history request that discovers the index through the ledger.
35    #[must_use]
36    pub fn new(ledger: IcrcLedgerRequest, account_owner: impl Into<String>, limit: u32) -> Self {
37        Self {
38            ledger,
39            index_canister_id: None,
40            account_owner: account_owner.into(),
41            subaccount_hex: None,
42            start: None,
43            limit,
44        }
45    }
46
47    /// Uses an explicit index canister instead of ICRC-106 discovery.
48    #[must_use]
49    pub fn with_index_canister_id(mut self, index_canister_id: impl Into<String>) -> Self {
50        self.index_canister_id = Some(index_canister_id.into());
51        self
52    }
53
54    /// Selects a 32-byte ICRC subaccount encoded as hex.
55    #[must_use]
56    pub fn with_subaccount_hex(mut self, subaccount_hex: impl Into<String>) -> Self {
57        self.subaccount_hex = Some(subaccount_hex.into());
58        self
59    }
60
61    /// Starts after the given transaction block index when paginating backward.
62    #[must_use]
63    pub fn with_start(mut self, start: impl Into<String>) -> Self {
64        self.start = Some(start.into());
65        self
66    }
67}
68
69///
70/// IcrcAccountTransactionCacheRequest
71///
72/// Stable account-history cache identity independent of page and view options.
73///
74
75#[derive(Clone, Debug, Eq, PartialEq)]
76pub struct IcrcAccountTransactionCacheRequest {
77    /// Root directory containing the shared cache.
78    pub cache_root: PathBuf,
79    /// IC API endpoint whose indexed history is cached.
80    pub source_endpoint: String,
81    /// Ledger canister whose account history is cached.
82    pub ledger_canister_id: String,
83    /// Account owner principal.
84    pub account_owner: String,
85    /// Optional normalized 32-byte subaccount hex.
86    pub subaccount_hex: Option<String>,
87}
88
89impl IcrcAccountTransactionCacheRequest {
90    /// Constructs a cache identity for the default subaccount.
91    #[must_use]
92    pub fn new(
93        cache_root: impl Into<PathBuf>,
94        source_endpoint: impl Into<String>,
95        ledger_canister_id: impl Into<String>,
96        account_owner: impl Into<String>,
97    ) -> Self {
98        Self {
99            cache_root: cache_root.into(),
100            source_endpoint: source_endpoint.into(),
101            ledger_canister_id: ledger_canister_id.into(),
102            account_owner: account_owner.into(),
103            subaccount_hex: None,
104        }
105    }
106
107    /// Selects a 32-byte ICRC subaccount encoded as hex.
108    #[must_use]
109    pub fn with_subaccount_hex(mut self, subaccount_hex: impl Into<String>) -> Self {
110        self.subaccount_hex = Some(subaccount_hex.into());
111        self
112    }
113}
114
115///
116/// IcrcAccountTransactionRefreshRequest
117///
118/// Request for a forced complete account-history refresh.
119///
120
121#[derive(Clone, Debug, Eq, PartialEq)]
122pub struct IcrcAccountTransactionRefreshRequest {
123    /// Stable cache identity.
124    pub cache: IcrcAccountTransactionCacheRequest,
125    /// Collection start clock in Unix seconds; completion adds monotonic elapsed time.
126    pub now_unix_secs: u64,
127    /// Optional explicit index canister; otherwise ICRC-106 discovery is used.
128    pub index_canister_id: Option<String>,
129    /// Maximum transactions requested per index page.
130    pub page_size: u32,
131    /// Optional diagnostic bound that fails rather than publishing a partial cache.
132    pub max_pages: Option<u32>,
133}
134
135impl IcrcAccountTransactionRefreshRequest {
136    /// Constructs a complete refresh request.
137    #[must_use]
138    pub const fn new(
139        cache: IcrcAccountTransactionCacheRequest,
140        now_unix_secs: u64,
141        page_size: u32,
142    ) -> Self {
143        Self {
144            cache,
145            now_unix_secs,
146            index_canister_id: None,
147            page_size,
148            max_pages: None,
149        }
150    }
151
152    /// Uses an explicit index canister instead of ICRC-106 discovery.
153    #[must_use]
154    pub fn with_index_canister_id(mut self, index_canister_id: impl Into<String>) -> Self {
155        self.index_canister_id = Some(index_canister_id.into());
156        self
157    }
158
159    /// Bounds pages for diagnostics; failing to exhaust the API within the bound prevents publication.
160    #[must_use]
161    pub const fn with_max_pages(mut self, max_pages: Option<u32>) -> Self {
162        self.max_pages = max_pages;
163        self
164    }
165}
166
167///
168/// IcrcAccountTransactionSort
169///
170/// Supported cached account-history ordering.
171///
172
173#[derive(Clone, Copy, Debug, Eq, PartialEq)]
174pub enum IcrcAccountTransactionSort {
175    /// Highest transaction id first.
176    Newest,
177    /// Lowest transaction id first.
178    Oldest,
179}
180
181impl IcrcAccountTransactionSort {
182    /// Stable JSON/text name for this ordering.
183    #[must_use]
184    pub const fn as_str(self) -> &'static str {
185        match self {
186            Self::Newest => "newest",
187            Self::Oldest => "oldest",
188        }
189    }
190}
191
192///
193/// IcrcAccountTransactionListRequest
194///
195/// Cache-only account-history list view.
196///
197
198#[derive(Clone, Debug, Eq, PartialEq)]
199pub struct IcrcAccountTransactionListRequest {
200    /// Stable cache identity.
201    pub cache: IcrcAccountTransactionCacheRequest,
202    /// Maximum cached rows returned by this view.
203    pub limit: u32,
204    /// Requested cached-row ordering.
205    pub sort: IcrcAccountTransactionSort,
206}
207
208impl IcrcAccountTransactionListRequest {
209    /// Constructs a newest-first cached list view.
210    #[must_use]
211    pub const fn new(cache: IcrcAccountTransactionCacheRequest, limit: u32) -> Self {
212        Self {
213            cache,
214            limit,
215            sort: IcrcAccountTransactionSort::Newest,
216        }
217    }
218
219    /// Selects cached-row ordering.
220    #[must_use]
221    pub const fn with_sort(mut self, sort: IcrcAccountTransactionSort) -> Self {
222        self.sort = sort;
223        self
224    }
225}