@oracle-agent/oracle 0.10.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.
- package/LICENSE +115 -201
- package/README.md +82 -91
- package/SECURITY.md +37 -12
- package/SETUP.md +207 -272
- package/dist/action-receipts.mjs +1 -0
- package/dist/action-semantics.mjs +1 -0
- package/dist/address-book.mjs +2 -0
- package/dist/bin/desk-server.mjs +14 -0
- package/dist/bin/oracle-data-mcp.mjs +8 -0
- package/dist/bin/oracle-init.mjs +24 -0
- package/dist/bin/oracle-public-server.mjs +5 -0
- package/dist/bin/oracle-route.mjs +22 -0
- package/dist/bin/oracle-scan.mjs +18 -0
- package/dist/bin/oracle-upgrade.mjs +21 -0
- package/dist/bin/oracle.mjs +68 -0
- package/dist/chains.mjs +1 -0
- package/dist/cli/commands/auth.mjs +16 -0
- package/dist/cli/commands/bootstrap.mjs +18 -0
- package/dist/cli/commands/chain.mjs +21 -0
- package/dist/cli/commands/chat.mjs +35 -0
- package/dist/cli/commands/credential.mjs +1 -0
- package/dist/cli/commands/data-mcp.mjs +2 -0
- package/dist/cli/commands/data.mjs +12 -0
- package/dist/cli/commands/doctor.mjs +5 -0
- package/dist/cli/commands/gate.mjs +13 -0
- package/dist/cli/commands/help.mjs +1 -0
- package/dist/cli/commands/init.mjs +3 -0
- package/dist/cli/commands/mcp.mjs +33 -0
- package/dist/cli/commands/model.mjs +44 -0
- package/dist/cli/commands/prepare.mjs +2 -0
- package/dist/cli/commands/public.mjs +3 -0
- package/dist/cli/commands/route.mjs +2 -0
- package/dist/cli/commands/runner.mjs +1 -0
- package/dist/cli/commands/scan.mjs +2 -0
- package/dist/cli/commands/setup.mjs +34 -0
- package/dist/cli/commands/sign.mjs +4 -0
- package/dist/cli/commands/signer.mjs +1 -0
- package/dist/cli/commands/upgrade.mjs +2 -0
- package/dist/cli/commands/vault.mjs +1 -0
- package/dist/cli/commands/version.mjs +2 -0
- package/dist/data/desk-data.mjs +12 -0
- package/dist/index.mjs +17 -0
- package/dist/nft-gas-war-guard.mjs +1 -0
- package/dist/onboarding/harness-configs.mjs +4 -0
- package/dist/portfolio-risk.mjs +1 -0
- package/dist/prepare-envelope.mjs +1 -0
- package/dist/public-control/policy-schema.mjs +1 -0
- package/dist/router/index.mjs +2 -0
- package/dist/scanner/index.mjs +4 -0
- package/dist/signals/index.mjs +1 -0
- package/dist/watch-preferences.mjs +1 -0
- package/package.json +27 -65
- package/public/oracle-splash/assets/cli-chain-hyperliquid.jpg +0 -0
- package/public/oracle-splash/brand/aave.webp +0 -0
- package/public/oracle-splash/brand/aavev2.webp +0 -0
- package/public/oracle-splash/brand/aborean.webp +0 -0
- package/public/oracle-splash/brand/across.webp +0 -0
- package/public/oracle-splash/brand/aerodrome.webp +0 -0
- package/public/oracle-splash/brand/afi.webp +0 -0
- package/public/oracle-splash/brand/arcus.webp +0 -0
- package/public/oracle-splash/brand/aster.webp +0 -0
- package/public/oracle-splash/brand/avant.webp +0 -0
- package/public/oracle-splash/brand/balancer.webp +0 -0
- package/public/oracle-splash/brand/beefy.webp +0 -0
- package/public/oracle-splash/brand/benqi.webp +0 -0
- package/public/oracle-splash/brand/bestinslot.ico +0 -0
- package/public/oracle-splash/brand/bitfi.webp +0 -0
- package/public/oracle-splash/brand/bonkswap.webp +0 -0
- package/public/oracle-splash/brand/bouncebit.webp +0 -0
- package/public/oracle-splash/brand/camelot.webp +0 -0
- package/public/oracle-splash/brand/compound.webp +0 -0
- package/public/oracle-splash/brand/concrete.webp +0 -0
- package/public/oracle-splash/brand/cow.webp +0 -0
- package/public/oracle-splash/brand/curve.webp +0 -0
- package/public/oracle-splash/brand/derive.webp +0 -0
- package/public/oracle-splash/brand/dolomite.webp +0 -0
- package/public/oracle-splash/brand/eigenlayer.webp +0 -0
- package/public/oracle-splash/brand/ekubo.webp +0 -0
- package/public/oracle-splash/brand/ethena.webp +0 -0
- package/public/oracle-splash/brand/etherfi.webp +0 -0
- package/public/oracle-splash/brand/etherfiborrow.webp +0 -0
- package/public/oracle-splash/brand/felix.webp +0 -0
- package/public/oracle-splash/brand/fluid.webp +0 -0
- package/public/oracle-splash/brand/fluxbeam.webp +0 -0
- package/public/oracle-splash/brand/folks.webp +0 -0
- package/public/oracle-splash/brand/fortyacres.webp +0 -0
- package/public/oracle-splash/brand/gainsnetwork.webp +0 -0
- package/public/oracle-splash/brand/gassss.webp +0 -0
- package/public/oracle-splash/brand/gmx.webp +0 -0
- package/public/oracle-splash/brand/harmonix.webp +0 -0
- package/public/oracle-splash/brand/hlorderbook.webp +0 -0
- package/public/oracle-splash/brand/hlp.webp +0 -0
- package/public/oracle-splash/brand/hop.webp +0 -0
- package/public/oracle-splash/brand/hyperbeat.webp +0 -0
- package/public/oracle-splash/brand/hyperlend.webp +0 -0
- package/public/oracle-splash/brand/hyperliquid.webp +0 -0
- package/public/oracle-splash/brand/hyperliquidhpl.webp +0 -0
- package/public/oracle-splash/brand/hyperliquidspot.webp +0 -0
- package/public/oracle-splash/brand/hyperswap.webp +0 -0
- package/public/oracle-splash/brand/hypha.webp +0 -0
- package/public/oracle-splash/brand/joedex.webp +0 -0
- package/public/oracle-splash/brand/jupiter.webp +0 -0
- package/public/oracle-splash/brand/kelp.webp +0 -0
- package/public/oracle-splash/brand/kinetiq.webp +0 -0
- package/public/oracle-splash/brand/kmhype.webp +0 -0
- package/public/oracle-splash/brand/kona.webp +0 -0
- package/public/oracle-splash/brand/konalend.webp +0 -0
- package/public/oracle-splash/brand/lfj.webp +0 -0
- package/public/oracle-splash/brand/lido.webp +0 -0
- package/public/oracle-splash/brand/lifi.webp +0 -0
- package/public/oracle-splash/brand/lighter.webp +0 -0
- package/public/oracle-splash/brand/lista.webp +0 -0
- package/public/oracle-splash/brand/loopedhype.webp +0 -0
- package/public/oracle-splash/brand/lorenzo.webp +0 -0
- package/public/oracle-splash/brand/magic-eden.webp +0 -0
- package/public/oracle-splash/brand/magiceden.webp +0 -0
- package/public/oracle-splash/brand/mempool.png +0 -0
- package/public/oracle-splash/brand/meteora.webp +0 -0
- package/public/oracle-splash/brand/morpho.webp +0 -0
- package/public/oracle-splash/brand/myriad.webp +0 -0
- package/public/oracle-splash/brand/noxa.webp +0 -0
- package/public/oracle-splash/brand/odos.webp +0 -0
- package/public/oracle-splash/brand/oneinch.webp +0 -0
- package/public/oracle-splash/brand/openbook.webp +0 -0
- package/public/oracle-splash/brand/opensea.webp +0 -0
- package/public/oracle-splash/brand/orca.webp +0 -0
- package/public/oracle-splash/brand/ordinals.png +0 -0
- package/public/oracle-splash/brand/ostium.webp +0 -0
- package/public/oracle-splash/brand/pancakeswap.webp +0 -0
- package/public/oracle-splash/brand/pendle.webp +0 -0
- package/public/oracle-splash/brand/perena.webp +0 -0
- package/public/oracle-splash/brand/pharaoh.webp +0 -0
- package/public/oracle-splash/brand/phoenix.webp +0 -0
- package/public/oracle-splash/brand/polymarket.webp +0 -0
- package/public/oracle-splash/brand/polynomial.webp +0 -0
- package/public/oracle-splash/brand/projectx.webp +0 -0
- package/public/oracle-splash/brand/pumpfun.webp +0 -0
- package/public/oracle-splash/brand/quickswap.webp +0 -0
- package/public/oracle-splash/brand/rain.webp +0 -0
- package/public/oracle-splash/brand/raydium.webp +0 -0
- package/public/oracle-splash/brand/relay.webp +0 -0
- package/public/oracle-splash/brand/rocketpool.webp +0 -0
- package/public/oracle-splash/brand/saber.webp +0 -0
- package/public/oracle-splash/brand/sakuraswap.webp +0 -0
- package/public/oracle-splash/brand/sanctum.webp +0 -0
- package/public/oracle-splash/brand/satflow.png +0 -0
- package/public/oracle-splash/brand/sierra.webp +0 -0
- package/public/oracle-splash/brand/sky.webp +0 -0
- package/public/oracle-splash/brand/solv.webp +0 -0
- package/public/oracle-splash/brand/spark.webp +0 -0
- package/public/oracle-splash/brand/sparksavings.webp +0 -0
- package/public/oracle-splash/brand/sphere.webp +0 -0
- package/public/oracle-splash/brand/ssv.webp +0 -0
- package/public/oracle-splash/brand/stabble.webp +0 -0
- package/public/oracle-splash/brand/stableswap.webp +0 -0
- package/public/oracle-splash/brand/stakewise.webp +0 -0
- package/public/oracle-splash/brand/stargate.webp +0 -0
- package/public/oracle-splash/brand/sthype.webp +0 -0
- package/public/oracle-splash/brand/sushiswap.webp +0 -0
- package/public/oracle-splash/brand/unisat.png +0 -0
- package/public/oracle-splash/brand/uniswap.webp +0 -0
- package/public/oracle-splash/brand/uniswapv2.webp +0 -0
- package/public/oracle-splash/brand/uniswapv4.webp +0 -0
- package/public/oracle-splash/brand/unit.webp +0 -0
- package/public/oracle-splash/brand/velodrome.webp +0 -0
- package/public/oracle-splash/brand/velora.webp +0 -0
- package/public/oracle-splash/brand/venus.webp +0 -0
- package/public/oracle-splash/brand/wbeth.webp +0 -0
- package/public/oracle-splash/brand/xsy.webp +0 -0
- package/public/oracle-splash/brand/yieldyak.webp +0 -0
- package/public/oracle-splash/brand/zerobase.webp +0 -0
- package/public/oracle-splash/brand/zerox.webp +0 -0
- package/public/oracle-splash/index.html +246 -169
- package/CONTRIBUTING.md +0 -98
- package/bin/desk-server.mjs +0 -440
- package/bin/oracle-data-mcp.mjs +0 -1010
- package/bin/oracle-init.mjs +0 -496
- package/bin/oracle-public-server.mjs +0 -36
- package/bin/oracle-route.mjs +0 -254
- package/bin/oracle-scan.mjs +0 -192
- package/bin/oracle-upgrade.mjs +0 -42
- package/bin/oracle.mjs +0 -33
- package/docs/adding-a-chain.md +0 -229
- package/docs/architecture.md +0 -136
- package/docs/cli.md +0 -47
- package/docs/connectors.md +0 -13
- package/docs/oracle-pack-standard.md +0 -29
- package/docs/profiles.md +0 -154
- package/examples/add-a-chain.mjs +0 -65
- package/examples/oracle-pack-template.mjs +0 -38
- package/examples/research-a-token.mjs +0 -70
- package/plugins/oracle-owner-gate/__init__.py +0 -227
- package/plugins/oracle-owner-gate/plugin.yaml +0 -9
- package/profiles/_template/SOUL.md +0 -54
- package/profiles/_template/profile.json +0 -22
- package/profiles/bitcoin-agent/SOUL.md +0 -31
- package/profiles/bitcoin-agent/profile.json +0 -32
- package/profiles/hyperliquid-agent/SOUL.md +0 -34
- package/profiles/hyperliquid-agent/profile.json +0 -37
- package/profiles/oracle/SOUL.md +0 -107
- package/profiles/oracle/profile.json +0 -39
- package/profiles/polymarket-agent/SOUL.md +0 -35
- package/profiles/polymarket-agent/profile.json +0 -34
- package/profiles/profile.schema.json +0 -90
- package/profiles/protocol-builder/SOUL.md +0 -57
- package/profiles/protocol-builder/profile.json +0 -39
- package/profiles/robinhood-agent/SOUL.md +0 -53
- package/profiles/robinhood-agent/profile.json +0 -40
- package/profiles/solana-agent/SOUL.md +0 -37
- package/profiles/solana-agent/profile.json +0 -37
- package/profiles/stable-agent/SOUL.md +0 -43
- package/profiles/stable-agent/profile.json +0 -37
- package/protocols/templates/safe-erc20/SECURITY.md +0 -16
- package/protocols/templates/safe-erc20/foundry.toml +0 -12
- package/protocols/templates/safe-erc20/remappings.txt +0 -2
- package/protocols/templates/safe-erc20/src/SafeERC20.sol +0 -53
- package/protocols/templates/safe-erc20/test/SafeERC20.t.sol +0 -72
- package/scripts/adversarial-bench.mjs +0 -114
- package/scripts/build-inscription.py +0 -230
- package/scripts/check-doc-drift.mjs +0 -112
- package/scripts/check-test-count.mjs +0 -105
- package/scripts/e2e-hl-markets.mjs +0 -21
- package/scripts/e2e-hl-perps.mjs +0 -48
- package/scripts/e2e-hypercore-staking.mjs +0 -128
- package/scripts/e2e-solana-bitcoin.mjs +0 -183
- package/scripts/protocol-template-gate.mjs +0 -15
- package/scripts/public-api-scan.mjs +0 -23
- package/scripts/secret-scan.mjs +0 -181
- package/scripts/verify-v3-venues.mjs +0 -192
- package/skills/balance/SKILL.md +0 -176
- package/skills/oracle-action-semantics/SKILL.md +0 -40
- package/skills/oracle-best-execution/SKILL.md +0 -127
- package/skills/oracle-bitcoin/SKILL.md +0 -53
- package/skills/oracle-chain-graphs-telegram-cards/SKILL.md +0 -59
- package/skills/oracle-chat/SKILL.md +0 -61
- package/skills/oracle-chat/chain.SKILL.md +0 -31
- package/skills/oracle-chat/setup.SKILL.md +0 -37
- package/skills/oracle-circuit-breaker/SKILL.md +0 -51
- package/skills/oracle-contract-research/SKILL.md +0 -55
- package/skills/oracle-desk/SKILL.md +0 -58
- package/skills/oracle-dex-launch/SKILL.md +0 -38
- package/skills/oracle-grants/SKILL.md +0 -69
- package/skills/oracle-hypercore-staking/SKILL.md +0 -57
- package/skills/oracle-hyperliquid/SKILL.md +0 -56
- package/skills/oracle-meme-token-sniper/SKILL.md +0 -73
- package/skills/oracle-multichain-nft-launch/SKILL.md +0 -338
- package/skills/oracle-multichain-token-launch/SKILL.md +0 -300
- package/skills/oracle-nft-gacha-launch/SKILL.md +0 -48
- package/skills/oracle-nft-mint-gas-war/SKILL.md +0 -63
- package/skills/oracle-polymarket/SKILL.md +0 -60
- package/skills/oracle-protocol-builder/SKILL.md +0 -59
- package/skills/oracle-protocol-security/SKILL.md +0 -60
- package/skills/oracle-public-product/SKILL.md +0 -44
- package/skills/oracle-receipts/SKILL.md +0 -52
- package/skills/oracle-rfq-tokenized-assets/SKILL.md +0 -69
- package/skills/oracle-smart-wallet-scanner/SKILL.md +0 -49
- package/skills/oracle-solana/SKILL.md +0 -65
- package/skills/oracle-solana-nft/SKILL.md +0 -54
- package/skills/oracle-token-research/SKILL.md +0 -67
- package/skins/oracle.yaml +0 -56
- package/src/action-receipts.mjs +0 -168
- package/src/action-semantics.mjs +0 -62
- package/src/address-book.mjs +0 -208
- package/src/agent-auth.mjs +0 -206
- package/src/approval-guard.mjs +0 -282
- package/src/attestation-secret.mjs +0 -88
- package/src/audit-log.mjs +0 -196
- package/src/auth/oauth.mjs +0 -672
- package/src/auto-slippage.mjs +0 -378
- package/src/capability-posture.mjs +0 -125
- package/src/chains.mjs +0 -62
- package/src/cli/chain-catalog.mjs +0 -215
- package/src/cli/chain-state.mjs +0 -74
- package/src/cli/commands/auth.mjs +0 -193
- package/src/cli/commands/bootstrap.mjs +0 -87
- package/src/cli/commands/chain.mjs +0 -143
- package/src/cli/commands/chat.mjs +0 -434
- package/src/cli/commands/credential.mjs +0 -9
- package/src/cli/commands/data-mcp.mjs +0 -18
- package/src/cli/commands/data.mjs +0 -73
- package/src/cli/commands/doctor.mjs +0 -126
- package/src/cli/commands/help.mjs +0 -7
- package/src/cli/commands/init.mjs +0 -27
- package/src/cli/commands/mcp.mjs +0 -142
- package/src/cli/commands/model.mjs +0 -99
- package/src/cli/commands/prepare.mjs +0 -12
- package/src/cli/commands/public.mjs +0 -20
- package/src/cli/commands/route.mjs +0 -12
- package/src/cli/commands/runner.mjs +0 -9
- package/src/cli/commands/scan.mjs +0 -12
- package/src/cli/commands/setup.mjs +0 -275
- package/src/cli/commands/sign.mjs +0 -21
- package/src/cli/commands/signer.mjs +0 -9
- package/src/cli/commands/upgrade.mjs +0 -12
- package/src/cli/commands/vault.mjs +0 -9
- package/src/cli/commands/version.mjs +0 -22
- package/src/cli/first-run.mjs +0 -23
- package/src/cli/kernel.mjs +0 -239
- package/src/cli/mcp-targets/chatgpt.mjs +0 -51
- package/src/cli/mcp-targets/claude-code.mjs +0 -39
- package/src/cli/mcp-targets/claude-desktop.mjs +0 -24
- package/src/cli/mcp-targets/codex.mjs +0 -41
- package/src/cli/mcp-targets/shared.mjs +0 -61
- package/src/cli/messaging-platforms.mjs +0 -209
- package/src/cli/model-config.mjs +0 -70
- package/src/cli/operator-dispatch.mjs +0 -258
- package/src/cli/oracle-harness.py +0 -415
- package/src/cli/paths.mjs +0 -83
- package/src/cli/runtime.mjs +0 -351
- package/src/cli/setup-state.mjs +0 -168
- package/src/cli/spawn-child.mjs +0 -43
- package/src/data/catalog.mjs +0 -554
- package/src/data/desk-data.mjs +0 -683
- package/src/data/http.mjs +0 -253
- package/src/data/provider-endpoint.mjs +0 -94
- package/src/data/providers/aerodrome.mjs +0 -245
- package/src/data/providers/balancer.mjs +0 -209
- package/src/data/providers/bitcoin-esplora.mjs +0 -216
- package/src/data/providers/bitcoin-meta.mjs +0 -378
- package/src/data/providers/blockscout.mjs +0 -14
- package/src/data/providers/bridges.mjs +0 -242
- package/src/data/providers/cowswap.mjs +0 -415
- package/src/data/providers/curve.mjs +0 -201
- package/src/data/providers/defillama.mjs +0 -88
- package/src/data/providers/dexscreener.mjs +0 -43
- package/src/data/providers/evm-rpc.mjs +0 -222
- package/src/data/providers/geckoterminal.mjs +0 -34
- package/src/data/providers/gmx.mjs +0 -496
- package/src/data/providers/hl-assets.mjs +0 -165
- package/src/data/providers/hl-info.mjs +0 -108
- package/src/data/providers/hl-markets.mjs +0 -210
- package/src/data/providers/hl-outcome.mjs +0 -61
- package/src/data/providers/hl-perps.mjs +0 -387
- package/src/data/providers/hl-staking.mjs +0 -353
- package/src/data/providers/hl-ws.mjs +0 -119
- package/src/data/providers/hyperevm-dex.mjs +0 -49
- package/src/data/providers/jupiter.mjs +0 -183
- package/src/data/providers/lifi.mjs +0 -151
- package/src/data/providers/magiceden-sol.mjs +0 -393
- package/src/data/providers/morpho.mjs +0 -173
- package/src/data/providers/nft-gallery.mjs +0 -163
- package/src/data/providers/nft-portfolio.mjs +0 -494
- package/src/data/providers/odos.mjs +0 -156
- package/src/data/providers/oneinch.mjs +0 -174
- package/src/data/providers/opensea-multichain.mjs +0 -136
- package/src/data/providers/opensea-nft.mjs +0 -371
- package/src/data/providers/paraswap.mjs +0 -118
- package/src/data/providers/pendle.mjs +0 -187
- package/src/data/providers/poly-clob.mjs +0 -283
- package/src/data/providers/poly-public.mjs +0 -96
- package/src/data/providers/poly-ws.mjs +0 -103
- package/src/data/providers/portfolio-history.mjs +0 -394
- package/src/data/providers/portfolio.mjs +0 -594
- package/src/data/providers/rfq.mjs +0 -15
- package/src/data/providers/rh-agent.mjs +0 -59
- package/src/data/providers/satflow.mjs +0 -338
- package/src/data/providers/solana-rpc.mjs +0 -197
- package/src/data/providers/uniswap-v3.mjs +0 -320
- package/src/data/providers/zerox.mjs +0 -167
- package/src/data/public-api-scan.mjs +0 -61
- package/src/data/quote-placeholder.mjs +0 -31
- package/src/exact-integer.mjs +0 -72
- package/src/exec-policy.mjs +0 -455
- package/src/flags.mjs +0 -15
- package/src/fresh-window.mjs +0 -76
- package/src/gmx-attestation.mjs +0 -176
- package/src/index.mjs +0 -100
- package/src/nft-gas-war-guard.mjs +0 -139
- package/src/onboarding/agent-keys.mjs +0 -161
- package/src/onboarding/harness-configs.mjs +0 -102
- package/src/onboarding/index.mjs +0 -18
- package/src/onboarding/tiers.mjs +0 -139
- package/src/oracle-env.mjs +0 -47
- package/src/portfolio-risk.mjs +0 -170
- package/src/prepare-envelope.mjs +0 -186
- package/src/profile-upgrade.mjs +0 -277
- package/src/protocol-execution.mjs +0 -84
- package/src/protocol-templates/gate.mjs +0 -179
- package/src/protocol-templates/prepare-deploy.mjs +0 -81
- package/src/public-api/buzz-integration.mjs +0 -256
- package/src/public-api/connect-agent.mjs +0 -416
- package/src/public-api/grants.mjs +0 -142
- package/src/public-api/http.mjs +0 -389
- package/src/public-control/aa-adapter.mjs +0 -402
- package/src/public-control/build-registry.mjs +0 -227
- package/src/public-control/bundler-client.mjs +0 -357
- package/src/public-control/grant-indexer.mjs +0 -296
- package/src/public-control/policy-render.mjs +0 -69
- package/src/public-control/policy-schema.mjs +0 -318
- package/src/public-control/runtime-config.mjs +0 -275
- package/src/public-control/session-key-model.mjs +0 -374
- package/src/public-control/session-orchestrator.mjs +0 -412
- package/src/rfq/intent.mjs +0 -180
- package/src/rfq/sources.mjs +0 -181
- package/src/route-attestation.mjs +0 -132
- package/src/router/best-execution.mjs +0 -326
- package/src/router/index.mjs +0 -226
- package/src/router/prepare-bridge.mjs +0 -289
- package/src/router/prepare-route.mjs +0 -381
- package/src/router/proposal.mjs +0 -311
- package/src/router/risk-classifier.mjs +0 -119
- package/src/router/route-sources.mjs +0 -329
- package/src/scanner/chains.config.mjs +0 -430
- package/src/scanner/contract.mjs +0 -270
- package/src/scanner/evm-scanner.mjs +0 -394
- package/src/scanner/index.mjs +0 -9
- package/src/scanner/v2-venue.mjs +0 -335
- package/src/scanner/v3-venue.mjs +0 -290
- package/src/scopes.mjs +0 -44
- package/src/sell-simulation.mjs +0 -167
- package/src/signals/engine.mjs +0 -146
- package/src/signals/index.mjs +0 -1
- package/src/token-transfer-guard.mjs +0 -188
- package/src/tui/app.mjs +0 -438
- package/src/tui/backend.mjs +0 -145
- package/src/tui/format.mjs +0 -272
- package/src/tui/gateway-client.mjs +0 -177
- package/src/tui/input.mjs +0 -501
- package/src/tui/renderer.mjs +0 -443
- package/src/tui/standalone-client.mjs +0 -666
- package/src/tui/theme.mjs +0 -81
- package/src/vault-attestation.mjs +0 -146
- package/src/venues.mjs +0 -206
- package/src/watch-preferences.mjs +0 -85
package/scripts/e2e-hl-perps.mjs
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { data as desk } from "../src/data/desk-data.mjs";
|
|
2
|
-
|
|
3
|
-
const info = await desk.call("hl-perps", "assetInfo", { coin: "BTC" });
|
|
4
|
-
console.log(`BTC assetId=${info.assetId} szDecimals=${info.szDecimals} maxLev=${info.maxLeverage}x mark=$${info.markPx}`);
|
|
5
|
-
|
|
6
|
-
// 1. LIMIT BUY
|
|
7
|
-
const lim = await desk.call("hl-perps", "prepareOrder", {
|
|
8
|
-
coin: "BTC", side: "buy", type: "limit", price: "60000.123456789", size: "0.0123456", tif: "Gtc",
|
|
9
|
-
});
|
|
10
|
-
console.log(`\nLIMIT BUY px=${lim.price} sz=${lim.size} notional=$${lim.notionalUsd?.toFixed(2)} tif=${JSON.stringify(lim.action.orders[0].t)}`);
|
|
11
|
-
console.log(` signingReady=${lim.signingReady} broadcastReady=${lim.broadcastReady} requiresUserSig=${lim.requiresUserSignature}`);
|
|
12
|
-
|
|
13
|
-
// 2. MARKET BUY with slippage cap
|
|
14
|
-
const mkt = await desk.call("hl-perps", "prepareOrder", {
|
|
15
|
-
coin: "ETH", side: "buy", type: "market", size: "0.5", maxSlippageBps: 50,
|
|
16
|
-
});
|
|
17
|
-
console.log(`\nMARKET BUY ETH aggressive px=${mkt.price} sz=${mkt.size} tif=${mkt.action.orders[0].t.limit.tif}`);
|
|
18
|
-
|
|
19
|
-
// 3. slippage cap enforced
|
|
20
|
-
try {
|
|
21
|
-
await desk.call("hl-perps", "prepareOrder", { coin: "ETH", side: "buy", type: "market", size: "1", maxSlippageBps: 500 });
|
|
22
|
-
console.log(" !! 500bps ACCEPTED — cap broken");
|
|
23
|
-
} catch (e) { console.log(` 500bps rejected: ${e.message.slice(0, 60)}`); }
|
|
24
|
-
|
|
25
|
-
// 4. LEVERAGE
|
|
26
|
-
const lev = await desk.call("hl-perps", "prepareLeverage", { coin: "BTC", leverage: 25, marginMode: "isolated" });
|
|
27
|
-
console.log(`\nLEVERAGE ${lev.leverage}x ${lev.marginMode} isCross=${lev.action.isCross}`);
|
|
28
|
-
console.log(` warning: ${lev.liquidationWarning}`);
|
|
29
|
-
|
|
30
|
-
try {
|
|
31
|
-
await desk.call("hl-perps", "prepareLeverage", { coin: "BTC", leverage: 999 });
|
|
32
|
-
console.log(" !! 999x ACCEPTED — cap broken");
|
|
33
|
-
} catch (e) { console.log(` 999x rejected: ${e.message.slice(0, 70)}`); }
|
|
34
|
-
|
|
35
|
-
// 5. BRACKET: entry + TP + SL
|
|
36
|
-
const br = await desk.call("hl-perps", "prepareBracket", {
|
|
37
|
-
coin: "BTC", side: "buy", type: "limit", price: "60000", size: "0.01",
|
|
38
|
-
takeProfitPx: "72000", stopLossPx: "57000",
|
|
39
|
-
});
|
|
40
|
-
console.log(`\nBRACKET legs=${br.legs} entry=${br.entry.price} tp=${br.takeProfitPx} sl=${br.stopLossPx} grouping=${br.action.grouping}`);
|
|
41
|
-
console.log(` tp reduceOnly=${br.action.orders[1].r} trigger=${JSON.stringify(br.action.orders[1].t.trigger)}`);
|
|
42
|
-
console.log(` sl reduceOnly=${br.action.orders[2].r} trigger=${JSON.stringify(br.action.orders[2].t.trigger)}`);
|
|
43
|
-
|
|
44
|
-
// 6. CANCEL
|
|
45
|
-
const c = await desk.call("hl-perps", "prepareCancel", { coin: "BTC", orderId: 12345 });
|
|
46
|
-
console.log(`\nCANCEL oid=${c.orderId} action=${JSON.stringify(c.action)}`);
|
|
47
|
-
|
|
48
|
-
console.log("\nNo submit function exists in hl-perps — every result is user-signed.");
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import { data as desk } from "../src/data/desk-data.mjs";
|
|
2
|
-
import {
|
|
3
|
-
hlPrepareStakeDeposit,
|
|
4
|
-
hlPrepareStakeWithdraw,
|
|
5
|
-
hlPrepareDelegate,
|
|
6
|
-
hypeToWei,
|
|
7
|
-
weiToHype,
|
|
8
|
-
} from "../src/data/providers/hl-staking.mjs";
|
|
9
|
-
|
|
10
|
-
const USER = process.env.ORACLE_E2E_EVM_ADDRESS || "0x0000000000000000000000000000000000000001";
|
|
11
|
-
const results = [];
|
|
12
|
-
function log(lane, status, detail) {
|
|
13
|
-
results.push({ lane, status });
|
|
14
|
-
console.log(`${status === "ok" ? "OK " : "FAIL"} ${lane} :: ${detail}`);
|
|
15
|
-
}
|
|
16
|
-
async function run(lane, fn) {
|
|
17
|
-
try {
|
|
18
|
-
log(lane, "ok", await fn());
|
|
19
|
-
} catch (e) {
|
|
20
|
-
log(lane, "fail", String(e?.message || e).slice(0, 150));
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
console.log("== HYPERCORE STAKING ==");
|
|
25
|
-
|
|
26
|
-
let validator = null;
|
|
27
|
-
await run("hl.staking.validators", async () => {
|
|
28
|
-
const v = await desk.hl.staking.validators();
|
|
29
|
-
const active = v.validators.filter((x) => x.isActive && !x.isJailed);
|
|
30
|
-
validator = active[0]?.validator || v.validators[0]?.validator;
|
|
31
|
-
return `validators=${v.count} activeUnjailed=${active.length} first=${(validator || "").slice(0, 10)}..`;
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
await run("hl.staking.health", async () => {
|
|
35
|
-
const h = await desk.hl.staking.health();
|
|
36
|
-
if (!h.ok) throw new Error("staking lane unhealthy");
|
|
37
|
-
return `ok validators=${h.validators} chain=${h.chain}`;
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
await run("hl.staking.delegatorSummary", async () => {
|
|
41
|
-
const s = await desk.hl.staking.summary(USER);
|
|
42
|
-
return `delegated=${s.delegatedWei} undelegated=${s.undelegatedWei} pendingWithdrawals=${s.nPendingWithdrawals}`;
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
await run("hl.staking.delegations", async () => {
|
|
46
|
-
const d = await desk.hl.staking.delegations(USER);
|
|
47
|
-
return `count=${d.count}`;
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
await run("hl.staking.rewards", async () => {
|
|
51
|
-
const r = await desk.hl.staking.rewards(USER);
|
|
52
|
-
return `rewards=${r.rewards.length}`;
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
await run("hl.staking.preflight", async () => {
|
|
56
|
-
const p = await desk.hl.staking.preflight(USER);
|
|
57
|
-
return `undelegated=${p.stakingBalanceUndelegated} queueDays=${p.unstakingQueueDays} lockupDays=${p.validatorLockupDays}`;
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
await run("hl.staking.units", async () => {
|
|
61
|
-
const w = hypeToWei("1.5");
|
|
62
|
-
if (w !== "150000000") throw new Error(`1.5 HYPE -> ${w}, expected 150000000`);
|
|
63
|
-
if (weiToHype("150000000") !== "1.5") throw new Error("roundtrip failed");
|
|
64
|
-
return `1.5 HYPE = ${w} wei roundtrip ok`;
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
await run("hl.staking.prepareStake", async () => {
|
|
68
|
-
const p = hlPrepareStakeDeposit({ amountHype: "2.5", maxHype: "10" });
|
|
69
|
-
if (p.action.type !== "cDeposit") throw new Error("wrong action type");
|
|
70
|
-
if (p.broadcastReady !== false || p.signingReady !== false) throw new Error("leaked readiness");
|
|
71
|
-
if (!p.requiresUserSignature) throw new Error("must require user signature");
|
|
72
|
-
return `cDeposit wei=${p.action.wei} primaryType=${p.typedData.primaryType} broadcastReady=false`;
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
await run("hl.staking.prepareStake.capBreach", async () => {
|
|
76
|
-
try {
|
|
77
|
-
hlPrepareStakeDeposit({ amountHype: "50", maxHype: "10" });
|
|
78
|
-
} catch (e) {
|
|
79
|
-
return `rejected over-cap: ${String(e.message).slice(0, 70)}`;
|
|
80
|
-
}
|
|
81
|
-
throw new Error("cap was NOT enforced");
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
await run("hl.staking.prepareDelegate", async () => {
|
|
85
|
-
if (!validator) throw new Error("no validator resolved");
|
|
86
|
-
const p = hlPrepareDelegate({ validator, amountHype: "2.5", isUndelegate: false, maxHype: "10" });
|
|
87
|
-
if (p.action.type !== "tokenDelegate" || p.action.isUndelegate !== false) throw new Error("wrong action");
|
|
88
|
-
return `tokenDelegate validator=${p.action.validator.slice(0, 10)}.. wei=${p.action.wei} isUndelegate=false`;
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
await run("hl.staking.prepareUndelegate", async () => {
|
|
92
|
-
const p = hlPrepareDelegate({ validator, amountHype: "2.5", isUndelegate: true });
|
|
93
|
-
if (p.action.isUndelegate !== true) throw new Error("undelegate flag lost");
|
|
94
|
-
return `tokenDelegate isUndelegate=true kind=${p.kind}`;
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
await run("hl.staking.prepareUnstake", async () => {
|
|
98
|
-
const p = hlPrepareStakeWithdraw({ amountHype: "2.5" });
|
|
99
|
-
if (p.action.type !== "cWithdraw") throw new Error("wrong action type");
|
|
100
|
-
if (!p.notes.join(" ").includes("7 day")) throw new Error("missing unstaking queue warning");
|
|
101
|
-
return `cWithdraw wei=${p.action.wei} queue warning present`;
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
await run("hl.staking.badAmount", async () => {
|
|
105
|
-
try {
|
|
106
|
-
hlPrepareStakeDeposit({ amountHype: "0" });
|
|
107
|
-
} catch (e) {
|
|
108
|
-
return `rejected zero amount`;
|
|
109
|
-
}
|
|
110
|
-
throw new Error("zero amount accepted");
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
await run("hl.staking.badValidator", async () => {
|
|
114
|
-
try {
|
|
115
|
-
hlPrepareDelegate({ validator: "not-an-address", amountHype: "1" });
|
|
116
|
-
} catch (e) {
|
|
117
|
-
return `rejected bad validator`;
|
|
118
|
-
}
|
|
119
|
-
throw new Error("bad validator accepted");
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
const failed = results.filter((r) => r.status === "fail");
|
|
123
|
-
console.log(`\nlanes=${results.length} ok=${results.length - failed.length} failed=${failed.length}`);
|
|
124
|
-
if (failed.length) {
|
|
125
|
-
console.log(`FAILED: ${failed.map((f) => f.lane).join(", ")}`);
|
|
126
|
-
process.exit(1);
|
|
127
|
-
}
|
|
128
|
-
console.log("HYPERCORE STAKING OK: reads live, stake/unstake/delegate prepare-only, caps enforced.");
|
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
// Oracle end-to-end LIVE lane probe: Solana + Bitcoin.
|
|
2
|
-
// Read/quote/prepare/simulate only. No signing. No broadcast. No keys required.
|
|
3
|
-
//
|
|
4
|
-
// Run: node scripts/e2e-solana-bitcoin.mjs
|
|
5
|
-
// Exit 0 = every mandatory lane answered live. Optional keyed lanes are reported, not failed.
|
|
6
|
-
|
|
7
|
-
import { data as desk } from "../src/data/desk-data.mjs";
|
|
8
|
-
import { jupiterQuote, jupiterPrepareSwap, SOL_MINT, USDC_MINT } from "../src/data/providers/jupiter.mjs";
|
|
9
|
-
import { solanaSimulateTransaction } from "../src/data/providers/solana-rpc.mjs";
|
|
10
|
-
import { magicEdenSolStats, magicEdenSolListings, magicEdenSolPrepareBuy } from "../src/data/providers/magiceden-sol.mjs";
|
|
11
|
-
|
|
12
|
-
const PROBE_WALLET = process.env.ORACLE_E2E_SOL_PUBKEY || "11111111111111111111111111111111";
|
|
13
|
-
const PROBE_BTC = process.env.ORACLE_E2E_BTC_ADDRESS || "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq";
|
|
14
|
-
|
|
15
|
-
const results = [];
|
|
16
|
-
function record(lane, status, detail) {
|
|
17
|
-
results.push({ lane, status, detail });
|
|
18
|
-
const tag = status === "ok" ? "OK " : status === "keyed" ? "KEY " : "FAIL";
|
|
19
|
-
console.log(`${tag} ${lane} :: ${detail}`);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
async function run(lane, fn, { optional = false } = {}) {
|
|
23
|
-
try {
|
|
24
|
-
const detail = await fn();
|
|
25
|
-
record(lane, "ok", detail);
|
|
26
|
-
return true;
|
|
27
|
-
} catch (error) {
|
|
28
|
-
const message = String(error?.message || error).slice(0, 140);
|
|
29
|
-
record(lane, optional ? "keyed" : "fail", message);
|
|
30
|
-
return optional;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
console.log("== SOLANA ==");
|
|
35
|
-
|
|
36
|
-
await run("solana.rpc.health", async () => {
|
|
37
|
-
const health = await desk.solana.health();
|
|
38
|
-
if (!health?.ok) throw new Error(`rpc unhealthy ${JSON.stringify(health).slice(0, 80)}`);
|
|
39
|
-
return `cluster ok slot lane live`;
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
await run("solana.rpc.balance", async () => {
|
|
43
|
-
const bal = await desk.solana.balance(PROBE_WALLET);
|
|
44
|
-
return `lamports=${bal?.lamports ?? bal?.value ?? "n/a"}`;
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
await run("solana.rpc.tokenAccounts", async () => {
|
|
48
|
-
const accounts = await desk.solana.tokenAccounts({ owner: PROBE_WALLET });
|
|
49
|
-
return `accounts=${accounts?.accounts?.length ?? 0}`;
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
let jupQuote = null;
|
|
53
|
-
await run("solana.jupiter.quote(SOL->USDC)", async () => {
|
|
54
|
-
jupQuote = await jupiterQuote({ inputMint: SOL_MINT, outputMint: USDC_MINT, amount: "10000000", slippageBps: 50 });
|
|
55
|
-
const g = jupQuote.solanaGuard;
|
|
56
|
-
if (jupQuote.executionReady !== false) throw new Error("quote must not be executionReady");
|
|
57
|
-
if (g.slippageBps > 100) throw new Error("slippage cap breached");
|
|
58
|
-
return `out=${jupQuote.quote.outAmount} bps=${g.slippageBps} expires=${g.expiresAtMs - g.quotedAtMs}ms execReady=false`;
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
await run("solana.jupiter.slippageCap", async () => {
|
|
62
|
-
try {
|
|
63
|
-
await jupiterQuote({ inputMint: SOL_MINT, outputMint: USDC_MINT, amount: "10000000", slippageBps: 500 });
|
|
64
|
-
} catch (error) {
|
|
65
|
-
return `rejected 500bps: ${String(error.message).slice(0, 60)}`;
|
|
66
|
-
}
|
|
67
|
-
throw new Error("500 bps was NOT rejected");
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
let jupPrepared = null;
|
|
71
|
-
await run("solana.jupiter.prepareSwap", async () => {
|
|
72
|
-
jupPrepared = await jupiterPrepareSwap({
|
|
73
|
-
quoteResponse: jupQuote.quote,
|
|
74
|
-
userPublicKey: PROBE_WALLET,
|
|
75
|
-
});
|
|
76
|
-
if (jupPrepared.signingReady !== false || jupPrepared.broadcastReady !== false) throw new Error("prepare leaked signing/broadcast readiness");
|
|
77
|
-
if (!jupPrepared.requiresUserSignature) throw new Error("prepare must require user signature");
|
|
78
|
-
return `tx=${jupPrepared.swapTransaction.length}b64 requiresUserSig=true signingReady=false broadcastReady=false`;
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
await run("solana.rpc.simulate(preparedSwap)", async () => {
|
|
82
|
-
const sim = await solanaSimulateTransaction({ transaction: jupPrepared.swapTransaction, sigVerify: false });
|
|
83
|
-
const err = sim?.err ?? sim?.value?.err ?? sim?.raw?.value?.err ?? null;
|
|
84
|
-
const units = sim?.unitsConsumed ?? sim?.value?.unitsConsumed ?? sim?.raw?.value?.unitsConsumed ?? null;
|
|
85
|
-
return `err=${JSON.stringify(err)} unitsConsumed=${units}`;
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
await run("solana.nft.magiceden.stats", async () => {
|
|
89
|
-
const stats = await magicEdenSolStats({ symbol: "mad_lads" });
|
|
90
|
-
if (!(stats.floorPriceSol > 0)) throw new Error("no floor");
|
|
91
|
-
return `floor=${stats.floorPriceSol} SOL listed=${stats.listedCount}`;
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
let meListing = null;
|
|
95
|
-
await run("solana.nft.magiceden.listings", async () => {
|
|
96
|
-
const out = await magicEdenSolListings({ symbol: "mad_lads", limit: 1 });
|
|
97
|
-
meListing = out.listings[0];
|
|
98
|
-
if (!meListing?.tokenMint) throw new Error("no listing");
|
|
99
|
-
return `mint=${meListing.tokenMint.slice(0, 8)}.. price=${meListing.priceSol} SOL seller=${meListing.seller.slice(0, 6)}..`;
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
await run(
|
|
103
|
-
"solana.nft.magiceden.prepareBuy",
|
|
104
|
-
async () => {
|
|
105
|
-
const prep = await magicEdenSolPrepareBuy({
|
|
106
|
-
buyer: PROBE_WALLET,
|
|
107
|
-
seller: meListing.seller,
|
|
108
|
-
auctionHouse: meListing.auctionHouse,
|
|
109
|
-
tokenMint: meListing.tokenMint,
|
|
110
|
-
tokenATA: meListing.tokenATA,
|
|
111
|
-
priceSol: meListing.priceSol,
|
|
112
|
-
});
|
|
113
|
-
if (prep.broadcastReady !== false) throw new Error("prepare leaked broadcast readiness");
|
|
114
|
-
return `tx prepared bytes=${String(prep.transaction || "").length} requiresUserSig=${prep.requiresUserSignature}`;
|
|
115
|
-
},
|
|
116
|
-
{ optional: true }
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
console.log("== BITCOIN ==");
|
|
120
|
-
|
|
121
|
-
await run("bitcoin.esplora.health", async () => {
|
|
122
|
-
const h = await desk.bitcoin.health();
|
|
123
|
-
if (!h?.ok) throw new Error("esplora unhealthy");
|
|
124
|
-
return `ok tip lane live`;
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
await run("bitcoin.esplora.tipHeight", async () => {
|
|
128
|
-
const t = await desk.bitcoin.tipHeight();
|
|
129
|
-
const height = t?.height ?? t?.tipHeight ?? t;
|
|
130
|
-
if (!Number(height)) throw new Error("no tip height");
|
|
131
|
-
return `tip=${height}`;
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
await run("bitcoin.esplora.fees", async () => {
|
|
135
|
-
const f = await desk.bitcoin.fees();
|
|
136
|
-
const fast = f?.fastestFee ?? f?.fees?.fastestFee ?? f?.["1"] ?? null;
|
|
137
|
-
return `fastest=${JSON.stringify(fast)}`;
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
await run("bitcoin.esplora.address", async () => {
|
|
141
|
-
const a = await desk.bitcoin.address(PROBE_BTC);
|
|
142
|
-
const funded = a?.chainStats?.fundedTxoSum ?? a?.balanceSats ?? a?.raw?.chain_stats?.funded_txo_sum ?? null;
|
|
143
|
-
return `fundedSats=${funded}`;
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
await run("bitcoin.esplora.utxos", async () => {
|
|
147
|
-
const u = await desk.bitcoin.utxos(PROBE_BTC);
|
|
148
|
-
const n = u?.utxos?.length ?? u?.length ?? 0;
|
|
149
|
-
return `utxos=${n}`;
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
await run("bitcoin.meta.health", async () => {
|
|
153
|
-
const h = await desk.bitcoin.metaHealth();
|
|
154
|
-
return `ok=${h?.ok} tier=${h?.tier ?? h?.mode ?? "keyless"}`;
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
await run(
|
|
158
|
-
"bitcoin.meta.inscriptionInfo",
|
|
159
|
-
async () => {
|
|
160
|
-
const info = await desk.bitcoin.inscriptions(PROBE_BTC);
|
|
161
|
-
return `inscriptions=${info?.inscriptions?.length ?? "unknown"}`;
|
|
162
|
-
},
|
|
163
|
-
{ optional: true }
|
|
164
|
-
);
|
|
165
|
-
|
|
166
|
-
await run(
|
|
167
|
-
"bitcoin.satflow.health",
|
|
168
|
-
async () => {
|
|
169
|
-
const h = await desk.bitcoin.satflowHealth();
|
|
170
|
-
if (!h?.ok) throw new Error(`satflow ${JSON.stringify(h).slice(0, 90)}`);
|
|
171
|
-
return `ok`;
|
|
172
|
-
},
|
|
173
|
-
{ optional: true }
|
|
174
|
-
);
|
|
175
|
-
|
|
176
|
-
const failed = results.filter((r) => r.status === "fail");
|
|
177
|
-
const keyed = results.filter((r) => r.status === "keyed");
|
|
178
|
-
console.log(`\nlanes=${results.length} ok=${results.length - failed.length - keyed.length} keyed=${keyed.length} failed=${failed.length}`);
|
|
179
|
-
if (failed.length) {
|
|
180
|
-
console.log(`FAILED: ${failed.map((f) => f.lane).join(", ")}`);
|
|
181
|
-
process.exit(1);
|
|
182
|
-
}
|
|
183
|
-
console.log("E2E OK: every mandatory Solana + Bitcoin lane answered live, prepare-only posture held.");
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { listProtocolTemplates, runProtocolTemplateGate } from "../src/protocol-templates/gate.mjs";
|
|
3
|
-
|
|
4
|
-
const id = process.argv[2];
|
|
5
|
-
if (!id || id === "list") {
|
|
6
|
-
console.log(JSON.stringify(listProtocolTemplates(), null, 2));
|
|
7
|
-
process.exit(0);
|
|
8
|
-
}
|
|
9
|
-
try {
|
|
10
|
-
const r = runProtocolTemplateGate(id, { allowSkipStatic: process.env.REQUIRE_SLITHER !== "1" });
|
|
11
|
-
console.log(JSON.stringify(r, null, 2));
|
|
12
|
-
} catch (e) {
|
|
13
|
-
console.error(String(e.message || e));
|
|
14
|
-
process.exit(1);
|
|
15
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import fs from "node:fs/promises";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
import { scanPublicApis } from "../src/data/public-api-scan.mjs";
|
|
5
|
-
|
|
6
|
-
const args = process.argv.slice(2);
|
|
7
|
-
const value = (flag) => {
|
|
8
|
-
const i = args.indexOf(flag);
|
|
9
|
-
return i >= 0 ? args[i + 1] : null;
|
|
10
|
-
};
|
|
11
|
-
const outPath = value("--out");
|
|
12
|
-
const timeoutMs = Number(value("--timeout-ms") || 12_000);
|
|
13
|
-
const providers = value("--providers")?.split(",").map((x) => x.trim()).filter(Boolean);
|
|
14
|
-
|
|
15
|
-
const report = await scanPublicApis({ providers, timeoutMs });
|
|
16
|
-
const json = `${JSON.stringify(report, null, 2)}\n`;
|
|
17
|
-
if (outPath) {
|
|
18
|
-
const target = path.resolve(outPath);
|
|
19
|
-
await fs.mkdir(path.dirname(target), { recursive: true });
|
|
20
|
-
await fs.writeFile(target, json, "utf8");
|
|
21
|
-
console.error(`wrote ${target}`);
|
|
22
|
-
}
|
|
23
|
-
process.stdout.write(json);
|
package/scripts/secret-scan.mjs
DELETED
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// Pre-publication secret scan. Fails CLOSED: any hit is an error.
|
|
3
|
-
//
|
|
4
|
-
// Checks the working tree AND every blob in git history, because a secret
|
|
5
|
-
// removed in a later commit is still public the moment the repo is.
|
|
6
|
-
|
|
7
|
-
import { execFileSync } from "node:child_process";
|
|
8
|
-
|
|
9
|
-
const ROOT = process.cwd();
|
|
10
|
-
|
|
11
|
-
// Live values that must never appear. Sourced from the environment at scan
|
|
12
|
-
// time so the scanner itself contains no secrets.
|
|
13
|
-
function liveSecrets() {
|
|
14
|
-
const out = [];
|
|
15
|
-
const push = (label, value) => {
|
|
16
|
-
const v = String(value || "").trim();
|
|
17
|
-
if (v.length >= 8) out.push({ label, value: v });
|
|
18
|
-
};
|
|
19
|
-
for (const k of Object.keys(process.env)) {
|
|
20
|
-
if (/(_KEY|_SECRET|_TOKEN|_PASSPHRASE|_WIF|PRIVATE_KEY)$/i.test(k)) {
|
|
21
|
-
push(`env:${k}`, process.env[k]);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
return out;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// A representative slice of the BIP39 English wordlist. Full coverage is not
|
|
28
|
-
// required: a real mnemonic is 12 or 24 words drawn ENTIRELY from the list, so
|
|
29
|
-
// any genuine phrase will hit these common entries, while English prose will
|
|
30
|
-
// not have every one of its words in the list.
|
|
31
|
-
const BIP39_SAMPLE = new Set(
|
|
32
|
-
("abandon ability able about above absent absorb abstract absurd abuse access accident account accuse achieve acid " +
|
|
33
|
-
"across act action actor actress actual adapt add addict address adjust admit adult advance advice aerobic affair " +
|
|
34
|
-
"afford afraid again age agent agree ahead aim air airport aisle alarm album alcohol alert alien all alley allow " +
|
|
35
|
-
"almost alone alpha already also alter always amateur amazing among amount amused analyst anchor ancient anger " +
|
|
36
|
-
"angle angry animal ankle announce annual another answer antenna antique anxiety any apart apology appear apple " +
|
|
37
|
-
"approve april arch arctic area arena argue arm armed armor army around arrange arrest arrive arrow art artefact " +
|
|
38
|
-
"artist artwork ask aspect assault asset assist assume asthma athlete atom attack attend attitude attract auction " +
|
|
39
|
-
"audit august aunt author auto autumn average avocado avoid awake aware away awesome awful awkward axis baby " +
|
|
40
|
-
"bachelor bacon badge bag balance balcony ball bamboo banana banner bar barely bargain barrel base basic basket " +
|
|
41
|
-
"battle beach bean beauty because become beef before begin behave behind believe below belt bench benefit best " +
|
|
42
|
-
"betray better between beyond bicycle bid bike bind biology bird birth bitter black blade blame blanket blast " +
|
|
43
|
-
"bleak bless blind blood blossom blouse blue blur blush board boat body boil bomb bone bonus book boost border " +
|
|
44
|
-
"boring borrow boss bottom bounce box boy bracket brain brand brass brave bread breeze brick bridge brief bright " +
|
|
45
|
-
"bring brisk broccoli broken bronze broom brother brown brush bubble buddy budget buffalo build bulb bulk bullet " +
|
|
46
|
-
"bundle bunker burden burger burst bus business busy butter buyer buzz cabbage cabin cable cactus cage cake call " +
|
|
47
|
-
"calm camera camp can canal cancel candy cannon canoe canvas canyon capable capital captain car carbon card cargo " +
|
|
48
|
-
"carpet carry cart case cash casino castle casual cat catalog catch category cattle caught cause caution cave " +
|
|
49
|
-
"ceiling celery cement census century cereal certain chair chalk champion change chaos chapter charge chase chat " +
|
|
50
|
-
"cheap check cheese chef cherry chest chicken chief child chimney choice choose chronic chuckle chunk churn cigar " +
|
|
51
|
-
"cinnamon circle citizen city civil claim clap clarify claw clay clean clerk clever click client cliff climb " +
|
|
52
|
-
"clinic clip clock clog close cloth cloud clown club clump cluster clutch coach coast coconut code coffee coil " +
|
|
53
|
-
"coin collect color column combine come comfort comic common company concert conduct confirm congress connect " +
|
|
54
|
-
"consider control convince cook cool copper copy coral core corn correct cost cotton couch country couple course " +
|
|
55
|
-
"cousin cover coyote crack cradle craft cram crane crash crater crawl crazy cream credit creek crew cricket crime " +
|
|
56
|
-
"crisp critic crop cross crouch crowd crucial cruel cruise crumble crunch crush cry crystal cube culture cup " +
|
|
57
|
-
"cupboard curious current curtain curve cushion custom cute cycle zoo zone zero youth young you yellow year " +
|
|
58
|
-
"wrong write wrist wrap worth world work word wood wonder woman wolf wire winter wing wine window wind wild wife " +
|
|
59
|
-
"why whisper white where when wheat what wet west welcome weird weekend week wedding web wealth wear weapon " +
|
|
60
|
-
"weasel wear wave water watch waste wash warrior warm want walnut wall walk wait wagon void voice vote volume " +
|
|
61
|
-
"vocal vivid virus violin virtual vintage view video vicious vibrant vessel very verify version verb vendor " +
|
|
62
|
-
"vehicle vegetable vault various vast vase vanish valve valley valid vacuum vacant").split(/\s+/)
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
const PATTERNS = [
|
|
66
|
-
{ name: "private key (hex 64)", re: /\b(?:0x)?[0-9a-fA-F]{64}\b/, refine: (m, line) =>
|
|
67
|
-
/priv|secret|wif|seed|mnemonic|signer|wallet/i.test(line) && !/hash|digest|sha256|txid|commit|blob|sha1|0x0{40,}/i.test(line) },
|
|
68
|
-
{ name: "BTC WIF", re: /\b[5KL][1-9A-HJ-NP-Za-km-z]{50,51}\b/ },
|
|
69
|
-
{ name: "BIP39 seed phrase", re: /\b(?:[a-z]{3,8} ){11,23}[a-z]{3,8}\b/, refine: (m) => {
|
|
70
|
-
// Ordinary English prose trivially matches "12-24 short lowercase words".
|
|
71
|
-
// A scanner that cries wolf on comments is a scanner people switch off,
|
|
72
|
-
// so require the words to actually be in the BIP39 wordlist.
|
|
73
|
-
const words = m[0].trim().split(/\s+/);
|
|
74
|
-
if (words.length !== 12 && words.length !== 24) return false;
|
|
75
|
-
return words.every((w) => BIP39_SAMPLE.has(w));
|
|
76
|
-
} },
|
|
77
|
-
{ name: "AWS access key", re: /\bAKIA[0-9A-Z]{16}\b/ },
|
|
78
|
-
{ name: "OpenAI key", re: /\bsk-[A-Za-z0-9_-]{20,}\b/ },
|
|
79
|
-
{ name: "Anthropic key", re: /\bsk-ant-[A-Za-z0-9_-]{20,}\b/ },
|
|
80
|
-
{ name: "GitHub token", re: /\bgh[pousr]_[A-Za-z0-9]{36,}\b/ },
|
|
81
|
-
{ name: "Slack token", re: /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/ },
|
|
82
|
-
{ name: "Telegram bot token", re: /\b\d{8,10}:[A-Za-z0-9_-]{35}\b/ },
|
|
83
|
-
{ name: "PEM private key", re: /-----BEGIN (?:RSA |EC |OPENSSH |PGP )?PRIVATE KEY-----/ },
|
|
84
|
-
{ name: "Solana keypair array", re: /\[\s*(?:\d{1,3}\s*,\s*){63}\d{1,3}\s*\]/ },
|
|
85
|
-
];
|
|
86
|
-
|
|
87
|
-
// Paths whose matches are known-safe test fixtures.
|
|
88
|
-
const ALLOWED_PATHS = [
|
|
89
|
-
/^scripts\/secret-scan\.mjs$/,
|
|
90
|
-
/^package-lock\.json$/,
|
|
91
|
-
];
|
|
92
|
-
|
|
93
|
-
// Literal strings that are documented, synthetic, or public by nature.
|
|
94
|
-
const ALLOWED_VALUES = [
|
|
95
|
-
"0x0123456789012345678901234567890123456789012345678901234567890123", // HL SDK public test vector
|
|
96
|
-
"L1aW4aubDFB7yfras2S1mN3bqg9nwySY8nkoLmJebSLD5BWv3ENZ",
|
|
97
|
-
"/-----BEGIN[A-Z ]*PRIVATE KEY-----/",
|
|
98
|
-
'{ value: "-----BEGIN EC PRIVATE KEY-----" }',
|
|
99
|
-
"0x0000000000000000000000000000000000000000",
|
|
100
|
-
];
|
|
101
|
-
|
|
102
|
-
function sh(cmd, args) {
|
|
103
|
-
return execFileSync(cmd, args, { cwd: ROOT, encoding: "utf8", maxBuffer: 256 * 1024 * 1024 });
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function scanText(text, origin, findings) {
|
|
107
|
-
const lines = text.split("\n");
|
|
108
|
-
for (let i = 0; i < lines.length; i++) {
|
|
109
|
-
const line = lines[i];
|
|
110
|
-
if (line.length > 4000) continue;
|
|
111
|
-
for (const p of PATTERNS) {
|
|
112
|
-
const m = p.re.exec(line);
|
|
113
|
-
if (!m) continue;
|
|
114
|
-
if (ALLOWED_VALUES.some((v) => line.includes(v))) continue;
|
|
115
|
-
if (p.refine && !p.refine(m, line)) continue;
|
|
116
|
-
findings.push({ origin, line: i + 1, kind: p.name, sample: line.trim().slice(0, 100) });
|
|
117
|
-
}
|
|
118
|
-
for (const s of LIVE) {
|
|
119
|
-
if (line.includes(s.value)) {
|
|
120
|
-
findings.push({ origin, line: i + 1, kind: `LIVE SECRET ${s.label}`, sample: "[REDACTED — real credential]" });
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
const LIVE = liveSecrets();
|
|
127
|
-
const findings = [];
|
|
128
|
-
|
|
129
|
-
// --- 1. working tree (tracked files only) ---
|
|
130
|
-
const tracked = sh("git", ["ls-files"]).split("\n").filter(Boolean);
|
|
131
|
-
for (const rel of tracked) {
|
|
132
|
-
if (ALLOWED_PATHS.some((r) => r.test(rel))) continue;
|
|
133
|
-
let content;
|
|
134
|
-
try {
|
|
135
|
-
content = sh("git", ["show", `:${rel}`]);
|
|
136
|
-
} catch {
|
|
137
|
-
continue; // binary or unreadable
|
|
138
|
-
}
|
|
139
|
-
if (content.includes("\u0000")) continue;
|
|
140
|
-
scanText(content, rel, findings);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// --- 2. every blob in history ---
|
|
144
|
-
const revs = sh("git", ["rev-list", "--all"]).split("\n").filter(Boolean);
|
|
145
|
-
const seen = new Set();
|
|
146
|
-
let historyBlobs = 0;
|
|
147
|
-
for (const rev of revs) {
|
|
148
|
-
const entries = sh("git", ["ls-tree", "-r", rev]).split("\n").filter(Boolean);
|
|
149
|
-
for (const entry of entries) {
|
|
150
|
-
const [meta, path] = entry.split("\t");
|
|
151
|
-
const sha = meta.split(/\s+/)[2];
|
|
152
|
-
if (!sha || seen.has(sha)) continue;
|
|
153
|
-
seen.add(sha);
|
|
154
|
-
if (ALLOWED_PATHS.some((r) => r.test(path))) continue;
|
|
155
|
-
let content;
|
|
156
|
-
try {
|
|
157
|
-
content = sh("git", ["cat-file", "-p", sha]);
|
|
158
|
-
} catch {
|
|
159
|
-
continue;
|
|
160
|
-
}
|
|
161
|
-
if (content.includes("\u0000")) continue;
|
|
162
|
-
historyBlobs++;
|
|
163
|
-
scanText(content, `history:${rev.slice(0, 8)}:${path}`, findings);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// --- 3. author identity leakage ---
|
|
168
|
-
const authors = new Set(sh("git", ["log", "--all", "--format=%an <%ae>|%cn <%ce>"]).split(/[\n|]/).filter(Boolean));
|
|
169
|
-
|
|
170
|
-
console.log(`scanned ${tracked.length} tracked files, ${historyBlobs} historical blobs, ${revs.length} commits`);
|
|
171
|
-
console.log(`live env secrets checked: ${LIVE.length}`);
|
|
172
|
-
console.log(`git identities: ${[...authors].join(", ") || "(none)"}`);
|
|
173
|
-
|
|
174
|
-
if (findings.length) {
|
|
175
|
-
console.error(`\nFAIL — ${findings.length} finding(s):`);
|
|
176
|
-
for (const f of findings.slice(0, 40)) {
|
|
177
|
-
console.error(` ${f.origin}:${f.line} [${f.kind}] ${f.sample}`);
|
|
178
|
-
}
|
|
179
|
-
process.exit(1);
|
|
180
|
-
}
|
|
181
|
-
console.log("\nPASS — no secrets found in tree or history");
|