dexterm-cli 0.1.6 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (395) hide show
  1. package/dist/packages/agents/src/schema.js +22 -1
  2. package/dist/packages/agents/src/spectator.js +3 -1
  3. package/dist/packages/agents/src/story.js +11 -2
  4. package/dist/packages/agents/src/tiers.js +36 -2
  5. package/dist/packages/agents/src/tools.js +35 -2
  6. package/dist/packages/autotrade/assets/exit-profile.schema.json +492 -0
  7. package/dist/packages/autotrade/assets/limits.schema.json +569 -0
  8. package/dist/packages/autotrade/assets/profiles/moonbag.json +46 -0
  9. package/dist/packages/autotrade/assets/profiles/runner.json +88 -0
  10. package/dist/packages/autotrade/assets/profiles/scalp.json +88 -0
  11. package/dist/packages/autotrade/assets/profiles/swing.json +88 -0
  12. package/dist/packages/autotrade/assets/strategies/moonbag.json +101 -0
  13. package/dist/packages/autotrade/assets/strategies/runner.json +101 -0
  14. package/dist/packages/autotrade/assets/strategies/sample-dip-ladder.json +188 -0
  15. package/dist/packages/autotrade/assets/strategies/scalp.json +98 -0
  16. package/dist/packages/autotrade/assets/strategies/swing.json +97 -0
  17. package/dist/packages/autotrade/assets/strategies/yolo.json +157 -0
  18. package/dist/packages/autotrade/assets/tapes/yolo-rehearsal.json +1 -0
  19. package/dist/packages/autotrade/examples/executor/README.md +70 -0
  20. package/dist/packages/autotrade/examples/executor/jsonl-tail-executor.mjs +57 -0
  21. package/dist/packages/autotrade/examples/executor/kit.mjs +144 -0
  22. package/dist/packages/autotrade/examples/executor/signal-cmd-executor.mjs +25 -0
  23. package/dist/packages/autotrade/examples/executor/telegram-bot-recipe.md +47 -0
  24. package/dist/packages/autotrade/examples/executor/webhook-executor.mjs +47 -0
  25. package/dist/packages/autotrade/src/account.js +74 -0
  26. package/dist/packages/autotrade/src/backtest.js +358 -0
  27. package/dist/packages/autotrade/src/basis-text.js +32 -0
  28. package/dist/packages/autotrade/src/chat/approvals.js +484 -0
  29. package/dist/packages/autotrade/src/chat/audit.js +140 -0
  30. package/dist/packages/autotrade/src/chat/config.js +95 -0
  31. package/dist/packages/autotrade/src/chat/connector.js +24 -0
  32. package/dist/packages/autotrade/src/chat/control.js +104 -0
  33. package/dist/packages/autotrade/src/chat/fake.js +100 -0
  34. package/dist/packages/autotrade/src/chat/format.js +71 -0
  35. package/dist/packages/autotrade/src/chat/hub.js +187 -0
  36. package/dist/packages/autotrade/src/chat/index.js +18 -0
  37. package/dist/packages/autotrade/src/chat/notify.js +302 -0
  38. package/dist/packages/autotrade/src/chat/pairing.js +46 -0
  39. package/dist/packages/autotrade/src/chat/redact.js +48 -0
  40. package/dist/packages/autotrade/src/chat/secrets.js +106 -0
  41. package/dist/packages/autotrade/src/chat/service.js +251 -0
  42. package/dist/packages/autotrade/src/chat/telegram.js +290 -0
  43. package/dist/packages/autotrade/src/desk-executor.js +188 -0
  44. package/dist/packages/autotrade/src/engine.js +401 -0
  45. package/dist/packages/autotrade/src/execution-port.js +97 -0
  46. package/dist/packages/autotrade/src/executor-health.js +217 -0
  47. package/dist/packages/autotrade/src/fleet-config.js +169 -0
  48. package/dist/packages/autotrade/src/fleet-control.js +276 -0
  49. package/dist/packages/autotrade/src/fleet.js +642 -0
  50. package/dist/packages/autotrade/src/forward.js +355 -0
  51. package/dist/packages/autotrade/src/index.js +72 -0
  52. package/dist/packages/autotrade/src/journey.js +477 -0
  53. package/dist/packages/autotrade/src/ledger.js +108 -0
  54. package/dist/packages/autotrade/src/limits.js +682 -0
  55. package/dist/packages/autotrade/src/live-source.js +182 -0
  56. package/dist/packages/autotrade/src/monitor-daemon.js +715 -0
  57. package/dist/packages/autotrade/src/monitor.js +190 -0
  58. package/dist/packages/autotrade/src/ollama-sessions.js +137 -0
  59. package/dist/packages/autotrade/src/outbox.js +394 -0
  60. package/dist/packages/autotrade/src/paper-accounts.js +72 -0
  61. package/dist/packages/autotrade/src/paper-limits.js +87 -0
  62. package/dist/packages/autotrade/src/real-mode.js +688 -0
  63. package/dist/packages/autotrade/src/receipts.js +330 -0
  64. package/dist/packages/autotrade/src/replay.js +198 -0
  65. package/dist/packages/autotrade/src/report.js +168 -0
  66. package/dist/packages/autotrade/src/runner-config.js +99 -0
  67. package/dist/packages/autotrade/src/runner.js +923 -0
  68. package/dist/packages/autotrade/src/safety.js +243 -0
  69. package/dist/packages/autotrade/src/service-guard.js +125 -0
  70. package/dist/packages/autotrade/src/service-install.js +213 -0
  71. package/dist/packages/autotrade/src/service-recover.js +232 -0
  72. package/dist/packages/autotrade/src/service.js +289 -0
  73. package/dist/packages/autotrade/src/session.js +269 -0
  74. package/dist/packages/autotrade/src/sessions.js +503 -0
  75. package/dist/packages/autotrade/src/signal-channels.js +312 -0
  76. package/dist/packages/autotrade/src/signal.js +196 -0
  77. package/dist/packages/autotrade/src/store.js +250 -0
  78. package/dist/packages/autotrade/src/strategy.js +258 -0
  79. package/dist/packages/autotrade/src/trade-ledger.js +241 -0
  80. package/dist/packages/autotrade/src/yolo.js +140 -0
  81. package/dist/packages/cli/assets/claude/analyst-system.md +4 -4
  82. package/dist/packages/cli/assets/claude/plugin/skills/token-dossier/SKILL.md +1 -1
  83. package/dist/packages/cli/src/ai-cmd.js +412 -0
  84. package/dist/packages/cli/src/analyst/backend.js +83 -15
  85. package/dist/packages/cli/src/analyst/codex.js +15 -9
  86. package/dist/packages/cli/src/analyst/ollama.js +263 -0
  87. package/dist/packages/cli/src/analyst/session.js +5 -2
  88. package/dist/packages/cli/src/app-help-gen.js +56 -8
  89. package/dist/packages/cli/src/autotrade-cmd/audit.js +74 -0
  90. package/dist/packages/cli/src/autotrade-cmd/backtest.js +216 -0
  91. package/dist/packages/cli/src/autotrade-cmd/executor.js +91 -0
  92. package/dist/packages/cli/src/autotrade-cmd/flatten.js +64 -0
  93. package/dist/packages/cli/src/autotrade-cmd/fleet.js +401 -0
  94. package/dist/packages/cli/src/autotrade-cmd/forward.js +283 -0
  95. package/dist/packages/cli/src/autotrade-cmd/journey.js +208 -0
  96. package/dist/packages/cli/src/autotrade-cmd/limits.js +393 -0
  97. package/dist/packages/cli/src/autotrade-cmd/receipt.js +63 -0
  98. package/dist/packages/cli/src/autotrade-cmd/report.js +79 -0
  99. package/dist/packages/cli/src/autotrade-cmd/requests.js +79 -0
  100. package/dist/packages/cli/src/autotrade-cmd/run.js +657 -0
  101. package/dist/packages/cli/src/autotrade-cmd/service.js +873 -0
  102. package/dist/packages/cli/src/autotrade-cmd/signal.js +824 -0
  103. package/dist/packages/cli/src/autotrade-cmd/stop.js +76 -0
  104. package/dist/packages/cli/src/autotrade-cmd/strategies.js +198 -0
  105. package/dist/packages/cli/src/autotrade-cmd/strategy-control.js +174 -0
  106. package/dist/packages/cli/src/autotrade-cmd/telegram-host.js +101 -0
  107. package/dist/packages/cli/src/autotrade-cmd.js +214 -0
  108. package/dist/packages/cli/src/display.js +156 -17
  109. package/dist/packages/cli/src/doctor.js +62 -3
  110. package/dist/packages/cli/src/export.js +10 -2
  111. package/dist/packages/cli/src/index.js +1 -1
  112. package/dist/packages/cli/src/ledger-cmd.js +290 -0
  113. package/dist/packages/cli/src/live/chart-fills.js +46 -0
  114. package/dist/packages/cli/src/live/index.js +23 -89
  115. package/dist/packages/cli/src/live/screens/token-live.js +9 -6
  116. package/dist/packages/cli/src/live/trade.js +12 -457
  117. package/dist/packages/cli/src/live/watchlist.js +1 -1
  118. package/dist/packages/cli/src/main.js +147 -190
  119. package/dist/packages/cli/src/mcp-cmd.js +7 -1
  120. package/dist/packages/cli/src/plan-cmd.js +1 -1
  121. package/dist/packages/cli/src/pnl-app.js +31 -21
  122. package/dist/packages/cli/src/pnl-card.js +162 -21
  123. package/dist/packages/cli/src/popup.js +22 -6
  124. package/dist/packages/cli/src/record-cmd.js +141 -20
  125. package/dist/packages/cli/src/screens/agent-hud.js +34 -2
  126. package/dist/packages/cli/src/screens/analyst-session.js +7 -4
  127. package/dist/packages/cli/src/screens/analyst.js +3 -2
  128. package/dist/packages/cli/src/screens/autotrade-journey.js +134 -0
  129. package/dist/packages/cli/src/screens/autotrade-keys.js +182 -0
  130. package/dist/packages/cli/src/screens/autotrade-proposals.js +123 -0
  131. package/dist/packages/cli/src/screens/autotrade-screen.js +776 -0
  132. package/dist/packages/cli/src/screens/autotrade-ui.js +650 -0
  133. package/dist/packages/cli/src/screens/autotrade-worker.js +91 -0
  134. package/dist/packages/cli/src/screens/brain.js +37 -11
  135. package/dist/packages/cli/src/screens/overlay.js +5 -2
  136. package/dist/packages/cli/src/screens/plans.js +5 -17
  137. package/dist/packages/cli/src/screens/pnl-chip.js +9 -8
  138. package/dist/packages/cli/src/screens/positions.js +6 -28
  139. package/dist/packages/cli/src/screens/ticket.js +38 -205
  140. package/dist/packages/cli/src/screens/token.js +3 -3
  141. package/dist/packages/cli/src/state.js +25 -19
  142. package/dist/packages/cli/src/telegram-cmd.js +454 -0
  143. package/dist/packages/cli/src/trade.js +3 -128
  144. package/dist/packages/cli/src/version.js +1 -1
  145. package/dist/packages/cli/src/wallet-cmd.js +39 -340
  146. package/dist/packages/cli/src/wallet-command.js +8 -11
  147. package/dist/packages/cli/src/widgets.js +0 -12
  148. package/dist/packages/custom/src/config.js +20 -2
  149. package/dist/packages/custom/src/schema.js +35 -10
  150. package/dist/packages/custom/src/workspace.js +3 -3
  151. package/dist/packages/data/src/basis.js +191 -0
  152. package/dist/packages/data/src/detail.js +53 -2
  153. package/dist/packages/data/src/index.js +0 -14
  154. package/dist/packages/data/src/store.js +14 -5
  155. package/dist/packages/data/src/trade/agent/paper-desk.js +228 -16
  156. package/dist/packages/data/src/trade/agent/rendezvous.js +3 -2
  157. package/dist/packages/data/src/trade/bridge.js +4 -102
  158. package/dist/packages/data/src/trade/ledger/export.js +101 -0
  159. package/dist/packages/data/src/trade/ledger/file.js +135 -0
  160. package/dist/packages/data/src/trade/ledger/fold.js +191 -0
  161. package/dist/packages/data/src/trade/ledger/index.js +9 -0
  162. package/dist/packages/data/src/trade/ledger/schema.js +83 -0
  163. package/dist/packages/data/src/trade/ledger/sources.js +307 -0
  164. package/dist/packages/data/src/trade/ledger/stats.js +123 -0
  165. package/dist/packages/data/src/trade/ledger/tags.js +116 -0
  166. package/dist/packages/data/src/trade/ledger/view.js +51 -0
  167. package/dist/packages/data/src/trade/plans/index.js +0 -1
  168. package/dist/packages/data/src/trade/plans/service.js +3 -27
  169. package/dist/packages/mcp/assets/kb/app-help/autotrade-chat.md +48 -0
  170. package/dist/packages/mcp/assets/kb/app-help/autotrade-executor-kit.md +44 -0
  171. package/dist/packages/mcp/assets/kb/app-help/autotrade-journey.md +46 -0
  172. package/dist/packages/mcp/assets/kb/app-help/autotrade-limits.md +48 -0
  173. package/dist/packages/mcp/assets/kb/app-help/autotrade-parallel.md +42 -0
  174. package/dist/packages/mcp/assets/kb/app-help/autotrade-real-signal.md +45 -0
  175. package/dist/packages/mcp/assets/kb/app-help/autotrade-runner.md +35 -0
  176. package/dist/packages/mcp/assets/kb/app-help/autotrade-stop.md +37 -0
  177. package/dist/packages/mcp/assets/kb/app-help/autotrade-strategies.md +35 -0
  178. package/dist/packages/mcp/assets/kb/app-help/autotrade-telegram.md +40 -0
  179. package/dist/packages/mcp/assets/kb/app-help/chart-trade-markers.md +42 -0
  180. package/dist/packages/mcp/assets/kb/app-help/link-a-wallet.md +4 -10
  181. package/dist/packages/mcp/assets/kb/app-help/live-trading.md +38 -0
  182. package/dist/packages/mcp/assets/kb/app-help/live-yolo.md +34 -0
  183. package/dist/packages/mcp/assets/kb/app-help/order-plans.md +1 -1
  184. package/dist/packages/mcp/assets/kb/app-help/price-or-marketcap.md +5 -2
  185. package/dist/packages/mcp/assets/kb/app-help/screen-analyst.md +3 -0
  186. package/dist/packages/mcp/assets/kb/app-help/screen-autotrade.md +229 -0
  187. package/dist/packages/mcp/assets/kb/app-help/screen-kol.md +3 -0
  188. package/dist/packages/mcp/assets/kb/app-help/screen-newpairs.md +3 -0
  189. package/dist/packages/mcp/assets/kb/app-help/screen-positions.md +3 -0
  190. package/dist/packages/mcp/assets/kb/app-help/screen-screener.md +3 -0
  191. package/dist/packages/mcp/assets/kb/app-help/screen-token.md +3 -0
  192. package/dist/packages/mcp/assets/kb/app-help/screen-trending.md +3 -0
  193. package/dist/packages/mcp/assets/kb/app-help/screen-watchlist.md +3 -0
  194. package/dist/packages/mcp/assets/kb/app-help/standing-mandates.md +1 -1
  195. package/dist/packages/mcp/assets/kb/app-help/trade-ledger.md +54 -0
  196. package/dist/packages/mcp/assets/kb/app-help/use-local-model.md +38 -0
  197. package/dist/packages/mcp/assets/kb/docs/docs-agents-agent-paper-trading.md +4 -1
  198. package/dist/packages/mcp/assets/kb/docs/docs-agents-reading-your-trade-ledger.md +31 -0
  199. package/dist/packages/mcp/assets/kb/docs/docs-agents-untrusted-by-default.md +1 -1
  200. package/dist/packages/mcp/assets/kb/docs/docs-analyst-if-claude-is-missing.md +1 -1
  201. package/dist/packages/mcp/assets/kb/docs/docs-analyst-use-a-local-model-instead.md +27 -0
  202. package/dist/packages/mcp/assets/kb/docs/docs-analyst-what-it-sees.md +2 -0
  203. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-backtests-and-their-limits.md +56 -0
  204. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-change-a-strategy-by-chat.md +51 -0
  205. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-checking-the-record-of-a-run.md +28 -0
  206. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-comparing-them.md +41 -0
  207. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-exits-and-wakes.md +76 -0
  208. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-how-a-stop-reaches-the-runner.md +32 -0
  209. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-on-the-q-screen.md +38 -0
  210. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-one-strategy-or-all-of-them.md +35 -0
  211. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-paper-accounts.md +50 -0
  212. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-presets.md +37 -0
  213. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-running-it-all-day.md +31 -0
  214. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-sessions-and-their-limits.md +31 -0
  215. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-several-strategies-at-once.md +33 -0
  216. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-stopping-it.md +37 -0
  217. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-strategies-and-presets.md +34 -0
  218. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-always-on-service.md +57 -0
  219. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-autotrade-json-file.md +48 -0
  220. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-heartbeat.md +27 -0
  221. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-run-file-and-the-heartbeat.md +34 -0
  222. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-the-runner-and-candidate-sessions.md +45 -0
  223. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-each-session-shows-first.md +31 -0
  224. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-it-costs-claude-usage-per-session.md +58 -0
  225. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-it-is-paper-self-directed.md +50 -0
  226. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-what-it-will-not-do.md +31 -0
  227. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-which-account-day-caps-and-the-usage-guard.md +44 -0
  228. package/dist/packages/mcp/assets/kb/docs/docs-autotrade-your-strategies.md +37 -0
  229. package/dist/packages/mcp/assets/kb/docs/docs-autotrade.md +22 -0
  230. package/dist/packages/mcp/assets/kb/docs/docs-beginners-before-any-experimental-trading.md +2 -2
  231. package/dist/packages/mcp/assets/kb/docs/docs-beginners.md +1 -1
  232. package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-1-ask-for-a-strategy.md +27 -0
  233. package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-2-backtest-it-held-out-split.md +31 -0
  234. package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-3-forward-test-it-on-live-data.md +44 -0
  235. package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-4-promote-it-to-always-on-paper.md +36 -0
  236. package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-5-real-only-if-you-choose.md +36 -0
  237. package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-the-ladder.md +39 -0
  238. package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-the-report.md +31 -0
  239. package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat-what-the-analyst-knows.md +30 -0
  240. package/dist/packages/mcp/assets/kb/docs/docs-build-a-strategy-by-chat.md +24 -0
  241. package/dist/packages/mcp/assets/kb/docs/docs-configuration-chart-markers.md +30 -0
  242. package/dist/packages/mcp/assets/kb/docs/docs-configuration-chart-y-axis.md +1 -1
  243. package/dist/packages/mcp/assets/kb/docs/docs-configuration-environment-variables.md +4 -1
  244. package/dist/packages/mcp/assets/kb/docs/docs-configuration-files-on-disk.md +1 -0
  245. package/dist/packages/mcp/assets/kb/docs/docs-configuration-headless-recorder-dexterm-record.md +3 -1
  246. package/dist/packages/mcp/assets/kb/docs/docs-configuration-price-display-mode.md +8 -6
  247. package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-stage-2-the-one-key-mirror-ticket-a-proposal.md +1 -1
  248. package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-stage-3-capped-auto-mirror-default-off-less.md +1 -1
  249. package/dist/packages/mcp/assets/kb/docs/docs-copy-trading-what-is-proven-what-is-not.md +1 -1
  250. package/dist/packages/mcp/assets/kb/docs/docs-copy-trading.md +1 -1
  251. package/dist/packages/mcp/assets/kb/docs/docs-data-sources-recorded-history-and-retention.md +36 -0
  252. package/dist/packages/mcp/assets/kb/docs/docs-data-sources-sources.md +1 -0
  253. package/dist/packages/mcp/assets/kb/docs/docs-getting-started-first-run.md +1 -1
  254. package/dist/packages/mcp/assets/kb/docs/docs-getting-started-install.md +3 -3
  255. package/dist/packages/mcp/assets/kb/docs/docs-getting-started-requirements.md +1 -1
  256. package/dist/packages/mcp/assets/kb/docs/docs-getting-started.md +1 -1
  257. package/dist/packages/mcp/assets/kb/docs/docs-going-real-executor-health.md +38 -0
  258. package/dist/packages/mcp/assets/kb/docs/docs-going-real-paper-vs-real.md +33 -0
  259. package/dist/packages/mcp/assets/kb/docs/docs-going-real-the-digest.md +36 -0
  260. package/dist/packages/mcp/assets/kb/docs/docs-going-real-the-executor-kit.md +48 -0
  261. package/dist/packages/mcp/assets/kb/docs/docs-going-real-the-whole-path.md +37 -0
  262. package/dist/packages/mcp/assets/kb/docs/docs-going-real-what-dexterm-does-and-never-does.md +44 -0
  263. package/dist/packages/mcp/assets/kb/docs/docs-going-real-your-limits.md +77 -0
  264. package/dist/packages/mcp/assets/kb/docs/docs-going-real.md +24 -0
  265. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-changed-in-0-1-7.md +26 -0
  266. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-real-mode-your-strategy-s-trades-to-your.md +31 -0
  267. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-stopping.md +28 -0
  268. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-the-short-version.md +34 -0
  269. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-using-a-trading-bot-with-dexterm.md +31 -0
  270. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-what-dexterm-does-not-do.md +30 -0
  271. package/dist/packages/mcp/assets/kb/docs/docs-live-trading-what-dexterm-does.md +29 -0
  272. package/dist/packages/mcp/assets/kb/docs/docs-live-trading.md +23 -0
  273. package/dist/packages/mcp/assets/kb/docs/docs-ollama-another-machine.md +28 -0
  274. package/dist/packages/mcp/assets/kb/docs/docs-ollama-autotrade-on-a-local-model.md +29 -0
  275. package/dist/packages/mcp/assets/kb/docs/docs-ollama-check-your-model-dexterm-ai-probe.md +38 -0
  276. package/dist/packages/mcp/assets/kb/docs/docs-ollama-how-we-checked.md +27 -0
  277. package/dist/packages/mcp/assets/kb/docs/docs-ollama-models-without-tool-calling.md +32 -0
  278. package/dist/packages/mcp/assets/kb/docs/docs-ollama-pick-the-engine-globally-or-per-surface.md +43 -0
  279. package/dist/packages/mcp/assets/kb/docs/docs-ollama-restriction-profiles.md +35 -0
  280. package/dist/packages/mcp/assets/kb/docs/docs-ollama-set-it-up-in-two-minutes.md +39 -0
  281. package/dist/packages/mcp/assets/kb/docs/docs-ollama-troubleshooting.md +35 -0
  282. package/dist/packages/mcp/assets/kb/docs/docs-ollama-what-runs-on-a-local-model.md +39 -0
  283. package/dist/packages/mcp/assets/kb/docs/docs-ollama-what-stays-outside-the-model.md +36 -0
  284. package/dist/packages/mcp/assets/kb/docs/docs-ollama-which-model.md +38 -0
  285. package/dist/packages/mcp/assets/kb/docs/docs-ollama-your-own-agent-on-the-local-model.md +28 -0
  286. package/dist/packages/mcp/assets/kb/docs/docs-ollama.md +28 -0
  287. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-letting-an-agent-paper-trade-experimental.md +3 -4
  288. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-link-a-wallet-read-only.md +30 -0
  289. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-order-plans-and-standing-mandates.md +3 -4
  290. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-panic.md +4 -7
  291. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-paper-only-mandates.md +6 -7
  292. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-pnl-cards.md +7 -7
  293. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-safety-model.md +34 -0
  294. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-ticket.md +3 -4
  295. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-trade-ledger.md +42 -0
  296. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-wallet.md +4 -5
  297. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-trade-moments.md +4 -5
  298. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading.md +4 -5
  299. package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-buy-and-sell-markers.md +37 -0
  300. package/dist/packages/mcp/assets/kb/docs/docs-popup-chart-what-it-shows.md +2 -1
  301. package/dist/packages/mcp/assets/kb/docs/docs-real-mode-receipts-what-your-executor-did.md +42 -0
  302. package/dist/packages/mcp/assets/kb/docs/docs-real-mode-safety.md +34 -0
  303. package/dist/packages/mcp/assets/kb/docs/docs-real-mode-set-it-up.md +47 -0
  304. package/dist/packages/mcp/assets/kb/docs/docs-real-mode-the-channels.md +42 -0
  305. package/dist/packages/mcp/assets/kb/docs/docs-real-mode-the-signal.md +48 -0
  306. package/dist/packages/mcp/assets/kb/docs/docs-real-mode-what-it-is.md +35 -0
  307. package/dist/packages/mcp/assets/kb/docs/docs-real-mode-what-it-will-not-do.md +34 -0
  308. package/dist/packages/mcp/assets/kb/docs/docs-real-mode-where-you-see-it.md +34 -0
  309. package/dist/packages/mcp/assets/kb/docs/docs-real-mode.md +27 -0
  310. package/dist/packages/mcp/assets/kb/docs/docs-screens-autotrade-paper.md +26 -0
  311. package/dist/packages/mcp/assets/kb/docs/docs-screens-order-plans.md +1 -1
  312. package/dist/packages/mcp/assets/kb/docs/docs-screens-token-screen.md +2 -0
  313. package/dist/packages/mcp/assets/kb/docs/docs-spectator-the-brain-view-and-the-pnl-chip.md +1 -1
  314. package/dist/packages/mcp/assets/kb/docs/docs-telegram-approve-one-tap-entries.md +50 -0
  315. package/dist/packages/mcp/assets/kb/docs/docs-telegram-control-the-commands.md +43 -0
  316. package/dist/packages/mcp/assets/kb/docs/docs-telegram-if-something-goes-wrong.md +30 -0
  317. package/dist/packages/mcp/assets/kb/docs/docs-telegram-notify-what-reaches-your-phone.md +41 -0
  318. package/dist/packages/mcp/assets/kb/docs/docs-telegram-set-it-up.md +47 -0
  319. package/dist/packages/mcp/assets/kb/docs/docs-telegram-the-record.md +26 -0
  320. package/dist/packages/mcp/assets/kb/docs/docs-telegram-what-it-is.md +33 -0
  321. package/dist/packages/mcp/assets/kb/docs/docs-telegram-what-it-will-not-do.md +31 -0
  322. package/dist/packages/mcp/assets/kb/docs/docs-telegram.md +23 -0
  323. package/dist/packages/mcp/assets/kb/docs/docs-troubleshooting-common-questions.md +1 -1
  324. package/dist/packages/mcp/assets/kb/docs/docs-troubleshooting-doctor-lines.md +4 -0
  325. package/dist/packages/mcp/assets/kb/docs/docs-voice-linux-and-windows.md +1 -1
  326. package/dist/packages/mcp/assets/kb/docs/docs-voice.md +1 -1
  327. package/dist/packages/mcp/assets/kb/docs/docs-yolo-1-replay-it-on-your-own-history.md +42 -0
  328. package/dist/packages/mcp/assets/kb/docs/docs-yolo-2-run-it-on-paper.md +34 -0
  329. package/dist/packages/mcp/assets/kb/docs/docs-yolo-3-watch-it-and-stop-it.md +32 -0
  330. package/dist/packages/mcp/assets/kb/docs/docs-yolo-the-rules.md +37 -0
  331. package/dist/packages/mcp/assets/kb/docs/docs-yolo-what-it-is.md +34 -0
  332. package/dist/packages/mcp/assets/kb/docs/docs-yolo-what-it-will-not-do.md +31 -0
  333. package/dist/packages/mcp/assets/kb/docs/docs-yolo.md +26 -0
  334. package/dist/packages/mcp/assets/kb/entries/autotrade.md +40 -0
  335. package/dist/packages/mcp/src/app-help.js +1 -1
  336. package/dist/packages/mcp/src/autotrade-tools.js +1107 -0
  337. package/dist/packages/mcp/src/backtest-requests.js +71 -0
  338. package/dist/packages/mcp/src/engine/config.js +159 -0
  339. package/dist/packages/mcp/src/engine/index.js +10 -0
  340. package/dist/packages/mcp/src/engine/loop.js +101 -0
  341. package/dist/packages/mcp/src/engine/mcp-client.js +123 -0
  342. package/dist/packages/mcp/src/engine/ollama.js +258 -0
  343. package/dist/packages/mcp/src/engine/probe.js +110 -0
  344. package/dist/packages/mcp/src/engine/reason.js +35 -0
  345. package/dist/packages/mcp/src/engine/restrictions.js +111 -0
  346. package/dist/packages/mcp/src/index.js +7 -1
  347. package/dist/packages/mcp/src/ledger-tools.js +494 -0
  348. package/dist/packages/mcp/src/paper-agent.js +2 -0
  349. package/dist/packages/mcp/src/server.js +138 -19
  350. package/dist/packages/packs/src/backtest.js +3 -1
  351. package/dist/packages/popup/src/pages/chart-lib.js +134 -21
  352. package/dist/packages/popup/src/pages/chart.css +9 -0
  353. package/dist/packages/popup/src/pages/chart.html +3 -1
  354. package/dist/packages/popup/src/pages/chart.js +104 -7
  355. package/dist/packages/popup/src/protocol.js +2 -0
  356. package/dist/packages/popup/src/server.js +4 -0
  357. package/dist/packages/recorder/src/index.js +2 -0
  358. package/dist/packages/recorder/src/recorder.js +63 -6
  359. package/dist/packages/recorder/src/retention.js +100 -0
  360. package/dist/packages/recorder/src/schema.js +34 -1
  361. package/dist/packages/recorder/src/ticks.js +237 -0
  362. package/dist/packages/tui/src/index.js +1 -0
  363. package/dist/packages/tui/src/keymap.js +28 -1
  364. package/dist/packages/tui/src/markers.js +219 -0
  365. package/dist/packages/tui/src/widgets.js +149 -2
  366. package/package.json +2 -1
  367. package/dist/packages/data/src/trade/caps.js +0 -323
  368. package/dist/packages/data/src/trade/executor.js +0 -933
  369. package/dist/packages/data/src/trade/plans/executor-live.js +0 -220
  370. package/dist/packages/data/src/trade/rpc-exec.js +0 -229
  371. package/dist/packages/data/src/trade/signer/client.js +0 -197
  372. package/dist/packages/data/src/trade/signer/fast-wallet.js +0 -154
  373. package/dist/packages/data/src/trade/signer/host.js +0 -97
  374. package/dist/packages/data/src/trade/signer/main.js +0 -121
  375. package/dist/packages/data/src/trade/signer/probe-builder.js +0 -85
  376. package/dist/packages/data/src/trade/signer/protocol.js +0 -92
  377. package/dist/packages/data/src/trade/signer/service.js +0 -400
  378. package/dist/packages/data/src/trade/signer/sol-usd-feed.js +0 -98
  379. package/dist/packages/data/src/trade/sol-usd.js +0 -86
  380. package/dist/packages/data/src/trade/swap-build.js +0 -108
  381. package/dist/packages/data/src/trade/token-delta.js +0 -201
  382. package/dist/packages/data/vendor/solana-web3/LICENSE +0 -20
  383. package/dist/packages/data/vendor/solana-web3/NOTICE.md +0 -13
  384. package/dist/packages/data/vendor/solana-web3/index.iife.min.js +0 -20
  385. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-a-live-ticket.md +0 -42
  386. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-before-you-press-size-vs-caps.md +0 -34
  387. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-devnet-signer-mainnet-token.md +0 -35
  388. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-jupiter-rate-limits.md +0 -33
  389. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-link-a-wallet.md +0 -32
  390. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-live-trading-devnet-first.md +0 -30
  391. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-mainnet.md +0 -31
  392. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-live-fire-path-devnet-the-fast-wallet.md +0 -41
  393. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-the-signer-process.md +0 -34
  394. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-what-the-live-path-keeps.md +0 -37
  395. package/dist/packages/mcp/assets/kb/docs/docs-paper-trading-your-first-live-trade.md +0 -41
@@ -0,0 +1,98 @@
1
+ {
2
+ "kind": "strategy",
3
+ "schema": "dexterm-strategy/1",
4
+ "id": "scalp",
5
+ "name": "Scalp (quick play)",
6
+ "version": "1.0.0",
7
+ "description": "Fresh momentum on a young coin: a 5-minute push with buyers in control, small size, fast partial profits, a tight trail, a 20-minute clock and a -25% hard stop.",
8
+ "mode": "paper",
9
+ "bankroll": {
10
+ "startUsd": 1000
11
+ },
12
+ "entry": {
13
+ "screen": "liq >= 30K vol5m >= 5K !flag:mint !flag:freeze",
14
+ "ageHours": {
15
+ "min": 0,
16
+ "max": 6
17
+ },
18
+ "safety": {
19
+ "maxTop10Pct": 35,
20
+ "maxDevPct": 5,
21
+ "requireNoMintAuthority": true,
22
+ "requireNoFreezeAuthority": true,
23
+ "maxMcapSplitX": 5,
24
+ "youngVertical": {
25
+ "maxAgeHours": 1,
26
+ "maxH1Pct": 250
27
+ },
28
+ "unknownHolders": "reject"
29
+ },
30
+ "triggers": [
31
+ {
32
+ "kind": "momentum",
33
+ "m5MinPct": 3,
34
+ "buySellMin": 1.2
35
+ }
36
+ ],
37
+ "triggerMode": "any",
38
+ "decide": "agent",
39
+ "candidateTtlSec": 300
40
+ },
41
+ "exits": {
42
+ "default": "scalp",
43
+ "profiles": [
44
+ "builtin:scalp",
45
+ "builtin:swing"
46
+ ]
47
+ },
48
+ "sizing": {
49
+ "mode": "pct",
50
+ "pct": 5,
51
+ "maxPctOfBankroll": 10,
52
+ "maxUsd": 500,
53
+ "minUsd": 5
54
+ },
55
+ "risk": {
56
+ "perTrade": {
57
+ "maxLossPctOfBankroll": 10,
58
+ "assumedLossPctNoStop": 100
59
+ },
60
+ "dailyLossHaltPct": 10,
61
+ "drawdown": {
62
+ "sizeDownAtPct": 15,
63
+ "sizeDownMult": 0.5,
64
+ "recoverBelowPct": 8,
65
+ "haltAtPct": 25
66
+ },
67
+ "maxConcurrent": 2,
68
+ "maxExposurePct": 25,
69
+ "lossStreak": {
70
+ "losses": 3,
71
+ "cooldownMin": 60
72
+ },
73
+ "maxEntriesPerDay": 12,
74
+ "perCoin": {
75
+ "maxEntries": 2,
76
+ "cooldownMin": 10
77
+ }
78
+ },
79
+ "agent": {
80
+ "model": "sonnet",
81
+ "maxSessions": 2,
82
+ "budgetUsdPerSession": 0.5,
83
+ "budgetUsdPerDay": 10,
84
+ "maxTurns": 60,
85
+ "deltaEverySec": 15,
86
+ "decideWithinSec": 90,
87
+ "sessionMaxMin": 240,
88
+ "onTimeout": "skip"
89
+ },
90
+ "execution": {
91
+ "slippageBps": 100,
92
+ "feeBps": 30,
93
+ "networkFeeUsd": 0.02,
94
+ "latencyMs": 3000,
95
+ "maxPriceImpactPct": 8,
96
+ "minExitLiquidityUsd": 2000
97
+ }
98
+ }
@@ -0,0 +1,97 @@
1
+ {
2
+ "kind": "strategy",
3
+ "schema": "dexterm-strategy/1",
4
+ "id": "swing",
5
+ "name": "Swing (intraday trend)",
6
+ "version": "1.0.0",
7
+ "description": "An intraday trend on a coin that has already held a pool for an hour or more: medium size, thirds at +50% and +100%, a 25% trail, a 90-minute review and thesis-break exits instead of a hard stop.",
8
+ "mode": "paper",
9
+ "bankroll": {
10
+ "startUsd": 1000
11
+ },
12
+ "entry": {
13
+ "screen": "liq >= 30K vol1h > 15K !flag:mint !flag:freeze",
14
+ "ageHours": {
15
+ "min": 1,
16
+ "max": 168
17
+ },
18
+ "safety": {
19
+ "maxTop10Pct": 35,
20
+ "maxDevPct": 5,
21
+ "requireNoMintAuthority": true,
22
+ "requireNoFreezeAuthority": true,
23
+ "maxMcapSplitX": 5,
24
+ "youngVertical": {
25
+ "maxAgeHours": 1,
26
+ "maxH1Pct": 250
27
+ },
28
+ "unknownHolders": "reject"
29
+ },
30
+ "triggers": [
31
+ {
32
+ "kind": "screen"
33
+ }
34
+ ],
35
+ "triggerMode": "any",
36
+ "decide": "agent",
37
+ "candidateTtlSec": 300
38
+ },
39
+ "exits": {
40
+ "default": "swing",
41
+ "profiles": [
42
+ "builtin:swing",
43
+ "builtin:runner",
44
+ "builtin:scalp"
45
+ ]
46
+ },
47
+ "sizing": {
48
+ "mode": "pct",
49
+ "pct": 10,
50
+ "maxPctOfBankroll": 15,
51
+ "maxUsd": 500,
52
+ "minUsd": 5
53
+ },
54
+ "risk": {
55
+ "perTrade": {
56
+ "maxLossPctOfBankroll": 10,
57
+ "assumedLossPctNoStop": 100
58
+ },
59
+ "dailyLossHaltPct": 15,
60
+ "drawdown": {
61
+ "sizeDownAtPct": 25,
62
+ "sizeDownMult": 0.5,
63
+ "recoverBelowPct": 15,
64
+ "haltAtPct": 40
65
+ },
66
+ "maxConcurrent": 2,
67
+ "maxExposurePct": 35,
68
+ "lossStreak": {
69
+ "losses": 3,
70
+ "cooldownMin": 60
71
+ },
72
+ "maxEntriesPerDay": 8,
73
+ "perCoin": {
74
+ "maxEntries": 1,
75
+ "cooldownMin": 30
76
+ }
77
+ },
78
+ "agent": {
79
+ "model": "sonnet",
80
+ "maxSessions": 2,
81
+ "budgetUsdPerSession": 0.5,
82
+ "budgetUsdPerDay": 10,
83
+ "maxTurns": 60,
84
+ "deltaEverySec": 15,
85
+ "decideWithinSec": 90,
86
+ "sessionMaxMin": 240,
87
+ "onTimeout": "skip"
88
+ },
89
+ "execution": {
90
+ "slippageBps": 100,
91
+ "feeBps": 30,
92
+ "networkFeeUsd": 0.02,
93
+ "latencyMs": 3000,
94
+ "maxPriceImpactPct": 8,
95
+ "minExitLiquidityUsd": 2000
96
+ }
97
+ }
@@ -0,0 +1,157 @@
1
+ {
2
+ "kind": "strategy",
3
+ "schema": "dexterm-strategy/1",
4
+ "id": "yolo",
5
+ "name": "YOLO full port (HIGH RISK)",
6
+ "version": "1.0.0",
7
+ "description": "HIGH RISK, PAPER only. One early-momentum entry at a time, the biggest size the paper book allows behind it. Holder-safety gates first: LP burned or locked, no mint or freeze authority, the LARP check, minimum liquidity. Take the cost back at about 2x, then a free bag with a loose trail; thesis-break and liquidity-pull exits, a time stop, never the same coin twice. Most entries lose and one rug can zero the wallet.",
8
+ "mode": "paper",
9
+ "highRisk": true,
10
+ "bankroll": {
11
+ "startUsd": 200
12
+ },
13
+ "entry": {
14
+ "screen": "liq >= 25K vol5m >= 5K lplocked >= 90 !flag:mint !flag:freeze",
15
+ "ageHours": {
16
+ "min": 0,
17
+ "max": 2
18
+ },
19
+ "safety": {
20
+ "maxTop10Pct": 30,
21
+ "maxDevPct": 5,
22
+ "requireNoMintAuthority": true,
23
+ "requireNoFreezeAuthority": true,
24
+ "maxMcapSplitX": 3,
25
+ "youngVertical": {
26
+ "maxAgeHours": 2,
27
+ "maxH1Pct": 150
28
+ },
29
+ "unknownHolders": "reject",
30
+ "larp": {
31
+ "maxScore": 49,
32
+ "unknown": "reject"
33
+ }
34
+ },
35
+ "triggers": [
36
+ {
37
+ "kind": "momentum",
38
+ "m5MinPct": 3,
39
+ "buySellMin": 1.3
40
+ }
41
+ ],
42
+ "triggerMode": "any",
43
+ "decide": "agent",
44
+ "candidateTtlSec": 180
45
+ },
46
+ "exits": {
47
+ "default": "yolo",
48
+ "profiles": [
49
+ {
50
+ "kind": "exit-profile",
51
+ "id": "yolo",
52
+ "name": "YOLO (cost back at 2x, free bag)",
53
+ "version": "1.2.0",
54
+ "description": "The whole stake on one young pair. At about 2x, sell the slice that pays back the position cost; the rest rides as a free bag on a loose 50% trail. Liquidity pulls, dev sells and dead volume exit at once; a -50% stop and a 45-minute time stop keep a full-port position from bleeding out slowly.",
55
+ "fit": {
56
+ "summary": "A young pair (0-2 h) with LP burned or locked, no mint or freeze authority, a LARP score below the high band, liquidity >= $25k and a first clean 5-minute push.",
57
+ "minLiquidityUsd": 25000,
58
+ "ageHours": { "min": 0, "max": 2 },
59
+ "maxTop10Pct": 30,
60
+ "signals": ["first clean 5m push with buyers ahead of sellers", "liquidity rising with price", "many distinct buyers, top-2 share low"]
61
+ },
62
+ "sizing": { "maxSizePctOfBankroll": 25 },
63
+ "tpLadder": [],
64
+ "trailingStop": null,
65
+ "costRecovery": { "atPct": 100, "maxSellFrac": 0.6 },
66
+ "bagTrail": { "trailPct": 50 },
67
+ "timeStop": { "minutes": 45, "ifBelowPct": 20, "action": "exit" },
68
+ "hardStop": {
69
+ "enabled": true,
70
+ "atPct": -50,
71
+ "why": "The whole wallet rides on one coin: a -50% stop ends a slow bleed. A rug or a pulled pool still fills near -100%, whatever the stop says."
72
+ },
73
+ "thesisBreak": {
74
+ "liquidityDropPct": 30,
75
+ "liquidityWindowMin": 5,
76
+ "mcapDivergenceX": 5,
77
+ "devSell": { "exitOnAnyDevSell": true, "topHolderSellPctOfBag": 30 },
78
+ "volumeDeath": { "m5TradesBelow": 5, "forMinutes": 20 }
79
+ },
80
+ "reentry": {
81
+ "allowed": false,
82
+ "cooldownMinutes": 0,
83
+ "maxEntriesPerCoinPerSession": 1,
84
+ "requires": "never the same coin twice: a full-port entry is never repeated"
85
+ },
86
+ "carry": { "allowed": false, "requiresTpFilled": 0, "maxRemainderPctOfBankroll": 0 },
87
+ "reprofileTo": [],
88
+ "wake": { "onTpFilled": false, "onTimeReview": false, "drawdownPct": -30, "thesisWarnFrac": 0.6, "noAnswer": "exit", "onCostRecovered": true },
89
+ "maxHoldMinutes": 1440,
90
+ "notes": [
91
+ "The bag trail arms on the cost-recovery sell; before that the stop, the time stop, the thesis breaks and the rug floor exit.",
92
+ "An agent can tighten or exit early, never loosen a stop or a trail."
93
+ ]
94
+ }
95
+ ]
96
+ },
97
+ "sizing": {
98
+ "mode": "pct",
99
+ "pct": 25,
100
+ "maxPctOfBankroll": 25,
101
+ "maxUsd": 1000,
102
+ "minUsd": 5
103
+ },
104
+ "risk": {
105
+ "perTrade": {
106
+ "maxLossPctOfBankroll": 25,
107
+ "assumedLossPctNoStop": 100
108
+ },
109
+ "dailyLossHaltPct": 60,
110
+ "drawdown": {
111
+ "sizeDownAtPct": 50,
112
+ "sizeDownMult": 1,
113
+ "recoverBelowPct": 10,
114
+ "haltAtPct": 80
115
+ },
116
+ "maxConcurrent": 1,
117
+ "maxExposurePct": 100,
118
+ "lossStreak": {
119
+ "losses": 3,
120
+ "cooldownMin": 60
121
+ },
122
+ "maxEntriesPerDay": 6,
123
+ "perCoin": {
124
+ "maxEntries": 1,
125
+ "cooldownMin": 10080
126
+ },
127
+ "recoveredBags": {
128
+ "countAsOpen": true,
129
+ "maxBags": 1
130
+ }
131
+ },
132
+ "agent": {
133
+ "model": "sonnet",
134
+ "maxSessions": 1,
135
+ "budgetUsdPerSession": 0.5,
136
+ "budgetUsdPerDay": 5,
137
+ "maxTurns": 60,
138
+ "deltaEverySec": 15,
139
+ "decideWithinSec": 45,
140
+ "sessionMaxMin": 240,
141
+ "onTimeout": "skip"
142
+ },
143
+ "execution": {
144
+ "slippageBps": 300,
145
+ "feeBps": 30,
146
+ "networkFeeUsd": 0.02,
147
+ "latencyMs": 3000,
148
+ "maxPriceImpactPct": 3,
149
+ "minExitLiquidityUsd": 5000
150
+ },
151
+ "notes": [
152
+ "HIGH RISK. Paper only: dexterm holds no key and places no live order. Experimental; not financial advice. Self-directed only.",
153
+ "Paper: the runner's book caps one position at 25% (the ceiling for every strategy); the replay below measures full port.",
154
+ "Run it: `dexterm autotrade run yolo --paper` (`--replay builtin:yolo-rehearsal --stub` for a short fixture run).",
155
+ "`dexterm autotrade yolo-replay yolo` shows what full-port compounding did on your recorded history: rugs, the loss spread and how often it zeroed the wallet."
156
+ ]
157
+ }
@@ -0,0 +1 @@
1
+ {"schema":"dexterm-autotrade-tape/1","source":"FIXTURE: yolo devnet rehearsal (synthetic)","extractedAt":"2026-10-22T00:00:00.000Z","window":{"from":1792800000000,"to":1792805940000},"note":"REHEARSAL FIXTURE, NOT MARKET DATA. Synthetic price paths written for the yolo devnet rehearsal, on three real, long-lived mainnet mint addresses (so the devnet signer can read their mint and freeze authority and their liquidity). The symbols, prices, ages and liquidity here are made up. Paths: a 3x push with the cost taken back and the bag trailed out; a flat entry the time stop closes; a pool pulled by half (the liquidity-pull exit). Never a performance sample.","columns":["t","kind","price","mcap","mcapResolved","mcapFlagged","liq","vol5m","vol1h","vol24","buys5m","sells5m","buys24","sells24","chg5m","chg1h","chg6h","chg24h","holders","top10","dev","mintAuth","freezeAuth","org"],"mints":[{"mint":"DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263","symbol":"REHA","launchpad":"pump.fun","createdAt":1792798800000,"rows":[[1792800000000,"live",1e-05,10000,10000,0,60000,10800.0,108000.0,540000.0,40,20,800,400,5.0,0.0,0.0,0.0,900,22.5,2.1,0,0,62.0],[1792800060000,"live",1.25e-05,12500,12500,0,66000,11700.0,117000.0,585000.0,45,20,900,400,25.0,25.0,25.0,25.0,905,22.5,2.1,0,0,62.0],[1792800120000,"live",1.5000000000000002e-05,15000,15000,0,72000,11700.0,117000.0,585000.0,45,20,900,400,50.0,50.0,50.0,50.0,910,22.5,2.1,0,0,62.0],[1792800180000,"live",1.7500000000000002e-05,17500,17500,0,78000,11700.0,117000.0,585000.0,45,20,900,400,75.0,75.0,75.0,75.0,915,22.5,2.1,0,0,62.0],[1792800240000,"live",2e-05,20000,20000,0,84000,11700.0,117000.0,585000.0,45,20,900,400,100.0,100.0,100.0,100.0,920,22.5,2.1,0,0,62.0],[1792800300000,"live",2.25e-05,22500,22500,0,90000,11700.0,117000.0,585000.0,45,20,900,400,125.0,125.0,125.0,125.0,925,22.5,2.1,0,0,62.0],[1792800360000,"live",2.5e-05,25000,25000,0,96000,11700.0,117000.0,585000.0,45,20,900,400,100.0,150.0,150.0,150.0,930,22.5,2.1,0,0,62.0],[1792800420000,"live",2.75e-05,27500,27500,0,102000,11700.0,117000.0,585000.0,45,20,900,400,83.33,175.0,175.0,175.0,935,22.5,2.1,0,0,62.0],[1792800480000,"live",3.0000000000000004e-05,30000,30000,0,108000,11700.0,117000.0,585000.0,45,20,900,400,71.43,200.0,200.0,200.0,940,22.5,2.1,0,0,62.0],[1792800540000,"live",2.7899999999999997e-05,27900,27900,0,106000,9900.0,99000.0,495000.0,25,30,500,600,39.5,179.0,179.0,179.0,945,22.5,2.1,0,0,62.0],[1792800600000,"live",2.58e-05,25800,25800,0,104000,9900.0,99000.0,495000.0,25,30,500,600,14.67,158.0,158.0,158.0,950,22.5,2.1,0,0,62.0],[1792800660000,"live",2.37e-05,23700,23700,0,102000,9900.0,99000.0,495000.0,25,30,500,600,-5.2,137.0,137.0,137.0,955,22.5,2.1,0,0,62.0],[1792800720000,"live",2.16e-05,21600,21600,0,100000,9900.0,99000.0,495000.0,25,30,500,600,-21.45,116.0,116.0,116.0,960,22.5,2.1,0,0,62.0],[1792800780000,"live",1.9499999999999996e-05,19500,19500,0,98000,9900.0,99000.0,495000.0,25,30,500,600,-35.0,95.0,95.0,95.0,965,22.5,2.1,0,0,62.0],[1792800840000,"live",1.74e-05,17400,17400,0,96000,9900.0,99000.0,495000.0,25,30,500,600,-37.63,74.0,74.0,74.0,970,22.5,2.1,0,0,62.0],[1792800900000,"live",1.53e-05,15300,15300,0,94000,9900.0,99000.0,495000.0,25,30,500,600,-40.7,53.0,53.0,53.0,975,22.5,2.1,0,0,62.0],[1792800960000,"live",1.3199999999999999e-05,13200,13200,0,92000,9900.0,99000.0,495000.0,25,30,500,600,-44.3,32.0,32.0,32.0,980,22.5,2.1,0,0,62.0],[1792801020000,"live",1.32e-05,13200,13200,0,92000,5400.0,54000.0,270000.0,15,15,300,300,-38.89,32.0,32.0,32.0,985,22.5,2.1,0,0,62.0],[1792801080000,"live",1.32e-05,13200,13200,0,92000,5400.0,54000.0,270000.0,15,15,300,300,-32.31,32.0,32.0,32.0,990,22.5,2.1,0,0,62.0],[1792801140000,"live",1.32e-05,13200,13200,0,92000,5400.0,54000.0,270000.0,15,15,300,300,-24.14,32.0,32.0,32.0,995,22.5,2.1,0,0,62.0],[1792801200000,"live",1.32e-05,13200,13200,0,92000,5400.0,54000.0,270000.0,15,15,300,300,-13.73,32.0,32.0,32.0,1000,22.5,2.1,0,0,62.0]]},{"mint":"7GCihgDB8fe6KNjn2MYtkzZcRjQy3t9GHdC8uHYmW2hr","symbol":"REHC","launchpad":"pump.fun","createdAt":1792800600000,"rows":[[1792801800000,"live",2e-05,20000,20000,0,70000,10800.0,108000.0,540000.0,40,20,800,400,5.0,0.0,0.0,0.0,900,22.5,2.1,0,0,62.0],[1792801860000,"live",2.0600000000000003e-05,20600,20600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,3.0,3.0,3.0,3.0,905,22.5,2.1,0,0,62.0],[1792801920000,"live",1.9600000000000002e-05,19600,19600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,-2.0,-2.0,-2.0,-2.0,910,22.5,2.1,0,0,62.0],[1792801980000,"live",2.0600000000000003e-05,20600,20600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,3.0,3.0,3.0,3.0,915,22.5,2.1,0,0,62.0],[1792802040000,"live",1.9600000000000002e-05,19600,19600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,-2.0,-2.0,-2.0,-2.0,920,22.5,2.1,0,0,62.0],[1792802100000,"live",2.0600000000000003e-05,20600,20600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,3.0,3.0,3.0,3.0,925,22.5,2.1,0,0,62.0],[1792802160000,"live",1.9600000000000002e-05,19600,19600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,-4.85,-2.0,-2.0,-2.0,930,22.5,2.1,0,0,62.0],[1792802220000,"live",2.0600000000000003e-05,20600,20600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,5.1,3.0,3.0,3.0,935,22.5,2.1,0,0,62.0],[1792802280000,"live",1.9600000000000002e-05,19600,19600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,-4.85,-2.0,-2.0,-2.0,940,22.5,2.1,0,0,62.0],[1792802340000,"live",2.0600000000000003e-05,20600,20600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,5.1,3.0,3.0,3.0,945,22.5,2.1,0,0,62.0],[1792802400000,"live",1.9600000000000002e-05,19600,19600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,-4.85,-2.0,-2.0,-2.0,950,22.5,2.1,0,0,62.0],[1792802460000,"live",2.0600000000000003e-05,20600,20600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,5.1,3.0,3.0,3.0,955,22.5,2.1,0,0,62.0],[1792802520000,"live",1.9600000000000002e-05,19600,19600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,-4.85,-2.0,-2.0,-2.0,960,22.5,2.1,0,0,62.0],[1792802580000,"live",2.0600000000000003e-05,20600,20600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,5.1,3.0,3.0,3.0,965,22.5,2.1,0,0,62.0],[1792802640000,"live",1.9600000000000002e-05,19600,19600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,-4.85,-2.0,-2.0,-2.0,970,22.5,2.1,0,0,62.0],[1792802700000,"live",2.0600000000000003e-05,20600,20600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,5.1,3.0,3.0,3.0,975,22.5,2.1,0,0,62.0],[1792802760000,"live",1.9600000000000002e-05,19600,19600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,-4.85,-2.0,-2.0,-2.0,980,22.5,2.1,0,0,62.0],[1792802820000,"live",2.0600000000000003e-05,20600,20600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,5.1,3.0,3.0,3.0,985,22.5,2.1,0,0,62.0],[1792802880000,"live",1.9600000000000002e-05,19600,19600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,-4.85,-2.0,-2.0,-2.0,990,22.5,2.1,0,0,62.0],[1792802940000,"live",2.0600000000000003e-05,20600,20600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,5.1,3.0,3.0,3.0,995,22.5,2.1,0,0,62.0],[1792803000000,"live",1.9600000000000002e-05,19600,19600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,-4.85,-2.0,-2.0,-2.0,1000,22.5,2.1,0,0,62.0],[1792803060000,"live",2.0600000000000003e-05,20600,20600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,5.1,3.0,3.0,3.0,1005,22.5,2.1,0,0,62.0],[1792803120000,"live",1.9600000000000002e-05,19600,19600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,-4.85,-2.0,-2.0,-2.0,1010,22.5,2.1,0,0,62.0],[1792803180000,"live",2.0600000000000003e-05,20600,20600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,5.1,3.0,3.0,3.0,1015,22.5,2.1,0,0,62.0],[1792803240000,"live",1.9600000000000002e-05,19600,19600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,-4.85,-2.0,-2.0,-2.0,1020,22.5,2.1,0,0,62.0],[1792803300000,"live",2.0600000000000003e-05,20600,20600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,5.1,3.0,3.0,3.0,1025,22.5,2.1,0,0,62.0],[1792803360000,"live",1.9600000000000002e-05,19600,19600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,-4.85,-2.0,-2.0,-2.0,1030,22.5,2.1,0,0,62.0],[1792803420000,"live",2.0600000000000003e-05,20600,20600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,5.1,3.0,3.0,3.0,1035,22.5,2.1,0,0,62.0],[1792803480000,"live",1.9600000000000002e-05,19600,19600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,-4.85,-2.0,-2.0,-2.0,1040,22.5,2.1,0,0,62.0],[1792803540000,"live",2.0600000000000003e-05,20600,20600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,5.1,3.0,3.0,3.0,1045,22.5,2.1,0,0,62.0],[1792803600000,"live",1.9600000000000002e-05,19600,19600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,-4.85,-2.0,-2.0,-2.0,1050,22.5,2.1,0,0,62.0],[1792803660000,"live",2.0600000000000003e-05,20600,20600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,5.1,3.0,3.0,3.0,1055,22.5,2.1,0,0,62.0],[1792803720000,"live",1.9600000000000002e-05,19600,19600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,-4.85,-2.0,-2.0,-2.0,1060,22.5,2.1,0,0,62.0],[1792803780000,"live",2.0600000000000003e-05,20600,20600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,5.1,3.0,3.0,3.0,1065,22.5,2.1,0,0,62.0],[1792803840000,"live",1.9600000000000002e-05,19600,19600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,-4.85,-2.0,-2.0,-2.0,1070,22.5,2.1,0,0,62.0],[1792803900000,"live",2.0600000000000003e-05,20600,20600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,5.1,3.0,3.0,3.0,1075,22.5,2.1,0,0,62.0],[1792803960000,"live",1.9600000000000002e-05,19600,19600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,-4.85,-2.0,-2.0,-2.0,1080,22.5,2.1,0,0,62.0],[1792804020000,"live",2.0600000000000003e-05,20600,20600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,5.1,3.0,3.0,3.0,1085,22.5,2.1,0,0,62.0],[1792804080000,"live",1.9600000000000002e-05,19600,19600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,-4.85,-2.0,-2.0,-2.0,1090,22.5,2.1,0,0,62.0],[1792804140000,"live",2.0600000000000003e-05,20600,20600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,5.1,3.0,3.0,3.0,1095,22.5,2.1,0,0,62.0],[1792804200000,"live",1.9600000000000002e-05,19600,19600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,-4.85,-2.0,-2.0,-2.0,1100,22.5,2.1,0,0,62.0],[1792804260000,"live",2.0600000000000003e-05,20600,20600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,5.1,3.0,3.0,3.0,1105,22.5,2.1,0,0,62.0],[1792804320000,"live",1.9600000000000002e-05,19600,19600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,-4.85,-2.0,-2.0,-2.0,1110,22.5,2.1,0,0,62.0],[1792804380000,"live",2.0600000000000003e-05,20600,20600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,5.1,3.0,3.0,3.0,1115,22.5,2.1,0,0,62.0],[1792804440000,"live",1.9600000000000002e-05,19600,19600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,-4.85,-2.0,-2.0,-2.0,1120,22.5,2.1,0,0,62.0],[1792804500000,"live",2.0600000000000003e-05,20600,20600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,5.1,3.0,3.0,3.0,1125,22.5,2.1,0,0,62.0],[1792804560000,"live",1.9600000000000002e-05,19600,19600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,-4.85,-2.0,-2.0,-2.0,1130,22.5,2.1,0,0,62.0],[1792804620000,"live",2.0600000000000003e-05,20600,20600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,5.1,3.0,3.0,3.0,1135,22.5,2.1,0,0,62.0],[1792804680000,"live",1.9600000000000002e-05,19600,19600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,-4.85,-2.0,-2.0,-2.0,1140,22.5,2.1,0,0,62.0],[1792804740000,"live",2.0600000000000003e-05,20600,20600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,5.1,3.0,3.0,3.0,1145,22.5,2.1,0,0,62.0],[1792804800000,"live",1.9600000000000002e-05,19600,19600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,-4.85,-2.0,-2.0,-2.0,1150,22.5,2.1,0,0,62.0],[1792804860000,"live",2.0600000000000003e-05,20600,20600,0,70000,4320.0,43200.0,216000.0,12,12,240,240,5.1,3.0,3.0,3.0,1155,22.5,2.1,0,0,62.0]]},{"mint":"EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm","symbol":"REHB","launchpad":"pump.fun","createdAt":1792804200000,"rows":[[1792805400000,"live",5e-06,5000,5000,0,80000,10800.0,108000.0,540000.0,40,20,800,400,5.0,0.0,0.0,0.0,900,22.5,2.1,0,0,62.0],[1792805460000,"live",5.2e-06,5200,5200,0,81000,9000.0,90000.0,450000.0,30,20,600,400,4.0,4.0,4.0,4.0,905,22.5,2.1,0,0,62.0],[1792805520000,"live",5.1e-06,5100,5100,0,80500,7560.0,75600.0,378000.0,20,22,400,440,2.0,2.0,2.0,2.0,910,22.5,2.1,0,0,62.0],[1792805580000,"live",2.4e-06,2400,2400,0,40000,12600.0,126000.0,630000.0,10,60,200,1200,-52.0,-52.0,-52.0,-52.0,915,22.5,2.1,0,0,62.0],[1792805640000,"live",1.9e-06,1900,1900,0,36000,8640.0,86400.0,432000.0,8,40,160,800,-62.0,-62.0,-62.0,-62.0,920,22.5,2.1,0,0,62.0],[1792805700000,"live",1.8e-06,1800,1800,0,35000,2880.0,28800.0,144000.0,6,10,120,200,-64.0,-64.0,-64.0,-64.0,925,22.5,2.1,0,0,62.0],[1792805760000,"live",1.8e-06,1800,1800,0,35000,2880.0,28800.0,144000.0,6,10,120,200,-65.38,-64.0,-64.0,-64.0,930,22.5,2.1,0,0,62.0],[1792805820000,"live",1.8e-06,1800,1800,0,35000,2880.0,28800.0,144000.0,6,10,120,200,-64.71,-64.0,-64.0,-64.0,935,22.5,2.1,0,0,62.0],[1792805880000,"live",1.8e-06,1800,1800,0,35000,2880.0,28800.0,144000.0,6,10,120,200,-25.0,-64.0,-64.0,-64.0,940,22.5,2.1,0,0,62.0],[1792805940000,"live",1.8e-06,1800,1800,0,35000,2880.0,28800.0,144000.0,6,10,120,200,-5.26,-64.0,-64.0,-64.0,945,22.5,2.1,0,0,62.0]]}]}
@@ -0,0 +1,70 @@
1
+ # dexterm executor reference kit
2
+
3
+ dexterm holds no key and signs nothing. In real mode a strategy sends a **LIVE TRADE FIRE** signal
4
+ (`dexterm-trade-fire/1`) for every buy and sell. **Your own executor** acts on it: a Telegram trading bot you chose,
5
+ or any script.
6
+
7
+ This folder holds three small executors you can wire up in minutes, so you can see the whole path work before
8
+ anything can spend money:
9
+
10
+ | file | channel | how dexterm reaches it |
11
+ |---|---|---|
12
+ | `webhook-executor.mjs` | webhook | `dexterm autotrade signal channels --webhook http://127.0.0.1:8787/signal` |
13
+ | `signal-cmd-executor.mjs` | command hook | `dexterm autotrade signal channels --signal-cmd '["/abs/node","/abs/signal-cmd-executor.mjs","--account","main"]'` |
14
+ | `jsonl-tail-executor.mjs` | JSONL stream | `dexterm autotrade signal channels --jsonl on` (add `--jsonl-signed on` for HMAC lines) |
15
+
16
+ Each one handles every signal the same way:
17
+
18
+ 1. It verifies the HMAC, when you give it the secret file. Without `--secret-file` it acts on unsigned bodies (it says `HMAC NOT checked` when it starts); before you put a real trade into `act()`, run it with `--secret-file` and `--require-hmac`.
19
+ 2. It checks the account id.
20
+ 3. It dedupes by nonce. Delivery is at-least-once, so a repeat is normal, and the seen set survives a restart.
21
+ 4. It ignores anything past `expiresAt` (the TTL).
22
+ 5. It writes a receipt to dexterm's `autotrade/real/receipts.jsonl` and a heartbeat to `autotrade/real/executor.jsonl`.
23
+
24
+ **All of them are DRY RUN.** `act()` in `kit.mjs` only logs what it WOULD do, and the receipt says so:
25
+ status `rejected`, reason `dry-run: would BUY …`. There is no wallet code, no key and no chain call anywhere in this
26
+ kit. Trading for real means replacing `act()` with your own code, or handing the order to your own bot. That is your
27
+ code and your wallet, never dexterm's.
28
+
29
+ ## Five minutes, end to end (paper money only)
30
+
31
+ ```sh
32
+ # 1. a secret for the HMAC (written to a 0600 file, stored in your keychain, never printed)
33
+ dexterm autotrade signal secret generate --out ~/.dexterm-exec.secret
34
+
35
+ # 2. start the kit's webhook executor (dry run) in another terminal
36
+ node webhook-executor.mjs --account main --secret-file ~/.dexterm-exec.secret
37
+
38
+ # 3. point dexterm at it, then prove the round trip
39
+ dexterm autotrade signal channels --webhook http://127.0.0.1:8787/signal
40
+ dexterm autotrade signal test # per channel: delivered, latency, the kit's receipt
41
+ dexterm autotrade executor status # alive · last heartbeat · last receipt · lag
42
+ ```
43
+
44
+ `signal test` sends a signal marked `test: true` that names no mint, so there is nothing in it to trade. The kit
45
+ receipts it as `rejected` (`test signal: received, never traded`).
46
+
47
+ ## Heartbeats and the silence pause
48
+
49
+ dexterm counts a heartbeat, a receipt, or an ack on the webhook or command hook as a sign of life. When it hears
50
+ nothing for longer than your `executorSilenceMin` limit (placeholder: 15 min), a real run **pauses new buy
51
+ signals** and tells you in the run log and on Telegram. Exits keep going out. The kit sends a heartbeat every 60 s
52
+ (`--heartbeat-sec`). Your own executor can append the same line, POST it to the run's loopback listener
53
+ (`--executor-port`), or run `dexterm autotrade executor heartbeat`:
54
+
55
+ ```json
56
+ {"schema":"dexterm-executor-heartbeat/1","at":1761300000000,"executor":"my-bot","accountId":"main","dryRun":false,"lastNonce":42}
57
+ ```
58
+
59
+ ## Receipts
60
+
61
+ A receipt is data only. It moves a real position from `unconfirmed` to executed / rejected / failed. With a fill
62
+ (`priceUsd`, `sizeSol`, `tokens`, `txSig`), dexterm also measures how far the real fill was from its own paper fill:
63
+ slippage, latency, partial fills and rejections. That shows in `dexterm autotrade audit`, `signal status` and
64
+ `dexterm autotrade report`.
65
+
66
+ ```json
67
+ {"schema":"dexterm-trade-receipt/1","signalId":"<the signal's id>","nonce":42,"accountId":"main","status":"executed","at":1761300001200,"fill":{"priceUsd":0.00123,"sizeSol":0.25,"tokens":40650,"txSig":null},"reason":null,"executor":"my-bot"}
68
+ ```
69
+
70
+ See `telegram-bot-recipe.md` for the Telegram trading-bot setup. The bot executes, and dexterm never signs.
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env node
2
+ // dexterm executor reference kit: the JSONL stream tail (task-1654). DRY RUN: logs what it would do; no wallet code.
3
+ //
4
+ // node jsonl-tail-executor.mjs --account main [--stream FILE] [--secret-file FILE --require-hmac] [--once] [--poll-ms 1000]
5
+ //
6
+ // Turn the stream on in dexterm (`dexterm autotrade signal channels --jsonl on`, default file
7
+ // autotrade/real/signals.jsonl). With `--jsonl-signed on` each line is an HMAC envelope this tail verifies; a bare
8
+ // line has no signature, so --require-hmac refuses it. The read offset is saved, so a restart resumes where it was.
9
+ // --once reads what is there and exits (handy for a test).
10
+
11
+ import { closeSync, existsSync, openSync, readFileSync, readSync, statSync, writeFileSync } from 'node:fs';
12
+ import { join } from 'node:path';
13
+ import { SeenStore, args, dextermHome, handle, heartbeat, readSecret, realDir, unwrapLine } from './kit.mjs';
14
+
15
+ const a = args();
16
+ if (!a.account) { console.error('usage: node jsonl-tail-executor.mjs --account ID [--stream FILE] [--secret-file FILE] [--once]'); process.exit(2); }
17
+ const home = a.home || dextermHome();
18
+ const stream = a.stream || join(realDir(home), 'signals.jsonl');
19
+ const offFile = a['offset-file'] || join(realDir(home), 'kit-tail-offset.json');
20
+ const seen = new SeenStore(a.state || join(realDir(home), 'kit-tail-seen.json'));
21
+ const secret = readSecret(a['secret-file']);
22
+ const name = String(a.name || 'kit-jsonl-tail').slice(0, 32);
23
+ const log = (s) => console.log(`[${new Date().toISOString()}] ${s}`);
24
+ let offset = 0;
25
+ try { offset = Number(JSON.parse(readFileSync(offFile, 'utf8')).offset) || 0; } catch { /* from the start */ }
26
+ let carry = '';
27
+
28
+ function poll() {
29
+ if (!existsSync(stream)) return;
30
+ const size = statSync(stream).size;
31
+ if (size < offset) { offset = 0; carry = ''; }
32
+ if (size === offset) return;
33
+ const fd = openSync(stream, 'r');
34
+ const buf = Buffer.alloc(size - offset);
35
+ try { readSync(fd, buf, 0, buf.length, offset); } finally { closeSync(fd); }
36
+ offset = size;
37
+ const lines = (carry + buf.toString('utf8')).split('\n');
38
+ carry = lines.pop() ?? '';
39
+ for (const l of lines) {
40
+ if (!l.trim()) continue;
41
+ const { body, signature } = unwrapLine(l);
42
+ handle(body, { accountId: a.account, secret, requireHmac: !!a['require-hmac'], signature, seen, home, executor: name, log, now: Date.now() });
43
+ }
44
+ writeFileSync(offFile, JSON.stringify({ offset: offset - Buffer.byteLength(carry) }));
45
+ }
46
+
47
+ const beat = () => { try { heartbeat(home, { executor: name, accountId: a.account, lastNonce: seen.maxNonce || null }); } catch (e) { log(`heartbeat failed: ${e.message}`); } };
48
+ poll();
49
+ beat();
50
+ if (!a.once) {
51
+ log(`dexterm kit JSONL tail executor (DRY RUN) on ${stream} · account ${a.account}`);
52
+ const t1 = setInterval(poll, Math.max(100, Number(a['poll-ms'] ?? 1000)));
53
+ const t2 = setInterval(beat, Math.max(5, Number(a['heartbeat-sec'] ?? 60)) * 1000);
54
+ const stop = () => { clearInterval(t1); clearInterval(t2); process.exit(0); };
55
+ process.on('SIGINT', stop);
56
+ process.on('SIGTERM', stop);
57
+ }
@@ -0,0 +1,144 @@
1
+ // dexterm executor reference kit: the shared part (task-1654). Plain Node (22+), no dependencies, no wallet code.
2
+ //
3
+ // Every kit executor does the same five things with a LIVE TRADE FIRE signal (`dexterm-trade-fire/1`):
4
+ // 1. verify the HMAC (`t=<unix s>,v1=<hex sha256 of "<t>.<body>">`) when you gave it the secret file
5
+ // 2. check the shape, and that the signal is for YOUR account id
6
+ // 3. dedupe by nonce and id (delivery is at-least-once: a repeat is normal); the seen set survives a restart
7
+ // 4. honor the TTL: anything past `expiresAt` is ignored, never acted on late
8
+ // 5. write a receipt (`dexterm-trade-receipt/1`) to dexterm's receipts.jsonl, and a heartbeat now and then
9
+ //
10
+ // It is DRY RUN, always: `act()` below only logs what it WOULD do and the receipt says so (status "rejected",
11
+ // reason "dry-run: …"). There is no key, no wallet and no chain call in this kit. To trade for real you replace
12
+ // `act()` with your own executor's code (or hand the order to the Telegram trading bot you chose); dexterm never
13
+ // signs anything.
14
+
15
+ import { createHmac, timingSafeEqual } from 'node:crypto';
16
+ import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync, renameSync } from 'node:fs';
17
+ import { dirname, join } from 'node:path';
18
+ import { homedir } from 'node:os';
19
+
20
+ export const SIGNAL_SCHEMA = 'dexterm-trade-fire/1';
21
+ export const RECEIPT_SCHEMA = 'dexterm-trade-receipt/1';
22
+ export const HEARTBEAT_SCHEMA = 'dexterm-executor-heartbeat/1';
23
+ export const ENVELOPE_SCHEMA = 'dexterm-trade-fire-envelope/1';
24
+ const TOLERANCE_SEC = 300;
25
+ const MINT = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
26
+
27
+ /** `--name value` / `--flag` argv into an object. */
28
+ export function args(argv = process.argv.slice(2)) {
29
+ const o = {};
30
+ for (let i = 0; i < argv.length; i++) {
31
+ const a = argv[i];
32
+ if (!a.startsWith('--')) continue;
33
+ const k = a.slice(2);
34
+ const v = argv[i + 1];
35
+ if (v !== undefined && !v.startsWith('--')) { o[k] = v; i++; } else o[k] = true;
36
+ }
37
+ return o;
38
+ }
39
+
40
+ /** Where dexterm keeps its files (DEXTERM_HOME, else ~/.dexterm). */
41
+ export const dextermHome = (env = process.env) => env.DEXTERM_HOME || join(homedir(), '.dexterm');
42
+ export const realDir = (home) => join(home, 'autotrade', 'real');
43
+
44
+ /** The HMAC secret from a file (`dexterm autotrade signal secret generate --out FILE`), or null. */
45
+ export function readSecret(file) {
46
+ if (!file) return null;
47
+ const v = readFileSync(file, 'utf8').trim();
48
+ return v || null;
49
+ }
50
+
51
+ export function verify(secret, header, body, nowMs = Date.now()) {
52
+ const m = /^t=(\d{1,12}),v1=([0-9a-f]{64})$/.exec(String(header ?? ''));
53
+ if (!m) return { ok: false, why: 'signature-missing' };
54
+ const t = Number(m[1]);
55
+ if (Math.abs(nowMs / 1000 - t) > TOLERANCE_SEC) return { ok: false, why: 'signature-stale' };
56
+ const want = createHmac('sha256', secret).update(`${t}.${body}`).digest();
57
+ const got = Buffer.from(m[2], 'hex');
58
+ return got.length === want.length && timingSafeEqual(got, want) ? { ok: true } : { ok: false, why: 'signature-bad' };
59
+ }
60
+
61
+ /** The seen nonces and ids, in a small JSON file so a restart does not act on a repeat. */
62
+ export class SeenStore {
63
+ constructor(file) { this.file = file; this.seen = new Set(); this.maxNonce = 0; try { const d = JSON.parse(readFileSync(file, 'utf8')); for (const x of d.seen ?? []) this.seen.add(x); this.maxNonce = Number(d.maxNonce) || 0; } catch { /* first run */ } }
64
+ has(s) { return this.seen.has(s.id) || this.seen.has(`n${s.nonce}`); }
65
+ add(s) {
66
+ this.seen.add(s.id); this.seen.add(`n${s.nonce}`); this.maxNonce = Math.max(this.maxNonce, s.nonce);
67
+ const keep = [...this.seen].slice(-4000);
68
+ mkdirSync(dirname(this.file), { recursive: true });
69
+ const tmp = `${this.file}.${process.pid}.tmp`;
70
+ writeFileSync(tmp, JSON.stringify({ seen: keep, maxNonce: this.maxNonce }));
71
+ renameSync(tmp, this.file);
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Check one signal body. Returns { verdict, signal?, why }: verdict is act | duplicate | expired | rejected.
77
+ * `secret` null = no HMAC check (only when you chose not to set one).
78
+ */
79
+ export function check(body, o) {
80
+ const now = o.now ?? Date.now();
81
+ if (o.secret) { const v = verify(o.secret, o.signature, body, now); if (!v.ok) return { verdict: 'rejected', why: v.why }; }
82
+ else if (o.requireHmac) return { verdict: 'rejected', why: 'signature-required' };
83
+ let s;
84
+ try { s = JSON.parse(body); } catch { return { verdict: 'rejected', why: 'not-json' }; }
85
+ if (!s || s.schema !== SIGNAL_SCHEMA || !['trade', 'halted', 'test'].includes(s.type) || !Number.isSafeInteger(s.nonce) || typeof s.id !== 'string') return { verdict: 'rejected', why: 'shape' };
86
+ if (s.paper !== false) return { verdict: 'rejected', why: 'paper-flag' };
87
+ if (s.accountId !== o.accountId) return { verdict: 'rejected', why: 'wrong-account', signal: s };
88
+ if (o.seen.has(s)) return { verdict: 'duplicate', why: 'duplicate', signal: s };
89
+ if (!(now <= s.expiresAt)) return { verdict: 'expired', why: 'expired', signal: s };
90
+ if (s.type === 'trade' && (!MINT.test(s.mint) || (s.side !== 'buy' && s.side !== 'sell'))) return { verdict: 'rejected', why: 'shape', signal: s };
91
+ if (s.type === 'trade' && s.nonce <= o.seen.maxNonce) return { verdict: 'rejected', why: 'nonce-replay', signal: s };
92
+ return { verdict: 'act', why: null, signal: s };
93
+ }
94
+
95
+ /**
96
+ * What the executor does with a fresh signal. DRY RUN: it only says what it WOULD do. Replace this with your own
97
+ * code to trade (your wallet, your bot); keep the rest of the pipeline (verify, dedupe, TTL, receipt) as it is.
98
+ */
99
+ export function act(s) {
100
+ if (s.type === 'test') return { status: 'rejected', reason: 'test signal: received, never traded' };
101
+ if (s.type === 'halted') return { status: null, reason: `halted (${s.reason}): would cancel ${s.outstanding.length} outstanding signal(s)` };
102
+ const what = s.side === 'buy' ? `would BUY ${s.sizeSol} SOL of ${s.symbol} (${s.mint}) with ${s.slippageBps} bps slippage` : `would SELL ${Math.round(s.sellFraction * 1000) / 10}% of ${s.symbol} (${s.mint}): ${s.exitReason}`;
103
+ return { status: 'rejected', reason: `dry-run: ${what}`.slice(0, 120) };
104
+ }
105
+
106
+ /** Append a receipt line to dexterm's receipts.jsonl (the same file `dexterm autotrade receipt` writes). */
107
+ export function writeReceipt(home, s, r, executor, now = Date.now()) {
108
+ const line = { schema: RECEIPT_SCHEMA, signalId: s.id, nonce: s.nonce, accountId: s.accountId, status: r.status, at: now, fill: r.fill ?? null, reason: r.reason ?? null, executor };
109
+ mkdirSync(realDir(home), { recursive: true, mode: 0o700 });
110
+ appendFileSync(join(realDir(home), 'receipts.jsonl'), `${JSON.stringify(line)}\n`, { mode: 0o600 });
111
+ return line;
112
+ }
113
+
114
+ /** Append a heartbeat to dexterm's executor.jsonl: dexterm pauses new buys when it hears nothing for too long. */
115
+ export function heartbeat(home, o) {
116
+ const hb = { schema: HEARTBEAT_SCHEMA, at: o.now ?? Date.now(), executor: o.executor, accountId: o.accountId ?? null, dryRun: true, lastNonce: o.lastNonce ?? null, note: o.note ?? null };
117
+ mkdirSync(realDir(home), { recursive: true, mode: 0o700 });
118
+ appendFileSync(join(realDir(home), 'executor.jsonl'), `${JSON.stringify(hb)}\n`, { mode: 0o600 });
119
+ return hb;
120
+ }
121
+
122
+ /** The whole pipeline for one body: check, act (dry run), receipt, log line. Returns the verdict. */
123
+ export function handle(body, o) {
124
+ const c = check(body, o);
125
+ const s = c.signal;
126
+ if (c.verdict === 'act') {
127
+ o.seen.add(s);
128
+ const r = act(s);
129
+ if (r.status && s.type !== 'halted') writeReceipt(o.home, s, r, o.executor, o.now ?? Date.now());
130
+ o.log(`#${s.nonce} ${s.type}${s.type === 'trade' ? ` ${s.side}` : ''}: ${r.reason}`);
131
+ } else o.log(`${s ? `#${s.nonce} ` : ''}${c.verdict}: ${c.why}`);
132
+ return c;
133
+ }
134
+
135
+ /** A stream line: a bare signal, or a signed envelope (`dexterm autotrade signal channels --jsonl-signed on`). */
136
+ export function unwrapLine(line) {
137
+ try {
138
+ const x = JSON.parse(line);
139
+ if (x && x.schema === ENVELOPE_SCHEMA && typeof x.signal === 'string') return { body: x.signal, signature: x.signature ?? null };
140
+ } catch { /* handled by check() */ }
141
+ return { body: line, signature: null };
142
+ }
143
+
144
+ export const exists = existsSync;