Problem
isRelayHealthy() and checkRelayHealth() in src/utils/relay-health.ts don't read the relay's pool state fields, causing false-healthy reports when the relay pool is degraded.
What the relay returns (v1.26.1)
{
"status": "ok",
"version": "1.26.1",
"nonce": {
"poolAvailable": 20,
"poolReserved": 0,
"conflictsDetected": 47,
"circuitBreakerOpen": true,
"effectiveCapacity": 1,
"poolStatus": "critical",
"lastConflictAt": "2026-03-28T17:53:50.250Z",
"recommendation": null
}
}
What the code reads
isRelayHealthy(): HTTP 200 + status === "ok" — misses pool degradation entirely
checkRelayHealth(): reads status and version only — same gap
What should be checked
At minimum, checkRelayHealth() should flag:
nonce.circuitBreakerOpen === true → issue: "Relay circuit breaker is open"
nonce.poolStatus === "critical" → issue: "Relay nonce pool is critical"
nonce.effectiveCapacity < 5 → issue: "Relay effective capacity degraded (N/20)"
nonce.conflictsDetected > 10 → issue: "Relay has N nonce conflicts"
isRelayHealthy() (the hot-path probe) should at minimum check nonce.circuitBreakerOpen !== true.
Additional: only wallet 0 nonces are checked
Both functions query Hiro for the hardcoded sponsor address SP1PMPPVCMVW96... (wallet 0 of 10). The relay now exposes GET /nonce/state with per-wallet state. checkRelayHealth() should either:
- Use
/nonce/state to get per-wallet health, or
- At minimum, surface the relay's self-reported pool health fields
New endpoint available
GET /nonce/state (v1.26.1) returns per-wallet: chainFrontier, assignmentHead, pendingTxs, gaps, circuitBreakerOpen, healthy, queueDepth, settlementTimes, plus global probeQueue state.
🤖 Generated with Claude Code
Problem
isRelayHealthy()andcheckRelayHealth()insrc/utils/relay-health.tsdon't read the relay's pool state fields, causing false-healthy reports when the relay pool is degraded.What the relay returns (v1.26.1)
{ "status": "ok", "version": "1.26.1", "nonce": { "poolAvailable": 20, "poolReserved": 0, "conflictsDetected": 47, "circuitBreakerOpen": true, "effectiveCapacity": 1, "poolStatus": "critical", "lastConflictAt": "2026-03-28T17:53:50.250Z", "recommendation": null } }What the code reads
isRelayHealthy(): HTTP 200 +status === "ok"— misses pool degradation entirelycheckRelayHealth(): readsstatusandversiononly — same gapWhat should be checked
At minimum,
checkRelayHealth()should flag:nonce.circuitBreakerOpen === true→ issue: "Relay circuit breaker is open"nonce.poolStatus === "critical"→ issue: "Relay nonce pool is critical"nonce.effectiveCapacity < 5→ issue: "Relay effective capacity degraded (N/20)"nonce.conflictsDetected > 10→ issue: "Relay has N nonce conflicts"isRelayHealthy()(the hot-path probe) should at minimum checknonce.circuitBreakerOpen !== true.Additional: only wallet 0 nonces are checked
Both functions query Hiro for the hardcoded sponsor address
SP1PMPPVCMVW96...(wallet 0 of 10). The relay now exposesGET /nonce/statewith per-wallet state.checkRelayHealth()should either:/nonce/stateto get per-wallet health, orNew endpoint available
GET /nonce/state(v1.26.1) returns per-wallet:chainFrontier,assignmentHead,pendingTxs,gaps,circuitBreakerOpen,healthy,queueDepth,settlementTimes, plus globalprobeQueuestate.🤖 Generated with Claude Code