openassets/openassets/
address.rs1use bitcoin::network::constants::Network;
2use bitcoin::util::address::Payload;
3use bitcoin::consensus::encode;
4use std::fmt::{self, Display, Formatter};
5use bitcoin::util::base58;
6use bitcoin::consensus::encode::Error::ParseFailed;
7
8#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
10pub struct Address {
11
12 pub network: Network,
13 pub payload: Payload,
14
15}
16
17const NAMESPACE: u8 = 0x13;
18
19impl Address {
20
21 pub fn new(payload: Payload, network: bitcoin::network::constants::Network) -> Result<Self, encode::Error> {
22 match payload {
23 Payload::PubkeyHash(_) | Payload::ScriptHash(_) => {},
24 _ => {return Err(ParseFailed("The Open Assets Address of the witness program does not defined."));}
25 }
26 Ok(Address { payload, network })
27 }
28
29 pub fn to_btc_addr(&self) -> Result<bitcoin::Address, encode::Error> {
30 Ok(bitcoin::Address {network: self.network, payload: self.payload.clone()})
31 }
32}
33
34impl Display for Address{
35 fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
36 let mut prefixed = [0; 22];
37 prefixed[0] = NAMESPACE;
38 prefixed[1] = match self.network {
39 bitcoin::network::constants::Network::Bitcoin => 0,
40 bitcoin::network::constants::Network::Testnet | bitcoin::network::constants::Network::Regtest => 111
41 };
42 match self.payload {
43 Payload::PubkeyHash(ref hash) => {
44 prefixed[2..].copy_from_slice(&hash[..]);
45 base58::check_encode_slice_to_fmt(fmt, &prefixed[..])
46 },
47 Payload::ScriptHash(ref hash) => {
48 prefixed[2..].copy_from_slice(&hash[..]);
49 base58::check_encode_slice_to_fmt(fmt, &prefixed[..])
50 },
51 Payload::WitnessProgram(_) => {
52 fmt.write_str("The Open Assets Address of the witness program does not defined.")
53 },
54 }
55 }
56}
57
58pub trait OAAddressConverter {
59
60 fn to_oa_address(&self) -> Result<Address, encode::Error>;
61
62}
63
64impl OAAddressConverter for bitcoin::Address{
65 fn to_oa_address(&self) -> Result<Address, encode::Error> {
66 Address::new(self.payload.clone(), self.network)
67 }
68}
69
70#[cfg(test)]
71mod tests {
72 use std::str::FromStr;
73 use std::string::ToString;
74 use openassets::address::OAAddressConverter;
75
76 #[test]
77 fn test_oa_address_converter(){
78 let addr = bitcoin::Address::from_str("1F2AQr6oqNtcJQ6p9SiCLQTrHuM9en44H8").unwrap();
79 assert_eq!("akQz3f1v9JrnJAeGBC4pNzGNRdWXKan4U6E", addr.to_oa_address().unwrap().to_string());
80 assert_eq!(addr, addr.to_oa_address().unwrap().to_btc_addr().unwrap());
81
82
83 let testnet_addr = bitcoin::Address::from_str("mkgW6hNYBctmqDtTTsTJrsf2Gh2NPtoCU4").unwrap();
84 assert_eq!("bWvePLsBsf6nThU3pWVZVWjZbcJCYQxHCpE", testnet_addr.to_oa_address().unwrap().to_string());
85 assert_eq!(testnet_addr, testnet_addr.to_oa_address().unwrap().to_btc_addr().unwrap());
86
87 let segwit_addr = bitcoin::Address::from_str("bc1qvzvkjn4q3nszqxrv3nraga2r822xjty3ykvkuw").unwrap();
88 assert!(segwit_addr.to_oa_address().is_err());
89 }
90
91}