anychain_bitcoin/
format.rs

1use crate::Prefix;
2use anychain_core::no_std::*;
3use anychain_core::{AddressError, Format};
4
5use core::fmt;
6use core::str::FromStr;
7use serde::Serialize;
8
9/// Represents the format of a Bitcoin address
10#[derive(Serialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
11#[allow(non_camel_case_types)]
12pub enum BitcoinFormat {
13    /// Pay-to-Pubkey Hash, e.g. 1NoZQSmjYHUZMbqLerwmT4xfe8A6mAo8TT
14    P2PKH,
15    /// Pay-to-Script Hash, e.g. 34AgLJhwXrvmkZS1o5TrcdeevMt22Nar53
16    //P2SH,
17    /// Pay-to-Witness-Script Hash, e.g. bc1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3qccfmv3
18    P2WSH,
19    /// SegWit Pay-to-Witness-Public-Key Hash, e.g. 34AgLJhwXrvmkZS1o5TrcdeevMt22Nar53
20    P2SH_P2WPKH,
21    /// Bech32, e.g. bc1pw508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7k7grplx
22    Bech32,
23    /// CashAddr, e.g. bitcoincash:qpkxa3xypl6rfp4nzewh9xrqnv90n2yxrcr0pmwas4
24    CashAddr,
25}
26
27impl Format for BitcoinFormat {}
28
29impl BitcoinFormat {
30    /// Returns the format of the given address prefix.
31    pub fn from_address_prefix(prefix: Prefix) -> Result<Self, AddressError> {
32        match prefix {
33            Prefix::AddressPrefix(prefix) => match prefix.as_str() {
34                "bc" | "tb" | "ltc" | "tltc" => Ok(Self::Bech32),
35                "bitcoincash" | "bchtest" => Ok(Self::CashAddr),
36                _ => Err(AddressError::Message(format!(
37                    "Unrecognized address prefix {}",
38                    prefix,
39                ))),
40            },
41            Prefix::Version(version) => match version {
42                0x00 | 0x6f | 0x1e | 0x71 | 0x30 => Ok(Self::P2PKH),
43                0x05 | 0xc4 | 0x16 | 0x32 | 0x3a => Ok(Self::P2SH_P2WPKH),
44                _ => Err(AddressError::Message(format!(
45                    "Unrecognized version byte {}",
46                    version,
47                ))),
48            },
49        }
50    }
51}
52
53impl fmt::Display for BitcoinFormat {
54    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
55        match self {
56            BitcoinFormat::P2PKH => write!(f, "p2pkh"),
57            BitcoinFormat::P2WSH => write!(f, "p2wsh"),
58            BitcoinFormat::P2SH_P2WPKH => write!(f, "p2sh_p2wpkh"),
59            BitcoinFormat::Bech32 => write!(f, "bech32"),
60            BitcoinFormat::CashAddr => write!(f, "cash_addr"),
61        }
62    }
63}
64
65impl FromStr for BitcoinFormat {
66    type Err = AddressError;
67
68    fn from_str(format: &str) -> Result<Self, AddressError> {
69        match format {
70            "p2pkh" => Ok(BitcoinFormat::P2PKH),
71            "p2sh_p2wpkh" => Ok(BitcoinFormat::P2SH_P2WPKH),
72            "p2wsh" => Ok(BitcoinFormat::P2WSH),
73            "bech32" => Ok(BitcoinFormat::Bech32),
74            "cash_addr" => Ok(BitcoinFormat::CashAddr),
75            _ => Err(AddressError::Message(format!(
76                "Unrecognized bitcoin address format {}",
77                format,
78            ))),
79        }
80    }
81}