fedimint_wallet_client/
client_db.rs

1use core::fmt;
2use std::ops;
3use std::str::FromStr;
4use std::time::SystemTime;
5
6use fedimint_client_module::module::init::recovery::RecoveryFromHistoryCommon;
7use fedimint_core::core::OperationId;
8use fedimint_core::encoding::{Decodable, Encodable};
9use fedimint_core::{TransactionId, impl_db_lookup, impl_db_record};
10use serde::{Deserialize, Serialize};
11use strum_macros::EnumIter;
12
13use crate::backup::WalletRecoveryState;
14
15#[derive(Clone, EnumIter, Debug)]
16pub enum DbKeyPrefix {
17    NextPegInTweakIndex = 0x2c,
18    PegInTweakIndex = 0x2d,
19    ClaimedPegIn = 0x2e,
20    RecoveryFinalized = 0x2f,
21    RecoveryState = 0x30,
22    SupportsSafeDeposit = 0x31,
23    /// Prefixes between 0xb0..=0xcf shall all be considered allocated for
24    /// historical and future external use
25    ExternalReservedStart = 0xb0,
26    /// Prefixes between 0xd0..=0xff shall all be considered allocated for
27    /// historical and future internal use
28    CoreInternalReservedStart = 0xd0,
29    /// Prefixes between 0xd0..=0xff shall all be considered allocated for
30    /// historical and future internal use
31    CoreInternalReservedEnd = 0xff,
32}
33
34impl std::fmt::Display for DbKeyPrefix {
35    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
36        write!(f, "{self:?}")
37    }
38}
39
40/// An index of a deposit address
41///
42/// Under the hood it's similar to `ChildId`, but in a wallet module
43/// it's used often enough to deserve own newtype.
44#[derive(
45    Copy,
46    Clone,
47    Debug,
48    Encodable,
49    Decodable,
50    Serialize,
51    Deserialize,
52    Default,
53    PartialEq,
54    Eq,
55    PartialOrd,
56    Ord,
57)]
58pub struct TweakIdx(pub u64);
59
60impl fmt::Display for TweakIdx {
61    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62        f.write_fmt(format_args!("TweakIdx({})", self.0))
63    }
64}
65
66impl FromStr for TweakIdx {
67    type Err = <u64 as FromStr>::Err;
68
69    fn from_str(s: &str) -> Result<Self, Self::Err> {
70        Ok(Self(FromStr::from_str(s)?))
71    }
72}
73
74impl TweakIdx {
75    #[must_use]
76    pub fn next(self) -> Self {
77        Self(self.0 + 1)
78    }
79
80    #[must_use]
81    pub fn prev(self) -> Option<Self> {
82        self.0.checked_sub(1).map(Self)
83    }
84
85    #[must_use]
86    pub fn advance(self, i: u64) -> Self {
87        Self(self.0 + i)
88    }
89
90    pub fn saturating_sub(&self, rhs: TweakIdx) -> u64 {
91        self.0.saturating_sub(rhs.0)
92    }
93}
94
95impl ops::Sub for TweakIdx {
96    type Output = u64;
97
98    fn sub(self, rhs: Self) -> Self::Output {
99        self.0 - rhs.0
100    }
101}
102
103/// A counter tracking next index to use to derive a peg-in address
104#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
105pub struct NextPegInTweakIndexKey;
106
107impl_db_record!(
108    key = NextPegInTweakIndexKey,
109    value = TweakIdx,
110    db_prefix = DbKeyPrefix::NextPegInTweakIndex,
111);
112
113/// Peg in index that was already allocated and is being tracked for deposits to
114/// claim
115#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
116pub struct PegInTweakIndexKey(pub TweakIdx);
117
118#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
119pub struct PegInTweakIndexPrefix;
120
121#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
122pub struct PegInTweakIndexData {
123    pub operation_id: OperationId,
124    pub creation_time: SystemTime,
125    pub last_check_time: Option<SystemTime>,
126    pub next_check_time: Option<SystemTime>,
127    pub claimed: Vec<bitcoin::OutPoint>,
128}
129
130impl_db_record!(
131    key = PegInTweakIndexKey,
132    value = PegInTweakIndexData,
133    db_prefix = DbKeyPrefix::PegInTweakIndex,
134);
135
136impl_db_lookup!(
137    key = PegInTweakIndexKey,
138    query_prefix = PegInTweakIndexPrefix
139);
140
141#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
142pub struct ClaimedPegInKey {
143    pub peg_in_index: TweakIdx,
144    pub btc_out_point: bitcoin::OutPoint,
145}
146
147#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
148pub struct ClaimedPegInPrefix;
149
150#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
151pub struct ClaimedPegInData {
152    pub claim_txid: TransactionId,
153    pub change: Vec<fedimint_core::OutPoint>,
154}
155
156impl_db_record!(
157    key = ClaimedPegInKey,
158    value = ClaimedPegInData,
159    db_prefix = DbKeyPrefix::ClaimedPegIn,
160    notify_on_modify = true,
161);
162impl_db_lookup!(key = ClaimedPegInKey, query_prefix = ClaimedPegInPrefix);
163
164#[derive(Debug, Clone, Encodable, Decodable, Serialize)]
165pub struct RecoveryFinalizedKey;
166
167#[derive(Debug, Clone, Encodable, Decodable)]
168pub struct RecoveryFinalizedKeyPrefix;
169
170impl_db_record!(
171    key = RecoveryFinalizedKey,
172    value = bool,
173    db_prefix = DbKeyPrefix::RecoveryFinalized,
174);
175
176#[derive(Debug, Clone, Encodable, Decodable, Serialize)]
177pub struct RecoveryStateKey;
178
179#[derive(Debug, Clone, Encodable, Decodable)]
180pub struct RestoreStateKeyPrefix;
181
182impl_db_record!(
183    key = RecoveryStateKey,
184    value = (WalletRecoveryState, RecoveryFromHistoryCommon),
185    db_prefix = DbKeyPrefix::RecoveryState,
186);
187
188#[derive(Clone, Debug, Encodable, Decodable, Serialize)]
189pub struct SupportsSafeDepositKey;
190
191#[derive(Clone, Debug, Encodable, Decodable)]
192pub struct SupportsSafeDepositPrefix;
193
194impl_db_record!(
195    key = SupportsSafeDepositKey,
196    value = (),
197    db_prefix = DbKeyPrefix::SupportsSafeDeposit,
198);
199
200impl_db_lookup!(
201    key = SupportsSafeDepositKey,
202    query_prefix = SupportsSafeDepositPrefix
203);