Add x402station action provider — pre-flight oracle for x402 endpoints#1154
Open
sF1nX wants to merge 4 commits intocoinbase:mainfrom
Open
Add x402station action provider — pre-flight oracle for x402 endpoints#1154sF1nX wants to merge 4 commits intocoinbase:mainfrom
sF1nX wants to merge 4 commits intocoinbase:mainfrom
Conversation
sF1nX
added a commit
to sF1nX/lucid-agents
that referenced
this pull request
Apr 27, 2026
…points
x402station is a public oracle for the x402 agentic-commerce network
that probes every endpoint on agentic.market every ~10 minutes and
flags decoys (price ≥ $1k USDC), zombies (100% erroring), dead
endpoints, and price/latency anomalies. Calling preflight before
each paid x402 request costs $0.001 USDC and is typically 20× cheaper
than the request an agent would otherwise lose to a decoy.
This package adds a thin client that builds on
@lucid-agents/payments — its `createX402Fetch` is the only x402
plumbing we need; we just wrap the six oracle endpoints behind a
typed surface and let payments handle the EIP-712 signing.
Six methods:
preflight({ url }) $0.001 {ok, warnings[], metadata}
forensics({ url }) $0.001 7-day uptime + p50/p90/p99 +
decoy probability + concentration
catalogDecoys() $0.005 full known-bad blacklist
watch.subscribe(...) $0.01 30-day webhook subscription +
100 prepaid HMAC-signed alerts
watch.status({ id, secret }) free secret-gated read-back
watch.unsubscribe(...) free secret-gated soft-delete
Networks: Base mainnet (eip155:8453) and Base Sepolia (eip155:84532).
The constructor allow-lists baseUrl to https://x402station.io or any
http(s)://localhost* dev URL — refuses to start otherwise so a
misconfigured agent can't sign x402 payments against an unknown
host. Mirrors the same guard shipped in the official x402station-mcp
npm package and the AgentKit action provider PR
(coinbase/agentkit#1154).
Tests cover the constructor allow-list (canonical + dev URL +
trailing-slash + non-canonical reject + malformed reject + port-
bypass reject), every paid action including the x-payment-response
receipt decode, the wallet-aware vs free-fetch split for the watch
endpoints, zod input validation (signal whitelist, UUID watchId,
64-hex secret) catching errors before any wallet round-trip, and
the 404-for-both-cases secret-gated behaviour. 19/19 passing under
`bun test`. tsup produces ESM (5.4 KB) + DTS (8.98 KB) cleanly.
5 tasks
61e7b5d to
40bdd63
Compare
sF1nX
added a commit
to sF1nX/lucid-agents
that referenced
this pull request
Apr 27, 2026
…points
x402station is a public oracle for the x402 agentic-commerce network
that probes every endpoint on agentic.market every ~10 minutes and
flags decoys (price ≥ $1k USDC), zombies (100% erroring), dead
endpoints, and price/latency anomalies. Calling preflight before
each paid x402 request costs $0.001 USDC and is typically 20× cheaper
than the request an agent would otherwise lose to a decoy.
This package adds a thin client that builds on
@lucid-agents/payments — its `createX402Fetch` is the only x402
plumbing we need; we just wrap the six oracle endpoints behind a
typed surface and let payments handle the EIP-712 signing.
Six methods:
preflight({ url }) $0.001 {ok, warnings[], metadata}
forensics({ url }) $0.001 7-day uptime + p50/p90/p99 +
decoy probability + concentration
catalogDecoys() $0.005 full known-bad blacklist
watch.subscribe(...) $0.01 30-day webhook subscription +
100 prepaid HMAC-signed alerts
watch.status({ id, secret }) free secret-gated read-back
watch.unsubscribe(...) free secret-gated soft-delete
Networks: Base mainnet (eip155:8453) and Base Sepolia (eip155:84532).
The constructor allow-lists baseUrl to https://x402station.io or any
http(s)://localhost* dev URL — refuses to start otherwise so a
misconfigured agent can't sign x402 payments against an unknown
host. Mirrors the same guard shipped in the official x402station-mcp
npm package and the AgentKit action provider PR
(coinbase/agentkit#1154).
Tests cover the constructor allow-list (canonical + dev URL +
trailing-slash + non-canonical reject + malformed reject + port-
bypass reject), every paid action including the x-payment-response
receipt decode, the wallet-aware vs free-fetch split for the watch
endpoints, zod input validation (signal whitelist, UUID watchId,
64-hex secret) catching errors before any wallet round-trip, and
the 404-for-both-cases secret-gated behaviour. 19/19 passing under
`bun test`. tsup produces ESM (5.4 KB) + DTS (8.98 KB) cleanly.
sF1nX
added a commit
to sF1nX/lucid-agents
that referenced
this pull request
Apr 27, 2026
…points
x402station is a public oracle for the x402 agentic-commerce network
that probes every endpoint on agentic.market every ~10 minutes and
flags decoys (price ≥ $1k USDC), zombies (100% erroring), dead
endpoints, and price/latency anomalies. Calling preflight before
each paid x402 request costs $0.001 USDC and is typically 20× cheaper
than the request an agent would otherwise lose to a decoy.
This package adds a thin client that builds on
@lucid-agents/payments — its `createX402Fetch` is the only x402
plumbing we need; we just wrap the six oracle endpoints behind a
typed surface and let payments handle the EIP-712 signing.
Six methods:
preflight({ url }) $0.001 {ok, warnings[], metadata}
forensics({ url }) $0.001 7-day uptime + p50/p90/p99 +
decoy probability + concentration
catalogDecoys() $0.005 full known-bad blacklist
watch.subscribe(...) $0.01 30-day webhook subscription +
100 prepaid HMAC-signed alerts
watch.status({ id, secret }) free secret-gated read-back
watch.unsubscribe(...) free secret-gated soft-delete
Networks: Base mainnet (eip155:8453) and Base Sepolia (eip155:84532).
The constructor allow-lists baseUrl to https://x402station.io or any
http(s)://localhost* dev URL — refuses to start otherwise so a
misconfigured agent can't sign x402 payments against an unknown
host. Mirrors the same guard shipped in the official x402station-mcp
npm package and the AgentKit action provider PR
(coinbase/agentkit#1154).
Tests cover the constructor allow-list (canonical + dev URL +
trailing-slash + non-canonical reject + malformed reject + port-
bypass reject), every paid action including the x-payment-response
receipt decode, the wallet-aware vs free-fetch split for the watch
endpoints, zod input validation (signal whitelist, UUID watchId,
64-hex secret) catching errors before any wallet round-trip, and
the 404-for-both-cases secret-gated behaviour. 19/19 passing under
`bun test`. tsup produces ESM (5.4 KB) + DTS (8.98 KB) cleanly.
x402station is a public oracle for the x402 agentic-commerce network
that probes every endpoint on agentic.market every ~10 minutes and
flags decoys (price ≥ $1k USDC), zombies (100% erroring), dead
endpoints, and price/latency anomalies. Calling preflight before
each paid x402 request costs $0.001 USDC and is typically 20× cheaper
than the request an agent would otherwise lose to a decoy.
This action provider mirrors the shape of the existing `x402` provider
in this repo and reuses the same EvmWalletProvider signer-wrapping
pattern, so the four paid actions auto-sign their own $0.001-$0.01
USDC payments through whatever EvmWalletProvider the agent is already
configured with. Two free secret-gated actions (watch_status,
watch_unsubscribe) manage an existing webhook subscription.
Six actions:
preflight $0.001 {ok, warnings[], metadata}
forensics $0.001 7-day uptime + latency p50/p90/p99 +
decoy probability + concentration
catalog_decoys $0.005 full known-bad blacklist, cacheable
watch_subscribe $0.01 30-day webhook subscription + 100
prepaid HMAC-signed alerts
watch_status free secret-gated read-back
watch_unsubscribe free secret-gated soft-delete
Networks: Base mainnet (eip155:8453) and Base Sepolia (eip155:84532).
Tests cover the constructor's host allowlist (canonical
x402station.io, http(s)://localhost dev URLs only — refuses to start
otherwise so a misconfigured agent can't sign x402 payments against
an unknown host), supportsNetwork (Base ✓, others ✗), every action
path including the x-payment-response header decoding into
paymentReceipt, and the secret-gated 404 behaviour for the free
watch endpoints. 21/21 passing.
40bdd63 to
d260b2d
Compare
4 tasks
CRITICAL: u.host.startsWith("localhost") matches an attacker host
"localhost.attacker.com" via prefix — same is true for
"127.0.0.1.evil.example" and "localhost-impersonation.example".
This was the only defense between a misconfigured baseUrl and a
signed X-PAYMENT being routed off-target.
Switch to u.hostname exact-match against "localhost", "127.0.0.1",
"[::1]" (WHATWG URL.hostname returns the bracketed form for IPv6
literals per RFC 2732). u.host stays as exact-match on canonical
"x402station.io" so port-bypass also stays blocked.
Three regression tests added (localhost.attacker.com,
127.0.0.1.evil.example, localhost-evil.example).
Discovered by CodeRabbit on the upstream Mastra integration PR
(mastra-ai/mastra#15804). Mirrored to the Daydreams Lucid PR
(daydreamsai/lucid-agents#1629), the @mastra/x402station
integration, and the x402station-mcp v1.0.6 npm package release.
27/27 jest passing, no tsc errors against locally-built workspace.
🟡 Heimdall Review Status
|
7th action wraps the new x402station /api/v1/alternatives endpoint:
given a URL flagged by preflight (or a taskClass hint), returns up
to 5 healthy sibling endpoints in the same provider/domain/category/
price-band, ranked by uptime + latency. Solves "preflight returned
ok=false, where do I go instead?" — the next question every agent
has after a blocked call.
Inputs (AlternativesSchema): { url?, taskClass?, limit? }, at least
one of url/taskClass required (route enforces 400 if both empty).
limit 1..10 default 5. zod refine on the input schema flags the
common case at construction time.
29/29 jest passing (+2 new: alternatives URL-mode body shape,
taskClass+limit body shape with omitted url field).
End-to-end verified on the upstream oracle (Base mainnet): URL-mode
returned similar_price siblings at 100% uptime + 80ms latency;
taskClass="Inference" returned 3 BlockRun.AI candidates with
same_category match_reason out of 188 total eligible.
8th action wraps the new x402station /api/v1/whats-new endpoint:
returns added_endpoints[] (first_seen_at >= since AND is_active=true),
removed_endpoints[] (flipped to is_active=false since), service-level
counts, polls_in_window, and current active totals. Default window
is 24h; cap is 30 days back; limit caps each list 1..500 default 200.
Designed for aggregator agents that need a fresh catalog delta
without re-pulling the whole 30k-endpoint dump. Cheapest tier
($0.001) — hourly polling stays under $1/month. Internal ingest
cron runs every 5 min, so polling more often returns identical
data.
Inputs (WhatsNewSchema): { since?, limit? }, both optional.
zod datetime() validates ISO 8601 client-side; route-level checks
catch since-too-old / since-in-future / limit-out-of-range.
31/31 jest passing (+2 new for whats_new: empty body when no args,
since+limit threading).
End-to-end verified on Base mainnet: default 24h window returned
4112 added / 71 removed (catalog grew 17% in 24h, 25950 -> 30200);
1h window returned 98 added / 71 removed.
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.
Summary
Adds a new
x402stationaction provider — a wrapper around the public oracle at x402station.io that gives any AgentKit-built agent six tools for safely paying x402 endpoints:preflight{ok, warnings[], metadata}for any URL — fast safety checkforensicscatalog_decoyswatch_subscribewatch_statuswatch_unsubscribeNetworks: Base mainnet (
eip155:8453) and Base Sepolia (eip155:84532). Payments auto-signed through whateverEvmWalletProviderthe agent is already configured with.Why pre-flight?
The agentic.market catalog has 25,000+ x402 endpoints. A non-trivial fraction are honeypots or unreachable:
x402station independently probes every active catalog endpoint every ~10 minutes (not facilitator-reported) so it surfaces what facilitator-only monitors miss. Calling
preflightbefore each paid x402 request costs $0.001 USDC — typically 20× cheaper than the request the agent would otherwise lose to a decoy.A recent independent run on the entire catalog (blog post — methodology + raw JSONL) found 53% of endpoints at Cloudflare-
isitagentready.comlevel 0 and 1.5% with x402 actually detected — so the "is this a real endpoint?" filter is doing real work.Implementation
Mirrors the shape of the existing
x402action provider and reuses itsEvmWalletProvidersigner-wrapping pattern, so the four paid actions auto-sign x402 challenges through the agent's existing wallet without extra plumbing.The
baseUrlis allow-listed: onlyhttps://x402station.io(canonical) or anyhttp(s)://localhost*(development) is accepted. Any other host throws at construction time so a misconfigured agent can't sign x402 payments against an unknown host.Test coverage
pnpm test src/action-providers/x402station/— 21/21 passing locally.https://x402station.io:9999is rejected even though.hostnamematches).base-mainnet✓,base-sepolia✓,ethereum-mainnet✗, non-EVM ✗.paymentReceiptdecoded fromx-payment-responseheader, error envelope on non-2xx.signalsomitted-vs-included.Manual end-to-end against the prod oracle ($0.018 USDC settled from a test wallet on Base mainnet) — 7/7 PASS via the consumer-side demo agent in the public repo.
Quick start
The LLM can then call
preflight,forensics, etc. viaagentKit.getActions().Existing alternatives
For agents that speak Model Context Protocol (Claude Code / Cursor / Windsurf / Continue), the same six tools are already available via the
x402station-mcpnpm package and the official MCP Registry. This PR is the AgentKit-native equivalent for the non-MCP path.Test plan
pnpm test src/action-providers/x402station/— 21/21 passingpnpm check— 0 type errors inx402station/files (15 pre-existing errors elsewhere —cdp/,opensea/,zora/— are not from this PR)Links
The oracle backend (probe pipeline, signal logic, ingest, internal stats history) lives in a private repo — by design. This PR's source is fully visible in the diff above and snapshotted at https://github.com/sF1nX/x402station-mcp/tree/main/examples/agentkit-action-provider for browseability.