casper_rust_wasm_sdk/sdk/contract/
call_entrypoint.rs

1#[cfg(target_arch = "wasm32")]
2use crate::transaction::transaction::PutTransactionResult;
3use crate::{
4    types::{
5        sdk_error::SdkError,
6        transaction_params::{
7            transaction_builder_params::TransactionBuilderParams,
8            transaction_str_params::TransactionStrParams,
9        },
10    },
11    SDK,
12};
13use casper_client::{
14    rpcs::results::PutTransactionResult as _PutTransactionResult, SuccessResponse,
15};
16#[cfg(target_arch = "wasm32")]
17use wasm_bindgen::prelude::*;
18
19/// A set of functions for working with smart contract entry points.
20#[cfg(target_arch = "wasm32")]
21#[wasm_bindgen]
22impl SDK {
23    /// Calls a smart contract entry point with the specified parameters and returns the result.
24    ///
25    /// # Arguments
26    ///
27    /// * `transaction_params` - Transaction parameters.
28    /// * `builder_params` - Transaction Builder parameters.
29    /// * `rpc_address` - An optional rpc address to send the request to.
30    ///
31    /// # Returns
32    ///
33    /// A `Result` containing either a `PutTransactionResult` or a `JsError` in case of an error.
34    ///
35    /// # Errors
36    ///
37    /// Returns a `JsError` if there is an error during the call.
38    #[wasm_bindgen(js_name = "call_entrypoint")]
39    pub async fn call_entrypoint_js_alias(
40        &self,
41        builder_params: TransactionBuilderParams,
42        transaction_params: TransactionStrParams,
43        rpc_address: Option<String>,
44    ) -> Result<PutTransactionResult, JsError> {
45        let result = self
46            .call_entrypoint(builder_params, transaction_params, 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                Err(JsError::new(err))
53            }
54        }
55    }
56}
57
58/// A set of functions for working with smart contract entry points.
59/// Alias of sdk.transaction
60impl SDK {
61    /// Calls a smart contract entry point with the specified parameters and returns the result.
62    ///
63    /// # Arguments
64    ///
65    /// * `builder_params` - Transaction Builder parameters.
66    /// * `transaction_params` - Transaction parameters.
67    /// * `rpc_address` - An optional rpc address to send the request to.
68    ///
69    /// # Returns
70    ///
71    /// A `Result` containing either a `_PutTransactionResult` or a `SdkError` in case of an error.
72    ///
73    /// # Errors
74    ///
75    /// Returns a `SdkError` if there is an error during the call.
76    pub async fn call_entrypoint(
77        &self,
78        builder_params: TransactionBuilderParams,
79        transaction_params: TransactionStrParams,
80        rpc_address: Option<String>,
81    ) -> Result<SuccessResponse<_PutTransactionResult>, SdkError> {
82        //log("call_entrypoint!");;
83        self.transaction(builder_params, transaction_params, None, rpc_address)
84            .await
85    }
86}
87
88#[cfg(test)]
89mod tests {
90    use super::*;
91    use crate::{
92        helpers::public_key_from_secret_key, install_cep78, types::addr::entity_addr::EntityAddr,
93    };
94    use once_cell::sync::Lazy;
95    use sdk_tests::{
96        config::{ARGS_SIMPLE, ENTRYPOINT_MINT, PAYMENT_AMOUNT},
97        tests::helpers::{get_network_constants, get_user_secret_key},
98    };
99    use tokio;
100
101    static ARGS: Lazy<Vec<String>> =
102        Lazy::new(|| ARGS_SIMPLE.iter().map(|s| s.to_string()).collect());
103
104    async fn get_entity_key() -> String {
105        install_cep78().await
106    }
107
108    #[tokio::test]
109    async fn test_call_entrypoint_with_none_values() {
110        // Arrange
111        let sdk = SDK::new(None, None, None);
112        let builder_params = TransactionBuilderParams::default();
113        let transaction_params = TransactionStrParams::default();
114        transaction_params.set_payment_amount(PAYMENT_AMOUNT);
115
116        let error_message =
117            "transaction requires account - use `with_account` or `with_secret_key`";
118
119        // Act
120        let result = sdk
121            .call_entrypoint(builder_params, transaction_params, None)
122            .await;
123
124        // Assert
125        assert!(result.is_err());
126        let err_string = result.err().unwrap().to_string();
127        assert!(err_string.contains(error_message));
128    }
129
130    #[tokio::test]
131    async fn test_call_entrypoint_with_valid_input() {
132        // Arrange
133        let sdk = SDK::new(None, None, None);
134        let (rpc_address, _, _, _, chain_name) = get_network_constants();
135        let secret_key = get_user_secret_key(None).unwrap();
136
137        let mut transaction_params = TransactionStrParams::default();
138        transaction_params.set_secret_key(&secret_key);
139        transaction_params.set_chain_name(&chain_name);
140        transaction_params.set_payment_amount(PAYMENT_AMOUNT);
141        transaction_params.set_session_args_simple(ARGS.to_vec());
142
143        let entity_addr = EntityAddr::from_formatted_str(&get_entity_key().await).unwrap();
144
145        let builder_params =
146            TransactionBuilderParams::new_invocable_entity(entity_addr.into(), ENTRYPOINT_MINT);
147
148        // Act
149        let result = sdk
150            .call_entrypoint(builder_params, transaction_params, Some(rpc_address))
151            .await;
152
153        // Assert
154        assert!(result.is_ok());
155        let transaction_hash = result.unwrap().result.transaction_hash;
156        assert!(!transaction_hash.to_string().is_empty());
157    }
158
159    #[tokio::test]
160    async fn test_call_entrypoint_with_invalid_input() {
161        // Arrange
162        let sdk = SDK::new(None, None, None);
163        let (rpc_address, _, _, _, chain_name) = get_network_constants();
164        let secret_key = get_user_secret_key(None).unwrap();
165
166        let error_message = "the transaction was invalid: no such contract at hash";
167        let mut transaction_params = TransactionStrParams::default();
168        transaction_params.set_secret_key(&secret_key);
169        transaction_params.set_chain_name(&chain_name);
170        transaction_params.set_session_args_simple(ARGS.to_vec());
171        transaction_params.set_payment_amount(PAYMENT_AMOUNT);
172
173        let entity_addr = EntityAddr::from_formatted_str(
174            "entity-contract-cfa781f5eb69c3eee952c2944ce9670a049f88c5e46b83fb5881ebe13fb98e6d",
175        )
176        .unwrap();
177
178        let builder_params =
179            TransactionBuilderParams::new_invocable_entity(entity_addr.into(), ENTRYPOINT_MINT);
180
181        // Act
182        let result = sdk
183            .call_entrypoint(builder_params, transaction_params, Some(rpc_address))
184            .await;
185
186        // Assert
187        assert!(result.is_err());
188        let err_string = result.err().unwrap().to_string();
189        assert!(err_string.contains(error_message));
190    }
191
192    #[tokio::test]
193    async fn test_call_entrypoint_without_secret_key() {
194        // Arrange
195        let sdk = SDK::new(None, None, None);
196        let (rpc_address, _, _, _, chain_name) = get_network_constants();
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 error_message = "the transaction was invalid: invalid associated keys";
201
202        let mut transaction_params = TransactionStrParams::default();
203        transaction_params.set_chain_name(&chain_name);
204        transaction_params.set_initiator_addr(&initiator_addr);
205        transaction_params.set_payment_amount(PAYMENT_AMOUNT);
206        transaction_params.set_session_args_simple(ARGS.to_vec());
207
208        let entity_addr = EntityAddr::from_formatted_str(
209            "entity-contract-cfa781f5eb69c3eee952c2944ce9670a049f88c5e46b83fb5881ebe13fb98e6d",
210        )
211        .unwrap();
212
213        let builder_params =
214            TransactionBuilderParams::new_invocable_entity(entity_addr.into(), ENTRYPOINT_MINT);
215
216        // Act
217        let result = sdk
218            .call_entrypoint(builder_params, transaction_params, Some(rpc_address))
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_call_entrypoint_with_error() {
229        // Arrange
230        let sdk = SDK::new(Some("http://localhost".to_string()), None, None);
231        let (_, _, _, _, chain_name) = get_network_constants();
232        let secret_key = get_user_secret_key(None).unwrap();
233
234        let error_message = "error sending request for url (http://localhost/rpc)";
235
236        let mut transaction_params = TransactionStrParams::default();
237        transaction_params.set_secret_key(&secret_key);
238        transaction_params.set_chain_name(&chain_name);
239        transaction_params.set_payment_amount(PAYMENT_AMOUNT);
240        transaction_params.set_session_args_simple(ARGS.to_vec());
241
242        let entity_addr = EntityAddr::from_formatted_str(
243            "entity-contract-cfa781f5eb69c3eee952c2944ce9670a049f88c5e46b83fb5881ebe13fb98e6d",
244        )
245        .unwrap();
246
247        let builder_params =
248            TransactionBuilderParams::new_invocable_entity(entity_addr.into(), ENTRYPOINT_MINT);
249
250        // Act
251        let result = sdk
252            .call_entrypoint(builder_params, transaction_params, None)
253            .await;
254
255        // Assert
256        assert!(result.is_err());
257        let err_string = result.err().unwrap().to_string();
258        assert!(err_string.contains(error_message));
259    }
260}