Introduce request package and integrate with exchanges

This commit is contained in:
Ryan O'Hara-Reid
2018-03-27 14:05:15 +11:00
committed by Adrian Gallagher
parent 52dfddbb18
commit 7fc9d20fd7
52 changed files with 1990 additions and 1544 deletions

View File

@@ -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{}, &currencies)
if err := b.SendHTTPRequest(path, &currencies); 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)
}

View File

@@ -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")
}

View File

@@ -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"`
}

View File

@@ -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,
},
)
}