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 MailboxSyncResponse {
99 pub checkpoint: u64,
102}
103
104#[derive(Serialize, Deserialize)]
105#[cfg_attr(feature = "utoipa", derive(ToSchema))]
106pub struct CreateWalletRequest {
107 pub ark_server: Option<String>,
110 pub ark_server_access_token: Option<String>,
112 pub chain_source: Option<ChainSourceConfig>,
115 pub mnemonic: Option<String>,
117 pub network: BarkNetwork,
119 pub birthday_height: Option<u32>,
121}
122
123#[derive(Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
125#[serde(rename_all = "kebab-case")]
126#[cfg_attr(feature = "utoipa", derive(ToSchema))]
127pub enum BarkNetwork {
128 Mainnet,
130 Signet,
132 Mutinynet,
134 Regtest,
136}
137
138#[derive(Serialize, Deserialize)]
139#[serde(rename_all = "kebab-case")]
140#[cfg_attr(feature = "utoipa", derive(ToSchema))]
141pub enum ChainSourceConfig {
142 Bitcoind {
144 bitcoind: String,
145 bitcoind_auth: BitcoindAuth,
146 },
147 Esplora {
149 url: String,
150 },
151}
152
153#[derive(Serialize, Deserialize)]
154#[serde(rename_all = "kebab-case")]
155#[cfg_attr(feature = "utoipa", derive(ToSchema))]
156pub enum BitcoindAuth {
157 Cookie {
159 cookie: String,
160 },
161 UserPass {
163 user: String,
164 pass: String,
165 },
166}
167
168#[derive(Serialize, Deserialize)]
169#[cfg_attr(feature = "utoipa", derive(ToSchema))]
170pub struct CreateWalletResponse {
171 pub fingerprint: String,
172}
173
174#[derive(Serialize, Deserialize)]
175#[cfg_attr(feature = "utoipa", derive(ToSchema))]
176pub struct ConnectedResponse {
177 pub connected: bool,
179}
180
181#[derive(Serialize, Deserialize)]
182#[cfg_attr(feature = "utoipa", derive(ToSchema))]
183pub struct ArkAddressResponse {
184 #[cfg_attr(feature = "utoipa", schema(value_type = String))]
185 pub address: String,
186}
187
188#[derive(Serialize, Deserialize)]
193#[cfg_attr(feature = "utoipa", derive(ToSchema))]
194pub struct EncodedVtxoResponse {
195 pub encoded: crate::primitives::EncodedVtxo,
197}
198
199#[derive(Serialize, Deserialize)]
200#[cfg_attr(feature = "utoipa", derive(ToSchema))]
201pub struct VtxosQuery {
202 pub all: Option<bool>,
204}
205
206#[derive(Serialize, Deserialize)]
207#[cfg_attr(feature = "utoipa", derive(ToSchema))]
208pub struct RefreshRequest {
209 pub vtxos: Vec<String>,
214}
215
216#[derive(Serialize, Deserialize)]
217#[cfg_attr(feature = "utoipa", derive(ToSchema))]
218pub struct BoardRequest {
219 pub amount_sat: u64,
223}
224
225#[derive(Serialize, Deserialize)]
226#[cfg_attr(feature = "utoipa", derive(ToSchema))]
227pub struct SendRequest {
228 pub destination: String,
230 pub amount_sat: Option<u64>,
234 pub comment: Option<String>,
236}
237
238#[derive(Serialize, Deserialize)]
239#[cfg_attr(feature = "utoipa", derive(ToSchema))]
240pub struct SendResponse {
241 pub message: String,
243}
244
245#[derive(Serialize, Deserialize)]
246#[cfg_attr(feature = "utoipa", derive(ToSchema))]
247pub struct SendOnchainRequest {
248 pub destination: String,
250 pub amount_sat: u64,
254}
255
256#[derive(Serialize, Deserialize)]
257#[cfg_attr(feature = "utoipa", derive(ToSchema))]
258pub struct OffboardVtxosRequest {
259 pub address: Option<String>,
261 pub vtxos: Vec<String>,
265}
266
267#[derive(Serialize, Deserialize)]
268#[cfg_attr(feature = "utoipa", derive(ToSchema))]
269pub struct OffboardAllRequest {
270 pub address: Option<String>,
272}
273
274#[derive(Serialize, Deserialize)]
275#[cfg_attr(feature = "utoipa", derive(ToSchema))]
276pub struct ImportVtxoRequest {
277 pub vtxos: Vec<String>,
279}
280
281#[derive(Serialize, Deserialize)]
282#[cfg_attr(feature = "utoipa", derive(ToSchema))]
283pub struct LightningInvoiceRequest {
284 pub amount_sat: u64,
288 #[serde(default, skip_serializing_if = "Option::is_none")]
290 pub description: Option<String>,
291}
292
293#[derive(Serialize, Deserialize)]
294#[cfg_attr(feature = "utoipa", derive(ToSchema))]
295pub struct LightningPayRequest {
296 pub destination: String,
298 pub amount_sat: Option<u64>,
303 pub comment: Option<String>,
305}
306
307#[derive(Serialize, Deserialize)]
308#[cfg_attr(feature = "utoipa", derive(ToSchema))]
309pub struct LightningPayResponse {
310 pub message: String,
312}
313
314#[derive(Serialize, Deserialize)]
315#[cfg_attr(feature = "utoipa", derive(ToSchema))]
316pub struct OnchainSendRequest {
317 pub destination: String,
319 pub amount_sat: u64,
321}
322
323#[derive(Serialize, Deserialize)]
324#[cfg_attr(feature = "utoipa", derive(ToSchema))]
325pub struct OnchainSendManyRequest {
326 pub destinations: Vec<String>,
328 pub immediate: Option<bool>,
330}
331
332#[derive(Serialize, Deserialize)]
333#[cfg_attr(feature = "utoipa", derive(ToSchema))]
334pub struct OnchainDrainRequest {
335 pub destination: String,
337}
338
339#[derive(Serialize, Deserialize)]
340#[cfg_attr(feature = "utoipa", derive(ToSchema))]
341pub struct ExitStatusRequest {
342 pub history: Option<bool>,
344 pub transactions: Option<bool>,
346}
347
348#[derive(Serialize, Deserialize)]
349#[cfg_attr(feature = "utoipa", derive(ToSchema))]
350pub struct ExitStartRequest {
351 pub vtxos: Vec<String>,
353}
354
355#[derive(Serialize, Deserialize)]
356#[cfg_attr(feature = "utoipa", derive(ToSchema))]
357pub struct ExitStartResponse {
358 pub message: String,
359}
360
361#[derive(Serialize, Deserialize)]
362#[cfg_attr(feature = "utoipa", derive(ToSchema))]
363pub struct ExitProgressRequest {
364 pub wait: Option<bool>,
366 pub fee_rate: Option<u64>,
368}
369
370#[derive(Serialize, Deserialize)]
371#[cfg_attr(feature = "utoipa", derive(ToSchema))]
372pub struct ExitClaimAllRequest {
373 pub destination: String,
375 pub fee_rate: Option<u64>,
377}
378
379#[derive(Serialize, Deserialize)]
380#[cfg_attr(feature = "utoipa", derive(ToSchema))]
381pub struct ExitClaimVtxosRequest {
382 pub destination: String,
384 pub vtxos: Vec<String>,
386 pub fee_rate: Option<u64>,
388}
389
390#[derive(Serialize, Deserialize)]
391#[cfg_attr(feature = "utoipa", derive(ToSchema))]
392pub struct ExitClaimResponse {
393 pub message: String,
394}
395
396
397#[derive(Serialize, Deserialize)]
398#[cfg_attr(feature = "utoipa", derive(ToSchema))]
399pub struct VtxoRequestInfo {
400 #[serde(rename = "amount_sat", with = "bitcoin::amount::serde::as_sat")]
401 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
402 pub amount: Amount,
403 #[cfg_attr(feature = "utoipa", schema(value_type = String))]
404 pub policy_type: VtxoPolicyKind,
405 #[cfg_attr(feature = "utoipa", schema(value_type = String))]
406 pub user_pubkey: PublicKey,
407}
408
409impl<'a> From<&'a ark::VtxoRequest> for VtxoRequestInfo {
410 fn from(v: &'a ark::VtxoRequest) -> Self {
411 Self {
412 amount: v.amount,
413 policy_type: v.policy.policy_type(),
414 user_pubkey: v.policy.user_pubkey(),
415 }
416 }
417}
418
419#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Deserialize, Serialize)]
420#[cfg_attr(feature = "utoipa", derive(ToSchema))]
421pub struct OffboardRequestInfo {
422 pub script_pubkey_hex: String,
424 pub script_pubkey_asm: String,
426 #[serde(rename = "net_amount_sat", with = "bitcoin::amount::serde::as_sat")]
428 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
429 pub net_amount: Amount,
430 pub deduct_fees_from_gross_amount: bool,
432 #[serde(rename = "fee_rate_kwu")]
434 #[cfg_attr(feature = "utoipa", schema(value_type = u64))]
435 pub fee_rate: FeeRate,
436}
437
438impl<'a> From<&'a OffboardRequest> for OffboardRequestInfo {
439 fn from(v: &'a OffboardRequest) -> Self {
440 Self {
441 script_pubkey_hex: v.script_pubkey.to_hex_string(),
442 script_pubkey_asm: v.script_pubkey.to_asm_string(),
443 net_amount: v.net_amount,
444 deduct_fees_from_gross_amount: v.deduct_fees_from_gross_amount,
445 fee_rate: v.fee_rate,
446 }
447 }
448}
449
450#[derive(Serialize, Deserialize)]
451#[cfg_attr(feature = "utoipa", derive(ToSchema))]
452pub struct RoundParticipationInfo {
453 #[cfg_attr(feature = "utoipa", schema(value_type = Vec<String>))]
454 pub inputs: Vec<VtxoId>,
455 pub outputs: Vec<VtxoRequestInfo>,
456}
457
458impl<'a> From<&'a bark::round::RoundParticipation> for RoundParticipationInfo {
459 fn from(v: &'a bark::round::RoundParticipation) -> Self {
460 Self {
461 inputs: v.inputs.iter().map(|v| v.id()).collect(),
462 outputs: v.outputs.iter().map(Into::into).collect(),
463 }
464 }
465}
466
467#[derive(Serialize, Deserialize)]
468#[cfg_attr(feature = "utoipa", derive(ToSchema))]
469pub struct PendingRoundInfo {
470 pub id: u32,
472 pub status: RoundStatus,
474 pub participation: RoundParticipationInfo,
476 #[cfg_attr(feature = "utoipa", schema(value_type = String, nullable = true))]
477 pub unlock_hash: Option<UnlockHash>,
478 #[cfg_attr(feature = "utoipa", schema(value_type = String, nullable = true))]
480 pub funding_txid: Option<Txid>,
481 pub funding_tx_hex: Option<String>,
482}
483
484impl PendingRoundInfo {
485 pub fn new<'a>(
486 state: &'a bark::persist::models::StoredRoundState,
487 sync_result: anyhow::Result<bark::round::RoundStatus>,
488 ) -> Self {
489 let funding_tx = state.state().funding_tx();
490 Self {
491 id: state.id().0,
492 status: match sync_result {
493 Ok(status) => status.into(),
494 Err(e) => RoundStatus::SyncError {
495 error: format!("{:#}", e),
496 },
497 },
498 participation: state.state().participation().into(),
499 unlock_hash: state.state().unlock_hash(),
500 funding_txid: funding_tx.map(|t| t.compute_txid()),
501 funding_tx_hex: funding_tx.map(|t| serialize_hex(t)),
502 }
503 }
504}
505
506#[derive(Serialize, Deserialize)]
507#[cfg_attr(feature = "utoipa", derive(ToSchema))]
508pub struct WalletExistsResponse {
509 pub fingerprint: Option<String>,
510}
511
512#[derive(Serialize, Deserialize)]
513#[cfg_attr(feature = "utoipa", derive(ToSchema))]
514pub struct WalletDeleteRequest {
515 pub dangerous: bool,
516 pub fingerprint: String,
517}
518
519#[derive(Serialize, Deserialize)]
520#[cfg_attr(feature = "utoipa", derive(ToSchema))]
521pub struct WalletDeleteResponse {
522 pub deleted: bool,
523 pub message: String,
524}
525