@sherwoodagent/cli 0.64.1 → 0.65.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agent-IVESTCYM.js → agent-AETROOEW.js} +2 -2
- package/dist/{chunk-J42NNFUV.js → chunk-RO26TXXE.js} +39 -20
- package/dist/chunk-RO26TXXE.js.map +1 -0
- package/dist/index.js +4302 -4093
- package/dist/index.js.map +1 -1
- package/dist/{research-RL2ASMQ5.js → research-OGMEJBX3.js} +2 -2
- package/dist/{research-N3R5MU6Q.js → research-XEXTHDT3.js} +2 -2
- package/dist/{trade-AJNB4ULF.js → trade-5KIGBEOP.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-J42NNFUV.js.map +0 -1
- /package/dist/{agent-IVESTCYM.js.map → agent-AETROOEW.js.map} +0 -0
- /package/dist/{research-RL2ASMQ5.js.map → research-OGMEJBX3.js.map} +0 -0
- /package/dist/{research-N3R5MU6Q.js.map → research-XEXTHDT3.js.map} +0 -0
- /package/dist/{trade-AJNB4ULF.js.map → trade-5KIGBEOP.js.map} +0 -0
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
import {
|
|
13
13
|
getResearchProvider,
|
|
14
14
|
isX402WalletFunded
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-RO26TXXE.js";
|
|
16
16
|
import {
|
|
17
17
|
HyperliquidProvider,
|
|
18
18
|
calculateATR,
|
|
@@ -9550,4 +9550,4 @@ function formatFearGreed(value) {
|
|
|
9550
9550
|
export {
|
|
9551
9551
|
registerAgentCommands
|
|
9552
9552
|
};
|
|
9553
|
-
//# sourceMappingURL=agent-
|
|
9553
|
+
//# sourceMappingURL=agent-AETROOEW.js.map
|
|
@@ -357,10 +357,14 @@ var NansenProvider = class {
|
|
|
357
357
|
* Endpoint: POST /api/v1/smart-money/netflow
|
|
358
358
|
* Cost: ~$0.06 (premium tier)
|
|
359
359
|
*
|
|
360
|
-
* Queries across all major chains (ethereum, solana, base, arbitrum, etc.)
|
|
361
|
-
*
|
|
362
|
-
*
|
|
363
|
-
*
|
|
360
|
+
* Queries across all major chains (ethereum, solana, base, arbitrum, etc.).
|
|
361
|
+
* The API returns per-chain rows so we get flows across ethereum, solana,
|
|
362
|
+
* base, L2s, etc.
|
|
363
|
+
*
|
|
364
|
+
* The netflow endpoint filters by `token_address` (string or array), NOT by
|
|
365
|
+
* `token_symbol` — passing `token_symbol` yields 422 "Unknown field". So we
|
|
366
|
+
* first resolve the symbol to its per-chain contract address(es) via the
|
|
367
|
+
* token screener, then filter netflow by those addresses.
|
|
364
368
|
*
|
|
365
369
|
* Response includes net_flow_1h/24h/7d/30d in USD per token+chain,
|
|
366
370
|
* plus trader_count (active smart money wallets in 30d window).
|
|
@@ -393,12 +397,23 @@ var NansenProvider = class {
|
|
|
393
397
|
jupiter: "JUP"
|
|
394
398
|
};
|
|
395
399
|
const symbol = symbolMap[target.toLowerCase()] ?? target.toUpperCase();
|
|
400
|
+
const isAddr = target.startsWith("0x") && target.length === 42;
|
|
401
|
+
const tokenAddresses = isAddr ? [target] : await this.resolveTokenAddresses(symbol);
|
|
402
|
+
if (tokenAddresses.length === 0) {
|
|
403
|
+
return {
|
|
404
|
+
provider: "nansen",
|
|
405
|
+
queryType: "smart-money",
|
|
406
|
+
target,
|
|
407
|
+
data: { flows: [], count: 0 },
|
|
408
|
+
costUsdc: "0",
|
|
409
|
+
timestamp: Math.floor(Date.now() / 1e3)
|
|
410
|
+
};
|
|
411
|
+
}
|
|
396
412
|
const body = {
|
|
397
|
-
// Query all supported smart-money chains — the API returns per-chain
|
|
398
|
-
// rows so we get flows across ethereum, solana, base, L2s, etc.
|
|
413
|
+
// Query all supported smart-money chains — the API returns per-chain rows.
|
|
399
414
|
chains: ["ethereum", "solana", "base", "arbitrum", "optimism", "polygon", "avalanche", "bnb"],
|
|
400
415
|
filters: {
|
|
401
|
-
|
|
416
|
+
token_address: tokenAddresses
|
|
402
417
|
},
|
|
403
418
|
order_by: [{ field: "net_flow_24h_usd", direction: "DESC" }],
|
|
404
419
|
pagination: { page: 1, per_page: 10 }
|
|
@@ -542,29 +557,33 @@ var NansenProvider = class {
|
|
|
542
557
|
};
|
|
543
558
|
}
|
|
544
559
|
/**
|
|
545
|
-
* Resolve a token symbol
|
|
546
|
-
*
|
|
547
|
-
*
|
|
560
|
+
* Resolve a token symbol to its per-chain contract address(es) via the
|
|
561
|
+
* token screener endpoint (~$0.01). Returns a deduped list across the major
|
|
562
|
+
* smart-money chains so the netflow filter (token_address only) can match
|
|
563
|
+
* the token wherever it trades.
|
|
564
|
+
*
|
|
565
|
+
* The screener caps `chains` at 5 items, so we query the highest-liquidity
|
|
566
|
+
* smart-money chains. Returns an empty array if the symbol resolves to
|
|
567
|
+
* nothing (unknown token) or the lookup fails.
|
|
548
568
|
*/
|
|
549
|
-
async
|
|
550
|
-
if (target.startsWith("0x") && target.length === 42) {
|
|
551
|
-
return target;
|
|
552
|
-
}
|
|
569
|
+
async resolveTokenAddresses(symbol) {
|
|
553
570
|
const fetchWithPay = await getNansenFetch();
|
|
554
571
|
const body = {
|
|
555
|
-
chains
|
|
572
|
+
// Screener allows at most 5 chains per request.
|
|
573
|
+
chains: ["ethereum", "base", "arbitrum", "solana", "bnb"],
|
|
556
574
|
timeframe: "24h",
|
|
557
|
-
filters: { token_symbol: [
|
|
558
|
-
pagination: { page: 1, records_per_page:
|
|
575
|
+
filters: { token_symbol: [symbol.toUpperCase()] },
|
|
576
|
+
pagination: { page: 1, records_per_page: 25 }
|
|
559
577
|
};
|
|
560
578
|
const res = await fetchWithPay(`${BASE_URL2}/api/v1/token-screener`, {
|
|
561
579
|
method: "POST",
|
|
562
580
|
headers: { "Content-Type": "application/json" },
|
|
563
581
|
body: JSON.stringify(body)
|
|
564
582
|
});
|
|
565
|
-
if (!res.ok) return
|
|
583
|
+
if (!res.ok) return [];
|
|
566
584
|
const json = await res.json();
|
|
567
|
-
|
|
585
|
+
const addresses = (json.data ?? []).map((row) => row.token_address).filter((addr) => typeof addr === "string" && addr.length > 0);
|
|
586
|
+
return [...new Set(addresses)];
|
|
568
587
|
}
|
|
569
588
|
/**
|
|
570
589
|
* Extract cost from x402 response headers.
|
|
@@ -616,4 +635,4 @@ export {
|
|
|
616
635
|
NansenProvider,
|
|
617
636
|
getResearchProvider
|
|
618
637
|
};
|
|
619
|
-
//# sourceMappingURL=chunk-
|
|
638
|
+
//# sourceMappingURL=chunk-RO26TXXE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/providers/research/messari.ts","../src/lib/x402.ts","../src/providers/research/nansen.ts","../src/providers/research/index.ts"],"sourcesContent":["/**\n * Messari research provider — x402 micropayments for crypto market data.\n *\n * Docs: https://docs.messari.io\n * Payment: x402 (USDC on Base) — no API key required\n * Data: 34,000+ assets, market metrics, asset profiles\n * Pricing: $0.10/call for asset details, ROI, ATH. $0.15–$0.35 for timeseries.\n * $0.55 for news/signals. Full pricing: https://docs.messari.io/api-reference/x402-payments\n *\n * Supports:\n * token → asset details (description, category, sector, links, market snapshot)\n * market → market metrics + ATH (price, volume, market cap, ROI, ATH, cycle low)\n *\n * Not supported (use --provider nansen instead):\n * smart-money → on-chain analytics not available in Messari x402 API\n * wallet → wallet profiling not available in Messari x402 API\n */\n\nimport { base, baseSepolia } from \"viem/chains\";\nimport type { ProviderInfo } from \"../../types.js\";\nimport type { ResearchProvider, ResearchQuery, ResearchResult } from \"./index.js\";\nimport { getX402Fetch } from \"../../lib/x402.js\";\n\nconst BASE_URL = \"https://api.messari.io\";\n\n/** Known x402 cost per Messari query (approximate). */\nexport const MESSARI_COST_ESTIMATE: Record<string, string> = {\n token: \"~$0.10\",\n market: \"~$0.20\",\n};\n\nexport class MessariProvider implements ResearchProvider {\n info(): ProviderInfo {\n return {\n name: \"messari\",\n type: \"research\",\n capabilities: [\n \"research.token\",\n \"research.market\",\n ],\n supportedChains: [base, baseSepolia],\n };\n }\n\n async query(params: ResearchQuery): Promise<ResearchResult> {\n switch (params.type) {\n case \"token\":\n return this.tokenReport(params.target);\n case \"market\":\n return this.marketOverview(params.target);\n case \"smart-money\":\n throw new Error(\n \"Messari x402 API does not support on-chain analytics. Use --provider nansen for smart money data.\",\n );\n case \"wallet\":\n throw new Error(\n \"Messari does not support wallet analytics. Use --provider nansen for wallet profiling.\",\n );\n default:\n throw new Error(`Unsupported query type: ${params.type}`);\n }\n }\n\n /**\n * Resolve any user input (symbol, name, slug, address) to a Messari asset slug.\n * Uses the free /metrics/v2/assets endpoint ($0.00) to search.\n */\n private async resolveSlug(target: string): Promise<string> {\n const fetchWithPay = await getX402Fetch();\n const params = new URLSearchParams({\n search: target,\n limit: \"1\",\n });\n const url = `${BASE_URL}/metrics/v2/assets?${params}`;\n\n const res = await fetchWithPay(url, { method: \"GET\" });\n if (!res.ok) {\n throw new Error(\n `Messari asset lookup failed: ${res.status} ${res.statusText}`,\n );\n }\n\n const json = (await res.json()) as {\n data?: Array<{ slug?: string }>;\n };\n\n const slug = json.data?.[0]?.slug;\n if (!slug) {\n throw new Error(\n `No Messari asset found for \"${target}\". Try a different name, symbol, or slug.`,\n );\n }\n return slug;\n }\n\n /**\n * Get asset details: description, category, sector, links, market snapshot.\n * Endpoint: GET /metrics/v2/assets/details?assetIDs={slug} ($0.10)\n */\n private async tokenReport(target: string): Promise<ResearchResult> {\n const slug = await this.resolveSlug(target);\n const fetchWithPay = await getX402Fetch();\n const url = `${BASE_URL}/metrics/v2/assets/details?assetIDs=${encodeURIComponent(slug)}`;\n\n const res = await fetchWithPay(url, { method: \"GET\" });\n if (!res.ok) {\n throw new Error(\n `Messari token query failed: ${res.status} ${res.statusText}`,\n );\n }\n\n const json = (await res.json()) as {\n data?: Array<Record<string, unknown>>;\n };\n const costUsdc = this.extractCost(res, \"token\");\n const asset = json.data?.[0] ?? {};\n\n return {\n provider: \"messari\",\n queryType: \"token\",\n target,\n data: asset,\n costUsdc,\n timestamp: Math.floor(Date.now() / 1000),\n };\n }\n\n /**\n * Get market metrics + ATH: price, volume, market cap, ROI, all-time high, cycle low.\n * Makes two parallel calls:\n * GET /metrics/v2/assets/details?assetIDs={slug} ($0.10)\n * GET /metrics/v2/assets/ath?assetIDs={slug} ($0.10)\n * Total: ~$0.20\n */\n private async marketOverview(target: string): Promise<ResearchResult> {\n const slug = await this.resolveSlug(target);\n const fetchWithPay = await getX402Fetch();\n const assetParam = encodeURIComponent(slug);\n\n const [detailsRes, athRes] = await Promise.all([\n fetchWithPay(`${BASE_URL}/metrics/v2/assets/details?assetIDs=${assetParam}`, { method: \"GET\" }),\n fetchWithPay(`${BASE_URL}/metrics/v2/assets/ath?assetIDs=${assetParam}`, { method: \"GET\" }),\n ]);\n\n if (!detailsRes.ok) {\n throw new Error(\n `Messari market query failed: ${detailsRes.status} ${detailsRes.statusText}`,\n );\n }\n if (!athRes.ok) {\n throw new Error(\n `Messari ATH query failed: ${athRes.status} ${athRes.statusText}`,\n );\n }\n\n const detailsJson = (await detailsRes.json()) as {\n data?: Array<Record<string, unknown>>;\n };\n const athJson = (await athRes.json()) as {\n data?: Array<Record<string, unknown>>;\n };\n\n // Sum costs from both responses\n const cost1 = this.extractCostRaw(detailsRes);\n const cost2 = this.extractCostRaw(athRes);\n const totalCost = cost1 + cost2;\n const costUsdc = totalCost > 0\n ? totalCost.toFixed(4)\n : MESSARI_COST_ESTIMATE[\"market\"]?.replace(\"~$\", \"\") ?? \"unknown\";\n\n const details = detailsJson.data?.[0] ?? {};\n const ath = athJson.data?.[0] ?? {};\n\n return {\n provider: \"messari\",\n queryType: \"market\",\n target,\n data: {\n ...details,\n allTimeHigh: ath.allTimeHigh ?? null,\n },\n costUsdc,\n timestamp: Math.floor(Date.now() / 1000),\n };\n }\n\n /**\n * Extract cost from x402 response headers as a number (USDC).\n * Returns 0 if no payment info found.\n */\n private extractCostRaw(res: Response): number {\n const paymentResponse = res.headers.get(\"payment-response\");\n if (paymentResponse) {\n try {\n const parsed = JSON.parse(paymentResponse) as { amount?: string };\n if (parsed.amount) {\n return Number(parsed.amount) / 1e6;\n }\n } catch {\n // Fall through\n }\n }\n return 0;\n }\n\n /**\n * Extract cost from x402 response headers as a formatted string.\n * Falls back to the known estimate for the query type when headers are absent.\n */\n private extractCost(res: Response, queryType: string = \"token\"): string {\n const cost = this.extractCostRaw(res);\n if (cost > 0) return cost.toFixed(4);\n\n // Fall back to known estimate (strip \"~$\" prefix)\n const est = MESSARI_COST_ESTIMATE[queryType];\n if (est) return est.replace(\"~$\", \"\");\n\n return \"unknown\";\n }\n}\n","/**\n * x402 fetch wrapper — wraps native fetch with automatic USDC micropayments.\n *\n * Uses the Coinbase x402 protocol: when a server responds 402 Payment Required,\n * the wrapper automatically signs a USDC payment on Base and retries the request.\n * The agent pays from its own wallet — no vault interaction needed.\n *\n * Singleton pattern matching client.ts — cached after first creation.\n */\n\nimport { getAccount } from \"./client.js\";\n\nlet _x402Fetch: typeof fetch | null = null;\n\n/**\n * Returns a fetch function that automatically handles x402 (402 Payment Required)\n * responses by signing USDC micropayments on Base.\n *\n * Lazily initializes the x402 client on first call and caches it.\n * Uses dynamic imports so @x402 packages are only loaded when research commands run.\n */\nexport async function getX402Fetch(): Promise<typeof fetch> {\n if (_x402Fetch) return _x402Fetch;\n\n const { x402Client, wrapFetchWithPayment } = await import(\"@x402/fetch\");\n const { registerExactEvmScheme } = await import(\"@x402/evm/exact/client\");\n\n const signer = getAccount();\n const client = new x402Client();\n registerExactEvmScheme(client, { signer });\n\n _x402Fetch = wrapFetchWithPayment(fetch, client) as typeof fetch;\n return _x402Fetch;\n}\n\n/**\n * Reset cached x402 fetch. Required for tests that change accounts.\n */\nexport function resetX402Fetch(): void {\n _x402Fetch = null;\n}\n\n// ── x402 USDC balance check ──\n\n/** USDC on Base mainnet. */\nconst BASE_USDC_ADDRESS = \"0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913\" as const;\n\n/** Minimum USDC balance (in 6-decimal units) to consider x402 available. $0.50 */\nconst MIN_USDC_BALANCE = 500_000n; // 0.50 USDC (6 decimals)\n\n/** Cache: { balance, timestamp }. Refreshed at most once per scan cycle. */\nlet _balanceCache: { available: boolean; timestamp: number } | null = null;\nconst BALANCE_CACHE_TTL_MS = 60_000; // 1 minute — covers a full scan cycle\n\n/**\n * Check whether the cron wallet has enough USDC on Base to pay for x402 requests.\n * Result is cached for 60s so we only make one RPC call per scan cycle.\n * On RPC error, returns true (assume available — don't break scoring).\n */\nexport async function isX402WalletFunded(): Promise<boolean> {\n // Return cached result if fresh\n if (_balanceCache && Date.now() - _balanceCache.timestamp < BALANCE_CACHE_TTL_MS) {\n return _balanceCache.available;\n }\n\n try {\n const { createPublicClient, http } = await import(\"viem\");\n const { base } = await import(\"viem/chains\");\n\n const account = getAccount();\n const client = createPublicClient({\n chain: base,\n transport: http(\"https://base-rpc.publicnode.com\"),\n });\n\n // ERC-20 balanceOf(address) — minimal ABI\n const balance = await client.readContract({\n address: BASE_USDC_ADDRESS,\n abi: [\n {\n name: \"balanceOf\",\n type: \"function\",\n stateMutability: \"view\",\n inputs: [{ name: \"account\", type: \"address\" }],\n outputs: [{ name: \"\", type: \"uint256\" }],\n },\n ] as const,\n functionName: \"balanceOf\",\n args: [account.address],\n });\n\n const available = (balance as bigint) >= MIN_USDC_BALANCE;\n _balanceCache = { available, timestamp: Date.now() };\n return available;\n } catch (err) {\n // RPC failure — assume funded so we don't break scoring\n console.error(`x402 balance check failed (assuming available): ${(err as Error).message}`);\n _balanceCache = { available: true, timestamp: Date.now() };\n return true;\n }\n}\n\n/** Reset balance cache — for tests. */\nexport function resetBalanceCache(): void {\n _balanceCache = null;\n}\n","/**\n * Nansen research provider — supports both API key auth (Pro subscription,\n * ~5× cheaper) and x402 micropayments (pay-per-request, no subscription).\n *\n * Auth priority:\n * 1. NANSEN_API_KEY env var → standard fetch with apiKey header (Pro plan)\n * 2. x402 fetch wrapper → automatic USDC micropayments on Base\n *\n * Docs: https://docs.nansen.ai\n * Pro pricing: 5 credits/call for Smart Money endpoints (~$0.005/call)\n * x402 pricing: ~$0.06/call for Smart Money endpoints\n *\n * Supports all query types:\n * token → token screener (on-chain metrics, holder quality)\n * market → token screener sorted by market cap / volume\n * smart-money → smart money net flow from labeled wallets\n * hl-perp-trades → Hyperliquid smart-money perp trades\n * wallet → wallet profiler (PnL, tx patterns, counterparties)\n */\n\nimport { base, baseSepolia } from \"viem/chains\";\nimport type { ProviderInfo } from \"../../types.js\";\nimport type { ResearchProvider, ResearchQuery, ResearchResult } from \"./index.js\";\nimport { getX402Fetch } from \"../../lib/x402.js\";\n\nconst BASE_URL = \"https://api.nansen.ai\";\n\n/**\n * Returns a fetch function configured for Nansen auth. Cached after first\n * creation — same pattern as getX402Fetch() to avoid allocating a new\n * closure on every call.\n *\n * If NANSEN_API_KEY is set → standard fetch with apiKey header (Pro plan).\n * Otherwise → x402 micropayment fetch.\n */\nlet _nansenFetch: typeof fetch | null = null;\nlet _nansenFetchKey: string | undefined;\n\nasync function getNansenFetch(): Promise<typeof fetch> {\n const apiKey = process.env.NANSEN_API_KEY;\n\n // Cache hit — return if key hasn't changed\n if (_nansenFetch && _nansenFetchKey === apiKey) return _nansenFetch;\n\n if (apiKey) {\n const baseFetch = globalThis.fetch;\n _nansenFetch = ((url: string | URL | Request, init?: RequestInit) => {\n const headers = new Headers(init?.headers);\n headers.set(\"apiKey\", apiKey);\n return baseFetch(url, { ...init, headers });\n }) as typeof fetch;\n _nansenFetchKey = apiKey;\n } else {\n _nansenFetch = await getX402Fetch();\n _nansenFetchKey = undefined;\n }\n\n return _nansenFetch;\n}\n\n/** Known x402 cost per Nansen query type. */\nexport const NANSEN_COST_ESTIMATE: Record<string, string> = {\n token: \"~$0.01\",\n market: \"~$0.01\",\n \"smart-money\": \"~$0.06\",\n \"hl-perp-trades\": \"~$0.06\",\n wallet: \"~$0.01\",\n \"flow-intelligence\": \"~$0.005\", // 1 credit — cheapest premium endpoint\n};\n\nexport class NansenProvider implements ResearchProvider {\n info(): ProviderInfo {\n return {\n name: \"nansen\",\n type: \"research\",\n capabilities: [\n \"research.token\",\n \"research.market\",\n \"research.smart-money\",\n \"research.wallet\",\n ],\n supportedChains: [base, baseSepolia],\n };\n }\n\n async query(params: ResearchQuery): Promise<ResearchResult> {\n switch (params.type) {\n case \"token\":\n return this.tokenScreener(params.target);\n case \"market\":\n return this.marketScreener(params.target);\n case \"smart-money\":\n return this.smartMoneyNetflow(params.options?.token ?? params.target);\n case \"wallet\":\n return this.walletProfile(params.target);\n default:\n throw new Error(`Unsupported query type: ${params.type}`);\n }\n }\n\n /**\n * Token Screener — comprehensive token discovery with on-chain metrics.\n * Endpoint: POST /api/v1/token-screener\n * Cost: ~$0.01 (basic tier)\n */\n private async tokenScreener(target: string): Promise<ResearchResult> {\n const fetchWithPay = await getNansenFetch();\n\n // Determine if target is an address or symbol\n const isAddr = target.startsWith(\"0x\") && target.length === 42;\n const filters: Record<string, unknown> = isAddr\n ? { token_address: [target] }\n : { token_symbol: [target.toUpperCase()] };\n\n const body = {\n chains: [\"base\"],\n timeframe: \"24h\",\n filters,\n pagination: { page: 1, records_per_page: 10 },\n };\n\n const res = await fetchWithPay(`${BASE_URL}/api/v1/token-screener`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n throw new Error(\n `Nansen token query failed: ${res.status} ${res.statusText}`,\n );\n }\n\n const json = (await res.json()) as { data?: unknown[] };\n const costUsdc = this.extractCost(res, \"token\");\n\n return {\n provider: \"nansen\",\n queryType: \"token\",\n target,\n data: { tokens: json.data ?? [], count: (json.data ?? []).length },\n costUsdc,\n timestamp: Math.floor(Date.now() / 1000),\n };\n }\n\n /**\n * Market Screener — token screener sorted by volume/market cap for market overview.\n * Endpoint: POST /api/v1/token-screener\n * Cost: ~$0.01 (basic tier)\n */\n private async marketScreener(asset: string): Promise<ResearchResult> {\n const fetchWithPay = await getNansenFetch();\n\n const isAddr = asset.startsWith(\"0x\") && asset.length === 42;\n const filters: Record<string, unknown> = isAddr\n ? { token_address: [asset] }\n : { token_symbol: [asset.toUpperCase()] };\n\n const body = {\n chains: [\"base\"],\n timeframe: \"24h\",\n filters,\n order_by: [{ field: \"buy_volume\", direction: \"desc\" }],\n pagination: { page: 1, records_per_page: 10 },\n };\n\n const res = await fetchWithPay(`${BASE_URL}/api/v1/token-screener`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n throw new Error(\n `Nansen market query failed: ${res.status} ${res.statusText}`,\n );\n }\n\n const json = (await res.json()) as { data?: unknown[] };\n const costUsdc = this.extractCost(res, \"market\");\n\n return {\n provider: \"nansen\",\n queryType: \"market\",\n target: asset,\n data: { tokens: json.data ?? [], count: (json.data ?? []).length },\n costUsdc,\n timestamp: Math.floor(Date.now() / 1000),\n };\n }\n\n /**\n * Smart Money Net Flow — capital flow analysis from labeled wallets.\n * Endpoint: POST /api/v1/smart-money/netflow\n * Cost: ~$0.06 (premium tier)\n *\n * Queries across all major chains (ethereum, solana, base, arbitrum, etc.).\n * The API returns per-chain rows so we get flows across ethereum, solana,\n * base, L2s, etc.\n *\n * The netflow endpoint filters by `token_address` (string or array), NOT by\n * `token_symbol` — passing `token_symbol` yields 422 \"Unknown field\". So we\n * first resolve the symbol to its per-chain contract address(es) via the\n * token screener, then filter netflow by those addresses.\n *\n * Response includes net_flow_1h/24h/7d/30d in USD per token+chain,\n * plus trader_count (active smart money wallets in 30d window).\n */\n private async smartMoneyNetflow(\n target: string,\n ): Promise<ResearchResult> {\n const fetchWithPay = await getNansenFetch();\n\n // Map CoinGecko token IDs to symbols for the lookup\n const symbolMap: Record<string, string> = {\n bitcoin: \"BTC\", ethereum: \"ETH\", solana: \"SOL\",\n arbitrum: \"ARB\", aave: \"AAVE\", uniswap: \"UNI\",\n chainlink: \"LINK\", dogecoin: \"DOGE\", ripple: \"XRP\",\n polkadot: \"DOT\", avalanche: \"AVAX\", near: \"NEAR\",\n sui: \"SUI\", aptos: \"APT\", hyperliquid: \"HYPE\",\n worldcoin: \"WLD\", \"worldcoin-wld\": \"WLD\",\n bittensor: \"TAO\", zcash: \"ZEC\", fartcoin: \"FARTCOIN\",\n pepe: \"PEPE\", pendle: \"PENDLE\", jupiter: \"JUP\",\n };\n const symbol = symbolMap[target.toLowerCase()] ?? target.toUpperCase();\n\n // Resolve symbol → per-chain contract address(es). The netflow filter is\n // token_address-only. If the target is already an address, use it directly.\n const isAddr = target.startsWith(\"0x\") && target.length === 42;\n const tokenAddresses = isAddr\n ? [target]\n : await this.resolveTokenAddresses(symbol);\n\n if (tokenAddresses.length === 0) {\n // No on-chain address found for this symbol — return an empty result\n // rather than firing an unfiltered (and expensive) all-token query.\n return {\n provider: \"nansen\",\n queryType: \"smart-money\",\n target,\n data: { flows: [], count: 0 },\n costUsdc: \"0\",\n timestamp: Math.floor(Date.now() / 1000),\n };\n }\n\n const body: Record<string, unknown> = {\n // Query all supported smart-money chains — the API returns per-chain rows.\n chains: [\"ethereum\", \"solana\", \"base\", \"arbitrum\", \"optimism\", \"polygon\", \"avalanche\", \"bnb\"],\n filters: {\n token_address: tokenAddresses,\n },\n order_by: [{ field: \"net_flow_24h_usd\", direction: \"DESC\" }],\n pagination: { page: 1, per_page: 10 },\n };\n\n const res = await fetchWithPay(`${BASE_URL}/api/v1/smart-money/netflow`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n throw new Error(\n `Nansen smart-money query failed: ${res.status} ${res.statusText}`,\n );\n }\n\n const json = (await res.json()) as { data?: unknown[] };\n const costUsdc = this.extractCost(res, \"smart-money\");\n\n return {\n provider: \"nansen\",\n queryType: \"smart-money\",\n target,\n data: { flows: json.data ?? [], count: (json.data ?? []).length },\n costUsdc,\n timestamp: Math.floor(Date.now() / 1000),\n };\n }\n\n /**\n * Hyperliquid Smart Money Perp Trades — what smart wallets are trading\n * on Hyperliquid perps right now.\n * Endpoint: POST /api/v1/smart-money/perp-trades\n * Cost: ~$0.06 (premium tier, estimated)\n *\n * Returns granular trade data: direction (Long/Short), size, price, action\n * (Buy - Add Long, Sell - Open Short, etc.), trader labels (Fund, Smart Trader).\n * Directly relevant — same venue + instrument we trade.\n */\n async queryHyperliquidSmartMoney(\n tokenSymbol: string,\n ): Promise<ResearchResult> {\n const fetchWithPay = await getNansenFetch();\n\n const body = {\n filters: {\n include_smart_money_labels: [\"Fund\", \"Smart Trader\", \"Smart HL Perps Trader\"],\n token_symbol: tokenSymbol,\n value_usd: { min: 50000 }, // only meaningful-size trades\n },\n only_new_positions: false,\n pagination: { page: 1, per_page: 20 },\n order_by: [{ field: \"block_timestamp\", direction: \"DESC\" }],\n };\n\n const res = await fetchWithPay(`${BASE_URL}/api/v1/smart-money/perp-trades`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n throw new Error(`Nansen HL perp-trades query failed: ${res.status} ${res.statusText}`);\n }\n\n const json = (await res.json()) as { data?: unknown[] };\n const costUsdc = this.extractCost(res, \"smart-money\");\n\n return {\n provider: \"nansen\",\n queryType: \"hl-perp-trades\",\n target: tokenSymbol,\n data: { trades: json.data ?? [], count: (json.data ?? []).length },\n costUsdc,\n timestamp: Math.floor(Date.now() / 1000),\n };\n }\n\n /**\n * Flow Intelligence — net inflows/outflows by investor category.\n * Endpoint: POST /api/v1/tgm/flow-intelligence\n * Cost: 1 credit (~$0.005 at Pro pricing)\n *\n * Returns aggregated flow data by investor type (Smart Traders, Whales,\n * Exchanges, Top PnL). More stable than individual trade data — shows\n * accumulation/distribution trends rather than noisy per-trade signals.\n */\n async queryFlowIntelligence(\n tokenSymbol: string,\n ): Promise<ResearchResult> {\n const fetchWithPay = await getNansenFetch();\n\n const body = {\n token_symbol: tokenSymbol,\n timeframe: \"24h\",\n };\n\n const res = await fetchWithPay(`${BASE_URL}/api/v1/tgm/flow-intelligence`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n throw new Error(`Nansen flow-intelligence query failed: ${res.status} ${res.statusText}`);\n }\n\n const json = (await res.json()) as { data?: unknown };\n const costUsdc = this.extractCost(res, \"flow-intelligence\");\n\n return {\n provider: \"nansen\",\n queryType: \"flow-intelligence\",\n target: tokenSymbol,\n data: (json.data ?? {}) as Record<string, unknown>,\n costUsdc,\n timestamp: Math.floor(Date.now() / 1000),\n };\n }\n\n /**\n * Wallet Profile — PnL summary, realized/unrealized gains, token breakdown.\n * Endpoint: POST /api/v1/profiler/address/pnl-summary\n * Cost: ~$0.01 (basic tier)\n *\n * Note: /api/v1/profiler/wallet-pnl requires an API key and does not support x402.\n * The correct x402 endpoint is /api/v1/profiler/address/pnl-summary.\n */\n private async walletProfile(address: string): Promise<ResearchResult> {\n const fetchWithPay = await getNansenFetch();\n\n // pnl-summary uses `chain` (singular) + a date range, not `chains` array\n const now = new Date();\n const thirtyDaysAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);\n const body = {\n address,\n chain: \"base\",\n date: {\n from: thirtyDaysAgo.toISOString().replace(/\\.\\d{3}Z$/, \"Z\"),\n to: now.toISOString().replace(/\\.\\d{3}Z$/, \"Z\"),\n },\n };\n\n const res = await fetchWithPay(`${BASE_URL}/api/v1/profiler/address/pnl-summary`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (!res.ok) {\n throw new Error(\n `Nansen wallet query failed: ${res.status} ${res.statusText}`,\n );\n }\n\n const json = (await res.json()) as { data?: Record<string, unknown> };\n const costUsdc = this.extractCost(res, \"wallet\");\n\n return {\n provider: \"nansen\",\n queryType: \"wallet\",\n target: address,\n data: json.data ?? (json as Record<string, unknown>),\n costUsdc,\n timestamp: Math.floor(Date.now() / 1000),\n };\n }\n\n /**\n * Resolve a token symbol to its per-chain contract address(es) via the\n * token screener endpoint (~$0.01). Returns a deduped list across the major\n * smart-money chains so the netflow filter (token_address only) can match\n * the token wherever it trades.\n *\n * The screener caps `chains` at 5 items, so we query the highest-liquidity\n * smart-money chains. Returns an empty array if the symbol resolves to\n * nothing (unknown token) or the lookup fails.\n */\n private async resolveTokenAddresses(symbol: string): Promise<string[]> {\n const fetchWithPay = await getNansenFetch();\n const body = {\n // Screener allows at most 5 chains per request.\n chains: [\"ethereum\", \"base\", \"arbitrum\", \"solana\", \"bnb\"],\n timeframe: \"24h\",\n filters: { token_symbol: [symbol.toUpperCase()] },\n pagination: { page: 1, records_per_page: 25 },\n };\n\n const res = await fetchWithPay(`${BASE_URL}/api/v1/token-screener`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (!res.ok) return [];\n\n const json = (await res.json()) as {\n data?: Array<{ token_address?: string }>;\n };\n const addresses = (json.data ?? [])\n .map((row) => row.token_address)\n .filter((addr): addr is string => typeof addr === \"string\" && addr.length > 0);\n return [...new Set(addresses)];\n }\n\n /**\n * Extract cost from x402 response headers.\n * Falls back to the known estimate for the query type when headers are absent.\n */\n private extractCost(res: Response, queryType: string): string {\n // Check Nansen-specific credit header\n const creditsUsed = res.headers.get(\"x-nansen-credits-used\");\n if (creditsUsed) {\n return creditsUsed;\n }\n\n // Fall back to x402 payment-response header\n const paymentResponse = res.headers.get(\"payment-response\");\n if (paymentResponse) {\n try {\n const parsed = JSON.parse(paymentResponse) as { amount?: string };\n if (parsed.amount) {\n const cents = Number(parsed.amount) / 1e6;\n return cents.toFixed(4);\n }\n } catch {\n // Fall through\n }\n }\n\n // Fall back to known estimate (strip \"~$\" prefix)\n const est = NANSEN_COST_ESTIMATE[queryType];\n if (est) {\n return est.replace(\"~$\", \"\");\n }\n\n return \"unknown\";\n }\n}\n","/**\n * Research providers — pluggable interface for DeFi research data via x402 micropayments.\n *\n * Same pattern as DeFi providers (Moonwell, Uniswap). Each research provider\n * implements ResearchProvider and uses x402-wrapped fetch for automatic USDC payments.\n */\n\nimport type { Provider } from \"../../types.js\";\nimport { MessariProvider } from \"./messari.js\";\nimport { NansenProvider } from \"./nansen.js\";\n\n// ── Types ──\n\nexport interface ResearchQuery {\n /** Query type determines which API endpoint is called */\n type: \"token\" | \"smart-money\" | \"market\" | \"wallet\";\n /** Token address, asset symbol, or wallet address depending on type */\n target: string;\n /** Additional query params (e.g. token symbol for smart-money queries) */\n options?: Record<string, string>;\n}\n\nexport interface ResearchResult {\n provider: string;\n queryType: string;\n target: string;\n /** Structured response data from the provider */\n data: Record<string, unknown>;\n /** Cost paid in USDC (human-readable, e.g. \"0.05\") */\n costUsdc: string;\n timestamp: number;\n}\n\nexport interface ResearchProvider extends Provider {\n /** Query the research provider. Payment is handled automatically via x402. */\n query(params: ResearchQuery): Promise<ResearchResult>;\n}\n\n// ── Factory ──\n\nexport function getResearchProvider(name: string): ResearchProvider {\n switch (name) {\n case \"messari\":\n return new MessariProvider();\n case \"nansen\":\n return new NansenProvider();\n default:\n throw new Error(\n `Unknown research provider: ${name}. Valid providers: messari, nansen`,\n );\n }\n}\n\n// ── Re-exports ──\n\nexport { MessariProvider, NansenProvider };\n"],"mappings":"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","names":["base","base","baseSepolia","BASE_URL","base","baseSepolia"]}
|