Phase 1 of the docs-by-domain reorg. Every snapshot now carries YAML frontmatter (domain + summary + tags); the auto-guess was hand-corrected against the full index (T6/interchain -> cross-chain, CDP/MBA/stablecoin -> fiatm, CitizenToken/Ballot -> governance, etc.). No file renamed/moved. build-snapshot-index.mjs now reads the frontmatter and emits a greppable INDEX.md: a top Quick-find table (No | domain | tags | summary) plus per-domain sections with summary + tags. 224/224 tagged, 8 domains, zero uncategorised. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3.6 KiB
| domain | summary | tags |
|---|---|---|
| wallet | Capacitor device build: CapacitorKeyStore |
Snapshot 0074 — Capacitor device build: CapacitorKeyStore
Date: 2026-05-29
Track: shells/app (web PWA shell → native device build)
Status: ✅ Typecheck clean, production build passes — device build ready to cap add android/ios
Captured 2026-05-29T20:40:32.192Z
Git state
- Rev:
(no git) - Working tree: clean
File counts
| Area | Files |
|---|---|
| src/ | 57 |
| contracts/ | 56 |
| test/ | 45 |
What shipped
Capacitor upgrade: 6.1 → 8.3
shells/app/package.json updated:
@capacitor/core^6.1.0→^8.3.4@capacitor/cli^6.1.0→^8.3.4
No native projects exist yet (no android/ or ios/ directories), so the upgrade is a pure package bump — no native code migration needed.
New Capacitor plugins installed
| Plugin | Version | Role |
|---|---|---|
capacitor-secure-storage-plugin |
^0.13.0 |
Vault storage — iOS Keychain / Android EncryptedSharedPreferences |
@capgo/capacitor-native-biometric |
^8.4.5 |
Biometric unlock — Face ID / Touch ID / fingerprint with BIOMETRY_ANY hardware access control |
CapacitorKeyStore.ts (NEW)
shells/app/src/keystore/CapacitorKeyStore.ts implements the full KeyStore interface:
Vault layer (capacitor-secure-storage-plugin):
- Mirrors WebKeyStore's
Vaultstructure (AES-GCM / PBKDF2 / base64) ssGet/ssSet/ssRemoveasync wrappers;ssGetcatches "key not found" → null
Biometric layer (@capgo/capacitor-native-biometric):
create()/restore(): auto-enrolls biometric PIN usingAccessControl.BIOMETRY_ANYhardware-backed credential (server: 'cash.deviant.wallet')unlock()with no secret: triggersNativeBiometric.getSecureCredentials()(native Face ID / Touch ID prompt), retrieves hardware-backed PIN, decrypts vaultunlock({ secret }): direct PIN AES-GCM decrypt (identical to WebKeyStore path)destroy(): clears SecureStoragePlugin keys + NativeBiometric credentials
Biometric auto-enroll is non-fatal; PIN always available as fallback.
App.tsx — conditional KeyStore
Uses Capacitor.isNativePlatform() to select CapacitorKeyStore (native) vs WebKeyStore (browser/PWA).
Unlock.tsx — biometric UX on native
useEffectauto-prompts biometrics on mount when native- Native: prominent "🔐 Use Face ID / Fingerprint" CTA + PIN as secondary
- Web: PIN-only, unchanged
Onboarding+Unlockprops changed fromWebKeyStoreclass toKeyStoreinterface
package.json — native build scripts
Added cap:add:android, cap:add:ios, cap:open:android/ios, cap:run:android/ios.
Build stats
- TypeScript: 0 errors
- Vite production build: ✅ 982 modules, JS 2,072 kB (623 kB gzip), CSS 47 kB
Native project bootstrap (manual — requires device SDK)
npm run cap:add:android # generates android/ (requires Android Studio)
npm run cap:add:ios # generates ios/ (requires Xcode on macOS)
npm run cap:run:android # build → sync → run
Capacitor CLI writes USE_BIOMETRIC, USE_FINGERPRINT (Android) and NSFaceIDUsageDescription (iOS) permissions on first cap sync.
What's next
| Priority | Item |
|---|---|
| High | Generate native projects: cap add android / cap add ios (requires device SDK) |
| Medium | Swap flow: live routeSwap() rate from src/wallet/market.ts |
| Medium | Activity: wire real on-chain event history |
| Low | Code splitting: bring JS chunk below 500 kB warning threshold |
| Low | UX polish: swap asset-picker sheet; larger QR code in Receive |