1
2use bitcoin::{Amount, FeeRate, Txid};
3use bitcoin::consensus::encode::serialize_hex;
4use bitcoin::secp256k1::PublicKey;
5use serde::{Deserialize, Serialize};
6
7use ark::VtxoId;
8use ark::offboard::OffboardRequest;
9use ark::tree::signed::UnlockHash;
10use ark::vtxo::VtxoPolicyKind;
11
12#[cfg(feature = "utoipa")]
13use utoipa::ToSchema;
14
15use crate::cli::RoundStatus;
16
17
18#[derive(Serialize, Deserialize)]
20#[cfg_attr(feature = "utoipa", derive(ToSchema))]
21pub struct FeeEstimateQuery {
22 pub amount_sat: u64,
24}
25
26#[derive(Serialize, Deserialize)]
28#[cfg_attr(feature = "utoipa", derive(ToSchema))]
29pub struct SendOnchainFeeEstimateQuery {
30 pub amount_sat: u64,
32 pub address: String,
34}
35
36#[derive(Serialize, Deserialize)]
38#[cfg_attr(feature = "utoipa", derive(ToSchema))]
39pub struct OffboardAllFeeEstimateQuery {
40 pub address: String,
42}
43
44#[derive(Serialize, Deserialize)]
46#[cfg_attr(feature = "utoipa", derive(ToSchema))]
47pub struct FeeEstimateResponse {
48 #[serde(rename = "gross_amount_sat", with = "bitcoin::amount::serde::as_sat")]
50 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
51 pub gross_amount: Amount,
52 #[serde(rename = "fee_sat", with = "bitcoin::amount::serde::as_sat")]
54 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
55 pub fee: Amount,
56 #[serde(rename = "net_amount_sat", with = "bitcoin::amount::serde::as_sat")]
59 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
60 pub net_amount: Amount,
61 #[cfg_attr(feature = "utoipa", schema(value_type = Vec<String>))]
63 pub vtxos_spent: Vec<VtxoId>,
64}
65
66impl From<bark::FeeEstimate> for FeeEstimateResponse {
67 fn from(estimate: bark::FeeEstimate) -> Self {
68 FeeEstimateResponse {
69 gross_amount: estimate.gross_amount,
70 fee: estimate.fee,
71 net_amount: estimate.net_amount,
72 vtxos_spent: estimate.vtxos_spent,
73 }
74 }
75}
76
77#[derive(Serialize, Deserialize)]
79#[cfg_attr(feature = "utoipa", derive(ToSchema))]
80pub struct OnchainFeeRatesResponse {
81 pub fast_sat_per_vb: u64,
83 pub regular_sat_per_vb: u64,
85 pub slow_sat_per_vb: u64,
87}
88
89
90#[derive(Serialize, Deserialize)]
91#[cfg_attr(feature = "utoipa", derive(ToSchema))]
92pub struct TipResponse {
93 pub tip_height: u32,
94}
95
96#[derive(Serialize, Deserialize)]
97#[cfg_attr(feature = "utoipa", derive(ToSchema))]
98pub struct CreateWalletRequest {
99 pub ark_server: String,
101 pub chain_source: ChainSourceConfig,
103 pub mnemonic: Option<String>,
105 pub network: BarkNetwork,
107 pub birthday_height: Option<u32>,
109}
110
111#[derive(Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
113#[serde(rename_all = "kebab-case")]
114#[cfg_attr(feature = "utoipa", derive(ToSchema))]
115pub enum BarkNetwork {
116 Mainnet,
118 Signet,
120 Mutinynet,
122 Regtest,
124}
125
126#[derive(Serialize, Deserialize)]
127#[serde(rename_all = "kebab-case")]
128#[cfg_attr(feature = "utoipa", derive(ToSchema))]
129pub enum ChainSourceConfig {
130 Bitcoind {
132 bitcoind: String,
133 bitcoind_auth: BitcoindAuth,
134 },
135 Esplora {
137 url: String,
138 },
139}
140
141#[derive(Serialize, Deserialize)]
142#[serde(rename_all = "kebab-case")]
143#[cfg_attr(feature = "utoipa", derive(ToSchema))]
144pub enum BitcoindAuth {
145 Cookie {
147 cookie: String,
148 },
149 UserPass {
151 user: String,
152 pass: String,
153 },
154}
155
156#[derive(Serialize, Deserialize)]
157#[cfg_attr(feature = "utoipa", derive(ToSchema))]
158pub struct CreateWalletResponse {
159 pub fingerprint: String,
160}
161
162#[derive(Serialize, Deserialize)]
163#[cfg_attr(feature = "utoipa", derive(ToSchema))]
164pub struct ConnectedResponse {
165 pub connected: bool,
167}
168
169#[derive(Serialize, Deserialize)]
170#[cfg_attr(feature = "utoipa", derive(ToSchema))]
171pub struct ArkAddressResponse {
172 #[cfg_attr(feature = "utoipa", schema(value_type = String))]
173 pub address: String,
174}
175
176#[derive(Serialize, Deserialize)]
181#[cfg_attr(feature = "utoipa", derive(ToSchema))]
182pub struct EncodedVtxoResponse {
183 pub encoded: crate::primitives::EncodedVtxo,
185}
186
187#[derive(Serialize, Deserialize)]
188#[cfg_attr(feature = "utoipa", derive(ToSchema))]
189pub struct VtxosQuery {
190 pub all: Option<bool>,
192}
193
194#[derive(Serialize, Deserialize)]
195#[cfg_attr(feature = "utoipa", derive(ToSchema))]
196pub struct RefreshRequest {
197 pub vtxos: Vec<String>,
202}
203
204#[derive(Serialize, Deserialize)]
205#[cfg_attr(feature = "utoipa", derive(ToSchema))]
206pub struct BoardRequest {
207 pub amount_sat: u64,
211}
212
213#[derive(Serialize, Deserialize)]
214#[cfg_attr(feature = "utoipa", derive(ToSchema))]
215pub struct SendRequest {
216 pub destination: String,
218 pub amount_sat: Option<u64>,
222 pub comment: Option<String>,
224}
225
226#[derive(Serialize, Deserialize)]
227#[cfg_attr(feature = "utoipa", derive(ToSchema))]
228pub struct SendResponse {
229 pub message: String,
231}
232
233#[derive(Serialize, Deserialize)]
234#[cfg_attr(feature = "utoipa", derive(ToSchema))]
235pub struct SendOnchainRequest {
236 pub destination: String,
238 pub amount_sat: u64,
242}
243
244#[derive(Serialize, Deserialize)]
245#[cfg_attr(feature = "utoipa", derive(ToSchema))]
246pub struct OffboardVtxosRequest {
247 pub address: Option<String>,
249 pub vtxos: Vec<String>,
253}
254
255#[derive(Serialize, Deserialize)]
256#[cfg_attr(feature = "utoipa", derive(ToSchema))]
257pub struct OffboardAllRequest {
258 pub address: Option<String>,
260}
261
262#[derive(Serialize, Deserialize)]
263#[cfg_attr(feature = "utoipa", derive(ToSchema))]
264pub struct ImportVtxoRequest {
265 pub vtxos: Vec<String>,
267}
268
269#[derive(Serialize, Deserialize)]
270#[cfg_attr(feature = "utoipa", derive(ToSchema))]
271pub struct LightningInvoiceRequest {
272 pub amount_sat: u64,
276}
277
278#[derive(Serialize, Deserialize)]
279#[cfg_attr(feature = "utoipa", derive(ToSchema))]
280pub struct LightningPayRequest {
281 pub destination: String,
283 pub amount_sat: Option<u64>,
288 pub comment: Option<String>,
290}
291
292#[derive(Serialize, Deserialize)]
293#[cfg_attr(feature = "utoipa", derive(ToSchema))]
294pub struct LightningPayResponse {
295 pub message: String,
297}
298
299#[derive(Serialize, Deserialize)]
300#[cfg_attr(feature = "utoipa", derive(ToSchema))]
301pub struct OnchainSendRequest {
302 pub destination: String,
304 pub amount_sat: u64,
306}
307
308#[derive(Serialize, Deserialize)]
309#[cfg_attr(feature = "utoipa", derive(ToSchema))]
310pub struct OnchainSendManyRequest {
311 pub destinations: Vec<String>,
313 pub immediate: Option<bool>,
315}
316
317#[derive(Serialize, Deserialize)]
318#[cfg_attr(feature = "utoipa", derive(ToSchema))]
319pub struct OnchainDrainRequest {
320 pub destination: String,
322}
323
324#[derive(Serialize, Deserialize)]
325#[cfg_attr(feature = "utoipa", derive(ToSchema))]
326pub struct ExitStatusRequest {
327 pub history: Option<bool>,
329 pub transactions: Option<bool>,
331}
332
333#[derive(Serialize, Deserialize)]
334#[cfg_attr(feature = "utoipa", derive(ToSchema))]
335pub struct ExitStartRequest {
336 pub vtxos: Vec<String>,
338}
339
340#[derive(Serialize, Deserialize)]
341#[cfg_attr(feature = "utoipa", derive(ToSchema))]
342pub struct ExitStartResponse {
343 pub message: String,
344}
345
346#[derive(Serialize, Deserialize)]
347#[cfg_attr(feature = "utoipa", derive(ToSchema))]
348pub struct ExitProgressRequest {
349 pub wait: Option<bool>,
351 pub fee_rate: Option<u64>,
353}
354
355#[derive(Serialize, Deserialize)]
356#[cfg_attr(feature = "utoipa", derive(ToSchema))]
357pub struct ExitClaimAllRequest {
358 pub destination: String,
360 pub fee_rate: Option<u64>,
362}
363
364#[derive(Serialize, Deserialize)]
365#[cfg_attr(feature = "utoipa", derive(ToSchema))]
366pub struct ExitClaimVtxosRequest {
367 pub destination: String,
369 pub vtxos: Vec<String>,
371 pub fee_rate: Option<u64>,
373}
374
375#[derive(Serialize, Deserialize)]
376#[cfg_attr(feature = "utoipa", derive(ToSchema))]
377pub struct ExitClaimResponse {
378 pub message: String,
379}
380
381
382#[derive(Serialize, Deserialize)]
383#[cfg_attr(feature = "utoipa", derive(ToSchema))]
384pub struct VtxoRequestInfo {
385 #[serde(rename = "amount_sat", with = "bitcoin::amount::serde::as_sat")]
386 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
387 pub amount: Amount,
388 #[cfg_attr(feature = "utoipa", schema(value_type = String))]
389 pub policy_type: VtxoPolicyKind,
390 #[cfg_attr(feature = "utoipa", schema(value_type = String))]
391 pub user_pubkey: PublicKey,
392}
393
394impl<'a> From<&'a ark::VtxoRequest> for VtxoRequestInfo {
395 fn from(v: &'a ark::VtxoRequest) -> Self {
396 Self {
397 amount: v.amount,
398 policy_type: v.policy.policy_type(),
399 user_pubkey: v.policy.user_pubkey(),
400 }
401 }
402}
403
404#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]
405#[cfg_attr(feature = "utoipa", derive(ToSchema))]
406pub struct OffboardRequestInfo {
407 pub script_pubkey_hex: String,
409 pub script_pubkey_asm: String,
411 #[serde(rename = "net_amount_sat", with = "bitcoin::amount::serde::as_sat")]
413 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
414 pub net_amount: Amount,
415 pub deduct_fees_from_gross_amount: bool,
417 #[serde(rename = "fee_rate_kwu")]
419 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
420 pub fee_rate: FeeRate,
421}
422
423impl<'a> From<&'a OffboardRequest> for OffboardRequestInfo {
424 fn from(v: &'a OffboardRequest) -> Self {
425 Self {
426 script_pubkey_hex: v.script_pubkey.to_hex_string(),
427 script_pubkey_asm: v.script_pubkey.to_asm_string(),
428 net_amount: v.net_amount,
429 deduct_fees_from_gross_amount: v.deduct_fees_from_gross_amount,
430 fee_rate: v.fee_rate,
431 }
432 }
433}
434
435#[derive(Serialize, Deserialize)]
436#[cfg_attr(feature = "utoipa", derive(ToSchema))]
437pub struct RoundParticipationInfo {
438 #[cfg_attr(feature = "utoipa", schema(value_type = Vec<String>))]
439 pub inputs: Vec<VtxoId>,
440 pub outputs: Vec<VtxoRequestInfo>,
441}
442
443impl<'a> From<&'a bark::round::RoundParticipation> for RoundParticipationInfo {
444 fn from(v: &'a bark::round::RoundParticipation) -> Self {
445 Self {
446 inputs: v.inputs.iter().map(|v| v.id()).collect(),
447 outputs: v.outputs.iter().map(Into::into).collect(),
448 }
449 }
450}
451
452#[derive(Serialize, Deserialize)]
453#[cfg_attr(feature = "utoipa", derive(ToSchema))]
454pub struct PendingRoundInfo {
455 pub id: u32,
457 pub status: RoundStatus,
459 pub participation: RoundParticipationInfo,
461 #[cfg_attr(feature = "utoipa", schema(value_type = String, nullable = true))]
462 pub unlock_hash: Option<UnlockHash>,
463 #[cfg_attr(feature = "utoipa", schema(value_type = String, nullable = true))]
465 pub funding_txid: Option<Txid>,
466 pub funding_tx_hex: Option<String>,
467}
468
469impl PendingRoundInfo {
470 pub fn new<'a>(
471 state: &'a bark::persist::models::StoredRoundState,
472 sync_result: anyhow::Result<bark::round::RoundStatus>,
473 ) -> Self {
474 let funding_tx = state.state().funding_tx();
475 Self {
476 id: state.id().0,
477 status: match sync_result {
478 Ok(status) => status.into(),
479 Err(e) => RoundStatus::SyncError {
480 error: format!("{:#}", e),
481 },
482 },
483 participation: state.state().participation().into(),
484 unlock_hash: state.state().unlock_hash(),
485 funding_txid: funding_tx.map(|t| t.compute_txid()),
486 funding_tx_hex: funding_tx.map(|t| serialize_hex(t)),
487 }
488 }
489}
490
491#[derive(Serialize, Deserialize)]
492#[cfg_attr(feature = "utoipa", derive(ToSchema))]
493pub struct WalletExistsResponse {
494 pub fingerprint: Option<String>,
495}
496
497#[derive(Serialize, Deserialize)]
498#[cfg_attr(feature = "utoipa", derive(ToSchema))]
499pub struct WalletDeleteRequest {
500 pub dangerous: bool,
501 pub fingerprint: String,
502}
503
504#[derive(Serialize, Deserialize)]
505#[cfg_attr(feature = "utoipa", derive(ToSchema))]
506pub struct WalletDeleteResponse {
507 pub deleted: bool,
508 pub message: String,
509}
510