Decentralized Cashu ecash wallet powered by Enbox.
nutsd is a Cashu ecash wallet that stores your wallet state in your personal Decentralized Web Node (DWN) instead of a centralized server or local-only browser storage. Your proofs, mints, and transaction history live in DWN records you control — synced across devices, owned by your DID. Sensitive record types (proofs, keysets, transactions) require DWN-level encryption (encryptionRequired: true), so even the DWN server operator cannot read your ecash secrets.
Live: nutsd.pages.dev · dnuts.pages.dev
Every other Cashu wallet stores your ecash proofs in localStorage, a mobile app's sandbox, or a cloud database controlled by the wallet provider. If you clear your browser, lose your phone, or the service shuts down — your tokens are gone.
nutsd takes a different approach:
| Traditional Cashu Wallets | nutsd | |
|---|---|---|
| Storage | localStorage / app sandbox / cloud DB | Your personal DWN (private, encrypted sensitive types) |
| Identity | None or custodial accounts | Decentralized Identifiers (DIDs) |
| Multi-device | Manual backup / restore | Automatic DWN sync |
| Portability | Locked to one app | Any DWN-compatible app can read your wallet |
| P2P transfers | Copy-paste tokens or Lightning | Send ecash directly to a DID (planned) |
| Interop | Isolated ecosystems | Open DWN protocols anyone can build on |
- Connect with a DID — either by connecting an Enbox wallet (delegated wallet-connect) or by creating a local identity
- DWN protocols define the schema for your wallet data (mints, proofs, transactions) as typed records in your personal data store — proofs, keysets, and transactions are encrypted at the DWN layer
- Cashu operations (mint, melt, send, receive) are handled by cashu-ts, with proof lifecycle managed through DWN records
- Real-time sync — subscribe to protocol-level changes so multi-device state stays consistent
The wallet defines two open DWN protocols:
cashu-wallet— private protocol storing mint configurations, keysets, individual proofs (one record per proof), transaction history, and preferencescashu-transfer— published protocol enabling P2P ecash transfers between DIDs (anyone can send you a token by writing to your DWN)
- Multi-mint — connect to multiple Cashu mints simultaneously, view per-mint balances
- Deposit — mint ecash by paying a Lightning invoice (NUT-04)
- Withdraw — melt ecash to pay a Lightning invoice (NUT-05)
- Send — create a Cashu token to share with anyone
- Receive — claim a Cashu V3 or V4 token
- Token status — check if a sent token has been claimed (NUT-07)
- Mint detail — view mint info, pubkey, supported NUTs, and connection details
- Dark/light theme — Enbox design language with dark-first aesthetic
- PWA — installable, works offline, service worker with Enbox polyfills
# Install dependencies
pnpm install
# Development server
pnpm dev
# Production build
pnpm build
# Preview production build
pnpm previewnutsd supports build-time branding via the VITE_PRODUCT_THEME environment variable. The same codebase produces multiple themed deployments:
| Variant | Theme | Accent | URL |
|---|---|---|---|
| nutsd | (default) | Gold | nutsd.pages.dev |
| dnuts | dnuts |
Teal | dnuts.pages.dev |
# Build the default (nutsd) variant
pnpm build
# Build the dnuts variant
VITE_PRODUCT_THEME=dnuts pnpm build# Deploy nutsd
pnpm build
npx wrangler pages deploy dist --project-name nutsd --branch main
# Deploy dnuts
VITE_PRODUCT_THEME=dnuts pnpm build
npx wrangler pages deploy dist --project-name dnuts --branch main┌──────────────────────────────────────────────────┐
│ nutsd (React PWA) │
│ │
│ ┌────────────┐ ┌────────────┐ ┌──────────────┐ │
│ │ Wallet UI │ │ Mint │ │ Transaction │ │
│ │ (dialogs) │ │ Detail │ │ History │ │
│ └─────┬──────┘ └─────┬──────┘ └──────┬───────┘ │
│ └──────────────┼───────────────┘ │
│ ┌────┴────┐ │
│ │ Hooks │ useWallet() │
│ └────┬────┘ │
│ ┌──────────────┼──────────────┐ │
│ ┌────┴─────┐ ┌─────┴──────┐ ┌────┴──────┐ │
│ │ cashu-ts │ │ @enbox/api │ │ Protocols │ │
│ │ Wallet │ │ repository │ │ (DWN) │ │
│ └──────────┘ └─────┬──────┘ └───────────┘ │
└────────────────────────┼─────────────────────────┘
│
┌───────────┴───────────┐
│ User's DWN │
│ (encrypted records) │
│ mint / keyset │
│ proof (one per rec) │
│ transaction │
│ preference │
└───────────────────────┘
| Path | Purpose |
|---|---|
src/protocol/cashu-wallet-protocol.ts |
DWN protocol definition for wallet state |
src/protocol/cashu-transfer-protocol.ts |
DWN protocol for P2P ecash transfers |
src/cashu/wallet-ops.ts |
cashu-ts wrapper (mint, melt, swap, receive) |
src/cashu/token-utils.ts |
Token parsing, encoding, proof selection |
src/hooks/use-wallet.ts |
React hook bridging DWN records and Cashu ops |
src/enbox/EnboxProvider.tsx |
Auth context (DID connect, session restore) |
src/lib/brand.ts |
Build-time brand configuration |
- React 18 + Vite + TypeScript
- Tailwind CSS with Enbox design tokens
- @cashu/cashu-ts — Cashu protocol library
- @enbox/api + @enbox/auth — DWN identity and data
- Workbox — PWA service worker
| NUT | Description | Status |
|---|---|---|
| 00 | Cryptography and models | Supported |
| 01 | Mint public keys | Supported |
| 02 | Keyset IDs | Supported |
| 03 | Token format (V3 + V4) | Supported |
| 04 | Minting (Lightning deposit) | Supported |
| 05 | Melting (Lightning withdraw) | Supported |
| 06 | Mint info | Supported |
| 07 | Token state check | Supported |
| 11 | Pay-to-Pubkey (P2PK) | Planned |
| 13 | Deterministic secrets | Planned |
- Proof secrets, keyset keys, and transaction details (including sent Cashu token strings) are stored in DWN record types with
encryptionRequired: true. The DWN encrypts these using protocol-path-derived keys from the tenant DID's X25519 keyAgreement key. A DWN server operator cannot read them. - Sent token strings are stored encrypted in the transaction record so they can be re-copied and spend-checked across sessions and devices. Once a sent token is confirmed spent (NUT-07), the token is cleared from the record -- it's no longer needed.
- Mint configurations are stored without encryption (they contain only public URLs and names).
- NUT-11 P2PK (Pay-to-Pubkey): The P2P transfer protocol (
cashu-transfer-protocol.ts) stores raw bearer tokens. Until NUT-11 locks tokens to the recipient DID's public key, DWN-mediated transfers are safe only when the recipient operates their own DWN. NUT-11 support is planned. - NUT-13 deterministic secrets: Proofs use random secrets. If DWN data is lost, funds cannot be independently recovered from a seed phrase the way they can in reference wallets. The recovery phrase shown during setup recovers the DID and DWN data, not the Cashu proofs directly. NUT-13 support is planned.
- NUT-09 signature restore: Not yet implemented. Would allow recovering proofs from a mint using deterministic secrets.
MIT