Skip to content

fix: point transfers to manual setup - #1696

Open
ovitrif wants to merge 14 commits into
masterfrom
fix/blocktank-sunset-sheet
Open

ovitrif wants to merge 14 commits into
masterfrom
fix/blocktank-sunset-sheet

Conversation

@ovitrif

@ovitrif ovitrif commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator

Twin: synonymdev/bitkit-ios#1127

This PR replaces the "not available in your country" screens with the Blocktank-sunset design, which sends users to Manual Setup, and stops the transfer confirm from paying a Blocktank order now that Blocktank no longer sells channels.

Description

Blocktank stopped selling Lightning channels on 26 Oct. Its geocheck now answers 403 for everyone, so the app treats every user as geo-blocked.

  • Adds the "Transfer Unavailable" sheet: "MANUAL SETUP REQUIRED" with Learn More and Continue. Continue opens the existing Manual Setup flow unchanged, and Learn More opens the Bitkit blog in the browser.
  • Opens the sheet from the wallet screens' Transfer To Spending buttons while geo-blocked, so no Blocktank order is created:
    • Savings wallet: the Transfer To Spending button shows again and opens the sheet.
    • Spending wallet: the transfer button.
    • Hardware wallet: Transfer To Spending.
  • Reworks "Fund your spending balance" while geo-blocked: the sheet's text replaces the "not available in your country" copy, Manual Setup moves to the top, Transfer from Savings, a new Transfer from HW wallet row and Use Other Wallet are disabled, and Learn More opens the Bitkit blog.
  • Shows the sheet's content on Receive › Spending › Receive Lightning Funds instead of the "not available in your country" screen.
  • Checks the geo state again when the confirm swipe or the hardware-wallet confirm runs, before an order is created or reused. A swipe no longer pays an order held from before the switch, and opens the sheet instead. Only an explicit "allowed" geocheck lets the payment through: a failed or unexpected check blocks it. A transfer whose funding was already broadcast still finishes. A signed hardware-wallet transaction whose broadcast failed is not retried while geo-blocked, since it would pay the old order.
  • Runs the geocheck as the node starts, without waiting for LDK, as well as after, and keeps its result when the node stops. Before, the state stayed "not blocked" until the node was up, so a restarted or resumed app offered the transfer flow for a while.
  • Repurposes Background Payments for Paykit notifications, since every push it relied on came from Blocktank: the settings screen, its intro, the Settings row, the Home card and "Keep Bitkit active in background" stay, reworded for subscription reminders and payment requests. While "Keep Bitkit active in background" is on, its notification now reads "Bitkit is running in the background so you can receive payments and requests". The prompt shows only to users with a Paykit subscription, and the preview shows the subscription reminder. Proposing or accepting a subscription, or accepting an allowance, asks for notification permission if it isn't granted. Neutral copy until the design copy lands.
  • Removes the Lightning ties of those notifications: the push device registration with Blocktank, its notification types and the handling of Blocktank's encrypted pushes.
  • Stops treating Blocktank's nodes as special. LDK no longer marks them as trusted (trustedPeers0conf, trustedPeersNoReserve), so the wallet broadcasts and fee-bumps its own force close with Blocktank. Before, LDK left that broadcast to Blocktank, whose node no longer acts, so a force-closed Blocktank channel kept its funds stuck in "claimable on channel close". The hardcoded Blocktank node list, the info.nodes fetch and the "trusted peers" network-graph checks are gone.
  • Startup no longer connects to Blocktank nodes. ldk-node reconnects the peers in its store and re-adds channel counterparties from the network graph. Instead, startup disconnects every stored peer with no channel and no claimable balance, which also drops it from the peer store. It skips the run while a closed channel's sweep is pending, since a sweep does not name its peer.
  • A Blocktank channel is now a normal channel in the close flow. When the cooperative close gives up, Bitkit offers Force Transfer for every channel, Blocktank ones included. The "cannot close" toast that sent the user back is gone, and so is the "channels skipped" note on the force-close toast (lightning__force_channels_skipped, removed in every locale). Node Info no longer names the Blocktank nodes from the hardcoded list, and the RN migration's peer recovery no longer filters them out.
  • Reuses the sheet's translations from feat: stop offering new lightning channels #1670 and translates the new strings in every locale.

Learn More opens https://blog.bitkit.to/, where the announcement post appears once it is published.

Out of Scope

  • ui/screens/transfer, TransferViewModel, BlocktankRepo: deleting the purchase screens and the order and CJIT code.
  • Choose a Lightning provider screen and the channels-closing banner from feat: stop offering new lightning channels #1670, which this PR replaces.
  • Existing Blocktank channels: closing them.
  • Onboarding: the geo-blocked note "Bitkit does not currently provide Lightning services in your country" still shows on the first slide.
  • Funding option labels: the design writes "Manual setup" and "Use other wallet"; the existing "Manual Setup" and "Use Other Wallet" strings stay.

Design

Bitkit Wallet › Bitkit - Final Review v63 › Blocktank sunsetting:

Preview

Figma (left) next to the app (right):

Transfer Unavailable Fund your spending balance

Each entry point on a geo-blocked regtest wallet (2x):

Savings › Learn More › Continue Spending wallet
savings-sheet.mp4
spending-sheet.mp4
Fund your spending balance Receive Lightning
funding-screen.mp4
receive-screen.mp4

Notifications, repurposed for Paykit, on c5f14db:

Intro Settings

QA Notes

Setup

  • Dev build (just build, regtest, staging LSP). Geoblocking is on by default and Blocktank's geocheck answers 403, so the app is geo-blocked with no extra setup.
  • Fresh wallet funded on-chain only: ./lsp POST /regtest/chain/deposit '{"address":"<savings address>","amountSat":100000}', then ./lsp POST /regtest/chain/mine '{"count":3}'.

Journeys

  • J1: new transfer-unavailable-sheet.xml — the wallet screens' Transfer To Spending buttons open the sheet, Learn More opens bitkit.to, Continue opens Manual Setup, the Funding screen leads with Manual Setup with the other options disabled, and Receive's Lightning screen shows the sheet's content

Manual Tests

  • 1. Hold an order on the confirm screen, then turn geoblocking on and swipe → the sheet opens and nothing is paid — needs a debug hook to flip the geo state mid-flow; covered by unit tests

Automated Checks

  • updated NotificationsTimedSheetTest.kt — the prompt depends on Paykit subscriptions
  • removed WakeNodeWorkerTest.kt and the push-registration case in LightningRepoTest.kt — the wake worker and the registration are gone
  • added TransferViewModelTest.kt — a geo-blocked confirm swipe opens the sheet and sends nothing on-chain
  • added LightningRepoTest.kt — the geo state updates before the node is up
  • added FundingScreenTest.kt — while geo-blocked only Manual Setup responds
  • added LightningServiceTest.kt — the node config trusts no peer for zero-conf or force-close broadcasts; only stored peers with no channel and no claimable balance count as idle, and none while a sweep is pending
  • updated LightningRepoTest.kt — start disconnects idle peers and connects to no fixed peer; removed the cases for fetching Blocktank peers into the node setup
  • ran just compile, just test, just lint and compileDevDebugAndroidTestKotlin — pass

Side effects checked

  • Anchor reserve: perChannelReserveSats stays 1, so each open Blocktank channel now holds 1 sat of on-chain reserve. Spendable balance is effectively unchanged.
  • Force-close broadcast: anchor commitments usually need a CPFP through the anchor, which spends a confirmed on-chain UTXO. A wallet with no confirmed savings coin retries on each new block until it has one.
  • Zero-conf: trustedPeers0conf only gates accepting new unconfirmed inbound channels, so channels already open are unaffected.
  • Peer reconnects: checked at ldk-node v0.7.0-rc.77, which both apps pin. The node reconnects persisted peers, re-persists channel counterparties from the network graph after each RGS sync, and disconnect removes the peer from the store.
  • A Blocktank peer with a pending force close stays connected until its claim and sweep finish, which can take days for the timelock.

Evidence

J1 ran on 23dab9a, a dev build on a Pixel 9 emulator (Android 15) against the staging regtest LSP, with a fresh wallet funded with 100 000 sats on-chain:

  • Savings › Transfer To Spending opened the sheet; Learn More opened bitkit.to in Chrome, and Continue opened Manual Setup.
  • Spending › transfer button opened the sheet.
  • Lightning Connections › add connection showed Manual Setup first, Transfer from Savings, Transfer from HW wallet and Use Other Wallet disabled, and Learn More at the bottom. Transfer from Savings did nothing, Learn More opened bitkit.to, and Manual Setup opened.
  • Receive › Spending › Receive Lightning funds showed the sheet's content titled "Transfer Unavailable" with a back button; Continue opened Manual Setup.

Gaps

    1. (held order, then geo-blocked swipe) was not run on a device; the unit tests cover it.
  • Hardware wallet Transfer To Spending was not run: no Trezor emulator. It opens the same sheet as the other buttons.

Models used

  • Planning/scoping: claude-opus-5-5 (reasoning: Not exposed)
  • Implementation: claude-opus-5-5 (reasoning: Not exposed)
  • Review: claude-sonnet-5-5 (reasoning: Not exposed)

Metadata note: the session records name the models but do not expose their reasoning settings.

@ovitrif ovitrif added this to the 3.1.0 milestone Oct 26, 2026
@ovitrif ovitrif self-assigned this Oct 26, 2026
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-26T13:27:05.250355Z a53e17f PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a53e17f8f1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread app/src/main/java/to/bitkit/ui/sheets/TransferUnavailableSheet.kt
@ovitrif
ovitrif requested review from a team, ben-kaufman and pwltr and removed request for a team October 26, 2026 13:28
@greptile-apps

greptile-apps Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerView in GreptileConfidence Score: 4/5

[Medium impact] The changes affect the Lightning transfer and receiving paths in the Android app.

Fix the hardware retry bypass before merging so unsent funding cannot pay an unavailable Blocktank order.

Findings

  1. P1 Hardware retries bypass transfer block ▶

Summary

Points blocked transfer entry points to Manual Setup through a new Transfer Unavailable sheet.

  • Blocked transfer taps open a sheet that points users to Manual Setup.
  • The Receive Lightning screen now points users to Manual Setup.
  • Spending orders now stop when the latest geo check says transfers are unavailable.

Acknowledged by ovitrif: Read More temporarily opens https://bitkit.to/ until the announcement is live. Deleting purchase flows and changing the existing Manual Setup flow are out of scope.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Transfer entry point] --> B{Geographically blocked?}
    B -->|Yes| C[Transfer Unavailable]
    C --> D[Manual Setup]
    B -->|No| E[Existing transfer flow]
    E --> F[Confirm]
    F --> G{Availability check}
    G -->|Unavailable| C
    G -->|Available| H[Fund order]
    F --> I[Retained hardware transaction]
    I -->|Retry skips check| H
Loading

Reviews (1) · Last reviewed commit: "fix: show the sunset sheet in every lang..." · Reviewed by Greptile

Comment thread app/src/main/java/to/bitkit/viewmodels/TransferViewModel.kt Outdated
@github-actions

github-actions Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Regtest APK

Built from 9e10dc3 (run).

Download bitkit-dev-debug universal APK (expires in 30 days).

@talosmachina talosmachina left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No findings. Replaces the geo-blocked copy and the hidden Transfer To Spending button with a Transfer Unavailable sheet that routes to Manual Setup, and re-checks the geo state in TransferViewModel before any Blocktank order is created or a held one is paid. Reviewed 5bc8c29, full tier, reasoned from the code and CI (the Bitkit Android branch is not built on this reviewer's machine).

What I checked, and 7 candidates I ruled out

Read in full: TransferUnavailableSheet.kt, LocationBlockScreen.kt, FundingScreen.kt, SheetIntro.kt, the four entry points and the effect collector in ContentView.kt, TransferViewModel from onTransferToSpendingConfirm through isTransferUnavailable and onTransferToSpendingHwConfirm, LightningRepo.start/stop/updateGeoBlockState, CoreService.isGeoBlocked, the new tests in TransferViewModelTest, LightningRepoTest, FundingScreenTest.
Call sites traced: blocktankRepo.createOrder (only getOrCreateSpendingOrder), navigateToTransferSpendingStart (all four now gated), ReceiveRoute.GeoBlock (CJIT button and ReceiveAdditionalLiquidityAction.GeoBlocked), R.string.lightning__funding__text_blocked* (no references left after the removal in every locale).
Strings: the five new keys are present in all 16 strings.xml.
CI: build (assemble + testDevDebugUnitTest), lint, detekt green at 5bc8c29; the e2e-tests-local suites were still running.

Ruled out

  • Held order paid after the switch: paySpendingConfirmOrder re-checks after the retained-attempt and paid-order branches, so an accepted broadcast still completes and a fresh pay stops; covered by the new TransferViewModelTest case.
  • HW passphrase prompt before the sheet: the check now runs first, and onHwPassphraseSubmit re-enters onTransferToSpendingHwConfirm, which re-checks; isBroadcastRetry keeps a signed transfer's rebroadcast open.
  • Stale isGeoBlocked at cold start opens the purchase flow: possible for the length of the geocheck request, but the confirm and HW confirm both refresh it before createOrder, so no order is created.
  • Effect lost: transferEffects has no replay, but the RootNavHost collector lives for the whole nav host, so OnTransferUnavailable always has a subscriber when the confirm screen is up.
  • Geo state dropped on stop: both stop branches now carry isGeoBlocked over; wipeStorage still resets it, and the next start refreshes it.
  • Geocheck fails open (network error or non-403 returns false): unchanged by this PR, and Blocktank refusing the order is the backstop.
  • Onboarding slide 1 still says "not currently provide Lightning services in your country" when geo-blocked: real copy left behind, but onboarding__slide1_note is untouched by this diff, so it is not this PR's defect.

Merge confidence: 4/5, the e2e suites had not finished at review time and the four ContentView entry-point branches are covered only by journey J1, not by a test.

Reviewer model: claude-opus-5-5
Reasoning effort: Unknown (not recorded in metadata this run can read)

@ovitrif

ovitrif commented Oct 26, 2026

Copy link
Copy Markdown
Collaborator Author

Pushed 1fd64df:

  • 5bc8c29 adds the changelog fragment, keeps the geo state when the node stops, and checks availability before the hardware-wallet passphrase prompt.
  • 1fd64df runs the availability check before a hardware broadcast retry too, so a geo-blocked retry can't pay an old order (from the Greptile review).

just compile, just lint and TransferViewModelTest pass.

@ovitrif

ovitrif commented Oct 26, 2026

Copy link
Copy Markdown
Collaborator Author

Pushed 23dab9a, following Aldert's updated Blocktank-sunsetting frames in Figma (links in the description):

  • The sheet's left button reads Learn More.
  • Fund your spending balance leads with Manual Setup while geo-blocked. Transfer from Savings, a new Transfer from HW wallet row and Use Other Wallet are disabled, and Learn More sits at the bottom.
  • Receive › Spending › Receive Lightning funds shows the sheet's content instead of separate receive copy.

Design comparisons and new recordings are in the description.

@ovitrif

ovitrif commented Oct 26, 2026

Copy link
Copy Markdown
Collaborator Author

Pushed 9af8509: Learn More, on the sheet and on the Funding screen, now opens https://blog.bitkit.to/, where the sunset article appears once it is published, so the link needs no further change. The recordings show the earlier bitkit.to target.

@ovitrif
ovitrif force-pushed the fix/blocktank-sunset-sheet branch from a1412d5 to a1c333c Compare October 26, 2026 17:23
@ovitrif

ovitrif commented Oct 26, 2026

Copy link
Copy Markdown
Collaborator Author

Tested manually before #1696 (comment), will retest.

@ovitrif

ovitrif commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator Author

Rebased onto master after #1699. Background Payments is repurposed for Paykit notifications rather than dropped (head f8641f4):

  • The settings route, screen, intro and Home card stay, reworded for subscription reminders and payment requests.
  • Keep Bitkit active in background stays.
  • The Blocktank push registration, its notification types and the wake worker are removed, since Blocktank no longer sends those pushes.
  • Proposing or accepting a subscription, or accepting an allowance, asks for notification permission if it isn't granted.

just compile, just test and just lint pass.

@piotr-iohk piotr-iohk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QA review

Scope: Reviewed the full PR diff against its merge base, at a1c333c0. No earlier assessment baseline was available.

2 actionable findings — resolve or provide an evidence-backed rebuttal.

A failed or non-403 geocheck on confirm still pays a held Blocktank order: the new availability check treats that result as not blocked, then broadcasts. Removing Background Payments also leaves Keep Bitkit active in background stuck on for wallets that had already enabled it.

Compared with bitkit-ios#1127 at 1883357a for this flow only. The confirm guard has the same fail-open geocheck. iOS still exposes a notification toggle after dropping Blocktank registration. Earlier comments on this PR about a missing changelog fragment and a hardware broadcast retry skipping the check do not apply at this revision: the fragment is present, and the availability check runs before that retry.

Validation: this review did not execute unit tests or a device. The new TransferViewModelTest case was inspected; it stubs an already-blocked state and does not run a failed geocheck. Author-reported just compile, just test, and just lint on this head were not re-run here. Device testing: not performed in this review. Journey J1 evidence in the PR body is from 23dab9a, except the Settings row check noted for a1c333c.

Suggested additional test cases

  1. Android, dev build, geoblocking on, spending confirm already holding a Blocktank order and no broadcast. Block https://api1.blocktank.to/api/geocheck or make it return a non-403 error, then swipe to transfer. Expected: the Transfer Unavailable sheet opens and no on-chain transaction is broadcast.
  2. Android, a wallet that already has Keep Bitkit active in background enabled, updated to this build. Background the app. Expected: the persistent node notification stops, or Settings still offers a way to turn that behavior off.

Findings

  • [MEDIUM] A failed geocheck still pays a held Blocktank order — inline at app/src/main/java/to/bitkit/viewmodels/TransferViewModel.kt:485.
  • [LOW] Keep Bitkit active can no longer be turned off — inline at app/src/main/java/to/bitkit/ui/settings/SettingsScreen.kt:370.

Reviewer model: grok-4.7
Reasoning effort: high

Comment thread app/src/main/java/to/bitkit/viewmodels/TransferViewModel.kt Outdated
Comment thread app/src/main/java/to/bitkit/ui/settings/SettingsScreen.kt
@ovitrif

ovitrif commented Oct 26, 2026

Copy link
Copy Markdown
Collaborator Author

Reviewed the full PR diff against its merge base, at a1c333c

@piotr-iohk thanks, both findings are fixed. Since a1c333c (head 64e3637):

  • Background Payments is repurposed for Paykit notifications instead of removed: the settings route, screen, intro, Home card and Keep Bitkit active stay, reworded for subscription reminders and payment requests. The prompt shows only to users with a Paykit subscription, and the preview shows the subscription reminder.
  • The Lightning ties are removed: Blocktank push registration, its notification types and the wake worker.
  • Proposing or accepting a subscription, or accepting an allowance, asks for notification permission if it isn't granted.
  • The confirm geocheck fails closed, so a failed or non-200 check no longer pays a held order.

Could you re-check on the new head?

@ovitrif
ovitrif requested a review from piotr-iohk October 26, 2026 18:06
@ovitrif

ovitrif commented Oct 26, 2026

Copy link
Copy Markdown
Collaborator Author

Pushed 2dfbc86: the notification shown while "Keep Bitkit active in background" is on now reads "Bitkit is running in the background so you can receive payments and requests", translated in every locale. It previously named only Lightning payments, which no longer fits now that the setting covers Paykit payments and requests.

@piotr-iohk piotr-iohk left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QA review

Scope: Follow-up review at 2dfbc86b of the changes since a1c333c0, using the inherited baseline review. This pass re-reviewed confirm-time geocheck failures, the Paykit repurposing of background payments, the string and unit-test updates in that delta, and the matching iOS behavior at c124633c. Inherited coverage: the Transfer Unavailable sheet with Learn More and Continue into Manual Setup, geo-blocked savings, spending, hardware, and funding entry points, Receive lightning location-block content, and geo refresh at node start with preservation when the node stops.

3 actionable findings — resolve or provide an evidence-backed rebuttal.

A failed or unexpected confirm-time geocheck is written into the shared geo flag, so savings, funding, and Receive lightning stay on the sunset path until the next geo refresh. Accepting a due subscription, or an allowance, can leave the sheet before the notification permission result is stored, so reminders and the keep-active service still see notifications as off. docs/timed-sheets.md still describes a Lightning-balance prompt; the sheet requires a Paykit subscription.

Validation was source inspection of 2dfbc86b. Unit tests, journeys, and device runs were not executed. TransferViewModelTest mocks isTransferBlocked() and does not cover a failed geocheck's effect on lightningState. iOS c124633c was compared only for this follow-up's geocheck and notification paths. Device testing: not performed in this review.

Suggested additional test cases

  • Android, geoblocking enabled, geocheck forced to time out or return a non-403 status, spending confirm open for an allowed region. Swipe confirm. The Transfer Unavailable sheet opens and nothing is paid; after dismiss, Savings Transfer To Spending opens the transfer flow again without an app restart.
  • Android 13+, notifications not granted, subscription accept starts a payment. Tap subscribe, leave the system permission dialog up until Send replaces the sheet, then tap Allow. Settings shows notifications on, and subscription reminders are scheduled, without opening the notifications settings screen.
  • Android, notifications off, Paykit subscription present, Lightning balance zero. Open Home after the ask interval. The notification prompt appears. Repeat with a Lightning balance and no subscription: the prompt stays hidden.

Earlier findings reconciled at this revision: 4 verified fixed.

Findings

  • [MEDIUM] Failed confirm geocheck sticks as geo-blocked — inline at app/src/main/java/to/bitkit/repositories/LightningRepo.kt:675.
  • [MEDIUM] Subscription permission grant is dropped when the sheet closes — inline at app/src/main/java/to/bitkit/ui/screens/subscriptions/SubscriptionsScreen.kt:739.
  • [LOW] Timed-sheet doc still requires a Lightning balance — inline at app/src/main/java/to/bitkit/utils/timedsheets/sheets/NotificationsTimedSheet.kt:25.

Reviewer model: grok-4.7
Reasoning effort: high

Comment thread app/src/main/java/to/bitkit/repositories/LightningRepo.kt
@ovitrif

ovitrif commented Oct 26, 2026

Copy link
Copy Markdown
Collaborator Author

@piotr-iohk

Android, geoblocking enabled, geocheck forced to time out or return a non-403 status, spending confirm open for an allowed region. Swipe confirm. The Transfer Unavailable sheet opens and nothing is paid; after dismiss, Savings Transfer To Spending opens the transfer flow again without an app restart.

Blocktank stopped selling channels for good, so there is no allowed region anymore. The first half holds (the sheet opens, nothing is paid); staying on the sunset path afterwards is intended.

Pushed 1cda841:

  • MainActivity.onResume() copies the OS notification permission into notificationsGranted, so a grant from a dialog launched by a subscription or allowance sheet that has since closed is kept.
  • docs/timed-sheets.md describes the Notifications sheet and its Paykit-subscription gate.

@ovitrif
ovitrif requested a review from piotr-iohk October 26, 2026 21:48
@ovitrif

ovitrif commented Oct 26, 2026

Copy link
Copy Markdown
Collaborator Author

Pushed 9e10dc3: Blocktank's nodes are no longer special.

  • LDK no longer trusts them for zero-conf or to broadcast our force closes, so a force close with Blocktank now broadcasts and fee-bumps from this wallet. Before, LDK skipped that broadcast for trusted peers, and with Blocktank's node no longer acting, the funds stayed in "claimable on channel close".
  • The hardcoded Blocktank node list, the info.nodes fetch, the startup connect and fallback, and the trusted-peer graph checks are removed.
  • Startup now disconnects stored peers with no channel and no claimable balance, and does nothing while a sweep is pending.
  • The close flow treats a Blocktank channel like any other: Force Transfer is offered for every channel once the cooperative close gives up.

The PR body lists the side effects checked.

@ovitrif

ovitrif commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator Author

QA:
Tested on a Pixel 10 Pro at c5f14db (this PR's head at the time), on regtest against staging Blocktank in read-only mode, paired with an iPhone running synonymdev/bitkit-ios#1127. The trusted-peer fix was verified with an equivalent local change before 9e10dc3 landed.

✅ Transfer Unavailable sheet

Savings › Transfer To Spending opens the sheet. Learn More opens blog.bitkit.to and Continue opens Manual Setup.

a-c1.mp4

✅ Manual setup still works

A channel to the staging Blocktank node opens with no service fee, confirms, and routes Lightning payments both ways between the two phones.

ConfirmAfter swipe

✅ Receive with a channel

Receive › Spending shows a normal invoice. The content for a wallet with no inbound capacity wasn't reachable with channels open, so it isn't covered.

a-c3.mp4

✅ Notifications for Paykit

Settings › Notifications shows the Paykit copy with the "Open Bitkit to review payment" preview. Accepting a subscription with notifications revoked asks for permission. The subscription-due reminder arrives in the background, and in the foreground the in-app sheet shows instead. The "Keep Bitkit active" notification shows on device; this capture predates its new copy.

✅ Allowance

A request from this phone within the iPhone's $5 cap is paid automatically. One over it (10,000 sats, about $8) asks for approval, then pays.

✅ Transfer to Savings with Blocktank

The cooperative close failed because LND's closing fee (141 sats) was below LDK's minimum (182), so it fell back to a force close. ldk-node never broadcast that close, because the config trusted Blocktank's node to broadcast it, and 199,056 sats stayed claimable. Without the trusted peers the close broadcast on first launch and 197,998 sats came back after the timelock. That fix is in this PR.

This branch has not been deployed

No deployments
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.

3 participants