use bitcoin::key::Secp256k1;
use bitcoin::{Address, Network, PublicKey};
use ex3_node_error::OtherError;
use ex3_node_types::address_types::BtcAddressType;
use ex3_node_types::chain::Chain;
use num_traits::ToPrimitive;
const BTC_MAIN_NET: u8 = 1u8;
const BTC_TEST_NET: u8 = 2u8;
const BTC_REG_TEST: u8 = 3u8;
pub struct BtcAddressParser;
impl BtcAddressParser {
pub fn to_address<T: AsRef<[u8]>>(
pub_key: &T,
chain: &Chain,
address_type: &BtcAddressType,
) -> super::Result<String> {
let network = match chain.network.clone().to_u8().unwrap() {
BTC_MAIN_NET => Network::Bitcoin,
BTC_TEST_NET => Network::Testnet,
BTC_REG_TEST => Network::Regtest,
_ => panic!("Invalid network"),
};
let ecdsa_pub_key = PublicKey::from_slice(pub_key.as_ref())
.map_err(|_| OtherError::new("Invalid address type"))?;
match address_type {
BtcAddressType::P2pkh => Ok(Address::p2pkh(&ecdsa_pub_key, network).to_string()),
BtcAddressType::P2wpkh => Ok(Address::p2wpkh(&ecdsa_pub_key, network)
.map_err(|e| OtherError::new(format!("Invalid public key: {}", e)))?
.to_string()),
BtcAddressType::P2shP2wpkh => Ok(Address::p2shwpkh(&ecdsa_pub_key, network)
.map_err(|e| OtherError::new(format!("Invalid public key: {}", e)))?
.to_string()),
BtcAddressType::P2tr => {
let secp = Secp256k1::verification_only();
Ok(Address::p2tr(&secp, ecdsa_pub_key.into(), None, network).to_string())
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use ex3_node_types::chain::{Chain, ChainType};
#[test]
fn test_to_address() {
let pub_key =
hex::decode("03e3bf8c4b1c2e8cf487257aebb77f5fe8e5175c5eaf5d8e743fb3037ae01780f0")
.unwrap();
let btc_test_chain = Chain {
network: BTC_TEST_NET.into(),
r#type: ChainType::Bitcoin,
};
let address =
BtcAddressParser::to_address(&pub_key, &btc_test_chain, &BtcAddressType::P2pkh)
.unwrap();
assert_eq!(address.to_lowercase(), "mjejgn6ppovfersvzhdxmum1obqagkclxp");
let address =
BtcAddressParser::to_address(&pub_key, &btc_test_chain, &BtcAddressType::P2wpkh)
.unwrap();
assert_eq!(
address.to_lowercase(),
"tb1q94zxlextqvnt2gw0us8hzwu8skntawungngulr"
);
let address =
BtcAddressParser::to_address(&pub_key, &btc_test_chain, &BtcAddressType::P2shP2wpkh)
.unwrap();
assert_eq!(
address.to_lowercase(),
"2mw8nsbar2n87etfb3ybmxkysf29tygrryr"
);
let address =
BtcAddressParser::to_address(&pub_key, &btc_test_chain, &BtcAddressType::P2tr).unwrap();
assert_eq!(
address.to_lowercase(),
"tb1pmyu9ecss64r0lhq2fkvytewq4luft6mzd7ewww6lsadtygssswpqdppecv"
);
}
}