[bdk_chain_redesign] Add balance methods to IndexedTxGraph
This commit is contained in:
parent
d0a2aa83be
commit
db7883d813
@ -14,6 +14,15 @@ pub enum ObservedIn<A> {
|
|||||||
Mempool(u64),
|
Mempool(u64),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<A: Clone> ObservedIn<&A> {
|
||||||
|
pub fn into_owned(self) -> ObservedIn<A> {
|
||||||
|
match self {
|
||||||
|
ObservedIn::Block(a) => ObservedIn::Block(a.clone()),
|
||||||
|
ObservedIn::Mempool(last_seen) => ObservedIn::Mempool(last_seen),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ChainPosition for ObservedIn<BlockId> {
|
impl ChainPosition for ObservedIn<BlockId> {
|
||||||
fn height(&self) -> TxHeight {
|
fn height(&self) -> TxHeight {
|
||||||
match self {
|
match self {
|
||||||
@ -259,4 +268,16 @@ impl<I: ChainPosition> FullTxOut<I> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<A: Clone> FullTxOut<ObservedIn<&A>> {
|
||||||
|
pub fn into_owned(self) -> FullTxOut<ObservedIn<A>> {
|
||||||
|
FullTxOut {
|
||||||
|
outpoint: self.outpoint,
|
||||||
|
txout: self.txout,
|
||||||
|
chain_position: self.chain_position.into_owned(),
|
||||||
|
spent_by: self.spent_by.map(|(o, txid)| (o.into_owned(), txid)),
|
||||||
|
is_on_coinbase: self.is_on_coinbase,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: make test
|
// TODO: make test
|
||||||
|
@ -4,6 +4,7 @@ use alloc::collections::BTreeSet;
|
|||||||
use bitcoin::{OutPoint, Transaction, TxOut};
|
use bitcoin::{OutPoint, Transaction, TxOut};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
keychain::Balance,
|
||||||
sparse_chain::ChainPosition,
|
sparse_chain::ChainPosition,
|
||||||
tx_graph::{Additions, TxGraph, TxInGraph},
|
tx_graph::{Additions, TxGraph, TxInGraph},
|
||||||
BlockAnchor, ChainOracle, FullTxOut, ObservedIn, TxIndex, TxIndexAdditions,
|
BlockAnchor, ChainOracle, FullTxOut, ObservedIn, TxIndex, TxIndexAdditions,
|
||||||
@ -260,4 +261,86 @@ impl<A: BlockAnchor, I: TxIndex> IndexedTxGraph<A, I> {
|
|||||||
self.try_list_chain_utxos(chain)
|
self.try_list_chain_utxos(chain)
|
||||||
.map(|r| r.expect("error is infallible"))
|
.map(|r| r.expect("error is infallible"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn try_balance<C, F>(
|
||||||
|
&self,
|
||||||
|
chain: C,
|
||||||
|
tip: u32,
|
||||||
|
mut should_trust: F,
|
||||||
|
) -> Result<Balance, C::Error>
|
||||||
|
where
|
||||||
|
C: ChainOracle,
|
||||||
|
ObservedIn<A>: ChainPosition + Clone,
|
||||||
|
F: FnMut(&I::SpkIndex) -> bool,
|
||||||
|
{
|
||||||
|
let mut immature = 0;
|
||||||
|
let mut trusted_pending = 0;
|
||||||
|
let mut untrusted_pending = 0;
|
||||||
|
let mut confirmed = 0;
|
||||||
|
|
||||||
|
for res in self.try_list_chain_txouts(&chain) {
|
||||||
|
let TxOutInChain { spk_index, txout } = res?;
|
||||||
|
let txout = txout.into_owned();
|
||||||
|
|
||||||
|
match &txout.chain_position {
|
||||||
|
ObservedIn::Block(_) => {
|
||||||
|
if txout.is_on_coinbase {
|
||||||
|
if txout.is_mature(tip) {
|
||||||
|
confirmed += txout.txout.value;
|
||||||
|
} else {
|
||||||
|
immature += txout.txout.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ObservedIn::Mempool(_) => {
|
||||||
|
if should_trust(spk_index) {
|
||||||
|
trusted_pending += txout.txout.value;
|
||||||
|
} else {
|
||||||
|
untrusted_pending += txout.txout.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Balance {
|
||||||
|
immature,
|
||||||
|
trusted_pending,
|
||||||
|
untrusted_pending,
|
||||||
|
confirmed,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn balance<C, F>(&self, chain: C, tip: u32, should_trust: F) -> Balance
|
||||||
|
where
|
||||||
|
C: ChainOracle<Error = Infallible>,
|
||||||
|
ObservedIn<A>: ChainPosition + Clone,
|
||||||
|
F: FnMut(&I::SpkIndex) -> bool,
|
||||||
|
{
|
||||||
|
self.try_balance(chain, tip, should_trust)
|
||||||
|
.expect("error is infallible")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_balance_at<C>(&self, chain: C, height: u32) -> Result<u64, C::Error>
|
||||||
|
where
|
||||||
|
C: ChainOracle,
|
||||||
|
ObservedIn<A>: ChainPosition + Clone,
|
||||||
|
{
|
||||||
|
let mut sum = 0;
|
||||||
|
for res in self.try_list_chain_txouts(chain) {
|
||||||
|
let txo = res?.txout.into_owned();
|
||||||
|
if txo.is_spendable_at(height) {
|
||||||
|
sum += txo.txout.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(sum)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn balance_at<C>(&self, chain: C, height: u32) -> u64
|
||||||
|
where
|
||||||
|
C: ChainOracle<Error = Infallible>,
|
||||||
|
ObservedIn<A>: ChainPosition + Clone,
|
||||||
|
{
|
||||||
|
self.try_balance_at(chain, height)
|
||||||
|
.expect("error is infallible")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user