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: Option<String>,
102 pub ark_server_access_token: Option<String>,
104 pub chain_source: Option<ChainSourceConfig>,
107 pub mnemonic: Option<String>,
109 pub network: BarkNetwork,
111 pub birthday_height: Option<u32>,
113}
114
115#[derive(Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
117#[serde(rename_all = "kebab-case")]
118#[cfg_attr(feature = "utoipa", derive(ToSchema))]
119pub enum BarkNetwork {
120 Mainnet,
122 Signet,
124 Mutinynet,
126 Regtest,
128}
129
130#[derive(Serialize, Deserialize)]
131#[serde(rename_all = "kebab-case")]
132#[cfg_attr(feature = "utoipa", derive(ToSchema))]
133pub enum ChainSourceConfig {
134 Bitcoind {
136 bitcoind: String,
137 bitcoind_auth: BitcoindAuth,
138 },
139 Esplora {
141 url: String,
142 },
143}
144
145#[derive(Serialize, Deserialize)]
146#[serde(rename_all = "kebab-case")]
147#[cfg_attr(feature = "utoipa", derive(ToSchema))]
148pub enum BitcoindAuth {
149 Cookie {
151 cookie: String,
152 },
153 UserPass {
155 user: String,
156 pass: String,
157 },
158}
159
160#[derive(Serialize, Deserialize)]
161#[cfg_attr(feature = "utoipa", derive(ToSchema))]
162pub struct CreateWalletResponse {
163 pub fingerprint: String,
164}
165
166#[derive(Serialize, Deserialize)]
167#[cfg_attr(feature = "utoipa", derive(ToSchema))]
168pub struct ConnectedResponse {
169 pub connected: bool,
171}
172
173#[derive(Serialize, Deserialize)]
174#[cfg_attr(feature = "utoipa", derive(ToSchema))]
175pub struct ArkAddressResponse {
176 #[cfg_attr(feature = "utoipa", schema(value_type = String))]
177 pub address: String,
178}
179
180#[derive(Serialize, Deserialize)]
185#[cfg_attr(feature = "utoipa", derive(ToSchema))]
186pub struct EncodedVtxoResponse {
187 pub encoded: crate::primitives::EncodedVtxo,
189}
190
191#[derive(Serialize, Deserialize)]
192#[cfg_attr(feature = "utoipa", derive(ToSchema))]
193pub struct VtxosQuery {
194 pub all: Option<bool>,
196}
197
198#[derive(Serialize, Deserialize)]
199#[cfg_attr(feature = "utoipa", derive(ToSchema))]
200pub struct RefreshRequest {
201 pub vtxos: Vec<String>,
206}
207
208#[derive(Serialize, Deserialize)]
209#[cfg_attr(feature = "utoipa", derive(ToSchema))]
210pub struct BoardRequest {
211 pub amount_sat: u64,
215}
216
217#[derive(Serialize, Deserialize)]
218#[cfg_attr(feature = "utoipa", derive(ToSchema))]
219pub struct SendRequest {
220 pub destination: String,
222 pub amount_sat: Option<u64>,
226 pub comment: Option<String>,
228}
229
230#[derive(Serialize, Deserialize)]
231#[cfg_attr(feature = "utoipa", derive(ToSchema))]
232pub struct SendResponse {
233 pub message: String,
235}
236
237#[derive(Serialize, Deserialize)]
238#[cfg_attr(feature = "utoipa", derive(ToSchema))]
239pub struct SendOnchainRequest {
240 pub destination: String,
242 pub amount_sat: u64,
246}
247
248#[derive(Serialize, Deserialize)]
249#[cfg_attr(feature = "utoipa", derive(ToSchema))]
250pub struct OffboardVtxosRequest {
251 pub address: Option<String>,
253 pub vtxos: Vec<String>,
257}
258
259#[derive(Serialize, Deserialize)]
260#[cfg_attr(feature = "utoipa", derive(ToSchema))]
261pub struct OffboardAllRequest {
262 pub address: Option<String>,
264}
265
266#[derive(Serialize, Deserialize)]
267#[cfg_attr(feature = "utoipa", derive(ToSchema))]
268pub struct ImportVtxoRequest {
269 pub vtxos: Vec<String>,
271}
272
273#[derive(Serialize, Deserialize)]
274#[cfg_attr(feature = "utoipa", derive(ToSchema))]
275pub struct LightningInvoiceRequest {
276 pub amount_sat: u64,
280}
281
282#[derive(Serialize, Deserialize)]
283#[cfg_attr(feature = "utoipa", derive(ToSchema))]
284pub struct LightningPayRequest {
285 pub destination: String,
287 pub amount_sat: Option<u64>,
292 pub comment: Option<String>,
294}
295
296#[derive(Serialize, Deserialize)]
297#[cfg_attr(feature = "utoipa", derive(ToSchema))]
298pub struct LightningPayResponse {
299 pub message: String,
301}
302
303#[derive(Serialize, Deserialize)]
304#[cfg_attr(feature = "utoipa", derive(ToSchema))]
305pub struct OnchainSendRequest {
306 pub destination: String,
308 pub amount_sat: u64,
310}
311
312#[derive(Serialize, Deserialize)]
313#[cfg_attr(feature = "utoipa", derive(ToSchema))]
314pub struct OnchainSendManyRequest {
315 pub destinations: Vec<String>,
317 pub immediate: Option<bool>,
319}
320
321#[derive(Serialize, Deserialize)]
322#[cfg_attr(feature = "utoipa", derive(ToSchema))]
323pub struct OnchainDrainRequest {
324 pub destination: String,
326}
327
328#[derive(Serialize, Deserialize)]
329#[cfg_attr(feature = "utoipa", derive(ToSchema))]
330pub struct ExitStatusRequest {
331 pub history: Option<bool>,
333 pub transactions: Option<bool>,
335}
336
337#[derive(Serialize, Deserialize)]
338#[cfg_attr(feature = "utoipa", derive(ToSchema))]
339pub struct ExitStartRequest {
340 pub vtxos: Vec<String>,
342}
343
344#[derive(Serialize, Deserialize)]
345#[cfg_attr(feature = "utoipa", derive(ToSchema))]
346pub struct ExitStartResponse {
347 pub message: String,
348}
349
350#[derive(Serialize, Deserialize)]
351#[cfg_attr(feature = "utoipa", derive(ToSchema))]
352pub struct ExitProgressRequest {
353 pub wait: Option<bool>,
355 pub fee_rate: Option<u64>,
357}
358
359#[derive(Serialize, Deserialize)]
360#[cfg_attr(feature = "utoipa", derive(ToSchema))]
361pub struct ExitClaimAllRequest {
362 pub destination: String,
364 pub fee_rate: Option<u64>,
366}
367
368#[derive(Serialize, Deserialize)]
369#[cfg_attr(feature = "utoipa", derive(ToSchema))]
370pub struct ExitClaimVtxosRequest {
371 pub destination: String,
373 pub vtxos: Vec<String>,
375 pub fee_rate: Option<u64>,
377}
378
379#[derive(Serialize, Deserialize)]
380#[cfg_attr(feature = "utoipa", derive(ToSchema))]
381pub struct ExitClaimResponse {
382 pub message: String,
383}
384
385
386#[derive(Serialize, Deserialize)]
387#[cfg_attr(feature = "utoipa", derive(ToSchema))]
388pub struct VtxoRequestInfo {
389 #[serde(rename = "amount_sat", with = "bitcoin::amount::serde::as_sat")]
390 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
391 pub amount: Amount,
392 #[cfg_attr(feature = "utoipa", schema(value_type = String))]
393 pub policy_type: VtxoPolicyKind,
394 #[cfg_attr(feature = "utoipa", schema(value_type = String))]
395 pub user_pubkey: PublicKey,
396}
397
398impl<'a> From<&'a ark::VtxoRequest> for VtxoRequestInfo {
399 fn from(v: &'a ark::VtxoRequest) -> Self {
400 Self {
401 amount: v.amount,
402 policy_type: v.policy.policy_type(),
403 user_pubkey: v.policy.user_pubkey(),
404 }
405 }
406}
407
408#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]
409#[cfg_attr(feature = "utoipa", derive(ToSchema))]
410pub struct OffboardRequestInfo {
411 pub script_pubkey_hex: String,
413 pub script_pubkey_asm: String,
415 #[serde(rename = "net_amount_sat", with = "bitcoin::amount::serde::as_sat")]
417 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
418 pub net_amount: Amount,
419 pub deduct_fees_from_gross_amount: bool,
421 #[serde(rename = "fee_rate_kwu")]
423 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
424 pub fee_rate: FeeRate,
425}
426
427impl<'a> From<&'a OffboardRequest> for OffboardRequestInfo {
428 fn from(v: &'a OffboardRequest) -> Self {
429 Self {
430 script_pubkey_hex: v.script_pubkey.to_hex_string(),
431 script_pubkey_asm: v.script_pubkey.to_asm_string(),
432 net_amount: v.net_amount,
433 deduct_fees_from_gross_amount: v.deduct_fees_from_gross_amount,
434 fee_rate: v.fee_rate,
435 }
436 }
437}
438
439#[derive(Serialize, Deserialize)]
440#[cfg_attr(feature = "utoipa", derive(ToSchema))]
441pub struct RoundParticipationInfo {
442 #[cfg_attr(feature = "utoipa", schema(value_type = Vec<String>))]
443 pub inputs: Vec<VtxoId>,
444 pub outputs: Vec<VtxoRequestInfo>,
445}
446
447impl<'a> From<&'a bark::round::RoundParticipation> for RoundParticipationInfo {
448 fn from(v: &'a bark::round::RoundParticipation) -> Self {
449 Self {
450 inputs: v.inputs.iter().map(|v| v.id()).collect(),
451 outputs: v.outputs.iter().map(Into::into).collect(),
452 }
453 }
454}
455
456#[derive(Serialize, Deserialize)]
457#[cfg_attr(feature = "utoipa", derive(ToSchema))]
458pub struct PendingRoundInfo {
459 pub id: u32,
461 pub status: RoundStatus,
463 pub participation: RoundParticipationInfo,
465 #[cfg_attr(feature = "utoipa", schema(value_type = String, nullable = true))]
466 pub unlock_hash: Option<UnlockHash>,
467 #[cfg_attr(feature = "utoipa", schema(value_type = String, nullable = true))]
469 pub funding_txid: Option<Txid>,
470 pub funding_tx_hex: Option<String>,
471}
472
473impl PendingRoundInfo {
474 pub fn new<'a>(
475 state: &'a bark::persist::models::StoredRoundState,
476 sync_result: anyhow::Result<bark::round::RoundStatus>,
477 ) -> Self {
478 let funding_tx = state.state().funding_tx();
479 Self {
480 id: state.id().0,
481 status: match sync_result {
482 Ok(status) => status.into(),
483 Err(e) => RoundStatus::SyncError {
484 error: format!("{:#}", e),
485 },
486 },
487 participation: state.state().participation().into(),
488 unlock_hash: state.state().unlock_hash(),
489 funding_txid: funding_tx.map(|t| t.compute_txid()),
490 funding_tx_hex: funding_tx.map(|t| serialize_hex(t)),
491 }
492 }
493}
494
495#[derive(Serialize, Deserialize)]
496#[cfg_attr(feature = "utoipa", derive(ToSchema))]
497pub struct WalletExistsResponse {
498 pub fingerprint: Option<String>,
499}
500
501#[derive(Serialize, Deserialize)]
502#[cfg_attr(feature = "utoipa", derive(ToSchema))]
503pub struct WalletDeleteRequest {
504 pub dangerous: bool,
505 pub fingerprint: String,
506}
507
508#[derive(Serialize, Deserialize)]
509#[cfg_attr(feature = "utoipa", derive(ToSchema))]
510pub struct WalletDeleteResponse {
511 pub deleted: bool,
512 pub message: String,
513}
514