Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Telos Privacy Wallet

A self-custodial mobile wallet for the Telos privacy layer. Inspired by Zashi / Zodl (Zcash) but built for Telos EVM, supporting the native TLOS asset and USDC via the zkBob-based privacy pools deployed on Telos.

  • Private by default. Every received deposit is autoshielded as soon as it lands in your transparent address.
  • "Pay Anywhere" powered by Li.Fi - spend your shielded TLOS/USDC at any address on any EVM chain via cross-chain routing.
  • iOS + Android, single codebase (Expo + React Native).
  • Non-custodial: seed phrase is held only in the device secure enclave (iOS Keychain / Android Keystore via expo-secure-store).

Status: v0.1 scaffold. Every screen, the wallet core, the zkBob bridge, the Li.Fi integration, and the autoshield runner are in place and type-checked. The one step that must be run before shipping to devices is node scripts/bundle-zkbob.js, which builds the WebView-hosted zkbob-client-js bundle (see zkBob WebView bridge).


Quick start

# Install deps
npm install

# Build the WASM-backed zkBob host bundle (required once, and whenever
# zkbob-client-js is upgraded). This installs a temporary workspace,
# bundles the library + libzkbob-rs-wasm-web, and inlines it into
# assets/zkbob/zkbob-host.html.
node scripts/bundle-zkbob.js

# iOS simulator
npx expo run:ios

# Android emulator
npx expo run:android

# Metro dev server only (after prebuild)
npm start

You need an Expo dev build (not the vanilla Expo Go app) because the wallet uses expo-secure-store, react-native-webview, and custom Android / iOS permissions. Run npx expo prebuild once to generate the native projects, then expo run:* to build them.


Architecture

┌──────────────────────────────────────┐
│            React Native UI           │
│   (expo-router screens + components) │
└──────────────┬───────────────────────┘
               │
        ┌──────┴──────┐
        │  useWallet  │  zustand store + derived account
        └──────┬──────┘
               │
   ┌───────────┼───────────┬─────────────┐
   │           │           │             │
┌──┴──┐   ┌────┴────┐  ┌───┴────┐   ┌────┴────┐
│ eth │   │ zkBob   │  │ Li.Fi  │   │ Secure  │
│ RPC │   │ bridge  │  │  SDK   │   │ Storage │
└──┬──┘   └────┬────┘  └───┬────┘   └─────────┘
   │           │           │
   │     ┌─────┴─────┐     │
   │     │ WebView   │     │
   │     │  host     │     │
   │     │ (hidden)  │     │
   │     └─────┬─────┘     │
   │           │           │
   │   zkbob-client-js     │
   │   libzkbob-rs-wasm    │
   │           │           │
   ▼           ▼           ▼
Telos EVM  Relayer    Li.Fi API
           (TLOS/USDC)

zkBob WebView bridge

zkbob-client-js depends on libzkbob-rs-wasm-web, a Rust → WebAssembly crypto core that is designed for a browser runtime. Hermes (React Native's JS engine) does not support WebAssembly, so we host the library inside a hidden react-native-webview and marshal all calls across postMessage.

This is the same pattern used by many mobile wallets that depend on WASM-first libraries (the Zcash Light Client, Namada SDK, etc.). The interface is strongly typed end-to-end:

  • src/zkbob/types.ts - BridgeMethods declares the typed RPC surface.
  • src/zkbob/bridge.tsx - React Native side. Exposes a useZkBobBridge hook and a ZkBobBridgeProvider that mounts the hidden WebView.
  • src/zkbob/client.ts - Thin facade used by screens (ZkBobClient).
  • assets/zkbob/zkbob-host.html - Template HTML loaded into the WebView. Contains the dispatcher shim. Before packaging, run node scripts/bundle-zkbob.js which inlines the real zkbob-client-js bundle into this file. Without that step the shim returns a clear "not bundled" error and the UI stays offline.

Wallet core

src/wallet/

  • Mnemonic + key derivation. A single BIP-39 seed is the root of trust. deriveEvmAccount produces the transparent EVM account on m/44'/60'/0'/0/0 for regular transactions. deriveShieldedSeed produces per-pool entropy that is fed into libzkbob-rs inside the WebView, so the TLOS pool and the USDC pool get independent shielded keys.
  • Secure storage. src/wallet/keystore.ts wraps expo-secure-store (iOS Keychain / Android Keystore) and adds a 6-digit PIN that hashes into the same store. Biometric unlock is optional and never bypasses the PIN-based seed encryption.

Pool configuration

src/config/pools.ts

Both Telos privacy pools are pre-wired with their relayer URLs:

TLOS_POOL.relayerUrl = 'https://dsw2020napxes.cloudfront.net/';
USDC_POOL.relayerUrl = 'https://d39zrx7k37xhn.cloudfront.net/';

On-chain addresses (poolAddress, tokenAddress, denominator) are hydrated from the relayer's /info endpoint at startup, so the app stays correct even if the Telos team rotates pools. src/zkbob/relayer.ts provides a typed HTTP client for /info, /version, /fee, /limits and /job/:id.

Autoshielding

src/zkbob/autoshield.ts

Every balance refresh (foreground poll every 30s, pull-to-refresh, and resume-from-background) runs evaluateAutoshield. If a transparent balance exceeds the user-configured threshold and leaves enough behind to cover the keepTransparent floor (for gas), the wallet immediately submits a deposit through the bridge. Defaults:

Asset Threshold Keep Transparent
TLOS 5 TLOS 2 TLOS
USDC 1 USDC 0 USDC

All values are editable from Settings → Autoshielding.

Pay Anywhere (Li.Fi)

src/lifi/client.ts + app/pay.tsx

  1. User picks the source asset (shielded TLOS or shielded USDC) and a destination chain + token + address.
  2. The wallet requests a quote via @lifi/sdk getQuote.
  3. On confirm, the wallet unshields exactly fromAmount to its own transparent Telos address, then calls executeRoute to bridge the funds to the destination. Because the bridge source is an ephemeral transparent address and never the same as the user's long-lived transparent identity, the payee cannot link the final destination back to the user's shielded account.

Directory layout

mobile-privacy-wallet/
├── app/                        # expo-router screens (file-based routing)
│   ├── _layout.tsx             # wraps everything in ZkBobBridgeProvider
│   ├── index.tsx               # launcher, routes by wallet phase
│   ├── onboarding/
│   │   ├── welcome.tsx
│   │   ├── create.tsx
│   │   ├── import.tsx
│   │   └── pin.tsx
│   ├── unlock.tsx
│   ├── (tabs)/
│   │   ├── _layout.tsx
│   │   ├── index.tsx           # Home - balances, actions
│   │   ├── history.tsx         # Shielded tx history
│   │   └── settings.tsx        # Autoshield, relayers, wipe wallet
│   ├── send.tsx                # Shielded → shielded transfer
│   ├── receive.tsx             # QR + shielded / transparent address
│   ├── shield.tsx              # Transparent → shielded deposit
│   ├── unshield.tsx            # Shielded → transparent withdraw
│   └── pay.tsx                 # Li.Fi cross-chain pay
├── src/
│   ├── config/                 # Telos + pools + Li.Fi config
│   ├── wallet/                 # Seed, keystore, account, balances
│   ├── zkbob/                  # Bridge, relayer, autoshield, client
│   ├── lifi/                   # Li.Fi SDK wrapper
│   ├── state/                  # zustand store + useWallet hook
│   ├── components/             # Buttons, PinPad, AssetRow, ...
│   ├── theme/                  # Colors, spacing, typography
│   └── polyfills.ts            # Buffer/process/crypto shims
├── assets/
│   └── zkbob/
│       └── zkbob-host.html     # WebView host (bundler rewrites this)
├── scripts/
│   └── bundle-zkbob.js         # Builds the WebView bundle
├── app.json                    # Expo config
├── babel.config.js
├── metro.config.js
└── tsconfig.json

Roadmap

  • Wallet core (seed, PIN, secure storage)
  • zkBob WebView bridge + typed RPC surface
  • Telos relayer hydration (/info, /fee, /limits, /job)
  • Autoshielding engine
  • Li.Fi "Pay Anywhere" integration
  • Full UI (onboarding → home → send/receive/shield/unshield/pay/history/settings)
  • Background autoshielding via iOS BGAppRefresh / Android WorkManager
  • Biometric auto-unlock convenience toggle
  • Ledger / WalletConnect for optional hardware co-signing on unshield
  • Desktop build via Expo Web → Tauri (stretch)

References

License

Apache-2.0 OR MIT - matching the upstream zkbob-client-js license so the library can be embedded in this wallet without friction.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages