@oracle-agent/oracle 0.13.1 → 0.14.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/CONTRIBUTING.md +99 -0
- package/README.md +20 -14
- package/SECURITY.md +6 -8
- package/SETUP.md +25 -27
- package/bin/desk-server.mjs +473 -0
- package/bin/oracle-data-mcp.mjs +1252 -0
- package/bin/oracle-equities.mjs +168 -0
- package/bin/oracle-init.mjs +525 -0
- package/bin/oracle-public-server.mjs +36 -0
- package/bin/oracle-route.mjs +254 -0
- package/bin/oracle-scan.mjs +192 -0
- package/bin/oracle-upgrade.mjs +42 -0
- package/bin/oracle.mjs +34 -0
- package/docs/adding-a-chain.md +229 -0
- package/docs/architecture.md +139 -0
- package/docs/buzz-integration.md +115 -0
- package/docs/cli.md +143 -0
- package/docs/connectors.md +13 -0
- package/docs/hyperliquid-builder-code.md +50 -0
- package/docs/locals-only-fee-waiver.md +34 -0
- package/docs/oracle-pack-standard.md +29 -0
- package/docs/profiles.md +151 -0
- package/docs/public-surface.md +206 -0
- package/examples/add-a-chain.mjs +65 -0
- package/examples/oracle-pack-template.mjs +38 -0
- package/examples/research-a-token.mjs +70 -0
- package/package.json +78 -32
- package/plugins/oracle-owner-gate/__init__.py +288 -0
- package/plugins/oracle-owner-gate/plugin.yaml +9 -0
- package/{dist/assets/profiles → profiles}/oracle/SOUL.md +0 -14
- package/protocols/templates/safe-erc20/SECURITY.md +16 -0
- package/protocols/templates/safe-erc20/foundry.toml +12 -0
- package/protocols/templates/safe-erc20/remappings.txt +2 -0
- package/protocols/templates/safe-erc20/src/SafeERC20.sol +53 -0
- package/protocols/templates/safe-erc20/test/SafeERC20.t.sol +72 -0
- package/public/oracle-splash/_variants/ice.html +3 -3
- package/public/oracle-splash/_variants/ivory.html +3 -3
- package/public/oracle-splash/downloads/index.html +34 -223
- package/public/oracle-splash/index.html +11 -11
- package/scripts/adversarial-bench.mjs +114 -0
- package/scripts/build-dist.mjs +119 -0
- package/scripts/build-inscription.py +230 -0
- package/scripts/check-doc-drift.mjs +123 -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/guard-publish.mjs +22 -0
- package/scripts/protocol-template-gate.mjs +15 -0
- package/scripts/public-api-scan.mjs +23 -0
- package/scripts/publish-dist.mjs +67 -0
- package/scripts/record-hero-cli.sh +80 -0
- package/scripts/secret-scan.mjs +169 -0
- package/scripts/smoke-dist-bins.mjs +89 -0
- package/scripts/verify-dist.mjs +29 -0
- package/scripts/verify-v3-venues.mjs +233 -0
- package/skins/oracle.yaml +56 -0
- package/src/action-receipts.mjs +265 -0
- package/src/action-semantics.mjs +62 -0
- package/src/address-book.mjs +208 -0
- package/src/agent-auth.mjs +206 -0
- package/src/approval-guard.mjs +282 -0
- package/src/attestation-secret.mjs +94 -0
- package/src/audit-log.mjs +196 -0
- package/src/auth/oauth.mjs +672 -0
- package/src/auto-slippage.mjs +378 -0
- package/src/capability-posture.mjs +125 -0
- package/src/cards.mjs +422 -0
- package/src/chains.mjs +62 -0
- package/src/cli/chain-catalog.mjs +215 -0
- package/src/cli/chain-state.mjs +74 -0
- package/src/cli/commands/auth.mjs +193 -0
- package/src/cli/commands/bootstrap.mjs +87 -0
- package/src/cli/commands/chain.mjs +143 -0
- package/src/cli/commands/chat.mjs +465 -0
- package/src/cli/commands/credential.mjs +9 -0
- package/src/cli/commands/data-mcp.mjs +18 -0
- package/src/cli/commands/data.mjs +75 -0
- package/src/cli/commands/doctor.mjs +136 -0
- package/src/cli/commands/equities.mjs +41 -0
- package/src/cli/commands/farm.mjs +129 -0
- package/src/cli/commands/fees.mjs +109 -0
- package/src/cli/commands/follow.mjs +130 -0
- package/src/cli/commands/harness.mjs +63 -0
- package/src/cli/commands/help.mjs +7 -0
- package/src/cli/commands/init.mjs +27 -0
- package/src/cli/commands/mcp.mjs +154 -0
- package/src/cli/commands/model.mjs +106 -0
- package/src/cli/commands/plugins.mjs +275 -0
- package/src/cli/commands/prepare.mjs +12 -0
- package/src/cli/commands/public.mjs +20 -0
- package/src/cli/commands/resolve.mjs +64 -0
- package/src/cli/commands/route.mjs +12 -0
- package/src/cli/commands/runner.mjs +9 -0
- package/src/cli/commands/scan.mjs +12 -0
- package/src/cli/commands/setup.mjs +294 -0
- package/src/cli/commands/sign.mjs +21 -0
- package/src/cli/commands/signer.mjs +9 -0
- package/src/cli/commands/swap.mjs +102 -0
- package/src/cli/commands/upgrade.mjs +12 -0
- package/src/cli/commands/vault.mjs +9 -0
- package/src/cli/commands/version.mjs +22 -0
- package/src/cli/first-run.mjs +23 -0
- package/src/cli/kernel.mjs +262 -0
- package/src/cli/mcp-targets/chatgpt.mjs +51 -0
- package/src/cli/mcp-targets/claude-code.mjs +39 -0
- package/src/cli/mcp-targets/claude-desktop.mjs +24 -0
- package/src/cli/mcp-targets/codex.mjs +41 -0
- package/src/cli/mcp-targets/cursor.mjs +32 -0
- package/src/cli/mcp-targets/shared.mjs +71 -0
- package/src/cli/mcp-targets/vscode.mjs +39 -0
- package/src/cli/messaging-platforms.mjs +217 -0
- package/src/cli/model-config.mjs +78 -0
- package/src/cli/operator-dispatch.mjs +194 -0
- package/src/cli/oracle-harness.py +415 -0
- package/src/cli/paths.mjs +107 -0
- package/src/cli/runtime.mjs +351 -0
- package/src/cli/setup-state.mjs +168 -0
- package/src/cli/spawn-child.mjs +43 -0
- package/src/data/catalog.mjs +858 -0
- package/src/data/desk-data.mjs +877 -0
- package/src/data/http.mjs +253 -0
- package/src/data/names.mjs +188 -0
- package/src/data/provider-endpoint.mjs +94 -0
- package/src/data/providers/aave-v3.mjs +139 -0
- package/src/data/providers/across-bridge.mjs +41 -0
- package/src/data/providers/aerodrome.mjs +245 -0
- package/src/data/providers/aevo.mjs +33 -0
- package/src/data/providers/approval-indexer.mjs +133 -0
- package/src/data/providers/approvals.mjs +594 -0
- package/src/data/providers/babylon-staking.mjs +149 -0
- package/src/data/providers/balancer.mjs +209 -0
- package/src/data/providers/beefy-yields.mjs +45 -0
- package/src/data/providers/birdeye-tokens.mjs +33 -0
- package/src/data/providers/bisq-markets.mjs +145 -0
- package/src/data/providers/bitcoin-esplora.mjs +216 -0
- package/src/data/providers/bitcoin-meta.mjs +378 -0
- package/src/data/providers/blockscout.mjs +14 -0
- package/src/data/providers/bob-rootstock.mjs +198 -0
- package/src/data/providers/braiins-insights.mjs +103 -0
- package/src/data/providers/bridge-aggregator.mjs +259 -0
- package/src/data/providers/bridges.mjs +242 -0
- package/src/data/providers/bungee.mjs +29 -0
- package/src/data/providers/celestia-da.mjs +38 -0
- package/src/data/providers/changenow.mjs +135 -0
- package/src/data/providers/compound.mjs +32 -0
- package/src/data/providers/connext.mjs +28 -0
- package/src/data/providers/convex.mjs +30 -0
- package/src/data/providers/cow-protocol.mjs +110 -0
- package/src/data/providers/cowswap.mjs +415 -0
- package/src/data/providers/curve.mjs +201 -0
- package/src/data/providers/das-assets.mjs +59 -0
- package/src/data/providers/debridge.mjs +109 -0
- package/src/data/providers/defillama.mjs +88 -0
- package/src/data/providers/dexscreener.mjs +43 -0
- package/src/data/providers/drift.mjs +32 -0
- package/src/data/providers/dydx.mjs +41 -0
- package/src/data/providers/evm-rpc.mjs +225 -0
- package/src/data/providers/farming.mjs +291 -0
- package/src/data/providers/geckoterminal.mjs +34 -0
- package/src/data/providers/gmx.mjs +496 -0
- package/src/data/providers/hiro-stacks.mjs +150 -0
- package/src/data/providers/hl-assets.mjs +165 -0
- package/src/data/providers/hl-info.mjs +108 -0
- package/src/data/providers/hl-markets.mjs +210 -0
- package/src/data/providers/hl-outcome.mjs +61 -0
- package/src/data/providers/hl-perps.mjs +419 -0
- package/src/data/providers/hl-staking.mjs +353 -0
- package/src/data/providers/hl-ws.mjs +119 -0
- package/src/data/providers/hyperevm-dex.mjs +49 -0
- package/src/data/providers/jito-mev.mjs +117 -0
- package/src/data/providers/jupiter-venues.mjs +119 -0
- package/src/data/providers/jupiter.mjs +315 -0
- package/src/data/providers/kamino-strategies.mjs +143 -0
- package/src/data/providers/l2beat-tvl.mjs +42 -0
- package/src/data/providers/lifi.mjs +166 -0
- package/src/data/providers/liquid-esplora.mjs +152 -0
- package/src/data/providers/magiceden-ordinals.mjs +141 -0
- package/src/data/providers/magiceden-sol.mjs +406 -0
- package/src/data/providers/mempool-lightning.mjs +144 -0
- package/src/data/providers/mempool-mining.mjs +142 -0
- package/src/data/providers/meteora-dlmm.mjs +168 -0
- package/src/data/providers/morpho.mjs +177 -0
- package/src/data/providers/nft-gallery.mjs +163 -0
- package/src/data/providers/nft-portfolio.mjs +494 -0
- package/src/data/providers/odos.mjs +156 -0
- package/src/data/providers/ondo.mjs +31 -0
- package/src/data/providers/oneinch.mjs +174 -0
- package/src/data/providers/opensea-multichain.mjs +136 -0
- package/src/data/providers/opensea-nft.mjs +371 -0
- package/src/data/providers/orca.mjs +29 -0
- package/src/data/providers/ordinals-runes.mjs +180 -0
- package/src/data/providers/pancakeswap.mjs +28 -0
- package/src/data/providers/paraswap.mjs +125 -0
- package/src/data/providers/pendle.mjs +188 -0
- package/src/data/providers/poly-clob.mjs +283 -0
- package/src/data/providers/poly-public.mjs +96 -0
- package/src/data/providers/poly-ws.mjs +103 -0
- package/src/data/providers/polygon-staking.mjs +227 -0
- package/src/data/providers/portfolio-history.mjs +394 -0
- package/src/data/providers/portfolio.mjs +600 -0
- package/src/data/providers/pyth-price-feeds.mjs +172 -0
- package/src/data/providers/raydium.mjs +35 -0
- package/src/data/providers/relayscan-mev.mjs +72 -0
- package/src/data/providers/rfq.mjs +15 -0
- package/src/data/providers/rh-agent.mjs +59 -0
- package/src/data/providers/sanctum-lst.mjs +180 -0
- package/src/data/providers/satflow.mjs +341 -0
- package/src/data/providers/signed-material-guard.mjs +108 -0
- package/src/data/providers/solana-rpc.mjs +197 -0
- package/src/data/providers/solend-lending.mjs +166 -0
- package/src/data/providers/spark-lend.mjs +42 -0
- package/src/data/providers/squid-router.mjs +29 -0
- package/src/data/providers/stargate.mjs +29 -0
- package/src/data/providers/sushiswap.mjs +30 -0
- package/src/data/providers/symbiotic-restaking.mjs +41 -0
- package/src/data/providers/thorchain.mjs +36 -0
- package/src/data/providers/traderjoe.mjs +28 -0
- package/src/data/providers/twap.mjs +152 -0
- package/src/data/providers/uniswap-v3.mjs +457 -0
- package/src/data/providers/uniswap-v4.mjs +414 -0
- package/src/data/providers/vertex.mjs +41 -0
- package/src/data/providers/wallet-watch.mjs +264 -0
- package/src/data/providers/wormhole.mjs +28 -0
- package/src/data/providers/yearn.mjs +31 -0
- package/src/data/providers/zerox.mjs +167 -0
- package/src/data/public-api-scan.mjs +61 -0
- package/src/data/quote-placeholder.mjs +31 -0
- package/src/desk/swap-prepare.mjs +194 -0
- package/src/equities/bridge.mjs +388 -0
- package/src/equities/fixtures/bridge_routes.json +159 -0
- package/src/equities/fixtures/dst_transitions.json +29 -0
- package/src/equities/fixtures/equity_dex_pools.json +154 -0
- package/src/equities/fixtures/hip3_l2books.json +2711 -0
- package/src/equities/fixtures/nyse_holidays.json +1 -0
- package/src/equities/fixtures/oracles.json +100 -0
- package/src/equities/fixtures/rh_pool_state.json +244 -0
- package/src/equities/fixtures/solana_xstocks.json +704 -0
- package/src/equities/fixtures/ton_xstocks.json +35 -0
- package/src/equities/fixtures/universe.json +411 -0
- package/src/equities/fixtures/venues.json +3542 -0
- package/src/equities/fixtures.mjs +405 -0
- package/src/equities/funding.mjs +142 -0
- package/src/equities/index.mjs +166 -0
- package/src/equities/liveness.mjs +148 -0
- package/src/equities/marketHours.mjs +249 -0
- package/src/equities/normalize.mjs +295 -0
- package/src/equities/num.mjs +146 -0
- package/src/equities/prepare.mjs +95 -0
- package/src/equities/rank.mjs +260 -0
- package/src/equities/sourceNum.mjs +69 -0
- package/src/equities/types.mjs +220 -0
- package/src/equities/venues/arcus-perp.mjs +84 -0
- package/src/equities/venues/arcus-spot.mjs +105 -0
- package/src/equities/venues/hyperliquid-hip3.mjs +224 -0
- package/src/equities/venues/rh-uniswap.mjs +216 -0
- package/src/equities/venues/solana-xstocks.mjs +139 -0
- package/src/equities/venues/ton-stonfi.mjs +139 -0
- package/src/exact-integer.mjs +72 -0
- package/src/exec-policy.mjs +419 -0
- package/src/flags.mjs +15 -0
- package/src/fresh-window.mjs +76 -0
- package/src/gmx-attestation.mjs +176 -0
- package/src/index.mjs +107 -0
- package/src/licensing/locals-only.mjs +25 -0
- package/src/nft-gas-war-guard.mjs +139 -0
- package/src/onboarding/agent-keys.mjs +161 -0
- package/src/onboarding/harness-configs.mjs +102 -0
- package/src/onboarding/index.mjs +18 -0
- package/src/onboarding/tiers.mjs +139 -0
- package/src/oracle-env.mjs +55 -0
- package/src/package-manifest.mjs +42 -0
- package/src/plugins/agent-plugin-loader.mjs +225 -0
- package/src/portfolio-risk.mjs +170 -0
- package/src/prepare-envelope.mjs +204 -0
- package/src/profile-upgrade.mjs +277 -0
- package/src/protocol-execution.mjs +84 -0
- package/src/protocol-templates/gate.mjs +179 -0
- package/src/protocol-templates/prepare-deploy.mjs +81 -0
- package/src/public-api/agent-grants.mjs +57 -0
- package/src/public-api/buzz-integration.mjs +267 -0
- package/src/public-api/connect-agent.mjs +424 -0
- package/src/public-api/grants.mjs +142 -0
- package/src/public-api/http.mjs +707 -0
- package/src/public-api/metering.mjs +111 -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 +357 -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 +322 -0
- package/src/public-control/runtime-config.mjs +275 -0
- package/src/public-control/session-key-model.mjs +379 -0
- package/src/public-control/session-orchestrator.mjs +418 -0
- package/src/rfq/intent.mjs +180 -0
- package/src/rfq/sources.mjs +181 -0
- package/src/route-attestation.mjs +132 -0
- package/src/router/best-execution.mjs +326 -0
- package/src/router/index.mjs +250 -0
- package/src/router/integrator-fee.mjs +135 -0
- package/src/router/prepare-bridge.mjs +293 -0
- package/src/router/prepare-route.mjs +398 -0
- package/src/router/proposal.mjs +311 -0
- package/src/router/risk-classifier.mjs +119 -0
- package/src/router/route-sources.mjs +364 -0
- package/src/scanner/chains.config.mjs +543 -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 +351 -0
- package/src/scanner/v3-venue.mjs +308 -0
- package/src/scopes.mjs +44 -0
- package/src/sell-simulation.mjs +167 -0
- package/src/signals/engine.mjs +146 -0
- package/src/signals/index.mjs +1 -0
- package/src/token-transfer-guard.mjs +188 -0
- package/src/tui/app.mjs +438 -0
- package/src/tui/backend.mjs +215 -0
- package/src/tui/format.mjs +272 -0
- package/src/tui/gateway-client.mjs +177 -0
- package/src/tui/input.mjs +501 -0
- package/src/tui/memory.mjs +105 -0
- package/src/tui/meta-learn.mjs +85 -0
- package/src/tui/renderer.mjs +443 -0
- package/src/tui/scheduler.mjs +205 -0
- package/src/tui/skills-loader.mjs +140 -0
- package/src/tui/standalone-client.mjs +752 -0
- package/src/tui/theme.mjs +81 -0
- package/src/vault-attestation.mjs +146 -0
- package/src/venues.mjs +206 -0
- package/src/watch-preferences.mjs +85 -0
- package/dist/action-receipts.mjs +0 -1
- package/dist/action-semantics.mjs +0 -1
- package/dist/address-book.mjs +0 -2
- package/dist/bin/desk-server.mjs +0 -59
- package/dist/bin/oracle-data-mcp.mjs +0 -8
- package/dist/bin/oracle-equities.mjs +0 -20
- package/dist/bin/oracle-init.mjs +0 -24
- package/dist/bin/oracle-public-server.mjs +0 -5
- package/dist/bin/oracle-route.mjs +0 -22
- package/dist/bin/oracle-scan.mjs +0 -18
- package/dist/bin/oracle-upgrade.mjs +0 -21
- package/dist/bin/oracle.mjs +0 -76
- package/dist/chains.mjs +0 -1
- package/dist/cli/commands/auth.mjs +0 -16
- package/dist/cli/commands/bootstrap.mjs +0 -18
- package/dist/cli/commands/chain.mjs +0 -21
- package/dist/cli/commands/chat.mjs +0 -45
- package/dist/cli/commands/credential.mjs +0 -1
- package/dist/cli/commands/data-mcp.mjs +0 -2
- package/dist/cli/commands/data.mjs +0 -12
- package/dist/cli/commands/doctor.mjs +0 -5
- package/dist/cli/commands/equities.mjs +0 -15
- package/dist/cli/commands/farm.mjs +0 -59
- package/dist/cli/commands/follow.mjs +0 -28
- package/dist/cli/commands/gate.mjs +0 -13
- package/dist/cli/commands/harness.mjs +0 -15
- package/dist/cli/commands/help.mjs +0 -1
- package/dist/cli/commands/init.mjs +0 -3
- package/dist/cli/commands/mcp.mjs +0 -60
- package/dist/cli/commands/model.mjs +0 -54
- package/dist/cli/commands/plugins.mjs +0 -38
- package/dist/cli/commands/prepare.mjs +0 -2
- package/dist/cli/commands/public.mjs +0 -3
- package/dist/cli/commands/resolve.mjs +0 -23
- package/dist/cli/commands/route.mjs +0 -2
- package/dist/cli/commands/runner.mjs +0 -1
- package/dist/cli/commands/scan.mjs +0 -2
- package/dist/cli/commands/setup.mjs +0 -34
- package/dist/cli/commands/sign.mjs +0 -21
- package/dist/cli/commands/signer.mjs +0 -1
- package/dist/cli/commands/swap.mjs +0 -36
- package/dist/cli/commands/upgrade.mjs +0 -2
- package/dist/cli/commands/vault.mjs +0 -1
- package/dist/cli/commands/version.mjs +0 -2
- package/dist/data/desk-data.mjs +0 -55
- package/dist/data/names.mjs +0 -2
- package/dist/data/providers/farming.mjs +0 -2
- package/dist/equities/index.mjs +0 -1
- package/dist/index.mjs +0 -60
- package/dist/nft-gas-war-guard.mjs +0 -1
- package/dist/onboarding/harness-configs.mjs +0 -4
- package/dist/portfolio-risk.mjs +0 -1
- package/dist/prepare-envelope.mjs +0 -1
- package/dist/public-api/agent-grants.mjs +0 -3
- package/dist/public-control/policy-schema.mjs +0 -1
- package/dist/router/index.mjs +0 -2
- package/dist/scanner/index.mjs +0 -4
- package/dist/signals/index.mjs +0 -1
- package/dist/watch-preferences.mjs +0 -1
- /package/{dist/assets/profiles → profiles}/_template/SOUL.md +0 -0
- /package/{dist/assets/profiles → profiles}/_template/profile.json +0 -0
- /package/{dist/assets/profiles → profiles}/bitcoin-agent/SOUL.md +0 -0
- /package/{dist/assets/profiles → profiles}/bitcoin-agent/profile.json +0 -0
- /package/{dist/assets/profiles → profiles}/hyperliquid-agent/SOUL.md +0 -0
- /package/{dist/assets/profiles → profiles}/hyperliquid-agent/profile.json +0 -0
- /package/{dist/assets/profiles → profiles}/oracle/profile.json +0 -0
- /package/{dist/assets/profiles → profiles}/polymarket-agent/SOUL.md +0 -0
- /package/{dist/assets/profiles → profiles}/polymarket-agent/profile.json +0 -0
- /package/{dist/assets/profiles → profiles}/profile.schema.json +0 -0
- /package/{dist/assets/profiles → profiles}/protocol-builder/SOUL.md +0 -0
- /package/{dist/assets/profiles → profiles}/protocol-builder/profile.json +0 -0
- /package/{dist/assets/profiles → profiles}/robinhood-agent/SOUL.md +0 -0
- /package/{dist/assets/profiles → profiles}/robinhood-agent/profile.json +0 -0
- /package/{dist/assets/profiles → profiles}/solana-agent/SOUL.md +0 -0
- /package/{dist/assets/profiles → profiles}/solana-agent/profile.json +0 -0
- /package/{dist/assets/profiles → profiles}/stable-agent/SOUL.md +0 -0
- /package/{dist/assets/profiles → profiles}/stable-agent/profile.json +0 -0
- /package/{dist/assets/skills → skills}/balance/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/bitcoin-l1.md +0 -0
- /package/{dist/assets/skills → skills}/chain-defi-ecosystem-profiling.md +0 -0
- /package/{dist/assets/skills → skills}/evm-contract-research.md +0 -0
- /package/{dist/assets/skills → skills}/hyperliquid.md +0 -0
- /package/{dist/assets/skills → skills}/multichain-exec-desk.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-action-semantics/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-best-execution/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-best-execution.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-bitcoin/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-chain-graphs-telegram-cards/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-chat/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-chat/chain.SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-chat/setup.SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-circuit-breaker/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-contract-research/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-desk/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-desk.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-dex-launch/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-equities/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-grants/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-hypercore-staking/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-hyperliquid/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-meme-token-sniper/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-multichain-nft-launch/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-multichain-token-launch/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-nft-gacha-launch/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-nft-mint-gas-war/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-polymarket/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-protocol-builder/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-protocol-security/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-public-product/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-receipts/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-receipts.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-rfq-tokenized-assets/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-smart-wallet-scanner/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-solana/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-solana-nft/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/oracle-token-research/SKILL.md +0 -0
- /package/{dist/assets/skills → skills}/solana.md +0 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// Babylon BTC staking — keyless read plane (staking-api.babylonlabs.io v2).
|
|
2
|
+
//
|
|
3
|
+
// Why this exists: Babylon is the largest native-BTC staking protocol, and its
|
|
4
|
+
// public v2 API answers the question Oracle actually needs — "what is THIS
|
|
5
|
+
// staker's BTC position?" — without a key, without an account, and without the
|
|
6
|
+
// user handing over anything but a public key.
|
|
7
|
+
//
|
|
8
|
+
// Verified live (v2):
|
|
9
|
+
// GET /v2/stats 200 APR / TVL / delegation counts
|
|
10
|
+
// GET /v2/finality-providers 200 FP roster + state + commission
|
|
11
|
+
// GET /v2/delegations?staker_pk_hex=<pk> 200 per-staker positions (paginated)
|
|
12
|
+
//
|
|
13
|
+
// Read-only. No signing, no unbonding, no withdrawal. Staking actions are
|
|
14
|
+
// user-wallet operations and are deliberately absent from this module.
|
|
15
|
+
|
|
16
|
+
import { httpJson } from "../http.mjs";
|
|
17
|
+
|
|
18
|
+
export const BABYLON_STAKING_API = "https://staking-api.babylonlabs.io";
|
|
19
|
+
|
|
20
|
+
function baseUrl(opts = {}) {
|
|
21
|
+
return String(opts.baseUrl || process.env.BABYLON_STAKING_API_URL || BABYLON_STAKING_API).replace(/\/$/, "");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function get(path, opts = {}) {
|
|
25
|
+
return httpJson(`${baseUrl(opts)}${path.startsWith("/") ? path : `/${path}`}`, {
|
|
26
|
+
fetchImpl: opts.fetchImpl,
|
|
27
|
+
timeoutMs: opts.timeoutMs ?? 15_000,
|
|
28
|
+
headers: { Accept: "application/json" },
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Babylon identifies stakers and finality providers by 32-byte x-only BTC
|
|
34
|
+
* public keys (64 hex chars). Accept the 33-byte compressed form too and drop
|
|
35
|
+
* the parity byte, because that is what most wallets hand the user.
|
|
36
|
+
*/
|
|
37
|
+
export function babylonPkHex(value, label = "pkHex") {
|
|
38
|
+
const text = String(value || "").trim().toLowerCase().replace(/^0x/, "");
|
|
39
|
+
if (!/^[0-9a-f]+$/.test(text)) throw new Error(`babylon-staking: ${label} must be hex`);
|
|
40
|
+
if (text.length === 66 && (text.startsWith("02") || text.startsWith("03"))) return text.slice(2);
|
|
41
|
+
if (text.length !== 64) throw new Error(`babylon-staking: ${label} must be a 64-char x-only (or 66-char compressed) BTC public key`);
|
|
42
|
+
return text;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export async function babylonHealth(opts = {}) {
|
|
46
|
+
try {
|
|
47
|
+
const res = await get("/v2/stats", opts);
|
|
48
|
+
const data = res?.data || {};
|
|
49
|
+
const tvl = Number(data.active_tvl ?? 0);
|
|
50
|
+
return {
|
|
51
|
+
ok: Number.isFinite(tvl) && tvl > 0,
|
|
52
|
+
provider: "babylon-staking",
|
|
53
|
+
baseUrl: baseUrl(opts),
|
|
54
|
+
activeTvlSats: String(data.active_tvl ?? ""),
|
|
55
|
+
activeFinalityProviders: data.active_finality_providers ?? null,
|
|
56
|
+
exec: false,
|
|
57
|
+
};
|
|
58
|
+
} catch (error) {
|
|
59
|
+
return {
|
|
60
|
+
ok: false,
|
|
61
|
+
provider: "babylon-staking",
|
|
62
|
+
baseUrl: baseUrl(opts),
|
|
63
|
+
error: String(error?.message || error),
|
|
64
|
+
exec: false,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Protocol-wide staking stats: TVL in sats, delegation counts, BTC staking APR. */
|
|
70
|
+
export async function babylonStats(_args = {}, opts = {}) {
|
|
71
|
+
const res = await get("/v2/stats", opts);
|
|
72
|
+
const d = res?.data || {};
|
|
73
|
+
return {
|
|
74
|
+
provider: "babylon-staking",
|
|
75
|
+
activeTvlSats: String(d.active_tvl ?? ""),
|
|
76
|
+
totalActiveTvlSats: String(d.total_active_tvl ?? ""),
|
|
77
|
+
activeDelegations: d.active_delegations ?? null,
|
|
78
|
+
totalActiveDelegations: d.total_active_delegations ?? null,
|
|
79
|
+
activeFinalityProviders: d.active_finality_providers ?? null,
|
|
80
|
+
totalFinalityProviders: d.total_finality_providers ?? null,
|
|
81
|
+
// APRs arrive as fractions (0.00042 = 0.042%). Surface both so a caller
|
|
82
|
+
// cannot silently render a fraction as a percent.
|
|
83
|
+
btcStakingApr: d.btc_staking_apr ?? null,
|
|
84
|
+
btcStakingAprPct: d.btc_staking_apr == null ? null : Number(d.btc_staking_apr) * 100,
|
|
85
|
+
maxStakingApr: d.max_staking_apr ?? null,
|
|
86
|
+
maxStakingAprPct: d.max_staking_apr == null ? null : Number(d.max_staking_apr) * 100,
|
|
87
|
+
raw: d,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Finality provider roster. Optional `state` filter, e.g. FINALITY_PROVIDER_STATUS_ACTIVE. */
|
|
92
|
+
export async function babylonFinalityProviders(args = {}, opts = {}) {
|
|
93
|
+
const res = await get("/v2/finality-providers", opts);
|
|
94
|
+
let rows = Array.isArray(res?.data) ? res.data : [];
|
|
95
|
+
if (args.state) {
|
|
96
|
+
const want = String(args.state).trim().toUpperCase();
|
|
97
|
+
rows = rows.filter((r) => String(r.state || "").toUpperCase().includes(want));
|
|
98
|
+
}
|
|
99
|
+
if (args.btcPk) {
|
|
100
|
+
const pk = babylonPkHex(args.btcPk, "btcPk");
|
|
101
|
+
rows = rows.filter((r) => String(r.btc_pk || "").toLowerCase() === pk);
|
|
102
|
+
}
|
|
103
|
+
const limit = Math.min(500, Math.max(1, Number(args.limit || rows.length || 1)));
|
|
104
|
+
return {
|
|
105
|
+
provider: "babylon-staking",
|
|
106
|
+
count: rows.length,
|
|
107
|
+
finalityProviders: rows.slice(0, limit).map((r) => ({
|
|
108
|
+
btcPk: r.btc_pk ?? null,
|
|
109
|
+
moniker: r.description?.moniker ?? null,
|
|
110
|
+
website: r.description?.website ?? null,
|
|
111
|
+
state: r.state ?? null,
|
|
112
|
+
commission: r.commission ?? null,
|
|
113
|
+
activeTvlSats: r.active_tvl == null ? null : String(r.active_tvl),
|
|
114
|
+
activeDelegations: r.active_delegations ?? null,
|
|
115
|
+
})),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Per-staker BTC delegations. This is the keyless per-user position read: the
|
|
121
|
+
* caller supplies only a PUBLIC key, so nothing here is custodial.
|
|
122
|
+
*/
|
|
123
|
+
export async function babylonDelegations(args = {}, opts = {}) {
|
|
124
|
+
const stakerPk = babylonPkHex(args.stakerPkHex || args.stakerPk || args.pkHex || args.pk, "stakerPkHex");
|
|
125
|
+
const params = new URLSearchParams({ staker_pk_hex: stakerPk });
|
|
126
|
+
if (args.paginationKey) params.set("pagination_key", String(args.paginationKey));
|
|
127
|
+
const res = await get(`/v2/delegations?${params}`, opts);
|
|
128
|
+
const rows = Array.isArray(res?.data) ? res.data : [];
|
|
129
|
+
const totalSats = rows.reduce((n, r) => n + Number(r.delegation_staking?.staking_amount ?? r.staking_amount ?? 0), 0);
|
|
130
|
+
return {
|
|
131
|
+
provider: "babylon-staking",
|
|
132
|
+
stakerPkHex: stakerPk,
|
|
133
|
+
count: rows.length,
|
|
134
|
+
totalStakedSats: String(totalSats),
|
|
135
|
+
nextKey: res?.pagination?.next_key || null,
|
|
136
|
+
delegations: rows.map((r) => ({
|
|
137
|
+
stakingTxHashHex: r.delegation_staking?.staking_tx_hash_hex ?? r.staking_tx_hash_hex ?? null,
|
|
138
|
+
state: r.state ?? null,
|
|
139
|
+
stakingAmountSats:
|
|
140
|
+
r.delegation_staking?.staking_amount == null && r.staking_amount == null
|
|
141
|
+
? null
|
|
142
|
+
: String(r.delegation_staking?.staking_amount ?? r.staking_amount),
|
|
143
|
+
stakingTimelock: r.delegation_staking?.staking_timelock ?? null,
|
|
144
|
+
startHeight: r.delegation_staking?.start_height ?? null,
|
|
145
|
+
finalityProviderBtcPks: r.finality_provider_btc_pks_hex ?? null,
|
|
146
|
+
})),
|
|
147
|
+
raw: rows,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
// Balancer public GraphQL API + v3 Router exact-input prepare. No key.
|
|
2
|
+
import { Interface, getAddress, isAddress } from "ethers";
|
|
3
|
+
import { httpJson } from "../http.mjs";
|
|
4
|
+
import { rpcCall as defaultRpcCall } from "./evm-rpc.mjs";
|
|
5
|
+
import { attachAutoSlippage, bindAutoSlippageGuardToCall } from "../../auto-slippage.mjs";
|
|
6
|
+
import { stampPrepared } from "../../prepare-envelope.mjs";
|
|
7
|
+
|
|
8
|
+
export const BALANCER_API = "https://api-v3.balancer.fi/";
|
|
9
|
+
const endpoint = (o = {}) => o.baseUrl || process.env.BALANCER_API_URL || BALANCER_API;
|
|
10
|
+
|
|
11
|
+
async function gql(query, variables, opts = {}) {
|
|
12
|
+
return httpJson(endpoint(opts), {
|
|
13
|
+
method: "POST",
|
|
14
|
+
body: { query, variables },
|
|
15
|
+
fetchImpl: opts.fetchImpl,
|
|
16
|
+
timeoutMs: opts.timeoutMs ?? 20_000,
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const POOLS_QUERY = `query Pools($first: Int, $where: GqlPoolFilter) { poolGetPools(first: $first, where: $where) { id address chain type protocolVersion dynamicData { totalLiquidity volume24h fees24h } } }`;
|
|
21
|
+
|
|
22
|
+
// Official Balancer v3 Router deployments; bytecode checked via eth_getCode on
|
|
23
|
+
// 2026-07-23. Polygon is intentionally excluded from this v3 prepare slice.
|
|
24
|
+
export const BALANCER_V3_CHAINS = Object.freeze({
|
|
25
|
+
1: {
|
|
26
|
+
name: "ethereum",
|
|
27
|
+
router: "0xAE563E3f8219521950555F5962419C8919758Ea2",
|
|
28
|
+
weth: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
|
|
29
|
+
usdc: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
30
|
+
},
|
|
31
|
+
10: {
|
|
32
|
+
name: "optimism",
|
|
33
|
+
router: "0xe2fa4e1d17725e72dcdAfe943Ecf45dF4B9E285b",
|
|
34
|
+
weth: "0x4200000000000000000000000000000000000006",
|
|
35
|
+
usdc: "0x0b2c639c533813f4aa9d7837caf62653d097ff85",
|
|
36
|
+
},
|
|
37
|
+
8453: {
|
|
38
|
+
name: "base",
|
|
39
|
+
router: "0x3f170631ed9821Ca51A59D996aB095162438DC10",
|
|
40
|
+
weth: "0x4200000000000000000000000000000000000006",
|
|
41
|
+
usdc: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
42
|
+
},
|
|
43
|
+
42161: {
|
|
44
|
+
name: "arbitrum",
|
|
45
|
+
router: "0xEAedc32a51c510d35ebC11088fD5fF2b47aACF2E",
|
|
46
|
+
weth: "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
|
|
47
|
+
usdc: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
|
|
48
|
+
},
|
|
49
|
+
43114: {
|
|
50
|
+
name: "avalanche",
|
|
51
|
+
router: "0xF39CA6ede9BF7820a952b52f3c94af526bAB9015",
|
|
52
|
+
weth: "0xB31f66AA3C1e785363F0875A1B74E27b85FD66c7",
|
|
53
|
+
usdc: "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
const NATIVE = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
|
|
58
|
+
const ZERO = "0x0000000000000000000000000000000000000000";
|
|
59
|
+
const BALANCER_V3_IFACE = new Interface([
|
|
60
|
+
"function querySwapSingleTokenExactIn(address pool,address tokenIn,address tokenOut,uint256 exactAmountIn,address sender,bytes userData) returns (uint256 amountOut)",
|
|
61
|
+
"function swapSingleTokenExactIn(address pool,address tokenIn,address tokenOut,uint256 exactAmountIn,uint256 minAmountOut,uint256 deadline,bool wethIsEth,bytes userData) payable returns (uint256 amountOut)",
|
|
62
|
+
]);
|
|
63
|
+
|
|
64
|
+
function chainMeta(chainId) {
|
|
65
|
+
const id = Number(chainId ?? 8453);
|
|
66
|
+
const meta = BALANCER_V3_CHAINS[id];
|
|
67
|
+
if (!meta) {
|
|
68
|
+
throw new Error(`balancer-v3: unsupported chainId ${chainId} (supported: ${Object.keys(BALANCER_V3_CHAINS).join(", ")})`);
|
|
69
|
+
}
|
|
70
|
+
return { chainId: id, ...meta };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function isNativeToken(value) {
|
|
74
|
+
const v = String(value || "").toLowerCase();
|
|
75
|
+
return !v || v === "eth" || v === "native" || v === ZERO || v === NATIVE.toLowerCase();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function normalizeAddress(value, label) {
|
|
79
|
+
if (!isAddress(value)) throw new Error(`${label} must be a valid EVM address`);
|
|
80
|
+
return getAddress(value);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function normalizeToken(value, meta, label) {
|
|
84
|
+
const s = String(value || "");
|
|
85
|
+
if (isNativeToken(s) || /^weth$/i.test(s)) return getAddress(meta.weth);
|
|
86
|
+
if (/^usdc$/i.test(s)) return getAddress(meta.usdc);
|
|
87
|
+
return normalizeAddress(s, label);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function positiveAmount(value, label) {
|
|
91
|
+
let amount;
|
|
92
|
+
try {
|
|
93
|
+
amount = BigInt(String(value));
|
|
94
|
+
} catch {
|
|
95
|
+
throw new Error(`${label} must be an integer string`);
|
|
96
|
+
}
|
|
97
|
+
if (amount <= 0n) throw new Error(`${label} must be positive`);
|
|
98
|
+
return amount;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function userData(value) {
|
|
102
|
+
if (value == null || value === "") return "0x";
|
|
103
|
+
const data = String(value);
|
|
104
|
+
if (!/^0x[0-9a-fA-F]*$/.test(data)) throw new Error("balancer userData must be hex");
|
|
105
|
+
return data;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export async function balancerPools(args = {}, opts = {}) {
|
|
109
|
+
const first = Math.min(100, Math.max(1, Number(args.first || 20)));
|
|
110
|
+
const chains = (args.chains || [args.chain || "ETHEREUM"]).map((x) => String(x).toUpperCase());
|
|
111
|
+
return gql(POOLS_QUERY, { first, chains, where: { chainIn: chains } }, opts);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export async function balancerHealth(opts = {}) {
|
|
115
|
+
const data = await gql("query { __typename }", {}, opts);
|
|
116
|
+
return { ok: data?.data?.__typename === "Query" };
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export async function balancerQuote(q = {}, opts = {}) {
|
|
120
|
+
const meta = chainMeta(q.chainId);
|
|
121
|
+
const pool = normalizeAddress(q.pool, "balancer pool");
|
|
122
|
+
const tokenInRaw = q.tokenIn || "WETH";
|
|
123
|
+
const tokenIn = normalizeToken(tokenInRaw, meta, "balancer tokenIn");
|
|
124
|
+
const tokenOut = normalizeToken(q.tokenOut || "USDC", meta, "balancer tokenOut");
|
|
125
|
+
const amountIn = positiveAmount(q.amountIn, "balancer amountIn");
|
|
126
|
+
const sender = normalizeAddress(q.sender || q.from || q.fromAddress || q.recipient, "balancer sender");
|
|
127
|
+
const data = BALANCER_V3_IFACE.encodeFunctionData("querySwapSingleTokenExactIn", [
|
|
128
|
+
pool,
|
|
129
|
+
tokenIn,
|
|
130
|
+
tokenOut,
|
|
131
|
+
amountIn,
|
|
132
|
+
sender,
|
|
133
|
+
userData(q.userData),
|
|
134
|
+
]);
|
|
135
|
+
const call = opts.rpcCall || defaultRpcCall;
|
|
136
|
+
const raw = await call(meta.chainId, "eth_call", [{ to: meta.router, data }, q.blockTag || "latest"], opts);
|
|
137
|
+
const decoded = BALANCER_V3_IFACE.decodeFunctionResult("querySwapSingleTokenExactIn", raw);
|
|
138
|
+
const amountOut = BigInt(decoded[0]);
|
|
139
|
+
if (amountOut <= 0n) throw new Error("balancer quote returned zero output");
|
|
140
|
+
return attachAutoSlippage({
|
|
141
|
+
venue: "balancer",
|
|
142
|
+
protocolVersion: 3,
|
|
143
|
+
chainId: meta.chainId,
|
|
144
|
+
chain: meta.name,
|
|
145
|
+
router: meta.router,
|
|
146
|
+
pool,
|
|
147
|
+
tokenIn,
|
|
148
|
+
tokenOut,
|
|
149
|
+
amountIn: amountIn.toString(),
|
|
150
|
+
amountOut: amountOut.toString(),
|
|
151
|
+
}, {
|
|
152
|
+
chainId: meta.chainId,
|
|
153
|
+
venue: meta.router,
|
|
154
|
+
amountOut: amountOut.toString(),
|
|
155
|
+
liquidityUsd: q.liquidityUsd,
|
|
156
|
+
priceChange5m: q.priceChange5m,
|
|
157
|
+
requestedCapBps: q.maxSlippageBps ?? q.slippageBps,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export async function balancerPrepare(q = {}, opts = {}) {
|
|
162
|
+
const meta = chainMeta(q.chainId);
|
|
163
|
+
const sender = normalizeAddress(q.sender || q.from || q.fromAddress || q.recipient, "balancer sender");
|
|
164
|
+
const inputRaw = q.tokenIn || "WETH";
|
|
165
|
+
const nativeInput = isNativeToken(inputRaw);
|
|
166
|
+
const quote = await balancerQuote({ ...q, sender }, opts);
|
|
167
|
+
const deadlineWindow = Math.min(600, Math.max(30, Number(q.deadlineSeconds ?? 300)));
|
|
168
|
+
const nowSeconds = Number(opts.nowSeconds ?? Math.floor(Date.now() / 1000));
|
|
169
|
+
const deadline = BigInt(nowSeconds + deadlineWindow);
|
|
170
|
+
const wethIsEth = q.wethIsEth != null ? Boolean(q.wethIsEth) : nativeInput;
|
|
171
|
+
const data = BALANCER_V3_IFACE.encodeFunctionData("swapSingleTokenExactIn", [
|
|
172
|
+
quote.pool,
|
|
173
|
+
quote.tokenIn,
|
|
174
|
+
quote.tokenOut,
|
|
175
|
+
BigInt(quote.amountIn),
|
|
176
|
+
BigInt(quote.amountOutMinimum),
|
|
177
|
+
deadline,
|
|
178
|
+
wethIsEth,
|
|
179
|
+
userData(q.userData),
|
|
180
|
+
]);
|
|
181
|
+
return stampPrepared({
|
|
182
|
+
provider: "balancer",
|
|
183
|
+
calldataReady: true,
|
|
184
|
+
// NOT executable authority. The bytes are assembled but nothing is signed:
|
|
185
|
+
// the user's wallet is still the only thing that can authorize this. The
|
|
186
|
+
// previous `executionReady: true` read as "cleared to execute" and trained
|
|
187
|
+
// agents to treat a quote as permission.
|
|
188
|
+
requiresUserSignature: true,
|
|
189
|
+
signingReady: false,
|
|
190
|
+
broadcastReady: false,
|
|
191
|
+
chainId: meta.chainId,
|
|
192
|
+
deadline: deadline.toString(),
|
|
193
|
+
quote,
|
|
194
|
+
autoSlippage: quote.autoSlippage,
|
|
195
|
+
requiresApproval: nativeInput ? null : {
|
|
196
|
+
token: quote.tokenIn,
|
|
197
|
+
spender: meta.router,
|
|
198
|
+
amount: quote.amountIn,
|
|
199
|
+
},
|
|
200
|
+
transaction: {
|
|
201
|
+
chainId: meta.chainId,
|
|
202
|
+
from: sender,
|
|
203
|
+
to: meta.router,
|
|
204
|
+
data,
|
|
205
|
+
value: nativeInput ? quote.amountIn : "0",
|
|
206
|
+
slippageGuard: bindAutoSlippageGuardToCall(quote.autoSlippage, { chainId: meta.chainId, venue: meta.router, data }),
|
|
207
|
+
},
|
|
208
|
+
}, { provider: "balancer", kind: "balancer-tx" });
|
|
209
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Beefy Finance — cross-chain yield aggregator vaults (no API key).
|
|
2
|
+
|
|
3
|
+
import { httpJson } from "../http.mjs";
|
|
4
|
+
|
|
5
|
+
export const BEEFY_API = "https://api.beefy.finance";
|
|
6
|
+
|
|
7
|
+
function base(opts = {}) {
|
|
8
|
+
return (opts.baseUrl || process.env.BEEFY_API_URL || BEEFY_API).replace(/\/$/, "");
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function beefyHealth(opts = {}) {
|
|
12
|
+
try {
|
|
13
|
+
const data = await httpJson(`${base(opts)}/apy`, {
|
|
14
|
+
fetchImpl: opts.fetchImpl,
|
|
15
|
+
timeoutMs: opts.timeoutMs ?? 15_000,
|
|
16
|
+
});
|
|
17
|
+
const keys = Object.keys(data || {});
|
|
18
|
+
return { ok: keys.length > 0, provider: "beefy-yields", vaultCount: keys.length };
|
|
19
|
+
} catch (e) {
|
|
20
|
+
return { ok: false, provider: "beefy-yields", error: String(e.message || e).slice(0, 120) };
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function beefyApy(args = {}, opts = {}) {
|
|
25
|
+
const data = await httpJson(`${base(opts)}/apy`, {
|
|
26
|
+
fetchImpl: opts.fetchImpl,
|
|
27
|
+
timeoutMs: opts.timeoutMs ?? 20_000,
|
|
28
|
+
});
|
|
29
|
+
if (args.chain) {
|
|
30
|
+
const prefix = String(args.chain).toLowerCase();
|
|
31
|
+
const filtered = {};
|
|
32
|
+
for (const [k, v] of Object.entries(data)) {
|
|
33
|
+
if (String(k).toLowerCase().startsWith(prefix)) filtered[k] = v;
|
|
34
|
+
}
|
|
35
|
+
return filtered;
|
|
36
|
+
}
|
|
37
|
+
return data;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export async function beefyApyBreakdown(opts = {}) {
|
|
41
|
+
return httpJson(`${base(opts)}/apy/breakdown`, {
|
|
42
|
+
fetchImpl: opts.fetchImpl,
|
|
43
|
+
timeoutMs: opts.timeoutMs ?? 25_000,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Birdeye public token list — Solana token rankings (no API key).
|
|
2
|
+
// Rate-limited public endpoint, light touch expected.
|
|
3
|
+
|
|
4
|
+
import { httpJson } from "../http.mjs";
|
|
5
|
+
|
|
6
|
+
export const BIRDEYE_PUBLIC = "https://public-api.birdeye.so";
|
|
7
|
+
|
|
8
|
+
function base(opts = {}) {
|
|
9
|
+
return (opts.baseUrl || process.env.BIRDEYE_API_URL || BIRDEYE_PUBLIC).replace(/\/$/, "");
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export async function birdeyeHealth(opts = {}) {
|
|
13
|
+
try {
|
|
14
|
+
const data = await httpJson(`${base(opts)}/public/tokenlist?sort_by=v24hUSD&sort_type=desc&offset=0&limit=1`, {
|
|
15
|
+
fetchImpl: opts.fetchImpl,
|
|
16
|
+
timeoutMs: opts.timeoutMs ?? 10_000,
|
|
17
|
+
});
|
|
18
|
+
return { ok: Array.isArray(data?.data) && data.data.length > 0, provider: "birdeye-tokens" };
|
|
19
|
+
} catch (e) {
|
|
20
|
+
return { ok: false, provider: "birdeye-tokens", error: String(e.message || e).slice(0, 120) };
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function birdeyeTokenList(args = {}, opts = {}) {
|
|
25
|
+
const sortBy = String(args.sortBy || "v24hUSD");
|
|
26
|
+
const sortType = String(args.sortType || "desc");
|
|
27
|
+
const offset = Math.max(0, Number(args.offset || 0));
|
|
28
|
+
const limit = Math.min(50, Math.max(1, Number(args.limit || 20)));
|
|
29
|
+
return httpJson(`${base(opts)}/public/tokenlist?sort_by=${encodeURIComponent(sortBy)}&sort_type=${encodeURIComponent(sortType)}&offset=${offset}&limit=${limit}`, {
|
|
30
|
+
fetchImpl: opts.fetchImpl,
|
|
31
|
+
timeoutMs: opts.timeoutMs ?? 15_000,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
// Bisq — non-KYC peer-to-peer BTC market data (markets.bisq.network) — keyless.
|
|
2
|
+
//
|
|
3
|
+
// Why this matters as a distinct price source: every other venue Oracle reads
|
|
4
|
+
// is a KYC'd exchange or an on-chain DEX. Bisq is neither — it is decentralized
|
|
5
|
+
// P2P trading settled by bank transfer and similar rails, so its print carries
|
|
6
|
+
// a non-KYC premium/discount relative to centralized spot. That basis is the
|
|
7
|
+
// signal; the absolute price is not meant to be a reference rate.
|
|
8
|
+
//
|
|
9
|
+
// Verified live:
|
|
10
|
+
// GET /api/markets 200 map keyed by pair (bsq_btc, btc_usd…)
|
|
11
|
+
// GET /api/ticker?market=btc_usd 200 { last, high, low, volume_left, … }
|
|
12
|
+
// GET /api/trades?market=btc_usd 200 array, newest first
|
|
13
|
+
//
|
|
14
|
+
// LIQUIDITY CAVEAT: Bisq volume is thin and trades are sparse. A single print
|
|
15
|
+
// can move `last` by percent, and the most recent trade may be hours or days
|
|
16
|
+
// old, so every response carries the trade timestamp/age for judgement.
|
|
17
|
+
//
|
|
18
|
+
// Read-only. Bisq trades are executed in the Bisq desktop client, not here.
|
|
19
|
+
|
|
20
|
+
import { httpJson } from "../http.mjs";
|
|
21
|
+
|
|
22
|
+
export const BISQ_MARKETS_API = "https://markets.bisq.network";
|
|
23
|
+
|
|
24
|
+
function baseUrl(opts = {}) {
|
|
25
|
+
return String(opts.baseUrl || process.env.BISQ_MARKETS_URL || BISQ_MARKETS_API).replace(/\/$/, "");
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** Bisq pairs are lowercase `left_right`, e.g. btc_usd, bsq_btc, xmr_btc. */
|
|
29
|
+
export function bisqMarket(value, label = "market") {
|
|
30
|
+
const text = String(value || "")
|
|
31
|
+
.trim()
|
|
32
|
+
.toLowerCase()
|
|
33
|
+
.replace(/[/\-\s]/g, "_");
|
|
34
|
+
if (!/^[a-z0-9]{2,12}_[a-z0-9]{2,12}$/.test(text)) {
|
|
35
|
+
throw new Error(`bisq-markets: ${label} must look like btc_usd (got "${value}")`);
|
|
36
|
+
}
|
|
37
|
+
return text;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function get(path, opts = {}) {
|
|
41
|
+
return httpJson(`${baseUrl(opts)}${path.startsWith("/") ? path : `/${path}`}`, {
|
|
42
|
+
fetchImpl: opts.fetchImpl,
|
|
43
|
+
timeoutMs: opts.timeoutMs ?? 15_000,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export async function bisqHealth(opts = {}) {
|
|
48
|
+
try {
|
|
49
|
+
const markets = await get("/api/markets", opts);
|
|
50
|
+
const count = markets && typeof markets === "object" ? Object.keys(markets).length : 0;
|
|
51
|
+
return {
|
|
52
|
+
ok: count > 0,
|
|
53
|
+
provider: "bisq-markets",
|
|
54
|
+
baseUrl: baseUrl(opts),
|
|
55
|
+
marketCount: count,
|
|
56
|
+
exec: false,
|
|
57
|
+
};
|
|
58
|
+
} catch (error) {
|
|
59
|
+
return {
|
|
60
|
+
ok: false,
|
|
61
|
+
provider: "bisq-markets",
|
|
62
|
+
baseUrl: baseUrl(opts),
|
|
63
|
+
error: String(error?.message || error),
|
|
64
|
+
exec: false,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Tradable pairs. Optional `quote`/`base` filter, e.g. quote: "btc". */
|
|
70
|
+
export async function bisqMarkets(args = {}, opts = {}) {
|
|
71
|
+
const res = await get("/api/markets", opts);
|
|
72
|
+
let rows = Object.values(res && typeof res === "object" ? res : {});
|
|
73
|
+
if (args.base) {
|
|
74
|
+
const b = String(args.base).trim().toLowerCase();
|
|
75
|
+
rows = rows.filter((m) => String(m.lsymbol || "").toLowerCase() === b);
|
|
76
|
+
}
|
|
77
|
+
if (args.quote) {
|
|
78
|
+
const q = String(args.quote).trim().toLowerCase();
|
|
79
|
+
rows = rows.filter((m) => String(m.rsymbol || "").toLowerCase() === q);
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
provider: "bisq-markets",
|
|
83
|
+
count: rows.length,
|
|
84
|
+
markets: rows.map((m) => ({
|
|
85
|
+
pair: m.pair ?? null,
|
|
86
|
+
name: m.name ?? null,
|
|
87
|
+
base: m.lsymbol ?? null,
|
|
88
|
+
baseName: m.lname ?? null,
|
|
89
|
+
quote: m.rsymbol ?? null,
|
|
90
|
+
quoteName: m.rname ?? null,
|
|
91
|
+
baseType: m.ltype ?? null,
|
|
92
|
+
quoteType: m.rtype ?? null,
|
|
93
|
+
})),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Ticker for one pair. `buy`/`sell` are frequently null — Bisq offers are sparse. */
|
|
98
|
+
export async function bisqTicker(args = {}, opts = {}) {
|
|
99
|
+
const market = bisqMarket(args.market || args.pair || "btc_usd", "market");
|
|
100
|
+
const t = await get(`/api/ticker?market=${encodeURIComponent(market)}`, opts);
|
|
101
|
+
const row = Array.isArray(t) ? t[0] || {} : t || {};
|
|
102
|
+
return {
|
|
103
|
+
provider: "bisq-markets",
|
|
104
|
+
market,
|
|
105
|
+
last: row.last == null ? null : Number(row.last),
|
|
106
|
+
high: row.high == null ? null : Number(row.high),
|
|
107
|
+
low: row.low == null ? null : Number(row.low),
|
|
108
|
+
bid: row.buy == null ? null : Number(row.buy),
|
|
109
|
+
ask: row.sell == null ? null : Number(row.sell),
|
|
110
|
+
volumeBase: row.volume_left == null ? null : Number(row.volume_left),
|
|
111
|
+
volumeQuote: row.volume_right == null ? null : Number(row.volume_right),
|
|
112
|
+
note: "Bisq is thin, non-KYC P2P — treat as a basis signal against centralized spot, not a reference rate",
|
|
113
|
+
raw: row,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** Recent trades, newest first. Reports the age of the latest print. */
|
|
118
|
+
export async function bisqTrades(args = {}, opts = {}) {
|
|
119
|
+
const market = bisqMarket(args.market || args.pair || "btc_usd", "market");
|
|
120
|
+
const limit = Math.min(2000, Math.max(1, Number(args.limit || 50)));
|
|
121
|
+
const params = new URLSearchParams({ market, limit: String(limit) });
|
|
122
|
+
if (args.timestampFrom) params.set("timestamp_from", String(args.timestampFrom));
|
|
123
|
+
if (args.timestampTo) params.set("timestamp_to", String(args.timestampTo));
|
|
124
|
+
const res = await get(`/api/trades?${params}`, opts);
|
|
125
|
+
const rows = Array.isArray(res) ? res : [];
|
|
126
|
+
// trade_date is epoch MILLISECONDS on this API.
|
|
127
|
+
const latestMs = rows.length ? Number(rows[0].trade_date || 0) : null;
|
|
128
|
+
const volumeBase = rows.reduce((n, r) => n + Number(r.amount || 0), 0);
|
|
129
|
+
return {
|
|
130
|
+
provider: "bisq-markets",
|
|
131
|
+
market,
|
|
132
|
+
count: rows.length,
|
|
133
|
+
latestTradeAt: latestMs ? new Date(latestMs).toISOString() : null,
|
|
134
|
+
latestTradeAgeHours: latestMs ? Math.round(((Date.now() - latestMs) / 3_600_000) * 10) / 10 : null,
|
|
135
|
+
volumeBase,
|
|
136
|
+
trades: rows.slice(0, limit).map((r) => ({
|
|
137
|
+
price: r.price == null ? null : Number(r.price),
|
|
138
|
+
amount: r.amount == null ? null : Number(r.amount),
|
|
139
|
+
volume: r.volume == null ? null : Number(r.volume),
|
|
140
|
+
paymentMethod: r.payment_method ?? null,
|
|
141
|
+
tradeDate: r.trade_date ?? null,
|
|
142
|
+
tradeAt: r.trade_date ? new Date(Number(r.trade_date)).toISOString() : null,
|
|
143
|
+
})),
|
|
144
|
+
};
|
|
145
|
+
}
|