@nemesis-oss/binance-sdk 2.0.0 → 3.0.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/dist/index.d.ts CHANGED
@@ -1,309 +1,1912 @@
1
- import { F as FuturesMarket, B as BinanceClient } from './index-BO27qOb5.js';
2
- export { A as Account, a as AccountAsset, b as AccountAssetSchema, c as AccountPosition, d as AccountPositionSchema, e as AccountSchema, f as AccountSnapshot, g as AccountSnapshotSchema, h as AggTrade, i as AggTradeSchema, j as AggTradesResponseSchema, k as AlgoOrder, l as AlgoOrderResponseSchema, m as AlgoOrderSchema, n as AlgoOrdersResponseSchema, o as ApiKeyPermissions, p as ApiKeyPermissionsSchema, q as ApiTradingStatus, r as ApiTradingStatusSchema, s as AssetDetail, t as AssetDetailSchema, u as AuthMode, v as AvgPrice, w as AvgPriceSchema, x as Balance, y as BalanceSchema, z as BalancesResponseSchema, C as BaseWS, D as BaseWSOptions, E as BatchOrdersItem, G as BatchOrdersItemSchema, H as BatchOrdersResponseSchema, I as BinanceClientOptions, J as BookTicker, K as BookTickerSchema, L as BorrowRepayParams, M as BorrowRepayParamsSchema, N as BorrowRepayRecordEntry, O as BorrowRepayRecordEntrySchema, P as BorrowRepayRecordResponse, Q as BorrowRepayRecordResponseSchema, R as BorrowRepayResult, S as BorrowRepayResultSchema, T as BracketOrderParams, U as ClosePositionParams, V as CoinMAccount, W as CoinMAccountAsset, X as CoinMAccountAssetSchema, Y as CoinMAccountInfo, Z as CoinMAccountPosition, _ as CoinMAccountPositionSchema, $ as CoinMAccountSchema, a0 as CoinMBalance, a1 as CoinMBalanceResponseSchema, a2 as CoinMBalanceSchema, a3 as CoinMCommissionRate, a4 as CoinMCommissionRateSchema, a5 as CoinMContractType, a6 as CoinMCreateOrderParams, a7 as CoinMCreateOrderParamsSchema, a8 as CoinMIncome, a9 as CoinMIncomeHistoryResponseSchema, aa as CoinMIncomeSchema, ab as CoinMLeverageBracket, ac as CoinMLeverageBracketResponseSchema, ad as CoinMLeverageBracketSchema, ae as CoinMLeverageChange, af as CoinMLeverageChangeSchema, ag as CoinMMarginTypeChange, ah as CoinMMarginTypeChangeSchema, ai as CoinMMarkPriceSpeed, aj as CoinMMarket, ak as CoinMMarketWS, al as CoinMOpenInterestHistEntry, am as CoinMOpenInterestHistEntrySchema, an as CoinMOpenInterestHistSchema, ao as CoinMOrder, ap as CoinMOrderResponseSchema, aq as CoinMOrderSchema, ar as CoinMOrdersResponseSchema, as as CoinMPositionMarginChange, at as CoinMPositionMarginChangeSchema, au as CoinMPositionMode, av as CoinMPositionModeSchema, aw as CoinMPositionRisk, ax as CoinMPositionRiskResponseSchema, ay as CoinMPositionRiskSchema, az as CoinMTrading, aA as CoinMUserDataStream, aB as CoinMUserTrade, aC as CoinMUserTradeSchema, aD as CoinMUserTradesResponseSchema, aE as CoinMUserWS, aF as CoinMUserWSOptions, aG as CommissionRate, aH as CommissionRateSchema, aI as ContractType, aJ as CountdownCancelAll, aK as CountdownCancelAllSchema, aL as CreateOrderParams, aM as CreateOrderParamsSchema, aN as CrossMarginAccount, aO as CrossMarginAccountSchema, aP as DepositAddress, aQ as DepositAddressSchema, aR as DepositHistoryEntry, aS as DepositHistoryEntrySchema, aT as DepositHistoryResponseSchema, aU as DepthSnapshot, aV as DepthSnapshotSchema, aW as DustConversionResult, aX as DustConversionResultSchema, aY as DustLogEntry, aZ as DustLogEntrySchema, a_ as DustLogResponse, a$ as DustLogResponseSchema, b0 as ExchangeInfo, b1 as ExchangeInfoSchema, b2 as ExchangeSymbol, b3 as ExchangeSymbolSchema, b4 as FeeBurnStatus, b5 as FeeBurnStatusSchema, b6 as FundingAsset, b7 as FundingAssetSchema, b8 as FundingAssetsResponseSchema, b9 as FundingRate, ba as FundingRateHistorySchema, bb as FundingRateSchema, bc as FuturesAccount, bd as FuturesData, be as FuturesDataEndpoints, bf as FuturesMarketWS, bg as FuturesOps, bh as FuturesToolkit, bi as FuturesTrading, bj as FuturesUserWS, bk as FuturesUserWSOptions, bl as HttpClient, bm as HttpClientOptions, bn as HttpMethod, bo as Income, bp as IncomeHistoryResponseSchema, bq as IncomeSchema, br as IsolatedMarginAccount, bs as IsolatedMarginAccountSchema, bt as IsolatedMarginAsset, bu as IsolatedMarginAssetSchema, bv as IsolatedMarginSymbol, bw as IsolatedMarginSymbolSchema, bx as IsolatedTransferParams, by as IsolatedTransferParamsSchema, bz as Kline, bA as KlineInterval, bB as KlineIntervalSchema, bC as KlineSchema, bD as KlinesResponseSchema, bE as LeverageBracket, bF as LeverageBracketResponseSchema, bG as LeverageBracketSchema, bH as LeverageChange, bI as LeverageChangeSchema, bJ as ListenKey, bK as ListenKeySchema, bL as LongShortRatioEntry, bM as LongShortRatioEntrySchema, bN as LongShortRatioSchema, bO as MarginAccount, bP as MarginAssetBalance, bQ as MarginAssetBalanceSchema, bR as MarginCreateOrderParams, bS as MarginCreateOrderParamsSchema, bT as MarginForceLiquidationEntry, bU as MarginForceLiquidationEntrySchema, bV as MarginForceLiquidationResponse, bW as MarginForceLiquidationResponseSchema, bX as MarginInterestHistoryEntry, bY as MarginInterestHistoryEntrySchema, bZ as MarginInterestHistoryResponse, b_ as MarginInterestHistoryResponseSchema, b$ as MarginOrder, c0 as MarginOrderResponseSchema, c1 as MarginOrderSchema, c2 as MarginOrdersResponseSchema, c3 as MarginPriceIndex, c4 as MarginPriceIndexSchema, c5 as MarginTrade, c6 as MarginTradeSchema, c7 as MarginTradesResponseSchema, c8 as MarginTrading, c9 as MarginTransferResult, ca as MarginTransferResultSchema, cb as MarginTypeChange, cc as MarginTypeChangeSchema, cd as MarkPriceSpeed, ce as MarketDataBase, cf as MaxBorrowable, cg as MaxBorrowableSchema, ch as MaxTransferable, ci as MaxTransferableSchema, cj as ModifyOrderParams, ck as ModifyOrderParamsSchema, cl as MultiAssetsMargin, cm as MultiAssetsMarginSchema, cn as NewOrderAck, co as NewOrderAckSchema, cp as OpenInterest, cq as OpenInterestHistEntry, cr as OpenInterestHistEntrySchema, cs as OpenInterestHistSchema, ct as OpenInterestSchema, cu as Order, cv as OrderModifyHistoryEntry, cw as OrderModifyHistoryEntrySchema, cx as OrderModifyHistorySchema, cy as OrderResponseSchema, cz as OrderSchema, cA as OrdersResponseSchema, cB as PositionMarginChange, cC as PositionMarginChangeSchema, cD as PositionMarginHistoryEntry, cE as PositionMarginHistoryEntrySchema, cF as PositionMarginHistorySchema, cG as PositionMode, cH as PositionModeSchema, cI as PositionRisk, cJ as PositionRiskResponseSchema, cK as PositionRiskSchema, cL as PositionSizing, cM as PremiumIndex, cN as PremiumIndexSchema, cO as RateLimitOrder, cP as RateLimitOrderResponseSchema, cQ as RateLimitOrderSchema, cR as RateLimitTracker, cS as RateLimitTrackerOptions, cT as RateLimitUsage, cU as SignatureAlgorithm, cV as Signer, cW as SignerOptions, cX as SizePositionParams, cY as SpotAccount, cZ as SpotAccountInfo, c_ as SpotAccountSchema, c$ as SpotBalance, d0 as SpotBalanceSchema, d1 as SpotBalanceUpdate, d2 as SpotBalanceUpdateSchema, d3 as SpotExecutionReport, d4 as SpotExecutionReportSchema, d5 as SpotListStatus, d6 as SpotListStatusSchema, d7 as SpotMarket, d8 as SpotMarketWS, d9 as SpotOCOOrderAck, da as SpotOCOOrderAckResponseSchema, db as SpotOCOOrderAckSchema, dc as SpotOCOOrdersResponseSchema, dd as SpotOrder, de as SpotOrderResponseSchema, df as SpotOrderSchema, dg as SpotOrdersResponseSchema, dh as SpotOutboundAccountPosition, di as SpotOutboundAccountPositionSchema, dj as SpotTrade, dk as SpotTradeSchema, dl as SpotTradesResponseSchema, dm as SpotTrading, dn as SpotUserDataEvent, dp as SpotUserDataStream, dq as SpotUserWS, dr as SpotUserWSOptions, ds as SpotWsApi, dt as SpotWsApiOptions, du as SubAccount, dv as SubAccountDepositAddress, dw as SubAccountDepositAddressSchema, dx as SubAccountDepositHistoryEntry, dy as SubAccountDepositHistoryEntrySchema, dz as SubAccountDepositHistoryResponseSchema, dA as SubAccountEnableResult, dB as SubAccountEnableResultSchema, dC as SubAccountEntry, dD as SubAccountEntrySchema, dE as SubAccountFuturesSummary, dF as SubAccountFuturesSummarySchema, dG as SubAccountListResponse, dH as SubAccountListResponseSchema, dI as SubAccountMarginAccount, dJ as SubAccountMarginAccountSchema, dK as SubAccountSpotAsset, dL as SubAccountSpotAssetSchema, dM as SubAccountSpotAssetsResponse, dN as SubAccountSpotAssetsResponseSchema, dO as SubAccountSpotSummary, dP as SubAccountSpotSummaryEntry, dQ as SubAccountSpotSummaryEntrySchema, dR as SubAccountSpotSummarySchema, dS as SubAccountStatus, dT as SubAccountStatusResponseSchema, dU as SubAccountStatusSchema, dV as SubAccountUniversalTransferEntry, dW as SubAccountUniversalTransferEntrySchema, dX as SubAccountUniversalTransferHistoryResponse, dY as SubAccountUniversalTransferHistoryResponseSchema, dZ as SubAccountUniversalTransferParams, d_ as SubAccountUniversalTransferParamsSchema, d$ as SubAccountUniversalTransferResult, e0 as SubAccountUniversalTransferResultSchema, e1 as SymbolRules, e2 as TakerLongShortRatioEntry, e3 as TakerLongShortRatioEntrySchema, e4 as TakerLongShortRatioSchema, e5 as Ticker24hr, e6 as Ticker24hrSchema, e7 as TickerPrice, e8 as TickerPriceSchema, e9 as ToolContext, ea as ToolDefinition, eb as Trade, ec as TradeFeeEntry, ed as TradeFeeEntrySchema, ee as TradeFeeResponseSchema, ef as TradeSchema, eg as TradesResponseSchema, eh as TradingPolicy, ei as TradingPolicyOptions, ej as TransferType, ek as TransferTypeSchema, el as UniversalTransferHistoryEntry, em as UniversalTransferHistoryEntrySchema, en as UniversalTransferHistoryResponse, eo as UniversalTransferHistoryResponseSchema, ep as UniversalTransferParams, eq as UniversalTransferParamsSchema, er as UniversalTransferResult, es as UniversalTransferResultSchema, et as UserAsset, eu as UserAssetSchema, ev as UserAssetsResponseSchema, ew as UserDataAccountUpdate, ex as UserDataAccountUpdateSchema, ey as UserDataEvent, ez as UserDataMarginCall, eA as UserDataMarginCallSchema, eB as UserDataOrderTradeUpdate, eC as UserDataOrderTradeUpdateSchema, eD as UserDataStream, eE as UserTrade, eF as UserTradeSchema, eG as UserTradesResponseSchema, eH as VirtualSubAccountResult, eI as VirtualSubAccountResultSchema, eJ as Wallet, eK as WithdrawHistoryEntry, eL as WithdrawHistoryEntrySchema, eM as WithdrawHistoryResponseSchema, eN as WithdrawParams, eO as WithdrawParamsSchema, eP as WithdrawResult, eQ as WithdrawResultSchema, eR as WsApi, eS as WsApiOptions, eT as WsApiResponse, eU as WsApiResponseSchema, eV as accountTools, eW as createFuturesToolkit, eX as createPaperContext, eY as derivedTools, eZ as floorToStep, e_ as formatToDecimals, e$ as getBufferedWsEvents, f0 as marketDataTools, f1 as paperTools, f2 as parseSpotUserDataEvent, f3 as parseUserDataEvent, f4 as roundToStep, f5 as spotTools, f6 as stepDecimals, f7 as symbolRulesFrom, f8 as textResult, f9 as toAnthropicTool, fa as toJsonSchema, fb as toMCPTool, fc as toOpenAITool, fd as toToolList, fe as toolkitToFormats, ff as tradingTools, fg as wsTools } from './index-BO27qOb5.js';
3
- import { z } from 'zod';
1
+ import { B as BinanceClient, a as BinanceClientOptions, C as CoreContext, E as ExecutionAdapter, P as PaperTradingEngine, b as CreateOrderParams, O as OrderKey, c as OrderShape, U as UserStreamLike, d as ExecutionReportShape, e as ExecutionFill, f as EventBus, W as WsConnection, g as WsConnectionOptions, h as ExecutionManager, i as BookLevel, j as OrderBookMetrics, D as DiffInput, k as BookSnapshotInput, l as UsdmSurface, S as SpotSurface, m as CoinMSurface, n as WsFamily, R as ReconnectPolicy, F as FuturesMarketWS, o as SpotMarketWS, p as CoinMMarketWS, q as WsConnectionStats, r as SubscribeOptions, s as Subscription, t as PaperTradingOptions, u as FuturesToolkitOptions } from './index-C06A22Dz.js';
2
+ export { A as Account, v as AccountAsset, w as AccountAssetSchema, x as AccountPosition, y as AccountPositionSchema, z as AccountSchema, G as AccountSnapshot, H as AccountSnapshotSchema, I as AggTrade, J as AggTradeSchema, K as AggTradesResponseSchema, L as AlgoOrder, M as AlgoOrderResponseSchema, N as AlgoOrderSchema, Q as AlgoOrdersResponseSchema, T as ApiKeyPermissions, V as ApiKeyPermissionsSchema, X as ApiTradingStatus, Y as ApiTradingStatusSchema, Z as AssetDetail, _ as AssetDetailSchema, $ as AuditAction, a0 as AuditOutcome, a1 as AuditRecord, a2 as AuditSink, a3 as AuthMode, a4 as AvgPrice, a5 as AvgPriceSchema, a6 as Balance, a7 as BalanceSchema, a8 as BalancesResponseSchema, a9 as BaseWS, aa as BaseWSOptions, ab as BatchOrdersItem, ac as BatchOrdersItemSchema, ad as BatchOrdersResponseSchema, ae as BinanceUsdmFeeModel, af as BookTicker, ag as BookTickerSchema, ah as BookView, ai as BorrowRepayParams, aj as BorrowRepayParamsSchema, ak as BorrowRepayRecordEntry, al as BorrowRepayRecordEntrySchema, am as BorrowRepayRecordResponse, an as BorrowRepayRecordResponseSchema, ao as BorrowRepayResult, ap as BorrowRepayResultSchema, aq as BracketOrderParams, ar as CircuitBreakerState, as as ClosePositionParams, at as CoinMAccount, au as CoinMAccountAsset, av as CoinMAccountAssetSchema, aw as CoinMAccountInfo, ax as CoinMAccountPosition, ay as CoinMAccountPositionSchema, az as CoinMAccountSchema, aA as CoinMBalance, aB as CoinMBalanceResponseSchema, aC as CoinMBalanceSchema, aD as CoinMCommissionRate, aE as CoinMCommissionRateSchema, aF as CoinMContractType, aG as CoinMCreateOrderParams, aH as CoinMCreateOrderParamsSchema, aI as CoinMIncome, aJ as CoinMIncomeHistoryResponseSchema, aK as CoinMIncomeSchema, aL as CoinMLeverageBracket, aM as CoinMLeverageBracketResponseSchema, aN as CoinMLeverageBracketSchema, aO as CoinMLeverageChange, aP as CoinMLeverageChangeSchema, aQ as CoinMMarginTypeChange, aR as CoinMMarginTypeChangeSchema, aS as CoinMMarkPriceSpeed, aT as CoinMMarket, aU as CoinMOpenInterestHistEntry, aV as CoinMOpenInterestHistEntrySchema, aW as CoinMOpenInterestHistSchema, aX as CoinMOrder, aY as CoinMOrderResponseSchema, aZ as CoinMOrderSchema, a_ as CoinMOrdersResponseSchema, a$ as CoinMPositionMarginChange, b0 as CoinMPositionMarginChangeSchema, b1 as CoinMPositionMode, b2 as CoinMPositionModeSchema, b3 as CoinMPositionRisk, b4 as CoinMPositionRiskResponseSchema, b5 as CoinMPositionRiskSchema, b6 as CoinMTrading, b7 as CoinMUserDataStream, b8 as CoinMUserTrade, b9 as CoinMUserTradeSchema, ba as CoinMUserTradesResponseSchema, bb as CoinMUserWS, bc as CoinMUserWSOptions, bd as CommissionRate, be as CommissionRateSchema, bf as CompositeModel, bg as ContractType, bh as CoreTransportOptions, bi as CountdownCancelAll, bj as CountdownCancelAllSchema, bk as CreateOrderParamsSchema, bl as Credentials, bm as CrossMarginAccount, bn as CrossMarginAccountSchema, bo as Decimal, bp as DecimalInput, bq as DepositAddress, br as DepositAddressSchema, bs as DepositHistoryEntry, bt as DepositHistoryEntrySchema, bu as DepositHistoryResponseSchema, bv as DepthSnapshot, bw as DepthSnapshotSchema, bx as DustConversionResult, by as DustConversionResultSchema, bz as DustLogEntry, bA as DustLogEntrySchema, bB as DustLogResponse, bC as DustLogResponseSchema, bD as Endpoints, bE as Environment, bF as EventBusOptions, bG as ExchangeInfo, bH as ExchangeInfoSchema, bI as ExchangeSymbol, bJ as ExchangeSymbolSchema, bK as Execution, bL as ExecutionBackend, bM as ExecutionContext, bN as ExecutionGateway, bO as ExecutionGatewayOptions, bP as ExecutionManagerOptions, bQ as ExecutionModel, bR as ExecutionQuote, bS as ExecutionUnknownError, bT as FanOutAuditSink, bU as FeeBurnStatus, bV as FeeBurnStatusSchema, bW as FeeModel, bX as FeeQuote, bY as FundingAsset, bZ as FundingAssetSchema, b_ as FundingAssetsResponseSchema, b$ as FundingRate, c0 as FundingRateHistorySchema, c1 as FundingRateSchema, c2 as FuturesAccount, c3 as FuturesData, c4 as FuturesDataEndpoints, c5 as FuturesExecutionAdapter, c6 as FuturesMarket, c7 as FuturesNamespace, c8 as FuturesOps, c9 as FuturesToolkit, ca as FuturesTrading, cb as FuturesUserWS, cc as FuturesUserWSOptions, cd as FuturesWsApiClient, ce as HttpClient, cf as HttpClientOptions, cg as HttpMethod, ch as InMemoryAuditSink, ci as Income, cj as IncomeHistoryResponseSchema, ck as IncomeSchema, cl as InstantFillModel, cm as IsolatedMarginAccount, cn as IsolatedMarginAccountSchema, co as IsolatedMarginAsset, cp as IsolatedMarginAssetSchema, cq as IsolatedMarginSymbol, cr as IsolatedMarginSymbolSchema, cs as IsolatedTransferParams, ct as IsolatedTransferParamsSchema, cu as Kline, cv as KlineInterval, cw as KlineIntervalSchema, cx as KlineSchema, cy as KlinesResponseSchema, cz as LatencyModel, cA as LeverageBracket, cB as LeverageBracketResponseSchema, cC as LeverageBracketSchema, cD as LeverageChange, cE as LeverageChangeSchema, cF as ListenKey, cG as ListenKeySchema, cH as LongShortRatioEntry, cI as LongShortRatioEntrySchema, cJ as LongShortRatioSchema, cK as MarginAccount, cL as MarginAssetBalance, cM as MarginAssetBalanceSchema, cN as MarginCreateOrderParams, cO as MarginCreateOrderParamsSchema, cP as MarginForceLiquidationEntry, cQ as MarginForceLiquidationEntrySchema, cR as MarginForceLiquidationResponse, cS as MarginForceLiquidationResponseSchema, cT as MarginInterestHistoryEntry, cU as MarginInterestHistoryEntrySchema, cV as MarginInterestHistoryResponse, cW as MarginInterestHistoryResponseSchema, cX as MarginNamespace, cY as MarginOrder, cZ as MarginOrderResponseSchema, c_ as MarginOrderSchema, c$ as MarginOrdersResponseSchema, d0 as MarginPriceIndex, d1 as MarginPriceIndexSchema, d2 as MarginTrade, d3 as MarginTradeSchema, d4 as MarginTradesResponseSchema, d5 as MarginTrading, d6 as MarginTransferResult, d7 as MarginTransferResultSchema, d8 as MarginTypeChange, d9 as MarginTypeChangeSchema, da as MarkPriceSpeed, db as MarketDataBase, dc as MaxBorrowable, dd as MaxBorrowableSchema, de as MaxTransferable, df as MaxTransferableSchema, dg as ModifyOrderParams, dh as ModifyOrderParamsSchema, di as MultiAssetsMargin, dj as MultiAssetsMarginSchema, dk as NewOrderAck, dl as NewOrderAckSchema, dm as OpenInterest, dn as OpenInterestHistEntry, dp as OpenInterestHistEntrySchema, dq as OpenInterestHistSchema, dr as OpenInterestSchema, ds as Order, dt as OrderBook, du as OrderBookEngine, dv as OrderBookEngineOptions, dw as OrderBookModel, dx as OrderModifyHistoryEntry, dy as OrderModifyHistoryEntrySchema, dz as OrderModifyHistorySchema, dA as OrderResponseSchema, dB as OrderSchema, dC as OrdersResponseSchema, dD as PaperAccount, dE as PaperOrder, dF as PaperPosition, dG as PaperPositionSide, dH as PartialFillModel, dI as PositionMarginChange, dJ as PositionMarginChangeSchema, dK as PositionMarginHistoryEntry, dL as PositionMarginHistoryEntrySchema, dM as PositionMarginHistorySchema, dN as PositionMode, dO as PositionModeSchema, dP as PositionRisk, dQ as PositionRiskResponseSchema, dR as PositionRiskSchema, dS as PositionSizing, dT as PremiumIndex, dU as PremiumIndexSchema, dV as RateLimitOrder, dW as RateLimitOrderResponseSchema, dX as RateLimitOrderSchema, dY as RateLimitTracker, dZ as RateLimitTrackerOptions, d_ as RateLimitUsage, d$ as RawLevel, e0 as ReconciliationState, e1 as RestHost, e2 as RetryPolicy, e3 as RiskGateway, e4 as RiskGatewayOptions, e5 as RiskStatus, e6 as SdkEvent, e7 as SdkEventListener, e8 as SdkLogger, e9 as SignatureAlgorithm, ea as Signer, eb as SignerOptions, ec as SizePositionParams, ed as SlippageModel, ee as SpotAccount, ef as SpotAccountInfo, eg as SpotAccountSchema, eh as SpotBalance, ei as SpotBalanceSchema, ej as SpotBalanceUpdate, ek as SpotBalanceUpdateSchema, el as SpotExecutionAdapter, em as SpotExecutionReport, en as SpotExecutionReportSchema, eo as SpotListStatus, ep as SpotListStatusSchema, eq as SpotMarket, er as SpotOCOOrderAck, es as SpotOCOOrderAckResponseSchema, et as SpotOCOOrderAckSchema, eu as SpotOCOOrdersResponseSchema, ev as SpotOrder, ew as SpotOrderResponseSchema, ex as SpotOrderSchema, ey as SpotOrdersResponseSchema, ez as SpotOutboundAccountPosition, eA as SpotOutboundAccountPositionSchema, eB as SpotTrade, eC as SpotTradeSchema, eD as SpotTradesResponseSchema, eE as SpotTrading, eF as SpotUserDataEvent, eG as SpotUserDataStream, eH as SpotUserWS, eI as SpotUserWSOptions, eJ as SpotWsApi, eK as SpotWsApiClient, eL as SpotWsApiOptions, eM as StreamAuditSink, eN as SubAccount, eO as SubAccountDepositAddress, eP as SubAccountDepositAddressSchema, eQ as SubAccountDepositHistoryEntry, eR as SubAccountDepositHistoryEntrySchema, eS as SubAccountDepositHistoryResponseSchema, eT as SubAccountEnableResult, eU as SubAccountEnableResultSchema, eV as SubAccountEntry, eW as SubAccountEntrySchema, eX as SubAccountFuturesSummary, eY as SubAccountFuturesSummarySchema, eZ as SubAccountListResponse, e_ as SubAccountListResponseSchema, e$ as SubAccountMarginAccount, f0 as SubAccountMarginAccountSchema, f1 as SubAccountSpotAsset, f2 as SubAccountSpotAssetSchema, f3 as SubAccountSpotAssetsResponse, f4 as SubAccountSpotAssetsResponseSchema, f5 as SubAccountSpotSummary, f6 as SubAccountSpotSummaryEntry, f7 as SubAccountSpotSummaryEntrySchema, f8 as SubAccountSpotSummarySchema, f9 as SubAccountStatus, fa as SubAccountStatusResponseSchema, fb as SubAccountStatusSchema, fc as SubAccountUniversalTransferEntry, fd as SubAccountUniversalTransferEntrySchema, fe as SubAccountUniversalTransferHistoryResponse, ff as SubAccountUniversalTransferHistoryResponseSchema, fg as SubAccountUniversalTransferParams, fh as SubAccountUniversalTransferParamsSchema, fi as SubAccountUniversalTransferResult, fj as SubAccountUniversalTransferResultSchema, fk as SubscriptionState, fl as SymbolRules, fm as TakerLongShortRatioEntry, fn as TakerLongShortRatioEntrySchema, fo as TakerLongShortRatioSchema, fp as TakerMakerFeeModel, fq as Ticker24hr, fr as Ticker24hrSchema, fs as TickerPrice, ft as TickerPriceSchema, fu as ToolContext, fv as ToolDefinition, fw as Trade, fx as TradeFeeEntry, fy as TradeFeeEntrySchema, fz as TradeFeeResponseSchema, fA as TradeSchema, fB as TradesResponseSchema, fC as TradingPolicy, fD as TradingPolicyOptions, fE as TransferType, fF as TransferTypeSchema, fG as UniversalTransferHistoryEntry, fH as UniversalTransferHistoryEntrySchema, fI as UniversalTransferHistoryResponse, fJ as UniversalTransferHistoryResponseSchema, fK as UniversalTransferParams, fL as UniversalTransferParamsSchema, fM as UniversalTransferResult, fN as UniversalTransferResultSchema, fO as UserAsset, fP as UserAssetSchema, fQ as UserAssetsResponseSchema, fR as UserDataAccountUpdate, fS as UserDataAccountUpdateSchema, fT as UserDataEvent, fU as UserDataMarginCall, fV as UserDataMarginCallSchema, fW as UserDataOrderTradeUpdate, fX as UserDataOrderTradeUpdateSchema, fY as UserDataStream, fZ as UserTrade, f_ as UserTradeSchema, f$ as UserTradesResponseSchema, g0 as VirtualSubAccountResult, g1 as VirtualSubAccountResultSchema, g2 as WS_FAMILY_LIMITS, g3 as WS_PLATFORM_DEFAULTS, g4 as Wallet, g5 as WithdrawHistoryEntry, g6 as WithdrawHistoryEntrySchema, g7 as WithdrawHistoryResponseSchema, g8 as WithdrawParams, g9 as WithdrawParamsSchema, ga as WithdrawResult, gb as WithdrawResultSchema, gc as WsAggTradePayload, gd as WsAggTradePayloadSchema, ge as WsApi, gf as WsApiClient, gg as WsApiClientOptions, gh as WsApiClientState, gi as WsApiOptions, gj as WsApiResponse, gk as WsApiResponseSchema, gl as WsApiSurface, gm as WsAssetIndexPayload, gn as WsAssetIndexPayloadSchema, go as WsBookTickerPayload, gp as WsBookTickerPayloadSchema, gq as WsCompositeIndexPayload, gr as WsCompositeIndexPayloadSchema, gs as WsConnectionState, gt as WsDepthUpdatePayload, gu as WsDepthUpdatePayloadSchema, gv as WsFamilyLimits, gw as WsFamilyStreams, gx as WsForceOrderPayload, gy as WsForceOrderPayloadSchema, gz as WsKlinePayload, gA as WsKlinePayloadSchema, gB as WsMarkPricePayload, gC as WsMarkPricePayloadSchema, gD as WsMiniTickerPayload, gE as WsMiniTickerPayloadSchema, gF as WsPlatform, gG as WsPlatformOptions, gH as WsPlatformStats, gI as WsRequestOptions, gJ as WsRollingWindowTickerPayload, gK as WsRollingWindowTickerPayloadSchema, gL as WsSpotAvgPricePayload, gM as WsSpotAvgPricePayloadSchema, gN as WsStreamPayload, gO as WsTicker24hrPayload, gP as WsTicker24hrPayloadSchema, gQ as WsTradePayload, gR as WsTradePayloadSchema, gS as accountTools, gT as auditRecordFromExecution, gU as createFuturesToolkit, gV as createPaperContext, gW as createWsPlatform, gX as dec, gY as derivedTools, gZ as executionTools, g_ as familyLimits, g$ as floorToStep, h0 as formatToDecimals, h1 as forwardEventsToLogger, h2 as getBufferedWsEvents, h3 as isExecutionAdapter, h4 as marketDataTools, h5 as paperTools, h6 as parseSpotUserDataEvent, h7 as parseUserDataEvent, h8 as parseWsPayload, h9 as resolveEnvironment, ha as roundToStep, hb as spotTools, hc as stepDecimals, hd as sum, he as symbolRulesFrom, hf as textResult, hg as toAnthropicTool, hh as toJsonSchema, hi as toMCPTool, hj as toOpenAITool, hk as toToolList, hl as toolkitToFormats, hm as tradingTools, hn as vwap, ho as wsTools } from './index-C06A22Dz.js';
3
+ import { EventEmitter } from 'node:events';
4
+ import WebSocket from 'ws';
4
5
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
5
6
  import 'axios';
6
- import 'node:events';
7
-
8
- type Environment = 'live' | 'testnet' | 'demo';
9
- interface Endpoints {
10
- restRoot: string;
11
- restFapi: string;
12
- restFuturesData: string;
13
- restSpot: string;
14
- restApiRoot: string;
15
- restDapiRoot: string;
16
- restDapi: string;
17
- wsMarket: string;
18
- wsUser: string;
19
- wsApi: string;
20
- wsSpotMarket: string;
21
- wsSpotUser: string;
22
- wsSpotApi: string;
23
- wsDapiMarket: string;
24
- wsDapiUser: string;
25
- }
26
- declare function resolveEnvironment(options?: {
27
- testnet?: boolean;
28
- demo?: boolean;
29
- apiBase?: string;
30
- wsBase?: string;
31
- wsUserBase?: string;
32
- wsApiBase?: string;
33
- dapiBase?: string;
34
- wsSpotApiBase?: string;
35
- wsDapiBase?: string;
36
- }): {
37
- env: Environment;
38
- endpoints: Endpoints;
7
+ import 'zod';
8
+
9
+ /**
10
+ * Single source of truth for the package version string.
11
+ *
12
+ * Read by:
13
+ * - {@link ./index.js} — re-exports as the public `VERSION` constant.
14
+ * - {@link ../mcp/server.js} — the MCP server identifies itself with this
15
+ * value when negotiating with hosts (was previously hard-coded as
16
+ * `'2.0.0'`, which drifted from `package.json`).
17
+ *
18
+ * Update in lockstep with the `version` field in `package.json` and the
19
+ * `[Unreleased]` / latest release section in `CHANGELOG.md`.
20
+ */
21
+ declare const VERSION = "3.0.0";
22
+
23
+ /**
24
+ * Standalone product clients.
25
+ *
26
+ * `BinanceClient` is the full multi-product surface; these factories give
27
+ * focused callers just their product plus the shared lifecycle helpers
28
+ * (`syncTime`, `close`), constructed from the same client underneath — no
29
+ * duplicated wiring, no divergent behavior:
30
+ *
31
+ * ```ts
32
+ * import { createSpotClient, createUSDMClient } from '@nemesis-oss/binance-sdk';
33
+ *
34
+ * const spot = createSpotClient({ apiKey, apiSecret });
35
+ * await spot.syncTime();
36
+ * const books = await spot.market.depth('BTCUSDT', 20);
37
+ * spot.close();
38
+ *
39
+ * const usdm = createUSDMClient({ apiKey, apiSecret });
40
+ * await usdm.execution.placeOrder({ symbol: 'BTCUSDT', ... });
41
+ * ```
42
+ */
43
+ /** The spot product surface plus shared lifecycle helpers. */
44
+ type SpotClient$1 = BinanceClient['spot'] & {
45
+ /** Sync local clocks against every REST host (mitigates -1021). */
46
+ syncTime(): Promise<void>;
47
+ /** Close all websockets and user streams created for this client. */
48
+ close(): void;
49
+ /** Rate-limit usage snapshots, per REST host. */
50
+ getRateLimitUsage(): ReturnType<BinanceClient['getRateLimitUsage']>;
39
51
  };
52
+ /** The USDⓈ-M futures product surface plus shared lifecycle helpers. */
53
+ type USDMClient$1 = BinanceClient['futures'] & {
54
+ syncTime(): Promise<void>;
55
+ close(): void;
56
+ getRateLimitUsage(): ReturnType<BinanceClient['getRateLimitUsage']>;
57
+ };
58
+ /** The COIN-M futures product surface plus shared lifecycle helpers. */
59
+ type CoinMClient$1 = BinanceClient['coinm'] & {
60
+ syncTime(): Promise<void>;
61
+ close(): void;
62
+ getRateLimitUsage(): ReturnType<BinanceClient['getRateLimitUsage']>;
63
+ };
64
+ /** A spot-only client (market, account, trading, execution, ws, wsApi). */
65
+ declare function createSpotClient(options?: BinanceClientOptions): SpotClient$1;
66
+ /** A USDⓈ-M futures-only client (market, data, account, trading, ops, execution, ws, wsApi). */
67
+ declare function createUSDMClient(options?: BinanceClientOptions): USDMClient$1;
68
+ /** A COIN-M futures-only client (market, account, trading, ws). */
69
+ declare function createCoinMClient(options?: BinanceClientOptions): CoinMClient$1;
70
+
71
+ /**
72
+ * Lossless JSON parsing for Binance payloads.
73
+ *
74
+ * `JSON.parse` coerces every integer to a JS double, silently corrupting values
75
+ * above Number.MAX_SAFE_INTEGER (2^53 - 1). Binance identifiers (orderId,
76
+ * tradeId, updateId, transaction IDs) are the classic casualties: two distinct
77
+ * exchange IDs can compare equal after parsing.
78
+ *
79
+ * `parseJsonLossless` pre-passes the raw text and quotes any integer literal
80
+ * whose magnitude exceeds the safe range, so oversized IDs surface as decimal
81
+ * *strings* instead of silently-corrupted numbers. Values within the safe range
82
+ * keep their original type, which keeps all existing Zod schemas valid.
83
+ */
84
+ declare function parseJsonLossless(text: string): unknown;
85
+ /** Type-safe wrapper for callers that know the payload shape. */
86
+ declare function parseJsonLosslessAs<T>(text: string): T;
87
+ /**
88
+ * Deep-walks a parsed payload converting long integer *strings* back into
89
+ * numbers only when they are safe — useful when the caller wants uniform
90
+ * `number` types for fields that are practically always small.
91
+ */
92
+ declare function normalizeIntStrings<T>(value: T): T;
40
93
 
41
- type PaperPositionSide = 'LONG' | 'SHORT' | 'NONE';
42
- interface PaperPosition {
94
+ /**
95
+ * Product identifiers — the canonical set v3 namespaces address. Grows as
96
+ * products are migrated onto the platform (Options, Portfolio Margin, …).
97
+ */
98
+ type ProductId = 'spot' | 'usdm' | 'coinm' | 'margin' | 'wallet' | 'subaccount' | 'convert';
99
+ /**
100
+ * v3 product boundary.
101
+ *
102
+ * A product client is anything constructed from a shared {@link CoreContext}
103
+ * that owns its product's surface. The contract is deliberately tiny —
104
+ * products differ wildly in surface, but every one of them:
105
+ *
106
+ * - declares its `product` id (routing key for the contract catalog,
107
+ * observability dimensions, and coverage accounting);
108
+ * - carries the core context it was built from (so callers can reach the
109
+ * shared transports, credentials and events without globals);
110
+ * - closes the product's own resources (websockets, listen-key timers).
111
+ *
112
+ * The raw API layer (`client.futures.usdm.trading.createOrder`) and the
113
+ * domain execution layer (`client.futures.usdm.execution.placeOrder`) both
114
+ * live inside product clients — API fidelity and trading infrastructure are
115
+ * siblings, not alternatives.
116
+ */
117
+ interface ProductClient {
118
+ /** Canonical product id ('usdm', 'spot', …). */
119
+ readonly product: ProductId;
120
+ /** The shared runtime this product was constructed from. */
121
+ readonly core: CoreContext;
122
+ /**
123
+ * Close this product's resources (WS connections, keep-alive timers).
124
+ * Safe to call more than once.
125
+ */
126
+ close(): void;
127
+ }
128
+ /**
129
+ * Factory signature for lazy product construction on a multi-product
130
+ * facade: receives the shared context, returns the cached product surface.
131
+ */
132
+ type ProductFactory<T> = (core: CoreContext) => T;
133
+ /** True when a value satisfies the v3 product boundary. */
134
+ declare function isProductClient(value: unknown): value is ProductClient;
135
+
136
+ /**
137
+ * Paper execution backend: routes orders through the local
138
+ * {@link PaperTradingEngine} simulator instead of the exchange, behind the
139
+ * exact same {@link ExecutionAdapter} interface the live products use.
140
+ *
141
+ * The point is *identical semantics*: `placeOrder` returns the same
142
+ * `Execution` envelope, `reconcile()` runs the same matrix, fetches of
143
+ * unknown orders fail with the same `-2013` Binance error the exchange would
144
+ * return, and fills stream in as execution reports just like a user-data
145
+ * stream would deliver them. Code written against the paper backend can be
146
+ * switched to live by changing one configuration value.
147
+ *
148
+ * The simulator fills instantly (per its execution model), so:
149
+ * - `createOrder` resolves with the fill already booked;
150
+ * - `fetchOrder` replays the stored record (reconciliation succeeds);
151
+ * - `cancelOrder` mirrors the exchange's `-2011` for orders no longer on
152
+ * the book, which the ExecutionManager reconciles into a terminal
153
+ * CANCELED execution — the same path live takes.
154
+ */
155
+ declare class PaperExecutionAdapter implements ExecutionAdapter {
156
+ private readonly engine;
157
+ private readonly options;
158
+ readonly product = "paper";
159
+ /** clientOrderId → raw order record, the simulator's "matching engine" view. */
160
+ private readonly orders;
161
+ /**
162
+ * Report listeners. Paper backends routinely have several consumers — the
163
+ * execution manager's ledger *and* (v3) the platform's paper session that
164
+ * translates fills into user-stream frames — so `onReport` fans out to
165
+ * every registered listener instead of replacing the previous one.
166
+ */
167
+ private readonly reportHandlers;
168
+ constructor(engine: PaperTradingEngine, options?: {
169
+ commissionAsset?: string;
170
+ });
171
+ /** The underlying simulator (account, positions, order history). */
172
+ get simulator(): PaperTradingEngine;
173
+ createOrder(submission: CreateOrderParams): Promise<Record<string, unknown>>;
174
+ fetchOrder(symbol: string, key: OrderKey): Promise<Record<string, unknown>>;
175
+ /**
176
+ * Every order record the simulator holds, client-order-id keyed — the
177
+ * authoritative "REST view" a paper-mode reconciliation pass folds into the
178
+ * v3 platform's order tracker (live reconciliation reads `/openOrders`).
179
+ */
180
+ listOrderRecords(): Record<string, unknown>[];
181
+ cancelOrder(symbol: string, key: OrderKey): Promise<Record<string, unknown>>;
182
+ toOrderShape(raw: Record<string, unknown>): OrderShape;
183
+ /** Paper has no user-data stream; attach is a no-op. */
184
+ setUserStream(_ws: UserStreamLike | null): void;
185
+ /** Register a report listener; every listener fires for every fill (additive). */
186
+ onReport(handler: (report: ExecutionReportShape) => void): void;
187
+ }
188
+
189
+ /**
190
+ * v3 execution platform — shared domain types.
191
+ *
192
+ * Milestone 3 turns execution from a per-call concern into a platform: the
193
+ * user-data stream becomes a managed session (listen-key lifecycle, keep-alive,
194
+ * rotation), order and position state become live feeds updated by that stream,
195
+ * and retry decisions become an explicit, classified contract instead of an
196
+ * implicit code path. These types are the vocabulary all three pieces share.
197
+ */
198
+ /**
199
+ * Binance order lifecycle statuses — the union of REST and user-stream values
200
+ * across USDⓈ-M and Spot. The trailing `string` intersection keeps the union
201
+ * open: Binance adds statuses (e.g. `EXPIRED_IN_MATCH` for STP) without
202
+ * breaking compilation, while known values still autocomplete.
203
+ */
204
+ type OrderStatus = 'NEW' | 'PARTIALLY_FILLED' | 'FILLED' | 'CANCELED' | 'PENDING_CANCEL' | 'REJECTED' | 'EXPIRED' | 'EXPIRED_IN_MATCH' | 'PARTIALLY_CANCELED' | 'LIQUIDATED' | (string & Record<never, never>);
205
+ /**
206
+ * True when the status is a terminal order state — no further execution
207
+ * reports or REST polls can change the outcome (late events for a terminal
208
+ * order are protocol noise; trackers stop mutating terminal records).
209
+ */
210
+ declare function isTerminalOrderStatus(status: string): boolean;
211
+ /**
212
+ * Live view of one order, folded from every source that observes it:
213
+ * user-stream execution reports, REST order queries, and the execution
214
+ * manager's submissions. All prices and quantities are exact decimal strings
215
+ * (see `core/decimal`) — never binary floats.
216
+ *
217
+ * Unlike the {@link import('../types.js').Execution} ledger entry (which
218
+ * follows one *intent*), the OrderRecord follows one *order* — including
219
+ * orders placed outside this SDK (by hand, by another bot, by the UI): the
220
+ * user stream reports them all.
221
+ */
222
+ interface OrderRecord {
223
+ /** Exchange reconciliation key (same field the execution manager derives). */
224
+ clientOrderId: string;
225
+ /** Exchange-assigned id, once any source has reported it. */
226
+ exchangeOrderId?: number;
43
227
  symbol: string;
44
- side: PaperPositionSide;
45
- entryPrice: number;
46
- quantity: number;
47
- leverage: number;
48
- /** Margin currently allocated to this position, released proportionally as it is reduced. */
49
- margin: number;
50
- unrealizedPnl: number;
51
- openedAt: number;
228
+ side: string;
229
+ type: string;
230
+ status: OrderStatus;
231
+ /** Requested quantity when a source reported it, else null. */
232
+ originalQuantity: string | null;
233
+ /** Cumulative executed quantity — decimal string. */
234
+ executedQuantity: string;
235
+ /**
236
+ * Cumulative quote volume — decimal string. USDⓈ-M execution reports do not
237
+ * carry it; the fold computes `executedQuantity × averagePrice` as an
238
+ * estimate, exactly like the execution ledger does.
239
+ */
240
+ cumulativeQuoteQuantity: string | null;
241
+ /** Volume-weighted average fill price — decimal string or null. */
242
+ averagePrice: string | null;
243
+ /** Individual fills, appended once per trade, deduplicated by trade id. */
244
+ fills: ExecutionFill[];
245
+ positionSide?: string;
246
+ reduceOnly?: boolean;
247
+ timeInForce?: string;
248
+ /** Epoch ms when this order was first observed by any source. */
249
+ firstSeenAt: number;
250
+ /** Epoch ms of the last applied update. */
251
+ updatedAt: number;
52
252
  }
53
- interface PaperOrder {
54
- orderId: number;
253
+ /**
254
+ * One fully-normalized order observation — the unit the tracker folds into
255
+ * {@link OrderRecord}. Produced from either a user-stream event or a REST
256
+ * order view by the platform normalizers.
257
+ */
258
+ interface OrderUpdate {
259
+ clientOrderId: string;
260
+ exchangeOrderId?: number;
261
+ symbol: string;
262
+ side: string;
263
+ type: string;
264
+ status: string;
265
+ originalQuantity: string | null;
266
+ executedQuantity: string;
267
+ cumulativeQuoteQuantity: string | null;
268
+ averagePrice: string | null;
269
+ /** The trade this update carries, when it reports one (fill quantity > 0). */
270
+ lastFill: ExecutionFill | null;
271
+ positionSide?: string;
272
+ reduceOnly?: boolean;
273
+ timeInForce?: string;
274
+ /** Epoch ms of the observation (event transaction time or REST time). */
275
+ updateTime: number;
276
+ source: 'user-stream' | 'rest';
277
+ /** The raw event/response this was normalized from, for auditing. */
278
+ raw: Record<string, unknown>;
279
+ }
280
+ /**
281
+ * Live view of one position (USDⓈ-M), folded from `ACCOUNT_UPDATE` user-stream
282
+ * events. Keyed by `symbol` + `positionSide` — one-way mode reports `BOTH`,
283
+ * hedge mode reports `LONG` and `SHORT` separately.
284
+ */
285
+ interface PositionRecord {
55
286
  symbol: string;
56
- side: 'BUY' | 'SELL';
57
- type: 'MARKET' | 'LIMIT';
287
+ /** 'BOTH' (one-way mode) | 'LONG' | 'SHORT' (hedge mode). */
288
+ positionSide: string;
289
+ /** Signed position amount — decimal string (negative for shorts). */
290
+ positionAmount: string;
291
+ /** Average entry price — decimal string. */
292
+ entryPrice: string;
293
+ /** Unrealized PnL as of the last event — decimal string (stream value; refresh via REST for precision). */
294
+ unrealizedPnl: string | null;
295
+ /** 'isolated' | 'cross' when reported, else null. */
296
+ marginType: string | null;
297
+ /** Isolated-position wallet balance when reported, else null. */
298
+ isolatedWallet: string | null;
299
+ /** Epoch ms of the last applied event. */
300
+ updatedAt: number;
301
+ }
302
+ /**
303
+ * One normalized position change — an `ACCOUNT_UPDATE` position entry
304
+ * (`a.P[i]`), decimal strings everywhere.
305
+ */
306
+ interface PositionUpdate {
307
+ symbol: string;
308
+ positionSide: string;
309
+ positionAmount: string;
310
+ entryPrice: string;
311
+ unrealizedPnl: string | null;
312
+ marginType: string | null;
313
+ isolatedWallet: string | null;
314
+ updateTime: number;
315
+ /** The raw `a.P` entry this was normalized from. */
316
+ raw: Record<string, unknown>;
317
+ }
318
+ /** Consumer-visible lifecycle of a managed {@link UserStreamSession}. */
319
+ type UserSessionState = 'idle' | 'starting' | 'live' | 'reconnecting' | 'closed';
320
+ /**
321
+ * REST listen-key lifecycle the session drives. Product adapters implement
322
+ * this over the shared `HttpClient` (USDⓈ-M `/fapi/v1/listenKey`, Spot
323
+ * `/api/v3/userDataStream`) — swap it out for a captive/mock backend in tests.
324
+ */
325
+ interface ListenKeyApi {
326
+ /** Create a fresh listen key. */
327
+ create(): Promise<string>;
328
+ /**
329
+ * Renew a listen key. Binance disconnects user streams after 60 minutes
330
+ * without renewal; the session calls this roughly every 30 minutes.
331
+ */
332
+ keepAlive(listenKey: string): Promise<void>;
333
+ /** Delete a listen key (server-side stream teardown). Best-effort. */
334
+ close?(listenKey: string): Promise<void>;
335
+ }
336
+ /**
337
+ * Result of one {@link ExecutionPlatform.reconcile} pass: how many REST (or
338
+ * simulator) views were folded into the trackers. A *view count*, not a
339
+ * change count — folding a view does not always mutate a record (the stream
340
+ * may have reported the same state already).
341
+ */
342
+ interface ReconciliationSummary {
343
+ /** Order views folded (open orders from REST, or the simulator's history). */
344
+ orders: number;
345
+ /** Position records folded (position-risk REST rows, or simulator positions). */
346
+ positions: number;
347
+ /** Epoch ms of the snapshot this pass folded. */
348
+ fetchedAt: number;
349
+ }
350
+ /**
351
+ * Execution platform defaults. Keep-alive runs at the documented 30-minute
352
+ * cadence; a key is rotated after 3 consecutive keep-alive failures (dead
353
+ * key) or 6 reconnect attempts without an OPEN (network partition or the
354
+ * key expired server-side mid-outage).
355
+ */
356
+ declare const EXECUTION_PLATFORM_DEFAULTS: {
357
+ /** Listen-key renewal cadence (Binance kills keys after 60 min). */
358
+ readonly keepAliveIntervalMs: number;
359
+ /** Consecutive keep-alive failures before the key is rotated. */
360
+ readonly keepAliveFailuresBeforeRotation: 3;
361
+ /**
362
+ * Reconnect attempts (with backoff) before the key is rotated — the escape
363
+ * hatch for "server accepts nothing on this key anymore".
364
+ */
365
+ readonly reconnectAttemptsBeforeRotation: 6;
366
+ /** Retained order records before the oldest are evicted. */
367
+ readonly maxTrackedOrders: 5000;
368
+ /** Default wait for an order to reach a terminal status. */
369
+ readonly terminalTimeoutMs: 30000;
370
+ };
371
+ /**
372
+ * What a retry of a failed order operation means, semantically:
373
+ *
374
+ * - `'safe'` — the failure proves no order side effect occurred; retrying is
375
+ * free of double-execution risk (order never reached the engine, request
376
+ * was throttled before processing, target of a cancel already gone).
377
+ * - `'idempotent'` — the target backend enforces the idempotency key, so a
378
+ * retry with the same key cannot double-execute. The live exchange never
379
+ * earns this label (Binance does not enforce `newClientOrderId`
380
+ * uniqueness); it is reserved for backends that do (e.g. a paper engine
381
+ * keyed by intent).
382
+ * - `'reconciliation-required'` — the outcome is unknown: the request may or
383
+ * may not have reached the engine. Retrying blind risks doubling the
384
+ * position; the caller must reconcile first (the execution manager's
385
+ * `reconcile()`, or `GET /fapi/v1/order` by clientOrderId).
386
+ * - `'never-retry'` — a definitive rejection or a programming error: the
387
+ * same request will fail the same way (filters, margin, permissions).
388
+ */
389
+ type RetrySafety = 'safe' | 'idempotent' | 'reconciliation-required' | 'never-retry';
390
+ /** Result of classifying an error for retry semantics. */
391
+ interface RetryClassification {
392
+ safety: RetrySafety;
393
+ /** Human-readable justification, stable enough for dashboards. */
394
+ reason: string;
395
+ }
396
+
397
+ /** Options for {@link OrderTracker}. */
398
+ interface OrderTrackerOptions {
399
+ /** Observability bus; `execution.order.*` events are published to it. */
400
+ events?: EventBus;
401
+ /** Retained records before the oldest are evicted. Default 5000. */
402
+ maxRecords?: number;
403
+ }
404
+ /**
405
+ * Live order-state feed.
406
+ *
407
+ * One {@link OrderRecord} per order, folded from every source that observes
408
+ * it: user-stream execution reports (all orders on the account — including
409
+ * orders placed outside this SDK), REST order views, and anything else a
410
+ * caller pushes through `applyUpdate`. Records hold exact decimal strings and
411
+ * per-trade fills deduplicated by trade id.
412
+ *
413
+ * ```ts
414
+ * const orders = platform.orders;
415
+ * orders.on('update', (record) => log(record.status));
416
+ *
417
+ * await platform.startUserSession(); // feed goes live
418
+ * const final = await orders.waitForTerminal('nbsdk-abc'); // promise form
419
+ * ```
420
+ *
421
+ * The tracker is a *view*, not a ledger: it keeps no intents and drives no
422
+ * requests — the execution manager owns submission/reconciliation, this owns
423
+ * "what does the account's order book look like right now".
424
+ */
425
+ declare class OrderTracker extends EventEmitter {
426
+ private readonly records;
427
+ private readonly byExchangeId;
428
+ private readonly maxRecords;
429
+ private readonly events?;
430
+ constructor(options?: OrderTrackerOptions);
431
+ /**
432
+ * Dispatch one raw user-data frame. Recognized execution reports
433
+ * (`ORDER_TRADE_UPDATE`, spot `executionReport`) fold into records;
434
+ * everything else is ignored — the session feeds this its full event flow.
435
+ */
436
+ applyUserEvent(event: unknown): void;
437
+ /** Fold a REST order view (create ack / query / cancel result). */
438
+ applyOrderShape(shape: OrderShape): void;
439
+ /** Fold one normalized observation and emit the updated record. */
440
+ applyUpdate(update: OrderUpdate): void;
441
+ /** Current record for a client order id (defensive copy). */
442
+ get(clientOrderId: string): OrderRecord | undefined;
443
+ /** Current record for an exchange order id (defensive copy). */
444
+ getByExchangeId(orderId: number): OrderRecord | undefined;
445
+ /** All tracked records (defensive copies), insertion order. */
446
+ all(): OrderRecord[];
447
+ /** Records that have not reached a terminal status. */
448
+ open(): OrderRecord[];
449
+ /**
450
+ * Resolve with the record once its status is terminal. Rejects if the order
451
+ * is unknown, or on timeout. Safe to call repeatedly for the same order.
452
+ */
453
+ waitForTerminal(clientOrderId: string, timeoutMs?: number): Promise<OrderRecord>;
454
+ /** Number of tracked records (cheap). */
455
+ get size(): number;
456
+ private evictOverflow;
457
+ private evict;
458
+ private copy;
459
+ }
460
+
461
+ /** Options for {@link PositionTracker}. */
462
+ interface PositionTrackerOptions {
463
+ /** Observability bus; `execution.position.*` events are published to it. */
464
+ events?: EventBus;
465
+ }
466
+ /**
467
+ * Live position-state feed (USDⓈ-M).
468
+ *
469
+ * Folds `ACCOUNT_UPDATE` user-stream events into one {@link PositionRecord}
470
+ * per `symbol` + `positionSide` (one-way mode reports `BOTH`; hedge mode
471
+ * reports `LONG` and `SHORT`). Every amount is an exact decimal string — the
472
+ * signed position amount distinguishes direction, so a short is a negative
473
+ * amount, never a separate flag.
474
+ *
475
+ * ```ts
476
+ * const positions = platform.positions;
477
+ * positions.on('update', (p) => log(p.symbol, p.positionAmount));
478
+ * await platform.startUserSession(); // feed goes live
479
+ * positions.get('BTCUSDT'); // current one-way position
480
+ * positions.nonZero(); // exposure view
481
+ * ```
482
+ *
483
+ * The unrealized PnL is the stream's own mark at event time; strategies that
484
+ * need a current mark should combine it with the mark-price stream rather
485
+ * than polling this field.
486
+ */
487
+ declare class PositionTracker extends EventEmitter {
488
+ private readonly positions;
489
+ private readonly events?;
490
+ constructor(options?: PositionTrackerOptions);
491
+ /**
492
+ * Dispatch one raw user-data frame. `ACCOUNT_UPDATE` position entries fold
493
+ * into records; everything else is ignored.
494
+ */
495
+ applyUserEvent(event: unknown): void;
496
+ /** Fold one normalized position update and emit the updated record. */
497
+ applyUpdate(update: PositionUpdate): void;
498
+ /**
499
+ * Current position for a symbol. In one-way mode pass no side (or 'BOTH');
500
+ * in hedge mode pass 'LONG' or 'SHORT'. Defensive copy.
501
+ */
502
+ get(symbol: string, positionSide?: string): PositionRecord | undefined;
503
+ /** All tracked positions (defensive copies), insertion order. */
504
+ all(): PositionRecord[];
505
+ /** Positions with a non-zero amount — the actual exposure view. */
506
+ nonZero(): PositionRecord[];
507
+ /** Number of tracked positions (cheap). */
508
+ get size(): number;
509
+ }
510
+
511
+ /**
512
+ * v3 execution platform — REST reconciliation pass.
513
+ *
514
+ * The user stream sees the present and the future, never the past: an order
515
+ * placed before `startUserSession()` (by hand, by another bot, by a previous
516
+ * process of this SDK) never appears in it, and after a partition the stream
517
+ * resumes without replaying what was missed. `reconcile()` closes that gap
518
+ * the same way the execution manager does for single intents — by folding an
519
+ * authoritative REST snapshot into the trackers:
520
+ *
521
+ * - `GET /fapi/v1/openOrders` (USDⓈ-M, one call) / per-symbol Spot
522
+ * `GET /api/v3/openOrders` → `OrderTracker.applyOrderShape`
523
+ * - `GET /fapi/v2/positionRisk` (USDⓈ-M) → `PositionTracker.applyUpdate`
524
+ *
525
+ * Paper mode reconciles against the simulator's own book instead — the same
526
+ * fold, the same events, zero network. Every fold emits the identical
527
+ * `order.updated` / `position.updated` events a stream fold emits, so
528
+ * consumers cannot tell which path updated a record.
529
+ */
530
+ /** Options for a reconciliation pass. */
531
+ interface ReconcileOptions {
532
+ /**
533
+ * Restrict the pass to these symbols. Required for live Spot (its
534
+ * `openOrders` route needs a symbol); optional for USDⓈ-M (one call covers
535
+ * the whole account, and the position fold filters to these symbols).
536
+ */
537
+ symbols?: string[];
538
+ }
539
+ /** Everything a reconciliation pass needs, provided by the platform. */
540
+ interface ReconcileTarget {
541
+ product: 'usdm' | 'spot';
542
+ /** Shared transports — the same hosts, weight budgets and mocks as always. */
543
+ core: Pick<CoreContext, 'events' | 'http'>;
544
+ /** Paper wiring; presence switches the pass to the simulator's book. */
545
+ paper?: {
546
+ engine: PaperTradingEngine;
547
+ adapter: PaperExecutionAdapter;
548
+ };
549
+ orders: OrderTracker;
550
+ positions: PositionTracker;
551
+ }
552
+ /**
553
+ * Run one reconciliation pass — see the module doc. Returns how many views
554
+ * were folded; throws only on transport failure (the caller decides whether
555
+ * that is fatal — for a startup gap-fill it usually is not).
556
+ */
557
+ declare function reconcileExecutionPlatform(target: ReconcileTarget, options?: ReconcileOptions): Promise<ReconciliationSummary>;
558
+ /**
559
+ * `GET /fapi/v1/openOrders` row (and the paper adapter's raw records, which
560
+ * mirror it) → decimal-string {@link OrderShape} for the tracker's REST fold.
561
+ */
562
+ declare function orderShapeFromUsdmOpenOrder(raw: Record<string, unknown>): OrderShape;
563
+ /**
564
+ * `GET /fapi/v2/positionRisk` row → {@link PositionUpdate}. Binance reports
565
+ * one row per symbol × positionSide, including zero-size rows — folding a
566
+ * zero row is the correct "authoritative flat" semantics.
567
+ */
568
+ declare function positionUpdatesFromPositionRisk(raw: Record<string, unknown>, fetchedAt: number): PositionUpdate[];
569
+ /** `GET /api/v3/openOrders` row → decimal-string {@link OrderShape}. */
570
+ declare function orderShapeFromSpotOpenOrder(raw: Record<string, unknown>): OrderShape;
571
+
572
+ /**
573
+ * Pure normalization for the execution platform: raw user-data frames and
574
+ * REST order views become decimal-string {@link OrderUpdate}s and
575
+ * {@link PositionUpdate}s, which the trackers fold. Product field-name
576
+ * differences (USDⓈ-M `ORDER_TRADE_UPDATE.o` vs Spot `executionReport`, spot
577
+ * `Z` cumulative quote vs none on futures) end here — nothing downstream
578
+ * knows which product an update came from.
579
+ *
580
+ * Normalization always reads the *raw frame* strings, never the
581
+ * schema-transformed numbers: Binance transmits exact decimals precisely
582
+ * because binary floats cannot represent them, so coercing through `Number`
583
+ * and back would corrupt values like `123.456` at exactly the fields money
584
+ * math depends on. Zod runs as a validation-only pass (see
585
+ * {@link createUserEventParser}); the raw string survives to `Decimal`.
586
+ */
587
+ /** Parse one raw user-data frame — validates, then returns the frame untouched. */
588
+ type UserEventParser = (raw: unknown) => unknown;
589
+ /**
590
+ * Build the per-product frame parser for a user-data session. The typed Zod
591
+ * schemas run as a *validation* pass — a frame that parses is known-good
592
+ * Binance shape; the raw frame (decimal strings intact) is returned untouched
593
+ * so normalization keeps exact decimals. Frames with unknown-but-valid `e`
594
+ * types (new Binance events, e.g. `TRADE_LITE`) pass through unvalidated;
595
+ * shapeless frames throw and the session surfaces them as errors.
596
+ */
597
+ declare function createUserEventParser(product: 'usdm' | 'spot'): UserEventParser;
598
+
599
+ /** Tuning for {@link UserStreamSession}. */
600
+ interface UserStreamSessionOptions {
601
+ /** Product label used in events and errors ('usdm' | 'spot' | …). */
602
+ product: string;
603
+ /** REST listen-key lifecycle the session drives. */
604
+ listenKeyApi: ListenKeyApi;
605
+ /** User-data stream base URL (the listen key is appended as the path). */
606
+ userStreamUrl: string;
607
+ /** Observability bus; `execution.session.*` events are published to it. */
608
+ events?: EventBus;
609
+ /** Connection label; defaults to `userSession:<product>`. */
610
+ name?: string;
611
+ /** Keep-alive cadence. Default 30 minutes. */
612
+ keepAliveIntervalMs?: number;
613
+ /** Consecutive keep-alive failures before key rotation. Default 3. */
614
+ keepAliveFailuresBeforeRotation?: number;
615
+ /** Reconnect attempts before key rotation. Default 6. */
616
+ reconnectAttemptsBeforeRotation?: number;
617
+ /**
618
+ * A connection that opens and dies within this window *without delivering
619
+ * a single frame* counts as a flap. Default 10s.
620
+ */
621
+ flapWindowMs?: number;
622
+ /** Consecutive flaps before key rotation. Default 5. */
623
+ flapFailuresBeforeRotation?: number;
624
+ /** Frame parser; defaults to the product's (usdm → futures, else spot). */
625
+ parseEvent?: UserEventParser;
626
+ /** Injectable WebSocket factory for tests. */
627
+ socketFactory?: (url: string) => WebSocket;
628
+ /** Called once when the session is closed by the user (or `close()`). */
629
+ onClose?: () => void;
630
+ /** Connection-level passthrough (reconnect tuning, rotation window, …). */
631
+ connection?: Partial<Omit<WsConnectionOptions, 'buildUrl' | 'name' | 'events' | 'socketFactory'>>;
632
+ }
633
+ /**
634
+ * Managed user-data stream session.
635
+ *
636
+ * v2 (and the v3 M1 product clients) left the listen-key dance to the caller:
637
+ * create the key, schedule the 30-minute keep-alive, notice when the key dies,
638
+ * restart. Every consumer reimplemented it, and the failure modes (key expiry
639
+ * mid-run, keep-alive failing silently, zombie sockets) were exactly the kind
640
+ * of thing that loses fills.
641
+ *
642
+ * The session owns the whole lifecycle over a {@link WsConnection}:
643
+ *
644
+ * - `start()` creates the key, connects, and schedules keep-alive;
645
+ * - keep-alive failures are counted — after 3 in a row the key is rotated
646
+ * (a fresh key is created and the connection swapped onto it);
647
+ * - a connection that cannot re-establish after 6 backoff attempts gets its
648
+ * key rotated too (the escape hatch for "the key died while we were
649
+ * partitioned");
650
+ * - the 24-hour server-side kill is preempted by the connection's own 23-hour
651
+ * rotation (same listen key, per Binance's renewal semantics);
652
+ * - `close()` stops everything and deletes the key server-side, best-effort.
653
+ *
654
+ * The session is also a drop-in user stream for the execution manager: it
655
+ * emits `userData` with each parsed (validated, raw-decimal-preserving) frame,
656
+ * so `executionManager.setUserStream(session)` immediately routes live
657
+ * execution reports into the intent ledger.
658
+ *
659
+ * ```ts
660
+ * const session = new UserStreamSession({
661
+ * product: 'usdm',
662
+ * listenKeyApi,
663
+ * userStreamUrl: core.endpoints.wsUser,
664
+ * events: core.events,
665
+ * });
666
+ * const key = await session.start();
667
+ * session.on('userData', (event) => { /* e: ORDER_TRADE_UPDATE … *\/ });
668
+ * session.close();
669
+ * ```
670
+ */
671
+ declare class UserStreamSession extends WsConnection {
672
+ private readonly api;
673
+ private readonly userStreamUrl;
674
+ private readonly parse;
675
+ private readonly sessionProduct;
676
+ private readonly keepAliveIntervalMs;
677
+ private readonly keepAliveFailuresBeforeRotation;
678
+ private readonly reconnectAttemptsBeforeRotation;
679
+ private readonly flapWindowMs;
680
+ private readonly flapFailuresBeforeRotation;
681
+ private readonly sessionEvents?;
682
+ private listenKeyValue;
683
+ private keepAliveTimer;
684
+ private keepAliveFailures;
685
+ private rotating;
686
+ private sessionStateValue;
687
+ private startPromise;
688
+ private readonly onClose?;
689
+ /** Epoch ms of the last 'open'; flap detection. */
690
+ private openedAtMs;
691
+ /** Inbound frames since the last 'open'; flap detection. */
692
+ private framesSinceOpen;
693
+ /** Consecutive open-then-die-without-frames cycles. */
694
+ private flapFailures;
695
+ constructor(options: UserStreamSessionOptions);
696
+ /** Product this session serves ('usdm' | 'spot' | …). */
697
+ get product(): string;
698
+ /** Consumer-visible session state. */
699
+ get sessionState(): UserSessionState;
700
+ /** The live listen key, or null before start / after close. */
701
+ get listenKey(): string | null;
702
+ /**
703
+ * Start the session: create a listen key, connect, schedule keep-alive.
704
+ * Idempotent — concurrent or repeated calls share one start; returns the
705
+ * listen key.
706
+ */
707
+ start(): Promise<string>;
708
+ /**
709
+ * Close the session: stop keep-alive, tear the connection down, delete the
710
+ * listen key server-side (best-effort). Safe to call repeatedly and from
711
+ * any state.
712
+ */
713
+ close(): void;
714
+ protected handleRawMessage(text: string): void;
715
+ private scheduleNextKeepAlive;
716
+ private keepAliveTick;
717
+ /**
718
+ * Rotate onto a fresh listen key: create it, swap `listenKeyValue`, and
719
+ * force the connection to re-establish on the new key. Guarded so overlapping
720
+ * triggers (keep-alive failure + reconnect storm) rotate once.
721
+ */
722
+ private rotateListenKey;
723
+ private setSessionState;
724
+ /** Narrowing-safe terminal check (crosses `await` boundaries). */
725
+ private isClosed;
726
+ private emitSessionEvent;
727
+ }
728
+
729
+ /**
730
+ * v3 paper backend — the simulator behind the execution-platform boundary.
731
+ *
732
+ * Milestone 3's execution platform gave live trading a managed session and
733
+ * order/position feeds. Milestone 4 puts the **paper simulator behind the
734
+ * same boundary**: a {@link PaperSession} emits the exact user-data frames a
735
+ * live session would (`ORDER_TRADE_UPDATE` for fills, `ACCOUNT_UPDATE` for
736
+ * the position the fill produced), so the platform's trackers, the
737
+ * `waitForTerminal()` promise API and the reconciliation semantics behave
738
+ * *identically* whether orders route to the exchange or to the simulator.
739
+ * Strategy code written against the paper platform runs unchanged live.
740
+ */
741
+ /** Options for {@link PaperSession}. */
742
+ interface PaperSessionOptions {
743
+ /** The simulator whose fills become user-data frames. */
744
+ engine: PaperTradingEngine;
745
+ /** Report source — the adapter orders flow through (one per engine). */
746
+ adapter: PaperExecutionAdapter;
747
+ /** Observability bus; `execution.session.*` events mirror the live session. */
748
+ events?: EventBus;
749
+ /** Called once when the session is closed by the user (or `close()`). */
750
+ onClose?: () => void;
751
+ }
752
+ /**
753
+ * A user-data stream session with no network: simulator fills, replayed as
754
+ * exchange-shaped user-data frames.
755
+ *
756
+ * The contract is the one the platform (and the execution manager) already
757
+ * consume: `start()` goes live, `close()` is terminal, frames arrive on
758
+ * `userData`. There is no listen key, no keep-alive, no rotation — nothing to
759
+ * rotate, because the "server" is an in-process {@link PaperTradingEngine}.
760
+ * Fill → frame translation is synchronous: by the time `placeOrder()` resolves,
761
+ * the trackers have already folded the fill.
762
+ *
763
+ * ```ts
764
+ * const session = new PaperSession({ engine, adapter });
765
+ * await session.start();
766
+ * session.on('userData', (event) => {
767
+ * // { e: 'ORDER_TRADE_UPDATE', … } / { e: 'ACCOUNT_UPDATE', … }
768
+ * });
769
+ * ```
770
+ */
771
+ declare class PaperSession extends EventEmitter implements UserStreamLike {
772
+ private readonly engine;
773
+ private readonly adapter;
774
+ private readonly sessionEvents?;
775
+ private readonly onClose?;
776
+ private sessionStateValue;
777
+ private readonly reportListener;
778
+ constructor(options: PaperSessionOptions);
779
+ /** Consumer-visible lifecycle: `idle` → `live` → `closed`. */
780
+ get sessionState(): UserSessionState;
781
+ /** Alias for {@link sessionState} — reads naturally next to book/tracker states. */
782
+ get state(): UserSessionState;
783
+ /**
784
+ * The listen key a live session would carry — always null here: the
785
+ * simulator *is* the server, there is nothing to register.
786
+ */
787
+ get listenKey(): string | null;
788
+ /** True while simulator fills flow into `userData`. */
789
+ get isLive(): boolean;
790
+ /**
791
+ * Session-contract member: resolve once frames are being delivered. For a
792
+ * live paper session that is immediate — the simulator delivers
793
+ * synchronously, there is no socket handshake to wait for.
794
+ */
795
+ waitForOpen(_timeoutMs?: number): Promise<void>;
796
+ /**
797
+ * Start the session: attach the fill listener. Idempotent; no I/O — the
798
+ * listen-key create/connect/keep-alive dance has no paper equivalent.
799
+ */
800
+ start(): Promise<PaperSession>;
801
+ /** Close the session (detach the fill listener). Terminal; safe repeatedly. */
802
+ close(): void;
803
+ /** Translate one simulator fill into the frames a live session would send. */
804
+ private onFill;
805
+ }
806
+ /**
807
+ * Simulator fill → USDⓈ-M `ORDER_TRADE_UPDATE` frame. Field-for-field the
808
+ * live shape (`o.c`, `o.X`, `o.z`, `o.ap`, …), decimal strings everywhere —
809
+ * `OrderTracker.applyUserEvent` cannot tell it from a real fill.
810
+ */
811
+ declare function paperOrderTradeUpdateFrame(report: ExecutionReportShape, atMs?: number): Record<string, unknown>;
812
+ /**
813
+ * Simulator position → USDⓈ-M `ACCOUNT_UPDATE` frame. One-way mode semantics
814
+ * (`ps: 'BOTH'`) with a *signed* amount, the way Binance reports it: a short
815
+ * is a negative `pa`, never a separate flag.
816
+ */
817
+ declare function paperAccountUpdateFrame(symbol: string, position: {
818
+ side: string;
58
819
  quantity: number;
59
- price: number;
60
- status: 'FILLED';
61
- filledQuantity: number;
62
- avgFillPrice: number;
63
- /** Realized PnL booked by this order, if it reduced or closed a position. */
64
- realizedPnl: number;
65
- createdAt: number;
66
- }
67
- interface PaperAccount {
68
- /** Wallet balance: starts at initialBalance and moves only with realized PnL. */
69
- balance: number;
70
- /** Wallet balance minus margin currently locked in open positions. */
71
- availableBalance: number;
72
- /** balance + unrealized PnL. */
73
- totalWalletBalance: number;
74
- realizedPnl: number;
820
+ entryPrice: number;
75
821
  unrealizedPnl: number;
76
- positions: Record<string, PaperPosition>;
77
- orders: PaperOrder[];
78
- }
79
- interface PaperTradingOptions {
80
- initialBalance?: number;
81
- /** Injectable so tests and offline callers can supply their own price source. */
82
- market?: FuturesMarket;
83
- }
84
- /**
85
- * In-memory simulator for USD-M futures fills. Prices come from the live public
86
- * market endpoints; nothing is ever sent to the exchange.
87
- *
88
- * Accounting model: `balance` moves only on realized PnL. Opening a position locks
89
- * `notional / leverage` of margin out of `availableBalance`; reducing it releases
90
- * that margin pro-rata and books the realized PnL. Orders fill instantly at the
91
- * current mark for MARKET, or at the stated limit price for LIMIT — there is no
92
- * order book simulation, slippage or funding.
93
- */
94
- declare class PaperTradingEngine {
95
- private readonly account;
96
- private readonly market;
97
- private orderIdCounter;
98
- constructor(options?: PaperTradingOptions);
99
- /** Current mark price for any tradeable symbol. */
100
- getMarketPrice(symbol: string): Promise<number>;
101
- private positionFor;
102
- placeOrder(params: {
103
- symbol: string;
104
- side: 'BUY' | 'SELL';
105
- type: 'MARKET' | 'LIMIT';
106
- quantity: number;
107
- price?: number;
108
- leverage?: number;
109
- }): Promise<PaperOrder>;
110
- /**
111
- * Apply a fill to a position, returning the realized PnL it booked.
112
- * Handles extend, partial reduce, full close, and a flip through zero.
113
- */
114
- private applyFill;
115
- private openExposure;
116
- /** Reduce a position, releasing margin pro-rata and booking realized PnL. */
117
- private reduceExposure;
118
- private markToMarket;
119
- private recomputeTotals;
120
- /** Refresh unrealized PnL for every open position against live prices. */
121
- updatePositions(): Promise<void>;
122
- getAccountInfo(): PaperAccount;
123
- getPosition(symbol: string): PaperPosition | undefined;
124
- getAllPositions(): Record<string, PaperPosition>;
125
- /** Open positions only — the zero-size entries left behind by closed trades are filtered out. */
126
- getOpenPositions(): PaperPosition[];
127
- getOrderHistory(symbol?: string): PaperOrder[];
128
- }
129
-
130
- declare const WsKlinePayloadSchema: z.ZodObject<{
131
- e: z.ZodLiteral<"kline">;
132
- E: z.ZodNumber;
133
- s: z.ZodString;
134
- k: z.ZodObject<{
135
- t: z.ZodNumber;
136
- T: z.ZodNumber;
137
- s: z.ZodString;
138
- i: z.ZodString;
139
- o: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
140
- c: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
141
- h: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
142
- l: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
143
- v: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
144
- n: z.ZodNumber;
145
- x: z.ZodBoolean;
146
- q: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
147
- V: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
148
- Q: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
149
- }, z.core.$strip>;
150
- }, z.core.$strip>;
151
- type WsKlinePayload = z.infer<typeof WsKlinePayloadSchema>;
152
- declare const WsAggTradePayloadSchema: z.ZodObject<{
153
- e: z.ZodLiteral<"aggTrade">;
154
- E: z.ZodNumber;
155
- s: z.ZodString;
156
- a: z.ZodNumber;
157
- p: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
158
- q: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
159
- f: z.ZodNumber;
160
- l: z.ZodNumber;
161
- T: z.ZodNumber;
162
- m: z.ZodBoolean;
163
- }, z.core.$strip>;
164
- type WsAggTradePayload = z.infer<typeof WsAggTradePayloadSchema>;
165
- declare const WsTradePayloadSchema: z.ZodObject<{
166
- e: z.ZodLiteral<"trade">;
167
- E: z.ZodNumber;
168
- s: z.ZodString;
169
- t: z.ZodNumber;
170
- p: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
171
- q: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
172
- T: z.ZodNumber;
173
- m: z.ZodBoolean;
174
- }, z.core.$strip>;
175
- type WsTradePayload = z.infer<typeof WsTradePayloadSchema>;
176
- declare const WsDepthUpdatePayloadSchema: z.ZodObject<{
177
- e: z.ZodLiteral<"depthUpdate">;
178
- E: z.ZodNumber;
179
- s: z.ZodString;
180
- U: z.ZodNumber;
181
- u: z.ZodNumber;
182
- T: z.ZodOptional<z.ZodNumber>;
183
- pu: z.ZodOptional<z.ZodNumber>;
184
- b: z.ZodArray<z.ZodTuple<[z.ZodString, z.ZodString], null>>;
185
- a: z.ZodArray<z.ZodTuple<[z.ZodString, z.ZodString], null>>;
186
- }, z.core.$strip>;
187
- type WsDepthUpdatePayload = z.infer<typeof WsDepthUpdatePayloadSchema>;
188
- declare const WsTicker24hrPayloadSchema: z.ZodObject<{
189
- e: z.ZodLiteral<"24hrTicker">;
190
- E: z.ZodNumber;
191
- s: z.ZodString;
192
- p: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
193
- P: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
194
- c: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
195
- o: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
196
- h: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
197
- l: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
198
- v: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
199
- q: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
200
- }, z.core.$strip>;
201
- type WsTicker24hrPayload = z.infer<typeof WsTicker24hrPayloadSchema>;
202
- declare const WsBookTickerPayloadSchema: z.ZodObject<{
203
- u: z.ZodNumber;
204
- s: z.ZodString;
205
- b: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
206
- B: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
207
- a: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
208
- A: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
209
- }, z.core.$strip>;
210
- type WsBookTickerPayload = z.infer<typeof WsBookTickerPayloadSchema>;
211
- declare const WsMarkPricePayloadSchema: z.ZodObject<{
212
- e: z.ZodLiteral<"markPriceUpdate">;
213
- E: z.ZodNumber;
214
- s: z.ZodString;
215
- p: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
216
- i: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
217
- P: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
218
- r: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
219
- T: z.ZodNumber;
220
- }, z.core.$strip>;
221
- type WsMarkPricePayload = z.infer<typeof WsMarkPricePayloadSchema>;
222
- declare const WsMiniTickerPayloadSchema: z.ZodObject<{
223
- e: z.ZodLiteral<"24hrMiniTicker">;
224
- E: z.ZodNumber;
225
- s: z.ZodString;
226
- c: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
227
- o: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
228
- h: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
229
- l: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
230
- v: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
231
- q: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
232
- }, z.core.$strip>;
233
- type WsMiniTickerPayload = z.infer<typeof WsMiniTickerPayloadSchema>;
234
- declare const WsForceOrderPayloadSchema: z.ZodObject<{
235
- e: z.ZodLiteral<"forceOrder">;
236
- E: z.ZodNumber;
237
- o: z.ZodObject<{
238
- s: z.ZodString;
239
- S: z.ZodString;
240
- o: z.ZodString;
241
- f: z.ZodString;
242
- q: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
243
- p: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
244
- ap: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
245
- X: z.ZodString;
246
- l: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
247
- z: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
248
- T: z.ZodNumber;
249
- }, z.core.$strip>;
250
- }, z.core.$strip>;
251
- type WsForceOrderPayload = z.infer<typeof WsForceOrderPayloadSchema>;
252
- declare const WsCompositeIndexPayloadSchema: z.ZodObject<{
253
- e: z.ZodLiteral<"compositeIndex">;
254
- E: z.ZodNumber;
255
- s: z.ZodString;
256
- p: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
257
- c: z.ZodArray<z.ZodObject<{
258
- b: z.ZodString;
259
- q: z.ZodString;
260
- w: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
261
- p: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
262
- }, z.core.$strip>>;
263
- }, z.core.$strip>;
264
- type WsCompositeIndexPayload = z.infer<typeof WsCompositeIndexPayloadSchema>;
265
- declare const WsAssetIndexPayloadSchema: z.ZodObject<{
266
- e: z.ZodLiteral<"assetIndex">;
267
- E: z.ZodNumber;
268
- s: z.ZodString;
269
- i: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
270
- b: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
271
- a: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
272
- }, z.core.$strip>;
273
- type WsAssetIndexPayload = z.infer<typeof WsAssetIndexPayloadSchema>;
274
- declare const WsRollingWindowTickerPayloadSchema: z.ZodObject<{
275
- e: z.ZodEnum<{
276
- "1hTicker": "1hTicker";
277
- "4hTicker": "4hTicker";
278
- "1dTicker": "1dTicker";
279
- "7dTicker": "7dTicker";
280
- "30dTicker": "30dTicker";
281
- }>;
282
- E: z.ZodNumber;
283
- s: z.ZodString;
284
- p: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
285
- P: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
286
- o: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
287
- h: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
288
- l: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
289
- c: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
290
- v: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
291
- q: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
292
- O: z.ZodNumber;
293
- C: z.ZodNumber;
294
- }, z.core.$strip>;
295
- type WsRollingWindowTickerPayload = z.infer<typeof WsRollingWindowTickerPayloadSchema>;
296
- declare const WsSpotAvgPricePayloadSchema: z.ZodObject<{
297
- e: z.ZodLiteral<"avgPrice">;
298
- E: z.ZodNumber;
299
- s: z.ZodString;
300
- i: z.ZodString;
301
- w: z.ZodPipe<z.ZodString, z.ZodTransform<number, string>>;
302
- T: z.ZodNumber;
303
- }, z.core.$strip>;
304
- type WsSpotAvgPricePayload = z.infer<typeof WsSpotAvgPricePayloadSchema>;
305
- type WsStreamPayload = WsKlinePayload | WsAggTradePayload | WsTradePayload | WsDepthUpdatePayload | WsTicker24hrPayload | WsBookTickerPayload | WsMarkPricePayload | WsMiniTickerPayload | WsForceOrderPayload | WsCompositeIndexPayload | WsAssetIndexPayload | WsRollingWindowTickerPayload | WsSpotAvgPricePayload;
306
- declare function parseWsPayload(streamName: string, raw: unknown): WsStreamPayload;
822
+ } | undefined, atMs?: number): Record<string, unknown>;
823
+ /**
824
+ * Format a simulator float as a clean decimal string. The simulator's
825
+ * internal arithmetic is IEEE-754 (by design — it is a model, not a ledger),
826
+ * so raw `String(number)` would leak representation noise (`0.1 + 0.2` →
827
+ * `0.30000000000000004`). Twelve significant digits strips that noise while
828
+ * staying far finer than any Binance tick; the boundary stays decimal-exact
829
+ * from here on (trackers, `Decimal`, ledger math).
830
+ */
831
+ declare function decimalString(value: number): string;
832
+
833
+ /** Session tuning accepted by {@link ExecutionPlatform.startUserSession}. */
834
+ type UserSessionTuning = Pick<UserStreamSessionOptions, 'keepAliveIntervalMs' | 'keepAliveFailuresBeforeRotation' | 'reconnectAttemptsBeforeRotation' | 'connection' | 'socketFactory'>;
835
+ /** Paper backend wiring: which simulator sits in the "server" seat. */
836
+ interface PaperBackendOptions {
837
+ /** The simulator whose fills the session replays as user-data frames. */
838
+ engine: PaperTradingEngine;
839
+ /** Report source — the adapter orders flow through. */
840
+ adapter: PaperExecutionAdapter;
841
+ }
842
+ /** Either session flavor a platform can hold: live (listen key) or paper. */
843
+ type PlatformUserSession = UserStreamSession | PaperSession;
844
+ /** Options for {@link ExecutionPlatform}. */
845
+ interface ExecutionPlatformOptions {
846
+ /** Product the platform serves — decides listen-key REST routes and WS URL. */
847
+ product: 'usdm' | 'spot';
848
+ /**
849
+ * Shared runtime: REST hosts (listen-key calls), resolved endpoints (user
850
+ * WS URL) and the observability bus. Same context every product client
851
+ * holds — one weight budget, one event stream.
852
+ */
853
+ core: Pick<CoreContext, 'endpoints' | 'events' | 'http'>;
854
+ /**
855
+ * Execution manager to auto-attach when a session starts: its intent ledger
856
+ * then tracks live fills from the stream (`setUserStream`), and detaches
857
+ * when the session closes.
858
+ */
859
+ executionManager?: ExecutionManager;
860
+ /** Order-record retention; default 5000. */
861
+ maxTrackedOrders?: number;
862
+ /**
863
+ * Paper backend wiring. When set, the platform runs in paper mode:
864
+ * `startUserSession()` opens a {@link PaperSession} (no listen key, no
865
+ * socket) that replays simulator fills as user-data frames, and
866
+ * `reconcile()` folds the simulator's own state. See
867
+ * {@link createPaperExecutionPlatform} for the assembled runtime.
868
+ */
869
+ paper?: PaperBackendOptions;
870
+ }
871
+ /**
872
+ * v3 execution platform — one product's live trading state.
873
+ *
874
+ * Milestone 3 composition root: a managed user-data stream session, the
875
+ * order/position feeds it drives, and the semantic retry classifier, all over
876
+ * a shared {@link CoreContext}. The raw API layer (`trading.createOrder`) and
877
+ * the intent layer (`execution.placeOrder`) stay where they were; the platform
878
+ * adds the *account view* — what is live right now, fed by the exchange
879
+ * itself:
880
+ *
881
+ * ```ts
882
+ * const usdm = new USDMClient(core);
883
+ * await usdm.executionPlatform.startUserSession();
884
+ *
885
+ * await usdm.execution.placeOrder({ symbol: 'BTCUSDT', side: 'BUY', … });
886
+ * // execution ledger now updates from the stream, and:
887
+ * usdm.executionPlatform.orders.get('nbsdk-…'); // live OrderRecord
888
+ * usdm.executionPlatform.positions.get('BTCUSDT'); // live PositionRecord
889
+ * usdm.executionPlatform.classify(err).safety; // 'reconciliation-required'
890
+ * ```
891
+ *
892
+ * Milestone 4 adds two capabilities on the same boundary:
893
+ * - **`reconcile()`** — a REST snapshot (open orders + position risk) folded
894
+ * into the trackers: the startup gap-fill for orders that existed before
895
+ * the stream went live, and the recovery pass after a disconnect.
896
+ * - **paper mode** — with the `paper` option (see
897
+ * {@link createPaperExecutionPlatform}) the session, trackers and
898
+ * reconcile semantics run against the local simulator instead.
899
+ *
900
+ * Standalone use (any product wiring, custom listen-key backends for tests):
901
+ *
902
+ * ```ts
903
+ * const platform = new ExecutionPlatform({ product: 'usdm', core });
904
+ * ```
905
+ */
906
+ declare class ExecutionPlatform {
907
+ readonly product: 'usdm' | 'spot';
908
+ readonly orders: OrderTracker;
909
+ readonly positions: PositionTracker;
910
+ private readonly core;
911
+ private readonly executionManager?;
912
+ private readonly paperBackend?;
913
+ private sessionValue;
914
+ constructor(options: ExecutionPlatformOptions);
915
+ /** The live user-data stream session, or null before `startUserSession`. */
916
+ get userSession(): PlatformUserSession | null;
917
+ /**
918
+ * The live session when it is a listen-key session (REST-wired products).
919
+ * Null in paper mode — the paper session carries no listen key.
920
+ */
921
+ get liveUserSession(): UserStreamSession | null;
922
+ /** True when the platform runs against the paper simulator. */
923
+ get isPaper(): boolean;
924
+ /** True once a session has been started (cheap, no I/O). */
925
+ hasUserSession(): boolean;
926
+ /**
927
+ * Start the managed user-data stream: create the listen key, connect, run
928
+ * the 30-minute keep-alive, rotate on failure. The platform's order and
929
+ * position feeds go live immediately, and the attached execution manager
930
+ * (when one was provided) begins tracking live fills.
931
+ *
932
+ * In paper mode there is nothing to connect: the returned
933
+ * {@link PaperSession} replays simulator fills as user-data frames through
934
+ * the exact same `userData` contract — the trackers go live identically.
935
+ */
936
+ startUserSession(tuning?: UserSessionTuning): Promise<PlatformUserSession>;
937
+ /** Classify an error for retry semantics — see {@link classifyRetrySafety}. */
938
+ classify(error: unknown): RetryClassification;
939
+ /**
940
+ * Fold a REST snapshot of the account into the trackers — the gap-fill the
941
+ * user stream cannot provide: orders that existed *before* the session went
942
+ * live, and the authoritative position state after any disconnect.
943
+ *
944
+ * Live mode pulls `GET /fapi/v1/openOrders` (or per-symbol Spot
945
+ * `openOrders`) and `GET /fapi/v2/positionRisk` over the shared core
946
+ * transports; paper mode folds the simulator's own book. Returns how many
947
+ * views were folded; every fold emits the same `order.updated` /
948
+ * `position.updated` events stream folds do.
949
+ *
950
+ * ```ts
951
+ * await platform.startUserSession();
952
+ * const summary = await platform.reconcile(); // startup gap-fill
953
+ * summary.orders; summary.positions;
954
+ * ```
955
+ */
956
+ reconcile(options?: ReconcileOptions): Promise<ReconciliationSummary>;
957
+ /** Close the session (stop keep-alive, disconnect, delete the key). Trackers keep their records. */
958
+ close(): void;
959
+ /** Shared wiring for both session flavors: feed the trackers, remember it. */
960
+ private attachSession;
961
+ }
962
+
963
+ /**
964
+ * v3 state platform — managed local book.
965
+ *
966
+ * The pure {@link OrderBook} owns the L2 algorithm (snapshot + diff + gap
967
+ * detection, exact-decimal levels). {@link ManagedBook} owns the *lifecycle*
968
+ * around it: the canonical Binance sync dance (buffer diffs while the REST
969
+ * snapshot is in flight, apply the tail that overlaps the snapshot), a
970
+ * consumer-visible sync state, events, and the `waitForSync()` promise —
971
+ * the same ergonomics the execution platform's trackers have.
972
+ */
973
+ /** Consumer-visible lifecycle of one managed book. */
974
+ type ManagedBookState = 'syncing' | 'live' | 'desynced' | 'closed';
975
+ /** Event payload for `update` — a cheap top-of-book summary. */
976
+ interface BookUpdateEvent {
977
+ symbol: string;
978
+ lastUpdateId: number | null;
979
+ bestBid: string | null;
980
+ bestAsk: string | null;
981
+ }
982
+ /** Event payload for `desync` / `resynced` / `synced`. */
983
+ interface BookSyncEvent {
984
+ symbol: string;
985
+ /** Last applied update id (null before the first snapshot). */
986
+ lastUpdateId: number | null;
987
+ /** Desync reason, when known (`sequence-gap` | `interrupted` | `snapshot-stream-race`). */
988
+ reason?: string;
989
+ /** Diffs applied straight from the pre-snapshot buffer, when > 0. */
990
+ buffered?: number;
991
+ }
992
+ /** Options for {@link ManagedBook}. */
993
+ interface ManagedBookOptions {
994
+ /** Diffs buffered while the snapshot is in flight before the oldest drop. */
995
+ maxBufferedDiffs?: number;
996
+ }
997
+ /**
998
+ * One symbol's live book, managed end to end.
999
+ *
1000
+ * ```ts
1001
+ * const book = await engine.watch('BTCUSDT'); // resolves once synced
1002
+ * book.state; // 'live'
1003
+ * book.bestBid; // { price: '42150.10', quantity: '2.5' } — exact
1004
+ * book.metrics(); // spread, microprice, imbalance, depth…
1005
+ * book.on('update', (e) => log(e.bestBid));
1006
+ * await book.waitForSync(); // after a desync, resolves on recovery
1007
+ * ```
1008
+ *
1009
+ * The book is a *view* over the platform's pooled WS subscription and the
1010
+ * REST snapshot route — it never opens a socket or issues a request itself
1011
+ * (the {@link BookEngine} drives it).
1012
+ */
1013
+ declare class ManagedBook extends EventEmitter {
1014
+ readonly symbol: string;
1015
+ private readonly book;
1016
+ private stateValue;
1017
+ /** Diffs received before the first snapshot, applied (filtered) after it. */
1018
+ private readonly diffBuffer;
1019
+ private readonly maxBufferedDiffs;
1020
+ constructor(symbol: string, options?: ManagedBookOptions);
1021
+ /** Consumer-visible sync state. */
1022
+ get state(): ManagedBookState;
1023
+ /** True while the local book mirrors the exchange book. */
1024
+ get isSynced(): boolean;
1025
+ /** Best bid level (exact decimal strings) or null when the bid side is empty. */
1026
+ get bestBid(): BookLevel | null;
1027
+ /** Best ask level (exact decimal strings) or null when the ask side is empty. */
1028
+ get bestAsk(): BookLevel | null;
1029
+ /** Mid price (exact decimal string) or null when one-sided. */
1030
+ get midPrice(): string | null;
1031
+ /** Top-of-book metrics (spread, microprice, imbalance, depth, …). */
1032
+ metrics(depthPct?: number): OrderBookMetrics;
1033
+ /** Bid levels (best first), for display/snapshotting. */
1034
+ bids(limit: number): BookLevel[];
1035
+ /** Ask levels (best first), for display/snapshotting. */
1036
+ asks(limit: number): BookLevel[];
1037
+ /** Last applied update id (null before the first snapshot). */
1038
+ get lastUpdateId(): number | null;
1039
+ /**
1040
+ * Resolve once the book is synced. Rejects on timeout or terminal close.
1041
+ * Safe to call repeatedly; also the recovery signal after a desync.
1042
+ */
1043
+ waitForSync(timeoutMs?: number): Promise<void>;
1044
+ /** Terminal close — the engine calls this on unwatch/engine close. */
1045
+ close(): void;
1046
+ /**
1047
+ * Feed one depth diff. Before the first snapshot the diff buffers (the
1048
+ * canonical Binance sync algorithm); after it, a failed apply means a
1049
+ * sequence gap — the book desyncs and the engine must resnapshot.
1050
+ * @internal
1051
+ */
1052
+ receiveDiff(diff: DiffInput): void;
1053
+ /**
1054
+ * Apply a REST snapshot, then the buffered diff tail that overlaps it.
1055
+ * This is the only path from `syncing`/`desynced` back to `live`.
1056
+ * @internal
1057
+ */
1058
+ applySnapshot(snapshot: BookSnapshotInput): void;
1059
+ /**
1060
+ * Mark the book desynced without a gap event — the engine knows the stream
1061
+ * was interrupted (a reconnect implies missed diffs by construction).
1062
+ * @internal
1063
+ */
1064
+ markInterrupted(reason?: string): void;
1065
+ private applyLiveDiff;
1066
+ private emitUpdate;
1067
+ }
1068
+
1069
+ /**
1070
+ * v3 state platform — multi-symbol local book manager.
1071
+ *
1072
+ * The v2 `OrderBookEngine` wired books to a connection-centric WS class and
1073
+ * re-ran the snapshot after subscribing. The v3 engine keeps the pure L2
1074
+ * algorithm (it lives in `OrderBook`, unchanged) and rebuilds everything
1075
+ * around it on the platform surfaces:
1076
+ *
1077
+ * - streams come from the **pooled WS platform** (`core.ws.usdm/spot`) —
1078
+ * connection placement, renewal and reconnects are the platform's problem;
1079
+ * - snapshots come from the **shared REST transports** (`core.http(...)`) —
1080
+ * same weight budget, same mocks, same environment as everything else;
1081
+ * - the sync algorithm is the canonical Binance one: diffs buffer while the
1082
+ * first snapshot is in flight, and the tail that overlaps the snapshot
1083
+ * applies on top of it — no blind window, no resubscribe dance;
1084
+ * - an interrupted subscription marks the book desynced *immediately* (the
1085
+ * missed-diffs fact is known before any frame says so) and a resync with
1086
+ * backoff repairs it.
1087
+ *
1088
+ * ```ts
1089
+ * const engine = new BookEngine({ core, product: 'usdm' });
1090
+ * const book = await engine.watch('BTCUSDT'); // resolves once synced
1091
+ * book.bestBid; // exact decimal strings
1092
+ * await engine.unwatch('BTCUSDT');
1093
+ * engine.close();
1094
+ * ```
1095
+ */
1096
+ /** Options for {@link BookEngine}. */
1097
+ interface BookEngineOptions {
1098
+ product: 'usdm' | 'spot';
1099
+ /** Shared runtime: pooled WS subscriptions + REST snapshot transports. */
1100
+ core: Pick<CoreContext, 'http' | 'events' | 'ws'>;
1101
+ /** Diff update speed; default `100ms`. */
1102
+ updateSpeed?: '100ms' | '500ms';
1103
+ /** REST snapshot depth (levels); default 1000. */
1104
+ snapshotLimit?: number;
1105
+ /** Backoff between resync attempts after a desync. Default 1000ms. */
1106
+ resyncDelayMs?: number;
1107
+ /** Per-book tuning (diff buffer size). */
1108
+ book?: ManagedBookOptions;
1109
+ }
1110
+ /**
1111
+ * Manages {@link ManagedBook}s across symbols on one product's stream family.
1112
+ *
1113
+ * Books are per-engine and per-symbol (a second `watch` of a live symbol
1114
+ * returns the existing book). The engine holds no sockets of its own — every
1115
+ * subscription rides the pooled platform connection, so depth streams share
1116
+ * connections with everything else the context runs.
1117
+ */
1118
+ declare class BookEngine {
1119
+ readonly product: 'usdm' | 'spot';
1120
+ private readonly core;
1121
+ private readonly updateSpeed;
1122
+ private readonly snapshotLimit;
1123
+ private readonly resyncDelayMs;
1124
+ private readonly bookOptions?;
1125
+ private readonly events?;
1126
+ private readonly books;
1127
+ private readonly subscriptions;
1128
+ /** Symbols with a resync in flight (dedup per symbol). */
1129
+ private readonly resyncing;
1130
+ private readonly messageHandler;
1131
+ private closed;
1132
+ constructor(options: BookEngineOptions);
1133
+ /**
1134
+ * Start maintaining a local book for `symbol`: subscribe the pooled depth
1135
+ * stream, buffer diffs, fetch the REST snapshot, apply the overlap, go
1136
+ * live. Resolves once the book is synced; throws (after unsubscribing)
1137
+ * when the snapshot cannot be fetched.
1138
+ */
1139
+ watch(symbol: string): Promise<ManagedBook>;
1140
+ /**
1141
+ * Stop maintaining a symbol: close the book and release its subscription
1142
+ * (refcounted — the server-level UNSUBSCRIBE fires only for the last
1143
+ * consumer). Idempotent; unknown symbols are a no-op.
1144
+ */
1145
+ unwatch(symbol: string): Promise<void>;
1146
+ /** The managed book for a symbol, if watching. */
1147
+ getBook(symbol: string): ManagedBook | undefined;
1148
+ /** All watched symbols (insertion order). */
1149
+ symbols(): string[];
1150
+ /** True while the engine is usable (not terminally closed). */
1151
+ get isClosed(): boolean;
1152
+ /** Close every book and release every subscription. Terminal; idempotent. */
1153
+ close(): void;
1154
+ /** The pooled stream family this product's depth streams ride on. */
1155
+ private family;
1156
+ /** Snapshot host: `fapi` (USDⓈ-M `/fapi/v1/depth`) or `spot` (`/api/v3/depth`). */
1157
+ private snapshotHttp;
1158
+ /** Fetch + apply one REST snapshot for a symbol. */
1159
+ private snapshot;
1160
+ /** One depth frame off the pooled subscription → the book for its symbol. */
1161
+ private onDepthFrame;
1162
+ /** Delayed, deduplicated resync after a desync. */
1163
+ private scheduleResync;
1164
+ }
1165
+
1166
+ /**
1167
+ * v3 USDⓈ-M futures product client.
1168
+ *
1169
+ * The full product surface over a shared {@link CoreContext} — identical
1170
+ * wiring to `client.futures` on the multi-product facade (same construction
1171
+ * path, same `ExecutionManager`, same WS URLs), but standing alone:
1172
+ *
1173
+ * ```ts
1174
+ * const usdm = new USDMClient(new CoreContext({ apiKey, apiSecret }));
1175
+ * await usdm.core.syncTime(); // shared clock sync
1176
+ * const fill = await usdm.execution.placeOrder({
1177
+ * symbol: 'BTCUSDT', side: 'BUY', type: 'MARKET', quantity: '0.01',
1178
+ * });
1179
+ * usdm.ws.bookTicker('BTCUSDT', handler); // product WS surface
1180
+ * usdm.close(); // product-scoped cleanup
1181
+ * ```
1182
+ *
1183
+ * What the v3 boundary adds over the v2 `createUSDMClient()` factory: the
1184
+ * core context is caller-visible (`usdm.core`) — transports, credentials
1185
+ * and the event bus are reachable without globals, and two product clients
1186
+ * can share one context (one weight budget, one observability stream).
1187
+ */
1188
+ declare class USDMClient implements ProductClient {
1189
+ readonly product: "usdm";
1190
+ readonly core: CoreContext;
1191
+ private readonly surface;
1192
+ private listenKeyValue;
1193
+ private keepAliveInterval;
1194
+ private executionPlatformValue;
1195
+ private bookEngineValue;
1196
+ private closed;
1197
+ constructor(core: CoreContext);
1198
+ get market(): UsdmSurface['market'];
1199
+ get data(): UsdmSurface['data'];
1200
+ get account(): UsdmSurface['account'];
1201
+ get trading(): UsdmSurface['trading'];
1202
+ get ops(): UsdmSurface['ops'];
1203
+ /** Idempotent order placement with transport-failure reconciliation. */
1204
+ get execution(): UsdmSurface['execution'];
1205
+ get userStream(): UsdmSurface['userStream'];
1206
+ get ws(): UsdmSurface['ws'];
1207
+ get wsUser(): UsdmSurface['wsUser'];
1208
+ get wsApi(): UsdmSurface['wsApi'];
1209
+ /**
1210
+ * The v3 execution platform: managed user-data stream session, live
1211
+ * order/position feeds, and semantic retry classification. Lazily built —
1212
+ * a REST-only caller never pays for it.
1213
+ *
1214
+ * ```ts
1215
+ * await usdm.executionPlatform.startUserSession();
1216
+ * usdm.executionPlatform.orders.get('nbsdk-…');
1217
+ * usdm.executionPlatform.positions.get('BTCUSDT');
1218
+ * ```
1219
+ */
1220
+ get executionPlatform(): ExecutionPlatform;
1221
+ /**
1222
+ * The v3 state platform for USDⓈ-M: managed local L2 books over the pooled
1223
+ * WS platform + shared REST snapshot transports. Lazily built — a
1224
+ * stream-only or REST-only caller never pays for it.
1225
+ *
1226
+ * ```ts
1227
+ * const book = await usdm.books.watch('BTCUSDT'); // resolves once synced
1228
+ * book.bestBid; // exact decimal strings
1229
+ * book.metrics(); // spread, imbalance, …
1230
+ * await usdm.books.unwatch('BTCUSDT');
1231
+ * ```
1232
+ */
1233
+ get books(): BookEngine;
1234
+ /**
1235
+ * Start the listen-key user-data stream: creates the key, schedules the
1236
+ * 30-minute keep-alive, and opens the user WS. Scoped to this product —
1237
+ * unlike the multi-product facade, no other product's sockets are touched.
1238
+ */
1239
+ startUserStream(): Promise<string>;
1240
+ /** Close the user stream (timer, socket, and listen-key deletion). */
1241
+ closeUserStream(): void;
1242
+ /** Close this product's resources. Safe to call more than once. */
1243
+ close(): void;
1244
+ }
1245
+
1246
+ /**
1247
+ * v3 Spot product client.
1248
+ *
1249
+ * The full Spot product surface over a shared {@link CoreContext} — identical
1250
+ * wiring to `client.spot` on the multi-product facade (same construction
1251
+ * path, same `ExecutionManager`, same WS URLs), but standing alone:
1252
+ *
1253
+ * ```ts
1254
+ * const spot = new SpotClient(new CoreContext({ apiKey, apiSecret }));
1255
+ * await spot.core.syncTime(); // shared clock sync
1256
+ * const fill = await spot.execution.placeOrder({
1257
+ * symbol: 'BTCUSDT', side: 'BUY', type: 'MARKET', quantity: '0.01',
1258
+ * });
1259
+ * spot.ws.bookTicker('BTCUSDT', handler); // product WS surface
1260
+ * spot.close(); // product-scoped cleanup
1261
+ * ```
1262
+ *
1263
+ * What the v3 boundary adds over the v2 `createSpotClient()` factory: the
1264
+ * core context is caller-visible (`spot.core`) — transports, credentials
1265
+ * and the event bus are reachable without globals, and two product clients
1266
+ * can share one context (one weight budget, one observability stream). It
1267
+ * also owns the v3 execution platform and the v3 state engine for Spot.
1268
+ */
1269
+ declare class SpotClient implements ProductClient {
1270
+ readonly product: "spot";
1271
+ readonly core: CoreContext;
1272
+ private readonly surface;
1273
+ private listenKeyValue;
1274
+ private keepAliveInterval;
1275
+ private executionPlatformValue;
1276
+ private bookEngineValue;
1277
+ private closed;
1278
+ constructor(core: CoreContext);
1279
+ get market(): SpotSurface['market'];
1280
+ get account(): SpotSurface['account'];
1281
+ get trading(): SpotSurface['trading'];
1282
+ /** Idempotent order placement with transport-failure reconciliation. */
1283
+ get execution(): SpotSurface['execution'];
1284
+ get userStream(): SpotSurface['userStream'];
1285
+ get ws(): SpotSurface['ws'];
1286
+ get wsUser(): SpotSurface['wsUser'];
1287
+ get wsApi(): SpotSurface['wsApi'];
1288
+ /**
1289
+ * The v3 execution platform for Spot: managed user-data stream session,
1290
+ * live order feeds, and semantic retry classification. Lazily built —
1291
+ * a REST-only caller never pays for it.
1292
+ *
1293
+ * ```ts
1294
+ * await spot.executionPlatform.startUserSession();
1295
+ * spot.executionPlatform.orders.get('nbsdk-…');
1296
+ * ```
1297
+ */
1298
+ get executionPlatform(): ExecutionPlatform;
1299
+ /**
1300
+ * The v3 state platform for Spot: managed local L2 books over the pooled
1301
+ * WS platform + shared REST snapshot transports. Lazily built — a
1302
+ * stream-only or REST-only caller never pays for it.
1303
+ *
1304
+ * ```ts
1305
+ * const book = await spot.books.watch('BTCUSDT'); // resolves once synced
1306
+ * book.bestBid; // exact decimal strings
1307
+ * book.metrics(); // spread, imbalance, …
1308
+ * await spot.books.unwatch('BTCUSDT');
1309
+ * ```
1310
+ */
1311
+ get books(): BookEngine;
1312
+ /**
1313
+ * Start the listen-key user-data stream: creates the key, schedules the
1314
+ * 30-minute keep-alive, and opens the user WS. Scoped to this product —
1315
+ * unlike the multi-product facade, no other product's sockets are touched.
1316
+ */
1317
+ startUserStream(): Promise<string>;
1318
+ /** Close the user stream (timer, socket, and listen-key deletion). */
1319
+ closeUserStream(): void;
1320
+ /** Close this product's resources. Safe to call more than once. */
1321
+ close(): void;
1322
+ }
1323
+
1324
+ /**
1325
+ * v3 COIN-M futures product client.
1326
+ *
1327
+ * The full COIN-M product surface over a shared {@link CoreContext} —
1328
+ * identical wiring to `client.coinm` on the multi-product facade (same
1329
+ * construction path, same resources, same WS URLs), but standing alone:
1330
+ *
1331
+ * ```ts
1332
+ * const coinm = new CoinMClient(new CoreContext({ apiKey, apiSecret }));
1333
+ * await coinm.core.syncTime(); // shared clock sync
1334
+ * const quote = await coinm.market.markPrice('BTCUSD_PERP');
1335
+ * coinm.ws.bookTicker('BTCUSD_PERP', handler); // product WS surface
1336
+ * coinm.close(); // product-scoped cleanup
1337
+ * ```
1338
+ *
1339
+ * What the v3 boundary adds over the v2 `createCoinMClient()` factory: the
1340
+ * core context is caller-visible (`coinm.core`) — transports, credentials
1341
+ * and the event bus are reachable without globals, and two product clients
1342
+ * can share one context (one weight budget, one observability stream).
1343
+ *
1344
+ * **Note on the v3 execution platform / state engine:** COIN-M does not yet
1345
+ * have its own `ExecutionPlatform` or `BookEngine` — those modules are
1346
+ * currently wired for `'usdm' | 'spot'` only. The full surface (`market`,
1347
+ * `account`, `trading`, `execution`, `userStream`, `ws`, `wsUser`) is here
1348
+ * and runs over the shared transports; the managed user-data session and
1349
+ * the L2 book engine for COIN-M are the next follow-up. Until then, the
1350
+ * manual `startUserStream()` path (listen key + 30-minute keep-alive +
1351
+ * user WS) is the way to consume COIN-M user data through this client.
1352
+ */
1353
+ declare class CoinMClient implements ProductClient {
1354
+ readonly product: "coinm";
1355
+ readonly core: CoreContext;
1356
+ private readonly surface;
1357
+ private listenKeyValue;
1358
+ private keepAliveInterval;
1359
+ private closed;
1360
+ constructor(core: CoreContext);
1361
+ get market(): CoinMSurface['market'];
1362
+ get account(): CoinMSurface['account'];
1363
+ get trading(): CoinMSurface['trading'];
1364
+ get userStream(): CoinMSurface['userStream'];
1365
+ get ws(): CoinMSurface['ws'];
1366
+ get wsUser(): CoinMSurface['wsUser'];
1367
+ /**
1368
+ * Start the listen-key user-data stream: creates the key, schedules the
1369
+ * 30-minute keep-alive, and opens the user WS. Scoped to this product —
1370
+ * unlike the multi-product facade, no other product's sockets are touched.
1371
+ */
1372
+ startUserStream(): Promise<string>;
1373
+ /** Close the user stream (timer, socket, and listen-key deletion). */
1374
+ closeUserStream(): void;
1375
+ /** Close this product's resources. Safe to call more than once. */
1376
+ close(): void;
1377
+ }
1378
+
1379
+ /**
1380
+ * Endpoint registry — machine-readable map of every REST endpoint this SDK
1381
+ * implements, the single source of truth consumed by:
1382
+ *
1383
+ * - `docs/endpoint-map/*.md` (generated by scripts/generate-endpoint-map.ts)
1384
+ * - `llms.txt` / `llms-full.txt` (agent-facing docs, also generated)
1385
+ * - tooling/CI (coverage accounting vs. Binance's published API surface)
1386
+ *
1387
+ * Registry entries are hand-curated but mechanically *checked*: the
1388
+ * `scripts/generate-endpoint-map.ts` script greps `src/resources` for live
1389
+ * `http.<verb>(...)` calls and fails when a registered endpoint is not
1390
+ * actually implemented (or vice versa), so the map cannot drift silently.
1391
+ */
1392
+ type EndpointAuth = 'public' | 'apiKey' | 'signed';
1393
+ type EndpointMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
1394
+ interface EndpointEntry {
1395
+ /** Binance product family. */
1396
+ product: 'spot' | 'usdm' | 'coinm' | 'margin' | 'wallet' | 'subaccount';
1397
+ /** SDK surface implementing it, e.g. `futures.trading.createOrder`. */
1398
+ operation: string;
1399
+ method: EndpointMethod;
1400
+ path: string;
1401
+ authentication: EndpointAuth;
1402
+ /** Documented request weight where known (IP weight unless noted). */
1403
+ weight?: number;
1404
+ /** Resource class + method implementing the call. */
1405
+ implementedBy: string;
1406
+ }
1407
+ /** Every implemented endpoint, across all products. */
1408
+ declare const ENDPOINT_REGISTRY: readonly EndpointEntry[];
1409
+ interface EndpointQuery {
1410
+ product?: EndpointEntry['product'];
1411
+ method?: EndpointMethod;
1412
+ authentication?: EndpointAuth;
1413
+ pathPrefix?: string;
1414
+ }
1415
+ declare function listEndpoints(query?: EndpointQuery): readonly EndpointEntry[];
1416
+ declare function findEndpoint(path: string, method?: EndpointMethod): EndpointEntry | undefined;
1417
+ /** Per-product coverage counts for docs/CI. */
1418
+ declare function endpointCounts(): Record<string, number>;
1419
+
1420
+ /**
1421
+ * API contract layer — the machine-readable view of the Binance REST surface
1422
+ * this SDK implements.
1423
+ *
1424
+ * The registry (src/registry) already lists every endpoint (operation, method,
1425
+ * path, authentication, implementer). This layer is the *contract* consumers
1426
+ * build on top of that list:
1427
+ *
1428
+ * - normalized **security schemes** (`none` / `apiKey` / `signature`) instead
1429
+ * of ad-hoc auth strings;
1430
+ * - **declared request weights** for the endpoints where Binance documents a
1431
+ * param-independent weight — informational only, response headers
1432
+ * (`X-MBX-USED-WEIGHT-*`) remain the source of truth for accounting;
1433
+ * - **path canonicalization** so a bare resource path (`/order`) resolves to
1434
+ * the registry's canonical form (`/api/v3/order`) using the HttpClient's
1435
+ * base URL — this is what lets the observability bus attach contract
1436
+ * metadata to every `http.request.*` event;
1437
+ * - a single query API (`getContract`, `findContract`, `listContracts`) for
1438
+ * tooling, docs generation and agent-facing surfaces.
1439
+ *
1440
+ * This is the stepping stone toward a fully generated contract layer (OpenAPI
1441
+ * spec → typed clients); the query surface below is deliberately shaped so a
1442
+ * generated implementation can replace the hand-curated backing store without
1443
+ * changing any consumer.
1444
+ */
1445
+
1446
+ /** Normalized security scheme an endpoint requires. */
1447
+ type EndpointSecurityScheme = 'none' | 'apiKey' | 'signature';
1448
+ /**
1449
+ * A single endpoint's contract: registry entry + normalized security scheme +
1450
+ * declared weight (where Binance documents a param-independent one).
1451
+ */
1452
+ interface EndpointContract extends EndpointEntry {
1453
+ security: EndpointSecurityScheme;
1454
+ /** Documented request weight where param-independent; see file docs. */
1455
+ declaredWeight?: number;
1456
+ }
1457
+ /**
1458
+ * Resolve a resource-supplied path against an HttpClient base URL to the
1459
+ * registry's canonical path. Bare paths (`/order`) are prefixed with the base
1460
+ * URL's own path segment (`https://…/api/v3` → `/api/v3/order`); paths that
1461
+ * already carry a version prefix pass through unchanged.
1462
+ */
1463
+ declare function canonicalPath(baseURL: string, path: string): string;
1464
+ /** Contract for a canonical path + method, or undefined when unknown. */
1465
+ declare function findContract(canonical: string, method?: EndpointMethod): EndpointContract | undefined;
1466
+ /** Contract lookup by product + operation, e.g. ('spot', 'trading.createOrder'). */
1467
+ declare function getContract(product: EndpointEntry['product'], operation: string): EndpointContract | undefined;
1468
+ /** Contract metadata attached to `http.request.*` observability events. */
1469
+ interface HttpContractMeta {
1470
+ product: EndpointEntry['product'];
1471
+ operation: string;
1472
+ authentication: EndpointAuth;
1473
+ security: EndpointSecurityScheme;
1474
+ declaredWeight: number | undefined;
1475
+ }
1476
+ /**
1477
+ * Resolve the contract for a request as the HttpClient sees it: base URL +
1478
+ * method + resource path. Returns undefined for unregistered paths (e.g.
1479
+ * host-level time endpoints reused across products).
1480
+ */
1481
+ declare function contractFor(baseURL: string, method: string, path: string): HttpContractMeta | undefined;
1482
+ /** One-line human description, for logs and agent-facing docs. */
1483
+ declare function describeContract(contract: EndpointContract): string;
1484
+
1485
+ /** The pooled connection classes the platform already ships per family. */
1486
+ type PooledConnection = FuturesMarketWS | SpotMarketWS | CoinMMarketWS;
1487
+ interface FamilyConnectionPoolOptions {
1488
+ family: WsFamily;
1489
+ /** Combined-stream base URL for the family (from core.endpoints). */
1490
+ baseStreamUrl: string;
1491
+ /** Cap on pooled connections; default is the family's documented default. */
1492
+ maxConnections?: number;
1493
+ /** Reconnect backoff; default jittered exponential. */
1494
+ reconnectPolicy?: ReconnectPolicy;
1495
+ /** Observability bus. */
1496
+ events?: EventBus;
1497
+ /** Injectable WebSocket factory for tests. */
1498
+ socketFactory?: (url: string) => WebSocket;
1499
+ /** Control-request ack timeout. Default 10s. */
1500
+ requestTimeoutMs?: number;
1501
+ /**
1502
+ * Called exactly once per created connection so the platform can wire
1503
+ * heartbeat liveness and centralized renewal (the pool itself never
1504
+ * schedules timers beyond the connection's own reconnect backoff).
1505
+ */
1506
+ onConnection?: (name: string, conn: PooledConnection) => void;
1507
+ }
1508
+ /**
1509
+ * Capacity-aware connection pool for one market-stream family.
1510
+ *
1511
+ * Binance documents a per-connection stream ceiling (200 for futures, 1024
1512
+ * for spot); the pool packs streams onto the least-loaded connection with
1513
+ * capacity and opens another connection (up to `maxConnections`) when every
1514
+ * existing one is full — so a 500-stream workload spreads across 3 USDⓈ-M
1515
+ * connections automatically instead of failing server-side.
1516
+ *
1517
+ * Pool-managed connections:
1518
+ * - disable the built-in 23h rotation timer (renewal is centralized in
1519
+ * {@link RenewalController} for stagger and observability);
1520
+ * - disable the built-in liveness watchdog (pool-level {@link WsHeartbeat}
1521
+ * uses one timer for all connections);
1522
+ * - use the platform reconnect policy (jittered backoff, so a pool-wide
1523
+ * outage does not retry in lockstep).
1524
+ */
1525
+ declare class FamilyConnectionPool {
1526
+ readonly family: WsFamily;
1527
+ private readonly baseStreamUrl;
1528
+ private readonly maxConnections;
1529
+ private readonly maxStreamsPerConnection;
1530
+ private readonly events?;
1531
+ private readonly socketFactory?;
1532
+ private readonly requestTimeoutMs;
1533
+ private readonly onConnection?;
1534
+ private readonly createConnection;
1535
+ private readonly pool;
1536
+ constructor(options: FamilyConnectionPoolOptions);
1537
+ /**
1538
+ * Pick the connection that should carry `newStreams` — the least-loaded one
1539
+ * with capacity, or a newly created one. Creates never perform I/O: the
1540
+ * returned connection connects lazily on first `subscribe()`.
1541
+ *
1542
+ * Throws when every connection is at the documented stream ceiling and the
1543
+ * `maxConnections` cap is reached — the caller is over the family's
1544
+ * capacity and must raise the cap.
1545
+ */
1546
+ selectOrCreate(newStreams: readonly string[]): PooledConnection;
1547
+ /** Live pooled connections (copy). */
1548
+ connections(): PooledConnection[];
1549
+ /** Number of pooled connections. */
1550
+ size(): number;
1551
+ /** Structural snapshot (cheap, no I/O). */
1552
+ stats(): WsConnectionStats[];
1553
+ /** Close every pooled connection. Safe repeatedly. */
1554
+ closeAll(): void;
1555
+ /** Next pool-assigned connection name, e.g. `usdmMarket[3]`. */
1556
+ private nextName;
1557
+ }
1558
+
1559
+ /**
1560
+ * Stream-level routing over one family's connection pool.
1561
+ *
1562
+ * Responsibilities:
1563
+ *
1564
+ * - **Refcounting** — N `Subscription` objects for one stream name share a
1565
+ * single server-level subscription; the last `close()` issues the protocol
1566
+ * UNSUBSCRIBE.
1567
+ * - **Fan-out** — one `message` listener per pooled connection dispatches
1568
+ * frames to every live subscription for that stream (parsed payload plus
1569
+ * lossless raw view).
1570
+ * - **Reconnect transparency** — when a pooled connection drops, its
1571
+ * subscriptions flip to `pending`; after the connection's own repair
1572
+ * (reconnect or rotation, followed by its resynchronize pass) the registry
1573
+ * re-marks every server-confirmed stream `live`.
1574
+ *
1575
+ * The registry never subscribes the same stream on two connections of the
1576
+ * same family — a stream maps to exactly one connection while it has
1577
+ * subscribers.
1578
+ */
1579
+ declare class FamilySubscriptionRegistry {
1580
+ private readonly pool;
1581
+ private readonly events?;
1582
+ private readonly confirmTimeoutMs;
1583
+ private readonly mappings;
1584
+ /** Connections whose dispatch listeners are attached (bounded by pool cap). */
1585
+ private readonly attached;
1586
+ constructor(options: {
1587
+ pool: FamilyConnectionPool;
1588
+ events?: EventBus;
1589
+ requestTimeoutMs?: number;
1590
+ });
1591
+ /**
1592
+ * Acquire a subscription for one stream, confirming it server-side. When
1593
+ * the stream already has subscribers this is a pure fan-out join (no I/O).
1594
+ *
1595
+ * Rejects when confirmation does not arrive within `confirmTimeoutMs`;
1596
+ * the subscription stays registered in that case — it flips to `live` via
1597
+ * the reconnect/repair path and remains reachable through
1598
+ * {@link FamilySubscriptionRegistry.getSubscription}.
1599
+ */
1600
+ acquire(stream: string, options?: SubscribeOptions): Promise<Subscription>;
1601
+ private doAcquire;
1602
+ /**
1603
+ * Release a subscription (refcount down). The last release for a stream
1604
+ * removes the mapping and issues the protocol UNSSUBSCRIBE (best-effort —
1605
+ * desired state is already dropped, so reconnects will not resurrect it).
1606
+ * Invoked automatically by {@link Subscription.close}.
1607
+ */
1608
+ release(subscription: Subscription): void;
1609
+ /** Active subscription object for a stream, if one is registered. */
1610
+ getSubscription(stream: string): Subscription | undefined;
1611
+ /** Streams with at least one live subscription. */
1612
+ activeStreams(): string[];
1613
+ /** Registry snapshot: streams per connection. */
1614
+ stats(): {
1615
+ streams: number;
1616
+ connections: number;
1617
+ };
1618
+ /** Close every subscription (platform teardown). */
1619
+ closeAll(): void;
1620
+ private attach;
1621
+ private markConnectionPending;
1622
+ private refreshConfirmed;
1623
+ }
1624
+
1625
+ /**
1626
+ * Minimal connection surface the heartbeat needs — implemented by
1627
+ * {@link WsConnection} and satisfiable by test stubs.
1628
+ */
1629
+ interface HeartbeatWatch {
1630
+ /** Connection label for events. */
1631
+ name?: string;
1632
+ getState(): string;
1633
+ /** ms since the last inbound frame; Infinity when never opened. */
1634
+ msSinceLastActivity(): number;
1635
+ /** Tear down into the reconnect path. */
1636
+ reconnect(): void;
1637
+ }
1638
+ interface WsHeartbeatOptions {
1639
+ /** Silence threshold that declares a connection dead. Default 10 min. */
1640
+ staleMs?: number;
1641
+ /** Sampling interval. Default 30s. */
1642
+ intervalMs?: number;
1643
+ /** Observability bus. */
1644
+ events?: EventBus;
1645
+ /** Injectable clock for tests. */
1646
+ now?: () => number;
1647
+ /** Injectable timer for tests (returns an unref-able handle). */
1648
+ setInterval?: (fn: () => void, ms: number) => {
1649
+ unref?: () => void;
1650
+ };
1651
+ }
1652
+ /**
1653
+ * Pool-level liveness watchdog with a *single* timer.
1654
+ *
1655
+ * `WsConnection` already supports per-connection `staleMs`, but v3 platforms
1656
+ * watch dozens of sockets; one tick beats N setInterval handles, and the
1657
+ * judgment (server pings every 3 minutes → 10 minutes of total silence means
1658
+ * the path is dead) lives in exactly one place. Protocol-level activity
1659
+ * (pings/pongs) counts as liveness via `msSinceLastActivity`.
1660
+ *
1661
+ * When a connection goes stale the heartbeat does not wait for TCP to notice:
1662
+ * it calls `reconnect()` (terminate + fresh socket), which is the correct
1663
+ * response to a half-open path.
1664
+ */
1665
+ declare class WsHeartbeat {
1666
+ private readonly staleMs;
1667
+ private readonly intervalMs;
1668
+ private readonly events?;
1669
+ private readonly now;
1670
+ private readonly timerFn;
1671
+ private readonly watched;
1672
+ private timer;
1673
+ constructor(options?: WsHeartbeatOptions);
1674
+ /** Start watching a connection under a stable key. */
1675
+ watch(key: string, conn: HeartbeatWatch): void;
1676
+ /** Stop watching (connection closed or pooled away). */
1677
+ unwatch(key: string): void;
1678
+ /** True when currently watched. */
1679
+ isWatching(key: string): boolean;
1680
+ /** Number of watched connections. */
1681
+ size(): number;
1682
+ /** Run one check immediately (also the interval body). */
1683
+ check(): {
1684
+ stale: string[];
1685
+ };
1686
+ start(): void;
1687
+ stop(): void;
1688
+ private ensureTicking;
1689
+ }
1690
+
1691
+ /**
1692
+ * Minimal connection surface the renewal controller needs — implemented by
1693
+ * {@link WsConnection} (an EventEmitter) and satisfiable by test stubs.
1694
+ *
1695
+ * Zero-gap rotation is transparent in the state machine: the connection stays
1696
+ * OPEN while the replacement connects, so completion is signalled by the
1697
+ * `rotated` / `rotationFailed` emitter events, not by state transitions.
1698
+ */
1699
+ interface RenewableConnection {
1700
+ on(event: 'state', listener: (to: string, from: string) => void): unknown;
1701
+ on(event: 'rotated', listener: () => void): unknown;
1702
+ on(event: 'rotationFailed', listener: (info: {
1703
+ code: number;
1704
+ reason: string;
1705
+ }) => void): unknown;
1706
+ off(event: 'state', listener: (to: string, from: string) => void): unknown;
1707
+ off(event: 'rotated', listener: () => void): unknown;
1708
+ off(event: 'rotationFailed', listener: (info: {
1709
+ code: number;
1710
+ reason: string;
1711
+ }) => void): unknown;
1712
+ getState(): string;
1713
+ /** Attempt a zero-gap rotation; false when not applicable. */
1714
+ rotateNow(): boolean;
1715
+ }
1716
+ interface RenewalControllerOptions {
1717
+ /**
1718
+ * Renewal window. Binance kills stream connections at 24h; the platform
1719
+ * rotates at 23h so the replacement carries traffic *before* the drop.
1720
+ * Default 23h.
1721
+ */
1722
+ rotationMs?: number;
1723
+ /**
1724
+ * Per-connection jitter (uniform [0, jitterMs)). Two connections opened in
1725
+ * the same millisecond would otherwise renew in the same millisecond — a
1726
+ * synchronized herd. Default 10 min.
1727
+ */
1728
+ jitterMs?: number;
1729
+ /**
1730
+ * Platform-wide cap on simultaneous renewals; the default 1 serializes
1731
+ * rotations so a pool of N connections renews one at a time.
1732
+ */
1733
+ maxConcurrent?: number;
1734
+ /** Observability bus. */
1735
+ events?: EventBus;
1736
+ /** Injectable randomness for tests; must return [0, 1). */
1737
+ random?: () => number;
1738
+ /** Injectable timer for tests. */
1739
+ setTimeout?: (fn: () => void, ms: number) => {
1740
+ unref?: () => void;
1741
+ };
1742
+ /** Postponement/retry interval. Default 30s. */
1743
+ retryMs?: number;
1744
+ }
1745
+ /**
1746
+ * Centralized, staggered 24h-safe renewal sequencing.
1747
+ *
1748
+ * `WsConnection` has a built-in 23h rotation timer; pool-managed connections
1749
+ * disable it (`rotationMs: 0`) and defer to this controller because:
1750
+ *
1751
+ * - **Decorrelation** — every connection gets a uniform jitter on top of the
1752
+ * 23h window, so a pool created at boot rotates across a spread, not a
1753
+ * synchronized herd.
1754
+ * - **Concurrency cap** — at most `maxConcurrent` rotations platform-wide;
1755
+ * a herd forced to serialize is a blip, not an event.
1756
+ * - **Observability** — `nextRenewalAt(name)` and `ws.renewal.*` events make
1757
+ * the rotation schedule inspectable instead of a hidden timer per socket.
1758
+ *
1759
+ * Renewals are zero-gap: the connection swaps sockets internally (traffic
1760
+ * keeps flowing on the old one until the replacement is open).
1761
+ */
1762
+ declare class RenewalController {
1763
+ private readonly rotationMs;
1764
+ private readonly jitterMs;
1765
+ private readonly maxConcurrent;
1766
+ private readonly events?;
1767
+ private readonly random;
1768
+ private readonly setTimeoutFn;
1769
+ private readonly retryMs;
1770
+ private readonly tracked;
1771
+ constructor(options?: RenewalControllerOptions);
1772
+ /**
1773
+ * Start centrally managing renewal for a connection. Scheduling anchors on
1774
+ * the connection reaching OPEN (or immediately, if already open), so a
1775
+ * tracked-but-not-yet-connected socket does not burn its rotation window.
1776
+ */
1777
+ track(name: string, conn: RenewableConnection): void;
1778
+ /** Stop managing a connection; safe to call for unknown names. */
1779
+ untrack(name: string): void;
1780
+ /** Epoch-ms of the next scheduled renewal, or null when idle/closed. */
1781
+ nextRenewalAt(name: string): number | null;
1782
+ /** True while a renewal is in flight for this connection. */
1783
+ isRenewing(name: string): boolean;
1784
+ /** Number of centrally managed connections. */
1785
+ size(): number;
1786
+ /** Stop managing everything. */
1787
+ close(): void;
1788
+ private scheduleRenewal;
1789
+ private fireRenewal;
1790
+ private countInFlight;
1791
+ }
1792
+
1793
+ /**
1794
+ * Reconnect backoff strategies.
1795
+ *
1796
+ * v2's {@link WsConnection} hard-coded `min(base * 2^attempt, max)`. The
1797
+ * platform keeps that as the default shape but makes it pluggable and adds
1798
+ * jitter: a reconnect storm (e.g. Binance restarting an edge) hits every
1799
+ * connection at once, and deterministic identical delays make the herd
1800
+ * collide on every subsequent attempt too. *Equal jitter* — half fixed, half
1801
+ * random — keeps the first retry responsive while decorrelating the herd.
1802
+ */
1803
+ interface ExponentialBackoffOptions {
1804
+ /** First-attempt delay. Default 1000ms. */
1805
+ baseMs?: number;
1806
+ /** Ceiling. Default 30000ms. */
1807
+ maxMs?: number;
1808
+ /** Random decorrelation; defaults on. Disable for deterministic tests. */
1809
+ jitter?: boolean;
1810
+ /** Injectable randomness for tests; must return [0, 1). */
1811
+ random?: () => number;
1812
+ }
1813
+ /**
1814
+ * Exponential backoff with equal jitter (default policy):
1815
+ * `raw = min(base * 2^attempt, max)`; returned delay is
1816
+ * `raw/2 + random() * raw/2` — always ≥ raw/2, ≤ raw.
1817
+ */
1818
+ declare function exponentialBackoff(options?: ExponentialBackoffOptions): ReconnectPolicy;
1819
+ /** Constant delay — reconnects at a fixed cadence regardless of attempt. */
1820
+ declare function fixedBackoff(delayMs: number): ReconnectPolicy;
1821
+ /** Linear backoff: `base * (attempt + 1)`, capped at `maxMs`. */
1822
+ declare function linearBackoff(options?: {
1823
+ baseMs?: number;
1824
+ maxMs?: number;
1825
+ }): ReconnectPolicy;
1826
+
1827
+ /**
1828
+ * Semantic retry classification for order operations.
1829
+ *
1830
+ * "Can I retry this?" is the first question every caller of a trading SDK
1831
+ * asks after an error, and the honest answer depends on *which* failure
1832
+ * occurred, not on generic error taxonomy:
1833
+ *
1834
+ * - a timeout on order placement leaves the outcome unknown — the order may
1835
+ * be live; retrying blind can double the position (`reconciliation-required`);
1836
+ * - a `-2013` after an ambiguous submission *proves* the order never reached
1837
+ * the engine — resubmission is free of risk (`safe`);
1838
+ * - `-1013` filter rejections are deterministic — the identical request
1839
+ * fails forever (`never-retry`).
1840
+ *
1841
+ * This module makes the SDK's answer explicit and testable. The execution
1842
+ * manager already *embodies* this matrix (its resubmit-after-`-2013` path is
1843
+ * the 'safe' branch; its `ExecutionUnknownError` is 'reconciliation-required'
1844
+ * made fatal); the classifier exposes the same reasoning to callers holding
1845
+ * raw errors, so agents and tools can decide without reimplementing it.
1846
+ *
1847
+ * Note on `'idempotent'`: the live exchange never earns it — Binance does not
1848
+ * enforce `newClientOrderId` uniqueness, so a "retry with the same key" is not
1849
+ * distinguishable from a second order. The category exists for backends whose
1850
+ * create operation is genuinely keyed (paper engines, future brokers).
1851
+ */
1852
+ /** Classify one error for retry semantics against the live exchange. */
1853
+ declare function classifyRetrySafety(error: unknown): RetryClassification;
1854
+ /** Narrow helper for switch-style consumers. */
1855
+ declare function isRetrySafety(value: unknown): value is RetrySafety;
1856
+
1857
+ /**
1858
+ * v3 paper execution platform — the assembled paper runtime.
1859
+ *
1860
+ * See `PaperSession.ts` for the session that replays simulator fills as
1861
+ * user-data frames; this module is the one-call wiring of the whole stack:
1862
+ * simulator + adapter + execution manager + execution platform, over one
1863
+ * shared {@link CoreContext}. Use {@link createPaperExecutionPlatform}.
1864
+ */
1865
+ /** Options for {@link createPaperExecutionPlatform}. */
1866
+ interface PaperExecutionPlatformOptions extends PaperTradingOptions {
1867
+ /**
1868
+ * Report source wiring: pass an adapter when one already routes this engine
1869
+ * (e.g. an existing gateway); a fresh one is built otherwise. The platform
1870
+ * registers its own listener — since M4, paper reports fan out to every
1871
+ * listener, so an execution manager over the same adapter keeps working.
1872
+ */
1873
+ adapter?: PaperExecutionAdapter;
1874
+ }
1875
+ /** The assembled paper execution platform. */
1876
+ interface PaperExecutionPlatform {
1877
+ /** Execution platform in paper mode — session, trackers, classify, reconcile. */
1878
+ platform: ExecutionPlatform;
1879
+ /** Paper-backed execution manager: idempotent place/cancel/reconcile. */
1880
+ execution: ExecutionManager;
1881
+ /** The simulator engine (account, positions, order history). */
1882
+ engine: PaperTradingEngine;
1883
+ /** The adapter orders flow through. */
1884
+ adapter: PaperExecutionAdapter;
1885
+ }
1886
+ /**
1887
+ * Build a complete paper trading runtime over a shared {@link CoreContext}:
1888
+ * simulator + adapter + execution manager + execution platform, all wired.
1889
+ *
1890
+ * This is "paper as a first-class execution backend": the same
1891
+ * {@link ExecutionPlatform} boundary live trading uses, with the simulator in
1892
+ * the server seat. Market prices come through the shared core transports
1893
+ * (testnet/demo envs and request mocks apply), so a paper run is the live
1894
+ * run with the matching engine swapped out.
1895
+ *
1896
+ * ```ts
1897
+ * const core = new CoreContext({ apiKey, apiSecret });
1898
+ * const paper = createPaperExecutionPlatform(core, { initialBalance: 25_000 });
1899
+ *
1900
+ * await paper.platform.startUserSession(); // no network — local session
1901
+ * const fill = await paper.execution.placeOrder({
1902
+ * symbol: 'BTCUSDT', side: 'BUY', type: 'MARKET', quantity: '0.01',
1903
+ * });
1904
+ * // the fill is already folded — same API as live:
1905
+ * paper.platform.orders.get(fill.clientOrderId); // OrderRecord (status: FILLED)
1906
+ * paper.platform.positions.get('BTCUSDT'); // PositionRecord (signed amount)
1907
+ * ```
1908
+ */
1909
+ declare function createPaperExecutionPlatform(core: CoreContext, options?: PaperExecutionPlatformOptions): PaperExecutionPlatform;
307
1910
 
308
1911
  declare class BinanceError extends Error {
309
1912
  constructor(message: string);
@@ -344,7 +1947,7 @@ declare class NetworkError extends BinanceError {
344
1947
  constructor(message: string, cause?: unknown);
345
1948
  }
346
1949
 
347
- type PolicyRule = 'readOnly' | 'symbolNotAllowed' | 'maxNotionalPerOrder' | 'notionalUndeterminable' | 'withdrawalsBlocked' | 'transfersBlocked' | 'blockedPath';
1950
+ type PolicyRule = 'readOnly' | 'symbolNotAllowed' | 'maxNotionalPerOrder' | 'notionalUndeterminable' | 'withdrawalsBlocked' | 'transfersBlocked' | 'blockedPath' | 'circuitBreaker' | 'maxLeverage' | 'maxOpenNotional' | 'maxDailyLoss';
348
1951
  /**
349
1952
  * Thrown when a request is refused by the client's own {@link TradingPolicy} — before it
350
1953
  * ever reaches Binance. Distinct from BinanceApiError, which reports an exchange rejection.
@@ -374,8 +1977,11 @@ declare class DryRunError extends BinanceError {
374
1977
  describe(): string;
375
1978
  }
376
1979
 
377
- declare function createBinanceMcpServer(client: BinanceClient): McpServer;
378
-
379
- declare const VERSION = "2.0.0";
1980
+ /**
1981
+ * MCP server over the toolkit. Pass `toolkit: { executionBackend: 'paper' }`
1982
+ * to route every order tool through the simulator — safe to expose to any
1983
+ * host without API-key trading risk.
1984
+ */
1985
+ declare function createBinanceMcpServer(client: BinanceClient, options?: FuturesToolkitOptions): McpServer;
380
1986
 
381
- export { BinanceApiError, type BinanceApiErrorContext, BinanceAuthError, BinanceClient, BinanceError, DryRunError, type Endpoints, type Environment, FuturesMarket, NetworkError, type PaperAccount, type PaperOrder, type PaperPosition, type PaperPositionSide, PaperTradingEngine, type PaperTradingOptions, type PolicyRule, PolicyViolationError, RateLimitError, VERSION, type WsAggTradePayload, WsAggTradePayloadSchema, type WsAssetIndexPayload, WsAssetIndexPayloadSchema, type WsBookTickerPayload, WsBookTickerPayloadSchema, type WsCompositeIndexPayload, WsCompositeIndexPayloadSchema, type WsDepthUpdatePayload, WsDepthUpdatePayloadSchema, type WsForceOrderPayload, WsForceOrderPayloadSchema, type WsKlinePayload, WsKlinePayloadSchema, type WsMarkPricePayload, WsMarkPricePayloadSchema, type WsMiniTickerPayload, WsMiniTickerPayloadSchema, type WsRollingWindowTickerPayload, WsRollingWindowTickerPayloadSchema, type WsSpotAvgPricePayload, WsSpotAvgPricePayloadSchema, type WsStreamPayload, type WsTicker24hrPayload, WsTicker24hrPayloadSchema, type WsTradePayload, WsTradePayloadSchema, createBinanceMcpServer, parseWsPayload, resolveEnvironment };
1987
+ export { BinanceApiError, type BinanceApiErrorContext, BinanceAuthError, BinanceClient, BinanceClientOptions, BinanceError, BookEngine, type BookEngineOptions, BookLevel, BookSnapshotInput, type BookSyncEvent, type BookUpdateEvent, CoinMClient, CoinMMarketWS, CoinMSurface, CoreContext, CreateOrderParams, DiffInput, DryRunError, ENDPOINT_REGISTRY, EXECUTION_PLATFORM_DEFAULTS, type EndpointAuth, type EndpointContract, type EndpointEntry, type EndpointMethod, type EndpointQuery, type EndpointSecurityScheme, EventBus, ExecutionAdapter, ExecutionFill, ExecutionManager, ExecutionPlatform, type ExecutionPlatformOptions, ExecutionReportShape, type ExponentialBackoffOptions, FamilyConnectionPool, type FamilyConnectionPoolOptions, FamilySubscriptionRegistry, FuturesMarketWS, FuturesToolkitOptions, type HttpContractMeta, type ListenKeyApi, ManagedBook, type ManagedBookOptions, type ManagedBookState, NetworkError, OrderBookMetrics, OrderKey, type OrderRecord, OrderShape, type OrderStatus, OrderTracker, type OrderTrackerOptions, type OrderUpdate, type PaperBackendOptions, PaperExecutionAdapter, type PaperExecutionPlatform, type PaperExecutionPlatformOptions, PaperSession, type PaperSessionOptions, PaperTradingEngine, PaperTradingOptions, type PlatformUserSession, type PolicyRule, PolicyViolationError, type PooledConnection, type PositionRecord, PositionTracker, type PositionTrackerOptions, type PositionUpdate, type ProductClient, type ProductFactory, type ProductId, RateLimitError, type ReconcileOptions, type ReconcileTarget, type ReconciliationSummary, ReconnectPolicy, type RenewableConnection, RenewalController, type RenewalControllerOptions, type RetryClassification, type RetrySafety, SpotClient, SpotMarketWS, SpotSurface, type CoinMClient$1 as StandaloneCoinMClient, type SpotClient$1 as StandaloneSpotClient, type USDMClient$1 as StandaloneUSDMClient, SubscribeOptions, Subscription, USDMClient, UsdmSurface, type UserEventParser, type UserSessionState, type UserSessionTuning, UserStreamLike, UserStreamSession, type UserStreamSessionOptions, VERSION, WsConnection, WsConnectionOptions, WsConnectionStats, WsFamily, WsHeartbeat, type WsHeartbeatOptions, canonicalPath, classifyRetrySafety, contractFor, createBinanceMcpServer, createCoinMClient, createPaperExecutionPlatform, createSpotClient, createUSDMClient, createUserEventParser, decimalString, describeContract, endpointCounts, exponentialBackoff, findContract, findEndpoint, fixedBackoff, getContract, isProductClient, isRetrySafety, isTerminalOrderStatus, linearBackoff, listEndpoints, normalizeIntStrings, orderShapeFromSpotOpenOrder, orderShapeFromUsdmOpenOrder, paperAccountUpdateFrame, paperOrderTradeUpdateFrame, parseJsonLossless, parseJsonLosslessAs, positionUpdatesFromPositionRisk, reconcileExecutionPlatform };