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
WalletRepository—createWallet,importWallet(mnemonic),importRawKey,createSubAccount,switchActiveWallet,renameWallet,deleteWallet, all keyed by a UUIDwalletId - 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
walletstable andwalletIdcolumns totransactions,balance_cache,dao_cells; idempotentWalletMigrationHelperpromoting existing single-wallet users to the multi-wallet schema - Color-coded
WalletAvatarwith 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
deleteWalletatomicity — Room row + caches removed inside awithTransactionblock; 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)derivesm/44'/309'/<n>'/0/0wheren = 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_materialtable (migration v4→v5) holdingencryptedPrivateKey,encryptedMnemonic,iv,walletType,mnemonicBackedUp KeystoreEncryptionManager— AES-256-GCM with hardware-backed Keystore key generation, round-trip verificationKeyStoreMigrationHelper— idempotent one-time migration reading from ESP and writing to Room, with round-trip verification before marking complete- ESP fallback retained in
KeyManagerfor one release cycle (read-only) so corrupted Room state can recover deleteEspFilesIfSafe()— only runs after migration completesKeyBackupManager— PIN-encrypted secondary backup on disk, written alongside every Room key update, used as a recovery path if Keystore eviction corrupts the AES keyAuthManageris the single source of truth for session PIN;KeyManagerreads 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 inNavGraph— every path that reaches Main is gated onpinManager.hasPin()- PIN removal refused while any wallet exists; dialog explains the constraint up front instead of surfacing it as a post-verify snackbar
PinViewModelpropagates PIN toAuthManager.setSessionPinon both CONFIRM and VERIFY soKeyBackupManagerbackups are always writtenSecurityChecklistScreen+SecuritySettingsViewModelexpose PIN/biometric/backup stateRecoveryScreen— 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:
SyncStrategyenum —ALL_WALLETS(up toMAX_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 diagnosticsSyncProgressTracker— rolling-window ETA + percentage withreset()on wallet switch to avoid cross-wallet sample contaminationSyncForegroundService—START_STICKYforeground service with notification updates showing current sync block/tipSyncNotificationManager— notification channel, permission flow, auto-dismiss when synced- Per-wallet sync mode (
NEW_WALLET,RECENT,FULL_HISTORY,CUSTOM) defaults: newly created wallets start inNEW_WALLETso they don’t walk history; imported wallets use the user-selected mode - Paging 3 wired into
ActivityScreenfor 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— pollsapi.github.com/repos/.../releases/latest, comparesversionCode, filters for the APK assetUpdateDownloader— AndroidDownloadManagerdownload with progress,FileProvider-backed install intent (REQUEST_INSTALL_PACKAGESpermission)UpdateDialogcomposable — 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
UpdateRepositoryTestcovering 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 typeActivityScreenexport flow — Storage Access FrameworkCreateDocumentcontract so users pick the destination- UTF-8 BOM prepended so Excel on Windows renders non-ASCII wallet names/memos correctly
pendingCsvContentcleared 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