dexbot 1.4.24 → 1.5.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 (256) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/README.md +7 -2
  3. package/analysis/README.md +61 -5
  4. package/analysis/ama_fitting/package.json +1 -1
  5. package/analysis/analyze_derivatives.ts +1 -1
  6. package/analysis/bot_key_utils.ts +272 -3
  7. package/analysis/bot_usage/discover_bot_accounts.ts +64 -9
  8. package/analysis/bot_usage/kibana_bot_queries.ts +40 -1
  9. package/analysis/chart_utils.ts +6 -3
  10. package/analysis/grid_correction_check.ts +932 -0
  11. package/analysis/resolve_bot_accounts.ts +199 -0
  12. package/analysis/trade_profitability.ts +36 -8
  13. package/analysis/tradingview/README.md +25 -0
  14. package/analysis/tradingview/analyze_tradingview.ts +2 -2
  15. package/analysis/trend_detection/package.json +1 -1
  16. package/claw/modules/claw_launcher.ts +5 -4
  17. package/claw/modules/credit_runtime_adapter.ts +2 -1
  18. package/claw/modules/dexbot_profiles.ts +4 -3
  19. package/claw/package.json +1 -1
  20. package/claw/runtimes/openclaw-plugin/openclaw.plugin.json +1 -1
  21. package/claw/runtimes/openclaw-plugin/package.json +1 -1
  22. package/claw/tests/test_claw_mcp_transport.ts +2 -2
  23. package/dist/analysis/analyze_derivatives.js +1 -1
  24. package/dist/analysis/bot_key_utils.d.ts +28 -1
  25. package/dist/analysis/bot_key_utils.d.ts.map +1 -1
  26. package/dist/analysis/bot_key_utils.js +385 -3
  27. package/dist/analysis/bot_key_utils.js.map +1 -1
  28. package/dist/analysis/bot_usage/discover_bot_accounts.js +60 -10
  29. package/dist/analysis/bot_usage/discover_bot_accounts.js.map +1 -1
  30. package/dist/analysis/bot_usage/kibana_bot_queries.d.ts +45 -1
  31. package/dist/analysis/bot_usage/kibana_bot_queries.d.ts.map +1 -1
  32. package/dist/analysis/bot_usage/kibana_bot_queries.js +39 -1
  33. package/dist/analysis/bot_usage/kibana_bot_queries.js.map +1 -1
  34. package/dist/analysis/chart_utils.d.ts +2 -1
  35. package/dist/analysis/chart_utils.d.ts.map +1 -1
  36. package/dist/analysis/chart_utils.js +4 -1
  37. package/dist/analysis/chart_utils.js.map +1 -1
  38. package/dist/analysis/grid_correction_check.d.ts +90 -0
  39. package/dist/analysis/grid_correction_check.d.ts.map +1 -0
  40. package/dist/analysis/grid_correction_check.js +901 -0
  41. package/dist/analysis/grid_correction_check.js.map +1 -0
  42. package/dist/analysis/resolve_bot_accounts.d.ts +3 -0
  43. package/dist/analysis/resolve_bot_accounts.d.ts.map +1 -0
  44. package/dist/analysis/resolve_bot_accounts.js +216 -0
  45. package/dist/analysis/resolve_bot_accounts.js.map +1 -0
  46. package/dist/analysis/trade_profitability.d.ts.map +1 -1
  47. package/dist/analysis/trade_profitability.js +40 -8
  48. package/dist/analysis/trade_profitability.js.map +1 -1
  49. package/dist/analysis/tradingview/analyze_tradingview.js +2 -2
  50. package/dist/analysis/tradingview/analyze_tradingview.js.map +1 -1
  51. package/dist/bot.d.ts.map +1 -1
  52. package/dist/bot.js +2 -1
  53. package/dist/bot.js.map +1 -1
  54. package/dist/dexbot.d.ts.map +1 -1
  55. package/dist/dexbot.js +134 -22
  56. package/dist/dexbot.js.map +1 -1
  57. package/dist/market_adapter/ama_signal_runner.js +2 -2
  58. package/dist/market_adapter/inputs/fetch_cex_synthetic_data.js +2 -1
  59. package/dist/market_adapter/inputs/fetch_cex_synthetic_data.js.map +1 -1
  60. package/dist/market_adapter/inputs/fetch_lp_data.d.ts +4 -1
  61. package/dist/market_adapter/inputs/fetch_lp_data.d.ts.map +1 -1
  62. package/dist/market_adapter/inputs/fetch_lp_data.js +3 -2
  63. package/dist/market_adapter/inputs/fetch_lp_data.js.map +1 -1
  64. package/dist/modules/account_bots.d.ts +42 -1
  65. package/dist/modules/account_bots.d.ts.map +1 -1
  66. package/dist/modules/account_bots.js +221 -22
  67. package/dist/modules/account_bots.js.map +1 -1
  68. package/dist/modules/account_orders.d.ts +7 -10
  69. package/dist/modules/account_orders.d.ts.map +1 -1
  70. package/dist/modules/account_orders.js +26 -2
  71. package/dist/modules/account_orders.js.map +1 -1
  72. package/dist/modules/bitshares_client.d.ts +4 -1
  73. package/dist/modules/bitshares_client.d.ts.map +1 -1
  74. package/dist/modules/bitshares_client.js +12 -4
  75. package/dist/modules/bitshares_client.js.map +1 -1
  76. package/dist/modules/bot_settings.d.ts.map +1 -1
  77. package/dist/modules/bot_settings.js +2 -1
  78. package/dist/modules/bot_settings.js.map +1 -1
  79. package/dist/modules/chain_orders.d.ts.map +1 -1
  80. package/dist/modules/chain_orders.js +21 -2
  81. package/dist/modules/chain_orders.js.map +1 -1
  82. package/dist/modules/cli_colors.d.ts +39 -0
  83. package/dist/modules/cli_colors.d.ts.map +1 -0
  84. package/dist/modules/cli_colors.js +42 -0
  85. package/dist/modules/cli_colors.js.map +1 -0
  86. package/dist/modules/config.d.ts.map +1 -1
  87. package/dist/modules/config.js +27 -0
  88. package/dist/modules/config.js.map +1 -1
  89. package/dist/modules/constants.d.ts +14 -1
  90. package/dist/modules/constants.d.ts.map +1 -1
  91. package/dist/modules/constants.js +66 -11
  92. package/dist/modules/constants.js.map +1 -1
  93. package/dist/modules/credit_pricing.d.ts +61 -0
  94. package/dist/modules/credit_pricing.d.ts.map +1 -0
  95. package/dist/modules/credit_pricing.js +237 -0
  96. package/dist/modules/credit_pricing.js.map +1 -0
  97. package/dist/modules/credit_runtime.d.ts +1 -0
  98. package/dist/modules/credit_runtime.d.ts.map +1 -1
  99. package/dist/modules/credit_runtime.js +49 -107
  100. package/dist/modules/credit_runtime.js.map +1 -1
  101. package/dist/modules/dexbot_class.d.ts +25 -0
  102. package/dist/modules/dexbot_class.d.ts.map +1 -1
  103. package/dist/modules/dexbot_class.js +82 -12
  104. package/dist/modules/dexbot_class.js.map +1 -1
  105. package/dist/modules/dexbot_cow_runtime.d.ts +39 -17
  106. package/dist/modules/dexbot_cow_runtime.d.ts.map +1 -1
  107. package/dist/modules/dexbot_cow_runtime.js +875 -134
  108. package/dist/modules/dexbot_cow_runtime.js.map +1 -1
  109. package/dist/modules/dexbot_fill_runtime.d.ts +11 -1
  110. package/dist/modules/dexbot_fill_runtime.d.ts.map +1 -1
  111. package/dist/modules/dexbot_fill_runtime.js +108 -1
  112. package/dist/modules/dexbot_fill_runtime.js.map +1 -1
  113. package/dist/modules/dexbot_maintenance_runtime.d.ts +29 -14
  114. package/dist/modules/dexbot_maintenance_runtime.d.ts.map +1 -1
  115. package/dist/modules/dexbot_maintenance_runtime.js +279 -63
  116. package/dist/modules/dexbot_maintenance_runtime.js.map +1 -1
  117. package/dist/modules/dexbot_startup_runtime.d.ts +1 -0
  118. package/dist/modules/dexbot_startup_runtime.d.ts.map +1 -1
  119. package/dist/modules/dexbot_startup_runtime.js +58 -7
  120. package/dist/modules/dexbot_startup_runtime.js.map +1 -1
  121. package/dist/modules/dexbot_state_recovery.d.ts.map +1 -1
  122. package/dist/modules/dexbot_state_recovery.js +55 -3
  123. package/dist/modules/dexbot_state_recovery.js.map +1 -1
  124. package/dist/modules/fund_registry.d.ts +1 -1
  125. package/dist/modules/fund_registry.js +1 -1
  126. package/dist/modules/graceful_shutdown.d.ts +12 -1
  127. package/dist/modules/graceful_shutdown.d.ts.map +1 -1
  128. package/dist/modules/graceful_shutdown.js +39 -1
  129. package/dist/modules/graceful_shutdown.js.map +1 -1
  130. package/dist/modules/key_store.d.ts.map +1 -1
  131. package/dist/modules/key_store.js +38 -1
  132. package/dist/modules/key_store.js.map +1 -1
  133. package/dist/modules/launcher/adapter_requirement.d.ts +38 -0
  134. package/dist/modules/launcher/adapter_requirement.d.ts.map +1 -0
  135. package/dist/modules/launcher/adapter_requirement.js +141 -0
  136. package/dist/modules/launcher/adapter_requirement.js.map +1 -0
  137. package/dist/modules/launcher/bot_supervisor.d.ts +2 -2
  138. package/dist/modules/launcher/bot_supervisor.d.ts.map +1 -1
  139. package/dist/modules/launcher/bot_supervisor.js +32 -3
  140. package/dist/modules/launcher/bot_supervisor.js.map +1 -1
  141. package/dist/modules/launcher/launch_modes.d.ts.map +1 -1
  142. package/dist/modules/launcher/launch_modes.js +5 -4
  143. package/dist/modules/launcher/launch_modes.js.map +1 -1
  144. package/dist/modules/launcher/monolithic_runtime.d.ts +1 -1
  145. package/dist/modules/launcher/monolithic_runtime.d.ts.map +1 -1
  146. package/dist/modules/launcher/monolithic_runtime.js +12 -8
  147. package/dist/modules/launcher/monolithic_runtime.js.map +1 -1
  148. package/dist/modules/launcher/status_reporting.d.ts +6 -6
  149. package/dist/modules/launcher/status_reporting.d.ts.map +1 -1
  150. package/dist/modules/launcher/status_reporting.js +9 -6
  151. package/dist/modules/launcher/status_reporting.js.map +1 -1
  152. package/dist/modules/order/accounting.d.ts.map +1 -1
  153. package/dist/modules/order/accounting.js +20 -3
  154. package/dist/modules/order/accounting.js.map +1 -1
  155. package/dist/modules/order/export.d.ts +1 -1
  156. package/dist/modules/order/export.js +1 -1
  157. package/dist/modules/order/grid.d.ts +1 -1
  158. package/dist/modules/order/grid.d.ts.map +1 -1
  159. package/dist/modules/order/grid.js +335 -43
  160. package/dist/modules/order/grid.js.map +1 -1
  161. package/dist/modules/order/grid_reconcile.d.ts +4 -2
  162. package/dist/modules/order/grid_reconcile.d.ts.map +1 -1
  163. package/dist/modules/order/grid_reconcile.js +242 -222
  164. package/dist/modules/order/grid_reconcile.js.map +1 -1
  165. package/dist/modules/order/grid_reconcile_internal.d.ts +11 -1
  166. package/dist/modules/order/grid_reconcile_internal.d.ts.map +1 -1
  167. package/dist/modules/order/grid_reconcile_internal.js +132 -6
  168. package/dist/modules/order/grid_reconcile_internal.js.map +1 -1
  169. package/dist/modules/order/logger.d.ts +23 -1
  170. package/dist/modules/order/logger.d.ts.map +1 -1
  171. package/dist/modules/order/logger.js +60 -17
  172. package/dist/modules/order/logger.js.map +1 -1
  173. package/dist/modules/order/manager.d.ts +68 -14
  174. package/dist/modules/order/manager.d.ts.map +1 -1
  175. package/dist/modules/order/manager.js +281 -52
  176. package/dist/modules/order/manager.js.map +1 -1
  177. package/dist/modules/order/strategy.d.ts.map +1 -1
  178. package/dist/modules/order/strategy.js +25 -8
  179. package/dist/modules/order/strategy.js.map +1 -1
  180. package/dist/modules/order/sync_engine.d.ts.map +1 -1
  181. package/dist/modules/order/sync_engine.js +262 -167
  182. package/dist/modules/order/sync_engine.js.map +1 -1
  183. package/dist/modules/order/utils/math.d.ts +47 -5
  184. package/dist/modules/order/utils/math.d.ts.map +1 -1
  185. package/dist/modules/order/utils/math.js +175 -11
  186. package/dist/modules/order/utils/math.js.map +1 -1
  187. package/dist/modules/order/utils/order.d.ts +16 -15
  188. package/dist/modules/order/utils/order.d.ts.map +1 -1
  189. package/dist/modules/order/utils/order.js +199 -32
  190. package/dist/modules/order/utils/order.js.map +1 -1
  191. package/dist/modules/order/utils/slot.d.ts +8 -0
  192. package/dist/modules/order/utils/slot.d.ts.map +1 -0
  193. package/dist/modules/order/utils/slot.js +16 -0
  194. package/dist/modules/order/utils/slot.js.map +1 -0
  195. package/dist/modules/order/utils/system.d.ts +52 -4
  196. package/dist/modules/order/utils/system.d.ts.map +1 -1
  197. package/dist/modules/order/utils/system.js +109 -16
  198. package/dist/modules/order/utils/system.js.map +1 -1
  199. package/dist/modules/order/utils/validate.d.ts +6 -9
  200. package/dist/modules/order/utils/validate.d.ts.map +1 -1
  201. package/dist/modules/order/utils/validate.js +107 -85
  202. package/dist/modules/order/utils/validate.js.map +1 -1
  203. package/dist/modules/order/working_grid.d.ts +5 -0
  204. package/dist/modules/order/working_grid.d.ts.map +1 -1
  205. package/dist/modules/order/working_grid.js +21 -0
  206. package/dist/modules/order/working_grid.js.map +1 -1
  207. package/dist/modules/paths.d.ts +4 -2
  208. package/dist/modules/paths.d.ts.map +1 -1
  209. package/dist/modules/paths.js +79 -24
  210. package/dist/modules/paths.js.map +1 -1
  211. package/dist/modules/utils/chain_logs.d.ts +11 -0
  212. package/dist/modules/utils/chain_logs.d.ts.map +1 -0
  213. package/dist/modules/utils/chain_logs.js +23 -0
  214. package/dist/modules/utils/chain_logs.js.map +1 -0
  215. package/dist/modules/utils/sanitize_key.d.ts +7 -0
  216. package/dist/modules/utils/sanitize_key.d.ts.map +1 -1
  217. package/dist/modules/utils/sanitize_key.js +15 -0
  218. package/dist/modules/utils/sanitize_key.js.map +1 -1
  219. package/dist/pm2.d.ts +11 -1
  220. package/dist/pm2.d.ts.map +1 -1
  221. package/dist/pm2.js +66 -15
  222. package/dist/pm2.js.map +1 -1
  223. package/dist/scripts/analyze-credit.d.ts +4 -0
  224. package/dist/scripts/analyze-credit.d.ts.map +1 -0
  225. package/dist/scripts/analyze-credit.js +760 -0
  226. package/dist/scripts/analyze-credit.js.map +1 -0
  227. package/dist/scripts/analyze-orders.d.ts +1 -10
  228. package/dist/scripts/analyze-orders.d.ts.map +1 -1
  229. package/dist/scripts/analyze-orders.js +34 -36
  230. package/dist/scripts/analyze-orders.js.map +1 -1
  231. package/dist/scripts/generate_market_adapter_whitelist.d.ts +2 -5
  232. package/dist/scripts/generate_market_adapter_whitelist.d.ts.map +1 -1
  233. package/dist/scripts/generate_market_adapter_whitelist.js +83 -1
  234. package/dist/scripts/generate_market_adapter_whitelist.js.map +1 -1
  235. package/dist/scripts/test-credit-renewal.d.ts.map +1 -1
  236. package/dist/scripts/test-credit-renewal.js +37 -5
  237. package/dist/scripts/test-credit-renewal.js.map +1 -1
  238. package/dist/scripts/tv.d.ts +11 -0
  239. package/dist/scripts/tv.d.ts.map +1 -0
  240. package/dist/scripts/tv.js +357 -0
  241. package/dist/scripts/tv.js.map +1 -0
  242. package/dist/scripts/update.js +77 -10
  243. package/dist/scripts/update.js.map +1 -1
  244. package/dist/unlock.d.ts.map +1 -1
  245. package/dist/unlock.js +20 -8
  246. package/dist/unlock.js.map +1 -1
  247. package/docs/DEXBOT_COMPARISON.md +11 -11
  248. package/docs/EVOLUTION.md +10 -8
  249. package/docs/FUND_MOVEMENT_AND_ACCOUNTING.md +1 -1
  250. package/docs/GRID_RECALCULATION.md +6 -0
  251. package/docs/MPA_CREDIT_USAGE.md +3 -1
  252. package/docs/README.md +2 -2
  253. package/docs/WORKFLOW.md +3 -1
  254. package/market_adapter/README.md +10 -0
  255. package/package.json +3 -1
  256. package/scripts/README.md +16 -0
@@ -18,12 +18,16 @@ const { writeJSON } = getStorage();
18
18
  * Q1 — top 100 accounts by limit_order_create count
19
19
  * Q2 — top 100 accounts by limit_order_cancel count
20
20
  * Q3 — top 100 accounts by fill_order count
21
+ * Q4 — top 200 accounts by limit_order_update count (op 77, DEXBot2 fingerprint)
21
22
  * 2. Merge & pre-filter:
22
23
  * creates ≥ MIN_CREATES (grid analysis determines DEXBot candidacy)
23
24
  * 3. Grid analysis (parallel, batches of 5):
24
25
  * Fetch 200 raw orders per candidate → per-session geometric spacing test
25
26
  * 4. BitShares: resolve account IDs → names (batch db.get_objects call)
26
- * 5. Rank by DEX score and print table
27
+ * 5. Rank by DEX score and print table.
28
+ * HIGH tier (80+) is split by op-77 usage:
29
+ * updates ≥ 1 → DEXBot2 (native limit_order_update in-place re-price)
30
+ * updates = 0 → DEXBot1-style (cancel-only, cancel + recreate)
27
31
  *
28
32
  * Usage:
29
33
  * node dist/analysis/bot_usage/discover_bot_accounts.js
@@ -51,6 +55,7 @@ import {
51
55
  buildTopSellerAccountsQuery,
52
56
  buildTopCancellerAccountsQuery,
53
57
  buildTopFilledAccountsQuery,
58
+ buildTopUpdaterAccountsQuery,
54
59
  DEFAULT_CONFIG,
55
60
  } from './kibana_bot_queries.js';
56
61
  import { NODE_MANAGEMENT } from '../../modules/constants.js';
@@ -61,6 +66,7 @@ interface AccountCounts {
61
66
  creates: number;
62
67
  cancels: number;
63
68
  fills: number;
69
+ updates: number;
64
70
  }
65
71
 
66
72
  interface CandidateInfo {
@@ -68,6 +74,8 @@ interface CandidateInfo {
68
74
  creates: number;
69
75
  cancels: number;
70
76
  fills: number;
77
+ updates: number;
78
+ flavor: 'DEXBot2' | 'DEXBot1' | '';
71
79
  cancelRatio: number;
72
80
  fillRate: number;
73
81
  gridScore: number;
@@ -323,18 +331,21 @@ async function run() {
323
331
 
324
332
  console.log('Phase 1: Querying Kibana for top active accounts...');
325
333
 
326
- const [createRes, cancelRes, fillRes]: any[] = await Promise.all([
334
+ const [createRes, cancelRes, fillRes, updateRes]: any[] = await Promise.all([
327
335
  withRetry(() => kibanaSearch(KIBANA_CFG, buildTopSellerAccountsQuery(lookbackH, 200, opts.minCreates)),
328
336
  'top-seller query'),
329
337
  withRetry(() => kibanaSearch(KIBANA_CFG, buildTopCancellerAccountsQuery(lookbackH, 200, 5)),
330
338
  'top-canceller query'),
331
339
  withRetry(() => kibanaSearch(KIBANA_CFG, buildTopFilledAccountsQuery(lookbackH, 200, 3)),
332
340
  'top-fills query'),
341
+ withRetry(() => kibanaSearch(KIBANA_CFG, buildTopUpdaterAccountsQuery(lookbackH, 200, 1)),
342
+ 'top-updater query'),
333
343
  ]);
334
344
 
335
345
  const createBuckets = createRes?.aggregations?.by_account?.buckets ?? [];
336
346
  const cancelBuckets = cancelRes?.aggregations?.by_account?.buckets ?? [];
337
347
  const fillBuckets = fillRes?.aggregations?.by_account?.buckets ?? [];
348
+ const updateBuckets = updateRes?.aggregations?.by_account?.buckets ?? [];
338
349
 
339
350
  if (opts.verbose) {
340
351
  console.log(` [verbose] createRes keys: ${Object.keys(createRes ?? {}).join(', ')}`);
@@ -344,6 +355,7 @@ async function run() {
344
355
  console.log(` Creates: ${createBuckets.length} accounts with ≥${opts.minCreates} creates`);
345
356
  console.log(` Cancels: ${cancelBuckets.length} accounts with ≥5 cancels`);
346
357
  console.log(` Fills: ${fillBuckets.length} accounts with ≥3 fills`);
358
+ console.log(` Updates: ${updateBuckets.length} accounts with ≥1 limit_order_update (op 77)`);
347
359
 
348
360
  if (createBuckets.length === 0) {
349
361
  console.log('');
@@ -360,17 +372,23 @@ async function run() {
360
372
  console.log('\nPhase 2: Merging and filtering candidates...');
361
373
 
362
374
  const accounts: Record<string, AccountCounts> = {};
363
- for (const b of createBuckets) accounts[b.key] = { creates: b.doc_count, cancels: 0, fills: 0 };
375
+ for (const b of createBuckets) accounts[b.key] = { creates: b.doc_count, cancels: 0, fills: 0, updates: 0 };
364
376
  for (const b of cancelBuckets) {
365
- if (!accounts[b.key]) accounts[b.key] = { creates: 0, cancels: 0, fills: 0 };
377
+ if (!accounts[b.key]) accounts[b.key] = { creates: 0, cancels: 0, fills: 0, updates: 0 };
366
378
  accounts[b.key].cancels = b.doc_count;
367
379
  }
368
380
  for (const b of fillBuckets) {
369
- if (!accounts[b.key]) accounts[b.key] = { creates: 0, cancels: 0, fills: 0 };
381
+ if (!accounts[b.key]) accounts[b.key] = { creates: 0, cancels: 0, fills: 0, updates: 0 };
370
382
  accounts[b.key].fills = b.doc_count;
371
383
  }
384
+ for (const b of updateBuckets) {
385
+ if (!accounts[b.key]) accounts[b.key] = { creates: 0, cancels: 0, fills: 0, updates: 0 };
386
+ accounts[b.key].updates = b.doc_count;
387
+ }
372
388
 
373
389
  // Pre-filter: must have creates ≥ minCreates (grid analysis determines DEXBot candidacy)
390
+ // Flavor: any limit_order_update (op 77) in-window → DEXBot2 (native in-place
391
+ // re-price); zero updates → DEXBot1-style (cancel-only: cancel + recreate).
374
392
  const candidates: CandidateInfo[] = (Object.entries(accounts) as [string, AccountCounts][])
375
393
  .filter(([, s]) => s.creates >= opts.minCreates)
376
394
  .map(([id, s]) => ({
@@ -378,6 +396,8 @@ async function run() {
378
396
  creates: s.creates,
379
397
  cancels: s.cancels,
380
398
  fills: s.fills,
399
+ updates: s.updates,
400
+ flavor: (s.updates >= 1 ? 'DEXBot2' : 'DEXBot1') as 'DEXBot2' | 'DEXBot1',
381
401
  cancelRatio: s.cancels / Math.max(s.creates, 1),
382
402
  fillRate: s.creates > 0 ? (s.fills / s.creates * 100) : 0,
383
403
  } as CandidateInfo))
@@ -492,9 +512,41 @@ async function run() {
492
512
  console.log('════════════════════════════════════════════════════════════════════════════════════');
493
513
  console.log('');
494
514
 
495
- // Print by DEX score tier
515
+ // Print by DEX score tier. HIGH tier (80+) splits by update-order usage:
516
+ // DEXBot2 — broadcast limit_order_update (op 77) in-window (in-place re-price)
517
+ // DEXBot1-style — cancel-only, no op 77 (cancel + recreate)
518
+ const highV2 = results.filter(r => r.dexScore >= 80 && r.updates >= 1);
519
+ const highV1 = results.filter(r => r.dexScore >= 80 && r.updates < 1);
520
+
521
+ const hdrHigh = ' # Name ID Creates Fills Cancel Fill% C/C MaxBatch Incr% Grid DEX Updates';
522
+ function printHighGroup(label: string, rows: CandidateInfo[]) {
523
+ if (!rows.length) return;
524
+ console.log(` ── ${label}`);
525
+ console.log('');
526
+ console.log(hdrHigh);
527
+ console.log(' ' + '─'.repeat(hdrHigh.length - 1));
528
+ for (const r of rows) {
529
+ const rank = String(results.indexOf(r) + 1).padStart(2);
530
+ const name = r.name.padEnd(22).slice(0, 22);
531
+ const id = r.id.padEnd(14);
532
+ const creates = String(r.creates).padStart(7);
533
+ const fills = String(r.fills).padStart(6);
534
+ const cancels = String(r.cancels).padStart(7);
535
+ const fr = (r.fillRate.toFixed(1) + '%').padStart(5);
536
+ const cr = r.cancelRatio.toFixed(2).padStart(4);
537
+ const batch = String(r.maxBatch || '-').padStart(9);
538
+ const inc = (r.impliedInc != null ? r.impliedInc.toFixed(2) + '%' : 'n/a').padStart(6);
539
+ const grid = String(r.gridScore).padStart(5);
540
+ const dex = String(r.dexScore).padStart(4);
541
+ const upd = String(r.updates).padStart(7);
542
+ console.log(` ${rank} ${name} ${id} ${creates} ${fills} ${cancels} ${fr} ${cr} ${batch} ${inc} ${grid} ${dex} ${upd}`);
543
+ }
544
+ console.log('');
545
+ }
546
+ printHighGroup('HIGH confidence — DEXBot2 (80+, uses limit_order_update op 77)', highV2);
547
+ printHighGroup('HIGH confidence — DEXBot1-style (80+, cancel-only, no op 77)', highV1);
548
+
496
549
  const tiers = [
497
- { label: 'HIGH confidence (80+) — almost certainly DEXBot/DEXBot2', min: 80, max: 101 },
498
550
  { label: 'MEDIUM confidence (50–79) — likely a grid bot', min: 50, max: 80 },
499
551
  { label: 'LOW confidence (25–49) — some automation detected', min: 25, max: 50 },
500
552
  { label: 'WEAK signal (<25) — create/cancel pattern, no grid', min: 0, max: 25 },
@@ -531,13 +583,13 @@ async function run() {
531
583
 
532
584
  // ── Summary ───────────────────────────────────────────────────────────────
533
585
 
534
- const high = results.filter(r => r.dexScore >= 80).length;
586
+ const high = highV2.length + highV1.length;
535
587
  const medium = results.filter(r => r.dexScore >= 50 && r.dexScore < 80).length;
536
588
  const low = results.filter(r => r.dexScore >= 25 && r.dexScore < 50).length;
537
589
 
538
590
  console.log('════════════════════════════════════════════════════════════════════════════════════');
539
591
  console.log(` Total candidates scanned: ${results.length}`);
540
- console.log(` HIGH (80+): ${high} accounts — almost certainly DEXBot/DEXBot2`);
592
+ console.log(` HIGH (80+): ${high} accounts — DEXBot2: ${highV2.length} (op 77 updates) / DEXBot1-style: ${highV1.length} (cancel-only)`);
541
593
  console.log(` MEDIUM (50+): ${medium} accounts — likely grid bots`);
542
594
  console.log(` LOW (25+): ${low} accounts — weak signal`);
543
595
  console.log('');
@@ -545,6 +597,7 @@ async function run() {
545
597
  console.log(' C/C = cancel/create ratio (grid bots: ~1.0)');
546
598
  console.log(' Incr% = implied grid increment from price spacing');
547
599
  console.log(' Grid = grid quality 0-100 | DEX = DEXBot confidence 0-100');
600
+ console.log(' Updates = limit_order_update (op 77) count — DEXBot2 only; 0 = cancel-only (DEXBot1-style)');
548
601
  console.log('');
549
602
 
550
603
  // ── Export JSON ────────────────────────────────────────────────────────────
@@ -553,9 +606,11 @@ async function run() {
553
606
  const exportData = results.map(r => ({
554
607
  id: r.id,
555
608
  name: r.name,
609
+ flavor: r.flavor,
556
610
  creates: r.creates,
557
611
  fills: r.fills,
558
612
  cancels: r.cancels,
613
+ updates: r.updates,
559
614
  fillPct: r.fillRate,
560
615
  cancelRatio: r.cancelRatio,
561
616
  maxBatch: r.maxBatch,
@@ -32,6 +32,10 @@
32
32
  * limit_order_cancel:
33
33
  * op_object.fee_paying_account — account that cancelled
34
34
  * op_object.order — the order ID cancelled
35
+ *
36
+ * limit_order_update (op 77, DEXBot2-only — native in-place re-price):
37
+ * op_object.seller — account that updated the order
38
+ * op_object.order — the limit order ID updated
35
39
  */
36
40
 
37
41
 
@@ -42,6 +46,11 @@ import { kibanaSearch, DEFAULT_CONFIG as BASE_CONFIG } from '../../market_adapte
42
46
  const OP_LIMIT_ORDER_CREATE = 1;
43
47
  const OP_LIMIT_ORDER_CANCEL = 2;
44
48
  const OP_FILL_ORDER = 4;
49
+ // Native in-place order re-price. Only DEXBot2 broadcasts this (COW UPDATE
50
+ // actions via buildUpdateOrderOp); DEXBot1 (Python staggered_orders) predates
51
+ // it and can only cancel + recreate. Presence of op 77 on an account is the
52
+ // DEXBot2 fingerprint; absence means cancel-only (DEXBot1-style).
53
+ const OP_LIMIT_ORDER_UPDATE = 77;
45
54
 
46
55
  const DEFAULT_CONFIG = {
47
56
  ...BASE_CONFIG,
@@ -166,7 +175,37 @@ function buildTopFilledAccountsQuery(lookbackHours: number, topN: number = 100,
166
175
  };
167
176
  }
168
177
 
178
+ /**
179
+ * Top N accounts by limit_order_update count (seller field, op 77).
180
+ * DEXBot2 fingerprint: only DEXBot2 broadcasts native in-place re-prices
181
+ * (COW UPDATE actions). DEXBot1-style bots never emit op 77 — they cancel
182
+ * (op 2) and recreate (op 1) instead.
183
+ */
184
+ function buildTopUpdaterAccountsQuery(lookbackHours: number, topN: number = 200, minUpdates: number = 1) {
185
+ return {
186
+ size: 0,
187
+ query: {
188
+ bool: {
189
+ filter: [
190
+ { term: { operation_type: OP_LIMIT_ORDER_UPDATE } },
191
+ { range: { 'block_data.block_time': { gte: `now-${lookbackHours}h`, lte: 'now' } } },
192
+ ],
193
+ },
194
+ },
195
+ aggs: {
196
+ by_account: {
197
+ terms: {
198
+ field: 'operation_history.op_object.seller.keyword',
199
+ size: topN,
200
+ min_doc_count: minUpdates,
201
+ order: { _count: 'desc' },
202
+ },
203
+ },
204
+ },
205
+ };
206
+ }
207
+
169
208
  // ─── Exports ──────────────────────────────────────────────────────────────────
170
209
 
171
- export { DEFAULT_CONFIG, kibanaSearch, buildOrderPriceQuery, buildTopSellerAccountsQuery, buildTopCancellerAccountsQuery, buildTopFilledAccountsQuery }
210
+ export { DEFAULT_CONFIG, kibanaSearch, buildOrderPriceQuery, buildTopSellerAccountsQuery, buildTopCancellerAccountsQuery, buildTopFilledAccountsQuery, buildTopUpdaterAccountsQuery, OP_LIMIT_ORDER_UPDATE }
172
211
 
@@ -54,8 +54,11 @@ function toEpochSeconds(ts: any, fallbackIdx: any) {
54
54
  return fallbackIdx * 3600;
55
55
  }
56
56
 
57
- function writeChartFile(filePath: any, html: any) {
58
- const chartDir = path.dirname(filePath);
57
+ function toFileUrl(filePath: any): string {
58
+ return `file://${path.resolve(String(filePath))}`;
59
+ }
60
+
61
+ function writeChartFile(filePath: any, html: any) { const chartDir = path.dirname(filePath);
59
62
  if (!fs.existsSync(chartDir)) ensureDir(chartDir);
60
63
  ensureSiblingUplotAssets(chartDir);
61
64
  // Atomic write (tmp + rename, matching the production storage adapter
@@ -190,5 +193,5 @@ function bindPan(chart) {
190
193
  }
191
194
  `;
192
195
 
193
- export { escapeHtml, serializeJsonForScript, toEpochSeconds, writeChartFile, embedFunctionSources, UPLOT_SHARED_SCRIPT }
196
+ export { escapeHtml, serializeJsonForScript, toEpochSeconds, writeChartFile, toFileUrl, embedFunctionSources, UPLOT_SHARED_SCRIPT }
194
197