forked from aibtcdev/skills
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnonce-manager.ts
More file actions
86 lines (75 loc) · 2.77 KB
/
Copy pathnonce-manager.ts
File metadata and controls
86 lines (75 loc) · 2.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#!/usr/bin/env bun
/**
* Nonce Manager skill CLI
* Backup sender nonce tracker for Stacks transactions.
* Use canonical payment-status polling as the primary x402 state machine.
*
* Usage: bun run nonce-manager/nonce-manager.ts <subcommand> [options]
*/
import { Command } from "commander";
import { acquireNonce, releaseNonce, syncNonce, getStatus, type FailureKind } from "./nonce-store.js";
import { printJson, handleError } from "../src/lib/utils/cli.js";
const program = new Command("nonce-manager")
.description("Backup sender nonce tracker for Stacks transactions — not the primary x402 payment state machine")
.version("1.0.0");
// ---- acquire ----
program
.command("acquire")
.description("Get the next nonce for a Stacks address (atomically incremented)")
.requiredOption("--address <address>", "Stacks address")
.action(async (options: { address: string }) => {
try {
const result = await acquireNonce(options.address);
printJson(result);
} catch (error) {
handleError(error);
}
});
// ---- release ----
program
.command("release")
.description("Mark a nonce as confirmed or failed after transaction outcome")
.requiredOption("--address <address>", "Stacks address")
.requiredOption("--nonce <nonce>", "Nonce value to release", parseInt)
.option("--failed", "Mark as failed (default is success)")
.option("--rejected", "Failure kind: tx never reached mempool, nonce can be reused")
.option("--broadcast", "Failure kind: tx reached mempool, nonce consumed (default for --failed)")
.action(async (options: { address: string; nonce: number; failed?: boolean; rejected?: boolean; broadcast?: boolean }) => {
try {
const success = !options.failed;
const failureKind: FailureKind | undefined = !success
? (options.rejected ? "rejected" : "broadcast")
: undefined;
const result = await releaseNonce(options.address, options.nonce, success, failureKind);
printJson(result);
} catch (error) {
handleError(error);
}
});
// ---- sync ----
program
.command("sync")
.description("Force re-sync nonce state from Hiro API")
.requiredOption("--address <address>", "Stacks address")
.action(async (options: { address: string }) => {
try {
const result = await syncNonce(options.address);
printJson(result);
} catch (error) {
handleError(error);
}
});
// ---- status ----
program
.command("status")
.description("Show current nonce state for one or all tracked addresses")
.option("--address <address>", "Stacks address (omit for all)")
.action(async (options: { address?: string }) => {
try {
const result = getStatus(options.address);
printJson(result ?? {});
} catch (error) {
handleError(error);
}
});
program.parse();