casper_rust_wasm_sdk/helpers/
mod.rs

1use crate::types::hash::account_hash::AccountHash;
2use crate::types::transaction_params::transaction_str_params::{DEFAULT_GAS_PRICE, DEFAULT_TTL};
3use crate::types::{key::Key, public_key::PublicKey, sdk_error::SdkError, verbosity::Verbosity};
4use base64::engine::general_purpose;
5use base64::Engine;
6use bigdecimal::BigDecimal;
7use blake2::{
8    digest::{Update, VariableOutput},
9    VarBlake2b,
10};
11use casper_client::cli::JsonArg;
12use casper_types::{
13    bytesrepr::ToBytes, cl_value_to_json as cl_value_to_json_from_casper_types, CLValue,
14    Key as CasperTypesKey, NamedArg, PublicKey as CasperTypesPublicKey, RuntimeArgs, SecretKey,
15    TimeDiff, Timestamp,
16};
17use chrono::{DateTime, SecondsFormat, Utc};
18#[cfg(target_arch = "wasm32")]
19use gloo_utils::format::JsValueSerdeExt;
20use serde::Serialize;
21use serde_json::Value;
22use std::str::FromStr;
23#[cfg(target_arch = "wasm32")]
24use wasm_bindgen::{JsCast, JsValue};
25
26pub const BLAKE2B_DIGEST_LENGTH: usize = 32;
27
28/// Converts a CLValue to a JSON Value.
29///
30/// # Arguments
31///
32/// * `cl_value` - The CLValue to convert.
33///
34/// # Returns
35///
36/// A JSON Value representing the CLValue data.
37pub fn cl_value_to_json(cl_value: &CLValue) -> Option<Value> {
38    cl_value_to_json_from_casper_types(cl_value)
39}
40
41/// Gets the current timestamp.
42///
43/// # Arguments
44///
45/// * `timestamp` - An optional timestamp value in milliseconds since the Unix epoch.
46///
47/// # Returns
48///
49/// A string containing the current timestamp in RFC3339 format.
50pub fn get_current_timestamp(timestamp: Option<String>) -> String {
51    let parsed_timestamp = timestamp.as_ref().and_then(|ts| ts.parse::<i64>().ok());
52    let current_timestamp = parsed_timestamp
53        .map(|parsed_time| DateTime::from_timestamp(parsed_time / 1000, 0).unwrap_or_else(Utc::now))
54        .unwrap_or_else(Utc::now);
55    current_timestamp.to_rfc3339_opts(SecondsFormat::Secs, true)
56}
57
58/// Computes the Blake2b hash of the provided metadata.
59///
60/// # Arguments
61///
62/// * `meta_data` - A reference to a string containing the metadata to be hashed.
63///
64/// # Returns
65///
66/// A hexadecimal string representing the Blake2b hash of the input metadata.
67pub fn get_blake2b_hash(meta_data: &str) -> String {
68    let mut result = [0; BLAKE2B_DIGEST_LENGTH];
69    let mut hasher = VarBlake2b::new(BLAKE2B_DIGEST_LENGTH).expect("should create hasher");
70
71    hasher.update(meta_data);
72    hasher.finalize_variable(|slice| {
73        result.copy_from_slice(slice);
74    });
75    hex::encode(result).to_lowercase()
76}
77
78/// Creates a dictionary item key by concatenating the serialized bytes of the key and value.
79///
80/// # Arguments
81///
82/// * `key` - The key to be serialized.
83/// * `value` - The value to be serialized.
84///
85/// # Returns
86///
87/// A hexadecimal-encoded string representing the dictionary item key.
88///
89/// # Panics
90///
91/// Panics if the hasher cannot be created.
92///
93/// # Example
94///
95/// ```rust
96/// use casper_types::{U256, U512};
97/// use casper_rust_wasm_sdk::helpers::make_dictionary_item_key;
98/// use casper_rust_wasm_sdk::types::key::Key;
99/// // Key / Value as U256
100/// let key = Key::from_formatted_str( "account-hash-e11bfffe63bf899ea07117af8a2bb43ef0078c0e38ebee6b6cb0b0e39c233538").unwrap();
101/// let value = U256::from(1);
102/// let dictionary_item_key = make_dictionary_item_key(&key, &value);
103/// println!("Dictionary Item Key (Key/Value as U256): {}", dictionary_item_key);
104/// assert_eq!(dictionary_item_key,"145f6211a24c0a8af16b47e7aa58431ea25172eb402903b3c25ac92b9784c7a9".to_string());
105/// // Key / Value as Key
106/// let key = Key::from_formatted_str( "account-hash-813428ce1a9805f1087db07e6017c6c4f5af0ee78a05591bb6577763e89b4f1f").unwrap();
107/// let value = Key::from_formatted_str("account-hash-e11bfffe63bf899ea07117af8a2bb43ef0078c0e38ebee6b6cb0b0e39c233538").unwrap();
108/// let dictionary_item_key = make_dictionary_item_key(&key, &value);
109/// println!("Dictionary Item Key (Key/Value as Key): {}", dictionary_item_key);
110/// assert_eq!(dictionary_item_key,"1e26dc82db208943c3785c0e11b9d78b9c408fee748c78dda5a5d016840dedca".to_string());
111/// ```
112pub fn make_dictionary_item_key<V: ToBytes>(key: &Key, value: &V) -> String {
113    let key: CasperTypesKey = CasperTypesKey::from(key.clone());
114    let mut bytes_a = key.to_bytes().unwrap_or_default();
115    let mut bytes_b = value.to_bytes().unwrap_or_default();
116
117    bytes_a.append(&mut bytes_b);
118
119    let mut result = [0; BLAKE2B_DIGEST_LENGTH];
120    let mut hasher = VarBlake2b::new(BLAKE2B_DIGEST_LENGTH).expect("should create hasher");
121
122    hasher.update(bytes_a);
123    hasher.finalize_variable(|slice| {
124        result.copy_from_slice(slice);
125    });
126    hex::encode(result)
127}
128
129/// Convert a formatted account hash to a base64-encoded Key as string (cep-18 key encoding).
130///
131/// # Arguments
132///
133/// * `formatted_account_hash` - A hex-formatted string representing the account hash.
134///
135/// Example: "account-hash-b485c074cef7ccaccd0302949d2043ab7133abdb14cfa87e8392945c0bd80a5f"
136///
137/// # Returns
138///
139/// Returns a `Result` with the base64-encoded string on success, or a `SdkError` on failure.
140/// Example: "ALSFwHTO98yszQMClJ0gQ6txM6vbFM+ofoOSlFwL2Apf"
141pub fn get_base64_key_from_account_hash(account_hash: &str) -> Result<String, SdkError> {
142    let account_hash = AccountHash::from_formatted_str(account_hash)?;
143    let key = Key::from_account(account_hash).to_bytes().unwrap();
144    Ok(general_purpose::STANDARD.encode(key)) // base64.encode
145}
146
147/// Converts a formatted key hash to a base64-encoded string (CEP-18 key encoding).
148///
149/// # Arguments
150///
151/// * `formatted_hash` - A hex-formatted string representing the key hash.
152///   Example: "hash-b485c074cef7ccaccd0302949d2043ab7133abdb14cfa87e8392945c0bd80a5f"
153///
154/// # Returns
155///
156/// Returns a `Result` containing the base64-encoded string on success.
157/// Example: "AbSFwHTO98yszQMClJ0gQ6txM6vbFM+ofoOSlFwL2Apf"
158///
159/// # Errors
160///
161/// This function returns an error if:
162/// - The input string is not a valid formatted key hash.
163/// - The conversion to bytes or base64 encoding fails.
164pub fn get_base64_key_from_key_hash(formatted_hash: &str) -> Result<String, Box<SdkError>> {
165    let key = Key::from_formatted_str(formatted_hash)?;
166    let key = key.to_bytes().unwrap();
167    Ok(general_purpose::STANDARD.encode(key)) // base64.encode
168}
169
170/// Gets the time to live (TTL) value or returns the default value if not provided.
171///
172/// # Arguments
173///
174/// * `ttl` - An optional TTL value as a string.
175///
176/// # Returns
177///
178/// A string containing the TTL value or the default TTL if not provided.
179pub fn get_ttl_or_default(ttl: Option<&str>) -> String {
180    if let Some(ttl) = ttl {
181        ttl.to_string()
182    } else {
183        DEFAULT_TTL.to_string()
184    }
185}
186
187/// Parses a timestamp string into a `Timestamp` object.
188///
189/// # Arguments
190///
191/// * `value` - The timestamp string to parse.
192///
193/// # Returns
194///
195/// A `Result` containing the parsed `Timestamp` or an error if parsing fails.
196pub fn parse_timestamp(value: &str) -> Result<Timestamp, SdkError> {
197    Timestamp::from_str(value).map_err(|error| SdkError::FailedToParseTimestamp {
198        context: "timestamp",
199        error,
200    })
201}
202
203/// Parses a TTL (time to live) string into a `TimeDiff` object.
204///
205/// # Arguments
206///
207/// * `value` - The TTL string to parse.
208///
209/// # Returns
210///
211/// A `Result` containing the parsed `TimeDiff` or an error if parsing fails.
212pub fn parse_ttl(value: &str) -> Result<TimeDiff, SdkError> {
213    TimeDiff::from_str(value).map_err(|error| SdkError::FailedToParseTimeDiff {
214        context: "ttl",
215        error,
216    })
217}
218
219/// Gets the gas price or returns the default value if not provided.
220///
221/// # Arguments
222///
223/// * `gas_price` - An optional gas price value.
224///
225/// # Returns
226///
227/// The gas price or the default gas price if not provided.
228pub fn get_gas_price_or_default(gas_price: Option<u64>) -> u64 {
229    gas_price.unwrap_or(DEFAULT_GAS_PRICE)
230}
231
232/// Gets the value as a string or returns an empty string if not provided.
233///
234/// # Arguments
235///
236/// * `opt_str` - An optional string value.
237///
238/// # Returns
239///
240/// The string value or an empty string if not provided.
241pub(crate) fn get_str_or_default(opt_str: Option<&String>) -> &str {
242    opt_str.map(String::as_str).unwrap_or_default()
243}
244
245/// Generates a secret key using the Ed25519 algorithm.
246///
247/// # Returns
248///
249/// A `Result` containing the generated secret key or an error if the generation fails.
250///
251/// # Errors
252///
253/// Returns an `SdkError` if the secret key generation fails.
254pub fn secret_key_generate() -> Result<SecretKey, SdkError> {
255    SecretKey::generate_ed25519().map_err(|err| SdkError::FailedToGenerateSecretKey {
256        context: "secret_key_from_pem".to_string(),
257        error: err,
258    })
259}
260
261/// Generates a secret key using the secp256k1 algorithm.
262///
263/// # Returns
264///
265/// A `Result` containing the generated secret key or an error if the generation fails.
266///
267/// # Errors
268///
269/// Returns an `SdkError` if the secret key generation fails.
270pub fn secret_key_secp256k1_generate() -> Result<SecretKey, SdkError> {
271    SecretKey::generate_secp256k1().map_err(|err| SdkError::FailedToGenerateSecretKey {
272        context: "secret_key_from_pem".to_string(),
273        error: err,
274    })
275}
276
277/// Parses a secret key in PEM format into a `SecretKey` object.
278///
279/// # Arguments
280///
281/// * `secret_key` - The secret key in PEM format.
282///
283/// # Returns
284///
285/// A `Result` containing the parsed `SecretKey` or an error if parsing fails.
286pub fn secret_key_from_pem(secret_key: &str) -> Result<SecretKey, SdkError> {
287    SecretKey::from_pem(secret_key).map_err(|err| SdkError::FailedToParseSecretKey {
288        context: "secret_key_from_pem".to_string(),
289        error: err,
290    })
291}
292
293/// Converts a secret key in PEM format to its corresponding public key as a string.
294///
295/// # Arguments
296///
297/// * `secret_key` - The secret key in PEM format.
298///
299/// # Returns
300///
301/// A `Result` containing the public key as a string or an error if the conversion fails.
302pub fn public_key_from_secret_key(secret_key: &str) -> Result<String, SdkError> {
303    // Handle the secret key parsing and map the error
304    let secret_key_from_pem = secret_key_from_pem(secret_key)?;
305
306    // Convert the secret key to public key and handle potential errors
307    let public_key = CasperTypesPublicKey::from(&secret_key_from_pem);
308
309    // Convert to desired public key format
310    let public_key_test: PublicKey = public_key.into();
311
312    // Return the public key as a string
313    Ok(public_key_test.to_string())
314}
315
316/// Converts a hexadecimal string to a vector of unsigned 8-bit integers (Uint8Array).
317///
318/// # Arguments
319///
320/// * `hex_string` - The hexadecimal string to convert.
321///
322/// # Returns
323///
324/// A vector of unsigned 8-bit integers (Uint8Array) containing the converted value.
325pub fn hex_to_uint8_vec(hex_string: &str) -> Vec<u8> {
326    let mut bytes = Vec::with_capacity(hex_string.len() / 2);
327    let mut hex_chars = hex_string.chars();
328    while let (Some(a), Some(b)) = (hex_chars.next(), hex_chars.next()) {
329        if let Ok(byte) = u8::from_str_radix(&format!("{}{}", a, b), 16) {
330            bytes.push(byte);
331        } else {
332            // If an invalid hex pair is encountered, return an empty vector.
333            return Vec::new();
334        }
335    }
336    bytes
337}
338
339/// Converts a hexadecimal string to a regular string.
340///
341/// # Arguments
342///
343/// * `hex_string` - The hexadecimal string to convert.
344///
345/// # Returns
346///
347/// A regular string containing the converted value.
348pub fn hex_to_string(hex_string: &str) -> String {
349    match hex::decode(hex_string) {
350        Ok(bytes) => String::from_utf8_lossy(&bytes).to_string(),
351        Err(_) => hex_string.to_string(),
352    }
353}
354
355/// Converts motes to CSPR (Casper tokens).
356///
357/// # Arguments
358///
359/// * `motes` - The motes value to convert.
360///
361/// # Returns
362///
363/// A string representing the CSPR amount.
364pub fn motes_to_cspr(motes: &str) -> Result<String, SdkError> {
365    match BigDecimal::from_str(motes) {
366        Ok(motes_decimal) => {
367            let divisor = BigDecimal::from(1_000_000_000);
368            let cspr_decimal = &motes_decimal / divisor;
369            let formatted_cspr = format!("{:.2}", cspr_decimal);
370
371            if formatted_cspr.ends_with(".00") {
372                Ok(formatted_cspr.replace(".00", ""))
373            } else {
374                Ok(formatted_cspr)
375            }
376        }
377        Err(err) => Err(SdkError::CustomError {
378            context: "Failed to parse input as BigDecimal",
379            error: format!("{:?}", err),
380        }),
381    }
382}
383
384/// Pretty prints a serializable value as a JSON string.
385///
386/// # Arguments
387///
388/// * `value` - The serializable value to pretty print.
389/// * `verbosity` - An optional verbosity level for pretty printing.
390///
391/// # Returns
392///
393/// A JSON string representing the pretty printed value.
394pub fn json_pretty_print<T>(value: T, verbosity: Option<Verbosity>) -> Result<String, SdkError>
395where
396    T: Serialize,
397{
398    let deserialized = serde_json::to_value(&value).map_err(SdkError::from)?;
399
400    match verbosity {
401        Some(Verbosity::Low) | None => Ok(deserialized.to_string()),
402        Some(Verbosity::Medium) => {
403            casper_types::json_pretty_print(&deserialized).map_err(|err| SdkError::CustomError {
404                context: "Error in json_pretty_print",
405                error: format!("{}", err),
406            })
407        }
408        Some(Verbosity::High) => {
409            serde_json::to_string_pretty(&deserialized).map_err(SdkError::from)
410        }
411    }
412}
413
414/// Inserts a JavaScript value argument into a RuntimeArgs map.
415///
416/// # Arguments
417///
418/// * `args` - The RuntimeArgs map to insert the argument into.
419/// * `js_value_arg` - The JavaScript value argument to insert.
420///
421/// # Returns
422///
423/// The modified `RuntimeArgs` map.
424#[cfg(target_arch = "wasm32")]
425pub fn insert_js_value_arg(
426    args: &mut RuntimeArgs,
427    js_value_arg: JsValue,
428) -> Result<&RuntimeArgs, SdkError> {
429    if js_sys::Object::instanceof(&js_value_arg) {
430        let json_arg: JsonArg = js_value_arg
431            .into_serde()
432            .map_err(|err| SdkError::CustomError {
433                context: "Error converting to JsonArg",
434                error: format!("{:?}", err),
435            })?;
436
437        let named_arg = NamedArg::try_from(json_arg).map_err(|err| SdkError::CustomError {
438            context: "Error converting to NamedArg",
439            error: format!("{:?}", err),
440        })?;
441
442        args.insert_cl_value(named_arg.name(), named_arg.cl_value().clone());
443    } else if let Some(string_arg) = js_value_arg.as_string() {
444        let simple_arg = string_arg;
445        casper_client::cli::insert_arg(&simple_arg, args).map_err(|err| SdkError::CustomError {
446            context: "Error inserting simple arg",
447            error: format!("{:?}", err),
448        })?;
449    } else {
450        return Err(SdkError::CustomError {
451            context: "Error converting to JsonArg or Simple Arg",
452            error: String::from("Conversion failed"),
453        });
454    }
455
456    Ok(args)
457}
458
459/// Inserts an argument into a RuntimeArgs map.
460///
461/// # Arguments
462///
463/// * `args` - The RuntimeArgs map to insert the argument into.
464/// * `new_arg` - The argument as a string.
465///
466/// # Returns
467///
468/// The modified `RuntimeArgs` map.
469pub(crate) fn insert_arg(args: &mut RuntimeArgs, new_arg: String) -> &RuntimeArgs {
470    match serde_json::from_str::<JsonArg>(&new_arg) {
471        Ok(json_arg) => {
472            if let Ok(named_arg) = NamedArg::try_from(json_arg.clone()) {
473                // JSON args
474                args.insert_cl_value(named_arg.name(), named_arg.cl_value().clone());
475            }
476        }
477        Err(_) => {
478            // Simple args
479            let _ = casper_client::cli::insert_arg(&new_arg, args);
480        }
481    }
482    args
483}
484
485#[cfg(test)]
486mod tests {
487    use super::*;
488    use casper_types::U256;
489
490    #[test]
491    fn test_cl_value_to_json() {
492        let cl_value = CLValue::from_t((1, 2, 3)).unwrap();
493        let json_value = cl_value_to_json(&cl_value).unwrap();
494        assert_eq!(
495            json_value,
496            Value::Array(vec![
497                Value::Number(1.into()),
498                Value::Number(2.into()),
499                Value::Number(3.into())
500            ])
501        );
502    }
503
504    #[test]
505    fn test_get_current_timestamp() {
506        let timestamp = Some("1234567890".to_string());
507        let current_timestamp = get_current_timestamp(timestamp);
508        assert_eq!(&current_timestamp, "1970-01-15T06:56:07Z");
509    }
510
511    #[test]
512    fn test_get_blake2b_hash() {
513        let metadata = "some metadata";
514        let hash = get_blake2b_hash(metadata);
515        assert_eq!(
516            &hash,
517            "767de9efccc76bc0eef85ea81fcaa56dc7047e660c74b3dc39f84ab8c4931c0d"
518        );
519    }
520
521    #[test]
522    fn test_get_ttl_or_default() {
523        let ttl = Some("1h".to_string());
524        let ttl_value = get_ttl_or_default(ttl.as_deref());
525        assert_eq!(ttl_value, "1h".to_string());
526
527        let default_ttl = get_ttl_or_default(None);
528        assert_eq!(default_ttl, DEFAULT_TTL.to_string());
529    }
530
531    #[test]
532    fn test_parse_timestamp() {
533        let valid_timestamp = "2023-11-06T12:00:00Z";
534        let parsed_timestamp = parse_timestamp(valid_timestamp);
535        assert!(parsed_timestamp.is_ok());
536
537        let invalid_timestamp = "invalid_timestamp";
538        let parsed_timestamp = parse_timestamp(invalid_timestamp);
539        assert!(parsed_timestamp.is_err());
540    }
541
542    #[test]
543    fn test_parse_ttl() {
544        let valid_ttl = "1h";
545        let parsed_ttl = parse_ttl(valid_ttl);
546        assert!(parsed_ttl.is_ok());
547
548        let invalid_ttl = "invalid_ttl";
549        let parsed_ttl = parse_ttl(invalid_ttl);
550        assert!(parsed_ttl.is_err());
551    }
552
553    #[test]
554    fn test_get_gas_price_or_default() {
555        let gas_price = Some(100);
556        let price = get_gas_price_or_default(gas_price);
557        assert_eq!(price, 100);
558
559        let default_price = get_gas_price_or_default(None);
560        assert_eq!(default_price, DEFAULT_GAS_PRICE);
561    }
562
563    #[test]
564    fn test_get_str_or_default() {
565        let input_str = Some("test_string".to_string());
566        let result = get_str_or_default(input_str.as_ref());
567        assert_eq!(result, "test_string");
568
569        let default_str: Option<String> = None;
570        let result = get_str_or_default(default_str.as_ref());
571        assert_eq!(result, "");
572    }
573
574    #[test]
575    fn test_secret_key_generate() {
576        // Act
577        let result = secret_key_generate();
578
579        // Assert
580        assert!(result.is_ok());
581        let secret_key = result.unwrap();
582        assert_eq!(&secret_key.to_string(), "SecretKey::Ed25519");
583    }
584
585    #[test]
586    fn test_secret_key_secp256k1_generate() {
587        // Act
588        let result = secret_key_secp256k1_generate();
589
590        // Assert
591        assert!(result.is_ok());
592        let secret_key = result.unwrap();
593        assert_eq!(&secret_key.to_string(), "SecretKey::Secp256k1");
594    }
595
596    #[test]
597    fn test_secret_key_from_pem() {
598        let pem_key = "-----BEGIN PRIVATE KEY-----\nTEST\n-----END PRIVATE KEY-----";
599        let result = secret_key_from_pem(pem_key);
600        assert!(result.is_err());
601        let pem_key =
602        "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEII8ULlk1CJ12ZQ+bScjBt/IxMAZNggClWqK56D1/7CbI\n-----END PRIVATE KEY-----";
603        let result = secret_key_from_pem(pem_key);
604        assert!(result.is_ok());
605        assert_eq!(&result.unwrap().to_string(), "SecretKey::Ed25519");
606    }
607
608    #[test]
609    fn test_public_key_from_secret_key() {
610        let pem_key = "-----BEGIN PRIVATE KEY-----\nTEST\n-----END PRIVATE KEY-----";
611        let result = public_key_from_secret_key(pem_key);
612        assert!(result.is_err());
613        let pem_key =
614        "-----BEGIN PRIVATE KEY-----\nMC4CAQAwBQYDK2VwBCIEII8ULlk1CJ12ZQ+bScjBt/IxMAZNggClWqK56D1/7CbI-----END PRIVATE KEY-----";
615        let result = public_key_from_secret_key(pem_key);
616        assert!(result.is_ok());
617        assert_eq!(
618            result.unwrap(),
619            "01aff5c18a954604dd27d139d8e0cfc533ac3d53784d76c7a7ac5ff4039510fdf6"
620        );
621    }
622
623    #[test]
624    fn test_hex_to_uint8_vec() {
625        let hex_string = "0161e40005434ba3cd9a791a2827f5fa3ee514d1475fe72b2823cbaac9c3c71483";
626        let result = hex_to_uint8_vec(hex_string);
627        assert_eq!(
628            result,
629            vec![
630                1, 97, 228, 0, 5, 67, 75, 163, 205, 154, 121, 26, 40, 39, 245, 250, 62, 229, 20,
631                209, 71, 95, 231, 43, 40, 35, 203, 170, 201, 195, 199, 20, 131
632            ]
633        );
634    }
635
636    #[test]
637    fn test_hex_to_string() {
638        let hex_string = "48656c6c6f20436173706572";
639        let result = hex_to_string(hex_string);
640        assert_eq!(result, "Hello Casper");
641    }
642
643    #[test]
644    fn test_motes_to_cspr() {
645        let motes = "1000000000";
646        let result = motes_to_cspr(motes).unwrap();
647        assert_eq!(result, "1");
648    }
649
650    #[test]
651    fn test_json_pretty_print() {
652        #[derive(Serialize, Clone)]
653        struct TestData {
654            age: i32,
655            name: String,
656        }
657
658        let data = TestData {
659            age: 42,
660            name: "Joe".to_string(),
661        };
662
663        let result = json_pretty_print(data.clone(), None).unwrap();
664        assert_eq!(result, "{\"age\":42,\"name\":\"Joe\"}");
665
666        let result = json_pretty_print(data.clone(), Some(Verbosity::Low)).unwrap();
667        assert_eq!(result, "{\"age\":42,\"name\":\"Joe\"}");
668
669        let result = json_pretty_print(data.clone(), Some(Verbosity::Medium)).unwrap();
670        assert_eq!(result, "{\n  \"age\": 42,\n  \"name\": \"Joe\"\n}");
671
672        let result = json_pretty_print(data, Some(Verbosity::High)).unwrap();
673        assert_eq!(result, "{\n  \"age\": 42,\n  \"name\": \"Joe\"\n}");
674    }
675
676    #[test]
677    fn test_insert_arg_simple() {
678        let mut args = RuntimeArgs::new();
679        let new_arg = "message:String='Hello Casper";
680        let result_args = insert_arg(&mut args, new_arg.to_string());
681        assert_eq!(result_args.len(), 1);
682        let cl_value = result_args.get("message").unwrap();
683        let json = cl_value_to_json(cl_value).unwrap();
684        let expexted_json = Value::String("Hello Casper".to_string());
685        assert_eq!(json, expexted_json);
686    }
687
688    #[test]
689    fn test_insert_arg_json() {
690        let mut args = RuntimeArgs::new();
691        let arg_json = r#"{"name": "bar", "type": "U256", "value": 1}"#; // No brackets only one arg
692        let result_args = insert_arg(&mut args, arg_json.to_string());
693        assert_eq!(result_args.len(), 1);
694        let cl_value = result_args.get("bar").unwrap();
695        let json = cl_value_to_json(cl_value).unwrap();
696        let expexted_json = Value::String("1".to_string());
697        assert_eq!(json, expexted_json);
698    }
699
700    #[test]
701    pub fn test_make_dictionary_item_key() {
702        let key = Key::from_formatted_str(
703            "account-hash-e11bfffe63bf899ea07117af8a2bb43ef0078c0e38ebee6b6cb0b0e39c233538",
704        )
705        .unwrap();
706        let value = U256::from(1);
707        let dictionary_item_key = make_dictionary_item_key(&key, &value);
708        assert_eq!(
709            dictionary_item_key,
710            "145f6211a24c0a8af16b47e7aa58431ea25172eb402903b3c25ac92b9784c7a9".to_string()
711        );
712        let key = Key::from_formatted_str(
713            "account-hash-813428ce1a9805f1087db07e6017c6c4f5af0ee78a05591bb6577763e89b4f1f",
714        )
715        .unwrap();
716        let value = Key::from_formatted_str(
717            "account-hash-e11bfffe63bf899ea07117af8a2bb43ef0078c0e38ebee6b6cb0b0e39c233538",
718        )
719        .unwrap();
720        let dictionary_item_key = make_dictionary_item_key(&key, &value);
721        assert_eq!(
722            dictionary_item_key,
723            "1e26dc82db208943c3785c0e11b9d78b9c408fee748c78dda5a5d016840dedca".to_string()
724        );
725    }
726
727    #[test]
728    fn test_get_base64_key_from_account_hash() {
729        // Test with a known input and expected output
730        let input_hash =
731            "account-hash-b485c074cef7ccaccd0302949d2043ab7133abdb14cfa87e8392945c0bd80a5f";
732        let expected_output = "ALSFwHTO98yszQMClJ0gQ6txM6vbFM+ofoOSlFwL2Apf";
733
734        // Call the function under test
735        let result = get_base64_key_from_account_hash(input_hash).unwrap();
736
737        // Check the result against the expected output
738        assert_eq!(result, expected_output.to_string());
739    }
740
741    #[test]
742    fn test_get_base64_key_from_key_hash() {
743        // Test with a known input and expected output
744        let input_hash = "hash-b485c074cef7ccaccd0302949d2043ab7133abdb14cfa87e8392945c0bd80a5f";
745        let expected_output = "AbSFwHTO98yszQMClJ0gQ6txM6vbFM+ofoOSlFwL2Apf";
746
747        // Call the function under test
748        let result = get_base64_key_from_key_hash(input_hash).unwrap();
749
750        // Check the result against the expected output
751        assert_eq!(result, expected_output.to_string());
752    }
753}