casper_rust_wasm_sdk/sdk/rpcs/
get_entity.rs1#[cfg(all(feature = "js", target_arch = "wasm32"))]
2use crate::types::identifier::block_identifier::BlockIdentifier;
3use crate::{
4 types::{
5 entity_or_account::EntityOrAccount,
6 identifier::{block_identifier::BlockIdentifierInput, entity_identifier::EntityIdentifier},
7 sdk_error::SdkError,
8 verbosity::Verbosity,
9 },
10 SDK,
11};
12use casper_client::{
13 cli::{get_entity as get_entity_cli, parse::entity_identifier as parse_entity_identifier},
14 get_entity as get_entity_lib,
15 rpcs::results::GetAddressableEntityResult as _GetAddressableEntityResult,
16 JsonRpcId, SuccessResponse,
17};
18#[cfg(all(feature = "js", target_arch = "wasm32"))]
19use gloo_utils::format::JsValueSerdeExt;
20use rand::RngExt;
21use serde::{Deserialize, Serialize};
22#[cfg(feature = "js")]
23use wasm_bindgen::prelude::*;
24
25#[derive(Debug, Deserialize, Clone, Serialize)]
27#[cfg_attr(feature = "js", wasm_bindgen)]
28pub struct GetAddressableEntityResult(_GetAddressableEntityResult);
29
30impl From<GetAddressableEntityResult> for _GetAddressableEntityResult {
31 fn from(result: GetAddressableEntityResult) -> Self {
32 result.0
33 }
34}
35
36impl From<_GetAddressableEntityResult> for GetAddressableEntityResult {
37 fn from(result: _GetAddressableEntityResult) -> Self {
38 GetAddressableEntityResult(result)
39 }
40}
41
42impl GetAddressableEntityResult {
43 pub fn entity_result_typed(&self) -> EntityOrAccount {
45 self.0.entity_result.clone().into()
46 }
47}
48
49#[cfg(all(feature = "js", target_arch = "wasm32"))]
50#[cfg_attr(feature = "js", wasm_bindgen)]
51impl GetAddressableEntityResult {
52 #[cfg_attr(feature = "js", wasm_bindgen(getter))]
53 #[cfg(feature = "js")]
54 pub fn api_version(&self) -> JsValue {
55 JsValue::from_serde(&self.0.api_version).unwrap()
56 }
57
58 #[cfg_attr(feature = "js", wasm_bindgen(getter))]
59 #[cfg(feature = "js")]
60 pub fn entity_result(&self) -> JsValue {
61 JsValue::from_serde(&self.0.entity_result).unwrap()
62 }
63
64 #[cfg_attr(feature = "js", wasm_bindgen(js_name = "entityResultTyped"))]
66 pub fn entity_result_typed_js(&self) -> EntityOrAccount {
67 self.entity_result_typed()
68 }
69
70 #[cfg_attr(feature = "js", wasm_bindgen(getter))]
71 pub fn merkle_proof(&self) -> String {
72 self.0.merkle_proof.clone()
73 }
74
75 #[cfg_attr(feature = "js", wasm_bindgen(js_name = "toJson"))]
76 #[cfg(feature = "js")]
77 pub fn to_json(&self) -> JsValue {
78 JsValue::from_serde(&self.0).unwrap_or(JsValue::null())
79 }
80}
81
82#[derive(Debug, Deserialize, Clone, Default, Serialize)]
84#[cfg(all(feature = "js", target_arch = "wasm32"))]
85#[cfg_attr(
86 feature = "js",
87 wasm_bindgen(js_name = "getEntityOptions", getter_with_clone)
88)]
89pub struct GetEntityOptions {
90 pub entity_identifier: Option<EntityIdentifier>,
91 pub entity_identifier_as_string: Option<String>,
92 pub maybe_block_id_as_string: Option<String>,
93 pub maybe_block_identifier: Option<BlockIdentifier>,
94 pub rpc_address: Option<String>,
95 pub verbosity: Option<Verbosity>,
96}
97
98#[cfg(all(feature = "js", target_arch = "wasm32"))]
99#[cfg_attr(feature = "js", wasm_bindgen)]
100impl SDK {
101 #[cfg(feature = "js")]
103 pub fn get_entity_options(&self, options: JsValue) -> Result<GetEntityOptions, JsError> {
104 options
105 .into_serde::<GetEntityOptions>()
106 .map_err(|err| JsError::new(&format!("Error deserializing options: {err:?}")))
107 }
108
109 #[cfg_attr(feature = "js", wasm_bindgen(js_name = "get_entity"))]
132 #[cfg(feature = "js")]
133 pub async fn get_entity_js_alias(
134 &self,
135 options: Option<GetEntityOptions>,
136 ) -> Result<GetAddressableEntityResult, JsError> {
137 let GetEntityOptions {
138 entity_identifier,
139 entity_identifier_as_string,
140 maybe_block_id_as_string,
141 maybe_block_identifier,
142 verbosity,
143 rpc_address,
144 } = options.unwrap_or_default();
145
146 let maybe_block_identifier = if let Some(maybe_block_identifier) = maybe_block_identifier {
147 Some(BlockIdentifierInput::BlockIdentifier(
148 maybe_block_identifier,
149 ))
150 } else {
151 maybe_block_id_as_string.map(BlockIdentifierInput::String)
152 };
153
154 let result = self
155 .get_entity(
156 entity_identifier,
157 entity_identifier_as_string,
158 maybe_block_identifier,
159 verbosity,
160 rpc_address,
161 )
162 .await;
163 match result {
164 Ok(data) => Ok(data.result.into()),
165 Err(err) => {
166 let err = &format!("Error occurred with {err:?}");
167 Err(JsError::new(err))
168 }
169 }
170 }
171
172 #[cfg_attr(feature = "js", wasm_bindgen(js_name = "state_get_entity"))]
174 #[cfg(feature = "js")]
175 pub async fn state_get_entity(
176 &self,
177 options: Option<GetEntityOptions>,
178 ) -> Result<GetAddressableEntityResult, JsError> {
179 self.get_entity_js_alias(options).await
180 }
181}
182
183impl SDK {
184 pub async fn get_entity(
202 &self,
203 entity_identifier: Option<EntityIdentifier>,
204 entity_identifier_as_string: Option<String>,
205 maybe_block_identifier: Option<BlockIdentifierInput>,
206 verbosity: Option<Verbosity>,
207 rpc_address: Option<String>,
208 ) -> Result<SuccessResponse<_GetAddressableEntityResult>, SdkError> {
209 let entity_identifier = if let Some(entity_identifier) = entity_identifier {
210 entity_identifier
211 } else if let Some(entity_identifier_as_string) = entity_identifier_as_string.clone() {
212 match parse_entity_identifier(&entity_identifier_as_string) {
213 Ok(parsed) => parsed.into(),
214 Err(err) => {
215 return Err(err.into());
216 }
217 }
218 } else {
219 let err = "Error: Missing entity identifier".to_string();
220 return Err(SdkError::InvalidArgument {
221 context: "get_entity",
222 error: err,
223 });
224 };
225 let random_id = rand::rng().random::<u64>().to_string();
226 if let Some(BlockIdentifierInput::String(maybe_block_id)) = maybe_block_identifier {
227 get_entity_cli(
228 &random_id,
229 &self.get_rpc_address(rpc_address),
230 self.get_verbosity(verbosity).into(),
231 &maybe_block_id,
232 &entity_identifier.to_string(),
233 )
234 .await
235 .map_err(SdkError::from)
236 } else {
237 let maybe_block_identifier =
238 if let Some(BlockIdentifierInput::BlockIdentifier(maybe_block_identifier)) =
239 maybe_block_identifier
240 {
241 Some(maybe_block_identifier)
242 } else {
243 None
244 };
245 get_entity_lib(
246 JsonRpcId::from(random_id),
247 &self.get_rpc_address(rpc_address),
248 self.get_verbosity(verbosity).into(),
249 maybe_block_identifier.map(Into::into),
250 entity_identifier.into(),
251 )
252 .await
253 .map_err(SdkError::from)
254 }
255 }
256}
257
258#[cfg(test)]
259mod tests {
260 use super::*;
261 use crate::{
262 helpers::public_key_from_secret_key,
263 types::{identifier::block_identifier::BlockIdentifier, public_key::PublicKey},
264 };
265 use sdk_tests::tests::helpers::{
266 get_enable_addressable_entity, get_network_constants, get_user_secret_key,
267 };
268
269 fn get_entity_identifier() -> EntityIdentifier {
270 let secret_key = get_user_secret_key(None).unwrap();
271 let account = public_key_from_secret_key(&secret_key).unwrap();
272 let public_key = PublicKey::new(&account).unwrap();
273
274 EntityIdentifier::from_entity_under_public_key(public_key)
275 }
276
277 #[tokio::test]
278 async fn test_get_entity_with_none_values() {
279 let sdk = SDK::new(None, None, None);
281 let error_message = "failed to parse node address as valid URL";
282 let entity_identifier = get_entity_identifier();
283
284 let result = sdk
286 .get_entity(Some(entity_identifier), None, None, None, None)
287 .await;
288
289 assert!(result.is_err());
291 let err_string = result.err().unwrap().to_string();
292 assert!(err_string.contains(error_message));
293 }
294
295 #[tokio::test]
296 async fn test_get_entity_with_missing_entity() {
297 let sdk = SDK::new(None, None, None);
299 let error_message = "Error: Missing entity identifier";
300
301 let result = sdk.get_entity(None, None, None, None, None).await;
303
304 assert!(result.is_err());
306 let err_string = result.err().unwrap().to_string();
307 assert!(err_string.contains(error_message));
308 }
309
310 #[tokio::test]
311 async fn test_get_entity_with_entity_identifier() {
312 if !get_enable_addressable_entity() {
313 return;
314 }
315 let sdk = SDK::new(None, None, None);
317 let entity_identifier = get_entity_identifier();
318 let verbosity = Some(Verbosity::High);
319 let (rpc_address, _, _, _, _) = get_network_constants();
320
321 let result = sdk
323 .get_entity(
324 Some(entity_identifier),
325 None,
326 None,
327 verbosity,
328 Some(rpc_address),
329 )
330 .await;
331 assert!(result.is_ok());
333 let typed = GetAddressableEntityResult::from(result.unwrap().result).entity_result_typed();
334 assert_eq!(typed.variant(), "AddressableEntity");
335 assert!(typed.as_addressable_entity().is_some());
336 }
337
338 #[tokio::test]
339 async fn test_get_entity_with_entity_identifier_as_string() {
340 if !get_enable_addressable_entity() {
341 return;
342 }
343 let sdk = SDK::new(None, None, None);
345 let entity_identifier_as_string = get_entity_identifier().to_string();
346 let verbosity = Some(Verbosity::High);
347 let (rpc_address, _, _, _, _) = get_network_constants();
348
349 let result = sdk
351 .get_entity(
352 None,
353 Some(entity_identifier_as_string),
354 None,
355 verbosity,
356 Some(rpc_address),
357 )
358 .await;
359
360 assert!(result.is_ok());
362 }
363
364 #[tokio::test]
365 async fn test_get_entity_with_block_identifier() {
366 if !get_enable_addressable_entity() {
367 return;
368 }
369 let sdk = SDK::new(None, None, None);
371 let block_identifier =
372 BlockIdentifierInput::BlockIdentifier(BlockIdentifier::from_height(1));
373 let entity_identifier = get_entity_identifier();
374 let verbosity = Some(Verbosity::High);
375 let (rpc_address, _, _, _, _) = get_network_constants();
376
377 let result = sdk
379 .get_entity(
380 Some(entity_identifier),
381 None,
382 Some(block_identifier),
383 verbosity,
384 Some(rpc_address),
385 )
386 .await;
387
388 assert!(result.is_ok());
390 }
391
392 #[tokio::test]
393 async fn test_get_entity_with_error() {
394 let sdk = SDK::new(Some("http://localhost".to_string()), None, None);
396 let entity_identifier = get_entity_identifier();
397 let error_message = "error sending request";
398
399 let result = sdk
401 .get_entity(Some(entity_identifier), None, None, None, None)
402 .await;
403
404 assert!(result.is_err());
406 let err_string = result.err().unwrap().to_string();
407 assert!(err_string.contains(error_message));
408 }
409}