Coinbene: Add swap endpoints and code cleanup/bugfixes (#403)

* Start Coinbene SWAP implementation

* Flesh out more API endpoints

* Code cleanup

* Add more endpoints, bug fixes and order validation checks

* More endpoints, tests and bugfixes

* Remove omitempty for enabled/available pairs
This commit is contained in:
Adrian Gallagher
2019-12-18 17:36:07 +11:00
committed by GitHub
parent edc07f7839
commit 467d8d91a2
9 changed files with 1797 additions and 502 deletions

View File

@@ -1271,22 +1271,33 @@
"websocketOrderbookBufferLimit": 5,
"baseCurrencies": "USD",
"currencyPairs": {
"requestFormat": {
"uppercase": true,
"delimiter": "/"
},
"configFormat": {
"uppercase": true,
"delimiter": "/"
},
"useGlobalFormat": true,
"assetTypes": [
"spot"
"spot",
"perpetualswap"
],
"pairs": {
"perpetualswap": {
"enabled": "BTC/USDT",
"available": "LTC/USDT,EOS/USDT,ETH/USDT,BTC/USDT",
"requestFormat": {
"uppercase": true
},
"configFormat": {
"uppercase": true,
"delimiter": "/"
}
},
"spot": {
"enabled": "BTC/USDT",
"available": "ABBC/BTC,ABBC/USDT,ABT/ETH,ABT/USDT,ABYSS/ETH,ACDC/BTC,ACDC/USDT,ADI/ETH,ADK/BTC,ADN/BTC,AE/BTC,AE/USDT,AIDOC/BTC,AION/BTC,AIPE/USDT,AIT/USDT,ALI/ETH,ALX/ETH,APL/ETH,ATX/BTC,BAAS/BTC,BABA/USDT,BAT/BTC,BCH/USDT,BETHER/ETH,BEZ/BTC,BGC/USDT,BKG/BTC,BNB/USDT,BNT/BTC,BOA/USDT,BSTN/ETH,BSV/USDT,BTC/USDT,BTNT/BTC,BTSC/BTC,BTT/USDT,BU/ETH,BVT/ETH,CAN/ETH,CCC/ETH,CCE/USDT,CEDEX/ETH,CENT/BTC,CFT/USDT,CMT/ETH,CMT/USDT,CNN/BTC,CNN/ETH,CNN/USDT,CONI/USDT,COSM/BTC,COSM/ETH,CPC/BTC,CREDO/ETH,CRN/BTC,CSCC/USDT,CS/ETH,CS/USDT,CTXC/ETH,CUST/USDT,CVC/BTC,CXP/BTC,DDAM/ETH,DDAM/USDT,DENT/BTC,DGD/BTC,DSCB/USDT,DTA/ETH,DUC/BTC,DVC/ETH,EBC/BTC,EBC/ETH,EBC/USDT,ECP/BTC,EDC/BTC,EDR/ETH,ELF/BTC,EMT/USDT,EOS/BTC,EOS/USDT,EQUAD/BTC,ETC/BTC,ETC/USDT,ETH/BTC,ETH/USDT,ETK/BTC,FAB/ETH,FCC/BTC,FND/ETH,FNKOS/ETH,FTN/BTC,FTN/USDT,FTT/BTC,FXT/ETH,GDC/BTC,GDC/ETH,GDC/USDT,GETX/ETH,GOM2/USDT,GRAM/USDT,GRN/BTC,GUSD/USDT,GVT/BTC,HAPPY/BTC,HDAC/BTC,HMB/USDT,HNB/USDT,HPT/ETH,HT/USDT,HUP/USDT,INCX/ETH,IOST/BTC,IOTE/USDT,ISR/ETH,IVY/ETH,JOB/BTC,KBC/BTC,KBC/USDT,KMD/BTC,KNT/ETH,KST/BTC,LAMB/USDT,LATX/BTC,LBK/BTC,LINK/BTC,LOOM/BTC,LTC/BTC,LTC/USDT,LUC/ETH,LUX/BTC,LVTC/ETH,MC/USDT,MIB/BTC,MINX/BTC,MINX/ETH,MOAC/USDT,MPL/BTC,MTC/BTC,MT/ETH,MTN/ETH,MT/USDT,MVL/ETH,MXM/ETH,MXM/USDT,MZG/USDT,NANO/BTC,NBAI/ETH,NEO/BTC,NEO/USDT,NFT/USDT,NOBS/BTC,NPXS/ETH,NPXS/USDT,NTY/ETH,ODC/USDT,OMG/BTC,OMX/ETH,OVC/ETH,OZX/ETH,PAT/ETH,PAX/USDT,PLAY/BTC,PMA/ETH,POLL/BTC,POLY/BTC,PPT/BTC,PSM/BTC,QKC/BTC,QTUM/BTC,QTUM/USDT,RBTC/BTC,RCOIN/BTC,RCOIN/USDT,REP/BTC,REV/BTC,RIF/BTC,RRW/USDT,SBT/USDT,SCC/BTC,SCO/BTC,SEN/BTC,SENC/ETH,SHE/BTC,SHVR/BTC,SIM/BTC,SKB/BTC,SKM/ETH,SKYM/USDT,SLT/ETH,SMARTUP/ETH,SMARTUP/USDT,SORO/USDT,SRCOIN/BTC,SRCOIN/ETH,STORJ/BTC,STQ/BTC,SWET/BTC,SWTC/USDT,TCT/BTC,TEMCO/USDT,TEN/BTC,TEN/ETH,TIB/BTC,TMTG/BTC,TOC/ETH,TOOS/USDT,TOSC/BTC,TRUE/ETH,TRX/BTC,TRX/USDT,TSL/BTC,UNI/USDT,UTNP/BTC,VBT/USDT,VEEN/BTC,VME/BTC,VME/ETH,VSC/ETH,VSF/BTC,W12/BTC,W12/ETH,WBL/BTC,WFX/BTC,XEM/BTC,XLM/BTC,XMCT/ETH,XMCT/USDT,XMR/BTC,XNK/ETH,XRP/BTC,XRP/USDT,XSR/USDT,YAP/BTC,YAP/USDT,YTA/USDT,ZAT/ETH,ZDC/BTC,ZEC/BTC,ZGC/BTC,ZRX/BTC"
"available": "ABBC/BTC,ABBC/USDT,ABT/ETH,ABT/USDT,ABYSS/ETH,ACDC/BTC,ACDC/USDT,ADI/ETH,ADK/BTC,ADN/BTC,AE/BTC,AE/USDT,AIDOC/BTC,AION/BTC,AIPE/USDT,AIT/USDT,ALI/ETH,ALX/ETH,APL/ETH,ATX/BTC,BAAS/BTC,BABA/USDT,BAT/BTC,BCH/USDT,BETHER/ETH,BEZ/BTC,BGC/USDT,BKG/BTC,BNB/USDT,BNT/BTC,BOA/USDT,BSTN/ETH,BSV/USDT,BTC/USDT,BTNT/BTC,BTSC/BTC,BTT/USDT,BU/ETH,BVT/ETH,CAN/ETH,CCC/ETH,CCE/USDT,CEDEX/ETH,CENT/BTC,CFT/USDT,CMT/ETH,CMT/USDT,CNN/BTC,CNN/ETH,CNN/USDT,CONI/USDT,COSM/BTC,COSM/ETH,CPC/BTC,CREDO/ETH,CRN/BTC,CSCC/USDT,CS/ETH,CS/USDT,CTXC/ETH,CUST/USDT,CVC/BTC,CXP/BTC,DDAM/ETH,DDAM/USDT,DENT/BTC,DGD/BTC,DSCB/USDT,DTA/ETH,DUC/BTC,DVC/ETH,EBC/BTC,EBC/ETH,EBC/USDT,ECP/BTC,EDC/BTC,EDR/ETH,ELF/BTC,EMT/USDT,EOS/BTC,EOS/USDT,EQUAD/BTC,ETC/BTC,ETC/USDT,ETH/BTC,ETH/USDT,ETK/BTC,FAB/ETH,FCC/BTC,FND/ETH,FNKOS/ETH,FTN/BTC,FTN/USDT,FTT/BTC,FXT/ETH,GDC/BTC,GDC/ETH,GDC/USDT,GETX/ETH,GOM2/USDT,GRAM/USDT,GRN/BTC,GUSD/USDT,GVT/BTC,HAPPY/BTC,HDAC/BTC,HMB/USDT,HNB/USDT,HPT/ETH,HT/USDT,HUP/USDT,INCX/ETH,IOST/BTC,IOTE/USDT,ISR/ETH,IVY/ETH,JOB/BTC,KBC/BTC,KBC/USDT,KMD/BTC,KNT/ETH,KST/BTC,LAMB/USDT,LATX/BTC,LBK/BTC,LINK/BTC,LOOM/BTC,LTC/BTC,LTC/USDT,LUC/ETH,LUX/BTC,LVTC/ETH,MC/USDT,MIB/BTC,MINX/BTC,MINX/ETH,MOAC/USDT,MPL/BTC,MTC/BTC,MT/ETH,MTN/ETH,MT/USDT,MVL/ETH,MXM/ETH,MXM/USDT,MZG/USDT,NANO/BTC,NBAI/ETH,NEO/BTC,NEO/USDT,NFT/USDT,NOBS/BTC,NPXS/ETH,NPXS/USDT,NTY/ETH,ODC/USDT,OMG/BTC,OMX/ETH,OVC/ETH,OZX/ETH,PAT/ETH,PAX/USDT,PLAY/BTC,PMA/ETH,POLL/BTC,POLY/BTC,PPT/BTC,PSM/BTC,QKC/BTC,QTUM/BTC,QTUM/USDT,RBTC/BTC,RCOIN/BTC,RCOIN/USDT,REP/BTC,REV/BTC,RIF/BTC,RRW/USDT,SBT/USDT,SCC/BTC,SCO/BTC,SEN/BTC,SENC/ETH,SHE/BTC,SHVR/BTC,SIM/BTC,SKB/BTC,SKM/ETH,SKYM/USDT,SLT/ETH,SMARTUP/ETH,SMARTUP/USDT,SORO/USDT,SRCOIN/BTC,SRCOIN/ETH,STORJ/BTC,STQ/BTC,SWET/BTC,SWTC/USDT,TCT/BTC,TEMCO/USDT,TEN/BTC,TEN/ETH,TIB/BTC,TMTG/BTC,TOC/ETH,TOOS/USDT,TOSC/BTC,TRUE/ETH,TRX/BTC,TRX/USDT,TSL/BTC,UNI/USDT,UTNP/BTC,VBT/USDT,VEEN/BTC,VME/BTC,VME/ETH,VSC/ETH,VSF/BTC,W12/BTC,W12/ETH,WBL/BTC,WFX/BTC,XEM/BTC,XLM/BTC,XMCT/ETH,XMCT/USDT,XMR/BTC,XNK/ETH,XRP/BTC,XRP/USDT,XSR/USDT,YAP/BTC,YAP/USDT,YTA/USDT,ZAT/ETH,ZDC/BTC,ZEC/BTC,ZGC/BTC,ZRX/BTC",
"requestFormat": {
"uppercase": true,
"delimiter": "/"
},
"configFormat": {
"uppercase": true,
"delimiter": "/"
}
}
}
},
@@ -1314,7 +1325,7 @@
"restCapabilities": {
"autoPairUpdates": true
},
"websocketAPI": false,
"websocketAPI": true,
"websocketCapabilities": {}
},
"enabled": {
@@ -1825,7 +1836,7 @@
"pairs": {
"spot": {
"enabled": "BTCUSD,BTCAUD",
"available": "BACETH,BTCUSD,USDSGD,USDJPY,LTCBTC,BTCCHF,BTCNZD,BTCJPY,USDNGN,BCHBTC,BTCAUD,NZDUSD,EURUSD,USDHKD,BTCEUR,USDCHF,GBPUSD,XRPBTC,AUDUSD,BTCHKD,BTCGBP,BTCCAD,BTCNGN,BTCSGD,USDCAD,ETHBTC"
"available": "BTCNZD,BTCUSD,BTCAUD,USDNGN,BCHBTC,BTCJPY,BTCCHF,BTCSGD,BTCCAD,GBPUSD,XRPBTC,USDCAD,AUDUSD,USDCHF,BACETH,USDJPY,NZDUSD,BTCEUR,USDSGD,USDHKD,ETHBTC,LTCBTC,EURUSD,BTCNGN,BTCGBP"
}
}
},

View File

@@ -19,8 +19,8 @@ type PairsManager struct {
// PairStore stores a currency pair store
type PairStore struct {
Enabled Pairs `json:"enabled,omitempty"`
Available Pairs `json:"available,omitempty"`
Enabled Pairs `json:"enabled"`
Available Pairs `json:"available"`
RequestFormat *PairFormat `json:"requestFormat,omitempty"`
ConfigFormat *PairFormat `json:"configFormat,omitempty"`
}

View File

@@ -2,6 +2,7 @@ package engine
import (
"errors"
"strings"
"sync/atomic"
"time"
@@ -371,8 +372,12 @@ func (e *ExchangeCurrencyPairSyncer) worker() {
c.Ticker.IsUsingWebsocket = false
c.Ticker.IsUsingREST = true
log.Warnf(log.SyncMgr,
"%s %s: No ticker update after %s, switching from websocket to rest\n",
c.Exchange, FormatCurrency(enabledPairs[i]).String(), e.Cfg.SyncTimeout)
"%s %s %s: No ticker update after %s, switching from websocket to rest\n",
c.Exchange,
FormatCurrency(enabledPairs[i]).String(),
strings.ToUpper(c.AssetType.String()),
e.Cfg.SyncTimeout,
)
switchedToRest = true
e.setProcessing(c.Exchange, c.Pair, c.AssetType, SyncItemTicker, false)
}
@@ -435,8 +440,12 @@ func (e *ExchangeCurrencyPairSyncer) worker() {
c.Orderbook.IsUsingWebsocket = false
c.Orderbook.IsUsingREST = true
log.Warnf(log.SyncMgr,
"%s %s: No orderbook update after %s, switching from websocket to rest\n",
c.Exchange, FormatCurrency(c.Pair).String(), e.Cfg.SyncTimeout)
"%s %s %s: No orderbook update after %s, switching from websocket to rest\n",
c.Exchange,
FormatCurrency(c.Pair).String(),
strings.ToUpper(c.AssetType.String()),
e.Cfg.SyncTimeout,
)
switchedToRest = true
e.setProcessing(c.Exchange, c.Pair, c.AssetType, SyncItemOrderbook, false)
}

File diff suppressed because it is too large Load Diff

View File

@@ -7,6 +7,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/config"
"github.com/thrasher-corp/gocryptotrader/currency"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
)
@@ -15,7 +16,8 @@ const (
testAPIKey = ""
testAPISecret = ""
canManipulateRealOrders = false
btcusdt = "BTC/USDT"
spotTestPair = "BTC/USDT"
swapTestPair = "BTCUSDT"
)
var c Coinbene
@@ -48,30 +50,6 @@ func areTestAPIKeysSet() bool {
return c.AllowAuthenticatedRequest()
}
func TestGetTicker(t *testing.T) {
t.Parallel()
_, err := c.GetTicker(btcusdt)
if err != nil {
t.Error(err)
}
}
func TestGetOrderbook(t *testing.T) {
t.Parallel()
_, err := c.GetOrderbook(btcusdt, 100)
if err != nil {
t.Error(err)
}
}
func TestGetTrades(t *testing.T) {
t.Parallel()
_, err := c.GetTrades(btcusdt)
if err != nil {
t.Error(err)
}
}
func TestGetAllPairs(t *testing.T) {
t.Parallel()
_, err := c.GetAllPairs()
@@ -82,18 +60,53 @@ func TestGetAllPairs(t *testing.T) {
func TestGetPairInfo(t *testing.T) {
t.Parallel()
_, err := c.GetPairInfo(btcusdt)
_, err := c.GetPairInfo(spotTestPair)
if err != nil {
t.Error(err)
}
}
func TestGetUserBalance(t *testing.T) {
func TestGetOrderbook(t *testing.T) {
t.Parallel()
_, err := c.GetOrderbook(spotTestPair, 100)
if err != nil {
t.Error(err)
}
}
func TestGetTicker(t *testing.T) {
t.Parallel()
_, err := c.GetTicker(spotTestPair)
if err != nil {
t.Error(err)
}
}
func TestGetTrades(t *testing.T) {
t.Parallel()
_, err := c.GetTrades(spotTestPair)
if err != nil {
t.Error(err)
}
}
func TestGetAcounntBalances(t *testing.T) {
t.Parallel()
if !areTestAPIKeysSet() {
t.Skip("API keys required but not set, skipping test")
}
_, err := c.GetUserBalance()
_, err := c.GetAccountBalances()
if err != nil {
t.Error(err)
}
}
func TestGetAccountAssetBalance(t *testing.T) {
t.Parallel()
if !areTestAPIKeysSet() {
t.Skip("API keys required but not set, skipping test")
}
_, err := c.GetAccountAssetBalance(currency.BTC.String())
if err != nil {
t.Error(err)
}
@@ -104,29 +117,38 @@ func TestPlaceOrder(t *testing.T) {
if !areTestAPIKeysSet() || !canManipulateRealOrders {
t.Skip("skipping test, either api keys or manipulaterealorders isnt set correctly")
}
_, err := c.PlaceOrder(1, 1, btcusdt, order.Buy.Lower(), "")
_, err := c.PlaceSpotOrder(
1,
1,
spotTestPair,
order.Buy.Lower(),
order.Limit.Lower(),
"Sup3rAw3s0m3Cl13ntiDH",
0,
)
if err != nil {
t.Error(err)
}
}
func TestFetchOrderInfo(t *testing.T) {
t.Parallel()
if !areTestAPIKeysSet() {
t.Skip("API keys required but not set, skipping test")
}
_, err := c.FetchOrderInfo("adfjashjgsag")
if err != nil {
t.Error(err)
}
}
func TestRemoveOrder(t *testing.T) {
func TestPlaceOrders(t *testing.T) {
t.Parallel()
if !areTestAPIKeysSet() || !canManipulateRealOrders {
t.Skip("skipping test, either api keys or manipulaterealorders isnt set correctly")
}
_, err := c.RemoveOrder("adfjashjgsag")
_, err := c.PlaceSpotOrders(
[]PlaceOrderRequest{
{
1,
1,
spotTestPair,
order.Buy.Lower(),
order.Limit.Lower(),
"Sup3rAw3s0m3Cl13ntiDH",
0,
},
})
if err != nil {
t.Error(err)
}
@@ -137,7 +159,7 @@ func TestFetchOpenOrders(t *testing.T) {
if !areTestAPIKeysSet() {
t.Skip("API keys required but not set, skipping test")
}
_, err := c.FetchOpenOrders(btcusdt)
_, err := c.FetchOpenSpotOrders(spotTestPair)
if err != nil {
t.Error(err)
}
@@ -148,7 +170,52 @@ func TestFetchClosedOrders(t *testing.T) {
if !areTestAPIKeysSet() {
t.Skip("API keys required but not set, skipping test")
}
_, err := c.FetchClosedOrders(btcusdt, "")
_, err := c.FetchClosedOrders(spotTestPair, "")
if err != nil {
t.Error(err)
}
}
func TestFetchOrderInfo(t *testing.T) {
t.Parallel()
if !areTestAPIKeysSet() {
t.Skip("API keys required but not set, skipping test")
}
_, err := c.FetchSpotOrderInfo("adfjashjgsag")
if err != nil {
t.Error(err)
}
}
func TestGetSpotOrderFills(t *testing.T) {
t.Parallel()
if !areTestAPIKeysSet() {
t.Skip("API keys required but not set, skipping test")
}
_, err := c.GetSpotOrderFills("1912131427156307968")
if err != nil {
t.Error(err)
}
}
func TestCancelSpotOrder(t *testing.T) {
t.Parallel()
if !areTestAPIKeysSet() || !canManipulateRealOrders {
t.Skip("skipping test, either api keys or manipulaterealorders isnt set correctly")
}
_, err := c.CancelSpotOrder("adfjashjgsag")
if err != nil {
t.Error(err)
}
}
func TestCancelSpotOrders(t *testing.T) {
t.Parallel()
if !areTestAPIKeysSet() || !canManipulateRealOrders {
t.Skip("skipping test, either api keys or manipulaterealorders isnt set correctly")
}
_, err := c.CancelSpotOrders([]string{"578639816552972288", "578639902896914432"})
if err != nil {
t.Error(err)
}
@@ -157,7 +224,11 @@ func TestFetchClosedOrders(t *testing.T) {
func TestUpdateTicker(t *testing.T) {
t.Parallel()
cp := currency.NewPairWithDelimiter("BTC", "USDT", "/")
_, err := c.UpdateTicker(cp, "spot")
_, err := c.UpdateTicker(cp, asset.Spot)
if err != nil {
t.Error(err)
}
_, err = c.UpdateTicker(cp, asset.PerpetualSwap)
if err != nil {
t.Error(err)
}
@@ -177,7 +248,203 @@ func TestGetAccountInfo(t *testing.T) {
func TestUpdateOrderbook(t *testing.T) {
t.Parallel()
cp := currency.NewPairWithDelimiter("BTC", "USDT", "/")
_, err := c.UpdateOrderbook(cp, "spot")
_, err := c.UpdateOrderbook(cp, asset.Spot)
if err != nil {
t.Error(err)
}
_, err = c.UpdateOrderbook(cp, asset.PerpetualSwap)
if err != nil {
t.Error(err)
}
}
func TestGetSwapTickers(t *testing.T) {
t.Parallel()
_, err := c.GetSwapTickers()
if err != nil {
t.Error(err)
}
}
func TestGetSwapTicker(t *testing.T) {
t.Parallel()
_, err := c.GetSwapTicker(swapTestPair)
if err != nil {
t.Error(err)
}
}
func TestGetSwapOrderbook(t *testing.T) {
t.Parallel()
_, err := c.GetSwapOrderbook(swapTestPair, 100)
if err != nil {
t.Error(err)
}
}
func TestGetSwapKlines(t *testing.T) {
t.Parallel()
_, err := c.GetSwapKlines(swapTestPair,
"1573184608",
"1573184808",
"1")
if err != nil {
t.Error(err)
}
}
func TestGetSwapTrades(t *testing.T) {
t.Parallel()
_, err := c.GetSwapTrades(swapTestPair, 10)
if err != nil {
t.Error(err)
}
}
func TestGetSwapAccountInfo(t *testing.T) {
t.Parallel()
if !areTestAPIKeysSet() {
t.Skip("API keys required but not set, skipping test")
}
_, err := c.GetSwapAccountInfo()
if err != nil {
t.Error(err)
}
}
func TestGetSwapPositions(t *testing.T) {
t.Parallel()
if !areTestAPIKeysSet() {
t.Skip("API keys required but not set, skipping test")
}
_, err := c.GetSwapPositions(swapTestPair)
if err != nil {
t.Error(err)
}
}
func TestPlaceSwapOrder(t *testing.T) {
t.Parallel()
if !areTestAPIKeysSet() || !canManipulateRealOrders {
t.Skip("skipping test, either api keys or manipulaterealorders isnt set correctly")
}
_, err := c.PlaceSwapOrder(swapTestPair,
order.Buy.Lower(),
"limit",
"fixed",
"12345",
1,
1,
2)
if err != nil {
t.Error(err)
}
}
func TestCancelSwapOrder(t *testing.T) {
t.Parallel()
if !areTestAPIKeysSet() || !canManipulateRealOrders {
t.Skip("skipping test, either api keys or manipulaterealorders isnt set correctly")
}
_, err := c.CancelSwapOrder("1337")
if err != nil {
t.Error(err)
}
}
func TestGetOpenSwapOrders(t *testing.T) {
t.Parallel()
if !areTestAPIKeysSet() || !canManipulateRealOrders {
t.Skip("skipping test, either api keys or manipulaterealorders isnt set correctly")
}
_, err := c.GetSwapOpenOrders(swapTestPair, 0, 0)
if err != nil {
t.Error(err)
}
}
func TestGetSwapOpenOrdersByPage(t *testing.T) {
t.Parallel()
if !areTestAPIKeysSet() || !canManipulateRealOrders {
t.Skip("skipping test, either api keys or manipulaterealorders isnt set correctly")
}
_, err := c.GetSwapOpenOrdersByPage(swapTestPair, 0)
if err != nil {
t.Error(err)
}
}
func TestGetSwapOrderInfo(t *testing.T) {
t.Parallel()
if !areTestAPIKeysSet() || !canManipulateRealOrders {
t.Skip("skipping test, either api keys or manipulaterealorders isnt set correctly")
}
_, err := c.GetSwapOrderInfo("1337")
if err != nil {
t.Error(err)
}
}
func TestGetSwapOrderHistory(t *testing.T) {
t.Parallel()
if !areTestAPIKeysSet() || !canManipulateRealOrders {
t.Skip("skipping test, either api keys or manipulaterealorders isnt set correctly")
}
_, err := c.GetSwapOrderHistory("", "", swapTestPair, 1, 10, "", "")
if err != nil {
t.Error(err)
}
}
func TestGetSwapOrderHistoryByOrderID(t *testing.T) {
t.Parallel()
if !areTestAPIKeysSet() || !canManipulateRealOrders {
t.Skip("skipping test, either api keys or manipulaterealorders isnt set correctly")
}
_, err := c.GetSwapOrderHistoryByOrderID("", "", swapTestPair, "", 0)
if err != nil {
t.Error(err)
}
}
func TestCancelSwapOrders(t *testing.T) {
t.Parallel()
if !areTestAPIKeysSet() || !canManipulateRealOrders {
t.Skip("skipping test, either api keys or manipulaterealorders isnt set correctly")
}
_, err := c.CancelSwapOrders([]string{"578639816552972288", "578639902896914432"})
if err != nil {
t.Error(err)
}
}
func TestGetSwapOrderFills(t *testing.T) {
t.Parallel()
if !areTestAPIKeysSet() || !canManipulateRealOrders {
t.Skip("skipping test, either api keys or manipulaterealorders isnt set correctly")
}
_, err := c.GetSwapOrderFills(swapTestPair, "5807143157122003", 580714315825905664)
if err != nil {
t.Error(err)
}
}
func TestGetSwapFundingRates(t *testing.T) {
t.Parallel()
if !areTestAPIKeysSet() || !canManipulateRealOrders {
t.Skip("skipping test, either api keys or manipulaterealorders isnt set correctly")
}
_, err := c.GetSwapFundingRates(1, 2)
if err != nil {
t.Error(err)
}

View File

@@ -1,5 +1,11 @@
package coinbene
import (
"time"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
)
// TickerData stores ticker data
type TickerData struct {
Symbol string `json:"symbol"`
@@ -11,35 +17,35 @@ type TickerData struct {
DailyVolume float64 `json:"volume24h,string"`
}
// TickerResponse stores ticker response data
type TickerResponse struct {
Code int64 `json:"code"`
Message string `json:"message"`
TickerData `json:"data"`
// OrderbookItem stores an individual orderbook item
type OrderbookItem struct {
Price float64
Amount float64
Count int64
}
// Orderbook stores orderbook info
// Orderbook stores the orderbook data
type Orderbook struct {
Asks [][]string `json:"asks"`
Bids [][]string `json:"bids"`
Bids []OrderbookItem
Asks []OrderbookItem
Symbol string
Time time.Time
}
// OrderbookResponse stores data from fetched orderbooks
type OrderbookResponse struct {
Code int64 `json:"code"`
Message string `json:"message"`
Orderbook `json:"data"`
// TradeItem stores a single trade
type TradeItem struct {
CurrencyPair string
Price float64
Volume float64
Direction string
TradeTime time.Time
}
// TradeResponse stores trade data
type TradeResponse struct {
Code int64 `json:"code"`
Message string `json:"message"`
Trades [][]string `json:"data"`
}
// Trades stores trade data
type Trades []TradeItem
// AllPairData stores pair data
type AllPairData struct {
// PairData stores pair data
type PairData struct {
Symbol string `json:"symbol"`
BaseAsset string `json:"baseAsset"`
QuoteAsset string `json:"quoteAsset"`
@@ -52,20 +58,6 @@ type AllPairData struct {
PriceFluctuation float64 `json:"priceFluctuation,string"`
}
// AllPairResponse stores data for all pairs enabled on exchange
type AllPairResponse struct {
Code int64 `json:"code"`
Message string `json:"message"`
Data []AllPairData `json:"data"`
}
// PairResponse stores data for a single queried pair
type PairResponse struct {
Code int64 `json:"code"`
Message string `json:"message"`
Data AllPairData `json:"data"`
}
// UserBalanceData stores user balance data
type UserBalanceData struct {
Asset string `json:"asset"`
@@ -74,24 +66,25 @@ type UserBalanceData struct {
Total float64 `json:"total,string"`
}
// UserBalanceResponse stores user balance data
type UserBalanceResponse struct {
Code int64 `json:"code"`
Message string `json:"message"`
Data []UserBalanceData `json:"data"`
// PlaceOrderRequest places an order request
type PlaceOrderRequest struct {
Price float64
Quantity float64
Symbol string
Direction string
OrderType string
ClientID string
Notional int
}
// PlaceOrderResponse stores data for a placed order
type PlaceOrderResponse struct {
Code int64 `json:"code"`
Message string `json:"message"`
Status string `json:"status"`
Timestamp int64 `json:"timestamp"`
OrderID string `json:"orderid"`
// CancelOrdersResponse stores data for a cancelled order
type CancelOrdersResponse struct {
OrderID string `json:"orderId"`
Message string `json:"message"`
}
// OrderInfoData stores order info
type OrderInfoData struct {
// OrderInfo stores order info
type OrderInfo struct {
OrderID string `json:"orderId"`
BaseAsset string `json:"baseAsset"`
QuoteAsset string `json:"quoteAsset"`
@@ -100,7 +93,7 @@ type OrderInfoData struct {
Amount float64 `json:"amout,string"`
FilledAmount float64 `json:"filledAmount"`
TakerRate float64 `json:"takerFeeRate,string"`
MakerRate float64 `json:"makerRate,string"`
MakerRate float64 `json:"makerFeeRate,string"`
AvgPrice float64 `json:"avgPrice,string"`
OrderPrice float64 `json:"orderPrice,string"`
OrderStatus string `json:"orderStatus"`
@@ -108,33 +101,19 @@ type OrderInfoData struct {
TotalFee float64 `json:"totalFee"`
}
// OrderInfoResponse stores orderinfo data
type OrderInfoResponse struct {
Order OrderInfoData `json:"data"`
Code int64 `json:"code"`
Message string `json:"message"`
// OrderFills stores the fill info
type OrderFills struct {
Price float64 `json:"price,string"`
Quantity float64 `json:"quantity,string"`
Amount float64 `json:"amount,string"`
Fee float64 `json:"fee,string"`
Direction string `json:"direction"`
TradeTime time.Time `json:"tradeTime"`
FeeByConi float64 `json:"feeByConi,string"`
}
// RemoveOrderResponse stores data for the remove request
type RemoveOrderResponse struct {
Code int64 `json:"code"`
Message string `json:"message"`
OrderID string `json:"data"`
}
// OpenOrderResponse stores data for open orders
type OpenOrderResponse struct {
Code int64 `json:"code"`
Message string `json:"message"`
OpenOrders []OrderInfoData `json:"data"`
}
// ClosedOrderResponse stores data for closed orders
type ClosedOrderResponse struct {
Code int64 `json:"code"`
Message string `json:"message"`
Data []OrderInfoData `json:"data"`
}
// OrdersInfo stores a collection of orders
type OrdersInfo []OrderInfo
// WsSub stores subscription data
type WsSub struct {
@@ -144,17 +123,17 @@ type WsSub struct {
// WsTickerData stores websocket ticker data
type WsTickerData struct {
Symbol string `json:"symbol"`
LastPrice float64 `json:"lastPrice,string"`
MarkPrice float64 `json:"markPrice,string"`
BestAskPrice float64 `json:"bestAskPrice,string"`
BestBidPrice float64 `json:"bestBidPrice,string"`
BestAskVolume float64 `json:"bestAskVolume,string"`
BestBidVolume float64 `json:"bestBidVolume,string"`
High24h float64 `json:"high24h,string"`
Low24h float64 `json:"low24h,string"`
Volume24h float64 `json:"volume,string"`
Timestamp string `json:"timestamp"`
Symbol string `json:"symbol"`
LastPrice float64 `json:"lastPrice,string"`
MarkPrice float64 `json:"markPrice,string"`
BestAskPrice float64 `json:"bestAskPrice,string"`
BestBidPrice float64 `json:"bestBidPrice,string"`
BestAskVolume float64 `json:"bestAskVolume,string"`
BestBidVolume float64 `json:"bestBidVolume,string"`
High24h float64 `json:"high24h,string"`
Low24h float64 `json:"low24h,string"`
Volume24h float64 `json:"volume24h,string"`
Timestamp time.Time `json:"timestamp"`
}
// WsTicker stores websocket ticker
@@ -169,15 +148,6 @@ type WsTradeList struct {
Data [][]string `json:"data"`
}
// WsOrderbook stores websocket orderbook data
type WsOrderbook struct {
Topic string `json:"topic"`
Action string `json:"action"`
Data []Orderbook `json:"data"`
Version int64 `json:"version,string"`
Timestamp string `json:"timestamp"`
}
// WsKline stores websocket kline data
type WsKline struct {
Topic string `json:"topic"`
@@ -186,11 +156,11 @@ type WsKline struct {
// WsUserData stores websocket user data
type WsUserData struct {
Asset string `json:"string"`
Available float64 `json:"availableBalance"`
Locked float64 `json:"frozenBalance"`
Total float64 `json:"balance"`
Timestamp string `json:"timestamp"`
Asset string `json:"string"`
Available float64 `json:"availableBalance"`
Locked float64 `json:"frozenBalance"`
Total float64 `json:"balance"`
Timestamp time.Time `json:"timestamp"`
}
// WsUserInfo stores websocket user info
@@ -201,18 +171,18 @@ type WsUserInfo struct {
// WsPositionData stores websocket info on user's position
type WsPositionData struct {
AvailableQuantity float64 `json:"availableQuantity"`
AveragePrice float64 `json:"avgPrice"`
Leverage float64 `json:"leverage"`
LiquidationPrice float64 `json:"liquidationPrice"`
MarkPrice float64 `json:"markPrice"`
PositionMargin float64 `json:"positionMargin"`
Quantity float64 `json:"quantity"`
RealisedPNL float64 `json:"realisedPnl"`
Side string `json:"side"`
Symbol string `json:"symbol"`
MarginMode int64 `json:"marginMode"`
CreateTime string `json:"createTime"`
AvailableQuantity float64 `json:"availableQuantity"`
AveragePrice float64 `json:"avgPrice"`
Leverage float64 `json:"leverage"`
LiquidationPrice float64 `json:"liquidationPrice"`
MarkPrice float64 `json:"markPrice"`
PositionMargin float64 `json:"positionMargin"`
Quantity float64 `json:"quantity"`
RealisedPNL float64 `json:"realisedPnl"`
Side string `json:"side"`
Symbol string `json:"symbol"`
MarginMode int64 `json:"marginMode"`
CreateTime time.Time `json:"createTime"`
}
// WsPosition stores websocket info on user's positions
@@ -223,22 +193,22 @@ type WsPosition struct {
// WsOrderData stores websocket user order data
type WsOrderData struct {
OrderID string `json:"orderId"`
Direction string `json:"direction"`
Leverage float64 `json:"leverage"`
Symbol string `json:"symbol"`
OrderType string `json:"orderType"`
Quantity float64 `json:"quantity"`
OrderPrice float64 `json:"orderPrice"`
OrderValue float64 `json:"orderValue"`
Fee float64 `json:"fee"`
FilledQuantity float64 `json:"filledQuantity"`
AveragePrice float64 `json:"averagePrice"`
OrderTime string `json:"orderTime"`
Status string `json:"status"`
LastFillQuantity float64 `json:"lastFillQuantity"`
LastFillPrice float64 `json:"lastFillPrice"`
LastFillTime string `json:"lastFillTime"`
OrderID string `json:"orderId"`
Direction string `json:"direction"`
Leverage float64 `json:"leverage"`
Symbol string `json:"symbol"`
OrderType string `json:"orderType"`
Quantity float64 `json:"quantity"`
OrderPrice float64 `json:"orderPrice"`
OrderValue float64 `json:"orderValue"`
Fee float64 `json:"fee"`
FilledQuantity float64 `json:"filledQuantity"`
AveragePrice float64 `json:"averagePrice"`
OrderTime time.Time `json:"orderTime"`
Status string `json:"status"`
LastFillQuantity float64 `json:"lastFillQuantity"`
LastFillPrice float64 `json:"lastFillPrice"`
LastFillTime time.Time `json:"lastFillTime"`
}
// WsUserOrders stores websocket user orders' data
@@ -246,3 +216,141 @@ type WsUserOrders struct {
Topic string `json:"topic"`
Data []WsOrderData `json:"data"`
}
// SwapTicker stores the swap ticker info
type SwapTicker struct {
LastPrice float64 `json:"lastPrice,string"`
MarkPrice float64 `json:"markPrice,string"`
BestAskPrice float64 `json:"bestAskPrice,string"`
BestBidPrice float64 `json:"bestBidPrice,string"`
High24Hour float64 `json:"high24h,string"`
Low24Hour float64 `json:"low24h,string"`
Volume24Hour float64 `json:"volume24h,string"`
BestAskVolume float64 `json:"bestAskVolume,string"`
BestBidVolume float64 `json:"bestBidVolume,string"`
Turnover float64 `json:"turnover,string"`
Timestamp time.Time `json:"timeStamp"`
}
// SwapTickers stores a map of swap tickers
type SwapTickers map[string]SwapTicker
// SwapKlineItem stores an individual kline data item
type SwapKlineItem struct {
Time time.Time
Open float64
Close float64
High float64
Low float64
Volume float64
Turnover float64
BuyVolume float64
BuyTurnover float64
}
// SwapKlines stores an array of kline data
type SwapKlines []SwapKlineItem
// SwapTrade stores an individual trade
type SwapTrade struct {
Price float64
Side order.Side
Volume float64
Time time.Time
}
// SwapTrades stores an array of swap trades
type SwapTrades []SwapTrade
// SwapAccountInfo returns the swap account balance info
type SwapAccountInfo struct {
AvailableBalance float64 `json:"availableBalance,string"`
FrozenBalance float64 `json:"frozenBalance,string"`
MarginBalance float64 `json:"marginBalance,string"`
MarginRate float64 `json:"marginRate,string"`
Balance float64 `json:"balance,string"`
UnrealisedPNL float64 `json:"unrealisedPnl,string"`
}
// SwapPosition stores a single swap position's data
type SwapPosition struct {
AvailableQuantity float64 `json:"availableQuantity,string"`
AveragePrice float64 `json:"averagePrice,string"`
CreateTime time.Time `json:"createTime"`
DeleveragePercentile int `json:"deleveragePercentile,string"`
Leverage int `json:"leverage,string"`
LiquidationPrice float64 `json:"liquidationPrice,string"`
MarkPrice float64 `json:"markPrice,string"`
PositionMargin float64 `json:"positionMargin,string"`
PositionValue float64 `json:"positionValue,string"`
Quantity float64 `json:"quantity,string"`
RateOfReturn float64 `json:"roe,string"`
Side string `json:"side"`
Symbol string `json:"symbol"`
UnrealisedProfitAndLoss float64 `json:"UnrealisedPnl,string"`
}
// SwapPositions stores a collection of swap positions
type SwapPositions []SwapPosition
// SwapPlaceOrderResponse stores the response data for placing a swap order
type SwapPlaceOrderResponse struct {
OrderID string `json:"orderId"`
ClientID string `json:"clientId"`
}
// SwapOrder stores the swap order data
type SwapOrder struct {
OrderID string `json:"orderId"`
Direction string `json:"direction"`
Leverage int `json:"leverage,string"`
OrderType string `json:"orderType"`
Quantitity float64 `json:"quantity,string"`
OrderPrice float64 `json:"orderPrice,string"`
OrderValue float64 `json:"orderValue,string"`
Fee float64 `json:"fee"`
FilledQuantity float64 `json:"filledQuantity,string"`
AveragePrice float64 `json:"averagePrice,string"`
OrderTime time.Time `json:"orderTime"`
Status string `json:"status"`
}
// SwapOrders stores a collection of swap orders
type SwapOrders []SwapOrder
// OrderCancellationResponse returns a list of cancel order status
type OrderCancellationResponse struct {
OrderID string `json:"orderId"`
Code int `json:"code,string"`
Message string `json:"message"`
}
// OrderPlacementResponse stores the order placement data
type OrderPlacementResponse OrderCancellationResponse
// SwapOrderFill stores a swap orders fill info
type SwapOrderFill struct {
Symbol string `json:"symbol"`
TradeTime time.Time `json:"tradeTime"`
TradeID int64 `json:"tradeId,string"`
OrderID int64 `json:"orderId,string"`
Price float64 `json:"price,string"`
Fee float64 `json:"fee,string"`
ExecType string `json:"execType"`
Side string `json:"side"`
Quantity float64 `json:"quantity,string"`
}
// SwapOrderFills stores a collection of swap order fills
type SwapOrderFills []SwapOrderFill
// SwapFundingRate stores a collection of funding rates
type SwapFundingRate struct {
Symbol string `json:"symbol"`
Side string `json:"side"`
MarkPrice float64 `json:"markPrice,string"`
PositionValue float64 `json:"positionValue,string"`
Fee float64 `json:"fee,string"`
FeeRate float64 `json:"feeRate,string"`
Leverage int64 `json:"leverage"`
}

View File

@@ -138,11 +138,14 @@ func (c *Coinbene) WsDataHandler() {
Last: ticker.Data[x].LastPrice,
High: ticker.Data[x].High24h,
Low: ticker.Data[x].Low24h,
Bid: ticker.Data[x].BestBidPrice,
Ask: ticker.Data[x].BestAskPrice,
Pair: currency.NewPairFromFormattedPairs(ticker.Data[x].Symbol,
c.GetEnabledPairs(asset.PerpetualSwap),
c.GetPairFormat(asset.PerpetualSwap, true)),
Exchange: c.Name,
AssetType: asset.PerpetualSwap,
Timestamp: ticker.Data[x].Timestamp,
}
}
case strings.Contains(result[topic].(string), "tradeList"):
@@ -182,13 +185,22 @@ func (c *Coinbene) WsDataHandler() {
Side: tradeList.Data[0][1],
}
case strings.Contains(result[topic].(string), "orderBook"):
var orderBook WsOrderbook
orderBook := struct {
Topic string `json:"topic"`
Action string `json:"action"`
Data []struct {
Bids [][]string `json:"bids"`
Asks [][]string `json:"asks"`
Version int64 `json:"version"`
Timestamp time.Time `json:"timestamp"`
} `json:"data"`
}{}
err = json.Unmarshal(stream.Raw, &orderBook)
if err != nil {
c.Websocket.DataHandler <- err
continue
}
p := strings.Replace(orderBook.Topic, "tradeList.", "", 1)
p := strings.Replace(orderBook.Topic, "orderBook.", "", 1)
cp := currency.NewPairFromFormattedPairs(p,
c.GetEnabledPairs(asset.PerpetualSwap),
c.GetPairFormat(asset.PerpetualSwap, true))
@@ -233,6 +245,7 @@ func (c *Coinbene) WsDataHandler() {
newOB.AssetType = asset.PerpetualSwap
newOB.Pair = cp
newOB.ExchangeName = c.Name
newOB.LastUpdated = orderBook.Data[0].Timestamp
err = c.Websocket.Orderbook.LoadSnapshot(&newOB)
if err != nil {
c.Websocket.DataHandler <- err
@@ -244,11 +257,12 @@ func (c *Coinbene) WsDataHandler() {
}
} else if orderBook.Action == "update" {
newOB := wsorderbook.WebsocketOrderbookUpdate{
Asks: asks,
Bids: bids,
Asset: asset.PerpetualSwap,
Pair: cp,
UpdateID: orderBook.Version,
Asks: asks,
Bids: bids,
Asset: asset.PerpetualSwap,
Pair: cp,
UpdateID: orderBook.Data[0].Version,
UpdateTime: orderBook.Data[0].Timestamp,
}
err = c.Websocket.Orderbook.Update(&newOB)
if err != nil {

View File

@@ -2,7 +2,6 @@ package coinbene
import (
"fmt"
"strconv"
"strings"
"sync"
"time"
@@ -56,8 +55,11 @@ func (c *Coinbene) SetDefaults() {
c.CurrencyPairs = currency.PairsManager{
AssetTypes: asset.Items{
asset.Spot,
asset.PerpetualSwap,
},
UseGlobalFormat: true,
}
c.CurrencyPairs.Store(asset.Spot, currency.PairStore{
RequestFormat: &currency.PairFormat{
Uppercase: true,
Delimiter: "/",
@@ -66,12 +68,22 @@ func (c *Coinbene) SetDefaults() {
Uppercase: true,
Delimiter: "/",
},
}
})
c.CurrencyPairs.Store(asset.PerpetualSwap, currency.PairStore{
RequestFormat: &currency.PairFormat{
Uppercase: true,
},
ConfigFormat: &currency.PairFormat{
Uppercase: true,
Delimiter: "/",
},
})
c.Features = exchange.Features{
Supports: exchange.FeaturesSupported{
REST: true,
Websocket: false, // Purposely disabled until SWAP is supported
Websocket: true,
RESTCapabilities: protocol.Features{
TickerFetching: true,
TradeFetching: true,
@@ -129,15 +141,6 @@ func (c *Coinbene) Setup(exch *config.ExchangeConfig) error {
return err
}
// TO-DO: Remove this once SWAP is supported
if exch.Features.Enabled.Websocket {
log.Warnf(log.ExchangeSys,
"%s websocket only supports SWAP which GoCryptoTrader currently "+
"does not. Disabling.\n",
c.Name)
exch.Features.Enabled.Websocket = false
}
err = c.Websocket.Setup(
&wshandler.WebsocketSetup{
Enabled: exch.Features.Enabled.Websocket,
@@ -150,6 +153,7 @@ func (c *Coinbene) Setup(exch *config.ExchangeConfig) error {
Connector: c.WsConnect,
Subscriber: c.Subscribe,
UnSubscriber: c.Unsubscribe,
Features: &c.Features.Supports.WebsocketCapabilities,
})
if err != nil {
return err
@@ -211,14 +215,34 @@ func (c *Coinbene) Run() {
// FetchTradablePairs returns a list of exchange tradable pairs
func (c *Coinbene) FetchTradablePairs(a asset.Item) ([]string, error) {
pairs, err := c.GetAllPairs()
if err != nil {
return nil, err
if !c.SupportsAsset(a) {
return nil, fmt.Errorf("%s does not support asset type %s", c.Name, a)
}
var currencies []string
for x := range pairs.Data {
currencies = append(currencies, pairs.Data[x].Symbol)
switch a {
case asset.Spot:
pairs, err := c.GetAllPairs()
if err != nil {
return nil, err
}
for x := range pairs {
currencies = append(currencies, pairs[x].Symbol)
}
case asset.PerpetualSwap:
tickers, err := c.GetSwapTickers()
if err != nil {
return nil, err
}
for t := range tickers {
idx := strings.Index(t, currency.USDT.String())
if idx == 0 {
return nil, fmt.Errorf("%s SWAP currency does not contain USDT", c.Name)
}
currencies = append(currencies,
t[0:idx]+c.GetPairFormat(a, false).Delimiter+t[idx:])
}
}
return currencies, nil
}
@@ -226,38 +250,78 @@ func (c *Coinbene) FetchTradablePairs(a asset.Item) ([]string, error) {
// UpdateTradablePairs updates the exchanges available pairs and stores
// them
func (c *Coinbene) UpdateTradablePairs(forceUpdate bool) error {
pairs, err := c.FetchTradablePairs(asset.Spot)
if err != nil {
return err
assets := c.GetAssetTypes()
for x := range assets {
pairs, err := c.FetchTradablePairs(assets[x])
if err != nil {
return err
}
err = c.UpdatePairs(currency.NewPairsFromStrings(pairs),
assets[x], false, forceUpdate)
if err != nil {
return err
}
}
return c.UpdatePairs(currency.NewPairsFromStrings(pairs),
asset.Spot,
false,
forceUpdate)
return nil
}
// UpdateTicker updates and returns the ticker for a currency pair
func (c *Coinbene) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
tickerPrice := new(ticker.Price)
allPairs := c.GetEnabledPairs(assetType)
for x := range allPairs {
tempResp, err := c.GetTicker(c.FormatExchangeCurrency(allPairs[x],
assetType).String())
if err != nil {
return tickerPrice, err
resp := new(ticker.Price)
if !c.SupportsAsset(assetType) {
return nil,
fmt.Errorf("%s does not support asset type %s", c.Name, assetType)
}
switch assetType {
case asset.Spot:
allPairs := c.GetEnabledPairs(assetType)
for x := range allPairs {
tempResp, err := c.GetTicker(c.FormatExchangeCurrency(allPairs[x],
assetType).String())
if err != nil {
return nil, err
}
resp.Pair = allPairs[x]
resp.Last = tempResp.LatestPrice
resp.High = tempResp.DailyHigh
resp.Low = tempResp.DailyLow
resp.Bid = tempResp.BestBid
resp.Ask = tempResp.BestAsk
resp.Volume = tempResp.DailyVolume
resp.LastUpdated = time.Now()
err = ticker.ProcessTicker(c.Name, resp, assetType)
if err != nil {
return nil, err
}
}
tickerPrice.Pair = allPairs[x]
tickerPrice.Last = tempResp.TickerData.LatestPrice
tickerPrice.High = tempResp.TickerData.DailyHigh
tickerPrice.Low = tempResp.TickerData.DailyLow
tickerPrice.Bid = tempResp.TickerData.BestBid
tickerPrice.Ask = tempResp.TickerData.BestAsk
tickerPrice.Volume = tempResp.TickerData.DailyVolume
tickerPrice.LastUpdated = time.Now()
err = ticker.ProcessTicker(c.Name, tickerPrice, assetType)
case asset.PerpetualSwap:
tickers, err := c.GetSwapTickers()
if err != nil {
return tickerPrice, err
return nil, err
}
allPairs := c.GetEnabledPairs(assetType)
for x := range allPairs {
tick, ok := tickers[c.FormatExchangeCurrency(allPairs[x],
assetType).String()]
if !ok {
log.Warnf(log.ExchangeSys,
"%s SWAP ticker item was not found", c.Name)
continue
}
resp.Pair = allPairs[x]
resp.Last = tick.LastPrice
resp.High = tick.High24Hour
resp.Low = tick.Low24Hour
resp.Bid = tick.BestBidPrice
resp.Ask = tick.BestAskPrice
resp.Volume = tick.Volume24Hour
resp.LastUpdated = tick.Timestamp
err = ticker.ProcessTicker(c.Name, resp, assetType)
if err != nil {
return nil, err
}
}
}
return ticker.GetTicker(c.Name, p, assetType)
@@ -265,6 +329,11 @@ func (c *Coinbene) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.
// FetchTicker returns the ticker for a currency pair
func (c *Coinbene) FetchTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
if !c.SupportsAsset(assetType) {
return nil,
fmt.Errorf("%s does not support asset type %s", c.Name, assetType)
}
tickerNew, err := ticker.GetTicker(c.Name, p, assetType)
if err != nil {
return c.UpdateTicker(p, assetType)
@@ -274,6 +343,11 @@ func (c *Coinbene) FetchTicker(p currency.Pair, assetType asset.Item) (*ticker.P
// FetchOrderbook returns orderbook base on the currency pair
func (c *Coinbene) FetchOrderbook(currency currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
if !c.SupportsAsset(assetType) {
return nil,
fmt.Errorf("%s does not support asset type %s", c.Name, assetType)
}
ob, err := orderbook.Get(c.Name, currency, assetType)
if err != nil {
return c.UpdateOrderbook(currency, assetType)
@@ -283,47 +357,56 @@ func (c *Coinbene) FetchOrderbook(currency currency.Pair, assetType asset.Item)
// UpdateOrderbook updates and returns the orderbook for a currency pair
func (c *Coinbene) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
orderBook := new(orderbook.Base)
tempResp, err := c.GetOrderbook(
c.FormatExchangeCurrency(p, assetType).String(),
100,
)
resp := new(orderbook.Base)
if !c.SupportsAsset(assetType) {
return nil,
fmt.Errorf("%s does not support asset type %s", c.Name, assetType)
}
var tempResp Orderbook
var err error
switch assetType {
case asset.Spot:
tempResp, err = c.GetOrderbook(
c.FormatExchangeCurrency(p, assetType).String(),
100, // TO-DO: Update this once we support configurable orderbook depth
)
case asset.PerpetualSwap:
tempResp, err = c.GetSwapOrderbook(
c.FormatExchangeCurrency(p, assetType).String(),
100, // TO-DO: Update this once we support configurable orderbook depth
)
}
if err != nil {
return orderBook, err
return nil, err
}
orderBook.ExchangeName = c.Name
orderBook.Pair = p
orderBook.AssetType = assetType
var amount, price float64
for i := range tempResp.Orderbook.Asks {
amount, err = strconv.ParseFloat(tempResp.Orderbook.Asks[i][1], 64)
if err != nil {
return orderBook, err
resp.ExchangeName = c.Name
resp.Pair = p
resp.AssetType = assetType
for x := range tempResp.Asks {
item := orderbook.Item{
Price: tempResp.Asks[x].Price,
Amount: tempResp.Asks[x].Amount,
}
price, err = strconv.ParseFloat(tempResp.Orderbook.Asks[i][0], 64)
if err != nil {
return orderBook, err
if assetType == asset.PerpetualSwap {
item.OrderCount = tempResp.Asks[x].Count
}
orderBook.Asks = append(orderBook.Asks, orderbook.Item{
Price: price,
Amount: amount})
resp.Asks = append(resp.Asks, item)
}
for j := range tempResp.Orderbook.Bids {
amount, err = strconv.ParseFloat(tempResp.Orderbook.Bids[j][1], 64)
if err != nil {
return orderBook, err
for x := range tempResp.Bids {
item := orderbook.Item{
Price: tempResp.Bids[x].Price,
Amount: tempResp.Bids[x].Amount,
}
price, err = strconv.ParseFloat(tempResp.Orderbook.Bids[j][0], 64)
if err != nil {
return orderBook, err
if assetType == asset.PerpetualSwap {
item.OrderCount = tempResp.Bids[x].Count
}
orderBook.Bids = append(orderBook.Bids, orderbook.Item{
Price: price,
Amount: amount})
resp.Bids = append(resp.Bids, item)
}
err = orderBook.Process()
err = resp.Process()
if err != nil {
return orderBook, err
return nil, err
}
return orderbook.Get(c.Name, p, assetType)
}
@@ -332,15 +415,15 @@ func (c *Coinbene) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orde
// Coinbene exchange
func (c *Coinbene) GetAccountInfo() (exchange.AccountInfo, error) {
var info exchange.AccountInfo
data, err := c.GetUserBalance()
balance, err := c.GetAccountBalances()
if err != nil {
return info, err
}
var account exchange.Account
for key := range data.Data {
c := currency.NewCode(data.Data[key].Asset)
hold := data.Data[key].Reserved
available := data.Data[key].Available
for key := range balance {
c := currency.NewCode(balance[key].Asset)
hold := balance[key].Reserved
available := balance[key].Available
account.Currencies = append(account.Currencies,
exchange.AccountCurrencyInfo{CurrencyName: c,
TotalValue: hold + available,
@@ -374,15 +457,17 @@ func (c *Coinbene) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
fmt.Errorf("%s orderside is not supported by this exchange",
s.OrderSide)
}
if s.OrderType != order.Limit {
return resp, fmt.Errorf("only limit order is supported by this exchange")
}
tempResp, err := c.PlaceOrder(s.Price,
tempResp, err := c.PlaceSpotOrder(s.Price,
s.Amount,
c.FormatExchangeCurrency(s.Pair, asset.Spot).String(),
s.OrderSide.String(),
s.OrderType.String(),
s.ClientID)
s.ClientID,
0)
if err != nil {
return resp, err
}
@@ -399,27 +484,27 @@ func (c *Coinbene) ModifyOrder(action *order.Modify) (string, error) {
// CancelOrder cancels an order by its corresponding ID number
func (c *Coinbene) CancelOrder(order *order.Cancel) error {
_, err := c.RemoveOrder(order.OrderID)
_, err := c.CancelSpotOrder(order.OrderID)
return err
}
// CancelAllOrders cancels all orders associated with a currency pair
func (c *Coinbene) CancelAllOrders(orderCancellation *order.Cancel) (order.CancelAllResponse, error) {
var resp order.CancelAllResponse
tempMap := make(map[string]string)
orders, err := c.FetchOpenOrders(
orders, err := c.FetchOpenSpotOrders(
c.FormatExchangeCurrency(orderCancellation.CurrencyPair,
asset.Spot).String(),
)
if err != nil {
return resp, err
}
for x := range orders.OpenOrders {
_, err := c.RemoveOrder(orders.OpenOrders[x].OrderID)
tempMap := make(map[string]string)
for x := range orders {
_, err := c.CancelSpotOrder(orders[x].OrderID)
if err != nil {
tempMap[orders.OpenOrders[x].OrderID] = "Failed"
tempMap[orders[x].OrderID] = "Failed"
} else {
tempMap[orders.OpenOrders[x].OrderID] = "Success"
tempMap[orders[x].OrderID] = "Success"
}
}
resp.Status = tempMap
@@ -429,24 +514,24 @@ func (c *Coinbene) CancelAllOrders(orderCancellation *order.Cancel) (order.Cance
// GetOrderInfo returns information on a current open order
func (c *Coinbene) GetOrderInfo(orderID string) (order.Detail, error) {
var resp order.Detail
tempResp, err := c.FetchOrderInfo(orderID)
tempResp, err := c.FetchSpotOrderInfo(orderID)
if err != nil {
return resp, err
}
var t time.Time
resp.Exchange = c.Name
resp.ID = orderID
resp.CurrencyPair = currency.NewPairWithDelimiter(tempResp.Order.BaseAsset,
resp.CurrencyPair = currency.NewPairWithDelimiter(tempResp.BaseAsset,
"/",
tempResp.Order.QuoteAsset)
t, err = time.Parse(time.RFC3339, tempResp.Order.OrderTime)
tempResp.QuoteAsset)
t, err = time.Parse(time.RFC3339, tempResp.OrderTime)
if err != nil {
return resp, err
}
resp.Price = tempResp.Order.OrderPrice
resp.Price = tempResp.OrderPrice
resp.OrderDate = t
resp.ExecutedAmount = tempResp.Order.FilledAmount
resp.Fee = tempResp.Order.TotalFee
resp.ExecutedAmount = tempResp.FilledAmount
resp.Fee = tempResp.TotalFee
return resp, nil
}
@@ -480,47 +565,53 @@ func (c *Coinbene) GetWebsocket() (*wshandler.Websocket, error) {
// GetActiveOrders retrieves any orders that are active/open
func (c *Coinbene) GetActiveOrders(getOrdersRequest *order.GetOrdersRequest) ([]order.Detail, error) {
var resp []order.Detail
var tempResp order.Detail
var tempData OpenOrderResponse
if len(getOrdersRequest.Currencies) == 0 {
allPairs, err := c.GetAllPairs()
if err != nil {
return resp, err
return nil, err
}
for a := range allPairs.Data {
getOrdersRequest.Currencies = append(getOrdersRequest.Currencies, currency.NewPairFromString(allPairs.Data[a].Symbol))
for a := range allPairs {
getOrdersRequest.Currencies = append(getOrdersRequest.Currencies,
currency.NewPairFromString(allPairs[a].Symbol))
}
}
var err error
var resp []order.Detail
for x := range getOrdersRequest.Currencies {
tempData, err = c.FetchOpenOrders(
var tempData OrdersInfo
tempData, err = c.FetchOpenSpotOrders(
c.FormatExchangeCurrency(
getOrdersRequest.Currencies[x],
asset.Spot).String(),
)
if err != nil {
return resp, err
return nil, err
}
var t time.Time
for y := range tempData.OpenOrders {
for y := range tempData {
var tempResp order.Detail
tempResp.Exchange = c.Name
tempResp.CurrencyPair = getOrdersRequest.Currencies[x]
tempResp.OrderSide = order.Buy
if strings.EqualFold(tempData.OpenOrders[y].OrderType, order.Sell.String()) {
if strings.EqualFold(tempData[y].OrderType, order.Sell.String()) {
tempResp.OrderSide = order.Sell
}
t, err = time.Parse(time.RFC3339, tempData.OpenOrders[y].OrderTime)
var t time.Time
t, err = time.Parse(time.RFC3339, tempData[y].OrderTime)
if err != nil {
return resp, err
return nil, err
}
tempResp.OrderDate = t
tempResp.Status = order.Status(tempData.OpenOrders[y].OrderStatus)
tempResp.Price = tempData.OpenOrders[y].OrderPrice
tempResp.Amount = tempData.OpenOrders[y].Amount
tempResp.ExecutedAmount = tempData.OpenOrders[y].FilledAmount
tempResp.RemainingAmount = tempData.OpenOrders[y].Amount - tempData.OpenOrders[y].FilledAmount
tempResp.Fee = tempData.OpenOrders[y].TotalFee
tempResp.Status = order.Status(tempData[y].OrderStatus)
tempResp.Price = tempData[y].OrderPrice
tempResp.Amount = tempData[y].Amount
tempResp.ExecutedAmount = tempData[y].FilledAmount
tempResp.RemainingAmount = tempData[y].Amount - tempData[y].FilledAmount
tempResp.Fee = tempData[y].TotalFee
resp = append(resp, tempResp)
}
}
@@ -530,19 +621,21 @@ func (c *Coinbene) GetActiveOrders(getOrdersRequest *order.GetOrdersRequest) ([]
// GetOrderHistory retrieves account order information
// Can Limit response to specific order status
func (c *Coinbene) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest) ([]order.Detail, error) {
var resp []order.Detail
var tempResp order.Detail
var tempData ClosedOrderResponse
if len(getOrdersRequest.Currencies) == 0 {
allPairs, err := c.GetAllPairs()
if err != nil {
return resp, err
return nil, err
}
for a := range allPairs.Data {
getOrdersRequest.Currencies = append(getOrdersRequest.Currencies, currency.NewPairFromString(allPairs.Data[a].Symbol))
for a := range allPairs {
getOrdersRequest.Currencies = append(getOrdersRequest.Currencies,
currency.NewPairFromString(allPairs[a].Symbol))
}
}
var resp []order.Detail
var tempData OrdersInfo
var err error
for x := range getOrdersRequest.Currencies {
tempData, err = c.FetchClosedOrders(
c.FormatExchangeCurrency(
@@ -551,27 +644,31 @@ func (c *Coinbene) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest) ([]
"",
)
if err != nil {
return resp, err
return nil, err
}
var t time.Time
for y := range tempData.Data {
for y := range tempData {
var tempResp order.Detail
tempResp.Exchange = c.Name
tempResp.CurrencyPair = getOrdersRequest.Currencies[x]
tempResp.OrderSide = order.Buy
if strings.EqualFold(tempData.Data[y].OrderType, order.Sell.String()) {
if strings.EqualFold(tempData[y].OrderType, order.Sell.String()) {
tempResp.OrderSide = order.Sell
}
t, err = time.Parse(time.RFC3339, tempData.Data[y].OrderTime)
var t time.Time
t, err = time.Parse(time.RFC3339, tempData[y].OrderTime)
if err != nil {
return resp, err
return nil, err
}
tempResp.OrderDate = t
tempResp.Status = order.Status(tempData.Data[y].OrderStatus)
tempResp.Price = tempData.Data[y].OrderPrice
tempResp.Amount = tempData.Data[y].Amount
tempResp.ExecutedAmount = tempData.Data[y].FilledAmount
tempResp.RemainingAmount = tempData.Data[y].Amount - tempData.Data[y].FilledAmount
tempResp.Fee = tempData.Data[y].TotalFee
tempResp.Status = order.Status(tempData[y].OrderStatus)
tempResp.Price = tempData[y].OrderPrice
tempResp.Amount = tempData[y].Amount
tempResp.ExecutedAmount = tempData[y].FilledAmount
tempResp.RemainingAmount = tempData[y].Amount - tempData[y].FilledAmount
tempResp.Fee = tempData[y].TotalFee
resp = append(resp, tempResp)
}
}
@@ -590,9 +687,9 @@ func (c *Coinbene) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error
}
switch feeBuilder.IsMaker {
case true:
fee = feeBuilder.PurchasePrice * feeBuilder.Amount * tempData.Data.MakerFeeRate
fee = feeBuilder.PurchasePrice * feeBuilder.Amount * tempData.MakerFeeRate
case false:
fee = feeBuilder.PurchasePrice * feeBuilder.Amount * tempData.Data.TakerFeeRate
fee = feeBuilder.PurchasePrice * feeBuilder.Amount * tempData.TakerFeeRate
}
return fee, nil
}

View File

@@ -1494,7 +1494,7 @@
"pairs": {
"spot": {
"enabled": "BTC-USDT",
"available": "NKN-HT,EKT-USDT,EDU-ETH,BHD-HT,LOOM-BTC,18C-ETH,ALGO-USDT,EM-HT,AST-BTC,BFT-ETH,ZJLT-ETH,AKRO-USDT,GNX-BTC,LET-ETH,BCV-ETH,DASH-HT,AAC-BTC,BTT-ETH,EVX-BTC,PAI-ETH,SEELE-ETH,XTZ-BTC,ETN-ETH,REN-USDT,KMD-ETH,NEW-HT,EOS-BTC,STEEM-ETH,STK-ETH,HIT-BTC,DAC-BTC,CRO-HT,WICC-BTC,TNB-ETH,ELA-USDT,XLM-ETH,USDT-HUSD,WTC-USDT,RUFF-ETH,LXT-ETH,VIDY-HT,XZC-USDT,CTXC-BTC,DGB-ETH,NEO-USDT,LAMB-HT,NEXO-BTC,GT-USDT,UC-ETH,XVG-ETH,PAY-ETH,UUU-ETH,OCN-USDT,ARPA-BTC,DOCK-ETH,CRE-HT,CHAT-ETH,SSP-BTC,FAIR-BTC,TRIO-ETH,MTN-ETH,QSP-BTC,DOGE-ETH,HT-USDT,IDT-BTC,USDC-HUSD,BUT-ETH,BTS-BTC,KAN-BTC,POWR-ETH,ZIL-BTC,NAS-BTC,UIP-ETH,KCASH-BTC,SNC-ETH,OGO-HT,BCH-BTC,ABT-ETH,MXC-BTC,TOS-BTC,KNC-BTC,GTC-ETH,NAS-USDT,VSYS-BTC,BCD-BTC,RCCC-ETH,BTC-HUSD,QASH-ETH,CVCOIN-ETH,WXT-HT,ELF-ETH,VSYS-USDT,CVC-BTC,ZRX-ETH,RSR-HT,ZEC-USDT,BHT-BTC,COVA-ETH,TRX-BTC,SOC-ETH,ATOM-USDT,EGT-BTC,HC-USDT,ACT-BTC,APPC-ETH,ATP-USDT,YEE-BTC,RTE-BTC,NANO-BTC,XTZ-USDT,YEE-ETH,GNT-USDT,TOP-HT,REN-BTC,ONE-HT,NULS-USDT,XMR-BTC,VET-BTC,NODE-BTC,BTM-USDT,QTUM-BTC,SKM-HT,QTUM-ETH,CKB-BTC,PNT-BTC,ADA-USDT,LSK-ETH,GSC-BTC,FOR-HT,ARDR-ETH,XMR-USDT,EKO-BTC,ETC-HT,GVE-ETH,BIX-ETH,HIT-USDT,IOTA-BTC,OST-ETH,ELA-BTC,TOPC-BTC,BTM-BTC,SRN-BTC,GXC-USDT,POLY-ETH,WPR-ETH,GTC-BTC,UIP-USDT,SMT-USDT,ETH-HUSD,WAVES-USDT,CVC-ETH,SNT-BTC,EKT-BTC,EGCC-BTC,ELF-BTC,QASH-BTC,RCCC-BTC,YCC-ETH,PVT-HT,IRIS-ETH,OGO-USDT,REQ-BTC,RDN-BTC,NCASH-BTC,ADX-ETH,PAY-BTC,WICC-ETH,ENG-ETH,MUSK-BTC,HOT-ETH,BAT-ETH,THETA-ETH,HPT-USDT,DBC-BTC,EGT-HT,FOR-BTC,NODE-USDT,BLZ-BTC,SC-ETH,FTI-BTC,EDU-BTC,LUN-BTC,SWFTC-BTC,CMT-ETH,MTX-ETH,PVT-BTC,LOOM-ETH,MX-USDT,NULS-ETH,GET-BTC,DOCK-USDT,ETC-USDT,FOR-USDT,WAN-BTC,ETC-BTC,UGAS-BTC,EVX-ETH,BCV-BTC,LET-BTC,MX-BTC,TUSD-HUSD,TNT-BTC,XTZ-ETH,EOS-ETH,HPT-HT,MDS-ETH,MT-ETH,ONE-USDT,GRS-ETH,OCN-ETH,ZIL-USDT,18C-BTC,CNN-BTC,WAXP-BTC,OMG-USDT,LYM-BTC,LAMB-ETH,AE-BTC,IIC-BTC,XLM-USDT,PORTAL-ETH,TOP-USDT,ZEN-BTC,UTK-BTC,IOST-ETH,MEX-ETH,DATX-ETH,HT-HUSD,LBA-ETH,RCN-BTC,ZEC-BTC,DAT-ETH,ETH-USDT,HT-BTC,ITC-BTC,RBTC-BTC,SALT-ETH,PROPY-BTC,LINK-BTC,ONT-ETH,CVNT-BTC,ZLA-ETH,DCR-ETH,XZC-BTC,DASH-USDT,NCC-BTC,HPT-BTC,MANA-ETH,XMX-ETH,OGO-BTC,BCH-HT,SKM-USDT,MX-HT,POWR-BTC,NAS-ETH,SMT-BTC,CMT-BTC,ABT-BTC,SNC-BTC,KCASH-HT,PC-BTC,FTT-USDT,LTC-BTC,BSV-BTC,LAMB-BTC,ELF-USDT,VIDY-BTC,ARPA-HT,MDS-BTC,CKB-HT,CVCOIN-BTC,GXC-BTC,ADA-BTC,TT-HT,WAXP-ETH,ZRX-BTC,NPXS-ETH,LYM-ETH,RUFF-BTC,LXT-BTC,BOX-ETH,CRO-BTC,CTXC-ETH,CNN-ETH,MCO-BTC,BKBT-ETH,WAVES-BTC,NEXO-ETH,GAS-BTC,VSYS-HT,QUN-ETH,EOS-HT,DGD-BTC,SEELE-USDT,ENG-BTC,HC-ETH,UC-BTC,GNT-BTC,BLZ-ETH,BTT-TRX,DASH-BTC,CHAT-BTC,TRIO-BTC,MTN-BTC,DOCK-BTC,FSN-USDT,ETH-BTC,LINK-USDT,BHD-BTC,BIFI-BTC,SHE-BTC,ATOM-ETH,PHX-BTC,QSP-ETH,EGT-USDT,MTL-BTC,AE-USDT,BTG-BTC,NKN-USDT,PNT-ETH,ALGO-ETH,MANA-USDT,BHD-USDT,ZJLT-BTC,STEEM-USDT,WTC-ETH,PVT-USDT,SSP-ETH,SRN-ETH,ELA-ETH,AAC-ETH,BTT-BTC,THETA-USDT,TOPC-ETH,GNX-ETH,NKN-BTC,PAI-BTC,SEELE-BTC,BIX-USDT,HIT-ETH,CRE-USDT,ICX-BTC,DAC-ETH,EKT-ETH,TOP-BTC,CRO-USDT,APPC-BTC,PAI-USDT,LXT-USDT,EGCC-ETH,LBA-USDT,XLM-BTC,ITC-USDT,STEEM-BTC,CRE-BTC,SOC-BTC,TRX-ETH,GT-BTC,ONE-BTC,SNT-USDT,MDS-USDT,OMG-ETH,ACT-ETH,BTS-USDT,MEET-BTC,MEET-ETH,REN-ETH,RUFF-USDT,OMG-BTC,MAN-BTC,STORJ-USDT,MAN-ETH,NANO-ETH,XMR-ETH,DTA-ETH,WICC-USDT,LET-USDT,DTA-BTC,IOTA-USDT,AIDOC-ETH,VET-ETH,KCASH-ETH,RTE-ETH,BCX-BTC,UIP-BTC,RSR-BTC,BHT-HT,WXT-BTC,LTC-USDT,LOL-USDT,KAN-ETH,LTC-HUSD,XMX-BTC,FSN-BTC,SWFTC-ETH,LUN-ETH,BSV-USDT,NULS-BTC,IDT-ETH,ALGO-BTC,MTX-BTC,ZIL-ETH,GET-ETH,BSV-HUSD,WTC-BTC,SKM-BTC,AIDOC-BTC,WAN-ETH,ZRX-USDT,RSR-USDT,ACT-USDT,CNNS-HT,TNT-ETH,GRS-BTC,KNC-ETH,ICX-ETH,TOS-ETH,CMT-USDT,GT-HT,OCN-BTC,IOST-USDT,NEO-BTC,SOC-USDT,AE-ETH,COVA-BTC,EOS-USDT,REQ-ETH,ONT-USDT,BKBT-BTC,RDN-ETH,BAT-BTC,BOX-BTC,CNNS-BTC,UUU-BTC,ADX-BTC,LAMB-USDT,NCASH-ETH,MCO-ETH,VIDY-USDT,WAVES-ETH,QUN-BTC,CKB-USDT,DGB-BTC,XVG-BTC,HOT-BTC,LOL-BTC,MUSK-ETH,NODE-HT,SBTC-BTC,WXT-USDT,XRP-HT,HC-BTC,DGD-ETH,GAS-ETH,THETA-BTC,NANO-USDT,FTT-BTC,DBC-ETH,GNT-ETH,UGAS-ETH,TRX-USDT,FAIR-ETH,NEW-USDT,SC-BTC,XRP-USDT,KAN-USDT,FTI-ETH,DCR-USDT,SHE-ETH,PAX-HUSD,BTS-ETH,BUT-BTC,DOGE-BTC,VET-USDT,ATOM-BTC,BCH-USDT,GSC-ETH,PC-ETH,LSK-BTC,FTT-HT,EKO-ETH,ARDR-BTC,TT-BTC,BCH-HUSD,SMT-ETH,GVE-BTC,TT-USDT,DTA-USDT,EM-BTC,OST-BTC,AST-ETH,HB10-USDT,LTC-HT,XEM-USDT,IOTA-ETH,BHT-USDT,BTM-ETH,BTC-USDT,QTUM-USDT,BFT-BTC,KMD-BTC,POLY-BTC,ETN-BTC,WPR-BTC,ARPA-USDT,IRIS-USDT,STK-BTC,YCC-BTC,FSN-HT,ADA-ETH,AKRO-HT,STORJ-BTC,BAT-USDT,GXC-ETH,EM-USDT,ATP-BTC,IRIS-BTC,TNB-BTC,XEM-BTC,NPXS-BTC,HT-ETH,PORTAL-BTC,ITC-ETH,IIC-ETH,MT-HT,NEW-BTC,LBA-BTC,ZEN-ETH,RCN-ETH,IOST-BTC,UTK-ETH,MEX-BTC,UUU-USDT,LOL-HT,IOST-HT,ONT-BTC,MT-BTC,EOS-HUSD,XRP-HUSD,CVC-USDT,DAT-BTC,DOGE-USDT,PROPY-ETH,XRP-BTC,SALT-BTC,ZLA-BTC,LINK-ETH,CTXC-USDT,CNNS-USDT,DCR-BTC,CVNT-ETH,ATP-HT,AKRO-BTC,BIX-BTC,BTT-USDT,NCC-ETH,XZC-ETH,DATX-BTC,MANA-BTC"
"available": "PROPY-ETH,IOTA-BTC,UGAS-ETH,PAI-USDT,BSV-HUSD,MTX-ETH,BCH-BTC,LTC-HT,SOC-USDT,WXT-BTC,SALT-BTC,RCN-ETH,PNT-ETH,TT-USDT,AIDOC-ETH,BIX-BTC,OCN-USDT,QTUM-ETH,KCASH-ETH,SNT-USDT,LUN-BTC,QASH-BTC,ITC-BTC,NAS-BTC,XMR-BTC,TNT-ETH,UC-ETH,FAIR-BTC,PC-ETH,YEE-BTC,PAY-ETH,XMX-BTC,CRE-USDT,BAT-ETH,BHT-USDT,CKB-HT,LAMB-HT,AE-USDT,QUN-ETH,LYM-BTC,BCH-HT,BHT-BTC,RUFF-ETH,CNN-BTC,FOR-USDT,GTC-ETH,TRX-ETH,ELA-USDT,ACT-ETH,SMT-ETH,BUT-ETH,BCH-USDT,ICX-BTC,MEET-BTC,NCC-BTC,APPC-BTC,GVE-ETH,TNB-BTC,STEEM-ETH,18C-ETH,LBA-BTC,EKO-BTC,REQ-BTC,SOC-BTC,BOX-ETH,ELF-BTC,ZRX-ETH,LET-USDT,HT-BTC,TUSD-HUSD,EGCC-BTC,WTC-BTC,ATP-USDT,DOCK-USDT,PAI-BTC,ONT-ETH,IRIS-BTC,BTT-ETH,SC-BTC,XZC-BTC,LBA-USDT,HT-USDT,VET-ETH,KMD-ETH,SHE-ETH,PORTAL-BTC,ONE-BTC,BIX-USDT,RCCC-BTC,SKM-USDT,XTZ-ETH,SWFTC-BTC,RSR-BTC,LINK-ETH,DATX-BTC,HPT-HT,GET-ETH,BLZ-ETH,CTXC-USDT,CNNS-USDT,PVT-HT,ITC-USDT,LTC-BTC,NCASH-BTC,HOT-ETH,ADA-USDT,ADX-BTC,NODE-USDT,TRIO-BTC,GXC-ETH,SNT-BTC,FOR-BTC,DBC-BTC,UUU-USDT,CVCOIN-ETH,RSR-USDT,CRO-USDT,OCN-BTC,NEW-USDT,EGT-USDT,MANA-BTC,CMT-USDT,WXT-HT,XRP-BTC,MT-ETH,PAX-HUSD,LSK-ETH,IOTA-USDT,SRN-ETH,ZIL-ETH,ELF-USDT,LXT-ETH,LAMB-BTC,CRE-HT,CKB-BTC,XVG-BTC,BSV-BTC,BFT-BTC,WPR-ETH,HT-HUSD,POWR-BTC,MANA-ETH,ENG-ETH,ZJLT-ETH,SNC-ETH,ATOM-ETH,WICC-USDT,KAN-ETH,DGD-BTC,VSYS-HT,BCD-BTC,BTM-ETH,DOGE-USDT,MEX-BTC,BTG-BTC,DAC-ETH,DAT-BTC,GRS-ETH,ADX-ETH,EM-HT,GXC-USDT,CVC-BTC,OMG-ETH,SSP-ETH,OGO-HT,CMT-ETH,POLY-ETH,XZC-USDT,THETA-USDT,XEM-USDT,LOL-USDT,BCH-HUSD,GSC-BTC,DOGE-ETH,MDS-BTC,BTS-ETH,CTXC-BTC,MCO-BTC,BCX-BTC,ZLA-ETH,EKT-USDT,MAN-BTC,BLZ-BTC,ATOM-USDT,LOL-BTC,HPT-USDT,EM-BTC,EOS-USDT,WAN-BTC,GNT-BTC,CRO-BTC,MANA-USDT,SEELE-USDT,FSN-BTC,VIDY-HT,USDC-HUSD,LTC-HUSD,XRP-USDT,VSYS-BTC,STORJ-BTC,LOOM-ETH,SKM-BTC,LINK-USDT,TT-HT,QSP-ETH,ETN-BTC,FSN-HT,NODE-BTC,HC-USDT,PHX-BTC,XLM-BTC,RCCC-ETH,LTC-USDT,UUU-BTC,SEELE-ETH,PVT-BTC,HC-ETH,REN-ETH,KAN-USDT,EOS-ETH,BSV-USDT,BTS-USDT,KMD-BTC,OGO-USDT,THETA-ETH,MUSK-BTC,CNNS-HT,ETC-BTC,COVA-BTC,BTT-TRX,XMR-USDT,MTN-ETH,QUN-BTC,NAS-USDT,ELA-ETH,HIT-ETH,BTT-USDT,EKT-ETH,TOS-BTC,GAS-ETH,DCR-USDT,ONT-BTC,NEW-HT,NEXO-BTC,ETH-USDT,WXT-USDT,FOR-HT,ADA-BTC,EVX-ETH,VET-BTC,ZEC-USDT,NANO-ETH,IOST-HT,BCV-ETH,REN-USDT,NULS-ETH,ACT-USDT,LET-ETH,BTM-USDT,MEET-ETH,AKRO-HT,ARDR-BTC,DCR-ETH,NANO-USDT,BTC-HUSD,ALGO-BTC,IIC-ETH,BHD-BTC,KNC-ETH,ATP-BTC,ZRX-BTC,ABT-BTC,18C-BTC,XMR-ETH,WAXP-BTC,CVNT-BTC,MX-USDT,OST-ETH,NKN-BTC,TOPC-BTC,GNX-BTC,FTT-USDT,ONE-HT,DGB-ETH,NULS-USDT,DASH-BTC,UIP-BTC,KCASH-HT,WICC-ETH,EKO-ETH,EGT-HT,IRIS-USDT,STK-ETH,MXC-BTC,NAS-ETH,OMG-USDT,SMT-BTC,BUT-BTC,HIT-USDT,BAT-BTC,IRIS-ETH,NKN-HT,PC-BTC,TOP-USDT,GTC-BTC,LSK-BTC,ITC-ETH,DTA-BTC,HOT-BTC,BTT-BTC,FAIR-ETH,DOCK-ETH,QTUM-BTC,ZEN-BTC,ZIL-BTC,RCN-BTC,FTI-BTC,BHD-USDT,VIDY-USDT,LUN-ETH,DBC-ETH,TOPC-ETH,IIC-BTC,STEEM-USDT,IOTA-ETH,KCASH-BTC,RUFF-BTC,APPC-ETH,MT-BTC,SOC-ETH,GT-HT,PROPY-BTC,AIDOC-BTC,ACT-BTC,LYM-ETH,CHAT-BTC,SWFTC-ETH,ETH-BTC,UIP-USDT,UGAS-BTC,XRP-HUSD,ALGO-USDT,TNT-BTC,ONT-USDT,YEE-ETH,AKRO-BTC,TRX-USDT,OCN-ETH,SRN-BTC,DASH-USDT,XMX-ETH,NANO-BTC,QASH-ETH,EOS-HT,GT-BTC,XTZ-USDT,ARPA-USDT,SALT-ETH,BKBT-ETH,MTX-BTC,SMT-USDT,GXC-BTC,VIDY-BTC,FTT-HT,LAMB-ETH,TRX-BTC,TRIO-ETH,BFT-ETH,LINK-BTC,AE-ETH,NULS-BTC,BHD-HT,AST-ETH,NEO-USDT,EDU-BTC,CVCOIN-BTC,GVE-BTC,GET-BTC,ZRX-USDT,ELF-ETH,DATX-ETH,ADA-ETH,TOP-HT,NCASH-ETH,QTUM-USDT,ETC-HT,ZIL-USDT,TNB-ETH,BIX-ETH,SHE-BTC,PNT-BTC,BTC-USDT,PORTAL-ETH,WAVES-USDT,XZC-ETH,HT-ETH,POLY-BTC,MCO-ETH,MUSK-ETH,PAI-ETH,LXT-USDT,UTK-BTC,RTE-BTC,NCC-ETH,HB10-USDT,BOX-BTC,RDN-ETH,ARPA-BTC,LBA-ETH,CNN-ETH,AAC-ETH,XTZ-BTC,IDT-BTC,AKRO-USDT,IOST-BTC,GT-USDT,WAN-ETH,ETN-ETH,PVT-USDT,NEO-BTC,WAVES-ETH,ONE-USDT,ZEC-BTC,SKM-HT,IOST-ETH,NPXS-ETH,CVC-ETH,CMT-BTC,COVA-ETH,ARDR-ETH,RDN-BTC,DCR-BTC,REN-BTC,YCC-ETH,MX-HT,NEXO-ETH,XLM-ETH,YCC-BTC,ENG-BTC,CNNS-BTC,ZLA-BTC,QSP-BTC,MAN-ETH,UUU-ETH,ETH-HUSD,RTE-ETH,ATP-HT,BTM-BTC,DAC-BTC,TOS-ETH,LAMB-USDT,DASH-HT,NPXS-BTC,NEW-BTC,FTT-BTC,EOS-HUSD,GRS-BTC,POWR-ETH,VET-USDT,AAC-BTC,MX-BTC,MTN-BTC,XVG-ETH,GNX-ETH,SSP-BTC,WAVES-BTC,EGT-BTC,CTXC-ETH,IDT-ETH,STK-BTC,WICC-BTC,UTK-ETH,CRO-HT,LXT-BTC,GSC-ETH,OMG-BTC,XRP-HT,DGB-BTC,IOST-USDT,CVNT-ETH,GAS-BTC,HIT-BTC,CKB-USDT,ARPA-HT,RUFF-USDT,HC-BTC,WTC-ETH,MDS-USDT,ABT-ETH,ALGO-ETH,BIFI-BTC,KNC-BTC,TT-BTC,LET-BTC,NKN-USDT,PAY-BTC,DTA-USDT,AE-BTC,UC-BTC,VSYS-USDT,USDT-HUSD,EOS-BTC,STEEM-BTC,DOGE-BTC,NODE-HT,MDS-ETH,CRE-BTC,GNT-USDT,UIP-ETH,AST-BTC,XEM-BTC,ZEN-ETH,EDU-ETH,MEX-ETH,EKT-BTC,CVC-USDT,WAXP-ETH,REQ-ETH,OST-BTC,STORJ-USDT,SBTC-BTC,DGD-ETH,SC-ETH,WTC-USDT,THETA-BTC,DTA-ETH,BCV-BTC,SNC-BTC,RSR-HT,KAN-BTC,ELA-BTC,ATOM-BTC,BKBT-BTC,FSN-USDT,EM-USDT,WPR-BTC,TOP-BTC,BTS-BTC,EGCC-ETH,MTL-BTC,GNT-ETH,SEELE-BTC,EVX-BTC,FTI-ETH,BAT-USDT,MT-HT,LOL-HT,ICX-ETH,LOOM-BTC,ZJLT-BTC,XLM-USDT,OGO-BTC,DOCK-BTC,CHAT-ETH,DAT-ETH,ETC-USDT,HPT-BTC,BHT-HT"
}
}
},
@@ -1726,7 +1726,7 @@
"pairs": {
"spot": {
"enabled": "BTCUSD,BTCEUR,LTCBTC",
"available": "BTCAUD,NZDUSD,BTCUSD,EURUSD,GBPUSD,USDCHF,USDNGN,BTCJPY,BTCSGD,BTCNZD,BTCNGN,USDSGD,LTCBTC,USDHKD,BCHBTC,BTCEUR,USDJPY,BTCGBP,BTCCHF,AUDUSD,BTCCAD,ETHBTC,XRPBTC,USDCAD,BACETH"
"available": "USDCAD,USDSGD,BTCUSD,GBPUSD,LTCBTC,BCHBTC,USDJPY,USDCHF,EURUSD,ETHBTC,XRPBTC,USDHKD,BTCGBP,BTCNZD,NZDUSD,BTCNGN,BTCHKD,BTCAUD,BTCEUR,BTCCHF,AUDUSD,USDNGN,BACETH,BTCJPY,BTCCAD,BTCSGD"
}
}
},
@@ -1802,7 +1802,7 @@
"pairs": {
"spot": {
"enabled": "BTCARS,BTCAUD,BTCBRL,BTCCAD,BTCCHF,BTCDKK,BTCEUR,BTCGBP,BTCHKD,BTCILS,BTCINR,BTCMXN,BTCNOK,BTCNZD,BTCPLN,BTCRUB,BTCSEK,BTCSGD,BTCTHB,BTCUSD,BTCZAR",
"available": "BTCBYN,BTCPHP,BTCSAR,BTCMDL,BTCGTQ,BTCZMW,BTCXAF,BTCCDF,BTCKZT,BTCNGN,BTCRSD,BTCBOB,BTCBDT,BTCEUR,BTCAOA,BTCBAM,BTCUYU,BTCUAH,BTCETH,BTCGHS,BTCEGP,BTCPEN,BTCXOF,BTCAWG,BTCIRR,BTCUSD,BTCTWD,BTCAUD,BTCHRK,BTCPYG,BTCIDR,BTCKWD,BTCCAD,BTCRWF,BTCUGX,BTCSGD,BTCTTD,BTCXRP,BTCPKR,BTCMYR,BTCTHB,BTCLTC,BTCZAR,BTCPAB,BTCMAD,BTCGBP,BTCDOP,BTCTRY,BTCNOK,BTCTZS,BTCHKD,BTCCNY,BTCETB,BTCLKR,BTCVES,BTCMXN,BTCKES,BTCMWK,BTCJOD,BTCVND,BTCGEL,BTCARS,BTCRUB,BTCCOP,BTCCRC,BTCCLP,BTCRON,BTCQAR,BTCKRW,BTCDKK,BTCBRL,BTCPLN,BTCAED,BTCJPY,BTCILS,BTCNZD,BTCINR,BTCCZK,BTCSEK,BTCCHF"
"available": "BTCRUB,BTCRON,BTCXRP,BTCIRR,BTCKRW,BTCCNY,BTCRWF,BTCRSD,BTCOMR,BTCGTQ,BTCKES,BTCCOP,BTCJPY,BTCIDR,BTCBAM,BTCBDT,BTCDOP,BTCMWK,BTCUGX,BTCAOA,BTCAWG,BTCNZD,BTCGBP,BTCBOB,BTCCHF,BTCBYN,BTCLTC,BTCBRL,BTCTWD,BTCCRC,BTCPKR,BTCMXN,BTCVND,BTCDKK,BTCETB,BTCSEK,BTCAED,BTCTHB,BTCEUR,BTCARS,BTCUAH,BTCCAD,BTCPYG,BTCPEN,BTCUSD,BTCETH,BTCLKR,BTCTTD,BTCMYR,BTCHRK,BTCILS,BTCJOD,BTCKWD,BTCHKD,BTCTRY,BTCPLN,BTCZAR,BTCXOF,BTCSAR,BTCUYU,BTCTZS,BTCVES,BTCXAF,BTCGHS,BTCSGD,BTCNOK,BTCINR,BTCEGP,BTCAUD,BTCZMW,BTCGEL,BTCPAB,BTCCLP,BTCCZK,BTCMAD,BTCNGN,BTCQAR,BTCMDL,BTCCDF,BTCKZT,BTCPHP"
}
}
},
@@ -2409,22 +2409,33 @@
"websocketOrderbookBufferLimit": 5,
"baseCurrencies": "USD",
"currencyPairs": {
"requestFormat": {
"uppercase": true,
"delimiter": "/"
},
"configFormat": {
"uppercase": true,
"delimiter": "/"
},
"useGlobalFormat": true,
"assetTypes": [
"spot"
"spot",
"perpetualswap"
],
"pairs": {
"perpetualswap": {
"enabled": "BTC/USDT",
"available": "EOS/USDT,LTC/USDT,ETH/USDT,BTC/USDT",
"requestFormat": {
"uppercase": true
},
"configFormat": {
"uppercase": true,
"delimiter": "/"
}
},
"spot": {
"enabled": "BTC/USDT",
"available": "ABBC/BTC,ABBC/USDT,ABT/ETH,ABT/USDT,ABYSS/ETH,ACDC/BTC,ACDC/USDT,ADI/ETH,ADK/BTC,ADN/BTC,AE/BTC,AE/USDT,AIDOC/BTC,AION/BTC,AIPE/USDT,AIT/USDT,ALI/ETH,ALX/ETH,APL/ETH,ATX/BTC,BAAS/BTC,BABA/USDT,BAT/BTC,BCH/USDT,BETHER/ETH,BEZ/BTC,BGC/USDT,BKG/BTC,BNB/USDT,BNT/BTC,BOA/USDT,BSTN/ETH,BSV/USDT,BTC/USDT,BTNT/BTC,BTSC/BTC,BTT/USDT,BU/ETH,BVT/ETH,CAN/ETH,CCC/ETH,CCE/USDT,CEDEX/ETH,CENT/BTC,CFT/USDT,CMT/ETH,CMT/USDT,CNN/BTC,CNN/ETH,CNN/USDT,CONI/USDT,COSM/BTC,COSM/ETH,CPC/BTC,CREDO/ETH,CRN/BTC,CSCC/USDT,CS/ETH,CS/USDT,CTXC/ETH,CUST/USDT,CVC/BTC,CXP/BTC,DDAM/ETH,DDAM/USDT,DENT/BTC,DGD/BTC,DSCB/USDT,DTA/ETH,DUC/BTC,DVC/ETH,EBC/BTC,EBC/ETH,EBC/USDT,ECP/BTC,EDC/BTC,EDR/ETH,ELF/BTC,EMT/USDT,EOS/BTC,EOS/USDT,EQUAD/BTC,ETC/BTC,ETC/USDT,ETH/BTC,ETH/USDT,ETK/BTC,FAB/ETH,FCC/BTC,FND/ETH,FNKOS/ETH,FTN/BTC,FTN/USDT,FTT/BTC,FXT/ETH,GDC/BTC,GDC/ETH,GDC/USDT,GETX/ETH,GOM2/USDT,GRAM/USDT,GRN/BTC,GUSD/USDT,GVT/BTC,HAPPY/BTC,HDAC/BTC,HMB/USDT,HNB/USDT,HPT/ETH,HT/USDT,HUP/USDT,INCX/ETH,IOST/BTC,IOTE/USDT,ISR/ETH,IVY/ETH,JOB/BTC,KBC/BTC,KBC/USDT,KMD/BTC,KNT/ETH,KST/BTC,LAMB/USDT,LATX/BTC,LBK/BTC,LINK/BTC,LOOM/BTC,LTC/BTC,LTC/USDT,LUC/ETH,LUX/BTC,LVTC/ETH,MC/USDT,MIB/BTC,MINX/BTC,MINX/ETH,MOAC/USDT,MPL/BTC,MTC/BTC,MT/ETH,MTN/ETH,MT/USDT,MVL/ETH,MXM/ETH,MXM/USDT,MZG/USDT,NANO/BTC,NBAI/ETH,NEO/BTC,NEO/USDT,NFT/USDT,NOBS/BTC,NPXS/ETH,NPXS/USDT,NTY/ETH,ODC/USDT,OMG/BTC,OMX/ETH,OVC/ETH,OZX/ETH,PAT/ETH,PAX/USDT,PLAY/BTC,PMA/ETH,POLL/BTC,POLY/BTC,PPT/BTC,PSM/BTC,QKC/BTC,QTUM/BTC,QTUM/USDT,RBTC/BTC,RCOIN/BTC,RCOIN/USDT,REP/BTC,REV/BTC,RIF/BTC,RRW/USDT,SBT/USDT,SCC/BTC,SCO/BTC,SEN/BTC,SENC/ETH,SHE/BTC,SHVR/BTC,SIM/BTC,SKB/BTC,SKM/ETH,SKYM/USDT,SLT/ETH,SMARTUP/ETH,SMARTUP/USDT,SORO/USDT,SRCOIN/BTC,SRCOIN/ETH,STORJ/BTC,STQ/BTC,SWET/BTC,SWTC/USDT,TCT/BTC,TEMCO/USDT,TEN/BTC,TEN/ETH,TIB/BTC,TMTG/BTC,TOC/ETH,TOOS/USDT,TOSC/BTC,TRUE/ETH,TRX/BTC,TRX/USDT,TSL/BTC,UNI/USDT,UTNP/BTC,VBT/USDT,VEEN/BTC,VME/BTC,VME/ETH,VSC/ETH,VSF/BTC,W12/BTC,W12/ETH,WBL/BTC,WFX/BTC,XEM/BTC,XLM/BTC,XMCT/ETH,XMCT/USDT,XMR/BTC,XNK/ETH,XRP/BTC,XRP/USDT,XSR/USDT,YAP/BTC,YAP/USDT,YTA/USDT,ZAT/ETH,ZDC/BTC,ZEC/BTC,ZGC/BTC,ZRX/BTC"
"available": "ABBC/BTC,ABBC/USDT,ABT/ETH,ABT/USDT,ABYSS/ETH,ACDC/BTC,ACDC/USDT,ADI/ETH,ADK/BTC,ADN/BTC,AE/BTC,AE/USDT,AIDOC/BTC,AION/BTC,AIPE/USDT,AIT/USDT,ALI/ETH,ALX/ETH,APL/ETH,ATX/BTC,BAAS/BTC,BABA/USDT,BAT/BTC,BCH/USDT,BETHER/ETH,BEZ/BTC,BGC/USDT,BKG/BTC,BNB/USDT,BNT/BTC,BOA/USDT,BSTN/ETH,BSV/USDT,BTC/USDT,BTNT/BTC,BTSC/BTC,BTT/USDT,BU/ETH,BVT/ETH,CAN/ETH,CCC/ETH,CCE/USDT,CEDEX/ETH,CENT/BTC,CFT/USDT,CMT/ETH,CMT/USDT,CNN/BTC,CNN/ETH,CNN/USDT,CONI/USDT,COSM/BTC,COSM/ETH,CPC/BTC,CREDO/ETH,CRN/BTC,CSCC/USDT,CS/ETH,CS/USDT,CTXC/ETH,CUST/USDT,CVC/BTC,CXP/BTC,DDAM/ETH,DDAM/USDT,DENT/BTC,DGD/BTC,DSCB/USDT,DTA/ETH,DUC/BTC,DVC/ETH,EBC/BTC,EBC/ETH,EBC/USDT,ECP/BTC,EDC/BTC,EDR/ETH,ELF/BTC,EMT/USDT,EOS/BTC,EOS/USDT,EQUAD/BTC,ETC/BTC,ETC/USDT,ETH/BTC,ETH/USDT,ETK/BTC,FAB/ETH,FCC/BTC,FND/ETH,FNKOS/ETH,FTN/BTC,FTN/USDT,FTT/BTC,FXT/ETH,GDC/BTC,GDC/ETH,GDC/USDT,GETX/ETH,GOM2/USDT,GRAM/USDT,GRN/BTC,GUSD/USDT,GVT/BTC,HAPPY/BTC,HDAC/BTC,HMB/USDT,HNB/USDT,HPT/ETH,HT/USDT,HUP/USDT,INCX/ETH,IOST/BTC,IOTE/USDT,ISR/ETH,IVY/ETH,JOB/BTC,KBC/BTC,KBC/USDT,KMD/BTC,KNT/ETH,KST/BTC,LAMB/USDT,LATX/BTC,LBK/BTC,LINK/BTC,LOOM/BTC,LTC/BTC,LTC/USDT,LUC/ETH,LUX/BTC,LVTC/ETH,MC/USDT,MIB/BTC,MINX/BTC,MINX/ETH,MOAC/USDT,MPL/BTC,MTC/BTC,MT/ETH,MTN/ETH,MT/USDT,MVL/ETH,MXM/ETH,MXM/USDT,MZG/USDT,NANO/BTC,NBAI/ETH,NEO/BTC,NEO/USDT,NFT/USDT,NOBS/BTC,NPXS/ETH,NPXS/USDT,NTY/ETH,ODC/USDT,OMG/BTC,OMX/ETH,OVC/ETH,OZX/ETH,PAT/ETH,PAX/USDT,PLAY/BTC,PMA/ETH,POLL/BTC,POLY/BTC,PPT/BTC,PSM/BTC,QKC/BTC,QTUM/BTC,QTUM/USDT,RBTC/BTC,RCOIN/BTC,RCOIN/USDT,REP/BTC,REV/BTC,RIF/BTC,RRW/USDT,SBT/USDT,SCC/BTC,SCO/BTC,SEN/BTC,SENC/ETH,SHE/BTC,SHVR/BTC,SIM/BTC,SKB/BTC,SKM/ETH,SKYM/USDT,SLT/ETH,SMARTUP/ETH,SMARTUP/USDT,SORO/USDT,SRCOIN/BTC,SRCOIN/ETH,STORJ/BTC,SWET/BTC,SWTC/USDT,TCT/BTC,TEMCO/USDT,TEN/BTC,TEN/ETH,TIB/BTC,TMTG/BTC,TOC/ETH,TOOS/USDT,TOSC/BTC,TRUE/ETH,TRX/BTC,TRX/USDT,TSL/BTC,UNI/USDT,UTNP/BTC,VBT/USDT,VEEN/BTC,VME/BTC,VME/ETH,VSC/ETH,VSF/BTC,W12/BTC,W12/ETH,WBL/BTC,WFX/BTC,XEM/BTC,XLM/BTC,XMCT/ETH,XMCT/USDT,XMR/BTC,XNK/ETH,XRP/BTC,XRP/USDT,XSR/USDT,YAP/BTC,YAP/USDT,YTA/USDT,ZAT/ETH,ZDC/BTC,ZEC/BTC,ZGC/BTC,ZRX/BTC",
"requestFormat": {
"uppercase": true,
"delimiter": "/"
},
"configFormat": {
"uppercase": true,
"delimiter": "/"
}
}
}
},
@@ -2451,7 +2462,7 @@
"restCapabilities": {
"autoPairUpdates": true
},
"websocketAPI": false,
"websocketAPI": true,
"websocketCapabilities": {}
},
"enabled": {