ic_query/icrc/model/contracts/reports/account_history.rs
1//! Module: icrc::model::contracts::reports::account_history
2//!
3//! Responsibility: serialized ICRC account-history page, cache, and row contracts.
4//! Does not own: ledger-wide history, requests, live transport, cache mechanics, or rendering.
5//! Boundary: owns the stable JSON and persisted snapshot shapes for indexed account history.
6
7use crate::cache::{CacheCollectionCompleteness, CacheRefreshAttemptStatus, CacheValidationStatus};
8use serde::{Deserialize as SerdeDeserialize, Serialize};
9use serde_json::Value as JsonValue;
10
11///
12/// IcrcAccountTransactionPageData
13///
14/// Source-layer account-history page returned by an ICRC index canister.
15///
16
17#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
18pub struct IcrcAccountTransactionPageData {
19 /// Index canister that answered the query.
20 pub index_canister_id: String,
21 /// Account balance reported by the index.
22 pub balance: String,
23 /// Oldest transaction id known for the account.
24 pub oldest_transaction_id: Option<String>,
25 /// Cursor for requesting the next older page.
26 pub next_start: Option<String>,
27 /// Ledger token symbol.
28 pub token_symbol: String,
29 /// Ledger token decimals.
30 pub decimals: u8,
31 /// Account transactions in index response order.
32 pub transactions: Vec<IcrcAccountTransactionRow>,
33}
34
35///
36/// IcrcAccountTransactionPageReport
37///
38/// Serializable report for a backward page of ICRC index account transactions.
39///
40
41#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
42pub struct IcrcAccountTransactionPageReport {
43 /// Report schema version.
44 pub schema_version: u32,
45 /// Ledger canister whose transactions were indexed.
46 pub ledger_canister_id: String,
47 /// Queried account owner principal.
48 pub account_owner: String,
49 /// Queried subaccount as normalized hex.
50 pub subaccount_hex: Option<String>,
51 /// Exclusive block-index cursor supplied by the caller.
52 pub requested_start: Option<String>,
53 /// Maximum number of transactions requested.
54 pub requested_limit: u32,
55 /// Collection timestamp in UTC text form.
56 pub fetched_at: String,
57 /// IC API endpoint used for ledger and index calls.
58 pub source_endpoint: String,
59 /// Collector identity.
60 pub fetched_by: String,
61 /// Validated index response and ledger display metadata.
62 #[serde(flatten)]
63 pub page: IcrcAccountTransactionPageData,
64}
65
66///
67/// IcrcAccountTransactionSnapshot
68///
69/// Complete persisted account-history snapshot collected by exhausting the index API.
70///
71
72#[derive(Clone, Debug, Eq, PartialEq, SerdeDeserialize, Serialize)]
73#[serde(deny_unknown_fields)]
74pub struct IcrcAccountTransactionSnapshot {
75 /// Cache schema version.
76 pub schema_version: u32,
77 /// IC API endpoint used for ledger and index calls.
78 pub source_endpoint: String,
79 /// Collection start timestamp supplied by the refresh caller's clock.
80 pub collection_started_at: String,
81 /// Collection completion timestamp derived from the start plus monotonic elapsed time.
82 pub collection_completed_at: String,
83 /// Collector identity.
84 pub fetched_by: String,
85 /// Ledger canister whose transactions were indexed.
86 pub ledger_canister_id: String,
87 /// Verified index canister used for every page.
88 pub index_canister_id: String,
89 /// Queried account owner principal.
90 pub account_owner: String,
91 /// Queried subaccount as normalized hex.
92 pub subaccount_hex: Option<String>,
93 /// Account balance reported by the first index page.
94 pub balance: String,
95 /// Ledger token symbol used for text rendering.
96 pub token_symbol: String,
97 /// Ledger token decimals used for text rendering.
98 pub decimals: u8,
99 /// Highest collected transaction id.
100 pub newest_transaction_id: Option<String>,
101 /// Lowest collected transaction id.
102 pub oldest_transaction_id: Option<String>,
103 /// Complete-collection evidence.
104 pub completeness: CacheCollectionCompleteness,
105 /// Canonical newest-first account transactions.
106 pub transactions: Vec<IcrcAccountTransactionRow>,
107}
108
109///
110/// IcrcAccountTransactionRefreshReport
111///
112/// Serializable forced-refresh outcome for one complete account-history cache.
113///
114
115#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
116pub struct IcrcAccountTransactionRefreshReport {
117 /// Report schema version.
118 pub schema_version: u32,
119 /// Ledger canister whose account history was collected.
120 pub ledger_canister_id: String,
121 /// Verified index canister used for every page.
122 pub index_canister_id: String,
123 /// Queried account owner principal.
124 pub account_owner: String,
125 /// Queried subaccount as normalized hex.
126 pub subaccount_hex: Option<String>,
127 /// Number of unique transactions published.
128 pub transaction_count: usize,
129 /// Highest published transaction id.
130 pub newest_transaction_id: Option<String>,
131 /// Lowest published transaction id.
132 pub oldest_transaction_id: Option<String>,
133 /// Maximum transactions requested per source page.
134 pub page_size: u32,
135 /// Number of source pages collected.
136 pub page_count: u32,
137 /// Whether the source guarantees one point-in-time snapshot.
138 pub point_in_time_guaranteed: bool,
139 /// Whether a prior complete cache existed.
140 pub replaced_existing_cache: bool,
141 /// Non-fatal error encountered finalizing the refresh-attempt sidecar.
142 pub attempt_finalization_error: Option<String>,
143 /// Collection start timestamp.
144 pub collection_started_at: String,
145 /// Collection completion timestamp.
146 pub collection_completed_at: String,
147 /// IC API endpoint used for ledger and index calls.
148 pub source_endpoint: String,
149 /// Collector identity.
150 pub fetched_by: String,
151 /// Published complete-cache path.
152 pub cache_path: String,
153 /// Refresh-attempt sidecar path.
154 pub refresh_attempt_path: String,
155 /// Refresh lock path.
156 pub refresh_lock_path: String,
157}
158
159///
160/// IcrcAccountTransactionListReport
161///
162/// Serializable cache-only view over a complete account-history snapshot.
163///
164
165#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
166pub struct IcrcAccountTransactionListReport {
167 /// Report schema version.
168 pub schema_version: u32,
169 /// Ledger canister whose cached history is shown.
170 pub ledger_canister_id: String,
171 /// Verified index canister used to collect the cache.
172 pub index_canister_id: String,
173 /// Cached account owner principal.
174 pub account_owner: String,
175 /// Cached subaccount as normalized hex.
176 pub subaccount_hex: Option<String>,
177 /// Maximum cached rows requested by this view.
178 pub requested_limit: u32,
179 /// Stable requested ordering name.
180 pub sort: String,
181 /// Total rows in the complete cache.
182 pub total_transaction_count: usize,
183 /// Rows returned by this view.
184 pub returned_transaction_count: usize,
185 /// Highest transaction id in the complete cache.
186 pub newest_transaction_id: Option<String>,
187 /// Lowest transaction id in the complete cache.
188 pub oldest_transaction_id: Option<String>,
189 /// Account balance captured from the first index page.
190 pub balance: String,
191 /// Ledger token symbol used for text rendering.
192 pub token_symbol: String,
193 /// Ledger token decimals used for text rendering.
194 pub decimals: u8,
195 /// Complete collection start timestamp.
196 pub collection_started_at: String,
197 /// Complete collection finish timestamp.
198 pub collection_completed_at: String,
199 /// IC API endpoint represented by the cache.
200 pub source_endpoint: String,
201 /// Collector identity.
202 pub fetched_by: String,
203 /// Whether source exhaustion was proven.
204 pub complete: bool,
205 /// Whether the source guaranteed one point-in-time snapshot.
206 pub point_in_time_guaranteed: bool,
207 /// Maximum transactions requested per source page.
208 pub page_size: u32,
209 /// Number of source pages collected.
210 pub page_count: u32,
211 /// Complete-cache path read by this view.
212 pub cache_path: String,
213 /// Selected cached rows in requested order.
214 pub transactions: Vec<IcrcAccountTransactionRow>,
215}
216
217///
218/// IcrcAccountTransactionCacheStatusReport
219///
220/// Serializable local cache and latest-refresh status.
221///
222
223#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
224pub struct IcrcAccountTransactionCacheStatusReport {
225 /// Report schema version.
226 pub schema_version: u32,
227 /// Ledger canister in the requested cache identity.
228 pub ledger_canister_id: String,
229 /// Account owner in the requested cache identity.
230 pub account_owner: String,
231 /// Subaccount in the requested cache identity.
232 pub subaccount_hex: Option<String>,
233 /// IC API endpoint in the requested cache identity.
234 pub source_endpoint: String,
235 /// Whether a cache file exists at the expected path.
236 pub found: bool,
237 /// Validation summary when a cache file exists.
238 pub cache: Option<IcrcAccountTransactionCacheSummary>,
239 /// Expected complete-cache path.
240 pub expected_cache_path: String,
241 /// Refresh-attempt sidecar path.
242 pub refresh_attempt_path: String,
243 /// Refresh lock path.
244 pub refresh_lock_path: String,
245 /// Latest refresh-attempt state when present.
246 pub latest_attempt: Option<IcrcAccountTransactionRefreshAttemptStatus>,
247}
248
249///
250/// IcrcAccountTransactionCacheSummary
251///
252/// Serializable validation summary for one complete account-history cache.
253///
254
255#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
256pub struct IcrcAccountTransactionCacheSummary {
257 /// Stable cache validation status.
258 pub cache_status: CacheValidationStatus,
259 /// Validation error when the existing cache is invalid.
260 pub cache_error: Option<String>,
261 /// Verified index canister when the cache is valid.
262 pub index_canister_id: Option<String>,
263 /// Number of cached transaction rows.
264 pub transaction_count: usize,
265 /// Highest cached transaction id.
266 pub newest_transaction_id: Option<String>,
267 /// Lowest cached transaction id.
268 pub oldest_transaction_id: Option<String>,
269 /// Maximum transactions requested per source page.
270 pub page_size: u32,
271 /// Number of source pages collected.
272 pub page_count: u32,
273 /// Whether source exhaustion was proven.
274 pub complete: bool,
275 /// Whether the source guaranteed one point-in-time snapshot.
276 pub point_in_time_guaranteed: bool,
277 /// Complete collection start timestamp.
278 pub collection_started_at: String,
279 /// Complete collection finish timestamp.
280 pub collection_completed_at: String,
281 /// Complete-cache path.
282 pub cache_path: String,
283}
284
285///
286/// IcrcAccountTransactionRefreshAttemptStatus
287///
288/// Serializable status of the latest complete-history refresh attempt.
289///
290
291#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
292pub struct IcrcAccountTransactionRefreshAttemptStatus {
293 /// Stable attempt lifecycle status.
294 pub status: CacheRefreshAttemptStatus,
295 /// Attempt start timestamp.
296 pub started_at: String,
297 /// Last attempt update timestamp.
298 pub updated_at: String,
299 /// Explicit or resolved index canister recorded by the attempt.
300 pub index_canister_id: Option<String>,
301 /// Maximum transactions requested per source page.
302 pub page_size: u32,
303 /// Successfully collected pages.
304 pub pages_fetched: u32,
305 /// Rows retained before the latest update.
306 pub rows_fetched: usize,
307 /// Last exclusive cursor when present.
308 pub last_cursor: Option<String>,
309 /// Final failure text when the attempt failed.
310 pub last_error: Option<String>,
311}
312
313///
314/// IcrcAccountRow
315///
316/// Serializable ICRC account identity used in account-transaction rows.
317///
318
319#[derive(Clone, Debug, Eq, PartialEq, SerdeDeserialize, Serialize)]
320pub struct IcrcAccountRow {
321 /// ICRC account owner principal when the index uses structured accounts.
322 pub owner: Option<String>,
323 /// Optional 32-byte subaccount as lowercase hex.
324 pub subaccount_hex: Option<String>,
325 /// Legacy ICP account identifier when the index returns identifier text.
326 pub account_identifier: Option<String>,
327}
328
329///
330/// IcrcAccountTransactionRow
331///
332/// Serializable projected and lossless JSON representation of one index transaction.
333///
334
335#[derive(Clone, Debug, Eq, PartialEq, SerdeDeserialize, Serialize)]
336pub struct IcrcAccountTransactionRow {
337 /// Ledger block index of the transaction.
338 pub id: String,
339 /// Index-reported transaction kind.
340 pub kind: String,
341 /// Ledger transaction timestamp as Unix nanoseconds when present.
342 pub timestamp_unix_nanos: Option<String>,
343 /// Operation amount in ledger base units when the operation carries one.
344 pub amount_base_units: Option<String>,
345 /// Operation fee in ledger base units when the operation carries one.
346 pub fee_base_units: Option<String>,
347 /// Source account when present.
348 pub from: Option<IcrcAccountRow>,
349 /// Destination account when present.
350 pub to: Option<IcrcAccountRow>,
351 /// Spender account when present.
352 pub spender: Option<IcrcAccountRow>,
353 /// Operation memo as lowercase hex when present.
354 pub memo_hex: Option<String>,
355 /// Caller-supplied creation time as Unix nanoseconds when present.
356 pub created_at_time_unix_nanos: Option<String>,
357 /// Approval expiry as Unix nanoseconds when present.
358 pub expires_at_unix_nanos: Option<String>,
359 /// Expected prior allowance in base units when present.
360 pub expected_allowance_base_units: Option<String>,
361 /// Lossless JSON projection of every typed transaction field returned by the index.
362 pub raw_transaction: JsonValue,
363}