@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.
- package/.gitignore +8 -0
- package/audit/mode-transition-audit.d.ts +11 -0
- package/audit/mode-transition-audit.js +29 -0
- package/balance-utils.d.ts +36 -0
- package/balance-utils.js +98 -0
- package/bridge/bridge.d.ts +109 -0
- package/bridge/bridge.js +1036 -0
- package/bridge/config.d.ts +43 -0
- package/bridge/config.js +176 -0
- package/bridge/connector.d.ts +52 -0
- package/bridge/connector.js +293 -0
- package/bridge/event-replay-buffer.d.ts +43 -0
- package/bridge/event-replay-buffer.js +109 -0
- package/bridge/gateway/event-parser.d.ts +209 -0
- package/bridge/gateway/event-parser.js +793 -0
- package/bridge/gateway/gateway-config.d.ts +39 -0
- package/bridge/gateway/gateway-config.js +86 -0
- package/bridge/gateway/gateway-http-client.d.ts +50 -0
- package/bridge/gateway/gateway-http-client.js +165 -0
- package/bridge/gateway/gateway-ws-client.d.ts +116 -0
- package/bridge/gateway/gateway-ws-client.js +417 -0
- package/bridge/gateway/poller.d.ts +146 -0
- package/bridge/gateway/poller.js +505 -0
- package/bridge/gateway/tool-discovery.d.ts +25 -0
- package/bridge/gateway/tool-discovery.js +198 -0
- package/bridge/index.d.ts +2 -0
- package/bridge/index.js +253 -0
- package/bridge/logger.d.ts +2 -0
- package/bridge/logger.js +2 -0
- package/bridge/provider.d.ts +156 -0
- package/bridge/provider.js +2 -0
- package/bridge/providers/emergency-commands.d.ts +54 -0
- package/bridge/providers/emergency-commands.js +235 -0
- package/bridge/providers/gateway.d.ts +322 -0
- package/bridge/providers/gateway.js +2302 -0
- package/bridge/providers/mock.d.ts +37 -0
- package/bridge/providers/mock.js +385 -0
- package/bridge/providers/onboarding-commands.d.ts +83 -0
- package/bridge/providers/onboarding-commands.js +213 -0
- package/bridge/providers/risk-calculator.d.ts +96 -0
- package/bridge/providers/risk-calculator.js +369 -0
- package/bridge/setup.d.ts +32 -0
- package/bridge/setup.js +226 -0
- package/bridge/types.d.ts +584 -0
- package/bridge/types.js +50 -0
- package/bridge/utils/reconnect.d.ts +6 -0
- package/bridge/utils/reconnect.js +6 -0
- package/bridge/utils/skill-signing.d.ts +51 -0
- package/bridge/utils/skill-signing.js +138 -0
- package/bridge/utils/skill-version.d.ts +17 -0
- package/bridge/utils/skill-version.js +74 -0
- package/ccxt/binance-ban-gate.d.ts +47 -0
- package/ccxt/binance-ban-gate.js +409 -0
- package/ccxt/binance-private.d.ts +325 -0
- package/ccxt/binance-private.js +1415 -0
- package/ccxt/binance-public.d.ts +18 -0
- package/ccxt/binance-public.js +147 -0
- package/config/agent-config-client.d.ts +55 -0
- package/config/agent-config-client.js +145 -0
- package/config/agent-config-poller.d.ts +25 -0
- package/config/agent-config-poller.js +100 -0
- package/config/brackets-config.d.ts +22 -0
- package/config/brackets-config.js +58 -0
- package/config/gate-store.d.ts +18 -0
- package/config/gate-store.js +61 -0
- package/config/plugin-config-io.d.ts +181 -0
- package/config/plugin-config-io.js +84 -0
- package/config/position-review-config.d.ts +35 -0
- package/config/position-review-config.js +105 -0
- package/config/tool-gate.d.ts +53 -0
- package/config/tool-gate.js +125 -0
- package/config/user-data-stream-config.d.ts +85 -0
- package/config/user-data-stream-config.js +224 -0
- package/connector-supervisor.d.ts +36 -0
- package/connector-supervisor.js +149 -0
- package/exchange-adapter.d.ts +49 -0
- package/exchange-adapter.js +4 -0
- package/index.d.ts +30 -0
- package/index.js +2030 -0
- package/ingest/pending-entry-metadata.d.ts +52 -0
- package/ingest/pending-entry-metadata.js +182 -0
- package/ingest/position-auto-capture.d.ts +98 -0
- package/ingest/position-auto-capture.js +394 -0
- package/ingest/position-decisions-client.d.ts +318 -0
- package/ingest/position-decisions-client.js +296 -0
- package/ingest/reconcile-db-vs-exchange.d.ts +13 -0
- package/ingest/reconcile-db-vs-exchange.js +114 -0
- package/ingest/reconciler-cleanup.d.ts +37 -0
- package/ingest/reconciler-cleanup.js +147 -0
- package/ingest/rest-gap-filler.d.ts +191 -0
- package/ingest/rest-gap-filler.js +565 -0
- package/ingest/touched-symbols-store.d.ts +25 -0
- package/ingest/touched-symbols-store.js +96 -0
- package/ingest/trade-store-client.d.ts +40 -0
- package/ingest/trade-store-client.js +125 -0
- package/ingest/ws-ingest.d.ts +43 -0
- package/ingest/ws-ingest.js +126 -0
- package/learning/setup-family.d.ts +21 -0
- package/learning/setup-family.js +103 -0
- package/lifecycle/install-signal-handlers.d.ts +33 -0
- package/lifecycle/install-signal-handlers.js +112 -0
- package/lifecycle/shutdown-coordinator.d.ts +43 -0
- package/lifecycle/shutdown-coordinator.js +131 -0
- package/live/bracket-id.d.ts +18 -0
- package/live/bracket-id.js +81 -0
- package/live/bracket-ledger.d.ts +54 -0
- package/live/bracket-ledger.js +267 -0
- package/live/bracket-manager.d.ts +82 -0
- package/live/bracket-manager.js +478 -0
- package/live/bracket-params.d.ts +22 -0
- package/live/bracket-params.js +124 -0
- package/live/bracket-reconciler.d.ts +95 -0
- package/live/bracket-reconciler.js +573 -0
- package/live/bracket-types.d.ts +102 -0
- package/live/bracket-types.js +8 -0
- package/live/deposit-tracker.d.ts +62 -0
- package/live/deposit-tracker.js +97 -0
- package/live/emergency-controls.d.ts +32 -0
- package/live/emergency-controls.js +226 -0
- package/live/exchange-errors.d.ts +12 -0
- package/live/exchange-errors.js +130 -0
- package/live/exchange-info-cache.d.ts +35 -0
- package/live/exchange-info-cache.js +119 -0
- package/live/fact-subscriber.d.ts +78 -0
- package/live/fact-subscriber.js +182 -0
- package/live/intent-journal.d.ts +42 -0
- package/live/intent-journal.js +122 -0
- package/live/listen-key-manager.d.ts +70 -0
- package/live/listen-key-manager.js +169 -0
- package/live/live-adapter.d.ts +264 -0
- package/live/live-adapter.js +1665 -0
- package/live/live-balance-enricher.d.ts +32 -0
- package/live/live-balance-enricher.js +104 -0
- package/live/live-bracket-api.d.ts +13 -0
- package/live/live-bracket-api.js +20 -0
- package/live/live-state-store.d.ts +194 -0
- package/live/live-state-store.js +450 -0
- package/live/local-signal-service.d.ts +57 -0
- package/live/local-signal-service.js +146 -0
- package/live/local-strategy-evaluator.d.ts +62 -0
- package/live/local-strategy-evaluator.js +127 -0
- package/live/microstructure-assembler.d.ts +54 -0
- package/live/microstructure-assembler.js +148 -0
- package/live/order-poller.d.ts +29 -0
- package/live/order-poller.js +125 -0
- package/live/position-state-store.d.ts +83 -0
- package/live/position-state-store.js +237 -0
- package/live/proposal-decision-listener.d.ts +64 -0
- package/live/proposal-decision-listener.js +288 -0
- package/live/proposal-manager.d.ts +76 -0
- package/live/proposal-manager.js +140 -0
- package/live/rate-limiter.d.ts +47 -0
- package/live/rate-limiter.js +159 -0
- package/live/reconciler.d.ts +39 -0
- package/live/reconciler.js +175 -0
- package/live/setup-buckets.d.ts +7 -0
- package/live/setup-buckets.js +33 -0
- package/live/slippage-tracker.d.ts +45 -0
- package/live/slippage-tracker.js +78 -0
- package/live/stop-watcher.d.ts +34 -0
- package/live/stop-watcher.js +158 -0
- package/live/user-data-active-probe.d.ts +54 -0
- package/live/user-data-active-probe.js +180 -0
- package/live/user-data-stream-controller.d.ts +200 -0
- package/live/user-data-stream-controller.js +579 -0
- package/live/user-data-stream-ws.d.ts +22 -0
- package/live/user-data-stream-ws.js +63 -0
- package/live/user-data-stream.d.ts +243 -0
- package/live/user-data-stream.js +704 -0
- package/logger.d.ts +2 -0
- package/logger.js +2 -0
- package/mfe.d.ts +21 -0
- package/mfe.js +68 -0
- package/onboarding/mode-ladder.d.ts +1 -0
- package/onboarding/mode-ladder.js +3 -0
- package/onboarding/runtime.d.ts +71 -0
- package/onboarding/runtime.js +153 -0
- package/openclaw.plugin.json +94 -0
- package/package.json +27 -0
- package/paper-adapter.d.ts +24 -0
- package/paper-adapter.js +91 -0
- package/persistence/state-manager.d.ts +42 -0
- package/persistence/state-manager.js +164 -0
- package/pinned-plan.d.ts +9 -0
- package/pinned-plan.js +23 -0
- package/risk/pre-trade-check.d.ts +38 -0
- package/risk/pre-trade-check.js +345 -0
- package/risk/pre-trade-types.d.ts +60 -0
- package/risk/pre-trade-types.js +3 -0
- package/scripts/assemble.mjs +114 -0
- package/shadow/shadow-tracker.d.ts +36 -0
- package/shadow/shadow-tracker.js +151 -0
- package/shadow/types.d.ts +42 -0
- package/shadow/types.js +20 -0
- package/shared/indicators-extended.d.ts +52 -0
- package/shared/indicators-extended.js +291 -0
- package/shared/indicators.d.ts +15 -0
- package/shared/indicators.js +114 -0
- package/signals/conditions/registry.d.ts +16 -0
- package/signals/conditions/registry.js +1274 -0
- package/signals/conditions/types.d.ts +1 -0
- package/signals/conditions/types.js +4 -0
- package/signals/direction-rules.d.ts +3 -0
- package/signals/direction-rules.js +24 -0
- package/signals/entry-rules.d.ts +6 -0
- package/signals/entry-rules.js +33 -0
- package/signals/serialize-context.d.ts +4 -0
- package/signals/serialize-context.js +39 -0
- package/signals/stop-rules.d.ts +3 -0
- package/signals/stop-rules.js +48 -0
- package/signals/strategy-adapter.d.ts +14 -0
- package/signals/strategy-adapter.js +122 -0
- package/signals/types.d.ts +1 -0
- package/signals/types.js +8 -0
- package/simulator/exchange-simulator.d.ts +93 -0
- package/simulator/exchange-simulator.js +684 -0
- package/simulator/fill-engine.d.ts +53 -0
- package/simulator/fill-engine.js +276 -0
- package/simulator/paper-market-feed.d.ts +26 -0
- package/simulator/paper-market-feed.js +104 -0
- package/simulator/realistic-fills.d.ts +59 -0
- package/simulator/realistic-fills.js +175 -0
- package/simulator/types.d.ts +219 -0
- package/simulator/types.js +43 -0
- package/skills/reefclaw/SKILL.md +97 -0
- package/strategy/builtin-strategies.d.ts +2 -0
- package/strategy/builtin-strategies.js +109 -0
- package/strategy/condition-registry.d.ts +3 -0
- package/strategy/condition-registry.js +153 -0
- package/strategy/evaluator.d.ts +67 -0
- package/strategy/evaluator.js +93 -0
- package/tools/assessment-validation.d.ts +118 -0
- package/tools/assessment-validation.js +415 -0
- package/tools/attach-brackets.d.ts +34 -0
- package/tools/attach-brackets.js +363 -0
- package/tools/audit-bracket-protection.d.ts +49 -0
- package/tools/audit-bracket-protection.js +527 -0
- package/tools/cancel-all-orders.d.ts +7 -0
- package/tools/cancel-all-orders.js +5 -0
- package/tools/cancel-order.d.ts +10 -0
- package/tools/cancel-order.js +14 -0
- package/tools/check-position-health.d.ts +46 -0
- package/tools/check-position-health.js +194 -0
- package/tools/clear-exchange-credentials.d.ts +24 -0
- package/tools/clear-exchange-credentials.js +70 -0
- package/tools/close-position.d.ts +22 -0
- package/tools/close-position.js +449 -0
- package/tools/create-order.d.ts +54 -0
- package/tools/create-order.js +338 -0
- package/tools/exit-gate.d.ts +58 -0
- package/tools/exit-gate.js +162 -0
- package/tools/fetch-balance.d.ts +5 -0
- package/tools/fetch-balance.js +4 -0
- package/tools/fetch-ohlcv.d.ts +11 -0
- package/tools/fetch-ohlcv.js +8 -0
- package/tools/fetch-open-orders.d.ts +7 -0
- package/tools/fetch-open-orders.js +4 -0
- package/tools/fetch-positions.d.ts +7 -0
- package/tools/fetch-positions.js +4 -0
- package/tools/fetch-ticker.d.ts +11 -0
- package/tools/fetch-ticker.js +5 -0
- package/tools/get-agent-profile.d.ts +4 -0
- package/tools/get-agent-profile.js +6 -0
- package/tools/get-analytics.d.ts +6 -0
- package/tools/get-analytics.js +7 -0
- package/tools/get-backtest.d.ts +12 -0
- package/tools/get-backtest.js +91 -0
- package/tools/get-basis.d.ts +7 -0
- package/tools/get-basis.js +7 -0
- package/tools/get-bracket-config.d.ts +11 -0
- package/tools/get-bracket-config.js +24 -0
- package/tools/get-cascade-risk.d.ts +7 -0
- package/tools/get-cascade-risk.js +8 -0
- package/tools/get-crypto-metrics.d.ts +18 -0
- package/tools/get-crypto-metrics.js +45 -0
- package/tools/get-cvd.d.ts +6 -0
- package/tools/get-cvd.js +6 -0
- package/tools/get-divergences.d.ts +6 -0
- package/tools/get-divergences.js +6 -0
- package/tools/get-funding-context.d.ts +6 -0
- package/tools/get-funding-context.js +16 -0
- package/tools/get-liquidation-levels.d.ts +7 -0
- package/tools/get-liquidation-levels.js +7 -0
- package/tools/get-liquidation-pulse.d.ts +9 -0
- package/tools/get-liquidation-pulse.js +22 -0
- package/tools/get-market-breadth.d.ts +6 -0
- package/tools/get-market-breadth.js +8 -0
- package/tools/get-market-intel.d.ts +19 -0
- package/tools/get-market-intel.js +116 -0
- package/tools/get-market-structure.d.ts +47 -0
- package/tools/get-market-structure.js +198 -0
- package/tools/get-my-mined-patterns.d.ts +20 -0
- package/tools/get-my-mined-patterns.js +61 -0
- package/tools/get-my-proposed-learnings.d.ts +20 -0
- package/tools/get-my-proposed-learnings.js +55 -0
- package/tools/get-my-recent-reviews.d.ts +22 -0
- package/tools/get-my-recent-reviews.js +66 -0
- package/tools/get-orderbook.d.ts +21 -0
- package/tools/get-orderbook.js +32 -0
- package/tools/get-pattern-scan.d.ts +7 -0
- package/tools/get-pattern-scan.js +8 -0
- package/tools/get-regime.d.ts +6 -0
- package/tools/get-regime.js +7 -0
- package/tools/get-relevant-learnings.d.ts +21 -0
- package/tools/get-relevant-learnings.js +65 -0
- package/tools/get-resting-liquidity.d.ts +6 -0
- package/tools/get-resting-liquidity.js +11 -0
- package/tools/get-risk-scenario.d.ts +29 -0
- package/tools/get-risk-scenario.js +47 -0
- package/tools/get-risk-summary.d.ts +51 -0
- package/tools/get-risk-summary.js +118 -0
- package/tools/get-sentiment.d.ts +4 -0
- package/tools/get-sentiment.js +6 -0
- package/tools/get-session-review.d.ts +7 -0
- package/tools/get-session-review.js +8 -0
- package/tools/get-setup-detail.d.ts +7 -0
- package/tools/get-setup-detail.js +303 -0
- package/tools/get-signals.d.ts +15 -0
- package/tools/get-signals.js +54 -0
- package/tools/get-sizing.d.ts +6 -0
- package/tools/get-sizing.js +6 -0
- package/tools/get-trade-feedback.d.ts +7 -0
- package/tools/get-trade-feedback.js +8 -0
- package/tools/get-trade-flow.d.ts +7 -0
- package/tools/get-trade-flow.js +7 -0
- package/tools/get-volume-analysis.d.ts +21 -0
- package/tools/get-volume-analysis.js +74 -0
- package/tools/get-volume-profile.d.ts +7 -0
- package/tools/get-volume-profile.js +7 -0
- package/tools/helpers.d.ts +25 -0
- package/tools/helpers.js +38 -0
- package/tools/intel-api.d.ts +14 -0
- package/tools/intel-api.js +52 -0
- package/tools/intel-cache.d.ts +25 -0
- package/tools/intel-cache.js +133 -0
- package/tools/list-strategies.d.ts +7 -0
- package/tools/list-strategies.js +6 -0
- package/tools/modify-stop.d.ts +17 -0
- package/tools/modify-stop.js +81 -0
- package/tools/modify-target.d.ts +17 -0
- package/tools/modify-target.js +71 -0
- package/tools/propose-learning.d.ts +22 -0
- package/tools/propose-learning.js +65 -0
- package/tools/query-review-outcomes.d.ts +30 -0
- package/tools/query-review-outcomes.js +64 -0
- package/tools/query-trades.d.ts +21 -0
- package/tools/query-trades.js +37 -0
- package/tools/record-position-reviews.d.ts +38 -0
- package/tools/record-position-reviews.js +147 -0
- package/tools/save-strategy.d.ts +16 -0
- package/tools/save-strategy.js +46 -0
- package/tools/scan-pairs.d.ts +18 -0
- package/tools/scan-pairs.js +220 -0
- package/tools/score-setup.d.ts +31 -0
- package/tools/score-setup.js +268 -0
- package/tools/set-bracket-requirement.d.ts +18 -0
- package/tools/set-bracket-requirement.js +81 -0
- package/tools/set-exchange-credentials.d.ts +25 -0
- package/tools/set-exchange-credentials.js +80 -0
- package/tools/set-trading-mode.d.ts +26 -0
- package/tools/set-trading-mode.js +135 -0
- package/tools/test-exchange-credentials.d.ts +16 -0
- package/tools/test-exchange-credentials.js +100 -0
- package/tools/toggle-strategy.d.ts +8 -0
- package/tools/toggle-strategy.js +8 -0
- package/trading-params-cache.d.ts +26 -0
- package/trading-params-cache.js +52 -0
- package/types.d.ts +110 -0
- package/types.js +7 -0
- package/util/plugin-paths.d.ts +3 -0
- package/util/plugin-paths.js +15 -0
package/.gitignore
ADDED
|
@@ -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;
|
package/balance-utils.js
ADDED
|
@@ -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
|
+
}
|