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::Failed
53 | Self::Rejected
54 )
55 }
56}
57
58impl std::fmt::Display for TransactionStatus {
59 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
60 match self {
61 Self::Submitted => write!(f, "SUBMITTED"),
62 Self::PendingAmlScreening => write!(f, "PENDING_AML_SCREENING"),
63 Self::PendingEnrichment => write!(f, "PENDING_ENRICHMENT"),
64 Self::PendingAuthorization => write!(f, "PENDING_AUTHORIZATION"),
65 Self::Queued => write!(f, "QUEUED"),
66 Self::PendingSignature => write!(f, "PENDING_SIGNATURE"),
67 Self::Pending3RdPartyManualApproval => write!(f, "PENDING_3RD_PARTY_MANUAL_APPROVAL"),
68 Self::Pending3RdParty => write!(f, "PENDING_3RD_PARTY"),
69 Self::Broadcasting => write!(f, "BROADCASTING"),
70 Self::Completed => write!(f, "COMPLETED"),
71 Self::Confirming => write!(f, "CONFIRMING"),
72 Self::Cancelling => write!(f, "CANCELLING"),
73 Self::Cancelled => write!(f, "CANCELLED"),
74 Self::Blocked => write!(f, "BLOCKED"),
75 Self::Rejected => write!(f, "REJECTED"),
76 Self::Failed => write!(f, "FAILED"),
77 Self::Other(s) => write!(f, "{s}"),
78 }
79 }
80}
81
82impl From<String> for TransactionStatus {
83 fn from(s: String) -> Self {
84 match s.as_str() {
85 "SUBMITTED" => Self::Submitted,
86 "PENDING_AML_SCREENING" => Self::PendingAmlScreening,
87 "PENDING_ENRICHMENT" => Self::PendingEnrichment,
88 "PENDING_AUTHORIZATION" => Self::PendingAuthorization,
89 "QUEUED" => Self::Queued,
90 "PENDING_SIGNATURE" => Self::PendingSignature,
91 "PENDING_3RD_PARTY_MANUAL_APPROVAL" => Self::Pending3RdPartyManualApproval,
92 "PENDING_3RD_PARTY" => Self::Pending3RdParty,
93 "BROADCASTING" => Self::Broadcasting,
94 "COMPLETED" => Self::Completed,
95 "CONFIRMING" => Self::Confirming,
96 "CANCELLING" => Self::Cancelling,
97 "CANCELLED" => Self::Cancelled,
98 "BLOCKED" => Self::Blocked,
99 "REJECTED" => Self::Rejected,
100 "FAILED" => Self::Failed,
101 _ => Self::Other(s),
102 }
103 }
104}
105
106impl From<&str> for TransactionStatus {
107 fn from(s: &str) -> Self {
108 Self::from(s.to_string())
109 }
110}
111
112impl Default for TransactionStatus {
113 fn default() -> Self {
114 Self::Submitted
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use super::*;
121
122 #[test]
123 fn test_transaction_status_display() {
124 let test_cases = [
126 (TransactionStatus::Submitted, "SUBMITTED"),
127 (
128 TransactionStatus::PendingAmlScreening,
129 "PENDING_AML_SCREENING",
130 ),
131 (TransactionStatus::PendingEnrichment, "PENDING_ENRICHMENT"),
132 (
133 TransactionStatus::PendingAuthorization,
134 "PENDING_AUTHORIZATION",
135 ),
136 (TransactionStatus::Queued, "QUEUED"),
137 (TransactionStatus::PendingSignature, "PENDING_SIGNATURE"),
138 (
139 TransactionStatus::Pending3RdPartyManualApproval,
140 "PENDING_3RD_PARTY_MANUAL_APPROVAL",
141 ),
142 (TransactionStatus::Pending3RdParty, "PENDING_3RD_PARTY"),
143 (TransactionStatus::Broadcasting, "BROADCASTING"),
144 (TransactionStatus::Completed, "COMPLETED"),
145 (TransactionStatus::Confirming, "CONFIRMING"),
146 (TransactionStatus::Cancelling, "CANCELLING"),
147 (TransactionStatus::Cancelled, "CANCELLED"),
148 (TransactionStatus::Blocked, "BLOCKED"),
149 (TransactionStatus::Rejected, "REJECTED"),
150 (TransactionStatus::Failed, "FAILED"),
151 ];
152
153 for (status, expected) in test_cases {
154 assert_eq!(status.to_string(), expected);
155 }
156 }
157
158 #[test]
159 fn test_is_done_final_statuses() {
160 let final_statuses = [
162 TransactionStatus::Cancelling,
163 TransactionStatus::Cancelled,
164 TransactionStatus::Blocked,
165 TransactionStatus::Completed,
166 TransactionStatus::Failed,
167 TransactionStatus::Rejected,
168 ];
169
170 for status in final_statuses {
171 assert!(status.is_done());
172 }
173 }
174
175 #[test]
176 fn test_is_done_in_progress_statuses() {
177 let in_progress_statuses = [
179 TransactionStatus::Submitted,
180 TransactionStatus::PendingAmlScreening,
181 TransactionStatus::PendingEnrichment,
182 TransactionStatus::PendingAuthorization,
183 TransactionStatus::Queued,
184 TransactionStatus::PendingSignature,
185 TransactionStatus::Pending3RdPartyManualApproval,
186 TransactionStatus::Pending3RdParty,
187 TransactionStatus::Broadcasting,
188 TransactionStatus::Confirming,
189 ];
190
191 for status in in_progress_statuses {
192 assert!(!status.is_done());
193 }
194 }
195
196 #[test]
197 fn test_from_string() {
198 let test_cases = [
200 ("SUBMITTED", TransactionStatus::Submitted),
201 (
202 "PENDING_AML_SCREENING",
203 TransactionStatus::PendingAmlScreening,
204 ),
205 ("PENDING_ENRICHMENT", TransactionStatus::PendingEnrichment),
206 (
207 "PENDING_AUTHORIZATION",
208 TransactionStatus::PendingAuthorization,
209 ),
210 ("QUEUED", TransactionStatus::Queued),
211 ("PENDING_SIGNATURE", TransactionStatus::PendingSignature),
212 (
213 "PENDING_3RD_PARTY_MANUAL_APPROVAL",
214 TransactionStatus::Pending3RdPartyManualApproval,
215 ),
216 ("PENDING_3RD_PARTY", TransactionStatus::Pending3RdParty),
217 ("BROADCASTING", TransactionStatus::Broadcasting),
218 ("COMPLETED", TransactionStatus::Completed),
219 ("CONFIRMING", TransactionStatus::Confirming),
220 ("CANCELLING", TransactionStatus::Cancelling),
221 ("CANCELLED", TransactionStatus::Cancelled),
222 ("BLOCKED", TransactionStatus::Blocked),
223 ("REJECTED", TransactionStatus::Rejected),
224 ("FAILED", TransactionStatus::Failed),
225 ];
226
227 for (input, expected) in test_cases {
228 let status: TransactionStatus = String::from(input).into();
230 assert_eq!(status, expected);
231
232 let status: TransactionStatus = input.into();
234 assert_eq!(status, expected);
235 }
236
237 let unknown_status: TransactionStatus = String::from("UNKNOWN_STATUS").into();
239 assert_eq!(
240 unknown_status,
241 TransactionStatus::Other("UNKNOWN_STATUS".to_string())
242 );
243
244 let unknown_status: TransactionStatus = "UNKNOWN_STATUS".into();
245 assert_eq!(
246 unknown_status,
247 TransactionStatus::Other("UNKNOWN_STATUS".to_string())
248 );
249 }
250
251 #[test]
252 fn test_string_conversion_roundtrip() {
253 let statuses = [
255 TransactionStatus::Submitted,
256 TransactionStatus::PendingAmlScreening,
257 TransactionStatus::Completed,
258 TransactionStatus::Failed,
259 TransactionStatus::Other("CUSTOM_STATUS".to_string()),
260 ];
261
262 for status in statuses {
263 let string_repr = status.to_string();
264 let parsed_status: TransactionStatus = string_repr.into();
265 assert_eq!(status, parsed_status);
266 }
267 }
268}