mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 15:09:42 +00:00
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:
@@ -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"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -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"`
|
||||
}
|
||||
|
||||
@@ -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
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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"`
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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: ¤cy.PairFormat{
|
||||
Uppercase: true,
|
||||
Delimiter: "/",
|
||||
@@ -66,12 +68,22 @@ func (c *Coinbene) SetDefaults() {
|
||||
Uppercase: true,
|
||||
Delimiter: "/",
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
c.CurrencyPairs.Store(asset.PerpetualSwap, currency.PairStore{
|
||||
RequestFormat: ¤cy.PairFormat{
|
||||
Uppercase: true,
|
||||
},
|
||||
ConfigFormat: ¤cy.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
|
||||
}
|
||||
|
||||
41
testdata/configtest.json
vendored
41
testdata/configtest.json
vendored
@@ -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": {
|
||||
|
||||
Reference in New Issue
Block a user