We've redesigned how Bark wallets receive updates from the Ark server. The new unified mailbox gives developers a single, efficient feed for all wallet notifications—Ark payments (arkoor), Lightning activity, and refreshes—instead of requiring separate queries for each address. This simplifies integration and scales to high transaction volumes without adding latency.

The sync problem

Most bitcoin wallets rely on Electrum or Esplora to monitor on-chain activity. These backends work by querying each address individually to check for new transactions, balance changes, and payment confirmations. For on-chain bitcoin, this approach works well enough because most users don't generate that many addresses or transactions.

Ark changes this equation. The protocol is designed for frequent, low-cost payments across Ark, Lightning, and on-chain, which means wallets need to track a higher volume of activity. On top of payments, wallets also need to monitor refreshes (both standard and delegated) and other state changes. Each of these creates notifications that the wallet needs to receive.

If a wallet queried each address individually—the traditional approach—sync times would grow with every new address. A wallet with hundreds of addresses would need hundreds of requests just to check for updates. For developers building on Ark, this creates two problems: latency that degrades the user experience, and complexity from having to aggregate multiple notification streams into a coherent wallet state.

One endpoint for everything

The unified mailbox consolidates all notifications into a single feed. Instead of querying each address, the wallet makes one request to its mailbox and receives everything: incoming Ark payments, Lightning preimages, BOLT-12 offers, and refresh completions. This scales from one address to thousands with no additional overhead.

The wallet stores a checkpoint locally, so subsequent syncs only fetch what's new since the last check:

let mailbox_req = MailboxRequest {
    unblinded_id: mailbox_id.to_vec(),
    authorization: None,
    checkpoint,
};
let messages = mailbox_client.read_mailbox(mailbox_req).await?;

If you've already processed messages up to checkpoint 42, your next request starts at 43. This makes incremental sync efficient regardless of how much activity the wallet has seen historically.

Privacy and blinding

Each Ark address a wallet generates includes delivery information that tells senders where to post payments. This delivery information contains a "blinded" mailbox ID—a cryptographic transformation of the wallet's actual mailbox identifier.

The blinding uses the VTXO keypair specific to each address, which means every address produces a different blinded ID even though they all route to the same underlying mailbox. When a sender pays to an address, their wallet extracts this blinded ID and posts the VTXO to the server. The server then unblinds it to route the notification to the correct mailbox.

let blinded_id = mailbox_id.to_blinded(server_pubkey, &vtxo_keypair);

This design creates a privacy trade-off that wallet implementations can choose:

  • Fast sync (Bark's default): One mailbox per wallet. Senders only see different blinded IDs for each address, so they cannot tell that two addresses belong to the same person. The server, however, can unblind and link all your addresses internally.
  • Maximum privacy: The protocol supports using a different mailbox keypair for every address. This prevents even the server from linking your activity, at the cost of slower sync since each mailbox must be queried separately.

Real-time notifications

Beyond checkpoint-based polling, the mailbox supports subscriptions that push notifications to the wallet the moment they arrive:

let stream = mailbox_client.subscribe_mailbox(mailbox_req).await?;

This is particularly important for mobile wallets, where a responsive payment experience depends on immediate feedback. When a payment arrives or a refresh completes, the wallet knows instantly rather than waiting for the next poll interval.

For Lightning receive, real-time notifications become critical. When an incoming Lightning payment targets your wallet, the mailbox notifies you so your wallet can wake up, request the HTLCs, and reveal the preimage to claim the funds. Unlike Ark payments, Lightning has timeouts—if your wallet doesn't respond before the HTLC expires, the payment fails. Polling intervals aren't reliable enough for this; you need the push.

Mobile devices can't maintain persistent WebSocket connections because the OS kills background processes to save battery. To solve this, you can authorize a third party—such as your wallet provider's notification service—to watch your mailbox on your behalf:

let expiry = chrono::Local::now() + Duration::from_secs(3600);
let authorization = MailboxAuthorization::new(&mailbox_keypair, expiry);

The authorization has an expiry you control. The third party can monitor for incoming payments and send push notifications to wake your app, but only for the duration you've permitted.


The unified mailbox is available now in Bark. See merge request !1412 for implementation details.