1use std::collections::HashSet;
2use std::fmt;
3
4use bitcoin::{Amount, FeeRate, Txid};
5
6use bitcoin_ext::{BlockHeight, BlockRef};
7
8use crate::exit::models::ExitState;
9
10#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
11pub struct ExitTx {
12 pub txid: Txid,
13 pub status: ExitTxStatus,
14}
15
16#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
17#[serde(tag = "type", rename_all = "kebab-case")]
18pub enum ExitTxStatus {
19 #[default]
20 VerifyInputs,
21 AwaitingInputConfirmation {
22 txids: HashSet<Txid>
23 },
24 NeedsSignedPackage,
25 NeedsReplacementPackage {
26 min_fee_rate: FeeRate,
27 min_fee: Amount,
28 },
29 NeedsBroadcasting {
30 child_txid: Txid,
31 origin: ExitTxOrigin,
32 },
33 BroadcastWithCpfp {
34 child_txid: Txid,
35 origin: ExitTxOrigin,
36 },
37 Confirmed {
38 child_txid: Txid,
39 block: BlockRef,
40 origin: ExitTxOrigin,
41 },
42}
43
44impl ExitTxStatus {
45 pub fn child_txid(&self) -> Option<&Txid> {
46 match self {
47 ExitTxStatus::NeedsBroadcasting { child_txid, .. } => Some(child_txid),
48 ExitTxStatus::BroadcastWithCpfp { child_txid, .. } => Some(child_txid),
49 ExitTxStatus::Confirmed { child_txid, .. } => Some(child_txid),
50 _ => None,
51 }
52 }
53
54 pub fn confirmed_in(&self) -> Option<&BlockRef> {
55 match self {
56 ExitTxStatus::Confirmed { block, .. } => Some(block),
57 _ => None,
58 }
59 }
60}
61
62impl fmt::Display for ExitTxStatus {
63 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64 fmt::Debug::fmt(self, f)
65 }
66}
67
68#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
69#[serde(tag = "type", rename_all = "kebab-case")]
70pub enum ExitTxOrigin {
71 Wallet {
72 confirmed_in: Option<BlockRef>
73 },
74 Mempool {
75 #[serde(rename = "fee_rate_kwu")]
77 fee_rate: FeeRate,
78 total_fee: Amount,
80 },
81 Block {
82 confirmed_in: BlockRef
83 },
84}
85
86impl ExitTxOrigin {
87 pub fn confirmed_in(&self) -> Option<BlockRef> {
88 match self {
89 ExitTxOrigin::Wallet { confirmed_in } => *confirmed_in,
90 ExitTxOrigin::Mempool { .. } => None,
91 ExitTxOrigin::Block { confirmed_in } => Some(*confirmed_in),
92 }
93 }
94}
95
96impl fmt::Display for ExitTxOrigin {
97 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98 fmt::Debug::fmt(self, f)
99 }
100}
101
102#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
103pub struct ExitStartState {
104 pub tip_height: BlockHeight,
105}
106
107#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
108pub struct ExitProcessingState {
109 pub tip_height: BlockHeight,
110 pub transactions: Vec<ExitTx>,
111}
112
113#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
114pub struct ExitAwaitingDeltaState {
115 pub tip_height: BlockHeight,
116 pub confirmed_block: BlockRef,
117 pub claimable_height: BlockHeight,
118}
119
120#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
121pub struct ExitClaimableState {
122 pub tip_height: BlockHeight,
123 pub claimable_since: BlockRef,
124 pub last_scanned_block: Option<BlockRef>,
125}
126
127#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
128pub struct ExitClaimInProgressState {
129 pub tip_height: BlockHeight,
130 pub claimable_since: BlockRef,
131 pub claim_txid: Txid,
132}
133
134#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
135pub struct ExitClaimedState {
136 pub tip_height: BlockHeight,
137 pub txid: Txid,
138 pub block: BlockRef,
139}
140
141impl Into<ExitState> for ExitStartState {
142 fn into(self) -> ExitState {
143 ExitState::Start(self)
144 }
145}
146
147impl Into<ExitState> for ExitProcessingState {
148 fn into(self) -> ExitState {
149 ExitState::Processing(self)
150 }
151}
152
153impl Into<ExitState> for ExitAwaitingDeltaState {
154 fn into(self) -> ExitState {
155 ExitState::AwaitingDelta(self)
156 }
157}
158
159impl Into<ExitState> for ExitClaimableState {
160 fn into(self) -> ExitState {
161 ExitState::Claimable(self)
162 }
163}
164
165impl Into<ExitState> for ExitClaimInProgressState {
166 fn into(self) -> ExitState {
167 ExitState::ClaimInProgress(self)
168 }
169}
170
171impl Into<ExitState> for ExitClaimedState {
172 fn into(self) -> ExitState {
173 ExitState::Claimed(self)
174 }
175}