lwk_wasm 0.11.0

Liquid Wallet Kit - WASM
Documentation
use std::{
    collections::{BTreeSet, HashSet},
    str::FromStr,
};

use crate::Error;
use lwk_wollet::elements;
use wasm_bindgen::prelude::*;

/// A valid asset identifier. wrapper of [`elements::AssetId`]
///
/// 32 bytes encoded as hex string.
#[wasm_bindgen]
#[derive(PartialEq, Eq, Debug, Hash, Clone, Copy)]
pub struct AssetId {
    inner: elements::AssetId,
}

// wasm_bindgen does not support Vec<T> as a wrapper of Vec<T>
/// A collection of asset identifiers. wrapper of [`Vec<elements::AssetId>`]
#[wasm_bindgen]
#[derive(PartialEq, Eq, Debug, Hash, Clone)]
pub struct AssetIds {
    inner: BTreeSet<elements::AssetId>,
}

impl std::fmt::Display for AssetId {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.inner)
    }
}

impl From<elements::AssetId> for AssetId {
    fn from(inner: elements::AssetId) -> Self {
        AssetId { inner }
    }
}

impl From<AssetId> for elements::AssetId {
    fn from(value: AssetId) -> Self {
        value.inner
    }
}

impl From<AssetIds> for Vec<elements::AssetId> {
    fn from(value: AssetIds) -> Self {
        value.inner.into_iter().collect()
    }
}

impl From<AssetIds> for Vec<AssetId> {
    fn from(value: AssetIds) -> Self {
        value.inner.into_iter().map(AssetId::from).collect()
    }
}

impl From<&AssetIds> for Vec<elements::AssetId> {
    fn from(value: &AssetIds) -> Self {
        value.inner.clone().into_iter().collect()
    }
}

impl From<Vec<elements::AssetId>> for AssetIds {
    fn from(value: Vec<elements::AssetId>) -> Self {
        AssetIds {
            inner: value.into_iter().collect(),
        }
    }
}

impl From<HashSet<elements::AssetId>> for AssetIds {
    fn from(value: HashSet<elements::AssetId>) -> Self {
        AssetIds {
            inner: value.into_iter().collect(),
        }
    }
}

impl From<Vec<AssetId>> for AssetIds {
    fn from(value: Vec<AssetId>) -> Self {
        AssetIds {
            inner: value.into_iter().map(|asset_id| asset_id.inner).collect(),
        }
    }
}

impl std::fmt::Display for AssetIds {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{:?}", self.inner)
    }
}

#[wasm_bindgen]
impl AssetId {
    /// Creates an `AssetId`
    #[wasm_bindgen(constructor)]
    pub fn new(asset_id: &str) -> Result<AssetId, Error> {
        Ok(elements::AssetId::from_str(asset_id)?.into())
    }

    #[wasm_bindgen(js_name = toString)]
    pub fn to_string_js(&self) -> String {
        format!("{}", self)
    }
}

#[wasm_bindgen]
impl AssetIds {
    pub fn empty() -> Result<AssetIds, Error> {
        Ok(AssetIds {
            inner: BTreeSet::new(),
        })
    }

    #[wasm_bindgen(js_name = toString)]
    pub fn to_string_js(&self) -> String {
        format!("{}", self)
    }
}
#[cfg(all(test, target_arch = "wasm32"))]
mod tests {

    use wasm_bindgen_test::*;

    use crate::{AssetId, AssetIds};

    wasm_bindgen_test_configure!(run_in_browser);

    #[wasm_bindgen_test]
    async fn test_asset_id() {
        let expected = "HexToArray(InvalidLength(InvalidLengthError { expected: 64, invalid: 2 }))";
        let hex = "xx";
        assert_eq!(expected, format!("{:?}", AssetId::new(hex).unwrap_err()));

        let expected = "HexToArray(InvalidChar(InvalidCharError { invalid: 120 }))";
        let hex = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
        assert_eq!(expected, format!("{:?}", AssetId::new(hex).unwrap_err()));

        let hex = "0000000000000000000000000000000000000000000000000000000000000001";
        assert_eq!(hex, AssetId::new(hex).unwrap().to_string());
    }

    #[wasm_bindgen_test]
    async fn test_asset_ids() {
        let a = "0000000000000000000000000000000000000000000000000000000000000001";
        let asset_id1 = AssetId::new(a).unwrap();
        let b = "0000000000000000000000000000000000000000000000000000000000000002";
        let asset_id2 = AssetId::new(b).unwrap();
        let c = "0000000000000000000000000000000000000000000000000000000000000003";
        let asset_id3 = AssetId::new(c).unwrap();

        let asset_ids: AssetIds = vec![asset_id3, asset_id1, asset_id2].into();
        assert_eq!(asset_ids.to_string(), format!("{{{a}, {b}, {c}}}"));
        let asset_ids2: AssetIds = vec![asset_id2, asset_id1, asset_id3].into();
        assert_eq!(asset_ids, asset_ids2);
    }
}