[DIS] Mobile-Ready CKB Light Client (Pocket Node) for Android

Milestone 3 Completion Report

Project: Pocket Node: Mobile CKB Light Client Wallet for Android
Repository: GitHub - RaheemJnr/pocket-node: A native Android CKB (Nervos) wallet that runs an embedded light client directly on the device via JNI — full sovereignty, no remote servers. · GitHub
Milestone: M3 — Multi-Wallet & Sync Optimization
Releases: v1.5.0

Deliverables Summary

All accepted deliverables for M3 have been completed:

# Deliverable Status
1 Multi-wallet data model, Room schema (walletId FKs), migrations v2→v5 Done
2 Wallet CRUD — create, import (mnemonic/raw key), switch, delete Done
3 HD sub-account derivation from parent mnemonics Done
4 Wallet-scoped data isolation (transactions, balance cache, DAO cells, sync mode) Done
5 Key storage redesign — ESP → Room encrypted with Android Keystore AES-256-GCM Done
6 Mandatory PIN with PIN-encrypted KeyBackupManager recovery path Done
7 Sync strategies — ALL_WALLETS / ACTIVE_ONLY / BALANCED; Paging 3 transaction list Done
8 Background sync foreground service with notification updates Done
9 In-app auto-update (GitHub Releases + DownloadManager) Done
10 CSV transaction export with UTF-8 BOM for Excel compatibility Done
11 End-to-end testing, multi-wallet edge-case guards, Review fixes Done
12 Release: v1.5.0 Done

Feature 1: Multi-Wallet Management

Users can now create, import, switch between, and delete multiple wallets independently, each with its own address, transaction history, balance, and sync state.

What was built:

  • Wallet CRUD in WalletRepositorycreateWallet, importWallet (mnemonic), importRawKey, createSubAccount, switchActiveWallet, renameWallet, deleteWallet, all keyed by a UUID walletId
  • Wallet Manager screen grouping parent wallets with their sub-accounts,account selector bottom sheet, per-wallet settings screen with seed reveal behind PIN
  • Wallet-scoped prefs — sync mode, custom block height, last-synced block, sync-completed flag all keyed by (walletId, network)
  • Room migrations v2→v3, v3→v4 adding the wallets table and walletId columns to transactions, balance_cache, dao_cells; idempotent WalletMigrationHelper promoting existing single-wallet users to the multi-wallet schema
  • Color-coded WalletAvatar with WCAG AA contrast-aware initials
  • Guards — can’t delete the active wallet, can’t delete a parent with sub-accounts, can’t import the same mnemonic/raw key twice, can’t rename to a duplicate name, can’t delete the last wallet
  • deleteWallet atomicity — Room row + caches removed inside a withTransaction block; key material destroyed only after commit

Issues: M3 Multi-Wallet PRs: #76, #80

Feature 2: HD Sub-Account Derivation

Parent mnemonic wallets can now spawn sub-accounts with their own keys and addresses, without exposing or duplicating the seed.

What was built:

  • createSubAccount(parentWalletId, name) derives m/44'/309'/<n>'/0/0 where n = max(existingSubIndexes) + 1 (gap-resistant after sub deletions)
  • Sub-accounts store their own derived private key — no need to re-derive from parent on every sign
  • Parent wallet’s mnemonic is the only place the seed lives; sub-accounts inherit via derivation path
  • UI: sub-accounts nested under their parent in Wallet Manager, own entry in account selector sheet
  • Backup reminder suppressed for sub-accounts (parent holds the seed)

Issues: M3 Sub-Accounts PR: #80

Feature 3: Key Storage Redesign (ESP → Room)

Private keys and mnemonics moved off EncryptedSharedPreferences and into Room, encrypted with an Android Keystore AES-256-GCM key.

What was built:

  • New key_material table (migration v4→v5) holding encryptedPrivateKey, encryptedMnemonic, iv, walletType, mnemonicBackedUp
  • KeystoreEncryptionManager — AES-256-GCM with hardware-backed Keystore key generation, round-trip verification
  • KeyStoreMigrationHelper — idempotent one-time migration reading from ESP and writing to Room, with round-trip verification before marking complete
  • ESP fallback retained in KeyManager for one release cycle (read-only) so corrupted Room state can recover
  • deleteEspFilesIfSafe() — only runs after migration completes
  • KeyBackupManager — PIN-encrypted secondary backup on disk, written alongside every Room key update, used as a recovery path if Keystore eviction corrupts the AES key
  • AuthManager is the single source of truth for session PIN; KeyManager reads it via injection; session PIN cleared on app backgrounding

Issues: M3 Key Storage Redesign (Phase 1 + 2) PR: #80

Feature 4: Mandatory PIN & Security Hardening

PIN is now required whenever a wallet exists, with a dedicated onboarding screen explaining why in layman terms.

What was built:

  • InitialPinSetupScreen — standalone composable with three internal phases (INTRO → SETUP → CONFIRM), explains that the PIN locks the wallet and unlocks an on-device encrypted recovery-phrase backup
  • Startup gate in MainActivity — users upgrading from v1.4.x are routed through the PIN flow once
  • destinationAfterWalletReady() helper in NavGraph — every path that reaches Main is gated on pinManager.hasPin()
  • PIN removal refused while any wallet exists; dialog explains the constraint up front instead of surfacing it as a post-verify snackbar
  • PinViewModel propagates PIN to AuthManager.setSessionPin on both CONFIRM and VERIFY so KeyBackupManager backups are always written
  • SecurityChecklistScreen + SecuritySettingsViewModel expose PIN/biometric/backup state
  • RecoveryScreen — Keystore-corruption recovery flow using PIN-encrypted backup

Issues: M3 Mandatory PIN, Security Checklist PR: #80

Feature 5: Sync Strategies & Background Sync

Users can choose how to balance freshness across multiple wallets, and sync continues while the app is backgrounded.

What was built:

  • SyncStrategy enum — ALL_WALLETS (up to MAX_CONCURRENT_WALLET_SCRIPTS = 3), ACTIVE_ONLY, BALANCED (active real-time, others every 15 min)
  • registerAllWalletScripts — registers every tracked wallet’s lock script with the light client; logs dropped wallets above the cap for support diagnostics
  • SyncProgressTracker — rolling-window ETA + percentage with reset() on wallet switch to avoid cross-wallet sample contamination
  • SyncForegroundServiceSTART_STICKY foreground service with notification updates showing current sync block/tip
  • SyncNotificationManager — notification channel, permission flow, auto-dismiss when synced
  • Per-wallet sync mode (NEW_WALLET, RECENT, FULL_HISTORY, CUSTOM) defaults: newly created wallets start in NEW_WALLET so they don’t walk history; imported wallets use the user-selected mode
  • Paging 3 wired into ActivityScreen for infinite-scroll transaction list
  • Post-send rescan captures sender wallet before the 5 s delay so switching wallets mid-flight doesn’t re-register the wrong script

Issues: M3 Sync Optimization, Background Sync PR: #80

Feature 6: In-App Auto-Update

Pocket Node checks GitHub Releases on launch and offers a one-tap install of new versions, Telegram-style.

What was built:

  • UpdateRepository — polls api.github.com/repos/.../releases/latest, compares versionCode, filters for the APK asset
  • UpdateDownloader — Android DownloadManager download with progress, FileProvider-backed install intent (REQUEST_INSTALL_PACKAGES permission)
  • UpdateDialog composable — modal with “What’s new” from release notes, download progress, install action
  • Wired into HomeViewModel — checks on wallet screen resume, respects 24 h backoff between checks
  • Tested via UpdateRepositoryTest covering version comparison, APK asset resolution, and no-update scenarios

Issues: M3 In-App Update PR: #80

Feature 7: CSV Transaction Export

Users can export a wallet’s transaction history as CSV, ready to open in Excel/Google Sheets.

What was built:

  • TransactionExporter — emits CSV with columns for tx hash, direction, amount (CKB), fee, block, timestamp, status, confirmations, DAO type
  • ActivityScreen export flow — Storage Access Framework CreateDocument contract so users pick the destination
  • UTF-8 BOM prepended so Excel on Windows renders non-ASCII wallet names/memos correctly
  • pendingCsvContent cleared on every picker result (even cancellation) so wallet data doesn’t leak across export sessions

Issues: M3 CSV Export PR: #80

Testing

15 new test files were added covering the full M3 feature surface:

Test File Coverage
WalletRepositoryTest Wallet CRUD, active-delete refusal, duplicate import rejection
WalletDaoTest Room wallets table: insert, deactivate-all, activate, sub-account queries
WalletEntityTest Entity round-trip, equality, sub-account relations
WalletMigrationHelperTest Idempotent single→multi wallet backfill
KeyManagerMultiWalletTest Per-wallet key store, storeKeysForWallet, deleteWalletKeys
KeyStoreMigrationHelperTest ESP→Room encryption, round-trip verification, migration-complete flag
KeystoreEncryptionManagerTest AES-256-GCM encrypt/decrypt, wrong-IV failure, Keystore key rotation
KeyBackupManagerTest PIN-encrypted backup write/read, recovery path
WalletPreferencesMultiWalletTest Wallet-scoped preference keys per network
MigrationTest Room migration chain 1→2→3→4→5 schema correctness
BalanceCacheDaoTest / BalanceCacheEntityTest Per-(walletId, network) balance cache
TransactionDaoWalletTest Wallet-scoped transaction queries and deletion
SyncProgressTrackerTest Rolling-window ETA, reset semantics
RecoveryViewModelTest Keystore-corruption recovery flow
UpdateRepositoryTest GitHub Releases poll, version comparison, APK asset filter
TransactionExporterTest CSV column formatting, DAO-type labelling
PinManagerTest / AuthManagerSessionPinTest PIN hashing, session PIN lifecycle

Releases

Version Highlights
v1.5.0 Multi-wallet, HD sub-accounts, key storage redesign (ESP→Room, Keystore AES-256-GCM), mandatory PIN, sync strategies, background sync foreground service, in-app auto-update, CSV export, Paging 3 transaction list, 15+ new test files

All releases include signed APKs attached as assets.

What’s Next: M4 — Address Book, Polish & Launch

Work on Milestone 4 will add:

  • Address book / contacts for frequent recipients
  • Play Store listing preparation, screenshots, store copy(almost done, I just need to open a company account and setup an organization for google)
  • User-facing documentation and onboarding polish
  • Any bug fixes discovered in v1.5.0 field testing (to ship as v1.6.0)

Latest Release: v1.5.0 — M3: Multi-Wallet & Key Storage Redesign

6 Likes