Skip to main content

casper_rust_wasm_sdk/sdk/deploy/
speculative_transfer.rs

1#[cfg(all(feature = "js", target_arch = "wasm32"))]
2use crate::rpcs::speculative_exec_deploy::SpeculativeExecResult;
3use crate::{
4    types::{
5        deploy_params::{
6            deploy_str_params::{deploy_str_params_to_casper_client, DeployStrParams},
7            payment_str_params::{payment_str_params_to_casper_client, PaymentStrParams},
8        },
9        sdk_error::SdkError,
10        verbosity::Verbosity,
11    },
12    SDK,
13};
14use casper_client::{
15    cli::deploy::make_transfer, rpcs::results::SpeculativeExecResult as _SpeculativeExecResult,
16    SuccessResponse,
17};
18use rand::RngExt;
19#[cfg(all(feature = "js", target_arch = "wasm32"))]
20use wasm_bindgen::prelude::*;
21
22#[cfg(all(feature = "js", target_arch = "wasm32"))]
23#[cfg_attr(feature = "js", wasm_bindgen)]
24impl SDK {
25    /// JS function for speculative transfer.
26    ///
27    /// # Arguments
28    ///
29    /// * `amount` - The amount to transfer.
30    /// * `target_account` - The target account.
31    /// * `transfer_id` - An optional transfer ID (defaults to a random number).
32    /// * `deploy_params` - The deployment parameters.
33    /// * `payment_params` - The payment parameters.
34    /// * `verbosity` - The verbosity level for logging (optional).
35    /// * `rpc_address` - The address of the node to connect to (optional).
36    ///
37    /// # Returns
38    ///
39    /// A `Result` containing the result of the speculative transfer or a `JsError` in case of an error.
40    #[cfg_attr(feature = "js", wasm_bindgen(js_name = "speculative_transfer"))]
41    #[allow(clippy::too_many_arguments, deprecated)]
42    #[deprecated(note = "prefer speculative_transfer_transaction")]
43    #[cfg(feature = "js")]
44    pub async fn speculative_transfer_js_alias(
45        &self,
46        amount: &str,
47        target_account: &str,
48        transfer_id: Option<String>,
49        deploy_params: DeployStrParams,
50        payment_params: PaymentStrParams,
51        verbosity: Option<Verbosity>,
52        rpc_address: Option<String>,
53    ) -> Result<SpeculativeExecResult, JsError> {
54        let result = self
55            .speculative_transfer(
56                amount,
57                target_account,
58                transfer_id,
59                deploy_params,
60                payment_params,
61                verbosity,
62                rpc_address,
63            )
64            .await;
65        match result {
66            Ok(data) => Ok(data.result.into()),
67            Err(err) => {
68                let err = &format!("Error occurred with {err:?}");
69                Err(JsError::new(err))
70            }
71        }
72    }
73}
74
75impl SDK {
76    /// Perform a speculative transfer.
77    ///
78    /// # Arguments
79    ///
80    /// * `amount` - The amount to transfer.
81    /// * `target_account` - The target account.
82    /// * `transfer_id` - An optional transfer ID (defaults to a random number).
83    /// * `deploy_params` - The deployment parameters.
84    /// * `payment_params` - The payment parameters.
85    /// * `verbosity` - The verbosity level for logging (optional).
86    /// * `rpc_address` - The address of the node to connect to (optional).
87    ///
88    /// # Returns
89    ///
90    /// A `Result` containing the result a `SuccessResponse<_SpeculativeExecResult>` or a `SdkError` in case of an error.
91    #[allow(clippy::too_many_arguments, deprecated)]
92    #[deprecated(note = "prefer speculative_transfer_transaction")]
93    pub async fn speculative_transfer(
94        &self,
95        amount: &str,
96        target_account: &str,
97        transfer_id: Option<String>,
98        deploy_params: DeployStrParams,
99        payment_params: PaymentStrParams,
100        verbosity: Option<Verbosity>,
101        rpc_address: Option<String>,
102    ) -> Result<SuccessResponse<_SpeculativeExecResult>, SdkError> {
103        // log("speculative_transfer!");
104        let transfer_id = if let Some(transfer_id) = transfer_id {
105            transfer_id
106        } else {
107            rand::rng().random::<u64>().to_string()
108        };
109        let deploy = make_transfer(
110            "",
111            amount,
112            target_account,
113            &transfer_id,
114            deploy_str_params_to_casper_client(&deploy_params),
115            payment_str_params_to_casper_client(&payment_params),
116            false,
117        );
118
119        if let Err(err) = deploy {
120            return Err(SdkError::from(err));
121        }
122
123        self.speculative_exec_deploy(deploy.unwrap().into(), verbosity, rpc_address)
124            .await
125    }
126}
127
128#[cfg(test)]
129#[allow(deprecated)]
130mod tests {
131    use super::*;
132    use crate::helpers::public_key_from_secret_key;
133    use sdk_tests::{
134        config::{PAYMENT_TRANSFER_AMOUNT, TRANSFER_AMOUNT},
135        tests::helpers::{get_network_constants, get_user_secret_key},
136    };
137
138    #[tokio::test]
139    #[ignore]
140    async fn _test_speculative_transfer_with_valid_params() {
141        // Arrange
142        let sdk = SDK::new(None, None, None);
143        let verbosity = Some(Verbosity::High);
144        let (_, _, default_speculative_address, _, chain_name) = get_network_constants();
145
146        let secret_key = get_user_secret_key(None).unwrap();
147        let account = public_key_from_secret_key(&secret_key).unwrap();
148
149        let deploy_params =
150            DeployStrParams::new(&chain_name, &account, Some(secret_key), None, None, None);
151        let payment_params = PaymentStrParams::default();
152        payment_params.set_payment_amount(PAYMENT_TRANSFER_AMOUNT);
153
154        // Act
155        let result = sdk
156            .speculative_transfer(
157                TRANSFER_AMOUNT,
158                &account,
159                None,
160                deploy_params,
161                payment_params,
162                verbosity,
163                Some(default_speculative_address),
164            )
165            .await;
166
167        // Assert
168        assert!(result.is_ok());
169    }
170
171    #[tokio::test]
172    async fn test_speculative_transfer_with_valid_params_without_secret_key() {
173        // Arrange
174        let sdk = SDK::new(None, None, None);
175        let verbosity = Some(Verbosity::High);
176        let (_, _, default_speculative_address, _, chain_name) = get_network_constants();
177
178        let secret_key = get_user_secret_key(None).unwrap();
179        let account = public_key_from_secret_key(&secret_key).unwrap();
180
181        let deploy_params = DeployStrParams::new(&chain_name, &account, None, None, None, None);
182        let payment_params = PaymentStrParams::default();
183        payment_params.set_payment_amount(PAYMENT_TRANSFER_AMOUNT);
184
185        // Act
186        let result = sdk
187            .speculative_transfer(
188                TRANSFER_AMOUNT,
189                &account,
190                None,
191                deploy_params,
192                payment_params,
193                verbosity,
194                Some(default_speculative_address),
195            )
196            .await;
197
198        // Assert
199        assert!(result.is_err());
200    }
201
202    #[tokio::test]
203    async fn test_speculative_transfer_with_invalid_params() {
204        // Arrange
205        let sdk = SDK::new(None, None, None);
206        let verbosity = Some(Verbosity::High);
207        let (_, _, default_speculative_address, _, chain_name) = get_network_constants();
208
209        let error_message = "Missing a required arg - exactly one of the following must be provided: [\"payment_amount\", \"payment_hash\", \"payment_name\", \"payment_package_hash\", \"payment_package_name\", \"payment_path\", \"has_payment_bytes\"]";
210        let secret_key = get_user_secret_key(None).unwrap();
211        let account = public_key_from_secret_key(&secret_key).unwrap();
212
213        let deploy_params =
214            DeployStrParams::new(&chain_name, &account, Some(secret_key), None, None, None);
215        let payment_params = PaymentStrParams::default();
216        payment_params.set_payment_amount(""); // This is not valid payment amount
217
218        // Act
219        let result = sdk
220            .speculative_transfer(
221                TRANSFER_AMOUNT,
222                &account,
223                None,
224                deploy_params,
225                payment_params,
226                verbosity,
227                Some(default_speculative_address),
228            )
229            .await;
230
231        // Assert
232        assert!(result.is_err());
233
234        let err_string = result.err().unwrap().to_string();
235        assert!(err_string.contains(error_message));
236    }
237}