mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-04-24 06:39:58 -07:00
global: fixes
This commit is contained in:
@@ -8198,7 +8198,7 @@ pub struct BrkClient {
|
||||
|
||||
impl BrkClient {
|
||||
/// Client version.
|
||||
pub const VERSION: &'static str = "v0.3.0-alpha.2";
|
||||
pub const VERSION: &'static str = "v0.3.0-alpha.3";
|
||||
|
||||
/// Create a new client with the given base URL.
|
||||
pub fn new(base_url: impl Into<String>) -> Self {
|
||||
|
||||
@@ -4,7 +4,7 @@ use brk_error::{Error, Result};
|
||||
use brk_reader::Reader;
|
||||
use brk_types::{
|
||||
BlkPosition, BlockExtras, BlockHash, BlockHashPrefix, BlockHeader, BlockInfo, BlockInfoV1,
|
||||
BlockPool, FeeRate, Height, Sats, Timestamp, TxIndex, VSize, pools,
|
||||
BlockPool, FeeRate, Height, PoolSlug, Sats, Timestamp, TxIndex, VSize, pools,
|
||||
};
|
||||
use vecdb::{AnyVec, ReadableVec, VecIndex};
|
||||
|
||||
@@ -126,15 +126,15 @@ impl Query {
|
||||
height: Height::from(begin + i),
|
||||
version: header.version,
|
||||
timestamp: timestamps[i],
|
||||
bits: header.bits,
|
||||
nonce: header.nonce,
|
||||
difficulty: *difficulties[i],
|
||||
merkle_root: header.merkle_root,
|
||||
tx_count,
|
||||
size: *sizes[i],
|
||||
weight: weights[i],
|
||||
merkle_root: header.merkle_root,
|
||||
previous_block_hash: header.previous_block_hash,
|
||||
median_time,
|
||||
nonce: header.nonce,
|
||||
bits: header.bits,
|
||||
difficulty: *difficulties[i],
|
||||
});
|
||||
}
|
||||
|
||||
@@ -251,14 +251,6 @@ impl Query {
|
||||
let fa_pct90 = fad.pct90.height.collect_range_at(begin, end);
|
||||
let fa_max = fad.max.height.collect_range_at(begin, end);
|
||||
|
||||
// Bulk read tx positions range covering all coinbase txs (first tx of each block)
|
||||
let tx_pos_begin = first_tx_indexes[0].to_usize();
|
||||
let tx_pos_end = first_tx_indexes[count - 1].to_usize() + 1;
|
||||
let all_tx_positions = indexer
|
||||
.vecs
|
||||
.transactions
|
||||
.position
|
||||
.collect_range_at(tx_pos_begin, tx_pos_end);
|
||||
|
||||
// Bulk read median time window
|
||||
let median_start = begin.saturating_sub(10);
|
||||
@@ -293,16 +285,25 @@ impl Query {
|
||||
let pool_slug = pool_slugs[i];
|
||||
let pool = all_pools.get(pool_slug);
|
||||
|
||||
let varint_len = Self::compact_size_len(tx_count);
|
||||
let coinbase_offset = HEADER_SIZE as u32 + varint_len;
|
||||
let coinbase_pos = positions[i] + coinbase_offset;
|
||||
let coinbase_read_len = size as usize - coinbase_offset as usize;
|
||||
|
||||
let (
|
||||
coinbase_raw,
|
||||
coinbase_address,
|
||||
coinbase_addresses,
|
||||
coinbase_signature,
|
||||
coinbase_signature_ascii,
|
||||
) = Self::parse_coinbase_tx(
|
||||
reader,
|
||||
all_tx_positions[first_tx_indexes[i].to_usize() - tx_pos_begin],
|
||||
);
|
||||
scriptsig_bytes,
|
||||
) = Self::parse_coinbase_tx(reader, coinbase_pos, coinbase_read_len);
|
||||
|
||||
let miner_names = if pool_slug == PoolSlug::Ocean {
|
||||
Self::parse_datum_miner_names(&scriptsig_bytes)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let median_time =
|
||||
Self::compute_median_time(&median_timestamps, begin + i, median_start);
|
||||
@@ -312,15 +313,15 @@ impl Query {
|
||||
height: Height::from(begin + i),
|
||||
version: header.version,
|
||||
timestamp: timestamps[i],
|
||||
bits: header.bits,
|
||||
nonce: header.nonce,
|
||||
difficulty: *difficulties[i],
|
||||
merkle_root: header.merkle_root,
|
||||
tx_count,
|
||||
size,
|
||||
weight,
|
||||
merkle_root: header.merkle_root,
|
||||
previous_block_hash: header.previous_block_hash,
|
||||
median_time,
|
||||
nonce: header.nonce,
|
||||
bits: header.bits,
|
||||
difficulty: *difficulties[i],
|
||||
};
|
||||
|
||||
let total_input_amt = input_volumes[i];
|
||||
@@ -343,7 +344,7 @@ impl Query {
|
||||
id: pool.unique_id(),
|
||||
name: pool.name.to_string(),
|
||||
slug: pool_slug,
|
||||
miner_names: None,
|
||||
miner_names,
|
||||
},
|
||||
avg_fee: Sats::from(if non_coinbase > 0 {
|
||||
total_fees_u64 / non_coinbase
|
||||
@@ -383,6 +384,8 @@ impl Query {
|
||||
total_input_amt,
|
||||
virtual_size: vsize as f64,
|
||||
price: prices[i],
|
||||
orphans: vec![],
|
||||
first_seen: None,
|
||||
};
|
||||
|
||||
blocks.push(BlockInfoV1 { info, extras });
|
||||
@@ -448,38 +451,94 @@ impl Query {
|
||||
Timestamp::from(sorted[sorted.len() / 2])
|
||||
}
|
||||
|
||||
fn compact_size_len(tx_count: u32) -> u32 {
|
||||
if tx_count <= 0xFC {
|
||||
1
|
||||
} else if tx_count <= 0xFFFF {
|
||||
3
|
||||
} else {
|
||||
5
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse OCEAN DATUM protocol miner names from coinbase scriptsig.
|
||||
/// Skips BIP34 height push, reads tag payload, splits on 0x0F delimiter.
|
||||
fn parse_datum_miner_names(scriptsig: &[u8]) -> Option<Vec<String>> {
|
||||
if scriptsig.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Skip BIP34 height push: first byte is length of height data
|
||||
let height_len = scriptsig[0] as usize;
|
||||
let mut tag_len_idx = 1 + height_len;
|
||||
if tag_len_idx >= scriptsig.len() {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Read tags payload length (may use OP_PUSHDATA1 for >75 bytes)
|
||||
let mut tags_len = scriptsig[tag_len_idx] as usize;
|
||||
if tags_len == 0x4c {
|
||||
tag_len_idx += 1;
|
||||
if tag_len_idx >= scriptsig.len() {
|
||||
return None;
|
||||
}
|
||||
tags_len = scriptsig[tag_len_idx] as usize;
|
||||
}
|
||||
|
||||
let tag_start = tag_len_idx + 1;
|
||||
if tag_start + tags_len > scriptsig.len() {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Decode tag bytes, strip nulls, split on 0x0F, keep only alphanumeric + space
|
||||
let tag_bytes = &scriptsig[tag_start..tag_start + tags_len];
|
||||
let tag_string: String = tag_bytes
|
||||
.iter()
|
||||
.filter(|&&b| b != 0x00)
|
||||
.map(|&b| b as char)
|
||||
.collect();
|
||||
|
||||
let names: Vec<String> = tag_string
|
||||
.split('\x0f')
|
||||
.map(|s| {
|
||||
s.chars()
|
||||
.filter(|c| c.is_ascii_alphanumeric() || *c == ' ')
|
||||
.collect::<String>()
|
||||
})
|
||||
.filter(|s| !s.trim().is_empty())
|
||||
.collect();
|
||||
|
||||
if names.is_empty() { None } else { Some(names) }
|
||||
}
|
||||
|
||||
fn parse_coinbase_tx(
|
||||
reader: &Reader,
|
||||
position: BlkPosition,
|
||||
) -> (String, Option<String>, Vec<String>, String, String) {
|
||||
let raw_bytes = match reader.read_raw_bytes(position, 1000) {
|
||||
len: usize,
|
||||
) -> (String, Option<String>, Vec<String>, String, String, Vec<u8>) {
|
||||
let empty = (String::new(), None, vec![], String::new(), String::new(), vec![]);
|
||||
let raw_bytes = match reader.read_raw_bytes(position, len) {
|
||||
Ok(bytes) => bytes,
|
||||
Err(_) => return (String::new(), None, vec![], String::new(), String::new()),
|
||||
Err(_) => return empty,
|
||||
};
|
||||
|
||||
let tx = match bitcoin::Transaction::consensus_decode(&mut raw_bytes.as_slice()) {
|
||||
Ok(tx) => tx,
|
||||
Err(_) => return (String::new(), None, vec![], String::new(), String::new()),
|
||||
Err(_) => return empty,
|
||||
};
|
||||
|
||||
let coinbase_raw = tx
|
||||
let scriptsig_bytes: Vec<u8> = tx
|
||||
.input
|
||||
.first()
|
||||
.map(|input| input.script_sig.as_bytes().to_lower_hex_string())
|
||||
.map(|input| input.script_sig.as_bytes().to_vec())
|
||||
.unwrap_or_default();
|
||||
|
||||
let coinbase_signature_ascii = tx
|
||||
.input
|
||||
.first()
|
||||
.map(|input| {
|
||||
input
|
||||
.script_sig
|
||||
.as_bytes()
|
||||
.iter()
|
||||
.map(|&b| b as char)
|
||||
.collect::<String>()
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let coinbase_raw = scriptsig_bytes.to_lower_hex_string();
|
||||
|
||||
let coinbase_signature_ascii: String = scriptsig_bytes
|
||||
.iter()
|
||||
.map(|&b| b as char)
|
||||
.collect();
|
||||
|
||||
let coinbase_addresses: Vec<String> = tx
|
||||
.output
|
||||
@@ -494,7 +553,12 @@ impl Query {
|
||||
|
||||
let coinbase_signature = tx
|
||||
.output
|
||||
.first()
|
||||
.iter()
|
||||
.find(|output| {
|
||||
bitcoin::Address::from_script(&output.script_pubkey, bitcoin::Network::Bitcoin)
|
||||
.is_ok()
|
||||
})
|
||||
.or(tx.output.first())
|
||||
.map(|output| output.script_pubkey.to_asm_string())
|
||||
.unwrap_or_default();
|
||||
|
||||
@@ -504,6 +568,7 @@ impl Query {
|
||||
coinbase_addresses,
|
||||
coinbase_signature,
|
||||
coinbase_signature_ascii,
|
||||
scriptsig_bytes,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,7 +170,16 @@ impl Query {
|
||||
.collect();
|
||||
|
||||
let weight = Weight::from(tx.weight());
|
||||
let total_sigop_cost = tx.total_sigop_cost(|_| None);
|
||||
let total_sigop_cost = tx.total_sigop_cost(|outpoint| {
|
||||
tx.input
|
||||
.iter()
|
||||
.position(|i| i.previous_output == *outpoint)
|
||||
.and_then(|j| input[j].prevout.as_ref())
|
||||
.map(|p| bitcoin::TxOut {
|
||||
value: bitcoin::Amount::from_sat(u64::from(p.value)),
|
||||
script_pubkey: p.script_pubkey.clone(),
|
||||
})
|
||||
});
|
||||
let output: Vec<TxOut> = tx.output.into_iter().map(TxOut::from).collect();
|
||||
|
||||
let mut transaction = Transaction {
|
||||
|
||||
@@ -107,6 +107,13 @@ pub struct BlockExtras {
|
||||
#[serde(rename = "virtualSize")]
|
||||
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,
|
||||
}
|
||||
|
||||
@@ -14,24 +14,24 @@ pub struct BlockInfo {
|
||||
pub version: u32,
|
||||
/// Block timestamp (Unix time)
|
||||
pub timestamp: Timestamp,
|
||||
/// Compact target (bits)
|
||||
pub bits: u32,
|
||||
/// Nonce
|
||||
pub nonce: u32,
|
||||
/// Block difficulty
|
||||
pub difficulty: f64,
|
||||
/// Merkle root of the transaction tree
|
||||
pub merkle_root: String,
|
||||
/// Number of transactions
|
||||
pub tx_count: u32,
|
||||
/// Block size in bytes
|
||||
pub size: u64,
|
||||
/// Block weight in weight units
|
||||
pub weight: Weight,
|
||||
/// Merkle root of the transaction tree
|
||||
pub merkle_root: String,
|
||||
/// Previous block hash
|
||||
#[serde(rename = "previousblockhash")]
|
||||
pub previous_block_hash: BlockHash,
|
||||
/// Median time of the last 11 blocks
|
||||
#[serde(rename = "mediantime")]
|
||||
pub median_time: Timestamp,
|
||||
/// Nonce
|
||||
pub nonce: u32,
|
||||
/// Compact target (bits)
|
||||
pub bits: u32,
|
||||
/// Block difficulty
|
||||
pub difficulty: f64,
|
||||
}
|
||||
|
||||
@@ -16,6 +16,6 @@ pub struct BlockPool {
|
||||
/// URL-friendly pool identifier
|
||||
pub slug: PoolSlug,
|
||||
|
||||
/// Alternative miner names (if identified)
|
||||
pub miner_names: Option<String>,
|
||||
/// Miner name tags found in coinbase scriptsig
|
||||
pub miner_names: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
@@ -31,9 +31,17 @@ pub enum OutputType {
|
||||
P2PKH,
|
||||
P2MS,
|
||||
P2SH,
|
||||
#[serde(rename = "op_return")]
|
||||
#[strum(serialize = "op_return")]
|
||||
OpReturn,
|
||||
#[serde(rename = "v0_p2wpkh")]
|
||||
#[strum(serialize = "v0_p2wpkh")]
|
||||
P2WPKH,
|
||||
#[serde(rename = "v0_p2wsh")]
|
||||
#[strum(serialize = "v0_p2wsh")]
|
||||
P2WSH,
|
||||
#[serde(rename = "v1_p2tr")]
|
||||
#[strum(serialize = "v1_p2tr")]
|
||||
P2TR,
|
||||
P2A,
|
||||
Empty,
|
||||
|
||||
@@ -10,7 +10,7 @@ pub struct TxIn {
|
||||
#[schemars(example = "0000000000000000000000000000000000000000000000000000000000000000")]
|
||||
pub txid: Txid,
|
||||
|
||||
/// Output index being spent
|
||||
/// Output index being spent (u16: coinbase is 65535, mempool.space uses u32: 4294967295)
|
||||
#[schemars(example = 0)]
|
||||
pub vout: Vout,
|
||||
|
||||
@@ -54,8 +54,8 @@ impl Serialize for TxIn {
|
||||
let has_witness = !self.witness.is_empty();
|
||||
let has_scriptsig = !self.script_sig.is_empty();
|
||||
|
||||
// P2SH-wrapped SegWit: both scriptsig and witness present
|
||||
let inner_redeem = if has_scriptsig && has_witness {
|
||||
// P2SH-wrapped SegWit: both scriptsig and witness present (not coinbase)
|
||||
let inner_redeem = if has_scriptsig && has_witness && !self.is_coinbase {
|
||||
self.script_sig
|
||||
.redeem_script()
|
||||
.map(|s| s.to_asm_string())
|
||||
@@ -64,8 +64,8 @@ impl Serialize for TxIn {
|
||||
String::new()
|
||||
};
|
||||
|
||||
// P2WSH: witness has >2 items, last is the witnessScript
|
||||
let inner_witness = if has_witness && !has_scriptsig && self.witness.len() > 2 {
|
||||
// P2WSH / P2SH-P2WSH: witness has >2 items, last is the witnessScript
|
||||
let inner_witness = if has_witness && self.witness.len() > 2 {
|
||||
if let Some(last) = self.witness.last() {
|
||||
let bytes: Vec<u8> = bitcoin::hex::FromHex::from_hex(last).unwrap_or_default();
|
||||
ScriptBuf::from(bytes).to_asm_string()
|
||||
|
||||
@@ -92,11 +92,15 @@ impl Serialize for TxOut {
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut state = serializer.serialize_struct("TxOut", 5)?;
|
||||
let addr = self.addr();
|
||||
let field_count = if addr.is_some() { 5 } else { 4 };
|
||||
let mut state = serializer.serialize_struct("TxOut", field_count)?;
|
||||
state.serialize_field("scriptpubkey", &self.script_pubkey.to_hex_string())?;
|
||||
state.serialize_field("scriptpubkey_asm", &self.script_pubkey_asm())?;
|
||||
state.serialize_field("scriptpubkey_type", &self.type_())?;
|
||||
state.serialize_field("scriptpubkey_address", &self.addr())?;
|
||||
if let Some(addr) = &addr {
|
||||
state.serialize_field("scriptpubkey_address", addr)?;
|
||||
}
|
||||
state.serialize_field("value", &self.value)?;
|
||||
state.end()
|
||||
}
|
||||
|
||||
@@ -139,6 +139,8 @@
|
||||
* @property {number} utxoSetSize - Total UTXO set size at this height
|
||||
* @property {Sats} totalInputAmt - Total input amount in satoshis
|
||||
* @property {number} virtualSize - Virtual size in vbytes
|
||||
* @property {?number=} firstSeen - Timestamp when the block was first seen (always null, not yet supported)
|
||||
* @property {string[]} orphans - Orphaned blocks (always empty)
|
||||
* @property {Dollars} price - USD price at block height
|
||||
*/
|
||||
/**
|
||||
@@ -177,15 +179,15 @@
|
||||
* @property {Height} height - Block height
|
||||
* @property {number} version - Block version
|
||||
* @property {Timestamp} timestamp - Block timestamp (Unix time)
|
||||
* @property {number} bits - Compact target (bits)
|
||||
* @property {number} nonce - Nonce
|
||||
* @property {number} difficulty - Block difficulty
|
||||
* @property {string} merkleRoot - Merkle root of the transaction tree
|
||||
* @property {number} txCount - Number of transactions
|
||||
* @property {number} size - Block size in bytes
|
||||
* @property {Weight} weight - Block weight in weight units
|
||||
* @property {string} merkleRoot - Merkle root of the transaction tree
|
||||
* @property {BlockHash} previousblockhash - Previous block hash
|
||||
* @property {Timestamp} mediantime - Median time of the last 11 blocks
|
||||
* @property {number} nonce - Nonce
|
||||
* @property {number} bits - Compact target (bits)
|
||||
* @property {number} difficulty - Block difficulty
|
||||
*/
|
||||
/**
|
||||
* Block information with extras, matching mempool.space /api/v1/blocks
|
||||
@@ -195,15 +197,15 @@
|
||||
* @property {Height} height - Block height
|
||||
* @property {number} version - Block version
|
||||
* @property {Timestamp} timestamp - Block timestamp (Unix time)
|
||||
* @property {number} bits - Compact target (bits)
|
||||
* @property {number} nonce - Nonce
|
||||
* @property {number} difficulty - Block difficulty
|
||||
* @property {string} merkleRoot - Merkle root of the transaction tree
|
||||
* @property {number} txCount - Number of transactions
|
||||
* @property {number} size - Block size in bytes
|
||||
* @property {Weight} weight - Block weight in weight units
|
||||
* @property {string} merkleRoot - Merkle root of the transaction tree
|
||||
* @property {BlockHash} previousblockhash - Previous block hash
|
||||
* @property {Timestamp} mediantime - Median time of the last 11 blocks
|
||||
* @property {number} nonce - Nonce
|
||||
* @property {number} bits - Compact target (bits)
|
||||
* @property {number} difficulty - Block difficulty
|
||||
* @property {BlockExtras} extras - Extended block data
|
||||
*/
|
||||
/**
|
||||
@@ -213,7 +215,7 @@
|
||||
* @property {number} id - Unique pool identifier
|
||||
* @property {string} name - Pool name
|
||||
* @property {PoolSlug} slug - URL-friendly pool identifier
|
||||
* @property {?string=} minerNames - Alternative miner names (if identified)
|
||||
* @property {?string[]=} minerNames - Miner name tags found in coinbase scriptsig
|
||||
*/
|
||||
/**
|
||||
* A single block rewards data point.
|
||||
@@ -672,7 +674,7 @@
|
||||
/**
|
||||
* Type (P2PKH, P2WPKH, P2SH, P2TR, etc.)
|
||||
*
|
||||
* @typedef {("p2pk65"|"p2pk33"|"p2pkh"|"p2ms"|"p2sh"|"opreturn"|"p2wpkh"|"p2wsh"|"p2tr"|"p2a"|"empty"|"unknown")} OutputType
|
||||
* @typedef {("p2pk65"|"p2pk33"|"p2pkh"|"p2ms"|"p2sh"|"op_return"|"v0_p2wpkh"|"v0_p2wsh"|"v1_p2tr"|"p2a"|"empty"|"unknown")} OutputType
|
||||
*/
|
||||
/** @typedef {TypeIndex} P2AAddrIndex */
|
||||
/** @typedef {U8x2} P2ABytes */
|
||||
@@ -1022,7 +1024,7 @@
|
||||
*
|
||||
* @typedef {Object} TxIn
|
||||
* @property {Txid} txid - Transaction ID of the output being spent
|
||||
* @property {Vout} vout - Output index being spent
|
||||
* @property {Vout} vout - Output index being spent (u16: coinbase is 65535, mempool.space uses u32: 4294967295)
|
||||
* @property {(TxOut|null)=} prevout - Information about the previous output being spent
|
||||
* @property {string} scriptsig - Signature script (hex, for non-SegWit inputs)
|
||||
* @property {string} scriptsigAsm - Signature script in assembly format
|
||||
@@ -6564,7 +6566,7 @@ function createTransferPattern(client, acc) {
|
||||
* @extends BrkClientBase
|
||||
*/
|
||||
class BrkClient extends BrkClientBase {
|
||||
VERSION = "v0.3.0-alpha.2";
|
||||
VERSION = "v0.3.0-alpha.3";
|
||||
|
||||
INDEXES = /** @type {const} */ ([
|
||||
"minute10",
|
||||
|
||||
@@ -40,5 +40,5 @@
|
||||
"url": "git+https://github.com/bitcoinresearchkit/brk.git"
|
||||
},
|
||||
"type": "module",
|
||||
"version": "0.3.0-alpha.2"
|
||||
"version": "0.3.0-alpha.3"
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ Open = Dollars
|
||||
OpReturnIndex = TypeIndex
|
||||
OutPoint = int
|
||||
# Type (P2PKH, P2WPKH, P2SH, P2TR, etc.)
|
||||
OutputType = Literal["p2pk65", "p2pk33", "p2pkh", "p2ms", "p2sh", "opreturn", "p2wpkh", "p2wsh", "p2tr", "p2a", "empty", "unknown"]
|
||||
OutputType = Literal["p2pk65", "p2pk33", "p2pkh", "p2ms", "p2sh", "op_return", "v0_p2wpkh", "v0_p2wsh", "v1_p2tr", "p2a", "empty", "unknown"]
|
||||
P2AAddrIndex = TypeIndex
|
||||
U8x2 = List[int]
|
||||
P2ABytes = U8x2
|
||||
@@ -316,12 +316,12 @@ class BlockPool(TypedDict):
|
||||
id: Unique pool identifier
|
||||
name: Pool name
|
||||
slug: URL-friendly pool identifier
|
||||
minerNames: Alternative miner names (if identified)
|
||||
minerNames: Miner name tags found in coinbase scriptsig
|
||||
"""
|
||||
id: int
|
||||
name: str
|
||||
slug: PoolSlug
|
||||
minerNames: Optional[str]
|
||||
minerNames: Optional[List[str]]
|
||||
|
||||
class BlockExtras(TypedDict):
|
||||
"""
|
||||
@@ -354,6 +354,8 @@ class BlockExtras(TypedDict):
|
||||
utxoSetSize: Total UTXO set size at this height
|
||||
totalInputAmt: Total input amount in satoshis
|
||||
virtualSize: Virtual size in vbytes
|
||||
firstSeen: Timestamp when the block was first seen (always null, not yet supported)
|
||||
orphans: Orphaned blocks (always empty)
|
||||
price: USD price at block height
|
||||
"""
|
||||
totalFees: Sats
|
||||
@@ -382,6 +384,8 @@ class BlockExtras(TypedDict):
|
||||
utxoSetSize: int
|
||||
totalInputAmt: Sats
|
||||
virtualSize: float
|
||||
firstSeen: Optional[int]
|
||||
orphans: List[str]
|
||||
price: Dollars
|
||||
|
||||
class BlockFeesEntry(TypedDict):
|
||||
@@ -429,29 +433,29 @@ class BlockInfo(TypedDict):
|
||||
height: Block height
|
||||
version: Block version
|
||||
timestamp: Block timestamp (Unix time)
|
||||
bits: Compact target (bits)
|
||||
nonce: Nonce
|
||||
difficulty: Block difficulty
|
||||
merkle_root: Merkle root of the transaction tree
|
||||
tx_count: Number of transactions
|
||||
size: Block size in bytes
|
||||
weight: Block weight in weight units
|
||||
merkle_root: Merkle root of the transaction tree
|
||||
previousblockhash: Previous block hash
|
||||
mediantime: Median time of the last 11 blocks
|
||||
nonce: Nonce
|
||||
bits: Compact target (bits)
|
||||
difficulty: Block difficulty
|
||||
"""
|
||||
id: BlockHash
|
||||
height: Height
|
||||
version: int
|
||||
timestamp: Timestamp
|
||||
bits: int
|
||||
nonce: int
|
||||
difficulty: float
|
||||
merkle_root: str
|
||||
tx_count: int
|
||||
size: int
|
||||
weight: Weight
|
||||
merkle_root: str
|
||||
previousblockhash: BlockHash
|
||||
mediantime: Timestamp
|
||||
nonce: int
|
||||
bits: int
|
||||
difficulty: float
|
||||
|
||||
class BlockInfoV1(TypedDict):
|
||||
"""
|
||||
@@ -462,30 +466,30 @@ class BlockInfoV1(TypedDict):
|
||||
height: Block height
|
||||
version: Block version
|
||||
timestamp: Block timestamp (Unix time)
|
||||
bits: Compact target (bits)
|
||||
nonce: Nonce
|
||||
difficulty: Block difficulty
|
||||
merkle_root: Merkle root of the transaction tree
|
||||
tx_count: Number of transactions
|
||||
size: Block size in bytes
|
||||
weight: Block weight in weight units
|
||||
merkle_root: Merkle root of the transaction tree
|
||||
previousblockhash: Previous block hash
|
||||
mediantime: Median time of the last 11 blocks
|
||||
nonce: Nonce
|
||||
bits: Compact target (bits)
|
||||
difficulty: Block difficulty
|
||||
extras: Extended block data
|
||||
"""
|
||||
id: BlockHash
|
||||
height: Height
|
||||
version: int
|
||||
timestamp: Timestamp
|
||||
bits: int
|
||||
nonce: int
|
||||
difficulty: float
|
||||
merkle_root: str
|
||||
tx_count: int
|
||||
size: int
|
||||
weight: Weight
|
||||
merkle_root: str
|
||||
previousblockhash: BlockHash
|
||||
mediantime: Timestamp
|
||||
nonce: int
|
||||
bits: int
|
||||
difficulty: float
|
||||
extras: BlockExtras
|
||||
|
||||
class BlockRewardsEntry(TypedDict):
|
||||
@@ -1333,7 +1337,7 @@ class TxIn(TypedDict):
|
||||
|
||||
Attributes:
|
||||
txid: Transaction ID of the output being spent
|
||||
vout: Output index being spent
|
||||
vout: Output index being spent (u16: coinbase is 65535, mempool.space uses u32: 4294967295)
|
||||
prevout: Information about the previous output being spent
|
||||
scriptsig: Signature script (hex, for non-SegWit inputs)
|
||||
scriptsig_asm: Signature script in assembly format
|
||||
@@ -6003,7 +6007,7 @@ class SeriesTree:
|
||||
class BrkClient(BrkClientBase):
|
||||
"""Main BRK client with series tree and API methods."""
|
||||
|
||||
VERSION = "v0.3.0-alpha.2"
|
||||
VERSION = "v0.3.0-alpha.3"
|
||||
|
||||
INDEXES = [
|
||||
"minute10",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "brk-client"
|
||||
version = "0.3.0-alpha.2"
|
||||
version = "0.3.0-alpha.3"
|
||||
description = "Bitcoin on-chain analytics client — thousands of metrics, block explorer, and address index"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.9"
|
||||
|
||||
Reference in New Issue
Block a user