dexbot 1.6.3 → 1.6.5
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 +78 -2
- package/README.md +23 -19
- package/analysis/README.md +26 -13
- package/analysis/account_resolver.ts +171 -0
- package/analysis/ama_fitting/analyze_lambda_vs_slow.ts +2 -5
- package/analysis/ama_fitting/package.json +1 -1
- package/analysis/analyze_dynamic_weight.ts +9 -3
- package/analysis/bot_usage/discover_bot_accounts.ts +20 -27
- package/analysis/chain_pool.ts +47 -0
- package/analysis/chart_utils.ts +33 -20
- package/analysis/derivative_chart_generator.ts +2 -3
- package/analysis/fills_source.ts +234 -0
- package/analysis/grid_correction_check.ts +38 -251
- package/analysis/trade_profitability.ts +169 -304
- package/analysis/tradingview/README.md +2 -2
- package/analysis/tradingview/analyze_tradingview.ts +5 -0
- package/analysis/tradingview/tradingview_uplot_chart_generator.ts +5 -6
- package/analysis/trend_detection/DYNAMIC_WEIGHT_RESEARCH.md +35 -2
- package/analysis/trend_detection/dynamic_weight_chart_generator.ts +84 -13
- package/analysis/trend_detection/kalman_chart_generator.ts +2 -3
- package/analysis/trend_detection/package.json +1 -1
- package/analysis/trend_detection/regime_chart_generator.ts +2 -3
- package/analysis/trend_detection/volatility_chart_generator.ts +2 -3
- package/claw/modules/dexbot_profiles.ts +4 -3
- 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/claw/tests/test_dexbot_profiles.ts +18 -1
- package/dist/analysis/account_resolver.d.ts +43 -0
- package/dist/analysis/account_resolver.d.ts.map +1 -0
- package/dist/analysis/account_resolver.js +137 -0
- package/dist/analysis/account_resolver.js.map +1 -0
- package/dist/analysis/ama_fitting/analyze_lambda_vs_slow.d.ts.map +1 -1
- package/dist/analysis/ama_fitting/analyze_lambda_vs_slow.js +2 -4
- package/dist/analysis/ama_fitting/analyze_lambda_vs_slow.js.map +1 -1
- package/dist/analysis/analyze_dynamic_weight.js +9 -3
- package/dist/analysis/analyze_dynamic_weight.js.map +1 -1
- package/dist/analysis/bot_usage/discover_bot_accounts.js +20 -28
- package/dist/analysis/bot_usage/discover_bot_accounts.js.map +1 -1
- package/dist/analysis/chain_pool.d.ts +10 -0
- package/dist/analysis/chain_pool.d.ts.map +1 -0
- package/dist/analysis/chain_pool.js +47 -0
- package/dist/analysis/chain_pool.js.map +1 -0
- package/dist/analysis/chart_utils.d.ts +14 -1
- package/dist/analysis/chart_utils.d.ts.map +1 -1
- package/dist/analysis/chart_utils.js +32 -22
- package/dist/analysis/chart_utils.js.map +1 -1
- package/dist/analysis/derivative_chart_generator.d.ts.map +1 -1
- package/dist/analysis/derivative_chart_generator.js +2 -3
- package/dist/analysis/derivative_chart_generator.js.map +1 -1
- package/dist/analysis/fills_source.d.ts +79 -0
- package/dist/analysis/fills_source.d.ts.map +1 -0
- package/dist/analysis/fills_source.js +186 -0
- package/dist/analysis/fills_source.js.map +1 -0
- package/dist/analysis/grid_correction_check.d.ts +1 -21
- package/dist/analysis/grid_correction_check.d.ts.map +1 -1
- package/dist/analysis/grid_correction_check.js +30 -257
- package/dist/analysis/grid_correction_check.js.map +1 -1
- package/dist/analysis/trade_profitability.d.ts +18 -19
- package/dist/analysis/trade_profitability.d.ts.map +1 -1
- package/dist/analysis/trade_profitability.js +136 -280
- package/dist/analysis/trade_profitability.js.map +1 -1
- package/dist/analysis/tradingview/analyze_tradingview.d.ts.map +1 -1
- package/dist/analysis/tradingview/analyze_tradingview.js +5 -0
- package/dist/analysis/tradingview/analyze_tradingview.js.map +1 -1
- package/dist/analysis/tradingview/tradingview_uplot_chart_generator.d.ts.map +1 -1
- package/dist/analysis/tradingview/tradingview_uplot_chart_generator.js +5 -6
- package/dist/analysis/tradingview/tradingview_uplot_chart_generator.js.map +1 -1
- package/dist/analysis/trend_detection/dynamic_weight_chart_generator.d.ts.map +1 -1
- package/dist/analysis/trend_detection/dynamic_weight_chart_generator.js +84 -13
- package/dist/analysis/trend_detection/dynamic_weight_chart_generator.js.map +1 -1
- package/dist/analysis/trend_detection/kalman_chart_generator.d.ts.map +1 -1
- package/dist/analysis/trend_detection/kalman_chart_generator.js +2 -3
- package/dist/analysis/trend_detection/kalman_chart_generator.js.map +1 -1
- package/dist/analysis/trend_detection/regime_chart_generator.d.ts.map +1 -1
- package/dist/analysis/trend_detection/regime_chart_generator.js +2 -3
- package/dist/analysis/trend_detection/regime_chart_generator.js.map +1 -1
- package/dist/analysis/trend_detection/volatility_chart_generator.d.ts.map +1 -1
- package/dist/analysis/trend_detection/volatility_chart_generator.js +2 -3
- package/dist/analysis/trend_detection/volatility_chart_generator.js.map +1 -1
- package/dist/dexbot.d.ts.map +1 -1
- package/dist/dexbot.js +27 -68
- package/dist/dexbot.js.map +1 -1
- package/dist/market_adapter/core/asymmetric_bounds.d.ts +2 -2
- package/dist/market_adapter/core/asymmetric_bounds.d.ts.map +1 -1
- package/dist/market_adapter/core/asymmetric_bounds.js +15 -12
- package/dist/market_adapter/core/asymmetric_bounds.js.map +1 -1
- package/dist/market_adapter/interval_utils.d.ts +1 -1
- package/dist/market_adapter/interval_utils.js +1 -1
- package/dist/market_adapter/lp_chart_core.d.ts.map +1 -1
- package/dist/market_adapter/lp_chart_core.js +2 -3
- package/dist/market_adapter/lp_chart_core.js.map +1 -1
- package/dist/modules/account_bots.d.ts +51 -18
- package/dist/modules/account_bots.d.ts.map +1 -1
- package/dist/modules/account_bots.js +258 -117
- package/dist/modules/account_bots.js.map +1 -1
- package/dist/modules/bitshares-native/serial/operations.d.ts +1 -84
- package/dist/modules/bitshares-native/serial/operations.d.ts.map +1 -1
- package/dist/modules/bitshares-native/serial/operations.js +1 -38
- package/dist/modules/bitshares-native/serial/operations.js.map +1 -1
- package/dist/modules/bot_defaults.d.ts +98 -0
- package/dist/modules/bot_defaults.d.ts.map +1 -0
- package/dist/modules/bot_defaults.js +169 -0
- package/dist/modules/bot_defaults.js.map +1 -0
- package/dist/modules/bot_settings.d.ts.map +1 -1
- package/dist/modules/bot_settings.js +4 -1
- package/dist/modules/bot_settings.js.map +1 -1
- package/dist/modules/cli_colors.d.ts +0 -1
- package/dist/modules/cli_colors.d.ts.map +1 -1
- package/dist/modules/config.d.ts +1 -0
- package/dist/modules/config.d.ts.map +1 -1
- package/dist/modules/config.js +1 -0
- package/dist/modules/config.js.map +1 -1
- package/dist/modules/constants.d.ts +11 -2
- package/dist/modules/constants.d.ts.map +1 -1
- package/dist/modules/constants.js +45 -32
- package/dist/modules/constants.js.map +1 -1
- package/dist/modules/credential_policy.d.ts +1 -25
- package/dist/modules/credential_policy.d.ts.map +1 -1
- package/dist/modules/credential_policy.js +1 -1
- package/dist/modules/credential_policy.js.map +1 -1
- package/dist/modules/credential_runtime.d.ts +1 -6
- package/dist/modules/credential_runtime.d.ts.map +1 -1
- package/dist/modules/credential_runtime.js +1 -1
- package/dist/modules/credential_runtime.js.map +1 -1
- package/dist/modules/credential_session_cache.d.ts +1 -5
- package/dist/modules/credential_session_cache.d.ts.map +1 -1
- package/dist/modules/credential_session_cache.js +1 -1
- package/dist/modules/credential_session_cache.js.map +1 -1
- package/dist/modules/crypto/pure_secp256k1.d.ts +1 -2
- package/dist/modules/crypto/pure_secp256k1.d.ts.map +1 -1
- package/dist/modules/crypto/pure_secp256k1.js +1 -1
- package/dist/modules/crypto/pure_secp256k1.js.map +1 -1
- package/dist/modules/dexbot_class.d.ts +8 -7
- package/dist/modules/dexbot_class.d.ts.map +1 -1
- package/dist/modules/dexbot_class.js +9 -8
- package/dist/modules/dexbot_class.js.map +1 -1
- package/dist/modules/dexbot_cow_runtime.d.ts +7 -6
- package/dist/modules/dexbot_cow_runtime.d.ts.map +1 -1
- package/dist/modules/dexbot_cow_runtime.js +8 -7
- package/dist/modules/dexbot_cow_runtime.js.map +1 -1
- package/dist/modules/dexbot_fill_runtime.d.ts +1 -17
- package/dist/modules/dexbot_fill_runtime.d.ts.map +1 -1
- package/dist/modules/dexbot_fill_runtime.js +1 -1
- package/dist/modules/dexbot_fill_runtime.js.map +1 -1
- package/dist/modules/dexbot_maintenance_runtime.d.ts +2 -2
- package/dist/modules/dexbot_maintenance_runtime.d.ts.map +1 -1
- package/dist/modules/dexbot_maintenance_runtime.js +24 -8
- package/dist/modules/dexbot_maintenance_runtime.js.map +1 -1
- package/dist/modules/dexbot_state_recovery.d.ts +1 -7
- package/dist/modules/dexbot_state_recovery.d.ts.map +1 -1
- package/dist/modules/dexbot_state_recovery.js +1 -1
- package/dist/modules/dexbot_state_recovery.js.map +1 -1
- package/dist/modules/launcher/adapter_requirement.d.ts +1 -5
- package/dist/modules/launcher/adapter_requirement.d.ts.map +1 -1
- package/dist/modules/launcher/adapter_requirement.js +2 -2
- package/dist/modules/launcher/adapter_requirement.js.map +1 -1
- package/dist/modules/launcher/bot_supervisor.d.ts +1 -6
- package/dist/modules/launcher/bot_supervisor.d.ts.map +1 -1
- package/dist/modules/launcher/bot_supervisor.js +1 -1
- package/dist/modules/launcher/bot_supervisor.js.map +1 -1
- package/dist/modules/launcher/foreign_cred_daemon.d.ts +1 -3
- package/dist/modules/launcher/foreign_cred_daemon.d.ts.map +1 -1
- package/dist/modules/launcher/foreign_cred_daemon.js +1 -1
- package/dist/modules/launcher/foreign_cred_daemon.js.map +1 -1
- package/dist/modules/launcher/launch_modes.d.ts +17 -2
- package/dist/modules/launcher/launch_modes.d.ts.map +1 -1
- package/dist/modules/launcher/launch_modes.js +18 -1
- package/dist/modules/launcher/launch_modes.js.map +1 -1
- package/dist/modules/launcher/market_adapter_runtime.d.ts +1 -3
- package/dist/modules/launcher/market_adapter_runtime.d.ts.map +1 -1
- package/dist/modules/launcher/market_adapter_runtime.js +1 -1
- package/dist/modules/launcher/market_adapter_runtime.js.map +1 -1
- package/dist/modules/launcher/monolithic_runtime.d.ts +1 -5
- package/dist/modules/launcher/monolithic_runtime.d.ts.map +1 -1
- package/dist/modules/launcher/monolithic_runtime.js +9 -2
- package/dist/modules/launcher/monolithic_runtime.js.map +1 -1
- package/dist/modules/launcher/status_reporting.d.ts +1 -2
- package/dist/modules/launcher/status_reporting.d.ts.map +1 -1
- package/dist/modules/launcher/status_reporting.js +1 -1
- package/dist/modules/launcher/status_reporting.js.map +1 -1
- package/dist/modules/market_adapter_whitelist.d.ts +40 -1
- package/dist/modules/market_adapter_whitelist.d.ts.map +1 -1
- package/dist/modules/market_adapter_whitelist.js +161 -11
- package/dist/modules/market_adapter_whitelist.js.map +1 -1
- package/dist/modules/order/export.d.ts +1 -8
- package/dist/modules/order/export.d.ts.map +1 -1
- package/dist/modules/order/export.js +1 -1
- package/dist/modules/order/export.js.map +1 -1
- package/dist/modules/order/grid.d.ts +16 -0
- package/dist/modules/order/grid.d.ts.map +1 -1
- package/dist/modules/order/grid.js +75 -103
- package/dist/modules/order/grid.js.map +1 -1
- package/dist/modules/order/grid_reconcile_internal.d.ts +1 -10
- package/dist/modules/order/grid_reconcile_internal.d.ts.map +1 -1
- package/dist/modules/order/grid_reconcile_internal.js +2 -2
- package/dist/modules/order/grid_reconcile_internal.js.map +1 -1
- package/dist/modules/order/manager.d.ts +10 -2
- package/dist/modules/order/manager.d.ts.map +1 -1
- package/dist/modules/order/manager.js +20 -8
- package/dist/modules/order/manager.js.map +1 -1
- package/dist/modules/order/sync_engine.d.ts.map +1 -1
- package/dist/modules/order/sync_engine.js +8 -15
- package/dist/modules/order/sync_engine.js.map +1 -1
- package/dist/modules/order/utils/math.d.ts +1 -10
- package/dist/modules/order/utils/math.d.ts.map +1 -1
- package/dist/modules/order/utils/math.js +1 -1
- package/dist/modules/order/utils/math.js.map +1 -1
- package/dist/modules/order/utils/system.d.ts +5 -16
- package/dist/modules/order/utils/system.d.ts.map +1 -1
- package/dist/modules/order/utils/system.js +7 -4
- package/dist/modules/order/utils/system.js.map +1 -1
- package/dist/modules/process_discovery.d.ts +0 -3
- package/dist/modules/process_discovery.d.ts.map +1 -1
- package/dist/modules/process_discovery.js +1 -1
- package/dist/modules/process_discovery.js.map +1 -1
- package/dist/modules/settings_merge.d.ts +10 -1
- package/dist/modules/settings_merge.d.ts.map +1 -1
- package/dist/modules/settings_merge.js +27 -17
- package/dist/modules/settings_merge.js.map +1 -1
- package/dist/modules/utils/chain_logs.d.ts +1 -2
- package/dist/modules/utils/chain_logs.d.ts.map +1 -1
- package/dist/modules/utils/chain_logs.js +1 -1
- package/dist/modules/utils/chain_logs.js.map +1 -1
- package/dist/modules/validate_profiles.d.ts.map +1 -1
- package/dist/modules/validate_profiles.js +4 -3
- package/dist/modules/validate_profiles.js.map +1 -1
- package/dist/scripts/analyze-git.js +2 -2
- package/dist/scripts/analyze-git.js.map +1 -1
- package/dist/scripts/chart_command.d.ts +48 -0
- package/dist/scripts/chart_command.d.ts.map +1 -0
- package/dist/scripts/chart_command.js +504 -0
- package/dist/scripts/chart_command.js.map +1 -0
- package/dist/scripts/dw.d.ts +3 -0
- package/dist/scripts/dw.d.ts.map +1 -0
- package/dist/scripts/dw.js +30 -0
- package/dist/scripts/dw.js.map +1 -0
- package/dist/scripts/tv.d.ts +1 -31
- package/dist/scripts/tv.d.ts.map +1 -1
- package/dist/scripts/tv.js +10 -463
- package/dist/scripts/tv.js.map +1 -1
- package/dist/scripts/update.js +145 -93
- package/dist/scripts/update.js.map +1 -1
- package/dist/scripts/update_dist_freshness.d.ts +46 -0
- package/dist/scripts/update_dist_freshness.d.ts.map +1 -0
- package/dist/scripts/update_dist_freshness.js +115 -0
- package/dist/scripts/update_dist_freshness.js.map +1 -0
- package/dist/unlock.js +1 -1
- package/dist/unlock.js.map +1 -1
- package/docs/BITSHARES_ONBOARDING.md +117 -44
- package/docs/COPY_ON_WRITE_MASTER_PLAN.md +10 -207
- package/docs/COW_INVARIANTS.md +16 -10
- package/docs/DEXBOT_COMPARISON.md +3 -3
- package/docs/EVOLUTION.md +76 -30
- package/docs/FUND_MOVEMENT_AND_ACCOUNTING.md +9 -9
- package/docs/GRID_RECALCULATION.md +34 -30
- package/docs/GRID_RECONCILE.md +30 -27
- package/docs/LIFECYCLE.md +12 -11
- package/docs/LOGGING.md +1 -0
- package/docs/README.md +58 -52
- package/docs/WORKFLOW.md +1 -2
- package/docs/architecture.md +21 -32
- package/docs/developer_guide.md +4 -3
- package/market_adapter/README.md +36 -60
- package/modules/README.md +2 -1
- package/package.json +1 -2
- package/scripts/README.md +18 -25
- package/scripts/git-viewer.sh +1 -1
- package/scripts/reset-settings.sh +1 -1
- package/tests/README.md +10 -1
- package/dist/scripts/generate_market_adapter_whitelist.d.ts +0 -15
- package/dist/scripts/generate_market_adapter_whitelist.d.ts.map +0 -1
- package/dist/scripts/generate_market_adapter_whitelist.js +0 -191
- package/dist/scripts/generate_market_adapter_whitelist.js.map +0 -1
|
@@ -78,6 +78,13 @@ NORMAL → REBALANCING → BROADCASTING → _commitWorkingGrid() → NORMAL
|
|
|
78
78
|
- Any master mutation marks the working grid stale.
|
|
79
79
|
- Commit succeeds only when stale/version/delta guards all pass.
|
|
80
80
|
|
|
81
|
+
### Atomic Boundary Shifts
|
|
82
|
+
|
|
83
|
+
Boundary index changes during divergence correction are atomic with slot-type reassignment:
|
|
84
|
+
`pendingBoundaryIdx` carries boundary changes through the COW pipeline and `manager.boundaryIdx`
|
|
85
|
+
is untouched until `_commitWorkingGrid` completes. This prevents transient mismatches between
|
|
86
|
+
boundary position and slot BUY/SELL roles during blockchain execution.
|
|
87
|
+
|
|
81
88
|
## Data Flow
|
|
82
89
|
|
|
83
90
|
### Normal Rebalance Flow
|
|
@@ -215,145 +222,6 @@ syncFromMaster(masterGrid, orderId, masterVersion?) {
|
|
|
215
222
|
- Prevents stale data from being committed.
|
|
216
223
|
- Avoids unnecessary aborts for individual fills.
|
|
217
224
|
|
|
218
|
-
## Historical Context: Immutable Master Grid Evolution
|
|
219
|
-
|
|
220
|
-
The COW architecture evolved from earlier attempts to achieve grid immutability. The three
|
|
221
|
-
eras below describe design evolution over time; they are **distinct from the Build Steps**
|
|
222
|
-
numbered 0–9 in the *Implementation Status* section (Build Steps track the construction
|
|
223
|
-
work that produced the current code).
|
|
224
|
-
|
|
225
|
-
### Era 0: Original Optimistic State (Pre-v1.0) — ❌ Removed
|
|
226
|
-
- **Approach:** Direct in-memory mutation of master grid during planning.
|
|
227
|
-
- **Pattern:** Modify master directly → Broadcast to blockchain → No recovery mechanism.
|
|
228
|
-
- **Vulnerability:** State corruption during any failure, no isolation between planning and committed state, no rollback capability.
|
|
229
|
-
- **Incident:** This approach caused the Price Jump incident — a sudden market move corrupted in-flight grid state because planning mutations were applied directly to the master grid, with no isolation or rollback.
|
|
230
|
-
|
|
231
|
-
### Era 1: Frozen Master State (v1.0) — ✅ Retained as defense-in-depth
|
|
232
|
-
- **Approach:** `Object.freeze()` on Maps and order objects.
|
|
233
|
-
- **Implementation:** Each `_applyOrderUpdate` creates a new frozen Map via immutable-swap pattern.
|
|
234
|
-
- **Advantage:** Runtime enforcement prevents accidental mutations; catches bugs that read `manager.orders` and mutate in-place.
|
|
235
|
-
- **Original concern:** Performance overhead, complexity in deep-freezing nested structures.
|
|
236
|
-
|
|
237
|
-
### Era 2: Copy-on-Write (v2.0 — Current) — ✅ Production-ready
|
|
238
|
-
- **Approach:** Working copy during planning, atomic swap on blockchain confirmation.
|
|
239
|
-
- **Pattern:** Clone → Modify working copy → Broadcast → Commit on success / Discard on failure.
|
|
240
|
-
- **Advantage:** True transactional semantics; master never in intermediate state; cleaner than snapshot/rollback.
|
|
241
|
-
|
|
242
|
-
The production implementation uses both Era 1 (`Object.freeze`) and Era 2 (COW) as
|
|
243
|
-
complementary layers; see **Freeze + COW Hybrid** under *Architecture* above.
|
|
244
|
-
|
|
245
|
-
## Implementation Status
|
|
246
|
-
|
|
247
|
-
Build Steps track the construction work that produced the current code; they are distinct
|
|
248
|
-
from the *Era* numbering used in *Historical Context*.
|
|
249
|
-
|
|
250
|
-
### Build Step 0: Dependencies ✅
|
|
251
|
-
Dependency utilities merged into `modules/order/utils/order.ts` during v0.6.0-patch.19 consolidation.
|
|
252
|
-
|
|
253
|
-
### Build Step 1: Infrastructure ✅
|
|
254
|
-
- Created `modules/order/working_grid.ts` — WorkingGrid class.
|
|
255
|
-
- Added `COW_PERFORMANCE` thresholds to `modules/constants.ts`.
|
|
256
|
-
|
|
257
|
-
### Build Step 2: Core Integration ✅
|
|
258
|
-
- `performSafeRebalance()` → delegates to `_applySafeRebalanceCOW()`.
|
|
259
|
-
- `_applySafeRebalanceCOW()` — creates working grid, runs planning, returns result without modifying master.
|
|
260
|
-
- `WorkingGrid.buildDelta()` — delta reconciliation against working copy (`modules/order/working_grid.ts:204`, delegating to `utils/order.ts`).
|
|
261
|
-
- `_commitWorkingGrid()` — atomic swap from working to master.
|
|
262
|
-
|
|
263
|
-
### Build Step 3: Broadcast Integration ✅
|
|
264
|
-
- `updateOrdersOnChainBatch()` — routes to COW path when `workingGrid` present.
|
|
265
|
-
- `_updateOrdersOnChainBatchCOW()` — full COW broadcast with commit on success.
|
|
266
|
-
- Removed legacy rollback code.
|
|
267
|
-
|
|
268
|
-
### Build Step 4: Fill Handling Strategy ✅
|
|
269
|
-
**Decision:** "Selective abort — continue individual fills, block full-side updates."
|
|
270
|
-
Full design is documented in the **Fill Handling Strategy** section above.
|
|
271
|
-
|
|
272
|
-
### Build Step 5: Tests ✅
|
|
273
|
-
- `tests/test_cow_master_plan.ts` — 11 COW core tests.
|
|
274
|
-
- `tests/test_cow_commit_guards.ts` — commit guard regression tests.
|
|
275
|
-
- `tests/test_cow_concurrent_fills.ts` — concurrent fill integration tests.
|
|
276
|
-
- `tests/test_cow_divergence_correction.ts` — divergence correction COW tests.
|
|
277
|
-
- `tests/test_cow_orchestration_fixes.ts` — COW orchestration fixes.
|
|
278
|
-
- `tests/test_cow_structural_resync.ts` — structural grid resync tests.
|
|
279
|
-
- `tests/test_cow_static_analysis.ts` — static analysis and invariant checks.
|
|
280
|
-
- `tests/test_cow_index_mutation_detection.ts` — index mutation detection.
|
|
281
|
-
- `tests/test_cow_fund_validation_precision.ts` — fund validation precision tests.
|
|
282
|
-
- `tests/test_cow_set_mutation_report.ts` — set mutation report tests.
|
|
283
|
-
- `tests/test_sync_lock_routing.ts` — lock routing verification tests.
|
|
284
|
-
- `tests/test_working_grid.ts` — WorkingGrid unit tests.
|
|
285
|
-
|
|
286
|
-
### Build Step 6: Divergence & Cache Updates ✅
|
|
287
|
-
Divergence checks and cache function updates only execute when no fills are pending. See
|
|
288
|
-
**Fill Handling Strategy → Divergence & Cache Checks Blocked During Rebalance**.
|
|
289
|
-
|
|
290
|
-
### Build Step 7: Divergence Correction COW Migration ✅
|
|
291
|
-
Migrated `applyGridDivergenceCorrections` from queue-based cancellations to full COW pattern.
|
|
292
|
-
|
|
293
|
-
**Atomic Boundary Shifts (Patch 20):** Boundary index changes during divergence correction are
|
|
294
|
-
now atomic with slot-type reassignment. The `pendingBoundaryIdx` variable carries boundary
|
|
295
|
-
changes through the COW pipeline without touching `manager.boundaryIdx` until
|
|
296
|
-
`_commitWorkingGrid` completes. This prevents temporary mismatches between boundary position
|
|
297
|
-
and slot BUY/SELL roles during blockchain execution.
|
|
298
|
-
|
|
299
|
-
```javascript
|
|
300
|
-
// Boundary changes flow through COW pipeline atomically
|
|
301
|
-
const boundarySync = syncBoundaryToFunds(manager); // Returns { changed, newIdx }
|
|
302
|
-
if (boundarySync.changed) {
|
|
303
|
-
pendingBoundaryIdx = boundarySync.newIdx; // NOT manager.boundaryIdx!
|
|
304
|
-
// updateGridFromBlockchainSnapshot reassigns slot types in WorkingGrid
|
|
305
|
-
// manager.boundaryIdx updated atomically in _commitWorkingGrid
|
|
306
|
-
}
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
**Before (Queue-Based):**
|
|
310
|
-
```javascript
|
|
311
|
-
// Detect divergence → Queue corrections → Execute batch → Clear queue
|
|
312
|
-
// Master grid stays ACTIVE during entire process (race condition)
|
|
313
|
-
ordersNeedingPriceCorrection.push({ gridOrder, chainOrderId, isSurplus: true });
|
|
314
|
-
// ...later...
|
|
315
|
-
await updateOrdersOnChainBatchFn({ ordersToCancel, ordersToPlace, ordersToRotate });
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
**After (COW-Based):**
|
|
319
|
-
```javascript
|
|
320
|
-
// Detect divergence → Create WorkingGrid → Update sizes in working copy
|
|
321
|
-
// → Execute UPDATE/CANCEL/CREATE ops on chain → Commit working grid on success
|
|
322
|
-
const workingGrid = new WorkingGrid(manager.orders);
|
|
323
|
-
workingGrid.set(orderId, convertToSpreadPlaceholder(order)); // Surplus → virtual slot
|
|
324
|
-
const actions = [{ type: COW_ACTIONS.CANCEL, id, orderId }, ...];
|
|
325
|
-
const cowResult = { actions, workingGrid, ... };
|
|
326
|
-
await updateOrdersOnChainBatch(cowResult); // Commit only on success
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
**Key Changes:**
|
|
330
|
-
1. **Surplus orders**: `CANCEL` on-chain and virtualize in working grid.
|
|
331
|
-
2. **State preservation**: `ACTIVE`/`PARTIAL` orders keep their state in working grid.
|
|
332
|
-
3. **No race conditions**: master unchanged until blockchain confirms.
|
|
333
|
-
4. **Unified flow**: same COW pattern as fill rebalancing.
|
|
334
|
-
|
|
335
|
-
**Grid Resizing Also Migrated:** `updateGridFromBlockchainSnapshot` now returns a COW result:
|
|
336
|
-
|
|
337
|
-
```javascript
|
|
338
|
-
// Before: Modified master grid directly
|
|
339
|
-
await Grid.updateGridFromBlockchainSnapshot(manager, 'buy'); // Direct update!
|
|
340
|
-
|
|
341
|
-
// After: Returns COW result for batch execution
|
|
342
|
-
const cowResult = await Grid.updateGridFromBlockchainSnapshot(manager, 'buy');
|
|
343
|
-
await updateOrdersOnChainBatch(cowResult); // Execute via COW
|
|
344
|
-
```
|
|
345
|
-
|
|
346
|
-
### Build Step 8: Benchmarks ✅
|
|
347
|
-
- 100 orders: ~0.03ms clone
|
|
348
|
-
- 500 orders: ~0.05ms clone
|
|
349
|
-
- 1000 orders: ~0.08ms clone
|
|
350
|
-
- 5000 orders: ~0.5ms clone
|
|
351
|
-
|
|
352
|
-
### Build Step 9: Cleanup ✅
|
|
353
|
-
- Removed snapshot/rollback pattern; `performSafeRebalance()` now delegates to `_applySafeRebalanceCOW()`.
|
|
354
|
-
- Removed duplicate `_updateOrdersOnChainBatchCOW`.
|
|
355
|
-
- Removed legacy rollback references in `dexbot_class.ts`.
|
|
356
|
-
|
|
357
225
|
## Key Methods
|
|
358
226
|
|
|
359
227
|
### OrderManager (`modules/order/manager.ts`)
|
|
@@ -411,78 +279,13 @@ This architecture makes the "Metadata Reinterpretation" bug impossible by ensuri
|
|
|
411
279
|
|
|
412
280
|
---
|
|
413
281
|
|
|
414
|
-
## Appendix
|
|
415
|
-
|
|
416
|
-
### Files Created
|
|
417
|
-
- `modules/order/working_grid.ts` — WorkingGrid class (COW wrapper with clone/delta/stale tracking).
|
|
418
|
-
- Test files listed under **Build Step 5**.
|
|
419
|
-
- *Dependency utilities consolidated into `modules/order/utils/order.ts` during v0.6.0-patch.19.*
|
|
420
|
-
|
|
421
|
-
### Files Modified
|
|
422
|
-
- `modules/constants.ts` — added `COW_PERFORMANCE` thresholds.
|
|
423
|
-
- `modules/order/manager.ts` — added COW methods, immutable master (`Object.freeze`), version tracking.
|
|
424
|
-
- `modules/dexbot_class.ts` — wired COW broadcast, removed legacy rollback.
|
|
425
|
-
- `modules/order/sync_engine.ts` — uses `_applyOrderUpdate` (lock-free) for all sync paths.
|
|
426
|
-
- `modules/order/grid_reconcile.ts` — uses `_applySync` (lock-free) when inside `_gridLock`.
|
|
427
|
-
- `modules/order/utils/system.ts` — migrated `applyGridDivergenceCorrections` to full COW pattern.
|
|
428
|
-
- `modules/order/grid.ts` — migrated `updateGridFromBlockchainSnapshot` to return COW result instead of modifying master directly.
|
|
429
|
-
|
|
430
|
-
## Appendix B: Test Results
|
|
431
|
-
|
|
432
|
-
```
|
|
433
|
-
Core COW Tests (test_cow_master_plan.ts):
|
|
434
|
-
✓ COW-001: Master unchanged on failure
|
|
435
|
-
✓ COW-002: Master updated only on success
|
|
436
|
-
✓ COW-003: Index transfer
|
|
437
|
-
✓ COW-004: Fund recalculation
|
|
438
|
-
✓ COW-005: Order comparison
|
|
439
|
-
✓ COW-006: Delta building
|
|
440
|
-
✓ COW-007: Index validation
|
|
441
|
-
✓ COW-008: Working grid independence
|
|
442
|
-
✓ COW-009: Empty grid handling
|
|
443
|
-
✓ COW-010: Memory stats
|
|
444
|
-
✓ COW-011: No spurious updates on unchanged grid
|
|
445
|
-
|
|
446
|
-
Commit Guard Tests (test_cow_commit_guards.ts):
|
|
447
|
-
✓ COW-COMMIT-001: Version mismatch rejection
|
|
448
|
-
✓ COW-COMMIT-002: Empty delta rejection
|
|
449
|
-
|
|
450
|
-
Concurrent Fill Tests (test_cow_concurrent_fills.ts):
|
|
451
|
-
✓ COW-FILL-001: Fill during REBALANCING syncs to working grid
|
|
452
|
-
✓ COW-FILL-002: Fill during BROADCASTING syncs to working grid
|
|
453
|
-
✓ COW-FILL-003: Commit rejected after fill during broadcast
|
|
454
|
-
✓ COW-FILL-004: No working grid sync during NORMAL state
|
|
455
|
-
✓ COW-FILL-005: _cloneOrder deep-clones rawOnChain
|
|
456
|
-
✓ COW-FILL-006: _cloneOrder handles missing rawOnChain
|
|
457
|
-
✓ COW-FILL-007: Staleness reason includes phase context
|
|
458
|
-
|
|
459
|
-
Divergence Correction Tests (test_cow_divergence_correction.ts):
|
|
460
|
-
✓ Surplus orders are CANCELLED (not UPDATE to size=0)
|
|
461
|
-
✓ Working grid preserves order states (ACTIVE, PARTIAL)
|
|
462
|
-
✓ Orders within target window get size updates
|
|
463
|
-
✓ No duplicate UPDATE/CANCEL overlap for same order
|
|
464
|
-
|
|
465
|
-
Stale-Plan & Stack Discipline Tests (v1.4.8):
|
|
466
|
-
✓ test_cow_guard_replan.ts — bounded re-plan from fresh master, boundary-budget
|
|
467
|
-
restore, push-marker contract, no double-pop on re-plan failure
|
|
468
|
-
✓ test_cow_stale_slot_guard.ts — slot-id based stale-placement veto,
|
|
469
|
-
boundary-only semantics, rotation-UPDATE coverage
|
|
470
|
-
✓ test_cow_commit_guards.ts — empty-action / never-pushed marker contract
|
|
471
|
-
✓ test_uncertain_broadcast.ts — verify-before-retry per op kind, truncated-read
|
|
472
|
-
deferral, pending-broadcast protection kept on ambiguous reads
|
|
473
|
-
```
|
|
474
|
-
|
|
475
|
-
**Additional Checks:**
|
|
476
|
-
- Unchanged grids do not emit global COW `update` actions.
|
|
477
|
-
- Missing on-chain `ACTIVE` order with `orderId` appears in `filledOrders` from open-order sync.
|
|
478
|
-
|
|
479
|
-
## Appendix C: Constants Added (`modules/constants.ts`)
|
|
282
|
+
## Appendix: COW Constants (`modules/constants.ts`)
|
|
480
283
|
|
|
481
284
|
### COW Performance Thresholds
|
|
482
285
|
- `COW_PERFORMANCE.MAX_REBALANCE_PLANNING_MS` — planning-phase duration above which a slow-plan warning is logged (100ms).
|
|
483
286
|
- `COW_PERFORMANCE.GRID_MEMORY_WARNING` — working grid size (bytes) that triggers a memory warning (5,000).
|
|
484
287
|
- `COW_PERFORMANCE.WORKING_GRID_BYTES_PER_ORDER` — estimated memory per order (500 bytes).
|
|
485
|
-
- `COW_PERFORMANCE.MAX_OPS_PER_BROADCAST` — *removed*; the per-broadcast operation cap is now derived from the grid gap-slot count (`DEXBot._getGapSlotBatchSize`); larger batches are split into sequential broadcasts.
|
|
288
|
+
- `COW_PERFORMANCE.MAX_OPS_PER_BROADCAST` — *removed*; the per-broadcast operation cap is now derived from the grid gap-slot count + 1 (`DEXBot._getGapSlotBatchSize`); larger batches are split into sequential broadcasts.
|
|
486
289
|
|
|
487
290
|
### Pipeline Timing
|
|
488
291
|
- `PIPELINE_TIMING.RECOVERY_DECAY_FALLBACK_MS` — recovery decay fallback (180 seconds).
|
|
@@ -491,7 +294,7 @@ Stale-Plan & Stack Discipline Tests (v1.4.8):
|
|
|
491
294
|
- `GRID_LIMITS.RELATIVE_ORDER_UPDATE_THRESHOLD_PERCENT` — relative threshold (%) for in-memory COW order equality checks.
|
|
492
295
|
- `TIMING.LOCK_REFRESH_MIN_MS` — minimum lock refresh interval (250ms).
|
|
493
296
|
|
|
494
|
-
## Appendix
|
|
297
|
+
## Appendix: Validation Gates
|
|
495
298
|
|
|
496
299
|
Run these tests before promotion:
|
|
497
300
|
- `node dist/tests/test_engine_integration.js`
|
package/docs/COW_INVARIANTS.md
CHANGED
|
@@ -79,11 +79,11 @@ This document defines the non-negotiable behavioral invariants for the DEXBot2 s
|
|
|
79
79
|
- `INV-PROJ-002` Preserve on-chain PARTIAL size in projection
|
|
80
80
|
- If identity is retained (`keepOrderId=true`) and current state is `PARTIAL`, projected size must preserve current on-chain remaining size.
|
|
81
81
|
- It must not be overwritten by ideal geometric `targetSize`.
|
|
82
|
-
- Exception: a `PARTIAL` with a rotation/size-update action targeting its `orderId` does use `targetSize` (the explicit-UPDATE path at `modules/order/utils/validate.ts:
|
|
82
|
+
- Exception: a `PARTIAL` with a rotation/size-update action targeting its `orderId` does use `targetSize` (the explicit-UPDATE path at `modules/order/utils/validate.ts:1129`).
|
|
83
83
|
- Preserve-path size must be normalized to finite, non-negative value.
|
|
84
84
|
|
|
85
85
|
- `INV-PROJ-003` ACTIVE on-chain projection preserves current size (same as PARTIAL)
|
|
86
|
-
- If identity is retained and state is `ACTIVE`, projection preserves current on-chain size via the same `shouldPreserveSize` path as `PARTIAL` (`validate.ts:
|
|
86
|
+
- If identity is retained and state is `ACTIVE`, projection preserves current on-chain size via the same `shouldPreserveSize` path as `PARTIAL` (`validate.ts:1129`).
|
|
87
87
|
- An explicit UPDATE action targeting the `orderId` is required to apply `targetSize`.
|
|
88
88
|
|
|
89
89
|
- `INV-ID-001` Order identity retention rule
|
|
@@ -102,7 +102,7 @@ This document defines the non-negotiable behavioral invariants for the DEXBot2 s
|
|
|
102
102
|
- `INV-ACC-003` Cross-bot fund registry invariant (INVARIANT 3)
|
|
103
103
|
- Shared-account per-bot commitment must not exceed the bot's proportional share of chain balance.
|
|
104
104
|
- Checked with widened tolerance `max(PERCENT_TOLERANCE * 3, 0.15)`.
|
|
105
|
-
- Registry failure logs an error (`accounting.ts:
|
|
105
|
+
- Registry failure logs an error (`order/accounting.ts:574-590`, with a "CRITICAL FIX: Log as ERROR instead of WARN" comment), not a silent skip.
|
|
106
106
|
|
|
107
107
|
---
|
|
108
108
|
|
|
@@ -195,6 +195,13 @@ This document defines the non-negotiable behavioral invariants for the DEXBot2 s
|
|
|
195
195
|
- Top-of-window partials remain always eligible.
|
|
196
196
|
- Two PARTIALs sharing a price with no active sibling do not qualify (left to rebalancer).
|
|
197
197
|
|
|
198
|
+
- `INV-GRID-004` Slot price equals its genesis level ([GRID_PRICE_INVARIANT.md](GRID_PRICE_INVARIANT.md))
|
|
199
|
+
- `order.price` for a slot-`idx` order must equal `priceForSlot(idx, genesis)`; the genesis ladder is the only authoritative price for a slot.
|
|
200
|
+
- Enforced at all six emission sites (CREATE / UPDATE / CREATE-FALLBACK, RECONCILE-CREATE / RECONCILE-UPDATE, STARTUP-CREATE): an off-grid emission is blocked, never broadcast.
|
|
201
|
+
- Range guards (`isChainPriceOutOfGrid`) are bounds checks, not membership checks — they cannot substitute for this invariant.
|
|
202
|
+
- Adoption keeps the slot's own level (a fill/chain price is metadata, not the slot's price); `loadGrid` repairs a pre-existing off-grid slot price at load.
|
|
203
|
+
- Tests: GPI-001..015 (`tests/test_grid_price_invariant_guard.ts`), GPI-WIRE-001..009 (`tests/test_grid_price_invariant_wiring.ts`), LEGACY-ADOPT/MATERIALIZE/ADOPT-NAME (`tests/test_sync_out_of_grid_defer.ts`).
|
|
204
|
+
|
|
198
205
|
---
|
|
199
206
|
|
|
200
207
|
## Reconcile ([GRID_RECONCILE.md](GRID_RECONCILE.md))
|
|
@@ -208,18 +215,17 @@ This document defines the non-negotiable behavioral invariants for the DEXBot2 s
|
|
|
208
215
|
- Dust health thresholding applies consistently to both CREATE and rotation destination holes.
|
|
209
216
|
|
|
210
217
|
- `INV-RECON-003` Reconcile cancels duplicate chain orders unconditionally
|
|
211
|
-
-
|
|
218
|
+
- An unmatched chain order whose price equals an active same-type grid slot's price (exact slot-price equality via `priceSlotEqual` at the asset precision) is a suspected duplicate and must be cancelled on chain via `_cancelChainOrder` with `releaseUntrackedFunds: true`.
|
|
212
219
|
- Cancelled IDs are filtered out of `unmatchedParsed` to prevent reprocessing.
|
|
213
220
|
- No size guard — any duplicate at the same price is a violation.
|
|
214
|
-
- `
|
|
215
|
-
- `SUSPECTED_DUPLICATE_TOLERANCE_MULTIPLIER` is a file-local constant (`modules/order/grid_reconcile.ts`, value `5`), not a centralized `constants.ts` entry.
|
|
221
|
+
- The earlier fuzzy `SUSPECTED_DUPLICATE_TOLERANCE_MULTIPLIER` (5× `calculatePriceTolerance`) and `SUSPECTED_DUPLICATE_TOLERANCE_FLOOR` are removed; only exact price-level equality triggers a reconcile cancel.
|
|
216
222
|
|
|
217
223
|
- `INV-RECON-004` Rebalance must not convert on-chain slots to SPREAD via CREATE
|
|
218
224
|
- `performSafeRebalance` must not emit `CREATE` actions that convert existing on-chain slots into SPREAD orders.
|
|
219
225
|
- On-chain mid-slot must keep its BUY/SELL type before commit.
|
|
220
226
|
|
|
221
227
|
- `INV-RECON-005` Extreme placement ordering
|
|
222
|
-
- BUY placements must use nearest available free slots first (descending price, so the nearest-to-center slots fill first — `
|
|
228
|
+
- BUY placements must use nearest available free slots first (descending price, so the nearest-to-center slots fill first — `order/utils/order.ts` `buildOutsideInPairGroups`).
|
|
223
229
|
- SELL placements must use nearest available free slots first (ascending price).
|
|
224
230
|
|
|
225
231
|
---
|
|
@@ -228,7 +234,7 @@ This document defines the non-negotiable behavioral invariants for the DEXBot2 s
|
|
|
228
234
|
|
|
229
235
|
- `INV-BATCH-001` Illegal state batch abort
|
|
230
236
|
- `executeBatch` throws `ILLEGAL_SPREAD_STATE` on an illegal grid layout (emitted at `modules/order/utils/validate.ts`, propagated via `modules/order/manager.ts` `_throwOnIllegalState`).
|
|
231
|
-
- The `_handleBatchHardAbort` catch for `ILLEGAL_ORDER_STATE` (`
|
|
237
|
+
- The `_handleBatchHardAbort` catch for `ILLEGAL_ORDER_STATE` (`dexbot_class.ts:455`) is a test-only dead branch — production never emits that code; only a test stub uses it.
|
|
232
238
|
- In production, recovery + cooldown are armed on the next maintenance tick via `_abortFlowIfIllegalState` (the `INV-MAINT-002` path), returning `abortedForIllegalState: true` to the caller. The caller does not need to return immediately; the maintenance tick handles recovery.
|
|
233
239
|
- Hard abort triggers one immediate recovery sync (`_triggerStateRecoverySync`) plus arms one maintenance cooldown cycle (`_maintenanceCooldownCycles = Math.max(current, 1)`).
|
|
234
240
|
|
|
@@ -247,7 +253,7 @@ This document defines the non-negotiable behavioral invariants for the DEXBot2 s
|
|
|
247
253
|
- NOT virtualize the slot.
|
|
248
254
|
- Preserve `orderId` until sync reconciles it.
|
|
249
255
|
- NOT mark the order as stale-cleaned.
|
|
250
|
-
- Fast path: if the batch result indicates `ORDER_SIZE_DRIFT_TARGETED` (`dexbot_state_recovery.ts:
|
|
256
|
+
- Fast path: if the batch result indicates `ORDER_SIZE_DRIFT_TARGETED` (`dexbot_state_recovery.ts:269`), a targeted repair applies the correction directly and skips `_triggerStateRecoverySync`.
|
|
251
257
|
|
|
252
258
|
---
|
|
253
259
|
|
|
@@ -271,7 +277,7 @@ This document defines the non-negotiable behavioral invariants for the DEXBot2 s
|
|
|
271
277
|
- `INV-REG-001` Cross-bot allocation ≤ proportional share
|
|
272
278
|
- Per-bot committed amounts (sum of on-chain orders) must not exceed `totalChainBalance × allocatedPercent`.
|
|
273
279
|
- Violation triggers an error-level log entry (not silent), with tolerance `max(PERCENT_TOLERANCE * 3, 0.15)`.
|
|
274
|
-
- Registry registration is pre-flight + atomic; only shared-account bots register (`dexbot.ts:
|
|
280
|
+
- Registry registration is pre-flight + atomic; only shared-account bots register (`dexbot.ts:611` filters `accountGroups[a].length > 1`), and registration completes before any shared-account bot starts.
|
|
275
281
|
- Release happens in `DEXBot.shutdown`.
|
|
276
282
|
|
|
277
283
|
- `INV-REG-002` Async-locked registry writes
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# DEXBot vs DEXBot2 — Detailed Comparison Report
|
|
2
2
|
|
|
3
3
|
> **Date:** 2026-09-02 *(metrics refreshed against local source trees)*
|
|
4
|
-
> **Scope:** Full architectural, functional, and operational comparison between the original [DEXBot](https://github.com/Codaone/DEXBot) (Python, v1.0.0) and DEXBot2 (TypeScript, v1.6.
|
|
4
|
+
> **Scope:** Full architectural, functional, and operational comparison between the original [DEXBot](https://github.com/Codaone/DEXBot) (Python, v1.0.0) and DEXBot2 (TypeScript, v1.6.5).
|
|
5
5
|
> **Audience:** Developers, contributors, and operators evaluating or migrating between the two projects.
|
|
6
6
|
|
|
7
7
|
---
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
|
|
37
37
|
| Attribute | DEXBot (original) | DEXBot2 |
|
|
38
38
|
|---|---|---|
|
|
39
|
-
| **Release Track** | 1.0.0 | v1.6.
|
|
39
|
+
| **Release Track** | 1.0.0 | v1.6.5 |
|
|
40
40
|
| **Language** | Python 3.6+ | TypeScript 5.x |
|
|
41
41
|
| **Status** | Released 1.0.0, unmaintained | Active development |
|
|
42
42
|
| **Last Repo Activity** | May 23, 2020 | 2026-09-02 |
|
|
@@ -776,7 +776,7 @@ Where:
|
|
|
776
776
|
|
|
777
777
|
| Metric | DEXBot | DEXBot2 |
|
|
778
778
|
|---|---|---|
|
|
779
|
-
| **Release Track** | 1.0.0 | v1.6.
|
|
779
|
+
| **Release Track** | 1.0.0 | v1.6.5 |
|
|
780
780
|
| **Active Since** | ~2018 | December 2025 |
|
|
781
781
|
| **Last Commit** | May 23, 2020 | 2026-09-02 |
|
|
782
782
|
| **Total Commits** | 2281 | 2,125 (v1.4.25) |
|
package/docs/EVOLUTION.md
CHANGED
|
@@ -2,14 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
## Executive Summary
|
|
4
4
|
|
|
5
|
-
DEXBot2 is a sophisticated decentralized exchange trading bot for the BitShares blockchain. This report documents the complete evolution of the project from its inception in December 2025 through the current 1.6.
|
|
5
|
+
DEXBot2 is a sophisticated decentralized exchange trading bot for the BitShares blockchain. This report documents the complete evolution of the project from its inception in December 2025 through the current 1.6.5 stable release.
|
|
6
6
|
|
|
7
7
|
### Key Milestones
|
|
8
8
|
- **Project Inception**: December 2, 2025
|
|
9
|
-
|
|
9
|
+
- **Growth Phase**: 2,263 commits over ~9 active months
|
|
10
10
|
- **Code Maturity**: Evolution from basic utilities to a ~100,000+ LoC intelligent TypeScript system
|
|
11
|
-
- **Stability**: Progression from manual testing to a suite of
|
|
12
|
-
- **Releases**:
|
|
11
|
+
- **Stability**: Progression from manual testing to a suite of 309 automated test files
|
|
12
|
+
- **Releases**: 109 release entries (v0.1.0 to v1.6.5)
|
|
13
|
+
|
|
14
|
+
> **Post-1.0.0 "why":** the thematic story behind the hardening releases — root cause, recurring
|
|
15
|
+
> bug families, and lessons — lives in
|
|
16
|
+
> [ORDER_ENGINE_POST_1.0_RETROSPECTIVE.md](ORDER_ENGINE_POST_1.0_RETROSPECTIVE.md).
|
|
17
|
+
> This report stays chronological.
|
|
13
18
|
|
|
14
19
|
---
|
|
15
20
|
|
|
@@ -61,10 +66,62 @@ v1.4.12 completed the module transition to native ES modules (root + claw `"type
|
|
|
61
66
|
|
|
62
67
|
### Phase 9: Post-ESM Cleanup, Consolidation & Hardening (August 2026)
|
|
63
68
|
|
|
64
|
-
The post-ESM releases consolidated state,
|
|
69
|
+
The post-ESM releases consolidated state, packaging, and tooling while hardening the grid engine — profile state on a resolver-derived `~/.config/dexbot2` dir, in-place order rotations, npm auto-update, dead-code purge, and a compile-first runtime (tsx removed; every entry point and the test suite run compiled `dist` under plain node). Grid work capped COW broadcasts and chunked retry-on-uncertain, gated boundary promotion and persisted-restore against gap-floor poison, fixed spread-collapse via the shared `isSlotInRail` filter, and cleared silent-failure defects from a modules-wide audit. **v1.4.24** fixed native fill-gap recovery and LP pricing; **v1.4.25** froze genesis price-slots and hardened orphan/self-trade/fill-guard/shutdown paths.
|
|
65
70
|
|
|
66
71
|
---
|
|
67
72
|
|
|
73
|
+
## Architecture Deep-Dive: COW & Memory Tracking
|
|
74
|
+
|
|
75
|
+
Two mechanisms shaped the order engine after the browser/TypeScript era: the Copy-on-Write grid
|
|
76
|
+
and the memory-only integer tracking model. The construction detail that used to live in
|
|
77
|
+
`COPY_ON_WRITE_MASTER_PLAN.md` and `architecture.md` is recorded here; those docs now describe
|
|
78
|
+
only the current design.
|
|
79
|
+
|
|
80
|
+
### Copy-on-Write: three eras
|
|
81
|
+
|
|
82
|
+
- **Era 0 — original optimistic state (pre-v1.0):** the master grid was mutated directly during
|
|
83
|
+
planning, with no isolation or rollback. A sudden market move corrupted in-flight state (the
|
|
84
|
+
"Price Jump" incident — planning mutations applied straight to the master grid).
|
|
85
|
+
- **Era 1 — frozen master state (v1.0):** `Object.freeze()` on the master Map and `deepFreeze()`
|
|
86
|
+
on order objects; every `_applyOrderUpdate` creates a new frozen Map via the immutable-swap
|
|
87
|
+
pattern. Retained as defense-in-depth — it catches accidental in-place mutation of
|
|
88
|
+
`manager.orders`.
|
|
89
|
+
- **Era 2 — Copy-on-Write (v2.0, current):** clone the master into a `WorkingGrid`, plan and
|
|
90
|
+
broadcast on the clone, commit atomically on blockchain success (discard on failure). True
|
|
91
|
+
transactional semantics; the master is never in an intermediate state.
|
|
92
|
+
|
|
93
|
+
The production code layers Era 1 and Era 2: freeze provides runtime mutation enforcement, COW
|
|
94
|
+
provides the plan → broadcast → commit/discard lifecycle.
|
|
95
|
+
|
|
96
|
+
### COW construction milestones (February–April 2026)
|
|
97
|
+
|
|
98
|
+
- `modules/order/working_grid.ts` (`WorkingGrid`: clone, delta, stale tracking) and
|
|
99
|
+
`COW_PERFORMANCE` thresholds added.
|
|
100
|
+
- `performSafeRebalance` → `_applySafeRebalanceCOW`; `buildDelta`; `_commitWorkingGrid` atomic
|
|
101
|
+
swap.
|
|
102
|
+
- COW broadcast path (`_updateOrdersOnChainBatchCOW`); legacy rollback code removed.
|
|
103
|
+
- Selective-abort fill strategy: individual fills continue, full-side updates block.
|
|
104
|
+
- Divergence corrections and `updateGridFromBlockchainSnapshot` migrated to the COW pattern.
|
|
105
|
+
- Atomic boundary shifts (patch 20): `pendingBoundaryIdx` carries boundary changes through the
|
|
106
|
+
pipeline and applies them only at `_commitWorkingGrid`, so boundary position and slot BUY/SELL
|
|
107
|
+
roles never transiently disagree during blockchain execution.
|
|
108
|
+
- Validation suites added: COW core, commit-guard, concurrent-fill, divergence-correction, and
|
|
109
|
+
stale-plan/stack-discipline tests.
|
|
110
|
+
|
|
111
|
+
### Memory-only integer tracking
|
|
112
|
+
|
|
113
|
+
- **Raw order cache (`rawOnChain`):** grid slots store the exact blockchain order integers
|
|
114
|
+
(satoshis); seeded from broadcast arguments on placement, updated in place on partial fills,
|
|
115
|
+
refreshed on updates/rotations.
|
|
116
|
+
- **Chain-free planning:** redundant `readOpenOrders()` calls were removed from the size-update
|
|
117
|
+
and rotation builders (`_buildSizeUpdateOps()`, `_buildRotationOps()`), and the
|
|
118
|
+
`computeVirtualOpenOrders()` virtual-order computation was dropped; `buildUpdateOrderOp`
|
|
119
|
+
gained an optional `cachedOrder` and returns `finalInts`.
|
|
120
|
+
- **Result:** batch updates and rotations run without blockchain fetches; only placements and
|
|
121
|
+
recovery syncs query the chain (~10–20× faster high-frequency operations).
|
|
122
|
+
- **Self-healing:** a failed memory-driven transaction triggers a full state-recovery sync so the
|
|
123
|
+
internal ledger stays consistent with the chain.
|
|
124
|
+
|
|
68
125
|
## Technical Challenges & Solutions
|
|
69
126
|
|
|
70
127
|
| Challenge | Solution | Impact |
|
|
@@ -86,42 +143,31 @@ Evolved from a basic README to a comprehensive framework (50+ docs entries, 80%+
|
|
|
86
143
|
|
|
87
144
|
## Post-1.0.0 Status
|
|
88
145
|
|
|
89
|
-
**Completed**: browser-safe core
|
|
146
|
+
**Completed**: browser-safe core; credit/MPA runtime; storage-adapter I/O centralization; self-healing recovery; Kibana PnL analytics; credit-only mode; Docker support; npm package. For the grid order engine arc specifically (COW pipeline, orphan/self-trade/fill-guard hardening, invariants) see [ORDER_ENGINE_POST_1.0_RETROSPECTIVE.md](ORDER_ENGINE_POST_1.0_RETROSPECTIVE.md) §R4.
|
|
90
147
|
|
|
91
148
|
**Planned**: backtesting engine (historical candle replay via exchange abstraction); injectable interfaces at call boundaries; SQLite persistence + Zod validation at the blockchain boundary; Telegram bot (**not yet implemented**) — owner-gated monitoring (`/status`, `/orders`, `/grid`, `/balance`) and opt-in+confirm gated control (`/start`, `/stop`, `/pause`); DEXBot is the only writer, private keys never reach the module (`TELEGRAM` block + `DEXBOT_TELEGRAM_TOKEN` env).
|
|
92
149
|
|
|
93
150
|
## Version History
|
|
94
151
|
|
|
95
|
-
Compact, era-level view
|
|
152
|
+
Compact, era-level view. Per-release detail lives in [CHANGELOG.md](../CHANGELOG.md); the thematic post-1.0.0 story in [ORDER_ENGINE_POST_1.0_RETROSPECTIVE.md](ORDER_ENGINE_POST_1.0_RETROSPECTIVE.md).
|
|
96
153
|
|
|
97
154
|
| Era | Commits | Theme |
|
|
98
155
|
|-----|--------:|-------|
|
|
99
156
|
| v0.1.0 → v0.6.0 | 1,217 | Foundation → COW architecture, strategy/sync engine, credential daemon, AMA prototype, credit/MPA runtime |
|
|
100
|
-
| v0.6.0 → v1.0.0 | 309 | Zero-dependency & TS migration, native BitShares, fill
|
|
101
|
-
| v1.0.0 → v1.
|
|
102
|
-
| v1.
|
|
103
|
-
| v1.
|
|
104
|
-
| v1.4.
|
|
105
|
-
| v1.
|
|
106
|
-
| v1.
|
|
107
|
-
| v1.
|
|
108
|
-
| v1.4
|
|
109
|
-
| v1.4.22 → v1.4.23 | 12 | Even geometric AMA ladder, BTS fee-carve fix, sub-1x price-bound rejection, tradingview axis restore, doc realignment |
|
|
110
|
-
| v1.4.23 → v1.4.24 | 3 | Native fill gap recovery with eager coalesced retry, LP collateral offer-first pricing |
|
|
111
|
-
| v1.4.24 → v1.4.25 | 26 | Genesis-frozen price-slots, self-trade & fill-guard hardening, orphan & gap-band fixes, trigger/shutdown hardening, bot poll, grid monotonicity gate, whitelist scoped overwrite, Range legend |
|
|
112
|
-
| v1.4.25 → v1.5.0 | 13 | Credit overview CLI + whitelist-scoped CR on shared pricing math, one-step TradingView chart, daemon-safe reload, offline account-ID cache, case-insensitive bot identity, stale-pivot guard fix, partial-surplus rotation clamp, adapter ownership centralization, op-77 bot discovery split |
|
|
113
|
-
| v1.5.0 → v1.5.1 | 11 | Gap-evacuation guard allowance + rail-typed holes, persisted streaks with cancel-only teeth, vacated-rail refill, adoption/accounting/duplicate-guard hardening |
|
|
114
|
-
| v1.5.1 → v1.5.2 | 10 | Sync rejection handling across pass-1/pass-2 adoption, crossing-guard candidate sharing, empty-read confirmation, broadcast-price CREATE validation, stamped gap-evacuation re-proof, credit whole-account display + expiry, offline export fill-block derivation |
|
|
115
|
-
| v1.5.2 → v1.5.3 | 6 | Boundary ownership hardening (fund-driven sync removal, guard-skipped refill hold), COW broadcast/reconcile dedup, TradingView bot-grid range highlight, createOrder unknown-id materialize-or-error, curve-comparison docs |
|
|
116
|
-
| v1.5.3 → v1.6.0 | 37 | Node-failure strike ledger and broadcast-deferred fill rebalancing, trust-chain free-balance heal with deferred-drain tolerance, bidirectional grid-regeneration trigger, TradingView order overlay and chart pref namespacing, credit short-offer id display, live-config pickup (issue #27), reserve ladder anchored at resolved bounds + live-grid rail edges with single-source ordering and exact-size activation, owed-crawl persistence across refused broadcasts/restarts + hold-aware reload-safe lifecycle, fill-anchored boundary recovery + poisoned persisted-boundary erase, startup rail gate + static-center crawl fold, all `*-deferred` holds non-blocking + hold metrics surfaced, opt-in MPA price-feed charts + range-aware shared candle cache, range-band span parity on grid-less charts, orange range zone widened to 1.40x, docs reserve-ladder sweep, reserve-deficit targeted-sync trigger with window-exclusion counting, matched-surplus startup excess planning, shelf-order guards across reserve classification/placement/startup cancels/size recalc (issue #27 follow-ups), unified Kibana candle cache on runCachedWindows with fetch retry budgets, genuine-coverage LP window reuse, feed volume/AMA timeframe alignment, TradingView monthly candles/stat badges/rigid pan/volume toggle/feed affordance, credit full offer id + empty-pair Curr. CR hiding, live-config onboarding note |
|
|
117
|
-
| v1.6.0 → v1.6.1 | 3 | Never-run-stale hardening (level-triggered deferred-fill retry, stale-totals fill parking, out-of-spread watchdog, region-end fan-out, one-sided spread honesty), whitelist range-scaling opt-in defaults, live-save vs reset vs reload docs + power-law paper restructure |
|
|
118
|
-
| v1.6.1 → v1.6.2 | 6 | Grid-price invariant + resync escalation, gap-slot batch sizing, shard candle cache + chart fixes, recovery stranding tolerance, fill-counter hygiene, dead-node prune + trace single-sourcing, obsolete-doc removal |
|
|
119
|
-
| v1.6.2 → v1.6.3 | 3 | Correction-queue staleness guard (validate queued price corrections against live slot), grid-checker price epochs across repriced order lifetimes, final pre-broadcast pivot gate (re-check built ops when a fill queued after the freeze moved the pivot) |
|
|
157
|
+
| v0.6.0 → v1.0.0 | 309 | Zero-dependency & TS migration, native BitShares, fill-detection overhaul, first stable release |
|
|
158
|
+
| v1.0.0 → v1.3.3 | 199 | Post-stable hardening, PnL analytics, auto-update, broadcast-deadlock fixes, AMA refits, credit-only mode, COW recovery hardening, runtime extraction |
|
|
159
|
+
| v1.3.3 → v1.4.13 | 119 | CJS→ESM completion, concurrency correction, uncertain-broadcast & truncated-read safety, native ESM runtime, broadcast serialization, onboarding |
|
|
160
|
+
| v1.4.13 → v1.4.25 | 101 | Profile-state centralization, consolidation, per-broadcast op cap, grid boundary/recovery hardening, tsx removal, genesis-frozen price-slots, self-trade & orphan fixes |
|
|
161
|
+
| v1.4.25 → v1.5.3 | 40 | Credit overview + whitelist-scoped CR, TradingView tooling, daemon-safe reload, gap-evacuation/rail-hole hardening, sync adoption hardening, boundary ownership |
|
|
162
|
+
| v1.5.3 → v1.6.0 | 37 | Node-failure ledger, grid regeneration, reserve ladder, live-config pickup, owed-crawl persistence, fill-anchored boundary recovery, TradingView overlay |
|
|
163
|
+
| v1.6.0 → v1.6.3 | 12 | Never-run-stale hardening, whitelist range-scaling opt-in, grid-price invariant, shard candle cache, correction-queue staleness, final pre-broadcast pivot gate |
|
|
164
|
+
| v1.6.3 → v1.6.4 | 18 | Fund-driven spread correction, gapSlots+1 batch cap, VIRTUAL RMS divergence, sync-lock log fix, invariant-doc contract, analysis shared modules, window-aware profitability annualisation, portable chart exports, range-threshold restore, dead-code purge, doc consolidation |
|
|
165
|
+
| v1.6.4 → v1.6.5 | 15 | Editor-managed whitelist flags + legacy generator removal, centralized bot defaults/settings docs, log-symmetric range-scaling tilt, AMA gridPrice default + unset → startPrice normalization, Pool default/warn-color cues, Grid Health AMA-slope Δ knob, dynamic-weight chart CLI, update dist-freshness self-heal, launcher worker rename, RMS log tagging |
|
|
120
166
|
|
|
121
167
|
---
|
|
122
168
|
|
|
123
169
|
**Report Originally Generated**: February 19, 2026
|
|
124
|
-
**Last Updated**: September
|
|
125
|
-
**Total Commits**: 2,
|
|
126
|
-
**Date Range**: December 2, 2025 – September
|
|
170
|
+
**Last Updated**: September 23, 2026
|
|
171
|
+
**Total Commits**: 2,263
|
|
172
|
+
**Date Range**: December 2, 2025 – September 23, 2026
|
|
127
173
|
**Repository**: DEXBot2 (BitShares DEX Trading Bot)
|
|
@@ -67,7 +67,7 @@ Mixed BUY/SELL batches are validated per asset using a signed-delta **peak** run
|
|
|
67
67
|
|
|
68
68
|
#### Implementation Location
|
|
69
69
|
|
|
70
|
-
File: `modules/dexbot_cow_runtime.ts` — `validateOperationFunds()` (line
|
|
70
|
+
File: `modules/dexbot_cow_runtime.ts` — `validateOperationFunds()` (line 1655), called from the COW batch broadcast path at line 4457.
|
|
71
71
|
|
|
72
72
|
```javascript
|
|
73
73
|
// Per-asset peak requirement vs. quantized chain-free snapshot.
|
|
@@ -114,9 +114,9 @@ See [developer_guide.md#order-state-helper-functions](developer_guide.md#order-s
|
|
|
114
114
|
|
|
115
115
|
**Mechanism**: Fill events arrive via `modules/dexbot_fill_runtime.ts` (the fill-runtime module), which pushes them into `bot._incomingFillQueue` (declared in `modules/dexbot_class.ts`). The drain loop in `dexbot_fill_runtime.ts` then chunks the queue into capped batches and calls `modules/order/manager.ts::processFilledOrders` (line 1438) once per chunk to run the full rebalance pipeline.
|
|
116
116
|
|
|
117
|
-
**Batch Sizing Algorithm**: Batch size is derived from the grid gap-slot count (`DEXBot._getGapSlotBatchSize`): a queue depth at or below gapSlots is processed as one unified batch; deeper queues are chunked into repeated batches of gapSlots (the last chunk may be smaller). The same
|
|
117
|
+
**Batch Sizing Algorithm**: Batch size is derived from the grid gap-slot count + 1 (`DEXBot._getGapSlotBatchSize`): a queue depth at or below gapSlots+1 is processed as one unified batch; deeper queues are chunked into repeated batches of gapSlots+1 (the last chunk may be smaller). The same gapSlots+1 size caps order operations per broadcast transaction (oversized op batches are split into sequential broadcasts).
|
|
118
118
|
|
|
119
|
-
**Configuration**: no fixed constant — both `FILL_PROCESSING.MAX_FILL_BATCH_SIZE` and `COW_PERFORMANCE.MAX_OPS_PER_BROADCAST` were removed; batch sizing follows the grid gap-slot count.
|
|
119
|
+
**Configuration**: no fixed constant — both `FILL_PROCESSING.MAX_FILL_BATCH_SIZE` and `COW_PERFORMANCE.MAX_OPS_PER_BROADCAST` were removed; batch sizing follows the grid gap-slot count + 1.
|
|
120
120
|
|
|
121
121
|
#### Fill Batch Processing Timeline
|
|
122
122
|
|
|
@@ -299,7 +299,7 @@ When a fill occurs, the boundary shifts to "follow" the price.
|
|
|
299
299
|
|
|
300
300
|
### 3.2 Global Side Capping
|
|
301
301
|
|
|
302
|
-
Budgets are dynamic. The bot calculates `
|
|
302
|
+
Budgets are dynamic. The bot calculates the per-side budget via `getSideBudget` from `funds.allocated.{buy,sell}` (the `botFunds`-capped capital per side — see §1.3). This ensures the bot never attempts to deploy more than its configured share of account capital, even when the account holds additional free balance for other bots or manual trading.
|
|
303
303
|
|
|
304
304
|
**Safety Check:**
|
|
305
305
|
If the calculated ideal grid requires more capital than available in the allocation, the *increase* is capped.
|
|
@@ -478,15 +478,15 @@ When a grid is regenerated or resized, existing partial orders (partially filled
|
|
|
478
478
|
A partial order is classified as **Dust** if:
|
|
479
479
|
$$Size_{current} < Size_{ideal} \times 0.05$$
|
|
480
480
|
|
|
481
|
-
Dust orders are too small to be efficient on-chain and are
|
|
481
|
+
Dust orders are too small to be efficient on-chain and are **cancelled immediately on detection** — no delay, no timer (`cancelDustOrders()`, `[DUST]` tag). Detection runs on every fill/sync tick plus a 5-minute health check (`DUST_HEALTH_CHECK_INTERVAL_MS`) as a crash/restart safety net; the cancel flows through the synthetic-fill pipeline so funds return to `ChainFree`.
|
|
482
482
|
|
|
483
483
|
### 4.2 Consolidation Strategy
|
|
484
484
|
|
|
485
485
|
When the strategy engine encounters partial orders during rebalancing:
|
|
486
486
|
|
|
487
487
|
**Direct Approach** (Simplified):
|
|
488
|
-
1. **
|
|
489
|
-
2. **
|
|
488
|
+
1. **Cancel dust first**: partials below the 5% dust threshold are cancelled on detection (see §4.1) and never reach the rebuild
|
|
489
|
+
2. **Consolidate the remainder**: surviving partials are absorbed when the grid is rebuilt in the next rebalance cycle
|
|
490
490
|
3. **Fund-driven grid rebuild**: Rather than complex slot-by-slot merge/split logic, the entire grid is regenerated based on current total funds (including proceeds from fills)
|
|
491
491
|
4. **Natural redistribution**: The rebuilt grid automatically sizes all orders (including those replacing consolidation candidates) using the Ideal Grid sizing formula
|
|
492
492
|
5. **Spread maintenance**: The target spread gap remains constant at `targetSpreadPercent`—no dynamically inflated corrections
|
|
@@ -751,7 +751,7 @@ Quantization has a single source of truth: `quantizeFloat()` in `modules/order/u
|
|
|
751
751
|
|
|
752
752
|
#### 5.5.4 Relationship to Fund Validation
|
|
753
753
|
|
|
754
|
-
The corrected fund validation in `
|
|
754
|
+
The corrected fund validation in `validateOperationFunds()` uses quantized values:
|
|
755
755
|
|
|
756
756
|
```javascript
|
|
757
757
|
// Check: Does required amount fit in available balance?
|
|
@@ -801,4 +801,4 @@ To prevent "Time-of-Check to Time-of-Use" errors:
|
|
|
801
801
|
**TOCTOU protection in `processFillAccounting`.** `_buildBtsDeferredRefundAdjustment` reads `btsFeeState` from `mgr.orders` while the order lock is held — the lock is acquired before accounting runs, and the POST-RESET and BOOTSTRAP tracked-fill accounting paths follow the same locking pattern.
|
|
802
802
|
|
|
803
803
|
---
|
|
804
|
-
*Technical Reference for DEXBot2 v1.6.
|
|
804
|
+
*Technical Reference for DEXBot2 v1.6.5 release*
|