redshift 1b93872b0b fix(wallet): deduplicate Cashu receives before recovery
Prevent repeated submissions of the same encoded Cashu token from creating an unbounded number of Coco receive operations. Routstrd now hashes each exact token with SHA-256 and atomically reserves that hash in persistent wallet metadata before preparing a Coco receive operation.

Persist the token hash, Coco operation ID, processing state, success state, and failure details so duplicate protection survives daemon restarts. Reconcile interrupted reservations against Coco operations at startup, cancel prepared operations that never reached the mint, preserve unresolved executing operations, and convert finalized operations into idempotent successful responses.

When a retry references an unresolved operation, refresh that existing operation instead of creating another one. If Coco finalized an operation while returning an earlier request error, report success. If a rolled-back operation has a finalized sibling with the same proofs, report the token as already received instead of recording a false failure.

Add a pre-recovery reconciliation pass for legacy executing receive operations. Group rows by normalized mint, unit, and complete sorted proof material so thousands of duplicate rows are handled as a small number of unique input sets.

For each unique group, check proof state only once. If inputs are unspent, retain one valid canonical operation and retire redundant copies. If inputs are spent, probe all stored deterministic outputs in bounded restore batches, retain operations whose outputs are recoverable, and roll back only non-owning duplicates. If restore conclusively returns no matching outputs, mark the group rolled back using Coco 2's terminal recovery reason.

Leave groups untouched when proof-state responses are incomplete or mixed, output data is malformed, the mint is unavailable, or any persistence step fails. Add per-request timeouts, a global 45-second startup budget, and per-mint fail-fast behavior so an offline mint cannot recreate the multi-hour startup incident.

Create and record a standalone SQLite backup before the first receive cleanup, before Coco watchers and processors are enabled. Continue normal send, melt, and mint recovery while limiting receive recovery to retained operations, avoiding Coco 1.0.1's expensive per-row sweep over unresolved duplicates.

Add focused tests for exact-token reservation, persistent state, interrupted reservation cleanup, grouping, unspent canonical selection, spent empty restore, restored output ownership, incomplete and mixed proof states, and a production-shaped case containing 1,924 operations collapsed into 47 mint checks.

Also add the detailed Coco 2.0.0 migration plan covering staged database migration, receive preflight, rollback, compatibility, and eventual upgrade work.

Validation:

- bun run lint

- bun run build

- 40 focused wallet tests pass

- full suite reaches 96 passing tests; one pre-existing Hermes config test remains unrelated and failing
2026-08-18 21:26:22 +01:00
2026-08-17 13:25:13 +01:00
2026-04-06 18:53:44 +01:00
2026-03-30 21:06:30 +01:00
2026-03-19 16:25:57 +00:00
2026-03-21 23:19:38 +00:00
2026-02-25 04:35:46 +00:00
2026-03-21 23:19:38 +00:00
2026-03-21 23:19:38 +00:00
2026-02-24 05:55:21 +00:00
bug
2026-03-28 22:36:13 +00:00

routstrd

Routstr daemon - A CLI tool for managing routstr processes, similar to cocod (a Cashu wallet daemon).

Overview

routstrd is a Bun-based CLI tool that provides a background daemon for the Routstr protocol. It integrates with cocod for wallet management and uses the Routstr SDK to handle provider routing and model discovery.

Routstr for Teams

For team-based routing, see routstrd-auth.

Features

  • Daemon Mode: Run routstrd as a background HTTP server
  • Wallet Integration: Works with cocod for Cashu token management
  • Provider Routing: Automatically discovers and routes requests to available providers
  • Config Management: Stores configuration in ~/.routstrd/

Requirements

curl -fsSL https://bun.com/install | bash

Installation

Step 1: Install

Global with bun:

bun i -g routstrd

OR - From source:

git clone https://github.com/routstr/routstrd.git
cd routstrd
bun install
bun link

Step 2: Setup & Fund

routstrd onboard
routstrd receive <cashu>       # receive a Cashu token
routstrd receive 2100         # to top up 2100 sats with lightning

Step 3: Integrate with Claude Code

routstrd clients add --claude-code  # or --pi-agent / --opencode

Use Routstrd Skill

Tip: You can also install the routstrd skill so the agent can manage routstrd for you.

More Commands

Start Daemon

Start the background daemon:

routstrd start

With custom port:

routstrd start --port 9000

The daemon binds to 127.0.0.1 by default. To expose it on another interface:

routstrd start --host 0.0.0.0

Only expose the daemon behind appropriate network controls.

With specific provider:

routstrd start --provider https://your-provider.com

CLI Commands

Check daemon status:

routstrd status

Get wallet balance:

routstrd balance

Test connection:

routstrd ping

Stop the daemon:

routstrd stop

NPC (Lightning Address)

The in-process wallet registers the NPC (npubx.cash) plugin, which gives the daemon a persistent Lightning address backed by the wallet's Cashu mints. Payments to the address are imported into the wallet automatically (websocket push, plus manual sync on demand).

# Show your NPC Lightning address (username@npubx.cash, or npub fallback)
routstrd wallet npc address

# Claim a username (quote first, then confirm to pay the claim fee from the wallet)
routstrd wallet npc username myname
routstrd wallet npc username myname --confirm

# Manually sync paid NPC quotes into the wallet
routstrd wallet npc sync

Equivalent daemon endpoints: GET /wallet/npc/address, POST /wallet/npc/username, POST /wallet/npc/sync.

Daemon API

The daemon exposes an HTTP server (default port 8008) with the following endpoints:

Health Check

GET /health

Route Request

POST /

Request body:

{
  "model": "model-id",
  "messages": [...],
  "stream": false
}

Response:

{
  "choices": [...],
  "usage": {...}
}

Wallet storage

The in-process Cashu wallet stores its mnemonic and proof database in ~/.routstrd/wallet/. On first startup, an existing wallet in ~/.cocod/ is migrated automatically after routstrd verifies that the legacy cocod daemon is not running. Back up your mnemonic before upgrading.

Set ROUTSTRD_WALLET_DIR to override the canonical wallet directory. The COCOD_DIR, COCOD_SOCKET, and COCOD_PID variables are retained only for locating and excluding a legacy external cocod process.

Configuration

Configuration is stored in ~/.routstrd/config.json:

{
  "port": 8008,
  "host": "127.0.0.1",
  "provider": null,
  "cocodPath": null
}

Environment Variables

  • ROUTSTRD_DIR - Config directory (default: ~/.routstrd)
  • ROUTSTRD_SOCKET - Socket path (default: ~/.routstrd/routstrd.sock)
  • ROUTSTRD_PID - PID file path (default: ~/.routstrd/routstrd.pid)

Development

Install dependencies:

bun install

Run CLI:

bun run start

Run daemon:

bun run start

Typecheck:

bun run lint

Project Structure

routstrd/
├── src/
│   ├── index.ts       # Entry point with shebang
│   ├── cli.ts         # Commander CLI commands
│   ├── cli-shared.ts  # IPC utilities
│   ├── daemon.ts      # HTTP server daemon
│   └── utils/
│       └── config.ts  # Path configuration
├── package.json
└── tsconfig.json

License

MIT

S
Description
A Routstr daemon that runs locally to route you to the best Routstr provider from all available Routstr nodes.
Readme
5.3 MiB
Languages
TypeScript 98.8%
Shell 1.2%