Merge pull request #96 from shazbert/master

Added function for IBotExchange interface and fixed linter issues within exchange packages.
This commit is contained in:
Adrian Gallagher
2018-02-26 17:09:09 +11:00
committed by GitHub
53 changed files with 1619 additions and 1181 deletions

View File

@@ -1,6 +1,8 @@
package alphapoint
import (
"errors"
"github.com/thrasher-/gocryptotrader/currency/pair"
"github.com/thrasher-/gocryptotrader/exchanges"
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
@@ -86,3 +88,10 @@ func (a *Alphapoint) GetOrderbookEx(p pair.CurrencyPair, assetType string) (orde
}
return ob, nil
}
// GetExchangeHistory returns historic trade data since exchange opening.
func (a *Alphapoint) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
var resp []exchange.TradeHistory
return resp, errors.New("trade history not yet implemented")
}

View File

@@ -15,24 +15,26 @@ import (
)
const (
ANX_API_URL = "https://anxpro.com/"
ANX_API_VERSION = "3"
ANX_APIKEY = "apiKey"
ANX_DATA_TOKEN = "dataToken"
ANX_ORDER_NEW = "order/new"
ANX_ORDER_INFO = "order/info"
ANX_SEND = "send"
ANX_SUBACCOUNT_NEW = "subaccount/new"
ANX_RECEIVE_ADDRESS = "receive"
ANX_CREATE_ADDRESS = "receive/create"
ANX_TICKER = "money/ticker"
ANX_DEPTH = "money/depth/full"
anxAPIURL = "https://anxpro.com/"
anxAPIVersion = "3"
anxAPIKey = "apiKey"
anxDataToken = "dataToken"
anxOrderNew = "order/new"
anxOrderInfo = "order/info"
anxSend = "send"
anxSubaccountNew = "subaccount/new"
anxReceieveAddress = "receive"
anxCreateAddress = "receive/create"
anxTicker = "money/ticker"
anxDepth = "money/depth/full"
)
// ANX is the overarching type across the alphapoint package
type ANX struct {
exchange.Base
}
// SetDefaults sets current default settings
func (a *ANX) SetDefaults() {
a.Name = "ANX"
a.Enabled = false
@@ -75,6 +77,7 @@ func (a *ANX) Setup(exch config.ExchangeConfig) {
}
}
// GetFee returns maker or taker fees
func (a *ANX) GetFee(maker bool) float64 {
if maker {
return a.MakerFee
@@ -82,24 +85,23 @@ func (a *ANX) GetFee(maker bool) float64 {
return a.TakerFee
}
func (a *ANX) GetTicker(currency string) (ANXTicker, error) {
var ticker ANXTicker
err := common.SendHTTPGetRequest(fmt.Sprintf("%sapi/2/%s/%s", ANX_API_URL, currency, ANX_TICKER), true, a.Verbose, &ticker)
if err != nil {
return ANXTicker{}, err
}
return ticker, nil
// GetTicker returns the current ticker
func (a *ANX) GetTicker(currency string) (Ticker, error) {
var ticker Ticker
path := fmt.Sprintf("%sapi/2/%s/%s", anxAPIURL, currency, anxTicker)
return ticker, common.SendHTTPGetRequest(path, true, a.Verbose, &ticker)
}
// GetDepth returns current orderbook depth.
func (a *ANX) GetDepth(currency string) (Depth, error) {
var depth Depth
err := common.SendHTTPGetRequest(fmt.Sprintf("%sapi/2/%s/%s", ANX_API_URL, currency, ANX_DEPTH), true, a.Verbose, &depth)
if err != nil {
return depth, err
}
return depth, nil
path := fmt.Sprintf("%sapi/2/%s/%s", anxAPIURL, currency, anxDepth)
return depth, common.SendHTTPGetRequest(path, true, a.Verbose, &depth)
}
// GetAPIKey returns a new generated API key set.
func (a *ANX) GetAPIKey(username, password, otp, deviceID string) (string, string, error) {
request := make(map[string]interface{})
request["nonce"] = strconv.FormatInt(time.Now().UnixNano(), 10)[0:13]
@@ -120,7 +122,7 @@ func (a *ANX) GetAPIKey(username, password, otp, deviceID string) (string, strin
}
var response APIKeyResponse
err := a.SendAuthenticatedHTTPRequest(ANX_APIKEY, request, &response)
err := a.SendAuthenticatedHTTPRequest(anxAPIKey, request, &response)
if err != nil {
return "", "", err
}
@@ -132,6 +134,7 @@ func (a *ANX) GetAPIKey(username, password, otp, deviceID string) (string, strin
return response.APIKey, response.APISecret, nil
}
// GetDataToken returns token data
func (a *ANX) GetDataToken() (string, error) {
request := make(map[string]interface{})
@@ -143,7 +146,7 @@ func (a *ANX) GetDataToken() (string, error) {
}
var response DataTokenResponse
err := a.SendAuthenticatedHTTPRequest(ANX_DATA_TOKEN, request, &response)
err := a.SendAuthenticatedHTTPRequest(anxDataToken, request, &response)
if err != nil {
return "", err
}
@@ -154,11 +157,12 @@ func (a *ANX) GetDataToken() (string, error) {
return response.Token, nil
}
// NewOrder sends a new order request to the exchange.
func (a *ANX) NewOrder(orderType string, buy bool, tradedCurrency, tradedCurrencyAmount, settlementCurrency, settlementCurrencyAmount, limitPriceSettlement string,
replace bool, replaceUUID string, replaceIfActive bool) error {
request := make(map[string]interface{})
var order ANXOrder
var order Order
order.OrderType = orderType
order.BuyTradedCurrency = buy
@@ -186,7 +190,7 @@ func (a *ANX) NewOrder(orderType string, buy bool, tradedCurrency, tradedCurrenc
}
var response OrderResponse
err := a.SendAuthenticatedHTTPRequest(ANX_ORDER_NEW, request, &response)
err := a.SendAuthenticatedHTTPRequest(anxOrderNew, request, &response)
if err != nil {
return err
}
@@ -197,30 +201,32 @@ func (a *ANX) NewOrder(orderType string, buy bool, tradedCurrency, tradedCurrenc
return nil
}
func (a *ANX) OrderInfo(orderID string) (ANXOrderResponse, error) {
// OrderInfo returns information about a specific order
func (a *ANX) OrderInfo(orderID string) (OrderResponse, error) {
request := make(map[string]interface{})
request["orderId"] = orderID
type OrderInfoResponse struct {
Order ANXOrderResponse `json:"order"`
ResultCode string `json:"resultCode"`
Timestamp int64 `json:"timestamp"`
Order OrderResponse `json:"order"`
ResultCode string `json:"resultCode"`
Timestamp int64 `json:"timestamp"`
}
var response OrderInfoResponse
err := a.SendAuthenticatedHTTPRequest(ANX_ORDER_INFO, request, &response)
err := a.SendAuthenticatedHTTPRequest(anxOrderInfo, request, &response)
if err != nil {
return ANXOrderResponse{}, err
return OrderResponse{}, err
}
if response.ResultCode != "OK" {
log.Printf("Response code is not OK: %s\n", response.ResultCode)
return ANXOrderResponse{}, errors.New(response.ResultCode)
return OrderResponse{}, errors.New(response.ResultCode)
}
return response.Order, nil
}
// Send withdraws a currency to an address
func (a *ANX) Send(currency, address, otp, amount string) (string, error) {
request := make(map[string]interface{})
request["ccy"] = currency
@@ -238,7 +244,7 @@ func (a *ANX) Send(currency, address, otp, amount string) (string, error) {
}
var response SendResponse
err := a.SendAuthenticatedHTTPRequest(ANX_SEND, request, &response)
err := a.SendAuthenticatedHTTPRequest(anxSend, request, &response)
if err != nil {
return "", err
@@ -251,6 +257,7 @@ func (a *ANX) Send(currency, address, otp, amount string) (string, error) {
return response.TransactionID, nil
}
// CreateNewSubAccount generates a new sub account
func (a *ANX) CreateNewSubAccount(currency, name string) (string, error) {
request := make(map[string]interface{})
request["ccy"] = currency
@@ -263,7 +270,7 @@ func (a *ANX) CreateNewSubAccount(currency, name string) (string, error) {
}
var response SubaccountResponse
err := a.SendAuthenticatedHTTPRequest(ANX_SUBACCOUNT_NEW, request, &response)
err := a.SendAuthenticatedHTTPRequest(anxSubaccountNew, request, &response)
if err != nil {
return "", err
@@ -276,6 +283,7 @@ func (a *ANX) CreateNewSubAccount(currency, name string) (string, error) {
return response.SubAccount, nil
}
// GetDepositAddress returns a deposit address for a specific currency
func (a *ANX) GetDepositAddress(currency, name string, new bool) (string, error) {
request := make(map[string]interface{})
request["ccy"] = currency
@@ -292,9 +300,9 @@ func (a *ANX) GetDepositAddress(currency, name string, new bool) (string, error)
}
var response AddressResponse
path := ANX_RECEIVE_ADDRESS
path := anxReceieveAddress
if new {
path = ANX_CREATE_ADDRESS
path = anxCreateAddress
}
err := a.SendAuthenticatedHTTPRequest(path, request, &response)
@@ -311,6 +319,7 @@ func (a *ANX) GetDepositAddress(currency, name string, new bool) (string, error)
return response.Address, nil
}
// SendAuthenticatedHTTPRequest sends a authenticated HTTP request
func (a *ANX) SendAuthenticatedHTTPRequest(path string, params map[string]interface{}, result interface{}) error {
if !a.AuthenticatedAPISupport {
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, a.Name)
@@ -324,7 +333,7 @@ func (a *ANX) SendAuthenticatedHTTPRequest(path string, params map[string]interf
request := make(map[string]interface{})
request["nonce"] = a.Nonce.String()[0:13]
path = fmt.Sprintf("api/%s/%s", ANX_API_VERSION, path)
path = fmt.Sprintf("api/%s/%s", anxAPIVersion, path)
if params != nil {
for key, value := range params {
@@ -348,7 +357,10 @@ func (a *ANX) SendAuthenticatedHTTPRequest(path string, params map[string]interf
headers["Rest-Sign"] = common.Base64Encode([]byte(hmac))
headers["Content-Type"] = "application/json"
resp, err := common.SendHTTPRequest("POST", ANX_API_URL+path, headers, bytes.NewBuffer(PayloadJSON))
resp, err := common.SendHTTPRequest("POST", anxAPIURL+path, headers, bytes.NewBuffer(PayloadJSON))
if err != nil {
return err
}
if a.Verbose {
log.Printf("Received raw: \n%s\n", resp)

View File

@@ -1,6 +1,7 @@
package anx
type ANXOrder struct {
// Order holds order information
type Order struct {
OrderType string `json:"orderType"`
BuyTradedCurrency bool `json:"buyTradedCurrency"`
TradedCurrency string `json:"tradedCurrency"`
@@ -12,7 +13,8 @@ type ANXOrder struct {
ReplaceOnlyIfActive bool `json:"replaceOnlyIfActive"`
}
type ANXOrderResponse struct {
// OrderResponse holds order response data
type OrderResponse struct {
BuyTradedCurrency bool `json:"buyTradedCurrency"`
ExecutedAverageRate string `json:"executedAverageRate"`
LimitPriceInSettlementCurrency string `json:"limitPriceInSettlementCurrency"`
@@ -29,29 +31,32 @@ type ANXOrderResponse struct {
TradedCurrencyOutstanding string `json:"tradedCurrencyOutstanding"`
}
type ANXTickerComponent struct {
// TickerComponent is a sub-type for ticker
type TickerComponent struct {
Currency string `json:"currency"`
Display string `json:"display"`
DisplayShort string `json:"display_short"`
Value string `json:"value"`
}
type ANXTicker struct {
// Ticker contains ticker data
type Ticker struct {
Result string `json:"result"`
Data struct {
High ANXTickerComponent `json:"high"`
Low ANXTickerComponent `json:"low"`
Avg ANXTickerComponent `json:"avg"`
Vwap ANXTickerComponent `json:"vwap"`
Vol ANXTickerComponent `json:"vol"`
Last ANXTickerComponent `json:"last"`
Buy ANXTickerComponent `json:"buy"`
Sell ANXTickerComponent `json:"sell"`
Now string `json:"now"`
UpdateTime string `json:"dataUpdateTime"`
High TickerComponent `json:"high"`
Low TickerComponent `json:"low"`
Avg TickerComponent `json:"avg"`
Vwap TickerComponent `json:"vwap"`
Vol TickerComponent `json:"vol"`
Last TickerComponent `json:"last"`
Buy TickerComponent `json:"buy"`
Sell TickerComponent `json:"sell"`
Now string `json:"now"`
UpdateTime string `json:"dataUpdateTime"`
} `json:"data"`
}
// DepthItem contains depth information
type DepthItem struct {
Price float64 `json:"price,string"`
PriceInt float64 `json:"price_int,string"`
@@ -59,12 +64,13 @@ type DepthItem struct {
AmountInt int64 `json:"amount_int,string"`
}
// Depth contains full depth information
type Depth struct {
Result string `json:"result"`
Data struct {
Now string `json:"now"`
DataUpdateTime string `json:"dataUpdateTime"`
Asks []DepthItem `json:"asks`
Asks []DepthItem `json:"asks"`
Bids []DepthItem `json:"bids"`
} `json:"data"`
}

View File

@@ -1,6 +1,7 @@
package anx
import (
"errors"
"log"
"strconv"
@@ -134,3 +135,10 @@ func (a *ANX) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
response.ExchangeName = a.GetName()
return response, nil
}
// GetExchangeHistory returns historic trade data since exchange opening.
func (a *ANX) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
var resp []exchange.TradeHistory
return resp, errors.New("trade history not yet implemented")
}

View File

@@ -120,3 +120,10 @@ func (b *Binance) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
var response exchange.AccountInfo
return response, errors.New("not implemented")
}
// GetExchangeHistory returns historic trade data since exchange opening.
func (b *Binance) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
var resp []exchange.TradeHistory
return resp, errors.New("trade history not yet implemented")
}

View File

@@ -1,6 +1,7 @@
package bitfinex
import (
"errors"
"log"
"net/url"
@@ -156,3 +157,10 @@ func (b *Bitfinex) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
return response, nil
}
// GetExchangeHistory returns historic trade data since exchange opening.
func (b *Bitfinex) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
var resp []exchange.TradeHistory
return resp, errors.New("trade history not yet implemented")
}

View File

@@ -132,3 +132,10 @@ func (b *Bitflyer) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
return response, nil
}
// GetExchangeHistory returns historic trade data since exchange opening.
func (b *Bitflyer) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
var resp []exchange.TradeHistory
return resp, errors.New("trade history not yet implemented")
}

View File

@@ -92,3 +92,10 @@ func (b *Bithumb) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
var response exchange.AccountInfo
return response, errors.New("not implemented")
}
// GetExchangeHistory returns historic trade data since exchange opening.
func (b *Bithumb) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
var resp []exchange.TradeHistory
return resp, errors.New("trade history not yet implemented")
}

View File

@@ -1,6 +1,7 @@
package bitstamp
import (
"errors"
"log"
"github.com/thrasher-/gocryptotrader/common"
@@ -122,3 +123,10 @@ func (b *Bitstamp) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
})
return response, nil
}
// GetExchangeHistory returns historic trade data since exchange opening.
func (b *Bitstamp) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
var resp []exchange.TradeHistory
return resp, errors.New("trade history not yet implemented")
}

View File

@@ -1,6 +1,7 @@
package bittrex
import (
"errors"
"log"
"github.com/thrasher-/gocryptotrader/common"
@@ -147,3 +148,10 @@ func (b *Bittrex) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderb
orderbook.ProcessOrderbook(b.GetName(), p, orderBook, assetType)
return orderbook.GetOrderbook(b.Name, p, assetType)
}
// GetExchangeHistory returns historic trade data since exchange opening.
func (b *Bittrex) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
var resp []exchange.TradeHistory
return resp, errors.New("trade history not yet implemented")
}

View File

@@ -139,6 +139,7 @@ func (b *BTCC) GetOrderBook(currencyPair string, limit int) (Orderbook, error) {
return result, common.SendHTTPGetRequest(req, true, b.Verbose, &result)
}
// GetAccountInfo returns account information
func (b *BTCC) GetAccountInfo(infoType string) error {
params := make([]interface{}, 0)
@@ -149,6 +150,7 @@ func (b *BTCC) GetAccountInfo(infoType string) error {
return b.SendAuthenticatedHTTPRequest(btccAccountInfo, params)
}
// PlaceOrder places a new order
func (b *BTCC) PlaceOrder(buyOrder bool, price, amount float64, symbol string) {
params := make([]interface{}, 0)
params = append(params, strconv.FormatFloat(price, 'f', -1, 64))
@@ -170,6 +172,7 @@ func (b *BTCC) PlaceOrder(buyOrder bool, price, amount float64, symbol string) {
}
}
// CancelOrder cancels an order
func (b *BTCC) CancelOrder(orderID int64, symbol string) {
params := make([]interface{}, 0)
params = append(params, orderID)
@@ -185,6 +188,7 @@ func (b *BTCC) CancelOrder(orderID int64, symbol string) {
}
}
// GetDeposits returns deposit information
func (b *BTCC) GetDeposits(currency string, pending bool) {
params := make([]interface{}, 0)
params = append(params, currency)
@@ -200,6 +204,7 @@ func (b *BTCC) GetDeposits(currency string, pending bool) {
}
}
// GetMarketDepth returns market depth at limit
func (b *BTCC) GetMarketDepth(symbol string, limit int64) {
params := make([]interface{}, 0)
@@ -218,6 +223,7 @@ func (b *BTCC) GetMarketDepth(symbol string, limit int64) {
}
}
// GetOrder returns information about a specific order
func (b *BTCC) GetOrder(orderID int64, symbol string, detailed bool) {
params := make([]interface{}, 0)
params = append(params, orderID)
@@ -237,6 +243,7 @@ func (b *BTCC) GetOrder(orderID int64, symbol string, detailed bool) {
}
}
// GetOrders returns information of a range of orders
func (b *BTCC) GetOrders(openonly bool, symbol string, limit, offset, since int64, detailed bool) {
params := make([]interface{}, 0)
@@ -271,6 +278,7 @@ func (b *BTCC) GetOrders(openonly bool, symbol string, limit, offset, since int6
}
}
// GetTransactions returns transaction lists
func (b *BTCC) GetTransactions(transType string, limit, offset, since int64, sinceType string) {
params := make([]interface{}, 0)
@@ -301,6 +309,7 @@ func (b *BTCC) GetTransactions(transType string, limit, offset, since int64, sin
}
}
// GetWithdrawal returns information about a withdrawal process
func (b *BTCC) GetWithdrawal(withdrawalID int64, currency string) {
params := make([]interface{}, 0)
params = append(params, withdrawalID)
@@ -316,6 +325,7 @@ func (b *BTCC) GetWithdrawal(withdrawalID int64, currency string) {
}
}
// GetWithdrawals gets information about all withdrawals
func (b *BTCC) GetWithdrawals(currency string, pending bool) {
params := make([]interface{}, 0)
params = append(params, currency)
@@ -331,6 +341,7 @@ func (b *BTCC) GetWithdrawals(currency string, pending bool) {
}
}
// RequestWithdrawal requests a new withdrawal
func (b *BTCC) RequestWithdrawal(currency string, amount float64) {
params := make([]interface{}, 0)
params = append(params, currency)
@@ -343,6 +354,8 @@ func (b *BTCC) RequestWithdrawal(currency string, amount float64) {
}
}
// IcebergOrder intiates a large order but at intervals to preserve orderbook
// integrity
func (b *BTCC) IcebergOrder(buyOrder bool, price, amount, discAmount, variance float64, symbol string) {
params := make([]interface{}, 0)
params = append(params, strconv.FormatFloat(price, 'f', -1, 64))
@@ -366,6 +379,7 @@ func (b *BTCC) IcebergOrder(buyOrder bool, price, amount, discAmount, variance f
}
}
// GetIcebergOrder returns information on your iceberg order
func (b *BTCC) GetIcebergOrder(orderID int64, symbol string) {
params := make([]interface{}, 0)
params = append(params, orderID)
@@ -381,6 +395,7 @@ func (b *BTCC) GetIcebergOrder(orderID int64, symbol string) {
}
}
// GetIcebergOrders returns information on all iceberg orders
func (b *BTCC) GetIcebergOrders(limit, offset int64, symbol string) {
params := make([]interface{}, 0)
@@ -403,6 +418,7 @@ func (b *BTCC) GetIcebergOrders(limit, offset int64, symbol string) {
}
}
// CancelIcebergOrder cancels iceberg order
func (b *BTCC) CancelIcebergOrder(orderID int64, symbol string) {
params := make([]interface{}, 0)
params = append(params, orderID)
@@ -418,6 +434,7 @@ func (b *BTCC) CancelIcebergOrder(orderID int64, symbol string) {
}
}
// PlaceStopOrder inserts a stop loss order
func (b *BTCC) PlaceStopOrder(buyOder bool, stopPrice, price, amount, trailingAmt, trailingPct float64, symbol string) {
params := make([]interface{}, 0)
@@ -452,6 +469,7 @@ func (b *BTCC) PlaceStopOrder(buyOder bool, stopPrice, price, amount, trailingAm
}
}
// GetStopOrder returns a stop order
func (b *BTCC) GetStopOrder(orderID int64, symbol string) {
params := make([]interface{}, 0)
params = append(params, orderID)
@@ -467,6 +485,7 @@ func (b *BTCC) GetStopOrder(orderID int64, symbol string) {
}
}
// GetStopOrders returns all stop orders
func (b *BTCC) GetStopOrders(status, orderType string, stopPrice float64, limit, offset int64, symbol string) {
params := make([]interface{}, 0)
@@ -501,6 +520,7 @@ func (b *BTCC) GetStopOrders(status, orderType string, stopPrice float64, limit,
}
}
// CancelStopOrder cancels a stop order
func (b *BTCC) CancelStopOrder(orderID int64, symbol string) {
params := make([]interface{}, 0)
params = append(params, orderID)
@@ -516,6 +536,7 @@ func (b *BTCC) CancelStopOrder(orderID int64, symbol string) {
}
}
// SendAuthenticatedHTTPRequest sends a valid authenticated HTTP request
func (b *BTCC) SendAuthenticatedHTTPRequest(method string, params []interface{}) (err error) {
if !b.AuthenticatedAPISupport {
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, b.Name)

View File

@@ -9,11 +9,13 @@ import (
)
const (
BTCC_SOCKETIO_ADDRESS = "https://websocket.btcc.com"
btccSocketioAddress = "https://websocket.btcc.com"
)
// BTCCSocket is a pointer to a IO socket
var BTCCSocket *socketio.SocketIO
// OnConnect gets information from the server when its connected
func (b *BTCC) OnConnect(output chan socketio.Message) {
if b.Verbose {
log.Printf("%s Connected to Websocket.", b.GetName())
@@ -37,16 +39,19 @@ func (b *BTCC) OnConnect(output chan socketio.Message) {
}
}
// OnDisconnect alerts when disconnection occurs
func (b *BTCC) OnDisconnect(output chan socketio.Message) {
log.Printf("%s Disconnected from websocket server.. Reconnecting.\n", b.GetName())
b.WebsocketClient()
}
// OnError alerts when error occurs
func (b *BTCC) OnError() {
log.Printf("%s Error with Websocket connection.. Reconnecting.\n", b.GetName())
b.WebsocketClient()
}
// OnMessage if message received and verbose it is printed out
func (b *BTCC) OnMessage(message []byte, output chan socketio.Message) {
if b.Verbose {
log.Printf("%s Websocket message received which isn't handled by default.\n", b.GetName())
@@ -54,6 +59,7 @@ func (b *BTCC) OnMessage(message []byte, output chan socketio.Message) {
}
}
// OnTicker handles ticker information
func (b *BTCC) OnTicker(message []byte, output chan socketio.Message) {
type Response struct {
Ticker WebsocketTicker `json:"ticker"`
@@ -67,6 +73,7 @@ func (b *BTCC) OnTicker(message []byte, output chan socketio.Message) {
}
}
// OnGroupOrder handles group order information
func (b *BTCC) OnGroupOrder(message []byte, output chan socketio.Message) {
type Response struct {
GroupOrder WebsocketGroupOrder `json:"grouporder"`
@@ -80,6 +87,7 @@ func (b *BTCC) OnGroupOrder(message []byte, output chan socketio.Message) {
}
}
// OnTrade handles group trade information
func (b *BTCC) OnTrade(message []byte, output chan socketio.Message) {
trade := WebsocketTrade{}
err := common.JSONDecode(message, &trade)
@@ -90,6 +98,7 @@ func (b *BTCC) OnTrade(message []byte, output chan socketio.Message) {
}
}
// WebsocketClient initiates a websocket client
func (b *BTCC) WebsocketClient() {
events := make(map[string]func(message []byte, output chan socketio.Message))
events["grouporder"] = b.OnGroupOrder
@@ -106,7 +115,7 @@ func (b *BTCC) WebsocketClient() {
}
for b.Enabled && b.Websocket {
err := socketio.ConnectToSocket(BTCC_SOCKETIO_ADDRESS, BTCCSocket)
err := socketio.ConnectToSocket(btccSocketioAddress, BTCCSocket)
if err != nil {
log.Printf("%s Unable to connect to Websocket. Err: %s\n", b.GetName(), err)
continue

View File

@@ -1,6 +1,7 @@
package btcc
import (
"errors"
"log"
"github.com/thrasher-/gocryptotrader/common"
@@ -126,3 +127,10 @@ func (b *BTCC) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
response.ExchangeName = b.GetName()
return response, nil
}
// GetExchangeHistory returns historic trade data since exchange opening.
func (b *BTCC) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
var resp []exchange.TradeHistory
return resp, errors.New("trade history not yet implemented")
}

View File

@@ -1,6 +1,7 @@
package btcmarkets
import (
"errors"
"log"
"github.com/thrasher-/gocryptotrader/common"
@@ -126,3 +127,10 @@ func (b *BTCMarkets) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
}
return response, nil
}
// GetExchangeHistory returns historic trade data since exchange opening.
func (b *BTCMarkets) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
var resp []exchange.TradeHistory
return resp, errors.New("trade history not yet implemented")
}

View File

@@ -84,8 +84,8 @@ func (c *COINUT) Setup(exch config.ExchangeConfig) {
}
// GetInstruments returns instruments
func (c *COINUT) GetInstruments() (CoinutInstruments, error) {
var result CoinutInstruments
func (c *COINUT) GetInstruments() (Instruments, error) {
var result Instruments
params := make(map[string]interface{})
params["sec_type"] = "SPOT"
err := c.SendHTTPRequest(coinutInstruments, params, false, &result)
@@ -95,8 +95,9 @@ func (c *COINUT) GetInstruments() (CoinutInstruments, error) {
return result, nil
}
func (c *COINUT) GetInstrumentTicker(instrumentID int) (CoinutTicker, error) {
var result CoinutTicker
// GetInstrumentTicker returns a ticker for a specific instrument
func (c *COINUT) GetInstrumentTicker(instrumentID int) (Ticker, error) {
var result Ticker
params := make(map[string]interface{})
params["inst_id"] = instrumentID
err := c.SendHTTPRequest(coinutTicker, params, false, &result)
@@ -106,8 +107,9 @@ func (c *COINUT) GetInstrumentTicker(instrumentID int) (CoinutTicker, error) {
return result, nil
}
func (c *COINUT) GetInstrumentOrderbook(instrumentID, limit int) (CoinutOrderbook, error) {
var result CoinutOrderbook
// GetInstrumentOrderbook returns the orderbooks for a specific instrument
func (c *COINUT) GetInstrumentOrderbook(instrumentID, limit int) (Orderbook, error) {
var result Orderbook
params := make(map[string]interface{})
params["inst_id"] = instrumentID
if limit > 0 {
@@ -120,8 +122,9 @@ func (c *COINUT) GetInstrumentOrderbook(instrumentID, limit int) (CoinutOrderboo
return result, nil
}
func (c *COINUT) GetTrades(instrumentID int) (CoinutTrades, error) {
var result CoinutTrades
// GetTrades returns trade information
func (c *COINUT) GetTrades(instrumentID int) (Trades, error) {
var result Trades
params := make(map[string]interface{})
params["inst_id"] = instrumentID
err := c.SendHTTPRequest(coinutTrades, params, false, &result)
@@ -131,8 +134,9 @@ func (c *COINUT) GetTrades(instrumentID int) (CoinutTrades, error) {
return result, nil
}
func (c *COINUT) GetUserBalance() (CoinutUserBalance, error) {
result := CoinutUserBalance{}
// GetUserBalance returns the full user balance
func (c *COINUT) GetUserBalance() (UserBalance, error) {
result := UserBalance{}
err := c.SendHTTPRequest(coinutBalance, nil, true, &result)
if err != nil {
return result, err
@@ -140,6 +144,7 @@ func (c *COINUT) GetUserBalance() (CoinutUserBalance, error) {
return result, nil
}
// NewOrder places a new order on the exchange
func (c *COINUT) NewOrder(instrumentID int, quantity, price float64, buy bool, orderID uint32) (interface{}, error) {
var result interface{}
params := make(map[string]interface{})
@@ -159,8 +164,9 @@ func (c *COINUT) NewOrder(instrumentID int, quantity, price float64, buy bool, o
return result, nil
}
func (c *COINUT) NewOrders(orders []CoinutOrder) ([]CoinutOrdersBase, error) {
var result CoinutOrdersResponse
// NewOrders places multiple orders on the exchange
func (c *COINUT) NewOrders(orders []Order) ([]OrdersBase, error) {
var result OrdersResponse
params := make(map[string]interface{})
params["orders"] = orders
err := c.SendHTTPRequest(coinutOrders, params, true, &result.Data)
@@ -170,8 +176,9 @@ func (c *COINUT) NewOrders(orders []CoinutOrder) ([]CoinutOrdersBase, error) {
return result.Data, nil
}
func (c *COINUT) GetOpenOrders(instrumentID int) ([]CoinutOrdersResponse, error) {
var result []CoinutOrdersResponse
// GetOpenOrders returns a list of open order and relevant information
func (c *COINUT) GetOpenOrders(instrumentID int) ([]OrdersResponse, error) {
var result []OrdersResponse
params := make(map[string]interface{})
params["inst_id"] = instrumentID
err := c.SendHTTPRequest(coinutOrdersOpen, params, true, &result)
@@ -181,8 +188,9 @@ func (c *COINUT) GetOpenOrders(instrumentID int) ([]CoinutOrdersResponse, error)
return result, nil
}
// CancelOrder cancels a specific order and returns if it was actioned
func (c *COINUT) CancelOrder(instrumentID, orderID int) (bool, error) {
var result CoinutGenericResponse
var result GenericResponse
params := make(map[string]interface{})
params["inst_id"] = instrumentID
params["order_id"] = orderID
@@ -193,8 +201,9 @@ func (c *COINUT) CancelOrder(instrumentID, orderID int) (bool, error) {
return true, nil
}
func (c *COINUT) CancelOrders(orders []CoinutCancelOrders) (CoinutCancelOrdersResponse, error) {
var result CoinutCancelOrdersResponse
// CancelOrders cancels multiple orders
func (c *COINUT) CancelOrders(orders []CancelOrders) (CancelOrdersResponse, error) {
var result CancelOrdersResponse
params := make(map[string]interface{})
params["entries"] = orders
err := c.SendHTTPRequest(coinutOrdersCancel, params, true, &result)
@@ -204,8 +213,9 @@ func (c *COINUT) CancelOrders(orders []CoinutCancelOrders) (CoinutCancelOrdersRe
return result, nil
}
func (c *COINUT) GetTradeHistory(instrumentID, start, limit int) (CoinutTradeHistory, error) {
var result CoinutTradeHistory
// GetTradeHistory returns trade history for a specific instrument.
func (c *COINUT) GetTradeHistory(instrumentID, start, limit int) (TradeHistory, error) {
var result TradeHistory
params := make(map[string]interface{})
params["inst_id"] = instrumentID
if start >= 0 && start <= 100 {
@@ -221,8 +231,9 @@ func (c *COINUT) GetTradeHistory(instrumentID, start, limit int) (CoinutTradeHis
return result, nil
}
func (c *COINUT) GetIndexTicker(asset string) (CoinutIndexTicker, error) {
var result CoinutIndexTicker
// GetIndexTicker returns the index ticker for an asset
func (c *COINUT) GetIndexTicker(asset string) (IndexTicker, error) {
var result IndexTicker
params := make(map[string]interface{})
params["asset"] = asset
err := c.SendHTTPRequest(coinutIndexTicker, params, false, &result)
@@ -232,6 +243,7 @@ func (c *COINUT) GetIndexTicker(asset string) (CoinutIndexTicker, error) {
return result, nil
}
// GetDerivativeInstruments returns a list of derivative instruments
func (c *COINUT) GetDerivativeInstruments(secType string) (interface{}, error) {
var result interface{} //to-do
params := make(map[string]interface{})
@@ -243,8 +255,9 @@ func (c *COINUT) GetDerivativeInstruments(secType string) (interface{}, error) {
return result, nil
}
func (c *COINUT) GetOptionChain(asset, secType string, expiry int64) (CoinutOptionChainResponse, error) {
var result CoinutOptionChainResponse
// GetOptionChain returns option chain
func (c *COINUT) GetOptionChain(asset, secType string, expiry int64) (OptionChainResponse, error) {
var result OptionChainResponse
params := make(map[string]interface{})
params["asset"] = asset
params["sec_type"] = secType
@@ -255,8 +268,9 @@ func (c *COINUT) GetOptionChain(asset, secType string, expiry int64) (CoinutOpti
return result, nil
}
func (c *COINUT) GetPositionHistory(secType string, start, limit int) (CoinutPositionHistory, error) {
var result CoinutPositionHistory
// GetPositionHistory returns position history
func (c *COINUT) GetPositionHistory(secType string, start, limit int) (PositionHistory, error) {
var result PositionHistory
params := make(map[string]interface{})
params["sec_type"] = secType
if start >= 0 {
@@ -272,9 +286,10 @@ func (c *COINUT) GetPositionHistory(secType string, start, limit int) (CoinutPos
return result, nil
}
func (c *COINUT) GetOpenPositions(instrumentID int) ([]CoinutOpenPosition, error) {
// GetOpenPositions returns all your current opened positions
func (c *COINUT) GetOpenPositions(instrumentID int) ([]OpenPosition, error) {
type Response struct {
Positions []CoinutOpenPosition `json:"positions"`
Positions []OpenPosition `json:"positions"`
}
var result Response
params := make(map[string]interface{})
@@ -289,6 +304,7 @@ func (c *COINUT) GetOpenPositions(instrumentID int) ([]CoinutOpenPosition, error
//to-do: user position update via websocket
// SendHTTPRequest sends an authenticated HTTP request
func (c *COINUT) SendHTTPRequest(apiRequest string, params map[string]interface{}, authenticated bool, result interface{}) (err error) {
if !c.AuthenticatedAPISupport && authenticated {
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, c.Name)
@@ -299,7 +315,6 @@ func (c *COINUT) SendHTTPRequest(apiRequest string, params map[string]interface{
} else {
c.Nonce.Inc()
}
payload := []byte("")
if params == nil {
params = map[string]interface{}{}
@@ -307,7 +322,7 @@ func (c *COINUT) SendHTTPRequest(apiRequest string, params map[string]interface{
params["nonce"] = c.Nonce.Get()
params["request"] = apiRequest
payload, err = common.JSONEncode(params)
payload, err := common.JSONEncode(params)
if err != nil {
return errors.New("SenddHTTPRequest: Unable to JSON request")
}
@@ -333,7 +348,7 @@ func (c *COINUT) SendHTTPRequest(apiRequest string, params map[string]interface{
log.Printf("Received raw: \n%s", resp)
}
genResp := CoinutGenericResponse{}
genResp := GenericResponse{}
err = common.JSONDecode([]byte(resp), &genResp)
if err != nil {
return errors.New("unable to JSON Unmarshal generic response")

View File

@@ -21,7 +21,6 @@ func TestSetDefaults(t *testing.T) {
func TestSetup(t *testing.T) {
t.Parallel()
c := COINUT{}
c.Name = "Coinut"
cfg := config.GetConfig()
cfg.LoadConfig("../../testdata/configtest.json")

View File

@@ -1,6 +1,7 @@
package coinut
type CoinutGenericResponse struct {
// GenericResponse is the generic response you will get from coinut
type GenericResponse struct {
Nonce int64 `json:"nonce"`
Reply string `json:"reply"`
Status []string `json:"status"`
@@ -8,18 +9,21 @@ type CoinutGenericResponse struct {
Timestamp int64 `json:"timestamp"`
}
type CoinutInstrumentBase struct {
// InstrumentBase holds information on base currency
type InstrumentBase 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"`
// Instruments holds the full information on base currencies
type Instruments struct {
Instruments map[string][]InstrumentBase `json:"SPOT"`
}
type CoinutTicker struct {
// Ticker holds ticker information
type Ticker struct {
HighestBuy float64 `json:"highest_buy,string"`
InstrumentID int `json:"inst_id"`
Last float64 `json:"last,string"`
@@ -31,22 +35,25 @@ type CoinutTicker struct {
Volume24 float64 `json:"volume24,string"`
}
type CoinutOrderbookBase struct {
// OrderbookBase is a sub-type holding price and quantity
type OrderbookBase struct {
Count int `json:"count"`
Price float64 `json:"price,string"`
Quantity float64 `json:"qty,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"`
// Orderbook is the full order book
type Orderbook struct {
Buy []OrderbookBase `json:"buy"`
Sell []OrderbookBase `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 {
// TradeBase is a sub-type holding information on trades
type TradeBase struct {
Price float64 `json:"price,string"`
Quantity float64 `json:"quantity,string"`
Side string `json:"side"`
@@ -54,11 +61,13 @@ type CoinutTradeBase struct {
TransID int64 `json:"trans_id"`
}
type CoinutTrades struct {
Trades []CoinutTradeBase `json:"trades"`
// Trades holds the full amount of trades associated with API keys
type Trades struct {
Trades []TradeBase `json:"trades"`
}
type CoinutUserBalance struct {
// UserBalance holds user balances on the exchange
type UserBalance struct {
BTC float64 `json:"btc,string"`
ETC float64 `json:"etc,string"`
ETH float64 `json:"eth,string"`
@@ -71,7 +80,8 @@ type CoinutUserBalance struct {
UnrealizedPL float64 `json:"unrealized_pl,string"`
}
type CoinutOrder struct {
// Order holds order information
type Order struct {
InstrumentID int64 `json:"inst_id"`
Price float64 `json:"price,string"`
Quantity float64 `json:"qty,string"`
@@ -79,7 +89,8 @@ type CoinutOrder struct {
Side string `json:"side,string"`
}
type CoinutOrderResponse struct {
// OrderResponse is a response for orders
type OrderResponse struct {
OrderID int64 `json:"order_id"`
OpenQuantity float64 `json:"open_qty,string"`
Price float64 `json:"price,string"`
@@ -91,40 +102,47 @@ type CoinutOrderResponse struct {
Side string `json:"side"`
}
type CoinutCommission struct {
// Commission holds trade commision structure
type Commission 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"`
// OrderFilledResponse contains order filled response
type OrderFilledResponse struct {
GenericResponse
Commission Commission `json:"commission"`
FillPrice float64 `json:"fill_price,string"`
FillQuantity float64 `json:"fill_qty,string"`
Order OrderResponse `json:"order"`
}
type CoinutOrderRejectResponse struct {
CoinutOrderResponse
// OrderRejectResponse holds information on a rejected order
type OrderRejectResponse struct {
OrderResponse
Reasons []string `json:"reasons"`
}
type CoinutOrdersBase struct {
CoinutGenericResponse
CoinutOrderResponse
// OrdersBase contains generic response and order responses
type OrdersBase struct {
GenericResponse
OrderResponse
}
type CoinutOrdersResponse struct {
Data []CoinutOrdersBase
// OrdersResponse holds the full data range on orders
type OrdersResponse struct {
Data []OrdersBase
}
type CoinutCancelOrders struct {
// CancelOrders holds information about a cancelled order
type CancelOrders struct {
InstrumentID int `json:"int"`
OrderID int64 `json:"order_id"`
}
type CoinutCancelOrdersResponse struct {
CoinutGenericResponse
// CancelOrdersResponse is response for a cancelled order
type CancelOrdersResponse struct {
GenericResponse
Results []struct {
OrderID int64 `json:"order_id"`
Status string `json:"status"`
@@ -132,17 +150,20 @@ type CoinutCancelOrdersResponse struct {
} `json:"results"`
}
type CoinutTradeHistory struct {
TotalNumber int64 `json:"total_number"`
Trades []CoinutOrderFilledResponse `json:"trades"`
// TradeHistory holds trade history information
type TradeHistory struct {
TotalNumber int64 `json:"total_number"`
Trades []OrderFilledResponse `json:"trades"`
}
type CoinutIndexTicker struct {
// IndexTicker holds indexed ticker inforamtion
type IndexTicker struct {
Asset string `json:"asset"`
Price float64 `json:"price,string"`
}
type CoinutOption struct {
// Option holds options information
type Option struct {
HighestBuy float64 `json:"highest_buy,string"`
InstrumentID int `json:"inst_id"`
Last float64 `json:"last,string"`
@@ -150,40 +171,43 @@ type CoinutOption struct {
OpenInterest float64 `json:"open_interest,string"`
}
type CoinutOptionChainResponse struct {
// OptionChainResponse is the response type for options
type OptionChainResponse 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"`
Call Option `json:"call"`
Put Option `json:"put"`
Strike float64 `json:"strike,string"`
}
}
type CoinutOptionChainUpdate struct {
CoinutOption
CoinutGenericResponse
// OptionChainUpdate contains information on the chain update options
type OptionChainUpdate struct {
Option
GenericResponse
Asset string `json:"asset"`
ExpiryTime int64 `json:"expiry_time"`
SecurityType string `json:"sec_type"`
Volume float64 `json:"volume,string"`
}
type CoinutPositionHistory struct {
// PositionHistory holds the complete position history
type PositionHistory 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"`
Commission Commission `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"`
Commission Commission `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"`
@@ -202,12 +226,13 @@ type CoinutPositionHistory struct {
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"`
// OpenPosition holds information on an open position
type OpenPosition struct {
PositionID int `json:"position_id"`
Commission Commission `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"`
}

View File

@@ -8,8 +8,9 @@ import (
"github.com/thrasher-/gocryptotrader/common"
)
const COINUT_WEBSOCKET_URL = "wss://wsapi.coinut.com"
const coinutWebsocketURL = "wss://wsapi.coinut.com"
// WebsocketClient initiates a websocket client
func (c *COINUT) WebsocketClient() {
for c.Enabled && c.Websocket {
var Dialer websocket.Dialer

View File

@@ -1,6 +1,7 @@
package coinut
import (
"errors"
"log"
"github.com/thrasher-/gocryptotrader/common"
@@ -18,7 +19,7 @@ func (c *COINUT) Start() {
// Run implements the COINUT wrapper
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 Websocket: %s. (url: %s).\n", c.GetName(), common.IsEnabled(c.Websocket), coinutWebsocketURL)
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)
}
@@ -123,3 +124,10 @@ func (c *COINUT) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderbo
orderbook.ProcessOrderbook(c.GetName(), p, orderBook, assetType)
return orderbook.GetOrderbook(c.Name, p, assetType)
}
// GetExchangeHistory returns historic trade data since exchange opening.
func (c *COINUT) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
var resp []exchange.TradeHistory
return resp, errors.New("trade history not yet implemented")
}

View File

@@ -35,6 +35,16 @@ type AccountCurrencyInfo struct {
Hold float64
}
// TradeHistory holds exchange history data
type TradeHistory struct {
Timestamp int64
TID int64
Price float64
Amount float64
Exchange string
Type string
}
// Base stores the individual exchange information
type Base struct {
Name string
@@ -74,6 +84,7 @@ type IBotExchange interface {
GetExchangeAccountInfo() (AccountInfo, error)
GetAuthenticatedAPISupport() bool
SetCurrencies(pairs []pair.CurrencyPair, enabledPairs bool) error
GetExchangeHistory(pair.CurrencyPair, string) ([]TradeHistory, error)
}
// SetAssetTypes checks the exchange asset types (whether it supports SPOT,

View File

@@ -1,6 +1,7 @@
package exmo
import (
"errors"
"log"
"strconv"
@@ -154,3 +155,10 @@ func (e *EXMO) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
}
return response, nil
}
// GetExchangeHistory returns historic trade data since exchange opening.
func (e *EXMO) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
var resp []exchange.TradeHistory
return resp, errors.New("trade history not yet implemented")
}

View File

@@ -31,7 +31,6 @@ func TestSetup(t *testing.T) {
}
func TestGetFee(t *testing.T) {
t.Parallel()
if g.GetFee(false) == 0 {
t.Error("Test failed - GetFee() error")
}
@@ -41,7 +40,6 @@ func TestGetFee(t *testing.T) {
}
func TestGetProducts(t *testing.T) {
t.Parallel()
_, err := g.GetProducts()
if err != nil {
t.Error("Test failed - GetProducts() error")
@@ -49,7 +47,6 @@ func TestGetProducts(t *testing.T) {
}
func TestGetTicker(t *testing.T) {
t.Parallel()
_, err := g.GetTicker("BTC-USD")
if err != nil {
t.Error("Test failed - GetTicker() error", err)
@@ -57,7 +54,6 @@ func TestGetTicker(t *testing.T) {
}
func TestGetTrades(t *testing.T) {
t.Parallel()
_, err := g.GetTrades("BTC-USD")
if err != nil {
t.Error("Test failed - GetTrades() error", err)
@@ -65,7 +61,6 @@ func TestGetTrades(t *testing.T) {
}
func TestGetHistoricRates(t *testing.T) {
t.Parallel()
_, err := g.GetHistoricRates("BTC-USD", 0, 0, 0)
if err != nil {
t.Error("Test failed - GetHistoricRates() error", err)
@@ -73,7 +68,6 @@ func TestGetHistoricRates(t *testing.T) {
}
func TestGetStats(t *testing.T) {
t.Parallel()
_, err := g.GetStats("BTC-USD")
if err != nil {
t.Error("Test failed - GetStats() error", err)
@@ -81,7 +75,6 @@ func TestGetStats(t *testing.T) {
}
func TestGetCurrencies(t *testing.T) {
t.Parallel()
_, err := g.GetCurrencies()
if err != nil {
t.Error("Test failed - GetCurrencies() error", err)
@@ -89,212 +82,143 @@ func TestGetCurrencies(t *testing.T) {
}
func TestGetServerTime(t *testing.T) {
t.Parallel()
_, err := g.GetServerTime()
if err != nil {
t.Error("Test failed - GetServerTime() error", err)
}
}
func TestGetAccounts(t *testing.T) {
t.Parallel()
_, err := g.GetAccounts()
if err == nil {
t.Error("Test failed - GetAccounts() error", err)
}
}
func TestGetAccount(t *testing.T) {
t.Parallel()
_, err := g.GetAccount("234cb213-ac6f-4ed8-b7b6-e62512930945")
if err == nil {
t.Error("Test failed - GetAccount() error", err)
}
}
func TestGetAccountHistory(t *testing.T) {
t.Parallel()
_, err := g.GetAccountHistory("234cb213-ac6f-4ed8-b7b6-e62512930945")
if err == nil {
t.Error("Test failed - GetAccountHistory() error", err)
}
}
func TestGetHolds(t *testing.T) {
t.Parallel()
_, err := g.GetHolds("234cb213-ac6f-4ed8-b7b6-e62512930945")
if err == nil {
t.Error("Test failed - GetHolds() error", err)
}
}
func TestPlaceLimitOrder(t *testing.T) {
t.Parallel()
_, err := g.PlaceLimitOrder("", 0, 0, "buy", "", "", "BTC-USD", "", false)
if err == nil {
t.Error("Test failed - PlaceLimitOrder() error", err)
}
}
func TestPlaceMarketOrder(t *testing.T) {
t.Parallel()
_, err := g.PlaceMarketOrder("", 1, 0, "buy", "BTC-USD", "")
if err == nil {
t.Error("Test failed - PlaceMarketOrder() error", err)
}
}
func TestCancelOrder(t *testing.T) {
t.Parallel()
err := g.CancelOrder("1337")
if err == nil {
t.Error("Test failed - CancelOrder() error", err)
}
}
func TestCancelAllOrders(t *testing.T) {
t.Parallel()
_, err := g.CancelAllOrders("BTC-USD")
if err == nil {
t.Error("Test failed - CancelAllOrders() error", err)
}
}
func TestGetOrders(t *testing.T) {
t.Parallel()
_, err := g.GetOrders([]string{"open", "done"}, "BTC-USD")
if err == nil {
t.Error("Test failed - GetOrders() error", err)
}
}
func TestGetOrder(t *testing.T) {
t.Parallel()
_, err := g.GetOrder("1337")
if err == nil {
t.Error("Test failed - GetOrders() error", err)
}
}
func TestGetFills(t *testing.T) {
t.Parallel()
_, err := g.GetFills("1337", "BTC-USD")
if err == nil {
t.Error("Test failed - GetFills() error", err)
}
_, err = g.GetFills("", "")
if err == nil {
t.Error("Test failed - GetFills() error", err)
}
}
func TestGetFundingRecords(t *testing.T) {
t.Parallel()
_, err := g.GetFundingRecords("rejected")
if err == nil {
t.Error("Test failed - GetFundingRecords() error", err)
}
}
// func TestRepayFunding(t *testing.T) {
// g.Verbose = true
// _, err := g.RepayFunding("1", "BTC")
// if err != nil {
// t.Error("Test failed - RepayFunding() error", err)
// }
// }
func TestMarginTransfer(t *testing.T) { //invalid sig issue
t.Parallel()
_, err := g.MarginTransfer(1, "withdraw", "45fa9e3b-00ba-4631-b907-8a98cbdf21be", "BTC")
if err == nil {
t.Error("Test failed - MarginTransfer() error", err)
}
}
func TestGetPosition(t *testing.T) {
t.Parallel()
_, err := g.GetPosition()
if err == nil {
t.Error("Test failed - GetPosition() error", err)
}
}
func TestClosePosition(t *testing.T) {
t.Parallel()
_, err := g.ClosePosition(false)
if err == nil {
t.Error("Test failed - ClosePosition() error", err)
}
}
func TestGetPayMethods(t *testing.T) {
t.Parallel()
_, err := g.GetPayMethods()
if err == nil {
t.Error("Test failed - GetPayMethods() error", err)
}
}
func TestDepositViaPaymentMethod(t *testing.T) {
t.Parallel()
_, err := g.DepositViaPaymentMethod(1, "BTC", "1337")
if err == nil {
t.Error("Test failed - DepositViaPaymentMethod() error", err)
}
}
func TestDepositViaCoinbase(t *testing.T) {
t.Parallel()
_, err := g.DepositViaCoinbase(1, "BTC", "1337")
if err == nil {
t.Error("Test failed - DepositViaCoinbase() error", err)
}
}
func TestWithdrawViaPaymentMethod(t *testing.T) {
t.Parallel()
_, err := g.WithdrawViaPaymentMethod(1, "BTC", "1337")
if err == nil {
t.Error("Test failed - WithdrawViaPaymentMethod() error", err)
}
}
// func TestWithdrawViaCoinbase(t *testing.T) { // No Route found error
// _, err := g.WithdrawViaCoinbase(1, "BTC", "c13cd0fc-72ca-55e9-843b-b84ef628c198")
// if err != nil {
// t.Error("Test failed - WithdrawViaCoinbase() error", err)
// }
// }
func TestWithdrawCrypto(t *testing.T) {
t.Parallel()
_, err := g.WithdrawCrypto(1, "BTC", "1337")
if err == nil {
t.Error("Test failed - WithdrawViaCoinbase() error", err)
}
}
func TestGetCoinbaseAccounts(t *testing.T) {
t.Parallel()
_, err := g.GetCoinbaseAccounts()
if err == nil {
t.Error("Test failed - GetCoinbaseAccounts() error", err)
}
}
func TestGetReportStatus(t *testing.T) {
t.Parallel()
_, err := g.GetReportStatus("1337")
if err == nil {
t.Error("Test failed - GetReportStatus() error", err)
}
}
func TestGetTrailingVolume(t *testing.T) {
t.Parallel()
_, err := g.GetTrailingVolume()
if err == nil {
t.Error("Test failed - GetTrailingVolume() error", err)
func TestAuthRequests(t *testing.T) {
if g.APIKey != "" && g.APISecret != "" && g.ClientID != "" {
_, err := g.GetAccounts()
if err == nil {
t.Error("Test failed - GetAccounts() error", err)
}
_, err = g.GetAccount("234cb213-ac6f-4ed8-b7b6-e62512930945")
if err == nil {
t.Error("Test failed - GetAccount() error", err)
}
_, err = g.GetAccountHistory("234cb213-ac6f-4ed8-b7b6-e62512930945")
if err == nil {
t.Error("Test failed - GetAccountHistory() error", err)
}
_, err = g.GetHolds("234cb213-ac6f-4ed8-b7b6-e62512930945")
if err == nil {
t.Error("Test failed - GetHolds() error", err)
}
_, err = g.PlaceLimitOrder("", 0, 0, "buy", "", "", "BTC-USD", "", false)
if err == nil {
t.Error("Test failed - PlaceLimitOrder() error", err)
}
_, err = g.PlaceMarketOrder("", 1, 0, "buy", "BTC-USD", "")
if err == nil {
t.Error("Test failed - PlaceMarketOrder() error", err)
}
err = g.CancelOrder("1337")
if err == nil {
t.Error("Test failed - CancelOrder() error", err)
}
_, err = g.CancelAllOrders("BTC-USD")
if err == nil {
t.Error("Test failed - CancelAllOrders() error", err)
}
_, err = g.GetOrders([]string{"open", "done"}, "BTC-USD")
if err == nil {
t.Error("Test failed - GetOrders() error", err)
}
_, err = g.GetOrder("1337")
if err == nil {
t.Error("Test failed - GetOrders() error", err)
}
_, err = g.GetFills("1337", "BTC-USD")
if err == nil {
t.Error("Test failed - GetFills() error", err)
}
_, err = g.GetFills("", "")
if err == nil {
t.Error("Test failed - GetFills() error", err)
}
_, err = g.GetFundingRecords("rejected")
if err == nil {
t.Error("Test failed - GetFundingRecords() error", err)
}
// _, err := g.RepayFunding("1", "BTC")
// if err != nil {
// t.Error("Test failed - RepayFunding() error", err)
// }
_, err = g.MarginTransfer(1, "withdraw", "45fa9e3b-00ba-4631-b907-8a98cbdf21be", "BTC")
if err == nil {
t.Error("Test failed - MarginTransfer() error", err)
}
_, err = g.GetPosition()
if err == nil {
t.Error("Test failed - GetPosition() error", err)
}
_, err = g.ClosePosition(false)
if err == nil {
t.Error("Test failed - ClosePosition() error", err)
}
_, err = g.GetPayMethods()
if err == nil {
t.Error("Test failed - GetPayMethods() error", err)
}
_, err = g.DepositViaPaymentMethod(1, "BTC", "1337")
if err == nil {
t.Error("Test failed - DepositViaPaymentMethod() error", err)
}
_, err = g.DepositViaCoinbase(1, "BTC", "1337")
if err == nil {
t.Error("Test failed - DepositViaCoinbase() error", err)
}
_, err = g.WithdrawViaPaymentMethod(1, "BTC", "1337")
if err == nil {
t.Error("Test failed - WithdrawViaPaymentMethod() error", err)
}
// _, err := g.WithdrawViaCoinbase(1, "BTC", "c13cd0fc-72ca-55e9-843b-b84ef628c198")
// if err != nil {
// t.Error("Test failed - WithdrawViaCoinbase() error", err)
// }
_, err = g.WithdrawCrypto(1, "BTC", "1337")
if err == nil {
t.Error("Test failed - WithdrawViaCoinbase() error", err)
}
_, err = g.GetCoinbaseAccounts()
if err == nil {
t.Error("Test failed - GetCoinbaseAccounts() error", err)
}
_, err = g.GetReportStatus("1337")
if err == nil {
t.Error("Test failed - GetReportStatus() error", err)
}
_, err = g.GetTrailingVolume()
if err == nil {
t.Error("Test failed - GetTrailingVolume() error", err)
}
}
}

View File

@@ -9,9 +9,10 @@ import (
)
const (
GDAX_WEBSOCKET_URL = "wss://ws-feed.gdax.com"
gdaxWebsocketURL = "wss://ws-feed.gdax.com"
)
// WebsocketSubscribe subscribes to a websocket connection
func (g *GDAX) WebsocketSubscribe(product string, conn *websocket.Conn) error {
subscribe := WebsocketSubscribe{"subscribe", product}
json, err := common.JSONEncode(subscribe)
@@ -27,10 +28,11 @@ func (g *GDAX) WebsocketSubscribe(product string, conn *websocket.Conn) error {
return nil
}
// WebsocketClient initiates a websocket client
func (g *GDAX) WebsocketClient() {
for g.Enabled && g.Websocket {
var Dialer websocket.Dialer
conn, _, err := Dialer.Dial(GDAX_WEBSOCKET_URL, http.Header{})
conn, _, err := Dialer.Dial(gdaxWebsocketURL, http.Header{})
if err != nil {
log.Printf("%s Unable to connect to Websocket. Error: %s\n", g.GetName(), err)

View File

@@ -1,6 +1,7 @@
package gdax
import (
"errors"
"log"
"github.com/thrasher-/gocryptotrader/common"
@@ -18,7 +19,7 @@ func (g *GDAX) Start() {
// Run implements the GDAX wrapper
func (g *GDAX) Run() {
if g.Verbose {
log.Printf("%s Websocket: %s. (url: %s).\n", g.GetName(), common.IsEnabled(g.Websocket), GDAX_WEBSOCKET_URL)
log.Printf("%s Websocket: %s. (url: %s).\n", g.GetName(), common.IsEnabled(g.Websocket), gdaxWebsocketURL)
log.Printf("%s polling delay: %ds.\n", g.GetName(), g.RESTPollingDelay)
log.Printf("%s %d currencies enabled: %s.\n", g.GetName(), len(g.EnabledPairs), g.EnabledPairs)
}
@@ -126,3 +127,10 @@ func (g *GDAX) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderbook
orderbook.ProcessOrderbook(g.GetName(), p, orderBook, assetType)
return orderbook.GetOrderbook(g.Name, p, assetType)
}
// GetExchangeHistory returns historic trade data since exchange opening.
func (g *GDAX) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
var resp []exchange.TradeHistory
return resp, errors.New("trade history not yet implemented")
}

View File

@@ -1,6 +1,7 @@
package gemini
import (
"errors"
"log"
"net/url"
@@ -105,3 +106,10 @@ func (g *Gemini) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderbo
orderbook.ProcessOrderbook(g.GetName(), p, orderBook, assetType)
return orderbook.GetOrderbook(g.Name, p, assetType)
}
// GetExchangeHistory returns historic trade data since exchange opening.
func (g *Gemini) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
var resp []exchange.TradeHistory
return resp, errors.New("trade history not yet implemented")
}

View File

@@ -16,29 +16,29 @@ import (
const (
// API
APIURL = "https://api.hitbtc.com"
apiURL = "https://api.hitbtc.com"
// Public
APIv2Trades = "api/2/public/trades"
APIv2Currency = "api/2/public/currency"
APIv2Symbol = "api/2/public/symbol"
APIv2Ticker = "api/2/public/ticker"
APIv2OrderBook = "api/2/public/orderbook"
APIv2Candles = "api/2/public/candles"
apiV2Trades = "api/2/public/trades"
apiV2Currency = "api/2/public/currency"
apiV2Symbol = "api/2/public/symbol"
apiV2Ticker = "api/2/public/ticker"
apiV2Orderbook = "api/2/public/orderbook"
apiV2Candles = "api/2/public/candles"
// Authenticated
APIv2Balance = "api/2/trading/balance"
APIv2CryptoAddress = "api/2/account/crypto/address"
APIv2CryptoWithdraw = "api/2/account/crypto/withdraw"
APIv2TradeHistory = "api/2/history/trades"
APIv2FeeInfo = "api/2/trading/fee"
Orders = "order"
OrderBuy = "buy"
OrderSell = "sell"
OrderCancel = "cancelOrder"
OrderMove = "moveOrder"
TradableBalances = "returnTradableBalances"
TransferBalance = "transferBalance"
apiV2Balance = "api/2/trading/balance"
apiV2CryptoAddress = "api/2/account/crypto/address"
apiV2CryptoWithdraw = "api/2/account/crypto/withdraw"
apiV2TradeHistory = "api/2/history/trades"
apiV2FeeInfo = "api/2/trading/fee"
orders = "order"
orderBuy = "buy"
orderSell = "sell"
orderCancel = "cancelOrder"
orderMove = "moveOrder"
tradableBalances = "returnTradableBalances"
transferBalance = "transferBalance"
)
// HitBTC is the overarching type across the hitbtc package
@@ -94,36 +94,35 @@ func (p *HitBTC) GetFee() float64 {
// Public Market Data
// https://api.hitbtc.com/?python#market-data
// GetCurrencies
// Return the actual list of available currencies, tokens, ICO etc.
// GetCurrencies returns the actual list of available currencies, tokens, ICO
// etc.
func (p *HitBTC) GetCurrencies(currency string) (map[string]Currencies, error) {
type Response struct {
Data []Currencies
}
resp := Response{}
path := fmt.Sprintf("%s/%s/%s", APIURL, APIv2Currency, currency)
path := fmt.Sprintf("%s/%s/%s", apiURL, apiV2Currency, currency)
err := common.SendHTTPGetRequest(path, true, p.Verbose, &resp.Data)
ret := make(map[string]Currencies)
for _, id := range resp.Data {
ret[id.Id] = id
ret[id.ID] = id
}
return ret, err
}
// GetSymbols
// Return the actual list of currency symbols (currency pairs) traded on HitBTC exchange.
// The first listed currency of a symbol is called the base currency, and the second currency
// is called the quote currency. The currency pair indicates how much of the quote currency
// is needed to purchase one unit of the base currency.
// GetSymbols Return the actual list of currency symbols (currency pairs) traded
// on HitBTC exchange. The first listed currency of a symbol is called the base
// currency, and the second currency is called the quote currency. The currency
// pair indicates how much of the quote currency is needed to purchase one unit
// of the base currency.
func (p *HitBTC) GetSymbols(symbol string) ([]string, error) {
resp := []Symbol{}
path := fmt.Sprintf("%s/%s/%s", APIURL, APIv2Symbol, symbol)
path := fmt.Sprintf("%s/%s/%s", apiURL, apiV2Symbol, symbol)
err := common.SendHTTPGetRequest(path, true, p.Verbose, &resp)
ret := make([]string, 0, len(resp))
for _, x := range resp {
ret = append(ret, x.Id)
ret = append(ret, x.ID)
}
return ret, err
@@ -133,19 +132,17 @@ func (p *HitBTC) GetSymbols(symbol string) ([]string, error) {
// all ther details.
func (p *HitBTC) GetSymbolsDetailed() ([]Symbol, error) {
resp := []Symbol{}
path := fmt.Sprintf("%s/%s", APIURL, APIv2Symbol)
path := fmt.Sprintf("%s/%s", apiURL, apiV2Symbol)
return resp, common.SendHTTPGetRequest(path, true, p.Verbose, &resp)
}
// GetTicker
// Return ticker information
// GetTicker returns ticker information
func (p *HitBTC) GetTicker(symbol string) (map[string]Ticker, error) {
resp1 := []TickerResponse{}
resp2 := TickerResponse{}
ret := make(map[string]TickerResponse)
result := make(map[string]Ticker)
path := fmt.Sprintf("%s/%s/%s", APIURL, APIv2Ticker, symbol)
path := fmt.Sprintf("%s/%s/%s", apiURL, apiV2Ticker, symbol)
var err error
if symbol == "" {
@@ -236,14 +233,13 @@ func (p *HitBTC) GetTrades(currencyPair, from, till, limit, offset, by, sort str
}
resp := []TradeHistory{}
path := fmt.Sprintf("%s/%s/%s?%s", APIURL, APIv2Trades, currencyPair, vals.Encode())
path := fmt.Sprintf("%s/%s/%s?%s", apiURL, apiV2Trades, currencyPair, vals.Encode())
return resp, common.SendHTTPGetRequest(path, true, p.Verbose, &resp)
}
// GetOrderbook
// An order book is an electronic list of buy and sell orders for a specific
// symbol, organized by price level.
// GetOrderbook an order book is an electronic list of buy and sell orders for a
// specific symbol, organized by price level.
func (p *HitBTC) GetOrderbook(currencyPair string, limit int) (Orderbook, error) {
// limit Limit of orderbook levels, default 100. Set 0 to view full orderbook levels
vals := url.Values{}
@@ -253,7 +249,7 @@ func (p *HitBTC) GetOrderbook(currencyPair string, limit int) (Orderbook, error)
}
resp := OrderbookResponse{}
path := fmt.Sprintf("%s/%s/%s?%s", APIURL, APIv2OrderBook, currencyPair, vals.Encode())
path := fmt.Sprintf("%s/%s/%s?%s", apiURL, apiV2Orderbook, currencyPair, vals.Encode())
err := common.SendHTTPGetRequest(path, true, p.Verbose, &resp)
if err != nil {
@@ -271,8 +267,7 @@ func (p *HitBTC) GetOrderbook(currencyPair string, limit int) (Orderbook, error)
return ob, nil
}
// GetCandles
// A candles used for OHLC a specific symbol.
// GetCandles returns candles which is used for OHLC a specific symbol.
// Note: Result contain candles only with non zero volume.
func (p *HitBTC) GetCandles(currencyPair, limit, period string) ([]ChartData, error) {
// limit Limit of candles, default 100.
@@ -288,24 +283,18 @@ func (p *HitBTC) GetCandles(currencyPair, limit, period string) ([]ChartData, er
}
resp := []ChartData{}
path := fmt.Sprintf("%s/%s/%s?%s", APIURL, APIv2Candles, currencyPair, vals.Encode())
path := fmt.Sprintf("%s/%s/%s?%s", apiURL, apiV2Candles, currencyPair, vals.Encode())
err := common.SendHTTPGetRequest(path, true, p.Verbose, &resp)
if err != nil {
return nil, err
}
return resp, nil
return resp, common.SendHTTPGetRequest(path, true, p.Verbose, &resp)
}
// Authenticated Market Data
// https://api.hitbtc.com/?python#market-data
// GetBalances
// GetBalances returns full balance for your account
func (p *HitBTC) GetBalances() (map[string]Balance, error) {
result := []Balance{}
err := p.SendAuthenticatedHTTPRequest("GET", APIv2Balance, url.Values{}, &result)
err := p.SendAuthenticatedHTTPRequest("GET", apiV2Balance, url.Values{}, &result)
ret := make(map[string]Balance)
if err != nil {
@@ -319,30 +308,31 @@ func (p *HitBTC) GetBalances() (map[string]Balance, error) {
return ret, nil
}
// GetDepositAddresses returns a deposit address for a specific currency
func (p *HitBTC) GetDepositAddresses(currency string) (DepositCryptoAddresses, error) {
resp := DepositCryptoAddresses{}
err := p.SendAuthenticatedHTTPRequest("GET", APIv2CryptoAddress+"/"+currency, url.Values{}, &resp)
err := p.SendAuthenticatedHTTPRequest("GET", apiV2CryptoAddress+"/"+currency, url.Values{}, &resp)
return resp, err
}
// GenerateNewAddress generates a new deposit address for a currency
func (p *HitBTC) GenerateNewAddress(currency string) (DepositCryptoAddresses, error) {
resp := DepositCryptoAddresses{}
err := p.SendAuthenticatedHTTPRequest("POST", APIv2CryptoAddress+"/"+currency, url.Values{}, &resp)
err := p.SendAuthenticatedHTTPRequest("POST", apiV2CryptoAddress+"/"+currency, url.Values{}, &resp)
return resp, err
}
// Get Active orders
func (p *HitBTC) GetActiveOrders(currency string) ([]Order, error) {
// GetActiveorders returns all your active orders
func (p *HitBTC) GetActiveorders(currency string) ([]Order, error) {
resp := []Order{}
err := p.SendAuthenticatedHTTPRequest("GET", Orders+"?symbol="+currency, url.Values{}, &resp)
err := p.SendAuthenticatedHTTPRequest("GET", orders+"?symbol="+currency, url.Values{}, &resp)
return resp, err
}
// GetAuthenticatedTradeHistory returns your trade history
func (p *HitBTC) GetAuthenticatedTradeHistory(currency, start, end string) (interface{}, error) {
values := url.Values{}
@@ -357,35 +347,26 @@ func (p *HitBTC) GetAuthenticatedTradeHistory(currency, start, end string) (inte
if currency != "" && currency != "all" {
values.Set("currencyPair", currency)
result := AuthenticatedTradeHistoryResponse{}
err := p.SendAuthenticatedHTTPRequest("POST", APIv2TradeHistory, values, &result.Data)
if err != nil {
return result, err
}
return result, nil
} else {
values.Set("currencyPair", "all")
result := AuthenticatedTradeHistoryAll{}
err := p.SendAuthenticatedHTTPRequest("POST", APIv2TradeHistory, values, &result.Data)
if err != nil {
return result, err
}
return result, nil
return result, p.SendAuthenticatedHTTPRequest("POST", apiV2TradeHistory, values, &result.Data)
}
values.Set("currencyPair", "all")
result := AuthenticatedTradeHistoryAll{}
return result, p.SendAuthenticatedHTTPRequest("POST", apiV2TradeHistory, values, &result.Data)
}
// PlaceOrder places an order on the exchange
func (p *HitBTC) PlaceOrder(currency string, rate, amount float64, immediate, fillOrKill, buy bool) (OrderResponse, error) {
result := OrderResponse{}
values := url.Values{}
var orderType string
if buy {
orderType = OrderBuy
orderType = orderBuy
} else {
orderType = OrderSell
orderType = orderSell
}
values.Set("currencyPair", currency)
@@ -409,12 +390,13 @@ func (p *HitBTC) PlaceOrder(currency string, rate, amount float64, immediate, fi
return result, nil
}
// CancelOrder cancels a specific order by OrderID
func (p *HitBTC) CancelOrder(orderID int64) (bool, error) {
result := GenericResponse{}
values := url.Values{}
values.Set("orderNumber", strconv.FormatInt(orderID, 10))
err := p.SendAuthenticatedHTTPRequest("POST", OrderCancel, values, &result)
err := p.SendAuthenticatedHTTPRequest("POST", orderCancel, values, &result)
if err != nil {
return false, err
@@ -427,6 +409,7 @@ func (p *HitBTC) CancelOrder(orderID int64) (bool, error) {
return true, nil
}
// MoveOrder generates a new move order
func (p *HitBTC) MoveOrder(orderID int64, rate, amount float64) (MoveOrderResponse, error) {
result := MoveOrderResponse{}
values := url.Values{}
@@ -437,7 +420,7 @@ func (p *HitBTC) MoveOrder(orderID int64, rate, amount float64) (MoveOrderRespon
values.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64))
}
err := p.SendAuthenticatedHTTPRequest("POST", OrderMove, values, &result)
err := p.SendAuthenticatedHTTPRequest("POST", orderMove, values, &result)
if err != nil {
return result, err
@@ -450,6 +433,7 @@ func (p *HitBTC) MoveOrder(orderID int64, rate, amount float64) (MoveOrderRespon
return result, nil
}
// Withdraw allows for the withdrawal to a specific address
func (p *HitBTC) Withdraw(currency, address string, amount float64) (bool, error) {
result := Withdraw{}
values := url.Values{}
@@ -458,7 +442,7 @@ func (p *HitBTC) Withdraw(currency, address string, amount float64) (bool, error
values.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64))
values.Set("address", address)
err := p.SendAuthenticatedHTTPRequest("POST", APIv2CryptoWithdraw, values, &result)
err := p.SendAuthenticatedHTTPRequest("POST", apiV2CryptoWithdraw, values, &result)
if err != nil {
return false, err
@@ -471,20 +455,22 @@ func (p *HitBTC) Withdraw(currency, address string, amount float64) (bool, error
return true, nil
}
// GetFeeInfo returns current fee information
func (p *HitBTC) GetFeeInfo(currencyPair string) (Fee, error) {
result := Fee{}
err := p.SendAuthenticatedHTTPRequest("GET", APIv2FeeInfo+"/"+currencyPair, url.Values{}, &result)
err := p.SendAuthenticatedHTTPRequest("GET", apiV2FeeInfo+"/"+currencyPair, url.Values{}, &result)
return result, err
}
// GetTradableBalances returns current tradable balances
func (p *HitBTC) GetTradableBalances() (map[string]map[string]float64, error) {
type Response struct {
Data map[string]map[string]interface{}
}
result := Response{}
err := p.SendAuthenticatedHTTPRequest("POST", TradableBalances, url.Values{}, &result.Data)
err := p.SendAuthenticatedHTTPRequest("POST", tradableBalances, url.Values{}, &result.Data)
if err != nil {
return nil, err
@@ -502,6 +488,7 @@ func (p *HitBTC) GetTradableBalances() (map[string]map[string]float64, error) {
return balances, nil
}
// TransferBalance transfers a balance
func (p *HitBTC) TransferBalance(currency, from, to string, amount float64) (bool, error) {
values := url.Values{}
result := GenericResponse{}
@@ -511,7 +498,7 @@ func (p *HitBTC) TransferBalance(currency, from, to string, amount float64) (boo
values.Set("fromAccount", from)
values.Set("toAccount", to)
err := p.SendAuthenticatedHTTPRequest("POST", TransferBalance, values, &result)
err := p.SendAuthenticatedHTTPRequest("POST", transferBalance, values, &result)
if err != nil {
return false, err
@@ -524,6 +511,7 @@ func (p *HitBTC) TransferBalance(currency, from, to string, amount float64) (boo
return true, nil
}
// SendAuthenticatedHTTPRequest sends an authenticated http request
func (p *HitBTC) SendAuthenticatedHTTPRequest(method, endpoint string, values url.Values, result interface{}) error {
if !p.AuthenticatedAPISupport {
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, p.Name)
@@ -531,17 +519,17 @@ func (p *HitBTC) SendAuthenticatedHTTPRequest(method, endpoint string, values ur
headers := make(map[string]string)
headers["Authorization"] = "Basic " + common.Base64Encode([]byte(p.APIKey+":"+p.APISecret))
path := fmt.Sprintf("%s/%s", APIURL, endpoint)
resp, err := common.SendHTTPRequest(method, path, headers, bytes.NewBufferString(values.Encode()))
path := fmt.Sprintf("%s/%s", apiURL, endpoint)
resp, err := common.SendHTTPRequest(method, path, headers, bytes.NewBufferString(values.Encode()))
if err != nil {
return err
}
err = common.JSONDecode([]byte(resp), &result)
if err != nil {
return errors.New("Unable to JSON Unmarshal response.")
return err
}
return nil
}

View File

@@ -2,6 +2,7 @@ package hitbtc
import "time"
// Ticker holds ticker information
type Ticker struct {
Last float64
Ask float64
@@ -15,6 +16,7 @@ type Ticker struct {
Open float64
}
// TickerResponse is the response type
type TickerResponse struct {
Last string `json:"last"` // Last trade price
Ask string `json:"ask"` // Best ask price
@@ -28,8 +30,9 @@ type TickerResponse struct {
Open string `json:"open"` // Last trade price 24 hours ago
}
// Symbol holds symbol data
type Symbol struct {
Id string `json:"id"` // Symbol identifier. In the future, the description will simply use the symbol
ID string `json:"id"` // Symbol identifier. In the future, the description will simply use the symbol
BaseCurrency string `json:"baseCurrency"`
QuoteCurrency string `json:"quoteCurrency"`
QuantityIncrement float64 `json:"quantityIncrement,string"`
@@ -39,29 +42,34 @@ type Symbol struct {
FeeCurrency string `json:"feeCurrency"` // Default fee rate for market making trades
}
// OrderbookResponse is the full orderbook response
type OrderbookResponse struct {
Asks []OrderbookItem `json:"ask"` // Ask side array of levels
Bids []OrderbookItem `json:"bid"` // Bid side array of levels
}
// OrderbookItem is a sub type for orderbook response
type OrderbookItem struct {
Price float64 `json:"price,string"` // Price level
Amount float64 `json:"size,string"` // Total volume of orders with the specified price
}
// Orderbook contains orderbook data
type Orderbook struct {
Asks []OrderbookItem `json:"asks"`
Bids []OrderbookItem `json:"bids"`
}
// TradeHistory contains trade history data
type TradeHistory struct {
Id int64 `json:"id"` // Trade id
ID int64 `json:"id"` // Trade id
Timestamp string `json:"timestamp"` // Trade timestamp
Side string `json:"side"` // Trade side sell or buy
Price float64 `json:"price,string"` // Trade price
Quantity float64 `json:"quantity,string"` // Trade quantity
}
// ChartData contains chart data
type ChartData struct {
Timestamp time.Time `json:"timestamp,string"`
Max float64 `json:"max,string"` // Max price
@@ -72,18 +80,20 @@ type ChartData struct {
VolumeQuote float64 `json:"volumeQuote,string"` // Volume in quote currency
}
// Currencies hold the full range of data for a specified currency
type Currencies struct {
Id string `json:"id"` // Currency identifier.
ID string `json:"id"` // Currency identifier.
FullName string `json:"fullName"` // Currency full name
Crypto bool `json:"crypto,boolean"` // Is currency belongs to blockchain (false for ICO and fiat, like EUR)
PayinEnabled bool `json:"payinEnabled"` // Is allowed for deposit (false for ICO)
PayinPaymentId bool `json:"payinPaymentId"` // Is required to provide additional information other than the address for deposit
PayinPaymentID bool `json:"payinPaymentId"` // Is required to provide additional information other than the address for deposit
PayinConfirmations int64 `json:"payinConfirmations"` // Blocks confirmations count for deposit
PayoutEnabled bool `json:"payoutEnabled"` // Is allowed for withdraw (false for ICO)
PayoutIsPaymentId bool `json:"payoutIsPaymentId"` // Is allowed to provide additional information for withdraw
PayoutIsPaymentID bool `json:"payoutIsPaymentId"` // Is allowed to provide additional information for withdraw
TransferEnabled bool `json:"transferEnabled"` // Is allowed to transfer between trading and account (may be disabled on maintain)
}
// LoanOrder contains information about your loans
type LoanOrder struct {
Rate float64 `json:"rate,string"`
Amount float64 `json:"amount,string"`
@@ -91,11 +101,13 @@ type LoanOrder struct {
RangeMax int `json:"rangeMax"`
}
// LoanOrders holds information on the full range of loan orders
type LoanOrders struct {
Offers []LoanOrder `json:"offers"`
Demands []LoanOrder `json:"demands"`
}
// Balance is a simple balance type
type Balance struct {
Currency string `json:"currency"`
Available float64 `json:"available,string"` // Amount available for trading or transfer to main account
@@ -103,14 +115,16 @@ type Balance struct {
}
// DepositCryptoAddresses contains address information
type DepositCryptoAddresses struct {
Address string `json:"address"` // Address for deposit
PaymentId string `json:"paymentId"` // Optional additional parameter. Required for deposit if persist
PaymentID string `json:"paymentId"` // Optional additional parameter. Required for deposit if persist
}
// Order contains information about an order
type Order struct {
Id int64 `json:"id,string"` // Unique identifier for Order as assigned by exchange
ClientOrderId string `json:"clientOrderId"` // Unique identifier for Order as assigned by trader. Uniqueness must be
ID int64 `json:"id,string"` // Unique identifier for Order as assigned by exchange
ClientOrderID string `json:"clientOrderId"` // Unique identifier for Order as assigned by trader. Uniqueness must be
// guaranteed within a single trading day, including all active orders.
Symbol string `json:"symbol"` // Trading symbol
Side string `json:"side"` // sell buy
@@ -134,14 +148,17 @@ type Order struct {
ExpireTime time.Time `json:"expireTime,string"`
}
// OpenOrdersResponseAll holds the full open order response
type OpenOrdersResponseAll struct {
Data map[string][]Order
}
// OpenOrdersResponse contains open order information
type OpenOrdersResponse struct {
Data []Order
}
// AuthentictedTradeHistory contains trade history data
type AuthentictedTradeHistory struct {
GlobalTradeID int64 `json:"globalTradeID"`
TradeID int64 `json:"tradeID,string"`
@@ -155,14 +172,17 @@ type AuthentictedTradeHistory struct {
Category string `json:"category"`
}
// AuthenticatedTradeHistoryAll contains the full trade history
type AuthenticatedTradeHistoryAll struct {
Data map[string][]AuthentictedTradeHistory
}
// AuthenticatedTradeHistoryResponse is the resp type for trade history
type AuthenticatedTradeHistoryResponse struct {
Data []AuthentictedTradeHistory
}
// ResultingTrades holds resulting trade information
type ResultingTrades struct {
Amount float64 `json:"amount,string"`
Date string `json:"date"`
@@ -172,16 +192,19 @@ type ResultingTrades struct {
Type string `json:"type"`
}
// OrderResponse holds the order response information
type OrderResponse struct {
OrderNumber int64 `json:"orderNumber,string"`
Trades []ResultingTrades `json:"resultingTrades"`
}
// GenericResponse is the common response from HitBTC
type GenericResponse struct {
Success int `json:"success"`
Error string `json:"error"`
}
// MoveOrderResponse holds information about a move order
type MoveOrderResponse struct {
Success int `json:"success"`
Error string `json:"error"`
@@ -189,16 +212,19 @@ type MoveOrderResponse struct {
Trades map[string][]ResultingTrades `json:"resultingTrades"`
}
// Withdraw holds response for a withdrawel process
type Withdraw struct {
Response string `json:"response"`
Error string `json:"error"`
}
// Fee holds fee structure
type Fee struct {
TakeLiquidityRate float64 `json:"takeLiquidityRate,string"` // Taker
ProvideLiquidityRate float64 `json:"provideLiquidityRate,string"` // Maker
}
// Margin holds full margin information
type Margin struct {
TotalValue float64 `json:"totalValue,string"`
ProfitLoss float64 `json:"pl,string"`
@@ -208,6 +234,7 @@ type Margin struct {
CurrentMargin float64 `json:"currentMargin,string"`
}
// MarginPosition holds information about your current margin position
type MarginPosition struct {
Amount float64 `json:"amount,string"`
Total float64 `json:"total,string"`
@@ -218,6 +245,7 @@ type MarginPosition struct {
Type string `json:"type"`
}
// LoanOffer holds information about your loan offers
type LoanOffer struct {
ID int64 `json:"id"`
Rate float64 `json:"rate,string"`
@@ -227,11 +255,13 @@ type LoanOffer struct {
Date string `json:"date"`
}
// ActiveLoans holds information about your active loans
type ActiveLoans struct {
Provided []LoanOffer `json:"provided"`
Used []LoanOffer `json:"used"`
}
// LendingHistory contains lending history data
type LendingHistory struct {
ID int64 `json:"id"`
Currency string `json:"currency"`

View File

@@ -8,13 +8,14 @@ import (
)
const (
HITBTC_WEBSOCKET_ADDRESS = "wss://api.hitbtc.com"
HITBTC_WEBSOCKET_REALM = "realm1"
HITBTC_WEBSOCKET_TICKER = "ticker"
HITBTC_WEBSOCKET_TROLLBOX = "trollbox"
hitbtcWebsocketAddress = "wss://api.hitbtc.com"
hitbtcWebsocketRealm = "realm1"
hitbtcWebsocketTicker = "ticker"
hitbtcWebsocketTrollbox = "trollbox"
)
type HitBTCWebsocketTicker struct {
// WebsocketTicker holds ticker data
type WebsocketTicker struct {
CurrencyPair string
Last float64
LowestAsk float64
@@ -27,8 +28,9 @@ type HitBTCWebsocketTicker struct {
Low float64
}
func HitBTCOnTicker(args []interface{}, kwargs map[string]interface{}) {
ticker := HitBTCWebsocketTicker{}
// OnTicker converts ticker to websocket ticker
func OnTicker(args []interface{}, kwargs map[string]interface{}) {
ticker := WebsocketTicker{}
ticker.CurrencyPair = args[0].(string)
ticker.Last, _ = strconv.ParseFloat(args[1].(string), 64)
ticker.LowestAsk, _ = strconv.ParseFloat(args[2].(string), 64)
@@ -47,15 +49,17 @@ func HitBTCOnTicker(args []interface{}, kwargs map[string]interface{}) {
ticker.Low, _ = strconv.ParseFloat(args[9].(string), 64)
}
type HitBTCWebsocketTrollboxMessage struct {
// WebsocketTrollboxMessage contains trollbox message information
type WebsocketTrollboxMessage struct {
MessageNumber float64
Username string
Message string
Reputation float64
}
func HitBTCOnTrollbox(args []interface{}, kwargs map[string]interface{}) {
message := HitBTCWebsocketTrollboxMessage{}
// OnTrollbox converts trollbox messages
func OnTrollbox(args []interface{}, kwargs map[string]interface{}) {
message := WebsocketTrollboxMessage{}
message.MessageNumber, _ = args[1].(float64)
message.Username = args[2].(string)
message.Message = args[3].(string)
@@ -64,7 +68,8 @@ func HitBTCOnTrollbox(args []interface{}, kwargs map[string]interface{}) {
}
}
func HitBTCOnDepthOrTrade(args []interface{}, kwargs map[string]interface{}) {
// OnDepthOrTrade converts depth and trade data
func OnDepthOrTrade(args []interface{}, kwargs map[string]interface{}) {
for x := range args {
data := args[x].(map[string]interface{})
msgData := data["data"].(map[string]interface{})
@@ -133,9 +138,10 @@ func HitBTCOnDepthOrTrade(args []interface{}, kwargs map[string]interface{}) {
}
}
// WebsocketClient initiates a websocket client
func (p *HitBTC) WebsocketClient() {
for p.Enabled && p.Websocket {
c, err := turnpike.NewWebsocketClient(turnpike.JSON, HITBTC_WEBSOCKET_ADDRESS, nil)
c, err := turnpike.NewWebsocketClient(turnpike.JSON, hitbtcWebsocketAddress, nil)
if err != nil {
log.Printf("%s Unable to connect to Websocket. Error: %s\n", p.GetName(), err)
continue
@@ -145,7 +151,7 @@ func (p *HitBTC) WebsocketClient() {
log.Printf("%s Connected to Websocket.\n", p.GetName())
}
_, err = c.JoinRealm(HITBTC_WEBSOCKET_REALM, nil)
_, err = c.JoinRealm(hitbtcWebsocketRealm, nil)
if err != nil {
log.Printf("%s Unable to join realm. Error: %s\n", p.GetName(), err)
continue
@@ -157,17 +163,17 @@ func (p *HitBTC) WebsocketClient() {
c.ReceiveDone = make(chan bool)
if err := c.Subscribe(HITBTC_WEBSOCKET_TICKER, HitBTCOnTicker); err != nil {
if err := c.Subscribe(hitbtcWebsocketTicker, OnTicker); err != nil {
log.Printf("%s Error subscribing to ticker channel: %s\n", p.GetName(), err)
}
if err := c.Subscribe(HITBTC_WEBSOCKET_TROLLBOX, HitBTCOnTrollbox); err != nil {
if err := c.Subscribe(hitbtcWebsocketTrollbox, OnTrollbox); err != nil {
log.Printf("%s Error subscribing to trollbox channel: %s\n", p.GetName(), err)
}
for x := range p.EnabledPairs {
currency := p.EnabledPairs[x]
if err := c.Subscribe(currency, HitBTCOnDepthOrTrade); err != nil {
if err := c.Subscribe(currency, OnDepthOrTrade); err != nil {
log.Printf("%s Error subscribing to %s channel: %s\n", p.GetName(), currency, err)
}
}

View File

@@ -1,6 +1,7 @@
package hitbtc
import (
"errors"
"log"
"github.com/thrasher-/gocryptotrader/common"
@@ -11,28 +12,28 @@ import (
)
// Start starts the HitBTC go routine
func (p *HitBTC) Start() {
go p.Run()
func (h *HitBTC) Start() {
go h.Run()
}
// Run implements the HitBTC wrapper
func (p *HitBTC) Run() {
if p.Verbose {
log.Printf("%s Websocket: %s (url: %s).\n", p.GetName(), common.IsEnabled(p.Websocket), HITBTC_WEBSOCKET_ADDRESS)
log.Printf("%s polling delay: %ds.\n", p.GetName(), p.RESTPollingDelay)
log.Printf("%s %d currencies enabled: %s.\n", p.GetName(), len(p.EnabledPairs), p.EnabledPairs)
func (h *HitBTC) Run() {
if h.Verbose {
log.Printf("%s Websocket: %s (url: %s).\n", h.GetName(), common.IsEnabled(h.Websocket), hitbtcWebsocketAddress)
log.Printf("%s polling delay: %ds.\n", h.GetName(), h.RESTPollingDelay)
log.Printf("%s %d currencies enabled: %s.\n", h.GetName(), len(h.EnabledPairs), h.EnabledPairs)
}
if p.Websocket {
go p.WebsocketClient()
if h.Websocket {
go h.WebsocketClient()
}
exchangeProducts, err := p.GetSymbolsDetailed()
exchangeProducts, err := h.GetSymbolsDetailed()
if err != nil {
log.Printf("%s Failed to get available symbols.\n", p.GetName())
log.Printf("%s Failed to get available symbols.\n", h.GetName())
} else {
forceUpgrade := false
if !common.StringDataContains(p.EnabledPairs, "-") || !common.StringDataContains(p.AvailablePairs, "-") {
if !common.StringDataContains(h.EnabledPairs, "-") || !common.StringDataContains(h.AvailablePairs, "-") {
forceUpgrade = true
}
var currencies []string
@@ -44,28 +45,28 @@ func (p *HitBTC) Run() {
enabledPairs := []string{"BTC-USD"}
log.Println("WARNING: Available pairs for HitBTC reset due to config upgrade, please enable the ones you would like again.")
err = p.UpdateEnabledCurrencies(enabledPairs, true)
err = h.UpdateEnabledCurrencies(enabledPairs, true)
if err != nil {
log.Printf("%s Failed to update enabled currencies.\n", p.GetName())
log.Printf("%s Failed to update enabled currencies.\n", h.GetName())
}
}
err = p.UpdateAvailableCurrencies(currencies, forceUpgrade)
err = h.UpdateAvailableCurrencies(currencies, forceUpgrade)
if err != nil {
log.Printf("%s Failed to update available currencies.\n", p.GetName())
log.Printf("%s Failed to update available currencies.\n", h.GetName())
}
}
}
// UpdateTicker updates and returns the ticker for a currency pair
func (p *HitBTC) UpdateTicker(currencyPair pair.CurrencyPair, assetType string) (ticker.Price, error) {
tick, err := p.GetTicker("")
func (h *HitBTC) UpdateTicker(currencyPair pair.CurrencyPair, assetType string) (ticker.Price, error) {
tick, err := h.GetTicker("")
if err != nil {
return ticker.Price{}, err
}
for _, x := range p.GetEnabledCurrencies() {
for _, x := range h.GetEnabledCurrencies() {
var tp ticker.Price
curr := exchange.FormatExchangeCurrency(p.GetName(), x).String()
curr := exchange.FormatExchangeCurrency(h.GetName(), x).String()
tp.Pair = x
tp.Ask = tick[curr].Ask
tp.Bid = tick[curr].Bid
@@ -73,33 +74,33 @@ func (p *HitBTC) UpdateTicker(currencyPair pair.CurrencyPair, assetType string)
tp.Last = tick[curr].Last
tp.Low = tick[curr].Low
tp.Volume = tick[curr].Volume
ticker.ProcessTicker(p.GetName(), x, tp, assetType)
ticker.ProcessTicker(h.GetName(), x, tp, assetType)
}
return ticker.GetTicker(p.Name, currencyPair, assetType)
return ticker.GetTicker(h.Name, currencyPair, assetType)
}
// GetTickerPrice returns the ticker for a currency pair
func (p *HitBTC) GetTickerPrice(currencyPair pair.CurrencyPair, assetType string) (ticker.Price, error) {
tickerNew, err := ticker.GetTicker(p.GetName(), currencyPair, assetType)
func (h *HitBTC) GetTickerPrice(currencyPair pair.CurrencyPair, assetType string) (ticker.Price, error) {
tickerNew, err := ticker.GetTicker(h.GetName(), currencyPair, assetType)
if err != nil {
return p.UpdateTicker(currencyPair, assetType)
return h.UpdateTicker(currencyPair, assetType)
}
return tickerNew, nil
}
// GetOrderbookEx returns orderbook base on the currency pair
func (p *HitBTC) GetOrderbookEx(currencyPair pair.CurrencyPair, assetType string) (orderbook.Base, error) {
ob, err := orderbook.GetOrderbook(p.GetName(), currencyPair, assetType)
func (h *HitBTC) GetOrderbookEx(currencyPair pair.CurrencyPair, assetType string) (orderbook.Base, error) {
ob, err := orderbook.GetOrderbook(h.GetName(), currencyPair, assetType)
if err != nil {
return p.UpdateOrderbook(currencyPair, assetType)
return h.UpdateOrderbook(currencyPair, assetType)
}
return ob, nil
}
// UpdateOrderbook updates and returns the orderbook for a currency pair
func (p *HitBTC) UpdateOrderbook(currencyPair pair.CurrencyPair, assetType string) (orderbook.Base, error) {
func (h *HitBTC) UpdateOrderbook(currencyPair pair.CurrencyPair, assetType string) (orderbook.Base, error) {
var orderBook orderbook.Base
orderbookNew, err := p.GetOrderbook(exchange.FormatExchangeCurrency(p.GetName(), currencyPair).String(), 1000)
orderbookNew, err := h.GetOrderbook(exchange.FormatExchangeCurrency(h.GetName(), currencyPair).String(), 1000)
if err != nil {
return orderBook, err
}
@@ -114,16 +115,16 @@ func (p *HitBTC) UpdateOrderbook(currencyPair pair.CurrencyPair, assetType strin
orderBook.Asks = append(orderBook.Asks, orderbook.Item{Amount: data.Amount, Price: data.Price})
}
orderbook.ProcessOrderbook(p.GetName(), currencyPair, orderBook, assetType)
return orderbook.GetOrderbook(p.Name, currencyPair, assetType)
orderbook.ProcessOrderbook(h.GetName(), currencyPair, orderBook, assetType)
return orderbook.GetOrderbook(h.Name, currencyPair, assetType)
}
// GetExchangeAccountInfo retrieves balances for all enabled currencies for the
// HitBTC exchange
func (p *HitBTC) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
func (h *HitBTC) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
var response exchange.AccountInfo
response.ExchangeName = p.GetName()
accountBalance, err := p.GetBalances()
response.ExchangeName = h.GetName()
accountBalance, err := h.GetBalances()
if err != nil {
return response, err
}
@@ -137,3 +138,10 @@ func (p *HitBTC) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
}
return response, nil
}
// GetExchangeHistory returns historic trade data since exchange opening.
func (h *HitBTC) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
var resp []exchange.TradeHistory
return resp, errors.New("trade history not yet implemented")
}

View File

@@ -176,7 +176,7 @@ func (h *HUOBI) GetTrades(symbol string) ([]Trade, error) {
type response struct {
Response
tick struct {
Tick struct {
Data []Trade `json:"data"`
} `json:"tick"`
}
@@ -188,7 +188,7 @@ func (h *HUOBI) GetTrades(symbol string) ([]Trade, error) {
if result.ErrorMessage != "" {
return nil, errors.New(result.ErrorMessage)
}
return result.tick.Data, err
return result.Tick.Data, err
}
// GetTradeHistory returns the trades for the specified symbol
@@ -222,7 +222,7 @@ func (h *HUOBI) GetMarketDetail(symbol string) (Detail, error) {
type response struct {
Response
tick Detail `json:"tick"`
Tick Detail `json:"tick"`
}
var result response
@@ -230,9 +230,9 @@ func (h *HUOBI) GetMarketDetail(symbol string) (Detail, error) {
err := common.SendHTTPGetRequest(common.EncodeURLValues(url, vals), true, h.Verbose, &result)
if result.ErrorMessage != "" {
return result.tick, errors.New(result.ErrorMessage)
return result.Tick, errors.New(result.ErrorMessage)
}
return result.tick, err
return result.Tick, err
}
// GetSymbols returns an array of symbols supported by Huobi

View File

@@ -8,39 +8,41 @@ import (
)
const (
HUOBI_SOCKETIO_ADDRESS = "https://hq.huobi.com:443"
huobiSocketIOAddress = "https://hq.huobi.com:443"
//Service API
HUOBI_SOCKET_REQ_SYMBOL_LIST = "reqSymbolList"
HUOBI_SOCKET_REQ_SYMBOL_DETAIL = "reqSymbolDetail"
HUOBI_SOCKET_REQ_SUBSCRIBE = "reqMsgSubscribe"
HUOBI_SOCKET_REQ_UNSUBSCRIBE = "reqMsgUnsubscribe"
huobiSocketReqSymbolList = "reqSymbolList"
huobiSocketReqSymbolDetail = "reqSymbolDetail"
huobiSocketReqSubscribe = "reqMsgSubscribe"
huobiSocketReqUnsubscribe = "reqMsgUnsubscribe"
// Market data API
HUOBI_SOCKET_MARKET_DETAIL = "marketDetail"
HUOBI_SOCKET_TRADE_DETAIL = "tradeDetail"
HUOBI_SOCKET_MARKET_DEPTH_TOP = "marketDepthTop"
HUOBI_SOCKET_MARKET_DEPTH_TOP_SHORT = "marketDepthTopShort"
HUOBI_SOCKET_MARKET_DEPTH = "marketDepth"
HUOBI_SOCKET_MARKET_DEPTH_TOP_DIFF = "marketDepthTopDiff"
HUOBI_SOCKET_MARKET_DEPTH_DIFF = "marketDepthDiff"
HUOBI_SOCKET_MARKET_LAST_KLINE = "lastKLine"
HUOBI_SOCKET_MARKET_LAST_TIMELINE = "lastTimeLine"
HUOBI_SOCKET_MARKET_OVERVIEW = "marketOverview"
HUOBI_SOCKET_MARKET_STATIC = "marketStatic"
huobiSocketMarketDetail = "marketDetail"
huobiSocketTradeDetail = "tradeDetail"
huobiSocketMarketDepthTop = "marketDepthTop"
huobiSocketMarketDepthTopShort = "marketDepthTopShort"
huobiSocketMarketDepth = "marketDepth"
huobiSocketMarketDepthTopDiff = "marketDepthTopDiff"
huobiSocketMarketDepthDiff = "marketDepthDiff"
huobiSocketMarketLastKline = "lastKLine"
huobiSocketMarketLastTimeline = "lastTimeLine"
huobiSocketMarketOverview = "marketOverview"
huobiSocketMarketStatic = "marketStatic"
// History data API
HUOBI_SOCKET_REQ_TIMELINE = "reqTimeLine"
HUOBI_SOCKET_REQ_KLINE = "reqKLine"
HUOBI_SOCKET_REQ_DEPTH_TOP = "reqMarketDepthTop"
HUOBI_SOCKET_REQ_DEPTH = "reqMarketDepth"
HUOBI_SOCKET_REQ_TRADE_DETAIL_TOP = "reqTradeDetailTop"
HUOBI_SOCKET_REQ_MARKET_DETAIL = "reqMarketDetail"
huobiSocketReqTimeline = "reqTimeLine"
huobiSocketReqKline = "reqKLine"
huobiSocketReqDepthTop = "reqMarketDepthTop"
huobiSocketReqDepth = "reqMarketDepth"
huobiSocketReqTradeDetailTop = "reqTradeDetailTop"
huobiSocketReqMarketDetail = "reqMarketDetail"
)
// HuobiSocket is a pointer to a IO Socket
var HuobiSocket *socketio.SocketIO
type HuobiDepth struct {
// Depth holds depth information
type Depth struct {
SymbolID string `json:"symbolId"`
Time float64 `json:"time"`
Version float64 `json:"version"`
@@ -54,24 +56,27 @@ type HuobiDepth struct {
AskAmount []float64 `json:"askAmount"`
}
type HuobiWebsocketTrade struct {
// WebsocketTrade holds full trade data
type WebsocketTrade struct {
Price []float64 `json:"price"`
Level []float64 `json:"level"`
Amount []float64 `json:"amount"`
AccuAmount []float64 `json:"accuAmount"`
}
type HuobiWebsocketTradeDetail struct {
SymbolID string `json:"symbolId"`
TradeID []int64 `json:"tradeId"`
Price []float64 `json:"price"`
Time []int64 `json:"time"`
Amount []float64 `json:"amount"`
TopBids []HuobiWebsocketTrade `json:"topBids"`
TopAsks []HuobiWebsocketTrade `json:"topAsks"`
// WebsocketTradeDetail holds specific trade details
type WebsocketTradeDetail struct {
SymbolID string `json:"symbolId"`
TradeID []int64 `json:"tradeId"`
Price []float64 `json:"price"`
Time []int64 `json:"time"`
Amount []float64 `json:"amount"`
TopBids []WebsocketTrade `json:"topBids"`
TopAsks []WebsocketTrade `json:"topAsks"`
}
type HuobiWebsocketMarketOverview struct {
// WebsocketMarketOverview holds market overview data
type WebsocketMarketOverview struct {
SymbolID string `json:"symbolId"`
Last float64 `json:"priceNew"`
Open float64 `json:"priceOpen"`
@@ -83,7 +88,8 @@ type HuobiWebsocketMarketOverview struct {
TotalAmount float64 `json:"totalAmount"`
}
type HuobiWebsocketLastTimeline struct {
// WebsocketLastTimeline holds timeline data
type WebsocketLastTimeline struct {
ID int64 `json:"_id"`
SymbolID string `json:"symbolId"`
Time int64 `json:"time"`
@@ -93,7 +99,8 @@ type HuobiWebsocketLastTimeline struct {
Count int64 `json:"count"`
}
type HuobiResponse struct {
// WebsocketResponse is a general response type for websocket
type WebsocketResponse struct {
Version int `json:"version"`
MsgType string `json:"msgType"`
RequestIndex int64 `json:"requestIndex"`
@@ -102,6 +109,7 @@ type HuobiResponse struct {
Payload map[string]interface{} `json:"payload"`
}
// BuildHuobiWebsocketRequest packages a new request
func (h *HUOBI) BuildHuobiWebsocketRequest(msgType string, requestIndex int64, symbolRequest []string) map[string]interface{} {
request := map[string]interface{}{}
request["version"] = 1
@@ -118,7 +126,8 @@ func (h *HUOBI) BuildHuobiWebsocketRequest(msgType string, requestIndex int64, s
return request
}
func (h *HUOBI) BuildHuobiWebsocketRequestExtra(msgType string, requestIndex int64, symbolIdList interface{}) interface{} {
// BuildHuobiWebsocketRequestExtra packages an extra request
func (h *HUOBI) BuildHuobiWebsocketRequestExtra(msgType string, requestIndex int64, symbolIDList interface{}) interface{} {
request := map[string]interface{}{}
request["version"] = 1
request["msgType"] = msgType
@@ -127,10 +136,11 @@ func (h *HUOBI) BuildHuobiWebsocketRequestExtra(msgType string, requestIndex int
request["requestIndex"] = requestIndex
}
request["symbolList"] = symbolIdList
request["symbolList"] = symbolIDList
return request
}
// BuildHuobiWebsocketParamsList packages a parameter list
func (h *HUOBI) BuildHuobiWebsocketParamsList(objectName, currency, pushType, period, count, from, to, percentage string) interface{} {
list := map[string]interface{}{}
list["symbolId"] = currency
@@ -160,6 +170,7 @@ func (h *HUOBI) BuildHuobiWebsocketParamsList(objectName, currency, pushType, pe
return listCompleted
}
// OnConnect handles connection establishment
func (h *HUOBI) OnConnect(output chan socketio.Message) {
if h.Verbose {
log.Printf("%s Connected to Websocket.", h.GetName())
@@ -167,7 +178,7 @@ func (h *HUOBI) OnConnect(output chan socketio.Message) {
for _, x := range h.EnabledPairs {
currency := common.StringToLower(x)
msg := h.BuildHuobiWebsocketRequestExtra(HUOBI_SOCKET_REQ_SUBSCRIBE, 100, h.BuildHuobiWebsocketParamsList(HUOBI_SOCKET_MARKET_OVERVIEW, currency, "pushLong", "", "", "", "", ""))
msg := h.BuildHuobiWebsocketRequestExtra(huobiSocketReqSubscribe, 100, h.BuildHuobiWebsocketParamsList(huobiSocketMarketOverview, currency, "pushLong", "", "", "", "", ""))
result, err := common.JSONEncode(msg)
if err != nil {
log.Println(err)
@@ -176,27 +187,32 @@ func (h *HUOBI) OnConnect(output chan socketio.Message) {
}
}
// OnDisconnect handles disconnection
func (h *HUOBI) OnDisconnect(output chan socketio.Message) {
log.Printf("%s Disconnected from websocket server.. Reconnecting.\n", h.GetName())
h.WebsocketClient()
}
// OnError handles error issues
func (h *HUOBI) OnError() {
log.Printf("%s Error with Websocket connection.. Reconnecting.\n", h.GetName())
h.WebsocketClient()
}
// OnMessage handles messages from the exchange
func (h *HUOBI) OnMessage(message []byte, output chan socketio.Message) {
}
// OnRequest handles requests
func (h *HUOBI) OnRequest(message []byte, output chan socketio.Message) {
response := HuobiResponse{}
response := WebsocketResponse{}
err := common.JSONDecode(message, &response)
if err != nil {
log.Println(err)
}
}
// WebsocketClient creates a new websocket client
func (h *HUOBI) WebsocketClient() {
events := make(map[string]func(message []byte, output chan socketio.Message))
events["request"] = h.OnRequest
@@ -211,7 +227,7 @@ func (h *HUOBI) WebsocketClient() {
}
for h.Enabled && h.Websocket {
err := socketio.ConnectToSocket(HUOBI_SOCKETIO_ADDRESS, HuobiSocket)
err := socketio.ConnectToSocket(huobiSocketIOAddress, HuobiSocket)
if err != nil {
log.Printf("%s Unable to connect to Websocket. Err: %s\n", h.GetName(), err)
continue

View File

@@ -1,6 +1,7 @@
package huobi
import (
"errors"
"log"
"github.com/thrasher-/gocryptotrader/common"
@@ -19,7 +20,7 @@ func (h *HUOBI) Start() {
// Run implements the HUOBI wrapper
func (h *HUOBI) Run() {
if h.Verbose {
log.Printf("%s Websocket: %s (url: %s).\n", h.GetName(), common.IsEnabled(h.Websocket), HUOBI_SOCKETIO_ADDRESS)
log.Printf("%s Websocket: %s (url: %s).\n", h.GetName(), common.IsEnabled(h.Websocket), huobiSocketIOAddress)
log.Printf("%s polling delay: %ds.\n", h.GetName(), h.RESTPollingDelay)
log.Printf("%s %d currencies enabled: %s.\n", h.GetName(), len(h.EnabledPairs), h.EnabledPairs)
}
@@ -39,17 +40,17 @@ func (h *HUOBI) Run() {
if common.StringDataContains(h.BaseCurrencies, "CNY") {
cfg := config.GetConfig()
exchCfg, err := cfg.GetExchangeConfig(h.Name)
exchCfg, errCNY := cfg.GetExchangeConfig(h.Name)
if err != nil {
log.Printf("%s failed to get exchange config. %s\n", h.Name, err)
log.Printf("%s failed to get exchange config. %s\n", h.Name, errCNY)
return
}
exchCfg.BaseCurrencies = "USD"
h.BaseCurrencies = []string{"USD"}
err = cfg.UpdateExchangeConfig(exchCfg)
if err != nil {
log.Printf("%s failed to update config. %s\n", h.Name, err)
errCNY = cfg.UpdateExchangeConfig(exchCfg)
if errCNY != nil {
log.Printf("%s failed to update config. %s\n", h.Name, errCNY)
return
}
}
@@ -142,3 +143,10 @@ func (h *HUOBI) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
response.ExchangeName = h.GetName()
return response, nil
}
// GetExchangeHistory returns historic trade data since exchange opening.
func (h *HUOBI) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
var resp []exchange.TradeHistory
return resp, errors.New("trade history not yet implemented")
}

View File

@@ -1,6 +1,7 @@
package itbit
import (
"errors"
"log"
"strconv"
@@ -107,3 +108,10 @@ func (i *ItBit) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
response.ExchangeName = i.GetName()
return response, nil
}
// GetExchangeHistory returns historic trade data since exchange opening.
func (i *ItBit) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
var resp []exchange.TradeHistory
return resp, errors.New("trade history not yet implemented")
}

View File

@@ -1,6 +1,7 @@
package kraken
import (
"errors"
"fmt"
"log"
"net/url"
@@ -178,3 +179,10 @@ func (k *Kraken) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
response.ExchangeName = k.GetName()
return response, nil
}
// GetExchangeHistory returns historic trade data since exchange opening.
func (k *Kraken) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
var resp []exchange.TradeHistory
return resp, errors.New("trade history not yet implemented")
}

View File

@@ -1,6 +1,7 @@
package lakebtc
import (
"errors"
"log"
"strconv"
@@ -107,3 +108,10 @@ func (l *LakeBTC) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
}
return response, nil
}
// GetExchangeHistory returns historic trade data since exchange opening.
func (l *LakeBTC) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
var resp []exchange.TradeHistory
return resp, errors.New("trade history not yet implemented")
}

View File

@@ -84,7 +84,6 @@ func (l *Liqui) Setup(exch config.ExchangeConfig) {
// GetFee returns a fee for a specific currency
func (l *Liqui) GetFee(currency string) (float64, error) {
log.Println(l.Info.Pairs)
val, ok := l.Info.Pairs[common.StringToLower(currency)]
if !ok {
return 0, errors.New("currency does not exist")
@@ -124,10 +123,12 @@ func (l *Liqui) GetInfo() (Info, error) {
// currencyPair - example "eth_btc"
func (l *Liqui) GetTicker(currencyPair string) (map[string]Ticker, error) {
type Response struct {
Data map[string]Ticker
Data map[string]Ticker
Success int `json:"success"`
Error string `json:"error"`
}
response := Response{}
response := Response{Data: make(map[string]Ticker)}
req := fmt.Sprintf("%s/%s/%s/%s", liquiAPIPublicURL, liquiAPIPublicVersion, liquiTicker, currencyPair)
return response.Data,
@@ -139,10 +140,12 @@ func (l *Liqui) GetTicker(currencyPair string) (map[string]Ticker, error) {
// displayed (150 by default). Is set to less than 2000.
func (l *Liqui) GetDepth(currencyPair string) (Orderbook, error) {
type Response struct {
Data map[string]Orderbook
Data map[string]Orderbook
Success int `json:"success"`
Error string `json:"error"`
}
response := Response{}
response := Response{Data: make(map[string]Orderbook)}
req := fmt.Sprintf("%s/%s/%s/%s", liquiAPIPublicURL, liquiAPIPublicVersion, liquiDepth, currencyPair)
return response.Data[currencyPair],
@@ -154,10 +157,12 @@ func (l *Liqui) GetDepth(currencyPair string) (Orderbook, error) {
// displayed (150 by default). The maximum allowable value is 2000.
func (l *Liqui) GetTrades(currencyPair string) ([]Trades, error) {
type Response struct {
Data map[string][]Trades
Data map[string][]Trades
Success int `json:"success"`
Error string `json:"error"`
}
response := Response{}
response := Response{Data: make(map[string][]Trades)}
req := fmt.Sprintf("%s/%s/%s/%s", liquiAPIPublicURL, liquiAPIPublicVersion, liquiTrades, currencyPair)
return response.Data[currencyPair],
@@ -190,19 +195,21 @@ func (l *Liqui) Trade(pair, orderType string, amount, price float64) (float64, e
// GetActiveOrders returns the list of your active orders.
func (l *Liqui) GetActiveOrders(pair string) (map[string]ActiveOrders, error) {
result := make(map[string]ActiveOrders)
req := url.Values{}
req.Add("pair", pair)
var result map[string]ActiveOrders
return result, l.SendAuthenticatedHTTPRequest(liquiActiveOrders, req, &result)
}
// GetOrderInfo returns the information on particular order.
func (l *Liqui) GetOrderInfo(OrderID int64) (map[string]OrderInfo, error) {
result := make(map[string]OrderInfo)
req := url.Values{}
req.Add("order_id", strconv.FormatInt(OrderID, 10))
var result map[string]OrderInfo
return result, l.SendAuthenticatedHTTPRequest(liquiOrderInfo, req, &result)
}
@@ -223,11 +230,12 @@ func (l *Liqui) CancelOrder(OrderID int64) (bool, error) {
// GetTradeHistory returns trade history
func (l *Liqui) GetTradeHistory(vals url.Values, pair string) (map[string]TradeHistory, error) {
result := make(map[string]TradeHistory)
if pair != "" {
vals.Add("pair", pair)
}
var result map[string]TradeHistory
return result, l.SendAuthenticatedHTTPRequest(liquiTradeHistory, vals, &result)
}

View File

@@ -1,6 +1,7 @@
package liqui
import (
"log"
"net/url"
"testing"
@@ -34,6 +35,7 @@ func TestSetup(t *testing.T) {
}
func TestGetFee(t *testing.T) {
t.Parallel()
_, err := l.GetFee("usd")
if err == nil {
t.Error("Test Failed - liqui GetFee() error", err)
@@ -41,6 +43,7 @@ func TestGetFee(t *testing.T) {
}
func TestGetAvailablePairs(t *testing.T) {
t.Parallel()
v := l.GetAvailablePairs(false)
if len(v) != 0 {
t.Error("Test Failed - liqui GetFee() error")
@@ -48,6 +51,7 @@ func TestGetAvailablePairs(t *testing.T) {
}
func TestGetInfo(t *testing.T) {
t.Parallel()
_, err := l.GetInfo()
if err != nil {
t.Error("Test Failed - liqui GetInfo() error", err)
@@ -55,6 +59,7 @@ func TestGetInfo(t *testing.T) {
}
func TestGetTicker(t *testing.T) {
t.Parallel()
_, err := l.GetTicker("eth_btc")
if err != nil {
t.Error("Test Failed - liqui GetTicker() error", err)
@@ -62,64 +67,57 @@ func TestGetTicker(t *testing.T) {
}
func TestGetDepth(t *testing.T) {
_, err := l.GetDepth("eth_btc")
t.Parallel()
v, err := l.GetDepth("eth_btc")
if err != nil {
t.Error("Test Failed - liqui GetDepth() error", err)
}
log.Println(v)
}
func TestGetTrades(t *testing.T) {
t.Parallel()
_, err := l.GetTrades("eth_btc")
if err != nil {
t.Error("Test Failed - liqui GetTrades() error", err)
}
}
func TestGetAccountInfo(t *testing.T) {
_, err := l.GetAccountInfo()
if err == nil {
t.Error("Test Failed - liqui GetAccountInfo() error", err)
}
}
func TestAuthRequests(t *testing.T) {
if l.APIKey != "" && l.APISecret != "" {
_, err := l.GetAccountInfo()
if err == nil {
t.Error("Test Failed - liqui GetAccountInfo() error", err)
}
func TestTrade(t *testing.T) {
_, err := l.Trade("", "", 0, 1)
if err == nil {
t.Error("Test Failed - liqui Trade() error", err)
}
}
_, err = l.Trade("", "", 0, 1)
if err == nil {
t.Error("Test Failed - liqui Trade() error", err)
}
func TestGetActiveOrders(t *testing.T) {
_, err := l.GetActiveOrders("eth_btc")
if err == nil {
t.Error("Test Failed - liqui GetActiveOrders() error", err)
}
}
_, err = l.GetActiveOrders("eth_btc")
if err == nil {
t.Error("Test Failed - liqui GetActiveOrders() error", err)
}
func TestGetOrderInfo(t *testing.T) {
_, err := l.GetOrderInfo(1337)
if err == nil {
t.Error("Test Failed - liqui GetOrderInfo() error", err)
}
}
_, err = l.GetOrderInfo(1337)
if err == nil {
t.Error("Test Failed - liqui GetOrderInfo() error", err)
}
func TestCancelOrder(t *testing.T) {
_, err := l.CancelOrder(1337)
if err == nil {
t.Error("Test Failed - liqui CancelOrder() error", err)
}
}
_, err = l.CancelOrder(1337)
if err == nil {
t.Error("Test Failed - liqui CancelOrder() error", err)
}
func TestGetTradeHistory(t *testing.T) {
_, err := l.GetTradeHistory(url.Values{}, "")
if err == nil {
t.Error("Test Failed - liqui GetTradeHistory() error", err)
}
}
_, err = l.GetTradeHistory(url.Values{}, "")
if err == nil {
t.Error("Test Failed - liqui GetTradeHistory() error", err)
}
func TestWithdrawCoins(t *testing.T) {
_, err := l.WithdrawCoins("btc", 1337, "someaddr")
if err == nil {
t.Error("Test Failed - liqui WithdrawCoins() error", err)
_, err = l.WithdrawCoins("btc", 1337, "someaddr")
if err == nil {
t.Error("Test Failed - liqui WithdrawCoins() error", err)
}
}
}

View File

@@ -4,6 +4,8 @@ package liqui
type Info struct {
ServerTime int64 `json:"server_time"`
Pairs map[string]PairData `json:"pairs"`
Success int `json:"success"`
Error string `json:"error"`
}
// PairData is a sub-type for Info
@@ -18,15 +20,15 @@ type PairData struct {
// Ticker contains ticker information
type Ticker struct {
High float64
Low float64
Avg float64
Vol float64
Vol_cur float64
Last float64
Buy float64
Sell float64
Updated int64
High float64
Low float64
Avg float64
Vol float64
VolumeCurrency float64
Last float64
Buy float64
Sell float64
Updated int64
}
// Orderbook references both ask and bid sides
@@ -55,6 +57,8 @@ type AccountInfo struct {
ServerTime float64 `json:"server_time"`
TransactionCount int `json:"transaction_count"`
OpenOrders int `json:"open_orders"`
Success int `json:"success"`
Error string `json:"error"`
}
// ActiveOrders holds active order information
@@ -65,6 +69,8 @@ type ActiveOrders struct {
Rate float64 `json:"rate"`
TimestampCreated float64 `json:"time_created"`
Status int `json:"status"`
Success int `json:"success"`
Error string `json:"error"`
}
// OrderInfo holds specific order information
@@ -76,12 +82,16 @@ type OrderInfo struct {
Rate float64 `json:"rate"`
TimestampCreated float64 `json:"time_created"`
Status int `json:"status"`
Success int `json:"success"`
Error string `json:"error"`
}
// CancelOrder holds cancelled order information
type CancelOrder struct {
OrderID float64 `json:"order_id"`
Funds map[string]float64 `json:"funds"`
Success int `json:"success"`
Error string `json:"error"`
}
// Trade holds trading information
@@ -90,6 +100,8 @@ type Trade struct {
Remains float64 `json:"remains"`
OrderID float64 `json:"order_id"`
Funds map[string]float64 `json:"funds"`
Success int `json:"success"`
Error string `json:"error"`
}
// TradeHistory contains trade history data
@@ -101,6 +113,8 @@ type TradeHistory struct {
OrderID float64 `json:"order_id"`
MyOrder int `json:"is_your_order"`
Timestamp float64 `json:"timestamp"`
Success int `json:"success"`
Error string `json:"error"`
}
// Response is a generalized return type
@@ -115,4 +129,6 @@ type WithdrawCoins struct {
TID int64 `json:"tId"`
AmountSent float64 `json:"amountSent"`
Funds map[string]float64 `json:"funds"`
Success int `json:"success"`
Error string `json:"error"`
}

View File

@@ -1,6 +1,7 @@
package liqui
import (
"errors"
"log"
"github.com/thrasher-/gocryptotrader/common"
@@ -58,7 +59,7 @@ func (l *Liqui) UpdateTicker(p pair.CurrencyPair, assetType string) (ticker.Pric
tp.Bid = result[currency].Buy
tp.Last = result[currency].Last
tp.Low = result[currency].Low
tp.Volume = result[currency].Vol_cur
tp.Volume = result[currency].VolumeCurrency
ticker.ProcessTicker(l.Name, x, tp, assetType)
}
@@ -125,3 +126,10 @@ func (l *Liqui) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
return response, nil
}
// GetExchangeHistory returns historic trade data since exchange opening.
func (l *Liqui) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
var resp []exchange.TradeHistory
return resp, errors.New("trade history not yet implemented")
}

View File

@@ -1,6 +1,7 @@
package localbitcoins
import (
"errors"
"log"
"github.com/thrasher-/gocryptotrader/currency/pair"
@@ -98,3 +99,10 @@ func (l *LocalBitcoins) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
response.Currencies = append(response.Currencies, exchangeCurrency)
return response, nil
}
// GetExchangeHistory returns historic trade data since exchange opening.
func (l *LocalBitcoins) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
var resp []exchange.TradeHistory
return resp, errors.New("trade history not yet implemented")
}

View File

@@ -16,61 +16,62 @@ import (
)
const (
OKCOIN_API_URL = "https://www.okcoin.com/api/v1/"
OKCOIN_API_URL_CHINA = "https://www.okcoin.cn/api/v1/"
OKCOIN_API_VERSION = "1"
OKCOIN_WEBSOCKET_URL = "wss://real.okcoin.com:10440/websocket/okcoinapi"
OKCOIN_WEBSOCKET_URL_CHINA = "wss://real.okcoin.cn:10440/websocket/okcoinapi"
OKCOIN_TICKER = "ticker.do"
OKCOIN_DEPTH = "depth.do"
OKCOIN_TRADES = "trades.do"
OKCOIN_KLINE = "kline.do"
OKCOIN_USERINFO = "userinfo.do"
OKCOIN_TRADE = "trade.do"
OKCOIN_TRADE_HISTORY = "trade_history.do"
OKCOIN_TRADE_BATCH = "batch_trade.do"
OKCOIN_ORDER_CANCEL = "cancel_order.do"
OKCOIN_ORDER_INFO = "order_info.do"
OKCOIN_ORDERS_INFO = "orders_info.do"
OKCOIN_ORDER_HISTORY = "order_history.do"
OKCOIN_WITHDRAW = "withdraw.do"
OKCOIN_WITHDRAW_CANCEL = "cancel_withdraw.do"
OKCOIN_WITHDRAW_INFO = "withdraw_info.do"
OKCOIN_ORDER_FEE = "order_fee.do"
OKCOIN_LEND_DEPTH = "lend_depth.do"
OKCOIN_BORROWS_INFO = "borrows_info.do"
OKCOIN_BORROW_MONEY = "borrow_money.do"
OKCOIN_BORROW_CANCEL = "cancel_borrow.do"
OKCOIN_BORROW_ORDER_INFO = "borrow_order_info.do"
OKCOIN_REPAYMENT = "repayment.do"
OKCOIN_UNREPAYMENTS_INFO = "unrepayments_info.do"
OKCOIN_ACCOUNT_RECORDS = "account_records.do"
OKCOIN_FUTURES_TICKER = "future_ticker.do"
OKCOIN_FUTURES_DEPTH = "future_depth.do"
OKCOIN_FUTURES_TRADES = "future_trades.do"
OKCOIN_FUTURES_INDEX = "future_index.do"
OKCOIN_EXCHANGE_RATE = "exchange_rate.do"
OKCOIN_FUTURES_ESTIMATED_PRICE = "future_estimated_price.do"
OKCOIN_FUTURES_KLINE = "future_kline.do"
OKCOIN_FUTURES_HOLD_AMOUNT = "future_hold_amount.do"
OKCOIN_FUTURES_USERINFO = "future_userinfo.do"
OKCOIN_FUTURES_POSITION = "future_position.do"
OKCOIN_FUTURES_TRADE = "future_trade.do"
OKCOIN_FUTURES_TRADE_HISTORY = "future_trades_history.do"
OKCOIN_FUTURES_TRADE_BATCH = "future_batch_trade.do"
OKCOIN_FUTURES_CANCEL = "future_cancel.do"
OKCOIN_FUTURES_ORDER_INFO = "future_order_info.do"
OKCOIN_FUTURES_ORDERS_INFO = "future_orders_info.do"
OKCOIN_FUTURES_USERINFO_4FIX = "future_userinfo_4fix.do"
OKCOIN_FUTURES_POSITION_4FIX = "future_position_4fix.do"
OKCOIN_FUTURES_EXPLOSIVE = "future_explosive.do"
OKCOIN_FUTURES_DEVOLVE = "future_devolve.do"
okcoinAPIURL = "https://www.okcoin.com/api/v1/"
okcoinAPIURLChina = "https://www.okcoin.cn/api/v1/"
okcoinAPIVersion = "1"
okcoinWebsocketURL = "wss://real.okcoin.com:10440/websocket/okcoinapi"
okcoinWebsocketURLChina = "wss://real.okcoin.cn:10440/websocket/okcoinapi"
okcoinTicker = "ticker.do"
okcoinDepth = "depth.do"
okcoinTrades = "trades.do"
okcoinKline = "kline.do"
okcoinUserInfo = "userinfo.do"
okcoinTrade = "trade.do"
okcoinTradeHistory = "trade_history.do"
okcoinTradeBatch = "batch_trade.do"
okcoinOrderCancel = "cancel_order.do"
okcoinOrderInfo = "order_info.do"
okcoinOrdersInfo = "orders_info.do"
okcoinOrderHistory = "order_history.do"
okcoinWithdraw = "withdraw.do"
okcoinWithdrawCancel = "cancel_withdraw.do"
okcoinWithdrawInfo = "withdraw_info.do"
okcoinOrderFee = "order_fee.do"
okcoinLendDepth = "lend_depth.do"
okcoinBorrowsInfo = "borrows_info.do"
okcoinBorrowMoney = "borrow_money.do"
okcoinBorrowCancel = "cancel_borrow.do"
okcoinBorrowOrderInfo = "borrow_order_info.do"
okcoinRepayment = "repayment.do"
okcoinUnrepaymentsInfo = "unrepayments_info.do"
okcoinAccountRecords = "account_records.do"
okcoinFuturesTicker = "future_ticker.do"
okcoinFuturesDepth = "future_depth.do"
okcoinFuturesTrades = "future_trades.do"
okcoinFuturesIndex = "future_index.do"
okcoinExchangeRate = "exchange_rate.do"
okcoinFuturesEstimatedPrice = "future_estimated_price.do"
okcoinFuturesKline = "future_kline.do"
okcoinFuturesHoldAmount = "future_hold_amount.do"
okcoinFuturesUserInfo = "future_userinfo.do"
okcoinFuturesPosition = "future_position.do"
okcoinFuturesTrade = "future_trade.do"
okcoinFuturesTradeHistory = "future_trades_history.do"
okcoinFuturesTradeBatch = "future_batch_trade.do"
okcoinFuturesCancel = "future_cancel.do"
okcoinFuturesOrderInfo = "future_order_info.do"
okcoinFuturesOrdersInfo = "future_orders_info.do"
okcoinFuturesUserInfo4Fix = "future_userinfo_4fix.do"
okcoinFuturesposition4Fix = "future_position_4fix.do"
okcoinFuturesExplosive = "future_explosive.do"
okcoinFuturesDevolve = "future_devolve.do"
)
var (
okcoinDefaultsSet = false
)
// OKCoin is the overarching type across this package
type OKCoin struct {
exchange.Base
RESTErrors map[string]string
@@ -79,6 +80,7 @@ type OKCoin struct {
WebsocketConn *websocket.Conn
}
// setCurrencyPairFormats sets currency pair formatting for this package
func (o *OKCoin) setCurrencyPairFormats() {
o.RequestCurrencyPairFormat.Delimiter = "_"
o.RequestCurrencyPairFormat.Uppercase = false
@@ -86,6 +88,7 @@ func (o *OKCoin) setCurrencyPairFormats() {
o.ConfigCurrencyPairFormat.Uppercase = true
}
// SetDefaults sets current default values for this package
func (o *OKCoin) SetDefaults() {
o.SetErrorDefaults()
o.SetWebsocketErrorDefaults()
@@ -98,19 +101,20 @@ func (o *OKCoin) SetDefaults() {
if okcoinDefaultsSet {
o.AssetTypes = append(o.AssetTypes, o.FuturesValues...)
o.APIUrl = OKCOIN_API_URL
o.APIUrl = okcoinAPIURL
o.Name = "OKCOIN International"
o.WebsocketURL = OKCOIN_WEBSOCKET_URL
o.WebsocketURL = okcoinWebsocketURL
o.setCurrencyPairFormats()
} else {
o.APIUrl = OKCOIN_API_URL_CHINA
o.APIUrl = okcoinAPIURLChina
o.Name = "OKCOIN China"
o.WebsocketURL = OKCOIN_WEBSOCKET_URL_CHINA
o.WebsocketURL = okcoinWebsocketURLChina
okcoinDefaultsSet = true
o.setCurrencyPairFormats()
}
}
// Setup sets exchange configuration parameters
func (o *OKCoin) Setup(exch config.ExchangeConfig) {
if !exch.Enabled {
o.SetEnabled(false)
@@ -135,32 +139,34 @@ func (o *OKCoin) Setup(exch config.ExchangeConfig) {
}
}
// GetFee returns current fees for the exchange
func (o *OKCoin) GetFee(maker bool) float64 {
if o.APIUrl == OKCOIN_API_URL {
if o.APIUrl == okcoinAPIURL {
if maker {
return o.MakerFee
} else {
return o.TakerFee
}
return o.TakerFee
}
// Chinese exchange does not have any trading fees
return 0
}
func (o *OKCoin) GetTicker(symbol string) (OKCoinTicker, error) {
resp := OKCoinTickerResponse{}
// GetTicker returns the current ticker
func (o *OKCoin) GetTicker(symbol string) (Ticker, error) {
resp := TickerResponse{}
vals := url.Values{}
vals.Set("symbol", symbol)
path := common.EncodeURLValues(o.APIUrl+OKCOIN_TICKER, vals)
path := common.EncodeURLValues(o.APIUrl+okcoinTicker, vals)
err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp)
if err != nil {
return OKCoinTicker{}, err
return Ticker{}, err
}
return resp.Ticker, nil
}
func (o *OKCoin) GetOrderBook(symbol string, size int64, merge bool) (OKCoinOrderbook, error) {
resp := OKCoinOrderbook{}
// GetOrderBook returns the current order book by size
func (o *OKCoin) GetOrderBook(symbol string, size int64, merge bool) (Orderbook, error) {
resp := Orderbook{}
vals := url.Values{}
vals.Set("symbol", symbol)
if size != 0 {
@@ -170,7 +176,7 @@ func (o *OKCoin) GetOrderBook(symbol string, size int64, merge bool) (OKCoinOrde
vals.Set("merge", "1")
}
path := common.EncodeURLValues(o.APIUrl+OKCOIN_DEPTH, vals)
path := common.EncodeURLValues(o.APIUrl+okcoinDepth, vals)
err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp)
if err != nil {
return resp, err
@@ -178,15 +184,16 @@ func (o *OKCoin) GetOrderBook(symbol string, size int64, merge bool) (OKCoinOrde
return resp, nil
}
func (o *OKCoin) GetTrades(symbol string, since int64) ([]OKCoinTrades, error) {
result := []OKCoinTrades{}
// GetTrades returns historic trades since a timestamp
func (o *OKCoin) GetTrades(symbol string, since int64) ([]Trades, error) {
result := []Trades{}
vals := url.Values{}
vals.Set("symbol", symbol)
if since != 0 {
vals.Set("since", strconv.FormatInt(since, 10))
}
path := common.EncodeURLValues(o.APIUrl+OKCOIN_TRADES, vals)
path := common.EncodeURLValues(o.APIUrl+okcoinTrades, vals)
err := common.SendHTTPGetRequest(path, true, o.Verbose, &result)
if err != nil {
return nil, err
@@ -194,6 +201,7 @@ func (o *OKCoin) GetTrades(symbol string, since int64) ([]OKCoinTrades, error) {
return result, nil
}
// GetKline returns kline data
func (o *OKCoin) GetKline(symbol, klineType string, size, since int64) ([]interface{}, error) {
resp := []interface{}{}
vals := url.Values{}
@@ -208,7 +216,7 @@ func (o *OKCoin) GetKline(symbol, klineType string, size, since int64) ([]interf
vals.Set("since", strconv.FormatInt(since, 10))
}
path := common.EncodeURLValues(o.APIUrl+OKCOIN_KLINE, vals)
path := common.EncodeURLValues(o.APIUrl+okcoinKline, vals)
err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp)
if err != nil {
return nil, err
@@ -217,21 +225,23 @@ func (o *OKCoin) GetKline(symbol, klineType string, size, since int64) ([]interf
return resp, nil
}
func (o *OKCoin) GetFuturesTicker(symbol, contractType string) (OKCoinFuturesTicker, error) {
resp := OKCoinFuturesTickerResponse{}
// GetFuturesTicker returns a current ticker for the futures market
func (o *OKCoin) GetFuturesTicker(symbol, contractType string) (FuturesTicker, error) {
resp := FuturesTickerResponse{}
vals := url.Values{}
vals.Set("symbol", symbol)
vals.Set("contract_type", contractType)
path := common.EncodeURLValues(o.APIUrl+OKCOIN_FUTURES_TICKER, vals)
path := common.EncodeURLValues(o.APIUrl+okcoinFuturesTicker, vals)
err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp)
if err != nil {
return OKCoinFuturesTicker{}, err
return FuturesTicker{}, err
}
return resp.Ticker, nil
}
func (o *OKCoin) GetFuturesDepth(symbol, contractType string, size int64, merge bool) (OKCoinOrderbook, error) {
result := OKCoinOrderbook{}
// GetFuturesDepth returns current depth for the futures market
func (o *OKCoin) GetFuturesDepth(symbol, contractType string, size int64, merge bool) (Orderbook, error) {
result := Orderbook{}
vals := url.Values{}
vals.Set("symbol", symbol)
vals.Set("contract_type", contractType)
@@ -243,7 +253,7 @@ func (o *OKCoin) GetFuturesDepth(symbol, contractType string, size int64, merge
vals.Set("merge", "1")
}
path := common.EncodeURLValues(o.APIUrl+OKCOIN_FUTURES_DEPTH, vals)
path := common.EncodeURLValues(o.APIUrl+okcoinFuturesDepth, vals)
err := common.SendHTTPGetRequest(path, true, o.Verbose, &result)
if err != nil {
return result, err
@@ -251,13 +261,14 @@ func (o *OKCoin) GetFuturesDepth(symbol, contractType string, size int64, merge
return result, nil
}
func (o *OKCoin) GetFuturesTrades(symbol, contractType string) ([]OKCoinFuturesTrades, error) {
result := []OKCoinFuturesTrades{}
// GetFuturesTrades returns historic trades for the futures market
func (o *OKCoin) GetFuturesTrades(symbol, contractType string) ([]FuturesTrades, error) {
result := []FuturesTrades{}
vals := url.Values{}
vals.Set("symbol", symbol)
vals.Set("contract_type", contractType)
path := common.EncodeURLValues(o.APIUrl+OKCOIN_FUTURES_TRADES, vals)
path := common.EncodeURLValues(o.APIUrl+okcoinFuturesTrades, vals)
err := common.SendHTTPGetRequest(path, true, o.Verbose, &result)
if err != nil {
return nil, err
@@ -265,6 +276,7 @@ func (o *OKCoin) GetFuturesTrades(symbol, contractType string) ([]OKCoinFuturesT
return result, nil
}
// GetFuturesIndex returns an index for the futures market
func (o *OKCoin) GetFuturesIndex(symbol string) (float64, error) {
type Response struct {
Index float64 `json:"future_index"`
@@ -274,7 +286,7 @@ func (o *OKCoin) GetFuturesIndex(symbol string) (float64, error) {
vals := url.Values{}
vals.Set("symbol", symbol)
path := common.EncodeURLValues(o.APIUrl+OKCOIN_FUTURES_INDEX, vals)
path := common.EncodeURLValues(o.APIUrl+okcoinFuturesIndex, vals)
err := common.SendHTTPGetRequest(path, true, o.Verbose, &result)
if err != nil {
return 0, err
@@ -282,19 +294,22 @@ func (o *OKCoin) GetFuturesIndex(symbol string) (float64, error) {
return result.Index, nil
}
// GetFuturesExchangeRate returns the exchange rate for the futures market
func (o *OKCoin) GetFuturesExchangeRate() (float64, error) {
type Response struct {
Rate float64 `json:"rate"`
}
result := Response{}
err := common.SendHTTPGetRequest(o.APIUrl+OKCOIN_EXCHANGE_RATE, true, o.Verbose, &result)
err := common.SendHTTPGetRequest(o.APIUrl+okcoinExchangeRate, true, o.Verbose, &result)
if err != nil {
return result.Rate, err
}
return result.Rate, nil
}
// GetFuturesEstimatedPrice returns a current estimated futures price for a
// currency
func (o *OKCoin) GetFuturesEstimatedPrice(symbol string) (float64, error) {
type Response struct {
Price float64 `json:"forecast_price"`
@@ -303,7 +318,7 @@ func (o *OKCoin) GetFuturesEstimatedPrice(symbol string) (float64, error) {
result := Response{}
vals := url.Values{}
vals.Set("symbol", symbol)
path := common.EncodeURLValues(o.APIUrl+OKCOIN_FUTURES_ESTIMATED_PRICE, vals)
path := common.EncodeURLValues(o.APIUrl+okcoinFuturesEstimatedPrice, vals)
err := common.SendHTTPGetRequest(path, true, o.Verbose, &result)
if err != nil {
return result.Price, err
@@ -311,6 +326,8 @@ func (o *OKCoin) GetFuturesEstimatedPrice(symbol string) (float64, error) {
return result.Price, nil
}
// GetFuturesKline returns kline data for a specific currency on the futures
// market
func (o *OKCoin) GetFuturesKline(symbol, klineType, contractType string, size, since int64) ([]interface{}, error) {
resp := []interface{}{}
vals := url.Values{}
@@ -325,7 +342,7 @@ func (o *OKCoin) GetFuturesKline(symbol, klineType, contractType string, size, s
vals.Set("since", strconv.FormatInt(since, 10))
}
path := common.EncodeURLValues(o.APIUrl+OKCOIN_FUTURES_KLINE, vals)
path := common.EncodeURLValues(o.APIUrl+okcoinFuturesKline, vals)
err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp)
if err != nil {
@@ -334,13 +351,14 @@ func (o *OKCoin) GetFuturesKline(symbol, klineType, contractType string, size, s
return resp, nil
}
func (o *OKCoin) GetFuturesHoldAmount(symbol, contractType string) ([]OKCoinFuturesHoldAmount, error) {
resp := []OKCoinFuturesHoldAmount{}
// GetFuturesHoldAmount returns the hold amount for a futures trade
func (o *OKCoin) GetFuturesHoldAmount(symbol, contractType string) ([]FuturesHoldAmount, error) {
resp := []FuturesHoldAmount{}
vals := url.Values{}
vals.Set("symbol", symbol)
vals.Set("contract_type", contractType)
path := common.EncodeURLValues(o.APIUrl+OKCOIN_FUTURES_HOLD_AMOUNT, vals)
path := common.EncodeURLValues(o.APIUrl+okcoinFuturesHoldAmount, vals)
err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp)
if err != nil {
@@ -349,9 +367,10 @@ func (o *OKCoin) GetFuturesHoldAmount(symbol, contractType string) ([]OKCoinFutu
return resp, nil
}
func (o *OKCoin) GetFuturesExplosive(symbol, contractType string, status, currentPage, pageLength int64) ([]OKCoinFuturesExplosive, error) {
// GetFuturesExplosive returns the explosive for a futures contract
func (o *OKCoin) GetFuturesExplosive(symbol, contractType string, status, currentPage, pageLength int64) ([]FuturesExplosive, error) {
type Response struct {
Data []OKCoinFuturesExplosive `json:"data"`
Data []FuturesExplosive `json:"data"`
}
resp := Response{}
vals := url.Values{}
@@ -361,7 +380,7 @@ func (o *OKCoin) GetFuturesExplosive(symbol, contractType string, status, curren
vals.Set("current_page", strconv.FormatInt(currentPage, 10))
vals.Set("page_length", strconv.FormatInt(pageLength, 10))
path := common.EncodeURLValues(o.APIUrl+OKCOIN_FUTURES_EXPLOSIVE, vals)
path := common.EncodeURLValues(o.APIUrl+okcoinFuturesExplosive, vals)
err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp)
if err != nil {
@@ -371,9 +390,10 @@ func (o *OKCoin) GetFuturesExplosive(symbol, contractType string, status, curren
return resp.Data, nil
}
func (o *OKCoin) GetUserInfo() (OKCoinUserInfo, error) {
result := OKCoinUserInfo{}
err := o.SendAuthenticatedHTTPRequest(OKCOIN_USERINFO, url.Values{}, &result)
// GetUserInfo returns user information associated with the calling APIkeys
func (o *OKCoin) GetUserInfo() (UserInfo, error) {
result := UserInfo{}
err := o.SendAuthenticatedHTTPRequest(okcoinUserInfo, url.Values{}, &result)
if err != nil {
return result, err
@@ -382,6 +402,7 @@ func (o *OKCoin) GetUserInfo() (OKCoinUserInfo, error) {
return result, nil
}
// Trade initiates a new trade
func (o *OKCoin) Trade(amount, price float64, symbol, orderType string) (int64, error) {
type Response struct {
Result bool `json:"result"`
@@ -395,26 +416,27 @@ func (o *OKCoin) Trade(amount, price float64, symbol, orderType string) (int64,
result := Response{}
err := o.SendAuthenticatedHTTPRequest(OKCOIN_TRADE, v, &result)
err := o.SendAuthenticatedHTTPRequest(okcoinTrade, v, &result)
if err != nil {
return 0, err
}
if !result.Result {
return 0, errors.New("Unable to place order.")
return 0, errors.New("unable to place order")
}
return result.OrderID, nil
}
func (o *OKCoin) GetTradeHistory(symbol string, TradeID int64) ([]OKCoinTrades, error) {
result := []OKCoinTrades{}
// GetTradeHistory returns client trade history
func (o *OKCoin) GetTradeHistory(symbol string, TradeID int64) ([]Trades, error) {
result := []Trades{}
v := url.Values{}
v.Set("symbol", symbol)
v.Set("since", strconv.FormatInt(TradeID, 10))
err := o.SendAuthenticatedHTTPRequest(OKCOIN_TRADE_HISTORY, v, &result)
err := o.SendAuthenticatedHTTPRequest(okcoinTradeHistory, v, &result)
if err != nil {
return nil, err
@@ -423,14 +445,15 @@ func (o *OKCoin) GetTradeHistory(symbol string, TradeID int64) ([]OKCoinTrades,
return result, nil
}
func (o *OKCoin) BatchTrade(orderData string, symbol, orderType string) (OKCoinBatchTrade, error) {
// BatchTrade initiates a trade by batch order
func (o *OKCoin) BatchTrade(orderData string, symbol, orderType string) (BatchTrade, error) {
v := url.Values{}
v.Set("orders_data", orderData)
v.Set("symbol", symbol)
v.Set("type", orderType)
result := OKCoinBatchTrade{}
result := BatchTrade{}
err := o.SendAuthenticatedHTTPRequest(OKCOIN_TRADE_BATCH, v, &result)
err := o.SendAuthenticatedHTTPRequest(okcoinTradeBatch, v, &result)
if err != nil {
return result, err
@@ -439,60 +462,56 @@ func (o *OKCoin) BatchTrade(orderData string, symbol, orderType string) (OKCoinB
return result, nil
}
func (o *OKCoin) CancelOrder(orderID []int64, symbol string) (OKCoinCancelOrderResponse, error) {
// CancelOrder cancels a specific order or list of orders by orderID
func (o *OKCoin) CancelOrder(orderID []int64, symbol string) (CancelOrderResponse, error) {
v := url.Values{}
orders := []string{}
orderStr := ""
result := OKCoinCancelOrderResponse{}
result := CancelOrderResponse{}
orderStr := strconv.FormatInt(orderID[0], 10)
if len(orderID) > 1 {
for x := range orderID {
orders = append(orders, strconv.FormatInt(orderID[x], 10))
}
orderStr = common.JoinStrings(orders, ",")
} else {
orderStr = strconv.FormatInt(orderID[0], 10)
}
v.Set("order_id", orderStr)
v.Set("symbol", symbol)
err := o.SendAuthenticatedHTTPRequest(OKCOIN_ORDER_CANCEL, v, &result)
if err != nil {
return result, err
}
return result, nil
return result, o.SendAuthenticatedHTTPRequest(okcoinOrderCancel, v, &result)
}
func (o *OKCoin) GetOrderInfo(orderID int64, symbol string) ([]OKCoinOrderInfo, error) {
// GetOrderInfo returns order information by orderID
func (o *OKCoin) GetOrderInfo(orderID int64, symbol string) ([]OrderInfo, error) {
type Response struct {
Result bool `json:"result"`
Orders []OKCoinOrderInfo `json:"orders"`
Result bool `json:"result"`
Orders []OrderInfo `json:"orders"`
}
v := url.Values{}
v.Set("symbol", symbol)
v.Set("order_id", strconv.FormatInt(orderID, 10))
result := Response{}
err := o.SendAuthenticatedHTTPRequest(OKCOIN_ORDER_INFO, v, &result)
err := o.SendAuthenticatedHTTPRequest(okcoinOrderInfo, v, &result)
if err != nil {
return nil, err
}
if result.Result != true {
return nil, errors.New("Unable to retrieve order info.")
return nil, errors.New("unable to retrieve order info")
}
return result.Orders, nil
}
func (o *OKCoin) GetOrderInfoBatch(orderID []int64, symbol string) ([]OKCoinOrderInfo, error) {
// GetOrderInfoBatch returns order info on a batch of orders
func (o *OKCoin) GetOrderInfoBatch(orderID []int64, symbol string) ([]OrderInfo, error) {
type Response struct {
Result bool `json:"result"`
Orders []OKCoinOrderInfo `json:"orders"`
Result bool `json:"result"`
Orders []OrderInfo `json:"orders"`
}
orders := []string{}
@@ -505,28 +524,29 @@ func (o *OKCoin) GetOrderInfoBatch(orderID []int64, symbol string) ([]OKCoinOrde
v.Set("order_id", common.JoinStrings(orders, ","))
result := Response{}
err := o.SendAuthenticatedHTTPRequest(OKCOIN_ORDER_INFO, v, &result)
err := o.SendAuthenticatedHTTPRequest(okcoinOrderInfo, v, &result)
if err != nil {
return nil, err
}
if result.Result != true {
return nil, errors.New("Unable to retrieve order info.")
return nil, errors.New("unable to retrieve order info")
}
return result.Orders, nil
}
func (o *OKCoin) GetOrderHistory(pageLength, currentPage int64, status, symbol string) (OKCoinOrderHistory, error) {
// GetOrderHistory returns a history of orders
func (o *OKCoin) GetOrderHistory(pageLength, currentPage int64, status, symbol string) (OrderHistory, error) {
v := url.Values{}
v.Set("symbol", symbol)
v.Set("status", status)
v.Set("current_page", strconv.FormatInt(currentPage, 10))
v.Set("page_length", strconv.FormatInt(pageLength, 10))
result := OKCoinOrderHistory{}
result := OrderHistory{}
err := o.SendAuthenticatedHTTPRequest(OKCOIN_ORDER_HISTORY, v, &result)
err := o.SendAuthenticatedHTTPRequest(okcoinOrderHistory, v, &result)
if err != nil {
return result, err
@@ -535,6 +555,7 @@ func (o *OKCoin) GetOrderHistory(pageLength, currentPage int64, status, symbol s
return result, nil
}
// Withdrawal withdraws a cryptocurrency to a supplied address
func (o *OKCoin) Withdrawal(symbol string, fee float64, tradePWD, address string, amount float64) (int, error) {
v := url.Values{}
v.Set("symbol", symbol)
@@ -545,67 +566,70 @@ func (o *OKCoin) Withdrawal(symbol string, fee float64, tradePWD, address string
v.Set("trade_pwd", tradePWD)
v.Set("withdraw_address", address)
v.Set("withdraw_amount", strconv.FormatFloat(amount, 'f', -1, 64))
result := OKCoinWithdrawalResponse{}
result := WithdrawalResponse{}
err := o.SendAuthenticatedHTTPRequest(OKCOIN_WITHDRAW, v, &result)
err := o.SendAuthenticatedHTTPRequest(okcoinWithdraw, v, &result)
if err != nil {
return 0, err
}
if !result.Result {
return 0, errors.New("Unable to process withdrawal request.")
return 0, errors.New("unable to process withdrawal request")
}
return result.WithdrawID, nil
}
// CancelWithdrawal cancels a withdrawal
func (o *OKCoin) CancelWithdrawal(symbol string, withdrawalID int64) (int, error) {
v := url.Values{}
v.Set("symbol", symbol)
v.Set("withdrawal_id", strconv.FormatInt(withdrawalID, 10))
result := OKCoinWithdrawalResponse{}
result := WithdrawalResponse{}
err := o.SendAuthenticatedHTTPRequest(OKCOIN_WITHDRAW_CANCEL, v, &result)
err := o.SendAuthenticatedHTTPRequest(okcoinWithdrawCancel, v, &result)
if err != nil {
return 0, err
}
if !result.Result {
return 0, errors.New("Unable to process withdrawal cancel request.")
return 0, errors.New("unable to process withdrawal cancel request")
}
return result.WithdrawID, nil
}
func (o *OKCoin) GetWithdrawalInfo(symbol string, withdrawalID int64) ([]OKCoinWithdrawInfo, error) {
// GetWithdrawalInfo returns withdrawal information
func (o *OKCoin) GetWithdrawalInfo(symbol string, withdrawalID int64) ([]WithdrawInfo, error) {
type Response struct {
Result bool
Withdraw []OKCoinWithdrawInfo `json:"withdraw"`
Withdraw []WithdrawInfo `json:"withdraw"`
}
v := url.Values{}
v.Set("symbol", symbol)
v.Set("withdrawal_id", strconv.FormatInt(withdrawalID, 10))
result := Response{}
err := o.SendAuthenticatedHTTPRequest(OKCOIN_WITHDRAW_INFO, v, &result)
err := o.SendAuthenticatedHTTPRequest(okcoinWithdrawInfo, v, &result)
if err != nil {
return nil, err
}
if !result.Result {
return nil, errors.New("Unable to process withdrawal cancel request.")
return nil, errors.New("unable to process withdrawal cancel request")
}
return result.Withdraw, nil
}
func (o *OKCoin) GetOrderFeeInfo(symbol string, orderID int64) (OKCoinOrderFeeInfo, error) {
// GetOrderFeeInfo returns order fee information
func (o *OKCoin) GetOrderFeeInfo(symbol string, orderID int64) (OrderFeeInfo, error) {
type Response struct {
Data OKCoinOrderFeeInfo `json:"data"`
Result bool `json:"result"`
Data OrderFeeInfo `json:"data"`
Result bool `json:"result"`
}
v := url.Values{}
@@ -613,29 +637,30 @@ func (o *OKCoin) GetOrderFeeInfo(symbol string, orderID int64) (OKCoinOrderFeeIn
v.Set("order_id", strconv.FormatInt(orderID, 10))
result := Response{}
err := o.SendAuthenticatedHTTPRequest(OKCOIN_ORDER_FEE, v, &result)
err := o.SendAuthenticatedHTTPRequest(okcoinOrderFee, v, &result)
if err != nil {
return result.Data, err
}
if !result.Result {
return result.Data, errors.New("Unable to get order fee info.")
return result.Data, errors.New("unable to get order fee info")
}
return result.Data, nil
}
func (o *OKCoin) GetLendDepth(symbol string) ([]OKCoinLendDepth, error) {
// GetLendDepth returns the depth of lends
func (o *OKCoin) GetLendDepth(symbol string) ([]LendDepth, error) {
type Response struct {
LendDepth []OKCoinLendDepth `json:"lend_depth"`
LendDepth []LendDepth `json:"lend_depth"`
}
v := url.Values{}
v.Set("symbol", symbol)
result := Response{}
err := o.SendAuthenticatedHTTPRequest(OKCOIN_LEND_DEPTH, v, &result)
err := o.SendAuthenticatedHTTPRequest(okcoinLendDepth, v, &result)
if err != nil {
return nil, err
@@ -644,12 +669,13 @@ func (o *OKCoin) GetLendDepth(symbol string) ([]OKCoinLendDepth, error) {
return result.LendDepth, nil
}
func (o *OKCoin) GetBorrowInfo(symbol string) (OKCoinBorrowInfo, error) {
// GetBorrowInfo returns borrow information
func (o *OKCoin) GetBorrowInfo(symbol string) (BorrowInfo, error) {
v := url.Values{}
v.Set("symbol", symbol)
result := OKCoinBorrowInfo{}
result := BorrowInfo{}
err := o.SendAuthenticatedHTTPRequest(OKCOIN_BORROWS_INFO, v, &result)
err := o.SendAuthenticatedHTTPRequest(okcoinBorrowsInfo, v, &result)
if err != nil {
return result, nil
@@ -658,113 +684,119 @@ func (o *OKCoin) GetBorrowInfo(symbol string) (OKCoinBorrowInfo, error) {
return result, nil
}
// Borrow initiates a borrow request
func (o *OKCoin) Borrow(symbol, days string, amount, rate float64) (int, error) {
v := url.Values{}
v.Set("symbol", symbol)
v.Set("days", days)
v.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64))
v.Set("rate", strconv.FormatFloat(rate, 'f', -1, 64))
result := OKCoinBorrowResponse{}
result := BorrowResponse{}
err := o.SendAuthenticatedHTTPRequest(OKCOIN_BORROW_MONEY, v, &result)
err := o.SendAuthenticatedHTTPRequest(okcoinBorrowMoney, v, &result)
if err != nil {
return 0, err
}
if !result.Result {
return 0, errors.New("Unable to borrow.")
return 0, errors.New("unable to borrow")
}
return result.BorrowID, nil
}
// CancelBorrow cancels a borrow request
func (o *OKCoin) CancelBorrow(symbol string, borrowID int64) (bool, error) {
v := url.Values{}
v.Set("symbol", symbol)
v.Set("borrow_id", strconv.FormatInt(borrowID, 10))
result := OKCoinBorrowResponse{}
result := BorrowResponse{}
err := o.SendAuthenticatedHTTPRequest(OKCOIN_BORROW_CANCEL, v, &result)
err := o.SendAuthenticatedHTTPRequest(okcoinBorrowCancel, v, &result)
if err != nil {
return false, err
}
if !result.Result {
return false, errors.New("Unable to cancel borrow.")
return false, errors.New("unable to cancel borrow")
}
return true, nil
}
func (o *OKCoin) GetBorrowOrderInfo(borrowID int64) (OKCoinBorrowInfo, error) {
// GetBorrowOrderInfo returns information about a borrow order
func (o *OKCoin) GetBorrowOrderInfo(borrowID int64) (BorrowInfo, error) {
type Response struct {
Result bool `json:"result"`
BorrowOrder OKCoinBorrowInfo `json:"borrow_order"`
Result bool `json:"result"`
BorrowOrder BorrowInfo `json:"borrow_order"`
}
v := url.Values{}
v.Set("borrow_id", strconv.FormatInt(borrowID, 10))
result := Response{}
err := o.SendAuthenticatedHTTPRequest(OKCOIN_BORROW_ORDER_INFO, v, &result)
err := o.SendAuthenticatedHTTPRequest(okcoinBorrowOrderInfo, v, &result)
if err != nil {
return result.BorrowOrder, err
}
if !result.Result {
return result.BorrowOrder, errors.New("Unable to get borrow info.")
return result.BorrowOrder, errors.New("unable to get borrow info")
}
return result.BorrowOrder, nil
}
// GetRepaymentInfo returns information on a repayment
func (o *OKCoin) GetRepaymentInfo(borrowID int64) (bool, error) {
v := url.Values{}
v.Set("borrow_id", strconv.FormatInt(borrowID, 10))
result := OKCoinBorrowResponse{}
result := BorrowResponse{}
err := o.SendAuthenticatedHTTPRequest(OKCOIN_REPAYMENT, v, &result)
err := o.SendAuthenticatedHTTPRequest(okcoinRepayment, v, &result)
if err != nil {
return false, err
}
if !result.Result {
return false, errors.New("Unable to get repayment info.")
return false, errors.New("unable to get repayment info")
}
return true, nil
}
func (o *OKCoin) GetUnrepaymentsInfo(symbol string, currentPage, pageLength int) ([]OKCoinBorrowOrder, error) {
// GetUnrepaymentsInfo returns information on an unrepayment
func (o *OKCoin) GetUnrepaymentsInfo(symbol string, currentPage, pageLength int) ([]BorrowOrder, error) {
type Response struct {
Unrepayments []OKCoinBorrowOrder `json:"unrepayments"`
Result bool `json:"result"`
Unrepayments []BorrowOrder `json:"unrepayments"`
Result bool `json:"result"`
}
v := url.Values{}
v.Set("symbol", symbol)
v.Set("current_page", strconv.Itoa(currentPage))
v.Set("page_length", strconv.Itoa(pageLength))
result := Response{}
err := o.SendAuthenticatedHTTPRequest(OKCOIN_UNREPAYMENTS_INFO, v, &result)
err := o.SendAuthenticatedHTTPRequest(okcoinUnrepaymentsInfo, v, &result)
if err != nil {
return nil, err
}
if !result.Result {
return nil, errors.New("Unable to get unrepayments info.")
return nil, errors.New("unable to get unrepayments info")
}
return result.Unrepayments, nil
}
func (o *OKCoin) GetAccountRecords(symbol string, recType, currentPage, pageLength int) ([]OKCoinAccountRecords, error) {
// GetAccountRecords returns account records
func (o *OKCoin) GetAccountRecords(symbol string, recType, currentPage, pageLength int) ([]AccountRecords, error) {
type Response struct {
Records []OKCoinAccountRecords `json:"records"`
Symbol string `json:"symbol"`
Records []AccountRecords `json:"records"`
Symbol string `json:"symbol"`
}
v := url.Values{}
v.Set("symbol", symbol)
@@ -773,7 +805,7 @@ func (o *OKCoin) GetAccountRecords(symbol string, recType, currentPage, pageLeng
v.Set("page_length", strconv.Itoa(pageLength))
result := Response{}
err := o.SendAuthenticatedHTTPRequest(OKCOIN_ACCOUNT_RECORDS, v, &result)
err := o.SendAuthenticatedHTTPRequest(okcoinAccountRecords, v, &result)
if err != nil {
return nil, err
@@ -782,25 +814,28 @@ func (o *OKCoin) GetAccountRecords(symbol string, recType, currentPage, pageLeng
return result.Records, nil
}
// GetFuturesUserInfo returns information on a users futures
func (o *OKCoin) GetFuturesUserInfo() {
err := o.SendAuthenticatedHTTPRequest(OKCOIN_FUTURES_USERINFO, url.Values{}, nil)
err := o.SendAuthenticatedHTTPRequest(okcoinFuturesUserInfo, url.Values{}, nil)
if err != nil {
log.Println(err)
}
}
// GetFuturesPosition returns position on a futures contract
func (o *OKCoin) GetFuturesPosition(symbol, contractType string) {
v := url.Values{}
v.Set("symbol", symbol)
v.Set("contract_type", contractType)
err := o.SendAuthenticatedHTTPRequest(OKCOIN_FUTURES_POSITION, v, nil)
err := o.SendAuthenticatedHTTPRequest(okcoinFuturesPosition, v, nil)
if err != nil {
log.Println(err)
}
}
// FuturesTrade initiates a new futures trade
func (o *OKCoin) FuturesTrade(amount, price float64, matchPrice, leverage int64, symbol, contractType, orderType string) {
v := url.Values{}
v.Set("symbol", symbol)
@@ -811,13 +846,14 @@ func (o *OKCoin) FuturesTrade(amount, price float64, matchPrice, leverage int64,
v.Set("match_price", strconv.FormatInt(matchPrice, 10))
v.Set("lever_rate", strconv.FormatInt(leverage, 10))
err := o.SendAuthenticatedHTTPRequest(OKCOIN_FUTURES_TRADE, v, nil)
err := o.SendAuthenticatedHTTPRequest(okcoinFuturesTrade, v, nil)
if err != nil {
log.Println(err)
}
}
// FuturesBatchTrade initiates a batch of futures contract trades
func (o *OKCoin) FuturesBatchTrade(orderData, symbol, contractType string, leverage int64, orderType string) {
v := url.Values{} //to-do batch trade support for orders_data)
v.Set("symbol", symbol)
@@ -825,26 +861,28 @@ func (o *OKCoin) FuturesBatchTrade(orderData, symbol, contractType string, lever
v.Set("orders_data", orderData)
v.Set("lever_rate", strconv.FormatInt(leverage, 10))
err := o.SendAuthenticatedHTTPRequest(OKCOIN_FUTURES_TRADE_BATCH, v, nil)
err := o.SendAuthenticatedHTTPRequest(okcoinFuturesTradeBatch, v, nil)
if err != nil {
log.Println(err)
}
}
// CancelFuturesOrder cancels a futures contract order
func (o *OKCoin) CancelFuturesOrder(orderID int64, symbol, contractType string) {
v := url.Values{}
v.Set("symbol", symbol)
v.Set("contract_type", contractType)
v.Set("order_id", strconv.FormatInt(orderID, 10))
err := o.SendAuthenticatedHTTPRequest(OKCOIN_FUTURES_CANCEL, v, nil)
err := o.SendAuthenticatedHTTPRequest(okcoinFuturesCancel, v, nil)
if err != nil {
log.Println(err)
}
}
// GetFuturesOrderInfo returns information on a specfic futures contract order
func (o *OKCoin) GetFuturesOrderInfo(orderID, status, currentPage, pageLength int64, symbol, contractType string) {
v := url.Values{}
v.Set("symbol", symbol)
@@ -854,49 +892,53 @@ func (o *OKCoin) GetFuturesOrderInfo(orderID, status, currentPage, pageLength in
v.Set("current_page", strconv.FormatInt(currentPage, 10))
v.Set("page_length", strconv.FormatInt(pageLength, 10))
err := o.SendAuthenticatedHTTPRequest(OKCOIN_FUTURES_ORDER_INFO, v, nil)
err := o.SendAuthenticatedHTTPRequest(okcoinFuturesOrderInfo, v, nil)
if err != nil {
log.Println(err)
}
}
// GetFutureOrdersInfo returns information on a range of futures orders
func (o *OKCoin) GetFutureOrdersInfo(orderID int64, contractType, symbol string) {
v := url.Values{}
v.Set("order_id", strconv.FormatInt(orderID, 10))
v.Set("contract_type", contractType)
v.Set("symbol", symbol)
err := o.SendAuthenticatedHTTPRequest(OKCOIN_FUTURES_ORDERS_INFO, v, nil)
err := o.SendAuthenticatedHTTPRequest(okcoinFuturesOrdersInfo, v, nil)
if err != nil {
log.Println(err)
}
}
// GetFuturesUserInfo4Fix returns futures user info fix rate
func (o *OKCoin) GetFuturesUserInfo4Fix() {
v := url.Values{}
err := o.SendAuthenticatedHTTPRequest(OKCOIN_FUTURES_USERINFO_4FIX, v, nil)
err := o.SendAuthenticatedHTTPRequest(okcoinFuturesUserInfo4Fix, v, nil)
if err != nil {
log.Println(err)
}
}
// GetFuturesUserPosition4Fix returns futures user info on a fixed position
func (o *OKCoin) GetFuturesUserPosition4Fix(symbol, contractType string) {
v := url.Values{}
v.Set("symbol", symbol)
v.Set("contract_type", contractType)
v.Set("type", strconv.FormatInt(1, 10))
err := o.SendAuthenticatedHTTPRequest(OKCOIN_FUTURES_POSITION_4FIX, v, nil)
err := o.SendAuthenticatedHTTPRequest(okcoinFuturesUserInfo4Fix, v, nil)
if err != nil {
log.Println(err)
}
}
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request
func (o *OKCoin) SendAuthenticatedHTTPRequest(method string, v url.Values, result interface{}) (err error) {
if !o.AuthenticatedAPISupport {
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, o.Name)
@@ -935,6 +977,7 @@ func (o *OKCoin) SendAuthenticatedHTTPRequest(method string, v url.Values, resul
return nil
}
// SetErrorDefaults sets default error map
func (o *OKCoin) SetErrorDefaults() {
o.RESTErrors = map[string]string{
"10000": "Required field, can not be null",

View File

@@ -1,6 +1,7 @@
package okcoin
type OKCoinTicker struct {
// Ticker holds ticker data
type Ticker struct {
Buy float64 `json:",string"`
High float64 `json:",string"`
Last float64 `json:",string"`
@@ -9,32 +10,38 @@ type OKCoinTicker struct {
Vol float64 `json:",string"`
}
type OKCoinTickerResponse struct {
// TickerResponse is the response type for ticker
type TickerResponse struct {
Date string
Ticker OKCoinTicker
}
type OKCoinFuturesTicker struct {
Last float64
Buy float64
Sell float64
High float64
Low float64
Vol float64
Contract_ID int64
Unit_Amount float64
Ticker Ticker
}
type OKCoinOrderbook struct {
// FuturesTicker holds futures ticker data
type FuturesTicker struct {
Last float64
Buy float64
Sell float64
High float64
Low float64
Vol float64
ContractID int64
UnitAmount float64
}
// Orderbook holds orderbook data
type Orderbook struct {
Asks [][]float64 `json:"asks"`
Bids [][]float64 `json:"bids"`
}
type OKCoinFuturesTickerResponse struct {
// FuturesTickerResponse is a response type
type FuturesTickerResponse struct {
Date string
Ticker OKCoinFuturesTicker
Ticker FuturesTicker
}
type OKCoinBorrowInfo struct {
// BorrowInfo holds borrowing amount data
type BorrowInfo struct {
BorrowBTC float64 `json:"borrow_btc"`
BorrowLTC float64 `json:"borrow_ltc"`
BorrowCNY float64 `json:"borrow_cny"`
@@ -47,7 +54,8 @@ type OKCoinBorrowInfo struct {
DailyInterestCNY float64 `json:"today_interest_cny"`
}
type OKCoinBorrowOrder struct {
// BorrowOrder holds order data
type BorrowOrder struct {
Amount float64 `json:"amount"`
BorrowDate int64 `json:"borrow_date"`
BorrowID int64 `json:"borrow_id"`
@@ -58,7 +66,8 @@ type OKCoinBorrowOrder struct {
Symbol string `json:"symbol"`
}
type OKCoinRecord struct {
// Record hold record data
type Record struct {
Address string `json:"addr"`
Account int64 `json:"account,string"`
Amount float64 `json:"amount"`
@@ -69,12 +78,14 @@ type OKCoinRecord struct {
Date float64 `json:"date"`
}
type OKCoinAccountRecords struct {
Records []OKCoinRecord `json:"records"`
Symbol string `json:"symbol"`
// AccountRecords holds account record data
type AccountRecords struct {
Records []Record `json:"records"`
Symbol string `json:"symbol"`
}
type OKCoinFuturesOrder struct {
// FuturesOrder holds information about a futures order
type FuturesOrder struct {
Amount float64 `json:"amount"`
ContractName string `json:"contract_name"`
DateCreated float64 `json:"create_date"`
@@ -90,19 +101,22 @@ type OKCoinFuturesOrder struct {
UnitAmount int64 `json:"unit_amount"`
}
type OKCoinFuturesHoldAmount struct {
// FuturesHoldAmount contains futures hold amount data
type FuturesHoldAmount struct {
Amount float64 `json:"amount"`
ContractName string `json:"contract_name"`
}
type OKCoinFuturesExplosive struct {
// FuturesExplosive holds inforamtion about explosive futures
type FuturesExplosive struct {
Amount float64 `json:"amount,string"`
DateCreated string `json:"create_date"`
Loss float64 `json:"loss,string"`
Type int64 `json:"type"`
}
type OKCoinTrades struct {
// Trades holds trade data
type Trades struct {
Amount float64 `json:"amount,string"`
Date int64 `json:"date"`
DateMS int64 `json:"date_ms"`
@@ -111,7 +125,8 @@ type OKCoinTrades struct {
Type string `json:"type"`
}
type OKCoinFuturesTrades struct {
// FuturesTrades holds trade data for the futures market
type FuturesTrades struct {
Amount float64 `json:"amount"`
Date int64 `json:"date"`
DateMS int64 `json:"date_ms"`
@@ -120,7 +135,8 @@ type OKCoinFuturesTrades struct {
Type string `json:"type"`
}
type OKCoinUserInfo struct {
// UserInfo holds user account details
type UserInfo struct {
Info struct {
Funds struct {
Asset struct {
@@ -154,7 +170,8 @@ type OKCoinUserInfo struct {
Result bool `json:"result"`
}
type OKCoinBatchTrade struct {
// BatchTrade holds data on a batch of trades
type BatchTrade struct {
OrderInfo []struct {
OrderID int64 `json:"order_id"`
ErrorCode int64 `json:"error_code"`
@@ -162,12 +179,14 @@ type OKCoinBatchTrade struct {
Result bool `json:"result"`
}
type OKCoinCancelOrderResponse struct {
// CancelOrderResponse is a response type for a cancelled order
type CancelOrderResponse struct {
Success string
Error string
}
type OKCoinOrderInfo struct {
// OrderInfo holds data on an order
type OrderInfo struct {
Amount float64 `json:"amount"`
AvgPrice float64 `json:"avg_price"`
Created int64 `json:"create_date"`
@@ -180,20 +199,23 @@ type OKCoinOrderInfo struct {
Type string `json:"type"`
}
type OKCoinOrderHistory struct {
CurrentPage int `json:"current_page"`
Orders []OKCoinOrderInfo `json:"orders"`
PageLength int `json:"page_length"`
Result bool `json:"result"`
Total int `json:"total"`
// OrderHistory holds information on order history
type OrderHistory struct {
CurrentPage int `json:"current_page"`
Orders []OrderInfo `json:"orders"`
PageLength int `json:"page_length"`
Result bool `json:"result"`
Total int `json:"total"`
}
type OKCoinWithdrawalResponse struct {
// WithdrawalResponse is a response type for withdrawal
type WithdrawalResponse struct {
WithdrawID int `json:"withdraw_id"`
Result bool `json:"result"`
}
type OKCoinWithdrawInfo struct {
// WithdrawInfo holds data on a withdraw
type WithdrawInfo struct {
Address string `json:"address"`
Amount float64 `json:"amount"`
Created int64 `json:"created_date"`
@@ -202,30 +224,35 @@ type OKCoinWithdrawInfo struct {
WithdrawID int64 `json:"withdraw_id"`
}
type OKCoinOrderFeeInfo struct {
// OrderFeeInfo holds data on order fees
type OrderFeeInfo struct {
Fee float64 `json:"fee,string"`
OrderID int64 `json:"order_id"`
Type string `json:"type"`
}
type OKCoinLendDepth struct {
// LendDepth hold lend depths
type LendDepth struct {
Amount float64 `json:"amount"`
Days string `json:"days"`
Num int64 `json:"num"`
Rate float64 `json:"rate,string"`
}
type OKCoinBorrowResponse struct {
// BorrowResponse is a response type for borrow
type BorrowResponse struct {
Result bool `json:"result"`
BorrowID int `json:"borrow_id"`
}
type OKCoinWebsocketFutureIndex struct {
// WebsocketFutureIndex holds future index data for websocket
type WebsocketFutureIndex struct {
FutureIndex float64 `json:"futureIndex"`
Timestamp int64 `json:"timestamp,string"`
}
type OKCoinWebsocketTicker struct {
// WebsocketTicker holds ticker data for websocket
type WebsocketTicker struct {
Timestamp float64
Vol string
Buy float64
@@ -235,7 +262,8 @@ type OKCoinWebsocketTicker struct {
Sell float64
}
type OKCoinWebsocketFuturesTicker struct {
// WebsocketFuturesTicker holds futures ticker data for websocket
type WebsocketFuturesTicker struct {
Buy float64 `json:"buy"`
ContractID string `json:"contractId"`
High float64 `json:"high"`
@@ -247,13 +275,15 @@ type OKCoinWebsocketFuturesTicker struct {
Volume float64 `json:"vol,string"`
}
type OKCoinWebsocketOrderbook struct {
// WebsocketOrderbook holds orderbook data for websocket
type WebsocketOrderbook struct {
Asks [][]float64 `json:"asks"`
Bids [][]float64 `json:"bids"`
Timestamp int64 `json:"timestamp,string"`
}
type OKCoinWebsocketUserinfo struct {
// WebsocketUserinfo holds user info for websocket
type WebsocketUserinfo struct {
Info struct {
Funds struct {
Asset struct {
@@ -277,7 +307,8 @@ type OKCoinWebsocketUserinfo struct {
Result bool `json:"result"`
}
type OKCoinWebsocketFuturesContract struct {
// WebsocketFuturesContract holds futures contract information for websocket
type WebsocketFuturesContract struct {
Available float64 `json:"available"`
Balance float64 `json:"balance"`
Bond float64 `json:"bond"`
@@ -288,23 +319,25 @@ type OKCoinWebsocketFuturesContract struct {
Loss float64 `json:"unprofit"`
}
type OKCoinWebsocketFuturesUserInfo struct {
// WebsocketFuturesUserInfo holds futures user information for websocket
type WebsocketFuturesUserInfo struct {
Info struct {
BTC struct {
Balance float64 `json:"balance"`
Contracts []OKCoinWebsocketFuturesContract `json:"contracts"`
Rights float64 `json:"rights"`
Balance float64 `json:"balance"`
Contracts []WebsocketFuturesContract `json:"contracts"`
Rights float64 `json:"rights"`
} `json:"btc"`
LTC struct {
Balance float64 `json:"balance"`
Contracts []OKCoinWebsocketFuturesContract `json:"contracts"`
Rights float64 `json:"rights"`
Balance float64 `json:"balance"`
Contracts []WebsocketFuturesContract `json:"contracts"`
Rights float64 `json:"rights"`
} `json:"ltc"`
} `json:"info"`
Result bool `json:"result"`
}
type OKCoinWebsocketOrder struct {
// WebsocketOrder holds order data for websocket
type WebsocketOrder struct {
Amount float64 `json:"amount"`
AvgPrice float64 `json:"avg_price"`
DateCreated float64 `json:"create_date"`
@@ -317,7 +350,8 @@ type OKCoinWebsocketOrder struct {
OrderType string `json:"type"`
}
type OKCoinWebsocketFuturesOrder struct {
// WebsocketFuturesOrder holds futures order data for websocket
type WebsocketFuturesOrder struct {
Amount float64 `json:"amount"`
ContractName string `json:"contract_name"`
DateCreated float64 `json:"createdDate"`
@@ -333,7 +367,8 @@ type OKCoinWebsocketFuturesOrder struct {
UnitAmount float64 `json:"unit_amount"`
}
type OKCoinWebsocketRealtrades struct {
// WebsocketRealtrades holds real trade data for WebSocket
type WebsocketRealtrades struct {
AveragePrice float64 `json:"averagePrice,string"`
CompletedTradeAmount float64 `json:"completedTradeAmount,string"`
DateCreated float64 `json:"createdDate"`
@@ -350,7 +385,8 @@ type OKCoinWebsocketRealtrades struct {
UnTrade float64 `json:"unTrade,string"`
}
type OKCoinWebsocketFuturesRealtrades struct {
// WebsocketFuturesRealtrades holds futures real trade data for websocket
type WebsocketFuturesRealtrades struct {
Amount float64 `json:"amount,string"`
ContractID float64 `json:"contract_id,string"`
ContractName string `json:"contract_name"`
@@ -366,29 +402,34 @@ type OKCoinWebsocketFuturesRealtrades struct {
LeverageAmount int `json:"lever_rate,string"`
}
type OKCoinWebsocketEvent struct {
// WebsocketEvent holds websocket events
type WebsocketEvent struct {
Event string `json:"event"`
Channel string `json:"channel"`
}
type OKCoinWebsocketResponse struct {
// WebsocketResponse holds websocket responses
type WebsocketResponse struct {
Channel string `json:"channel"`
Data interface{} `json:"data"`
}
type OKCoinWebsocketEventAuth struct {
// WebsocketEventAuth holds websocket authenticated events
type WebsocketEventAuth struct {
Event string `json:"event"`
Channel string `json:"channel"`
Parameters map[string]string `json:"parameters"`
}
type OKCoinWebsocketEventAuthRemove struct {
// WebsocketEventAuthRemove holds websocket remove authenticated events
type WebsocketEventAuthRemove struct {
Event string `json:"event"`
Channel string `json:"channel"`
Parameters map[string]string `json:"parameters"`
}
type OKCoinWebsocketTradeOrderResponse struct {
// WebsocketTradeOrderResponse holds trade order responses for websocket
type WebsocketTradeOrderResponse struct {
OrderID int64 `json:"order_id,string"`
Result bool `json:"result,string"`
}

View File

@@ -15,23 +15,24 @@ import (
)
const (
OKCOIN_WEBSOCKET_USD_REALTRADES = "ok_usd_realtrades"
OKCOIN_WEBSOCKET_CNY_REALTRADES = "ok_cny_realtrades"
OKCOIN_WEBSOCKET_SPOTUSD_TRADE = "ok_spotusd_trade"
OKCOIN_WEBSOCKET_SPOTCNY_TRADE = "ok_spotcny_trade"
OKCOIN_WEBSOCKET_SPOTUSD_CANCEL_ORDER = "ok_spotusd_cancel_order"
OKCOIN_WEBSOCKET_SPOTCNY_CANCEL_ORDER = "ok_spotcny_cancel_order"
OKCOIN_WEBSOCKET_SPOTUSD_USERINFO = "ok_spotusd_userinfo"
OKCOIN_WEBSOCKET_SPOTCNY_USERINFO = "ok_spotcny_userinfo"
OKCOIN_WEBSOCKET_SPOTUSD_ORDER_INFO = "ok_spotusd_order_info"
OKCOIN_WEBSOCKET_SPOTCNY_ORDER_INFO = "ok_spotcny_order_info"
OKCOIN_WEBSOCKET_FUTURES_TRADE = "ok_futuresusd_trade"
OKCOIN_WEBSOCKET_FUTURES_CANCEL_ORDER = "ok_futuresusd_cancel_order"
OKCOIN_WEBSOCKET_FUTURES_REALTRADES = "ok_usd_future_realtrades"
OKCOIN_WEBSOCKET_FUTURES_USERINFO = "ok_futureusd_userinfo"
OKCOIN_WEBSOCKET_FUTURES_ORDER_INFO = "ok_futureusd_order_info"
okcoinWebsocketUSDRealTrades = "ok_usd_realtrades"
okcoinWebsocketCNYRealTrades = "ok_cny_realtrades"
okcoinWebsocketSpotUSDTrade = "ok_spotusd_trade"
okcoinWebsocketSpotCNYTrade = "ok_spotcny_trade"
okcoinWebsocketSpotUSDCancelOrder = "ok_spotusd_cancel_order"
okcoinWebsocketSpotCNYCancelOrder = "ok_spotcny_cancel_order"
okcoinWebsocketSpotUSDUserInfo = "ok_spotusd_userinfo"
okcoinWebsocketSpotCNYUserInfo = "ok_spotcny_userinfo"
okcoinWebsocketSpotUSDOrderInfo = "ok_spotusd_order_info"
okcoinWebsocketSpotCNYOrderInfo = "ok_spotcny_order_info"
okcoinWebsocketFuturesTrade = "ok_futuresusd_trade"
okcoinWebsocketFuturesCancelOrder = "ok_futuresusd_cancel_order"
okcoinWebsocketFuturesRealTrades = "ok_usd_future_realtrades"
okcoinWebsocketFuturesUserInfo = "ok_futureusd_userinfo"
okcoinWebsocketFuturesOrderInfo = "ok_futureusd_order_info"
)
// PingHandler handles the keep alive
func (o *OKCoin) PingHandler(message string) error {
err := o.WebsocketConn.WriteControl(websocket.PingMessage, []byte("{'event':'ping'}"), time.Now().Add(time.Second))
@@ -42,8 +43,9 @@ func (o *OKCoin) PingHandler(message string) error {
return nil
}
// AddChannel adds a new channel on the websocket client
func (o *OKCoin) AddChannel(channel string) {
event := OKCoinWebsocketEvent{"addChannel", channel}
event := WebsocketEvent{"addChannel", channel}
json, err := common.JSONEncode(event)
if err != nil {
log.Println(err)
@@ -61,8 +63,9 @@ func (o *OKCoin) AddChannel(channel string) {
}
}
// RemoveChannel removes a channel on the websocket client
func (o *OKCoin) RemoveChannel(channel string) {
event := OKCoinWebsocketEvent{"removeChannel", channel}
event := WebsocketEvent{"removeChannel", channel}
json, err := common.JSONEncode(event)
if err != nil {
log.Println(err)
@@ -80,23 +83,23 @@ func (o *OKCoin) RemoveChannel(channel string) {
}
}
// WebsocketSpotTrade handles spot trade request on the websocket client
func (o *OKCoin) WebsocketSpotTrade(symbol, orderType string, price, amount float64) {
values := make(map[string]string)
values["symbol"] = symbol
values["type"] = orderType
values["price"] = strconv.FormatFloat(price, 'f', -1, 64)
values["amount"] = strconv.FormatFloat(amount, 'f', -1, 64)
channel := ""
if o.WebsocketURL == OKCOIN_WEBSOCKET_URL_CHINA {
channel = OKCOIN_WEBSOCKET_SPOTCNY_TRADE
} else {
channel = OKCOIN_WEBSOCKET_SPOTUSD_TRADE
channel := okcoinWebsocketSpotUSDTrade
if o.WebsocketURL == okcoinWebsocketURLChina {
channel = okcoinWebsocketSpotCNYTrade
}
o.AddChannelAuthenticated(channel, values)
}
// WebsocketFuturesTrade handles a futures trade on the websocket client
func (o *OKCoin) WebsocketFuturesTrade(symbol, contractType string, price, amount float64, orderType, matchPrice, leverage int) {
values := make(map[string]string)
values["symbol"] = symbol
@@ -106,47 +109,48 @@ func (o *OKCoin) WebsocketFuturesTrade(symbol, contractType string, price, amoun
values["type"] = strconv.Itoa(orderType)
values["match_price"] = strconv.Itoa(matchPrice)
values["lever_rate"] = strconv.Itoa(orderType)
o.AddChannelAuthenticated(OKCOIN_WEBSOCKET_FUTURES_TRADE, values)
o.AddChannelAuthenticated(okcoinWebsocketFuturesTrade, values)
}
// WebsocketSpotCancel cancels a spot trade on the websocket client
func (o *OKCoin) WebsocketSpotCancel(symbol string, orderID int64) {
values := make(map[string]string)
values["symbol"] = symbol
values["order_id"] = strconv.FormatInt(orderID, 10)
channel := ""
if o.WebsocketURL == OKCOIN_WEBSOCKET_URL_CHINA {
channel = OKCOIN_WEBSOCKET_SPOTCNY_CANCEL_ORDER
} else {
channel = OKCOIN_WEBSOCKET_SPOTUSD_CANCEL_ORDER
channel := okcoinWebsocketSpotUSDCancelOrder
if o.WebsocketURL == okcoinWebsocketURLChina {
channel = okcoinWebsocketSpotCNYCancelOrder
}
o.AddChannelAuthenticated(channel, values)
}
// WebsocketFuturesCancel cancels a futures contract on the websocket client
func (o *OKCoin) WebsocketFuturesCancel(symbol, contractType string, orderID int64) {
values := make(map[string]string)
values["symbol"] = symbol
values["order_id"] = strconv.FormatInt(orderID, 10)
values["contract_type"] = contractType
o.AddChannelAuthenticated(OKCOIN_WEBSOCKET_FUTURES_CANCEL_ORDER, values)
o.AddChannelAuthenticated(okcoinWebsocketFuturesCancelOrder, values)
}
// WebsocketSpotOrderInfo request information on an order on the websocket
// client
func (o *OKCoin) WebsocketSpotOrderInfo(symbol string, orderID int64) {
values := make(map[string]string)
values["symbol"] = symbol
values["order_id"] = strconv.FormatInt(orderID, 10)
channel := ""
if o.WebsocketURL == OKCOIN_WEBSOCKET_URL_CHINA {
channel = OKCOIN_WEBSOCKET_SPOTCNY_ORDER_INFO
} else {
channel = OKCOIN_WEBSOCKET_SPOTUSD_ORDER_INFO
channel := okcoinWebsocketSpotUSDOrderInfo
if o.WebsocketURL == okcoinWebsocketURLChina {
channel = okcoinWebsocketSpotCNYOrderInfo
}
o.AddChannelAuthenticated(channel, values)
}
// WebsocketFuturesOrderInfo requests futures order info on the websocket client
func (o *OKCoin) WebsocketFuturesOrderInfo(symbol, contractType string, orderID int64, orderStatus, currentPage, pageLength int) {
values := make(map[string]string)
values["symbol"] = symbol
@@ -155,9 +159,10 @@ func (o *OKCoin) WebsocketFuturesOrderInfo(symbol, contractType string, orderID
values["status"] = strconv.Itoa(orderStatus)
values["current_page"] = strconv.Itoa(currentPage)
values["page_length"] = strconv.Itoa(pageLength)
o.AddChannelAuthenticated(OKCOIN_WEBSOCKET_FUTURES_ORDER_INFO, values)
o.AddChannelAuthenticated(okcoinWebsocketFuturesOrderInfo, values)
}
// ConvertToURLValues converts values to url.Values
func (o *OKCoin) ConvertToURLValues(values map[string]string) url.Values {
urlVals := url.Values{}
for i, x := range values {
@@ -166,15 +171,17 @@ func (o *OKCoin) ConvertToURLValues(values map[string]string) url.Values {
return urlVals
}
// WebsocketSign signs values on the webcoket client
func (o *OKCoin) WebsocketSign(values map[string]string) string {
values["api_key"] = o.APIKey
urlVals := o.ConvertToURLValues(values)
return strings.ToUpper(common.HexEncodeToString(common.GetMD5([]byte(urlVals.Encode() + "&secret_key=" + o.APISecret))))
}
// AddChannelAuthenticated adds an authenticated channel on the websocket client
func (o *OKCoin) AddChannelAuthenticated(channel string, values map[string]string) {
values["sign"] = o.WebsocketSign(values)
event := OKCoinWebsocketEventAuth{"addChannel", channel, values}
event := WebsocketEventAuth{"addChannel", channel, values}
json, err := common.JSONEncode(event)
if err != nil {
log.Println(err)
@@ -192,9 +199,11 @@ func (o *OKCoin) AddChannelAuthenticated(channel string, values map[string]strin
}
}
// RemoveChannelAuthenticated removes the added authenticated channel on the
// websocket client
func (o *OKCoin) RemoveChannelAuthenticated(conn *websocket.Conn, channel string, values map[string]string) {
values["sign"] = o.WebsocketSign(values)
event := OKCoinWebsocketEventAuthRemove{"removeChannel", channel, values}
event := WebsocketEventAuthRemove{"removeChannel", channel, values}
json, err := common.JSONEncode(event)
if err != nil {
log.Println(err)
@@ -212,16 +221,17 @@ func (o *OKCoin) RemoveChannelAuthenticated(conn *websocket.Conn, channel string
}
}
// WebsocketClient starts a websocket client
func (o *OKCoin) WebsocketClient() {
klineValues := []string{"1min", "3min", "5min", "15min", "30min", "1hour", "2hour", "4hour", "6hour", "12hour", "day", "3day", "week"}
currencyChan, userinfoChan := "", ""
var currencyChan, userinfoChan string
if o.WebsocketURL == OKCOIN_WEBSOCKET_URL_CHINA {
currencyChan = OKCOIN_WEBSOCKET_CNY_REALTRADES
userinfoChan = OKCOIN_WEBSOCKET_SPOTCNY_USERINFO
if o.WebsocketURL == okcoinWebsocketURLChina {
currencyChan = okcoinWebsocketCNYRealTrades
userinfoChan = okcoinWebsocketSpotCNYUserInfo
} else {
currencyChan = OKCOIN_WEBSOCKET_USD_REALTRADES
userinfoChan = OKCOIN_WEBSOCKET_SPOTUSD_USERINFO
currencyChan = okcoinWebsocketUSDRealTrades
userinfoChan = okcoinWebsocketSpotUSDUserInfo
}
for o.Enabled && o.Websocket {
@@ -241,9 +251,9 @@ func (o *OKCoin) WebsocketClient() {
o.WebsocketConn.SetPingHandler(o.PingHandler)
if o.AuthenticatedAPISupport {
if o.WebsocketURL == OKCOIN_WEBSOCKET_URL {
o.AddChannelAuthenticated(OKCOIN_WEBSOCKET_FUTURES_REALTRADES, map[string]string{})
o.AddChannelAuthenticated(OKCOIN_WEBSOCKET_FUTURES_USERINFO, map[string]string{})
if o.WebsocketURL == okcoinWebsocketURL {
o.AddChannelAuthenticated(okcoinWebsocketFuturesRealTrades, map[string]string{})
o.AddChannelAuthenticated(okcoinWebsocketFuturesUserInfo, map[string]string{})
}
o.AddChannelAuthenticated(currencyChan, map[string]string{})
o.AddChannelAuthenticated(userinfoChan, map[string]string{})
@@ -255,7 +265,7 @@ func (o *OKCoin) WebsocketClient() {
if o.AuthenticatedAPISupport {
o.WebsocketSpotOrderInfo(currencyUL, -1)
}
if o.WebsocketURL == OKCOIN_WEBSOCKET_URL {
if o.WebsocketURL == okcoinWebsocketURL {
o.AddChannel(fmt.Sprintf("ok_%s_future_index", currency))
for _, y := range o.FuturesValues {
if o.AuthenticatedAPISupport {
@@ -336,15 +346,15 @@ func (o *OKCoin) WebsocketClient() {
case common.StringContains(channelStr, "ticker") && !common.StringContains(channelStr, "future"):
tickerValues := []string{"buy", "high", "last", "low", "sell", "timestamp"}
tickerMap := data.(map[string]interface{})
ticker := OKCoinWebsocketTicker{}
ticker := WebsocketTicker{}
ticker.Vol = tickerMap["vol"].(string)
for _, z := range tickerValues {
result := reflect.TypeOf(tickerMap[z]).String()
if result == "string" {
value, err := strconv.ParseFloat(tickerMap[z].(string), 64)
if err != nil {
log.Println(err)
value, errTickVals := strconv.ParseFloat(tickerMap[z].(string), 64)
if errTickVals != nil {
log.Println(errTickVals)
continue
}
@@ -381,7 +391,7 @@ func (o *OKCoin) WebsocketClient() {
}
}
case common.StringContains(channelStr, "ticker") && common.StringContains(channelStr, "future"):
ticker := OKCoinWebsocketFuturesTicker{}
ticker := WebsocketFuturesTicker{}
err = common.JSONDecode(dataJSON, &ticker)
if err != nil {
@@ -389,7 +399,7 @@ func (o *OKCoin) WebsocketClient() {
continue
}
case common.StringContains(channelStr, "depth"):
orderbook := OKCoinWebsocketOrderbook{}
orderbook := WebsocketOrderbook{}
err = common.JSONDecode(dataJSON, &orderbook)
if err != nil {
@@ -411,8 +421,8 @@ func (o *OKCoin) WebsocketClient() {
// to-do: convert from string array to trade struct
case common.StringContains(channelStr, "kline"):
klines := []interface{}{}
err := common.JSONDecode(dataJSON, &klines)
err = common.JSONDecode(dataJSON, &klines)
if err != nil {
log.Println(err)
continue
@@ -421,9 +431,9 @@ func (o *OKCoin) WebsocketClient() {
if string(dataJSON) == "null" {
continue
}
realtrades := OKCoinWebsocketRealtrades{}
err := common.JSONDecode(dataJSON, &realtrades)
realtrades := WebsocketRealtrades{}
err = common.JSONDecode(dataJSON, &realtrades)
if err != nil {
log.Println(err)
continue
@@ -432,73 +442,73 @@ func (o *OKCoin) WebsocketClient() {
if string(dataJSON) == "null" {
continue
}
realtrades := OKCoinWebsocketFuturesRealtrades{}
err := common.JSONDecode(dataJSON, &realtrades)
realtrades := WebsocketFuturesRealtrades{}
err = common.JSONDecode(dataJSON, &realtrades)
if err != nil {
log.Println(err)
continue
}
case common.StringContains(channelStr, "spot") && common.StringContains(channelStr, "trade") || common.StringContains(channelStr, "futures") && common.StringContains(channelStr, "trade"):
tradeOrder := OKCoinWebsocketTradeOrderResponse{}
err := common.JSONDecode(dataJSON, &tradeOrder)
tradeOrder := WebsocketTradeOrderResponse{}
err = common.JSONDecode(dataJSON, &tradeOrder)
if err != nil {
log.Println(err)
continue
}
case common.StringContains(channelStr, "cancel_order"):
cancelOrder := OKCoinWebsocketTradeOrderResponse{}
err := common.JSONDecode(dataJSON, &cancelOrder)
cancelOrder := WebsocketTradeOrderResponse{}
err = common.JSONDecode(dataJSON, &cancelOrder)
if err != nil {
log.Println(err)
continue
}
case common.StringContains(channelStr, "spot") && common.StringContains(channelStr, "userinfo"):
userinfo := OKCoinWebsocketUserinfo{}
err = common.JSONDecode(dataJSON, &userinfo)
userinfo := WebsocketUserinfo{}
err = common.JSONDecode(dataJSON, &userinfo)
if err != nil {
log.Println(err)
continue
}
case common.StringContains(channelStr, "futureusd_userinfo"):
userinfo := OKCoinWebsocketFuturesUserInfo{}
err = common.JSONDecode(dataJSON, &userinfo)
userinfo := WebsocketFuturesUserInfo{}
err = common.JSONDecode(dataJSON, &userinfo)
if err != nil {
log.Println(err)
continue
}
case common.StringContains(channelStr, "spot") && common.StringContains(channelStr, "order_info"):
type OrderInfoResponse struct {
Result bool `json:"result"`
Orders []OKCoinWebsocketOrder `json:"orders"`
Result bool `json:"result"`
Orders []WebsocketOrder `json:"orders"`
}
var orders OrderInfoResponse
err := common.JSONDecode(dataJSON, &orders)
err = common.JSONDecode(dataJSON, &orders)
if err != nil {
log.Println(err)
continue
}
case common.StringContains(channelStr, "futureusd_order_info"):
type OrderInfoResponse struct {
Result bool `json:"result"`
Orders []OKCoinWebsocketFuturesOrder `json:"orders"`
Result bool `json:"result"`
Orders []WebsocketFuturesOrder `json:"orders"`
}
var orders OrderInfoResponse
err := common.JSONDecode(dataJSON, &orders)
err = common.JSONDecode(dataJSON, &orders)
if err != nil {
log.Println(err)
continue
}
case common.StringContains(channelStr, "future_index"):
index := OKCoinWebsocketFutureIndex{}
err = common.JSONDecode(dataJSON, &index)
index := WebsocketFutureIndex{}
err = common.JSONDecode(dataJSON, &index)
if err != nil {
log.Println(err)
continue
@@ -512,6 +522,7 @@ func (o *OKCoin) WebsocketClient() {
}
}
// SetWebsocketErrorDefaults sets default errors for websocket
func (o *OKCoin) SetWebsocketErrorDefaults() {
o.WebsocketErrors = map[string]string{
"10001": "Illegal parameters",

View File

@@ -1,6 +1,7 @@
package okcoin
import (
"errors"
"log"
"github.com/thrasher-/gocryptotrader/common"
@@ -33,7 +34,7 @@ func (o *OKCoin) UpdateTicker(p pair.CurrencyPair, assetType string) (ticker.Pri
currency := exchange.FormatExchangeCurrency(o.Name, p).String()
var tickerPrice ticker.Price
if assetType != ticker.Spot && o.APIUrl == OKCOIN_API_URL {
if assetType != ticker.Spot && o.APIUrl == okcoinAPIURL {
tick, err := o.GetFuturesTicker(currency, assetType)
if err != nil {
return tickerPrice, err
@@ -140,3 +141,10 @@ func (o *OKCoin) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
return response, nil
}
// GetExchangeHistory returns historic trade data since exchange opening.
func (o *OKCoin) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
var resp []exchange.TradeHistory
return resp, errors.New("trade history not yet implemented")
}

View File

@@ -146,3 +146,10 @@ func (o *OKEX) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
var response exchange.AccountInfo
return response, errors.New("not implemented")
}
// GetExchangeHistory returns historic trade data since exchange opening.
func (o *OKEX) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
var resp []exchange.TradeHistory
return resp, errors.New("trade history not yet implemented")
}

View File

@@ -99,9 +99,9 @@ func (p *Poloniex) GetFee() float64 {
}
// GetTicker returns current ticker information
func (p *Poloniex) GetTicker() (map[string]PoloniexTicker, error) {
func (p *Poloniex) GetTicker() (map[string]Ticker, error) {
type response struct {
Data map[string]PoloniexTicker
Data map[string]Ticker
}
resp := response{}
@@ -119,17 +119,17 @@ func (p *Poloniex) GetVolume() (interface{}, error) {
}
// GetOrderbook returns the full orderbook from poloniex
func (p *Poloniex) GetOrderbook(currencyPair string, depth int) (PoloniexOrderbookAll, error) {
func (p *Poloniex) GetOrderbook(currencyPair string, depth int) (OrderbookAll, error) {
vals := url.Values{}
if depth != 0 {
vals.Set("depth", strconv.Itoa(depth))
}
oba := PoloniexOrderbookAll{Data: make(map[string]PoloniexOrderbook)}
oba := OrderbookAll{Data: make(map[string]Orderbook)}
if currencyPair != "" {
vals.Set("currencyPair", currencyPair)
resp := PoloniexOrderbookResponse{}
resp := OrderbookResponse{}
path := fmt.Sprintf("%s/public?command=returnOrderBook&%s", poloniexAPIURL, vals.Encode())
err := common.SendHTTPGetRequest(path, true, p.Verbose, &resp)
if err != nil {
@@ -139,7 +139,7 @@ func (p *Poloniex) GetOrderbook(currencyPair string, depth int) (PoloniexOrderbo
log.Println(resp.Error)
return oba, fmt.Errorf("Poloniex GetOrderbook() error: %s", resp.Error)
}
ob := PoloniexOrderbook{}
ob := Orderbook{}
for x := range resp.Asks {
data := resp.Asks[x]
price, err := strconv.ParseFloat(data[0].(string), 64)
@@ -147,7 +147,7 @@ func (p *Poloniex) GetOrderbook(currencyPair string, depth int) (PoloniexOrderbo
return oba, err
}
amount := data[1].(float64)
ob.Asks = append(ob.Asks, PoloniexOrderbookItem{Price: price, Amount: amount})
ob.Asks = append(ob.Asks, OrderbookItem{Price: price, Amount: amount})
}
for x := range resp.Bids {
@@ -157,19 +157,19 @@ func (p *Poloniex) GetOrderbook(currencyPair string, depth int) (PoloniexOrderbo
return oba, err
}
amount := data[1].(float64)
ob.Bids = append(ob.Bids, PoloniexOrderbookItem{Price: price, Amount: amount})
ob.Bids = append(ob.Bids, OrderbookItem{Price: price, Amount: amount})
}
oba.Data[currencyPair] = PoloniexOrderbook{Bids: ob.Bids, Asks: ob.Asks}
oba.Data[currencyPair] = Orderbook{Bids: ob.Bids, Asks: ob.Asks}
} else {
vals.Set("currencyPair", "all")
resp := PoloniexOrderbookResponseAll{}
resp := OrderbookResponseAll{}
path := fmt.Sprintf("%s/public?command=returnOrderBook&%s", poloniexAPIURL, vals.Encode())
err := common.SendHTTPGetRequest(path, true, p.Verbose, &resp.Data)
if err != nil {
return oba, err
}
for currency, orderbook := range resp.Data {
ob := PoloniexOrderbook{}
ob := Orderbook{}
for x := range orderbook.Asks {
data := orderbook.Asks[x]
price, err := strconv.ParseFloat(data[0].(string), 64)
@@ -177,7 +177,7 @@ func (p *Poloniex) GetOrderbook(currencyPair string, depth int) (PoloniexOrderbo
return oba, err
}
amount := data[1].(float64)
ob.Asks = append(ob.Asks, PoloniexOrderbookItem{Price: price, Amount: amount})
ob.Asks = append(ob.Asks, OrderbookItem{Price: price, Amount: amount})
}
for x := range orderbook.Bids {
@@ -187,16 +187,16 @@ func (p *Poloniex) GetOrderbook(currencyPair string, depth int) (PoloniexOrderbo
return oba, err
}
amount := data[1].(float64)
ob.Bids = append(ob.Bids, PoloniexOrderbookItem{Price: price, Amount: amount})
ob.Bids = append(ob.Bids, OrderbookItem{Price: price, Amount: amount})
}
oba.Data[currency] = PoloniexOrderbook{Bids: ob.Bids, Asks: ob.Asks}
oba.Data[currency] = Orderbook{Bids: ob.Bids, Asks: ob.Asks}
}
}
return oba, nil
}
// GetTradeHistory returns trades history from poloniex
func (p *Poloniex) GetTradeHistory(currencyPair, start, end string) ([]PoloniexTradeHistory, error) {
func (p *Poloniex) GetTradeHistory(currencyPair, start, end string) ([]TradeHistory, error) {
vals := url.Values{}
vals.Set("currencyPair", currencyPair)
@@ -208,14 +208,14 @@ func (p *Poloniex) GetTradeHistory(currencyPair, start, end string) ([]PoloniexT
vals.Set("end", end)
}
resp := []PoloniexTradeHistory{}
resp := []TradeHistory{}
path := fmt.Sprintf("%s/public?command=returnTradeHistory&%s", poloniexAPIURL, vals.Encode())
return resp, common.SendHTTPGetRequest(path, true, p.Verbose, &resp)
}
// GetChartData returns chart data for a specific currency pair
func (p *Poloniex) GetChartData(currencyPair, start, end, period string) ([]PoloniexChartData, error) {
func (p *Poloniex) GetChartData(currencyPair, start, end, period string) ([]ChartData, error) {
vals := url.Values{}
vals.Set("currencyPair", currencyPair)
@@ -231,7 +231,7 @@ func (p *Poloniex) GetChartData(currencyPair, start, end, period string) ([]Polo
vals.Set("period", period)
}
resp := []PoloniexChartData{}
resp := []ChartData{}
path := fmt.Sprintf("%s/public?command=returnChartData&%s", poloniexAPIURL, vals.Encode())
err := common.SendHTTPGetRequest(path, true, p.Verbose, &resp)
@@ -243,9 +243,9 @@ func (p *Poloniex) GetChartData(currencyPair, start, end, period string) ([]Polo
}
// GetCurrencies returns information about currencies
func (p *Poloniex) GetCurrencies() (map[string]PoloniexCurrencies, error) {
func (p *Poloniex) GetCurrencies() (map[string]Currencies, error) {
type Response struct {
Data map[string]PoloniexCurrencies
Data map[string]Currencies
}
resp := Response{}
path := fmt.Sprintf("%s/public?command=returnCurrencies", poloniexAPIURL)
@@ -271,23 +271,24 @@ func (p *Poloniex) GetExchangeCurrencies() ([]string, error) {
// GetLoanOrders returns the list of loan offers and demands for a given
// currency, specified by the "currency" GET parameter.
func (p *Poloniex) GetLoanOrders(currency string) (PoloniexLoanOrders, error) {
resp := PoloniexLoanOrders{}
func (p *Poloniex) GetLoanOrders(currency string) (LoanOrders, error) {
resp := LoanOrders{}
path := fmt.Sprintf("%s/public?command=returnLoanOrders&currency=%s", poloniexAPIURL, currency)
return resp, common.SendHTTPGetRequest(path, true, p.Verbose, &resp)
}
func (p *Poloniex) GetBalances() (PoloniexBalance, error) {
// GetBalances returns balances for your account.
func (p *Poloniex) GetBalances() (Balance, error) {
var result interface{}
err := p.SendAuthenticatedHTTPRequest("POST", poloniexBalances, url.Values{}, &result)
if err != nil {
return PoloniexBalance{}, err
return Balance{}, err
}
data := result.(map[string]interface{})
balance := PoloniexBalance{}
balance := Balance{}
balance.Currency = make(map[string]float64)
for x, y := range data {
@@ -297,25 +298,22 @@ func (p *Poloniex) GetBalances() (PoloniexBalance, error) {
return balance, nil
}
type PoloniexCompleteBalances struct {
Currency map[string]PoloniexCompleteBalance
}
func (p *Poloniex) GetCompleteBalances() (PoloniexCompleteBalances, error) {
// GetCompleteBalances returns complete balances from your account.
func (p *Poloniex) GetCompleteBalances() (CompleteBalances, error) {
var result interface{}
err := p.SendAuthenticatedHTTPRequest("POST", poloniexBalancesComplete, url.Values{}, &result)
if err != nil {
return PoloniexCompleteBalances{}, err
return CompleteBalances{}, err
}
data := result.(map[string]interface{})
balance := PoloniexCompleteBalances{}
balance.Currency = make(map[string]PoloniexCompleteBalance)
balance := CompleteBalances{}
balance.Currency = make(map[string]CompleteBalance)
for x, y := range data {
dataVals := y.(map[string]interface{})
balancesData := PoloniexCompleteBalance{}
balancesData := CompleteBalance{}
balancesData.Available, _ = strconv.ParseFloat(dataVals["available"].(string), 64)
balancesData.OnOrders, _ = strconv.ParseFloat(dataVals["onOrders"].(string), 64)
balancesData.BTCValue, _ = strconv.ParseFloat(dataVals["btcValue"].(string), 64)
@@ -325,9 +323,10 @@ func (p *Poloniex) GetCompleteBalances() (PoloniexCompleteBalances, error) {
return balance, nil
}
func (p *Poloniex) GetDepositAddresses() (PoloniexDepositAddresses, error) {
// GetDepositAddresses returns deposit addresses for all enabled cryptos.
func (p *Poloniex) GetDepositAddresses() (DepositAddresses, error) {
var result interface{}
addresses := PoloniexDepositAddresses{}
addresses := DepositAddresses{}
err := p.SendAuthenticatedHTTPRequest("POST", poloniexDepositAddresses, url.Values{}, &result)
if err != nil {
@@ -343,6 +342,7 @@ func (p *Poloniex) GetDepositAddresses() (PoloniexDepositAddresses, error) {
return addresses, nil
}
// GenerateNewAddress generates a new address for a currency
func (p *Poloniex) GenerateNewAddress(currency string) (string, error) {
type Response struct {
Success int
@@ -366,8 +366,9 @@ func (p *Poloniex) GenerateNewAddress(currency string) (string, error) {
return resp.Response, nil
}
func (p *Poloniex) GetDepositsWithdrawals(start, end string) (PoloniexDepositsWithdrawals, error) {
resp := PoloniexDepositsWithdrawals{}
// GetDepositsWithdrawals returns a list of deposits and withdrawals
func (p *Poloniex) GetDepositsWithdrawals(start, end string) (DepositsWithdrawals, error) {
resp := DepositsWithdrawals{}
values := url.Values{}
if start != "" {
@@ -391,32 +392,33 @@ func (p *Poloniex) GetDepositsWithdrawals(start, end string) (PoloniexDepositsWi
return resp, nil
}
// GetOpenOrders returns current unfilled opened orders
func (p *Poloniex) GetOpenOrders(currency string) (interface{}, error) {
values := url.Values{}
if currency != "" {
values.Set("currencyPair", currency)
result := PoloniexOpenOrdersResponse{}
result := OpenOrdersResponse{}
err := p.SendAuthenticatedHTTPRequest("POST", poloniexOrders, values, &result.Data)
if err != nil {
return result, err
}
return result, nil
} else {
values.Set("currencyPair", "all")
result := PoloniexOpenOrdersResponseAll{}
err := p.SendAuthenticatedHTTPRequest("POST", poloniexOrders, values, &result.Data)
if err != nil {
return result, err
}
return result, nil
}
values.Set("currencyPair", "all")
result := OpenOrdersResponseAll{}
err := p.SendAuthenticatedHTTPRequest("POST", poloniexOrders, values, &result.Data)
if err != nil {
return result, err
}
return result, nil
}
// GetAuthenticatedTradeHistory returns account trade history
func (p *Poloniex) GetAuthenticatedTradeHistory(currency, start, end, limit string) (interface{}, error) {
values := url.Values{}
@@ -434,29 +436,29 @@ func (p *Poloniex) GetAuthenticatedTradeHistory(currency, start, end, limit stri
if currency != "" && currency != "all" {
values.Set("currencyPair", currency)
result := PoloniexAuthenticatedTradeHistoryResponse{}
result := AuthenticatedTradeHistoryResponse{}
err := p.SendAuthenticatedHTTPRequest("POST", poloniexTradeHistory, values, &result.Data)
if err != nil {
return result, err
}
return result, nil
} else {
values.Set("currencyPair", "all")
result := PoloniexAuthenticatedTradeHistoryAll{}
err := p.SendAuthenticatedHTTPRequest("POST", poloniexTradeHistory, values, &result.Data)
if err != nil {
return result, err
}
return result, nil
}
values.Set("currencyPair", "all")
result := AuthenticatedTradeHistoryAll{}
err := p.SendAuthenticatedHTTPRequest("POST", poloniexTradeHistory, values, &result.Data)
if err != nil {
return result, err
}
return result, nil
}
func (p *Poloniex) PlaceOrder(currency string, rate, amount float64, immediate, fillOrKill, buy bool) (PoloniexOrderResponse, error) {
result := PoloniexOrderResponse{}
// PlaceOrder places a new order on the exchange
func (p *Poloniex) PlaceOrder(currency string, rate, amount float64, immediate, fillOrKill, buy bool) (OrderResponse, error) {
result := OrderResponse{}
values := url.Values{}
var orderType string
@@ -487,8 +489,9 @@ func (p *Poloniex) PlaceOrder(currency string, rate, amount float64, immediate,
return result, nil
}
// CancelOrder cancels and order by orderID
func (p *Poloniex) CancelOrder(orderID int64) (bool, error) {
result := PoloniexGenericResponse{}
result := GenericResponse{}
values := url.Values{}
values.Set("orderNumber", strconv.FormatInt(orderID, 10))
@@ -505,8 +508,9 @@ func (p *Poloniex) CancelOrder(orderID int64) (bool, error) {
return true, nil
}
func (p *Poloniex) MoveOrder(orderID int64, rate, amount float64) (PoloniexMoveOrderResponse, error) {
result := PoloniexMoveOrderResponse{}
// MoveOrder moves an order
func (p *Poloniex) MoveOrder(orderID int64, rate, amount float64) (MoveOrderResponse, error) {
result := MoveOrderResponse{}
values := url.Values{}
values.Set("orderNumber", strconv.FormatInt(orderID, 10))
values.Set("rate", strconv.FormatFloat(rate, 'f', -1, 64))
@@ -528,8 +532,9 @@ func (p *Poloniex) MoveOrder(orderID int64, rate, amount float64) (PoloniexMoveO
return result, nil
}
// Withdraw withdraws a currency to a specific delegated address
func (p *Poloniex) Withdraw(currency, address string, amount float64) (bool, error) {
result := PoloniexWithdraw{}
result := Withdraw{}
values := url.Values{}
values.Set("currency", currency)
@@ -549,17 +554,14 @@ func (p *Poloniex) Withdraw(currency, address string, amount float64) (bool, err
return true, nil
}
func (p *Poloniex) GetFeeInfo() (PoloniexFee, error) {
result := PoloniexFee{}
err := p.SendAuthenticatedHTTPRequest("POST", poloniexFeeInfo, url.Values{}, &result)
// GetFeeInfo returns fee information
func (p *Poloniex) GetFeeInfo() (Fee, error) {
result := Fee{}
if err != nil {
return result, err
}
return result, nil
return result, p.SendAuthenticatedHTTPRequest("POST", poloniexFeeInfo, url.Values{}, &result)
}
// GetTradableBalances returns tradable balances
func (p *Poloniex) GetTradableBalances() (map[string]map[string]float64, error) {
type Response struct {
Data map[string]map[string]interface{}
@@ -584,9 +586,10 @@ func (p *Poloniex) GetTradableBalances() (map[string]map[string]float64, error)
return balances, nil
}
// TransferBalance transfers balances between your accounts
func (p *Poloniex) TransferBalance(currency, from, to string, amount float64) (bool, error) {
values := url.Values{}
result := PoloniexGenericResponse{}
result := GenericResponse{}
values.Set("currency", currency)
values.Set("amount", strconv.FormatFloat(amount, 'f', -1, 64))
@@ -606,8 +609,9 @@ func (p *Poloniex) TransferBalance(currency, from, to string, amount float64) (b
return true, nil
}
func (p *Poloniex) GetMarginAccountSummary() (PoloniexMargin, error) {
result := PoloniexMargin{}
// GetMarginAccountSummary returns a summary on your margin accounts
func (p *Poloniex) GetMarginAccountSummary() (Margin, error) {
result := Margin{}
err := p.SendAuthenticatedHTTPRequest("POST", poloniexMarginAccountSummary, url.Values{}, &result)
if err != nil {
@@ -617,8 +621,9 @@ func (p *Poloniex) GetMarginAccountSummary() (PoloniexMargin, error) {
return result, nil
}
func (p *Poloniex) PlaceMarginOrder(currency string, rate, amount, lendingRate float64, buy bool) (PoloniexOrderResponse, error) {
result := PoloniexOrderResponse{}
// PlaceMarginOrder places a margin order
func (p *Poloniex) PlaceMarginOrder(currency string, rate, amount, lendingRate float64, buy bool) (OrderResponse, error) {
result := OrderResponse{}
values := url.Values{}
var orderType string
@@ -645,41 +650,41 @@ func (p *Poloniex) PlaceMarginOrder(currency string, rate, amount, lendingRate f
return result, nil
}
// GetMarginPosition returns a position on a margin order
func (p *Poloniex) GetMarginPosition(currency string) (interface{}, error) {
values := url.Values{}
if currency != "" && currency != "all" {
values.Set("currencyPair", currency)
result := PoloniexMarginPosition{}
result := MarginPosition{}
err := p.SendAuthenticatedHTTPRequest("POST", poloniexMarginPosition, values, &result)
if err != nil {
return result, err
}
return result, nil
} else {
values.Set("currencyPair", "all")
type Response struct {
Data map[string]PoloniexMarginPosition
}
result := Response{}
err := p.SendAuthenticatedHTTPRequest("POST", poloniexMarginPosition, values, &result.Data)
if err != nil {
return result, err
}
return result, nil
}
values.Set("currencyPair", "all")
type Response struct {
Data map[string]MarginPosition
}
result := Response{}
err := p.SendAuthenticatedHTTPRequest("POST", poloniexMarginPosition, values, &result.Data)
if err != nil {
return result, err
}
return result, nil
}
// CloseMarginPosition closes a current margin position
func (p *Poloniex) CloseMarginPosition(currency string) (bool, error) {
values := url.Values{}
values.Set("currencyPair", currency)
result := PoloniexGenericResponse{}
result := GenericResponse{}
err := p.SendAuthenticatedHTTPRequest("POST", poloniexMarginPositionClose, values, &result)
@@ -694,6 +699,7 @@ func (p *Poloniex) CloseMarginPosition(currency string) (bool, error) {
return true, nil
}
// CreateLoanOffer places a loan offer on the exchange
func (p *Poloniex) CreateLoanOffer(currency string, amount, rate float64, duration int, autoRenew bool) (int64, error) {
values := url.Values{}
values.Set("currency", currency)
@@ -729,8 +735,9 @@ func (p *Poloniex) CreateLoanOffer(currency string, amount, rate float64, durati
return result.OrderID, nil
}
// CancelLoanOffer cancels a loan offer order
func (p *Poloniex) CancelLoanOffer(orderNumber int64) (bool, error) {
result := PoloniexGenericResponse{}
result := GenericResponse{}
values := url.Values{}
values.Set("orderID", strconv.FormatInt(orderNumber, 10))
@@ -747,9 +754,10 @@ func (p *Poloniex) CancelLoanOffer(orderNumber int64) (bool, error) {
return true, nil
}
func (p *Poloniex) GetOpenLoanOffers() (map[string][]PoloniexLoanOffer, error) {
// GetOpenLoanOffers returns all open loan offers
func (p *Poloniex) GetOpenLoanOffers() (map[string][]LoanOffer, error) {
type Response struct {
Data map[string][]PoloniexLoanOffer
Data map[string][]LoanOffer
}
result := Response{}
@@ -760,14 +768,15 @@ func (p *Poloniex) GetOpenLoanOffers() (map[string][]PoloniexLoanOffer, error) {
}
if result.Data == nil {
return nil, errors.New("There are no open loan offers.")
return nil, errors.New("there are no open loan offers")
}
return result.Data, nil
}
func (p *Poloniex) GetActiveLoans() (PoloniexActiveLoans, error) {
result := PoloniexActiveLoans{}
// GetActiveLoans returns active loans
func (p *Poloniex) GetActiveLoans() (ActiveLoans, error) {
result := ActiveLoans{}
err := p.SendAuthenticatedHTTPRequest("POST", poloniexActiveLoans, url.Values{}, &result)
if err != nil {
@@ -777,7 +786,8 @@ func (p *Poloniex) GetActiveLoans() (PoloniexActiveLoans, error) {
return result, nil
}
func (p *Poloniex) GetLendingHistory(start, end string) ([]PoloniexLendingHistory, error) {
// GetLendingHistory returns lending history for the account
func (p *Poloniex) GetLendingHistory(start, end string) ([]LendingHistory, error) {
vals := url.Values{}
if start != "" {
@@ -788,7 +798,7 @@ func (p *Poloniex) GetLendingHistory(start, end string) ([]PoloniexLendingHistor
vals.Set("end", end)
}
resp := []PoloniexLendingHistory{}
resp := []LendingHistory{}
err := p.SendAuthenticatedHTTPRequest("POST", poloniexLendingHistory, vals, &resp)
if err != nil {
@@ -797,10 +807,11 @@ func (p *Poloniex) GetLendingHistory(start, end string) ([]PoloniexLendingHistor
return resp, nil
}
// ToggleAutoRenew allows for the autorenew of a contract
func (p *Poloniex) ToggleAutoRenew(orderNumber int64) (bool, error) {
values := url.Values{}
values.Set("orderNumber", strconv.FormatInt(orderNumber, 10))
result := PoloniexGenericResponse{}
result := GenericResponse{}
err := p.SendAuthenticatedHTTPRequest("POST", poloniexAutoRenew, values, &result)
@@ -815,6 +826,7 @@ func (p *Poloniex) ToggleAutoRenew(orderNumber int64) (bool, error) {
return true, nil
}
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request
func (p *Poloniex) SendAuthenticatedHTTPRequest(method, endpoint string, values url.Values, result interface{}) error {
if !p.AuthenticatedAPISupport {
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, p.Name)
@@ -835,16 +847,11 @@ func (p *Poloniex) SendAuthenticatedHTTPRequest(method, endpoint string, values
headers["Sign"] = common.HexEncodeToString(hmac)
path := fmt.Sprintf("%s/%s", poloniexAPIURL, poloniexAPITradingEndpoint)
resp, err := common.SendHTTPRequest(method, path, headers, bytes.NewBufferString(values.Encode()))
resp, err := common.SendHTTPRequest(method, path, headers, bytes.NewBufferString(values.Encode()))
if err != nil {
return err
}
err = common.JSONDecode([]byte(resp), &result)
if err != nil {
return errors.New("Unable to JSON Unmarshal response.")
}
return nil
return common.JSONDecode([]byte(resp), &result)
}

View File

@@ -1,6 +1,7 @@
package poloniex
type PoloniexTicker struct {
// Ticker holds ticker data
type Ticker struct {
Last float64 `json:"last,string"`
LowestAsk float64 `json:"lowestAsk,string"`
HighestBid float64 `json:"highestBid,string"`
@@ -12,32 +13,43 @@ type PoloniexTicker struct {
Low24Hr float64 `json:"low24hr,string"`
}
type PoloniexOrderbookResponseAll struct {
Data map[string]PoloniexOrderbookResponse
// OrderbookResponseAll holds the full response type orderbook
type OrderbookResponseAll struct {
Data map[string]OrderbookResponse
}
type PoloniexOrderbookResponse struct {
// CompleteBalances holds the full balance data
type CompleteBalances struct {
Currency map[string]CompleteBalance
}
// OrderbookResponse is a sub-type for orderbooks
type OrderbookResponse struct {
Asks [][]interface{} `json:"asks"`
Bids [][]interface{} `json:"bids"`
IsFrozen string `json:"isFrozen"`
Error string `json:"error"`
}
type PoloniexOrderbookItem struct {
// OrderbookItem holds data on an individual item
type OrderbookItem struct {
Price float64
Amount float64
}
type PoloniexOrderbookAll struct {
Data map[string]PoloniexOrderbook
// OrderbookAll contains the full range of orderbooks
type OrderbookAll struct {
Data map[string]Orderbook
}
type PoloniexOrderbook struct {
Asks []PoloniexOrderbookItem `json:"asks"`
Bids []PoloniexOrderbookItem `json:"bids"`
// Orderbook is a generic type golding orderbook information
type Orderbook struct {
Asks []OrderbookItem `json:"asks"`
Bids []OrderbookItem `json:"bids"`
}
type PoloniexTradeHistory struct {
// TradeHistory holds trade history data
type TradeHistory struct {
GlobalTradeID int64 `json:"globalTradeID"`
TradeID int64 `json:"tradeID"`
Date string `json:"date"`
@@ -47,7 +59,8 @@ type PoloniexTradeHistory struct {
Total float64 `json:"total,string"`
}
type PoloniexChartData struct {
// ChartData holds kline data
type ChartData struct {
Date int `json:"date"`
High float64 `json:"high"`
Low float64 `json:"low"`
@@ -59,7 +72,8 @@ type PoloniexChartData struct {
Error string `json:"error"`
}
type PoloniexCurrencies struct {
// Currencies contains currency information
type Currencies struct {
Name string `json:"name"`
MaxDailyWithdrawal string `json:"maxDailyWithdrawal"`
TxFee float64 `json:"txFee,string"`
@@ -70,33 +84,39 @@ type PoloniexCurrencies struct {
Frozen int `json:"frozen"`
}
type PoloniexLoanOrder struct {
// LoanOrder holds loan order information
type LoanOrder struct {
Rate float64 `json:"rate,string"`
Amount float64 `json:"amount,string"`
RangeMin int `json:"rangeMin"`
RangeMax int `json:"rangeMax"`
}
type PoloniexLoanOrders struct {
Offers []PoloniexLoanOrder `json:"offers"`
Demands []PoloniexLoanOrder `json:"demands"`
// LoanOrders holds loan order information range
type LoanOrders struct {
Offers []LoanOrder `json:"offers"`
Demands []LoanOrder `json:"demands"`
}
type PoloniexBalance struct {
// Balance holds data for a range of currencies
type Balance struct {
Currency map[string]float64
}
type PoloniexCompleteBalance struct {
// CompleteBalance contains the complete balance with a btcvalue
type CompleteBalance struct {
Available float64
OnOrders float64
BTCValue float64
}
type PoloniexDepositAddresses struct {
// DepositAddresses holds the full address per crypto-currency
type DepositAddresses struct {
Addresses map[string]string
}
type PoloniexDepositsWithdrawals struct {
// DepositsWithdrawals holds withdrawal information
type DepositsWithdrawals struct {
Deposits []struct {
Currency string `json:"currency"`
Address string `json:"address"`
@@ -119,7 +139,8 @@ type PoloniexDepositsWithdrawals struct {
} `json:"withdrawals"`
}
type PoloniexOrder struct {
// Order hold order information
type Order struct {
OrderNumber int64 `json:"orderNumber,string"`
Type string `json:"type"`
Rate float64 `json:"rate,string"`
@@ -129,15 +150,18 @@ type PoloniexOrder struct {
Margin float64 `json:"margin"`
}
type PoloniexOpenOrdersResponseAll struct {
Data map[string][]PoloniexOrder
// OpenOrdersResponseAll holds all open order responses
type OpenOrdersResponseAll struct {
Data map[string][]Order
}
type PoloniexOpenOrdersResponse struct {
Data []PoloniexOrder
// OpenOrdersResponse holds open response orders
type OpenOrdersResponse struct {
Data []Order
}
type PoloniexAuthentictedTradeHistory struct {
// AuthentictedTradeHistory holds client trade history information
type AuthentictedTradeHistory struct {
GlobalTradeID int64 `json:"globalTradeID"`
TradeID int64 `json:"tradeID,string"`
Date string `json:"date"`
@@ -150,15 +174,18 @@ type PoloniexAuthentictedTradeHistory struct {
Category string `json:"category"`
}
type PoloniexAuthenticatedTradeHistoryAll struct {
Data map[string][]PoloniexAuthentictedTradeHistory
// AuthenticatedTradeHistoryAll holds the full client trade history
type AuthenticatedTradeHistoryAll struct {
Data map[string][]AuthentictedTradeHistory
}
type PoloniexAuthenticatedTradeHistoryResponse struct {
Data []PoloniexAuthentictedTradeHistory
// AuthenticatedTradeHistoryResponse is a response type for trade history
type AuthenticatedTradeHistoryResponse struct {
Data []AuthentictedTradeHistory
}
type PoloniexResultingTrades struct {
// ResultingTrades holds resultant trade information
type ResultingTrades struct {
Amount float64 `json:"amount,string"`
Date string `json:"date"`
Rate float64 `json:"rate,string"`
@@ -167,36 +194,42 @@ type PoloniexResultingTrades struct {
Type string `json:"type"`
}
type PoloniexOrderResponse struct {
OrderNumber int64 `json:"orderNumber,string"`
Trades []PoloniexResultingTrades `json:"resultingTrades"`
// OrderResponse is a response type of trades
type OrderResponse struct {
OrderNumber int64 `json:"orderNumber,string"`
Trades []ResultingTrades `json:"resultingTrades"`
}
type PoloniexGenericResponse struct {
// GenericResponse is a response type for exchange generic responses
type GenericResponse struct {
Success int `json:"success"`
Error string `json:"error"`
}
type PoloniexMoveOrderResponse struct {
Success int `json:"success"`
Error string `json:"error"`
OrderNumber int64 `json:"orderNumber,string"`
Trades map[string][]PoloniexResultingTrades `json:"resultingTrades"`
// MoveOrderResponse is a response type for move order trades
type MoveOrderResponse struct {
Success int `json:"success"`
Error string `json:"error"`
OrderNumber int64 `json:"orderNumber,string"`
Trades map[string][]ResultingTrades `json:"resultingTrades"`
}
type PoloniexWithdraw struct {
// Withdraw holds withdraw information
type Withdraw struct {
Response string `json:"response"`
Error string `json:"error"`
}
type PoloniexFee struct {
// Fee holds fees for specific trades
type Fee struct {
MakerFee float64 `json:"makerFee,string"`
TakerFee float64 `json:"takerFee,string"`
ThirtyDayVolume float64 `json:"thirtyDayVolume,string"`
NextTier float64 `json:"nextTier,string"`
}
type PoloniexMargin struct {
// Margin holds margin information
type Margin struct {
TotalValue float64 `json:"totalValue,string"`
ProfitLoss float64 `json:"pl,string"`
LendingFees float64 `json:"lendingFees,string"`
@@ -205,7 +238,8 @@ type PoloniexMargin struct {
CurrentMargin float64 `json:"currentMargin,string"`
}
type PoloniexMarginPosition struct {
// MarginPosition holds margin positional information
type MarginPosition struct {
Amount float64 `json:"amount,string"`
Total float64 `json:"total,string"`
BasePrice float64 `json:"basePrice,string"`
@@ -215,7 +249,8 @@ type PoloniexMarginPosition struct {
Type string `json:"type"`
}
type PoloniexLoanOffer struct {
// LoanOffer holds loan offer information
type LoanOffer struct {
ID int64 `json:"id"`
Rate float64 `json:"rate,string"`
Amount float64 `json:"amount,string"`
@@ -224,12 +259,14 @@ type PoloniexLoanOffer struct {
Date string `json:"date"`
}
type PoloniexActiveLoans struct {
Provided []PoloniexLoanOffer `json:"provided"`
Used []PoloniexLoanOffer `json:"used"`
// ActiveLoans shows the full active loans on the exchange
type ActiveLoans struct {
Provided []LoanOffer `json:"provided"`
Used []LoanOffer `json:"used"`
}
type PoloniexLendingHistory struct {
// LendingHistory holds the full lending history data
type LendingHistory struct {
ID int64 `json:"id"`
Currency string `json:"currency"`
Rate float64 `json:"rate,string"`
@@ -241,3 +278,26 @@ type PoloniexLendingHistory struct {
Open string `json:"open"`
Close string `json:"close"`
}
// WebsocketTicker holds ticker data for the websocket
type WebsocketTicker struct {
CurrencyPair string
Last float64
LowestAsk float64
HighestBid float64
PercentChange float64
BaseVolume float64
QuoteVolume float64
IsFrozen bool
High float64
Low float64
}
// WebsocketTrollboxMessage holds trollbox messages and information for
// websocket
type WebsocketTrollboxMessage struct {
MessageNumber float64
Username string
Message string
Reputation float64
}

View File

@@ -8,27 +8,15 @@ import (
)
const (
POLONIEX_WEBSOCKET_ADDRESS = "wss://api.poloniex.com"
POLONIEX_WEBSOCKET_REALM = "realm1"
POLONIEX_WEBSOCKET_TICKER = "ticker"
POLONIEX_WEBSOCKET_TROLLBOX = "trollbox"
poloniexWebsocketAddress = "wss://api.poloniex.com"
poloniexWebsocketRealm = "realm1"
poloniexWebsocketTicker = "ticker"
poloniexWebsocketTrollbox = "trollbox"
)
type PoloniexWebsocketTicker struct {
CurrencyPair string
Last float64
LowestAsk float64
HighestBid float64
PercentChange float64
BaseVolume float64
QuoteVolume float64
IsFrozen bool
High float64
Low float64
}
func PoloniexOnTicker(args []interface{}, kwargs map[string]interface{}) {
ticker := PoloniexWebsocketTicker{}
// OnTicker converts ticker data to a websocketTicker
func OnTicker(args []interface{}, kwargs map[string]interface{}) {
ticker := WebsocketTicker{}
ticker.CurrencyPair = args[0].(string)
ticker.Last, _ = strconv.ParseFloat(args[1].(string), 64)
ticker.LowestAsk, _ = strconv.ParseFloat(args[2].(string), 64)
@@ -47,15 +35,9 @@ func PoloniexOnTicker(args []interface{}, kwargs map[string]interface{}) {
ticker.Low, _ = strconv.ParseFloat(args[9].(string), 64)
}
type PoloniexWebsocketTrollboxMessage struct {
MessageNumber float64
Username string
Message string
Reputation float64
}
func PoloniexOnTrollbox(args []interface{}, kwargs map[string]interface{}) {
message := PoloniexWebsocketTrollboxMessage{}
// OnTrollbox handles trollbox messages
func OnTrollbox(args []interface{}, kwargs map[string]interface{}) {
message := WebsocketTrollboxMessage{}
message.MessageNumber, _ = args[1].(float64)
message.Username = args[2].(string)
message.Message = args[3].(string)
@@ -64,7 +46,8 @@ func PoloniexOnTrollbox(args []interface{}, kwargs map[string]interface{}) {
}
}
func PoloniexOnDepthOrTrade(args []interface{}, kwargs map[string]interface{}) {
// OnDepthOrTrade handles orderbook depth and trade events
func OnDepthOrTrade(args []interface{}, kwargs map[string]interface{}) {
for x := range args {
data := args[x].(map[string]interface{})
msgData := data["data"].(map[string]interface{})
@@ -133,9 +116,10 @@ func PoloniexOnDepthOrTrade(args []interface{}, kwargs map[string]interface{}) {
}
}
// WebsocketClient creates a new websocket client
func (p *Poloniex) WebsocketClient() {
for p.Enabled && p.Websocket {
c, err := turnpike.NewWebsocketClient(turnpike.JSON, POLONIEX_WEBSOCKET_ADDRESS, nil)
c, err := turnpike.NewWebsocketClient(turnpike.JSON, poloniexWebsocketAddress, nil)
if err != nil {
log.Printf("%s Unable to connect to Websocket. Error: %s\n", p.GetName(), err)
continue
@@ -145,7 +129,7 @@ func (p *Poloniex) WebsocketClient() {
log.Printf("%s Connected to Websocket.\n", p.GetName())
}
_, err = c.JoinRealm(POLONIEX_WEBSOCKET_REALM, nil)
_, err = c.JoinRealm(poloniexWebsocketRealm, nil)
if err != nil {
log.Printf("%s Unable to join realm. Error: %s\n", p.GetName(), err)
continue
@@ -157,17 +141,17 @@ func (p *Poloniex) WebsocketClient() {
c.ReceiveDone = make(chan bool)
if err := c.Subscribe(POLONIEX_WEBSOCKET_TICKER, PoloniexOnTicker); err != nil {
if err := c.Subscribe(poloniexWebsocketTicker, OnTicker); err != nil {
log.Printf("%s Error subscribing to ticker channel: %s\n", p.GetName(), err)
}
if err := c.Subscribe(POLONIEX_WEBSOCKET_TROLLBOX, PoloniexOnTrollbox); err != nil {
if err := c.Subscribe(poloniexWebsocketTrollbox, OnTrollbox); err != nil {
log.Printf("%s Error subscribing to trollbox channel: %s\n", p.GetName(), err)
}
for x := range p.EnabledPairs {
currency := p.EnabledPairs[x]
if err := c.Subscribe(currency, PoloniexOnDepthOrTrade); err != nil {
if err := c.Subscribe(currency, OnDepthOrTrade); err != nil {
log.Printf("%s Error subscribing to %s channel: %s\n", p.GetName(), currency, err)
}
}

View File

@@ -1,6 +1,7 @@
package poloniex
import (
"errors"
"log"
"github.com/thrasher-/gocryptotrader/common"
@@ -11,50 +12,50 @@ import (
)
// Start starts the Poloniex go routine
func (p *Poloniex) Start() {
go p.Run()
func (po *Poloniex) Start() {
go po.Run()
}
// Run implements the Poloniex wrapper
func (p *Poloniex) Run() {
if p.Verbose {
log.Printf("%s Websocket: %s (url: %s).\n", p.GetName(), common.IsEnabled(p.Websocket), POLONIEX_WEBSOCKET_ADDRESS)
log.Printf("%s polling delay: %ds.\n", p.GetName(), p.RESTPollingDelay)
log.Printf("%s %d currencies enabled: %s.\n", p.GetName(), len(p.EnabledPairs), p.EnabledPairs)
func (po *Poloniex) Run() {
if po.Verbose {
log.Printf("%s Websocket: %s (url: %s).\n", po.GetName(), common.IsEnabled(po.Websocket), poloniexWebsocketAddress)
log.Printf("%s polling delay: %ds.\n", po.GetName(), po.RESTPollingDelay)
log.Printf("%s %d currencies enabled: %s.\n", po.GetName(), len(po.EnabledPairs), po.EnabledPairs)
}
if p.Websocket {
go p.WebsocketClient()
if po.Websocket {
go po.WebsocketClient()
}
exchangeCurrencies, err := p.GetExchangeCurrencies()
exchangeCurrencies, err := po.GetExchangeCurrencies()
if err != nil {
log.Printf("%s Failed to get available symbols.\n", p.GetName())
log.Printf("%s Failed to get available symbols.\n", po.GetName())
} else {
forceUpdate := false
if common.StringDataCompare(p.AvailablePairs, "BTC_USDT") {
if common.StringDataCompare(po.AvailablePairs, "BTC_USDT") {
log.Printf("%s contains invalid pair, forcing upgrade of available currencies.\n",
p.GetName())
po.GetName())
forceUpdate = true
}
err = p.UpdateAvailableCurrencies(exchangeCurrencies, forceUpdate)
err = po.UpdateAvailableCurrencies(exchangeCurrencies, forceUpdate)
if err != nil {
log.Printf("%s Failed to update available currencies %s.\n", p.GetName(), err)
log.Printf("%s Failed to update available currencies %s.\n", po.GetName(), err)
}
}
}
// UpdateTicker updates and returns the ticker for a currency pair
func (p *Poloniex) UpdateTicker(currencyPair pair.CurrencyPair, assetType string) (ticker.Price, error) {
func (po *Poloniex) UpdateTicker(currencyPair pair.CurrencyPair, assetType string) (ticker.Price, error) {
var tickerPrice ticker.Price
tick, err := p.GetTicker()
tick, err := po.GetTicker()
if err != nil {
return tickerPrice, err
}
for _, x := range p.GetEnabledCurrencies() {
for _, x := range po.GetEnabledCurrencies() {
var tp ticker.Price
curr := exchange.FormatExchangeCurrency(p.GetName(), x).String()
curr := exchange.FormatExchangeCurrency(po.GetName(), x).String()
tp.Pair = x
tp.Ask = tick[curr].LowestAsk
tp.Bid = tick[curr].HighestBid
@@ -62,39 +63,39 @@ func (p *Poloniex) UpdateTicker(currencyPair pair.CurrencyPair, assetType string
tp.Last = tick[curr].Last
tp.Low = tick[curr].Low24Hr
tp.Volume = tick[curr].BaseVolume
ticker.ProcessTicker(p.GetName(), x, tp, assetType)
ticker.ProcessTicker(po.GetName(), x, tp, assetType)
}
return ticker.GetTicker(p.Name, currencyPair, assetType)
return ticker.GetTicker(po.Name, currencyPair, assetType)
}
// GetTickerPrice returns the ticker for a currency pair
func (p *Poloniex) GetTickerPrice(currencyPair pair.CurrencyPair, assetType string) (ticker.Price, error) {
tickerNew, err := ticker.GetTicker(p.GetName(), currencyPair, assetType)
func (po *Poloniex) GetTickerPrice(currencyPair pair.CurrencyPair, assetType string) (ticker.Price, error) {
tickerNew, err := ticker.GetTicker(po.GetName(), currencyPair, assetType)
if err != nil {
return p.UpdateTicker(currencyPair, assetType)
return po.UpdateTicker(currencyPair, assetType)
}
return tickerNew, nil
}
// GetOrderbookEx returns orderbook base on the currency pair
func (p *Poloniex) GetOrderbookEx(currencyPair pair.CurrencyPair, assetType string) (orderbook.Base, error) {
ob, err := orderbook.GetOrderbook(p.GetName(), currencyPair, assetType)
func (po *Poloniex) GetOrderbookEx(currencyPair pair.CurrencyPair, assetType string) (orderbook.Base, error) {
ob, err := orderbook.GetOrderbook(po.GetName(), currencyPair, assetType)
if err != nil {
return p.UpdateOrderbook(currencyPair, assetType)
return po.UpdateOrderbook(currencyPair, assetType)
}
return ob, nil
}
// UpdateOrderbook updates and returns the orderbook for a currency pair
func (p *Poloniex) UpdateOrderbook(currencyPair pair.CurrencyPair, assetType string) (orderbook.Base, error) {
func (po *Poloniex) UpdateOrderbook(currencyPair pair.CurrencyPair, assetType string) (orderbook.Base, error) {
var orderBook orderbook.Base
orderbookNew, err := p.GetOrderbook("", 1000)
orderbookNew, err := po.GetOrderbook("", 1000)
if err != nil {
return orderBook, err
}
for _, x := range p.GetEnabledCurrencies() {
currency := exchange.FormatExchangeCurrency(p.Name, x).String()
for _, x := range po.GetEnabledCurrencies() {
currency := exchange.FormatExchangeCurrency(po.Name, x).String()
data, ok := orderbookNew.Data[currency]
if !ok {
continue
@@ -114,17 +115,17 @@ func (p *Poloniex) UpdateOrderbook(currencyPair pair.CurrencyPair, assetType str
obItems = append(obItems, orderbook.Item{Amount: obData.Amount, Price: obData.Price})
}
orderBook.Asks = obItems
orderbook.ProcessOrderbook(p.Name, x, orderBook, assetType)
orderbook.ProcessOrderbook(po.Name, x, orderBook, assetType)
}
return orderbook.GetOrderbook(p.Name, currencyPair, assetType)
return orderbook.GetOrderbook(po.Name, currencyPair, assetType)
}
// GetExchangeAccountInfo retrieves balances for all enabled currencies for the
// Poloniex exchange
func (p *Poloniex) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
func (po *Poloniex) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
var response exchange.AccountInfo
response.ExchangeName = p.GetName()
accountBalance, err := p.GetBalances()
response.ExchangeName = po.GetName()
accountBalance, err := po.GetBalances()
if err != nil {
return response, err
}
@@ -137,3 +138,10 @@ func (p *Poloniex) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
}
return response, nil
}
// GetExchangeHistory returns historic trade data since exchange opening.
func (po *Poloniex) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
var resp []exchange.TradeHistory
return resp, errors.New("trade history not yet implemented")
}

View File

@@ -1,6 +1,7 @@
package wex
import (
"errors"
"log"
"github.com/thrasher-/gocryptotrader/common"
@@ -112,3 +113,10 @@ func (w *WEX) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
return response, nil
}
// GetExchangeHistory returns historic trade data since exchange opening.
func (w *WEX) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
var resp []exchange.TradeHistory
return resp, errors.New("trade history not yet implemented")
}

View File

@@ -207,7 +207,7 @@ func (y *Yobit) GetTradeHistory(TIDFrom, Count, TIDEnd int64, order, since, end,
return result, y.SendAuthenticatedHTTPRequest(privateTradeHistory, req, &result)
}
// CoinDepositAddress returns the deposit address for a specific currency
// GetDepositAddress returns the deposit address for a specific currency
func (y *Yobit) GetDepositAddress(coin string) (DepositAddress, error) {
req := url.Values{}
req.Add("coinName", coin)
@@ -217,7 +217,7 @@ func (y *Yobit) GetDepositAddress(coin string) (DepositAddress, error) {
return result, y.SendAuthenticatedHTTPRequest(privateGetDepositAddress, req, &result)
}
// CoinDepositAddress returns the deposit address for a specific currency
// WithdrawCoinsToAddress initiates a withdrawal to a specified address
func (y *Yobit) WithdrawCoinsToAddress(coin string, amount float64, address string) (WithdrawCoinsToAddress, error) {
req := url.Values{}
req.Add("coinName", coin)

View File

@@ -111,14 +111,14 @@ type TradeHistory struct {
Timestamp float64 `json:"timestamp"`
}
// CoinDepositAddress stores a curency deposit address
// DepositAddress stores a curency deposit address
type DepositAddress struct {
Address string `json:"address"`
ProcessedAmount float64 `json:"processed_amount"`
ServerTime int64 `json:"server_time"`
}
// WithdrawCoins stores information for a withdrawcoins request
// WithdrawCoinsToAddress stores information for a withdrawcoins request
type WithdrawCoinsToAddress struct {
ServerTime int64 `json:"server_time"`
}

View File

@@ -1,6 +1,7 @@
package yobit
import (
"errors"
"log"
"github.com/thrasher-/gocryptotrader/common"
@@ -118,3 +119,10 @@ func (y *Yobit) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
return response, nil
}
// GetExchangeHistory returns historic trade data since exchange opening.
func (y *Yobit) GetExchangeHistory(p pair.CurrencyPair, assetType string) ([]exchange.TradeHistory, error) {
var resp []exchange.TradeHistory
return resp, errors.New("trade history not yet implemented")
}