@reefclaw/connect 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.
- package/assets/bridge/bridge.d.ts +96 -0
- package/assets/bridge/bridge.js +969 -0
- package/assets/bridge/config.d.ts +43 -0
- package/assets/bridge/config.js +176 -0
- package/assets/bridge/connector.d.ts +52 -0
- package/assets/bridge/connector.js +293 -0
- package/assets/bridge/event-replay-buffer.d.ts +43 -0
- package/assets/bridge/event-replay-buffer.js +109 -0
- package/assets/bridge/gateway/event-parser.d.ts +209 -0
- package/assets/bridge/gateway/event-parser.js +793 -0
- package/assets/bridge/gateway/gateway-config.d.ts +39 -0
- package/assets/bridge/gateway/gateway-config.js +86 -0
- package/assets/bridge/gateway/gateway-http-client.d.ts +50 -0
- package/assets/bridge/gateway/gateway-http-client.js +165 -0
- package/assets/bridge/gateway/gateway-ws-client.d.ts +116 -0
- package/assets/bridge/gateway/gateway-ws-client.js +417 -0
- package/assets/bridge/gateway/poller.d.ts +146 -0
- package/assets/bridge/gateway/poller.js +505 -0
- package/assets/bridge/gateway/tool-discovery.d.ts +25 -0
- package/assets/bridge/gateway/tool-discovery.js +198 -0
- package/assets/bridge/index.d.ts +2 -0
- package/assets/bridge/index.js +253 -0
- package/assets/bridge/logger.d.ts +2 -0
- package/assets/bridge/logger.js +2 -0
- package/assets/bridge/provider.d.ts +156 -0
- package/assets/bridge/provider.js +2 -0
- package/assets/bridge/providers/emergency-commands.d.ts +54 -0
- package/assets/bridge/providers/emergency-commands.js +235 -0
- package/assets/bridge/providers/gateway.d.ts +322 -0
- package/assets/bridge/providers/gateway.js +2302 -0
- package/assets/bridge/providers/mock.d.ts +37 -0
- package/assets/bridge/providers/mock.js +385 -0
- package/assets/bridge/providers/onboarding-commands.d.ts +83 -0
- package/assets/bridge/providers/onboarding-commands.js +213 -0
- package/assets/bridge/providers/risk-calculator.d.ts +96 -0
- package/assets/bridge/providers/risk-calculator.js +369 -0
- package/assets/bridge/setup.d.ts +32 -0
- package/assets/bridge/setup.js +226 -0
- package/assets/bridge/types.d.ts +584 -0
- package/assets/bridge/types.js +50 -0
- package/assets/bridge/utils/reconnect.d.ts +6 -0
- package/assets/bridge/utils/reconnect.js +6 -0
- package/assets/bridge/utils/skill-signing.d.ts +51 -0
- package/assets/bridge/utils/skill-signing.js +138 -0
- package/assets/bridge/utils/skill-version.d.ts +17 -0
- package/assets/bridge/utils/skill-version.js +71 -0
- package/assets/plugin/audit/mode-transition-audit.d.ts +11 -0
- package/assets/plugin/audit/mode-transition-audit.js +29 -0
- package/assets/plugin/balance-utils.d.ts +36 -0
- package/assets/plugin/balance-utils.js +98 -0
- package/assets/plugin/ccxt/binance-ban-gate.d.ts +47 -0
- package/assets/plugin/ccxt/binance-ban-gate.js +409 -0
- package/assets/plugin/ccxt/binance-private.d.ts +325 -0
- package/assets/plugin/ccxt/binance-private.js +1415 -0
- package/assets/plugin/ccxt/binance-public.d.ts +18 -0
- package/assets/plugin/ccxt/binance-public.js +147 -0
- package/assets/plugin/config/agent-config-client.d.ts +55 -0
- package/assets/plugin/config/agent-config-client.js +145 -0
- package/assets/plugin/config/agent-config-poller.d.ts +25 -0
- package/assets/plugin/config/agent-config-poller.js +100 -0
- package/assets/plugin/config/brackets-config.d.ts +22 -0
- package/assets/plugin/config/brackets-config.js +58 -0
- package/assets/plugin/config/gate-store.d.ts +18 -0
- package/assets/plugin/config/gate-store.js +61 -0
- package/assets/plugin/config/plugin-config-io.d.ts +175 -0
- package/assets/plugin/config/plugin-config-io.js +84 -0
- package/assets/plugin/config/position-review-config.d.ts +35 -0
- package/assets/plugin/config/position-review-config.js +105 -0
- package/assets/plugin/config/tool-gate.d.ts +53 -0
- package/assets/plugin/config/tool-gate.js +125 -0
- package/assets/plugin/config/user-data-stream-config.d.ts +85 -0
- package/assets/plugin/config/user-data-stream-config.js +224 -0
- package/assets/plugin/exchange-adapter.d.ts +49 -0
- package/assets/plugin/exchange-adapter.js +4 -0
- package/assets/plugin/index.d.ts +30 -0
- package/assets/plugin/index.js +1989 -0
- package/assets/plugin/ingest/pending-entry-metadata.d.ts +52 -0
- package/assets/plugin/ingest/pending-entry-metadata.js +182 -0
- package/assets/plugin/ingest/position-auto-capture.d.ts +98 -0
- package/assets/plugin/ingest/position-auto-capture.js +394 -0
- package/assets/plugin/ingest/position-decisions-client.d.ts +318 -0
- package/assets/plugin/ingest/position-decisions-client.js +296 -0
- package/assets/plugin/ingest/reconcile-db-vs-exchange.d.ts +13 -0
- package/assets/plugin/ingest/reconcile-db-vs-exchange.js +114 -0
- package/assets/plugin/ingest/reconciler-cleanup.d.ts +37 -0
- package/assets/plugin/ingest/reconciler-cleanup.js +147 -0
- package/assets/plugin/ingest/rest-gap-filler.d.ts +191 -0
- package/assets/plugin/ingest/rest-gap-filler.js +565 -0
- package/assets/plugin/ingest/touched-symbols-store.d.ts +25 -0
- package/assets/plugin/ingest/touched-symbols-store.js +96 -0
- package/assets/plugin/ingest/trade-store-client.d.ts +40 -0
- package/assets/plugin/ingest/trade-store-client.js +125 -0
- package/assets/plugin/ingest/ws-ingest.d.ts +43 -0
- package/assets/plugin/ingest/ws-ingest.js +126 -0
- package/assets/plugin/learning/setup-family.d.ts +21 -0
- package/assets/plugin/learning/setup-family.js +103 -0
- package/assets/plugin/lifecycle/install-signal-handlers.d.ts +33 -0
- package/assets/plugin/lifecycle/install-signal-handlers.js +112 -0
- package/assets/plugin/lifecycle/shutdown-coordinator.d.ts +43 -0
- package/assets/plugin/lifecycle/shutdown-coordinator.js +131 -0
- package/assets/plugin/live/bracket-id.d.ts +18 -0
- package/assets/plugin/live/bracket-id.js +81 -0
- package/assets/plugin/live/bracket-ledger.d.ts +54 -0
- package/assets/plugin/live/bracket-ledger.js +267 -0
- package/assets/plugin/live/bracket-manager.d.ts +82 -0
- package/assets/plugin/live/bracket-manager.js +478 -0
- package/assets/plugin/live/bracket-params.d.ts +22 -0
- package/assets/plugin/live/bracket-params.js +124 -0
- package/assets/plugin/live/bracket-reconciler.d.ts +95 -0
- package/assets/plugin/live/bracket-reconciler.js +573 -0
- package/assets/plugin/live/bracket-types.d.ts +102 -0
- package/assets/plugin/live/bracket-types.js +8 -0
- package/assets/plugin/live/deposit-tracker.d.ts +62 -0
- package/assets/plugin/live/deposit-tracker.js +97 -0
- package/assets/plugin/live/emergency-controls.d.ts +32 -0
- package/assets/plugin/live/emergency-controls.js +226 -0
- package/assets/plugin/live/exchange-errors.d.ts +12 -0
- package/assets/plugin/live/exchange-errors.js +130 -0
- package/assets/plugin/live/exchange-info-cache.d.ts +35 -0
- package/assets/plugin/live/exchange-info-cache.js +119 -0
- package/assets/plugin/live/fact-subscriber.d.ts +78 -0
- package/assets/plugin/live/fact-subscriber.js +182 -0
- package/assets/plugin/live/intent-journal.d.ts +42 -0
- package/assets/plugin/live/intent-journal.js +122 -0
- package/assets/plugin/live/listen-key-manager.d.ts +70 -0
- package/assets/plugin/live/listen-key-manager.js +169 -0
- package/assets/plugin/live/live-adapter.d.ts +264 -0
- package/assets/plugin/live/live-adapter.js +1665 -0
- package/assets/plugin/live/live-balance-enricher.d.ts +32 -0
- package/assets/plugin/live/live-balance-enricher.js +104 -0
- package/assets/plugin/live/live-bracket-api.d.ts +13 -0
- package/assets/plugin/live/live-bracket-api.js +20 -0
- package/assets/plugin/live/live-state-store.d.ts +194 -0
- package/assets/plugin/live/live-state-store.js +450 -0
- package/assets/plugin/live/local-signal-service.d.ts +57 -0
- package/assets/plugin/live/local-signal-service.js +146 -0
- package/assets/plugin/live/local-strategy-evaluator.d.ts +62 -0
- package/assets/plugin/live/local-strategy-evaluator.js +127 -0
- package/assets/plugin/live/microstructure-assembler.d.ts +54 -0
- package/assets/plugin/live/microstructure-assembler.js +148 -0
- package/assets/plugin/live/order-poller.d.ts +29 -0
- package/assets/plugin/live/order-poller.js +125 -0
- package/assets/plugin/live/position-state-store.d.ts +83 -0
- package/assets/plugin/live/position-state-store.js +237 -0
- package/assets/plugin/live/proposal-decision-listener.d.ts +64 -0
- package/assets/plugin/live/proposal-decision-listener.js +288 -0
- package/assets/plugin/live/proposal-manager.d.ts +76 -0
- package/assets/plugin/live/proposal-manager.js +140 -0
- package/assets/plugin/live/rate-limiter.d.ts +47 -0
- package/assets/plugin/live/rate-limiter.js +159 -0
- package/assets/plugin/live/reconciler.d.ts +39 -0
- package/assets/plugin/live/reconciler.js +175 -0
- package/assets/plugin/live/setup-buckets.d.ts +7 -0
- package/assets/plugin/live/setup-buckets.js +33 -0
- package/assets/plugin/live/slippage-tracker.d.ts +45 -0
- package/assets/plugin/live/slippage-tracker.js +78 -0
- package/assets/plugin/live/stop-watcher.d.ts +34 -0
- package/assets/plugin/live/stop-watcher.js +158 -0
- package/assets/plugin/live/user-data-active-probe.d.ts +54 -0
- package/assets/plugin/live/user-data-active-probe.js +180 -0
- package/assets/plugin/live/user-data-stream-controller.d.ts +200 -0
- package/assets/plugin/live/user-data-stream-controller.js +579 -0
- package/assets/plugin/live/user-data-stream-ws.d.ts +22 -0
- package/assets/plugin/live/user-data-stream-ws.js +63 -0
- package/assets/plugin/live/user-data-stream.d.ts +243 -0
- package/assets/plugin/live/user-data-stream.js +704 -0
- package/assets/plugin/logger.d.ts +2 -0
- package/assets/plugin/logger.js +2 -0
- package/assets/plugin/mfe.d.ts +21 -0
- package/assets/plugin/mfe.js +68 -0
- package/assets/plugin/onboarding/mode-ladder.d.ts +1 -0
- package/assets/plugin/onboarding/mode-ladder.js +3 -0
- package/assets/plugin/onboarding/runtime.d.ts +71 -0
- package/assets/plugin/onboarding/runtime.js +153 -0
- package/assets/plugin/openclaw.plugin.json +91 -0
- package/assets/plugin/paper-adapter.d.ts +24 -0
- package/assets/plugin/paper-adapter.js +91 -0
- package/assets/plugin/persistence/state-manager.d.ts +42 -0
- package/assets/plugin/persistence/state-manager.js +164 -0
- package/assets/plugin/pinned-plan.d.ts +9 -0
- package/assets/plugin/pinned-plan.js +23 -0
- package/assets/plugin/risk/pre-trade-check.d.ts +38 -0
- package/assets/plugin/risk/pre-trade-check.js +345 -0
- package/assets/plugin/risk/pre-trade-types.d.ts +60 -0
- package/assets/plugin/risk/pre-trade-types.js +3 -0
- package/assets/plugin/shadow/shadow-tracker.d.ts +36 -0
- package/assets/plugin/shadow/shadow-tracker.js +151 -0
- package/assets/plugin/shadow/types.d.ts +42 -0
- package/assets/plugin/shadow/types.js +20 -0
- package/assets/plugin/shared/indicators-extended.d.ts +52 -0
- package/assets/plugin/shared/indicators-extended.js +291 -0
- package/assets/plugin/shared/indicators.d.ts +15 -0
- package/assets/plugin/shared/indicators.js +114 -0
- package/assets/plugin/signals/conditions/registry.d.ts +16 -0
- package/assets/plugin/signals/conditions/registry.js +1274 -0
- package/assets/plugin/signals/conditions/types.d.ts +1 -0
- package/assets/plugin/signals/conditions/types.js +4 -0
- package/assets/plugin/signals/direction-rules.d.ts +3 -0
- package/assets/plugin/signals/direction-rules.js +24 -0
- package/assets/plugin/signals/entry-rules.d.ts +6 -0
- package/assets/plugin/signals/entry-rules.js +33 -0
- package/assets/plugin/signals/serialize-context.d.ts +4 -0
- package/assets/plugin/signals/serialize-context.js +39 -0
- package/assets/plugin/signals/stop-rules.d.ts +3 -0
- package/assets/plugin/signals/stop-rules.js +48 -0
- package/assets/plugin/signals/strategy-adapter.d.ts +14 -0
- package/assets/plugin/signals/strategy-adapter.js +122 -0
- package/assets/plugin/signals/types.d.ts +1 -0
- package/assets/plugin/signals/types.js +8 -0
- package/assets/plugin/simulator/exchange-simulator.d.ts +93 -0
- package/assets/plugin/simulator/exchange-simulator.js +684 -0
- package/assets/plugin/simulator/fill-engine.d.ts +53 -0
- package/assets/plugin/simulator/fill-engine.js +276 -0
- package/assets/plugin/simulator/paper-market-feed.d.ts +26 -0
- package/assets/plugin/simulator/paper-market-feed.js +104 -0
- package/assets/plugin/simulator/realistic-fills.d.ts +59 -0
- package/assets/plugin/simulator/realistic-fills.js +175 -0
- package/assets/plugin/simulator/types.d.ts +219 -0
- package/assets/plugin/simulator/types.js +43 -0
- package/assets/plugin/strategy/builtin-strategies.d.ts +2 -0
- package/assets/plugin/strategy/builtin-strategies.js +109 -0
- package/assets/plugin/strategy/condition-registry.d.ts +3 -0
- package/assets/plugin/strategy/condition-registry.js +153 -0
- package/assets/plugin/strategy/evaluator.d.ts +67 -0
- package/assets/plugin/strategy/evaluator.js +93 -0
- package/assets/plugin/tools/assessment-validation.d.ts +118 -0
- package/assets/plugin/tools/assessment-validation.js +415 -0
- package/assets/plugin/tools/attach-brackets.d.ts +34 -0
- package/assets/plugin/tools/attach-brackets.js +363 -0
- package/assets/plugin/tools/audit-bracket-protection.d.ts +49 -0
- package/assets/plugin/tools/audit-bracket-protection.js +527 -0
- package/assets/plugin/tools/cancel-all-orders.d.ts +7 -0
- package/assets/plugin/tools/cancel-all-orders.js +5 -0
- package/assets/plugin/tools/cancel-order.d.ts +10 -0
- package/assets/plugin/tools/cancel-order.js +14 -0
- package/assets/plugin/tools/check-position-health.d.ts +46 -0
- package/assets/plugin/tools/check-position-health.js +194 -0
- package/assets/plugin/tools/clear-exchange-credentials.d.ts +24 -0
- package/assets/plugin/tools/clear-exchange-credentials.js +70 -0
- package/assets/plugin/tools/close-position.d.ts +22 -0
- package/assets/plugin/tools/close-position.js +449 -0
- package/assets/plugin/tools/create-order.d.ts +54 -0
- package/assets/plugin/tools/create-order.js +338 -0
- package/assets/plugin/tools/exit-gate.d.ts +58 -0
- package/assets/plugin/tools/exit-gate.js +162 -0
- package/assets/plugin/tools/fetch-balance.d.ts +5 -0
- package/assets/plugin/tools/fetch-balance.js +4 -0
- package/assets/plugin/tools/fetch-ohlcv.d.ts +11 -0
- package/assets/plugin/tools/fetch-ohlcv.js +8 -0
- package/assets/plugin/tools/fetch-open-orders.d.ts +7 -0
- package/assets/plugin/tools/fetch-open-orders.js +4 -0
- package/assets/plugin/tools/fetch-positions.d.ts +7 -0
- package/assets/plugin/tools/fetch-positions.js +4 -0
- package/assets/plugin/tools/fetch-ticker.d.ts +11 -0
- package/assets/plugin/tools/fetch-ticker.js +5 -0
- package/assets/plugin/tools/get-agent-profile.d.ts +4 -0
- package/assets/plugin/tools/get-agent-profile.js +6 -0
- package/assets/plugin/tools/get-analytics.d.ts +6 -0
- package/assets/plugin/tools/get-analytics.js +7 -0
- package/assets/plugin/tools/get-backtest.d.ts +12 -0
- package/assets/plugin/tools/get-backtest.js +91 -0
- package/assets/plugin/tools/get-basis.d.ts +7 -0
- package/assets/plugin/tools/get-basis.js +7 -0
- package/assets/plugin/tools/get-bracket-config.d.ts +11 -0
- package/assets/plugin/tools/get-bracket-config.js +24 -0
- package/assets/plugin/tools/get-cascade-risk.d.ts +7 -0
- package/assets/plugin/tools/get-cascade-risk.js +8 -0
- package/assets/plugin/tools/get-crypto-metrics.d.ts +18 -0
- package/assets/plugin/tools/get-crypto-metrics.js +45 -0
- package/assets/plugin/tools/get-cvd.d.ts +6 -0
- package/assets/plugin/tools/get-cvd.js +6 -0
- package/assets/plugin/tools/get-divergences.d.ts +6 -0
- package/assets/plugin/tools/get-divergences.js +6 -0
- package/assets/plugin/tools/get-funding-context.d.ts +6 -0
- package/assets/plugin/tools/get-funding-context.js +16 -0
- package/assets/plugin/tools/get-liquidation-levels.d.ts +7 -0
- package/assets/plugin/tools/get-liquidation-levels.js +7 -0
- package/assets/plugin/tools/get-liquidation-pulse.d.ts +9 -0
- package/assets/plugin/tools/get-liquidation-pulse.js +22 -0
- package/assets/plugin/tools/get-market-breadth.d.ts +6 -0
- package/assets/plugin/tools/get-market-breadth.js +8 -0
- package/assets/plugin/tools/get-market-intel.d.ts +19 -0
- package/assets/plugin/tools/get-market-intel.js +116 -0
- package/assets/plugin/tools/get-market-structure.d.ts +47 -0
- package/assets/plugin/tools/get-market-structure.js +198 -0
- package/assets/plugin/tools/get-my-mined-patterns.d.ts +20 -0
- package/assets/plugin/tools/get-my-mined-patterns.js +61 -0
- package/assets/plugin/tools/get-my-proposed-learnings.d.ts +20 -0
- package/assets/plugin/tools/get-my-proposed-learnings.js +55 -0
- package/assets/plugin/tools/get-my-recent-reviews.d.ts +22 -0
- package/assets/plugin/tools/get-my-recent-reviews.js +66 -0
- package/assets/plugin/tools/get-orderbook.d.ts +21 -0
- package/assets/plugin/tools/get-orderbook.js +32 -0
- package/assets/plugin/tools/get-pattern-scan.d.ts +7 -0
- package/assets/plugin/tools/get-pattern-scan.js +8 -0
- package/assets/plugin/tools/get-regime.d.ts +6 -0
- package/assets/plugin/tools/get-regime.js +7 -0
- package/assets/plugin/tools/get-relevant-learnings.d.ts +21 -0
- package/assets/plugin/tools/get-relevant-learnings.js +65 -0
- package/assets/plugin/tools/get-resting-liquidity.d.ts +6 -0
- package/assets/plugin/tools/get-resting-liquidity.js +11 -0
- package/assets/plugin/tools/get-risk-scenario.d.ts +29 -0
- package/assets/plugin/tools/get-risk-scenario.js +47 -0
- package/assets/plugin/tools/get-risk-summary.d.ts +51 -0
- package/assets/plugin/tools/get-risk-summary.js +118 -0
- package/assets/plugin/tools/get-sentiment.d.ts +4 -0
- package/assets/plugin/tools/get-sentiment.js +6 -0
- package/assets/plugin/tools/get-session-review.d.ts +7 -0
- package/assets/plugin/tools/get-session-review.js +8 -0
- package/assets/plugin/tools/get-setup-detail.d.ts +7 -0
- package/assets/plugin/tools/get-setup-detail.js +303 -0
- package/assets/plugin/tools/get-signals.d.ts +15 -0
- package/assets/plugin/tools/get-signals.js +54 -0
- package/assets/plugin/tools/get-sizing.d.ts +6 -0
- package/assets/plugin/tools/get-sizing.js +6 -0
- package/assets/plugin/tools/get-trade-feedback.d.ts +7 -0
- package/assets/plugin/tools/get-trade-feedback.js +8 -0
- package/assets/plugin/tools/get-trade-flow.d.ts +7 -0
- package/assets/plugin/tools/get-trade-flow.js +7 -0
- package/assets/plugin/tools/get-volume-analysis.d.ts +21 -0
- package/assets/plugin/tools/get-volume-analysis.js +74 -0
- package/assets/plugin/tools/get-volume-profile.d.ts +7 -0
- package/assets/plugin/tools/get-volume-profile.js +7 -0
- package/assets/plugin/tools/helpers.d.ts +25 -0
- package/assets/plugin/tools/helpers.js +38 -0
- package/assets/plugin/tools/intel-api.d.ts +14 -0
- package/assets/plugin/tools/intel-api.js +52 -0
- package/assets/plugin/tools/intel-cache.d.ts +25 -0
- package/assets/plugin/tools/intel-cache.js +133 -0
- package/assets/plugin/tools/list-strategies.d.ts +7 -0
- package/assets/plugin/tools/list-strategies.js +6 -0
- package/assets/plugin/tools/modify-stop.d.ts +17 -0
- package/assets/plugin/tools/modify-stop.js +81 -0
- package/assets/plugin/tools/modify-target.d.ts +17 -0
- package/assets/plugin/tools/modify-target.js +71 -0
- package/assets/plugin/tools/propose-learning.d.ts +22 -0
- package/assets/plugin/tools/propose-learning.js +65 -0
- package/assets/plugin/tools/query-review-outcomes.d.ts +30 -0
- package/assets/plugin/tools/query-review-outcomes.js +64 -0
- package/assets/plugin/tools/query-trades.d.ts +21 -0
- package/assets/plugin/tools/query-trades.js +37 -0
- package/assets/plugin/tools/record-position-reviews.d.ts +38 -0
- package/assets/plugin/tools/record-position-reviews.js +147 -0
- package/assets/plugin/tools/save-strategy.d.ts +16 -0
- package/assets/plugin/tools/save-strategy.js +46 -0
- package/assets/plugin/tools/scan-pairs.d.ts +18 -0
- package/assets/plugin/tools/scan-pairs.js +220 -0
- package/assets/plugin/tools/score-setup.d.ts +31 -0
- package/assets/plugin/tools/score-setup.js +268 -0
- package/assets/plugin/tools/set-bracket-requirement.d.ts +18 -0
- package/assets/plugin/tools/set-bracket-requirement.js +81 -0
- package/assets/plugin/tools/set-exchange-credentials.d.ts +25 -0
- package/assets/plugin/tools/set-exchange-credentials.js +80 -0
- package/assets/plugin/tools/set-trading-mode.d.ts +26 -0
- package/assets/plugin/tools/set-trading-mode.js +135 -0
- package/assets/plugin/tools/test-exchange-credentials.d.ts +16 -0
- package/assets/plugin/tools/test-exchange-credentials.js +100 -0
- package/assets/plugin/tools/toggle-strategy.d.ts +8 -0
- package/assets/plugin/tools/toggle-strategy.js +8 -0
- package/assets/plugin/trading-params-cache.d.ts +26 -0
- package/assets/plugin/trading-params-cache.js +52 -0
- package/assets/plugin/types.d.ts +110 -0
- package/assets/plugin/types.js +7 -0
- package/assets/plugin/util/plugin-paths.d.ts +3 -0
- package/assets/plugin/util/plugin-paths.js +15 -0
- package/assets/shared/fills.d.ts +36 -0
- package/assets/shared/fills.js +20 -0
- package/assets/shared/index.d.ts +10 -0
- package/assets/shared/index.js +5 -0
- package/assets/shared/logger.d.ts +10 -0
- package/assets/shared/logger.js +34 -0
- package/assets/shared/protocol.d.ts +29 -0
- package/assets/shared/protocol.js +14 -0
- package/assets/shared/redact.d.ts +6 -0
- package/assets/shared/redact.js +31 -0
- package/assets/shared/shared/indicators-extended.d.ts +52 -0
- package/assets/shared/shared/indicators-extended.js +284 -0
- package/assets/shared/shared/indicators.d.ts +15 -0
- package/assets/shared/shared/indicators.js +107 -0
- package/assets/shared/signals/conditions/registry.d.ts +16 -0
- package/assets/shared/signals/conditions/registry.js +1267 -0
- package/assets/shared/signals/conditions/types.d.ts +65 -0
- package/assets/shared/signals/conditions/types.js +8 -0
- package/assets/shared/signals/direction-rules.d.ts +3 -0
- package/assets/shared/signals/direction-rules.js +18 -0
- package/assets/shared/signals/entry-rules.d.ts +6 -0
- package/assets/shared/signals/entry-rules.js +26 -0
- package/assets/shared/signals/indicators-extended.d.ts +52 -0
- package/assets/shared/signals/indicators-extended.js +284 -0
- package/assets/shared/signals/indicators.d.ts +15 -0
- package/assets/shared/signals/indicators.js +107 -0
- package/assets/shared/signals/serialize-context.d.ts +4 -0
- package/assets/shared/signals/serialize-context.js +41 -0
- package/assets/shared/signals/stop-rules.d.ts +3 -0
- package/assets/shared/signals/stop-rules.js +41 -0
- package/assets/shared/signals/strategy-adapter.d.ts +14 -0
- package/assets/shared/signals/strategy-adapter.js +117 -0
- package/assets/shared/signals/types.d.ts +187 -0
- package/assets/shared/signals/types.js +9 -0
- package/assets/shared/trading-mode.d.ts +16 -0
- package/assets/shared/trading-mode.js +49 -0
- package/assets/skill/SKILL.md +1357 -0
- package/dist/bridge.js +25 -0
- package/dist/bundle.js +33 -0
- package/dist/cli.js +120 -0
- package/dist/daemon.js +104 -0
- package/dist/deps.js +41 -0
- package/dist/exec.js +28 -0
- package/dist/openclaw.js +153 -0
- package/dist/paths.js +23 -0
- package/dist/plugin.js +48 -0
- package/dist/skill.js +35 -0
- package/dist/ui.js +29 -0
- package/dist/validate.js +28 -0
- package/package.json +32 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// Ed25519 signature verification for OTA SKILL.md updates.
|
|
2
|
+
//
|
|
3
|
+
// Security finding C1 (docs/PRE_LAUNCH_SECURITY_HARDENING.md §2.5 + Appendix B):
|
|
4
|
+
// the relay is treated as a DUMB TRANSPORT. A pushed/pulled SKILL.md is applied
|
|
5
|
+
// only if it carries a valid signature from the operator's offline private key,
|
|
6
|
+
// whose PUBLIC key is pinned here in the build. A leaked ADMIN_SECRET, a
|
|
7
|
+
// compromised relay process, or a tampered Durable-Object value therefore
|
|
8
|
+
// CANNOT rewrite an agent's trading instructions — they all fail verification.
|
|
9
|
+
//
|
|
10
|
+
// Key provisioning (one-time, operator, OFFLINE):
|
|
11
|
+
// 1. python scripts/gen-skill-signing-key.py
|
|
12
|
+
// 2. paste the printed PUBLIC key (base64) into TRUSTED_SKILL_SIGNING_KEYS below
|
|
13
|
+
// 3. put the printed PRIVATE key into .env.deploy as SKILL_SIGNING_PRIVATE_KEY
|
|
14
|
+
// (gitignored — keep it offline; NEVER on the relay or any server)
|
|
15
|
+
// 4. rebuild + redeploy the skill (deploy-skillmd-ota.py is already wired to sign)
|
|
16
|
+
//
|
|
17
|
+
// Until a key is pinned, OTA is FAIL-CLOSED (every push rejected) while
|
|
18
|
+
// SKILL_OTA_REQUIRE_SIGNATURE is on (the default). Normal trading is unaffected
|
|
19
|
+
// — only the OTA-update path gates on this.
|
|
20
|
+
import { createHash, createPublicKey, verify as cryptoVerify } from 'node:crypto';
|
|
21
|
+
import { readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
22
|
+
import { join } from 'node:path';
|
|
23
|
+
import { homedir } from 'node:os';
|
|
24
|
+
import { parseSkillVersion } from './skill-version.js';
|
|
25
|
+
/**
|
|
26
|
+
* Pinned Ed25519 PUBLIC keys (base64 of the raw 32-byte key) trusted to sign OTA
|
|
27
|
+
* SKILL.md updates. Multiple entries enable key rotation (accept current + next,
|
|
28
|
+
* retire the old after every client has updated). EMPTY until the operator pins
|
|
29
|
+
* one — see the header for provisioning.
|
|
30
|
+
*/
|
|
31
|
+
export const TRUSTED_SKILL_SIGNING_KEYS = [
|
|
32
|
+
// 'Base64OfRaw32BytePublicKey=' ← paste from scripts/gen-skill-signing-key.py
|
|
33
|
+
];
|
|
34
|
+
const OTA_STATE_PATH = join(homedir(), '.openclaw', 'workspace', '.skill-ota-state.json');
|
|
35
|
+
/** Lowercase hex SHA-256 of the UTF-8 content. MUST match the Python signer. */
|
|
36
|
+
export function sha256Hex(content) {
|
|
37
|
+
return createHash('sha256').update(content, 'utf8').digest('hex');
|
|
38
|
+
}
|
|
39
|
+
/** Canonical signed message — MUST match deploy-skillmd-ota.py byte-for-byte. */
|
|
40
|
+
export function signedMessage(version, contentSha256, signedAt) {
|
|
41
|
+
return `${version}\n${contentSha256}\n${signedAt}`;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Is OTA signature verification enforced?
|
|
45
|
+
*
|
|
46
|
+
* Default **OFF** while C1 (signed OTA) is ON HOLD — see
|
|
47
|
+
* docs/PRE_LAUNCH_SECURITY_HARDENING.md §2.5. Keeping it off by default makes
|
|
48
|
+
* this whole module DORMANT, so deploying skill/relay for UNRELATED reasons can
|
|
49
|
+
* never break the existing (unsigned) OTA flow — no env flag to remember.
|
|
50
|
+
*
|
|
51
|
+
* To ENABLE signed-OTA (when the agent-update mechanism is finalized): pin a
|
|
52
|
+
* public key in TRUSTED_SKILL_SIGNING_KEYS **and** set
|
|
53
|
+
* SKILL_OTA_REQUIRE_SIGNATURE=on. Both are required — a pinned key alone does
|
|
54
|
+
* nothing without the flag, and the flag alone fails closed (no key → reject).
|
|
55
|
+
*/
|
|
56
|
+
export function signatureRequired() {
|
|
57
|
+
return (process.env.SKILL_OTA_REQUIRE_SIGNATURE ?? 'off').toLowerCase() === 'on';
|
|
58
|
+
}
|
|
59
|
+
function publicKeyFromRawB64(b64) {
|
|
60
|
+
try {
|
|
61
|
+
const raw = Buffer.from(b64, 'base64');
|
|
62
|
+
if (raw.length !== 32)
|
|
63
|
+
return null; // raw Ed25519 public key is exactly 32 bytes
|
|
64
|
+
return createPublicKey({
|
|
65
|
+
format: 'jwk',
|
|
66
|
+
key: { kty: 'OKP', crv: 'Ed25519', x: raw.toString('base64url') },
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Verify a signed OTA envelope against the pinned (or supplied) trusted keys.
|
|
75
|
+
* Checks: required fields present, content hash matches (no tampering), the
|
|
76
|
+
* frontmatter version matches the signed version (no number-bump replay), and
|
|
77
|
+
* the Ed25519 signature verifies under some trusted key. Pure — does NOT touch
|
|
78
|
+
* disk or the replay clock; the caller enforces monotonic signedAt.
|
|
79
|
+
*/
|
|
80
|
+
export function verifySkillSignature(env, opts) {
|
|
81
|
+
const keys = opts?.trustedKeys ?? TRUSTED_SKILL_SIGNING_KEYS;
|
|
82
|
+
if (keys.length === 0) {
|
|
83
|
+
return { ok: false, reason: 'no trusted signing keys configured — pin a public key in skill-signing.ts (see scripts/gen-skill-signing-key.py)' };
|
|
84
|
+
}
|
|
85
|
+
if (!env.signature || !env.signedAt || !env.contentSha256) {
|
|
86
|
+
return { ok: false, reason: 'missing signature/signedAt/contentSha256 (unsigned push)' };
|
|
87
|
+
}
|
|
88
|
+
if (sha256Hex(env.content) !== env.contentSha256) {
|
|
89
|
+
return { ok: false, reason: 'content hash mismatch (tampered content)' };
|
|
90
|
+
}
|
|
91
|
+
const frontmatterVersion = parseSkillVersion(env.content);
|
|
92
|
+
if (frontmatterVersion !== env.version) {
|
|
93
|
+
return { ok: false, reason: `version mismatch (envelope ${env.version} vs frontmatter ${frontmatterVersion ?? 'none'})` };
|
|
94
|
+
}
|
|
95
|
+
const msg = Buffer.from(signedMessage(env.version, env.contentSha256, env.signedAt), 'utf8');
|
|
96
|
+
let sig;
|
|
97
|
+
try {
|
|
98
|
+
sig = Buffer.from(env.signature, 'base64');
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return { ok: false, reason: 'signature is not valid base64' };
|
|
102
|
+
}
|
|
103
|
+
for (const keyB64 of keys) {
|
|
104
|
+
const pub = publicKeyFromRawB64(keyB64);
|
|
105
|
+
if (!pub)
|
|
106
|
+
continue;
|
|
107
|
+
try {
|
|
108
|
+
if (cryptoVerify(null, msg, pub, sig))
|
|
109
|
+
return { ok: true };
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
/* malformed key/sig for this candidate — try the next */
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return { ok: false, reason: 'signature does not verify under any trusted key' };
|
|
116
|
+
}
|
|
117
|
+
/** Last applied signedAt as epoch ms, 0 if none/unreadable (replay clock). */
|
|
118
|
+
export function readLastAppliedSignedAtMs() {
|
|
119
|
+
try {
|
|
120
|
+
const raw = readFileSync(OTA_STATE_PATH, 'utf-8');
|
|
121
|
+
const t = JSON.parse(raw).lastAppliedSignedAt;
|
|
122
|
+
const ms = t ? new Date(t).getTime() : 0;
|
|
123
|
+
return Number.isFinite(ms) ? ms : 0;
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
return 0;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/** Persist the signedAt of the just-applied update (monotonic replay clock). */
|
|
130
|
+
export function recordAppliedSignedAt(signedAt) {
|
|
131
|
+
try {
|
|
132
|
+
mkdirSync(join(homedir(), '.openclaw', 'workspace'), { recursive: true });
|
|
133
|
+
writeFileSync(OTA_STATE_PATH, JSON.stringify({ lastAppliedSignedAt: signedAt }), 'utf-8');
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
/* best-effort — if this fails the replay window is bounded to one process life */
|
|
137
|
+
}
|
|
138
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** Extract version from SKILL.md frontmatter */
|
|
2
|
+
export declare function parseSkillVersion(content: string): string | null;
|
|
3
|
+
/** Read current SKILL.md version from disk */
|
|
4
|
+
export declare function readLocalSkillVersion(): string | null;
|
|
5
|
+
/**
|
|
6
|
+
* Compare two semver strings.
|
|
7
|
+
* Returns 1 if a > b, -1 if a < b, 0 if equal.
|
|
8
|
+
* Non-semver inputs (or null) are treated as -Infinity so a valid semver always
|
|
9
|
+
* wins, which is the safe direction for "should I accept this OTA push?".
|
|
10
|
+
*/
|
|
11
|
+
export declare function compareSemver(a: string | null, b: string | null): number;
|
|
12
|
+
/** Validate SKILL.md content is well-formed */
|
|
13
|
+
export declare function validateSkillContent(content: string): {
|
|
14
|
+
valid: boolean;
|
|
15
|
+
version: string | null;
|
|
16
|
+
error?: string;
|
|
17
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// SKILL.md version parsing utility for OTA updates
|
|
2
|
+
import { readFileSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { homedir } from 'os';
|
|
5
|
+
const SKILL_MD_PATH = join(homedir(), '.openclaw', 'workspace', 'SKILL.md');
|
|
6
|
+
/** Extract version from SKILL.md frontmatter */
|
|
7
|
+
export function parseSkillVersion(content) {
|
|
8
|
+
const match = content.match(/^---[\s\S]*?version:\s*(\S+)[\s\S]*?---/);
|
|
9
|
+
return match ? match[1] : null;
|
|
10
|
+
}
|
|
11
|
+
/** Read current SKILL.md version from disk */
|
|
12
|
+
export function readLocalSkillVersion() {
|
|
13
|
+
try {
|
|
14
|
+
const content = readFileSync(SKILL_MD_PATH, 'utf-8');
|
|
15
|
+
return parseSkillVersion(content);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const MAX_SKILL_CONTENT_SIZE = 100_000; // 100KB
|
|
22
|
+
const SEMVER_REGEX = /^\d+\.\d+\.\d+$/;
|
|
23
|
+
/**
|
|
24
|
+
* Compare two semver strings.
|
|
25
|
+
* Returns 1 if a > b, -1 if a < b, 0 if equal.
|
|
26
|
+
* Non-semver inputs (or null) are treated as -Infinity so a valid semver always
|
|
27
|
+
* wins, which is the safe direction for "should I accept this OTA push?".
|
|
28
|
+
*/
|
|
29
|
+
export function compareSemver(a, b) {
|
|
30
|
+
const parse = (v) => {
|
|
31
|
+
if (!v || !SEMVER_REGEX.test(v))
|
|
32
|
+
return null;
|
|
33
|
+
const [maj, min, pat] = v.split('.').map(Number);
|
|
34
|
+
return [maj, min, pat];
|
|
35
|
+
};
|
|
36
|
+
const pa = parse(a);
|
|
37
|
+
const pb = parse(b);
|
|
38
|
+
if (!pa && !pb)
|
|
39
|
+
return 0;
|
|
40
|
+
if (!pa)
|
|
41
|
+
return -1;
|
|
42
|
+
if (!pb)
|
|
43
|
+
return 1;
|
|
44
|
+
for (let i = 0; i < 3; i++) {
|
|
45
|
+
if (pa[i] > pb[i])
|
|
46
|
+
return 1;
|
|
47
|
+
if (pa[i] < pb[i])
|
|
48
|
+
return -1;
|
|
49
|
+
}
|
|
50
|
+
return 0;
|
|
51
|
+
}
|
|
52
|
+
/** Validate SKILL.md content is well-formed */
|
|
53
|
+
export function validateSkillContent(content) {
|
|
54
|
+
if (content.length > MAX_SKILL_CONTENT_SIZE) {
|
|
55
|
+
return { valid: false, version: null, error: `Content too large (${content.length} bytes, max ${MAX_SKILL_CONTENT_SIZE})` };
|
|
56
|
+
}
|
|
57
|
+
if (!content.startsWith('---')) {
|
|
58
|
+
return { valid: false, version: null, error: 'Missing frontmatter delimiter' };
|
|
59
|
+
}
|
|
60
|
+
const version = parseSkillVersion(content);
|
|
61
|
+
if (!version) {
|
|
62
|
+
return { valid: false, version: null, error: 'No version in frontmatter' };
|
|
63
|
+
}
|
|
64
|
+
if (!SEMVER_REGEX.test(version)) {
|
|
65
|
+
return { valid: false, version, error: `Invalid version format: ${version} (expected semver x.y.z)` };
|
|
66
|
+
}
|
|
67
|
+
if (content.length < 100) {
|
|
68
|
+
return { valid: false, version, error: 'Content suspiciously short' };
|
|
69
|
+
}
|
|
70
|
+
return { valid: true, version };
|
|
71
|
+
}
|
|
@@ -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,47 @@
|
|
|
1
|
+
/** Thrown by `assertNotBanned` while the gate is closed. Carries the
|
|
2
|
+
* remaining cooldown so callers/telemetry can reason about it. Methods
|
|
3
|
+
* catch this in their existing catch block — it is NOT meant to escape
|
|
4
|
+
* the API layer with special handling; it degrades to the method's normal
|
|
5
|
+
* failure contract. */
|
|
6
|
+
export declare class BinanceBannedError extends Error {
|
|
7
|
+
readonly retryAfterMs: number;
|
|
8
|
+
constructor(retryAfterMs: number, context: string);
|
|
9
|
+
}
|
|
10
|
+
/** Thrown by the proactive weight pacer. Subclass of BinanceBannedError so
|
|
11
|
+
* every `instanceof BinanceBannedError` check and every method's existing
|
|
12
|
+
* catch keep working unchanged — it degrades to the same null/[]/throw
|
|
13
|
+
* contract (treated exactly like a transient fetch failure). The distinct
|
|
14
|
+
* name lets journal/telemetry tell prevention apart from a real IP ban. */
|
|
15
|
+
export declare class BinanceWeightPacedError extends BinanceBannedError {
|
|
16
|
+
constructor(retryAfterMs: number, context: string);
|
|
17
|
+
}
|
|
18
|
+
/** Fast pre-flight check. Call as the first line inside a Binance call's
|
|
19
|
+
* try-block. Throws `BinanceBannedError` (no network) while the gate is
|
|
20
|
+
* open. */
|
|
21
|
+
export declare function assertNotBanned(context: string): void;
|
|
22
|
+
/** Inspect a failed call's error and arm/extend the gate on a Binance
|
|
23
|
+
* rate-limit signal. Non-rate-limit errors are ignored (normal transient
|
|
24
|
+
* handling stays in the caller). Safe to call with any error shape. */
|
|
25
|
+
export declare function noteBinanceError(err: unknown): void;
|
|
26
|
+
/** Relax the soft-429 ladder after a clean call. (A hard 418 window is NOT
|
|
27
|
+
* shortened by this — only Binance's stated expiry clears it.) */
|
|
28
|
+
export declare function noteSuccess(): void;
|
|
29
|
+
/** Reconcile the local weight estimate against Binance truth from a response
|
|
30
|
+
* header (`x-mbx-used-weight-1m`). Best-effort: callers pass whatever header
|
|
31
|
+
* bag they have; absent/garbage values are ignored. The local estimate
|
|
32
|
+
* leads (counts in-flight calls Binance hasn't tallied yet), so we take the
|
|
33
|
+
* MAX within the window — never let a lagging header lower our guard. A
|
|
34
|
+
* header far BELOW the estimate means Binance's minute rolled; re-anchor the
|
|
35
|
+
* window to Binance's clock so we don't shed for a stale local total. */
|
|
36
|
+
export declare function noteResponseWeight(headers: Record<string, string> | undefined | null): void;
|
|
37
|
+
/** Test/diagnostic helper — current gate state. */
|
|
38
|
+
export declare function getBanGateState(): {
|
|
39
|
+
banUntilMs: number;
|
|
40
|
+
remainingMs: number;
|
|
41
|
+
rateLimitStep: number;
|
|
42
|
+
weightUsed: number;
|
|
43
|
+
weightCeiling: number;
|
|
44
|
+
cosmeticCeiling: number;
|
|
45
|
+
};
|
|
46
|
+
/** Test-only reset. Not used in production code paths. */
|
|
47
|
+
export declare function __resetBanGateForTests(): void;
|