1use std::fmt;
18use std::ops::Deref;
19
20use ark::vtxo::VtxoRef;
21
22use ark::Vtxo;
23use crate::movement::MovementId;
24
25const SPENDABLE: &'static str = "Spendable";
26const LOCKED: &'static str = "Locked";
27const SPENT: &'static str = "Spent";
28
29#[derive(Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
33pub enum VtxoStateKind {
34 Spendable,
36 Locked,
38 Spent,
40}
41
42impl VtxoStateKind {
43 pub fn as_str(&self) -> &str {
45 match self {
46 VtxoStateKind::Spendable => SPENDABLE,
47 VtxoStateKind::Locked => LOCKED,
48 VtxoStateKind::Spent => SPENT,
49 }
50 }
51
52 pub const UNSPENT_STATES: &[VtxoStateKind] = &[
54 VtxoStateKind::Spendable,
55 VtxoStateKind::Locked,
56 ];
57}
58
59impl fmt::Display for VtxoStateKind {
60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61 f.write_str(self.as_str())
62 }
63}
64
65impl fmt::Debug for VtxoStateKind {
66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67 f.write_str(self.as_str())
68 }
69}
70
71#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
73#[serde(tag = "type", rename_all = "kebab-case")]
74pub enum VtxoState {
75 Spendable,
77 Spent,
79 Locked {
81 movement_id: Option<MovementId>,
83 },
84}
85
86impl VtxoState {
87 pub fn kind(&self) -> VtxoStateKind {
89 match self {
90 VtxoState::Locked { .. } => VtxoStateKind::Locked,
91 VtxoState::Spendable => VtxoStateKind::Spendable,
92 VtxoState::Spent => VtxoStateKind::Spent,
93 }
94 }
95}
96
97#[derive(Clone, Debug, PartialEq, Eq)]
99pub struct WalletVtxo {
100 pub vtxo: Vtxo,
102 pub state: VtxoState,
104}
105
106impl VtxoRef for WalletVtxo {
107 fn vtxo_id(&self) -> ark::VtxoId { self.vtxo.id() }
108 fn vtxo(&self) -> Option<&Vtxo> { Some(&self.vtxo) }
109}
110
111impl<'a> VtxoRef for &'a WalletVtxo {
112 fn vtxo_id(&self) -> ark::VtxoId { self.vtxo.id() }
113 fn vtxo(&self) -> Option<&Vtxo> { Some(&self.vtxo) }
114}
115
116impl AsRef<Vtxo> for WalletVtxo {
117 fn as_ref(&self) -> &Vtxo {
118 &self.vtxo
119 }
120}
121
122impl Deref for WalletVtxo {
123 type Target = Vtxo;
124
125 fn deref(&self) -> &Vtxo {
126 &self.vtxo
127 }
128}
129
130#[cfg(test)]
131mod test {
132 use super::*;
133
134 #[test]
135 fn convert_serialize() {
136 let states = [
137 VtxoStateKind::Spendable,
138 VtxoStateKind::Spent,
139 VtxoStateKind::Locked,
140 ];
141
142 assert_eq!(
143 serde_json::to_string(&states).unwrap(),
144 serde_json::to_string(&[SPENDABLE, SPENT, LOCKED]).unwrap(),
145 );
146
147 match VtxoState::Spent {
150 VtxoState::Spendable => {},
151 VtxoState::Spent => {},
152 VtxoState::Locked { .. } => {},
153 }
154 }
155}