use serde::{Deserialize, Serialize};
use crate::mint_url::MintUrl;
use crate::nuts::CurrencyUnit;
use crate::wallet::OperationKind;
use crate::Amount;
mod issue;
mod melt;
mod receive;
mod send;
mod swap;
pub use issue::{IssueSagaState, MintOperationData};
pub use melt::{MeltOperationData, MeltSagaState};
pub use receive::{ReceiveOperationData, ReceiveSagaState};
pub use send::{SendOperationData, SendSagaState};
pub use swap::{SwapOperationData, SwapSagaState};
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "type", content = "state", rename_all = "snake_case")]
pub enum WalletSagaState {
Send(SendSagaState),
Receive(ReceiveSagaState),
Swap(SwapSagaState),
Issue(IssueSagaState),
Melt(MeltSagaState),
}
impl WalletSagaState {
pub fn kind(&self) -> OperationKind {
match self {
WalletSagaState::Send(_) => OperationKind::Send,
WalletSagaState::Receive(_) => OperationKind::Receive,
WalletSagaState::Swap(_) => OperationKind::Swap,
WalletSagaState::Issue(_) => OperationKind::Mint,
WalletSagaState::Melt(_) => OperationKind::Melt,
}
}
pub fn state_str(&self) -> &'static str {
match self {
WalletSagaState::Send(s) => match s {
SendSagaState::ProofsReserved => "proofs_reserved",
SendSagaState::TokenCreated => "token_created",
SendSagaState::RollingBack => "rolling_back",
},
WalletSagaState::Receive(s) => match s {
ReceiveSagaState::ProofsPending => "proofs_pending",
ReceiveSagaState::SwapRequested => "swap_requested",
},
WalletSagaState::Swap(s) => match s {
SwapSagaState::ProofsReserved => "proofs_reserved",
SwapSagaState::SwapRequested => "swap_requested",
},
WalletSagaState::Issue(s) => match s {
IssueSagaState::SecretsPrepared => "secrets_prepared",
IssueSagaState::MintRequested => "mint_requested",
},
WalletSagaState::Melt(s) => match s {
MeltSagaState::ProofsReserved => "proofs_reserved",
MeltSagaState::MeltRequested => "melt_requested",
MeltSagaState::PaymentPending => "payment_pending",
},
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "kind", content = "data", rename_all = "snake_case")]
pub enum OperationData {
Send(SendOperationData),
Receive(ReceiveOperationData),
Swap(SwapOperationData),
Mint(MintOperationData),
Melt(MeltOperationData),
}
impl OperationData {
pub fn kind(&self) -> OperationKind {
match self {
OperationData::Send(_) => OperationKind::Send,
OperationData::Receive(_) => OperationKind::Receive,
OperationData::Swap(_) => OperationKind::Swap,
OperationData::Mint(_) => OperationKind::Mint,
OperationData::Melt(_) => OperationKind::Melt,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct WalletSaga {
pub id: uuid::Uuid,
pub kind: OperationKind,
pub state: WalletSagaState,
pub amount: Amount,
pub mint_url: MintUrl,
pub unit: CurrencyUnit,
pub quote_id: Option<String>,
pub created_at: u64,
pub updated_at: u64,
pub data: OperationData,
pub version: u32,
}
impl WalletSaga {
pub fn new(
id: uuid::Uuid,
state: WalletSagaState,
amount: Amount,
mint_url: MintUrl,
unit: CurrencyUnit,
data: OperationData,
) -> Self {
let now = web_time::SystemTime::now()
.duration_since(web_time::UNIX_EPOCH)
.unwrap_or_default()
.as_secs();
let quote_id = match &data {
OperationData::Mint(d) => Some(d.primary_quote_id().to_string()),
OperationData::Melt(d) => Some(d.quote_id.clone()),
_ => None,
};
Self {
id,
kind: state.kind(),
state,
amount,
mint_url,
unit,
quote_id,
created_at: now,
updated_at: now,
data,
version: 0,
}
}
pub fn update_state(&mut self, state: WalletSagaState) {
self.state = state;
self.kind = state.kind();
self.updated_at = web_time::SystemTime::now()
.duration_since(web_time::UNIX_EPOCH)
.unwrap_or_default()
.as_secs();
self.version += 1;
}
}