dexbot 1.5.0 → 1.5.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.
- package/CHANGELOG.md +44 -0
- package/analysis/ama_fitting/package.json +1 -1
- package/analysis/trend_detection/package.json +1 -1
- package/claw/package.json +1 -1
- package/claw/runtimes/openclaw-plugin/openclaw.plugin.json +1 -1
- package/claw/runtimes/openclaw-plugin/package.json +1 -1
- package/claw/tests/test_claw_mcp_transport.ts +2 -2
- package/dist/dexbot.js +5 -5
- package/dist/dexbot.js.map +1 -1
- package/dist/modules/account_orders.d.ts +7 -1
- package/dist/modules/account_orders.d.ts.map +1 -1
- package/dist/modules/account_orders.js +34 -1
- package/dist/modules/account_orders.js.map +1 -1
- package/dist/modules/constants.d.ts +2 -0
- package/dist/modules/constants.d.ts.map +1 -1
- package/dist/modules/constants.js +12 -0
- package/dist/modules/constants.js.map +1 -1
- package/dist/modules/dexbot_class.d.ts +1 -0
- package/dist/modules/dexbot_class.d.ts.map +1 -1
- package/dist/modules/dexbot_cow_runtime.d.ts +19 -1
- package/dist/modules/dexbot_cow_runtime.d.ts.map +1 -1
- package/dist/modules/dexbot_cow_runtime.js +335 -78
- package/dist/modules/dexbot_cow_runtime.js.map +1 -1
- package/dist/modules/dexbot_fill_runtime.d.ts.map +1 -1
- package/dist/modules/dexbot_fill_runtime.js +7 -1
- package/dist/modules/dexbot_fill_runtime.js.map +1 -1
- package/dist/modules/dexbot_startup_runtime.d.ts +1 -0
- package/dist/modules/dexbot_startup_runtime.d.ts.map +1 -1
- package/dist/modules/dexbot_startup_runtime.js +54 -4
- package/dist/modules/dexbot_startup_runtime.js.map +1 -1
- package/dist/modules/dexbot_state_recovery.d.ts.map +1 -1
- package/dist/modules/dexbot_state_recovery.js +7 -0
- package/dist/modules/dexbot_state_recovery.js.map +1 -1
- package/dist/modules/order/accounting.d.ts +34 -0
- package/dist/modules/order/accounting.d.ts.map +1 -1
- package/dist/modules/order/accounting.js +199 -5
- package/dist/modules/order/accounting.js.map +1 -1
- package/dist/modules/order/export.d.ts +122 -15
- package/dist/modules/order/export.d.ts.map +1 -1
- package/dist/modules/order/export.js +310 -46
- package/dist/modules/order/export.js.map +1 -1
- package/dist/modules/order/grid.d.ts.map +1 -1
- package/dist/modules/order/grid.js +22 -17
- package/dist/modules/order/grid.js.map +1 -1
- package/dist/modules/order/grid_reconcile.d.ts.map +1 -1
- package/dist/modules/order/grid_reconcile.js +7 -3
- package/dist/modules/order/grid_reconcile.js.map +1 -1
- package/dist/modules/order/grid_reconcile_internal.d.ts.map +1 -1
- package/dist/modules/order/grid_reconcile_internal.js +98 -28
- package/dist/modules/order/grid_reconcile_internal.js.map +1 -1
- package/dist/modules/order/manager.d.ts +52 -6
- package/dist/modules/order/manager.d.ts.map +1 -1
- package/dist/modules/order/manager.js +156 -21
- package/dist/modules/order/manager.js.map +1 -1
- package/dist/modules/order/strategy.d.ts.map +1 -1
- package/dist/modules/order/strategy.js +17 -2
- package/dist/modules/order/strategy.js.map +1 -1
- package/dist/modules/order/sync_engine.d.ts.map +1 -1
- package/dist/modules/order/sync_engine.js +213 -17
- package/dist/modules/order/sync_engine.js.map +1 -1
- package/dist/modules/order/utils/math.d.ts +70 -4
- package/dist/modules/order/utils/math.d.ts.map +1 -1
- package/dist/modules/order/utils/math.js +136 -5
- package/dist/modules/order/utils/math.js.map +1 -1
- package/dist/modules/order/utils/order.d.ts +117 -5
- package/dist/modules/order/utils/order.d.ts.map +1 -1
- package/dist/modules/order/utils/order.js +274 -13
- package/dist/modules/order/utils/order.js.map +1 -1
- package/dist/modules/order/utils/system.d.ts +14 -0
- package/dist/modules/order/utils/system.d.ts.map +1 -1
- package/dist/modules/order/utils/system.js +51 -3
- package/dist/modules/order/utils/system.js.map +1 -1
- package/dist/modules/order/utils/validate.d.ts +29 -2
- package/dist/modules/order/utils/validate.d.ts.map +1 -1
- package/dist/modules/order/utils/validate.js +207 -35
- package/dist/modules/order/utils/validate.js.map +1 -1
- package/dist/scripts/analyze-credit.d.ts.map +1 -1
- package/dist/scripts/analyze-credit.js +53 -33
- package/dist/scripts/analyze-credit.js.map +1 -1
- package/docs/DEXBOT_COMPARISON.md +3 -3
- package/docs/EVOLUTION.md +7 -5
- package/docs/FUND_MOVEMENT_AND_ACCOUNTING.md +3 -1
- package/docs/GRID_RECONCILE.md +1 -0
- package/docs/LOGGING.md +3 -0
- package/docs/README.md +2 -2
- package/docs/WORKFLOW.md +1 -1
- package/package.json +1 -1
|
@@ -19,7 +19,18 @@ declare class COWRebalanceEngine {
|
|
|
19
19
|
assets: any;
|
|
20
20
|
config: any;
|
|
21
21
|
constructor(deps: any);
|
|
22
|
-
execute({ masterGrid, gridVersion, boundaryIdx, funds, fills, excludeIds }: any): Promise<{
|
|
22
|
+
execute({ masterGrid, gridVersion, boundaryIdx, funds, fills, excludeIds, gapSlots, evacStreaks }: any): Promise<{
|
|
23
|
+
actions: never[];
|
|
24
|
+
stateUpdates: never[];
|
|
25
|
+
hadRotation: boolean;
|
|
26
|
+
workingGrid: null;
|
|
27
|
+
workingIndexes: null;
|
|
28
|
+
workingBoundary: null;
|
|
29
|
+
planningDuration: number;
|
|
30
|
+
aborted: boolean;
|
|
31
|
+
reason: any;
|
|
32
|
+
} | {
|
|
33
|
+
evacReady: any;
|
|
23
34
|
actions: any;
|
|
24
35
|
stateUpdates: any;
|
|
25
36
|
hadRotation: any;
|
|
@@ -138,6 +149,8 @@ declare class OrderManager {
|
|
|
138
149
|
_lastFilledSellPrice: number | null;
|
|
139
150
|
_lastFilledPrice: number | null;
|
|
140
151
|
_lastFilledType: string | null;
|
|
152
|
+
_gapEvacStreaks: Map<string, number>;
|
|
153
|
+
_gapEvacCancelQueued: Set<string>;
|
|
141
154
|
_metrics: any;
|
|
142
155
|
private _currentWorkingGridStack;
|
|
143
156
|
_cowEngine: any;
|
|
@@ -565,17 +578,23 @@ declare class OrderManager {
|
|
|
565
578
|
*/
|
|
566
579
|
_logBoundaryDebug(source: string, newIdx: number | null): void;
|
|
567
580
|
/**
|
|
568
|
-
* Record last filled price for
|
|
569
|
-
*
|
|
570
|
-
*
|
|
581
|
+
* Record last filled price for the single-pivot guard: when armed, BOTH
|
|
582
|
+
* sides are gated against the most recent fill price (BUY blocked above
|
|
583
|
+
* pivot*(1-halfInc), SELL blocked below pivot*(1+halfInc); see
|
|
584
|
+
* isLastFillGuardBlocked). Spread-correction bypasses. _lastFilledType is
|
|
585
|
+
* purely the cold/armed discriminator (null => disabled). The per-side
|
|
586
|
+
* fields are not read by the guard itself; they feed the book-seed
|
|
587
|
+
* cold-check and per-side seeding in seedLastFilledPricesFromBook.
|
|
571
588
|
* @param {Array} fills
|
|
572
589
|
*/
|
|
573
590
|
recordLastFilledPrices(fills: any): void;
|
|
574
591
|
/**
|
|
575
592
|
* Seed last-filled guard from the live book at startup. Book-derived
|
|
576
593
|
* (survives restart), analogous to the deleted MarketAnchor book-seed.
|
|
577
|
-
*
|
|
578
|
-
*
|
|
594
|
+
* A single-sided book arms the guard immediately; a two-sided book
|
|
595
|
+
* deliberately stays cold (type null) until the first real fill, because
|
|
596
|
+
* book quotes are not fills and the latest-fill side is unknowable from
|
|
597
|
+
* the book alone.
|
|
579
598
|
* @param {Array} chainOpenOrders - raw chain open orders (from readOpenOrdersGuarded)
|
|
580
599
|
*/
|
|
581
600
|
seedLastFilledPricesFromBook(chainOpenOrders: any): void;
|
|
@@ -644,6 +663,7 @@ declare class OrderManager {
|
|
|
644
663
|
actions: any[];
|
|
645
664
|
aborted: boolean;
|
|
646
665
|
boundaryIdx: any;
|
|
666
|
+
evacReady: any[];
|
|
647
667
|
summary: {
|
|
648
668
|
total: any;
|
|
649
669
|
creates: any;
|
|
@@ -651,6 +671,32 @@ declare class OrderManager {
|
|
|
651
671
|
updates: any;
|
|
652
672
|
};
|
|
653
673
|
};
|
|
674
|
+
/**
|
|
675
|
+
* Phase 3 safety net — turn stuck gap-evacuation candidates (evacReady
|
|
676
|
+
* from the COW reconcile streak tick) into cancel-only corrections.
|
|
677
|
+
*
|
|
678
|
+
* Gate chain per candidate, in order:
|
|
679
|
+
* 1. Slot idx is STILL genuinely in-band under the CURRENT committed
|
|
680
|
+
* boundary/gap geometry (the plan's frozen geometry may be stale).
|
|
681
|
+
* 2. Streak >= GRID_LIMITS.GAP_EVACUATION_CANCEL_THRESHOLD (warn fires
|
|
682
|
+
* one cycle earlier at GAP_EVACUATION_STREAK_THRESHOLD).
|
|
683
|
+
* 3. Queued-once marker (_gapEvacCancelQueued) not set — a queued entry
|
|
684
|
+
* never re-queues until the slot resolves (leaves the band and its
|
|
685
|
+
* streak entry is dropped).
|
|
686
|
+
* 4. No correction entry already exists for the same chain order.
|
|
687
|
+
* 5. The live slot still exists, is on-chain, and still owns that
|
|
688
|
+
* chain order id.
|
|
689
|
+
*
|
|
690
|
+
* The entry uses isSurplus semantics (not bare cancelOnly): the runner
|
|
691
|
+
* cancels the chain order AND settles the slot back to a spread
|
|
692
|
+
* placeholder via convertToSpreadPlaceholder, keeping fund tracking
|
|
693
|
+
* honest and matching Phase 2 band semantics (genuinely in-band slots
|
|
694
|
+
* are SPREAD VIRTUAL). No re-placement, fee-light.
|
|
695
|
+
*
|
|
696
|
+
* @param {Array} candidates - evacReady candidates [{id, idx, type, price, size, orderId}]
|
|
697
|
+
* @returns {number} Number of corrections queued
|
|
698
|
+
*/
|
|
699
|
+
_processGapEvacuationTeeth(candidates: any): number;
|
|
654
700
|
/**
|
|
655
701
|
* Wait (bounded) until any non-COW broadcast/placement activity — the
|
|
656
702
|
* refcounted _broadcastingFlag — has released. Startup/structural
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../../modules/order/manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;
|
|
1
|
+
{"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../../modules/order/manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -26,10 +26,10 @@ import StrategyEngine from './strategy.js';
|
|
|
26
26
|
import SyncEngine from './sync_engine.js';
|
|
27
27
|
import { calculateCurrentSpread, checkSpreadCondition, checkGridHealth } from './grid.js';
|
|
28
28
|
import * as Format from './format.js';
|
|
29
|
-
import { ORDER_TYPES, ORDER_STATES, REBALANCE_STATES, DEFAULT_CONFIG, TIMING, LOG_LEVEL, PIPELINE_TIMING, COW_PERFORMANCE, COW_ACTIONS } from '../constants.js';
|
|
29
|
+
import { ORDER_TYPES, ORDER_STATES, REBALANCE_STATES, DEFAULT_CONFIG, TIMING, LOG_LEVEL, PIPELINE_TIMING, COW_PERFORMANCE, COW_ACTIONS, GRID_LIMITS } from '../constants.js';
|
|
30
30
|
import { getMinOrderSize, computeChainFundTotals, hasValidAccountTotals, resolveConfigValueWithRegistry, isExplicitZeroAllocation, floatToBlockchainInt, validateBoundaryCommit, resolveGapSlots } from './utils/math.js';
|
|
31
31
|
import { validateOrder, validateGridForPersistence, validateWorkingGridFunds, checkFundDrift, reconcileGrid, optimizeRebalanceActions, projectTargetToWorkingGrid, buildStateUpdates, buildAbortedResult, buildSuccessResult, evaluateCommit } from './utils/validate.js';
|
|
32
|
-
import { resolveSpreadOrderSide, parseSlotIndex, parseChainOrder } from './utils/order.js';
|
|
32
|
+
import { resolveSpreadOrderSide, parseSlotIndex, parseChainOrder, geometryTypeForSlotIndex, isOrderOnChain } from './utils/order.js';
|
|
33
33
|
import { getErrorMessage } from '../utils/errors.js';
|
|
34
34
|
const { toFiniteNumber } = Format;
|
|
35
35
|
// ===============================================================================
|
|
@@ -133,7 +133,7 @@ class COWRebalanceEngine {
|
|
|
133
133
|
this.assets = deps.assets;
|
|
134
134
|
this.config = deps.config;
|
|
135
135
|
}
|
|
136
|
-
async execute({ masterGrid, gridVersion, boundaryIdx, funds, fills = [], excludeIds = new Set() }) {
|
|
136
|
+
async execute({ masterGrid, gridVersion, boundaryIdx, funds, fills = [], excludeIds = new Set(), gapSlots = null, evacStreaks = null }) {
|
|
137
137
|
const startTime = Date.now();
|
|
138
138
|
const workingGrid = new WorkingGrid(masterGrid, { baseVersion: gridVersion });
|
|
139
139
|
const strategyParams = {
|
|
@@ -149,13 +149,28 @@ class COWRebalanceEngine {
|
|
|
149
149
|
let dustThresholdPercent = this.config?.gridLimits?.PARTIAL_DUST_THRESHOLD_PERCENTAGE;
|
|
150
150
|
const reconcileResult = reconcileGrid(masterGrid, targetGrid, targetBoundary, {
|
|
151
151
|
logger: (msg, level) => this.logger?.log(msg, level),
|
|
152
|
-
dustThresholdPercent
|
|
152
|
+
dustThresholdPercent,
|
|
153
|
+
gapSlots,
|
|
154
|
+
evacStreaks,
|
|
155
|
+
assets: this.assets
|
|
153
156
|
});
|
|
157
|
+
// Gap-evacuation telemetry: evacReady is the streak-tick output of
|
|
158
|
+
// reconcileGrid (stuck in-band candidates). It must survive both
|
|
159
|
+
// abort and success so the manager can act on it even when the
|
|
160
|
+
// rebalance plan itself aborts for an unrelated reason.
|
|
161
|
+
const evacReady = Array.isArray(reconcileResult?.evacReady)
|
|
162
|
+
? reconcileResult.evacReady
|
|
163
|
+
: [];
|
|
154
164
|
if (reconcileResult.aborted) {
|
|
155
|
-
|
|
165
|
+
const aborted = buildAbortedResult(reconcileResult.reason);
|
|
166
|
+
aborted.evacReady = evacReady;
|
|
167
|
+
return aborted;
|
|
156
168
|
}
|
|
157
169
|
const optimizedActions = optimizeRebalanceActions(reconcileResult.actions, masterGrid, {
|
|
158
|
-
logger: (msg, level) => this.logger?.log(msg, level)
|
|
170
|
+
logger: (msg, level) => this.logger?.log(msg, level),
|
|
171
|
+
boundaryIdx: targetBoundary,
|
|
172
|
+
gapSlots,
|
|
173
|
+
assets: this.assets
|
|
159
174
|
});
|
|
160
175
|
// Stale-placement guard: drop placements crossing the plan's own
|
|
161
176
|
// boundary (see stalePlacementDropReason) — defer them to the next
|
|
@@ -219,13 +234,16 @@ class COWRebalanceEngine {
|
|
|
219
234
|
`price=${Number.isFinite(price) ? Format.formatPrice6(price) : 'n/a'})`;
|
|
220
235
|
this.logger?.log(line, a.type === COW_ACTIONS.UPDATE ? 'info' : 'debug');
|
|
221
236
|
}
|
|
222
|
-
return
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
237
|
+
return {
|
|
238
|
+
...buildSuccessResult({
|
|
239
|
+
actions: optimizedActions,
|
|
240
|
+
stateUpdates,
|
|
241
|
+
workingGrid,
|
|
242
|
+
workingBoundary: targetBoundary,
|
|
243
|
+
planningDuration: duration
|
|
244
|
+
}),
|
|
245
|
+
evacReady
|
|
246
|
+
};
|
|
229
247
|
}
|
|
230
248
|
}
|
|
231
249
|
// ===============================================================================
|
|
@@ -359,6 +377,8 @@ class OrderManager {
|
|
|
359
377
|
_lastFilledSellPrice;
|
|
360
378
|
_lastFilledPrice;
|
|
361
379
|
_lastFilledType;
|
|
380
|
+
_gapEvacStreaks;
|
|
381
|
+
_gapEvacCancelQueued;
|
|
362
382
|
// anchor fields removed
|
|
363
383
|
// Note: dedupe lives inside the anchor object (`_seenKeys`), not here.
|
|
364
384
|
// Kept for backwards compat if external code checks existence; not used.
|
|
@@ -471,6 +491,8 @@ class OrderManager {
|
|
|
471
491
|
this._lastFilledSellPrice = null;
|
|
472
492
|
this._lastFilledPrice = null;
|
|
473
493
|
this._lastFilledType = null;
|
|
494
|
+
this._gapEvacStreaks = new Map();
|
|
495
|
+
this._gapEvacCancelQueued = new Set();
|
|
474
496
|
this._metrics = {
|
|
475
497
|
fundRecalcCount: 0,
|
|
476
498
|
lockAcquisitions: 0,
|
|
@@ -1479,9 +1501,13 @@ class OrderManager {
|
|
|
1479
1501
|
}
|
|
1480
1502
|
}
|
|
1481
1503
|
/**
|
|
1482
|
-
* Record last filled price for
|
|
1483
|
-
*
|
|
1484
|
-
*
|
|
1504
|
+
* Record last filled price for the single-pivot guard: when armed, BOTH
|
|
1505
|
+
* sides are gated against the most recent fill price (BUY blocked above
|
|
1506
|
+
* pivot*(1-halfInc), SELL blocked below pivot*(1+halfInc); see
|
|
1507
|
+
* isLastFillGuardBlocked). Spread-correction bypasses. _lastFilledType is
|
|
1508
|
+
* purely the cold/armed discriminator (null => disabled). The per-side
|
|
1509
|
+
* fields are not read by the guard itself; they feed the book-seed
|
|
1510
|
+
* cold-check and per-side seeding in seedLastFilledPricesFromBook.
|
|
1485
1511
|
* @param {Array} fills
|
|
1486
1512
|
*/
|
|
1487
1513
|
recordLastFilledPrices(fills) {
|
|
@@ -1535,8 +1561,10 @@ class OrderManager {
|
|
|
1535
1561
|
/**
|
|
1536
1562
|
* Seed last-filled guard from the live book at startup. Book-derived
|
|
1537
1563
|
* (survives restart), analogous to the deleted MarketAnchor book-seed.
|
|
1538
|
-
*
|
|
1539
|
-
*
|
|
1564
|
+
* A single-sided book arms the guard immediately; a two-sided book
|
|
1565
|
+
* deliberately stays cold (type null) until the first real fill, because
|
|
1566
|
+
* book quotes are not fills and the latest-fill side is unknowable from
|
|
1567
|
+
* the book alone.
|
|
1540
1568
|
* @param {Array} chainOpenOrders - raw chain open orders (from readOpenOrdersGuarded)
|
|
1541
1569
|
*/
|
|
1542
1570
|
seedLastFilledPricesFromBook(chainOpenOrders) {
|
|
@@ -1608,7 +1636,7 @@ class OrderManager {
|
|
|
1608
1636
|
// inferable by the absence of any log line.
|
|
1609
1637
|
if (this._lastFilledPrice == null || this._lastFilledType == null) {
|
|
1610
1638
|
try {
|
|
1611
|
-
this.logger?.log?.(`[LAST-FILL-GUARD] Book seed left guard DISABLED (cold): lastBuy=${maxBuy} lastSell=${minSell} lastPrice=${this._lastFilledPrice} lastType=${this._lastFilledType}; guard arms on the first fill`, '
|
|
1639
|
+
this.logger?.log?.(`[LAST-FILL-GUARD] Book seed left guard DISABLED (cold): lastBuy=${maxBuy} lastSell=${minSell} lastPrice=${this._lastFilledPrice} lastType=${this._lastFilledType}; guard arms on the first fill`, 'info');
|
|
1612
1640
|
}
|
|
1613
1641
|
catch { }
|
|
1614
1642
|
}
|
|
@@ -1727,11 +1755,101 @@ class OrderManager {
|
|
|
1727
1755
|
* @returns {Object}
|
|
1728
1756
|
*/
|
|
1729
1757
|
reconcileGrid(targetGrid, targetBoundary) {
|
|
1758
|
+
if (!(this._gapEvacStreaks instanceof Map))
|
|
1759
|
+
this._gapEvacStreaks = new Map();
|
|
1730
1760
|
return reconcileGrid(this.orders, targetGrid, targetBoundary, {
|
|
1731
1761
|
logger: (msg, level) => this.logger.log(msg, level),
|
|
1732
|
-
dustThresholdPercent: this.config?.gridLimits?.PARTIAL_DUST_THRESHOLD_PERCENTAGE
|
|
1762
|
+
dustThresholdPercent: this.config?.gridLimits?.PARTIAL_DUST_THRESHOLD_PERCENTAGE,
|
|
1763
|
+
gapSlots: this._gapSlots,
|
|
1764
|
+
evacStreaks: this._gapEvacStreaks,
|
|
1765
|
+
assets: this.assets
|
|
1733
1766
|
});
|
|
1734
1767
|
}
|
|
1768
|
+
/**
|
|
1769
|
+
* Phase 3 safety net — turn stuck gap-evacuation candidates (evacReady
|
|
1770
|
+
* from the COW reconcile streak tick) into cancel-only corrections.
|
|
1771
|
+
*
|
|
1772
|
+
* Gate chain per candidate, in order:
|
|
1773
|
+
* 1. Slot idx is STILL genuinely in-band under the CURRENT committed
|
|
1774
|
+
* boundary/gap geometry (the plan's frozen geometry may be stale).
|
|
1775
|
+
* 2. Streak >= GRID_LIMITS.GAP_EVACUATION_CANCEL_THRESHOLD (warn fires
|
|
1776
|
+
* one cycle earlier at GAP_EVACUATION_STREAK_THRESHOLD).
|
|
1777
|
+
* 3. Queued-once marker (_gapEvacCancelQueued) not set — a queued entry
|
|
1778
|
+
* never re-queues until the slot resolves (leaves the band and its
|
|
1779
|
+
* streak entry is dropped).
|
|
1780
|
+
* 4. No correction entry already exists for the same chain order.
|
|
1781
|
+
* 5. The live slot still exists, is on-chain, and still owns that
|
|
1782
|
+
* chain order id.
|
|
1783
|
+
*
|
|
1784
|
+
* The entry uses isSurplus semantics (not bare cancelOnly): the runner
|
|
1785
|
+
* cancels the chain order AND settles the slot back to a spread
|
|
1786
|
+
* placeholder via convertToSpreadPlaceholder, keeping fund tracking
|
|
1787
|
+
* honest and matching Phase 2 band semantics (genuinely in-band slots
|
|
1788
|
+
* are SPREAD VIRTUAL). No re-placement, fee-light.
|
|
1789
|
+
*
|
|
1790
|
+
* @param {Array} candidates - evacReady candidates [{id, idx, type, price, size, orderId}]
|
|
1791
|
+
* @returns {number} Number of corrections queued
|
|
1792
|
+
*/
|
|
1793
|
+
_processGapEvacuationTeeth(candidates) {
|
|
1794
|
+
if (!Array.isArray(candidates) || candidates.length === 0)
|
|
1795
|
+
return 0;
|
|
1796
|
+
if (!Array.isArray(this.ordersNeedingPriceCorrection))
|
|
1797
|
+
return 0;
|
|
1798
|
+
if (!(this._gapEvacStreaks instanceof Map))
|
|
1799
|
+
this._gapEvacStreaks = new Map();
|
|
1800
|
+
if (!(this._gapEvacCancelQueued instanceof Set))
|
|
1801
|
+
this._gapEvacCancelQueued = new Set();
|
|
1802
|
+
// Release queued-once markers for slots that resolved (dropped from
|
|
1803
|
+
// the streak map) so a future return to the band can be acted on again.
|
|
1804
|
+
for (const id of Array.from(this._gapEvacCancelQueued)) {
|
|
1805
|
+
if (!this._gapEvacStreaks.has(id))
|
|
1806
|
+
this._gapEvacCancelQueued.delete(id);
|
|
1807
|
+
}
|
|
1808
|
+
const rawThreshold = Number(GRID_LIMITS?.GAP_EVACUATION_CANCEL_THRESHOLD);
|
|
1809
|
+
const cancelThreshold = Number.isFinite(rawThreshold) && rawThreshold > 0 ? Math.floor(rawThreshold) : 3;
|
|
1810
|
+
const boundary = this.boundaryIdx;
|
|
1811
|
+
const gapSlots = this._gapSlots;
|
|
1812
|
+
let queued = 0;
|
|
1813
|
+
for (const candidate of candidates) {
|
|
1814
|
+
const slotId = candidate?.id;
|
|
1815
|
+
const chainOrderId = candidate?.orderId;
|
|
1816
|
+
if (!slotId || !chainOrderId)
|
|
1817
|
+
continue;
|
|
1818
|
+
// 1. Re-verify geometry against the CURRENT committed boundary.
|
|
1819
|
+
const idx = parseSlotIndex(slotId);
|
|
1820
|
+
if (idx === null || geometryTypeForSlotIndex(idx, boundary, gapSlots) !== ORDER_TYPES.SPREAD)
|
|
1821
|
+
continue;
|
|
1822
|
+
// 2. Act threshold (stricter than the warn threshold).
|
|
1823
|
+
if (Number(this._gapEvacStreaks.get(slotId) || 0) < cancelThreshold)
|
|
1824
|
+
continue;
|
|
1825
|
+
// 3./4. Queued-once + no duplicate chain-order entry.
|
|
1826
|
+
if (this._gapEvacCancelQueued.has(slotId))
|
|
1827
|
+
continue;
|
|
1828
|
+
if (this.ordersNeedingPriceCorrection.some((entry) => entry?.chainOrderId === chainOrderId))
|
|
1829
|
+
continue;
|
|
1830
|
+
// 5. Live slot check.
|
|
1831
|
+
const slot = this.orders.get(slotId);
|
|
1832
|
+
if (!slot || !isOrderOnChain(slot) || slot.orderId !== chainOrderId)
|
|
1833
|
+
continue;
|
|
1834
|
+
this.ordersNeedingPriceCorrection.push({
|
|
1835
|
+
gridOrder: { ...slot },
|
|
1836
|
+
chainOrderId,
|
|
1837
|
+
expectedPrice: slot.price,
|
|
1838
|
+
actualPrice: slot.price,
|
|
1839
|
+
size: slot.size,
|
|
1840
|
+
type: slot.type,
|
|
1841
|
+
isSurplus: true,
|
|
1842
|
+
gapEvacuation: true,
|
|
1843
|
+
boundaryIdx: boundary
|
|
1844
|
+
});
|
|
1845
|
+
this._gapEvacCancelQueued.add(slotId);
|
|
1846
|
+
queued++;
|
|
1847
|
+
this.logger?.log?.(`[GAP-EVAC] Queued cancel-only evacuation for ${slotId} ` +
|
|
1848
|
+
`(${slot.type} @${Format.formatPrice6(slot.price)}, ` +
|
|
1849
|
+
`x${this._gapEvacStreaks.get(slotId)} in band, boundary ${boundary}, gap ${gapSlots})`, 'warn');
|
|
1850
|
+
}
|
|
1851
|
+
return queued;
|
|
1852
|
+
}
|
|
1735
1853
|
/**
|
|
1736
1854
|
* Wait (bounded) until any non-COW broadcast/placement activity — the
|
|
1737
1855
|
* refcounted _broadcastingFlag — has released. Startup/structural
|
|
@@ -1802,14 +1920,31 @@ class OrderManager {
|
|
|
1802
1920
|
return buildAbortedResult('COW Engine not initialized (assets not available)');
|
|
1803
1921
|
}
|
|
1804
1922
|
this._setRebalanceState(REBALANCE_STATES.REBALANCING);
|
|
1923
|
+
if (!(this._gapEvacStreaks instanceof Map))
|
|
1924
|
+
this._gapEvacStreaks = new Map();
|
|
1925
|
+
if (!(this._gapEvacCancelQueued instanceof Set))
|
|
1926
|
+
this._gapEvacCancelQueued = new Set();
|
|
1805
1927
|
const result = await cowEngine.execute({
|
|
1806
1928
|
masterGrid: this.orders,
|
|
1807
1929
|
gridVersion: this._gridVersion,
|
|
1808
1930
|
boundaryIdx: this.boundaryIdx,
|
|
1809
1931
|
funds: this.getChainFundsSnapshot(),
|
|
1810
1932
|
fills,
|
|
1811
|
-
excludeIds
|
|
1933
|
+
excludeIds,
|
|
1934
|
+
gapSlots: this._gapSlots,
|
|
1935
|
+
evacStreaks: this._gapEvacStreaks
|
|
1812
1936
|
});
|
|
1937
|
+
// Phase 3 safety net: act on stuck in-band orders regardless of the
|
|
1938
|
+
// plan outcome — a plan that aborted for unrelated reasons must not
|
|
1939
|
+
// delay the cancel-only evacuation queue. Queued-once per slot; the
|
|
1940
|
+
// corrections runner (correctAllPriceMismatches) executes the cancel
|
|
1941
|
+
// and settles the slot back to a spread placeholder.
|
|
1942
|
+
try {
|
|
1943
|
+
this._processGapEvacuationTeeth(result?.evacReady);
|
|
1944
|
+
}
|
|
1945
|
+
catch (gapEvacError) {
|
|
1946
|
+
this.logger?.log?.(`[GAP-EVAC] Teeth processing failed (non-fatal): ${getErrorMessage(gapEvacError)}`, 'warn');
|
|
1947
|
+
}
|
|
1813
1948
|
if (result.aborted) {
|
|
1814
1949
|
// Nothing was pushed for an aborted result — the push below is
|
|
1815
1950
|
// skipped — so there is no working-grid ref to clear here. Popping
|