Skip to content

feat: POC — bark (Ark) as an alternative spending backend [DO NOT MERGE] - #1129

Draft
jvsena42 wants to merge 11 commits into
masterfrom
feat/bark-POC
Draft

feat: POC — bark (Ark) as an alternative spending backend [DO NOT MERGE]#1129
jvsena42 wants to merge 11 commits into
masterfrom
feat/bark-POC

Conversation

@jvsena42

@jvsena42 jvsena42 commented Aug 3, 2026

Copy link
Copy Markdown
Member

Warning

This is a proof of concept and must not be merged. It exists to evaluate Second's Bark (Ark) as a
replacement for the local ldk-node Lightning node. Ark funds created by this branch are not backed
up
— the recovery phrase alone cannot restore them — and several flows are deliberately unfinished.
Use signet and trivial amounts only.

Description

Adds Bark (Second's Ark implementation) as an alternative spending backend, switchable at runtime from
Settings → Advanced. Savings is untouched: ldk-node keeps running and keeps owning the on-chain wallet, so
only the Lightning/spending half is swapped out.

Second publishes an official Kotlin/UniFFI binding, so this is an integration rather than a bindings project.

  • Dependency & flavortech.second.bark:bark-android:0.12.2+bark-0.4.0 from Second's public GitLab
    Maven, plus a new signet flavor (the only test network with a Second-hosted Ark server). Signet reuses
    the testnet applicationId so the checked-in google-services.json resolves without a signet Firebase
    client; the trade-off is that signet and tnet cannot be installed side by side.
  • BarkService — thin wrapper over uniffi.bark.Wallet, shaped after LightningService, with all rust
    calls on a dedicated ServiceQueue.ARK thread.
  • BarkRepoBarkState StateFlow plus an executeWhenRunning gate mirroring
    LightningRepo.executeWhenNodeRunning. uniffi.bark types are wrapped so they never reach UI state.
  • BalancesDeriveBalanceStateUseCase branches on the selected backend, so every existing balance
    surface (home tiles, spending screen, send flows) works with no UI change.
  • Activities — bark Movements are mapped to bitkit-core LightningActivity and inserted through the
    existing path, so the activity list, detail screen, tags and contacts all work unchanged.
  • Transfers — offboard (spending → savings) is one step. Board (savings → spending) is two, because bark
    boards from its own on-chain wallet; a persisted state machine survives the app being killed between them.
  • VTXO maintenance — a 6h WorkManager worker plus a foreground pass run maintenanceDelegated(), the
    mobile refresh path. This is not optional: VTXOs expire (~28 days, ~3 days for Lightning receives) and the
    server can sweep them.
  • Switch gate — the toggle is blocked unless the spending balance is 0, no channels are open, no transfer
    is in flight and no Ark exit is in progress. When blocked on a balance it deep-links into the existing
    Transfer → Savings flow.

Two findings worth calling out

  1. bark cannot reuse bitkit's on-chain wallet. bark exposes CustomOnchainWalletCallbacks, which would
    have given one-step boarding and a single UTXO set — but it needs prepareTx → PSBT and finishPsbt, and
    ldk-node's OnchainPaymentInterface (verified against 0.7.0-rc.62 sources) has no PSBT API at all. bark
    therefore keeps a second on-chain wallet on the same seed. It is never presented as "Savings".
  2. Both build risks flagged during planning are resolved. libbark_ffi_kotlin.so packages cleanly
    without bark's README-mandated useLegacyPackaging = true (which would have changed packaging for
    ldk-node/bitkit-core/paykit/vss too), and the arm64 lib is 16 KB page-size compliant (PT_LOAD align
    0x4000).

Deliberately out of scope

  • No backup of the bark database. Mandatory before this is anything more than a POC.
  • Send/receive UI routing is wired at the repo layer; the send/receive ViewModels still need to branch on
    the backend, and the Transfer screens still need bark-specific copy.
  • Blocktank/CJIT entry points are not yet hidden in bark mode (the Advanced-tab Lightning rows are).
  • WakeNodeWorker (FCM push wake) is untouched — bark has no push, so waking on an LSP notification would be
    a no-op. Background liveness comes from BarkMaintenanceWorker instead.

Preview

QA Notes

Journeys live in journeys/bark/ and are written for the android-cli journey runner:

  • bark-toggle-gate.xml — the switch is blocked with a spending balance and offers Transfer To Savings
  • bark-enable.xml — the no-backup warning shows, and Lightning-only rows disappear once enabled
  • bark-receive-lightning.xml — BOLT11 receive over Ark lands in balance and activity
  • bark-send-lightning.xml — BOLT11 send decreases balance and records a sent activity
  • bark-board.xml — savings → spending shows as in-transfer until the board completes
  • ldk-regression.xmlrun this on a dev build; guards that the shipping ldk-node path is untouched
    and that the Ark toggle is hidden on networks with no Ark server

Unit tests: BarkMovementsTest.kt (movement → activity mapping), CanSwitchSpendingBackendUseCaseTest.kt
(every allow/block branch, both directions), BarkTransferRepoTest.kt (board state machine, including
resume-after-death and failure keeping the pending board), plus ContentViewTest.kt for the extracted
transferSavingsStartRoute helper.

Validation run: just compile, just test, just lint all pass, and assembleSignetDebug produces an APK
with libbark_ffi_kotlin.so present. compileMainnetDebugKotlin needs a local
app/src/mainnet/google-services.json, which is gitignored and not present in a fresh worktree.

🤖 Generated with Claude Code

jvsena42 and others added 11 commits August 3, 2026 10:09
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant