cardano_sdk/wallet/
utxo.rs1use crate::chain::{TransactionOutput, TxHash, TxIndex};
2use std::collections::{btree_map::Entry, BTreeMap};
3
4pub struct Utxos {
5 inner: BTreeMap<TxHash, ConsumableUtxo>,
6}
7
8pub enum UtxosError {
9 DuplicateTx(TxHash),
10 UsingInexistantTx(TxHash),
11 UsingInexistantTxIndex(TxHash, TxIndex),
12}
13
14impl Utxos {
15 pub fn new() -> Self {
16 Self {
17 inner: BTreeMap::new(),
18 }
19 }
20
21 pub fn add(
22 &mut self,
23 key: TxHash,
24 value: Vec<(TxIndex, TransactionOutput)>,
25 ) -> Result<(), UtxosError> {
26 if self
27 .inner
28 .insert(key.clone(), ConsumableUtxo::new(value))
29 .is_some()
30 {
31 return Err(UtxosError::DuplicateTx(key));
32 }
33 Ok(())
34 }
35
36 pub fn remove(&mut self, key: TxHash, value: TxIndex) -> Result<(), UtxosError> {
37 match self.inner.entry(key.clone()) {
38 Entry::Vacant(_) => {
39 return Err(UtxosError::UsingInexistantTx(key));
40 }
41 Entry::Occupied(mut ent) => match ent.get_mut().consume(value) {
42 Err(()) => return Err(UtxosError::UsingInexistantTxIndex(key, value)),
43 Ok(()) => {
44 if ent.get().is_empty() {
45 ent.remove_entry();
46 }
47 Ok(())
48 }
49 },
50 }
51 }
52
53 pub fn iter(&self) -> impl Iterator<Item = (&TxHash, &TxIndex, &TransactionOutput)> {
54 self.inner
55 .iter()
56 .map(|(k, v)| v.iter().map(move |(txidx, txo)| (k, txidx, txo)))
57 .flatten()
58 }
59}
60
61pub struct ConsumableUtxo(BTreeMap<TxIndex, TransactionOutput>);
62
63impl ConsumableUtxo {
64 pub fn new(outs: Vec<(TxIndex, TransactionOutput)>) -> Self {
65 let map = outs.into_iter().collect();
66 Self(map)
67 }
68
69 pub fn is_consumable(&self, index: TxIndex) -> bool {
70 self.0.contains_key(&index)
71 }
72
73 pub fn consume(&mut self, index: TxIndex) -> Result<(), ()> {
74 match self.0.remove(&index) {
75 None => Ok(()),
76 Some(_) => Err(()),
77 }
78 }
79
80 pub fn is_empty(&self) -> bool {
81 self.0.is_empty()
82 }
83
84 pub fn iter(&self) -> impl Iterator<Item = (&TxIndex, &TransactionOutput)> {
85 self.0.iter()
86 }
87}