@oracle-agent/oracle 0.1.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.
- package/CONTRIBUTING.md +98 -0
- package/LICENSE +202 -0
- package/README.md +384 -0
- package/SECURITY.md +89 -0
- package/SETUP.md +235 -0
- package/artifacts/inscription/oracle-was-here-preview.png +0 -0
- package/artifacts/inscription/oracle-was-here.svg +1 -0
- package/artifacts/specialist-packs/oracle-full-crypto.json +273 -0
- package/bin/desk-server.mjs +438 -0
- package/bin/oracle-data-mcp.mjs +603 -0
- package/bin/oracle-init.mjs +423 -0
- package/bin/oracle-public-server.mjs +36 -0
- package/bin/oracle-route.mjs +254 -0
- package/bin/oracle-scan.mjs +192 -0
- package/docs/adding-a-chain.md +229 -0
- package/docs/architecture.md +135 -0
- package/docs/profiles.md +132 -0
- package/examples/add-a-chain.mjs +65 -0
- package/examples/research-a-token.mjs +70 -0
- package/package.json +90 -0
- package/profiles/_template/SOUL.md +47 -0
- package/profiles/_template/profile.json +22 -0
- package/profiles/bitcoin-agent/SOUL.md +31 -0
- package/profiles/bitcoin-agent/profile.json +32 -0
- package/profiles/hyperliquid-agent/SOUL.md +34 -0
- package/profiles/hyperliquid-agent/profile.json +37 -0
- package/profiles/oracle/SOUL.md +65 -0
- package/profiles/oracle/profile.json +35 -0
- package/profiles/polymarket-agent/SOUL.md +35 -0
- package/profiles/polymarket-agent/profile.json +34 -0
- package/profiles/profile.schema.json +90 -0
- package/profiles/protocol-builder/SOUL.md +50 -0
- package/profiles/protocol-builder/profile.json +37 -0
- package/profiles/robinhood-agent/SOUL.md +45 -0
- package/profiles/robinhood-agent/profile.json +39 -0
- package/profiles/solana-agent/SOUL.md +37 -0
- package/profiles/solana-agent/profile.json +37 -0
- package/profiles/stable-agent/SOUL.md +43 -0
- package/profiles/stable-agent/profile.json +37 -0
- package/public/oracle-console/app.js +272 -0
- package/public/oracle-console/bitcoin-wallets.js +206 -0
- package/public/oracle-console/index.html +91 -0
- package/public/oracle-console/styles.css +239 -0
- package/public/oracle-splash/index.html +931 -0
- package/scripts/build-inscription.py +230 -0
- package/scripts/check-test-count.mjs +105 -0
- package/scripts/e2e-hl-markets.mjs +21 -0
- package/scripts/e2e-hl-perps.mjs +48 -0
- package/scripts/e2e-hypercore-staking.mjs +128 -0
- package/scripts/e2e-solana-bitcoin.mjs +183 -0
- package/scripts/public-api-scan.mjs +23 -0
- package/scripts/secret-scan.mjs +181 -0
- package/scripts/verify-v3-venues.mjs +192 -0
- package/skills/oracle-best-execution/SKILL.md +127 -0
- package/skills/oracle-bitcoin/SKILL.md +53 -0
- package/skills/oracle-chain-graphs-telegram-cards/SKILL.md +59 -0
- package/skills/oracle-circuit-breaker/SKILL.md +51 -0
- package/skills/oracle-contract-research/SKILL.md +55 -0
- package/skills/oracle-desk/SKILL.md +58 -0
- package/skills/oracle-dex-launch/SKILL.md +38 -0
- package/skills/oracle-grants/SKILL.md +69 -0
- package/skills/oracle-hypercore-staking/SKILL.md +57 -0
- package/skills/oracle-hyperliquid/SKILL.md +56 -0
- package/skills/oracle-meme-token-sniper/SKILL.md +73 -0
- package/skills/oracle-nft-gacha-launch/SKILL.md +48 -0
- package/skills/oracle-nft-mint-gas-war/SKILL.md +63 -0
- package/skills/oracle-polymarket/SKILL.md +60 -0
- package/skills/oracle-protocol-builder/SKILL.md +38 -0
- package/skills/oracle-protocol-security/SKILL.md +60 -0
- package/skills/oracle-public-product/SKILL.md +44 -0
- package/skills/oracle-receipts/SKILL.md +52 -0
- package/skills/oracle-rfq-tokenized-assets/SKILL.md +69 -0
- package/skills/oracle-smart-wallet-scanner/SKILL.md +49 -0
- package/skills/oracle-solana/SKILL.md +65 -0
- package/skills/oracle-solana-nft/SKILL.md +54 -0
- package/skills/oracle-token-research/SKILL.md +67 -0
- package/src/agent-auth.mjs +191 -0
- package/src/approval-guard.mjs +282 -0
- package/src/attestation-secret.mjs +88 -0
- package/src/audit-log.mjs +196 -0
- package/src/auto-slippage.mjs +378 -0
- package/src/capability-posture.mjs +125 -0
- package/src/chains.mjs +62 -0
- package/src/data/catalog.mjs +495 -0
- package/src/data/desk-data.mjs +623 -0
- package/src/data/http.mjs +200 -0
- package/src/data/provider-endpoint.mjs +94 -0
- package/src/data/providers/aerodrome.mjs +244 -0
- package/src/data/providers/balancer.mjs +208 -0
- package/src/data/providers/bitcoin-esplora.mjs +230 -0
- package/src/data/providers/bitcoin-meta.mjs +378 -0
- package/src/data/providers/blockscout.mjs +14 -0
- package/src/data/providers/bridges.mjs +241 -0
- package/src/data/providers/cowswap.mjs +501 -0
- package/src/data/providers/curve.mjs +200 -0
- package/src/data/providers/defillama.mjs +88 -0
- package/src/data/providers/dexscreener.mjs +43 -0
- package/src/data/providers/evm-rpc.mjs +203 -0
- package/src/data/providers/geckoterminal.mjs +34 -0
- package/src/data/providers/gmx.mjs +495 -0
- package/src/data/providers/hl-info.mjs +102 -0
- package/src/data/providers/hl-markets.mjs +210 -0
- package/src/data/providers/hl-perps.mjs +382 -0
- package/src/data/providers/hl-staking.mjs +352 -0
- package/src/data/providers/hl-ws.mjs +119 -0
- package/src/data/providers/hyperevm-dex.mjs +49 -0
- package/src/data/providers/jupiter.mjs +182 -0
- package/src/data/providers/lifi.mjs +150 -0
- package/src/data/providers/magiceden-sol.mjs +355 -0
- package/src/data/providers/morpho.mjs +173 -0
- package/src/data/providers/odos.mjs +155 -0
- package/src/data/providers/oneinch.mjs +173 -0
- package/src/data/providers/opensea-multichain.mjs +136 -0
- package/src/data/providers/opensea-nft.mjs +99 -0
- package/src/data/providers/paraswap.mjs +117 -0
- package/src/data/providers/pendle.mjs +187 -0
- package/src/data/providers/poly-public.mjs +96 -0
- package/src/data/providers/poly-ws.mjs +103 -0
- package/src/data/providers/rh-agent.mjs +59 -0
- package/src/data/providers/satflow.mjs +336 -0
- package/src/data/providers/solana-rpc.mjs +186 -0
- package/src/data/providers/uniswap-v3.mjs +303 -0
- package/src/data/providers/zerox.mjs +166 -0
- package/src/data/public-api-scan.mjs +61 -0
- package/src/data/quote-placeholder.mjs +31 -0
- package/src/exact-integer.mjs +72 -0
- package/src/exec-policy.mjs +444 -0
- package/src/flags.mjs +15 -0
- package/src/fresh-window.mjs +76 -0
- package/src/gmx-attestation.mjs +175 -0
- package/src/index.mjs +50 -0
- package/src/nft-gas-war-guard.mjs +139 -0
- package/src/onboarding/agent-keys.mjs +157 -0
- package/src/onboarding/index.mjs +18 -0
- package/src/onboarding/tiers.mjs +139 -0
- package/src/oracle-env.mjs +38 -0
- package/src/protocol-execution.mjs +84 -0
- package/src/public-api/buzz-integration.mjs +256 -0
- package/src/public-api/connect-agent.mjs +397 -0
- package/src/public-api/grants.mjs +142 -0
- package/src/public-api/http.mjs +374 -0
- package/src/public-control/aa-adapter.mjs +402 -0
- package/src/public-control/build-registry.mjs +227 -0
- package/src/public-control/bundler-client.mjs +372 -0
- package/src/public-control/grant-indexer.mjs +296 -0
- package/src/public-control/policy-render.mjs +69 -0
- package/src/public-control/policy-schema.mjs +318 -0
- package/src/public-control/runtime-config.mjs +265 -0
- package/src/public-control/session-key-model.mjs +374 -0
- package/src/public-control/session-orchestrator.mjs +412 -0
- package/src/route-attestation.mjs +132 -0
- package/src/router/best-execution.mjs +221 -0
- package/src/router/index.mjs +185 -0
- package/src/router/prepare-bridge.mjs +288 -0
- package/src/router/prepare-route.mjs +341 -0
- package/src/router/proposal.mjs +311 -0
- package/src/router/risk-classifier.mjs +119 -0
- package/src/router/route-sources.mjs +292 -0
- package/src/scanner/chains.config.mjs +381 -0
- package/src/scanner/contract.mjs +270 -0
- package/src/scanner/evm-scanner.mjs +394 -0
- package/src/scanner/index.mjs +9 -0
- package/src/scanner/v2-venue.mjs +335 -0
- package/src/scanner/v3-venue.mjs +290 -0
- package/src/scopes.mjs +44 -0
- package/src/sell-simulation.mjs +167 -0
- package/src/token-transfer-guard.mjs +188 -0
- package/src/vault-attestation.mjs +145 -0
- package/src/venues.mjs +206 -0
package/src/chains.mjs
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// EVM chain registry — the desk is multi-chain by design (any EVM chain).
|
|
2
|
+
// A "venue" (rh/poly/hl) is a product surface; a "chain" is where a tx settles.
|
|
3
|
+
// One agent wallet can sign on ANY EVM chain — same key, different
|
|
4
|
+
// provider/RPC. This registry keeps chainIds first-class so adapters never
|
|
5
|
+
// hardcode a single chain (a real bug we unwound once: an inline chainId===1
|
|
6
|
+
// special case in a mint path).
|
|
7
|
+
|
|
8
|
+
// Known chains the desk touches today. Extensible: add an entry, nothing else changes.
|
|
9
|
+
export const CHAINS = {
|
|
10
|
+
robinhood: { chainId: 4663, name: "Robinhood Chain", rpcEnv: ["RH_CHAIN_RPC"], evm: true },
|
|
11
|
+
ethereum: { chainId: 1, name: "Ethereum", rpcEnv: ["ETH_RPC_URL", "ETHEREUM_RPC_URL", "MAINNET_RPC_URL"], evm: true },
|
|
12
|
+
polygon: { chainId: 137, name: "Polygon", rpcEnv: ["POLYGON_RPC_URL", "POLYGON_RPC"], evm: true },
|
|
13
|
+
arbitrum: { chainId: 42161, name: "Arbitrum One", rpcEnv: ["ARBITRUM_RPC_URL", "ARB_RPC_URL"], evm: true },
|
|
14
|
+
base: { chainId: 8453, name: "Base", rpcEnv: ["BASE_RPC_URL"], evm: true },
|
|
15
|
+
hyperevm: { chainId: 999, name: "HyperEVM", rpcEnv: ["HYPEREVM_RPC_URL", "HYPER_EVM_RPC"], evm: true },
|
|
16
|
+
bsc: { chainId: 56, name: "BNB Smart Chain", rpcEnv: ["BSC_RPC_URL", "BNB_RPC_URL"], evm: true },
|
|
17
|
+
avalanche: { chainId: 43114, name: "Avalanche C-Chain", rpcEnv: ["AVALANCHE_RPC_URL", "AVAX_RPC_URL"], evm: true },
|
|
18
|
+
optimism: { chainId: 10, name: "OP Mainnet", rpcEnv: ["OPTIMISM_RPC_URL", "OP_RPC_URL"], evm: true },
|
|
19
|
+
abstract: { chainId: 2741, name: "Abstract", rpcEnv: ["ABSTRACT_RPC_URL", "ABS_RPC_URL"], evm: true },
|
|
20
|
+
// Tether/Bitfinex-linked Stable L1 — gas = USDT0/gUSDT; FEFER-class memes (Dyor)
|
|
21
|
+
stable: { chainId: 988, name: "Stable Mainnet", rpcEnv: ["STABLE_RPC_URL", "STABLE_RPC"], evm: true },
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const BY_ID = new Map(Object.values(CHAINS).map((c) => [c.chainId, c]));
|
|
25
|
+
|
|
26
|
+
/** Look up a chain by numeric chainId. Returns null if unknown (never throws here). */
|
|
27
|
+
export function chainById(chainId) {
|
|
28
|
+
return BY_ID.get(Number(chainId)) || null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Register (or override) an EVM chain at runtime so the desk supports ANY EVM
|
|
33
|
+
* chain without a code change. Idempotent.
|
|
34
|
+
* @param {{ key:string, chainId:number, name?:string, rpcEnv?:string[] }} def
|
|
35
|
+
*/
|
|
36
|
+
export function registerChain({ key, chainId, name, rpcEnv = [] }) {
|
|
37
|
+
if (!key) throw new Error("registerChain requires a key");
|
|
38
|
+
if (!Number.isInteger(Number(chainId))) throw new Error("registerChain requires a numeric chainId");
|
|
39
|
+
const entry = { chainId: Number(chainId), name: name || key, rpcEnv, evm: true };
|
|
40
|
+
CHAINS[key] = entry;
|
|
41
|
+
BY_ID.set(entry.chainId, entry);
|
|
42
|
+
return entry;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Resolve a usable RPC URL for a chainId from the environment, trying each
|
|
47
|
+
* candidate env var in order. Returns null if none set (caller decides if fatal).
|
|
48
|
+
*/
|
|
49
|
+
export function rpcUrlFor(chainId, env = process.env) {
|
|
50
|
+
const c = chainById(chainId);
|
|
51
|
+
if (!c) return null;
|
|
52
|
+
for (const name of c.rpcEnv) {
|
|
53
|
+
const v = (env[name] || "").trim();
|
|
54
|
+
if (v) return v;
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** True if we recognize this chainId as a supported EVM chain. */
|
|
60
|
+
export function isSupportedChain(chainId) {
|
|
61
|
+
return BY_ID.has(Number(chainId));
|
|
62
|
+
}
|
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
// Provider catalog — DATA plane registry. Wallet keys never live here.
|
|
2
|
+
|
|
3
|
+
/** @typedef {{ id: string, venue: string, chainIds: number[], auth: 'none'|'apiKey'|'agentKey', ops: string[], baseEnv?: string[], description?: string }} ProviderMeta */
|
|
4
|
+
|
|
5
|
+
const REGISTRY = new Map();
|
|
6
|
+
|
|
7
|
+
export function registerProvider(meta) {
|
|
8
|
+
if (!meta?.id) throw new Error("registerProvider requires id");
|
|
9
|
+
if (!meta.venue) throw new Error("registerProvider requires venue");
|
|
10
|
+
if (!Array.isArray(meta.ops)) throw new Error("registerProvider requires ops[]");
|
|
11
|
+
REGISTRY.set(meta.id, {
|
|
12
|
+
chainIds: meta.chainIds || [],
|
|
13
|
+
auth: meta.auth || "none",
|
|
14
|
+
description: meta.description || "",
|
|
15
|
+
baseEnv: meta.baseEnv || [],
|
|
16
|
+
...meta,
|
|
17
|
+
});
|
|
18
|
+
return REGISTRY.get(meta.id);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function getProvider(id) {
|
|
22
|
+
return REGISTRY.get(id) || null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function listProviders({ venue, op } = {}) {
|
|
26
|
+
let all = [...REGISTRY.values()];
|
|
27
|
+
if (venue) all = all.filter((p) => p.venue === venue);
|
|
28
|
+
if (op) all = all.filter((p) => p.ops.includes(op));
|
|
29
|
+
return all;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function clearProvidersForTest() {
|
|
33
|
+
REGISTRY.clear();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// ── Built-in providers ──────────────────────────────────────────────────────
|
|
37
|
+
|
|
38
|
+
registerProvider({
|
|
39
|
+
id: "hl-info",
|
|
40
|
+
venue: "hl",
|
|
41
|
+
chainIds: [],
|
|
42
|
+
auth: "none",
|
|
43
|
+
ops: [
|
|
44
|
+
"health",
|
|
45
|
+
"allMids",
|
|
46
|
+
"l2Book",
|
|
47
|
+
"outcomeMeta",
|
|
48
|
+
"clearinghouse",
|
|
49
|
+
"userFills",
|
|
50
|
+
"meta",
|
|
51
|
+
"metaAndAssetCtxs",
|
|
52
|
+
"candleSnapshot",
|
|
53
|
+
"openOrders",
|
|
54
|
+
"frontendOpenOrders",
|
|
55
|
+
"userState",
|
|
56
|
+
"spotMeta",
|
|
57
|
+
],
|
|
58
|
+
baseEnv: ["HL_INFO_URL", "HL_API_URL"],
|
|
59
|
+
description: "Hyperliquid public /info",
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
registerProvider({
|
|
63
|
+
id: "poly-public",
|
|
64
|
+
venue: "poly",
|
|
65
|
+
chainIds: [137],
|
|
66
|
+
auth: "none",
|
|
67
|
+
ops: ["health", "time", "markets", "book", "midpoint", "spread", "price", "events"],
|
|
68
|
+
baseEnv: ["POLY_CLOB_URL", "POLY_GAMMA_URL"],
|
|
69
|
+
description: "Polymarket CLOB + Gamma public REST",
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
registerProvider({
|
|
73
|
+
id: "rh-agent",
|
|
74
|
+
venue: "rh",
|
|
75
|
+
chainIds: [4663, 1],
|
|
76
|
+
auth: "none",
|
|
77
|
+
ops: [
|
|
78
|
+
"health",
|
|
79
|
+
"policy",
|
|
80
|
+
"chainConfig",
|
|
81
|
+
"chainGas",
|
|
82
|
+
"swapsConfig",
|
|
83
|
+
"swapsPresets",
|
|
84
|
+
"tradingStatus",
|
|
85
|
+
"nftDrops",
|
|
86
|
+
"feeEstimate",
|
|
87
|
+
],
|
|
88
|
+
baseEnv: ["RH_AGENT_BASE_URL", "RH_AGENT_URL"],
|
|
89
|
+
description: "RH agent local HTTP (unauthenticated read routes)",
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
registerProvider({
|
|
93
|
+
id: "evm-rpc",
|
|
94
|
+
venue: "evm",
|
|
95
|
+
chainIds: [1, 137, 42161, 8453, 10, 4663, 999],
|
|
96
|
+
auth: "none",
|
|
97
|
+
ops: ["health", "healthAll", "blockNumber", "chainId", "getBalance", "call", "erc20Allowance", "erc20Balance", "transactionReceipt"],
|
|
98
|
+
baseEnv: ["ETH_RPC_URL", "POLYGON_RPC_URL", "RH_CHAIN_RPC", "BASE_RPC_URL", "ARBITRUM_RPC_URL"],
|
|
99
|
+
description: "EVM JSON-RPC multi-chain (env RPC or public fallbacks)",
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
registerProvider({
|
|
103
|
+
id: "solana-rpc",
|
|
104
|
+
venue: "solana",
|
|
105
|
+
chainIds: [],
|
|
106
|
+
auth: "none",
|
|
107
|
+
ops: ["health", "latestBlockhash", "getBalance", "tokenAccounts", "simulate"],
|
|
108
|
+
baseEnv: ["SOLANA_RPC_URL"],
|
|
109
|
+
description: "Solana mainnet JSON-RPC read/prepare surface (no key, no signing, no broadcast)",
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
registerProvider({
|
|
113
|
+
id: "bitcoin-esplora",
|
|
114
|
+
venue: "bitcoin",
|
|
115
|
+
chainIds: [],
|
|
116
|
+
auth: "none",
|
|
117
|
+
ops: ["health", "tipHeight", "fees", "address", "utxos", "tx", "decode"],
|
|
118
|
+
execution: "read-only",
|
|
119
|
+
baseEnv: ["BTC_ESPLORA_URL", "BTC_NETWORK"],
|
|
120
|
+
description:
|
|
121
|
+
"Bitcoin L1 via Esplora (mempool.space/Blockstream). Reads only on data plane. User-signed broadcast is bitcoin_send on exec MCP. No Core RPC, no house keys. Wallets: Xverse/UniSat/Leather/OKX/Phantom",
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
registerProvider({
|
|
125
|
+
id: "bitcoin-meta",
|
|
126
|
+
venue: "bitcoin-metaprotocol",
|
|
127
|
+
chainIds: [],
|
|
128
|
+
auth: "optionalApiKey",
|
|
129
|
+
ops: [
|
|
130
|
+
"health",
|
|
131
|
+
"runeBalances",
|
|
132
|
+
"inscriptions",
|
|
133
|
+
"inscriptionInfo",
|
|
134
|
+
"inscriptionChildren",
|
|
135
|
+
"ordBlockInfo",
|
|
136
|
+
],
|
|
137
|
+
execution: "read-only",
|
|
138
|
+
baseEnv: ["BTC_META_API_URL", "UNISAT_API_KEY", "BESTINSLOT_API_KEY"],
|
|
139
|
+
description:
|
|
140
|
+
"Bitcoin ordinals/runes reads. Keyless tier via ordinals.com recursive (inscriptionInfo/children/blockInfo); address-indexed ops (inscriptions, runeBalances) need a keyed indexer. Hiro is deprecated (410) and Magic Eden BTC is dead — use satflow for market.",
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
registerProvider({
|
|
144
|
+
id: "satflow",
|
|
145
|
+
venue: "bitcoin-marketplace",
|
|
146
|
+
chainIds: [],
|
|
147
|
+
auth: "apiKey",
|
|
148
|
+
ops: [
|
|
149
|
+
"health",
|
|
150
|
+
"collectionFloors",
|
|
151
|
+
"collectionStats",
|
|
152
|
+
"item",
|
|
153
|
+
"walletContents",
|
|
154
|
+
"floorListings",
|
|
155
|
+
"preparePurchase",
|
|
156
|
+
"prepareList",
|
|
157
|
+
],
|
|
158
|
+
execution: "prepare",
|
|
159
|
+
baseEnv: ["SATFLOW_API_KEY", "SATFLOW_API_URL"],
|
|
160
|
+
description:
|
|
161
|
+
"Satflow ordinals+runes marketplace (api.satflow.com). Primary BTC NFT market after Magic Eden BTC sunset. PSBT intents for buy/list; key via x-api-key.",
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
registerProvider({
|
|
165
|
+
id: "jupiter",
|
|
166
|
+
venue: "solana-dex",
|
|
167
|
+
chainIds: [],
|
|
168
|
+
auth: "none",
|
|
169
|
+
ops: ["health", "quote", "prepare"],
|
|
170
|
+
execution: "prepare",
|
|
171
|
+
baseEnv: ["JUPITER_SWAP_API_URL"],
|
|
172
|
+
description: "Jupiter Swap API v1 quote + unsigned user-signature swap transaction preparation",
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
registerProvider({
|
|
176
|
+
id: "hl-perps",
|
|
177
|
+
venue: "hyperliquid",
|
|
178
|
+
chainIds: [],
|
|
179
|
+
auth: "none",
|
|
180
|
+
ops: ["health", "assetInfo", "prepareOrder", "prepareCancel", "prepareLeverage", "prepareIsolatedMargin", "prepareBracket"],
|
|
181
|
+
notes: "Hyperliquid perp orders/leverage. PREPARE-ONLY: returns signable actions, never submits.",
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
registerProvider({
|
|
185
|
+
id: "hl-markets",
|
|
186
|
+
venue: "hyperliquid",
|
|
187
|
+
chainIds: [],
|
|
188
|
+
auth: "none",
|
|
189
|
+
ops: ["health", "markets", "leaderboards", "coin", "spot"],
|
|
190
|
+
notes: "Joined Hyperliquid market datapoints for the Hyperliquid agent. Read-only.",
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
registerProvider({
|
|
194
|
+
id: "hl-staking",
|
|
195
|
+
venue: "hypercore-staking",
|
|
196
|
+
chainIds: [],
|
|
197
|
+
auth: "none",
|
|
198
|
+
ops: [
|
|
199
|
+
"health",
|
|
200
|
+
"validators",
|
|
201
|
+
"delegatorSummary",
|
|
202
|
+
"delegations",
|
|
203
|
+
"rewards",
|
|
204
|
+
"history",
|
|
205
|
+
"preflight",
|
|
206
|
+
"prepareStakeDeposit",
|
|
207
|
+
"prepareStakeWithdraw",
|
|
208
|
+
"prepareDelegate",
|
|
209
|
+
],
|
|
210
|
+
execution: "prepare",
|
|
211
|
+
baseEnv: ["HL_INFO_URL", "HL_EXCHANGE_URL", "HL_TESTNET"],
|
|
212
|
+
description:
|
|
213
|
+
"Hyperliquid HyperCore HYPE staking. Public reads (validators, delegations, rewards) plus EIP-712 prepare for cDeposit / cWithdraw / tokenDelegate. Prepare-only: the user's wallet signs and submits, Oracle never posts to /exchange.",
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
registerProvider({
|
|
217
|
+
id: "magiceden-sol",
|
|
218
|
+
venue: "solana-nft",
|
|
219
|
+
chainIds: [],
|
|
220
|
+
auth: "optionalApiKey",
|
|
221
|
+
ops: ["health", "stats", "listings", "tokenListings", "prepareBuy", "prepareList", "prepareMint"],
|
|
222
|
+
execution: "prepare",
|
|
223
|
+
baseEnv: ["MAGICEDEN_API_KEY", "MAGICEDEN_API_URL"],
|
|
224
|
+
description:
|
|
225
|
+
"Magic Eden Solana NFT market. Reads (stats/listings) are keyless; buy/list/mint instruction builders need MAGICEDEN_API_KEY and return an unsigned base64 transaction for the user's Solana wallet. Never signs or broadcasts.",
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
registerProvider({
|
|
229
|
+
id: "defillama",
|
|
230
|
+
venue: "prices",
|
|
231
|
+
chainIds: [],
|
|
232
|
+
auth: "none",
|
|
233
|
+
ops: ["health", "prices", "pricesBySymbol", "protocols", "yields", "stablecoins", "dexVolumes"],
|
|
234
|
+
baseEnv: ["DEFILLAMA_COINS_URL", "DEFILLAMA_API_URL"],
|
|
235
|
+
description: "DeFiLlama public prices + protocols TVL",
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
registerProvider({
|
|
239
|
+
id: "lifi",
|
|
240
|
+
venue: "dex",
|
|
241
|
+
chainIds: [1, 10, 56, 137, 988, 999, 2741, 4663, 8453, 42161, 43114],
|
|
242
|
+
auth: "none",
|
|
243
|
+
ops: ["health", "quote", "prepare", "chains"],
|
|
244
|
+
execution: "prepare",
|
|
245
|
+
baseEnv: ["LIFI_API_URL"],
|
|
246
|
+
description: "LI.FI public cross-chain / DEX aggregator quotes (no key)",
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
registerProvider({
|
|
250
|
+
id: "dexscreener",
|
|
251
|
+
venue: "dex",
|
|
252
|
+
chainIds: [],
|
|
253
|
+
auth: "none",
|
|
254
|
+
ops: ["health", "token", "search", "pair"],
|
|
255
|
+
baseEnv: ["DEXSCREENER_API_URL"],
|
|
256
|
+
description: "DexScreener public token/pair discovery",
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
registerProvider({
|
|
260
|
+
id: "uniswap-v3",
|
|
261
|
+
venue: "dex",
|
|
262
|
+
chainIds: [1, 8453, 42161],
|
|
263
|
+
auth: "none",
|
|
264
|
+
ops: ["health", "quote", "prepare", "quotePath", "ethUsdc", "chains"],
|
|
265
|
+
execution: "prepare",
|
|
266
|
+
baseEnv: [
|
|
267
|
+
"ETH_RPC_URL",
|
|
268
|
+
"BASE_RPC_URL",
|
|
269
|
+
"ARBITRUM_RPC_URL",
|
|
270
|
+
],
|
|
271
|
+
description: "Uniswap V3 QuoterV2 exact-in quotes via eth_call (ETH/Base/Arb, no key)",
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
registerProvider({
|
|
275
|
+
id: "aerodrome",
|
|
276
|
+
venue: "dex",
|
|
277
|
+
chainIds: [8453],
|
|
278
|
+
auth: "none",
|
|
279
|
+
ops: ["health", "quote", "prepare", "chains"],
|
|
280
|
+
execution: "prepare",
|
|
281
|
+
baseEnv: ["BASE_RPC_URL"],
|
|
282
|
+
description:
|
|
283
|
+
"Aerodrome Slipstream CL on Base — QuoterV2 + SwapRouter exact-input via eth_call (tickSpacing, no key)",
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
registerProvider({
|
|
287
|
+
id: "zerox",
|
|
288
|
+
venue: "dex",
|
|
289
|
+
chainIds: [1, 10, 137, 8453, 42161],
|
|
290
|
+
auth: "apiKey",
|
|
291
|
+
ops: ["health", "price", "quote", "prepare"],
|
|
292
|
+
execution: "prepare",
|
|
293
|
+
baseEnv: ["ZEROX_API_KEY", "ZEROX_API_URL"],
|
|
294
|
+
description:
|
|
295
|
+
"0x Swap API v2 price/quote/prepare — requires ZEROX_API_KEY (unconfigured without key; no Oracle key shipped)",
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
registerProvider({
|
|
299
|
+
id: "across",
|
|
300
|
+
venue: "bridge",
|
|
301
|
+
chainIds: [1, 10, 137, 42161, 8453],
|
|
302
|
+
auth: "none",
|
|
303
|
+
ops: ["health", "suggestedFees"],
|
|
304
|
+
baseEnv: ["ACROSS_API_URL"],
|
|
305
|
+
description: "Across bridge suggested-fees (public)",
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
registerProvider({
|
|
309
|
+
id: "hop",
|
|
310
|
+
venue: "bridge",
|
|
311
|
+
chainIds: [1, 10, 137, 42161],
|
|
312
|
+
auth: "none",
|
|
313
|
+
ops: ["health", "quote"],
|
|
314
|
+
baseEnv: ["HOP_API_URL"],
|
|
315
|
+
description: "Hop Protocol bridge quotes (public)",
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
registerProvider({
|
|
319
|
+
id: "relay",
|
|
320
|
+
venue: "bridge",
|
|
321
|
+
chainIds: [1, 10, 137, 8453, 42161],
|
|
322
|
+
auth: "none",
|
|
323
|
+
ops: ["health", "quote", "prepare"],
|
|
324
|
+
execution: "prepare",
|
|
325
|
+
baseEnv: ["RELAY_API_URL"],
|
|
326
|
+
description: "Relay.link bridge/swap quotes (public)",
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
registerProvider({
|
|
330
|
+
id: "cowswap",
|
|
331
|
+
venue: "dex",
|
|
332
|
+
chainIds: [1, 100, 42161, 8453],
|
|
333
|
+
auth: "none",
|
|
334
|
+
ops: ["health", "quote", "prepareOrder", "order", "status", "chains"],
|
|
335
|
+
execution: "intent",
|
|
336
|
+
baseEnv: [],
|
|
337
|
+
description: "CowSwap batch auction quotes + guarded EIP-712 order intents (public)",
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
registerProvider({
|
|
341
|
+
id: "oneinch",
|
|
342
|
+
venue: "dex",
|
|
343
|
+
chainIds: [1, 10, 137, 8453, 42161],
|
|
344
|
+
auth: "apiKey",
|
|
345
|
+
ops: ["health", "quote", "prepare", "approveSpender"],
|
|
346
|
+
execution: "prepare",
|
|
347
|
+
baseEnv: ["ONEINCH_API_KEY", "ONEINCH_API_URL"],
|
|
348
|
+
description:
|
|
349
|
+
"1inch Swap API v6 quote/prepare — requires ONEINCH_API_KEY (unconfigured without key; no Oracle key shipped)",
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
registerProvider({
|
|
353
|
+
id: "hl-ws",
|
|
354
|
+
venue: "hl",
|
|
355
|
+
chainIds: [],
|
|
356
|
+
auth: "none",
|
|
357
|
+
ops: ["health", "allMids", "l2Book", "snapshot"],
|
|
358
|
+
baseEnv: ["HL_WS_URL"],
|
|
359
|
+
description: "Hyperliquid short-lived WS snapshots (allMids/l2Book)",
|
|
360
|
+
});
|
|
361
|
+
|
|
362
|
+
registerProvider({
|
|
363
|
+
id: "poly-ws",
|
|
364
|
+
venue: "poly",
|
|
365
|
+
chainIds: [137],
|
|
366
|
+
auth: "none",
|
|
367
|
+
ops: ["health", "book", "snapshot"],
|
|
368
|
+
baseEnv: ["POLY_WS_URL"],
|
|
369
|
+
description: "Polymarket CLOB short-lived WS market snapshots",
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
registerProvider({
|
|
373
|
+
id: "opensea-nft",
|
|
374
|
+
venue: "nft",
|
|
375
|
+
chainIds: [1],
|
|
376
|
+
auth: "apiKey",
|
|
377
|
+
ops: ["health", "collection", "floor"],
|
|
378
|
+
baseEnv: ["OPENSEA_API_KEY", "OPENSEA_ENV_FILE"],
|
|
379
|
+
description: "OpenSea collection + floor (OPENSEA_API_KEY)",
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
registerProvider({
|
|
383
|
+
id: "hyperevm-dex",
|
|
384
|
+
venue: "hyperevm",
|
|
385
|
+
chainIds: [999],
|
|
386
|
+
auth: "none",
|
|
387
|
+
ops: ["health", "search", "token"],
|
|
388
|
+
baseEnv: ["HYPEREVM_RPC_URL"],
|
|
389
|
+
description: "HyperEVM pair discovery via DexScreener + optional RPC",
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
registerProvider({
|
|
393
|
+
id: "geckoterminal",
|
|
394
|
+
venue: "dex-data",
|
|
395
|
+
chainIds: [],
|
|
396
|
+
auth: "none",
|
|
397
|
+
ops: ["health", "networks", "pool", "token", "ohlcv"],
|
|
398
|
+
baseEnv: ["GECKOTERMINAL_API_URL"],
|
|
399
|
+
description: "GeckoTerminal public networks, pools, tokens, and OHLCV",
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
registerProvider({
|
|
403
|
+
id: "curve",
|
|
404
|
+
venue: "dex",
|
|
405
|
+
chainIds: [1, 10, 56, 137, 988, 999, 4663, 8453, 42161, 43114],
|
|
406
|
+
auth: "none",
|
|
407
|
+
ops: ["health", "openapi", "pools", "quote", "prepare"],
|
|
408
|
+
execution: "prepare",
|
|
409
|
+
baseEnv: ["CURVE_API_URL"],
|
|
410
|
+
description: "Curve public pool registry API + RouterNG validated single-hop prepare",
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
registerProvider({
|
|
414
|
+
id: "gmx",
|
|
415
|
+
venue: "perps-data",
|
|
416
|
+
chainIds: [42161, 43114],
|
|
417
|
+
auth: "none",
|
|
418
|
+
ops: ["health", "tickers", "markets", "marketsInfo", "tokens", "prepareOrder", "positions", "orderStatus", "verifyOrder"],
|
|
419
|
+
execution: "intent",
|
|
420
|
+
baseEnv: [],
|
|
421
|
+
description: "GMX v2 public oracle/markets plus guarded async order intents on Arbitrum and Avalanche",
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
registerProvider({
|
|
425
|
+
id: "morpho",
|
|
426
|
+
venue: "lending-data",
|
|
427
|
+
chainIds: [1, 10, 137, 2741, 8453, 42161, 4663, 999, 988],
|
|
428
|
+
auth: "none",
|
|
429
|
+
ops: ["health", "markets", "vaults", "prepareVault"],
|
|
430
|
+
execution: "intent",
|
|
431
|
+
baseEnv: ["MORPHO_API_URL"],
|
|
432
|
+
description: "Morpho public GraphQL markets/vaults + guarded ERC-4626 vault intents",
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
registerProvider({
|
|
436
|
+
id: "balancer",
|
|
437
|
+
venue: "dex",
|
|
438
|
+
chainIds: [1, 10, 137, 42161, 43114, 8453],
|
|
439
|
+
auth: "none",
|
|
440
|
+
ops: ["health", "pools", "quote", "prepare"],
|
|
441
|
+
execution: "prepare",
|
|
442
|
+
baseEnv: ["BALANCER_API_URL"],
|
|
443
|
+
description: "Balancer public GraphQL pool data + v3 Router exact-input prepare (Polygon read-only)",
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
registerProvider({
|
|
447
|
+
id: "pendle",
|
|
448
|
+
venue: "yield",
|
|
449
|
+
chainIds: [1, 10, 56, 8453, 42161, 999],
|
|
450
|
+
auth: "none",
|
|
451
|
+
ops: ["health", "markets", "quote", "prepare"],
|
|
452
|
+
execution: "prepare",
|
|
453
|
+
baseEnv: ["PENDLE_API_URL"],
|
|
454
|
+
description: "Pendle public yield-market API + Hosted SDK direct Convert prepare",
|
|
455
|
+
});
|
|
456
|
+
|
|
457
|
+
registerProvider({
|
|
458
|
+
id: "odos",
|
|
459
|
+
venue: "dex",
|
|
460
|
+
chainIds: [1, 10, 56, 137, 8453, 42161, 43114],
|
|
461
|
+
auth: "none",
|
|
462
|
+
ops: ["health", "chains", "quote", "prepare"],
|
|
463
|
+
// Tier is the honest signal here: the API returns HTTP 410 Gone as of
|
|
464
|
+
// 2026-07-30, so it can no longer read or prepare anything. Leaving it as
|
|
465
|
+
// "prepare" would advertise a capability that is provably dead.
|
|
466
|
+
execution: "unavailable",
|
|
467
|
+
deprecated: {
|
|
468
|
+
since: "2026-07-30",
|
|
469
|
+
reason: "Odos sunset the public SOR API; /sor/quote/v2 and v3 both return 410 Gone",
|
|
470
|
+
evidence: "sunset: Thu, 30 Jul 2026 12:00:00 GMT response header",
|
|
471
|
+
},
|
|
472
|
+
baseEnv: ["ODOS_API_URL"],
|
|
473
|
+
description: "Odos public SOR (DEPRECATED upstream 2026-07-30 -- endpoint returns 410)",
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
registerProvider({
|
|
477
|
+
id: "blockscout",
|
|
478
|
+
venue: "explorer",
|
|
479
|
+
chainIds: [1, 10, 137, 8453, 42161],
|
|
480
|
+
auth: "none",
|
|
481
|
+
ops: ["health", "stats", "address", "token"],
|
|
482
|
+
baseEnv: [],
|
|
483
|
+
description: "Verified public Blockscout REST v2 instances",
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
registerProvider({
|
|
487
|
+
id: "paraswap",
|
|
488
|
+
venue: "dex",
|
|
489
|
+
chainIds: [1, 10, 56, 137, 8453, 42161, 43114],
|
|
490
|
+
auth: "none",
|
|
491
|
+
ops: ["health", "tokens", "price", "quote", "prepare"],
|
|
492
|
+
execution: "prepare",
|
|
493
|
+
baseEnv: ["PARASWAP_API_URL"],
|
|
494
|
+
description: "ParaSwap/Velora public price routes + validated transaction builder",
|
|
495
|
+
});
|