1use std::collections::BTreeMap;
2
3use bitcoin::secp256k1::SecretKey;
4use bitcoin::Network;
5use fedimint_core::core::ModuleKind;
6use fedimint_core::encoding::{Decodable, Encodable};
7use fedimint_core::envs::BitcoinRpcConfig;
8use fedimint_core::module::serde_json;
9use fedimint_core::util::SafeUrl;
10use fedimint_core::{plugin_types_trait_impl_config, Feerate, PeerId};
11use miniscript::descriptor::{Wpkh, Wsh};
12use serde::{Deserialize, Serialize};
13
14use crate::envs::FM_PORT_ESPLORA_ENV;
15use crate::keys::CompressedPublicKey;
16use crate::{PegInDescriptor, WalletCommonInit};
17
18const DEFAULT_DEPOSIT_FEE_SATS: u64 = 1000;
21
22#[derive(Debug, Clone, Serialize, Deserialize)]
23pub struct WalletGenParams {
24 pub local: WalletGenParamsLocal,
25 pub consensus: WalletGenParamsConsensus,
26}
27
28impl WalletGenParams {
29 pub fn regtest(bitcoin_rpc: BitcoinRpcConfig) -> WalletGenParams {
30 WalletGenParams {
31 local: WalletGenParamsLocal { bitcoin_rpc },
32 consensus: WalletGenParamsConsensus {
33 network: Network::Regtest,
34 finality_delay: 10,
35 client_default_bitcoin_rpc: BitcoinRpcConfig {
36 kind: "esplora".to_string(),
37 url: SafeUrl::parse(&format!(
38 "http://127.0.0.1:{}/",
39 std::env::var(FM_PORT_ESPLORA_ENV).unwrap_or(String::from("50002"))
40 ))
41 .expect("Failed to parse default esplora server"),
42 },
43 fee_consensus: FeeConsensus::default(),
44 },
45 }
46 }
47}
48
49#[derive(Debug, Clone, Serialize, Deserialize)]
50pub struct WalletGenParamsLocal {
51 pub bitcoin_rpc: BitcoinRpcConfig,
52}
53
54#[derive(Debug, Clone, Serialize, Deserialize)]
55pub struct WalletGenParamsConsensus {
56 pub network: Network,
57 pub finality_delay: u32,
58 pub client_default_bitcoin_rpc: BitcoinRpcConfig,
60 pub fee_consensus: FeeConsensus,
65}
66
67#[derive(Clone, Debug, Serialize, Deserialize)]
68pub struct WalletConfig {
69 pub local: WalletConfigLocal,
70 pub private: WalletConfigPrivate,
71 pub consensus: WalletConfigConsensus,
72}
73
74#[derive(Clone, Debug, Serialize, Deserialize, Decodable, Encodable)]
75pub struct WalletConfigLocal {
76 pub bitcoin_rpc: BitcoinRpcConfig,
78}
79
80#[derive(Clone, Debug, Serialize, Deserialize)]
81pub struct WalletConfigPrivate {
82 pub peg_in_key: SecretKey,
84}
85
86#[derive(Clone, Debug, Serialize, Deserialize, Encodable, Decodable)]
87pub struct WalletConfigConsensus {
88 pub network: Network,
90 pub peg_in_descriptor: PegInDescriptor,
92 pub peer_peg_in_keys: BTreeMap<PeerId, CompressedPublicKey>,
94 pub finality_delay: u32,
97 pub default_fee: Feerate,
100 pub fee_consensus: FeeConsensus,
102 pub client_default_bitcoin_rpc: BitcoinRpcConfig,
110}
111
112#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize, Deserialize, Encodable, Decodable)]
113pub struct WalletClientConfig {
114 pub peg_in_descriptor: PegInDescriptor,
116 pub network: Network,
118 pub finality_delay: u32,
120 pub fee_consensus: FeeConsensus,
121 pub default_bitcoin_rpc: BitcoinRpcConfig,
126}
127
128impl std::fmt::Display for WalletClientConfig {
129 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
130 write!(
131 f,
132 "WalletClientConfig {}",
133 serde_json::to_string(self).map_err(|_e| std::fmt::Error)?
134 )
135 }
136}
137
138#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize, Encodable, Decodable)]
139pub struct FeeConsensus {
140 pub peg_in_abs: fedimint_core::Amount,
141 pub peg_out_abs: fedimint_core::Amount,
142}
143
144impl Default for FeeConsensus {
145 fn default() -> Self {
146 Self {
147 peg_in_abs: fedimint_core::Amount::from_sats(DEFAULT_DEPOSIT_FEE_SATS),
148 peg_out_abs: fedimint_core::Amount::ZERO,
149 }
150 }
151}
152
153impl WalletConfig {
154 #[allow(clippy::too_many_arguments)]
155 pub fn new(
156 pubkeys: BTreeMap<PeerId, CompressedPublicKey>,
157 sk: SecretKey,
158 threshold: usize,
159 network: Network,
160 finality_delay: u32,
161 bitcoin_rpc: BitcoinRpcConfig,
162 client_default_bitcoin_rpc: BitcoinRpcConfig,
163 fee_consensus: FeeConsensus,
164 ) -> Self {
165 let peg_in_descriptor = if pubkeys.len() == 1 {
166 PegInDescriptor::Wpkh(
167 Wpkh::new(
168 *pubkeys
169 .values()
170 .next()
171 .expect("there is exactly one pub key"),
172 )
173 .expect("Our key type is always compressed"),
174 )
175 } else {
176 PegInDescriptor::Wsh(
177 Wsh::new_sortedmulti(threshold, pubkeys.values().copied().collect()).unwrap(),
178 )
179 };
180
181 Self {
182 local: WalletConfigLocal { bitcoin_rpc },
183 private: WalletConfigPrivate { peg_in_key: sk },
184 consensus: WalletConfigConsensus {
185 network,
186 peg_in_descriptor,
187 peer_peg_in_keys: pubkeys,
188 finality_delay,
189 default_fee: Feerate { sats_per_kvb: 1000 },
190 fee_consensus,
191 client_default_bitcoin_rpc,
192 },
193 }
194 }
195}
196
197plugin_types_trait_impl_config!(
198 WalletCommonInit,
199 WalletGenParams,
200 WalletGenParamsLocal,
201 WalletGenParamsConsensus,
202 WalletConfig,
203 WalletConfigLocal,
204 WalletConfigPrivate,
205 WalletConfigConsensus,
206 WalletClientConfig
207);