Skip to main content

Overview

Bark wallets can receive payments through:
  • Ark addresses: For receiving arkoor (out-of-round) payments
  • Lightning invoices: For receiving over the Lightning Network
  • Onchain: Through boarding transactions

Generating Ark Addresses

Create a New Address

Generate a fresh Ark address for receiving payments:
#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Generate a new Ark address
    let address = wallet.new_address().await?;
    println!("Your Ark address: {}", address);

    // Share this address with the sender
    Ok(())
}

Generate Address with Index

Get both the address and its derivation index:
// Generate address and return the key index
let (address, index) = wallet.new_address_with_index().await?;
println!("Address: {}", address);
println!("Key index: {}", index);

Peek at Existing Address

Retrieve a previously generated address by its index:
// Peek at address at index 0 (must be previously derived)
let address = wallet.peak_address(0).await?;
println!("Address at index 0: {}", address);

Understanding Ark Addresses

Ark addresses contain:
  • Server public key: Identifies the Ark server
  • User policy: Your public key for receiving funds
  • Mailbox identifier: For receiving VTXO notifications
  • Network indicator: Testnet vs mainnet
let address = wallet.new_address().await?;

// Addresses are encoded in a bech32-like format
println!("Address: {}", address);
// Example: ark1...

Receiving Arkoor Payments

Check for Received VTXOs

Periodically sync your mailbox to receive incoming payments:
// Sync the mailbox to receive new VTXOs
wallet.sync_mailbox().await?;

// Or use comprehensive sync
wallet.sync().await;

// Check your balance
let balance = wallet.balance().await?;
println!("Spendable balance: {}", balance.spendable);

Automatic Mailbox Syncing

Mailbox syncing happens automatically during wallet maintenance:
// Syncs mailbox along with other wallet state
wallet.maintenance().await?;

Inspecting Received VTXOs

View the VTXOs you’ve received:
// Get all spendable VTXOs
let vtxos = wallet.spendable_vtxos().await?;

for vtxo in vtxos {
    println!("VTXO ID: {}", vtxo.id());
    println!("Amount: {}", vtxo.amount());
    println!("Expiry: {}", vtxo.expiry_height());
    println!("State: {:?}", vtxo.state);
}

Query Specific VTXOs

use ark::VtxoId;

// Get a specific VTXO by ID
let vtxo_id = VtxoId::from_slice(&[...])?;
let vtxo = wallet.get_vtxo_by_id(vtxo_id).await?;

println!("VTXO amount: {}", vtxo.amount());

Filter VTXOs

use bark::vtxo::{VtxoFilter, VtxoStateKind};

// Get VTXOs expiring soon
let threshold = 144; // blocks
let expiring = wallet.get_expiring_vtxos(threshold).await?;
println!("VTXOs expiring within {} blocks: {}", threshold, expiring.len());

// Get VTXOs by state
let pending = wallet.vtxos_with(&VtxoStateKind::Locked).await?;
println!("Locked VTXOs: {}", pending.len());

Wallet Balance

Check your complete balance breakdown:
use bitcoin::Amount;

let balance = wallet.balance().await?;

// Available for spending
println!("Spendable: {}", balance.spendable);

// Locked in pending rounds
println!("Pending in round: {}", balance.pending_in_round);

// Pending Lightning sends
println!("Pending Lightning send: {}", balance.pending_lightning_send);

// Claimable Lightning receives
println!("Claimable Lightning receive: {}", balance.claimable_lightning_receive);

// In unilateral exit process
if let Some(exit) = balance.pending_exit {
    println!("Pending exit: {}", exit);
}

// Pending board confirmations
println!("Pending board: {}", balance.pending_board);

Complete Receiving Workflow

use bark::{Config, Wallet, SqliteClient};
use std::sync::Arc;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Setup wallet
    let wallet = Wallet::open(
        &mnemonic,
        Arc::new(SqliteClient::open("db.sqlite").await?),
        Config::network_default(bitcoin::Network::Signet)
    ).await?;

    // Generate and share address
    let address = wallet.new_address().await?;
    println!("Share this address with the sender:");
    println!("{}", address);

    // Wait for payment (in practice, poll periodically)
    println!("Waiting for payment...");
    
    loop {
        // Sync to check for new VTXOs
        wallet.sync_mailbox().await?;
        
        // Check balance
        let balance = wallet.balance().await?;
        
        if balance.spendable > Amount::ZERO {
            println!("Payment received! Balance: {}", balance.spendable);
            
            // Show received VTXOs
            let vtxos = wallet.spendable_vtxos().await?;
            println!("Received {} VTXOs", vtxos.len());
            for vtxo in vtxos {
                println!("  - {}: {}", vtxo.id(), vtxo.amount());
            }
            
            break;
        }
        
        tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
    }

    Ok(())
}

VTXO States

VTXOs move through different states:
use bark::vtxo::VtxoState;

let vtxos = wallet.vtxos().await?;

for vtxo in vtxos {
    match vtxo.state {
        VtxoState::Spendable => {
            println!("VTXO {} is ready to spend", vtxo.id());
        }
        VtxoState::Locked { movement_id } => {
            println!("VTXO {} is locked in movement {:?}", vtxo.id(), movement_id);
        }
        VtxoState::Spent => {
            println!("VTXO {} has been spent", vtxo.id());
        }
    }
}

Key Derivation for Receiving

Bark uses hierarchical deterministic key derivation:
// Derive the next keypair for receiving
let (keypair, index) = wallet.derive_store_next_keypair().await?;
println!("Derived keypair at index {}", index);

// The mailbox keypair is fixed
let mailbox_keypair = wallet.mailbox_keypair()?;
println!("Mailbox pubkey: {}", mailbox_keypair.public_key());

Importing VTXOs

Manually import a VTXO (advanced):
use ark::Vtxo;

// Import a VTXO you own
let vtxo: Vtxo = /* obtained from somewhere */;

wallet.import_vtxo(&vtxo).await?;
println!("VTXO imported successfully");
Importing validates that:
  • The VTXO’s chain anchor exists and is valid
  • The wallet owns a signable clause for the VTXO
  • The VTXO hasn’t expired

Best Practices

1

Regular syncing

Sync your mailbox regularly to receive payments promptly:
// Sync every 30 seconds
loop {
    wallet.sync_mailbox().await?;
    tokio::time::sleep(tokio::time::Duration::from_secs(30)).await;
}
2

Monitor VTXO expiry

VTXOs have an expiry height. Refresh them before they expire:
let expiring = wallet.get_expiring_vtxos(144).await?;
if !expiring.is_empty() {
    wallet.refresh_vtxos(expiring).await?;
}
3

Use unique addresses

Generate a fresh address for each payment to improve privacy:
// Generate new address for each sender
let address = wallet.new_address().await?;
4

Track movements

Monitor received payments through the movements API:
let movements = wallet.history().await?;
for movement in movements {
    if movement.effective_balance.is_positive() {
        println!("Received: {}", movement.effective_balance);
    }
}

Validating Received VTXOs

Verify a VTXO against the chain:
// Validate a VTXO's chain anchor
let vtxo = wallet.spendable_vtxos().await?.first()
    .ok_or(anyhow!("No VTXOs"))?;

wallet.validate_vtxo(&vtxo.vtxo).await?;
println!("VTXO is valid");

Troubleshooting

Address Generation Fails

match wallet.new_address().await {
    Ok(addr) => println!("Address: {}", addr),
    Err(e) if e.to_string().contains("server") => {
        println!("Not connected to server. Check connection.");
    }
    Err(e) => return Err(e),
}

No VTXOs Received

  1. Ensure you’ve synced the mailbox:
    wallet.sync_mailbox().await?;
    
  2. Check if VTXOs are locked:
    let locked = wallet.vtxos_with(&VtxoStateKind::Locked).await?;
    println!("Locked VTXOs: {}", locked.len());
    
  3. Verify the sender used the correct address

VTXO Import Fails

match wallet.import_vtxo(&vtxo).await {
    Ok(()) => println!("Imported"),
    Err(e) if e.to_string().contains("expired") => {
        println!("VTXO has expired");
    }
    Err(e) if e.to_string().contains("not owned") => {
        println!("You don't own this VTXO");
    }
    Err(e) => return Err(e),
}

Next Steps

Sending Payments

Use your received funds to send payments

Lightning Integration

Receive payments via Lightning invoices

Build docs developers (and LLMs) love