dexbot 1.6.3 → 1.6.4

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 (204) hide show
  1. package/CHANGELOG.md +38 -2
  2. package/README.md +11 -7
  3. package/analysis/README.md +18 -12
  4. package/analysis/account_resolver.ts +171 -0
  5. package/analysis/ama_fitting/analyze_lambda_vs_slow.ts +2 -5
  6. package/analysis/ama_fitting/package.json +1 -1
  7. package/analysis/bot_usage/discover_bot_accounts.ts +20 -27
  8. package/analysis/chain_pool.ts +47 -0
  9. package/analysis/chart_utils.ts +33 -20
  10. package/analysis/derivative_chart_generator.ts +2 -3
  11. package/analysis/fills_source.ts +234 -0
  12. package/analysis/grid_correction_check.ts +38 -251
  13. package/analysis/trade_profitability.ts +169 -304
  14. package/analysis/tradingview/README.md +2 -2
  15. package/analysis/tradingview/tradingview_uplot_chart_generator.ts +3 -4
  16. package/analysis/trend_detection/dynamic_weight_chart_generator.ts +2 -3
  17. package/analysis/trend_detection/kalman_chart_generator.ts +2 -3
  18. package/analysis/trend_detection/package.json +1 -1
  19. package/analysis/trend_detection/regime_chart_generator.ts +2 -3
  20. package/analysis/trend_detection/volatility_chart_generator.ts +2 -3
  21. package/claw/package.json +1 -1
  22. package/claw/runtimes/openclaw-plugin/openclaw.plugin.json +1 -1
  23. package/claw/runtimes/openclaw-plugin/package.json +1 -1
  24. package/claw/tests/test_claw_mcp_transport.ts +2 -2
  25. package/dist/analysis/account_resolver.d.ts +43 -0
  26. package/dist/analysis/account_resolver.d.ts.map +1 -0
  27. package/dist/analysis/account_resolver.js +137 -0
  28. package/dist/analysis/account_resolver.js.map +1 -0
  29. package/dist/analysis/ama_fitting/analyze_lambda_vs_slow.d.ts.map +1 -1
  30. package/dist/analysis/ama_fitting/analyze_lambda_vs_slow.js +2 -4
  31. package/dist/analysis/ama_fitting/analyze_lambda_vs_slow.js.map +1 -1
  32. package/dist/analysis/bot_usage/discover_bot_accounts.js +20 -28
  33. package/dist/analysis/bot_usage/discover_bot_accounts.js.map +1 -1
  34. package/dist/analysis/chain_pool.d.ts +10 -0
  35. package/dist/analysis/chain_pool.d.ts.map +1 -0
  36. package/dist/analysis/chain_pool.js +47 -0
  37. package/dist/analysis/chain_pool.js.map +1 -0
  38. package/dist/analysis/chart_utils.d.ts +14 -1
  39. package/dist/analysis/chart_utils.d.ts.map +1 -1
  40. package/dist/analysis/chart_utils.js +32 -22
  41. package/dist/analysis/chart_utils.js.map +1 -1
  42. package/dist/analysis/derivative_chart_generator.d.ts.map +1 -1
  43. package/dist/analysis/derivative_chart_generator.js +2 -3
  44. package/dist/analysis/derivative_chart_generator.js.map +1 -1
  45. package/dist/analysis/fills_source.d.ts +79 -0
  46. package/dist/analysis/fills_source.d.ts.map +1 -0
  47. package/dist/analysis/fills_source.js +186 -0
  48. package/dist/analysis/fills_source.js.map +1 -0
  49. package/dist/analysis/grid_correction_check.d.ts +1 -21
  50. package/dist/analysis/grid_correction_check.d.ts.map +1 -1
  51. package/dist/analysis/grid_correction_check.js +30 -257
  52. package/dist/analysis/grid_correction_check.js.map +1 -1
  53. package/dist/analysis/trade_profitability.d.ts +18 -19
  54. package/dist/analysis/trade_profitability.d.ts.map +1 -1
  55. package/dist/analysis/trade_profitability.js +136 -280
  56. package/dist/analysis/trade_profitability.js.map +1 -1
  57. package/dist/analysis/tradingview/tradingview_uplot_chart_generator.d.ts.map +1 -1
  58. package/dist/analysis/tradingview/tradingview_uplot_chart_generator.js +3 -4
  59. package/dist/analysis/tradingview/tradingview_uplot_chart_generator.js.map +1 -1
  60. package/dist/analysis/trend_detection/dynamic_weight_chart_generator.d.ts.map +1 -1
  61. package/dist/analysis/trend_detection/dynamic_weight_chart_generator.js +2 -3
  62. package/dist/analysis/trend_detection/dynamic_weight_chart_generator.js.map +1 -1
  63. package/dist/analysis/trend_detection/kalman_chart_generator.d.ts.map +1 -1
  64. package/dist/analysis/trend_detection/kalman_chart_generator.js +2 -3
  65. package/dist/analysis/trend_detection/kalman_chart_generator.js.map +1 -1
  66. package/dist/analysis/trend_detection/regime_chart_generator.d.ts.map +1 -1
  67. package/dist/analysis/trend_detection/regime_chart_generator.js +2 -3
  68. package/dist/analysis/trend_detection/regime_chart_generator.js.map +1 -1
  69. package/dist/analysis/trend_detection/volatility_chart_generator.d.ts.map +1 -1
  70. package/dist/analysis/trend_detection/volatility_chart_generator.js +2 -3
  71. package/dist/analysis/trend_detection/volatility_chart_generator.js.map +1 -1
  72. package/dist/market_adapter/lp_chart_core.d.ts.map +1 -1
  73. package/dist/market_adapter/lp_chart_core.js +2 -3
  74. package/dist/market_adapter/lp_chart_core.js.map +1 -1
  75. package/dist/modules/account_bots.d.ts +1 -18
  76. package/dist/modules/account_bots.d.ts.map +1 -1
  77. package/dist/modules/account_bots.js +1 -1
  78. package/dist/modules/account_bots.js.map +1 -1
  79. package/dist/modules/bitshares-native/serial/operations.d.ts +1 -84
  80. package/dist/modules/bitshares-native/serial/operations.d.ts.map +1 -1
  81. package/dist/modules/bitshares-native/serial/operations.js +1 -38
  82. package/dist/modules/bitshares-native/serial/operations.js.map +1 -1
  83. package/dist/modules/cli_colors.d.ts +0 -1
  84. package/dist/modules/cli_colors.d.ts.map +1 -1
  85. package/dist/modules/constants.js +5 -5
  86. package/dist/modules/constants.js.map +1 -1
  87. package/dist/modules/credential_policy.d.ts +1 -25
  88. package/dist/modules/credential_policy.d.ts.map +1 -1
  89. package/dist/modules/credential_policy.js +1 -1
  90. package/dist/modules/credential_policy.js.map +1 -1
  91. package/dist/modules/credential_runtime.d.ts +1 -6
  92. package/dist/modules/credential_runtime.d.ts.map +1 -1
  93. package/dist/modules/credential_runtime.js +1 -1
  94. package/dist/modules/credential_runtime.js.map +1 -1
  95. package/dist/modules/credential_session_cache.d.ts +1 -5
  96. package/dist/modules/credential_session_cache.d.ts.map +1 -1
  97. package/dist/modules/credential_session_cache.js +1 -1
  98. package/dist/modules/credential_session_cache.js.map +1 -1
  99. package/dist/modules/crypto/pure_secp256k1.d.ts +1 -2
  100. package/dist/modules/crypto/pure_secp256k1.d.ts.map +1 -1
  101. package/dist/modules/crypto/pure_secp256k1.js +1 -1
  102. package/dist/modules/crypto/pure_secp256k1.js.map +1 -1
  103. package/dist/modules/dexbot_class.d.ts +8 -7
  104. package/dist/modules/dexbot_class.d.ts.map +1 -1
  105. package/dist/modules/dexbot_class.js +9 -8
  106. package/dist/modules/dexbot_class.js.map +1 -1
  107. package/dist/modules/dexbot_cow_runtime.d.ts +7 -6
  108. package/dist/modules/dexbot_cow_runtime.d.ts.map +1 -1
  109. package/dist/modules/dexbot_cow_runtime.js +8 -7
  110. package/dist/modules/dexbot_cow_runtime.js.map +1 -1
  111. package/dist/modules/dexbot_fill_runtime.d.ts +1 -17
  112. package/dist/modules/dexbot_fill_runtime.d.ts.map +1 -1
  113. package/dist/modules/dexbot_fill_runtime.js +1 -1
  114. package/dist/modules/dexbot_fill_runtime.js.map +1 -1
  115. package/dist/modules/dexbot_maintenance_runtime.d.ts +1 -1
  116. package/dist/modules/dexbot_maintenance_runtime.d.ts.map +1 -1
  117. package/dist/modules/dexbot_maintenance_runtime.js +15 -4
  118. package/dist/modules/dexbot_maintenance_runtime.js.map +1 -1
  119. package/dist/modules/dexbot_state_recovery.d.ts +1 -7
  120. package/dist/modules/dexbot_state_recovery.d.ts.map +1 -1
  121. package/dist/modules/dexbot_state_recovery.js +1 -1
  122. package/dist/modules/dexbot_state_recovery.js.map +1 -1
  123. package/dist/modules/launcher/adapter_requirement.d.ts +1 -5
  124. package/dist/modules/launcher/adapter_requirement.d.ts.map +1 -1
  125. package/dist/modules/launcher/adapter_requirement.js +1 -1
  126. package/dist/modules/launcher/adapter_requirement.js.map +1 -1
  127. package/dist/modules/launcher/bot_supervisor.d.ts +1 -6
  128. package/dist/modules/launcher/bot_supervisor.d.ts.map +1 -1
  129. package/dist/modules/launcher/bot_supervisor.js +1 -1
  130. package/dist/modules/launcher/bot_supervisor.js.map +1 -1
  131. package/dist/modules/launcher/foreign_cred_daemon.d.ts +1 -3
  132. package/dist/modules/launcher/foreign_cred_daemon.d.ts.map +1 -1
  133. package/dist/modules/launcher/foreign_cred_daemon.js +1 -1
  134. package/dist/modules/launcher/foreign_cred_daemon.js.map +1 -1
  135. package/dist/modules/launcher/launch_modes.d.ts +1 -2
  136. package/dist/modules/launcher/launch_modes.d.ts.map +1 -1
  137. package/dist/modules/launcher/launch_modes.js +1 -1
  138. package/dist/modules/launcher/launch_modes.js.map +1 -1
  139. package/dist/modules/launcher/market_adapter_runtime.d.ts +1 -3
  140. package/dist/modules/launcher/market_adapter_runtime.d.ts.map +1 -1
  141. package/dist/modules/launcher/market_adapter_runtime.js +1 -1
  142. package/dist/modules/launcher/market_adapter_runtime.js.map +1 -1
  143. package/dist/modules/launcher/monolithic_runtime.d.ts +1 -5
  144. package/dist/modules/launcher/monolithic_runtime.d.ts.map +1 -1
  145. package/dist/modules/launcher/monolithic_runtime.js +1 -1
  146. package/dist/modules/launcher/monolithic_runtime.js.map +1 -1
  147. package/dist/modules/launcher/status_reporting.d.ts +1 -2
  148. package/dist/modules/launcher/status_reporting.d.ts.map +1 -1
  149. package/dist/modules/launcher/status_reporting.js +1 -1
  150. package/dist/modules/launcher/status_reporting.js.map +1 -1
  151. package/dist/modules/order/export.d.ts +1 -8
  152. package/dist/modules/order/export.d.ts.map +1 -1
  153. package/dist/modules/order/export.js +1 -1
  154. package/dist/modules/order/export.js.map +1 -1
  155. package/dist/modules/order/grid.d.ts +7 -0
  156. package/dist/modules/order/grid.d.ts.map +1 -1
  157. package/dist/modules/order/grid.js +52 -98
  158. package/dist/modules/order/grid.js.map +1 -1
  159. package/dist/modules/order/grid_reconcile_internal.d.ts +1 -10
  160. package/dist/modules/order/grid_reconcile_internal.d.ts.map +1 -1
  161. package/dist/modules/order/grid_reconcile_internal.js +2 -2
  162. package/dist/modules/order/grid_reconcile_internal.js.map +1 -1
  163. package/dist/modules/order/manager.d.ts +10 -2
  164. package/dist/modules/order/manager.d.ts.map +1 -1
  165. package/dist/modules/order/manager.js +17 -6
  166. package/dist/modules/order/manager.js.map +1 -1
  167. package/dist/modules/order/sync_engine.d.ts.map +1 -1
  168. package/dist/modules/order/sync_engine.js +8 -15
  169. package/dist/modules/order/sync_engine.js.map +1 -1
  170. package/dist/modules/order/utils/math.d.ts +1 -10
  171. package/dist/modules/order/utils/math.d.ts.map +1 -1
  172. package/dist/modules/order/utils/math.js +1 -1
  173. package/dist/modules/order/utils/math.js.map +1 -1
  174. package/dist/modules/order/utils/system.d.ts +0 -15
  175. package/dist/modules/order/utils/system.d.ts.map +1 -1
  176. package/dist/modules/order/utils/system.js +2 -2
  177. package/dist/modules/order/utils/system.js.map +1 -1
  178. package/dist/modules/process_discovery.d.ts +0 -3
  179. package/dist/modules/process_discovery.d.ts.map +1 -1
  180. package/dist/modules/process_discovery.js +1 -1
  181. package/dist/modules/process_discovery.js.map +1 -1
  182. package/dist/modules/utils/chain_logs.d.ts +1 -2
  183. package/dist/modules/utils/chain_logs.d.ts.map +1 -1
  184. package/dist/modules/utils/chain_logs.js +1 -1
  185. package/dist/modules/utils/chain_logs.js.map +1 -1
  186. package/dist/scripts/analyze-git.js +2 -2
  187. package/dist/scripts/analyze-git.js.map +1 -1
  188. package/dist/scripts/update.js +46 -31
  189. package/dist/scripts/update.js.map +1 -1
  190. package/docs/BITSHARES_ONBOARDING.md +110 -40
  191. package/docs/COPY_ON_WRITE_MASTER_PLAN.md +10 -207
  192. package/docs/COW_INVARIANTS.md +16 -10
  193. package/docs/DEXBOT_COMPARISON.md +3 -3
  194. package/docs/EVOLUTION.md +75 -30
  195. package/docs/FUND_MOVEMENT_AND_ACCOUNTING.md +6 -6
  196. package/docs/GRID_RECALCULATION.md +14 -6
  197. package/docs/GRID_RECONCILE.md +28 -25
  198. package/docs/LIFECYCLE.md +12 -11
  199. package/docs/README.md +48 -42
  200. package/docs/architecture.md +19 -30
  201. package/docs/developer_guide.md +3 -3
  202. package/package.json +1 -1
  203. package/scripts/git-viewer.sh +1 -1
  204. package/tests/README.md +10 -1
@@ -37,83 +37,23 @@ import fs from 'node:fs';
37
37
  import { pathToFileURL } from 'node:url';
38
38
  import * as KC from '../market_adapter/core/kibana_client.js';
39
39
  import * as C from '../modules/constants.js';
40
- import { loadBotMeta, loadBotSettings, computeBotKey, persistBotAccountId } from './bot_key_utils.js';
40
+ import { loadBotSettings, computeBotKey } from './bot_key_utils.js';
41
+ import { resolveBotAccount } from './account_resolver.js';
42
+ import {
43
+ BTS_ID,
44
+ FillRecord,
45
+ assetPrec,
46
+ assetSymbol,
47
+ fetchAllFills,
48
+ resolveAssetPrecisions,
49
+ toReal,
50
+ } from './fills_source.js';
41
51
 
42
52
  const { kibanaSearch, DEFAULT_CONFIG: BASE_CONFIG } = KC;
43
53
 
44
- const OP_FILL_ORDER = 4;
45
54
  const OP_LIMIT_ORDER_UPDATE = 77;
46
- const BTS_ID = '1.3.0';
47
-
48
- interface AssetInfo { symbol: string; precision: number; }
49
- const ASSETS: Record<string, AssetInfo> = {
50
- '1.3.0': { symbol: 'BTS', precision: 5 },
51
- '1.3.118': { symbol: 'GBP', precision: 4 },
52
- '1.3.119': { symbol: 'JPY', precision: 2 },
53
- '1.3.120': { symbol: 'EUR', precision: 4 },
54
- '1.3.1325': { symbol: 'RUBLE', precision: 5 },
55
- '1.3.2512': { symbol: 'EVRAZ', precision: 4 },
56
- '1.3.3291': { symbol: 'TWENTIX', precision: 5 },
57
- '1.3.4099': { symbol: 'XBTSX.STH', precision: 6 },
58
- '1.3.4156': { symbol: 'XBTSX.DOGE', precision: 5 },
59
- '1.3.4157': { symbol: 'XBTSX.BTC', precision: 8 },
60
- '1.3.4159': { symbol: 'XBTSX.LTC', precision: 8 },
61
- '1.3.4176': { symbol: 'XBTSX.DASH', precision: 8 },
62
- '1.3.4274': { symbol: 'XBTSX.BCH', precision: 8 },
63
- '1.3.4760': { symbol: 'XBTSX.ETH', precision: 7 },
64
- '1.3.5537': { symbol: 'IOB.XRP', precision: 4 },
65
- '1.3.5541': { symbol: 'XBTSX.BNB', precision: 7 },
66
- '1.3.5589': { symbol: 'XBTSX.USDT', precision: 6 },
67
- '1.3.5641': { symbol: 'HONEST.CNY', precision: 4 },
68
- '1.3.5649': { symbol: 'HONEST.USD', precision: 4 },
69
- '1.3.5650': { symbol: 'HONEST.BTC', precision: 8 },
70
- '1.3.5659': { symbol: 'HONEST.ETH', precision: 6 },
71
- '1.3.5870': { symbol: 'XBTSX.FIL', precision: 6 },
72
- '1.3.5887': { symbol: 'XBTSX.RUB', precision: 4 },
73
- '1.3.5902': { symbol: 'XBTSX.USDC', precision: 6 },
74
- '1.3.6013': { symbol: 'XBTSX.HIVE', precision: 6 },
75
- '1.3.6124': { symbol: 'XBTSX.AVAX', precision: 6 },
76
- '1.3.6139': { symbol: 'XBTSX.XAUT', precision: 6 },
77
- '1.3.6166': { symbol: 'XBTSX.MATIC', precision: 5 },
78
- '1.3.6241': { symbol: 'XBTSX.ETC', precision: 7 },
79
- '1.3.6268': { symbol: 'BTWTY.EOS', precision: 4 },
80
- '1.3.6301': { symbol: 'HONEST.MONEY', precision: 8 },
81
- '1.3.6304': { symbol: 'HONEST.ADA', precision: 8 },
82
- '1.3.6305': { symbol: 'HONEST.DOT', precision: 8 },
83
- '1.3.6309': { symbol: 'HONEST.ATOM', precision: 8 },
84
- '1.3.6311': { symbol: 'HONEST.ALGO', precision: 8 },
85
- '1.3.6312': { symbol: 'HONEST.FIL', precision: 8 },
86
- '1.3.6313': { symbol: 'HONEST.EOS', precision: 8 },
87
- '1.3.6315': { symbol: 'HONEST.EUR', precision: 4 },
88
- '1.3.6316': { symbol: 'HONEST.GBP', precision: 4 },
89
- '1.3.6317': { symbol: 'HONEST.JPY', precision: 4 },
90
- '1.3.6444': { symbol: 'IOB.XLM', precision: 4 },
91
- '1.3.6573': { symbol: 'XBTSX.DAI', precision: 6 },
92
- '1.3.6620': { symbol: 'XBTSX.A', precision: 6 },
93
- '1.3.6627': { symbol: 'XBTSX.LINK', precision: 6 },
94
- };
95
- const resolvedPrecisions: Record<string, number> = {};
96
- function assetSymbol(id: string): string { return ASSETS[id]?.symbol ?? id; }
97
- function assetPrec(id: string): number | undefined { return ASSETS[id]?.precision ?? resolvedPrecisions[id]; }
98
- function toReal(amount: number, assetId: string): number {
99
- const p = assetPrec(assetId);
100
- if (p === undefined) return NaN;
101
- return amount / Math.pow(10, p);
102
- }
103
55
 
104
56
  // ─── Types ────────────────────────────────────────────────────────────────────
105
- interface FillRecord {
106
- time: string;
107
- blockNum: number;
108
- opNum: number;
109
- orderId: string;
110
- accountId: string;
111
- pays: { amount: number; asset_id: string };
112
- receives: { amount: number; asset_id: string };
113
- fee: { amount: number; asset_id: string };
114
- isMaker: boolean;
115
- sort: any[];
116
- }
117
57
  interface OrderUpdate {
118
58
  orderId: string;
119
59
  sequence: number;
@@ -230,7 +170,6 @@ Options:
230
170
  --refresh-account Force re-resolution of preferredAccount and update the
231
171
  stored accountId when it changed (default: reuse the
232
172
  stored accountId with no chain lookup)
233
- --node <url> BitShares node URL for account / precision resolution
234
173
  --increment <pct> Grid increment percent (default: from bot config or ${Number((C as any)?.DEFAULT_CONFIG?.incrementPercent ?? 0.5)})
235
174
  --tolerance <pct> Deprecated alias for --increment (kept for compat, prefer --increment)
236
175
  --per-fill Check at fill granularity (default: per-order aggregated)
@@ -271,7 +210,6 @@ function parseArgs() {
271
210
  account: null,
272
211
  lookup: false,
273
212
  refreshAccount: false,
274
- node: C.NODE_MANAGEMENT.DEFAULT_NODES[0],
275
213
  perFill: false,
276
214
  includeCrossPair: false,
277
215
  incrementPercent: null as number | null,
@@ -289,7 +227,6 @@ function parseArgs() {
289
227
  case '--account': opts.account = args[++i]; break;
290
228
  case '--lookup': opts.lookup = true; break;
291
229
  case '--refresh-account': opts.refreshAccount = true; break;
292
- case '--node': opts.node = args[++i]; break;
293
230
  case '--per-fill': opts.perFill = true; break;
294
231
  case '--include-cross-pair': opts.includeCrossPair = true; break;
295
232
  case '--increment': opts.incrementPercent = parseFloat(args[++i]); break;
@@ -346,150 +283,26 @@ function resolveTimeRange(opts: any): { gte: string; lte: string; label: string
346
283
  return { gte, lte, label };
347
284
  }
348
285
 
349
- // ─── Account resolution ───────────────────────────────────────────────────────
350
- async function resolveAccountId(name: string, nodeUrl: string): Promise<string | null> {
351
- const { createReadOnlyClient } = await import('../modules/bitshares-native/index.js');
352
- const client = createReadOnlyClient({ nodes: [nodeUrl] });
353
- const prevLevel = process.env.LOG_LEVEL;
354
- process.env.LOG_LEVEL = 'warn';
355
- try {
356
- await client.connect();
357
- const accounts = await client.db('lookup_account_names', [[name]]);
358
- if (Array.isArray(accounts) && accounts[0]?.id) return accounts[0].id;
359
- return null;
360
- } catch (e: any) {
361
- console.warn(` [warn] Account resolution failed: ${e.message}`);
362
- return null;
363
- } finally {
364
- try { client.disconnect(); } catch (_) {}
365
- process.env.LOG_LEVEL = prevLevel;
366
- }
367
- }
368
-
369
- async function resolveAccountForBot(botKey: string, overrideAccount: string | null, nodeUrl: string, doRefresh: boolean): Promise<{ accountId: string; botMeta: any }> {
370
- const botMeta = loadBotMeta(botKey);
371
- if (!botMeta && !overrideAccount) {
372
- console.error(`Error: bot key '${botKey}' not found in profiles/bots.json and no --account provided.`);
373
- console.error(`Use --list-bots to see available keys, or pass --account <1.2.x> explicitly.`);
374
- process.exit(1);
375
- }
376
- // An explicit --account always wins and is never persisted.
377
- if (overrideAccount) {
378
- if (/^1\.2\.\d+$/.test(String(overrideAccount))) {
379
- return { accountId: String(overrideAccount), botMeta };
380
- }
381
- console.log(` Resolving account name '${overrideAccount}'...`);
382
- const resolvedOverride = await resolveAccountId(String(overrideAccount), nodeUrl);
383
- if (!resolvedOverride) {
384
- console.error(`Error: failed to resolve --account '${overrideAccount}' to 1.2.x`);
385
- process.exit(1);
386
- }
387
- console.log(` → ${resolvedOverride}`);
388
- return { accountId: String(resolvedOverride), botMeta };
389
- }
390
- const prefRaw = botMeta?.preferredAccount != null ? String(botMeta.preferredAccount) : null;
391
- const prefIsId = !!prefRaw && /^1\.2\.\d+$/.test(prefRaw);
392
- const storedId = /^1\.2\.\d+$/.test(String(botMeta?.accountId ?? '')) ? String(botMeta.accountId) : null;
393
- // An explicit 1.2.x preferredAccount is authoritative: the stored accountId
394
- // is a derived cache and must never override it. Self-heal the cache.
395
- if (prefIsId) {
396
- if (storedId && storedId !== prefRaw && persistBotAccountId(botKey, prefRaw as string)) {
397
- console.log(` Updated stale stored accountId ${storedId} → ${prefRaw} from preferredAccount`);
398
- }
399
- return { accountId: prefRaw as string, botMeta };
400
- }
401
- if (!prefRaw) {
402
- console.error(`Error: bot '${botKey}' has no preferredAccount and no --account provided.`);
403
- process.exit(1);
404
- }
405
- // Name + fresh-enough cache + no refresh requested: offline-friendly fast path.
406
- if (storedId && !doRefresh) {
407
- console.log(` Using stored accountId ${storedId} from profiles/bots.json (no lookup needed; pass --refresh-account to re-verify)`);
408
- return { accountId: storedId, botMeta };
409
- }
410
- // No cache, or --refresh-account: resolve the name on-chain.
411
- console.log(` Resolving account name '${prefRaw}'...`);
412
- const resolved = await resolveAccountId(prefRaw, nodeUrl);
413
- if (!resolved) {
414
- console.error(`Error: failed to resolve account name '${prefRaw}' to 1.2.x`);
415
- process.exit(1);
416
- }
417
- console.log(` → ${resolved}`);
418
- if (!storedId && persistBotAccountId(botKey, resolved)) {
419
- console.log(` Stored accountId ${resolved} in profiles/bots.json for '${botKey}'`);
420
- } else if (storedId && storedId !== resolved && persistBotAccountId(botKey, resolved)) {
421
- console.log(` Updated stored accountId ${storedId} → ${resolved} in profiles/bots.json for '${botKey}'`);
422
- } else if (storedId === resolved) {
423
- console.log(` Stored accountId ${resolved} confirmed up to date`);
424
- }
425
- return { accountId: String(resolved), botMeta };
426
- }
427
-
428
- // ─── Asset precision resolution ───────────────────────────────────────────────
429
- async function resolveAssetPrecisions(fills: FillRecord[], nodeUrl: string | null): Promise<void> {
430
- const unknownIds = new Set<string>();
431
- for (const f of fills) {
432
- for (const id of [f.pays.asset_id, f.receives.asset_id, f.fee.asset_id]) {
433
- if (id !== BTS_ID && !(id in ASSETS) && !(id in resolvedPrecisions)) unknownIds.add(id);
434
- }
435
- }
436
- if (unknownIds.size === 0 || !nodeUrl) return;
437
- const ids = [...unknownIds];
438
- console.log(` Resolving ${ids.length} unknown asset(s) from blockchain...`);
439
- const { createReadOnlyClient } = await import('../modules/bitshares-native/index.js');
440
- const client = createReadOnlyClient({ nodes: [nodeUrl] });
441
- try {
442
- await client.connect();
443
- const assets = await client.db('get_assets', [ids]);
444
- if (Array.isArray(assets)) {
445
- for (const asset of assets) {
446
- if (asset?.id && asset.precision != null) {
447
- resolvedPrecisions[asset.id] = asset.precision;
448
- console.log(` ${asset.id} → ${asset.symbol || '?'} (precision ${asset.precision})`);
449
- }
450
- }
451
- }
452
- const missing = ids.filter(id => !(id in resolvedPrecisions));
453
- if (missing.length > 0) console.warn(` [warn] ${missing.length} asset(s) not found on chain: ${missing.join(', ')}`);
454
- } catch (e: any) {
455
- console.warn(` [warn] Asset resolution failed: ${e.message}`);
456
- } finally {
457
- try { client.disconnect(); } catch (_) {}
286
+ // ─── Account resolution errors ────────────────────────────────────────────────
287
+ /** Map a shared account-resolver failure onto this tool's operator-facing hint. */
288
+ function reportAccountFailure(resolved: any, opts: any): void {
289
+ switch (resolved.reason) {
290
+ case 'bot-not-found':
291
+ console.error(`Error: bot key '${opts.botKey}' not found in profiles/bots.json and no --account provided.`);
292
+ console.error('Use --list-bots to see available keys, or pass --account <1.2.x> explicitly.');
293
+ break;
294
+ case 'override-unresolved':
295
+ console.error(`Error: failed to resolve --account '${opts.account}' to 1.2.x`);
296
+ break;
297
+ case 'no-preferred-account':
298
+ console.error(`Error: bot '${opts.botKey}' has no preferredAccount and no --account provided.`);
299
+ break;
300
+ default:
301
+ console.error(`Error: failed to resolve account name '${resolved?.botMeta?.preferredAccount ?? opts.botKey}' to 1.2.x`);
458
302
  }
459
303
  }
460
304
 
461
305
  // ─── Kibana fetch ─────────────────────────────────────────────────────────────
462
- function buildFillQuery(accountId: string, gte: string, lte: string, size: number) {
463
- return {
464
- size,
465
- track_total_hits: false,
466
- _source: [
467
- 'block_data.block_time',
468
- 'block_data.block_num',
469
- 'operation_id_num',
470
- 'operation_history.op_object.pays',
471
- 'operation_history.op_object.receives',
472
- 'operation_history.op_object.fee',
473
- 'operation_history.op_object.order_id',
474
- 'operation_history.op_object.account_id',
475
- 'operation_history.op_object.is_maker',
476
- ],
477
- query: {
478
- bool: {
479
- filter: [
480
- { term: { operation_type: OP_FILL_ORDER } },
481
- { term: { 'operation_history.op_object.account_id.keyword': accountId } },
482
- { range: { 'block_data.block_time': { gte, lte } } },
483
- ],
484
- },
485
- },
486
- sort: [
487
- { 'block_data.block_time': { order: 'asc' } },
488
- { operation_id_num: { order: 'asc' } },
489
- ],
490
- };
491
- }
492
-
493
306
  async function fetchAllOrderUpdates(config: any, accountId: string, gte: string, lte: string): Promise<OrderUpdate[]> {
494
307
  const pageSize = 10000;
495
308
  const updates: OrderUpdate[] = [];
@@ -534,41 +347,6 @@ async function fetchAllOrderUpdates(config: any, accountId: string, gte: string,
534
347
  return updates;
535
348
  }
536
349
 
537
- async function fetchAllFills(config: any, accountId: string, gte: string, lte: string): Promise<FillRecord[]> {
538
- const pageSize = 10000;
539
- const fills: FillRecord[] = [];
540
- let searchAfter: any[] | null = null;
541
- const cfg = { ...BASE_CONFIG, timeout: 60000, ...config };
542
- while (true) {
543
- const query = buildFillQuery(accountId, gte, lte, pageSize);
544
- if (searchAfter) (query as any).search_after = searchAfter;
545
- const result: any = await kibanaSearch(cfg, query);
546
- const hits = result?.hits?.hits ?? [];
547
- if (!hits.length) break;
548
- for (const hit of hits) {
549
- const src = hit?._source;
550
- const op = src?.operation_history?.op_object;
551
- if (!op || !op.pays || !op.receives) continue;
552
- fills.push({
553
- time: src.block_data?.block_time ?? '',
554
- blockNum: src.block_data?.block_num ?? 0,
555
- opNum: Number(src.operation_id_num ?? 0),
556
- orderId: op.order_id ?? '',
557
- accountId: op.account_id ?? '',
558
- pays: { amount: Number(op.pays.amount ?? 0), asset_id: op.pays.asset_id ?? '' },
559
- receives: { amount: Number(op.receives.amount ?? 0), asset_id: op.receives.asset_id ?? '' },
560
- fee: { amount: Number(op.fee?.amount ?? 0), asset_id: op.fee?.asset_id ?? '' },
561
- isMaker: op.is_maker ?? false,
562
- sort: hit.sort,
563
- });
564
- }
565
- if (hits.length < pageSize) break;
566
- searchAfter = hits[hits.length - 1].sort;
567
- if (!Array.isArray(searchAfter)) break;
568
- }
569
- return fills;
570
- }
571
-
572
350
  // ─── Fill classification ─────────────────────────────────────────────────────
573
351
  function classifyFills(fills: FillRecord[]): { trades: TradeFill[]; skipped: number } {
574
352
  const trades: TradeFill[] = [];
@@ -934,7 +712,16 @@ async function main() {
934
712
  console.log(`\nGrid correction check — bot-key: ${opts.botKey}`);
935
713
  console.log(`Range: ${label}`);
936
714
 
937
- const { accountId, botMeta } = await resolveAccountForBot(opts.botKey, opts.account, opts.node, opts.refreshAccount);
715
+ const resolvedAccount = await resolveBotAccount(opts.botKey, {
716
+ overrideAccount: opts.account,
717
+ refresh: opts.refreshAccount,
718
+ });
719
+ if (!resolvedAccount.accountId) {
720
+ reportAccountFailure(resolvedAccount, opts);
721
+ process.exit(1);
722
+ }
723
+ const accountId = resolvedAccount.accountId;
724
+ const botMeta = resolvedAccount.botMeta;
938
725
  console.log(`Account: ${accountId}${botMeta ? ` (${botMeta.assetA}/${botMeta.assetB})` : ''}`);
939
726
  const incrementPercent = resolveIncrementPercent(botMeta, opts.incrementPercent);
940
727
  console.log(`Increment: ${incrementPercent}% (halfInc ${incrementPercent/2}%)${opts.incrementPercent == null && botMeta?.incrementPercent != null ? ' — from bot config' : opts.incrementPercent != null ? ' — from --increment' : ' — default'}`);
@@ -952,7 +739,7 @@ async function main() {
952
739
  process.exit(0);
953
740
  }
954
741
 
955
- await resolveAssetPrecisions(fills, opts.node);
742
+ await resolveAssetPrecisions(fills);
956
743
 
957
744
  const { trades, skipped } = classifyFills(fills);
958
745
  console.log(` Classified ${trades.length} trade(s)${skipped > 0 ? `, ${skipped} skipped (unknown precision)` : ''}`);