From a8517d2c768c970b4b78a9e6c0e35a8a69cd56bc Mon Sep 17 00:00:00 2001 From: Jkorf Date: Wed, 23 Sep 2026 10:16:15 +0200 Subject: [PATCH] AI docs --- docs/ai-api-map.md | 147 +++++++++++++++++++++ llms-full.txt | 323 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 470 insertions(+) create mode 100644 docs/ai-api-map.md create mode 100644 llms-full.txt diff --git a/docs/ai-api-map.md b/docs/ai-api-map.md new file mode 100644 index 00000000..8cc4a581 --- /dev/null +++ b/docs/ai-api-map.md @@ -0,0 +1,147 @@ +# CryptoExchange.Net Shared API V2 map + +This is a compact map for choosing Shared API V2 types. All listed types are in `CryptoExchange.Net.SharedApis`. Exchange libraries implement subsets; the map describes available abstractions, not guaranteed exchange support. + +## Entry points + +| Need | Use | +| --- | --- | +| Known exchange and API surface | Its typed `.SharedApi` property | +| Runtime selection within one exchange | Exchange-wide `I[Exchange]SharedApiClient` | +| Strongly typed runtime lookup key | `SharedCapabilities` | +| One preferred match | `GetCapability(...)` | +| Every matching surface/transport in one exchange | `GetCapabilities(...)` | +| V1 compatibility during migration | `.SharedClient` | + +Prefer a direct typed `.SharedApi` when the API surface is known. Dynamic lookup returns `SharedCapabilityResolution?`; handle `null`. + +```csharp +IGetTickerRest ticker = restClient.SpotApi.SharedApi; +var result = await ticker.GetTickerAsync(request); +``` + +```csharp +var match = sharedClient.GetCapability( + SharedCapabilities.Tickers.GetTicker.Rest, + TradingMode.Spot); +``` + +## Interface suffixes and results + +| Interface shape | Transport | Typical result | +| --- | --- | --- | +| Operation with no suffix, e.g. `IPlaceSpotOrder` | selected/preferred | `IExchangeCallResult` | +| `...Rest` | REST | `HttpResult` | +| socket command, e.g. `IPlaceSpotOrderSocket` | WebSocket | `QueryResult` | +| subscription, e.g. `ISubscribeTickerSocket` | WebSocket | `WebSocketResult` | + +When a `SharedCapabilities` entry supports multiple transports, use the base entry for preferred transport, `.Rest` for REST, or `.Socket` for socket. Exchange-wide preferred transport normally defaults to REST. + +## Market data + +| Operation | Capability interface | Lookup reference | +| --- | --- | --- | +| Get one ticker | `IGetTickerRest` | `SharedCapabilities.Tickers.GetTicker.Rest` | +| Get all tickers | `IGetAllTickersRest` | `SharedCapabilities.Tickers.GetAllTickers.Rest` | +| Subscribe to one ticker | `ISubscribeTickerSocket` | `SharedCapabilities.Tickers.SubscribeTicker` | +| Subscribe to all tickers | `ISubscribeAllTickersSocket` | `SharedCapabilities.Tickers.SubscribeAllTickers` | +| Subscribe to book ticker | `ISubscribeBookTickerSocket` | `SharedCapabilities.Tickers.SubscribeBookTicker` | +| Get order book | `IGetOrderBookRest` | `SharedCapabilities.OrderBooks.GetOrderBook.Rest` | +| Get book ticker | `IGetBookTickerRest` | `SharedCapabilities.OrderBooks.GetBookTicker.Rest` | +| Subscribe to order book | `ISubscribeOrderBookSocket` | `SharedCapabilities.OrderBooks.SubscribeOrderBook` | +| Subscribe to incremental book | `ISubscribeIncrementalOrderBookSocket` | `SharedCapabilities.OrderBooks.SubscribeIncrementalOrderBook` | +| Get klines | `IGetKlinesRest` | `SharedCapabilities.Klines.GetKlines.Rest` | +| Subscribe to klines | `ISubscribeKlinesSocket` | `SharedCapabilities.Klines.SubscribeKlines` | +| Get recent trades | `IGetRecentTradesRest` | `SharedCapabilities.Trades.GetRecentTrades.Rest` | +| Subscribe to trades | `ISubscribeTradesSocket` | `SharedCapabilities.Trades.SubscribeTrades` | +| Get spot symbols | `IGetSpotSymbolsRest` | `SharedCapabilities.Symbols.GetSpotSymbols.Rest` | +| Get futures symbols | `IGetFuturesSymbolsRest` | `SharedCapabilities.Symbols.GetFuturesSymbols.Rest` | + +Ticker V2 methods are `GetTickerAsync` and `GetAllTickersAsync`; both use `SharedTicker` for spot and futures. Use separate mark-price, index-price, funding, or open-interest capabilities for derivatives-specific data. + +## Spot orders + +| Operation | Capability family | Lookup reference | +| --- | --- | --- | +| Place | `IPlaceSpotOrder`, `IPlaceSpotOrderRest`, `IPlaceSpotOrderSocket` | `SharedCapabilities.Orders.Spot.PlaceOrder[.Rest/.Socket]` | +| Edit | `IEditSpotOrder`, `IEditSpotOrderRest`, `IEditSpotOrderSocket` | `SharedCapabilities.Orders.Spot.EditOrder[.Rest/.Socket]` | +| Cancel | `ICancelSpotOrder`, `ICancelSpotOrderRest`, `ICancelSpotOrderSocket` | `SharedCapabilities.Orders.Spot.CancelOrder[.Rest/.Socket]` | +| Get one | `IGetSpotOrderRest` | `SharedCapabilities.Orders.Spot.GetOrder.Rest` | +| Get open | `IGetOpenSpotOrdersRest` | `SharedCapabilities.Orders.Spot.GetOpenOrders.Rest` | +| Get closed | `IGetClosedSpotOrdersRest` | `SharedCapabilities.Orders.Spot.GetClosedOrders.Rest` | +| Subscribe to updates | `ISubscribeSpotOrdersSocket` | `SharedCapabilities.Orders.Spot.SubscribeOrders` | + +Client-order-id variants exist for edit, cancel, and get. Batch placement and cancel-all capabilities also exist; resolve them only when the application needs those operations and the exchange supports them. + +## Futures orders + +| Operation | Capability family | Lookup reference | +| --- | --- | --- | +| Place | `IPlaceFuturesOrder`, `IPlaceFuturesOrderRest`, `IPlaceFuturesOrderSocket` | `SharedCapabilities.Orders.Futures.PlaceOrder[.Rest/.Socket]` | +| Edit | `IEditFuturesOrder`, `IEditFuturesOrderRest`, `IEditFuturesOrderSocket` | `SharedCapabilities.Orders.Futures.EditOrder[.Rest/.Socket]` | +| Cancel | `ICancelFuturesOrder`, `ICancelFuturesOrderRest`, `ICancelFuturesOrderSocket` | `SharedCapabilities.Orders.Futures.CancelOrder[.Rest/.Socket]` | +| Get one | `IGetFuturesOrderRest` | `SharedCapabilities.Orders.Futures.GetOrder.Rest` | +| Get open | `IGetOpenFuturesOrdersRest` | `SharedCapabilities.Orders.Futures.GetOpenOrders.Rest` | +| Get closed | `IGetClosedFuturesOrdersRest` | `SharedCapabilities.Orders.Futures.GetClosedOrders.Rest` | +| Subscribe to updates | `ISubscribeFuturesOrdersSocket` | `SharedCapabilities.Orders.Futures.SubscribeOrders` | + +Specify `TradingMode.PerpetualLinear`, `PerpetualInverse`, or the appropriate delivery mode when multiple futures APIs can match. + +## Account and derivatives + +Use the following capability families for common account workflows: + +| Area | Common interfaces | +| --- | --- | +| Balances | `IGetBalancesRest`, `ISubscribeBalancesSocket` | +| Positions | `IGetPositionsRest`, `ISubscribePositionsSocket`, `IGetPositionHistoryRest` | +| User trades | `IGetSpotUserTradeHistoryRest`, `IGetFuturesUserTradeHistoryRest`, `ISubscribeUserTradesSocket` | +| Fees | `IGetFeesRest` | +| Deposits | `IGetDepositAddressesRest`, `IGetDepositHistoryRest` | +| Withdrawals | `IWithdrawRest`, `IGetWithdrawalHistoryRest` | +| Transfers | `ITransferRest`, `IGetTransferHistoryRest` | +| Leverage | `IGetLeverageRest`, `ISetLeverageRest`, `IGetLeverageTiersRest` | +| Funding | `IGetFundingInfoRest`, `IGetFundingRateHistoryRest`, `IGetUserFundingHistoryRest` | +| Mark/index data | `IGetMarkPriceRest`, `IGetIndexPriceRest` and their all-market/subscription variants | +| Open interest | `IGetOpenInterestRest` | + +The `SharedCapabilities` catalog groups these under matching plural categories such as `Balances`, `Positions`, `Funding`, `Leverage`, `MarkPrices`, and `IndexPrices`. + +## Parameter support map + +Every successful runtime resolution includes `Options`: + +| Property | Meaning | +| --- | --- | +| `RequestParameterRules` | Shared request fields that are required, optional, or unsupported | +| `ExchangeParameterRules` | Exchange-specific fields accepted through `ExchangeParameters` | +| `SupportedTradingModes` | Modes supported by this capability implementation | +| `NeedsAuthentication` | Whether credentials are required | + +Capability presence is not proof that all properties on its request model are accepted. Inspect rules for dynamically generated requests. + +## Common V1 to V2 mappings + +| V1 call | V2 capability call | +| --- | --- | +| `ISpotTickerRestClient.GetSpotTickerAsync` | `IGetTickerRest.GetTickerAsync` | +| `ISpotTickerRestClient.GetSpotTickersAsync` | `IGetAllTickersRest.GetAllTickersAsync` | +| `ISpotOrderRestClient.PlaceSpotOrderAsync` | `IPlaceSpotOrderRest.PlaceSpotOrderAsync` | +| `ISpotOrderRestClient.CancelSpotOrderAsync` | `ICancelSpotOrderRest.CancelSpotOrderAsync` | +| `IFuturesOrderRestClient.PlaceFuturesOrderAsync` | `IPlaceFuturesOrderRest.PlaceFuturesOrderAsync` | +| `IFuturesOrderRestClient.CancelFuturesOrderAsync` | `ICancelFuturesOrderRest.CancelFuturesOrderAsync` | +| `IFuturesOrderRestClient.GetPositionsAsync` | `IGetPositionsRest.GetPositionsAsync` | + +V1 uses `.SharedClient`; V2 uses `.SharedApi`. Migrate operation by operation. + +## Selection checklist + +1. Use the exchange-native API if portability is unnecessary. +2. For portable code, identify the single operation capability required. +3. Use the typed `.SharedApi` directly when the surface is known. +4. Otherwise resolve through the exchange-wide shared client and handle `null`. +5. Specify trading mode and transport when ambiguity matters. +6. Inspect parameter rules for dynamic requests. +7. Check `Success` before using `Data`. + +For migration edge cases and CryptoClients.Net cross-exchange lookup, see `SHARED_API_V2_MIGRATION.md`. diff --git a/llms-full.txt b/llms-full.txt new file mode 100644 index 00000000..af205bfd --- /dev/null +++ b/llms-full.txt @@ -0,0 +1,323 @@ +# CryptoExchange.Net — full AI context + +Library: CryptoExchange.Net +Library version: 13.0.0 +CryptoExchange.Net package version: 13.0.0 +Language: C#/.NET +Targets: netstandard2.0, netstandard2.1, net8.0, net9.0, net10.0 + +## Purpose + +CryptoExchange.Net is the base library used by 28+ exchange-specific clients. It provides shared REST and WebSocket infrastructure, authentication and result conventions, rate limiting, order-book support, and exchange-agnostic Shared APIs. + +CryptoExchange.Net does not provide exchange endpoints by itself. Install the exchange libraries required by the application, such as Binance.Net, Bybit.Net, JK.OKX.Net, Kraken.Net, or Coinbase.Net. Install `CryptoClients.Net` when one package should provide the full exchange bundle. + +Use an exchange's native API for code tied to that exchange. Use Shared API V2 for portable code that performs the same operation against multiple exchanges. + +## Shared API V2 mental model + +Shared API V2 models each operation as a fine-grained capability. A typed exchange API surface exposes implemented capabilities through `.SharedApi`. Examples include: + +- `IGetTickerRest` +- `IGetOrderBookRest` +- `IGetKlinesRest` +- `IPlaceSpotOrderRest` +- `ICancelFuturesOrderRest` +- `ISubscribeTickerSocket` +- `ISubscribeTradesSocket` + +This replaces the V1 assumption that one broad interface represents a complete feature group. An exchange may support order placement without editing, or REST placement without socket placement. Write services against only the capabilities they require. + +V1 aggregate interfaces remain available through `.SharedClient` for incremental migration. Use `.SharedApi` for new code. + +## Installation + +Install only the exchange packages needed: + +```bash +dotnet add package Binance.Net +dotnet add package JK.OKX.Net +dotnet add package Bybit.Net +``` + +Or install the combined package: + +```bash +dotnet add package CryptoClients.Net +``` + +Do not add CryptoExchange.Net alone and expect to create an exchange client. + +## Direct typed capability usage + +When the exchange and API surface are known, assign `.SharedApi` to the operation interface. The API surface's compile-time type exposes only the capabilities implemented there. + +```csharp +using Binance.Net.Clients; +using OKX.Net.Clients; +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)); + +if (!result.Success) +{ + Console.WriteLine($"[{result.Exchange}] {result.Error}"); + return; +} + +Console.WriteLine($"[{result.Exchange}] {result.Data!.LastPrice}"); +``` + +Use `SharedSymbol` rather than exchange-native strings. Each exchange implementation converts base asset, quote asset, and trading mode into its own symbol format. + +Common trading modes include `Spot`, `PerpetualLinear`, and `PerpetualInverse`. Use the mode that corresponds to the intended exchange API surface. + +## Multi-exchange concurrency + +Shared capabilities allow uniform concurrent calls: + +```csharp +var clients = new IGetTickerRest[] +{ + new BinanceRestClient().SpotApi.SharedApi, + new OKXRestClient().UnifiedApi.SharedApi, + new BybitRestClient().V5Api.SharedApi, +}; + +var symbol = new SharedSymbol(TradingMode.Spot, "BTC", "USDT"); +var tasks = clients.Select(client => + client.GetTickerAsync(new GetTickerRequest(symbol))); + +var results = await Task.WhenAll(tasks); +foreach (var ticker in results.Where(x => x.Success)) + Console.WriteLine($"{ticker.Exchange}: {ticker.Data!.LastPrice}"); +``` + +Independent requests should normally run concurrently. Reuse long-lived clients or dependency-injected clients instead of creating clients for each request. + +## Dynamic capability resolution + +Each exchange library registers an exchange-wide `I[Exchange]SharedApiClient`. Use this client when the API surface, trading mode, or transport is selected at runtime. + +`SharedCapabilities` is a catalog of strongly typed references. A reference identifies the interface to find; it does not guarantee support and does not perform an exchange request. + +```csharp +var resolution = sharedClient.GetCapability( + SharedCapabilities.Orders.Futures.PlaceOrder.Rest, + TradingMode.PerpetualLinear); + +if (resolution is null) +{ + Console.WriteLine("Futures REST placement is unavailable."); + return; +} + +var result = await resolution.Capability.PlaceFuturesOrderAsync(request); +``` + +`GetCapability` returns one `SharedCapabilityResolution` or `null`. The resolution exposes: + +- `Capability`: the callable typed interface. +- `Options`: capability metadata and request rules. +- `Exchange`: the exchange name. +- `Transport`: REST or socket. + +`GetCapabilities` returns every matching implementation on that exchange-wide client. Pass a `TradingMode` when an exchange can expose multiple matching API surfaces, especially separate linear and inverse futures APIs. + +Use the typed `.SharedApi` property when the desired surface is already known. Use dynamic resolution only when the choice or support is genuinely runtime-dependent. + +## Transport selection + +Some operations have transport-agnostic, REST-specific, and socket-specific variants. Order placement is representative: + +- `IPlaceSpotOrder`: transport-agnostic, returns `IExchangeCallResult`. +- `IPlaceSpotOrderRest`: REST-specific, returns `HttpResult`. +- `IPlaceSpotOrderSocket`: socket-specific, returns `QueryResult`. + +Subscription interfaces such as `ISubscribeTickerSocket` return `WebSocketResult`. + +Use a capability reference without a suffix when either transport is acceptable: + +```csharp +var preferred = sharedClient.GetCapability( + SharedCapabilities.Orders.Spot.PlaceOrder); +``` + +Use `.Rest` or `.Socket` when the transport or concrete result type matters: + +```csharp +var rest = sharedClient.GetCapability( + SharedCapabilities.Orders.Spot.PlaceOrder.Rest); + +var socket = sharedClient.GetCapability( + SharedCapabilities.Orders.Spot.PlaceOrder.Socket); +``` + +Exchange-wide transport-agnostic lookup follows the configured `SharedApi.PreferredTransport`, which normally defaults to REST. Do not rely on that preference when application semantics require a particular transport. + +## Result handling + +All result types expose `Success`, `Data`, and `Error`. Check `Success` before reading `Data`. + +- REST capability: `HttpResult` +- socket command capability: `QueryResult` +- socket subscription capability: `WebSocketResult` +- transport-agnostic capability: `IExchangeCallResult` + +Shared results carry the exchange name, which should be included in logs and aggregation records. + +```csharp +if (!result.Success) +{ + logger.LogWarning( + "{Exchange} ticker request failed: {Error}", + result.Exchange, + result.Error); + return; +} +``` + +## Request parameter discovery + +A capability can exist even when an exchange does not accept every property on the shared request. Inspect the selected capability's `Options` before building fully dynamic requests: + +- `RequestParameterRules`: each shared request field is `Required`, `Optional`, or `NotSupported`. +- `ExchangeParameterRules`: exchange-specific required or optional parameters supplied through the request's `ExchangeParameters`. +- `SupportedTradingModes`: modes supported by this particular implementation. + +```csharp +var placement = sharedClient.GetCapability( + SharedCapabilities.Orders.Futures.PlaceOrder.Rest, + TradingMode.PerpetualLinear); + +var leverageRule = placement?.Options.RequestParameterRules + .FirstOrDefault(rule => + rule.Name == nameof(PlaceFuturesOrderRequest.Leverage)); + +if (leverageRule?.Support == RequestParameterSupport.NotSupported) + Console.WriteLine("Set leverage with a separate capability."); +``` + +Do not infer field support from the request model alone. Handle a missing capability, unsupported trading mode, required field, and required exchange parameter before submitting a trading request. + +## Dependency injection + +Each exchange library provides a `services.Add[Exchange](...)` extension. Registration includes native clients, V1 shared facades, V2 operation capabilities, and the exchange-wide shared client. + +Direct capability injection is appropriate when one implementation is intended: + +```csharp +public sealed class TickerService +{ + private readonly IGetTickerRest _ticker; + + public TickerService(IGetTickerRest ticker) + => _ticker = ticker; + + public Task> GetAsync( + SharedSymbol symbol, + CancellationToken ct = default) + => _ticker.GetTickerAsync(new GetTickerRequest(symbol), ct); +} +``` + +If multiple exchanges or multiple API surfaces register the same capability interface, inject the exchange-specific shared client and select a typed API property or use `GetCapability`. Resolving one unqualified capability does not express which registered implementation is desired. + +`CryptoClients.Net` registers `IExchangeSharedApiClient` for V2 lookup across exchanges. Its `GetCapabilities` returns one preferred matching implementation per exchange, while `GetImplementations` returns every matching transport and API surface. + +## Common capability families + +Frequently used market-data capabilities: + +- Tickers: `IGetTickerRest`, `IGetAllTickersRest`, `ISubscribeTickerSocket`, `ISubscribeAllTickersSocket`, `ISubscribeBookTickerSocket`. +- Order books: `IGetOrderBookRest`, `IGetBookTickerRest`, `ISubscribeOrderBookSocket`, `ISubscribeIncrementalOrderBookSocket`. +- Klines and trades: `IGetKlinesRest`, `ISubscribeKlinesSocket`, `IGetRecentTradesRest`, `ISubscribeTradesSocket`. +- Symbols: `IGetSpotSymbolsRest`, `IGetFuturesSymbolsRest`. + +Frequently used trading and account capabilities: + +- Spot and futures order placement, editing, cancellation, retrieval, open/closed orders, and order-update subscriptions. +- Balances, positions, user trades, fees, deposits, withdrawals, and transfers. +- Funding, open interest, leverage, mark price, and index price operations for derivatives. + +Use `docs/ai-api-map.md` or the typed API surface for names. Do not assume every exchange implements every family. + +## V2 ticker behavior + +V2 uses `GetTickerAsync` and `GetAllTickersAsync` for both spot and futures and returns `SharedTicker`. Futures-specific mark price, index price, and funding data have separate capabilities rather than being assumed to exist on the common ticker. + +```csharp +IGetTickerRest ticker = restClient.SpotApi.SharedApi; +var result = await ticker.GetTickerAsync( + new GetTickerRequest( + new SharedSymbol(TradingMode.Spot, "ETH", "USDT"))); +``` + +## Order and subscription behavior + +V2 exposes REST and socket order commands under the same operation capability when both are supported. Choose the transport-specific interface when the caller needs `HttpResult` or `QueryResult`. + +Order-update subscriptions use `SharedSpotOrderUpdate` and `SharedFuturesOrderUpdate`. REST order retrieval returns `SharedSpotOrder` or `SharedFuturesOrder`. Keep update-only stream semantics out of ordinary order snapshots. + +`ICloseFullPosition` closes the entire position and has no quantity parameter. It is not a replacement for partial close logic; use a suitable order capability when an exchange supports partial reduction. + +## V1 migration essentials + +V1 remains available through `.SharedClient`; V2 is exposed through `.SharedApi`. Both are views over the exchange API, so migration can happen operation by operation. + +```csharp +var symbol = new SharedSymbol(TradingMode.Spot, "BTC", "USDT"); +var request = new GetTickerRequest(symbol); + +// V1 compatibility facade +var oldResult = await restClient.SpotApi.SharedClient + .GetSpotTickerAsync(request); + +// V2 capability +var newResult = await restClient.SpotApi.SharedApi + .GetTickerAsync(request); +``` + +Representative mappings: + +- `ISpotTickerRestClient.GetSpotTickerAsync` -> `IGetTickerRest.GetTickerAsync` +- `ISpotOrderRestClient.PlaceSpotOrderAsync` -> `IPlaceSpotOrderRest.PlaceSpotOrderAsync` +- `ISpotOrderRestClient.CancelSpotOrderAsync` -> `ICancelSpotOrderRest.CancelSpotOrderAsync` +- `IFuturesOrderRestClient.PlaceFuturesOrderAsync` -> `IPlaceFuturesOrderRest.PlaceFuturesOrderAsync` +- `IFuturesOrderRestClient.GetPositionsAsync` -> `IGetPositionsRest.GetPositionsAsync` + +Transport-agnostic V2 methods return `IExchangeCallResult`. Select `...Rest` or `...Socket` if old code depends on a concrete transport result. See `docs/SHARED_API_V2_MIGRATION.md` for detailed migration examples and CryptoClients.Net behavior. + +## Code-generation rules + +- Use `.SharedApi` and fine-grained V2 interfaces for new portable code. +- Use `.SharedClient` only when maintaining or incrementally migrating V1 code. +- Use `SharedSymbol` instead of native symbol strings. +- Resolve capability support rather than assuming it. +- Inspect capability options when requests are generated dynamically. +- Select REST or socket explicitly when transport semantics matter. +- Check `Success` before accessing `Data`. +- Reuse clients through DI and keep calls asynchronous. +- Run independent exchange calls concurrently. +- Keep exchange-native models out of cross-exchange service contracts. + +## Implementing an exchange library + +Exchange implementations derive from the shared REST and socket client bases, provide their authentication and option types, and expose typed Shared API classes. Implement the fine-grained capability interfaces actually supported by each API surface and publish accurate `CapabilityOptions`, including trading modes and request/exchange parameter rules. Register the Shared APIs and exchange-wide shared client in the exchange library's DI extension. + +Use established exchange libraries as references. Do not advertise a capability merely because a similar native endpoint exists; its shared request and result semantics must be implemented correctly. + +## References + +- Source: https://github.com/JKorf/CryptoExchange.Net +- Documentation: https://cryptoexchange.jkorf.dev/ +- Shared API V2 migration: https://github.com/JKorf/CryptoExchange.Net/blob/master/docs/SHARED_API_V2_MIGRATION.md +- AI API map: https://github.com/JKorf/CryptoExchange.Net/blob/master/docs/ai-api-map.md +- CryptoClients.Net: https://github.com/JKorf/CryptoClients.Net +- CryptoManager.Net: https://github.com/JKorf/CryptoManager.Net +- NuGet: https://www.nuget.org/packages/CryptoExchange.Net +- Discord: https://discord.gg/MSpeEtSY8t