@trucore/atf
v1.4.2
Published
Agent Transaction Firewall CLI — simulate, verify, and audit on-chain transactions trustlessly.
Maintainers
Readme
@trucore/atf
Agent Transaction Firewall CLI — simulate, verify, and execute on-chain transactions trustlessly.
One-Liner
npx @trucore/[email protected] simulate --preset swap_small --verify --prettyThat's it. No install, no config, no API key required.
What It Does
- Sends a deterministic preset transaction to the ATF public API
- Returns allowed or denied with a reason and receipt hash
- Verifies content_hash integrity client-side — don't trust TruCore, verify
- Executes real on-chain Solana swaps (Jupiter DEX) gated by ATF policy
- Profile-based config — switch between mainnet/devnet, Helius RPC, keypairs
- Transaction tooling — sign, send, confirm, and verify receipts offline
Install (optional)
npm install -g @trucore/[email protected]Or use directly with npx (always pin the version):
npx @trucore/[email protected] simulate --preset swap_smallQuickstart: Doctor (Dev Environment Check)
npx @trucore/[email protected] doctor --prettyQuickstart: Devnet Burner
npx @trucore/[email protected] swap --burner --devnet --in SOL --out USDC --amount-in 0.01 --execute --yes --confirmQuickstart: Helius Profile Setup
npx @trucore/[email protected] config init --yes
npx @trucore/[email protected] profile create devnet
npx @trucore/[email protected] profile use devnet
npx @trucore/[email protected] config set solana_cluster devnet
npx @trucore/[email protected] config set rpc_url helius
export HELIUS_API_KEY=your_key_here
npx @trucore/[email protected] rpc pingCommands
health
Check API health and round-trip latency.
npx @trucore/[email protected] health
npx @trucore/[email protected] health --pretty
npx @trucore/[email protected] health --base-url http://localhost:3000Output shape:
{ "ok": true, "base_url": "https://api.trucore.xyz", "latency_ms": 42, "response": { "status": "ok" } }simulate
Run a transaction simulation against the ATF API.
npx @trucore/[email protected] simulate --preset swap_small --verify
npx @trucore/[email protected] simulate --preset swap_too_large --pretty
npx @trucore/[email protected] simulate --json '{"chain_id":1,"value_eth":"0.5"}' --base-url http://localhost:3000Output shape:
{ "ok": true, "base_url": "https://api.trucore.xyz", "preset": "swap_small", "verified": true, "response": { "decision": "allowed", "reasons": [], "receipt_hash": "a1b2...64hex", "content_hash": "c3d4...64hex" } }approve
Approve a pending intent (requires authentication).
npx @trucore/[email protected] approve --intent abc123 --token mytoken
npx @trucore/[email protected] approve --intent abc123 --token mytoken --prettyOutput shape:
{ "ok": true, "base_url": "https://api.trucore.xyz", "intent": "abc123", "response": { "intent_id": "abc123", "status": "approved" } }version
Show rich version information (CLI version, Node version, build info).
npx @trucore/[email protected] version
npx @trucore/[email protected] version --prettyOutput shape:
{ "ok": true, "cli_version": "1.3.1", "node_version": "v22.0.0", "platform": "linux", "arch": "x64", "default_base_url": "https://api.trucore.xyz", "build_commit": "abc1234", "build_date": "2025-01-01T00:00:00Z" }swap
Execute a real on-chain Solana swap (Jupiter DEX) gated by ATF policy evaluation.
⚠ WARNING: This command signs transactions with your local keypair. Use a burner wallet for demos. Start with a tiny amount (e.g. 0.001 SOL).
Dry run (no funds move):
npx @trucore/[email protected] swap \
--in SOL --out USDC \
--amount-in 0.001 \
--slippage-bps 50 \
--keypair ~/.config/solana/id.json \
--dry-runReal transaction (mainnet):
npx @trucore/[email protected] swap \
--in SOL --out USDC \
--amount-in 0.001 \
--slippage-bps 50 \
--keypair ~/.config/solana/id.json \
--rpc https://api.mainnet-beta.solana.com \
--confirmDevnet burner one-liner (generates ephemeral keypair, no files needed):
npx @trucore/[email protected] swap \
--burner --devnet \
--in SOL --out USDC \
--amount-in 0.01 \
--slippage-bps 100 \
--execute --yes --confirm⚠️ burner is devnet-only. The
--burnerflag auto-generates an ephemeral keypair in memory. It forces devnet mode and will refuse any mainnet RPC. Do not use for real funds. Devnet swaps use a SOL transfer fallback since Jupiter does not support devnet.
Output shape (success):
{
"ok": true,
"request_id": "abc123...",
"base_url": "https://api.trucore.xyz",
"preset": null,
"verified": true,
"response": {
"decision": "allowed",
"receipt_hash": "a1b2...64hex",
"content_hash": "c3d4...64hex"
},
"execution": {
"rpc": "https://api.mainnet-beta.solana.com",
"signature": "5SiGA...",
"explorer_url": "https://solscan.io/tx/5SiGA...",
"jupiter": { "inAmount": "1000000", "outAmount": "150000", "priceImpactPct": "0.01" },
"confirmation_status": "confirmed",
"sent_at": "2026-02-28T12:00:00.000Z"
}
}If denied: exits 1 with ok: false, no on-chain transaction executed.
config
Manage CLI configuration (init, set, get, list).
atf config init --yes # Create default config
atf config set solana_cluster devnet
atf config set rpc_url helius # Use Helius RPC (requires HELIUS_API_KEY)
atf config set tx.max_retries 5
atf config get rpc_url
atf config list # Show merged effective config
atf config list --prettyprofile
Manage named configuration profiles.
atf profile list # List all profiles
atf profile create staging # Create new profile
atf profile use staging # Switch active profile
atf profile delete staging # Delete a profileUse --profile <name> on any command to override the active profile for that invocation.
secret
Manage sensitive credentials (stored in ~/.config/atf/secrets.json with 0600 permissions).
echo "my-helius-key" | atf secret set helius
atf secret list # Shows namespaces/profiles, never values
atf secret unset heliusSecrets are resolved with priority: environment variable > secrets store.
rpc ping
Check Solana RPC connectivity and latency.
atf rpc ping # Uses profile RPC or default
atf rpc ping --devnet # Ping devnet
atf rpc ping --rpc https://custom-rpc.example.com
atf rpc ping --prettyOutput shape:
{ "ok": true, "cluster": "mainnet-beta", "rpc_host": "mainnet.helius-rpc.com", "latency_ms": 85, "version": "2.2.1", "slot": 348123456 }tx sign
Offline-sign a base64-encoded Solana transaction.
atf tx sign --tx-base64 <base64> --keypair ~/.config/solana/id.json
atf tx sign --tx-file unsigned.bin --keypair ~/.config/solana/id.jsonOutput shape:
{ "ok": true, "signed_tx_base64": "..." }tx send
Sign, send, and optionally confirm a Solana transaction.
atf tx send --tx-base64 <base64> --keypair ~/.config/solana/id.json
atf tx send --tx-base64 <base64> --keypair ~/id.json --confirm --rpc heliusOutput shape:
{ "ok": true, "signature": "5SiGA...", "explorer_url": "https://solscan.io/tx/5SiGA...", "confirmation_status": "confirmed" }tx status
Poll the confirmation status of a transaction signature.
atf tx status --sig 5SiGA...
atf tx status --sig 5SiGA... --prettyOutput shape:
{ "ok": true, "signature": "5SiGA...", "status": "finalized", "slot": 348123456, "err": null }receipts verify
Verify ATF receipt hash integrity offline.
atf receipts verify --file receipt.json
cat receipt.json | atf receipts verify --stdin
atf receipts verify --file receipt.json --prettyOutput shape:
{ "ok": true, "content_hash_valid": true, "receipt_hash_valid": true, "file": "receipt.json" }whoami
Show current profile context, config, and CLI version.
atf whoami
atf whoami --pretty
atf whoami --profile stagingOutput shape:
{ "ok": true, "profile": "default", "atf_base_url": "https://api.trucore.xyz", "solana_cluster": "mainnet-beta", "rpc_host": "mainnet.helius-rpc.com", "commitment": "confirmed", "explorer": "solscan", "cli_version": "1.3.1" }ls
Alias for config list.
atf ls
atf ls --prettycompletion
Generate shell completion scripts.
atf completion bash >> ~/.bashrc
atf completion zsh >> ~/.zshrc
atf completion fish > ~/.config/fish/completions/atf.fish
atf completion powershell >> $PROFILEdoctor
Run a comprehensive dev environment health check — ATF API, RPC, config, keypair, and explorer.
npx @trucore/[email protected] doctor --pretty
npx @trucore/[email protected] doctor --profile devnet --pretty
npx @trucore/[email protected] doctor --rpc https://custom-rpc.example.com
npx @trucore/[email protected] doctor --verboseOutput shape (JSON, default):
{
"ok": true,
"summary": { "status": "ok", "passed": 5, "warned": 0, "failed": 0 },
"env": { "cli_version": "1.3.1", "node_version": "v22.0.0", "platform": "linux", "arch": "x64" },
"effective": { "profile": "default", "atf_base_url": "https://api.trucore.xyz", "solana_cluster": "mainnet" },
"checks": [
{ "name": "atf_health", "status": "pass", "latency_ms": 42, "details": { "http_status": 200 }, "actions": [] },
{ "name": "simulate_sanity", "status": "pass", "latency_ms": 55, "details": { "decision": "allowed" }, "actions": [] },
{ "name": "rpc_health", "status": "pass", "latency_ms": 30, "details": { "solana_version": "2.2.1" }, "actions": [] },
{ "name": "keypair", "status": "pass", "details": { "configured": true, "valid": true }, "actions": [] },
{ "name": "explorer_link", "status": "pass", "details": { "explorer": "solscan" }, "actions": [] }
]
}Exit codes:
| Code | Meaning | |------|---------| | 0 | All checks pass (or warn-only) | | 1 | User/actionable misconfiguration (missing Helius key, invalid config) | | 2 | Network/server failure (ATF API or RPC unreachable) |
Global Options
| Flag | Description | Default |
|------|-------------|---------|
| --base-url <url> | API base URL | https://api.trucore.xyz |
| --timeout-ms <ms> | Request timeout in milliseconds | 20000 |
| --format <fmt> | Output: json or pretty | json |
| --pretty | Shorthand for --format pretty | false |
| --no-color | Disable ANSI colors | false |
| --api-key <key> | API key (also: ATF_API_KEY env var) | — |
| --profile <name> | Use a named config profile | default |
Simulate Options
| Flag | Description | Default |
|------|-------------|---------|
| --preset <name> | Built-in preset: swap_small, swap_too_large, ttl_too_high | — |
| --json '<json>' | Raw JSON transaction body | — |
| --verify | Verify content_hash integrity | false |
| --quiet | Suppress non-essential output | false |
Approve Options
| Flag | Description | Default |
|------|-------------|---------|
| --intent <id> | Intent ID to approve (required) | — |
| --intent-id <id> | Alias for --intent (backward compat) | — |
| --token <bearer> | Bearer token for auth (also: ATF_API_KEY env var) | — |
Swap Options
| Flag | Description | Default |
|------|-------------|---------|
| --in <symbol\|mint> | Input token symbol or mint address | — |
| --out <symbol\|mint> | Output token symbol or mint address | — |
| --amount-in <number> | Amount of input token (human units, e.g. 0.001) | — |
| --slippage-bps <int> | Slippage tolerance in basis points | 50 |
| --keypair <path> | Path to Solana id.json keypair file | — |
| --rpc <url> | Solana RPC URL (or "helius" to auto-build) | https://api.mainnet-beta.solana.com |
| --dry-run | Simulate + quote only; do NOT sign or send | false |
| --confirm | Poll signature status until confirmed or timeout | false |
| --verify | Verify content_hash integrity | false |
| --burner | Generate ephemeral keypair (devnet only, never printed) | false |
| --devnet | Force devnet mode (RPC, token mints, explorer links) | false |
| --faucet | Print faucet instructions + burner pubkey and exit | false |
| --airdrop <sol> | Request devnet SOL airdrop (e.g. --airdrop 1) | — |
| --save-burner <path> | Save burner keypair to disk (explicit opt-in, 0600) | — |
| --load-burner <path> | Load a previously saved burner keypair | — |
Supported tokens (mainnet v1): SOL, USDC, USDT
Supported tokens (devnet): SOL, USDC
Presets
| Preset | Description | Expected |
|--------|-------------|----------|
| swap_small | Small 0.01 ETH swap | ALLOWED |
| swap_too_large | 999,999 ETH swap | DENIED (value limit) |
| ttl_too_high | Swap with 24h TTL | DENIED (TTL policy) |
Output
All commands return a JSON envelope with "ok": true/false.
Success (JSON, default)
{
"ok": true,
"base_url": "https://api.trucore.xyz",
"preset": "swap_small",
"verified": true,
"response": {
"decision": "allowed",
"reasons": [],
"receipt_hash": "a1b2c3...64hex",
"content_hash": "d4e5f6...64hex"
}
}When --verify is not used, the verified field is null.
When a preset is not used, the preset field is null.
### Success (Pretty, `--pretty`)
✓ ALLOWED Reason: All policies passed Receipt: a1b2c3...64hex
✓ Content hash verified
### Errors
All errors return a structured JSON envelope:
```json
{
"ok": false,
"error": {
"code": "NETWORK_ERROR",
"message": "Network failure — fetch failed",
"details": {
"hint": "Check your network connection and base URL."
}
}
}Error codes: USER_ERROR, DENIED, NETWORK_ERROR, SERVER_ERROR, VALIDATION_ERROR, AUTH_ERROR, VERIFY_FAILED.
Exit Codes
| Code | Meaning | |------|---------| | 0 | Success (allowed, healthy, approved, etc.) | | 1 | User error or denied (bad input, auth failure, transaction denied, verify failed) | | 2 | Network / server error (unreachable, 5xx, timeout, rate limited) |
Trustless Verification
Don't trust TruCore — verify.
Every simulation produces a content_hash (SHA-256). You can:
- Use
--verifyflag: Automatically recomputes and checks content_hash integrity client-side. - Recompute locally: The policy engine is deterministic. Same input → same hash.
- Check receipt signatures (when available):
GET /api/receipt-signing-key
The --verify flag checks content_hash integrity automatically. On mismatch it exits 1 with VERIFY_FAILED.
Token Redaction
Bearer tokens are never emitted in CLI output. All stdout/stderr is scrubbed
for token values and Bearer <token> patterns before printing.
Environment Variables
| Variable | Description |
|----------|-------------|
| ATF_API_KEY | API key (sent as x-api-key header or Bearer token) |
| ATF_BASE_URL | Override default base URL |
| ATF_TIMEOUT_MS | Override default timeout (milliseconds, default: 20000) |
| ATF_DEVNET_RPC | Override devnet RPC URL (default: https://api.devnet.solana.com) |
| HELIUS_API_KEY | Helius RPC API key (used when rpc_url=helius) |
| NO_COLOR | Disable ANSI colors when set |
Requirements
- Node.js 18+
- Runtime dependency:
[email protected](ed25519 signing for Solana transactions)
Development
# Build
node build.mjs
# Test (all offline — no network calls)
node --test tests/*.mjs
# Pack (dry run — verify included files)
npm pack --dry-runPublishing
# 1. Build
node build.mjs
# 2. Run all tests
node --test tests/*.mjs
# 3. Inspect the tarball
npm pack --dry-run
# Expected files: LICENSE, README.md, dist/index.js, package.json
# 4. Publish to npm (requires npm login)
npm publish --access public
# 5. Verify install (from a clean machine or CI)
npx @trucore/[email protected] version
npx @trucore/[email protected] health
npx @trucore/[email protected] whoami
npx @trucore/[email protected] doctor --prettyLicense
MIT
