0d3acef182d735656a2f0e49b3983ba7cc1d105b
Koins
Desktop wallet for Monero and XRP. Built with Bun + Electrobun + Svelte.
Features
- Monero mode: Self-contained Monero wallet — auto-downloads
monero-wallet-rpcbinary on first launch, no manual binary install - XRP mode: XRP Ledger wallet — generate or import XRP seeds, send payments with optional destination tags
- 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: Live XRP ledger transactions and Monero wallet transactions
- Settings: Reset app clears all keychain entries
Prerequisites
- Bun 1.2+
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
│ │ │ ├── xrp/ # XRP Ledger client (xrpl)
│ │ │ └── biometric.ts # Biometric auth (Swift subprocess)
│ │ ├── rpc/
│ │ │ ├── monero/ # Monero RPC handlers
│ │ │ └── xrp/ # XRP RPC handlers
│ │ └── native/
│ │ └── biometric-helper.swift # Touch ID prompt binary
│ ├── lib/
│ │ ├── states/
│ │ │ ├── monero-wallet.svelte.ts # Monero wallet state (singleton)
│ │ │ └── xrp-wallet.svelte.ts # XRP wallet state (singleton)
│ │ └── electrobun.ts # RPC type definitions
│ └── routes/
│ ├── index.svelte # Login/welcome page
│ ├── monero/ # Monero routes
│ ├── xrp/ # XRP routes
│ └── settings.svelte # App settings
└── 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-rpcruns as a child process. - XRP via xrpl: Uses the official
xrpllibrary over the publicwss://s1.ripple.comWebSocket server. XRP seeds are stored in the system keychain. - Keychain storage: Wallet seeds and metadata are stored in the macOS keychain via
Bun.secrets, not a local database. - Biometric auth: Uses a Swift binary spawned via
Bun.spawnSync()(notdlopen— Bun crashes on ObjC runtime; notnode-mac-auth— fragile node-gyp chain). - Separate account types: Monero and XRP are separate account types with their own seed formats and auth flows.
Dependencies
- xrpl — XRP Ledger client
- monero-ts — Monero RPC client
- Svelte 5 — UI framework
- Electrobun — Desktop app shell
- sv-router — File-based routing
- Lucide — Icons
- QRCode — QR code generation
Scripts
bun run dev # Start development server