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..5f67eda --- /dev/null +++ b/packages/langchain/src/tools/x402search.ts @@ -0,0 +1,92 @@ +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 & { + limit?: number; +}; + +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 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") -> 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") -> 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(); + } +}