dexterm-cli 0.0.0-stage → 0.1.2
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 +661 -0
- package/dist/packages/agents/src/audit.js +122 -0
- package/dist/packages/agents/src/bus.js +394 -0
- package/dist/packages/agents/src/executor.js +202 -0
- package/dist/packages/agents/src/gate.js +179 -0
- package/dist/packages/agents/src/identity.js +218 -0
- package/dist/packages/agents/src/index.js +15 -0
- package/dist/packages/agents/src/proposals.js +153 -0
- package/dist/packages/agents/src/schema.js +87 -0
- package/dist/packages/agents/src/sdk.js +140 -0
- package/dist/packages/agents/src/tiers.js +119 -0
- package/dist/packages/agents/src/tools.js +72 -0
- package/dist/packages/agents/src/ws.js +158 -0
- package/dist/packages/cli/assets/claude/analyst-system.md +76 -0
- package/dist/packages/cli/assets/claude/plugin/.claude-plugin/plugin.json +5 -0
- package/dist/packages/cli/assets/claude/plugin/skills/REGISTRY.json +16 -0
- package/dist/packages/cli/assets/claude/plugin/skills/larp-check/SKILL.md +75 -0
- package/dist/packages/cli/assets/claude/plugin/skills/rug-check/SKILL.md +74 -0
- package/dist/packages/cli/assets/claude/plugin/skills/token-dossier/SKILL.md +63 -0
- package/dist/packages/cli/assets/claude/plugin/skills/trench-scan/SKILL.md +44 -0
- package/dist/packages/cli/assets/claude/schemas/larp.schema.json +117 -0
- package/dist/packages/cli/assets/claude/schemas/trench-scan.schema.json +71 -0
- package/dist/packages/cli/assets/claude/schemas/verdict.schema.json +115 -0
- package/dist/packages/cli/bin/dexterm.mjs +11 -0
- package/dist/packages/cli/src/agent-cmd.js +336 -0
- package/dist/packages/cli/src/agent-roster.js +26 -0
- package/dist/packages/cli/src/alerts/adapters/desktop.js +40 -0
- package/dist/packages/cli/src/alerts/adapters/discord.js +36 -0
- package/dist/packages/cli/src/alerts/adapters/telegram.js +43 -0
- package/dist/packages/cli/src/alerts/adapters/toast.js +16 -0
- package/dist/packages/cli/src/alerts/creds.js +83 -0
- package/dist/packages/cli/src/alerts/format.js +41 -0
- package/dist/packages/cli/src/alerts/index.js +10 -0
- package/dist/packages/cli/src/alerts/notifier.js +53 -0
- package/dist/packages/cli/src/alerts/route.js +19 -0
- package/dist/packages/cli/src/alerts/types.js +1 -0
- package/dist/packages/cli/src/alerts-cmd.js +212 -0
- package/dist/packages/cli/src/analyst/backend.js +526 -0
- package/dist/packages/cli/src/analyst/results.js +38 -0
- package/dist/packages/cli/src/analyst/session.js +319 -0
- package/dist/packages/cli/src/audit.js +51 -0
- package/dist/packages/cli/src/backtest-cmd.js +208 -0
- package/dist/packages/cli/src/boot-state.js +62 -0
- package/dist/packages/cli/src/coin-target.js +2 -0
- package/dist/packages/cli/src/custom.js +261 -0
- package/dist/packages/cli/src/display.js +191 -0
- package/dist/packages/cli/src/doctor.js +375 -0
- package/dist/packages/cli/src/export.js +235 -0
- package/dist/packages/cli/src/feed.js +634 -0
- package/dist/packages/cli/src/fixtures.js +275 -0
- package/dist/packages/cli/src/follow-cmd.js +221 -0
- package/dist/packages/cli/src/images-config.js +59 -0
- package/dist/packages/cli/src/index.js +31 -0
- package/dist/packages/cli/src/kb-skill-cmd.js +240 -0
- package/dist/packages/cli/src/larp-record.js +21 -0
- package/dist/packages/cli/src/live/copy.js +80 -0
- package/dist/packages/cli/src/live/flow.js +233 -0
- package/dist/packages/cli/src/live/index.js +511 -0
- package/dist/packages/cli/src/live/intel.js +227 -0
- package/dist/packages/cli/src/live/newpairs.js +334 -0
- package/dist/packages/cli/src/live/screens/newpairs-live.js +219 -0
- package/dist/packages/cli/src/live/screens/token-live.js +459 -0
- package/dist/packages/cli/src/live/screens/watchlist-live.js +149 -0
- package/dist/packages/cli/src/live/token.js +585 -0
- package/dist/packages/cli/src/live/trade.js +929 -0
- package/dist/packages/cli/src/live/watchlist.js +178 -0
- package/dist/packages/cli/src/main.js +5785 -0
- package/dist/packages/cli/src/mcp-cmd.js +326 -0
- package/dist/packages/cli/src/narrative-cmd.js +76 -0
- package/dist/packages/cli/src/pack-cmd.js +323 -0
- package/dist/packages/cli/src/plan-cmd.js +278 -0
- package/dist/packages/cli/src/popup.js +810 -0
- package/dist/packages/cli/src/rules-cmd.js +131 -0
- package/dist/packages/cli/src/rules.js +358 -0
- package/dist/packages/cli/src/scan/command.js +57 -0
- package/dist/packages/cli/src/scan/engine.js +419 -0
- package/dist/packages/cli/src/scan/observe.js +64 -0
- package/dist/packages/cli/src/scan/ui.js +98 -0
- package/dist/packages/cli/src/screener/filter.js +241 -0
- package/dist/packages/cli/src/screener/presets.js +80 -0
- package/dist/packages/cli/src/screener/rows.js +146 -0
- package/dist/packages/cli/src/screener/rug.js +50 -0
- package/dist/packages/cli/src/screener/sort.js +52 -0
- package/dist/packages/cli/src/screener/view.js +183 -0
- package/dist/packages/cli/src/screens/analyst-session.js +343 -0
- package/dist/packages/cli/src/screens/analyst.js +326 -0
- package/dist/packages/cli/src/screens/boot.js +74 -0
- package/dist/packages/cli/src/screens/bubbles.js +255 -0
- package/dist/packages/cli/src/screens/coin.js +33 -0
- package/dist/packages/cli/src/screens/follows.js +201 -0
- package/dist/packages/cli/src/screens/kol.js +90 -0
- package/dist/packages/cli/src/screens/narrative.js +90 -0
- package/dist/packages/cli/src/screens/newpairs.js +150 -0
- package/dist/packages/cli/src/screens/overlay.js +257 -0
- package/dist/packages/cli/src/screens/plans.js +126 -0
- package/dist/packages/cli/src/screens/positions.js +176 -0
- package/dist/packages/cli/src/screens/rules.js +170 -0
- package/dist/packages/cli/src/screens/screener.js +459 -0
- package/dist/packages/cli/src/screens/social-panel.js +107 -0
- package/dist/packages/cli/src/screens/ticket.js +342 -0
- package/dist/packages/cli/src/screens/token.js +312 -0
- package/dist/packages/cli/src/screens/trending.js +181 -0
- package/dist/packages/cli/src/screens/watchlist.js +104 -0
- package/dist/packages/cli/src/skill-eval-build.js +109 -0
- package/dist/packages/cli/src/social/demo.js +96 -0
- package/dist/packages/cli/src/social/view.js +250 -0
- package/dist/packages/cli/src/state.js +463 -0
- package/dist/packages/cli/src/theme-cmd.js +126 -0
- package/dist/packages/cli/src/trade.js +319 -0
- package/dist/packages/cli/src/update.js +294 -0
- package/dist/packages/cli/src/version.js +3 -0
- package/dist/packages/cli/src/voice-cmd.js +119 -0
- package/dist/packages/cli/src/voice-hud.js +42 -0
- package/dist/packages/cli/src/wallet-cmd.js +440 -0
- package/dist/packages/cli/src/wallet-command.js +31 -0
- package/dist/packages/cli/src/watch-cmd.js +190 -0
- package/dist/packages/cli/src/widgets.js +208 -0
- package/dist/packages/cli/src/workspace-cmd.js +68 -0
- package/dist/packages/cli/src/x-cmd.js +154 -0
- package/dist/packages/custom/src/config.js +213 -0
- package/dist/packages/custom/src/index.js +10 -0
- package/dist/packages/custom/src/keymap.js +107 -0
- package/dist/packages/custom/src/layout.js +235 -0
- package/dist/packages/custom/src/packs.js +633 -0
- package/dist/packages/custom/src/rules.js +704 -0
- package/dist/packages/custom/src/schema.js +538 -0
- package/dist/packages/custom/src/themes.js +176 -0
- package/dist/packages/custom/src/widget-html.js +222 -0
- package/dist/packages/custom/src/workspace.js +141 -0
- package/dist/packages/data/src/analyst-actions.js +133 -0
- package/dist/packages/data/src/budget.js +88 -0
- package/dist/packages/data/src/cache.js +142 -0
- package/dist/packages/data/src/candles.js +168 -0
- package/dist/packages/data/src/clock.js +64 -0
- package/dist/packages/data/src/coin-target.js +82 -0
- package/dist/packages/data/src/credits.js +137 -0
- package/dist/packages/data/src/detail.js +97 -0
- package/dist/packages/data/src/fast-lane.js +321 -0
- package/dist/packages/data/src/fixtures.js +135 -0
- package/dist/packages/data/src/health.js +245 -0
- package/dist/packages/data/src/http.js +277 -0
- package/dist/packages/data/src/images/cache.js +141 -0
- package/dist/packages/data/src/images/decode-worker.js +28 -0
- package/dist/packages/data/src/images/decode.js +81 -0
- package/dist/packages/data/src/images/fetch.js +162 -0
- package/dist/packages/data/src/images/gif.js +214 -0
- package/dist/packages/data/src/images/index.js +10 -0
- package/dist/packages/data/src/images/jpeg.js +544 -0
- package/dist/packages/data/src/images/png.js +310 -0
- package/dist/packages/data/src/images/service.js +334 -0
- package/dist/packages/data/src/images/types.js +27 -0
- package/dist/packages/data/src/index.js +211 -0
- package/dist/packages/data/src/intel/helius-history.js +70 -0
- package/dist/packages/data/src/intel/holder-class.js +125 -0
- package/dist/packages/data/src/intel/rules.js +421 -0
- package/dist/packages/data/src/intel/scan.js +170 -0
- package/dist/packages/data/src/larp/evidence.js +288 -0
- package/dist/packages/data/src/larp/link-baseline.js +196 -0
- package/dist/packages/data/src/larp/links.js +137 -0
- package/dist/packages/data/src/larp/robots.js +90 -0
- package/dist/packages/data/src/larp/safe-fetch.js +389 -0
- package/dist/packages/data/src/limiter.js +341 -0
- package/dist/packages/data/src/model.js +12 -0
- package/dist/packages/data/src/paper.js +331 -0
- package/dist/packages/data/src/rpc-config.js +126 -0
- package/dist/packages/data/src/rpc-pool.js +166 -0
- package/dist/packages/data/src/social/chain.js +83 -0
- package/dist/packages/data/src/social/dedupe.js +205 -0
- package/dist/packages/data/src/social/feed.js +462 -0
- package/dist/packages/data/src/social/firewall.js +110 -0
- package/dist/packages/data/src/social/index.js +11 -0
- package/dist/packages/data/src/social/kol.js +269 -0
- package/dist/packages/data/src/social/model.js +11 -0
- package/dist/packages/data/src/social/rank.js +184 -0
- package/dist/packages/data/src/social/rss.js +113 -0
- package/dist/packages/data/src/social/summary.js +104 -0
- package/dist/packages/data/src/social/venues.js +186 -0
- package/dist/packages/data/src/sources/dexscreener.js +184 -0
- package/dist/packages/data/src/sources/geckoterminal.js +133 -0
- package/dist/packages/data/src/sources/goplus.js +161 -0
- package/dist/packages/data/src/sources/jupiter-swap.js +236 -0
- package/dist/packages/data/src/sources/jupiter.js +198 -0
- package/dist/packages/data/src/sources/pda.js +113 -0
- package/dist/packages/data/src/sources/pump-curve.js +58 -0
- package/dist/packages/data/src/sources/pumpportal.js +252 -0
- package/dist/packages/data/src/sources/rugcheck.js +71 -0
- package/dist/packages/data/src/sources/solana-rpc.js +299 -0
- package/dist/packages/data/src/sources/solana-ws.js +287 -0
- package/dist/packages/data/src/store.js +289 -0
- package/dist/packages/data/src/trade/bridge.js +464 -0
- package/dist/packages/data/src/trade/caps.js +323 -0
- package/dist/packages/data/src/trade/copy/auto.js +385 -0
- package/dist/packages/data/src/trade/copy/follows.js +103 -0
- package/dist/packages/data/src/trade/copy/index.js +9 -0
- package/dist/packages/data/src/trade/copy/mirror.js +91 -0
- package/dist/packages/data/src/trade/copy/stats.js +120 -0
- package/dist/packages/data/src/trade/copy/tracker.js +158 -0
- package/dist/packages/data/src/trade/copy/trades.js +87 -0
- package/dist/packages/data/src/trade/copy/types.js +6 -0
- package/dist/packages/data/src/trade/executor.js +933 -0
- package/dist/packages/data/src/trade/kill-switch.js +47 -0
- package/dist/packages/data/src/trade/link-store.js +52 -0
- package/dist/packages/data/src/trade/plans/confirm.js +157 -0
- package/dist/packages/data/src/trade/plans/engine.js +784 -0
- package/dist/packages/data/src/trade/plans/executor-live.js +220 -0
- package/dist/packages/data/src/trade/plans/executor-paper.js +44 -0
- package/dist/packages/data/src/trade/plans/executor.js +11 -0
- package/dist/packages/data/src/trade/plans/index.js +12 -0
- package/dist/packages/data/src/trade/plans/journal.js +77 -0
- package/dist/packages/data/src/trade/plans/mandate.js +129 -0
- package/dist/packages/data/src/trade/plans/plan.js +179 -0
- package/dist/packages/data/src/trade/plans/service.js +168 -0
- package/dist/packages/data/src/trade/plans/types.js +6 -0
- package/dist/packages/data/src/trade/rpc-exec.js +229 -0
- package/dist/packages/data/src/trade/signer/client.js +197 -0
- package/dist/packages/data/src/trade/signer/fast-wallet.js +154 -0
- package/dist/packages/data/src/trade/signer/host.js +97 -0
- package/dist/packages/data/src/trade/signer/main.js +121 -0
- package/dist/packages/data/src/trade/signer/probe-builder.js +85 -0
- package/dist/packages/data/src/trade/signer/protocol.js +92 -0
- package/dist/packages/data/src/trade/signer/service.js +400 -0
- package/dist/packages/data/src/trade/signer/sol-usd-feed.js +98 -0
- package/dist/packages/data/src/trade/sol-usd.js +86 -0
- package/dist/packages/data/src/trade/swap-build.js +108 -0
- package/dist/packages/data/src/trade/token-delta.js +201 -0
- package/dist/packages/data/src/trade/tx-decode.js +632 -0
- package/dist/packages/data/src/util.js +24 -0
- package/dist/packages/data/src/watchlist.js +176 -0
- package/dist/packages/data/src/x/api.js +256 -0
- package/dist/packages/data/src/x/budget.js +66 -0
- package/dist/packages/data/src/x/config.js +49 -0
- package/dist/packages/data/src/x/index.js +10 -0
- package/dist/packages/data/src/x/mock-server.js +217 -0
- package/dist/packages/data/src/x/oauth.js +242 -0
- package/dist/packages/data/src/x/pkce.js +21 -0
- package/dist/packages/data/src/x/source.js +285 -0
- package/dist/packages/data/src/x/token-store.js +134 -0
- package/dist/packages/data/src/x/transport.js +71 -0
- package/dist/packages/data/vendor/solana-web3/LICENSE +20 -0
- package/dist/packages/data/vendor/solana-web3/NOTICE.md +13 -0
- package/dist/packages/data/vendor/solana-web3/index.iife.min.js +20 -0
- package/dist/packages/mcp/assets/cases.json +1194 -0
- package/dist/packages/mcp/assets/kb/entries/cabal-and-coordinated-launches.md +28 -0
- package/dist/packages/mcp/assets/kb/entries/common-rug-patterns.md +40 -0
- package/dist/packages/mcp/assets/kb/entries/dbc-mechanics.md +30 -0
- package/dist/packages/mcp/assets/kb/entries/dev-wallet-behaviour.md +33 -0
- package/dist/packages/mcp/assets/kb/entries/glossary.md +35 -0
- package/dist/packages/mcp/assets/kb/entries/holder-concentration.md +30 -0
- package/dist/packages/mcp/assets/kb/entries/jito-bundles.md +29 -0
- package/dist/packages/mcp/assets/kb/entries/launchlab-curve.md +31 -0
- package/dist/packages/mcp/assets/kb/entries/lp-burn-vs-lock.md +31 -0
- package/dist/packages/mcp/assets/kb/entries/metadata-and-copycats.md +29 -0
- package/dist/packages/mcp/assets/kb/entries/mint-freeze-authority.md +31 -0
- package/dist/packages/mcp/assets/kb/entries/narrative-lifecycle.md +32 -0
- package/dist/packages/mcp/assets/kb/entries/pump-bonding-curve.md +33 -0
- package/dist/packages/mcp/assets/kb/entries/pumpswap-migration.md +29 -0
- package/dist/packages/mcp/assets/kb/entries/sniping-and-snipers.md +29 -0
- package/dist/packages/mcp/assets/kb/entries/token2022-extensions-risk.md +32 -0
- package/dist/packages/mcp/assets/kb/entries/wash-trading-fake-volume.md +33 -0
- package/dist/packages/mcp/assets/skills/rug-check.md +52 -0
- package/dist/packages/mcp/assets/skills/token-dossier.md +57 -0
- package/dist/packages/mcp/assets/skills/trench-scan.md +40 -0
- package/dist/packages/mcp/bin/dexterm-mcp.mjs +16 -0
- package/dist/packages/mcp/src/dossier.js +78 -0
- package/dist/packages/mcp/src/firewall.js +21 -0
- package/dist/packages/mcp/src/index.js +22 -0
- package/dist/packages/mcp/src/server.js +936 -0
- package/dist/packages/mcp/src/user-content.js +434 -0
- package/dist/packages/packs/src/backtest.js +183 -0
- package/dist/packages/packs/src/digest.js +95 -0
- package/dist/packages/packs/src/firewall.js +57 -0
- package/dist/packages/packs/src/index.js +20 -0
- package/dist/packages/packs/src/larp-eval.js +100 -0
- package/dist/packages/packs/src/narrative.js +309 -0
- package/dist/packages/packs/src/reason.js +135 -0
- package/dist/packages/packs/src/rug-model.js +137 -0
- package/dist/packages/packs/src/schema.js +54 -0
- package/dist/packages/packs/src/skill-backtest.js +300 -0
- package/dist/packages/packs/src/token-dossier.js +174 -0
- package/dist/packages/packs/src/verdicts.js +17 -0
- package/dist/packages/packs/src/wallet-dossier.js +105 -0
- package/dist/packages/popup/src/config.js +71 -0
- package/dist/packages/popup/src/dock.js +271 -0
- package/dist/packages/popup/src/host.js +210 -0
- package/dist/packages/popup/src/index.js +12 -0
- package/dist/packages/popup/src/loopback.js +53 -0
- package/dist/packages/popup/src/open.js +183 -0
- package/dist/packages/popup/src/pages/bubbles-lib.js +160 -0
- package/dist/packages/popup/src/pages/bubbles.css +23 -0
- package/dist/packages/popup/src/pages/bubbles.html +36 -0
- package/dist/packages/popup/src/pages/bubbles.js +214 -0
- package/dist/packages/popup/src/pages/chart-lib.js +262 -0
- package/dist/packages/popup/src/pages/chart.css +50 -0
- package/dist/packages/popup/src/pages/chart.html +56 -0
- package/dist/packages/popup/src/pages/chart.js +554 -0
- package/dist/packages/popup/src/pages/common.css +34 -0
- package/dist/packages/popup/src/pages/common.js +187 -0
- package/dist/packages/popup/src/pages/feeds.html +20 -0
- package/dist/packages/popup/src/pages/feeds.js +77 -0
- package/dist/packages/popup/src/pages/narrative.html +20 -0
- package/dist/packages/popup/src/pages/narrative.js +61 -0
- package/dist/packages/popup/src/pages/plans.css +30 -0
- package/dist/packages/popup/src/pages/plans.html +26 -0
- package/dist/packages/popup/src/pages/plans.js +82 -0
- package/dist/packages/popup/src/pages/roster.css +41 -0
- package/dist/packages/popup/src/pages/roster.html +25 -0
- package/dist/packages/popup/src/pages/roster.js +75 -0
- package/dist/packages/popup/src/pages/token.html +20 -0
- package/dist/packages/popup/src/pages/token.js +112 -0
- package/dist/packages/popup/src/pages/widget-sdk.js +224 -0
- package/dist/packages/popup/src/pages/widget.css +5 -0
- package/dist/packages/popup/src/pages/widget.html +21 -0
- package/dist/packages/popup/src/pages/widget.js +85 -0
- package/dist/packages/popup/src/protocol.js +31 -0
- package/dist/packages/popup/src/selftest.js +156 -0
- package/dist/packages/popup/src/server.js +582 -0
- package/dist/packages/popup/src/sinkproxy.js +167 -0
- package/dist/packages/popup/src/widget-html.js +231 -0
- package/dist/packages/popup/vendor/lightweight-charts/LICENSE +201 -0
- package/dist/packages/popup/vendor/lightweight-charts/NOTICE +2 -0
- package/dist/packages/popup/vendor/lightweight-charts/README.md +30 -0
- package/dist/packages/popup/vendor/lightweight-charts/VERSION +1 -0
- package/dist/packages/popup/vendor/lightweight-charts/lightweight-charts.standalone.production.js +7 -0
- package/dist/packages/recorder/bin/dexterm-recorder.mjs +11 -0
- package/dist/packages/recorder/src/cli.js +113 -0
- package/dist/packages/recorder/src/export.js +71 -0
- package/dist/packages/recorder/src/index.js +20 -0
- package/dist/packages/recorder/src/labels.js +151 -0
- package/dist/packages/recorder/src/open.js +29 -0
- package/dist/packages/recorder/src/recorder.js +553 -0
- package/dist/packages/recorder/src/schedule.js +43 -0
- package/dist/packages/recorder/src/schema.js +135 -0
- package/dist/packages/recorder/src/snapshot.js +191 -0
- package/dist/packages/recorder/src/sweep.js +52 -0
- package/dist/packages/recorder/src/verdicts.js +52 -0
- package/dist/packages/tui/src/bubbles.js +415 -0
- package/dist/packages/tui/src/canvas.js +370 -0
- package/dist/packages/tui/src/chrome.js +85 -0
- package/dist/packages/tui/src/color.js +133 -0
- package/dist/packages/tui/src/flush.js +62 -0
- package/dist/packages/tui/src/fmt.js +188 -0
- package/dist/packages/tui/src/fx-trade.js +278 -0
- package/dist/packages/tui/src/fx.js +527 -0
- package/dist/packages/tui/src/images/blocks.js +141 -0
- package/dist/packages/tui/src/images/coin.js +22 -0
- package/dist/packages/tui/src/images/detect.js +140 -0
- package/dist/packages/tui/src/images/index.js +7 -0
- package/dist/packages/tui/src/images/layer.js +146 -0
- package/dist/packages/tui/src/images/pixels.js +157 -0
- package/dist/packages/tui/src/images/protocols.js +87 -0
- package/dist/packages/tui/src/index.js +18 -0
- package/dist/packages/tui/src/keymap.js +357 -0
- package/dist/packages/tui/src/layout.js +11 -0
- package/dist/packages/tui/src/raster-font.js +195 -0
- package/dist/packages/tui/src/raster.js +213 -0
- package/dist/packages/tui/src/sound.js +177 -0
- package/dist/packages/tui/src/theme.js +182 -0
- package/dist/packages/tui/src/widgets.js +598 -0
- package/dist/packages/voice/src/controller.js +407 -0
- package/dist/packages/voice/src/doctor.js +131 -0
- package/dist/packages/voice/src/download.js +184 -0
- package/dist/packages/voice/src/engines.js +84 -0
- package/dist/packages/voice/src/index.js +20 -0
- package/dist/packages/voice/src/router.js +502 -0
- package/dist/packages/voice/src/stt/apple-helper.swift.js +103 -0
- package/dist/packages/voice/src/stt/apple.js +179 -0
- package/dist/packages/voice/src/stt/fake.js +34 -0
- package/dist/packages/voice/src/stt/whisper.js +112 -0
- package/dist/packages/voice/src/summary.js +44 -0
- package/dist/packages/voice/src/tts/espeak.js +131 -0
- package/dist/packages/voice/src/tts/fake.js +30 -0
- package/dist/packages/voice/src/tts/piper.js +206 -0
- package/dist/packages/voice/src/tts/say.js +132 -0
- package/dist/packages/voice/src/tts/voices.js +206 -0
- package/dist/packages/voice/src/types.js +3 -0
- package/package.json +38 -4
- package/README.md +0 -3
|
@@ -0,0 +1,511 @@
|
|
|
1
|
+
// dexterm — live bindings for the TOKEN, NEW PAIRS and WATCHLIST screens (task-1298). One context per
|
|
2
|
+
// run, created over the screener feed's data layer so every screen shares the cache, limiter, health
|
|
3
|
+
// registry and (when the Helius key is configured) the credit meter. Screens stay pure renderers: the
|
|
4
|
+
// context owns the loaders and tells the UI loop when to redraw.
|
|
5
|
+
import { PumpPortalClient, PUMPPORTAL_WS, WatchlistStore, PaperWallet, PaperExecutor, FastLane, WalletLinkStore, WalletBridge, KillSwitch, CapLedger, SignerClient, defaultLiveLedgerPath, defaultLinkPath, defaultPanicPath, defaultCapLedgerPath, shortPubkey, } from '../../../data/src/index.js';
|
|
6
|
+
import { SocialFeed, KolStore, socialDeps, chainSignalsFromToken, chainSignalsFromIntel, chainSignalToRaw, RSS_FEEDS, JUPITER_HOSTS } from '../../../data/src/index.js';
|
|
7
|
+
import { XSource, XApi, XOAuth, XTokenStore, XSpendMeter } from '../../../data/src/index.js';
|
|
8
|
+
import { TokenLive, INTERVALS } from "./token.js";
|
|
9
|
+
import { NewPairsLive } from "./newpairs.js";
|
|
10
|
+
import { WatchlistLive } from "./watchlist.js";
|
|
11
|
+
import { TradeTicketLive, PositionsLive, LivePositions, CombinedPositions, POSITIONS_REFRESH_MS } from "./trade.js";
|
|
12
|
+
import { IntelLive } from "./intel.js";
|
|
13
|
+
import { CopyLive } from "./copy.js";
|
|
14
|
+
export { TokenLive, INTERVALS, panelCaption, emptyView } from "./token.js";
|
|
15
|
+
export { NewPairsLive, latencyStats, percentile, RECENT_POLL_MS, NEW_TOKENS_POLL_MS, ENRICH_POLL_MS } from "./newpairs.js";
|
|
16
|
+
export { WatchlistLive, WATCH_REFRESH_MS } from "./watchlist.js";
|
|
17
|
+
export { TradeTicketLive, PositionsLive, LivePositions, CombinedPositions, POSITIONS_REFRESH_MS } from "./trade.js";
|
|
18
|
+
export { IntelLive, popupBubbleVM, unavailableText, INTEL_AUTOSCAN_DELAY_MS } from "./intel.js";
|
|
19
|
+
export { renderTokenLive } from "./screens/token-live.js";
|
|
20
|
+
export { renderNewPairsLive } from "./screens/newpairs-live.js";
|
|
21
|
+
export { renderWatchlistLive } from "./screens/watchlist-live.js";
|
|
22
|
+
export class LiveContext {
|
|
23
|
+
dl;
|
|
24
|
+
mode;
|
|
25
|
+
rpc;
|
|
26
|
+
credits;
|
|
27
|
+
newpairs;
|
|
28
|
+
watch;
|
|
29
|
+
/** PAPER trading (task-1310): the simulated wallet, its executor and the two screens' bindings. */
|
|
30
|
+
wallet;
|
|
31
|
+
/** The linked (non-custodial) wallet pubkey, or null. Shown in the status bar (T1). */
|
|
32
|
+
linkedWallet = null;
|
|
33
|
+
executor;
|
|
34
|
+
positions;
|
|
35
|
+
/** LIVE positions from the signer's ledger file (read-only); null when live trading is off for this run. */
|
|
36
|
+
livePositions;
|
|
37
|
+
/** Paper + live behind the task-1323 PositionSource (token screen row, popup chart). */
|
|
38
|
+
positionSource;
|
|
39
|
+
/** The signer process handle once started (lazily, on the first LIVE action). Never respawned. */
|
|
40
|
+
signer = null;
|
|
41
|
+
signerFailed = null;
|
|
42
|
+
trade;
|
|
43
|
+
linkStore;
|
|
44
|
+
ticket = null;
|
|
45
|
+
/** Fast lane (on-chain price push) for the open token + watchlist; null in replay/when no endpoints. */
|
|
46
|
+
fastLane;
|
|
47
|
+
/** task-1330 keyless social layer: venues + news + posts, and the KOL lists behind the credibility tiers. */
|
|
48
|
+
social;
|
|
49
|
+
kol;
|
|
50
|
+
/** task-1357 Login with X: the user-context poller (null in replay / when off). Status via social.xStatus(). */
|
|
51
|
+
x;
|
|
52
|
+
/** Set by the UI loop: the screener's current rows (symbol ↔ mint for news matching + squat rules). */
|
|
53
|
+
boardSource = null;
|
|
54
|
+
token = null;
|
|
55
|
+
/** task-1340 wallet intel: the holder scan per mint (light on open, deep for watched coins) behind the bubble map. */
|
|
56
|
+
intel;
|
|
57
|
+
/** task-1360 copy trading Tier 1: the follow store + wallet tracker (alerts on a followed wallet's buys/sells). */
|
|
58
|
+
copy;
|
|
59
|
+
/**
|
|
60
|
+
* task-1340 trade moments: set by the UI loop; the ticket calls it once per SETTLED outcome (paper fill, live
|
|
61
|
+
* fill, refusal, failure) and never for a quote, plan or in-flight send. Effects + sound hang off this only.
|
|
62
|
+
*/
|
|
63
|
+
onSettled = () => { };
|
|
64
|
+
/**
|
|
65
|
+
* History recorder (task-1329): attached by main.ts in live mode when enabled; closed with the context.
|
|
66
|
+
* Typed structurally so this package does not import @dexterm/recorder (the CLI package owns the wiring).
|
|
67
|
+
*/
|
|
68
|
+
recorder = null;
|
|
69
|
+
/** Transient one-liner for screens that have no notice slot of their own; cleared on the next key. */
|
|
70
|
+
notice = null;
|
|
71
|
+
/** Set by the UI loop: called whenever a binding changed something worth drawing. */
|
|
72
|
+
onChange = () => { };
|
|
73
|
+
client;
|
|
74
|
+
stream;
|
|
75
|
+
watchStore;
|
|
76
|
+
now;
|
|
77
|
+
interval;
|
|
78
|
+
started = false;
|
|
79
|
+
fastLaneStarted = false;
|
|
80
|
+
closed = false;
|
|
81
|
+
/** task-1401: true once close() ran (an async coin-link resolution must not open a token after quit). */
|
|
82
|
+
get isClosed() { return this.closed; }
|
|
83
|
+
/** Latest SOL/USD, fed from the screener feed each refresh; the fast lane turns on-chain SOL into USD. */
|
|
84
|
+
solUsd = null;
|
|
85
|
+
lastSolFetch = 0;
|
|
86
|
+
onLog;
|
|
87
|
+
lastFastLogAt = 0;
|
|
88
|
+
lastFastLog = '';
|
|
89
|
+
constructor(dl, opts) {
|
|
90
|
+
this.dl = dl;
|
|
91
|
+
this.mode = opts.mode;
|
|
92
|
+
this.rpc = opts.rpc ?? { provider: 'public', basis: 'public mainnet (no key)' };
|
|
93
|
+
this.credits = dl.credits;
|
|
94
|
+
this.now = opts.now ?? (() => Date.now());
|
|
95
|
+
this.interval = opts.interval ?? '1h';
|
|
96
|
+
const emit = (reason) => { if (!this.closed)
|
|
97
|
+
this.onChange(reason); };
|
|
98
|
+
this.newpairs = new NewPairsLive(dl, { now: this.now, onChange: (r) => emit(`newpairs:${r}`), polls: opts.polls });
|
|
99
|
+
let record;
|
|
100
|
+
if (opts.record) {
|
|
101
|
+
record = { url: PUMPPORTAL_WS, startedAt: new Date(this.now()).toISOString(), sent: [], messages: [] };
|
|
102
|
+
opts.record.streams.push(record);
|
|
103
|
+
}
|
|
104
|
+
this.stream = opts.replay?.streams[0] ?? null;
|
|
105
|
+
this.client = new PumpPortalClient({
|
|
106
|
+
health: dl.health,
|
|
107
|
+
clock: dl.clock,
|
|
108
|
+
record,
|
|
109
|
+
ws: opts.mode === 'replay' ? () => { throw new Error('replay mode never connects'); } : opts.ws,
|
|
110
|
+
onEvent: (ev) => this.newpairs.handleEvent(ev),
|
|
111
|
+
onStatus: () => emit('newpairs:status'),
|
|
112
|
+
});
|
|
113
|
+
this.newpairs.attach(this.client, opts.mode);
|
|
114
|
+
this.watchStore = new WatchlistStore({ path: opts.dbPath, clock: dl.clock });
|
|
115
|
+
this.watch = new WatchlistLive(dl, this.watchStore, { now: this.now, onChange: () => emit('watch') });
|
|
116
|
+
// Fast lane: live-only, needs at least one WS endpoint. Price USD comes from the SOL/USD this
|
|
117
|
+
// context is fed each refresh. A price push just re-renders (coalesced; calm mode skips it, §3.9).
|
|
118
|
+
this.fastLane = opts.mode === 'live' && opts.fastEndpoints && opts.fastEndpoints.length > 0
|
|
119
|
+
? new FastLane({
|
|
120
|
+
rpcPool: dl.rpcPool,
|
|
121
|
+
health: dl.health,
|
|
122
|
+
clock: dl.clock,
|
|
123
|
+
credits: dl.credits,
|
|
124
|
+
endpoints: opts.fastEndpoints,
|
|
125
|
+
solUsd: () => this.solUsd,
|
|
126
|
+
ws: opts.ws,
|
|
127
|
+
onPrice: (_p) => emit('fastprice'),
|
|
128
|
+
onStatus: () => { emit('fastlane:status'); this.logFast(); },
|
|
129
|
+
})
|
|
130
|
+
: null;
|
|
131
|
+
this.onLog = opts.onLog;
|
|
132
|
+
// task-1330: KOL lists persist in the shared cache DB; the social feed runs the keyless venues + RSS in live
|
|
133
|
+
// mode, and in replay mode only when the recording actually carries those routes (else they stay off and
|
|
134
|
+
// the board says so — never a fixture miss on screen).
|
|
135
|
+
this.kol = new KolStore({ cache: dl.cache, clock: dl.clock, allowedSigners: opts.allowedSigners ?? null });
|
|
136
|
+
const deps = socialDeps(dl);
|
|
137
|
+
const has = (url) => !!opts.replay?.find({ method: 'GET', url });
|
|
138
|
+
const venues = opts.mode === 'live' || has(`${JUPITER_HOSTS[0]}/tokens/v2/toptrending/1h`) ? deps.venues : null;
|
|
139
|
+
const news = opts.mode === 'live' || has(RSS_FEEDS[0].url) ? deps.news : null;
|
|
140
|
+
this.social = new SocialFeed({ clock: dl.clock, now: this.now, kol: this.kol, venues, news, board: () => this.boardSource?.() ?? [], onChange: (r) => emit(r) });
|
|
141
|
+
// task-1357: X reads only through the user's own login. The poller exists in live mode; it stays `logged-out`
|
|
142
|
+
// (and costs nothing) until ~/.dexterm/x/tokens.json exists, and degrades visibly on 401/429/403/budget.
|
|
143
|
+
if (opts.mode === 'live' && !opts.x?.off) {
|
|
144
|
+
const env = opts.x?.env ?? process.env;
|
|
145
|
+
const store = opts.x?.store ?? new XTokenStore({ env });
|
|
146
|
+
const oauth = new XOAuth({ store, endpoints: opts.x?.endpoints, transport: opts.x?.transport, now: this.now });
|
|
147
|
+
const spend = new XSpendMeter({ cache: dl.cache, now: this.now, env });
|
|
148
|
+
const api = new XApi({ oauth, endpoints: opts.x?.endpoints, transport: opts.x?.transport, limiter: dl.limiter, health: dl.health, cache: dl.cache, spend, clock: dl.clock, env, onRequest: (r) => this.onLog?.(` x-api ${r.cached ? 'hit' : r.status === null ? 'ERR' : String(r.status).padStart(3)} ${String(r.latencyMs).padStart(5)}ms ${r.endpoint}`) });
|
|
149
|
+
this.x = new XSource({ api, store, kol: this.kol, now: this.now, board: () => this.boardSource?.() ?? [], tokenPollMs: opts.x?.tokenPollMs, kolPollMs: opts.x?.kolPollMs, onChange: (r) => emit(r), onLog: (l) => this.onLog?.(` ${l}`) });
|
|
150
|
+
this.social.attachX(this.x);
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
this.x = null;
|
|
154
|
+
}
|
|
155
|
+
// PAPER wallet: same DB file as the cache/watchlist (one --db controls everything). Simulated only.
|
|
156
|
+
this.wallet = new PaperWallet({ path: opts.dbPath, clock: dl.clock });
|
|
157
|
+
// T1: the linked wallet (pubkey only) for the status bar. Re-read by /wallet link|unlink.
|
|
158
|
+
this.trade = opts.trade ?? null;
|
|
159
|
+
this.linkStore = new WalletLinkStore(this.trade?.paths?.link ?? defaultLinkPath());
|
|
160
|
+
this.linkedWallet = this.linkStore.get();
|
|
161
|
+
this.executor = new PaperExecutor(this.wallet, { clock: dl.clock });
|
|
162
|
+
this.positions = new PositionsLive(dl, this.wallet, { now: this.now, onChange: () => emit('positions') });
|
|
163
|
+
// task-1328: live positions read the signer's ledger file (read-only). Present whenever live trading
|
|
164
|
+
// is configured for the run, so a position booked by a previous run shows even before the signer starts.
|
|
165
|
+
this.livePositions = this.trade
|
|
166
|
+
? new LivePositions(this.trade.paths?.liveLedger ?? defaultLiveLedgerPath(), { now: this.now, mark: (m) => this.positions.markOf(m), solUsd: () => this.positions.solUsd() ?? this.solUsd })
|
|
167
|
+
: null;
|
|
168
|
+
this.positionSource = new CombinedPositions(this.positions, this.livePositions);
|
|
169
|
+
this.intel = new IntelLive(dl, { now: this.now, onChange: () => { this.syncIntelRows(); emit('intel'); }, isWatched: (mint) => this.watch.has(mint) });
|
|
170
|
+
// task-1360: followed wallets are polled only in a real live run (replay never spends credits); the store is always readable.
|
|
171
|
+
this.copy = new CopyLive(opts.mode === 'live' ? dl : null, { onChange: (r) => emit(r), solUsd: () => this.solUsd, env: opts.copy?.env, followsPath: opts.copy?.followsPath, history: opts.copy?.history, pollMs: opts.copy?.pollMs });
|
|
172
|
+
}
|
|
173
|
+
/** Open a trade ticket (PAPER by default; `L` flips it LIVE when a wallet is linked). Replaces any open ticket. */
|
|
174
|
+
openTicket(seed, side, mode = 'paper') {
|
|
175
|
+
const live = this.trade ? {
|
|
176
|
+
signer: () => this.ensureSigner(),
|
|
177
|
+
linked: () => this.linkedWallet,
|
|
178
|
+
onFill: () => { this.livePositions?.invalidate(); this.onChange('positions'); },
|
|
179
|
+
} : undefined;
|
|
180
|
+
const t = new TradeTicketLive(this.dl, this.wallet, this.executor, { mint: seed.mint, symbol: seed.symbol, decimals: seed.decimals, side, mode: 'paper' }, {
|
|
181
|
+
now: this.now, onChange: () => this.onChange('ticket'), live, onSettled: (tx) => this.onSettled(tx),
|
|
182
|
+
livePositionRaw: (mint) => { const p = this.livePositions?.positions().find((x) => x.mint === mint); return p?.tokensRaw ?? 0n; },
|
|
183
|
+
});
|
|
184
|
+
this.ticket = t;
|
|
185
|
+
if (mode === 'live')
|
|
186
|
+
t.setMode('live');
|
|
187
|
+
return t;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* The signer process (task-1328), started on first use with the run's caps argv. A signer that
|
|
191
|
+
* failed to start or died is never respawned: LIVE stays off until dexterm restarts (fail closed).
|
|
192
|
+
*/
|
|
193
|
+
ensureSigner() {
|
|
194
|
+
if (!this.trade || this.signerFailed)
|
|
195
|
+
return this.signer;
|
|
196
|
+
if (!this.signer) {
|
|
197
|
+
try {
|
|
198
|
+
this.signer = this.trade.createSigner ? this.trade.createSigner() : new SignerClient({ argv: this.trade.signerArgv ?? [], log: this.onLog ? (l) => this.onLog?.(` signer ${l}\n`) : undefined });
|
|
199
|
+
}
|
|
200
|
+
catch (e) {
|
|
201
|
+
this.signerFailed = e instanceof Error ? e.message : String(e);
|
|
202
|
+
return null;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return this.signer;
|
|
206
|
+
}
|
|
207
|
+
/** `/wallet …` typed in the app (task-1328). Returns the line to show. */
|
|
208
|
+
async walletCommand(cmd) {
|
|
209
|
+
const paths = this.trade?.paths ?? {};
|
|
210
|
+
switch (cmd) {
|
|
211
|
+
case 'status': {
|
|
212
|
+
const linked = this.linkedWallet ? `linked: ${shortPubkey(this.linkedWallet.publicKey)}` : 'no wallet linked (/wallet link)';
|
|
213
|
+
const ks = new KillSwitch(paths.panic ?? defaultPanicPath()).engaged();
|
|
214
|
+
const s = this.signer?.alive ? await this.signer.status().catch(() => null) : null;
|
|
215
|
+
if (s) {
|
|
216
|
+
const caps = s.caps;
|
|
217
|
+
return `${linked} · signer ${s.network.toUpperCase()} (${s.rpcHost}) · $${caps.perTradeUsd}/trade $${caps.dailyUsd}/day · spent $${s.spentTodayUsd.toFixed(2)}${s.panic || s.ledgerLocked ? ' · ⛔ PANICKED' : ''}`;
|
|
218
|
+
}
|
|
219
|
+
return `${linked} · signer ${this.signer ? (this.signerFailed ?? 'stopped') : 'not started (starts on the first LIVE plan)'}${ks ? ' · ⛔ PANICKED' : ''}${this.trade ? '' : ' · live trading off in this run'}`;
|
|
220
|
+
}
|
|
221
|
+
case 'link': {
|
|
222
|
+
if (!this.trade)
|
|
223
|
+
return 'live trading is off in this run';
|
|
224
|
+
const bridge = new WalletBridge(this.trade.open ? { open: this.trade.open } : {});
|
|
225
|
+
try {
|
|
226
|
+
const res = await bridge.link();
|
|
227
|
+
const rec = this.linkStore.set(res.publicKey, { network: 'devnet' });
|
|
228
|
+
this.linkedWallet = rec;
|
|
229
|
+
this.onChange('wallet');
|
|
230
|
+
return `linked: ${shortPubkey(rec.publicKey)} (public key only) · L on a ticket for LIVE`;
|
|
231
|
+
}
|
|
232
|
+
catch (e) {
|
|
233
|
+
return `wallet link failed: ${e instanceof Error ? e.message : String(e)}`;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
case 'unlink': {
|
|
237
|
+
const had = this.linkStore.clear();
|
|
238
|
+
this.linkedWallet = null;
|
|
239
|
+
if (this.ticket?.ticket.mode === 'live')
|
|
240
|
+
this.ticket.setMode('paper');
|
|
241
|
+
this.onChange('wallet');
|
|
242
|
+
return had ? 'unlinked' : 'no wallet was linked';
|
|
243
|
+
}
|
|
244
|
+
case 'panic': {
|
|
245
|
+
// Local first (the kill-switch FILE every signer re-reads + the shared ledger lock), then the signer.
|
|
246
|
+
const ks = new KillSwitch(paths.panic ?? defaultPanicPath());
|
|
247
|
+
ks.engage('panic from dexterm UI', this.now());
|
|
248
|
+
try {
|
|
249
|
+
const l = new CapLedger({ path: paths.capLedger ?? defaultCapLedgerPath(), clock: this.dl.clock });
|
|
250
|
+
try {
|
|
251
|
+
l.lock('panic from dexterm UI', this.now());
|
|
252
|
+
}
|
|
253
|
+
finally {
|
|
254
|
+
l.close();
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
catch { /* the file alone disables trading */ }
|
|
258
|
+
if (this.signer?.alive)
|
|
259
|
+
await this.signer.panic('panic from dexterm UI').catch(() => { });
|
|
260
|
+
if (this.ticket?.ticket.mode === 'live') {
|
|
261
|
+
this.ticket.ticket.phase = 'refused';
|
|
262
|
+
this.ticket.ticket.message = '⛔ PANIC — live signing disabled';
|
|
263
|
+
}
|
|
264
|
+
this.onChange('wallet');
|
|
265
|
+
return '⛔ PANIC: live signing disabled everywhere · re-enable only from a shell: dexterm wallet resume';
|
|
266
|
+
}
|
|
267
|
+
case 'probe': {
|
|
268
|
+
if (!this.trade)
|
|
269
|
+
return 'live trading is off in this run';
|
|
270
|
+
const t = this.openTicket({ mint: this.WSOL, symbol: 'SOL', decimals: 9 }, 'buy');
|
|
271
|
+
const why = t.startProbe();
|
|
272
|
+
return why ?? 'devnet probe: review the plan, then Y to sign the wrap-and-unwrap in Phantom (fees only)';
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return '';
|
|
276
|
+
}
|
|
277
|
+
/** Throttled fast-lane status line for --verbose (so measure.py can report the subscription count). */
|
|
278
|
+
logFast() {
|
|
279
|
+
if (!this.onLog || !this.fastLane)
|
|
280
|
+
return;
|
|
281
|
+
const s = this.fastLane.status();
|
|
282
|
+
const line = ` fastlane subs=${s.subscriptions} tracked=${s.tracked} live=${s.live} state=${s.wsState} ep=${s.endpoint}${s.keyed ? ' (keyed)' : ''}`;
|
|
283
|
+
const now = this.now();
|
|
284
|
+
if (line === this.lastFastLog && now - this.lastFastLogAt < 15_000)
|
|
285
|
+
return; // only on change or every 15 s
|
|
286
|
+
this.lastFastLog = line;
|
|
287
|
+
this.lastFastLogAt = now;
|
|
288
|
+
this.onLog(`${line}\n`);
|
|
289
|
+
}
|
|
290
|
+
/** Feed the latest SOL/USD to the new-pairs mcap math and the fast lane's USD conversion. */
|
|
291
|
+
setSolPrice(price) {
|
|
292
|
+
this.newpairs.setSolPrice(price);
|
|
293
|
+
if (typeof price === 'number' && Number.isFinite(price)) {
|
|
294
|
+
this.solUsd = price;
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
// The screener pool need not carry wrapped SOL (e.g. the trench preset hides it), so the fast lane
|
|
298
|
+
// has no USD rate. Fetch SOL/USD ourselves, keyless and cached, at most ~1/min (SPEC §3.9, task-1312).
|
|
299
|
+
if (this.fastLane)
|
|
300
|
+
void this.ensureSolUsd();
|
|
301
|
+
}
|
|
302
|
+
WSOL = 'So11111111111111111111111111111111111111112';
|
|
303
|
+
async ensureSolUsd() {
|
|
304
|
+
const now = this.now();
|
|
305
|
+
if (this.solUsd !== null && now - this.lastSolFetch < 60_000)
|
|
306
|
+
return;
|
|
307
|
+
if (now - this.lastSolFetch < 15_000)
|
|
308
|
+
return; // debounce
|
|
309
|
+
this.lastSolFetch = now;
|
|
310
|
+
try {
|
|
311
|
+
const p = (await this.dl.jupiter.price([this.WSOL])).get(this.WSOL)?.usdPrice;
|
|
312
|
+
if (typeof p === 'number' && Number.isFinite(p) && !this.closed) {
|
|
313
|
+
this.solUsd = p;
|
|
314
|
+
this.onChange('fastprice');
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
catch { /* keep the last value */ }
|
|
318
|
+
}
|
|
319
|
+
/** The fast set = the open token first, then the watchlist (the fast lane caps and drops the rest). */
|
|
320
|
+
syncFastSet() {
|
|
321
|
+
if (!this.fastLane)
|
|
322
|
+
return;
|
|
323
|
+
const mints = [];
|
|
324
|
+
if (this.token)
|
|
325
|
+
mints.push(this.token.mint);
|
|
326
|
+
for (const e of this.watchStore.list())
|
|
327
|
+
if (!mints.includes(e.mint))
|
|
328
|
+
mints.push(e.mint);
|
|
329
|
+
this.fastLane.setTracked(mints);
|
|
330
|
+
}
|
|
331
|
+
/** Honest per-row/panel badge for a mint: LIVE when the fast lane is actually streaming it, else POLL. */
|
|
332
|
+
badgeFor(mint) {
|
|
333
|
+
return this.fastLane?.badgeFor(mint) ?? 'POLL';
|
|
334
|
+
}
|
|
335
|
+
laneFor(mint) {
|
|
336
|
+
return this.fastLane?.laneFor(mint) ?? 'slow';
|
|
337
|
+
}
|
|
338
|
+
/** Latest fast-lane USD price for a mint (used in place of the polled price while LIVE), or null. */
|
|
339
|
+
livePrice(mint) {
|
|
340
|
+
return this.fastLane?.priceUsd(mint) ?? null;
|
|
341
|
+
}
|
|
342
|
+
/** Start the push feed (live) or replay the recorded stream (replay). Idempotent. */
|
|
343
|
+
startFeed(speed = 0) {
|
|
344
|
+
if (this.started)
|
|
345
|
+
return Promise.resolve();
|
|
346
|
+
this.started = true;
|
|
347
|
+
if (this.mode === 'replay') {
|
|
348
|
+
if (!this.stream)
|
|
349
|
+
return Promise.resolve();
|
|
350
|
+
return this.newpairs.replay(this.stream, speed).then(() => undefined);
|
|
351
|
+
}
|
|
352
|
+
this.newpairs.start();
|
|
353
|
+
this.startFastLane();
|
|
354
|
+
return Promise.resolve();
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Start just the on-chain fast lane (open token + watchlist real-time price). Idempotent and
|
|
358
|
+
* live-only. Decoupled from the new-pairs PumpPortal stream (task-1319): the fast lane must run for
|
|
359
|
+
* `--preset trending` and `--mint` launches and on the token screen, not only the live-stream
|
|
360
|
+
* presets (trench/new/all). It is push-only and subscribes to nothing until a token or watchlist
|
|
361
|
+
* exists, so starting it early costs one idle WS and no HTTP.
|
|
362
|
+
*/
|
|
363
|
+
startFastLane() {
|
|
364
|
+
if (this.mode !== 'live' || !this.fastLane || this.fastLaneStarted)
|
|
365
|
+
return;
|
|
366
|
+
this.fastLaneStarted = true;
|
|
367
|
+
this.fastLane.start();
|
|
368
|
+
this.syncFastSet();
|
|
369
|
+
}
|
|
370
|
+
get feedStarted() {
|
|
371
|
+
return this.started;
|
|
372
|
+
}
|
|
373
|
+
/** True once the on-chain fast lane has been started (independent of the push stream). */
|
|
374
|
+
get fastLaneRunning() {
|
|
375
|
+
return this.fastLaneStarted;
|
|
376
|
+
}
|
|
377
|
+
/** Open a token: a fresh loader, first load kicked off; the view is readable immediately (row fields). */
|
|
378
|
+
openToken(row) {
|
|
379
|
+
const t = new TokenLive(this.dl, row, { interval: this.token?.view.interval ?? this.interval, now: this.now, onChange: () => { this.syncChainRows(t); this.onChange('token'); } });
|
|
380
|
+
this.token = t;
|
|
381
|
+
this.syncFastSet(); // promote the opened token to the fast lane (slow→fast, no seam)
|
|
382
|
+
this.x?.setFocus({ mint: row.mint, symbol: row.symbol }); // task-1357: the open token's X search (60 s, cached 15 min)
|
|
383
|
+
void t.load();
|
|
384
|
+
// task-1340: a light wallet-intel scan follows the open after a short delay (flipping through tokens spends nothing)
|
|
385
|
+
if (this.mode === 'live')
|
|
386
|
+
this.intel.autoscanLater({ mint: row.mint, symbol: row.symbol, name: row.name, holderCount: row.holders ?? null });
|
|
387
|
+
return t;
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* task-1330: rule-derived on-chain rows for the open token (labelled holders, tracked-wallet buys, large
|
|
391
|
+
* trades) become `platform: 'chain'` posts in the social feed. Idempotent per signal id; cheap (≤ 12 rows).
|
|
392
|
+
*/
|
|
393
|
+
syncChainRows(t) {
|
|
394
|
+
if (this.closed)
|
|
395
|
+
return;
|
|
396
|
+
const v = t.view;
|
|
397
|
+
if (!v.holdersTop.length && !v.trades.length)
|
|
398
|
+
return;
|
|
399
|
+
const kolWallets = new Set();
|
|
400
|
+
for (const l of this.kol.all())
|
|
401
|
+
if (l.enabled)
|
|
402
|
+
for (const w of l.wallets)
|
|
403
|
+
kolWallets.add(w.toLowerCase());
|
|
404
|
+
const now = this.now();
|
|
405
|
+
const sigs = chainSignalsFromToken({ mint: v.mint, holders: v.holdersTop.map((h) => ({ address: h.address, pct: h.pct, label: h.label })), trades: v.trades, kolWallets, now });
|
|
406
|
+
if (sigs.length)
|
|
407
|
+
this.social.ingest(sigs.map((s) => chainSignalToRaw(s, now)));
|
|
408
|
+
}
|
|
409
|
+
/**
|
|
410
|
+
* task-1359: a settled wallet-intel scan of the open token becomes rule-written `platform: 'chain'` rows in the
|
|
411
|
+
* SOCIAL panel: its linked clusters (R1 funder / R2 bundle / R3 transfer / R4 dev-linked) and the launch-window
|
|
412
|
+
* snipers. One id per scan (the scan's fetch time), so a cached re-read never duplicates a row.
|
|
413
|
+
*/
|
|
414
|
+
syncIntelRows() {
|
|
415
|
+
if (this.closed || !this.token)
|
|
416
|
+
return;
|
|
417
|
+
const mint = this.token.view.mint;
|
|
418
|
+
const r = this.intel.entry(mint)?.result;
|
|
419
|
+
if (!r || r.state !== 'ok')
|
|
420
|
+
return;
|
|
421
|
+
const I = r.analysis.insights;
|
|
422
|
+
const sigs = chainSignalsFromIntel({ mint, clusters: r.analysis.clusters, snipers: I.coverage.launchTxs > 0 ? I.snipers : null, t: r.fetchedAt });
|
|
423
|
+
if (sigs.length)
|
|
424
|
+
this.social.ingest(sigs.map((s) => chainSignalToRaw(s, this.now())));
|
|
425
|
+
}
|
|
426
|
+
/** The token screen's `1`..`6` keys. */
|
|
427
|
+
setTimeframe(n) {
|
|
428
|
+
const iv = INTERVALS[n - 1];
|
|
429
|
+
if (iv && this.token)
|
|
430
|
+
void this.token.setInterval(iv);
|
|
431
|
+
}
|
|
432
|
+
/** Candidate for the watchlist from whatever row the user is on. */
|
|
433
|
+
static candidate(r) {
|
|
434
|
+
return { mint: r.mint, symbol: r.symbol, name: r.name, launchpad: r.launchpad, price: r.price ?? null, liq: 'liq' in r ? r.liq : null, mcap: r.mcap ?? null };
|
|
435
|
+
}
|
|
436
|
+
/**
|
|
437
|
+
* AI scan mode's analyst meter (task-1324): analyst turns the scan started in the rolling hour vs its
|
|
438
|
+
* cap, and for the locked coin. Set by the UI loop on every scan tick while the scan is on; null = off.
|
|
439
|
+
*/
|
|
440
|
+
scanMeter = null;
|
|
441
|
+
/** `ai 2/8 per h · coin 1/4` while the scan is on, else null. */
|
|
442
|
+
scanMeterLabel() {
|
|
443
|
+
const m = this.scanMeter;
|
|
444
|
+
if (!m)
|
|
445
|
+
return null;
|
|
446
|
+
return `ai ${m.hour}/${m.hourCap} per h${m.locked ? ` · coin ${m.coin}/${m.coinCap}` : ''}`;
|
|
447
|
+
}
|
|
448
|
+
/**
|
|
449
|
+
* The header's meter status (task-1324): the scan indicator + its analyst meter alongside the Helius
|
|
450
|
+
* credit meter. Without a running scan this is exactly creditsStatus().
|
|
451
|
+
*/
|
|
452
|
+
meterStatus(scanIndicator) {
|
|
453
|
+
const credits = this.creditsStatus();
|
|
454
|
+
const ai = this.scanMeterLabel();
|
|
455
|
+
if (!ai)
|
|
456
|
+
return credits;
|
|
457
|
+
return [scanIndicator, ai, credits].filter((x) => !!x).join(' · ');
|
|
458
|
+
}
|
|
459
|
+
/** Header status fragments: credits warning first, then whatever the screen's feed says. */
|
|
460
|
+
creditsStatus() {
|
|
461
|
+
const s = this.credits?.status();
|
|
462
|
+
if (!s)
|
|
463
|
+
return undefined;
|
|
464
|
+
if (s.level === 'degraded')
|
|
465
|
+
return s.runCapHit ? '◐ helius run cap hit · keyless' : `◐ helius credits ${Math.round(s.dayPct * 100)}% · keyless`;
|
|
466
|
+
if (s.level === 'warn')
|
|
467
|
+
return `◐ helius credits ${Math.round(s.dayPct * 100)}%`;
|
|
468
|
+
return undefined;
|
|
469
|
+
}
|
|
470
|
+
close() {
|
|
471
|
+
if (this.closed)
|
|
472
|
+
return;
|
|
473
|
+
this.closed = true;
|
|
474
|
+
try {
|
|
475
|
+
this.client.stop();
|
|
476
|
+
}
|
|
477
|
+
catch { /* ignore */ }
|
|
478
|
+
try {
|
|
479
|
+
this.fastLane?.stop();
|
|
480
|
+
}
|
|
481
|
+
catch { /* ignore */ }
|
|
482
|
+
try {
|
|
483
|
+
this.watchStore.close();
|
|
484
|
+
}
|
|
485
|
+
catch { /* ignore */ }
|
|
486
|
+
try {
|
|
487
|
+
this.wallet.close();
|
|
488
|
+
}
|
|
489
|
+
catch { /* ignore */ }
|
|
490
|
+
try {
|
|
491
|
+
this.recorder?.close();
|
|
492
|
+
}
|
|
493
|
+
catch { /* ignore */ }
|
|
494
|
+
try {
|
|
495
|
+
this.social.close();
|
|
496
|
+
}
|
|
497
|
+
catch { /* ignore */ }
|
|
498
|
+
try {
|
|
499
|
+
this.signer?.close();
|
|
500
|
+
}
|
|
501
|
+
catch { /* ignore */ }
|
|
502
|
+
try {
|
|
503
|
+
this.intel.close();
|
|
504
|
+
}
|
|
505
|
+
catch { /* ignore */ }
|
|
506
|
+
try {
|
|
507
|
+
this.copy.stop();
|
|
508
|
+
}
|
|
509
|
+
catch { /* ignore */ }
|
|
510
|
+
}
|
|
511
|
+
}
|