nonce-manager
Original:🇺🇸 English
Translated
2 scriptsChecked / no sensitive code detected
Cross-process Stacks nonce oracle — atomic acquire/release prevents mempool collisions across skills
17installs
Sourceaibtcdev/skills
Added on
NPX Install
npx skill4agent add aibtcdev/skills nonce-managerTags
Translated version includes tags in frontmatterSKILL.md Content
View Translation Comparison →Nonce Manager
Centralized nonce oracle for all Stacks blockchain transactions. Prevents mempool collisions when multiple skills send transactions concurrently or in rapid succession.
Problem
Each skill independently fetches nonce from Hiro API. When tasks fire back-to-back (before mempool clears), they grab the same nonce and collide with or errors.
SENDER_NONCE_STALESENDER_NONCE_DUPLICATESolution
Single file-locked nonce state at . Skills call to get the next nonce (atomically incremented), and after the transaction confirms or fails. If state is stale (>5 min), auto-resyncs from Hiro.
~/.aibtc/nonce-state.jsonacquirereleaseSubcommands
acquire
Get the next nonce for a Stacks address. Atomically increments the stored value. Auto-syncs from Hiro if state is missing or stale (>5 min).
bun run nonce-manager/nonce-manager.ts acquire --address SP...Output:
json
{ "nonce": 42, "address": "SP...", "source": "local" }release
Mark a nonce as confirmed or failed after transaction outcome is known.
bun run nonce-manager/nonce-manager.ts release --address SP... --nonce 42
bun run nonce-manager/nonce-manager.ts release --address SP... --nonce 42 --failed
bun run nonce-manager/nonce-manager.ts release --address SP... --nonce 42 --failed --rejectedFailure kinds (critical distinction):
- — tx never reached mempool (signing error, relay 409 nonce rejection). Nonce NOT consumed, safe to roll back and reuse.
--rejected - (default when
--broadcast) — tx reached mempool. Nonce IS consumed even if the tx fails on-chain. Do NOT roll back.--failed
Only triggers a rollback. Default assumes broadcast (safer).
--failed --rejected--failedOutput:
json
{ "address": "SP...", "nonce": 42, "action": "confirmed" }sync
Force re-sync nonce state from Hiro API. Use after manual intervention or mempool clearance.
bun run nonce-manager/nonce-manager.ts sync --address SP...Output:
json
{ "nonce": 42, "address": "SP...", "mempoolPending": 3, "lastExecuted": 41, "detectedMissing": [] }status
Show current nonce state for one or all tracked addresses.
bun run nonce-manager/nonce-manager.ts status
bun run nonce-manager/nonce-manager.ts status --address SP...Library Import
Skills running in the same process can import directly:
typescript
import { acquireNonce, releaseNonce, syncNonce } from "../nonce-manager/nonce-store.js";
const { nonce } = await acquireNonce("SP...");
// ... send transaction ...
await releaseNonce("SP...", nonce, true); // true = successNonce Strategy
- Acquire before send — always get nonce from manager, never from Hiro directly
- Release after confirm/fail — keeps state accurate for next caller
- Auto-sync on stale — if last sync >5 min ago, re-fetch from Hiro before returning
- File lock for atomicity — mkdir-based lock prevents concurrent reads returning same nonce
- Distinguish broadcast vs rejected — only rejected nonces can be rolled back
Integration with x402 Error Codes
Per landing-page#522, map relay error codes to release actions:
| Relay Response | Release Action |
|---|---|
| |
| |
| |
| |
| |
| |