dexbot 1.2.0 → 1.2.1
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/dist/credential-daemon.d.ts.map +1 -1
- package/dist/credential-daemon.js +6 -3
- package/dist/credential-daemon.js.map +1 -1
- package/dist/modules/credential_policy.d.ts.map +1 -1
- package/dist/modules/credential_policy.js +7 -5
- package/dist/modules/credential_policy.js.map +1 -1
- package/dist/modules/dexbot_class.d.ts.map +1 -1
- package/dist/modules/dexbot_class.js +52 -20
- package/dist/modules/dexbot_class.js.map +1 -1
- package/dist/modules/dexbot_maintenance_runtime.d.ts.map +1 -1
- package/dist/modules/dexbot_maintenance_runtime.js +4 -0
- package/dist/modules/dexbot_maintenance_runtime.js.map +1 -1
- package/dist/modules/order/accounting.d.ts +8 -2
- package/dist/modules/order/accounting.d.ts.map +1 -1
- package/dist/modules/order/accounting.js +25 -15
- package/dist/modules/order/accounting.js.map +1 -1
- package/dist/modules/order/grid.js +1 -1
- package/dist/modules/order/grid.js.map +1 -1
- package/dist/modules/order/grid_reconcile_internal.js +13 -2
- package/dist/modules/order/grid_reconcile_internal.js.map +1 -1
- package/dist/modules/order/manager.d.ts +82 -16
- package/dist/modules/order/manager.d.ts.map +1 -1
- package/dist/modules/order/manager.js +126 -235
- package/dist/modules/order/manager.js.map +1 -1
- package/dist/modules/order/sync_engine.d.ts +2 -3
- package/dist/modules/order/sync_engine.d.ts.map +1 -1
- package/dist/modules/order/sync_engine.js +13 -3
- package/dist/modules/order/sync_engine.js.map +1 -1
- package/dist/modules/order/utils/order.d.ts.map +1 -1
- package/dist/modules/order/utils/order.js +42 -6
- package/dist/modules/order/utils/order.js.map +1 -1
- package/dist/modules/types.d.ts +7 -12
- package/dist/modules/types.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -349,7 +349,7 @@ class DEXBot {
|
|
|
349
349
|
shadowLocks: this.manager?.shadowOrderIds?.size || 0,
|
|
350
350
|
batchInFlight: this._batchInFlight,
|
|
351
351
|
recoveryInFlight: this._recoverySyncInFlight,
|
|
352
|
-
broadcasting: this.manager?.
|
|
352
|
+
broadcasting: this.manager?.isBroadcastingActive?.() || false
|
|
353
353
|
};
|
|
354
354
|
}
|
|
355
355
|
/**
|
|
@@ -1279,6 +1279,30 @@ class DEXBot {
|
|
|
1279
1279
|
await this._processFillsWithBootstrapMode(chainOrders);
|
|
1280
1280
|
}
|
|
1281
1281
|
this.manager.finishBootstrap();
|
|
1282
|
+
// Refresh account totals after bootstrap to eliminate the timing
|
|
1283
|
+
// gap between the initial balance fetch and grid operations (sync,
|
|
1284
|
+
// reconcile, fills). Without this, the first maintenance cycle sees
|
|
1285
|
+
// a fund drift (expected at bootstrap) and triggers an unnecessary
|
|
1286
|
+
// invariant violation + full recovery cycle.
|
|
1287
|
+
// Bound by a timeout to avoid blocking _fillProcessingLock on a
|
|
1288
|
+
// flaky node. If the fetch times out, continue with cached values;
|
|
1289
|
+
// the next periodic maintenance cycle will retry.
|
|
1290
|
+
const FETCH_TIMEOUT_MS = 30000;
|
|
1291
|
+
let _fetchTimeoutHandle;
|
|
1292
|
+
try {
|
|
1293
|
+
await Promise.race([
|
|
1294
|
+
this.manager.fetchAccountTotals(),
|
|
1295
|
+
new Promise((_, reject) => {
|
|
1296
|
+
_fetchTimeoutHandle = setTimeout(() => reject(new Error('timeout')), FETCH_TIMEOUT_MS);
|
|
1297
|
+
})
|
|
1298
|
+
]);
|
|
1299
|
+
}
|
|
1300
|
+
catch (fetchErr) {
|
|
1301
|
+
this._log(`[STARTUP] [${this.config?.botKey || 'unknown'}] fetchAccountTotals ${fetchErr.message === 'timeout' ? 'timed out' : 'failed'} (${fetchErr.message}). Continuing with cached account totals.`, 'warn');
|
|
1302
|
+
}
|
|
1303
|
+
finally {
|
|
1304
|
+
clearTimeout(_fetchTimeoutHandle);
|
|
1305
|
+
}
|
|
1282
1306
|
// Perform initial grid maintenance (thresholds, divergence, spread, health)
|
|
1283
1307
|
// Consolidated into shared logic to ensure consistent behavior at boot and runtime.
|
|
1284
1308
|
// CRITICAL: Pass lockAlreadyHeld since we're inside _fillProcessingLock.acquire()
|
|
@@ -1504,11 +1528,11 @@ class DEXBot {
|
|
|
1504
1528
|
try {
|
|
1505
1529
|
// BOOTSTRAP OPTIMIZATION: During bootstrap, prioritize fill processing over grid-wide checks
|
|
1506
1530
|
// Process fills immediately with side-only rebalancing (no expensive full grid recalculations)
|
|
1507
|
-
if (this.manager.
|
|
1531
|
+
if (this.manager.isBootstrapping()) {
|
|
1508
1532
|
// During bootstrap: skip lock contention checks, process fills directly
|
|
1509
1533
|
let bootstrapSkipped = false;
|
|
1510
1534
|
await this.manager._fillProcessingLock.acquire(async () => {
|
|
1511
|
-
if (!this.manager.
|
|
1535
|
+
if (!this.manager.isBootstrapping()) {
|
|
1512
1536
|
// Bootstrap finished while waiting for the lock — no
|
|
1513
1537
|
// work to do, but the iteration is still healthy.
|
|
1514
1538
|
bootstrapSkipped = true;
|
|
@@ -2628,7 +2652,11 @@ class DEXBot {
|
|
|
2628
2652
|
fingerprint: entry.fingerprint
|
|
2629
2653
|
});
|
|
2630
2654
|
if (match) {
|
|
2631
|
-
adopted.push({
|
|
2655
|
+
adopted.push({
|
|
2656
|
+
slotId: entry.slotId,
|
|
2657
|
+
chainOrderId: match.id,
|
|
2658
|
+
orderType: entry.orderType || entry.order?.type,
|
|
2659
|
+
});
|
|
2632
2660
|
this.manager._pendingBroadcasts.delete(entry.fingerprint);
|
|
2633
2661
|
}
|
|
2634
2662
|
else {
|
|
@@ -2665,7 +2693,11 @@ class DEXBot {
|
|
|
2665
2693
|
fingerprint: entry.fingerprint
|
|
2666
2694
|
});
|
|
2667
2695
|
if (match) {
|
|
2668
|
-
adopted.push({
|
|
2696
|
+
adopted.push({
|
|
2697
|
+
slotId: entry.slotId,
|
|
2698
|
+
chainOrderId: match.id,
|
|
2699
|
+
orderType: entry.orderType || entry.order?.type,
|
|
2700
|
+
});
|
|
2669
2701
|
this.manager.logger.log(`[COW][UNCERTAIN] CREATE re-adopted after ${recheckRound} block(s): ` +
|
|
2670
2702
|
`${entry.slotId}->${match.id}`, 'info');
|
|
2671
2703
|
}
|
|
@@ -2748,27 +2780,27 @@ class DEXBot {
|
|
|
2748
2780
|
this.manager.logger.log(`[COW][UNCERTAIN] Auto-cancel pass failed: ${orphanErr?.message || orphanErr}`, 'warn');
|
|
2749
2781
|
}
|
|
2750
2782
|
// Boundary shift recovery: the COW batch that should have committed the
|
|
2751
|
-
// boundary shift from this fill cycle failed before commit.
|
|
2752
|
-
//
|
|
2753
|
-
//
|
|
2754
|
-
//
|
|
2755
|
-
//
|
|
2756
|
-
//
|
|
2783
|
+
// boundary shift from this fill cycle failed before commit. Only COUNT
|
|
2784
|
+
// ADOPTED CREATEs — orders that actually landed on-chain. Discarded
|
|
2785
|
+
// CREATEs represent orders that never existed, so the grid must NOT
|
|
2786
|
+
// shift the boundary for them. The next fill cycle's
|
|
2787
|
+
// calculateTargetGrid → deriveTargetBoundary will recompute the correct
|
|
2788
|
+
// boundary from scratch for any discarded slots.
|
|
2757
2789
|
//
|
|
2758
2790
|
// NOTE: Direct mutation of manager.boundaryIdx outside a COW commit
|
|
2759
2791
|
// violates the invariant stated in grid.ts:1217-1220 (boundary must only
|
|
2760
2792
|
// be updated atomically inside _commitWorkingGrid). This is intentional
|
|
2761
2793
|
// here because the COW commit already failed — the invariant was already
|
|
2762
2794
|
// broken by the broadcast uncertainty, and the adjustment only restores
|
|
2763
|
-
// the state to what the successful commit would have produced
|
|
2764
|
-
|
|
2795
|
+
// the state to what the successful commit would have produced for
|
|
2796
|
+
// orders that are confirmed on-chain.
|
|
2797
|
+
if (hadRotation && this.manager && adopted.length > 0) {
|
|
2765
2798
|
let boundaryShift = 0;
|
|
2766
|
-
for (const entry of
|
|
2767
|
-
|
|
2768
|
-
if (orderType === ORDER_TYPES.SELL) {
|
|
2799
|
+
for (const entry of adopted) {
|
|
2800
|
+
if (entry.orderType === ORDER_TYPES.SELL) {
|
|
2769
2801
|
boundaryShift--; // SELL CREATE → fill was BUY → boundary LEFT
|
|
2770
2802
|
}
|
|
2771
|
-
else if (orderType === ORDER_TYPES.BUY) {
|
|
2803
|
+
else if (entry.orderType === ORDER_TYPES.BUY) {
|
|
2772
2804
|
boundaryShift++; // BUY CREATE → fill was SELL → boundary RIGHT
|
|
2773
2805
|
}
|
|
2774
2806
|
}
|
|
@@ -2780,10 +2812,10 @@ class DEXBot {
|
|
|
2780
2812
|
if (newIdx !== oldIdx) {
|
|
2781
2813
|
this.manager.boundaryIdx = newIdx;
|
|
2782
2814
|
this.manager.logger.log(`[COW][UNCERTAIN] Boundary adjusted by ${boundaryShift} ` +
|
|
2783
|
-
`(${adopted.length} adopted
|
|
2815
|
+
`(${adopted.length} adopted CREATE(s), ${discarded.length} discarded): ` +
|
|
2784
2816
|
`${oldIdx} → ${newIdx}. Next COW cycle will generate replacement opposite-side orders.`, 'warn');
|
|
2785
2817
|
if (typeof this.manager._markGridDirty === 'function') {
|
|
2786
|
-
this.manager._markGridDirty(
|
|
2818
|
+
this.manager._markGridDirty();
|
|
2787
2819
|
}
|
|
2788
2820
|
}
|
|
2789
2821
|
}
|
|
@@ -3324,7 +3356,7 @@ class DEXBot {
|
|
|
3324
3356
|
if (this._credentialRecoveryInFlight || !this._credentialRecoveryNeeded || this._shuttingDown) {
|
|
3325
3357
|
return;
|
|
3326
3358
|
}
|
|
3327
|
-
if (this.manager?.
|
|
3359
|
+
if (this.manager?.isBootstrapping?.() || this.manager?.isBroadcastingActive?.()) {
|
|
3328
3360
|
if (!this._credentialRecoveryDeferredTimer) {
|
|
3329
3361
|
this.manager?.logger?.log?.('[CREDENTIAL] Deferring credential recovery until startup/broadcast activity is idle.', 'info');
|
|
3330
3362
|
this._credentialRecoveryDeferredTimer = setTimeout(() => {
|