//! `Pubkey` Javascript interface #![cfg(target_arch = "wasm32")] #![allow(non_snake_case)] use { crate::{pubkey::*, wasm::display_to_jsvalue}, js_sys::{Array, Uint8Array}, wasm_bindgen::{prelude::*, JsCast}, }; fn js_value_to_seeds_vec(array_of_uint8_arrays: &[JsValue]) -> Result>, JsValue> { let vec_vec_u8 = array_of_uint8_arrays .iter() .filter_map(|u8_array| { u8_array .dyn_ref::() .map(|u8_array| u8_array.to_vec()) }) .collect::>(); if vec_vec_u8.len() != array_of_uint8_arrays.len() { Err("Invalid Array of Uint8Arrays".into()) } else { Ok(vec_vec_u8) } } #[wasm_bindgen] impl Pubkey { /// Create a new Pubkey object /// /// * `value` - optional public key as a base58 encoded string, `Uint8Array`, `[number]` #[wasm_bindgen(constructor)] pub fn constructor(value: JsValue) -> Result { if let Some(base58_str) = value.as_string() { base58_str.parse::().map_err(display_to_jsvalue) } else if let Some(uint8_array) = value.dyn_ref::() { Ok(Pubkey::new(&uint8_array.to_vec())) } else if let Some(array) = value.dyn_ref::() { let mut bytes = vec![]; let iterator = js_sys::try_iter(&array.values())?.expect("array to be iterable"); for x in iterator { let x = x?; if let Some(n) = x.as_f64() { if n >= 0. && n <= 255. { bytes.push(n as u8); continue; } } return Err(format!("Invalid array argument: {:?}", x).into()); } Ok(Pubkey::new(&bytes)) } else if value.is_undefined() { Ok(Pubkey::default()) } else { Err("Unsupported argument".into()) } } /// Return the base58 string representation of the public key pub fn toString(&self) -> String { self.to_string() } /// Check if a `Pubkey` is on the ed25519 curve. pub fn isOnCurve(&self) -> bool { self.is_on_curve() } /// Checks if two `Pubkey`s are equal pub fn equals(&self, other: &Pubkey) -> bool { self == other } /// Return the `Uint8Array` representation of the public key pub fn toBytes(&self) -> Box<[u8]> { self.0.clone().into() } /// Derive a Pubkey from another Pubkey, string seed, and a program id pub fn createWithSeed(base: &Pubkey, seed: &str, owner: &Pubkey) -> Result { Pubkey::create_with_seed(base, seed, owner).map_err(display_to_jsvalue) } /// Derive a program address from seeds and a program id pub fn createProgramAddress( seeds: Box<[JsValue]>, program_id: &Pubkey, ) -> Result { let seeds_vec = js_value_to_seeds_vec(&seeds)?; let seeds_slice = seeds_vec .iter() .map(|seed| seed.as_slice()) .collect::>(); Pubkey::create_program_address(seeds_slice.as_slice(), program_id) .map_err(display_to_jsvalue) } /// Find a valid program address /// /// Returns: /// * `[PubKey, number]` - the program address and bump seed pub fn findProgramAddress( seeds: Box<[JsValue]>, program_id: &Pubkey, ) -> Result { let seeds_vec = js_value_to_seeds_vec(&seeds)?; let seeds_slice = seeds_vec .iter() .map(|seed| seed.as_slice()) .collect::>(); let (address, bump_seed) = Pubkey::find_program_address(seeds_slice.as_slice(), program_id); let result = Array::new_with_length(2); result.set(0, address.into()); result.set(1, bump_seed.into()); Ok(result.into()) } }