use std::fmt;
use std::ops::Deref;
use ark::Vtxo;
use ark::vtxo::{Bare, Full, VtxoRef};
use crate::movement::MovementId;
const SPENDABLE: &'static str = "Spendable";
const LOCKED: &'static str = "Locked";
const SPENT: &'static str = "Spent";
#[derive(Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum VtxoStateKind {
Spendable,
Locked,
Spent,
}
impl VtxoStateKind {
pub fn as_str(&self) -> &str {
match self {
VtxoStateKind::Spendable => SPENDABLE,
VtxoStateKind::Locked => LOCKED,
VtxoStateKind::Spent => SPENT,
}
}
pub fn as_byte(&self) -> u8 {
match self {
VtxoStateKind::Spendable => 0,
VtxoStateKind::Locked { .. } => 1,
VtxoStateKind::Spent => 2,
}
}
pub const ALL: &[VtxoStateKind] = &[
VtxoStateKind::Spendable,
VtxoStateKind::Locked,
VtxoStateKind::Spent,
];
pub const UNSPENT_STATES: &[VtxoStateKind] = &[
VtxoStateKind::Spendable,
VtxoStateKind::Locked,
];
}
impl fmt::Display for VtxoStateKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
impl fmt::Debug for VtxoStateKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "kebab-case")]
pub enum VtxoState {
Spendable,
Locked {
movement_id: Option<MovementId>,
},
Spent,
}
impl VtxoState {
pub fn kind(&self) -> VtxoStateKind {
match self {
VtxoState::Spendable => VtxoStateKind::Spendable,
VtxoState::Locked { .. } => VtxoStateKind::Locked,
VtxoState::Spent => VtxoStateKind::Spent,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct WalletVtxo {
#[serde(with = "ark::encode::serde")]
pub vtxo: Vtxo<Full>,
pub state: VtxoState,
}
impl VtxoRef for WalletVtxo {
fn vtxo_id(&self) -> ark::VtxoId { self.vtxo.id() }
fn as_bare_vtxo(&self) -> Option<std::borrow::Cow<'_, Vtxo<Bare>>> {
Some(std::borrow::Cow::Owned(self.vtxo.to_bare()))
}
fn as_full_vtxo(&self) -> Option<&Vtxo<Full>> { Some(&self.vtxo) }
fn into_full_vtxo(self) -> Option<Vtxo<Full>> { Some(self.vtxo) }
}
impl<'a> VtxoRef for &'a WalletVtxo {
fn vtxo_id(&self) -> ark::VtxoId { self.vtxo.id() }
fn as_bare_vtxo(&self) -> Option<std::borrow::Cow<'_, Vtxo<Bare>>> {
Some(std::borrow::Cow::Owned(self.vtxo.to_bare()))
}
fn as_full_vtxo(&self) -> Option<&Vtxo<Full>> { Some(&self.vtxo) }
fn into_full_vtxo(self) -> Option<Vtxo<Full>> { Some(self.vtxo.clone()) }
}
impl AsRef<Vtxo<Full>> for WalletVtxo {
fn as_ref(&self) -> &Vtxo<Full> {
&self.vtxo
}
}
impl Deref for WalletVtxo {
type Target = Vtxo<Full>;
fn deref(&self) -> &Vtxo<Full> {
&self.vtxo
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn convert_serialize() {
let states = [
VtxoStateKind::Spendable,
VtxoStateKind::Spent,
VtxoStateKind::Locked,
];
assert_eq!(
serde_json::to_string(&states).unwrap(),
serde_json::to_string(&[SPENDABLE, SPENT, LOCKED]).unwrap(),
);
match VtxoState::Spent {
VtxoState::Spendable => {},
VtxoState::Spent => {},
VtxoState::Locked { .. } => {},
}
}
}