dexterm-cli 0.1.5 → 0.1.7
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/dist/packages/agents/src/index.js +2 -0
- package/dist/packages/agents/src/schema.js +22 -1
- package/dist/packages/agents/src/spectator.js +54 -0
- package/dist/packages/agents/src/story.js +532 -0
- package/dist/packages/agents/src/tiers.js +28 -2
- package/dist/packages/agents/src/tools.js +31 -2
- package/dist/packages/autotrade/assets/exit-profile.schema.json +492 -0
- package/dist/packages/autotrade/assets/profiles/moonbag.json +46 -0
- package/dist/packages/autotrade/assets/profiles/runner.json +88 -0
- package/dist/packages/autotrade/assets/profiles/scalp.json +88 -0
- package/dist/packages/autotrade/assets/profiles/swing.json +88 -0
- package/dist/packages/autotrade/assets/strategies/moonbag.json +101 -0
- package/dist/packages/autotrade/assets/strategies/runner.json +101 -0
- package/dist/packages/autotrade/assets/strategies/sample-dip-ladder.json +188 -0
- package/dist/packages/autotrade/assets/strategies/scalp.json +98 -0
- package/dist/packages/autotrade/assets/strategies/swing.json +97 -0
- package/dist/packages/autotrade/assets/strategies/yolo.json +157 -0
- package/dist/packages/autotrade/assets/tapes/yolo-rehearsal.json +1 -0
- package/dist/packages/autotrade/src/account.js +74 -0
- package/dist/packages/autotrade/src/backtest.js +357 -0
- package/dist/packages/autotrade/src/basis-text.js +32 -0
- package/dist/packages/autotrade/src/chat/approvals.js +484 -0
- package/dist/packages/autotrade/src/chat/audit.js +140 -0
- package/dist/packages/autotrade/src/chat/config.js +93 -0
- package/dist/packages/autotrade/src/chat/connector.js +24 -0
- package/dist/packages/autotrade/src/chat/control.js +103 -0
- package/dist/packages/autotrade/src/chat/fake.js +100 -0
- package/dist/packages/autotrade/src/chat/format.js +71 -0
- package/dist/packages/autotrade/src/chat/hub.js +187 -0
- package/dist/packages/autotrade/src/chat/index.js +18 -0
- package/dist/packages/autotrade/src/chat/notify.js +292 -0
- package/dist/packages/autotrade/src/chat/pairing.js +46 -0
- package/dist/packages/autotrade/src/chat/redact.js +48 -0
- package/dist/packages/autotrade/src/chat/secrets.js +99 -0
- package/dist/packages/autotrade/src/chat/service.js +248 -0
- package/dist/packages/autotrade/src/chat/telegram.js +290 -0
- package/dist/packages/autotrade/src/desk-executor.js +188 -0
- package/dist/packages/autotrade/src/engine.js +387 -0
- package/dist/packages/autotrade/src/execution-port.js +97 -0
- package/dist/packages/autotrade/src/fleet-config.js +169 -0
- package/dist/packages/autotrade/src/fleet-control.js +276 -0
- package/dist/packages/autotrade/src/fleet.js +639 -0
- package/dist/packages/autotrade/src/index.js +53 -0
- package/dist/packages/autotrade/src/ledger.js +108 -0
- package/dist/packages/autotrade/src/live-source.js +182 -0
- package/dist/packages/autotrade/src/monitor-daemon.js +715 -0
- package/dist/packages/autotrade/src/monitor.js +190 -0
- package/dist/packages/autotrade/src/ollama-sessions.js +137 -0
- package/dist/packages/autotrade/src/paper-accounts.js +72 -0
- package/dist/packages/autotrade/src/replay.js +198 -0
- package/dist/packages/autotrade/src/runner-config.js +99 -0
- package/dist/packages/autotrade/src/runner.js +872 -0
- package/dist/packages/autotrade/src/safety.js +243 -0
- package/dist/packages/autotrade/src/session.js +269 -0
- package/dist/packages/autotrade/src/sessions.js +503 -0
- package/dist/packages/autotrade/src/store.js +250 -0
- package/dist/packages/autotrade/src/strategy.js +256 -0
- package/dist/packages/autotrade/src/trade-ledger.js +241 -0
- package/dist/packages/autotrade/src/yolo.js +140 -0
- package/dist/packages/cli/assets/claude/analyst-system.md +4 -4
- package/dist/packages/cli/assets/claude/plugin/skills/REGISTRY.json +1 -1
- package/dist/packages/cli/assets/claude/plugin/skills/larp-check/SKILL.md +15 -8
- package/dist/packages/cli/assets/claude/plugin/skills/token-dossier/SKILL.md +1 -1
- package/dist/packages/cli/src/agent-cmd.js +6 -4
- package/dist/packages/cli/src/agent-spectator.js +17 -1
- package/dist/packages/cli/src/ai-cmd.js +412 -0
- package/dist/packages/cli/src/analyst/backend.js +105 -15
- package/dist/packages/cli/src/analyst/codex.js +14 -9
- package/dist/packages/cli/src/analyst/larp-gauge.js +60 -0
- package/dist/packages/cli/src/analyst/ollama.js +263 -0
- package/dist/packages/cli/src/analyst/session.js +17 -3
- package/dist/packages/cli/src/app-help-gen.js +51 -15
- package/dist/packages/cli/src/autotrade-cmd/audit.js +57 -0
- package/dist/packages/cli/src/autotrade-cmd/backtest.js +199 -0
- package/dist/packages/cli/src/autotrade-cmd/flatten.js +64 -0
- package/dist/packages/cli/src/autotrade-cmd/fleet.js +397 -0
- package/dist/packages/cli/src/autotrade-cmd/requests.js +79 -0
- package/dist/packages/cli/src/autotrade-cmd/run.js +413 -0
- package/dist/packages/cli/src/autotrade-cmd/stop.js +76 -0
- package/dist/packages/cli/src/autotrade-cmd/strategies.js +198 -0
- package/dist/packages/cli/src/autotrade-cmd/strategy-control.js +174 -0
- package/dist/packages/cli/src/autotrade-cmd/telegram-host.js +101 -0
- package/dist/packages/cli/src/autotrade-cmd.js +168 -0
- package/dist/packages/cli/src/backtest-cmd.js +13 -2
- package/dist/packages/cli/src/display.js +208 -23
- package/dist/packages/cli/src/doctor.js +62 -3
- package/dist/packages/cli/src/export.js +10 -2
- package/dist/packages/cli/src/index.js +1 -1
- package/dist/packages/cli/src/ledger-cmd.js +288 -0
- package/dist/packages/cli/src/live/chart-fills.js +46 -0
- package/dist/packages/cli/src/live/dev-history.js +31 -15
- package/dist/packages/cli/src/live/index.js +28 -90
- package/dist/packages/cli/src/live/screens/newpairs-live.js +1 -1
- package/dist/packages/cli/src/live/screens/token-live.js +48 -15
- package/dist/packages/cli/src/live/screens/watchlist-live.js +1 -1
- package/dist/packages/cli/src/live/trade.js +30 -453
- package/dist/packages/cli/src/live/watchlist.js +1 -1
- package/dist/packages/cli/src/main.js +290 -199
- package/dist/packages/cli/src/mcp-cmd.js +7 -1
- package/dist/packages/cli/src/mcp-follow.js +103 -6
- package/dist/packages/cli/src/plan-cmd.js +15 -5
- package/dist/packages/cli/src/pnl-app.js +31 -21
- package/dist/packages/cli/src/pnl-card.js +158 -21
- package/dist/packages/cli/src/popup.js +38 -6
- package/dist/packages/cli/src/record-cmd.js +141 -20
- package/dist/packages/cli/src/scan/ui.js +7 -1
- package/dist/packages/cli/src/screens/agent-hud.js +773 -0
- package/dist/packages/cli/src/screens/analyst-session.js +11 -4
- package/dist/packages/cli/src/screens/analyst.js +3 -2
- package/dist/packages/cli/src/screens/autotrade-keys.js +169 -0
- package/dist/packages/cli/src/screens/autotrade-proposals.js +123 -0
- package/dist/packages/cli/src/screens/autotrade-screen.js +725 -0
- package/dist/packages/cli/src/screens/autotrade-ui.js +640 -0
- package/dist/packages/cli/src/screens/autotrade-worker.js +89 -0
- package/dist/packages/cli/src/screens/brain.js +634 -0
- package/dist/packages/cli/src/screens/newpairs.js +1 -1
- package/dist/packages/cli/src/screens/overlay.js +5 -2
- package/dist/packages/cli/src/screens/plans.js +5 -17
- package/dist/packages/cli/src/screens/pnl-chip.js +144 -0
- package/dist/packages/cli/src/screens/positions.js +6 -28
- package/dist/packages/cli/src/screens/screener.js +1 -0
- package/dist/packages/cli/src/screens/ticket.js +38 -205
- package/dist/packages/cli/src/screens/token.js +18 -9
- package/dist/packages/cli/src/screens/trending.js +1 -1
- package/dist/packages/cli/src/state.js +88 -18
- package/dist/packages/cli/src/telegram-cmd.js +451 -0
- package/dist/packages/cli/src/trade.js +3 -128
- package/dist/packages/cli/src/version.js +1 -1
- package/dist/packages/cli/src/wallet-cmd.js +39 -340
- package/dist/packages/cli/src/wallet-command.js +8 -11
- package/dist/packages/cli/src/widgets.js +0 -12
- package/dist/packages/custom/src/config.js +20 -2
- package/dist/packages/custom/src/schema.js +41 -10
- package/dist/packages/custom/src/workspace.js +3 -3
- package/dist/packages/data/src/basis.js +191 -0
- package/dist/packages/data/src/detail.js +53 -2
- package/dist/packages/data/src/index.js +2 -14
- package/dist/packages/data/src/larp/score.js +220 -0
- package/dist/packages/data/src/larp/x-account.js +316 -0
- package/dist/packages/data/src/store.js +14 -5
- package/dist/packages/data/src/trade/agent/paper-desk.js +300 -23
- package/dist/packages/data/src/trade/agent/rendezvous.js +3 -2
- package/dist/packages/data/src/trade/bridge.js +4 -102
- package/dist/packages/data/src/trade/ledger/export.js +101 -0
- package/dist/packages/data/src/trade/ledger/file.js +135 -0
- package/dist/packages/data/src/trade/ledger/fold.js +191 -0
- package/dist/packages/data/src/trade/ledger/index.js +9 -0
- package/dist/packages/data/src/trade/ledger/schema.js +83 -0
- package/dist/packages/data/src/trade/ledger/sources.js +307 -0
- package/dist/packages/data/src/trade/ledger/stats.js +123 -0
- package/dist/packages/data/src/trade/ledger/tags.js +116 -0
- package/dist/packages/data/src/trade/ledger/view.js +51 -0
- package/dist/packages/data/src/trade/plans/engine.js +7 -0
- package/dist/packages/data/src/trade/plans/index.js +0 -1
- package/dist/packages/data/src/trade/plans/mandate.js +28 -15
- package/dist/packages/data/src/trade/plans/service.js +4 -28
- package/dist/packages/mcp/assets/kb/app-help/autotrade-chat.md +48 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-parallel.md +42 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-runner.md +35 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-stop.md +37 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-strategies.md +35 -0
- package/dist/packages/mcp/assets/kb/app-help/autotrade-telegram.md +40 -0
- package/dist/packages/mcp/assets/kb/app-help/chart-trade-markers.md +42 -0
- package/dist/packages/mcp/assets/kb/app-help/dev-history.md +1 -1
- package/dist/packages/mcp/assets/kb/app-help/larp-check.md +5 -1
- package/dist/packages/mcp/assets/kb/app-help/link-a-wallet.md +4 -10
- package/dist/packages/mcp/assets/kb/app-help/live-trading.md +38 -0
- package/dist/packages/mcp/assets/kb/app-help/live-yolo.md +34 -0
- package/dist/packages/mcp/assets/kb/app-help/order-plans.md +1 -1
- package/dist/packages/mcp/assets/kb/app-help/price-or-marketcap.md +5 -2
- package/dist/packages/mcp/assets/kb/app-help/scan-mode.md +1 -1
- package/dist/packages/mcp/assets/kb/app-help/screen-analyst.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-autotrade.md +217 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-kol.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-newpairs.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-positions.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-screener.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-token.md +6 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-trending.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/screen-watchlist.md +3 -0
- package/dist/packages/mcp/assets/kb/app-help/spectate-an-agent.md +2 -1
- package/dist/packages/mcp/assets/kb/app-help/standing-mandates.md +1 -1
- package/dist/packages/mcp/assets/kb/app-help/trade-ledger.md +54 -0
- package/dist/packages/mcp/assets/kb/app-help/use-local-model.md +38 -0
- package/dist/packages/mcp/assets/kb/docs/docs-agents-agent-paper-trading.md +7 -3
- package/dist/packages/mcp/assets/kb/docs/docs-agents-reading-your-trade-ledger.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-agents-untrusted-by-default.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-analyst-if-claude-is-missing.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-analyst-starting-a-run.md +2 -0
- package/dist/packages/mcp/assets/kb/docs/docs-analyst-use-a-local-model-instead.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-analyst-what-it-sees.md +2 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-backtests-and-their-limits.md +56 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-change-a-strategy-by-chat.md +49 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-checking-the-record-of-a-run.md +28 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-comparing-them.md +41 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-exits-and-wakes.md +76 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-how-a-stop-reaches-the-runner.md +32 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-on-the-q-screen.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-one-strategy-or-all-of-them.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-paper-accounts.md +50 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-presets.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-running-it-all-day.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-sessions-and-their-limits.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-several-strategies-at-once.md +33 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-stopping-it.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-strategies-and-presets.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-autotrade-json-file.md +48 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-heartbeat.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-run-file-and-the-heartbeat.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-runner-and-candidate-sessions.md +45 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-each-session-shows-first.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-it-costs-claude-usage-per-session.md +58 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-it-is-paper-self-directed.md +43 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-it-will-not-do.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-which-account-day-caps-and-the-usage-guard.md +44 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade-your-strategies.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-autotrade.md +22 -0
- package/dist/packages/mcp/assets/kb/docs/docs-beginners-before-any-experimental-trading.md +2 -2
- package/dist/packages/mcp/assets/kb/docs/docs-beginners.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-chart-markers.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-chart-y-axis.md +32 -0
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-environment-variables.md +4 -1
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-files-on-disk.md +1 -0
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-headless-recorder-dexterm-record.md +3 -1
- package/dist/packages/mcp/assets/kb/docs/docs-configuration-price-display-mode.md +9 -7
- package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-stage-2-the-one-key-mirror-ticket-a-proposal.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-stage-3-capped-auto-mirror-default-off-less.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-what-is-proven-what-is-not.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-copy-trading.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-data-sources-recorded-history-and-retention.md +36 -0
- package/dist/packages/mcp/assets/kb/docs/docs-data-sources-sources.md +1 -0
- package/dist/packages/mcp/assets/kb/docs/docs-getting-started-first-run.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-getting-started-install.md +3 -3
- package/dist/packages/mcp/assets/kb/docs/docs-getting-started-requirements.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-getting-started-running-the-tests.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-getting-started.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-larp-measured-accuracy.md +1 -0
- package/dist/packages/mcp/assets/kb/docs/docs-larp-the-larp-score.md +60 -0
- package/dist/packages/mcp/assets/kb/docs/docs-larp-the-verdict.md +0 -2
- package/dist/packages/mcp/assets/kb/docs/docs-larp-what-it-looks-at.md +4 -1
- package/dist/packages/mcp/assets/kb/docs/docs-larp.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-live-trading-changed-in-0-1-7.md +26 -0
- package/dist/packages/mcp/assets/kb/docs/docs-live-trading-stopping.md +28 -0
- package/dist/packages/mcp/assets/kb/docs/docs-live-trading-the-short-version.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-live-trading-using-a-trading-bot-with-dexterm.md +33 -0
- package/dist/packages/mcp/assets/kb/docs/docs-live-trading-what-dexterm-does-not-do.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-live-trading-what-dexterm-does.md +29 -0
- package/dist/packages/mcp/assets/kb/docs/docs-live-trading.md +23 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-another-machine.md +28 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-autotrade-on-a-local-model.md +29 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-check-your-model-dexterm-ai-probe.md +38 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-how-we-checked.md +27 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-models-without-tool-calling.md +32 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-pick-the-engine-globally-or-per-surface.md +43 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-restriction-profiles.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-set-it-up-in-two-minutes.md +39 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-troubleshooting.md +35 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-what-runs-on-a-local-model.md +39 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-what-stays-outside-the-model.md +36 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-which-model.md +38 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama-your-own-agent-on-the-local-model.md +28 -0
- package/dist/packages/mcp/assets/kb/docs/docs-ollama.md +28 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-letting-an-agent-paper-trade-experimental.md +3 -4
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-link-a-wallet-read-only.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-order-plans-and-standing-mandates.md +4 -13
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-panic.md +4 -7
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-paper-only-mandates.md +40 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-pnl-cards.md +7 -7
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-safety-model.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-ticket.md +3 -4
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-trade-ledger.md +42 -0
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-wallet.md +4 -5
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-trade-moments.md +4 -5
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading.md +4 -5
- package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-buy-and-sell-markers.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-market-cap-axis.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-what-it-shows.md +3 -1
- package/dist/packages/mcp/assets/kb/docs/docs-scan-the-read.md +2 -0
- package/dist/packages/mcp/assets/kb/docs/docs-screens-autotrade-paper.md +26 -0
- package/dist/packages/mcp/assets/kb/docs/docs-screens-dev-history.md +10 -7
- package/dist/packages/mcp/assets/kb/docs/docs-screens-order-plans.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-screens-token-screen.md +2 -0
- package/dist/packages/mcp/assets/kb/docs/docs-spectator-follow-over-mcp-in-the-running-terminal.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-spectator-limits.md +2 -0
- package/dist/packages/mcp/assets/kb/docs/docs-spectator-the-agent-hud-spectator-v2.md +58 -0
- package/dist/packages/mcp/assets/kb/docs/docs-spectator-the-brain-view-and-the-pnl-chip.md +46 -0
- package/dist/packages/mcp/assets/kb/docs/docs-spectator-the-three-surfaces.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-spectator.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-approve-one-tap-entries.md +50 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-control-the-commands.md +43 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-if-something-goes-wrong.md +30 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-notify-what-reaches-your-phone.md +41 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-set-it-up.md +47 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-the-record.md +26 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-what-it-is.md +33 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram-what-it-will-not-do.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-telegram.md +23 -0
- package/dist/packages/mcp/assets/kb/docs/docs-troubleshooting-common-questions.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-troubleshooting-doctor-lines.md +4 -0
- package/dist/packages/mcp/assets/kb/docs/docs-voice-linux-and-windows.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-voice.md +1 -1
- package/dist/packages/mcp/assets/kb/docs/docs-yolo-1-replay-it-on-your-own-history.md +42 -0
- package/dist/packages/mcp/assets/kb/docs/docs-yolo-2-run-it-on-paper.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-yolo-3-watch-it-and-stop-it.md +32 -0
- package/dist/packages/mcp/assets/kb/docs/docs-yolo-the-rules.md +37 -0
- package/dist/packages/mcp/assets/kb/docs/docs-yolo-what-it-is.md +34 -0
- package/dist/packages/mcp/assets/kb/docs/docs-yolo-what-it-will-not-do.md +31 -0
- package/dist/packages/mcp/assets/kb/docs/docs-yolo.md +26 -0
- package/dist/packages/mcp/assets/kb/entries/autotrade.md +38 -0
- package/dist/packages/mcp/src/app-help.js +1 -1
- package/dist/packages/mcp/src/autotrade-tools.js +944 -0
- package/dist/packages/mcp/src/backtest-requests.js +71 -0
- package/dist/packages/mcp/src/engine/config.js +159 -0
- package/dist/packages/mcp/src/engine/index.js +10 -0
- package/dist/packages/mcp/src/engine/loop.js +101 -0
- package/dist/packages/mcp/src/engine/mcp-client.js +123 -0
- package/dist/packages/mcp/src/engine/ollama.js +258 -0
- package/dist/packages/mcp/src/engine/probe.js +110 -0
- package/dist/packages/mcp/src/engine/reason.js +35 -0
- package/dist/packages/mcp/src/engine/restrictions.js +111 -0
- package/dist/packages/mcp/src/index.js +7 -1
- package/dist/packages/mcp/src/ledger-tools.js +346 -0
- package/dist/packages/mcp/src/paper-agent.js +5 -2
- package/dist/packages/mcp/src/server.js +285 -36
- package/dist/packages/mcp/src/spectator-sink.js +85 -0
- package/dist/packages/packs/src/backtest.js +3 -1
- package/dist/packages/packs/src/index.js +1 -0
- package/dist/packages/packs/src/larp-score-backtest.js +119 -0
- package/dist/packages/popup/src/pages/chart-lib.js +169 -35
- package/dist/packages/popup/src/pages/chart.css +18 -0
- package/dist/packages/popup/src/pages/chart.html +6 -1
- package/dist/packages/popup/src/pages/chart.js +136 -10
- package/dist/packages/popup/src/pages/spectator.css +45 -0
- package/dist/packages/popup/src/pages/spectator.html +1 -0
- package/dist/packages/popup/src/pages/spectator.js +69 -0
- package/dist/packages/popup/src/protocol.js +4 -0
- package/dist/packages/popup/src/server.js +9 -1
- package/dist/packages/recorder/src/dev-history.js +7 -3
- package/dist/packages/recorder/src/index.js +2 -0
- package/dist/packages/recorder/src/recorder.js +63 -6
- package/dist/packages/recorder/src/retention.js +100 -0
- package/dist/packages/recorder/src/schema.js +34 -1
- package/dist/packages/recorder/src/ticks.js +237 -0
- package/dist/packages/tui/src/canvas.js +7 -0
- package/dist/packages/tui/src/fmt.js +53 -0
- package/dist/packages/tui/src/index.js +1 -0
- package/dist/packages/tui/src/keymap.js +25 -1
- package/dist/packages/tui/src/markers.js +219 -0
- package/dist/packages/tui/src/widgets.js +158 -6
- package/package.json +2 -1
- package/dist/packages/data/src/trade/caps.js +0 -323
- package/dist/packages/data/src/trade/executor.js +0 -933
- package/dist/packages/data/src/trade/plans/executor-live.js +0 -220
- package/dist/packages/data/src/trade/rpc-exec.js +0 -229
- package/dist/packages/data/src/trade/signer/client.js +0 -197
- package/dist/packages/data/src/trade/signer/fast-wallet.js +0 -154
- package/dist/packages/data/src/trade/signer/host.js +0 -97
- package/dist/packages/data/src/trade/signer/main.js +0 -121
- package/dist/packages/data/src/trade/signer/probe-builder.js +0 -85
- package/dist/packages/data/src/trade/signer/protocol.js +0 -92
- package/dist/packages/data/src/trade/signer/service.js +0 -400
- package/dist/packages/data/src/trade/signer/sol-usd-feed.js +0 -98
- package/dist/packages/data/src/trade/sol-usd.js +0 -86
- package/dist/packages/data/src/trade/swap-build.js +0 -108
- package/dist/packages/data/src/trade/token-delta.js +0 -201
- package/dist/packages/data/vendor/solana-web3/LICENSE +0 -20
- package/dist/packages/data/vendor/solana-web3/NOTICE.md +0 -13
- package/dist/packages/data/vendor/solana-web3/index.iife.min.js +0 -20
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-a-live-ticket.md +0 -42
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-before-you-press-size-vs-caps.md +0 -34
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-devnet-signer-mainnet-token.md +0 -35
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-jupiter-rate-limits.md +0 -33
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-link-a-wallet.md +0 -32
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-live-trading-devnet-first.md +0 -30
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-mainnet.md +0 -31
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-live-fire-path-devnet-the-fast-wallet.md +0 -41
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-signer-process.md +0 -34
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-what-the-live-path-keeps.md +0 -37
- package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-your-first-live-trade.md +0 -41
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// @dexterm/autotrade — the autotrade engine (AUTOTRADE-SPEC, task-1503 AT-1). PAPER ONLY.
|
|
2
|
+
//
|
|
3
|
+
// strategy the dexterm-strategy/1 document, exit profiles 1.0.0..1.2.0, the validator, presets
|
|
4
|
+
// engine entry rules on the screener grammar, sizing, the clamp, the constant-product fill model
|
|
5
|
+
// monitor mechanical exits + wake events (no LLM)
|
|
6
|
+
// replay the recorded tape (MarketTick) read from the recorder DB or a committed fixture
|
|
7
|
+
// session the decision protocol, dossier/delta text, the stub session (types for the runner card)
|
|
8
|
+
// runner the run loop (lockstep for backtests, paced for replays, live for `autotrade run`), lock + rendezvous
|
|
9
|
+
// ledger the hash-chained run ledger, runs/<runId>.jsonl, chain verification (task-1505)
|
|
10
|
+
// sessions the user's own `claude -p` sessions, day caps + allowance guard, the mcp dossier (task-1505)
|
|
11
|
+
// live-source Store-fed MarketTicks: the screener pool every 10 s, candidate/held coins every 5 s (task-1505)
|
|
12
|
+
// runner-config / account runner.json (dexterm-runner/1) and the four Claude account kinds (task-1505)
|
|
13
|
+
// backtest the report, every-candidate mode, runner recall, held-out split + sweeps
|
|
14
|
+
// store ~/.dexterm/strategies/<id>.json CRUD + the append-only .journal.jsonl
|
|
15
|
+
// desk-executor orders through the app's paper desk (armed paper-only mandate, exit plans, quote-sized cost recovery)
|
|
16
|
+
// monitor-daemon the position monitor process: §5 exits on the desk, one wake message per tick, restart recovery
|
|
17
|
+
// safety stop / flatten / pause (the control file), the kill switch + dead-man every step, the run audit, session isolation (task-1509)
|
|
18
|
+
// fleet parallel strategies: N strategies on one feed, each with its own book, ledger, caps and budget, under global caps (task-1529)
|
|
19
|
+
// fleet-config / fleet-control autotrade.json (dexterm-autotrade/1), per-strategy control files, the fleet status + comparison table
|
|
20
|
+
// paper-accounts shared paper accounts: many strategies trading from one simulated wallet, one strategy on many (task-1538)
|
|
21
|
+
// trade-ledger the run ledgers as unified trade ledger drafts (task-1530, read-only)
|
|
22
|
+
// execution-port where an approved entry goes: the paper port (local single-use proofs) and the live stub (task-1527)
|
|
23
|
+
// chat Telegram notify, control and approve-to-trade through the user's own bot; chat/ (task-1527)
|
|
24
|
+
// yolo task-1532: the full-port replay (rugs, loss spread, how often it zeroed the wallet); paper only
|
|
25
|
+
//
|
|
26
|
+
// The screener filter grammar is imported by path from the CLI's screener (one parser for the screen and
|
|
27
|
+
// for strategies); nothing in this package touches a key or a wallet, and nothing places a live order (task-1571). The desk executor
|
|
28
|
+
// trades only through the paper desk (a paper executor, by construction) on a keyless quote.
|
|
29
|
+
export * from "./strategy.js";
|
|
30
|
+
export * from "./engine.js";
|
|
31
|
+
export * from "./monitor.js";
|
|
32
|
+
export * from "./replay.js";
|
|
33
|
+
export * from "./session.js";
|
|
34
|
+
export * from "./runner.js";
|
|
35
|
+
export * from "./ledger.js";
|
|
36
|
+
export * from "./sessions.js";
|
|
37
|
+
export * from "./live-source.js";
|
|
38
|
+
export * from "./runner-config.js";
|
|
39
|
+
export * from "./basis-text.js";
|
|
40
|
+
export * from "./account.js";
|
|
41
|
+
export * from "./backtest.js";
|
|
42
|
+
export * from "./store.js";
|
|
43
|
+
export * from "./desk-executor.js";
|
|
44
|
+
export * from "./monitor-daemon.js";
|
|
45
|
+
export * from "./safety.js";
|
|
46
|
+
export * from "./fleet-config.js";
|
|
47
|
+
export * from "./fleet-control.js";
|
|
48
|
+
export * from "./fleet.js";
|
|
49
|
+
export * from "./paper-accounts.js";
|
|
50
|
+
export * from "./trade-ledger.js";
|
|
51
|
+
export * from "./execution-port.js";
|
|
52
|
+
export * from "./chat/index.js";
|
|
53
|
+
export * from "./yolo.js";
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// dexterm autotrade — the run ledger (task-1505 AT-3, AUTOTRADE-SPEC §4, §6.4).
|
|
2
|
+
//
|
|
3
|
+
// Every step of a run is one hash-chained event: the tick, the message text sent, the raw reply, the parsed
|
|
4
|
+
// decision, the clamp request and result, fills, wakes, no-answers, halts and session costs. Each event's hash
|
|
5
|
+
// covers the previous hash plus the canonical event, so editing, dropping or reordering any line breaks the chain
|
|
6
|
+
// from that line on (`verifyChain`).
|
|
7
|
+
//
|
|
8
|
+
// A real run (`dexterm autotrade run`) appends each event as one JSON line to
|
|
9
|
+
// $DEXTERM_HOME/autotrade/runs/<runId>.jsonl (0600) as it happens, and writes <runId>.summary.json at the end
|
|
10
|
+
// (and on every heartbeat, so a crash leaves a current summary). Backtests keep the ledger in memory.
|
|
11
|
+
//
|
|
12
|
+
// What never goes in: keys, tokens, environment variables. The session layer logs the names of the account kind
|
|
13
|
+
// and of the init event's apiKeySource only; account.ts hands a token to `claude` on a file descriptor and to
|
|
14
|
+
// nothing else.
|
|
15
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
16
|
+
import { appendFileSync, closeSync, existsSync, mkdirSync, openSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
|
|
17
|
+
import { join } from 'node:path';
|
|
18
|
+
import { canonical } from "./strategy.js";
|
|
19
|
+
export const GENESIS = '0'.repeat(16);
|
|
20
|
+
/** The chain step (exported for the chat audit chain, task-1527, which uses the same rule). */
|
|
21
|
+
export function chainHash(prev, e) {
|
|
22
|
+
// canonical() drops `hash` keys and undefined values, so the stored line (JSON drops undefined too) re-hashes
|
|
23
|
+
// to the same value; `prev` is added after hashing and excluded here.
|
|
24
|
+
const { prev: _p, ...body } = e;
|
|
25
|
+
return createHash('sha256').update(prev + canonical(body)).digest('hex').slice(0, 16);
|
|
26
|
+
}
|
|
27
|
+
export class Ledger {
|
|
28
|
+
events = [];
|
|
29
|
+
prev = GENESIS;
|
|
30
|
+
sink;
|
|
31
|
+
constructor(sink) { this.sink = sink; }
|
|
32
|
+
add(t, kind, data = {}) {
|
|
33
|
+
// seq / t / kind are the engine's: a data field of the same name can never overwrite them (task-1498 found a
|
|
34
|
+
// `kind` field in a session payload replacing the ledger kind).
|
|
35
|
+
const e = { ...data, seq: this.events.length + 1, t, kind };
|
|
36
|
+
delete e.prev;
|
|
37
|
+
delete e.hash;
|
|
38
|
+
const h = chainHash(this.prev, e);
|
|
39
|
+
e.prev = this.prev;
|
|
40
|
+
e.hash = h;
|
|
41
|
+
this.prev = h;
|
|
42
|
+
this.events.push(e);
|
|
43
|
+
this.sink?.(e, JSON.stringify(e));
|
|
44
|
+
return e;
|
|
45
|
+
}
|
|
46
|
+
head() { return this.prev; }
|
|
47
|
+
}
|
|
48
|
+
/** Recompute the chain: every event's prev is the previous hash, every hash matches its content, seq runs 1..n. */
|
|
49
|
+
export function verifyChain(events) {
|
|
50
|
+
let prev = GENESIS;
|
|
51
|
+
for (let i = 0; i < events.length; i++) {
|
|
52
|
+
const e = events[i];
|
|
53
|
+
if (e.seq !== i + 1)
|
|
54
|
+
return { ok: false, events: events.length, at: i + 1, error: `seq ${String(e.seq)} where ${i + 1} was expected` };
|
|
55
|
+
if (e.prev !== prev)
|
|
56
|
+
return { ok: false, events: events.length, at: i + 1, error: 'prev does not match the previous hash (a line was removed, added or reordered)' };
|
|
57
|
+
const want = chainHash(prev, { ...e, hash: undefined });
|
|
58
|
+
if (e.hash !== want)
|
|
59
|
+
return { ok: false, events: events.length, at: i + 1, error: 'hash does not match the content (the line was edited)' };
|
|
60
|
+
prev = want;
|
|
61
|
+
}
|
|
62
|
+
return { ok: true, events: events.length, head: prev };
|
|
63
|
+
}
|
|
64
|
+
// ───────────────────────────── files ─────────────────────────────
|
|
65
|
+
export const runsDir = (home) => join(home, 'autotrade', 'runs');
|
|
66
|
+
/** `20261021T055501Z-moonbag-3fa2`: sortable by start time, unique per start. */
|
|
67
|
+
export function newRunId(strategyId, now = Date.now(), rand = randomBytes(2).toString('hex')) {
|
|
68
|
+
const ts = new Date(now).toISOString().replace(/[-:]/g, '').replace(/\.\d{3}/, '');
|
|
69
|
+
return `${ts}-${strategyId}-${rand}`;
|
|
70
|
+
}
|
|
71
|
+
export function runFiles(home, runId) {
|
|
72
|
+
if (!/^[0-9TZ]+-[a-z][a-z0-9-]{1,31}-[0-9a-f]{4}$/.test(runId))
|
|
73
|
+
throw new Error(`not a run id: ${JSON.stringify(runId)}`);
|
|
74
|
+
const dir = runsDir(home);
|
|
75
|
+
return { runId, ledger: join(dir, `${runId}.jsonl`), summary: join(dir, `${runId}.summary.json`) };
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* A Ledger whose every event is appended to runs/<runId>.jsonl as it happens (0600, the directory 0700). `tap` sees
|
|
79
|
+
* each event after it is written (task-1527: the chat notify bus); a tap that throws never stops the ledger.
|
|
80
|
+
*/
|
|
81
|
+
export function fileLedger(home, runId, tap) {
|
|
82
|
+
const files = runFiles(home, runId);
|
|
83
|
+
mkdirSync(runsDir(home), { recursive: true, mode: 0o700 });
|
|
84
|
+
if (existsSync(files.ledger))
|
|
85
|
+
throw new Error(`run ledger ${files.ledger} already exists`);
|
|
86
|
+
closeSync(openSync(files.ledger, 'a', 0o600));
|
|
87
|
+
const ledger = new Ledger((e, line) => { appendFileSync(files.ledger, `${line}\n`); if (tap) {
|
|
88
|
+
try {
|
|
89
|
+
tap(e);
|
|
90
|
+
}
|
|
91
|
+
catch { /* never the ledger's problem */ }
|
|
92
|
+
} });
|
|
93
|
+
return { ledger, files };
|
|
94
|
+
}
|
|
95
|
+
export function readLedgerFile(path) {
|
|
96
|
+
const out = [];
|
|
97
|
+
for (const line of readFileSync(path, 'utf8').split('\n'))
|
|
98
|
+
if (line.trim())
|
|
99
|
+
out.push(JSON.parse(line));
|
|
100
|
+
return out;
|
|
101
|
+
}
|
|
102
|
+
export const RUN_SUMMARY_SCHEMA = 'dexterm-autotrade-run-summary/1';
|
|
103
|
+
/** Atomic write (tmp + rename) of a JSON document, 0600. */
|
|
104
|
+
export function writeJsonAtomic(path, doc) {
|
|
105
|
+
const tmp = `${path}.${process.pid}.tmp`;
|
|
106
|
+
writeFileSync(tmp, `${JSON.stringify(doc, null, 2)}\n`, { mode: 0o600 });
|
|
107
|
+
renameSync(tmp, path);
|
|
108
|
+
}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
// dexterm autotrade — Store-fed MarketTicks for a live paper run (task-1505 AT-3, AUTOTRADE-SPEC §4 "Daemon").
|
|
2
|
+
//
|
|
3
|
+
// The same data layer as the TUI, so the runner screens exactly what the screener shows:
|
|
4
|
+
// pool Store.discover(preset, …, {max}) every `discoverEveryMs` (60 s; the feeds are list calls, keyless
|
|
5
|
+
// pacing applies), then Store.enrich(pool) every `refreshMs` (10 s). Enrich serves DexScreener pairs from
|
|
6
|
+
// the shared cache (TTL 10 s) and Jupiter records from the cache only, so a refresh never queues behind the
|
|
7
|
+
// keyless Jupiter bucket.
|
|
8
|
+
// fast lane candidate and held coins every `fastMs` (5 s) straight from DexScreener `tokens/v1`, batches of 30
|
|
9
|
+
// (never per-coin Jupiter calls: keyless Jupiter allows about 5 per 10 s per IP), under a daily call
|
|
10
|
+
// ceiling. The slow fields a pair does not carry (holders, top 10, dev share, authorities, organic score)
|
|
11
|
+
// are carried from the coin's last pool row, the way the recorder's tick lane does.
|
|
12
|
+
//
|
|
13
|
+
// Every row becomes the MarketTick a recorded tape would hold for it (same fields, same nulls), in time order. A row
|
|
14
|
+
// whose data did not change since the last tick of that coin (same fetch) is not emitted twice.
|
|
15
|
+
const fin = (v) => (typeof v === 'number' && Number.isFinite(v) ? v : null);
|
|
16
|
+
const bool = (v) => (v === null || v === undefined ? null : Boolean(v));
|
|
17
|
+
/** Display-safe symbol (control, bidi and zero-width code points dropped, 16 chars); the firewall still wraps it for a model. */
|
|
18
|
+
export function cleanSymbol(s) {
|
|
19
|
+
let out = '';
|
|
20
|
+
for (const ch of String(s ?? '').normalize('NFC')) {
|
|
21
|
+
const cp = ch.codePointAt(0);
|
|
22
|
+
if (cp < 0x20 || (cp >= 0x7f && cp <= 0x9f) || cp === 0x200b || cp === 0x200c || cp === 0x200d || cp === 0x2060 || cp === 0xfeff)
|
|
23
|
+
continue;
|
|
24
|
+
if ((cp >= 0x200e && cp <= 0x200f) || (cp >= 0x202a && cp <= 0x202e) || (cp >= 0x2066 && cp <= 0x2069))
|
|
25
|
+
continue;
|
|
26
|
+
out += ch;
|
|
27
|
+
}
|
|
28
|
+
out = out.replace(/\s+/g, ' ').trim();
|
|
29
|
+
return out.length > 16 ? `${out.slice(0, 16)}…` : out;
|
|
30
|
+
}
|
|
31
|
+
/** A screener row as a tape tick (`t` = the newest fetch among its parts). */
|
|
32
|
+
export function tickFromRow(r, now = Date.now()) {
|
|
33
|
+
const { token, pair, stats, audit } = r;
|
|
34
|
+
const t = Math.max(token.fetchedAt || 0, pair.fetchedAt || 0, stats?.fetchedAt ?? 0, audit?.fetchedAt ?? 0) || now;
|
|
35
|
+
return {
|
|
36
|
+
mint: r.mint, t, kind: 'live',
|
|
37
|
+
symbol: cleanSymbol(token.symbol), launchpad: (token.launchpad ?? 'unknown'),
|
|
38
|
+
createdAt: fin(token.createdAt ?? pair.createdAt),
|
|
39
|
+
price: fin(pair.priceUsd), mcap: fin(pair.mcap), mcapResolved: fin(r.mcap?.value), mcapFlagged: !!r.mcap?.flagged,
|
|
40
|
+
liq: fin(pair.liquidityUsd), vol5m: fin(pair.volume.m5), vol1h: fin(pair.volume.h1), vol24: fin(pair.volume.h24),
|
|
41
|
+
buys5m: fin(pair.txns.m5?.buys), sells5m: fin(pair.txns.m5?.sells), buys24: fin(pair.txns.h24?.buys), sells24: fin(pair.txns.h24?.sells),
|
|
42
|
+
chg5m: fin(pair.priceChange.m5), chg1h: fin(pair.priceChange.h1), chg6h: fin(pair.priceChange.h6), chg24h: fin(pair.priceChange.h24),
|
|
43
|
+
holders: fin(stats?.holderCount), top10: fin(audit?.top10Pct), dev: fin(audit?.devPct),
|
|
44
|
+
mintAuth: bool(audit?.mintAuthority), freezeAuth: bool(audit?.freezeAuthority), org: fin(stats?.organicScore),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/** A fast-lane DexScreener view on top of the coin's last pool tick (slow fields carried, mcap re-resolved by the price move). */
|
|
48
|
+
export function tickFromDs(v, base, now = Date.now()) {
|
|
49
|
+
const p = v.pair;
|
|
50
|
+
const price = fin(p.priceUsd);
|
|
51
|
+
const scaled = base?.mcapResolved !== null && base?.mcapResolved !== undefined && base.price && price !== null ? base.mcapResolved * (price / base.price) : fin(p.mcap);
|
|
52
|
+
return {
|
|
53
|
+
mint: v.token.mint, t: p.fetchedAt || now, kind: 'live',
|
|
54
|
+
symbol: base?.symbol ?? cleanSymbol(v.token.symbol), launchpad: base?.launchpad ?? (v.token.launchpad ?? 'unknown'),
|
|
55
|
+
createdAt: base?.createdAt ?? fin(v.token.createdAt ?? p.createdAt),
|
|
56
|
+
price, mcap: fin(p.mcap), mcapResolved: scaled, mcapFlagged: base?.mcapFlagged ?? false,
|
|
57
|
+
liq: fin(p.liquidityUsd), vol5m: fin(p.volume.m5), vol1h: fin(p.volume.h1), vol24: fin(p.volume.h24) ?? base?.vol24 ?? null,
|
|
58
|
+
buys5m: fin(p.txns.m5?.buys), sells5m: fin(p.txns.m5?.sells), buys24: fin(p.txns.h24?.buys) ?? base?.buys24 ?? null, sells24: fin(p.txns.h24?.sells) ?? base?.sells24 ?? null,
|
|
59
|
+
chg5m: fin(p.priceChange.m5), chg1h: fin(p.priceChange.h1), chg6h: fin(p.priceChange.h6) ?? base?.chg6h ?? null, chg24h: fin(p.priceChange.h24) ?? base?.chg24h ?? null,
|
|
60
|
+
holders: base?.holders ?? null, top10: base?.top10 ?? null, dev: base?.dev ?? null,
|
|
61
|
+
mintAuth: base?.mintAuth ?? null, freezeAuth: base?.freezeAuth ?? null, org: base?.org ?? null,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
export const LIVE_DEFAULTS = { presets: ['trending', 'recent'], poolMax: 150, discoverEveryMs: 60_000, refreshMs: 10_000, fastMs: 5_000, batch: 30, maxFastCallsPerDay: 17_280 };
|
|
65
|
+
export class LiveSource {
|
|
66
|
+
deps;
|
|
67
|
+
o;
|
|
68
|
+
focus = [];
|
|
69
|
+
pool = [];
|
|
70
|
+
last = new Map();
|
|
71
|
+
stopped = false;
|
|
72
|
+
wake = null;
|
|
73
|
+
fastDay = '';
|
|
74
|
+
stats = { discovers: 0, refreshes: 0, fastCalls: 0, fastCallsToday: 0, ticks: 0, errors: 0, fastSkippedCeiling: 0 };
|
|
75
|
+
constructor(deps, opts = {}) {
|
|
76
|
+
this.deps = deps;
|
|
77
|
+
this.o = {
|
|
78
|
+
...LIVE_DEFAULTS, ...Object.fromEntries(Object.entries(opts).filter(([, v]) => v !== undefined)),
|
|
79
|
+
now: opts.now ?? Date.now,
|
|
80
|
+
sleep: opts.sleep ?? ((ms) => new Promise((r) => { const t = setTimeout(r, ms); this.wake = () => { clearTimeout(t); r(); }; })),
|
|
81
|
+
onLog: opts.onLog ?? (() => { }),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
/** The runner's candidate + held coins (the fast lane). */
|
|
85
|
+
setFocus(marks) { this.focus = marks.slice(0, 60); }
|
|
86
|
+
stop() { this.stopped = true; this.wake?.(); }
|
|
87
|
+
emitNew(ticks, out) {
|
|
88
|
+
for (const k of ticks) {
|
|
89
|
+
const prev = this.last.get(k.mint);
|
|
90
|
+
if (prev && k.t <= prev.t)
|
|
91
|
+
continue;
|
|
92
|
+
this.last.set(k.mint, k);
|
|
93
|
+
out.push(k);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/** One fast-lane pass over the focus coins; returns the new ticks. Respects the daily ceiling. */
|
|
97
|
+
async fastPass() {
|
|
98
|
+
const mints = [...new Set(this.focus.map((f) => f.mint))];
|
|
99
|
+
if (!mints.length)
|
|
100
|
+
return [];
|
|
101
|
+
const day = new Date(this.o.now()).toISOString().slice(0, 10);
|
|
102
|
+
if (day !== this.fastDay) {
|
|
103
|
+
this.fastDay = day;
|
|
104
|
+
this.stats.fastCallsToday = 0;
|
|
105
|
+
}
|
|
106
|
+
const out = [];
|
|
107
|
+
for (let i = 0; i < mints.length; i += this.o.batch) {
|
|
108
|
+
if (this.stats.fastCallsToday >= this.o.maxFastCallsPerDay) {
|
|
109
|
+
this.stats.fastSkippedCeiling++;
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
const batch = mints.slice(i, i + this.o.batch);
|
|
113
|
+
this.stats.fastCalls++;
|
|
114
|
+
this.stats.fastCallsToday++;
|
|
115
|
+
try {
|
|
116
|
+
const views = await this.deps.dexscreener.tokens(batch);
|
|
117
|
+
const now = this.o.now();
|
|
118
|
+
this.emitNew(batch.map((m) => views.get(m)).filter((v) => !!v).map((v) => tickFromDs(v, this.last.get(v.token.mint), now)), out);
|
|
119
|
+
}
|
|
120
|
+
catch (e) {
|
|
121
|
+
this.stats.errors++;
|
|
122
|
+
this.o.onLog(`fast lane: ${e.message}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return out;
|
|
126
|
+
}
|
|
127
|
+
/** One pool pass: discover when due, then enrich the pool. */
|
|
128
|
+
async poolPass(discover) {
|
|
129
|
+
const out = [];
|
|
130
|
+
try {
|
|
131
|
+
if (discover || !this.pool.length) {
|
|
132
|
+
const seen = new Set();
|
|
133
|
+
for (const p of this.o.presets)
|
|
134
|
+
for (const m of (await this.deps.store.discover(p, 30, { max: this.o.poolMax })).mints)
|
|
135
|
+
seen.add(m);
|
|
136
|
+
this.pool = [...seen].slice(0, this.o.poolMax);
|
|
137
|
+
this.stats.discovers++;
|
|
138
|
+
}
|
|
139
|
+
const { rows } = await this.deps.store.enrich(this.pool, { jup: 'cache' });
|
|
140
|
+
this.stats.refreshes++;
|
|
141
|
+
const now = this.o.now();
|
|
142
|
+
this.emitNew(rows.filter((r) => r.mint && r.pair).map((r) => tickFromRow(r, now)), out);
|
|
143
|
+
}
|
|
144
|
+
catch (e) {
|
|
145
|
+
this.stats.errors++;
|
|
146
|
+
this.o.onLog(`pool refresh: ${e.message}`);
|
|
147
|
+
}
|
|
148
|
+
return out;
|
|
149
|
+
}
|
|
150
|
+
/** The tick stream: pool every refreshMs, fast lane every fastMs, in time order within each pass. Ends on stop(). */
|
|
151
|
+
async *ticks() {
|
|
152
|
+
let lastPool = -Infinity;
|
|
153
|
+
let lastDiscover = -Infinity;
|
|
154
|
+
let lastT = 0;
|
|
155
|
+
while (!this.stopped) {
|
|
156
|
+
const t = this.o.now();
|
|
157
|
+
const batch = [];
|
|
158
|
+
if (t - lastPool >= this.o.refreshMs) {
|
|
159
|
+
const disc = t - lastDiscover >= this.o.discoverEveryMs;
|
|
160
|
+
batch.push(...await this.poolPass(disc));
|
|
161
|
+
lastPool = t;
|
|
162
|
+
if (disc)
|
|
163
|
+
lastDiscover = t;
|
|
164
|
+
}
|
|
165
|
+
batch.push(...await this.fastPass());
|
|
166
|
+
batch.sort((a, b) => a.t - b.t || (a.mint < b.mint ? -1 : 1));
|
|
167
|
+
// The run clock never goes backwards: a cached row fetched before the last tick is stamped at that tick.
|
|
168
|
+
for (const k of batch) {
|
|
169
|
+
if (k.t < lastT)
|
|
170
|
+
k.t = lastT;
|
|
171
|
+
lastT = k.t;
|
|
172
|
+
this.stats.ticks++;
|
|
173
|
+
yield k;
|
|
174
|
+
if (this.stopped)
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
if (this.stopped)
|
|
178
|
+
return;
|
|
179
|
+
await this.o.sleep(Math.max(250, this.o.fastMs - (this.o.now() - t)));
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|