--- description: Conventions for cross-exchange C# code using CryptoExchange.Net Shared API V2 capabilities. globs: - "**/*.cs" - "**/*.csproj" alwaysApply: false --- # CryptoExchange.Net conventions CryptoExchange.Net is the base dependency for exchange-specific libraries. Install Binance.Net, Bybit.Net, JK.OKX.Net, or another exchange library; use `CryptoClients.Net` when the application needs the bundle. ## Use Shared API V2 For new cross-exchange code, use the fine-grained interfaces in `CryptoExchange.Net.SharedApis` and each API surface's `.SharedApi` property: ```csharp using CryptoExchange.Net.SharedApis; IGetTickerRest binance = new BinanceRestClient().SpotApi.SharedApi; IGetTickerRest okx = new OKXRestClient().UnifiedApi.SharedApi; var symbol = new SharedSymbol(TradingMode.Spot, "BTC", "USDT"); var result = await binance.GetTickerAsync(new GetTickerRequest(symbol)); ``` Use one capability per operation, such as `IGetTickerRest`, `IGetOrderBookRest`, `IPlaceSpotOrderRest`, or `ISubscribeTradesSocket`. Do not use a broad V1 interface for new code. `.SharedClient` remains only for incremental V1 migration. ## Capability discovery When the exchange and API surface are known, assign the typed `.SharedApi` to the required capability. When selection is dynamic, use an exchange-wide `I[Exchange]SharedApiClient` and a strongly typed reference: ```csharp var match = sharedClient.GetCapability( SharedCapabilities.Orders.Futures.PlaceOrder.Rest, TradingMode.PerpetualLinear); if (match is not null) await match.Capability.PlaceFuturesOrderAsync(request); ``` `GetCapability` returns one preferred match or `null`; `GetCapabilities` returns all matches. Specify `TradingMode` when multiple API surfaces may implement the same capability. A `SharedCapabilities` reference is a lookup key, not proof of exchange support. ## Symbols and parameters Use `SharedSymbol` instead of native strings such as `BTCUSDT`. The exchange library performs formatting. Capability presence does not imply support for every request property. For dynamic code, inspect `match.Options.RequestParameterRules`, `ExchangeParameterRules`, and `SupportedTradingModes`. Supply exchange-specific values through the request's `ExchangeParameters`. ## Transports and results - Transport-agnostic capabilities return `IExchangeCallResult`. - `...Rest` capabilities return `HttpResult`. - socket command capabilities return `QueryResult`. - `ISubscribe...Socket` capabilities return `WebSocketResult`. Use `.Rest` or `.Socket` on capability references when the transport matters. Otherwise exchange-wide lookup honors `PreferredTransport`, normally REST. Always check `.Success` before `.Data` and include `.Exchange` in multi-exchange logs. ## Concurrent aggregation ```csharp var clients = new IGetTickerRest[] { binance, okx, bybit }; var tasks = clients.Select(x => x.GetTickerAsync(new GetTickerRequest(symbol))); var results = await Task.WhenAll(tasks); ``` Reuse clients through dependency injection and run independent exchange calls concurrently. ## V2 semantics - `GetTickerAsync` and `GetAllTickersAsync` return `SharedTicker` for spot and futures. - WebSocket order updates use `SharedSpotOrderUpdate` and `SharedFuturesOrderUpdate`. - `ICloseFullPosition` closes the entire position; use an order capability for partial closes. - Each exchange supports a subset of capabilities and parameter combinations. ## Hard rules - Never install CryptoExchange.Net alone and expect exchange endpoints. - Never pass exchange-native models or symbols through shared services. - Never assume a capability or request field is supported; resolve and inspect it. - Never use `.Result` or `.Wait()`. - Never instantiate exchange clients per request. - Prefer `Task.WhenAll` for independent cross-exchange calls. - Prefer `.SharedApi` and fine-grained V2 interfaces for new code. ## Reference - `AGENTS.md` for fuller examples - `docs/ai-api-map.md` for the V2 interface map - `docs/SHARED_API_V2_MIGRATION.md` for V1 migration details - `llms-full.txt` for expanded AI context