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.
Files changed (807) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +287 -0
  3. package/claw/README.md +513 -0
  4. package/claw/scripts/memu_runner.py +385 -0
  5. package/claw/skills/bitshares-guide/SKILL.md +14 -0
  6. package/claw/skills/bitshares-guide/references/example-skill-shells.md +18 -0
  7. package/claw/skills/bitshares-guide/references/presentation-patterns.md +19 -0
  8. package/claw/skills/bitshares-guide/references/scope-guardrails.md +9 -0
  9. package/claw/skills/launcher-ops/SKILL.md +18 -0
  10. package/claw/skills/launcher-ops/references/launcher-workflow.md +23 -0
  11. package/claw/skills/margin-trading/SKILL.md +23 -0
  12. package/claw/skills/margin-trading/references/honest-asset-list.md +74 -0
  13. package/claw/skills/margin-trading/references/honest-assets.md +44 -0
  14. package/claw/skills/margin-trading/references/position-management.md +203 -0
  15. package/claw/skills/margin-trading/references/trading-concepts.md +80 -0
  16. package/claw/skills/memu-memory/SKILL.md +218 -0
  17. package/claw/skills/shared/references/js-automation-overview.md +24 -0
  18. package/claw/skills/shared/references/safety-and-staleness.md +11 -0
  19. package/claw/skills/shared/references/skill-boundaries.md +17 -0
  20. package/claw/skills/trend-detection/SKILL.md +33 -0
  21. package/claw/skills/trend-detection/agents/openai.yaml +3 -0
  22. package/claw/skills/trend-detection/references/service.md +45 -0
  23. package/dist/analysis/ama_fitting/analyze_ama_price_changes.d.ts +3 -0
  24. package/dist/analysis/ama_fitting/analyze_ama_price_changes.d.ts.map +1 -0
  25. package/dist/analysis/ama_fitting/analyze_ama_price_changes.js +149 -0
  26. package/dist/analysis/ama_fitting/analyze_ama_price_changes.js.map +1 -0
  27. package/dist/analysis/ama_fitting/analyze_lambda_vs_slow.d.ts +3 -0
  28. package/dist/analysis/ama_fitting/analyze_lambda_vs_slow.d.ts.map +1 -0
  29. package/dist/analysis/ama_fitting/analyze_lambda_vs_slow.js +387 -0
  30. package/dist/analysis/ama_fitting/analyze_lambda_vs_slow.js.map +1 -0
  31. package/dist/analysis/ama_fitting/calibrate_convergence_er.d.ts +3 -0
  32. package/dist/analysis/ama_fitting/calibrate_convergence_er.d.ts.map +1 -0
  33. package/dist/analysis/ama_fitting/calibrate_convergence_er.js +200 -0
  34. package/dist/analysis/ama_fitting/calibrate_convergence_er.js.map +1 -0
  35. package/dist/analysis/ama_fitting/fetch_lp_candles.d.ts +3 -0
  36. package/dist/analysis/ama_fitting/fetch_lp_candles.d.ts.map +1 -0
  37. package/dist/analysis/ama_fitting/fetch_lp_candles.js +212 -0
  38. package/dist/analysis/ama_fitting/fetch_lp_candles.js.map +1 -0
  39. package/dist/analysis/ama_fitting/generate_unified_comparison_chart.d.ts +31 -0
  40. package/dist/analysis/ama_fitting/generate_unified_comparison_chart.d.ts.map +1 -0
  41. package/dist/analysis/ama_fitting/generate_unified_comparison_chart.js +249 -0
  42. package/dist/analysis/ama_fitting/generate_unified_comparison_chart.js.map +1 -0
  43. package/dist/analysis/ama_fitting/optimizer_high_resolution.d.ts +2 -0
  44. package/dist/analysis/ama_fitting/optimizer_high_resolution.d.ts.map +1 -0
  45. package/dist/analysis/ama_fitting/optimizer_high_resolution.js +782 -0
  46. package/dist/analysis/ama_fitting/optimizer_high_resolution.js.map +1 -0
  47. package/dist/analysis/analyze_derivatives.d.ts +95 -0
  48. package/dist/analysis/analyze_derivatives.d.ts.map +1 -0
  49. package/dist/analysis/analyze_derivatives.js +295 -0
  50. package/dist/analysis/analyze_derivatives.js.map +1 -0
  51. package/dist/analysis/analyze_dynamic_weight.d.ts +14 -0
  52. package/dist/analysis/analyze_dynamic_weight.d.ts.map +1 -0
  53. package/dist/analysis/analyze_dynamic_weight.js +208 -0
  54. package/dist/analysis/analyze_dynamic_weight.js.map +1 -0
  55. package/dist/analysis/analyze_kalman.d.ts +13 -0
  56. package/dist/analysis/analyze_kalman.d.ts.map +1 -0
  57. package/dist/analysis/analyze_kalman.js +123 -0
  58. package/dist/analysis/analyze_kalman.js.map +1 -0
  59. package/dist/analysis/analyze_regime.d.ts +20 -0
  60. package/dist/analysis/analyze_regime.d.ts.map +1 -0
  61. package/dist/analysis/analyze_regime.js +139 -0
  62. package/dist/analysis/analyze_regime.js.map +1 -0
  63. package/dist/analysis/analyze_regime_windows.d.ts +19 -0
  64. package/dist/analysis/analyze_regime_windows.d.ts.map +1 -0
  65. package/dist/analysis/analyze_regime_windows.js +413 -0
  66. package/dist/analysis/analyze_regime_windows.js.map +1 -0
  67. package/dist/analysis/analyze_risk_profile.d.ts +3 -0
  68. package/dist/analysis/analyze_risk_profile.d.ts.map +1 -0
  69. package/dist/analysis/analyze_risk_profile.js +159 -0
  70. package/dist/analysis/analyze_risk_profile.js.map +1 -0
  71. package/dist/analysis/analyze_trade_heatmap.d.ts +3 -0
  72. package/dist/analysis/analyze_trade_heatmap.d.ts.map +1 -0
  73. package/dist/analysis/analyze_trade_heatmap.js +367 -0
  74. package/dist/analysis/analyze_trade_heatmap.js.map +1 -0
  75. package/dist/analysis/analyze_volatility.d.ts +22 -0
  76. package/dist/analysis/analyze_volatility.d.ts.map +1 -0
  77. package/dist/analysis/analyze_volatility.js +172 -0
  78. package/dist/analysis/analyze_volatility.js.map +1 -0
  79. package/dist/analysis/bot_fitting/backtest_ama_sweep.d.ts +99 -0
  80. package/dist/analysis/bot_fitting/backtest_ama_sweep.d.ts.map +1 -0
  81. package/dist/analysis/bot_fitting/backtest_ama_sweep.js +804 -0
  82. package/dist/analysis/bot_fitting/backtest_ama_sweep.js.map +1 -0
  83. package/dist/analysis/bot_fitting/backtest_bot_fitting.d.ts +2 -0
  84. package/dist/analysis/bot_fitting/backtest_bot_fitting.d.ts.map +1 -0
  85. package/dist/analysis/bot_fitting/backtest_bot_fitting.js +347 -0
  86. package/dist/analysis/bot_fitting/backtest_bot_fitting.js.map +1 -0
  87. package/dist/analysis/bot_fitting/shared_utils.d.ts +15 -0
  88. package/dist/analysis/bot_fitting/shared_utils.d.ts.map +1 -0
  89. package/dist/analysis/bot_fitting/shared_utils.js +48 -0
  90. package/dist/analysis/bot_fitting/shared_utils.js.map +1 -0
  91. package/dist/analysis/bot_key_utils.d.ts +16 -0
  92. package/dist/analysis/bot_key_utils.d.ts.map +1 -0
  93. package/dist/analysis/bot_key_utils.js +61 -0
  94. package/dist/analysis/bot_key_utils.js.map +1 -0
  95. package/dist/analysis/bot_usage/discover_bot_accounts.d.ts +3 -0
  96. package/dist/analysis/bot_usage/discover_bot_accounts.d.ts.map +1 -0
  97. package/dist/analysis/bot_usage/discover_bot_accounts.js +498 -0
  98. package/dist/analysis/bot_usage/discover_bot_accounts.js.map +1 -0
  99. package/dist/analysis/bot_usage/kibana_bot_queries.d.ts +546 -0
  100. package/dist/analysis/bot_usage/kibana_bot_queries.d.ts.map +1 -0
  101. package/dist/analysis/bot_usage/kibana_bot_queries.js +427 -0
  102. package/dist/analysis/bot_usage/kibana_bot_queries.js.map +1 -0
  103. package/dist/analysis/chart_utils.d.ts +13 -0
  104. package/dist/analysis/chart_utils.d.ts.map +1 -0
  105. package/dist/analysis/chart_utils.js +142 -0
  106. package/dist/analysis/chart_utils.js.map +1 -0
  107. package/dist/analysis/derivative_chart_generator.d.ts +18 -0
  108. package/dist/analysis/derivative_chart_generator.d.ts.map +1 -0
  109. package/dist/analysis/derivative_chart_generator.js +896 -0
  110. package/dist/analysis/derivative_chart_generator.js.map +1 -0
  111. package/dist/analysis/math_utils.d.ts +35 -0
  112. package/dist/analysis/math_utils.d.ts.map +1 -0
  113. package/dist/analysis/math_utils.js +121 -0
  114. package/dist/analysis/math_utils.js.map +1 -0
  115. package/dist/analysis/price_sources.d.ts +34 -0
  116. package/dist/analysis/price_sources.d.ts.map +1 -0
  117. package/dist/analysis/price_sources.js +103 -0
  118. package/dist/analysis/price_sources.js.map +1 -0
  119. package/dist/analysis/trade_profitability.d.ts +115 -0
  120. package/dist/analysis/trade_profitability.d.ts.map +1 -0
  121. package/dist/analysis/trade_profitability.js +1247 -0
  122. package/dist/analysis/trade_profitability.js.map +1 -0
  123. package/dist/analysis/tradingview/analyze_tradingview.d.ts +38 -0
  124. package/dist/analysis/tradingview/analyze_tradingview.d.ts.map +1 -0
  125. package/dist/analysis/tradingview/analyze_tradingview.js +212 -0
  126. package/dist/analysis/tradingview/analyze_tradingview.js.map +1 -0
  127. package/dist/analysis/tradingview/tradingview_uplot_chart_generator.d.ts +9 -0
  128. package/dist/analysis/tradingview/tradingview_uplot_chart_generator.d.ts.map +1 -0
  129. package/dist/analysis/tradingview/tradingview_uplot_chart_generator.js +1717 -0
  130. package/dist/analysis/tradingview/tradingview_uplot_chart_generator.js.map +1 -0
  131. package/dist/analysis/trend_detection/derivative_analyzer.d.ts +250 -0
  132. package/dist/analysis/trend_detection/derivative_analyzer.d.ts.map +1 -0
  133. package/dist/analysis/trend_detection/derivative_analyzer.js +903 -0
  134. package/dist/analysis/trend_detection/derivative_analyzer.js.map +1 -0
  135. package/dist/analysis/trend_detection/dynamic_weight_chart_generator.d.ts +6 -0
  136. package/dist/analysis/trend_detection/dynamic_weight_chart_generator.d.ts.map +1 -0
  137. package/dist/analysis/trend_detection/dynamic_weight_chart_generator.js +1449 -0
  138. package/dist/analysis/trend_detection/dynamic_weight_chart_generator.js.map +1 -0
  139. package/dist/analysis/trend_detection/hurst_analyzer.d.ts +42 -0
  140. package/dist/analysis/trend_detection/hurst_analyzer.d.ts.map +1 -0
  141. package/dist/analysis/trend_detection/hurst_analyzer.js +159 -0
  142. package/dist/analysis/trend_detection/hurst_analyzer.js.map +1 -0
  143. package/dist/analysis/trend_detection/kalman_chart_generator.d.ts +6 -0
  144. package/dist/analysis/trend_detection/kalman_chart_generator.d.ts.map +1 -0
  145. package/dist/analysis/trend_detection/kalman_chart_generator.js +408 -0
  146. package/dist/analysis/trend_detection/kalman_chart_generator.js.map +1 -0
  147. package/dist/analysis/trend_detection/kalman_trend_analyzer.d.ts +103 -0
  148. package/dist/analysis/trend_detection/kalman_trend_analyzer.d.ts.map +1 -0
  149. package/dist/analysis/trend_detection/kalman_trend_analyzer.js +229 -0
  150. package/dist/analysis/trend_detection/kalman_trend_analyzer.js.map +1 -0
  151. package/dist/analysis/trend_detection/kalman_velocity_smoothing.d.ts +34 -0
  152. package/dist/analysis/trend_detection/kalman_velocity_smoothing.d.ts.map +1 -0
  153. package/dist/analysis/trend_detection/kalman_velocity_smoothing.js +89 -0
  154. package/dist/analysis/trend_detection/kalman_velocity_smoothing.js.map +1 -0
  155. package/dist/analysis/trend_detection/permutation_entropy_analyzer.d.ts +39 -0
  156. package/dist/analysis/trend_detection/permutation_entropy_analyzer.d.ts.map +1 -0
  157. package/dist/analysis/trend_detection/permutation_entropy_analyzer.js +132 -0
  158. package/dist/analysis/trend_detection/permutation_entropy_analyzer.js.map +1 -0
  159. package/dist/analysis/trend_detection/regime_chart_generator.d.ts +6 -0
  160. package/dist/analysis/trend_detection/regime_chart_generator.d.ts.map +1 -0
  161. package/dist/analysis/trend_detection/regime_chart_generator.js +345 -0
  162. package/dist/analysis/trend_detection/regime_chart_generator.js.map +1 -0
  163. package/dist/analysis/trend_detection/tests/test_kalman_trend.d.ts +2 -0
  164. package/dist/analysis/trend_detection/tests/test_kalman_trend.d.ts.map +1 -0
  165. package/dist/analysis/trend_detection/tests/test_kalman_trend.js +130 -0
  166. package/dist/analysis/trend_detection/tests/test_kalman_trend.js.map +1 -0
  167. package/dist/analysis/trend_detection/tests/test_kalman_velocity_smoothing.d.ts +2 -0
  168. package/dist/analysis/trend_detection/tests/test_kalman_velocity_smoothing.d.ts.map +1 -0
  169. package/dist/analysis/trend_detection/tests/test_kalman_velocity_smoothing.js +38 -0
  170. package/dist/analysis/trend_detection/tests/test_kalman_velocity_smoothing.js.map +1 -0
  171. package/dist/analysis/trend_detection/volatility_chart_generator.d.ts +6 -0
  172. package/dist/analysis/trend_detection/volatility_chart_generator.d.ts.map +1 -0
  173. package/dist/analysis/trend_detection/volatility_chart_generator.js +732 -0
  174. package/dist/analysis/trend_detection/volatility_chart_generator.js.map +1 -0
  175. package/dist/bot.d.ts +49 -0
  176. package/dist/bot.d.ts.map +1 -0
  177. package/dist/bot.js +221 -0
  178. package/dist/bot.js.map +1 -0
  179. package/dist/credential-daemon.d.ts +64 -0
  180. package/dist/credential-daemon.d.ts.map +1 -0
  181. package/dist/credential-daemon.js +987 -0
  182. package/dist/credential-daemon.js.map +1 -0
  183. package/dist/dexbot.d.ts +87 -0
  184. package/dist/dexbot.d.ts.map +1 -0
  185. package/dist/dexbot.js +1222 -0
  186. package/dist/dexbot.js.map +1 -0
  187. package/dist/market_adapter/ama_signal_runner.d.ts +3 -0
  188. package/dist/market_adapter/ama_signal_runner.d.ts.map +1 -0
  189. package/dist/market_adapter/ama_signal_runner.js +175 -0
  190. package/dist/market_adapter/ama_signal_runner.js.map +1 -0
  191. package/dist/market_adapter/candle_utils.d.ts +57 -0
  192. package/dist/market_adapter/candle_utils.d.ts.map +1 -0
  193. package/dist/market_adapter/candle_utils.js +252 -0
  194. package/dist/market_adapter/candle_utils.js.map +1 -0
  195. package/dist/market_adapter/core/asymmetric_bounds.d.ts +20 -0
  196. package/dist/market_adapter/core/asymmetric_bounds.d.ts.map +1 -0
  197. package/dist/market_adapter/core/asymmetric_bounds.js +88 -0
  198. package/dist/market_adapter/core/asymmetric_bounds.js.map +1 -0
  199. package/dist/market_adapter/core/config_normalizers.d.ts +10 -0
  200. package/dist/market_adapter/core/config_normalizers.d.ts.map +1 -0
  201. package/dist/market_adapter/core/config_normalizers.js +24 -0
  202. package/dist/market_adapter/core/config_normalizers.js.map +1 -0
  203. package/dist/market_adapter/core/kibana_candles.d.ts +74 -0
  204. package/dist/market_adapter/core/kibana_candles.d.ts.map +1 -0
  205. package/dist/market_adapter/core/kibana_candles.js +249 -0
  206. package/dist/market_adapter/core/kibana_candles.js.map +1 -0
  207. package/dist/market_adapter/core/kibana_client.d.ts +27 -0
  208. package/dist/market_adapter/core/kibana_client.d.ts.map +1 -0
  209. package/dist/market_adapter/core/kibana_client.js +120 -0
  210. package/dist/market_adapter/core/kibana_client.js.map +1 -0
  211. package/dist/market_adapter/core/kibana_market_candles.d.ts +143 -0
  212. package/dist/market_adapter/core/kibana_market_candles.d.ts.map +1 -0
  213. package/dist/market_adapter/core/kibana_market_candles.js +170 -0
  214. package/dist/market_adapter/core/kibana_market_candles.js.map +1 -0
  215. package/dist/market_adapter/core/market_adapter_service.d.ts +210 -0
  216. package/dist/market_adapter/core/market_adapter_service.d.ts.map +1 -0
  217. package/dist/market_adapter/core/market_adapter_service.js +2328 -0
  218. package/dist/market_adapter/core/market_adapter_service.js.map +1 -0
  219. package/dist/market_adapter/core/strategies/ama.d.ts +2 -0
  220. package/dist/market_adapter/core/strategies/ama.d.ts.map +1 -0
  221. package/dist/market_adapter/core/strategies/ama.js +138 -0
  222. package/dist/market_adapter/core/strategies/ama.js.map +1 -0
  223. package/dist/market_adapter/core/strategies/ama_slope_model.d.ts +50 -0
  224. package/dist/market_adapter/core/strategies/ama_slope_model.d.ts.map +1 -0
  225. package/dist/market_adapter/core/strategies/ama_slope_model.js +143 -0
  226. package/dist/market_adapter/core/strategies/ama_slope_model.js.map +1 -0
  227. package/dist/market_adapter/core/strategies/atr/calculator.d.ts +12 -0
  228. package/dist/market_adapter/core/strategies/atr/calculator.d.ts.map +1 -0
  229. package/dist/market_adapter/core/strategies/atr/calculator.js +47 -0
  230. package/dist/market_adapter/core/strategies/atr/calculator.js.map +1 -0
  231. package/dist/market_adapter/core/strategies/collateral_manager.d.ts +32 -0
  232. package/dist/market_adapter/core/strategies/collateral_manager.d.ts.map +1 -0
  233. package/dist/market_adapter/core/strategies/collateral_manager.js +68 -0
  234. package/dist/market_adapter/core/strategies/collateral_manager.js.map +1 -0
  235. package/dist/market_adapter/core/strategies/regime_gate.d.ts +66 -0
  236. package/dist/market_adapter/core/strategies/regime_gate.d.ts.map +1 -0
  237. package/dist/market_adapter/core/strategies/regime_gate.js +189 -0
  238. package/dist/market_adapter/core/strategies/regime_gate.js.map +1 -0
  239. package/dist/market_adapter/index.d.ts +10 -0
  240. package/dist/market_adapter/index.d.ts.map +1 -0
  241. package/dist/market_adapter/index.js +71 -0
  242. package/dist/market_adapter/index.js.map +1 -0
  243. package/dist/market_adapter/inputs/fetch_cex_synthetic_data.d.ts +3 -0
  244. package/dist/market_adapter/inputs/fetch_cex_synthetic_data.d.ts.map +1 -0
  245. package/dist/market_adapter/inputs/fetch_cex_synthetic_data.js +1165 -0
  246. package/dist/market_adapter/inputs/fetch_cex_synthetic_data.js.map +1 -0
  247. package/dist/market_adapter/inputs/fetch_lp_data.d.ts +54 -0
  248. package/dist/market_adapter/inputs/fetch_lp_data.d.ts.map +1 -0
  249. package/dist/market_adapter/inputs/fetch_lp_data.js +743 -0
  250. package/dist/market_adapter/inputs/fetch_lp_data.js.map +1 -0
  251. package/dist/market_adapter/inputs/kibana_source.d.ts +68 -0
  252. package/dist/market_adapter/inputs/kibana_source.d.ts.map +1 -0
  253. package/dist/market_adapter/inputs/kibana_source.js +143 -0
  254. package/dist/market_adapter/inputs/kibana_source.js.map +1 -0
  255. package/dist/market_adapter/interval_utils.d.ts +6 -0
  256. package/dist/market_adapter/interval_utils.d.ts.map +1 -0
  257. package/dist/market_adapter/interval_utils.js +14 -0
  258. package/dist/market_adapter/interval_utils.js.map +1 -0
  259. package/dist/market_adapter/log_format.d.ts +16 -0
  260. package/dist/market_adapter/log_format.d.ts.map +1 -0
  261. package/dist/market_adapter/log_format.js +72 -0
  262. package/dist/market_adapter/log_format.js.map +1 -0
  263. package/dist/market_adapter/lp_chart_core.d.ts +6 -0
  264. package/dist/market_adapter/lp_chart_core.d.ts.map +1 -0
  265. package/dist/market_adapter/lp_chart_core.js +874 -0
  266. package/dist/market_adapter/lp_chart_core.js.map +1 -0
  267. package/dist/market_adapter/lp_chart_runner.d.ts +135 -0
  268. package/dist/market_adapter/lp_chart_runner.d.ts.map +1 -0
  269. package/dist/market_adapter/lp_chart_runner.js +337 -0
  270. package/dist/market_adapter/lp_chart_runner.js.map +1 -0
  271. package/dist/market_adapter/lp_chart_strategy_loader.d.ts +23 -0
  272. package/dist/market_adapter/lp_chart_strategy_loader.d.ts.map +1 -0
  273. package/dist/market_adapter/lp_chart_strategy_loader.js +169 -0
  274. package/dist/market_adapter/lp_chart_strategy_loader.js.map +1 -0
  275. package/dist/market_adapter/market_adapter.d.ts +133 -0
  276. package/dist/market_adapter/market_adapter.d.ts.map +1 -0
  277. package/dist/market_adapter/market_adapter.js +1331 -0
  278. package/dist/market_adapter/market_adapter.js.map +1 -0
  279. package/dist/market_adapter/merge_lp_data.d.ts +3 -0
  280. package/dist/market_adapter/merge_lp_data.d.ts.map +1 -0
  281. package/dist/market_adapter/merge_lp_data.js +125 -0
  282. package/dist/market_adapter/merge_lp_data.js.map +1 -0
  283. package/dist/market_adapter/test_helpers.d.ts +14 -0
  284. package/dist/market_adapter/test_helpers.d.ts.map +1 -0
  285. package/dist/market_adapter/test_helpers.js +22 -0
  286. package/dist/market_adapter/test_helpers.js.map +1 -0
  287. package/dist/market_adapter/utils/adapter_client.d.ts +20 -0
  288. package/dist/market_adapter/utils/adapter_client.d.ts.map +1 -0
  289. package/dist/market_adapter/utils/adapter_client.js +88 -0
  290. package/dist/market_adapter/utils/adapter_client.js.map +1 -0
  291. package/dist/market_adapter/utils/atomic_write.d.ts +9 -0
  292. package/dist/market_adapter/utils/atomic_write.d.ts.map +1 -0
  293. package/dist/market_adapter/utils/atomic_write.js +13 -0
  294. package/dist/market_adapter/utils/atomic_write.js.map +1 -0
  295. package/dist/market_adapter/utils/chain.d.ts +50 -0
  296. package/dist/market_adapter/utils/chain.d.ts.map +1 -0
  297. package/dist/market_adapter/utils/chain.js +196 -0
  298. package/dist/market_adapter/utils/chain.js.map +1 -0
  299. package/dist/market_adapter/utils/data_discovery.d.ts +6 -0
  300. package/dist/market_adapter/utils/data_discovery.d.ts.map +1 -0
  301. package/dist/market_adapter/utils/data_discovery.js +35 -0
  302. package/dist/market_adapter/utils/data_discovery.js.map +1 -0
  303. package/dist/market_adapter/utils/dynamic_grid_snapshot.d.ts +15 -0
  304. package/dist/market_adapter/utils/dynamic_grid_snapshot.d.ts.map +1 -0
  305. package/dist/market_adapter/utils/dynamic_grid_snapshot.js +60 -0
  306. package/dist/market_adapter/utils/dynamic_grid_snapshot.js.map +1 -0
  307. package/dist/market_adapter/utils/file_lock.d.ts +19 -0
  308. package/dist/market_adapter/utils/file_lock.d.ts.map +1 -0
  309. package/dist/market_adapter/utils/file_lock.js +191 -0
  310. package/dist/market_adapter/utils/file_lock.js.map +1 -0
  311. package/dist/market_adapter/utils/native_history.d.ts +19 -0
  312. package/dist/market_adapter/utils/native_history.d.ts.map +1 -0
  313. package/dist/market_adapter/utils/native_history.js +172 -0
  314. package/dist/market_adapter/utils/native_history.js.map +1 -0
  315. package/dist/market_adapter/utils/paths.d.ts +5 -0
  316. package/dist/market_adapter/utils/paths.d.ts.map +1 -0
  317. package/dist/market_adapter/utils/paths.js +7 -0
  318. package/dist/market_adapter/utils/paths.js.map +1 -0
  319. package/dist/modules/account_bots.d.ts +112 -0
  320. package/dist/modules/account_bots.d.ts.map +1 -0
  321. package/dist/modules/account_bots.js +1259 -0
  322. package/dist/modules/account_bots.js.map +1 -0
  323. package/dist/modules/account_orders.d.ts +273 -0
  324. package/dist/modules/account_orders.d.ts.map +1 -0
  325. package/dist/modules/account_orders.js +662 -0
  326. package/dist/modules/account_orders.js.map +1 -0
  327. package/dist/modules/authority_resolver.d.ts +2 -0
  328. package/dist/modules/authority_resolver.d.ts.map +1 -0
  329. package/dist/modules/authority_resolver.js +231 -0
  330. package/dist/modules/authority_resolver.js.map +1 -0
  331. package/dist/modules/bitshares-native/chain_client.d.ts +38 -0
  332. package/dist/modules/bitshares-native/chain_client.d.ts.map +1 -0
  333. package/dist/modules/bitshares-native/chain_client.js +322 -0
  334. package/dist/modules/bitshares-native/chain_client.js.map +1 -0
  335. package/dist/modules/bitshares-native/crypto/ecc.browser.d.ts +59 -0
  336. package/dist/modules/bitshares-native/crypto/ecc.browser.d.ts.map +1 -0
  337. package/dist/modules/bitshares-native/crypto/ecc.browser.js +456 -0
  338. package/dist/modules/bitshares-native/crypto/ecc.browser.js.map +1 -0
  339. package/dist/modules/bitshares-native/crypto/ecc.d.ts +66 -0
  340. package/dist/modules/bitshares-native/crypto/ecc.d.ts.map +1 -0
  341. package/dist/modules/bitshares-native/crypto/ecc.js +557 -0
  342. package/dist/modules/bitshares-native/crypto/ecc.js.map +1 -0
  343. package/dist/modules/bitshares-native/crypto/ecc_selector.d.ts +2 -0
  344. package/dist/modules/bitshares-native/crypto/ecc_selector.d.ts.map +1 -0
  345. package/dist/modules/bitshares-native/crypto/ecc_selector.js +20 -0
  346. package/dist/modules/bitshares-native/crypto/ecc_selector.js.map +1 -0
  347. package/dist/modules/bitshares-native/index.d.ts +3 -0
  348. package/dist/modules/bitshares-native/index.d.ts.map +1 -0
  349. package/dist/modules/bitshares-native/index.js +32 -0
  350. package/dist/modules/bitshares-native/index.js.map +1 -0
  351. package/dist/modules/bitshares-native/resolvers.d.ts +40 -0
  352. package/dist/modules/bitshares-native/resolvers.d.ts.map +1 -0
  353. package/dist/modules/bitshares-native/resolvers.js +161 -0
  354. package/dist/modules/bitshares-native/resolvers.js.map +1 -0
  355. package/dist/modules/bitshares-native/serial/chain_constants.d.ts +56 -0
  356. package/dist/modules/bitshares-native/serial/chain_constants.d.ts.map +1 -0
  357. package/dist/modules/bitshares-native/serial/chain_constants.js +92 -0
  358. package/dist/modules/bitshares-native/serial/chain_constants.js.map +1 -0
  359. package/dist/modules/bitshares-native/serial/index.d.ts +10 -0
  360. package/dist/modules/bitshares-native/serial/index.d.ts.map +1 -0
  361. package/dist/modules/bitshares-native/serial/index.js +14 -0
  362. package/dist/modules/bitshares-native/serial/index.js.map +1 -0
  363. package/dist/modules/bitshares-native/serial/operations.d.ts +102 -0
  364. package/dist/modules/bitshares-native/serial/operations.d.ts.map +1 -0
  365. package/dist/modules/bitshares-native/serial/operations.js +615 -0
  366. package/dist/modules/bitshares-native/serial/operations.js.map +1 -0
  367. package/dist/modules/bitshares-native/serial/serializer.d.ts +64 -0
  368. package/dist/modules/bitshares-native/serial/serializer.d.ts.map +1 -0
  369. package/dist/modules/bitshares-native/serial/serializer.js +252 -0
  370. package/dist/modules/bitshares-native/serial/serializer.js.map +1 -0
  371. package/dist/modules/bitshares-native/serial/types.d.ts +120 -0
  372. package/dist/modules/bitshares-native/serial/types.d.ts.map +1 -0
  373. package/dist/modules/bitshares-native/serial/types.js +837 -0
  374. package/dist/modules/bitshares-native/serial/types.js.map +1 -0
  375. package/dist/modules/bitshares-native/signing_client.d.ts +6 -0
  376. package/dist/modules/bitshares-native/signing_client.d.ts.map +1 -0
  377. package/dist/modules/bitshares-native/signing_client.js +141 -0
  378. package/dist/modules/bitshares-native/signing_client.js.map +1 -0
  379. package/dist/modules/bitshares-native/subscriptions.d.ts +6 -0
  380. package/dist/modules/bitshares-native/subscriptions.d.ts.map +1 -0
  381. package/dist/modules/bitshares-native/subscriptions.js +865 -0
  382. package/dist/modules/bitshares-native/subscriptions.js.map +1 -0
  383. package/dist/modules/bitshares-native/transport.d.ts +51 -0
  384. package/dist/modules/bitshares-native/transport.d.ts.map +1 -0
  385. package/dist/modules/bitshares-native/transport.js +447 -0
  386. package/dist/modules/bitshares-native/transport.js.map +1 -0
  387. package/dist/modules/bitshares-native/tx/builder.d.ts +30 -0
  388. package/dist/modules/bitshares-native/tx/builder.d.ts.map +1 -0
  389. package/dist/modules/bitshares-native/tx/builder.js +262 -0
  390. package/dist/modules/bitshares-native/tx/builder.js.map +1 -0
  391. package/dist/modules/bitshares_client.d.ts +129 -0
  392. package/dist/modules/bitshares_client.d.ts.map +1 -0
  393. package/dist/modules/bitshares_client.js +627 -0
  394. package/dist/modules/bitshares_client.js.map +1 -0
  395. package/dist/modules/bot_settings.d.ts +33 -0
  396. package/dist/modules/bot_settings.d.ts.map +1 -0
  397. package/dist/modules/bot_settings.js +328 -0
  398. package/dist/modules/bot_settings.js.map +1 -0
  399. package/dist/modules/bots_file_lock.d.ts +88 -0
  400. package/dist/modules/bots_file_lock.d.ts.map +1 -0
  401. package/dist/modules/bots_file_lock.js +161 -0
  402. package/dist/modules/bots_file_lock.js.map +1 -0
  403. package/dist/modules/chain_keys.d.ts +302 -0
  404. package/dist/modules/chain_keys.d.ts.map +1 -0
  405. package/dist/modules/chain_keys.js +1095 -0
  406. package/dist/modules/chain_keys.js.map +1 -0
  407. package/dist/modules/chain_orders.d.ts +423 -0
  408. package/dist/modules/chain_orders.d.ts.map +1 -0
  409. package/dist/modules/chain_orders.js +1201 -0
  410. package/dist/modules/chain_orders.js.map +1 -0
  411. package/dist/modules/cli_whitelist_args.d.ts +6 -0
  412. package/dist/modules/cli_whitelist_args.d.ts.map +1 -0
  413. package/dist/modules/cli_whitelist_args.js +13 -0
  414. package/dist/modules/cli_whitelist_args.js.map +1 -0
  415. package/dist/modules/config.d.ts +57 -0
  416. package/dist/modules/config.d.ts.map +1 -0
  417. package/dist/modules/config.js +107 -0
  418. package/dist/modules/config.js.map +1 -0
  419. package/dist/modules/constants.d.ts +635 -0
  420. package/dist/modules/constants.d.ts.map +1 -0
  421. package/dist/modules/constants.js +1464 -0
  422. package/dist/modules/constants.js.map +1 -0
  423. package/dist/modules/cr_planner.d.ts +51 -0
  424. package/dist/modules/cr_planner.d.ts.map +1 -0
  425. package/dist/modules/cr_planner.js +299 -0
  426. package/dist/modules/cr_planner.js.map +1 -0
  427. package/dist/modules/credential_policy.d.ts +188 -0
  428. package/dist/modules/credential_policy.d.ts.map +1 -0
  429. package/dist/modules/credential_policy.js +1452 -0
  430. package/dist/modules/credential_policy.js.map +1 -0
  431. package/dist/modules/credential_runtime.d.ts +42 -0
  432. package/dist/modules/credential_runtime.d.ts.map +1 -0
  433. package/dist/modules/credential_runtime.js +148 -0
  434. package/dist/modules/credential_runtime.js.map +1 -0
  435. package/dist/modules/credential_session_cache.d.ts +36 -0
  436. package/dist/modules/credential_session_cache.d.ts.map +1 -0
  437. package/dist/modules/credential_session_cache.js +106 -0
  438. package/dist/modules/credential_session_cache.js.map +1 -0
  439. package/dist/modules/credit_runtime.d.ts +412 -0
  440. package/dist/modules/credit_runtime.d.ts.map +1 -0
  441. package/dist/modules/credit_runtime.js +2866 -0
  442. package/dist/modules/credit_runtime.js.map +1 -0
  443. package/dist/modules/crypto/browser_provider.d.ts +15 -0
  444. package/dist/modules/crypto/browser_provider.d.ts.map +1 -0
  445. package/dist/modules/crypto/browser_provider.js +113 -0
  446. package/dist/modules/crypto/browser_provider.js.map +1 -0
  447. package/dist/modules/crypto/index.d.ts +9 -0
  448. package/dist/modules/crypto/index.d.ts.map +1 -0
  449. package/dist/modules/crypto/index.js +44 -0
  450. package/dist/modules/crypto/index.js.map +1 -0
  451. package/dist/modules/crypto/node_provider.d.ts +15 -0
  452. package/dist/modules/crypto/node_provider.d.ts.map +1 -0
  453. package/dist/modules/crypto/node_provider.js +74 -0
  454. package/dist/modules/crypto/node_provider.js.map +1 -0
  455. package/dist/modules/crypto/provider.d.ts +34 -0
  456. package/dist/modules/crypto/provider.d.ts.map +1 -0
  457. package/dist/modules/crypto/provider.js +3 -0
  458. package/dist/modules/crypto/provider.js.map +1 -0
  459. package/dist/modules/crypto/pure_ripemd160.d.ts +8 -0
  460. package/dist/modules/crypto/pure_ripemd160.d.ts.map +1 -0
  461. package/dist/modules/crypto/pure_ripemd160.js +142 -0
  462. package/dist/modules/crypto/pure_ripemd160.js.map +1 -0
  463. package/dist/modules/crypto/pure_scrypt.d.ts +23 -0
  464. package/dist/modules/crypto/pure_scrypt.d.ts.map +1 -0
  465. package/dist/modules/crypto/pure_scrypt.js +161 -0
  466. package/dist/modules/crypto/pure_scrypt.js.map +1 -0
  467. package/dist/modules/crypto/pure_secp256k1.d.ts +29 -0
  468. package/dist/modules/crypto/pure_secp256k1.d.ts.map +1 -0
  469. package/dist/modules/crypto/pure_secp256k1.js +195 -0
  470. package/dist/modules/crypto/pure_secp256k1.js.map +1 -0
  471. package/dist/modules/crypto/sync.d.ts +13 -0
  472. package/dist/modules/crypto/sync.d.ts.map +1 -0
  473. package/dist/modules/crypto/sync.js +37 -0
  474. package/dist/modules/crypto/sync.js.map +1 -0
  475. package/dist/modules/dexbot_class.d.ts +1074 -0
  476. package/dist/modules/dexbot_class.d.ts.map +1 -0
  477. package/dist/modules/dexbot_class.js +4613 -0
  478. package/dist/modules/dexbot_class.js.map +1 -0
  479. package/dist/modules/dexbot_credential_client.d.ts +71 -0
  480. package/dist/modules/dexbot_credential_client.d.ts.map +1 -0
  481. package/dist/modules/dexbot_credential_client.js +224 -0
  482. package/dist/modules/dexbot_credential_client.js.map +1 -0
  483. package/dist/modules/dexbot_fill_runtime.d.ts +173 -0
  484. package/dist/modules/dexbot_fill_runtime.d.ts.map +1 -0
  485. package/dist/modules/dexbot_fill_runtime.js +217 -0
  486. package/dist/modules/dexbot_fill_runtime.js.map +1 -0
  487. package/dist/modules/dexbot_maintenance_runtime.d.ts +279 -0
  488. package/dist/modules/dexbot_maintenance_runtime.d.ts.map +1 -0
  489. package/dist/modules/dexbot_maintenance_runtime.js +1613 -0
  490. package/dist/modules/dexbot_maintenance_runtime.js.map +1 -0
  491. package/dist/modules/env.d.ts +12 -0
  492. package/dist/modules/env.d.ts.map +1 -0
  493. package/dist/modules/env.js +57 -0
  494. package/dist/modules/env.js.map +1 -0
  495. package/dist/modules/fund_registry.d.ts +96 -0
  496. package/dist/modules/fund_registry.d.ts.map +1 -0
  497. package/dist/modules/fund_registry.js +261 -0
  498. package/dist/modules/fund_registry.js.map +1 -0
  499. package/dist/modules/general_settings.d.ts +36 -0
  500. package/dist/modules/general_settings.d.ts.map +1 -0
  501. package/dist/modules/general_settings.js +63 -0
  502. package/dist/modules/general_settings.js.map +1 -0
  503. package/dist/modules/graceful_shutdown.d.ts +86 -0
  504. package/dist/modules/graceful_shutdown.d.ts.map +1 -0
  505. package/dist/modules/graceful_shutdown.js +164 -0
  506. package/dist/modules/graceful_shutdown.js.map +1 -0
  507. package/dist/modules/key_store.d.ts +60 -0
  508. package/dist/modules/key_store.d.ts.map +1 -0
  509. package/dist/modules/key_store.js +215 -0
  510. package/dist/modules/key_store.js.map +1 -0
  511. package/dist/modules/launcher/bot_supervisor.d.ts +84 -0
  512. package/dist/modules/launcher/bot_supervisor.d.ts.map +1 -0
  513. package/dist/modules/launcher/bot_supervisor.js +1067 -0
  514. package/dist/modules/launcher/bot_supervisor.js.map +1 -0
  515. package/dist/modules/launcher/child_env.d.ts +9 -0
  516. package/dist/modules/launcher/child_env.d.ts.map +1 -0
  517. package/dist/modules/launcher/child_env.js +78 -0
  518. package/dist/modules/launcher/child_env.js.map +1 -0
  519. package/dist/modules/launcher/credential_bootstrap.d.ts +22 -0
  520. package/dist/modules/launcher/credential_bootstrap.d.ts.map +1 -0
  521. package/dist/modules/launcher/credential_bootstrap.js +303 -0
  522. package/dist/modules/launcher/credential_bootstrap.js.map +1 -0
  523. package/dist/modules/launcher/credential_daemon.d.ts +32 -0
  524. package/dist/modules/launcher/credential_daemon.d.ts.map +1 -0
  525. package/dist/modules/launcher/credential_daemon.js +173 -0
  526. package/dist/modules/launcher/credential_daemon.js.map +1 -0
  527. package/dist/modules/launcher/credential_secret.d.ts +6 -0
  528. package/dist/modules/launcher/credential_secret.d.ts.map +1 -0
  529. package/dist/modules/launcher/credential_secret.js +15 -0
  530. package/dist/modules/launcher/credential_secret.js.map +1 -0
  531. package/dist/modules/launcher/foreign_cred_daemon.d.ts +2 -0
  532. package/dist/modules/launcher/foreign_cred_daemon.d.ts.map +1 -0
  533. package/dist/modules/launcher/foreign_cred_daemon.js +166 -0
  534. package/dist/modules/launcher/foreign_cred_daemon.js.map +1 -0
  535. package/dist/modules/launcher/headless_password.d.ts +8 -0
  536. package/dist/modules/launcher/headless_password.d.ts.map +1 -0
  537. package/dist/modules/launcher/headless_password.js +33 -0
  538. package/dist/modules/launcher/headless_password.js.map +1 -0
  539. package/dist/modules/launcher/launch_modes.d.ts +36 -0
  540. package/dist/modules/launcher/launch_modes.d.ts.map +1 -0
  541. package/dist/modules/launcher/launch_modes.js +129 -0
  542. package/dist/modules/launcher/launch_modes.js.map +1 -0
  543. package/dist/modules/launcher/market_adapter_runtime.d.ts +43 -0
  544. package/dist/modules/launcher/market_adapter_runtime.d.ts.map +1 -0
  545. package/dist/modules/launcher/market_adapter_runtime.js +217 -0
  546. package/dist/modules/launcher/market_adapter_runtime.js.map +1 -0
  547. package/dist/modules/launcher/market_adapter_watchdog.d.ts +26 -0
  548. package/dist/modules/launcher/market_adapter_watchdog.d.ts.map +1 -0
  549. package/dist/modules/launcher/market_adapter_watchdog.js +214 -0
  550. package/dist/modules/launcher/market_adapter_watchdog.js.map +1 -0
  551. package/dist/modules/launcher/monolithic_runtime.d.ts +89 -0
  552. package/dist/modules/launcher/monolithic_runtime.d.ts.map +1 -0
  553. package/dist/modules/launcher/monolithic_runtime.js +425 -0
  554. package/dist/modules/launcher/monolithic_runtime.js.map +1 -0
  555. package/dist/modules/launcher/runtime_entry.d.ts +26 -0
  556. package/dist/modules/launcher/runtime_entry.d.ts.map +1 -0
  557. package/dist/modules/launcher/runtime_entry.js +49 -0
  558. package/dist/modules/launcher/runtime_entry.js.map +1 -0
  559. package/dist/modules/launcher/status_reporting.d.ts +48 -0
  560. package/dist/modules/launcher/status_reporting.d.ts.map +1 -0
  561. package/dist/modules/launcher/status_reporting.js +113 -0
  562. package/dist/modules/launcher/status_reporting.js.map +1 -0
  563. package/dist/modules/launcher/supervisor_control.d.ts +6 -0
  564. package/dist/modules/launcher/supervisor_control.d.ts.map +1 -0
  565. package/dist/modules/launcher/supervisor_control.js +59 -0
  566. package/dist/modules/launcher/supervisor_control.js.map +1 -0
  567. package/dist/modules/logger.d.ts +2 -0
  568. package/dist/modules/logger.d.ts.map +1 -0
  569. package/dist/modules/logger.js +71 -0
  570. package/dist/modules/logger.js.map +1 -0
  571. package/dist/modules/market_adapter_whitelist.d.ts +22 -0
  572. package/dist/modules/market_adapter_whitelist.d.ts.map +1 -0
  573. package/dist/modules/market_adapter_whitelist.js +82 -0
  574. package/dist/modules/market_adapter_whitelist.js.map +1 -0
  575. package/dist/modules/node_health_cache.d.ts +55 -0
  576. package/dist/modules/node_health_cache.d.ts.map +1 -0
  577. package/dist/modules/node_health_cache.js +134 -0
  578. package/dist/modules/node_health_cache.js.map +1 -0
  579. package/dist/modules/node_manager.d.ts +215 -0
  580. package/dist/modules/node_manager.d.ts.map +1 -0
  581. package/dist/modules/node_manager.js +628 -0
  582. package/dist/modules/node_manager.js.map +1 -0
  583. package/dist/modules/order/accounting.d.ts +349 -0
  584. package/dist/modules/order/accounting.d.ts.map +1 -0
  585. package/dist/modules/order/accounting.js +1191 -0
  586. package/dist/modules/order/accounting.js.map +1 -0
  587. package/dist/modules/order/async_lock.d.ts +126 -0
  588. package/dist/modules/order/async_lock.d.ts.map +1 -0
  589. package/dist/modules/order/async_lock.js +195 -0
  590. package/dist/modules/order/async_lock.js.map +1 -0
  591. package/dist/modules/order/export.d.ts +129 -0
  592. package/dist/modules/order/export.d.ts.map +1 -0
  593. package/dist/modules/order/export.js +316 -0
  594. package/dist/modules/order/export.js.map +1 -0
  595. package/dist/modules/order/format.d.ts +158 -0
  596. package/dist/modules/order/format.d.ts.map +1 -0
  597. package/dist/modules/order/format.js +232 -0
  598. package/dist/modules/order/format.js.map +1 -0
  599. package/dist/modules/order/grid.d.ts +549 -0
  600. package/dist/modules/order/grid.d.ts.map +1 -0
  601. package/dist/modules/order/grid.js +1746 -0
  602. package/dist/modules/order/grid.js.map +1 -0
  603. package/dist/modules/order/grid_reconcile.d.ts +154 -0
  604. package/dist/modules/order/grid_reconcile.d.ts.map +1 -0
  605. package/dist/modules/order/grid_reconcile.js +1192 -0
  606. package/dist/modules/order/grid_reconcile.js.map +1 -0
  607. package/dist/modules/order/index.d.ts +55 -0
  608. package/dist/modules/order/index.d.ts.map +1 -0
  609. package/dist/modules/order/index.js +79 -0
  610. package/dist/modules/order/index.js.map +1 -0
  611. package/dist/modules/order/logger.d.ts +136 -0
  612. package/dist/modules/order/logger.d.ts.map +1 -0
  613. package/dist/modules/order/logger.js +614 -0
  614. package/dist/modules/order/logger.js.map +1 -0
  615. package/dist/modules/order/logger_state.d.ts +133 -0
  616. package/dist/modules/order/logger_state.d.ts.map +1 -0
  617. package/dist/modules/order/logger_state.js +170 -0
  618. package/dist/modules/order/logger_state.js.map +1 -0
  619. package/dist/modules/order/manager.d.ts +413 -0
  620. package/dist/modules/order/manager.d.ts.map +1 -0
  621. package/dist/modules/order/manager.js +1605 -0
  622. package/dist/modules/order/manager.js.map +1 -0
  623. package/dist/modules/order/processed_fill_store.d.ts +135 -0
  624. package/dist/modules/order/processed_fill_store.d.ts.map +1 -0
  625. package/dist/modules/order/processed_fill_store.js +288 -0
  626. package/dist/modules/order/processed_fill_store.js.map +1 -0
  627. package/dist/modules/order/runner.d.ts +70 -0
  628. package/dist/modules/order/runner.d.ts.map +1 -0
  629. package/dist/modules/order/runner.js +140 -0
  630. package/dist/modules/order/runner.js.map +1 -0
  631. package/dist/modules/order/strategy.d.ts +196 -0
  632. package/dist/modules/order/strategy.d.ts.map +1 -0
  633. package/dist/modules/order/strategy.js +398 -0
  634. package/dist/modules/order/strategy.js.map +1 -0
  635. package/dist/modules/order/sync_engine.d.ts +386 -0
  636. package/dist/modules/order/sync_engine.d.ts.map +1 -0
  637. package/dist/modules/order/sync_engine.js +1459 -0
  638. package/dist/modules/order/sync_engine.js.map +1 -0
  639. package/dist/modules/order/utils/math.d.ts +677 -0
  640. package/dist/modules/order/utils/math.d.ts.map +1 -0
  641. package/dist/modules/order/utils/math.js +1172 -0
  642. package/dist/modules/order/utils/math.js.map +1 -0
  643. package/dist/modules/order/utils/order.d.ts +572 -0
  644. package/dist/modules/order/utils/order.d.ts.map +1 -0
  645. package/dist/modules/order/utils/order.js +1145 -0
  646. package/dist/modules/order/utils/order.js.map +1 -0
  647. package/dist/modules/order/utils/system.d.ts +268 -0
  648. package/dist/modules/order/utils/system.d.ts.map +1 -0
  649. package/dist/modules/order/utils/system.js +1261 -0
  650. package/dist/modules/order/utils/system.js.map +1 -0
  651. package/dist/modules/order/utils/validate.d.ts +280 -0
  652. package/dist/modules/order/utils/validate.d.ts.map +1 -0
  653. package/dist/modules/order/utils/validate.js +918 -0
  654. package/dist/modules/order/utils/validate.js.map +1 -0
  655. package/dist/modules/order/working_grid.d.ts +212 -0
  656. package/dist/modules/order/working_grid.d.ts.map +1 -0
  657. package/dist/modules/order/working_grid.js +279 -0
  658. package/dist/modules/order/working_grid.js.map +1 -0
  659. package/dist/modules/path_api.d.ts +32 -0
  660. package/dist/modules/path_api.d.ts.map +1 -0
  661. package/dist/modules/path_api.js +148 -0
  662. package/dist/modules/path_api.js.map +1 -0
  663. package/dist/modules/paths.d.ts +58 -0
  664. package/dist/modules/paths.d.ts.map +1 -0
  665. package/dist/modules/paths.js +82 -0
  666. package/dist/modules/paths.js.map +1 -0
  667. package/dist/modules/process_discovery.d.ts +58 -0
  668. package/dist/modules/process_discovery.d.ts.map +1 -0
  669. package/dist/modules/process_discovery.js +265 -0
  670. package/dist/modules/process_discovery.js.map +1 -0
  671. package/dist/modules/runtime.d.ts +34 -0
  672. package/dist/modules/runtime.d.ts.map +1 -0
  673. package/dist/modules/runtime.js +98 -0
  674. package/dist/modules/runtime.js.map +1 -0
  675. package/dist/modules/runtime_settings.d.ts +12 -0
  676. package/dist/modules/runtime_settings.d.ts.map +1 -0
  677. package/dist/modules/runtime_settings.js +122 -0
  678. package/dist/modules/runtime_settings.js.map +1 -0
  679. package/dist/modules/settings_merge.d.ts +38 -0
  680. package/dist/modules/settings_merge.d.ts.map +1 -0
  681. package/dist/modules/settings_merge.js +246 -0
  682. package/dist/modules/settings_merge.js.map +1 -0
  683. package/dist/modules/storage/browser_adapter.d.ts +56 -0
  684. package/dist/modules/storage/browser_adapter.d.ts.map +1 -0
  685. package/dist/modules/storage/browser_adapter.js +231 -0
  686. package/dist/modules/storage/browser_adapter.js.map +1 -0
  687. package/dist/modules/storage/index.d.ts +28 -0
  688. package/dist/modules/storage/index.d.ts.map +1 -0
  689. package/dist/modules/storage/index.js +52 -0
  690. package/dist/modules/storage/index.js.map +1 -0
  691. package/dist/modules/storage/node_adapter.d.ts +49 -0
  692. package/dist/modules/storage/node_adapter.d.ts.map +1 -0
  693. package/dist/modules/storage/node_adapter.js +167 -0
  694. package/dist/modules/storage/node_adapter.js.map +1 -0
  695. package/dist/modules/storage/types.d.ts +92 -0
  696. package/dist/modules/storage/types.d.ts.map +1 -0
  697. package/dist/modules/storage/types.js +3 -0
  698. package/dist/modules/storage/types.js.map +1 -0
  699. package/dist/modules/types.d.ts +1382 -0
  700. package/dist/modules/types.d.ts.map +1 -0
  701. package/dist/modules/types.js +11 -0
  702. package/dist/modules/types.js.map +1 -0
  703. package/dist/modules/utils/base58check.d.ts +12 -0
  704. package/dist/modules/utils/base58check.d.ts.map +1 -0
  705. package/dist/modules/utils/base58check.js +112 -0
  706. package/dist/modules/utils/base58check.js.map +1 -0
  707. package/dist/modules/utils/build_dir.d.ts +7 -0
  708. package/dist/modules/utils/build_dir.d.ts.map +1 -0
  709. package/dist/modules/utils/build_dir.js +8 -0
  710. package/dist/modules/utils/build_dir.js.map +1 -0
  711. package/dist/modules/utils/fs_utils.d.ts +25 -0
  712. package/dist/modules/utils/fs_utils.d.ts.map +1 -0
  713. package/dist/modules/utils/fs_utils.js +27 -0
  714. package/dist/modules/utils/fs_utils.js.map +1 -0
  715. package/dist/modules/utils/math_utils.d.ts +10 -0
  716. package/dist/modules/utils/math_utils.d.ts.map +1 -0
  717. package/dist/modules/utils/math_utils.js +17 -0
  718. package/dist/modules/utils/math_utils.js.map +1 -0
  719. package/dist/modules/validate_profiles.d.ts +37 -0
  720. package/dist/modules/validate_profiles.d.ts.map +1 -0
  721. package/dist/modules/validate_profiles.js +369 -0
  722. package/dist/modules/validate_profiles.js.map +1 -0
  723. package/dist/pm2.d.ts +167 -0
  724. package/dist/pm2.d.ts.map +1 -0
  725. package/dist/pm2.js +998 -0
  726. package/dist/pm2.js.map +1 -0
  727. package/dist/scripts/analyze-git.d.ts +11 -0
  728. package/dist/scripts/analyze-git.d.ts.map +1 -0
  729. package/dist/scripts/analyze-git.js +851 -0
  730. package/dist/scripts/analyze-git.js.map +1 -0
  731. package/dist/scripts/analyze-orders.d.ts +17 -0
  732. package/dist/scripts/analyze-orders.d.ts.map +1 -0
  733. package/dist/scripts/analyze-orders.js +1568 -0
  734. package/dist/scripts/analyze-orders.js.map +1 -0
  735. package/dist/scripts/diagnose-kibana-candles.d.ts +3 -0
  736. package/dist/scripts/diagnose-kibana-candles.d.ts.map +1 -0
  737. package/dist/scripts/diagnose-kibana-candles.js +82 -0
  738. package/dist/scripts/diagnose-kibana-candles.js.map +1 -0
  739. package/dist/scripts/diagnose-pool-history.d.ts +3 -0
  740. package/dist/scripts/diagnose-pool-history.d.ts.map +1 -0
  741. package/dist/scripts/diagnose-pool-history.js +296 -0
  742. package/dist/scripts/diagnose-pool-history.js.map +1 -0
  743. package/dist/scripts/divergence-calc.d.ts +26 -0
  744. package/dist/scripts/divergence-calc.d.ts.map +1 -0
  745. package/dist/scripts/divergence-calc.js +119 -0
  746. package/dist/scripts/divergence-calc.js.map +1 -0
  747. package/dist/scripts/generate_lp_chart.d.ts +31 -0
  748. package/dist/scripts/generate_lp_chart.d.ts.map +1 -0
  749. package/dist/scripts/generate_lp_chart.js +92 -0
  750. package/dist/scripts/generate_lp_chart.js.map +1 -0
  751. package/dist/scripts/generate_mainnet_corpus_report.d.ts +24 -0
  752. package/dist/scripts/generate_mainnet_corpus_report.d.ts.map +1 -0
  753. package/dist/scripts/generate_mainnet_corpus_report.js +237 -0
  754. package/dist/scripts/generate_mainnet_corpus_report.js.map +1 -0
  755. package/dist/scripts/generate_market_adapter_whitelist.d.ts +2 -0
  756. package/dist/scripts/generate_market_adapter_whitelist.d.ts.map +1 -0
  757. package/dist/scripts/generate_market_adapter_whitelist.js +111 -0
  758. package/dist/scripts/generate_market_adapter_whitelist.js.map +1 -0
  759. package/dist/scripts/migrate_bot_keys.d.ts +6 -0
  760. package/dist/scripts/migrate_bot_keys.d.ts.map +1 -0
  761. package/dist/scripts/migrate_bot_keys.js +301 -0
  762. package/dist/scripts/migrate_bot_keys.js.map +1 -0
  763. package/dist/scripts/native_release_gates.d.ts +3 -0
  764. package/dist/scripts/native_release_gates.d.ts.map +1 -0
  765. package/dist/scripts/native_release_gates.js +52 -0
  766. package/dist/scripts/native_release_gates.js.map +1 -0
  767. package/dist/scripts/print_grid.d.ts +16 -0
  768. package/dist/scripts/print_grid.d.ts.map +1 -0
  769. package/dist/scripts/print_grid.js +80 -0
  770. package/dist/scripts/print_grid.js.map +1 -0
  771. package/dist/scripts/run-tests.d.ts +2 -0
  772. package/dist/scripts/run-tests.d.ts.map +1 -0
  773. package/dist/scripts/run-tests.js +49 -0
  774. package/dist/scripts/run-tests.js.map +1 -0
  775. package/dist/scripts/sync-version.d.ts +14 -0
  776. package/dist/scripts/sync-version.d.ts.map +1 -0
  777. package/dist/scripts/sync-version.js +158 -0
  778. package/dist/scripts/sync-version.js.map +1 -0
  779. package/dist/scripts/test-credit-renewal.d.ts +2 -0
  780. package/dist/scripts/test-credit-renewal.d.ts.map +1 -0
  781. package/dist/scripts/test-credit-renewal.js +329 -0
  782. package/dist/scripts/test-credit-renewal.js.map +1 -0
  783. package/dist/scripts/update.d.ts +24 -0
  784. package/dist/scripts/update.d.ts.map +1 -0
  785. package/dist/scripts/update.js +650 -0
  786. package/dist/scripts/update.js.map +1 -0
  787. package/dist/scripts/validate_bots.d.ts +16 -0
  788. package/dist/scripts/validate_bots.d.ts.map +1 -0
  789. package/dist/scripts/validate_bots.js +106 -0
  790. package/dist/scripts/validate_bots.js.map +1 -0
  791. package/dist/scripts/verify-browser-bundle.d.ts +22 -0
  792. package/dist/scripts/verify-browser-bundle.d.ts.map +1 -0
  793. package/dist/scripts/verify-browser-bundle.js +339 -0
  794. package/dist/scripts/verify-browser-bundle.js.map +1 -0
  795. package/dist/unlock.d.ts +48 -0
  796. package/dist/unlock.d.ts.map +1 -0
  797. package/dist/unlock.js +925 -0
  798. package/dist/unlock.js.map +1 -0
  799. package/package.json +112 -0
  800. package/scripts/README.md +356 -0
  801. package/scripts/clear-all.sh +195 -0
  802. package/scripts/clear-logs.sh +95 -0
  803. package/scripts/clear-market-adapter.sh +196 -0
  804. package/scripts/clear-orders.sh +113 -0
  805. package/scripts/create-bot-symlinks.sh +51 -0
  806. package/scripts/postinstall.js +9 -0
  807. 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