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