openassets-tapyrus 0.2.4

The implementation of the Open Assets Protocol for Rust.
Documentation
use bitcoin_hashes::{hash160, Hash};
use std::fmt::{self, Display, Formatter};
use std::str::FromStr;
use tapyrus::util::base58;
use tapyrus::Script;

#[derive(PartialEq, Eq, Debug, Clone)]
pub struct AssetId {
    pub hash: bitcoin_hashes::hash160::Hash,
    pub network: tapyrus::network::constants::Network,
}

impl AssetId {
    pub fn new(script: &Script, network: tapyrus::network::constants::Network) -> AssetId {
        AssetId {
            hash: hash160::Hash::hash(&script.to_bytes()),
            network,
        }
    }
}

impl Display for AssetId {
    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        let mut prefixed = [0; 21];
        prefixed[0] = match self.network {
            tapyrus::network::constants::Network::Prod => 0x17,
            tapyrus::network::constants::Network::Dev => 0x73,
        };
        prefixed[1..].copy_from_slice(&self.hash[..]);
        base58::check_encode_slice_to_fmt(fmt, &prefixed[..])
    }
}

impl FromStr for AssetId {
    type Err = base58::Error;

    fn from_str(s: &str) -> Result<AssetId, base58::Error> {
        let data = base58::from_check(s)?;
        let (network, hash) = match data[0] {
            0x17 => (
                tapyrus::network::constants::Network::Prod,
                hash160::Hash::from_slice(&data[1..]).unwrap(),
            ),
            0x73 => (
                tapyrus::network::constants::Network::Dev,
                hash160::Hash::from_slice(&data[1..]).unwrap(),
            ),
            x => return Err(base58::Error::InvalidVersion(vec![x])),
        };
        Ok(AssetId { hash, network })
    }
}

#[cfg(test)]
mod tests {
    use hex::decode as hex_decode;
    use openassets::asset_id::AssetId;
    use std::str::FromStr;
    use tapyrus::blockdata::script::Builder;

    #[test]
    fn test_calculate_asset_id() {
        let p2pkh = Builder::from(
            hex_decode("76a914010966776006953d5567439e5e39f86a0d273bee88ac").unwrap(),
        )
        .into_script();
        let p2pkh_asset = AssetId::new(&p2pkh, tapyrus::network::constants::Network::Prod);
        assert_eq!(
            "ALn3aK1fSuG27N96UGYB1kUYUpGKRhBuBC",
            p2pkh_asset.to_string()
        );
        assert_eq!(
            AssetId::from_str("ALn3aK1fSuG27N96UGYB1kUYUpGKRhBuBC").unwrap(),
            p2pkh_asset
        );

        let p2sh =
            Builder::from(hex_decode("a914f9d499817e88ef7b10a88673296c6d6df2f4292d87").unwrap())
                .into_script();
        let testnet_asset = AssetId::new(&p2sh, tapyrus::network::constants::Network::Dev);
        assert_eq!(
            "oMb2yzA542yQgwn8XtmGefTzBv5NJ2nDjh",
            testnet_asset.to_string()
        );
        assert_eq!(
            AssetId::from_str("oMb2yzA542yQgwn8XtmGefTzBv5NJ2nDjh").unwrap(),
            testnet_asset
        );
    }
}