1use crate::{cdk::types::Principal, ids::IntentResourceKey, model::replay::OperationId};
8use serde::{Deserialize, Serialize};
9
10pub const PAYLOAD_BINDING_SCHEMA_VERSION: u32 = 1;
11pub const RECEIPT_BACKED_INTENT_SCHEMA_VERSION: u32 = 1;
12pub const TERMINAL_EVIDENCE_SCHEMA_VERSION: u32 = 1;
13
14#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
16pub struct PayloadBinding {
17 pub schema_version: u32,
18 pub digest: [u8; 32],
19}
20
21impl PayloadBinding {
22 #[must_use]
23 pub const fn new(digest: [u8; 32]) -> Self {
24 Self {
25 schema_version: PAYLOAD_BINDING_SCHEMA_VERSION,
26 digest,
27 }
28 }
29}
30
31#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
33pub enum TerminalEvidenceDecision {
34 Committed,
35 RolledBack,
36}
37
38#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
40pub struct TerminalEvidence {
41 pub source_canister: Principal,
42 pub schema_version: u32,
43 pub decision: TerminalEvidenceDecision,
44 pub fingerprint: [u8; 32],
45}
46
47impl TerminalEvidence {
48 #[must_use]
49 pub const fn new(
50 source_canister: Principal,
51 decision: TerminalEvidenceDecision,
52 fingerprint: [u8; 32],
53 ) -> Self {
54 Self {
55 source_canister,
56 schema_version: TERMINAL_EVIDENCE_SCHEMA_VERSION,
57 decision,
58 fingerprint,
59 }
60 }
61}
62
63#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
65pub enum ReceiptBackedIntentState {
66 Pending,
67 Committed { evidence: TerminalEvidence },
68 RolledBack { evidence: TerminalEvidence },
69}
70
71#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
73pub struct ReceiptBackedIntent {
74 pub schema_version: u32,
75 pub operation_id: OperationId,
76 pub payload_binding: PayloadBinding,
77 pub resource_key: IntentResourceKey,
78 pub quantity: u64,
79 pub state: ReceiptBackedIntentState,
80 pub revision: u64,
81 pub created_at_ns: u64,
82 pub updated_at_ns: u64,
83}
84
85#[derive(Clone, Debug, Eq, PartialEq)]
87pub struct BeginLocalIntentInput {
88 pub resource_key: IntentResourceKey,
89 pub quantity: u64,
90 pub ttl_secs: Option<u64>,
91 pub reservation_limit: Option<u64>,
92}
93
94#[derive(Clone, Debug, Eq, PartialEq)]
96pub struct BeginReceiptBackedIntentInput {
97 pub operation_id: OperationId,
98 pub payload_binding: PayloadBinding,
99 pub resource_key: IntentResourceKey,
100 pub quantity: u64,
101 pub reservation_limit: u64,
102}
103
104#[derive(Clone, Debug, Eq, PartialEq)]
106pub enum BeginReceiptBackedIntentResult {
107 Created {
108 revision: u64,
109 },
110 ExistingPending {
111 revision: u64,
112 },
113 ExistingCommitted {
114 revision: u64,
115 evidence: TerminalEvidence,
116 },
117 ExistingRolledBack {
118 revision: u64,
119 evidence: TerminalEvidence,
120 },
121 BindingConflict,
122 CapacityExceeded {
123 current_quantity: u64,
124 requested_quantity: u64,
125 limit: u64,
126 },
127 StoreCapacityReached {
128 current_records: u64,
129 limit: u64,
130 },
131}
132
133#[derive(Clone, Debug, Eq, PartialEq)]
135pub struct SettleReceiptBackedIntentInput {
136 pub operation_id: OperationId,
137 pub expected_revision: u64,
138 pub expected_payload_binding: PayloadBinding,
139 pub evidence: TerminalEvidence,
140}
141
142#[derive(Clone, Copy, Debug, Eq, PartialEq)]
144pub enum SettleReceiptBackedIntentResult {
145 Settled {
146 revision: u64,
147 state: ReceiptBackedIntentState,
148 },
149 AlreadySettled {
150 revision: u64,
151 state: ReceiptBackedIntentState,
152 },
153 NotFound,
154 RevisionConflict {
155 actual_revision: u64,
156 },
157 BindingConflict,
158}