Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
193c838
feat: add TRON GasFree payment support
Jul 15, 2026
143f9aa
chore: prepare CLI 1.0.1 beta.1
Jul 15, 2026
fb2b08f
fix: bundle gateway beta.1 in CLI
Jul 15, 2026
3095876
fix: fail CLI payments on HTTP errors
Jul 16, 2026
ae91671
fix: use canonical TRON network IDs by default
Jul 16, 2026
099c545
fix: reject legacy TRON network identifiers
Jul 16, 2026
a7851d1
fix: preserve settlement details on payment errors
Jul 16, 2026
5f29732
docs: clarify payment safety and CLI behavior
Jul 16, 2026
1540f33
fix: improve multi-network payment selection
Jul 16, 2026
963c8a6
fix: cap GasFree fees and report settlement state
Jul 16, 2026
36261b9
Merge remote-tracking branch 'origin/main' into feat/cli-1.0.1-gasfree
Jul 17, 2026
8f648e7
docs: install and use CLI beta explicitly
Jul 17, 2026
9ed2445
chore: use x402 SDK 1.0.1 release
Jul 17, 2026
5cbb584
fix: harden CLI payment validation
Jul 17, 2026
7a1ce2b
test: verify daemon readiness and packed CLI
Jul 17, 2026
8da9584
ci: test TypeScript CLI and release package
Jul 17, 2026
8146b71
chore: bundle gateway 1.0.1-beta.7
Jul 18, 2026
1617cc2
refactor: extract CLI infrastructure modules
Jul 20, 2026
b562c95
refactor: isolate CLI daemon lifecycle
Jul 20, 2026
d07246a
refactor: extract catalog gateway and help commands
Jul 20, 2026
cf0c6cc
refactor: delegate provider operations to gateway API
Jul 20, 2026
2ce4237
fix: make CLI package builds clean and reproducible
Jul 20, 2026
c1f940d
chore: prepare CLI 1.0.1 release
Jul 20, 2026
c42c832
test: validate packed CLI release version
Jul 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
name: cli-ci

on:
pull_request:
push:
branches: [main]
tags: ["v*", "test-v*"]
workflow_dispatch:

permissions:
contents: read

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "20.11"
cache: npm

- name: Install dependencies
run: npm ci

- name: Test
run: npm test

- name: Audit production dependencies
run: npm audit --omit=dev --audit-level=high

- name: Verify packed CLI
run: npm run test:package
96 changes: 74 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,25 @@
TypeScript command-line client for BankofAI x402 payments. This version uses
the npm TypeScript SDK packages only:

- `@bankofai/x402-core@1.0.0`
- `@bankofai/x402-evm@1.0.0`
- `@bankofai/x402-tron@1.0.0`
- `@bankofai/x402-core@1.0.1`
- `@bankofai/x402-evm@1.0.1`
- `@bankofai/x402-tron@1.0.1`

Stablecoin payments use `scheme=exact` with
`extra.assetTransferMethod=permit2`.
Stablecoin payments support `scheme=exact` and TRON `scheme=exact_gasfree`.
The GasFree flow lets the relayer pay network energy while deducting its fee
from the payment token, so the payer does not need TRX.

## Install

Install the CLI package:

```bash
npm install -g @bankofai/x402-cli@1.0.1
x402-cli --version
```

For repository development:

```bash
npm install
npm run build
Expand All @@ -20,7 +30,7 @@ npm run build
Run from source during development:

```bash
npm run dev -- serve --pay-to <recipient> --amount 0.0001 --network tron:nile --token USDT
npm run dev -- serve --pay-to <recipient> --amount 0.0001 --network tron:0xcd8690dc --token USDT
```

Run the compiled CLI:
Expand Down Expand Up @@ -48,10 +58,10 @@ envelope with `ok`, `command`, `result`, or structured `error` fields.
Start a local x402 paywall endpoint:

```bash
node dist/cli.js serve \
x402-cli serve \
--pay-to <recipient> \
--amount 0.0001 \
--network tron:nile \
--network tron:0xcd8690dc \
--token USDT \
--port 4020
```
Expand All @@ -60,49 +70,90 @@ The server exposes:

- `GET /health`
- `GET /.well-known/x402`
- `GET /pay` returns `402 Payment Required`
- `POST /pay` verifies and settles with the facilitator
- `/pay` returns `402 Payment Required` without a payment signature
- The signed retry uses the same HTTP method, then verifies and settles with the facilitator

### Pay

Pay an x402-protected URL:

```bash
TRON_PRIVATE_KEY=<hex> \
node dist/cli.js pay http://127.0.0.1:4020/pay \
--network tron:nile \
x402-cli pay http://127.0.0.1:4020/pay \
--network tron:0xcd8690dc \
--token USDT
```

For automated or unfamiliar endpoints, set `--max-amount` or
`--max-raw-amount` before allowing the CLI to sign a payment.

Pay a TRON GasFree endpoint (the CLI normally selects this automatically from
the server challenge):

```bash
TRON_PRIVATE_KEY=<hex> \
x402-cli pay https://api.example.com/pay \
--network tron:0xcd8690dc \
--token USDT \
--scheme exact_gasfree
```

Use `--gasfree-api-url <url>` or `X402_GASFREE_API_URL` to override the SDK's
default relayer endpoint.

GasFree fees are separate from the advertised payment amount. Set a fee limit
so the CLI estimates the relayer fee and rejects the payment before signing if
the estimate is too high:

```bash
x402-cli pay https://api.example.com/pay \
--scheme exact_gasfree \
--max-amount 0.01 \
--max-gasfree-fee 0.5 \
--json
```

Use `--max-gasfree-fee-raw` to express the fee limit in the token's smallest
unit. Successful and failed paid responses distinguish `settled` (payment
completed) from `delivered` (HTTP business response succeeded). A settled
upstream failure has `paid=true`, `settled=true`, and `delivered=false` and
includes its transaction information.

For EVM networks use `EVM_PRIVATE_KEY` or `PRIVATE_KEY`.
Prefer environment variables over `--private-key` in shared environments,
because command-line arguments may be visible to other local processes.

If the gateway settles a payment but the upstream request fails, JSON error
output includes `error.details.paymentResponse` for reconciliation. Do not retry
such a request blindly; inspect the transaction and provider behavior first.

### Roundtrip

Start a temporary local server and immediately pay it:

```bash
TRON_PRIVATE_KEY=<hex> \
node dist/cli.js roundtrip \
x402-cli roundtrip \
--pay-to <recipient> \
--amount 0.0001 \
--network tron:nile \
--network tron:0xcd8690dc \
--token USDT
```

## Networks

Supported built-in token registry:

- `tron:mainnet` USDT, USDD
- `tron:nile` USDT, USDD
- `tron:shasta` USDT
- `tron:0x2b6653dc` USDT, USDD
- `tron:0xcd8690dc` USDT, USDD
- `tron:0x94a9059e` USDT
- `eip155:56` USDT
- `eip155:97` USDT, USDC

Aliases accepted:
Non-CAIP TRON aliases are rejected. Use the canonical TRON IDs above.

EVM convenience aliases accepted:

- `tron-mainnet` -> `tron:mainnet`
- `tron-nile` -> `tron:nile`
- `bsc-mainnet` -> `eip155:56`
- `bsc-testnet` -> `eip155:97`

Expand All @@ -114,5 +165,6 @@ Pass a facilitator URL when needed:
x402-cli serve --facilitator-url https://facilitator.bankofai.io ...
```

CLI payment challenges and payload selection always emit `scheme: "exact"` for
the SDK 1.0 Permit2 path.
`serve --scheme exact_gasfree` advertises a TRON GasFree requirement. The
configured facilitator must advertise and settle `exact_gasfree` for that
network and token.
70 changes: 23 additions & 47 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 12 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@bankofai/x402-cli",
"version": "1.0.0",
"version": "1.0.1",
"type": "module",
"files": [
"dist"
Expand All @@ -9,28 +9,32 @@
"x402-cli": "dist/cli.js"
},
"scripts": {
"build": "tsc -p tsconfig.json",
"clean": "node scripts/clean.mjs",
"build": "npm run clean && tsc -p tsconfig.json",
"bundle:gateway": "node scripts/bundle-gateway.mjs",
"prepack": "npm run build && npm run bundle:gateway",
"test": "npm run build && node --test tests/*.test.mjs",
"test:package": "node scripts/test-package.mjs",
"start": "node dist/cli.js",
"dev": "tsx src/cli.ts"
},
"engines": {
"node": ">=20"
},
"dependencies": {
"@bankofai/x402-core": "1.0.0",
"@bankofai/x402-evm": "1.0.0",
"@bankofai/x402-gateway": "^1.0.0",
"@bankofai/x402-tron": "1.0.0",
"@bankofai/x402-core": "1.0.1",
"@bankofai/x402-evm": "1.0.1",
"@bankofai/x402-gateway": "1.0.1",
"@bankofai/x402-tron": "1.0.1",
"tronweb": "6.4.0",
"viem": "^2.55.0",
"yaml": "^2.8.2"
"viem": "^2.55.0"
},
"devDependencies": {
"@types/node": "^24.10.1",
"tsx": "^4.20.6",
"typescript": "^5.9.3"
},
"overrides": {
"ws": "8.21.0"
}
}
8 changes: 4 additions & 4 deletions scripts/bundle-gateway.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@ const require = createRequire(import.meta.url);

function gatewayPackageDist() {
try {
return path.dirname(require.resolve("@bankofai/x402-gateway/dist/cli.js"));
return path.join(path.dirname(require.resolve("@bankofai/x402-gateway/package.json")), "dist");
} catch {
return undefined;
}
}

const source = process.env.X402_GATEWAY_DIST
? path.resolve(process.env.X402_GATEWAY_DIST)
: gatewayPackageDist() ?? path.resolve(root, "..", "x402-gateway", "dist");
: gatewayPackageDist();
const target = path.join(root, "dist", "gateway");

if (!fs.existsSync(path.join(source, "cli.js"))) {
throw new Error(`gateway dist not found at ${source}; install @bankofai/x402-gateway, run npm run build in x402-gateway, or set X402_GATEWAY_DIST`);
if (!source || !fs.existsSync(path.join(source, "cli.js"))) {
throw new Error("gateway dist not found in @bankofai/x402-gateway; install dependencies or explicitly set X402_GATEWAY_DIST for development");
}

fs.rmSync(target, { recursive: true, force: true });
Expand Down
Loading
Loading