1pub use bitcoin::consensus::{deserialize, serialize};
6pub use bitcoin::hex::FromHex;
7use bitcoin::Weight;
8pub use bitcoin::{
9 transaction, Amount, BlockHash, OutPoint, ScriptBuf, Transaction, TxIn, TxOut, Txid, Witness,
10};
11
12use serde::Deserialize;
13
14#[derive(Deserialize, Clone, Debug, PartialEq, Eq)]
15pub struct PrevOut {
16 pub value: u64,
17 pub scriptpubkey: ScriptBuf,
18}
19
20#[derive(Deserialize, Clone, Debug, PartialEq, Eq)]
21pub struct Vin {
22 pub txid: Txid,
23 pub vout: u32,
24 pub prevout: Option<PrevOut>,
26 pub scriptsig: ScriptBuf,
27 #[serde(deserialize_with = "deserialize_witness", default)]
28 pub witness: Vec<Vec<u8>>,
29 pub sequence: u32,
30 pub is_coinbase: bool,
31}
32
33#[derive(Deserialize, Clone, Debug, PartialEq, Eq)]
34pub struct Vout {
35 pub value: u64,
36 pub scriptpubkey: ScriptBuf,
37}
38
39#[derive(Deserialize, Clone, Debug, PartialEq, Eq)]
40pub struct TxStatus {
41 pub confirmed: bool,
42 pub block_height: Option<u32>,
43 pub block_hash: Option<BlockHash>,
44 pub block_time: Option<u64>,
45}
46
47#[derive(Deserialize, Clone, Debug, PartialEq, Eq)]
48pub struct MerkleProof {
49 pub block_height: u32,
50 pub merkle: Vec<Txid>,
51 pub pos: usize,
52}
53
54#[derive(Deserialize, Clone, Debug, PartialEq, Eq)]
55pub struct OutputStatus {
56 pub spent: bool,
57 pub txid: Option<Txid>,
58 pub vin: Option<u64>,
59 pub status: Option<TxStatus>,
60}
61
62#[derive(Deserialize, Clone, Debug, PartialEq, Eq)]
63pub struct BlockStatus {
64 pub in_best_chain: bool,
65 pub height: Option<u32>,
66 pub next_best: Option<BlockHash>,
67}
68
69#[derive(Deserialize, Clone, Debug, PartialEq, Eq)]
70pub struct Tx {
71 pub txid: Txid,
72 pub version: i32,
73 pub locktime: u32,
74 pub vin: Vec<Vin>,
75 pub vout: Vec<Vout>,
76 pub size: usize,
78 pub weight: u64,
80 pub status: TxStatus,
81 pub fee: u64,
82}
83
84#[derive(Deserialize, Clone, Debug, PartialEq, Eq)]
85pub struct BlockTime {
86 pub timestamp: u64,
87 pub height: u32,
88}
89
90#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
91pub struct BlockSummary {
92 pub id: BlockHash,
93 #[serde(flatten)]
94 pub time: BlockTime,
95 pub previousblockhash: Option<bitcoin::BlockHash>,
97 pub merkle_root: bitcoin::hash_types::TxMerkleNode,
98}
99
100#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
102pub struct AddressStats {
103 pub address: String,
105 pub chain_stats: AddressTxsSummary,
107 pub mempool_stats: AddressTxsSummary,
109}
110
111#[derive(Debug, Copy, Clone, PartialEq, Eq, Deserialize)]
113pub struct AddressTxsSummary {
114 pub funded_txo_count: u32,
116 pub funded_txo_sum: u64,
118 pub spent_txo_count: u32,
120 pub spent_txo_sum: u64,
122 pub tx_count: u32,
124}
125
126impl Tx {
127 pub fn to_tx(&self) -> Transaction {
128 Transaction {
129 version: transaction::Version::non_standard(self.version),
130 lock_time: bitcoin::absolute::LockTime::from_consensus(self.locktime),
131 input: self
132 .vin
133 .iter()
134 .cloned()
135 .map(|vin| TxIn {
136 previous_output: OutPoint {
137 txid: vin.txid,
138 vout: vin.vout,
139 },
140 script_sig: vin.scriptsig,
141 sequence: bitcoin::Sequence(vin.sequence),
142 witness: Witness::from_slice(&vin.witness),
143 })
144 .collect(),
145 output: self
146 .vout
147 .iter()
148 .cloned()
149 .map(|vout| TxOut {
150 value: Amount::from_sat(vout.value),
151 script_pubkey: vout.scriptpubkey,
152 })
153 .collect(),
154 }
155 }
156
157 pub fn confirmation_time(&self) -> Option<BlockTime> {
158 match self.status {
159 TxStatus {
160 confirmed: true,
161 block_height: Some(height),
162 block_time: Some(timestamp),
163 ..
164 } => Some(BlockTime { timestamp, height }),
165 _ => None,
166 }
167 }
168
169 pub fn previous_outputs(&self) -> Vec<Option<TxOut>> {
170 self.vin
171 .iter()
172 .cloned()
173 .map(|vin| {
174 vin.prevout.map(|po| TxOut {
175 script_pubkey: po.scriptpubkey,
176 value: Amount::from_sat(po.value),
177 })
178 })
179 .collect()
180 }
181
182 pub fn weight(&self) -> Weight {
183 Weight::from_wu(self.weight)
184 }
185
186 pub fn fee(&self) -> Amount {
187 Amount::from_sat(self.fee)
188 }
189}
190
191fn deserialize_witness<'de, D>(d: D) -> Result<Vec<Vec<u8>>, D::Error>
192where
193 D: serde::de::Deserializer<'de>,
194{
195 let list = Vec::<String>::deserialize(d)?;
196 list.into_iter()
197 .map(|hex_str| Vec::<u8>::from_hex(&hex_str))
198 .collect::<Result<Vec<Vec<u8>>, _>>()
199 .map_err(serde::de::Error::custom)
200}