stellar_base/operations/
manage_data.rs1use crate::account::DataValue;
2use crate::crypto::MuxedAccount;
3use crate::error::{Error, Result};
4use crate::operations::Operation;
5use crate::xdr;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct ManageDataOperation {
9 source_account: Option<MuxedAccount>,
10 data_name: String,
11 data_value: Option<DataValue>,
12}
13
14#[derive(Debug, Default)]
15pub struct ManageDataOperationBuilder {
16 source_account: Option<MuxedAccount>,
17 data_name: Option<String>,
18 data_value: Option<DataValue>,
19}
20
21impl ManageDataOperation {
22 pub fn source_account(&self) -> &Option<MuxedAccount> {
24 &self.source_account
25 }
26
27 pub fn source_account_mut(&mut self) -> &mut Option<MuxedAccount> {
29 &mut self.source_account
30 }
31
32 pub fn data_name(&self) -> &str {
34 &self.data_name
35 }
36
37 pub fn data_name_mut(&mut self) -> &mut str {
39 &mut self.data_name
40 }
41
42 pub fn data_value(&self) -> &Option<DataValue> {
44 &self.data_value
45 }
46
47 pub fn data_value_mut(&mut self) -> &mut Option<DataValue> {
49 &mut self.data_value
50 }
51
52 pub fn to_xdr_operation_body(&self) -> Result<xdr::OperationBody> {
54 let data_name = self
55 .data_name
56 .as_bytes()
57 .to_vec()
58 .try_into()
59 .map_err(|_| Error::XdrError)?;
60 let data_value = self.data_value.as_ref().map(|d| d.to_xdr()).transpose()?;
61 let inner = xdr::ManageDataOp {
62 data_name,
63 data_value,
64 };
65 Ok(xdr::OperationBody::ManageData(inner))
66 }
67
68 pub fn from_xdr_operation_body(
70 source_account: Option<MuxedAccount>,
71 x: &xdr::ManageDataOp,
72 ) -> Result<ManageDataOperation> {
73 let data_name = x.data_name.to_string();
74 let data_value = x.data_value.as_ref().map(DataValue::from_xdr).transpose()?;
75
76 Ok(ManageDataOperation {
77 source_account,
78 data_name,
79 data_value,
80 })
81 }
82}
83
84impl ManageDataOperationBuilder {
85 pub fn new() -> ManageDataOperationBuilder {
86 Default::default()
87 }
88
89 pub fn with_source_account<S>(mut self, source: S) -> ManageDataOperationBuilder
90 where
91 S: Into<MuxedAccount>,
92 {
93 self.source_account = Some(source.into());
94 self
95 }
96
97 pub fn with_data_name(mut self, name: String) -> ManageDataOperationBuilder {
98 self.data_name = Some(name);
99 self
100 }
101
102 pub fn with_data_value(mut self, value: Option<DataValue>) -> ManageDataOperationBuilder {
103 self.data_value = value;
104 self
105 }
106
107 pub fn build(self) -> Result<Operation> {
108 let data_name = self
109 .data_name
110 .ok_or_else(|| Error::InvalidOperation("missing manage data data name".to_string()))?;
111
112 Ok(Operation::ManageData(ManageDataOperation {
113 source_account: self.source_account,
114 data_name,
115 data_value: self.data_value,
116 }))
117 }
118}
119
120#[cfg(test)]
121mod tests {
122 use crate::account::DataValue;
123
124 use crate::network::Network;
125 use crate::operations::tests::*;
126 use crate::operations::Operation;
127 use crate::transaction::{Transaction, TransactionEnvelope, MIN_BASE_FEE};
128 use crate::xdr::{XDRDeserialize, XDRSerialize};
129
130 #[test]
131 fn test_manage_data() {
132 let kp = keypair0();
133 let value = DataValue::from_slice("value value".as_bytes()).unwrap();
134 let op = Operation::new_manage_data()
135 .with_data_name("TEST TEST".to_string())
136 .with_data_value(Some(value))
137 .build()
138 .unwrap();
139
140 let mut tx = Transaction::builder(kp.public_key(), 3556091187167235, MIN_BASE_FEE)
141 .add_operation(op)
142 .into_transaction()
143 .unwrap();
144 tx.sign(kp.as_ref(), &Network::new_test()).unwrap();
145 let envelope = tx.to_envelope();
146 let xdr = envelope.xdr_base64().unwrap();
147 let expected = "AAAAAgAAAADg3G3hclysZlFitS+s5zWyiiJD5B0STWy5LXCj6i5yxQAAAGQADKI/AAAAAwAAAAAAAAAAAAAAAQAAAAAAAAAKAAAACVRFU1QgVEVTVAAAAAAAAAEAAAALdmFsdWUgdmFsdWUAAAAAAAAAAAHqLnLFAAAAQLxeb1DkXDTXi/rOffnHpyxuJhl8vN/GDMKLtxFFTGn5b99FNHmWUyUoxb4KTE9bBguIe33SEQ/npj32f2vt/gY=";
148 assert_eq!(expected, xdr);
149 let back = TransactionEnvelope::from_xdr_base64(&xdr).unwrap();
150 assert_eq!(envelope, back);
151 }
152
153 #[test]
154 fn test_manage_data_with_source_account() {
155 let kp = keypair0();
156 let kp1 = keypair1();
157 let value = DataValue::from_slice("value value".as_bytes()).unwrap();
158 let op = Operation::new_manage_data()
159 .with_source_account(kp1.public_key())
160 .with_data_name("TEST TEST".to_string())
161 .with_data_value(Some(value))
162 .build()
163 .unwrap();
164
165 let mut tx = Transaction::builder(kp.public_key(), 3556091187167235, MIN_BASE_FEE)
166 .add_operation(op)
167 .into_transaction()
168 .unwrap();
169 tx.sign(kp.as_ref(), &Network::new_test()).unwrap();
170 let envelope = tx.to_envelope();
171 let xdr = envelope.xdr_base64().unwrap();
172 let expected = "AAAAAgAAAADg3G3hclysZlFitS+s5zWyiiJD5B0STWy5LXCj6i5yxQAAAGQADKI/AAAAAwAAAAAAAAAAAAAAAQAAAAEAAAAAJcrx2g/Hbs/ohF5CVFG7B5JJSJR+OqDKzDGK7dKHZH4AAAAKAAAACVRFU1QgVEVTVAAAAAAAAAEAAAALdmFsdWUgdmFsdWUAAAAAAAAAAAHqLnLFAAAAQBQKnwjKQ1RbYg0rk7G9VV1jHwM29YEp1EoOug960nTVWga6aFmPlQ0mDDudEsbSMq+9G8eYX5mcu9EHTjZUBQI=";
173 assert_eq!(expected, xdr);
174 let back = TransactionEnvelope::from_xdr_base64(&xdr).unwrap();
175 assert_eq!(envelope, back);
176 }
177}