Brings the whole project into git (previously only the on-ramp feature and a few parallel files were tracked). Includes: wallet core (src/), CashScript contracts/, the Capacitor shell (shells/), scripts/, tests, and the docs corpus (wiki/, snapshots/, Parameters/, Archive/, KnowledgeBase text). Excluded via .gitignore: node_modules/, dist/, .env (secrets), testnet WIF key files (.chipnet-*.json, devWallets.ts), KnowledgeBase/RAW media (~9.6 GB), transcripts/ (session logs), and machine-local config (.claude/*.local, *.lock). Secret-scanned before commit — no credentials in the tree. Note: src/swapMath.ts, src/swapBuilder.ts, contracts/OpenMintToken.cash are legacy (OP_RETURN era) but still imported; committed as-is, flagged for a separate removal once de-referenced. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| nodejs-assets/nodejs-project | ||
| src | ||
| package.json | ||
| README.md | ||
| tsconfig.json | ||
Deviant — React Native mobile shell (Phase 4)
STATUS: architecture slice only — UNBUILT and UNVERIFIED. This directory contains the runtime-architecture decision (ADR-0022) made real as a reviewable skeleton: the RN↔Node bridge and the
KeyChainKeyStore. It has never been compiled or run — it was authored on a Windows box with no RN / iOS / Android toolchain. No screens exist yet, by deliberate scope: they are worthless until the runtime path (esp. the iOS open risk below) is device-verified. Do not treat any of this as working code.
Why the core runs in Node, not in React Native
See ../../wiki/decisions.md → ADR-0022 for the full reasoning. In short:
@bitauth/libauth ships its secp256k1 / sha256 / sha512 / ripemd160 primitives as
WebAssembly only, with no pure-JS fallback and no seam to swap them. Hermes
(and RN's JSC) have no WebAssembly support. mainnet-js depends on libauth, so
it inherits the blocker. Therefore the core cannot run directly in the RN JS
engine.
Decision: embed the shared core in an on-device nodejs-mobile process (a
real Node/V8 runtime, where WASM works) and make the RN/Hermes layer a thin UI +
key-custody + bridge client. One crypto implementation across all shells; the
~231-test core ships unmodified; the seed never leaves the device (non-custodial).
┌─────────────── React Native (Hermes) ───────────────┐ ┌──── nodejs-mobile (V8) ────┐
│ screens (NOT BUILT) │ │ main.js (bridge entry) │
│ bootstrap.ts │ │ ├─ InMemoryTokenRegistry │
│ ├─ KeyChainKeyStore ── SecureStore (Keychain) │ JSON │ ├─ connectWallet(...) │
│ │ └─ IdentityCache (AsyncStorage, non-secret) │◄────►│ └─ src/web/api.ts handlers│
│ └─ NodeCoreClient ── BridgeChannel ────────────────┼──────┤ (balance/tokens/...) │
└──────────────────────────────────────────────────────┘ └────────────────────────────┘
UI + secret custody only; NO blockchain crypto ALL derivation + signing
⚠️ Load-bearing OPEN RISK — iOS jitless WASM (must be device-verified)
Apple forbids JIT for third-party apps, so nodejs-mobile runs V8 in --jitless
mode on iOS. V8 jitless mode has historically disabled WebAssembly compilation.
If that still holds, libauth's WASM will fail on iOS even inside nodejs-mobile —
defeating the whole decision on iOS specifically. This is unverified (no Mac/device
here). Verify on a real iOS device before committing to the iOS shell. Android
(V8 with JIT) is expected to work and should be validated first.
Fallbacks if iOS jitless WASM proves fatal, in preference order:
- Ship Android first; resolve iOS separately.
- Compile a native secp256k1/hash addon into the nodejs-mobile iOS build to replace libauth's WASM crypto.
- Adopt a Hermes-side pure-JS derivation/signing path (
@scure/bip39+@scure/bip32+@noble/secp256k1) for iOS only — accepting a parity-test burden against libauth (the reason it was rejected for v1).
Layout
| Path | Role |
|---|---|
src/core-bridge/protocol.ts |
Wire contract; mirrors src/web/api.ts + session lifecycle |
src/core-bridge/NodeCoreClient.ts |
RN-side client; correlates requests by id (pure, testable) |
src/core-bridge/bridge-channel.native.ts |
Real channel over nodejs-mobile-react-native (device-only) |
src/keystore/core-contract.ts |
Single re-export of src/wallet/keystore.ts |
src/keystore/KeyChainKeyStore.ts |
The KeyStore impl — secret custody + lifecycle; delegates crypto to Node |
src/keystore/SecureStore.ts |
Biometric/PIN secret-custody seam |
src/keystore/KeychainSecureStore.ts |
react-native-keychain impl (device-only) |
src/keystore/IdentityCache.ts |
Non-secret identity cache (AsyncStorage) for locked-view |
src/bootstrap.ts |
Composition point wiring it all together (no UI) |
nodejs-assets/nodejs-project/main.js |
Node bridge entry; rebuilds the src/web/server.ts RunContext per session |
KeyStore mapping (src/wallet/keystore.ts)
KeyChainKeyStore implements the cross-shell contract verbatim, including the
documented wiring: unlock() returns an UnlockedAccount whose cashaddr,
tokenAddress, ownedAddresses and await exportPrivateKey() feed
connectWallet(). Mechanics on this platform (ADR-0022 §4): the seed is sealed
in the Keychain and never leaves it; derivation runs in the Node core, which returns
the derived signing key to RN so exportPrivateKey() yields real bytes. That key
is held in memory only while unlocked and zeroed on lock(). A live Node session
(currentSessionId()) also exists for executing signed commands over the bridge.
To actually build this (NOT done here — needs a Mac + device/simulator)
npx @react-native-community/cli init DeviantMobile(or fold thesesrc/files into an existing RN 0.76 app) and copynodejs-assets/.yarn add nodejs-mobile-react-native react-native-keychain @react-native-async-storage/async-storage.- Wire the build step that compiles the core (
npm run buildat repo root →dist/) and copies/bundles it intonodejs-assets/nodejs-project/core/, somain.js's./core/*imports resolve. Addmainnet-jsto the nodejs-project. - Map the cross-project import in
src/keystore/core-contract.ts(Metroresolver/watchFolders+ tsconfig path) so RN resolves../../../../src/wallet/keystore. - iOS:
cd ios && pod install. Thennpx react-native run-android/run-ios. - First verification = the iOS open risk above: on a real iOS device, confirm
instantiateSecp256k1()succeeds inside the nodejs-mobile process before building any screens.
Next (only after the runtime path is device-verified)
Build the IA from ../../wiki/wallet-ui-design.md: bottom tab bar
(Home / Activity / Swap / Settings; Founder as a 5th tab once a minting NFT is
detected), the four V2.7 §9 interfaces, the verification-status surface, the
eight-class matrix, D-4/D-5/D-6, tier + verification badges, QR receive scan,
deep-linking, preview-before-broadcast on every tx, and app-store packaging.