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::lightning::PaymentHash;
9use ark::offboard::OffboardRequest;
10use ark::tree::signed::UnlockHash;
11use ark::vtxo::VtxoPolicyKind;
12use bark::round::RoundFlowKind;
13
14#[cfg(feature = "utoipa")]
15use utoipa::ToSchema;
16
17use crate::cli::RoundStatus;
18
19
20#[derive(Default, Serialize, Deserialize)]
26#[cfg_attr(feature = "utoipa", derive(ToSchema))]
27pub struct HistoryQuery {
28 #[serde(rename = "type")]
32 pub method_type: Option<String>,
33 pub value: Option<String>,
36}
37
38#[derive(Serialize, Deserialize)]
40#[cfg_attr(feature = "utoipa", derive(ToSchema))]
41pub struct FeeEstimateQuery {
42 pub amount_sat: u64,
44}
45
46#[derive(Serialize, Deserialize)]
48#[cfg_attr(feature = "utoipa", derive(ToSchema))]
49pub struct SendOnchainFeeEstimateQuery {
50 pub amount_sat: u64,
52 pub address: String,
54}
55
56#[derive(Serialize, Deserialize)]
58#[cfg_attr(feature = "utoipa", derive(ToSchema))]
59pub struct OffboardAllFeeEstimateQuery {
60 pub address: String,
62}
63
64#[derive(Serialize, Deserialize)]
66#[cfg_attr(feature = "utoipa", derive(ToSchema))]
67pub struct OffboardFeeEstimateRequest {
68 pub address: String,
70 pub vtxos: Vec<String>,
72}
73
74#[derive(Serialize, Deserialize)]
76#[cfg_attr(feature = "utoipa", derive(ToSchema))]
77pub struct FeeEstimateResponse {
78 #[serde(rename = "gross_amount_sat", with = "bitcoin::amount::serde::as_sat")]
80 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
81 pub gross_amount: Amount,
82 #[serde(rename = "fee_sat", with = "bitcoin::amount::serde::as_sat")]
84 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
85 pub fee: Amount,
86 #[serde(rename = "net_amount_sat", with = "bitcoin::amount::serde::as_sat")]
89 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
90 pub net_amount: Amount,
91 #[cfg_attr(feature = "utoipa", schema(value_type = Vec<String>))]
93 pub vtxos_spent: Vec<VtxoId>,
94}
95
96impl From<bark::FeeEstimate> for FeeEstimateResponse {
97 fn from(estimate: bark::FeeEstimate) -> Self {
98 FeeEstimateResponse {
99 gross_amount: estimate.gross_amount,
100 fee: estimate.fee,
101 net_amount: estimate.net_amount,
102 vtxos_spent: estimate.vtxos_spent,
103 }
104 }
105}
106
107#[derive(Serialize, Deserialize)]
109#[cfg_attr(feature = "utoipa", derive(ToSchema))]
110pub struct EmergencyExitFeeEstimateQuery {
111 pub vtxo_ids: Option<String>,
114 pub fee_rate_sat_per_vb: Option<u64>,
118 pub destination: Option<String>,
121}
122
123#[derive(Debug, Clone, Serialize, Deserialize)]
125#[cfg_attr(feature = "utoipa", derive(ToSchema))]
126pub struct EmergencyExitFeeEstimateResponse {
127 #[serde(rename = "exit_broadcast_fee_sat", with = "bitcoin::amount::serde::as_sat")]
130 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
131 pub exit_broadcast_fee: Amount,
132 #[serde(rename = "claim_fee_sat", with = "bitcoin::amount::serde::as_sat")]
135 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
136 pub claim_fee: Amount,
137 #[serde(rename = "total_fee_sat", with = "bitcoin::amount::serde::as_sat")]
139 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
140 pub total_fee: Amount,
141 pub fee_rate_sat_per_vb: u64,
144 pub txs_to_broadcast: usize,
146 pub fundable: bool,
148}
149
150impl From<bark::exit::ExitFeeEstimate> for EmergencyExitFeeEstimateResponse {
151 fn from(e: bark::exit::ExitFeeEstimate) -> Self {
152 EmergencyExitFeeEstimateResponse {
153 total_fee: e.total(),
154 exit_broadcast_fee: e.exit_broadcast_fee,
155 claim_fee: e.claim_fee,
156 fee_rate_sat_per_vb: e.fee_rate.to_sat_per_vb_ceil(),
157 txs_to_broadcast: e.txs_to_broadcast,
158 fundable: e.fundable,
159 }
160 }
161}
162
163#[derive(Serialize, Deserialize)]
165#[cfg_attr(feature = "utoipa", derive(ToSchema))]
166pub struct OnchainFeeRatesResponse {
167 pub fast_sat_per_vb: u64,
169 pub regular_sat_per_vb: u64,
171 pub slow_sat_per_vb: u64,
173}
174
175
176#[derive(Serialize, Deserialize)]
177#[cfg_attr(feature = "utoipa", derive(ToSchema))]
178pub struct TipResponse {
179 pub tip_height: u32,
180}
181
182#[derive(Serialize, Deserialize)]
183#[cfg_attr(feature = "utoipa", derive(ToSchema))]
184pub struct MailboxSyncResponse {
185 pub checkpoint: u64,
188}
189
190#[derive(Serialize, Deserialize)]
191#[cfg_attr(feature = "utoipa", derive(ToSchema))]
192pub struct CreateWalletRequest {
193 pub ark_server: Option<String>,
196 #[deprecated(
201 since = "0.2.4",
202 note = "access tokens are not enforced by the server; this field will be removed",
203 )]
204 pub ark_server_access_token: Option<String>,
205 pub chain_source: Option<ChainSourceConfig>,
208 pub mnemonic: Option<String>,
210 pub network: BarkNetwork,
212 pub birthday_height: Option<u32>,
214 #[serde(default)]
216 pub force: bool,
217}
218
219#[derive(Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
221#[serde(rename_all = "kebab-case")]
222#[cfg_attr(feature = "utoipa", derive(ToSchema))]
223pub enum BarkNetwork {
224 Mainnet,
226 Signet,
228 Mutinynet,
230 Regtest,
232}
233
234#[derive(Serialize, Deserialize)]
235#[serde(rename_all = "kebab-case")]
236#[cfg_attr(feature = "utoipa", derive(ToSchema))]
237pub enum ChainSourceConfig {
238 Bitcoind {
240 bitcoind: String,
241 bitcoind_auth: BitcoindAuth,
242 },
243 Esplora {
245 url: String,
246 },
247}
248
249#[derive(Serialize, Deserialize)]
250#[serde(rename_all = "kebab-case")]
251#[cfg_attr(feature = "utoipa", derive(ToSchema))]
252pub enum BitcoindAuth {
253 Cookie {
255 cookie: String,
256 },
257 UserPass {
259 user: String,
260 pass: String,
261 },
262}
263
264#[derive(Serialize, Deserialize)]
265#[cfg_attr(feature = "utoipa", derive(ToSchema))]
266pub struct CreateWalletResponse {
267 pub fingerprint: String,
268}
269
270#[derive(Serialize, Deserialize)]
271#[cfg_attr(feature = "utoipa", derive(ToSchema))]
272pub struct ConnectedResponse {
273 pub connected: bool,
275}
276
277#[derive(Serialize, Deserialize)]
278#[cfg_attr(feature = "utoipa", derive(ToSchema))]
279pub struct MnemonicResponse {
280 pub mnemonic: String,
282}
283
284#[derive(Serialize, Deserialize)]
285#[cfg_attr(feature = "utoipa", derive(ToSchema))]
286pub struct ArkAddressResponse {
287 #[cfg_attr(feature = "utoipa", schema(value_type = String))]
288 pub address: String,
289}
290
291#[derive(Serialize, Deserialize)]
297#[cfg_attr(feature = "utoipa", derive(ToSchema))]
298pub struct Bip321UriRequest {
299 #[serde(default, skip_serializing_if = "Option::is_none")]
304 pub amount_sat: Option<u64>,
305 #[serde(default, skip_serializing_if = "Option::is_none")]
308 pub onchain: Option<bool>,
309 #[serde(default, skip_serializing_if = "Option::is_none")]
311 pub label: Option<String>,
312 #[serde(default, skip_serializing_if = "Option::is_none")]
314 pub message: Option<String>,
315}
316
317#[derive(Serialize, Deserialize)]
319#[cfg_attr(feature = "utoipa", derive(ToSchema))]
320pub struct Bip321UriQuery {
321 pub uppercase: Option<bool>,
327}
328
329#[derive(Serialize, Deserialize)]
335#[cfg_attr(feature = "utoipa", derive(ToSchema))]
336pub struct Bip321UriResponse {
337 #[serde(skip_serializing_if = "Option::is_none")]
339 pub ark: Option<String>,
340 #[serde(skip_serializing_if = "Option::is_none")]
342 pub bolt11: Option<String>,
343 #[serde(skip_serializing_if = "Option::is_none")]
345 pub onchain: Option<String>,
346 pub bip321: String,
348}
349
350#[derive(Serialize, Deserialize)]
355#[cfg_attr(feature = "utoipa", derive(ToSchema))]
356pub struct EncodedVtxoResponse {
357 pub encoded: crate::primitives::EncodedVtxo,
359}
360
361#[derive(Serialize, Deserialize)]
362#[cfg_attr(feature = "utoipa", derive(ToSchema))]
363pub struct VtxosQuery {
364 pub all: Option<bool>,
366}
367
368#[derive(Serialize, Deserialize)]
369#[cfg_attr(feature = "utoipa", derive(ToSchema))]
370pub struct RefreshRequest {
371 pub vtxos: Vec<String>,
376}
377
378#[derive(Serialize, Deserialize)]
379#[cfg_attr(feature = "utoipa", derive(ToSchema))]
380pub struct DelegatedRefreshRequest {
381 pub vtxos: Vec<String>,
386 pub height: Option<u32>,
390}
391
392#[derive(Serialize, Deserialize)]
393#[cfg_attr(feature = "utoipa", derive(ToSchema))]
394pub struct BoardRequest {
395 pub amount_sat: u64,
399}
400
401#[derive(Serialize, Deserialize)]
402#[cfg_attr(feature = "utoipa", derive(ToSchema))]
403pub struct SendRequest {
404 pub destination: String,
406 pub amount_sat: Option<u64>,
410 pub comment: Option<String>,
412}
413
414#[derive(Serialize, Deserialize)]
415#[cfg_attr(feature = "utoipa", derive(ToSchema))]
416pub struct SendResponse {
417 pub message: String,
419 #[serde(default, skip_serializing_if = "Option::is_none")]
422 #[cfg_attr(feature = "utoipa", schema(value_type = Option<String>))]
423 pub payment_hash: Option<PaymentHash>,
424}
425
426#[derive(Serialize, Deserialize)]
428#[cfg_attr(feature = "utoipa", derive(ToSchema))]
429pub struct SignMessageRequest {
430 pub message: String,
432 pub address: String,
434}
435
436#[derive(Serialize, Deserialize)]
440#[cfg_attr(feature = "utoipa", derive(ToSchema))]
441pub struct VerifyMessageRequest {
442 pub message: String,
444 pub signature: String,
447 pub pubkey: Option<String>,
449 pub address: Option<String>,
451}
452
453#[derive(Serialize, Deserialize)]
454#[cfg_attr(feature = "utoipa", derive(ToSchema))]
455pub struct SendOnchainRequest {
456 pub destination: String,
458 pub amount_sat: u64,
462}
463
464#[derive(Serialize, Deserialize)]
465#[cfg_attr(feature = "utoipa", derive(ToSchema))]
466pub struct OffboardVtxosRequest {
467 pub address: Option<String>,
469 pub vtxos: Vec<String>,
473}
474
475#[derive(Serialize, Deserialize)]
476#[cfg_attr(feature = "utoipa", derive(ToSchema))]
477pub struct OffboardAllRequest {
478 pub address: Option<String>,
480}
481
482#[derive(Serialize, Deserialize)]
483#[cfg_attr(feature = "utoipa", derive(ToSchema))]
484pub struct ImportVtxoRequest {
485 pub vtxos: Vec<String>,
487}
488
489#[derive(Serialize, Deserialize)]
490#[cfg_attr(feature = "utoipa", derive(ToSchema))]
491pub struct LightningInvoiceRequest {
492 pub amount_sat: u64,
496 #[serde(default, skip_serializing_if = "Option::is_none")]
498 pub description: Option<String>,
499 #[serde(default, skip_serializing_if = "Option::is_none")]
503 pub token: Option<String>,
504}
505
506#[derive(Serialize, Deserialize)]
507#[cfg_attr(feature = "utoipa", derive(ToSchema))]
508pub struct LightningInvoiceForAddressRequest {
509 pub amount_sat: u64,
511 pub address: String,
513 #[serde(default, skip_serializing_if = "Option::is_none")]
515 pub description: Option<String>,
516}
517
518#[derive(Serialize, Deserialize)]
519#[cfg_attr(feature = "utoipa", derive(ToSchema))]
520pub struct LightningPayRequest {
521 pub destination: String,
523 pub amount_sat: Option<u64>,
528 pub comment: Option<String>,
530}
531
532#[derive(Serialize, Deserialize)]
533#[cfg_attr(feature = "utoipa", derive(ToSchema))]
534pub struct LightningPayResponse {
535 pub message: String,
537 #[serde(default, skip_serializing_if = "Option::is_none")]
540 #[cfg_attr(feature = "utoipa", schema(value_type = Option<String>))]
541 pub payment_hash: Option<PaymentHash>,
542}
543
544#[derive(Serialize, Deserialize)]
545#[cfg_attr(feature = "utoipa", derive(ToSchema))]
546pub struct OnchainSendRequest {
547 pub destination: String,
549 pub amount_sat: u64,
551}
552
553#[derive(Serialize, Deserialize)]
554#[cfg_attr(feature = "utoipa", derive(ToSchema))]
555pub struct OnchainSendManyRequest {
556 pub destinations: Vec<String>,
558 pub immediate: Option<bool>,
560}
561
562#[derive(Serialize, Deserialize)]
563#[cfg_attr(feature = "utoipa", derive(ToSchema))]
564pub struct OnchainDrainRequest {
565 pub destination: String,
567}
568
569#[derive(Serialize, Deserialize)]
570#[cfg_attr(feature = "utoipa", derive(ToSchema))]
571pub struct ExitStatusRequest {
572 pub history: Option<bool>,
574 pub transactions: Option<bool>,
576}
577
578#[derive(Serialize, Deserialize)]
579#[cfg_attr(feature = "utoipa", derive(ToSchema))]
580pub struct ExitStartRequest {
581 pub vtxos: Vec<String>,
583}
584
585#[derive(Serialize, Deserialize)]
586#[cfg_attr(feature = "utoipa", derive(ToSchema))]
587pub struct ExitStartResponse {
588 pub message: String,
589}
590
591#[derive(Serialize, Deserialize)]
592#[cfg_attr(feature = "utoipa", derive(ToSchema))]
593pub struct ExitProgressRequest {
594 pub wait: Option<bool>,
596 pub fee_rate: Option<u64>,
598}
599
600#[derive(Serialize, Deserialize)]
601#[cfg_attr(feature = "utoipa", derive(ToSchema))]
602pub struct ExitClaimAllRequest {
603 pub destination: String,
605 pub fee_rate: Option<u64>,
607}
608
609#[derive(Serialize, Deserialize)]
610#[cfg_attr(feature = "utoipa", derive(ToSchema))]
611pub struct ExitClaimVtxosRequest {
612 pub destination: String,
614 pub vtxos: Vec<String>,
616 pub fee_rate: Option<u64>,
618}
619
620#[derive(Serialize, Deserialize)]
621#[cfg_attr(feature = "utoipa", derive(ToSchema))]
622pub struct ExitClaimResponse {
623 pub message: String,
624}
625
626#[derive(Serialize, Deserialize)]
627#[cfg_attr(feature = "utoipa", derive(ToSchema))]
628pub struct ExitCancelResponse {
629 pub message: String,
630}
631
632
633#[derive(Serialize, Deserialize)]
634#[cfg_attr(feature = "utoipa", derive(ToSchema))]
635pub struct VtxoRequestInfo {
636 #[serde(rename = "amount_sat", with = "bitcoin::amount::serde::as_sat")]
637 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
638 pub amount: Amount,
639 #[cfg_attr(feature = "utoipa", schema(value_type = String))]
640 pub policy_type: VtxoPolicyKind,
641 #[cfg_attr(feature = "utoipa", schema(value_type = String))]
642 pub user_pubkey: PublicKey,
643}
644
645impl<'a> From<&'a ark::VtxoRequest> for VtxoRequestInfo {
646 fn from(v: &'a ark::VtxoRequest) -> Self {
647 Self {
648 amount: v.amount,
649 policy_type: v.policy.policy_type(),
650 user_pubkey: v.policy.user_pubkey(),
651 }
652 }
653}
654
655#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]
656#[cfg_attr(feature = "utoipa", derive(ToSchema))]
657pub struct OffboardRequestInfo {
658 pub script_pubkey_hex: String,
660 pub script_pubkey_asm: String,
662 #[serde(rename = "net_amount_sat", with = "bitcoin::amount::serde::as_sat")]
664 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
665 pub net_amount: Amount,
666 pub deduct_fees_from_gross_amount: bool,
668 #[serde(rename = "fee_rate_kwu")]
670 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
671 pub fee_rate: FeeRate,
672}
673
674impl<'a> From<&'a OffboardRequest> for OffboardRequestInfo {
675 fn from(v: &'a OffboardRequest) -> Self {
676 Self {
677 script_pubkey_hex: v.script_pubkey.to_hex_string(),
678 script_pubkey_asm: v.script_pubkey.to_asm_string(),
679 net_amount: v.net_amount,
680 deduct_fees_from_gross_amount: v.deduct_fees_from_gross_amount,
681 fee_rate: v.fee_rate,
682 }
683 }
684}
685
686#[derive(Serialize, Deserialize)]
687#[cfg_attr(feature = "utoipa", derive(ToSchema))]
688pub struct RoundParticipationInfo {
689 #[cfg_attr(feature = "utoipa", schema(value_type = Vec<String>))]
690 pub inputs: Vec<VtxoId>,
691 pub outputs: Vec<VtxoRequestInfo>,
692}
693
694impl<'a> From<&'a bark::round::RoundParticipation> for RoundParticipationInfo {
695 fn from(v: &'a bark::round::RoundParticipation) -> Self {
696 Self {
697 inputs: v.inputs.iter().map(|v| v.id()).collect(),
698 outputs: v.outputs.iter().map(Into::into).collect(),
699 }
700 }
701}
702
703#[derive(Serialize, Deserialize)]
705#[cfg_attr(feature = "utoipa", derive(ToSchema))]
706#[serde(rename_all = "kebab-case")]
707pub enum RoundFlowState {
708 DelegatedPending,
710 Pending,
712 Ongoing,
714 AwaitingConfirmations,
716 Failed,
718 Canceled,
720}
721
722impl From<RoundFlowKind> for RoundFlowState {
723 fn from(kind: RoundFlowKind) -> Self {
724 match kind {
725 RoundFlowKind::DelegatedPending => Self::DelegatedPending,
726 RoundFlowKind::Pending => Self::Pending,
727 RoundFlowKind::Ongoing => Self::Ongoing,
728 RoundFlowKind::AwaitingConfirmations => Self::AwaitingConfirmations,
729 RoundFlowKind::Failed => Self::Failed,
730 RoundFlowKind::Canceled => Self::Canceled,
731 }
732 }
733}
734
735#[derive(Serialize, Deserialize)]
736#[cfg_attr(feature = "utoipa", derive(ToSchema))]
737pub struct PendingRoundInfo {
738 pub id: u32,
740 pub status: RoundStatus,
742 pub state: RoundFlowState,
744 pub participation: RoundParticipationInfo,
746 #[cfg_attr(feature = "utoipa", schema(value_type = String, nullable = true))]
747 pub unlock_hash: Option<UnlockHash>,
748 #[serde(default)]
750 pub scheduled_height: Option<u32>,
751 #[cfg_attr(feature = "utoipa", schema(value_type = String, nullable = true))]
753 pub funding_txid: Option<Txid>,
754 pub funding_tx_hex: Option<String>,
755}
756
757impl PendingRoundInfo {
758 pub fn new<G>(
759 state: &bark::persist::models::StoredRoundState<G>,
760 sync_result: anyhow::Result<bark::round::RoundStatus>,
761 ) -> Self {
762 let funding_tx = state.state().funding_tx();
763 Self {
764 id: state.id().0,
765 status: match sync_result {
766 Ok(status) => status.into(),
767 Err(e) => RoundStatus::SyncError {
768 error: format!("{:#}", e),
769 },
770 },
771 state: state.state().flow_kind().into(),
772 participation: state.state().participation().into(),
773 unlock_hash: state.state().unlock_hash(),
774 scheduled_height: state.state().scheduled_height(),
775 funding_txid: funding_tx.map(|t| t.compute_txid()),
776 funding_tx_hex: funding_tx.map(|t| serialize_hex(t)),
777 }
778 }
779
780 pub fn from_state<G>(state: &bark::persist::models::StoredRoundState<G>) -> Self {
783 let status = match state.state().flow_kind() {
784 RoundFlowKind::AwaitingConfirmations => {
785 bark::round::RoundStatus::Unconfirmed {
786 funding_txid: state.state().funding_tx()
787 .expect("finished rounds have a funding tx")
788 .compute_txid(),
789 }
790 },
791 RoundFlowKind::Canceled => bark::round::RoundStatus::Canceled,
792 RoundFlowKind::DelegatedPending
793 | RoundFlowKind::Pending
794 | RoundFlowKind::Ongoing
795 | RoundFlowKind::Failed
796 => bark::round::RoundStatus::Pending,
797 };
798 Self::new(state, Ok(status))
799 }
800}
801
802#[derive(Serialize, Deserialize)]
803#[cfg_attr(feature = "utoipa", derive(ToSchema))]
804pub struct WalletExistsResponse {
805 pub fingerprint: Option<String>,
806}
807
808#[derive(Serialize, Deserialize)]
809#[cfg_attr(feature = "utoipa", derive(ToSchema))]
810pub struct WalletDeleteRequest {
811 pub dangerous: bool,
812 pub fingerprint: String,
813}
814
815#[derive(Serialize, Deserialize)]
816#[cfg_attr(feature = "utoipa", derive(ToSchema))]
817pub struct WalletDeleteResponse {
818 pub deleted: bool,
819 pub fingerprint: Option<String>,
820 pub message: String,
821}