@bankofai/x402-cli 1.0.1-beta.0 → 1.0.1-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,9 +3,9 @@
3
3
  TypeScript command-line client for BankofAI x402 payments. This version uses
4
4
  the npm TypeScript SDK packages only:
5
5
 
6
- - `@bankofai/x402-core@1.0.1-beta.2`
7
- - `@bankofai/x402-evm@1.0.1-beta.2`
8
- - `@bankofai/x402-tron@1.0.1-beta.2`
6
+ - `@bankofai/x402-core@1.0.1`
7
+ - `@bankofai/x402-evm@1.0.1`
8
+ - `@bankofai/x402-tron@1.0.1`
9
9
 
10
10
  Stablecoin payments support `scheme=exact` and TRON `scheme=exact_gasfree`.
11
11
  The GasFree flow lets the relayer pay network energy while deducting its fee
@@ -13,6 +13,15 @@ from the payment token, so the payer does not need TRX.
13
13
 
14
14
  ## Install
15
15
 
16
+ Install the CLI package:
17
+
18
+ ```bash
19
+ npm install -g @bankofai/x402-cli@beta
20
+ x402-cli --version
21
+ ```
22
+
23
+ For repository development:
24
+
16
25
  ```bash
17
26
  npm install
18
27
  npm run build
@@ -21,7 +30,7 @@ npm run build
21
30
  Run from source during development:
22
31
 
23
32
  ```bash
24
- npm run dev -- serve --pay-to <recipient> --amount 0.0001 --network tron:nile --token USDT
33
+ npm run dev -- serve --pay-to <recipient> --amount 0.0001 --network tron:0xcd8690dc --token USDT
25
34
  ```
26
35
 
27
36
  Run the compiled CLI:
@@ -49,10 +58,10 @@ envelope with `ok`, `command`, `result`, or structured `error` fields.
49
58
  Start a local x402 paywall endpoint:
50
59
 
51
60
  ```bash
52
- node dist/cli.js serve \
61
+ x402-cli serve \
53
62
  --pay-to <recipient> \
54
63
  --amount 0.0001 \
55
- --network tron:nile \
64
+ --network tron:0xcd8690dc \
56
65
  --token USDT \
57
66
  --port 4020
58
67
  ```
@@ -61,8 +70,8 @@ The server exposes:
61
70
 
62
71
  - `GET /health`
63
72
  - `GET /.well-known/x402`
64
- - `GET /pay` returns `402 Payment Required`
65
- - `POST /pay` verifies and settles with the facilitator
73
+ - `/pay` returns `402 Payment Required` without a payment signature
74
+ - The signed retry uses the same HTTP method, then verifies and settles with the facilitator
66
75
 
67
76
  ### Pay
68
77
 
@@ -70,18 +79,21 @@ Pay an x402-protected URL:
70
79
 
71
80
  ```bash
72
81
  TRON_PRIVATE_KEY=<hex> \
73
- node dist/cli.js pay http://127.0.0.1:4020/pay \
74
- --network tron:nile \
82
+ x402-cli pay http://127.0.0.1:4020/pay \
83
+ --network tron:0xcd8690dc \
75
84
  --token USDT
76
85
  ```
77
86
 
87
+ For automated or unfamiliar endpoints, set `--max-amount` or
88
+ `--max-raw-amount` before allowing the CLI to sign a payment.
89
+
78
90
  Pay a TRON GasFree endpoint (the CLI normally selects this automatically from
79
91
  the server challenge):
80
92
 
81
93
  ```bash
82
94
  TRON_PRIVATE_KEY=<hex> \
83
- node dist/cli.js pay https://api.example.com/pay \
84
- --network tron:nile \
95
+ x402-cli pay https://api.example.com/pay \
96
+ --network tron:0xcd8690dc \
85
97
  --token USDT \
86
98
  --scheme exact_gasfree
87
99
  ```
@@ -89,7 +101,31 @@ node dist/cli.js pay https://api.example.com/pay \
89
101
  Use `--gasfree-api-url <url>` or `X402_GASFREE_API_URL` to override the SDK's
90
102
  default relayer endpoint.
91
103
 
104
+ GasFree fees are separate from the advertised payment amount. Set a fee limit
105
+ so the CLI estimates the relayer fee and rejects the payment before signing if
106
+ the estimate is too high:
107
+
108
+ ```bash
109
+ x402-cli pay https://api.example.com/pay \
110
+ --scheme exact_gasfree \
111
+ --max-amount 0.01 \
112
+ --max-gasfree-fee 0.5 \
113
+ --json
114
+ ```
115
+
116
+ Use `--max-gasfree-fee-raw` to express the fee limit in the token's smallest
117
+ unit. Successful and failed paid responses distinguish `settled` (payment
118
+ completed) from `delivered` (HTTP business response succeeded). A settled
119
+ upstream failure has `paid=true`, `settled=true`, and `delivered=false` and
120
+ includes its transaction information.
121
+
92
122
  For EVM networks use `EVM_PRIVATE_KEY` or `PRIVATE_KEY`.
123
+ Prefer environment variables over `--private-key` in shared environments,
124
+ because command-line arguments may be visible to other local processes.
125
+
126
+ If the gateway settles a payment but the upstream request fails, JSON error
127
+ output includes `error.details.paymentResponse` for reconciliation. Do not retry
128
+ such a request blindly; inspect the transaction and provider behavior first.
93
129
 
94
130
  ### Roundtrip
95
131
 
@@ -97,10 +133,10 @@ Start a temporary local server and immediately pay it:
97
133
 
98
134
  ```bash
99
135
  TRON_PRIVATE_KEY=<hex> \
100
- node dist/cli.js roundtrip \
136
+ x402-cli roundtrip \
101
137
  --pay-to <recipient> \
102
138
  --amount 0.0001 \
103
- --network tron:nile \
139
+ --network tron:0xcd8690dc \
104
140
  --token USDT
105
141
  ```
106
142
 
@@ -108,16 +144,16 @@ node dist/cli.js roundtrip \
108
144
 
109
145
  Supported built-in token registry:
110
146
 
111
- - `tron:mainnet` USDT, USDD
112
- - `tron:nile` USDT, USDD
113
- - `tron:shasta` USDT
147
+ - `tron:0x2b6653dc` USDT, USDD
148
+ - `tron:0xcd8690dc` USDT, USDD
149
+ - `tron:0x94a9059e` USDT
114
150
  - `eip155:56` USDT
115
151
  - `eip155:97` USDT, USDC
116
152
 
117
- Aliases accepted:
153
+ Non-CAIP TRON aliases are rejected. Use the canonical TRON IDs above.
154
+
155
+ EVM convenience aliases accepted:
118
156
 
119
- - `tron-mainnet` -> `tron:mainnet`
120
- - `tron-nile` -> `tron:nile`
121
157
  - `bsc-mainnet` -> `eip155:56`
122
158
  - `bsc-testnet` -> `eip155:97`
123
159
 
package/dist/args.js ADDED
@@ -0,0 +1,96 @@
1
+ const BOOLEAN_FLAGS = new Set([
2
+ "daemon", "dry-run", "force", "help", "human", "include-blocked", "json", "raw", "version",
3
+ ]);
4
+ export class CliError extends Error {
5
+ code;
6
+ hint;
7
+ exitCode;
8
+ details;
9
+ constructor(code, message, hint, exitCode = 1, details) {
10
+ super(message);
11
+ this.code = code;
12
+ this.hint = hint;
13
+ this.exitCode = exitCode;
14
+ this.details = details;
15
+ }
16
+ }
17
+ export function parseArgs(argv) {
18
+ const [command = "help", ...rest] = argv;
19
+ const positional = [];
20
+ const options = {};
21
+ for (let i = 0; i < rest.length; i += 1) {
22
+ const item = rest[i];
23
+ if (item === "-h") {
24
+ options.help = true;
25
+ continue;
26
+ }
27
+ if (item === "-V") {
28
+ options.version = true;
29
+ continue;
30
+ }
31
+ if (item === "-d") {
32
+ options.daemon = true;
33
+ continue;
34
+ }
35
+ if (item === "-n") {
36
+ const next = rest[i + 1];
37
+ if (!next || next.startsWith("-"))
38
+ options.limit = true;
39
+ else {
40
+ options.limit = next;
41
+ i += 1;
42
+ }
43
+ continue;
44
+ }
45
+ if (!item.startsWith("--")) {
46
+ positional.push(item);
47
+ continue;
48
+ }
49
+ const eq = item.indexOf("=");
50
+ const key = eq > 2 ? item.slice(2, eq) : item.slice(2);
51
+ const inline = eq > 2 ? item.slice(eq + 1) : undefined;
52
+ const next = rest[i + 1];
53
+ if (inline !== undefined)
54
+ options[key] = inline;
55
+ else if (BOOLEAN_FLAGS.has(key))
56
+ options[key] = true;
57
+ else if (!next || next.startsWith("--")) {
58
+ throw new CliError("MISSING_ARGUMENT", `--${key} requires a value`, `Pass --${key} <value>.`, 2);
59
+ }
60
+ else {
61
+ if (key === "header") {
62
+ const current = options[key];
63
+ options[key] = Array.isArray(current) ? [...current, next] : current ? [String(current), next] : [next];
64
+ }
65
+ else
66
+ options[key] = next;
67
+ i += 1;
68
+ }
69
+ }
70
+ return { command, positional, options };
71
+ }
72
+ export function opt(options, key, fallback) {
73
+ const value = options[key];
74
+ return typeof value === "string" ? value : fallback;
75
+ }
76
+ export function hasFlag(options, key) {
77
+ return options[key] === true;
78
+ }
79
+ export function outputMode(options) {
80
+ if (hasFlag(options, "json") && hasFlag(options, "human")) {
81
+ throw new CliError("INVALID_ARGUMENT", "--json and --human are mutually exclusive", "Pass either --json or --human, not both.", 2);
82
+ }
83
+ return hasFlag(options, "json") ? "json" : "human";
84
+ }
85
+ export function requireArgument(value, name, usage) {
86
+ if (value === undefined || value === "") {
87
+ throw new CliError("MISSING_ARGUMENT", `${name} is required`, `Usage: ${usage}`, 2);
88
+ }
89
+ return value;
90
+ }
91
+ export function optAll(options, key) {
92
+ const value = options[key];
93
+ if (Array.isArray(value))
94
+ return value;
95
+ return typeof value === "string" ? [value] : [];
96
+ }