casper_rust_wasm_sdk/sdk/contract/
install_deploy.rs

1#[cfg(target_arch = "wasm32")]
2use crate::deploy::deploy::PutDeployResult;
3use crate::types::deploy_params::{
4    deploy_str_params::{deploy_str_params_to_casper_client, DeployStrParams},
5    payment_str_params::{payment_str_params_to_casper_client, PaymentStrParams},
6    session_str_params::{session_str_params_to_casper_client, SessionStrParams},
7};
8use crate::{types::sdk_error::SdkError, SDK};
9use casper_client::{
10    cli::deploy::make_deploy, rpcs::results::PutDeployResult as _PutDeployResult, SuccessResponse,
11};
12#[cfg(target_arch = "wasm32")]
13use wasm_bindgen::prelude::*;
14
15/// A set of functions for installing smart contracts on the blockchain.
16#[cfg(target_arch = "wasm32")]
17#[wasm_bindgen]
18impl SDK {
19    /// Installs a smart contract with the specified parameters and returns the result.
20    ///
21    /// # Arguments
22    ///
23    /// * `deploy_params` - The deploy parameters.
24    /// * `session_params` - The session parameters.
25    /// * `payment_amount` - The payment amount as a string.
26    /// * `rpc_address` - An optional rpc address to send the request to.
27    ///
28    /// # Returns
29    ///
30    /// A `Result` containing either a `PutDeployResult` or a `JsError` in case of an error.
31    ///
32    /// # Errors
33    ///
34    /// Returns a `JsError` if there is an error during the installation.
35    #[wasm_bindgen(js_name = "install_deploy")]
36    #[deprecated(note = "prefer 'install' with transaction")]
37    #[allow(deprecated)]
38    pub async fn install_deploy_js_alias(
39        &self,
40        deploy_params: DeployStrParams,
41        session_params: SessionStrParams,
42        payment_amount: &str,
43        rpc_address: Option<String>,
44    ) -> Result<PutDeployResult, JsError> {
45        let result = self
46            .install_deploy(deploy_params, session_params, payment_amount, rpc_address)
47            .await;
48        match result {
49            Ok(data) => Ok(data.result.into()),
50            Err(err) => {
51                let err = &format!("Error occurred with {:?}", err);
52
53                Err(JsError::new(err))
54            }
55        }
56    }
57}
58
59/// A set of functions for installing smart contracts on the blockchain.
60/// Alias of sdk.deploy
61impl SDK {
62    /// Installs a smart contract with the specified parameters and returns the result.
63    ///
64    /// # Arguments
65    ///
66    /// * `deploy_params` - The deploy parameters.
67    /// * `session_params` - The session parameters.
68    /// * `payment_amount` - The payment amount as a string.
69    /// * `rpc_address` - An optional rpc address to send the request to.
70    ///
71    /// # Returns
72    ///
73    /// A `Result` containing either a `_PutDeployResult` or a `SdkError` in case of an error.
74    ///
75    /// # Errors
76    ///
77    /// Returns a `SdkError` if there is an error during the installation.
78    #[deprecated(note = "prefer 'install' with transaction")]
79    #[allow(deprecated)]
80    pub async fn install_deploy(
81        &self,
82        deploy_params: DeployStrParams,
83        session_params: SessionStrParams,
84        payment_amount: &str,
85        rpc_address: Option<String>,
86    ) -> Result<SuccessResponse<_PutDeployResult>, SdkError> {
87        //log("install!");
88        let payment_params = PaymentStrParams::default();
89        payment_params.set_payment_amount(payment_amount);
90
91        let deploy = make_deploy(
92            "",
93            deploy_str_params_to_casper_client(&deploy_params),
94            session_str_params_to_casper_client(&session_params),
95            payment_str_params_to_casper_client(&payment_params),
96            false,
97        );
98        if let Err(err) = deploy {
99            return Err(SdkError::from(err));
100        }
101        self.put_deploy(deploy.unwrap().into(), None, rpc_address)
102            .await
103            .map_err(SdkError::from)
104    }
105}
106
107#[cfg(test)]
108#[allow(deprecated)]
109mod tests {
110    use super::*;
111    use crate::helpers::public_key_from_secret_key;
112    use sdk_tests::{
113        config::{ARGS_SIMPLE, HELLO_CONTRACT, PAYMENT_AMOUNT, TTL, WASM_PATH},
114        tests::helpers::{get_network_constants, get_user_secret_key, read_wasm_file},
115    };
116    use tokio;
117
118    #[tokio::test]
119    async fn test_install_deploy_with_none_values() {
120        // Arrange
121        let sdk = SDK::new(None, None, None);
122        let deploy_params = DeployStrParams::new("", "", None, None, None, None);
123        let session_params = SessionStrParams::default();
124
125        let error_message =
126            "Invalid argument 'is_session_transfer': requires --session-arg to be present";
127
128        // Act
129        let result = sdk
130            .install_deploy(deploy_params, session_params, "", None)
131            .await;
132
133        // Assert
134        assert!(result.is_err());
135        let err_string = result.err().unwrap().to_string();
136        assert!(err_string.contains(error_message));
137    }
138
139    #[tokio::test]
140    async fn test_install_deploy_with_valid_input() {
141        // Arrange
142        let sdk = SDK::new(None, None, None);
143        let (rpc_address, _, _, _, chain_name) = get_network_constants();
144        let secret_key = get_user_secret_key(None).unwrap();
145        let account = public_key_from_secret_key(&secret_key).unwrap();
146
147        let deploy_params =
148            DeployStrParams::new(&chain_name, &account, Some(secret_key), None, None, None);
149        let mut session_params = SessionStrParams::default();
150
151        let module_bytes = match read_wasm_file(&format!("{WASM_PATH}{HELLO_CONTRACT}")) {
152            Ok(module_bytes) => module_bytes,
153            Err(err) => {
154                eprintln!("Error reading file: {:?}", err);
155                return;
156            }
157        };
158        session_params.set_session_bytes(module_bytes.into());
159        let args_simple: Vec<String> = ARGS_SIMPLE.iter().map(|s| s.to_string()).collect();
160        session_params.set_session_args(args_simple);
161
162        // Act
163        let result = sdk
164            .install_deploy(
165                deploy_params,
166                session_params,
167                PAYMENT_AMOUNT,
168                Some(rpc_address),
169            )
170            .await;
171
172        // Assert
173
174        assert!(result.is_ok());
175        let deploy_hash = result.unwrap().result.deploy_hash;
176        assert!(!deploy_hash.to_string().is_empty());
177    }
178
179    #[tokio::test]
180    async fn test_install_deploy_with_invalid_input() {
181        // Arrange
182        let sdk = SDK::new(None, None, None);
183        let (rpc_address, _, _, _, chain_name) = get_network_constants();
184        let secret_key = get_user_secret_key(None).unwrap();
185        let account = public_key_from_secret_key(&secret_key).unwrap();
186
187        let error_message =
188            "Missing a required arg - exactly one of the following must be provided";
189
190        let deploy_params = DeployStrParams::new(
191            &chain_name,
192            &account,
193            Some(secret_key.clone()),
194            None,
195            Some(TTL.to_string()),
196            None,
197        );
198        let mut session_params = SessionStrParams::default();
199
200        let module_bytes = match read_wasm_file(&format!("{WASM_PATH}{HELLO_CONTRACT}")) {
201            Ok(module_bytes) => module_bytes,
202            Err(err) => {
203                eprintln!("Error reading file: {:?}", err);
204                return;
205            }
206        };
207        session_params.set_session_bytes(module_bytes.into());
208        let args_simple: Vec<String> = ARGS_SIMPLE.iter().map(|s| s.to_string()).collect();
209        session_params.set_session_args(args_simple);
210
211        // Act
212        let result = sdk
213            .install_deploy(
214                deploy_params,
215                session_params,
216                "", // This is not valid payment amount
217                Some(rpc_address),
218            )
219            .await;
220
221        // Assert
222        assert!(result.is_err());
223        let err_string = result.err().unwrap().to_string();
224        assert!(err_string.contains(error_message));
225    }
226
227    #[tokio::test]
228    async fn test_install_deploy_without_secret_key() {
229        // Arrange
230        let sdk = SDK::new(None, None, None);
231        let (rpc_address, _, _, _, chain_name) = get_network_constants();
232        let secret_key = get_user_secret_key(None).unwrap();
233        let account = public_key_from_secret_key(&secret_key).unwrap();
234
235        let error_message = "the deploy was invalid: invalid associated keys";
236
237        let deploy_params = DeployStrParams::new(
238            &chain_name,
239            &account,
240            None,
241            None,
242            Some(TTL.to_string()),
243            None,
244        );
245        let mut session_params = SessionStrParams::default();
246
247        let module_bytes = match read_wasm_file(&format!("{WASM_PATH}{HELLO_CONTRACT}")) {
248            Ok(module_bytes) => module_bytes,
249            Err(err) => {
250                eprintln!("Error reading file: {:?}", err);
251                return;
252            }
253        };
254        session_params.set_session_bytes(module_bytes.into());
255        let args_simple: Vec<String> = ARGS_SIMPLE.iter().map(|s| s.to_string()).collect();
256        session_params.set_session_args(args_simple);
257
258        // Act
259        let result = sdk
260            .install_deploy(
261                deploy_params,
262                session_params,
263                PAYMENT_AMOUNT,
264                Some(rpc_address),
265            )
266            .await;
267
268        // Assert
269        assert!(result.is_err());
270        let err_string = result.err().unwrap().to_string();
271        assert!(err_string.contains(error_message));
272    }
273
274    #[tokio::test]
275    async fn test_install_deploy_with_error() {
276        // Arrange
277        let sdk = SDK::new(Some("http://localhost".to_string()), None, None);
278        let (_, _, _, _, chain_name) = get_network_constants();
279        let secret_key = get_user_secret_key(None).unwrap();
280        let account = public_key_from_secret_key(&secret_key).unwrap();
281
282        let deploy_params = DeployStrParams::new(
283            &chain_name,
284            &account,
285            Some(secret_key.clone()),
286            None,
287            None,
288            None,
289        );
290
291        let error_message = "error sending request for url (http://localhost/rpc)";
292
293        let mut session_params = SessionStrParams::default();
294
295        let module_bytes = match read_wasm_file(&format!("{WASM_PATH}{HELLO_CONTRACT}")) {
296            Ok(module_bytes) => module_bytes,
297            Err(err) => {
298                eprintln!("Error reading file: {:?}", err);
299                return;
300            }
301        };
302        session_params.set_session_bytes(module_bytes.into());
303        let args_simple: Vec<String> = ARGS_SIMPLE.iter().map(|s| s.to_string()).collect();
304        session_params.set_session_args(args_simple);
305
306        // Act
307        let result = sdk
308            .install_deploy(deploy_params, session_params, PAYMENT_AMOUNT, None)
309            .await;
310
311        // Assert
312        assert!(result.is_err());
313        let err_string = result.err().unwrap().to_string();
314        assert!(err_string.contains(error_message));
315    }
316}