From d3be869bf15f8743b2cb98eba2d01c7e1652b969 Mon Sep 17 00:00:00 2001 From: Gareth Kirwan Date: Mon, 23 Oct 2023 13:22:13 +0700 Subject: [PATCH] Kucoin: Subscription configuration * Simplify GenerateDefaultSubs * Improve TestGenSubs coverage * Test Candle Sub generation * Support Candle intervals * Full responsibility for formatting Channel name on GenerateDefaultSubs OR consumer of Subscribe * Simplify generatePayloads as a result --- currency/currencies.go | 8 + currency/currencies_test.go | 12 + exchanges/kucoin/kucoin_test.go | 209 ++++-- exchanges/kucoin/kucoin_types.go | 2 + exchanges/kucoin/kucoin_websocket.go | 596 +++++++----------- exchanges/kucoin/kucoin_wrapper.go | 16 + .../kucoin/testdata/wsMarketSnapshot.json | 6 +- testdata/configtest.json | 10 +- 8 files changed, 420 insertions(+), 439 deletions(-) diff --git a/currency/currencies.go b/currency/currencies.go index 013b7223924..7bf0d315a60 100644 --- a/currency/currencies.go +++ b/currency/currencies.go @@ -20,6 +20,14 @@ func NewCurrenciesFromStringArray(currencies []string) Currencies { // Currencies define a range of supported currency codes type Currencies []Code +// Add adds a currency to the list if it doesn't exist +func (c Currencies) Add(a Code) Currencies { + if !c.Contains(a) { + c = append(c, a) + } + return c +} + // Strings returns an array of currency strings func (c Currencies) Strings() []string { list := make([]string, len(c)) diff --git a/currency/currencies_test.go b/currency/currencies_test.go index f6d950c9b92..b095045b541 100644 --- a/currency/currencies_test.go +++ b/currency/currencies_test.go @@ -3,6 +3,8 @@ package currency import ( "encoding/json" "testing" + + "github.com/stretchr/testify/assert" ) func TestCurrenciesUnmarshalJSON(t *testing.T) { @@ -62,3 +64,13 @@ func TestMatch(t *testing.T) { t.Fatal("should not match") } } + +func TestCurrenciesAdd(t *testing.T) { + c := Currencies{} + c = c.Add(BTC) + assert.Len(t, c, 1, "Should have one currency") + c = c.Add(ETH) + assert.Len(t, c, 2, "Should have one currency") + c = c.Add(BTC) + assert.Len(t, c, 2, "Adding a duplicate should not change anything") +} diff --git a/exchanges/kucoin/kucoin_test.go b/exchanges/kucoin/kucoin_test.go index 9694507fbbc..ee95da0f8e8 100644 --- a/exchanges/kucoin/kucoin_test.go +++ b/exchanges/kucoin/kucoin_test.go @@ -6,6 +6,7 @@ import ( "errors" "log" "os" + "strings" "testing" "time" @@ -24,8 +25,8 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/order" "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues" - "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer" + "github.com/thrasher-corp/gocryptotrader/exchanges/subscription" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" "github.com/thrasher-corp/gocryptotrader/portfolio/withdraw" ) @@ -1930,7 +1931,7 @@ var websocketPushDatas = map[string]string{ "SymbolTickerPushDataJSON": `{"type": "message","topic": "/market/ticker:FET-BTC","subject": "trade.ticker","data": {"bestAsk": "0.000018679","bestAskSize": "258.4609","bestBid": "0.000018622","bestBidSize": "68.5961","price": "0.000018628","sequence": "38509148","size": "8.943","time": 1677321643926}}`, "AllSymbolsTickerPushDataJSON": `{"type": "message","topic": "/market/ticker:all","subject": "FTM-ETH","data": {"bestAsk": "0.0002901","bestAskSize": "3514.4978","bestBid": "0.0002894","bestBidSize": "65.536","price": "0.0002894","sequence": "186911324","size": "150","time": 1677320967673}}`, "MarketTradeSnapshotPushDataJSON": `{"type": "message","topic": "/market/snapshot:BTC","subject": "trade.snapshot","data": {"sequence": "5701753771","data": {"averagePrice": 21736.73225440,"baseCurrency": "BTC","board": 1,"buy": 21423,"changePrice": -556.80000000000000000000,"changeRate": -0.0253,"close": 21423.1,"datetime": 1676310802092,"high": 22030.70000000000000000000,"lastTradedPrice": 21423.1,"low": 21407.00000000000000000000,"makerCoefficient": 1.000000,"makerFeeRate": 0.001,"marginTrade": true,"mark": 0,"market": "USDS","markets": ["USDS"],"open": 21979.90000000000000000000,"quoteCurrency": "USDT","sell": 21423.1,"sort": 100,"symbol": "BTC-USDT","symbolCode": "BTC-USDT","takerCoefficient": 1.000000,"takerFeeRate": 0.001,"trading": true,"vol": 6179.80570155000000000000,"volValue": 133988049.45570351500000000000}}}`, - "Orderbook Level 2 PushDataJSON": `{"type": "message","topic": "/spotMarket/level2Depth5:ETH-USDT","subject": "level2","data": {"asks": [[ "21612.7", "0.32307467"],[ "21613.1", "0.1581911"],[ "21613.2", "1.37156153"],[ "21613.3", "2.58327302"],[ "21613.4", "0.00302088"]],"bids": [[ "21612.6", "2.34316818"],[ "21612.3", "0.5771615"],[ "21612.2", "0.21605964"],[ "21612.1", "0.22894841"],[ "21611.6", "0.29251003"]],"timestamp": 1676319909635}}`, + "Orderbook Level 2 PushDataJSON": `{"type": "message","topic": "/spotMarket/level2Depth5:ETH-USDT","subject": "level2","data": {"asks": [["21612.7","0.32307467"],["21613.1","0.1581911"],["21613.2","1.37156153"],["21613.3","2.58327302"],["21613.4","0.00302088"]],"bids": [["21612.6","2.34316818"],["21612.3","0.5771615"],["21612.2","0.21605964"],["21612.1","0.22894841"],["21611.6","0.29251003"]],"timestamp": 1676319909635}}`, "TradeCandlesUpdatePushDataJSON": `{"type":"message","topic":"/market/candles:BTC-USDT_1hour","subject":"trade.candles.update","data":{"symbol":"BTC-USDT","candles":["1589968800","9786.9","9740.8","9806.1","9732","27.45649579","268280.09830877"],"time":1589970010253893337}}`, "SymbolSnapshotPushDataJSON": `{"type": "message","topic": "/market/snapshot:KCS-BTC","subject": "trade.snapshot","data": {"sequence": "1545896669291","data": {"trading": true,"symbol": "KCS-BTC","buy": 0.00011,"sell": 0.00012, "sort": 100, "volValue": 3.13851792584, "baseCurrency": "KCS", "market": "BTC", "quoteCurrency": "BTC", "symbolCode": "KCS-BTC", "datetime": 1548388122031, "high": 0.00013, "vol": 27514.34842, "low": 0.0001, "changePrice": -1.0e-5, "changeRate": -0.0769, "lastTradedPrice": 0.00012, "board": 0, "mark": 0 } }}`, "MatchExecutionPushDataJSON": `{"type":"message","topic":"/market/match:BTC-USDT","subject":"trade.l3match","data":{"sequence":"1545896669145","type":"match","symbol":"BTC-USDT","side":"buy","price":"0.08200000000000000000","size":"0.01022222000000000000","tradeId":"5c24c5da03aa673885cd67aa","takerOrderId":"5c24c5d903aa6772d55b371e","makerOrderId":"5c2187d003aa677bd09d5c93","time":"1545913818099033203"}}`, @@ -1953,7 +1954,7 @@ var websocketPushDatas = map[string]string{ "Public Futures TickerV1PushDataJSON": `{"subject": "ticker","topic": "/contractMarket/ticker:ETHUSDCM","data": {"symbol": "ETHUSDCM","sequence": 45,"side": "sell","price": 3600.00,"size": 16,"tradeId": "5c9dcf4170744d6f5a3d32fb","bestBidSize": 795,"bestBidPrice": 3200.00,"bestAskPrice": 3600.00,"bestAskSize": 284,"ts": 1553846081210004941}}`, "Public Futures Level2OrderbookPushDataJSON": `{"subject": "level2", "topic": "/contractMarket/level2:ETHUSDCM", "type": "message", "data": { "sequence": 18, "change": "5000.0,sell,83","timestamp": 1551770400000}}`, "Public Futures ExecutionDataJSON": `{"type": "message","topic": "/contractMarket/execution:ETHUSDCM","subject": "match","data": {"makerUserId": "6287c3015c27f000017d0c2f","symbol": "ETHUSDCM","sequence": 31443494,"side": "buy","size": 35,"price": 23083.00000000,"takerOrderId": "63f94040839d00000193264b","makerOrderId": "63f94036839d0000019310c3","takerUserId": "6133f817230d8d000607b941","tradeId": "63f940400000650065f4996f","ts": 1677279296134648869}}`, - "PublicFuturesOrderbookWithDepth5PushDataJSON": `{ "type": "message", "topic": "/contractMarket/level2Depth5:ETHUSDCM", "subject": "level2", "data": { "sequence": 1672332328701, "asks": [[ 23149, 13703],[ 23150, 1460],[ 23151.00000000, 941],[ 23152, 4591],[ 23153, 4107] ], "bids": [[ 23148.00000000, 22801],[23147.0,4766],[ 23146, 1388],[ 23145.00000000, 2593],[ 23144.00000000, 6286] ], "ts": 1677280435684, "timestamp": 1677280435684 }}`, + "PublicFuturesOrderbookWithDepth5PushDataJSON": `{ "type": "message", "topic": "/contractMarket/level2Depth5:ETHUSDCM", "subject": "level2", "data": { "sequence": 1672332328701, "asks": [[23149,13703],[23150,1460],[23151.00000000,941],[23152,4591],[23153,4107] ], "bids": [[23148.00000000,22801],[23147.0,4766],[23146,1388],[23145.00000000,2593],[23144.00000000,6286] ], "ts": 1677280435684, "timestamp": 1677280435684 }}`, "Private PositionSettlementPushDataJSON": `{"userId": "xbc453tg732eba53a88ggyt8c","topic": "/contract/position:ETHUSDCM","subject": "position.settlement","data": {"fundingTime": 1551770400000,"qty": 100,"markPrice": 3610.85,"fundingRate": -0.002966,"fundingFee": -296,"ts": 1547697294838004923,"settleCurrency": "XBT"}}`, "Futures PositionChangePushDataJSON": `{ "userId": "5cd3f1a7b7ebc19ae9558591","topic": "/contract/position:ETHUSDCM", "subject": "position.change", "data": {"markPrice": 7947.83,"markValue": 0.00251640,"maintMargin": 0.00252044,"realLeverage": 10.06,"unrealisedPnl": -0.00014735,"unrealisedRoePcnt": -0.0553,"unrealisedPnlPcnt": -0.0553,"delevPercentage": 0.52,"currentTimestamp": 1558087175068,"settleCurrency": "XBT"}}`, "Futures PositionChangeWithChangeReasonPushDataJSON": `{ "type": "message","userId": "5c32d69203aa676ce4b543c7","channelType": "private","topic": "/contract/position:ETHUSDCM", "subject": "position.change", "data": {"realisedGrossPnl": 0E-8,"symbol":"ETHUSDCM","crossMode": false,"liquidationPrice": 1000000.0,"posLoss": 0E-8,"avgEntryPrice": 7508.22,"unrealisedPnl": -0.00014735,"markPrice": 7947.83,"posMargin": 0.00266779,"autoDeposit": false,"riskLimit": 100000,"unrealisedCost": 0.00266375,"posComm": 0.00000392,"posMaint": 0.00001724,"posCost": 0.00266375,"maintMarginReq": 0.005,"bankruptPrice": 1000000.0,"realisedCost": 0.00000271,"markValue": 0.00251640,"posInit": 0.00266375,"realisedPnl": -0.00000253,"maintMargin": 0.00252044,"realLeverage": 1.06,"changeReason": "positionChange","currentCost": 0.00266375,"openingTimestamp": 1558433191000,"currentQty": -20,"delevPercentage": 0.52,"currentComm": 0.00000271,"realisedGrossCost": 0E-8,"isOpen": true,"posCross": 1.2E-7,"currentTimestamp": 1558506060394,"unrealisedRoePcnt": -0.0553,"unrealisedPnlPcnt": -0.0553,"settleCurrency": "XBT"}}`, @@ -1979,10 +1980,133 @@ func TestPushData(t *testing.T) { } } +func verifySubs(tb testing.TB, subs []subscription.Subscription, a asset.Item, prefix string, expected ...string) { + tb.Helper() + var sub *subscription.Subscription + for i, s := range subs { + if s.Asset == a && strings.HasPrefix(s.Channel, prefix) { + if len(expected) == 1 && !strings.Contains(s.Channel, expected[0]) { + continue + } + if sub != nil { + assert.Failf(tb, "Too many subs with prefix", "Asset %s; Prefix %s", a.String(), prefix) + return + } + sub = &subs[i] + } + } + if assert.NotNil(tb, sub, "Should find a sub for asset %s with prefix %s for %s", a.String(), prefix, strings.Join(expected, ", ")) { + suffix := strings.TrimPrefix(sub.Channel, prefix) + if len(expected) == 0 { + assert.Empty(tb, suffix, "Sub for asset %s with prefix %s should have no symbol suffix", a.String(), prefix) + } else { + currs := strings.Split(suffix, ",") + assert.ElementsMatch(tb, currs, expected, "Currencies should match in sub for asset %s with prefix %s", a.String(), prefix) + } + } +} + +// Pairs for Subscription tests: +// Only in Spot: BTC-USDT, ETH-USDT +// In Both: ETH-BTC, LTC-USDT +// Only in Margin: XMR-BTC, SOL-USDC + func TestGenerateDefaultSubscriptions(t *testing.T) { t.Parallel() - if _, err := ku.GenerateDefaultSubscriptions(); err != nil { - t.Error(err) + + subs, err := ku.GenerateDefaultSubscriptions() + assert.NoError(t, err, "GenerateDefaultSubscriptions should not error") + + assert.Len(t, subs, 12, "Should generate the correct number of subs when not logged in") + for _, p := range []string{"ticker", "match", "level2"} { + verifySubs(t, subs, asset.Spot, "/market/"+p+":", "BTC-USDT", "ETH-USDT", "LTC-USDT", "ETH-BTC") + verifySubs(t, subs, asset.Margin, "/market/"+p+":", "SOL-USDC", "XMR-BTC") + } + for _, c := range []string{"ETHUSDCM", "XBTUSDCM", "SOLUSDTM"} { + verifySubs(t, subs, asset.Futures, "/contractMarket/tickerV2:", c) + verifySubs(t, subs, asset.Futures, "/contractMarket/level2Depth50:", c) + } +} + +func TestGenerateAuthSubscriptions(t *testing.T) { + t.Parallel() + + // Create a parallel safe Kucoin to mess with + nu := new(Kucoin) + nu.Base.Features = ku.Base.Features + assert.NoError(t, nu.CurrencyPairs.Load(&ku.CurrencyPairs), "Loading Pairs should not error") + nu.Websocket = sharedtestvalues.NewTestWebsocket() + nu.Websocket.SetCanUseAuthenticatedEndpoints(true) + + subs, err := nu.GenerateDefaultSubscriptions() + assert.NoError(t, err, "GenerateDefaultSubscriptions with Auth should not error") + assert.Len(t, subs, 25, "Should generate the correct number of subs when logged in") + for _, p := range []string{"ticker", "match", "level2"} { + verifySubs(t, subs, asset.Spot, "/market/"+p+":", "BTC-USDT", "ETH-USDT", "LTC-USDT", "ETH-BTC") + verifySubs(t, subs, asset.Margin, "/market/"+p+":", "SOL-USDC", "XMR-BTC") + } + for _, c := range []string{"ETHUSDCM", "XBTUSDCM", "SOLUSDTM"} { + verifySubs(t, subs, asset.Futures, "/contractMarket/tickerV2:", c) + verifySubs(t, subs, asset.Futures, "/contractMarket/level2Depth50:", c) + } + for _, c := range []string{"SOL", "BTC", "XMR", "LTC", "USDC", "USDT", "ETH"} { + verifySubs(t, subs, asset.Margin, "/margin/loan:", c) + } + verifySubs(t, subs, asset.Spot, "/account/balance") + verifySubs(t, subs, asset.Margin, "/margin/position") + verifySubs(t, subs, asset.Margin, "/margin/fundingBook:", "SOL", "BTC", "XMR", "LTC", "USDT", "USDC", "ETH") + verifySubs(t, subs, asset.Futures, "/contractAccount/wallet") + verifySubs(t, subs, asset.Futures, "/contractMarket/advancedOrders") + verifySubs(t, subs, asset.Futures, "/contractMarket/tradeOrders") +} + +func TestGenerateCandleSubscription(t *testing.T) { + t.Parallel() + + // Create a parallel safe Kucoin to mess with + nu := new(Kucoin) + nu.Base.Features = ku.Base.Features + nu.Websocket = sharedtestvalues.NewTestWebsocket() + assert.NoError(t, nu.CurrencyPairs.Load(&ku.CurrencyPairs), "Loading Pairs should not error") + + nu.Features.Subscriptions = []*subscription.Subscription{ + {Channel: subscription.CandlesChannel, Interval: kline.FourHour}, + } + + subs, err := nu.GenerateDefaultSubscriptions() + assert.NoError(t, err, "GenerateDefaultSubscriptions with Candles should not error") + + assert.Len(t, subs, 6, "Should generate the correct number of subs for candles") + for _, c := range []string{"BTC-USDT", "ETH-USDT", "LTC-USDT", "ETH-BTC"} { + verifySubs(t, subs, asset.Spot, "/market/candles:", c+"_4hour") + } + for _, c := range []string{"SOL-USDC", "XMR-BTC"} { + verifySubs(t, subs, asset.Margin, "/market/candles:", c+"_4hour") + } +} + +func TestGenerateMarketSubscription(t *testing.T) { + t.Parallel() + + // Create a parallel safe Kucoin to mess with + nu := new(Kucoin) + nu.Base.Features = ku.Base.Features + nu.Websocket = sharedtestvalues.NewTestWebsocket() + assert.NoError(t, nu.CurrencyPairs.Load(&ku.CurrencyPairs), "Loading Pairs should not error") + + nu.Features.Subscriptions = []*subscription.Subscription{ + {Channel: marketSnapshotChannel}, + } + + subs, err := nu.GenerateDefaultSubscriptions() + assert.NoError(t, err, "GenerateDefaultSubscriptions with MarketSnapshot should not error") + + assert.Len(t, subs, 7, "Should generate the correct number of subs for snapshot") + for _, c := range []string{"BTC", "ETH", "LTC", "USDT"} { + verifySubs(t, subs, asset.Spot, "/market/snapshot:", c) + } + for _, c := range []string{"SOL", "USDC", "XMR"} { + verifySubs(t, subs, asset.Margin, "/market/snapshot:", c) } } @@ -2160,21 +2284,6 @@ func TestCancelAllOrders(t *testing.T) { } } -func TestGeneratePayloads(t *testing.T) { - t.Parallel() - subscriptions, err := ku.GenerateDefaultSubscriptions() - if err != nil { - t.Error(err) - } - payload, err := ku.generatePayloads(subscriptions, "subscribe") - if err != nil { - t.Error(err) - } - if len(payload) != len(subscriptions) { - t.Error("derived payload is not same as generated channel subscription instances") - } -} - const ( subUserResponseJSON = `{"userId":"635002438793b80001dcc8b3", "uid":62356, "subName":"margin01", "status":2, "type":4, "access":"Margin", "createdAt":1666187844000, "remarks":null }` positionSettlementPushData = `{"userId": "xbc453tg732eba53a88ggyt8c", "topic": "/contract/position:XBTUSDM", "subject": "position.settlement", "data": { "fundingTime": 1551770400000, "qty": 100, "markPrice": 3610.85, "fundingRate": -0.002966, "fundingFee": -296, "ts": 1547697294838004923, "settleCurrency": "XBT" } }` @@ -2422,6 +2531,7 @@ func TestProcessMarketSnapshot(t *testing.T) { n := new(Kucoin) sharedtestvalues.TestFixtureToDataHandler(t, ku, n, "testdata/wsMarketSnapshot.json", n.wsHandleData) seen := 0 + seenAssetTypes := map[asset.Item]int{} for reading := true; reading; { select { default: @@ -2431,33 +2541,37 @@ func TestProcessMarketSnapshot(t *testing.T) { switch v := resp.(type) { case *ticker.Price: switch seen { - // spot only case 1: - assert.Equal(t, time.UnixMilli(1698740324415), v.LastUpdated, "datetime") - assert.Equal(t, 0.00001402100000000000, v.High, "high") - assert.Equal(t, 0.000012508, v.Last, "lastTradedPrice") - assert.Equal(t, 0.00001129200000000000, v.Low, "low") + assert.Equal(t, asset.Margin, v.AssetType, "AssetType") + assert.Equal(t, time.UnixMilli(1700555342007), v.LastUpdated, "datetime") + assert.Equal(t, 0.004445, v.High, "high") + assert.Equal(t, 0.004415, v.Last, "lastTradedPrice") + assert.Equal(t, 0.004191, v.Low, "low") assert.Equal(t, currency.NewPairWithDelimiter("XMR", "BTC", "-"), v.Pair, "symbol") - assert.Equal(t, 28474.47280000000000000000, v.Volume, "volume") - assert.Equal(t, 0.37038038297340000000, v.QuoteVolume, "volValue") - // margin only - case 2: - assert.Equal(t, time.UnixMilli(1698740324483), v.LastUpdated, "datetime") - assert.Equal(t, 0.00000039450000000000, v.High, "high") - assert.Equal(t, 0.0000003897, v.Last, "lastTradedPrice") - assert.Equal(t, 0.00000034200000000000, v.Low, "low") - assert.Equal(t, currency.NewPairWithDelimiter("MTV", "BTC", "-"), v.Pair, "symbol") - assert.Equal(t, 316078.69700000000000000000, v.Volume, "volume") - assert.Equal(t, 0.11768519138877000000, v.QuoteVolume, "volValue") - // both margin and spot - case 3: - assert.Equal(t, time.UnixMilli(1698740324437), v.LastUpdated, "datetime") - assert.Equal(t, 0.00008486000000000000, v.High, "high") - assert.Equal(t, 0.00008318, v.Last, "lastTradedPrice") - assert.Equal(t, 0.00007152000000000000, v.Low, "low") + assert.Equal(t, 13097.3357, v.Volume, "volume") + assert.Equal(t, 57.44552981, v.QuoteVolume, "volValue") + case 2, 3: + assert.Equal(t, time.UnixMilli(1700555340197), v.LastUpdated, "datetime") + assert.Contains(t, []asset.Item{asset.Spot, asset.Margin}, v.AssetType, "AssetType is Spot or Margin") + seenAssetTypes[v.AssetType]++ + assert.Equal(t, seenAssetTypes[v.AssetType], 1, "Each Asset Type is sent only once per unique snapshot") + assert.Equal(t, 0.054846, v.High, "high") + assert.Equal(t, 0.053778, v.Last, "lastTradedPrice") + assert.Equal(t, 0.05364, v.Low, "low") + assert.Equal(t, currency.NewPairWithDelimiter("ETH", "BTC", "-"), v.Pair, "symbol") + assert.Equal(t, 2958.3139116, v.Volume, "volume") + assert.Equal(t, 160.7847672784213, v.QuoteVolume, "volValue") + case 4: + assert.Equal(t, asset.Spot, v.AssetType, "AssetType") + assert.Equal(t, time.UnixMilli(1700555342151), v.LastUpdated, "datetime") + assert.Equal(t, 37750.0, v.High, "high") + assert.Equal(t, 37366.8, v.Last, "lastTradedPrice") + assert.Equal(t, 36700.0, v.Low, "low") assert.Equal(t, currency.NewPairWithDelimiter("BTC", "USDT", "-"), v.Pair, "symbol") - assert.Equal(t, 17062.45450000000000000000, v.Volume, "volume") - assert.Equal(t, 1.33076678861000000000, v.QuoteVolume, "volValue") + assert.Equal(t, 2900.37846402, v.Volume, "volume") + assert.Equal(t, 108210331.34015164, v.QuoteVolume, "volValue") + default: + t.Errorf("Got an unexpected *ticker.Price: %v", v) } case error: t.Error(v) @@ -2472,13 +2586,10 @@ func TestProcessMarketSnapshot(t *testing.T) { func TestSubscribeMarketSnapshot(t *testing.T) { t.Parallel() setupWS() - s := []stream.ChannelSubscription{ - {Channel: marketTickerSnapshotForCurrencyChannel, - Currency: currency.Pair{Base: currency.BTC}}, - } - err := ku.Subscribe(s) + err := ku.Subscribe([]subscription.Subscription{{Channel: marketSymbolSnapshotChannel, Pair: currency.Pair{Base: currency.BTC}}}) assert.NoError(t, err, "Subscribe to MarketSnapshot should not error") } + func TestSeedLocalCache(t *testing.T) { t.Parallel() pair, err := currency.NewPairFromString("ETH-USDT") diff --git a/exchanges/kucoin/kucoin_types.go b/exchanges/kucoin/kucoin_types.go index af5a1faea65..66dcbb4183d 100644 --- a/exchanges/kucoin/kucoin_types.go +++ b/exchanges/kucoin/kucoin_types.go @@ -33,6 +33,8 @@ var ( errSizeOrFundIsRequired = errors.New("at least one required among size and funds") errInvalidLeverage = errors.New("invalid leverage value") errInvalidClientOrderID = errors.New("no client order ID supplied, this endpoint requires a UUID or similar string") + errInvalidMsgType = errors.New("message type field not valid") + errSubscriptionPairRequired = errors.New("pair required for manual subscriptions") subAccountRegExp = regexp.MustCompile("^[a-zA-Z0-9]{7-32}$") subAccountPassphraseRegExp = regexp.MustCompile("^[a-zA-Z0-9]{7-24}$") diff --git a/exchanges/kucoin/kucoin_websocket.go b/exchanges/kucoin/kucoin_websocket.go index b713fef6180..4716343ee58 100644 --- a/exchanges/kucoin/kucoin_websocket.go +++ b/exchanges/kucoin/kucoin_websocket.go @@ -11,13 +11,13 @@ import ( "sync" "time" + "github.com/buger/jsonparser" "github.com/gorilla/websocket" "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/currency" exchange "github.com/thrasher-corp/gocryptotrader/exchanges" "github.com/thrasher-corp/gocryptotrader/exchanges/account" "github.com/thrasher-corp/gocryptotrader/exchanges/asset" - "github.com/thrasher-corp/gocryptotrader/exchanges/kline" "github.com/thrasher-corp/gocryptotrader/exchanges/order" "github.com/thrasher-corp/gocryptotrader/exchanges/orderbook" "github.com/thrasher-corp/gocryptotrader/exchanges/request" @@ -35,21 +35,20 @@ const ( privateBullets = "/v1/bullet-private" // spot channels - marketTickerChannel = "/market/ticker:%s" // /market/ticker:{symbol},{symbol}... - marketAllTickersChannel = "/market/ticker:all" - marketTickerSnapshotChannel = "/market/snapshot:%s" // /market/snapshot:{symbol} - marketTickerSnapshotForCurrencyChannel = "/market/snapshot:" // /market/snapshot:{market} <--- market represents a currency - marketOrderbookLevel2Channels = "/market/level2:%s" // /market/level2:{symbol},{symbol}... - marketOrderbookLevel2to5Channel = "/spotMarket/level2Depth5:%s" // /spotMarket/level2Depth5:{symbol},{symbol}... - marketOrderbokLevel2To50Channel = "/spotMarket/level2Depth50:%s" // /spotMarket/level2Depth50:{symbol},{symbol}... - marketCandlesChannel = "/market/candles:%s_%s" // /market/candles:{symbol}_{type} - marketMatchChannel = "/market/match:%s" // /market/match:{symbol},{symbol}... - indexPriceIndicatorChannel = "/indicator/index:%s" // /indicator/index:{symbol0},{symbol1}.. - markPriceIndicatorChannel = "/indicator/markPrice:%s" // /indicator/markPrice:{symbol0},{symbol1}... - marginFundingbookChangeChannel = "/margin/fundingBook:%s" // /margin/fundingBook:{currency0},{currency1}... - - // Private channel - + marketAllTickersChannel = "/market/ticker:all" + marketTickerChannel = "/market/ticker:%s" // /market/ticker:{symbol},{symbol}... + marketSymbolSnapshotChannel = "/market/snapshot:%s" // /market/snapshot:{symbol} + marketSnapshotChannel = "/market/snapshot:%v" // /market/snapshot:{market} <--- market represents a currency + marketOrderbookLevel2Channels = "/market/level2:%s" // /market/level2:{pair},{pair}... + marketOrderbookLevel2to5Channel = "/spotMarket/level2Depth5:%s" // /spotMarket/level2Depth5:{symbol},{symbol}... + marketOrderbokLevel2To50Channel = "/spotMarket/level2Depth50:%s" // /spotMarket/level2Depth50:{symbol},{symbol}... + marketCandlesChannel = "/market/candles:%s_%s" // /market/candles:{symbol}_{interval} + marketMatchChannel = "/market/match:%s" // /market/match:{symbol},{symbol}... + indexPriceIndicatorChannel = "/indicator/index:%s" // /indicator/index:{symbol0},{symbol1}.. + markPriceIndicatorChannel = "/indicator/markPrice:%s" // /indicator/markPrice:{symbol0},{symbol1}... + marginFundingbookChangeChannel = "/margin/fundingBook:%s" // /margin/fundingBook:{currency0},{currency1}... + + // Private channels privateSpotTradeOrders = "/spotMarket/tradeOrders" accountBalanceChannel = "/account/balance" marginPositionChannel = "/margin/position" @@ -57,7 +56,6 @@ const ( spotMarketAdvancedChannel = "/spotMarket/advancedOrders" // futures channels - futuresTickerV2Channel = "/contractMarket/tickerV2:%s" // /contractMarket/tickerV2:{symbol} futuresTickerChannel = "/contractMarket/ticker:%s" // /contractMarket/ticker:{symbol} futuresOrderbookLevel2Channel = "/contractMarket/level2:%s" // /contractMarket/level2:{symbol} @@ -69,7 +67,6 @@ const ( futuresTrasactionStatisticsTimerEventChannel = "/contractMarket/snapshot:%s" // /contractMarket/snapshot:{symbol} // futures private channels - futuresTradeOrdersBySymbolChannel = "/contractMarket/tradeOrders:%s" // /contractMarket/tradeOrders:{symbol} futuresTradeOrderChannel = "/contractMarket/tradeOrders" futuresStopOrdersLifecycleEventChannel = "/contractMarket/advancedOrders" @@ -77,6 +74,14 @@ const ( futuresPositionChangeEventChannel = "/contract/position:%s" // /contract/position:{symbol} ) +var subscriptionNames = map[string]string{ + subscription.TickerChannel: marketTickerChannel, + subscription.OrderbookChannel: marketOrderbookLevel2Channels, + subscription.CandlesChannel: marketCandlesChannel, + subscription.AllTradesChannel: marketMatchChannel, + // No equivalents for: AllOrders, MyTrades, MyOrders +} + var ( // maxWSUpdateBuffer defines max websocket updates to apply when an // orderbook is initially fetched @@ -89,22 +94,6 @@ var ( maxWSOrderbookWorkers = 10 ) -var requiredSubscriptionIDS map[string]bool -var requiredSubscriptionIDSLock sync.Mutex - -// checkRequiredSubscriptionID check whether the id included in the required subscription ids list. -func (ku *Kucoin) checkRequiredSubscriptionID(id string) bool { - if len(requiredSubscriptionIDS) > 0 { - if requiredSubscriptionIDS[id] { - requiredSubscriptionIDSLock.Lock() - delete(requiredSubscriptionIDS, id) - requiredSubscriptionIDSLock.Unlock() - return true - } - } - return false -} - // WsConnect creates a new websocket connection. func (ku *Kucoin) WsConnect() error { if !ku.Websocket.IsEnabled() || !ku.IsEnabled() { @@ -209,17 +198,16 @@ func (ku *Kucoin) wsHandleData(respData []byte) error { err := json.Unmarshal(respData, &resp) if err != nil { return err - } else if resp.ID != "" { - if ku.checkRequiredSubscriptionID(resp.ID) { - if !ku.Websocket.Match.IncomingWithData(resp.ID, respData) { - return fmt.Errorf("can not match subscription message with signature ID:%s", resp.ID) - } - } - return nil } if resp.Type == "pong" || resp.Type == "welcome" { return nil } + if resp.ID != "" { + if !ku.Websocket.Match.IncomingWithData("msgID:"+resp.ID, respData) { + return fmt.Errorf("message listener not found: %s", resp.ID) + } + return nil + } topicInfo := strings.Split(resp.Topic, ":") switch { case strings.HasPrefix(marketAllTickersChannel, topicInfo[0]), @@ -231,8 +219,7 @@ func (ku *Kucoin) wsHandleData(respData []byte) error { instruments = topicInfo[1] } return ku.processTicker(resp.Data, instruments) - case strings.HasPrefix(marketTickerSnapshotChannel, topicInfo[0]) || - strings.HasPrefix(marketTickerSnapshotForCurrencyChannel, topicInfo[0]): + case strings.HasPrefix(marketSymbolSnapshotChannel, topicInfo[0]): return ku.processMarketSnapshot(resp.Data) case strings.HasPrefix(marketOrderbookLevel2Channels, topicInfo[0]): return ku.processOrderbookWithDepth(respData, topicInfo[1]) @@ -926,387 +913,232 @@ func (ku *Kucoin) Unsubscribe(subscriptions []subscription.Subscription) error { return ku.handleSubscriptions(subscriptions, "unsubscribe") } -func (ku *Kucoin) handleSubscriptions(subscriptions []subscription.Subscription, operation string) error { - if requiredSubscriptionIDS == nil { - requiredSubscriptionIDS = map[string]bool{} - } - payloads, err := ku.generatePayloads(subscriptions, operation) - if err != nil { - return err +func (ku *Kucoin) expandManualSubscriptions(in []subscription.Subscription) ([]subscription.Subscription, error) { + subs := make([]subscription.Subscription, 0, len(in)) + for i := range in { + if isSymbolChannel(in[i].Channel) { + if in[i].Pair.IsEmpty() { + return nil, errSubscriptionPairRequired + } + a := in[i].Asset + if !a.IsValid() { + a = getChannelsAssetType(in[i].Channel) + } + assetPairs := map[asset.Item]currency.Pairs{a: {in[i].Pair}} + n, err := ku.expandSubscription(&in[i], assetPairs) + if err != nil { + return nil, err + } + subs = append(subs, n...) + } else { + subs = append(subs, in[i]) + } } + return subs, nil +} + +func (ku *Kucoin) handleSubscriptions(subs []subscription.Subscription, operation string) error { var errs error - for x := range payloads { - err = ku.Websocket.Conn.SendJSONMessage(payloads[x]) - if err != nil { + subs, errs = ku.expandManualSubscriptions(subs) + for i := range subs { + msgID := strconv.FormatInt(ku.Websocket.Conn.GenerateMessageID(false), 10) + req := WsSubscriptionInput{ + ID: msgID, + Type: operation, + Topic: subs[i].Channel, + PrivateChannel: subs[i].Authenticated, + Response: true, + } + if respRaw, err := ku.Websocket.Conn.SendMessageReturnResponse("msgID:"+msgID, req); err != nil { errs = common.AppendError(errs, err) - continue + } else { + rType, err := jsonparser.GetUnsafeString(respRaw, "type") + switch { + case err != nil: + errs = common.AppendError(errs, err) + case rType != "ack": + errs = common.AppendError(errs, fmt.Errorf("%w: %s from %s", errInvalidMsgType, rType, respRaw)) + default: + ku.Websocket.AddSuccessfulSubscriptions(subs[i]) + if ku.Verbose { + log.Debugf(log.ExchangeSys, "%s Subscribed to Channel: %s", ku.Name, subs[i].Channel) + } + } } - ku.Websocket.AddSuccessfulSubscriptions(subscriptions[x]) } return errs } -// getChannelsAssetType returns the asset type to which the subscription channel belongs to -// or returns an error otherwise. -func (ku *Kucoin) getChannelsAssetType(channelName string) (asset.Item, error) { +// getChannelsAssetType returns the asset type to which the subscription channel belongs to or asset.Empty +func getChannelsAssetType(channelName string) asset.Item { switch channelName { case futuresTickerV2Channel, futuresTickerChannel, futuresOrderbookLevel2Channel, futuresExecutionDataChannel, futuresOrderbookLevel2Depth5Channel, futuresOrderbookLevel2Depth50Channel, futuresContractMarketDataChannel, futuresSystemAnnouncementChannel, futuresTrasactionStatisticsTimerEventChannel, futuresTradeOrdersBySymbolChannel, futuresTradeOrderChannel, futuresStopOrdersLifecycleEventChannel, futuresAccountBalanceEventChannel, futuresPositionChangeEventChannel: - return asset.Futures, nil + return asset.Futures case marketTickerChannel, marketAllTickersChannel, - marketTickerSnapshotChannel, marketTickerSnapshotForCurrencyChannel, + marketSnapshotChannel, marketSymbolSnapshotChannel, marketOrderbookLevel2Channels, marketOrderbookLevel2to5Channel, marketOrderbokLevel2To50Channel, marketCandlesChannel, - marketMatchChannel, indexPriceIndicatorChannel, - markPriceIndicatorChannel, marginFundingbookChangeChannel, - privateSpotTradeOrders, accountBalanceChannel, - marginPositionChannel, marginLoanChannel, - spotMarketAdvancedChannel: - return asset.Spot, nil + marketMatchChannel, indexPriceIndicatorChannel, markPriceIndicatorChannel, + privateSpotTradeOrders, accountBalanceChannel, spotMarketAdvancedChannel: + return asset.Spot + case marginFundingbookChangeChannel, marginPositionChannel, marginLoanChannel: + return asset.Margin default: - return asset.Empty, errors.New("channel not supported") + return asset.Empty } } // GenerateDefaultSubscriptions Adds default subscriptions to websocket. func (ku *Kucoin) GenerateDefaultSubscriptions() ([]subscription.Subscription, error) { - channels := []string{} - if ku.CurrencyPairs.IsAssetEnabled(asset.Spot) == nil || ku.CurrencyPairs.IsAssetEnabled(asset.Margin) == nil { - channels = append(channels, - marketTickerChannel, - marketMatchChannel, - marketOrderbookLevel2Channels) - } - if ku.CurrencyPairs.IsAssetEnabled(asset.Margin) == nil { - channels = append(channels, - marginFundingbookChangeChannel) - } - if ku.CurrencyPairs.IsAssetEnabled(asset.Futures) == nil { - channels = append(channels, - futuresTickerV2Channel, - futuresOrderbookLevel2Depth50Channel) - } - var subscriptions []subscription.Subscription - if ku.Websocket.CanUseAuthenticatedEndpoints() { - if ku.CurrencyPairs.IsAssetEnabled(asset.Spot) == nil { - channels = append(channels, - accountBalanceChannel, - ) - } - if ku.CurrencyPairs.IsAssetEnabled(asset.Margin) == nil { - channels = append(channels, - marginPositionChannel, - marginLoanChannel, - ) - } - if ku.CurrencyPairs.IsAssetEnabled(asset.Futures) == nil { - channels = append(channels, - // futures authenticated channels - futuresTradeOrdersBySymbolChannel, - futuresTradeOrderChannel, - futuresStopOrdersLifecycleEventChannel, - futuresAccountBalanceEventChannel) + assetPairs := map[asset.Item]currency.Pairs{} + for _, a := range ku.GetAssetTypes(false) { + if p, err := ku.GetEnabledPairs(a); err == nil { + assetPairs[a] = p + } else { + assetPairs[a] = currency.Pairs{} // err is probably that Asset isn't enabled, but we don't care about errors of any type } } - var err error - var spotPairs currency.Pairs - if ku.CurrencyPairs.IsAssetEnabled(asset.Spot) == nil { - spotPairs, err = ku.GetEnabledPairs(asset.Spot) - if err != nil { - return nil, err + authed := ku.Websocket.CanUseAuthenticatedEndpoints() + var subscriptions = []subscription.Subscription{} + for _, s := range ku.Features.Subscriptions { + if !authed && s.Authenticated { + continue } - } - var marginPairs currency.Pairs - if ku.CurrencyPairs.IsAssetEnabled(asset.Margin) == nil { - marginPairs, err = ku.GetEnabledPairs(asset.Margin) + subs, err := ku.expandSubscription(s, assetPairs) if err != nil { return nil, err } + subscriptions = append(subscriptions, subs...) } + return subscriptions, nil +} - var futuresPairs currency.Pairs - if ku.CurrencyPairs.IsAssetEnabled(asset.Futures) == nil { - futuresPairs, err = ku.GetEnabledPairs(asset.Futures) +// expandSubscription takes a subscription and expands it across the relevand asset and pairs passed in +func (ku *Kucoin) expandSubscription(baseSub *subscription.Subscription, assetPairs map[asset.Item]currency.Pairs) ([]subscription.Subscription, error) { + var subscriptions = []subscription.Subscription{} + s := *baseSub + s.Channel = channelName(s.Channel) + if !s.Asset.IsValid() { + s.Asset = getChannelsAssetType(s.Channel) + } + switch { + case s.Channel == marginLoanChannel: + for _, c := range assetPairs[asset.Margin].GetCurrencies() { + i := s + i.Channel = fmt.Sprintf(s.Channel, c) + subscriptions = append(subscriptions, i) + } + case s.Channel == marketCandlesChannel: + interval, err := ku.intervalToString(s.Interval) if err != nil { return nil, err } - } - marginLoanCurrencyCheckMap := map[currency.Code]bool{} - for x := range channels { - switch channels[x] { - case accountBalanceChannel, marginPositionChannel, - futuresTradeOrderChannel, futuresStopOrdersLifecycleEventChannel, - spotMarketAdvancedChannel, privateSpotTradeOrders, - marketAllTickersChannel, futuresSystemAnnouncementChannel, - futuresAccountBalanceEventChannel: - subscriptions = append(subscriptions, subscription.Subscription{ - Channel: channels[x], - }) - case marketTickerSnapshotChannel, - marketOrderbookLevel2Channels, - marketTickerSnapshotForCurrencyChannel, - marketOrderbookLevel2to5Channel, - marketOrderbokLevel2To50Channel, - marketTickerChannel: - subscribedPairsMap := map[string]bool{} - for b := range spotPairs { - if okay := subscribedPairsMap[spotPairs[b].String()]; okay { - continue - } - subscriptions = append(subscriptions, subscription.Subscription{ - Channel: channels[x], - Asset: asset.Spot, - Pair: spotPairs[b], - }) - subscribedPairsMap[spotPairs[b].String()] = true - } - for b := range marginPairs { - if okay := subscribedPairsMap[marginPairs[b].String()]; okay { - continue - } - subscriptions = append(subscriptions, subscription.Subscription{ - Channel: channels[x], - Asset: asset.Margin, - Pair: marginPairs[b], - }) - subscribedPairsMap[marginPairs[b].String()] = true - } - case indexPriceIndicatorChannel, - markPriceIndicatorChannel, - marketMatchChannel: - pairs := currency.Pairs{} - for p := range spotPairs { - pairs = pairs.Add(spotPairs[p]) - } - for p := range marginPairs { - pairs = pairs.Add(marginPairs[p]) - } - subscriptions = append(subscriptions, subscription.Subscription{ - Channel: channels[x], - Asset: asset.Spot, - Params: map[string]interface{}{"symbols": pairs.Join()}, - }) - case marketCandlesChannel: - subscribedPairsMap := map[string]bool{} - for p := range spotPairs { - if okay := subscribedPairsMap[spotPairs[p].String()]; okay { - continue - } - subscriptions = append(subscriptions, subscription.Subscription{ - Channel: channels[x], - Asset: asset.Spot, - Pair: spotPairs[p], - Params: map[string]interface{}{"interval": kline.FifteenMin}, - }) - subscribedPairsMap[spotPairs[p].String()] = true - } - for p := range marginPairs { - if okay := subscribedPairsMap[marginPairs[p].String()]; okay { - continue - } - subscriptions = append(subscriptions, subscription.Subscription{ - Channel: channels[x], - Asset: asset.Margin, - Pair: marginPairs[p], - Params: map[string]interface{}{"interval": kline.FifteenMin}, - }) - subscribedPairsMap[marginPairs[p].String()] = true - } - case marginLoanChannel: - for b := range marginPairs { - if !marginLoanCurrencyCheckMap[marginPairs[b].Quote] { - subscriptions = append(subscriptions, subscription.Subscription{ - Channel: channels[x], - Pair: currency.Pair{Base: marginPairs[b].Quote}, - }) - marginLoanCurrencyCheckMap[marginPairs[b].Quote] = true - } - if !marginLoanCurrencyCheckMap[marginPairs[b].Base] { - subscriptions = append(subscriptions, subscription.Subscription{ - Channel: channels[x], - Pair: currency.Pair{Base: marginPairs[b].Base}, - }) - marginLoanCurrencyCheckMap[marginPairs[b].Base] = true - } - } - case marginFundingbookChangeChannel: - currencyExist := map[currency.Code]bool{} - for b := range marginPairs { - okay := currencyExist[marginPairs[b].Base] - if !okay { - currencyExist[marginPairs[b].Base] = true - } - okay = currencyExist[marginPairs[b].Quote] - if !okay { - currencyExist[marginPairs[b].Quote] = true - } - } - var currencies string - for b := range currencyExist { - currencies += b.String() + "," - } - currencies = strings.TrimSuffix(currencies, ",") - subscriptions = append(subscriptions, subscription.Subscription{ - Channel: channels[x], - Params: map[string]interface{}{"currencies": currencies}, - }) - case futuresTickerV2Channel, - futuresTickerChannel, - futuresExecutionDataChannel, - futuresOrderbookLevel2Channel, - futuresOrderbookLevel2Depth5Channel, - futuresOrderbookLevel2Depth50Channel, - futuresContractMarketDataChannel, - futuresTradeOrdersBySymbolChannel, - futuresPositionChangeEventChannel, - futuresTrasactionStatisticsTimerEventChannel: - for b := range futuresPairs { - futuresPairs[b], err = ku.FormatExchangeCurrency(futuresPairs[b], asset.Futures) - if err != nil { - continue - } - subscriptions = append(subscriptions, subscription.Subscription{ - Channel: channels[x], - Asset: asset.Futures, - Pair: futuresPairs[b], - }) + subs := spotOrMarginPairSubs(assetPairs, &s, false, interval) + subscriptions = append(subscriptions, subs...) + case s.Channel == marginFundingbookChangeChannel: + s.Channel = fmt.Sprintf(s.Channel, assetPairs[asset.Margin].GetCurrencies().Join()) + subscriptions = append(subscriptions, s) + case s.Channel == marketSnapshotChannel: + subs := spotOrMarginCurrencySubs(assetPairs, &s) + subscriptions = append(subscriptions, subs...) + case getChannelsAssetType(s.Channel) == asset.Futures && isSymbolChannel(s.Channel): + for _, p := range assetPairs[asset.Futures] { + c, err := ku.FormatExchangeCurrency(p, asset.Futures) + if err != nil { + continue } + i := s + i.Channel = fmt.Sprintf(s.Channel, c) + subscriptions = append(subscriptions, i) } + case isSymbolChannel(s.Channel): + // Subscriptions which can use a single comma-separated sub per asset + subs := spotOrMarginPairSubs(assetPairs, &s, true) + subscriptions = append(subscriptions, subs...) + default: + subscriptions = append(subscriptions, s) } return subscriptions, nil } -func (ku *Kucoin) generatePayloads(subscriptions []subscription.Subscription, operation string) ([]WsSubscriptionInput, error) { - payloads := make([]WsSubscriptionInput, 0, len(subscriptions)) - marketTickerSnapshotForCurrencyChannelCurrencyFilter := map[currency.Code]int{} - for x := range subscriptions { - var err error - var a asset.Item - a, err = ku.getChannelsAssetType(subscriptions[x].Channel) - if err != nil { - return nil, err +// isSymbolChannel returns true it this channel path ends in a formatting %s to accept a Symbol +func isSymbolChannel(c string) bool { + return strings.HasSuffix(c, "%s") || strings.HasSuffix(c, "%v") +} + +// channelName converts global channel Names used in config of channel input into kucoin channel names +// returns the name unchanged if no match is found +func channelName(name string) string { + if s, ok := subscriptionNames[name]; ok { + return s + } + return name +} + +// spotOrMarginPairSubs accepts a map of pairs and a template subscription and returns a list of subscriptions for Spot and Margin pairs +// If there's a Spot subscription, it won't be added again as a Margin subscription +// If joined param is true then one subscription per asset type with the currencies comma delimited +func spotOrMarginPairSubs(assetPairs map[asset.Item]currency.Pairs, b *subscription.Subscription, join bool, fmtArgs ...any) []subscription.Subscription { + subs := []subscription.Subscription{} + add := func(a asset.Item, pairs currency.Pairs) { + if len(pairs) == 0 { + return } - if !subscriptions[x].Pair.IsEmpty() { - subscriptions[x].Pair, err = ku.FormatExchangeCurrency(subscriptions[x].Pair, a) - if err != nil { - return nil, err + s := *b + s.Asset = a + if join { + f := append([]any{pairs.Join()}, fmtArgs...) + s.Channel = fmt.Sprintf(b.Channel, f...) + subs = append(subs, s) + } else { + for i := range pairs { + f := append([]any{pairs[i].String()}, fmtArgs...) + s.Channel = fmt.Sprintf(b.Channel, f...) + subs = append(subs, s) } } - if subscriptions[x].Asset == asset.Futures { - subscriptions[x].Pair, err = ku.FormatExchangeCurrency(subscriptions[x].Pair, asset.Futures) - if err != nil { - continue - } + } + + add(asset.Spot, assetPairs[asset.Spot]) + + marginPairs := currency.Pairs{} + for _, p := range assetPairs[asset.Margin] { + if !assetPairs[asset.Spot].Contains(p, false) { + marginPairs = marginPairs.Add(p) } - switch subscriptions[x].Channel { - case marketTickerChannel, - marketOrderbookLevel2Channels, - marketOrderbookLevel2to5Channel, - marketOrderbokLevel2To50Channel, - indexPriceIndicatorChannel, - marketMatchChannel, - markPriceIndicatorChannel: - symbols, okay := subscriptions[x].Params["symbols"].(string) - if !okay { - if subscriptions[x].Pair.IsEmpty() { - return nil, errors.New("symbols not passed") - } - symbols = subscriptions[x].Pair.String() - } - payloads = append(payloads, WsSubscriptionInput{ - ID: strconv.FormatInt(ku.Websocket.Conn.GenerateMessageID(false), 10), - Type: operation, - Topic: fmt.Sprintf(subscriptions[x].Channel, symbols), - Response: true, - }) - case marketAllTickersChannel, - privateSpotTradeOrders, - accountBalanceChannel, - marginPositionChannel, - spotMarketAdvancedChannel, - futuresTradeOrderChannel, - futuresStopOrdersLifecycleEventChannel, - futuresAccountBalanceEventChannel, futuresSystemAnnouncementChannel: - input := WsSubscriptionInput{ - ID: strconv.FormatInt(ku.Websocket.Conn.GenerateMessageID(false), 10), - Type: operation, - Topic: subscriptions[x].Channel, - Response: true, - } - switch subscriptions[x].Channel { - case futuresTradeOrderChannel, - futuresStopOrdersLifecycleEventChannel, - futuresAccountBalanceEventChannel, - privateSpotTradeOrders, - accountBalanceChannel, - marginPositionChannel, - spotMarketAdvancedChannel: - input.PrivateChannel = true - } - payloads = append(payloads, input) - case marketTickerSnapshotChannel, futuresPositionChangeEventChannel, - futuresTradeOrdersBySymbolChannel, futuresTrasactionStatisticsTimerEventChannel, - futuresContractMarketDataChannel, futuresOrderbookLevel2Depth50Channel, - futuresOrderbookLevel2Depth5Channel, futuresExecutionDataChannel, - futuresOrderbookLevel2Channel, futuresTickerChannel, - futuresTickerV2Channel: // Symbols - item := WsSubscriptionInput{ - ID: strconv.FormatInt(ku.Websocket.Conn.GenerateMessageID(false), 10), - Type: operation, - Topic: fmt.Sprintf(subscriptions[x].Channel, subscriptions[x].Pair.String()), - Response: true, - } - switch subscriptions[x].Channel { - case futuresPositionChangeEventChannel, - futuresTradeOrdersBySymbolChannel: - item.PrivateChannel = true - } - payloads = append(payloads, item) - case marketTickerSnapshotForCurrencyChannel, - marginLoanChannel: - // 3 means the Currency is used by both switch cases - // 2 means the currency is used by channel = marginLoanChannel - // 1 if used by marketTickerSnapshotForCurrencyChannel - if stat := marketTickerSnapshotForCurrencyChannelCurrencyFilter[subscriptions[x].Pair.Base]; stat == 3 || (stat == 2 && subscriptions[x].Channel == marginLoanChannel) || stat == 1 { - continue - } - input := WsSubscriptionInput{} - if subscriptions[x].Channel == marginLoanChannel { - input.PrivateChannel = true - marketTickerSnapshotForCurrencyChannelCurrencyFilter[subscriptions[x].Pair.Base] += 2 - } else { - marketTickerSnapshotForCurrencyChannelCurrencyFilter[subscriptions[x].Pair.Base]++ - subscriptions[x].Channel += "%s" - } - input.ID = strconv.FormatInt(ku.Websocket.Conn.GenerateMessageID(false), 10) - input.Type = operation - input.Topic = fmt.Sprintf(subscriptions[x].Channel, subscriptions[x].Pair.Base.Upper().String()) - input.Response = true - payloads = append(payloads, input) - case marketCandlesChannel: - interval, err := ku.intervalToString(subscriptions[x].Params["interval"].(kline.Interval)) - if err != nil { - return nil, err - } - payloads = append(payloads, WsSubscriptionInput{ - ID: strconv.FormatInt(ku.Websocket.Conn.GenerateMessageID(false), 10), - Type: operation, - Topic: fmt.Sprintf(subscriptions[x].Channel, subscriptions[x].Pair.Upper().String(), interval), - Response: true, - }) - case marginFundingbookChangeChannel: - currencies, okay := subscriptions[x].Params["currencies"].(string) - if !okay { - return nil, errors.New("currencies not passed") - } - payloads = append(payloads, WsSubscriptionInput{ - ID: strconv.FormatInt(ku.Websocket.Conn.GenerateMessageID(false), 10), - Type: operation, - Topic: fmt.Sprintf(subscriptions[x].Channel, currencies), - Response: true, - }) + } + add(asset.Margin, marginPairs) + + return subs +} + +// spotOrMarginCurrencySubs accepts a map of pairs and a template subscription and returns a list of subscriptions for every currency in Spot and Margin pairs +// If there's a Spot subscription, it won't be added again as a Margin subscription +func spotOrMarginCurrencySubs(assetPairs map[asset.Item]currency.Pairs, b *subscription.Subscription) []subscription.Subscription { + subs := []subscription.Subscription{} + add := func(a asset.Item, currs currency.Currencies) { + if len(currs) == 0 { + return + } + s := *b + s.Asset = a + for _, c := range currs { + s.Channel = fmt.Sprintf(b.Channel, c) + subs = append(subs, s) + } + } + + add(asset.Spot, assetPairs[asset.Spot].GetCurrencies()) + + marginCurrencies := currency.Currencies{} + for _, c := range assetPairs[asset.Margin].GetCurrencies() { + if !assetPairs[asset.Spot].ContainsCurrency(c) { + marginCurrencies = marginCurrencies.Add(c) } } - return payloads, nil + add(asset.Margin, marginCurrencies) + + return subs } // orderbookManager defines a way of managing and maintaining synchronisation diff --git a/exchanges/kucoin/kucoin_wrapper.go b/exchanges/kucoin/kucoin_wrapper.go index 98906dd5514..8c5b659a97d 100644 --- a/exchanges/kucoin/kucoin_wrapper.go +++ b/exchanges/kucoin/kucoin_wrapper.go @@ -28,6 +28,7 @@ import ( "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/stream" "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer" + "github.com/thrasher-corp/gocryptotrader/exchanges/subscription" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" "github.com/thrasher-corp/gocryptotrader/exchanges/trade" "github.com/thrasher-corp/gocryptotrader/log" @@ -157,6 +158,21 @@ func (ku *Kucoin) SetDefaults() { GlobalResultLimit: 1500, }, }, + Subscriptions: []*subscription.Subscription{ + // Where we can we use generic names + {Enabled: true, Channel: subscription.TickerChannel}, // marketTickerChannel + {Enabled: true, Channel: subscription.AllTradesChannel}, // marketMatchChannel + {Enabled: true, Channel: subscription.OrderbookChannel, Interval: kline.HundredMilliseconds}, // marketOrderbookLevel2Channels + {Enabled: true, Channel: futuresTickerV2Channel}, + {Enabled: true, Channel: futuresOrderbookLevel2Depth50Channel}, + {Enabled: true, Channel: marginFundingbookChangeChannel, Authenticated: true}, + {Enabled: true, Channel: accountBalanceChannel, Authenticated: true}, + {Enabled: true, Channel: marginPositionChannel, Authenticated: true}, + {Enabled: true, Channel: marginLoanChannel, Authenticated: true}, + {Enabled: true, Channel: futuresTradeOrderChannel, Authenticated: true}, + {Enabled: true, Channel: futuresStopOrdersLifecycleEventChannel, Authenticated: true}, + {Enabled: true, Channel: futuresAccountBalanceEventChannel, Authenticated: true}, + }, } ku.Requester, err = request.New(ku.Name, common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout), diff --git a/exchanges/kucoin/testdata/wsMarketSnapshot.json b/exchanges/kucoin/testdata/wsMarketSnapshot.json index 51261e57009..7654c401a70 100644 --- a/exchanges/kucoin/testdata/wsMarketSnapshot.json +++ b/exchanges/kucoin/testdata/wsMarketSnapshot.json @@ -1,3 +1,3 @@ -{"type":"message","topic":"/market/snapshot:BTC","subject":"trade.snapshot","data":{"sequence":1698740324504,"data":{"averagePrice":0.00001164,"baseCurrency":"XMR","board":0,"buy":0.00001252,"changePrice":0.00000104800000000000,"changeRate":0.0914,"close":0.000012508,"datetime":1698740324415,"high":0.00001402100000000000,"lastTradedPrice":0.000012508,"low":0.00001129200000000000,"makerCoefficient":2.000000,"makerFeeRate":0.001,"marginTrade":false,"mark":0,"market":"BTC","marketChange1h":{"changeRate":0,"high":0,"low":0,"open":0,"vol":0,"volValue":0},"marketChange24h":{"changePrice":0.00000104800000000000,"changeRate":0.0914,"high":0.00001402100000000000,"low":0.00001129200000000000,"open":0.00001146000000000000,"vol":28474.47280000000000000000,"volValue":0.37038038297340000000},"marketChange4h":{"changePrice":0.00000009600000000000,"changeRate":0.0077,"high":0.00001308400000000000,"low":0.00001241200000000000,"open":0.00001241200000000000,"vol":7090.00000000000000000000,"volValue":0.08885800028840000000},"markets":["BTC"],"open":0.00001146000000000000,"quoteCurrency":"BTC","sell":0.000013191,"sort":100,"symbol":"XMR-BTC","symbolCode":"XMR-BTC","takerCoefficient":2.000000,"takerFeeRate":0.001,"trading":true,"vol":28474.47280000000000000000,"volValue":0.37038038297340000000}}} -{"type":"message","topic":"/market/snapshot:BTC","subject":"trade.snapshot","data":{"sequence":1698740324488,"data":{"averagePrice":0.00000037,"baseCurrency":"MTV","board":0,"buy":0.0000003641,"changePrice":0.00000004770000000000,"changeRate":0.1394,"close":0.0000003897,"datetime":1698740324483,"high":0.00000039450000000000,"lastTradedPrice":0.0000003897,"low":0.00000034200000000000,"makerCoefficient":2.000000,"makerFeeRate":0.001,"marginTrade":false,"mark":0,"market":"BTC","marketChange1h":{"changeRate":0,"high":0,"low":0,"open":0,"vol":0,"volValue":0},"marketChange24h":{"changePrice":0.00000004770000000000,"changeRate":0.1394,"high":0.00000039450000000000,"low":0.00000034200000000000,"open":0.00000034200000000000,"vol":316078.69700000000000000000,"volValue":0.11768519138877000000},"marketChange4h":{"changePrice":0.00000003290000000000,"changeRate":0.0922,"high":0.00000038970000000000,"low":0.00000035680000000000,"open":0.00000035680000000000,"vol":2309.46880000000000000000,"volValue":0.00089999999136000000},"markets":["BTC"],"open":0.00000034200000000000,"quoteCurrency":"BTC","sell":0.0000004022,"sort":100,"symbol":"MTV-BTC","symbolCode":"MTV-BTC","takerCoefficient":2.000000,"takerFeeRate":0.001,"trading":true,"vol":316078.69700000000000000000,"volValue":0.11768519138877000000}}} -{"type":"message","topic":"/market/snapshot:BTC","subject":"trade.snapshot","data":{"sequence":1698740324508,"data":{"averagePrice":0.00007307,"baseCurrency":"BTC","board":0,"buy":0.00008388,"changePrice":0.00001166000000000000,"changeRate":0.1630,"close":0.00008318,"datetime":1698740324437,"high":0.00008486000000000000,"lastTradedPrice":0.00008318,"low":0.00007152000000000000,"makerCoefficient":1.000000,"makerFeeRate":0.001,"marginTrade":false,"mark":0,"market":"USDT","marketChange1h":{"changePrice":-0.00000116000000000000,"changeRate":-0.0137,"high":0.00008434000000000000,"low":0.00008318000000000000,"open":0.00008434000000000000,"vol":189.33430000000000000000,"volValue":0.01578748292300000000},"marketChange24h":{"changePrice":0.00001166000000000000,"changeRate":0.1630,"high":0.00008486000000000000,"low":0.00007152000000000000,"open":0.00007152000000000000,"vol":17062.45450000000000000000,"volValue":1.33076678861000000000},"marketChange4h":{"changePrice":0.00000143000000000000,"changeRate":0.0174,"high":0.00008486000000000000,"low":0.00008175000000000000,"open":0.00008175000000000000,"vol":1752.55690000000000000000,"volValue":0.14543003812900000000},"markets":["BTC"],"open":0.00007152000000000000,"quoteCurrency":"USDT","sell":0.00008421,"sort":100,"symbol":"BTC-USDT","symbolCode":"BTC-USDT","takerCoefficient":1.000000,"takerFeeRate":0.001,"trading":true,"vol":17062.45450000000000000000,"volValue":1.33076678861000000000}}} +{"type":"message","topic":"/market/snapshot:BTC","subject":"trade.snapshot","data":{"sequence":"459320318","data":{"averagePrice":0.00442293,"baseCurrency":"XMR","board":1,"buy":0.004411,"changePrice":0.00000000000000000000,"changeRate":0.0000,"close":0.004415,"datetime":1700555342007,"high":0.00444500000000000000,"lastTradedPrice":0.004415,"low":0.00419100000000000000,"makerCoefficient":1.000000,"makerFeeRate":0.001,"marginTrade":true,"mark":0,"market":"BTC","marketChange1h":{"changePrice":-0.00000200000000000000,"changeRate":-0.0004,"high":0.00443600000000000000,"low":0.00441300000000000000,"open":0.00441700000000000000,"vol":505.11910000000000000000,"volValue":2.23457327520000000000},"marketChange24h":{"changePrice":0.00000000000000000000,"changeRate":0.0000,"high":0.00444500000000000000,"low":0.00419100000000000000,"open":0.00441500000000000000,"vol":13097.33570000000000000000,"volValue":57.44552981000000000000},"marketChange4h":{"changePrice":0.00001100000000000000,"changeRate":0.0024,"high":0.00443600000000000000,"low":0.00439300000000000000,"open":0.00440400000000000000,"vol":2124.84330000000000000000,"volValue":9.37472351370000000000},"markets":["BTC"],"open":0.00441500000000000000,"quoteCurrency":"BTC","sell":0.004415,"sort":100,"symbol":"XMR-BTC","symbolCode":"XMR-BTC","takerCoefficient":1.000000,"takerFeeRate":0.001,"trading":true,"vol":13097.33570000000000000000,"volValue":57.44552981000000000000}}} +{"type":"message","topic":"/market/snapshot:BTC","subject":"trade.snapshot","data":{"sequence":"692562428","data":{"averagePrice":0.05414932,"baseCurrency":"ETH","board":1,"buy":0.053778,"changePrice":-0.00045800000000000000,"changeRate":-0.0084,"close":0.053778,"datetime":1700555340197,"high":0.05484600000000000000,"lastTradedPrice":0.053778,"low":0.05364000000000000000,"makerCoefficient":1.000000,"makerFeeRate":0.001,"marginTrade":true,"mark":0,"market":"BTC","marketChange1h":{"changePrice":-0.00008000000000000000,"changeRate":-0.0014,"high":0.05387400000000000000,"low":0.05371000000000000000,"open":0.05385800000000000000,"vol":63.72190510000000000000,"volValue":3.42879155215990000000},"marketChange24h":{"changePrice":-0.00045800000000000000,"changeRate":-0.0084,"high":0.05484600000000000000,"low":0.05364000000000000000,"open":0.05423600000000000000,"vol":2958.31391160000000000000,"volValue":160.78476727842130000000},"marketChange4h":{"changePrice":-0.00002700000000000000,"changeRate":-0.0005,"high":0.05399000000000000000,"low":0.05371000000000000000,"open":0.05380500000000000000,"vol":166.22099950000000000000,"volValue":8.95534024043750000000},"markets":["BTC","Shanghai-Upgrade"],"open":0.05423600000000000000,"quoteCurrency":"BTC","sell":0.053779,"sort":100,"symbol":"ETH-BTC","symbolCode":"ETH-BTC","takerCoefficient":1.000000,"takerFeeRate":0.001,"trading":true,"vol":2958.31391160000000000000,"volValue":160.78476727842130000000}}} +{"type":"message","topic":"/market/snapshot:BTC","subject":"trade.snapshot","data":{"sequence":"9860735911","data":{"averagePrice":37110.27939304,"baseCurrency":"BTC","board":1,"buy":37366.7,"changePrice":171.50000000000000000000,"changeRate":0.0046,"close":37366.8,"datetime":1700555342151,"high":37750.00000000000000000000,"lastTradedPrice":37366.8,"low":36700.00000000000000000000,"makerCoefficient":1.000000,"makerFeeRate":0.001,"marginTrade":true,"mark":0,"market":"USDS","marketChange1h":{"changePrice":105.60000000000000000000,"changeRate":0.0028,"high":37366.80000000000000000000,"low":37232.30000000000000000000,"open":37261.20000000000000000000,"vol":52.88854739000000000000,"volValue":1972678.83173137400000000000},"marketChange24h":{"changePrice":171.50000000000000000000,"changeRate":0.0046,"high":37750.00000000000000000000,"low":36700.00000000000000000000,"open":37195.30000000000000000000,"vol":2900.37846402000000000000,"volValue":108210331.34015163900000000000},"marketChange4h":{"changePrice":-94.70000000000000000000,"changeRate":-0.0025,"high":37476.40000000000000000000,"low":37232.30000000000000000000,"open":37461.50000000000000000000,"vol":263.14059486000000000000,"volValue":9829529.74388805200000000000},"markets":["USDS"],"open":37195.30000000000000000000,"quoteCurrency":"USDT","sell":37366.8,"sort":100,"symbol":"BTC-USDT","symbolCode":"BTC-USDT","takerCoefficient":1.000000,"takerFeeRate":0.001,"trading":true,"vol":2900.37846402000000000000,"volValue":108210331.34015163900000000000}}} diff --git a/testdata/configtest.json b/testdata/configtest.json index bfaacb5707f..2dc528dad21 100644 --- a/testdata/configtest.json +++ b/testdata/configtest.json @@ -1996,8 +1996,8 @@ "pairs": { "spot": { "assetEnabled": true, - "enabled": "BTC-USDT,ETH-USDT,LTC-USDT,OXEN-BTC,OXEN-ETH,NRG-BTC,AVA-USDT,FET-BTC,FET-ETH,ANKR-BTC,XMR-BTC", - "available": "BTC-USDT,MHC-ETH,MHC-BTC,OXEN-BTC,OXEN-ETH,NRG-BTC,AVA-USDT,FET-BTC,FET-ETH,ANKR-BTC,MHC-USDT,XMR-BTC,XMR-ETH,RIF-BTC,MTV-BTC,MTV-ETH,CRO-BTC,MTV-USDT,KMD-BTC,KMD-USDT,RFOX-USDT,TEL-USDT,TT-USDT,AERGO-USDT,XMR-USDT,TRX-KCS,ATOM-BTC,ATOM-ETH,ATOM-USDT,ATOM-KCS,ETN-USDT,FTM-USDT,TOMO-USDT,VSYS-USDT,OCEAN-BTC,OCEAN-ETH,CHR-BTC,CHR-USDT,FX-BTC,FX-ETH,NIM-BTC,NIM-ETH,COTI-BTC,COTI-USDT,NRG-ETH,BNB-BTC,BNB-USDT,JAR-BTC,JAR-USDT,ALGO-BTC,ALGO-ETH,ALGO-USDT,XEM-BTC,XEM-USDT,CIX100-USDT,XTZ-BTC,XTZ-USDT,ZEC-BTC,ZEC-USDT,ADA-BTC,ADA-USDT,REV-USDT,WXT-BTC,WXT-USDT,FORESTPLUS-BTC,FORESTPLUS-USDT,BOLT-BTC,BOLT-USDT,ARPA-USDT,CHZ-BTC,CHZ-USDT,DAPPT-BTC,DAPPT-USDT,NOIA-BTC,NOIA-USDT,WIN-BTC,WIN-USDT,DERO-BTC,DERO-USDT,BTT-USDT,EOSC-USDT,ENQ-BTC,ENQ-USDT,ONE-BTC,ONE-USDT,TOKO-BTC,TOKO-USDT,VID-BTC,VID-USDT,LUNA-USDT,SXP-BTC,SXP-USDT,AKRO-BTC,AKRO-USDT,ROOBEE-BTC,WIN-TRX,MAP-BTC,MAP-USDT,AMPL-BTC,AMPL-USDT,DAG-USDT,POL-USDT,ARX-USDT,NWC-BTC,NWC-USDT,BEPRO-BTC,BEPRO-USDT,VRA-BTC,VRA-USDT,KSM-BTC,KSM-USDT,DASH-USDT,SUTER-USDT,ACOIN-USDT,SUTER-BTC,SENSO-USDT,PRE-BTC,XDB-USDT,SYLO-USDT,WOM-USDT,SENSO-BTC,DGB-USDT,LYXE-USDT,LYXE-ETH,XDB-BTC,STX-BTC,STX-USDT,XSR-USDT,COMP-USDT,CRO-USDT,KAI-USDT,KAI-BTC,WEST-BTC,WEST-USDT,EWT-BTC,WAVES-USDT,WAVES-BTC,ORN-USDT,AMPL-ETH,BNS-USDT,MKR-USDT,SUKU-BTC,MLK-BTC,MLK-USDT,JST-USDT,KAI-ETH,SUKU-USDT,DIA-USDT,DIA-BTC,LINK-BTC,LINK-USDT,DOT-USDT,DOT-BTC,SHA-BTC,SHA-USDT,EWT-USDT,USDJ-USDT,EFX-BTC,CKB-BTC,CKB-USDT,UMA-USDT,ALEPH-USDT,VELO-USDT,SUN-USDT,BUY-USDT,YFI-USDT,OXEN-USDT,UNI-USDT,UOS-USDT,UOS-BTC,NIM-USDT,DEGO-USDT,DEGO-ETH,UDOO-ETH,RFUEL-USDT,FIL-USDT,UBX-ETH,REAP-USDT,AAVE-USDT,AAVE-BTC,TONE-BTC,TONE-ETH,ELF-ETH,AERGO-BTC,IOST-ETH,KCS-USDT,SNX-ETH,TOMO-ETH,KCS-ETH,DRGN-BTC,WAN-ETH,NULS-ETH,AXPR-ETH,POWR-BTC,QTUM-BTC,MANA-BTC,TEL-BTC,XYO-ETH,AXPR-BTC,ETN-BTC,COV-ETH,VET-BTC,KCS-BTC,CAPP-ETH,ONT-BTC,DRGN-ETH,DAG-ETH,TOMO-BTC,WAN-BTC,KNC-ETH,CRPT-ETH,LTC-USDT,BAX-ETH,BSV-USDT,DENT-ETH,AION-ETH,LYM-ETH,TRAC-ETH,ENJ-BTC,WAXP-BTC,DGB-BTC,ELA-BTC,ZIL-BTC,BSV-BTC,XLM-USDT,IOTX-ETH,SOUL-BTC,DOCK-BTC,AMB-ETH,TRX-BTC,XRP-TUSD,NULS-BTC,ETH-DAI,LSK-BTC,GMB-ETH,GMB-BTC,NEO-ETH,OMG-ETH,BTC-TUSD,KAT-USDT,KNC-BTC,ELF-BTC,MANA-ETH,ETC-USDT,ONT-ETH,MKR-BTC,KAT-BTC,XRP-USDC,XYO-BTC,SNT-ETH,ZRX-BTC,LOOM-ETH,AION-BTC,POWR-ETH,OLT-ETH,OLT-BTC,SNT-BTC,TRAC-BTC,XLM-ETH,ETH-USDT,BSV-ETH,TRX-ETH,ETN-ETH,AOA-USDT,BCD-BTC,DENT-BTC,DOCK-ETH,KEY-BTC,EOS-KCS,XLM-BTC,ADB-ETH,TIME-ETH,CVC-BTC,LSK-ETH,QKC-BTC,AMB-BTC,USDT-TUSD,ETC-ETH,XRP-BTC,NEO-KCS,SNX-USDT,CRPT-BTC,IOTX-BTC,LTC-ETH,XRP-KCS,ADB-BTC,LTC-KCS,TEL-ETH,DCR-ETH,LYM-USDT,USDT-USDC,ETH-USDC,DAG-BTC,AVA-BTC,BTC-USDT,WAXP-ETH,XRP-USDT,KEY-ETH,VET-ETH,FTM-BTC,USDT-DAI,QKC-ETH,ETH-BTC,MAN-BTC,CPC-ETH,TRX-USDT,BTC-DAI,ONT-USDT,DASH-ETH,BAX-BTC,AVA-ETH,LOOM-BTC,MVP-BTC,MKR-ETH,COV-BTC,CPC-BTC,REQ-ETH,EOS-BTC,LTC-BTC,XRP-ETH,CAPP-BTC,FTM-ETH,BCD-ETH,ZRX-ETH,DGB-ETH,VET-USDT,REQ-BTC,UTK-BTC,PLAY-BTC,UTK-ETH,SNX-BTC,MVP-ETH,NEO-BTC,SOUL-ETH,NEO-USDT,ELA-ETH,OMG-BTC,TIME-BTC,AOA-BTC,ETC-BTC,DCR-BTC,BTC-USDC,ENJ-ETH,IOST-BTC,DASH-BTC,EOS-USDT,EOS-ETH,ZIL-ETH,ETH-TUSD,GAS-BTC,LYM-BTC,BCH-BTC,VSYS-BTC,BCH-USDT,MKR-DAI,SOLVE-BTC,GRIN-BTC,GRIN-USDT,UQC-BTC,UQC-ETH,OPCT-BTC,OPCT-ETH,PRE-USDT,SHR-BTC,SHR-USDT,UBXT-USDT,ROSE-USDT,USDC-USDT,CTI-USDT,CTI-ETH,ETH2-ETH,BUX-BTC,XHV-USDT,PLU-USDT,GRT-USDT,CAS-BTC,CAS-USDT,MSWAP-BTC,MSWAP-USDT,GOM2-BTC,GOM2-USDT,REVV-BTC,REVV-USDT,LON-USDT,1INCH-USDT,LOC-USDT,API3-USDT,UNFI-USDT,HTR-USDT,FRONT-USDT,FRONT-BTC,WBTC-BTC,WBTC-ETH,MIR-USDT,LTC-USDC,BCH-USDC,HYDRA-USDT,DFI-USDT,DFI-BTC,CRV-USDT,SUSHI-USDT,FRM-USDT,EOS-USDC,BSV-USDC,ZEN-USDT,CUDOS-USDT,ADA-USDC,REN-USDT,LRC-USDT,LINK-USDC,KLV-USDT,KLV-BTC,BOA-USDT,THETA-USDT,QNT-USDT,BAT-USDT,DOGE-USDT,DOGE-USDC,DAO-USDT,STRONG-USDT,TRIAS-USDT,TRIAS-BTC,DOGE-BTC,MITX-BTC,MITX-USDT,CAKE-USDT,ORAI-USDT,ZEE-USDT,LTX-USDT,LTX-BTC,MASK-USDT,KLV-TRX,IDEA-USDT,PHA-USDT,PHA-ETH,BCH-KCS,SRK-USDT,SRK-BTC,ADA-KCS,HTR-BTC,BSV-KCS,DOT-KCS,LINK-KCS,MIR-KCS,BNB-KCS,XLM-KCS,VET-KCS,SWINGBY-USDT,SWINGBY-BTC,XHV-BTC,DASH-KCS,UNI-KCS,AAVE-KCS,DOGE-KCS,ZEC-KCS,XTZ-KCS,GRT-KCS,ALGO-KCS,EWT-KCS,GAS-USDT,AVAX-USDT,AVAX-BTC,KRL-BTC,KRL-USDT,POLK-USDT,POLK-BTC,ENJ-USDT,MANA-USDT,RNDR-USDT,RNDR-BTC,RLY-USDT,ANC-USDT,SKEY-USDT,LAYER-USDT,TARA-USDT,TARA-ETH,IOST-USDT,DYP-USDT,DYP-ETH,XYM-USDT,XYM-BTC,PCX-USDT,PCX-BTC,ORBS-USDT,ORBS-BTC,BTC3L-USDT,BTC3S-USDT,ETH3L-USDT,ETH3S-USDT,ANKR-USDT,DSLA-USDT,DSLA-BTC,SAND-USDT,VAI-USDT,XCUR-USDT,XCUR-BTC,FLUX-USDT,OMG-USDT,ZIL-USDT,DODO-USDT,MAN-USDT,BAX-USDT,BOSON-USDT,BOSON-ETH,PUNDIX-USDT,PUNDIX-BTC,WAXP-USDT,HT-USDT,PDEX-USDT,LABS-USDT,LABS-ETH,GMB-USDT,PHNX-USDT,PHNX-BTC,HAI-USDT,EQZ-USDT,FORTH-USDT,HORD-USDT,CGG-USDT,UBX-USDT,GHX-USDT,TCP-USDT,STND-USDT,STND-ETH,TOWER-USDT,TOWER-BTC,ACE-USDT,LOCG-USDT,CARD-USDT,FLY-USDT,CWS-USDT,XDC-USDT,XDC-ETH,STRK-BTC,STRK-ETH,SHIB-USDT,POLX-USDT,KDA-USDT,KDA-BTC,ICP-USDT,ICP-BTC,STC-USDT,STC-BTC,GOVI-USDT,GOVI-BTC,FKX-USDT,CELO-USDT,CELO-BTC,CUSD-USDT,CUSD-BTC,FCL-USDT,MATIC-USDT,MATIC-BTC,ELA-USDT,CRPT-USDT,OPCT-USDT,OGN-USDT,OGN-BTC,OUSD-USDT,OUSD-BTC,TLOS-USDT,TLOS-BTC,YOP-USDT,YOP-ETH,GLQ-USDT,GLQ-BTC,MXC-USDT,ERSDL-USDT,HOTCROSS-USDT,ADA3L-USDT,ADA3S-USDT,HYVE-USDT,HYVE-BTC,DAPPX-USDT,KONO-USDT,PRQ-USDT,MAHA-USDT,MAHA-BTC,FEAR-USDT,PYR-USDT,PYR-BTC,PROM-USDT,PROM-BTC,GLCH-USDT,UNO-USDT,ALBT-USDT,ALBT-ETH,XCAD-USDT,EOS3L-USDT,EOS3S-USDT,BCH3L-USDT,BCH3S-USDT,ELON-USDT,APL-USDT,FCL-ETH,VEED-USDT,VEED-BTC,DIVI-USDT,PDEX-BTC,JUP-USDT,JUP-ETH,POLS-USDT,POLS-BTC,LPOOL-USDT,LPOOL-BTC,LSS-USDT,VET3L-USDT,VET3S-USDT,LTC3L-USDT,LTC3S-USDT,ABBC-USDT,ABBC-BTC,KOK-USDT,ROSN-USDT,DORA-USDT,DORA-BTC,ZCX-USDT,ZCX-BTC,NORD-USDT,GMEE-USDT,SFUND-USDT,XAVA-USDT,AI-USDT,ALPACA-USDT,IOI-USDT,NFT-USDT,NFT-TRX,MNST-USDT,MEM-USDT,AGIX-USDT,AGIX-BTC,AGIX-ETH,CQT-USDT,AIOZ-USDT,MARSH-USDT,HAPI-USDT,MODEFI-USDT,MODEFI-BTC,YFDAI-USDT,YFDAI-BTC,GENS-USDT,FORM-USDT,ARRR-USDT,ARRR-BTC,TOKO-KCS,EXRD-USDT,NGM-USDT,LPT-USDT,STMX-USDT,ASD-USDT,BOND-USDT,HAI-BTC,SOUL-USDT,2CRZ-USDT,NEAR-USDT,NEAR-BTC,DFYN-USDT,OOE-USDT,CFG-USDT,CFG-BTC,AXS-USDT,CLV-USDT,ROUTE-USDT,KAR-USDT,EFX-USDT,XDC-BTC,SHFT-USDT,PMON-USDT,DPET-USDT,ERG-USDT,ERG-BTC,SOL-USDT,SLP-USDT,LITH-USDT,LITH-ETH,XCH-USDT,HAKA-USDT,LAYER-BTC,MTL-USDT,MTL-BTC,IOTX-USDT,GALA-USDT,REQ-USDT,TXA-USDT,TXA-USDC,CIRUS-USDT,QI-USDT,QI-BTC,ODDZ-USDT,PNT-USDT,PNT-BTC,XPR-USDT,XPR-BTC,TRIBE-USDT,SHFT-BTC,MOVR-USDT,MOVR-ETH,WOO-USDT,WILD-USDT,QRDO-USDT,QRDO-ETH,SDN-USDT,SDN-ETH,MAKI-USDT,MAKI-BTC,REP-USDT,REP-BTC,REP-ETH,BNT-USDT,BNT-BTC,BNT-ETH,OXT-USDT,OXT-BTC,OXT-ETH,BAL-USDT,BAL-BTC,BAL-ETH,STORJ-USDT,STORJ-BTC,STORJ-ETH,YGG-USDT,NDAU-USDT,SDAO-USDT,SDAO-ETH,XRP3L-USDT,XRP3S-USDT,SKL-USDT,SKL-BTC,NMR-USDT,NMR-BTC,IXS-USDT,TRB-USDT,TRB-BTC,DYDX-USDT,XYO-USDT,GTC-USDT,GTC-BTC,EQX-USDT,EQX-BTC,RLC-USDT,RLC-BTC,XPRT-USDT,EGLD-USDT,EGLD-BTC,HBAR-USDT,HBAR-BTC,DOGE3L-USDT,DOGE3S-USDT,FLOW-USDT,FLOW-BTC,NKN-USDT,NKN-BTC,PBX-USDT,SOL3L-USDT,SOL3S-USDT,MLN-USDT,MLN-BTC,XNL-USDT,SOLVE-USDT,WNCG-USDT,WNCG-BTC,DMTR-USDT,LINK3L-USDT,LINK3S-USDT,DOT3L-USDT,DOT3S-USDT,CTSI-USDT,CTSI-BTC,ALICE-USDT,ALICE-BTC,ALICE-ETH,OPUL-USDT,ILV-USDT,BAND-USDT,BAND-BTC,FTT-USDT,FTT-BTC,DVPN-USDT,SKU-USDT,SKU-BTC,EDG-USDT,SLIM-USDT,TLM-USDT,TLM-BTC,TLM-ETH,DEXE-USDT,DEXE-BTC,DEXE-ETH,MATTER-USDT,CUDOS-BTC,RUNE-USDT,RUNE-BTC,RMRK-USDT,BMON-USDT,C98-USDT,BLOK-USDT,SOLR-USDT,ATOM3L-USDT,ATOM3S-USDT,UNI3L-USDT,UNI3S-USDT,WSIENNA-USDT,PUSH-USDT,PUSH-BTC,FORM-ETH,NTVRK-USDT,NTVRK-USDC,AXS3L-USDT,AXS3S-USDT,FTM3L-USDT,FTM3S-USDT,FLAME-USDT,AGLD-USDT,NAKA-USDT,YLD-USDT,TONE-USDT,REEF-USDT,REEF-BTC,TIDAL-USDT,TVK-USDT,TVK-BTC,INJ-USDT,INJ-BTC,BNB3L-USDT,BNB3S-USDT,MATIC3L-USDT,MATIC3S-USDT,NFTB-USDT,VEGA-USDT,VEGA-ETH,ALPHA-USDT,ALPHA-BTC,BADGER-USDT,BADGER-BTC,UNO-BTC,ZKT-USDT,AR-USDT,AR-BTC,XVS-USDT,XVS-BTC,JASMY-USDT,PERP-USDT,PERP-BTC,GHST-USDT,GHST-BTC,SCLP-USDT,SCLP-BTC,SUPER-USDT,SUPER-BTC,CPOOL-USDT,HERO-USDT,BASIC-USDT,XED-USDT,XED-BTC,AURY-USDT,SWASH-USDT,LTO-USDT,LTO-BTC,BUX-USDT,MTRG-USDT,DREAMS-USDT,SHIB-DOGE,QUICK-USDT,QUICK-BTC,TRU-USDT,TRU-BTC,WRX-USDT,WRX-BTC,TKO-USDT,TKO-BTC,SUSHI3L-USDT,SUSHI3S-USDT,NEAR3L-USDT,NEAR3S-USDT,DATA-USDT,DATA-BTC,NORD-BTC,ISP-USDT,CERE-USDT,SHILL-USDT,HEGIC-USDT,HEGIC-BTC,ERN-USDT,ERN-BTC,FTG-USDT,PAXG-USDT,PAXG-BTC,AUDIO-USDT,AUDIO-BTC,ENS-USDT,AAVE3L-USDT,AAVE3S-USDT,SAND3L-USDT,SAND3S-USDT,XTM-USDT,MNW-USDT,FXS-USDT,FXS-BTC,ATA-USDT,ATA-BTC,VXV-USDT,LRC-BTC,LRC-ETH,DPR-USDT,CWAR-USDT,CWAR-BTC,FLUX-BTC,EDG-BTC,PBR-USDT,WNXM-USDT,WNXM-BTC,ANT-USDT,ANT-BTC,COV-USDT,SWP-USDT,TWT-USDT,TWT-BTC,OM-USDT,OM-BTC,ADX-USDT,AVAX3L-USDT,AVAX3S-USDT,MANA3L-USDT,MANA3S-USDT,GLM-USDT,GLM-BTC,BAKE-USDT,BAKE-BTC,BAKE-ETH,NUM-USDT,VLX-USDT,VLX-BTC,TRADE-USDT,TRADE-BTC,1EARTH-USDT,MONI-USDT,LIKE-USDT,MFT-USDT,MFT-BTC,LIT-USDT,LIT-BTC,KAVA-USDT,SFP-USDT,SFP-BTC,BURGER-USDT,BURGER-BTC,ILA-USDT,CREAM-USDT,CREAM-BTC,RSR-USDT,RSR-BTC,BUY-BTC,IMX-USDT,GODS-USDT,KMA-USDT,SRM-USDT,SRM-BTC,POLC-USDT,XTAG-USDT,MNET-USDT,NGC-USDT,HARD-USDT,GALAX3L-USDT,GALAX3S-USDT,UNIC-USDT,POND-USDT,POND-BTC,VR-USDT,EPIK-USDT,NGL-USDT,NGL-BTC,KDON-USDT,PEL-USDT,CIRUS-ETH,LINA-USDT,LINA-BTC,KLAY-USDT,KLAY-BTC,CREDI-USDT,TRVL-USDT,LACE-USDT,LACE-ETH,ARKER-USDT,BONDLY-USDT,BONDLY-ETH,XEC-USDT,HEART-USDT,HEART-BTC,UNB-USDT,GAFI-USDT,KOL-USDT,KOL-ETH,H3RO3S-USDT,FALCONS-USDT,UFO-USDT,CHMB-USDT,GEEQ-USDT,ORC-USDT,RACEFI-USDT,PEOPLE-USDT,ADS-USDT,ADS-BTC,OCEAN-USDT,SOS-USDT,WHALE-USDT,TIME-USDT,CWEB-USDT,IOTA-USDT,IOTA-BTC,OOKI-USDT,OOKI-BTC,HNT-USDT,HNT-BTC,GGG-USDT,POWR-USDT,REVU-USDT,CLH-USDT,PLGR-USDT,GLMR-USDT,GLMR-BTC,LOVE-USDT,CTC-USDT,CTC-BTC,GARI-USDT,FRR-USDT,ASTR-USDT,ASTR-BTC,ERTHA-USDT,FCON-USDT,ACA-USDT,ACA-BTC,MTS-USDT,ROAR-USDT,HBB-USDT,SURV-USDT,CVX-USDT,AMP-USDT,ACT-USDT,MJT-USDT,MJT-KCS,SHX-USDT,SHX-BTC,STARLY-USDT,ONSTON-USDT,RANKER-USDT,WMT-USDT,XNO-USDT,XNO-BTC,MARS4-USDT,TFUEL-USDT,TFUEL-BTC,METIS-USDT,LAVAX-USDT,WAL-USDT,BULL-USDT,SON-USDT,MELOS-USDT,APE-USDT,GMT-USDT,BICO-USDT,STG-USDT,LMR-USDT,LMR-BTC,LOKA-USDT,URUS-USDT,JAM-USDT,JAM-ETH,BNC-USDT,LBP-USDT,CFX-USDT,LOOKS-USDT,XCN-USDT,XCN-BTC,KP3R-USDT,TITAN-USDT,INDI-USDT,UPO-USDT,SPELL-USDT,SLCL-USDT,CEEK-USDT,VEMP-USDT,BETA-USDT,NHCT-USDT,ARNM-USDT,FRA-USDT,VISION-USDT,COCOS-USDT,ALPINE-USDT,BNX-USDT,ZBC-USDT,WOOP-USDT,T-USDT,NYM-USDT,VOXEL-USDT,VOXEL-ETH,PSTAKE-USDT,SPA-USDT,SPA-ETH,SYNR-USDT,DAR-USDT,DAR-BTC,MV-USDT,XDEFI-USDT,RACA-USDT,XWG-USDT,HAWK-USDT,TRVL-BTC,SWFTC-USDT,IDEX-USDT,BRWL-USDT,PLATO-USDT,TAUM-USDT,CELR-USDT,AURORA-USDT,POSI-USDT,COOHA-USDT,KNC-USDT,EPK-USDT,PLD-USDT,PSL-USDT,PKF-USDT,OVR-USDT,SYS-USDT,SYS-BTC,BRISE-USDT,DG-USDT,EPX-USDT,GST-USDT,PLY-USDT,GAL-USDT,BSW-USDT,FITFI-USDT,FSN-USDT,H2O-USDT,GMM-USDT,AKT-USDT,SIN-USDT,AUSD-USDT,BOBA-USDT,KARA-USDT,BFC-USDT,BIFI-USDT,DFA-USDT,KYL-USDT,FCD-USDT,MBL-USDT,CELT-USDT,DUSK-USDT,USDD-USDT,USDD-USDC,FITFI-USDC,MBOX-USDT,MBOX-BTC,APE-USDC,AVAX-USDC,SHIB-USDC,XCN-USDC,TRX-USDC,NEAR-USDC,MATIC-USDC,FTM-USDC,ZIL-USDC,SOL-USDC,MLS-USDT,AFK-USDT,AFK-USDC,ACH-USDT,SCRT-USDT,SCRT-BTC,APE3L-USDT,APE3S-USDT,STORE-USDT,STORE-ETH,GMT3L-USDT,GMT3S-USDT,CCD-USDT,DOSE-USDC,LUNC-USDT,LUNC-USDC,USTC-USDT,USTC-USDC,GMT-USDC,VRA-USDC,DOT-USDC,RUNE-USDC,ATOM-USDC,BNB-USDC,JASMY-USDC,KCS-USDC,KDA-USDC,ALGO-USDC,LUNA-USDC,OP-USDT,OP-USDC,JASMY3L-USDT,JASMY3S-USDT,EVER-USDT,MOOV-USDT,IHC-USDT,ICX-USDT,ICX-ETH,BTC-BRL,ETH-BRL,USDT-BRL,WELL-USDT,FORT-USDT,USDP-USDT,USDD-TRX,CSPR-USDT,CSPR-ETH,WEMIX-USDT,REV3L-USDT,OLE-USDT,LDO-USDT,LDO-USDC,CULT-USDT,SWFTC-USDC,FIDA-USDT,BUSD-USDT,RBP-USDT,SRBP-USDT,HIBAYC-USDT,BUSD-USDC,OGV-USDT,WOMBAT-USDT,HIPUNKS-USDT,FT-USDT,ETC-USDC,HIENS4-USDT,EGAME-USDT,EGAME-BTC,STEPWATCH-USDT,HISAND33-USDT,DC-USDT,NEER-USDT,RVN-USDT,HIENS3-USDT,MC-USDT,PEEL-USDT,PEEL-BTC,SDL-USDT,SDL-BTC,SWEAT-USDT,HIODBS-USDT,CMP-USDT,PIX-USDT,MPLX-USDT,HIDOODLES-USDT,ETHW-USDT,QUARTZ-USDT,ACQ-USDT,ACQ-USDC,AOG-USDT,HIMAYC-USDT,PRMX-USDT,RED-USDT,PUMLX-USDT,XETA-USDT,GEM-USDT,DERC-USDT,P00LS-USDT,P00LS-USDC,KICKS-USDT,TRIBL-USDT,GMX-USDT,HIOD-USDT,POKT-USDT,EFI-USDT,APT-USDT,BBC-USDT,EUL-USDT,TON-USDT,PIAS-USDT,HIMEEBITS-USDT,HISQUIGGLE-USDT,XCV-USDT,HFT-USDT,HFT-USDC,ECOX-USDT,AMB-USDT,AZERO-USDT,HIFIDENZA-USDT,BEAT-USDT", + "enabled": "BTC-USDT,ETH-BTC,ETH-USDT,LTC-USDT", + "available": "BTC-USDT,MHC-ETH,MHC-BTC,AVA-USDT,FET-BTC,FET-ETH,ANKR-BTC,MHC-USDT,XMR-BTC,XMR-ETH,RIF-BTC,MTV-BTC,MTV-ETH,CRO-BTC,MTV-USDT,KMD-BTC,KMD-USDT,RFOX-USDT,TEL-USDT,TT-USDT,AERGO-USDT,XMR-USDT,TRX-KCS,ATOM-BTC,ATOM-ETH,ATOM-USDT,ATOM-KCS,ETN-USDT,FTM-USDT,TOMO-USDT,VSYS-USDT,OCEAN-BTC,OCEAN-ETH,CHR-BTC,CHR-USDT,FX-BTC,FX-ETH,NIM-BTC,NIM-ETH,COTI-BTC,COTI-USDT,NRG-ETH,BNB-BTC,BNB-USDT,JAR-BTC,JAR-USDT,ALGO-BTC,ALGO-ETH,ALGO-USDT,XEM-BTC,XEM-USDT,CIX100-USDT,XTZ-BTC,XTZ-USDT,ZEC-BTC,ZEC-USDT,ADA-BTC,ADA-USDT,REV-USDT,WXT-BTC,WXT-USDT,FORESTPLUS-BTC,FORESTPLUS-USDT,BOLT-BTC,BOLT-USDT,ARPA-USDT,CHZ-BTC,CHZ-USDT,DAPPT-BTC,DAPPT-USDT,NOIA-BTC,NOIA-USDT,WIN-BTC,WIN-USDT,DERO-BTC,DERO-USDT,BTT-USDT,EOSC-USDT,ENQ-BTC,ENQ-USDT,ONE-BTC,ONE-USDT,TOKO-BTC,TOKO-USDT,VID-BTC,VID-USDT,LUNA-USDT,SXP-BTC,SXP-USDT,AKRO-BTC,AKRO-USDT,ROOBEE-BTC,WIN-TRX,MAP-BTC,MAP-USDT,AMPL-BTC,AMPL-USDT,DAG-USDT,POL-USDT,ARX-USDT,NWC-BTC,NWC-USDT,BEPRO-BTC,BEPRO-USDT,VRA-BTC,VRA-USDT,KSM-BTC,KSM-USDT,DASH-USDT,SUTER-USDT,ACOIN-USDT,SUTER-BTC,SENSO-USDT,PRE-BTC,XDB-USDT,SYLO-USDT,WOM-USDT,SENSO-BTC,DGB-USDT,LYXE-USDT,LYXE-ETH,XDB-BTC,STX-BTC,STX-USDT,XSR-USDT,COMP-USDT,CRO-USDT,KAI-USDT,KAI-BTC,WEST-BTC,WEST-USDT,EWT-BTC,WAVES-USDT,WAVES-BTC,ORN-USDT,AMPL-ETH,BNS-USDT,MKR-USDT,SUKU-BTC,MLK-BTC,MLK-USDT,JST-USDT,KAI-ETH,SUKU-USDT,DIA-USDT,DIA-BTC,LINK-BTC,LINK-USDT,DOT-USDT,DOT-BTC,SHA-BTC,SHA-USDT,EWT-USDT,USDJ-USDT,EFX-BTC,CKB-BTC,CKB-USDT,UMA-USDT,ALEPH-USDT,VELO-USDT,SUN-USDT,BUY-USDT,YFI-USDT,OXEN-USDT,UNI-USDT,UOS-USDT,UOS-BTC,NIM-USDT,DEGO-USDT,DEGO-ETH,UDOO-ETH,RFUEL-USDT,FIL-USDT,UBX-ETH,REAP-USDT,AAVE-USDT,AAVE-BTC,TONE-BTC,TONE-ETH,ELF-ETH,AERGO-BTC,IOST-ETH,KCS-USDT,SNX-ETH,TOMO-ETH,KCS-ETH,DRGN-BTC,WAN-ETH,NULS-ETH,AXPR-ETH,POWR-BTC,QTUM-BTC,MANA-BTC,TEL-BTC,XYO-ETH,AXPR-BTC,ETN-BTC,COV-ETH,VET-BTC,KCS-BTC,CAPP-ETH,ONT-BTC,DRGN-ETH,DAG-ETH,TOMO-BTC,WAN-BTC,KNC-ETH,CRPT-ETH,LTC-USDT,BAX-ETH,BSV-USDT,DENT-ETH,AION-ETH,LYM-ETH,TRAC-ETH,ENJ-BTC,WAXP-BTC,DGB-BTC,ELA-BTC,ZIL-BTC,BSV-BTC,XLM-USDT,IOTX-ETH,SOUL-BTC,DOCK-BTC,AMB-ETH,TRX-BTC,XRP-TUSD,NULS-BTC,ETH-DAI,LSK-BTC,GMB-ETH,GMB-BTC,NEO-ETH,OMG-ETH,BTC-TUSD,KAT-USDT,KNC-BTC,ELF-BTC,MANA-ETH,ETC-USDT,ONT-ETH,MKR-BTC,KAT-BTC,XRP-USDC,XYO-BTC,SNT-ETH,ZRX-BTC,LOOM-ETH,AION-BTC,POWR-ETH,OLT-ETH,OLT-BTC,SNT-BTC,TRAC-BTC,XLM-ETH,ETH-USDT,BSV-ETH,TRX-ETH,ETN-ETH,AOA-USDT,BCD-BTC,DENT-BTC,DOCK-ETH,KEY-BTC,EOS-KCS,XLM-BTC,ADB-ETH,TIME-ETH,CVC-BTC,LSK-ETH,QKC-BTC,AMB-BTC,USDT-TUSD,ETC-ETH,XRP-BTC,NEO-KCS,SNX-USDT,CRPT-BTC,IOTX-BTC,LTC-ETH,XRP-KCS,ADB-BTC,LTC-KCS,TEL-ETH,DCR-ETH,LYM-USDT,USDT-USDC,ETH-USDC,DAG-BTC,AVA-BTC,BTC-USDT,WAXP-ETH,XRP-USDT,KEY-ETH,VET-ETH,FTM-BTC,USDT-DAI,QKC-ETH,ETH-BTC,MAN-BTC,CPC-ETH,TRX-USDT,BTC-DAI,ONT-USDT,DASH-ETH,BAX-BTC,AVA-ETH,LOOM-BTC,MVP-BTC,MKR-ETH,COV-BTC,CPC-BTC,REQ-ETH,EOS-BTC,LTC-BTC,XRP-ETH,CAPP-BTC,FTM-ETH,BCD-ETH,ZRX-ETH,DGB-ETH,VET-USDT,REQ-BTC,UTK-BTC,PLAY-BTC,UTK-ETH,SNX-BTC,MVP-ETH,NEO-BTC,SOUL-ETH,NEO-USDT,ELA-ETH,OMG-BTC,TIME-BTC,AOA-BTC,ETC-BTC,DCR-BTC,BTC-USDC,ENJ-ETH,IOST-BTC,DASH-BTC,EOS-USDT,EOS-ETH,ZIL-ETH,ETH-TUSD,GAS-BTC,LYM-BTC,BCH-BTC,VSYS-BTC,BCH-USDT,MKR-DAI,SOLVE-BTC,GRIN-BTC,GRIN-USDT,UQC-BTC,UQC-ETH,OPCT-BTC,OPCT-ETH,PRE-USDT,SHR-BTC,SHR-USDT,UBXT-USDT,ROSE-USDT,USDC-USDT,CTI-USDT,CTI-ETH,ETH2-ETH,BUX-BTC,XHV-USDT,PLU-USDT,GRT-USDT,CAS-BTC,CAS-USDT,MSWAP-BTC,MSWAP-USDT,GOM2-BTC,GOM2-USDT,REVV-BTC,REVV-USDT,LON-USDT,1INCH-USDT,LOC-USDT,API3-USDT,UNFI-USDT,HTR-USDT,FRONT-USDT,FRONT-BTC,WBTC-BTC,WBTC-ETH,MIR-USDT,LTC-USDC,BCH-USDC,HYDRA-USDT,DFI-USDT,DFI-BTC,CRV-USDT,SUSHI-USDT,FRM-USDT,EOS-USDC,BSV-USDC,ZEN-USDT,CUDOS-USDT,ADA-USDC,REN-USDT,LRC-USDT,LINK-USDC,KLV-USDT,KLV-BTC,BOA-USDT,THETA-USDT,QNT-USDT,BAT-USDT,DOGE-USDT,DOGE-USDC,DAO-USDT,STRONG-USDT,TRIAS-USDT,TRIAS-BTC,DOGE-BTC,MITX-BTC,MITX-USDT,CAKE-USDT,ORAI-USDT,ZEE-USDT,LTX-USDT,LTX-BTC,MASK-USDT,KLV-TRX,IDEA-USDT,PHA-USDT,PHA-ETH,BCH-KCS,SRK-USDT,SRK-BTC,ADA-KCS,HTR-BTC,BSV-KCS,DOT-KCS,LINK-KCS,MIR-KCS,BNB-KCS,XLM-KCS,VET-KCS,SWINGBY-USDT,SWINGBY-BTC,XHV-BTC,DASH-KCS,UNI-KCS,AAVE-KCS,DOGE-KCS,ZEC-KCS,XTZ-KCS,GRT-KCS,ALGO-KCS,EWT-KCS,GAS-USDT,AVAX-USDT,AVAX-BTC,KRL-BTC,KRL-USDT,POLK-USDT,POLK-BTC,ENJ-USDT,MANA-USDT,RNDR-USDT,RNDR-BTC,RLY-USDT,ANC-USDT,SKEY-USDT,LAYER-USDT,TARA-USDT,TARA-ETH,IOST-USDT,DYP-USDT,DYP-ETH,XYM-USDT,XYM-BTC,PCX-USDT,PCX-BTC,ORBS-USDT,ORBS-BTC,BTC3L-USDT,BTC3S-USDT,ETH3L-USDT,ETH3S-USDT,ANKR-USDT,DSLA-USDT,DSLA-BTC,SAND-USDT,VAI-USDT,XCUR-USDT,XCUR-BTC,FLUX-USDT,OMG-USDT,ZIL-USDT,DODO-USDT,MAN-USDT,BAX-USDT,BOSON-USDT,BOSON-ETH,PUNDIX-USDT,PUNDIX-BTC,WAXP-USDT,HT-USDT,PDEX-USDT,LABS-USDT,LABS-ETH,GMB-USDT,PHNX-USDT,PHNX-BTC,HAI-USDT,EQZ-USDT,FORTH-USDT,HORD-USDT,CGG-USDT,UBX-USDT,GHX-USDT,TCP-USDT,STND-USDT,STND-ETH,TOWER-USDT,TOWER-BTC,ACE-USDT,LOCG-USDT,CARD-USDT,FLY-USDT,CWS-USDT,XDC-USDT,XDC-ETH,STRK-BTC,STRK-ETH,SHIB-USDT,POLX-USDT,KDA-USDT,KDA-BTC,ICP-USDT,ICP-BTC,STC-USDT,STC-BTC,GOVI-USDT,GOVI-BTC,FKX-USDT,CELO-USDT,CELO-BTC,CUSD-USDT,CUSD-BTC,FCL-USDT,MATIC-USDT,MATIC-BTC,ELA-USDT,CRPT-USDT,OPCT-USDT,OGN-USDT,OGN-BTC,OUSD-USDT,OUSD-BTC,TLOS-USDT,TLOS-BTC,YOP-USDT,YOP-ETH,GLQ-USDT,GLQ-BTC,MXC-USDT,ERSDL-USDT,HOTCROSS-USDT,ADA3L-USDT,ADA3S-USDT,HYVE-USDT,HYVE-BTC,DAPPX-USDT,KONO-USDT,PRQ-USDT,MAHA-USDT,MAHA-BTC,FEAR-USDT,PYR-USDT,PYR-BTC,PROM-USDT,PROM-BTC,GLCH-USDT,UNO-USDT,ALBT-USDT,ALBT-ETH,XCAD-USDT,EOS3L-USDT,EOS3S-USDT,BCH3L-USDT,BCH3S-USDT,ELON-USDT,APL-USDT,FCL-ETH,VEED-USDT,VEED-BTC,DIVI-USDT,PDEX-BTC,JUP-USDT,JUP-ETH,POLS-USDT,POLS-BTC,LPOOL-USDT,LPOOL-BTC,LSS-USDT,VET3L-USDT,VET3S-USDT,LTC3L-USDT,LTC3S-USDT,ABBC-USDT,ABBC-BTC,KOK-USDT,ROSN-USDT,DORA-USDT,DORA-BTC,ZCX-USDT,ZCX-BTC,NORD-USDT,GMEE-USDT,SFUND-USDT,XAVA-USDT,AI-USDT,ALPACA-USDT,IOI-USDT,NFT-USDT,NFT-TRX,MNST-USDT,MEM-USDT,AGIX-USDT,AGIX-BTC,AGIX-ETH,CQT-USDT,AIOZ-USDT,MARSH-USDT,HAPI-USDT,MODEFI-USDT,MODEFI-BTC,YFDAI-USDT,YFDAI-BTC,GENS-USDT,FORM-USDT,ARRR-USDT,ARRR-BTC,TOKO-KCS,EXRD-USDT,NGM-USDT,LPT-USDT,STMX-USDT,ASD-USDT,BOND-USDT,HAI-BTC,SOUL-USDT,2CRZ-USDT,NEAR-USDT,NEAR-BTC,DFYN-USDT,OOE-USDT,CFG-USDT,CFG-BTC,AXS-USDT,CLV-USDT,ROUTE-USDT,KAR-USDT,EFX-USDT,XDC-BTC,SHFT-USDT,PMON-USDT,DPET-USDT,ERG-USDT,ERG-BTC,SOL-USDT,SLP-USDT,LITH-USDT,LITH-ETH,XCH-USDT,HAKA-USDT,LAYER-BTC,MTL-USDT,MTL-BTC,IOTX-USDT,GALA-USDT,REQ-USDT,TXA-USDT,TXA-USDC,CIRUS-USDT,QI-USDT,QI-BTC,ODDZ-USDT,PNT-USDT,PNT-BTC,XPR-USDT,XPR-BTC,TRIBE-USDT,SHFT-BTC,MOVR-USDT,MOVR-ETH,WOO-USDT,WILD-USDT,QRDO-USDT,QRDO-ETH,SDN-USDT,SDN-ETH,MAKI-USDT,MAKI-BTC,REP-USDT,REP-BTC,REP-ETH,BNT-USDT,BNT-BTC,BNT-ETH,OXT-USDT,OXT-BTC,OXT-ETH,BAL-USDT,BAL-BTC,BAL-ETH,STORJ-USDT,STORJ-BTC,STORJ-ETH,YGG-USDT,NDAU-USDT,SDAO-USDT,SDAO-ETH,XRP3L-USDT,XRP3S-USDT,SKL-USDT,SKL-BTC,NMR-USDT,NMR-BTC,IXS-USDT,TRB-USDT,TRB-BTC,DYDX-USDT,XYO-USDT,GTC-USDT,GTC-BTC,EQX-USDT,EQX-BTC,RLC-USDT,RLC-BTC,XPRT-USDT,EGLD-USDT,EGLD-BTC,HBAR-USDT,HBAR-BTC,DOGE3L-USDT,DOGE3S-USDT,FLOW-USDT,FLOW-BTC,NKN-USDT,NKN-BTC,PBX-USDT,SOL3L-USDT,SOL3S-USDT,MLN-USDT,MLN-BTC,XNL-USDT,SOLVE-USDT,WNCG-USDT,WNCG-BTC,DMTR-USDT,LINK3L-USDT,LINK3S-USDT,DOT3L-USDT,DOT3S-USDT,CTSI-USDT,CTSI-BTC,ALICE-USDT,ALICE-BTC,ALICE-ETH,OPUL-USDT,ILV-USDT,BAND-USDT,BAND-BTC,FTT-USDT,FTT-BTC,DVPN-USDT,SKU-USDT,SKU-BTC,EDG-USDT,SLIM-USDT,TLM-USDT,TLM-BTC,TLM-ETH,DEXE-USDT,DEXE-BTC,DEXE-ETH,MATTER-USDT,CUDOS-BTC,RUNE-USDT,RUNE-BTC,RMRK-USDT,BMON-USDT,C98-USDT,BLOK-USDT,SOLR-USDT,ATOM3L-USDT,ATOM3S-USDT,UNI3L-USDT,UNI3S-USDT,WSIENNA-USDT,PUSH-USDT,PUSH-BTC,FORM-ETH,NTVRK-USDT,NTVRK-USDC,AXS3L-USDT,AXS3S-USDT,FTM3L-USDT,FTM3S-USDT,FLAME-USDT,AGLD-USDT,NAKA-USDT,YLD-USDT,TONE-USDT,REEF-USDT,REEF-BTC,TIDAL-USDT,TVK-USDT,TVK-BTC,INJ-USDT,INJ-BTC,BNB3L-USDT,BNB3S-USDT,MATIC3L-USDT,MATIC3S-USDT,NFTB-USDT,VEGA-USDT,VEGA-ETH,ALPHA-USDT,ALPHA-BTC,BADGER-USDT,BADGER-BTC,UNO-BTC,ZKT-USDT,AR-USDT,AR-BTC,XVS-USDT,XVS-BTC,JASMY-USDT,PERP-USDT,PERP-BTC,GHST-USDT,GHST-BTC,SCLP-USDT,SCLP-BTC,SUPER-USDT,SUPER-BTC,CPOOL-USDT,HERO-USDT,BASIC-USDT,XED-USDT,XED-BTC,AURY-USDT,SWASH-USDT,LTO-USDT,LTO-BTC,BUX-USDT,MTRG-USDT,DREAMS-USDT,SHIB-DOGE,QUICK-USDT,QUICK-BTC,TRU-USDT,TRU-BTC,WRX-USDT,WRX-BTC,TKO-USDT,TKO-BTC,SUSHI3L-USDT,SUSHI3S-USDT,NEAR3L-USDT,NEAR3S-USDT,DATA-USDT,DATA-BTC,NORD-BTC,ISP-USDT,CERE-USDT,SHILL-USDT,HEGIC-USDT,HEGIC-BTC,ERN-USDT,ERN-BTC,FTG-USDT,PAXG-USDT,PAXG-BTC,AUDIO-USDT,AUDIO-BTC,ENS-USDT,AAVE3L-USDT,AAVE3S-USDT,SAND3L-USDT,SAND3S-USDT,XTM-USDT,MNW-USDT,FXS-USDT,FXS-BTC,ATA-USDT,ATA-BTC,VXV-USDT,LRC-BTC,LRC-ETH,DPR-USDT,CWAR-USDT,CWAR-BTC,FLUX-BTC,EDG-BTC,PBR-USDT,WNXM-USDT,WNXM-BTC,ANT-USDT,ANT-BTC,COV-USDT,SWP-USDT,TWT-USDT,TWT-BTC,OM-USDT,OM-BTC,ADX-USDT,AVAX3L-USDT,AVAX3S-USDT,MANA3L-USDT,MANA3S-USDT,GLM-USDT,GLM-BTC,BAKE-USDT,BAKE-BTC,BAKE-ETH,NUM-USDT,VLX-USDT,VLX-BTC,TRADE-USDT,TRADE-BTC,1EARTH-USDT,MONI-USDT,LIKE-USDT,MFT-USDT,MFT-BTC,LIT-USDT,LIT-BTC,KAVA-USDT,SFP-USDT,SFP-BTC,BURGER-USDT,BURGER-BTC,ILA-USDT,CREAM-USDT,CREAM-BTC,RSR-USDT,RSR-BTC,BUY-BTC,IMX-USDT,GODS-USDT,KMA-USDT,SRM-USDT,SRM-BTC,POLC-USDT,XTAG-USDT,MNET-USDT,NGC-USDT,HARD-USDT,GALAX3L-USDT,GALAX3S-USDT,UNIC-USDT,POND-USDT,POND-BTC,VR-USDT,EPIK-USDT,NGL-USDT,NGL-BTC,KDON-USDT,PEL-USDT,CIRUS-ETH,LINA-USDT,LINA-BTC,KLAY-USDT,KLAY-BTC,CREDI-USDT,TRVL-USDT,LACE-USDT,LACE-ETH,ARKER-USDT,BONDLY-USDT,BONDLY-ETH,XEC-USDT,HEART-USDT,HEART-BTC,UNB-USDT,GAFI-USDT,KOL-USDT,KOL-ETH,H3RO3S-USDT,FALCONS-USDT,UFO-USDT,CHMB-USDT,GEEQ-USDT,ORC-USDT,RACEFI-USDT,PEOPLE-USDT,ADS-USDT,ADS-BTC,OCEAN-USDT,SOS-USDT,WHALE-USDT,TIME-USDT,CWEB-USDT,IOTA-USDT,IOTA-BTC,OOKI-USDT,OOKI-BTC,HNT-USDT,HNT-BTC,GGG-USDT,POWR-USDT,REVU-USDT,CLH-USDT,PLGR-USDT,GLMR-USDT,GLMR-BTC,LOVE-USDT,CTC-USDT,CTC-BTC,GARI-USDT,FRR-USDT,ASTR-USDT,ASTR-BTC,ERTHA-USDT,FCON-USDT,ACA-USDT,ACA-BTC,MTS-USDT,ROAR-USDT,HBB-USDT,SURV-USDT,CVX-USDT,AMP-USDT,ACT-USDT,MJT-USDT,MJT-KCS,SHX-USDT,SHX-BTC,STARLY-USDT,ONSTON-USDT,RANKER-USDT,WMT-USDT,XNO-USDT,XNO-BTC,MARS4-USDT,TFUEL-USDT,TFUEL-BTC,METIS-USDT,LAVAX-USDT,WAL-USDT,BULL-USDT,SON-USDT,MELOS-USDT,APE-USDT,GMT-USDT,BICO-USDT,STG-USDT,LMR-USDT,LMR-BTC,LOKA-USDT,URUS-USDT,JAM-USDT,JAM-ETH,BNC-USDT,LBP-USDT,CFX-USDT,LOOKS-USDT,XCN-USDT,XCN-BTC,KP3R-USDT,TITAN-USDT,INDI-USDT,UPO-USDT,SPELL-USDT,SLCL-USDT,CEEK-USDT,VEMP-USDT,BETA-USDT,NHCT-USDT,ARNM-USDT,FRA-USDT,VISION-USDT,COCOS-USDT,ALPINE-USDT,BNX-USDT,ZBC-USDT,WOOP-USDT,T-USDT,NYM-USDT,VOXEL-USDT,VOXEL-ETH,PSTAKE-USDT,SPA-USDT,SPA-ETH,SYNR-USDT,DAR-USDT,DAR-BTC,MV-USDT,XDEFI-USDT,RACA-USDT,XWG-USDT,HAWK-USDT,TRVL-BTC,SWFTC-USDT,IDEX-USDT,BRWL-USDT,PLATO-USDT,TAUM-USDT,CELR-USDT,AURORA-USDT,POSI-USDT,COOHA-USDT,KNC-USDT,EPK-USDT,PLD-USDT,PSL-USDT,PKF-USDT,OVR-USDT,SYS-USDT,SYS-BTC,BRISE-USDT,DG-USDT,EPX-USDT,GST-USDT,PLY-USDT,GAL-USDT,BSW-USDT,FITFI-USDT,FSN-USDT,H2O-USDT,GMM-USDT,AKT-USDT,SIN-USDT,AUSD-USDT,BOBA-USDT,KARA-USDT,BFC-USDT,BIFI-USDT,DFA-USDT,KYL-USDT,FCD-USDT,MBL-USDT,CELT-USDT,DUSK-USDT,USDD-USDT,USDD-USDC,FITFI-USDC,MBOX-USDT,MBOX-BTC,APE-USDC,AVAX-USDC,SHIB-USDC,XCN-USDC,TRX-USDC,NEAR-USDC,MATIC-USDC,FTM-USDC,ZIL-USDC,SOL-USDC,MLS-USDT,AFK-USDT,AFK-USDC,ACH-USDT,SCRT-USDT,SCRT-BTC,APE3L-USDT,APE3S-USDT,STORE-USDT,STORE-ETH,GMT3L-USDT,GMT3S-USDT,CCD-USDT,DOSE-USDC,LUNC-USDT,LUNC-USDC,USTC-USDT,USTC-USDC,GMT-USDC,VRA-USDC,DOT-USDC,RUNE-USDC,ATOM-USDC,BNB-USDC,JASMY-USDC,KCS-USDC,KDA-USDC,ALGO-USDC,LUNA-USDC,OP-USDT,OP-USDC,JASMY3L-USDT,JASMY3S-USDT,EVER-USDT,MOOV-USDT,IHC-USDT,ICX-USDT,ICX-ETH,BTC-BRL,ETH-BRL,USDT-BRL,WELL-USDT,FORT-USDT,USDP-USDT,USDD-TRX,CSPR-USDT,CSPR-ETH,WEMIX-USDT,REV3L-USDT,OLE-USDT,LDO-USDT,LDO-USDC,CULT-USDT,SWFTC-USDC,FIDA-USDT,BUSD-USDT,RBP-USDT,SRBP-USDT,HIBAYC-USDT,BUSD-USDC,OGV-USDT,WOMBAT-USDT,HIPUNKS-USDT,FT-USDT,ETC-USDC,HIENS4-USDT,EGAME-USDT,EGAME-BTC,STEPWATCH-USDT,HISAND33-USDT,DC-USDT,NEER-USDT,RVN-USDT,HIENS3-USDT,MC-USDT,PEEL-USDT,PEEL-BTC,SDL-USDT,SDL-BTC,SWEAT-USDT,HIODBS-USDT,CMP-USDT,PIX-USDT,MPLX-USDT,HIDOODLES-USDT,ETHW-USDT,QUARTZ-USDT,ACQ-USDT,ACQ-USDC,AOG-USDT,HIMAYC-USDT,PRMX-USDT,RED-USDT,PUMLX-USDT,XETA-USDT,GEM-USDT,DERC-USDT,P00LS-USDT,P00LS-USDC,KICKS-USDT,TRIBL-USDT,GMX-USDT,HIOD-USDT,POKT-USDT,EFI-USDT,APT-USDT,BBC-USDT,EUL-USDT,TON-USDT,PIAS-USDT,HIMEEBITS-USDT,HISQUIGGLE-USDT,XCV-USDT,HFT-USDT,HFT-USDC,ECOX-USDT,AMB-USDT,AZERO-USDT,HIFIDENZA-USDT,BEAT-USDT", "requestFormat": { "uppercase": true, "delimiter": "-" @@ -2009,8 +2009,8 @@ }, "margin": { "assetEnabled": true, - "enabled": "BTC-USDT,ETH-USDT,LTC-USDT,OXEN-BTC,OXEN-ETH,NRG-BTC,AVA-USDT,FET-BTC,FET-ETH,ANKR-BTC,MTV-BTC", - "available": "BTC-USDT,MHC-ETH,MHC-BTC,OXEN-BTC,OXEN-ETH,NRG-BTC,AVA-USDT,FET-BTC,FET-ETH,ANKR-BTC,MHC-USDT,XMR-BTC,XMR-ETH,RIF-BTC,MTV-BTC,MTV-ETH,CRO-BTC,MTV-USDT,KMD-BTC,KMD-USDT,RFOX-USDT,TEL-USDT,TT-USDT,AERGO-USDT,XMR-USDT,TRX-KCS,ATOM-BTC,ATOM-ETH,ATOM-USDT,ATOM-KCS,ETN-USDT,FTM-USDT,TOMO-USDT,VSYS-USDT,OCEAN-BTC,OCEAN-ETH,CHR-BTC,CHR-USDT,FX-BTC,FX-ETH,NIM-BTC,NIM-ETH,COTI-BTC,COTI-USDT,NRG-ETH,BNB-BTC,BNB-USDT,JAR-BTC,JAR-USDT,ALGO-BTC,ALGO-ETH,ALGO-USDT,XEM-BTC,XEM-USDT,CIX100-USDT,XTZ-BTC,XTZ-USDT,ZEC-BTC,ZEC-USDT,ADA-BTC,ADA-USDT,REV-USDT,WXT-BTC,WXT-USDT,FORESTPLUS-BTC,FORESTPLUS-USDT,BOLT-BTC,BOLT-USDT,ARPA-USDT,CHZ-BTC,CHZ-USDT,DAPPT-BTC,DAPPT-USDT,NOIA-BTC,NOIA-USDT,WIN-BTC,WIN-USDT,DERO-BTC,DERO-USDT,BTT-USDT,EOSC-USDT,ENQ-BTC,ENQ-USDT,ONE-BTC,ONE-USDT,TOKO-BTC,TOKO-USDT,VID-BTC,VID-USDT,LUNA-USDT,SXP-BTC,SXP-USDT,AKRO-BTC,AKRO-USDT,ROOBEE-BTC,WIN-TRX,MAP-BTC,MAP-USDT,AMPL-BTC,AMPL-USDT,DAG-USDT,POL-USDT,ARX-USDT,NWC-BTC,NWC-USDT,BEPRO-BTC,BEPRO-USDT,VRA-BTC,VRA-USDT,KSM-BTC,KSM-USDT,DASH-USDT,SUTER-USDT,ACOIN-USDT,SUTER-BTC,SENSO-USDT,PRE-BTC,XDB-USDT,SYLO-USDT,WOM-USDT,SENSO-BTC,DGB-USDT,LYXE-USDT,LYXE-ETH,XDB-BTC,STX-BTC,STX-USDT,XSR-USDT,COMP-USDT,CRO-USDT,KAI-USDT,KAI-BTC,WEST-BTC,WEST-USDT,EWT-BTC,WAVES-USDT,WAVES-BTC,ORN-USDT,AMPL-ETH,BNS-USDT,MKR-USDT,SUKU-BTC,MLK-BTC,MLK-USDT,JST-USDT,KAI-ETH,SUKU-USDT,DIA-USDT,DIA-BTC,LINK-BTC,LINK-USDT,DOT-USDT,DOT-BTC,SHA-BTC,SHA-USDT,EWT-USDT,USDJ-USDT,EFX-BTC,CKB-BTC,CKB-USDT,UMA-USDT,ALEPH-USDT,VELO-USDT,SUN-USDT,BUY-USDT,YFI-USDT,OXEN-USDT,UNI-USDT,UOS-USDT,UOS-BTC,NIM-USDT,DEGO-USDT,DEGO-ETH,UDOO-ETH,RFUEL-USDT,FIL-USDT,UBX-ETH,REAP-USDT,AAVE-USDT,AAVE-BTC,TONE-BTC,TONE-ETH,ELF-ETH,AERGO-BTC,IOST-ETH,KCS-USDT,SNX-ETH,TOMO-ETH,KCS-ETH,DRGN-BTC,WAN-ETH,NULS-ETH,AXPR-ETH,POWR-BTC,QTUM-BTC,MANA-BTC,TEL-BTC,XYO-ETH,AXPR-BTC,ETN-BTC,COV-ETH,VET-BTC,KCS-BTC,CAPP-ETH,ONT-BTC,DRGN-ETH,DAG-ETH,TOMO-BTC,WAN-BTC,KNC-ETH,CRPT-ETH,LTC-USDT,BAX-ETH,BSV-USDT,DENT-ETH,AION-ETH,LYM-ETH,TRAC-ETH,ENJ-BTC,WAXP-BTC,DGB-BTC,ELA-BTC,ZIL-BTC,BSV-BTC,XLM-USDT,IOTX-ETH,SOUL-BTC,DOCK-BTC,AMB-ETH,TRX-BTC,XRP-TUSD,NULS-BTC,ETH-DAI,LSK-BTC,GMB-ETH,GMB-BTC,NEO-ETH,OMG-ETH,BTC-TUSD,KAT-USDT,KNC-BTC,ELF-BTC,MANA-ETH,ETC-USDT,ONT-ETH,MKR-BTC,KAT-BTC,XRP-USDC,XYO-BTC,SNT-ETH,ZRX-BTC,LOOM-ETH,AION-BTC,POWR-ETH,OLT-ETH,OLT-BTC,SNT-BTC,TRAC-BTC,XLM-ETH,ETH-USDT,BSV-ETH,TRX-ETH,ETN-ETH,AOA-USDT,BCD-BTC,DENT-BTC,DOCK-ETH,KEY-BTC,EOS-KCS,XLM-BTC,ADB-ETH,TIME-ETH,CVC-BTC,LSK-ETH,QKC-BTC,AMB-BTC,USDT-TUSD,ETC-ETH,XRP-BTC,NEO-KCS,SNX-USDT,CRPT-BTC,IOTX-BTC,LTC-ETH,XRP-KCS,ADB-BTC,LTC-KCS,TEL-ETH,DCR-ETH,LYM-USDT,USDT-USDC,ETH-USDC,DAG-BTC,AVA-BTC,BTC-USDT,WAXP-ETH,XRP-USDT,KEY-ETH,VET-ETH,FTM-BTC,USDT-DAI,QKC-ETH,ETH-BTC,MAN-BTC,CPC-ETH,TRX-USDT,BTC-DAI,ONT-USDT,DASH-ETH,BAX-BTC,AVA-ETH,LOOM-BTC,MVP-BTC,MKR-ETH,COV-BTC,CPC-BTC,REQ-ETH,EOS-BTC,LTC-BTC,XRP-ETH,CAPP-BTC,FTM-ETH,BCD-ETH,ZRX-ETH,DGB-ETH,VET-USDT,REQ-BTC,UTK-BTC,PLAY-BTC,UTK-ETH,SNX-BTC,MVP-ETH,NEO-BTC,SOUL-ETH,NEO-USDT,ELA-ETH,OMG-BTC,TIME-BTC,AOA-BTC,ETC-BTC,DCR-BTC,BTC-USDC,ENJ-ETH,IOST-BTC,DASH-BTC,EOS-USDT,EOS-ETH,ZIL-ETH,ETH-TUSD,GAS-BTC,LYM-BTC,BCH-BTC,VSYS-BTC,BCH-USDT,MKR-DAI,SOLVE-BTC,GRIN-BTC,GRIN-USDT,UQC-BTC,UQC-ETH,OPCT-BTC,OPCT-ETH,PRE-USDT,SHR-BTC,SHR-USDT,UBXT-USDT,ROSE-USDT,USDC-USDT,CTI-USDT,CTI-ETH,ETH2-ETH,BUX-BTC,XHV-USDT,PLU-USDT,GRT-USDT,CAS-BTC,CAS-USDT,MSWAP-BTC,MSWAP-USDT,GOM2-BTC,GOM2-USDT,REVV-BTC,REVV-USDT,LON-USDT,1INCH-USDT,LOC-USDT,API3-USDT,UNFI-USDT,HTR-USDT,FRONT-USDT,FRONT-BTC,WBTC-BTC,WBTC-ETH,MIR-USDT,LTC-USDC,BCH-USDC,HYDRA-USDT,DFI-USDT,DFI-BTC,CRV-USDT,SUSHI-USDT,FRM-USDT,EOS-USDC,BSV-USDC,ZEN-USDT,CUDOS-USDT,ADA-USDC,REN-USDT,LRC-USDT,LINK-USDC,KLV-USDT,KLV-BTC,BOA-USDT,THETA-USDT,QNT-USDT,BAT-USDT,DOGE-USDT,DOGE-USDC,DAO-USDT,STRONG-USDT,TRIAS-USDT,TRIAS-BTC,DOGE-BTC,MITX-BTC,MITX-USDT,CAKE-USDT,ORAI-USDT,ZEE-USDT,LTX-USDT,LTX-BTC,MASK-USDT,KLV-TRX,IDEA-USDT,PHA-USDT,PHA-ETH,BCH-KCS,SRK-USDT,SRK-BTC,ADA-KCS,HTR-BTC,BSV-KCS,DOT-KCS,LINK-KCS,MIR-KCS,BNB-KCS,XLM-KCS,VET-KCS,SWINGBY-USDT,SWINGBY-BTC,XHV-BTC,DASH-KCS,UNI-KCS,AAVE-KCS,DOGE-KCS,ZEC-KCS,XTZ-KCS,GRT-KCS,ALGO-KCS,EWT-KCS,GAS-USDT,AVAX-USDT,AVAX-BTC,KRL-BTC,KRL-USDT,POLK-USDT,POLK-BTC,ENJ-USDT,MANA-USDT,RNDR-USDT,RNDR-BTC,RLY-USDT,ANC-USDT,SKEY-USDT,LAYER-USDT,TARA-USDT,TARA-ETH,IOST-USDT,DYP-USDT,DYP-ETH,XYM-USDT,XYM-BTC,PCX-USDT,PCX-BTC,ORBS-USDT,ORBS-BTC,BTC3L-USDT,BTC3S-USDT,ETH3L-USDT,ETH3S-USDT,ANKR-USDT,DSLA-USDT,DSLA-BTC,SAND-USDT,VAI-USDT,XCUR-USDT,XCUR-BTC,FLUX-USDT,OMG-USDT,ZIL-USDT,DODO-USDT,MAN-USDT,BAX-USDT,BOSON-USDT,BOSON-ETH,PUNDIX-USDT,PUNDIX-BTC,WAXP-USDT,HT-USDT,PDEX-USDT,LABS-USDT,LABS-ETH,GMB-USDT,PHNX-USDT,PHNX-BTC,HAI-USDT,EQZ-USDT,FORTH-USDT,HORD-USDT,CGG-USDT,UBX-USDT,GHX-USDT,TCP-USDT,STND-USDT,STND-ETH,TOWER-USDT,TOWER-BTC,ACE-USDT,LOCG-USDT,CARD-USDT,FLY-USDT,CWS-USDT,XDC-USDT,XDC-ETH,STRK-BTC,STRK-ETH,SHIB-USDT,POLX-USDT,KDA-USDT,KDA-BTC,ICP-USDT,ICP-BTC,STC-USDT,STC-BTC,GOVI-USDT,GOVI-BTC,FKX-USDT,CELO-USDT,CELO-BTC,CUSD-USDT,CUSD-BTC,FCL-USDT,MATIC-USDT,MATIC-BTC,ELA-USDT,CRPT-USDT,OPCT-USDT,OGN-USDT,OGN-BTC,OUSD-USDT,OUSD-BTC,TLOS-USDT,TLOS-BTC,YOP-USDT,YOP-ETH,GLQ-USDT,GLQ-BTC,MXC-USDT,ERSDL-USDT,HOTCROSS-USDT,ADA3L-USDT,ADA3S-USDT,HYVE-USDT,HYVE-BTC,DAPPX-USDT,KONO-USDT,PRQ-USDT,MAHA-USDT,MAHA-BTC,FEAR-USDT,PYR-USDT,PYR-BTC,PROM-USDT,PROM-BTC,GLCH-USDT,UNO-USDT,ALBT-USDT,ALBT-ETH,XCAD-USDT,EOS3L-USDT,EOS3S-USDT,BCH3L-USDT,BCH3S-USDT,ELON-USDT,APL-USDT,FCL-ETH,VEED-USDT,VEED-BTC,DIVI-USDT,PDEX-BTC,JUP-USDT,JUP-ETH,POLS-USDT,POLS-BTC,LPOOL-USDT,LPOOL-BTC,LSS-USDT,VET3L-USDT,VET3S-USDT,LTC3L-USDT,LTC3S-USDT,ABBC-USDT,ABBC-BTC,KOK-USDT,ROSN-USDT,DORA-USDT,DORA-BTC,ZCX-USDT,ZCX-BTC,NORD-USDT,GMEE-USDT,SFUND-USDT,XAVA-USDT,AI-USDT,ALPACA-USDT,IOI-USDT,NFT-USDT,NFT-TRX,MNST-USDT,MEM-USDT,AGIX-USDT,AGIX-BTC,AGIX-ETH,CQT-USDT,AIOZ-USDT,MARSH-USDT,HAPI-USDT,MODEFI-USDT,MODEFI-BTC,YFDAI-USDT,YFDAI-BTC,GENS-USDT,FORM-USDT,ARRR-USDT,ARRR-BTC,TOKO-KCS,EXRD-USDT,NGM-USDT,LPT-USDT,STMX-USDT,ASD-USDT,BOND-USDT,HAI-BTC,SOUL-USDT,2CRZ-USDT,NEAR-USDT,NEAR-BTC,DFYN-USDT,OOE-USDT,CFG-USDT,CFG-BTC,AXS-USDT,CLV-USDT,ROUTE-USDT,KAR-USDT,EFX-USDT,XDC-BTC,SHFT-USDT,PMON-USDT,DPET-USDT,ERG-USDT,ERG-BTC,SOL-USDT,SLP-USDT,LITH-USDT,LITH-ETH,XCH-USDT,HAKA-USDT,LAYER-BTC,MTL-USDT,MTL-BTC,IOTX-USDT,GALA-USDT,REQ-USDT,TXA-USDT,TXA-USDC,CIRUS-USDT,QI-USDT,QI-BTC,ODDZ-USDT,PNT-USDT,PNT-BTC,XPR-USDT,XPR-BTC,TRIBE-USDT,SHFT-BTC,MOVR-USDT,MOVR-ETH,WOO-USDT,WILD-USDT,QRDO-USDT,QRDO-ETH,SDN-USDT,SDN-ETH,MAKI-USDT,MAKI-BTC,REP-USDT,REP-BTC,REP-ETH,BNT-USDT,BNT-BTC,BNT-ETH,OXT-USDT,OXT-BTC,OXT-ETH,BAL-USDT,BAL-BTC,BAL-ETH,STORJ-USDT,STORJ-BTC,STORJ-ETH,YGG-USDT,NDAU-USDT,SDAO-USDT,SDAO-ETH,XRP3L-USDT,XRP3S-USDT,SKL-USDT,SKL-BTC,NMR-USDT,NMR-BTC,IXS-USDT,TRB-USDT,TRB-BTC,DYDX-USDT,XYO-USDT,GTC-USDT,GTC-BTC,EQX-USDT,EQX-BTC,RLC-USDT,RLC-BTC,XPRT-USDT,EGLD-USDT,EGLD-BTC,HBAR-USDT,HBAR-BTC,DOGE3L-USDT,DOGE3S-USDT,FLOW-USDT,FLOW-BTC,NKN-USDT,NKN-BTC,PBX-USDT,SOL3L-USDT,SOL3S-USDT,MLN-USDT,MLN-BTC,XNL-USDT,SOLVE-USDT,WNCG-USDT,WNCG-BTC,DMTR-USDT,LINK3L-USDT,LINK3S-USDT,DOT3L-USDT,DOT3S-USDT,CTSI-USDT,CTSI-BTC,ALICE-USDT,ALICE-BTC,ALICE-ETH,OPUL-USDT,ILV-USDT,BAND-USDT,BAND-BTC,FTT-USDT,FTT-BTC,DVPN-USDT,SKU-USDT,SKU-BTC,EDG-USDT,SLIM-USDT,TLM-USDT,TLM-BTC,TLM-ETH,DEXE-USDT,DEXE-BTC,DEXE-ETH,MATTER-USDT,CUDOS-BTC,RUNE-USDT,RUNE-BTC,RMRK-USDT,BMON-USDT,C98-USDT,BLOK-USDT,SOLR-USDT,ATOM3L-USDT,ATOM3S-USDT,UNI3L-USDT,UNI3S-USDT,WSIENNA-USDT,PUSH-USDT,PUSH-BTC,FORM-ETH,NTVRK-USDT,NTVRK-USDC,AXS3L-USDT,AXS3S-USDT,FTM3L-USDT,FTM3S-USDT,FLAME-USDT,AGLD-USDT,NAKA-USDT,YLD-USDT,TONE-USDT,REEF-USDT,REEF-BTC,TIDAL-USDT,TVK-USDT,TVK-BTC,INJ-USDT,INJ-BTC,BNB3L-USDT,BNB3S-USDT,MATIC3L-USDT,MATIC3S-USDT,NFTB-USDT,VEGA-USDT,VEGA-ETH,ALPHA-USDT,ALPHA-BTC,BADGER-USDT,BADGER-BTC,UNO-BTC,ZKT-USDT,AR-USDT,AR-BTC,XVS-USDT,XVS-BTC,JASMY-USDT,PERP-USDT,PERP-BTC,GHST-USDT,GHST-BTC,SCLP-USDT,SCLP-BTC,SUPER-USDT,SUPER-BTC,CPOOL-USDT,HERO-USDT,BASIC-USDT,XED-USDT,XED-BTC,AURY-USDT,SWASH-USDT,LTO-USDT,LTO-BTC,BUX-USDT,MTRG-USDT,DREAMS-USDT,SHIB-DOGE,QUICK-USDT,QUICK-BTC,TRU-USDT,TRU-BTC,WRX-USDT,WRX-BTC,TKO-USDT,TKO-BTC,SUSHI3L-USDT,SUSHI3S-USDT,NEAR3L-USDT,NEAR3S-USDT,DATA-USDT,DATA-BTC,NORD-BTC,ISP-USDT,CERE-USDT,SHILL-USDT,HEGIC-USDT,HEGIC-BTC,ERN-USDT,ERN-BTC,FTG-USDT,PAXG-USDT,PAXG-BTC,AUDIO-USDT,AUDIO-BTC,ENS-USDT,AAVE3L-USDT,AAVE3S-USDT,SAND3L-USDT,SAND3S-USDT,XTM-USDT,MNW-USDT,FXS-USDT,FXS-BTC,ATA-USDT,ATA-BTC,VXV-USDT,LRC-BTC,LRC-ETH,DPR-USDT,CWAR-USDT,CWAR-BTC,FLUX-BTC,EDG-BTC,PBR-USDT,WNXM-USDT,WNXM-BTC,ANT-USDT,ANT-BTC,COV-USDT,SWP-USDT,TWT-USDT,TWT-BTC,OM-USDT,OM-BTC,ADX-USDT,AVAX3L-USDT,AVAX3S-USDT,MANA3L-USDT,MANA3S-USDT,GLM-USDT,GLM-BTC,BAKE-USDT,BAKE-BTC,BAKE-ETH,NUM-USDT,VLX-USDT,VLX-BTC,TRADE-USDT,TRADE-BTC,1EARTH-USDT,MONI-USDT,LIKE-USDT,MFT-USDT,MFT-BTC,LIT-USDT,LIT-BTC,KAVA-USDT,SFP-USDT,SFP-BTC,BURGER-USDT,BURGER-BTC,ILA-USDT,CREAM-USDT,CREAM-BTC,RSR-USDT,RSR-BTC,BUY-BTC,IMX-USDT,GODS-USDT,KMA-USDT,SRM-USDT,SRM-BTC,POLC-USDT,XTAG-USDT,MNET-USDT,NGC-USDT,HARD-USDT,GALAX3L-USDT,GALAX3S-USDT,UNIC-USDT,POND-USDT,POND-BTC,VR-USDT,EPIK-USDT,NGL-USDT,NGL-BTC,KDON-USDT,PEL-USDT,CIRUS-ETH,LINA-USDT,LINA-BTC,KLAY-USDT,KLAY-BTC,CREDI-USDT,TRVL-USDT,LACE-USDT,LACE-ETH,ARKER-USDT,BONDLY-USDT,BONDLY-ETH,XEC-USDT,HEART-USDT,HEART-BTC,UNB-USDT,GAFI-USDT,KOL-USDT,KOL-ETH,H3RO3S-USDT,FALCONS-USDT,UFO-USDT,CHMB-USDT,GEEQ-USDT,ORC-USDT,RACEFI-USDT,PEOPLE-USDT,ADS-USDT,ADS-BTC,OCEAN-USDT,SOS-USDT,WHALE-USDT,TIME-USDT,CWEB-USDT,IOTA-USDT,IOTA-BTC,OOKI-USDT,OOKI-BTC,HNT-USDT,HNT-BTC,GGG-USDT,POWR-USDT,REVU-USDT,CLH-USDT,PLGR-USDT,GLMR-USDT,GLMR-BTC,LOVE-USDT,CTC-USDT,CTC-BTC,GARI-USDT,FRR-USDT,ASTR-USDT,ASTR-BTC,ERTHA-USDT,FCON-USDT,ACA-USDT,ACA-BTC,MTS-USDT,ROAR-USDT,HBB-USDT,SURV-USDT,CVX-USDT,AMP-USDT,ACT-USDT,MJT-USDT,MJT-KCS,SHX-USDT,SHX-BTC,STARLY-USDT,ONSTON-USDT,RANKER-USDT,WMT-USDT,XNO-USDT,XNO-BTC,MARS4-USDT,TFUEL-USDT,TFUEL-BTC,METIS-USDT,LAVAX-USDT,WAL-USDT,BULL-USDT,SON-USDT,MELOS-USDT,APE-USDT,GMT-USDT,BICO-USDT,STG-USDT,LMR-USDT,LMR-BTC,LOKA-USDT,URUS-USDT,JAM-USDT,JAM-ETH,BNC-USDT,LBP-USDT,CFX-USDT,LOOKS-USDT,XCN-USDT,XCN-BTC,KP3R-USDT,TITAN-USDT,INDI-USDT,UPO-USDT,SPELL-USDT,SLCL-USDT,CEEK-USDT,VEMP-USDT,BETA-USDT,NHCT-USDT,ARNM-USDT,FRA-USDT,VISION-USDT,COCOS-USDT,ALPINE-USDT,BNX-USDT,ZBC-USDT,WOOP-USDT,T-USDT,NYM-USDT,VOXEL-USDT,VOXEL-ETH,PSTAKE-USDT,SPA-USDT,SPA-ETH,SYNR-USDT,DAR-USDT,DAR-BTC,MV-USDT,XDEFI-USDT,RACA-USDT,XWG-USDT,HAWK-USDT,TRVL-BTC,SWFTC-USDT,IDEX-USDT,BRWL-USDT,PLATO-USDT,TAUM-USDT,CELR-USDT,AURORA-USDT,POSI-USDT,COOHA-USDT,KNC-USDT,EPK-USDT,PLD-USDT,PSL-USDT,PKF-USDT,OVR-USDT,SYS-USDT,SYS-BTC,BRISE-USDT,DG-USDT,EPX-USDT,GST-USDT,PLY-USDT,GAL-USDT,BSW-USDT,FITFI-USDT,FSN-USDT,H2O-USDT,GMM-USDT,AKT-USDT,SIN-USDT,AUSD-USDT,BOBA-USDT,KARA-USDT,BFC-USDT,BIFI-USDT,DFA-USDT,KYL-USDT,FCD-USDT,MBL-USDT,CELT-USDT,DUSK-USDT,USDD-USDT,USDD-USDC,FITFI-USDC,MBOX-USDT,MBOX-BTC,APE-USDC,AVAX-USDC,SHIB-USDC,XCN-USDC,TRX-USDC,NEAR-USDC,MATIC-USDC,FTM-USDC,ZIL-USDC,SOL-USDC,MLS-USDT,AFK-USDT,AFK-USDC,ACH-USDT,SCRT-USDT,SCRT-BTC,APE3L-USDT,APE3S-USDT,STORE-USDT,STORE-ETH,GMT3L-USDT,GMT3S-USDT,CCD-USDT,DOSE-USDC,LUNC-USDT,LUNC-USDC,USTC-USDT,USTC-USDC,GMT-USDC,VRA-USDC,DOT-USDC,RUNE-USDC,ATOM-USDC,BNB-USDC,JASMY-USDC,KCS-USDC,KDA-USDC,ALGO-USDC,LUNA-USDC,OP-USDT,OP-USDC,JASMY3L-USDT,JASMY3S-USDT,EVER-USDT,MOOV-USDT,IHC-USDT,ICX-USDT,ICX-ETH,BTC-BRL,ETH-BRL,USDT-BRL,WELL-USDT,FORT-USDT,USDP-USDT,USDD-TRX,CSPR-USDT,CSPR-ETH,WEMIX-USDT,REV3L-USDT,OLE-USDT,LDO-USDT,LDO-USDC,CULT-USDT,SWFTC-USDC,FIDA-USDT,BUSD-USDT,RBP-USDT,SRBP-USDT,HIBAYC-USDT,BUSD-USDC,OGV-USDT,WOMBAT-USDT,HIPUNKS-USDT,FT-USDT,ETC-USDC,HIENS4-USDT,EGAME-USDT,EGAME-BTC,STEPWATCH-USDT,HISAND33-USDT,DC-USDT,NEER-USDT,RVN-USDT,HIENS3-USDT,MC-USDT,PEEL-USDT,PEEL-BTC,SDL-USDT,SDL-BTC,SWEAT-USDT,HIODBS-USDT,CMP-USDT,PIX-USDT,MPLX-USDT,HIDOODLES-USDT,ETHW-USDT,QUARTZ-USDT,ACQ-USDT,ACQ-USDC,AOG-USDT,HIMAYC-USDT,PRMX-USDT,RED-USDT,PUMLX-USDT,XETA-USDT,GEM-USDT,DERC-USDT,P00LS-USDT,P00LS-USDC,KICKS-USDT,TRIBL-USDT,GMX-USDT,HIOD-USDT,POKT-USDT,EFI-USDT,APT-USDT,BBC-USDT,EUL-USDT,TON-USDT,PIAS-USDT,HIMEEBITS-USDT,HISQUIGGLE-USDT,XCV-USDT,HFT-USDT,HFT-USDC,ECOX-USDT,AMB-USDT,AZERO-USDT,HIFIDENZA-USDT,BEAT-USDT", + "enabled": "ETH-BTC,XMR-BTC,LTC-USDT,SOL-USDC", + "available": "BTC-USDT,MHC-ETH,MHC-BTC,MHC-USDT,XMR-BTC,XMR-ETH,RIF-BTC,MTV-ETH,CRO-BTC,MTV-USDT,KMD-BTC,KMD-USDT,RFOX-USDT,TEL-USDT,TT-USDT,AERGO-USDT,XMR-USDT,TRX-KCS,ATOM-BTC,ATOM-ETH,ATOM-USDT,ATOM-KCS,ETN-USDT,FTM-USDT,TOMO-USDT,VSYS-USDT,OCEAN-BTC,OCEAN-ETH,CHR-BTC,CHR-USDT,FX-BTC,FX-ETH,NIM-BTC,NIM-ETH,COTI-BTC,COTI-USDT,NRG-ETH,BNB-BTC,BNB-USDT,JAR-BTC,JAR-USDT,ALGO-BTC,ALGO-ETH,ALGO-USDT,XEM-BTC,XEM-USDT,CIX100-USDT,XTZ-BTC,XTZ-USDT,ZEC-BTC,ZEC-USDT,ADA-BTC,ADA-USDT,REV-USDT,WXT-BTC,WXT-USDT,FORESTPLUS-BTC,FORESTPLUS-USDT,BOLT-BTC,BOLT-USDT,ARPA-USDT,CHZ-BTC,CHZ-USDT,DAPPT-BTC,DAPPT-USDT,NOIA-BTC,NOIA-USDT,WIN-BTC,WIN-USDT,DERO-BTC,DERO-USDT,BTT-USDT,EOSC-USDT,ENQ-BTC,ENQ-USDT,ONE-BTC,ONE-USDT,TOKO-BTC,TOKO-USDT,VID-BTC,VID-USDT,LUNA-USDT,SXP-BTC,SXP-USDT,AKRO-BTC,AKRO-USDT,ROOBEE-BTC,WIN-TRX,MAP-BTC,MAP-USDT,AMPL-BTC,AMPL-USDT,DAG-USDT,POL-USDT,ARX-USDT,NWC-BTC,NWC-USDT,BEPRO-BTC,BEPRO-USDT,VRA-BTC,VRA-USDT,KSM-BTC,KSM-USDT,DASH-USDT,SUTER-USDT,ACOIN-USDT,SUTER-BTC,SENSO-USDT,PRE-BTC,XDB-USDT,SYLO-USDT,WOM-USDT,SENSO-BTC,DGB-USDT,LYXE-USDT,LYXE-ETH,XDB-BTC,STX-BTC,STX-USDT,XSR-USDT,COMP-USDT,CRO-USDT,KAI-USDT,KAI-BTC,WEST-BTC,WEST-USDT,EWT-BTC,WAVES-USDT,WAVES-BTC,ORN-USDT,AMPL-ETH,BNS-USDT,MKR-USDT,SUKU-BTC,MLK-BTC,MLK-USDT,JST-USDT,KAI-ETH,SUKU-USDT,DIA-USDT,DIA-BTC,LINK-BTC,LINK-USDT,DOT-USDT,DOT-BTC,SHA-BTC,SHA-USDT,EWT-USDT,USDJ-USDT,EFX-BTC,CKB-BTC,CKB-USDT,UMA-USDT,ALEPH-USDT,VELO-USDT,SUN-USDT,BUY-USDT,YFI-USDT,OXEN-USDT,UNI-USDT,UOS-USDT,UOS-BTC,NIM-USDT,DEGO-USDT,DEGO-ETH,UDOO-ETH,RFUEL-USDT,FIL-USDT,UBX-ETH,REAP-USDT,AAVE-USDT,AAVE-BTC,TONE-BTC,TONE-ETH,ELF-ETH,AERGO-BTC,IOST-ETH,KCS-USDT,SNX-ETH,TOMO-ETH,KCS-ETH,DRGN-BTC,WAN-ETH,NULS-ETH,AXPR-ETH,POWR-BTC,QTUM-BTC,MANA-BTC,TEL-BTC,XYO-ETH,AXPR-BTC,ETN-BTC,COV-ETH,VET-BTC,KCS-BTC,CAPP-ETH,ONT-BTC,DRGN-ETH,DAG-ETH,TOMO-BTC,WAN-BTC,KNC-ETH,CRPT-ETH,LTC-USDT,BAX-ETH,BSV-USDT,DENT-ETH,AION-ETH,LYM-ETH,TRAC-ETH,ENJ-BTC,WAXP-BTC,DGB-BTC,ELA-BTC,ZIL-BTC,BSV-BTC,XLM-USDT,IOTX-ETH,SOUL-BTC,DOCK-BTC,AMB-ETH,TRX-BTC,XRP-TUSD,NULS-BTC,ETH-DAI,LSK-BTC,GMB-ETH,GMB-BTC,NEO-ETH,OMG-ETH,BTC-TUSD,KAT-USDT,KNC-BTC,ELF-BTC,MANA-ETH,ETC-USDT,ONT-ETH,MKR-BTC,KAT-BTC,XRP-USDC,XYO-BTC,SNT-ETH,ZRX-BTC,LOOM-ETH,AION-BTC,POWR-ETH,OLT-ETH,OLT-BTC,SNT-BTC,TRAC-BTC,XLM-ETH,ETH-USDT,BSV-ETH,TRX-ETH,ETN-ETH,AOA-USDT,BCD-BTC,DENT-BTC,DOCK-ETH,KEY-BTC,EOS-KCS,XLM-BTC,ADB-ETH,TIME-ETH,CVC-BTC,LSK-ETH,QKC-BTC,AMB-BTC,USDT-TUSD,ETC-ETH,XRP-BTC,NEO-KCS,SNX-USDT,CRPT-BTC,IOTX-BTC,LTC-ETH,XRP-KCS,ADB-BTC,LTC-KCS,TEL-ETH,DCR-ETH,LYM-USDT,USDT-USDC,ETH-USDC,DAG-BTC,AVA-BTC,BTC-USDT,WAXP-ETH,XRP-USDT,KEY-ETH,VET-ETH,FTM-BTC,USDT-DAI,QKC-ETH,ETH-BTC,MAN-BTC,CPC-ETH,TRX-USDT,BTC-DAI,ONT-USDT,DASH-ETH,BAX-BTC,AVA-ETH,LOOM-BTC,MVP-BTC,MKR-ETH,COV-BTC,CPC-BTC,REQ-ETH,EOS-BTC,LTC-BTC,XRP-ETH,CAPP-BTC,FTM-ETH,BCD-ETH,ZRX-ETH,DGB-ETH,VET-USDT,REQ-BTC,UTK-BTC,PLAY-BTC,UTK-ETH,SNX-BTC,MVP-ETH,NEO-BTC,SOUL-ETH,NEO-USDT,ELA-ETH,OMG-BTC,TIME-BTC,AOA-BTC,ETC-BTC,DCR-BTC,BTC-USDC,ENJ-ETH,IOST-BTC,DASH-BTC,EOS-USDT,EOS-ETH,ZIL-ETH,ETH-TUSD,GAS-BTC,LYM-BTC,BCH-BTC,VSYS-BTC,BCH-USDT,MKR-DAI,SOLVE-BTC,GRIN-BTC,GRIN-USDT,UQC-BTC,UQC-ETH,OPCT-BTC,OPCT-ETH,PRE-USDT,SHR-BTC,SHR-USDT,UBXT-USDT,ROSE-USDT,USDC-USDT,CTI-USDT,CTI-ETH,ETH2-ETH,BUX-BTC,XHV-USDT,PLU-USDT,GRT-USDT,CAS-BTC,CAS-USDT,MSWAP-BTC,MSWAP-USDT,GOM2-BTC,GOM2-USDT,REVV-BTC,REVV-USDT,LON-USDT,1INCH-USDT,LOC-USDT,API3-USDT,UNFI-USDT,HTR-USDT,FRONT-USDT,FRONT-BTC,WBTC-BTC,WBTC-ETH,MIR-USDT,LTC-USDC,BCH-USDC,HYDRA-USDT,DFI-USDT,DFI-BTC,CRV-USDT,SUSHI-USDT,FRM-USDT,EOS-USDC,BSV-USDC,ZEN-USDT,CUDOS-USDT,ADA-USDC,REN-USDT,LRC-USDT,LINK-USDC,KLV-USDT,KLV-BTC,BOA-USDT,THETA-USDT,QNT-USDT,BAT-USDT,DOGE-USDT,DOGE-USDC,DAO-USDT,STRONG-USDT,TRIAS-USDT,TRIAS-BTC,DOGE-BTC,MITX-BTC,MITX-USDT,CAKE-USDT,ORAI-USDT,ZEE-USDT,LTX-USDT,LTX-BTC,MASK-USDT,KLV-TRX,IDEA-USDT,PHA-USDT,PHA-ETH,BCH-KCS,SRK-USDT,SRK-BTC,ADA-KCS,HTR-BTC,BSV-KCS,DOT-KCS,LINK-KCS,MIR-KCS,BNB-KCS,XLM-KCS,VET-KCS,SWINGBY-USDT,SWINGBY-BTC,XHV-BTC,DASH-KCS,UNI-KCS,AAVE-KCS,DOGE-KCS,ZEC-KCS,XTZ-KCS,GRT-KCS,ALGO-KCS,EWT-KCS,GAS-USDT,AVAX-USDT,AVAX-BTC,KRL-BTC,KRL-USDT,POLK-USDT,POLK-BTC,ENJ-USDT,MANA-USDT,RNDR-USDT,RNDR-BTC,RLY-USDT,ANC-USDT,SKEY-USDT,LAYER-USDT,TARA-USDT,TARA-ETH,IOST-USDT,DYP-USDT,DYP-ETH,XYM-USDT,XYM-BTC,PCX-USDT,PCX-BTC,ORBS-USDT,ORBS-BTC,BTC3L-USDT,BTC3S-USDT,ETH3L-USDT,ETH3S-USDT,ANKR-USDT,DSLA-USDT,DSLA-BTC,SAND-USDT,VAI-USDT,XCUR-USDT,XCUR-BTC,FLUX-USDT,OMG-USDT,ZIL-USDT,DODO-USDT,MAN-USDT,BAX-USDT,BOSON-USDT,BOSON-ETH,PUNDIX-USDT,PUNDIX-BTC,WAXP-USDT,HT-USDT,PDEX-USDT,LABS-USDT,LABS-ETH,GMB-USDT,PHNX-USDT,PHNX-BTC,HAI-USDT,EQZ-USDT,FORTH-USDT,HORD-USDT,CGG-USDT,UBX-USDT,GHX-USDT,TCP-USDT,STND-USDT,STND-ETH,TOWER-USDT,TOWER-BTC,ACE-USDT,LOCG-USDT,CARD-USDT,FLY-USDT,CWS-USDT,XDC-USDT,XDC-ETH,STRK-BTC,STRK-ETH,SHIB-USDT,POLX-USDT,KDA-USDT,KDA-BTC,ICP-USDT,ICP-BTC,STC-USDT,STC-BTC,GOVI-USDT,GOVI-BTC,FKX-USDT,CELO-USDT,CELO-BTC,CUSD-USDT,CUSD-BTC,FCL-USDT,MATIC-USDT,MATIC-BTC,ELA-USDT,CRPT-USDT,OPCT-USDT,OGN-USDT,OGN-BTC,OUSD-USDT,OUSD-BTC,TLOS-USDT,TLOS-BTC,YOP-USDT,YOP-ETH,GLQ-USDT,GLQ-BTC,MXC-USDT,ERSDL-USDT,HOTCROSS-USDT,ADA3L-USDT,ADA3S-USDT,HYVE-USDT,HYVE-BTC,DAPPX-USDT,KONO-USDT,PRQ-USDT,MAHA-USDT,MAHA-BTC,FEAR-USDT,PYR-USDT,PYR-BTC,PROM-USDT,PROM-BTC,GLCH-USDT,UNO-USDT,ALBT-USDT,ALBT-ETH,XCAD-USDT,EOS3L-USDT,EOS3S-USDT,BCH3L-USDT,BCH3S-USDT,ELON-USDT,APL-USDT,FCL-ETH,VEED-USDT,VEED-BTC,DIVI-USDT,PDEX-BTC,JUP-USDT,JUP-ETH,POLS-USDT,POLS-BTC,LPOOL-USDT,LPOOL-BTC,LSS-USDT,VET3L-USDT,VET3S-USDT,LTC3L-USDT,LTC3S-USDT,ABBC-USDT,ABBC-BTC,KOK-USDT,ROSN-USDT,DORA-USDT,DORA-BTC,ZCX-USDT,ZCX-BTC,NORD-USDT,GMEE-USDT,SFUND-USDT,XAVA-USDT,AI-USDT,ALPACA-USDT,IOI-USDT,NFT-USDT,NFT-TRX,MNST-USDT,MEM-USDT,AGIX-USDT,AGIX-BTC,AGIX-ETH,CQT-USDT,AIOZ-USDT,MARSH-USDT,HAPI-USDT,MODEFI-USDT,MODEFI-BTC,YFDAI-USDT,YFDAI-BTC,GENS-USDT,FORM-USDT,ARRR-USDT,ARRR-BTC,TOKO-KCS,EXRD-USDT,NGM-USDT,LPT-USDT,STMX-USDT,ASD-USDT,BOND-USDT,HAI-BTC,SOUL-USDT,2CRZ-USDT,NEAR-USDT,NEAR-BTC,DFYN-USDT,OOE-USDT,CFG-USDT,CFG-BTC,AXS-USDT,CLV-USDT,ROUTE-USDT,KAR-USDT,EFX-USDT,XDC-BTC,SHFT-USDT,PMON-USDT,DPET-USDT,ERG-USDT,ERG-BTC,SOL-USDT,SLP-USDT,LITH-USDT,LITH-ETH,XCH-USDT,HAKA-USDT,LAYER-BTC,MTL-USDT,MTL-BTC,IOTX-USDT,GALA-USDT,REQ-USDT,TXA-USDT,TXA-USDC,CIRUS-USDT,QI-USDT,QI-BTC,ODDZ-USDT,PNT-USDT,PNT-BTC,XPR-USDT,XPR-BTC,TRIBE-USDT,SHFT-BTC,MOVR-USDT,MOVR-ETH,WOO-USDT,WILD-USDT,QRDO-USDT,QRDO-ETH,SDN-USDT,SDN-ETH,MAKI-USDT,MAKI-BTC,REP-USDT,REP-BTC,REP-ETH,BNT-USDT,BNT-BTC,BNT-ETH,OXT-USDT,OXT-BTC,OXT-ETH,BAL-USDT,BAL-BTC,BAL-ETH,STORJ-USDT,STORJ-BTC,STORJ-ETH,YGG-USDT,NDAU-USDT,SDAO-USDT,SDAO-ETH,XRP3L-USDT,XRP3S-USDT,SKL-USDT,SKL-BTC,NMR-USDT,NMR-BTC,IXS-USDT,TRB-USDT,TRB-BTC,DYDX-USDT,XYO-USDT,GTC-USDT,GTC-BTC,EQX-USDT,EQX-BTC,RLC-USDT,RLC-BTC,XPRT-USDT,EGLD-USDT,EGLD-BTC,HBAR-USDT,HBAR-BTC,DOGE3L-USDT,DOGE3S-USDT,FLOW-USDT,FLOW-BTC,NKN-USDT,NKN-BTC,PBX-USDT,SOL3L-USDT,SOL3S-USDT,MLN-USDT,MLN-BTC,XNL-USDT,SOLVE-USDT,WNCG-USDT,WNCG-BTC,DMTR-USDT,LINK3L-USDT,LINK3S-USDT,DOT3L-USDT,DOT3S-USDT,CTSI-USDT,CTSI-BTC,ALICE-USDT,ALICE-BTC,ALICE-ETH,OPUL-USDT,ILV-USDT,BAND-USDT,BAND-BTC,FTT-USDT,FTT-BTC,DVPN-USDT,SKU-USDT,SKU-BTC,EDG-USDT,SLIM-USDT,TLM-USDT,TLM-BTC,TLM-ETH,DEXE-USDT,DEXE-BTC,DEXE-ETH,MATTER-USDT,CUDOS-BTC,RUNE-USDT,RUNE-BTC,RMRK-USDT,BMON-USDT,C98-USDT,BLOK-USDT,SOLR-USDT,ATOM3L-USDT,ATOM3S-USDT,UNI3L-USDT,UNI3S-USDT,WSIENNA-USDT,PUSH-USDT,PUSH-BTC,FORM-ETH,NTVRK-USDT,NTVRK-USDC,AXS3L-USDT,AXS3S-USDT,FTM3L-USDT,FTM3S-USDT,FLAME-USDT,AGLD-USDT,NAKA-USDT,YLD-USDT,TONE-USDT,REEF-USDT,REEF-BTC,TIDAL-USDT,TVK-USDT,TVK-BTC,INJ-USDT,INJ-BTC,BNB3L-USDT,BNB3S-USDT,MATIC3L-USDT,MATIC3S-USDT,NFTB-USDT,VEGA-USDT,VEGA-ETH,ALPHA-USDT,ALPHA-BTC,BADGER-USDT,BADGER-BTC,UNO-BTC,ZKT-USDT,AR-USDT,AR-BTC,XVS-USDT,XVS-BTC,JASMY-USDT,PERP-USDT,PERP-BTC,GHST-USDT,GHST-BTC,SCLP-USDT,SCLP-BTC,SUPER-USDT,SUPER-BTC,CPOOL-USDT,HERO-USDT,BASIC-USDT,XED-USDT,XED-BTC,AURY-USDT,SWASH-USDT,LTO-USDT,LTO-BTC,BUX-USDT,MTRG-USDT,DREAMS-USDT,SHIB-DOGE,QUICK-USDT,QUICK-BTC,TRU-USDT,TRU-BTC,WRX-USDT,WRX-BTC,TKO-USDT,TKO-BTC,SUSHI3L-USDT,SUSHI3S-USDT,NEAR3L-USDT,NEAR3S-USDT,DATA-USDT,DATA-BTC,NORD-BTC,ISP-USDT,CERE-USDT,SHILL-USDT,HEGIC-USDT,HEGIC-BTC,ERN-USDT,ERN-BTC,FTG-USDT,PAXG-USDT,PAXG-BTC,AUDIO-USDT,AUDIO-BTC,ENS-USDT,AAVE3L-USDT,AAVE3S-USDT,SAND3L-USDT,SAND3S-USDT,XTM-USDT,MNW-USDT,FXS-USDT,FXS-BTC,ATA-USDT,ATA-BTC,VXV-USDT,LRC-BTC,LRC-ETH,DPR-USDT,CWAR-USDT,CWAR-BTC,FLUX-BTC,EDG-BTC,PBR-USDT,WNXM-USDT,WNXM-BTC,ANT-USDT,ANT-BTC,COV-USDT,SWP-USDT,TWT-USDT,TWT-BTC,OM-USDT,OM-BTC,ADX-USDT,AVAX3L-USDT,AVAX3S-USDT,MANA3L-USDT,MANA3S-USDT,GLM-USDT,GLM-BTC,BAKE-USDT,BAKE-BTC,BAKE-ETH,NUM-USDT,VLX-USDT,VLX-BTC,TRADE-USDT,TRADE-BTC,1EARTH-USDT,MONI-USDT,LIKE-USDT,MFT-USDT,MFT-BTC,LIT-USDT,LIT-BTC,KAVA-USDT,SFP-USDT,SFP-BTC,BURGER-USDT,BURGER-BTC,ILA-USDT,CREAM-USDT,CREAM-BTC,RSR-USDT,RSR-BTC,BUY-BTC,IMX-USDT,GODS-USDT,KMA-USDT,SRM-USDT,SRM-BTC,POLC-USDT,XTAG-USDT,MNET-USDT,NGC-USDT,HARD-USDT,GALAX3L-USDT,GALAX3S-USDT,UNIC-USDT,POND-USDT,POND-BTC,VR-USDT,EPIK-USDT,NGL-USDT,NGL-BTC,KDON-USDT,PEL-USDT,CIRUS-ETH,LINA-USDT,LINA-BTC,KLAY-USDT,KLAY-BTC,CREDI-USDT,TRVL-USDT,LACE-USDT,LACE-ETH,ARKER-USDT,BONDLY-USDT,BONDLY-ETH,XEC-USDT,HEART-USDT,HEART-BTC,UNB-USDT,GAFI-USDT,KOL-USDT,KOL-ETH,H3RO3S-USDT,FALCONS-USDT,UFO-USDT,CHMB-USDT,GEEQ-USDT,ORC-USDT,RACEFI-USDT,PEOPLE-USDT,ADS-USDT,ADS-BTC,OCEAN-USDT,SOS-USDT,WHALE-USDT,TIME-USDT,CWEB-USDT,IOTA-USDT,IOTA-BTC,OOKI-USDT,OOKI-BTC,HNT-USDT,HNT-BTC,GGG-USDT,POWR-USDT,REVU-USDT,CLH-USDT,PLGR-USDT,GLMR-USDT,GLMR-BTC,LOVE-USDT,CTC-USDT,CTC-BTC,GARI-USDT,FRR-USDT,ASTR-USDT,ASTR-BTC,ERTHA-USDT,FCON-USDT,ACA-USDT,ACA-BTC,MTS-USDT,ROAR-USDT,HBB-USDT,SURV-USDT,CVX-USDT,AMP-USDT,ACT-USDT,MJT-USDT,MJT-KCS,SHX-USDT,SHX-BTC,STARLY-USDT,ONSTON-USDT,RANKER-USDT,WMT-USDT,XNO-USDT,XNO-BTC,MARS4-USDT,TFUEL-USDT,TFUEL-BTC,METIS-USDT,LAVAX-USDT,WAL-USDT,BULL-USDT,SON-USDT,MELOS-USDT,APE-USDT,GMT-USDT,BICO-USDT,STG-USDT,LMR-USDT,LMR-BTC,LOKA-USDT,URUS-USDT,JAM-USDT,JAM-ETH,BNC-USDT,LBP-USDT,CFX-USDT,LOOKS-USDT,XCN-USDT,XCN-BTC,KP3R-USDT,TITAN-USDT,INDI-USDT,UPO-USDT,SPELL-USDT,SLCL-USDT,CEEK-USDT,VEMP-USDT,BETA-USDT,NHCT-USDT,ARNM-USDT,FRA-USDT,VISION-USDT,COCOS-USDT,ALPINE-USDT,BNX-USDT,ZBC-USDT,WOOP-USDT,T-USDT,NYM-USDT,VOXEL-USDT,VOXEL-ETH,PSTAKE-USDT,SPA-USDT,SPA-ETH,SYNR-USDT,DAR-USDT,DAR-BTC,MV-USDT,XDEFI-USDT,RACA-USDT,XWG-USDT,HAWK-USDT,TRVL-BTC,SWFTC-USDT,IDEX-USDT,BRWL-USDT,PLATO-USDT,TAUM-USDT,CELR-USDT,AURORA-USDT,POSI-USDT,COOHA-USDT,KNC-USDT,EPK-USDT,PLD-USDT,PSL-USDT,PKF-USDT,OVR-USDT,SYS-USDT,SYS-BTC,BRISE-USDT,DG-USDT,EPX-USDT,GST-USDT,PLY-USDT,GAL-USDT,BSW-USDT,FITFI-USDT,FSN-USDT,H2O-USDT,GMM-USDT,AKT-USDT,SIN-USDT,AUSD-USDT,BOBA-USDT,KARA-USDT,BFC-USDT,BIFI-USDT,DFA-USDT,KYL-USDT,FCD-USDT,MBL-USDT,CELT-USDT,DUSK-USDT,USDD-USDT,USDD-USDC,FITFI-USDC,MBOX-USDT,MBOX-BTC,APE-USDC,AVAX-USDC,SHIB-USDC,XCN-USDC,TRX-USDC,NEAR-USDC,MATIC-USDC,FTM-USDC,ZIL-USDC,SOL-USDC,MLS-USDT,AFK-USDT,AFK-USDC,ACH-USDT,SCRT-USDT,SCRT-BTC,APE3L-USDT,APE3S-USDT,STORE-USDT,STORE-ETH,GMT3L-USDT,GMT3S-USDT,CCD-USDT,DOSE-USDC,LUNC-USDT,LUNC-USDC,USTC-USDT,USTC-USDC,GMT-USDC,VRA-USDC,DOT-USDC,RUNE-USDC,ATOM-USDC,BNB-USDC,JASMY-USDC,KCS-USDC,KDA-USDC,ALGO-USDC,LUNA-USDC,OP-USDT,OP-USDC,JASMY3L-USDT,JASMY3S-USDT,EVER-USDT,MOOV-USDT,IHC-USDT,ICX-USDT,ICX-ETH,BTC-BRL,ETH-BRL,USDT-BRL,WELL-USDT,FORT-USDT,USDP-USDT,USDD-TRX,CSPR-USDT,CSPR-ETH,WEMIX-USDT,REV3L-USDT,OLE-USDT,LDO-USDT,LDO-USDC,CULT-USDT,SWFTC-USDC,FIDA-USDT,BUSD-USDT,RBP-USDT,SRBP-USDT,HIBAYC-USDT,BUSD-USDC,OGV-USDT,WOMBAT-USDT,HIPUNKS-USDT,FT-USDT,ETC-USDC,HIENS4-USDT,EGAME-USDT,EGAME-BTC,STEPWATCH-USDT,HISAND33-USDT,DC-USDT,NEER-USDT,RVN-USDT,HIENS3-USDT,MC-USDT,PEEL-USDT,PEEL-BTC,SDL-USDT,SDL-BTC,SWEAT-USDT,HIODBS-USDT,CMP-USDT,PIX-USDT,MPLX-USDT,HIDOODLES-USDT,ETHW-USDT,QUARTZ-USDT,ACQ-USDT,ACQ-USDC,AOG-USDT,HIMAYC-USDT,PRMX-USDT,RED-USDT,PUMLX-USDT,XETA-USDT,GEM-USDT,DERC-USDT,P00LS-USDT,P00LS-USDC,KICKS-USDT,TRIBL-USDT,GMX-USDT,HIOD-USDT,POKT-USDT,EFI-USDT,APT-USDT,BBC-USDT,EUL-USDT,TON-USDT,PIAS-USDT,HIMEEBITS-USDT,HISQUIGGLE-USDT,XCV-USDT,HFT-USDT,HFT-USDC,ECOX-USDT,AMB-USDT,AZERO-USDT,HIFIDENZA-USDT,BEAT-USDT", "requestFormat": { "uppercase": true, "delimiter": "-" @@ -2532,4 +2532,4 @@ "supportedExchanges": "Kraken,Bitstamp" } ] -} \ No newline at end of file +}