Skip to content

# Title: feat(hce): Add HCE support for receiving payments via NFC#97

Draft
Delgado74 wants to merge 14 commits into
lachispame:mainfrom
Delgado74:feat/hce-receive
Draft

# Title: feat(hce): Add HCE support for receiving payments via NFC#97
Delgado74 wants to merge 14 commits into
lachispame:mainfrom
Delgado74:feat/hce-receive

Conversation

@Delgado74
Copy link
Copy Markdown
Contributor

@Delgado74 Delgado74 commented May 3, 2026

Description

This PR adds HCE (Host Card Emulation) support to LaChispa, enabling users to receive Lightning payments by emulating an NFC card. BoltCard reader mode is already working in production; this PR focuses on HCE.

Goal

Allow LaChispa users to receive payments by tapping their phone against another device running a Lightning wallet with HCE support.

Modes Available (After This PR)

  1. HCE Mode (New) - Emulate a contactless card

    • Target: Lightning wallets with HCE support
    • Exposes LNURL (flexible amount) or BOLT11 (fixed amount) via NFC
    • User selects "Emular HCE" → Phone acts as card
  2. BoltCard Reader Mode - Read physical BoltCards (Already in production)

    • Target: Physical BoltCard devices
    • Reads LNURLw from card, sends BOLT11 invoice to BoltCard callback
    • User selects "Cargar BoltCard" → Phone reads the card

Technical Implementation

Core Service: lib/services/nfc_charge_service.dart

  • NfcChargeService class with startChargeSession() method
  • ModoNfcRecibir enum: { hceWallet, lectorBoltcard }
  • HCE Mode: Uses FlutterNfcHce to emulate NFC card
    • Emits LNURL (if Lightning Address configured) or BOLT11 invoice
    • KHostApduService configured in AndroidManifest.xml
    • AID configuration in apduservice.xml
  • BoltCard Reader Mode: Uses NfcManager to read physical cards
    • LNURLw normalization and validation
    • BoltCard withdraw request protocol (tag: 'withdrawRequest')
    • Sends BOLT11 invoice to callback with k1 parameter
  • Clean separation: HCE stopped before reader mode (300ms delay) to prevent OS interception

UI Integration: lib/screens/9receive_screen.dart

  • Smart mode detection:
    • With invoice → Shows mode selector dialog (HCE / BoltCard)
    • Without invoice → Goes directly to HCE (BoltCard requires invoice)
  • NfcChargeSheet widget with real-time status updates
    • States: scanning, reading, charging, success, error
    • Proper SingleTickerProviderStateMixin for animations
    • AppLocalizations accessed in didChangeDependencies() (fixes InheritedWidget error)

Android Configuration (HCE Support)

  • AndroidManifest.xml:
    • NFC permissions: android.permission.NFC
    • HCE service: com.novice.flutter_nfc_hce.KHostApduService
    • Intent-filters for NFC tag dispatch: NDEF_DISCOVERED, TECH_DISCOVERED
    • Meta-data: nfc_tech_filter.xml for TECH_DISCOVERED
  • apduservice.xml: AID configuration for HCE (F0010203040506)
  • nfc_tech_filter.xml: ISO-DEP and Ndef tech lists
  • strings.xml: HCE service display name

Internationalization

  • Added 12 new i18n keys across 7 languages (ES, EN, DE, FR, IT, PT, RU)
  • Keys: nfc_mode_title, nfc_mode_boltcard, nfc_mode_hce, error messages
  • Localized error messages for BoltCard reader mode
  • Debug logs kept in Spanish (development environment)

Bug Fixes

  • Fixed InheritedWidget error by moving AppLocalizations to didChangeDependencies()
  • Fixed _tabController not defined in _NfcChargeSheetState
  • Added SingleTickerProviderStateMixin for proper TickerProvider
  • Fixed HCE service interference with reader mode (added 300ms delay)
  • Proper invalidateAfterFirstRead: false for BoltCard mode

Dependencies Added

  • flutter_nfc_hce: ^0.1.8 - HCE support
  • nfc_manager: ^3.5.0 - NFC reader support

Testing Checklist

Please test and check the following:

  • HCE Mode without amount (uses LNURL):

    • Go to Receive → NFC (should go directly to HCE)
    • Lightning wallet reads LNURL successfully
    • Wallet allows entering any amount
    • Payment completes successfully
  • HCE Mode with fixed amount (BOLT11):

    • Go to Receive → Enter amount → Generate invoice → NFC
    • Select "Emular HCE"
    • Lightning wallet reads BOLT11 with fixed amount
    • Payment completes successfully
  • BoltCard Reader Mode (Already in production - verify still works):

    • Go to Receive → Enter amount → Generate invoice → NFC
    • Select "Cargar BoltCard"
    • Tap physical BoltCard to phone
    • BoltCard loads with invoice successfully
  • UI/UX:

    • Mode selector appears when invoice exists
    • Direct HCE when no invoice (no unnecessary dialog)
    • Proper status messages in Spanish/English
    • NFC status sheet shows correct state
  • Internationalization:

    • All NFC texts localized in ES, EN, DE, FR, IT, PT, RU
    • Error messages show in correct language

Related Issues

  • Implements HCE for Lightning wallet compatibility
  • Complements existing BoltCard reader (already in production)

Pre-merge Checklist

  • Code compiles without errors (flutter build apk --debug)
  • No analyzer warnings in modified files
  • Commits are clean (rebased on lachispame/main)
  • i18n keys added for all supported languages
  • AndroidManifest properly configured for HCE
  • Tested on physical device (Xiaomi Redmi Note 9)
  • HCE tested with Lightning wallet
  • BoltCard verified still working (regression test)

Note: BoltCard reader mode is already working in production. This PR adds HCE support to complement it. The commit history is clean with 9 commits implementing the full feature.

Summary by CodeRabbit

  • New Features

    • Added NFC Host Card Emulation (HCE) mode and a selector to choose BoltCard reader or HCE wallet
    • Auto-start NFC flows after invoice generation and mode-aware NFC charge UI/status messages
  • Platform

    • Android now registers HCE support and NFC tech handling so devices can act as/accept wallet HCE sessions
  • Internationalization

    • Added NFC UI and error message translations (EN, DE, ES, FR, IT, PT, RU)

Delgado74 added 9 commits May 2, 2026 19:38
… intent filters

- Add mode selector dialog when invoice exists (BoltCard vs HCE)
- Skip dialog when no invoice (HCE direct, BoltCard needs invoice)
- Stop HCE before reader mode to prevent system interception
- Add NFC intent-filters to Manifest for foreground dispatch
- Create nfc_tech_filter.xml for TECH_DISCOVERED
- Use invalidateAfterFirstRead:false for BoltCard mode
- Fix lnurlOrInvoice parameter name in charge service
- Add i18n keys for NFC mode selector (BoltCard/HCE)
- Add error messages for BoltCard reader mode
- Update receive screen to use AppLocalizations
- Fix NfcChargeService to accept AppLocalizations
- Move service init to didChangeDependencies (fix InheritedWidget error)
- Add SingleTickerProviderStateMixin to _NfcChargeSheetState
- Fix _tabController not defined error
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 3, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b386eb86-081c-43ce-8004-fa07384e60b2

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds selectable NFC receive modes (HCE emission vs BoltCard reader). Registers an Android HCE service and NFC tech filters in the manifest and resources, adds the flutter_nfc_hce dependency, extends the NFC charge service and ReceiveScreen to handle a modo selector, and adds localized strings across languages.

Changes

NFC Mode Support & Android HCE Integration

Layer / File(s) Summary
Data / Types
lib/services/nfc_charge_service.dart
Adds enum ModoNfcRecibir { hceWallet, lectorBoltcard }.
Core Service Logic
lib/services/nfc_charge_service.dart
NfcChargeService now requires AppLocalizations; startChargeSession signature changed to accept lnurlOrInvoice and modo; branches between HCE emission (_hce.startNfcHce(...)) and BoltCard reader flow with stricter tag validation, localized error messages, session/processing guards, and stop logic.
Android HCE Wiring
android/app/src/main/AndroidManifest.xml, android/app/src/main/res/xml/apduservice.xml, android/app/src/main/res/xml/nfc_tech_filter.xml, android/app/src/main/res/values/strings.xml
Manifest: MainActivity intent-filters for android.nfc.action.NDEF_DISCOVERED (mime text/plain) and android.nfc.action.TECH_DISCOVERED; meta-data points to @xml/nfc_tech_filter; registers exported HCE service com.novice.flutter_nfc_hce.KHostApduService with android:permission="android.permission.BIND_NFC_SERVICE" and HOST_APDU_SERVICE action plus @xml/apduservice meta-data. Resources: apduservice.xml defines host-apdu-service with aid-filter AID D2760000850101; nfc_tech_filter.xml lists IsoDep and Ndef; strings.xml adds app_name, hce_service_description, hce_aid_group.
UI / Flow Integration
lib/screens/9receive_screen.dart
ReceiveScreen: adds _isHceActive state; _activateNfc now either auto-starts HCE when no invoice or prompts mode choice if invoice exists; _openNfcChargeSheet and _NfcChargeSheet accept ModoNfcRecibir modo and optional onFinish; status text uses HCE-specific localization when in HCE mode; request-amount flow propagates modoLector for auto-start behavior.
Localization
lib/l10n/app_*.arb (de, en, es, fr, it, pt, ru)
Adds/relocates NFC and HCE keys across ARB files: nfc_hce_message, nfc_mode_title, nfc_mode_boltcard, nfc_mode_boltcard_subtitle, nfc_mode_hce, nfc_mode_hce_subtitle, nfc_tag_not_compatible, nfc_not_boltcard, nfc_incomplete_data, nfc_invalid_response, nfc_network_error.
Dependency
pubspec.yaml
Adds flutter_nfc_hce: ^0.1.8 to dependencies.

Sequence Diagram

sequenceDiagram
    participant User as User
    participant UI as ReceiveScreen
    participant Service as NfcChargeService
    participant HceLib as FlutterNfcHce
    participant NfcSystem as Android NFC / Reader
    participant Server as LnurlServer

    User->>UI: Tap Receive / auto-start
    UI->>Service: startChargeSession(lnurlOrInvoice, modo)
    alt modo == hceWallet
        Service->>HceLib: startNfcHce(lnurlOrInvoice)
        HceLib->>NfcSystem: Advertise HCE (IsoDep/AID)
        NfcSystem->>Server: External reader interacts with emulated card
        Server-->>NfcSystem: Confirm/handle payment
        NfcSystem-->>Service: notify interaction/result
        Service-->>UI: notify success/error
    else modo == lectorBoltcard
        Service->>NfcSystem: start listening (poll iso14443)
        NfcSystem->>Service: Tag discovered
        Service->>Server: POST claim using extracted tag and lnurlOrInvoice
        Server-->>Service: claim result
        Service-->>UI: notify success/error
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Poem

🐰 I hopped into code with a tiny cheer,

Two NFC paths now both draw near.
HCE hums softly, cards still scan,
Pick a mode — tap or emu-plan.
A carrot-sized update, quick and clear.

🚥 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 'feat(hce): Add HCE support for receiving payments via NFC' clearly and concisely summarizes the main change—adding Host Card Emulation (HCE) support for NFC payments. It is specific, descriptive, and directly reflects the core changes throughout the PR (HCE service integration, UI updates, Android configuration, and internationalization).
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ 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: 8

Caution

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

⚠️ Outside diff range comments (1)
lib/services/nfc_charge_service.dart (1)

193-207: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

stopSession() does not stop HCE emulation.

When HCE mode is active and stopSession() is called (e.g., when dismissing the sheet), it only stops NfcManager sessions but does not call _hce.stopNfcHce(). This leaves HCE emitting the LNURL/invoice even after the UI is closed.

🐛 Proposed fix
  Future<void> stopSession() async {
+   try { await _hce.stopNfcHce(); } catch (_) {}
    await _safeStop();
    _sessionActive = false;
  }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/services/nfc_charge_service.dart` around lines 193 - 207, stopSession()
currently only stops the NfcManager session and doesn't stop HCE emulation;
update stopSession() to also stop HCE by invoking _hce.stopNfcHce() when HCE
mode is active (wrap the call in a try/catch similar to _safeStop to avoid
throwing), ensuring _hce.stopNfcHce() is called before or alongside await
_safeStop(...) and that _sessionActive is still set to false after both stop
attempts; reference stopSession, _safeStop, and _hce.stopNfcHce in your changes.
🧹 Nitpick comments (2)
lib/services/nfc_charge_service.dart (1)

91-102: ⚡ Quick win

HCE mode lacks session completion handling.

After startNfcHce is called, the method returns but _sessionActive remains true indefinitely. Unlike BoltCard mode which sets _sessionActive = false in the finally block, HCE mode has no mechanism to mark the session as complete or detect payment success.

Consider adding a way to stop HCE and reset _sessionActive when the charge sheet is dismissed, or rely on stopSession() being called externally.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/services/nfc_charge_service.dart` around lines 91 - 102, The HCE branch
never clears the session flag or stops HCE, so _sessionActive stays true after
_hce.startNfcHce completes; update the ModoNfcRecibir.hceWallet case to ensure
the session is ended: after calling _hce.startNfcHce (or in a
finally/when-dismissed handler) call the existing stopSession() or _hce.stop...
method and set _sessionActive = false, and emit the final status via
onStatus(NfcChargeResult(...)) as done in the BoltCard flow so the charge sheet
dismissal or external stopSession() reliably resets the session state.
lib/screens/9receive_screen.dart (1)

1024-1030: 💤 Low value

Simplify duplicated code.

Both branches perform the same operation. The conditional is unnecessary.

♻️ Suggested simplification
     if (modo == null) return;
 
-    if (modo == ModoNfcRecibir.hceWallet) {
-      _openNfcChargeSheet(_generatedInvoice!.paymentRequest, 
-                          modo: modo);
-    } else {
-      _openNfcChargeSheet(_generatedInvoice!.paymentRequest, 
-                          modo: modo);
-    }
+    _openNfcChargeSheet(_generatedInvoice!.paymentRequest, modo: modo);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/screens/9receive_screen.dart` around lines 1024 - 1030, The if/else
around ModoNfcRecibir.hceWallet is redundant because both branches call
_openNfcChargeSheet with the same arguments; remove the conditional and replace
it with a single call to _openNfcChargeSheet(_generatedInvoice!.paymentRequest,
modo: modo) (referencing the symbols ModoNfcRecibir, _openNfcChargeSheet, and
_generatedInvoice.paymentRequest) so the logic is simplified and identical
behavior preserved.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@android/app/src/main/res/xml/apduservice.xml`:
- Line 3: The APDU service currently allows handling while the device is locked
because android:requireDeviceUnlock="false"; update the APDU service declaration
in apduservice.xml (the <service> or <host-apdu-service> element that contains
android:requireDeviceUnlock) to set android:requireDeviceUnlock="true" so the
HCE service requires the device to be unlocked before responding to ISO-DEP
readers, preventing locked-device leakage of LNURL/BOLT11 data.
- Line 3: The apduservice XML currently sets
android:requireDeviceUnlock="false", which allows HCE responses while the device
is locked; update the apduservice configuration to set
android:requireDeviceUnlock="true" so the HostApduService only responds when the
device is unlocked (locate the HostApduService / <service> / <host-apdu-service>
declaration in apduservice.xml and change the android:requireDeviceUnlock
attribute value accordingly).
- Line 5: The AID in apduservice.xml is wrong: update the <aid-filter
android:name="..."> value to match the flutter_nfc_hce native default AID
("D2760000850101") or, if you intentionally want "F0010203040506", configure the
flutter_nfc_hce native implementation to use that AID instead; locate the
<aid-filter> entry in apduservice.xml and replace its android:name with
"D2760000850101" (or change the plugin's native AID configuration in the
flutter_nfc_hce source if AID customization is supported), then verify the AID
matches the SELECT command your BoltCard terminal sends.
- Line 5: Update the registered AID in apduservice.xml so it matches the
hardcoded AID used by the flutter_nfc_hce plugin (D2760000850101); specifically
replace the current aid-filter value F0010203040506 with D2760000850101 so
Android will route SELECT commands to KHostApduService correctly and match the
AID expected by the plugin at runtime.

In `@lib/l10n/app_en.arb`:
- Line 394: The "nfc_mode_boltcard" message value is semantically wrong — it
implies adding funds rather than collecting a Lightning payment; update the
value for the key "nfc_mode_boltcard" in lib/l10n/app_en.arb to a clearer phrase
such as "Charge BoltCard" (or "Collect from BoltCard") and apply equivalent
corrected translations across all other locale files where the same key appears
(e.g., replace "Charger BoltCard", "Carica BoltCard", "BoltCard laden",
"Carregar BoltCard" with the appropriate localized phrasing). Ensure only the
string values change, keeping the key "nfc_mode_boltcard" intact so code
references remain unchanged.

In `@lib/screens/9receive_screen.dart`:
- Around line 1636-1642: The _tabController field is declared and initialized in
initState but never used and not disposed, leaking a ticker because the State
mixes in SingleTickerProviderStateMixin; either remove the unused TabController
entirely (delete the late final _tabController declaration and its
initialization in initState) and also remove the SingleTickerProviderStateMixin
from the State class if it's no longer needed, or keep it and add a dispose
method that calls _tabController.dispose() (implement dispose() =>
_tabController.dispose(); super.dispose()) to properly clean up; locate symbols
_tabController, initState, dispose, and SingleTickerProviderStateMixin to apply
the change.
- Around line 1666-1671: Auto-close block currently calls
Navigator.of(context).pop() and then invokes widget.onFinish, but
widget.onFinish also pops the modal, causing a double-pop; remove the
Navigator.of(context).pop() invocation from the Future.delayed auto-close path
(leave setting _autoCloseScheduled and invoking widget.onFinish), and update the
onFinish implementation (the callback invoked by widget.onFinish) to always
perform the pop (e.g., ensure it calls Navigator.pop(sheetContext)
unconditionally) so the modal is only dismissed once by the onFinish handler.

In `@lib/services/nfc_charge_service.dart`:
- Around line 38-45: The class NfcChargeService references _hce.startNfcHce(...)
and _hce.stopNfcHce() but never declares or imports the NFC HCE API; add the
missing import for the flutter_nfc_hce package
(package:flutter_nfc_hce/flutter_nfc_hce.dart) and declare a private field
inside NfcChargeService (e.g., final FlutterNfcHce _hce) and initialize it
(either inline or in the constructor) so the calls to _hce.startNfcHce and
_hce.stopNfcHce compile; update the constructor NfcChargeService(...) if you
choose constructor initialization.

---

Outside diff comments:
In `@lib/services/nfc_charge_service.dart`:
- Around line 193-207: stopSession() currently only stops the NfcManager session
and doesn't stop HCE emulation; update stopSession() to also stop HCE by
invoking _hce.stopNfcHce() when HCE mode is active (wrap the call in a try/catch
similar to _safeStop to avoid throwing), ensuring _hce.stopNfcHce() is called
before or alongside await _safeStop(...) and that _sessionActive is still set to
false after both stop attempts; reference stopSession, _safeStop, and
_hce.stopNfcHce in your changes.

---

Nitpick comments:
In `@lib/screens/9receive_screen.dart`:
- Around line 1024-1030: The if/else around ModoNfcRecibir.hceWallet is
redundant because both branches call _openNfcChargeSheet with the same
arguments; remove the conditional and replace it with a single call to
_openNfcChargeSheet(_generatedInvoice!.paymentRequest, modo: modo) (referencing
the symbols ModoNfcRecibir, _openNfcChargeSheet, and
_generatedInvoice.paymentRequest) so the logic is simplified and identical
behavior preserved.

In `@lib/services/nfc_charge_service.dart`:
- Around line 91-102: The HCE branch never clears the session flag or stops HCE,
so _sessionActive stays true after _hce.startNfcHce completes; update the
ModoNfcRecibir.hceWallet case to ensure the session is ended: after calling
_hce.startNfcHce (or in a finally/when-dismissed handler) call the existing
stopSession() or _hce.stop... method and set _sessionActive = false, and emit
the final status via onStatus(NfcChargeResult(...)) as done in the BoltCard flow
so the charge sheet dismissal or external stopSession() reliably resets the
session state.
🪄 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: 92ea70ee-4c8c-4bcf-9297-f5797d4ac7e1

📥 Commits

Reviewing files that changed from the base of the PR and between bd2fd72 and 3ef532c.

⛔ Files ignored due to path filters (9)
  • 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/**
  • pubspec.lock is excluded by !**/*.lock
📒 Files selected for processing (13)
  • android/app/src/main/AndroidManifest.xml
  • android/app/src/main/res/values/strings.xml
  • android/app/src/main/res/xml/apduservice.xml
  • android/app/src/main/res/xml/nfc_tech_filter.xml
  • 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/9receive_screen.dart
  • lib/services/nfc_charge_service.dart

Comment thread android/app/src/main/res/xml/apduservice.xml Outdated
Comment thread android/app/src/main/res/xml/apduservice.xml Outdated
Comment thread lib/l10n/app_en.arb Outdated
Comment thread lib/screens/9receive_screen.dart Outdated
Comment thread lib/screens/9receive_screen.dart Outdated
Comment thread lib/services/nfc_charge_service.dart
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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@lib/services/nfc_charge_service.dart`:
- Around line 97-104: The HCE emulation started by _hce.startNfcHce (called in
the NFC flow) is never stopped; update stopSession() and dispose() to also stop
HCE: when stopping the session (stopSession) call the corresponding HCE stop
method on _hce (e.g., _hce.stopNfcHce or _hce.stop) with a null-check and await
it if async, and likewise call/await that same stop in dispose() before cleaning
up; wrap the call in try/catch to swallow/log errors and ensure idempotence so
multiple stops are safe.
- Around line 109-113: The onDiscovered callback can re-enter while a previous
tag is being processed; add a private boolean field (e.g., _processingTag) to
guard the callback: at the start of the onDiscovered handler check if
(_processingTag) return immediately, otherwise set _processingTag = true, run
the existing tag handling and withdrawal request code (the block that performs
the claim/withdraw request), and ensure you reset _processingTag = false in a
finally block so it always clears even on errors; keep the existing
_sessionActive logic for session lifecycle but use _processingTag to prevent
concurrent execution of onDiscovered.
🪄 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: 0c955ee9-192f-4419-8c51-1dd0323690ae

📥 Commits

Reviewing files that changed from the base of the PR and between 3ef532c and 34f3deb.

📒 Files selected for processing (2)
  • lib/services/nfc_charge_service.dart
  • pubspec.yaml

Comment thread lib/services/nfc_charge_service.dart Outdated
Comment thread lib/services/nfc_charge_service.dart
Delgado74 added 2 commits May 3, 2026 06:08
…ightning: prefix

- Sin monto: Exone Lightning Address (user@domain) en lugar de LNURL
- Con monto: Expone invoice directo (lnbc1...) sin prefijo lightning:
- Agrega logs HCE_DEBUG y NFC_CHARGE para depuración
- Phoenix y otras wallets pueden leer ambos formatos
@Delgado74 Delgado74 marked this pull request as draft May 4, 2026 16:10
Delgado74 added 2 commits May 5, 2026 01:00
…fore HCE start

- Use lnurl (bech32) instead of lightning address for HCE without amount
- Stop NfcManager and previous HCE before starting HCE to avoid conflicts
- Change persistMessage to true for NDEF persistence
- Add debug logs for HCE wallet mode
- Fix double prefix in debug logs
# Conflicts:
#	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/l10n/generated/app_localizations.dart
#	lib/l10n/generated/app_localizations_de.dart
#	lib/l10n/generated/app_localizations_en.dart
#	lib/l10n/generated/app_localizations_es.dart
#	lib/l10n/generated/app_localizations_fr.dart
#	lib/l10n/generated/app_localizations_it.dart
#	lib/l10n/generated/app_localizations_pt.dart
#	lib/l10n/generated/app_localizations_ru.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.

1 participant