stellar_base/operations/
account_merge.rs

1use crate::crypto::MuxedAccount;
2use crate::error::{Error, Result};
3use crate::operations::Operation;
4use crate::xdr;
5
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct AccountMergeOperation {
8    source_account: Option<MuxedAccount>,
9    destination: MuxedAccount,
10}
11
12#[derive(Debug, Default)]
13pub struct AccountMergeOperationBuilder {
14    source_account: Option<MuxedAccount>,
15    destination: Option<MuxedAccount>,
16}
17
18impl AccountMergeOperation {
19    /// Retrieves the operation source account.
20    pub fn source_account(&self) -> &Option<MuxedAccount> {
21        &self.source_account
22    }
23
24    /// Retrieves a reference to the operation source account.
25    pub fn source_account_mut(&mut self) -> &mut Option<MuxedAccount> {
26        &mut self.source_account
27    }
28
29    /// Retrieve the operation destination.
30    pub fn destination(&self) -> &MuxedAccount {
31        &self.destination
32    }
33
34    /// Retrieve the operation destination.
35    pub fn destination_mut(&mut self) -> &mut MuxedAccount {
36        &mut self.destination
37    }
38
39    /// Returns tho xdr operation body.
40    pub fn to_xdr_operation_body(&self) -> Result<xdr::OperationBody> {
41        let muxed_account = self.destination.to_xdr()?;
42        Ok(xdr::OperationBody::AccountMerge(muxed_account))
43    }
44
45    /// Creates from the xdr operation body.
46    pub fn from_xdr_operation_body(
47        source_account: Option<MuxedAccount>,
48        x: &xdr::MuxedAccount,
49    ) -> Result<AccountMergeOperation> {
50        let destination = MuxedAccount::from_xdr(x)?;
51        Ok(AccountMergeOperation {
52            source_account,
53            destination,
54        })
55    }
56}
57
58impl AccountMergeOperationBuilder {
59    pub fn new() -> AccountMergeOperationBuilder {
60        Default::default()
61    }
62
63    pub fn with_source_account<S>(mut self, source: S) -> AccountMergeOperationBuilder
64    where
65        S: Into<MuxedAccount>,
66    {
67        self.source_account = Some(source.into());
68        self
69    }
70
71    pub fn with_destination(mut self, destination: MuxedAccount) -> AccountMergeOperationBuilder {
72        self.destination = Some(destination);
73        self
74    }
75
76    pub fn build(mut self) -> Result<Operation> {
77        if let Some(destination) = self.destination.take() {
78            Ok(Operation::AccountMerge(AccountMergeOperation {
79                source_account: self.source_account,
80                destination,
81            }))
82        } else {
83            Err(Error::InvalidOperation(
84                "missing account merge destination".to_string(),
85            ))
86        }
87    }
88}
89
90#[cfg(test)]
91mod tests {
92
93    use crate::network::Network;
94    use crate::operations::tests::*;
95    use crate::operations::Operation;
96    use crate::transaction::{Transaction, TransactionEnvelope, MIN_BASE_FEE};
97    use crate::xdr::{XDRDeserialize, XDRSerialize};
98    #[test]
99    fn test_account_merge() {
100        let kp = keypair0();
101        let kp1 = keypair1();
102
103        let op = Operation::new_account_merge()
104            .with_destination(kp1.public_key().to_muxed_account(123).clone())
105            .build()
106            .unwrap();
107        let mut tx = Transaction::builder(kp.public_key(), 3556091187167235, MIN_BASE_FEE)
108            .add_operation(op)
109            .into_transaction()
110            .unwrap();
111        tx.sign(kp.as_ref(), &Network::new_test()).unwrap();
112        let envelope = tx.to_envelope();
113        let xdr = envelope.xdr_base64().unwrap();
114        let expected = "AAAAAgAAAADg3G3hclysZlFitS+s5zWyiiJD5B0STWy5LXCj6i5yxQAAAGQADKI/AAAAAwAAAAAAAAAAAAAAAQAAAAAAAAAIAAABAAAAAAAAAAB7Jcrx2g/Hbs/ohF5CVFG7B5JJSJR+OqDKzDGK7dKHZH4AAAAAAAAAAeoucsUAAABAsar7y6Xy4F1R8InkdOL21n646Z5Fe6dUUfhAkDf9GnIQKHcFzVoeo7z73S6V0zW1AxfR/wJDsFprWPhbllYhBw==";
115        assert_eq!(expected, xdr);
116        let back = TransactionEnvelope::from_xdr_base64(&xdr).unwrap();
117        assert_eq!(envelope, back);
118    }
119
120    #[test]
121    fn test_account_merge_with_source_account() {
122        let kp = keypair0();
123        let kp1 = keypair1();
124        let kp2 = keypair2();
125
126        let op = Operation::new_account_merge()
127            .with_destination(kp1.public_key().to_muxed_account(123).clone())
128            .with_source_account(kp2.public_key())
129            .build()
130            .unwrap();
131        let mut tx = Transaction::builder(kp.public_key(), 3556091187167235, MIN_BASE_FEE)
132            .add_operation(op)
133            .into_transaction()
134            .unwrap();
135        tx.sign(kp.as_ref(), &Network::new_test()).unwrap();
136        let envelope = tx.to_envelope();
137        let xdr = envelope.xdr_base64().unwrap();
138        let expected = "AAAAAgAAAADg3G3hclysZlFitS+s5zWyiiJD5B0STWy5LXCj6i5yxQAAAGQADKI/AAAAAwAAAAAAAAAAAAAAAQAAAAEAAAAAfhHLNNY19eGrAtSgLD3VpaRm2AjNjxIBWQg9zS4VWZgAAAAIAAABAAAAAAAAAAB7Jcrx2g/Hbs/ohF5CVFG7B5JJSJR+OqDKzDGK7dKHZH4AAAAAAAAAAeoucsUAAABAXZWyIftD9wZB7iI/CPWdye29ggvdwf20/WQr00IbTshuas0JDIbJhhfK8NUrEILhBspQjRx82XCrppZVrampAQ==";
139        assert_eq!(expected, xdr);
140        let back = TransactionEnvelope::from_xdr_base64(&xdr).unwrap();
141        assert_eq!(envelope, back);
142    }
143}