Files
koins/README.md
T

3.8 KiB

Koins

Multi-chain desktop wallet for Ethereum, BSC, Polygon, and Monero. Built with Bun + Electrobun + Svelte.

Features

  • Multi-coin mode: ETH, BSC, Polygon wallet with seed phrase vault stored in system keychain
  • Monero mode: Self-contained Monero wallet — auto-downloads monero-wallet-rpc binary on first launch, no manual binary install
  • Touch ID unlock: Biometric auth via Swift helper, no node-gyp or FFI dylib
  • Password fallback: PBKDF2-salted password stored in keychain, used when biometric is unavailable
  • QR codes: Address QR with chain logo overlay
  • Transaction history: Cached in local SQLite via Drizzle ORM
  • Settings: Reset app clears all DB tables and keychain entries

Prerequisites

Getting Started

bun install
cd apps/desktop
bun run dev

Architecture

apps/desktop/
├── src/
│   ├── bun/                    # Backend (Electrobun main process)
│   │   ├── index.ts            # RPC handlers
│   │   ├── lib/
│   │   │   ├── monero/         # Monero RPC management
│   │   │   │   ├── binary.ts   # Download/extract monero-wallet-rpc
│   │   │   │   └── wallet.ts   # Child process + RPC client
│   │   │   ├── alchemy/        # Alchemy API calls
│   │   │   ├── viem/           # viem chain calls
│   │   │   ├── tokens/         # Token metadata (DB-first cache)
│   │   │   ├── transactions/   # Tx history + details (DB-first cache)
│   │   │   ├── db/             # Drizzle ORM + SQLite schema
│   │   │   └── biometric.ts    # Biometric auth (Swift subprocess)
│   │   └── native/
│   │       └── biometric-helper.swift  # Touch ID prompt binary
│   ├── lib/
│   │   ├── states/
│   │   │   └── wallet.svelte.ts        # Wallet state (singleton)
│   │   ├── components/
│   │   │   └── EvmDashboard.svelte     # Shared EVM dashboard
│   │   └── electrobun.ts               # RPC type definitions
│   └── routes/
│       ├── index.svelte       # Login/welcome page
│       ├── multicoin/         # ETH / BSC / Polygon routes
│       ├── monero/            # Monero dashboard
│       ├── settings.svelte    # App settings
│       └── tx/                # Transaction details
└── package.json

Key Decisions

  • Monero via RPC, not WASM: monero-ts's WASM wallet (MoneroWalletFull) doesn't work in Bun because the C++ HTTP client fails at runtime. Instead, monero-wallet-rpc runs as a child process.
  • SQLite cache: All chain data (tx history, receipts, token metadata) cached in SQLite via Drizzle, not localStorage.
  • Biometric auth: Uses a Swift binary spawned via Bun.spawnSync() (not dlopen — Bun crashes on ObjC runtime; not node-mac-auth — fragile node-gyp chain).
  • Separate account types: Multi Coins and Monero are separate account types with their own seed formats and auth flows.

Dependencies

Scripts

bun run dev       # Start development server
bun run db:push   # Push Drizzle schema to SQLite