instant wallet

A mobile wallet where you choose: send crypto publicly or privately. [WIP, unfortunately]

instant wallet

Created At

ETHGlobal Cannes 2026

Project Description

Instant is a privacy-first mobile crypto wallet on Base where every transaction has a simple choice: public or private.

Sign in with just your email — no seed phrases, no extensions. A smart account is deployed in the background, gaslessly. The 3-step send flow (pick token → enter amount → confirm) includes a "Send privately" toggle. When enabled, the sender-recipient link is broken through a ZK privacy pool, completely invisible to the user.

If your email is compromised, rotate your wallet's signing key to any photo. Pick an image, set a password, and your photo deterministically becomes your new private key — same wallet address, same assets, new signer. Your photo is your cold storage.

Multi-token support (ETH, ULNKm, USDC) with real-time balances. Dual login: email or image key. All privacy operations run client-side on the device. No backend needed for core flows.

How it's Made

The mobile app is built with Expo/React Native in a pnpm monorepo (apps/mobile, apps/backend, packages/shared).

Dynamic SDK v4 handles auth and embedded wallets using their new client-based architecture — createClient() with ReactNative and Viem extensions, no providers. The Dynamic WebView runs at the app root for the MPC wallet iframe.

Safe v1.4.1 is the primary wallet via permissionless.js and Pimlico's ERC-4337 bundler + paymaster. Every user gets a gasless smart account on first login. Key rotation uses Safe's swapOwner() to replace the Dynamic signer with an image-derived key without changing the wallet address.

Unlink SDK runs fully client-side for ZK private transfers. The Unlink seed is derived from the Dynamic wallet's signMessage("unlink-seed-v1") → SHA-256 → 32-byte seed, so there's no separate backup. During key rotation, the seed is XOR-encrypted with the image private key's hash and stored locally, then decrypted on image login — preserving private pool balances across auth methods.

Hacky bits worth mentioning:

  • Hermes engine doesn't support import.meta — needed Babel's unstable_transformImportMeta for the Unlink SDK
  • Unlink SDK uses Node.js createRequire internally to load EdDSA crypto — we shimmed it in Metro config to route directly to the @zk-kit/eddsa-poseidon/blake-2b CJS module
  • permissionless.js crashed at module scope in Hermes ("protocol" undefined) — all imports are lazy (dynamic import() inside functions) with a hardcoded EntryPoint address to avoid importing from viem/account-abstraction
  • Dynamic's MPC wallet doesn't expose the raw private key, so we wrap the signer with viem's toAccount() to prevent eth_requestAccounts calls that crash permissionless
  • BigInt.prototype.toJSON polyfill in the entry point because the Dynamic WebView can't serialize BigInt in UserOperations
  • Image key derivation: image bytes → SHA-256 → PBKDF2 (3000 iterations) → BIP39 mnemonic → HD key at m/44'/60'/0'/0/0. Same image
  • password = same key, every time.

Moralis provides token balances and transaction history with client-side caching (60s/30s TTL). Viem is the on-chain backbone. Everything runs on Base Sepolia.

background image mobile

Join the mailing list

Get the latest news and updates