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;
12
13#[cfg(feature = "utoipa")]
14use utoipa::ToSchema;
15
16use crate::cli::RoundStatus;
17
18
19#[derive(Default, Serialize, Deserialize)]
25#[cfg_attr(feature = "utoipa", derive(ToSchema))]
26pub struct HistoryQuery {
27 #[serde(rename = "type")]
31 pub method_type: Option<String>,
32 pub value: Option<String>,
35}
36
37#[derive(Serialize, Deserialize)]
39#[cfg_attr(feature = "utoipa", derive(ToSchema))]
40pub struct FeeEstimateQuery {
41 pub amount_sat: u64,
43}
44
45#[derive(Serialize, Deserialize)]
47#[cfg_attr(feature = "utoipa", derive(ToSchema))]
48pub struct SendOnchainFeeEstimateQuery {
49 pub amount_sat: u64,
51 pub address: String,
53}
54
55#[derive(Serialize, Deserialize)]
57#[cfg_attr(feature = "utoipa", derive(ToSchema))]
58pub struct OffboardAllFeeEstimateQuery {
59 pub address: String,
61}
62
63#[derive(Serialize, Deserialize)]
65#[cfg_attr(feature = "utoipa", derive(ToSchema))]
66pub struct OffboardFeeEstimateRequest {
67 pub address: String,
69 pub vtxos: Vec<String>,
71}
72
73#[derive(Serialize, Deserialize)]
75#[cfg_attr(feature = "utoipa", derive(ToSchema))]
76pub struct FeeEstimateResponse {
77 #[serde(rename = "gross_amount_sat", with = "bitcoin::amount::serde::as_sat")]
79 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
80 pub gross_amount: Amount,
81 #[serde(rename = "fee_sat", with = "bitcoin::amount::serde::as_sat")]
83 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
84 pub fee: Amount,
85 #[serde(rename = "net_amount_sat", with = "bitcoin::amount::serde::as_sat")]
88 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
89 pub net_amount: Amount,
90 #[cfg_attr(feature = "utoipa", schema(value_type = Vec<String>))]
92 pub vtxos_spent: Vec<VtxoId>,
93}
94
95impl From<bark::FeeEstimate> for FeeEstimateResponse {
96 fn from(estimate: bark::FeeEstimate) -> Self {
97 FeeEstimateResponse {
98 gross_amount: estimate.gross_amount,
99 fee: estimate.fee,
100 net_amount: estimate.net_amount,
101 vtxos_spent: estimate.vtxos_spent,
102 }
103 }
104}
105
106#[derive(Serialize, Deserialize)]
108#[cfg_attr(feature = "utoipa", derive(ToSchema))]
109pub struct EmergencyExitFeeEstimateQuery {
110 pub vtxo_ids: Option<String>,
113 pub fee_rate_sat_per_vb: Option<u64>,
117 pub destination: Option<String>,
120}
121
122#[derive(Debug, Clone, Serialize, Deserialize)]
124#[cfg_attr(feature = "utoipa", derive(ToSchema))]
125pub struct EmergencyExitFeeEstimateResponse {
126 #[serde(rename = "exit_broadcast_fee_sat", with = "bitcoin::amount::serde::as_sat")]
129 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
130 pub exit_broadcast_fee: Amount,
131 #[serde(rename = "claim_fee_sat", with = "bitcoin::amount::serde::as_sat")]
134 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
135 pub claim_fee: Amount,
136 #[serde(rename = "total_fee_sat", with = "bitcoin::amount::serde::as_sat")]
138 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
139 pub total_fee: Amount,
140 pub fee_rate_sat_per_vb: u64,
143 pub txs_to_broadcast: usize,
145 pub fundable: bool,
147}
148
149impl From<bark::exit::ExitFeeEstimate> for EmergencyExitFeeEstimateResponse {
150 fn from(e: bark::exit::ExitFeeEstimate) -> Self {
151 EmergencyExitFeeEstimateResponse {
152 total_fee: e.total(),
153 exit_broadcast_fee: e.exit_broadcast_fee,
154 claim_fee: e.claim_fee,
155 fee_rate_sat_per_vb: e.fee_rate.to_sat_per_vb_ceil(),
156 txs_to_broadcast: e.txs_to_broadcast,
157 fundable: e.fundable,
158 }
159 }
160}
161
162#[derive(Serialize, Deserialize)]
164#[cfg_attr(feature = "utoipa", derive(ToSchema))]
165pub struct OnchainFeeRatesResponse {
166 pub fast_sat_per_vb: u64,
168 pub regular_sat_per_vb: u64,
170 pub slow_sat_per_vb: u64,
172}
173
174
175#[derive(Serialize, Deserialize)]
176#[cfg_attr(feature = "utoipa", derive(ToSchema))]
177pub struct TipResponse {
178 pub tip_height: u32,
179}
180
181#[derive(Serialize, Deserialize)]
182#[cfg_attr(feature = "utoipa", derive(ToSchema))]
183pub struct MailboxSyncResponse {
184 pub checkpoint: u64,
187}
188
189#[derive(Serialize, Deserialize)]
190#[cfg_attr(feature = "utoipa", derive(ToSchema))]
191pub struct CreateWalletRequest {
192 pub ark_server: Option<String>,
195 #[deprecated(
200 since = "0.2.4",
201 note = "access tokens are not enforced by the server; this field will be removed",
202 )]
203 pub ark_server_access_token: Option<String>,
204 pub chain_source: Option<ChainSourceConfig>,
207 pub mnemonic: Option<String>,
209 pub network: BarkNetwork,
211 pub birthday_height: Option<u32>,
213 #[serde(default)]
215 pub force: bool,
216}
217
218#[derive(Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
220#[serde(rename_all = "kebab-case")]
221#[cfg_attr(feature = "utoipa", derive(ToSchema))]
222pub enum BarkNetwork {
223 Mainnet,
225 Signet,
227 Mutinynet,
229 Regtest,
231}
232
233#[derive(Serialize, Deserialize)]
234#[serde(rename_all = "kebab-case")]
235#[cfg_attr(feature = "utoipa", derive(ToSchema))]
236pub enum ChainSourceConfig {
237 Bitcoind {
239 bitcoind: String,
240 bitcoind_auth: BitcoindAuth,
241 },
242 Esplora {
244 url: String,
245 },
246}
247
248#[derive(Serialize, Deserialize)]
249#[serde(rename_all = "kebab-case")]
250#[cfg_attr(feature = "utoipa", derive(ToSchema))]
251pub enum BitcoindAuth {
252 Cookie {
254 cookie: String,
255 },
256 UserPass {
258 user: String,
259 pass: String,
260 },
261}
262
263#[derive(Serialize, Deserialize)]
264#[cfg_attr(feature = "utoipa", derive(ToSchema))]
265pub struct CreateWalletResponse {
266 pub fingerprint: String,
267}
268
269#[derive(Serialize, Deserialize)]
270#[cfg_attr(feature = "utoipa", derive(ToSchema))]
271pub struct ConnectedResponse {
272 pub connected: bool,
274}
275
276#[derive(Serialize, Deserialize)]
277#[cfg_attr(feature = "utoipa", derive(ToSchema))]
278pub struct MnemonicResponse {
279 pub mnemonic: String,
281}
282
283#[derive(Serialize, Deserialize)]
284#[cfg_attr(feature = "utoipa", derive(ToSchema))]
285pub struct ArkAddressResponse {
286 #[cfg_attr(feature = "utoipa", schema(value_type = String))]
287 pub address: String,
288}
289
290#[derive(Serialize, Deserialize)]
296#[cfg_attr(feature = "utoipa", derive(ToSchema))]
297pub struct Bip321UriRequest {
298 #[serde(default, skip_serializing_if = "Option::is_none")]
303 pub amount_sat: Option<u64>,
304 #[serde(default, skip_serializing_if = "Option::is_none")]
307 pub onchain: Option<bool>,
308 #[serde(default, skip_serializing_if = "Option::is_none")]
310 pub label: Option<String>,
311 #[serde(default, skip_serializing_if = "Option::is_none")]
313 pub message: Option<String>,
314}
315
316#[derive(Serialize, Deserialize)]
318#[cfg_attr(feature = "utoipa", derive(ToSchema))]
319pub struct Bip321UriQuery {
320 pub uppercase: Option<bool>,
326}
327
328#[derive(Serialize, Deserialize)]
334#[cfg_attr(feature = "utoipa", derive(ToSchema))]
335pub struct Bip321UriResponse {
336 #[serde(skip_serializing_if = "Option::is_none")]
338 pub ark: Option<String>,
339 #[serde(skip_serializing_if = "Option::is_none")]
341 pub bolt11: Option<String>,
342 #[serde(skip_serializing_if = "Option::is_none")]
344 pub onchain: Option<String>,
345 pub bip321: String,
347}
348
349#[derive(Serialize, Deserialize)]
354#[cfg_attr(feature = "utoipa", derive(ToSchema))]
355pub struct EncodedVtxoResponse {
356 pub encoded: crate::primitives::EncodedVtxo,
358}
359
360#[derive(Serialize, Deserialize)]
361#[cfg_attr(feature = "utoipa", derive(ToSchema))]
362pub struct VtxosQuery {
363 pub all: Option<bool>,
365}
366
367#[derive(Serialize, Deserialize)]
368#[cfg_attr(feature = "utoipa", derive(ToSchema))]
369pub struct RefreshRequest {
370 pub vtxos: Vec<String>,
375}
376
377#[derive(Serialize, Deserialize)]
378#[cfg_attr(feature = "utoipa", derive(ToSchema))]
379pub struct DelegatedRefreshRequest {
380 pub vtxos: Vec<String>,
385 pub height: Option<u32>,
389}
390
391#[derive(Serialize, Deserialize)]
392#[cfg_attr(feature = "utoipa", derive(ToSchema))]
393pub struct BoardRequest {
394 pub amount_sat: u64,
398}
399
400#[derive(Serialize, Deserialize)]
401#[cfg_attr(feature = "utoipa", derive(ToSchema))]
402pub struct SendRequest {
403 pub destination: String,
405 pub amount_sat: Option<u64>,
409 pub comment: Option<String>,
411}
412
413#[derive(Serialize, Deserialize)]
414#[cfg_attr(feature = "utoipa", derive(ToSchema))]
415pub struct SendResponse {
416 pub message: String,
418 #[serde(default, skip_serializing_if = "Option::is_none")]
421 #[cfg_attr(feature = "utoipa", schema(value_type = Option<String>))]
422 pub payment_hash: Option<PaymentHash>,
423}
424
425#[derive(Serialize, Deserialize)]
427#[cfg_attr(feature = "utoipa", derive(ToSchema))]
428pub struct SignMessageRequest {
429 pub message: String,
431 pub address: String,
433}
434
435#[derive(Serialize, Deserialize)]
439#[cfg_attr(feature = "utoipa", derive(ToSchema))]
440pub struct VerifyMessageRequest {
441 pub message: String,
443 pub signature: String,
446 pub pubkey: Option<String>,
448 pub address: Option<String>,
450}
451
452#[derive(Serialize, Deserialize)]
453#[cfg_attr(feature = "utoipa", derive(ToSchema))]
454pub struct SendOnchainRequest {
455 pub destination: String,
457 pub amount_sat: u64,
461}
462
463#[derive(Serialize, Deserialize)]
464#[cfg_attr(feature = "utoipa", derive(ToSchema))]
465pub struct OffboardVtxosRequest {
466 pub address: Option<String>,
468 pub vtxos: Vec<String>,
472}
473
474#[derive(Serialize, Deserialize)]
475#[cfg_attr(feature = "utoipa", derive(ToSchema))]
476pub struct OffboardAllRequest {
477 pub address: Option<String>,
479}
480
481#[derive(Serialize, Deserialize)]
482#[cfg_attr(feature = "utoipa", derive(ToSchema))]
483pub struct ImportVtxoRequest {
484 pub vtxos: Vec<String>,
486}
487
488#[derive(Serialize, Deserialize)]
489#[cfg_attr(feature = "utoipa", derive(ToSchema))]
490pub struct LightningInvoiceRequest {
491 pub amount_sat: u64,
495 #[serde(default, skip_serializing_if = "Option::is_none")]
497 pub description: Option<String>,
498 #[serde(default, skip_serializing_if = "Option::is_none")]
502 pub token: Option<String>,
503}
504
505#[derive(Serialize, Deserialize)]
506#[cfg_attr(feature = "utoipa", derive(ToSchema))]
507pub struct LightningInvoiceForAddressRequest {
508 pub amount_sat: u64,
510 pub address: String,
512 #[serde(default, skip_serializing_if = "Option::is_none")]
514 pub description: Option<String>,
515}
516
517#[derive(Serialize, Deserialize)]
518#[cfg_attr(feature = "utoipa", derive(ToSchema))]
519pub struct LightningPayRequest {
520 pub destination: String,
522 pub amount_sat: Option<u64>,
527 pub comment: Option<String>,
529}
530
531#[derive(Serialize, Deserialize)]
532#[cfg_attr(feature = "utoipa", derive(ToSchema))]
533pub struct LightningPayResponse {
534 pub message: String,
536 #[serde(default, skip_serializing_if = "Option::is_none")]
539 #[cfg_attr(feature = "utoipa", schema(value_type = Option<String>))]
540 pub payment_hash: Option<PaymentHash>,
541}
542
543#[derive(Serialize, Deserialize)]
544#[cfg_attr(feature = "utoipa", derive(ToSchema))]
545pub struct OnchainSendRequest {
546 pub destination: String,
548 pub amount_sat: u64,
550}
551
552#[derive(Serialize, Deserialize)]
553#[cfg_attr(feature = "utoipa", derive(ToSchema))]
554pub struct OnchainSendManyRequest {
555 pub destinations: Vec<String>,
557 pub immediate: Option<bool>,
559}
560
561#[derive(Serialize, Deserialize)]
562#[cfg_attr(feature = "utoipa", derive(ToSchema))]
563pub struct OnchainDrainRequest {
564 pub destination: String,
566}
567
568#[derive(Serialize, Deserialize)]
569#[cfg_attr(feature = "utoipa", derive(ToSchema))]
570pub struct ExitStatusRequest {
571 pub history: Option<bool>,
573 pub transactions: Option<bool>,
575}
576
577#[derive(Serialize, Deserialize)]
578#[cfg_attr(feature = "utoipa", derive(ToSchema))]
579pub struct ExitStartRequest {
580 pub vtxos: Vec<String>,
582}
583
584#[derive(Serialize, Deserialize)]
585#[cfg_attr(feature = "utoipa", derive(ToSchema))]
586pub struct ExitStartResponse {
587 pub message: String,
588}
589
590#[derive(Serialize, Deserialize)]
591#[cfg_attr(feature = "utoipa", derive(ToSchema))]
592pub struct ExitProgressRequest {
593 pub wait: Option<bool>,
595 pub fee_rate: Option<u64>,
597}
598
599#[derive(Serialize, Deserialize)]
600#[cfg_attr(feature = "utoipa", derive(ToSchema))]
601pub struct ExitClaimAllRequest {
602 pub destination: String,
604 pub fee_rate: Option<u64>,
606}
607
608#[derive(Serialize, Deserialize)]
609#[cfg_attr(feature = "utoipa", derive(ToSchema))]
610pub struct ExitClaimVtxosRequest {
611 pub destination: String,
613 pub vtxos: Vec<String>,
615 pub fee_rate: Option<u64>,
617}
618
619#[derive(Serialize, Deserialize)]
620#[cfg_attr(feature = "utoipa", derive(ToSchema))]
621pub struct ExitClaimResponse {
622 pub message: String,
623}
624
625#[derive(Serialize, Deserialize)]
626#[cfg_attr(feature = "utoipa", derive(ToSchema))]
627pub struct ExitCancelResponse {
628 pub message: String,
629}
630
631
632#[derive(Serialize, Deserialize)]
633#[cfg_attr(feature = "utoipa", derive(ToSchema))]
634pub struct VtxoRequestInfo {
635 #[serde(rename = "amount_sat", with = "bitcoin::amount::serde::as_sat")]
636 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
637 pub amount: Amount,
638 #[cfg_attr(feature = "utoipa", schema(value_type = String))]
639 pub policy_type: VtxoPolicyKind,
640 #[cfg_attr(feature = "utoipa", schema(value_type = String))]
641 pub user_pubkey: PublicKey,
642}
643
644impl<'a> From<&'a ark::VtxoRequest> for VtxoRequestInfo {
645 fn from(v: &'a ark::VtxoRequest) -> Self {
646 Self {
647 amount: v.amount,
648 policy_type: v.policy.policy_type(),
649 user_pubkey: v.policy.user_pubkey(),
650 }
651 }
652}
653
654#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]
655#[cfg_attr(feature = "utoipa", derive(ToSchema))]
656pub struct OffboardRequestInfo {
657 pub script_pubkey_hex: String,
659 pub script_pubkey_asm: String,
661 #[serde(rename = "net_amount_sat", with = "bitcoin::amount::serde::as_sat")]
663 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
664 pub net_amount: Amount,
665 pub deduct_fees_from_gross_amount: bool,
667 #[serde(rename = "fee_rate_kwu")]
669 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
670 pub fee_rate: FeeRate,
671}
672
673impl<'a> From<&'a OffboardRequest> for OffboardRequestInfo {
674 fn from(v: &'a OffboardRequest) -> Self {
675 Self {
676 script_pubkey_hex: v.script_pubkey.to_hex_string(),
677 script_pubkey_asm: v.script_pubkey.to_asm_string(),
678 net_amount: v.net_amount,
679 deduct_fees_from_gross_amount: v.deduct_fees_from_gross_amount,
680 fee_rate: v.fee_rate,
681 }
682 }
683}
684
685#[derive(Serialize, Deserialize)]
686#[cfg_attr(feature = "utoipa", derive(ToSchema))]
687pub struct RoundParticipationInfo {
688 #[cfg_attr(feature = "utoipa", schema(value_type = Vec<String>))]
689 pub inputs: Vec<VtxoId>,
690 pub outputs: Vec<VtxoRequestInfo>,
691}
692
693impl<'a> From<&'a bark::round::RoundParticipation> for RoundParticipationInfo {
694 fn from(v: &'a bark::round::RoundParticipation) -> Self {
695 Self {
696 inputs: v.inputs.iter().map(|v| v.id()).collect(),
697 outputs: v.outputs.iter().map(Into::into).collect(),
698 }
699 }
700}
701
702#[derive(Serialize, Deserialize)]
703#[cfg_attr(feature = "utoipa", derive(ToSchema))]
704pub struct PendingRoundInfo {
705 pub id: u32,
707 pub status: RoundStatus,
709 pub participation: RoundParticipationInfo,
711 #[cfg_attr(feature = "utoipa", schema(value_type = String, nullable = true))]
712 pub unlock_hash: Option<UnlockHash>,
713 #[cfg_attr(feature = "utoipa", schema(value_type = String, nullable = true))]
715 pub funding_txid: Option<Txid>,
716 pub funding_tx_hex: Option<String>,
717}
718
719impl PendingRoundInfo {
720 pub fn new<G>(
721 state: &bark::persist::models::StoredRoundState<G>,
722 sync_result: anyhow::Result<bark::round::RoundStatus>,
723 ) -> Self {
724 let funding_tx = state.state().funding_tx();
725 Self {
726 id: state.id().0,
727 status: match sync_result {
728 Ok(status) => status.into(),
729 Err(e) => RoundStatus::SyncError {
730 error: format!("{:#}", e),
731 },
732 },
733 participation: state.state().participation().into(),
734 unlock_hash: state.state().unlock_hash(),
735 funding_txid: funding_tx.map(|t| t.compute_txid()),
736 funding_tx_hex: funding_tx.map(|t| serialize_hex(t)),
737 }
738 }
739}
740
741#[derive(Serialize, Deserialize)]
742#[cfg_attr(feature = "utoipa", derive(ToSchema))]
743pub struct WalletExistsResponse {
744 pub fingerprint: Option<String>,
745}
746
747#[derive(Serialize, Deserialize)]
748#[cfg_attr(feature = "utoipa", derive(ToSchema))]
749pub struct WalletDeleteRequest {
750 pub dangerous: bool,
751 pub fingerprint: String,
752}
753
754#[derive(Serialize, Deserialize)]
755#[cfg_attr(feature = "utoipa", derive(ToSchema))]
756pub struct WalletDeleteResponse {
757 pub deleted: bool,
758 pub message: String,
759}