casper_rust_wasm_sdk/sdk/transaction/
transaction.rs1#[cfg(all(feature = "js", target_arch = "wasm32"))]
2use crate::types::hash::transaction_hash::TransactionHash;
3use crate::{
4 types::{
5 sdk_error::SdkError,
6 transaction_params::{
7 transaction_builder_params::{
8 transaction_builder_params_to_casper_client, TransactionBuilderParams,
9 },
10 transaction_str_params::{
11 transaction_str_params_to_casper_client, TransactionStrParams,
12 },
13 },
14 verbosity::Verbosity,
15 },
16 SDK,
17};
18
19use casper_client::{
20 cli::make_transaction, rpcs::results::PutTransactionResult as _PutTransactionResult,
21 SuccessResponse,
22};
23#[cfg(all(feature = "js", target_arch = "wasm32"))]
24use gloo_utils::format::JsValueSerdeExt;
25#[cfg(all(feature = "js", target_arch = "wasm32"))]
26use serde::{Deserialize, Serialize};
27#[cfg(all(feature = "js", target_arch = "wasm32"))]
28use wasm_bindgen::prelude::*;
29
30#[cfg(all(feature = "js", target_arch = "wasm32"))]
32#[derive(Debug, Deserialize, Clone, Serialize)]
33#[cfg_attr(feature = "js", wasm_bindgen)]
34pub struct PutTransactionResult(_PutTransactionResult);
35
36#[cfg(all(feature = "js", target_arch = "wasm32"))]
38impl From<PutTransactionResult> for _PutTransactionResult {
39 fn from(result: PutTransactionResult) -> Self {
40 result.0
41 }
42}
43#[cfg(all(feature = "js", target_arch = "wasm32"))]
44impl From<_PutTransactionResult> for PutTransactionResult {
45 fn from(result: _PutTransactionResult) -> Self {
46 PutTransactionResult(result)
47 }
48}
49
50#[cfg(all(feature = "js", target_arch = "wasm32"))]
52#[cfg_attr(feature = "js", wasm_bindgen)]
53impl PutTransactionResult {
54 #[cfg_attr(feature = "js", wasm_bindgen(getter))]
56 #[cfg(feature = "js")]
57 pub fn api_version(&self) -> JsValue {
58 JsValue::from_serde(&self.0.api_version).unwrap()
59 }
60
61 #[cfg_attr(feature = "js", wasm_bindgen(getter))]
63 pub fn transaction_hash(&self) -> TransactionHash {
64 self.0.transaction_hash.into()
65 }
66
67 #[cfg_attr(feature = "js", wasm_bindgen(js_name = "toJson"))]
69 #[cfg(feature = "js")]
70 pub fn to_json(&self) -> JsValue {
71 JsValue::from_serde(&self.0).unwrap_or(JsValue::null())
72 }
73}
74
75#[cfg(all(feature = "js", target_arch = "wasm32"))]
76#[cfg_attr(feature = "js", wasm_bindgen)]
77impl SDK {
78 #[cfg_attr(feature = "js", wasm_bindgen(js_name = "transaction"))]
91 #[cfg(feature = "js")]
92 pub async fn transaction_js_alias(
93 &self,
94 builder_params: TransactionBuilderParams,
95 transaction_params: TransactionStrParams,
96 verbosity: Option<Verbosity>,
97 rpc_address: Option<String>,
98 ) -> Result<PutTransactionResult, JsError> {
99 let result = self
100 .transaction(builder_params, transaction_params, verbosity, rpc_address)
101 .await;
102 match result {
103 Ok(data) => Ok(data.result.into()),
104 Err(err) => {
105 let err = &format!("Error occurred with {err:?}");
106 Err(JsError::new(err))
107 }
108 }
109 }
110}
111
112impl SDK {
113 pub async fn transaction(
126 &self,
127 builder_params: TransactionBuilderParams,
128 transaction_params: TransactionStrParams,
129 verbosity: Option<Verbosity>,
130 rpc_address: Option<String>,
131 ) -> Result<SuccessResponse<_PutTransactionResult>, SdkError> {
132 let transaction = match make_transaction(
134 transaction_builder_params_to_casper_client(&builder_params),
135 transaction_str_params_to_casper_client(&transaction_params),
136 false,
137 ) {
138 Ok(transaction) => transaction,
139 Err(err) => {
140 return Err(SdkError::from(err));
141 }
142 };
143 self.put_transaction(transaction.into(), verbosity, rpc_address)
144 .await
145 }
146}
147
148#[cfg(test)]
149mod tests {
150 use std::sync::Mutex;
151
152 use super::*;
153 use crate::helpers::public_key_from_secret_key;
154 use once_cell::sync::Lazy;
155 use sdk_tests::{
156 config::{ARGS_SIMPLE, HELLO_CONTRACT, PAYMENT_AMOUNT, WASM_PATH},
157 tests::helpers::{get_network_constants, get_user_secret_key, read_wasm_file},
158 };
159
160 static ARGS: Lazy<Vec<String>> =
161 Lazy::new(|| ARGS_SIMPLE.iter().map(|s| s.to_string()).collect());
162
163 static BUILDER_PARAMS: Lazy<Mutex<Option<TransactionBuilderParams>>> =
164 Lazy::new(|| Mutex::new(None));
165
166 fn get_builder_params() -> TransactionBuilderParams {
167 let mut builder_params = BUILDER_PARAMS.lock().unwrap();
168
169 if builder_params.is_none() {
170 let file_path = &format!("{WASM_PATH}{HELLO_CONTRACT}");
171 let transaction_bytes = match read_wasm_file(file_path) {
172 Ok(transaction_bytes) => transaction_bytes,
173 Err(err) => {
174 eprintln!("Error reading file: {err:?}");
175 unimplemented!()
176 }
177 };
178
179 let is_install_upgrade = Some(true);
180
181 let mut new_builder_params = TransactionBuilderParams::new_session(
182 Some(transaction_bytes.into()),
183 is_install_upgrade,
184 );
185 new_builder_params.set_runtime_v1();
187 *builder_params = Some(new_builder_params);
188 }
189
190 builder_params.clone().unwrap()
191 }
192
193 #[tokio::test]
194 async fn test_transaction_with_valid_transaction_params() {
195 let sdk = SDK::new(None, None, None);
197 let verbosity = Some(Verbosity::High);
198 let (rpc_address, _, _, _, chain_name) = get_network_constants();
199 let secret_key = get_user_secret_key(None).unwrap();
200
201 let mut transaction_params = TransactionStrParams::default();
202 transaction_params.set_secret_key(&secret_key);
203 transaction_params.set_chain_name(&chain_name);
204 transaction_params.set_payment_amount(PAYMENT_AMOUNT);
205 transaction_params.set_session_args_simple(ARGS.to_vec());
206
207 let result = sdk
209 .transaction(
210 get_builder_params().clone(),
211 transaction_params,
212 verbosity,
213 Some(rpc_address),
214 )
215 .await;
216
217 assert!(result.is_ok());
219 }
220
221 #[tokio::test]
222 async fn test_transaction_with_valid_transaction_params_without_secret_key() {
223 let sdk = SDK::new(None, None, None);
225 let verbosity = Some(Verbosity::High);
226 let (rpc_address, _, _, _, chain_name) = get_network_constants();
227 let secret_key = get_user_secret_key(None).unwrap();
228 let initiator_addr = public_key_from_secret_key(&secret_key).unwrap();
229 let error_message = "the transaction was invalid: invalid associated keys";
230
231 let mut transaction_params = TransactionStrParams::default();
232 transaction_params.set_chain_name(&chain_name);
233 transaction_params.set_initiator_addr(&initiator_addr);
234 transaction_params.set_payment_amount(PAYMENT_AMOUNT);
235 transaction_params.set_session_args_simple(ARGS.to_vec());
236
237 let result = sdk
239 .transaction(
240 get_builder_params().clone(),
241 transaction_params,
242 verbosity,
243 Some(rpc_address),
244 )
245 .await;
246
247 assert!(result.is_err());
249 let err_string = result.err().unwrap().to_string();
250 assert!(err_string.contains(error_message));
251 }
252
253 #[tokio::test]
254 async fn test_transaction_with_invalid_transaction_params() {
255 let sdk = SDK::new(None, None, None);
257 let verbosity = Some(Verbosity::High);
258 let (rpc_address, _, _, _, _) = get_network_constants();
259
260 let error_message = "The transaction sent to the network had an invalid chain name";
261 let secret_key = get_user_secret_key(None).unwrap();
262
263 let transaction_params = TransactionStrParams::default();
264 transaction_params.set_payment_amount(PAYMENT_AMOUNT);
265 transaction_params.set_secret_key(&secret_key);
266 transaction_params.set_chain_name("");
267
268 let result = sdk
270 .transaction(
271 get_builder_params().clone(),
272 transaction_params,
273 verbosity,
274 Some(rpc_address),
275 )
276 .await;
277 assert!(result.is_err());
279
280 let err_string = result.err().unwrap().to_string();
281 assert!(err_string.contains(error_message));
282 }
283}