From 093def35e9b3c0b2dfba5b59c41fb04d920deb22 Mon Sep 17 00:00:00 2001 From: Adrian Gallagher Date: Tue, 27 Jun 2017 17:03:04 +1000 Subject: [PATCH] Add basic support for COINUT exchange --- README.md | 6 +- config/config.go | 2 +- config_example.dat | 16 +- exchanges/coinut/coinut.go | 324 +++++++++++++++++++++++++++ exchanges/coinut/coinut_types.go | 213 ++++++++++++++++++ exchanges/coinut/coinut_websocket.go | 60 +++++ exchanges/coinut/coinut_wrapper.go | 129 +++++++++++ main.go | 3 + 8 files changed, 748 insertions(+), 5 deletions(-) create mode 100644 exchanges/coinut/coinut.go create mode 100644 exchanges/coinut/coinut_types.go create mode 100644 exchanges/coinut/coinut_websocket.go create mode 100644 exchanges/coinut/coinut_wrapper.go diff --git a/README.md b/README.md index 725a32dc..a2c9090c 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![GoDoc](https://godoc.org/github.com/thrasher-/gocryptotrader?status.svg)](https://godoc.org/github.com/thrasher-/gocryptotrader) [![Coverage Status](http://codecov.io/github/thrasher-/gocryptotrader/coverage.svg?branch=master)](http://codecov.io/github/thrasher-/gocryptotrader?branch=master) -A cryptocurrency trading bot supporting multiple exchanges written in Golang. +A cryptocurrency trading bot supporting multiple exchanges written in Golang. **Please note that this bot is under development and is not ready for production!** @@ -19,12 +19,13 @@ A cryptocurrency trading bot supporting multiple exchanges written in Golang. | BTCC | Yes | Yes | No | | BTCE | Yes | NA | NA | | BTCMarkets | Yes | NA | NA | +| COINUT | Yes | No | NA | | GDAX(Coinbase) | Yes | Yes | No| | Gemini | Yes | NA | NA | | Huobi | Yes | Yes |No | | ItBit | Yes | NA | NA | | Kraken | Yes | NA | NA | -| LakeBTC | Yes | No | NA | +| LakeBTC | Yes | No | NA | | Liqui | Yes | No | NA | | LocalBitcoins | Yes | NA | NA | | OKCoin (both) | Yes | Yes | No | @@ -70,4 +71,3 @@ Run the application! ## Binaries Binaries will be published once the codebase reaches a stable condition. - diff --git a/config/config.go b/config/config.go index 1aaf4ad5..0274b260 100644 --- a/config/config.go +++ b/config/config.go @@ -168,7 +168,7 @@ func (c *Config) CheckExchangeConfigValues() error { c.Exchanges[i].AuthenticatedAPISupport = false log.Printf(WarningExchangeAuthAPIDefaultOrEmptyValues, exch.Name) continue - } else if exch.Name == "ITBIT" || exch.Name == "Bitstamp" || exch.Name == "Coinbase" { + } else if exch.Name == "ITBIT" || exch.Name == "Bitstamp" || exch.Name == "COINUT" || exch.Name == "GDAX" { if exch.ClientID == "" || exch.ClientID == "ClientID" { c.Exchanges[i].AuthenticatedAPISupport = false log.Printf(WarningExchangeAuthAPIDefaultOrEmptyValues, exch.Name) diff --git a/config_example.dat b/config_example.dat index 973ffa04..2120fa62 100644 --- a/config_example.dat +++ b/config_example.dat @@ -129,6 +129,20 @@ "EnabledPairs": "LTC,BTC", "BaseCurrencies": "AUD" }, + { + "Name": "COINUT", + "Enabled": true, + "Verbose": false, + "Websocket": false, + "RESTPollingDelay": 10, + "AuthenticatedAPISupport": false, + "APIKey": "Key", + "APISecret": "Secret", + "ClientID": "ClientID", + "AvailablePairs": "LTCBTC,ETCBTC,ETHBTC", + "EnabledPairs": "LTCBTC,ETCBTC,ETHBTC", + "BaseCurrencies": "USD" + }, { "Name": "GDAX", "Enabled": true, @@ -284,4 +298,4 @@ "BaseCurrencies": "USD" } ] -} \ No newline at end of file +} diff --git a/exchanges/coinut/coinut.go b/exchanges/coinut/coinut.go new file mode 100644 index 00000000..0e1400ca --- /dev/null +++ b/exchanges/coinut/coinut.go @@ -0,0 +1,324 @@ +package coinut + +import ( + "bytes" + "errors" + "log" + "time" + + "github.com/gorilla/websocket" + "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/config" + "github.com/thrasher-/gocryptotrader/exchanges" +) + +const ( + COINUT_API_URL = "https://api.coinut.com" + COINUT_API_VERISON = "1" + COINUT_INSTRUMENTS = "inst_list" + COINUT_TICKER = "inst_tick" + COINUT_ORDERBOOK = "inst_order_book" + COINUT_TRADES = "inst_trade" + COINUT_BALANCE = "user_balance" + COINUT_ORDER = "new_order" + COINUT_ORDERS = "new_orders" + COINUT_ORDERS_OPEN = "user_open_orders" + COINUT_ORDER_CANCEL = "cancel_order" + COINUT_ORDERS_CANCEL = "cancel_orders" + COINUT_TRADE_HISTORY = "trade_history" + COINUT_INDEX_TICKER = "index_tick" + COINUT_OPTION_CHAIN = "option_chain" + COINUT_POSITION_HISTORY = "position_history" + COINUT_POSITION_OPEN = "user_open_positions" +) + +type COINUT struct { + exchange.ExchangeBase + WebsocketConn *websocket.Conn + InstrumentMap map[string]int +} + +func (c *COINUT) SetDefaults() { + c.Name = "COINUT" + c.Enabled = false + c.Verbose = false + c.TakerFee = 0.1 //spot + c.MakerFee = 0 + c.Verbose = false + c.Websocket = false + c.RESTPollingDelay = 10 +} + +func (c *COINUT) Setup(exch config.ExchangeConfig) { + if !exch.Enabled { + c.SetEnabled(false) + } else { + c.Enabled = true + c.AuthenticatedAPISupport = exch.AuthenticatedAPISupport + c.SetAPIKeys(exch.APIKey, exch.APISecret, exch.ClientID, true) + c.RESTPollingDelay = exch.RESTPollingDelay + c.Verbose = exch.Verbose + c.Websocket = exch.Websocket + c.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",") + c.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",") + c.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",") + } +} + +func (c *COINUT) GetInstruments() (CoinutInstruments, error) { + var result CoinutInstruments + params := make(map[string]interface{}) + params["sec_type"] = "SPOT" + err := c.SendAuthenticatedHTTPRequest(COINUT_INSTRUMENTS, params, &result) + if err != nil { + return result, err + } + return result, nil +} + +func (c *COINUT) GetInstrumentTicker(instrumentID int) (CoinutTicker, error) { + var result CoinutTicker + params := make(map[string]interface{}) + params["inst_id"] = instrumentID + err := c.SendAuthenticatedHTTPRequest(COINUT_TICKER, params, &result) + if err != nil { + return result, err + } + return result, nil +} + +func (c *COINUT) GetInstrumentOrderbook(instrumentID, limit int) (CoinutOrderbook, error) { + var result CoinutOrderbook + params := make(map[string]interface{}) + params["inst_id"] = instrumentID + if limit > 0 { + params["top_n"] = limit + } + err := c.SendAuthenticatedHTTPRequest(COINUT_ORDERBOOK, params, &result) + if err != nil { + return result, err + } + return result, nil +} + +func (c *COINUT) GetTrades(instrumentID int) (CoinutTrades, error) { + var result CoinutTrades + params := make(map[string]interface{}) + params["inst_id"] = instrumentID + err := c.SendAuthenticatedHTTPRequest(COINUT_TRADES, params, &result) + if err != nil { + return result, err + } + return result, nil +} + +func (c *COINUT) GetUserBalance() (CoinutUserBalance, error) { + result := CoinutUserBalance{} + err := c.SendAuthenticatedHTTPRequest(COINUT_BALANCE, nil, &result) + if err != nil { + return result, err + } + return result, nil +} + +func (c *COINUT) NewOrder(instrumentID int, quantity, price float64, buy bool, orderID uint32) (interface{}, error) { + var result interface{} + params := make(map[string]interface{}) + params["inst_id"] = instrumentID + params["price"] = price + params["qty"] = quantity + params["side"] = "BUY" + if !buy { + params["side"] = "SELL" + } + params["client_ord_id"] = orderID + + err := c.SendAuthenticatedHTTPRequest(COINUT_ORDER, params, &result) + if err != nil { + return result, err + } + return result, nil +} + +func (c *COINUT) NewOrders(orders []CoinutOrder) ([]CoinutOrdersBase, error) { + var result CoinutOrdersResponse + params := make(map[string]interface{}) + params["orders"] = orders + err := c.SendAuthenticatedHTTPRequest(COINUT_ORDERS, params, &result.Data) + if err != nil { + return nil, err + } + return result.Data, nil +} + +func (c *COINUT) GetOpenOrders(instrumentID int) ([]CoinutOrdersResponse, error) { + var result []CoinutOrdersResponse + params := make(map[string]interface{}) + params["inst_id"] = instrumentID + err := c.SendAuthenticatedHTTPRequest(COINUT_ORDERS_OPEN, params, &result) + if err != nil { + return nil, err + } + return result, nil +} + +func (c *COINUT) CancelOrder(instrumentID, orderID int) (bool, error) { + var result CoinutGenericResponse + params := make(map[string]interface{}) + params["inst_id"] = instrumentID + params["order_id"] = orderID + err := c.SendAuthenticatedHTTPRequest(COINUT_ORDERS_CANCEL, params, &result) + if err != nil { + return false, err + } + return true, nil +} + +func (c *COINUT) CancelOrders(orders []CoinutCancelOrders) (CoinutCancelOrdersResponse, error) { + var result CoinutCancelOrdersResponse + params := make(map[string]interface{}) + params["entries"] = orders + err := c.SendAuthenticatedHTTPRequest(COINUT_ORDERS_CANCEL, params, &result) + if err != nil { + return result, err + } + return result, nil +} + +func (c *COINUT) GetTradeHistory(instrumentID, start, limit int) (CoinutTradeHistory, error) { + var result CoinutTradeHistory + params := make(map[string]interface{}) + params["inst_id"] = instrumentID + if start >= 0 && start <= 100 { + params["start"] = start + } + if limit >= 0 && start <= 100 { + params["limit"] = limit + } + err := c.SendAuthenticatedHTTPRequest(COINUT_TRADE_HISTORY, params, &result) + if err != nil { + return result, err + } + return result, nil +} + +func (c *COINUT) GetIndexTicker(asset string) (CoinutIndexTicker, error) { + var result CoinutIndexTicker + params := make(map[string]interface{}) + params["asset"] = asset + err := c.SendAuthenticatedHTTPRequest(COINUT_INDEX_TICKER, params, &result) + if err != nil { + return result, err + } + return result, nil +} + +func (c *COINUT) GetDerivativeInstruments(secType string) (interface{}, error) { + var result interface{} //to-do + params := make(map[string]interface{}) + params["sec_type"] = secType + err := c.SendAuthenticatedHTTPRequest(COINUT_INSTRUMENTS, params, &result) + if err != nil { + return result, err + } + return result, nil +} + +func (c *COINUT) GetOptionChain(asset, secType string, expiry int64) (CoinutOptionChainResponse, error) { + var result CoinutOptionChainResponse + params := make(map[string]interface{}) + params["asset"] = asset + params["sec_type"] = secType + err := c.SendAuthenticatedHTTPRequest(COINUT_OPTION_CHAIN, params, &result) + if err != nil { + return result, err + } + return result, nil +} + +func (c *COINUT) GetPositionHistory(secType string, start, limit int) (CoinutPositionHistory, error) { + var result CoinutPositionHistory + params := make(map[string]interface{}) + params["sec_type"] = secType + if start >= 0 { + params["start"] = start + } + if limit >= 0 { + params["limit"] = limit + } + err := c.SendAuthenticatedHTTPRequest(COINUT_POSITION_HISTORY, params, &result) + if err != nil { + return result, err + } + return result, nil +} + +func (c *COINUT) GetOpenPosition(instrumentID int) ([]CoinutOpenPosition, error) { + type Response struct { + Positions []CoinutOpenPosition `json:"positions"` + } + var result Response + params := make(map[string]interface{}) + params["inst_id"] = instrumentID + + err := c.SendAuthenticatedHTTPRequest(COINUT_POSITION_OPEN, params, &result) + if err != nil { + return result.Positions, err + } + return result.Positions, nil +} + +//to-do: user position update via websocket + +func (c *COINUT) SendAuthenticatedHTTPRequest(apiRequest string, params map[string]interface{}, result interface{}) (err error) { + timestamp := time.Now().Unix() + payload := []byte("") + + if params == nil { + params = map[string]interface{}{} + } + params["nonce"] = timestamp + params["request"] = apiRequest + + payload, err = common.JSONEncode(params) + + if err != nil { + return errors.New("SendAuthenticatedHTTPRequest: Unable to JSON request") + } + + if c.Verbose { + log.Printf("Request JSON: %s\n", payload) + } + + hmac := common.GetHMAC(common.HASH_SHA256, []byte(payload), []byte(c.APIKey)) + headers := make(map[string]string) + headers["X-USER"] = c.ClientID + headers["X-SIGNATURE"] = common.HexEncodeToString(hmac) + headers["Content-Type"] = "application/json" + + resp, err := common.SendHTTPRequest("POST", COINUT_API_URL, headers, bytes.NewBuffer(payload)) + + if c.Verbose { + log.Printf("Recieved raw: \n%s", resp) + } + + genResp := CoinutGenericResponse{} + + err = common.JSONDecode([]byte(resp), &genResp) + + if err != nil { + return errors.New("Unable to JSON Unmarshal generic response.") + } + + if genResp.Status[0] != "OK" { + return errors.New("Status is not OK.") + } + + err = common.JSONDecode([]byte(resp), &result) + + if err != nil { + return errors.New("Unable to JSON Unmarshal response.") + } + + return nil +} diff --git a/exchanges/coinut/coinut_types.go b/exchanges/coinut/coinut_types.go new file mode 100644 index 00000000..91b55223 --- /dev/null +++ b/exchanges/coinut/coinut_types.go @@ -0,0 +1,213 @@ +package coinut + +type CoinutGenericResponse struct { + Nonce int64 `json:"nonce"` + Reply string `json:"reply"` + Status []string `json:"status"` + TransID int64 `json:"trans_id"` + Timestamp int64 `json:"timestamp"` +} + +type CoinutInstrumentBase struct { + Base string `json:"base"` + DecimalPlaces int `json:"decimal_places"` + InstID int `json:"inst_id"` + Quote string `json:"quote"` +} + +type CoinutInstruments struct { + Instruments map[string][]CoinutInstrumentBase `json:"SPOT"` +} + +type CoinutTicker struct { + HighestBuy float64 `json:"highest_buy,string"` + InstrumentID int `json:"inst_id"` + Last float64 `json:"last,string"` + LowestSell float64 `json:"lowest_sell,string"` + OpenInterest float64 `json:"open_interest,string"` + Timestamp float64 `json:"timestamp"` + TransID int64 `json:"trans_id"` + Volume float64 `json:"volume,string"` + Volume24 float64 `json:"volume24,string"` +} + +type CoinutOrderbookBase struct { + Count int `json:"count"` + Price float64 `json:"price,string"` + Quantity float64 `json:"quantity,string"` +} + +type CoinutOrderbook struct { + Buy []CoinutOrderbookBase `json:"buy"` + Sell []CoinutOrderbookBase `json:"sell"` + InstrumentID int `json:"inst_id"` + TotalBuy float64 `json:"total_buy,string"` + TotalSell float64 `json:"total_sell,string"` + TransID int64 `json:"trans_id"` +} + +type CoinutTradeBase struct { + Price float64 `json:"price,string"` + Quantity float64 `json:"quantity,string"` + Side string `json:"side"` + Timestamp float64 `json:"timestamp"` + TransID int64 `json:"trans_id"` +} + +type CoinutTrades struct { + Trades []CoinutTradeBase `json:"trades"` +} + +type CoinutUserBalance struct { + BTC float64 `json:"btc,string"` + ETC float64 `json:"etc,string"` + ETH float64 `json:"eth,string"` + LTC float64 `json:"ltc,string"` + Equity float64 `json:"equity,string,string"` + InitialMargin float64 `json:"initial_margin,string"` + MaintenanceMargin float64 `json:"maintenance_margin,string"` + RealizedPL float64 `json:"realized_pl,string"` + TransID int64 `json:"trans_id"` + UnrealizedPL float64 `json:"unrealized_pl,string"` +} + +type CoinutOrder struct { + InstrumentID int64 `json:"inst_id"` + Price float64 `json:"price,string"` + Quantity float64 `json:"qty,string"` + ClientOrderID int `json:"client_ord_id"` + Side string `json:"side,string"` +} + +type CoinutOrderResponse struct { + OrderID int64 `json:"order_id"` + OpenQuantity float64 `json:"open_qty,string"` + Price float64 `json:"price,string"` + Quantity float64 `json:"qty,string"` + InstrumentID int64 `json:"inst_id"` + ClientOrderID int64 `json:"client_ord_id"` + Timestamp int64 `json:"timestamp"` + OrderPrice float64 `json:"order_price,string"` + Side string `json:"side"` +} + +type CoinutCommission struct { + Currency string `json:"currency"` + Amount float64 `json:"amount,string"` +} + +type CoinutOrderFilledResponse struct { + CoinutGenericResponse + Commission CoinutCommission `json:"commission"` + FillPrice float64 `json:"fill_price,string"` + FillQuantity float64 `json:"fill_qty,string"` + Order CoinutOrderResponse `json:"order"` +} + +type CoinutOrderRejectResponse struct { + CoinutOrderResponse + Reasons []string `json:"reasons"` +} + +type CoinutOrdersBase struct { + CoinutGenericResponse + CoinutOrderResponse +} + +type CoinutOrdersResponse struct { + Data []CoinutOrdersBase +} + +type CoinutCancelOrders struct { + InstrumentID int `json:"int"` + OrderID int64 `json:"order_id"` +} + +type CoinutCancelOrdersResponse struct { + CoinutGenericResponse + Results []struct { + OrderID int64 `json:"order_id"` + Status string `json:"status"` + InstrumentID int `json:"inst_id"` + } `json:"results"` +} + +type CoinutTradeHistory struct { + TotalNumber int64 `json:"total_number"` + Trades []CoinutOrderFilledResponse `json:"trades"` +} + +type CoinutIndexTicker struct { + Asset string `json:"asset"` + Price float64 `json:"price,string"` +} + +type CoinutOption struct { + HighestBuy float64 `json:"highest_buy,string"` + InstrumentID int `json:"inst_id"` + Last float64 `json:"last,string"` + LowestSell float64 `json:"lowest_sell,string"` + OpenInterest float64 `json:"open_interest,string"` +} + +type CoinutOptionChainResponse struct { + ExpiryTime int64 `json:"expiry_time"` + SecurityType string `json:"sec_type"` + Asset string `json:"asset"` + Entries []struct { + Call CoinutOption `json:"call"` + Put CoinutOption `json:"put"` + Strike float64 `json:"strike,string"` + } +} + +type CoinutOptionChainUpdate struct { + CoinutOption + CoinutGenericResponse + Asset string `json:"asset"` + ExpiryTime int64 `json:"expiry_time"` + SecurityType string `json:"sec_type"` + Volume float64 `json:"volume,string"` +} + +type CoinutPositionHistory struct { + Positions []struct { + PositionID int `json:"position_id"` + Records []struct { + Commission CoinutCommission `json:"commission"` + FillPrice float64 `json:"fill_price,string,omitempty"` + TransactionID int `json:"trans_id"` + FillQuantity float64 `json:"fill_qty,omitempty"` + Position struct { + Commission CoinutCommission `json:"commission"` + Timestamp int64 `json:"timestamp"` + OpenPrice float64 `json:"open_price,string"` + RealizedPL float64 `json:"realized_pl,string"` + Quantity float64 `json:"qty,string"` + } `json:"position"` + AssetAtExpiry float64 `json:"asset_at_expiry,string,omitempty"` + } `json:"records"` + Instrument struct { + ExpiryTime int64 `json:"expiry_time"` + ContractSize float64 `json:"contract_size,string"` + ConversionRate float64 `json:"conversion_rate,string"` + OptionType string `json:"option_type"` + InstrumentID int `json:"inst_id"` + SecType string `json:"sec_type"` + Asset string `json:"asset"` + Strike float64 `json:"strike,string"` + } `json:"inst"` + OpenTimestamp int64 `json:"open_timestamp"` + } `json:"positions"` + TotalNumber int `json:"total_number"` +} + +type CoinutOpenPosition struct { + PositionID int `json:"position_id"` + Commission CoinutCommission `json:"commission"` + OpenPrice float64 `json:"open_price,string"` + RealizedPL float64 `json:"realized_pl,string"` + Quantity float64 `json:"qty,string"` + OpenTimestamp int64 `json:"open_timestamp"` + InstrumentID int `json:"inst_id"` +} diff --git a/exchanges/coinut/coinut_websocket.go b/exchanges/coinut/coinut_websocket.go new file mode 100644 index 00000000..53e8c9a1 --- /dev/null +++ b/exchanges/coinut/coinut_websocket.go @@ -0,0 +1,60 @@ +package coinut + +import ( + "log" + "net/http" + + "github.com/gorilla/websocket" + "github.com/thrasher-/gocryptotrader/common" +) + +const COINUT_WEBSOCKET_URL = "wss://wsapi.coinut.com" + +func (c *COINUT) WebsocketClient() { + for c.Enabled && c.Websocket { + var Dialer websocket.Dialer + var err error + c.WebsocketConn, _, err = Dialer.Dial(c.WebsocketURL, http.Header{}) + + if err != nil { + log.Printf("%s Unable to connect to Websocket. Error: %s\n", c.Name, err) + continue + } + + if c.Verbose { + log.Printf("%s Connected to Websocket.\n", c.Name) + } + + err = c.WebsocketConn.WriteMessage(websocket.TextMessage, []byte(`{"messageType": "hello_world"}`)) + + if err != nil { + log.Println(err) + return + } + + for c.Enabled && c.Websocket { + msgType, resp, err := c.WebsocketConn.ReadMessage() + if err != nil { + log.Println(err) + break + } + + switch msgType { + case websocket.TextMessage: + type MsgType struct { + MessageType string `json:"messageType"` + } + + msgType := MsgType{} + err := common.JSONDecode(resp, &msgType) + if err != nil { + log.Println(err) + continue + } + log.Println(string(resp)) + } + } + c.WebsocketConn.Close() + log.Printf("%s Websocket client disconnected.", c.Name) + } +} diff --git a/exchanges/coinut/coinut_wrapper.go b/exchanges/coinut/coinut_wrapper.go new file mode 100644 index 00000000..213db2e2 --- /dev/null +++ b/exchanges/coinut/coinut_wrapper.go @@ -0,0 +1,129 @@ +package coinut + +import ( + "log" + "time" + + "github.com/thrasher-/gocryptotrader/common" + "github.com/thrasher-/gocryptotrader/currency/pair" + "github.com/thrasher-/gocryptotrader/exchanges" + "github.com/thrasher-/gocryptotrader/exchanges/orderbook" + "github.com/thrasher-/gocryptotrader/exchanges/stats" + "github.com/thrasher-/gocryptotrader/exchanges/ticker" +) + +func (c *COINUT) Start() { + go c.Run() +} + +func (c *COINUT) Run() { + if c.Verbose { + log.Printf("%s Websocket: %s. (url: %s).\n", c.GetName(), common.IsEnabled(c.Websocket), COINUT_WEBSOCKET_URL) + log.Printf("%s polling delay: %ds.\n", c.GetName(), c.RESTPollingDelay) + log.Printf("%s %d currencies enabled: %s.\n", c.GetName(), len(c.EnabledPairs), c.EnabledPairs) + } + + if c.Websocket { + go c.WebsocketClient() + } + + exchangeProducts, err := c.GetInstruments() + if err != nil { + log.Printf("%s Failed to get available products.\n", c.GetName()) + return + } + + currencies := []string{} + c.InstrumentMap = make(map[string]int) + for x, y := range exchangeProducts.Instruments { + c.InstrumentMap[x] = y[0].InstID + currencies = append(currencies, x) + } + + err = c.UpdateAvailableCurrencies(currencies) + if err != nil { + log.Printf("%s Failed to get config.\n", c.GetName()) + } + + for c.Enabled { + for _, x := range c.EnabledPairs { + currency := pair.NewCurrencyPair(x[0:3], x[3:]) + go func() { + ticker, err := c.GetTickerPrice(currency) + if err != nil { + log.Println(err) + return + } + log.Printf("COINUT %s: Last %f High %f Low %f Volume %f\n", currency.Pair().String(), ticker.Last, ticker.High, ticker.Low, ticker.Volume) + stats.AddExchangeInfo(c.GetName(), currency.GetFirstCurrency().String(), currency.GetSecondCurrency().String(), ticker.Last, ticker.Volume) + }() + } + time.Sleep(time.Second * c.RESTPollingDelay) + } +} + +//GetExchangeAccountInfo : Retrieves balances for all enabled currencies for the COINUT exchange +func (e *COINUT) GetExchangeAccountInfo() (exchange.ExchangeAccountInfo, error) { + var response exchange.ExchangeAccountInfo + /* + response.ExchangeName = e.GetName() + accountBalance, err := e.GetAccounts() + if err != nil { + return response, err + } + for i := 0; i < len(accountBalance); i++ { + var exchangeCurrency exchange.ExchangeAccountCurrencyInfo + exchangeCurrency.CurrencyName = accountBalance[i].Currency + exchangeCurrency.TotalValue = accountBalance[i].Available + exchangeCurrency.Hold = accountBalance[i].Hold + + response.Currencies = append(response.Currencies, exchangeCurrency) + } + */ + return response, nil +} + +func (c *COINUT) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { + tickerNew, err := ticker.GetTicker(c.GetName(), p) + if err == nil { + return tickerNew, nil + } + + var tickerPrice ticker.TickerPrice + tick, err := c.GetInstrumentTicker(c.InstrumentMap[p.Pair().String()]) + if err != nil { + return ticker.TickerPrice{}, err + } + + tickerPrice.Pair = p + tickerPrice.Volume = tick.Volume + tickerPrice.Last = tick.Last + tickerPrice.High = tick.HighestBuy + tickerPrice.Low = tick.LowestSell + ticker.ProcessTicker(c.GetName(), p, tickerPrice) + return tickerPrice, nil +} + +func (c *COINUT) GetOrderbookEx(p pair.CurrencyPair) (orderbook.OrderbookBase, error) { + ob, err := orderbook.GetOrderbook(c.GetName(), p) + if err == nil { + return ob, nil + } + + var orderBook orderbook.OrderbookBase + orderbookNew, err := c.GetInstrumentOrderbook(c.InstrumentMap[p.Pair().String()], 200) + if err != nil { + return orderBook, err + } + + for x := range orderbookNew.Buy { + orderBook.Bids = append(orderBook.Bids, orderbook.OrderbookItem{Amount: orderbookNew.Buy[x].Quantity, Price: orderbookNew.Buy[x].Price}) + } + + for x := range orderbookNew.Sell { + orderBook.Asks = append(orderBook.Asks, orderbook.OrderbookItem{Amount: orderbookNew.Sell[x].Quantity, Price: orderbookNew.Sell[x].Price}) + } + orderBook.Pair = p + orderbook.ProcessOrderbook(c.GetName(), p, orderBook) + return orderBook, nil +} diff --git a/main.go b/main.go index 0fe9af7d..7c9d95b6 100644 --- a/main.go +++ b/main.go @@ -19,6 +19,7 @@ import ( "github.com/thrasher-/gocryptotrader/exchanges/btcc" "github.com/thrasher-/gocryptotrader/exchanges/btce" "github.com/thrasher-/gocryptotrader/exchanges/btcmarkets" + "github.com/thrasher-/gocryptotrader/exchanges/coinut" "github.com/thrasher-/gocryptotrader/exchanges/gdax" "github.com/thrasher-/gocryptotrader/exchanges/gemini" "github.com/thrasher-/gocryptotrader/exchanges/huobi" @@ -41,6 +42,7 @@ type ExchangeMain struct { bitfinex bitfinex.Bitfinex btce btce.BTCE btcmarkets btcmarkets.BTCMarkets + coinut coinut.COINUT gdax gdax.GDAX gemini gemini.Gemini okcoinChina okcoin.OKCoin @@ -119,6 +121,7 @@ func main() { new(bitfinex.Bitfinex), new(btce.BTCE), new(btcmarkets.BTCMarkets), + new(coinut.COINUT), new(gdax.GDAX), new(gemini.Gemini), new(okcoin.OKCoin),