use std::path::Path;
use brk_error::Result;
use brk_types::{Age, Cents, FundedAddrData, Sats, SupplyState};
use vecdb::unlikely;
use super::super::cost_basis::{CostBasisRaw, RealizedOps};
use super::base::CohortState;
const COST_BASIS_PRICE_DIGITS: i32 = 4;
pub struct AddrCohortState<R: RealizedOps> {
pub addr_count: u64,
pub inner: CohortState<R, CostBasisRaw>,
}
impl<R: RealizedOps> AddrCohortState<R> {
pub(crate) fn new(path: &Path, name: &str) -> Self {
Self {
addr_count: 0,
inner: CohortState::new(path, name).with_price_rounding(COST_BASIS_PRICE_DIGITS),
}
}
pub(crate) fn reset(&mut self) {
self.addr_count = 0;
self.inner.supply = SupplyState::default();
self.inner.sent = Sats::ZERO;
self.inner.spent_utxo_count = 0;
self.inner.satdays_destroyed = Sats::ZERO;
self.inner.realized = R::default();
}
pub(crate) fn send(
&mut self,
addr_data: &mut FundedAddrData,
value: Sats,
current_price: Cents,
prev_price: Cents,
ath: Cents,
age: Age,
) -> Result<()> {
let prev = addr_data.cost_basis_snapshot();
addr_data.send(value, prev_price)?;
let current = addr_data.cost_basis_snapshot();
self.inner.send_addr(
&SupplyState {
utxo_count: 1,
value,
},
current_price,
prev_price,
ath,
age,
¤t,
&prev,
);
Ok(())
}
pub(crate) fn receive_outputs(
&mut self,
addr_data: &mut FundedAddrData,
value: Sats,
price: Cents,
output_count: u32,
) {
let prev = addr_data.cost_basis_snapshot();
addr_data.receive_outputs(value, price, output_count);
let current = addr_data.cost_basis_snapshot();
self.inner.receive_addr(
&SupplyState {
utxo_count: output_count as u64,
value,
},
price,
¤t,
&prev,
);
}
pub(crate) fn add(&mut self, addr_data: &FundedAddrData) {
self.addr_count += 1;
self.inner
.increment_snapshot(&addr_data.cost_basis_snapshot());
}
pub(crate) fn subtract(&mut self, addr_data: &FundedAddrData) {
let snapshot = addr_data.cost_basis_snapshot();
if unlikely(self.inner.supply.utxo_count < snapshot.supply_state.utxo_count) {
panic!(
"AddrCohortState::subtract underflow!\n\
Cohort state: addr_count={}, supply={}\n\
Addr being subtracted: {}\n\
Addr supply: {}\n\
Realized price: {}\n\
This means the addr is not properly tracked in this cohort.",
self.addr_count,
self.inner.supply,
addr_data,
snapshot.supply_state,
snapshot.realized_price
);
}
if unlikely(self.inner.supply.value < snapshot.supply_state.value) {
panic!(
"AddrCohortState::subtract value underflow!\n\
Cohort state: addr_count={}, supply={}\n\
Addr being subtracted: {}\n\
Addr supply: {}\n\
Realized price: {}\n\
This means the addr is not properly tracked in this cohort.",
self.addr_count,
self.inner.supply,
addr_data,
snapshot.supply_state,
snapshot.realized_price
);
}
self.addr_count = self.addr_count.checked_sub(1).unwrap_or_else(|| {
panic!(
"AddrCohortState::subtract addr_count underflow! addr_count=0\n\
Addr being subtracted: {}\n\
Realized price: {}",
addr_data, snapshot.realized_price
)
});
self.inner.decrement_snapshot(&snapshot);
}
}