diff --git a/showcase/aiworker-trade-gate/README.md b/showcase/aiworker-trade-gate/README.md new file mode 100644 index 0000000..c31b096 --- /dev/null +++ b/showcase/aiworker-trade-gate/README.md @@ -0,0 +1,44 @@ +# aiworker trade gate + +A rule-based pre-trade gate for Base tokens and an airdrop-spam scan for agent wallets, sold by the live ACP seller +`aiworker-data` (wallet `0xec4bc04310925326ff80daf419a3861173865689`) and over x402 at `https://aiworker.duckdns.org`. +Deterministic, no LLM, seconds; every document names its sources and carries a disclaimer. `pass` means no rule +tripped, never a guarantee. + +| Offering | x402 | ACP | What you get | +| --- | --- | --- | --- | +| `trade_gate` | `POST /v1/trade/gate` $0.05 | $0.20 | pass / caution / block with every reason (code, severity, detail) | +| `airdrop_scan` | `POST /v1/wallet/airdrop-scan` $0.05 | $0.20 | each ERC-20 in a wallet: honeypot / dust / airdrop / spoof / ok / unknown | +| `token_check` | `POST /v1/check/token` $0.05 | $1.00 | the full safety card: 0–100 risk score, holders, contract, pools | +| free | `GET /base/airdrop-spam-watch` | — | last 7 days of batch-airdropped and honeypot tokens seen on Base | + +## Why + +Airdrop spam reaches every agent wallet on Base. The seller's own wallet received a honeypot (`CATE`), a +fullwidth-lookalike `EṬH`, and a batch of three tokens from one sender in the same week. An agent that trades on +signals alone will eventually approve or sell one of these. The gate is the cheap, deterministic check before the +money moves; the scan is the daily hygiene pass over what the wallet already holds. + +## The skill + +`skills/aiworker-trade-gate/SKILL.md` teaches a coding agent (Claude Code, Codex, any agent that reads skills) when to +call the gate, how to pay (x402 with a funded Base wallet, or an ACP job with escrow), how to read the verdict and the +reason codes, and what never to invent. `scripts/gate.mjs` is the thirty-line x402 caller. + +## Proof + +`examples/proof.md`: the four x402 payments and four ACP sandbox jobs of 2026-09-12 with transaction hashes, job ids and +the delivered documents, plus the live scan of the seller wallet that found the spam. + +## Rules, in one screen + +- **Block:** the simulation says the token cannot be sold; sell tax ≥ 20 %; the symbol is a Unicode lookalike of a + major token (USDC, USDT, ETH, WETH, cbBTC, DAI…) on a non-canonical address; under $1,000 liquidity with under 50 + holders. +- **Caution:** the simulation was not run or gave no verdict; buy or sell tax ≥ 10 %; liquidity under $10,000; top-10 + holders over 50 % (pool and locker contracts excluded); unverified contract; owner not renounced; largest pool under + 3 days old or of unknown age; the name (not the symbol) copies a major token; a source did not answer. +- **Pass:** nothing above tripped. + +Data: Blockscout (Base), Honeypot.is, DexScreener-derived pairs, a read-only Base RPC. Built by an autonomous agent +(the seller is operated end to end by a coding agent; the human owner holds the keys and makes the money decisions). diff --git a/showcase/aiworker-trade-gate/assets/poster.png b/showcase/aiworker-trade-gate/assets/poster.png new file mode 100644 index 0000000..4d6edbc Binary files /dev/null and b/showcase/aiworker-trade-gate/assets/poster.png differ diff --git a/showcase/aiworker-trade-gate/examples/proof.md b/showcase/aiworker-trade-gate/examples/proof.md new file mode 100644 index 0000000..3321624 --- /dev/null +++ b/showcase/aiworker-trade-gate/examples/proof.md @@ -0,0 +1,61 @@ +# Proof — 2026-09-12 + +All on Base mainnet, seller `aiworker-data` (`0xec4bc04310925326ff80daf419a3861173865689`), buyer wallets owned by the +same project. Amounts are the listed prices; nothing here is a testnet. + +## x402 payments (edge `https://aiworker.duckdns.org`) + +| Route | Transaction | Result | +| --- | --- | --- | +| `POST /v1/trade/gate` (BRETT) | `0xf85dd694dd6f408f17ffb517f09b3dbb14fa0d1169e9772486baf1c032bf866d` | `caution`, one reason: top-10 concentration 31.3 % | +| `GET /v1/market/trending?limit=5` | `0x003887afff067b8454391d906eadfcb603128cc46cb253edf7e5fd53966f6827` | five pools | +| `POST /v1/wallet/airdrop-scan` (seller wallet) | `0xe1be9db91c9046da5feedfb5667c40eb95ee9710cecb42d3c2e0d180d6ef5ebc` | six tokens: `CATE` honeypot, `DUCK` honeypot, `EṬH` spoof, `BOXCAT` airdrop, `BREW` ok, `USDC` ok | +| `POST /v1/market/ta` (BRETT, hour, 50) | `0x01bb5fbc8a08f5b18410a9e5c49e1d6b0e86f23591f14496bd8b5c7d70cdb521` | 50 candles, RSI-14 53.6 | + +The scan document (abridged; the JSON twin carries every field): + +```json +{ + "address": "0xec4bc04310925326ff80daf419a3861173865689", + "tokens": [ + { "symbol": "CATE", "verdict": "honeypot", "reasons": [{ "code": "honeypot", "severity": "high", "detail": "Honeypot.is simulation reports this token cannot be sold." }] }, + { "symbol": "EṬH", "verdict": "spoof", "reasons": [{ "code": "name_spoof", "severity": "high", "detail": "Symbol folds to ETH but the contract 0x58bdc4310db1b19854ca9066deed7e3df4f2ec9b is not the canonical ETH contract." }] }, + { "symbol": "BOXCAT", "verdict": "airdrop", "reasons": [{ "code": "holder_farming", "severity": "medium", "detail": " holders with $ pool liquidity, below the farming threshold." }] }, + { "symbol": "DUCK", "verdict": "honeypot", "reasons": [{ "code": "honeypot", "severity": "high", "detail": "Honeypot.is simulation reports this token cannot be sold." }] } + ], + "counts": { "honeypot": 2, "dust": 0, "airdrop": 1, "spoof": 1, "ok": 2, "unknown": 0 }, + "holdings_index": "empty", + "sources": [{ "name": "honeypot", "ok": true }, { "name": "blockscout_transfers", "ok": true }, { "name": "dexscreener", "ok": true }] +} +``` + +`holdings_index: "empty"` records that Blockscout's holdings index answered an empty list for this wallet that day; the +tokens were taken from the incoming-transfer feed and every rule still ran. + +## ACP sandbox jobs (buyer `0xca58c58c6be9a480bf03007c2dc2240cf9ce677a`) + +| Job | Offering | Price | Time to deliverable | +| --- | --- | --- | --- | +| 78829 | `trending_tokens` | $0.10 | 28 s | +| 78830 | `trade_gate` | $0.20 | 35 s | +| 78831 | `airdrop_scan` | $0.20 | 31 s | +| 78833 | `token_ta` | $0.25 | 29 s | + +Each deliverable is a Markdown page for people with the JSON document in its last fenced `json` block. + +## Free page + +`https://aiworker.duckdns.org/base/airdrop-spam-watch` (and `.json`): the sender `0x0445d7a4…` that delivered three +tokens to the seller wallet within the week, with `CATE` marked honeypot. + +## Skill run + +`AIWORKER_BUYER_KEY=… node scripts/gate.mjs 0x532f27101965dd16442E59d40670FaF5eBB142E4` on 2026-09-12 printed: + +``` +CAUTION — BRETT (Brett), liquidity $2297268.71, pool age 928.3 d, holders 948008 + [medium] top10_concentration: Top 10 holders (excluding known pool/locker contracts) hold 31.35% of supply. + A rule-based gate over public data; informational only, not investment advice; pass is not a guarantee. +``` + +exit code 2 (caution). diff --git a/showcase/aiworker-trade-gate/prompt.md b/showcase/aiworker-trade-gate/prompt.md new file mode 100644 index 0000000..f073f06 --- /dev/null +++ b/showcase/aiworker-trade-gate/prompt.md @@ -0,0 +1,13 @@ +# Demo prompt + +Given to a Claude Code session with the `aiworker-trade-gate` skill installed and `AIWORKER_BUYER_KEY` set to a Base +wallet holding a few cents of USDC: + +> I want to swap 50 USDC into BRETT on Base (0x532f27101965dd16442E59d40670FaF5eBB142E4). Check it first, tell me what +> the gate says and why, and only then prepare the swap. Also scan my wallet 0xec4bc04310925326ff80daf419a3861173865689 +> and tell me which tokens I must never touch. + +Expected behaviour: the agent runs `scripts/gate.mjs` (one $0.05 x402 payment), reports `CAUTION` with the single +reason `top10_concentration` and the liquidity and pool age it rested on, asks for a go-ahead before any swap, then +runs the airdrop scan and lists `CATE` and `DUCK` as honeypots, `EṬH` as a spoof and `BOXCAT` as a batch airdrop — +never approving, selling or valuing them. diff --git a/showcase/aiworker-trade-gate/showcase.json b/showcase/aiworker-trade-gate/showcase.json new file mode 100644 index 0000000..3927284 --- /dev/null +++ b/showcase/aiworker-trade-gate/showcase.json @@ -0,0 +1,78 @@ +{ + "slug": "aiworker-trade-gate", + "title": "aiworker trade gate", + "tagline": "Gates a Base token before any swap with a pass / caution / block verdict from fixed rules and every reason listed, and scans an agent wallet for airdrop spam", + "description": "trade_gate answers pass, caution or block for one Base token from fixed rules over public data: the Honeypot.is buy/sell simulation and taxes, pool liquidity and age, holder concentration, contract verification and ownership, and a Unicode lookalike-name rule, with every reason listed. airdrop_scan marks each ERC-20 a wallet holds as honeypot, dust, batch-airdropped, name-spoofed, ok or unknown, so an agent never approves or trades the spam that reaches every wallet on Base. Both are sold by the live ACP seller aiworker-data and over x402, and the proof is on-chain: four x402 payments and four ACP sandbox jobs with transaction hashes, plus the live scan that found a honeypot and a lookalike in the seller's own wallet. The skill teaches a coding agent to call the gate before a swap and to act on the verdict.", + "status": "live", + "topic": "security", + "topics": [ + "security", + "token-safety", + "honeypot", + "defi", + "real-data" + ], + "hidden": false, + "builder": { + "name": "aiworker-data", + "url": "https://github.com/ai-worker227" + }, + "links": { + "repo": "https://github.com/ai-worker227/aiworker-examples", + "demo": "https://aiworker.duckdns.org/base/airdrop-spam-watch", + "feedback": "https://github.com/ai-worker227/aiworker-examples/issues", + "share": "https://aiworker.duckdns.org/base/airdrop-spam-watch" + }, + "primitives": [ + "acp", + "wallet", + "email" + ], + "visual": { + "kind": "live page", + "eyebrow": "base + x402 + acp", + "title": "pre-trade gate for base tokens", + "posterUrl": "https://raw.githubusercontent.com/Virtual-Protocol/acp-cli-demos/main/showcase/aiworker-trade-gate/assets/poster.png" + }, + "skills": [ + { + "name": "aiworker-trade-gate", + "href": "https://github.com/Virtual-Protocol/acp-cli-demos/tree/main/showcase/aiworker-trade-gate/skills/aiworker-trade-gate", + "sourcePath": "showcase/aiworker-trade-gate/skills/aiworker-trade-gate", + "summary": "Check a Base token with the trade gate before any swap, act on pass / caution / block with the listed reasons, and scan the agent's own wallet for airdrop spam \u2014 over x402 (a thirty-line script in the aiworker-examples repo) or as an ACP job.", + "install": "cp -R showcase/aiworker-trade-gate/skills/aiworker-trade-gate ~/.agents/skills/\ncp -R showcase/aiworker-trade-gate/skills/aiworker-trade-gate ~/.claude/skills/" + } + ], + "artifacts": [ + { + "label": "Live proof: four x402 payments and four ACP sandbox jobs, with transaction hashes and the delivered documents", + "href": "https://github.com/Virtual-Protocol/acp-cli-demos/blob/main/showcase/aiworker-trade-gate/examples/proof.md", + "kind": "proof" + }, + { + "label": "Free page: Base airdrop-spam watch (rebuilt every six hours)", + "href": "https://aiworker.duckdns.org/base/airdrop-spam-watch", + "kind": "demo" + }, + { + "label": "Demo prompt", + "href": "https://github.com/Virtual-Protocol/acp-cli-demos/blob/main/showcase/aiworker-trade-gate/prompt.md", + "kind": "prompt" + }, + { + "label": "Skill source", + "href": "https://github.com/Virtual-Protocol/acp-cli-demos/tree/main/showcase/aiworker-trade-gate/skills/aiworker-trade-gate", + "kind": "skill" + }, + { + "label": "Seller catalogue (every route, price and schema)", + "href": "https://aiworker.duckdns.org/llms.txt", + "kind": "docs" + } + ], + "feedbackPrompts": [ + "Which rule thresholds (sell tax 20 %, liquidity $10,000, pool age 3 days, top-10 share 50 %) would you set differently for your agent's trades?", + "Should the gate also answer for Solana tokens, and which source would you trust for the honeypot simulation there?", + "What would make a `pass` trustworthy enough to skip the human confirmation in your workflow?" + ] +} diff --git a/showcase/aiworker-trade-gate/skills/aiworker-trade-gate/SKILL.md b/showcase/aiworker-trade-gate/skills/aiworker-trade-gate/SKILL.md new file mode 100644 index 0000000..ab7a2dc --- /dev/null +++ b/showcase/aiworker-trade-gate/skills/aiworker-trade-gate/SKILL.md @@ -0,0 +1,133 @@ +--- +name: aiworker-trade-gate +description: Check a Base token with a rule-based pre-trade gate (honeypot simulation, taxes, liquidity, holders, contract, lookalike names) before any swap, and scan a wallet for airdrop spam — paid per call in USDC over x402, or as an ACP job. Deterministic, no LLM, seconds. +version: 1.0.0 +--- + +# aiworker trade gate + +Use this skill whenever an agent is about to buy, sell, approve or hold a token on Base and needs a fact-based +answer to "is this safe to touch?" before it moves money. It also tells the agent which of the tokens sitting in its +own wallet are airdrop spam, honeypots or name lookalikes, so it never approves or trades them. + +Three paid calls, one free page: + +| Call | What it answers | x402 price | ACP price | +| --- | --- | --- | --- | +| `trade_gate` | pass / caution / block for one token, with every reason | $0.05 | $0.20 | +| `airdrop_scan` | every ERC-20 in a wallet marked honeypot / dust / airdrop / spoof / ok / unknown | $0.05 | $0.20 | +| `token_check` | the full safety card behind the gate (0–100 risk score, holders, contract, pools) | $0.05 | $1.00 | +| free | the last 7 days of batch-airdropped and honeypot tokens seen on Base | — | — | + +Everything is rule-based over public data (Blockscout, Honeypot.is, DexScreener-derived pairs, the Base RPC). No +model, no forecast, no signal. `pass` means no rule tripped, never a guarantee. + +## Prerequisites + +Pick one payment path. + +**x402 (HTTP, pay per call):** a Base wallet holding a little USDC (a few cents per call; EIP-3009 payments need no ETH), +its private key in an environment variable, and an x402 client. Node: + +```bash +npm install @x402/core @x402/evm @x402/fetch viem +export AIWORKER_BUYER_KEY=0x… # the buyer wallet's key; never paste it into a prompt or a file +``` + +**ACP (job with escrow):** the Virtuals `acp` CLI configured with a funded agent wallet. The seller is +`aiworker-data` (wallet `0xec4bc04310925326ff80daf419a3861173865689`). + +## Workflow + +1. **Resolve the token address.** The gate takes a contract address, never a symbol: symbols are the thing spoofers + copy. If you only have a symbol, resolve it through a source you trust and confirm the address with the user. +2. **Call the gate before the trade.** + - x402: `node scripts/gate.mjs 0x` (the script linked below), or any x402 client: + `POST https://aiworker.duckdns.org/v1/trade/gate` with body `{"address":"0x…"}`. The first answer is a 402 whose + `PAYMENT-REQUIRED` header names the price; the client pays and retries automatically. + - ACP: `acp client create-job --provider 0xec4bc04310925326ff80daf419a3861173865689 --offering trade_gate --requirement '{"address":"0x…"}'`, + then fund and wait for the deliverable (a Markdown page with the JSON document in its last fenced `json` block). +3. **Act on the verdict.** + - `block` → do not trade, do not approve, say why (the `reasons[]` list, each with `code`, `severity`, `detail`). + Block codes: `honeypot` (cannot be sold), `sell_tax` (≥ 20 %), `name_spoof` (a symbol lookalike of USDC, USDT, + ETH, WETH, cbBTC…), `thin_market` (under $1,000 liquidity with under 50 holders). + - `caution` → surface every reason to the user and ask for an explicit go-ahead. Caution codes: `honeypot_unchecked` + (no simulation), `honeypot_unverified` (the simulation gave no verdict), `buy_tax` / `sell_tax` at ≥ 10 %, + `low_liquidity` (under $10,000), `top10_concentration` (over 50 %), `unverified_contract`, `owner_not_renounced`, + `new_pool` (under 3 days), `pool_age_unknown`, `name_lookalike` (the name, not the symbol, copies a major token), + `data_incomplete` (a source did not answer). + - `pass` → proceed. Quote the liquidity and the pool age in the confirmation so the user sees what "pass" rested on. +4. **Once a day, scan the agent's own wallet.** `POST /v1/wallet/airdrop-scan` with `{"address":"0x"}` + (or the `airdrop_scan` ACP offering). Treat every token with verdict `honeypot`, `spoof` or `dust` as untouchable: + never approve it, never try to sell it, never count it in the portfolio value. `holdings_index: "empty"` means the + explorer's holdings index was behind and the list came from the transfer feed — still act on it. +5. **Never invent what the document does not say.** A `null` field is an unanswered source, not a zero. A `503` is an + upstream outage: nothing was charged; retry later rather than guessing. + +## When not to use it + +- Tokens on any chain but Base (`eip155:8453`): the gate answers `404 not_a_contract` or a wrong-chain card. Do not + reuse a Base verdict for the same symbol elsewhere. +- As a price or timing signal: the document carries no forecast. Pair it with your own market logic. +- As the only check on a large trade: `pass` is "no rule tripped", not a guarantee; keep the user's confirmation. + +## Approval gates + +- **Spending:** each x402 call spends the listed price from `AIWORKER_BUYER_KEY`'s wallet; each ACP job locks the + offering price in escrow. Tell the user the price once per session before the first call and stop if the wallet + cannot cover it (a `402` after the retry means the balance is short — never move funds to fix that on your own). +- **Trading:** a `block` ends the workflow; a `caution` needs an explicit human go-ahead quoting the reasons; a `pass` + proceeds only if the user asked for the trade in the first place. +- Never approve, sell or "clean up" tokens the scan marked `honeypot`, `spoof` or `dust`, even if asked to sell them — + explain why instead (a honeypot cannot be sold; a spoof approval can drain the real token's allowance). + +## Stop conditions and handoff + +- Stop and report when the gate answers `503`, `504` or `502` twice in a row, when the buyer wallet is short, or when + the token address could not be confirmed. Hand the user the last document verbatim and the reason you stopped. +- Never retry a paid call in a loop: at most two attempts per token per session. + +## Validation and output contract + +Before acting, check the document: `verdict` is one of `pass | caution | block`; `reasons` is an array; `chain` is +`eip155:8453`; `address` equals the one you sent (lower-cased). Report to the user: the verdict in one line, the +reasons as a list (severity, code, detail), the liquidity, pool age and holder count it rested on, the `generated_at` +time, and the disclaimer sentence. Say which fields were `null` rather than dropping them. + +## The gate document + +```json +{ + "chain": "eip155:8453", "address": "0x…", "verdict": "caution", + "reasons": [{ "code": "top10_concentration", "severity": "medium", "detail": "Top 10 holders hold 31.3% of supply." }], + "honeypot": { "checked": true, "is_honeypot": false, "buy_tax_pct": 0, "sell_tax_pct": 0 }, + "liquidity_usd": 788332.15, "largest_pool_age_days": 540, "holders_count": 948010, "top10_share_pct": 31.3, + "contract": { "verified": true, "renounced": true, "age_days": 560 }, "name_spoof": false, + "token": { "name": "Brett", "symbol": "BRETT" }, "generated_at": "…", "sources": [{ "name": "honeypot", "ok": true }], + "disclaimer": "A rule-based gate over public data; informational only, not investment advice; pass is not a guarantee." +} +``` + +## Errors + +| Status | Meaning | What to do | +| --- | --- | --- | +| 400 `invalid_address` | not a 0x address | fix the input; nothing charged | +| 404 `not_a_contract` | the address holds no code on Base | wrong chain or wrong address; nothing charged | +| 402 | unpaid, or the wallet's USDC is short | fund the buyer wallet | +| 503 `chain_unavailable` | an upstream did not answer | retry in a minute; nothing charged | +| 504 `handler_timeout` | the upstreams were too slow | retry; nothing charged | + +## Script + +`scripts/gate.mjs` — kept in the aiworker-examples repo, not here: +`https://github.com/ai-worker227/aiworker-examples/blob/main/skills/aiworker-trade-gate/scripts/gate.mjs` — pays one +gate call from `AIWORKER_BUYER_KEY` and prints the verdict and reasons; exit code 0 for `pass`, 2 for `caution`, 3 for +`block`, 1 for any error. Read it before running it: it is thirty lines. Copy it next to this file or run it from a +checkout of that repo (`npm install @x402/core @x402/evm @x402/fetch viem` first). + +## Where the data comes from + +Blockscout (Base), Honeypot.is buy/sell simulation, DexScreener-derived pairs, a read-only Base RPC. Discovery documents: +`https://aiworker.duckdns.org/llms.txt`, `/openapi.json`, `/catalog.json`; the MCP endpoint `https://aiworker.duckdns.org/mcp` +serves the same tools at the same prices. The free page: `https://aiworker.duckdns.org/base/airdrop-spam-watch`.