use std::marker::PhantomData;
use coins_core::{
enc::{AddressEncoder, EncodingError},
nets::Network,
};
use crate::{
builder::BitcoinTxBuilder,
enc::encoder::{Address, BitcoinEncoderMarker, MainnetEncoder, SignetEncoder, TestnetEncoder},
types::{
BitcoinTransaction, BitcoinTx, BitcoinTxIn, ScriptPubkey, TxOut, WitnessTransaction,
WitnessTx,
},
};
pub trait BitcoinNetwork: Network {
type WTx: WitnessTransaction + BitcoinTransaction;
}
#[derive(Debug)]
pub struct Bitcoin<T: AddressEncoder>(PhantomData<fn(T) -> T>);
impl<T> Network for Bitcoin<T>
where
T: BitcoinEncoderMarker,
{
type Address = Address;
type Error = EncodingError;
type RecipientIdentifier = ScriptPubkey;
type Encoder = T;
type TxIn = BitcoinTxIn;
type TxOut = TxOut;
type Tx = BitcoinTx;
type Builder = BitcoinTxBuilder<T>;
}
impl<T> BitcoinNetwork for Bitcoin<T>
where
T: BitcoinEncoderMarker,
{
type WTx = WitnessTx;
}
pub type BitcoinMainnet = Bitcoin<MainnetEncoder>;
pub type BitcoinTestnet = Bitcoin<TestnetEncoder>;
pub type BitcoinSignet = Bitcoin<SignetEncoder>;
#[cfg(test)]
mod test {
use super::*;
use crate::types::txin::BitcoinOutpoint;
use coins_core::{builder::TxBuilder, ser::ByteFormat};
#[test]
fn it_has_sensible_syntax() {
let tx_hex = BitcoinMainnet::tx_builder()
.version(2)
.spend(BitcoinOutpoint::default(), 0xaabbccdd)
.pay(
0x8888_8888_8888_8888,
&Address::Wpkh("bc1qvyyvsdcd0t9863stt7u9rf37wx443lzasg0usy".to_owned()),
)
.pay(
0x7777_7777_7777_7777,
&Address::Sh("377mKFYsaJPsxYSB5aFfx8SW3RaN5BzZVh".to_owned()),
)
.build()
.unwrap()
.serialize_hex();
BitcoinMainnet::builder_from_hex(&tx_hex).unwrap();
}
#[test]
fn it_exposes_encoder_interface() {
let addr_string = "bc1qvyyvsdcd0t9863stt7u9rf37wx443lzasg0usy".to_owned();
let address = Address::Wpkh(addr_string.clone());
assert_eq!(
&address,
&BitcoinMainnet::string_to_address(&addr_string).unwrap()
);
let u = BitcoinMainnet::decode_address(&address);
assert_eq!(&address, &BitcoinMainnet::encode_address(&u).unwrap())
}
}