//! structs from the esplora API //! //! see: use crate::BlockTime; use bitcoin::{OutPoint, Script, Transaction, TxIn, TxOut, Txid, Witness}; #[derive(serde::Deserialize, Clone, Debug)] pub struct PrevOut { pub value: u64, pub scriptpubkey: Script, } #[derive(serde::Deserialize, Clone, Debug)] pub struct Vin { pub txid: Txid, pub vout: u32, // None if coinbase pub prevout: Option, pub scriptsig: Script, #[serde(deserialize_with = "deserialize_witness", default)] pub witness: Vec>, pub sequence: u32, pub is_coinbase: bool, } #[derive(serde::Deserialize, Clone, Debug)] pub struct Vout { pub value: u64, pub scriptpubkey: Script, } #[derive(serde::Deserialize, Clone, Debug)] pub struct TxStatus { pub confirmed: bool, pub block_height: Option, pub block_time: Option, } #[derive(serde::Deserialize, Clone, Debug)] pub struct Tx { pub txid: Txid, pub version: i32, pub locktime: u32, pub vin: Vec, pub vout: Vec, pub status: TxStatus, pub fee: u64, } impl Tx { pub fn to_tx(&self) -> Transaction { Transaction { version: self.version, lock_time: self.locktime, input: self .vin .iter() .cloned() .map(|vin| TxIn { previous_output: OutPoint { txid: vin.txid, vout: vin.vout, }, script_sig: vin.scriptsig, sequence: vin.sequence, witness: Witness::from_vec(vin.witness), }) .collect(), output: self .vout .iter() .cloned() .map(|vout| TxOut { value: vout.value, script_pubkey: vout.scriptpubkey, }) .collect(), } } pub fn confirmation_time(&self) -> Option { match self.status { TxStatus { confirmed: true, block_height: Some(height), block_time: Some(timestamp), } => Some(BlockTime { timestamp, height }), _ => None, } } pub fn previous_outputs(&self) -> Vec> { self.vin .iter() .cloned() .map(|vin| { vin.prevout.map(|po| TxOut { script_pubkey: po.scriptpubkey, value: po.value, }) }) .collect() } } fn deserialize_witness<'de, D>(d: D) -> Result>, D::Error> where D: serde::de::Deserializer<'de>, { use crate::serde::Deserialize; use bitcoin::hashes::hex::FromHex; let list = Vec::::deserialize(d)?; list.into_iter() .map(|hex_str| Vec::::from_hex(&hex_str)) .collect::>, _>>() .map_err(serde::de::Error::custom) }