Skip to content

feat: add Invoice Key QR screen for LaChispaPOS integration#99

Open
Delgado74 wants to merge 5 commits into
lachispame:mainfrom
Delgado74:feature/invoice-key-clean
Open

feat: add Invoice Key QR screen for LaChispaPOS integration#99
Delgado74 wants to merge 5 commits into
lachispame:mainfrom
Delgado74:feature/invoice-key-clean

Conversation

@Delgado74
Copy link
Copy Markdown
Contributor

@Delgado74 Delgado74 commented May 3, 2026

Resolves #68


Description:
Adds a dedicated screen to display the invoice key (readKey) as a QR code, accessible from Settings. Enables POS integration and allows external apps to read the invoice key.


How it works:

  • New InvoiceKeyScreen accessible from Settings > Invoice Key QR
  • Displays the wallet's invoice key (readKey) as a QR code
  • Includes copy button for easy copying

Use Cases:

  • POS Integration: External POS apps can scan the QR to get the invoice key programmatically
  • Backup: Users can export their invoice key for backup purposes

Files Modified:

  • lib/screens/19invoice_key_screen.dart - New screen with QR code display
  • lib/screens/17settings_screen.dart - Added link to Invoice Key screen in Settings menu

Summary by CodeRabbit

  • New Features
    • Added Invoice Key QR screen allowing users to view their invoice key as a QR code, toggle visibility, and copy to clipboard
    • New Invoice Key settings option for easy access to key management
    • Security warnings inform users about sharing invoice keys with trusted devices
    • Enhanced multi-language support across German, English, Spanish, French, Italian, Portuguese, and Russian

Review Change Stack

Delgado74 added 3 commits May 3, 2026 04:28
- Add InvoiceKeyScreen with QR code display for readKey
- Use readKey with fallback to inKey (least privilege)
- Add 'Invoice Key QR' option in Settings screen
- Update localizations for all 7 supported languages
- Make readKey required in WalletInfo model
- Update WalletProvider to forward readKey when updating wallet

Resolves lachispame#68
- Add invoice_key localization strings for all 7 languages
- Add currency_count plural support for localized currency display
- Regenerate localization files
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 3, 2026

Warning

Rate limit exceeded

@Delgado74 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 46 minutes and 21 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: 7e1208be-8113-449d-81e7-ba7373ca61b2

📥 Commits

Reviewing files that changed from the base of the PR and between fc0b9e0 and 5a588fd.

⛔ Files ignored due to path filters (8)
  • lib/l10n/generated/app_localizations.dart is excluded by !**/generated/**
  • lib/l10n/generated/app_localizations_de.dart is excluded by !**/generated/**
  • lib/l10n/generated/app_localizations_en.dart is excluded by !**/generated/**
  • lib/l10n/generated/app_localizations_es.dart is excluded by !**/generated/**
  • lib/l10n/generated/app_localizations_fr.dart is excluded by !**/generated/**
  • lib/l10n/generated/app_localizations_it.dart is excluded by !**/generated/**
  • lib/l10n/generated/app_localizations_pt.dart is excluded by !**/generated/**
  • lib/l10n/generated/app_localizations_ru.dart is excluded by !**/generated/**
📒 Files selected for processing (8)
  • lib/l10n/app_de.arb
  • lib/l10n/app_en.arb
  • lib/l10n/app_es.arb
  • lib/l10n/app_fr.arb
  • lib/l10n/app_it.arb
  • lib/l10n/app_pt.arb
  • lib/l10n/app_ru.arb
  • lib/screens/17settings_screen.dart
📝 Walkthrough

Walkthrough

This PR implements an invoice key QR display feature enabling business owners to share their invoice key with employees via QR code for LaChispaPOS integration. Changes include a new data field in WalletInfo, localization across seven languages, settings screen integration with styling refactoring, a complete new screen displaying the QR and masked/unmasked key with copy functionality, and provider formatting updates.

Changes

Invoice Key QR Display Feature

Layer / File(s) Summary
WalletInfo readKey field and serialization
lib/models/wallet_info.dart
Added readKey field to WalletInfo with constructor requirement and JSON serialization supporting readkey/read_key/readKey key variants in fromJson() and readkey emission in toJson().
Localization strings for invoice key QR feature
lib/l10n/app_de.arb, lib/l10n/app_en.arb, lib/l10n/app_es.arb, lib/l10n/app_fr.arb, lib/l10n/app_it.arb, lib/l10n/app_pt.arb, lib/l10n/app_ru.arb
Added currency_count ICU pluralization and invoice key QR strings (invoice_key_qr_title/description/subtitle, copy_invoice_key, invoice_key_show/hide, security warning, error/empty states) across all seven supported languages.
Settings screen refactoring and invoice key tile
lib/screens/17settings_screen.dart
Removed AppTokens-driven theming and replaced with hardcoded white/translucent colors and Inter font; added new "Invoice Key QR" settings tile that navigates to InvoiceKeyScreen; updated header builder signature and styling for back button, title, and chevron affordance.
InvoiceKeyScreen widget implementation
lib/screens/19invoice_key_screen.dart
New stateful widget displaying invoice key from WalletProvider.primaryWallet (preferring readKey unless empty, else inKey) as QR code and masked/unmasked text; includes visibility toggle, clipboard copy button with localized snackbar feedback, header with back button, and security warning panel.
WalletProvider formatting and maintenance
lib/providers/wallet_provider.dart
Refactored line-wrapping, indentation, and multiline formatting across state initialization, persistence helpers, wallet lifecycle methods, and debug output; no logic changes to wallet initialization, preferred selection, balance refresh, or wallet creation/deletion.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • lachispame/lachispa#75: Both PRs modify lib/screens/17settings_screen.dart and adjust theming; this PR replaces AppTokens usage with hardcoded styling while the retrieved PR migrated toward AppTokens, creating potential theming conflicts.

Poem

🐰 A rabbit's delight, oh what a sight!
QR codes gleam with invoice key light,
Employees now scan without admin fear,
Settings are styled, much cleaner and clear,
Business wallets unite, from far and near! 🌟

🚥 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 PR title accurately captures the main change: adding an InvoiceKeyScreen with QR functionality for LaChispaPOS integration, matching the primary objective and changeset.
Linked Issues check ✅ Passed All primary coding requirements from issue #68 are met: InvoiceKeyScreen created with QR display and copy button, readKey field added to WalletInfo, Settings integration completed, and localizations updated for 7 languages.
Out of Scope Changes check ✅ Passed All changes are directly aligned with issue #68 requirements. Minor refactoring in SettingsScreen (styling updates from AppTokens to hardcoded values) supports the new feature but is consistent with the stated objective of updating Settings UI.
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

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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: 2

🧹 Nitpick comments (1)
lib/screens/19invoice_key_screen.dart (1)

119-121: 💤 Low value

Simplify the key selection logic for better readability.

The current nested ternary with repeated null-coalescing is harder to read than necessary. Consider extracting the readKey check to a local variable:

♻️ Proposed refactor
-        final invoiceKey = (wallet?.readKey ?? '').isEmpty
-            ? (wallet?.inKey ?? '')
-            : (wallet?.readKey ?? '');
+        final readKey = wallet?.readKey ?? '';
+        final invoiceKey = readKey.isNotEmpty ? readKey : (wallet?.inKey ?? '');
🤖 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/19invoice_key_screen.dart` around lines 119 - 121, The ternary
expression used to compute invoiceKey is repetitive and hard to read; simplify
by extracting wallet?.readKey into a local variable (e.g., final readKey =
wallet?.readKey ?? '') then compute invoiceKey using that variable and fallback
to wallet?.inKey (e.g., invoiceKey = readKey.isEmpty ? (wallet?.inKey ?? '') :
readKey) so you avoid repeating the null-coalescing and nested ternary and
improve readability around the invoiceKey computation.
🤖 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/models/wallet_info.dart`:
- Line 7: The constructor change for class WalletInfo made the field readKey
required, which breaks callers that construct WalletInfo directly; change the
WalletInfo constructor to make readKey optional with a default (e.g., empty
string) so existing code continues to compile, while leaving fromJson
(WalletInfo.fromJson) unchanged (it already falls back to ''), and ensure the
field declaration final String readKey remains compatible with the new
constructor signature.
- Line 7: The Invoice Key QR screen is preferring readKey over inKey which is
reversed; update the logic in the invoice_key_screen widget (the code that
selects the key for the QR and the security text) to prefer walletInfo.inKey
first and only fall back to walletInfo.readKey when inKey is absent, and ensure
any displayed warning text and QR payload reference the chosen key (symbols:
inKey, readKey, createInvoice(), checkInvoiceStatus()) so POS devices receive
the invoice-creation key.

---

Nitpick comments:
In `@lib/screens/19invoice_key_screen.dart`:
- Around line 119-121: The ternary expression used to compute invoiceKey is
repetitive and hard to read; simplify by extracting wallet?.readKey into a local
variable (e.g., final readKey = wallet?.readKey ?? '') then compute invoiceKey
using that variable and fallback to wallet?.inKey (e.g., invoiceKey =
readKey.isEmpty ? (wallet?.inKey ?? '') : readKey) so you avoid repeating the
null-coalescing and nested ternary and improve readability around the invoiceKey
computation.
🪄 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: ebb27c17-05a0-4947-9f7c-a6cebfff42f4

📥 Commits

Reviewing files that changed from the base of the PR and between dbafc40 and fc0b9e0.

⛔ Files ignored due to path filters (8)
  • lib/l10n/generated/app_localizations.dart is excluded by !**/generated/**
  • lib/l10n/generated/app_localizations_de.dart is excluded by !**/generated/**
  • lib/l10n/generated/app_localizations_en.dart is excluded by !**/generated/**
  • lib/l10n/generated/app_localizations_es.dart is excluded by !**/generated/**
  • lib/l10n/generated/app_localizations_fr.dart is excluded by !**/generated/**
  • lib/l10n/generated/app_localizations_it.dart is excluded by !**/generated/**
  • lib/l10n/generated/app_localizations_pt.dart is excluded by !**/generated/**
  • lib/l10n/generated/app_localizations_ru.dart is excluded by !**/generated/**
📒 Files selected for processing (11)
  • lib/l10n/app_de.arb
  • lib/l10n/app_en.arb
  • lib/l10n/app_es.arb
  • lib/l10n/app_fr.arb
  • lib/l10n/app_it.arb
  • lib/l10n/app_pt.arb
  • lib/l10n/app_ru.arb
  • lib/models/wallet_info.dart
  • lib/providers/wallet_provider.dart
  • lib/screens/17settings_screen.dart
  • lib/screens/19invoice_key_screen.dart

final String name;
final String adminKey;
final String inKey;
final String readKey;
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

Breaking change: making readKey required may break existing code.

The constructor parameter is marked required (line 15), but this introduces a breaking change for any code that constructs WalletInfo objects directly. While fromJson safely handles missing values with an empty-string fallback (line 28), callers using the constructor directly will fail to compile without providing readKey.

Consider making readKey optional with a default value:

final String readKey;

WalletInfo({
  required this.id,
  required this.name,
  required this.adminKey,
  required this.inKey,
  this.readKey = '',  // Default to empty string
  required this.balanceMsat,
});

This preserves backward compatibility while still supporting the new field.

Also applies to: 15-15

🤖 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/models/wallet_info.dart` at line 7, The constructor change for class
WalletInfo made the field readKey required, which breaks callers that construct
WalletInfo directly; change the WalletInfo constructor to make readKey optional
with a default (e.g., empty string) so existing code continues to compile, while
leaving fromJson (WalletInfo.fromJson) unchanged (it already falls back to ''),
and ensure the field declaration final String readKey remains compatible with
the new constructor signature.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify LNBits key permission model and check if readKey can create invoices
rg -n -C3 'readKey|inKey' --type=dart -g '!**/l10n/**'

Repository: lachispame/lachispa

Length of output: 30508


🏁 Script executed:

# Search for the security warning mentioned in the review (app_en.arb:408)
find . -name "app_*.arb" -type f | head -5

Repository: lachispame/lachispa

Length of output: 173


🏁 Script executed:

# Look at the invoice key screen more closely
sed -n '115,125p' lib/screens/19invoice_key_screen.dart

Repository: lachispame/lachispa

Length of output: 490


🏁 Script executed:

# Check the app localization file for the security warning
rg -n "create invoices" -A2 -B2 --type=json

Repository: lachispame/lachispa

Length of output: 212


🏁 Script executed:

# Verify what operations actually use readKey vs inKey throughout the codebase
rg -n "\.readKey|\.inKey" lib/screens/ lib/services/ --type=dart | grep -E "(createInvoice|checkInvoice|readKey)" | head -20

Repository: lachispame/lachispa

Length of output: 245


🏁 Script executed:

# Check the security warning in app_en.arb around line 408
sed -n '400,420p' lib/l10n/app_en.arb

Repository: lachispame/lachispa

Length of output: 1044


🏁 Script executed:

# Search for references to the invoice key screen and its purpose
rg -n "invoice.*key|InvoiceKey" lib/screens/19invoice_key_screen.dart -A5 -B5 --type=dart | head -40

Repository: lachispame/lachispa

Length of output: 1400


🏁 Script executed:

# Check if readKey is used anywhere for actual invoice creation
rg -n "readKey" lib/services/ --type=dart -A2 -B2

Repository: lachispame/lachispa

Length of output: 45


🏁 Script executed:

# Look at the LNBits documentation or comments about key permissions
rg -n "readkey|inkey|read.*only|invoice.*creation" -i --type=dart lib/models/ lib/services/ | head -20

Repository: lachispame/lachispa

Length of output: 1657


🏁 Script executed:

# Final verification: check if readKey is ever used for any write operations
rg -n "readKey" lib/ --type=dart -A3 | grep -E "create|send|pay|invoice"

Repository: lachispame/lachispa

Length of output: 527


🏁 Script executed:

# Confirm: is readKey used anywhere except in invoice_key_screen?
rg -n "readKey" lib/ --type=dart --files-with-matches

Repository: lachispame/lachispa

Length of output: 164


Prefer inKey over readKey for the Invoice Key QR screen: the keys are reversed.

The logic in invoice_key_screen.dart (lines 119–121) currently prefers readKey and falls back to inKey. This is backwards:

  • LNBits key semantics: readKey is read-only; inKey creates invoices
  • Screen purpose: "Use this QR code with LaChispaPOS or other Lightning apps to receive payments" — requires invoice creation capability
  • Security warning: Correctly states "This key allows third parties to create invoices" — describing inKey, not readKey
  • All invoice operations throughout the codebase use inKey: createInvoice(), checkInvoiceStatus(), and Lightning Address setup
  • readKey is unused for any write operations in the entire codebase

The current implementation exposes a read-only key to POS devices, breaking payment reception. Swap the preference: use inKey first, fall back to readKey.

🤖 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/models/wallet_info.dart` at line 7, The Invoice Key QR screen is
preferring readKey over inKey which is reversed; update the logic in the
invoice_key_screen widget (the code that selects the key for the QR and the
security text) to prefer walletInfo.inKey first and only fall back to
walletInfo.readKey when inKey is absent, and ensure any displayed warning text
and QR payload reference the chosen key (symbols: inKey, readKey,
createInvoice(), checkInvoiceStatus()) so POS devices receive the
invoice-creation key.

…-clean

# Conflicts:
#	lib/screens/17settings_screen.dart
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.

Feature: Mostrar QR de Invoice Key para integración con LaChispaPOS

1 participant