* feat: support BLE device detection for Ledger and Trezor wallets, update trezor-flutter dependency
* feat: add BLE connection state listener for Trezor devices, handle disconnect events, and clean up resources on close
* feat: add mutex locking to MoneroTrezorService for thread-safe operations
* feat: add support for Trezor device settings configuration and `AwaitingSettings` state in pairing flow
* fix ugly widgets
* trezor options ui
* feat: add support for Trezor on device passphrases
* chore: bump trezor_flutter deps
* fix: remove unused subtitle property in proceed_on_device_sheet [skip ci]
* chore: update trezor_flutter dependency to latest commit [skip ci]
* fix: set restore height and store wallet during initialization steps
---------
Co-authored-by: Robert Malikowski <malikowskirobert@gmail.com>
* fix(CW-1638): include transaction notes in history CSV export
The `note` column of the transaction-history CSV export was always written
as an empty string for transaction rows, so notes a user added to a
transaction never appeared in the exported file.
Index the `TransactionDescription` Hive box once per export and look each
transaction's note up by the same keys the app writes them under
(`<txHash>_<primaryAddress>`, falling back to the legacy bare `<txHash>`),
then write it through the existing `escapeField` so multi-line notes and
notes containing commas or quotes stay valid CSV.
`CsvExportService` now takes the box, so it is resolved through `getIt` at
both export entry points.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5EdTdWZSvzbKKmd9MCEJh
* perf(CW-1638): resolve the note-key address once per CSV export
`_noteFor` read `balanceViewModel.wallet.walletAddresses.primaryAddress`
once per transaction row. On Monero and Wownero that getter is not a field
read: it calls `getAddress`, which issues an FFI `numSubaddresses` call plus
four `ffiAddress` calls before its address cache is consulted. Since
`buildCsvContent` runs on the main isolate, exporting a wallet with a long
history meant thousands of synchronous FFI round-trips with no yield point.
Every item in one export belongs to the same wallet, so the value is
invariant across rows. Resolve it once in `buildCsvContent` and thread it
through to `_noteFor`. An export holding no transaction rows now skips the
read entirely.
No change to the exported output.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5EdTdWZSvzbKKmd9MCEJh
* fix(CW-1638): neutralise spreadsheet formulas in CSV export
The note column this PR adds is fed by TransactionDescription.transactionNote,
which is not always authored by the user: a scanned bitcoin: URI carries
tx_description / message straight through payment_request.dart into
Output.note, and an address-resolution result writes Output.note too. Both are
folded into the note persisted by SendViewModel.
escapeField only quoted for , " and \n, so a note beginning with = + - @ TAB or
CR reached the cell untouched and Excel / LibreOffice / Sheets evaluate it as a
formula (=IMPORTDATA to exfiltrate a neighbouring cell, =HYPERLINK for phishing
anchor text, =cmd|… for DDE). trade.memo and the provider-supplied trade/order
strings had the same exposure already.
Neutralise inside escapeField rather than at the two call sites so every column
is covered and a future free-text column cannot forget it. Values starting with
a trigger are prefixed with an apostrophe, the spreadsheet text marker, guarded
by a plain-number test so negative amounts are left alone — formatFixed really
can emit a leading '-'. Also quote on a bare \r, which previously passed through
unquoted and splits rows in many CSV parsers.
Tests cover the escaping rules, the neutralisation, a row built end to end, and
the note column itself, including the two lookup keys and the payment-request
injection path.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* perf(CW-1638): bound the CSV note lookup to the exported rows
Review feedback: the note index copied every entry in the shared
transactionDescriptionBox, including notes belonging to other wallets,
so its memory scaled with the box rather than with the export.
Collect the keys the exported rows can ask for first — for each
transaction row both `<txHash>_<primaryAddress>` and the bare
`<txHash>` — then walk the box once and keep only matching notes.
Lookups stay O(1) per row and first-wins/key-preference behaviour is
unchanged; a box walk is skipped entirely when the export has no
transaction rows.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5EdTdWZSvzbKKmd9MCEJh
* refactor(CW-1638): simplify the CSV note lookup to a plain scan
Notes are written into the TransactionDescriptions box with `add`
(send_view_model.dart:1257,1263 and transaction_details_view_model.dart:299),
so entries carry auto-incrementing integer keys and `box.get(descriptionKey)`
cannot find them. Drop the prebuilt lookup map and the wanted-key set in
favour of a per-row scan that mirrors the app's own read path in
`TransactionDetailsViewModel.note`.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5EdTdWZSvzbKKmd9MCEJh
* docs(CW-1638): drop the explanatory comments from the CSV note lookup [skip ci]
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q5EdTdWZSvzbKKmd9MCEJh
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Omar <omarh.ismail1@gmail.com>
* feat: improvements covering solana nfts(send, ownership badge, persistent imports etc), closing emptied token accounts and other fixes from patch
* feat: more improvements for nfts including security hardening
* fix: display error in full
* fix android CI
* fix: address book wallet contacts tab not updating after wallet changes
* feat: add page open listener for contact list and handle concurrent calls to fetch contact list
* fix android CI
* fix: harden walletconnect auth so a connected session won't transfer on dApp when wallet is switched within the app
* refactor: improve session mgmt and better error handling, also added a loader to the listing page
* feat: switch to newer id for solana dapps connections and fix requests not triggering
* fix android CI
* fix: duplicate outgoing tx for jup swaps and stuck pending state
* fix solana security risk by handling duplicate token symbols in wallet transactions
* feat: implement additional cost handling for pending transactions in Solana wallet.
* fix: Items on security audit list for solana wallet
* refactor: streamline fee payer index handling and improve error logging
* fix: verifySignature for solana and handle wrong mint on default token
* fix: token decimals defaulting to zero and breaking amount parsing in solana
* fix: use token mask in tx history
* refactor: apply lint to modified code
* fix: merge conflicts
* fix: use Money and mint decimals when parsing sol swaps
* test: add unit tests for SPL token amount handling and parsing
* test: add more tests
* fix: update decimal handling for fetched token and remove unused fields
* fix: zcash address for exchange
* fix: honour the restore height the user entered
- Make Zcash rescan work in both directions by resetting sync from the new birth height
- Keep the entered height when restoring a wallet from keys
- Tolerate grouping separators in typed restore heights
---------
Co-authored-by: Vik Sharma <vik@cakewallet.com>
* feat: show Bitcoin master fingerprint in wallet keys
Add the BIP-32 master fingerprint (XFP) to the Bitcoin wallet keys shown
under Settings > Seed & Keys > Keys, labeled "Master fingerprint".
* fix: keep xPub in Keys tab by splitting silent payment keys into a dedicated list
The Keys tab / Silent Payments tab split relied on a hardcoded item index
(`items.sublist(0, 4)` / `sublist(4)`) that assumed the first four items
were always WIF/private key/public key/xPub. Adding the master fingerprint
as the first item pushed xPub into the Silent Payments tab.
Route Bitcoin silent payment keys into their own `silentPaymentItems` list
instead, and render each tab from its list.
* Label new-UI dashboard navigation and sync status for screen readers
Each bottom-nav tab becomes one button node carrying its localized name, its
selected state and mutual exclusion; the pill text no longer duplicates the
selected tab. The assets/history tabs gain selected state, the Bitcoin/Lightning
switcher becomes a labeled toggle, and the sync bar becomes a single button whose
label is the localized status (plus Tor/MWEB/Silent Payments badges) with a hint
pointing at node management. Compact mode's pulsing dot and the chain icon's
progress ring now have text equivalents, and the invisible pointer-absorbing
strip behind the nav bar is excluded from traversal.
* Make new-UI dashboard cards, lists and menus operable by screen readers
Collapse the wallet-name row into one labeled button (hardware-wallet glyph
folded into the label, inner accounts button no longer a second stop) and give
balance cards a labeled, selectable node with a long-press action for show/hide
balance. Balances hidden behind AnimatedOpacity, card artwork and decorative
glyphs leave the semantics tree; the 3-dots customize target and the card action
buttons are now named buttons. Assets/history rows, the history header, the MWEB
promo, long-press menu items, the account cards and the add-account and
generate-name controls become single button nodes, the phantom action chip in the
assets header is built conditionally instead of drawn at opacity 0, and app cards
get a close tooltip plus an 'opens externally' hint.
* Use expression bodies for the new a11y helpers
* Restore untouched expressions in cards_view
* Address review: state-aware balance hint, tooltip-free close label
* Address review: keep header height without the chip, name the selected index
* Give ModernButton and CoinActionButton one labeled a11y node
ModernButton, CoinActionButton and the ModalTopBar chrome buttons were
icon-only IconButtons with no tooltip and a detached caption sibling, so
screen readers announced an unnamed "button" plus unrelated static text.
- Add optional semanticLabel to ModernButton; wrap the control in
MergeSemantics + Semantics(button: true, label: semanticLabel ?? label)
and exclude both the icon and the visible caption so exactly one node
is exposed. No visual or pointer change.
- Give CoinActionButton the same treatment, reusing the label callers
already pass (dashboard Send / Receive / Swap / Scan).
- Add leadingSemanticLabel / trailingSemanticLabel to ModalTopBar,
defaulting the leading button to "Close", and mark a non-empty title
as a semantics header.
- Migrate every ModernButton / ModalTopBar call site to pass a localized
label, and drop the now-redundant external Semantics wrapper in
base_page.dart so the back button is not labeled twice.
- Localize the hard-coded "Settings" modal title in settings_page.dart.
New English keys: rotate_address, swap_reverse_direction, switch_camera,
switch_input_currency, test_node_speeds, turn_flash_off, turn_flash_on.
* Require explicit accessible names on ModalTopBar and ModernButton icons
ModalTopBar defaulted every leading icon's accessible name to "Close", so
the ~40 callers that pass a back arrow announced the wrong action, and
trailingSemanticLabel was optional, leaving the trailing icon controls
unnamed.
- Drop the "?? close" fallback in ModalTopBar: the leading ModernButton
now gets exactly leadingSemanticLabel, and constructor asserts require a
non-empty label whenever leadingIcon / trailingIcon is supplied. Callers
that pass leadingWidget / trailingWidget instead are unaffected, and a
null icon still builds no button at all.
- Assert in both ModernButton constructors that the control has a name:
either semanticLabel or a non-empty visible label.
- Pass the matching localized label at every ModalTopBar call site: "Go
back" for back arrows, "Close" for close icons, and the action name for
trailing icons (History, Configure, Export CSV, Save, Scan, Close).
- Label the last unnamed ModernButton (wallet accounts, wallet_info.dart).
No new localization keys; all labels reuse existing strings_en.arb keys.
* fix(a11y): put ModalTopBar header flag on the title Text node
On-device audit (CW-1574, defect D2) found zero [heading] nodes in the
Android accessibility tree on the Receive page: Semantics(header:) wrapped
the AnimatedSwitcher rather than the Text inside it, so the flag never
landed on the node that carries the title label.
Move the header semantics inside the AnimatedSwitcher, directly around the
Text. The ValueKey(title) moves with it onto the Semantics wrapper, since
AnimatedSwitcher switches on its direct child's key -- keying the Semantics
by title preserves the existing switch/animation behavior exactly.
No test or robot resolves the title ValueKey through a Text-typed finder,
so the key relocation is not observable from the test suites on this branch.
* Set headingLevel so Android surfaces modal titles as headings
The Flutter 3.41 engine drives AccessibilityNodeInfo.setHeading from
headingLevel, not the IS_HEADER flag (which 3.35 used). Proven by an
on-device probe: header:-only headings print on a 3.35-engine build and
vanish on the 3.41-engine CI build.
* fix: enforce passphrase confirmation in restore passphrase bottom sheet
The confirm-passphrase field in AddPassphraseBottomSheet already had a
validator comparing it to the first field, but the fields were not inside
a Form and nothing ever called validate(), so the validator never ran.
Tapping "Restore" restored the wallet with the first field's value even
when the confirmation did not match, defeating the typo check.
Wrap both fields in a Form and validate it before completing the restore,
matching the existing pattern in advanced_privacy_settings_page.dart.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019DtLNfYw1H81p7zZrkNDXM
* Validate passphrase confirmation when the passphrase field is empty
---------
Co-authored-by: Claude <noreply@anthropic.com>
* v6.3.0 Release Candidate
- the new transaction history
- Radar in Apps screen
- Zcash update
- Flutter update
- Parts of the Refactor
should improve how amounts are handled in the app and fix any issue with amounts
improve handling sending to aliases
- Improvements for Cake Pay mobile
- Bug fixes
* don't use memo for note/message values
* save message in QR locally in the notes field
* Make stealth addresses generated from silent payment, not reliant on output index (#3420)
* - fix swaps showing only on primary account
- switch tron default node
- privacy fixes
* - enlarge destination tag and make it copiable
- migrate users on hashvault
- minor fix
* feat: zkool2
* feat: rescan on zkool
fix: sending to extracted addresses
fix: labeling shielding txs
fix: autoshield endless loop
fix: autoshield t addr not firing
fix: autoshield destinations
chore: remove old routes for rescan with zkool
other minor fixes/cleanups
* fix: zcash hardfork
* fix: update sync progress more reliably
* fix: pending transaction loading
fix: autoshield txs
fix: taddress
fix: fee estimation
fix: tx send errors
* chore: bump zkool2 to latest version
fix: reduce amount of taddrs generated
fix: derivation path for internal wallets
fix: display address in correct hidden/usable spots
fix: get wallet db height before it syncs for the first time
fix: taddr rotation with passphrase
fix: sync progress ui refresh
fix: taddress generation not getting capped
fix: hidden addresses not being hidden
fix: pending transactions not being shown
fix: t address cache misses
fix: t address rotation not getting refreshed
fix: t address high index not being used
* fix: refresh t addresses
* fix: patch rust side to make t addr rotation work
* fix: ui issue in recipient address
fix: zcash multiaddress send to show in the ui
fix: potential race condition
* minor fixes
* format
* fix: flashing on receive screen
* remove unused 'autoShield'
* review