Skip to content

feat: Ledger account info sheet + rekeyed-account import [PERA-4235]#526

Merged
fmsouza merged 39 commits into
mainfrom
fmsouza/ledger-account-info-sheet
May 20, 2026
Merged

feat: Ledger account info sheet + rekeyed-account import [PERA-4235]#526
fmsouza merged 39 commits into
mainfrom
fmsouza/ledger-account-info-sheet

Conversation

@fmsouza
Copy link
Copy Markdown
Contributor

@fmsouza fmsouza commented May 18, 2026

Description

Brings the native Ledger-import "account info" and "rekeyed account" capabilities to the RN app. Two cohesive, separately-specced sub-projects on this branch:

A — Ledger account info sheet

  • Adds an ⓘ affordance to each discovered-account row in the Ledger import "N accounts found" list (row reordered to native-parity layout [checkbox][avatar][text][ⓘ], shown for already-imported accounts too).
  • Tapping ⓘ opens a read-only bottom sheet: Account details (address, "Ledger Account" label, ALGO balance + fiat), Assets (held assets with verification tier), and a read-only rekey section ("Can be signed by" / "Can sign for these").
  • Logic layer (packages/accounts): useLedgerAccountPreview composes existing on-chain/assets/prices/rekey queries; useRekeyedAddressesQuery; best-effort prefetchLedgerAccountPreview (hybrid prefetch on selection-screen mount). UI uses the existing request-based bottom-sheet system; money rendered via the canonical CurrencyDisplay (Decimal in, formatted out).

B — Rekeyed-account discovery & import

  • Accounts rekeyed to a discovered Ledger address are scanned from the indexer and surfaced as selectable rows (progressively appended, with a "Rekeyed" chip and a scanning indicator).
  • Selecting a rekeyed account auto-includes its auth Ledger account. LedgerVerify device-verifies only the unique auth Ledger accounts — rekeyed addresses are never device-verified.
  • Import persists derived → HardwareWalletAccount, rekeyed → WatchAccount { rekeyAddress: <auth Ledger address> }, so deriveAccountLogicalType resolves RekeyedAuth and the existing signing pipeline routes signing to the Ledger. No keystore/signing changes; reuses the established rekey/watch model.

A typed LedgerSelectableAccount discriminated union is threaded select → verify → import. One additive, backward-compatible change to A's info sheet (optional title override, used to show "Rekeyed account" for rekeyed rows). New i18n keys added.

Related Issues

Checklist

  • Have you tested your changes locally?
  • Have you reviewed the code for any potential issues?
  • Have you documented any necessary changes in the project's documentation?
  • Have you added any necessary tests for your changes?
  • Have you updated any relevant dependencies?

Additional Notes

  • Security invariants (B), all test-verified: a rekeyed account is persisted only if its auth Ledger account is present (no dangling rekeyAddress); rekeyed addresses are never sent to on-device verification; no KMS/keystore/signing code changed; addresses validated via isValidAlgorandAddress before persistence; auth auto-include is deduped.
  • Reviewer focus: packages/accounts/src/hooks/useLedgerVerifyScreen import builder and useLedgerSelectAccountsScreen handleContinue (auto-include) are the security-sensitive seams.

fmsouza added 29 commits May 18, 2026 12:30
Adds end-to-end integration coverage for the Ledger rekeyed-account
import flow: indexer scan surfaces a rekeyed account, user selects it,
handleContinue auto-includes the auth Ledger account, LedgerVerifyScreen
verifies only the hardware account, import persists a WatchAccount with
rekeyAddress and a HardwareWalletAccount, and deriveAccountLogicalType
returns RekeyedAuth.

Also exposes a real (empty) HardwareWalletRegistry in the
platform-driver unit mock so integration tests can register a fake
Ledger BLE transport provider to drive on-device verification.
@fmsouza fmsouza self-assigned this May 18, 2026
fmsouza added 7 commits May 19, 2026 11:00
…+ AccountAssetItemView

Replace bespoke LedgerAccountInfoRows with canonical design-system components:
- Account row now uses AccountDisplay (showChevron=false showAccountType) + CurrencyDisplay/PreferredCurrencyDisplay mirroring AccountWithBalance layout
- Asset rows now use AccountAssetItemView for correct icon size and chip rendering
- Rekey-address rows use AccountDisplay with synth WalletAccount objects
- useLedgerAccountInfoContent item shapes updated to carry WalletAccount synth accounts, AssetWithAccountBalance for assets, and algoUsdPrice from preview
- LedgerAccountInfoRows.tsx deleted; unit test spec and select-screen spec mock updated
- accounts: give useRekeyedAddressesQuery an explicit return type
  instead of leaking UseQueryResult; update consumer + specs
- ledger: dedupe preview prefetch by network+address and cover
  scanned rekeyed addresses (no full-list re-prefetch on Find another)
- ledger: drop dead `accounts` from useLedgerSelectAccountsScreen
  result; assert via the canonical selectableAccounts surface
- ledger: compute real algoValue for info-sheet asset rows
- accounts: replace anonymous authAddr cast in mappers with a
  named, documented type; remove the test `as any` it enabled
- accounts: correct the useLedgerRekeyedScan caching JSDoc
- test: rename 4 hook specs *.test.ts -> *.spec.ts; give the
  imported-account-row integration test a real assertion
@fmsouza fmsouza marked this pull request as ready for review May 19, 2026 14:01
@fmsouza fmsouza requested a review from a team as a code owner May 19, 2026 14:01
fmsouza added 3 commits May 20, 2026 12:33
QA reports the Ledger Connection sheet's Cancel button can fail to
close the sheet in some cases on the accounts-found flow. The wiring
itself was correct (resolve('cancel') is the close function), but the
inline arrow created a fresh onPress reference each render. Extract a
named, memoized handleClose so onPress is a stable bound function on
PWButton -> PWTouchableOpacity -> TouchableOpacity.
- i18n: replace hardcoded `Ledger #N` default title with
  ledger.account_info.default_title and {{index}} interpolation
- accounts: thread `network` through fetchRekeyedAddresses so the
  fetch is network-scoped by construction, matching the query keys
  and the sibling fetchOnChainAccountInformation(algokit, ...) call
- ledger: stabilize useLedgerRekeyedScan memo with a primitive
  resultsSig dep (useQueries returns a fresh array every render)
- accounts: 30s staleTime on the rekeyed-addresses queries so the
  prefetch warm-up actually pays off across a Ledger import session
- ledger: clear prefetchedRef on network switch (each entry is
  bound to a specific network, the prefix implied that intent)
- ledger: document the watch/hardware `id` asymmetry in handleAdd
  to match the existing rekeyed-watch precedent
@fmsouza fmsouza merged commit a631b70 into main May 20, 2026
8 checks passed
@fmsouza fmsouza deleted the fmsouza/ledger-account-info-sheet branch May 20, 2026 13:06
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.

2 participants