1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use crate::{BlockPool, Dollars, FeeRate, Sats, Weight};
/// Extended block data matching mempool.space /api/v1/blocks extras
#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
pub struct BlockExtras {
/// Total fees in satoshis
#[serde(rename = "totalFees")]
pub total_fees: Sats,
/// Median fee rate in sat/vB
#[serde(rename = "medianFee")]
pub median_fee: FeeRate,
/// Fee rate range: [min, 10%, 25%, 50%, 75%, 90%, max]
#[serde(rename = "feeRange")]
pub fee_range: [FeeRate; 7],
/// Total block reward (subsidy + fees) in satoshis
pub reward: Sats,
/// Mining pool that mined this block
pub pool: BlockPool,
/// Average fee per transaction in satoshis
#[serde(rename = "avgFee")]
pub avg_fee: Sats,
/// Average fee rate in sat/vB
#[serde(rename = "avgFeeRate")]
pub avg_fee_rate: FeeRate,
/// Raw coinbase transaction scriptsig as hex
#[serde(rename = "coinbaseRaw")]
pub coinbase_raw: String,
/// Primary coinbase output address
#[serde(rename = "coinbaseAddress")]
pub coinbase_address: Option<String>,
/// All coinbase output addresses
#[serde(rename = "coinbaseAddresses")]
pub coinbase_addresses: Vec<String>,
/// Coinbase output script in ASM format
#[serde(rename = "coinbaseSignature")]
pub coinbase_signature: String,
/// Coinbase scriptsig decoded as ASCII
#[serde(rename = "coinbaseSignatureAscii")]
pub coinbase_signature_ascii: String,
/// Average transaction size in bytes
#[serde(rename = "avgTxSize")]
#[schemars(example = 534.5)]
pub avg_tx_size: f64,
/// Total number of inputs (excluding coinbase)
#[serde(rename = "totalInputs")]
#[schemars(example = 5000)]
pub total_inputs: u64,
/// Total number of outputs
#[serde(rename = "totalOutputs")]
#[schemars(example = 7500)]
pub total_outputs: u64,
/// Total output amount in satoshis
#[serde(rename = "totalOutputAmt")]
pub total_output_amt: Sats,
/// Median fee amount in satoshis
#[serde(rename = "medianFeeAmt")]
pub median_fee_amt: Sats,
/// Fee amount percentiles in satoshis: [min, 10%, 25%, 50%, 75%, 90%, max]
#[serde(rename = "feePercentiles")]
pub fee_percentiles: [Sats; 7],
/// Number of segwit transactions
#[serde(rename = "segwitTotalTxs")]
#[schemars(example = 2000)]
pub segwit_total_txs: u32,
/// Total size of segwit transactions in bytes
#[serde(rename = "segwitTotalSize")]
#[schemars(example = 1200000)]
pub segwit_total_size: u64,
/// Total weight of segwit transactions
#[serde(rename = "segwitTotalWeight")]
pub segwit_total_weight: Weight,
/// Raw 80-byte block header as hex
pub header: String,
/// UTXO set change (total outputs - total inputs, includes unspendable like OP_RETURN).
/// Note: intentionally differs from utxo_set_size diff which excludes unspendable outputs.
/// Matches mempool.space/bitcoin-cli behavior.
#[serde(rename = "utxoSetChange")]
#[schemars(example = 2500)]
pub utxo_set_change: i64,
/// Total spendable UTXO set size at this height (excludes OP_RETURN and other unspendable outputs)
#[serde(rename = "utxoSetSize")]
#[schemars(example = 170_000_000)]
pub utxo_set_size: u64,
/// Total input amount in satoshis
#[serde(rename = "totalInputAmt")]
pub total_input_amt: Sats,
/// Virtual size in vbytes
#[serde(rename = "virtualSize")]
#[schemars(example = 998000.25)]
pub virtual_size: f64,
/// Timestamp when the block was first seen (always null, not yet supported)
#[serde(rename = "firstSeen")]
pub first_seen: Option<u64>,
/// Orphaned blocks (always empty)
pub orphans: Vec<String>,
/// USD price at block height
pub price: Dollars,
}