Overview
Bark supports multiple payment types:
- Arkoor Payments: Fast offchain payments between Ark users
- Lightning Payments: Pay Lightning invoices from your Ark balance
- Onchain Payments: Send to Bitcoin addresses using
send_onchain
Address Generation
new_address
Generate a new Ark address to receive payments.
pub async fn new_address(&self) -> anyhow::Result<ark::Address>
A new mailbox-based Ark address for receiving payments
Example:
let address = wallet.new_address().await?;
println!("Send to: {}", address);
new_address_with_index
Generate a new address and return the derivation index.
pub async fn new_address_with_index(&self) -> anyhow::Result<(ark::Address, u32)>
Returns
Result<(ark::Address, u32)>
Tuple of the address and its derivation index
peak_address
Get the address at a specific index without deriving a new one.
pub async fn peak_address(&self, index: u32) -> anyhow::Result<ark::Address>
The derivation index to peek at
Arkoor Payments
Arkoor payments are instant, out-of-round transfers between Ark users.
send_arkoor_payment
Send an instant Ark payment to an Ark address.
pub async fn send_arkoor_payment(
&self,
destination: &ark::Address,
amount: Amount,
) -> anyhow::Result<Vec<Vtxo>>
The VTXOs created for the recipient
Example:
use bitcoin::Amount;
// Get recipient's address
let recipient_addr = ark::Address::from_str("ark1...")?.assume_checked();
// Send payment
let vtxos = wallet.send_arkoor_payment(
&recipient_addr,
Amount::from_sat(10_000)
).await?;
println!("Sent {} VTXOs to recipient", vtxos.len());
Arkoor payments are instant and don’t require waiting for rounds. Change VTXOs may be created.
validate_arkoor_address
Validate an Ark address before sending.
pub async fn validate_arkoor_address(&self, address: &ark::Address) -> anyhow::Result<()>
Example:
match wallet.validate_arkoor_address(&addr).await {
Ok(()) => println!("Address is valid"),
Err(e) => eprintln!("Invalid address: {}", e),
}
Send Onchain
send_onchain
Send from your Ark balance directly to a Bitcoin address.
pub async fn send_onchain(
&self,
destination: bitcoin::Address,
amount: Amount,
) -> anyhow::Result<Txid>
Bitcoin address to send to
Net amount to send (before fees)
Transaction ID of the offboard transaction
Example:
use bitcoin::Address;
let btc_address = Address::from_str("bc1q...")?.assume_checked();
let txid = wallet.send_onchain(
btc_address,
Amount::from_sat(50_000)
).await?;
println!("Onchain tx: {}", txid);
This uses an arkoor transaction internally to create the right VTXO amount, then performs an offboard. Fees are higher than regular arkoor payments.
Receiving Payments
Payments are received through the mailbox system.
Mailbox Sync
// Sync is called automatically by maintenance methods
wallet.sync().await;
// Or manually sync mailbox
wallet.sync_mailbox().await?;
Checking Received Payments
Received VTXOs appear in your spendable balance:
let balance = wallet.balance().await?;
let vtxos = wallet.spendable_vtxos().await?;
Payment History
history
Get all wallet fund movements.
pub async fn history(&self) -> anyhow::Result<Vec<Movement>>
pub struct Movement {
pub id: MovementId,
pub subsystem: String,
pub operation: String,
pub status: MovementStatus,
pub intended_balance_change: SignedAmount,
pub effective_balance_change: SignedAmount,
pub fee: Amount,
pub timestamp: DateTime<Utc>,
// ... more fields
}
Example:
let history = wallet.history().await?;
for movement in history {
println!(
"{}: {} {} {}",
movement.timestamp,
movement.operation,
movement.effective_balance_change,
movement.status
);
}
VTXO Management
vtxos
Get all unspent VTXOs.
pub async fn vtxos(&self) -> anyhow::Result<Vec<WalletVtxo>>
spendable_vtxos
Get only spendable VTXOs.
pub async fn spendable_vtxos(&self) -> anyhow::Result<Vec<WalletVtxo>>
Example:
let vtxos = wallet.spendable_vtxos().await?;
for vtxo in vtxos {
println!(
"VTXO {}: {} sats, expires at block {}",
vtxo.id(),
vtxo.amount().to_sat(),
vtxo.expiry_height()
);
}
vtxos_with
Filter VTXOs with a custom predicate.
pub async fn vtxos_with(
&self,
filter: &impl FilterVtxos
) -> anyhow::Result<Vec<WalletVtxo>>
Example:
use bark::vtxo::VtxoFilter;
let tip = wallet.chain.tip().await?;
let filter = VtxoFilter::new(&wallet)
.expires_before(tip + 100)
.min_amount(Amount::from_sat(1000));
let expiring = wallet.vtxos_with(&filter).await?;
get_expiring_vtxos
Get VTXOs expiring within a threshold.
pub async fn get_expiring_vtxos(
&self,
threshold: BlockHeight,
) -> anyhow::Result<Vec<WalletVtxo>>
Number of blocks before expiry
VTXO Refresh
Refreshing extends VTXO expiry by participating in a round.
refresh_vtxos
Refresh specific VTXOs interactively.
pub async fn refresh_vtxos<V: VtxoRef>(
&self,
vtxos: impl IntoIterator<Item = V>,
) -> anyhow::Result<Option<RoundStatus>>
vtxos
impl IntoIterator<Item = V>
required
VTXOs to refresh (can be VtxoId, &Vtxo, or WalletVtxo)
Returns
Result<Option<RoundStatus>>
Round status if refresh occurred, None if no VTXOs needed refresh
Example:
let expiring = wallet.get_expiring_vtxos(50).await?;
if !expiring.is_empty() {
wallet.refresh_vtxos(expiring).await?;
}
refresh_vtxos_delegated
Schedule a delegated (non-interactive) refresh.
pub async fn refresh_vtxos_delegated<V: VtxoRef>(
&self,
vtxos: impl IntoIterator<Item = V>,
) -> anyhow::Result<Option<StoredRoundState>>
maintenance_refresh
Automatically refresh VTXOs that need it.
pub async fn maintenance_refresh(&self) -> anyhow::Result<Option<RoundStatus>>
Returns
Result<Option<RoundStatus>>
Round status if any VTXOs were refreshed
Example:
// Refresh VTXOs that must or should be refreshed
wallet.maintenance_refresh().await?;
Import VTXO
import_vtxo
Manually import a VTXO into the wallet.
pub async fn import_vtxo(&self, vtxo: &Vtxo) -> anyhow::Result<()>
Example:
// Import a VTXO from external source
let vtxo: Vtxo = /* obtained elsewhere */;
wallet.import_vtxo(&vtxo).await?;
The wallet must own a signable clause in the VTXO’s policy. Import will fail for VTXOs the wallet doesn’t control.
Sync Methods
sync
Sync offchain state and fee rates.
This syncs:
- Fee rates from chain source
- Mailbox for received payments
- Pending rounds
- Pending Lightning payments
- Pending boards
Example:
maintenance
Full wallet maintenance including refresh.
pub async fn maintenance(&self) -> anyhow::Result<()>
This performs:
- Full sync
- Progress pending rounds
- Refresh VTXOs as needed
Example:
// Recommended to call periodically
wallet.maintenance().await?;
Fee Estimation
VTXO operations incur fees based on their properties:
let ark_info = wallet.ark_info().await?.unwrap();
// Arkoor fees
let arkoor_fee = ark_info.fees.arkoor.calculate(/* ... */);
// Refresh fees
let refresh_fee = ark_info.fees.refresh.calculate(/* ... */);
// Offboard fees
let offboard_fee = ark_info.fees.offboard.calculate(/* ... */);