stellar_base/operations/
revoke_sponsorship.rs

1use crate::asset::TrustLineAsset;
2use crate::claim::ClaimableBalanceId;
3use crate::crypto::{MuxedAccount, PublicKey, SignerKey};
4use crate::error::{Error, Result};
5use crate::ledger::LedgerKey;
6use crate::liquidity_pool::LiquidityPoolId;
7use crate::operations::Operation;
8use crate::xdr;
9
10#[derive(Debug, Clone, PartialEq, Eq)]
11pub enum RevokeSponsorshipOperation {
12    LedgerEntry(RevokeSponsorshipLedgerEntry),
13    Signer(RevokeSponsorshipSigner),
14}
15
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct RevokeSponsorshipLedgerEntry {
18    source_account: Option<MuxedAccount>,
19    ledger_key: LedgerKey,
20}
21
22#[derive(Debug, Clone, PartialEq, Eq)]
23pub struct RevokeSponsorshipSigner {
24    source_account: Option<MuxedAccount>,
25    account_id: PublicKey,
26    signer_key: SignerKey,
27}
28
29#[derive(Debug, Default)]
30pub struct RevokeSponsorshipOperationBuilder {
31    source_account: Option<MuxedAccount>,
32    value: Option<RevokeSponsorshipValue>,
33}
34
35#[derive(Debug)]
36pub enum RevokeSponsorshipValue {
37    LedgerEntry(LedgerKey),
38    Signer(PublicKey, SignerKey),
39}
40
41impl RevokeSponsorshipOperation {
42    /// Retrieves the operation source account.
43    pub fn source_account(&self) -> &Option<MuxedAccount> {
44        match *self {
45            RevokeSponsorshipOperation::LedgerEntry(ref le) => le.source_account(),
46            RevokeSponsorshipOperation::Signer(ref s) => s.source_account(),
47        }
48    }
49
50    /// Retrieves a reference to the operation source account.
51    pub fn source_account_mut(&mut self) -> &mut Option<MuxedAccount> {
52        match *self {
53            RevokeSponsorshipOperation::LedgerEntry(ref mut le) => le.source_account_mut(),
54            RevokeSponsorshipOperation::Signer(ref mut s) => s.source_account_mut(),
55        }
56    }
57
58    /// If the operation is a LedgerEntry, returns its value. Returns None otherwise.
59    pub fn as_ledger_entry(&self) -> Option<&RevokeSponsorshipLedgerEntry> {
60        match *self {
61            RevokeSponsorshipOperation::LedgerEntry(ref inner) => Some(inner),
62            _ => None,
63        }
64    }
65
66    /// If the operation is a LedgerEntry, returns its value. Returns None otherwise.
67    pub fn as_ledger_entry_mut(&mut self) -> Option<&mut RevokeSponsorshipLedgerEntry> {
68        match *self {
69            RevokeSponsorshipOperation::LedgerEntry(ref mut inner) => Some(inner),
70            _ => None,
71        }
72    }
73
74    /// Returns true if the operation is a LedgerEntry.
75    pub fn is_ledger_entry(&self) -> bool {
76        self.as_ledger_entry().is_some()
77    }
78
79    /// If the operation is a Signer, returns its value. Returns None otherwise.
80    pub fn as_signer(&self) -> Option<&RevokeSponsorshipSigner> {
81        match *self {
82            RevokeSponsorshipOperation::Signer(ref inner) => Some(inner),
83            _ => None,
84        }
85    }
86
87    /// If the operation is a Signer, returns its value. Returns None otherwise.
88    pub fn as_signer_mut(&mut self) -> Option<&mut RevokeSponsorshipSigner> {
89        match *self {
90            RevokeSponsorshipOperation::Signer(ref mut inner) => Some(inner),
91            _ => None,
92        }
93    }
94
95    /// Returns true if the operation is a Signer.
96    pub fn is_signer(&self) -> bool {
97        self.as_signer().is_some()
98    }
99
100    /// Returns tho xdr operation body.
101    pub fn to_xdr_operation_body(&self) -> Result<xdr::OperationBody> {
102        let inner = match *self {
103            RevokeSponsorshipOperation::LedgerEntry(ref le) => {
104                let ledger_key = le.ledger_key.to_xdr()?;
105                xdr::RevokeSponsorshipOp::LedgerEntry(ledger_key)
106            }
107            RevokeSponsorshipOperation::Signer(ref s) => {
108                let account_id = s.account_id.to_xdr_account_id()?;
109                let signer_key = s.signer_key.to_xdr()?;
110                let inner = xdr::RevokeSponsorshipOpSigner {
111                    account_id,
112                    signer_key,
113                };
114                xdr::RevokeSponsorshipOp::Signer(inner)
115            }
116        };
117        Ok(xdr::OperationBody::RevokeSponsorship(inner))
118    }
119
120    /// Creates from the xdr operation body.
121    pub fn from_xdr_operation_body(
122        source_account: Option<MuxedAccount>,
123        x: &xdr::RevokeSponsorshipOp,
124    ) -> Result<RevokeSponsorshipOperation> {
125        match x {
126            xdr::RevokeSponsorshipOp::LedgerEntry(ref le) => {
127                let ledger_key = LedgerKey::from_xdr(le)?;
128                let inner = RevokeSponsorshipLedgerEntry {
129                    source_account,
130                    ledger_key,
131                };
132                Ok(RevokeSponsorshipOperation::LedgerEntry(inner))
133            }
134            xdr::RevokeSponsorshipOp::Signer(ref s) => {
135                let account_id = PublicKey::from_xdr_account_id(&s.account_id)?;
136                let signer_key = SignerKey::from_xdr(&s.signer_key)?;
137                let inner = RevokeSponsorshipSigner {
138                    source_account,
139                    account_id,
140                    signer_key,
141                };
142                Ok(RevokeSponsorshipOperation::Signer(inner))
143            }
144        }
145    }
146}
147
148impl RevokeSponsorshipLedgerEntry {
149    /// Retrieves the operation source account.
150    pub fn source_account(&self) -> &Option<MuxedAccount> {
151        &self.source_account
152    }
153
154    /// Retrieves a reference to the operation source account.
155    pub fn source_account_mut(&mut self) -> &mut Option<MuxedAccount> {
156        &mut self.source_account
157    }
158}
159
160impl RevokeSponsorshipSigner {
161    /// Retrieves the operation source account.
162    pub fn source_account(&self) -> &Option<MuxedAccount> {
163        &self.source_account
164    }
165
166    /// Retrieves a reference to the operation source account.
167    pub fn source_account_mut(&mut self) -> &mut Option<MuxedAccount> {
168        &mut self.source_account
169    }
170}
171
172impl LedgerKey {
173    /// Returns the xdr object.
174    pub fn to_xdr(&self) -> Result<xdr::LedgerKey> {
175        match *self {
176            LedgerKey::Account(ref account_id) => {
177                let account_id = account_id.to_xdr_account_id()?;
178                let inner = xdr::LedgerKeyAccount { account_id };
179                Ok(xdr::LedgerKey::Account(inner))
180            }
181            LedgerKey::Trustline(ref account_id, ref asset) => {
182                let account_id = account_id.to_xdr_account_id()?;
183                let asset = asset.to_xdr()?;
184                let inner = xdr::LedgerKeyTrustLine { account_id, asset };
185                Ok(xdr::LedgerKey::Trustline(inner))
186            }
187            LedgerKey::Offer(ref seller_id, ref offer_id) => {
188                let seller_id = seller_id.to_xdr_account_id()?;
189                let inner = xdr::LedgerKeyOffer {
190                    seller_id,
191                    offer_id: *offer_id,
192                };
193                Ok(xdr::LedgerKey::Offer(inner))
194            }
195            LedgerKey::Data(ref account_id, ref data_name) => {
196                let account_id = account_id.to_xdr_account_id()?;
197                let data_name = data_name
198                    .as_bytes()
199                    .to_vec()
200                    .try_into()
201                    .map_err(|_| Error::XdrError)?;
202                let inner = xdr::LedgerKeyData {
203                    account_id,
204                    data_name,
205                };
206                Ok(xdr::LedgerKey::Data(inner))
207            }
208            LedgerKey::ClaimableBalance(ref balance_id) => {
209                let balance_id = balance_id.to_xdr();
210                let inner = xdr::LedgerKeyClaimableBalance { balance_id };
211                Ok(xdr::LedgerKey::ClaimableBalance(inner))
212            }
213            LedgerKey::LiquidityPool(ref liquidity_pool_id) => {
214                let liquidity_pool_id = liquidity_pool_id.to_xdr();
215                let inner = xdr::LedgerKeyLiquidityPool { liquidity_pool_id };
216                Ok(xdr::LedgerKey::LiquidityPool(inner))
217            }
218            LedgerKey::ContractData(ref contract_data) => {
219                Ok(xdr::LedgerKey::ContractData(contract_data.clone()))
220            }
221            LedgerKey::ContractCode(ref contract_code) => {
222                Ok(xdr::LedgerKey::ContractCode(contract_code.clone()))
223            }
224            LedgerKey::ConfigSetting(ref config_setting) => {
225                Ok(xdr::LedgerKey::ConfigSetting(config_setting.clone()))
226            }
227            LedgerKey::Ttl(ref ttl) => Ok(xdr::LedgerKey::Ttl(ttl.clone())),
228        }
229    }
230
231    /// Creates from the xdr object.
232    pub fn from_xdr(x: &xdr::LedgerKey) -> Result<LedgerKey> {
233        match x {
234            xdr::LedgerKey::Account(ref account) => {
235                let account_id = PublicKey::from_xdr_account_id(&account.account_id)?;
236                Ok(LedgerKey::Account(account_id))
237            }
238            xdr::LedgerKey::Trustline(ref trustline) => {
239                let account_id = PublicKey::from_xdr_account_id(&trustline.account_id)?;
240                let asset = TrustLineAsset::from_xdr(&trustline.asset)?;
241                Ok(LedgerKey::Trustline(account_id, asset))
242            }
243            xdr::LedgerKey::Offer(ref offer) => {
244                let seller_id = PublicKey::from_xdr_account_id(&offer.seller_id)?;
245                let offer_id = offer.offer_id;
246                Ok(LedgerKey::Offer(seller_id, offer_id))
247            }
248            xdr::LedgerKey::Data(ref data) => {
249                let account_id = PublicKey::from_xdr_account_id(&data.account_id)?;
250                let data_name = data.data_name.to_string();
251                Ok(LedgerKey::Data(account_id, data_name))
252            }
253            xdr::LedgerKey::ClaimableBalance(ref claimable_balance) => {
254                let balance_id = ClaimableBalanceId::from_xdr(&claimable_balance.balance_id)?;
255                Ok(LedgerKey::ClaimableBalance(balance_id))
256            }
257            xdr::LedgerKey::LiquidityPool(ref liquidity_pool) => {
258                let liquidity_pool_id =
259                    LiquidityPoolId::from_xdr(&liquidity_pool.liquidity_pool_id)?;
260                Ok(LedgerKey::LiquidityPool(liquidity_pool_id))
261            }
262            xdr::LedgerKey::ContractData(ref contract_data) => {
263                Ok(LedgerKey::ContractData(contract_data.to_owned()))
264            }
265            xdr::LedgerKey::ContractCode(ref contract_code) => {
266                Ok(LedgerKey::ContractCode(contract_code.to_owned()))
267            }
268            xdr::LedgerKey::ConfigSetting(ref config_setting) => {
269                Ok(LedgerKey::ConfigSetting(config_setting.to_owned()))
270            }
271            xdr::LedgerKey::Ttl(ref ttl) => Ok(LedgerKey::Ttl(ttl.to_owned())),
272        }
273    }
274}
275
276impl RevokeSponsorshipOperationBuilder {
277    pub fn new() -> RevokeSponsorshipOperationBuilder {
278        Default::default()
279    }
280
281    pub fn with_source_account<S>(mut self, source: S) -> RevokeSponsorshipOperationBuilder
282    where
283        S: Into<MuxedAccount>,
284    {
285        self.source_account = Some(source.into());
286        self
287    }
288
289    pub fn with_ledger_key(mut self, ledger_key: LedgerKey) -> RevokeSponsorshipOperationBuilder {
290        self.value = Some(RevokeSponsorshipValue::LedgerEntry(ledger_key));
291        self
292    }
293
294    pub fn with_signer(
295        mut self,
296        account_id: PublicKey,
297        signer_key: SignerKey,
298    ) -> RevokeSponsorshipOperationBuilder {
299        self.value = Some(RevokeSponsorshipValue::Signer(account_id, signer_key));
300        self
301    }
302
303    pub fn build(self) -> Result<Operation> {
304        match self.value {
305            None => Err(Error::InvalidOperation(
306                "missing revoke sponsorship operation ledger key or signer".to_string(),
307            )),
308            Some(RevokeSponsorshipValue::LedgerEntry(ledger_key)) => {
309                let ledger_entry = RevokeSponsorshipLedgerEntry {
310                    source_account: self.source_account,
311                    ledger_key,
312                };
313                let inner = RevokeSponsorshipOperation::LedgerEntry(ledger_entry);
314                Ok(Operation::RevokeSponsorship(inner))
315            }
316            Some(RevokeSponsorshipValue::Signer(account_id, signer_key)) => {
317                let signer = RevokeSponsorshipSigner {
318                    source_account: self.source_account,
319                    account_id,
320                    signer_key,
321                };
322                let inner = RevokeSponsorshipOperation::Signer(signer);
323                Ok(Operation::RevokeSponsorship(inner))
324            }
325        }
326    }
327}
328
329#[cfg(test)]
330mod tests {
331    use crate::asset::TrustLineAsset;
332    use crate::claim::ClaimableBalanceId;
333    use crate::crypto::SignerKey;
334    use crate::ledger::LedgerKey;
335    use crate::network::Network;
336    use crate::operations::tests::*;
337    use crate::operations::Operation;
338    use crate::transaction::{Transaction, TransactionEnvelope, MIN_BASE_FEE};
339    use crate::xdr::{XDRDeserialize, XDRSerialize};
340
341    #[test]
342    fn test_revoke_sponsorship_ledger_key_account() {
343        let kp = keypair0();
344        let kp1 = keypair1();
345
346        let op = Operation::new_revoke_sponsorship()
347            .with_ledger_key(LedgerKey::Account(kp1.public_key()))
348            .build()
349            .unwrap();
350        let mut tx = Transaction::builder(kp.public_key(), 3556091187167235, MIN_BASE_FEE)
351            .add_operation(op)
352            .into_transaction()
353            .unwrap();
354        tx.sign(kp.as_ref(), &Network::new_test()).unwrap();
355        let envelope = tx.to_envelope();
356        let xdr = envelope.xdr_base64().unwrap();
357        let expected = "AAAAAgAAAADg3G3hclysZlFitS+s5zWyiiJD5B0STWy5LXCj6i5yxQAAAGQADKI/AAAAAwAAAAAAAAAAAAAAAQAAAAAAAAASAAAAAAAAAAAAAAAAJcrx2g/Hbs/ohF5CVFG7B5JJSJR+OqDKzDGK7dKHZH4AAAAAAAAAAeoucsUAAABAlhwbGG2OC+ym0bD7G0GsGnbLInIVKzfLdhCl6AsyioseAydDXCVOB2A8Ywv4XfT0nC4BY26UdPBuLWG3cALmAg==";
358        assert_eq!(expected, xdr);
359        let back = TransactionEnvelope::from_xdr_base64(&xdr).unwrap();
360        assert_eq!(envelope, back);
361    }
362
363    #[test]
364    fn test_revoke_sponsorship_ledger_key_trustline() {
365        let kp = keypair0();
366        let kp1 = keypair1();
367        let kp2 = keypair2();
368
369        let abcd = TrustLineAsset::new_credit("ABCD", kp2.public_key()).unwrap();
370
371        let op = Operation::new_revoke_sponsorship()
372            .with_ledger_key(LedgerKey::Trustline(kp1.public_key(), abcd))
373            .build()
374            .unwrap();
375        let mut tx = Transaction::builder(kp.public_key(), 3556091187167235, MIN_BASE_FEE)
376            .add_operation(op)
377            .into_transaction()
378            .unwrap();
379        tx.sign(kp.as_ref(), &Network::new_test()).unwrap();
380        let envelope = tx.to_envelope();
381        let xdr = envelope.xdr_base64().unwrap();
382        let expected = "AAAAAgAAAADg3G3hclysZlFitS+s5zWyiiJD5B0STWy5LXCj6i5yxQAAAGQADKI/AAAAAwAAAAAAAAAAAAAAAQAAAAAAAAASAAAAAAAAAAEAAAAAJcrx2g/Hbs/ohF5CVFG7B5JJSJR+OqDKzDGK7dKHZH4AAAABQUJDRAAAAAB+Ecs01jX14asC1KAsPdWlpGbYCM2PEgFZCD3NLhVZmAAAAAAAAAAB6i5yxQAAAEA+1KnFKV7vhXjLxRJ+/aWfusVTrV3Az+Iscd13uKG0g6Pi41uTC5nsU07GeC2Os2bwz7r8XlNtxlkwHF89DCcG";
383        assert_eq!(expected, xdr);
384        let back = TransactionEnvelope::from_xdr_base64(&xdr).unwrap();
385        assert_eq!(envelope, back);
386    }
387
388    #[test]
389    fn test_revoke_sponsorship_ledger_key_offer() {
390        let kp = keypair0();
391        let kp1 = keypair1();
392
393        let op = Operation::new_revoke_sponsorship()
394            .with_ledger_key(LedgerKey::Offer(kp1.public_key(), 123))
395            .build()
396            .unwrap();
397        let mut tx = Transaction::builder(kp.public_key(), 3556091187167235, MIN_BASE_FEE)
398            .add_operation(op)
399            .into_transaction()
400            .unwrap();
401        tx.sign(kp.as_ref(), &Network::new_test()).unwrap();
402        let envelope = tx.to_envelope();
403        let xdr = envelope.xdr_base64().unwrap();
404        let expected = "AAAAAgAAAADg3G3hclysZlFitS+s5zWyiiJD5B0STWy5LXCj6i5yxQAAAGQADKI/AAAAAwAAAAAAAAAAAAAAAQAAAAAAAAASAAAAAAAAAAIAAAAAJcrx2g/Hbs/ohF5CVFG7B5JJSJR+OqDKzDGK7dKHZH4AAAAAAAAAewAAAAAAAAAB6i5yxQAAAECBX+hYvz4LN3DoBmTTabB7aZGCjUqps1DZaMm9jLBsHgIUrfmoVNx2e0a6t1o0nvAKpatd3SCZFWIY0W6TnAYJ";
405        assert_eq!(expected, xdr);
406        let back = TransactionEnvelope::from_xdr_base64(&xdr).unwrap();
407        assert_eq!(envelope, back);
408    }
409
410    #[test]
411    fn test_revoke_sponsorship_ledger_key_data() {
412        let kp = keypair0();
413        let kp1 = keypair1();
414
415        let op = Operation::new_revoke_sponsorship()
416            .with_ledger_key(LedgerKey::Data(kp1.public_key(), "Test_Data".to_string()))
417            .build()
418            .unwrap();
419        let mut tx = Transaction::builder(kp.public_key(), 3556091187167235, MIN_BASE_FEE)
420            .add_operation(op)
421            .into_transaction()
422            .unwrap();
423        tx.sign(kp.as_ref(), &Network::new_test()).unwrap();
424        let envelope = tx.to_envelope();
425        let xdr = envelope.xdr_base64().unwrap();
426        let expected = "AAAAAgAAAADg3G3hclysZlFitS+s5zWyiiJD5B0STWy5LXCj6i5yxQAAAGQADKI/AAAAAwAAAAAAAAAAAAAAAQAAAAAAAAASAAAAAAAAAAMAAAAAJcrx2g/Hbs/ohF5CVFG7B5JJSJR+OqDKzDGK7dKHZH4AAAAJVGVzdF9EYXRhAAAAAAAAAAAAAAHqLnLFAAAAQIEt621z4bNoQ9RXuT+bUktPySCRYocLfde5SKO2/94r4K8GBZhVzKBez80hNxfljncOuG4ZkzQ+mWaCGBjnpgE=";
427        assert_eq!(expected, xdr);
428        let back = TransactionEnvelope::from_xdr_base64(&xdr).unwrap();
429        assert_eq!(envelope, back);
430    }
431
432    #[test]
433    fn test_revoke_sponsorship_ledger_key_balance_id() {
434        let kp = keypair0();
435
436        let balance_id = ClaimableBalanceId::new(vec![7; 32]).unwrap();
437
438        let op = Operation::new_revoke_sponsorship()
439            .with_ledger_key(LedgerKey::ClaimableBalance(balance_id))
440            .build()
441            .unwrap();
442        let mut tx = Transaction::builder(kp.public_key(), 3556091187167235, MIN_BASE_FEE)
443            .add_operation(op)
444            .into_transaction()
445            .unwrap();
446        tx.sign(kp.as_ref(), &Network::new_test()).unwrap();
447        let envelope = tx.to_envelope();
448        let xdr = envelope.xdr_base64().unwrap();
449        let expected = "AAAAAgAAAADg3G3hclysZlFitS+s5zWyiiJD5B0STWy5LXCj6i5yxQAAAGQADKI/AAAAAwAAAAAAAAAAAAAAAQAAAAAAAAASAAAAAAAAAAQAAAAABwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcAAAAAAAAAAeoucsUAAABAAofz60qpHGLrsNmcT9fgAnUOywCE5xDW8OMYpusgis1zODTg3fmsbFmUGB32DrGn+aeVtrLkVVjIY8vey3cVDQ==";
450        assert_eq!(expected, xdr);
451        let back = TransactionEnvelope::from_xdr_base64(&xdr).unwrap();
452        assert_eq!(envelope, back);
453    }
454
455    #[test]
456    fn test_revoke_sponsorship_ledger_key_account_with_source_account() {
457        let kp = keypair0();
458        let kp1 = keypair1();
459
460        let op = Operation::new_revoke_sponsorship()
461            .with_ledger_key(LedgerKey::Account(kp1.public_key()))
462            .with_source_account(kp1.public_key())
463            .build()
464            .unwrap();
465        let mut tx = Transaction::builder(kp.public_key(), 3556091187167235, MIN_BASE_FEE)
466            .add_operation(op)
467            .into_transaction()
468            .unwrap();
469        tx.sign(kp.as_ref(), &Network::new_test()).unwrap();
470        let envelope = tx.to_envelope();
471        let xdr = envelope.xdr_base64().unwrap();
472        let expected = "AAAAAgAAAADg3G3hclysZlFitS+s5zWyiiJD5B0STWy5LXCj6i5yxQAAAGQADKI/AAAAAwAAAAAAAAAAAAAAAQAAAAEAAAAAJcrx2g/Hbs/ohF5CVFG7B5JJSJR+OqDKzDGK7dKHZH4AAAASAAAAAAAAAAAAAAAAJcrx2g/Hbs/ohF5CVFG7B5JJSJR+OqDKzDGK7dKHZH4AAAAAAAAAAeoucsUAAABA0Fd2Pp3NfMLTFGXbb6oks4IiwWQLqzQ71DFgVjv98Cle113hcH2toNlNEF7iT1D+262C4ajIhdAReZBubwTHCg==";
473        assert_eq!(expected, xdr);
474        let back = TransactionEnvelope::from_xdr_base64(&xdr).unwrap();
475        assert_eq!(envelope, back);
476    }
477
478    #[test]
479    fn test_revoke_sponsorship_ledger_key_signer_key() {
480        let kp = keypair0();
481        let kp1 = keypair1();
482
483        let signer_key = SignerKey::new_from_public_key(kp1.public_key());
484
485        let op = Operation::new_revoke_sponsorship()
486            .with_signer(kp1.public_key(), signer_key)
487            .build()
488            .unwrap();
489        let mut tx = Transaction::builder(kp.public_key(), 3556091187167235, MIN_BASE_FEE)
490            .add_operation(op)
491            .into_transaction()
492            .unwrap();
493        tx.sign(kp.as_ref(), &Network::new_test()).unwrap();
494        let envelope = tx.to_envelope();
495        let xdr = envelope.xdr_base64().unwrap();
496        let expected = "AAAAAgAAAADg3G3hclysZlFitS+s5zWyiiJD5B0STWy5LXCj6i5yxQAAAGQADKI/AAAAAwAAAAAAAAAAAAAAAQAAAAAAAAASAAAAAQAAAAAlyvHaD8duz+iEXkJUUbsHkklIlH46oMrMMYrt0odkfgAAAAAlyvHaD8duz+iEXkJUUbsHkklIlH46oMrMMYrt0odkfgAAAAAAAAAB6i5yxQAAAECkJuiFk6qWll/g4XtiknA2GktvVLIsQuxSs2SC2NvzrzxF0WSxZjOaKdDqeZ/AfkzgajS6mCo7s9e7sg9DcF8P";
497        assert_eq!(expected, xdr);
498        let back = TransactionEnvelope::from_xdr_base64(&xdr).unwrap();
499        assert_eq!(envelope, back);
500    }
501
502    #[test]
503    fn test_revoke_sponsorship_ledger_key_signer_key_with_source_account() {
504        let kp = keypair0();
505        let kp1 = keypair1();
506
507        let signer_key = SignerKey::new_from_public_key(kp1.public_key());
508
509        let op = Operation::new_revoke_sponsorship()
510            .with_signer(kp1.public_key(), signer_key)
511            .with_source_account(kp1.public_key())
512            .build()
513            .unwrap();
514        let mut tx = Transaction::builder(kp.public_key(), 3556091187167235, MIN_BASE_FEE)
515            .add_operation(op)
516            .into_transaction()
517            .unwrap();
518        tx.sign(kp.as_ref(), &Network::new_test()).unwrap();
519        let envelope = tx.to_envelope();
520        let xdr = envelope.xdr_base64().unwrap();
521        let expected = "AAAAAgAAAADg3G3hclysZlFitS+s5zWyiiJD5B0STWy5LXCj6i5yxQAAAGQADKI/AAAAAwAAAAAAAAAAAAAAAQAAAAEAAAAAJcrx2g/Hbs/ohF5CVFG7B5JJSJR+OqDKzDGK7dKHZH4AAAASAAAAAQAAAAAlyvHaD8duz+iEXkJUUbsHkklIlH46oMrMMYrt0odkfgAAAAAlyvHaD8duz+iEXkJUUbsHkklIlH46oMrMMYrt0odkfgAAAAAAAAAB6i5yxQAAAECe7rfndyOX8KE0jYOH5hH8oTYFF06UOEeQWvtLdxP9s0a/V8kTDclsyPpfCiC4dcNV5CPVifcolty05Qap2TUN";
522        assert_eq!(expected, xdr);
523        let back = TransactionEnvelope::from_xdr_base64(&xdr).unwrap();
524        assert_eq!(envelope, back);
525    }
526}