casper_rust_wasm_sdk/sdk/rpcs/
get_entity.rs1#[cfg(target_arch = "wasm32")]
2use crate::types::identifier::block_identifier::BlockIdentifier;
3use crate::{
4 types::{
5 identifier::{block_identifier::BlockIdentifierInput, entity_identifier::EntityIdentifier},
6 sdk_error::SdkError,
7 verbosity::Verbosity,
8 },
9 SDK,
10};
11use casper_client::{
12 cli::{get_entity as get_entity_cli, parse::entity_identifier as parse_entity_identifier},
13 get_entity as get_entity_lib,
14 rpcs::results::GetAddressableEntityResult as _GetAddressableEntityResult,
15 JsonRpcId, SuccessResponse,
16};
17#[cfg(target_arch = "wasm32")]
18use gloo_utils::format::JsValueSerdeExt;
19use rand::Rng;
20#[cfg(target_arch = "wasm32")]
21use serde::{Deserialize, Serialize};
22#[cfg(target_arch = "wasm32")]
23use wasm_bindgen::prelude::*;
24
25#[cfg(target_arch = "wasm32")]
27#[derive(Debug, Deserialize, Clone, Serialize)]
28#[wasm_bindgen]
29pub struct GetAddressableEntityResult(_GetAddressableEntityResult);
30
31#[cfg(target_arch = "wasm32")]
33impl From<GetAddressableEntityResult> for _GetAddressableEntityResult {
34 fn from(result: GetAddressableEntityResult) -> Self {
35 result.0
36 }
37}
38
39#[cfg(target_arch = "wasm32")]
40impl From<_GetAddressableEntityResult> for GetAddressableEntityResult {
41 fn from(result: _GetAddressableEntityResult) -> Self {
42 GetAddressableEntityResult(result)
43 }
44}
45
46#[cfg(target_arch = "wasm32")]
47#[wasm_bindgen]
48impl GetAddressableEntityResult {
49 #[wasm_bindgen(getter)]
51 pub fn api_version(&self) -> JsValue {
52 JsValue::from_serde(&self.0.api_version).unwrap()
53 }
54
55 #[wasm_bindgen(getter)]
56 pub fn entity_result(&self) -> JsValue {
57 JsValue::from_serde(&self.0.entity_result).unwrap()
58 }
59
60 #[wasm_bindgen(getter)]
61 pub fn merkle_proof(&self) -> String {
62 self.0.merkle_proof.clone()
63 }
64
65 #[wasm_bindgen(js_name = "toJson")]
66 pub fn to_json(&self) -> JsValue {
67 JsValue::from_serde(&self.0).unwrap_or(JsValue::null())
68 }
69}
70
71#[derive(Debug, Deserialize, Clone, Default, Serialize)]
73#[cfg(target_arch = "wasm32")]
74#[wasm_bindgen(js_name = "getEntityOptions", getter_with_clone)]
75pub struct GetEntityOptions {
76 pub entity_identifier: Option<EntityIdentifier>,
77 pub entity_identifier_as_string: Option<String>,
78 pub maybe_block_id_as_string: Option<String>,
79 pub maybe_block_identifier: Option<BlockIdentifier>,
80 pub rpc_address: Option<String>,
81 pub verbosity: Option<Verbosity>,
82}
83
84#[cfg(target_arch = "wasm32")]
85#[wasm_bindgen]
86impl SDK {
87 pub fn get_entity_options(&self, options: JsValue) -> Result<GetEntityOptions, JsError> {
89 options
90 .into_serde::<GetEntityOptions>()
91 .map_err(|err| JsError::new(&format!("Error deserializing options: {:?}", err)))
92 }
93
94 #[wasm_bindgen(js_name = "get_entity")]
117 pub async fn get_entity_js_alias(
118 &self,
119 options: Option<GetEntityOptions>,
120 ) -> Result<GetAddressableEntityResult, JsError> {
121 let GetEntityOptions {
122 entity_identifier,
123 entity_identifier_as_string,
124 maybe_block_id_as_string,
125 maybe_block_identifier,
126 verbosity,
127 rpc_address,
128 } = options.unwrap_or_default();
129
130 let maybe_block_identifier = if let Some(maybe_block_identifier) = maybe_block_identifier {
131 Some(BlockIdentifierInput::BlockIdentifier(
132 maybe_block_identifier,
133 ))
134 } else {
135 maybe_block_id_as_string.map(BlockIdentifierInput::String)
136 };
137
138 let result = self
139 .get_entity(
140 entity_identifier,
141 entity_identifier_as_string,
142 maybe_block_identifier,
143 verbosity,
144 rpc_address,
145 )
146 .await;
147 match result {
148 Ok(data) => Ok(data.result.into()),
149 Err(err) => {
150 let err = &format!("Error occurred with {:?}", err);
151 Err(JsError::new(err))
152 }
153 }
154 }
155
156 #[wasm_bindgen(js_name = "state_get_entity")]
158 pub async fn state_get_entity(
159 &self,
160 options: Option<GetEntityOptions>,
161 ) -> Result<GetAddressableEntityResult, JsError> {
162 self.get_entity_js_alias(options).await
163 }
164}
165
166impl SDK {
167 pub async fn get_entity(
185 &self,
186 entity_identifier: Option<EntityIdentifier>,
187 entity_identifier_as_string: Option<String>,
188 maybe_block_identifier: Option<BlockIdentifierInput>,
189 verbosity: Option<Verbosity>,
190 rpc_address: Option<String>,
191 ) -> Result<SuccessResponse<_GetAddressableEntityResult>, SdkError> {
192 let entity_identifier = if let Some(entity_identifier) = entity_identifier {
193 entity_identifier
194 } else if let Some(entity_identifier_as_string) = entity_identifier_as_string.clone() {
195 match parse_entity_identifier(&entity_identifier_as_string) {
196 Ok(parsed) => parsed.into(),
197 Err(err) => {
198 return Err(err.into());
199 }
200 }
201 } else {
202 let err = "Error: Missing entity identifier".to_string();
203 return Err(SdkError::InvalidArgument {
204 context: "get_entity",
205 error: err,
206 });
207 };
208 if let Some(BlockIdentifierInput::String(maybe_block_id)) = maybe_block_identifier {
209 get_entity_cli(
210 &rand::thread_rng().gen::<u64>().to_string(),
211 &self.get_rpc_address(rpc_address),
212 self.get_verbosity(verbosity).into(),
213 &maybe_block_id,
214 &entity_identifier.to_string(),
215 )
216 .await
217 .map_err(SdkError::from)
218 } else {
219 let maybe_block_identifier =
220 if let Some(BlockIdentifierInput::BlockIdentifier(maybe_block_identifier)) =
221 maybe_block_identifier
222 {
223 Some(maybe_block_identifier)
224 } else {
225 None
226 };
227 get_entity_lib(
228 JsonRpcId::from(rand::thread_rng().gen::<u64>().to_string()),
229 &self.get_rpc_address(rpc_address),
230 self.get_verbosity(verbosity).into(),
231 maybe_block_identifier.map(Into::into),
232 entity_identifier.into(),
233 )
234 .await
235 .map_err(SdkError::from)
236 }
237 }
238}
239
240#[cfg(test)]
241mod tests {
242 use super::*;
243 use crate::{
244 helpers::public_key_from_secret_key,
245 types::{identifier::block_identifier::BlockIdentifier, public_key::PublicKey},
246 };
247 use sdk_tests::tests::helpers::{
248 get_enable_addressable_entity, get_network_constants, get_user_secret_key,
249 };
250
251 fn get_entity_identifier() -> EntityIdentifier {
252 let secret_key = get_user_secret_key(None).unwrap();
253 let account = public_key_from_secret_key(&secret_key).unwrap();
254 let public_key = PublicKey::new(&account).unwrap();
255
256 EntityIdentifier::from_entity_under_public_key(public_key)
257 }
258
259 #[tokio::test]
260 async fn test_get_entity_with_none_values() {
261 let sdk = SDK::new(None, None, None);
263 let error_message = "failed to parse node address as valid URL";
264 let entity_identifier = get_entity_identifier();
265
266 let result = sdk
268 .get_entity(Some(entity_identifier), None, None, None, None)
269 .await;
270
271 assert!(result.is_err());
273 let err_string = result.err().unwrap().to_string();
274 assert!(err_string.contains(error_message));
275 }
276
277 #[tokio::test]
278 async fn test_get_entity_with_missing_entity() {
279 let sdk = SDK::new(None, None, None);
281 let error_message = "Error: Missing entity identifier";
282
283 let result = sdk.get_entity(None, None, None, None, None).await;
285
286 assert!(result.is_err());
288 let err_string = result.err().unwrap().to_string();
289 assert!(err_string.contains(error_message));
290 }
291
292 #[tokio::test]
293 async fn test_get_entity_with_entity_identifier() {
294 if !get_enable_addressable_entity() {
295 return;
296 }
297 let sdk = SDK::new(None, None, None);
299 let entity_identifier = get_entity_identifier();
300 let verbosity = Some(Verbosity::High);
301 let (rpc_address, _, _, _, _) = get_network_constants();
302
303 let result = sdk
305 .get_entity(
306 Some(entity_identifier),
307 None,
308 None,
309 verbosity,
310 Some(rpc_address),
311 )
312 .await;
313 assert!(result.is_ok());
315 }
316
317 #[tokio::test]
318 async fn test_get_entity_with_entity_identifier_as_string() {
319 if !get_enable_addressable_entity() {
320 return;
321 }
322 let sdk = SDK::new(None, None, None);
324 let entity_identifier_as_string = get_entity_identifier().to_string();
325 let verbosity = Some(Verbosity::High);
326 let (rpc_address, _, _, _, _) = get_network_constants();
327
328 let result = sdk
330 .get_entity(
331 None,
332 Some(entity_identifier_as_string),
333 None,
334 verbosity,
335 Some(rpc_address),
336 )
337 .await;
338
339 assert!(result.is_ok());
341 }
342
343 #[tokio::test]
344 async fn test_get_entity_with_block_identifier() {
345 if !get_enable_addressable_entity() {
346 return;
347 }
348 let sdk = SDK::new(None, None, None);
350 let block_identifier =
351 BlockIdentifierInput::BlockIdentifier(BlockIdentifier::from_height(1));
352 let entity_identifier = get_entity_identifier();
353 let verbosity = Some(Verbosity::High);
354 let (rpc_address, _, _, _, _) = get_network_constants();
355
356 let result = sdk
358 .get_entity(
359 Some(entity_identifier),
360 None,
361 Some(block_identifier),
362 verbosity,
363 Some(rpc_address),
364 )
365 .await;
366
367 assert!(result.is_ok());
369 }
370
371 #[tokio::test]
372 async fn test_get_entity_with_error() {
373 let sdk = SDK::new(Some("http://localhost".to_string()), None, None);
375 let entity_identifier = get_entity_identifier();
376 let error_message = "error sending request for url (http://localhost/rpc)";
377
378 let result = sdk
380 .get_entity(Some(entity_identifier), None, None, None, None)
381 .await;
382
383 assert!(result.is_err());
385 let err_string = result.err().unwrap().to_string();
386 assert!(err_string.contains(error_message));
387 }
388}