dexbot 1.2.1 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/modules/bitshares-native/lru_cache.d.ts +9 -0
  2. package/dist/modules/bitshares-native/lru_cache.d.ts.map +1 -1
  3. package/dist/modules/bitshares-native/lru_cache.js +12 -0
  4. package/dist/modules/bitshares-native/lru_cache.js.map +1 -1
  5. package/dist/modules/bitshares-native/tx/builder.d.ts +4 -0
  6. package/dist/modules/bitshares-native/tx/builder.d.ts.map +1 -1
  7. package/dist/modules/bitshares-native/tx/builder.js +19 -0
  8. package/dist/modules/bitshares-native/tx/builder.js.map +1 -1
  9. package/dist/modules/bitshares-native/tx/tx_cache.d.ts +7 -0
  10. package/dist/modules/bitshares-native/tx/tx_cache.d.ts.map +1 -1
  11. package/dist/modules/bitshares-native/tx/tx_cache.js +11 -0
  12. package/dist/modules/bitshares-native/tx/tx_cache.js.map +1 -1
  13. package/dist/modules/bitshares_client.d.ts.map +1 -1
  14. package/dist/modules/bitshares_client.js +5 -0
  15. package/dist/modules/bitshares_client.js.map +1 -1
  16. package/dist/modules/constants.d.ts +1 -0
  17. package/dist/modules/constants.d.ts.map +1 -1
  18. package/dist/modules/constants.js +1 -0
  19. package/dist/modules/constants.js.map +1 -1
  20. package/dist/modules/dexbot_class.d.ts +0 -1
  21. package/dist/modules/dexbot_class.d.ts.map +1 -1
  22. package/dist/modules/dexbot_class.js +67 -37
  23. package/dist/modules/dexbot_class.js.map +1 -1
  24. package/dist/modules/dexbot_fill_runtime.d.ts.map +1 -1
  25. package/dist/modules/dexbot_fill_runtime.js +3 -0
  26. package/dist/modules/dexbot_fill_runtime.js.map +1 -1
  27. package/dist/modules/node_manager.d.ts +1 -0
  28. package/dist/modules/node_manager.d.ts.map +1 -1
  29. package/dist/modules/node_manager.js +11 -1
  30. package/dist/modules/node_manager.js.map +1 -1
  31. package/dist/modules/order/accounting.d.ts.map +1 -1
  32. package/dist/modules/order/accounting.js +4 -1
  33. package/dist/modules/order/accounting.js.map +1 -1
  34. package/dist/modules/order/index.d.ts +3 -8
  35. package/dist/modules/order/index.d.ts.map +1 -1
  36. package/dist/modules/order/index.js +3 -10
  37. package/dist/modules/order/index.js.map +1 -1
  38. package/dist/modules/order/manager.d.ts +2 -0
  39. package/dist/modules/order/manager.d.ts.map +1 -1
  40. package/dist/modules/order/manager.js +5 -0
  41. package/dist/modules/order/manager.js.map +1 -1
  42. package/dist/modules/order/strategy.js +1 -1
  43. package/dist/modules/order/strategy.js.map +1 -1
  44. package/dist/modules/order/sync_engine.d.ts.map +1 -1
  45. package/dist/modules/order/sync_engine.js +40 -17
  46. package/dist/modules/order/sync_engine.js.map +1 -1
  47. package/dist/modules/order/utils/math.d.ts +28 -1
  48. package/dist/modules/order/utils/math.d.ts.map +1 -1
  49. package/dist/modules/order/utils/math.js +40 -2
  50. package/dist/modules/order/utils/math.js.map +1 -1
  51. package/dist/modules/utils/math_utils.d.ts +3 -6
  52. package/dist/modules/utils/math_utils.d.ts.map +1 -1
  53. package/dist/modules/utils/math_utils.js +1 -14
  54. package/dist/modules/utils/math_utils.js.map +1 -1
  55. package/dist/{modules/order → scripts}/runner.d.ts +15 -9
  56. package/dist/scripts/runner.d.ts.map +1 -0
  57. package/dist/{modules/order → scripts}/runner.js +24 -45
  58. package/dist/scripts/runner.js.map +1 -0
  59. package/package.json +1 -2
  60. package/scripts/README.md +13 -0
  61. package/dist/modules/cli_whitelist_args.d.ts +0 -6
  62. package/dist/modules/cli_whitelist_args.d.ts.map +0 -1
  63. package/dist/modules/cli_whitelist_args.js +0 -13
  64. package/dist/modules/cli_whitelist_args.js.map +0 -1
  65. package/dist/modules/order/runner.d.ts.map +0 -1
  66. package/dist/modules/order/runner.js.map +0 -1
@@ -134,7 +134,6 @@ class DEXBot {
134
134
  _currentCycleId;
135
135
  _autoCancelOrphanCycleMarker;
136
136
  _autoCancelOrphanSubCount;
137
- _orphanFillsCreditedAt;
138
137
  _consecutiveConsumeFailures;
139
138
  _consumeFailureFirstAt;
140
139
  _reconnectUnregister;
@@ -226,7 +225,6 @@ class DEXBot {
226
225
  this._currentCycleId = 0;
227
226
  this._autoCancelOrphanCycleMarker = null;
228
227
  this._autoCancelOrphanSubCount = 0;
229
- this._orphanFillsCreditedAt = null;
230
228
  // Per-session guard: ghost order IDs successfully cancelled
231
229
  // (avoids spamming the chain with repeated cancel attempts for the same
232
230
  // orphan residual on every fill cycle).
@@ -1070,24 +1068,30 @@ class DEXBot {
1070
1068
  if (trackedFillKey && !this._isNewFillKey(trackedFillKey, processedFillKeys, '[POST-RESET]', fillOp.order_id)) {
1071
1069
  continue;
1072
1070
  }
1073
- const accountingResult = await this._applyReplaySafeTrackedFillAccounting(fill, fillOp, {
1074
- context: 'POST-RESET',
1075
- logger: { log: this._log.bind(this) },
1076
- replayMessage: (op) => `[POST-RESET] Replay detected for ${op.order_id}; skipping duplicate rebalance`
1077
- });
1078
- if (accountingResult.status === 'missing_key') {
1079
- requiresOpenOrdersSync = true;
1080
- continue;
1081
- }
1082
- if (accountingResult.status !== 'applied') {
1083
- continue;
1071
+ this.manager.lockOrders([gridOrder.id]);
1072
+ try {
1073
+ const accountingResult = await this._applyReplaySafeTrackedFillAccounting(fill, fillOp, {
1074
+ context: 'POST-RESET',
1075
+ logger: { log: this._log.bind(this) },
1076
+ replayMessage: (op) => `[POST-RESET] Replay detected for ${op.order_id}; skipping duplicate rebalance`
1077
+ });
1078
+ if (accountingResult.status === 'missing_key') {
1079
+ requiresOpenOrdersSync = true;
1080
+ continue;
1081
+ }
1082
+ if (accountingResult.status !== 'applied') {
1083
+ continue;
1084
+ }
1085
+ // Process this fill through the full rebalance pipeline
1086
+ // This will shift the boundary and place a new order on the filled slot
1087
+ const result = await this._processFillsWithBatching([gridOrder], new Set(), `[POST-RESET] fill ${gridOrder.id}`);
1088
+ if (result.aborted) {
1089
+ this._warn('[POST-RESET] Aborted batch due to illegal state; skipping grid persistence this cycle');
1090
+ continue;
1091
+ }
1084
1092
  }
1085
- // Process this fill through the full rebalance pipeline
1086
- // This will shift the boundary and place a new order on the filled slot
1087
- const result = await this._processFillsWithBatching([gridOrder], new Set(), `[POST-RESET] fill ${gridOrder.id}`);
1088
- if (result.aborted) {
1089
- this._warn('[POST-RESET] Aborted batch due to illegal state; skipping grid persistence this cycle');
1090
- continue;
1093
+ finally {
1094
+ this.manager.unlockOrders([gridOrder.id]);
1091
1095
  }
1092
1096
  }
1093
1097
  if (requiresOpenOrdersSync) {
@@ -1566,10 +1570,12 @@ class DEXBot {
1566
1570
  // fill cycle. It is re-set when orphan fills are credited,
1567
1571
  // and consumed (set to null) on the next fund-invariant check
1568
1572
  // in accounting.ts, which widens tolerance by 5x while set.
1573
+ // Written to this.manager (not this) because accounting.ts
1574
+ // reads from the OrderManager reference (mgr).
1569
1575
  // Also cleared by _performStateRecovery after a fresh chain
1570
1576
  // fetch. The timestamp value itself is not compared against a
1571
1577
  // window — it acts as a consume-on-read boolean.
1572
- this._orphanFillsCreditedAt = null;
1578
+ this.manager._orphanFillsCreditedAt = null;
1573
1579
  while (this._incomingFillQueue.length > 0) {
1574
1580
  const batchStartTime = Date.now();
1575
1581
  // Track max queue depth
@@ -1634,9 +1640,9 @@ class DEXBot {
1634
1640
  requiresOpenOrdersSync = true;
1635
1641
  }
1636
1642
  // Record orphan fill credit timestamp for fund invariant
1637
- // tolerance widening. Accounting checks recency via
1638
- // _checkOrphanFillRecency() instead of a cross-module flag.
1639
- this._orphanFillsCreditedAt = Date.now();
1643
+ // tolerance widening. Written to this.manager because
1644
+ // accounting.ts reads from the OrderManager (mgr).
1645
+ this.manager._orphanFillsCreditedAt = Date.now();
1640
1646
  // Don't add to validFills - we can't do rebalancing without a grid slot
1641
1647
  // But the funds are now credited, preventing fund invariant violation
1642
1648
  continue;
@@ -1644,7 +1650,7 @@ class DEXBot {
1644
1650
  // Process both maker and taker fills for our grid orders
1645
1651
  // Grid validation ensures we only process fills belonging to our account
1646
1652
  // Taker fills are included because the bot may execute market orders or act as taker
1647
- const roleStr = fillOp.is_maker ? 'maker' : 'taker';
1653
+ const roleStr = fillOp.is_maker !== false ? 'maker' : 'taker';
1648
1654
  this.manager.logger.log(`Processing ${roleStr} fill for order ${fillOp.order_id}`, 'debug');
1649
1655
  const fillKey = buildFillKey(fill);
1650
1656
  if (!fillKey) {
@@ -1751,6 +1757,12 @@ class DEXBot {
1751
1757
  const sortedBlocks = [...fillsByBlock.keys()].sort((a, b) => a - b);
1752
1758
  const accumulatedOrders = [];
1753
1759
  let anyRequiresSync = false;
1760
+ // Capture whether any fill was skipped during validation
1761
+ // (e.g. missing history ID) and set the sync flag. The
1762
+ // per-block reset below would lose this state since those
1763
+ // fills were filtered out of validFills and never enter
1764
+ // any block group.
1765
+ const initialRequiresSync = requiresOpenOrdersSync;
1754
1766
  for (const blockNum of sortedBlocks) {
1755
1767
  // Reset requiresOpenOrdersSync per block group so one
1756
1768
  // block's history-id gap doesn't force the next block
@@ -1762,12 +1774,24 @@ class DEXBot {
1762
1774
  if (requiresOpenOrdersSync)
1763
1775
  anyRequiresSync = true;
1764
1776
  }
1765
- requiresOpenOrdersSync = anyRequiresSync;
1777
+ // Preserve both per-block sync flags and the initial flag
1778
+ // from filtered-out fills (missing history ID).
1779
+ requiresOpenOrdersSync = anyRequiresSync || initialRequiresSync;
1766
1780
  if (fillsWithoutBlock.length > 0) {
1767
1781
  this.manager.logger.log(`[FILL-BLOCK] Processing ${fillsWithoutBlock.length} fill(s) without block info`, 'debug');
1768
1782
  const noBlockResult = await processValidFills(fillsWithoutBlock);
1769
1783
  accumulatedOrders.push(...noBlockResult);
1770
1784
  }
1785
+ // If a fill was filtered out during validation (e.g. missing
1786
+ // history ID) and no block group triggered the open-orders
1787
+ // sync, run it now so the grid state is reconciled.
1788
+ if (requiresOpenOrdersSync && !anyRequiresSync) {
1789
+ this.manager.logger.log('[FILL-BLOCK] Running open-orders sync for fills with missing history identifiers', 'warn');
1790
+ const fallbackOrders = await processValidFills([]);
1791
+ accumulatedOrders.push(...fallbackOrders);
1792
+ // Flag consumed — variable goes out of scope on
1793
+ // next while iteration.
1794
+ }
1771
1795
  allFilledOrders = accumulatedOrders;
1772
1796
  // 4. Handle Price Corrections
1773
1797
  if (ordersNeedingCorrection.length > 0) {
@@ -2002,20 +2026,26 @@ class DEXBot {
2002
2026
  if (trackedFillKey && !this._isNewFillKey(trackedFillKey, processedFillKeys, '[BOOTSTRAP]', fillOp.order_id)) {
2003
2027
  continue;
2004
2028
  }
2005
- const accountingResult = await this._applyReplaySafeTrackedFillAccounting(fill, fillOp, {
2006
- context: 'BOOTSTRAP',
2007
- replayMessage: (op) => `[BOOTSTRAP] Replay detected for ${op.order_id}; skipping duplicate bootstrap rebalance`
2008
- });
2009
- if (accountingResult.status === 'missing_key') {
2010
- requiresOpenOrdersSync = true;
2011
- continue;
2029
+ this.manager.lockOrders([gridOrder.id]);
2030
+ try {
2031
+ const accountingResult = await this._applyReplaySafeTrackedFillAccounting(fill, fillOp, {
2032
+ context: 'BOOTSTRAP',
2033
+ replayMessage: (op) => `[BOOTSTRAP] Replay detected for ${op.order_id}; skipping duplicate bootstrap rebalance`
2034
+ });
2035
+ if (accountingResult.status === 'missing_key') {
2036
+ requiresOpenOrdersSync = true;
2037
+ continue;
2038
+ }
2039
+ if (accountingResult.status !== 'applied') {
2040
+ continue;
2041
+ }
2042
+ validFills.push({ ...fill, gridOrder });
2043
+ const fillType = gridOrder.type === ORDER_TYPES.BUY ? 'BUY' : 'SELL';
2044
+ this._log(`[BOOTSTRAP] Fill detected: ${fillType} order (${fillOp.is_maker !== false ? 'maker' : 'taker'})`);
2012
2045
  }
2013
- if (accountingResult.status !== 'applied') {
2014
- continue;
2046
+ finally {
2047
+ this.manager.unlockOrders([gridOrder.id]);
2015
2048
  }
2016
- validFills.push({ ...fill, gridOrder });
2017
- const fillType = gridOrder.type === ORDER_TYPES.BUY ? 'BUY' : 'SELL';
2018
- this._log(`[BOOTSTRAP] Fill detected: ${fillType} order (${fillOp.is_maker ? 'maker' : 'taker'})`);
2019
2049
  }
2020
2050
  if (requiresOpenOrdersSync) {
2021
2051
  this._log('[BOOTSTRAP] Falling back to open-orders sync for fill(s) missing replay-safe history identifiers', 'warn');