From a3795113cee4c18f0b6b9bbcd43c887ac764de24 Mon Sep 17 00:00:00 2001 From: Tevfik Efe AYDIN <93277682+tevfikefeaydin@users.noreply.github.com> Date: Fri, 7 Aug 2026 08:56:23 +0300 Subject: [PATCH 1/2] Add AgentToll action provider Pay-per-call Base data over x402: new-token scout with safety verdicts, token safety checks, wallet portfolios, onchain token prices, Basename resolution and a market brief - paid in USDC from the agent wallet, no API keys. Uses the same wallet-to-signer pattern as the existing x402 provider. --- typescript/.changeset/great-lions-happen.md | 5 + .../src/action-providers/agenttoll/README.md | 48 ++++ .../agenttoll/agenttollActionProvider.test.ts | 155 +++++++++++ .../agenttoll/agenttollActionProvider.ts | 260 ++++++++++++++++++ .../src/action-providers/agenttoll/index.ts | 2 + .../src/action-providers/agenttoll/schemas.ts | 103 +++++++ .../agentkit/src/action-providers/index.ts | 87 +++--- 7 files changed, 617 insertions(+), 43 deletions(-) create mode 100644 typescript/.changeset/great-lions-happen.md create mode 100644 typescript/agentkit/src/action-providers/agenttoll/README.md create mode 100644 typescript/agentkit/src/action-providers/agenttoll/agenttollActionProvider.test.ts create mode 100644 typescript/agentkit/src/action-providers/agenttoll/agenttollActionProvider.ts create mode 100644 typescript/agentkit/src/action-providers/agenttoll/index.ts create mode 100644 typescript/agentkit/src/action-providers/agenttoll/schemas.ts diff --git a/typescript/.changeset/great-lions-happen.md b/typescript/.changeset/great-lions-happen.md new file mode 100644 index 000000000..db21d91bf --- /dev/null +++ b/typescript/.changeset/great-lions-happen.md @@ -0,0 +1,5 @@ +--- +"@coinbase/agentkit": minor +--- + +Added AgentToll action provider: pay-per-call Base data over x402 (new-token scout with safety verdicts, token safety checks, wallet portfolios, onchain token prices, Basename resolution, market brief), paid in USDC from the agent's wallet with no API keys diff --git a/typescript/agentkit/src/action-providers/agenttoll/README.md b/typescript/agentkit/src/action-providers/agenttoll/README.md new file mode 100644 index 000000000..e782e9076 --- /dev/null +++ b/typescript/agentkit/src/action-providers/agenttoll/README.md @@ -0,0 +1,48 @@ +# AgentToll Action Provider + +Base-native onchain data for agents, pay-per-call over [x402](https://x402.org): +each action costs $0.001–$0.008 in USDC, paid automatically from the agent's +wallet. No API keys, no accounts — and a failed request is never charged, since +settlement only happens when data is returned. + +Backed by [agenttoll.app](https://agenttoll.app) (open source, MIT), settled +through the Coinbase CDP facilitator on Base mainnet. + +## Actions + +| Action | What it answers | Price | +|---|---|---| +| `scout_new_base_tokens` | What launched on Base today, and is any of it safe to touch? New pools with a safety verdict attached | $0.008 | +| `check_base_token_safety` | Is this token a honeypot? Simulated buy & sell, taxes, owner powers, holder concentration | $0.002 | +| `get_base_wallet_portfolio` | What does this address hold, in USD? ETH + ERC-20s, largest first, spam floor | $0.003 | +| `get_base_token_price` | What is this token worth right now? Priced from onchain DEX liquidity | $0.001 | +| `resolve_basename` | Who is `jesse.base.eth`? Name → address + records, or address → primary name | $0.001 | +| `get_market_brief` | One-call snapshot: prices, Base gas, Fear & Greed | $0.005 | + +Safety verdicts are deliberately conservative: a check that could not run is +never a "pass", and a token too new to judge is reported `insufficient-data`, +never `clear`. + +## Setup + +```typescript +import { AgentKit, agenttollActionProvider } from "@coinbase/agentkit"; + +const agentKit = await AgentKit.from({ + walletProvider, + actionProviders: [agenttollActionProvider()], +}); +``` + +The wallet needs a little USDC on Base mainnet — a dollar covers hundreds of +calls. Supported network: `base-mainnet`. + +## Notes + +- Every endpoint also answers unauthenticated with an x402 v2 quote that + carries its own request/response schema, so agents can discover the API + without this provider: `curl -i https://agenttoll.app/api/base/scout`. +- Machine-readable catalog: https://agenttoll.app/api/catalog · + discovery: https://agenttoll.app/.well-known/x402 +- Usage stats are read from USDC transfers onchain, not self-reported: + https://agenttoll.app/api/stats diff --git a/typescript/agentkit/src/action-providers/agenttoll/agenttollActionProvider.test.ts b/typescript/agentkit/src/action-providers/agenttoll/agenttollActionProvider.test.ts new file mode 100644 index 000000000..ef87aed73 --- /dev/null +++ b/typescript/agentkit/src/action-providers/agenttoll/agenttollActionProvider.test.ts @@ -0,0 +1,155 @@ +import { agenttollActionProvider } from "./agenttollActionProvider"; +import { EvmWalletProvider } from "../../wallet-providers"; + +// The x402 payment wrapper is exercised by its own package tests; here it is +// mocked so these tests cover the provider's request building and error paths. +jest.mock("@x402/fetch", () => ({ + x402Client: jest.fn().mockImplementation(() => ({})), + wrapFetchWithPayment: jest.fn((fetchFn: typeof fetch) => fetchFn), +})); +jest.mock("@x402/evm/exact/client", () => ({ + registerExactEvmScheme: jest.fn(), +})); + +describe("AgenttollActionProvider", () => { + const fetchMock = jest.fn(); + global.fetch = fetchMock; + + const mockWallet = { + toSigner: jest.fn().mockReturnValue({ address: "0x1234" }), + readContract: jest.fn(), + } as unknown as EvmWalletProvider; + Object.setPrototypeOf(mockWallet, EvmWalletProvider.prototype); + + const provider = agenttollActionProvider(); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe("scoutNewTokens", () => { + it("returns the response body on success", async () => { + const body = JSON.stringify({ pools: [], summary: { found: 0 } }); + fetchMock.mockResolvedValue({ ok: true, text: jest.fn().mockResolvedValue(body) }); + + const result = await provider.scoutNewTokens(mockWallet, { minLiquidity: 25000, pools: 2 }); + + expect(result).toBe(body); + expect(fetchMock).toHaveBeenCalledWith( + "https://agenttoll.app/api/base/scout?minLiquidity=25000&pools=2", + { method: "GET" }, + ); + }); + + it("omits unset query parameters", async () => { + fetchMock.mockResolvedValue({ ok: true, text: jest.fn().mockResolvedValue("{}") }); + + await provider.scoutNewTokens(mockWallet, {}); + + expect(fetchMock).toHaveBeenCalledWith("https://agenttoll.app/api/base/scout", { + method: "GET", + }); + }); + + it("reports a non-ok response without throwing", async () => { + fetchMock.mockResolvedValue({ + ok: false, + status: 502, + text: jest.fn().mockResolvedValue('{"error":"upstream"}'), + }); + + const result = JSON.parse(await provider.scoutNewTokens(mockWallet, {})); + + expect(result.error).toBe(true); + expect(result.status).toBe(502); + }); + + it("reports network errors without throwing", async () => { + fetchMock.mockRejectedValue(new Error("boom")); + + const result = JSON.parse(await provider.scoutNewTokens(mockWallet, {})); + + expect(result.error).toBe(true); + expect(result.message).toContain("boom"); + }); + }); + + describe("checkTokenSafety", () => { + it("builds the path from the address", async () => { + fetchMock.mockResolvedValue({ ok: true, text: jest.fn().mockResolvedValue("{}") }); + const address = "0x940181a94A35A4569E4529A3CDfB74e38FD98631"; + + await provider.checkTokenSafety(mockWallet, { address }); + + expect(fetchMock).toHaveBeenCalledWith(`https://agenttoll.app/api/base/safety/${address}`, { + method: "GET", + }); + }); + }); + + describe("getWalletPortfolio", () => { + it("passes the optional floor and limit", async () => { + fetchMock.mockResolvedValue({ ok: true, text: jest.fn().mockResolvedValue("{}") }); + const address = "0xe55359021A6A22D8385b827405991c56075F56f8"; + + await provider.getWalletPortfolio(mockWallet, { address, minValue: 100, limit: 5 }); + + expect(fetchMock).toHaveBeenCalledWith( + `https://agenttoll.app/api/base/portfolio/${address}?minValue=100&limit=5`, + { method: "GET" }, + ); + }); + }); + + describe("resolveBasename", () => { + it("URL-encodes the query", async () => { + fetchMock.mockResolvedValue({ ok: true, text: jest.fn().mockResolvedValue("{}") }); + + await provider.resolveBasename(mockWallet, { query: "jesse.base.eth" }); + + expect(fetchMock).toHaveBeenCalledWith("https://agenttoll.app/api/base/name/jesse.base.eth", { + method: "GET", + }); + }); + }); + + describe("getMarketBrief", () => { + it("joins symbols into one parameter", async () => { + fetchMock.mockResolvedValue({ ok: true, text: jest.fn().mockResolvedValue("{}") }); + + await provider.getMarketBrief(mockWallet, { symbols: ["eth", "degen"] }); + + expect(fetchMock).toHaveBeenCalledWith( + "https://agenttoll.app/api/brief?symbols=eth%2Cdegen", + { + method: "GET", + }, + ); + }); + }); + + describe("supportsNetwork", () => { + it("supports base-mainnet only", () => { + expect(provider.supportsNetwork({ protocolFamily: "evm", networkId: "base-mainnet" })).toBe( + true, + ); + expect(provider.supportsNetwork({ protocolFamily: "evm", networkId: "base-sepolia" })).toBe( + false, + ); + expect( + provider.supportsNetwork({ protocolFamily: "evm", networkId: "ethereum-mainnet" }), + ).toBe(false); + }); + }); + + describe("config", () => { + it("honors a base URL override", async () => { + fetchMock.mockResolvedValue({ ok: true, text: jest.fn().mockResolvedValue("{}") }); + const custom = agenttollActionProvider({ baseUrl: "https://example.test/" }); + + await custom.getMarketBrief(mockWallet, {}); + + expect(fetchMock).toHaveBeenCalledWith("https://example.test/api/brief", { method: "GET" }); + }); + }); +}); diff --git a/typescript/agentkit/src/action-providers/agenttoll/agenttollActionProvider.ts b/typescript/agentkit/src/action-providers/agenttoll/agenttollActionProvider.ts new file mode 100644 index 000000000..dbe49dca2 --- /dev/null +++ b/typescript/agentkit/src/action-providers/agenttoll/agenttollActionProvider.ts @@ -0,0 +1,260 @@ +import { z } from "zod"; +import { ActionProvider } from "../actionProvider"; +import { Network } from "../../network"; +import { CreateAction } from "../actionDecorator"; +import { EvmWalletProvider } from "../../wallet-providers"; +import { x402Client, wrapFetchWithPayment } from "@x402/fetch"; +import { registerExactEvmScheme } from "@x402/evm/exact/client"; +import { + ScoutNewTokensSchema, + TokenSafetySchema, + PortfolioSchema, + TokenPriceSchema, + BasenameSchema, + MarketBriefSchema, +} from "./schemas"; + +const DEFAULT_BASE_URL = "https://agenttoll.app"; +const SUPPORTED_NETWORKS = ["base-mainnet"]; + +/** + * Configuration for AgenttollActionProvider. + */ +export interface AgenttollConfig { + /** API base URL override (default: https://agenttoll.app) */ + baseUrl?: string; +} + +/** + * AgenttollActionProvider exposes AgentToll's Base-native data APIs as actions. + * + * AgentToll (https://agenttoll.app) sells onchain Base data pay-per-call over + * x402: each action costs $0.001-$0.008 in USDC, paid automatically from the + * agent's wallet. There are no API keys or accounts, and a request that fails + * is never charged — settlement only happens when data is returned. + */ +export class AgenttollActionProvider extends ActionProvider { + private readonly baseUrl: string; + + /** + * Creates a new AgenttollActionProvider. + * + * @param config - Optional configuration (API base URL override) + */ + constructor(config: AgenttollConfig = {}) { + super("agenttoll", []); + this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, ""); + } + + /** + * Scouts new Base tokens: fresh pools with a safety verdict attached. + * + * @param walletProvider - The wallet that pays for the call + * @param args - Optional liquidity floor and pool count + * @returns JSON string with pools, per-pool safety verdicts, and a summary + */ + @CreateAction({ + name: "scout_new_base_tokens", + description: `Find tokens that launched on Base in the last ~24 hours AND learn whether each is safe to touch, in one call. +Returns new liquidity pools above a USD floor, each with a safety verdict already attached (simulated buy & sell, buy/sell taxes, owner powers, holder concentration). +Verdicts: high-risk (a check failed), caution (warnings), insufficient-data (too new to judge - never reported as safe), clear. +A pool whose check could not run is returned with safety: null, never dropped. +Costs $0.008 in USDC via x402, paid automatically from the wallet. Not investment advice.`, + schema: ScoutNewTokensSchema, + }) + async scoutNewTokens( + walletProvider: EvmWalletProvider, + args: z.infer, + ): Promise { + return this.paidGet(walletProvider, "/api/base/scout", { + minLiquidity: args.minLiquidity, + pools: args.pools, + }); + } + + /** + * Runs automated safety checks on a Base token. + * + * @param walletProvider - The wallet that pays for the call + * @param args - The token contract address + * @returns JSON string with a verdict and the individual check results + */ + @CreateAction({ + name: "check_base_token_safety", + description: `Run automated safety checks on a Base token before touching it: a simulated buy AND sell to catch honeypots, buy/sell taxes, contract verification, what the owner can still do (mint, pause, blacklist), holder concentration, and whether anyone can still pull the liquidity. +The verdict is clear, caution, high-risk or insufficient-data - a token too new to check is never reported as clear. +Costs $0.002 in USDC via x402, paid automatically from the wallet. Not investment advice.`, + schema: TokenSafetySchema, + }) + async checkTokenSafety( + walletProvider: EvmWalletProvider, + args: z.infer, + ): Promise { + return this.paidGet(walletProvider, `/api/base/safety/${args.address}`); + } + + /** + * Values everything a Base address holds, in USD. + * + * @param walletProvider - The wallet that pays for the call + * @param args - The address plus optional spam floor and row limit + * @returns JSON string with ETH + ERC-20 holdings, totals, and honesty counters + */ + @CreateAction({ + name: "get_base_wallet_portfolio", + description: `Get everything a Base address holds, valued in USD: ETH plus its ERC-20 tokens, largest first, above a spam floor you control. +The reply also says what it did NOT count (holdings below the floor, tokens with no price) instead of quietly answering short, and marks itself partial if only a degraded data path was available. +Costs $0.003 in USDC via x402, paid automatically from the wallet.`, + schema: PortfolioSchema, + }) + async getWalletPortfolio( + walletProvider: EvmWalletProvider, + args: z.infer, + ): Promise { + return this.paidGet(walletProvider, `/api/base/portfolio/${args.address}`, { + minValue: args.minValue, + limit: args.limit, + }); + } + + /** + * Prices any Base token by contract address. + * + * @param walletProvider - The wallet that pays for the call + * @param args - The token contract address + * @returns JSON string with the USD price and its source + */ + @CreateAction({ + name: "get_base_token_price", + description: `Get the current USD price of any token on Base by its contract address, read from onchain DEX liquidity - works for tokens too new or too small for the big price APIs. +Costs $0.001 in USDC via x402, paid automatically from the wallet.`, + schema: TokenPriceSchema, + }) + async getTokenPrice( + walletProvider: EvmWalletProvider, + args: z.infer, + ): Promise { + return this.paidGet(walletProvider, `/api/base/token/${args.address}`); + } + + /** + * Resolves a Basename in either direction. + * + * @param walletProvider - The wallet that pays for the call + * @param args - A basename or a 0x address + * @returns JSON string with the resolution result + */ + @CreateAction({ + name: "resolve_basename", + description: `Resolve a Basename (Base's onchain names) in either direction: pass a name like 'jesse.base.eth' (the .base.eth suffix is optional) to get its address and text records, or pass a 0x address to get its primary basename. +Costs $0.001 in USDC via x402, paid automatically from the wallet.`, + schema: BasenameSchema, + }) + async resolveBasename( + walletProvider: EvmWalletProvider, + args: z.infer, + ): Promise { + return this.paidGet(walletProvider, `/api/base/name/${encodeURIComponent(args.query)}`); + } + + /** + * Fetches a one-call market brief. + * + * @param walletProvider - The wallet that pays for the call + * @param args - Optional list of symbols to price instead of the majors + * @returns JSON string with prices, Base gas, and market sentiment + */ + @CreateAction({ + name: "get_market_brief", + description: `Get a one-call market snapshot: spot prices (BTC/ETH/SOL by default, or up to 6 symbols you choose), current Base gas, and the crypto Fear & Greed sentiment index. +Costs $0.005 in USDC via x402 regardless of how many symbols, paid automatically from the wallet.`, + schema: MarketBriefSchema, + }) + async getMarketBrief( + walletProvider: EvmWalletProvider, + args: z.infer, + ): Promise { + return this.paidGet(walletProvider, "/api/brief", { + symbols: args.symbols?.join(","), + }); + } + + /** + * Checks whether the provider supports the given network. + * AgentToll settles USDC on Base mainnet only. + * + * @param network - The network to check + * @returns True if the network is supported + */ + supportsNetwork = (network: Network) => SUPPORTED_NETWORKS.includes(network.networkId ?? ""); + + /** + * Performs a GET request that pays the x402 quote from the agent's wallet. + * + * @param walletProvider - The wallet that signs the USDC authorization + * @param path - The API path to call + * @param query - Optional query parameters (undefined values are dropped) + * @returns The response body as a string, or a JSON error description + */ + private async paidGet( + walletProvider: EvmWalletProvider, + path: string, + query: Record = {}, + ): Promise { + try { + const client = new x402Client(); + const account = walletProvider.toSigner(); + const signer = { + ...account, + readContract: (args: { + address: `0x${string}`; + abi: readonly unknown[]; + functionName: string; + args?: readonly unknown[]; + }) => + walletProvider.readContract({ + address: args.address, + abi: args.abi as never, + functionName: args.functionName as never, + args: args.args as never, + }), + }; + registerExactEvmScheme(client, { signer }); + const fetchWithPayment = wrapFetchWithPayment(fetch, client); + + const params = new URLSearchParams(); + for (const [key, value] of Object.entries(query)) { + if (value !== undefined) params.set(key, String(value)); + } + const qs = params.toString(); + + const response = await fetchWithPayment(`${this.baseUrl}${path}${qs ? `?${qs}` : ""}`, { + method: "GET", + }); + const body = await response.text(); + if (!response.ok) { + return JSON.stringify({ + error: true, + status: response.status, + message: body.slice(0, 500), + note: "A failed request is never charged - settlement only happens when data is returned.", + }); + } + return body; + } catch (error) { + return JSON.stringify({ + error: true, + message: `Error calling AgentToll: ${error}`, + }); + } + } +} + +/** + * Creates a new AgenttollActionProvider. + * + * @param config - Optional configuration (API base URL override) + * @returns A new AgenttollActionProvider instance + */ +export const agenttollActionProvider = (config?: AgenttollConfig) => + new AgenttollActionProvider(config); diff --git a/typescript/agentkit/src/action-providers/agenttoll/index.ts b/typescript/agentkit/src/action-providers/agenttoll/index.ts new file mode 100644 index 000000000..392afd72b --- /dev/null +++ b/typescript/agentkit/src/action-providers/agenttoll/index.ts @@ -0,0 +1,2 @@ +export * from "./agenttollActionProvider"; +export * from "./schemas"; diff --git a/typescript/agentkit/src/action-providers/agenttoll/schemas.ts b/typescript/agentkit/src/action-providers/agenttoll/schemas.ts new file mode 100644 index 000000000..ac097757b --- /dev/null +++ b/typescript/agentkit/src/action-providers/agenttoll/schemas.ts @@ -0,0 +1,103 @@ +import { z } from "zod"; + +/** + * Input schema for scouting new Base tokens. + */ +export const ScoutNewTokensSchema = z + .object({ + minLiquidity: z + .number() + .min(0) + .optional() + .describe("Liquidity floor in USD for new pools (default 15000)"), + pools: z + .number() + .int() + .min(1) + .max(4) + .optional() + .describe("How many of the top new pools to safety-check (default 3)"), + }) + .strip() + .describe("Input schema for scouting new Base tokens with safety verdicts"); + +/** + * Input schema for checking a Base token's safety. + */ +export const TokenSafetySchema = z + .object({ + address: z + .string() + .regex(/^0x[0-9a-fA-F]{40}$/, "Must be a 0x-prefixed 40-hex-character address") + .describe("Token contract address on Base"), + }) + .strip() + .describe("Input schema for token safety checks"); + +/** + * Input schema for reading a Base wallet portfolio. + */ +export const PortfolioSchema = z + .object({ + address: z + .string() + .regex(/^0x[0-9a-fA-F]{40}$/, "Must be a 0x-prefixed 40-hex-character address") + .describe("Wallet address on Base"), + minValue: z + .number() + .min(0) + .optional() + .describe("USD floor per holding, filters airdropped spam (default 1)"), + limit: z + .number() + .int() + .min(1) + .max(50) + .optional() + .describe("How many holdings to list, largest first (default 20)"), + }) + .strip() + .describe("Input schema for wallet portfolio valuation"); + +/** + * Input schema for pricing a Base token by contract address. + */ +export const TokenPriceSchema = z + .object({ + address: z + .string() + .regex(/^0x[0-9a-fA-F]{40}$/, "Must be a 0x-prefixed 40-hex-character address") + .describe("Token contract address on Base"), + }) + .strip() + .describe("Input schema for onchain token pricing"); + +/** + * Input schema for Basename resolution. + */ +export const BasenameSchema = z + .object({ + query: z + .string() + .min(1) + .max(255) + .describe( + "A basename (e.g. 'jesse.base.eth' — the .base.eth suffix is optional) or a 0x address to reverse-resolve", + ), + }) + .strip() + .describe("Input schema for Basename resolution"); + +/** + * Input schema for the one-call market brief. + */ +export const MarketBriefSchema = z + .object({ + symbols: z + .array(z.string().regex(/^[a-zA-Z0-9][a-zA-Z0-9-]{0,31}$/)) + .max(6) + .optional() + .describe("Tickers or CoinGecko ids to price instead of the default BTC/ETH/SOL, up to 6"), + }) + .strip() + .describe("Input schema for the market brief"); diff --git a/typescript/agentkit/src/action-providers/index.ts b/typescript/agentkit/src/action-providers/index.ts index 9f7164086..150d7d2ff 100644 --- a/typescript/agentkit/src/action-providers/index.ts +++ b/typescript/agentkit/src/action-providers/index.ts @@ -1,43 +1,44 @@ -export * from "./actionDecorator"; -export * from "./actionProvider"; - -export * from "./customActionProvider"; - -export * from "./across"; -export * from "./alchemy"; -export * from "./baseAccount"; -export * from "./basename"; -export * from "./cdp"; -export * from "./clanker"; -export * from "./compound"; -export * from "./defillama"; -export * from "./dtelecom"; -export * from "./enso"; -export * from "./erc20"; -export * from "./erc721"; -export * from "./erc8004"; -export * from "./farcaster"; -export * from "./jupiter"; -export * from "./messari"; -export * from "./pyth"; -export * from "./moonwell"; -export * from "./morpho"; -export * from "./opensea"; -export * from "./spl"; -export * from "./superfluid"; -export * from "./sushi"; -export * from "./truemarkets"; -export * from "./twitter"; -export * from "./wallet"; -export * from "./weth"; -export * from "./wow"; -export * from "./allora"; -export * from "./flaunch"; -export * from "./onramp"; -export * from "./vaultsfyi"; -export * from "./x402"; -export * from "./yelay"; -export * from "./zerion"; -export * from "./zerodev"; -export * from "./zeroX"; -export * from "./zora"; +export * from "./actionDecorator"; +export * from "./actionProvider"; + +export * from "./customActionProvider"; + +export * from "./across"; +export * from "./agenttoll"; +export * from "./alchemy"; +export * from "./baseAccount"; +export * from "./basename"; +export * from "./cdp"; +export * from "./clanker"; +export * from "./compound"; +export * from "./defillama"; +export * from "./dtelecom"; +export * from "./enso"; +export * from "./erc20"; +export * from "./erc721"; +export * from "./erc8004"; +export * from "./farcaster"; +export * from "./jupiter"; +export * from "./messari"; +export * from "./pyth"; +export * from "./moonwell"; +export * from "./morpho"; +export * from "./opensea"; +export * from "./spl"; +export * from "./superfluid"; +export * from "./sushi"; +export * from "./truemarkets"; +export * from "./twitter"; +export * from "./wallet"; +export * from "./weth"; +export * from "./wow"; +export * from "./allora"; +export * from "./flaunch"; +export * from "./onramp"; +export * from "./vaultsfyi"; +export * from "./x402"; +export * from "./yelay"; +export * from "./zerion"; +export * from "./zerodev"; +export * from "./zeroX"; +export * from "./zora"; From 054a691303eedee16b853525d0e03f481aca6712 Mon Sep 17 00:00:00 2001 From: Tevfik Efe AYDIN <93277682+tevfikefeaydin@users.noreply.github.com> Date: Fri, 7 Aug 2026 10:45:37 +0300 Subject: [PATCH 2/2] Correct the safety action price to $0.003 The tool description and README listed $0.002 for check_base_token_safety; the endpoint charges $0.003. Also notes the deployer-history check the endpoint now runs. --- typescript/agentkit/src/action-providers/agenttoll/README.md | 2 +- .../src/action-providers/agenttoll/agenttollActionProvider.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/typescript/agentkit/src/action-providers/agenttoll/README.md b/typescript/agentkit/src/action-providers/agenttoll/README.md index e782e9076..cd33b5d8f 100644 --- a/typescript/agentkit/src/action-providers/agenttoll/README.md +++ b/typescript/agentkit/src/action-providers/agenttoll/README.md @@ -13,7 +13,7 @@ through the Coinbase CDP facilitator on Base mainnet. | Action | What it answers | Price | |---|---|---| | `scout_new_base_tokens` | What launched on Base today, and is any of it safe to touch? New pools with a safety verdict attached | $0.008 | -| `check_base_token_safety` | Is this token a honeypot? Simulated buy & sell, taxes, owner powers, holder concentration | $0.002 | +| `check_base_token_safety` | Is this token a honeypot? Simulated buy & sell, taxes, owner powers, holder concentration, deployer history | $0.003 | | `get_base_wallet_portfolio` | What does this address hold, in USD? ETH + ERC-20s, largest first, spam floor | $0.003 | | `get_base_token_price` | What is this token worth right now? Priced from onchain DEX liquidity | $0.001 | | `resolve_basename` | Who is `jesse.base.eth`? Name → address + records, or address → primary name | $0.001 | diff --git a/typescript/agentkit/src/action-providers/agenttoll/agenttollActionProvider.ts b/typescript/agentkit/src/action-providers/agenttoll/agenttollActionProvider.ts index dbe49dca2..88591a02d 100644 --- a/typescript/agentkit/src/action-providers/agenttoll/agenttollActionProvider.ts +++ b/typescript/agentkit/src/action-providers/agenttoll/agenttollActionProvider.ts @@ -83,7 +83,7 @@ Costs $0.008 in USDC via x402, paid automatically from the wallet. Not investmen name: "check_base_token_safety", description: `Run automated safety checks on a Base token before touching it: a simulated buy AND sell to catch honeypots, buy/sell taxes, contract verification, what the owner can still do (mint, pause, blacklist), holder concentration, and whether anyone can still pull the liquidity. The verdict is clear, caution, high-risk or insufficient-data - a token too new to check is never reported as clear. -Costs $0.002 in USDC via x402, paid automatically from the wallet. Not investment advice.`, +Costs $0.003 in USDC via x402, paid automatically from the wallet. Not investment advice.`, schema: TokenSafetySchema, }) async checkTokenSafety(