mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-17 15:09:59 +00:00
Coinut code impovements and websocket pair formatting fixes
This commit is contained in:
@@ -285,10 +285,10 @@ func (c *CoinbasePro) GenerateDefaultSubscriptions() {
|
||||
continue
|
||||
}
|
||||
for j := range enabledCurrencies {
|
||||
enabledCurrencies[j].Delimiter = "-"
|
||||
subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
|
||||
Channel: channels[i],
|
||||
Currency: enabledCurrencies[j],
|
||||
Channel: channels[i],
|
||||
Currency: c.FormatExchangeCurrency(enabledCurrencies[j],
|
||||
asset.Spot),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -303,7 +303,8 @@ func (c *CoinbasePro) Subscribe(channelToSubscribe wshandler.WebsocketChannelSub
|
||||
{
|
||||
Name: channelToSubscribe.Channel,
|
||||
ProductIDs: []string{
|
||||
channelToSubscribe.Currency.String(),
|
||||
c.FormatExchangeCurrency(channelToSubscribe.Currency,
|
||||
asset.Spot).String(),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -329,7 +330,8 @@ func (c *CoinbasePro) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelS
|
||||
{
|
||||
Name: channelToSubscribe.Channel,
|
||||
ProductIDs: []string{
|
||||
channelToSubscribe.Currency.String(),
|
||||
c.FormatExchangeCurrency(channelToSubscribe.Currency,
|
||||
asset.Spot).String(),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -159,14 +159,22 @@ func (c *CoinbasePro) Start(wg *sync.WaitGroup) {
|
||||
// Run implements the coinbasepro wrapper
|
||||
func (c *CoinbasePro) Run() {
|
||||
if c.Verbose {
|
||||
log.Debugf(log.ExchangeSys, "%s Websocket: %s. (url: %s).\n", c.GetName(), common.IsEnabled(c.Websocket.IsEnabled()), coinbaseproWebsocketURL)
|
||||
log.Debugf(log.ExchangeSys, "%s Websocket: %s. (url: %s).\n",
|
||||
c.GetName(),
|
||||
common.IsEnabled(c.Websocket.IsEnabled()),
|
||||
coinbaseproWebsocketURL)
|
||||
c.PrintEnabledPairs()
|
||||
}
|
||||
|
||||
forceUpdate := false
|
||||
if !common.StringDataContains(c.GetEnabledPairs(asset.Spot).Strings(), c.GetPairFormat(asset.Spot, false).Delimiter) ||
|
||||
!common.StringDataContains(c.GetAvailablePairs(asset.Spot).Strings(), c.GetPairFormat(asset.Spot, false).Delimiter) {
|
||||
enabledPairs := currency.NewPairsFromStrings([]string{fmt.Sprintf("BTC%vUSD", c.GetPairFormat(asset.Spot, false).Delimiter)})
|
||||
delim := c.GetPairFormat(asset.Spot, false).Delimiter
|
||||
if !common.StringDataContains(c.CurrencyPairs.GetPairs(asset.Spot,
|
||||
true).Strings(), delim) ||
|
||||
!common.StringDataContains(c.CurrencyPairs.GetPairs(asset.Spot,
|
||||
false).Strings(), delim) {
|
||||
enabledPairs := currency.NewPairsFromStrings(
|
||||
[]string{fmt.Sprintf("BTC%sUSD", delim)},
|
||||
)
|
||||
log.Warn(log.ExchangeSys,
|
||||
"Enabled pairs for CoinbasePro reset due to config upgrade, please enable the ones you would like to use again")
|
||||
forceUpdate = true
|
||||
@@ -294,7 +302,8 @@ func (c *CoinbasePro) FetchOrderbook(p currency.Pair, assetType asset.Item) (ord
|
||||
// UpdateOrderbook updates and returns the orderbook for a currency pair
|
||||
func (c *CoinbasePro) UpdateOrderbook(p currency.Pair, assetType asset.Item) (orderbook.Base, error) {
|
||||
var orderBook orderbook.Base
|
||||
orderbookNew, err := c.GetOrderbook(c.FormatExchangeCurrency(p, assetType).String(), 2)
|
||||
orderbookNew, err := c.GetOrderbook(c.FormatExchangeCurrency(p,
|
||||
assetType).String(), 2)
|
||||
if err != nil {
|
||||
return orderBook, err
|
||||
}
|
||||
@@ -324,8 +333,7 @@ func (c *CoinbasePro) UpdateOrderbook(p currency.Pair, assetType asset.Item) (or
|
||||
// GetFundingHistory returns funding history, deposits and
|
||||
// withdrawals
|
||||
func (c *CoinbasePro) GetFundingHistory() ([]exchange.FundHistory, error) {
|
||||
var fundHistory []exchange.FundHistory
|
||||
return fundHistory, common.ErrFunctionNotSupported
|
||||
return nil, common.ErrFunctionNotSupported
|
||||
}
|
||||
|
||||
// GetExchangeHistory returns historic trade data since exchange opening.
|
||||
@@ -352,7 +360,7 @@ func (c *CoinbasePro) SubmitOrder(order *exchange.OrderSubmission) (exchange.Sub
|
||||
order.Amount,
|
||||
order.Amount,
|
||||
order.OrderSide.ToString(),
|
||||
order.Pair.String(),
|
||||
c.FormatExchangeCurrency(order.Pair, asset.Spot).String(),
|
||||
"")
|
||||
case exchange.LimitOrderType:
|
||||
response, err = c.PlaceLimitOrder("",
|
||||
@@ -361,7 +369,7 @@ func (c *CoinbasePro) SubmitOrder(order *exchange.OrderSubmission) (exchange.Sub
|
||||
order.OrderSide.ToString(),
|
||||
"",
|
||||
"",
|
||||
order.Pair.String(),
|
||||
c.FormatExchangeCurrency(order.Pair, asset.Spot).String(),
|
||||
"",
|
||||
false)
|
||||
default:
|
||||
|
||||
@@ -42,11 +42,29 @@ const (
|
||||
coinutStatusOK = "OK"
|
||||
)
|
||||
|
||||
var (
|
||||
errLookupInstrumentID = errors.New("unable to lookup instrument ID")
|
||||
errLookupInstrumentCurrency = errors.New("unable to lookup instrument")
|
||||
)
|
||||
|
||||
// COINUT is the overarching type across the coinut package
|
||||
type COINUT struct {
|
||||
exchange.Base
|
||||
WebsocketConn *wshandler.WebsocketConnection
|
||||
InstrumentMap map[string]int
|
||||
instrumentMap instrumentMap
|
||||
}
|
||||
|
||||
// SeedInstruments seeds the instrument map
|
||||
func (c *COINUT) SeedInstruments() error {
|
||||
i, err := c.GetInstruments()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, y := range i.Instruments {
|
||||
c.instrumentMap.Seed(y[0].Base+y[0].Quote, y[0].InstID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetInstruments returns instruments
|
||||
@@ -54,21 +72,19 @@ func (c *COINUT) GetInstruments() (Instruments, error) {
|
||||
var result Instruments
|
||||
params := make(map[string]interface{})
|
||||
params["sec_type"] = strings.ToUpper(asset.Spot.String())
|
||||
|
||||
return result, c.SendHTTPRequest(coinutInstruments, params, false, &result)
|
||||
}
|
||||
|
||||
// GetInstrumentTicker returns a ticker for a specific instrument
|
||||
func (c *COINUT) GetInstrumentTicker(instrumentID int) (Ticker, error) {
|
||||
func (c *COINUT) GetInstrumentTicker(instrumentID int64) (Ticker, error) {
|
||||
var result Ticker
|
||||
params := make(map[string]interface{})
|
||||
params["inst_id"] = instrumentID
|
||||
|
||||
return result, c.SendHTTPRequest(coinutTicker, params, false, &result)
|
||||
}
|
||||
|
||||
// GetInstrumentOrderbook returns the orderbooks for a specific instrument
|
||||
func (c *COINUT) GetInstrumentOrderbook(instrumentID, limit int) (Orderbook, error) {
|
||||
func (c *COINUT) GetInstrumentOrderbook(instrumentID, limit int64) (Orderbook, error) {
|
||||
var result Orderbook
|
||||
params := make(map[string]interface{})
|
||||
params["inst_id"] = instrumentID
|
||||
@@ -96,7 +112,7 @@ func (c *COINUT) GetUserBalance() (UserBalance, error) {
|
||||
}
|
||||
|
||||
// NewOrder places a new order on the exchange
|
||||
func (c *COINUT) NewOrder(instrumentID int, quantity, price float64, buy bool, orderID uint32) (interface{}, error) {
|
||||
func (c *COINUT) NewOrder(instrumentID int64, quantity, price float64, buy bool, orderID uint32) (interface{}, error) {
|
||||
var result interface{}
|
||||
params := make(map[string]interface{})
|
||||
params["inst_id"] = instrumentID
|
||||
@@ -133,21 +149,20 @@ func (c *COINUT) NewOrders(orders []Order) ([]OrdersBase, error) {
|
||||
}
|
||||
|
||||
// GetOpenOrders returns a list of open order and relevant information
|
||||
func (c *COINUT) GetOpenOrders(instrumentID int) (GetOpenOrdersResponse, error) {
|
||||
func (c *COINUT) GetOpenOrders(instrumentID int64) (GetOpenOrdersResponse, error) {
|
||||
var result GetOpenOrdersResponse
|
||||
params := make(map[string]interface{})
|
||||
params["inst_id"] = instrumentID
|
||||
|
||||
return result, c.SendHTTPRequest(coinutOrdersOpen, params, true, &result)
|
||||
}
|
||||
|
||||
// CancelExistingOrder cancels a specific order and returns if it was actioned
|
||||
func (c *COINUT) CancelExistingOrder(instrumentID, orderID int) (bool, error) {
|
||||
func (c *COINUT) CancelExistingOrder(instrumentID, orderID int64) (bool, error) {
|
||||
var result GenericResponse
|
||||
params := make(map[string]interface{})
|
||||
type Request struct {
|
||||
InstrumentID int `json:"inst_id"`
|
||||
OrderID int `json:"order_id"`
|
||||
InstrumentID int64 `json:"inst_id"`
|
||||
OrderID int64 `json:"order_id"`
|
||||
}
|
||||
|
||||
var entry = Request{
|
||||
@@ -182,7 +197,7 @@ func (c *COINUT) CancelOrders(orders []CancelOrders) (CancelOrdersResponse, erro
|
||||
}
|
||||
|
||||
// GetTradeHistory returns trade history for a specific instrument.
|
||||
func (c *COINUT) GetTradeHistory(instrumentID, start, limit int) (TradeHistory, error) {
|
||||
func (c *COINUT) GetTradeHistory(instrumentID, start, limit int64) (TradeHistory, error) {
|
||||
var result TradeHistory
|
||||
params := make(map[string]interface{})
|
||||
params["inst_id"] = instrumentID
|
||||
|
||||
@@ -76,9 +76,6 @@ func setupWSTestAuth(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
instrumentListByString = make(map[string]int64)
|
||||
instrumentListByString[currency.NewPair(currency.LTC, currency.BTC).String()] = 1
|
||||
wsSetupRan = true
|
||||
}
|
||||
|
||||
@@ -89,6 +86,18 @@ func TestGetInstruments(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSeedInstruments(t *testing.T) {
|
||||
err := c.SeedInstruments()
|
||||
if err != nil {
|
||||
// No point checking the next condition
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(c.instrumentMap.GetInstrumentIDs()) == 0 {
|
||||
t.Error("instrument map hasn't been seeded")
|
||||
}
|
||||
}
|
||||
|
||||
func setFeeBuilder() *exchange.FeeBuilder {
|
||||
return &exchange.FeeBuilder{
|
||||
Amount: 1,
|
||||
@@ -543,3 +552,89 @@ func TestWsAuthGetOpenOrders(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCurrencyMapIsLoaded(t *testing.T) {
|
||||
t.Parallel()
|
||||
var i instrumentMap
|
||||
if l := i.IsLoaded(); l {
|
||||
t.Error("unexpected result")
|
||||
}
|
||||
|
||||
i.Seed("BTCUSD", 1337)
|
||||
if l := i.IsLoaded(); !l {
|
||||
t.Error("unexpected result")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCurrencyMapSeed(t *testing.T) {
|
||||
t.Parallel()
|
||||
var i instrumentMap
|
||||
|
||||
// Test non-seeded lookups
|
||||
if id := i.LookupInstrument(1234); id != "" {
|
||||
t.Error("unexpected result")
|
||||
}
|
||||
if id := i.LookupID("BLAH"); id != 0 {
|
||||
t.Error("unexpected result")
|
||||
}
|
||||
|
||||
// Test seeded lookups
|
||||
i.Seed("BTCUSD", 1337)
|
||||
if id := i.LookupID("BTCUSD"); id != 1337 {
|
||||
t.Error("unexpected result")
|
||||
}
|
||||
if id := i.LookupInstrument(1337); id != "BTCUSD" {
|
||||
t.Error("unexpected result")
|
||||
}
|
||||
|
||||
// Test invalid lookups
|
||||
if id := i.LookupInstrument(1234); id != "" {
|
||||
t.Error("unexpected result")
|
||||
}
|
||||
if id := i.LookupID("BLAH"); id != 0 {
|
||||
t.Error("unexpected result")
|
||||
}
|
||||
|
||||
// Test seeding existing item
|
||||
i.Seed("BTCUSD", 1234)
|
||||
if id := i.LookupID("BTCUSD"); id != 1337 {
|
||||
t.Error("unexpected result")
|
||||
}
|
||||
if id := i.LookupInstrument(1337); id != "BTCUSD" {
|
||||
t.Error("unexpected result")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCurrencyMapInstrumentIDs(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var i instrumentMap
|
||||
if r := i.GetInstrumentIDs(); len(r) > 0 {
|
||||
t.Error("non initialised instrument map shouldn't return any ids")
|
||||
}
|
||||
|
||||
// Seed the instrument map
|
||||
i.Seed("BTCUSD", 1234)
|
||||
i.Seed("LTCUSD", 1337)
|
||||
|
||||
f := func(ids []int64, target int64) bool {
|
||||
for x := range ids {
|
||||
if ids[x] == target {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Test 2 valid instruments and one invalid
|
||||
ids := i.GetInstrumentIDs()
|
||||
if r := f(ids, 1234); !r {
|
||||
t.Error("unexpected result")
|
||||
}
|
||||
if r := f(ids, 1337); !r {
|
||||
t.Error("unexpected result")
|
||||
}
|
||||
if r := f(ids, 4321); r {
|
||||
t.Error("unexpected result")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package coinut
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
)
|
||||
@@ -17,7 +20,7 @@ type GenericResponse struct {
|
||||
type InstrumentBase struct {
|
||||
Base string `json:"base"`
|
||||
DecimalPlaces int `json:"decimal_places"`
|
||||
InstID int `json:"inst_id"`
|
||||
InstID int64 `json:"inst_id"`
|
||||
Quote string `json:"quote"`
|
||||
}
|
||||
|
||||
@@ -665,3 +668,85 @@ type WsGetAccountBalanceResponse struct {
|
||||
Status []string `json:"status"`
|
||||
TransID int64 `json:"trans_id"`
|
||||
}
|
||||
|
||||
type instrumentMap struct {
|
||||
Instruments map[string]int64
|
||||
Loaded bool
|
||||
m sync.Mutex
|
||||
}
|
||||
|
||||
// IsLoaded returns whether or not the instrument map has been seeded
|
||||
func (i *instrumentMap) IsLoaded() bool {
|
||||
i.m.Lock()
|
||||
defer i.m.Unlock()
|
||||
return i.Loaded
|
||||
}
|
||||
|
||||
// Seed seeds the instrument map
|
||||
func (i *instrumentMap) Seed(currency string, id int64) {
|
||||
i.m.Lock()
|
||||
defer i.m.Unlock()
|
||||
|
||||
if !i.Loaded {
|
||||
i.Instruments = make(map[string]int64)
|
||||
}
|
||||
|
||||
// check to see if the instrument already exists
|
||||
_, ok := i.Instruments[currency]
|
||||
if ok {
|
||||
return
|
||||
}
|
||||
|
||||
i.Instruments[currency] = id
|
||||
i.Loaded = true
|
||||
}
|
||||
|
||||
// LookupInstrument looks up an instrument based on an id
|
||||
func (i *instrumentMap) LookupInstrument(id int64) string {
|
||||
i.m.Lock()
|
||||
defer i.m.Unlock()
|
||||
|
||||
if !i.Loaded {
|
||||
return ""
|
||||
}
|
||||
|
||||
for k, v := range i.Instruments {
|
||||
if v == id {
|
||||
return k
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// LookupID looks up an ID based on a string
|
||||
func (i *instrumentMap) LookupID(currency string) int64 {
|
||||
i.m.Lock()
|
||||
defer i.m.Unlock()
|
||||
|
||||
if !i.Loaded {
|
||||
return 0
|
||||
}
|
||||
|
||||
for k, v := range i.Instruments {
|
||||
if strings.EqualFold(currency, k) {
|
||||
return v
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// GetInstrumentIDs returns a list of IDs
|
||||
func (i *instrumentMap) GetInstrumentIDs() []int64 {
|
||||
i.m.Lock()
|
||||
defer i.m.Unlock()
|
||||
|
||||
if !i.Loaded {
|
||||
return nil
|
||||
}
|
||||
|
||||
var instruments []int64
|
||||
for _, x := range i.Instruments {
|
||||
instruments = append(instruments, x)
|
||||
}
|
||||
return instruments
|
||||
}
|
||||
|
||||
@@ -18,14 +18,15 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wsorderbook"
|
||||
)
|
||||
|
||||
const coinutWebsocketURL = "wss://wsapi.coinut.com"
|
||||
const coinutWebsocketRateLimit = 30
|
||||
const (
|
||||
coinutWebsocketURL = "wss://wsapi.coinut.com"
|
||||
coinutWebsocketRateLimit = 30
|
||||
)
|
||||
|
||||
var nNonce map[int64]string
|
||||
var channels map[string]chan []byte
|
||||
var instrumentListByString map[string]int64
|
||||
var instrumentListByCode map[int64]string
|
||||
var populatedList bool
|
||||
var (
|
||||
channels map[string]chan []byte
|
||||
wsInstrumentMap instrumentMap
|
||||
)
|
||||
|
||||
// NOTE for speed considerations
|
||||
// wss://wsapi-as.coinut.com
|
||||
@@ -44,14 +45,11 @@ func (c *COINUT) WsConnect() error {
|
||||
}
|
||||
go c.WsHandleData()
|
||||
|
||||
if !populatedList {
|
||||
instrumentListByString = make(map[string]int64)
|
||||
instrumentListByCode = make(map[int64]string)
|
||||
if !wsInstrumentMap.IsLoaded() {
|
||||
err = c.WsSetInstrumentList()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
populatedList = true
|
||||
}
|
||||
c.wsAuthenticate()
|
||||
c.GenerateDefaultSubscriptions()
|
||||
@@ -137,7 +135,7 @@ func (c *COINUT) wsProcessResponse(resp []byte) {
|
||||
c.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
currencyPair := instrumentListByCode[ticker.InstID]
|
||||
currencyPair := wsInstrumentMap.LookupInstrument(ticker.InstID)
|
||||
c.Websocket.DataHandler <- wshandler.TickerData{
|
||||
Exchange: c.Name,
|
||||
Volume: ticker.Volume,
|
||||
@@ -147,7 +145,9 @@ func (c *COINUT) wsProcessResponse(resp []byte) {
|
||||
Last: ticker.Last,
|
||||
Timestamp: time.Unix(0, ticker.Timestamp),
|
||||
AssetType: asset.Spot,
|
||||
Pair: currency.NewPairFromString(currencyPair),
|
||||
Pair: currency.NewPairFromFormattedPairs(currencyPair,
|
||||
c.GetEnabledPairs(asset.Spot),
|
||||
c.GetPairFormat(asset.Spot, true)),
|
||||
}
|
||||
|
||||
case "inst_order_book":
|
||||
@@ -162,11 +162,13 @@ func (c *COINUT) wsProcessResponse(resp []byte) {
|
||||
c.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
currencyPair := instrumentListByCode[orderbooksnapshot.InstID]
|
||||
currencyPair := wsInstrumentMap.LookupInstrument(orderbooksnapshot.InstID)
|
||||
c.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
|
||||
Exchange: c.GetName(),
|
||||
Asset: asset.Spot,
|
||||
Pair: currency.NewPairFromString(currencyPair),
|
||||
Pair: currency.NewPairFromFormattedPairs(currencyPair,
|
||||
c.GetEnabledPairs(asset.Spot),
|
||||
c.GetPairFormat(asset.Spot, true)),
|
||||
}
|
||||
case "inst_order_book_update":
|
||||
var orderbookUpdate WsOrderbookUpdate
|
||||
@@ -180,11 +182,13 @@ func (c *COINUT) wsProcessResponse(resp []byte) {
|
||||
c.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
currencyPair := instrumentListByCode[orderbookUpdate.InstID]
|
||||
currencyPair := wsInstrumentMap.LookupInstrument(orderbookUpdate.InstID)
|
||||
c.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
|
||||
Exchange: c.GetName(),
|
||||
Asset: asset.Spot,
|
||||
Pair: currency.NewPairFromString(currencyPair),
|
||||
Pair: currency.NewPairFromFormattedPairs(currencyPair,
|
||||
c.GetEnabledPairs(asset.Spot),
|
||||
c.GetPairFormat(asset.Spot, true)),
|
||||
}
|
||||
case "inst_trade":
|
||||
var tradeSnap WsTradeSnapshot
|
||||
@@ -201,14 +205,16 @@ func (c *COINUT) wsProcessResponse(resp []byte) {
|
||||
c.Websocket.DataHandler <- err
|
||||
return
|
||||
}
|
||||
currencyPair := instrumentListByCode[tradeUpdate.InstID]
|
||||
currencyPair := wsInstrumentMap.LookupInstrument(tradeUpdate.InstID)
|
||||
c.Websocket.DataHandler <- wshandler.TradeData{
|
||||
Timestamp: time.Unix(tradeUpdate.Timestamp, 0),
|
||||
CurrencyPair: currency.NewPairFromString(currencyPair),
|
||||
AssetType: asset.Spot,
|
||||
Exchange: c.GetName(),
|
||||
Price: tradeUpdate.Price,
|
||||
Side: tradeUpdate.Side,
|
||||
Timestamp: time.Unix(tradeUpdate.Timestamp, 0),
|
||||
CurrencyPair: currency.NewPairFromFormattedPairs(currencyPair,
|
||||
c.GetEnabledPairs(asset.Spot),
|
||||
c.GetPairFormat(asset.Spot, true)),
|
||||
AssetType: asset.Spot,
|
||||
Exchange: c.GetName(),
|
||||
Price: tradeUpdate.Price,
|
||||
Side: tradeUpdate.Side,
|
||||
}
|
||||
default:
|
||||
if incoming.Nonce > 0 {
|
||||
@@ -247,11 +253,10 @@ func (c *COINUT) WsSetInstrumentList() error {
|
||||
return err
|
||||
}
|
||||
for curr, data := range list.Spot {
|
||||
instrumentListByString[curr] = data[0].InstID
|
||||
instrumentListByCode[data[0].InstID] = curr
|
||||
wsInstrumentMap.Seed(curr, data[0].InstID)
|
||||
}
|
||||
if len(instrumentListByString) == 0 || len(instrumentListByCode) == 0 {
|
||||
return errors.New("instrument lists failed to populate")
|
||||
if len(wsInstrumentMap.GetInstrumentIDs()) == 0 {
|
||||
return errors.New("instrument list failed to populate")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -277,7 +282,11 @@ func (c *COINUT) WsProcessOrderbookSnapshot(ob *WsOrderbookSnapshot) error {
|
||||
var newOrderBook orderbook.Base
|
||||
newOrderBook.Asks = asks
|
||||
newOrderBook.Bids = bids
|
||||
newOrderBook.Pair = currency.NewPairFromString(instrumentListByCode[ob.InstID])
|
||||
newOrderBook.Pair = currency.NewPairFromFormattedPairs(
|
||||
wsInstrumentMap.LookupInstrument(ob.InstID),
|
||||
c.GetEnabledPairs(asset.Spot),
|
||||
c.GetPairFormat(asset.Spot, true),
|
||||
)
|
||||
newOrderBook.AssetType = asset.Spot
|
||||
|
||||
return c.Websocket.Orderbook.LoadSnapshot(&newOrderBook, false)
|
||||
@@ -285,7 +294,11 @@ func (c *COINUT) WsProcessOrderbookSnapshot(ob *WsOrderbookSnapshot) error {
|
||||
|
||||
// WsProcessOrderbookUpdate process an orderbook update
|
||||
func (c *COINUT) WsProcessOrderbookUpdate(update *WsOrderbookUpdate) error {
|
||||
p := currency.NewPairFromString(instrumentListByCode[update.InstID])
|
||||
p := currency.NewPairFromFormattedPairs(
|
||||
wsInstrumentMap.LookupInstrument(update.InstID),
|
||||
c.GetEnabledPairs(asset.Spot),
|
||||
c.GetPairFormat(asset.Spot, true),
|
||||
)
|
||||
bufferUpdate := &wsorderbook.WebsocketOrderbookUpdate{
|
||||
CurrencyPair: p,
|
||||
UpdateID: update.TransID,
|
||||
@@ -318,8 +331,9 @@ func (c *COINUT) GenerateDefaultSubscriptions() {
|
||||
// Subscribe sends a websocket message to receive data from the channel
|
||||
func (c *COINUT) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
|
||||
subscribe := wsRequest{
|
||||
Request: channelToSubscribe.Channel,
|
||||
InstID: instrumentListByString[channelToSubscribe.Currency.String()],
|
||||
Request: channelToSubscribe.Channel,
|
||||
InstID: wsInstrumentMap.LookupID(c.FormatExchangeCurrency(channelToSubscribe.Currency,
|
||||
asset.Spot).String()),
|
||||
Subscribe: true,
|
||||
Nonce: c.WebsocketConn.GenerateMessageID(false),
|
||||
}
|
||||
@@ -329,8 +343,9 @@ func (c *COINUT) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscrip
|
||||
// Unsubscribe sends a websocket message to stop receiving data from the channel
|
||||
func (c *COINUT) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
|
||||
subscribe := wsRequest{
|
||||
Request: channelToSubscribe.Channel,
|
||||
InstID: instrumentListByString[channelToSubscribe.Currency.String()],
|
||||
Request: channelToSubscribe.Channel,
|
||||
InstID: wsInstrumentMap.LookupID(c.FormatExchangeCurrency(channelToSubscribe.Currency,
|
||||
asset.Spot).String()),
|
||||
Subscribe: false,
|
||||
Nonce: c.WebsocketConn.GenerateMessageID(false),
|
||||
}
|
||||
@@ -419,7 +434,7 @@ func (c *COINUT) wsSubmitOrder(order *WsSubmitOrderParameters) (*WsStandardOrder
|
||||
var orderSubmissionRequest WsSubmitOrderRequest
|
||||
orderSubmissionRequest.Request = "new_order"
|
||||
orderSubmissionRequest.Nonce = c.WebsocketConn.GenerateMessageID(false)
|
||||
orderSubmissionRequest.InstID = instrumentListByString[curr]
|
||||
orderSubmissionRequest.InstID = wsInstrumentMap.LookupID(curr)
|
||||
orderSubmissionRequest.Qty = order.Amount
|
||||
orderSubmissionRequest.Price = order.Price
|
||||
orderSubmissionRequest.Side = string(order.Side)
|
||||
@@ -530,7 +545,7 @@ func (c *COINUT) wsSubmitOrders(orders []WsSubmitOrderParameters) ([]WsStandardO
|
||||
Qty: orders[i].Amount,
|
||||
Price: orders[i].Price,
|
||||
Side: string(orders[i].Side),
|
||||
InstID: instrumentListByString[curr],
|
||||
InstID: wsInstrumentMap.LookupID(curr),
|
||||
ClientOrdID: i + 1,
|
||||
})
|
||||
}
|
||||
@@ -567,7 +582,7 @@ func (c *COINUT) wsSubmitOrders(orders []WsSubmitOrderParameters) ([]WsStandardO
|
||||
if len(standardOrder.Reasons) > 0 && standardOrder.Reasons[0] != "" {
|
||||
errors = append(errors, fmt.Errorf("%v order submission failed for currency %v and orderID %v, message %v ",
|
||||
c.Name,
|
||||
instrumentListByCode[standardOrder.InstID],
|
||||
wsInstrumentMap.LookupInstrument(standardOrder.InstID),
|
||||
standardOrder.OrderID,
|
||||
standardOrder.Reasons[0]))
|
||||
|
||||
@@ -587,7 +602,7 @@ func (c *COINUT) wsGetOpenOrders(p currency.Pair) error {
|
||||
var openOrdersRequest WsGetOpenOrdersRequest
|
||||
openOrdersRequest.Request = "user_open_orders"
|
||||
openOrdersRequest.Nonce = c.WebsocketConn.GenerateMessageID(false)
|
||||
openOrdersRequest.InstID = instrumentListByString[curr]
|
||||
openOrdersRequest.InstID = wsInstrumentMap.LookupID(curr)
|
||||
|
||||
resp, err := c.WebsocketConn.SendMessageReturnResponse(openOrdersRequest.Nonce, openOrdersRequest)
|
||||
if err != nil {
|
||||
@@ -613,7 +628,7 @@ func (c *COINUT) wsCancelOrder(cancellation WsCancelOrderParameters) error {
|
||||
currency := c.FormatExchangeCurrency(cancellation.Currency, asset.Spot).String()
|
||||
var cancellationRequest WsCancelOrderRequest
|
||||
cancellationRequest.Request = "cancel_order"
|
||||
cancellationRequest.InstID = instrumentListByString[currency]
|
||||
cancellationRequest.InstID = wsInstrumentMap.LookupID(currency)
|
||||
cancellationRequest.OrderID = cancellation.OrderID
|
||||
cancellationRequest.Nonce = c.WebsocketConn.GenerateMessageID(false)
|
||||
|
||||
@@ -645,7 +660,7 @@ func (c *COINUT) wsCancelOrders(cancellations []WsCancelOrderParameters) (*WsCan
|
||||
for i := range cancellations {
|
||||
currency := c.FormatExchangeCurrency(cancellations[i].Currency, asset.Spot).String()
|
||||
cancelOrderRequest.Entries = append(cancelOrderRequest.Entries, WsCancelOrdersRequestEntry{
|
||||
InstID: instrumentListByString[currency],
|
||||
InstID: wsInstrumentMap.LookupID(currency),
|
||||
OrderID: cancellations[i].OrderID,
|
||||
})
|
||||
}
|
||||
@@ -668,7 +683,7 @@ func (c *COINUT) wsCancelOrders(cancellations []WsCancelOrderParameters) (*WsCan
|
||||
if response.Results[i].Status != "OK" {
|
||||
errors = append(errors, fmt.Errorf("%v order cancellation failed for currency %v and orderID %v, message %v",
|
||||
c.Name,
|
||||
instrumentListByCode[response.Results[i].InstID],
|
||||
wsInstrumentMap.LookupInstrument(response.Results[i].InstID),
|
||||
response.Results[i].OrderID,
|
||||
response.Results[i].Status))
|
||||
}
|
||||
@@ -683,7 +698,7 @@ func (c *COINUT) wsGetTradeHistory(p currency.Pair, start, limit int64) error {
|
||||
curr := c.FormatExchangeCurrency(p, asset.Spot).String()
|
||||
var request WsTradeHistoryRequest
|
||||
request.Request = "trade_history"
|
||||
request.InstID = instrumentListByString[curr]
|
||||
request.InstID = wsInstrumentMap.LookupID(curr)
|
||||
request.Nonce = c.WebsocketConn.GenerateMessageID(false)
|
||||
request.Start = start
|
||||
request.Limit = limit
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package coinut
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -60,6 +61,7 @@ func (c *COINUT) SetDefaults() {
|
||||
},
|
||||
ConfigFormat: ¤cy.PairFormat{
|
||||
Uppercase: true,
|
||||
Delimiter: "-",
|
||||
},
|
||||
}
|
||||
|
||||
@@ -162,11 +164,30 @@ func (c *COINUT) Run() {
|
||||
c.PrintEnabledPairs()
|
||||
}
|
||||
|
||||
if !c.GetEnabledFeatures().AutoPairUpdates {
|
||||
forceUpdate := false
|
||||
delim := c.GetPairFormat(asset.Spot, false).Delimiter
|
||||
if !common.StringDataContains(c.CurrencyPairs.GetPairs(asset.Spot,
|
||||
true).Strings(), delim) ||
|
||||
!common.StringDataContains(c.CurrencyPairs.GetPairs(asset.Spot,
|
||||
false).Strings(), delim) {
|
||||
enabledPairs := currency.NewPairsFromStrings(
|
||||
[]string{fmt.Sprintf("LTC%sUSDT", delim)},
|
||||
)
|
||||
log.Warn(log.ExchangeSys,
|
||||
"Enabled pairs for Coinut reset due to config upgrade, please enable the ones you would like to use again")
|
||||
forceUpdate = true
|
||||
|
||||
err := c.UpdatePairs(enabledPairs, asset.Spot, true, true)
|
||||
if err != nil {
|
||||
log.Errorf(log.ExchangeSys, "%s failed to update currencies. Err: %s\n", c.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
if !c.GetEnabledFeatures().AutoPairUpdates && !forceUpdate {
|
||||
return
|
||||
}
|
||||
|
||||
err := c.UpdateTradablePairs(false)
|
||||
err := c.UpdateTradablePairs(forceUpdate)
|
||||
if err != nil {
|
||||
log.Errorf(log.ExchangeSys, "%s failed to update tradable pairs. Err: %s", c.Name, err)
|
||||
}
|
||||
@@ -180,10 +201,10 @@ func (c *COINUT) FetchTradablePairs(asset asset.Item) ([]string, error) {
|
||||
}
|
||||
|
||||
var pairs []string
|
||||
c.InstrumentMap = make(map[string]int)
|
||||
for x, y := range i.Instruments {
|
||||
c.InstrumentMap[x] = y[0].InstID
|
||||
pairs = append(pairs, x)
|
||||
for _, y := range i.Instruments {
|
||||
c.instrumentMap.Seed(y[0].Base+y[0].Quote, y[0].InstID)
|
||||
p := y[0].Base + c.GetPairFormat(asset, false).Delimiter + y[0].Quote
|
||||
pairs = append(pairs, p)
|
||||
}
|
||||
|
||||
return pairs, nil
|
||||
@@ -197,7 +218,8 @@ func (c *COINUT) UpdateTradablePairs(forceUpdate bool) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.UpdatePairs(currency.NewPairsFromStrings(pairs), asset.Spot, false, forceUpdate)
|
||||
return c.UpdatePairs(currency.NewPairsFromStrings(pairs),
|
||||
asset.Spot, false, forceUpdate)
|
||||
}
|
||||
|
||||
// GetAccountInfo retrieves balances for all enabled currencies for the
|
||||
@@ -278,7 +300,21 @@ func (c *COINUT) GetAccountInfo() (exchange.AccountInfo, error) {
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func (c *COINUT) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Price, error) {
|
||||
var tickerPrice ticker.Price
|
||||
tick, err := c.GetInstrumentTicker(c.InstrumentMap[c.FormatExchangeCurrency(p, assetType).String()])
|
||||
|
||||
if !c.instrumentMap.IsLoaded() {
|
||||
err := c.SeedInstruments()
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
}
|
||||
|
||||
instID := c.instrumentMap.LookupID(c.FormatExchangeCurrency(p,
|
||||
assetType).String())
|
||||
if instID == 0 {
|
||||
return tickerPrice, errors.New("unable to lookup instrument ID")
|
||||
}
|
||||
|
||||
tick, err := c.GetInstrumentTicker(instID)
|
||||
if err != nil {
|
||||
return tickerPrice, err
|
||||
}
|
||||
@@ -320,7 +356,21 @@ func (c *COINUT) FetchOrderbook(p currency.Pair, assetType asset.Item) (orderboo
|
||||
// UpdateOrderbook updates and returns the orderbook for a currency pair
|
||||
func (c *COINUT) UpdateOrderbook(p currency.Pair, assetType asset.Item) (orderbook.Base, error) {
|
||||
var orderBook orderbook.Base
|
||||
orderbookNew, err := c.GetInstrumentOrderbook(c.InstrumentMap[p.String()], 200)
|
||||
|
||||
if !c.instrumentMap.IsLoaded() {
|
||||
err := c.SeedInstruments()
|
||||
if err != nil {
|
||||
return orderBook, err
|
||||
}
|
||||
}
|
||||
|
||||
instID := c.instrumentMap.LookupID(c.FormatExchangeCurrency(p,
|
||||
assetType).String())
|
||||
if instID == 0 {
|
||||
return orderBook, errLookupInstrumentID
|
||||
}
|
||||
|
||||
orderbookNew, err := c.GetInstrumentOrderbook(instID, 200)
|
||||
if err != nil {
|
||||
return orderBook, err
|
||||
}
|
||||
@@ -378,14 +428,18 @@ func (c *COINUT) SubmitOrder(order *exchange.OrderSubmission) (exchange.SubmitOr
|
||||
|
||||
clientIDUint := uint32(clientIDInt)
|
||||
|
||||
// Need to get the ID of the currency sent
|
||||
instruments, err := c.GetInstruments()
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
if !c.instrumentMap.IsLoaded() {
|
||||
err = c.SeedInstruments()
|
||||
if err != nil {
|
||||
return submitOrderResponse, err
|
||||
}
|
||||
}
|
||||
|
||||
currencyArray := instruments.Instruments[order.Pair.String()]
|
||||
currencyID := currencyArray[0].InstID
|
||||
currencyID := c.instrumentMap.LookupID(c.FormatExchangeCurrency(order.Pair,
|
||||
asset.Spot).String())
|
||||
if currencyID == 0 {
|
||||
return submitOrderResponse, errLookupInstrumentID
|
||||
}
|
||||
|
||||
switch order.OrderType {
|
||||
case exchange.LimitOrderType:
|
||||
@@ -425,23 +479,25 @@ func (c *COINUT) ModifyOrder(action *exchange.ModifyOrder) (string, error) {
|
||||
// CancelOrder cancels an order by its corresponding ID number
|
||||
func (c *COINUT) CancelOrder(order *exchange.OrderCancellation) error {
|
||||
orderIDInt, err := strconv.ParseInt(order.OrderID, 10, 64)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Need to get the ID of the currency sent
|
||||
instruments, err := c.GetInstruments()
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
if !c.instrumentMap.IsLoaded() {
|
||||
err = c.SeedInstruments()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
currencyArray := instruments.Instruments[c.FormatExchangeCurrency(order.CurrencyPair,
|
||||
order.AssetType).String()]
|
||||
currencyID := currencyArray[0].InstID
|
||||
_, err = c.CancelExistingOrder(currencyID, int(orderIDInt))
|
||||
|
||||
currencyID := c.instrumentMap.LookupID(c.FormatExchangeCurrency(
|
||||
order.CurrencyPair,
|
||||
asset.Spot).String(),
|
||||
)
|
||||
if currencyID == 0 {
|
||||
return errLookupInstrumentID
|
||||
}
|
||||
_, err = c.CancelExistingOrder(currencyID, orderIDInt)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -454,22 +510,22 @@ func (c *COINUT) CancelAllOrders(_ *exchange.OrderCancellation) (exchange.Cancel
|
||||
cancelAllOrdersResponse := exchange.CancelAllOrdersResponse{
|
||||
OrderStatus: make(map[string]string),
|
||||
}
|
||||
instruments, err := c.GetInstruments()
|
||||
if err != nil {
|
||||
return cancelAllOrdersResponse, err
|
||||
|
||||
if !c.instrumentMap.IsLoaded() {
|
||||
err := c.SeedInstruments()
|
||||
if err != nil {
|
||||
return cancelAllOrdersResponse, err
|
||||
}
|
||||
}
|
||||
|
||||
var allTheOrders []OrderResponse
|
||||
for _, allInstrumentData := range instruments.Instruments {
|
||||
for _, instrumentData := range allInstrumentData {
|
||||
|
||||
openOrders, err := c.GetOpenOrders(instrumentData.InstID)
|
||||
if err != nil {
|
||||
return cancelAllOrdersResponse, err
|
||||
}
|
||||
|
||||
allTheOrders = append(allTheOrders, openOrders.Orders...)
|
||||
ids := c.instrumentMap.GetInstrumentIDs()
|
||||
for x := range ids {
|
||||
openOrders, err := c.GetOpenOrders(ids[x])
|
||||
if err != nil {
|
||||
return cancelAllOrdersResponse, err
|
||||
}
|
||||
allTheOrders = append(allTheOrders, openOrders.Orders...)
|
||||
}
|
||||
|
||||
var allTheOrdersToCancel []CancelOrders
|
||||
@@ -499,8 +555,7 @@ func (c *COINUT) CancelAllOrders(_ *exchange.OrderCancellation) (exchange.Cancel
|
||||
|
||||
// GetOrderInfo returns information on a current open order
|
||||
func (c *COINUT) GetOrderInfo(orderID string) (exchange.OrderDetail, error) {
|
||||
var orderDetail exchange.OrderDetail
|
||||
return orderDetail, common.ErrNotYetImplemented
|
||||
return exchange.OrderDetail{}, common.ErrNotYetImplemented
|
||||
}
|
||||
|
||||
// GetDepositAddress returns a deposit address for a specified currency
|
||||
@@ -542,51 +597,51 @@ func (c *COINUT) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error)
|
||||
|
||||
// GetActiveOrders retrieves any orders that are active/open
|
||||
func (c *COINUT) GetActiveOrders(getOrdersRequest *exchange.GetOrdersRequest) ([]exchange.OrderDetail, error) {
|
||||
instruments, err := c.GetInstruments()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var allTheOrders []OrderResponse
|
||||
for instrument, allInstrumentData := range instruments.Instruments {
|
||||
for _, instrumentData := range allInstrumentData {
|
||||
for _, currency := range getOrdersRequest.Currencies {
|
||||
currStr := fmt.Sprintf("%v%v%v",
|
||||
currency.Base.String(),
|
||||
c.CurrencyPairs.Get(asset.Spot).ConfigFormat.Delimiter,
|
||||
currency.Quote.String())
|
||||
if strings.EqualFold(currStr, instrument) {
|
||||
openOrders, err := c.GetOpenOrders(instrumentData.InstID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
allTheOrders = append(allTheOrders, openOrders.Orders...)
|
||||
|
||||
continue
|
||||
}
|
||||
}
|
||||
if !c.instrumentMap.IsLoaded() {
|
||||
err := c.SeedInstruments()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var instrumentsToUse []int64
|
||||
if len(getOrdersRequest.Currencies) > 0 {
|
||||
for x := range getOrdersRequest.Currencies {
|
||||
currency := c.FormatExchangeCurrency(getOrdersRequest.Currencies[x],
|
||||
asset.Spot).String()
|
||||
instrumentsToUse = append(instrumentsToUse,
|
||||
c.instrumentMap.LookupID(currency))
|
||||
}
|
||||
} else {
|
||||
instrumentsToUse = c.instrumentMap.GetInstrumentIDs()
|
||||
}
|
||||
|
||||
if len(instrumentsToUse) == 0 {
|
||||
return nil, errors.New("no instrument IDs to use")
|
||||
}
|
||||
|
||||
var orders []exchange.OrderDetail
|
||||
for _, order := range allTheOrders {
|
||||
for instrument, allInstrumentData := range instruments.Instruments {
|
||||
for _, instrumentData := range allInstrumentData {
|
||||
if instrumentData.InstID == int(order.InstrumentID) {
|
||||
currPair := currency.NewPairDelimiter(instrument, "")
|
||||
orderSide := exchange.OrderSide(strings.ToUpper(order.Side))
|
||||
orderDate := time.Unix(order.Timestamp, 0)
|
||||
orders = append(orders, exchange.OrderDetail{
|
||||
ID: strconv.FormatInt(order.OrderID, 10),
|
||||
Amount: order.Quantity,
|
||||
Price: order.Price,
|
||||
Exchange: c.Name,
|
||||
OrderSide: orderSide,
|
||||
OrderDate: orderDate,
|
||||
CurrencyPair: currPair,
|
||||
})
|
||||
}
|
||||
}
|
||||
for x := range instrumentsToUse {
|
||||
openOrders, err := c.GetOpenOrders(instrumentsToUse[x])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for y := range openOrders.Orders {
|
||||
curr := c.instrumentMap.LookupInstrument(instrumentsToUse[x])
|
||||
p := currency.NewPairFromFormattedPairs(curr,
|
||||
c.GetEnabledPairs(asset.Spot),
|
||||
c.GetPairFormat(asset.Spot, true))
|
||||
orderSide := exchange.OrderSide(strings.ToUpper(openOrders.Orders[y].Side))
|
||||
orderDate := time.Unix(openOrders.Orders[y].Timestamp, 0)
|
||||
orders = append(orders, exchange.OrderDetail{
|
||||
ID: strconv.FormatInt(openOrders.Orders[y].OrderID, 10),
|
||||
Amount: openOrders.Orders[y].Quantity,
|
||||
Price: openOrders.Orders[y].Price,
|
||||
Exchange: c.Name,
|
||||
OrderSide: orderSide,
|
||||
OrderDate: orderDate,
|
||||
CurrencyPair: p,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -598,56 +653,60 @@ func (c *COINUT) GetActiveOrders(getOrdersRequest *exchange.GetOrdersRequest) ([
|
||||
// GetOrderHistory retrieves account order information
|
||||
// Can Limit response to specific order status
|
||||
func (c *COINUT) GetOrderHistory(getOrdersRequest *exchange.GetOrdersRequest) ([]exchange.OrderDetail, error) {
|
||||
instruments, err := c.GetInstruments()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var allTheOrders []OrderFilledResponse
|
||||
for instrument, allInstrumentData := range instruments.Instruments {
|
||||
for _, instrumentData := range allInstrumentData {
|
||||
for _, currency := range getOrdersRequest.Currencies {
|
||||
currStr := fmt.Sprintf("%v%v",
|
||||
currency.Base.String(), currency.Quote.String())
|
||||
if strings.EqualFold(currStr, instrument) {
|
||||
orders, err := c.GetTradeHistory(instrumentData.InstID, -1, -1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
allTheOrders = append(allTheOrders, orders.Trades...)
|
||||
|
||||
continue
|
||||
}
|
||||
}
|
||||
if !c.instrumentMap.IsLoaded() {
|
||||
err := c.SeedInstruments()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var orders []exchange.OrderDetail
|
||||
for i := range allTheOrders {
|
||||
for instrument, allInstrumentData := range instruments.Instruments {
|
||||
for j := range allInstrumentData {
|
||||
if allInstrumentData[j].InstID == int(allTheOrders[i].Order.InstrumentID) {
|
||||
currPair := currency.NewPairDelimiter(instrument, "")
|
||||
orderSide := exchange.OrderSide(strings.ToUpper(allTheOrders[i].Order.Side))
|
||||
orderDate := time.Unix(allTheOrders[i].Order.Timestamp, 0)
|
||||
orders = append(orders, exchange.OrderDetail{
|
||||
ID: strconv.FormatInt(allTheOrders[i].Order.OrderID, 10),
|
||||
Amount: allTheOrders[i].Order.Quantity,
|
||||
Price: allTheOrders[i].Order.Price,
|
||||
Exchange: c.Name,
|
||||
OrderSide: orderSide,
|
||||
OrderDate: orderDate,
|
||||
CurrencyPair: currPair,
|
||||
})
|
||||
}
|
||||
}
|
||||
var instrumentsToUse []int64
|
||||
if len(getOrdersRequest.Currencies) > 0 {
|
||||
for x := range getOrdersRequest.Currencies {
|
||||
currency := c.FormatExchangeCurrency(getOrdersRequest.Currencies[x],
|
||||
asset.Spot).String()
|
||||
instrumentsToUse = append(instrumentsToUse,
|
||||
c.instrumentMap.LookupID(currency))
|
||||
}
|
||||
} else {
|
||||
instrumentsToUse = c.instrumentMap.GetInstrumentIDs()
|
||||
}
|
||||
|
||||
exchange.FilterOrdersByTickRange(&orders, getOrdersRequest.StartTicks,
|
||||
if len(instrumentsToUse) == 0 {
|
||||
return nil, errors.New("no instrument IDs to use")
|
||||
}
|
||||
|
||||
var allOrders []exchange.OrderDetail
|
||||
for x := range instrumentsToUse {
|
||||
orders, err := c.GetTradeHistory(instrumentsToUse[x], -1, -1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for y := range orders.Trades {
|
||||
curr := c.instrumentMap.LookupInstrument(instrumentsToUse[x])
|
||||
p := currency.NewPairFromFormattedPairs(curr,
|
||||
c.GetEnabledPairs(asset.Spot),
|
||||
c.GetPairFormat(asset.Spot, true))
|
||||
orderSide := exchange.OrderSide(
|
||||
strings.ToUpper(orders.Trades[y].Order.Side))
|
||||
orderDate := time.Unix(orders.Trades[y].Order.Timestamp, 0)
|
||||
allOrders = append(allOrders, exchange.OrderDetail{
|
||||
ID: strconv.FormatInt(orders.Trades[y].Order.OrderID, 10),
|
||||
Amount: orders.Trades[y].Order.Quantity,
|
||||
Price: orders.Trades[y].Order.Price,
|
||||
Exchange: c.Name,
|
||||
OrderSide: orderSide,
|
||||
OrderDate: orderDate,
|
||||
CurrencyPair: p,
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
exchange.FilterOrdersByTickRange(&allOrders, getOrdersRequest.StartTicks,
|
||||
getOrdersRequest.EndTicks)
|
||||
exchange.FilterOrdersBySide(&orders, getOrdersRequest.OrderSide)
|
||||
return orders, nil
|
||||
exchange.FilterOrdersBySide(&allOrders, getOrdersRequest.OrderSide)
|
||||
return allOrders, nil
|
||||
}
|
||||
|
||||
// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
|
||||
|
||||
@@ -124,20 +124,19 @@ func (o *OKCoin) Run() {
|
||||
log.Debugf(log.ExchangeSys, "%s Websocket: %s. (url: %s).\n", o.GetName(), common.IsEnabled(o.Websocket.IsEnabled()), o.WebsocketURL)
|
||||
}
|
||||
|
||||
if o.Config.CurrencyPairs.ConfigFormat.Delimiter != o.CurrencyPairs.ConfigFormat.Delimiter {
|
||||
o.Config.CurrencyPairs.ConfigFormat.Delimiter = o.CurrencyPairs.ConfigFormat.Delimiter
|
||||
}
|
||||
if o.Config.CurrencyPairs.RequestFormat.Uppercase != o.CurrencyPairs.RequestFormat.Uppercase {
|
||||
o.Config.CurrencyPairs.RequestFormat.Uppercase = true
|
||||
}
|
||||
if o.Config.CurrencyPairs.RequestFormat.Delimiter != o.CurrencyPairs.RequestFormat.Delimiter {
|
||||
o.Config.CurrencyPairs.RequestFormat.Delimiter = o.CurrencyPairs.RequestFormat.Delimiter
|
||||
}
|
||||
|
||||
if !common.StringDataContains(o.Config.CurrencyPairs.Pairs[asset.Spot].Enabled.Strings(), o.CurrencyPairs.RequestFormat.Delimiter) {
|
||||
enabledPairs := currency.NewPairsFromStrings([]string{"BTC-USD"})
|
||||
forceUpdate := false
|
||||
delim := o.GetPairFormat(asset.Spot, false).Delimiter
|
||||
if !common.StringDataContains(o.CurrencyPairs.GetPairs(asset.Spot,
|
||||
true).Strings(), delim) ||
|
||||
!common.StringDataContains(o.CurrencyPairs.GetPairs(asset.Spot,
|
||||
false).Strings(), delim) {
|
||||
enabledPairs := currency.NewPairsFromStrings([]string{
|
||||
fmt.Sprintf("BTC%sUSD", delim),
|
||||
})
|
||||
log.Warnf(log.ExchangeSys,
|
||||
"Enabled pairs for %v reset due to config upgrade, please enable the ones you would like again.", o.Name)
|
||||
"Enabled pairs for %v reset due to config upgrade, please enable the ones you would like again.\n",
|
||||
o.Name)
|
||||
forceUpdate = true
|
||||
|
||||
err := o.UpdatePairs(enabledPairs, asset.Spot, true, true)
|
||||
if err != nil {
|
||||
@@ -146,11 +145,11 @@ func (o *OKCoin) Run() {
|
||||
}
|
||||
}
|
||||
|
||||
if !o.GetEnabledFeatures().AutoPairUpdates {
|
||||
if !o.GetEnabledFeatures().AutoPairUpdates && !forceUpdate {
|
||||
return
|
||||
}
|
||||
|
||||
err := o.UpdateTradablePairs(false)
|
||||
err := o.UpdateTradablePairs(forceUpdate)
|
||||
if err != nil {
|
||||
log.Errorf(log.ExchangeSys, "%s failed to update tradable pairs. Err: %s", o.Name, err)
|
||||
}
|
||||
@@ -165,7 +164,8 @@ func (o *OKCoin) FetchTradablePairs(asset asset.Item) ([]string, error) {
|
||||
|
||||
var pairs []string
|
||||
for x := range prods {
|
||||
pairs = append(pairs, fmt.Sprintf("%v%v%v", prods[x].BaseCurrency, o.GetPairFormat(asset, false).Delimiter, prods[x].QuoteCurrency))
|
||||
pairs = append(pairs, fmt.Sprintf("%v%v%v", prods[x].BaseCurrency,
|
||||
o.GetPairFormat(asset, false).Delimiter, prods[x].QuoteCurrency))
|
||||
}
|
||||
|
||||
return pairs, nil
|
||||
|
||||
Reference in New Issue
Block a user