mirror of
https://github.com/bitcoinresearchkit/brk.git
synced 2026-06-09 22:43:33 -07:00
global: snapshot
This commit is contained in:
Generated
-6
@@ -3899,8 +3899,6 @@ checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc"
|
||||
[[package]]
|
||||
name = "seqdb"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c54ab988c96efa9d275ca2b12bf2d3c6adec993b8e82ea31a88c984abdaa14fa"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
@@ -4727,8 +4725,6 @@ checksum = "8f54a172d0620933a27a4360d3db3e2ae0dd6cceae9730751a036bbf182c4b23"
|
||||
[[package]]
|
||||
name = "vecdb"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e5c4ec34c376be3a41435eeb7672d0ea0e9c1d60c5d1d90218912588f91abea"
|
||||
dependencies = [
|
||||
"ctrlc",
|
||||
"log",
|
||||
@@ -4747,8 +4743,6 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "vecdb_derive"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "778c4874c05822465e28cae6a7dead593a73124ec80afb85b85adae5ac883368"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 2.0.106",
|
||||
|
||||
+2
-2
@@ -52,8 +52,8 @@ serde_bytes = "0.11.17"
|
||||
serde_derive = "1.0.219"
|
||||
serde_json = { version = "1.0.143", features = ["float_roundtrip"] }
|
||||
tokio = { version = "1.47.1", features = ["rt-multi-thread"] }
|
||||
# vecdb = { path = "../seqdb/crates/vecdb", features = ["derive"]}
|
||||
vecdb = { version = "0.2.5", features = ["derive"]}
|
||||
vecdb = { path = "../seqdb/crates/vecdb", features = ["derive"]}
|
||||
# vecdb = { version = "0.2.5", features = ["derive"]}
|
||||
zerocopy = "0.8.26"
|
||||
zerocopy-derive = "0.8.26"
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
- **add rollback of states (in stateful)**
|
||||
- add costs basis by percentile (percentile cost basis) back
|
||||
- add support for per index computation
|
||||
- fix min feerate which is always ZERO due to coinbase transaction
|
||||
- fix min fee_rate which is always ZERO due to coinbase transaction
|
||||
- before computing multiple sources check their length, panic if not equal
|
||||
- add oracle price dataset (https://utxo.live/oracle/UTXOracle.py)
|
||||
- add address counts relative to all datasets
|
||||
|
||||
@@ -1,279 +0,0 @@
|
||||
use std::path::Path;
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_structs::{
|
||||
CheckedSub, DifficultyEpoch, HalvingEpoch, Height, StoredU32, StoredU64, Timestamp, Version,
|
||||
Weight,
|
||||
};
|
||||
use vecdb::{AnyCollectableVec, Database, EagerVec, Exit, PAGE_SIZE, VecIterator};
|
||||
|
||||
use crate::grouped::Source;
|
||||
|
||||
use super::{
|
||||
Indexes,
|
||||
grouped::{ComputedVecsFromDateIndex, ComputedVecsFromHeight, VecBuilderOptions},
|
||||
indexes,
|
||||
};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Vecs {
|
||||
db: Database,
|
||||
|
||||
pub height_to_interval: EagerVec<Height, Timestamp>,
|
||||
pub height_to_vbytes: EagerVec<Height, StoredU64>,
|
||||
pub difficultyepoch_to_timestamp: EagerVec<DifficultyEpoch, Timestamp>,
|
||||
pub halvingepoch_to_timestamp: EagerVec<HalvingEpoch, Timestamp>,
|
||||
pub timeindexes_to_timestamp: ComputedVecsFromDateIndex<Timestamp>,
|
||||
pub indexes_to_block_count: ComputedVecsFromHeight<StoredU32>,
|
||||
pub indexes_to_block_interval: ComputedVecsFromHeight<Timestamp>,
|
||||
pub indexes_to_block_size: ComputedVecsFromHeight<StoredU64>,
|
||||
pub indexes_to_block_vbytes: ComputedVecsFromHeight<StoredU64>,
|
||||
pub indexes_to_block_weight: ComputedVecsFromHeight<Weight>,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
pub fn forced_import(parent: &Path, version: Version, indexes: &indexes::Vecs) -> Result<Self> {
|
||||
let db = Database::open(&parent.join("blocks"))?;
|
||||
db.set_min_len(PAGE_SIZE * 1_000_000)?;
|
||||
|
||||
Ok(Self {
|
||||
height_to_interval: EagerVec::forced_import_compressed(
|
||||
&db,
|
||||
"interval",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
timeindexes_to_timestamp: ComputedVecsFromDateIndex::forced_import(
|
||||
&db,
|
||||
"timestamp",
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_first(),
|
||||
)?,
|
||||
indexes_to_block_interval: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"block_interval",
|
||||
Source::None,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default()
|
||||
.add_percentiles()
|
||||
.add_minmax()
|
||||
.add_average(),
|
||||
)?,
|
||||
indexes_to_block_count: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"block_count",
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_sum().add_cumulative(),
|
||||
)?,
|
||||
indexes_to_block_weight: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"block_weight",
|
||||
Source::None,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default()
|
||||
.add_sum()
|
||||
.add_minmax()
|
||||
.add_average()
|
||||
.add_percentiles()
|
||||
.add_cumulative(),
|
||||
)?,
|
||||
indexes_to_block_size: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"block_size",
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default()
|
||||
.add_sum()
|
||||
.add_minmax()
|
||||
.add_average()
|
||||
.add_percentiles()
|
||||
.add_cumulative(),
|
||||
)?,
|
||||
height_to_vbytes: EagerVec::forced_import_compressed(
|
||||
&db,
|
||||
"vbytes",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
indexes_to_block_vbytes: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"block_vbytes",
|
||||
Source::None,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default()
|
||||
.add_sum()
|
||||
.add_minmax()
|
||||
.add_average()
|
||||
.add_percentiles()
|
||||
.add_cumulative(),
|
||||
)?,
|
||||
difficultyepoch_to_timestamp: EagerVec::forced_import_compressed(
|
||||
&db,
|
||||
"timestamp",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
halvingepoch_to_timestamp: EagerVec::forced_import_compressed(
|
||||
&db,
|
||||
"timestamp",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
|
||||
db,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn compute(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.compute_(indexer, indexes, starting_indexes, exit)?;
|
||||
self.db.flush_then_punch()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn compute_(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.timeindexes_to_timestamp.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, indexes, starting_indexes, exit| {
|
||||
vec.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
&indexes.dateindex_to_date,
|
||||
|(di, d, ..)| (di, Timestamp::from(d)),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_block_count.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_range(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs.height_to_weight,
|
||||
|h| (h, StoredU32::from(1_u32)),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
let mut height_to_timestamp_iter = indexer.vecs.height_to_timestamp.iter();
|
||||
self.height_to_interval.compute_transform(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs.height_to_timestamp,
|
||||
|(height, timestamp, ..)| {
|
||||
let interval = height.decremented().map_or(Timestamp::ZERO, |prev_h| {
|
||||
let prev_timestamp = height_to_timestamp_iter.unwrap_get_inner(prev_h);
|
||||
timestamp
|
||||
.checked_sub(prev_timestamp)
|
||||
.unwrap_or(Timestamp::ZERO)
|
||||
});
|
||||
(height, interval)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.indexes_to_block_interval.compute_rest(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(&self.height_to_interval),
|
||||
)?;
|
||||
|
||||
self.indexes_to_block_weight.compute_rest(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(&indexer.vecs.height_to_weight),
|
||||
)?;
|
||||
|
||||
self.indexes_to_block_size.compute_rest(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(&indexer.vecs.height_to_total_size),
|
||||
)?;
|
||||
|
||||
self.height_to_vbytes.compute_transform(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs.height_to_weight,
|
||||
|(h, w, ..)| {
|
||||
(
|
||||
h,
|
||||
StoredU64::from(bitcoin::Weight::from(w).to_vbytes_floor()),
|
||||
)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.indexes_to_block_vbytes.compute_rest(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(&self.height_to_vbytes),
|
||||
)?;
|
||||
|
||||
let mut height_to_timestamp_iter = indexer.vecs.height_to_timestamp.iter();
|
||||
|
||||
self.difficultyepoch_to_timestamp.compute_transform(
|
||||
starting_indexes.difficultyepoch,
|
||||
&indexes.difficultyepoch_to_first_height,
|
||||
|(i, h, ..)| (i, height_to_timestamp_iter.unwrap_get_inner(h)),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.halvingepoch_to_timestamp.compute_transform(
|
||||
starting_indexes.halvingepoch,
|
||||
&indexes.halvingepoch_to_first_height,
|
||||
|(i, h, ..)| (i, height_to_timestamp_iter.unwrap_get_inner(h)),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
||||
[
|
||||
vec![
|
||||
&self.height_to_interval as &dyn AnyCollectableVec,
|
||||
&self.height_to_vbytes,
|
||||
&self.difficultyepoch_to_timestamp,
|
||||
&self.halvingepoch_to_timestamp,
|
||||
],
|
||||
self.timeindexes_to_timestamp.vecs(),
|
||||
self.indexes_to_block_count.vecs(),
|
||||
self.indexes_to_block_interval.vecs(),
|
||||
self.indexes_to_block_size.vecs(),
|
||||
self.indexes_to_block_vbytes.vecs(),
|
||||
self.indexes_to_block_weight.vecs(),
|
||||
]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,9 @@ use std::path::Path;
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_structs::{
|
||||
CheckedSub, Feerate, HalvingEpoch, Height, InputIndex, OutputIndex, Sats, StoredBool,
|
||||
StoredU32, StoredU64, TxIndex, TxVersion, Version, Weight,
|
||||
CheckedSub, Date, DateIndex, DifficultyEpoch, Dollars, FeeRate, HalvingEpoch, Height,
|
||||
InputIndex, OutputIndex, Sats, StoredBool, StoredF32, StoredF64, StoredU32, StoredU64,
|
||||
Timestamp, TxIndex, TxVersion, Version, Weight,
|
||||
};
|
||||
use vecdb::{
|
||||
AnyCloneableIterableVec, AnyCollectableVec, AnyIterableVec, Database, EagerVec, Exit,
|
||||
@@ -12,25 +13,37 @@ use vecdb::{
|
||||
};
|
||||
|
||||
use crate::grouped::{
|
||||
ComputedValueVecsFromHeight, ComputedValueVecsFromTxindex, ComputedVecsFromHeight,
|
||||
ComputedVecsFromTxindex, Source, VecBuilderOptions,
|
||||
ComputedValueVecsFromHeight, ComputedValueVecsFromTxindex, ComputedVecsFromDateIndex,
|
||||
ComputedVecsFromHeight, ComputedVecsFromTxindex, Source, VecBuilderOptions,
|
||||
};
|
||||
|
||||
use super::{Indexes, indexes, price};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
const TARGET_BLOCKS_PER_DAY: f64 = 144.0;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Vecs {
|
||||
db: Database,
|
||||
|
||||
// pub txindex_to_is_v1: LazyVec<Txindex, bool>,
|
||||
// pub txindex_to_is_v2: LazyVec<Txindex, bool>,
|
||||
// pub txindex_to_is_v3: LazyVec<Txindex, bool>,
|
||||
pub height_to_interval: EagerVec<Height, Timestamp>,
|
||||
pub height_to_vbytes: EagerVec<Height, StoredU64>,
|
||||
pub difficultyepoch_to_timestamp: EagerVec<DifficultyEpoch, Timestamp>,
|
||||
pub halvingepoch_to_timestamp: EagerVec<HalvingEpoch, Timestamp>,
|
||||
pub timeindexes_to_timestamp: ComputedVecsFromDateIndex<Timestamp>,
|
||||
pub indexes_to_block_count: ComputedVecsFromHeight<StoredU32>,
|
||||
pub indexes_to_block_interval: ComputedVecsFromHeight<Timestamp>,
|
||||
pub indexes_to_block_size: ComputedVecsFromHeight<StoredU64>,
|
||||
pub indexes_to_block_vbytes: ComputedVecsFromHeight<StoredU64>,
|
||||
pub indexes_to_block_weight: ComputedVecsFromHeight<Weight>,
|
||||
pub indexes_to_difficulty: ComputedVecsFromHeight<StoredF64>,
|
||||
pub indexes_to_difficultyepoch: ComputedVecsFromDateIndex<DifficultyEpoch>,
|
||||
pub indexes_to_halvingepoch: ComputedVecsFromDateIndex<HalvingEpoch>,
|
||||
|
||||
pub indexes_to_coinbase: ComputedValueVecsFromHeight,
|
||||
pub indexes_to_emptyoutput_count: ComputedVecsFromHeight<StoredU64>,
|
||||
pub indexes_to_fee: ComputedValueVecsFromTxindex,
|
||||
pub indexes_to_feerate: ComputedVecsFromTxindex<Feerate>,
|
||||
pub indexes_to_fee_rate: ComputedVecsFromTxindex<FeeRate>,
|
||||
/// Value == 0 when Coinbase
|
||||
pub txindex_to_input_value:
|
||||
LazyVecFrom3<TxIndex, Sats, TxIndex, InputIndex, TxIndex, StoredU64, InputIndex, Sats>,
|
||||
@@ -65,8 +78,18 @@ pub struct Vecs {
|
||||
pub txindex_to_vsize: LazyVecFrom1<TxIndex, StoredU64, TxIndex, Weight>,
|
||||
pub txindex_to_weight: LazyVecFrom2<TxIndex, Weight, TxIndex, StoredU32, TxIndex, StoredU32>,
|
||||
pub txindex_to_fee: EagerVec<TxIndex, Sats>,
|
||||
pub txindex_to_feerate: EagerVec<TxIndex, Feerate>,
|
||||
pub txindex_to_fee_rate: EagerVec<TxIndex, FeeRate>,
|
||||
pub indexes_to_exact_utxo_count: ComputedVecsFromHeight<StoredU64>,
|
||||
pub dateindex_to_fee_dominance: EagerVec<DateIndex, StoredF32>,
|
||||
pub dateindex_to_subsidy_dominance: EagerVec<DateIndex, StoredF32>,
|
||||
pub indexes_to_subsidy_usd_1y_sma: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
pub indexes_to_puell_multiple: Option<ComputedVecsFromDateIndex<StoredF32>>,
|
||||
pub indexes_to_hash_rate: ComputedVecsFromDateIndex<StoredF64>,
|
||||
pub indexes_to_hash_rate_1w_sma: ComputedVecsFromDateIndex<StoredF64>,
|
||||
pub indexes_to_hash_rate_1m_sma: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub indexes_to_hash_rate_2m_sma: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub indexes_to_hash_rate_1y_sma: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub indexes_to_difficulty_as_hash: ComputedVecsFromDateIndex<StoredF32>,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
@@ -77,7 +100,7 @@ impl Vecs {
|
||||
indexes: &indexes::Vecs,
|
||||
price: Option<&price::Vecs>,
|
||||
) -> Result<Self> {
|
||||
let db = Database::open(&parent.join("transactions"))?;
|
||||
let db = Database::open(&parent.join("chain"))?;
|
||||
db.set_min_len(PAGE_SIZE * 10_000_000)?;
|
||||
|
||||
let compute_dollars = price.is_some();
|
||||
@@ -262,10 +285,131 @@ impl Vecs {
|
||||
let txindex_to_fee =
|
||||
EagerVec::forced_import_compressed(&db, "fee", version + VERSION + Version::ZERO)?;
|
||||
|
||||
let txindex_to_feerate =
|
||||
EagerVec::forced_import_compressed(&db, "feerate", version + VERSION + Version::ZERO)?;
|
||||
let txindex_to_fee_rate =
|
||||
EagerVec::forced_import_compressed(&db, "fee_rate", version + VERSION + Version::ZERO)?;
|
||||
|
||||
Ok(Self {
|
||||
height_to_interval: EagerVec::forced_import_compressed(
|
||||
&db,
|
||||
"interval",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
timeindexes_to_timestamp: ComputedVecsFromDateIndex::forced_import(
|
||||
&db,
|
||||
"timestamp",
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_first(),
|
||||
)?,
|
||||
indexes_to_block_interval: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"block_interval",
|
||||
Source::None,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default()
|
||||
.add_percentiles()
|
||||
.add_minmax()
|
||||
.add_average(),
|
||||
)?,
|
||||
indexes_to_block_count: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"block_count",
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_sum().add_cumulative(),
|
||||
)?,
|
||||
indexes_to_block_weight: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"block_weight",
|
||||
Source::None,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default()
|
||||
.add_sum()
|
||||
.add_minmax()
|
||||
.add_average()
|
||||
.add_percentiles()
|
||||
.add_cumulative(),
|
||||
)?,
|
||||
indexes_to_block_size: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"block_size",
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default()
|
||||
.add_sum()
|
||||
.add_minmax()
|
||||
.add_average()
|
||||
.add_percentiles()
|
||||
.add_cumulative(),
|
||||
)?,
|
||||
height_to_vbytes: EagerVec::forced_import_compressed(
|
||||
&db,
|
||||
"vbytes",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
indexes_to_block_vbytes: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"block_vbytes",
|
||||
Source::None,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default()
|
||||
.add_sum()
|
||||
.add_minmax()
|
||||
.add_average()
|
||||
.add_percentiles()
|
||||
.add_cumulative(),
|
||||
)?,
|
||||
difficultyepoch_to_timestamp: EagerVec::forced_import_compressed(
|
||||
&db,
|
||||
"timestamp",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
halvingepoch_to_timestamp: EagerVec::forced_import_compressed(
|
||||
&db,
|
||||
"timestamp",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
|
||||
dateindex_to_fee_dominance: EagerVec::forced_import_compressed(
|
||||
&db,
|
||||
"fee_dominance",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
dateindex_to_subsidy_dominance: EagerVec::forced_import_compressed(
|
||||
&db,
|
||||
"subsidy_dominance",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
indexes_to_difficulty: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"difficulty",
|
||||
Source::None,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_difficultyepoch: ComputedVecsFromDateIndex::forced_import(
|
||||
&db,
|
||||
"difficultyepoch",
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_halvingepoch: ComputedVecsFromDateIndex::forced_import(
|
||||
&db,
|
||||
"halvingepoch",
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_tx_count: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"tx_count",
|
||||
@@ -343,9 +487,9 @@ impl Vecs {
|
||||
.add_minmax()
|
||||
.add_average(),
|
||||
)?,
|
||||
indexes_to_feerate: ComputedVecsFromTxindex::forced_import(
|
||||
indexes_to_fee_rate: ComputedVecsFromTxindex::forced_import(
|
||||
&db,
|
||||
"feerate",
|
||||
"fee_rate",
|
||||
Source::None,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
@@ -577,6 +721,77 @@ impl Vecs {
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_subsidy_usd_1y_sma: compute_dollars.then(|| {
|
||||
ComputedVecsFromDateIndex::forced_import(
|
||||
&db,
|
||||
"subsidy_usd_1y_sma",
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
indexes_to_puell_multiple: compute_dollars.then(|| {
|
||||
ComputedVecsFromDateIndex::forced_import(
|
||||
&db,
|
||||
"puell_multiple",
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
indexes_to_hash_rate: ComputedVecsFromDateIndex::forced_import(
|
||||
&db,
|
||||
"hash_rate",
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ONE,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_hash_rate_1w_sma: ComputedVecsFromDateIndex::forced_import(
|
||||
&db,
|
||||
"hash_rate_1w_sma",
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_hash_rate_1m_sma: ComputedVecsFromDateIndex::forced_import(
|
||||
&db,
|
||||
"hash_rate_1m_sma",
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_hash_rate_2m_sma: ComputedVecsFromDateIndex::forced_import(
|
||||
&db,
|
||||
"hash_rate_2m_sma",
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_hash_rate_1y_sma: ComputedVecsFromDateIndex::forced_import(
|
||||
&db,
|
||||
"hash_rate_1y_sma",
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_difficulty_as_hash: ComputedVecsFromDateIndex::forced_import(
|
||||
&db,
|
||||
"difficulty_as_hash",
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
|
||||
txindex_to_is_coinbase,
|
||||
inputindex_to_value,
|
||||
// indexes_to_input_value,
|
||||
@@ -584,7 +799,7 @@ impl Vecs {
|
||||
txindex_to_input_value,
|
||||
txindex_to_output_value,
|
||||
txindex_to_fee,
|
||||
txindex_to_feerate,
|
||||
txindex_to_fee_rate,
|
||||
txindex_to_vsize,
|
||||
txindex_to_weight,
|
||||
|
||||
@@ -613,6 +828,167 @@ impl Vecs {
|
||||
price: Option<&price::Vecs>,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.timeindexes_to_timestamp.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, indexes, starting_indexes, exit| {
|
||||
vec.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
&indexes.dateindex_to_date,
|
||||
|(di, d, ..)| (di, Timestamp::from(d)),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_block_count.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, indexer, _, starting_indexes, exit| {
|
||||
v.compute_range(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs.height_to_weight,
|
||||
|h| (h, StoredU32::from(1_u32)),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
let mut height_to_timestamp_iter = indexer.vecs.height_to_timestamp.iter();
|
||||
self.height_to_interval.compute_transform(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs.height_to_timestamp,
|
||||
|(height, timestamp, ..)| {
|
||||
let interval = height.decremented().map_or(Timestamp::ZERO, |prev_h| {
|
||||
let prev_timestamp = height_to_timestamp_iter.unwrap_get_inner(prev_h);
|
||||
timestamp
|
||||
.checked_sub(prev_timestamp)
|
||||
.unwrap_or(Timestamp::ZERO)
|
||||
});
|
||||
(height, interval)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.indexes_to_block_interval.compute_rest(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(&self.height_to_interval),
|
||||
)?;
|
||||
|
||||
self.indexes_to_block_weight.compute_rest(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(&indexer.vecs.height_to_weight),
|
||||
)?;
|
||||
|
||||
self.indexes_to_block_size.compute_rest(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(&indexer.vecs.height_to_total_size),
|
||||
)?;
|
||||
|
||||
self.height_to_vbytes.compute_transform(
|
||||
starting_indexes.height,
|
||||
&indexer.vecs.height_to_weight,
|
||||
|(h, w, ..)| {
|
||||
(
|
||||
h,
|
||||
StoredU64::from(bitcoin::Weight::from(w).to_vbytes_floor()),
|
||||
)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.indexes_to_block_vbytes.compute_rest(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(&self.height_to_vbytes),
|
||||
)?;
|
||||
|
||||
let mut height_to_timestamp_iter = indexer.vecs.height_to_timestamp.iter();
|
||||
|
||||
self.difficultyepoch_to_timestamp.compute_transform(
|
||||
starting_indexes.difficultyepoch,
|
||||
&indexes.difficultyepoch_to_first_height,
|
||||
|(i, h, ..)| (i, height_to_timestamp_iter.unwrap_get_inner(h)),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.halvingepoch_to_timestamp.compute_transform(
|
||||
starting_indexes.halvingepoch,
|
||||
&indexes.halvingepoch_to_first_height,
|
||||
|(i, h, ..)| (i, height_to_timestamp_iter.unwrap_get_inner(h)),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
let mut height_to_difficultyepoch_iter = indexes.height_to_difficultyepoch.into_iter();
|
||||
self.indexes_to_difficultyepoch.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, indexes, starting_indexes, exit| {
|
||||
let mut height_count_iter = indexes.dateindex_to_height_count.into_iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
&indexes.dateindex_to_first_height,
|
||||
|(di, height, ..)| {
|
||||
(
|
||||
di,
|
||||
height_to_difficultyepoch_iter.unwrap_get_inner(
|
||||
height + (*height_count_iter.unwrap_get_inner(di) - 1),
|
||||
),
|
||||
)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
let mut height_to_halvingepoch_iter = indexes.height_to_halvingepoch.into_iter();
|
||||
self.indexes_to_halvingepoch.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, indexes, starting_indexes, exit| {
|
||||
let mut height_count_iter = indexes.dateindex_to_height_count.into_iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
&indexes.dateindex_to_first_height,
|
||||
|(di, height, ..)| {
|
||||
(
|
||||
di,
|
||||
height_to_halvingepoch_iter.unwrap_get_inner(
|
||||
height + (*height_count_iter.unwrap_get_inner(di) - 1),
|
||||
),
|
||||
)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_difficulty.compute_rest(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(&indexer.vecs.height_to_difficulty),
|
||||
)?;
|
||||
|
||||
self.indexes_to_tx_count.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
@@ -722,11 +1098,11 @@ impl Vecs {
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.txindex_to_feerate.compute_transform2(
|
||||
self.txindex_to_fee_rate.compute_transform2(
|
||||
starting_indexes.txindex,
|
||||
&self.txindex_to_fee,
|
||||
&self.txindex_to_vsize,
|
||||
|(txindex, fee, vsize, ..)| (txindex, Feerate::from((fee, vsize))),
|
||||
|(txindex, fee, vsize, ..)| (txindex, FeeRate::from((fee, vsize))),
|
||||
exit,
|
||||
)?;
|
||||
|
||||
@@ -739,12 +1115,12 @@ impl Vecs {
|
||||
price,
|
||||
)?;
|
||||
|
||||
self.indexes_to_feerate.compute_rest(
|
||||
self.indexes_to_fee_rate.compute_rest(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(&self.txindex_to_feerate),
|
||||
Some(&self.txindex_to_fee_rate),
|
||||
)?;
|
||||
|
||||
self.indexes_to_tx_weight.compute_rest(
|
||||
@@ -1085,25 +1461,241 @@ impl Vecs {
|
||||
},
|
||||
)?;
|
||||
|
||||
self.dateindex_to_fee_dominance.compute_transform2(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_fee.sats.dateindex.unwrap_sum(),
|
||||
self.indexes_to_coinbase.sats.dateindex.unwrap_sum(),
|
||||
|(i, fee, coinbase, ..)| {
|
||||
(
|
||||
i,
|
||||
StoredF32::from(u64::from(fee) as f64 / u64::from(coinbase) as f64 * 100.0),
|
||||
)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
self.dateindex_to_subsidy_dominance.compute_transform2(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_subsidy.sats.dateindex.unwrap_sum(),
|
||||
self.indexes_to_coinbase.sats.dateindex.unwrap_sum(),
|
||||
|(i, subsidy, coinbase, ..)| {
|
||||
(
|
||||
i,
|
||||
StoredF32::from(u64::from(subsidy) as f64 / u64::from(coinbase) as f64 * 100.0),
|
||||
)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.indexes_to_difficulty_as_hash.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
let multiplier = 2.0_f64.powi(32) / 600.0;
|
||||
v.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_difficulty.dateindex.unwrap_last(),
|
||||
|(i, v, ..)| (i, StoredF32::from(*v * multiplier)),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
let now = Timestamp::now();
|
||||
let today = Date::from(now);
|
||||
self.indexes_to_hash_rate.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_transform3(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_block_count.dateindex.unwrap_sum(),
|
||||
self.indexes_to_difficulty_as_hash
|
||||
.dateindex
|
||||
.as_ref()
|
||||
.unwrap(),
|
||||
&indexes.dateindex_to_date,
|
||||
|(i, block_count_sum, difficulty_as_hash, date, ..)| {
|
||||
let target_multiplier = if date == today {
|
||||
now.day_completion()
|
||||
} else {
|
||||
1.0
|
||||
};
|
||||
(
|
||||
i,
|
||||
StoredF64::from(
|
||||
(f64::from(block_count_sum)
|
||||
/ (target_multiplier * TARGET_BLOCKS_PER_DAY))
|
||||
* f64::from(difficulty_as_hash),
|
||||
),
|
||||
)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_hash_rate_1w_sma.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_sma(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_hash_rate.dateindex.as_ref().unwrap(),
|
||||
7,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_hash_rate_1m_sma.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_sma(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_hash_rate.dateindex.as_ref().unwrap(),
|
||||
30,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_hash_rate_2m_sma.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_sma(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_hash_rate.dateindex.as_ref().unwrap(),
|
||||
2 * 30,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_hash_rate_1y_sma.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_sma(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_hash_rate.dateindex.as_ref().unwrap(),
|
||||
365,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
if self.indexes_to_subsidy_usd_1y_sma.is_some() {
|
||||
let date_to_coinbase_usd_sum = self
|
||||
.indexes_to_coinbase
|
||||
.dollars
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.unwrap_sum();
|
||||
|
||||
self.indexes_to_subsidy_usd_1y_sma
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_sma(
|
||||
starting_indexes.dateindex,
|
||||
date_to_coinbase_usd_sum,
|
||||
365,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_puell_multiple
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_divide(
|
||||
starting_indexes.dateindex,
|
||||
date_to_coinbase_usd_sum,
|
||||
self.indexes_to_subsidy_usd_1y_sma
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.as_ref()
|
||||
.unwrap(),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
||||
[
|
||||
vec![
|
||||
&self.inputindex_to_value as &dyn AnyCollectableVec,
|
||||
&self.height_to_interval as &dyn AnyCollectableVec,
|
||||
&self.height_to_vbytes,
|
||||
&self.difficultyepoch_to_timestamp,
|
||||
&self.halvingepoch_to_timestamp,
|
||||
&self.inputindex_to_value,
|
||||
&self.txindex_to_fee,
|
||||
&self.txindex_to_feerate,
|
||||
&self.txindex_to_fee_rate,
|
||||
&self.txindex_to_input_value,
|
||||
&self.txindex_to_is_coinbase,
|
||||
&self.txindex_to_output_value,
|
||||
&self.txindex_to_vsize,
|
||||
&self.txindex_to_weight,
|
||||
&self.dateindex_to_fee_dominance,
|
||||
&self.dateindex_to_subsidy_dominance,
|
||||
],
|
||||
self.indexes_to_hash_rate.vecs(),
|
||||
self.indexes_to_hash_rate_1w_sma.vecs(),
|
||||
self.indexes_to_hash_rate_1m_sma.vecs(),
|
||||
self.indexes_to_hash_rate_2m_sma.vecs(),
|
||||
self.indexes_to_hash_rate_1y_sma.vecs(),
|
||||
self.timeindexes_to_timestamp.vecs(),
|
||||
self.indexes_to_block_count.vecs(),
|
||||
self.indexes_to_block_interval.vecs(),
|
||||
self.indexes_to_block_size.vecs(),
|
||||
self.indexes_to_block_vbytes.vecs(),
|
||||
self.indexes_to_block_weight.vecs(),
|
||||
self.indexes_to_difficulty.vecs(),
|
||||
self.indexes_to_difficultyepoch.vecs(),
|
||||
self.indexes_to_halvingepoch.vecs(),
|
||||
self.indexes_to_coinbase.vecs(),
|
||||
self.indexes_to_emptyoutput_count.vecs(),
|
||||
self.indexes_to_fee.vecs(),
|
||||
self.indexes_to_feerate.vecs(),
|
||||
self.indexes_to_fee_rate.vecs(),
|
||||
self.indexes_to_input_count.vecs(),
|
||||
self.indexes_to_opreturn_count.vecs(),
|
||||
self.indexes_to_output_count.vecs(),
|
||||
@@ -1111,6 +1703,7 @@ impl Vecs {
|
||||
self.indexes_to_p2ms_count.vecs(),
|
||||
self.indexes_to_p2pk33_count.vecs(),
|
||||
self.indexes_to_p2pk65_count.vecs(),
|
||||
self.indexes_to_difficulty_as_hash.vecs(),
|
||||
self.indexes_to_p2pkh_count.vecs(),
|
||||
self.indexes_to_p2sh_count.vecs(),
|
||||
self.indexes_to_p2tr_count.vecs(),
|
||||
@@ -1126,6 +1719,12 @@ impl Vecs {
|
||||
self.indexes_to_unknownoutput_count.vecs(),
|
||||
self.indexes_to_exact_utxo_count.vecs(),
|
||||
self.indexes_to_unclaimed_rewards.vecs(),
|
||||
self.indexes_to_subsidy_usd_1y_sma
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
self.indexes_to_puell_multiple
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
@@ -6,12 +6,12 @@ use brk_structs::{Bitcoin, CheckedSub, Dollars, StoredF64, Version};
|
||||
use vecdb::{AnyCollectableVec, Database, Exit, PAGE_SIZE, VecIterator};
|
||||
|
||||
use super::{
|
||||
Indexes,
|
||||
Indexes, chain,
|
||||
grouped::{
|
||||
ComputedRatioVecsFromDateIndex, ComputedValueVecsFromHeight, ComputedVecsFromHeight,
|
||||
Source, VecBuilderOptions,
|
||||
},
|
||||
indexes, price, stateful, transactions,
|
||||
indexes, price, stateful,
|
||||
};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
@@ -257,7 +257,7 @@ impl Vecs {
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
price: Option<&price::Vecs>,
|
||||
transactions: &transactions::Vecs,
|
||||
chain: &chain::Vecs,
|
||||
stateful: &stateful::Vecs,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
@@ -266,7 +266,7 @@ impl Vecs {
|
||||
indexes,
|
||||
starting_indexes,
|
||||
price,
|
||||
transactions,
|
||||
chain,
|
||||
stateful,
|
||||
exit,
|
||||
)?;
|
||||
@@ -281,7 +281,7 @@ impl Vecs {
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
price: Option<&price::Vecs>,
|
||||
transactions: &transactions::Vecs,
|
||||
chain: &chain::Vecs,
|
||||
stateful: &stateful::Vecs,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
@@ -446,7 +446,7 @@ impl Vecs {
|
||||
|vec, _, _, starting_indexes, exit| {
|
||||
vec.compute_transform(
|
||||
starting_indexes.height,
|
||||
transactions
|
||||
chain
|
||||
.indexes_to_subsidy
|
||||
.dollars
|
||||
.as_ref()
|
||||
|
||||
@@ -19,11 +19,11 @@ where
|
||||
pub average: Option<Box<EagerVec<I, T>>>,
|
||||
pub sum: Option<Box<EagerVec<I, T>>>,
|
||||
pub max: Option<Box<EagerVec<I, T>>>,
|
||||
pub _90p: Option<Box<EagerVec<I, T>>>,
|
||||
pub _75p: Option<Box<EagerVec<I, T>>>,
|
||||
pub p90: Option<Box<EagerVec<I, T>>>,
|
||||
pub p75: Option<Box<EagerVec<I, T>>>,
|
||||
pub median: Option<Box<EagerVec<I, T>>>,
|
||||
pub _25p: Option<Box<EagerVec<I, T>>>,
|
||||
pub _10p: Option<Box<EagerVec<I, T>>>,
|
||||
pub p25: Option<Box<EagerVec<I, T>>>,
|
||||
pub p10: Option<Box<EagerVec<I, T>>>,
|
||||
pub min: Option<Box<EagerVec<I, T>>>,
|
||||
pub last: Option<Box<EagerVec<I, T>>>,
|
||||
pub cumulative: Option<Box<EagerVec<I, T>>>,
|
||||
@@ -118,7 +118,7 @@ where
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
db,
|
||||
&maybe_suffix("average"),
|
||||
&maybe_suffix("avg"),
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
)
|
||||
@@ -144,51 +144,51 @@ where
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
db,
|
||||
&suffix("cumulative"),
|
||||
&suffix("cum"),
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
}),
|
||||
_90p: options._90p.then(|| {
|
||||
p90: options.p90.then(|| {
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
db,
|
||||
&maybe_suffix("90p"),
|
||||
&maybe_suffix("p90"),
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
}),
|
||||
_75p: options._75p.then(|| {
|
||||
p75: options.p75.then(|| {
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
db,
|
||||
&maybe_suffix("75p"),
|
||||
&maybe_suffix("p75"),
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
}),
|
||||
_25p: options._25p.then(|| {
|
||||
p25: options.p25.then(|| {
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
db,
|
||||
&maybe_suffix("25p"),
|
||||
&maybe_suffix("p25"),
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
)
|
||||
.unwrap(),
|
||||
)
|
||||
}),
|
||||
_10p: options._10p.then(|| {
|
||||
p10: options.p10.then(|| {
|
||||
Box::new(
|
||||
EagerVec::forced_import(
|
||||
db,
|
||||
&maybe_suffix("10p"),
|
||||
&maybe_suffix("p10"),
|
||||
version + VERSION + Version::ZERO,
|
||||
format,
|
||||
)
|
||||
@@ -292,11 +292,11 @@ where
|
||||
let needs_average_sum_or_cumulative =
|
||||
needs_sum_or_cumulative || self.average.is_some();
|
||||
let needs_sorted = self.max.is_some()
|
||||
|| self._90p.is_some()
|
||||
|| self._75p.is_some()
|
||||
|| self.p90.is_some()
|
||||
|| self.p75.is_some()
|
||||
|| self.median.is_some()
|
||||
|| self._25p.is_some()
|
||||
|| self._10p.is_some()
|
||||
|| self.p25.is_some()
|
||||
|| self.p10.is_some()
|
||||
|| self.min.is_some();
|
||||
let needs_values = needs_sorted || needs_average_sum_or_cumulative;
|
||||
|
||||
@@ -333,24 +333,24 @@ where
|
||||
)?;
|
||||
}
|
||||
|
||||
if let Some(_90p) = self._90p.as_mut() {
|
||||
_90p.forced_push_at(index, get_percentile(&values, 0.90), exit)?;
|
||||
if let Some(p90) = self.p90.as_mut() {
|
||||
p90.forced_push_at(index, get_percentile(&values, 0.90), exit)?;
|
||||
}
|
||||
|
||||
if let Some(_75p) = self._75p.as_mut() {
|
||||
_75p.forced_push_at(index, get_percentile(&values, 0.75), exit)?;
|
||||
if let Some(p75) = self.p75.as_mut() {
|
||||
p75.forced_push_at(index, get_percentile(&values, 0.75), exit)?;
|
||||
}
|
||||
|
||||
if let Some(median) = self.median.as_mut() {
|
||||
median.forced_push_at(index, get_percentile(&values, 0.50), exit)?;
|
||||
}
|
||||
|
||||
if let Some(_25p) = self._25p.as_mut() {
|
||||
_25p.forced_push_at(index, get_percentile(&values, 0.25), exit)?;
|
||||
if let Some(p25) = self.p25.as_mut() {
|
||||
p25.forced_push_at(index, get_percentile(&values, 0.25), exit)?;
|
||||
}
|
||||
|
||||
if let Some(_10p) = self._10p.as_mut() {
|
||||
_10p.forced_push_at(index, get_percentile(&values, 0.10), exit)?;
|
||||
if let Some(p10) = self.p10.as_mut() {
|
||||
p10.forced_push_at(index, get_percentile(&values, 0.10), exit)?;
|
||||
}
|
||||
|
||||
if let Some(min) = self.min.as_mut() {
|
||||
@@ -401,11 +401,11 @@ where
|
||||
where
|
||||
I2: StoredIndex + StoredRaw + CheckedSub<I2>,
|
||||
{
|
||||
if self._90p.is_some()
|
||||
|| self._75p.is_some()
|
||||
if self.p90.is_some()
|
||||
|| self.p75.is_some()
|
||||
|| self.median.is_some()
|
||||
|| self._25p.is_some()
|
||||
|| self._10p.is_some()
|
||||
|| self.p25.is_some()
|
||||
|| self.p10.is_some()
|
||||
{
|
||||
panic!("unsupported");
|
||||
}
|
||||
@@ -558,24 +558,24 @@ where
|
||||
self.max.as_ref().unwrap()
|
||||
}
|
||||
#[allow(unused)]
|
||||
pub fn unwrap_90p(&self) -> &EagerVec<I, T> {
|
||||
self._90p.as_ref().unwrap()
|
||||
pub fn unwrap_p90(&self) -> &EagerVec<I, T> {
|
||||
self.p90.as_ref().unwrap()
|
||||
}
|
||||
#[allow(unused)]
|
||||
pub fn unwrap_75p(&self) -> &EagerVec<I, T> {
|
||||
self._75p.as_ref().unwrap()
|
||||
pub fn unwrap_p75(&self) -> &EagerVec<I, T> {
|
||||
self.p75.as_ref().unwrap()
|
||||
}
|
||||
#[allow(unused)]
|
||||
pub fn unwrap_median(&self) -> &EagerVec<I, T> {
|
||||
self.median.as_ref().unwrap()
|
||||
}
|
||||
#[allow(unused)]
|
||||
pub fn unwrap_25p(&self) -> &EagerVec<I, T> {
|
||||
self._25p.as_ref().unwrap()
|
||||
pub fn unwrap_p25(&self) -> &EagerVec<I, T> {
|
||||
self.p25.as_ref().unwrap()
|
||||
}
|
||||
#[allow(unused)]
|
||||
pub fn unwrap_10p(&self) -> &EagerVec<I, T> {
|
||||
self._10p.as_ref().unwrap()
|
||||
pub fn unwrap_p10(&self) -> &EagerVec<I, T> {
|
||||
self.p10.as_ref().unwrap()
|
||||
}
|
||||
pub fn unwrap_min(&self) -> &EagerVec<I, T> {
|
||||
self.min.as_ref().unwrap()
|
||||
@@ -615,17 +615,17 @@ where
|
||||
if let Some(cumulative) = self.cumulative.as_ref() {
|
||||
v.push(cumulative.as_ref());
|
||||
}
|
||||
if let Some(_90p) = self._90p.as_ref() {
|
||||
v.push(_90p.as_ref());
|
||||
if let Some(p90) = self.p90.as_ref() {
|
||||
v.push(p90.as_ref());
|
||||
}
|
||||
if let Some(_75p) = self._75p.as_ref() {
|
||||
v.push(_75p.as_ref());
|
||||
if let Some(p75) = self.p75.as_ref() {
|
||||
v.push(p75.as_ref());
|
||||
}
|
||||
if let Some(_25p) = self._25p.as_ref() {
|
||||
v.push(_25p.as_ref());
|
||||
if let Some(p25) = self.p25.as_ref() {
|
||||
v.push(p25.as_ref());
|
||||
}
|
||||
if let Some(_10p) = self._10p.as_ref() {
|
||||
v.push(_10p.as_ref());
|
||||
if let Some(p10) = self.p10.as_ref() {
|
||||
v.push(p10.as_ref());
|
||||
}
|
||||
|
||||
v
|
||||
@@ -656,17 +656,17 @@ where
|
||||
if let Some(cumulative) = self.cumulative.as_mut() {
|
||||
cumulative.safe_flush(exit)?;
|
||||
}
|
||||
if let Some(_90p) = self._90p.as_mut() {
|
||||
_90p.safe_flush(exit)?;
|
||||
if let Some(p90) = self.p90.as_mut() {
|
||||
p90.safe_flush(exit)?;
|
||||
}
|
||||
if let Some(_75p) = self._75p.as_mut() {
|
||||
_75p.safe_flush(exit)?;
|
||||
if let Some(p75) = self.p75.as_mut() {
|
||||
p75.safe_flush(exit)?;
|
||||
}
|
||||
if let Some(_25p) = self._25p.as_mut() {
|
||||
_25p.safe_flush(exit)?;
|
||||
if let Some(p25) = self.p25.as_mut() {
|
||||
p25.safe_flush(exit)?;
|
||||
}
|
||||
if let Some(_10p) = self._10p.as_mut() {
|
||||
_10p.safe_flush(exit)?;
|
||||
if let Some(p10) = self.p10.as_mut() {
|
||||
p10.safe_flush(exit)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -697,17 +697,17 @@ where
|
||||
if let Some(cumulative) = self.cumulative.as_mut() {
|
||||
cumulative.validate_computed_version_or_reset(Version::ZERO + version)?;
|
||||
}
|
||||
if let Some(_90p) = self._90p.as_mut() {
|
||||
_90p.validate_computed_version_or_reset(Version::ZERO + version)?;
|
||||
if let Some(p90) = self.p90.as_mut() {
|
||||
p90.validate_computed_version_or_reset(Version::ZERO + version)?;
|
||||
}
|
||||
if let Some(_75p) = self._75p.as_mut() {
|
||||
_75p.validate_computed_version_or_reset(Version::ZERO + version)?;
|
||||
if let Some(p75) = self.p75.as_mut() {
|
||||
p75.validate_computed_version_or_reset(Version::ZERO + version)?;
|
||||
}
|
||||
if let Some(_25p) = self._25p.as_mut() {
|
||||
_25p.validate_computed_version_or_reset(Version::ZERO + version)?;
|
||||
if let Some(p25) = self.p25.as_mut() {
|
||||
p25.validate_computed_version_or_reset(Version::ZERO + version)?;
|
||||
}
|
||||
if let Some(_10p) = self._10p.as_mut() {
|
||||
_10p.validate_computed_version_or_reset(Version::ZERO + version)?;
|
||||
if let Some(p10) = self.p10.as_mut() {
|
||||
p10.validate_computed_version_or_reset(Version::ZERO + version)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -719,11 +719,11 @@ pub struct VecBuilderOptions {
|
||||
average: bool,
|
||||
sum: bool,
|
||||
max: bool,
|
||||
_90p: bool,
|
||||
_75p: bool,
|
||||
p90: bool,
|
||||
p75: bool,
|
||||
median: bool,
|
||||
_25p: bool,
|
||||
_10p: bool,
|
||||
p25: bool,
|
||||
p10: bool,
|
||||
min: bool,
|
||||
first: bool,
|
||||
last: bool,
|
||||
@@ -743,24 +743,24 @@ impl VecBuilderOptions {
|
||||
self.max
|
||||
}
|
||||
|
||||
pub fn _90p(&self) -> bool {
|
||||
self._90p
|
||||
pub fn p90(&self) -> bool {
|
||||
self.p90
|
||||
}
|
||||
|
||||
pub fn _75p(&self) -> bool {
|
||||
self._75p
|
||||
pub fn p75(&self) -> bool {
|
||||
self.p75
|
||||
}
|
||||
|
||||
pub fn median(&self) -> bool {
|
||||
self.median
|
||||
}
|
||||
|
||||
pub fn _25p(&self) -> bool {
|
||||
self._25p
|
||||
pub fn p25(&self) -> bool {
|
||||
self.p25
|
||||
}
|
||||
|
||||
pub fn _10p(&self) -> bool {
|
||||
self._10p
|
||||
pub fn p10(&self) -> bool {
|
||||
self.p10
|
||||
}
|
||||
|
||||
pub fn min(&self) -> bool {
|
||||
@@ -816,26 +816,26 @@ impl VecBuilderOptions {
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn add_90p(mut self) -> Self {
|
||||
self._90p = true;
|
||||
pub fn add_p90(mut self) -> Self {
|
||||
self.p90 = true;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn add_75p(mut self) -> Self {
|
||||
self._75p = true;
|
||||
pub fn add_p75(mut self) -> Self {
|
||||
self.p75 = true;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn add_25p(mut self) -> Self {
|
||||
self._25p = true;
|
||||
pub fn add_p25(mut self) -> Self {
|
||||
self.p25 = true;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn add_10p(mut self) -> Self {
|
||||
self._10p = true;
|
||||
pub fn add_p10(mut self) -> Self {
|
||||
self.p10 = true;
|
||||
self
|
||||
}
|
||||
|
||||
@@ -875,26 +875,26 @@ impl VecBuilderOptions {
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn rm_90p(mut self) -> Self {
|
||||
self._90p = false;
|
||||
pub fn rm_p90(mut self) -> Self {
|
||||
self.p90 = false;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn rm_75p(mut self) -> Self {
|
||||
self._75p = false;
|
||||
pub fn rm_p75(mut self) -> Self {
|
||||
self.p75 = false;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn rm_25p(mut self) -> Self {
|
||||
self._25p = false;
|
||||
pub fn rm_p25(mut self) -> Self {
|
||||
self.p25 = false;
|
||||
self
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn rm_10p(mut self) -> Self {
|
||||
self._10p = false;
|
||||
pub fn rm_p10(mut self) -> Self {
|
||||
self.p10 = false;
|
||||
self
|
||||
}
|
||||
|
||||
@@ -911,20 +911,20 @@ impl VecBuilderOptions {
|
||||
}
|
||||
|
||||
pub fn add_percentiles(mut self) -> Self {
|
||||
self._90p = true;
|
||||
self._75p = true;
|
||||
self.p90 = true;
|
||||
self.p75 = true;
|
||||
self.median = true;
|
||||
self._25p = true;
|
||||
self._10p = true;
|
||||
self.p25 = true;
|
||||
self.p10 = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn remove_percentiles(mut self) -> Self {
|
||||
self._90p = false;
|
||||
self._75p = false;
|
||||
self.p90 = false;
|
||||
self.p75 = false;
|
||||
self.median = false;
|
||||
self._25p = false;
|
||||
self._10p = false;
|
||||
self.p25 = false;
|
||||
self.p10 = false;
|
||||
self
|
||||
}
|
||||
|
||||
@@ -933,11 +933,11 @@ impl VecBuilderOptions {
|
||||
self.average,
|
||||
self.sum,
|
||||
self.max,
|
||||
self._90p,
|
||||
self._75p,
|
||||
self.p90,
|
||||
self.p75,
|
||||
self.median,
|
||||
self._25p,
|
||||
self._10p,
|
||||
self.p25,
|
||||
self.p10,
|
||||
self.min,
|
||||
self.first,
|
||||
self.last,
|
||||
|
||||
@@ -142,7 +142,7 @@ where
|
||||
}),
|
||||
average: options.average.then(|| {
|
||||
Box::new(LazyVecFrom2::init(
|
||||
&maybe_suffix("average"),
|
||||
&maybe_suffix("avg"),
|
||||
version + VERSION + Version::ZERO,
|
||||
source_extra
|
||||
.average
|
||||
@@ -197,7 +197,7 @@ where
|
||||
}),
|
||||
cumulative: options.cumulative.then(|| {
|
||||
Box::new(LazyVecFrom2::init(
|
||||
&suffix("cumulative"),
|
||||
&suffix("cum"),
|
||||
version + VERSION + Version::ZERO,
|
||||
source_extra.cumulative.as_ref().unwrap().boxed_clone(),
|
||||
len_source.clone(),
|
||||
|
||||
@@ -319,24 +319,24 @@ impl ComputedVecsFromTxindex<Bitcoin> {
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(_90p) = self.height._90p.as_mut() {
|
||||
if let Some(_90p) = self.height.p90.as_mut() {
|
||||
_90p.forced_push_at(
|
||||
height,
|
||||
Bitcoin::from(
|
||||
sats.height
|
||||
.unwrap_90p()
|
||||
.unwrap_p90()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(_75p) = self.height._75p.as_mut() {
|
||||
if let Some(_75p) = self.height.p75.as_mut() {
|
||||
_75p.forced_push_at(
|
||||
height,
|
||||
Bitcoin::from(
|
||||
sats.height
|
||||
.unwrap_75p()
|
||||
.unwrap_p75()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
),
|
||||
@@ -355,24 +355,24 @@ impl ComputedVecsFromTxindex<Bitcoin> {
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(_25p) = self.height._25p.as_mut() {
|
||||
if let Some(_25p) = self.height.p25.as_mut() {
|
||||
_25p.forced_push_at(
|
||||
height,
|
||||
Bitcoin::from(
|
||||
sats.height
|
||||
.unwrap_25p()
|
||||
.unwrap_p25()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(_10p) = self.height._10p.as_mut() {
|
||||
if let Some(_10p) = self.height.p10.as_mut() {
|
||||
_10p.forced_push_at(
|
||||
height,
|
||||
Bitcoin::from(
|
||||
sats.height
|
||||
.unwrap_10p()
|
||||
.unwrap_p10()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
),
|
||||
@@ -502,25 +502,25 @@ impl ComputedVecsFromTxindex<Dollars> {
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(_90p) = self.height._90p.as_mut() {
|
||||
if let Some(_90p) = self.height.p90.as_mut() {
|
||||
_90p.forced_push_at(
|
||||
height,
|
||||
price
|
||||
* bitcoin
|
||||
.height
|
||||
.unwrap_90p()
|
||||
.unwrap_p90()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(_75p) = self.height._75p.as_mut() {
|
||||
if let Some(_75p) = self.height.p75.as_mut() {
|
||||
_75p.forced_push_at(
|
||||
height,
|
||||
price
|
||||
* bitcoin
|
||||
.height
|
||||
.unwrap_75p()
|
||||
.unwrap_p75()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
exit,
|
||||
@@ -538,25 +538,25 @@ impl ComputedVecsFromTxindex<Dollars> {
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(_25p) = self.height._25p.as_mut() {
|
||||
if let Some(_25p) = self.height.p25.as_mut() {
|
||||
_25p.forced_push_at(
|
||||
height,
|
||||
price
|
||||
* bitcoin
|
||||
.height
|
||||
.unwrap_25p()
|
||||
.unwrap_p25()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
if let Some(_10p) = self.height._10p.as_mut() {
|
||||
if let Some(_10p) = self.height.p10.as_mut() {
|
||||
_10p.forced_push_at(
|
||||
height,
|
||||
price
|
||||
* bitcoin
|
||||
.height
|
||||
.unwrap_10p()
|
||||
.unwrap_p10()
|
||||
.into_iter()
|
||||
.unwrap_get_inner(height),
|
||||
exit,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#![doc = include_str!("../README.md")]
|
||||
|
||||
use std::path::Path;
|
||||
use std::{path::Path, thread};
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_fetcher::Fetcher;
|
||||
@@ -9,19 +9,17 @@ use brk_structs::Version;
|
||||
use log::info;
|
||||
use vecdb::{AnyCollectableVec, Exit, Format};
|
||||
|
||||
mod blocks;
|
||||
mod chain;
|
||||
mod cointime;
|
||||
mod constants;
|
||||
mod fetched;
|
||||
mod grouped;
|
||||
mod indexes;
|
||||
mod market;
|
||||
mod mining;
|
||||
mod price;
|
||||
mod stateful;
|
||||
mod states;
|
||||
mod traits;
|
||||
mod transactions;
|
||||
mod utils;
|
||||
|
||||
use indexes::Indexes;
|
||||
@@ -33,11 +31,9 @@ use states::*;
|
||||
pub struct Computer {
|
||||
pub indexes: indexes::Vecs,
|
||||
pub constants: constants::Vecs,
|
||||
pub blocks: blocks::Vecs,
|
||||
pub mining: mining::Vecs,
|
||||
pub market: market::Vecs,
|
||||
pub price: Option<price::Vecs>,
|
||||
pub transactions: transactions::Vecs,
|
||||
pub chain: chain::Vecs,
|
||||
pub stateful: stateful::Vecs,
|
||||
pub fetched: Option<fetched::Vecs>,
|
||||
pub cointime: cointime::Vecs,
|
||||
@@ -68,8 +64,6 @@ impl Computer {
|
||||
});
|
||||
|
||||
Ok(Self {
|
||||
blocks: blocks::Vecs::forced_import(&computed_path, VERSION + Version::ZERO, &indexes)?,
|
||||
mining: mining::Vecs::forced_import(&computed_path, VERSION + Version::ZERO, &indexes)?,
|
||||
constants: constants::Vecs::forced_import(
|
||||
&computed_path,
|
||||
VERSION + Version::ZERO,
|
||||
@@ -83,7 +77,7 @@ impl Computer {
|
||||
&indexes,
|
||||
price.as_ref(),
|
||||
)?,
|
||||
transactions: transactions::Vecs::forced_import(
|
||||
chain: chain::Vecs::forced_import(
|
||||
&computed_path,
|
||||
VERSION + Version::ZERO,
|
||||
indexer,
|
||||
@@ -115,14 +109,6 @@ impl Computer {
|
||||
self.constants
|
||||
.compute(indexer, &self.indexes, &starting_indexes, exit)?;
|
||||
|
||||
info!("Computing blocks...");
|
||||
self.blocks
|
||||
.compute(indexer, &self.indexes, &starting_indexes, exit)?;
|
||||
|
||||
info!("Computing mining...");
|
||||
self.mining
|
||||
.compute(indexer, &self.indexes, &starting_indexes, exit)?;
|
||||
|
||||
if let Some(fetched) = self.fetched.as_mut() {
|
||||
info!("Computing fetched...");
|
||||
fetched.compute(indexer, &self.indexes, &starting_indexes, exit)?;
|
||||
@@ -137,44 +123,49 @@ impl Computer {
|
||||
)?;
|
||||
}
|
||||
|
||||
info!("Computing transactions...");
|
||||
self.transactions.compute(
|
||||
indexer,
|
||||
&self.indexes,
|
||||
&starting_indexes,
|
||||
self.price.as_ref(),
|
||||
exit,
|
||||
)?;
|
||||
thread::scope(|scope| -> Result<()> {
|
||||
let chain = scope.spawn(|| {
|
||||
info!("Computing chain...");
|
||||
self.chain.compute(
|
||||
indexer,
|
||||
&self.indexes,
|
||||
&starting_indexes,
|
||||
self.price.as_ref(),
|
||||
exit,
|
||||
)
|
||||
});
|
||||
|
||||
if let Some(price) = self.price.as_ref() {
|
||||
info!("Computing market...");
|
||||
self.market.compute(
|
||||
indexer,
|
||||
&self.indexes,
|
||||
price,
|
||||
&mut self.transactions,
|
||||
&starting_indexes,
|
||||
exit,
|
||||
)?;
|
||||
}
|
||||
let market = scope.spawn(|| -> Result<()> {
|
||||
if let Some(price) = self.price.as_ref() {
|
||||
info!("Computing market...");
|
||||
self.market
|
||||
.compute(indexer, &self.indexes, price, &starting_indexes, exit)?;
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
|
||||
chain.join().unwrap()?;
|
||||
market.join().unwrap()?;
|
||||
Ok(())
|
||||
})?;
|
||||
|
||||
info!("Computing stateful...");
|
||||
self.stateful.compute(
|
||||
indexer,
|
||||
&self.indexes,
|
||||
&self.transactions,
|
||||
&self.chain,
|
||||
self.price.as_ref(),
|
||||
&self.market,
|
||||
&mut starting_indexes,
|
||||
exit,
|
||||
)?;
|
||||
|
||||
info!("Computing cointime...");
|
||||
self.cointime.compute(
|
||||
indexer,
|
||||
&self.indexes,
|
||||
&starting_indexes,
|
||||
self.price.as_ref(),
|
||||
&self.transactions,
|
||||
&self.chain,
|
||||
&self.stateful,
|
||||
exit,
|
||||
)?;
|
||||
@@ -186,10 +177,8 @@ impl Computer {
|
||||
[
|
||||
self.constants.vecs(),
|
||||
self.indexes.vecs(),
|
||||
self.blocks.vecs(),
|
||||
self.mining.vecs(),
|
||||
self.market.vecs(),
|
||||
self.transactions.vecs(),
|
||||
self.chain.vecs(),
|
||||
self.stateful.vecs(),
|
||||
self.cointime.vecs(),
|
||||
self.fetched.as_ref().map_or(vec![], |v| v.vecs()),
|
||||
|
||||
@@ -14,7 +14,7 @@ use crate::{
|
||||
use super::{
|
||||
Indexes,
|
||||
grouped::{ComputedRatioVecsFromDateIndex, ComputedVecsFromDateIndex, VecBuilderOptions},
|
||||
indexes, transactions,
|
||||
indexes,
|
||||
};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
@@ -23,10 +23,8 @@ const VERSION: Version = Version::ZERO;
|
||||
pub struct Vecs {
|
||||
db: Database,
|
||||
|
||||
pub height_to_marketcap: EagerVec<Height, Dollars>,
|
||||
pub height_to_ath: EagerVec<Height, Dollars>,
|
||||
pub height_to_drawdown: EagerVec<Height, StoredF32>,
|
||||
pub indexes_to_marketcap: ComputedVecsFromDateIndex<Dollars>,
|
||||
pub indexes_to_ath: ComputedVecsFromDateIndex<Dollars>,
|
||||
pub indexes_to_drawdown: ComputedVecsFromDateIndex<StoredF32>,
|
||||
pub indexes_to_days_since_ath: ComputedVecsFromDateIndex<StoredU16>,
|
||||
@@ -188,11 +186,6 @@ impl Vecs {
|
||||
db.set_min_len(PAGE_SIZE * 1_000_000)?;
|
||||
|
||||
Ok(Self {
|
||||
height_to_marketcap: EagerVec::forced_import_compressed(
|
||||
&db,
|
||||
"marketcap",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
height_to_ath: EagerVec::forced_import_compressed(
|
||||
&db,
|
||||
"ath",
|
||||
@@ -203,14 +196,6 @@ impl Vecs {
|
||||
"drawdown",
|
||||
version + VERSION + Version::ZERO,
|
||||
)?,
|
||||
indexes_to_marketcap: ComputedVecsFromDateIndex::forced_import(
|
||||
&db,
|
||||
"marketcap",
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_ath: ComputedVecsFromDateIndex::forced_import(
|
||||
&db,
|
||||
"ath",
|
||||
@@ -1381,18 +1366,10 @@ impl Vecs {
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
price: &price::Vecs,
|
||||
transactions: &mut transactions::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.compute_(
|
||||
indexer,
|
||||
indexes,
|
||||
price,
|
||||
transactions,
|
||||
starting_indexes,
|
||||
exit,
|
||||
)?;
|
||||
self.compute_(indexer, indexes, price, starting_indexes, exit)?;
|
||||
self.db.flush_then_punch()?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -1402,20 +1379,9 @@ impl Vecs {
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
price: &price::Vecs,
|
||||
transactions: &mut transactions::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.height_to_marketcap.compute_multiply(
|
||||
starting_indexes.height,
|
||||
&price.chainindexes_to_close.height,
|
||||
transactions
|
||||
.indexes_to_subsidy
|
||||
.bitcoin
|
||||
.height_extra
|
||||
.unwrap_cumulative(),
|
||||
exit,
|
||||
)?;
|
||||
self.height_to_ath.compute_max(
|
||||
starting_indexes.height,
|
||||
&price.chainindexes_to_high.height,
|
||||
@@ -1428,26 +1394,6 @@ impl Vecs {
|
||||
exit,
|
||||
)?;
|
||||
|
||||
self.indexes_to_marketcap.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_multiply(
|
||||
starting_indexes.dateindex,
|
||||
price.timeindexes_to_close.dateindex.as_ref().unwrap(),
|
||||
transactions
|
||||
.indexes_to_subsidy
|
||||
.bitcoin
|
||||
.dateindex
|
||||
.unwrap_cumulative(),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_ath.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
@@ -2104,7 +2050,6 @@ impl Vecs {
|
||||
|
||||
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
||||
[
|
||||
self.indexes_to_marketcap.vecs(),
|
||||
self.indexes_to_ath.vecs(),
|
||||
self.indexes_to_drawdown.vecs(),
|
||||
self.indexes_to_days_since_ath.vecs(),
|
||||
@@ -2249,11 +2194,7 @@ impl Vecs {
|
||||
self.dca_class_2017_returns.vecs(),
|
||||
self.dca_class_2016_returns.vecs(),
|
||||
self.dca_class_2015_returns.vecs(),
|
||||
vec![
|
||||
&self.height_to_marketcap,
|
||||
&self.height_to_ath,
|
||||
&self.height_to_drawdown,
|
||||
],
|
||||
vec![&self.height_to_ath, &self.height_to_drawdown],
|
||||
]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
|
||||
@@ -1,151 +0,0 @@
|
||||
use std::path::Path;
|
||||
|
||||
use brk_error::Result;
|
||||
use brk_indexer::Indexer;
|
||||
use brk_structs::{DifficultyEpoch, HalvingEpoch, StoredF64, Version};
|
||||
use vecdb::{AnyCollectableVec, Database, Exit, PAGE_SIZE, VecIterator};
|
||||
|
||||
use crate::grouped::Source;
|
||||
|
||||
use super::{
|
||||
Indexes,
|
||||
grouped::{ComputedVecsFromDateIndex, ComputedVecsFromHeight, VecBuilderOptions},
|
||||
indexes,
|
||||
};
|
||||
|
||||
const VERSION: Version = Version::ZERO;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Vecs {
|
||||
db: Database,
|
||||
|
||||
pub indexes_to_difficulty: ComputedVecsFromHeight<StoredF64>,
|
||||
pub indexes_to_difficultyepoch: ComputedVecsFromDateIndex<DifficultyEpoch>,
|
||||
pub indexes_to_halvingepoch: ComputedVecsFromDateIndex<HalvingEpoch>,
|
||||
}
|
||||
|
||||
impl Vecs {
|
||||
pub fn forced_import(parent: &Path, version: Version, indexes: &indexes::Vecs) -> Result<Self> {
|
||||
let db = Database::open(&parent.join("mining"))?;
|
||||
db.set_min_len(PAGE_SIZE * 1_000_000)?;
|
||||
|
||||
Ok(Self {
|
||||
indexes_to_difficulty: ComputedVecsFromHeight::forced_import(
|
||||
&db,
|
||||
"difficulty",
|
||||
Source::None,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_difficultyepoch: ComputedVecsFromDateIndex::forced_import(
|
||||
&db,
|
||||
"difficultyepoch",
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
indexes_to_halvingepoch: ComputedVecsFromDateIndex::forced_import(
|
||||
&db,
|
||||
"halvingepoch",
|
||||
Source::Compute,
|
||||
version + VERSION + Version::ZERO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
|
||||
db,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn compute(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.compute_(indexer, indexes, starting_indexes, exit)?;
|
||||
self.db.flush_then_punch()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn compute_(
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
starting_indexes: &Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
let mut height_to_difficultyepoch_iter = indexes.height_to_difficultyepoch.into_iter();
|
||||
self.indexes_to_difficultyepoch.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, indexes, starting_indexes, exit| {
|
||||
let mut height_count_iter = indexes.dateindex_to_height_count.into_iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
&indexes.dateindex_to_first_height,
|
||||
|(di, height, ..)| {
|
||||
(
|
||||
di,
|
||||
height_to_difficultyepoch_iter.unwrap_get_inner(
|
||||
height + (*height_count_iter.unwrap_get_inner(di) - 1),
|
||||
),
|
||||
)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
let mut height_to_halvingepoch_iter = indexes.height_to_halvingepoch.into_iter();
|
||||
self.indexes_to_halvingepoch.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|vec, _, indexes, starting_indexes, exit| {
|
||||
let mut height_count_iter = indexes.dateindex_to_height_count.into_iter();
|
||||
vec.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
&indexes.dateindex_to_first_height,
|
||||
|(di, height, ..)| {
|
||||
(
|
||||
di,
|
||||
height_to_halvingepoch_iter.unwrap_get_inner(
|
||||
height + (*height_count_iter.unwrap_get_inner(di) - 1),
|
||||
),
|
||||
)
|
||||
},
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
|
||||
self.indexes_to_difficulty.compute_rest(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
Some(&indexer.vecs.height_to_difficulty),
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn vecs(&self) -> Vec<&dyn AnyCollectableVec> {
|
||||
[
|
||||
self.indexes_to_difficulty.vecs(),
|
||||
self.indexes_to_difficultyepoch.vecs(),
|
||||
self.indexes_to_halvingepoch.vecs(),
|
||||
]
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ use vecdb::{
|
||||
use crate::{
|
||||
Indexes,
|
||||
grouped::{ComputedVecsFromHeight, Source, VecBuilderOptions},
|
||||
indexes, market, price,
|
||||
indexes, price,
|
||||
stateful::{
|
||||
common,
|
||||
r#trait::{CohortVecs, DynCohortVecs},
|
||||
@@ -228,9 +228,10 @@ impl CohortVecs for Vecs {
|
||||
indexes: &indexes::Vecs,
|
||||
price: Option<&price::Vecs>,
|
||||
starting_indexes: &Indexes,
|
||||
market: &market::Vecs,
|
||||
height_to_supply: &impl AnyIterableVec<Height, Bitcoin>,
|
||||
dateindex_to_supply: &impl AnyIterableVec<DateIndex, Bitcoin>,
|
||||
height_to_market_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
|
||||
dateindex_to_market_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
||||
height_to_realized_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
|
||||
dateindex_to_realized_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
||||
exit: &Exit,
|
||||
@@ -240,9 +241,10 @@ impl CohortVecs for Vecs {
|
||||
indexes,
|
||||
price,
|
||||
starting_indexes,
|
||||
market,
|
||||
height_to_supply,
|
||||
dateindex_to_supply,
|
||||
height_to_market_cap,
|
||||
dateindex_to_market_cap,
|
||||
height_to_realized_cap,
|
||||
dateindex_to_realized_cap,
|
||||
exit,
|
||||
|
||||
@@ -10,7 +10,7 @@ use derive_deref::{Deref, DerefMut};
|
||||
use vecdb::{AnyIterableVec, Database, Exit, Format};
|
||||
|
||||
use crate::{
|
||||
Indexes, indexes, market, price,
|
||||
Indexes, indexes, price,
|
||||
stateful::{
|
||||
address_cohort,
|
||||
r#trait::{CohortVecs, DynCohortVecs},
|
||||
@@ -520,9 +520,10 @@ impl Vecs {
|
||||
indexes: &indexes::Vecs,
|
||||
price: Option<&price::Vecs>,
|
||||
starting_indexes: &Indexes,
|
||||
market: &market::Vecs,
|
||||
height_to_supply: &impl AnyIterableVec<Height, Bitcoin>,
|
||||
dateindex_to_supply: &impl AnyIterableVec<DateIndex, Bitcoin>,
|
||||
height_to_market_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
|
||||
dateindex_to_market_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
||||
height_to_realized_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
|
||||
dateindex_to_realized_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
||||
exit: &Exit,
|
||||
@@ -534,9 +535,10 @@ impl Vecs {
|
||||
indexes,
|
||||
price,
|
||||
starting_indexes,
|
||||
market,
|
||||
height_to_supply,
|
||||
dateindex_to_supply,
|
||||
height_to_market_cap,
|
||||
dateindex_to_market_cap,
|
||||
height_to_realized_cap,
|
||||
dateindex_to_realized_cap,
|
||||
exit,
|
||||
|
||||
@@ -14,7 +14,7 @@ use crate::{
|
||||
ComputedHeightValueVecs, ComputedRatioVecsFromDateIndex, ComputedValueVecsFromDateIndex,
|
||||
ComputedVecsFromDateIndex, ComputedVecsFromHeight, Source, VecBuilderOptions,
|
||||
},
|
||||
indexes, market, price,
|
||||
indexes, price,
|
||||
states::CohortState,
|
||||
};
|
||||
|
||||
@@ -2353,9 +2353,10 @@ impl Vecs {
|
||||
indexes: &indexes::Vecs,
|
||||
price: Option<&price::Vecs>,
|
||||
starting_indexes: &Indexes,
|
||||
market: &market::Vecs,
|
||||
height_to_supply: &impl AnyIterableVec<Height, Bitcoin>,
|
||||
dateindex_to_supply: &impl AnyIterableVec<DateIndex, Bitcoin>,
|
||||
height_to_market_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
|
||||
dateindex_to_market_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
||||
height_to_realized_cap: Option<&impl AnyIterableVec<Height, Dollars>>,
|
||||
dateindex_to_realized_cap: Option<&impl AnyIterableVec<DateIndex, Dollars>>,
|
||||
exit: &Exit,
|
||||
@@ -2382,6 +2383,9 @@ impl Vecs {
|
||||
}
|
||||
|
||||
if let Some(indexes_to_realized_cap) = self.indexes_to_realized_cap.as_mut() {
|
||||
let height_to_market_cap = height_to_market_cap.unwrap();
|
||||
let dateindex_to_market_cap = dateindex_to_market_cap.unwrap();
|
||||
|
||||
indexes_to_realized_cap.compute_rest(
|
||||
indexes,
|
||||
starting_indexes,
|
||||
@@ -2780,7 +2784,7 @@ impl Vecs {
|
||||
.compute_percentage(
|
||||
starting_indexes.height,
|
||||
self.height_to_unrealized_profit.as_ref().unwrap(),
|
||||
&market.height_to_marketcap,
|
||||
height_to_market_cap,
|
||||
exit,
|
||||
)?;
|
||||
self.height_to_unrealized_loss_relative_to_market_cap
|
||||
@@ -2789,7 +2793,7 @@ impl Vecs {
|
||||
.compute_percentage(
|
||||
starting_indexes.height,
|
||||
self.height_to_unrealized_loss.as_ref().unwrap(),
|
||||
&market.height_to_marketcap,
|
||||
height_to_market_cap,
|
||||
exit,
|
||||
)?;
|
||||
self.height_to_negative_unrealized_loss_relative_to_market_cap
|
||||
@@ -2798,7 +2802,7 @@ impl Vecs {
|
||||
.compute_percentage(
|
||||
starting_indexes.height,
|
||||
self.height_to_negative_unrealized_loss.as_ref().unwrap(),
|
||||
&market.height_to_marketcap,
|
||||
height_to_market_cap,
|
||||
exit,
|
||||
)?;
|
||||
self.height_to_net_unrealized_profit_and_loss_relative_to_market_cap
|
||||
@@ -2809,7 +2813,7 @@ impl Vecs {
|
||||
self.height_to_net_unrealized_profit_and_loss
|
||||
.as_ref()
|
||||
.unwrap(),
|
||||
&market.height_to_marketcap,
|
||||
height_to_market_cap,
|
||||
exit,
|
||||
)?;
|
||||
self.indexes_to_unrealized_profit_relative_to_market_cap
|
||||
@@ -2824,7 +2828,7 @@ impl Vecs {
|
||||
vec.compute_percentage(
|
||||
starting_indexes.dateindex,
|
||||
self.dateindex_to_unrealized_profit.as_ref().unwrap(),
|
||||
market.indexes_to_marketcap.dateindex.as_ref().unwrap(),
|
||||
dateindex_to_market_cap,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
@@ -2842,7 +2846,7 @@ impl Vecs {
|
||||
vec.compute_percentage(
|
||||
starting_indexes.dateindex,
|
||||
self.dateindex_to_unrealized_loss.as_ref().unwrap(),
|
||||
market.indexes_to_marketcap.dateindex.as_ref().unwrap(),
|
||||
dateindex_to_market_cap,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
@@ -2865,7 +2869,7 @@ impl Vecs {
|
||||
.dateindex
|
||||
.as_ref()
|
||||
.unwrap(),
|
||||
market.indexes_to_marketcap.dateindex.as_ref().unwrap(),
|
||||
dateindex_to_market_cap,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
@@ -2888,7 +2892,7 @@ impl Vecs {
|
||||
.dateindex
|
||||
.as_ref()
|
||||
.unwrap(),
|
||||
market.indexes_to_marketcap.dateindex.as_ref().unwrap(),
|
||||
dateindex_to_market_cap,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
@@ -3442,7 +3446,7 @@ impl Vecs {
|
||||
v.compute_percentage(
|
||||
starting_indexes.dateindex,
|
||||
self.indexes_to_net_realized_profit_and_loss_cumulative_30d_change.as_ref().unwrap().dateindex.as_ref().unwrap(),
|
||||
market.indexes_to_marketcap.dateindex.as_ref().unwrap(),
|
||||
dateindex_to_market_cap,
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
|
||||
@@ -18,15 +18,18 @@ use brk_structs::{
|
||||
use log::info;
|
||||
use rayon::prelude::*;
|
||||
use vecdb::{
|
||||
AnyCollectableVec, AnyStoredVec, AnyVec, CollectableVec, Database, EagerVec, Exit, Format,
|
||||
GenericStoredVec, ImportOptions, PAGE_SIZE, RawVec, Reader, Stamp, StoredIndex, VecIterator,
|
||||
AnyCloneableIterableVec, AnyCollectableVec, AnyStoredVec, AnyVec, CollectableVec, Database,
|
||||
EagerVec, Exit, Format, GenericStoredVec, ImportOptions, LazyVecFrom1, PAGE_SIZE, RawVec,
|
||||
Reader, Stamp, StoredIndex, VecIterator,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
BlockState, Indexes, SupplyState, Transacted,
|
||||
grouped::{ComputedValueVecsFromHeight, VecBuilderOptions},
|
||||
grouped::{ComputedVecsFromHeight, Source},
|
||||
indexes, market, price, transactions,
|
||||
BlockState, Indexes, SupplyState, Transacted, chain,
|
||||
grouped::{
|
||||
ComputedValueVecsFromHeight, ComputedVecsFromDateIndex, ComputedVecsFromHeight, Source,
|
||||
VecBuilderOptions,
|
||||
},
|
||||
indexes, price,
|
||||
};
|
||||
|
||||
mod address_cohort;
|
||||
@@ -82,6 +85,8 @@ pub struct Vecs {
|
||||
pub indexes_to_opreturn_supply: ComputedValueVecsFromHeight,
|
||||
pub indexes_to_address_count: ComputedVecsFromHeight<StoredU64>,
|
||||
pub indexes_to_empty_address_count: ComputedVecsFromHeight<StoredU64>,
|
||||
pub height_to_market_cap: Option<LazyVecFrom1<Height, Dollars, Height, Dollars>>,
|
||||
pub indexes_to_market_cap: Option<ComputedVecsFromDateIndex<Dollars>>,
|
||||
}
|
||||
|
||||
const SAVED_STAMPED_CHANGES: u16 = 10;
|
||||
@@ -103,6 +108,9 @@ impl Vecs {
|
||||
|
||||
let compute_dollars = price.is_some();
|
||||
|
||||
let utxo_cohorts =
|
||||
utxo_cohorts::Vecs::forced_import(&db, version, format, indexes, price, &states_path)?;
|
||||
|
||||
Ok(Self {
|
||||
chain_state: RawVec::forced_import_with(
|
||||
ImportOptions::new(&db, "chain", version + VERSION + Version::ZERO)
|
||||
@@ -153,6 +161,37 @@ impl Vecs {
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)?,
|
||||
height_to_market_cap: compute_dollars.then(|| {
|
||||
LazyVecFrom1::init(
|
||||
"market_cap",
|
||||
version + VERSION + Version::ONE,
|
||||
utxo_cohorts
|
||||
.all
|
||||
.1
|
||||
.height_to_supply_value
|
||||
.dollars
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.boxed_clone(),
|
||||
|height: Height, iter| {
|
||||
iter.next_at(height.unwrap_to_usize()).map(|(_, value)| {
|
||||
let d: Dollars = value.into_owned();
|
||||
d
|
||||
})
|
||||
},
|
||||
)
|
||||
}),
|
||||
indexes_to_market_cap: compute_dollars.then(|| {
|
||||
ComputedVecsFromDateIndex::forced_import(
|
||||
&db,
|
||||
"market_cap",
|
||||
Source::Compute,
|
||||
version + VERSION + Version::TWO,
|
||||
indexes,
|
||||
VecBuilderOptions::default().add_last(),
|
||||
)
|
||||
.unwrap()
|
||||
}),
|
||||
addresstype_to_height_to_address_count: AddressTypeToHeightToAddressCount::from(
|
||||
ByAddressType {
|
||||
p2pk65: EagerVec::forced_import_compressed(
|
||||
@@ -377,14 +416,7 @@ impl Vecs {
|
||||
)?,
|
||||
},
|
||||
),
|
||||
utxo_cohorts: utxo_cohorts::Vecs::forced_import(
|
||||
&db,
|
||||
version,
|
||||
format,
|
||||
indexes,
|
||||
price,
|
||||
&states_path,
|
||||
)?,
|
||||
utxo_cohorts,
|
||||
address_cohorts: address_cohorts::Vecs::forced_import(
|
||||
&db,
|
||||
version,
|
||||
@@ -445,22 +477,13 @@ impl Vecs {
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
transactions: &transactions::Vecs,
|
||||
chain: &chain::Vecs,
|
||||
price: Option<&price::Vecs>,
|
||||
market: &market::Vecs,
|
||||
// Must take ownership as its indexes will be updated for this specific function
|
||||
starting_indexes: &mut Indexes,
|
||||
exit: &Exit,
|
||||
) -> Result<()> {
|
||||
self.compute_(
|
||||
indexer,
|
||||
indexes,
|
||||
transactions,
|
||||
price,
|
||||
market,
|
||||
starting_indexes,
|
||||
exit,
|
||||
)?;
|
||||
self.compute_(indexer, indexes, chain, price, starting_indexes, exit)?;
|
||||
self.db.flush_then_punch()?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -470,9 +493,8 @@ impl Vecs {
|
||||
&mut self,
|
||||
indexer: &Indexer,
|
||||
indexes: &indexes::Vecs,
|
||||
transactions: &transactions::Vecs,
|
||||
chain: &chain::Vecs,
|
||||
price: Option<&price::Vecs>,
|
||||
market: &market::Vecs,
|
||||
// Must take ownership as its indexes will be updated for this specific function
|
||||
starting_indexes: &mut Indexes,
|
||||
exit: &Exit,
|
||||
@@ -487,8 +509,8 @@ impl Vecs {
|
||||
let height_to_first_p2traddressindex = &indexer.vecs.height_to_first_p2traddressindex;
|
||||
let height_to_first_p2wpkhaddressindex = &indexer.vecs.height_to_first_p2wpkhaddressindex;
|
||||
let height_to_first_p2wshaddressindex = &indexer.vecs.height_to_first_p2wshaddressindex;
|
||||
let height_to_output_count = transactions.indexes_to_output_count.height.unwrap_sum();
|
||||
let height_to_input_count = transactions.indexes_to_input_count.height.unwrap_sum();
|
||||
let height_to_output_count = chain.indexes_to_output_count.height.unwrap_sum();
|
||||
let height_to_input_count = chain.indexes_to_input_count.height.unwrap_sum();
|
||||
let inputindex_to_outputindex = &indexer.vecs.inputindex_to_outputindex;
|
||||
let outputindex_to_value = &indexer.vecs.outputindex_to_value;
|
||||
let txindex_to_height = &indexes.txindex_to_height;
|
||||
@@ -496,7 +518,7 @@ impl Vecs {
|
||||
let outputindex_to_txindex = &indexes.outputindex_to_txindex;
|
||||
let outputindex_to_outputtype = &indexer.vecs.outputindex_to_outputtype;
|
||||
let outputindex_to_typeindex = &indexer.vecs.outputindex_to_typeindex;
|
||||
let height_to_unclaimed_rewards = transactions
|
||||
let height_to_unclaimed_rewards = chain
|
||||
.indexes_to_unclaimed_rewards
|
||||
.sats
|
||||
.height
|
||||
@@ -1331,6 +1353,33 @@ impl Vecs {
|
||||
self.address_cohorts
|
||||
.compute_rest_part1(indexer, indexes, price, starting_indexes, exit)?;
|
||||
|
||||
if let Some(indexes_to_market_cap) = self.indexes_to_market_cap.as_mut() {
|
||||
indexes_to_market_cap.compute_all(
|
||||
indexer,
|
||||
indexes,
|
||||
starting_indexes,
|
||||
exit,
|
||||
|v, _, _, starting_indexes, exit| {
|
||||
v.compute_transform(
|
||||
starting_indexes.dateindex,
|
||||
self.utxo_cohorts
|
||||
.all
|
||||
.1
|
||||
.indexes_to_supply
|
||||
.dollars
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.dateindex
|
||||
.as_ref()
|
||||
.unwrap(),
|
||||
|(i, v, ..)| (i, v),
|
||||
exit,
|
||||
)?;
|
||||
Ok(())
|
||||
},
|
||||
)?;
|
||||
}
|
||||
|
||||
info!("Computing rest part 2...");
|
||||
|
||||
let height_to_supply = &self
|
||||
@@ -1348,6 +1397,11 @@ impl Vecs {
|
||||
.bitcoin
|
||||
.dateindex
|
||||
.clone();
|
||||
let height_to_market_cap = self.height_to_market_cap.clone();
|
||||
let dateindex_to_market_cap = self
|
||||
.indexes_to_market_cap
|
||||
.as_ref()
|
||||
.map(|v| v.dateindex.as_ref().unwrap().clone());
|
||||
let height_to_realized_cap = self.utxo_cohorts.all.1.height_to_realized_cap.clone();
|
||||
let dateindex_to_realized_cap = self
|
||||
.utxo_cohorts
|
||||
@@ -1357,6 +1411,8 @@ impl Vecs {
|
||||
.as_ref()
|
||||
.map(|v| v.dateindex.unwrap_last().clone());
|
||||
let dateindex_to_supply_ref = dateindex_to_supply.as_ref().unwrap();
|
||||
let height_to_market_cap_ref = height_to_market_cap.as_ref();
|
||||
let dateindex_to_market_cap_ref = dateindex_to_market_cap.as_ref();
|
||||
let height_to_realized_cap_ref = height_to_realized_cap.as_ref();
|
||||
let dateindex_to_realized_cap_ref = dateindex_to_realized_cap.as_ref();
|
||||
|
||||
@@ -1365,9 +1421,10 @@ impl Vecs {
|
||||
indexes,
|
||||
price,
|
||||
starting_indexes,
|
||||
market,
|
||||
height_to_supply,
|
||||
dateindex_to_supply_ref,
|
||||
height_to_market_cap_ref,
|
||||
dateindex_to_market_cap_ref,
|
||||
height_to_realized_cap_ref,
|
||||
dateindex_to_realized_cap_ref,
|
||||
exit,
|
||||
@@ -1378,9 +1435,10 @@ impl Vecs {
|
||||
indexes,
|
||||
price,
|
||||
starting_indexes,
|
||||
market,
|
||||
height_to_supply,
|
||||
dateindex_to_supply_ref,
|
||||
height_to_market_cap_ref,
|
||||
dateindex_to_market_cap_ref,
|
||||
height_to_realized_cap_ref,
|
||||
dateindex_to_realized_cap_ref,
|
||||
exit,
|
||||
@@ -1790,6 +1848,9 @@ impl Vecs {
|
||||
self.indexes_to_address_count.vecs(),
|
||||
self.indexes_to_empty_address_count.vecs(),
|
||||
self.addresstype_to_indexes_to_address_count.vecs(),
|
||||
self.indexes_to_market_cap
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| v.vecs()),
|
||||
self.addresstype_to_indexes_to_empty_address_count.vecs(),
|
||||
self.addresstype_to_height_to_address_count
|
||||
.as_typed_vec()
|
||||
@@ -1801,6 +1862,9 @@ impl Vecs {
|
||||
.into_iter()
|
||||
.map(|(_, v)| v as &dyn AnyCollectableVec)
|
||||
.collect::<Vec<_>>(),
|
||||
self.height_to_market_cap
|
||||
.as_ref()
|
||||
.map_or(vec![], |v| vec![v]),
|
||||
vec
|
||||
|
||||
## What it provides
|
||||
|
||||
- **MCP Server Implementation**: Standards-compliant Model Context Protocol server
|
||||
|
||||
@@ -145,7 +145,7 @@ curl "/api/vecs/month-to-supply"
|
||||
|
||||
**CSV Format**:
|
||||
```csv
|
||||
index,close,supply,feerate
|
||||
index,close,supply,fee_rate
|
||||
0,42.5,1500,0.05
|
||||
1,43.1,1520,0.052
|
||||
2,44.2,1480,0.048
|
||||
|
||||
@@ -47,6 +47,10 @@ impl Date {
|
||||
pub fn into_jiff(self) -> Date_ {
|
||||
self.into()
|
||||
}
|
||||
|
||||
pub fn today() -> Self {
|
||||
Self::from(Timestamp::now())
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Date {
|
||||
|
||||
@@ -12,9 +12,9 @@ use super::{Sats, StoredU64};
|
||||
#[derive(
|
||||
Debug, Clone, Copy, Serialize, FromBytes, Immutable, IntoBytes, KnownLayout, StoredCompressed,
|
||||
)]
|
||||
pub struct Feerate(f64);
|
||||
pub struct FeeRate(f64);
|
||||
|
||||
impl From<(Sats, StoredU64)> for Feerate {
|
||||
impl From<(Sats, StoredU64)> for FeeRate {
|
||||
fn from((sats, vsize): (Sats, StoredU64)) -> Self {
|
||||
let sats = u64::from(sats);
|
||||
let vsize = u64::from(vsize);
|
||||
@@ -22,44 +22,44 @@ impl From<(Sats, StoredU64)> for Feerate {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f64> for Feerate {
|
||||
impl From<f64> for FeeRate {
|
||||
fn from(value: f64) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl From<Feerate> for f64 {
|
||||
fn from(value: Feerate) -> Self {
|
||||
impl From<FeeRate> for f64 {
|
||||
fn from(value: FeeRate) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Add for Feerate {
|
||||
impl Add for FeeRate {
|
||||
type Output = Self;
|
||||
fn add(self, rhs: Self) -> Self::Output {
|
||||
Self(self.0 + rhs.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl AddAssign for Feerate {
|
||||
impl AddAssign for FeeRate {
|
||||
fn add_assign(&mut self, rhs: Self) {
|
||||
*self = *self + rhs
|
||||
}
|
||||
}
|
||||
|
||||
impl Div<usize> for Feerate {
|
||||
impl Div<usize> for FeeRate {
|
||||
type Output = Self;
|
||||
fn div(self, rhs: usize) -> Self::Output {
|
||||
Self(self.0 / rhs as f64)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for Feerate {
|
||||
impl From<usize> for FeeRate {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(value as f64)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Feerate {
|
||||
impl PartialEq for FeeRate {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
match (self.0.is_nan(), other.0.is_nan()) {
|
||||
(true, true) => true,
|
||||
@@ -70,17 +70,17 @@ impl PartialEq for Feerate {
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Feerate {}
|
||||
impl Eq for FeeRate {}
|
||||
|
||||
#[allow(clippy::derive_ord_xor_partial_ord)]
|
||||
impl PartialOrd for Feerate {
|
||||
impl PartialOrd for FeeRate {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::derive_ord_xor_partial_ord)]
|
||||
impl Ord for Feerate {
|
||||
impl Ord for FeeRate {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
match (self.0.is_nan(), other.0.is_nan()) {
|
||||
(true, true) => Ordering::Equal,
|
||||
|
||||
@@ -36,6 +36,12 @@ impl From<f64> for StoredF64 {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f32> for StoredF64 {
|
||||
fn from(value: f32) -> Self {
|
||||
Self(value as f64)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<usize> for StoredF64 {
|
||||
fn from(value: usize) -> Self {
|
||||
Self(value as f64)
|
||||
@@ -88,6 +94,12 @@ impl From<StoredF64> for f64 {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StoredF64> for f32 {
|
||||
fn from(value: StoredF64) -> Self {
|
||||
value.0 as f32
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Dollars> for StoredF64 {
|
||||
fn from(value: Dollars) -> Self {
|
||||
Self(f64::from(value))
|
||||
|
||||
@@ -69,6 +69,18 @@ impl Timestamp {
|
||||
pub fn is_more_than_hour(&self) -> bool {
|
||||
self.0 >= ONE_HOUR_IN_SEC
|
||||
}
|
||||
|
||||
pub fn now() -> Self {
|
||||
Self::from(jiff::Timestamp::now())
|
||||
}
|
||||
|
||||
pub fn day_completion(&self) -> f64 {
|
||||
let rounded = jiff::Timestamp::from(Self::from(Date::from(*self)));
|
||||
ONE_DAY_IN_SEC_F64
|
||||
/ jiff::Timestamp::from(*self)
|
||||
.duration_since(rounded)
|
||||
.as_secs_f64()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u32> for Timestamp {
|
||||
|
||||
@@ -997,13 +997,13 @@ function numberToShortUSFormat(value, digits) {
|
||||
return numberToUSFormat(value, Math.min(1, digits || 10));
|
||||
} else if (absoluteValue < 1_000_000) {
|
||||
return numberToUSFormat(value, 0);
|
||||
} else if (absoluteValue >= 900_000_000_000_000_000) {
|
||||
} else if (absoluteValue >= 900_000_000_000_000_000_000_000) {
|
||||
return "Inf.";
|
||||
}
|
||||
|
||||
const log = Math.floor(Math.log10(absoluteValue) - 6);
|
||||
|
||||
const suffices = ["M", "B", "T", "P", "E"];
|
||||
const suffices = ["M", "B", "T", "P", "E", "Z"];
|
||||
const letterIndex = Math.floor(log / 3);
|
||||
const letter = suffices[letterIndex];
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
* "%self" |
|
||||
* "%all" |
|
||||
* "Years" |
|
||||
* "H/s" |
|
||||
* "Locktime" |
|
||||
* "sat/vB" |
|
||||
* "%pnl" |
|
||||
@@ -732,13 +733,15 @@ function createUtils() {
|
||||
id.endsWith("stack") ||
|
||||
(id.endsWith("value") && !id.includes("realized")) ||
|
||||
((id.includes("coinbase") ||
|
||||
(id.includes("fee") && !id.includes("feerate")) ||
|
||||
id.includes("fee") ||
|
||||
id.includes("subsidy") ||
|
||||
id.includes("rewards")) &&
|
||||
!(
|
||||
id.startsWith("is_") ||
|
||||
id.includes("in_btc") ||
|
||||
id.includes("in_usd")
|
||||
id.includes("_btc") ||
|
||||
id.includes("_usd") ||
|
||||
id.includes("fee_rate") ||
|
||||
id.endsWith("dominance")
|
||||
)))
|
||||
) {
|
||||
if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`);
|
||||
@@ -755,8 +758,8 @@ function createUtils() {
|
||||
id === "low" ||
|
||||
id === "close" ||
|
||||
id === "open" ||
|
||||
id === "marketcap" ||
|
||||
id.includes("in_usd") ||
|
||||
id === "market_cap" ||
|
||||
id.includes("_usd") ||
|
||||
id.includes("cointime_value") ||
|
||||
id.startsWith("price") ||
|
||||
id.endsWith("price_paid") ||
|
||||
@@ -768,7 +771,8 @@ function createUtils() {
|
||||
!id.includes("ratio") &&
|
||||
!id.includes("relative_to")) ||
|
||||
((id.endsWith("sma") || id.includes("sma_x") || id.endsWith("ema")) &&
|
||||
!id.includes("ratio")) ||
|
||||
!id.includes("ratio") &&
|
||||
!id.includes("hash_rate")) ||
|
||||
id === "ath")
|
||||
) {
|
||||
if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`);
|
||||
@@ -796,14 +800,17 @@ function createUtils() {
|
||||
id.endsWith("p98") ||
|
||||
id.endsWith("p99"))) ||
|
||||
id.includes("liveliness") ||
|
||||
id.includes("vaultedness")
|
||||
id.includes("vaultedness") ||
|
||||
id == "puell_multiple"
|
||||
) {
|
||||
if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`);
|
||||
unit = "Ratio";
|
||||
}
|
||||
if (
|
||||
(!unit || thoroughUnitCheck) &&
|
||||
(id === "drawdown" || id.endsWith("oscillator"))
|
||||
(id === "drawdown" ||
|
||||
id.endsWith("oscillator") ||
|
||||
id.endsWith("dominance"))
|
||||
) {
|
||||
if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`);
|
||||
unit = "percentage";
|
||||
@@ -818,7 +825,14 @@ function createUtils() {
|
||||
if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`);
|
||||
unit = "Count";
|
||||
}
|
||||
if ((!unit || thoroughUnitCheck) && id.includes("feerate")) {
|
||||
if (
|
||||
(!unit || thoroughUnitCheck) &&
|
||||
(id.startsWith("hash_rate") || id.endsWith("as_hash"))
|
||||
) {
|
||||
if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`);
|
||||
unit = "H/s";
|
||||
}
|
||||
if ((!unit || thoroughUnitCheck) && id.includes("fee_rate")) {
|
||||
if (unit) throw Error(`Unit "${unit}" already assigned "${id}"`);
|
||||
unit = "sat/vB";
|
||||
}
|
||||
|
||||
@@ -157,24 +157,24 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
* @typedef {"_30d_change"} _30DChageSubString
|
||||
* @typedef {StartsWith<CumulativePrefix>} CumulativeVecId
|
||||
* @typedef {ExcludeSubstring<WithoutPrefix<CumulativeVecId, CumulativePrefix>, _30DChageSubString>} CumulativeVecIdBase
|
||||
* @typedef {"_average"} AverageSuffix
|
||||
* @typedef {"_avg"} AverageSuffix
|
||||
* @typedef {EndsWith<AverageSuffix>} VecIdAverage
|
||||
* @typedef {WithoutSuffix<VecIdAverage, AverageSuffix>} VecIdAverageBase
|
||||
* @typedef {"_median"} MedianSuffix
|
||||
* @typedef {EndsWith<MedianSuffix>} VecIdMedian
|
||||
* @typedef {WithoutSuffix<VecIdMedian, MedianSuffix>} VecIdMedianBase
|
||||
* @typedef {"_90p"} _90pSuffix
|
||||
* @typedef {EndsWith<_90pSuffix>} VecId90p
|
||||
* @typedef {WithoutSuffix<VecId90p, _90pSuffix>} VecId90pBase
|
||||
* @typedef {"_75p"} _75pSuffix
|
||||
* @typedef {EndsWith<_75pSuffix>} VecId75p
|
||||
* @typedef {WithoutSuffix<VecId75p, _75pSuffix>} VecId75pBase
|
||||
* @typedef {"_25p"} _25pSuffix
|
||||
* @typedef {EndsWith<_25pSuffix>} VecId25p
|
||||
* @typedef {WithoutSuffix<VecId25p, _25pSuffix>} VecId25pBase
|
||||
* @typedef {"_10p"} _10pSuffix
|
||||
* @typedef {EndsWith<_10pSuffix>} VecId10p
|
||||
* @typedef {WithoutSuffix<VecId10p, _10pSuffix>} VecId10pBase
|
||||
* @typedef {"_p90"} _p90Suffix
|
||||
* @typedef {EndsWith<_p90Suffix>} VecIdp90
|
||||
* @typedef {WithoutSuffix<VecIdp90, _p90Suffix>} VecIdp90Base
|
||||
* @typedef {"_p75"} _p75Suffix
|
||||
* @typedef {EndsWith<_p75Suffix>} VecIdp75
|
||||
* @typedef {WithoutSuffix<VecIdp75, _p75Suffix>} VecIdp75Base
|
||||
* @typedef {"_p25"} _p25Suffix
|
||||
* @typedef {EndsWith<_p25Suffix>} VecIdp25
|
||||
* @typedef {WithoutSuffix<VecIdp25, _p25Suffix>} VecIdp25Base
|
||||
* @typedef {"_p10"} _p10Suffix
|
||||
* @typedef {EndsWith<_p10Suffix>} VecIdp10
|
||||
* @typedef {WithoutSuffix<VecIdp10, _p10Suffix>} VecIdp10Base
|
||||
* @typedef {"_max"} MaxSuffix
|
||||
* @typedef {EndsWith<MaxSuffix>} VecIdMax
|
||||
* @typedef {WithoutSuffix<VecIdMax, MaxSuffix>} VecIdMaxBase
|
||||
@@ -1152,7 +1152,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
*/
|
||||
function createAverageSeries({ concat, title = "" }) {
|
||||
return /** @satisfies {AnyFetchedSeriesBlueprint} */ ({
|
||||
key: `${concat}_average`,
|
||||
key: `${concat}_avg`,
|
||||
title: `Average ${title}`,
|
||||
});
|
||||
}
|
||||
@@ -1191,10 +1191,11 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
* @param {Color} [args.color]
|
||||
*/
|
||||
function createSumSeries({ key, title = "", color }) {
|
||||
const sumKey = `${key}_sum`;
|
||||
return /** @satisfies {AnyFetchedSeriesBlueprint} */ ({
|
||||
key: key in vecIdToIndexes ? key : `${key}_sum`,
|
||||
key: `${key}_sum` in vecIdToIndexes ? sumKey : key,
|
||||
title: `Sum ${title}`,
|
||||
color: color ?? colors.orange,
|
||||
color: color ?? colors.red,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1206,16 +1207,16 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
*/
|
||||
function createCumulativeSeries({ concat, title = "", color }) {
|
||||
return /** @satisfies {AnyFetchedSeriesBlueprint} */ ({
|
||||
key: `${concat}_cumulative`,
|
||||
key: `${concat}_cum`,
|
||||
title: `Cumulative ${title}`,
|
||||
color: color ?? colors.red,
|
||||
color: color ?? colors.cyan,
|
||||
defaultActive: false,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} args
|
||||
* @param {VecIdMinBase & VecIdMaxBase & VecId90pBase & VecId75pBase & VecIdMedianBase & VecId25pBase & VecId10pBase} args.concat
|
||||
* @param {VecIdMinBase & VecIdMaxBase & VecIdp90Base & VecIdp75Base & VecIdMedianBase & VecIdp25Base & VecIdp10Base} args.concat
|
||||
* @param {string} [args.title]
|
||||
*/
|
||||
function createMinMaxPercentilesSeries({ concat, title = "" }) {
|
||||
@@ -1239,26 +1240,26 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
key: `${concat}_75p`,
|
||||
title: `75p ${title}`,
|
||||
key: `${concat}_p75`,
|
||||
title: `p75 ${title}`,
|
||||
color: colors.red,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
key: `${concat}_25p`,
|
||||
title: `25p ${title}`,
|
||||
key: `${concat}_p25`,
|
||||
title: `p25 ${title}`,
|
||||
color: colors.yellow,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
key: `${concat}_90p`,
|
||||
title: `90p ${title}`,
|
||||
key: `${concat}_p90`,
|
||||
title: `p90 ${title}`,
|
||||
color: colors.rose,
|
||||
defaultActive: false,
|
||||
},
|
||||
{
|
||||
key: `${concat}_10p`,
|
||||
title: `10p ${title}`,
|
||||
key: `${concat}_p10`,
|
||||
title: `p10 ${title}`,
|
||||
color: colors.lime,
|
||||
defaultActive: false,
|
||||
},
|
||||
@@ -1266,7 +1267,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {VecIdAverageBase & CumulativeVecIdBase & VecIdMinBase & VecIdMaxBase & VecId90pBase & VecId75pBase & VecIdMedianBase & VecId25pBase & VecId10pBase} key
|
||||
* @param {VecIdAverageBase & CumulativeVecIdBase & VecIdMinBase & VecIdMaxBase & VecIdp90Base & VecIdp75Base & VecIdMedianBase & VecIdp25Base & VecIdp10Base} key
|
||||
*/
|
||||
function createSumCumulativeMinMaxPercentilesSeries(key) {
|
||||
return [
|
||||
@@ -1276,7 +1277,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {VecIdAverageBase & CumulativeVecIdBase & VecIdMinBase & VecIdMaxBase & VecId90pBase & VecId75pBase & VecIdMedianBase & VecId25pBase & VecId10pBase} key
|
||||
* @param {VecIdAverageBase & CumulativeVecIdBase & VecIdMinBase & VecIdMaxBase & VecIdp90Base & VecIdp75Base & VecIdMedianBase & VecIdp25Base & VecIdp10Base} key
|
||||
*/
|
||||
function createAverageSumCumulativeMinMaxPercentilesSeries(key) {
|
||||
return [
|
||||
@@ -1287,7 +1288,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
|
||||
/**
|
||||
* @param {Object} args
|
||||
* @param {VecId & VecIdAverageBase & CumulativeVecIdBase & VecIdMinBase & VecIdMaxBase & VecId90pBase & VecId75pBase & VecIdMedianBase & VecId25pBase & VecId10pBase} args.key
|
||||
* @param {VecId & VecIdAverageBase & CumulativeVecIdBase & VecIdMinBase & VecIdMaxBase & VecIdp90Base & VecIdp75Base & VecIdMedianBase & VecIdp25Base & VecIdp10Base} args.key
|
||||
* @param {string} args.name
|
||||
*/
|
||||
function createBaseAverageSumCumulativeMinMaxPercentilesSeries({
|
||||
@@ -2177,7 +2178,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
color: colors.green,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: `${fixKey(args.key)}realized_profit_cumulative`,
|
||||
key: `${fixKey(args.key)}realized_profit_cum`,
|
||||
name: "Cumulative Profit",
|
||||
color: colors.green,
|
||||
defaultActive: false,
|
||||
@@ -2189,7 +2190,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
defaultActive: false,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: `${fixKey(args.key)}realized_loss_cumulative`,
|
||||
key: `${fixKey(args.key)}realized_loss_cum`,
|
||||
name: "Cumulative Loss",
|
||||
color: colors.red,
|
||||
defaultActive: false,
|
||||
@@ -2200,9 +2201,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
color: colors.red,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: `${fixKey(
|
||||
args.key,
|
||||
)}negative_realized_loss_cumulative`,
|
||||
key: `${fixKey(args.key)}negative_realized_loss_cum`,
|
||||
name: "Cumulative Negative Loss",
|
||||
color: colors.red,
|
||||
defaultActive: false,
|
||||
@@ -2243,9 +2242,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
}),
|
||||
/** @satisfies {FetchedBaselineSeriesBlueprint} */ ({
|
||||
type: "Baseline",
|
||||
key: `${fixKey(
|
||||
key,
|
||||
)}net_realized_profit_and_loss_cumulative`,
|
||||
key: `${fixKey(key)}net_realized_profit_and_loss_cum`,
|
||||
title: "Cumulative",
|
||||
defaultActive: false,
|
||||
}),
|
||||
@@ -2476,7 +2473,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
const key = fixKey(_key);
|
||||
return /** @type {const} */ ([
|
||||
createBaseSeries({
|
||||
key: `${key}realized_profit_cumulative`,
|
||||
key: `${key}realized_profit_cum`,
|
||||
name,
|
||||
color,
|
||||
}),
|
||||
@@ -2490,7 +2487,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
const key = fixKey(_key);
|
||||
return /** @type {const} */ ([
|
||||
createBaseSeries({
|
||||
key: `${key}realized_loss_cumulative`,
|
||||
key: `${key}realized_loss_cum`,
|
||||
name,
|
||||
color,
|
||||
}),
|
||||
@@ -2506,7 +2503,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
type: "Baseline",
|
||||
key: `${fixKey(
|
||||
key,
|
||||
)}net_realized_profit_and_loss_cumulative`,
|
||||
)}net_realized_profit_and_loss_cum`,
|
||||
title: name,
|
||||
color,
|
||||
defaultActive: false,
|
||||
@@ -2946,7 +2943,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
color,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: `${key}coinblocks_destroyed_cumulative`,
|
||||
key: `${key}coinblocks_destroyed_cum`,
|
||||
name: useGroupName ? name : "cumulative",
|
||||
color,
|
||||
defaultActive: false,
|
||||
@@ -2957,7 +2954,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
color,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: `${key}coindays_destroyed_cumulative`,
|
||||
key: `${key}coindays_destroyed_cum`,
|
||||
name: useGroupName ? name : "cumulative",
|
||||
color,
|
||||
defaultActive: false,
|
||||
@@ -2994,7 +2991,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
title: "Market Capitalization",
|
||||
bottom: [
|
||||
createBaseSeries({
|
||||
key: "marketcap",
|
||||
key: "market_cap",
|
||||
name: "Capitalization",
|
||||
}),
|
||||
],
|
||||
@@ -3296,7 +3293,15 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
title: "Circulating Supply",
|
||||
bottom: [
|
||||
createBaseSeries({
|
||||
key: "subsidy_in_btc_cumulative",
|
||||
key: "supply",
|
||||
name: "Mined",
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: "supply_in_btc",
|
||||
name: "Mined",
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: "supply_in_usd",
|
||||
name: "Mined",
|
||||
}),
|
||||
],
|
||||
@@ -3327,6 +3332,10 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
key: "subsidy",
|
||||
name: "Subsidy",
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: "subsidy_usd_1y_sma",
|
||||
name: "1y sma",
|
||||
}),
|
||||
...createBaseAverageSumCumulativeMinMaxPercentilesSeries({
|
||||
key: "subsidy_in_btc",
|
||||
name: "Subsidy",
|
||||
@@ -3350,6 +3359,22 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Dominance",
|
||||
title: "Reward Dominance",
|
||||
bottom: [
|
||||
createBaseSeries({
|
||||
key: "fee_dominance",
|
||||
name: "Fee",
|
||||
color: colors.amber,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: "subsidy_dominance",
|
||||
name: "Subsidy",
|
||||
color: colors.red,
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Unclaimed Rewards",
|
||||
title: "Unclaimed Rewards",
|
||||
@@ -3369,9 +3394,19 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
name: "Feerate",
|
||||
title: "Transaction Fee Rate",
|
||||
bottom: [
|
||||
createAverageSeries({ concat: "feerate" }),
|
||||
createAverageSeries({ concat: "fee_rate" }),
|
||||
...createMinMaxPercentilesSeries({
|
||||
concat: "feerate",
|
||||
concat: "fee_rate",
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Puell multiple",
|
||||
title: "Puell multiple",
|
||||
bottom: [
|
||||
createBaseSeries({
|
||||
key: "puell_multiple",
|
||||
name: "Multiple",
|
||||
}),
|
||||
],
|
||||
},
|
||||
@@ -3385,6 +3420,50 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
}),
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "hash",
|
||||
tree: [
|
||||
{
|
||||
name: "Rate",
|
||||
title: "Hash Rate",
|
||||
bottom: [
|
||||
createBaseSeries({
|
||||
key: "hash_rate",
|
||||
name: "Raw",
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: "hash_rate_1w_sma",
|
||||
name: "1w sma",
|
||||
color: colors.red,
|
||||
defaultActive: false,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: "hash_rate_1m_sma",
|
||||
name: "1m sma",
|
||||
color: colors.pink,
|
||||
defaultActive: false,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: "hash_rate_2m_sma",
|
||||
name: "2m sma",
|
||||
color: colors.purple,
|
||||
defaultActive: false,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: "hash_rate_1y_sma",
|
||||
name: "1y sma",
|
||||
color: colors.indigo,
|
||||
defaultActive: false,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: "difficulty_as_hash",
|
||||
name: "difficulty",
|
||||
color: colors.default,
|
||||
}),
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "Difficulty Epoch",
|
||||
title: "Difficulty Epoch",
|
||||
@@ -3750,7 +3829,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
name: "sum",
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: "opreturn_count_cumulative",
|
||||
key: "opreturn_count_cum",
|
||||
name: "cumulative",
|
||||
color: colors.red,
|
||||
}),
|
||||
@@ -3815,7 +3894,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
title: "Compare Cointime Capitalizations",
|
||||
bottom: [
|
||||
createBaseSeries({
|
||||
key: `marketcap`,
|
||||
key: `market_cap`,
|
||||
name: "Market",
|
||||
color: colors.default,
|
||||
}),
|
||||
@@ -3844,7 +3923,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
color,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: `marketcap`,
|
||||
key: `market_cap`,
|
||||
name: "Market",
|
||||
color: colors.default,
|
||||
}),
|
||||
@@ -3924,7 +4003,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
color: colors.red,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: "coinblocks_destroyed_cumulative",
|
||||
key: "coinblocks_destroyed_cum",
|
||||
name: "Cumulative Destroyed",
|
||||
color: colors.red,
|
||||
defaultActive: false,
|
||||
@@ -3935,7 +4014,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
color: colors.orange,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: "coinblocks_created_cumulative",
|
||||
key: "coinblocks_created_cum",
|
||||
name: "Cumulative created",
|
||||
color: colors.orange,
|
||||
defaultActive: false,
|
||||
@@ -3946,7 +4025,7 @@ function createPartialOptions({ env, colors, vecIdToIndexes }) {
|
||||
color: colors.green,
|
||||
}),
|
||||
createBaseSeries({
|
||||
key: "coinblocks_stored_cumulative",
|
||||
key: "coinblocks_stored_cum",
|
||||
name: "Cumulative stored",
|
||||
color: colors.green,
|
||||
defaultActive: false,
|
||||
|
||||
Reference in New Issue
Block a user