dexbot 1.1.10
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/LICENSE +21 -0
- package/README.md +287 -0
- package/claw/README.md +513 -0
- package/claw/scripts/memu_runner.py +385 -0
- package/claw/skills/bitshares-guide/SKILL.md +14 -0
- package/claw/skills/bitshares-guide/references/example-skill-shells.md +18 -0
- package/claw/skills/bitshares-guide/references/presentation-patterns.md +19 -0
- package/claw/skills/bitshares-guide/references/scope-guardrails.md +9 -0
- package/claw/skills/launcher-ops/SKILL.md +18 -0
- package/claw/skills/launcher-ops/references/launcher-workflow.md +23 -0
- package/claw/skills/margin-trading/SKILL.md +23 -0
- package/claw/skills/margin-trading/references/honest-asset-list.md +74 -0
- package/claw/skills/margin-trading/references/honest-assets.md +44 -0
- package/claw/skills/margin-trading/references/position-management.md +203 -0
- package/claw/skills/margin-trading/references/trading-concepts.md +80 -0
- package/claw/skills/memu-memory/SKILL.md +218 -0
- package/claw/skills/shared/references/js-automation-overview.md +24 -0
- package/claw/skills/shared/references/safety-and-staleness.md +11 -0
- package/claw/skills/shared/references/skill-boundaries.md +17 -0
- package/claw/skills/trend-detection/SKILL.md +33 -0
- package/claw/skills/trend-detection/agents/openai.yaml +3 -0
- package/claw/skills/trend-detection/references/service.md +45 -0
- package/dist/analysis/ama_fitting/analyze_ama_price_changes.d.ts +3 -0
- package/dist/analysis/ama_fitting/analyze_ama_price_changes.d.ts.map +1 -0
- package/dist/analysis/ama_fitting/analyze_ama_price_changes.js +149 -0
- package/dist/analysis/ama_fitting/analyze_ama_price_changes.js.map +1 -0
- package/dist/analysis/ama_fitting/analyze_lambda_vs_slow.d.ts +3 -0
- package/dist/analysis/ama_fitting/analyze_lambda_vs_slow.d.ts.map +1 -0
- package/dist/analysis/ama_fitting/analyze_lambda_vs_slow.js +387 -0
- package/dist/analysis/ama_fitting/analyze_lambda_vs_slow.js.map +1 -0
- package/dist/analysis/ama_fitting/calibrate_convergence_er.d.ts +3 -0
- package/dist/analysis/ama_fitting/calibrate_convergence_er.d.ts.map +1 -0
- package/dist/analysis/ama_fitting/calibrate_convergence_er.js +200 -0
- package/dist/analysis/ama_fitting/calibrate_convergence_er.js.map +1 -0
- package/dist/analysis/ama_fitting/fetch_lp_candles.d.ts +3 -0
- package/dist/analysis/ama_fitting/fetch_lp_candles.d.ts.map +1 -0
- package/dist/analysis/ama_fitting/fetch_lp_candles.js +212 -0
- package/dist/analysis/ama_fitting/fetch_lp_candles.js.map +1 -0
- package/dist/analysis/ama_fitting/generate_unified_comparison_chart.d.ts +31 -0
- package/dist/analysis/ama_fitting/generate_unified_comparison_chart.d.ts.map +1 -0
- package/dist/analysis/ama_fitting/generate_unified_comparison_chart.js +249 -0
- package/dist/analysis/ama_fitting/generate_unified_comparison_chart.js.map +1 -0
- package/dist/analysis/ama_fitting/optimizer_high_resolution.d.ts +2 -0
- package/dist/analysis/ama_fitting/optimizer_high_resolution.d.ts.map +1 -0
- package/dist/analysis/ama_fitting/optimizer_high_resolution.js +782 -0
- package/dist/analysis/ama_fitting/optimizer_high_resolution.js.map +1 -0
- package/dist/analysis/analyze_derivatives.d.ts +95 -0
- package/dist/analysis/analyze_derivatives.d.ts.map +1 -0
- package/dist/analysis/analyze_derivatives.js +295 -0
- package/dist/analysis/analyze_derivatives.js.map +1 -0
- package/dist/analysis/analyze_dynamic_weight.d.ts +14 -0
- package/dist/analysis/analyze_dynamic_weight.d.ts.map +1 -0
- package/dist/analysis/analyze_dynamic_weight.js +208 -0
- package/dist/analysis/analyze_dynamic_weight.js.map +1 -0
- package/dist/analysis/analyze_kalman.d.ts +13 -0
- package/dist/analysis/analyze_kalman.d.ts.map +1 -0
- package/dist/analysis/analyze_kalman.js +123 -0
- package/dist/analysis/analyze_kalman.js.map +1 -0
- package/dist/analysis/analyze_regime.d.ts +20 -0
- package/dist/analysis/analyze_regime.d.ts.map +1 -0
- package/dist/analysis/analyze_regime.js +139 -0
- package/dist/analysis/analyze_regime.js.map +1 -0
- package/dist/analysis/analyze_regime_windows.d.ts +19 -0
- package/dist/analysis/analyze_regime_windows.d.ts.map +1 -0
- package/dist/analysis/analyze_regime_windows.js +413 -0
- package/dist/analysis/analyze_regime_windows.js.map +1 -0
- package/dist/analysis/analyze_risk_profile.d.ts +3 -0
- package/dist/analysis/analyze_risk_profile.d.ts.map +1 -0
- package/dist/analysis/analyze_risk_profile.js +159 -0
- package/dist/analysis/analyze_risk_profile.js.map +1 -0
- package/dist/analysis/analyze_trade_heatmap.d.ts +3 -0
- package/dist/analysis/analyze_trade_heatmap.d.ts.map +1 -0
- package/dist/analysis/analyze_trade_heatmap.js +367 -0
- package/dist/analysis/analyze_trade_heatmap.js.map +1 -0
- package/dist/analysis/analyze_volatility.d.ts +22 -0
- package/dist/analysis/analyze_volatility.d.ts.map +1 -0
- package/dist/analysis/analyze_volatility.js +172 -0
- package/dist/analysis/analyze_volatility.js.map +1 -0
- package/dist/analysis/bot_fitting/backtest_ama_sweep.d.ts +99 -0
- package/dist/analysis/bot_fitting/backtest_ama_sweep.d.ts.map +1 -0
- package/dist/analysis/bot_fitting/backtest_ama_sweep.js +804 -0
- package/dist/analysis/bot_fitting/backtest_ama_sweep.js.map +1 -0
- package/dist/analysis/bot_fitting/backtest_bot_fitting.d.ts +2 -0
- package/dist/analysis/bot_fitting/backtest_bot_fitting.d.ts.map +1 -0
- package/dist/analysis/bot_fitting/backtest_bot_fitting.js +347 -0
- package/dist/analysis/bot_fitting/backtest_bot_fitting.js.map +1 -0
- package/dist/analysis/bot_fitting/shared_utils.d.ts +15 -0
- package/dist/analysis/bot_fitting/shared_utils.d.ts.map +1 -0
- package/dist/analysis/bot_fitting/shared_utils.js +48 -0
- package/dist/analysis/bot_fitting/shared_utils.js.map +1 -0
- package/dist/analysis/bot_key_utils.d.ts +16 -0
- package/dist/analysis/bot_key_utils.d.ts.map +1 -0
- package/dist/analysis/bot_key_utils.js +61 -0
- package/dist/analysis/bot_key_utils.js.map +1 -0
- package/dist/analysis/bot_usage/discover_bot_accounts.d.ts +3 -0
- package/dist/analysis/bot_usage/discover_bot_accounts.d.ts.map +1 -0
- package/dist/analysis/bot_usage/discover_bot_accounts.js +498 -0
- package/dist/analysis/bot_usage/discover_bot_accounts.js.map +1 -0
- package/dist/analysis/bot_usage/kibana_bot_queries.d.ts +546 -0
- package/dist/analysis/bot_usage/kibana_bot_queries.d.ts.map +1 -0
- package/dist/analysis/bot_usage/kibana_bot_queries.js +427 -0
- package/dist/analysis/bot_usage/kibana_bot_queries.js.map +1 -0
- package/dist/analysis/chart_utils.d.ts +13 -0
- package/dist/analysis/chart_utils.d.ts.map +1 -0
- package/dist/analysis/chart_utils.js +142 -0
- package/dist/analysis/chart_utils.js.map +1 -0
- package/dist/analysis/derivative_chart_generator.d.ts +18 -0
- package/dist/analysis/derivative_chart_generator.d.ts.map +1 -0
- package/dist/analysis/derivative_chart_generator.js +896 -0
- package/dist/analysis/derivative_chart_generator.js.map +1 -0
- package/dist/analysis/math_utils.d.ts +35 -0
- package/dist/analysis/math_utils.d.ts.map +1 -0
- package/dist/analysis/math_utils.js +121 -0
- package/dist/analysis/math_utils.js.map +1 -0
- package/dist/analysis/price_sources.d.ts +34 -0
- package/dist/analysis/price_sources.d.ts.map +1 -0
- package/dist/analysis/price_sources.js +103 -0
- package/dist/analysis/price_sources.js.map +1 -0
- package/dist/analysis/trade_profitability.d.ts +115 -0
- package/dist/analysis/trade_profitability.d.ts.map +1 -0
- package/dist/analysis/trade_profitability.js +1247 -0
- package/dist/analysis/trade_profitability.js.map +1 -0
- package/dist/analysis/tradingview/analyze_tradingview.d.ts +38 -0
- package/dist/analysis/tradingview/analyze_tradingview.d.ts.map +1 -0
- package/dist/analysis/tradingview/analyze_tradingview.js +212 -0
- package/dist/analysis/tradingview/analyze_tradingview.js.map +1 -0
- package/dist/analysis/tradingview/tradingview_uplot_chart_generator.d.ts +9 -0
- package/dist/analysis/tradingview/tradingview_uplot_chart_generator.d.ts.map +1 -0
- package/dist/analysis/tradingview/tradingview_uplot_chart_generator.js +1717 -0
- package/dist/analysis/tradingview/tradingview_uplot_chart_generator.js.map +1 -0
- package/dist/analysis/trend_detection/derivative_analyzer.d.ts +250 -0
- package/dist/analysis/trend_detection/derivative_analyzer.d.ts.map +1 -0
- package/dist/analysis/trend_detection/derivative_analyzer.js +903 -0
- package/dist/analysis/trend_detection/derivative_analyzer.js.map +1 -0
- package/dist/analysis/trend_detection/dynamic_weight_chart_generator.d.ts +6 -0
- package/dist/analysis/trend_detection/dynamic_weight_chart_generator.d.ts.map +1 -0
- package/dist/analysis/trend_detection/dynamic_weight_chart_generator.js +1449 -0
- package/dist/analysis/trend_detection/dynamic_weight_chart_generator.js.map +1 -0
- package/dist/analysis/trend_detection/hurst_analyzer.d.ts +42 -0
- package/dist/analysis/trend_detection/hurst_analyzer.d.ts.map +1 -0
- package/dist/analysis/trend_detection/hurst_analyzer.js +159 -0
- package/dist/analysis/trend_detection/hurst_analyzer.js.map +1 -0
- package/dist/analysis/trend_detection/kalman_chart_generator.d.ts +6 -0
- package/dist/analysis/trend_detection/kalman_chart_generator.d.ts.map +1 -0
- package/dist/analysis/trend_detection/kalman_chart_generator.js +408 -0
- package/dist/analysis/trend_detection/kalman_chart_generator.js.map +1 -0
- package/dist/analysis/trend_detection/kalman_trend_analyzer.d.ts +103 -0
- package/dist/analysis/trend_detection/kalman_trend_analyzer.d.ts.map +1 -0
- package/dist/analysis/trend_detection/kalman_trend_analyzer.js +229 -0
- package/dist/analysis/trend_detection/kalman_trend_analyzer.js.map +1 -0
- package/dist/analysis/trend_detection/kalman_velocity_smoothing.d.ts +34 -0
- package/dist/analysis/trend_detection/kalman_velocity_smoothing.d.ts.map +1 -0
- package/dist/analysis/trend_detection/kalman_velocity_smoothing.js +89 -0
- package/dist/analysis/trend_detection/kalman_velocity_smoothing.js.map +1 -0
- package/dist/analysis/trend_detection/permutation_entropy_analyzer.d.ts +39 -0
- package/dist/analysis/trend_detection/permutation_entropy_analyzer.d.ts.map +1 -0
- package/dist/analysis/trend_detection/permutation_entropy_analyzer.js +132 -0
- package/dist/analysis/trend_detection/permutation_entropy_analyzer.js.map +1 -0
- package/dist/analysis/trend_detection/regime_chart_generator.d.ts +6 -0
- package/dist/analysis/trend_detection/regime_chart_generator.d.ts.map +1 -0
- package/dist/analysis/trend_detection/regime_chart_generator.js +345 -0
- package/dist/analysis/trend_detection/regime_chart_generator.js.map +1 -0
- package/dist/analysis/trend_detection/tests/test_kalman_trend.d.ts +2 -0
- package/dist/analysis/trend_detection/tests/test_kalman_trend.d.ts.map +1 -0
- package/dist/analysis/trend_detection/tests/test_kalman_trend.js +130 -0
- package/dist/analysis/trend_detection/tests/test_kalman_trend.js.map +1 -0
- package/dist/analysis/trend_detection/tests/test_kalman_velocity_smoothing.d.ts +2 -0
- package/dist/analysis/trend_detection/tests/test_kalman_velocity_smoothing.d.ts.map +1 -0
- package/dist/analysis/trend_detection/tests/test_kalman_velocity_smoothing.js +38 -0
- package/dist/analysis/trend_detection/tests/test_kalman_velocity_smoothing.js.map +1 -0
- package/dist/analysis/trend_detection/volatility_chart_generator.d.ts +6 -0
- package/dist/analysis/trend_detection/volatility_chart_generator.d.ts.map +1 -0
- package/dist/analysis/trend_detection/volatility_chart_generator.js +732 -0
- package/dist/analysis/trend_detection/volatility_chart_generator.js.map +1 -0
- package/dist/bot.d.ts +49 -0
- package/dist/bot.d.ts.map +1 -0
- package/dist/bot.js +221 -0
- package/dist/bot.js.map +1 -0
- package/dist/credential-daemon.d.ts +64 -0
- package/dist/credential-daemon.d.ts.map +1 -0
- package/dist/credential-daemon.js +987 -0
- package/dist/credential-daemon.js.map +1 -0
- package/dist/dexbot.d.ts +87 -0
- package/dist/dexbot.d.ts.map +1 -0
- package/dist/dexbot.js +1222 -0
- package/dist/dexbot.js.map +1 -0
- package/dist/market_adapter/ama_signal_runner.d.ts +3 -0
- package/dist/market_adapter/ama_signal_runner.d.ts.map +1 -0
- package/dist/market_adapter/ama_signal_runner.js +175 -0
- package/dist/market_adapter/ama_signal_runner.js.map +1 -0
- package/dist/market_adapter/candle_utils.d.ts +57 -0
- package/dist/market_adapter/candle_utils.d.ts.map +1 -0
- package/dist/market_adapter/candle_utils.js +252 -0
- package/dist/market_adapter/candle_utils.js.map +1 -0
- package/dist/market_adapter/core/asymmetric_bounds.d.ts +20 -0
- package/dist/market_adapter/core/asymmetric_bounds.d.ts.map +1 -0
- package/dist/market_adapter/core/asymmetric_bounds.js +88 -0
- package/dist/market_adapter/core/asymmetric_bounds.js.map +1 -0
- package/dist/market_adapter/core/config_normalizers.d.ts +10 -0
- package/dist/market_adapter/core/config_normalizers.d.ts.map +1 -0
- package/dist/market_adapter/core/config_normalizers.js +24 -0
- package/dist/market_adapter/core/config_normalizers.js.map +1 -0
- package/dist/market_adapter/core/kibana_candles.d.ts +74 -0
- package/dist/market_adapter/core/kibana_candles.d.ts.map +1 -0
- package/dist/market_adapter/core/kibana_candles.js +249 -0
- package/dist/market_adapter/core/kibana_candles.js.map +1 -0
- package/dist/market_adapter/core/kibana_client.d.ts +27 -0
- package/dist/market_adapter/core/kibana_client.d.ts.map +1 -0
- package/dist/market_adapter/core/kibana_client.js +120 -0
- package/dist/market_adapter/core/kibana_client.js.map +1 -0
- package/dist/market_adapter/core/kibana_market_candles.d.ts +143 -0
- package/dist/market_adapter/core/kibana_market_candles.d.ts.map +1 -0
- package/dist/market_adapter/core/kibana_market_candles.js +170 -0
- package/dist/market_adapter/core/kibana_market_candles.js.map +1 -0
- package/dist/market_adapter/core/market_adapter_service.d.ts +210 -0
- package/dist/market_adapter/core/market_adapter_service.d.ts.map +1 -0
- package/dist/market_adapter/core/market_adapter_service.js +2328 -0
- package/dist/market_adapter/core/market_adapter_service.js.map +1 -0
- package/dist/market_adapter/core/strategies/ama.d.ts +2 -0
- package/dist/market_adapter/core/strategies/ama.d.ts.map +1 -0
- package/dist/market_adapter/core/strategies/ama.js +138 -0
- package/dist/market_adapter/core/strategies/ama.js.map +1 -0
- package/dist/market_adapter/core/strategies/ama_slope_model.d.ts +50 -0
- package/dist/market_adapter/core/strategies/ama_slope_model.d.ts.map +1 -0
- package/dist/market_adapter/core/strategies/ama_slope_model.js +143 -0
- package/dist/market_adapter/core/strategies/ama_slope_model.js.map +1 -0
- package/dist/market_adapter/core/strategies/atr/calculator.d.ts +12 -0
- package/dist/market_adapter/core/strategies/atr/calculator.d.ts.map +1 -0
- package/dist/market_adapter/core/strategies/atr/calculator.js +47 -0
- package/dist/market_adapter/core/strategies/atr/calculator.js.map +1 -0
- package/dist/market_adapter/core/strategies/collateral_manager.d.ts +32 -0
- package/dist/market_adapter/core/strategies/collateral_manager.d.ts.map +1 -0
- package/dist/market_adapter/core/strategies/collateral_manager.js +68 -0
- package/dist/market_adapter/core/strategies/collateral_manager.js.map +1 -0
- package/dist/market_adapter/core/strategies/regime_gate.d.ts +66 -0
- package/dist/market_adapter/core/strategies/regime_gate.d.ts.map +1 -0
- package/dist/market_adapter/core/strategies/regime_gate.js +189 -0
- package/dist/market_adapter/core/strategies/regime_gate.js.map +1 -0
- package/dist/market_adapter/index.d.ts +10 -0
- package/dist/market_adapter/index.d.ts.map +1 -0
- package/dist/market_adapter/index.js +71 -0
- package/dist/market_adapter/index.js.map +1 -0
- package/dist/market_adapter/inputs/fetch_cex_synthetic_data.d.ts +3 -0
- package/dist/market_adapter/inputs/fetch_cex_synthetic_data.d.ts.map +1 -0
- package/dist/market_adapter/inputs/fetch_cex_synthetic_data.js +1165 -0
- package/dist/market_adapter/inputs/fetch_cex_synthetic_data.js.map +1 -0
- package/dist/market_adapter/inputs/fetch_lp_data.d.ts +54 -0
- package/dist/market_adapter/inputs/fetch_lp_data.d.ts.map +1 -0
- package/dist/market_adapter/inputs/fetch_lp_data.js +743 -0
- package/dist/market_adapter/inputs/fetch_lp_data.js.map +1 -0
- package/dist/market_adapter/inputs/kibana_source.d.ts +68 -0
- package/dist/market_adapter/inputs/kibana_source.d.ts.map +1 -0
- package/dist/market_adapter/inputs/kibana_source.js +143 -0
- package/dist/market_adapter/inputs/kibana_source.js.map +1 -0
- package/dist/market_adapter/interval_utils.d.ts +6 -0
- package/dist/market_adapter/interval_utils.d.ts.map +1 -0
- package/dist/market_adapter/interval_utils.js +14 -0
- package/dist/market_adapter/interval_utils.js.map +1 -0
- package/dist/market_adapter/log_format.d.ts +16 -0
- package/dist/market_adapter/log_format.d.ts.map +1 -0
- package/dist/market_adapter/log_format.js +72 -0
- package/dist/market_adapter/log_format.js.map +1 -0
- package/dist/market_adapter/lp_chart_core.d.ts +6 -0
- package/dist/market_adapter/lp_chart_core.d.ts.map +1 -0
- package/dist/market_adapter/lp_chart_core.js +874 -0
- package/dist/market_adapter/lp_chart_core.js.map +1 -0
- package/dist/market_adapter/lp_chart_runner.d.ts +135 -0
- package/dist/market_adapter/lp_chart_runner.d.ts.map +1 -0
- package/dist/market_adapter/lp_chart_runner.js +337 -0
- package/dist/market_adapter/lp_chart_runner.js.map +1 -0
- package/dist/market_adapter/lp_chart_strategy_loader.d.ts +23 -0
- package/dist/market_adapter/lp_chart_strategy_loader.d.ts.map +1 -0
- package/dist/market_adapter/lp_chart_strategy_loader.js +169 -0
- package/dist/market_adapter/lp_chart_strategy_loader.js.map +1 -0
- package/dist/market_adapter/market_adapter.d.ts +133 -0
- package/dist/market_adapter/market_adapter.d.ts.map +1 -0
- package/dist/market_adapter/market_adapter.js +1331 -0
- package/dist/market_adapter/market_adapter.js.map +1 -0
- package/dist/market_adapter/merge_lp_data.d.ts +3 -0
- package/dist/market_adapter/merge_lp_data.d.ts.map +1 -0
- package/dist/market_adapter/merge_lp_data.js +125 -0
- package/dist/market_adapter/merge_lp_data.js.map +1 -0
- package/dist/market_adapter/test_helpers.d.ts +14 -0
- package/dist/market_adapter/test_helpers.d.ts.map +1 -0
- package/dist/market_adapter/test_helpers.js +22 -0
- package/dist/market_adapter/test_helpers.js.map +1 -0
- package/dist/market_adapter/utils/adapter_client.d.ts +20 -0
- package/dist/market_adapter/utils/adapter_client.d.ts.map +1 -0
- package/dist/market_adapter/utils/adapter_client.js +88 -0
- package/dist/market_adapter/utils/adapter_client.js.map +1 -0
- package/dist/market_adapter/utils/atomic_write.d.ts +9 -0
- package/dist/market_adapter/utils/atomic_write.d.ts.map +1 -0
- package/dist/market_adapter/utils/atomic_write.js +13 -0
- package/dist/market_adapter/utils/atomic_write.js.map +1 -0
- package/dist/market_adapter/utils/chain.d.ts +50 -0
- package/dist/market_adapter/utils/chain.d.ts.map +1 -0
- package/dist/market_adapter/utils/chain.js +196 -0
- package/dist/market_adapter/utils/chain.js.map +1 -0
- package/dist/market_adapter/utils/data_discovery.d.ts +6 -0
- package/dist/market_adapter/utils/data_discovery.d.ts.map +1 -0
- package/dist/market_adapter/utils/data_discovery.js +35 -0
- package/dist/market_adapter/utils/data_discovery.js.map +1 -0
- package/dist/market_adapter/utils/dynamic_grid_snapshot.d.ts +15 -0
- package/dist/market_adapter/utils/dynamic_grid_snapshot.d.ts.map +1 -0
- package/dist/market_adapter/utils/dynamic_grid_snapshot.js +60 -0
- package/dist/market_adapter/utils/dynamic_grid_snapshot.js.map +1 -0
- package/dist/market_adapter/utils/file_lock.d.ts +19 -0
- package/dist/market_adapter/utils/file_lock.d.ts.map +1 -0
- package/dist/market_adapter/utils/file_lock.js +191 -0
- package/dist/market_adapter/utils/file_lock.js.map +1 -0
- package/dist/market_adapter/utils/native_history.d.ts +19 -0
- package/dist/market_adapter/utils/native_history.d.ts.map +1 -0
- package/dist/market_adapter/utils/native_history.js +172 -0
- package/dist/market_adapter/utils/native_history.js.map +1 -0
- package/dist/market_adapter/utils/paths.d.ts +5 -0
- package/dist/market_adapter/utils/paths.d.ts.map +1 -0
- package/dist/market_adapter/utils/paths.js +7 -0
- package/dist/market_adapter/utils/paths.js.map +1 -0
- package/dist/modules/account_bots.d.ts +112 -0
- package/dist/modules/account_bots.d.ts.map +1 -0
- package/dist/modules/account_bots.js +1259 -0
- package/dist/modules/account_bots.js.map +1 -0
- package/dist/modules/account_orders.d.ts +273 -0
- package/dist/modules/account_orders.d.ts.map +1 -0
- package/dist/modules/account_orders.js +662 -0
- package/dist/modules/account_orders.js.map +1 -0
- package/dist/modules/authority_resolver.d.ts +2 -0
- package/dist/modules/authority_resolver.d.ts.map +1 -0
- package/dist/modules/authority_resolver.js +231 -0
- package/dist/modules/authority_resolver.js.map +1 -0
- package/dist/modules/bitshares-native/chain_client.d.ts +38 -0
- package/dist/modules/bitshares-native/chain_client.d.ts.map +1 -0
- package/dist/modules/bitshares-native/chain_client.js +322 -0
- package/dist/modules/bitshares-native/chain_client.js.map +1 -0
- package/dist/modules/bitshares-native/crypto/ecc.browser.d.ts +59 -0
- package/dist/modules/bitshares-native/crypto/ecc.browser.d.ts.map +1 -0
- package/dist/modules/bitshares-native/crypto/ecc.browser.js +456 -0
- package/dist/modules/bitshares-native/crypto/ecc.browser.js.map +1 -0
- package/dist/modules/bitshares-native/crypto/ecc.d.ts +66 -0
- package/dist/modules/bitshares-native/crypto/ecc.d.ts.map +1 -0
- package/dist/modules/bitshares-native/crypto/ecc.js +557 -0
- package/dist/modules/bitshares-native/crypto/ecc.js.map +1 -0
- package/dist/modules/bitshares-native/crypto/ecc_selector.d.ts +2 -0
- package/dist/modules/bitshares-native/crypto/ecc_selector.d.ts.map +1 -0
- package/dist/modules/bitshares-native/crypto/ecc_selector.js +20 -0
- package/dist/modules/bitshares-native/crypto/ecc_selector.js.map +1 -0
- package/dist/modules/bitshares-native/index.d.ts +3 -0
- package/dist/modules/bitshares-native/index.d.ts.map +1 -0
- package/dist/modules/bitshares-native/index.js +32 -0
- package/dist/modules/bitshares-native/index.js.map +1 -0
- package/dist/modules/bitshares-native/resolvers.d.ts +40 -0
- package/dist/modules/bitshares-native/resolvers.d.ts.map +1 -0
- package/dist/modules/bitshares-native/resolvers.js +161 -0
- package/dist/modules/bitshares-native/resolvers.js.map +1 -0
- package/dist/modules/bitshares-native/serial/chain_constants.d.ts +56 -0
- package/dist/modules/bitshares-native/serial/chain_constants.d.ts.map +1 -0
- package/dist/modules/bitshares-native/serial/chain_constants.js +92 -0
- package/dist/modules/bitshares-native/serial/chain_constants.js.map +1 -0
- package/dist/modules/bitshares-native/serial/index.d.ts +10 -0
- package/dist/modules/bitshares-native/serial/index.d.ts.map +1 -0
- package/dist/modules/bitshares-native/serial/index.js +14 -0
- package/dist/modules/bitshares-native/serial/index.js.map +1 -0
- package/dist/modules/bitshares-native/serial/operations.d.ts +102 -0
- package/dist/modules/bitshares-native/serial/operations.d.ts.map +1 -0
- package/dist/modules/bitshares-native/serial/operations.js +615 -0
- package/dist/modules/bitshares-native/serial/operations.js.map +1 -0
- package/dist/modules/bitshares-native/serial/serializer.d.ts +64 -0
- package/dist/modules/bitshares-native/serial/serializer.d.ts.map +1 -0
- package/dist/modules/bitshares-native/serial/serializer.js +252 -0
- package/dist/modules/bitshares-native/serial/serializer.js.map +1 -0
- package/dist/modules/bitshares-native/serial/types.d.ts +120 -0
- package/dist/modules/bitshares-native/serial/types.d.ts.map +1 -0
- package/dist/modules/bitshares-native/serial/types.js +837 -0
- package/dist/modules/bitshares-native/serial/types.js.map +1 -0
- package/dist/modules/bitshares-native/signing_client.d.ts +6 -0
- package/dist/modules/bitshares-native/signing_client.d.ts.map +1 -0
- package/dist/modules/bitshares-native/signing_client.js +141 -0
- package/dist/modules/bitshares-native/signing_client.js.map +1 -0
- package/dist/modules/bitshares-native/subscriptions.d.ts +6 -0
- package/dist/modules/bitshares-native/subscriptions.d.ts.map +1 -0
- package/dist/modules/bitshares-native/subscriptions.js +865 -0
- package/dist/modules/bitshares-native/subscriptions.js.map +1 -0
- package/dist/modules/bitshares-native/transport.d.ts +51 -0
- package/dist/modules/bitshares-native/transport.d.ts.map +1 -0
- package/dist/modules/bitshares-native/transport.js +447 -0
- package/dist/modules/bitshares-native/transport.js.map +1 -0
- package/dist/modules/bitshares-native/tx/builder.d.ts +30 -0
- package/dist/modules/bitshares-native/tx/builder.d.ts.map +1 -0
- package/dist/modules/bitshares-native/tx/builder.js +262 -0
- package/dist/modules/bitshares-native/tx/builder.js.map +1 -0
- package/dist/modules/bitshares_client.d.ts +129 -0
- package/dist/modules/bitshares_client.d.ts.map +1 -0
- package/dist/modules/bitshares_client.js +627 -0
- package/dist/modules/bitshares_client.js.map +1 -0
- package/dist/modules/bot_settings.d.ts +33 -0
- package/dist/modules/bot_settings.d.ts.map +1 -0
- package/dist/modules/bot_settings.js +328 -0
- package/dist/modules/bot_settings.js.map +1 -0
- package/dist/modules/bots_file_lock.d.ts +88 -0
- package/dist/modules/bots_file_lock.d.ts.map +1 -0
- package/dist/modules/bots_file_lock.js +161 -0
- package/dist/modules/bots_file_lock.js.map +1 -0
- package/dist/modules/chain_keys.d.ts +302 -0
- package/dist/modules/chain_keys.d.ts.map +1 -0
- package/dist/modules/chain_keys.js +1095 -0
- package/dist/modules/chain_keys.js.map +1 -0
- package/dist/modules/chain_orders.d.ts +423 -0
- package/dist/modules/chain_orders.d.ts.map +1 -0
- package/dist/modules/chain_orders.js +1201 -0
- package/dist/modules/chain_orders.js.map +1 -0
- package/dist/modules/cli_whitelist_args.d.ts +6 -0
- package/dist/modules/cli_whitelist_args.d.ts.map +1 -0
- package/dist/modules/cli_whitelist_args.js +13 -0
- package/dist/modules/cli_whitelist_args.js.map +1 -0
- package/dist/modules/config.d.ts +57 -0
- package/dist/modules/config.d.ts.map +1 -0
- package/dist/modules/config.js +107 -0
- package/dist/modules/config.js.map +1 -0
- package/dist/modules/constants.d.ts +635 -0
- package/dist/modules/constants.d.ts.map +1 -0
- package/dist/modules/constants.js +1464 -0
- package/dist/modules/constants.js.map +1 -0
- package/dist/modules/cr_planner.d.ts +51 -0
- package/dist/modules/cr_planner.d.ts.map +1 -0
- package/dist/modules/cr_planner.js +299 -0
- package/dist/modules/cr_planner.js.map +1 -0
- package/dist/modules/credential_policy.d.ts +188 -0
- package/dist/modules/credential_policy.d.ts.map +1 -0
- package/dist/modules/credential_policy.js +1452 -0
- package/dist/modules/credential_policy.js.map +1 -0
- package/dist/modules/credential_runtime.d.ts +42 -0
- package/dist/modules/credential_runtime.d.ts.map +1 -0
- package/dist/modules/credential_runtime.js +148 -0
- package/dist/modules/credential_runtime.js.map +1 -0
- package/dist/modules/credential_session_cache.d.ts +36 -0
- package/dist/modules/credential_session_cache.d.ts.map +1 -0
- package/dist/modules/credential_session_cache.js +106 -0
- package/dist/modules/credential_session_cache.js.map +1 -0
- package/dist/modules/credit_runtime.d.ts +412 -0
- package/dist/modules/credit_runtime.d.ts.map +1 -0
- package/dist/modules/credit_runtime.js +2866 -0
- package/dist/modules/credit_runtime.js.map +1 -0
- package/dist/modules/crypto/browser_provider.d.ts +15 -0
- package/dist/modules/crypto/browser_provider.d.ts.map +1 -0
- package/dist/modules/crypto/browser_provider.js +113 -0
- package/dist/modules/crypto/browser_provider.js.map +1 -0
- package/dist/modules/crypto/index.d.ts +9 -0
- package/dist/modules/crypto/index.d.ts.map +1 -0
- package/dist/modules/crypto/index.js +44 -0
- package/dist/modules/crypto/index.js.map +1 -0
- package/dist/modules/crypto/node_provider.d.ts +15 -0
- package/dist/modules/crypto/node_provider.d.ts.map +1 -0
- package/dist/modules/crypto/node_provider.js +74 -0
- package/dist/modules/crypto/node_provider.js.map +1 -0
- package/dist/modules/crypto/provider.d.ts +34 -0
- package/dist/modules/crypto/provider.d.ts.map +1 -0
- package/dist/modules/crypto/provider.js +3 -0
- package/dist/modules/crypto/provider.js.map +1 -0
- package/dist/modules/crypto/pure_ripemd160.d.ts +8 -0
- package/dist/modules/crypto/pure_ripemd160.d.ts.map +1 -0
- package/dist/modules/crypto/pure_ripemd160.js +142 -0
- package/dist/modules/crypto/pure_ripemd160.js.map +1 -0
- package/dist/modules/crypto/pure_scrypt.d.ts +23 -0
- package/dist/modules/crypto/pure_scrypt.d.ts.map +1 -0
- package/dist/modules/crypto/pure_scrypt.js +161 -0
- package/dist/modules/crypto/pure_scrypt.js.map +1 -0
- package/dist/modules/crypto/pure_secp256k1.d.ts +29 -0
- package/dist/modules/crypto/pure_secp256k1.d.ts.map +1 -0
- package/dist/modules/crypto/pure_secp256k1.js +195 -0
- package/dist/modules/crypto/pure_secp256k1.js.map +1 -0
- package/dist/modules/crypto/sync.d.ts +13 -0
- package/dist/modules/crypto/sync.d.ts.map +1 -0
- package/dist/modules/crypto/sync.js +37 -0
- package/dist/modules/crypto/sync.js.map +1 -0
- package/dist/modules/dexbot_class.d.ts +1074 -0
- package/dist/modules/dexbot_class.d.ts.map +1 -0
- package/dist/modules/dexbot_class.js +4613 -0
- package/dist/modules/dexbot_class.js.map +1 -0
- package/dist/modules/dexbot_credential_client.d.ts +71 -0
- package/dist/modules/dexbot_credential_client.d.ts.map +1 -0
- package/dist/modules/dexbot_credential_client.js +224 -0
- package/dist/modules/dexbot_credential_client.js.map +1 -0
- package/dist/modules/dexbot_fill_runtime.d.ts +173 -0
- package/dist/modules/dexbot_fill_runtime.d.ts.map +1 -0
- package/dist/modules/dexbot_fill_runtime.js +217 -0
- package/dist/modules/dexbot_fill_runtime.js.map +1 -0
- package/dist/modules/dexbot_maintenance_runtime.d.ts +279 -0
- package/dist/modules/dexbot_maintenance_runtime.d.ts.map +1 -0
- package/dist/modules/dexbot_maintenance_runtime.js +1613 -0
- package/dist/modules/dexbot_maintenance_runtime.js.map +1 -0
- package/dist/modules/env.d.ts +12 -0
- package/dist/modules/env.d.ts.map +1 -0
- package/dist/modules/env.js +57 -0
- package/dist/modules/env.js.map +1 -0
- package/dist/modules/fund_registry.d.ts +96 -0
- package/dist/modules/fund_registry.d.ts.map +1 -0
- package/dist/modules/fund_registry.js +261 -0
- package/dist/modules/fund_registry.js.map +1 -0
- package/dist/modules/general_settings.d.ts +36 -0
- package/dist/modules/general_settings.d.ts.map +1 -0
- package/dist/modules/general_settings.js +63 -0
- package/dist/modules/general_settings.js.map +1 -0
- package/dist/modules/graceful_shutdown.d.ts +86 -0
- package/dist/modules/graceful_shutdown.d.ts.map +1 -0
- package/dist/modules/graceful_shutdown.js +164 -0
- package/dist/modules/graceful_shutdown.js.map +1 -0
- package/dist/modules/key_store.d.ts +60 -0
- package/dist/modules/key_store.d.ts.map +1 -0
- package/dist/modules/key_store.js +215 -0
- package/dist/modules/key_store.js.map +1 -0
- package/dist/modules/launcher/bot_supervisor.d.ts +84 -0
- package/dist/modules/launcher/bot_supervisor.d.ts.map +1 -0
- package/dist/modules/launcher/bot_supervisor.js +1067 -0
- package/dist/modules/launcher/bot_supervisor.js.map +1 -0
- package/dist/modules/launcher/child_env.d.ts +9 -0
- package/dist/modules/launcher/child_env.d.ts.map +1 -0
- package/dist/modules/launcher/child_env.js +78 -0
- package/dist/modules/launcher/child_env.js.map +1 -0
- package/dist/modules/launcher/credential_bootstrap.d.ts +22 -0
- package/dist/modules/launcher/credential_bootstrap.d.ts.map +1 -0
- package/dist/modules/launcher/credential_bootstrap.js +303 -0
- package/dist/modules/launcher/credential_bootstrap.js.map +1 -0
- package/dist/modules/launcher/credential_daemon.d.ts +32 -0
- package/dist/modules/launcher/credential_daemon.d.ts.map +1 -0
- package/dist/modules/launcher/credential_daemon.js +173 -0
- package/dist/modules/launcher/credential_daemon.js.map +1 -0
- package/dist/modules/launcher/credential_secret.d.ts +6 -0
- package/dist/modules/launcher/credential_secret.d.ts.map +1 -0
- package/dist/modules/launcher/credential_secret.js +15 -0
- package/dist/modules/launcher/credential_secret.js.map +1 -0
- package/dist/modules/launcher/foreign_cred_daemon.d.ts +2 -0
- package/dist/modules/launcher/foreign_cred_daemon.d.ts.map +1 -0
- package/dist/modules/launcher/foreign_cred_daemon.js +166 -0
- package/dist/modules/launcher/foreign_cred_daemon.js.map +1 -0
- package/dist/modules/launcher/headless_password.d.ts +8 -0
- package/dist/modules/launcher/headless_password.d.ts.map +1 -0
- package/dist/modules/launcher/headless_password.js +33 -0
- package/dist/modules/launcher/headless_password.js.map +1 -0
- package/dist/modules/launcher/launch_modes.d.ts +36 -0
- package/dist/modules/launcher/launch_modes.d.ts.map +1 -0
- package/dist/modules/launcher/launch_modes.js +129 -0
- package/dist/modules/launcher/launch_modes.js.map +1 -0
- package/dist/modules/launcher/market_adapter_runtime.d.ts +43 -0
- package/dist/modules/launcher/market_adapter_runtime.d.ts.map +1 -0
- package/dist/modules/launcher/market_adapter_runtime.js +217 -0
- package/dist/modules/launcher/market_adapter_runtime.js.map +1 -0
- package/dist/modules/launcher/market_adapter_watchdog.d.ts +26 -0
- package/dist/modules/launcher/market_adapter_watchdog.d.ts.map +1 -0
- package/dist/modules/launcher/market_adapter_watchdog.js +214 -0
- package/dist/modules/launcher/market_adapter_watchdog.js.map +1 -0
- package/dist/modules/launcher/monolithic_runtime.d.ts +89 -0
- package/dist/modules/launcher/monolithic_runtime.d.ts.map +1 -0
- package/dist/modules/launcher/monolithic_runtime.js +425 -0
- package/dist/modules/launcher/monolithic_runtime.js.map +1 -0
- package/dist/modules/launcher/runtime_entry.d.ts +26 -0
- package/dist/modules/launcher/runtime_entry.d.ts.map +1 -0
- package/dist/modules/launcher/runtime_entry.js +49 -0
- package/dist/modules/launcher/runtime_entry.js.map +1 -0
- package/dist/modules/launcher/status_reporting.d.ts +48 -0
- package/dist/modules/launcher/status_reporting.d.ts.map +1 -0
- package/dist/modules/launcher/status_reporting.js +113 -0
- package/dist/modules/launcher/status_reporting.js.map +1 -0
- package/dist/modules/launcher/supervisor_control.d.ts +6 -0
- package/dist/modules/launcher/supervisor_control.d.ts.map +1 -0
- package/dist/modules/launcher/supervisor_control.js +59 -0
- package/dist/modules/launcher/supervisor_control.js.map +1 -0
- package/dist/modules/logger.d.ts +2 -0
- package/dist/modules/logger.d.ts.map +1 -0
- package/dist/modules/logger.js +71 -0
- package/dist/modules/logger.js.map +1 -0
- package/dist/modules/market_adapter_whitelist.d.ts +22 -0
- package/dist/modules/market_adapter_whitelist.d.ts.map +1 -0
- package/dist/modules/market_adapter_whitelist.js +82 -0
- package/dist/modules/market_adapter_whitelist.js.map +1 -0
- package/dist/modules/node_health_cache.d.ts +55 -0
- package/dist/modules/node_health_cache.d.ts.map +1 -0
- package/dist/modules/node_health_cache.js +134 -0
- package/dist/modules/node_health_cache.js.map +1 -0
- package/dist/modules/node_manager.d.ts +215 -0
- package/dist/modules/node_manager.d.ts.map +1 -0
- package/dist/modules/node_manager.js +628 -0
- package/dist/modules/node_manager.js.map +1 -0
- package/dist/modules/order/accounting.d.ts +349 -0
- package/dist/modules/order/accounting.d.ts.map +1 -0
- package/dist/modules/order/accounting.js +1191 -0
- package/dist/modules/order/accounting.js.map +1 -0
- package/dist/modules/order/async_lock.d.ts +126 -0
- package/dist/modules/order/async_lock.d.ts.map +1 -0
- package/dist/modules/order/async_lock.js +195 -0
- package/dist/modules/order/async_lock.js.map +1 -0
- package/dist/modules/order/export.d.ts +129 -0
- package/dist/modules/order/export.d.ts.map +1 -0
- package/dist/modules/order/export.js +316 -0
- package/dist/modules/order/export.js.map +1 -0
- package/dist/modules/order/format.d.ts +158 -0
- package/dist/modules/order/format.d.ts.map +1 -0
- package/dist/modules/order/format.js +232 -0
- package/dist/modules/order/format.js.map +1 -0
- package/dist/modules/order/grid.d.ts +549 -0
- package/dist/modules/order/grid.d.ts.map +1 -0
- package/dist/modules/order/grid.js +1746 -0
- package/dist/modules/order/grid.js.map +1 -0
- package/dist/modules/order/grid_reconcile.d.ts +154 -0
- package/dist/modules/order/grid_reconcile.d.ts.map +1 -0
- package/dist/modules/order/grid_reconcile.js +1192 -0
- package/dist/modules/order/grid_reconcile.js.map +1 -0
- package/dist/modules/order/index.d.ts +55 -0
- package/dist/modules/order/index.d.ts.map +1 -0
- package/dist/modules/order/index.js +79 -0
- package/dist/modules/order/index.js.map +1 -0
- package/dist/modules/order/logger.d.ts +136 -0
- package/dist/modules/order/logger.d.ts.map +1 -0
- package/dist/modules/order/logger.js +614 -0
- package/dist/modules/order/logger.js.map +1 -0
- package/dist/modules/order/logger_state.d.ts +133 -0
- package/dist/modules/order/logger_state.d.ts.map +1 -0
- package/dist/modules/order/logger_state.js +170 -0
- package/dist/modules/order/logger_state.js.map +1 -0
- package/dist/modules/order/manager.d.ts +413 -0
- package/dist/modules/order/manager.d.ts.map +1 -0
- package/dist/modules/order/manager.js +1605 -0
- package/dist/modules/order/manager.js.map +1 -0
- package/dist/modules/order/processed_fill_store.d.ts +135 -0
- package/dist/modules/order/processed_fill_store.d.ts.map +1 -0
- package/dist/modules/order/processed_fill_store.js +288 -0
- package/dist/modules/order/processed_fill_store.js.map +1 -0
- package/dist/modules/order/runner.d.ts +70 -0
- package/dist/modules/order/runner.d.ts.map +1 -0
- package/dist/modules/order/runner.js +140 -0
- package/dist/modules/order/runner.js.map +1 -0
- package/dist/modules/order/strategy.d.ts +196 -0
- package/dist/modules/order/strategy.d.ts.map +1 -0
- package/dist/modules/order/strategy.js +398 -0
- package/dist/modules/order/strategy.js.map +1 -0
- package/dist/modules/order/sync_engine.d.ts +386 -0
- package/dist/modules/order/sync_engine.d.ts.map +1 -0
- package/dist/modules/order/sync_engine.js +1459 -0
- package/dist/modules/order/sync_engine.js.map +1 -0
- package/dist/modules/order/utils/math.d.ts +677 -0
- package/dist/modules/order/utils/math.d.ts.map +1 -0
- package/dist/modules/order/utils/math.js +1172 -0
- package/dist/modules/order/utils/math.js.map +1 -0
- package/dist/modules/order/utils/order.d.ts +572 -0
- package/dist/modules/order/utils/order.d.ts.map +1 -0
- package/dist/modules/order/utils/order.js +1145 -0
- package/dist/modules/order/utils/order.js.map +1 -0
- package/dist/modules/order/utils/system.d.ts +268 -0
- package/dist/modules/order/utils/system.d.ts.map +1 -0
- package/dist/modules/order/utils/system.js +1261 -0
- package/dist/modules/order/utils/system.js.map +1 -0
- package/dist/modules/order/utils/validate.d.ts +280 -0
- package/dist/modules/order/utils/validate.d.ts.map +1 -0
- package/dist/modules/order/utils/validate.js +918 -0
- package/dist/modules/order/utils/validate.js.map +1 -0
- package/dist/modules/order/working_grid.d.ts +212 -0
- package/dist/modules/order/working_grid.d.ts.map +1 -0
- package/dist/modules/order/working_grid.js +279 -0
- package/dist/modules/order/working_grid.js.map +1 -0
- package/dist/modules/path_api.d.ts +32 -0
- package/dist/modules/path_api.d.ts.map +1 -0
- package/dist/modules/path_api.js +148 -0
- package/dist/modules/path_api.js.map +1 -0
- package/dist/modules/paths.d.ts +58 -0
- package/dist/modules/paths.d.ts.map +1 -0
- package/dist/modules/paths.js +82 -0
- package/dist/modules/paths.js.map +1 -0
- package/dist/modules/process_discovery.d.ts +58 -0
- package/dist/modules/process_discovery.d.ts.map +1 -0
- package/dist/modules/process_discovery.js +265 -0
- package/dist/modules/process_discovery.js.map +1 -0
- package/dist/modules/runtime.d.ts +34 -0
- package/dist/modules/runtime.d.ts.map +1 -0
- package/dist/modules/runtime.js +98 -0
- package/dist/modules/runtime.js.map +1 -0
- package/dist/modules/runtime_settings.d.ts +12 -0
- package/dist/modules/runtime_settings.d.ts.map +1 -0
- package/dist/modules/runtime_settings.js +122 -0
- package/dist/modules/runtime_settings.js.map +1 -0
- package/dist/modules/settings_merge.d.ts +38 -0
- package/dist/modules/settings_merge.d.ts.map +1 -0
- package/dist/modules/settings_merge.js +246 -0
- package/dist/modules/settings_merge.js.map +1 -0
- package/dist/modules/storage/browser_adapter.d.ts +56 -0
- package/dist/modules/storage/browser_adapter.d.ts.map +1 -0
- package/dist/modules/storage/browser_adapter.js +231 -0
- package/dist/modules/storage/browser_adapter.js.map +1 -0
- package/dist/modules/storage/index.d.ts +28 -0
- package/dist/modules/storage/index.d.ts.map +1 -0
- package/dist/modules/storage/index.js +52 -0
- package/dist/modules/storage/index.js.map +1 -0
- package/dist/modules/storage/node_adapter.d.ts +49 -0
- package/dist/modules/storage/node_adapter.d.ts.map +1 -0
- package/dist/modules/storage/node_adapter.js +167 -0
- package/dist/modules/storage/node_adapter.js.map +1 -0
- package/dist/modules/storage/types.d.ts +92 -0
- package/dist/modules/storage/types.d.ts.map +1 -0
- package/dist/modules/storage/types.js +3 -0
- package/dist/modules/storage/types.js.map +1 -0
- package/dist/modules/types.d.ts +1382 -0
- package/dist/modules/types.d.ts.map +1 -0
- package/dist/modules/types.js +11 -0
- package/dist/modules/types.js.map +1 -0
- package/dist/modules/utils/base58check.d.ts +12 -0
- package/dist/modules/utils/base58check.d.ts.map +1 -0
- package/dist/modules/utils/base58check.js +112 -0
- package/dist/modules/utils/base58check.js.map +1 -0
- package/dist/modules/utils/build_dir.d.ts +7 -0
- package/dist/modules/utils/build_dir.d.ts.map +1 -0
- package/dist/modules/utils/build_dir.js +8 -0
- package/dist/modules/utils/build_dir.js.map +1 -0
- package/dist/modules/utils/fs_utils.d.ts +25 -0
- package/dist/modules/utils/fs_utils.d.ts.map +1 -0
- package/dist/modules/utils/fs_utils.js +27 -0
- package/dist/modules/utils/fs_utils.js.map +1 -0
- package/dist/modules/utils/math_utils.d.ts +10 -0
- package/dist/modules/utils/math_utils.d.ts.map +1 -0
- package/dist/modules/utils/math_utils.js +17 -0
- package/dist/modules/utils/math_utils.js.map +1 -0
- package/dist/modules/validate_profiles.d.ts +37 -0
- package/dist/modules/validate_profiles.d.ts.map +1 -0
- package/dist/modules/validate_profiles.js +369 -0
- package/dist/modules/validate_profiles.js.map +1 -0
- package/dist/pm2.d.ts +167 -0
- package/dist/pm2.d.ts.map +1 -0
- package/dist/pm2.js +998 -0
- package/dist/pm2.js.map +1 -0
- package/dist/scripts/analyze-git.d.ts +11 -0
- package/dist/scripts/analyze-git.d.ts.map +1 -0
- package/dist/scripts/analyze-git.js +851 -0
- package/dist/scripts/analyze-git.js.map +1 -0
- package/dist/scripts/analyze-orders.d.ts +17 -0
- package/dist/scripts/analyze-orders.d.ts.map +1 -0
- package/dist/scripts/analyze-orders.js +1568 -0
- package/dist/scripts/analyze-orders.js.map +1 -0
- package/dist/scripts/diagnose-kibana-candles.d.ts +3 -0
- package/dist/scripts/diagnose-kibana-candles.d.ts.map +1 -0
- package/dist/scripts/diagnose-kibana-candles.js +82 -0
- package/dist/scripts/diagnose-kibana-candles.js.map +1 -0
- package/dist/scripts/diagnose-pool-history.d.ts +3 -0
- package/dist/scripts/diagnose-pool-history.d.ts.map +1 -0
- package/dist/scripts/diagnose-pool-history.js +296 -0
- package/dist/scripts/diagnose-pool-history.js.map +1 -0
- package/dist/scripts/divergence-calc.d.ts +26 -0
- package/dist/scripts/divergence-calc.d.ts.map +1 -0
- package/dist/scripts/divergence-calc.js +119 -0
- package/dist/scripts/divergence-calc.js.map +1 -0
- package/dist/scripts/generate_lp_chart.d.ts +31 -0
- package/dist/scripts/generate_lp_chart.d.ts.map +1 -0
- package/dist/scripts/generate_lp_chart.js +92 -0
- package/dist/scripts/generate_lp_chart.js.map +1 -0
- package/dist/scripts/generate_mainnet_corpus_report.d.ts +24 -0
- package/dist/scripts/generate_mainnet_corpus_report.d.ts.map +1 -0
- package/dist/scripts/generate_mainnet_corpus_report.js +237 -0
- package/dist/scripts/generate_mainnet_corpus_report.js.map +1 -0
- package/dist/scripts/generate_market_adapter_whitelist.d.ts +2 -0
- package/dist/scripts/generate_market_adapter_whitelist.d.ts.map +1 -0
- package/dist/scripts/generate_market_adapter_whitelist.js +111 -0
- package/dist/scripts/generate_market_adapter_whitelist.js.map +1 -0
- package/dist/scripts/migrate_bot_keys.d.ts +6 -0
- package/dist/scripts/migrate_bot_keys.d.ts.map +1 -0
- package/dist/scripts/migrate_bot_keys.js +301 -0
- package/dist/scripts/migrate_bot_keys.js.map +1 -0
- package/dist/scripts/native_release_gates.d.ts +3 -0
- package/dist/scripts/native_release_gates.d.ts.map +1 -0
- package/dist/scripts/native_release_gates.js +52 -0
- package/dist/scripts/native_release_gates.js.map +1 -0
- package/dist/scripts/print_grid.d.ts +16 -0
- package/dist/scripts/print_grid.d.ts.map +1 -0
- package/dist/scripts/print_grid.js +80 -0
- package/dist/scripts/print_grid.js.map +1 -0
- package/dist/scripts/run-tests.d.ts +2 -0
- package/dist/scripts/run-tests.d.ts.map +1 -0
- package/dist/scripts/run-tests.js +49 -0
- package/dist/scripts/run-tests.js.map +1 -0
- package/dist/scripts/sync-version.d.ts +14 -0
- package/dist/scripts/sync-version.d.ts.map +1 -0
- package/dist/scripts/sync-version.js +158 -0
- package/dist/scripts/sync-version.js.map +1 -0
- package/dist/scripts/test-credit-renewal.d.ts +2 -0
- package/dist/scripts/test-credit-renewal.d.ts.map +1 -0
- package/dist/scripts/test-credit-renewal.js +329 -0
- package/dist/scripts/test-credit-renewal.js.map +1 -0
- package/dist/scripts/update.d.ts +24 -0
- package/dist/scripts/update.d.ts.map +1 -0
- package/dist/scripts/update.js +650 -0
- package/dist/scripts/update.js.map +1 -0
- package/dist/scripts/validate_bots.d.ts +16 -0
- package/dist/scripts/validate_bots.d.ts.map +1 -0
- package/dist/scripts/validate_bots.js +106 -0
- package/dist/scripts/validate_bots.js.map +1 -0
- package/dist/scripts/verify-browser-bundle.d.ts +22 -0
- package/dist/scripts/verify-browser-bundle.d.ts.map +1 -0
- package/dist/scripts/verify-browser-bundle.js +339 -0
- package/dist/scripts/verify-browser-bundle.js.map +1 -0
- package/dist/unlock.d.ts +48 -0
- package/dist/unlock.d.ts.map +1 -0
- package/dist/unlock.js +925 -0
- package/dist/unlock.js.map +1 -0
- package/package.json +112 -0
- package/scripts/README.md +356 -0
- package/scripts/clear-all.sh +195 -0
- package/scripts/clear-logs.sh +95 -0
- package/scripts/clear-market-adapter.sh +196 -0
- package/scripts/clear-orders.sh +113 -0
- package/scripts/create-bot-symlinks.sh +51 -0
- package/scripts/postinstall.js +9 -0
- package/scripts/reset-settings.sh +118 -0
|
@@ -0,0 +1,1191 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* modules/order/accounting.ts - Accountant Engine
|
|
4
|
+
*
|
|
5
|
+
* Specialized engine for financial state and fund tracking.
|
|
6
|
+
* Responsible for calculating available funds, committed capital, and managing BTS blockchain fees.
|
|
7
|
+
* Exports a single Accountant class that manages all fund accounting operations.
|
|
8
|
+
*
|
|
9
|
+
* ===============================================================================
|
|
10
|
+
* TABLE OF CONTENTS - Accountant Class (18 methods)
|
|
11
|
+
* ===============================================================================
|
|
12
|
+
*
|
|
13
|
+
* CORE INITIALIZATION & RECALCULATION (2 methods)
|
|
14
|
+
* 1. constructor(manager) - Create new Accountant instance
|
|
15
|
+
* 2. resetFunds() - Initialize funds structure with zeroed values
|
|
16
|
+
*
|
|
17
|
+
* MASTER FUND CALCULATIONS (1 method)
|
|
18
|
+
* 3. recalculateFunds() - MASTER FUND CALCULATION: Recalculate all fund values based on order states
|
|
19
|
+
* Called after any state change. Aggregates committed/available funds and triggers allocation.
|
|
20
|
+
*
|
|
21
|
+
* VERIFICATION & RECOVERY (3 methods - async, internal)
|
|
22
|
+
* 4. _verifyFundInvariants(mgr, chainFreeBuy, chainFreeSell, chainBuy, chainSell) - Verify fund tracking invariants
|
|
23
|
+
* 5. _performStateRecovery(mgr) - Centralized state recovery (fetch + sync + validate) (async, internal)
|
|
24
|
+
* 6. _attemptFundRecovery(mgr, violationType) - Attempt immediate recovery from invariant violations (async, internal)
|
|
25
|
+
*
|
|
26
|
+
* CHAINFREE BALANCE MANAGEMENT (2 methods)
|
|
27
|
+
* 7. tryDeductFromChainFree(orderType, size, operation) - Atomically deduct from FREE portion
|
|
28
|
+
* 8. addToChainFree(orderType, size, operation) - Add amount back to optimistic chainFree balance
|
|
29
|
+
*
|
|
30
|
+
* BALANCE ADJUSTMENTS (4 methods)
|
|
31
|
+
* 9. adjustTotalBalance(orderType, delta, operation, totalOnly) - Adjust total and free balances
|
|
32
|
+
* 10. _normalizeSideHint(sideHint) - Normalize side hint to standard key (internal)
|
|
33
|
+
* 11. _resolveOrderSide(order, fallbackOrder, explicitSideHint) - Resolve order side (internal)
|
|
34
|
+
* 12. updateOptimisticFreeBalance(oldOrder, newOrder, context, fee, skipAssetAccounting) - Update optimistic balance during transitions
|
|
35
|
+
*
|
|
36
|
+
* FEE MANAGEMENT (2 methods)
|
|
37
|
+
* 13. deductBtsFees(requestedSide) - Deduct BTS fees using adjustTotalBalance with deferral strategy (async)
|
|
38
|
+
* 14. _deductFeesFromProceeds(assetSymbol, rawAmount, isMaker) - Deduct fees from fill proceeds (internal)
|
|
39
|
+
*
|
|
40
|
+
* FILL BALANCE TRACKING (1 method)
|
|
41
|
+
* 15. recordFillBalances(paysAsset, paysAmount, receivesAsset, receivesAmount, context) - Record fill proceeds (async)
|
|
42
|
+
*
|
|
43
|
+
* FILL PROCESSING (1 method)
|
|
44
|
+
* 16. processFillAccounting(fillOp, fillKey, persistenceMode) - Process fund impact of order fill (atomically updates accountTotals)
|
|
45
|
+
*
|
|
46
|
+
* RECOVERY & VALIDATION (2 methods)
|
|
47
|
+
* 17. resetRecoveryState() - Reset recovery backoff and state
|
|
48
|
+
* 18. validateTargetGrid(targetGrid, mgr) - Validate target grid fund requirements
|
|
49
|
+
*
|
|
50
|
+
* ===============================================================================
|
|
51
|
+
* FUND STRUCTURE (managed by Accountant)
|
|
52
|
+
* ===============================================================================
|
|
53
|
+
*
|
|
54
|
+
* manager.funds = {
|
|
55
|
+
* available: { buy, sell } // Available funds for placement
|
|
56
|
+
* total: { chain, grid } // Total across blockchain + grid
|
|
57
|
+
* virtual: { buy, sell } // Virtual order capital
|
|
58
|
+
* committed: { chain, grid } // Capital locked in active orders
|
|
59
|
+
* btsFeesOwed: number // Unpaid BTS fees
|
|
60
|
+
* }
|
|
61
|
+
*
|
|
62
|
+
* manager.accountTotals = {
|
|
63
|
+
* buy: number // Total BUY balance on blockchain
|
|
64
|
+
* sell: number // Total SELL balance on blockchain
|
|
65
|
+
* buyFree: number // FREE BUY (not in any order)
|
|
66
|
+
* sellFree: number // FREE SELL (not in any order)
|
|
67
|
+
* }
|
|
68
|
+
*
|
|
69
|
+
* ===============================================================================
|
|
70
|
+
*
|
|
71
|
+
* FUND INVARIANTS (verified by _verifyFundInvariants):
|
|
72
|
+
* - blockchainTotal = chainFreeBalance + committedAmount
|
|
73
|
+
* - Virtual orders don't reduce FREE balance
|
|
74
|
+
*
|
|
75
|
+
* ===============================================================================
|
|
76
|
+
*/
|
|
77
|
+
const { ORDER_TYPES, ORDER_STATES, PIPELINE_TIMING, TIMING, FEE_PARAMETERS } = require('../constants');
|
|
78
|
+
const { calculateAvailableFundsValue, getAssetFees, blockchainToFloat, getPrecisionSlack } = require('./utils/math');
|
|
79
|
+
const { PROCESSED_FILL_PERSISTENCE_MODES, resolveProcessedFillPersistenceMode } = require('./processed_fill_store');
|
|
80
|
+
const { resolveAccountRef } = require('./utils/system');
|
|
81
|
+
const Format = require('./format');
|
|
82
|
+
const { toFiniteNumber } = Format;
|
|
83
|
+
const fundRegistry = require('../fund_registry');
|
|
84
|
+
/**
|
|
85
|
+
* Accountant engine - Specialized handler for fund tracking and calculations
|
|
86
|
+
* @class Accountant
|
|
87
|
+
*/
|
|
88
|
+
class Accountant {
|
|
89
|
+
/**
|
|
90
|
+
* Create a new Accountant instance
|
|
91
|
+
*
|
|
92
|
+
* @param {Object} manager - OrderManager instance
|
|
93
|
+
* @param {Map<string, Object>} manager.orders - Orders map
|
|
94
|
+
* @param {Object} manager.accountTotals - Blockchain account balances
|
|
95
|
+
* @param {Object} manager.funds - Fund tracking structure
|
|
96
|
+
* @param {Logger} manager.logger - Logger instance
|
|
97
|
+
*/
|
|
98
|
+
manager;
|
|
99
|
+
_isVerifyingInvariants;
|
|
100
|
+
_pendingInvariantSnapshot;
|
|
101
|
+
_logThrottleState;
|
|
102
|
+
constructor(manager) {
|
|
103
|
+
this.manager = manager;
|
|
104
|
+
this._isVerifyingInvariants = false; // Prevents overlapping invariant checks
|
|
105
|
+
this._pendingInvariantSnapshot = null; // Coalesces latest request while one is running
|
|
106
|
+
this._logThrottleState = new Map();
|
|
107
|
+
}
|
|
108
|
+
_logThrottled(key, message, level = 'warn', intervalMs = TIMING.LOG_THROTTLE_INTERVAL_MS) {
|
|
109
|
+
const now = Date.now();
|
|
110
|
+
const state = this._logThrottleState.get(key) || { lastAt: 0, suppressed: 0, lastMessage: null };
|
|
111
|
+
if (!state.lastAt || (now - state.lastAt) >= intervalMs) {
|
|
112
|
+
const suffix = state.suppressed > 0 ? ` (suppressed ${state.suppressed} repeated log(s))` : '';
|
|
113
|
+
this.manager?.logger?.log?.(`${message}${suffix}`, level);
|
|
114
|
+
this._logThrottleState.set(key, { lastAt: now, suppressed: 0, lastMessage: message });
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
state.suppressed += 1;
|
|
118
|
+
this._logThrottleState.set(key, state);
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* @returns {Map<string, number>|null}
|
|
123
|
+
*/
|
|
124
|
+
_getProcessedFillTracker() {
|
|
125
|
+
return this.manager.processedFillTracker;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* @returns {import('./processed_fill_store').ProcessedFillStore|null}
|
|
129
|
+
*/
|
|
130
|
+
_getProcessedFillStore() {
|
|
131
|
+
return this.manager.processedFillStore;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Apply a list of balance adjustments.
|
|
135
|
+
* @param {Array<{orderType: string, delta: number, operation: string}>} balanceAdjustments
|
|
136
|
+
* @returns {void}
|
|
137
|
+
*/
|
|
138
|
+
_applyBalanceAdjustments(balanceAdjustments) {
|
|
139
|
+
for (const adjustment of balanceAdjustments) {
|
|
140
|
+
this.adjustTotalBalance(adjustment.orderType, adjustment.delta, adjustment.operation);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Roll back a list of balance adjustments in reverse order.
|
|
145
|
+
* @param {Array<{orderType: string, delta: number, operation: string}>} balanceAdjustments
|
|
146
|
+
* @returns {void}
|
|
147
|
+
*/
|
|
148
|
+
_rollbackBalanceAdjustments(balanceAdjustments) {
|
|
149
|
+
for (let i = balanceAdjustments.length - 1; i >= 0; i--) {
|
|
150
|
+
const adjustment = balanceAdjustments[i];
|
|
151
|
+
this.adjustTotalBalance(adjustment.orderType, -adjustment.delta, `${adjustment.operation}-rollback`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
_getBtsOrderType() {
|
|
155
|
+
const mgr = this.manager;
|
|
156
|
+
const btsSide = (mgr.config?.assetA === 'BTS') ? ORDER_TYPES.SELL : (mgr.config?.assetB === 'BTS') ? ORDER_TYPES.BUY : null;
|
|
157
|
+
return btsSide;
|
|
158
|
+
}
|
|
159
|
+
_normalizeBtsFeeState(order) {
|
|
160
|
+
const deferredFee = toFiniteNumber(order?.btsFeeState?.deferredFee, 0);
|
|
161
|
+
return {
|
|
162
|
+
deferredFee: Math.max(0, deferredFee)
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
_getBtsFeeSchedule() {
|
|
166
|
+
try {
|
|
167
|
+
const fees = getAssetFees('BTS');
|
|
168
|
+
return {
|
|
169
|
+
createFee: Math.max(0, toFiniteNumber(fees?.createFee, 0)),
|
|
170
|
+
updateFee: Math.max(0, toFiniteNumber(fees?.updateFee, 0)),
|
|
171
|
+
cancelFee: Math.max(0, toFiniteNumber(fees?.cancelFee, 0)),
|
|
172
|
+
makerFeeDiscountPercent: Math.max(0, toFiniteNumber(fees?.makerFeeDiscountPercent, this.manager?.config?.feeParams?.MAKER_REFUND_PERCENT ?? FEE_PARAMETERS.MAKER_REFUND_PERCENT))
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
catch (err) {
|
|
176
|
+
this.manager?.logger?.log?.(`[FEE] Failed to load BTS fee schedule: ${err?.message || err}; using fallback defaults`, 'warn');
|
|
177
|
+
return {
|
|
178
|
+
createFee: 0,
|
|
179
|
+
updateFee: 0,
|
|
180
|
+
cancelFee: 0,
|
|
181
|
+
makerFeeDiscountPercent: this.manager?.config?.feeParams?.MAKER_REFUND_PERCENT ?? FEE_PARAMETERS.MAKER_REFUND_PERCENT
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
_calculateUpdateDeferredCharge(oldDeferredFee, feeSchedule) {
|
|
186
|
+
const deferred = Math.max(0, toFiniteNumber(oldDeferredFee, 0));
|
|
187
|
+
const cancelFee = Math.max(0, toFiniteNumber(feeSchedule?.cancelFee, 0));
|
|
188
|
+
const createFee = Math.max(0, toFiniteNumber(feeSchedule?.createFee, 0));
|
|
189
|
+
const updateFee = Math.max(0, toFiniteNumber(feeSchedule?.updateFee, 0));
|
|
190
|
+
if (deferred <= 0 || cancelFee <= 0)
|
|
191
|
+
return 0;
|
|
192
|
+
// Core's formula (process_deferred_fee market_evaluator.cpp:294-296):
|
|
193
|
+
// charge = cancel_fee * update_fee / create_fee (integer division)
|
|
194
|
+
// Cap at deferred_fee. All amounts are already in float BTS units.
|
|
195
|
+
let charge = cancelFee;
|
|
196
|
+
if (createFee > 0) {
|
|
197
|
+
charge = (cancelFee * updateFee) / createFee;
|
|
198
|
+
}
|
|
199
|
+
return Math.min(deferred, Math.max(0, charge));
|
|
200
|
+
}
|
|
201
|
+
_resolveBtsFeeLifecycle(oldOrder, newOrder, context, explicitFee) {
|
|
202
|
+
const fee = Math.max(0, toFiniteNumber(explicitFee, 0));
|
|
203
|
+
const oldActive = !!(oldOrder && (oldOrder.state === ORDER_STATES.ACTIVE || oldOrder.state === ORDER_STATES.PARTIAL) && oldOrder.orderId);
|
|
204
|
+
const newActive = !!(newOrder && (newOrder.state === ORDER_STATES.ACTIVE || newOrder.state === ORDER_STATES.PARTIAL) && newOrder.orderId);
|
|
205
|
+
const oldDeferred = this._normalizeBtsFeeState(oldOrder).deferredFee;
|
|
206
|
+
const sameChainOrder = oldActive && newActive && oldOrder.orderId === newOrder.orderId;
|
|
207
|
+
const feeSchedule = this._getBtsFeeSchedule();
|
|
208
|
+
const isFillTransition = typeof context === 'string' && context.startsWith('handle-fill-');
|
|
209
|
+
let balanceDelta = 0;
|
|
210
|
+
let nextDeferred = newActive ? oldDeferred : 0;
|
|
211
|
+
if (!oldActive && newActive && fee > 0) {
|
|
212
|
+
// Core stores limit_order_create fees as deferred_fee on the new order.
|
|
213
|
+
balanceDelta -= fee;
|
|
214
|
+
nextDeferred = fee;
|
|
215
|
+
}
|
|
216
|
+
else if (oldActive && sameChainOrder && fee > 0) {
|
|
217
|
+
// Core processes the previous deferred fee before deferring the update fee.
|
|
218
|
+
const oldDeferredCharge = this._calculateUpdateDeferredCharge(oldDeferred, feeSchedule);
|
|
219
|
+
balanceDelta += oldDeferred - oldDeferredCharge;
|
|
220
|
+
balanceDelta -= fee;
|
|
221
|
+
nextDeferred = fee;
|
|
222
|
+
}
|
|
223
|
+
else if (oldActive && isFillTransition) {
|
|
224
|
+
// Core processes deferred fees during fill_order handling, before
|
|
225
|
+
// the in-memory order is resized or removed.
|
|
226
|
+
nextDeferred = 0;
|
|
227
|
+
}
|
|
228
|
+
else if (oldActive && !newActive && fee > 0) {
|
|
229
|
+
// A real cancel pays the cancel operation fee and refunds the remaining deferred fee.
|
|
230
|
+
// Core caps the cancel fee at deferred_fee (cancel_limit_order db_market.cpp:551-554).
|
|
231
|
+
balanceDelta += Math.max(0, oldDeferred - fee);
|
|
232
|
+
nextDeferred = 0;
|
|
233
|
+
}
|
|
234
|
+
else if (!newActive) {
|
|
235
|
+
nextDeferred = 0;
|
|
236
|
+
}
|
|
237
|
+
if (newOrder && typeof newOrder === 'object') {
|
|
238
|
+
if (nextDeferred > 0) {
|
|
239
|
+
newOrder.btsFeeState = {
|
|
240
|
+
...(newOrder.btsFeeState || {}),
|
|
241
|
+
deferredFee: nextDeferred
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
else if (newOrder.btsFeeState) {
|
|
245
|
+
// nextDeferred is 0: the deferred fee is consumed on-chain
|
|
246
|
+
// (fill, cancel, or order removed). Core zeros both
|
|
247
|
+
// deferred_fee and deferred_paid_fee on the order at this
|
|
248
|
+
// point, so clear the entire btsFeeState.
|
|
249
|
+
delete newOrder.btsFeeState;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
if (this.manager?.logger?.level === 'debug' && Math.abs(balanceDelta) > 0) {
|
|
253
|
+
this.manager.logger.log(`[BTS-FEE] ${context}: oldDeferred=${Format.formatAmount8(oldDeferred)}, fee=${Format.formatAmount8(fee)}, nextDeferred=${Format.formatAmount8(nextDeferred)}, delta=${Format.formatAmount8(balanceDelta)}`, 'debug');
|
|
254
|
+
}
|
|
255
|
+
return { balanceDelta, nextDeferred };
|
|
256
|
+
}
|
|
257
|
+
_buildBtsDeferredRefundAdjustment(orderId, isMaker) {
|
|
258
|
+
const btsOrderType = this._getBtsOrderType();
|
|
259
|
+
if (!btsOrderType || !orderId)
|
|
260
|
+
return null;
|
|
261
|
+
const order = Array.from(this.manager.orders?.values?.() || []).find((o) => o?.orderId === orderId);
|
|
262
|
+
const deferredFee = this._normalizeBtsFeeState(order).deferredFee;
|
|
263
|
+
if (deferredFee <= 0)
|
|
264
|
+
return null;
|
|
265
|
+
const feeSchedule = this._getBtsFeeSchedule();
|
|
266
|
+
if (!isMaker)
|
|
267
|
+
return null;
|
|
268
|
+
// Core's BSIP85 maker refund: deferred_fee * maker_discount_percent / GRAPHENE_100_PERCENT
|
|
269
|
+
const refund = deferredFee * feeSchedule.makerFeeDiscountPercent;
|
|
270
|
+
if (refund <= 0)
|
|
271
|
+
return null;
|
|
272
|
+
return {
|
|
273
|
+
orderType: btsOrderType,
|
|
274
|
+
delta: refund,
|
|
275
|
+
operation: 'fill-bts-deferred-fee-refund'
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Initialize the funds structure with zeroed values.
|
|
280
|
+
*
|
|
281
|
+
* @returns {void}
|
|
282
|
+
*/
|
|
283
|
+
resetFunds() {
|
|
284
|
+
const mgr = this.manager;
|
|
285
|
+
mgr.accountTotals = mgr.accountTotals || (mgr.config.accountTotals ? { ...mgr.config.accountTotals } : { buy: null, sell: null, buyFree: null, sellFree: null });
|
|
286
|
+
mgr.funds = {
|
|
287
|
+
available: { buy: 0, sell: 0 },
|
|
288
|
+
total: { chain: { buy: 0, sell: 0 }, grid: { buy: 0, sell: 0 } },
|
|
289
|
+
virtual: { buy: 0, sell: 0 },
|
|
290
|
+
committed: { chain: { buy: 0, sell: 0 }, grid: { buy: 0, sell: 0 } },
|
|
291
|
+
btsFeesOwed: 0, // Unpaid BTS fees
|
|
292
|
+
btsBalance: { free: 0, total: 0, locked: 0 } // BTS balance for non-BTS pairs
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Recalculate all fund values based on current order states.
|
|
297
|
+
* This is THE MASTER FUND CALCULATION and must be called after any state change.
|
|
298
|
+
* Called automatically by _updateOrder(), but can be manually triggered to verify consistency.
|
|
299
|
+
*
|
|
300
|
+
* PSEUDOCODE ALGORITHM:
|
|
301
|
+
* =====================
|
|
302
|
+
* 1. Initialize accumulators (gridBuy, gridSell, chainBuy, chainSell, virtualBuy, virtualSell)
|
|
303
|
+
* 2. Classify each order's state (ACTIVE/PARTIAL = on-chain committed, VIRTUAL = pending)
|
|
304
|
+
* 3. Determine side from order.type, or derive from SPREAD price vs startPrice threshold
|
|
305
|
+
* 4. Aggregate sizes by side and state:
|
|
306
|
+
* - ACTIVE/PARTIAL orders → committed.grid and committed.chain
|
|
307
|
+
* - VIRTUAL orders → virtual pool
|
|
308
|
+
* - Skip zero-sized orders
|
|
309
|
+
* 5. Calculate blockchain totals:
|
|
310
|
+
* - chainTotalBuy = chainFreeBuy (from accountTotals) + chainBuy (committed on-chain)
|
|
311
|
+
* - chainTotalSell = chainFreeSell + chainSell
|
|
312
|
+
* 6. Calculate available funds by subtracting committed amounts from blockchain totals
|
|
313
|
+
* - available.buy = chainTotalBuy - committed.chain.buy (after grid allocation)
|
|
314
|
+
* - available.sell = chainTotalSell - committed.chain.sell (after grid allocation)
|
|
315
|
+
* 7. Apply percentage-based fund allocations (botFunds) if configured
|
|
316
|
+
* 8. Verify fund invariants (total = free + committed) to detect tracking drift
|
|
317
|
+
*
|
|
318
|
+
* CRITICAL INVARIANTS MAINTAINED:
|
|
319
|
+
* - Total on-chain balance = Free portion + Committed portion
|
|
320
|
+
* - Virtual orders don't reduce blockchain-tracked free balance
|
|
321
|
+
* - Grid totals = committed amounts + virtual amounts (pending placements)
|
|
322
|
+
* - Available funds represent true spending power (after commitment deductions)
|
|
323
|
+
*
|
|
324
|
+
* @returns {void}
|
|
325
|
+
*/
|
|
326
|
+
async recalculateFunds() {
|
|
327
|
+
const mgr = this.manager;
|
|
328
|
+
if (mgr._pauseFundRecalc > 0)
|
|
329
|
+
return;
|
|
330
|
+
if (!mgr.funds)
|
|
331
|
+
this.resetFunds();
|
|
332
|
+
// Sync btsBalance from manager into funds for non-BTS pairs
|
|
333
|
+
if (mgr.btsBalance) {
|
|
334
|
+
mgr.funds.btsBalance = { ...mgr.funds.btsBalance, ...mgr.btsBalance };
|
|
335
|
+
}
|
|
336
|
+
// No lock needed for read-only access to frozen orders (COW pattern)
|
|
337
|
+
const orderSnapshot = Array.from(mgr.orders.values());
|
|
338
|
+
let gridBuy = 0, gridSell = 0;
|
|
339
|
+
let chainBuy = 0, chainSell = 0;
|
|
340
|
+
let virtualBuy = 0, virtualSell = 0;
|
|
341
|
+
// AUTO-SYNC SPREAD COUNT
|
|
342
|
+
mgr.currentSpreadCount = mgr._ordersByType[ORDER_TYPES.SPREAD]?.size || 0;
|
|
343
|
+
// STEP 1-4: Iterate all orders, classify, and aggregate by state
|
|
344
|
+
for (const order of orderSnapshot) {
|
|
345
|
+
const isActive = (order.state === ORDER_STATES.ACTIVE || order.state === ORDER_STATES.PARTIAL) && !!order.orderId;
|
|
346
|
+
const isVirtual = (order.state === ORDER_STATES.VIRTUAL);
|
|
347
|
+
const size = toFiniteNumber(order.size);
|
|
348
|
+
if (size <= 0)
|
|
349
|
+
continue;
|
|
350
|
+
// SIDE DETERMINATION:
|
|
351
|
+
// - Explicit BUY/SELL: use order.type directly
|
|
352
|
+
// - SPREAD type: derive from price relation to startPrice (market midpoint)
|
|
353
|
+
// * price < startPrice → BUY side (lower prices are bids)
|
|
354
|
+
// * price >= startPrice → SELL side (higher prices are asks)
|
|
355
|
+
const isBuy = order.type === ORDER_TYPES.BUY || (order.type === ORDER_TYPES.SPREAD && order.price < mgr.startPrice);
|
|
356
|
+
const isSell = order.type === ORDER_TYPES.SELL || (order.type === ORDER_TYPES.SPREAD && order.price >= mgr.startPrice);
|
|
357
|
+
if (isBuy) {
|
|
358
|
+
if (isActive) {
|
|
359
|
+
gridBuy += size;
|
|
360
|
+
chainBuy += size;
|
|
361
|
+
}
|
|
362
|
+
if (isVirtual)
|
|
363
|
+
virtualBuy += size;
|
|
364
|
+
}
|
|
365
|
+
else if (isSell) {
|
|
366
|
+
if (isActive) {
|
|
367
|
+
gridSell += size;
|
|
368
|
+
chainSell += size;
|
|
369
|
+
}
|
|
370
|
+
if (isVirtual)
|
|
371
|
+
virtualSell += size;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
// STEP 5: Fetch blockchain free balances and compute totals
|
|
375
|
+
const chainFreeBuy = mgr.accountTotals?.buyFree || 0;
|
|
376
|
+
const chainFreeSell = mgr.accountTotals?.sellFree || 0;
|
|
377
|
+
// Store committed amounts (on-chain and in-memory grid)
|
|
378
|
+
mgr.funds.committed.grid = { buy: gridBuy, sell: gridSell };
|
|
379
|
+
mgr.funds.committed.chain = { buy: chainBuy, sell: chainSell };
|
|
380
|
+
mgr.funds.virtual = { buy: virtualBuy, sell: virtualSell };
|
|
381
|
+
// STEP 5: Compute total balances (free + committed)
|
|
382
|
+
// These represent ALL funds we have, regardless of state
|
|
383
|
+
const chainTotalBuy = chainFreeBuy + chainBuy;
|
|
384
|
+
const chainTotalSell = chainFreeSell + chainSell;
|
|
385
|
+
mgr.funds.total.chain = { buy: chainTotalBuy, sell: chainTotalSell };
|
|
386
|
+
mgr.funds.total.grid = { buy: gridBuy + virtualBuy, sell: gridSell + virtualSell };
|
|
387
|
+
// STEP 6: Calculate available funds (what we can spend right now)
|
|
388
|
+
// Uses utils::calculateAvailableFundsValue which deducts committe amounts
|
|
389
|
+
mgr.funds.available.buy = calculateAvailableFundsValue('buy', mgr.accountTotals, mgr.funds, mgr.config.assetA, mgr.config.assetB, mgr.config.activeOrders, mgr.config.min_BTS_value, mgr.config?.feeParams ?? null);
|
|
390
|
+
mgr.funds.available.sell = calculateAvailableFundsValue('sell', mgr.accountTotals, mgr.funds, mgr.config.assetA, mgr.config.assetB, mgr.config.activeOrders, mgr.config.min_BTS_value, mgr.config?.feeParams ?? null);
|
|
391
|
+
// Ensure percentage-based allocations are applied to the newly calculated totals
|
|
392
|
+
if (typeof mgr.applyBotFundsAllocation === 'function') {
|
|
393
|
+
mgr.applyBotFundsAllocation();
|
|
394
|
+
}
|
|
395
|
+
if (mgr.logger && mgr.logger.level === 'debug' && mgr._pauseFundRecalc === 0 && !mgr._pauseRecalcLogging) {
|
|
396
|
+
const buyPrecision = mgr.config?.assetB?.precision;
|
|
397
|
+
const sellPrecision = mgr.config?.assetA?.precision;
|
|
398
|
+
if (Number.isFinite(buyPrecision) && Number.isFinite(sellPrecision)) {
|
|
399
|
+
mgr.logger.log(`[RECALC] BUY: Total=${Format.formatAmountByPrecision(chainTotalBuy, buyPrecision)} (Free=${Format.formatAmountByPrecision(chainFreeBuy, buyPrecision)}, Grid=${Format.formatAmountByPrecision(gridBuy, buyPrecision)})`, 'debug');
|
|
400
|
+
mgr.logger.log(`[RECALC] SELL: Total=${Format.formatAmountByPrecision(chainTotalSell, sellPrecision)} (Free=${Format.formatAmountByPrecision(chainFreeSell, sellPrecision)}, Grid=${Format.formatAmountByPrecision(gridSell, sellPrecision)})`, 'debug');
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
if (mgr._pauseFundRecalc === 0 && !mgr._state.isBootstrapping() && !mgr._state.isBroadcastingActive()) {
|
|
404
|
+
const snapshot = { chainFreeBuy, chainFreeSell, chainBuy, chainSell };
|
|
405
|
+
const runVerification = (nextSnapshot) => {
|
|
406
|
+
this._isVerifyingInvariants = true;
|
|
407
|
+
this._verifyFundInvariants(mgr, nextSnapshot.chainFreeBuy, nextSnapshot.chainFreeSell, nextSnapshot.chainBuy, nextSnapshot.chainSell)
|
|
408
|
+
.catch(err => {
|
|
409
|
+
mgr.logger?.log?.(`[RECOVERY] Verification error: ${err.message}`, 'error');
|
|
410
|
+
})
|
|
411
|
+
.finally(() => {
|
|
412
|
+
this._isVerifyingInvariants = false;
|
|
413
|
+
if (this._pendingInvariantSnapshot) {
|
|
414
|
+
const pending = this._pendingInvariantSnapshot;
|
|
415
|
+
this._pendingInvariantSnapshot = null;
|
|
416
|
+
runVerification(pending);
|
|
417
|
+
}
|
|
418
|
+
});
|
|
419
|
+
};
|
|
420
|
+
if (this._isVerifyingInvariants) {
|
|
421
|
+
this._pendingInvariantSnapshot = snapshot;
|
|
422
|
+
}
|
|
423
|
+
else {
|
|
424
|
+
runVerification(snapshot);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Verify critical fund tracking invariants.
|
|
430
|
+
*
|
|
431
|
+
* Checks that accountTotals.buy/sell match chainFree + committed amounts
|
|
432
|
+
* within combined precision and percentage tolerances. Detects fee double-
|
|
433
|
+
* deductions, missing fills, and blockchain state desync.
|
|
434
|
+
*
|
|
435
|
+
* @param {Object} mgr - OrderManager instance
|
|
436
|
+
* @param {number} chainFreeBuy - Free (unallocated) buy-side balance from chain
|
|
437
|
+
* @param {number} chainFreeSell - Free (unallocated) sell-side balance from chain
|
|
438
|
+
* @param {number} chainBuy - Committed buy-side balance from chain
|
|
439
|
+
* @param {number} chainSell - Committed sell-side balance from chain
|
|
440
|
+
* @returns {void}
|
|
441
|
+
* @private
|
|
442
|
+
*/
|
|
443
|
+
async _verifyFundInvariants(mgr, chainFreeBuy, chainFreeSell, chainBuy, chainSell) {
|
|
444
|
+
const buyPrecision = mgr.assets?.assetB?.precision;
|
|
445
|
+
const sellPrecision = mgr.assets?.assetA?.precision;
|
|
446
|
+
if (!Number.isFinite(buyPrecision) || !Number.isFinite(sellPrecision)) {
|
|
447
|
+
return; // Skip invariant check if precision not available
|
|
448
|
+
}
|
|
449
|
+
const precisionSlackBuy = getPrecisionSlack(buyPrecision);
|
|
450
|
+
const precisionSlackSell = getPrecisionSlack(sellPrecision);
|
|
451
|
+
const PERCENT_TOLERANCE = (mgr.config?.gridLimits?.FUND_INVARIANT_PERCENT_TOLERANCE) / 100;
|
|
452
|
+
let hasViolation = false;
|
|
453
|
+
// INVARIANT 1: Drift detection
|
|
454
|
+
// FORMULA: expectedBuy = chainFreeBuy + chainBuy (what we think we have)
|
|
455
|
+
// actualBuy = mgr.accountTotals.buy (what blockchain says)
|
|
456
|
+
// If |actualBuy - expectedBuy| > tolerance → fund tracking corruption detected
|
|
457
|
+
const expectedBuy = chainFreeBuy + chainBuy;
|
|
458
|
+
const actualBuy = mgr.accountTotals?.buy;
|
|
459
|
+
const diffBuy = Math.abs((actualBuy ?? expectedBuy) - expectedBuy);
|
|
460
|
+
const allowedBuyTolerance = Math.max(precisionSlackBuy, (actualBuy || expectedBuy) * PERCENT_TOLERANCE);
|
|
461
|
+
if (actualBuy !== null && actualBuy !== undefined && diffBuy > allowedBuyTolerance) {
|
|
462
|
+
hasViolation = true;
|
|
463
|
+
// CRITICAL FIX: Log as ERROR instead of WARN
|
|
464
|
+
// Invariant violations indicate serious fund tracking corruption and must not be silent
|
|
465
|
+
// This triggers immediate recovery attempt
|
|
466
|
+
this._logThrottled('fund-invariant-buy', `CRITICAL: Fund invariant violation (BUY): blockchainTotal (${Format.formatAmountByPrecision(actualBuy, buyPrecision)}) != trackedTotal (${Format.formatAmountByPrecision(expectedBuy, buyPrecision)}) (diff: ${Format.formatAmountByPrecision(diffBuy, buyPrecision)}, allowed: ${Format.formatAmountByPrecision(allowedBuyTolerance, buyPrecision)})`, 'error');
|
|
467
|
+
}
|
|
468
|
+
const expectedSell = chainFreeSell + chainSell;
|
|
469
|
+
const actualSell = mgr.accountTotals?.sell;
|
|
470
|
+
const diffSell = Math.abs((actualSell ?? expectedSell) - expectedSell);
|
|
471
|
+
const allowedSellTolerance = Math.max(precisionSlackSell, (actualSell || expectedSell) * PERCENT_TOLERANCE);
|
|
472
|
+
if (actualSell !== null && actualSell !== undefined && diffSell > allowedSellTolerance) {
|
|
473
|
+
hasViolation = true;
|
|
474
|
+
// CRITICAL FIX: Log as ERROR instead of WARN
|
|
475
|
+
this._logThrottled('fund-invariant-sell', `CRITICAL: Fund invariant violation (SELL): blockchainTotal (${Format.formatAmountByPrecision(actualSell, sellPrecision)}) != trackedTotal (${Format.formatAmountByPrecision(expectedSell, sellPrecision)}) (diff: ${Format.formatAmountByPrecision(diffSell, sellPrecision)}, allowed: ${Format.formatAmountByPrecision(allowedSellTolerance, sellPrecision)})`, 'error');
|
|
476
|
+
}
|
|
477
|
+
// INVARIANT 3: Cross-bot registry invariant (shared accounts)
|
|
478
|
+
// Checks that this bot's committed ≤ expected proportional share, with
|
|
479
|
+
// a wider tolerance than per-bot invariant to accommodate transient
|
|
480
|
+
// over-allocation during mid-flight rebalances.
|
|
481
|
+
if (mgr.config?.preferredAccount && mgr.config.botKey) {
|
|
482
|
+
try {
|
|
483
|
+
const account = mgr.config.preferredAccount;
|
|
484
|
+
const botName = mgr.config.botKey;
|
|
485
|
+
const registeredBots = fundRegistry.getRegisteredBots(account);
|
|
486
|
+
if (registeredBots.length > 1) {
|
|
487
|
+
const crossBotTolerance = Math.max(PERCENT_TOLERANCE * 3, 0.15);
|
|
488
|
+
const totalBuyPct = fundRegistry.getTotalAllocatedPct(account, 'buy');
|
|
489
|
+
const totalSellPct = fundRegistry.getTotalAllocatedPct(account, 'sell');
|
|
490
|
+
const myBuyPct = fundRegistry.getBotAllocationPct(account, botName, 'buy');
|
|
491
|
+
const mySellPct = fundRegistry.getBotAllocationPct(account, botName, 'sell');
|
|
492
|
+
if (myBuyPct !== null && totalBuyPct > 0) {
|
|
493
|
+
const proportionalBuy = (chainFreeBuy + chainBuy) * (myBuyPct / totalBuyPct);
|
|
494
|
+
const committedBuy = mgr.funds?.committed?.chain?.buy || 0;
|
|
495
|
+
const maxAllowedBuy = proportionalBuy * (1 + crossBotTolerance);
|
|
496
|
+
if (committedBuy > maxAllowedBuy && proportionalBuy > precisionSlackBuy) {
|
|
497
|
+
hasViolation = true;
|
|
498
|
+
this._logThrottled('fund-invariant-crossbot-buy', `[SHARED ACCOUNT] BUY over-allocation: committed=${Format.formatAmountByPrecision(committedBuy, buyPrecision)}, ` +
|
|
499
|
+
`proportionalShare=${Format.formatAmountByPrecision(proportionalBuy, buyPrecision)} ` +
|
|
500
|
+
`(myPct=${(myBuyPct * 100).toFixed(1)}%, totalPct=${(totalBuyPct * 100).toFixed(1)}%)`, 'error');
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
if (mySellPct !== null && totalSellPct > 0) {
|
|
504
|
+
const proportionalSell = (chainFreeSell + chainSell) * (mySellPct / totalSellPct);
|
|
505
|
+
const committedSell = mgr.funds?.committed?.chain?.sell || 0;
|
|
506
|
+
const maxAllowedSell = proportionalSell * (1 + crossBotTolerance);
|
|
507
|
+
if (committedSell > maxAllowedSell && proportionalSell > precisionSlackSell) {
|
|
508
|
+
hasViolation = true;
|
|
509
|
+
this._logThrottled('fund-invariant-crossbot-sell', `[SHARED ACCOUNT] SELL over-allocation: committed=${Format.formatAmountByPrecision(committedSell, sellPrecision)}, ` +
|
|
510
|
+
`proportionalShare=${Format.formatAmountByPrecision(proportionalSell, sellPrecision)} ` +
|
|
511
|
+
`(myPct=${(mySellPct * 100).toFixed(1)}%, totalPct=${(totalSellPct * 100).toFixed(1)}%)`, 'error');
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
catch (_err) {
|
|
517
|
+
mgr.logger?.log?.(`[INVARIANT] Cross-bot registry check skipped: ${_err.message}`, 'warn');
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
// NEW: Attempt immediate recovery if violation detected
|
|
521
|
+
if (hasViolation) {
|
|
522
|
+
const doRecovery = async () => {
|
|
523
|
+
try {
|
|
524
|
+
await this._attemptFundRecovery(mgr, 'Fund invariant violation');
|
|
525
|
+
}
|
|
526
|
+
catch (err) {
|
|
527
|
+
mgr.logger?.log?.(`[RECOVERY] Deferred recovery failed: ${err.message}`, 'error');
|
|
528
|
+
mgr._recoveryState = mgr._recoveryState || {};
|
|
529
|
+
mgr._recoveryState.lastFailureAt = Date.now();
|
|
530
|
+
}
|
|
531
|
+
};
|
|
532
|
+
if (mgr._gridLock?.isLocked?.()) {
|
|
533
|
+
doRecovery().catch(err => {
|
|
534
|
+
mgr.logger?.log?.(`[RECOVERY] Deferred recovery scheduling failed: ${err.message}`, 'error');
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
else {
|
|
538
|
+
await doRecovery();
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* Perform centralized state recovery (fetch + sync + validate).
|
|
544
|
+
* Shared by both immediate recovery and stabilization gate.
|
|
545
|
+
*
|
|
546
|
+
* @param {Object} mgr - Manager instance
|
|
547
|
+
* @returns {Promise<Object>} - Validation result from validateGridStateForPersistence()
|
|
548
|
+
*/
|
|
549
|
+
async _performStateRecovery(mgr) {
|
|
550
|
+
const accountRef = resolveAccountRef(mgr);
|
|
551
|
+
if (!accountRef) {
|
|
552
|
+
return {
|
|
553
|
+
isValid: false,
|
|
554
|
+
reason: 'Recovery skipped: missing account context (accountId/account)'
|
|
555
|
+
};
|
|
556
|
+
}
|
|
557
|
+
// 1. Fetch fresh blockchain state
|
|
558
|
+
await mgr.fetchAccountTotals(accountRef);
|
|
559
|
+
// 2. Sync from open orders
|
|
560
|
+
const chainOrders = require('../chain_orders');
|
|
561
|
+
const openOrders = await chainOrders.readOpenOrders(accountRef);
|
|
562
|
+
// Recovery runs after fetchAccountTotals() has refreshed authoritative balances
|
|
563
|
+
// from chain. During this pass we only want to reconcile grid structure/order
|
|
564
|
+
// mapping against open orders; re-applying optimistic accounting deltas here
|
|
565
|
+
// double-counts commitment changes and can amplify invariant drift.
|
|
566
|
+
const syncResult = await mgr.syncFromOpenOrders(openOrders, { skipAccounting: true, fillLockAlreadyHeld: true });
|
|
567
|
+
const unmatchedChainOrders = Array.isArray(syncResult?.unmatchedChainOrders)
|
|
568
|
+
? syncResult.unmatchedChainOrders
|
|
569
|
+
: [];
|
|
570
|
+
// 3. Validate recovery. Persistence validation catches structural
|
|
571
|
+
// corruption; drift validation catches accounting mismatches that are
|
|
572
|
+
// otherwise masked while bootstrap suppression is active.
|
|
573
|
+
const persistenceValidation = mgr.validateGridStateForPersistence({ allowBootstrapTransient: false });
|
|
574
|
+
if (!persistenceValidation.isValid) {
|
|
575
|
+
if (unmatchedChainOrders.length > 0) {
|
|
576
|
+
return {
|
|
577
|
+
...persistenceValidation,
|
|
578
|
+
structuralGridResyncRequired: true,
|
|
579
|
+
unmatchedChainOrders,
|
|
580
|
+
reason: `${persistenceValidation.reason}; ${unmatchedChainOrders.length} unmatched chain order(s) require structural grid resync`
|
|
581
|
+
};
|
|
582
|
+
}
|
|
583
|
+
return persistenceValidation;
|
|
584
|
+
}
|
|
585
|
+
if (typeof mgr.checkFundDriftAfterFills === 'function') {
|
|
586
|
+
const driftValidation = mgr.checkFundDriftAfterFills();
|
|
587
|
+
if (driftValidation && driftValidation.isValid === false) {
|
|
588
|
+
if (unmatchedChainOrders.length > 0) {
|
|
589
|
+
return {
|
|
590
|
+
...driftValidation,
|
|
591
|
+
structuralGridResyncRequired: true,
|
|
592
|
+
unmatchedChainOrders,
|
|
593
|
+
reason: `${driftValidation.reason}; ${unmatchedChainOrders.length} unmatched chain order(s) require structural grid resync`
|
|
594
|
+
};
|
|
595
|
+
}
|
|
596
|
+
return driftValidation;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
return persistenceValidation;
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* Attempt immediate recovery from fund invariant violations.
|
|
603
|
+
* Runs once per cycle - subsequent violations in same cycle are skipped.
|
|
604
|
+
*
|
|
605
|
+
* @param {Object} mgr - Manager instance
|
|
606
|
+
* @param {string} violationType - Description of the violation for logging
|
|
607
|
+
* @returns {Promise<boolean>} - True if recovery succeeded, false otherwise
|
|
608
|
+
*/
|
|
609
|
+
async _attemptFundRecovery(mgr, violationType) {
|
|
610
|
+
if (!mgr._recoveryState || typeof mgr._recoveryState !== 'object') {
|
|
611
|
+
mgr._recoveryState = { attemptCount: 0, lastAttemptAt: 0, inFlight: false, lastFailureAt: 0, structuralResyncRequested: false };
|
|
612
|
+
}
|
|
613
|
+
const state = mgr._recoveryState;
|
|
614
|
+
const now = Date.now();
|
|
615
|
+
const retryIntervalMs = Math.max(0, Number(PIPELINE_TIMING.RECOVERY_RETRY_INTERVAL_MS));
|
|
616
|
+
const maxAttemptsRaw = Number(PIPELINE_TIMING.MAX_RECOVERY_ATTEMPTS);
|
|
617
|
+
const hasAttemptLimit = Number.isFinite(maxAttemptsRaw) && maxAttemptsRaw > 0;
|
|
618
|
+
if (state.inFlight) {
|
|
619
|
+
mgr.logger?.log?.('[RECOVERY] Skipping recovery: attempt already in flight', 'debug');
|
|
620
|
+
return false;
|
|
621
|
+
}
|
|
622
|
+
// Decay: if enough time has passed since the last failure, treat this
|
|
623
|
+
// as a fresh violation cycle to prevent stale counts from a previous
|
|
624
|
+
// cycle permanently exhausting the attempt budget.
|
|
625
|
+
const decayMs = retryIntervalMs > 0 ? retryIntervalMs * 3 : PIPELINE_TIMING.RECOVERY_DECAY_FALLBACK_MS;
|
|
626
|
+
if (state.attemptCount > 0 && state.lastFailureAt > 0 && (now - state.lastFailureAt) > decayMs) {
|
|
627
|
+
// Log at 'info' level so operators can monitor for repeated decay patterns
|
|
628
|
+
// which may indicate a persistent issue that self-corrects just long enough
|
|
629
|
+
// to trigger decay, then recurs. Pattern: repeated "decayed" messages.
|
|
630
|
+
mgr.logger?.log?.(`[RECOVERY] Attempt count decayed (${state.attemptCount} -> 0) after ${Math.round((now - state.lastFailureAt) / TIMING.MILLISECONDS_PER_SECOND)}s idle`, 'info');
|
|
631
|
+
state.attemptCount = 0;
|
|
632
|
+
state.lastFailureAt = 0;
|
|
633
|
+
}
|
|
634
|
+
if (hasAttemptLimit && state.attemptCount >= maxAttemptsRaw) {
|
|
635
|
+
this._logThrottled('recovery-max-attempts', `[RECOVERY] Skipping recovery: max attempts reached (${state.attemptCount}/${maxAttemptsRaw})`, 'warn');
|
|
636
|
+
return false;
|
|
637
|
+
}
|
|
638
|
+
if (state.attemptCount > 0 && retryIntervalMs > 0) {
|
|
639
|
+
const elapsed = now - state.lastAttemptAt;
|
|
640
|
+
if (elapsed < retryIntervalMs) {
|
|
641
|
+
mgr.logger?.log?.(`[RECOVERY] Cooldown active (${elapsed}ms/${retryIntervalMs}ms). Skipping retry.`, 'debug');
|
|
642
|
+
return false;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
state.inFlight = true;
|
|
646
|
+
state.attemptCount += 1;
|
|
647
|
+
state.lastAttemptAt = now;
|
|
648
|
+
mgr._recoveryAttempted = true;
|
|
649
|
+
mgr.logger?.log?.(`[RECOVERY] ${violationType} - attempting state recovery (attempt ${state.attemptCount}${hasAttemptLimit ? `/${maxAttemptsRaw}` : ''})...`, 'warn');
|
|
650
|
+
try {
|
|
651
|
+
const validation = await this._performStateRecovery(mgr);
|
|
652
|
+
if (validation.isValid) {
|
|
653
|
+
mgr.logger?.log?.('[RECOVERY] State recovery succeeded', 'info');
|
|
654
|
+
state.structuralResyncRequested = false;
|
|
655
|
+
// NOTE: Do NOT reset attemptCount here. The fund invariant check will
|
|
656
|
+
// run again after recovery returns. If the invariant is still violated,
|
|
657
|
+
// we want the counter to increment properly (2/5, 3/5, etc.) rather
|
|
658
|
+
// than resetting to 1/5 each time. The decay logic (line ~402) will
|
|
659
|
+
// reset the counter if enough time passes without violations.
|
|
660
|
+
return true;
|
|
661
|
+
}
|
|
662
|
+
state.lastFailureAt = Date.now();
|
|
663
|
+
if (validation.structuralGridResyncRequired && typeof mgr.requestStructuralGridResync === 'function') {
|
|
664
|
+
const unmatchedCount = Array.isArray(validation.unmatchedChainOrders)
|
|
665
|
+
? validation.unmatchedChainOrders.length
|
|
666
|
+
: 0;
|
|
667
|
+
if (!state.structuralResyncRequested) {
|
|
668
|
+
state.structuralResyncRequested = true;
|
|
669
|
+
mgr.logger?.log?.(`[RECOVERY] Structural drift detected (${unmatchedCount} unmatched chain order(s)); scheduling full grid resync.`, 'warn');
|
|
670
|
+
Promise.resolve()
|
|
671
|
+
.then(async () => {
|
|
672
|
+
const scheduleResult = await mgr.requestStructuralGridResync('fund invariant structural drift', {
|
|
673
|
+
unmatchedChainOrders: validation.unmatchedChainOrders || [],
|
|
674
|
+
source: 'fund-invariant-recovery'
|
|
675
|
+
});
|
|
676
|
+
if (scheduleResult?.skipped) {
|
|
677
|
+
state.structuralResyncRequested = false;
|
|
678
|
+
mgr.logger?.log?.(`[RECOVERY] Structural grid resync not scheduled: ${scheduleResult.reason || 'request skipped'}`, 'warn');
|
|
679
|
+
}
|
|
680
|
+
})
|
|
681
|
+
.catch(err => {
|
|
682
|
+
state.structuralResyncRequested = false;
|
|
683
|
+
mgr.logger?.log?.(`[RECOVERY] Structural grid resync scheduling failed: ${err.message}`, 'error');
|
|
684
|
+
});
|
|
685
|
+
}
|
|
686
|
+
else {
|
|
687
|
+
this._logThrottled('structural-resync-already-requested', '[RECOVERY] Structural grid resync already scheduled; suppressing duplicate request.', 'warn');
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
mgr.logger?.log?.(`[RECOVERY] State recovery failed: ${validation.reason}`, 'error');
|
|
691
|
+
return false;
|
|
692
|
+
}
|
|
693
|
+
catch (err) {
|
|
694
|
+
state.lastFailureAt = Date.now();
|
|
695
|
+
mgr.logger?.log?.(`[RECOVERY] State recovery error: ${err.message}`, 'error');
|
|
696
|
+
return false;
|
|
697
|
+
}
|
|
698
|
+
finally {
|
|
699
|
+
state.inFlight = false;
|
|
700
|
+
mgr._recoveryAttempted = false;
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
/**
|
|
704
|
+
* Reset the recovery attempt flag.
|
|
705
|
+
* Called at the start of each fill processing cycle to allow fresh recovery attempts.
|
|
706
|
+
* @returns {void}
|
|
707
|
+
*/
|
|
708
|
+
resetRecoveryState() {
|
|
709
|
+
if (!this.manager)
|
|
710
|
+
return;
|
|
711
|
+
this.manager._recoveryAttempted = false;
|
|
712
|
+
this.manager._recoveryState = {
|
|
713
|
+
attemptCount: 0,
|
|
714
|
+
lastAttemptAt: 0,
|
|
715
|
+
inFlight: false,
|
|
716
|
+
lastFailureAt: 0,
|
|
717
|
+
structuralResyncRequested: false
|
|
718
|
+
};
|
|
719
|
+
}
|
|
720
|
+
/**
|
|
721
|
+
* Check if sufficient funds exist AND atomically deduct (FREE portion only).
|
|
722
|
+
* PRIVATE: Must be called while holding _fundLock.
|
|
723
|
+
* @param {string} orderType - ORDER_TYPES.BUY or ORDER_TYPES.SELL
|
|
724
|
+
* @param {number} size - Amount to deduct from chainFree
|
|
725
|
+
* @param {string} [operation='move'] - Label for logging
|
|
726
|
+
* @returns {Promise<boolean>} true if deduction succeeded, false if insufficient funds
|
|
727
|
+
*/
|
|
728
|
+
async tryDeductFromChainFree(orderType, size, operation = 'move') {
|
|
729
|
+
const mgr = this.manager;
|
|
730
|
+
const isBuy = orderType === ORDER_TYPES.BUY;
|
|
731
|
+
const key = isBuy ? 'buyFree' : 'sellFree';
|
|
732
|
+
if (!mgr.accountTotals || mgr.accountTotals[key] === undefined)
|
|
733
|
+
return false;
|
|
734
|
+
const current = toFiniteNumber(mgr.accountTotals[key]);
|
|
735
|
+
if (current < size) {
|
|
736
|
+
mgr.logger.log(`[chainFree] ${orderType} ${operation}: INSUFFICIENT FUNDS (have ${Format.formatAmount8(current)}, need ${Format.formatAmount8(size)})`, 'warn');
|
|
737
|
+
return false;
|
|
738
|
+
}
|
|
739
|
+
const oldValue = mgr.accountTotals[key];
|
|
740
|
+
mgr.accountTotals[key] = Math.max(0, current - size);
|
|
741
|
+
if (mgr.logger && mgr.logger.level === 'debug') {
|
|
742
|
+
mgr.logger.log(`[ACCOUNTING] ${key} -${Format.formatAmount8(size)} (${operation}) -> ${Format.formatAmount8(mgr.accountTotals[key])} (was ${Format.formatAmount8(oldValue)})`, 'debug');
|
|
743
|
+
}
|
|
744
|
+
return true;
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
747
|
+
* Add an amount back to the optimistic chainFree balance (FREE portion only).
|
|
748
|
+
* PRIVATE: Must be called while holding _fundLock.
|
|
749
|
+
* @param {string} orderType - ORDER_TYPES.BUY or ORDER_TYPES.SELL
|
|
750
|
+
* @param {number} size - Amount to add to chainFree
|
|
751
|
+
* @param {string} [operation='release'] - Label for logging
|
|
752
|
+
* @returns {Promise<boolean>} true if addition succeeded
|
|
753
|
+
*/
|
|
754
|
+
async addToChainFree(orderType, size, operation = 'release') {
|
|
755
|
+
const mgr = this.manager;
|
|
756
|
+
const isBuy = orderType === ORDER_TYPES.BUY;
|
|
757
|
+
const key = isBuy ? 'buyFree' : 'sellFree';
|
|
758
|
+
if (!mgr.accountTotals || mgr.accountTotals[key] === undefined)
|
|
759
|
+
return false;
|
|
760
|
+
const oldFree = toFiniteNumber(mgr.accountTotals[key]);
|
|
761
|
+
mgr.accountTotals[key] = oldFree + size;
|
|
762
|
+
if (mgr.logger && mgr.logger.level === 'debug') {
|
|
763
|
+
mgr.logger.log(`[ACCOUNTING] ${key} +${Format.formatAmount8(size)} (${operation}) -> ${Format.formatAmount8(mgr.accountTotals[key])} (was ${Format.formatAmount8(oldFree)})`, 'debug');
|
|
764
|
+
}
|
|
765
|
+
return true;
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* Record a fill in the optimistic total balances.
|
|
769
|
+
* PUBLIC API: Acquires _fundLock.
|
|
770
|
+
* @param {string} paysAsset - Asset symbol or ID the bot paid
|
|
771
|
+
* @param {number} paysAmount - Amount the bot paid
|
|
772
|
+
* @param {string} receivesAsset - Asset symbol or ID the bot received
|
|
773
|
+
* @param {number} receivesAmount - Amount the bot received
|
|
774
|
+
* @param {string} [context='fill'] - Label for logging
|
|
775
|
+
* @returns {Promise<void>}
|
|
776
|
+
*/
|
|
777
|
+
async recordFillBalances(paysAsset, paysAmount, receivesAsset, receivesAmount, context = 'fill') {
|
|
778
|
+
return await this.manager._fundLock.acquire(async () => {
|
|
779
|
+
const mgr = this.manager;
|
|
780
|
+
const assetA = mgr.config.assetA;
|
|
781
|
+
const assetB = mgr.config.assetB;
|
|
782
|
+
// Determine orientation
|
|
783
|
+
if (paysAsset === assetA) {
|
|
784
|
+
// Bot paid assetA (Selling assetA, buying assetB)
|
|
785
|
+
this.adjustTotalBalance(ORDER_TYPES.SELL, -paysAmount, `${context}-pays`);
|
|
786
|
+
this.adjustTotalBalance(ORDER_TYPES.BUY, receivesAmount, `${context}-receives`);
|
|
787
|
+
}
|
|
788
|
+
else {
|
|
789
|
+
// Bot paid assetB (Buying assetA, selling assetB)
|
|
790
|
+
this.adjustTotalBalance(ORDER_TYPES.BUY, -paysAmount, `${context}-pays`);
|
|
791
|
+
this.adjustTotalBalance(ORDER_TYPES.SELL, receivesAmount, `${context}-receives`);
|
|
792
|
+
}
|
|
793
|
+
});
|
|
794
|
+
}
|
|
795
|
+
/**
|
|
796
|
+
* Adjust both total and free balances (for fills, fees, deposits).
|
|
797
|
+
* @param {string} orderType - ORDER_TYPES.BUY or ORDER_TYPES.SELL
|
|
798
|
+
* @param {number} delta - Amount to adjust
|
|
799
|
+
* @param {string} operation - Context for logging
|
|
800
|
+
* @param {boolean} totalOnly - If true, only adjust TOTAL balance, not FREE portion.
|
|
801
|
+
*/
|
|
802
|
+
adjustTotalBalance(orderType, delta, operation, totalOnly = false) {
|
|
803
|
+
const mgr = this.manager;
|
|
804
|
+
const isBuy = (orderType === ORDER_TYPES.BUY);
|
|
805
|
+
const freeKey = isBuy ? 'buyFree' : 'sellFree';
|
|
806
|
+
const totalKey = isBuy ? 'buy' : 'sell';
|
|
807
|
+
if (!mgr.accountTotals)
|
|
808
|
+
return;
|
|
809
|
+
if (!totalOnly) {
|
|
810
|
+
const oldFree = toFiniteNumber(mgr.accountTotals[freeKey]);
|
|
811
|
+
// IMPORTANT: No clamping to 0 here. Allowing temporary negative Free balance
|
|
812
|
+
// ensures the invariant Total = Free + Committed remains stable during
|
|
813
|
+
// the short race between Fill detection and Order state update.
|
|
814
|
+
mgr.accountTotals[freeKey] = oldFree + delta;
|
|
815
|
+
}
|
|
816
|
+
if (mgr.accountTotals[totalKey] !== undefined && mgr.accountTotals[totalKey] !== null) {
|
|
817
|
+
const oldTotal = toFiniteNumber(mgr.accountTotals[totalKey]);
|
|
818
|
+
mgr.accountTotals[totalKey] = Math.max(0, oldTotal + delta);
|
|
819
|
+
}
|
|
820
|
+
if (mgr.logger && mgr.logger.level === 'debug') {
|
|
821
|
+
const freeMsg = totalOnly ? `Free: (untouched)` : `Free: ${Format.formatAmount8(mgr.accountTotals[freeKey])}`;
|
|
822
|
+
mgr.logger.log(`[ACCOUNTING] ${totalKey} ${delta >= 0 ? '+' : ''}${Format.formatAmount8(delta)} (${operation}) -> Total: ${Format.formatAmount8(mgr.accountTotals[totalKey])}, ${freeMsg}`, 'debug');
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
/**
|
|
826
|
+
* Normalize side hint to standard ORDER_TYPES constant.
|
|
827
|
+
* @param {string|null} sideHint - Side hint ('buy', 'sell', ORDER_TYPES.BUY, ORDER_TYPES.SELL, or null)
|
|
828
|
+
* @returns {string|null} Normalized side or null if unrecognised
|
|
829
|
+
*/
|
|
830
|
+
_normalizeSideHint(sideHint) {
|
|
831
|
+
if (sideHint === ORDER_TYPES.BUY || sideHint === 'buy')
|
|
832
|
+
return ORDER_TYPES.BUY;
|
|
833
|
+
if (sideHint === ORDER_TYPES.SELL || sideHint === 'sell')
|
|
834
|
+
return ORDER_TYPES.SELL;
|
|
835
|
+
return null;
|
|
836
|
+
}
|
|
837
|
+
/**
|
|
838
|
+
* Resolve the effective order side from multiple sources of truth.
|
|
839
|
+
* @param {Object|null} order - Order object carrying optional side hints
|
|
840
|
+
* @param {Object|null} [fallbackOrder] - Fallback order object
|
|
841
|
+
* @param {string|null} [explicitSideHint] - Explicit side override
|
|
842
|
+
* @returns {string|null} Resolved side (ORDER_TYPES.BUY, ORDER_TYPES.SELL) or null
|
|
843
|
+
*/
|
|
844
|
+
_resolveOrderSide(order, fallbackOrder = null, explicitSideHint = null) {
|
|
845
|
+
const fromHint = this._normalizeSideHint(explicitSideHint);
|
|
846
|
+
if (fromHint)
|
|
847
|
+
return fromHint;
|
|
848
|
+
// Prefer explicit order type over carried metadata.
|
|
849
|
+
// committedSide/sideHint can be stale during boundary flips, but type is the
|
|
850
|
+
// authoritative current side for BUY/SELL commitments.
|
|
851
|
+
const fromOrderType = this._normalizeSideHint(order?.type);
|
|
852
|
+
if (fromOrderType)
|
|
853
|
+
return fromOrderType;
|
|
854
|
+
const fromFallbackType = this._normalizeSideHint(fallbackOrder?.type);
|
|
855
|
+
if (fromFallbackType)
|
|
856
|
+
return fromFallbackType;
|
|
857
|
+
const candidates = [
|
|
858
|
+
order?.sideHint,
|
|
859
|
+
order?.committedSide,
|
|
860
|
+
fallbackOrder?.sideHint,
|
|
861
|
+
fallbackOrder?.committedSide
|
|
862
|
+
];
|
|
863
|
+
for (const candidate of candidates) {
|
|
864
|
+
const normalized = this._normalizeSideHint(candidate);
|
|
865
|
+
if (normalized)
|
|
866
|
+
return normalized;
|
|
867
|
+
}
|
|
868
|
+
return null;
|
|
869
|
+
}
|
|
870
|
+
/**
|
|
871
|
+
* Update optimistic balance during transitions.
|
|
872
|
+
* @param {Object} oldOrder - Previous order state
|
|
873
|
+
* @param {Object} newOrder - New order state
|
|
874
|
+
* @param {string} context - Context for logging/tracking
|
|
875
|
+
* @param {number} fee - Blockchain fee to deduct
|
|
876
|
+
* @param {boolean} skipAssetAccounting - If true, skip capital commitment changes (asset amounts) but still process fees
|
|
877
|
+
*/
|
|
878
|
+
async updateOptimisticFreeBalance(oldOrder, newOrder, context, fee = 0, skipAssetAccounting = false) {
|
|
879
|
+
const mgr = this.manager;
|
|
880
|
+
if (!oldOrder || !newOrder)
|
|
881
|
+
return;
|
|
882
|
+
// Ensure a mutable copy: _resolveBtsFeeLifecycle mutates btsFeeState on
|
|
883
|
+
// newOrder (line 230), but the caller may pass a frozen master-grid order.
|
|
884
|
+
if (Object.isFrozen(newOrder)) {
|
|
885
|
+
newOrder = { ...newOrder };
|
|
886
|
+
}
|
|
887
|
+
if (!skipAssetAccounting) {
|
|
888
|
+
const oldIsActive = (oldOrder.state === ORDER_STATES.ACTIVE || oldOrder.state === ORDER_STATES.PARTIAL);
|
|
889
|
+
const newIsActive = (newOrder.state === ORDER_STATES.ACTIVE || newOrder.state === ORDER_STATES.PARTIAL);
|
|
890
|
+
const oldSize = toFiniteNumber(oldOrder.size);
|
|
891
|
+
const newSize = toFiniteNumber(newOrder.size);
|
|
892
|
+
// 1. Handle Capital Commitment (Moves between FREE and LOCKED)
|
|
893
|
+
// For COMMITMENT: Use GRID state (isActive), not blockchain ID
|
|
894
|
+
const oldGridCommitted = oldIsActive ? oldSize : 0;
|
|
895
|
+
const newGridCommitted = newIsActive ? newSize : 0;
|
|
896
|
+
const commitmentDelta = newGridCommitted - oldGridCommitted;
|
|
897
|
+
const newSideType = this._resolveOrderSide(newOrder, oldOrder);
|
|
898
|
+
const oldSideType = this._resolveOrderSide(oldOrder, newOrder);
|
|
899
|
+
const sideForPrecision = newSideType || oldSideType;
|
|
900
|
+
if (mgr.logger && mgr.logger.level === 'debug') {
|
|
901
|
+
mgr.logger.log(`[ACCOUNTING] updateOptimisticFreeBalance: id=${newOrder.id}, type=${newOrder.type}, ` +
|
|
902
|
+
`state=${oldOrder.state}->${newOrder.state}, ` +
|
|
903
|
+
`size=${Format.formatSizeByOrderType(oldSize, sideForPrecision, mgr.assets)}->${Format.formatSizeByOrderType(newSize, sideForPrecision, mgr.assets)}, ` +
|
|
904
|
+
`delta=${Format.formatSizeByOrderType(commitmentDelta, sideForPrecision, mgr.assets)}, context=${context}`, 'debug');
|
|
905
|
+
}
|
|
906
|
+
if (commitmentDelta > 0) {
|
|
907
|
+
// Lock capital: move from Free to Committed
|
|
908
|
+
const commitmentSide = newSideType || newOrder.type;
|
|
909
|
+
const deducted = await this.tryDeductFromChainFree(commitmentSide, commitmentDelta, `${context}`);
|
|
910
|
+
if (!deducted) {
|
|
911
|
+
const failure = {
|
|
912
|
+
code: 'ACCOUNTING_COMMITMENT_FAILED',
|
|
913
|
+
side: commitmentSide,
|
|
914
|
+
amount: commitmentDelta,
|
|
915
|
+
context,
|
|
916
|
+
at: Date.now()
|
|
917
|
+
};
|
|
918
|
+
mgr._lastAccountingFailure = failure;
|
|
919
|
+
mgr.logger?.log?.(`[ACCOUNTING] CRITICAL: Failed to lock ${Format.formatAmount8(commitmentDelta)} for ${commitmentSide} during ${context}. Scheduling recovery.`, 'error');
|
|
920
|
+
if (mgr._throwOnIllegalState) {
|
|
921
|
+
const err = new Error(`CRITICAL ACCOUNTING STATE: failed to lock ${Format.formatAmount8(commitmentDelta)} ${commitmentSide} during ${context}`);
|
|
922
|
+
err.code = 'ACCOUNTING_COMMITMENT_FAILED';
|
|
923
|
+
throw err;
|
|
924
|
+
}
|
|
925
|
+
this._attemptFundRecovery(mgr, 'Optimistic commitment deduction failure').catch(err => {
|
|
926
|
+
mgr.logger?.log?.(`[RECOVERY] Immediate recovery scheduling failed: ${err.message}`, 'error');
|
|
927
|
+
mgr._recoveryState = mgr._recoveryState || {};
|
|
928
|
+
mgr._recoveryState.lastFailureAt = Date.now();
|
|
929
|
+
});
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
else if (commitmentDelta < 0) {
|
|
933
|
+
// Release capital: move from Committed back to Free
|
|
934
|
+
const releaseSide = oldSideType || oldOrder.type;
|
|
935
|
+
await this.addToChainFree(releaseSide, Math.abs(commitmentDelta), `${context}`);
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
// 2. Handle BTS blockchain fee lifecycle.
|
|
939
|
+
// BitShares stores create/update fees as order.deferred_fee and later
|
|
940
|
+
// refunds or charges that deferred fee on fill, update, or cancel.
|
|
941
|
+
const btsOrderType = this._getBtsOrderType();
|
|
942
|
+
if (btsOrderType) {
|
|
943
|
+
const { balanceDelta } = this._resolveBtsFeeLifecycle(oldOrder, newOrder, context, fee);
|
|
944
|
+
if (Math.abs(balanceDelta) > 0) {
|
|
945
|
+
this.adjustTotalBalance(btsOrderType, balanceDelta, `${context}-fee`);
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
/**
|
|
950
|
+
* Deduct BTS fees using adjustTotalBalance.
|
|
951
|
+
*
|
|
952
|
+
* Strategy: Accumulate fees in btsFeesOwed, then settle when sufficient funds available.
|
|
953
|
+
* - Fees are part of chainFree (not separate capital)
|
|
954
|
+
* - Full fee amount must reduce chainFree
|
|
955
|
+
* - Defers settlement if insufficient funds (will retry when funds become available)
|
|
956
|
+
* @param {string|null} [requestedSide=null] - ORDER_TYPES.BUY or ORDER_TYPES.SELL to target a specific side
|
|
957
|
+
* @returns {void}
|
|
958
|
+
*/
|
|
959
|
+
async deductBtsFees(requestedSide = null) {
|
|
960
|
+
const mgr = this.manager;
|
|
961
|
+
// Early returns for no work needed
|
|
962
|
+
if (!mgr.funds || !mgr.funds.btsFeesOwed || mgr.funds.btsFeesOwed <= 0)
|
|
963
|
+
return;
|
|
964
|
+
if (!mgr.accountTotals)
|
|
965
|
+
return;
|
|
966
|
+
const btsSide = (mgr.config.assetA === 'BTS') ? 'sell' : (mgr.config.assetB === 'BTS') ? 'buy' : null;
|
|
967
|
+
const normalizedRequestedSide = (requestedSide === 'buy' || requestedSide === 'sell') ? requestedSide : null;
|
|
968
|
+
let side = btsSide || normalizedRequestedSide;
|
|
969
|
+
if (normalizedRequestedSide && btsSide && normalizedRequestedSide !== btsSide) {
|
|
970
|
+
mgr.logger?.log?.(`[BTS-FEE] Ignoring requested side '${normalizedRequestedSide}' (configured BTS side is '${btsSide}').`, 'warn');
|
|
971
|
+
side = btsSide;
|
|
972
|
+
}
|
|
973
|
+
if (!side)
|
|
974
|
+
return;
|
|
975
|
+
const fees = mgr.funds.btsFeesOwed;
|
|
976
|
+
const orderType = (side === 'buy') ? ORDER_TYPES.BUY : ORDER_TYPES.SELL;
|
|
977
|
+
const freeKey = (side === 'buy') ? 'buyFree' : 'sellFree';
|
|
978
|
+
const chainFree = mgr.accountTotals[freeKey] || 0;
|
|
979
|
+
// SUFFICIENCY CHECK: Defer if insufficient funds
|
|
980
|
+
if (chainFree < fees) {
|
|
981
|
+
if (mgr.logger && mgr.logger.level === 'debug') {
|
|
982
|
+
mgr.logger.log(`[BTS-FEE] Deferring settlement: need ${Format.formatAmount8(fees)}, have ${Format.formatAmount8(chainFree)}`, 'debug');
|
|
983
|
+
}
|
|
984
|
+
return;
|
|
985
|
+
}
|
|
986
|
+
// FULL DEDUCTION from chainFree
|
|
987
|
+
this.adjustTotalBalance(orderType, -fees, 'bts-fee-settlement');
|
|
988
|
+
if (mgr.logger && mgr.logger.level === 'debug') {
|
|
989
|
+
mgr.logger.log(`[BTS-FEE] Settled: ${Format.formatAmount8(fees)} BTS`, 'debug');
|
|
990
|
+
}
|
|
991
|
+
// Reset fees after successful settlement
|
|
992
|
+
mgr.funds.btsFeesOwed = 0;
|
|
993
|
+
// Recalculate funds to update all tracking metrics
|
|
994
|
+
await mgr.recalculateFunds();
|
|
995
|
+
}
|
|
996
|
+
/**
|
|
997
|
+
* Validate that a proposed Target Grid fits within the account's total available funds.
|
|
998
|
+
* Prevents over-commitment before orders are broadcast.
|
|
999
|
+
*
|
|
1000
|
+
* @param {Map} targetGrid - Proposed grid (price -> {size, type})
|
|
1001
|
+
* @returns {Object} { isValid, shortfall, details }
|
|
1002
|
+
*/
|
|
1003
|
+
validateTargetGrid(targetGrid) {
|
|
1004
|
+
if (!targetGrid || typeof targetGrid.values !== 'function') {
|
|
1005
|
+
return { isValid: false, shortfall: { buy: 0, sell: 0 }, details: { error: 'Invalid targetGrid' } };
|
|
1006
|
+
}
|
|
1007
|
+
const mgr = this.manager;
|
|
1008
|
+
let requiredBuy = 0;
|
|
1009
|
+
let requiredSell = 0;
|
|
1010
|
+
// 1. Sum up requirements for the new grid
|
|
1011
|
+
for (const order of targetGrid.values()) {
|
|
1012
|
+
const size = toFiniteNumber(order.size);
|
|
1013
|
+
if (size <= 0)
|
|
1014
|
+
continue;
|
|
1015
|
+
if (order.type === ORDER_TYPES.BUY) {
|
|
1016
|
+
// Buy order uses Asset B (Quote)
|
|
1017
|
+
requiredBuy += size;
|
|
1018
|
+
}
|
|
1019
|
+
else if (order.type === ORDER_TYPES.SELL) {
|
|
1020
|
+
// Sell order uses Asset A (Base)
|
|
1021
|
+
requiredSell += size;
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
// 2. Add Estimated BTS Fees (if BTS is one of the pairs)
|
|
1025
|
+
// Fees reduce the "Free" balance, so they compete with Order Capital
|
|
1026
|
+
const btsSide = (mgr.config.assetA === 'BTS') ? 'sell' : (mgr.config.assetB === 'BTS') ? 'buy' : null;
|
|
1027
|
+
if (btsSide && mgr.funds.btsFeesOwed > 0) {
|
|
1028
|
+
if (btsSide === 'buy')
|
|
1029
|
+
requiredBuy += mgr.funds.btsFeesOwed;
|
|
1030
|
+
else
|
|
1031
|
+
requiredSell += mgr.funds.btsFeesOwed;
|
|
1032
|
+
}
|
|
1033
|
+
// 3. Compare against Total Account Balance (Free + Committed)
|
|
1034
|
+
// Note: We use the *current* totals from the manager, which includes
|
|
1035
|
+
// money locked in current orders. Since the new grid *replaces* the old one,
|
|
1036
|
+
// we can essentially "re-spend" the money from old orders.
|
|
1037
|
+
const totalBuy = (mgr.accountTotals?.buy || 0);
|
|
1038
|
+
const totalSell = (mgr.accountTotals?.sell || 0);
|
|
1039
|
+
// Add slack for precision rounding errors
|
|
1040
|
+
if (mgr.assets?.assetB?.precision === undefined || mgr.assets?.assetA?.precision === undefined) {
|
|
1041
|
+
throw new Error(`CRITICAL: Asset precision unavailable for slack calculation`);
|
|
1042
|
+
}
|
|
1043
|
+
const slackBuy = getPrecisionSlack(mgr.assets?.assetB?.precision);
|
|
1044
|
+
const slackSell = getPrecisionSlack(mgr.assets?.assetA?.precision);
|
|
1045
|
+
const buyShortfall = Math.max(0, requiredBuy - (totalBuy + slackBuy));
|
|
1046
|
+
const sellShortfall = Math.max(0, requiredSell - (totalSell + slackSell));
|
|
1047
|
+
const isValid = buyShortfall === 0 && sellShortfall === 0;
|
|
1048
|
+
if (!isValid) {
|
|
1049
|
+
mgr.logger.log(`[ACCOUNTING] Target Grid validation failed. Shortfall: Buy=${Format.formatAmount8(buyShortfall)}, Sell=${Format.formatAmount8(sellShortfall)}`, 'warn');
|
|
1050
|
+
}
|
|
1051
|
+
return {
|
|
1052
|
+
isValid,
|
|
1053
|
+
shortfall: { buy: buyShortfall, sell: sellShortfall },
|
|
1054
|
+
details: { requiredBuy, requiredSell, totalBuy, totalSell }
|
|
1055
|
+
};
|
|
1056
|
+
}
|
|
1057
|
+
/**
|
|
1058
|
+
* Centralized fee deduction helper - prevents duplicate logic across codebase.
|
|
1059
|
+
* Returns net proceeds after market fees, or raw amount if asset is not recognized.
|
|
1060
|
+
* @param {string} assetSymbol - Asset symbol (e.g., 'BTS', 'XRP')
|
|
1061
|
+
* @param {number} rawAmount - Amount before fees
|
|
1062
|
+
* @param {boolean} isMaker - Whether this was a maker order (lower fee) vs taker (full fee)
|
|
1063
|
+
* @returns {number} Net proceeds after fees, or rawAmount if symbol not found
|
|
1064
|
+
* @private
|
|
1065
|
+
*/
|
|
1066
|
+
_deductFeesFromProceeds(assetSymbol, rawAmount, isMaker) {
|
|
1067
|
+
if (!assetSymbol)
|
|
1068
|
+
return rawAmount;
|
|
1069
|
+
// BTS has no market fee. Deferred order-fee refunds are handled from
|
|
1070
|
+
// fill_order.order_id in processFillAccounting so they are not tied to
|
|
1071
|
+
// whether BTS was the received asset.
|
|
1072
|
+
if (assetSymbol === 'BTS') {
|
|
1073
|
+
return rawAmount;
|
|
1074
|
+
}
|
|
1075
|
+
// For other assets: apply normal fee calculation (market fee %)
|
|
1076
|
+
// Fail-safe: if fee cache is missing/stale, do not crash fill processing.
|
|
1077
|
+
try {
|
|
1078
|
+
const feeInfo = getAssetFees(assetSymbol, rawAmount, isMaker);
|
|
1079
|
+
const netProceeds = toFiniteNumber(feeInfo?.netProceeds, null);
|
|
1080
|
+
if (netProceeds === null) {
|
|
1081
|
+
throw new Error('netProceeds is not finite');
|
|
1082
|
+
}
|
|
1083
|
+
return netProceeds;
|
|
1084
|
+
}
|
|
1085
|
+
catch (err) {
|
|
1086
|
+
this.manager?.logger?.log?.(`[FILL-FEE] Failed to compute fees for ${assetSymbol}: ${err.message}. Using raw proceeds (${Format.formatAmount8(rawAmount)}).`, 'warn');
|
|
1087
|
+
return rawAmount;
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
/**
|
|
1091
|
+
* Process the fund impact of an order fill.
|
|
1092
|
+
* Atomically updates accountTotals to keep internal state in sync with blockchain.
|
|
1093
|
+
* CRITICAL: Called within fill processing lock context to prevent race conditions.
|
|
1094
|
+
* @param {Object} fillOp - Fill operation object from chain history
|
|
1095
|
+
* @param {string} [fillKey=null] - Deduplication key for processed fill store
|
|
1096
|
+
* @param {Object} [options={}] - Persistence mode options
|
|
1097
|
+
* @returns {Promise<boolean>} true if fill was successfully processed
|
|
1098
|
+
*/
|
|
1099
|
+
async processFillAccounting(fillOp, fillKey = null, options = {}) {
|
|
1100
|
+
const mgr = this.manager;
|
|
1101
|
+
// Persistence is durable by default. Callers that process many fills under
|
|
1102
|
+
// the fill lock can opt into deferred persistence and close the window with
|
|
1103
|
+
// one explicit batch flush before leaving the processing cycle.
|
|
1104
|
+
const persistenceMode = resolveProcessedFillPersistenceMode(options);
|
|
1105
|
+
const pays = fillOp?.pays;
|
|
1106
|
+
const receives = fillOp?.receives;
|
|
1107
|
+
if (!pays || !receives)
|
|
1108
|
+
return false;
|
|
1109
|
+
// Default to maker (not taker) because:
|
|
1110
|
+
// 1. This bot primarily places orders (maker orders, not taker)
|
|
1111
|
+
// 2. Maker fees are CHEAPER: 10% of fee vs 100% for taker
|
|
1112
|
+
// 3. When is_maker is missing, it's safer to assume maker (the normal case)
|
|
1113
|
+
// 4. Makers get 90% refund on BTS fees, so we account for that
|
|
1114
|
+
const isMaker = fillOp.is_maker !== false;
|
|
1115
|
+
const assetAId = mgr.assets?.assetA?.id;
|
|
1116
|
+
const assetBId = mgr.assets?.assetB?.id;
|
|
1117
|
+
const assetAPrecision = mgr.assets?.assetA?.precision;
|
|
1118
|
+
const assetBPrecision = mgr.assets?.assetB?.precision;
|
|
1119
|
+
if (assetAPrecision === undefined || assetBPrecision === undefined)
|
|
1120
|
+
return false;
|
|
1121
|
+
// Derive all numeric effects before recording the fill key.
|
|
1122
|
+
// This keeps retries safe if a later computation unexpectedly fails.
|
|
1123
|
+
const balanceAdjustments = [];
|
|
1124
|
+
const assetASymbol = mgr.config?.assetA;
|
|
1125
|
+
const assetBSymbol = mgr.config?.assetB;
|
|
1126
|
+
if (pays.asset_id === assetAId) {
|
|
1127
|
+
const amount = blockchainToFloat(pays.amount, assetAPrecision, true);
|
|
1128
|
+
balanceAdjustments.push({ orderType: ORDER_TYPES.SELL, delta: -amount, operation: 'fill-pays' });
|
|
1129
|
+
}
|
|
1130
|
+
else if (pays.asset_id === assetBId) {
|
|
1131
|
+
const amount = blockchainToFloat(pays.amount, assetBPrecision, true);
|
|
1132
|
+
balanceAdjustments.push({ orderType: ORDER_TYPES.BUY, delta: -amount, operation: 'fill-pays' });
|
|
1133
|
+
}
|
|
1134
|
+
if (receives.asset_id === assetAId) {
|
|
1135
|
+
const rawAmount = blockchainToFloat(receives.amount, assetAPrecision, true);
|
|
1136
|
+
const netAmount = this._deductFeesFromProceeds(assetASymbol, rawAmount, isMaker);
|
|
1137
|
+
balanceAdjustments.push({ orderType: ORDER_TYPES.SELL, delta: netAmount, operation: 'fill-receives' });
|
|
1138
|
+
}
|
|
1139
|
+
else if (receives.asset_id === assetBId) {
|
|
1140
|
+
const rawAmount = blockchainToFloat(receives.amount, assetBPrecision, true);
|
|
1141
|
+
const netAmount = this._deductFeesFromProceeds(assetBSymbol, rawAmount, isMaker);
|
|
1142
|
+
balanceAdjustments.push({ orderType: ORDER_TYPES.BUY, delta: netAmount, operation: 'fill-receives' });
|
|
1143
|
+
}
|
|
1144
|
+
const btsRefundAdjustment = this._buildBtsDeferredRefundAdjustment(fillOp.order_id, isMaker);
|
|
1145
|
+
if (btsRefundAdjustment) {
|
|
1146
|
+
balanceAdjustments.push(btsRefundAdjustment);
|
|
1147
|
+
}
|
|
1148
|
+
let processedAt = null;
|
|
1149
|
+
const tracker = fillKey ? this._getProcessedFillTracker() : null;
|
|
1150
|
+
if (fillKey) {
|
|
1151
|
+
processedAt = Date.now();
|
|
1152
|
+
const lastProcessed = tracker.get(fillKey);
|
|
1153
|
+
if (lastProcessed !== undefined && (processedAt - lastProcessed) < TIMING.FILL_RECORD_RETENTION_MS) {
|
|
1154
|
+
this.manager?.logger?.log(`[FILL-DEDUP] Skipping duplicate credit for fill ${fillKey} (processed ${processedAt - lastProcessed}ms ago)`, 'warn');
|
|
1155
|
+
return false;
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
const processedFillStore = this._getProcessedFillStore();
|
|
1159
|
+
// Record/queue the dedup key before applying balance adjustments. In
|
|
1160
|
+
// immediate mode this is durable before funds move; batched/manual modes
|
|
1161
|
+
// still preserve the existing deferred flush behavior for batch commit.
|
|
1162
|
+
if (fillKey && processedFillStore) {
|
|
1163
|
+
try {
|
|
1164
|
+
await processedFillStore.persist(fillKey, processedAt || Date.now(), { mode: persistenceMode });
|
|
1165
|
+
}
|
|
1166
|
+
catch (err) {
|
|
1167
|
+
if (persistenceMode === PROCESSED_FILL_PERSISTENCE_MODES.IMMEDIATE) {
|
|
1168
|
+
// Clean up any pending write that the flush error handler re-queued.
|
|
1169
|
+
processedFillStore.discard(fillKey, processedAt || Date.now());
|
|
1170
|
+
throw err;
|
|
1171
|
+
}
|
|
1172
|
+
mgr.logger?.log?.(`[FILL-DEDUP] Failed to persist fill ${fillKey}: ${err.message}`, 'warn');
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
this._applyBalanceAdjustments(balanceAdjustments);
|
|
1176
|
+
if (fillKey) {
|
|
1177
|
+
tracker.set(fillKey, processedAt || Date.now());
|
|
1178
|
+
// Prune entries beyond the retention horizon to prevent unbounded growth.
|
|
1179
|
+
if (tracker.size > 500) {
|
|
1180
|
+
const cutoff = (processedAt || Date.now()) - TIMING.FILL_RECORD_RETENTION_MS;
|
|
1181
|
+
for (const [k, ts] of tracker) {
|
|
1182
|
+
if (ts < cutoff)
|
|
1183
|
+
tracker.delete(k);
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
return true;
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
module.exports = Accountant;
|
|
1191
|
+
//# sourceMappingURL=accounting.js.map
|