stellar_base/
transaction_result.rs

1use std::io::Read;
2
3use crate::amount::Stroops;
4use crate::error::Result;
5use crate::operation_result::OperationResult;
6use crate::xdr;
7
8/// Result of a transaction.
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub enum TransactionResult {
11    FeeBumpSuccess(TransactionResultFeeBumpSuccess),
12    FeeBumpFailed(TransactionResultFeeBumpFailed),
13    Success(TransactionResultSuccess),
14    Failed(TransactionResultFailed),
15    TooEarly(TransactionResultTooEarly),
16    TooLate(TransactionResultTooLate),
17    MissingOperation(TransactionResultMissingOperation),
18    BadSequence(TransactionResultBadSequence),
19    BadAuth(TransactionResultBadAuth),
20    InsufficientBalance(TransactionResultInsufficientBalance),
21    NoAccount(TransactionResultNoAccount),
22    InsufficientFee(TransactionResultInsufficientFee),
23    BadAuthExtra(TransactionResultBadAuthExtra),
24    InternalError(TransactionResultInternalError),
25    NotSupported(TransactionResultNotSupported),
26    BadSponsorship(TransactionResultBadSponsorship),
27    BadMinSeqAgeOrGap(TransactionResultBadMinSeqAgeOrGap),
28    Malformed(TransactionResultMalformed),
29    SorobanInvalid(TransactionResultSorobanInvalid),
30}
31
32/// Result of the inner transaction in a FeeBumpTransaction.
33#[derive(Debug, Clone, PartialEq, Eq)]
34pub enum InnerTransactionResult {
35    Success(TransactionResultSuccess),
36    Failed(TransactionResultFailed),
37    TooEarly(TransactionResultTooEarly),
38    TooLate(TransactionResultTooLate),
39    MissingOperation(TransactionResultMissingOperation),
40    BadSequence(TransactionResultBadSequence),
41    BadAuth(TransactionResultBadAuth),
42    InsufficientBalance(TransactionResultInsufficientBalance),
43    NoAccount(TransactionResultNoAccount),
44    InsufficientFee(TransactionResultInsufficientFee),
45    BadAuthExtra(TransactionResultBadAuthExtra),
46    InternalError(TransactionResultInternalError),
47    NotSupported(TransactionResultNotSupported),
48    BadSponsorship(TransactionResultBadSponsorship),
49    BadMinSeqAgeOrGap(TransactionResultBadMinSeqAgeOrGap),
50    Malformed(TransactionResultMalformed),
51    SorobanInvalid(TransactionResultSorobanInvalid),
52}
53
54#[derive(Debug, Clone, PartialEq, Eq)]
55pub struct TransactionResultFeeBumpSuccess {
56    pub fee_charged: Stroops,
57    pub transaction_hash: Vec<u8>,
58    pub result: InnerTransactionResult,
59}
60
61#[derive(Debug, Clone, PartialEq, Eq)]
62pub struct TransactionResultFeeBumpInnerSuccess {
63    pub fee_charged: Stroops,
64}
65
66#[derive(Debug, Clone, PartialEq, Eq)]
67pub struct TransactionResultFeeBumpFailed {
68    pub fee_charged: Stroops,
69    pub transaction_hash: Vec<u8>,
70    pub result: InnerTransactionResult,
71}
72
73#[derive(Debug, Clone, PartialEq, Eq)]
74pub struct TransactionResultFeeBumpInnerFailed {
75    pub fee_charged: Stroops,
76}
77
78#[derive(Debug, Clone, PartialEq, Eq)]
79pub struct TransactionResultSuccess {
80    pub fee_charged: Stroops,
81    pub results: Vec<OperationResult>,
82}
83
84#[derive(Debug, Clone, PartialEq, Eq)]
85pub struct TransactionResultFailed {
86    pub fee_charged: Stroops,
87    pub results: Vec<OperationResult>,
88}
89
90#[derive(Debug, Clone, PartialEq, Eq)]
91pub struct TransactionResultTooEarly {
92    pub fee_charged: Stroops,
93}
94
95#[derive(Debug, Clone, PartialEq, Eq)]
96pub struct TransactionResultTooLate {
97    pub fee_charged: Stroops,
98}
99
100#[derive(Debug, Clone, PartialEq, Eq)]
101pub struct TransactionResultMissingOperation {
102    pub fee_charged: Stroops,
103}
104
105#[derive(Debug, Clone, PartialEq, Eq)]
106pub struct TransactionResultBadSequence {
107    pub fee_charged: Stroops,
108}
109
110#[derive(Debug, Clone, PartialEq, Eq)]
111pub struct TransactionResultBadAuth {
112    pub fee_charged: Stroops,
113}
114
115#[derive(Debug, Clone, PartialEq, Eq)]
116pub struct TransactionResultInsufficientBalance {
117    pub fee_charged: Stroops,
118}
119
120#[derive(Debug, Clone, PartialEq, Eq)]
121pub struct TransactionResultNoAccount {
122    pub fee_charged: Stroops,
123}
124
125#[derive(Debug, Clone, PartialEq, Eq)]
126pub struct TransactionResultInsufficientFee {
127    pub fee_charged: Stroops,
128}
129
130#[derive(Debug, Clone, PartialEq, Eq)]
131pub struct TransactionResultBadAuthExtra {
132    pub fee_charged: Stroops,
133}
134
135#[derive(Debug, Clone, PartialEq, Eq)]
136pub struct TransactionResultInternalError {
137    pub fee_charged: Stroops,
138}
139
140#[derive(Debug, Clone, PartialEq, Eq)]
141pub struct TransactionResultNotSupported {
142    pub fee_charged: Stroops,
143}
144
145#[derive(Debug, Clone, PartialEq, Eq)]
146pub struct TransactionResultBadSponsorship {
147    pub fee_charged: Stroops,
148}
149
150#[derive(Debug, Clone, PartialEq, Eq)]
151pub struct TransactionResultBadMinSeqAgeOrGap {
152    pub fee_charged: Stroops,
153}
154
155#[derive(Debug, Clone, PartialEq, Eq)]
156pub struct TransactionResultMalformed {
157    pub fee_charged: Stroops,
158}
159
160#[derive(Debug, Clone, PartialEq, Eq)]
161pub struct TransactionResultSorobanInvalid {
162    pub fee_charged: Stroops,
163}
164
165impl TransactionResult {
166    /// If the result is a FeeBumpSuccess, returns its value. Returns None otherwise
167    pub fn as_fee_bump_success(&self) -> Option<&TransactionResultFeeBumpSuccess> {
168        match *self {
169            TransactionResult::FeeBumpSuccess(ref inner) => Some(inner),
170            _ => None,
171        }
172    }
173
174    /// Returns true if the transaction result is a FeeBumpSuccess.
175    pub fn is_fee_bump_success(&self) -> bool {
176        self.as_fee_bump_success().is_some()
177    }
178
179    /// If the result is a FeeBumpFailed, returns its value. Returns None otherwise
180    pub fn as_fee_bump_failed(&self) -> Option<&TransactionResultFeeBumpFailed> {
181        match *self {
182            TransactionResult::FeeBumpFailed(ref inner) => Some(inner),
183            _ => None,
184        }
185    }
186
187    /// Returns true if the transaction result is a FeeBumpFailed.
188    pub fn is_fee_bump_failed(&self) -> bool {
189        self.as_fee_bump_failed().is_some()
190    }
191
192    /// If the result is a Success, returns its value. Returns None otherwise
193    pub fn as_success(&self) -> Option<&TransactionResultSuccess> {
194        match *self {
195            TransactionResult::Success(ref inner) => Some(inner),
196            _ => None,
197        }
198    }
199
200    /// Returns true if the transaction result is a Success.
201    pub fn is_success(&self) -> bool {
202        self.as_success().is_some()
203    }
204
205    /// If the result is a Failed, returns its value. Returns None otherwise
206    pub fn as_failed(&self) -> Option<&TransactionResultFailed> {
207        match *self {
208            TransactionResult::Failed(ref inner) => Some(inner),
209            _ => None,
210        }
211    }
212
213    /// Returns true if the transaction result is a Failed.
214    pub fn is_failed(&self) -> bool {
215        self.as_failed().is_some()
216    }
217
218    /// If the result is a TooEarly, returns its value. Returns None otherwise
219    pub fn as_too_early(&self) -> Option<&TransactionResultTooEarly> {
220        match *self {
221            TransactionResult::TooEarly(ref inner) => Some(inner),
222            _ => None,
223        }
224    }
225
226    /// Returns true if the transaction result is a TooEarly.
227    pub fn is_too_early(&self) -> bool {
228        self.as_too_early().is_some()
229    }
230
231    /// If the result is a TooLate, returns its value. Returns None otherwise
232    pub fn as_too_late(&self) -> Option<&TransactionResultTooLate> {
233        match *self {
234            TransactionResult::TooLate(ref inner) => Some(inner),
235            _ => None,
236        }
237    }
238
239    /// Returns true if the transaction result is a TooLate.
240    pub fn is_too_late(&self) -> bool {
241        self.as_too_late().is_some()
242    }
243
244    /// If the result is a MissingOperation, returns its value. Returns None otherwise
245    pub fn as_missing_operation(&self) -> Option<&TransactionResultMissingOperation> {
246        match *self {
247            TransactionResult::MissingOperation(ref inner) => Some(inner),
248            _ => None,
249        }
250    }
251
252    /// Returns true if the transaction result is a MissingOperation.
253    pub fn is_missing_operation(&self) -> bool {
254        self.as_missing_operation().is_some()
255    }
256
257    /// If the result is a BadSequence, returns its value. Returns None otherwise
258    pub fn as_bad_sequence(&self) -> Option<&TransactionResultBadSequence> {
259        match *self {
260            TransactionResult::BadSequence(ref inner) => Some(inner),
261            _ => None,
262        }
263    }
264
265    /// Returns true if the transaction result is a BadSequence.
266    pub fn is_bad_sequence(&self) -> bool {
267        self.as_bad_sequence().is_some()
268    }
269
270    /// If the result is a BadAuth, returns its value. Returns None otherwise
271    pub fn as_bad_auth(&self) -> Option<&TransactionResultBadAuth> {
272        match *self {
273            TransactionResult::BadAuth(ref inner) => Some(inner),
274            _ => None,
275        }
276    }
277
278    /// Returns true if the transaction result is a BadAuth.
279    pub fn is_bad_auth(&self) -> bool {
280        self.as_bad_auth().is_some()
281    }
282
283    /// If the result is a InsufficientBalance, returns its value. Returns None otherwise
284    pub fn as_insufficient_balance(&self) -> Option<&TransactionResultInsufficientBalance> {
285        match *self {
286            TransactionResult::InsufficientBalance(ref inner) => Some(inner),
287            _ => None,
288        }
289    }
290
291    /// Returns true if the transaction result is a InsufficientBalance.
292    pub fn is_insufficient_balance(&self) -> bool {
293        self.as_insufficient_balance().is_some()
294    }
295
296    /// If the result is a NoAccount, returns its value. Returns None otherwise
297    pub fn as_no_account(&self) -> Option<&TransactionResultNoAccount> {
298        match *self {
299            TransactionResult::NoAccount(ref inner) => Some(inner),
300            _ => None,
301        }
302    }
303
304    /// Returns true if the transaction result is a NoAccount.
305    pub fn is_no_account(&self) -> bool {
306        self.as_no_account().is_some()
307    }
308
309    /// If the result is a InsufficientFee, returns its value. Returns None otherwise
310    pub fn as_insufficient_fee(&self) -> Option<&TransactionResultInsufficientFee> {
311        match *self {
312            TransactionResult::InsufficientFee(ref inner) => Some(inner),
313            _ => None,
314        }
315    }
316
317    /// Returns true if the transaction result is a InsufficientFee.
318    pub fn is_insufficient_fee(&self) -> bool {
319        self.as_insufficient_fee().is_some()
320    }
321
322    /// If the result is a BadAuthExtra, returns its value. Returns None otherwise
323    pub fn as_bad_auth_extra(&self) -> Option<&TransactionResultBadAuthExtra> {
324        match *self {
325            TransactionResult::BadAuthExtra(ref inner) => Some(inner),
326            _ => None,
327        }
328    }
329
330    /// Returns true if the transaction result is a BadAuthExtra.
331    pub fn is_bad_auth_extra(&self) -> bool {
332        self.as_bad_auth_extra().is_some()
333    }
334
335    /// If the result is a InternalError, returns its value. Returns None otherwise
336    pub fn as_internal_error(&self) -> Option<&TransactionResultInternalError> {
337        match *self {
338            TransactionResult::InternalError(ref inner) => Some(inner),
339            _ => None,
340        }
341    }
342
343    /// Returns true if the transaction result is a InternalError.
344    pub fn is_internal_error(&self) -> bool {
345        self.as_internal_error().is_some()
346    }
347
348    /// If the result is a NotSupported, returns its value. Returns None otherwise
349    pub fn as_not_supported(&self) -> Option<&TransactionResultNotSupported> {
350        match *self {
351            TransactionResult::NotSupported(ref inner) => Some(inner),
352            _ => None,
353        }
354    }
355
356    /// Returns true if the transaction result is a NotSupported.
357    pub fn is_not_supported(&self) -> bool {
358        self.as_not_supported().is_some()
359    }
360
361    /// If the result is a BadSponsorship, returns its value. Returns None otherwise
362    pub fn as_bad_sponsorship(&self) -> Option<&TransactionResultBadSponsorship> {
363        match *self {
364            TransactionResult::BadSponsorship(ref inner) => Some(inner),
365            _ => None,
366        }
367    }
368
369    /// Returns true if the transaction result is a BadSponsorship.
370    pub fn is_bad_sponsorship(&self) -> bool {
371        self.as_bad_sponsorship().is_some()
372    }
373
374    /// Creates `TransactionResult` from xdr object.
375    pub fn from_xdr(x: &xdr::TransactionResult) -> Result<TransactionResult> {
376        let fee_charged = Stroops::from_xdr_int64(x.fee_charged)?;
377        match x.result {
378            xdr::TransactionResultResult::TxFeeBumpInnerSuccess(ref xdr_inner) => {
379                let transaction_hash = xdr_inner.transaction_hash.0.to_vec();
380                let result = InnerTransactionResult::from_xdr(&xdr_inner.result)?;
381                let inner = TransactionResultFeeBumpSuccess {
382                    fee_charged,
383                    transaction_hash,
384                    result,
385                };
386                Ok(TransactionResult::FeeBumpSuccess(inner))
387            }
388            xdr::TransactionResultResult::TxFeeBumpInnerFailed(ref xdr_inner) => {
389                let transaction_hash = xdr_inner.transaction_hash.0.to_vec();
390                let result = InnerTransactionResult::from_xdr(&xdr_inner.result)?;
391                let inner = TransactionResultFeeBumpFailed {
392                    fee_charged,
393                    transaction_hash,
394                    result,
395                };
396                Ok(TransactionResult::FeeBumpFailed(inner))
397            }
398            xdr::TransactionResultResult::TxSuccess(ref xdr_results) => {
399                let mut results = Vec::new();
400                for xdr_result in xdr_results.as_vec() {
401                    let result = OperationResult::from_xdr(xdr_result)?;
402                    results.push(result);
403                }
404                let inner = TransactionResultSuccess {
405                    fee_charged,
406                    results,
407                };
408                Ok(TransactionResult::Success(inner))
409            }
410            xdr::TransactionResultResult::TxFailed(ref xdr_results) => {
411                let mut results = Vec::new();
412                for xdr_result in xdr_results.as_vec() {
413                    let result = OperationResult::from_xdr(xdr_result)?;
414                    results.push(result);
415                }
416                let inner = TransactionResultFailed {
417                    fee_charged,
418                    results,
419                };
420                Ok(TransactionResult::Failed(inner))
421            }
422            xdr::TransactionResultResult::TxTooEarly => {
423                let inner = TransactionResultTooEarly { fee_charged };
424                Ok(TransactionResult::TooEarly(inner))
425            }
426            xdr::TransactionResultResult::TxTooLate => {
427                let inner = TransactionResultTooLate { fee_charged };
428                Ok(TransactionResult::TooLate(inner))
429            }
430            xdr::TransactionResultResult::TxMissingOperation => {
431                let inner = TransactionResultMissingOperation { fee_charged };
432                Ok(TransactionResult::MissingOperation(inner))
433            }
434            xdr::TransactionResultResult::TxBadSeq => {
435                let inner = TransactionResultBadSequence { fee_charged };
436                Ok(TransactionResult::BadSequence(inner))
437            }
438            xdr::TransactionResultResult::TxBadAuth => {
439                let inner = TransactionResultBadAuth { fee_charged };
440                Ok(TransactionResult::BadAuth(inner))
441            }
442            xdr::TransactionResultResult::TxInsufficientBalance => {
443                let inner = TransactionResultInsufficientBalance { fee_charged };
444                Ok(TransactionResult::InsufficientBalance(inner))
445            }
446            xdr::TransactionResultResult::TxNoAccount => {
447                let inner = TransactionResultNoAccount { fee_charged };
448                Ok(TransactionResult::NoAccount(inner))
449            }
450            xdr::TransactionResultResult::TxInsufficientFee => {
451                let inner = TransactionResultInsufficientFee { fee_charged };
452                Ok(TransactionResult::InsufficientFee(inner))
453            }
454            xdr::TransactionResultResult::TxBadAuthExtra => {
455                let inner = TransactionResultBadAuthExtra { fee_charged };
456                Ok(TransactionResult::BadAuthExtra(inner))
457            }
458            xdr::TransactionResultResult::TxInternalError => {
459                let inner = TransactionResultInternalError { fee_charged };
460                Ok(TransactionResult::InternalError(inner))
461            }
462            xdr::TransactionResultResult::TxNotSupported => {
463                let inner = TransactionResultNotSupported { fee_charged };
464                Ok(TransactionResult::NotSupported(inner))
465            }
466            xdr::TransactionResultResult::TxBadSponsorship => {
467                let inner = TransactionResultBadSponsorship { fee_charged };
468                Ok(TransactionResult::BadSponsorship(inner))
469            }
470            xdr::TransactionResultResult::TxBadMinSeqAgeOrGap => {
471                let inner = TransactionResultBadMinSeqAgeOrGap { fee_charged };
472                Ok(TransactionResult::BadMinSeqAgeOrGap(inner))
473            }
474            xdr::TransactionResultResult::TxMalformed => {
475                let inner = TransactionResultMalformed { fee_charged };
476                Ok(TransactionResult::Malformed(inner))
477            }
478            xdr::TransactionResultResult::TxSorobanInvalid => {
479                let inner = TransactionResultSorobanInvalid { fee_charged };
480                Ok(TransactionResult::SorobanInvalid(inner))
481            }
482        }
483    }
484}
485
486impl xdr::ReadXdr for TransactionResult {
487    fn read_xdr<R: Read>(r: &mut xdr::Limited<R>) -> xdr::Result<Self> {
488        let xdr_result = xdr::TransactionResult::read_xdr(r)?;
489        Self::from_xdr(&xdr_result).map_err(|_| xdr::Error::Invalid)
490    }
491}
492
493impl InnerTransactionResult {
494    /// If the result is a Success, returns its value. Returns None otherwise
495    pub fn as_success(&self) -> Option<&TransactionResultSuccess> {
496        match *self {
497            InnerTransactionResult::Success(ref inner) => Some(inner),
498            _ => None,
499        }
500    }
501
502    /// Returns true if the transaction result is a Success.
503    pub fn is_success(&self) -> bool {
504        self.as_success().is_some()
505    }
506
507    /// If the result is a Failed, returns its value. Returns None otherwise
508    pub fn as_failed(&self) -> Option<&TransactionResultFailed> {
509        match *self {
510            InnerTransactionResult::Failed(ref inner) => Some(inner),
511            _ => None,
512        }
513    }
514
515    /// Returns true if the transaction result is a Failed.
516    pub fn is_failed(&self) -> bool {
517        self.as_failed().is_some()
518    }
519
520    /// If the result is a TooEarly, returns its value. Returns None otherwise
521    pub fn as_too_early(&self) -> Option<&TransactionResultTooEarly> {
522        match *self {
523            InnerTransactionResult::TooEarly(ref inner) => Some(inner),
524            _ => None,
525        }
526    }
527
528    /// Returns true if the transaction result is a TooEarly.
529    pub fn is_too_early(&self) -> bool {
530        self.as_too_early().is_some()
531    }
532
533    /// If the result is a TooLate, returns its value. Returns None otherwise
534    pub fn as_too_late(&self) -> Option<&TransactionResultTooLate> {
535        match *self {
536            InnerTransactionResult::TooLate(ref inner) => Some(inner),
537            _ => None,
538        }
539    }
540
541    /// Returns true if the transaction result is a TooLate.
542    pub fn is_too_late(&self) -> bool {
543        self.as_too_late().is_some()
544    }
545
546    /// If the result is a MissingOperation, returns its value. Returns None otherwise
547    pub fn as_missing_operation(&self) -> Option<&TransactionResultMissingOperation> {
548        match *self {
549            InnerTransactionResult::MissingOperation(ref inner) => Some(inner),
550            _ => None,
551        }
552    }
553
554    /// Returns true if the transaction result is a MissingOperation.
555    pub fn is_missing_operation(&self) -> bool {
556        self.as_missing_operation().is_some()
557    }
558
559    /// If the result is a BadSequence, returns its value. Returns None otherwise
560    pub fn as_bad_sequence(&self) -> Option<&TransactionResultBadSequence> {
561        match *self {
562            InnerTransactionResult::BadSequence(ref inner) => Some(inner),
563            _ => None,
564        }
565    }
566
567    /// Returns true if the transaction result is a BadSequence.
568    pub fn is_bad_sequence(&self) -> bool {
569        self.as_bad_sequence().is_some()
570    }
571
572    /// If the result is a BadAuth, returns its value. Returns None otherwise
573    pub fn as_bad_auth(&self) -> Option<&TransactionResultBadAuth> {
574        match *self {
575            InnerTransactionResult::BadAuth(ref inner) => Some(inner),
576            _ => None,
577        }
578    }
579
580    /// Returns true if the transaction result is a BadAuth.
581    pub fn is_bad_auth(&self) -> bool {
582        self.as_bad_auth().is_some()
583    }
584
585    /// If the result is a InsufficientBalance, returns its value. Returns None otherwise
586    pub fn as_insufficient_balance(&self) -> Option<&TransactionResultInsufficientBalance> {
587        match *self {
588            InnerTransactionResult::InsufficientBalance(ref inner) => Some(inner),
589            _ => None,
590        }
591    }
592
593    /// Returns true if the transaction result is a InsufficientBalance.
594    pub fn is_insufficient_balance(&self) -> bool {
595        self.as_insufficient_balance().is_some()
596    }
597
598    /// If the result is a NoAccount, returns its value. Returns None otherwise
599    pub fn as_no_account(&self) -> Option<&TransactionResultNoAccount> {
600        match *self {
601            InnerTransactionResult::NoAccount(ref inner) => Some(inner),
602            _ => None,
603        }
604    }
605
606    /// Returns true if the transaction result is a NoAccount.
607    pub fn is_no_account(&self) -> bool {
608        self.as_no_account().is_some()
609    }
610
611    /// If the result is a InsufficientFee, returns its value. Returns None otherwise
612    pub fn as_insufficient_fee(&self) -> Option<&TransactionResultInsufficientFee> {
613        match *self {
614            InnerTransactionResult::InsufficientFee(ref inner) => Some(inner),
615            _ => None,
616        }
617    }
618
619    /// Returns true if the transaction result is a InsufficientFee.
620    pub fn is_insufficient_fee(&self) -> bool {
621        self.as_insufficient_fee().is_some()
622    }
623
624    /// If the result is a BadAuthExtra, returns its value. Returns None otherwise
625    pub fn as_bad_auth_extra(&self) -> Option<&TransactionResultBadAuthExtra> {
626        match *self {
627            InnerTransactionResult::BadAuthExtra(ref inner) => Some(inner),
628            _ => None,
629        }
630    }
631
632    /// Returns true if the transaction result is a BadAuthExtra.
633    pub fn is_bad_auth_extra(&self) -> bool {
634        self.as_bad_auth_extra().is_some()
635    }
636
637    /// If the result is a InternalError, returns its value. Returns None otherwise
638    pub fn as_internal_error(&self) -> Option<&TransactionResultInternalError> {
639        match *self {
640            InnerTransactionResult::InternalError(ref inner) => Some(inner),
641            _ => None,
642        }
643    }
644
645    /// Returns true if the transaction result is a InternalError.
646    pub fn is_internal_error(&self) -> bool {
647        self.as_internal_error().is_some()
648    }
649
650    /// If the result is a NotSupported, returns its value. Returns None otherwise
651    pub fn as_not_supported(&self) -> Option<&TransactionResultNotSupported> {
652        match *self {
653            InnerTransactionResult::NotSupported(ref inner) => Some(inner),
654            _ => None,
655        }
656    }
657
658    /// Returns true if the transaction result is a NotSupported.
659    pub fn is_not_supported(&self) -> bool {
660        self.as_not_supported().is_some()
661    }
662
663    /// If the result is a BadSponsorship, returns its value. Returns None otherwise
664    pub fn as_bad_sponsorship(&self) -> Option<&TransactionResultBadSponsorship> {
665        match *self {
666            InnerTransactionResult::BadSponsorship(ref inner) => Some(inner),
667            _ => None,
668        }
669    }
670
671    /// Returns true if the transaction result is a BadSponsorship.
672    pub fn is_bad_sponsorship(&self) -> bool {
673        self.as_bad_sponsorship().is_some()
674    }
675
676    /// Creates `TransactionResult` from xdr object.
677    pub fn from_xdr(x: &xdr::InnerTransactionResult) -> Result<InnerTransactionResult> {
678        let fee_charged = Stroops::from_xdr_int64(x.fee_charged)?;
679        match x.result {
680            xdr::InnerTransactionResultResult::TxSuccess(ref xdr_results) => {
681                let mut results = Vec::new();
682                for xdr_result in xdr_results.as_slice() {
683                    let result = OperationResult::from_xdr(xdr_result)?;
684                    results.push(result);
685                }
686                let inner = TransactionResultSuccess {
687                    fee_charged,
688                    results,
689                };
690                Ok(InnerTransactionResult::Success(inner))
691            }
692            xdr::InnerTransactionResultResult::TxFailed(ref xdr_results) => {
693                let mut results = Vec::new();
694                for xdr_result in xdr_results.as_slice() {
695                    let result = OperationResult::from_xdr(xdr_result)?;
696                    results.push(result);
697                }
698                let inner = TransactionResultFailed {
699                    fee_charged,
700                    results,
701                };
702                Ok(InnerTransactionResult::Failed(inner))
703            }
704            xdr::InnerTransactionResultResult::TxTooEarly => {
705                let inner = TransactionResultTooEarly { fee_charged };
706                Ok(InnerTransactionResult::TooEarly(inner))
707            }
708            xdr::InnerTransactionResultResult::TxTooLate => {
709                let inner = TransactionResultTooLate { fee_charged };
710                Ok(InnerTransactionResult::TooLate(inner))
711            }
712            xdr::InnerTransactionResultResult::TxMissingOperation => {
713                let inner = TransactionResultMissingOperation { fee_charged };
714                Ok(InnerTransactionResult::MissingOperation(inner))
715            }
716            xdr::InnerTransactionResultResult::TxBadSeq => {
717                let inner = TransactionResultBadSequence { fee_charged };
718                Ok(InnerTransactionResult::BadSequence(inner))
719            }
720            xdr::InnerTransactionResultResult::TxBadAuth => {
721                let inner = TransactionResultBadAuth { fee_charged };
722                Ok(InnerTransactionResult::BadAuth(inner))
723            }
724            xdr::InnerTransactionResultResult::TxInsufficientBalance => {
725                let inner = TransactionResultInsufficientBalance { fee_charged };
726                Ok(InnerTransactionResult::InsufficientBalance(inner))
727            }
728            xdr::InnerTransactionResultResult::TxNoAccount => {
729                let inner = TransactionResultNoAccount { fee_charged };
730                Ok(InnerTransactionResult::NoAccount(inner))
731            }
732            xdr::InnerTransactionResultResult::TxInsufficientFee => {
733                let inner = TransactionResultInsufficientFee { fee_charged };
734                Ok(InnerTransactionResult::InsufficientFee(inner))
735            }
736            xdr::InnerTransactionResultResult::TxBadAuthExtra => {
737                let inner = TransactionResultBadAuthExtra { fee_charged };
738                Ok(InnerTransactionResult::BadAuthExtra(inner))
739            }
740            xdr::InnerTransactionResultResult::TxInternalError => {
741                let inner = TransactionResultInternalError { fee_charged };
742                Ok(InnerTransactionResult::InternalError(inner))
743            }
744            xdr::InnerTransactionResultResult::TxNotSupported => {
745                let inner = TransactionResultNotSupported { fee_charged };
746                Ok(InnerTransactionResult::NotSupported(inner))
747            }
748            xdr::InnerTransactionResultResult::TxBadSponsorship => {
749                let inner = TransactionResultBadSponsorship { fee_charged };
750                Ok(InnerTransactionResult::BadSponsorship(inner))
751            }
752            xdr::InnerTransactionResultResult::TxBadMinSeqAgeOrGap => {
753                let inner = TransactionResultBadMinSeqAgeOrGap { fee_charged };
754                Ok(InnerTransactionResult::BadMinSeqAgeOrGap(inner))
755            }
756            xdr::InnerTransactionResultResult::TxMalformed => {
757                let inner = TransactionResultMalformed { fee_charged };
758                Ok(InnerTransactionResult::Malformed(inner))
759            }
760            xdr::InnerTransactionResultResult::TxSorobanInvalid => {
761                let inner = TransactionResultSorobanInvalid { fee_charged };
762                Ok(InnerTransactionResult::SorobanInvalid(inner))
763            }
764        }
765    }
766}
767
768impl xdr::ReadXdr for InnerTransactionResult {
769    fn read_xdr<R: Read>(r: &mut xdr::Limited<R>) -> xdr::Result<Self> {
770        let xdr_result = xdr::InnerTransactionResult::read_xdr(r)?;
771        Self::from_xdr(&xdr_result).map_err(|_| xdr::Error::Invalid)
772    }
773}
774
775#[cfg(test)]
776mod tests {
777    use super::TransactionResult;
778    use crate::xdr::XDRDeserialize;
779
780    #[test]
781    fn test_fee_bump_success() {
782        let xdr = "AAAAAAAAA+gAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH0AAAAAAAAAAAAAAAAAAAAAA=";
783        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
784        assert!(result.is_fee_bump_success());
785    }
786
787    #[test]
788    fn test_fee_bump_failed() {
789        let xdr = "AAAAAAAAA+j////zAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH0AAAAAAAAAAAAAAAAAAAAAA=";
790        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
791        assert!(result.is_fee_bump_failed());
792    }
793
794    #[test]
795    fn test_success() {
796        let xdr = "AAAAAAAAA+gAAAAAAAAAAAAAAAA=";
797        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
798        assert!(result.is_success());
799    }
800
801    #[test]
802    fn test_failed() {
803        let xdr = "AAAAAAAAA+j/////AAAAAAAAAAA=";
804        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
805        assert!(result.is_failed());
806    }
807
808    #[test]
809    fn test_too_early() {
810        let xdr = "AAAAAAAPQkD////+AAAAAA==";
811        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
812        assert!(result.is_too_early());
813    }
814
815    #[test]
816    fn test_too_late() {
817        let xdr = "AAAAAAAPQkD////9AAAAAA==";
818        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
819        assert!(result.is_too_late());
820    }
821
822    #[test]
823    fn test_missing_operation() {
824        let xdr = "AAAAAAAPQkD////8AAAAAA==";
825        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
826        assert!(result.is_missing_operation());
827    }
828
829    #[test]
830    fn test_bad_sequence() {
831        let xdr = "AAAAAAAPQkD////7AAAAAA==";
832        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
833        assert!(result.is_bad_sequence());
834    }
835
836    #[test]
837    fn test_bad_auth() {
838        let xdr = "AAAAAAAPQkD////6AAAAAA==";
839        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
840        assert!(result.is_bad_auth());
841    }
842
843    #[test]
844    fn test_insufficient_balance() {
845        let xdr = "AAAAAAAPQkD////5AAAAAA==";
846        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
847        assert!(result.is_insufficient_balance());
848    }
849
850    #[test]
851    fn test_no_account() {
852        let xdr = "AAAAAAAPQkD////4AAAAAA==";
853        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
854        assert!(result.is_no_account());
855    }
856
857    #[test]
858    fn test_insufficient_fee() {
859        let xdr = "AAAAAAAPQkD////3AAAAAA==";
860        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
861        assert!(result.is_insufficient_fee());
862    }
863
864    #[test]
865    fn test_bad_auth_extra() {
866        let xdr = "AAAAAAAPQkD////2AAAAAA==";
867        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
868        assert!(result.is_bad_auth_extra());
869    }
870
871    #[test]
872    fn test_internal_error() {
873        let xdr = "AAAAAAAPQkD////1AAAAAA==";
874        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
875        assert!(result.is_internal_error());
876    }
877
878    #[test]
879    fn test_not_supported() {
880        let xdr = "AAAAAAAPQkD////0AAAAAA==";
881        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
882        assert!(result.is_not_supported());
883    }
884
885    #[test]
886    fn test_bad_sponsorship() {
887        let xdr = "AAAAAAAPQkD////yAAAAAA==";
888        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
889        assert!(result.is_bad_sponsorship());
890    }
891
892    #[test]
893    fn test_inner_success() {
894        let xdr = "AAAAAAAAA+gAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH0AAAAAAAAAAAAAAAAAAAAAA=";
895        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
896        let inner_result = result.as_fee_bump_success().unwrap().result.clone();
897        assert!(inner_result.is_success());
898    }
899
900    #[test]
901    fn test_inner_failed() {
902        let xdr = "AAAAAAAAA+gAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH0P////8AAAAAAAAAAAAAAAA=";
903        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
904        let inner_result = result.as_fee_bump_success().unwrap().result.clone();
905        assert!(inner_result.is_failed());
906    }
907
908    #[test]
909    fn test_inner_too_early() {
910        let xdr = "AAAAAAAAA+gAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH0P////4AAAAAAAAAAA==";
911        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
912        let inner_result = result.as_fee_bump_success().unwrap().result.clone();
913        assert!(inner_result.is_too_early());
914    }
915
916    #[test]
917    fn test_inner_too_late() {
918        let xdr = "AAAAAAAAA+gAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH0P////0AAAAAAAAAAA==";
919        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
920        let inner_result = result.as_fee_bump_success().unwrap().result.clone();
921        assert!(inner_result.is_too_late());
922    }
923
924    #[test]
925    fn test_inner_missing_operation() {
926        let xdr = "AAAAAAAAA+gAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH0P////wAAAAAAAAAAA==";
927        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
928        let inner_result = result.as_fee_bump_success().unwrap().result.clone();
929        assert!(inner_result.is_missing_operation());
930    }
931
932    #[test]
933    fn test_inner_bad_sequence() {
934        let xdr = "AAAAAAAAA+gAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH0P////sAAAAAAAAAAA==";
935        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
936        let inner_result = result.as_fee_bump_success().unwrap().result.clone();
937        assert!(inner_result.is_bad_sequence());
938    }
939
940    #[test]
941    fn test_inner_bad_auth() {
942        let xdr = "AAAAAAAAA+gAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH0P////oAAAAAAAAAAA==";
943        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
944        let inner_result = result.as_fee_bump_success().unwrap().result.clone();
945        assert!(inner_result.is_bad_auth());
946    }
947
948    #[test]
949    fn test_inner_insufficient_balance() {
950        let xdr = "AAAAAAAAA+gAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH0P////kAAAAAAAAAAA==";
951        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
952        let inner_result = result.as_fee_bump_success().unwrap().result.clone();
953        assert!(inner_result.is_insufficient_balance());
954    }
955
956    #[test]
957    fn test_inner_no_account() {
958        let xdr = "AAAAAAAAA+gAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH0P////gAAAAAAAAAAA==";
959        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
960        let inner_result = result.as_fee_bump_success().unwrap().result.clone();
961        assert!(inner_result.is_no_account());
962    }
963
964    #[test]
965    fn test_inner_insufficient_fee() {
966        let xdr = "AAAAAAAAA+gAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH0P////cAAAAAAAAAAA==";
967        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
968        let inner_result = result.as_fee_bump_success().unwrap().result.clone();
969        assert!(inner_result.is_insufficient_fee());
970    }
971
972    #[test]
973    fn test_inner_bad_auth_extra() {
974        let xdr = "AAAAAAAAA+gAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH0P////YAAAAAAAAAAA==";
975        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
976        let inner_result = result.as_fee_bump_success().unwrap().result.clone();
977        assert!(inner_result.is_bad_auth_extra());
978    }
979
980    #[test]
981    fn test_inner_internal_error() {
982        let xdr = "AAAAAAAAA+gAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH0P////UAAAAAAAAAAA==";
983        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
984        let inner_result = result.as_fee_bump_success().unwrap().result.clone();
985        assert!(inner_result.is_internal_error());
986    }
987
988    #[test]
989    fn test_inner_not_supported() {
990        let xdr = "AAAAAAAAA+gAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH0P////QAAAAAAAAAAA==";
991        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
992        let inner_result = result.as_fee_bump_success().unwrap().result.clone();
993        assert!(inner_result.is_not_supported());
994    }
995
996    #[test]
997    fn test_inner_bad_sponsorship() {
998        let xdr = "AAAAAAAAA+gAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH0P////IAAAAAAAAAAA==";
999        let result = TransactionResult::from_xdr_base64(xdr).unwrap();
1000        let inner_result = result.as_fee_bump_success().unwrap().result.clone();
1001        assert!(inner_result.is_bad_sponsorship());
1002    }
1003}