global: snapshot

This commit is contained in:
nym21
2025-12-29 17:02:17 +01:00
parent 445959f5b9
commit e89a67b9a7
40 changed files with 4057 additions and 1829 deletions

View File

@@ -1,4 +1,4 @@
use brk_types::{Bitcoin, Close, Dollars, High, Sats, StoredF32, StoredF64, StoredU32};
use brk_types::{Bitcoin, Close, Dollars, Sats, StoredF32, StoredF64, StoredU32};
use vecdb::{BinaryTransform, UnaryTransform};
/// (Dollars, Dollars) -> Dollars addition
@@ -320,18 +320,3 @@ impl BinaryTransform<Close<Dollars>, Dollars, StoredF32> for PercentageDiffClose
}
}
}
/// (High<Dollars>, Dollars) -> StoredF32 percentage difference ((a/b - 1) × 100)
/// Used for drawdown calculation from high prices
pub struct PercentageDiffHighDollars;
impl BinaryTransform<High<Dollars>, Dollars, StoredF32> for PercentageDiffHighDollars {
#[inline(always)]
fn apply(high: High<Dollars>, base: Dollars) -> StoredF32 {
if base == Dollars::ZERO {
StoredF32::default()
} else {
StoredF32::from((**high / *base - 1.0) * 100.0)
}
}
}

View File

@@ -50,9 +50,11 @@ impl AddressCohortVecs {
///
/// `all_supply` is the supply metrics from the "all" cohort, used as global
/// sources for `*_rel_to_market_cap` ratios. Pass `None` if not available.
#[allow(clippy::too_many_arguments)]
pub fn forced_import(
db: &Database,
filter: Filter,
name: &str,
version: Version,
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
@@ -60,11 +62,12 @@ impl AddressCohortVecs {
all_supply: Option<&SupplyMetrics>,
) -> Result<Self> {
let compute_dollars = price.is_some();
let full_name = filter.to_full_name(CohortContext::Address);
let full_name = CohortContext::Address.full_name(&filter, name);
let cfg = ImportConfig {
db,
filter,
full_name: &full_name,
context: CohortContext::Address,
version,
indexes,

View File

@@ -2,11 +2,10 @@ use std::path::Path;
use brk_error::Result;
use brk_grouper::{
AddressGroups, AmountFilter, ByAmountRange, ByGreatEqualAmount, ByLowerThanAmount, Filter,
Filtered,
AddressGroups, ByAmountRange, ByGreatEqualAmount, ByLowerThanAmount, Filter, Filtered,
};
use brk_traversable::Traversable;
use brk_types::{Bitcoin, DateIndex, Dollars, Height, Sats, Version};
use brk_types::{Bitcoin, DateIndex, Dollars, Height, Version};
use derive_deref::{Deref, DerefMut};
use rayon::prelude::*;
use vecdb::{AnyStoredVec, Database, Exit, IterableVec};
@@ -37,90 +36,19 @@ impl AddressCohorts {
let v = version + VERSION + Version::ZERO;
// Helper to create a cohort - only amount_range cohorts have state
let create = |filter: Filter, has_state: bool| -> Result<AddressCohortVecs> {
let states_path = if has_state { Some(states_path) } else { None };
AddressCohortVecs::forced_import(db, filter, v, indexes, price, states_path, all_supply)
};
let create =
|filter: Filter, name: &'static str, has_state: bool| -> Result<AddressCohortVecs> {
let sp = if has_state { Some(states_path) } else { None };
AddressCohortVecs::forced_import(db, filter, name, v, indexes, price, sp, all_supply)
};
let full = |f: Filter| create(f, true);
let none = |f: Filter| create(f, false);
let full = |f: Filter, name: &'static str| create(f, name, true);
let none = |f: Filter, name: &'static str| create(f, name, false);
Ok(Self(AddressGroups {
amount_range: ByAmountRange {
_0sats: full(Filter::Amount(AmountFilter::LowerThan(Sats::_1)))?,
_1sat_to_10sats: full(Filter::Amount(AmountFilter::Range(Sats::_1..Sats::_10)))?,
_10sats_to_100sats: full(Filter::Amount(AmountFilter::Range(
Sats::_10..Sats::_100,
)))?,
_100sats_to_1k_sats: full(Filter::Amount(AmountFilter::Range(
Sats::_100..Sats::_1K,
)))?,
_1k_sats_to_10k_sats: full(Filter::Amount(AmountFilter::Range(
Sats::_1K..Sats::_10K,
)))?,
_10k_sats_to_100k_sats: full(Filter::Amount(AmountFilter::Range(
Sats::_10K..Sats::_100K,
)))?,
_100k_sats_to_1m_sats: full(Filter::Amount(AmountFilter::Range(
Sats::_100K..Sats::_1M,
)))?,
_1m_sats_to_10m_sats: full(Filter::Amount(AmountFilter::Range(
Sats::_1M..Sats::_10M,
)))?,
_10m_sats_to_1btc: full(Filter::Amount(AmountFilter::Range(
Sats::_10M..Sats::_1BTC,
)))?,
_1btc_to_10btc: full(Filter::Amount(AmountFilter::Range(
Sats::_1BTC..Sats::_10BTC,
)))?,
_10btc_to_100btc: full(Filter::Amount(AmountFilter::Range(
Sats::_10BTC..Sats::_100BTC,
)))?,
_100btc_to_1k_btc: full(Filter::Amount(AmountFilter::Range(
Sats::_100BTC..Sats::_1K_BTC,
)))?,
_1k_btc_to_10k_btc: full(Filter::Amount(AmountFilter::Range(
Sats::_1K_BTC..Sats::_10K_BTC,
)))?,
_10k_btc_to_100k_btc: full(Filter::Amount(AmountFilter::Range(
Sats::_10K_BTC..Sats::_100K_BTC,
)))?,
_100k_btc_or_more: full(Filter::Amount(AmountFilter::GreaterOrEqual(
Sats::_100K_BTC,
)))?,
},
lt_amount: ByLowerThanAmount {
_10sats: none(Filter::Amount(AmountFilter::LowerThan(Sats::_10)))?,
_100sats: none(Filter::Amount(AmountFilter::LowerThan(Sats::_100)))?,
_1k_sats: none(Filter::Amount(AmountFilter::LowerThan(Sats::_1K)))?,
_10k_sats: none(Filter::Amount(AmountFilter::LowerThan(Sats::_10K)))?,
_100k_sats: none(Filter::Amount(AmountFilter::LowerThan(Sats::_100K)))?,
_1m_sats: none(Filter::Amount(AmountFilter::LowerThan(Sats::_1M)))?,
_10m_sats: none(Filter::Amount(AmountFilter::LowerThan(Sats::_10M)))?,
_1btc: none(Filter::Amount(AmountFilter::LowerThan(Sats::_1BTC)))?,
_10btc: none(Filter::Amount(AmountFilter::LowerThan(Sats::_10BTC)))?,
_100btc: none(Filter::Amount(AmountFilter::LowerThan(Sats::_100BTC)))?,
_1k_btc: none(Filter::Amount(AmountFilter::LowerThan(Sats::_1K_BTC)))?,
_10k_btc: none(Filter::Amount(AmountFilter::LowerThan(Sats::_10K_BTC)))?,
_100k_btc: none(Filter::Amount(AmountFilter::LowerThan(Sats::_100K_BTC)))?,
},
ge_amount: ByGreatEqualAmount {
_1sat: none(Filter::Amount(AmountFilter::GreaterOrEqual(Sats::_1)))?,
_10sats: none(Filter::Amount(AmountFilter::GreaterOrEqual(Sats::_10)))?,
_100sats: none(Filter::Amount(AmountFilter::GreaterOrEqual(Sats::_100)))?,
_1k_sats: none(Filter::Amount(AmountFilter::GreaterOrEqual(Sats::_1K)))?,
_10k_sats: none(Filter::Amount(AmountFilter::GreaterOrEqual(Sats::_10K)))?,
_100k_sats: none(Filter::Amount(AmountFilter::GreaterOrEqual(Sats::_100K)))?,
_1m_sats: none(Filter::Amount(AmountFilter::GreaterOrEqual(Sats::_1M)))?,
_10m_sats: none(Filter::Amount(AmountFilter::GreaterOrEqual(Sats::_10M)))?,
_1btc: none(Filter::Amount(AmountFilter::GreaterOrEqual(Sats::_1BTC)))?,
_10btc: none(Filter::Amount(AmountFilter::GreaterOrEqual(Sats::_10BTC)))?,
_100btc: none(Filter::Amount(AmountFilter::GreaterOrEqual(Sats::_100BTC)))?,
_1k_btc: none(Filter::Amount(AmountFilter::GreaterOrEqual(Sats::_1K_BTC)))?,
_10k_btc: none(Filter::Amount(AmountFilter::GreaterOrEqual(Sats::_10K_BTC)))?,
},
amount_range: ByAmountRange::try_new(&full)?,
lt_amount: ByLowerThanAmount::try_new(&none)?,
ge_amount: ByGreatEqualAmount::try_new(&none)?,
}))
}

View File

@@ -38,6 +38,7 @@ impl UTXOCohortVecs {
pub fn forced_import(
db: &Database,
filter: Filter,
name: &str,
version: Version,
indexes: &indexes::Vecs,
price: Option<&price::Vecs>,
@@ -46,11 +47,12 @@ impl UTXOCohortVecs {
all_supply: Option<&SupplyMetrics>,
) -> Result<Self> {
let compute_dollars = price.is_some();
let full_name = filter.to_full_name(CohortContext::Utxo);
let full_name = CohortContext::Utxo.full_name(&filter, name);
let cfg = ImportConfig {
db,
filter,
full_name: &full_name,
context: CohortContext::Utxo,
version,
indexes,

View File

@@ -6,16 +6,11 @@ use std::path::Path;
use brk_error::Result;
use brk_grouper::{
AmountFilter, ByAgeRange, ByAmountRange, ByEpoch, ByGreatEqualAmount, ByLowerThanAmount,
ByMaxAge, ByMinAge, BySpendableType, ByTerm, ByYear, DAYS_1D, DAYS_1M, DAYS_1W, DAYS_1Y,
DAYS_2M, DAYS_2Y, DAYS_3M, DAYS_3Y, DAYS_4M, DAYS_4Y, DAYS_5M, DAYS_5Y, DAYS_6M, DAYS_6Y,
DAYS_7Y, DAYS_8Y, DAYS_10Y, DAYS_12Y, DAYS_15Y, Filter, Filtered, StateLevel, Term, TimeFilter,
UTXOGroups,
ByAgeRange, ByAmountRange, ByEpoch, ByGreatEqualAmount, ByLowerThanAmount, ByMaxAge, ByMinAge,
BySpendableType, ByTerm, ByYear, Filter, Filtered, StateLevel, UTXOGroups,
};
use brk_traversable::Traversable;
use brk_types::{
Bitcoin, DateIndex, Dollars, HalvingEpoch, Height, OutputType, Sats, Version, Year,
};
use brk_types::{Bitcoin, DateIndex, Dollars, Height, Sats, Version};
use derive_deref::{Deref, DerefMut};
use rayon::prelude::*;
use vecdb::{AnyStoredVec, Database, Exit, IterableVec};
@@ -50,6 +45,7 @@ impl UTXOCohorts {
let all = UTXOCohortVecs::forced_import(
db,
Filter::All,
"",
version + VERSION + Version::ONE,
indexes,
price,
@@ -62,227 +58,34 @@ impl UTXOCohorts {
let all_supply = Some(&all.metrics.supply);
// Create all cohorts first (while borrowing all_supply), then assemble struct
let term = ByTerm {
short: UTXOCohortVecs::forced_import(
db,
Filter::Term(Term::Sth),
v,
indexes,
price,
states_path,
StateLevel::PriceOnly,
all_supply,
)?,
long: UTXOCohortVecs::forced_import(
db,
Filter::Term(Term::Lth),
v,
indexes,
price,
states_path,
StateLevel::PriceOnly,
all_supply,
)?,
};
let full = |f: Filter| {
let price_only = |f: Filter, name: &'static str| {
UTXOCohortVecs::forced_import(
db,
f,
v,
indexes,
price,
states_path,
StateLevel::Full,
all_supply,
)
};
let none = |f: Filter| {
UTXOCohortVecs::forced_import(
db,
f,
v,
indexes,
price,
states_path,
StateLevel::None,
all_supply,
db, f, name, v, indexes, price, states_path, StateLevel::PriceOnly, all_supply,
)
};
let epoch = ByEpoch {
_0: full(Filter::Epoch(HalvingEpoch::new(0)))?,
_1: full(Filter::Epoch(HalvingEpoch::new(1)))?,
_2: full(Filter::Epoch(HalvingEpoch::new(2)))?,
_3: full(Filter::Epoch(HalvingEpoch::new(3)))?,
_4: full(Filter::Epoch(HalvingEpoch::new(4)))?,
let term = ByTerm::try_new(&price_only)?;
let full = |f: Filter, name: &'static str| {
UTXOCohortVecs::forced_import(
db, f, name, v, indexes, price, states_path, StateLevel::Full, all_supply,
)
};
let none = |f: Filter, name: &'static str| {
UTXOCohortVecs::forced_import(
db, f, name, v, indexes, price, states_path, StateLevel::None, all_supply,
)
};
let year = ByYear {
_2009: full(Filter::Year(Year::new(2009)))?,
_2010: full(Filter::Year(Year::new(2010)))?,
_2011: full(Filter::Year(Year::new(2011)))?,
_2012: full(Filter::Year(Year::new(2012)))?,
_2013: full(Filter::Year(Year::new(2013)))?,
_2014: full(Filter::Year(Year::new(2014)))?,
_2015: full(Filter::Year(Year::new(2015)))?,
_2016: full(Filter::Year(Year::new(2016)))?,
_2017: full(Filter::Year(Year::new(2017)))?,
_2018: full(Filter::Year(Year::new(2018)))?,
_2019: full(Filter::Year(Year::new(2019)))?,
_2020: full(Filter::Year(Year::new(2020)))?,
_2021: full(Filter::Year(Year::new(2021)))?,
_2022: full(Filter::Year(Year::new(2022)))?,
_2023: full(Filter::Year(Year::new(2023)))?,
_2024: full(Filter::Year(Year::new(2024)))?,
_2025: full(Filter::Year(Year::new(2025)))?,
_2026: full(Filter::Year(Year::new(2026)))?,
};
let type_ = BySpendableType {
p2pk65: full(Filter::Type(OutputType::P2PK65))?,
p2pk33: full(Filter::Type(OutputType::P2PK33))?,
p2pkh: full(Filter::Type(OutputType::P2PKH))?,
p2sh: full(Filter::Type(OutputType::P2SH))?,
p2wpkh: full(Filter::Type(OutputType::P2WPKH))?,
p2wsh: full(Filter::Type(OutputType::P2WSH))?,
p2tr: full(Filter::Type(OutputType::P2TR))?,
p2a: full(Filter::Type(OutputType::P2A))?,
p2ms: full(Filter::Type(OutputType::P2MS))?,
empty: full(Filter::Type(OutputType::Empty))?,
unknown: full(Filter::Type(OutputType::Unknown))?,
};
let max_age = ByMaxAge {
_1w: none(Filter::Time(TimeFilter::LowerThan(DAYS_1W)))?,
_1m: none(Filter::Time(TimeFilter::LowerThan(DAYS_1M)))?,
_2m: none(Filter::Time(TimeFilter::LowerThan(DAYS_2M)))?,
_3m: none(Filter::Time(TimeFilter::LowerThan(DAYS_3M)))?,
_4m: none(Filter::Time(TimeFilter::LowerThan(DAYS_4M)))?,
_5m: none(Filter::Time(TimeFilter::LowerThan(DAYS_5M)))?,
_6m: none(Filter::Time(TimeFilter::LowerThan(DAYS_6M)))?,
_1y: none(Filter::Time(TimeFilter::LowerThan(DAYS_1Y)))?,
_2y: none(Filter::Time(TimeFilter::LowerThan(DAYS_2Y)))?,
_3y: none(Filter::Time(TimeFilter::LowerThan(DAYS_3Y)))?,
_4y: none(Filter::Time(TimeFilter::LowerThan(DAYS_4Y)))?,
_5y: none(Filter::Time(TimeFilter::LowerThan(DAYS_5Y)))?,
_6y: none(Filter::Time(TimeFilter::LowerThan(DAYS_6Y)))?,
_7y: none(Filter::Time(TimeFilter::LowerThan(DAYS_7Y)))?,
_8y: none(Filter::Time(TimeFilter::LowerThan(DAYS_8Y)))?,
_10y: none(Filter::Time(TimeFilter::LowerThan(DAYS_10Y)))?,
_12y: none(Filter::Time(TimeFilter::LowerThan(DAYS_12Y)))?,
_15y: none(Filter::Time(TimeFilter::LowerThan(DAYS_15Y)))?,
};
let min_age = ByMinAge {
_1d: none(Filter::Time(TimeFilter::GreaterOrEqual(DAYS_1D)))?,
_1w: none(Filter::Time(TimeFilter::GreaterOrEqual(DAYS_1W)))?,
_1m: none(Filter::Time(TimeFilter::GreaterOrEqual(DAYS_1M)))?,
_2m: none(Filter::Time(TimeFilter::GreaterOrEqual(DAYS_2M)))?,
_3m: none(Filter::Time(TimeFilter::GreaterOrEqual(DAYS_3M)))?,
_4m: none(Filter::Time(TimeFilter::GreaterOrEqual(DAYS_4M)))?,
_5m: none(Filter::Time(TimeFilter::GreaterOrEqual(DAYS_5M)))?,
_6m: none(Filter::Time(TimeFilter::GreaterOrEqual(DAYS_6M)))?,
_1y: none(Filter::Time(TimeFilter::GreaterOrEqual(DAYS_1Y)))?,
_2y: none(Filter::Time(TimeFilter::GreaterOrEqual(DAYS_2Y)))?,
_3y: none(Filter::Time(TimeFilter::GreaterOrEqual(DAYS_3Y)))?,
_4y: none(Filter::Time(TimeFilter::GreaterOrEqual(DAYS_4Y)))?,
_5y: none(Filter::Time(TimeFilter::GreaterOrEqual(DAYS_5Y)))?,
_6y: none(Filter::Time(TimeFilter::GreaterOrEqual(DAYS_6Y)))?,
_7y: none(Filter::Time(TimeFilter::GreaterOrEqual(DAYS_7Y)))?,
_8y: none(Filter::Time(TimeFilter::GreaterOrEqual(DAYS_8Y)))?,
_10y: none(Filter::Time(TimeFilter::GreaterOrEqual(DAYS_10Y)))?,
_12y: none(Filter::Time(TimeFilter::GreaterOrEqual(DAYS_12Y)))?,
};
let age_range = ByAgeRange {
up_to_1d: full(Filter::Time(TimeFilter::Range(0..DAYS_1D)))?,
_1d_to_1w: full(Filter::Time(TimeFilter::Range(DAYS_1D..DAYS_1W)))?,
_1w_to_1m: full(Filter::Time(TimeFilter::Range(DAYS_1W..DAYS_1M)))?,
_1m_to_2m: full(Filter::Time(TimeFilter::Range(DAYS_1M..DAYS_2M)))?,
_2m_to_3m: full(Filter::Time(TimeFilter::Range(DAYS_2M..DAYS_3M)))?,
_3m_to_4m: full(Filter::Time(TimeFilter::Range(DAYS_3M..DAYS_4M)))?,
_4m_to_5m: full(Filter::Time(TimeFilter::Range(DAYS_4M..DAYS_5M)))?,
_5m_to_6m: full(Filter::Time(TimeFilter::Range(DAYS_5M..DAYS_6M)))?,
_6m_to_1y: full(Filter::Time(TimeFilter::Range(DAYS_6M..DAYS_1Y)))?,
_1y_to_2y: full(Filter::Time(TimeFilter::Range(DAYS_1Y..DAYS_2Y)))?,
_2y_to_3y: full(Filter::Time(TimeFilter::Range(DAYS_2Y..DAYS_3Y)))?,
_3y_to_4y: full(Filter::Time(TimeFilter::Range(DAYS_3Y..DAYS_4Y)))?,
_4y_to_5y: full(Filter::Time(TimeFilter::Range(DAYS_4Y..DAYS_5Y)))?,
_5y_to_6y: full(Filter::Time(TimeFilter::Range(DAYS_5Y..DAYS_6Y)))?,
_6y_to_7y: full(Filter::Time(TimeFilter::Range(DAYS_6Y..DAYS_7Y)))?,
_7y_to_8y: full(Filter::Time(TimeFilter::Range(DAYS_7Y..DAYS_8Y)))?,
_8y_to_10y: full(Filter::Time(TimeFilter::Range(DAYS_8Y..DAYS_10Y)))?,
_10y_to_12y: full(Filter::Time(TimeFilter::Range(DAYS_10Y..DAYS_12Y)))?,
_12y_to_15y: full(Filter::Time(TimeFilter::Range(DAYS_12Y..DAYS_15Y)))?,
from_15y: full(Filter::Time(TimeFilter::GreaterOrEqual(DAYS_15Y)))?,
};
let amount_range = ByAmountRange {
_0sats: full(Filter::Amount(AmountFilter::LowerThan(Sats::_1)))?,
_1sat_to_10sats: full(Filter::Amount(AmountFilter::Range(Sats::_1..Sats::_10)))?,
_10sats_to_100sats: full(Filter::Amount(AmountFilter::Range(Sats::_10..Sats::_100)))?,
_100sats_to_1k_sats: full(Filter::Amount(AmountFilter::Range(Sats::_100..Sats::_1K)))?,
_1k_sats_to_10k_sats: full(Filter::Amount(AmountFilter::Range(Sats::_1K..Sats::_10K)))?,
_10k_sats_to_100k_sats: full(Filter::Amount(AmountFilter::Range(
Sats::_10K..Sats::_100K,
)))?,
_100k_sats_to_1m_sats: full(Filter::Amount(AmountFilter::Range(
Sats::_100K..Sats::_1M,
)))?,
_1m_sats_to_10m_sats: full(Filter::Amount(AmountFilter::Range(Sats::_1M..Sats::_10M)))?,
_10m_sats_to_1btc: full(Filter::Amount(AmountFilter::Range(Sats::_10M..Sats::_1BTC)))?,
_1btc_to_10btc: full(Filter::Amount(AmountFilter::Range(
Sats::_1BTC..Sats::_10BTC,
)))?,
_10btc_to_100btc: full(Filter::Amount(AmountFilter::Range(
Sats::_10BTC..Sats::_100BTC,
)))?,
_100btc_to_1k_btc: full(Filter::Amount(AmountFilter::Range(
Sats::_100BTC..Sats::_1K_BTC,
)))?,
_1k_btc_to_10k_btc: full(Filter::Amount(AmountFilter::Range(
Sats::_1K_BTC..Sats::_10K_BTC,
)))?,
_10k_btc_to_100k_btc: full(Filter::Amount(AmountFilter::Range(
Sats::_10K_BTC..Sats::_100K_BTC,
)))?,
_100k_btc_or_more: full(Filter::Amount(AmountFilter::GreaterOrEqual(
Sats::_100K_BTC,
)))?,
};
let lt_amount = ByLowerThanAmount {
_10sats: none(Filter::Amount(AmountFilter::LowerThan(Sats::_10)))?,
_100sats: none(Filter::Amount(AmountFilter::LowerThan(Sats::_100)))?,
_1k_sats: none(Filter::Amount(AmountFilter::LowerThan(Sats::_1K)))?,
_10k_sats: none(Filter::Amount(AmountFilter::LowerThan(Sats::_10K)))?,
_100k_sats: none(Filter::Amount(AmountFilter::LowerThan(Sats::_100K)))?,
_1m_sats: none(Filter::Amount(AmountFilter::LowerThan(Sats::_1M)))?,
_10m_sats: none(Filter::Amount(AmountFilter::LowerThan(Sats::_10M)))?,
_1btc: none(Filter::Amount(AmountFilter::LowerThan(Sats::_1BTC)))?,
_10btc: none(Filter::Amount(AmountFilter::LowerThan(Sats::_10BTC)))?,
_100btc: none(Filter::Amount(AmountFilter::LowerThan(Sats::_100BTC)))?,
_1k_btc: none(Filter::Amount(AmountFilter::LowerThan(Sats::_1K_BTC)))?,
_10k_btc: none(Filter::Amount(AmountFilter::LowerThan(Sats::_10K_BTC)))?,
_100k_btc: none(Filter::Amount(AmountFilter::LowerThan(Sats::_100K_BTC)))?,
};
let ge_amount = ByGreatEqualAmount {
_1sat: none(Filter::Amount(AmountFilter::GreaterOrEqual(Sats::_1)))?,
_10sats: none(Filter::Amount(AmountFilter::GreaterOrEqual(Sats::_10)))?,
_100sats: none(Filter::Amount(AmountFilter::GreaterOrEqual(Sats::_100)))?,
_1k_sats: none(Filter::Amount(AmountFilter::GreaterOrEqual(Sats::_1K)))?,
_10k_sats: none(Filter::Amount(AmountFilter::GreaterOrEqual(Sats::_10K)))?,
_100k_sats: none(Filter::Amount(AmountFilter::GreaterOrEqual(Sats::_100K)))?,
_1m_sats: none(Filter::Amount(AmountFilter::GreaterOrEqual(Sats::_1M)))?,
_10m_sats: none(Filter::Amount(AmountFilter::GreaterOrEqual(Sats::_10M)))?,
_1btc: none(Filter::Amount(AmountFilter::GreaterOrEqual(Sats::_1BTC)))?,
_10btc: none(Filter::Amount(AmountFilter::GreaterOrEqual(Sats::_10BTC)))?,
_100btc: none(Filter::Amount(AmountFilter::GreaterOrEqual(Sats::_100BTC)))?,
_1k_btc: none(Filter::Amount(AmountFilter::GreaterOrEqual(Sats::_1K_BTC)))?,
_10k_btc: none(Filter::Amount(AmountFilter::GreaterOrEqual(Sats::_10K_BTC)))?,
};
let epoch = ByEpoch::try_new(&full)?;
let year = ByYear::try_new(&full)?;
let type_ = BySpendableType::try_new(&full)?;
let max_age = ByMaxAge::try_new(&none)?;
let min_age = ByMinAge::try_new(&none)?;
let age_range = ByAgeRange::try_new(&full)?;
let amount_range = ByAmountRange::try_new(&full)?;
let lt_amount = ByLowerThanAmount::try_new(&none)?;
let ge_amount = ByGreatEqualAmount::try_new(&none)?;
Ok(Self(UTXOGroups {
all,

View File

@@ -8,6 +8,7 @@ use crate::{indexes, price};
pub struct ImportConfig<'a> {
pub db: &'a Database,
pub filter: Filter,
pub full_name: &'a str,
pub context: CohortContext,
pub version: Version,
pub indexes: &'a indexes::Vecs,
@@ -37,11 +38,10 @@ impl<'a> ImportConfig<'a> {
/// Get full metric name with filter prefix.
pub fn name(&self, suffix: &str) -> String {
let prefix = self.filter.to_full_name(self.context);
if prefix.is_empty() {
if self.full_name.is_empty() {
suffix.to_string()
} else {
format!("{prefix}_{suffix}")
format!("{}_{suffix}", self.full_name)
}
}
}