Skip to content

fix: prevent cleared Bolt11 invoices from appearing in transaction history#111

Open
Delgado74 wants to merge 4 commits into
lachispame:mainfrom
Delgado74:fix/clear-invoice-removes-from-history
Open

fix: prevent cleared Bolt11 invoices from appearing in transaction history#111
Delgado74 wants to merge 4 commits into
lachispame:mainfrom
Delgado74:fix/clear-invoice-removes-from-history

Conversation

@Delgado74
Copy link
Copy Markdown
Contributor

@Delgado74 Delgado74 commented May 12, 2026

Description

Fixes #107. When a user generates a Bolt11 invoice from the receive screen and clears it (via the "Clear invoice" button, 10-minute timeout, or navigating away), the invoice should not appear in the transaction history. Previously, it remained visible because the invoice was only removed from local UI state without any cancellation on the LNBits server or local record of the cleared invoice.

Changes

Why additional modifications were needed beyond issue #107 proposals

The original issue proposed four options (A-D), with Option D (hybrid: server cancel + local filtering) as the recommended approach. During implementation, three additional problems were discovered that required going beyond the original proposal:

  1. **Race condition in **: The original Option D added the payment hash to the cleared set only inside the async method — AFTER an HTTP call to LNBits. If the user navigated to the history screen before this async operation completed, the hash wasn’t in the set yet, and the invoice appeared.

  2. Timeout and dispose were not covered: The 10-minute invoice monitoring timeout handler and the widget’s method (when the user navigates away) both cleared locally but never recorded the hash anywhere. These paths left pending invoices visible in history.

  3. No persistence across app restarts: The original proposals only kept the cleared hashes in an in-memory . If the app was closed and reopened (or crashed), the set was empty and ALL previously cleared invoices reappeared in history.

To solve all three, we added:

  • **** (lib/services/cleared_invoice_store.dart): a singleton that persists cleared payment hashes to as JSON, surviving app restarts and crashes.
  • **** (9receive_screen.dart): a synchronous helper that records the hash to the persistent store before any async operation. Used by all three discard paths (clear button, timeout, dispose).
  • Hash recorded synchronously: In , the hash is added to the store BEFORE the fire-and-forget server cancellation attempt, eliminating race conditions entirely.

Files changed

File Change
lib/services/cleared_invoice_store.dart New. Singleton persisting cleared invoice hashes via SharedPreferences
lib/services/invoice_service.dart Added cancelInvoice() method attempting DELETE on LNBits API endpoints
lib/screens/9receive_screen.dart Added _discardInvoice() helper. Updated _clearInvoice(), timeout handler, and dispose() to synchronously record hash. Simplified _tryCancelInvoiceOnServer()
lib/screens/7history_screen.dart _filteredTransactions now excludes pending transactions whose hash is in ClearedInvoiceStore
lib/main.dart Initialize ClearedInvoiceStore on app startup

Summary by CodeRabbit

  • New Features

    • Persist cleared invoices so they remain cleared across app restarts.
    • Generated invoices are recorded as cleared when discarded, cleared by the user, or when monitoring times out.
    • Invoice clearing triggers server-side cancellation attempts.
  • Bug Fixes

    • Cleared invoices are excluded from the transaction history display.

Review Change Stack

Delgado74 added 2 commits May 12, 2026 11:34
…g transactions

When a user generates a Bolt11 invoice from the receive screen and
presses 'Clear invoice', the invoice remained visible in the transaction
history because _clearInvoice() only cleared local UI state without
cancelling the pending invoice on the LNBits server.

Add cancelInvoice() method to InvoiceService that attempts DELETE on
LNBits API endpoints. If the server does not support cancellation, the
payment hash is stored in a shared set and filtered from the history
screen locally.
…story

When a user generated a Bolt11 invoice on the receive screen and then
pressed 'Clear invoice', or when the 10-minute monitoring timeout
expired, or when navigating away, the invoice remained visible in the
transaction history. This happened because the invoice was only removed
from local UI state but was never cancelled on the LNBits server, and
no local record of the cleared invoice was kept.

Key changes:
- Add cancelInvoice() to InvoiceService: attempts DELETE on LNBits
  API endpoints to cancel the pending invoice server-side
- Add ClearedInvoiceStore: persists cleared invoice payment hashes
  to SharedPreferences as JSON, surviving app restarts and crashes
- Add _discardInvoice() helper: used by both clear and timeout paths
  to ensure the hash is always recorded before async cancellation
- Update HistoryScreen filter: excludes pending transactions whose
  payment hash is in the cleared set

All discard paths (_clearInvoice, timeout, dispose) now record the
hash synchronously before async cancellation is attempted, eliminating
race conditions between clearing and history navigation.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 12, 2026

Warning

Rate limit exceeded

@Delgado74 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 42 minutes and 19 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 79c3787e-81d8-4312-b785-d4548a176cad

📥 Commits

Reviewing files that changed from the base of the PR and between 7079d97 and 52471dd.

📒 Files selected for processing (5)
  • lib/main.dart
  • lib/screens/7history_screen.dart
  • lib/screens/9receive_screen.dart
  • lib/services/cleared_invoice_store.dart
  • lib/services/invoice_service.dart
📝 Walkthrough

Walkthrough

Adds a persisted ClearedInvoiceStore, loads it at app startup, records cleared/discarded invoice hashes from ReceiveScreen (and attempts server cancellation), and filters those hashes out of HistoryScreen results.

Changes

Cleared Invoice Tracking and Cancellation

Layer / File(s) Summary
Cleared invoice store implementation
lib/services/cleared_invoice_store.dart
New singleton service persisting cleared invoice hashes using shared_preferences. Provides load(), add(hash), contains(hash), and all.

|App startup initialization
lib/main.dart|Loads ClearedInvoiceStore at startup with await ClearedInvoiceStore.instance.load() before runApp().|

|Invoice cancellation API
lib/services/invoice_service.dart|New cancelInvoice(serverUrl, adminKey, paymentHash) attempts DELETE against LNBits endpoints and returns success (200/204) or failure.|

|ReceiveScreen invoice tracking and cancellation
lib/screens/9receive_screen.dart|Records generated invoice paymentHash into ClearedInvoiceStore on clear, discard (timeout), and dispose; cancels local timers and starts async server cancellation via _tryCancelInvoiceOnServer().|

|HistoryScreen cleared invoice filtering
lib/screens/7history_screen.dart|Filters out pending transactions whose paymentHash is present in ClearedInvoiceStore before applying incoming/outgoing/all filters.|

Sequence Diagram

sequenceDiagram
  participant User
  participant ReceiveScreen
  participant ClearedInvoiceStore
  participant InvoiceService
  participant LNBits
  participant HistoryScreen
  User->>ReceiveScreen: Generate invoice
  ReceiveScreen->>ReceiveScreen: set _generatedInvoice
  User->>ReceiveScreen: Clear / Discard / Timeout
  ReceiveScreen->>ClearedInvoiceStore: add(paymentHash)
  ReceiveScreen->>InvoiceService: _tryCancelInvoiceOnServer(paymentHash) (async)
  InvoiceService->>LNBits: DELETE /api/v1/payments/{paymentHash}
  alt Server cancellation succeeds
    LNBits-->>InvoiceService: 200/204
  else Server cancellation fails
    InvoiceService->>LNBits: DELETE /api/v1/wallet/payment/{paymentHash}
  end
  User->>HistoryScreen: View transaction history
  HistoryScreen->>ClearedInvoiceStore: contains(paymentHash)?
  ClearedInvoiceStore-->>HistoryScreen: exclude from display
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • lachispame/lachispa#85: Receive-screen invoice generation and clear/timeout actions intersect with this PR's invoice tracking and cancellation logic.

Poem

🐰 I nibble hashes, tuck them tight,

Saved in burrows out of sight,
Cleared and silent, history neat,
No phantom invoices to greet,
Hops of joy — the ledger's sweet.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: preventing cleared invoices from appearing in transaction history, which is the primary objective of the PR.
Linked Issues check ✅ Passed The PR fully implements Option D (hybrid approach) from issue #107: attempts server-side cancellation via new cancelInvoice() method in InvoiceService [#107], records cleared hashes persistently via ClearedInvoiceStore [#107], filters history based on cleared hashes [#107], and handles all three discard paths (clear, timeout, dispose) [#107].
Out of Scope Changes check ✅ Passed All changes are directly scoped to issue #107: ClearedInvoiceStore for persistence, cancelInvoice() for server-side cancellation, history filtering, and initialization logic all address the core requirement to prevent cleared invoices from appearing in history.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/screens/9receive_screen.dart`:
- Around line 129-131: The discard/dispose paths currently only record cleared
invoices locally via
ClearedInvoiceStore.instance.add(_generatedInvoice!.paymentHash) (seen where
_generatedInvoice is handled) but do not attempt server cancellation; update
those paths (the discard and dispose flows that call
ClearedInvoiceStore.instance.add and any similar local-only branches) to also
fire a best-effort, unawaited cancellation by calling
unawaited(_tryCancelInvoiceOnServer(hash)) with the same payment hash (e.g., use
_generatedInvoice!.paymentHash or the local hash variable) so the upstream
pending invoice is best-effort cancelled while preserving the existing local
recording.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6886fec3-b482-4f11-9b19-6de8f9e4abec

📥 Commits

Reviewing files that changed from the base of the PR and between ac3e168 and 5646db6.

📒 Files selected for processing (5)
  • lib/main.dart
  • lib/screens/7history_screen.dart
  • lib/screens/9receive_screen.dart
  • lib/services/cleared_invoice_store.dart
  • lib/services/invoice_service.dart

CodeRabbit review found that _discardInvoice() and dispose() only
recorded the cleared invoice hash locally but did not fire a best-effort
server cancellation. This could leave pending invoices active on LNBits
even when the user navigated away or the monitoring timeout fired.

Add unawaited(_tryCancelInvoiceOnServer(hash)) to both paths so the
DELETE attempt is always made regardless of how the invoice is discarded.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
lib/screens/9receive_screen.dart (1)

122-136: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

context.read from dispose() is unsafe and wallet.inKey is the wrong credential for server cancellation.

The call to _tryCancelInvoiceOnServer from dispose() (line 133) invokes context.read<WalletProvider>() and context.read<AuthProvider>() (lines 824–825), which is unsafe during widget teardown. Per Flutter provider documentation, this can throw "Looking up a deactivated widget's ancestor is unsafe," and the error will be silently swallowed by the empty catch (_) at line 836, leaving invoices un-cancelled with no signal.

Additionally, the method passes wallet.inKey as the adminKey parameter to cancelInvoice() (line 828). Since WalletInfo has both adminKey and inKey fields, and only the admin key can perform DELETE operations on the LNBits API, this will fail to cancel invoices on the server. This same bug appears in createInvoice() and checkInvoiceStatus() calls.

Fix: Cache serverUrl, wallet, and auth data after invoice generation into _State fields and pass them directly to _tryCancelInvoiceOnServer instead of resolving from context. Use wallet.adminKey instead of wallet.inKey for all server operations.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/screens/9receive_screen.dart` around lines 122 - 136, The dispose() call
is unsafe because _tryCancelInvoiceOnServer currently resolves
WalletProvider/AuthProvider from context and uses wallet.inKey; change the flow
to cache serverUrl, WalletInfo, and auth credentials into State fields when you
generate the invoice (e.g., where _generatedInvoice is set), then have dispose()
call unawaited(_tryCancelInvoiceOnServer(cachedServerUrl, cachedWallet,
cachedAuth, ...)) using those cached fields; also update all server calls
(createInvoice(), checkInvoiceStatus(), _tryCancelInvoiceOnServer) to use
wallet.adminKey instead of wallet.inKey so DELETE/auth operations use the admin
credential. Ensure _tryCancelInvoiceOnServer signature and calls are updated to
accept the cached values rather than reading from context.
🧹 Nitpick comments (1)
lib/screens/9receive_screen.dart (1)

790-820: ⚡ Quick win

De-duplicate _clearInvoice and _discardInvoice.

The bodies are identical except for the trailing snackbar. Have _clearInvoice delegate to _discardInvoice and then show the snackbar — keeps the cleanup/recording logic in one place so future tweaks (e.g., capturing the server credentials suggested above) only need to land once.

♻️ Proposed refactor
   void _clearInvoice() {
-    _invoicePaymentTimer?.cancel();
-    _invoicePaymentTimeoutTimer?.cancel();
-
-    if (_generatedInvoice != null) {
-      final hash = _generatedInvoice!.paymentHash;
-      ClearedInvoiceStore.instance.add(hash);
-      unawaited(_tryCancelInvoiceOnServer(hash));
-    }
-
-    setState(() {
-      _generatedInvoice = null;
-    });
+    _discardInvoice();
     _showAccentSnackBar(
       icon: Icons.check_circle,
       message: AppLocalizations.of(context)!.invoice_cleared_message,
     );
   }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/screens/9receive_screen.dart` around lines 790 - 820, Refactor to remove
duplicate cleanup logic by making _discardInvoice contain the shared
cancellation/clearing/recording logic (cancel _invoicePaymentTimer and
_invoicePaymentTimeoutTimer, add paymentHash to ClearedInvoiceStore, call
unawaited(_tryCancelInvoiceOnServer(hash)), and setState to clear
_generatedInvoice), then have _clearInvoice simply call _discardInvoice() and
afterwards call _showAccentSnackBar(...) to display the success message; update
references to paymentHash, ClearedInvoiceStore.instance,
_tryCancelInvoiceOnServer, and setState in those functions to ensure behavior is
identical after delegating.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/screens/9receive_screen.dart`:
- Around line 130-134: The call to ClearedInvoiceStore.instance.add(hash)
returns a Future and must be wrapped with unawaited(...) to avoid dropping the
Future and to match the surrounding pattern (_tryCancelInvoiceOnServer is
already unawaited); replace direct calls to
ClearedInvoiceStore.instance.add(hash) with
unawaited(ClearedInvoiceStore.instance.add(hash)) at all three call sites in
this file (the branch guarded by _generatedInvoice != null and the other two
occurrences referenced in the review) so persistence I/O errors are not silently
discarded.
- Around line 822-837: In _tryCancelInvoiceOnServer replace the read-only
invoice key with the wallet's admin key when calling
InvoiceService.cancelInvoice: pass wallet.adminKey (not wallet.inKey) as the
adminKey argument to ensure the LNBits DELETE endpoint is authorized; locate the
call to cancelInvoice inside _tryCancelInvoiceOnServer and update the adminKey
parameter to use wallet.adminKey.

---

Outside diff comments:
In `@lib/screens/9receive_screen.dart`:
- Around line 122-136: The dispose() call is unsafe because
_tryCancelInvoiceOnServer currently resolves WalletProvider/AuthProvider from
context and uses wallet.inKey; change the flow to cache serverUrl, WalletInfo,
and auth credentials into State fields when you generate the invoice (e.g.,
where _generatedInvoice is set), then have dispose() call
unawaited(_tryCancelInvoiceOnServer(cachedServerUrl, cachedWallet, cachedAuth,
...)) using those cached fields; also update all server calls (createInvoice(),
checkInvoiceStatus(), _tryCancelInvoiceOnServer) to use wallet.adminKey instead
of wallet.inKey so DELETE/auth operations use the admin credential. Ensure
_tryCancelInvoiceOnServer signature and calls are updated to accept the cached
values rather than reading from context.

---

Nitpick comments:
In `@lib/screens/9receive_screen.dart`:
- Around line 790-820: Refactor to remove duplicate cleanup logic by making
_discardInvoice contain the shared cancellation/clearing/recording logic (cancel
_invoicePaymentTimer and _invoicePaymentTimeoutTimer, add paymentHash to
ClearedInvoiceStore, call unawaited(_tryCancelInvoiceOnServer(hash)), and
setState to clear _generatedInvoice), then have _clearInvoice simply call
_discardInvoice() and afterwards call _showAccentSnackBar(...) to display the
success message; update references to paymentHash, ClearedInvoiceStore.instance,
_tryCancelInvoiceOnServer, and setState in those functions to ensure behavior is
identical after delegating.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: dd069189-1d7f-4f56-8660-e129b4533a28

📥 Commits

Reviewing files that changed from the base of the PR and between 5646db6 and 7079d97.

📒 Files selected for processing (1)
  • lib/screens/9receive_screen.dart

Comment on lines +130 to +134
if (_generatedInvoice != null) {
final hash = _generatedInvoice!.paymentHash;
ClearedInvoiceStore.instance.add(hash);
unawaited(_tryCancelInvoiceOnServer(hash));
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm ClearedInvoiceStore.add signature
fd -t f 'cleared_invoice_store.dart' | xargs cat

Repository: lachispame/lachispa

Length of output: 1204


🏁 Script executed:

#!/bin/bash
# Find the receive screen file
fd -t f 'receive_screen.dart' -o '.*receive.*\.dart'

Repository: lachispame/lachispa

Length of output: 217


🏁 Script executed:

#!/bin/bash
# Find the receive screen file correctly
fd 'receive' --type f

Repository: lachispame/lachispa

Length of output: 129


🏁 Script executed:

#!/bin/bash
# Check line count and then examine the specific lines
wc -l lib/screens/9receive_screen.dart
echo "---"
# Extract the three relevant sections
echo "Lines 128-136:"
sed -n '128,136p' lib/screens/9receive_screen.dart
echo "---"
echo "Lines 791-799:"
sed -n '791,799p' lib/screens/9receive_screen.dart
echo "---"
echo "Lines 810-818:"
sed -n '810,818p' lib/screens/9receive_screen.dart

Repository: lachispame/lachispa

Length of output: 1042


Wrap ClearedInvoiceStore.instance.add(hash) with unawaited() at all three call sites.

ClearedInvoiceStore.add() returns Future<void> and performs async SharedPreferences I/O. The current code at lines 132, 796, and 814 drops the returned Future without unawaited(), which violates the unawaited_futures lint and silently discards persistence errors. Wrap each call in unawaited(...) for consistency with the adjacent _tryCancelInvoiceOnServer call.

♻️ Proposed change (apply at all three sites)
-      ClearedInvoiceStore.instance.add(hash);
+      unawaited(ClearedInvoiceStore.instance.add(hash));
       unawaited(_tryCancelInvoiceOnServer(hash));

Also applies to: 796, 814

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/screens/9receive_screen.dart` around lines 130 - 134, The call to
ClearedInvoiceStore.instance.add(hash) returns a Future and must be wrapped with
unawaited(...) to avoid dropping the Future and to match the surrounding pattern
(_tryCancelInvoiceOnServer is already unawaited); replace direct calls to
ClearedInvoiceStore.instance.add(hash) with
unawaited(ClearedInvoiceStore.instance.add(hash)) at all three call sites in
this file (the branch guarded by _generatedInvoice != null and the other two
occurrences referenced in the review) so persistence I/O errors are not silently
discarded.

Comment on lines +822 to +837
Future<void> _tryCancelInvoiceOnServer(String paymentHash) async {
try {
final walletProvider = context.read<WalletProvider>();
final authProvider = context.read<AuthProvider>();
final serverUrl = authProvider.sessionData?.serverUrl;
final wallet = walletProvider.primaryWallet;

if (serverUrl == null || wallet == null) return;

await _invoiceService.cancelInvoice(
serverUrl: serverUrl,
adminKey: wallet.inKey,
paymentHash: paymentHash,
);
} catch (_) {}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect InvoiceService.cancelInvoice to confirm which key the endpoint expects
fd -t f 'invoice_service.dart' | xargs cat

Repository: lachispame/lachispa

Length of output: 50375


🏁 Script executed:

rg -A 20 'Future.*cancelInvoice' lib/services/

Repository: lachispame/lachispa

Length of output: 1376


🏁 Script executed:

rg -A 40 'Future<bool> cancelInvoice' lib/services/invoice_service.dart

Repository: lachispame/lachispa

Length of output: 1355


🏁 Script executed:

rg -B 5 -A 15 '_tryCancelInvoiceOnServer' lib/screens/9receive_screen.dart

Repository: lachispame/lachispa

Length of output: 2176


🏁 Script executed:

fd -t f 'wallet' lib/models/ | xargs grep -l 'class.*Wallet' | head -1 | xargs grep -A 30 'class.*Wallet' | grep -E '(inKey|adminKey)'

Repository: lachispame/lachispa

Length of output: 313


Pass wallet.adminKey instead of wallet.inKey to cancelInvoice.

_tryCancelInvoiceOnServer at lines 822–837 passes wallet.inKey as adminKey to InvoiceService.cancelInvoice, but the LNBits DELETE endpoint for cancelling invoices requires the wallet's admin key, not the read-only invoice key. Using inKey causes a 401/403 response, which the empty catch (_) {} silently swallows. The invoice then remains live on the server while appearing cancelled locally.

Change line 833 to:

adminKey: wallet.adminKey,

The wallet model already provides both keys separately (see line 144: setAuthHeaders(wallet.inKey, wallet.adminKey)).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/screens/9receive_screen.dart` around lines 822 - 837, In
_tryCancelInvoiceOnServer replace the read-only invoice key with the wallet's
admin key when calling InvoiceService.cancelInvoice: pass wallet.adminKey (not
wallet.inKey) as the adminKey argument to ensure the LNBits DELETE endpoint is
authorized; locate the call to cancelInvoice inside _tryCancelInvoiceOnServer
and update the adminKey parameter to use wallet.adminKey.

@Delgado74 Delgado74 force-pushed the fix/clear-invoice-removes-from-history branch from 7079d97 to 52471dd Compare May 13, 2026 01:53
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.

Bug: Cleared Bolt11 invoices from receive screen still appear in transaction history

1 participant