1use cashu::{MeltQuoteState, State};
4
5#[derive(thiserror::Error, Debug)]
7pub enum Error {
8 #[error("Token already pending for another update")]
10 Pending,
11 #[error("Token already spent")]
13 AlreadySpent,
14 #[error("Invalid transition: From {0} to {1}")]
16 InvalidTransition(State, State),
17 #[error("Quote already paid")]
19 AlreadyPaid,
20 #[error("Invalid melt quote state transition: From {0} to {1}")]
22 InvalidMeltQuoteTransition(MeltQuoteState, MeltQuoteState),
23}
24
25#[inline]
26pub fn check_state_transition(current_state: State, new_state: State) -> Result<(), Error> {
28 let is_valid_transition = match current_state {
29 State::Unspent => matches!(new_state, State::Pending | State::Spent),
30 State::Pending => matches!(new_state, State::Unspent | State::Spent),
31 _ => false,
34 };
35
36 if !is_valid_transition {
37 Err(match current_state {
38 State::Pending => Error::Pending,
39 State::Spent => Error::AlreadySpent,
40 _ => Error::InvalidTransition(current_state, new_state),
41 })
42 } else {
43 Ok(())
44 }
45}
46
47#[inline]
48pub fn check_melt_quote_state_transition(
56 current_state: MeltQuoteState,
57 new_state: MeltQuoteState,
58) -> Result<(), Error> {
59 let is_valid_transition = match current_state {
60 MeltQuoteState::Unpaid => {
61 matches!(new_state, MeltQuoteState::Pending | MeltQuoteState::Failed)
62 }
63 MeltQuoteState::Pending => matches!(
64 new_state,
65 MeltQuoteState::Unpaid | MeltQuoteState::Paid | MeltQuoteState::Failed
66 ),
67 MeltQuoteState::Failed => {
68 matches!(new_state, MeltQuoteState::Pending | MeltQuoteState::Unpaid)
69 }
70 MeltQuoteState::Paid => false,
71 MeltQuoteState::Unknown => true,
72 };
73
74 if !is_valid_transition {
75 Err(match current_state {
76 MeltQuoteState::Pending => Error::Pending,
77 MeltQuoteState::Paid => Error::AlreadyPaid,
78 _ => Error::InvalidMeltQuoteTransition(current_state, new_state),
79 })
80 } else {
81 Ok(())
82 }
83}