stellar_base/operations/
restore_footprint.rs

1use crate::crypto::MuxedAccount;
2use crate::error::Result;
3use crate::operations::Operation;
4use crate::xdr;
5
6/// Represents an operation to restore the Soroban footprint.
7///
8/// Soroban transactions include a footprint describing which ledger entries they
9/// read and/or write. Some ledger entries used by smart contracts may have a TTL
10/// (time to live) in the eviction queue. This operation restores any evicted
11/// entries referenced in the transaction's footprint back into the ledger.
12///
13/// The XDR struct `RestoreFootprintOp` currently contains only an `ExtensionPoint`
14/// which is always the `V0` (empty) variant for now.
15#[derive(Debug, Clone, PartialEq, Eq)]
16pub struct RestoreFootprintOperation {
17    source_account: Option<MuxedAccount>,
18}
19
20#[derive(Debug, Default)]
21pub struct RestoreFootprintOperationBuilder {
22    source_account: Option<MuxedAccount>,
23}
24
25impl RestoreFootprintOperation {
26    /// Retrieves the operation source account.
27    pub fn source_account(&self) -> &Option<MuxedAccount> {
28        &self.source_account
29    }
30
31    /// Retrieves a mutable reference to the operation source account.
32    pub fn source_account_mut(&mut self) -> &mut Option<MuxedAccount> {
33        &mut self.source_account
34    }
35
36    /// Returns the XDR operation body.
37    pub fn to_xdr_operation_body(&self) -> Result<xdr::OperationBody> {
38        let inner = xdr::RestoreFootprintOp {
39            ext: xdr::ExtensionPoint::V0,
40        };
41        Ok(xdr::OperationBody::RestoreFootprint(inner))
42    }
43
44    /// Creates from the XDR operation body.
45    pub fn from_xdr_operation_body(
46        source_account: Option<MuxedAccount>,
47        _x: &xdr::RestoreFootprintOp,
48    ) -> Result<RestoreFootprintOperation> {
49        Ok(RestoreFootprintOperation { source_account })
50    }
51}
52
53impl RestoreFootprintOperationBuilder {
54    pub fn new() -> RestoreFootprintOperationBuilder {
55        Default::default()
56    }
57
58    /// Sets the operation source account.
59    pub fn with_source_account<S>(mut self, source: S) -> RestoreFootprintOperationBuilder
60    where
61        S: Into<MuxedAccount>,
62    {
63        self.source_account = Some(source.into());
64        self
65    }
66
67    /// Builds the operation.
68    pub fn build(self) -> Operation {
69        Operation::RestoreFootprint(RestoreFootprintOperation {
70            source_account: self.source_account,
71        })
72    }
73}
74
75#[cfg(test)]
76mod tests {
77    use super::*;
78    use crate::operations::tests::*;
79    use crate::operations::Operation;
80    use crate::xdr::{XDRDeserialize, XDRSerialize};
81
82    #[test]
83    fn test_restore_footprint_roundtrip() {
84        let op = RestoreFootprintOperationBuilder::new().build();
85        let encoded = op.xdr_base64().unwrap();
86        let decoded = Operation::from_xdr_base64(&encoded).unwrap();
87        assert_eq!(op, decoded);
88        if let Operation::RestoreFootprint(inner) = decoded {
89            assert!(inner.source_account().is_none());
90        } else {
91            panic!("expected RestoreFootprint operation");
92        }
93    }
94
95    #[test]
96    fn test_restore_footprint_with_source_account() {
97        let source = keypair0().public_key();
98        let op = RestoreFootprintOperationBuilder::new()
99            .with_source_account(source)
100            .build();
101        let encoded = op.xdr_base64().unwrap();
102        let decoded = Operation::from_xdr_base64(&encoded).unwrap();
103        assert_eq!(op, decoded);
104        match decoded {
105            Operation::RestoreFootprint(inner) => {
106                assert!(inner.source_account().is_some());
107            }
108            _ => panic!("expected RestoreFootprint operation"),
109        }
110    }
111}