@reefclaw/openclaw-plugin 0.1.0

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 (371) hide show
  1. package/.gitignore +8 -0
  2. package/audit/mode-transition-audit.d.ts +11 -0
  3. package/audit/mode-transition-audit.js +29 -0
  4. package/balance-utils.d.ts +36 -0
  5. package/balance-utils.js +98 -0
  6. package/bridge/bridge.d.ts +109 -0
  7. package/bridge/bridge.js +1036 -0
  8. package/bridge/config.d.ts +43 -0
  9. package/bridge/config.js +176 -0
  10. package/bridge/connector.d.ts +52 -0
  11. package/bridge/connector.js +293 -0
  12. package/bridge/event-replay-buffer.d.ts +43 -0
  13. package/bridge/event-replay-buffer.js +109 -0
  14. package/bridge/gateway/event-parser.d.ts +209 -0
  15. package/bridge/gateway/event-parser.js +793 -0
  16. package/bridge/gateway/gateway-config.d.ts +39 -0
  17. package/bridge/gateway/gateway-config.js +86 -0
  18. package/bridge/gateway/gateway-http-client.d.ts +50 -0
  19. package/bridge/gateway/gateway-http-client.js +165 -0
  20. package/bridge/gateway/gateway-ws-client.d.ts +116 -0
  21. package/bridge/gateway/gateway-ws-client.js +417 -0
  22. package/bridge/gateway/poller.d.ts +146 -0
  23. package/bridge/gateway/poller.js +505 -0
  24. package/bridge/gateway/tool-discovery.d.ts +25 -0
  25. package/bridge/gateway/tool-discovery.js +198 -0
  26. package/bridge/index.d.ts +2 -0
  27. package/bridge/index.js +253 -0
  28. package/bridge/logger.d.ts +2 -0
  29. package/bridge/logger.js +2 -0
  30. package/bridge/provider.d.ts +156 -0
  31. package/bridge/provider.js +2 -0
  32. package/bridge/providers/emergency-commands.d.ts +54 -0
  33. package/bridge/providers/emergency-commands.js +235 -0
  34. package/bridge/providers/gateway.d.ts +322 -0
  35. package/bridge/providers/gateway.js +2302 -0
  36. package/bridge/providers/mock.d.ts +37 -0
  37. package/bridge/providers/mock.js +385 -0
  38. package/bridge/providers/onboarding-commands.d.ts +83 -0
  39. package/bridge/providers/onboarding-commands.js +213 -0
  40. package/bridge/providers/risk-calculator.d.ts +96 -0
  41. package/bridge/providers/risk-calculator.js +369 -0
  42. package/bridge/setup.d.ts +32 -0
  43. package/bridge/setup.js +226 -0
  44. package/bridge/types.d.ts +584 -0
  45. package/bridge/types.js +50 -0
  46. package/bridge/utils/reconnect.d.ts +6 -0
  47. package/bridge/utils/reconnect.js +6 -0
  48. package/bridge/utils/skill-signing.d.ts +51 -0
  49. package/bridge/utils/skill-signing.js +138 -0
  50. package/bridge/utils/skill-version.d.ts +17 -0
  51. package/bridge/utils/skill-version.js +74 -0
  52. package/ccxt/binance-ban-gate.d.ts +47 -0
  53. package/ccxt/binance-ban-gate.js +409 -0
  54. package/ccxt/binance-private.d.ts +325 -0
  55. package/ccxt/binance-private.js +1415 -0
  56. package/ccxt/binance-public.d.ts +18 -0
  57. package/ccxt/binance-public.js +147 -0
  58. package/config/agent-config-client.d.ts +55 -0
  59. package/config/agent-config-client.js +145 -0
  60. package/config/agent-config-poller.d.ts +25 -0
  61. package/config/agent-config-poller.js +100 -0
  62. package/config/brackets-config.d.ts +22 -0
  63. package/config/brackets-config.js +58 -0
  64. package/config/gate-store.d.ts +18 -0
  65. package/config/gate-store.js +61 -0
  66. package/config/plugin-config-io.d.ts +181 -0
  67. package/config/plugin-config-io.js +84 -0
  68. package/config/position-review-config.d.ts +35 -0
  69. package/config/position-review-config.js +105 -0
  70. package/config/tool-gate.d.ts +53 -0
  71. package/config/tool-gate.js +125 -0
  72. package/config/user-data-stream-config.d.ts +85 -0
  73. package/config/user-data-stream-config.js +224 -0
  74. package/connector-supervisor.d.ts +36 -0
  75. package/connector-supervisor.js +149 -0
  76. package/exchange-adapter.d.ts +49 -0
  77. package/exchange-adapter.js +4 -0
  78. package/index.d.ts +30 -0
  79. package/index.js +2030 -0
  80. package/ingest/pending-entry-metadata.d.ts +52 -0
  81. package/ingest/pending-entry-metadata.js +182 -0
  82. package/ingest/position-auto-capture.d.ts +98 -0
  83. package/ingest/position-auto-capture.js +394 -0
  84. package/ingest/position-decisions-client.d.ts +318 -0
  85. package/ingest/position-decisions-client.js +296 -0
  86. package/ingest/reconcile-db-vs-exchange.d.ts +13 -0
  87. package/ingest/reconcile-db-vs-exchange.js +114 -0
  88. package/ingest/reconciler-cleanup.d.ts +37 -0
  89. package/ingest/reconciler-cleanup.js +147 -0
  90. package/ingest/rest-gap-filler.d.ts +191 -0
  91. package/ingest/rest-gap-filler.js +565 -0
  92. package/ingest/touched-symbols-store.d.ts +25 -0
  93. package/ingest/touched-symbols-store.js +96 -0
  94. package/ingest/trade-store-client.d.ts +40 -0
  95. package/ingest/trade-store-client.js +125 -0
  96. package/ingest/ws-ingest.d.ts +43 -0
  97. package/ingest/ws-ingest.js +126 -0
  98. package/learning/setup-family.d.ts +21 -0
  99. package/learning/setup-family.js +103 -0
  100. package/lifecycle/install-signal-handlers.d.ts +33 -0
  101. package/lifecycle/install-signal-handlers.js +112 -0
  102. package/lifecycle/shutdown-coordinator.d.ts +43 -0
  103. package/lifecycle/shutdown-coordinator.js +131 -0
  104. package/live/bracket-id.d.ts +18 -0
  105. package/live/bracket-id.js +81 -0
  106. package/live/bracket-ledger.d.ts +54 -0
  107. package/live/bracket-ledger.js +267 -0
  108. package/live/bracket-manager.d.ts +82 -0
  109. package/live/bracket-manager.js +478 -0
  110. package/live/bracket-params.d.ts +22 -0
  111. package/live/bracket-params.js +124 -0
  112. package/live/bracket-reconciler.d.ts +95 -0
  113. package/live/bracket-reconciler.js +573 -0
  114. package/live/bracket-types.d.ts +102 -0
  115. package/live/bracket-types.js +8 -0
  116. package/live/deposit-tracker.d.ts +62 -0
  117. package/live/deposit-tracker.js +97 -0
  118. package/live/emergency-controls.d.ts +32 -0
  119. package/live/emergency-controls.js +226 -0
  120. package/live/exchange-errors.d.ts +12 -0
  121. package/live/exchange-errors.js +130 -0
  122. package/live/exchange-info-cache.d.ts +35 -0
  123. package/live/exchange-info-cache.js +119 -0
  124. package/live/fact-subscriber.d.ts +78 -0
  125. package/live/fact-subscriber.js +182 -0
  126. package/live/intent-journal.d.ts +42 -0
  127. package/live/intent-journal.js +122 -0
  128. package/live/listen-key-manager.d.ts +70 -0
  129. package/live/listen-key-manager.js +169 -0
  130. package/live/live-adapter.d.ts +264 -0
  131. package/live/live-adapter.js +1665 -0
  132. package/live/live-balance-enricher.d.ts +32 -0
  133. package/live/live-balance-enricher.js +104 -0
  134. package/live/live-bracket-api.d.ts +13 -0
  135. package/live/live-bracket-api.js +20 -0
  136. package/live/live-state-store.d.ts +194 -0
  137. package/live/live-state-store.js +450 -0
  138. package/live/local-signal-service.d.ts +57 -0
  139. package/live/local-signal-service.js +146 -0
  140. package/live/local-strategy-evaluator.d.ts +62 -0
  141. package/live/local-strategy-evaluator.js +127 -0
  142. package/live/microstructure-assembler.d.ts +54 -0
  143. package/live/microstructure-assembler.js +148 -0
  144. package/live/order-poller.d.ts +29 -0
  145. package/live/order-poller.js +125 -0
  146. package/live/position-state-store.d.ts +83 -0
  147. package/live/position-state-store.js +237 -0
  148. package/live/proposal-decision-listener.d.ts +64 -0
  149. package/live/proposal-decision-listener.js +288 -0
  150. package/live/proposal-manager.d.ts +76 -0
  151. package/live/proposal-manager.js +140 -0
  152. package/live/rate-limiter.d.ts +47 -0
  153. package/live/rate-limiter.js +159 -0
  154. package/live/reconciler.d.ts +39 -0
  155. package/live/reconciler.js +175 -0
  156. package/live/setup-buckets.d.ts +7 -0
  157. package/live/setup-buckets.js +33 -0
  158. package/live/slippage-tracker.d.ts +45 -0
  159. package/live/slippage-tracker.js +78 -0
  160. package/live/stop-watcher.d.ts +34 -0
  161. package/live/stop-watcher.js +158 -0
  162. package/live/user-data-active-probe.d.ts +54 -0
  163. package/live/user-data-active-probe.js +180 -0
  164. package/live/user-data-stream-controller.d.ts +200 -0
  165. package/live/user-data-stream-controller.js +579 -0
  166. package/live/user-data-stream-ws.d.ts +22 -0
  167. package/live/user-data-stream-ws.js +63 -0
  168. package/live/user-data-stream.d.ts +243 -0
  169. package/live/user-data-stream.js +704 -0
  170. package/logger.d.ts +2 -0
  171. package/logger.js +2 -0
  172. package/mfe.d.ts +21 -0
  173. package/mfe.js +68 -0
  174. package/onboarding/mode-ladder.d.ts +1 -0
  175. package/onboarding/mode-ladder.js +3 -0
  176. package/onboarding/runtime.d.ts +71 -0
  177. package/onboarding/runtime.js +153 -0
  178. package/openclaw.plugin.json +94 -0
  179. package/package.json +27 -0
  180. package/paper-adapter.d.ts +24 -0
  181. package/paper-adapter.js +91 -0
  182. package/persistence/state-manager.d.ts +42 -0
  183. package/persistence/state-manager.js +164 -0
  184. package/pinned-plan.d.ts +9 -0
  185. package/pinned-plan.js +23 -0
  186. package/risk/pre-trade-check.d.ts +38 -0
  187. package/risk/pre-trade-check.js +345 -0
  188. package/risk/pre-trade-types.d.ts +60 -0
  189. package/risk/pre-trade-types.js +3 -0
  190. package/scripts/assemble.mjs +114 -0
  191. package/shadow/shadow-tracker.d.ts +36 -0
  192. package/shadow/shadow-tracker.js +151 -0
  193. package/shadow/types.d.ts +42 -0
  194. package/shadow/types.js +20 -0
  195. package/shared/indicators-extended.d.ts +52 -0
  196. package/shared/indicators-extended.js +291 -0
  197. package/shared/indicators.d.ts +15 -0
  198. package/shared/indicators.js +114 -0
  199. package/signals/conditions/registry.d.ts +16 -0
  200. package/signals/conditions/registry.js +1274 -0
  201. package/signals/conditions/types.d.ts +1 -0
  202. package/signals/conditions/types.js +4 -0
  203. package/signals/direction-rules.d.ts +3 -0
  204. package/signals/direction-rules.js +24 -0
  205. package/signals/entry-rules.d.ts +6 -0
  206. package/signals/entry-rules.js +33 -0
  207. package/signals/serialize-context.d.ts +4 -0
  208. package/signals/serialize-context.js +39 -0
  209. package/signals/stop-rules.d.ts +3 -0
  210. package/signals/stop-rules.js +48 -0
  211. package/signals/strategy-adapter.d.ts +14 -0
  212. package/signals/strategy-adapter.js +122 -0
  213. package/signals/types.d.ts +1 -0
  214. package/signals/types.js +8 -0
  215. package/simulator/exchange-simulator.d.ts +93 -0
  216. package/simulator/exchange-simulator.js +684 -0
  217. package/simulator/fill-engine.d.ts +53 -0
  218. package/simulator/fill-engine.js +276 -0
  219. package/simulator/paper-market-feed.d.ts +26 -0
  220. package/simulator/paper-market-feed.js +104 -0
  221. package/simulator/realistic-fills.d.ts +59 -0
  222. package/simulator/realistic-fills.js +175 -0
  223. package/simulator/types.d.ts +219 -0
  224. package/simulator/types.js +43 -0
  225. package/skills/reefclaw/SKILL.md +97 -0
  226. package/strategy/builtin-strategies.d.ts +2 -0
  227. package/strategy/builtin-strategies.js +109 -0
  228. package/strategy/condition-registry.d.ts +3 -0
  229. package/strategy/condition-registry.js +153 -0
  230. package/strategy/evaluator.d.ts +67 -0
  231. package/strategy/evaluator.js +93 -0
  232. package/tools/assessment-validation.d.ts +118 -0
  233. package/tools/assessment-validation.js +415 -0
  234. package/tools/attach-brackets.d.ts +34 -0
  235. package/tools/attach-brackets.js +363 -0
  236. package/tools/audit-bracket-protection.d.ts +49 -0
  237. package/tools/audit-bracket-protection.js +527 -0
  238. package/tools/cancel-all-orders.d.ts +7 -0
  239. package/tools/cancel-all-orders.js +5 -0
  240. package/tools/cancel-order.d.ts +10 -0
  241. package/tools/cancel-order.js +14 -0
  242. package/tools/check-position-health.d.ts +46 -0
  243. package/tools/check-position-health.js +194 -0
  244. package/tools/clear-exchange-credentials.d.ts +24 -0
  245. package/tools/clear-exchange-credentials.js +70 -0
  246. package/tools/close-position.d.ts +22 -0
  247. package/tools/close-position.js +449 -0
  248. package/tools/create-order.d.ts +54 -0
  249. package/tools/create-order.js +338 -0
  250. package/tools/exit-gate.d.ts +58 -0
  251. package/tools/exit-gate.js +162 -0
  252. package/tools/fetch-balance.d.ts +5 -0
  253. package/tools/fetch-balance.js +4 -0
  254. package/tools/fetch-ohlcv.d.ts +11 -0
  255. package/tools/fetch-ohlcv.js +8 -0
  256. package/tools/fetch-open-orders.d.ts +7 -0
  257. package/tools/fetch-open-orders.js +4 -0
  258. package/tools/fetch-positions.d.ts +7 -0
  259. package/tools/fetch-positions.js +4 -0
  260. package/tools/fetch-ticker.d.ts +11 -0
  261. package/tools/fetch-ticker.js +5 -0
  262. package/tools/get-agent-profile.d.ts +4 -0
  263. package/tools/get-agent-profile.js +6 -0
  264. package/tools/get-analytics.d.ts +6 -0
  265. package/tools/get-analytics.js +7 -0
  266. package/tools/get-backtest.d.ts +12 -0
  267. package/tools/get-backtest.js +91 -0
  268. package/tools/get-basis.d.ts +7 -0
  269. package/tools/get-basis.js +7 -0
  270. package/tools/get-bracket-config.d.ts +11 -0
  271. package/tools/get-bracket-config.js +24 -0
  272. package/tools/get-cascade-risk.d.ts +7 -0
  273. package/tools/get-cascade-risk.js +8 -0
  274. package/tools/get-crypto-metrics.d.ts +18 -0
  275. package/tools/get-crypto-metrics.js +45 -0
  276. package/tools/get-cvd.d.ts +6 -0
  277. package/tools/get-cvd.js +6 -0
  278. package/tools/get-divergences.d.ts +6 -0
  279. package/tools/get-divergences.js +6 -0
  280. package/tools/get-funding-context.d.ts +6 -0
  281. package/tools/get-funding-context.js +16 -0
  282. package/tools/get-liquidation-levels.d.ts +7 -0
  283. package/tools/get-liquidation-levels.js +7 -0
  284. package/tools/get-liquidation-pulse.d.ts +9 -0
  285. package/tools/get-liquidation-pulse.js +22 -0
  286. package/tools/get-market-breadth.d.ts +6 -0
  287. package/tools/get-market-breadth.js +8 -0
  288. package/tools/get-market-intel.d.ts +19 -0
  289. package/tools/get-market-intel.js +116 -0
  290. package/tools/get-market-structure.d.ts +47 -0
  291. package/tools/get-market-structure.js +198 -0
  292. package/tools/get-my-mined-patterns.d.ts +20 -0
  293. package/tools/get-my-mined-patterns.js +61 -0
  294. package/tools/get-my-proposed-learnings.d.ts +20 -0
  295. package/tools/get-my-proposed-learnings.js +55 -0
  296. package/tools/get-my-recent-reviews.d.ts +22 -0
  297. package/tools/get-my-recent-reviews.js +66 -0
  298. package/tools/get-orderbook.d.ts +21 -0
  299. package/tools/get-orderbook.js +32 -0
  300. package/tools/get-pattern-scan.d.ts +7 -0
  301. package/tools/get-pattern-scan.js +8 -0
  302. package/tools/get-regime.d.ts +6 -0
  303. package/tools/get-regime.js +7 -0
  304. package/tools/get-relevant-learnings.d.ts +21 -0
  305. package/tools/get-relevant-learnings.js +65 -0
  306. package/tools/get-resting-liquidity.d.ts +6 -0
  307. package/tools/get-resting-liquidity.js +11 -0
  308. package/tools/get-risk-scenario.d.ts +29 -0
  309. package/tools/get-risk-scenario.js +47 -0
  310. package/tools/get-risk-summary.d.ts +51 -0
  311. package/tools/get-risk-summary.js +118 -0
  312. package/tools/get-sentiment.d.ts +4 -0
  313. package/tools/get-sentiment.js +6 -0
  314. package/tools/get-session-review.d.ts +7 -0
  315. package/tools/get-session-review.js +8 -0
  316. package/tools/get-setup-detail.d.ts +7 -0
  317. package/tools/get-setup-detail.js +303 -0
  318. package/tools/get-signals.d.ts +15 -0
  319. package/tools/get-signals.js +54 -0
  320. package/tools/get-sizing.d.ts +6 -0
  321. package/tools/get-sizing.js +6 -0
  322. package/tools/get-trade-feedback.d.ts +7 -0
  323. package/tools/get-trade-feedback.js +8 -0
  324. package/tools/get-trade-flow.d.ts +7 -0
  325. package/tools/get-trade-flow.js +7 -0
  326. package/tools/get-volume-analysis.d.ts +21 -0
  327. package/tools/get-volume-analysis.js +74 -0
  328. package/tools/get-volume-profile.d.ts +7 -0
  329. package/tools/get-volume-profile.js +7 -0
  330. package/tools/helpers.d.ts +25 -0
  331. package/tools/helpers.js +38 -0
  332. package/tools/intel-api.d.ts +14 -0
  333. package/tools/intel-api.js +52 -0
  334. package/tools/intel-cache.d.ts +25 -0
  335. package/tools/intel-cache.js +133 -0
  336. package/tools/list-strategies.d.ts +7 -0
  337. package/tools/list-strategies.js +6 -0
  338. package/tools/modify-stop.d.ts +17 -0
  339. package/tools/modify-stop.js +81 -0
  340. package/tools/modify-target.d.ts +17 -0
  341. package/tools/modify-target.js +71 -0
  342. package/tools/propose-learning.d.ts +22 -0
  343. package/tools/propose-learning.js +65 -0
  344. package/tools/query-review-outcomes.d.ts +30 -0
  345. package/tools/query-review-outcomes.js +64 -0
  346. package/tools/query-trades.d.ts +21 -0
  347. package/tools/query-trades.js +37 -0
  348. package/tools/record-position-reviews.d.ts +38 -0
  349. package/tools/record-position-reviews.js +147 -0
  350. package/tools/save-strategy.d.ts +16 -0
  351. package/tools/save-strategy.js +46 -0
  352. package/tools/scan-pairs.d.ts +18 -0
  353. package/tools/scan-pairs.js +220 -0
  354. package/tools/score-setup.d.ts +31 -0
  355. package/tools/score-setup.js +268 -0
  356. package/tools/set-bracket-requirement.d.ts +18 -0
  357. package/tools/set-bracket-requirement.js +81 -0
  358. package/tools/set-exchange-credentials.d.ts +25 -0
  359. package/tools/set-exchange-credentials.js +80 -0
  360. package/tools/set-trading-mode.d.ts +26 -0
  361. package/tools/set-trading-mode.js +135 -0
  362. package/tools/test-exchange-credentials.d.ts +16 -0
  363. package/tools/test-exchange-credentials.js +100 -0
  364. package/tools/toggle-strategy.d.ts +8 -0
  365. package/tools/toggle-strategy.js +8 -0
  366. package/trading-params-cache.d.ts +26 -0
  367. package/trading-params-cache.js +52 -0
  368. package/types.d.ts +110 -0
  369. package/types.js +7 -0
  370. package/util/plugin-paths.d.ts +3 -0
  371. package/util/plugin-paths.js +15 -0
package/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ # Assembled output — everything except the package sources is generated by
2
+ # scripts/assemble.mjs from plugin/dist + skill/dist + the bootstrap skill.
3
+ *
4
+ !package.json
5
+ !scripts/
6
+ !scripts/**
7
+ !README.md
8
+ !.gitignore
@@ -0,0 +1,11 @@
1
+ import type { TradingMode } from '../types.js';
2
+ export interface ModeTransitionAuditEntry {
3
+ ts: string;
4
+ previousMode: TradingMode;
5
+ targetMode: TradingMode;
6
+ acknowledged: boolean;
7
+ ok: boolean;
8
+ reason?: string;
9
+ testnet?: boolean;
10
+ }
11
+ export declare function recordModeTransition(entry: Omit<ModeTransitionAuditEntry, 'ts'>, pluginId?: string): void;
@@ -0,0 +1,29 @@
1
+ // Mode-transition audit — append-only JSONL record of every set_trading_mode call.
2
+ //
3
+ // Written BEFORE the adapter swap (so even a crashed transition leaves a trail)
4
+ // and updated with the outcome. Intended for post-incident review and regulatory
5
+ // defence ("the operator acknowledged the LIVE transition at 2026-04-20T14:32:11Z").
6
+ //
7
+ // Path: ~/.openclaw/plugins/<pluginId>/mode-transitions.jsonl
8
+ // Append-only; never truncated. One JSON object per line.
9
+ import { appendFileSync, existsSync, mkdirSync } from 'node:fs';
10
+ import { join } from 'node:path';
11
+ import { logger, formatError } from '../logger.js';
12
+ import { resolvePluginsBaseDir } from '../util/plugin-paths.js';
13
+ const TAG = 'mode-audit';
14
+ function resolvePath(pluginId) {
15
+ const dir = join(resolvePluginsBaseDir(), pluginId ?? 'reefclaw-paper-trading');
16
+ if (!existsSync(dir))
17
+ mkdirSync(dir, { recursive: true });
18
+ return join(dir, 'mode-transitions.jsonl');
19
+ }
20
+ export function recordModeTransition(entry, pluginId) {
21
+ const full = { ts: new Date().toISOString(), ...entry };
22
+ try {
23
+ appendFileSync(resolvePath(pluginId), JSON.stringify(full) + '\n', 'utf8');
24
+ logger.info(TAG, `${full.previousMode} → ${full.targetMode} ok=${full.ok} ack=${full.acknowledged}`);
25
+ }
26
+ catch (err) {
27
+ logger.error(TAG, `Failed to write audit entry: ${formatError(err)}`);
28
+ }
29
+ }
@@ -0,0 +1,36 @@
1
+ import type { CcxtBalance } from './types.js';
2
+ /**
3
+ * Read the total quote-currency balance from a CCXT balance map.
4
+ *
5
+ * Uses the PRIMARY funded currency only — whichever of USDT/USDC has
6
+ * the larger balance. Summing both was incorrect because Binance
7
+ * cross-margin accounting reports position margin/value as a phantom
8
+ * balance in the settlement currency (e.g., opening an ATOM/USDT
9
+ * position with a USDC-funded account creates a USDT "balance" entry
10
+ * equal to the position's notional, inflating getQuoteBalance by the
11
+ * position value and causing the KPI to double-count).
12
+ *
13
+ * For wallet/equity/NAV reads on Binance Futures, prefer
14
+ * `getQuoteWalletBalance(balance)` — it handles BNFCR.
15
+ */
16
+ export declare function getQuoteBalance(balanceMap: Record<string, number> | undefined): number;
17
+ /**
18
+ * Read the effective wallet-equivalent quote balance from a Binance Futures
19
+ * fetchBalance response, including the BNFCR realized-PnL accumulator.
20
+ *
21
+ * Why this exists: Binance multi-asset accounts settle realized PnL into
22
+ * BNFCR (negative when net-loss, positive when net-gain). CCXT's `total`
23
+ * map carries `marginBalance` (= walletBalance + uPnl), so the BNFCR line
24
+ * mixes uPnl into the total, which double-counts when the caller adds
25
+ * position uPnl on top. This helper reads `info.assets[i].walletBalance`
26
+ * directly, which excludes uPnl by construction.
27
+ *
28
+ * Returns max(USDT_wallet, USDC_wallet) + BNFCR_wallet. BNFCR is added
29
+ * (not max'd) because it is independent of the funded stablecoin — a
30
+ * USDC-funded account with cumulative losses shows USDC unchanged plus
31
+ * BNFCR negative; the user's true wallet is the sum.
32
+ *
33
+ * Falls back to `getQuoteBalance(balance.total)` when `info.assets` is
34
+ * absent (mock balances in unit tests, non-Binance exchanges).
35
+ */
36
+ export declare function getQuoteWalletBalance(balance: CcxtBalance | null | undefined): number;
@@ -0,0 +1,98 @@
1
+ // Utility for reading quote-currency balance from CCXT balance objects.
2
+ // Binance USDⓈ-M Futures settles in USDT or USDC — accounts may hold either or both.
3
+ // On multi-asset accounts a third asset, BNFCR, accumulates realized PnL as a
4
+ // signed wallet line (negative = cumulative loss, positive = cumulative gain).
5
+ /**
6
+ * Read the total quote-currency balance from a CCXT balance map.
7
+ *
8
+ * Uses the PRIMARY funded currency only — whichever of USDT/USDC has
9
+ * the larger balance. Summing both was incorrect because Binance
10
+ * cross-margin accounting reports position margin/value as a phantom
11
+ * balance in the settlement currency (e.g., opening an ATOM/USDT
12
+ * position with a USDC-funded account creates a USDT "balance" entry
13
+ * equal to the position's notional, inflating getQuoteBalance by the
14
+ * position value and causing the KPI to double-count).
15
+ *
16
+ * For wallet/equity/NAV reads on Binance Futures, prefer
17
+ * `getQuoteWalletBalance(balance)` — it handles BNFCR.
18
+ */
19
+ export function getQuoteBalance(balanceMap) {
20
+ if (!balanceMap)
21
+ return 0;
22
+ const usdt = balanceMap.USDT ?? 0;
23
+ const usdc = balanceMap.USDC ?? 0;
24
+ // Use whichever currency has the larger wallet balance (the funded one).
25
+ // If both are zero, return 0. If both are funded, use the larger.
26
+ return Math.max(usdt, usdc);
27
+ }
28
+ /**
29
+ * Read the effective wallet-equivalent quote balance from a Binance Futures
30
+ * fetchBalance response, including the BNFCR realized-PnL accumulator.
31
+ *
32
+ * Why this exists: Binance multi-asset accounts settle realized PnL into
33
+ * BNFCR (negative when net-loss, positive when net-gain). CCXT's `total`
34
+ * map carries `marginBalance` (= walletBalance + uPnl), so the BNFCR line
35
+ * mixes uPnl into the total, which double-counts when the caller adds
36
+ * position uPnl on top. This helper reads `info.assets[i].walletBalance`
37
+ * directly, which excludes uPnl by construction.
38
+ *
39
+ * Returns max(USDT_wallet, USDC_wallet) + BNFCR_wallet. BNFCR is added
40
+ * (not max'd) because it is independent of the funded stablecoin — a
41
+ * USDC-funded account with cumulative losses shows USDC unchanged plus
42
+ * BNFCR negative; the user's true wallet is the sum.
43
+ *
44
+ * Falls back to `getQuoteBalance(balance.total)` when `info.assets` is
45
+ * absent (mock balances in unit tests, non-Binance exchanges).
46
+ */
47
+ export function getQuoteWalletBalance(balance) {
48
+ if (!balance)
49
+ return 0;
50
+ // Prefer Binance's own account-level wallet aggregate when present.
51
+ // `/fapi/v3/account` (CCXT passes it through verbatim at `info`) returns
52
+ // `totalWalletBalance` — in Multi-Assets Mode this is the USD-denominated
53
+ // sum across all margin assets, with each non-USD collateral valued at
54
+ // Binance's live index price (verified against developers.binance.com →
55
+ // Account Information V3, 2026-05-16). It also excludes uPnL by
56
+ // construction (marginBalance = walletBalance + uPnL), matching this
57
+ // function's "wallet, uPnL added by caller" contract.
58
+ //
59
+ // Why this beats the per-asset reconstruction below: summing
60
+ // `max(USDT,USDC) + BNFCR` values USDC at FACE 1.0000, but Binance values
61
+ // USDC collateral at the live USDC/USD index (~0.9998). That made the
62
+ // dashboard wallet permanently ~$0.2 high vs the Binance app on this
63
+ // account (always-on, same-sign, slowly varying with the USDC peg —
64
+ // 2026-05-16 "figures slightly off always"). totalWalletBalance is the
65
+ // exact number the app's Futures "Wallet Balance" shows. The read path is
66
+ // already REST (`LiveAdapter.getBalance` → `fetchBalance()` every poll),
67
+ // so this is zero freshness regression — same cadence, correct value.
68
+ const info = balance?.info;
69
+ if (info && info.totalWalletBalance != null) {
70
+ const twb = parseFloat(String(info.totalWalletBalance));
71
+ if (Number.isFinite(twb))
72
+ return twb;
73
+ }
74
+ // Fallback (no Binance aggregate — non-Binance exchange, mock balances in
75
+ // unit tests, or a WS-store-derived balance object): the legacy
76
+ // face-value per-asset reconstruction. Carries the documented ~USDC-index
77
+ // drift but is the best available when the aggregate is absent.
78
+ const assets = balance?.info?.assets;
79
+ if (!Array.isArray(assets))
80
+ return getQuoteBalance(balance.total);
81
+ let usdt = 0;
82
+ let usdc = 0;
83
+ let bnfcr = 0;
84
+ for (const a of assets) {
85
+ if (!a || typeof a.asset !== 'string')
86
+ continue;
87
+ const wb = parseFloat(String(a.walletBalance ?? 0));
88
+ if (!Number.isFinite(wb))
89
+ continue;
90
+ if (a.asset === 'USDT')
91
+ usdt = wb;
92
+ else if (a.asset === 'USDC')
93
+ usdc = wb;
94
+ else if (a.asset === 'BNFCR')
95
+ bnfcr = wb;
96
+ }
97
+ return Math.max(usdt, usdc) + bnfcr;
98
+ }
@@ -0,0 +1,109 @@
1
+ import type { OpenClawProvider } from './provider.js';
2
+ import type { ConnectorConfig } from './types.js';
3
+ export declare class Bridge {
4
+ private readonly provider;
5
+ private connector;
6
+ private readonly seqs;
7
+ private throttleBuffer;
8
+ private throttleTimer;
9
+ /**
10
+ * Bounded ring buffer of every frame this bridge has emitted to the relay.
11
+ * On a `reconcile` request the bridge populates `snapshot.gapFill` with
12
+ * everything the browser hasn't seen yet (per-channel `seq > lastSeq`).
13
+ * Defaults: 500 events × 4 channels × 5 min age cap. See
14
+ * event-replay-buffer.ts for the rationale.
15
+ */
16
+ private readonly replayBuffer;
17
+ /** Current local SKILL.md version (from frontmatter) */
18
+ private currentSkillVersion;
19
+ /** Last trading mode observed from either a tradingMode event or a
20
+ * successful set_trading_mode outcome. Used by the skill-side ladder
21
+ * check so the dashboard can be rejected quickly without a plugin
22
+ * round-trip. `null` means "unknown yet" — the plugin is the authority. */
23
+ private lastKnownTradingMode;
24
+ private readonly listeners;
25
+ /** rc_ connection token — also authenticates the webapp skill-content pull */
26
+ private readonly connectionToken;
27
+ constructor(provider: OpenClawProvider, connectorConfig: ConnectorConfig);
28
+ /** Start the bridge: connect to relay + start provider */
29
+ start(): void;
30
+ /** Stop the bridge: disconnect + stop provider */
31
+ stop(): void;
32
+ private wireProviderEvents;
33
+ private addListener;
34
+ private unwireProviderEvents;
35
+ private emit;
36
+ /** Send a frame to the relay AND record it in the replay buffer.
37
+ *
38
+ * Both writes happen unconditionally:
39
+ * - replayBuffer.record() is the canonical wire-history; gapFill draws
40
+ * from it on the next reconcile, even if this frame's wire send was
41
+ * a no-op because the connector was disconnected.
42
+ * - connector.sendEvent() internally checks readyState and silently
43
+ * no-ops when the socket is closed (connector.ts:164), so calling it
44
+ * during a disconnect is safe and we don't have to mirror the gate
45
+ * here. */
46
+ private sendFrame;
47
+ /** Flush all buffered low-priority events (latest value per type).
48
+ *
49
+ * Drains through sendFrame regardless of connector state — the replay
50
+ * buffer is the authoritative record and must capture coalesced events
51
+ * even when the link is down. The wire send inside sendFrame is a no-op
52
+ * until the connector reconnects, at which point new events flow live and
53
+ * the offline coalesced ones are available via gapFill on reconcile. */
54
+ private flushThrottleBuffer;
55
+ private startThrottleTimer;
56
+ private stopThrottleTimer;
57
+ private handleRequest;
58
+ private handleStateChange;
59
+ /** Today every authenticated session carries operator.write via the
60
+ * relay-level Clerk token. This method exists as the enforcement seam —
61
+ * a future PR can drop per-session roles in here without restructuring
62
+ * the dispatcher. Returning true keeps current behavior identical. */
63
+ private hasOperatorWriteScope;
64
+ /** Handle a set_trading_mode request. Returns 'responded' if the handler
65
+ * already wrote the response frame (e.g. on validation failure), otherwise
66
+ * returns the structured outcome for the caller to wrap in a success
67
+ * frame. Ladder validation runs here for fast dashboard feedback and
68
+ * again in the plugin (defense in depth). */
69
+ private handleSetTradingMode;
70
+ /** Handle a set_exchange_credentials request. The secret value passes
71
+ * through once and is never cached or logged; only a redacted fingerprint
72
+ * appears in the audit trail. */
73
+ private handleSetExchangeCredentials;
74
+ /** Handle a test_exchange_credentials request — transient read-only
75
+ * verification, nothing persisted. Same input validation + secret
76
+ * redaction rules as set_exchange_credentials. */
77
+ private handleTestExchangeCredentials;
78
+ /** Handle a clear_exchange_credentials request. No input — the method
79
+ * itself is the "yes I want this" signal; the webapp is expected to
80
+ * gate this behind a confirmation dialog before calling. */
81
+ private handleClearExchangeCredentials;
82
+ /** Apply a SKILL.md update: verify signature (C1), write to workspace +
83
+ * installed skill dir, clear session cache, notify agent. */
84
+ private applySkillUpdate;
85
+ /**
86
+ * Fetch the stored SKILL.md envelope from the relay's Durable-Object store
87
+ * and apply it. The DO store is writable exclusively through the
88
+ * ADMIN_SECRET-gated HTTP push (party.ts handleSkillPush) — pulling makes
89
+ * the STORE, not any WS frame, the trust anchor for OTA content. Refuses to
90
+ * downgrade below the local version (a stale relay copy must never clobber
91
+ * a newer local SKILL.md — prod incident 2026-05-13); an equal version
92
+ * re-applies (idempotent repair for a re-push). Returns null when the relay
93
+ * has nothing stored; throws on transport error.
94
+ */
95
+ private pullAndApplySkillUpdate;
96
+ /**
97
+ * Pull the full SKILL.md from the webapp's authenticated endpoint and apply
98
+ * it when newer than local. This is how a FRESH install upgrades from the
99
+ * bundled bootstrap (v0.0.x) to the real trading instructions — the relay's
100
+ * per-room Durable-Object store is empty for a new user, so the relay push
101
+ * channel alone can never deliver the first full copy. Token-gated: no valid
102
+ * rc_ token → 401 → no content (the full SKILL.md never ships unauthenticated).
103
+ * Same downgrade guard + applySkillUpdate pipeline (incl. the C1 signature
104
+ * gate when enforced) as the relay pull path.
105
+ */
106
+ private pullSkillContentFromWebapp;
107
+ /** Check relay's latest SKILL.md version against local and auto-update if stale */
108
+ private handleConnectAck;
109
+ }