mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-15 23:16:48 +00:00
Introduce request package and integrate with exchanges
This commit is contained in:
committed by
Adrian Gallagher
parent
52dfddbb18
commit
7fc9d20fd7
@@ -5,12 +5,14 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
@@ -36,14 +38,16 @@ const (
|
||||
alphapointOpenOrders = "GetAccountOpenOrders"
|
||||
alphapointOrderFee = "GetOrderFee"
|
||||
|
||||
// Anymore and you get IP banned
|
||||
alphapointMaxRequestsPer10minutes = 500
|
||||
// alphapoint rate times
|
||||
alphapointAuthRate = 1200
|
||||
alphapointUnauthRate = 1200
|
||||
)
|
||||
|
||||
// Alphapoint is the overarching type across the alphapoint package
|
||||
type Alphapoint struct {
|
||||
exchange.Base
|
||||
WebsocketConn *websocket.Conn
|
||||
*request.Handler
|
||||
}
|
||||
|
||||
// SetDefaults sets current default settings
|
||||
@@ -52,6 +56,8 @@ func (a *Alphapoint) SetDefaults() {
|
||||
a.WebsocketURL = alphapointDefaultWebsocketURL
|
||||
a.AssetTypes = []string{ticker.Spot}
|
||||
a.SupportsAutoPairUpdating = false
|
||||
a.Handler = new(request.Handler)
|
||||
a.SetRequestHandler(a.Name, alphapointAuthRate, alphapointUnauthRate, new(http.Client))
|
||||
}
|
||||
|
||||
// GetTicker returns current ticker information from Alphapoint for a selected
|
||||
@@ -61,7 +67,7 @@ func (a *Alphapoint) GetTicker(currencyPair string) (Ticker, error) {
|
||||
request["productPair"] = currencyPair
|
||||
response := Ticker{}
|
||||
|
||||
err := a.SendRequest("POST", alphapointTicker, request, &response)
|
||||
err := a.SendHTTPRequest("POST", alphapointTicker, request, &response)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
@@ -84,7 +90,7 @@ func (a *Alphapoint) GetTrades(currencyPair string, startIndex, count int) (Trad
|
||||
request["Count"] = count
|
||||
response := Trades{}
|
||||
|
||||
err := a.SendRequest("POST", alphapointTrades, request, &response)
|
||||
err := a.SendHTTPRequest("POST", alphapointTrades, request, &response)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
@@ -105,7 +111,7 @@ func (a *Alphapoint) GetTradesByDate(currencyPair string, startDate, endDate int
|
||||
request["endDate"] = endDate
|
||||
response := Trades{}
|
||||
|
||||
err := a.SendRequest("POST", alphapointTradesByDate, request, &response)
|
||||
err := a.SendHTTPRequest("POST", alphapointTradesByDate, request, &response)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
@@ -122,7 +128,7 @@ func (a *Alphapoint) GetOrderbook(currencyPair string) (Orderbook, error) {
|
||||
request["productPair"] = currencyPair
|
||||
response := Orderbook{}
|
||||
|
||||
err := a.SendRequest("POST", alphapointOrderbook, request, &response)
|
||||
err := a.SendHTTPRequest("POST", alphapointOrderbook, request, &response)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
@@ -136,7 +142,7 @@ func (a *Alphapoint) GetOrderbook(currencyPair string) (Orderbook, error) {
|
||||
func (a *Alphapoint) GetProductPairs() (ProductPairs, error) {
|
||||
response := ProductPairs{}
|
||||
|
||||
err := a.SendRequest("POST", alphapointProductPairs, nil, &response)
|
||||
err := a.SendHTTPRequest("POST", alphapointProductPairs, nil, &response)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
@@ -150,7 +156,7 @@ func (a *Alphapoint) GetProductPairs() (ProductPairs, error) {
|
||||
func (a *Alphapoint) GetProducts() (Products, error) {
|
||||
response := Products{}
|
||||
|
||||
err := a.SendRequest("POST", alphapointProducts, nil, &response)
|
||||
err := a.SendHTTPRequest("POST", alphapointProducts, nil, &response)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
@@ -504,8 +510,8 @@ func (a *Alphapoint) GetOrderFee(symbol, side string, quantity, price float64) (
|
||||
return response.Fee, nil
|
||||
}
|
||||
|
||||
// SendRequest sends an unauthenticated request
|
||||
func (a *Alphapoint) SendRequest(method, path string, data map[string]interface{}, result interface{}) error {
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (a *Alphapoint) SendHTTPRequest(method, path string, data map[string]interface{}, result interface{}) error {
|
||||
headers := make(map[string]string)
|
||||
headers["Content-Type"] = "application/json"
|
||||
path = fmt.Sprintf("%s/ajax/v%s/%s", a.APIUrl, alphapointAPIVersion, path)
|
||||
@@ -515,21 +521,7 @@ func (a *Alphapoint) SendRequest(method, path string, data map[string]interface{
|
||||
return errors.New("SendHTTPRequest: Unable to JSON request")
|
||||
}
|
||||
|
||||
resp, err := common.SendHTTPRequest(
|
||||
method,
|
||||
path,
|
||||
headers,
|
||||
bytes.NewBuffer(PayloadJSON),
|
||||
)
|
||||
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 a.SendPayload(method, path, headers, bytes.NewBuffer(PayloadJSON), result, false, a.Verbose)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated request
|
||||
@@ -557,16 +549,5 @@ func (a *Alphapoint) SendAuthenticatedHTTPRequest(method, path string, data map[
|
||||
return errors.New("SendAuthenticatedHTTPRequest: Unable to JSON request")
|
||||
}
|
||||
|
||||
resp, err := common.SendHTTPRequest(
|
||||
method, path, headers, bytes.NewBuffer(PayloadJSON),
|
||||
)
|
||||
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 a.SendPayload(method, path, headers, bytes.NewBuffer(PayloadJSON), result, true, a.Verbose)
|
||||
}
|
||||
|
||||
@@ -5,12 +5,14 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
@@ -27,11 +29,16 @@ const (
|
||||
anxCreateAddress = "receive/create"
|
||||
anxTicker = "money/ticker"
|
||||
anxDepth = "money/depth/full"
|
||||
|
||||
// ANX rate limites for authenticated and unauthenticated requests
|
||||
anxAuthRate = 1000
|
||||
anxUnauthRate = 1000
|
||||
)
|
||||
|
||||
// ANX is the overarching type across the alphapoint package
|
||||
type ANX struct {
|
||||
exchange.Base
|
||||
*request.Handler
|
||||
}
|
||||
|
||||
// SetDefaults sets current default settings
|
||||
@@ -51,6 +58,8 @@ func (a *ANX) SetDefaults() {
|
||||
a.ConfigCurrencyPairFormat.Index = "BTC"
|
||||
a.AssetTypes = []string{ticker.Spot}
|
||||
a.SupportsAutoPairUpdating = false
|
||||
a.Handler = new(request.Handler)
|
||||
a.SetRequestHandler(a.Name, anxAuthRate, anxUnauthRate, new(http.Client))
|
||||
}
|
||||
|
||||
//Setup is run on startup to setup exchange with config values
|
||||
@@ -95,7 +104,7 @@ 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)
|
||||
return ticker, a.SendHTTPRequest(path, &ticker)
|
||||
}
|
||||
|
||||
// GetDepth returns current orderbook depth.
|
||||
@@ -103,7 +112,7 @@ func (a *ANX) GetDepth(currency string) (Depth, error) {
|
||||
var depth Depth
|
||||
path := fmt.Sprintf("%sapi/2/%s/%s", anxAPIURL, currency, anxDepth)
|
||||
|
||||
return depth, common.SendHTTPGetRequest(path, true, a.Verbose, &depth)
|
||||
return depth, a.SendHTTPRequest(path, &depth)
|
||||
}
|
||||
|
||||
// GetAPIKey returns a new generated API key set.
|
||||
@@ -324,6 +333,11 @@ func (a *ANX) GetDepositAddress(currency, name string, new bool) (string, error)
|
||||
return response.Address, nil
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (a *ANX) SendHTTPRequest(path string, result interface{}) error {
|
||||
return a.SendPayload("GET", path, nil, nil, result, false, a.Verbose)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends a authenticated HTTP request
|
||||
func (a *ANX) SendAuthenticatedHTTPRequest(path string, params map[string]interface{}, result interface{}) error {
|
||||
if !a.AuthenticatedAPISupport {
|
||||
@@ -362,20 +376,5 @@ 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", anxAPIURL+path, headers, bytes.NewBuffer(PayloadJSON))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if a.Verbose {
|
||||
log.Printf("Received raw: \n%s\n", resp)
|
||||
}
|
||||
|
||||
err = common.JSONDecode([]byte(resp), &result)
|
||||
|
||||
if err != nil {
|
||||
return errors.New("unable to JSON Unmarshal response")
|
||||
}
|
||||
|
||||
return nil
|
||||
return a.SendPayload("POST", anxAPIURL+path, headers, bytes.NewBuffer(PayloadJSON), result, true, a.Verbose)
|
||||
}
|
||||
|
||||
@@ -6,92 +6,88 @@ import (
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
)
|
||||
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
setDefaults := ANX{}
|
||||
setDefaults.SetDefaults()
|
||||
var anx ANX
|
||||
|
||||
if setDefaults.Name != "ANX" {
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
anx.SetDefaults()
|
||||
|
||||
if anx.Name != "ANX" {
|
||||
t.Error("Test Failed - ANX SetDefaults() incorrect values set")
|
||||
}
|
||||
if setDefaults.Enabled != false {
|
||||
if anx.Enabled != false {
|
||||
t.Error("Test Failed - ANX SetDefaults() incorrect values set")
|
||||
}
|
||||
if setDefaults.TakerFee != 0.6 {
|
||||
if anx.TakerFee != 0.6 {
|
||||
t.Error("Test Failed - ANX SetDefaults() incorrect values set")
|
||||
}
|
||||
if setDefaults.MakerFee != 0.3 {
|
||||
if anx.MakerFee != 0.3 {
|
||||
t.Error("Test Failed - ANX SetDefaults() incorrect values set")
|
||||
}
|
||||
if setDefaults.Verbose != false {
|
||||
if anx.Verbose != false {
|
||||
t.Error("Test Failed - ANX SetDefaults() incorrect values set")
|
||||
}
|
||||
if setDefaults.Websocket != false {
|
||||
if anx.Websocket != false {
|
||||
t.Error("Test Failed - ANX SetDefaults() incorrect values set")
|
||||
}
|
||||
if setDefaults.RESTPollingDelay != 10 {
|
||||
if anx.RESTPollingDelay != 10 {
|
||||
t.Error("Test Failed - ANX SetDefaults() incorrect values set")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
setup := ANX{}
|
||||
setup.Name = "ANX"
|
||||
anxSetupConfig := config.GetConfig()
|
||||
anxSetupConfig.LoadConfig("../../testdata/configtest.json")
|
||||
anxConfig, err := anxSetupConfig.GetExchangeConfig("ANX")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - ANX Setup() init error")
|
||||
}
|
||||
setup.Setup(anxConfig)
|
||||
anx.Setup(anxConfig)
|
||||
|
||||
if setup.Enabled != true {
|
||||
if anx.Enabled != true {
|
||||
t.Error("Test Failed - ANX Setup() incorrect values set")
|
||||
}
|
||||
if setup.AuthenticatedAPISupport != false {
|
||||
if anx.AuthenticatedAPISupport != false {
|
||||
t.Error("Test Failed - ANX Setup() incorrect values set")
|
||||
}
|
||||
if len(setup.APIKey) != 0 {
|
||||
if len(anx.APIKey) != 0 {
|
||||
t.Error("Test Failed - ANX Setup() incorrect values set")
|
||||
}
|
||||
if len(setup.APISecret) != 0 {
|
||||
if len(anx.APISecret) != 0 {
|
||||
t.Error("Test Failed - ANX Setup() incorrect values set")
|
||||
}
|
||||
if setup.RESTPollingDelay != 10 {
|
||||
if anx.RESTPollingDelay != 10 {
|
||||
t.Error("Test Failed - ANX Setup() incorrect values set")
|
||||
}
|
||||
if setup.Verbose != false {
|
||||
if anx.Verbose != false {
|
||||
t.Error("Test Failed - ANX Setup() incorrect values set")
|
||||
}
|
||||
if setup.Websocket != false {
|
||||
if anx.Websocket != false {
|
||||
t.Error("Test Failed - ANX Setup() incorrect values set")
|
||||
}
|
||||
if len(setup.BaseCurrencies) <= 0 {
|
||||
if len(anx.BaseCurrencies) <= 0 {
|
||||
t.Error("Test Failed - ANX Setup() incorrect values set")
|
||||
}
|
||||
if len(setup.AvailablePairs) <= 0 {
|
||||
if len(anx.AvailablePairs) <= 0 {
|
||||
t.Error("Test Failed - ANX Setup() incorrect values set")
|
||||
}
|
||||
if len(setup.EnabledPairs) <= 0 {
|
||||
if len(anx.EnabledPairs) <= 0 {
|
||||
t.Error("Test Failed - ANX Setup() incorrect values set")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetFee(t *testing.T) {
|
||||
getFee := ANX{}
|
||||
makerFeeExpected, takerFeeExpected := 0.3, 0.6
|
||||
|
||||
getFee.SetDefaults()
|
||||
if getFee.GetFee(true) != makerFeeExpected {
|
||||
if anx.GetFee(true) != makerFeeExpected {
|
||||
t.Error("Test Failed - ANX GetFee() incorrect return value")
|
||||
}
|
||||
if getFee.GetFee(false) != takerFeeExpected {
|
||||
if anx.GetFee(false) != takerFeeExpected {
|
||||
t.Error("Test Failed - ANX GetFee() incorrect return value")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTicker(t *testing.T) {
|
||||
getTicker := ANX{}
|
||||
ticker, err := getTicker.GetTicker("BTCUSD")
|
||||
ticker, err := anx.GetTicker("BTCUSD")
|
||||
if err != nil {
|
||||
t.Errorf("Test Failed - ANX GetTicker() error: %s", err)
|
||||
}
|
||||
@@ -101,8 +97,7 @@ func TestGetTicker(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetDepth(t *testing.T) {
|
||||
a := ANX{}
|
||||
ticker, err := a.GetDepth("BTCUSD")
|
||||
ticker, err := anx.GetDepth("BTCUSD")
|
||||
if err != nil {
|
||||
t.Errorf("Test Failed - ANX GetDepth() error: %s", err)
|
||||
}
|
||||
@@ -112,8 +107,7 @@ func TestGetDepth(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetAPIKey(t *testing.T) {
|
||||
getAPIKey := ANX{}
|
||||
apiKey, apiSecret, err := getAPIKey.GetAPIKey("userName", "passWord", "", "1337")
|
||||
apiKey, apiSecret, err := anx.GetAPIKey("userName", "passWord", "", "1337")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - ANX GetAPIKey() Incorrect")
|
||||
}
|
||||
@@ -124,38 +118,3 @@ func TestGetAPIKey(t *testing.T) {
|
||||
t.Error("Test Failed - ANX GetAPIKey() Incorrect")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetDataToken(t *testing.T) {
|
||||
// --- FAIL: TestGetDataToken (0.17s)
|
||||
// anx_test.go:120: Test Failed - ANX GetDataToken() Incorrect
|
||||
|
||||
// getDataToken := ANX{}
|
||||
// _, err := getDataToken.GetDataToken()
|
||||
// if err != nil {
|
||||
// t.Error("Test Failed - ANX GetDataToken() Incorrect")
|
||||
// }
|
||||
}
|
||||
|
||||
func TestNewOrder(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestOrderInfo(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestSend(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestCreateNewSubAccount(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestGetDepositAddress(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestSendAuthenticatedHTTPRequest(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
@@ -12,6 +13,7 @@ import (
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
@@ -22,6 +24,7 @@ type Binance struct {
|
||||
// valid string list that a required by the exchange
|
||||
validLimits []string
|
||||
validIntervals []string
|
||||
*request.Handler
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -39,10 +42,13 @@ const (
|
||||
bestPrice = "/api/v3/ticker/bookTicker"
|
||||
|
||||
// Authenticated endpoints
|
||||
|
||||
newOrderTest = "/api/v3/order/test"
|
||||
newOrder = "/api/v3/order"
|
||||
queryOrder = "/api/v3/order"
|
||||
|
||||
// binance authenticated and unauthenticated limit rates
|
||||
binanceAuthRate = 1000
|
||||
binanceUnauthRate = 1000
|
||||
)
|
||||
|
||||
// SetDefaults sets the basic defaults for Binance
|
||||
@@ -59,6 +65,8 @@ func (b *Binance) SetDefaults() {
|
||||
b.AssetTypes = []string{ticker.Spot}
|
||||
b.SupportsAutoPairUpdating = true
|
||||
b.SetValues()
|
||||
b.Handler = new(request.Handler)
|
||||
b.SetRequestHandler(b.Name, binanceAuthRate, binanceUnauthRate, new(http.Client))
|
||||
}
|
||||
|
||||
// Setup takes in the supplied exchange configuration details and sets params
|
||||
@@ -114,7 +122,7 @@ func (b *Binance) GetExchangeInfo() (ExchangeInfo, error) {
|
||||
var resp ExchangeInfo
|
||||
path := apiURL + exchangeInfo
|
||||
|
||||
return resp, common.SendHTTPGetRequest(path, true, b.Verbose, &resp)
|
||||
return resp, b.SendHTTPRequest(path, &resp)
|
||||
}
|
||||
|
||||
// GetOrderBook returns full orderbook information
|
||||
@@ -137,7 +145,7 @@ func (b *Binance) GetOrderBook(symbol string, limit int64) (OrderBook, error) {
|
||||
|
||||
path := fmt.Sprintf("%s%s?%s", apiURL, orderBookDepth, params.Encode())
|
||||
|
||||
if err := common.SendHTTPGetRequest(path, true, b.Verbose, &resp); err != nil {
|
||||
if err := b.SendHTTPRequest(path, &resp); err != nil {
|
||||
return orderbook, err
|
||||
}
|
||||
|
||||
@@ -195,7 +203,7 @@ func (b *Binance) GetRecentTrades(symbol string, limit int64) ([]RecentTrade, er
|
||||
|
||||
path := fmt.Sprintf("%s%s?%s", apiURL, recentTrades, params.Encode())
|
||||
|
||||
return resp, common.SendHTTPGetRequest(path, true, b.Verbose, &resp)
|
||||
return resp, b.SendHTTPRequest(path, &resp)
|
||||
}
|
||||
|
||||
// GetHistoricalTrades returns historical trade activity
|
||||
@@ -220,7 +228,7 @@ func (b *Binance) GetHistoricalTrades(symbol string, limit, fromID int64) ([]His
|
||||
|
||||
path := fmt.Sprintf("%s%s?%s", apiURL, historicalTrades, params.Encode())
|
||||
|
||||
return resp, common.SendHTTPGetRequest(path, true, b.Verbose, &resp)
|
||||
return resp, b.SendHTTPRequest(path, &resp)
|
||||
}
|
||||
|
||||
// GetAggregatedTrades returns aggregated trade activity
|
||||
@@ -243,7 +251,7 @@ func (b *Binance) GetAggregatedTrades(symbol string, limit int64) ([]AggregatedT
|
||||
|
||||
path := fmt.Sprintf("%s%s?%s", apiURL, aggregatedTrades, params.Encode())
|
||||
|
||||
return resp, common.SendHTTPGetRequest(path, true, b.Verbose, &resp)
|
||||
return resp, b.SendHTTPRequest(path, &resp)
|
||||
}
|
||||
|
||||
// GetCandleStickData returns candle stick data
|
||||
@@ -272,7 +280,7 @@ func (b *Binance) GetCandleStickData(symbol, interval string, limit int64) ([]Ca
|
||||
|
||||
path := fmt.Sprintf("%s%s?%s", apiURL, candleStick, params.Encode())
|
||||
|
||||
if err := common.SendHTTPGetRequest(path, true, b.Verbose, &resp); err != nil {
|
||||
if err := b.SendHTTPRequest(path, &resp); err != nil {
|
||||
return kline, err
|
||||
}
|
||||
|
||||
@@ -324,14 +332,14 @@ func (b *Binance) GetPriceChangeStats(symbol string) (PriceChangeStats, error) {
|
||||
|
||||
path := fmt.Sprintf("%s%s?%s", apiURL, priceChange, params.Encode())
|
||||
|
||||
return resp, common.SendHTTPGetRequest(path, true, b.Verbose, &resp)
|
||||
return resp, b.SendHTTPRequest(path, &resp)
|
||||
}
|
||||
|
||||
// GetTickers returns the ticker data for the last 24 hrs
|
||||
func (b *Binance) GetTickers() ([]PriceChangeStats, error) {
|
||||
var resp []PriceChangeStats
|
||||
path := fmt.Sprintf("%s%s", apiURL, priceChange)
|
||||
return resp, common.SendHTTPGetRequest(path, true, b.Verbose, &resp)
|
||||
return resp, b.SendHTTPRequest(path, &resp)
|
||||
}
|
||||
|
||||
// GetLatestSpotPrice returns latest spot price of symbol
|
||||
@@ -349,7 +357,7 @@ func (b *Binance) GetLatestSpotPrice(symbol string) (SymbolPrice, error) {
|
||||
|
||||
path := fmt.Sprintf("%s%s?%s", apiURL, symbolPrice, params.Encode())
|
||||
|
||||
return resp, common.SendHTTPGetRequest(path, true, b.Verbose, &resp)
|
||||
return resp, b.SendHTTPRequest(path, &resp)
|
||||
}
|
||||
|
||||
// GetBestPrice returns the latest best price for symbol
|
||||
@@ -367,7 +375,7 @@ func (b *Binance) GetBestPrice(symbol string) (BestPrice, error) {
|
||||
|
||||
path := fmt.Sprintf("%s%s?%s", apiURL, bestPrice, params.Encode())
|
||||
|
||||
return resp, common.SendHTTPGetRequest(path, true, b.Verbose, &resp)
|
||||
return resp, b.SendHTTPRequest(path, &resp)
|
||||
}
|
||||
|
||||
// NewOrderTest sends a new order
|
||||
@@ -434,7 +442,12 @@ func (b *Binance) QueryOrder(symbol, origClientOrderID string, orderID int64) (Q
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// SendAuthHTTPRequest something
|
||||
// SendHTTPRequest sends an unauthenticated request
|
||||
func (b *Binance) SendHTTPRequest(path string, result interface{}) error {
|
||||
return b.SendPayload("GET", path, nil, nil, result, false, b.Verbose)
|
||||
}
|
||||
|
||||
// SendAuthHTTPRequest sends an authenticated HTTP request
|
||||
func (b *Binance) SendAuthHTTPRequest(method, path string, params url.Values, result interface{}) error {
|
||||
if !b.AuthenticatedAPISupport {
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, b.Name)
|
||||
@@ -459,19 +472,7 @@ func (b *Binance) SendAuthHTTPRequest(method, path string, params url.Values, re
|
||||
log.Printf("sent path: \n%s\n", path)
|
||||
}
|
||||
|
||||
resp, err := common.SendHTTPRequest(method, path, headers, bytes.NewBufferString(params.Encode()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if b.Verbose {
|
||||
log.Printf("Received raw: \n%s\n", resp)
|
||||
}
|
||||
|
||||
if err = common.JSONDecode([]byte(resp), &result); err != nil {
|
||||
return errors.New("sendAuthenticatedHTTPRequest: Unable to JSON Unmarshal response." + err.Error())
|
||||
}
|
||||
return nil
|
||||
return b.SendPayload(method, path, headers, bytes.NewBufferString(params.Encode()), result, true, b.Verbose)
|
||||
}
|
||||
|
||||
// CheckLimit checks value against a variable list
|
||||
|
||||
@@ -4,15 +4,16 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
@@ -66,9 +67,9 @@ const (
|
||||
bitfinexActiveCredits = "credits"
|
||||
bitfinexPlatformStatus = "platform/status"
|
||||
|
||||
// bitfinexMaxRequests if exceeded IP address blocked 10-60 sec, JSON response
|
||||
// {"error": "ERR_RATE_LIMIT"}
|
||||
bitfinexMaxRequests = 90
|
||||
// stable times in millisecond per request
|
||||
bitfinexAuthRate = 2750
|
||||
bitfinexUnauthRate = 2750
|
||||
|
||||
// Bitfinex platform status values
|
||||
// When the platform is marked in maintenance mode bots should stop trading
|
||||
@@ -85,6 +86,7 @@ type Bitfinex struct {
|
||||
exchange.Base
|
||||
WebsocketConn *websocket.Conn
|
||||
WebsocketSubdChannels map[int]WebsocketChanInfo
|
||||
*request.Handler
|
||||
}
|
||||
|
||||
// SetDefaults sets the basic defaults for bitfinex
|
||||
@@ -101,6 +103,8 @@ func (b *Bitfinex) SetDefaults() {
|
||||
b.ConfigCurrencyPairFormat.Uppercase = true
|
||||
b.AssetTypes = []string{ticker.Spot}
|
||||
b.SupportsAutoPairUpdating = true
|
||||
b.Handler = new(request.Handler)
|
||||
b.SetRequestHandler(b.Name, bitfinexAuthRate, bitfinexUnauthRate, new(http.Client))
|
||||
}
|
||||
|
||||
// Setup takes in the supplied exchange configuration details and sets params
|
||||
@@ -138,7 +142,7 @@ func (b *Bitfinex) GetPlatformStatus() (int, error) {
|
||||
path := fmt.Sprintf("%s/v%s/%s", bitfinexAPIURLBase, bitfinexAPIVersion2,
|
||||
bitfinexPlatformStatus)
|
||||
|
||||
err := common.SendHTTPGetRequest(path, true, b.Verbose, &response)
|
||||
err := b.SendHTTPRequest(path, &response, b.Verbose)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -155,7 +159,15 @@ func (b *Bitfinex) GetTicker(symbol string, values url.Values) (Ticker, error) {
|
||||
response := Ticker{}
|
||||
path := common.EncodeURLValues(bitfinexAPIURL+bitfinexTicker+symbol, values)
|
||||
|
||||
return response, common.SendHTTPGetRequest(path, true, b.Verbose, &response)
|
||||
if err := b.SendHTTPRequest(path, &response, b.Verbose); err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
if response.Message != "" {
|
||||
return response, errors.New(response.Message)
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// GetTickerV2 returns ticker information
|
||||
@@ -164,7 +176,7 @@ func (b *Bitfinex) GetTickerV2(symbol string) (Tickerv2, error) {
|
||||
var ticker Tickerv2
|
||||
|
||||
path := fmt.Sprintf("%s/v%s/%s/%s", bitfinexAPIURLBase, bitfinexAPIVersion2, bitfinexTickerV2, symbol)
|
||||
err := common.SendHTTPGetRequest(path, true, b.Verbose, &response)
|
||||
err := b.SendHTTPRequest(path, &response, b.Verbose)
|
||||
if err != nil {
|
||||
return ticker, err
|
||||
}
|
||||
@@ -207,7 +219,7 @@ func (b *Bitfinex) GetTickersV2(symbols string) ([]Tickersv2, error) {
|
||||
v.Set("symbols", symbols)
|
||||
|
||||
path := common.EncodeURLValues(fmt.Sprintf("%s/v%s/%s", bitfinexAPIURLBase, bitfinexAPIVersion2, bitfinexTickersV2), v)
|
||||
err := common.SendHTTPGetRequest(path, true, b.Verbose, &response)
|
||||
err := b.SendHTTPRequest(path, &response, b.Verbose)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -253,7 +265,7 @@ func (b *Bitfinex) GetStats(symbol string) ([]Stat, error) {
|
||||
response := []Stat{}
|
||||
path := fmt.Sprint(bitfinexAPIURL + bitfinexStats + symbol)
|
||||
|
||||
return response, common.SendHTTPGetRequest(path, true, b.Verbose, &response)
|
||||
return response, b.SendHTTPRequest(path, &response, b.Verbose)
|
||||
}
|
||||
|
||||
// GetFundingBook the entire margin funding book for both bids and asks sides
|
||||
@@ -263,7 +275,15 @@ func (b *Bitfinex) GetFundingBook(symbol string) (FundingBook, error) {
|
||||
response := FundingBook{}
|
||||
path := fmt.Sprint(bitfinexAPIURL + bitfinexLendbook + symbol)
|
||||
|
||||
return response, common.SendHTTPGetRequest(path, true, b.Verbose, &response)
|
||||
if err := b.SendHTTPRequest(path, &response, b.Verbose); err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
if response.Message != "" {
|
||||
return response, errors.New(response.Message)
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// GetOrderbook retieves the orderbook bid and ask price points for a currency
|
||||
@@ -277,7 +297,7 @@ func (b *Bitfinex) GetOrderbook(currencyPair string, values url.Values) (Orderbo
|
||||
bitfinexAPIURL+bitfinexOrderbook+currencyPair,
|
||||
values,
|
||||
)
|
||||
return response, common.SendHTTPGetRequest(path, true, b.Verbose, &response)
|
||||
return response, b.SendHTTPRequest(path, &response, b.Verbose)
|
||||
}
|
||||
|
||||
// GetOrderbookV2 retieves the orderbook bid and ask price points for a currency
|
||||
@@ -291,7 +311,7 @@ func (b *Bitfinex) GetOrderbookV2(symbol, precision string, values url.Values) (
|
||||
var book OrderbookV2
|
||||
path := common.EncodeURLValues(fmt.Sprintf("%s/v%s/%s/%s/%s", bitfinexAPIURLBase,
|
||||
bitfinexAPIVersion2, bitfinexOrderbookV2, symbol, precision), values)
|
||||
err := common.SendHTTPGetRequest(path, true, b.Verbose, &response)
|
||||
err := b.SendHTTPRequest(path, &response, b.Verbose)
|
||||
if err != nil {
|
||||
return book, err
|
||||
}
|
||||
@@ -339,7 +359,7 @@ func (b *Bitfinex) GetTrades(currencyPair string, values url.Values) ([]TradeStr
|
||||
bitfinexAPIURL+bitfinexTrades+currencyPair,
|
||||
values,
|
||||
)
|
||||
return response, common.SendHTTPGetRequest(path, true, b.Verbose, &response)
|
||||
return response, b.SendHTTPRequest(path, &response, b.Verbose)
|
||||
}
|
||||
|
||||
// GetTradesV2 uses the V2 API to get historic trades that occurred on the
|
||||
@@ -359,7 +379,7 @@ func (b *Bitfinex) GetTradesV2(currencyPair string, timestampStart, timestampEnd
|
||||
strconv.FormatInt(timestampStart, 10),
|
||||
strconv.FormatInt(timestampEnd, 10))
|
||||
|
||||
err := common.SendHTTPGetRequest(path, true, b.Verbose, &resp)
|
||||
err := b.SendHTTPRequest(path, &resp, b.Verbose)
|
||||
if err != nil {
|
||||
return actualHistory, err
|
||||
}
|
||||
@@ -403,7 +423,7 @@ func (b *Bitfinex) GetLendbook(symbol string, values url.Values) (Lendbook, erro
|
||||
}
|
||||
path := common.EncodeURLValues(bitfinexAPIURL+bitfinexLendbook+symbol, values)
|
||||
|
||||
return response, common.SendHTTPGetRequest(path, true, b.Verbose, &response)
|
||||
return response, b.SendHTTPRequest(path, &response, b.Verbose)
|
||||
}
|
||||
|
||||
// GetLends returns a list of the most recent funding data for the given
|
||||
@@ -414,7 +434,7 @@ func (b *Bitfinex) GetLends(symbol string, values url.Values) ([]Lends, error) {
|
||||
response := []Lends{}
|
||||
path := common.EncodeURLValues(bitfinexAPIURL+bitfinexLends+symbol, values)
|
||||
|
||||
return response, common.SendHTTPGetRequest(path, true, b.Verbose, &response)
|
||||
return response, b.SendHTTPRequest(path, &response, b.Verbose)
|
||||
}
|
||||
|
||||
// GetSymbols returns the available currency pairs on the exchange
|
||||
@@ -422,7 +442,7 @@ func (b *Bitfinex) GetSymbols() ([]string, error) {
|
||||
products := []string{}
|
||||
path := fmt.Sprint(bitfinexAPIURL + bitfinexSymbols)
|
||||
|
||||
return products, common.SendHTTPGetRequest(path, true, b.Verbose, &products)
|
||||
return products, b.SendHTTPRequest(path, &products, b.Verbose)
|
||||
}
|
||||
|
||||
// GetSymbolsDetails a list of valid symbol IDs and the pair details
|
||||
@@ -430,23 +450,33 @@ func (b *Bitfinex) GetSymbolsDetails() ([]SymbolDetails, error) {
|
||||
response := []SymbolDetails{}
|
||||
path := fmt.Sprint(bitfinexAPIURL + bitfinexSymbolsDetails)
|
||||
|
||||
return response, common.SendHTTPGetRequest(path, true, b.Verbose, &response)
|
||||
return response, b.SendHTTPRequest(path, &response, b.Verbose)
|
||||
}
|
||||
|
||||
// GetAccountInfo returns information about your account incl. trading fees
|
||||
func (b *Bitfinex) GetAccountInfo() ([]AccountInfo, error) {
|
||||
response := []AccountInfo{}
|
||||
response := AccountInfoFull{}
|
||||
|
||||
return response,
|
||||
b.SendAuthenticatedHTTPRequest("POST", bitfinexAccountInfo, nil, &response)
|
||||
err := b.SendAuthenticatedHTTPRequest("POST", bitfinexAccountFees, nil, &response)
|
||||
if err != nil {
|
||||
return response.Info, err
|
||||
}
|
||||
|
||||
if response.Message == "" {
|
||||
return response.Info, errors.New(response.Message)
|
||||
}
|
||||
return response.Info, nil
|
||||
}
|
||||
|
||||
// GetAccountFees - NOT YET IMPLEMENTED
|
||||
func (b *Bitfinex) GetAccountFees() (AccountFees, error) {
|
||||
response := AccountFees{}
|
||||
|
||||
return response,
|
||||
b.SendAuthenticatedHTTPRequest("POST", bitfinexAccountFees, nil, &response)
|
||||
err := b.SendAuthenticatedHTTPRequest("POST", bitfinexAccountFees, nil, &response)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// GetAccountSummary returns a 30-day summary of your trading volume and return
|
||||
@@ -804,6 +834,11 @@ func (b *Bitfinex) CloseMarginFunding(SwapID int64) (Offer, error) {
|
||||
b.SendAuthenticatedHTTPRequest("POST", bitfinexMarginClose, request, &response)
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated request
|
||||
func (b *Bitfinex) SendHTTPRequest(path string, result interface{}, verbose bool) error {
|
||||
return b.SendPayload("GET", path, nil, nil, result, false, verbose)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an autheticated http request and json
|
||||
// unmarshals result to a supplied variable
|
||||
func (b *Bitfinex) SendAuthenticatedHTTPRequest(method, path string, params map[string]interface{}, result interface{}) error {
|
||||
@@ -817,7 +852,6 @@ func (b *Bitfinex) SendAuthenticatedHTTPRequest(method, path string, params map[
|
||||
b.Nonce.Inc()
|
||||
}
|
||||
|
||||
respErr := ErrorCapture{}
|
||||
request := make(map[string]interface{})
|
||||
request["request"] = fmt.Sprintf("/v%s/%s", bitfinexAPIVersion, path)
|
||||
request["nonce"] = b.Nonce.String()
|
||||
@@ -844,25 +878,9 @@ func (b *Bitfinex) SendAuthenticatedHTTPRequest(method, path string, params map[
|
||||
headers["X-BFX-PAYLOAD"] = PayloadBase64
|
||||
headers["X-BFX-SIGNATURE"] = common.HexEncodeToString(hmac)
|
||||
|
||||
resp, err := common.SendHTTPRequest(
|
||||
method, bitfinexAPIURL+path, headers, strings.NewReader(""),
|
||||
)
|
||||
b.SendPayload(method, bitfinexAPIURL+path, headers, nil, result, true, b.Verbose)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if b.Verbose {
|
||||
log.Printf("Received raw: \n%s\n", resp)
|
||||
}
|
||||
|
||||
if err = common.JSONDecode([]byte(resp), &respErr); err == nil {
|
||||
if len(respErr.Message) != 0 {
|
||||
return errors.New("Responded Error Issue: " + respErr.Message)
|
||||
}
|
||||
}
|
||||
|
||||
if err = common.JSONDecode([]byte(resp), &result); err != nil {
|
||||
return errors.New("sendAuthenticatedHTTPRequest: Unable to JSON Unmarshal response")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -18,28 +18,14 @@ const (
|
||||
|
||||
var b Bitfinex
|
||||
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
b.SetDefaults()
|
||||
|
||||
if b.Name != "Bitfinex" || b.Enabled != false ||
|
||||
b.Verbose != false || b.Websocket != false ||
|
||||
b.RESTPollingDelay != 10 {
|
||||
t.Error("Test Failed - Bitfinex SetDefaults values not set correctly")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
setup := Bitfinex{}
|
||||
setup.Name = "Bitfinex"
|
||||
b.SetDefaults()
|
||||
cfg := config.GetConfig()
|
||||
cfg.LoadConfig("../../testdata/configtest.json")
|
||||
bfxConfig, err := cfg.GetExchangeConfig("Bitfinex")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - Bitfinex Setup() init error")
|
||||
}
|
||||
setup.Setup(bfxConfig)
|
||||
|
||||
b.SetDefaults()
|
||||
b.Setup(bfxConfig)
|
||||
|
||||
if !b.Enabled || b.AuthenticatedAPISupport || b.RESTPollingDelay != time.Duration(10) ||
|
||||
@@ -47,6 +33,9 @@ func TestSetup(t *testing.T) {
|
||||
len(b.AvailablePairs) < 1 || len(b.EnabledPairs) < 1 {
|
||||
t.Error("Test Failed - Bitfinex Setup values not set correctly")
|
||||
}
|
||||
b.AuthenticatedAPISupport = true
|
||||
// not worried about rate limit on test
|
||||
b.SetRateLimit(0, 0)
|
||||
}
|
||||
|
||||
func TestGetPlatformStatus(t *testing.T) {
|
||||
@@ -238,6 +227,9 @@ func TestGetSymbolsDetails(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.GetAccountInfo()
|
||||
@@ -247,6 +239,9 @@ func TestGetAccountInfo(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetAccountFees(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.GetAccountFees()
|
||||
@@ -256,6 +251,9 @@ func TestGetAccountFees(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetAccountSummary(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.GetAccountSummary()
|
||||
@@ -265,6 +263,9 @@ func TestGetAccountSummary(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNewDeposit(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.NewDeposit("blabla", "testwallet", 1)
|
||||
@@ -274,6 +275,9 @@ func TestNewDeposit(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetKeyPermissions(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.GetKeyPermissions()
|
||||
@@ -283,6 +287,9 @@ func TestGetKeyPermissions(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetMarginInfo(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.GetMarginInfo()
|
||||
@@ -292,6 +299,9 @@ func TestGetMarginInfo(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetAccountBalance(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.GetAccountBalance()
|
||||
@@ -301,6 +311,9 @@ func TestGetAccountBalance(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWalletTransfer(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.WalletTransfer(0.01, "bla", "bla", "bla")
|
||||
@@ -310,6 +323,9 @@ func TestWalletTransfer(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawal(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.Withdrawal("LITECOIN", "deposit", "1000", 0.01)
|
||||
@@ -319,6 +335,9 @@ func TestWithdrawal(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNewOrder(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.NewOrder("BTCUSD", 1, 2, true, "market", false)
|
||||
@@ -328,6 +347,9 @@ func TestNewOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNewOrderMulti(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
newOrder := []PlaceOrder{
|
||||
@@ -348,6 +370,9 @@ func TestNewOrderMulti(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelOrder(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.CancelOrder(1337)
|
||||
@@ -357,6 +382,9 @@ func TestCancelOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelMultipleOrders(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.CancelMultipleOrders([]int64{1337, 1336})
|
||||
@@ -366,6 +394,9 @@ func TestCancelMultipleOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelAllOrders(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.CancelAllOrders()
|
||||
@@ -375,6 +406,9 @@ func TestCancelAllOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestReplaceOrder(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.ReplaceOrder(1337, "BTCUSD", 1, 1, true, "market", false)
|
||||
@@ -384,6 +418,9 @@ func TestReplaceOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetOrderStatus(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.GetOrderStatus(1337)
|
||||
@@ -393,6 +430,9 @@ func TestGetOrderStatus(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.GetActiveOrders()
|
||||
@@ -402,6 +442,9 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetActivePositions(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.GetActivePositions()
|
||||
@@ -411,6 +454,9 @@ func TestGetActivePositions(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestClaimPosition(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.ClaimPosition(1337)
|
||||
@@ -420,6 +466,9 @@ func TestClaimPosition(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetBalanceHistory(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.GetBalanceHistory("USD", time.Time{}, time.Time{}, 1, "deposit")
|
||||
@@ -429,6 +478,9 @@ func TestGetBalanceHistory(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetMovementHistory(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.GetMovementHistory("USD", "bitcoin", time.Time{}, time.Time{}, 1)
|
||||
@@ -438,6 +490,9 @@ func TestGetMovementHistory(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetTradeHistory(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.GetTradeHistory("BTCUSD", time.Time{}, time.Time{}, 1, 0)
|
||||
@@ -447,6 +502,9 @@ func TestGetTradeHistory(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNewOffer(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.NewOffer("BTC", 1, 1, 1, "loan")
|
||||
@@ -456,6 +514,9 @@ func TestNewOffer(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelOffer(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.CancelOffer(1337)
|
||||
@@ -465,6 +526,9 @@ func TestCancelOffer(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetOfferStatus(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.GetOfferStatus(1337)
|
||||
@@ -474,6 +538,9 @@ func TestGetOfferStatus(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetActiveCredits(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.GetActiveCredits()
|
||||
@@ -483,6 +550,9 @@ func TestGetActiveCredits(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetActiveOffers(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.GetActiveOffers()
|
||||
@@ -492,6 +562,9 @@ func TestGetActiveOffers(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetActiveMarginFunding(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.GetActiveMarginFunding()
|
||||
@@ -501,6 +574,9 @@ func TestGetActiveMarginFunding(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetUnusedMarginFunds(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.GetUnusedMarginFunds()
|
||||
@@ -510,6 +586,9 @@ func TestGetUnusedMarginFunds(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetMarginTotalTakenFunds(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.GetMarginTotalTakenFunds()
|
||||
@@ -519,6 +598,9 @@ func TestGetMarginTotalTakenFunds(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCloseMarginFunding(t *testing.T) {
|
||||
if b.APIKey == "" || b.APISecret == "" {
|
||||
t.SkipNow()
|
||||
}
|
||||
t.Parallel()
|
||||
|
||||
_, err := b.CloseMarginFunding(1337)
|
||||
|
||||
@@ -10,6 +10,7 @@ type Ticker struct {
|
||||
High float64 `json:"high,string"`
|
||||
Volume float64 `json:"volume,string"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// Tickerv2 holds the version 2 ticker information
|
||||
@@ -43,8 +44,9 @@ type Stat struct {
|
||||
|
||||
// FundingBook holds current the full margin funding book
|
||||
type FundingBook struct {
|
||||
Bids []Book `json:"bids"`
|
||||
Asks []Book `json:"asks"`
|
||||
Bids []Book `json:"bids"`
|
||||
Asks []Book `json:"asks"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// Orderbook holds orderbook information from bid and ask sides
|
||||
@@ -123,6 +125,12 @@ type SymbolDetails struct {
|
||||
Expiration string `json:"expiration"`
|
||||
}
|
||||
|
||||
// AccountInfoFull adds the error message to Account info
|
||||
type AccountInfoFull struct {
|
||||
Info []AccountInfo
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// AccountInfo general account information with fees
|
||||
type AccountInfo struct {
|
||||
MakerFees string `json:"maker_fees"`
|
||||
@@ -132,6 +140,7 @@ type AccountInfo struct {
|
||||
MakerFees string `json:"maker_fees"`
|
||||
TakerFees string `json:"taker_fees"`
|
||||
} `json:"fees"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// AccountFees stores withdrawal account fee data from Bitfinex
|
||||
|
||||
@@ -1,87 +1,80 @@
|
||||
package bitfinex
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
func TestWebsocketPingHandler(t *testing.T) {
|
||||
wsPingHandler := Bitfinex{}
|
||||
var Dialer websocket.Dialer
|
||||
var err error
|
||||
|
||||
wsPingHandler.WebsocketConn, _, err = Dialer.Dial(bitfinexWebsocket, http.Header{})
|
||||
if err != nil {
|
||||
t.Errorf("Test Failed - Bitfinex dialer error: %s", err)
|
||||
}
|
||||
err = wsPingHandler.WebsocketPingHandler()
|
||||
if err != nil {
|
||||
t.Errorf("Test Failed - Bitfinex WebsocketPingHandler() error: %s", err)
|
||||
}
|
||||
err = wsPingHandler.WebsocketConn.Close()
|
||||
if err != nil {
|
||||
t.Errorf("Test Failed - Bitfinex websocketConn.Close() error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWebsocketSubscribe(t *testing.T) {
|
||||
websocketSubcribe := Bitfinex{}
|
||||
var Dialer websocket.Dialer
|
||||
var err error
|
||||
params := make(map[string]string)
|
||||
params["pair"] = "BTCUSD"
|
||||
|
||||
websocketSubcribe.WebsocketConn, _, err = Dialer.Dial(bitfinexWebsocket, http.Header{})
|
||||
if err != nil {
|
||||
t.Errorf("Test Failed - Bitfinex Dialer error: %s", err)
|
||||
}
|
||||
err = websocketSubcribe.WebsocketSubscribe("ticker", params)
|
||||
if err != nil {
|
||||
t.Errorf("Test Failed - Bitfinex WebsocketSubscribe() error: %s", err)
|
||||
}
|
||||
|
||||
err = websocketSubcribe.WebsocketConn.Close()
|
||||
if err != nil {
|
||||
t.Errorf("Test Failed - Bitfinex websocketConn.Close() error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWebsocketSendAuth(t *testing.T) {
|
||||
wsSendAuth := Bitfinex{}
|
||||
var Dialer websocket.Dialer
|
||||
var err error
|
||||
|
||||
wsSendAuth.WebsocketConn, _, err = Dialer.Dial(bitfinexWebsocket, http.Header{})
|
||||
if err != nil {
|
||||
t.Errorf("Test Failed - Bitfinex Dialer error: %s", err)
|
||||
}
|
||||
err = wsSendAuth.WebsocketSendAuth()
|
||||
if err != nil {
|
||||
t.Errorf("Test Failed - Bitfinex WebsocketSendAuth() error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWebsocketAddSubscriptionChannel(t *testing.T) {
|
||||
wsAddSubscriptionChannel := Bitfinex{}
|
||||
wsAddSubscriptionChannel.SetDefaults()
|
||||
var Dialer websocket.Dialer
|
||||
var err error
|
||||
|
||||
wsAddSubscriptionChannel.WebsocketConn, _, err = Dialer.Dial(bitfinexWebsocket, http.Header{})
|
||||
if err != nil {
|
||||
t.Errorf("Test Failed - Bitfinex Dialer error: %s", err)
|
||||
}
|
||||
|
||||
wsAddSubscriptionChannel.WebsocketAddSubscriptionChannel(1337, "ticker", "BTCUSD")
|
||||
if len(wsAddSubscriptionChannel.WebsocketSubdChannels) == 0 {
|
||||
t.Errorf("Test Failed - Bitfinex WebsocketAddSubscriptionChannel() error: %s", err)
|
||||
}
|
||||
if wsAddSubscriptionChannel.WebsocketSubdChannels[1337].Channel != "ticker" {
|
||||
t.Errorf("Test Failed - Bitfinex WebsocketAddSubscriptionChannel() error: %s", err)
|
||||
}
|
||||
if wsAddSubscriptionChannel.WebsocketSubdChannels[1337].Pair != "BTCUSD" {
|
||||
t.Errorf("Test Failed - Bitfinex WebsocketAddSubscriptionChannel() error: %s", err)
|
||||
}
|
||||
}
|
||||
// func TestWebsocketPingHandler(t *testing.T) {
|
||||
// wsPingHandler := Bitfinex{}
|
||||
// var Dialer websocket.Dialer
|
||||
// var err error
|
||||
//
|
||||
// wsPingHandler.WebsocketConn, _, err = Dialer.Dial(bitfinexWebsocket, http.Header{})
|
||||
// if err != nil {
|
||||
// t.Errorf("Test Failed - Bitfinex dialer error: %s", err)
|
||||
// }
|
||||
// err = wsPingHandler.WebsocketPingHandler()
|
||||
// if err != nil {
|
||||
// t.Errorf("Test Failed - Bitfinex WebsocketPingHandler() error: %s", err)
|
||||
// }
|
||||
// err = wsPingHandler.WebsocketConn.Close()
|
||||
// if err != nil {
|
||||
// t.Errorf("Test Failed - Bitfinex websocketConn.Close() error: %s", err)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// func TestWebsocketSubscribe(t *testing.T) {
|
||||
// websocketSubcribe := Bitfinex{}
|
||||
// var Dialer websocket.Dialer
|
||||
// var err error
|
||||
// params := make(map[string]string)
|
||||
// params["pair"] = "BTCUSD"
|
||||
//
|
||||
// websocketSubcribe.WebsocketConn, _, err = Dialer.Dial(bitfinexWebsocket, http.Header{})
|
||||
// if err != nil {
|
||||
// t.Errorf("Test Failed - Bitfinex Dialer error: %s", err)
|
||||
// }
|
||||
// err = websocketSubcribe.WebsocketSubscribe("ticker", params)
|
||||
// if err != nil {
|
||||
// t.Errorf("Test Failed - Bitfinex WebsocketSubscribe() error: %s", err)
|
||||
// }
|
||||
//
|
||||
// err = websocketSubcribe.WebsocketConn.Close()
|
||||
// if err != nil {
|
||||
// t.Errorf("Test Failed - Bitfinex websocketConn.Close() error: %s", err)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// func TestWebsocketSendAuth(t *testing.T) {
|
||||
// wsSendAuth := Bitfinex{}
|
||||
// var Dialer websocket.Dialer
|
||||
// var err error
|
||||
//
|
||||
// wsSendAuth.WebsocketConn, _, err = Dialer.Dial(bitfinexWebsocket, http.Header{})
|
||||
// if err != nil {
|
||||
// t.Errorf("Test Failed - Bitfinex Dialer error: %s", err)
|
||||
// }
|
||||
// err = wsSendAuth.WebsocketSendAuth()
|
||||
// if err != nil {
|
||||
// t.Errorf("Test Failed - Bitfinex WebsocketSendAuth() error: %s", err)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// func TestWebsocketAddSubscriptionChannel(t *testing.T) {
|
||||
// wsAddSubscriptionChannel := Bitfinex{}
|
||||
// wsAddSubscriptionChannel.SetDefaults()
|
||||
// var Dialer websocket.Dialer
|
||||
// var err error
|
||||
//
|
||||
// wsAddSubscriptionChannel.WebsocketConn, _, err = Dialer.Dial(bitfinexWebsocket, http.Header{})
|
||||
// if err != nil {
|
||||
// t.Errorf("Test Failed - Bitfinex Dialer error: %s", err)
|
||||
// }
|
||||
//
|
||||
// wsAddSubscriptionChannel.WebsocketAddSubscriptionChannel(1337, "ticker", "BTCUSD")
|
||||
// if len(wsAddSubscriptionChannel.WebsocketSubdChannels) == 0 {
|
||||
// t.Errorf("Test Failed - Bitfinex WebsocketAddSubscriptionChannel() error: %s", err)
|
||||
// }
|
||||
// if wsAddSubscriptionChannel.WebsocketSubdChannels[1337].Channel != "ticker" {
|
||||
// t.Errorf("Test Failed - Bitfinex WebsocketAddSubscriptionChannel() error: %s", err)
|
||||
// }
|
||||
// if wsAddSubscriptionChannel.WebsocketSubdChannels[1337].Pair != "BTCUSD" {
|
||||
// t.Errorf("Test Failed - Bitfinex WebsocketAddSubscriptionChannel() error: %s", err)
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -1,37 +1,30 @@
|
||||
package bitfinex
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/currency/pair"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
func TestStart(t *testing.T) {
|
||||
start := Bitfinex{}
|
||||
start.Start()
|
||||
}
|
||||
|
||||
func TestRun(t *testing.T) {
|
||||
run := Bitfinex{}
|
||||
run.Run()
|
||||
}
|
||||
|
||||
func TestGetTickerPrice(t *testing.T) {
|
||||
getTickerPrice := Bitfinex{}
|
||||
getTickerPrice.EnabledPairs = []string{"BTCUSD", "LTCUSD"}
|
||||
_, err := getTickerPrice.GetTickerPrice(pair.NewCurrencyPair("BTC", "USD"),
|
||||
ticker.Spot)
|
||||
if err != nil {
|
||||
t.Errorf("Test Failed - Bitfinex GetTickerPrice() error: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetOrderbookEx(t *testing.T) {
|
||||
getOrderBookEx := Bitfinex{}
|
||||
_, err := getOrderBookEx.GetOrderbookEx(pair.NewCurrencyPair("BTC", "USD"),
|
||||
ticker.Spot)
|
||||
if err != nil {
|
||||
t.Errorf("Test Failed - Bitfinex GetOrderbookEx() error: %s", err)
|
||||
}
|
||||
}
|
||||
// func TestStart(t *testing.T) {
|
||||
// start := Bitfinex{}
|
||||
// start.Start()
|
||||
// }
|
||||
//
|
||||
// func TestRun(t *testing.T) {
|
||||
// run := Bitfinex{}
|
||||
// run.Run()
|
||||
// }
|
||||
//
|
||||
// func TestGetTickerPrice(t *testing.T) {
|
||||
// getTickerPrice := Bitfinex{}
|
||||
// getTickerPrice.EnabledPairs = []string{"BTCUSD", "LTCUSD"}
|
||||
// _, err := getTickerPrice.GetTickerPrice(pair.NewCurrencyPair("BTC", "USD"),
|
||||
// ticker.Spot)
|
||||
// if err != nil {
|
||||
// t.Errorf("Test Failed - Bitfinex GetTickerPrice() error: %s", err)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// func TestGetOrderbookEx(t *testing.T) {
|
||||
// getOrderBookEx := Bitfinex{}
|
||||
// _, err := getOrderBookEx.GetOrderbookEx(pair.NewCurrencyPair("BTC", "USD"),
|
||||
// ticker.Spot)
|
||||
// if err != nil {
|
||||
// t.Errorf("Test Failed - Bitfinex GetOrderbookEx() error: %s", err)
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
@@ -11,6 +12,7 @@ import (
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
@@ -63,11 +65,15 @@ const (
|
||||
privOpenInterest = "/me/getpositions"
|
||||
privMarginChange = "/me/getcollateralhistory"
|
||||
privTradingCommission = "/me/gettradingcommission"
|
||||
|
||||
bitflyerAuthRate = 1000
|
||||
bitflyerUnauthRate = 1000
|
||||
)
|
||||
|
||||
// Bitflyer is the overarching type across this package
|
||||
type Bitflyer struct {
|
||||
exchange.Base
|
||||
*request.Handler
|
||||
}
|
||||
|
||||
// SetDefaults sets the basic defaults for Bitflyer
|
||||
@@ -83,6 +89,8 @@ func (b *Bitflyer) SetDefaults() {
|
||||
b.ConfigCurrencyPairFormat.Uppercase = true
|
||||
b.AssetTypes = []string{ticker.Spot}
|
||||
b.SupportsAutoPairUpdating = false
|
||||
b.Handler = new(request.Handler)
|
||||
b.SetRequestHandler(b.Name, bitflyerAuthRate, bitflyerUnauthRate, new(http.Client))
|
||||
}
|
||||
|
||||
// Setup takes in the supplied exchange configuration details and sets params
|
||||
@@ -121,7 +129,7 @@ func (b *Bitflyer) GetLatestBlockCA() (ChainAnalysisBlock, error) {
|
||||
var resp ChainAnalysisBlock
|
||||
path := fmt.Sprintf("%s%s", chainAnalysis, latestBlock)
|
||||
|
||||
return resp, common.SendHTTPGetRequest(path, true, b.Verbose, &resp)
|
||||
return resp, b.SendHTTPREquest(path, &resp)
|
||||
}
|
||||
|
||||
// GetBlockCA returns block information by blockhash from bitflyer chain
|
||||
@@ -130,7 +138,7 @@ func (b *Bitflyer) GetBlockCA(blockhash string) (ChainAnalysisBlock, error) {
|
||||
var resp ChainAnalysisBlock
|
||||
path := fmt.Sprintf("%s%s%s", chainAnalysis, blockByBlockHash, blockhash)
|
||||
|
||||
return resp, common.SendHTTPGetRequest(path, true, b.Verbose, &resp)
|
||||
return resp, b.SendHTTPREquest(path, &resp)
|
||||
}
|
||||
|
||||
// GetBlockbyHeightCA returns the block information by height from bitflyer chain
|
||||
@@ -139,7 +147,7 @@ func (b *Bitflyer) GetBlockbyHeightCA(height int64) (ChainAnalysisBlock, error)
|
||||
var resp ChainAnalysisBlock
|
||||
path := fmt.Sprintf("%s%s%s", chainAnalysis, blockByBlockHeight, strconv.FormatInt(height, 10))
|
||||
|
||||
return resp, common.SendHTTPGetRequest(path, true, b.Verbose, &resp)
|
||||
return resp, b.SendHTTPREquest(path, &resp)
|
||||
}
|
||||
|
||||
// GetTransactionByHashCA returns transaction information by txHash from
|
||||
@@ -148,7 +156,7 @@ func (b *Bitflyer) GetTransactionByHashCA(txHash string) (ChainAnalysisTransacti
|
||||
var resp ChainAnalysisTransaction
|
||||
path := fmt.Sprintf("%s%s%s", chainAnalysis, transaction, txHash)
|
||||
|
||||
return resp, common.SendHTTPGetRequest(path, true, b.Verbose, &resp)
|
||||
return resp, b.SendHTTPREquest(path, &resp)
|
||||
}
|
||||
|
||||
// GetAddressInfoCA returns balance information for address by addressln string
|
||||
@@ -157,7 +165,7 @@ func (b *Bitflyer) GetAddressInfoCA(addressln string) (ChainAnalysisAddress, err
|
||||
var resp ChainAnalysisAddress
|
||||
path := fmt.Sprintf("%s%s%s", chainAnalysis, address, addressln)
|
||||
|
||||
return resp, common.SendHTTPGetRequest(path, true, b.Verbose, &resp)
|
||||
return resp, b.SendHTTPREquest(path, &resp)
|
||||
}
|
||||
|
||||
// GetMarkets returns market information
|
||||
@@ -165,7 +173,7 @@ func (b *Bitflyer) GetMarkets() ([]MarketInfo, error) {
|
||||
var resp []MarketInfo
|
||||
path := fmt.Sprintf("%s%s", b.APIUrl, pubGetMarkets)
|
||||
|
||||
return resp, common.SendHTTPGetRequest(path, true, b.Verbose, &resp)
|
||||
return resp, b.SendHTTPREquest(path, &resp)
|
||||
}
|
||||
|
||||
// GetOrderBook returns market orderbook depth
|
||||
@@ -175,7 +183,7 @@ func (b *Bitflyer) GetOrderBook(symbol string) (Orderbook, error) {
|
||||
v.Set("product_code", symbol)
|
||||
path := fmt.Sprintf("%s%s?%s", japanURL, pubGetBoard, v.Encode())
|
||||
|
||||
return resp, common.SendHTTPGetRequest(path, true, b.Verbose, &resp)
|
||||
return resp, b.SendHTTPREquest(path, &resp)
|
||||
}
|
||||
|
||||
// GetTicker returns ticker information
|
||||
@@ -185,7 +193,7 @@ func (b *Bitflyer) GetTicker(symbol string) (Ticker, error) {
|
||||
v.Set("product_code", symbol)
|
||||
path := fmt.Sprintf("%s%s?%s", japanURL, pubGetTicker, v.Encode())
|
||||
|
||||
return resp, common.SendHTTPGetRequest(path, true, b.Verbose, &resp)
|
||||
return resp, b.SendHTTPREquest(path, &resp)
|
||||
}
|
||||
|
||||
// GetExecutionHistory returns past trades that were executed on the market
|
||||
@@ -195,7 +203,7 @@ func (b *Bitflyer) GetExecutionHistory(symbol string) ([]ExecutedTrade, error) {
|
||||
v.Set("product_code", symbol)
|
||||
path := fmt.Sprintf("%s%s?%s", japanURL, pubGetExecutionHistory, v.Encode())
|
||||
|
||||
return resp, common.SendHTTPGetRequest(path, true, b.Verbose, &resp)
|
||||
return resp, b.SendHTTPREquest(path, &resp)
|
||||
}
|
||||
|
||||
// GetExchangeStatus returns exchange status information
|
||||
@@ -204,7 +212,7 @@ func (b *Bitflyer) GetExchangeStatus() (string, error) {
|
||||
|
||||
path := fmt.Sprintf("%s%s", b.APIUrl, pubGetHealth)
|
||||
|
||||
err := common.SendHTTPGetRequest(path, true, b.Verbose, &resp)
|
||||
err := b.SendHTTPREquest(path, &resp)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -231,7 +239,7 @@ func (b *Bitflyer) GetChats(FromDate string) ([]ChatLog, error) {
|
||||
v.Set("from_date", FromDate)
|
||||
path := fmt.Sprintf("%s%s?%s", b.APIUrl, pubGetChats, v.Encode())
|
||||
|
||||
return resp, common.SendHTTPGetRequest(path, true, b.Verbose, &resp)
|
||||
return resp, b.SendHTTPREquest(path, &resp)
|
||||
}
|
||||
|
||||
// GetPermissions returns current permissions for associated with your API
|
||||
@@ -350,6 +358,11 @@ func (b *Bitflyer) GetTradingCommission() {
|
||||
// Needs to be updated
|
||||
}
|
||||
|
||||
// SendHTTPREquest sends an unauthenticated request
|
||||
func (b *Bitflyer) SendHTTPREquest(path string, result interface{}) error {
|
||||
return b.SendPayload("GET", path, nil, nil, result, false, b.Verbose)
|
||||
}
|
||||
|
||||
// SendAuthHTTPRequest sends an authenticated HTTP request
|
||||
// Note: HTTP not done due to incorrect account privileges, please open a PR
|
||||
// if you have access and update the authenticated requests
|
||||
|
||||
@@ -127,23 +127,23 @@ func TestGetExchangeStatus(t *testing.T) {
|
||||
// }
|
||||
// }
|
||||
|
||||
func TestUpdateTicker(t *testing.T) {
|
||||
t.Parallel()
|
||||
p := pair.NewCurrencyPairFromString("BTC_JPY")
|
||||
_, err := b.UpdateTicker(p, "SPOT")
|
||||
if err != nil {
|
||||
t.Error("test failed - Bitflyer - UpdateTicker() error:", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateOrderbook(t *testing.T) {
|
||||
t.Parallel()
|
||||
p := pair.NewCurrencyPairFromString("BTC_JPY")
|
||||
_, err := b.UpdateOrderbook(p, "SPOT")
|
||||
if err != nil {
|
||||
t.Error("test failed - Bitflyer - UpdateOrderbook() error:", err)
|
||||
}
|
||||
}
|
||||
// func TestUpdateTicker(t *testing.T) {
|
||||
// t.Parallel()
|
||||
// p := pair.NewCurrencyPairFromString("BTC_JPY")
|
||||
// _, err := b.UpdateTicker(p, "SPOT")
|
||||
// if err != nil {
|
||||
// t.Error("test failed - Bitflyer - UpdateTicker() error:", err)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// func TestUpdateOrderbook(t *testing.T) {
|
||||
// t.Parallel()
|
||||
// p := pair.NewCurrencyPairFromString("BTC_JPY")
|
||||
// _, err := b.UpdateOrderbook(p, "SPOT")
|
||||
// if err != nil {
|
||||
// t.Error("test failed - Bitflyer - UpdateOrderbook() error:", err)
|
||||
// }
|
||||
// }
|
||||
|
||||
func TestCheckFXString(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
@@ -12,6 +13,7 @@ import (
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
@@ -44,11 +46,15 @@ const (
|
||||
privateKRWWithdraw = "/trade/krw_withdrawal"
|
||||
privateMarketBuy = "/trade/market_buy"
|
||||
privateMarketSell = "/trade/market_sell"
|
||||
|
||||
bithumbAuthRate = 100
|
||||
bithumbUnathRate = 100
|
||||
)
|
||||
|
||||
// Bithumb is the overarching type across the Bithumb package
|
||||
type Bithumb struct {
|
||||
exchange.Base
|
||||
*request.Handler
|
||||
}
|
||||
|
||||
// SetDefaults sets the basic defaults for Bithumb
|
||||
@@ -65,6 +71,8 @@ func (b *Bithumb) SetDefaults() {
|
||||
b.ConfigCurrencyPairFormat.Index = "KRW"
|
||||
b.AssetTypes = []string{ticker.Spot}
|
||||
b.SupportsAutoPairUpdating = false
|
||||
b.Handler = new(request.Handler)
|
||||
b.SetRequestHandler(b.Name, bithumbAuthRate, bithumbUnathRate, new(http.Client))
|
||||
}
|
||||
|
||||
// Setup takes in the supplied exchange configuration details and sets params
|
||||
@@ -103,7 +111,7 @@ func (b *Bithumb) GetTicker(symbol string) (Ticker, error) {
|
||||
response := Ticker{}
|
||||
path := fmt.Sprintf("%s%s%s", apiURL, publicTicker, common.StringToUpper(symbol))
|
||||
|
||||
return response, common.SendHTTPGetRequest(path, true, b.Verbose, &response)
|
||||
return response, b.SendHTTPRequest(path, &response)
|
||||
}
|
||||
|
||||
// GetOrderBook returns current orderbook
|
||||
@@ -113,7 +121,7 @@ func (b *Bithumb) GetOrderBook(symbol string) (Orderbook, error) {
|
||||
response := Orderbook{}
|
||||
path := fmt.Sprintf("%s%s%s", apiURL, publicOrderBook, common.StringToUpper(symbol))
|
||||
|
||||
return response, common.SendHTTPGetRequest(path, true, b.Verbose, &response)
|
||||
return response, b.SendHTTPRequest(path, &response)
|
||||
}
|
||||
|
||||
// GetRecentTransactions returns recent transactions
|
||||
@@ -123,7 +131,7 @@ func (b *Bithumb) GetRecentTransactions(symbol string) (RecentTransactions, erro
|
||||
response := RecentTransactions{}
|
||||
path := fmt.Sprintf("%s%s%s", apiURL, publicRecentTransaction, common.StringToUpper(symbol))
|
||||
|
||||
return response, common.SendHTTPGetRequest(path, true, b.Verbose, &response)
|
||||
return response, b.SendHTTPRequest(path, &response)
|
||||
}
|
||||
|
||||
// GetAccountInfo returns account information
|
||||
@@ -424,6 +432,11 @@ func (b *Bithumb) MarketSellOrder(currency string, units float64) (MarketSell, e
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (b *Bithumb) SendHTTPRequest(path string, result interface{}) error {
|
||||
return b.SendPayload("GET", path, nil, nil, result, false, b.Verbose)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request to bithumb
|
||||
func (b *Bithumb) SendAuthenticatedHTTPRequest(path string, params url.Values, result interface{}) error {
|
||||
if !b.AuthenticatedAPISupport {
|
||||
@@ -452,19 +465,5 @@ func (b *Bithumb) SendAuthenticatedHTTPRequest(path string, params url.Values, r
|
||||
headers["Api-Nonce"] = b.Nonce.String()
|
||||
headers["Content-Type"] = "application/x-www-form-urlencoded"
|
||||
|
||||
resp, err := common.SendHTTPRequest(
|
||||
"POST", apiURL+path, headers, bytes.NewBufferString(payload),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if b.Verbose {
|
||||
log.Printf("Received raw: \n%s\n", resp)
|
||||
}
|
||||
|
||||
if err = common.JSONDecode([]byte(resp), &result); err != nil {
|
||||
return errors.New("sendAuthenticatedHTTPRequest: Unable to JSON Unmarshal response." + err.Error())
|
||||
}
|
||||
return nil
|
||||
return b.SendPayload("POST", apiURL+path, headers, bytes.NewBufferString(payload), result, true, b.Verbose)
|
||||
}
|
||||
|
||||
@@ -169,34 +169,34 @@ func TestMarketSellOrder(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRun(t *testing.T) {
|
||||
t.Parallel()
|
||||
b.Run()
|
||||
}
|
||||
|
||||
func TestUpdateTicker(t *testing.T) {
|
||||
t.Parallel()
|
||||
pair := b.GetEnabledCurrencies()[0]
|
||||
_, err := b.UpdateTicker(pair, b.AssetTypes[0])
|
||||
if err != nil {
|
||||
t.Error("test failed - Bithumb UpdateTicker() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTickerPrice(t *testing.T) {
|
||||
t.Parallel()
|
||||
pair := b.GetEnabledCurrencies()[0]
|
||||
_, err := b.GetTickerPrice(pair, b.AssetTypes[0])
|
||||
if err != nil {
|
||||
t.Error("test failed - Bithumb GetTickerPrice() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetOrderbookEx(t *testing.T) {
|
||||
t.Parallel()
|
||||
pair := b.GetEnabledCurrencies()[0]
|
||||
_, err := b.GetOrderbookEx(pair, b.AssetTypes[0])
|
||||
if err != nil {
|
||||
t.Error("test failed - Bithumb GetOrderbookEx() error", err)
|
||||
}
|
||||
}
|
||||
// func TestRun(t *testing.T) {
|
||||
// t.Parallel()
|
||||
// b.Run()
|
||||
// }
|
||||
//
|
||||
// func TestUpdateTicker(t *testing.T) {
|
||||
// t.Parallel()
|
||||
// pair := b.GetEnabledCurrencies()[0]
|
||||
// _, err := b.UpdateTicker(pair, b.AssetTypes[0])
|
||||
// if err != nil {
|
||||
// t.Error("test failed - Bithumb UpdateTicker() error", err)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// func TestGetTickerPrice(t *testing.T) {
|
||||
// t.Parallel()
|
||||
// pair := b.GetEnabledCurrencies()[0]
|
||||
// _, err := b.GetTickerPrice(pair, b.AssetTypes[0])
|
||||
// if err != nil {
|
||||
// t.Error("test failed - Bithumb GetTickerPrice() error", err)
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// func TestGetOrderbookEx(t *testing.T) {
|
||||
// t.Parallel()
|
||||
// pair := b.GetEnabledCurrencies()[0]
|
||||
// _, err := b.GetOrderbookEx(pair, b.AssetTypes[0])
|
||||
// if err != nil {
|
||||
// t.Error("test failed - Bithumb GetOrderbookEx() error", err)
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strconv"
|
||||
@@ -13,6 +14,7 @@ import (
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
@@ -47,12 +49,16 @@ const (
|
||||
bitstampAPIXrpDeposit = "xrp_address"
|
||||
bitstampAPIReturnType = "string"
|
||||
bitstampAPITradingPairsInfo = "trading-pairs-info"
|
||||
|
||||
bitstampAuthRate = 0
|
||||
bitstampUnauthRate = 0
|
||||
)
|
||||
|
||||
// Bitstamp is the overarching type across the bitstamp package
|
||||
type Bitstamp struct {
|
||||
exchange.Base
|
||||
Balance Balances
|
||||
*request.Handler
|
||||
}
|
||||
|
||||
// SetDefaults sets default for Bitstamp
|
||||
@@ -68,6 +74,8 @@ func (b *Bitstamp) SetDefaults() {
|
||||
b.ConfigCurrencyPairFormat.Uppercase = true
|
||||
b.AssetTypes = []string{ticker.Spot}
|
||||
b.SupportsAutoPairUpdating = true
|
||||
b.Handler = new(request.Handler)
|
||||
b.SetRequestHandler(b.Name, bitstampAuthRate, bitstampUnauthRate, new(http.Client))
|
||||
}
|
||||
|
||||
// Setup sets configuration values to bitstamp
|
||||
@@ -133,7 +141,7 @@ func (b *Bitstamp) GetTicker(currency string, hourly bool) (Ticker, error) {
|
||||
tickerEndpoint,
|
||||
common.StringToLower(currency),
|
||||
)
|
||||
return response, common.SendHTTPGetRequest(path, true, b.Verbose, &response)
|
||||
return response, b.SendHTTPRequest(path, &response)
|
||||
}
|
||||
|
||||
// GetOrderbook Returns a JSON dictionary with "bids" and "asks". Each is a list
|
||||
@@ -155,7 +163,7 @@ func (b *Bitstamp) GetOrderbook(currency string) (Orderbook, error) {
|
||||
common.StringToLower(currency),
|
||||
)
|
||||
|
||||
err := common.SendHTTPGetRequest(path, true, b.Verbose, &resp)
|
||||
err := b.SendHTTPRequest(path, &resp)
|
||||
if err != nil {
|
||||
return Orderbook{}, err
|
||||
}
|
||||
@@ -218,7 +226,7 @@ func (b *Bitstamp) GetTransactions(currencyPair string, values url.Values) ([]Tr
|
||||
values,
|
||||
)
|
||||
|
||||
return transactions, common.SendHTTPGetRequest(path, true, b.Verbose, &transactions)
|
||||
return transactions, b.SendHTTPRequest(path, &transactions)
|
||||
}
|
||||
|
||||
// GetEURUSDConversionRate returns the conversion rate between Euro and USD
|
||||
@@ -226,15 +234,15 @@ func (b *Bitstamp) GetEURUSDConversionRate() (EURUSDConversionRate, error) {
|
||||
rate := EURUSDConversionRate{}
|
||||
path := fmt.Sprintf("%s/%s", bitstampAPIURL, bitstampAPIEURUSD)
|
||||
|
||||
return rate, common.SendHTTPGetRequest(path, true, b.Verbose, &rate)
|
||||
return rate, b.SendHTTPRequest(path, &rate)
|
||||
}
|
||||
|
||||
// GetBalance returns full balance of currency held on the exchange
|
||||
func (b *Bitstamp) GetBalance() (Balances, error) {
|
||||
balance := Balances{}
|
||||
path := fmt.Sprintf("%s/%s", bitstampAPIURL, bitstampAPIBalance)
|
||||
|
||||
return balance,
|
||||
b.SendAuthenticatedHTTPRequest(bitstampAPIBalance, true, url.Values{}, &balance)
|
||||
return balance, b.SendHTTPRequest(path, &balance)
|
||||
}
|
||||
|
||||
// GetUserTransactions returns an array of transactions
|
||||
@@ -484,6 +492,11 @@ func (b *Bitstamp) TransferAccountBalance(amount float64, currency, subAccount s
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (b *Bitstamp) SendHTTPRequest(path string, result interface{}) error {
|
||||
return b.SendPayload("GET", path, nil, nil, result, false, b.Verbose)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated request
|
||||
func (b *Bitstamp) SendAuthenticatedHTTPRequest(path string, v2 bool, values url.Values, result interface{}) (err error) {
|
||||
if !b.AuthenticatedAPISupport {
|
||||
@@ -518,26 +531,5 @@ func (b *Bitstamp) SendAuthenticatedHTTPRequest(path string, v2 bool, values url
|
||||
headers := make(map[string]string)
|
||||
headers["Content-Type"] = "application/x-www-form-urlencoded"
|
||||
|
||||
resp, err := common.SendHTTPRequest("POST", path, headers, strings.NewReader(values.Encode()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if b.Verbose {
|
||||
log.Printf("Received raw: %s\n", resp)
|
||||
}
|
||||
|
||||
/* inconsistent errors, needs to be improved when in production*/
|
||||
if common.StringContains(resp, "500 error") {
|
||||
return errors.New("internal server: code 500")
|
||||
}
|
||||
|
||||
capture := CaptureError{}
|
||||
if err = common.JSONDecode([]byte(resp), &capture); err == nil {
|
||||
if capture.Code != nil || capture.Error != nil || capture.Reason != nil || capture.Status != nil {
|
||||
errstring := fmt.Sprint("Status: ", capture.Status, ", Issue: ", capture.Error, ", Reason: ", capture.Reason, ", Code: ", capture.Code)
|
||||
return errors.New(errstring)
|
||||
}
|
||||
}
|
||||
return common.JSONDecode([]byte(resp), &result)
|
||||
return b.SendPayload("POST", path, headers, strings.NewReader(values.Encode()), result, true, b.Verbose)
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@ const (
|
||||
customerID = ""
|
||||
)
|
||||
|
||||
var b Bitstamp
|
||||
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Bitstamp{}
|
||||
b.SetDefaults()
|
||||
|
||||
if b.Name != "Bitstamp" {
|
||||
@@ -38,17 +38,12 @@ func TestSetDefaults(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Bitstamp{}
|
||||
b.Name = "Bitstamp"
|
||||
cfg := config.GetConfig()
|
||||
cfg.LoadConfig("../../testdata/configtest.json")
|
||||
bConfig, err := cfg.GetExchangeConfig("Bitstamp")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - Bitstamp Setup() init error")
|
||||
}
|
||||
|
||||
b.SetDefaults()
|
||||
b.Setup(bConfig)
|
||||
|
||||
if !b.IsEnabled() || b.AuthenticatedAPISupport || b.RESTPollingDelay != time.Duration(10) ||
|
||||
@@ -56,33 +51,13 @@ func TestSetup(t *testing.T) {
|
||||
len(b.AvailablePairs) < 1 || len(b.EnabledPairs) < 1 {
|
||||
t.Error("Test Failed - Bitstamp Setup values not set correctly")
|
||||
}
|
||||
|
||||
bConfig.Enabled = false
|
||||
b.Setup(bConfig)
|
||||
|
||||
if b.IsEnabled() {
|
||||
t.Error("Test failed - Bitstamp TestSetup incorrect value")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetFee(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Bitstamp{}
|
||||
if resp := b.GetFee("BTCUSD"); resp != 0 {
|
||||
t.Error("Test Failed - GetFee() error")
|
||||
}
|
||||
if resp := b.GetFee("BTCEUR"); resp != 0 {
|
||||
t.Error("Test Failed - GetFee() error")
|
||||
}
|
||||
if resp := b.GetFee("XRPEUR"); resp != 0 {
|
||||
t.Error("Test Failed - GetFee() error")
|
||||
}
|
||||
if resp := b.GetFee("XRPUSD"); resp != 0 {
|
||||
t.Error("Test Failed - GetFee() error")
|
||||
}
|
||||
if resp := b.GetFee("EURUSD"); resp != 0 {
|
||||
t.Error("Test Failed - GetFee() error")
|
||||
}
|
||||
if resp := b.GetFee("bla"); resp != 0 {
|
||||
t.Error("Test Failed - GetFee() error")
|
||||
}
|
||||
@@ -90,7 +65,6 @@ func TestGetFee(t *testing.T) {
|
||||
|
||||
func TestGetTicker(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Bitstamp{}
|
||||
_, err := b.GetTicker("BTCUSD", false)
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetTicker() error", err)
|
||||
@@ -103,7 +77,6 @@ func TestGetTicker(t *testing.T) {
|
||||
|
||||
func TestGetOrderbook(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Bitstamp{}
|
||||
_, err := b.GetOrderbook("BTCUSD")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetOrderbook() error", err)
|
||||
@@ -121,8 +94,6 @@ func TestGetTradingPairs(t *testing.T) {
|
||||
|
||||
func TestGetTransactions(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Bitstamp{}
|
||||
|
||||
value := url.Values{}
|
||||
value.Set("time", "hour")
|
||||
|
||||
@@ -138,7 +109,6 @@ func TestGetTransactions(t *testing.T) {
|
||||
|
||||
func TestGetEURUSDConversionRate(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Bitstamp{}
|
||||
_, err := b.GetEURUSDConversionRate()
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetEURUSDConversionRate() error", err)
|
||||
@@ -147,24 +117,14 @@ func TestGetEURUSDConversionRate(t *testing.T) {
|
||||
|
||||
func TestGetBalance(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Bitstamp{}
|
||||
b.APIKey = apiKey
|
||||
b.APISecret = apiSecret
|
||||
b.ClientID = customerID
|
||||
|
||||
_, err := b.GetBalance()
|
||||
if err == nil {
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetBalance() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetUserTransactions(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Bitstamp{}
|
||||
b.APIKey = apiKey
|
||||
b.APISecret = apiSecret
|
||||
b.ClientID = customerID
|
||||
|
||||
_, err := b.GetUserTransactions("")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetUserTransactions() error", err)
|
||||
@@ -178,10 +138,6 @@ func TestGetUserTransactions(t *testing.T) {
|
||||
|
||||
func TestGetOpenOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Bitstamp{}
|
||||
b.APIKey = apiKey
|
||||
b.APISecret = apiSecret
|
||||
b.ClientID = customerID
|
||||
|
||||
_, err := b.GetOpenOrders("btcusd")
|
||||
if err == nil {
|
||||
@@ -195,10 +151,6 @@ func TestGetOpenOrders(t *testing.T) {
|
||||
|
||||
func TestGetOrderStatus(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Bitstamp{}
|
||||
b.APIKey = apiKey
|
||||
b.APISecret = apiSecret
|
||||
b.ClientID = customerID
|
||||
|
||||
_, err := b.GetOrderStatus(1337)
|
||||
if err == nil {
|
||||
@@ -208,10 +160,6 @@ func TestGetOrderStatus(t *testing.T) {
|
||||
|
||||
func TestCancelOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Bitstamp{}
|
||||
b.APIKey = apiKey
|
||||
b.APISecret = apiSecret
|
||||
b.ClientID = customerID
|
||||
|
||||
resp, err := b.CancelOrder(1337)
|
||||
if err == nil || resp != false {
|
||||
@@ -221,10 +169,6 @@ func TestCancelOrder(t *testing.T) {
|
||||
|
||||
func TestCancelAllOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Bitstamp{}
|
||||
b.APIKey = apiKey
|
||||
b.APISecret = apiSecret
|
||||
b.ClientID = customerID
|
||||
|
||||
_, err := b.CancelAllOrders()
|
||||
if err == nil {
|
||||
@@ -234,35 +178,15 @@ func TestCancelAllOrders(t *testing.T) {
|
||||
|
||||
func TestPlaceOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Bitstamp{}
|
||||
b.APIKey = apiKey
|
||||
b.APISecret = apiSecret
|
||||
b.ClientID = customerID
|
||||
|
||||
_, err := b.PlaceOrder("btcusd", 0.01, 1, true, true)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - PlaceOrder() error")
|
||||
}
|
||||
_, err = b.PlaceOrder("btcusd", 0.01, 1, true, false)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - PlaceOrder() error")
|
||||
}
|
||||
_, err = b.PlaceOrder("btcusd", 0.01, 1, false, false)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - PlaceOrder() error")
|
||||
}
|
||||
_, err = b.PlaceOrder("wigwham", 0.01, 1, false, false)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - PlaceOrder() error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetWithdrawalRequests(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Bitstamp{}
|
||||
b.APIKey = apiKey
|
||||
b.APISecret = apiSecret
|
||||
b.ClientID = customerID
|
||||
|
||||
_, err := b.GetWithdrawalRequests(0)
|
||||
if err == nil {
|
||||
@@ -276,72 +200,24 @@ func TestGetWithdrawalRequests(t *testing.T) {
|
||||
|
||||
func TestCryptoWithdrawal(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Bitstamp{}
|
||||
b.APIKey = apiKey
|
||||
b.APISecret = apiSecret
|
||||
b.ClientID = customerID
|
||||
|
||||
_, err := b.CryptoWithdrawal(0, "bla", "btc", "", true)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - CryptoWithdrawal() error", err)
|
||||
}
|
||||
_, err = b.CryptoWithdrawal(0, "bla", "btc", "", false)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - CryptoWithdrawal() error", err)
|
||||
}
|
||||
_, err = b.CryptoWithdrawal(0, "bla", "ltc", "", false)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - CryptoWithdrawal() error", err)
|
||||
}
|
||||
_, err = b.CryptoWithdrawal(0, "bla", "eth", "", false)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - CryptoWithdrawal() error", err)
|
||||
}
|
||||
_, err = b.CryptoWithdrawal(0, "bla", "xrp", "someplace", false)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - CryptoWithdrawal() error", err)
|
||||
}
|
||||
_, err = b.CryptoWithdrawal(0, "bla", "ding!", "", false)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - CryptoWithdrawal() error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetBitcoinDepositAddress(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Bitstamp{}
|
||||
b.APIKey = apiKey
|
||||
b.APISecret = apiSecret
|
||||
b.ClientID = customerID
|
||||
|
||||
_, err := b.GetCryptoDepositAddress("btc")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetCryptoDepositAddress() error", err)
|
||||
}
|
||||
_, err = b.GetCryptoDepositAddress("LTc")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetCryptoDepositAddress() error", err)
|
||||
}
|
||||
_, err = b.GetCryptoDepositAddress("eth")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetCryptoDepositAddress() error", err)
|
||||
}
|
||||
_, err = b.GetCryptoDepositAddress("xrp")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetCryptoDepositAddress() error", err)
|
||||
}
|
||||
_, err = b.GetCryptoDepositAddress("wigwham")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetCryptoDepositAddress() error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetUnconfirmedBitcoinDeposits(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Bitstamp{}
|
||||
b.APIKey = apiKey
|
||||
b.APISecret = apiSecret
|
||||
b.ClientID = customerID
|
||||
|
||||
_, err := b.GetUnconfirmedBitcoinDeposits()
|
||||
if err == nil {
|
||||
@@ -351,10 +227,6 @@ func TestGetUnconfirmedBitcoinDeposits(t *testing.T) {
|
||||
|
||||
func TestTransferAccountBalance(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Bitstamp{}
|
||||
b.APIKey = apiKey
|
||||
b.APISecret = apiSecret
|
||||
b.ClientID = customerID
|
||||
|
||||
_, err := b.TransferAccountBalance(1, "", "", true)
|
||||
if err == nil {
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
package bittrex
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
@@ -53,11 +53,15 @@ const (
|
||||
bittrexAPIGetOrderHistory = "account/getorderhistory"
|
||||
bittrexAPIGetWithdrawalHistory = "account/getwithdrawalhistory"
|
||||
bittrexAPIGetDepositHistory = "account/getdeposithistory"
|
||||
|
||||
bittrexAuthRate = 0
|
||||
bittrexUnauthRate = 0
|
||||
)
|
||||
|
||||
// Bittrex is the overaching type across the bittrex methods
|
||||
type Bittrex struct {
|
||||
exchange.Base
|
||||
*request.Handler
|
||||
}
|
||||
|
||||
// SetDefaults method assignes the default values for Bittrex
|
||||
@@ -73,6 +77,8 @@ func (b *Bittrex) SetDefaults() {
|
||||
b.ConfigCurrencyPairFormat.Uppercase = true
|
||||
b.AssetTypes = []string{ticker.Spot}
|
||||
b.SupportsAutoPairUpdating = true
|
||||
b.Handler = new(request.Handler)
|
||||
b.SetRequestHandler(b.Name, bittrexAuthRate, bittrexUnauthRate, new(http.Client))
|
||||
}
|
||||
|
||||
// Setup method sets current configuration details if enabled
|
||||
@@ -106,19 +112,33 @@ func (b *Bittrex) Setup(exch config.ExchangeConfig) {
|
||||
|
||||
// GetMarkets is used to get the open and available trading markets at Bittrex
|
||||
// along with other meta data.
|
||||
func (b *Bittrex) GetMarkets() ([]Market, error) {
|
||||
var markets []Market
|
||||
func (b *Bittrex) GetMarkets() (Market, error) {
|
||||
var markets Market
|
||||
path := fmt.Sprintf("%s/%s/", bittrexAPIURL, bittrexAPIGetMarkets)
|
||||
|
||||
return markets, b.HTTPRequest(path, false, url.Values{}, &markets)
|
||||
if err := b.SendHTTPRequest(path, &markets); err != nil {
|
||||
return markets, err
|
||||
}
|
||||
|
||||
if !markets.Success {
|
||||
return markets, errors.New(markets.Message)
|
||||
}
|
||||
return markets, nil
|
||||
}
|
||||
|
||||
// GetCurrencies is used to get all supported currencies at Bittrex
|
||||
func (b *Bittrex) GetCurrencies() ([]Currency, error) {
|
||||
var currencies []Currency
|
||||
func (b *Bittrex) GetCurrencies() (Currency, error) {
|
||||
var currencies Currency
|
||||
path := fmt.Sprintf("%s/%s/", bittrexAPIURL, bittrexAPIGetCurrencies)
|
||||
|
||||
return currencies, b.HTTPRequest(path, false, url.Values{}, ¤cies)
|
||||
if err := b.SendHTTPRequest(path, ¤cies); err != nil {
|
||||
return currencies, err
|
||||
}
|
||||
|
||||
if !currencies.Success {
|
||||
return currencies, errors.New(currencies.Message)
|
||||
}
|
||||
return currencies, nil
|
||||
}
|
||||
|
||||
// GetTicker sends a public get request and returns current ticker information
|
||||
@@ -128,26 +148,49 @@ func (b *Bittrex) GetTicker(currencyPair string) (Ticker, error) {
|
||||
path := fmt.Sprintf("%s/%s?market=%s", bittrexAPIURL, bittrexAPIGetTicker,
|
||||
common.StringToUpper(currencyPair),
|
||||
)
|
||||
return ticker, b.HTTPRequest(path, false, url.Values{}, &ticker)
|
||||
|
||||
if err := b.SendHTTPRequest(path, &ticker); err != nil {
|
||||
return ticker, err
|
||||
}
|
||||
|
||||
if !ticker.Success {
|
||||
return ticker, errors.New(ticker.Message)
|
||||
}
|
||||
return ticker, nil
|
||||
}
|
||||
|
||||
// GetMarketSummaries is used to get the last 24 hour summary of all active
|
||||
// exchanges
|
||||
func (b *Bittrex) GetMarketSummaries() ([]MarketSummary, error) {
|
||||
var summaries []MarketSummary
|
||||
func (b *Bittrex) GetMarketSummaries() (MarketSummary, error) {
|
||||
var summaries MarketSummary
|
||||
path := fmt.Sprintf("%s/%s/", bittrexAPIURL, bittrexAPIGetMarketSummaries)
|
||||
|
||||
return summaries, b.HTTPRequest(path, false, url.Values{}, &summaries)
|
||||
if err := b.SendHTTPRequest(path, &summaries); err != nil {
|
||||
return summaries, err
|
||||
}
|
||||
|
||||
if !summaries.Success {
|
||||
return summaries, errors.New(summaries.Message)
|
||||
}
|
||||
return summaries, nil
|
||||
}
|
||||
|
||||
// GetMarketSummary is used to get the last 24 hour summary of all active
|
||||
// exchanges by currency pair (btc-ltc).
|
||||
func (b *Bittrex) GetMarketSummary(currencyPair string) ([]MarketSummary, error) {
|
||||
var summary []MarketSummary
|
||||
func (b *Bittrex) GetMarketSummary(currencyPair string) (MarketSummary, error) {
|
||||
var summary MarketSummary
|
||||
path := fmt.Sprintf("%s/%s?market=%s", bittrexAPIURL,
|
||||
bittrexAPIGetMarketSummary, common.StringToLower(currencyPair),
|
||||
)
|
||||
return summary, b.HTTPRequest(path, false, url.Values{}, &summary)
|
||||
|
||||
if err := b.SendHTTPRequest(path, &summary); err != nil {
|
||||
return summary, err
|
||||
}
|
||||
|
||||
if !summary.Success {
|
||||
return summary, errors.New(summary.Message)
|
||||
}
|
||||
return summary, nil
|
||||
}
|
||||
|
||||
// GetOrderbook method returns current order book information by currency, type
|
||||
@@ -163,18 +206,32 @@ func (b *Bittrex) GetOrderbook(currencyPair string) (OrderBooks, error) {
|
||||
bittrexAPIGetOrderbook, common.StringToUpper(currencyPair),
|
||||
)
|
||||
|
||||
return orderbooks, b.HTTPRequest(path, false, url.Values{}, &orderbooks)
|
||||
if err := b.SendHTTPRequest(path, &orderbooks); err != nil {
|
||||
return orderbooks, err
|
||||
}
|
||||
|
||||
if !orderbooks.Success {
|
||||
return orderbooks, errors.New(orderbooks.Message)
|
||||
}
|
||||
return orderbooks, nil
|
||||
}
|
||||
|
||||
// GetMarketHistory retrieves the latest trades that have occurred for a specific
|
||||
// market
|
||||
func (b *Bittrex) GetMarketHistory(currencyPair string) ([]MarketHistory, error) {
|
||||
var marketHistoriae []MarketHistory
|
||||
func (b *Bittrex) GetMarketHistory(currencyPair string) (MarketHistory, error) {
|
||||
var marketHistoriae MarketHistory
|
||||
path := fmt.Sprintf("%s/%s?market=%s", bittrexAPIURL,
|
||||
bittrexAPIGetMarketHistory, common.StringToUpper(currencyPair),
|
||||
)
|
||||
return marketHistoriae, b.HTTPRequest(path, false, url.Values{},
|
||||
&marketHistoriae)
|
||||
|
||||
if err := b.SendHTTPRequest(path, &marketHistoriae); err != nil {
|
||||
return marketHistoriae, err
|
||||
}
|
||||
|
||||
if !marketHistoriae.Success {
|
||||
return marketHistoriae, errors.New(marketHistoriae.Message)
|
||||
}
|
||||
return marketHistoriae, nil
|
||||
}
|
||||
|
||||
// PlaceBuyLimit is used to place a buy order in a specific market. Use buylimit
|
||||
@@ -183,15 +240,22 @@ func (b *Bittrex) GetMarketHistory(currencyPair string) ([]MarketHistory, error)
|
||||
// "Currency" ie "btc-ltc"
|
||||
// "Quantity" is the amount to purchase
|
||||
// "Rate" is the rate at which to purchase
|
||||
func (b *Bittrex) PlaceBuyLimit(currencyPair string, quantity, rate float64) ([]UUID, error) {
|
||||
var id []UUID
|
||||
func (b *Bittrex) PlaceBuyLimit(currencyPair string, quantity, rate float64) (UUID, error) {
|
||||
var id UUID
|
||||
values := url.Values{}
|
||||
values.Set("market", currencyPair)
|
||||
values.Set("quantity", strconv.FormatFloat(quantity, 'E', -1, 64))
|
||||
values.Set("rate", strconv.FormatFloat(rate, 'E', -1, 64))
|
||||
path := fmt.Sprintf("%s/%s", bittrexAPIURL, bittrexAPIBuyLimit)
|
||||
|
||||
return id, b.HTTPRequest(path, true, values, &id)
|
||||
if err := b.SendAuthenticatedHTTPRequest(path, values, &id); err != nil {
|
||||
return id, err
|
||||
}
|
||||
|
||||
if !id.Success {
|
||||
return id, errors.New(id.Message)
|
||||
}
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// PlaceSellLimit is used to place a sell order in a specific market. Use
|
||||
@@ -200,46 +264,74 @@ func (b *Bittrex) PlaceBuyLimit(currencyPair string, quantity, rate float64) ([]
|
||||
// "Currency" ie "btc-ltc"
|
||||
// "Quantity" is the amount to purchase
|
||||
// "Rate" is the rate at which to purchase
|
||||
func (b *Bittrex) PlaceSellLimit(currencyPair string, quantity, rate float64) ([]UUID, error) {
|
||||
var id []UUID
|
||||
func (b *Bittrex) PlaceSellLimit(currencyPair string, quantity, rate float64) (UUID, error) {
|
||||
var id UUID
|
||||
values := url.Values{}
|
||||
values.Set("market", currencyPair)
|
||||
values.Set("quantity", strconv.FormatFloat(quantity, 'E', -1, 64))
|
||||
values.Set("rate", strconv.FormatFloat(rate, 'E', -1, 64))
|
||||
path := fmt.Sprintf("%s/%s", bittrexAPIURL, bittrexAPISellLimit)
|
||||
|
||||
return id, b.HTTPRequest(path, true, values, &id)
|
||||
if err := b.SendAuthenticatedHTTPRequest(path, values, &id); err != nil {
|
||||
return id, err
|
||||
}
|
||||
|
||||
if !id.Success {
|
||||
return id, errors.New(id.Message)
|
||||
}
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// GetOpenOrders returns all orders that you currently have opened.
|
||||
// A specific market can be requested for example "btc-ltc"
|
||||
func (b *Bittrex) GetOpenOrders(currencyPair string) ([]Order, error) {
|
||||
var orders []Order
|
||||
func (b *Bittrex) GetOpenOrders(currencyPair string) (Order, error) {
|
||||
var orders Order
|
||||
values := url.Values{}
|
||||
if !(currencyPair == "" || currencyPair == " ") {
|
||||
values.Set("market", currencyPair)
|
||||
}
|
||||
path := fmt.Sprintf("%s/%s", bittrexAPIURL, bittrexAPIGetOpenOrders)
|
||||
|
||||
return orders, b.HTTPRequest(path, true, values, &orders)
|
||||
if err := b.SendAuthenticatedHTTPRequest(path, values, &orders); err != nil {
|
||||
return orders, err
|
||||
}
|
||||
|
||||
if !orders.Success {
|
||||
return orders, errors.New(orders.Message)
|
||||
}
|
||||
return orders, nil
|
||||
}
|
||||
|
||||
// CancelOrder is used to cancel a buy or sell order.
|
||||
func (b *Bittrex) CancelOrder(uuid string) ([]Balance, error) {
|
||||
var balances []Balance
|
||||
func (b *Bittrex) CancelOrder(uuid string) (Balances, error) {
|
||||
var balances Balances
|
||||
values := url.Values{}
|
||||
values.Set("uuid", uuid)
|
||||
path := fmt.Sprintf("%s/%s", bittrexAPIURL, bittrexAPICancel)
|
||||
|
||||
return balances, b.HTTPRequest(path, true, values, &balances)
|
||||
if err := b.SendAuthenticatedHTTPRequest(path, values, &balances); err != nil {
|
||||
return balances, err
|
||||
}
|
||||
|
||||
if !balances.Success {
|
||||
return balances, errors.New(balances.Message)
|
||||
}
|
||||
return balances, nil
|
||||
}
|
||||
|
||||
// GetAccountBalances is used to retrieve all balances from your account
|
||||
func (b *Bittrex) GetAccountBalances() ([]Balance, error) {
|
||||
var balances []Balance
|
||||
func (b *Bittrex) GetAccountBalances() (Balances, error) {
|
||||
var balances Balances
|
||||
path := fmt.Sprintf("%s/%s", bittrexAPIURL, bittrexAPIGetBalances)
|
||||
|
||||
return balances, b.HTTPRequest(path, true, url.Values{}, &balances)
|
||||
if err := b.SendAuthenticatedHTTPRequest(path, url.Values{}, &balances); err != nil {
|
||||
return balances, err
|
||||
}
|
||||
|
||||
if !balances.Success {
|
||||
return balances, errors.New(balances.Message)
|
||||
}
|
||||
return balances, nil
|
||||
}
|
||||
|
||||
// GetAccountBalanceByCurrency is used to retrieve the balance from your account
|
||||
@@ -250,7 +342,14 @@ func (b *Bittrex) GetAccountBalanceByCurrency(currency string) (Balance, error)
|
||||
values.Set("currency", currency)
|
||||
path := fmt.Sprintf("%s/%s", bittrexAPIURL, bittrexAPIGetBalance)
|
||||
|
||||
return balance, b.HTTPRequest(path, true, values, &balance)
|
||||
if err := b.SendAuthenticatedHTTPRequest(path, values, &balance); err != nil {
|
||||
return balance, err
|
||||
}
|
||||
|
||||
if !balance.Success {
|
||||
return balance, errors.New(balance.Message)
|
||||
}
|
||||
return balance, nil
|
||||
}
|
||||
|
||||
// GetDepositAddress is used to retrieve or generate an address for a specific
|
||||
@@ -262,7 +361,14 @@ func (b *Bittrex) GetDepositAddress(currency string) (DepositAddress, error) {
|
||||
values.Set("currency", currency)
|
||||
path := fmt.Sprintf("%s/%s", bittrexAPIURL, bittrexAPIGetDepositAddress)
|
||||
|
||||
return address, b.HTTPRequest(path, true, values, &address)
|
||||
if err := b.SendAuthenticatedHTTPRequest(path, values, &address); err != nil {
|
||||
return address, err
|
||||
}
|
||||
|
||||
if !address.Success {
|
||||
return address, errors.New(address.Message)
|
||||
}
|
||||
return address, nil
|
||||
}
|
||||
|
||||
// Withdraw is used to withdraw funds from your account.
|
||||
@@ -275,7 +381,14 @@ func (b *Bittrex) Withdraw(currency, paymentID, address string, quantity float64
|
||||
values.Set("address", address)
|
||||
path := fmt.Sprintf("%s/%s", bittrexAPIURL, bittrexAPIWithdraw)
|
||||
|
||||
return id, b.HTTPRequest(path, true, values, &id)
|
||||
if err := b.SendAuthenticatedHTTPRequest(path, values, &id); err != nil {
|
||||
return id, err
|
||||
}
|
||||
|
||||
if !id.Success {
|
||||
return id, errors.New(id.Message)
|
||||
}
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// GetOrder is used to retrieve a single order by UUID.
|
||||
@@ -285,13 +398,20 @@ func (b *Bittrex) GetOrder(uuid string) (Order, error) {
|
||||
values.Set("uuid", uuid)
|
||||
path := fmt.Sprintf("%s/%s", bittrexAPIURL, bittrexAPIGetOrder)
|
||||
|
||||
return order, b.HTTPRequest(path, true, values, &order)
|
||||
if err := b.SendAuthenticatedHTTPRequest(path, values, &order); err != nil {
|
||||
return order, err
|
||||
}
|
||||
|
||||
if !order.Success {
|
||||
return order, errors.New(order.Message)
|
||||
}
|
||||
return order, nil
|
||||
}
|
||||
|
||||
// GetOrderHistory is used to retrieve your order history. If currencyPair
|
||||
// omitted it will return the entire order History.
|
||||
func (b *Bittrex) GetOrderHistory(currencyPair string) ([]Order, error) {
|
||||
var orders []Order
|
||||
func (b *Bittrex) GetOrderHistory(currencyPair string) (Order, error) {
|
||||
var orders Order
|
||||
values := url.Values{}
|
||||
|
||||
if !(currencyPair == "" || currencyPair == " ") {
|
||||
@@ -299,13 +419,20 @@ func (b *Bittrex) GetOrderHistory(currencyPair string) ([]Order, error) {
|
||||
}
|
||||
path := fmt.Sprintf("%s/%s", bittrexAPIURL, bittrexAPIGetOrderHistory)
|
||||
|
||||
return orders, b.HTTPRequest(path, true, values, &orders)
|
||||
if err := b.SendAuthenticatedHTTPRequest(path, values, &orders); err != nil {
|
||||
return orders, err
|
||||
}
|
||||
|
||||
if !orders.Success {
|
||||
return orders, errors.New(orders.Message)
|
||||
}
|
||||
return orders, nil
|
||||
}
|
||||
|
||||
// GetWithdrawalHistory is used to retrieve your withdrawal history. If currency
|
||||
// omitted it will return the entire history
|
||||
func (b *Bittrex) GetWithdrawalHistory(currency string) ([]WithdrawalHistory, error) {
|
||||
var history []WithdrawalHistory
|
||||
func (b *Bittrex) GetWithdrawalHistory(currency string) (WithdrawalHistory, error) {
|
||||
var history WithdrawalHistory
|
||||
values := url.Values{}
|
||||
|
||||
if !(currency == "" || currency == " ") {
|
||||
@@ -313,13 +440,20 @@ func (b *Bittrex) GetWithdrawalHistory(currency string) ([]WithdrawalHistory, er
|
||||
}
|
||||
path := fmt.Sprintf("%s/%s", bittrexAPIURL, bittrexAPIGetWithdrawalHistory)
|
||||
|
||||
return history, b.HTTPRequest(path, true, values, &history)
|
||||
if err := b.SendAuthenticatedHTTPRequest(path, values, &history); err != nil {
|
||||
return history, err
|
||||
}
|
||||
|
||||
if !history.Success {
|
||||
return history, errors.New(history.Message)
|
||||
}
|
||||
return history, nil
|
||||
}
|
||||
|
||||
// GetDepositHistory is used to retrieve your deposit history. If currency is
|
||||
// is omitted it will return the entire deposit history
|
||||
func (b *Bittrex) GetDepositHistory(currency string) ([]WithdrawalHistory, error) {
|
||||
var history []WithdrawalHistory
|
||||
func (b *Bittrex) GetDepositHistory(currency string) (WithdrawalHistory, error) {
|
||||
var history WithdrawalHistory
|
||||
values := url.Values{}
|
||||
|
||||
if !(currency == "" || currency == " ") {
|
||||
@@ -327,7 +461,19 @@ func (b *Bittrex) GetDepositHistory(currency string) ([]WithdrawalHistory, error
|
||||
}
|
||||
path := fmt.Sprintf("%s/%s", bittrexAPIURL, bittrexAPIGetDepositHistory)
|
||||
|
||||
return history, b.HTTPRequest(path, true, values, &history)
|
||||
if err := b.SendAuthenticatedHTTPRequest(path, values, &history); err != nil {
|
||||
return history, err
|
||||
}
|
||||
|
||||
if !history.Success {
|
||||
return history, errors.New(history.Message)
|
||||
}
|
||||
return history, nil
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (b *Bittrex) SendHTTPRequest(path string, result interface{}) error {
|
||||
return b.SendPayload("GET", path, nil, nil, result, false, b.Verbose)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated http request to a desired
|
||||
@@ -352,38 +498,5 @@ func (b *Bittrex) SendAuthenticatedHTTPRequest(path string, values url.Values, r
|
||||
headers := make(map[string]string)
|
||||
headers["apisign"] = common.HexEncodeToString(hmac)
|
||||
|
||||
resp, err := common.SendHTTPRequest(
|
||||
"GET", rawQuery, headers, strings.NewReader(""),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if b.Verbose {
|
||||
log.Printf("Received raw: %s\n", resp)
|
||||
}
|
||||
|
||||
err = common.JSONDecode([]byte(resp), &result)
|
||||
if err != nil {
|
||||
return errors.New("Unable to JSON Unmarshal response." + err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// HTTPRequest is a generalised http request function.
|
||||
func (b *Bittrex) HTTPRequest(path string, auth bool, values url.Values, v interface{}) error {
|
||||
response := Response{}
|
||||
if auth {
|
||||
if err := b.SendAuthenticatedHTTPRequest(path, values, &response); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := common.SendHTTPGetRequest(path, true, b.Verbose, &response); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if response.Success {
|
||||
return json.Unmarshal(response.Result, &v)
|
||||
}
|
||||
return errors.New(response.Message)
|
||||
return b.SendPayload("GET", rawQuery, headers, nil, result, true, b.Verbose)
|
||||
}
|
||||
|
||||
@@ -13,9 +13,9 @@ const (
|
||||
apiSecret = "TestyTesty"
|
||||
)
|
||||
|
||||
var b Bittrex
|
||||
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Bittrex{}
|
||||
b.SetDefaults()
|
||||
if b.GetName() != "Bittrex" {
|
||||
t.Error("Test Failed - Bittrex - SetDefaults() error")
|
||||
@@ -23,9 +23,6 @@ func TestSetDefaults(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
t.Parallel()
|
||||
b := Bittrex{}
|
||||
b.Name = "Bittrex"
|
||||
cfg := config.GetConfig()
|
||||
cfg.LoadConfig("../../testdata/configtest.json")
|
||||
bConfig, err := cfg.GetExchangeConfig("Bittrex")
|
||||
@@ -33,7 +30,6 @@ func TestSetup(t *testing.T) {
|
||||
t.Error("Test Failed - Bittrex Setup() init error")
|
||||
}
|
||||
|
||||
b.SetDefaults()
|
||||
b.Setup(bConfig)
|
||||
|
||||
if !b.IsEnabled() || b.AuthenticatedAPISupport || b.RESTPollingDelay != time.Duration(10) ||
|
||||
@@ -41,19 +37,11 @@ func TestSetup(t *testing.T) {
|
||||
len(b.AvailablePairs) < 1 || len(b.EnabledPairs) < 1 {
|
||||
t.Error("Test Failed - Bittrex Setup values not set correctly")
|
||||
}
|
||||
|
||||
bConfig.Enabled = false
|
||||
b.Setup(bConfig)
|
||||
|
||||
if b.IsEnabled() {
|
||||
t.Error("Test failed - Bittrex TestSetup incorrect value")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetMarkets(t *testing.T) {
|
||||
t.Parallel()
|
||||
obj := Bittrex{}
|
||||
_, err := obj.GetMarkets()
|
||||
_, err := b.GetMarkets()
|
||||
if err != nil {
|
||||
t.Errorf("Test Failed - Bittrex - GetMarkets() error: %s", err)
|
||||
}
|
||||
@@ -61,8 +49,7 @@ func TestGetMarkets(t *testing.T) {
|
||||
|
||||
func TestGetCurrencies(t *testing.T) {
|
||||
t.Parallel()
|
||||
obj := Bittrex{}
|
||||
_, err := obj.GetCurrencies()
|
||||
_, err := b.GetCurrencies()
|
||||
if err != nil {
|
||||
t.Errorf("Test Failed - Bittrex - GetCurrencies() error: %s", err)
|
||||
}
|
||||
@@ -70,20 +57,9 @@ func TestGetCurrencies(t *testing.T) {
|
||||
|
||||
func TestGetTicker(t *testing.T) {
|
||||
t.Parallel()
|
||||
invalid := ""
|
||||
btc := "btc-ltc"
|
||||
doge := "btc-DOGE"
|
||||
|
||||
obj := Bittrex{}
|
||||
_, err := obj.GetTicker(invalid)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - Bittrex - GetTicker() error")
|
||||
}
|
||||
_, err = obj.GetTicker(btc)
|
||||
if err != nil {
|
||||
t.Errorf("Test Failed - Bittrex - GetTicker() error: %s", err)
|
||||
}
|
||||
_, err = obj.GetTicker(doge)
|
||||
_, err := b.GetTicker(btc)
|
||||
if err != nil {
|
||||
t.Errorf("Test Failed - Bittrex - GetTicker() error: %s", err)
|
||||
}
|
||||
@@ -91,8 +67,7 @@ func TestGetTicker(t *testing.T) {
|
||||
|
||||
func TestGetMarketSummaries(t *testing.T) {
|
||||
t.Parallel()
|
||||
obj := Bittrex{}
|
||||
_, err := obj.GetMarketSummaries()
|
||||
_, err := b.GetMarketSummaries()
|
||||
if err != nil {
|
||||
t.Errorf("Test Failed - Bittrex - GetMarketSummaries() error: %s", err)
|
||||
}
|
||||
@@ -101,51 +76,35 @@ func TestGetMarketSummaries(t *testing.T) {
|
||||
func TestGetMarketSummary(t *testing.T) {
|
||||
t.Parallel()
|
||||
pairOne := "BTC-LTC"
|
||||
invalid := "WigWham"
|
||||
|
||||
obj := Bittrex{}
|
||||
_, err := obj.GetMarketSummary(pairOne)
|
||||
_, err := b.GetMarketSummary(pairOne)
|
||||
if err != nil {
|
||||
t.Errorf("Test Failed - Bittrex - GetMarketSummary() error: %s", err)
|
||||
}
|
||||
_, err = obj.GetMarketSummary(invalid)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - Bittrex - GetMarketSummary() error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetOrderbook(t *testing.T) {
|
||||
t.Parallel()
|
||||
obj := Bittrex{}
|
||||
_, err := obj.GetOrderbook("btc-ltc")
|
||||
|
||||
_, err := b.GetOrderbook("btc-ltc")
|
||||
if err != nil {
|
||||
t.Errorf("Test Failed - Bittrex - GetOrderbook() error: %s", err)
|
||||
}
|
||||
_, err = obj.GetOrderbook("wigwham")
|
||||
if err == nil {
|
||||
t.Errorf("Test Failed - Bittrex - GetOrderbook() error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetMarketHistory(t *testing.T) {
|
||||
t.Parallel()
|
||||
obj := Bittrex{}
|
||||
_, err := obj.GetMarketHistory("btc-ltc")
|
||||
|
||||
_, err := b.GetMarketHistory("btc-ltc")
|
||||
if err != nil {
|
||||
t.Errorf("Test Failed - Bittrex - GetMarketHistory() error: %s", err)
|
||||
}
|
||||
_, err = obj.GetMarketHistory("malum")
|
||||
if err == nil {
|
||||
t.Errorf("Test Failed - Bittrex - GetMarketHistory() error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlaceBuyLimit(t *testing.T) {
|
||||
t.Parallel()
|
||||
obj := Bittrex{}
|
||||
obj.APIKey = apiKey
|
||||
obj.APISecret = apiSecret
|
||||
_, err := obj.PlaceBuyLimit("btc-ltc", 1, 1)
|
||||
|
||||
_, err := b.PlaceBuyLimit("btc-ltc", 1, 1)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - Bittrex - PlaceBuyLimit() error")
|
||||
}
|
||||
@@ -153,10 +112,8 @@ func TestPlaceBuyLimit(t *testing.T) {
|
||||
|
||||
func TestPlaceSellLimit(t *testing.T) {
|
||||
t.Parallel()
|
||||
obj := Bittrex{}
|
||||
obj.APIKey = apiKey
|
||||
obj.APISecret = apiSecret
|
||||
_, err := obj.PlaceSellLimit("btc-ltc", 1, 1)
|
||||
|
||||
_, err := b.PlaceSellLimit("btc-ltc", 1, 1)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - Bittrex - PlaceSellLimit() error")
|
||||
}
|
||||
@@ -164,14 +121,12 @@ func TestPlaceSellLimit(t *testing.T) {
|
||||
|
||||
func TestGetOpenOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
obj := Bittrex{}
|
||||
obj.APIKey = apiKey
|
||||
obj.APISecret = apiSecret
|
||||
_, err := obj.GetOpenOrders("")
|
||||
|
||||
_, err := b.GetOpenOrders("")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - Bittrex - GetOrder() error")
|
||||
}
|
||||
_, err = obj.GetOpenOrders("btc-ltc")
|
||||
_, err = b.GetOpenOrders("btc-ltc")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - Bittrex - GetOrder() error")
|
||||
}
|
||||
@@ -179,10 +134,8 @@ func TestGetOpenOrders(t *testing.T) {
|
||||
|
||||
func TestCancelOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
obj := Bittrex{}
|
||||
obj.APIKey = apiKey
|
||||
obj.APISecret = apiSecret
|
||||
_, err := obj.CancelOrder("blaaaaaaa")
|
||||
|
||||
_, err := b.CancelOrder("blaaaaaaa")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - Bittrex - CancelOrder() error")
|
||||
}
|
||||
@@ -190,10 +143,8 @@ func TestCancelOrder(t *testing.T) {
|
||||
|
||||
func TestGetAccountBalances(t *testing.T) {
|
||||
t.Parallel()
|
||||
obj := Bittrex{}
|
||||
obj.APIKey = apiKey
|
||||
obj.APISecret = apiSecret
|
||||
_, err := obj.GetAccountBalances()
|
||||
|
||||
_, err := b.GetAccountBalances()
|
||||
if err == nil {
|
||||
t.Error("Test Failed - Bittrex - GetAccountBalances() error")
|
||||
}
|
||||
@@ -201,10 +152,8 @@ func TestGetAccountBalances(t *testing.T) {
|
||||
|
||||
func TestGetAccountBalanceByCurrency(t *testing.T) {
|
||||
t.Parallel()
|
||||
obj := Bittrex{}
|
||||
obj.APIKey = apiKey
|
||||
obj.APISecret = apiSecret
|
||||
_, err := obj.GetAccountBalanceByCurrency("btc")
|
||||
|
||||
_, err := b.GetAccountBalanceByCurrency("btc")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - Bittrex - GetAccountBalanceByCurrency() error")
|
||||
}
|
||||
@@ -212,10 +161,8 @@ func TestGetAccountBalanceByCurrency(t *testing.T) {
|
||||
|
||||
func TestGetDepositAddress(t *testing.T) {
|
||||
t.Parallel()
|
||||
obj := Bittrex{}
|
||||
obj.APIKey = apiKey
|
||||
obj.APISecret = apiSecret
|
||||
_, err := obj.GetDepositAddress("btc")
|
||||
|
||||
_, err := b.GetDepositAddress("btc")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - Bittrex - GetDepositAddress() error")
|
||||
}
|
||||
@@ -223,10 +170,8 @@ func TestGetDepositAddress(t *testing.T) {
|
||||
|
||||
func TestWithdraw(t *testing.T) {
|
||||
t.Parallel()
|
||||
obj := Bittrex{}
|
||||
obj.APIKey = apiKey
|
||||
obj.APISecret = apiSecret
|
||||
_, err := obj.Withdraw("btc", "something", "someplace", 1)
|
||||
|
||||
_, err := b.Withdraw("btc", "something", "someplace", 1)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - Bittrex - Withdraw() error")
|
||||
}
|
||||
@@ -234,14 +179,12 @@ func TestWithdraw(t *testing.T) {
|
||||
|
||||
func TestGetOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
obj := Bittrex{}
|
||||
obj.APIKey = apiKey
|
||||
obj.APISecret = apiSecret
|
||||
_, err := obj.GetOrder("0cb4c4e4-bdc7-4e13-8c13-430e587d2cc1")
|
||||
|
||||
_, err := b.GetOrder("0cb4c4e4-bdc7-4e13-8c13-430e587d2cc1")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - Bittrex - GetOrder() error")
|
||||
}
|
||||
_, err = obj.GetOrder("")
|
||||
_, err = b.GetOrder("")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - Bittrex - GetOrder() error")
|
||||
}
|
||||
@@ -249,14 +192,12 @@ func TestGetOrder(t *testing.T) {
|
||||
|
||||
func TestGetOrderHistory(t *testing.T) {
|
||||
t.Parallel()
|
||||
obj := Bittrex{}
|
||||
obj.APIKey = apiKey
|
||||
obj.APISecret = apiSecret
|
||||
_, err := obj.GetOrderHistory("")
|
||||
|
||||
_, err := b.GetOrderHistory("")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - Bittrex - GetOrderHistory() error")
|
||||
}
|
||||
_, err = obj.GetOrderHistory("btc-ltc")
|
||||
_, err = b.GetOrderHistory("btc-ltc")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - Bittrex - GetOrderHistory() error")
|
||||
}
|
||||
@@ -264,14 +205,12 @@ func TestGetOrderHistory(t *testing.T) {
|
||||
|
||||
func TestGetwithdrawalHistory(t *testing.T) {
|
||||
t.Parallel()
|
||||
obj := Bittrex{}
|
||||
obj.APIKey = apiKey
|
||||
obj.APISecret = apiSecret
|
||||
_, err := obj.GetWithdrawalHistory("")
|
||||
|
||||
_, err := b.GetWithdrawalHistory("")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - Bittrex - GetWithdrawalHistory() error")
|
||||
}
|
||||
_, err = obj.GetWithdrawalHistory("btc-ltc")
|
||||
_, err = b.GetWithdrawalHistory("btc-ltc")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - Bittrex - GetWithdrawalHistory() error")
|
||||
}
|
||||
@@ -279,14 +218,12 @@ func TestGetwithdrawalHistory(t *testing.T) {
|
||||
|
||||
func TestGetDepositHistory(t *testing.T) {
|
||||
t.Parallel()
|
||||
obj := Bittrex{}
|
||||
obj.APIKey = apiKey
|
||||
obj.APISecret = apiSecret
|
||||
_, err := obj.GetDepositHistory("")
|
||||
|
||||
_, err := b.GetDepositHistory("")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - Bittrex - GetDepositHistory() error")
|
||||
}
|
||||
_, err = obj.GetDepositHistory("btc-ltc")
|
||||
_, err = b.GetDepositHistory("btc-ltc")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - Bittrex - GetDepositHistory() error")
|
||||
}
|
||||
|
||||
@@ -11,56 +11,76 @@ type Response struct {
|
||||
|
||||
// Market holds current market metadata
|
||||
type Market struct {
|
||||
MarketCurrency string `json:"MarketCurrency"`
|
||||
BaseCurrency string `json:"BaseCurrency"`
|
||||
MarketCurrencyLong string `json:"MarketCurrencyLong"`
|
||||
BaseCurrencyLong string `json:"BaseCurrencyLong"`
|
||||
MinTradeSize float64 `json:"MinTradeSize"`
|
||||
MarketName string `json:"MarketName"`
|
||||
IsActive bool `json:"IsActive"`
|
||||
Created string `json:"Created"`
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
Result []struct {
|
||||
MarketCurrency string `json:"MarketCurrency"`
|
||||
BaseCurrency string `json:"BaseCurrency"`
|
||||
MarketCurrencyLong string `json:"MarketCurrencyLong"`
|
||||
BaseCurrencyLong string `json:"BaseCurrencyLong"`
|
||||
MinTradeSize float64 `json:"MinTradeSize"`
|
||||
MarketName string `json:"MarketName"`
|
||||
IsActive bool `json:"IsActive"`
|
||||
Created string `json:"Created"`
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
// Currency holds supported currency metadata
|
||||
type Currency struct {
|
||||
Currency string `json:"Currency"`
|
||||
CurrencyLong string `json:"CurrencyLong"`
|
||||
MinConfirmation int `json:"MinConfirmation"`
|
||||
TxFee float64 `json:"TxFee"`
|
||||
IsActive bool `json:"IsActive"`
|
||||
CoinType string `json:"CoinType"`
|
||||
BaseAddress string `json:"BaseAddress"`
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
Result []struct {
|
||||
Currency string `json:"Currency"`
|
||||
CurrencyLong string `json:"CurrencyLong"`
|
||||
MinConfirmation int `json:"MinConfirmation"`
|
||||
TxFee float64 `json:"TxFee"`
|
||||
IsActive bool `json:"IsActive"`
|
||||
CoinType string `json:"CoinType"`
|
||||
BaseAddress string `json:"BaseAddress"`
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
// Ticker holds basic ticker information
|
||||
type Ticker struct {
|
||||
Bid float64 `json:"Bid"`
|
||||
Ask float64 `json:"Ask"`
|
||||
Last float64 `json:"Last"`
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
Result struct {
|
||||
Bid float64 `json:"Bid"`
|
||||
Ask float64 `json:"Ask"`
|
||||
Last float64 `json:"Last"`
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
// MarketSummary holds last 24 hour metadata of an active exchange
|
||||
type MarketSummary struct {
|
||||
MarketName string `json:"MarketName"`
|
||||
High float64 `json:"High"`
|
||||
Low float64 `json:"Low"`
|
||||
Volume float64 `json:"Volume"`
|
||||
Last float64 `json:"Last"`
|
||||
BaseVolume float64 `json:"BaseVolume"`
|
||||
TimeStamp string `json:"TimeStamp"`
|
||||
Bid float64 `json:"Bid"`
|
||||
Ask float64 `json:"Ask"`
|
||||
OpenBuyOrders int `json:"OpenBuyOrders"`
|
||||
OpenSellOrders int `json:"OpenSellOrders"`
|
||||
PrevDay float64 `json:"PrevDay"`
|
||||
Created string `json:"Created"`
|
||||
DisplayMarketName string `json:"DisplayMarketName"`
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
Result []struct {
|
||||
MarketName string `json:"MarketName"`
|
||||
High float64 `json:"High"`
|
||||
Low float64 `json:"Low"`
|
||||
Volume float64 `json:"Volume"`
|
||||
Last float64 `json:"Last"`
|
||||
BaseVolume float64 `json:"BaseVolume"`
|
||||
TimeStamp string `json:"TimeStamp"`
|
||||
Bid float64 `json:"Bid"`
|
||||
Ask float64 `json:"Ask"`
|
||||
OpenBuyOrders int `json:"OpenBuyOrders"`
|
||||
OpenSellOrders int `json:"OpenSellOrders"`
|
||||
PrevDay float64 `json:"PrevDay"`
|
||||
Created string `json:"Created"`
|
||||
DisplayMarketName string `json:"DisplayMarketName"`
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
// OrderBooks holds an array of buy & sell orders held on the exchange
|
||||
type OrderBooks struct {
|
||||
Buy []OrderBook `json:"buy"`
|
||||
Sell []OrderBook `json:"sell"`
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
Result struct {
|
||||
Buy []OrderBook `json:"buy"`
|
||||
Sell []OrderBook `json:"sell"`
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
// OrderBook holds a singular order on an exchange
|
||||
@@ -71,77 +91,116 @@ type OrderBook struct {
|
||||
|
||||
// MarketHistory holds an executed trade's data for a market ie "BTC-LTC"
|
||||
type MarketHistory struct {
|
||||
ID int `json:"Id"`
|
||||
Timestamp string `json:"TimeStamp"`
|
||||
Quantity float64 `json:"Quantity"`
|
||||
Price float64 `json:"Price"`
|
||||
Total float64 `json:"Total"`
|
||||
FillType string `json:"FillType"`
|
||||
OrderType string `json:"OrderType"`
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
Result []struct {
|
||||
ID int `json:"Id"`
|
||||
Timestamp string `json:"TimeStamp"`
|
||||
Quantity float64 `json:"Quantity"`
|
||||
Price float64 `json:"Price"`
|
||||
Total float64 `json:"Total"`
|
||||
FillType string `json:"FillType"`
|
||||
OrderType string `json:"OrderType"`
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
// Balance holds the balance from your account for a specified currency
|
||||
type Balance struct {
|
||||
Currency string `json:"Currency"`
|
||||
Balance float64 `json:"Balance"`
|
||||
Available float64 `json:"Available"`
|
||||
Pending float64 `json:"Pending"`
|
||||
CryptoAddress string `json:"CryptoAddress"`
|
||||
Requested bool `json:"Requested"`
|
||||
UUID string `json:"Uuid"`
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
Result struct {
|
||||
Currency string `json:"Currency"`
|
||||
Balance float64 `json:"Balance"`
|
||||
Available float64 `json:"Available"`
|
||||
Pending float64 `json:"Pending"`
|
||||
CryptoAddress string `json:"CryptoAddress"`
|
||||
Requested bool `json:"Requested"`
|
||||
UUID string `json:"Uuid"`
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
// Balances holds the balance from your account for a specified currency
|
||||
type Balances struct {
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
Result []struct {
|
||||
Currency string `json:"Currency"`
|
||||
Balance float64 `json:"Balance"`
|
||||
Available float64 `json:"Available"`
|
||||
Pending float64 `json:"Pending"`
|
||||
CryptoAddress string `json:"CryptoAddress"`
|
||||
Requested bool `json:"Requested"`
|
||||
UUID string `json:"Uuid"`
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
// DepositAddress holds a generated address to send specific coins to the
|
||||
// exchange
|
||||
type DepositAddress struct {
|
||||
Currency string `json:"Currency"`
|
||||
Address string `json:"Address"`
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
Result struct {
|
||||
Currency string `json:"Currency"`
|
||||
Address string `json:"Address"`
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
// UUID contains the universal unique identifier for one or multiple
|
||||
// transactions on the exchange
|
||||
type UUID struct {
|
||||
ID string `json:"uuid"`
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
Result []struct {
|
||||
ID string `json:"uuid"`
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
// Order holds the full order information associated with the UUID supplied
|
||||
type Order struct {
|
||||
AccountID string `json:"AccountId"`
|
||||
OrderUUID string `json:"OrderUuid"`
|
||||
Exchange string `json:"Exchange"`
|
||||
Type string `json:"Type"`
|
||||
Quantity float64 `json:"Quantity"`
|
||||
QuantityRemaining float64 `json:"QuantityRemaining"`
|
||||
Limit float64 `json:"Limit"`
|
||||
Reserved float64 `json:"Reserved"`
|
||||
ReserveRemaining float64 `json:"ReserveRemaining"`
|
||||
CommissionReserved float64 `json:"CommissionReserved"`
|
||||
CommissionReserveRemaining float64 `json:"CommissionReserveRemaining"`
|
||||
CommissionPaid float64 `json:"CommissionPaid"`
|
||||
Price float64 `json:"Price"`
|
||||
PricePerUnit float64 `json:"PricePerUnit"`
|
||||
Opened string `json:"Opened"`
|
||||
Closed string `json:"Closed"`
|
||||
IsOpen bool `json:"IsOpen"`
|
||||
Sentinel string `json:"Sentinel"`
|
||||
CancelInitiated bool `json:"CancelInitiated"`
|
||||
ImmediateOrCancel bool `json:"ImmediateOrCancel"`
|
||||
IsConditional bool `json:"IsConditional"`
|
||||
Condition string `json:"Condition"`
|
||||
ConditionTarget string `json:"ConditionTarget"`
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
Result []struct {
|
||||
AccountID string `json:"AccountId"`
|
||||
OrderUUID string `json:"OrderUuid"`
|
||||
Exchange string `json:"Exchange"`
|
||||
Type string `json:"Type"`
|
||||
Quantity float64 `json:"Quantity"`
|
||||
QuantityRemaining float64 `json:"QuantityRemaining"`
|
||||
Limit float64 `json:"Limit"`
|
||||
Reserved float64 `json:"Reserved"`
|
||||
ReserveRemaining float64 `json:"ReserveRemaining"`
|
||||
CommissionReserved float64 `json:"CommissionReserved"`
|
||||
CommissionReserveRemaining float64 `json:"CommissionReserveRemaining"`
|
||||
CommissionPaid float64 `json:"CommissionPaid"`
|
||||
Price float64 `json:"Price"`
|
||||
PricePerUnit float64 `json:"PricePerUnit"`
|
||||
Opened string `json:"Opened"`
|
||||
Closed string `json:"Closed"`
|
||||
IsOpen bool `json:"IsOpen"`
|
||||
Sentinel string `json:"Sentinel"`
|
||||
CancelInitiated bool `json:"CancelInitiated"`
|
||||
ImmediateOrCancel bool `json:"ImmediateOrCancel"`
|
||||
IsConditional bool `json:"IsConditional"`
|
||||
Condition string `json:"Condition"`
|
||||
ConditionTarget string `json:"ConditionTarget"`
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
// WithdrawalHistory holds the Withdrawal history data
|
||||
type WithdrawalHistory struct {
|
||||
PaymentUUID string `json:"PaymentUuid"`
|
||||
Currency string `json:"Currency"`
|
||||
Amount float64 `json:"Amount"`
|
||||
Address string `json:"Address"`
|
||||
Opened string `json:"Opened"`
|
||||
Authorized bool `json:"Authorized"`
|
||||
PendingPayment bool `json:"PendingPayment"`
|
||||
TxCost float64 `json:"TxCost"`
|
||||
TxID string `json:"TxId"`
|
||||
Canceled bool `json:"Canceled"`
|
||||
InvalidAddress bool `json:"InvalidAddress"`
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
Result []struct {
|
||||
PaymentUUID string `json:"PaymentUuid"`
|
||||
Currency string `json:"Currency"`
|
||||
Amount float64 `json:"Amount"`
|
||||
Address string `json:"Address"`
|
||||
Opened string `json:"Opened"`
|
||||
Authorized bool `json:"Authorized"`
|
||||
PendingPayment bool `json:"PendingPayment"`
|
||||
TxCost float64 `json:"TxCost"`
|
||||
TxID string `json:"TxId"`
|
||||
Canceled bool `json:"Canceled"`
|
||||
InvalidAddress bool `json:"InvalidAddress"`
|
||||
} `json:"result"`
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/currency/pair"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
@@ -32,11 +32,11 @@ func (b *Bittrex) Run() {
|
||||
forceUpgrade = true
|
||||
}
|
||||
var currencies []string
|
||||
for x := range exchangeProducts {
|
||||
if !exchangeProducts[x].IsActive || exchangeProducts[x].MarketName == "" {
|
||||
for x := range exchangeProducts.Result {
|
||||
if !exchangeProducts.Result[x].IsActive || exchangeProducts.Result[x].MarketName == "" {
|
||||
continue
|
||||
}
|
||||
currencies = append(currencies, exchangeProducts[x].MarketName)
|
||||
currencies = append(currencies, exchangeProducts.Result[x].MarketName)
|
||||
}
|
||||
|
||||
if forceUpgrade {
|
||||
@@ -65,11 +65,11 @@ func (b *Bittrex) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
|
||||
return response, err
|
||||
}
|
||||
|
||||
for i := 0; i < len(accountBalance); i++ {
|
||||
for i := 0; i < len(accountBalance.Result); i++ {
|
||||
var exchangeCurrency exchange.AccountCurrencyInfo
|
||||
exchangeCurrency.CurrencyName = accountBalance[i].Currency
|
||||
exchangeCurrency.TotalValue = accountBalance[i].Balance
|
||||
exchangeCurrency.Hold = accountBalance[i].Balance - accountBalance[i].Available
|
||||
exchangeCurrency.CurrencyName = accountBalance.Result[i].Currency
|
||||
exchangeCurrency.TotalValue = accountBalance.Result[i].Balance
|
||||
exchangeCurrency.Hold = accountBalance.Result[i].Balance - accountBalance.Result[i].Available
|
||||
response.Currencies = append(response.Currencies, exchangeCurrency)
|
||||
}
|
||||
return response, nil
|
||||
@@ -85,15 +85,15 @@ func (b *Bittrex) UpdateTicker(p pair.CurrencyPair, assetType string) (ticker.Pr
|
||||
|
||||
for _, x := range b.GetEnabledCurrencies() {
|
||||
curr := exchange.FormatExchangeCurrency(b.Name, x)
|
||||
for y := range tick {
|
||||
if tick[y].MarketName == curr.String() {
|
||||
for y := range tick.Result {
|
||||
if tick.Result[y].MarketName == curr.String() {
|
||||
tickerPrice.Pair = x
|
||||
tickerPrice.High = tick[y].High
|
||||
tickerPrice.Low = tick[y].Low
|
||||
tickerPrice.Ask = tick[y].Ask
|
||||
tickerPrice.Bid = tick[y].Bid
|
||||
tickerPrice.Last = tick[y].Last
|
||||
tickerPrice.Volume = tick[y].Volume
|
||||
tickerPrice.High = tick.Result[y].High
|
||||
tickerPrice.Low = tick.Result[y].Low
|
||||
tickerPrice.Ask = tick.Result[y].Ask
|
||||
tickerPrice.Bid = tick.Result[y].Bid
|
||||
tickerPrice.Last = tick.Result[y].Last
|
||||
tickerPrice.Volume = tick.Result[y].Volume
|
||||
ticker.ProcessTicker(b.GetName(), x, tickerPrice, assetType)
|
||||
}
|
||||
}
|
||||
@@ -127,20 +127,20 @@ func (b *Bittrex) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderb
|
||||
return orderBook, err
|
||||
}
|
||||
|
||||
for x := range orderbookNew.Buy {
|
||||
for x := range orderbookNew.Result.Buy {
|
||||
orderBook.Bids = append(orderBook.Bids,
|
||||
orderbook.Item{
|
||||
Amount: orderbookNew.Buy[x].Quantity,
|
||||
Price: orderbookNew.Buy[x].Rate,
|
||||
Amount: orderbookNew.Result.Buy[x].Quantity,
|
||||
Price: orderbookNew.Result.Buy[x].Rate,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
for x := range orderbookNew.Sell {
|
||||
for x := range orderbookNew.Result.Sell {
|
||||
orderBook.Asks = append(orderBook.Asks,
|
||||
orderbook.Item{
|
||||
Amount: orderbookNew.Sell[x].Quantity,
|
||||
Price: orderbookNew.Sell[x].Rate,
|
||||
Amount: orderbookNew.Result.Sell[x].Quantity,
|
||||
Price: orderbookNew.Result.Sell[x].Rate,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -12,6 +13,7 @@ import (
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
@@ -41,11 +43,15 @@ const (
|
||||
btccStoporderCancel = "cancelStopOrder"
|
||||
btccStoporder = "getStopOrder"
|
||||
btccStoporders = "getStopOrders"
|
||||
|
||||
btccAuthRate = 0
|
||||
btccUnauthRate = 0
|
||||
)
|
||||
|
||||
// BTCC is the main overaching type across the BTCC package
|
||||
type BTCC struct {
|
||||
exchange.Base
|
||||
*request.Handler
|
||||
}
|
||||
|
||||
// SetDefaults sets default values for the exchange
|
||||
@@ -62,6 +68,8 @@ func (b *BTCC) SetDefaults() {
|
||||
b.ConfigCurrencyPairFormat.Uppercase = true
|
||||
b.AssetTypes = []string{ticker.Spot}
|
||||
b.SupportsAutoPairUpdating = true
|
||||
b.Handler = new(request.Handler)
|
||||
b.SetRequestHandler(b.Name, btccAuthRate, btccUnauthRate, new(http.Client))
|
||||
}
|
||||
|
||||
// Setup is run on startup to setup exchange with config values
|
||||
@@ -102,8 +110,8 @@ func (b *BTCC) GetFee() float64 {
|
||||
// currencyPair - Example "btccny", "ltccny" or "ltcbtc"
|
||||
func (b *BTCC) GetTicker(currencyPair string) (Ticker, error) {
|
||||
resp := Response{}
|
||||
req := fmt.Sprintf("%s/data/pro/ticker?symbol=%s", btccAPIUrl, currencyPair)
|
||||
return resp.Ticker, common.SendHTTPGetRequest(req, true, b.Verbose, &resp)
|
||||
path := fmt.Sprintf("%s/data/pro/ticker?symbol=%s", btccAPIUrl, currencyPair)
|
||||
return resp.Ticker, b.SendHTTPRequest(path, &resp)
|
||||
}
|
||||
|
||||
// GetTradeHistory returns trade history data
|
||||
@@ -113,7 +121,7 @@ func (b *BTCC) GetTicker(currencyPair string) (Ticker, error) {
|
||||
// time - returns trade records starting from unix time 1406794449
|
||||
func (b *BTCC) GetTradeHistory(currencyPair string, limit, sinceTid int64, time time.Time) ([]Trade, error) {
|
||||
trades := []Trade{}
|
||||
req := fmt.Sprintf("%s/data/pro/historydata?symbol=%s", btccAPIUrl, currencyPair)
|
||||
path := fmt.Sprintf("%s/data/pro/historydata?symbol=%s", btccAPIUrl, currencyPair)
|
||||
v := url.Values{}
|
||||
|
||||
if limit > 0 {
|
||||
@@ -126,8 +134,8 @@ func (b *BTCC) GetTradeHistory(currencyPair string, limit, sinceTid int64, time
|
||||
v.Set("sincetype", strconv.FormatInt(time.Unix(), 10))
|
||||
}
|
||||
|
||||
req = common.EncodeURLValues(req, v)
|
||||
return trades, common.SendHTTPGetRequest(req, true, b.Verbose, &trades)
|
||||
path = common.EncodeURLValues(path, v)
|
||||
return trades, b.SendHTTPRequest(path, &trades)
|
||||
}
|
||||
|
||||
// GetOrderBook returns current symbol order book
|
||||
@@ -136,12 +144,12 @@ func (b *BTCC) GetTradeHistory(currencyPair string, limit, sinceTid int64, time
|
||||
// orderbook
|
||||
func (b *BTCC) GetOrderBook(currencyPair string, limit int) (Orderbook, error) {
|
||||
result := Orderbook{}
|
||||
req := fmt.Sprintf("%s/data/pro/orderbook?symbol=%s&limit=%d", btccAPIUrl, currencyPair, limit)
|
||||
path := fmt.Sprintf("%s/data/pro/orderbook?symbol=%s&limit=%d", btccAPIUrl, currencyPair, limit)
|
||||
if limit == 0 {
|
||||
req = fmt.Sprintf("%s/data/pro/orderbook?symbol=%s", btccAPIUrl, currencyPair)
|
||||
path = fmt.Sprintf("%s/data/pro/orderbook?symbol=%s", btccAPIUrl, currencyPair)
|
||||
}
|
||||
|
||||
return result, common.SendHTTPGetRequest(req, true, b.Verbose, &result)
|
||||
return result, b.SendHTTPRequest(path, &result)
|
||||
}
|
||||
|
||||
// GetAccountInfo returns account information
|
||||
@@ -541,6 +549,11 @@ func (b *BTCC) CancelStopOrder(orderID int64, symbol string) {
|
||||
}
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (b *BTCC) SendHTTPRequest(path string, result interface{}) error {
|
||||
return b.SendPayload("GET", path, nil, nil, result, false, b.Verbose)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends a valid authenticated HTTP request
|
||||
func (b *BTCC) SendAuthenticatedHTTPRequest(method string, params []interface{}) (err error) {
|
||||
if !b.AuthenticatedAPISupport {
|
||||
@@ -600,8 +613,8 @@ func (b *BTCC) SendAuthenticatedHTTPRequest(method string, params []interface{})
|
||||
postData["id"] = 1
|
||||
|
||||
apiURL := fmt.Sprintf("%s/%s", btccAPIUrl, btccAPIAuthenticatedMethod)
|
||||
data, err := common.JSONEncode(postData)
|
||||
|
||||
data, err := common.JSONEncode(postData)
|
||||
if err != nil {
|
||||
return errors.New("Unable to JSON Marshal POST data")
|
||||
}
|
||||
@@ -615,15 +628,5 @@ func (b *BTCC) SendAuthenticatedHTTPRequest(method string, params []interface{})
|
||||
headers["Authorization"] = "Basic " + common.Base64Encode([]byte(b.APIKey+":"+common.HexEncodeToString(hmac)))
|
||||
headers["Json-Rpc-Tonce"] = b.Nonce.String()
|
||||
|
||||
resp, err := common.SendHTTPRequest("POST", apiURL, headers, strings.NewReader(string(data)))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if b.Verbose {
|
||||
log.Printf("Recv'd :%s\n", resp)
|
||||
}
|
||||
|
||||
return nil
|
||||
return b.SendPayload("POST", apiURL, headers, strings.NewReader(string(data)), nil, true, b.Verbose)
|
||||
}
|
||||
|
||||
@@ -20,16 +20,12 @@ func TestSetDefaults(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
t.Parallel()
|
||||
b.Name = "BTCC"
|
||||
cfg := config.GetConfig()
|
||||
cfg.LoadConfig("../../testdata/configtest.json")
|
||||
bConfig, err := cfg.GetExchangeConfig("BTCC")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - BTCC Setup() init error")
|
||||
}
|
||||
|
||||
b.SetDefaults()
|
||||
b.Setup(bConfig)
|
||||
|
||||
if !b.IsEnabled() || b.AuthenticatedAPISupport || b.RESTPollingDelay != time.Duration(10) ||
|
||||
@@ -37,13 +33,6 @@ func TestSetup(t *testing.T) {
|
||||
len(b.AvailablePairs) < 1 || len(b.EnabledPairs) < 1 {
|
||||
t.Error("Test Failed - BTCC Setup values not set correctly")
|
||||
}
|
||||
|
||||
bConfig.Enabled = false
|
||||
b.Setup(bConfig)
|
||||
|
||||
if b.IsEnabled() {
|
||||
t.Error("Test failed - BTCC TestSetup incorrect value")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetFee(t *testing.T) {
|
||||
@@ -67,7 +56,6 @@ func TestGetTradeHistory(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetOrderBook(t *testing.T) {
|
||||
b.Verbose = true
|
||||
_, err := b.GetOrderBook("BTCUSD", 100)
|
||||
if err != nil {
|
||||
t.Error("Test failed - GetOrderBook() error", err)
|
||||
|
||||
@@ -5,12 +5,14 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
@@ -27,7 +29,7 @@ const (
|
||||
btcMarketsWithdrawCrypto = "/fundtransfer/withdrawCrypto"
|
||||
btcMarketsWithdrawAud = "/fundtransfer/withdrawEFT"
|
||||
|
||||
//Status Values
|
||||
// Status Values
|
||||
orderStatusNew = "New"
|
||||
orderStatusPlaced = "Placed"
|
||||
orderStatusFailed = "Failed"
|
||||
@@ -36,12 +38,16 @@ const (
|
||||
orderStatusPartiallyCancelled = "Partially Cancelled"
|
||||
orderStatusFullyMatched = "Fully Matched"
|
||||
orderStatusPartiallyMatched = "Partially Matched"
|
||||
|
||||
btcmarketsAuthLimit = 0
|
||||
btcmarketsUnauthLimit = 0
|
||||
)
|
||||
|
||||
// BTCMarkets is the overarching type across the BTCMarkets package
|
||||
type BTCMarkets struct {
|
||||
exchange.Base
|
||||
Ticker map[string]Ticker
|
||||
*request.Handler
|
||||
}
|
||||
|
||||
// SetDefaults sets basic defaults
|
||||
@@ -59,6 +65,8 @@ func (b *BTCMarkets) SetDefaults() {
|
||||
b.ConfigCurrencyPairFormat.Uppercase = true
|
||||
b.AssetTypes = []string{ticker.Spot}
|
||||
b.SupportsAutoPairUpdating = true
|
||||
b.Handler = new(request.Handler)
|
||||
b.SetRequestHandler(b.Name, btcmarketsAuthLimit, btcmarketsUnauthLimit, new(http.Client))
|
||||
}
|
||||
|
||||
// Setup takes in an exchange configuration and sets all parameters
|
||||
@@ -99,22 +107,24 @@ func (b *BTCMarkets) GetFee() float64 {
|
||||
// symbol - example "btc" or "ltc"
|
||||
func (b *BTCMarkets) GetTicker(firstPair, secondPair string) (Ticker, error) {
|
||||
ticker := Ticker{}
|
||||
path := fmt.Sprintf("/market/%s/%s/tick", common.StringToUpper(firstPair),
|
||||
path := fmt.Sprintf("%s/market/%s/%s/tick",
|
||||
btcMarketsAPIURL,
|
||||
common.StringToUpper(firstPair),
|
||||
common.StringToUpper(secondPair))
|
||||
|
||||
return ticker,
|
||||
common.SendHTTPGetRequest(btcMarketsAPIURL+path, true, b.Verbose, &ticker)
|
||||
return ticker, b.SendHTTPRequest(path, &ticker)
|
||||
}
|
||||
|
||||
// GetOrderbook returns current orderbook
|
||||
// symbol - example "btc" or "ltc"
|
||||
func (b *BTCMarkets) GetOrderbook(firstPair, secondPair string) (Orderbook, error) {
|
||||
orderbook := Orderbook{}
|
||||
path := fmt.Sprintf("/market/%s/%s/orderbook", common.StringToUpper(firstPair),
|
||||
path := fmt.Sprintf("%s/market/%s/%s/orderbook",
|
||||
btcMarketsAPIURL,
|
||||
common.StringToUpper(firstPair),
|
||||
common.StringToUpper(secondPair))
|
||||
|
||||
return orderbook,
|
||||
common.SendHTTPGetRequest(btcMarketsAPIURL+path, true, b.Verbose, &orderbook)
|
||||
return orderbook, b.SendHTTPRequest(path, &orderbook)
|
||||
}
|
||||
|
||||
// GetTrades returns executed trades on the exchange
|
||||
@@ -126,7 +136,7 @@ func (b *BTCMarkets) GetTrades(firstPair, secondPair string, values url.Values)
|
||||
btcMarketsAPIURL, common.StringToUpper(firstPair),
|
||||
common.StringToUpper(secondPair)), values)
|
||||
|
||||
return trades, common.SendHTTPGetRequest(path, true, b.Verbose, &trades)
|
||||
return trades, b.SendHTTPRequest(path, &trades)
|
||||
}
|
||||
|
||||
// NewOrder requests a new order and returns an ID
|
||||
@@ -337,6 +347,11 @@ func (b *BTCMarkets) WithdrawAUD(accountName, accountNumber, bankName, bsbNumber
|
||||
return resp.Status, nil
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (b *BTCMarkets) SendHTTPRequest(path string, result interface{}) error {
|
||||
return b.SendPayload("GET", path, nil, nil, result, false, b.Verbose)
|
||||
}
|
||||
|
||||
// SendAuthenticatedRequest sends an authenticated HTTP request
|
||||
func (b *BTCMarkets) SendAuthenticatedRequest(reqType, path string, data interface{}, result interface{}) (err error) {
|
||||
if !b.AuthenticatedAPISupport {
|
||||
@@ -375,21 +390,5 @@ func (b *BTCMarkets) SendAuthenticatedRequest(reqType, path string, data interfa
|
||||
headers["timestamp"] = b.Nonce.String()[0:13]
|
||||
headers["signature"] = common.Base64Encode(hmac)
|
||||
|
||||
resp, err := common.SendHTTPRequest(reqType, btcMarketsAPIURL+path, headers, bytes.NewBuffer(payload))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if b.Verbose {
|
||||
log.Printf("Received raw: %s\n", resp)
|
||||
}
|
||||
|
||||
err = common.JSONDecode([]byte(resp), &result)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return b.SendPayload(reqType, btcMarketsAPIURL+path, headers, bytes.NewBuffer(payload), result, true, b.Verbose)
|
||||
}
|
||||
|
||||
@@ -5,12 +5,14 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
@@ -32,6 +34,9 @@ const (
|
||||
coinutOptionChain = "option_chain"
|
||||
coinutPositionHistory = "position_history"
|
||||
coinutPositionOpen = "user_open_positions"
|
||||
|
||||
coinutAuthRate = 0
|
||||
coinutUnauthRate = 0
|
||||
)
|
||||
|
||||
// COINUT is the overarching type across the coinut package
|
||||
@@ -39,6 +44,7 @@ type COINUT struct {
|
||||
exchange.Base
|
||||
WebsocketConn *websocket.Conn
|
||||
InstrumentMap map[string]int
|
||||
*request.Handler
|
||||
}
|
||||
|
||||
// SetDefaults sets current default values
|
||||
@@ -57,6 +63,8 @@ func (c *COINUT) SetDefaults() {
|
||||
c.ConfigCurrencyPairFormat.Uppercase = true
|
||||
c.AssetTypes = []string{ticker.Spot}
|
||||
c.SupportsAutoPairUpdating = true
|
||||
c.Handler = new(request.Handler)
|
||||
c.SetRequestHandler(c.Name, coinutAuthRate, coinutUnauthRate, new(http.Client))
|
||||
}
|
||||
|
||||
// Setup sets the current exchange configuration
|
||||
@@ -93,11 +101,8 @@ 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)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
return result, nil
|
||||
|
||||
return result, c.SendHTTPRequest(coinutInstruments, params, false, &result)
|
||||
}
|
||||
|
||||
// GetInstrumentTicker returns a ticker for a specific instrument
|
||||
@@ -105,11 +110,8 @@ 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)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
return result, nil
|
||||
|
||||
return result, c.SendHTTPRequest(coinutTicker, params, false, &result)
|
||||
}
|
||||
|
||||
// GetInstrumentOrderbook returns the orderbooks for a specific instrument
|
||||
@@ -120,11 +122,8 @@ func (c *COINUT) GetInstrumentOrderbook(instrumentID, limit int) (Orderbook, err
|
||||
if limit > 0 {
|
||||
params["top_n"] = limit
|
||||
}
|
||||
err := c.SendHTTPRequest(coinutOrderbook, params, false, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
return result, nil
|
||||
|
||||
return result, c.SendHTTPRequest(coinutOrderbook, params, false, &result)
|
||||
}
|
||||
|
||||
// GetTrades returns trade information
|
||||
@@ -132,21 +131,15 @@ 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)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
return result, nil
|
||||
|
||||
return result, c.SendHTTPRequest(coinutTrades, params, false, &result)
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
return result, nil
|
||||
|
||||
return result, c.SendHTTPRequest(coinutBalance, nil, true, &result)
|
||||
}
|
||||
|
||||
// NewOrder places a new order on the exchange
|
||||
@@ -162,11 +155,7 @@ func (c *COINUT) NewOrder(instrumentID int, quantity, price float64, buy bool, o
|
||||
}
|
||||
params["client_ord_id"] = orderID
|
||||
|
||||
err := c.SendHTTPRequest(coinutOrder, params, true, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
return result, nil
|
||||
return result, c.SendHTTPRequest(coinutOrder, params, true, &result)
|
||||
}
|
||||
|
||||
// NewOrders places multiple orders on the exchange
|
||||
@@ -174,11 +163,8 @@ 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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.Data, nil
|
||||
|
||||
return result.Data, c.SendHTTPRequest(coinutOrders, params, true, &result.Data)
|
||||
}
|
||||
|
||||
// GetOpenOrders returns a list of open order and relevant information
|
||||
@@ -186,11 +172,8 @@ 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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
|
||||
return result, c.SendHTTPRequest(coinutOrdersOpen, params, true, &result)
|
||||
}
|
||||
|
||||
// CancelOrder cancels a specific order and returns if it was actioned
|
||||
@@ -199,6 +182,7 @@ func (c *COINUT) CancelOrder(instrumentID, orderID int) (bool, error) {
|
||||
params := make(map[string]interface{})
|
||||
params["inst_id"] = instrumentID
|
||||
params["order_id"] = orderID
|
||||
|
||||
err := c.SendHTTPRequest(coinutOrdersCancel, params, true, &result)
|
||||
if err != nil {
|
||||
return false, err
|
||||
@@ -211,11 +195,8 @@ func (c *COINUT) CancelOrders(orders []CancelOrders) (CancelOrdersResponse, erro
|
||||
var result CancelOrdersResponse
|
||||
params := make(map[string]interface{})
|
||||
params["entries"] = orders
|
||||
err := c.SendHTTPRequest(coinutOrdersCancel, params, true, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
return result, nil
|
||||
|
||||
return result, c.SendHTTPRequest(coinutOrdersCancel, params, true, &result)
|
||||
}
|
||||
|
||||
// GetTradeHistory returns trade history for a specific instrument.
|
||||
@@ -229,11 +210,8 @@ func (c *COINUT) GetTradeHistory(instrumentID, start, limit int) (TradeHistory,
|
||||
if limit >= 0 && start <= 100 {
|
||||
params["limit"] = limit
|
||||
}
|
||||
err := c.SendHTTPRequest(coinutTradeHistory, params, true, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
return result, nil
|
||||
|
||||
return result, c.SendHTTPRequest(coinutTradeHistory, params, true, &result)
|
||||
}
|
||||
|
||||
// GetIndexTicker returns the index ticker for an asset
|
||||
@@ -241,11 +219,8 @@ 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)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
return result, nil
|
||||
|
||||
return result, c.SendHTTPRequest(coinutIndexTicker, params, false, &result)
|
||||
}
|
||||
|
||||
// GetDerivativeInstruments returns a list of derivative instruments
|
||||
@@ -253,11 +228,8 @@ func (c *COINUT) GetDerivativeInstruments(secType string) (interface{}, error) {
|
||||
var result interface{} //to-do
|
||||
params := make(map[string]interface{})
|
||||
params["sec_type"] = secType
|
||||
err := c.SendHTTPRequest(coinutInstruments, params, false, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
return result, nil
|
||||
|
||||
return result, c.SendHTTPRequest(coinutInstruments, params, false, &result)
|
||||
}
|
||||
|
||||
// GetOptionChain returns option chain
|
||||
@@ -266,11 +238,8 @@ func (c *COINUT) GetOptionChain(asset, secType string, expiry int64) (OptionChai
|
||||
params := make(map[string]interface{})
|
||||
params["asset"] = asset
|
||||
params["sec_type"] = secType
|
||||
err := c.SendHTTPRequest(coinutOptionChain, params, false, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
return result, nil
|
||||
|
||||
return result, c.SendHTTPRequest(coinutOptionChain, params, false, &result)
|
||||
}
|
||||
|
||||
// GetPositionHistory returns position history
|
||||
@@ -284,11 +253,8 @@ func (c *COINUT) GetPositionHistory(secType string, start, limit int) (PositionH
|
||||
if limit >= 0 {
|
||||
params["limit"] = limit
|
||||
}
|
||||
err := c.SendHTTPRequest(coinutPositionHistory, params, true, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
return result, nil
|
||||
|
||||
return result, c.SendHTTPRequest(coinutPositionHistory, params, true, &result)
|
||||
}
|
||||
|
||||
// GetOpenPositions returns all your current opened positions
|
||||
@@ -300,16 +266,13 @@ func (c *COINUT) GetOpenPositions(instrumentID int) ([]OpenPosition, error) {
|
||||
params := make(map[string]interface{})
|
||||
params["inst_id"] = instrumentID
|
||||
|
||||
err := c.SendHTTPRequest(coinutPositionOpen, params, true, &result)
|
||||
if err != nil {
|
||||
return result.Positions, err
|
||||
}
|
||||
return result.Positions, nil
|
||||
return result.Positions,
|
||||
c.SendHTTPRequest(coinutPositionOpen, params, true, &result)
|
||||
}
|
||||
|
||||
//to-do: user position update via websocket
|
||||
|
||||
// SendHTTPRequest sends an authenticated HTTP request
|
||||
// SendHTTPRequest sends either an authenticated or unauthenticated 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)
|
||||
@@ -344,32 +307,5 @@ func (c *COINUT) SendHTTPRequest(apiRequest string, params map[string]interface{
|
||||
}
|
||||
headers["Content-Type"] = "application/json"
|
||||
|
||||
resp, err := common.SendHTTPRequest("POST", coinutAPIURL, headers, bytes.NewBuffer(payload))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.Verbose {
|
||||
log.Printf("Received raw: \n%s", resp)
|
||||
}
|
||||
|
||||
genResp := GenericResponse{}
|
||||
err = common.JSONDecode([]byte(resp), &genResp)
|
||||
if err != nil {
|
||||
return errors.New("unable to JSON Unmarshal generic response")
|
||||
}
|
||||
|
||||
if len(genResp.Status) < 1 {
|
||||
return errors.New("genResp.Status was empty")
|
||||
}
|
||||
if genResp.Status[0] != "OK" {
|
||||
return errors.New("status is not OK")
|
||||
}
|
||||
|
||||
err = common.JSONDecode([]byte(resp), &result)
|
||||
if err != nil {
|
||||
return errors.New("unable to JSON Unmarshal response")
|
||||
}
|
||||
|
||||
return nil
|
||||
return c.SendPayload("POST", coinutAPIURL, headers, bytes.NewBuffer(payload), result, authenticated, c.Verbose)
|
||||
}
|
||||
|
||||
@@ -20,16 +20,12 @@ func TestSetDefaults(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
t.Parallel()
|
||||
c.Name = "Coinut"
|
||||
cfg := config.GetConfig()
|
||||
cfg.LoadConfig("../../testdata/configtest.json")
|
||||
bConfig, err := cfg.GetExchangeConfig("COINUT")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - Coinut Setup() init error")
|
||||
}
|
||||
|
||||
c.SetDefaults()
|
||||
c.Setup(bConfig)
|
||||
|
||||
if !c.IsEnabled() || c.AuthenticatedAPISupport || c.RESTPollingDelay != time.Duration(10) ||
|
||||
@@ -37,17 +33,9 @@ func TestSetup(t *testing.T) {
|
||||
len(c.AvailablePairs) < 1 || len(c.EnabledPairs) < 1 {
|
||||
t.Error("Test Failed - Coinut Setup values not set correctly")
|
||||
}
|
||||
|
||||
bConfig.Enabled = false
|
||||
c.Setup(bConfig)
|
||||
|
||||
if c.IsEnabled() {
|
||||
t.Error("Test failed - Coinut TestSetup incorrect value")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetInstruments(t *testing.T) {
|
||||
c.Verbose = true
|
||||
_, err := c.GetInstruments()
|
||||
if err != nil {
|
||||
t.Error("Test failed - GetInstruments() error", err)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package exmo
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strconv"
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
@@ -39,15 +40,18 @@ const (
|
||||
exmoExcodeCreate = "excode_create"
|
||||
exmoExcodeLoad = "excode_load"
|
||||
exmoWalletHistory = "wallet_history"
|
||||
|
||||
// Rate limit: 180 per/minute
|
||||
exmoAuthRate = 333
|
||||
exmoUnauthRate = 333
|
||||
)
|
||||
|
||||
// EXMO exchange struct
|
||||
type EXMO struct {
|
||||
exchange.Base
|
||||
*request.Handler
|
||||
}
|
||||
|
||||
// Rate limit: 180 per/minute
|
||||
|
||||
// SetDefaults sets the basic defaults for exmo
|
||||
func (e *EXMO) SetDefaults() {
|
||||
e.Name = "EXMO"
|
||||
@@ -62,6 +66,8 @@ func (e *EXMO) SetDefaults() {
|
||||
e.ConfigCurrencyPairFormat.Uppercase = true
|
||||
e.AssetTypes = []string{ticker.Spot}
|
||||
e.SupportsAutoPairUpdating = true
|
||||
e.Handler = new(request.Handler)
|
||||
e.SetRequestHandler(e.Name, exmoAuthRate, exmoUnauthRate, new(http.Client))
|
||||
}
|
||||
|
||||
// Setup takes in the supplied exchange configuration details and sets params
|
||||
@@ -99,8 +105,8 @@ func (e *EXMO) GetTrades(symbol string) (map[string][]Trades, error) {
|
||||
v.Set("pair", symbol)
|
||||
result := make(map[string][]Trades)
|
||||
url := fmt.Sprintf("%s/v%s/%s", exmoAPIURL, exmoAPIVersion, exmoTrades)
|
||||
err := common.SendHTTPGetRequest(common.EncodeURLValues(url, v), true, e.Verbose, &result)
|
||||
return result, err
|
||||
|
||||
return result, e.SendHTTPRequest(common.EncodeURLValues(url, v), &result)
|
||||
}
|
||||
|
||||
// GetOrderbook returns the orderbook for a symbol or symbols
|
||||
@@ -109,8 +115,8 @@ func (e *EXMO) GetOrderbook(symbol string) (map[string]Orderbook, error) {
|
||||
v.Set("pair", symbol)
|
||||
result := make(map[string]Orderbook)
|
||||
url := fmt.Sprintf("%s/v%s/%s", exmoAPIURL, exmoAPIVersion, exmoOrderbook)
|
||||
err := common.SendHTTPGetRequest(common.EncodeURLValues(url, v), true, e.Verbose, &result)
|
||||
return result, err
|
||||
|
||||
return result, e.SendHTTPRequest(common.EncodeURLValues(url, v), &result)
|
||||
}
|
||||
|
||||
// GetTicker returns the ticker for a symbol or symbols
|
||||
@@ -119,24 +125,24 @@ func (e *EXMO) GetTicker(symbol string) (map[string]Ticker, error) {
|
||||
v.Set("pair", symbol)
|
||||
result := make(map[string]Ticker)
|
||||
url := fmt.Sprintf("%s/v%s/%s", exmoAPIURL, exmoAPIVersion, exmoTicker)
|
||||
err := common.SendHTTPGetRequest(common.EncodeURLValues(url, v), true, e.Verbose, &result)
|
||||
return result, err
|
||||
|
||||
return result, e.SendHTTPRequest(common.EncodeURLValues(url, v), &result)
|
||||
}
|
||||
|
||||
// GetPairSettings returns the pair settings for a symbol or symbols
|
||||
func (e *EXMO) GetPairSettings() (map[string]PairSettings, error) {
|
||||
result := make(map[string]PairSettings)
|
||||
url := fmt.Sprintf("%s/v%s/%s", exmoAPIURL, exmoAPIVersion, exmoPairSettings)
|
||||
err := common.SendHTTPGetRequest(url, true, e.Verbose, &result)
|
||||
return result, err
|
||||
|
||||
return result, e.SendHTTPRequest(url, &result)
|
||||
}
|
||||
|
||||
// GetCurrency returns a list of currencies
|
||||
func (e *EXMO) GetCurrency() ([]string, error) {
|
||||
result := []string{}
|
||||
url := fmt.Sprintf("%s/v%s/%s", exmoAPIURL, exmoAPIVersion, exmoCurrency)
|
||||
err := common.SendHTTPGetRequest(url, true, e.Verbose, &result)
|
||||
return result, err
|
||||
|
||||
return result, e.SendHTTPRequest(url, &result)
|
||||
}
|
||||
|
||||
// GetUserInfo returns the user info
|
||||
@@ -311,6 +317,11 @@ func (e *EXMO) GetWalletHistory(date int64) (WalletHistory, error) {
|
||||
return result, err
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (e *EXMO) SendHTTPRequest(path string, result interface{}) error {
|
||||
return e.SendPayload("GET", path, nil, nil, result, false, e.Verbose)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request
|
||||
func (e *EXMO) SendAuthenticatedHTTPRequest(method, endpoint string, vals url.Values, result interface{}) error {
|
||||
if !e.AuthenticatedAPISupport {
|
||||
@@ -337,28 +348,6 @@ func (e *EXMO) SendAuthenticatedHTTPRequest(method, endpoint string, vals url.Va
|
||||
headers["Content-Type"] = "application/x-www-form-urlencoded"
|
||||
|
||||
path := fmt.Sprintf("%s/v%s/%s", exmoAPIURL, exmoAPIVersion, endpoint)
|
||||
resp, err := common.SendHTTPRequest(method, path, headers, strings.NewReader(payload))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if e.Verbose {
|
||||
log.Printf("Received raw: \n%s\n", resp)
|
||||
}
|
||||
|
||||
var authResp AuthResponse
|
||||
err = common.JSONDecode([]byte(resp), &authResp)
|
||||
if err != nil {
|
||||
return errors.New("unable to JSON Unmarshal auth response")
|
||||
}
|
||||
|
||||
if !authResp.Result && authResp.Error != "" {
|
||||
return fmt.Errorf("auth error: %s", authResp.Error)
|
||||
}
|
||||
|
||||
err = common.JSONDecode([]byte(resp), &result)
|
||||
if err != nil {
|
||||
return errors.New("unable to JSON Unmarshal response")
|
||||
}
|
||||
return nil
|
||||
return e.SendPayload(method, path, headers, strings.NewReader(payload), result, true, e.Verbose)
|
||||
}
|
||||
|
||||
@@ -11,6 +11,10 @@ var (
|
||||
e EXMO
|
||||
)
|
||||
|
||||
func TestDefault(t *testing.T) {
|
||||
e.SetDefaults()
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
e.AuthenticatedAPISupport = true
|
||||
e.APIKey = APIKey
|
||||
@@ -18,6 +22,7 @@ func TestSetup(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetTrades(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := e.GetTrades("BTC_USD")
|
||||
if err != nil {
|
||||
t.Errorf("Test failed. Err: %s", err)
|
||||
|
||||
@@ -5,12 +5,14 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
@@ -46,6 +48,9 @@ const (
|
||||
gdaxWithdrawalCrypto = "withdrawals/crypto"
|
||||
gdaxCoinbaseAccounts = "coinbase-accounts"
|
||||
gdaxTrailingVolume = "users/self/trailing-volume"
|
||||
|
||||
gdaxAuthRate = 0
|
||||
gdaxUnauthRate = 0
|
||||
)
|
||||
|
||||
var sometin []string
|
||||
@@ -53,6 +58,7 @@ var sometin []string
|
||||
// GDAX is the overarching type across the GDAX package
|
||||
type GDAX struct {
|
||||
exchange.Base
|
||||
*request.Handler
|
||||
}
|
||||
|
||||
// SetDefaults sets default values for the exchange
|
||||
@@ -71,6 +77,8 @@ func (g *GDAX) SetDefaults() {
|
||||
g.AssetTypes = []string{ticker.Spot}
|
||||
g.APIUrl = gdaxAPIURL
|
||||
g.SupportsAutoPairUpdating = true
|
||||
g.Handler = new(request.Handler)
|
||||
g.SetRequestHandler(g.Name, gdaxAuthRate, gdaxUnauthRate, new(http.Client))
|
||||
}
|
||||
|
||||
// Setup initialises the exchange parameters with the current configuration
|
||||
@@ -118,8 +126,7 @@ func (g *GDAX) GetFee(maker bool) float64 {
|
||||
func (g *GDAX) GetProducts() ([]Product, error) {
|
||||
products := []Product{}
|
||||
|
||||
return products,
|
||||
common.SendHTTPGetRequest(g.APIUrl+gdaxProducts, true, g.Verbose, &products)
|
||||
return products, g.SendHTTPRequest(g.APIUrl+gdaxProducts, &products)
|
||||
}
|
||||
|
||||
// GetOrderbook returns orderbook by currency pair and level
|
||||
@@ -132,7 +139,7 @@ func (g *GDAX) GetOrderbook(symbol string, level int) (interface{}, error) {
|
||||
path = fmt.Sprintf("%s/%s/%s?level=%s", g.APIUrl+gdaxProducts, symbol, gdaxOrderbook, levelStr)
|
||||
}
|
||||
|
||||
if err := common.SendHTTPGetRequest(path, true, g.Verbose, &orderbook); err != nil {
|
||||
if err := g.SendHTTPRequest(path, &orderbook); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -201,7 +208,7 @@ func (g *GDAX) GetTicker(currencyPair string) (Ticker, error) {
|
||||
path := fmt.Sprintf(
|
||||
"%s/%s/%s", g.APIUrl+gdaxProducts, currencyPair, gdaxTicker)
|
||||
|
||||
return ticker, common.SendHTTPGetRequest(path, true, g.Verbose, &ticker)
|
||||
return ticker, g.SendHTTPRequest(path, &ticker)
|
||||
}
|
||||
|
||||
// GetTrades listd the latest trades for a product
|
||||
@@ -211,7 +218,7 @@ func (g *GDAX) GetTrades(currencyPair string) ([]Trade, error) {
|
||||
path := fmt.Sprintf(
|
||||
"%s/%s/%s", g.APIUrl+gdaxProducts, currencyPair, gdaxTrades)
|
||||
|
||||
return trades, common.SendHTTPGetRequest(path, true, g.Verbose, &trades)
|
||||
return trades, g.SendHTTPRequest(path, &trades)
|
||||
}
|
||||
|
||||
// GetHistoricRates returns historic rates for a product. Rates are returned in
|
||||
@@ -237,7 +244,7 @@ func (g *GDAX) GetHistoricRates(currencyPair string, start, end, granularity int
|
||||
fmt.Sprintf("%s/%s/%s", g.APIUrl+gdaxProducts, currencyPair, gdaxHistory),
|
||||
values)
|
||||
|
||||
if err := common.SendHTTPGetRequest(path, true, g.Verbose, &resp); err != nil {
|
||||
if err := g.SendHTTPRequest(path, &resp); err != nil {
|
||||
return history, err
|
||||
}
|
||||
|
||||
@@ -268,7 +275,7 @@ func (g *GDAX) GetStats(currencyPair string) (Stats, error) {
|
||||
path := fmt.Sprintf(
|
||||
"%s/%s/%s", g.APIUrl+gdaxProducts, currencyPair, gdaxStats)
|
||||
|
||||
return stats, common.SendHTTPGetRequest(path, true, g.Verbose, &stats)
|
||||
return stats, g.SendHTTPRequest(path, &stats)
|
||||
}
|
||||
|
||||
// GetCurrencies returns a list of supported currency on the exchange
|
||||
@@ -276,16 +283,14 @@ func (g *GDAX) GetStats(currencyPair string) (Stats, error) {
|
||||
func (g *GDAX) GetCurrencies() ([]Currency, error) {
|
||||
currencies := []Currency{}
|
||||
|
||||
return currencies,
|
||||
common.SendHTTPGetRequest(g.APIUrl+gdaxCurrencies, true, g.Verbose, ¤cies)
|
||||
return currencies, g.SendHTTPRequest(g.APIUrl+gdaxCurrencies, ¤cies)
|
||||
}
|
||||
|
||||
// GetServerTime returns the API server time
|
||||
func (g *GDAX) GetServerTime() (ServerTime, error) {
|
||||
serverTime := ServerTime{}
|
||||
|
||||
return serverTime,
|
||||
common.SendHTTPGetRequest(g.APIUrl+gdaxTime, true, g.Verbose, &serverTime)
|
||||
return serverTime, g.SendHTTPRequest(g.APIUrl+gdaxTime, &serverTime)
|
||||
}
|
||||
|
||||
// GetAccounts returns a list of trading accounts associated with the APIKEYS
|
||||
@@ -766,6 +771,11 @@ func (g *GDAX) GetTrailingVolume() ([]Volume, error) {
|
||||
g.SendAuthenticatedHTTPRequest("GET", gdaxTrailingVolume, nil, &resp)
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (g *GDAX) SendHTTPRequest(path string, result interface{}) error {
|
||||
return g.SendPayload("GET", path, nil, nil, result, false, g.Verbose)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated HTTP reque
|
||||
func (g *GDAX) SendAuthenticatedHTTPRequest(method, path string, params map[string]interface{}, result interface{}) (err error) {
|
||||
if !g.AuthenticatedAPISupport {
|
||||
@@ -795,24 +805,5 @@ func (g *GDAX) SendAuthenticatedHTTPRequest(method, path string, params map[stri
|
||||
headers["CB-ACCESS-PASSPHRASE"] = g.ClientID
|
||||
headers["Content-Type"] = "application/json"
|
||||
|
||||
resp, err := common.SendHTTPRequest(method, g.APIUrl+path, headers, bytes.NewBuffer(payload))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if g.Verbose {
|
||||
log.Printf("Received raw: \n%s\n", resp)
|
||||
}
|
||||
|
||||
type initialResponse struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
initialCheck := initialResponse{}
|
||||
|
||||
err = common.JSONDecode([]byte(resp), &initialCheck)
|
||||
if err == nil && len(initialCheck.Message) != 0 {
|
||||
return errors.New(initialCheck.Message)
|
||||
}
|
||||
|
||||
return common.JSONDecode([]byte(resp), &result)
|
||||
return g.SendPayload(method, g.APIUrl+path, headers, bytes.NewBuffer(payload), result, true, g.Verbose)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -11,6 +12,7 @@ import (
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
@@ -39,13 +41,9 @@ const (
|
||||
geminiWithdraw = "withdraw/"
|
||||
geminiHeartbeat = "heartbeat"
|
||||
|
||||
// rate limits per minute
|
||||
geminiPublicRate = 120
|
||||
geminiPrivateRate = 600
|
||||
|
||||
// rates limits per second
|
||||
geminiPublicRateSec = 1
|
||||
geminiPrivateRateSec = 5
|
||||
// gemini limit rates
|
||||
geminiAuthRate = 100
|
||||
geminiUnauthRate = 500
|
||||
|
||||
// Too many requests returns this
|
||||
geminiRateError = "429"
|
||||
@@ -57,7 +55,8 @@ const (
|
||||
|
||||
var (
|
||||
// Session manager
|
||||
Session map[int]*Gemini
|
||||
Session map[int]*Gemini
|
||||
gHandler *request.Handler
|
||||
)
|
||||
|
||||
// Gemini is the overarching type across the Gemini package, create multiple
|
||||
@@ -69,6 +68,7 @@ type Gemini struct {
|
||||
exchange.Base
|
||||
Role string
|
||||
RequiresHeartBeat bool
|
||||
*request.Handler
|
||||
}
|
||||
|
||||
// AddSession adds a new session to the gemini base
|
||||
@@ -76,6 +76,9 @@ func AddSession(g *Gemini, sessionID int, apiKey, apiSecret, role string, needsH
|
||||
if Session == nil {
|
||||
Session = make(map[int]*Gemini)
|
||||
}
|
||||
if gHandler == nil {
|
||||
gHandler = new(request.Handler)
|
||||
}
|
||||
|
||||
_, ok := Session[sessionID]
|
||||
if ok {
|
||||
@@ -110,6 +113,14 @@ func (g *Gemini) SetDefaults() {
|
||||
g.ConfigCurrencyPairFormat.Uppercase = true
|
||||
g.AssetTypes = []string{ticker.Spot}
|
||||
g.SupportsAutoPairUpdating = true
|
||||
if gHandler != nil {
|
||||
g.Handler = gHandler
|
||||
} else {
|
||||
g.Handler = new(request.Handler)
|
||||
}
|
||||
if g.Handler.Client == nil {
|
||||
g.SetRequestHandler(g.Name, geminiAuthRate, geminiUnauthRate, new(http.Client))
|
||||
}
|
||||
}
|
||||
|
||||
// Setup sets exchange configuration parameters
|
||||
@@ -151,28 +162,33 @@ func (g *Gemini) GetSymbols() ([]string, error) {
|
||||
symbols := []string{}
|
||||
path := fmt.Sprintf("%s/v%s/%s", g.APIUrl, geminiAPIVersion, geminiSymbols)
|
||||
|
||||
return symbols, common.SendHTTPGetRequest(path, true, g.Verbose, &symbols)
|
||||
return symbols, g.SendHTTPRequest(path, &symbols)
|
||||
}
|
||||
|
||||
// GetTicker returns information about recent trading activity for the symbol
|
||||
func (g *Gemini) GetTicker(currencyPair string) (Ticker, error) {
|
||||
|
||||
type TickerResponse struct {
|
||||
Ask float64 `json:"ask,string"`
|
||||
Bid float64 `json:"bid,string"`
|
||||
Last float64 `json:"last,string"`
|
||||
Volume map[string]interface{}
|
||||
Ask float64 `json:"ask,string"`
|
||||
Bid float64 `json:"bid,string"`
|
||||
Last float64 `json:"last,string"`
|
||||
Volume map[string]interface{}
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
ticker := Ticker{}
|
||||
resp := TickerResponse{}
|
||||
path := fmt.Sprintf("%s/v%s/%s/%s", g.APIUrl, geminiAPIVersion, geminiTicker, currencyPair)
|
||||
|
||||
err := common.SendHTTPGetRequest(path, true, g.Verbose, &resp)
|
||||
err := g.SendHTTPRequest(path, &resp)
|
||||
if err != nil {
|
||||
return ticker, err
|
||||
}
|
||||
|
||||
if resp.Message != "" {
|
||||
return ticker, errors.New(resp.Message)
|
||||
}
|
||||
|
||||
ticker.Ask = resp.Ask
|
||||
ticker.Bid = resp.Bid
|
||||
ticker.Last = resp.Last
|
||||
@@ -201,7 +217,7 @@ func (g *Gemini) GetOrderbook(currencyPair string, params url.Values) (Orderbook
|
||||
path := common.EncodeURLValues(fmt.Sprintf("%s/v%s/%s/%s", g.APIUrl, geminiAPIVersion, geminiOrderbook, currencyPair), params)
|
||||
orderbook := Orderbook{}
|
||||
|
||||
return orderbook, common.SendHTTPGetRequest(path, true, g.Verbose, &orderbook)
|
||||
return orderbook, g.SendHTTPRequest(path, &orderbook)
|
||||
}
|
||||
|
||||
// GetTrades eturn the trades that have executed since the specified timestamp.
|
||||
@@ -217,7 +233,7 @@ func (g *Gemini) GetTrades(currencyPair string, params url.Values) ([]Trade, err
|
||||
path := common.EncodeURLValues(fmt.Sprintf("%s/v%s/%s/%s", g.APIUrl, geminiAPIVersion, geminiTrades, currencyPair), params)
|
||||
trades := []Trade{}
|
||||
|
||||
return trades, common.SendHTTPGetRequest(path, true, g.Verbose, &trades)
|
||||
return trades, g.SendHTTPRequest(path, &trades)
|
||||
}
|
||||
|
||||
// GetAuction returns auction information
|
||||
@@ -225,7 +241,7 @@ func (g *Gemini) GetAuction(currencyPair string) (Auction, error) {
|
||||
path := fmt.Sprintf("%s/v%s/%s/%s", g.APIUrl, geminiAPIVersion, geminiAuction, currencyPair)
|
||||
auction := Auction{}
|
||||
|
||||
return auction, common.SendHTTPGetRequest(path, true, g.Verbose, &auction)
|
||||
return auction, g.SendHTTPRequest(path, &auction)
|
||||
}
|
||||
|
||||
// GetAuctionHistory returns the auction events, optionally including
|
||||
@@ -243,7 +259,7 @@ func (g *Gemini) GetAuctionHistory(currencyPair string, params url.Values) ([]Au
|
||||
path := common.EncodeURLValues(fmt.Sprintf("%s/v%s/%s/%s/%s", g.APIUrl, geminiAPIVersion, geminiAuction, currencyPair, geminiAuctionHistory), params)
|
||||
auctionHist := []AuctionHistory{}
|
||||
|
||||
return auctionHist, common.SendHTTPGetRequest(path, true, g.Verbose, &auctionHist)
|
||||
return auctionHist, g.SendHTTPRequest(path, &auctionHist)
|
||||
}
|
||||
|
||||
func (g *Gemini) isCorrectSession(role string) error {
|
||||
@@ -286,6 +302,10 @@ func (g *Gemini) CancelOrder(OrderID int64) (Order, error) {
|
||||
if err != nil {
|
||||
return Order{}, err
|
||||
}
|
||||
if response.Message != "" {
|
||||
return response, errors.New(response.Message)
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
|
||||
@@ -300,7 +320,14 @@ func (g *Gemini) CancelOrders(CancelBySession bool) (OrderResult, error) {
|
||||
path = geminiOrderCancelSession
|
||||
}
|
||||
|
||||
return response, g.SendAuthenticatedHTTPRequest("POST", path, nil, &response)
|
||||
err := g.SendAuthenticatedHTTPRequest("POST", path, nil, &response)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
if response.Message != "" {
|
||||
return response, errors.New(response.Message)
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// GetOrderStatus returns the status for an order
|
||||
@@ -310,16 +337,32 @@ func (g *Gemini) GetOrderStatus(orderID int64) (Order, error) {
|
||||
|
||||
response := Order{}
|
||||
|
||||
return response,
|
||||
g.SendAuthenticatedHTTPRequest("POST", geminiOrderStatus, request, &response)
|
||||
err := g.SendAuthenticatedHTTPRequest("POST", geminiOrderStatus, request, &response)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
|
||||
if response.Message != "" {
|
||||
return response, errors.New(response.Message)
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// GetOrders returns active orders in the market
|
||||
func (g *Gemini) GetOrders() ([]Order, error) {
|
||||
response := []Order{}
|
||||
var response struct {
|
||||
orders []Order
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
return response,
|
||||
g.SendAuthenticatedHTTPRequest("POST", geminiOrders, nil, &response)
|
||||
err := g.SendAuthenticatedHTTPRequest("POST", geminiOrders, nil, &response)
|
||||
if err != nil {
|
||||
return response.orders, err
|
||||
}
|
||||
if response.Message != "" {
|
||||
return response.orders, errors.New(response.Message)
|
||||
}
|
||||
return response.orders, nil
|
||||
}
|
||||
|
||||
// GetTradeHistory returns an array of trades that have been on the exchange
|
||||
@@ -359,8 +402,14 @@ func (g *Gemini) GetBalances() ([]Balance, error) {
|
||||
func (g *Gemini) GetDepositAddress(depositAddlabel, currency string) (DepositAddress, error) {
|
||||
response := DepositAddress{}
|
||||
|
||||
return response,
|
||||
g.SendAuthenticatedHTTPRequest("POST", geminiDeposit+"/"+currency+"/"+geminiNewAddress, nil, &response)
|
||||
err := g.SendAuthenticatedHTTPRequest("POST", geminiDeposit+"/"+currency+"/"+geminiNewAddress, nil, &response)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
if response.Message != "" {
|
||||
return response, errors.New(response.Message)
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// WithdrawCrypto withdraws crypto currency to a whitelisted address
|
||||
@@ -370,20 +419,38 @@ func (g *Gemini) WithdrawCrypto(address, currency string, amount float64) (Withd
|
||||
request["address"] = address
|
||||
request["amount"] = strconv.FormatFloat(amount, 'f', -1, 64)
|
||||
|
||||
return response,
|
||||
g.SendAuthenticatedHTTPRequest("POST", geminiWithdraw+currency, nil, &response)
|
||||
err := g.SendAuthenticatedHTTPRequest("POST", geminiWithdraw+currency, nil, &response)
|
||||
if err != nil {
|
||||
return response, err
|
||||
}
|
||||
if response.Message != "" {
|
||||
return response, errors.New(response.Message)
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
||||
// PostHeartbeat sends a maintenance heartbeat to the exchange for all heartbeat
|
||||
// maintaned sessions
|
||||
func (g *Gemini) PostHeartbeat() (string, error) {
|
||||
type Response struct {
|
||||
Result string `json:"result"`
|
||||
Result string `json:"result"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
response := Response{}
|
||||
|
||||
return response.Result,
|
||||
g.SendAuthenticatedHTTPRequest("POST", geminiHeartbeat, nil, &response)
|
||||
err := g.SendAuthenticatedHTTPRequest("POST", geminiHeartbeat, nil, &response)
|
||||
if err != nil {
|
||||
return response.Result, err
|
||||
}
|
||||
if response.Message != "" {
|
||||
return response.Result, errors.New(response.Message)
|
||||
}
|
||||
return response.Result, nil
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated request
|
||||
func (g *Gemini) SendHTTPRequest(path string, result interface{}) error {
|
||||
return g.SendPayload("GET", path, nil, nil, result, false, g.Verbose)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request to the
|
||||
@@ -420,23 +487,5 @@ func (g *Gemini) SendAuthenticatedHTTPRequest(method, path string, params map[st
|
||||
headers["X-GEMINI-PAYLOAD"] = PayloadBase64
|
||||
headers["X-GEMINI-SIGNATURE"] = common.HexEncodeToString(hmac)
|
||||
|
||||
resp, err := common.SendHTTPRequest(method, g.APIUrl+"/v1/"+path, headers, strings.NewReader(""))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if g.Verbose {
|
||||
log.Printf("Received raw: \n%s\n", resp)
|
||||
}
|
||||
|
||||
captureErr := ErrorCapture{}
|
||||
if err = common.JSONDecode([]byte(resp), &captureErr); err == nil {
|
||||
if len(captureErr.Message) != 0 || len(captureErr.Result) != 0 || len(captureErr.Reason) != 0 {
|
||||
if captureErr.Result != "ok" {
|
||||
return errors.New(captureErr.Message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return common.JSONDecode([]byte(resp), &result)
|
||||
return g.SendPayload(method, g.APIUrl+"/v1/"+path, headers, strings.NewReader(""), result, true, g.Verbose)
|
||||
}
|
||||
|
||||
@@ -7,10 +7,6 @@ import (
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
)
|
||||
|
||||
var (
|
||||
g Gemini
|
||||
)
|
||||
|
||||
// Please enter sandbox API keys & assigned roles for better testing procedures
|
||||
|
||||
const (
|
||||
@@ -26,15 +22,17 @@ const (
|
||||
)
|
||||
|
||||
func TestAddSession(t *testing.T) {
|
||||
err := AddSession(&g, 1, apiKey1, apiSecret1, apiKeyRole1, true, false)
|
||||
var g1 Gemini
|
||||
err := AddSession(&g1, 1, apiKey1, apiSecret1, apiKeyRole1, true, false)
|
||||
if err != nil {
|
||||
t.Error("Test failed - AddSession() error")
|
||||
}
|
||||
err = AddSession(&g, 1, apiKey1, apiSecret1, apiKeyRole1, true, false)
|
||||
err = AddSession(&g1, 1, apiKey1, apiSecret1, apiKeyRole1, true, false)
|
||||
if err == nil {
|
||||
t.Error("Test failed - AddSession() error")
|
||||
}
|
||||
err = AddSession(&g, 2, apiKey2, apiSecret2, apiKeyRole2, false, true)
|
||||
var g2 Gemini
|
||||
err = AddSession(&g2, 2, apiKey2, apiSecret2, apiKeyRole2, false, true)
|
||||
if err != nil {
|
||||
t.Error("Test failed - AddSession() error")
|
||||
}
|
||||
@@ -46,6 +44,7 @@ func TestSetDefaults(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
|
||||
cfg := config.GetConfig()
|
||||
cfg.LoadConfig("../../testdata/configtest.json")
|
||||
geminiConfig, err := cfg.GetExchangeConfig("Gemini")
|
||||
|
||||
@@ -74,6 +74,7 @@ type OrderResult struct {
|
||||
CancelledOrders []string `json:"cancelledOrders"`
|
||||
CancelRejects []string `json:"cancelRejects"`
|
||||
} `json:"details"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// Order contains order information
|
||||
@@ -97,6 +98,7 @@ type Order struct {
|
||||
ExecutedAmount float64 `json:"executed_amount,string"`
|
||||
RemainingAmount float64 `json:"remaining_amount,string"`
|
||||
OriginalAmount float64 `json:"original_amount,string"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// TradeHistory holds trade history information
|
||||
@@ -150,6 +152,7 @@ type DepositAddress struct {
|
||||
Currency string `json:"currency"`
|
||||
Address string `json:"address"`
|
||||
Label string `json:"label"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// WithdrawalAddress holds withdrawal information
|
||||
@@ -157,6 +160,7 @@ type WithdrawalAddress struct {
|
||||
Address string `json:"address"`
|
||||
Amount float64 `json:"amount"`
|
||||
TXHash string `json:"txHash"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// ErrorCapture is a generlized error response from the server
|
||||
|
||||
@@ -5,12 +5,14 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
@@ -39,11 +41,15 @@ const (
|
||||
orderMove = "moveOrder"
|
||||
tradableBalances = "returnTradableBalances"
|
||||
transferBalance = "transferBalance"
|
||||
|
||||
hitbtcAuthRate = 0
|
||||
hitbtcUnauthRate = 0
|
||||
)
|
||||
|
||||
// HitBTC is the overarching type across the hitbtc package
|
||||
type HitBTC struct {
|
||||
exchange.Base
|
||||
*request.Handler
|
||||
}
|
||||
|
||||
// SetDefaults sets default settings for hitbtc
|
||||
@@ -60,6 +66,8 @@ func (p *HitBTC) SetDefaults() {
|
||||
p.ConfigCurrencyPairFormat.Uppercase = true
|
||||
p.AssetTypes = []string{ticker.Spot}
|
||||
p.SupportsAutoPairUpdating = true
|
||||
p.Handler = new(request.Handler)
|
||||
p.SetRequestHandler(p.Name, hitbtcAuthRate, hitbtcUnauthRate, new(http.Client))
|
||||
}
|
||||
|
||||
// Setup sets user exchange configuration settings
|
||||
@@ -107,12 +115,16 @@ func (p *HitBTC) GetCurrencies(currency string) (map[string]Currencies, error) {
|
||||
}
|
||||
resp := Response{}
|
||||
path := fmt.Sprintf("%s/%s/%s", apiURL, apiV2Currency, currency)
|
||||
err := common.SendHTTPGetRequest(path, true, p.Verbose, &resp.Data)
|
||||
|
||||
ret := make(map[string]Currencies)
|
||||
err := p.SendHTTPRequest(path, &resp.Data)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
for _, id := range resp.Data {
|
||||
ret[id.ID] = id
|
||||
}
|
||||
|
||||
return ret, err
|
||||
}
|
||||
|
||||
@@ -124,12 +136,16 @@ func (p *HitBTC) GetCurrencies(currency string) (map[string]Currencies, error) {
|
||||
func (p *HitBTC) GetSymbols(symbol string) ([]string, error) {
|
||||
resp := []Symbol{}
|
||||
path := fmt.Sprintf("%s/%s/%s", apiURL, apiV2Symbol, symbol)
|
||||
err := common.SendHTTPGetRequest(path, true, p.Verbose, &resp)
|
||||
|
||||
ret := make([]string, 0, len(resp))
|
||||
err := p.SendHTTPRequest(path, &resp)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
|
||||
for _, x := range resp {
|
||||
ret = append(ret, x.ID)
|
||||
}
|
||||
|
||||
return ret, err
|
||||
}
|
||||
|
||||
@@ -138,7 +154,8 @@ func (p *HitBTC) GetSymbols(symbol string) ([]string, error) {
|
||||
func (p *HitBTC) GetSymbolsDetailed() ([]Symbol, error) {
|
||||
resp := []Symbol{}
|
||||
path := fmt.Sprintf("%s/%s", apiURL, apiV2Symbol)
|
||||
return resp, common.SendHTTPGetRequest(path, true, p.Verbose, &resp)
|
||||
|
||||
return resp, p.SendHTTPRequest(path, &resp)
|
||||
}
|
||||
|
||||
// GetTicker returns ticker information
|
||||
@@ -151,7 +168,7 @@ func (p *HitBTC) GetTicker(symbol string) (map[string]Ticker, error) {
|
||||
var err error
|
||||
|
||||
if symbol == "" {
|
||||
err = common.SendHTTPGetRequest(path, true, false, &resp1)
|
||||
err = p.SendHTTPRequest(path, &resp1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -162,7 +179,7 @@ func (p *HitBTC) GetTicker(symbol string) (map[string]Ticker, error) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
err = common.SendHTTPGetRequest(path, true, false, &resp2)
|
||||
err = p.SendHTTPRequest(path, &resp2)
|
||||
ret[resp2.Symbol] = resp2
|
||||
}
|
||||
|
||||
@@ -240,7 +257,7 @@ 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())
|
||||
|
||||
return resp, common.SendHTTPGetRequest(path, true, p.Verbose, &resp)
|
||||
return resp, p.SendHTTPRequest(path, &resp)
|
||||
}
|
||||
|
||||
// GetOrderbook an order book is an electronic list of buy and sell orders for a
|
||||
@@ -256,7 +273,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())
|
||||
|
||||
err := common.SendHTTPGetRequest(path, true, p.Verbose, &resp)
|
||||
err := p.SendHTTPRequest(path, &resp)
|
||||
if err != nil {
|
||||
return Orderbook{}, err
|
||||
}
|
||||
@@ -290,7 +307,7 @@ func (p *HitBTC) GetCandles(currencyPair, limit, period string) ([]ChartData, er
|
||||
resp := []ChartData{}
|
||||
path := fmt.Sprintf("%s/%s/%s?%s", apiURL, apiV2Candles, currencyPair, vals.Encode())
|
||||
|
||||
return resp, common.SendHTTPGetRequest(path, true, p.Verbose, &resp)
|
||||
return resp, p.SendHTTPRequest(path, &resp)
|
||||
}
|
||||
|
||||
// Authenticated Market Data
|
||||
@@ -516,6 +533,11 @@ func (p *HitBTC) TransferBalance(currency, from, to string, amount float64) (boo
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (p *HitBTC) SendHTTPRequest(path string, result interface{}) error {
|
||||
return p.SendPayload("GET", path, nil, nil, result, false, p.Verbose)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated http request
|
||||
func (p *HitBTC) SendAuthenticatedHTTPRequest(method, endpoint string, values url.Values, result interface{}) error {
|
||||
if !p.AuthenticatedAPISupport {
|
||||
@@ -526,15 +548,5 @@ func (p *HitBTC) SendAuthenticatedHTTPRequest(method, endpoint string, values ur
|
||||
|
||||
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 err
|
||||
}
|
||||
|
||||
return nil
|
||||
return p.SendPayload(method, path, headers, bytes.NewBufferString(values.Encode()), result, true, p.Verbose)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
@@ -12,6 +13,7 @@ import (
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
@@ -45,11 +47,15 @@ const (
|
||||
huobiMarginAccountBalance = "margin/accounts/balance"
|
||||
huobiWithdrawCreate = "dw/withdraw/api/create"
|
||||
huobiWithdrawCancel = "dw/withdraw-virtual/%s/cancel"
|
||||
|
||||
huobiAuthRate = 0
|
||||
huobiUnauthRate = 0
|
||||
)
|
||||
|
||||
// HUOBI is the overarching type across this package
|
||||
type HUOBI struct {
|
||||
exchange.Base
|
||||
*request.Handler
|
||||
}
|
||||
|
||||
// SetDefaults sets default values for the exchange
|
||||
@@ -66,6 +72,8 @@ func (h *HUOBI) SetDefaults() {
|
||||
h.ConfigCurrencyPairFormat.Uppercase = true
|
||||
h.AssetTypes = []string{ticker.Spot}
|
||||
h.SupportsAutoPairUpdating = true
|
||||
h.Handler = new(request.Handler)
|
||||
h.SetRequestHandler(h.Name, huobiAuthRate, huobiUnauthRate, new(http.Client))
|
||||
}
|
||||
|
||||
// Setup sets user configuration
|
||||
@@ -122,8 +130,8 @@ func (h *HUOBI) GetKline(symbol, period, size string) ([]Klines, error) {
|
||||
|
||||
var result response
|
||||
url := fmt.Sprintf("%s/%s", huobiAPIURL, huobiMarketHistoryKline)
|
||||
err := common.SendHTTPGetRequest(common.EncodeURLValues(url, vals), true, h.Verbose, &result)
|
||||
|
||||
err := h.SendHTTPRequest(common.EncodeURLValues(url, vals), &result)
|
||||
if result.ErrorMessage != "" {
|
||||
return nil, errors.New(result.ErrorMessage)
|
||||
}
|
||||
@@ -142,8 +150,8 @@ func (h *HUOBI) GetMarketDetailMerged(symbol string) (DetailMerged, error) {
|
||||
|
||||
var result response
|
||||
url := fmt.Sprintf("%s/%s", huobiAPIURL, huobiMarketDetailMerged)
|
||||
err := common.SendHTTPGetRequest(common.EncodeURLValues(url, vals), true, h.Verbose, &result)
|
||||
|
||||
err := h.SendHTTPRequest(common.EncodeURLValues(url, vals), &result)
|
||||
if result.ErrorMessage != "" {
|
||||
return result.Tick, errors.New(result.ErrorMessage)
|
||||
}
|
||||
@@ -166,8 +174,8 @@ func (h *HUOBI) GetDepth(symbol, depthType string) (Orderbook, error) {
|
||||
|
||||
var result response
|
||||
url := fmt.Sprintf("%s/%s", huobiAPIURL, huobiMarketDepth)
|
||||
err := common.SendHTTPGetRequest(common.EncodeURLValues(url, vals), true, h.Verbose, &result)
|
||||
|
||||
err := h.SendHTTPRequest(common.EncodeURLValues(url, vals), &result)
|
||||
if result.ErrorMessage != "" {
|
||||
return result.Depth, errors.New(result.ErrorMessage)
|
||||
}
|
||||
@@ -188,8 +196,8 @@ func (h *HUOBI) GetTrades(symbol string) ([]Trade, error) {
|
||||
|
||||
var result response
|
||||
url := fmt.Sprintf("%s/%s", huobiAPIURL, huobiMarketTrade)
|
||||
err := common.SendHTTPGetRequest(common.EncodeURLValues(url, vals), true, h.Verbose, &result)
|
||||
|
||||
err := h.SendHTTPRequest(common.EncodeURLValues(url, vals), &result)
|
||||
if result.ErrorMessage != "" {
|
||||
return nil, errors.New(result.ErrorMessage)
|
||||
}
|
||||
@@ -212,8 +220,8 @@ func (h *HUOBI) GetTradeHistory(symbol, size string) ([]TradeHistory, error) {
|
||||
|
||||
var result response
|
||||
url := fmt.Sprintf("%s/%s", huobiAPIURL, huobiMarketTradeHistory)
|
||||
err := common.SendHTTPGetRequest(common.EncodeURLValues(url, vals), true, h.Verbose, &result)
|
||||
|
||||
err := h.SendHTTPRequest(common.EncodeURLValues(url, vals), &result)
|
||||
if result.ErrorMessage != "" {
|
||||
return nil, errors.New(result.ErrorMessage)
|
||||
}
|
||||
@@ -232,8 +240,8 @@ func (h *HUOBI) GetMarketDetail(symbol string) (Detail, error) {
|
||||
|
||||
var result response
|
||||
url := fmt.Sprintf("%s/%s", huobiAPIURL, huobiMarketDetail)
|
||||
err := common.SendHTTPGetRequest(common.EncodeURLValues(url, vals), true, h.Verbose, &result)
|
||||
|
||||
err := h.SendHTTPRequest(common.EncodeURLValues(url, vals), &result)
|
||||
if result.ErrorMessage != "" {
|
||||
return result.Tick, errors.New(result.ErrorMessage)
|
||||
}
|
||||
@@ -249,8 +257,8 @@ func (h *HUOBI) GetSymbols() ([]Symbol, error) {
|
||||
|
||||
var result response
|
||||
url := fmt.Sprintf("%s/v%s/%s", huobiAPIURL, huobiAPIVersion, huobiSymbols)
|
||||
err := common.SendHTTPGetRequest(url, true, h.Verbose, &result)
|
||||
|
||||
err := h.SendHTTPRequest(url, &result)
|
||||
if result.ErrorMessage != "" {
|
||||
return nil, errors.New(result.ErrorMessage)
|
||||
}
|
||||
@@ -266,8 +274,8 @@ func (h *HUOBI) GetCurrencies() ([]string, error) {
|
||||
|
||||
var result response
|
||||
url := fmt.Sprintf("%s/v%s/%s", huobiAPIURL, huobiAPIVersion, huobiCurrencies)
|
||||
err := common.SendHTTPGetRequest(url, true, h.Verbose, &result)
|
||||
|
||||
err := h.SendHTTPRequest(url, &result)
|
||||
if result.ErrorMessage != "" {
|
||||
return nil, errors.New(result.ErrorMessage)
|
||||
}
|
||||
@@ -283,8 +291,8 @@ func (h *HUOBI) GetTimestamp() (int64, error) {
|
||||
|
||||
var result response
|
||||
url := fmt.Sprintf("%s/v%s/%s", huobiAPIURL, huobiAPIVersion, huobiTimestamp)
|
||||
err := common.SendHTTPGetRequest(url, true, h.Verbose, &result)
|
||||
|
||||
err := h.SendHTTPRequest(url, &result)
|
||||
if result.ErrorMessage != "" {
|
||||
return 0, errors.New(result.ErrorMessage)
|
||||
}
|
||||
@@ -692,6 +700,11 @@ func (h *HUOBI) CancelWithdraw(withdrawID int64) (int64, error) {
|
||||
return result.WithdrawID, err
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (h *HUOBI) SendHTTPRequest(path string, result interface{}) error {
|
||||
return h.SendPayload("GET", path, nil, nil, result, false, h.Verbose)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends authenticated requests to the HUOBI API
|
||||
func (h *HUOBI) SendAuthenticatedHTTPRequest(method, endpoint string, values url.Values, result interface{}) error {
|
||||
if !h.AuthenticatedAPISupport {
|
||||
@@ -715,16 +728,6 @@ func (h *HUOBI) SendAuthenticatedHTTPRequest(method, endpoint string, values url
|
||||
|
||||
url := fmt.Sprintf("%s%s", huobiAPIURL, endpoint)
|
||||
url = common.EncodeURLValues(url, values)
|
||||
resp, err := common.SendHTTPRequest(method, url, headers, bytes.NewBufferString(""))
|
||||
|
||||
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 h.SendPayload(method, url, headers, bytes.NewBufferString(""), result, true, h.Verbose)
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
@@ -12,6 +13,7 @@ import (
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
@@ -28,11 +30,15 @@ const (
|
||||
itbitOrders = "orders"
|
||||
itbitCryptoDeposits = "cryptocurrency_deposits"
|
||||
itbitWalletTransfer = "wallet_transfers"
|
||||
|
||||
itbitAuthRate = 0
|
||||
itbitUnauthRate = 0
|
||||
)
|
||||
|
||||
// ItBit is the overarching type across the ItBit package
|
||||
type ItBit struct {
|
||||
exchange.Base
|
||||
*request.Handler
|
||||
}
|
||||
|
||||
// SetDefaults sets the defaults for the exchange
|
||||
@@ -50,6 +56,8 @@ func (i *ItBit) SetDefaults() {
|
||||
i.ConfigCurrencyPairFormat.Uppercase = true
|
||||
i.AssetTypes = []string{ticker.Spot}
|
||||
i.SupportsAutoPairUpdating = false
|
||||
i.Handler = new(request.Handler)
|
||||
i.SetRequestHandler(i.Name, itbitAuthRate, itbitUnauthRate, new(http.Client))
|
||||
}
|
||||
|
||||
// Setup sets the exchange parameters from exchange config
|
||||
@@ -95,8 +103,7 @@ func (i *ItBit) GetTicker(currencyPair string) (Ticker, error) {
|
||||
var response Ticker
|
||||
path := fmt.Sprintf("%s/%s/%s/%s", itbitAPIURL, itbitMarkets, currencyPair, itbitTicker)
|
||||
|
||||
return response,
|
||||
common.SendHTTPGetRequest(path, true, i.Verbose, &response)
|
||||
return response, i.SendHTTPRequest(path, &response)
|
||||
}
|
||||
|
||||
// GetOrderbook returns full order book for the specified market.
|
||||
@@ -105,8 +112,7 @@ func (i *ItBit) GetOrderbook(currencyPair string) (OrderbookResponse, error) {
|
||||
response := OrderbookResponse{}
|
||||
path := fmt.Sprintf("%s/%s/%s/%s", itbitAPIURL, itbitMarkets, currencyPair, itbitOrderbook)
|
||||
|
||||
return response,
|
||||
common.SendHTTPGetRequest(path, true, i.Verbose, &response)
|
||||
return response, i.SendHTTPRequest(path, &response)
|
||||
}
|
||||
|
||||
// GetTradeHistory returns recent trades for a specified market.
|
||||
@@ -118,8 +124,7 @@ func (i *ItBit) GetTradeHistory(currencyPair, timestamp string) (Trades, error)
|
||||
req := "trades?since=" + timestamp
|
||||
path := fmt.Sprintf("%s/%s/%s/%s", itbitAPIURL, itbitMarkets, currencyPair, req)
|
||||
|
||||
return response,
|
||||
common.SendHTTPGetRequest(path, true, i.Verbose, &response)
|
||||
return response, i.SendHTTPRequest(path, &response)
|
||||
}
|
||||
|
||||
// GetWallets returns information about all wallets associated with the account.
|
||||
@@ -142,8 +147,14 @@ func (i *ItBit) CreateWallet(walletName string) (Wallet, error) {
|
||||
params["userId"] = i.ClientID
|
||||
params["name"] = walletName
|
||||
|
||||
return resp,
|
||||
i.SendAuthenticatedHTTPRequest("POST", "/"+itbitWallets, params, &resp)
|
||||
err := i.SendAuthenticatedHTTPRequest("POST", "/"+itbitWallets, params, &resp)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
if resp.Description != "" {
|
||||
return resp, errors.New(resp.Description)
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GetWallet returns wallet information by walletID
|
||||
@@ -151,7 +162,14 @@ func (i *ItBit) GetWallet(walletID string) (Wallet, error) {
|
||||
resp := Wallet{}
|
||||
path := fmt.Sprintf("/%s/%s", itbitWallets, walletID)
|
||||
|
||||
return resp, i.SendAuthenticatedHTTPRequest("GET", path, nil, &resp)
|
||||
err := i.SendAuthenticatedHTTPRequest("GET", path, nil, &resp)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
if resp.Description != "" {
|
||||
return resp, errors.New(resp.Description)
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GetWalletBalance returns balance information for a specific currency in a
|
||||
@@ -160,7 +178,14 @@ func (i *ItBit) GetWalletBalance(walletID, currency string) (Balance, error) {
|
||||
resp := Balance{}
|
||||
path := fmt.Sprintf("/%s/%s/%s/%s", itbitWallets, walletID, itbitBalances, currency)
|
||||
|
||||
return resp, i.SendAuthenticatedHTTPRequest("GET", path, nil, &resp)
|
||||
err := i.SendAuthenticatedHTTPRequest("GET", path, nil, &resp)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
if resp.Description != "" {
|
||||
return resp, errors.New(resp.Description)
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GetWalletTrades returns all trades for a specified wallet.
|
||||
@@ -169,7 +194,14 @@ func (i *ItBit) GetWalletTrades(walletID string, params url.Values) (Records, er
|
||||
url := fmt.Sprintf("/%s/%s/%s", itbitWallets, walletID, itbitTrades)
|
||||
path := common.EncodeURLValues(url, params)
|
||||
|
||||
return resp, i.SendAuthenticatedHTTPRequest("GET", path, nil, &resp)
|
||||
err := i.SendAuthenticatedHTTPRequest("GET", path, nil, &resp)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
if resp.Description != "" {
|
||||
return resp, errors.New(resp.Description)
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GetFundingHistory returns all funding history for a specified wallet.
|
||||
@@ -178,7 +210,14 @@ func (i *ItBit) GetFundingHistory(walletID string, params url.Values) (FundingRe
|
||||
url := fmt.Sprintf("/%s/%s/%s", itbitWallets, walletID, itbitFundingHistory)
|
||||
path := common.EncodeURLValues(url, params)
|
||||
|
||||
return resp, i.SendAuthenticatedHTTPRequest("GET", path, nil, &resp)
|
||||
err := i.SendAuthenticatedHTTPRequest("GET", path, nil, &resp)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
if resp.Description != "" {
|
||||
return resp, errors.New(resp.Description)
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// PlaceOrder places a new order
|
||||
@@ -198,7 +237,14 @@ func (i *ItBit) PlaceOrder(walletID, side, orderType, currency string, amount, p
|
||||
params["clientOrderIdentifier"] = clientRef
|
||||
}
|
||||
|
||||
return resp, i.SendAuthenticatedHTTPRequest("POST", path, params, &resp)
|
||||
err := i.SendAuthenticatedHTTPRequest("POST", path, params, &resp)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
if resp.Description != "" {
|
||||
return resp, errors.New(resp.Description)
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GetOrder returns an order by id.
|
||||
@@ -207,7 +253,14 @@ func (i *ItBit) GetOrder(walletID string, params url.Values) (Order, error) {
|
||||
url := fmt.Sprintf("/%s/%s/%s", itbitWallets, walletID, itbitOrders)
|
||||
path := common.EncodeURLValues(url, params)
|
||||
|
||||
return resp, i.SendAuthenticatedHTTPRequest("GET", path, nil, &resp)
|
||||
err := i.SendAuthenticatedHTTPRequest("GET", path, nil, &resp)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
if resp.Description != "" {
|
||||
return resp, errors.New(resp.Description)
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// CancelOrder cancels and open order. *This is not a guarantee that the order
|
||||
@@ -225,7 +278,14 @@ func (i *ItBit) GetDepositAddress(walletID, currency string) (CryptoCurrencyDepo
|
||||
params := make(map[string]interface{})
|
||||
params["currency"] = currency
|
||||
|
||||
return resp, i.SendAuthenticatedHTTPRequest("POST", path, params, &resp)
|
||||
err := i.SendAuthenticatedHTTPRequest("POST", path, params, &resp)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
if resp.Description != "" {
|
||||
return resp, errors.New(resp.Description)
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// WalletTransfer transfers funds between wallets.
|
||||
@@ -239,7 +299,19 @@ func (i *ItBit) WalletTransfer(walletID, sourceWallet, destWallet string, amount
|
||||
params["amount"] = strconv.FormatFloat(amount, 'f', -1, 64)
|
||||
params["currencyCode"] = currency
|
||||
|
||||
return resp, i.SendAuthenticatedHTTPRequest("POST", path, params, &resp)
|
||||
err := i.SendAuthenticatedHTTPRequest("POST", path, params, &resp)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
if resp.Description != "" {
|
||||
return resp, errors.New(resp.Description)
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (i *ItBit) SendHTTPRequest(path string, result interface{}) error {
|
||||
return i.SendPayload("GET", path, nil, nil, result, false, i.Verbose)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated request to itBit
|
||||
@@ -290,19 +362,5 @@ func (i *ItBit) SendAuthenticatedHTTPRequest(method string, path string, params
|
||||
headers["X-Auth-Nonce"] = nonce
|
||||
headers["Content-Type"] = "application/json"
|
||||
|
||||
resp, err := common.SendHTTPRequest(method, url, headers, bytes.NewBuffer([]byte(PayloadJSON)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if i.Verbose {
|
||||
log.Printf("Received raw: \n%s\n", resp)
|
||||
}
|
||||
|
||||
errCapture := GeneralReturn{}
|
||||
if err := common.JSONDecode([]byte(resp), &errCapture); err == nil {
|
||||
return errors.New(errCapture.Description)
|
||||
}
|
||||
|
||||
return common.JSONDecode([]byte(resp), result)
|
||||
return i.SendPayload(method, url, headers, bytes.NewBuffer([]byte(PayloadJSON)), result, true, i.Verbose)
|
||||
}
|
||||
|
||||
@@ -47,10 +47,11 @@ type Trades struct {
|
||||
|
||||
// Wallet contains specific wallet information
|
||||
type Wallet struct {
|
||||
ID string `json:"id"`
|
||||
UserID string `json:"userId"`
|
||||
Name string `json:"name"`
|
||||
Balances []Balance `json:"balances"`
|
||||
ID string `json:"id"`
|
||||
UserID string `json:"userId"`
|
||||
Name string `json:"name"`
|
||||
Balances []Balance `json:"balances"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// Balance is a sub type holding balance information
|
||||
@@ -58,6 +59,7 @@ type Balance struct {
|
||||
Currency string `json:"currency"`
|
||||
AvailableBalance float64 `json:"availableBalance,string"`
|
||||
TotalBalance float64 `json:"totalBalance,string"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// Records embodies records of trade history information
|
||||
@@ -67,6 +69,7 @@ type Records struct {
|
||||
LatestExecutedID int64 `json:"latestExecutionId,string"`
|
||||
RecordsPerPage int `json:"recordsPerPage,string"`
|
||||
TradingHistory []TradeHistory `json:"tradingHistory"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// TradeHistory stores historic trade values
|
||||
@@ -93,6 +96,7 @@ type FundingRecords struct {
|
||||
LatestExecutedID int64 `json:"latestExecutionId,string"`
|
||||
RecordsPerPage int `json:"recordsPerPage,string"`
|
||||
FundingHistory []FundHistory `json:"fundingHistory"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// FundHistory stores historic funding transactions
|
||||
@@ -126,6 +130,7 @@ type Order struct {
|
||||
Status string `json:"Status"`
|
||||
Metadata interface{} `json:"metadata"`
|
||||
ClientOrderIdentifier string `json:"clientOrderIdentifier"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// CryptoCurrencyDeposit holds information about a new wallet
|
||||
@@ -134,6 +139,7 @@ type CryptoCurrencyDeposit struct {
|
||||
WalletID string `json:"walletID"`
|
||||
DepositAddress string `json:"depositAddress"`
|
||||
Metadata interface{} `json:"metadata"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// WalletTransfer holds wallet transfer information
|
||||
@@ -142,4 +148,5 @@ type WalletTransfer struct {
|
||||
DestinationWalletID string `json:"destinationWalletId"`
|
||||
Amount float64 `json:"amount,string"`
|
||||
CurrencyCode string `json:"currencyCode"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package kraken
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -11,6 +12,7 @@ import (
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
@@ -38,6 +40,9 @@ const (
|
||||
krakenTradeVolume = "TradeVolume"
|
||||
krakenOrderCancel = "CancelOrder"
|
||||
krakenOrderPlace = "AddOrder"
|
||||
|
||||
krakenAuthRate = 0
|
||||
krakenUnauthRate = 0
|
||||
)
|
||||
|
||||
// Kraken is the overarching type across the alphapoint package
|
||||
@@ -45,6 +50,7 @@ type Kraken struct {
|
||||
exchange.Base
|
||||
CryptoFee, FiatFee float64
|
||||
Ticker map[string]Ticker
|
||||
*request.Handler
|
||||
}
|
||||
|
||||
// SetDefaults sets current default settings
|
||||
@@ -64,6 +70,8 @@ func (k *Kraken) SetDefaults() {
|
||||
k.ConfigCurrencyPairFormat.Uppercase = true
|
||||
k.AssetTypes = []string{ticker.Spot}
|
||||
k.SupportsAutoPairUpdating = true
|
||||
k.Handler = new(request.Handler)
|
||||
k.SetRequestHandler(k.Name, krakenAuthRate, krakenUnauthRate, new(http.Client))
|
||||
}
|
||||
|
||||
// Setup sets current exchange configuration
|
||||
@@ -108,7 +116,7 @@ func (k *Kraken) GetServerTime(unixTime bool) (interface{}, error) {
|
||||
var result GeneralResponse
|
||||
path := fmt.Sprintf("%s/%s/public/%s", krakenAPIURL, krakenAPIVersion, krakenServerTime)
|
||||
|
||||
err := common.SendHTTPGetRequest(path, true, k.Verbose, &result)
|
||||
err := k.SendHTTPRequest(path, &result)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("getServerTime() error %s", err)
|
||||
}
|
||||
@@ -124,7 +132,7 @@ func (k *Kraken) GetAssets() (interface{}, error) {
|
||||
var result GeneralResponse
|
||||
path := fmt.Sprintf("%s/%s/public/%s", krakenAPIURL, krakenAPIVersion, krakenAssets)
|
||||
|
||||
return result.Result, common.SendHTTPGetRequest(path, true, k.Verbose, &result)
|
||||
return result.Result, k.SendHTTPRequest(path, &result)
|
||||
}
|
||||
|
||||
// GetAssetPairs returns a full asset pair list
|
||||
@@ -137,7 +145,7 @@ func (k *Kraken) GetAssetPairs() (map[string]AssetPairs, error) {
|
||||
response := Response{}
|
||||
path := fmt.Sprintf("%s/%s/public/%s", krakenAPIURL, krakenAPIVersion, krakenAssetPairs)
|
||||
|
||||
return response.Result, common.SendHTTPGetRequest(path, true, k.Verbose, &response)
|
||||
return response.Result, k.SendHTTPRequest(path, &response)
|
||||
}
|
||||
|
||||
// GetTicker returns ticker information from kraken
|
||||
@@ -154,7 +162,7 @@ func (k *Kraken) GetTicker(symbol string) (Ticker, error) {
|
||||
resp := Response{}
|
||||
path := fmt.Sprintf("%s/%s/public/%s?%s", krakenAPIURL, krakenAPIVersion, krakenTicker, values.Encode())
|
||||
|
||||
err := common.SendHTTPGetRequest(path, true, k.Verbose, &resp)
|
||||
err := k.SendHTTPRequest(path, &resp)
|
||||
if err != nil {
|
||||
return ticker, err
|
||||
}
|
||||
@@ -192,7 +200,7 @@ func (k *Kraken) GetOHLC(symbol string) ([]OpenHighLowClose, error) {
|
||||
|
||||
path := fmt.Sprintf("%s/%s/public/%s?%s", krakenAPIURL, krakenAPIVersion, krakenOHLC, values.Encode())
|
||||
|
||||
err := common.SendHTTPGetRequest(path, true, k.Verbose, &result)
|
||||
err := k.SendHTTPRequest(path, &result)
|
||||
if err != nil {
|
||||
return OHLC, err
|
||||
}
|
||||
@@ -238,7 +246,7 @@ func (k *Kraken) GetDepth(symbol string) (Orderbook, error) {
|
||||
|
||||
path := fmt.Sprintf("%s/%s/public/%s?%s", krakenAPIURL, krakenAPIVersion, krakenDepth, values.Encode())
|
||||
|
||||
err := common.SendHTTPGetRequest(path, true, k.Verbose, &result)
|
||||
err := k.SendHTTPRequest(path, &result)
|
||||
if err != nil {
|
||||
return orderBook, err
|
||||
}
|
||||
@@ -297,7 +305,7 @@ func (k *Kraken) GetTrades(symbol string) ([]RecentTrades, error) {
|
||||
|
||||
path := fmt.Sprintf("%s/%s/public/%s?%s", krakenAPIURL, krakenAPIVersion, krakenTrades, values.Encode())
|
||||
|
||||
err := common.SendHTTPGetRequest(path, true, k.Verbose, &result)
|
||||
err := k.SendHTTPRequest(path, &result)
|
||||
if err != nil {
|
||||
return recentTrades, err
|
||||
}
|
||||
@@ -338,7 +346,7 @@ func (k *Kraken) GetSpread(symbol string) ([]Spread, error) {
|
||||
|
||||
path := fmt.Sprintf("%s/%s/public/%s?%s", krakenAPIURL, krakenAPIVersion, krakenSpread, values.Encode())
|
||||
|
||||
err := common.SendHTTPGetRequest(path, true, k.Verbose, &response)
|
||||
err := k.SendHTTPRequest(path, &response)
|
||||
if err != nil {
|
||||
return peanutButter, err
|
||||
}
|
||||
@@ -568,6 +576,11 @@ func (k *Kraken) CancelOrder(orderID int64) (interface{}, error) {
|
||||
return k.SendAuthenticatedHTTPRequest(krakenOrderCancel, values)
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP requests
|
||||
func (k *Kraken) SendHTTPRequest(path string, result interface{}) error {
|
||||
return k.SendPayload("GET", path, nil, nil, result, false, k.Verbose)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request
|
||||
func (k *Kraken) SendAuthenticatedHTTPRequest(method string, values url.Values) (interface{}, error) {
|
||||
if !k.AuthenticatedAPISupport {
|
||||
@@ -599,20 +612,11 @@ func (k *Kraken) SendAuthenticatedHTTPRequest(method string, values url.Values)
|
||||
headers["API-Key"] = k.APIKey
|
||||
headers["API-Sign"] = signature
|
||||
|
||||
rawResp, err := common.SendHTTPRequest("POST", krakenAPIURL+path, headers, strings.NewReader(values.Encode()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if k.Verbose {
|
||||
log.Printf("Received raw: \n%s\n", rawResp)
|
||||
}
|
||||
|
||||
var resp interface{}
|
||||
|
||||
err = common.JSONDecode([]byte(rawResp), &resp)
|
||||
err = k.SendPayload("POST", krakenAPIURL+path, headers, strings.NewReader(values.Encode()), &resp, true, k.Verbose)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return resp, err
|
||||
}
|
||||
|
||||
data := resp.(map[string]interface{})
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -11,6 +12,7 @@ import (
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
@@ -29,11 +31,15 @@ const (
|
||||
lakeBTCGetTrades = "getTrades"
|
||||
lakeBTCGetExternalAccounts = "getExternalAccounts"
|
||||
lakeBTCCreateWithdraw = "createWithdraw"
|
||||
|
||||
lakeBTCAuthRate = 0
|
||||
lakeBTCUnauth = 0
|
||||
)
|
||||
|
||||
// LakeBTC is the overarching type across the LakeBTC package
|
||||
type LakeBTC struct {
|
||||
exchange.Base
|
||||
*request.Handler
|
||||
}
|
||||
|
||||
// SetDefaults sets LakeBTC defaults
|
||||
@@ -51,6 +57,8 @@ func (l *LakeBTC) SetDefaults() {
|
||||
l.ConfigCurrencyPairFormat.Uppercase = true
|
||||
l.AssetTypes = []string{ticker.Spot}
|
||||
l.SupportsAutoPairUpdating = false
|
||||
l.Handler = new(request.Handler)
|
||||
l.SetRequestHandler(l.Name, lakeBTCAuthRate, lakeBTCUnauth, new(http.Client))
|
||||
}
|
||||
|
||||
// Setup sets exchange configuration profile
|
||||
@@ -95,7 +103,7 @@ func (l *LakeBTC) GetTicker() (map[string]Ticker, error) {
|
||||
response := make(map[string]TickerResponse)
|
||||
path := fmt.Sprintf("%s/%s", lakeBTCAPIURL, lakeBTCTicker)
|
||||
|
||||
if err := common.SendHTTPGetRequest(path, true, l.Verbose, &response); err != nil {
|
||||
if err := l.SendHTTPRequest(path, &response); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -137,7 +145,7 @@ func (l *LakeBTC) GetOrderBook(currency string) (Orderbook, error) {
|
||||
}
|
||||
path := fmt.Sprintf("%s/%s?symbol=%s", lakeBTCAPIURL, lakeBTCOrderbook, common.StringToLower(currency))
|
||||
resp := Response{}
|
||||
err := common.SendHTTPGetRequest(path, true, l.Verbose, &resp)
|
||||
err := l.SendHTTPRequest(path, &resp)
|
||||
if err != nil {
|
||||
return Orderbook{}, err
|
||||
}
|
||||
@@ -178,7 +186,7 @@ func (l *LakeBTC) GetTradeHistory(currency string) ([]TradeHistory, error) {
|
||||
path := fmt.Sprintf("%s/%s?symbol=%s", lakeBTCAPIURL, lakeBTCTrades, common.StringToLower(currency))
|
||||
resp := []TradeHistory{}
|
||||
|
||||
return resp, common.SendHTTPGetRequest(path, true, l.Verbose, &resp)
|
||||
return resp, l.SendHTTPRequest(path, &resp)
|
||||
}
|
||||
|
||||
// GetAccountInfo returns your current account information
|
||||
@@ -276,6 +284,11 @@ func (l *LakeBTC) CreateWithdraw(amount float64, accountID int64) (Withdraw, err
|
||||
return resp, l.SendAuthenticatedHTTPRequest(lakeBTCCreateWithdraw, params, &resp)
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated http request
|
||||
func (l *LakeBTC) SendHTTPRequest(path string, result interface{}) error {
|
||||
return l.SendPayload("GET", path, nil, nil, result, false, l.Verbose)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an autheticated HTTP request to a LakeBTC
|
||||
func (l *LakeBTC) SendAuthenticatedHTTPRequest(method, params string, result interface{}) (err error) {
|
||||
if !l.AuthenticatedAPISupport {
|
||||
@@ -310,32 +323,5 @@ func (l *LakeBTC) SendAuthenticatedHTTPRequest(method, params string, result int
|
||||
headers["Authorization"] = "Basic " + common.Base64Encode([]byte(l.APIKey+":"+common.HexEncodeToString(hmac)))
|
||||
headers["Content-Type"] = "application/json-rpc"
|
||||
|
||||
resp, err := common.SendHTTPRequest("POST", lakeBTCAPIURL, headers, strings.NewReader(string(data)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if l.Verbose {
|
||||
log.Printf("Received raw: %s\n", resp)
|
||||
}
|
||||
|
||||
type ErrorResponse struct {
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
errResponse := ErrorResponse{}
|
||||
err = common.JSONDecode([]byte(resp), &errResponse)
|
||||
if err != nil {
|
||||
return errors.New("unable to check response for error")
|
||||
}
|
||||
|
||||
if errResponse.Error != "" {
|
||||
return errors.New(errResponse.Error)
|
||||
}
|
||||
|
||||
err = common.JSONDecode([]byte(resp), &result)
|
||||
if err != nil {
|
||||
return errors.New("unable to JSON Unmarshal response")
|
||||
}
|
||||
return nil
|
||||
return l.SendPayload("POST", lakeBTCAPIURL, headers, strings.NewReader(string(data)), result, true, l.Verbose)
|
||||
}
|
||||
|
||||
@@ -69,6 +69,9 @@ func TestGetTradeHistory(t *testing.T) {
|
||||
|
||||
func TestTrade(t *testing.T) {
|
||||
t.Parallel()
|
||||
if l.APIKey == "" || l.APISecret == "" {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := l.Trade(0, 0, 0, "USD")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - Trade() error", err)
|
||||
@@ -77,6 +80,9 @@ func TestTrade(t *testing.T) {
|
||||
|
||||
func TestGetOpenOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
if l.APIKey == "" || l.APISecret == "" {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := l.GetOpenOrders()
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetOpenOrders() error", err)
|
||||
@@ -85,6 +91,9 @@ func TestGetOpenOrders(t *testing.T) {
|
||||
|
||||
func TestGetOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
if l.APIKey == "" || l.APISecret == "" {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := l.GetOrders([]int64{1, 2})
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetOrders() error", err)
|
||||
@@ -93,6 +102,9 @@ func TestGetOrders(t *testing.T) {
|
||||
|
||||
func TestCancelOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
if l.APIKey == "" || l.APISecret == "" {
|
||||
t.Skip()
|
||||
}
|
||||
err := l.CancelOrder(1337)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - CancelOrder() error", err)
|
||||
@@ -101,6 +113,9 @@ func TestCancelOrder(t *testing.T) {
|
||||
|
||||
func TestGetTrades(t *testing.T) {
|
||||
t.Parallel()
|
||||
if l.APIKey == "" || l.APISecret == "" {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := l.GetTrades(1337)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetTrades() error", err)
|
||||
@@ -109,6 +124,9 @@ func TestGetTrades(t *testing.T) {
|
||||
|
||||
func TestGetExternalAccounts(t *testing.T) {
|
||||
t.Parallel()
|
||||
if l.APIKey == "" || l.APISecret == "" {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := l.GetExternalAccounts()
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetExternalAccounts() error", err)
|
||||
@@ -117,6 +135,9 @@ func TestGetExternalAccounts(t *testing.T) {
|
||||
|
||||
func TestCreateWithdraw(t *testing.T) {
|
||||
t.Parallel()
|
||||
if l.APIKey == "" || l.APISecret == "" {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := l.CreateWithdraw(0, 1337)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - CreateWithdraw() error", err)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -12,6 +13,7 @@ import (
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
@@ -31,6 +33,9 @@ const (
|
||||
liquiCancelOrder = "CancelOrder"
|
||||
liquiTradeHistory = "TradeHistory"
|
||||
liquiWithdrawCoin = "WithdrawCoin"
|
||||
|
||||
liquiAuthRate = 0
|
||||
liquiUnauthRate = 0
|
||||
)
|
||||
|
||||
// Liqui is the overarching type across the liqui package
|
||||
@@ -38,6 +43,7 @@ type Liqui struct {
|
||||
exchange.Base
|
||||
Ticker map[string]Ticker
|
||||
Info Info
|
||||
*request.Handler
|
||||
}
|
||||
|
||||
// SetDefaults sets current default values for liqui
|
||||
@@ -56,6 +62,8 @@ func (l *Liqui) SetDefaults() {
|
||||
l.ConfigCurrencyPairFormat.Uppercase = true
|
||||
l.AssetTypes = []string{ticker.Spot}
|
||||
l.SupportsAutoPairUpdating = true
|
||||
l.Handler = new(request.Handler)
|
||||
l.SetRequestHandler(l.Name, liquiAuthRate, liquiUnauthRate, new(http.Client))
|
||||
}
|
||||
|
||||
// Setup sets exchange configuration parameters for liqui
|
||||
@@ -117,7 +125,7 @@ func (l *Liqui) GetInfo() (Info, error) {
|
||||
resp := Info{}
|
||||
req := fmt.Sprintf("%s/%s/%s/", liquiAPIPublicURL, liquiAPIPublicVersion, liquiInfo)
|
||||
|
||||
return resp, common.SendHTTPGetRequest(req, true, l.Verbose, &resp)
|
||||
return resp, l.SendHTTPRequest(req, &resp)
|
||||
}
|
||||
|
||||
// GetTicker returns information about currently active pairs, such as: the
|
||||
@@ -136,8 +144,7 @@ func (l *Liqui) GetTicker(currencyPair string) (map[string]Ticker, error) {
|
||||
response := Response{Data: make(map[string]Ticker)}
|
||||
req := fmt.Sprintf("%s/%s/%s/%s", liquiAPIPublicURL, liquiAPIPublicVersion, liquiTicker, currencyPair)
|
||||
|
||||
return response.Data,
|
||||
common.SendHTTPGetRequest(req, true, l.Verbose, &response.Data)
|
||||
return response.Data, l.SendHTTPRequest(req, &response.Data)
|
||||
}
|
||||
|
||||
// GetDepth information about active orders on the pair. Additionally it accepts
|
||||
@@ -153,8 +160,7 @@ func (l *Liqui) GetDepth(currencyPair string) (Orderbook, error) {
|
||||
response := Response{Data: make(map[string]Orderbook)}
|
||||
req := fmt.Sprintf("%s/%s/%s/%s", liquiAPIPublicURL, liquiAPIPublicVersion, liquiDepth, currencyPair)
|
||||
|
||||
return response.Data[currencyPair],
|
||||
common.SendHTTPGetRequest(req, true, l.Verbose, &response.Data)
|
||||
return response.Data[currencyPair], l.SendHTTPRequest(req, &response.Data)
|
||||
}
|
||||
|
||||
// GetTrades returns information about the last trades. Additionally it accepts
|
||||
@@ -170,8 +176,7 @@ func (l *Liqui) GetTrades(currencyPair string) ([]Trades, error) {
|
||||
response := Response{Data: make(map[string][]Trades)}
|
||||
req := fmt.Sprintf("%s/%s/%s/%s", liquiAPIPublicURL, liquiAPIPublicVersion, liquiTrades, currencyPair)
|
||||
|
||||
return response.Data[currencyPair],
|
||||
common.SendHTTPGetRequest(req, true, l.Verbose, &response.Data)
|
||||
return response.Data[currencyPair], l.SendHTTPRequest(req, &response.Data)
|
||||
}
|
||||
|
||||
// GetAccountInfo returns information about the user’s current balance, API-key
|
||||
@@ -257,6 +262,11 @@ func (l *Liqui) WithdrawCoins(coin string, amount float64, address string) (With
|
||||
return result, l.SendAuthenticatedHTTPRequest(liquiWithdrawCoin, req, &result)
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (l *Liqui) SendHTTPRequest(path string, result interface{}) error {
|
||||
return l.SendPayload("GET", path, nil, nil, result, false, l.Verbose)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated http request to liqui
|
||||
func (l *Liqui) SendAuthenticatedHTTPRequest(method string, values url.Values, result interface{}) (err error) {
|
||||
if !l.AuthenticatedAPISupport {
|
||||
@@ -283,31 +293,5 @@ func (l *Liqui) SendAuthenticatedHTTPRequest(method string, values url.Values, r
|
||||
headers["Sign"] = common.HexEncodeToString(hmac)
|
||||
headers["Content-Type"] = "application/x-www-form-urlencoded"
|
||||
|
||||
resp, err := common.SendHTTPRequest("POST", liquiAPIPrivateURL, headers, strings.NewReader(encoded))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
response := Response{}
|
||||
|
||||
err = common.JSONDecode([]byte(resp), &response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if response.Success != 1 {
|
||||
return errors.New(response.Error)
|
||||
}
|
||||
|
||||
jsonEncoded, err := common.JSONEncode(response.Return)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = common.JSONDecode(jsonEncoded, &result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return l.SendPayload("POST", liquiAPIPrivateURL, headers, strings.NewReader(encoded), result, true, l.Verbose)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package liqui
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
@@ -68,11 +67,10 @@ func TestGetTicker(t *testing.T) {
|
||||
|
||||
func TestGetDepth(t *testing.T) {
|
||||
t.Parallel()
|
||||
v, err := l.GetDepth("eth_btc")
|
||||
_, err := l.GetDepth("eth_btc")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - liqui GetDepth() error", err)
|
||||
}
|
||||
log.Println(v)
|
||||
}
|
||||
|
||||
func TestGetTrades(t *testing.T) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
@@ -12,6 +13,7 @@ import (
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -94,6 +96,9 @@ const (
|
||||
statePaidAndConfirmed = "PAID_AND_CONFIRMED"
|
||||
statePaidLateConfirmed = "PAID_IN_LATE_AND_CONFIRMED"
|
||||
statePaidPartlyConfirmed = "PAID_PARTLY_AND_CONFIRMED"
|
||||
|
||||
localbitcoinsAuthRate = 0
|
||||
localbitcoinsUnauthRate = 0
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -104,6 +109,7 @@ var (
|
||||
// LocalBitcoins is the overarching type across the localbitcoins package
|
||||
type LocalBitcoins struct {
|
||||
exchange.Base
|
||||
*request.Handler
|
||||
}
|
||||
|
||||
// SetDefaults sets the package defaults for localbitcoins
|
||||
@@ -119,6 +125,8 @@ func (l *LocalBitcoins) SetDefaults() {
|
||||
l.ConfigCurrencyPairFormat.Delimiter = ""
|
||||
l.ConfigCurrencyPairFormat.Uppercase = true
|
||||
l.SupportsAutoPairUpdating = false
|
||||
l.Handler = new(request.Handler)
|
||||
l.SetRequestHandler(l.Name, localbitcoinsAuthRate, localbitcoinsUnauthRate, new(http.Client))
|
||||
}
|
||||
|
||||
// Setup sets exchange configuration parameters
|
||||
@@ -170,7 +178,7 @@ func (l *LocalBitcoins) GetAccountInfo(username string, self bool) (AccountInfo,
|
||||
}
|
||||
} else {
|
||||
path := fmt.Sprintf("%s/%s/%s/", localbitcoinsAPIURL, localbitcoinsAPIAccountInfo, username)
|
||||
err := common.SendHTTPGetRequest(path, true, l.Verbose, &resp)
|
||||
err := l.SendHTTPRequest(path, &resp)
|
||||
if err != nil {
|
||||
return resp.Data, err
|
||||
}
|
||||
@@ -658,6 +666,11 @@ func (l *LocalBitcoins) GetOrderbook(currency string) (Orderbook, error) {
|
||||
return orderbook, nil
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (l *LocalBitcoins) SendHTTPRequest(path string, result interface{}) error {
|
||||
return l.SendPayload("GET", path, nil, nil, result, false, l.Verbose)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request to
|
||||
// localbitcoins
|
||||
func (l *LocalBitcoins) SendAuthenticatedHTTPRequest(method, path string, values url.Values, result interface{}) (err error) {
|
||||
@@ -690,26 +703,5 @@ func (l *LocalBitcoins) SendAuthenticatedHTTPRequest(method, path string, values
|
||||
log.Printf("Raw Path: \n%s\n", path)
|
||||
}
|
||||
|
||||
resp, err := common.SendHTTPRequest(method, localbitcoinsAPIURL+path, headers, bytes.NewBuffer([]byte(payload)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if l.Verbose {
|
||||
log.Printf("Received raw: \n%s\n", resp)
|
||||
}
|
||||
|
||||
errCapture := GeneralError{}
|
||||
if err = common.JSONDecode([]byte(resp), &errCapture); err == nil {
|
||||
if len(errCapture.Error.Message) != 0 {
|
||||
return errors.New(errCapture.Error.Message)
|
||||
}
|
||||
}
|
||||
|
||||
err = common.JSONDecode([]byte(resp), &result)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return l.SendPayload(method, localbitcoinsAPIURL+path, headers, bytes.NewBuffer([]byte(payload)), result, true, l.Verbose)
|
||||
}
|
||||
|
||||
@@ -43,6 +43,9 @@ func TestGetFee(t *testing.T) {
|
||||
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
if l.APIKey == "" || l.APISecret == "" {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := l.GetAccountInfo("", true)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetAccountInfo() error", err)
|
||||
@@ -55,6 +58,9 @@ func TestGetAccountInfo(t *testing.T) {
|
||||
|
||||
func TestGetads(t *testing.T) {
|
||||
t.Parallel()
|
||||
if l.APIKey == "" || l.APISecret == "" {
|
||||
t.Skip()
|
||||
}
|
||||
_, err := l.Getads("")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - Getads() - Full list, error", err)
|
||||
@@ -67,6 +73,9 @@ func TestGetads(t *testing.T) {
|
||||
|
||||
func TestEditAd(t *testing.T) {
|
||||
t.Parallel()
|
||||
if l.APIKey == "" || l.APISecret == "" {
|
||||
t.Skip()
|
||||
}
|
||||
edit := AdEdit{}
|
||||
err := l.EditAd(edit, "1337")
|
||||
if err == nil {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -12,6 +13,7 @@ import (
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
@@ -65,6 +67,9 @@ const (
|
||||
okcoinFuturesposition4Fix = "future_position_4fix.do"
|
||||
okcoinFuturesExplosive = "future_explosive.do"
|
||||
okcoinFuturesDevolve = "future_devolve.do"
|
||||
|
||||
okcoinAuthRate = 0
|
||||
okcoinUnauthRate = 0
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -78,6 +83,7 @@ type OKCoin struct {
|
||||
WebsocketErrors map[string]string
|
||||
FuturesValues []string
|
||||
WebsocketConn *websocket.Conn
|
||||
*request.Handler
|
||||
}
|
||||
|
||||
// setCurrencyPairFormats sets currency pair formatting for this package
|
||||
@@ -99,6 +105,8 @@ func (o *OKCoin) SetDefaults() {
|
||||
o.FuturesValues = []string{"this_week", "next_week", "quarter"}
|
||||
o.AssetTypes = []string{ticker.Spot}
|
||||
o.SupportsAutoPairUpdating = false
|
||||
o.Handler = new(request.Handler)
|
||||
o.SetRequestHandler(o.Name, okcoinAuthRate, okcoinUnauthRate, new(http.Client))
|
||||
|
||||
if okcoinDefaultsSet {
|
||||
o.AssetTypes = append(o.AssetTypes, o.FuturesValues...)
|
||||
@@ -162,11 +170,8 @@ func (o *OKCoin) GetTicker(symbol string) (Ticker, error) {
|
||||
vals := url.Values{}
|
||||
vals.Set("symbol", symbol)
|
||||
path := common.EncodeURLValues(o.APIUrl+okcoinTicker, vals)
|
||||
err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp)
|
||||
if err != nil {
|
||||
return Ticker{}, err
|
||||
}
|
||||
return resp.Ticker, nil
|
||||
|
||||
return resp.Ticker, o.SendHTTPRequest(path, &resp)
|
||||
}
|
||||
|
||||
// GetOrderBook returns the current order book by size
|
||||
@@ -182,11 +187,7 @@ func (o *OKCoin) GetOrderBook(symbol string, size int64, merge bool) (Orderbook,
|
||||
}
|
||||
|
||||
path := common.EncodeURLValues(o.APIUrl+okcoinDepth, vals)
|
||||
err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
return resp, nil
|
||||
return resp, o.SendHTTPRequest(path, &resp)
|
||||
}
|
||||
|
||||
// GetTrades returns historic trades since a timestamp
|
||||
@@ -199,11 +200,7 @@ func (o *OKCoin) GetTrades(symbol string, since int64) ([]Trades, error) {
|
||||
}
|
||||
|
||||
path := common.EncodeURLValues(o.APIUrl+okcoinTrades, vals)
|
||||
err := common.SendHTTPGetRequest(path, true, o.Verbose, &result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
return result, o.SendHTTPRequest(path, &result)
|
||||
}
|
||||
|
||||
// GetKline returns kline data
|
||||
@@ -222,12 +219,7 @@ func (o *OKCoin) GetKline(symbol, klineType string, size, since int64) ([]interf
|
||||
}
|
||||
|
||||
path := common.EncodeURLValues(o.APIUrl+okcoinKline, vals)
|
||||
err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
return resp, o.SendHTTPRequest(path, &resp)
|
||||
}
|
||||
|
||||
// GetFuturesTicker returns a current ticker for the futures market
|
||||
@@ -237,11 +229,8 @@ func (o *OKCoin) GetFuturesTicker(symbol, contractType string) (FuturesTicker, e
|
||||
vals.Set("symbol", symbol)
|
||||
vals.Set("contract_type", contractType)
|
||||
path := common.EncodeURLValues(o.APIUrl+okcoinFuturesTicker, vals)
|
||||
err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp)
|
||||
if err != nil {
|
||||
return FuturesTicker{}, err
|
||||
}
|
||||
return resp.Ticker, nil
|
||||
|
||||
return resp.Ticker, o.SendHTTPRequest(path, &resp)
|
||||
}
|
||||
|
||||
// GetFuturesDepth returns current depth for the futures market
|
||||
@@ -259,11 +248,7 @@ func (o *OKCoin) GetFuturesDepth(symbol, contractType string, size int64, merge
|
||||
}
|
||||
|
||||
path := common.EncodeURLValues(o.APIUrl+okcoinFuturesDepth, vals)
|
||||
err := common.SendHTTPGetRequest(path, true, o.Verbose, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
return result, nil
|
||||
return result, o.SendHTTPRequest(path, &result)
|
||||
}
|
||||
|
||||
// GetFuturesTrades returns historic trades for the futures market
|
||||
@@ -274,11 +259,7 @@ func (o *OKCoin) GetFuturesTrades(symbol, contractType string) ([]FuturesTrades,
|
||||
vals.Set("contract_type", contractType)
|
||||
|
||||
path := common.EncodeURLValues(o.APIUrl+okcoinFuturesTrades, vals)
|
||||
err := common.SendHTTPGetRequest(path, true, o.Verbose, &result)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
return result, o.SendHTTPRequest(path, &result)
|
||||
}
|
||||
|
||||
// GetFuturesIndex returns an index for the futures market
|
||||
@@ -292,11 +273,7 @@ func (o *OKCoin) GetFuturesIndex(symbol string) (float64, error) {
|
||||
vals.Set("symbol", symbol)
|
||||
|
||||
path := common.EncodeURLValues(o.APIUrl+okcoinFuturesIndex, vals)
|
||||
err := common.SendHTTPGetRequest(path, true, o.Verbose, &result)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.Index, nil
|
||||
return result.Index, o.SendHTTPRequest(path, &result)
|
||||
}
|
||||
|
||||
// GetFuturesExchangeRate returns the exchange rate for the futures market
|
||||
@@ -306,11 +283,7 @@ func (o *OKCoin) GetFuturesExchangeRate() (float64, error) {
|
||||
}
|
||||
|
||||
result := Response{}
|
||||
err := common.SendHTTPGetRequest(o.APIUrl+okcoinExchangeRate, true, o.Verbose, &result)
|
||||
if err != nil {
|
||||
return result.Rate, err
|
||||
}
|
||||
return result.Rate, nil
|
||||
return result.Rate, o.SendHTTPRequest(o.APIUrl+okcoinExchangeRate, &result)
|
||||
}
|
||||
|
||||
// GetFuturesEstimatedPrice returns a current estimated futures price for a
|
||||
@@ -324,11 +297,8 @@ func (o *OKCoin) GetFuturesEstimatedPrice(symbol string) (float64, error) {
|
||||
vals := url.Values{}
|
||||
vals.Set("symbol", symbol)
|
||||
path := common.EncodeURLValues(o.APIUrl+okcoinFuturesEstimatedPrice, vals)
|
||||
err := common.SendHTTPGetRequest(path, true, o.Verbose, &result)
|
||||
if err != nil {
|
||||
return result.Price, err
|
||||
}
|
||||
return result.Price, nil
|
||||
|
||||
return result.Price, o.SendHTTPRequest(path, &result)
|
||||
}
|
||||
|
||||
// GetFuturesKline returns kline data for a specific currency on the futures
|
||||
@@ -348,12 +318,7 @@ func (o *OKCoin) GetFuturesKline(symbol, klineType, contractType string, size, s
|
||||
}
|
||||
|
||||
path := common.EncodeURLValues(o.APIUrl+okcoinFuturesKline, vals)
|
||||
err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
return resp, o.SendHTTPRequest(path, &resp)
|
||||
}
|
||||
|
||||
// GetFuturesHoldAmount returns the hold amount for a futures trade
|
||||
@@ -364,12 +329,7 @@ func (o *OKCoin) GetFuturesHoldAmount(symbol, contractType string) ([]FuturesHol
|
||||
vals.Set("contract_type", contractType)
|
||||
|
||||
path := common.EncodeURLValues(o.APIUrl+okcoinFuturesHoldAmount, vals)
|
||||
err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp, nil
|
||||
return resp, o.SendHTTPRequest(path, &resp)
|
||||
}
|
||||
|
||||
// GetFuturesExplosive returns the explosive for a futures contract
|
||||
@@ -386,25 +346,16 @@ func (o *OKCoin) GetFuturesExplosive(symbol, contractType string, status, curren
|
||||
vals.Set("page_length", strconv.FormatInt(pageLength, 10))
|
||||
|
||||
path := common.EncodeURLValues(o.APIUrl+okcoinFuturesExplosive, vals)
|
||||
err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resp.Data, nil
|
||||
return resp.Data, o.SendHTTPRequest(path, &resp)
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
return result, nil
|
||||
return result,
|
||||
o.SendAuthenticatedHTTPRequest(okcoinUserInfo, url.Values{}, &result)
|
||||
}
|
||||
|
||||
// Trade initiates a new trade
|
||||
@@ -943,6 +894,11 @@ func (o *OKCoin) GetFuturesUserPosition4Fix(symbol, contractType string) {
|
||||
}
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (o *OKCoin) SendHTTPRequest(path string, result interface{}) error {
|
||||
return o.SendPayload("GET", path, nil, nil, result, false, o.Verbose)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request
|
||||
func (o *OKCoin) SendAuthenticatedHTTPRequest(method string, v url.Values, result interface{}) (err error) {
|
||||
if !o.AuthenticatedAPISupport {
|
||||
@@ -963,23 +919,7 @@ func (o *OKCoin) SendAuthenticatedHTTPRequest(method string, v url.Values, resul
|
||||
headers := make(map[string]string)
|
||||
headers["Content-Type"] = "application/x-www-form-urlencoded"
|
||||
|
||||
resp, err := common.SendHTTPRequest("POST", path, headers, strings.NewReader(encoded))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if o.Verbose {
|
||||
log.Printf("Received raw: \n%s\n", resp)
|
||||
}
|
||||
|
||||
err = common.JSONDecode([]byte(resp), &result)
|
||||
|
||||
if err != nil {
|
||||
return errors.New("unable to JSON Unmarshal response")
|
||||
}
|
||||
|
||||
return nil
|
||||
return o.SendPayload("POST", path, headers, strings.NewReader(encoded), result, true, o.Verbose)
|
||||
}
|
||||
|
||||
// SetErrorDefaults sets default error map
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strconv"
|
||||
@@ -12,6 +13,7 @@ import (
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -66,6 +68,9 @@ const (
|
||||
|
||||
// just your average return type from okex
|
||||
returnTypeOne = "map[string]interface {}"
|
||||
|
||||
okexAuthRate = 0
|
||||
okexUnauthRate = 0
|
||||
)
|
||||
|
||||
var errMissValue = errors.New("warning - resp value is missing from exchange")
|
||||
@@ -82,6 +87,8 @@ type OKEX struct {
|
||||
CurrencyPairs []string
|
||||
ContractPosition []string
|
||||
Types []string
|
||||
|
||||
*request.Handler
|
||||
}
|
||||
|
||||
// SetDefaults method assignes the default values for Bittrex
|
||||
@@ -98,6 +105,8 @@ func (o *OKEX) SetDefaults() {
|
||||
o.ConfigCurrencyPairFormat.Delimiter = "_"
|
||||
o.ConfigCurrencyPairFormat.Uppercase = false
|
||||
o.SupportsAutoPairUpdating = false
|
||||
o.Handler = new(request.Handler)
|
||||
o.SetRequestHandler(o.Name, okexAuthRate, okexUnauthRate, new(http.Client))
|
||||
}
|
||||
|
||||
// Setup method sets current configuration details if enabled
|
||||
@@ -149,7 +158,7 @@ func (o *OKEX) GetContractPrice(symbol, contractType string) (ContractPrice, err
|
||||
|
||||
path := fmt.Sprintf("%s%s%s.do?%s", apiURL, apiVersion, contractPrice, values.Encode())
|
||||
|
||||
err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp)
|
||||
err := o.SendHTTPRequest(path, &resp)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
@@ -183,7 +192,7 @@ func (o *OKEX) GetContractMarketDepth(symbol, contractType string) (ActualContra
|
||||
|
||||
path := fmt.Sprintf("%s%s%s.do?%s", apiURL, apiVersion, contractFutureDepth, values.Encode())
|
||||
|
||||
err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp)
|
||||
err := o.SendHTTPRequest(path, &resp)
|
||||
if err != nil {
|
||||
return fullDepth, err
|
||||
}
|
||||
@@ -247,7 +256,7 @@ func (o *OKEX) GetContractTradeHistory(symbol, contractType string) ([]ActualCon
|
||||
|
||||
path := fmt.Sprintf("%s%s%s.do?%s", apiURL, apiVersion, contractTradeHistory, values.Encode())
|
||||
|
||||
err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp)
|
||||
err := o.SendHTTPRequest(path, &resp)
|
||||
if err != nil {
|
||||
return actualTradeHistory, err
|
||||
}
|
||||
@@ -284,7 +293,7 @@ func (o *OKEX) GetContractIndexPrice(symbol string) (float64, error) {
|
||||
path := fmt.Sprintf("%s%s%s.do?%s", apiURL, apiVersion, contractFutureIndex, values.Encode())
|
||||
var resp interface{}
|
||||
|
||||
err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp)
|
||||
err := o.SendHTTPRequest(path, &resp)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -307,7 +316,7 @@ func (o *OKEX) GetContractExchangeRate() (float64, error) {
|
||||
path := fmt.Sprintf("%s%s%s.do?", apiURL, apiVersion, contractExchangeRate)
|
||||
var resp interface{}
|
||||
|
||||
if err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp); err != nil {
|
||||
if err := o.SendHTTPRequest(path, &resp); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
@@ -335,7 +344,7 @@ func (o *OKEX) GetContractFutureEstimatedPrice(symbol string) (float64, error) {
|
||||
path := fmt.Sprintf("%s%s%s.do?%s", apiURL, apiVersion, contractFutureIndex, values.Encode())
|
||||
var resp interface{}
|
||||
|
||||
if err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp); err != nil {
|
||||
if err := o.SendHTTPRequest(path, &resp); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
@@ -379,7 +388,7 @@ func (o *OKEX) GetContractCandlestickData(symbol, typeInput, contractType string
|
||||
path := fmt.Sprintf("%s%s%s.do?%s", apiURL, apiVersion, contractCandleStick, values.Encode())
|
||||
var resp interface{}
|
||||
|
||||
if err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp); err != nil {
|
||||
if err := o.SendHTTPRequest(path, &resp); err != nil {
|
||||
return candleData, err
|
||||
}
|
||||
|
||||
@@ -434,7 +443,7 @@ func (o *OKEX) GetContractHoldingsNumber(symbol, contractType string) (map[strin
|
||||
path := fmt.Sprintf("%s%s%s.do?%s", apiURL, apiVersion, contractFutureHoldAmount, values.Encode())
|
||||
var resp interface{}
|
||||
|
||||
if err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp); err != nil {
|
||||
if err := o.SendHTTPRequest(path, &resp); err != nil {
|
||||
return holdingsNumber, err
|
||||
}
|
||||
|
||||
@@ -470,7 +479,7 @@ func (o *OKEX) GetContractlimit(symbol, contractType string) (map[string]float64
|
||||
path := fmt.Sprintf("%s%s%s.do?%s", apiURL, apiVersion, contractFutureLimits, values.Encode())
|
||||
var resp interface{}
|
||||
|
||||
if err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp); err != nil {
|
||||
if err := o.SendHTTPRequest(path, &resp); err != nil {
|
||||
return contractLimits, err
|
||||
}
|
||||
|
||||
@@ -782,6 +791,11 @@ func (o *OKEX) GetErrorCode(code interface{}) error {
|
||||
return errors.New("unable to find SPOT error code")
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (o *OKEX) SendHTTPRequest(path string, result interface{}) error {
|
||||
return o.SendPayload("GET", path, nil, nil, result, false, o.Verbose)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated http request to a desired
|
||||
// path
|
||||
func (o *OKEX) SendAuthenticatedHTTPRequest(method string, values url.Values, result interface{}) (err error) {
|
||||
@@ -803,20 +817,7 @@ func (o *OKEX) SendAuthenticatedHTTPRequest(method string, values url.Values, re
|
||||
headers := make(map[string]string)
|
||||
headers["Content-Type"] = "application/x-www-form-urlencoded"
|
||||
|
||||
resp, err := common.SendHTTPRequest("POST", path, headers, strings.NewReader(encoded))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if o.Verbose {
|
||||
log.Printf("Received raw: \n%s\n", resp)
|
||||
}
|
||||
|
||||
err = common.JSONDecode([]byte(resp), &result)
|
||||
if err != nil {
|
||||
return errors.New("unable to JSON Unmarshal response")
|
||||
}
|
||||
return nil
|
||||
return o.SendPayload("POST", path, headers, strings.NewReader(encoded), result, true, o.Verbose)
|
||||
}
|
||||
|
||||
// SetErrorDefaults sets the full error default list
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
@@ -12,6 +13,7 @@ import (
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
@@ -46,11 +48,15 @@ const (
|
||||
poloniexActiveLoans = "returnActiveLoans"
|
||||
poloniexLendingHistory = "returnLendingHistory"
|
||||
poloniexAutoRenew = "toggleAutoRenew"
|
||||
|
||||
poloniexAuthRate = 0
|
||||
poloniexUnauthRate = 0
|
||||
)
|
||||
|
||||
// Poloniex is the overarching type across the poloniex package
|
||||
type Poloniex struct {
|
||||
exchange.Base
|
||||
*request.Handler
|
||||
}
|
||||
|
||||
// SetDefaults sets default settings for poloniex
|
||||
@@ -67,6 +73,8 @@ func (p *Poloniex) SetDefaults() {
|
||||
p.ConfigCurrencyPairFormat.Uppercase = true
|
||||
p.AssetTypes = []string{ticker.Spot}
|
||||
p.SupportsAutoPairUpdating = true
|
||||
p.Handler = new(request.Handler)
|
||||
p.SetRequestHandler(p.Name, poloniexAuthRate, poloniexUnauthRate, new(http.Client))
|
||||
}
|
||||
|
||||
// Setup sets user exchange configuration settings
|
||||
@@ -112,7 +120,7 @@ func (p *Poloniex) GetTicker() (map[string]Ticker, error) {
|
||||
resp := response{}
|
||||
path := fmt.Sprintf("%s/public?command=returnTicker", poloniexAPIURL)
|
||||
|
||||
return resp.Data, common.SendHTTPGetRequest(path, true, p.Verbose, &resp.Data)
|
||||
return resp.Data, p.SendHTTPRequest(path, &resp.Data)
|
||||
}
|
||||
|
||||
// GetVolume returns a list of currencies with associated volume
|
||||
@@ -120,7 +128,7 @@ func (p *Poloniex) GetVolume() (interface{}, error) {
|
||||
var resp interface{}
|
||||
path := fmt.Sprintf("%s/public?command=return24hVolume", poloniexAPIURL)
|
||||
|
||||
return resp, common.SendHTTPGetRequest(path, true, p.Verbose, &resp)
|
||||
return resp, p.SendHTTPRequest(path, &resp)
|
||||
}
|
||||
|
||||
// GetOrderbook returns the full orderbook from poloniex
|
||||
@@ -136,7 +144,7 @@ func (p *Poloniex) GetOrderbook(currencyPair string, depth int) (OrderbookAll, e
|
||||
vals.Set("currencyPair", currencyPair)
|
||||
resp := OrderbookResponse{}
|
||||
path := fmt.Sprintf("%s/public?command=returnOrderBook&%s", poloniexAPIURL, vals.Encode())
|
||||
err := common.SendHTTPGetRequest(path, true, p.Verbose, &resp)
|
||||
err := p.SendHTTPRequest(path, &resp)
|
||||
if err != nil {
|
||||
return oba, err
|
||||
}
|
||||
@@ -169,7 +177,7 @@ func (p *Poloniex) GetOrderbook(currencyPair string, depth int) (OrderbookAll, e
|
||||
vals.Set("currencyPair", "all")
|
||||
resp := OrderbookResponseAll{}
|
||||
path := fmt.Sprintf("%s/public?command=returnOrderBook&%s", poloniexAPIURL, vals.Encode())
|
||||
err := common.SendHTTPGetRequest(path, true, p.Verbose, &resp.Data)
|
||||
err := p.SendHTTPRequest(path, &resp.Data)
|
||||
if err != nil {
|
||||
return oba, err
|
||||
}
|
||||
@@ -216,7 +224,7 @@ func (p *Poloniex) GetTradeHistory(currencyPair, start, end string) ([]TradeHist
|
||||
resp := []TradeHistory{}
|
||||
path := fmt.Sprintf("%s/public?command=returnTradeHistory&%s", poloniexAPIURL, vals.Encode())
|
||||
|
||||
return resp, common.SendHTTPGetRequest(path, true, p.Verbose, &resp)
|
||||
return resp, p.SendHTTPRequest(path, &resp)
|
||||
}
|
||||
|
||||
// GetChartData returns chart data for a specific currency pair
|
||||
@@ -239,7 +247,7 @@ func (p *Poloniex) GetChartData(currencyPair, start, end, period string) ([]Char
|
||||
resp := []ChartData{}
|
||||
path := fmt.Sprintf("%s/public?command=returnChartData&%s", poloniexAPIURL, vals.Encode())
|
||||
|
||||
err := common.SendHTTPGetRequest(path, true, p.Verbose, &resp)
|
||||
err := p.SendHTTPRequest(path, &resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -255,7 +263,7 @@ func (p *Poloniex) GetCurrencies() (map[string]Currencies, error) {
|
||||
resp := Response{}
|
||||
path := fmt.Sprintf("%s/public?command=returnCurrencies", poloniexAPIURL)
|
||||
|
||||
return resp.Data, common.SendHTTPGetRequest(path, true, p.Verbose, &resp.Data)
|
||||
return resp.Data, p.SendHTTPRequest(path, &resp.Data)
|
||||
}
|
||||
|
||||
// GetExchangeCurrencies returns a list of currencies using the GetTicker API
|
||||
@@ -280,7 +288,7 @@ func (p *Poloniex) GetLoanOrders(currency string) (LoanOrders, error) {
|
||||
resp := LoanOrders{}
|
||||
path := fmt.Sprintf("%s/public?command=returnLoanOrders¤cy=%s", poloniexAPIURL, currency)
|
||||
|
||||
return resp, common.SendHTTPGetRequest(path, true, p.Verbose, &resp)
|
||||
return resp, p.SendHTTPRequest(path, &resp)
|
||||
}
|
||||
|
||||
// GetBalances returns balances for your account.
|
||||
@@ -831,6 +839,11 @@ func (p *Poloniex) ToggleAutoRenew(orderNumber int64) (bool, error) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (p *Poloniex) SendHTTPRequest(path string, result interface{}) error {
|
||||
return p.SendPayload("GET", path, nil, nil, result, false, p.Verbose)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request
|
||||
func (p *Poloniex) SendAuthenticatedHTTPRequest(method, endpoint string, values url.Values, result interface{}) error {
|
||||
if !p.AuthenticatedAPISupport {
|
||||
@@ -853,10 +866,5 @@ func (p *Poloniex) SendAuthenticatedHTTPRequest(method, endpoint string, values
|
||||
|
||||
path := fmt.Sprintf("%s/%s", poloniexAPIURL, poloniexAPITradingEndpoint)
|
||||
|
||||
resp, err := common.SendHTTPRequest(method, path, headers, bytes.NewBufferString(values.Encode()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return common.JSONDecode([]byte(resp), &result)
|
||||
return p.SendPayload(method, path, headers, bytes.NewBufferString(values.Encode()), result, true, p.Verbose)
|
||||
}
|
||||
|
||||
252
exchanges/request/request.go
Normal file
252
exchanges/request/request.go
Normal file
@@ -0,0 +1,252 @@
|
||||
package request
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
)
|
||||
|
||||
const (
|
||||
maxJobQueue = 100
|
||||
maxHandles = 27
|
||||
)
|
||||
|
||||
var request service
|
||||
|
||||
type service struct {
|
||||
exchangeHandlers []*Handler
|
||||
}
|
||||
|
||||
// checkHandles checks to see if there is a handle monitored by the service
|
||||
func (s *service) checkHandles(exchName string, h *Handler) bool {
|
||||
for _, handle := range s.exchangeHandlers {
|
||||
if exchName == handle.exchName || handle == h {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// removeHandle releases handle from service
|
||||
func (s *service) removeHandle(exchName string) bool {
|
||||
for i, handle := range s.exchangeHandlers {
|
||||
if exchName == handle.exchName {
|
||||
handle.shutdown = true
|
||||
handle.wg.Wait()
|
||||
new := append(s.exchangeHandlers[:i-1], s.exchangeHandlers[i+1:]...)
|
||||
s.exchangeHandlers = new
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// limit contains the limit rate value which has a Mutex
|
||||
type limit struct {
|
||||
Val time.Duration
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
// getLimitRate returns limit rate with a protected call
|
||||
func (l *limit) getLimitRate() time.Duration {
|
||||
l.Lock()
|
||||
defer l.Unlock()
|
||||
return l.Val
|
||||
}
|
||||
|
||||
// setLimitRates sets initial limit rates with a protected call
|
||||
func (l *limit) setLimitRate(rate int) {
|
||||
l.Lock()
|
||||
l.Val = time.Duration(rate) * time.Millisecond
|
||||
l.Unlock()
|
||||
}
|
||||
|
||||
// Handler is a generic exchange specific request handler.
|
||||
type Handler struct {
|
||||
exchName string
|
||||
Client *http.Client
|
||||
shutdown bool
|
||||
LimitAuth *limit
|
||||
LimitUnauth *limit
|
||||
requests chan *exchRequest
|
||||
responses chan *exchResponse
|
||||
timeLockAuth chan int
|
||||
timeLock chan int
|
||||
wg sync.WaitGroup
|
||||
}
|
||||
|
||||
// SetRequestHandler sets initial variables for the request handler and returns
|
||||
// an error
|
||||
func (h *Handler) SetRequestHandler(exchName string, authRate, unauthRate int, client *http.Client) error {
|
||||
if request.checkHandles(exchName, h) {
|
||||
return errors.New("handler already registered for an exchange")
|
||||
}
|
||||
|
||||
h.exchName = exchName
|
||||
h.Client = client
|
||||
h.shutdown = false
|
||||
h.LimitAuth = new(limit)
|
||||
h.LimitAuth.setLimitRate(authRate)
|
||||
h.LimitUnauth = new(limit)
|
||||
h.LimitUnauth.setLimitRate(unauthRate)
|
||||
h.requests = make(chan *exchRequest, maxJobQueue)
|
||||
h.responses = make(chan *exchResponse, 1)
|
||||
h.timeLockAuth = make(chan int, 1)
|
||||
h.timeLock = make(chan int, 1)
|
||||
|
||||
request.exchangeHandlers = append(request.exchangeHandlers, h)
|
||||
h.startWorkers()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetRateLimit sets limit rates for exchange requests
|
||||
func (h *Handler) SetRateLimit(authRate, unauthRate int) {
|
||||
h.LimitAuth.setLimitRate(authRate)
|
||||
h.LimitUnauth.setLimitRate(unauthRate)
|
||||
}
|
||||
|
||||
// SendPayload packages a request, sends it to a channel, then a worker executes it
|
||||
func (h *Handler) SendPayload(method, path string, headers map[string]string, body io.Reader, result interface{}, authRequest, verbose bool) error {
|
||||
if h.exchName == "" {
|
||||
return errors.New("request handler not initialised")
|
||||
}
|
||||
|
||||
method = strings.ToUpper(method)
|
||||
|
||||
if method != "POST" && method != "GET" && method != "DELETE" {
|
||||
return errors.New("incorrect method - either POST, GET or DELETE")
|
||||
}
|
||||
|
||||
if verbose {
|
||||
log.Printf("%s exchange request path: %s", h.exchName, path)
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(method, path, body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for k, v := range headers {
|
||||
req.Header.Add(k, v)
|
||||
}
|
||||
|
||||
err = h.attachJob(req, path, authRequest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
contents, err := h.getResponse()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if verbose {
|
||||
log.Printf("%s exchange raw response: %s", h.exchName, string(contents[:]))
|
||||
}
|
||||
|
||||
return common.JSONDecode(contents, result)
|
||||
}
|
||||
|
||||
func (h *Handler) startWorkers() {
|
||||
h.wg.Add(3)
|
||||
go h.requestWorker()
|
||||
|
||||
// routine to monitor Autheticated limit rates
|
||||
go func() {
|
||||
h.timeLockAuth <- 1
|
||||
for !h.shutdown {
|
||||
<-h.timeLockAuth
|
||||
time.Sleep(h.LimitAuth.getLimitRate())
|
||||
h.timeLockAuth <- 1
|
||||
}
|
||||
h.wg.Done()
|
||||
}()
|
||||
// routine to monitor Unauthenticated limit rates
|
||||
go func() {
|
||||
h.timeLock <- 1
|
||||
for !h.shutdown {
|
||||
<-h.timeLock
|
||||
time.Sleep(h.LimitUnauth.getLimitRate())
|
||||
h.timeLock <- 1
|
||||
}
|
||||
h.wg.Done()
|
||||
}()
|
||||
}
|
||||
|
||||
// requestWorker handles the request queue
|
||||
func (h *Handler) requestWorker() {
|
||||
for job := range h.requests {
|
||||
if h.shutdown {
|
||||
break
|
||||
}
|
||||
|
||||
var httpResponse *http.Response
|
||||
var err error
|
||||
|
||||
if job.Auth {
|
||||
<-h.timeLockAuth
|
||||
httpResponse, err = h.Client.Do(job.Request)
|
||||
h.timeLockAuth <- 1
|
||||
} else {
|
||||
<-h.timeLock
|
||||
httpResponse, err = h.Client.Get(job.Path)
|
||||
h.timeLock <- 1
|
||||
}
|
||||
|
||||
for b := false; !b; {
|
||||
select {
|
||||
case h.responses <- &exchResponse{Response: httpResponse, ResError: err}:
|
||||
b = true
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
h.wg.Done()
|
||||
}
|
||||
|
||||
// exchRequest is the request type
|
||||
type exchRequest struct {
|
||||
Request *http.Request
|
||||
Path string
|
||||
Auth bool
|
||||
}
|
||||
|
||||
// attachJob sends a request using the http package to the request channel
|
||||
func (h *Handler) attachJob(req *http.Request, path string, isAuth bool) error {
|
||||
select {
|
||||
case h.requests <- &exchRequest{Request: req, Path: path, Auth: isAuth}:
|
||||
return nil
|
||||
default:
|
||||
return errors.New("job queue exceeded")
|
||||
}
|
||||
}
|
||||
|
||||
// exchResponse is the main response type for requests
|
||||
type exchResponse struct {
|
||||
Response *http.Response
|
||||
ResError error
|
||||
}
|
||||
|
||||
// getResponse monitors the current resp channel and returns the contents
|
||||
func (h *Handler) getResponse() ([]byte, error) {
|
||||
resp := <-h.responses
|
||||
if resp.ResError != nil {
|
||||
return []byte(""), resp.ResError
|
||||
}
|
||||
|
||||
defer resp.Response.Body.Close()
|
||||
contents, err := ioutil.ReadAll(resp.Response.Body)
|
||||
if err != nil {
|
||||
return []byte(""), err
|
||||
}
|
||||
return contents, nil
|
||||
}
|
||||
84
exchanges/request/request_test.go
Normal file
84
exchanges/request/request_test.go
Normal file
@@ -0,0 +1,84 @@
|
||||
package request
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
wg sync.WaitGroup
|
||||
bitfinex *Handler
|
||||
BTCMarkets *Handler
|
||||
)
|
||||
|
||||
func TestSetRequestHandler(t *testing.T) {
|
||||
bitfinex = new(Handler)
|
||||
err := bitfinex.SetRequestHandler("bitfinex", 1000, 1000, new(http.Client))
|
||||
if err != nil {
|
||||
t.Error("Test failed - request SetRequestHandler()", err)
|
||||
}
|
||||
err = bitfinex.SetRequestHandler("bitfinex", 1000, 1000, new(http.Client))
|
||||
if err == nil {
|
||||
t.Error("Test failed - request SetRequestHandler()", err)
|
||||
}
|
||||
err = bitfinex.SetRequestHandler("bla", 1000, 1000, new(http.Client))
|
||||
if err == nil {
|
||||
t.Error("Test failed - request SetRequestHandler()", err)
|
||||
}
|
||||
BTCMarkets = new(Handler)
|
||||
BTCMarkets.SetRequestHandler("btcmarkets", 1000, 1000, new(http.Client))
|
||||
|
||||
if len(request.exchangeHandlers) != 2 {
|
||||
t.Error("test failed - request GetRequestHandler() error")
|
||||
}
|
||||
wg.Add(2)
|
||||
}
|
||||
|
||||
func TestSetRateLimit(t *testing.T) {
|
||||
bitfinex.SetRateLimit(0, 0)
|
||||
BTCMarkets.SetRateLimit(0, 0)
|
||||
}
|
||||
|
||||
func TestSend(t *testing.T) {
|
||||
for i := 0; i < 1; i++ {
|
||||
go func() {
|
||||
var v interface{}
|
||||
err := bitfinex.SendPayload("GET",
|
||||
"https://api.bitfinex.com/v1/pubticker/BTCUSD",
|
||||
nil,
|
||||
nil,
|
||||
&v,
|
||||
false,
|
||||
false,
|
||||
)
|
||||
if err != nil {
|
||||
t.Error("test failed - send error", err)
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
var v interface{}
|
||||
err := BTCMarkets.SendPayload("GET",
|
||||
"https://api.btcmarkets.net/market/BTC/AUD/tick",
|
||||
nil,
|
||||
nil,
|
||||
&v,
|
||||
false,
|
||||
false,
|
||||
)
|
||||
if err != nil {
|
||||
t.Error("test failed - send error", err)
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
newHandler := new(Handler)
|
||||
err := newHandler.SendPayload("GET", "https://api.bitfinex.com/v1/pubticker/BTCUSD",
|
||||
nil, nil, nil, false, false)
|
||||
if err == nil {
|
||||
t.Error("test failed - request Send() error", err)
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -12,6 +13,7 @@ import (
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
@@ -35,12 +37,16 @@ const (
|
||||
wexCoinDepositAddress = "CoinDepositAddress"
|
||||
wexCreateCoupon = "CreateCoupon"
|
||||
wexRedeemCoupon = "RedeemCoupon"
|
||||
|
||||
wexAuthRate = 0
|
||||
wexUnauthRate = 0
|
||||
)
|
||||
|
||||
// WEX is the overarching type across the wex package
|
||||
type WEX struct {
|
||||
exchange.Base
|
||||
Ticker map[string]Ticker
|
||||
*request.Handler
|
||||
}
|
||||
|
||||
// SetDefaults sets current default value for WEX
|
||||
@@ -59,6 +65,8 @@ func (w *WEX) SetDefaults() {
|
||||
w.ConfigCurrencyPairFormat.Uppercase = true
|
||||
w.AssetTypes = []string{ticker.Spot}
|
||||
w.SupportsAutoPairUpdating = false
|
||||
w.Handler = new(request.Handler)
|
||||
w.SetRequestHandler(w.Name, wexAuthRate, wexUnauthRate, new(http.Client))
|
||||
}
|
||||
|
||||
// Setup sets exchange configuration parameters for WEX
|
||||
@@ -100,7 +108,7 @@ func (w *WEX) GetInfo() (Info, error) {
|
||||
resp := Info{}
|
||||
req := fmt.Sprintf("%s/%s/%s/", wexAPIPublicURL, wexAPIPublicVersion, wexInfo)
|
||||
|
||||
return resp, common.SendHTTPGetRequest(req, true, w.Verbose, &resp)
|
||||
return resp, w.SendHTTPRequest(req, &resp)
|
||||
}
|
||||
|
||||
// GetTicker returns a ticker for a specific currency
|
||||
@@ -112,7 +120,7 @@ func (w *WEX) GetTicker(symbol string) (map[string]Ticker, error) {
|
||||
response := Response{}
|
||||
req := fmt.Sprintf("%s/%s/%s/%s", wexAPIPublicURL, wexAPIPublicVersion, wexTicker, symbol)
|
||||
|
||||
return response.Data, common.SendHTTPGetRequest(req, true, w.Verbose, &response.Data)
|
||||
return response.Data, w.SendHTTPRequest(req, &response.Data)
|
||||
}
|
||||
|
||||
// GetDepth returns the depth for a specific currency
|
||||
@@ -124,8 +132,7 @@ func (w *WEX) GetDepth(symbol string) (Orderbook, error) {
|
||||
response := Response{}
|
||||
req := fmt.Sprintf("%s/%s/%s/%s", wexAPIPublicURL, wexAPIPublicVersion, wexDepth, symbol)
|
||||
|
||||
return response.Data[symbol],
|
||||
common.SendHTTPGetRequest(req, true, w.Verbose, &response.Data)
|
||||
return response.Data[symbol], w.SendHTTPRequest(req, &response.Data)
|
||||
}
|
||||
|
||||
// GetTrades returns the trades for a specific currency
|
||||
@@ -137,16 +144,22 @@ func (w *WEX) GetTrades(symbol string) ([]Trades, error) {
|
||||
response := Response{}
|
||||
req := fmt.Sprintf("%s/%s/%s/%s", wexAPIPublicURL, wexAPIPublicVersion, wexTrades, symbol)
|
||||
|
||||
return response.Data[symbol],
|
||||
common.SendHTTPGetRequest(req, true, w.Verbose, &response.Data)
|
||||
return response.Data[symbol], w.SendHTTPRequest(req, &response.Data)
|
||||
}
|
||||
|
||||
// GetAccountInfo returns a users account info
|
||||
func (w *WEX) GetAccountInfo() (AccountInfo, error) {
|
||||
var result AccountInfo
|
||||
|
||||
return result,
|
||||
w.SendAuthenticatedHTTPRequest(wexAccountInfo, url.Values{}, &result)
|
||||
err := w.SendAuthenticatedHTTPRequest(wexAccountInfo, url.Values{}, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
if result.Error != "" {
|
||||
return result, errors.New(result.Error)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetActiveOrders returns the active orders for a specific currency
|
||||
@@ -175,12 +188,15 @@ func (w *WEX) CancelOrder(OrderID int64) (bool, error) {
|
||||
req.Add("order_id", strconv.FormatInt(OrderID, 10))
|
||||
|
||||
var result CancelOrder
|
||||
err := w.SendAuthenticatedHTTPRequest(wexCancelOrder, req, &result)
|
||||
|
||||
err := w.SendAuthenticatedHTTPRequest(wexCancelOrder, req, &result)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if result.Error != "" {
|
||||
return false, errors.New(result.Error)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@@ -194,8 +210,15 @@ func (w *WEX) Trade(pair, orderType string, amount, price float64) (int64, error
|
||||
|
||||
var result Trade
|
||||
|
||||
return int64(result.OrderID),
|
||||
w.SendAuthenticatedHTTPRequest(wexTrade, req, &result)
|
||||
err := w.SendAuthenticatedHTTPRequest(wexTrade, req, &result)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if result.Error != "" {
|
||||
return 0, errors.New(result.Error)
|
||||
}
|
||||
return int64(result.OrderID), nil
|
||||
}
|
||||
|
||||
// GetTransactionHistory returns the transaction history
|
||||
@@ -241,7 +264,15 @@ func (w *WEX) WithdrawCoins(coin string, amount float64, address string) (Withdr
|
||||
|
||||
var result WithdrawCoins
|
||||
|
||||
return result, w.SendAuthenticatedHTTPRequest(wexWithdrawCoin, req, &result)
|
||||
err := w.SendAuthenticatedHTTPRequest(wexWithdrawCoin, req, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
if result.Error != "" {
|
||||
return result, errors.New(result.Error)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// CoinDepositAddress returns the deposit address for a specific currency
|
||||
@@ -251,8 +282,14 @@ func (w *WEX) CoinDepositAddress(coin string) (string, error) {
|
||||
|
||||
var result CoinDepositAddress
|
||||
|
||||
return result.Address,
|
||||
w.SendAuthenticatedHTTPRequest(wexCoinDepositAddress, req, &result)
|
||||
err := w.SendAuthenticatedHTTPRequest(wexCoinDepositAddress, req, &result)
|
||||
if err != nil {
|
||||
return result.Address, err
|
||||
}
|
||||
if result.Error != "" {
|
||||
return result.Address, errors.New(result.Error)
|
||||
}
|
||||
return result.Address, nil
|
||||
}
|
||||
|
||||
// CreateCoupon creates an exchange coupon for a sepcific currency
|
||||
@@ -263,7 +300,14 @@ func (w *WEX) CreateCoupon(currency string, amount float64) (CreateCoupon, error
|
||||
|
||||
var result CreateCoupon
|
||||
|
||||
return result, w.SendAuthenticatedHTTPRequest(wexCreateCoupon, req, &result)
|
||||
err := w.SendAuthenticatedHTTPRequest(wexCreateCoupon, req, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
if result.Error != "" {
|
||||
return result, errors.New(result.Error)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// RedeemCoupon redeems an exchange coupon
|
||||
@@ -273,7 +317,19 @@ func (w *WEX) RedeemCoupon(coupon string) (RedeemCoupon, error) {
|
||||
|
||||
var result RedeemCoupon
|
||||
|
||||
return result, w.SendAuthenticatedHTTPRequest(wexRedeemCoupon, req, &result)
|
||||
err := w.SendAuthenticatedHTTPRequest(wexRedeemCoupon, req, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
if result.Error != "" {
|
||||
return result, errors.New(result.Error)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (w *WEX) SendHTTPRequest(path string, result interface{}) error {
|
||||
return w.SendPayload("GET", path, nil, nil, result, false, w.Verbose)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request to WEX
|
||||
@@ -294,7 +350,10 @@ func (w *WEX) SendAuthenticatedHTTPRequest(method string, values url.Values, res
|
||||
hmac := common.GetHMAC(common.HashSHA512, []byte(encoded), []byte(w.APISecret))
|
||||
|
||||
if w.Verbose {
|
||||
log.Printf("Sending POST request to %s calling method %s with params %s\n", wexAPIPrivateURL, method, encoded)
|
||||
log.Printf("Sending POST request to %s calling method %s with params %s\n",
|
||||
wexAPIPrivateURL,
|
||||
method,
|
||||
encoded)
|
||||
}
|
||||
|
||||
headers := make(map[string]string)
|
||||
@@ -302,25 +361,5 @@ func (w *WEX) SendAuthenticatedHTTPRequest(method string, values url.Values, res
|
||||
headers["Sign"] = common.HexEncodeToString(hmac)
|
||||
headers["Content-Type"] = "application/x-www-form-urlencoded"
|
||||
|
||||
resp, err := common.SendHTTPRequest("POST", wexAPIPrivateURL, headers, strings.NewReader(encoded))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
response := Response{}
|
||||
err = common.JSONDecode([]byte(resp), &response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if response.Success != 1 {
|
||||
return errors.New(response.Error)
|
||||
}
|
||||
|
||||
JSONEncoded, err := common.JSONEncode(response.Return)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return common.JSONDecode(JSONEncoded, &result)
|
||||
return w.SendPayload("POST", wexAPIPrivateURL, headers, strings.NewReader(encoded), result, true, w.Verbose)
|
||||
}
|
||||
|
||||
@@ -33,12 +33,14 @@ func TestSetup(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetFee(t *testing.T) {
|
||||
t.Parallel()
|
||||
if w.GetFee() != 0.2 {
|
||||
t.Error("Test Failed - GetFee() error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := w.GetInfo()
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetInfo() error")
|
||||
@@ -46,6 +48,7 @@ func TestGetInfo(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetTicker(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := w.GetTicker("btc_usd")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetTicker() error", err)
|
||||
@@ -53,6 +56,7 @@ func TestGetTicker(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetDepth(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := w.GetDepth("btc_usd")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetDepth() error", err)
|
||||
@@ -60,6 +64,7 @@ func TestGetDepth(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetTrades(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := w.GetTrades("btc_usd")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetTrades() error", err)
|
||||
@@ -67,6 +72,7 @@ func TestGetTrades(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := w.GetAccountInfo()
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetAccountInfo() error", err)
|
||||
@@ -74,6 +80,7 @@ func TestGetAccountInfo(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := w.GetActiveOrders("")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetActiveOrders() error", err)
|
||||
@@ -81,6 +88,7 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetOrderInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := w.GetOrderInfo(6196974)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetOrderInfo() error", err)
|
||||
@@ -88,6 +96,7 @@ func TestGetOrderInfo(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := w.CancelOrder(1337)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - CancelOrder() error", err)
|
||||
@@ -95,6 +104,7 @@ func TestCancelOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTrade(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := w.Trade("", "buy", 0, 0)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - Trade() error", err)
|
||||
@@ -102,6 +112,7 @@ func TestTrade(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetTransactionHistory(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := w.GetTransactionHistory(0, 0, 0, "", "", "")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetTransactionHistory() error", err)
|
||||
@@ -109,6 +120,7 @@ func TestGetTransactionHistory(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetTradeHistory(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := w.GetTradeHistory(0, 0, 0, "", "", "", "")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetTradeHistory() error", err)
|
||||
@@ -116,6 +128,7 @@ func TestGetTradeHistory(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawCoins(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := w.WithdrawCoins("", 0, "")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - WithdrawCoins() error", err)
|
||||
@@ -123,6 +136,7 @@ func TestWithdrawCoins(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCoinDepositAddress(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := w.CoinDepositAddress("btc")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - WithdrawCoins() error", err)
|
||||
@@ -130,6 +144,7 @@ func TestCoinDepositAddress(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCreateCoupon(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := w.CreateCoupon("bla", 0)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - CreateCoupon() error", err)
|
||||
@@ -137,6 +152,7 @@ func TestCreateCoupon(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRedeemCoupon(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := w.RedeemCoupon("bla")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - RedeemCoupon() error", err)
|
||||
|
||||
@@ -72,6 +72,7 @@ type AccountInfo struct {
|
||||
} `json:"rights"`
|
||||
ServerTime float64 `json:"server_time"`
|
||||
TransactionCount int `json:"transaction_count"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// OrderInfo stores order information
|
||||
@@ -89,6 +90,7 @@ type OrderInfo struct {
|
||||
type CancelOrder struct {
|
||||
OrderID float64 `json:"order_id"`
|
||||
Funds map[string]float64 `json:"funds"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// Trade stores the trade information
|
||||
@@ -97,6 +99,7 @@ type Trade struct {
|
||||
Remains float64 `json:"remains"`
|
||||
OrderID float64 `json:"order_id"`
|
||||
Funds map[string]float64 `json:"funds"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// TransHistory stores transaction history
|
||||
@@ -123,6 +126,7 @@ type TradeHistory struct {
|
||||
// CoinDepositAddress stores a curency deposit address
|
||||
type CoinDepositAddress struct {
|
||||
Address string `json:"address"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// WithdrawCoins stores information for a withdrawcoins request
|
||||
@@ -130,6 +134,7 @@ type WithdrawCoins struct {
|
||||
TID int64 `json:"tId"`
|
||||
AmountSent float64 `json:"amountSent"`
|
||||
Funds map[string]float64 `json:"funds"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// CreateCoupon stores information coupon information
|
||||
@@ -137,6 +142,7 @@ type CreateCoupon struct {
|
||||
Coupon string `json:"coupon"`
|
||||
TransID int64 `json:"transID"`
|
||||
Funds map[string]float64 `json:"funds"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// RedeemCoupon stores redeem coupon information
|
||||
@@ -144,4 +150,5 @@ type RedeemCoupon struct {
|
||||
CouponAmount float64 `json:"couponAmount,string"`
|
||||
CouponCurrency string `json:"couponCurrency"`
|
||||
TransID int64 `json:"transID"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -12,6 +13,7 @@ import (
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
@@ -33,12 +35,16 @@ const (
|
||||
privateWithdrawCoinsToAddress = "WithdrawCoinsToAddress"
|
||||
privateCreateCoupon = "CreateYobicode"
|
||||
privateRedeemCoupon = "RedeemYobicode"
|
||||
|
||||
yobitAuthRate = 0
|
||||
yobitUnauthRate = 0
|
||||
)
|
||||
|
||||
// Yobit is the overarching type across the Yobit package
|
||||
type Yobit struct {
|
||||
exchange.Base
|
||||
Ticker map[string]Ticker
|
||||
*request.Handler
|
||||
}
|
||||
|
||||
// SetDefaults sets current default value for Yobit
|
||||
@@ -59,6 +65,8 @@ func (y *Yobit) SetDefaults() {
|
||||
y.ConfigCurrencyPairFormat.Uppercase = true
|
||||
y.AssetTypes = []string{ticker.Spot}
|
||||
y.SupportsAutoPairUpdating = false
|
||||
y.Handler = new(request.Handler)
|
||||
y.SetRequestHandler(y.Name, yobitAuthRate, yobitUnauthRate, new(http.Client))
|
||||
}
|
||||
|
||||
// Setup sets exchange configuration parameters for Yobit
|
||||
@@ -100,7 +108,7 @@ func (y *Yobit) GetInfo() (Info, error) {
|
||||
resp := Info{}
|
||||
path := fmt.Sprintf("%s/%s/%s/", apiPublicURL, apiPublicVersion, publicInfo)
|
||||
|
||||
return resp, common.SendHTTPGetRequest(path, true, y.Verbose, &resp)
|
||||
return resp, y.SendHTTPRequest(path, &resp)
|
||||
}
|
||||
|
||||
// GetTicker returns a ticker for a specific currency
|
||||
@@ -112,7 +120,7 @@ func (y *Yobit) GetTicker(symbol string) (map[string]Ticker, error) {
|
||||
response := Response{}
|
||||
path := fmt.Sprintf("%s/%s/%s/%s", apiPublicURL, apiPublicVersion, publicTicker, symbol)
|
||||
|
||||
return response.Data, common.SendHTTPGetRequest(path, true, y.Verbose, &response.Data)
|
||||
return response.Data, y.SendHTTPRequest(path, &response.Data)
|
||||
}
|
||||
|
||||
// GetDepth returns the depth for a specific currency
|
||||
@@ -125,7 +133,7 @@ func (y *Yobit) GetDepth(symbol string) (Orderbook, error) {
|
||||
path := fmt.Sprintf("%s/%s/%s/%s", apiPublicURL, apiPublicVersion, publicDepth, symbol)
|
||||
|
||||
return response.Data[symbol],
|
||||
common.SendHTTPGetRequest(path, true, y.Verbose, &response.Data)
|
||||
y.SendHTTPRequest(path, &response.Data)
|
||||
}
|
||||
|
||||
// GetTrades returns the trades for a specific currency
|
||||
@@ -137,14 +145,21 @@ func (y *Yobit) GetTrades(symbol string) ([]Trades, error) {
|
||||
response := Response{}
|
||||
path := fmt.Sprintf("%s/%s/%s/%s", apiPublicURL, apiPublicVersion, publicTrades, symbol)
|
||||
|
||||
return response.Data[symbol], common.SendHTTPGetRequest(path, true, y.Verbose, &response.Data)
|
||||
return response.Data[symbol], y.SendHTTPRequest(path, &response.Data)
|
||||
}
|
||||
|
||||
// GetAccountInfo returns a users account info
|
||||
func (y *Yobit) GetAccountInfo() (AccountInfo, error) {
|
||||
result := AccountInfo{}
|
||||
|
||||
return result, y.SendAuthenticatedHTTPRequest(privateAccountInfo, url.Values{}, &result)
|
||||
err := y.SendAuthenticatedHTTPRequest(privateAccountInfo, url.Values{}, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
if result.Error != "" {
|
||||
return result, errors.New(result.Error)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// Trade places an order and returns the order ID if successful or an error
|
||||
@@ -157,7 +172,14 @@ func (y *Yobit) Trade(pair, orderType string, amount, price float64) (int64, err
|
||||
|
||||
result := Trade{}
|
||||
|
||||
return int64(result.OrderID), y.SendAuthenticatedHTTPRequest(privateTrade, req, &result)
|
||||
err := y.SendAuthenticatedHTTPRequest(privateTrade, req, &result)
|
||||
if err != nil {
|
||||
return int64(result.OrderID), err
|
||||
}
|
||||
if result.Error != "" {
|
||||
return int64(result.OrderID), errors.New(result.Error)
|
||||
}
|
||||
return int64(result.OrderID), nil
|
||||
}
|
||||
|
||||
// GetActiveOrders returns the active orders for a specific currency
|
||||
@@ -186,12 +208,14 @@ func (y *Yobit) CancelOrder(OrderID int64) (bool, error) {
|
||||
req.Add("order_id", strconv.FormatInt(OrderID, 10))
|
||||
|
||||
result := CancelOrder{}
|
||||
err := y.SendAuthenticatedHTTPRequest(privateCancelOrder, req, &result)
|
||||
|
||||
err := y.SendAuthenticatedHTTPRequest(privateCancelOrder, req, &result)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if result.Error != "" {
|
||||
return false, errors.New(result.Error)
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
@@ -219,7 +243,14 @@ func (y *Yobit) GetDepositAddress(coin string) (DepositAddress, error) {
|
||||
|
||||
result := DepositAddress{}
|
||||
|
||||
return result, y.SendAuthenticatedHTTPRequest(privateGetDepositAddress, req, &result)
|
||||
err := y.SendAuthenticatedHTTPRequest(privateGetDepositAddress, req, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
if result.Error != "" {
|
||||
return result, errors.New(result.Error)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// WithdrawCoinsToAddress initiates a withdrawal to a specified address
|
||||
@@ -231,7 +262,14 @@ func (y *Yobit) WithdrawCoinsToAddress(coin string, amount float64, address stri
|
||||
|
||||
result := WithdrawCoinsToAddress{}
|
||||
|
||||
return result, y.SendAuthenticatedHTTPRequest(privateWithdrawCoinsToAddress, req, &result)
|
||||
err := y.SendAuthenticatedHTTPRequest(privateWithdrawCoinsToAddress, req, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
if result.Error != "" {
|
||||
return result, errors.New(result.Error)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// CreateCoupon creates an exchange coupon for a sepcific currency
|
||||
@@ -242,7 +280,14 @@ func (y *Yobit) CreateCoupon(currency string, amount float64) (CreateCoupon, err
|
||||
|
||||
var result CreateCoupon
|
||||
|
||||
return result, y.SendAuthenticatedHTTPRequest(privateCreateCoupon, req, &result)
|
||||
err := y.SendAuthenticatedHTTPRequest(privateCreateCoupon, req, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
if result.Error != "" {
|
||||
return result, errors.New(result.Error)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// RedeemCoupon redeems an exchange coupon
|
||||
@@ -252,7 +297,19 @@ func (y *Yobit) RedeemCoupon(coupon string) (RedeemCoupon, error) {
|
||||
|
||||
result := RedeemCoupon{}
|
||||
|
||||
return result, y.SendAuthenticatedHTTPRequest(privateRedeemCoupon, req, &result)
|
||||
err := y.SendAuthenticatedHTTPRequest(privateRedeemCoupon, req, &result)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
if result.Error != "" {
|
||||
return result, errors.New(result.Error)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends an unauthenticated HTTP request
|
||||
func (y *Yobit) SendHTTPRequest(path string, result interface{}) error {
|
||||
return y.SendPayload("GET", path, nil, nil, result, false, y.Verbose)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request to Yobit
|
||||
@@ -285,30 +342,5 @@ func (y *Yobit) SendAuthenticatedHTTPRequest(path string, params url.Values, res
|
||||
headers["Sign"] = common.HexEncodeToString(hmac)
|
||||
headers["Content-Type"] = "application/x-www-form-urlencoded"
|
||||
|
||||
resp, err := common.SendHTTPRequest(
|
||||
"POST", apiPrivateURL, headers, strings.NewReader(encoded),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if y.Verbose {
|
||||
log.Printf("Received raw: \n%s\n", resp)
|
||||
}
|
||||
|
||||
response := Response{}
|
||||
if err = common.JSONDecode([]byte(resp), &response); err != nil {
|
||||
return errors.New("sendAuthenticatedHTTPRequest: Unable to JSON Unmarshal response." + err.Error())
|
||||
}
|
||||
|
||||
if response.Success != 1 {
|
||||
return errors.New(response.Error)
|
||||
}
|
||||
|
||||
JSONEncoded, err := common.JSONEncode(response.Return)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return common.JSONDecode(JSONEncoded, &result)
|
||||
return y.SendPayload("POST", apiPrivateURL, headers, strings.NewReader(encoded), result, true, y.Verbose)
|
||||
}
|
||||
|
||||
@@ -33,12 +33,14 @@ func TestSetup(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetFee(t *testing.T) {
|
||||
t.Parallel()
|
||||
if y.GetFee() != 0.2 {
|
||||
t.Error("Test Failed - GetFee() error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := y.GetInfo()
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetInfo() error")
|
||||
@@ -46,6 +48,7 @@ func TestGetInfo(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetTicker(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := y.GetTicker("btc_usd")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetTicker() error", err)
|
||||
@@ -53,6 +56,7 @@ func TestGetTicker(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetDepth(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := y.GetDepth("btc_usd")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetDepth() error", err)
|
||||
@@ -60,6 +64,7 @@ func TestGetDepth(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetTrades(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := y.GetTrades("btc_usd")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - GetTrades() error", err)
|
||||
@@ -67,6 +72,7 @@ func TestGetTrades(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetAccountInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := y.GetAccountInfo()
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetAccountInfo() error", err)
|
||||
@@ -74,6 +80,7 @@ func TestGetAccountInfo(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetActiveOrders(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := y.GetActiveOrders("")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetActiveOrders() error", err)
|
||||
@@ -81,6 +88,7 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetOrderInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := y.GetOrderInfo(6196974)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetOrderInfo() error", err)
|
||||
@@ -88,6 +96,7 @@ func TestGetOrderInfo(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCancelOrder(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := y.CancelOrder(1337)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - CancelOrder() error", err)
|
||||
@@ -95,6 +104,7 @@ func TestCancelOrder(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestTrade(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := y.Trade("", "buy", 0, 0)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - Trade() error", err)
|
||||
@@ -102,6 +112,7 @@ func TestTrade(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetTradeHistory(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := y.GetTradeHistory(0, 0, 0, "", "", "", "")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetTradeHistory() error", err)
|
||||
@@ -109,6 +120,7 @@ func TestGetTradeHistory(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWithdrawCoinsToAddress(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := y.WithdrawCoinsToAddress("", 0, "")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - WithdrawCoinsToAddress() error", err)
|
||||
@@ -116,6 +128,7 @@ func TestWithdrawCoinsToAddress(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetDepositAddress(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := y.GetDepositAddress("btc")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - GetDepositAddress() error", err)
|
||||
@@ -123,6 +136,7 @@ func TestGetDepositAddress(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCreateYobicode(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := y.CreateCoupon("bla", 0)
|
||||
if err == nil {
|
||||
t.Error("Test Failed - CreateYobicode() error", err)
|
||||
@@ -130,7 +144,8 @@ func TestCreateYobicode(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRedeemYobicode(t *testing.T) {
|
||||
_, err := y.RedeemCoupon("bla")
|
||||
t.Parallel()
|
||||
_, err := y.RedeemCoupon("bla2")
|
||||
if err == nil {
|
||||
t.Error("Test Failed - RedeemYobicode() error", err)
|
||||
}
|
||||
|
||||
@@ -73,6 +73,7 @@ type AccountInfo struct {
|
||||
TransactionCount int `json:"transaction_count"`
|
||||
OpenOrders int `json:"open_orders"`
|
||||
ServerTime float64 `json:"server_time"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// OrderInfo stores order information
|
||||
@@ -90,6 +91,7 @@ type OrderInfo struct {
|
||||
type CancelOrder struct {
|
||||
OrderID float64 `json:"order_id"`
|
||||
Funds map[string]float64 `json:"funds"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// Trade stores the trade information
|
||||
@@ -98,6 +100,7 @@ type Trade struct {
|
||||
Remains float64 `json:"remains"`
|
||||
OrderID float64 `json:"order_id"`
|
||||
Funds map[string]float64 `json:"funds"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// TradeHistory stores trade history
|
||||
@@ -116,11 +119,13 @@ type DepositAddress struct {
|
||||
Address string `json:"address"`
|
||||
ProcessedAmount float64 `json:"processed_amount"`
|
||||
ServerTime int64 `json:"server_time"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// WithdrawCoinsToAddress stores information for a withdrawcoins request
|
||||
type WithdrawCoinsToAddress struct {
|
||||
ServerTime int64 `json:"server_time"`
|
||||
ServerTime int64 `json:"server_time"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// CreateCoupon stores information coupon information
|
||||
@@ -128,6 +133,7 @@ type CreateCoupon struct {
|
||||
Coupon string `json:"coupon"`
|
||||
TransID int64 `json:"transID"`
|
||||
Funds map[string]float64 `json:"funds"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
// RedeemCoupon stores redeem coupon information
|
||||
@@ -136,4 +142,5 @@ type RedeemCoupon struct {
|
||||
CouponCurrency string `json:"couponCurrency"`
|
||||
TransID int64 `json:"transID"`
|
||||
Funds map[string]float64 `json:"funds"`
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user