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
104        self.put_transaction(transaction, verbosity, rpc_address)
105            .await
106            .map_err(SdkError::from)
107    }
108}
109
110#[cfg(test)]
111mod tests {
112
113    use super::*;
114    use crate::helpers::public_key_from_secret_key;
115    use sdk_tests::{
116        config::TRANSFER_AMOUNT,
117        tests::helpers::{get_network_constants, get_user_secret_key},
118    };
119
120    #[tokio::test]
121    async fn test_transfer_with_valid_transfer_params() {
122        // Arrange
123        let sdk = SDK::new(None, None, None);
124        let verbosity = Some(Verbosity::High);
125        let (rpc_address, _, _, _, chain_name) = get_network_constants();
126
127        let secret_key = get_user_secret_key(None).unwrap();
128        let initiator_addr = public_key_from_secret_key(&secret_key).unwrap();
129
130        let transaction_params = TransactionStrParams::default();
131        transaction_params.set_secret_key(&secret_key);
132        transaction_params.set_chain_name(&chain_name);
133        transaction_params.set_payment_amount(TRANSFER_AMOUNT);
134
135        // Act
136        let result = sdk
137            .transfer_transaction(
138                None,
139                &initiator_addr,
140                TRANSFER_AMOUNT,
141                transaction_params,
142                None,
143                verbosity,
144                Some(rpc_address),
145            )
146            .await;
147
148        // Assert
149        assert!(result.is_ok());
150    }
151
152    #[tokio::test]
153    async fn test_transfer_with_valid_transfer_params_without_secret_key() {
154        // Arrange
155        let sdk = SDK::new(None, None, None);
156        let verbosity = Some(Verbosity::High);
157        let (rpc_address, _, _, _, chain_name) = get_network_constants();
158
159        let error_message = "the transaction was invalid: invalid associated keys";
160
161        let secret_key = get_user_secret_key(None).unwrap();
162        let initiator_addr = public_key_from_secret_key(&secret_key).unwrap();
163
164        let transaction_params = TransactionStrParams::default();
165        transaction_params.set_chain_name(&chain_name);
166        transaction_params.set_initiator_addr(&initiator_addr);
167        transaction_params.set_payment_amount(TRANSFER_AMOUNT);
168
169        // Act
170        let result = sdk
171            .transfer_transaction(
172                None,
173                &initiator_addr,
174                TRANSFER_AMOUNT,
175                transaction_params,
176                None,
177                verbosity,
178                Some(rpc_address),
179            )
180            .await;
181
182        // Assert
183        assert!(result.is_err());
184        let err_string = result.err().unwrap().to_string();
185        assert!(err_string.contains(error_message));
186    }
187
188    #[tokio::test]
189    async fn test_transfer_with_invalid_transfer_params() {
190        // Arrange
191        let sdk = SDK::new(None, None, None);
192        let verbosity = Some(Verbosity::High);
193        let (rpc_address, _, _, _, _) = get_network_constants();
194
195        let error_message = "The transaction sent to the network had an invalid chain name";
196        let secret_key = get_user_secret_key(None).unwrap();
197        let initiator_addr = public_key_from_secret_key(&secret_key).unwrap();
198
199        let transaction_params = TransactionStrParams::default();
200        transaction_params.set_secret_key(&secret_key);
201        transaction_params.set_payment_amount(TRANSFER_AMOUNT);
202        transaction_params.set_chain_name("");
203
204        // Act
205        let result = sdk
206            .transfer_transaction(
207                None,
208                &initiator_addr,
209                TRANSFER_AMOUNT,
210                transaction_params,
211                None,
212                verbosity,
213                Some(rpc_address),
214            )
215            .await;
216        // Assert
217        assert!(result.is_err());
218
219        let err_string = result.err().unwrap().to_string();
220        assert!(err_string.contains(error_message));
221    }
222}