Skip to main content

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>
Returns
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>
index
u32
required
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>>
destination
&ark::Address
required
Recipient’s Ark address
amount
Amount
required
Amount to send
Returns
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<()>
address
&ark::Address
required
Address to validate
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>
destination
bitcoin::Address
required
Bitcoin address to send to
amount
Amount
required
Net amount to send (before fees)
Returns
Result<Txid>
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>>
Returns
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>>
threshold
BlockHeight
required
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<()>
vtxo
&Vtxo
required
The VTXO to import
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.
pub async fn sync(&self)
This syncs:
  • Fee rates from chain source
  • Mailbox for received payments
  • Pending rounds
  • Pending Lightning payments
  • Pending boards
Example:
wallet.sync().await;

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(/* ... */);

Build docs developers (and LLMs) love