global: utxos part 4

This commit is contained in:
nym21
2025-05-19 17:53:09 +02:00
parent 411c5e4c4d
commit 5893376279
36 changed files with 1502 additions and 391 deletions

2
Cargo.lock generated
View File

@@ -439,6 +439,8 @@ dependencies = [
"rayon", "rayon",
"serde", "serde",
"serde_json", "serde_json",
"zerocopy",
"zerocopy-derive",
] ]
[[package]] [[package]]

View File

@@ -23,3 +23,5 @@ log = { workspace = true }
rayon = { workspace = true } rayon = { workspace = true }
serde = { workspace = true } serde = { workspace = true }
serde_json = { workspace = true } serde_json = { workspace = true }
zerocopy = { workspace = true }
zerocopy-derive = { workspace = true }

View File

@@ -1,9 +1,40 @@
#![allow(unused)] #![allow(unused)]
use brk_core::{Sats, StoredU32}; use std::{
iter::Sum,
ops::{Add, AddAssign, SubAssign},
};
use brk_core::{CheckedSub, Sats, StoredU32};
use serde::Serialize;
use zerocopy_derive::{FromBytes, Immutable, IntoBytes, KnownLayout};
#[derive(Debug, Default, Clone, FromBytes, Immutable, IntoBytes, KnownLayout, Serialize)]
pub struct BlockState { pub struct BlockState {
utxos: StoredU32, pub utxos: usize,
value: Sats, pub value: Sats,
unspendable: Sats, }
impl Add<BlockState> for BlockState {
type Output = Self;
fn add(self, rhs: BlockState) -> Self::Output {
Self {
utxos: self.utxos + rhs.utxos,
value: self.value + rhs.value,
}
}
}
impl AddAssign<&BlockState> for BlockState {
fn add_assign(&mut self, rhs: &BlockState) {
self.utxos += rhs.utxos;
self.value += rhs.value;
}
}
impl SubAssign for BlockState {
fn sub_assign(&mut self, rhs: Self) {
self.utxos = self.utxos.checked_sub(rhs.utxos).unwrap();
self.value = self.value.checked_sub(rhs.value).unwrap();
}
} }

View File

@@ -3,11 +3,10 @@
use brk_core::{Dollars, Sats, StoredUsize}; use brk_core::{Dollars, Sats, StoredUsize};
// Vecs ? probably // Vecs ? probably
#[derive(Default)] #[derive(Default, Clone)]
pub struct CohortState { pub struct CohortState {
pub realized_cap: Dollars, pub realized_cap: Dollars,
pub supply: Sats, pub supply: Sats,
pub unspendable_supply: Sats,
pub utxo_count: StoredUsize, pub utxo_count: StoredUsize,
// pub price_to_amount: PriceToValue<Amount>, save it not rounded in fjall // pub price_to_amount: PriceToValue<Amount>, save it not rounded in fjall
} }

View File

@@ -1,111 +0,0 @@
#![allow(unused)]
#[derive(Default, Clone)]
pub struct Outputs<T> {
pub all: T,
// pub by_term: OutputsByTerm<T>,
// pub by_up_to: OutputsByUpTo<T>,
// pub by_from: OutputsByFrom<T>,
// pub by_range: OutputsByRange<T>,
// pub by_epoch: OutputsByEpoch<T>,
// pub by_size: OutputsBySize<T>,
// pub by_value: OutputsByValue<T>,
// pub by_type: OutputsByType<T>, // all but op-return
}
#[derive(Default)]
pub struct OutputsByTerm<T> {
pub short: T,
pub long: T,
}
#[derive(Default)]
pub struct OutputsByUpTo<T> {
pub _1d: T,
pub _1w: T,
pub _1m: T,
pub _2m: T,
pub _3m: T,
pub _4m: T,
pub _5m: T,
pub _6m: T,
pub _1y: T,
pub _2y: T,
pub _3y: T,
pub _5y: T,
pub _7y: T,
pub _10y: T,
pub _15y: T,
}
#[derive(Default)]
pub struct OutputsByRange<T> {
pub _1d_to_1w: T,
pub _1w_to_1m: T,
pub _1m_to_3m: T,
pub _3m_to_6m: T,
pub _6m_to_1y: T,
pub _1y_to_2y: T,
pub _2y_to_3y: T,
pub _3y_to_5y: T,
pub _5y_to_7y: T,
pub _7y_to_10y: T,
pub _10y_to_15y: T,
}
#[derive(Default)]
pub struct OutputsByFrom<T> {
pub _1y: T,
pub _2y: T,
pub _4y: T,
pub _10y: T,
pub _15y: T,
}
#[derive(Default)]
pub struct OutputsByEpoch<T> {
pub _1: T,
pub _2: T,
pub _3: T,
pub _4: T,
pub _5: T,
}
#[derive(Default)]
pub struct OutputsBySize<T> {
pub from_1_to_10: T,
pub from_10_to_100: T,
pub from_100_to_1_000: T,
pub from_1_000_to_10_000: T,
pub from_10000_to_100_000: T,
pub from_100_000_to_1_000_000: T,
pub from_1_000_000_to_10_000_000: T,
pub from_10_000_000_to_1btc: T,
pub from_1btc_to_10btc: T,
pub from_10btc_to_100btc: T,
pub from_100btc_to_1_000btc: T,
pub from_1_000btc_to_10_000btc: T,
pub from_10_000btc_to_100_000btc: T,
pub from_100_000btc: T,
}
#[derive(Default)]
pub struct OutputsByValue<T> {
pub up_to_1cent: T,
pub from_1c_to_10c: T,
pub from_10c_to_1d: T,
pub from_1d_to_10d: T,
pub from_10usd_to_100usd: T,
pub from_100usd_to_1_000usd: T,
pub from_1_000usd_to_10_000usd: T,
pub from_10_000usd_to_100_000usd: T,
pub from_100_000usd_to_1_000_000usd: T,
pub from_1_000_000usd_to_10_000_000usd: T,
pub from_10_000_000usd_to_100_000_000usd: T,
pub from_100_000_000usd_to_1_000_000_000usd: T,
pub from_1_000_000_000usd: T,
// ...
}
// #[derive(Default)]
// pub struct OutputsByType<T> {}

View File

@@ -0,0 +1,20 @@
#[derive(Default, Clone)]
pub struct OutputsByEpoch<T> {
pub _1: T,
pub _2: T,
pub _3: T,
pub _4: T,
pub _5: T,
}
impl<T> OutputsByEpoch<T> {
pub fn mut_flatten(&mut self) -> Vec<&mut T> {
vec![
&mut self._1,
&mut self._2,
&mut self._3,
&mut self._4,
&mut self._5,
]
}
}

View File

@@ -0,0 +1,20 @@
#[derive(Default, Clone)]
pub struct OutputsByFrom<T> {
pub _1y: T,
pub _2y: T,
pub _4y: T,
pub _10y: T,
pub _15y: T,
}
impl<T> OutputsByFrom<T> {
pub fn mut_flatten(&mut self) -> Vec<&mut T> {
vec![
&mut self._1y,
&mut self._2y,
&mut self._4y,
&mut self._10y,
&mut self._15y,
]
}
}

View File

@@ -0,0 +1,32 @@
#[derive(Default, Clone)]
pub struct OutputsByRange<T> {
pub _1d_to_1w: T,
pub _1w_to_1m: T,
pub _1m_to_3m: T,
pub _3m_to_6m: T,
pub _6m_to_1y: T,
pub _1y_to_2y: T,
pub _2y_to_3y: T,
pub _3y_to_5y: T,
pub _5y_to_7y: T,
pub _7y_to_10y: T,
pub _10y_to_15y: T,
}
impl<T> OutputsByRange<T> {
pub fn mut_flatten(&mut self) -> Vec<&mut T> {
vec![
&mut self._1d_to_1w,
&mut self._1w_to_1m,
&mut self._1m_to_3m,
&mut self._3m_to_6m,
&mut self._6m_to_1y,
&mut self._1y_to_2y,
&mut self._2y_to_3y,
&mut self._3y_to_5y,
&mut self._5y_to_7y,
&mut self._7y_to_10y,
&mut self._10y_to_15y,
]
}
}

View File

@@ -0,0 +1,38 @@
#[derive(Default, Clone)]
pub struct OutputsBySize<T> {
pub from_1sat_to_10sats: T,
pub from_10sats_to_100sats: T,
pub from_100sats_to_1_000sats: T,
pub from_1_000sats_to_10_000sats: T,
pub from_10_000sats_to_100_000sats: T,
pub from_100_000sats_to_1_000_000sats: T,
pub from_1_000_000sats_to_10_000_000sats: T,
pub from_10_000_000sats_to_1btc: T,
pub from_1btc_to_10btc: T,
pub from_10btc_to_100btc: T,
pub from_100btc_to_1_000btc: T,
pub from_1_000btc_to_10_000btc: T,
pub from_10_000btc_to_100_000btc: T,
pub from_100_000btc: T,
}
impl<T> OutputsBySize<T> {
pub fn mut_flatten(&mut self) -> Vec<&mut T> {
vec![
&mut self.from_1sat_to_10sats,
&mut self.from_10sats_to_100sats,
&mut self.from_100sats_to_1_000sats,
&mut self.from_1_000sats_to_10_000sats,
&mut self.from_10_000sats_to_100_000sats,
&mut self.from_100_000sats_to_1_000_000sats,
&mut self.from_1_000_000sats_to_10_000_000sats,
&mut self.from_10_000_000sats_to_1btc,
&mut self.from_1btc_to_10btc,
&mut self.from_10btc_to_100btc,
&mut self.from_100btc_to_1_000btc,
&mut self.from_1_000btc_to_10_000btc,
&mut self.from_10_000btc_to_100_000btc,
&mut self.from_100_000btc,
]
}
}

View File

@@ -0,0 +1,11 @@
#[derive(Default, Clone)]
pub struct OutputsByTerm<T> {
pub short: T,
pub long: T,
}
impl<T> OutputsByTerm<T> {
pub fn mut_flatten(&mut self) -> Vec<&mut T> {
vec![&mut self.short, &mut self.long]
}
}

View File

@@ -0,0 +1,94 @@
use brk_core::OutputType;
#[derive(Default, Clone)]
pub struct OutputsByType<T> {
pub p2pk65: T,
pub p2pk33: T,
pub p2pkh: T,
pub p2ms: T,
pub p2sh: T,
pub op_return: T,
pub p2wpkh: T,
pub p2wsh: T,
pub p2tr: T,
pub p2a: T,
pub empty: T,
pub unknown: T,
}
impl<T> OutputsByType<T> {
pub fn get(&self, output_type: OutputType) -> &T {
match output_type {
OutputType::P2PK65 => &self.p2pk65,
OutputType::P2PK33 => &self.p2pk33,
OutputType::P2PKH => &self.p2pkh,
OutputType::P2MS => &self.p2ms,
OutputType::P2SH => &self.p2sh,
OutputType::OpReturn => &self.op_return,
OutputType::P2WPKH => &self.p2wpkh,
OutputType::P2WSH => &self.p2wsh,
OutputType::P2TR => &self.p2tr,
OutputType::P2A => &self.p2a,
OutputType::Empty => &self.empty,
OutputType::Unknown => &self.unknown,
}
}
pub fn get_mut(&mut self, output_type: OutputType) -> &mut T {
match output_type {
OutputType::P2PK65 => &mut self.p2pk65,
OutputType::P2PK33 => &mut self.p2pk33,
OutputType::P2PKH => &mut self.p2pkh,
OutputType::P2MS => &mut self.p2ms,
OutputType::P2SH => &mut self.p2sh,
OutputType::OpReturn => &mut self.op_return,
OutputType::P2WPKH => &mut self.p2wpkh,
OutputType::P2WSH => &mut self.p2wsh,
OutputType::P2TR => &mut self.p2tr,
OutputType::P2A => &mut self.p2a,
OutputType::Empty => &mut self.empty,
OutputType::Unknown => &mut self.unknown,
}
}
pub fn to_spendable_vec(&self) -> Vec<&T> {
OutputType::as_vec()
.into_iter()
.map(|t| (self.get(t)))
.collect::<Vec<_>>()
}
pub fn as_vec(&mut self) -> Vec<&T> {
vec![
&self.p2pk65,
&self.p2pk33,
&self.p2pkh,
&self.p2ms,
&self.p2sh,
&self.op_return,
&self.p2wpkh,
&self.p2wsh,
&self.p2tr,
&self.p2a,
&self.empty,
&self.unknown,
]
}
pub fn as_mut_vec(&mut self) -> Vec<&mut T> {
vec![
&mut self.p2pk65,
&mut self.p2pk33,
&mut self.p2pkh,
&mut self.p2ms,
&mut self.p2sh,
&mut self.op_return,
&mut self.p2wpkh,
&mut self.p2wsh,
&mut self.p2tr,
&mut self.p2a,
&mut self.empty,
&mut self.unknown,
]
}
}

View File

@@ -0,0 +1,40 @@
#[derive(Default, Clone)]
pub struct OutputsByUpTo<T> {
pub _1d: T,
pub _1w: T,
pub _1m: T,
pub _2m: T,
pub _3m: T,
pub _4m: T,
pub _5m: T,
pub _6m: T,
pub _1y: T,
pub _2y: T,
pub _3y: T,
pub _5y: T,
pub _7y: T,
pub _10y: T,
pub _15y: T,
}
impl<T> OutputsByUpTo<T> {
pub fn mut_flatten(&mut self) -> Vec<&mut T> {
vec![
&mut self._1d,
&mut self._1w,
&mut self._1m,
&mut self._2m,
&mut self._3m,
&mut self._4m,
&mut self._5m,
&mut self._6m,
&mut self._1y,
&mut self._2y,
&mut self._3y,
&mut self._5y,
&mut self._7y,
&mut self._10y,
&mut self._15y,
]
}
}

View File

@@ -0,0 +1,37 @@
#[derive(Default, Clone)]
pub struct OutputsByValue<T> {
pub up_to_1cent: T,
pub from_1c_to_10c: T,
pub from_10c_to_1d: T,
pub from_1d_to_10d: T,
pub from_10usd_to_100usd: T,
pub from_100usd_to_1_000usd: T,
pub from_1_000usd_to_10_000usd: T,
pub from_10_000usd_to_100_000usd: T,
pub from_100_000usd_to_1_000_000usd: T,
pub from_1_000_000usd_to_10_000_000usd: T,
pub from_10_000_000usd_to_100_000_000usd: T,
pub from_100_000_000usd_to_1_000_000_000usd: T,
pub from_1_000_000_000usd: T,
// ...
}
impl<T> OutputsByValue<T> {
pub fn mut_flatten(&mut self) -> Vec<&mut T> {
vec![
&mut self.up_to_1cent,
&mut self.from_1c_to_10c,
&mut self.from_10c_to_1d,
&mut self.from_1d_to_10d,
&mut self.from_10usd_to_100usd,
&mut self.from_100usd_to_1_000usd,
&mut self.from_1_000usd_to_10_000usd,
&mut self.from_10_000usd_to_100_000usd,
&mut self.from_100_000usd_to_1_000_000usd,
&mut self.from_1_000_000usd_to_10_000_000usd,
&mut self.from_10_000_000usd_to_100_000_000usd,
&mut self.from_100_000_000usd_to_1_000_000_000usd,
&mut self.from_1_000_000_000usd,
]
}
}

View File

@@ -0,0 +1,45 @@
#![allow(unused)]
use brk_core::OutputType;
use crate::vecs::utxos::Vecs_;
mod by_epoch;
mod by_from;
mod by_range;
mod by_size;
mod by_term;
mod by_type;
mod by_up_to;
mod by_value;
pub use by_epoch::*;
pub use by_from::*;
pub use by_range::*;
pub use by_size::*;
pub use by_term::*;
pub use by_type::*;
pub use by_up_to::*;
pub use by_value::*;
#[derive(Default, Clone)]
pub struct Outputs<T> {
pub all: T,
pub by_term: OutputsByTerm<T>,
pub by_up_to: OutputsByUpTo<T>,
pub by_from: OutputsByFrom<T>,
pub by_range: OutputsByRange<T>,
pub by_epoch: OutputsByEpoch<T>,
pub by_size: OutputsBySize<T>,
pub by_value: OutputsByValue<T>,
pub by_type: OutputsByType<T>,
}
impl<T> Outputs<T> {
pub fn mut_flatten(&mut self) -> Vec<&mut T> {
[vec![&mut self.all], self.by_term.mut_flatten()]
.into_iter()
.flatten()
.collect::<Vec<_>>()
}
}

View File

@@ -241,6 +241,8 @@ impl Vecs {
self.indexes_to_block_vbytes.vecs(), self.indexes_to_block_vbytes.vecs(),
self.indexes_to_block_weight.vecs(), self.indexes_to_block_weight.vecs(),
] ]
.concat() .into_iter()
.flatten()
.collect::<Vec<_>>()
} }
} }

View File

@@ -144,6 +144,8 @@ impl Vecs {
self._50.vecs(), self._50.vecs(),
self._100.vecs(), self._100.vecs(),
] ]
.concat() .into_iter()
.flatten()
.collect::<Vec<_>>()
} }
} }

View File

@@ -1089,6 +1089,8 @@ impl Vecs {
self.chainindexes_to_low_in_sats.vecs(), self.chainindexes_to_low_in_sats.vecs(),
self.chainindexes_to_open_in_sats.vecs(), self.chainindexes_to_open_in_sats.vecs(),
] ]
.concat() .into_iter()
.flatten()
.collect::<Vec<_>>()
} }
} }

View File

@@ -155,6 +155,8 @@ where
self.yearindex.vecs(), self.yearindex.vecs(),
self.decadeindex.vecs(), self.decadeindex.vecs(),
] ]
.concat() .into_iter()
.flatten()
.collect::<Vec<_>>()
} }
} }

View File

@@ -215,6 +215,8 @@ where
// self.halvingepoch.vecs(), // self.halvingepoch.vecs(),
self.decadeindex.vecs(), self.decadeindex.vecs(),
] ]
.concat() .into_iter()
.flatten()
.collect::<Vec<_>>()
} }
} }

View File

@@ -92,6 +92,8 @@ where
self.difficultyepoch.vecs(), self.difficultyepoch.vecs(),
// self.halvingepoch.vecs(), // self.halvingepoch.vecs(),
] ]
.concat() .into_iter()
.flatten()
.collect::<Vec<_>>()
} }
} }

View File

@@ -211,6 +211,8 @@ where
// self.halvingepoch.vecs(), // self.halvingepoch.vecs(),
self.decadeindex.vecs(), self.decadeindex.vecs(),
] ]
.concat() .into_iter()
.flatten()
.collect::<Vec<_>>()
} }
} }

View File

@@ -896,6 +896,8 @@ impl ComputedRatioVecsFromDateIndex {
self.ratio_m3sd_as_price.vecs(), self.ratio_m3sd_as_price.vecs(),
self.ratio_zscore.vecs(), self.ratio_zscore.vecs(),
] ]
.concat() .into_iter()
.flatten()
.collect::<Vec<_>>()
} }
} }

View File

@@ -165,6 +165,8 @@ impl ComputedValueVecsFromHeight {
self.bitcoin.vecs(), self.bitcoin.vecs(),
self.dollars.as_ref().map_or(vec![], |v| v.vecs()), self.dollars.as_ref().map_or(vec![], |v| v.vecs()),
] ]
.concat() .into_iter()
.flatten()
.collect::<Vec<_>>()
} }
} }

View File

@@ -221,6 +221,8 @@ impl ComputedValueVecsFromTxindex {
self.bitcoin.vecs(), self.bitcoin.vecs(),
self.dollars.as_ref().map_or(vec![], |v| v.vecs()), self.dollars.as_ref().map_or(vec![], |v| v.vecs()),
] ]
.concat() .into_iter()
.flatten()
.collect::<Vec<_>>()
} }
} }

View File

@@ -13,7 +13,7 @@ use super::{
indexes, transactions, indexes, transactions,
}; };
const VERSION: Version = Version::new(0); const VERSION: Version = Version::ZERO;
#[derive(Clone)] #[derive(Clone)]
pub struct Vecs { pub struct Vecs {
@@ -1774,6 +1774,8 @@ impl Vecs {
self.dca_class_2016_returns.vecs(), self.dca_class_2016_returns.vecs(),
self.dca_class_2015_returns.vecs(), self.dca_class_2015_returns.vecs(),
] ]
.concat() .into_iter()
.flatten()
.collect::<Vec<_>>()
} }
} }

View File

@@ -123,6 +123,8 @@ impl Vecs {
self.indexes_to_difficultyepoch.vecs(), self.indexes_to_difficultyepoch.vecs(),
self.indexes_to_halvingepoch.vecs(), self.indexes_to_halvingepoch.vecs(),
] ]
.concat() .into_iter()
.flatten()
.collect::<Vec<_>>()
} }
} }

View File

@@ -25,7 +25,7 @@ pub struct Vecs {
pub mining: mining::Vecs, pub mining: mining::Vecs,
pub market: market::Vecs, pub market: market::Vecs,
pub transactions: transactions::Vecs, pub transactions: transactions::Vecs,
pub utxos: utxos::Vecs, // pub utxos: utxos::Vecs,
pub fetched: Option<fetched::Vecs>, pub fetched: Option<fetched::Vecs>,
} }
@@ -49,7 +49,7 @@ impl Vecs {
mining: mining::Vecs::forced_import(path, computation, compressed)?, mining: mining::Vecs::forced_import(path, computation, compressed)?,
constants: constants::Vecs::forced_import(path, computation, compressed)?, constants: constants::Vecs::forced_import(path, computation, compressed)?,
market: market::Vecs::forced_import(path, computation, compressed)?, market: market::Vecs::forced_import(path, computation, compressed)?,
utxos: utxos::Vecs::forced_import(path, computation, compressed, fetched.as_ref())?, // utxos: utxos::Vecs::forced_import(path, computation, compressed, fetched.as_ref())?,
transactions: transactions::Vecs::forced_import( transactions: transactions::Vecs::forced_import(
path, path,
indexer, indexer,
@@ -110,14 +110,14 @@ impl Vecs {
)?; )?;
} }
self.utxos.compute( // self.utxos.compute(
indexer, // indexer,
&self.indexes, // &self.indexes,
&self.transactions, // &self.transactions,
self.fetched.as_ref(), // self.fetched.as_ref(),
&starting_indexes, // &starting_indexes,
exit, // exit,
)?; // )?;
Ok(()) Ok(())
} }
@@ -130,9 +130,11 @@ impl Vecs {
self.mining.vecs(), self.mining.vecs(),
self.market.vecs(), self.market.vecs(),
self.transactions.vecs(), self.transactions.vecs(),
self.utxos.vecs(), // self.utxos.vecs(),
self.fetched.as_ref().map_or(vec![], |v| v.vecs()), self.fetched.as_ref().map_or(vec![], |v| v.vecs()),
] ]
.concat() .into_iter()
.flatten()
.collect::<Vec<_>>()
} }
} }

View File

@@ -1169,6 +1169,8 @@ impl Vecs {
self.indexes_to_exact_utxo_count.vecs(), self.indexes_to_exact_utxo_count.vecs(),
self.indexes_to_unclaimed_rewards.vecs(), self.indexes_to_unclaimed_rewards.vecs(),
] ]
.concat() .into_iter()
.flatten()
.collect::<Vec<_>>()
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -32,6 +32,46 @@ pub enum OutputType {
Unknown = 255, Unknown = 255,
} }
impl OutputType {
pub fn is_spendable(&self) -> bool {
match self {
Self::P2PK65 => true,
Self::P2PK33 => true,
Self::P2PKH => true,
Self::P2MS => true,
Self::P2SH => true,
Self::OpReturn => false,
Self::P2WPKH => true,
Self::P2WSH => true,
Self::P2TR => true,
Self::P2A => true,
Self::Empty => false,
Self::Unknown => false,
}
}
pub fn is_unspendable(&self) -> bool {
!self.is_spendable()
}
pub fn as_vec() -> Vec<Self> {
vec![
Self::P2PK65,
Self::P2PK33,
Self::P2PKH,
Self::P2MS,
Self::P2SH,
Self::OpReturn,
Self::P2WPKH,
Self::P2WSH,
Self::P2TR,
Self::P2A,
Self::Empty,
Self::Unknown,
]
}
}
impl From<&ScriptBuf> for OutputType { impl From<&ScriptBuf> for OutputType {
fn from(script: &ScriptBuf) -> Self { fn from(script: &ScriptBuf) -> Self {
if script.is_p2pk() { if script.is_p2pk() {

View File

@@ -15,6 +15,7 @@ use super::{
Debug, Debug,
Deref, Deref,
Clone, Clone,
Default,
Copy, Copy,
PartialEq, PartialEq,
Eq, Eq,

View File

@@ -1,4 +1,7 @@
use std::ops::{Add, Div}; use std::{
cmp::Ordering,
ops::{Add, Div},
};
use derive_deref::Deref; use derive_deref::Deref;
use jiff::{civil::date, tz::TimeZone}; use jiff::{civil::date, tz::TimeZone};
@@ -26,6 +29,8 @@ use super::Date;
)] )]
pub struct Timestamp(u32); pub struct Timestamp(u32);
const ONE_DAY_IN_SEC: i64 = 24 * 60 * 60;
impl Timestamp { impl Timestamp {
pub const ZERO: Self = Self(0); pub const ZERO: Self = Self(0);
@@ -39,6 +44,19 @@ impl Timestamp {
let d = date(d.year(), d.month(), d.day()).at(d.hour(), d.minute(), 0, 0); let d = date(d.year(), d.month(), d.day()).at(d.hour(), d.minute(), 0, 0);
Self::from(d.to_zoned(TimeZone::UTC).unwrap().timestamp()) Self::from(d.to_zoned(TimeZone::UTC).unwrap().timestamp())
} }
pub fn difference_in_days_between(earlier: Self, later: Self) -> usize {
match later.cmp(&earlier) {
Ordering::Less => panic!("Shouldn't be used with inverted"),
Ordering::Equal => 0,
Ordering::Greater => {
(jiff::Timestamp::from(earlier)
.duration_until(jiff::Timestamp::from(later))
.as_secs()
/ ONE_DAY_IN_SEC) as usize
}
}
}
} }
impl From<u32> for Timestamp { impl From<u32> for Timestamp {

View File

@@ -681,7 +681,7 @@ impl EagerVec<DateIndex, Sats> {
exit: &Exit, exit: &Exit,
) -> Result<()> { ) -> Result<()> {
self.validate_computed_version_or_reset_file( self.validate_computed_version_or_reset_file(
Version::new(5) + self.inner.version() + closes.version(), Version::ZERO + self.inner.version() + closes.version(),
)?; )?;
let mut other_iter = closes.iter(); let mut other_iter = closes.iter();

View File

@@ -740,7 +740,8 @@ function createUtils() {
id.includes("coinbase") || id.includes("coinbase") ||
id.includes("subsidy") || id.includes("subsidy") ||
id.endsWith("stack") || id.endsWith("stack") ||
id.includes("supply") id.includes("supply") ||
id.includes("rewards")
) { ) {
unit = "Sats"; unit = "Sats";
} else if ( } else if (
@@ -798,6 +799,8 @@ function createUtils() {
return numberToUSFormat(value, 1); return numberToUSFormat(value, 1);
} else if (absoluteValue < 100_000) { } else if (absoluteValue < 100_000) {
return numberToUSFormat(value, 0); return numberToUSFormat(value, 0);
} else if (absoluteValue < 200_000) {
return `${numberToUSFormat(value / 1_000, 2)}K`;
} else if (absoluteValue < 1_000_000) { } else if (absoluteValue < 1_000_000) {
return `${numberToUSFormat(value / 1_000, 1)}K`; return `${numberToUSFormat(value / 1_000, 1)}K`;
} else if (absoluteValue >= 900_000_000_000_000_000) { } else if (absoluteValue >= 900_000_000_000_000_000) {

View File

@@ -325,6 +325,23 @@ function createPartialOptions(colors) {
]; ];
} }
/**
* @param {Object} args
* @param {ChartableVecId & VecIdSumBase & TotalVecIdBase} args.key
* @param {string} args.name
*/
function createBaseSumTotalSeries({ key, name }) {
return [
createBaseSeries({
key,
name,
}),
...createSumTotalSeries({
concat: key,
}),
];
}
return [ return [
{ {
name: "Charts", name: "Charts",
@@ -901,6 +918,24 @@ function createPartialOptions(colors) {
...createAverageSumTotalMinMaxPercentilesSeries("fee-in-usd"), ...createAverageSumTotalMinMaxPercentilesSeries("fee-in-usd"),
], ],
}, },
{
name: "Unclaimed Rewards",
title: "Unclaimed Rewards",
bottom: [
...createBaseSumTotalSeries({
key: "unclaimed-rewards",
name: "unclaimed",
}),
...createBaseSumTotalSeries({
key: "unclaimed-rewards-in-btc",
name: "unclaimed",
}),
...createBaseSumTotalSeries({
key: "unclaimed-rewards-in-usd",
name: "unclaimed",
}),
],
},
{ {
name: "Feerate", name: "Feerate",
title: "Transaction Fee Rate", title: "Transaction Fee Rate",
@@ -1338,62 +1373,62 @@ function createPartialOptions(colors) {
{ {
name: "UTXOs", name: "UTXOs",
tree: [ tree: [
{ // {
name: "supply", // name: "supply",
title: "Supply", // title: "Supply",
bottom: [ // bottom: [
createBaseSeries({ // createBaseSeries({
key: "supply", // key: "supply",
name: "Supply", // name: "Supply",
}), // }),
createBaseSeries({ // createBaseSeries({
key: "supply-in-btc", // key: "supply-in-btc",
name: "Supply", // name: "Supply",
}), // }),
createBaseSeries({ // createBaseSeries({
key: "supply-in-usd", // key: "supply-in-usd",
name: "Supply", // name: "Supply",
}), // }),
], // ],
}, // },
{ // {
name: "unspendable supply", // name: "unspendable supply",
title: "Unspendable Supply", // title: "Unspendable Supply",
bottom: [ // bottom: [
createBaseSeries({ // createBaseSeries({
key: "unspendable-supply", // key: "unspendable-supply",
name: "Supply", // name: "Supply",
}), // }),
createBaseSeries({ // createBaseSeries({
key: "unspendable-supply-in-btc", // key: "unspendable-supply-in-btc",
name: "Supply", // name: "Supply",
}), // }),
createBaseSeries({ // createBaseSeries({
key: "unspendable-supply-in-usd", // key: "unspendable-supply-in-usd",
name: "Supply", // name: "Supply",
}), // }),
], // ],
}, // },
{ // {
name: "count", // name: "count",
title: "UTXO Count", // title: "UTXO Count",
bottom: [ // bottom: [
createBaseSeries({ // createBaseSeries({
key: "utxo-count", // key: "utxo-count",
name: "Count", // name: "Count",
}), // }),
], // ],
}, // },
{ // {
name: "realized cap", // name: "realized cap",
title: "Realized Capitalization", // title: "Realized Capitalization",
bottom: [ // bottom: [
createBaseSeries({ // createBaseSeries({
key: "realized-cap", // key: "realized-cap",
name: "Realized Cap", // name: "Realized Cap",
}), // }),
], // ],
}, // },
], ],
}, },
], ],

View File

@@ -893,7 +893,6 @@ export function createVecIdToIndexes() {
"price-8y-ago": [DateIndex, DecadeIndex, MonthIndex, QuarterIndex, WeekIndex, YearIndex], "price-8y-ago": [DateIndex, DecadeIndex, MonthIndex, QuarterIndex, WeekIndex, YearIndex],
"quarterindex": [MonthIndex, QuarterIndex], "quarterindex": [MonthIndex, QuarterIndex],
"rawlocktime": [TxIndex], "rawlocktime": [TxIndex],
"realized-cap": [DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, WeekIndex, YearIndex],
"subsidy": [Height], "subsidy": [Height],
"subsidy-10p": [DateIndex], "subsidy-10p": [DateIndex],
"subsidy-25p": [DateIndex], "subsidy-25p": [DateIndex],
@@ -924,9 +923,6 @@ export function createVecIdToIndexes() {
"subsidy-median": [DateIndex], "subsidy-median": [DateIndex],
"subsidy-min": [DateIndex, DecadeIndex, DifficultyEpoch, MonthIndex, QuarterIndex, WeekIndex, YearIndex], "subsidy-min": [DateIndex, DecadeIndex, DifficultyEpoch, MonthIndex, QuarterIndex, WeekIndex, YearIndex],
"subsidy-sum": [DateIndex, DecadeIndex, DifficultyEpoch, MonthIndex, QuarterIndex, WeekIndex, YearIndex], "subsidy-sum": [DateIndex, DecadeIndex, DifficultyEpoch, MonthIndex, QuarterIndex, WeekIndex, YearIndex],
"supply": [DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, WeekIndex, YearIndex],
"supply-in-btc": [DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, WeekIndex, YearIndex],
"supply-in-usd": [DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, WeekIndex, YearIndex],
"timestamp": [DateIndex, DecadeIndex, DifficultyEpoch, HalvingEpoch, Height, MonthIndex, QuarterIndex, WeekIndex, YearIndex], "timestamp": [DateIndex, DecadeIndex, DifficultyEpoch, HalvingEpoch, Height, MonthIndex, QuarterIndex, WeekIndex, YearIndex],
"timestamp-fixed": [Height], "timestamp-fixed": [Height],
"total-block-count": [DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, WeekIndex, YearIndex], "total-block-count": [DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, WeekIndex, YearIndex],
@@ -1017,10 +1013,6 @@ export function createVecIdToIndexes() {
"unknownoutput-count-min": [DateIndex, DecadeIndex, DifficultyEpoch, MonthIndex, QuarterIndex, WeekIndex, YearIndex], "unknownoutput-count-min": [DateIndex, DecadeIndex, DifficultyEpoch, MonthIndex, QuarterIndex, WeekIndex, YearIndex],
"unknownoutput-count-sum": [DateIndex, DecadeIndex, DifficultyEpoch, MonthIndex, QuarterIndex, WeekIndex, YearIndex], "unknownoutput-count-sum": [DateIndex, DecadeIndex, DifficultyEpoch, MonthIndex, QuarterIndex, WeekIndex, YearIndex],
"unknownoutputindex": [UnknownOutputIndex], "unknownoutputindex": [UnknownOutputIndex],
"unspendable-supply": [DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, WeekIndex, YearIndex],
"unspendable-supply-in-btc": [DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, WeekIndex, YearIndex],
"unspendable-supply-in-usd": [DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, WeekIndex, YearIndex],
"utxo-count": [DateIndex, DecadeIndex, DifficultyEpoch, Height, MonthIndex, QuarterIndex, WeekIndex, YearIndex],
"value": [InputIndex, OutputIndex], "value": [InputIndex, OutputIndex],
"vbytes": [Height], "vbytes": [Height],
"vsize": [TxIndex], "vsize": [TxIndex],