From 07fa0420e48e4a7d61bccee662ec38df56953d2a Mon Sep 17 00:00:00 2001 From: x402-index Date: Fri, 20 Mar 2026 09:58:43 +0200 Subject: [PATCH 1/2] feat(langchain): add X402SearchTool for API discovery --- packages/langchain/src/tools.ts | 4 ++- packages/langchain/src/tools/x402search.ts | 30 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 packages/langchain/src/tools/x402search.ts diff --git a/packages/langchain/src/tools.ts b/packages/langchain/src/tools.ts index 22fa9c3..8217296 100644 --- a/packages/langchain/src/tools.ts +++ b/packages/langchain/src/tools.ts @@ -114,4 +114,6 @@ export class DataAnalysisTool extends X402Tool { apiUrl: 'http://localhost:3001/api/analyze', }); } -} \ No newline at end of file +} + +export { X402SearchTool } from './tools/x402search'; \ No newline at end of file diff --git a/packages/langchain/src/tools/x402search.ts b/packages/langchain/src/tools/x402search.ts new file mode 100644 index 0000000..41f8159 --- /dev/null +++ b/packages/langchain/src/tools/x402search.ts @@ -0,0 +1,30 @@ +import { X402Tool, X402ToolConfig } from '../tools'; + +const X402SEARCH_URL = 'https://x402search.xyz/v1/search'; + +export type X402SearchToolConfig = Omit & { + limit?: number; +}; + +export class X402SearchTool extends X402Tool { + constructor(config: X402SearchToolConfig) { + super({ + ...config, + toolName: 'search_apis', + toolDescription: `Search for API services and data providers by natural language capability query. +Searches 14,000+ indexed APIs across crypto, DeFi, NFT, weather, finance, AI, and more. +Returns matching services with names, descriptions, and endpoints. +Cost: $0.01 USDC per query via x402 protocol on Base mainnet — paid automatically. + +Coinbase Bazaar lists services. x402search searches them by capability — complementary, not competing. + +Examples: +- search_apis("token price") -> 88 results including CoinGecko, CryptoCompare +- search_apis("crypto market data") -> 10 focused results +- search_apis("NFT metadata") -> NFT-related APIs +- search_apis("btc price") -> 8 targeted results`, + apiUrl: X402SEARCH_URL, + defaultParams: { limit: config.limit ?? 5 }, + }); + } +} From a06e2a849508f41fc4f0fa992bfe74efee8f9194 Mon Sep 17 00:00:00 2001 From: x402-index Date: Sun, 22 Mar 2026 17:35:58 +0200 Subject: [PATCH 2/2] fix(x402search): use StructuredTool, fix query params, enforce Base mainnet chainId --- packages/langchain/src/tools/x402search.ts | 90 ++++++++++++++++++---- 1 file changed, 76 insertions(+), 14 deletions(-) diff --git a/packages/langchain/src/tools/x402search.ts b/packages/langchain/src/tools/x402search.ts index 41f8159..5f67eda 100644 --- a/packages/langchain/src/tools/x402search.ts +++ b/packages/langchain/src/tools/x402search.ts @@ -1,30 +1,92 @@ -import { X402Tool, X402ToolConfig } from '../tools'; +import { StructuredTool } from '@langchain/core/tools'; +import { z } from 'zod'; +import { X402AgentClient, AgentPaymentConfig } from '@xpaysh/agent-kit-core'; const X402SEARCH_URL = 'https://x402search.xyz/v1/search'; +const X402SEARCH_CHAIN_ID = 8453; // Base mainnet — required for x402search payments -export type X402SearchToolConfig = Omit & { +export type X402SearchToolConfig = Omit & { limit?: number; }; -export class X402SearchTool extends X402Tool { - constructor(config: X402SearchToolConfig) { - super({ - ...config, - toolName: 'search_apis', - toolDescription: `Search for API services and data providers by natural language capability query. +const X402SearchSchema = z.object({ + query: z.string().describe('Natural language search query, e.g. "btc price" or "NFT metadata"'), +}); + +export class X402SearchTool extends StructuredTool { + name = 'search_apis'; + description = `Search for API services and data providers by natural language capability query. Searches 14,000+ indexed APIs across crypto, DeFi, NFT, weather, finance, AI, and more. -Returns matching services with names, descriptions, and endpoints. +Returns matching services with endpoints and payment metadata. Cost: $0.01 USDC per query via x402 protocol on Base mainnet — paid automatically. Coinbase Bazaar lists services. x402search searches them by capability — complementary, not competing. Examples: -- search_apis("token price") -> 88 results including CoinGecko, CryptoCompare -- search_apis("crypto market data") -> 10 focused results +- search_apis("token price") -> price feeds including CoinGecko, try402.fun +- search_apis("crypto market data") -> CoinGecko, Heyanon, analytics APIs - search_apis("NFT metadata") -> NFT-related APIs -- search_apis("btc price") -> 8 targeted results`, - apiUrl: X402SEARCH_URL, - defaultParams: { limit: config.limit ?? 5 }, +- search_apis("btc price") -> targeted BTC price feeds`; + + schema = X402SearchSchema; + + private client: X402AgentClient; + private limit: number; + + constructor(config: X402SearchToolConfig) { + super(); + this.limit = config.limit ?? 5; + this.client = new X402AgentClient({ + ...config, + chainId: X402SEARCH_CHAIN_ID, }); } + + async _call(input: z.infer): Promise { + const url = `${X402SEARCH_URL}?q=${encodeURIComponent(input.query)}&limit=${this.limit}`; + + try { + const response = await this.client.makePayedCall({ url, method: 'GET' }); + const data = response.data; + const results = Array.isArray(data) ? data : (data?.results ?? []); + + if (!results.length) { + return JSON.stringify({ + success: true, + query: input.query, + results: [], + message: `No APIs found for '${input.query}'. Try broader terms: 'crypto' or 'token price'.`, + }); + } + + const formatted = results.slice(0, this.limit).map((r: any) => ({ + url: r.resource_url, + rank: r.rank, + accepts: (r.accepts ?? []).map((a: any) => ({ + network: a.network, + max_amount: a.max_amount, + payTo: a.payTo, + })), + })); + + return JSON.stringify({ + success: true, + query: input.query, + count: formatted.length, + payment: { cost: response.cost, currency: response.currency, hash: response.paymentHash }, + results: formatted, + }, null, 2); + + } catch (error: any) { + return JSON.stringify({ + success: false, + error: `x402search request failed: ${error.message}`, + hint: 'Ensure the wallet has USDC on Base mainnet (eip155:8453).', + }); + } + } + + getSpendingStats() { + return this.client.getSpendingStats(); + } }