1use crate::server::VirtualTxOutPoint;
2use crate::ExplorerUtxo;
3use crate::Vtxo;
4use bitcoin::Amount;
5use bitcoin::ScriptBuf;
6use std::collections::HashMap;
7use std::time::Duration;
8
9#[derive(Clone, Debug)]
10pub struct VtxoList {
11 pre_confirmed: Vec<VirtualTxOutPoint>,
13 confirmed: Vec<VirtualTxOutPoint>,
14 recoverable: Vec<VirtualTxOutPoint>,
15
16 spent: Vec<VirtualTxOutPoint>,
18}
19
20impl VtxoList {
21 pub fn new(
22 dust: Amount,
24 virtual_tx_outpoints: Vec<VirtualTxOutPoint>,
25 ) -> Self {
26 let mut recoverable = Vec::new();
27 let mut spent = Vec::new();
28 let mut pre_confirmed = Vec::new();
29 let mut confirmed = Vec::new();
30 for virtual_tx_outpoint in virtual_tx_outpoints {
31 if virtual_tx_outpoint.is_recoverable(dust) {
32 recoverable.push(virtual_tx_outpoint);
33 } else if virtual_tx_outpoint.is_unrolled
34 || virtual_tx_outpoint.is_spent
35 || virtual_tx_outpoint.is_swept
36 {
37 spent.push(virtual_tx_outpoint);
38 } else if virtual_tx_outpoint.is_preconfirmed {
39 pre_confirmed.push(virtual_tx_outpoint);
40 } else {
41 confirmed.push(virtual_tx_outpoint);
42 }
43 }
44
45 VtxoList {
46 pre_confirmed,
47 confirmed,
48 recoverable,
49 spent,
50 }
51 }
52
53 pub fn all(&self) -> impl Iterator<Item = &VirtualTxOutPoint> {
54 self.all_unspent().chain(self.spent())
55 }
56
57 pub fn all_unspent(&self) -> impl Iterator<Item = &VirtualTxOutPoint> {
58 self.pre_confirmed
59 .iter()
60 .chain(self.confirmed.iter())
61 .chain(self.recoverable.iter())
62 }
63
64 pub fn could_exit_unilaterally(&self) -> impl Iterator<Item = &VirtualTxOutPoint> {
69 self.pre_confirmed.iter().chain(self.confirmed.iter())
70 }
71
72 pub fn spendable_offchain(&self) -> impl Iterator<Item = &VirtualTxOutPoint> {
74 self.pre_confirmed.iter().chain(self.confirmed.iter())
75 }
76
77 pub fn pre_confirmed(&self) -> impl Iterator<Item = &VirtualTxOutPoint> {
78 self.pre_confirmed.iter()
79 }
80
81 pub fn confirmed(&self) -> impl Iterator<Item = &VirtualTxOutPoint> {
82 self.confirmed.iter()
83 }
84
85 pub fn recoverable(&self) -> impl Iterator<Item = &VirtualTxOutPoint> {
93 self.recoverable.iter()
94 }
95
96 pub fn exit_ready(
98 &self,
99 now: Duration,
100 explorer_utxos: Vec<ExplorerUtxo>,
102 vtxos: HashMap<ScriptBuf, Vtxo>,
104 ) -> impl Iterator<Item = &VirtualTxOutPoint> {
105 self.all_unspent().filter(move |v| {
106 match explorer_utxos
107 .iter()
108 .find(|explorer_utxo| explorer_utxo.outpoint == v.outpoint)
109 {
110 Some(ExplorerUtxo {
112 confirmation_blocktime: Some(confirmation_blocktime),
113 confirmations,
114 ..
115 }) => {
116 if let Some(vtxo) = vtxos.get(&v.script) {
118 vtxo.can_be_claimed_unilaterally_by_owner(
119 now,
120 Duration::from_secs(*confirmation_blocktime),
121 *confirmations,
122 )
123 } else {
124 false
125 }
126 }
127 _ => false,
128 }
129 })
130 }
131
132 pub fn spent(&self) -> impl Iterator<Item = &VirtualTxOutPoint> {
133 self.spent.iter()
134 }
135}