casper_rust_wasm_sdk/sdk/rpcs/
get_transaction.rs1use crate::types::hash::transaction_hash::TransactionHash;
2#[cfg(all(feature = "js", target_arch = "wasm32"))]
3use crate::types::transaction::Transaction;
4use crate::{
5 types::{sdk_error::SdkError, verbosity::Verbosity},
6 SDK,
7};
8use casper_client::{
9 get_transaction, rpcs::results::GetTransactionResult as _GetTransactionResult, JsonRpcId,
10 SuccessResponse,
11};
12#[cfg(all(feature = "js", target_arch = "wasm32"))]
13use gloo_utils::format::JsValueSerdeExt;
14use rand::RngExt;
15#[cfg(all(feature = "js", target_arch = "wasm32"))]
16use serde::{Deserialize, Serialize};
17#[cfg(feature = "js")]
18use wasm_bindgen::prelude::*;
19
20#[cfg(all(feature = "js", target_arch = "wasm32"))]
22#[derive(Debug, Deserialize, Clone, Serialize)]
23#[cfg_attr(feature = "js", wasm_bindgen)]
24pub struct GetTransactionResult(_GetTransactionResult);
25
26#[cfg(all(feature = "js", target_arch = "wasm32"))]
27impl From<GetTransactionResult> for _GetTransactionResult {
28 fn from(result: GetTransactionResult) -> Self {
29 result.0
30 }
31}
32#[cfg(all(feature = "js", target_arch = "wasm32"))]
33impl From<_GetTransactionResult> for GetTransactionResult {
34 fn from(result: _GetTransactionResult) -> Self {
35 GetTransactionResult(result)
36 }
37}
38
39#[cfg(all(feature = "js", target_arch = "wasm32"))]
40#[cfg_attr(feature = "js", wasm_bindgen)]
41impl GetTransactionResult {
42 #[cfg_attr(feature = "js", wasm_bindgen(getter))]
43 #[cfg(feature = "js")]
45 pub fn api_version(&self) -> JsValue {
46 JsValue::from_serde(&self.0.api_version).unwrap()
47 }
48
49 #[cfg_attr(feature = "js", wasm_bindgen(getter))]
50 pub fn transaction(&self) -> Transaction {
52 self.0.transaction.clone().into()
53 }
54
55 #[cfg_attr(feature = "js", wasm_bindgen(getter))]
56 #[cfg(feature = "js")]
58 pub fn execution_info(&self) -> JsValue {
59 JsValue::from_serde(&self.0.execution_info).unwrap()
60 }
61
62 #[cfg_attr(feature = "js", wasm_bindgen(js_name = "toJson"))]
63 #[cfg(feature = "js")]
65 pub fn to_json(&self) -> JsValue {
66 JsValue::from_serde(&self.0).unwrap_or(JsValue::null())
67 }
68}
69
70#[derive(Debug, Clone, Default, Deserialize, Serialize)]
72#[cfg(all(feature = "js", target_arch = "wasm32"))]
73#[cfg_attr(
74 feature = "js",
75 wasm_bindgen(js_name = "getTransactionOptions", getter_with_clone)
76)]
77pub struct GetTransactionOptions {
78 pub transaction_hash_as_string: Option<String>,
79 pub transaction_hash: Option<TransactionHash>,
80 pub finalized_approvals: Option<bool>,
81 pub rpc_address: Option<String>,
82 pub verbosity: Option<Verbosity>,
83}
84
85#[cfg_attr(feature = "js", wasm_bindgen)]
86impl SDK {
87 #[cfg(all(feature = "js", target_arch = "wasm32"))]
97 pub fn get_transaction_options(
98 &self,
99 options: JsValue,
100 ) -> Result<GetTransactionOptions, JsError> {
101 let options_result: Result<GetTransactionOptions, _> = options.into_serde();
102 match options_result {
103 Ok(mut options) => {
104 if let Some(finalized_approvals) = options.finalized_approvals {
105 options.finalized_approvals =
106 Some(JsValue::from_bool(finalized_approvals) == JsValue::TRUE);
107 }
108 Ok(options)
109 }
110 Err(err) => Err(JsError::new(&format!(
111 "Error deserializing options: {err:?}"
112 ))),
113 }
114 }
115
116 #[cfg(all(feature = "js", target_arch = "wasm32"))]
126 #[cfg_attr(feature = "js", wasm_bindgen(js_name = "get_transaction"))]
127 pub async fn get_transaction_js_alias(
128 &self,
129 options: Option<GetTransactionOptions>,
130 ) -> Result<GetTransactionResult, JsError> {
131 let GetTransactionOptions {
132 transaction_hash_as_string,
133 transaction_hash,
134 finalized_approvals,
135 verbosity,
136 rpc_address,
137 } = options.unwrap_or_default();
138
139 let transaction_hash = if let Some(transaction_hash_as_string) = transaction_hash_as_string
140 {
141 TransactionHash::new(&transaction_hash_as_string)?
142 } else {
143 if transaction_hash.is_none() {
144 let err_msg =
145 "Error: Missing transaction hash as string or transaction hash".to_string();
146 return Err(JsError::new(&err_msg));
147 }
148 transaction_hash.unwrap()
149 };
150
151 let result = self
152 .get_transaction(
153 transaction_hash,
154 finalized_approvals,
155 verbosity,
156 rpc_address,
157 )
158 .await;
159 match result {
160 Ok(data) => Ok(data.result.into()),
161 Err(err) => {
162 let err = &format!("Error occurred with {err:?}");
163 Err(JsError::new(err))
164 }
165 }
166 }
167
168 #[cfg(all(feature = "js", target_arch = "wasm32"))]
170 #[deprecated(note = "This function is an alias. Please use `get_transaction` instead.")]
171 #[allow(deprecated)]
172 pub async fn info_get_transaction(
173 &self,
174 options: Option<GetTransactionOptions>,
175 ) -> Result<GetTransactionResult, JsError> {
176 self.get_transaction_js_alias(options).await
177 }
178}
179
180impl SDK {
181 pub async fn get_transaction(
194 &self,
195 transaction_hash: TransactionHash,
196 finalized_approvals: Option<bool>,
197 verbosity: Option<Verbosity>,
198 rpc_address: Option<String>,
199 ) -> Result<SuccessResponse<_GetTransactionResult>, SdkError> {
200 let random_id = JsonRpcId::from(rand::rng().random::<u64>().to_string());
202 get_transaction(
203 random_id,
204 &self.get_rpc_address(rpc_address),
205 self.get_verbosity(verbosity).into(),
206 transaction_hash.into(),
207 finalized_approvals.unwrap_or_default(),
208 )
209 .await
210 .map_err(Into::into)
211 }
212}
213
214#[cfg(test)]
215mod tests {
216 use super::*;
217 use crate::{
218 helpers::public_key_from_secret_key,
219 types::transaction_params::transaction_str_params::TransactionStrParams,
220 };
221 use sdk_tests::{
222 config::TRANSFER_AMOUNT,
223 tests::helpers::{get_network_constants, get_user_secret_key},
224 };
225
226 #[tokio::test]
227 async fn test_get_transaction_with_none_values() {
228 let sdk = SDK::new(None, None, None);
230 let transaction_hash = TransactionHash::from_raw(&[1u8; 32]).unwrap();
231 let error_message = "failed to parse node address as valid URL";
232
233 let result = sdk
235 .get_transaction(transaction_hash, None, None, None)
236 .await;
237
238 assert!(result.is_err());
240 let err_string = result.err().unwrap().to_string();
241 assert!(err_string.contains(error_message));
242 }
243
244 #[tokio::test]
245 async fn test_get_transaction_with_invalid_transaction_hash() {
246 let sdk = SDK::new(None, None, None);
248 let transaction_hash = TransactionHash::from_raw(&[1u8; 32]).unwrap();
249 let verbosity = Some(Verbosity::High);
250 let (rpc_address, _, _, _, _) = get_network_constants();
251
252 let result = sdk
254 .get_transaction(transaction_hash, None, verbosity, Some(rpc_address))
255 .await;
256
257 assert!(result.is_err());
259 }
260
261 #[tokio::test]
262 async fn test_get_transaction_with_valid_transaction_hash() {
263 let sdk = SDK::new(None, None, None);
265 let verbosity = Some(Verbosity::High);
266 let (rpc_address, _, _, _, chain_name) = get_network_constants();
267
268 let secret_key = get_user_secret_key(None).unwrap();
269 let initiator_addr = public_key_from_secret_key(&secret_key).unwrap();
270
271 let transaction_params = TransactionStrParams::default();
272 transaction_params.set_secret_key(&secret_key);
273 transaction_params.set_chain_name(&chain_name);
274 transaction_params.set_payment_amount(TRANSFER_AMOUNT);
275
276 let transfer = sdk
277 .transfer_transaction(
278 None,
279 &initiator_addr, TRANSFER_AMOUNT,
281 transaction_params,
282 None,
283 verbosity,
284 Some(rpc_address.clone()),
285 )
286 .await
287 .unwrap();
288 let transaction_hash = transfer.result.transaction_hash;
289 assert!(!transaction_hash.to_string().is_empty());
290
291 let result = sdk
293 .get_transaction(transaction_hash.into(), None, verbosity, Some(rpc_address))
294 .await;
295
296 assert!(result.is_ok());
299 }
300
301 #[tokio::test]
302 async fn test_get_transaction_with_finalized_approvals() {
303 let sdk = SDK::new(None, None, None);
305 let verbosity = Some(Verbosity::High);
306 let (rpc_address, _, _, _, chain_name) = get_network_constants();
307
308 let secret_key = get_user_secret_key(None).unwrap();
309 let initiator_addr = public_key_from_secret_key(&secret_key).unwrap();
310
311 let transaction_params = TransactionStrParams::default();
312 transaction_params.set_secret_key(&secret_key);
313 transaction_params.set_chain_name(&chain_name);
314 transaction_params.set_payment_amount(TRANSFER_AMOUNT);
315
316 let transfer = sdk
317 .transfer_transaction(
318 None,
319 &initiator_addr, TRANSFER_AMOUNT,
321 transaction_params,
322 None,
323 verbosity,
324 Some(rpc_address.clone()),
325 )
326 .await
327 .unwrap();
328 let transaction_hash = transfer.result.transaction_hash;
329 assert!(!transaction_hash.to_string().is_empty());
330 let finalized_approvals = true;
331
332 let result = sdk
334 .get_transaction(
335 transaction_hash.into(),
336 Some(finalized_approvals),
337 verbosity,
338 Some(rpc_address),
339 )
340 .await;
341
342 assert!(result.is_ok());
344 }
345
346 #[tokio::test]
347 async fn test_get_transaction_with_error() {
348 let sdk = SDK::new(Some("http://localhost".to_string()), None, None);
350 let transaction_hash = TransactionHash::from_raw(&[1u8; 32]).unwrap();
351 let error_message = "error sending request";
352
353 let result = sdk
355 .get_transaction(transaction_hash, None, None, None)
356 .await;
357
358 assert!(result.is_err());
360 let err_string = result.err().unwrap().to_string();
361 assert!(err_string.contains(error_message));
362 }
363}