BULL app icon

Self-custody wallet + non-custodial exchange

BULL Bitcoin Mobile: on-chain, Liquid and exchange-side data

Every BULL install derives two wallets from a single BIP39 seed: a descriptor-based Bitcoin wallet using bech32 SegWit addresses, and a confidential Liquid wallet using blinded SegWit addresses. Both come from the same backup. Alongside them sits a separate Bull Bitcoin exchange account that handles buys, sells, recurring purchases and bill payments. Three data surfaces, one app.

Because the wallet is self-custodial and the code is open, the cleanest path to a user's holdings is the math, not a server. A consented output descriptor rebuilds the full Bitcoin and Liquid history against public chain indexers, no exchange involvement needed. The account-side records, including orders, recurring buys and Bylls payouts, live behind the login, so we reach those through consented interface integration and join the two on settlement addresses. That split — chain math for holdings, consented account access for the fiat side — shapes every BULL build.

What BULL holds, and where each surface comes from

Data domainWhere it originates in BULLGranularityWhat an integrator does with it
Secure Bitcoin Wallet holdingsDescriptor-based on-chain wallet managed by BDK, bech32 SegWitPer UTXO, per transaction, confirmation depthRebuild balance and history, derive cost basis from the chain
Instant Payments holdingsConfidential Liquid wallet managed by LWKPer confidential UTXO (needs the blinding key), per transactionUnblind L-BTC amounts, track daily-spend flow separately from savings
Lightning paymentsBoltz atomic swaps between Liquid and LightningPer swap: id, lifecycle state, direction, preimageReconcile each Lightning payment to its underlying Liquid HTLC
Exchange ordersBull Bitcoin account (buy and sell)Per order: amount, fiat currency, rate, fee, statusOrder history, realized P&L, statement export
Recurring buysExchange account dollar-cost-averaging schedulesPer schedule and per fillMonitor automation, fold fills into a treasury feed
Bylls bill payments and payoutsExchange account fiat-out railPer payment: payee, fiat amount, Interac / SEPA / wireReconcile against bank statements
Address labelsLocal BIP-329 label store, exportablePer address and per transactionEnrich records with human-readable context

Three authorized ways into BULL's data

Consented descriptor reconstruction

The wallet hands the account holder an output descriptor (and, for Liquid, a blinding key). With that supplied under consent, we scan public Bitcoin and Liquid indexers and rebuild balances, UTXOs and the full transaction history watch-only. Spend authority stays on the device. This is durable: it depends on Bitcoin and Liquid, not on any app screen, so it survives app updates untouched. We set up the indexer access and the scan job; the client supplies the descriptor during onboarding.

Interface integration of the exchange account

Orders, recurring-buy schedules, Bylls payouts and fiat funding events sit behind the Bull Bitcoin login. Working from a consenting account, we capture the request and token flow the mobile app uses, map the endpoints that return account state, and turn them into a clean read interface. Effort is moderate; durability is tied to the account back end, so the build includes a check that flags when the request flow shifts between releases. Access is arranged with the client as part of the work.

Native export for a one-off snapshot

The app exports BIP-329 labels and descriptors directly. Where a project needs only a point-in-time snapshot, that export plus a chain scan covers the wallet side without any live connection. It pairs with the descriptor route and gives a clean cold-start for the label metadata.

For most BULL projects we lead with descriptor reconstruction for everything self-custodied and add the consented account channel only for the fiat-side records that the chain cannot show. The two are joined on settlement addresses so the picture stays whole.

What lands in your repo

Concrete artifacts, written against BULL's actual surfaces:

  • An OpenAPI specification covering the read endpoints we expose: wallet balances and history, swap status, exchange orders, recurring-buy fills, payouts.
  • A protocol and auth-flow report for the exchange account: the token chain the app uses, refresh behaviour, and the request shapes that return account state.
  • Runnable source for the key paths, in Python or Node.js: descriptor scan and balance reconstruction, Boltz swap reconciliation, and the consented account pull.
  • A normalizer that folds Bitcoin, Liquid and Lightning records into one ledger, with the fiat side attached from exchange orders.
  • Automated tests, including fixtures for confidential Liquid UTXOs and a refunded-swap case so reconciliation is proven, not assumed.
  • Interface documentation plus data-retention and consent-handling guidance fit for a money-services context.

Rebuilding a wallet from its descriptor

The on-chain side is reconstructed watch-only from the consented descriptor. The snippet is illustrative; exact descriptor and field shapes are confirmed against the wallet during the build.

# Rebuild a BULL "Secure Bitcoin Wallet" from its consented output descriptor.
# Watch-only: the descriptor grants read, never spend.
descriptor = "wpkh([a1b2c3d4/84h/0h/0h]xpub6.../0/*)"   # supplied by the account holder

scan = esplora.scan_descriptor(descriptor, gap_limit=20)   # Esplora / Electrum backend
for tx in scan.transactions:
    yield {
        "txid":      tx.txid,
        "height":    tx.status.block_height,   # None while unconfirmed
        "value_sat": tx.net_value,             # signed: +receive / -send
        "address":   tx.address,               # bech32 SegWit
        "label":     labels.get(tx.txid),      # from a BIP-329 export, if present
    }

A Lightning payment is really a Boltz swap, so it is reconciled against the swap lifecycle rather than treated as a plain transfer:

GET https://api.boltz.exchange/v2/swap/{id}
-> 200 { "id": "...", "status": "transaction.claimed",   # swap lifecycle state
         "type": "reverse" }                              # reverse = Lightning in -> Liquid

# map status -> settled | pending | refunded
# on 404, treat the swap as expired or never locked, not as a payment

One schema across on-chain, Liquid and Lightning

The normalizer collapses three settlement layers and a fiat side into a single record shape so downstream code never branches on network:

{
  "source":     "bull.secure_btc | bull.instant_liquid | bull.exchange",
  "type":       "receive | send | buy | sell | dca_fill | bill_payment | swap",
  "asset":      "BTC | L-BTC",
  "amount_sat": -150000,
  "fiat":       { "ccy": "CAD", "amount": null },   # null unless tied to an exchange order
  "settled_at": "2026-06-15T00:00:00Z",
  "ref":        { "txid": "...", "swap_id": "...", "order_id": "..." }
}

Where this gets used

  • Tax and accounting export: pull every buy, sell and recurring-buy fill with its on-chain settlement, attach CAD or EUR cost basis, emit a CSV a tax package can read.
  • Treasury feed: a business running auto-buy wants live recurring-buy fills and a combined Bitcoin-plus-Liquid balance in its internal dashboard.
  • Bank reconciliation: match Bylls bill payments and fiat payouts against statement lines by amount, date and rail.
  • Portfolio aggregation: fold a user's self-custodied BULL holdings, reconstructed from the descriptor, into a multi-wallet net-worth view.

The dependable basis here is the account holder's own authorization. The wallet is self-custodial, so the user holds the keys and can authorize a watch-only reconstruction directly; nothing about that requires a third party's permission. For the exchange-account records, Bull Bitcoin describes itself as a registered money services business in Canada, which places its fiat operations under FINTRAC's MSB regime and the personal data under PIPEDA. Canada's consumer-driven banking framework is still being stood up and does not reach crypto wallets, so we do not pretend an open-banking rail applies; consent plus self-custody is the route.

Consent scope is read-only: order, transaction and payout history, never spend authority. It is revocable by rotating the account credentials, and a descriptor is watch-only by nature, so it cannot move funds. We log what was accessed, keep consent records, pull only the fields a project needs, and sign an NDA where the client wants one.

Build notes we plan around

Three things specific to BULL that we account for up front:

  • Confidential Liquid UTXOs. L-BTC amounts are blinded on-chain, so a generic explorer reads them as zero. We reconstruct the Liquid wallet through LWK using the wallet's blinding key, derived from the consented descriptor, so confidential balances unblind correctly.
  • The Boltz swap state machine. A Lightning payment is a Liquid-to-Lightning atomic swap, not a single transfer. We model the full lifecycle, from swap created through locked to claimed or refunded, so a Lightning payment reconciles to its underlying HTLC and a refund is never double-counted as a payment.
  • The xpub is never shared with the exchange. The repo notes the wallet hands per-address receive points to Bull Bitcoin rather than its xpub. So we design wallet-history reconstruction off the consented descriptor against public indexers, keep the exchange-account pull as its own consented channel, and join the two on settlement addresses. Because the app ships often, the wallet side is pinned to the stable descriptor math while the account side is checked against each release.

The app, screen by screen

Store screenshots we reviewed while mapping the surfaces above. Select one to enlarge.

BULL screen 1 BULL screen 2 BULL screen 3 BULL screen 4 BULL screen 5 BULL screen 6 BULL screen 7 BULL screen 8 BULL screen 9 BULL screen 10

Sources I opened for this brief

I worked from the open-source mobile repository, Bull Bitcoin's own technical write-up on its Liquid-Lightning design, the Google Play listing, and the Boltz swap-lifecycle reference, cross-checked on 15 June 2026. The data domains and the descriptor and blinding-key handling above come from the repository and the blog post directly; the swap states come from the Boltz documentation.

Reviewed 2026-06-15 by the OpenBanking Studio integration desk.

Same category, useful when a project wants one integration across several of them:

  • Aqua Wallet — non-custodial Bitcoin, Liquid and stablecoin wallet that, like BULL, uses Boltz for Liquid-to-Lightning swaps.
  • Phoenix — self-custodial Lightning wallet that opens and closes channels automatically; holds per-payment Lightning history.
  • Blockstream Green — Bitcoin and Liquid self-custody wallet with multisig, descriptor and confidential-asset support.
  • Zeus — self-custodial Lightning wallet and remote node controller; channel and payment data.
  • Breez — self-custodial Lightning wallet that also integrates the Boltz swap API.
  • Electrum — long-standing Bitcoin wallet built on output descriptors and SPV.
  • Cake Wallet — multi-asset non-custodial wallet covering Bitcoin and Litecoin among others.
  • Bisq — desktop peer-to-peer non-custodial exchange with its own trade and offer records.
  • Proton Wallet — self-custody Bitcoin wallet with end-to-end encrypted account data.

Questions integrators ask about BULL

Can you get my full balance without my seed phrase?

For the on-chain and Liquid wallets, yes. A watch-only output descriptor or xpub is enough to rebuild balances, UTXOs and transaction history; the seed, which carries spend authority, never leaves your device. For Liquid we also need the wallet's blinding key so confidential L-BTC amounts unblind correctly. Exchange-account records are reached separately, with your account consent.

Why does a Lightning payment show up as a Liquid transaction in BULL?

Because that is how the wallet works. A Lightning send or receive is a non-custodial Boltz atomic swap between the Instant Payments (Liquid) wallet and the Lightning Network. We model the Boltz swap lifecycle so every Lightning payment reconciles to its underlying Liquid HTLC, and a refunded swap is not counted as a completed payment.

Can you separate exchange buys from plain on-chain receives?

Yes. Buys, sells, recurring-buy fills and Bylls payouts come from the Bull Bitcoin exchange account and carry a fiat side such as CAD, EUR or the Costa Rican colon; plain on-chain receives come from the wallet reconstruction. We tag every record by source and join the two on the settlement address, so a dollar-cost-averaging fill lines up with the deposit it produced.

We auto-buy on a schedule. Can the feed stay current as new releases ship?

The wallet-side reconstruction is pinned to the output descriptor and does not move when the app updates. The exchange-side pull is checked against each release, so a changed request flow is caught early rather than failing silently. Turnaround on a build like this is one to two weeks.

Working with us

The runnable source for these paths — descriptor reconstruction, Boltz swap reconciliation and the consented exchange-account pull — starts at $300, billed only after delivery once it works in your hands. If you would rather not host anything, the same endpoints are available as a pay-per-call hosted API with no upfront fee. Either path runs one to two weeks. Tell us the app and what you need out of its data at /contact.html.

App profile: Bull Bitcoin Mobile

BULL (listed as com.bullbitcoin.mobile on Google Play) is a self-custodial wallet for Bitcoin and the Liquid Network, released under the MIT license per its GitHub repository. From one BIP39 seed it derives a descriptor-based Secure Bitcoin Wallet and a confidential Liquid Instant Payments Wallet, and it performs Lightning send and receive through non-custodial Boltz atomic swaps. The companion Bull Bitcoin exchange, described as a registered money services business in Canada, supports buying and selling, recurring purchases, and Bylls bill payments, and per Bull Bitcoin's site operates in Canada, the EU, Costa Rica, Argentina, Mexico and Colombia. Features cited above are drawn from the sources listed; figures such as the Boltz fee range are stated as the app's own materials describe them.

Mapping last checked 2026-06-15.

BULL screen 1 enlarged
BULL screen 2 enlarged
BULL screen 3 enlarged
BULL screen 4 enlarged
BULL screen 5 enlarged
BULL screen 6 enlarged
BULL screen 7 enlarged
BULL screen 8 enlarged
BULL screen 9 enlarged
BULL screen 10 enlarged