1use serde::{Deserialize, Serialize};
2
3#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Serialize, Deserialize)]
8pub enum TransactionStatus {
9 #[serde(rename = "SUBMITTED")]
10 Submitted,
11 #[serde(rename = "PENDING_AML_SCREENING")]
12 PendingAmlScreening,
13 #[serde(rename = "PENDING_ENRICHMENT")]
14 PendingEnrichment,
15 #[serde(rename = "PENDING_AUTHORIZATION")]
16 PendingAuthorization,
17 #[serde(rename = "QUEUED")]
18 Queued,
19 #[serde(rename = "PENDING_SIGNATURE")]
20 PendingSignature,
21 #[serde(rename = "PENDING_3RD_PARTY_MANUAL_APPROVAL")]
22 Pending3RdPartyManualApproval,
23 #[serde(rename = "PENDING_3RD_PARTY")]
24 Pending3RdParty,
25 #[serde(rename = "BROADCASTING")]
26 Broadcasting,
27 #[serde(rename = "COMPLETED")]
28 Completed,
29 #[serde(rename = "CONFIRMING")]
30 Confirming,
31 #[serde(rename = "CANCELLING")]
32 Cancelling,
33 #[serde(rename = "CANCELLED")]
34 Cancelled,
35 #[serde(rename = "BLOCKED")]
36 Blocked,
37 #[serde(rename = "REJECTED")]
38 Rejected,
39 #[serde(rename = "FAILED")]
40 Failed,
41 Other(String),
42}
43
44impl TransactionStatus {
45 pub const fn is_done(&self) -> bool {
46 matches!(
47 self,
48 Self::Cancelling
49 | Self::Cancelled
50 | Self::Blocked
51 | Self::Completed
52 | Self::Confirming
53 | Self::Failed
54 | Self::Rejected
55 )
56 }
57}
58
59impl std::fmt::Display for TransactionStatus {
60 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
61 match self {
62 Self::Submitted => write!(f, "SUBMITTED"),
63 Self::PendingAmlScreening => write!(f, "PENDING_AML_SCREENING"),
64 Self::PendingEnrichment => write!(f, "PENDING_ENRICHMENT"),
65 Self::PendingAuthorization => write!(f, "PENDING_AUTHORIZATION"),
66 Self::Queued => write!(f, "QUEUED"),
67 Self::PendingSignature => write!(f, "PENDING_SIGNATURE"),
68 Self::Pending3RdPartyManualApproval => write!(f, "PENDING_3RD_PARTY_MANUAL_APPROVAL"),
69 Self::Pending3RdParty => write!(f, "PENDING_3RD_PARTY"),
70 Self::Broadcasting => write!(f, "BROADCASTING"),
71 Self::Completed => write!(f, "COMPLETED"),
72 Self::Confirming => write!(f, "CONFIRMING"),
73 Self::Cancelling => write!(f, "CANCELLING"),
74 Self::Cancelled => write!(f, "CANCELLED"),
75 Self::Blocked => write!(f, "BLOCKED"),
76 Self::Rejected => write!(f, "REJECTED"),
77 Self::Failed => write!(f, "FAILED"),
78 Self::Other(s) => write!(f, "{s}"),
79 }
80 }
81}
82
83impl From<String> for TransactionStatus {
84 fn from(s: String) -> Self {
85 match s.as_str() {
86 "SUBMITTED" => Self::Submitted,
87 "PENDING_AML_SCREENING" => Self::PendingAmlScreening,
88 "PENDING_ENRICHMENT" => Self::PendingEnrichment,
89 "PENDING_AUTHORIZATION" => Self::PendingAuthorization,
90 "QUEUED" => Self::Queued,
91 "PENDING_SIGNATURE" => Self::PendingSignature,
92 "PENDING_3RD_PARTY_MANUAL_APPROVAL" => Self::Pending3RdPartyManualApproval,
93 "PENDING_3RD_PARTY" => Self::Pending3RdParty,
94 "BROADCASTING" => Self::Broadcasting,
95 "COMPLETED" => Self::Completed,
96 "CONFIRMING" => Self::Confirming,
97 "CANCELLING" => Self::Cancelling,
98 "CANCELLED" => Self::Cancelled,
99 "BLOCKED" => Self::Blocked,
100 "REJECTED" => Self::Rejected,
101 "FAILED" => Self::Failed,
102 _ => Self::Other(s),
103 }
104 }
105}
106
107impl From<&str> for TransactionStatus {
108 fn from(s: &str) -> Self {
109 Self::from(s.to_string())
110 }
111}
112
113impl Default for TransactionStatus {
114 fn default() -> Self {
115 Self::Submitted
116 }
117}
118
119#[cfg(test)]
120mod tests {
121 use super::*;
122
123 #[test]
124 fn test_transaction_status_display() {
125 let test_cases = [
127 (TransactionStatus::Submitted, "SUBMITTED"),
128 (
129 TransactionStatus::PendingAmlScreening,
130 "PENDING_AML_SCREENING",
131 ),
132 (TransactionStatus::PendingEnrichment, "PENDING_ENRICHMENT"),
133 (
134 TransactionStatus::PendingAuthorization,
135 "PENDING_AUTHORIZATION",
136 ),
137 (TransactionStatus::Queued, "QUEUED"),
138 (TransactionStatus::PendingSignature, "PENDING_SIGNATURE"),
139 (
140 TransactionStatus::Pending3RdPartyManualApproval,
141 "PENDING_3RD_PARTY_MANUAL_APPROVAL",
142 ),
143 (TransactionStatus::Pending3RdParty, "PENDING_3RD_PARTY"),
144 (TransactionStatus::Broadcasting, "BROADCASTING"),
145 (TransactionStatus::Completed, "COMPLETED"),
146 (TransactionStatus::Confirming, "CONFIRMING"),
147 (TransactionStatus::Cancelling, "CANCELLING"),
148 (TransactionStatus::Cancelled, "CANCELLED"),
149 (TransactionStatus::Blocked, "BLOCKED"),
150 (TransactionStatus::Rejected, "REJECTED"),
151 (TransactionStatus::Failed, "FAILED"),
152 ];
153
154 for (status, expected) in test_cases {
155 assert_eq!(status.to_string(), expected);
156 }
157 }
158
159 #[test]
160 fn test_is_done_final_statuses() {
161 let final_statuses = [
163 TransactionStatus::Cancelling,
164 TransactionStatus::Cancelled,
165 TransactionStatus::Blocked,
166 TransactionStatus::Completed,
167 TransactionStatus::Confirming,
168 TransactionStatus::Failed,
169 TransactionStatus::Rejected,
170 ];
171
172 for status in final_statuses {
173 assert!(status.is_done());
174 }
175 }
176
177 #[test]
178 fn test_is_done_in_progress_statuses() {
179 let in_progress_statuses = [
181 TransactionStatus::Submitted,
182 TransactionStatus::PendingAmlScreening,
183 TransactionStatus::PendingEnrichment,
184 TransactionStatus::PendingAuthorization,
185 TransactionStatus::Queued,
186 TransactionStatus::PendingSignature,
187 TransactionStatus::Pending3RdPartyManualApproval,
188 TransactionStatus::Pending3RdParty,
189 TransactionStatus::Broadcasting,
190 ];
191
192 for status in in_progress_statuses {
193 assert!(!status.is_done());
194 }
195 }
196
197 #[test]
198 fn test_from_string() {
199 let test_cases = [
201 ("SUBMITTED", TransactionStatus::Submitted),
202 (
203 "PENDING_AML_SCREENING",
204 TransactionStatus::PendingAmlScreening,
205 ),
206 ("PENDING_ENRICHMENT", TransactionStatus::PendingEnrichment),
207 (
208 "PENDING_AUTHORIZATION",
209 TransactionStatus::PendingAuthorization,
210 ),
211 ("QUEUED", TransactionStatus::Queued),
212 ("PENDING_SIGNATURE", TransactionStatus::PendingSignature),
213 (
214 "PENDING_3RD_PARTY_MANUAL_APPROVAL",
215 TransactionStatus::Pending3RdPartyManualApproval,
216 ),
217 ("PENDING_3RD_PARTY", TransactionStatus::Pending3RdParty),
218 ("BROADCASTING", TransactionStatus::Broadcasting),
219 ("COMPLETED", TransactionStatus::Completed),
220 ("CONFIRMING", TransactionStatus::Confirming),
221 ("CANCELLING", TransactionStatus::Cancelling),
222 ("CANCELLED", TransactionStatus::Cancelled),
223 ("BLOCKED", TransactionStatus::Blocked),
224 ("REJECTED", TransactionStatus::Rejected),
225 ("FAILED", TransactionStatus::Failed),
226 ];
227
228 for (input, expected) in test_cases {
229 let status: TransactionStatus = String::from(input).into();
231 assert_eq!(status, expected);
232
233 let status: TransactionStatus = input.into();
235 assert_eq!(status, expected);
236 }
237
238 let unknown_status: TransactionStatus = String::from("UNKNOWN_STATUS").into();
240 assert_eq!(
241 unknown_status,
242 TransactionStatus::Other("UNKNOWN_STATUS".to_string())
243 );
244
245 let unknown_status: TransactionStatus = "UNKNOWN_STATUS".into();
246 assert_eq!(
247 unknown_status,
248 TransactionStatus::Other("UNKNOWN_STATUS".to_string())
249 );
250 }
251
252 #[test]
253 fn test_string_conversion_roundtrip() {
254 let statuses = [
256 TransactionStatus::Submitted,
257 TransactionStatus::PendingAmlScreening,
258 TransactionStatus::Completed,
259 TransactionStatus::Failed,
260 TransactionStatus::Other("CUSTOM_STATUS".to_string()),
261 ];
262
263 for status in statuses {
264 let string_repr = status.to_string();
265 let parsed_status: TransactionStatus = string_repr.into();
266 assert_eq!(status, parsed_status);
267 }
268 }
269}