terra_rust_api/messages/
wasm.rs

1use crate::core_types::{Coin, MsgInternal};
2use crate::terra_u64_format;
3use std::path::Path;
4
5use crate::errors::TerraRustAPIError;
6use crate::messages::Message;
7use serde::Serialize;
8
9#[derive(Serialize, Debug)]
10/// Message: Exec Contract
11pub struct MsgExecuteContract {
12    pub coins: Vec<Coin>,
13    pub contract: String,
14    pub execute_msg: serde_json::Value,
15    pub sender: String,
16}
17
18impl MsgInternal for MsgExecuteContract {}
19impl MsgExecuteContract {
20    /// use provided base64 exec message
21    pub fn create_from_value(
22        sender: &str,
23        contract: &str,
24        execute_msg: &serde_json::Value,
25        coins: &[Coin],
26    ) -> Result<Message, TerraRustAPIError> {
27        let internal = MsgExecuteContract {
28            sender: sender.into(),
29            contract: contract.into(),
30            execute_msg: execute_msg.clone(),
31            coins: coins.to_vec(),
32        };
33        Ok(Message {
34            s_type: "wasm/MsgExecuteContract".into(),
35            value: serde_json::to_value(internal)?,
36        })
37    }
38    /// use provided base64 exec message
39    pub fn create_from_json(
40        sender: &str,
41        contract: &str,
42        execute_msg_json: &str,
43        coins: &[Coin],
44    ) -> Result<Message, TerraRustAPIError> {
45        let exec_b64: serde_json::Value = serde_json::from_str(execute_msg_json)?;
46        MsgExecuteContract::create_from_value(sender, contract, &exec_b64, coins)
47    }
48}
49
50#[derive(Serialize, Debug)]
51/// Message: Exec Contract
52pub struct MsgStoreCode {
53    pub sender: String,
54    pub wasm_byte_code: String,
55}
56
57impl MsgInternal for MsgStoreCode {}
58impl MsgStoreCode {
59    /// use provided base64 exec message
60    pub fn create_from_b64(
61        sender: &str,
62        wasm_byte_code: &str,
63    ) -> Result<Message, TerraRustAPIError> {
64        let internal = MsgStoreCode {
65            sender: sender.into(),
66            wasm_byte_code: wasm_byte_code.into(),
67        };
68        Ok(Message {
69            s_type: "wasm/MsgStoreCode".into(),
70            value: serde_json::to_value(internal)?,
71        })
72    }
73    /// use provided base64 exec message
74    pub fn create_from_file(sender: &str, file_name: &Path) -> Result<Message, TerraRustAPIError> {
75        let file_contents = std::fs::read(file_name)?;
76        let exec_b64 = base64::encode(file_contents);
77        MsgStoreCode::create_from_b64(sender, &exec_b64)
78    }
79}
80
81#[derive(Serialize, Debug)]
82/// Message: Exec Contract
83pub struct MsgInstantiateContract {
84    pub admin: Option<String>,
85    #[serde(with = "terra_u64_format")]
86    pub code_id: u64,
87    pub sender: String,
88    pub init_coins: Vec<Coin>,
89    pub init_msg: serde_json::Value,
90}
91
92impl MsgInternal for MsgInstantiateContract {}
93impl MsgInstantiateContract {
94    /*
95    /// use provided base64 exec message
96    pub fn create_from_b64(
97        sender: &str,
98        admin: Option<String>,
99        code_id: usize,
100        init_msg: &str,
101        init_coins: Vec<Coin>,
102    ) -> Message {
103        let internal = MsgInstantiateContract {
104            admin: admin.map(|f| f.into()),
105            code_id: code_id.to_string(),
106            sender: sender.into(),
107            init_coins,
108            init_msg: init_msg.into(),
109        };
110        Message {
111            s_type: "wasm/MsgInstantiateContract".into(),
112            value: Box::new(internal),
113        }
114    }
115
116     */
117    /// create from JSON
118    pub fn create_from_json(
119        sender: &str,
120        admin: Option<String>,
121        code_id: u64,
122        init_msg: &str,
123        init_coins: Vec<Coin>,
124    ) -> Result<Message, TerraRustAPIError> {
125        // panic!("This message does not function");
126
127        let contents: serde_json::Value = serde_json::from_str(init_msg)?;
128        //let exec_b64 = base64::encode(contents.to_string());
129
130        let internal = MsgInstantiateContract {
131            admin, //: admin.unwrap_or_else(|| "".into()),
132            code_id,
133            sender: sender.into(),
134            init_coins,
135            init_msg: contents,
136        };
137        Ok(Message {
138            s_type: "wasm/MsgInstantiateContract".into(),
139            value: serde_json::to_value(internal)?,
140        })
141    }
142    /// use provided base64 exec message
143    /// switches ##SENDER##, ##ADMIN##, ##CODE_ID## with respective values
144    pub fn create_from_file(
145        sender: &str,
146        admin: Option<String>,
147        code_id: u64,
148        init_file: &Path,
149        init_coins: Vec<Coin>,
150    ) -> Result<Message, TerraRustAPIError> {
151        let contents = std::fs::read_to_string(init_file)?;
152        let new_contents = Self::replace_parameters(sender, admin.clone(), code_id, &contents);
153        Self::create_from_json(sender, admin, code_id, &new_contents, init_coins)
154    }
155    /// replace parts of the string with current values
156    pub fn replace_parameters(
157        sender: &str,
158        admin: Option<String>,
159        code_id: u64,
160        instantiate_str: &str,
161    ) -> String {
162        let part_1 = instantiate_str
163            .replace("##SENDER##", sender)
164            .replace("##CODE_ID##", &format!("{}", code_id));
165        match admin {
166            Some(admin_str) => part_1.replace("##ADMIN##", &admin_str),
167            None => part_1.replace("##ADMIN##", ""),
168        }
169    }
170}
171
172#[derive(Serialize, Debug)]
173/// Message: Exec Contract
174pub struct MsgMigrateContract {
175    pub admin: String,
176    pub contract: String,
177    #[serde(with = "terra_u64_format")]
178    pub new_code_id: u64,
179    pub migrate_msg: serde_json::Value,
180}
181
182impl MsgInternal for MsgMigrateContract {}
183impl MsgMigrateContract {
184    /// create from JSON
185    pub fn create_from_json(
186        admin: &str,
187        contract: &str,
188        new_code_id: u64,
189        migrate_msg: &str,
190    ) -> Result<Message, TerraRustAPIError> {
191        let contents: serde_json::Value = serde_json::from_str(migrate_msg)?;
192
193        let internal = MsgMigrateContract {
194            admin: String::from(admin),
195            contract: String::from(contract),
196            new_code_id,
197            migrate_msg: contents,
198        };
199        Ok(Message {
200            s_type: "wasm/MsgMigrateContract".into(),
201            value: serde_json::to_value(internal)?,
202        })
203    }
204    /// use provided base64 exec message
205    /// switches ##SENDER##, ##ADMIN##, ##CODE_ID## with respective values
206    pub fn create_from_file(
207        admin: &str,
208        contract: &str,
209        new_code_id: u64,
210        migrate_file: &Path,
211    ) -> Result<Message, TerraRustAPIError> {
212        let contents = std::fs::read_to_string(migrate_file)?;
213        let new_contents = Self::replace_parameters(admin, contract, new_code_id, &contents);
214
215        Self::create_from_json(admin, contract, new_code_id, &new_contents)
216    }
217    /// switches ##SENDER##, ##ADMIN##, ##CODE_ID## with respective values
218    pub fn replace_parameters(
219        admin: &str,
220        contract: &str,
221        new_code_id: u64,
222        migrate_str: &str,
223    ) -> String {
224        migrate_str
225            .replace("##ADMIN##", admin)
226            .replace("##CONTRACT##", contract)
227            .replace("##NEW_CODE_ID##", &format!("{}", new_code_id))
228    }
229}
230
231#[cfg(test)]
232mod tst {
233    use super::*;
234    /*
235    #[test]
236    pub fn test_b64() -> anyhow::Result<()> {
237        let vote_1 = MsgExecuteContract::create_from_b64(
238            "terra1vr0e7kylhu9am44v0s3gwkccmz7k3naxysrwew",
239            "terra1f32xyep306hhcxxxf7mlyh0ucggc00rm2s9da5",
240            "eyJjYXN0X3ZvdGUiOnsicG9sbF9pZCI6NDQsInZvdGUiOiJ5ZXMiLCJhbW91bnQiOiIxMDAwMDAwMCJ9fQ==",
241            &vec![],
242        );
243        let vote_2 = MsgExecuteContract::create_from_json(
244            "terra1vr0e7kylhu9am44v0s3gwkccmz7k3naxysrwew",
245            "terra1f32xyep306hhcxxxf7mlyh0ucggc00rm2s9da5",
246            r#"{"cast_vote":{"poll_id":44,"vote":"yes","amount":"10000000"}}"#,
247            &vec![],
248        );
249
250        let js_1 = serde_json::to_string(&vote_1)?;
251        let js_2 = serde_json::to_string(&vote_2)?;
252
253        assert_eq!(js_1, js_2);
254        let js_real = r#"{"type":"wasm/MsgExecuteContract","value":{"coins":[],"contract":"terra1f32xyep306hhcxxxf7mlyh0ucggc00rm2s9da5","execute_msg":"eyJjYXN0X3ZvdGUiOnsicG9sbF9pZCI6NDQsInZvdGUiOiJ5ZXMiLCJhbW91bnQiOiIxMDAwMDAwMCJ9fQ==","sender":"terra1vr0e7kylhu9am44v0s3gwkccmz7k3naxysrwew"}}"#;
255        assert_eq!(js_1, js_real);
256        Ok(())
257    }
258
259     */
260    #[test]
261    pub fn test_file_conversion() -> anyhow::Result<()> {
262        let token_file = Path::new("./resources/terraswap_pair.wasm");
263        let output = Path::new("./resources/terraswap_pair.output");
264        let out_json = std::fs::read_to_string(output)?;
265        let msg = MsgStoreCode::create_from_file(
266            "terra1vr0e7kylhu9am44v0s3gwkccmz7k3naxysrwew",
267            token_file,
268        )?;
269
270        let js = serde_json::to_string(&msg)?;
271        log::debug!("Test file conversion: {} - {}", out_json.len(), js.len());
272        assert_eq!(out_json.trim(), js);
273        Ok(())
274    }
275}