@oracle-agent/oracle 0.11.0 → 0.12.0

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.
Files changed (308) hide show
  1. package/LICENSE +115 -201
  2. package/README.md +66 -84
  3. package/SECURITY.md +37 -12
  4. package/SETUP.md +207 -272
  5. package/dist/action-receipts.mjs +1 -0
  6. package/dist/action-semantics.mjs +1 -0
  7. package/dist/address-book.mjs +2 -0
  8. package/dist/bin/desk-server.mjs +14 -0
  9. package/dist/bin/oracle-data-mcp.mjs +8 -0
  10. package/dist/bin/oracle-init.mjs +24 -0
  11. package/dist/bin/oracle-public-server.mjs +5 -0
  12. package/dist/bin/oracle-route.mjs +22 -0
  13. package/dist/bin/oracle-scan.mjs +18 -0
  14. package/dist/bin/oracle-upgrade.mjs +21 -0
  15. package/dist/bin/oracle.mjs +68 -0
  16. package/dist/chains.mjs +1 -0
  17. package/dist/cli/commands/auth.mjs +16 -0
  18. package/dist/cli/commands/bootstrap.mjs +18 -0
  19. package/dist/cli/commands/chain.mjs +21 -0
  20. package/dist/cli/commands/chat.mjs +35 -0
  21. package/dist/cli/commands/credential.mjs +1 -0
  22. package/dist/cli/commands/data-mcp.mjs +2 -0
  23. package/dist/cli/commands/data.mjs +12 -0
  24. package/dist/cli/commands/doctor.mjs +5 -0
  25. package/dist/cli/commands/gate.mjs +13 -0
  26. package/dist/cli/commands/help.mjs +1 -0
  27. package/dist/cli/commands/init.mjs +3 -0
  28. package/dist/cli/commands/mcp.mjs +33 -0
  29. package/dist/cli/commands/model.mjs +44 -0
  30. package/dist/cli/commands/prepare.mjs +2 -0
  31. package/dist/cli/commands/public.mjs +3 -0
  32. package/dist/cli/commands/route.mjs +2 -0
  33. package/dist/cli/commands/runner.mjs +1 -0
  34. package/dist/cli/commands/scan.mjs +2 -0
  35. package/dist/cli/commands/setup.mjs +34 -0
  36. package/dist/cli/commands/sign.mjs +4 -0
  37. package/dist/cli/commands/signer.mjs +1 -0
  38. package/dist/cli/commands/upgrade.mjs +2 -0
  39. package/dist/cli/commands/vault.mjs +1 -0
  40. package/dist/cli/commands/version.mjs +2 -0
  41. package/dist/data/desk-data.mjs +12 -0
  42. package/dist/index.mjs +17 -0
  43. package/dist/nft-gas-war-guard.mjs +1 -0
  44. package/dist/onboarding/harness-configs.mjs +4 -0
  45. package/dist/portfolio-risk.mjs +1 -0
  46. package/dist/prepare-envelope.mjs +1 -0
  47. package/dist/public-control/policy-schema.mjs +1 -0
  48. package/dist/router/index.mjs +2 -0
  49. package/dist/scanner/index.mjs +4 -0
  50. package/dist/signals/index.mjs +1 -0
  51. package/dist/watch-preferences.mjs +1 -0
  52. package/package.json +27 -65
  53. package/public/oracle-splash/index.html +11 -1
  54. package/CONTRIBUTING.md +0 -98
  55. package/bin/desk-server.mjs +0 -440
  56. package/bin/oracle-data-mcp.mjs +0 -1019
  57. package/bin/oracle-init.mjs +0 -496
  58. package/bin/oracle-public-server.mjs +0 -36
  59. package/bin/oracle-route.mjs +0 -254
  60. package/bin/oracle-scan.mjs +0 -192
  61. package/bin/oracle-upgrade.mjs +0 -42
  62. package/bin/oracle.mjs +0 -33
  63. package/docs/adding-a-chain.md +0 -229
  64. package/docs/architecture.md +0 -138
  65. package/docs/cli.md +0 -47
  66. package/docs/connectors.md +0 -13
  67. package/docs/oracle-pack-standard.md +0 -29
  68. package/docs/profiles.md +0 -151
  69. package/docs/public-surface.md +0 -133
  70. package/examples/add-a-chain.mjs +0 -65
  71. package/examples/oracle-pack-template.mjs +0 -38
  72. package/examples/research-a-token.mjs +0 -70
  73. package/plugins/oracle-owner-gate/__init__.py +0 -227
  74. package/plugins/oracle-owner-gate/plugin.yaml +0 -9
  75. package/profiles/_template/SOUL.md +0 -54
  76. package/profiles/_template/profile.json +0 -22
  77. package/profiles/bitcoin-agent/SOUL.md +0 -31
  78. package/profiles/bitcoin-agent/profile.json +0 -32
  79. package/profiles/hyperliquid-agent/SOUL.md +0 -34
  80. package/profiles/hyperliquid-agent/profile.json +0 -37
  81. package/profiles/oracle/SOUL.md +0 -107
  82. package/profiles/oracle/profile.json +0 -39
  83. package/profiles/polymarket-agent/SOUL.md +0 -35
  84. package/profiles/polymarket-agent/profile.json +0 -34
  85. package/profiles/profile.schema.json +0 -90
  86. package/profiles/protocol-builder/SOUL.md +0 -57
  87. package/profiles/protocol-builder/profile.json +0 -39
  88. package/profiles/robinhood-agent/SOUL.md +0 -53
  89. package/profiles/robinhood-agent/profile.json +0 -40
  90. package/profiles/solana-agent/SOUL.md +0 -37
  91. package/profiles/solana-agent/profile.json +0 -37
  92. package/profiles/stable-agent/SOUL.md +0 -43
  93. package/profiles/stable-agent/profile.json +0 -37
  94. package/protocols/templates/safe-erc20/SECURITY.md +0 -16
  95. package/protocols/templates/safe-erc20/foundry.toml +0 -12
  96. package/protocols/templates/safe-erc20/remappings.txt +0 -2
  97. package/protocols/templates/safe-erc20/src/SafeERC20.sol +0 -53
  98. package/protocols/templates/safe-erc20/test/SafeERC20.t.sol +0 -72
  99. package/scripts/adversarial-bench.mjs +0 -114
  100. package/scripts/build-inscription.py +0 -230
  101. package/scripts/check-doc-drift.mjs +0 -123
  102. package/scripts/check-test-count.mjs +0 -105
  103. package/scripts/e2e-hl-markets.mjs +0 -21
  104. package/scripts/e2e-hl-perps.mjs +0 -48
  105. package/scripts/e2e-hypercore-staking.mjs +0 -128
  106. package/scripts/e2e-solana-bitcoin.mjs +0 -183
  107. package/scripts/protocol-template-gate.mjs +0 -15
  108. package/scripts/public-api-scan.mjs +0 -23
  109. package/scripts/secret-scan.mjs +0 -181
  110. package/scripts/verify-v3-venues.mjs +0 -192
  111. package/skills/balance/SKILL.md +0 -176
  112. package/skills/oracle-action-semantics/SKILL.md +0 -40
  113. package/skills/oracle-best-execution/SKILL.md +0 -127
  114. package/skills/oracle-bitcoin/SKILL.md +0 -53
  115. package/skills/oracle-chain-graphs-telegram-cards/SKILL.md +0 -59
  116. package/skills/oracle-chat/SKILL.md +0 -61
  117. package/skills/oracle-chat/chain.SKILL.md +0 -31
  118. package/skills/oracle-chat/setup.SKILL.md +0 -37
  119. package/skills/oracle-circuit-breaker/SKILL.md +0 -51
  120. package/skills/oracle-contract-research/SKILL.md +0 -55
  121. package/skills/oracle-desk/SKILL.md +0 -58
  122. package/skills/oracle-dex-launch/SKILL.md +0 -38
  123. package/skills/oracle-grants/SKILL.md +0 -69
  124. package/skills/oracle-hypercore-staking/SKILL.md +0 -57
  125. package/skills/oracle-hyperliquid/SKILL.md +0 -56
  126. package/skills/oracle-meme-token-sniper/SKILL.md +0 -73
  127. package/skills/oracle-multichain-nft-launch/SKILL.md +0 -338
  128. package/skills/oracle-multichain-token-launch/SKILL.md +0 -300
  129. package/skills/oracle-nft-gacha-launch/SKILL.md +0 -48
  130. package/skills/oracle-nft-mint-gas-war/SKILL.md +0 -63
  131. package/skills/oracle-polymarket/SKILL.md +0 -60
  132. package/skills/oracle-protocol-builder/SKILL.md +0 -59
  133. package/skills/oracle-protocol-security/SKILL.md +0 -60
  134. package/skills/oracle-public-product/SKILL.md +0 -44
  135. package/skills/oracle-receipts/SKILL.md +0 -52
  136. package/skills/oracle-rfq-tokenized-assets/SKILL.md +0 -69
  137. package/skills/oracle-smart-wallet-scanner/SKILL.md +0 -49
  138. package/skills/oracle-solana/SKILL.md +0 -65
  139. package/skills/oracle-solana-nft/SKILL.md +0 -54
  140. package/skills/oracle-token-research/SKILL.md +0 -67
  141. package/skins/oracle.yaml +0 -56
  142. package/src/action-receipts.mjs +0 -265
  143. package/src/action-semantics.mjs +0 -62
  144. package/src/address-book.mjs +0 -208
  145. package/src/agent-auth.mjs +0 -206
  146. package/src/approval-guard.mjs +0 -282
  147. package/src/attestation-secret.mjs +0 -88
  148. package/src/audit-log.mjs +0 -196
  149. package/src/auth/oauth.mjs +0 -672
  150. package/src/auto-slippage.mjs +0 -378
  151. package/src/capability-posture.mjs +0 -125
  152. package/src/chains.mjs +0 -62
  153. package/src/cli/chain-catalog.mjs +0 -215
  154. package/src/cli/chain-state.mjs +0 -74
  155. package/src/cli/commands/auth.mjs +0 -193
  156. package/src/cli/commands/bootstrap.mjs +0 -87
  157. package/src/cli/commands/chain.mjs +0 -143
  158. package/src/cli/commands/chat.mjs +0 -434
  159. package/src/cli/commands/credential.mjs +0 -9
  160. package/src/cli/commands/data-mcp.mjs +0 -18
  161. package/src/cli/commands/data.mjs +0 -75
  162. package/src/cli/commands/doctor.mjs +0 -136
  163. package/src/cli/commands/help.mjs +0 -7
  164. package/src/cli/commands/init.mjs +0 -27
  165. package/src/cli/commands/mcp.mjs +0 -142
  166. package/src/cli/commands/model.mjs +0 -99
  167. package/src/cli/commands/prepare.mjs +0 -12
  168. package/src/cli/commands/public.mjs +0 -20
  169. package/src/cli/commands/route.mjs +0 -12
  170. package/src/cli/commands/runner.mjs +0 -9
  171. package/src/cli/commands/scan.mjs +0 -12
  172. package/src/cli/commands/setup.mjs +0 -275
  173. package/src/cli/commands/sign.mjs +0 -21
  174. package/src/cli/commands/signer.mjs +0 -9
  175. package/src/cli/commands/upgrade.mjs +0 -12
  176. package/src/cli/commands/vault.mjs +0 -9
  177. package/src/cli/commands/version.mjs +0 -22
  178. package/src/cli/first-run.mjs +0 -23
  179. package/src/cli/kernel.mjs +0 -239
  180. package/src/cli/mcp-targets/chatgpt.mjs +0 -51
  181. package/src/cli/mcp-targets/claude-code.mjs +0 -39
  182. package/src/cli/mcp-targets/claude-desktop.mjs +0 -24
  183. package/src/cli/mcp-targets/codex.mjs +0 -41
  184. package/src/cli/mcp-targets/shared.mjs +0 -61
  185. package/src/cli/messaging-platforms.mjs +0 -209
  186. package/src/cli/model-config.mjs +0 -70
  187. package/src/cli/operator-dispatch.mjs +0 -258
  188. package/src/cli/oracle-harness.py +0 -415
  189. package/src/cli/paths.mjs +0 -83
  190. package/src/cli/runtime.mjs +0 -351
  191. package/src/cli/setup-state.mjs +0 -168
  192. package/src/cli/spawn-child.mjs +0 -43
  193. package/src/data/catalog.mjs +0 -585
  194. package/src/data/desk-data.mjs +0 -695
  195. package/src/data/http.mjs +0 -253
  196. package/src/data/provider-endpoint.mjs +0 -94
  197. package/src/data/providers/aerodrome.mjs +0 -245
  198. package/src/data/providers/balancer.mjs +0 -209
  199. package/src/data/providers/bitcoin-esplora.mjs +0 -216
  200. package/src/data/providers/bitcoin-meta.mjs +0 -378
  201. package/src/data/providers/blockscout.mjs +0 -14
  202. package/src/data/providers/bridges.mjs +0 -242
  203. package/src/data/providers/cowswap.mjs +0 -415
  204. package/src/data/providers/curve.mjs +0 -201
  205. package/src/data/providers/defillama.mjs +0 -88
  206. package/src/data/providers/dexscreener.mjs +0 -43
  207. package/src/data/providers/evm-rpc.mjs +0 -225
  208. package/src/data/providers/geckoterminal.mjs +0 -34
  209. package/src/data/providers/gmx.mjs +0 -496
  210. package/src/data/providers/hl-assets.mjs +0 -165
  211. package/src/data/providers/hl-info.mjs +0 -108
  212. package/src/data/providers/hl-markets.mjs +0 -210
  213. package/src/data/providers/hl-outcome.mjs +0 -61
  214. package/src/data/providers/hl-perps.mjs +0 -387
  215. package/src/data/providers/hl-staking.mjs +0 -353
  216. package/src/data/providers/hl-ws.mjs +0 -119
  217. package/src/data/providers/hyperevm-dex.mjs +0 -49
  218. package/src/data/providers/jupiter-venues.mjs +0 -119
  219. package/src/data/providers/jupiter.mjs +0 -315
  220. package/src/data/providers/lifi.mjs +0 -151
  221. package/src/data/providers/magiceden-sol.mjs +0 -406
  222. package/src/data/providers/morpho.mjs +0 -177
  223. package/src/data/providers/nft-gallery.mjs +0 -163
  224. package/src/data/providers/nft-portfolio.mjs +0 -494
  225. package/src/data/providers/odos.mjs +0 -156
  226. package/src/data/providers/oneinch.mjs +0 -174
  227. package/src/data/providers/opensea-multichain.mjs +0 -136
  228. package/src/data/providers/opensea-nft.mjs +0 -371
  229. package/src/data/providers/paraswap.mjs +0 -118
  230. package/src/data/providers/pendle.mjs +0 -188
  231. package/src/data/providers/poly-clob.mjs +0 -283
  232. package/src/data/providers/poly-public.mjs +0 -96
  233. package/src/data/providers/poly-ws.mjs +0 -103
  234. package/src/data/providers/portfolio-history.mjs +0 -394
  235. package/src/data/providers/portfolio.mjs +0 -594
  236. package/src/data/providers/rfq.mjs +0 -15
  237. package/src/data/providers/rh-agent.mjs +0 -59
  238. package/src/data/providers/satflow.mjs +0 -341
  239. package/src/data/providers/signed-material-guard.mjs +0 -108
  240. package/src/data/providers/solana-rpc.mjs +0 -197
  241. package/src/data/providers/uniswap-v3.mjs +0 -349
  242. package/src/data/providers/uniswap-v4.mjs +0 -414
  243. package/src/data/providers/zerox.mjs +0 -167
  244. package/src/data/public-api-scan.mjs +0 -61
  245. package/src/data/quote-placeholder.mjs +0 -31
  246. package/src/exact-integer.mjs +0 -72
  247. package/src/exec-policy.mjs +0 -455
  248. package/src/flags.mjs +0 -15
  249. package/src/fresh-window.mjs +0 -76
  250. package/src/gmx-attestation.mjs +0 -176
  251. package/src/index.mjs +0 -100
  252. package/src/nft-gas-war-guard.mjs +0 -139
  253. package/src/onboarding/agent-keys.mjs +0 -161
  254. package/src/onboarding/harness-configs.mjs +0 -102
  255. package/src/onboarding/index.mjs +0 -18
  256. package/src/onboarding/tiers.mjs +0 -139
  257. package/src/oracle-env.mjs +0 -47
  258. package/src/portfolio-risk.mjs +0 -170
  259. package/src/prepare-envelope.mjs +0 -204
  260. package/src/profile-upgrade.mjs +0 -277
  261. package/src/protocol-execution.mjs +0 -84
  262. package/src/protocol-templates/gate.mjs +0 -179
  263. package/src/protocol-templates/prepare-deploy.mjs +0 -81
  264. package/src/public-api/buzz-integration.mjs +0 -256
  265. package/src/public-api/connect-agent.mjs +0 -416
  266. package/src/public-api/grants.mjs +0 -142
  267. package/src/public-api/http.mjs +0 -389
  268. package/src/public-control/aa-adapter.mjs +0 -402
  269. package/src/public-control/build-registry.mjs +0 -227
  270. package/src/public-control/bundler-client.mjs +0 -357
  271. package/src/public-control/grant-indexer.mjs +0 -296
  272. package/src/public-control/policy-render.mjs +0 -69
  273. package/src/public-control/policy-schema.mjs +0 -318
  274. package/src/public-control/runtime-config.mjs +0 -275
  275. package/src/public-control/session-key-model.mjs +0 -374
  276. package/src/public-control/session-orchestrator.mjs +0 -412
  277. package/src/rfq/intent.mjs +0 -180
  278. package/src/rfq/sources.mjs +0 -181
  279. package/src/route-attestation.mjs +0 -132
  280. package/src/router/best-execution.mjs +0 -326
  281. package/src/router/index.mjs +0 -226
  282. package/src/router/prepare-bridge.mjs +0 -289
  283. package/src/router/prepare-route.mjs +0 -398
  284. package/src/router/proposal.mjs +0 -311
  285. package/src/router/risk-classifier.mjs +0 -119
  286. package/src/router/route-sources.mjs +0 -364
  287. package/src/scanner/chains.config.mjs +0 -430
  288. package/src/scanner/contract.mjs +0 -270
  289. package/src/scanner/evm-scanner.mjs +0 -394
  290. package/src/scanner/index.mjs +0 -9
  291. package/src/scanner/v2-venue.mjs +0 -335
  292. package/src/scanner/v3-venue.mjs +0 -290
  293. package/src/scopes.mjs +0 -44
  294. package/src/sell-simulation.mjs +0 -167
  295. package/src/signals/engine.mjs +0 -146
  296. package/src/signals/index.mjs +0 -1
  297. package/src/token-transfer-guard.mjs +0 -188
  298. package/src/tui/app.mjs +0 -438
  299. package/src/tui/backend.mjs +0 -145
  300. package/src/tui/format.mjs +0 -272
  301. package/src/tui/gateway-client.mjs +0 -177
  302. package/src/tui/input.mjs +0 -501
  303. package/src/tui/renderer.mjs +0 -443
  304. package/src/tui/standalone-client.mjs +0 -666
  305. package/src/tui/theme.mjs +0 -81
  306. package/src/vault-attestation.mjs +0 -146
  307. package/src/venues.mjs +0 -206
  308. package/src/watch-preferences.mjs +0 -85
@@ -1,88 +0,0 @@
1
- // DeFiLlama public prices — protocol pack D3 (no API key).
2
-
3
- import { httpJson } from "../http.mjs";
4
-
5
- export const DEFILLAMA_COINS = "https://coins.llama.fi";
6
- export const DEFILLAMA_API = "https://api.llama.fi";
7
- export const DEFILLAMA_YIELDS = "https://yields.llama.fi";
8
- export const DEFILLAMA_STABLECOINS = "https://stablecoins.llama.fi";
9
-
10
- function coinsBase(opts = {}) {
11
- return (opts.baseUrl || process.env.DEFILLAMA_COINS_URL || DEFILLAMA_COINS).replace(/\/$/, "");
12
- }
13
-
14
- function apiBase(opts = {}) {
15
- return (opts.baseUrl || process.env.DEFILLAMA_API_URL || DEFILLAMA_API).replace(/\/$/, "");
16
- }
17
-
18
- /** @param {string[]} coins e.g. ['coingecko:ethereum','coingecko:bitcoin'] */
19
- export async function llamaPrices(coins, opts = {}) {
20
- if (!Array.isArray(coins) || !coins.length) throw new Error("llamaPrices requires coins[]");
21
- const path = coins.map(encodeURIComponent).join(",");
22
- return httpJson(`${coinsBase(opts)}/prices/current/${path}`, {
23
- fetchImpl: opts.fetchImpl,
24
- timeoutMs: opts.timeoutMs,
25
- });
26
- }
27
-
28
- export async function llamaHealth(opts = {}) {
29
- const data = await llamaPrices(["coingecko:ethereum"], opts);
30
- const eth = data?.coins?.["coingecko:ethereum"];
31
- return { ok: !!eth?.price, ethUsd: eth?.price ?? null };
32
- }
33
-
34
- export async function llamaProtocols(opts = {}) {
35
- return httpJson(`${apiBase(opts)}/protocols`, {
36
- fetchImpl: opts.fetchImpl,
37
- timeoutMs: opts.timeoutMs ?? 20_000,
38
- });
39
- }
40
-
41
- export async function llamaYields(args = {}, opts = {}) {
42
- const base = (opts.yieldsBaseUrl || process.env.DEFILLAMA_YIELDS_URL || DEFILLAMA_YIELDS).replace(/\/$/, "");
43
- const result = await httpJson(`${base}/pools`, {
44
- fetchImpl: opts.fetchImpl,
45
- timeoutMs: opts.timeoutMs ?? 30_000,
46
- });
47
- let rows = Array.isArray(result?.data) ? result.data : [];
48
- if (args.chain) rows = rows.filter((x) => String(x.chain).toLowerCase() === String(args.chain).toLowerCase());
49
- if (args.project) rows = rows.filter((x) => String(x.project).toLowerCase() === String(args.project).toLowerCase());
50
- if (args.stablecoin != null) rows = rows.filter((x) => Boolean(x.stablecoin) === Boolean(args.stablecoin));
51
- rows.sort((a, b) => Number(b.tvlUsd || 0) - Number(a.tvlUsd || 0));
52
- const limit = Math.min(5000, Math.max(1, Number(args.limit || rows.length || 1)));
53
- return { ...result, data: rows.slice(0, limit) };
54
- }
55
-
56
- export async function llamaStablecoins(args = {}, opts = {}) {
57
- const base = (opts.stablecoinsBaseUrl || process.env.DEFILLAMA_STABLECOINS_URL || DEFILLAMA_STABLECOINS).replace(/\/$/, "");
58
- const includePrices = args.includePrices !== false;
59
- return httpJson(`${base}/stablecoins?includePrices=${includePrices}`, {
60
- fetchImpl: opts.fetchImpl,
61
- timeoutMs: opts.timeoutMs ?? 30_000,
62
- });
63
- }
64
-
65
- export async function llamaDexVolumes(args = {}, opts = {}) {
66
- const chain = encodeURIComponent(String(args.chain || "Ethereum"));
67
- const params = new URLSearchParams({
68
- excludeTotalDataChart: String(args.includeChart !== true),
69
- excludeTotalDataChartBreakdown: String(args.includeBreakdown !== true),
70
- dataType: "dailyVolume",
71
- });
72
- return httpJson(`${apiBase(opts)}/overview/dexs/${chain}?${params}`, {
73
- fetchImpl: opts.fetchImpl,
74
- timeoutMs: opts.timeoutMs ?? 30_000,
75
- });
76
- }
77
-
78
- /** Convenience: map symbols via coingecko ids */
79
- export async function llamaPricesBySymbol(symbols = ["ethereum", "bitcoin", "solana"], opts = {}) {
80
- const coins = symbols.map((s) => `coingecko:${String(s).toLowerCase()}`);
81
- const data = await llamaPrices(coins, opts);
82
- const out = {};
83
- for (const s of symbols) {
84
- const key = `coingecko:${String(s).toLowerCase()}`;
85
- out[s] = data?.coins?.[key] || null;
86
- }
87
- return out;
88
- }
@@ -1,43 +0,0 @@
1
- // DexScreener public API — token/pair discovery, no key.
2
-
3
- import { httpJson } from "../http.mjs";
4
-
5
- export const DEXSCREENER_API = "https://api.dexscreener.com";
6
-
7
- function base(opts = {}) {
8
- return (opts.baseUrl || process.env.DEXSCREENER_API_URL || DEXSCREENER_API).replace(/\/$/, "");
9
- }
10
-
11
- export async function dexscreenerHealth(opts = {}) {
12
- // tokenless root sometimes 404 — use a known stablecoin query
13
- const data = await httpJson(
14
- `${base(opts)}/latest/dex/search?q=USDC`,
15
- { fetchImpl: opts.fetchImpl, timeoutMs: opts.timeoutMs ?? 12_000 }
16
- );
17
- const n = data?.pairs?.length || 0;
18
- return { ok: n > 0, pairSample: n };
19
- }
20
-
21
- export async function dexscreenerToken(tokenAddress, opts = {}) {
22
- if (!tokenAddress) throw new Error("tokenAddress required");
23
- return httpJson(`${base(opts)}/latest/dex/tokens/${tokenAddress}`, {
24
- fetchImpl: opts.fetchImpl,
25
- timeoutMs: opts.timeoutMs ?? 12_000,
26
- });
27
- }
28
-
29
- export async function dexscreenerSearch(q, opts = {}) {
30
- if (!q) throw new Error("query required");
31
- return httpJson(`${base(opts)}/latest/dex/search?q=${encodeURIComponent(q)}`, {
32
- fetchImpl: opts.fetchImpl,
33
- timeoutMs: opts.timeoutMs ?? 12_000,
34
- });
35
- }
36
-
37
- export async function dexscreenerPair(chainId, pairAddress, opts = {}) {
38
- if (!chainId || !pairAddress) throw new Error("chainId and pairAddress required");
39
- return httpJson(`${base(opts)}/latest/dex/pairs/${chainId}/${pairAddress}`, {
40
- fetchImpl: opts.fetchImpl,
41
- timeoutMs: opts.timeoutMs ?? 12_000,
42
- });
43
- }
@@ -1,225 +0,0 @@
1
- // EVM JSON-RPC read pack — multi-chain balances/blocks via public or env RPCs.
2
- // No wallet keys. Uses chain registry rpcEnv + optional public fallbacks.
3
-
4
- import { httpJson } from "../http.mjs";
5
- import { CHAINS, chainById, rpcUrlFor, isSupportedChain } from "../../chains.mjs";
6
- import { Interface, getAddress } from "ethers";
7
-
8
- const ERC20 = new Interface([
9
- "function allowance(address owner,address spender) view returns (uint256)",
10
- "function balanceOf(address account) view returns (uint256)",
11
- ]);
12
-
13
- function normalizeAddress(value, label) {
14
- try {
15
- return getAddress(value).toLowerCase();
16
- } catch {
17
- throw new Error(`${label} must be a valid EVM address`);
18
- }
19
- }
20
-
21
- function normalizeTxHash(value) {
22
- const hash = String(value || "").trim();
23
- if (!/^0x[0-9a-fA-F]{64}$/.test(hash)) throw new Error("txHash must be a 32-byte hex transaction hash");
24
- return hash.toLowerCase();
25
- }
26
-
27
- function parseHexInt(value) {
28
- if (value == null) return null;
29
- return Number.parseInt(String(value), 16);
30
- }
31
-
32
- /** Public fallbacks when env RPC unset — rate-limited, fine for health/read. */
33
- export const PUBLIC_RPC_FALLBACKS = {
34
- 1: "https://ethereum.publicnode.com",
35
- 137: "https://polygon-bor-rpc.publicnode.com",
36
- 42161: "https://arbitrum-one-rpc.publicnode.com",
37
- 8453: "https://base-rpc.publicnode.com",
38
- 10: "https://optimism-rpc.publicnode.com",
39
- 988: "https://rpc.stable.xyz",
40
- 56: "https://bsc-rpc.publicnode.com",
41
- 43114: "https://avalanche-c-chain-rpc.publicnode.com",
42
- 999: "https://rpc.hyperliquid.xyz/evm",
43
- 2741: "https://api.mainnet.abs.xyz",
44
- 4663: "https://rpc.mainnet.chain.robinhood.com",
45
- };
46
-
47
- /**
48
- * Resolve RPC URL for a chainId: explicit > env (registry) > public fallback.
49
- */
50
- export function resolveRpcUrl(chainId, { rpcUrl, env = process.env } = {}) {
51
- if (rpcUrl) return rpcUrl;
52
- const fromEnv = rpcUrlFor(chainId, env);
53
- if (fromEnv) return fromEnv;
54
- return PUBLIC_RPC_FALLBACKS[Number(chainId)] || null;
55
- }
56
-
57
- /**
58
- * JSON-RPC call
59
- * @param {number} chainId
60
- * @param {string} method
61
- * @param {any[]} [params]
62
- */
63
-
64
- // `rpcCall` is the raw public transport exposed by the data facade. It must be
65
- // an allowlist, not a partial write denylist: every unrecognized method is
66
- // unsafe to forward because vendors add write namespaces (`wallet_send*`,
67
- // `pm_sendUserOperation`, `mev_sendBundle`) faster than a denylist stays fresh.
68
- //
69
- // Canonical JSON-RPC method names are ASCII lowercase + underscores. Reject
70
- // whitespace, separator tricks, and Unicode homoglyphs rather than normalizing
71
- // them into a different network request.
72
- const EVM_READ_RPC = /^(?:eth_(?:call|blocknumber|chainid|get[a-z0-9]+|feehistory|gasprice|maxpriorityfeepergas|syncing|protocolversion|estimategas|createaccesslist)|net_(?:version|listening|peercount)|web3_(?:clientversion|sha3))$/;
73
-
74
- function readRpcMethod(method) {
75
- const raw = String(method || "");
76
- const probe = raw.toLowerCase();
77
- if (raw !== raw.trim() || !/^[a-zA-Z0-9_]+$/.test(raw) || !EVM_READ_RPC.test(probe)) {
78
- throw new Error(`evm-rpc: ${raw} refused — @oracle-agent/oracle is prepare-only (read RPC only; no broadcast/sign)`);
79
- }
80
- return probe;
81
- }
82
-
83
- export async function rpcCall(chainId, method, params = [], opts = {}) {
84
- const methodName = String(method || "");
85
- readRpcMethod(methodName);
86
- const url = resolveRpcUrl(chainId, opts);
87
- if (!url) {
88
- throw new Error(
89
- `No RPC URL for chainId ${chainId} (set env from chain registry rpcEnv or pass rpcUrl)`
90
- );
91
- }
92
- const body = { jsonrpc: "2.0", id: 1, method, params };
93
- const res = await httpJson(url, {
94
- method: "POST",
95
- body,
96
- fetchImpl: opts.fetchImpl,
97
- timeoutMs: opts.timeoutMs ?? 12_000,
98
- });
99
- if (res?.error) {
100
- const err = new Error(res.error.message || JSON.stringify(res.error));
101
- err.code = res.error.code;
102
- throw err;
103
- }
104
- return res.result;
105
- }
106
-
107
- export async function rpcHealth(chainId, opts = {}) {
108
- const blockHex = await rpcCall(chainId, "eth_blockNumber", [], opts);
109
- const block = parseInt(blockHex, 16);
110
- const idHex = await rpcCall(chainId, "eth_chainId", [], opts);
111
- const reported = parseInt(idHex, 16);
112
- return {
113
- ok: Number.isFinite(block) && reported === Number(chainId),
114
- chainId: Number(chainId),
115
- reportedChainId: reported,
116
- blockNumber: block,
117
- name: chainById(chainId)?.name || null,
118
- };
119
- }
120
-
121
- export async function rpcBlockNumber(chainId, opts = {}) {
122
- const hex = await rpcCall(chainId, "eth_blockNumber", [], opts);
123
- return parseInt(hex, 16);
124
- }
125
-
126
- export async function rpcChainId(chainId, opts = {}) {
127
- const hex = await rpcCall(chainId, "eth_chainId", [], opts);
128
- return parseInt(hex, 16);
129
- }
130
-
131
- export async function rpcGetBalance(chainId, address, opts = {}) {
132
- if (!address) throw new Error("rpcGetBalance requires address");
133
- const hex = await rpcCall(chainId, "eth_getBalance", [address, "latest"], opts);
134
- return { chainId: Number(chainId), address, balanceWei: BigInt(hex).toString(), balanceHex: hex };
135
- }
136
-
137
- export async function erc20Allowance(args = {}, opts = {}) {
138
- const chainId = Number(args.chainId ?? opts.chainId ?? 1);
139
- const token = normalizeAddress(args.token || args.tokenAddress, "token");
140
- const owner = normalizeAddress(args.owner, "owner");
141
- const spender = normalizeAddress(args.spender, "spender");
142
- const data = ERC20.encodeFunctionData("allowance", [owner, spender]);
143
- const result = await rpcCall(chainId, "eth_call", [{ to: token, data }, args.blockTag || "latest"], opts);
144
- const decoded = ERC20.decodeFunctionResult("allowance", result);
145
- const allowance = BigInt(decoded[0]);
146
- return {
147
- chainId,
148
- token,
149
- owner,
150
- spender,
151
- allowance: allowance.toString(),
152
- allowanceHex: `0x${allowance.toString(16)}`,
153
- blockTag: args.blockTag || "latest",
154
- };
155
- }
156
-
157
- export async function erc20BalanceOf(args = {}, opts = {}) {
158
- const chainId = Number(args.chainId ?? opts.chainId ?? 1);
159
- const token = normalizeAddress(args.token || args.tokenAddress, "token");
160
- const account = normalizeAddress(args.account || args.owner || args.address, "account");
161
- const data = ERC20.encodeFunctionData("balanceOf", [account]);
162
- const result = await rpcCall(chainId, "eth_call", [{ to: token, data }, args.blockTag || "latest"], opts);
163
- const decoded = ERC20.decodeFunctionResult("balanceOf", result);
164
- const balance = BigInt(decoded[0]);
165
- return {
166
- chainId,
167
- token,
168
- account,
169
- balance: balance.toString(),
170
- balanceHex: `0x${balance.toString(16)}`,
171
- blockTag: args.blockTag || "latest",
172
- };
173
- }
174
-
175
- export async function transactionReceipt(args = {}, opts = {}) {
176
- const chainId = Number(args.chainId ?? opts.chainId ?? 1);
177
- const txHash = normalizeTxHash(args.txHash || args.hash || args.transactionHash);
178
- const receipt = await rpcCall(chainId, "eth_getTransactionReceipt", [txHash], opts);
179
- if (!receipt) {
180
- return { ok: false, chainId, txHash, status: "pending", receipt: null, reason: "receipt pending" };
181
- }
182
- const statusNumber = parseHexInt(receipt.status);
183
- let ok = statusNumber === 1;
184
- const status = statusNumber === 1 ? "success" : statusNumber === 0 ? "reverted" : "unknown";
185
- let reason = ok ? null : status === "reverted" ? "transaction reverted" : "unknown receipt status";
186
- const expectedTo = args.expectedTo ? normalizeAddress(args.expectedTo, "expectedTo") : null;
187
- const actualTo = receipt.to ? normalizeAddress(receipt.to, "receipt.to") : null;
188
- if (expectedTo && actualTo !== expectedTo) {
189
- ok = false;
190
- reason = `to mismatch: expected ${expectedTo}, got ${actualTo || "null"}`;
191
- }
192
- return {
193
- ok,
194
- chainId,
195
- txHash,
196
- status,
197
- reason,
198
- statusCode: statusNumber,
199
- to: actualTo,
200
- from: receipt.from ? normalizeAddress(receipt.from, "receipt.from") : null,
201
- blockNumber: parseHexInt(receipt.blockNumber),
202
- transactionIndex: parseHexInt(receipt.transactionIndex),
203
- logs: Array.isArray(receipt.logs) ? receipt.logs : [],
204
- receipt,
205
- };
206
- }
207
-
208
- export async function rpcHealthAll(opts = {}) {
209
- const ids = opts.chainIds || Object.values(CHAINS).map((c) => c.chainId);
210
- const out = {};
211
- await Promise.all(
212
- ids.map(async (id) => {
213
- if (!isSupportedChain(id) && !PUBLIC_RPC_FALLBACKS[id] && !resolveRpcUrl(id, opts)) {
214
- out[id] = { ok: false, error: "no rpc configured", chainId: id };
215
- return;
216
- }
217
- try {
218
- out[id] = await rpcHealth(id, opts);
219
- } catch (e) {
220
- out[id] = { ok: false, chainId: id, error: String(e.message || e) };
221
- }
222
- })
223
- );
224
- return out;
225
- }
@@ -1,34 +0,0 @@
1
- // GeckoTerminal public market-data API — no key.
2
- import { httpJson } from "../http.mjs";
3
-
4
- export const GECKOTERMINAL_API = "https://api.geckoterminal.com/api/v2";
5
- const base = (o={}) => (o.baseUrl || process.env.GECKOTERMINAL_API_URL || GECKOTERMINAL_API).replace(/\/$/, "");
6
- const enc = (v) => encodeURIComponent(String(v));
7
-
8
- export async function geckoNetworks(args = {}, opts = {}) {
9
- const page = Math.max(1, Number(args.page || 1));
10
- return httpJson(`${base(opts)}/networks?page=${page}`, { fetchImpl: opts.fetchImpl, timeoutMs: opts.timeoutMs });
11
- }
12
- export async function geckoPool(args = {}, opts = {}) {
13
- if (!args.network || !args.poolAddress) throw new Error("network and poolAddress required");
14
- return httpJson(`${base(opts)}/networks/${enc(args.network)}/pools/${enc(args.poolAddress)}`, { fetchImpl: opts.fetchImpl, timeoutMs: opts.timeoutMs });
15
- }
16
- export async function geckoToken(args = {}, opts = {}) {
17
- if (!args.network || !(args.address || args.tokenAddress)) throw new Error("network and token address required");
18
- return httpJson(`${base(opts)}/networks/${enc(args.network)}/tokens/${enc(args.address || args.tokenAddress)}`, { fetchImpl: opts.fetchImpl, timeoutMs: opts.timeoutMs });
19
- }
20
- export async function geckoPoolOhlcv(args = {}, opts = {}) {
21
- if (!args.network || !args.poolAddress) throw new Error("network and poolAddress required");
22
- const timeframe = ["minute","hour","day"].includes(args.timeframe) ? args.timeframe : "hour";
23
- const p = new URLSearchParams();
24
- p.set("aggregate", String(Math.max(1, Number(args.aggregate || 1))));
25
- p.set("limit", String(Math.min(1000, Math.max(1, Number(args.limit || 168)))));
26
- if (args.beforeTimestamp != null) p.set("before_timestamp", String(args.beforeTimestamp));
27
- if (args.currency) p.set("currency", String(args.currency));
28
- if (args.token) p.set("token", String(args.token));
29
- return httpJson(`${base(opts)}/networks/${enc(args.network)}/pools/${enc(args.poolAddress)}/ohlcv/${timeframe}?${p}`, { fetchImpl: opts.fetchImpl, timeoutMs: opts.timeoutMs });
30
- }
31
- export async function geckoHealth(opts = {}) {
32
- const data = await geckoNetworks({ page: 1 }, opts);
33
- return { ok: Array.isArray(data?.data) && data.data.length > 0, networkSample: data?.data?.length || 0 };
34
- }