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 domain | Where it originates in BULL | Granularity | What an integrator does with it |
|---|---|---|---|
| Secure Bitcoin Wallet holdings | Descriptor-based on-chain wallet managed by BDK, bech32 SegWit | Per UTXO, per transaction, confirmation depth | Rebuild balance and history, derive cost basis from the chain |
| Instant Payments holdings | Confidential Liquid wallet managed by LWK | Per confidential UTXO (needs the blinding key), per transaction | Unblind L-BTC amounts, track daily-spend flow separately from savings |
| Lightning payments | Boltz atomic swaps between Liquid and Lightning | Per swap: id, lifecycle state, direction, preimage | Reconcile each Lightning payment to its underlying Liquid HTLC |
| Exchange orders | Bull Bitcoin account (buy and sell) | Per order: amount, fiat currency, rate, fee, status | Order history, realized P&L, statement export |
| Recurring buys | Exchange account dollar-cost-averaging schedules | Per schedule and per fill | Monitor automation, fold fills into a treasury feed |
| Bylls bill payments and payouts | Exchange account fiat-out rail | Per payment: payee, fiat amount, Interac / SEPA / wire | Reconcile against bank statements |
| Address labels | Local BIP-329 label store, exportable | Per address and per transaction | Enrich 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.
Consent, FINTRAC and a self-custodial data basis
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.
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.
- SatoshiPortal/bullbitcoin-mobile README — wallet descriptors, BDK/LWK, MIT license, no xpub shared
- Bull Bitcoin: how BULL uses Liquid for Lightning — dual wallet, Boltz swaps, fee range
- Google Play listing — feature set and package identity
- Boltz API: swap types and states — swap lifecycle used in reconciliation
Reviewed 2026-06-15 by the OpenBanking Studio integration desk.
Similar wallets in the swap-and-self-custody space
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.