bark/onchain/mod.rs
1//! Onchain wallet integration interfaces.
2//!
3//! This module defines the traits and types that an external onchain wallet must
4//! implement to be used by the library. The goal is to let integrators plug in
5//! their own wallet implementation, so features like boarding (moving onchain funds
6//! into Ark) and unilateral exit (claiming VTXOs onchain without server cooperation)
7//! are supported.
8//!
9//! Key concepts exposed here:
10//! - [Utxo], [LocalUtxo] & [SpendableExit]: lightweight types representing wallet UTXOs and
11//! spendable exit outputs.
12//! - [PreparePsbt] & [SignPsbt]: funding and signing interfaces for building transactions.
13//! - [GetBalance], [GetWalletTx], [GetSpendingTx]: read-access to wallet state for balance
14//! and [Transaction] lookups required by various parts of the library.
15//! - [MakeCpfp]: CPFP construction interfaces used for create child transactions.
16//! - [ExitUnilaterally]: a convenience trait that aggregates the required capabilities a
17//! wallet must provide to support unilateral exits.
18//!
19//! A reference implementation based on BDK is available behind the `onchain_bdk`
20//! cargo feature. Enable it to use the provided [OnchainWallet] implementation.
21//! You can use all features from BDK because [bdk_wallet] is re-exported.
22
23#[cfg(feature = "onchain_bdk")]
24mod bdk;
25
26#[cfg(feature = "onchain_bdk")]
27pub use bdk_wallet;
28
29pub use bitcoin_ext::cpfp::{CpfpError, MakeCpfpFees};
30
31/// BDK-backed onchain wallet implementation.
32///
33/// Available only when the `onchain_bdk` feature is enabled.
34#[cfg(feature = "onchain_bdk")]
35pub use crate::onchain::bdk::{OnchainWallet, TxBuilderExt};
36
37use std::sync::Arc;
38
39use bitcoin::{
40 Address, Amount, FeeRate, OutPoint, Psbt, Transaction, Txid
41};
42
43use ark::Vtxo;
44use bitcoin_ext::{BlockHeight, BlockRef};
45
46use crate::chain::ChainSource;
47
48/// Represents an onchain UTXO known to the wallet.
49///
50/// This can be either:
51/// - `Local`: a standard wallet UTXO
52/// - `Exit`: a spendable exit output produced by the Ark exit mechanism
53#[derive(Debug, Clone)]
54pub enum Utxo {
55 Local(LocalUtxo),
56 Exit(SpendableExit),
57}
58
59/// A standard wallet [Utxo] owned by the local wallet implementation.
60#[derive(Debug, Clone)]
61pub struct LocalUtxo {
62 /// The outpoint referencing the UTXO.
63 pub outpoint: OutPoint,
64 /// The amount contained in the UTXO.
65 pub amount: Amount,
66 /// Optional confirmation height; `None` if unconfirmed.
67 pub confirmation_height: Option<BlockHeight>,
68}
69
70/// A spendable unilateral exit of a [Vtxo] which can be claimed onchain.
71///
72/// When exiting unilaterally, the wallet will end up with onchain outputs that correspond to
73/// previously-held VTXOs. These can be claimed and used for further spending.
74#[derive(Debug, Clone)]
75pub struct SpendableExit {
76 /// The VTXO being exited.
77 pub vtxo: Vtxo,
78 /// The block height associated with the exits' validity window.
79 pub height: BlockHeight,
80}
81
82/// Ability to finalize a [Psbt] into a fully signed [Transaction].
83///
84/// Wallets should apply all necessary signatures and finalize inputs according
85/// to their internal key management and policies.
86#[async_trait]
87pub trait SignPsbt {
88 /// Consume a [Psbt] and return a fully signed and finalized [Transaction].
89 async fn finish_tx(&mut self, psbt: Psbt) -> anyhow::Result<Transaction>;
90}
91
92/// Ability to query the wallets' total balance.
93///
94/// This is used by higher-level flows to decide when onchain funds are available for boarding or
95/// fee bumping, and to present balance information to users.
96pub trait GetBalance {
97 /// Get the total balance of the wallet.
98 fn get_balance(&self) -> Amount;
99}
100
101/// Ability to look up transactions known to the wallet.
102///
103/// Implementations should return wallet-related transactions and, when possible,
104/// the block information those transactions confirmed in.
105pub trait GetWalletTx {
106 /// Retrieve the wallet [Transaction] for the given [Txid] if any.
107 fn get_wallet_tx(&self, txid: Txid) -> Option<Arc<Transaction>>;
108
109 /// Retrieve information about the block, if any, a given wallet transaction was confirmed in.
110 fn get_wallet_tx_confirmed_block(&self, txid: Txid) -> anyhow::Result<Option<BlockRef>>;
111}
112
113/// Ability to construct funded PSBTs for specific destinations or to drain the wallet.
114///
115/// These methods are used to build transactions for boarding, exits, and fee bumping.
116pub trait PreparePsbt {
117 /// Prepare a [Transaction] which will send to the given destinations.
118 fn prepare_tx(
119 &mut self,
120 destinations: &[(Address, Amount)],
121 fee_rate: FeeRate,
122 ) -> anyhow::Result<Psbt>;
123
124 /// Prepare a [Transaction] for sending all wallet funds to the given destination.
125 fn prepare_drain_tx(
126 &mut self,
127 destination: Address,
128 fee_rate: FeeRate,
129 ) -> anyhow::Result<Psbt>;
130}
131
132/// Ability to find wallet-local spends of a specific [OutPoint].
133///
134/// This helps identify if the wallet has already spent an exit or parent [Transaction].
135pub trait GetSpendingTx {
136 /// This should search the wallet and look for any [Transaction] that spends the given
137 /// [OutPoint]. The intent of the function is to only look at spends which happen in the wallet
138 /// itself.
139 fn get_spending_tx(&self, outpoint: OutPoint) -> Option<Arc<Transaction>>;
140}
141
142/// Ability to create and persist CPFP transactions for spending P2A outputs.
143#[async_trait]
144pub trait MakeCpfp {
145 /// Creates a signed Child Pays for Parent (CPFP) transaction using a Pay-to-Anchor (P2A) output
146 /// to broadcast unilateral exits and other TRUC transactions.
147 ///
148 /// For more information please see [BIP431](https://github.com/bitcoin/bips/blob/master/bip-0431.mediawiki#topologically-restricted-until-confirmation).
149 ///
150 /// # Arguments
151 ///
152 /// * `tx` - A parent `Transaction` that is guaranteed to have one P2A output which
153 /// implementations must spend so that both the parent and child transactions can be
154 /// broadcast to the network as a v3 transaction package.
155 /// * `fees` - Informs the implementation how fees should be paid by the child transaction. Note
156 /// that an effective fee rate should be calculated using the weight of both the
157 /// parent and child transactions.
158 ///
159 /// # Returns
160 ///
161 /// Returns a `Result` containing:
162 /// * `Transaction` - The signed CPFP transaction ready to be broadcasted to the network with
163 /// the given parent transaction if construction and signing were successful.
164 /// * `CpfpError` - An error indicating the reason for failure in constructing the CPFP
165 /// transaction (e.g., insufficient funds, invalid parent transaction, or
166 /// signing failure).
167 fn make_signed_p2a_cpfp(
168 &mut self,
169 tx: &Transaction,
170 fees: MakeCpfpFees,
171 ) -> Result<Transaction, CpfpError>;
172
173 /// Persist the signed CPFP transaction so it can be rebroadcast or retrieved as needed.
174 async fn store_signed_p2a_cpfp(&mut self, tx: &Transaction) -> anyhow::Result<(), CpfpError>;
175}
176
177/// Trait alias for wallets that support boarding.
178///
179/// Any wallet type implementing these component traits automatically implements
180/// `Board`. The trait requires Send + Sync because boarding flows may be
181/// executed from async tasks and across threads.
182///
183/// Required capabilities:
184/// - [SignPsbt]: to finalize transactions
185/// - [GetWalletTx]: to query related transactions and their confirmations
186/// - [PreparePsbt]: to prepare transactions for boarding
187pub trait Board: PreparePsbt + SignPsbt + GetWalletTx + Send + Sync {}
188
189impl <W: PreparePsbt + SignPsbt + GetWalletTx + Send + Sync> Board for W {}
190
191/// Trait alias for wallets that support unilateral exit end-to-end.
192///
193/// Any wallet type implementing these component traits automatically implements
194/// `ExitUnilaterally`. The trait requires Send + Sync because exit flows may be
195/// executed from async tasks and across threads.
196///
197/// Required capabilities:
198/// - [GetBalance]: to evaluate available funds
199/// - [GetWalletTx]: to query related transactions and their confirmations
200/// - [MakeCpfp]: to accelerate slow/pinned exits
201/// - [SignPsbt]: to finalize transactions
202/// - [GetSpendingTx]: to detect local spends relevant to exit coordination
203pub trait ExitUnilaterally:
204 GetBalance +
205 GetWalletTx +
206 MakeCpfp +
207 SignPsbt +
208 GetSpendingTx +
209 Send + Sync + {}
210
211impl <W: GetBalance +
212 GetWalletTx +
213 MakeCpfp +
214 SignPsbt +
215 GetSpendingTx +
216 Send + Sync> ExitUnilaterally for W {}
217
218/// Ability to sync the wallet with the onchain network.
219#[async_trait]
220pub trait ChainSync {
221 /// Sync the wallet with the onchain network.
222 async fn sync(&mut self, chain: &ChainSource) -> anyhow::Result<()>;
223}
224
225/// Trait that covers the requirements to use an onchain wallet with
226/// [Wallet::run_daemon](crate::Wallet::run_daemon).
227pub trait DaemonizableOnchainWallet: ExitUnilaterally + ChainSync {}
228impl <W: ExitUnilaterally + ChainSync> DaemonizableOnchainWallet for W {}