1use crate::network::BitcoinNetwork;
2use wagyu_model::{AddressError, ExtendedPrivateKeyError, ExtendedPublicKeyError, Format};
3
4use serde::Serialize;
5use std::fmt;
6
7#[derive(Serialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
9#[allow(non_camel_case_types)]
10pub enum BitcoinFormat {
11 P2PKH,
13 P2WSH,
15 P2SH_P2WPKH,
17 Bech32,
19}
20
21impl Format for BitcoinFormat {}
22
23impl BitcoinFormat {
24 pub fn to_address_prefix<N: BitcoinNetwork>(&self) -> Vec<u8> {
26 N::to_address_prefix(self)
27 }
28
29 pub fn from_address_prefix(prefix: &[u8]) -> Result<Self, AddressError> {
31 if prefix.len() < 2 {
32 return Err(AddressError::InvalidPrefix(prefix.to_vec()));
33 }
34 match (prefix[0], prefix[1]) {
35 (0x00, _) | (0x6F, _) => Ok(BitcoinFormat::P2PKH),
36 (0x05, _) | (0xC4, _) => Ok(BitcoinFormat::P2SH_P2WPKH),
37 (0x62, 0x63) | (0x74, 0x62) => Ok(BitcoinFormat::Bech32),
38 _ => return Err(AddressError::InvalidPrefix(prefix.to_vec())),
39 }
40 }
41
42 pub fn from_extended_private_key_version_bytes(prefix: &[u8]) -> Result<Self, ExtendedPrivateKeyError> {
45 match prefix[0..4] {
46 [0x04, 0x88, 0xAD, 0xE4] | [0x04, 0x35, 0x83, 0x94] => Ok(BitcoinFormat::P2PKH),
47 [0x04, 0x9D, 0x78, 0x78] | [0x04, 0x4A, 0x4E, 0x28] => Ok(BitcoinFormat::P2SH_P2WPKH),
48 _ => Err(ExtendedPrivateKeyError::InvalidVersionBytes(prefix.to_vec())),
49 }
50 }
51
52 pub fn from_extended_public_key_version_bytes(prefix: &[u8]) -> Result<Self, ExtendedPublicKeyError> {
55 match prefix[0..4] {
56 [0x04, 0x88, 0xB2, 0x1E] | [0x04, 0x35, 0x87, 0xCF] => Ok(BitcoinFormat::P2PKH),
57 [0x04, 0x9D, 0x7C, 0xB2] | [0x04, 0x4A, 0x52, 0x62] => Ok(BitcoinFormat::P2SH_P2WPKH),
58 _ => Err(ExtendedPublicKeyError::InvalidVersionBytes(prefix.to_vec())),
59 }
60 }
61}
62
63impl fmt::Display for BitcoinFormat {
64 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
65 match self {
66 BitcoinFormat::P2PKH => write!(f, "p2pkh"),
67 BitcoinFormat::P2WSH => write!(f, "p2wsh"),
68 BitcoinFormat::P2SH_P2WPKH => write!(f, "p2sh_p2wpkh"),
69 BitcoinFormat::Bech32 => write!(f, "bech32"),
70 }
71 }
72}