casper_rust_wasm_sdk/sdk/transaction/
transfer_transaction.rs

1#[cfg(target_arch = "wasm32")]
2use crate::transaction::transaction::PutTransactionResult;
3use crate::{
4    make_transfer_transaction,
5    types::{
6        sdk_error::SdkError, transaction_params::transaction_str_params::TransactionStrParams,
7        uref::URef, verbosity::Verbosity,
8    },
9    SDK,
10};
11use casper_client::{
12    rpcs::results::PutTransactionResult as _PutTransactionResult, SuccessResponse,
13};
14#[cfg(target_arch = "wasm32")]
15use wasm_bindgen::prelude::*;
16
17#[cfg(target_arch = "wasm32")]
18#[wasm_bindgen]
19impl SDK {
20    /// JS function for transaction transferring funds.
21    ///
22    /// # Arguments
23    ///
24    /// * `maybe_source` - Optional transfer source uref.
25    /// * `target_account` - The target account.
26    /// * `amount` - The amount to transfer.
27    /// * `transaction_params` - The transaction parameters.
28    /// * `maybe_id` - An optional transfer ID (defaults to a random number).
29    /// * `verbosity` - The verbosity level for logging (optional).
30    /// * `rpc_address` - The address of the node to connect to (optional).
31    ///
32    /// # Returns
33    ///
34    /// A `Result` containing the result of the transfer or a `JsError` in case of an error.
35    #[wasm_bindgen(js_name = "transfer_transaction")]
36    #[allow(clippy::too_many_arguments)]
37    pub async fn transfer_transactionjs_alias(
38        &self,
39        maybe_source: Option<URef>,
40        target_account: &str,
41        amount: &str,
42        transaction_params: TransactionStrParams,
43        maybe_id: Option<String>,
44        verbosity: Option<Verbosity>,
45        rpc_address: Option<String>,
46    ) -> Result<PutTransactionResult, JsError> {
47        let result = self
48            .transfer_transaction(
49                maybe_source,
50                target_account,
51                amount,
52                transaction_params,
53                maybe_id,
54                verbosity,
55                rpc_address,
56            )
57            .await;
58        match result {
59            Ok(data) => Ok(data.result.into()),
60            Err(err) => {
61                let err = &format!("Error occurred with {err:?}");
62                Err(JsError::new(err))
63            }
64        }
65    }
66}
67
68impl SDK {
69    /// Perform a transfer transaction of funds.
70    ///
71    /// # Arguments
72    ///
73    /// * `maybe_source` - Optional transfer source uref.
74    /// * `target_account` - The target account.
75    /// * `amount` - The amount to transfer.
76    /// * `transaction_params` - The transaction parameters.
77    /// * `maybe_id` - An optional transfer ID (defaults to a random number).
78    /// * `verbosity` - The verbosity level for logging (optional).
79    /// * `rpc_address` - The address of the node to connect to (optional).
80    ///
81    /// # Returns
82    ///
83    /// A `Result` containing the result a `SuccessResponse<_PutTransactionResult>` of the transfer or a `SdkError` in case of an error.
84    #[allow(clippy::too_many_arguments)]
85    pub async fn transfer_transaction(
86        &self,
87        maybe_source: Option<URef>,
88        target_account: &str,
89        amount: &str,
90        transaction_params: TransactionStrParams,
91        maybe_id: Option<String>,
92        verbosity: Option<Verbosity>,
93        rpc_address: Option<String>,
94    ) -> Result<SuccessResponse<_PutTransactionResult>, SdkError> {
95        //log("transfer!");
96        let transaction = make_transfer_transaction(
97            maybe_source,
98            target_account,
99            amount,
100            transaction_params,
101            maybe_id,
102        )
103        .map_err(|e| *e)?;
104
105        self.put_transaction(transaction, verbosity, rpc_address)
106            .await
107            .map_err(SdkError::from)
108    }
109}
110
111#[cfg(test)]
112mod tests {
113
114    use super::*;
115    use crate::helpers::public_key_from_secret_key;
116    use sdk_tests::{
117        config::TRANSFER_AMOUNT,
118        tests::helpers::{get_network_constants, get_user_secret_key},
119    };
120
121    #[tokio::test]
122    async fn test_transfer_with_valid_transfer_params() {
123        // Arrange
124        let sdk = SDK::new(None, None, None);
125        let verbosity = Some(Verbosity::High);
126        let (rpc_address, _, _, _, chain_name) = get_network_constants();
127
128        let secret_key = get_user_secret_key(None).unwrap();
129        let initiator_addr = public_key_from_secret_key(&secret_key).unwrap();
130
131        let transaction_params = TransactionStrParams::default();
132        transaction_params.set_secret_key(&secret_key);
133        transaction_params.set_chain_name(&chain_name);
134        transaction_params.set_payment_amount(TRANSFER_AMOUNT);
135
136        // Act
137        let result = sdk
138            .transfer_transaction(
139                None,
140                &initiator_addr,
141                TRANSFER_AMOUNT,
142                transaction_params,
143                None,
144                verbosity,
145                Some(rpc_address),
146            )
147            .await;
148
149        // Assert
150        assert!(result.is_ok());
151    }
152
153    #[tokio::test]
154    async fn test_transfer_with_valid_transfer_params_without_secret_key() {
155        // Arrange
156        let sdk = SDK::new(None, None, None);
157        let verbosity = Some(Verbosity::High);
158        let (rpc_address, _, _, _, chain_name) = get_network_constants();
159
160        let error_message = "the transaction was invalid: invalid associated keys";
161
162        let secret_key = get_user_secret_key(None).unwrap();
163        let initiator_addr = public_key_from_secret_key(&secret_key).unwrap();
164
165        let transaction_params = TransactionStrParams::default();
166        transaction_params.set_chain_name(&chain_name);
167        transaction_params.set_initiator_addr(&initiator_addr);
168        transaction_params.set_payment_amount(TRANSFER_AMOUNT);
169
170        // Act
171        let result = sdk
172            .transfer_transaction(
173                None,
174                &initiator_addr,
175                TRANSFER_AMOUNT,
176                transaction_params,
177                None,
178                verbosity,
179                Some(rpc_address),
180            )
181            .await;
182
183        // Assert
184        assert!(result.is_err());
185        let err_string = result.err().unwrap().to_string();
186        assert!(err_string.contains(error_message));
187    }
188
189    #[tokio::test]
190    async fn test_transfer_with_invalid_transfer_params() {
191        // Arrange
192        let sdk = SDK::new(None, None, None);
193        let verbosity = Some(Verbosity::High);
194        let (rpc_address, _, _, _, _) = get_network_constants();
195
196        let error_message = "The transaction sent to the network had an invalid chain name";
197        let secret_key = get_user_secret_key(None).unwrap();
198        let initiator_addr = public_key_from_secret_key(&secret_key).unwrap();
199
200        let transaction_params = TransactionStrParams::default();
201        transaction_params.set_secret_key(&secret_key);
202        transaction_params.set_payment_amount(TRANSFER_AMOUNT);
203        transaction_params.set_chain_name("");
204
205        // Act
206        let result = sdk
207            .transfer_transaction(
208                None,
209                &initiator_addr,
210                TRANSFER_AMOUNT,
211                transaction_params,
212                None,
213                verbosity,
214                Some(rpc_address),
215            )
216            .await;
217        // Assert
218        assert!(result.is_err());
219
220        let err_string = result.err().unwrap().to_string();
221        assert!(err_string.contains(error_message));
222    }
223}