Paperclip Deployment Engineer 8009714cda feat: mint health cache, xcashu token sweep, network error fallback patterns
Three changes that harden the mint-fallback branch against upstream
failures and enable proper provider failover:

1. Mint health cache (src/daemon/wallet/index.ts)
   Track mints that are temporarily unreachable (connection refused,
   DNS failure, TLS error). Unhealthy mints are skipped by
   getActiveMintUrl() and sendToken() so we don't waste a round-trip
   on every request. Mints are automatically retried after a 60s
   cooldown. The active mint switches to a healthy one when the current
   one goes unhealthy.

   This is critical for the xcashu 402 failover fix: when the primary
   provider (localhost:8011) is down, the wallet needs to successfully
   create a token via a healthy mint BEFORE the SDK's failover logic
   can route the request to the next provider (routstr.otrta.me).
   Without the health cache, every request wasted 2-3 seconds on a
   failed mint.minibits.cash fetch before falling back to cubabitcoin.

2. xcashu token sweep (src/daemon/index.ts)
   The scheduled refund loop now also sweeps pending xcashu tokens that
   failed inline refund (e.g. 'proofs already spent' — the token stays
   in storage and needs retry). This prevents orphaned IOUs from
   accumulating and ensures the background refundXcashuTokens path
   gets a chance to reclaim sats from tokens where the inline receive
   raced with the sweep.

   This is the race condition that caused the double-refund negative
   satsSpent bug (xcashu-double-refund-negative-sats, prio 998): the
   inline receive and the background sweep both received the same token,
   producing a negative satsSpent written to usage_tracking.

3. Network error patterns (src/daemon/wallet/mint-fallback.ts)
   Extend inspectForMintUnreachable to recognize Bun-specific network
   failures: 'Failed to fetch mint <url>', 'NetworkError when attempting
   to fetch resource', and 'Load failed'. These are treated as
   mint-unreachable so the fallback to the next configured mint kicks
   in immediately instead of surfacing the raw error.

   This pairs with the SDK fix (routstr-sdk PR #32) that adds
   'Unable to connect' and 'ECONNREFUSED' to isNetworkErrorMessage so
   the SDK's failover path is triggered when the upstream provider is
   completely unreachable (not just returning an HTTP error).

Related issues:
- Nostr: xcashu-402-body-refund-no-failover (prio 990, event a4d7e1cd...)
- Nostr: xcashu-double-refund-negative-sats (prio 998, event 14982f8d...)
- SDK PR: https://github.com/Routstr/routstr-sdk/pull/32
- SDK PR: https://github.com/Routstr/routstr-sdk/pull/31 (clamp fix)
2026-07-28 13:24:14 +00:00
2026-07-12 08:26:44 +05:30
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

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

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": {...}
}

Configuration

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

{
  "port": 8008,
  "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
1.2 MiB
Languages
TypeScript 99.5%
Shell 0.4%