Release 0.1.0 — first stable#1
Merged
Merged
Conversation
- Import EvmClientSigner and TronClientSigner from correct module path (bankofai.x402.signers.client instead of bankofai.x402.signers) - Fix EVM signer creation from private key using eth_account.Account - Fix TRON signer creation from private key using tronpy.hdwallet - Properly initialize signer addresses after creation This enables both agent-wallet and env-var wallet modes to work correctly. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add comprehensive documentation and AI-friendly project structure: **New Directories:** - .claude/ — AI development guidance and automation - specs/ — Protocol and design specifications **AI Structure (.claude/):** - CLAUDE.md — Project overview and conventions - rules/python.md — Python coding guidelines - smoke-test.sh — Automated smoke test suite **Specifications (specs/):** - README.md — Documentation guide - server.md — Server command design (architecture, endpoints, flow) - client.md — Client command design (architecture, flow, signers) - smoke-tests.md — Test specification (6 tests, all passing) **Benefits:** 1. Enables Claude and other AI agents to contribute safely 2. Documents design decisions before implementation 3. Provides testing specification and coverage analysis 4. Follows x402 project conventions for consistency 5. Separates concerns: how to build vs. what we're building **Test Coverage:** ✓ Server startup ✓ /health endpoint ✓ /.well-known/x402 configuration ✓ /pay GET (402 challenge) ✓ Signer initialization (EVM + TRON) ✓ Output formatting Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ield names - Rename binary from x402-tools to x402-cli - Rename commands: server → serve, client → pay - Add new roundtrip command for one-shot testing - Fix field naming: --decimal → --rawAmount, --max-decimal → --max-rawAmount - Update all documentation and specs to reflect new names and field conventions - Support daemon and foreground modes for serve command - Update smoke test script with new command names and field names Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Update x402-tools references to x402-cli - Fix --rawAmounts to --decimals where appropriate - Update command examples in debug section
- Replace non-existent key_to_address with eth_keys.PrivateKey - Works for TRON address derivation from private key - Update error messages to use x402-cli instead of x402-tools
- Allow overriding facilitator URL via environment variable - Default to https://facilitator.bankofai.io - Enables testing with different facilitators
- Initialize ExactGasFreeClientMechanism with required clients kwarg - Add LocalTronWallet/LocalEvmWallet for proper EIP-712/TIP-712 signing - Forward 402 extensions (paymentPermitContext) to create_payment_payload - Convert EVM hex to TRON Base58 before GasFree API calls - Bump HTTP client timeout from 10s to 60s for facilitator settlement - Bump version to 0.1.0-beta.5 Verified on-chain: - TRON Nile (exact_gasfree) - BSC Testnet (exact_permit)
…rences - beta.5 imports fastapi/uvicorn/eth-account/eth-keys but did not declare them in pyproject.toml, so a fresh `pip install` fails at import. - Replace remaining `x402-tools` references in README/FEATURES/specs with `x402-cli`; swap deprecated --max-decimal for --max-rawAmount. - Bump to 0.1.0-beta.6.
beta.5 and beta.6 were broken on fresh installs: - httpx 1.0.dev3 removed AsyncClient — pin to 0.x stable - eth-account 0.14.0b1 has API changes — pin to 0.13 - web3 needed for EVM allowance checks - tronpy needed for TRON balance reads Verified locally (`pip install dist/*.whl` in clean venv): - 5/5 smoke tests - TRON Nile roundtrip + serve/pay - BSC Testnet roundtrip
rawAmount = amount × 10^decimals — earlier betas had this backwards. - --amount is now human-readable (e.g. 1.25) - --rawAmount is now smallest-unit integer (e.g. 1250000) - --max-amount and --max-rawAmount mirror the same split - JSON output fields amount/rawAmount follow new convention - --max-rawAmount actually wired up (was a no-op before) Verified locally on 0.1.0b9 wheel in clean venv: - 5/5 smoke tests - TRON Nile roundtrip with --amount 0.0001 → tx 0cf5a907... - TRON Nile roundtrip with --rawAmount 100 → tx 54dfd585... - TRON Nile serve+pay with --max-amount 0.001 → tx 0d3a66cc... - BSC roundtrip with --rawAmount 100000000000000 → tx 4c77ab52... - --max-amount 0.00005 correctly rejects 0.0001 USDT payment - --max-rawAmount 50 correctly rejects 100-unit payment - /.well-known/x402 returns rawAmount=1250000, amount=1.25
…let only) --token was a dead flag in pay: cli.py parsed it, threaded it to cmd_client, but the filter dict passed to select_payment_requirements contained only network+scheme. The SDK's selector also has no token key, so the CLI now filters candidates itself by symbol (case-insensitive) via TokenRegistry.find_by_address before delegating. --token foo now errors out instead of silently picking whatever the server offered. Wallet flow is consolidated onto bankofai-agent-wallet: - Removed --wallet flag from serve/pay/roundtrip - Removed LocalTronWallet/LocalEvmWallet/read_private_key from wallet.py - agent-wallet itself resolves: encrypted ~/.agent-wallet store first, then env vars (TRON_PRIVATE_KEY, AGENT_WALLET_PRIVATE_KEY, mnemonic) - If the local store is broken, fall back to agent-wallet's EnvWalletProvider directly (still inside agent-wallet, not LocalWallet) - Added bankofai-agent-wallet>=2.4 as a direct dep - Removed direct eth-account/eth-keys deps (SDK pulls them in) README gains a 'Wallet — agent-wallet' section explaining one-time setup. Verified locally on 0.1.0b10 wheel in clean venv: - 5/5 smoke tests - --token foo rejected: 'No payment options match --token foo' - TRON Nile (--token USDT) → tx 485e057f... - BSC Testnet → tx 80b2b1f1...
…hain test Single doc that walks a human through three end-to-end flows on real testnets: A. TRON Nile + exact_gasfree (no TRX on main wallet) B. TRON Nile + exact_permit (TRX gas + USDT on main wallet) C. BSC Testnet + exact_permit Includes: - AGENT_WALLET_DIR isolation pattern so users don't have to nuke their existing ~/.agent-wallet/ - Pre-flight balance scripts (tronpy + web3) for both chains - Tronscan/BscScan URLs for verification - Note that Nile USDT does support TIP-2612 permit (default-to-GasFree is conservative for mainnet stable-coins) - One-page quick-reference card at the end - Troubleshooting table covering the actual errors users hit (master password prompt, GasFree balance, rate limits, port-in-use, etc.) README.md gains a one-line pointer to the guide.
Help text was previously a vague 'e.g. tron:nile, eip155:97' that left users guessing what was actually supported. Now lists all five CAIP-2 network IDs and all four registry token symbols across serve/pay/roundtrip. For 'pay --network' / 'pay --token' (filters, not server config), help also says 'omit to accept any …' so the filter semantics are explicit.
The Python module name still carried the old project name (x402_tools) even though the package on PyPI, the CLI binary, and the docs were all already x402-cli. This was confusing in stack traces, in import paths, and in subprocess invocations like 'python -m bankofai.x402_tools.cli' inside the roundtrip command. Done in one pass: - git mv src/bankofai/x402_tools src/bankofai/x402_cli - pyproject.toml entry point: bankofai.x402_cli.cli:main - All 'from bankofai.x402_tools.X' imports updated (cli, server_cmd, client_cmd, wallet, schemes, output, tests). - subprocess.Popen call in roundtrip uses '-m bankofai.x402_cli.cli' - Docstrings in schemes.py / output.py: 'for x402-cli' - Docs (.claude/CLAUDE.md, smoke-test.sh, CONTRIBUTING.md, specs/README.md, manual-test-guide.md, .github/workflows/test.yml) updated. - CHANGELOG.md left as-is (the historical entry already documents the earlier x402-tools → x402-cli renaming). Verified: pytest 11/11 pass; live roundtrip on TRON Nile + exact_permit settled successfully (tx e9e7d8972cabdbd2f54ccc2829002ec35d268c21176e85126933e4747bfd0843).
Slipped in via 'git add -A' on the previous commit (ce8b360). Pure macOS Finder metadata, no code or config inside it.
…s table Wallet: - Drop the multi-step setup walkthrough (env vars, agent-wallet start / list / use, single-key-for-both-chains explainer). The detail belonged in agent-wallet's own getting-started doc, not in this README. - Keep two sentences explaining what the dependency is and the absence of a --wallet flag; link out to BofAI/agent-wallet getting-started. Design: - Remove. The 'we use SDK X402Server instead of reimplementing' note was about internal architecture, not user-facing behavior. - Pull the only useful bit (per-network default scheme rationale) into a new compact 'Schemes' table that also covers BSC/EVM, not just TRON. Reading flow is now: Install → Wallet (link out) → Amounts → Quick start → Schemes → Env vars → Development. Net delta ~30 lines shorter.
A user reported on a fresh `pip install bankofai-x402-cli==0.1.0b10`:
ImportError: cannot import name 'TokenRegistry' from 'bankofai.x402'
(...) Did you mean: 'AssetRegistry'?
Root cause: their environment had a newer `bankofai-x402` already
installed (anaconda3 base), and the SDK had renamed the registry from
`TokenRegistry` to `AssetRegistry`. Our pyproject pin was the loose
`bankofai-x402>=0.5.9`, so pip kept their existing version and we
mismatched the symbol.
Per user direction ("sdk 不要改, 就改 cli"), the fix is local to
this package — we do not touch the SDK. At each call site:
try:
from bankofai.x402 import TokenRegistry
except ImportError:
from bankofai.x402 import AssetRegistry as TokenRegistry
Both branches are real installable states today; whichever wins, the
rest of the file keeps using the `TokenRegistry` name unchanged.
Bumped to 0.1.0-beta.11 and verified in a clean venv:
- pip install picks up the new wheel
- x402-cli --help / --version / pytest 11/11 all green
- On an SDK that exposes only `TokenRegistry` (PyPI 0.5.8/0.5.9):
try succeeds, no fallback needed
- On an SDK that exposes only `AssetRegistry` (the user's env):
try fails, except branch resolves the alias
PyPI: https://pypi.org/project/bankofai-x402-cli/0.1.0b11/
…ADME Two things: 1) Cap every dependency upper bound. b10's TokenRegistry breakage was caused by writing 'bankofai-x402>=0.5.9' (no upper limit) and then having pip silently accept a preinstalled v2-dev SDK that had renamed the symbol. Same risk existed for every other dep that wasn't bounded. Now: bankofai-x402>=0.5.9,<0.6 bankofai-agent-wallet>=2.4,<3 pydantic>=2.0,<3 fastapi>=0.110,<1.0 uvicorn>=0.27,<1.0 click>=8.1.0,<10 (httpx, web3, tronpy already had caps) A future major version of any of these now has to be opted into via a new cli release, not auto-resolved into a user's environment. 2) README rewritten for end users. Was a contributor-style doc with 'Design', 'Environment variables', 'Development' sections explaining internals like 'we use the SDK's X402Server'. New flow targets someone who wants to send a payment from the command line: install -> wallet (one cmd, link out) -> what each cmd is for -> copy-paste GasFree TRON-mainnet transfer -> other-network templates -> amount units -> common errors Verified end-to-end on real testnets with the b12 wheel from a clean venv: TRON Nile exact_permit: 887c65b63a81009ca7ccc1545575189bf4b604174205187638189b3d61e1cdcb TRON Nile exact_gasfree: 524d01f8ac1451bfd7d0fd835922c7930a4714749efe28471bd6a10dc064375b BSC Testnet exact_permit: 90bd524e7cda5a9587ab7212e3a9efea5e0725fe4d249e53b4a460f89bdd6e4e PyPI: https://pypi.org/project/bankofai-x402-cli/0.1.0b12/
The b12 README rewrite was for end users (correct), but I wrote it in mixed CN/EN — that doesn't fit the project's docs convention (everything else under docs/ and specs/ is English) and makes the PyPI project page unreadable for non-CN readers. Verbatim same structure and content, just translated. No code changes.
The b12 rewrite changed the README's audience from contributor to end user (correct), but I wrote it in mixed CN/EN. Other docs in the repo (specs/, docs/, FEATURES.md, TROUBLESHOOTING.md, CONTRIBUTING.md) are all English, and the PyPI project page renders the README directly — non-CN readers saw a half-foreign README. Pure docs change; same structure, same examples, no behavior change. b12's three on-chain tests still cover runtime.
The SDK's tron_client logs a WARNING on every invocation when
TRON_GRID_API_KEY is unset:
[bankofai.x402.utils.tron_client] WARNING: TRON_GRID_API_KEY is
not set. Mainnet RPC calls will be routed to https://hptg.bankofai.io.
Set TRON_GRID_API_KEY to use TronGrid.
For cli users, falling back to the BankofAI-hosted gateway is the
documented default, not a warning condition. So setup_logging() now
sets that specific logger to ERROR level. Users who want TronGrid
still set TRON_GRID_API_KEY exactly as before, no behavior change.
Verified: serve --network tron:mainnet on a clean b14 venv produces
no TRON_GRID line in its output.
Three classes of improvement, no behavior change for the happy path:
A. Dependencies
- bankofai-x402[evm,tron]>=0.5.9,<0.6 (was bankofai-x402>=0.5.9,<0.6
plus separate web3 and tronpy entries). cli source never imports
web3 or tronpy directly — they were redundant top-level deps. Now
pulled via the SDK's own [evm,tron] extras so the SDK owns those
ranges. Resolved versions identical to b14.
B. UX
- x402-cli with no args prints --help instead of an empty error.
- -h is now an alias for --help.
- Top-level docstring lists the three commands as 'common flows',
a one-line first-time setup hint, and a copy-paste GasFree
example so users don't have to leave the terminal.
- --scheme help text lists every supported value with a one-phrase
explanation and notes the auto-pick fallback.
C. Friendly errors
- New module bankofai.x402_cli.errors with classify(err) → (code,
message, hint). The hint line tells the user what to do, instead
of leaving them alone with an SDK stack trace.
- Wired into client_cmd.py and server_cmd.py outer except blocks.
- Also wired into the post-retry !=200 path that previously emitted
errors as 'successful' envelopes.
- Mapped: WALLET_NOT_CONFIGURED, WALLET_CONFIG_CORRUPT,
INSUFFICIENT_GASFREE_BALANCE, GASFREE_NOT_ACTIVATED,
INSUFFICIENT_GAS, RATE_LIMITED, DEADLINE_TOO_SOON,
PERMIT_REVERTED, SDK_API_DRIFT.
D. Doc fix
- specs/smoke-tests.md was still using the long-removed --decimal
flag. Updated to --amount.
Verified end-to-end on b15 wheel from a clean venv:
TRON Nile exact_permit: 23ee1731547dc4fadc06f5d26d3e3df22c4d39799ae80d887dfa2fee0c82c42a
TRON Nile exact_gasfree: 292bc6e17353dc976eac5925f1cd9b88a1b6edeb293c963e36fb67e01f2198ee
BSC Testnet exact_permit: 43ed0a7d3a77baf30b559d39926fc63fd657eb4389553c1884f2a86edb5a4a72
PyPI: https://pypi.org/project/bankofai-x402-cli/0.1.0b15/
Twelve unused imports across cli.py / server_cmd.py / tests/test_output.py that ruff (F401) flagged in the GitHub Actions test job. All auto-fixable; no behavior change. Re-running pytest 11/11 still green; cli --version / serve --help still work; runtime tests on a clean venv still pass.
added 3 commits
May 3, 2026 02:58
CI's mypy strict-mode job was producing 26 errors:
22 × 'Skipping analyzing bankofai.x402.*: missing py.typed marker'
3 × var-annotated / type-arg / unused-ignore in cli source
Fixed:
- Added a [[tool.mypy.overrides]] for bankofai.x402.* with
ignore_missing_imports = true. We lose type checking against the
SDK (which we'd lose anyway without their py.typed marker), but
the strict-mode job is now actionable for cli-only issues.
- Replaced two '# type: ignore[no-redef]' (now redundant under the
override) with '# noqa: F401' to keep ruff happy on the unused
AssetRegistry alias.
- Annotated networks_schemes: dict[str, set[str]].
- Annotated FastAPI route handlers' return types: dict[str, bool] /
dict[str, str] instead of bare dict.
Local: ruff + mypy + pytest all green.
Removed it in 0459863 because local mypy reported 'unused section(s): module = [agent_wallet.*]'. But that's a benign note (mypy exit code 0), not an error. On CI, wallet.py:24 'from agent_wallet import EnvWalletProvider' still triggered import-untyped because agent_wallet has no py.typed marker. Re-adding both 'agent_wallet' and 'agent_wallet.*' to the override list. Local mypy now reports an unused-section note for one of them (whichever isn't matched), which is fine — it's a note, not an error, and exit code is 0 in both environments.
CI runs: pytest tests/ -v --cov=src/bankofai/x402_cli --cov-report=xml But pytest-cov was missing from [project.optional-dependencies] dev, so on a fresh CI venv pytest reports 'unrecognized arguments: --cov...' and exits 4. Adding pytest-cov>=4.0 fixes the CI step. Local 'pytest --cov ...' now also works (writes coverage.xml; reports 'No data was collected' since our 11 unit tests don't import most of cli source — that's expected and harmless).
…approval)
QA hit a hard failure when running:
x402-cli pay --network tron:mainnet --scheme exact_permit
with an agent-wallet privy wallet that hadn't pre-approved the
PaymentPermit contract. The cli's allowance check trips, ensure_allowance
builds an approval txn, hands it to privy — privy rejects:
SigningError: Payload must include raw_data_hex for TRON signing
Root cause turned out to be a long-standing integration gap, not a new
break:
- tronpy 0.4–0.6 (verified all on-PyPI versions) do NOT expose
raw_data_hex on the Transaction object — neither in to_json(), as
an attribute, nor as a method.
- SDK's TronClientSigner._build_unsigned_tx_payload tries those three
sources, fails on all three, and ships raw_data_hex=None to the
wallet adapter.
- agent-wallet raw_secret/local_secure adapters tolerate None — they
sign txID directly. Every internal cli test used those, so this
never showed up.
- agent-wallet 2.4's privy adapter requires non-empty raw_data_hex
(Privy's hosted signer needs the full payload for compliance review).
QA was the first to run cli pay through privy.
Fix is purely cli-side: a monkey-patch installed at cli import time
that wraps SDK's _build_unsigned_tx_payload. When raw_data_hex is
missing, it serializes txn._raw_data via tronpy's own protobuf helper
(tronpy.proto._raw_data_to_protobuf + tron_pb2.Transaction(raw_data=...).
SerializeToString()) — the same path tronpy itself uses for offline
txid calculation.
Verified bit-for-bit: sha256(our_raw_data_hex) == tronpy.txn.txid for
every test input. 6 new unit tests in tests/test_tron_patch.py cover
serialization correctness, idempotency, forward-compat (no overwrite if
SDK ever starts populating raw_data_hex itself), and the full SDK
patched call.
Live verified: TRON Nile exact_permit roundtrip on a fresh b16 install
settled successfully (tx f2c5ed31a5bb07ae7de4d35094b589f7197de6ccb444014eadcd6914e03e6e33),
proving raw_secret path still works and the patch isn't a regression.
The privy path can only be verified end-to-end with a real privy wallet
on QA's side; the unit tests prove the patched payload now satisfies
privy's strict isinstance(raw_data_hex, str) check.
Adds protobuf>=4.21,<7 as a direct dep (tronpy.proto's import gate).
This patch becomes a no-op the day SDK starts emitting raw_data_hex
natively, so it's not a long-term liability.
Slipped in via 'git add -A' on f9d57a7. Pure test-run output, not source.
QA on b16 hit a new failure once the raw_data_hex patch unblocked the approval signing path: Contract validate error : account [TT3mqNohVNyzMr6H2SBHWCWzU7bXPaAGUX] does not exist This is TRON's account activation rule, not a cli bug. Every TRON address must have received any inflow (TRX / TRC10 / TRC20) at least once before it can be the owner_address of a contract call. fresh privy-derived addresses haven't, so the node validator refuses the approval broadcast. Cli now classifies this error as TRON_ACCOUNT_NOT_ACTIVATED with a clear hint: send ~1 TRX once to bootstrap, or use --scheme exact_gasfree which routes through the GasFree relayer and doesn't need main-wallet activation. 30 unit tests in tests/test_errors.py lock down all the classifier rules.
…aries
Two cosmetic UX polishes spotted during a help-output review. No
behavior change, no version bump (will roll into the next real release).
1. Top-level 'Commands' list was truncating each command's first
docstring sentence at ~50 chars (Click's default for the summary
line):
pay Pay an x402-protected URL when the server returns 402...
roundtrip One-shot roundtrip: start server, pay it, shut down (for...
Each command's docstring now starts with a short title sentence (full
sentence shows in the Commands list) followed by a longer paragraph
that's only seen in 'x402-cli <cmd> --help'. Resulting Commands list:
pay Pay an x402-protected URL.
roundtrip One-shot transfer: serve → pay → tear down.
serve Run a local x402 paywall endpoint.
2. 'x402-cli pay --help --scheme' was a one-liner ('Require a specific
x402 scheme') while 'x402-cli serve --help --scheme' listed every
supported value with a one-phrase explanation. Inconsistent. pay's
--scheme help is now the same detailed form, just rephrased in 'filter'
semantics ('Omit to accept any scheme the server advertises').
Consolidates everything from 0.1.0-beta.5 through 0.1.0-beta.17 into the first stable release. Headline features: - Three commands: pay <url>, serve, roundtrip — each with full --help including supported networks, tokens, schemes, and worked examples. - Wallets fully delegated to bankofai-agent-wallet (raw_secret / local_secure / privy / mnemonic). One private key derives both EVM and TRON addresses. - Auto-pick scheme per (network, token), override with --scheme. - 10-rule friendly error classifier (WALLET_NOT_CONFIGURED, TRON_ACCOUNT_NOT_ACTIVATED, INSUFFICIENT_GASFREE_BALANCE, ... ), each with a one-line resolution hint. - _tron_patch.py compat shim: fills in raw_data_hex on TRON unsigned txs that all released tronpy versions leave empty, so privy-style wallets that strictly require it can sign approvals. Bit-correct vs tronpy's own offline txid calculation, idempotent, becomes a no-op once SDK emits raw_data_hex natively. - TokenRegistry/AssetRegistry import-drift tolerance. - Pinned dependency upper bounds (no silent major bumps). - English-only user-facing README + docs/manual-test-guide.md with three full hands-on walkthroughs ending in real on-chain receipts. Verified on PyPI install: - TRON Nile permit / gasfree / mainnet permit (3 distinct QA TXs) - BSC Testnet permit - All 30 unit tests pass on Python 3.11 and 3.12 in CI. Known limitations (not cli bugs): - Fresh TRON addresses need activation (cli now surfaces this clearly). - BSC mainnet USDC does not implement transferWithAuthorization or permit — (token, scheme) compatibility is a facilitator concern, not cli's.
added 2 commits
May 8, 2026 10:38
mypy 1.x in CI flagged 5 issues introduced when _tron_patch.py landed: src/bankofai/x402_cli/_tron_patch.py:54: Missing type arguments for generic type "dict" src/bankofai/x402_cli/_tron_patch.py:61: import-untyped: tronpy.proto.transaction src/bankofai/x402_cli/_tron_patch.py:62: import-untyped: tronpy.proto src/bankofai/x402_cli/_tron_patch.py:66: Returning Any from function declared to return "str | None" src/bankofai/x402_cli/_tron_patch.py:105: Unused "type: ignore" comment Fixes: - raw_data parameter typed as dict[str, Any] (was bare 'dict'). - Both tronpy.proto.* imports tagged 'type: ignore[import-untyped]' because tronpy ships without a py.typed marker. Stable across 0.6.x. - The serializer's hex() result coerced through a typed local 'result: str' before return, eliminating the 'returning Any' diagnostic. - Removed the now-unused 'type: ignore[attr-defined]' tag on the _x402_cli_raw_data_hex_patched marker assignment (mypy 1.x learned to infer this on bare attr writes). Local verification: mypy src/bankofai/x402_cli → Success: no issues found in 9 source files pytest -q tests/ → 30 passed Behavior unchanged. Patch shim still byte-equal to tronpy's own offline txid calculation (covered by tests/test_tron_patch.py).
…match 0.1.0
Spec files had drifted while the cli evolved code-first through b11..b17.
This commit aligns them with the actual 0.1.0 surface — no behavior or
source changes.
server.md:
- --daemon row clarified as a reserved flag (currently no-op; the
server still runs in the foreground). Real daemonization is not
implemented yet.
- /health endpoint response corrected: it returns just {"ok": true},
not the wrapped envelope the doc previously claimed. Added a note
explaining why /health is intentionally tiny (used by roundtrip's
_wait_for_server_ready before any chain handshakes).
- New 'Compat shim — _tron_patch.py' section describing the
raw_data_hex monkey-patch layer added in b16. Includes deletion
criteria so future maintainers know when to remove it.
client.md:
- 'Register Mechanisms' code example now passes the required
clients={network: GasFreeAPIClient(...)} kwarg to
ExactGasFreeClientMechanism (added in b11).
- 'Signer Resolution' rewritten: cli has no in-tree wallet plumbing,
everything goes through agent-wallet. Removed the misleading
'or TRON_PRIVATE_KEY' fallback line.
- 'Error Codes' table replaced: was a generic 6-row list (IO_ERROR,
VALIDATION_ERROR, ...); now reflects the 10-rule friendly classifier
in errors.py (WALLET_NOT_CONFIGURED, TRON_ACCOUNT_NOT_ACTIVATED,
INSUFFICIENT_GASFREE_BALANCE, ...) with one-line resolution hints
each, plus pointers to errors.py + tests/test_errors.py.
- Failure example now shows the structured triplet (code, message,
hint) actually emitted in --json.
smoke-tests.md:
- Status timestamp + version updated to 2026-05-08 / 0.1.0.
- Added a 'Two complementary layers' overview at the top: pytest unit
layer (30 cases across 4 files) is what CI runs every PR; the shell
smoke is what this doc describes.
- /health expected-response example corrected (matches the real body).
- --daemon row in 'NOT Tested' updated: flag exists but cmd_server
ignores it; planned for v0.2.
specs/README.md:
- 'Updating These Specs' rewritten to acknowledge the project is
code-first. CHANGELOG is canonical; specs are architecture
references refreshed at version boundaries. Includes explicit
'edit a spec file when ...' / 'don't bother when ...' lists so
contributors don't waste time on spec round-trips for routine
flag-tweak commits.
Will-Guan
approved these changes
May 8, 2026
added 2 commits
May 8, 2026 14:41
…act_permit
The original default was set when exact_permit settlement was unproven
on TRON mainnet (the in-tree comment cited 'permitTransferFrom may
revert during broadcast'). That was b15-and-earlier territory.
Two things changed since:
1. b16's _tron_patch.py compat shim removed the only known
blocker for exact_permit on TRON (the empty-raw_data_hex issue
that broke the privy wallet adapter).
2. QA produced three independent on-chain mainnet receipts via
exact_permit on b16+:
- fd1c6678574f7d68454ad76c1ab2efaddaabbcbb61e5f123575619d8c662dba4
- 9ad3be693d42c6aed3ff732f2072b6ca26fc0d878dac1326058a44de8636f078
- 1383a0db66c46520fafb1ad98db7d7ce8a6b68ad0fb12131704ec78b7f1959a6
So exact_permit is now the better default for typical payers because:
- Settlement reaches the recipient in a single permitTransferFrom
on-chain — no relayer intermediary, no per-settlement transferFee,
no one-time activateFee on a derived custodial address.
- Fits the EVM mental model (the payer signs an EIP-2612-style
permit, gas is the payer's responsibility).
- QA-validated on mainnet through multiple wallet backends.
exact_gasfree remains a first-class option, registered as the SECOND
choice for every TRON network/token entry. Users who have USDT but
no TRX can still pass --scheme exact_gasfree to route through the
GasFree relayer exactly as before. The mechanism, helper API client
plumbing, and all docs for that path are unchanged.
Files touched:
- src/bankofai/x402_cli/schemes.py
Per-token list reordered: ['exact_permit', 'exact_gasfree']
across tron:mainnet / tron:nile / tron:shasta. Comment rewritten
to explain the new rationale + the opt-in fallback contract.
- tests/test_schemes.py
Two assertions flipped to expect exact_permit as default. New
test 'test_tron_keeps_gasfree_as_second_choice' locks in the
contract that gasfree must remain registered (regression guard).
Result: 31/31 pass (was 30; +1 new test).
- README.md
'Copy-paste' section header retitled from 'GasFree transfer'
to 'USDT transfer'. Output excerpt now shows scheme:
exact_permit. The 'Why is this GasFree' callout swapped for
'What just happened' (explains permit + transferFrom) plus a
'No TRX in your wallet?' tip pointing at --scheme exact_gasfree.
Network-template table footnote updated.
- docs/manual-test-guide.md
Section 3 'Pick a scheme' table marks exact_permit as default
and exact_gasfree as opt-in. Walkthrough A title gains
'(opt-in path)' + a top callout explaining when to use it
vs Walkthrough B; its roundtrip command now shows the
explicit --scheme exact_gasfree (since it's no longer the
default and would otherwise auto-pick permit). Walkthrough B
title gains '(DEFAULT)'. Note about Nile USDT permit support
updated to reflect the new cli-wide default. Quick-reference
card reordered: TRON permit shown first as the default,
exact_gasfree shown second with explicit --scheme.
- CHANGELOG.md
[0.1.0] 'Settlement schemes' bullet rewritten to spell out
the new default-vs-opt-in registry mapping.
No SDK / agent-wallet changes. The mechanism registration code in
client_cmd.py / server_cmd.py also untouched — the change is
purely in the auto-pick table.
…ment TRX)
Previous wording in README, manual-test-guide, schemes.py comment, and
CHANGELOG conflated the cli's one-time ensure_allowance step with the
per-payment cost. The cleaner mental model:
- permit = signed OFF-CHAIN, never costs gas
- permit + transferFrom settlement = broadcast by facilitator, *they*
pay TRX
- ensure_allowance approve = broadcast by payer, payer pays ~6 TRX
BUT this only happens on the very first payment for a given token
contract; subsequent payments skip this step entirely
So the user-friendly framing is: 'facilitator pays per-payment gas;
the only TRX you spend is a one-time approve when you first use a
token from a fresh wallet.' That's the message now everywhere.
Files updated:
README.md
- 'What just happened?' callout rewritten so the dominant
message is 'You pay no TRX per payment.' The one-time approve
is now a tip in italics, not the headline.
- Templates table: TRON mainnet row says 'Facilitator pays
per-payment gas. One-time ~6 TRX approve...'. BSC row
similarly clarified.
docs/manual-test-guide.md
- Walkthrough B intro (5.0): now leads with the two-step flow
(off-chain permit + facilitator-broadcast settlement) and
labels the approve as a 'one-time exception'. No more
'Payer must hold TRX for gas' as an absolute claim.
- 5.1 balance prerequisites: TRX is now described as
'only required if this is the wallet's first payment',
not as a generic requirement.
- 5.4 expected on-chain effect: distinguishes the one-time
approve tx (where ~6 TRX comes from) from the actual
permit + transferFrom settlement (which does NOT draw
from the payer's wallet). Notes that from the second
payment onward TRX stays put.
src/bankofai/x402_cli/schemes.py
- TRON registry comment rewritten to describe the steady-state
gas model (facilitator pays per-payment) plus the one-time
approve caveat. Also makes the trade-off vs exact_gasfree
explicit (gasfree adds per-settlement fees, that's why
permit is the better default).
CHANGELOG.md
- [0.1.0] 'Settlement schemes' bullet expanded with the same
'facilitator pays per-payment, payer pays one-time approve'
framing.
No behavior change, no source changes. 31/31 tests still pass.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Release 0.1.0 — first stable
Consolidates everything from
0.1.0-beta.5through0.1.0-beta.17into the first stable release on PyPI.After merge, the user-facing install drops the
--preflag:pip install bankofai-x402-cli # → 0.1.0What you get
x402-cli pay <url>,x402-cli serve,x402-cli roundtrip. Each has a polished--helplisting supported networks, tokens, schemes, plus worked examples in the top-level--help.bankofai-agent-wallet(raw_secret / local_secure / privy / mnemonic). One private key derives both EVM and TRON addresses; no--walletflag.(network, token)registry; override with--scheme exact_gasfree | exact_permit | exact.tron:mainnet/tron:nile/tron:shasta) and EVM (eip155:56/eip155:97).--asset+--decimalsfor any other ERC-20.WALLET_NOT_CONFIGURED,TRON_ACCOUNT_NOT_ACTIVATED,INSUFFICIENT_GASFREE_BALANCE,INSUFFICIENT_GAS,RATE_LIMITED,PERMIT_REVERTED), each with a one-line resolution hint.raw_data_hexcompat shim (_tron_patch.py) — fills in the field that all released tronpy versions (0.4–0.6) leave empty, so privy-style wallets that strictly require it can sign approvals. Bit-correct vs tronpy's own offline txid calculation. Idempotent and forward-compatible.bankofai-x402[evm,tron]>=0.5.9,<0.6,bankofai-agent-wallet>=2.4,<3, plus caps on click/httpx/pydantic/fastapi/uvicorn. A future major-version release of any dependency cannot silently land in user environments.docs/manual-test-guide.mdwith three full hands-on walkthroughs (TRON GasFree, TRON permit, BSC permit) ending in real on-chain receipts.Verification
test (3.11)PASS,test (3.12)PASS, all 30 unit tests).pip install bankofai-x402-clifrom a clean venv pulls 3 BofAI packages + full transitive stack, nopip checkissues.[0.1.0].exact_permitafter b16's raw_data_hex patch landed (3 mainnet TXs).Post-merge release plan
git checkout main && git pullpython3 -m buildtwine upload dist/bankofai_x402_cli-0.1.0*(no--pre)git tag -a v0.1.0 -m "release: 0.1.0 — first stable"+git push --tagsKnown limitations (not cli bugs, documented)
TRON_ACCOUNT_NOT_ACTIVATEDwith a one-line fix hint.0x8AC76a51…does not implementtransferWithAuthorizationorpermit(verified by bytecode scan).--scheme exactagainst this token reverts at facilitator's settle step. (token, scheme) compatibility is a facilitator concern.