feat: add boltz savings swap#632
Open
coreyphillips wants to merge 7 commits into
Open
Conversation
Bring the iOS savings-swap flow to parity with bitkit-android #1081: - Bump bitkit-core 0.5.1 -> 0.5.2 and pass acceptZeroConf so reverse swaps claim once the lockup hits the mempool - Make BoltzSwap.isClaimable permissive so the manual-claim recovery tool stays reachable when the updates stream stalls - Add a settling progress state instead of showing success while the on-chain claim is still landing - Move the updates-stream orchestration into WalletViewModel with retry/backoff and ensure it is running before starting a swap - Shorten the claim wait to 30s and let the swipe close the channel when the amount is below the swap minimum
coreyphillips
marked this pull request as ready for review
July 20, 2026 17:39
Greptile SummaryThis PR adds a Boltz reverse-swap path for moving Lightning funds to on-chain savings. The main changes are:
Confidence Score: 5/5This looks safe to merge.
|
| Filename | Overview |
|---|---|
| Bitkit/ViewModels/TransferViewModel.swift | Adds reverse-swap quotes, payment initiation, and a bounded wait for claim events. |
| Bitkit/ViewModels/WalletViewModel.swift | Adds swap-update startup, retry, shutdown, and balance refresh handling. |
| Bitkit/Services/BoltzService.swift | Wraps the Boltz API and forwards swap lifecycle events through asynchronous streams. |
| Bitkit/Views/Transfer/SavingsConfirmView.swift | Adds swap quotes, amount selection, and the channel-close fallback. |
| Bitkit/Views/Transfer/SavingsProgressView.swift | Runs the selected transfer path and shows pending claims as settling on-chain. |
| BitkitTests/SavingsSwapTests.swift | Covers quote calculations and manual claim eligibility. |
Reviews (2): Last reviewed commit: "refactor: simplify savings swap payment ..." | Re-trigger Greptile
Paying a Boltz hold invoice only settles once the swap is claimed on-chain, so awaiting the payment before starting the claim timeout could leave the progress screen spinning when a lockup is delayed. Run the hold-invoice payment in a background task and drive the outcome off the bounded claim wait, which now runs concurrently. A timeout means the transfer is settling in the background; a payment that fails to initiate is still surfaced.
…g send LDK returns a payment id as soon as a bolt11 payment is initiated; it does not block until a hold invoice settles, so awaiting the payment before the bounded claim wait does not gate the claim timeout. Restore the direct structure so a payment that fails to initiate surfaces immediately instead of after the claim timeout, and document the semantics so the ordering is not mistaken for a stuck flow.
piotr-iohk
marked this pull request as draft
July 21, 2026 06:08
piotr-iohk
marked this pull request as ready for review
July 21, 2026 06:08
Ports the latest bitkit-android #1081 refinement. Closing a channel is now the default and a priced quote is the only thing that upgrades a transfer to a swap, so the swipe always commits the transfer instead of going inert when no quote is available. Gate swaps to mainnet: Boltz's testnet deployment is deprecated and regtest expects a local backend, so on every other network the confirm screen shows no quote, fees, slider, or close-instead action and the swipe closes the channel exactly as it did before swaps existed. Skip the limits fetch entirely where swaps are unsupported, bound it to 15s elsewhere so a hanging Boltz request cannot leave the swipe stuck loading, and drop the quote error and amount-too-low state now that every failure simply leaves the quote nil. Also skip starting the swap updates stream on unsupported networks, and add an optional loading state to the swipe button so it cannot be swiped past a quote that is still being fetched.
Ports the bitkit-android #1081 dev gate. The savings swap UI is not final yet, so the flow now stays off until "Enable Savings Swap" is switched on under Dev Settings. With it off the confirm screen fetches no quote and resolves to the channel-close path, and the swap updates stream never starts, so the journey is exactly what shipped before swaps existed. Groups the toggle with the existing swaps list under a new Swaps section in Dev Settings, and drops the changelog fragment now that the flow is not user-facing.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR adds a swap-based path for transferring spending balance to savings, so Lightning funds can move on-chain through a Boltz reverse swap instead of only by closing a channel. It ports the equivalent Android feature (synonymdev/bitkit-android#1081) to iOS, including its later refinements.
Description
Linked Issues/Tasks
Android counterpart: synonymdev/bitkit-android#1081
Screenshot / Video
Insert relevant screenshot / recording
QA Notes
Manual Tests (swap path needs mainnet plus Dev Settings → Enable Savings Swap)
regression:Savings Confirm → Close channel instead: falls back to the channel-close path.regression:Start the app with a pending swap: swap resumes and balance updates once it lands on-chain.regression:On a regtest or testnet build, Transfer to Savings → Savings Confirm: no quote, fees, slider, or close-instead action, and the swipe closes the channel as before.regression:With Dev Settings → Enable Savings Swap off, Transfer to Savings → Savings Confirm: no quote, fees, slider, or close-instead action, and the swipe closes the channel as before.Automated Checks
BitkitTests/SavingsSwapTests.swift.SavingsSwapTestspass.