Your crypto shouldn't die with you.
Open-source crypto inheritance platform built on OWS + Base + Chainlink
Quick Start • How It Works • Mock vs Real • Deployment • Smart Contract • Contributing
Dead Man's Switch automatically distributes your crypto assets to the people you choose if you ever become unreachable. Set up your will, check in periodically, and know that your loved ones are protected.
git clone https://github.com/yourusername/dead-mans-switch.git
cd dead-mans-switch
./setup.sh
npm run dev:allOpen http://localhost:3001. That's it.
What happens:
setup.shinstalls all dependencies, copies.env.examplefiles, and sets up the SQLite databasenpm run dev:allstarts the API (port 3000) and frontend (port 3001) in mock mode- You land on the welcome page → create an account → set up your first will
- Node.js 20+
- npm
- Create your will — name your beneficiaries (who gets what %) and guardians (who confirms if you're gone)
- Fund your vault — send USDC to your wallet address on Base chain
- Check in regularly — click a button or click a link in your email every 30 days (configurable)
- That's it — as long as you check in, nothing happens
Day 0: You miss a check-in
→ Grace period starts (7 days default)
→ You get email alerts + push notifications
→ You can still check in to cancel
Day 7: Grace expires
→ Your guardians are notified
→ They vote on whether you're truly unreachable
Day 7+: 2 of 3 guardians vote "proceed"
→ Final pending window starts (48 hours)
→ You can STILL cancel
Day 9+: Pending window expires
→ Funds are distributed to your beneficiaries
→ Immediate beneficiaries get their full share
→ Drip beneficiaries get a rate-limited vault
- They receive an invite link via email
- They click it, enter their wallet address (or ENS name like
sarah.eth) - You approve their address
- If the plan executes, funds are sent automatically
- They can check their status anytime on the claim page
- They receive an invite to accept the guardian role
- They acknowledge the responsibility
- If you become unreachable, they vote on whether to proceed
- They can vote "proceed", "unsure", or "cancel"
The app has two modes controlled by MOCK_TRANSFERS:
npm run dev:all # or MOCK_TRANSFERS=true npm run devWhat mock mode does:
- Wallet balance always shows $10.00 (no real chain query)
- USDC transfers are simulated — no real tokens move, fake tx hashes are generated
- Emails are logged to console (not actually sent)
- Push notifications are logged (not actually sent)
- OWS wallets are created for real (local encrypted vault at
~/.ows/) - The state machine, guardian voting, drip vault — everything else works for real
Use mock mode for: development, demos, testing the full flow without real money.
MOCK_TRANSFERS=false npm run dev # or just: npm run devWhat changes in real mode:
- Wallet balance is queried from Base chain via RPC
- USDC transfers are signed by OWS and broadcast to Base — real tokens move
- You need real USDC on Base in your wallet
- You need ETH on Base for gas fees
- Emails are sent via Resend or SMTP — see Email Setup Guide
Switching from mock to real:
- Set
MOCK_TRANSFERS=falseinapps/api/.env - Set
BASE_RPC_URL=https://mainnet.base.org(mainnet) or keep the default (Base Sepolia testnet) - Fund your wallet with USDC + ETH on the chosen chain
- Set up email — see Email Setup Guide
- Restart the server
Recommended path: Start on Base Sepolia testnet (free test USDC from faucets), then switch to mainnet when ready.
- 5-gate safety pipeline — check-in → grace → guardian vote → pending → execution
- Programmable drip payouts — release funds gradually over time
- Guardian quorum — 2-of-3 (configurable) must agree before any distribution
- Emergency freeze — halt everything instantly with one click
- Personal messages — leave words for your loved ones, shown after execution
- Passkey (WebAuthn) — sign in with Touch ID / Face ID, no passwords
- Email/password — traditional auth as fallback
- Hardware wallet support — connect Ledger/Trezor via WalletConnect
- Safe multi-sig — use Gnosis Safe as the policy owner for maximum security
- Field encryption — emails and personal messages encrypted at rest (AES-256-GCM)
- Rate limiting — per-endpoint limits to prevent abuse
- Invite token expiry — 72-hour expiration on invite links
- Smart contract escrow — funds held on-chain, not by the app
- On-chain guardian voting — guardians vote directly on the contract
- Chainlink Automation — decentralized keepers trigger execution (no server dependency)
- Multi-token — distribute USDC, ETH, WBTC, or any ERC-20
- NFT inheritance — transfer ERC-721 NFTs to beneficiaries
- Gasless claiming — pull mode lets relayers pay gas for beneficiaries
- ENS resolution — enter
sarah.ethinstead of0x...
- Beneficiary invite flow — they provide their own wallet, you approve
- Guardian acceptance — formal role acknowledgment before voting access
- One-click email check-in — click a link in the reminder email
- Push notifications — browser notifications for check-in reminders
- Activity timeline — full event history on the dashboard
- Mobile responsive — hamburger menu, stacking layouts
- Light/dark mode
- GDPR data export + account deletion
- Terms of Service page
| Layer | Technology |
|---|---|
| Backend | Hono + Node.js + SQLite (Drizzle ORM) |
| Frontend | Next.js 16 + shadcn/ui + Tailwind CSS |
| Auth | Better Auth (passkey + email + SIWE) |
| Wallet | OWS SDK + wagmi + ConnectKit |
| Smart Contract | Solidity + Hardhat + OpenZeppelin + Chainlink |
| Chain | Base (USDC) via viem |
| Resend / Nodemailer SMTP / console fallback |
| Command | Description |
|---|---|
npm run dev:all |
Start API (mock) + frontend |
npm run dev |
Start backend only (real mode) |
npm run dev:mock |
Start backend only (mock mode) |
npm run dev:web |
Start frontend only |
npm test |
Run 30 backend tests |
npm run contracts:test |
Run 82 smart contract tests |
npm run build |
Build frontend (22 routes) |
npm run seed |
Seed demo data (wallets + policy + beneficiaries + guardians) |
npm run reset |
Clear all data |
npm run backup |
Backup SQLite database |
make dev |
Shortcut for npm run dev:all |
make test |
Run all tests (backend + contracts) |
| Variable | Default | Description |
|---|---|---|
PORT |
3000 |
Backend port |
MOCK_TRANSFERS |
true |
true = simulated transfers, false = real USDC on Base |
BETTER_AUTH_URL |
http://localhost:3000 |
Where the API is accessible (for auth callbacks) |
RPID |
localhost |
Passkey domain (e.g., yourdomain.com in production) |
ORIGIN |
http://localhost:3001 |
Frontend URL (for CORS + cookies) |
ENCRYPTION_KEY |
dev fallback | Change in production. Encrypts emails and messages. |
EXECUTOR_SECRET |
demo-secret |
Change in production. Protects the executor endpoint. |
RESEND_API_KEY |
— | Resend.com API key for sending emails |
SMTP_HOST |
— | SMTP server (alternative to Resend) |
BASE_RPC_URL |
Base Sepolia | Base chain RPC (https://mainnet.base.org for production) |
LOG_LEVEL |
info |
debug / info / warn / error |
| Variable | Default | Description |
|---|---|---|
NEXT_PUBLIC_SKIP_AUTH |
false |
true bypasses auth (for demos only) |
NEXT_PUBLIC_CONTRACT_ADDRESS |
— | Deployed escrow contract address |
NEXT_PUBLIC_WC_PROJECT_ID |
— | WalletConnect Cloud project ID |
See apps/api/.env.example and apps/web/.env.example for the complete list.
apps/
├── api/ # Hono backend
│ ├── src/server.ts # Entry point + cron loop
│ ├── src/auth/ # Better Auth (passkey + email + SIWE)
│ ├── src/cron/ # 5-gate state machine
│ ├── src/db/ # Drizzle schema + SQLite
│ ├── src/lib/ # Email, encryption, events, rate limiting, logging
│ ├── src/ows/ # OWS wallet + USDC transfer helpers
│ └── src/routes/ # API endpoints (~30 routes)
└── web/ # Next.js frontend (22 routes)
├── (dashboard)/ # Authenticated: overview, check-in, guardians, drip, invites, settings
├── welcome/ # Public landing page
├── login/ # Auth (passkey + email)
├── claim/ # Beneficiary claim page (public)
├── accept-invite/ # Beneficiary invite acceptance (public)
├── accept-guardian/ # Guardian role acceptance (public)
├── deposit/ # Hardware wallet USDC deposit
├── onchain-checkin/ # On-chain check-in via Ledger
└── security/ # Custody model settings
packages/
└── contracts/ # Solidity smart contracts
├── DeadMansSwitch.sol # Escrow + guardian voting + Chainlink + multi-token + NFT
└── 82 tests
The escrow contract enforces fund protection on-chain. Even if the backend server goes down, the critical path works:
| Action | Server alive | Server dead |
|---|---|---|
| Owner check-in | Dashboard button or email link | Call checkIn() directly from Ledger |
| Guardian voting | Web UI | Call vote() directly on the contract |
| Distribution trigger | Backend executor | Chainlink keeper calls performUpkeep() |
| Beneficiary claiming | Web claim page | Call claim() on the contract |
- USDC escrow with check-in timer enforcement
- On-chain guardian voting with configurable quorum
- Chainlink Automation — decentralized execution trigger
- Multi-ERC20 distribution (USDC, WBTC, DAI, etc.)
- Native ETH distribution
- ERC-721 NFT inheritance (single + batch)
- Pull mode — gasless claiming for beneficiaries
- Emergency withdraw — owner can pull all funds at any time
- Freeze/unfreeze — halt distribution instantly
cd packages/contracts
DEPLOYER_PRIVATE_KEY=0x... EXECUTOR_ADDRESS=0x... npx hardhat run scripts/deploy.ts --network baseSepoliaThen set NEXT_PUBLIC_CONTRACT_ADDRESS in your .env.
./setup.sh # One-time setup
npm run dev:all # Start everything (mock mode)cp .env.docker.example .env # Edit ENCRYPTION_KEY, EXECUTOR_SECRET
docker compose up -d # Start API + Web
docker compose exec api npx tsx scripts/seed-demo.ts # Optional: seed datacp .env.docker.example .env
# Edit: DOMAIN, ENCRYPTION_KEY, EXECUTOR_SECRET, MOCK_TRANSFERS=false
DOMAIN=deadswitch.yourdomain.com docker compose -f docker-compose.production.yml up -dCaddy auto-provisions HTTPS via Let's Encrypt. DNS must point to your server. Ports 80 + 443 must be open.
Internet → Caddy (:443, auto HTTPS)
├── / → Next.js frontend
└── /api/* → Hono backend
+ daily SQLite backups
See CONTRIBUTING.md for development setup, code style, and PR guidelines.
- 30 backend tests (Vitest) — auth, state machine, drip vault, validation
- 82 smart contract tests (Hardhat/Chai) — escrow, guardian voting, Chainlink, multi-token, NFT, freeze, emergency withdraw
make test # or: npm test && npm run contracts:test