Skip to main content

bark_json/
web.rs

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/// Query parameters for filtering wallet history by payment method.
21///
22/// Both fields are optional but must be supplied together: omit both to get the
23/// full history, or provide both to filter by a single payment method. The pair
24/// mirrors the serialized form of a payment method (its `type` tag and `value`).
25#[derive(Default, Serialize, Deserialize)]
26#[cfg_attr(feature = "utoipa", derive(ToSchema))]
27pub struct HistoryQuery {
28	/// The payment method type tag to filter by, e.g. `ark`, `bitcoin`,
29	/// `output-script`, `invoice`, `offer`, `lightning-address`, `lnurl` or
30	/// `custom`. Must be provided together with `value`.
31	#[serde(rename = "type")]
32	pub method_type: Option<String>,
33	/// The payment method value to filter by, e.g. the destination address or
34	/// invoice. Must be provided together with `type`.
35	pub value: Option<String>,
36}
37
38/// Query parameters for fee estimates that only require an amount.
39#[derive(Serialize, Deserialize)]
40#[cfg_attr(feature = "utoipa", derive(ToSchema))]
41pub struct FeeEstimateQuery {
42	/// The amount in satoshis to estimate fees for
43	pub amount_sat: u64,
44}
45
46/// Query parameters for send-onchain fee estimates.
47#[derive(Serialize, Deserialize)]
48#[cfg_attr(feature = "utoipa", derive(ToSchema))]
49pub struct SendOnchainFeeEstimateQuery {
50	/// The amount in satoshis to send
51	pub amount_sat: u64,
52	/// The destination Bitcoin address
53	pub address: String,
54}
55
56/// Query parameters for offboard-all fee estimates.
57#[derive(Serialize, Deserialize)]
58#[cfg_attr(feature = "utoipa", derive(ToSchema))]
59pub struct OffboardAllFeeEstimateQuery {
60	/// The destination Bitcoin address
61	pub address: String,
62}
63
64/// Request body for estimating the fee of offboarding a specific set of VTXOs.
65#[derive(Serialize, Deserialize)]
66#[cfg_attr(feature = "utoipa", derive(ToSchema))]
67pub struct OffboardFeeEstimateRequest {
68	/// The destination Bitcoin address. The fee depends on its script type.
69	pub address: String,
70	/// The IDs of the VTXOs to offboard. Each is offboarded in full.
71	pub vtxos: Vec<String>,
72}
73
74/// A fee estimate for an Ark wallet operation.
75#[derive(Serialize, Deserialize)]
76#[cfg_attr(feature = "utoipa", derive(ToSchema))]
77pub struct FeeEstimateResponse {
78	/// The total amount including fees (in satoshis)
79	#[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	/// The fee portion (in satoshis)
83	#[serde(rename = "fee_sat", with = "bitcoin::amount::serde::as_sat")]
84	#[cfg_attr(feature = "utoipa", schema(value_type = u64))]
85	pub fee: Amount,
86	/// The amount excluding fees (in satoshis). For sends, this is the amount
87	/// the recipient receives. For receives, this is the amount the user gets.
88	#[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	/// The VTXOs that would be spent for this operation
92	#[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/// Query parameters for emergency (unilateral) exit fee estimates.
108#[derive(Serialize, Deserialize)]
109#[cfg_attr(feature = "utoipa", derive(ToSchema))]
110pub struct EmergencyExitFeeEstimateQuery {
111	/// Comma-separated VTXO ids to estimate the exit for. When omitted, every spendable VTXO in
112	/// the wallet is used (i.e. exit the entire wallet).
113	pub vtxo_ids: Option<String>,
114	/// The fee rate to price the estimate at, in sat/vB. Applied to both the broadcast and claim
115	/// legs. When omitted, the broadcast leg uses the current `fast` rate and the claim leg the
116	/// `regular` rate.
117	pub fee_rate_sat_per_vb: Option<u64>,
118	/// The destination address for the claim. Only affects the claim-fee weight; when omitted a
119	/// placeholder of the configured network is used.
120	pub destination: Option<String>,
121}
122
123/// A fee breakdown for unilaterally (emergency) exiting a set of VTXOs.
124#[derive(Debug, Clone, Serialize, Deserialize)]
125#[cfg_attr(feature = "utoipa", derive(ToSchema))]
126pub struct EmergencyExitFeeEstimateResponse {
127	/// The CPFP fees to broadcast every not-yet-confirmed exit transaction (in satoshis). Paid now
128	/// from confirmed on-chain funds.
129	#[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	/// The fee for the single batched transaction that drains the matured exit outputs (in
133	/// satoshis). Paid later out of the recovered value.
134	#[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	/// The sum of the broadcast and claim fees (in satoshis).
138	#[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	/// The fee rate the exit-broadcast leg was priced at (sat/vB). Unless an explicit fee rate was
142	/// supplied, the claim leg is priced separately at the chain's `regular` rate.
143	pub fee_rate_sat_per_vb: u64,
144	/// The number of exit transactions that still need to be broadcast and CPFP-bumped.
145	pub txs_to_broadcast: usize,
146	/// Whether the wallet's current on-chain balance covers the full serial exit-broadcast walk.
147	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/// Mempool fee rates for on-chain transactions.
164#[derive(Serialize, Deserialize)]
165#[cfg_attr(feature = "utoipa", derive(ToSchema))]
166pub struct OnchainFeeRatesResponse {
167	/// Fee rate targeting ~1 block confirmation (sat/vB)
168	pub fast_sat_per_vb: u64,
169	/// Fee rate targeting ~3 block confirmation (sat/vB)
170	pub regular_sat_per_vb: u64,
171	/// Fee rate targeting ~6 block confirmation (sat/vB)
172	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	/// The mailbox checkpoint (tip) the wallet has consumed up to after
186	/// the sync. Monotonically non-decreasing across successful syncs.
187	pub checkpoint: u64,
188}
189
190#[derive(Serialize, Deserialize)]
191#[cfg_attr(feature = "utoipa", derive(ToSchema))]
192pub struct CreateWalletRequest {
193	/// The Ark server to use for the wallet.
194	/// Optional when a config.toml already exists in the datadir.
195	pub ark_server: Option<String>,
196	/// An access token for a private Ark server.
197	///
198	/// **Deprecated**: access tokens are no longer enforced by the server;
199	/// this field will be removed in a future release.
200	#[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	/// The chain source to use for the wallet.
206	/// Optional when a config.toml already exists in the datadir.
207	pub chain_source: Option<ChainSourceConfig>,
208	/// The optional mnemonic to use for the wallet
209	pub mnemonic: Option<String>,
210	/// The network to use for the wallet
211	pub network: BarkNetwork,
212	/// An optional birthday height to start syncing the wallet from
213	pub birthday_height: Option<u32>,
214	/// Proceed even if the datadir contains unexpected files
215	#[serde(default)]
216	pub force: bool,
217}
218
219/// Networks bark can be used on
220#[derive(Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
221#[serde(rename_all = "kebab-case")]
222#[cfg_attr(feature = "utoipa", derive(ToSchema))]
223pub enum BarkNetwork {
224	/// Bitcoin's mainnet
225	Mainnet,
226	/// The official Bitcoin Core signet
227	Signet,
228	/// Mutinynet
229	Mutinynet,
230	/// Any regtest network
231	Regtest,
232}
233
234#[derive(Serialize, Deserialize)]
235#[serde(rename_all = "kebab-case")]
236#[cfg_attr(feature = "utoipa", derive(ToSchema))]
237pub enum ChainSourceConfig {
238	/// Use a bitcoind RPC server
239	Bitcoind {
240		bitcoind: String,
241		bitcoind_auth: BitcoindAuth,
242	},
243	/// Use an Esplora HTTP server
244	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	/// Use a cookie file for authentication
254	Cookie {
255		cookie: String,
256	},
257	/// Use a username and password for authentication
258	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	/// Whether the wallet is currently connected to its Ark server
274	pub connected: bool,
275}
276
277#[derive(Serialize, Deserialize)]
278#[cfg_attr(feature = "utoipa", derive(ToSchema))]
279pub struct MnemonicResponse {
280	/// The BIP-39 mnemonic phrase backing the wallet.
281	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/// Request to build a BIP 321 unified payment URI.
292///
293/// An Ark address is always included. A BOLT11 invoice is only included when
294/// `amount_sat` is given (an amount is required to create one). An on-chain
295/// address is included only when `onchain` is `true`.
296#[derive(Serialize, Deserialize)]
297#[cfg_attr(feature = "utoipa", derive(ToSchema))]
298pub struct Bip321UriRequest {
299	/// Optional amount (in satoshis) to request. When set, it is embedded in
300	/// the URI and used to create the BOLT11 invoice. Any server-configured
301	/// [LightningReceiveFees](crate::cli::fees::LightningReceiveFees) are
302	/// deducted from the amount the client ultimately receives over Lightning.
303	#[serde(default, skip_serializing_if = "Option::is_none")]
304	pub amount_sat: Option<u64>,
305	/// Whether to include a fresh on-chain address as a payment destination.
306	/// Defaults to `false`.
307	#[serde(default, skip_serializing_if = "Option::is_none")]
308	pub onchain: Option<bool>,
309	/// Optional label describing the payment, recorded in the URI's `label`.
310	#[serde(default, skip_serializing_if = "Option::is_none")]
311	pub label: Option<String>,
312	/// Optional message describing the payment, recorded in the URI's `message`.
313	#[serde(default, skip_serializing_if = "Option::is_none")]
314	pub message: Option<String>,
315}
316
317/// Query parameters for building a BIP 321 URI.
318#[derive(Serialize, Deserialize)]
319#[cfg_attr(feature = "utoipa", derive(ToSchema))]
320pub struct Bip321UriQuery {
321	/// Whether to upper-case the returned `bip321` URI so QR encoders can use
322	/// the compact alphanumeric mode. Defaults to `false`.
323	/// Requesting an upper-case URI fails when it carries case-sensitive data
324	/// (a label or message with lowercase characters, or base58 address) that
325	/// cannot be upper-cased.
326	pub uppercase: Option<bool>,
327}
328
329/// A BIP 321 unified payment URI together with its individual destinations.
330///
331/// The `bip321` field is the combined `bitcoin:` URI; the other fields expose
332/// each generated destination separately for convenience. A field is `null`
333/// when that destination was not requested or could not be produced.
334#[derive(Serialize, Deserialize)]
335#[cfg_attr(feature = "utoipa", derive(ToSchema))]
336pub struct Bip321UriResponse {
337	/// The generated Ark address, if any.
338	#[serde(skip_serializing_if = "Option::is_none")]
339	pub ark: Option<String>,
340	/// The generated BOLT11 invoice, included only when an amount was given.
341	#[serde(skip_serializing_if = "Option::is_none")]
342	pub bolt11: Option<String>,
343	/// The generated on-chain address, included only when `onchain` was set.
344	#[serde(skip_serializing_if = "Option::is_none")]
345	pub onchain: Option<String>,
346	/// The combined BIP 321 `bitcoin:` URI.
347	pub bip321: String,
348}
349
350/// Response for the encoded-VTXO endpoint.
351///
352/// Wraps the hex-encoded VTXO in a named field so clients can easily
353/// extract it.
354#[derive(Serialize, Deserialize)]
355#[cfg_attr(feature = "utoipa", derive(ToSchema))]
356pub struct EncodedVtxoResponse {
357	/// Hex-encoded serialized VTXO.
358	pub encoded: crate::primitives::EncodedVtxo,
359}
360
361#[derive(Serialize, Deserialize)]
362#[cfg_attr(feature = "utoipa", derive(ToSchema))]
363pub struct VtxosQuery {
364	/// Return all VTXOs regardless of their state (including spent ones)
365	pub all: Option<bool>,
366}
367
368#[derive(Serialize, Deserialize)]
369#[cfg_attr(feature = "utoipa", derive(ToSchema))]
370pub struct RefreshRequest {
371	/// List of VTXO IDs to refresh. The sum of the VTXOs being refreshed must be
372	/// >= [P2TR_DUST](bitcoin_ext::P2TR_DUST). Keep in mind that fees set out in
373	/// [RefreshFees](crate::cli::fees::RefreshFees) will be deducted from the newly created VTXO, this
374	/// value must also be >= [P2TR_DUST](bitcoin_ext::P2TR_DUST).
375	pub vtxos: Vec<String>,
376}
377
378#[derive(Serialize, Deserialize)]
379#[cfg_attr(feature = "utoipa", derive(ToSchema))]
380pub struct DelegatedRefreshRequest {
381	/// List of VTXO IDs to refresh. The sum of the VTXOs being refreshed must be
382	/// >= [P2TR_DUST](bitcoin_ext::P2TR_DUST). Keep in mind that fees set out in
383	/// [RefreshFees](crate::cli::fees::RefreshFees) will be deducted from the newly created VTXO, this
384	/// value must also be >= [P2TR_DUST](bitcoin_ext::P2TR_DUST).
385	pub vtxos: Vec<String>,
386	/// Optional block height to schedule the refresh at. When set, the refresh fee is priced at
387	/// that height and the server includes the participation in the first round once the chain
388	/// tip reaches it; when omitted, the participation is eligible for the next round.
389	pub height: Option<u32>,
390}
391
392#[derive(Serialize, Deserialize)]
393#[cfg_attr(feature = "utoipa", derive(ToSchema))]
394pub struct BoardRequest {
395	/// An amount of onchain funds to board (in satoshis). For a board operation to be successful,
396	/// this value, with any server-configured [BoardFees](crate::cli::fees::BoardFees) deducted, must be
397	/// >= [P2TR_DUST](bitcoin_ext::P2TR_DUST).
398	pub amount_sat: u64,
399}
400
401#[derive(Serialize, Deserialize)]
402#[cfg_attr(feature = "utoipa", derive(ToSchema))]
403pub struct SendRequest {
404	/// The destination can be an Ark address, a BOLT11-invoice, LNURL or a lightning address
405	pub destination: String,
406	/// The amount to send (in satoshis). Optional for bolt11 invoices. Depending on the
407	/// `destination`, the wallet must contain this amount plus any fees configured by the server in
408	/// [FeeSchedule](crate::cli::fees::FeeSchedule).
409	pub amount_sat: Option<u64>,
410	/// An optional comment, only supported when paying to lightning addresses
411	pub comment: Option<String>,
412}
413
414#[derive(Serialize, Deserialize)]
415#[cfg_attr(feature = "utoipa", derive(ToSchema))]
416pub struct SendResponse {
417	/// Success message
418	pub message: String,
419	/// The payment hash, when the destination resolved to a lightning
420	/// payment. Can be used to poll the payment status.
421	#[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/// Request to sign an arbitrary message with one of the wallet's keys
427#[derive(Serialize, Deserialize)]
428#[cfg_attr(feature = "utoipa", derive(ToSchema))]
429pub struct SignMessageRequest {
430	/// The message to sign
431	pub message: String,
432	/// The Ark address to sign the message with
433	pub address: String,
434}
435
436/// Request to verify a signed message
437///
438/// Exactly one of `pubkey` and `address` must be set.
439#[derive(Serialize, Deserialize)]
440#[cfg_attr(feature = "utoipa", derive(ToSchema))]
441pub struct VerifyMessageRequest {
442	/// The message that was signed
443	pub message: String,
444	/// The BIP-340 Schnorr signature over the message digest
445	/// `SHA256("bark/message" || message)`, in hex
446	pub signature: String,
447	/// The public key to verify the signature against
448	pub pubkey: Option<String>,
449	/// The Ark address whose user public key to verify the signature against
450	pub address: Option<String>,
451}
452
453#[derive(Serialize, Deserialize)]
454#[cfg_attr(feature = "utoipa", derive(ToSchema))]
455pub struct SendOnchainRequest {
456	/// The destination Bitcoin address
457	pub destination: String,
458	/// The amount (in satoshis) to be received by `destination` onchain. Must be
459	/// >= [P2TR_DUST](bitcoin_ext::P2TR_DUST). Server-configured fees laid out in
460	/// [OffboardFees](crate::cli::fees::OffboardFees) will be added on top of this amount.
461	pub amount_sat: u64,
462}
463
464#[derive(Serialize, Deserialize)]
465#[cfg_attr(feature = "utoipa", derive(ToSchema))]
466pub struct OffboardVtxosRequest {
467	/// Optional Bitcoin address to send to. If not provided, uses the onchain wallet's address
468	pub address: Option<String>,
469	/// List of VTXO IDs to offboard. The sum of the VTXOs being refreshed must be
470	/// >= [P2TR_DUST](bitcoin_ext::P2TR_DUST) after the server-configured
471	/// [OffboardFees](crate::cli::fees::OffboardFees) are deducted.
472	pub vtxos: Vec<String>,
473}
474
475#[derive(Serialize, Deserialize)]
476#[cfg_attr(feature = "utoipa", derive(ToSchema))]
477pub struct OffboardAllRequest {
478	/// Optional Bitcoin address to send to. If not provided, uses the onchain wallet's address
479	pub address: Option<String>,
480}
481
482#[derive(Serialize, Deserialize)]
483#[cfg_attr(feature = "utoipa", derive(ToSchema))]
484pub struct ImportVtxoRequest {
485	/// Hex-encoded VTXOs to import
486	pub vtxos: Vec<String>,
487}
488
489#[derive(Serialize, Deserialize)]
490#[cfg_attr(feature = "utoipa", derive(ToSchema))]
491pub struct LightningInvoiceRequest {
492	/// The amount to create invoice for (in satoshis). This is the amount the payee will pay but
493	/// the final amount received by the client will have any server-configured
494	/// [LightningReceiveFees](crate::cli::fees::LightningReceiveFees) deducted.
495	pub amount_sat: u64,
496	/// Optional description embedded in the invoice as its memo.
497	#[serde(default, skip_serializing_if = "Option::is_none")]
498	pub description: Option<String>,
499	/// Optional lightning receive token for authentication of the claim, if
500	/// the server requires one and there are no existing spendable VTXOs to
501	/// prove ownership of.
502	#[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	/// The amount to create invoice for (in satoshis).
510	pub amount_sat: u64,
511	/// Ark address that will receive the claimed VTXO.
512	pub address: String,
513	/// Optional description embedded in the invoice as its memo.
514	#[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	/// The invoice, offer, or lightning address to pay
522	pub destination: String,
523	/// The amount to send (in satoshis). Optional for bolt11 invoices with amount. This must be
524	/// higher than the minimum fee laid out in server-configured
525	/// [LightningSendFees](crate::cli::fees::LightningSendFees). The wallet must also contain enough
526	/// funds to cover the amount plus any fees.
527	pub amount_sat: Option<u64>,
528	/// An optional comment, only supported when paying to lightning addresses
529	pub comment: Option<String>,
530}
531
532#[derive(Serialize, Deserialize)]
533#[cfg_attr(feature = "utoipa", derive(ToSchema))]
534pub struct LightningPayResponse {
535	/// Success message
536	pub message: String,
537	/// The payment hash of the lightning payment. Can be used to poll the
538	/// payment status.
539	#[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	/// The destination Bitcoin address
548	pub destination: String,
549	/// The amount to send (in satoshis)
550	pub amount_sat: u64,
551}
552
553#[derive(Serialize, Deserialize)]
554#[cfg_attr(feature = "utoipa", derive(ToSchema))]
555pub struct OnchainSendManyRequest {
556	/// List of destinations in format "address:amount"
557	pub destinations: Vec<String>,
558	/// Sends the transaction immediately instead of waiting
559	pub immediate: Option<bool>,
560}
561
562#[derive(Serialize, Deserialize)]
563#[cfg_attr(feature = "utoipa", derive(ToSchema))]
564pub struct OnchainDrainRequest {
565	/// The destination Bitcoin address
566	pub destination: String,
567}
568
569#[derive(Serialize, Deserialize)]
570#[cfg_attr(feature = "utoipa", derive(ToSchema))]
571pub struct ExitStatusRequest {
572	/// Whether to include the detailed history of the exit process
573	pub history: Option<bool>,
574	/// Whether to include the exit transactions and their CPFP children
575	pub transactions: Option<bool>,
576}
577
578#[derive(Serialize, Deserialize)]
579#[cfg_attr(feature = "utoipa", derive(ToSchema))]
580pub struct ExitStartRequest {
581	/// The ID of VTXOs to unilaterally exit
582	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	/// Wait until the exit is completed
595	pub wait: Option<bool>,
596	/// Sets the desired fee-rate in sats/kvB to use broadcasting exit transactions
597	pub fee_rate: Option<u64>,
598}
599
600#[derive(Serialize, Deserialize)]
601#[cfg_attr(feature = "utoipa", derive(ToSchema))]
602pub struct ExitClaimAllRequest {
603	/// The destination Bitcoin address
604	pub destination: String,
605	/// Sets the desired fee-rate in sats/kvB to use broadcasting exit transactions
606	pub fee_rate: Option<u64>,
607}
608
609#[derive(Serialize, Deserialize)]
610#[cfg_attr(feature = "utoipa", derive(ToSchema))]
611pub struct ExitClaimVtxosRequest {
612	/// The destination Bitcoin address
613	pub destination: String,
614	/// The ID of an exited VTXO to be claimed
615	pub vtxos: Vec<String>,
616	/// Sets the desired fee-rate in sats/kvB to use broadcasting exit transactions
617	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	/// hexadecimal representation of the output script
659	pub script_pubkey_hex: String,
660	/// opcode representation of the output script
661	pub script_pubkey_asm: String,
662	/// The target amount in sats.
663	#[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	/// Determines whether fees should be added onto the given amount or deducted from it.
667	pub deduct_fees_from_gross_amount: bool,
668	/// What fee rate was used when calculating the fee for the offboard.
669	#[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/// Lifecycle phase of a round participation.
704#[derive(Serialize, Deserialize)]
705#[cfg_attr(feature = "utoipa", derive(ToSchema))]
706#[serde(rename_all = "kebab-case")]
707pub enum RoundFlowState {
708	/// Delegated participation waiting for its round.
709	DelegatedPending,
710	/// Interactive participation waiting for its round.
711	Pending,
712	/// The interactive part is being played out with the server.
713	Ongoing,
714	/// The round finished and its funding tx is waiting for confirmations.
715	AwaitingConfirmations,
716	/// The participation failed.
717	Failed,
718	/// The user canceled the participation.
719	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	/// Unique identifier for the round
739	pub id: u32,
740	/// the current status of the round
741	pub status: RoundStatus,
742	/// Lifecycle phase of the participation
743	pub state: RoundFlowState,
744	/// the round participation details
745	pub participation: RoundParticipationInfo,
746	#[cfg_attr(feature = "utoipa", schema(value_type = String, nullable = true))]
747	pub unlock_hash: Option<UnlockHash>,
748	/// The block height a delegated participation is scheduled for, if any
749	#[serde(default)]
750	pub scheduled_height: Option<u32>,
751	/// The round transaction id, if already assigned
752	#[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	/// Like [PendingRoundInfo::new], but without contacting the server: the
781	/// status is derived from the stored state alone.
782	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}