In the common package added JSONDecode error check. Added verbosity in SendHTTPGetRequest. Updated Nonce package function. Fixed issues in ItBit package and expanded test coverage.

This commit is contained in:
Ryan O'Hara-Reid
2017-09-12 08:37:18 +10:00
parent dae90a2eaa
commit 79a1911c93
24 changed files with 601 additions and 241 deletions

View File

@@ -20,6 +20,7 @@ import (
"net/http"
"net/url"
"os"
"reflect"
"regexp"
"strconv"
"strings"
@@ -294,16 +295,24 @@ func SendHTTPRequest(method, path string, headers map[string]string, body io.Rea
// SendHTTPGetRequest sends a simple get request using a url string & JSON
// decodes the response into a struct pointer you have supplied. Returns an error
// on failure.
func SendHTTPGetRequest(url string, jsonDecode bool, result interface{}) error {
func SendHTTPGetRequest(url string, jsonDecode, isVerbose bool, result interface{}) error {
if isVerbose {
log.Println("Raw URL: ", url)
}
res, err := http.Get(url)
if err != nil {
return err
}
if res.StatusCode != 200 {
<<<<<<< dae90a2eaa109648bdb85f8298d805e00ad4e974
log.Printf("HTTP status code: %d\n", res.StatusCode)
log.Printf("URL: %s\n", url)
return errors.New("status code was not 200")
=======
return fmt.Errorf("common.SendHTTPGetRequest() error: HTTP status code %d", res.StatusCode)
>>>>>>> In the common package added JSONDecode error check. Added verbosity in SendHTTPGetRequest. Updated Nonce package function. Fixed issues in ItBit package and expanded test coverage.
}
contents, err := ioutil.ReadAll(res.Body)
@@ -311,16 +320,18 @@ func SendHTTPGetRequest(url string, jsonDecode bool, result interface{}) error {
return err
}
if isVerbose {
log.Println("Raw Resp: ", string(contents[:]))
}
defer res.Body.Close()
if jsonDecode {
err := JSONDecode(contents, &result)
err := JSONDecode(contents, result)
if err != nil {
log.Println(string(contents[:]))
return err
}
} else {
result = &contents
}
return nil
@@ -333,6 +344,9 @@ func JSONEncode(v interface{}) ([]byte, error) {
// JSONDecode decodes JSON data into a structure
func JSONDecode(data []byte, to interface{}) error {
if !StringContains(reflect.ValueOf(to).Type().String(), "*") {
return errors.New("json decode error - memory address not supplied")
}
return json.Unmarshal(data, to)
}

View File

@@ -488,15 +488,15 @@ func TestSendHTTPGetRequest(t *testing.T) {
url := `https://etherchain.org/api/account/multiple/0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe`
result := test{}
err := SendHTTPGetRequest(url, true, &result)
err := SendHTTPGetRequest(url, true, false, &result)
if err != nil {
t.Errorf("Test failed - common SendHTTPGetRequest error: %s", err)
}
err = SendHTTPGetRequest("DINGDONG", true, &result)
err = SendHTTPGetRequest("DINGDONG", true, false, &result)
if err == nil {
t.Error("Test failed - common SendHTTPGetRequest error")
}
err = SendHTTPGetRequest(url, false, &result)
err = SendHTTPGetRequest(url, false, false, &result)
if err != nil {
t.Error("Test failed - common SendHTTPGetRequest error")
}

View File

@@ -314,7 +314,7 @@ func FetchFixerCurrencyData() error {
CurrencyStoreFixer = make(map[string]float64)
err := common.SendHTTPGetRequest(url, true, &result)
err := common.SendHTTPGetRequest(url, true, false, &result)
if err != nil {
return err
}

View File

@@ -83,7 +83,7 @@ func (a *ANX) GetFee(maker bool) float64 {
func (a *ANX) GetTicker(currency string) (ANXTicker, error) {
var ticker ANXTicker
err := common.SendHTTPGetRequest(fmt.Sprintf("%sapi/2/%s/%s", ANX_API_URL, currency, ANX_TICKER), true, &ticker)
err := common.SendHTTPGetRequest(fmt.Sprintf("%sapi/2/%s/%s", ANX_API_URL, currency, ANX_TICKER), true, a.Verbose, &ticker)
if err != nil {
return ANXTicker{}, err
}

View File

@@ -119,7 +119,7 @@ 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, &response)
return response, common.SendHTTPGetRequest(path, true, b.Verbose, &response)
}
// GetStats returns various statistics about the requested pair
@@ -127,7 +127,7 @@ func (b *Bitfinex) GetStats(symbol string) ([]Stat, error) {
response := []Stat{}
path := fmt.Sprint(bitfinexAPIURL + bitfinexStats + symbol)
return response, common.SendHTTPGetRequest(path, true, &response)
return response, common.SendHTTPGetRequest(path, true, b.Verbose, &response)
}
// GetFundingBook the entire margin funding book for both bids and asks sides
@@ -137,7 +137,7 @@ func (b *Bitfinex) GetFundingBook(symbol string) (FundingBook, error) {
response := FundingBook{}
path := fmt.Sprint(bitfinexAPIURL + bitfinexLendbook + symbol)
return response, common.SendHTTPGetRequest(path, true, &response)
return response, common.SendHTTPGetRequest(path, true, b.Verbose, &response)
}
// GetOrderbook retieves the entire orderbook bid and ask price on a currency
@@ -149,7 +149,7 @@ func (b *Bitfinex) GetOrderbook(currencyPair string, values url.Values) (Orderbo
bitfinexAPIURL+bitfinexOrderbook+currencyPair,
values,
)
return response, common.SendHTTPGetRequest(path, true, &response)
return response, common.SendHTTPGetRequest(path, true, b.Verbose, &response)
}
// GetTrades returns a list of the most recent trades for the given curencyPair
@@ -160,7 +160,7 @@ func (b *Bitfinex) GetTrades(currencyPair string, values url.Values) ([]TradeStr
bitfinexAPIURL+bitfinexTrades+currencyPair,
values,
)
return response, common.SendHTTPGetRequest(path, true, &response)
return response, common.SendHTTPGetRequest(path, true, b.Verbose, &response)
}
// GetLendbook returns a list of the most recent funding data for the given
@@ -174,7 +174,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, &response)
return response, common.SendHTTPGetRequest(path, true, b.Verbose, &response)
}
// GetLends returns a list of the most recent funding data for the given
@@ -185,7 +185,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, &response)
return response, common.SendHTTPGetRequest(path, true, b.Verbose, &response)
}
// GetSymbols returns the avaliable currency pairs on the exchange
@@ -193,7 +193,7 @@ func (b *Bitfinex) GetSymbols() ([]string, error) {
products := []string{}
path := fmt.Sprint(bitfinexAPIURL + bitfinexSymbols)
return products, common.SendHTTPGetRequest(path, true, &products)
return products, common.SendHTTPGetRequest(path, true, b.Verbose, &products)
}
// GetSymbolsDetails a list of valid symbol IDs and the pair details
@@ -201,7 +201,7 @@ func (b *Bitfinex) GetSymbolsDetails() ([]SymbolDetails, error) {
response := []SymbolDetails{}
path := fmt.Sprint(bitfinexAPIURL + bitfinexSymbolsDetails)
return response, common.SendHTTPGetRequest(path, true, &response)
return response, common.SendHTTPGetRequest(path, true, b.Verbose, &response)
}
// GetAccountInfo returns information about your account incl. trading fees

View File

@@ -127,7 +127,7 @@ func (b *Bitstamp) GetTicker(currency string, hourly bool) (Ticker, error) {
tickerEndpoint,
common.StringToLower(currency),
)
return response, common.SendHTTPGetRequest(path, true, &response)
return response, common.SendHTTPGetRequest(path, true, b.Verbose, &response)
}
// GetOrderbook Returns a JSON dictionary with "bids" and "asks". Each is a list
@@ -149,7 +149,7 @@ func (b *Bitstamp) GetOrderbook(currency string) (Orderbook, error) {
common.StringToLower(currency),
)
err := common.SendHTTPGetRequest(path, true, &resp)
err := common.SendHTTPGetRequest(path, true, b.Verbose, &resp)
if err != nil {
return Orderbook{}, err
}
@@ -204,7 +204,7 @@ func (b *Bitstamp) GetTransactions(currencyPair string, values url.Values) ([]Tr
values,
)
return transactions, common.SendHTTPGetRequest(path, true, &transactions)
return transactions, common.SendHTTPGetRequest(path, true, b.Verbose, &transactions)
}
// GetEURUSDConversionRate returns the conversion rate between Euro and USD
@@ -212,7 +212,7 @@ func (b *Bitstamp) GetEURUSDConversionRate() (EURUSDConversionRate, error) {
rate := EURUSDConversionRate{}
path := fmt.Sprintf("%s/%s", bitstampAPIURL, bitstampAPIEURUSD)
return rate, common.SendHTTPGetRequest(path, true, &rate)
return rate, common.SendHTTPGetRequest(path, true, b.Verbose, &rate)
}
// GetBalance returns full balance of currency held on the exchange

View File

@@ -373,7 +373,7 @@ func (b *Bittrex) HTTPRequest(path string, auth bool, values url.Values, v inter
return err
}
} else {
if err := common.SendHTTPGetRequest(path, true, &response); err != nil {
if err := common.SendHTTPGetRequest(path, true, b.Verbose, &response); err != nil {
return err
}
}

View File

@@ -99,7 +99,7 @@ func (b *BTCC) GetTicker(currencyPair string) (Ticker, error) {
resp := Response{}
req := fmt.Sprintf("%sdata/ticker?market=%s", btccAPIUrl, currencyPair)
return resp.Ticker, common.SendHTTPGetRequest(req, true, &resp)
return resp.Ticker, common.SendHTTPGetRequest(req, true, b.Verbose, &resp)
}
// GetTradesLast24h returns the trades executed on the exchange over the past
@@ -109,7 +109,7 @@ func (b *BTCC) GetTradesLast24h(currencyPair string) ([]Trade, error) {
trades := []Trade{}
req := fmt.Sprintf("%sdata/trades?market=%s", btccAPIUrl, currencyPair)
return trades, common.SendHTTPGetRequest(req, true, &trades)
return trades, common.SendHTTPGetRequest(req, true, b.Verbose, &trades)
}
// GetTradeHistory returns trade history data
@@ -136,7 +136,7 @@ func (b *BTCC) GetTradeHistory(currencyPair string, limit, sinceTid int64, time
req = common.EncodeURLValues(req, v)
return trades, common.SendHTTPGetRequest(req, true, &trades)
return trades, common.SendHTTPGetRequest(req, true, b.Verbose, &trades)
}
// GetOrderBook returns current market order book
@@ -151,7 +151,7 @@ func (b *BTCC) GetOrderBook(currencyPair string, limit int) (Orderbook, error) {
req = fmt.Sprintf("%sdata/orderbook?market=%s", btccAPIUrl, currencyPair)
}
return result, common.SendHTTPGetRequest(req, true, &result)
return result, common.SendHTTPGetRequest(req, true, b.Verbose, &result)
}
func (b *BTCC) GetAccountInfo(infoType string) error {

View File

@@ -97,7 +97,7 @@ func (b *BTCMarkets) GetTicker(symbol string) (Ticker, error) {
path := fmt.Sprintf("/market/%s/AUD/tick", common.StringToUpper(symbol))
return ticker,
common.SendHTTPGetRequest(btcMarketsAPIURL+path, true, &ticker)
common.SendHTTPGetRequest(btcMarketsAPIURL+path, true, b.Verbose, &ticker)
}
// GetOrderbook returns current orderbook
@@ -107,7 +107,7 @@ func (b *BTCMarkets) GetOrderbook(symbol string) (Orderbook, error) {
path := fmt.Sprintf("/market/%s/AUD/orderbook", common.StringToUpper(symbol))
return orderbook,
common.SendHTTPGetRequest(btcMarketsAPIURL+path, true, &orderbook)
common.SendHTTPGetRequest(btcMarketsAPIURL+path, true, b.Verbose, &orderbook)
}
// GetTrades returns executed trades on the exchange
@@ -117,7 +117,7 @@ func (b *BTCMarkets) GetTrades(symbol string, values url.Values) ([]Trade, error
trades := []Trade{}
path := common.EncodeURLValues(fmt.Sprintf("%s/market/%s/AUD/trades", btcMarketsAPIURL, symbol), values)
return trades, common.SendHTTPGetRequest(path, true, &trades)
return trades, common.SendHTTPGetRequest(path, true, b.Verbose, &trades)
}
// NewOrder requests a new order and returns an ID

View File

@@ -110,7 +110,7 @@ func (g *GDAX) GetProducts() ([]Product, error) {
products := []Product{}
return products,
common.SendHTTPGetRequest(gdaxAPIURL+gdaxProducts, true, &products)
common.SendHTTPGetRequest(gdaxAPIURL+gdaxProducts, true, g.Verbose, &products)
}
// GetOrderbook returns orderbook by currency pair and level
@@ -123,7 +123,7 @@ func (g *GDAX) GetOrderbook(symbol string, level int) (interface{}, error) {
path = fmt.Sprintf("%s/%s/%s?level=%s", gdaxAPIURL+gdaxProducts, symbol, gdaxOrderbook, levelStr)
}
if err := common.SendHTTPGetRequest(path, true, &orderbook); err != nil {
if err := common.SendHTTPGetRequest(path, true, g.Verbose, &orderbook); err != nil {
return nil, err
}
@@ -193,7 +193,7 @@ func (g *GDAX) GetTicker(currencyPair string) (Ticker, error) {
"%s/%s/%s", gdaxAPIURL+gdaxProducts, currencyPair, gdaxTicker)
log.Println(path)
return ticker, common.SendHTTPGetRequest(path, true, &ticker)
return ticker, common.SendHTTPGetRequest(path, true, g.Verbose, &ticker)
}
// GetTrades listd the latest trades for a product
@@ -203,7 +203,7 @@ func (g *GDAX) GetTrades(currencyPair string) ([]Trade, error) {
path := fmt.Sprintf(
"%s/%s/%s", gdaxAPIURL+gdaxProducts, currencyPair, gdaxTrades)
return trades, common.SendHTTPGetRequest(path, true, &trades)
return trades, common.SendHTTPGetRequest(path, true, g.Verbose, &trades)
}
// GetHistoricRates returns historic rates for a product. Rates are returned in
@@ -229,7 +229,7 @@ func (g *GDAX) GetHistoricRates(currencyPair string, start, end, granularity int
fmt.Sprintf("%s/%s/%s", gdaxAPIURL+gdaxProducts, currencyPair, gdaxHistory),
values)
if err := common.SendHTTPGetRequest(path, true, &resp); err != nil {
if err := common.SendHTTPGetRequest(path, true, g.Verbose, &resp); err != nil {
return history, err
}
@@ -255,7 +255,7 @@ func (g *GDAX) GetStats(currencyPair string) (Stats, error) {
path := fmt.Sprintf(
"%s/%s/%s", gdaxAPIURL+gdaxProducts, currencyPair, gdaxStats)
return stats, common.SendHTTPGetRequest(path, true, &stats)
return stats, common.SendHTTPGetRequest(path, true, g.Verbose, &stats)
}
// GetCurrencies returns a list of supported currency on the exchange
@@ -264,7 +264,7 @@ func (g *GDAX) GetCurrencies() ([]Currency, error) {
currencies := []Currency{}
return currencies,
common.SendHTTPGetRequest(gdaxAPIURL+gdaxCurrencies, true, &currencies)
common.SendHTTPGetRequest(gdaxAPIURL+gdaxCurrencies, true, g.Verbose, &currencies)
}
// GetServerTime returns the API server time
@@ -272,7 +272,7 @@ func (g *GDAX) GetServerTime() (ServerTime, error) {
serverTime := ServerTime{}
return serverTime,
common.SendHTTPGetRequest(gdaxAPIURL+gdaxTime, true, &serverTime)
common.SendHTTPGetRequest(gdaxAPIURL+gdaxTime, true, g.Verbose, &serverTime)
}
// GetAccounts returns a list of trading accounts associated with the APIKEYS
@@ -772,7 +772,7 @@ func (g *GDAX) SendAuthenticatedHTTPRequest(method, path string, params map[stri
}
}
nonce := g.Nonce.Evaluate()
nonce := g.Nonce.GetValue(g.Name, false).String()
message := nonce + method + "/" + path + string(payload)
hmac := common.GetHMAC(common.HashSHA256, []byte(message), []byte(g.APISecret))
headers := make(map[string]string)

View File

@@ -160,7 +160,7 @@ func (g *Gemini) GetSymbols() ([]string, error) {
symbols := []string{}
path := fmt.Sprintf("%s/v%s/%s", geminiAPIURL, geminiAPIVersion, geminiSymbols)
return symbols, common.SendHTTPGetRequest(path, true, &symbols)
return symbols, common.SendHTTPGetRequest(path, true, g.Verbose, &symbols)
}
// GetTicker returns information about recent trading activity for the symbol
@@ -177,7 +177,7 @@ func (g *Gemini) GetTicker(currencyPair string) (Ticker, error) {
resp := TickerResponse{}
path := fmt.Sprintf("%s/v%s/%s/%s", geminiAPIURL, geminiAPIVersion, geminiTicker, currencyPair)
err := common.SendHTTPGetRequest(path, true, &resp)
err := common.SendHTTPGetRequest(path, true, g.Verbose, &resp)
if err != nil {
return ticker, err
}
@@ -204,7 +204,7 @@ func (g *Gemini) GetOrderbook(currencyPair string, params url.Values) (Orderbook
path := common.EncodeURLValues(fmt.Sprintf("%s/v%s/%s/%s", geminiAPIURL, geminiAPIVersion, geminiOrderbook, currencyPair), params)
orderbook := Orderbook{}
return orderbook, common.SendHTTPGetRequest(path, true, &orderbook)
return orderbook, common.SendHTTPGetRequest(path, true, g.Verbose, &orderbook)
}
// GetTrades eturn the trades that have executed since the specified timestamp.
@@ -220,7 +220,7 @@ func (g *Gemini) GetTrades(currencyPair string, params url.Values) ([]Trade, err
path := common.EncodeURLValues(fmt.Sprintf("%s/v%s/%s/%s", geminiAPIURL, geminiAPIVersion, geminiTrades, currencyPair), params)
trades := []Trade{}
return trades, common.SendHTTPGetRequest(path, true, &trades)
return trades, common.SendHTTPGetRequest(path, true, g.Verbose, &trades)
}
// GetAuction returns auction infomation
@@ -228,7 +228,7 @@ func (g *Gemini) GetAuction(currencyPair string) (Auction, error) {
path := fmt.Sprintf("%s/v%s/%s/%s", geminiAPIURL, geminiAPIVersion, geminiAuction, currencyPair)
auction := Auction{}
return auction, common.SendHTTPGetRequest(path, true, &auction)
return auction, common.SendHTTPGetRequest(path, true, g.Verbose, &auction)
}
// GetAuctionHistory returns the auction events, optionally including
@@ -246,7 +246,7 @@ func (g *Gemini) GetAuctionHistory(currencyPair string, params url.Values) ([]Au
path := common.EncodeURLValues(fmt.Sprintf("%s/v%s/%s/%s/%s", geminiAPIURL, geminiAPIVersion, geminiAuction, currencyPair, geminiAuctionHistory), params)
auctionHist := []AuctionHistory{}
return auctionHist, common.SendHTTPGetRequest(path, true, &auctionHist)
return auctionHist, common.SendHTTPGetRequest(path, true, g.Verbose, &auctionHist)
}
func (g *Gemini) isCorrectSession(role string) error {

View File

@@ -68,7 +68,7 @@ func (h *HUOBI) GetFee() float64 {
func (h *HUOBI) GetTicker(symbol string) (HuobiTicker, error) {
resp := HuobiTickerResponse{}
path := fmt.Sprintf("https://api.huobi.com/staticmarket/ticker_%s_json.js", symbol)
err := common.SendHTTPGetRequest(path, true, &resp)
err := common.SendHTTPGetRequest(path, true, h.Verbose, &resp)
if err != nil {
return HuobiTicker{}, err
@@ -79,7 +79,7 @@ func (h *HUOBI) GetTicker(symbol string) (HuobiTicker, error) {
func (h *HUOBI) GetOrderBook(symbol string) (HuobiOrderbook, error) {
path := fmt.Sprintf("https://api.huobi.com/staticmarket/depth_%s_json.js", symbol)
resp := HuobiOrderbook{}
err := common.SendHTTPGetRequest(path, true, &resp)
err := common.SendHTTPGetRequest(path, true, h.Verbose, &resp)
if err != nil {
return resp, err
}

View File

@@ -16,14 +16,26 @@ import (
)
const (
ITBIT_API_URL = "https://api.itbit.com/v1"
ITBIT_API_VERSION = "1"
itbitAPIURL = "https://api.itbit.com/v1"
itbitAPIVersion = "1"
itbitMarkets = "markets"
itbitOrderbook = "order_book"
itbitTicker = "ticker"
itbitWallets = "wallets"
itbitBalances = "balances"
itbitTrades = "trades"
itbitFundingHistory = "funding_history"
itbitOrders = "orders"
itbitCryptoDeposits = "cryptocurrency_deposits"
itbitWalletTransfer = "wallet_transfers"
)
// ItBit is the overarching type across the ItBit package
type ItBit struct {
exchange.Base
}
// SetDefaults sets the defaults for the exchange
func (i *ItBit) SetDefaults() {
i.Name = "ITBIT"
i.Enabled = false
@@ -39,6 +51,7 @@ func (i *ItBit) SetDefaults() {
i.AssetTypes = []string{ticker.Spot}
}
// Setup sets the exchange paramaters from exchange config
func (i *ItBit) Setup(exch config.ExchangeConfig) {
if !exch.Enabled {
i.SetEnabled(false)
@@ -63,6 +76,7 @@ func (i *ItBit) Setup(exch config.ExchangeConfig) {
}
}
// GetFee returns the maker or taker fee
func (i *ItBit) GetFee(maker bool) float64 {
if maker {
return i.MakerFee
@@ -70,98 +84,103 @@ func (i *ItBit) GetFee(maker bool) float64 {
return i.TakerFee
}
func (i *ItBit) GetTicker(currency string) (Ticker, error) {
path := ITBIT_API_URL + "/markets/" + currency + "/ticker"
var itbitTicker Ticker
err := common.SendHTTPGetRequest(path, true, &itbitTicker)
if err != nil {
return Ticker{}, err
}
return itbitTicker, nil
// GetTicker returns ticker info for a specified market.
// currencyPair - example "XBTUSD" "XBTSGD" "XBTEUR"
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)
}
func (i *ItBit) GetOrderbook(currency string) (OrderbookResponse, error) {
// GetOrderbook returns full order book for the specified market.
// currencyPair - example "XBTUSD" "XBTSGD" "XBTEUR"
func (i *ItBit) GetOrderbook(currencyPair string) (OrderbookResponse, error) {
response := OrderbookResponse{}
path := ITBIT_API_URL + "/markets/" + currency + "/order_book"
err := common.SendHTTPGetRequest(path, true, &response)
if err != nil {
return OrderbookResponse{}, err
}
return response, nil
path := fmt.Sprintf("%s/%s/%s/%s", itbitAPIURL, itbitMarkets, currencyPair, itbitOrderbook)
return response,
common.SendHTTPGetRequest(path, true, i.Verbose, &response)
}
func (i *ItBit) GetTradeHistory(currency, timestamp string) bool {
req := "/trades?since=" + timestamp
err := common.SendHTTPGetRequest(ITBIT_API_URL+"markets/"+currency+req, true, nil)
if err != nil {
log.Println(err)
return false
}
return true
// GetTradeHistory returns recent trades for a specified market.
//
// currencyPair - example "XBTUSD" "XBTSGD" "XBTEUR"
// timestamp - matchNumber, only executions after this will be returned
func (i *ItBit) GetTradeHistory(currencyPair, timestamp string) (Trades, error) {
response := Trades{}
req := "trades?since=" + timestamp
path := fmt.Sprintf("%s/%s/%s/%s", itbitAPIURL, itbitMarkets, currencyPair, req)
return response,
common.SendHTTPGetRequest(path, true, i.Verbose, &response)
}
func (i *ItBit) GetWallets(params url.Values) {
// GetWallets returns information about all wallets associated with the account.
//
// params --
// page - [optional] page to return example 1. default 1
// perPage - [optional] items per page example 50, default 50 max 50
func (i *ItBit) GetWallets(params url.Values) ([]Wallet, error) {
resp := []Wallet{}
params.Set("userId", i.ClientID)
path := "/wallets?" + params.Encode()
path := fmt.Sprintf("/%s?%s", itbitWallets, params.Encode())
err := i.SendAuthenticatedHTTPRequest("GET", path, nil)
if err != nil {
log.Println(err)
}
return resp, i.SendAuthenticatedHTTPRequest("GET", path, nil, &resp)
}
func (i *ItBit) CreateWallet(walletName string) {
path := "/wallets"
// CreateWallet creates a new wallet with a specified name.
func (i *ItBit) CreateWallet(walletName string) (Wallet, error) {
resp := Wallet{}
params := make(map[string]interface{})
params["userId"] = i.ClientID
params["name"] = walletName
err := i.SendAuthenticatedHTTPRequest("POST", path, params)
if err != nil {
log.Println(err)
}
return resp,
i.SendAuthenticatedHTTPRequest("POST", "/"+itbitWallets, params, &resp)
}
func (i *ItBit) GetWallet(walletID string) {
path := "/wallets/" + walletID
err := i.SendAuthenticatedHTTPRequest("GET", path, nil)
// GetWallet returns wallet information by walletID
func (i *ItBit) GetWallet(walletID string) (Wallet, error) {
resp := Wallet{}
path := fmt.Sprintf("/%s/%s", itbitWallets, walletID)
if err != nil {
log.Println(err)
}
return resp, i.SendAuthenticatedHTTPRequest("GET", path, nil, &resp)
}
func (i *ItBit) GetWalletBalance(walletID, currency string) {
path := "/wallets/ " + walletID + "/balances/" + currency
err := i.SendAuthenticatedHTTPRequest("GET", path, nil)
// GetWalletBalance returns balance information for a specific currency in a
// wallet.
func (i *ItBit) GetWalletBalance(walletID, currency string) (Balance, error) {
resp := Balance{}
path := fmt.Sprintf("/%s/%s/%s/%s", itbitWallets, walletID, itbitBalances, currency)
if err != nil {
log.Println(err)
}
return resp, i.SendAuthenticatedHTTPRequest("GET", path, nil, &resp)
}
func (i *ItBit) GetWalletTrades(walletID string, params url.Values) {
path := common.EncodeURLValues("/wallets/"+walletID+"/trades", params)
err := i.SendAuthenticatedHTTPRequest("GET", path, nil)
// GetWalletTrades returns all trades for a specified wallet.
func (i *ItBit) GetWalletTrades(walletID string, params url.Values) (Records, error) {
resp := Records{}
url := fmt.Sprintf("/%s/%s/%s", itbitWallets, walletID, itbitTrades)
path := common.EncodeURLValues(url, params)
if err != nil {
log.Println(err)
}
return resp, i.SendAuthenticatedHTTPRequest("GET", path, nil, &resp)
}
func (i *ItBit) GetWalletOrders(walletID string, params url.Values) {
path := common.EncodeURLValues("/wallets/"+walletID+"/orders", params)
err := i.SendAuthenticatedHTTPRequest("GET", path, nil)
// GetFundingHistory returns all funding history for a specified wallet.
func (i *ItBit) GetFundingHistory(walletID string, params url.Values) (FundingRecords, error) {
resp := FundingRecords{}
url := fmt.Sprintf("/%s/%s/%s", itbitWallets, walletID, itbitFundingHistory)
path := common.EncodeURLValues(url, params)
if err != nil {
log.Println(err)
}
return resp, i.SendAuthenticatedHTTPRequest("GET", path, nil, &resp)
}
func (i *ItBit) PlaceWalletOrder(walletID, side, orderType, currency string, amount, price float64, instrument string, clientRef string) {
path := "/wallets/" + walletID + "/orders"
// PlaceOrder places a new order
func (i *ItBit) PlaceOrder(walletID, side, orderType, currency string, amount, price float64, instrument, clientRef string) (Order, error) {
resp := Order{}
path := fmt.Sprintf("/%s/%s/%s", itbitWallets, walletID, itbitOrders)
params := make(map[string]interface{})
params["side"] = side
params["type"] = orderType
@@ -174,85 +193,58 @@ func (i *ItBit) PlaceWalletOrder(walletID, side, orderType, currency string, amo
params["clientOrderIdentifier"] = clientRef
}
err := i.SendAuthenticatedHTTPRequest("POST", path, params)
if err != nil {
log.Println(err)
}
return resp, i.SendAuthenticatedHTTPRequest("POST", path, params, &resp)
}
func (i *ItBit) GetWalletOrder(walletID, orderID string) {
path := "/wallets/" + walletID + "/orders/" + orderID
err := i.SendAuthenticatedHTTPRequest("GET", path, nil)
// GetOrder returns an order by id.
func (i *ItBit) GetOrder(walletID string, params url.Values) (Order, error) {
resp := Order{}
url := fmt.Sprintf("/%s/%s/%s", itbitWallets, walletID, itbitOrders)
path := common.EncodeURLValues(url, params)
if err != nil {
log.Println(err)
}
return resp, i.SendAuthenticatedHTTPRequest("GET", path, nil, &resp)
}
func (i *ItBit) CancelWalletOrder(walletID, orderID string) {
path := "/wallets/" + walletID + "/orders/" + orderID
err := i.SendAuthenticatedHTTPRequest("DELETE", path, nil)
// CancelOrder cancels and open order. *This is not a guarantee that the order
// has been cancelled!*
func (i *ItBit) CancelOrder(walletID, orderID string) error {
path := fmt.Sprintf("/%s/%s/%s/%s", itbitWallets, walletID, itbitOrders, orderID)
if err != nil {
log.Println(err)
}
return i.SendAuthenticatedHTTPRequest("DELETE", path, nil, nil)
}
func (i *ItBit) PlaceWithdrawalRequest(walletID, currency, address string, amount float64) {
path := "/wallets/" + walletID + "/cryptocurrency_withdrawals"
params := make(map[string]interface{})
params["currency"] = currency
params["amount"] = amount
params["address"] = address
err := i.SendAuthenticatedHTTPRequest("POST", path, params)
if err != nil {
log.Println(err)
}
}
func (i *ItBit) GetDepositAddress(walletID, currency string) {
path := "/wallets/" + walletID + "/cryptocurrency_deposits"
// GetDepositAddress returns a deposit address to send cryptocurrency to.
func (i *ItBit) GetDepositAddress(walletID, currency string) (CryptoCurrencyDeposit, error) {
resp := CryptoCurrencyDeposit{}
path := fmt.Sprintf("/%s/%s/%s", itbitWallets, walletID, itbitCryptoDeposits)
params := make(map[string]interface{})
params["currency"] = currency
err := i.SendAuthenticatedHTTPRequest("POST", path, params)
if err != nil {
log.Println(err)
}
return resp, i.SendAuthenticatedHTTPRequest("POST", path, params, &resp)
}
func (i *ItBit) WalletTransfer(walletID, sourceWallet, destWallet string, amount float64, currency string) {
path := "/wallets/" + walletID + "/wallet_transfers"
// WalletTransfer transfers funds between wallets.
func (i *ItBit) WalletTransfer(walletID, sourceWallet, destWallet string, amount float64, currency string) (WalletTransfer, error) {
resp := WalletTransfer{}
path := fmt.Sprintf("/%s/%s/%s", itbitWallets, walletID, itbitWalletTransfer)
params := make(map[string]interface{})
params["sourceWalletId"] = sourceWallet
params["destinationWalletId"] = destWallet
params["amount"] = strconv.FormatFloat(amount, 'f', -1, 64)
params["currencyCode"] = currency
err := i.SendAuthenticatedHTTPRequest("POST", path, params)
if err != nil {
log.Println(err)
}
return resp, i.SendAuthenticatedHTTPRequest("POST", path, params, &resp)
}
func (i *ItBit) SendAuthenticatedHTTPRequest(method string, path string, params map[string]interface{}) (err error) {
// SendAuthenticatedHTTPRequest sends an authenticated request to itBit
func (i *ItBit) SendAuthenticatedHTTPRequest(method string, path string, params map[string]interface{}, result interface{}) error {
if !i.AuthenticatedAPISupport {
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, i.Name)
}
if i.Nonce.Get() == 0 {
i.Nonce.Set(time.Now().UnixNano())
} else {
i.Nonce.Inc()
}
request := make(map[string]interface{})
url := ITBIT_API_URL + path
url := itbitAPIURL + path
if params != nil {
for key, value := range params {
@@ -261,12 +253,13 @@ func (i *ItBit) SendAuthenticatedHTTPRequest(method string, path string, params
}
PayloadJSON := []byte("")
var err error
if params != nil {
PayloadJSON, err = common.JSONEncode(request)
PayloadJSON, err = common.JSONEncode(request)
if err != nil {
return errors.New("SendAuthenticatedHTTPRequest: Unable to JSON Marshal request")
return err
}
if i.Verbose {
@@ -274,26 +267,37 @@ func (i *ItBit) SendAuthenticatedHTTPRequest(method string, path string, params
}
}
message, err := common.JSONEncode([]string{method, url, string(PayloadJSON), i.Nonce.String(), i.Nonce.String()[0:13]})
nonce := i.Nonce.GetValue(i.Name, false).String()
timestamp := strconv.FormatInt(time.Now().UnixNano()/1000000, 10)
message, err := common.JSONEncode([]string{method, url, string(PayloadJSON), nonce, timestamp})
if err != nil {
log.Println(err)
return
return err
}
hash := common.GetSHA256([]byte(i.Nonce.String() + string(message)))
hash := common.GetSHA256([]byte(nonce + string(message)))
hmac := common.GetHMAC(common.HashSHA512, []byte(url+string(hash)), []byte(i.APISecret))
signature := common.Base64Encode(hmac)
headers := make(map[string]string)
headers["Authorization"] = i.ClientID + ":" + signature
headers["X-Auth-Timestamp"] = i.Nonce.String()[0:13]
headers["X-Auth-Nonce"] = i.Nonce.String()
headers["X-Auth-Timestamp"] = timestamp
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)
}
return nil
errCapture := GeneralReturn{}
if err := common.JSONDecode([]byte(resp), &errCapture); err == nil {
return errors.New(errCapture.Description)
}
return common.JSONDecode([]byte(resp), result)
}

View File

@@ -0,0 +1,145 @@
package itbit
import (
"net/url"
"testing"
"github.com/thrasher-/gocryptotrader/config"
)
var i ItBit
// Please provide your own keys to do proper testing
const (
apiKey = ""
apiSecret = ""
clientID = ""
)
func TestSetDefaults(t *testing.T) {
i.SetDefaults()
}
func TestSetup(t *testing.T) {
cfg := config.GetConfig()
cfg.LoadConfig("../../testdata/configtest.dat")
itbitConfig, err := cfg.GetExchangeConfig("ITBIT")
if err != nil {
t.Error("Test Failed - Gemini Setup() init error")
}
itbitConfig.AuthenticatedAPISupport = true
itbitConfig.APIKey = apiKey
itbitConfig.APISecret = apiSecret
itbitConfig.ClientID = clientID
i.Setup(itbitConfig)
}
func TestGetFee(t *testing.T) {
t.Parallel()
if i.GetFee(true) != -0.1 || i.GetFee(false) != 0.5 {
t.Error("Test Failed - GetFee() error")
}
}
func TestGetTicker(t *testing.T) {
t.Parallel()
_, err := i.GetTicker("XBTUSD")
if err != nil {
t.Error("Test Failed - GetTicker() error", err)
}
}
func TestGetOrderbook(t *testing.T) {
t.Parallel()
_, err := i.GetOrderbook("XBTSGD")
if err != nil {
t.Error("Test Failed - GetOrderbook() error", err)
}
}
func TestGetTradeHistory(t *testing.T) {
t.Parallel()
_, err := i.GetTradeHistory("XBTUSD", "0")
if err != nil {
t.Error("Test Failed - GetTradeHistory() error", err)
}
}
func TestGetWallets(t *testing.T) {
_, err := i.GetWallets(url.Values{})
if err == nil {
t.Error("Test Failed - GetWallets() error", err)
}
}
func TestCreateWallet(t *testing.T) {
_, err := i.CreateWallet("test")
if err == nil {
t.Error("Test Failed - CreateWallet() error", err)
}
}
func TestGetWallet(t *testing.T) {
_, err := i.GetWallet("1337")
if err == nil {
t.Error("Test Failed - GetWallet() error", err)
}
}
func TestGetWalletBalance(t *testing.T) {
_, err := i.GetWalletBalance("1337", "XRT")
if err == nil {
t.Error("Test Failed - GetWalletBalance() error", err)
}
}
func TestGetWalletTrades(t *testing.T) {
_, err := i.GetWalletTrades("1337", url.Values{})
if err == nil {
t.Error("Test Failed - GetWalletTrades() error", err)
}
}
func TestGetFundingHistory(t *testing.T) {
_, err := i.GetFundingHistory("1337", url.Values{})
if err == nil {
t.Error("Test Failed - GetFundingHistory() error", err)
}
}
func TestPlaceOrder(t *testing.T) {
_, err := i.PlaceOrder("1337", "buy", "limit", "USD", 1, 0.2, "banjo", "sauce")
if err == nil {
t.Error("Test Failed - PlaceOrder() error", err)
}
}
func TestGetOrder(t *testing.T) {
_, err := i.GetOrder("1337", url.Values{})
if err == nil {
t.Error("Test Failed - GetOrder() error", err)
}
}
func TestCancelOrder(t *testing.T) {
err := i.CancelOrder("1337", "1337order")
if err == nil {
t.Error("Test Failed - CancelOrder() error", err)
}
}
func TestGetDepositAddress(t *testing.T) {
_, err := i.GetDepositAddress("1337", "AUD")
if err == nil {
t.Error("Test Failed - GetDepositAddress() error", err)
}
}
func TestWalletTransfer(t *testing.T) {
_, err := i.WalletTransfer("1337", "mywallet", "anotherwallet", 200, "USD")
if err == nil {
t.Error("Test Failed - WalletTransfer() error", err)
}
}

View File

@@ -1,26 +1,145 @@
package itbit
type Ticker struct {
Pair string
Bid float64 `json:",string"`
BidAmt float64 `json:",string"`
Ask float64 `json:",string"`
AskAmt float64 `json:",string"`
LastPrice float64 `json:",string"`
LastAmt float64 `json:",string"`
Volume24h float64 `json:",string"`
VolumeToday float64 `json:",string"`
High24h float64 `json:",string"`
Low24h float64 `json:",string"`
HighToday float64 `json:",string"`
LowToday float64 `json:",string"`
OpenToday float64 `json:",string"`
VwapToday float64 `json:",string"`
Vwap24h float64 `json:",string"`
ServertimeUTC string
// GeneralReturn is a generalized return type to capture any errors
type GeneralReturn struct {
Code int `json:"code"`
Description string `json:"description"`
RequestID string `json:"requestId"`
}
// Ticker holds returned ticker information
type Ticker struct {
Pair string `json:"pair"`
Bid float64 `json:"bid,string"`
BidAmt float64 `json:"bidAmt,string"`
Ask float64 `json:"ask,string"`
AskAmt float64 `json:"askAmt,string"`
LastPrice float64 `json:"lastPrice,string"`
LastAmt float64 `json:"lastAmt,string"`
Volume24h float64 `json:"volume24h,string"`
VolumeToday float64 `json:"volumeToday,string"`
High24h float64 `json:"high24h,string"`
Low24h float64 `json:"low24h,string"`
HighToday float64 `json:"highToday,string"`
LowToday float64 `json:"lowToday,string"`
OpenToday float64 `json:"openToday,string"`
VwapToday float64 `json:"vwapToday,string"`
Vwap24h float64 `json:"vwap24h,string"`
ServertimeUTC string `json:"serverTimeUTC"`
}
// OrderbookResponse contains multi-arrayed strings of bid and ask side
// information
type OrderbookResponse struct {
Bids [][]string `json:"bids"`
Asks [][]string `json:"asks"`
}
// Trades holds recent trades with associated information
type Trades struct {
RecentTrades []struct {
Timestamp string `json:"timestamp"`
MatchNumber int64 `json:"matchNumber"`
Price float64 `json:"price,string"`
Amount float64 `json:"amount,string"`
} `json:"recentTrades"`
}
// Wallet contains specific wallet information
type Wallet struct {
ID string `json:"id"`
UserID string `json:"userId"`
Name string `json:"name"`
Balances []Balance `json:"balances"`
}
// Balance is a sub type holding balance information
type Balance struct {
Currency string `json:"currency"`
AvailableBalance float64 `json:"availableBalance,string"`
TotalBalance float64 `json:"totalBalance,string"`
}
// Records embodies records of trade history information
type Records struct {
TotalNumberOfRecords int `json:"totalNumberOfRecords,string"`
CurrentPageNumber int `json:"currentPageNumber,string"`
LatestExecutedID int64 `json:"latestExecutionId,string"`
RecordsPerPage int `json:"recordsPerPage,string"`
TradingHistory []TradeHistory `json:"tradingHistory"`
}
// TradeHistory stores historic trade values
type TradeHistory struct {
OrderID string `json:"orderId"`
Timestamp string `json:"timestamp"`
Instrument string `json:"instrument"`
Direction string `json:"direction"`
CurrencyOne string `json:"currency1"`
CurrencyOneAmount float64 `json:"currency1Amount,string"`
CurrencyTwo string `json:"currency2"`
CurrencyTwoAmount float64 `json:"currency2Amount"`
Rate float64 `json:"rate,string"`
CommissionPaid float64 `json:"commissionPaid,string"`
CommissionCurrency string `json:"commissionCurrency"`
RebatesApplied float64 `json:"rebatesApplied,string"`
RebateCurrency string `json:"rebateCurrency"`
}
// FundingRecords embodies records of fund history information
type FundingRecords struct {
TotalNumberOfRecords int `json:"totalNumberOfRecords,string"`
CurrentPageNumber int `json:"currentPageNumber,string"`
LatestExecutedID int64 `json:"latestExecutionId,string"`
RecordsPerPage int `json:"recordsPerPage,string"`
FundingHistory []FundHistory `json:"fundingHistory"`
}
// FundHistory stores historic funding transactions
type FundHistory struct {
BankName string `json:"bankName"`
WithdrawalID int64 `json:"withdrawalId"`
HoldingPeriodCompletionDate string `json:"holdingPeriodCompletionDate"`
DestinationAddress string `json:"destinationAddress"`
TxnHash string `json:"txnHash"`
Time string `json:"time"`
Currency string `json:"currency"`
TransactionType string `json:"transactionType"`
Amount float64 `json:"amount,string"`
WalletName string `json:"walletName"`
Status string `json:"status"`
}
// Order holds order information
type Order struct {
ID string `json:"id"`
WalletID string `json:"walletId"`
Side string `json:"side"`
Instrument string `json:"instrument"`
Type string `json:"type"`
Currency string `json:"currency"`
Amount float64 `json:"amount,string"`
Price float64 `json:"price,string"`
AmountFilled float64 `json:"amountFilled,string"`
VolumeWeightedAveragePrice float64 `json:"volumeWeightedAveragePrice,string"`
CreatedTime string `json:"createdTime"`
Status string `json:"Status"`
Metadata interface{} `json:"metadata"`
ClientOrderIdentifier string `json:"clientOrderIdentifier"`
}
// CryptoCurrencyDeposit holds information about a new wallet
type CryptoCurrencyDeposit struct {
ID int `json:"id"`
WalletID string `json:"walletID"`
DepositAddress string `json:"depositAddress"`
Metadata interface{} `json:"metadata"`
}
// WalletTransfer holds wallet transfer information
type WalletTransfer struct {
SourceWalletID string `json:"sourceWalletId"`
DestinationWalletID string `json:"destinationWalletId"`
Amount float64 `json:"amount,string"`
CurrencyCode string `json:"currencyCode"`
}

View File

@@ -99,7 +99,7 @@ func (k *Kraken) GetFee(cryptoTrade bool) float64 {
func (k *Kraken) GetServerTime() error {
var result interface{}
path := fmt.Sprintf("%s/%s/public/%s", KRAKEN_API_URL, KRAKEN_API_VERSION, KRAKEN_SERVER_TIME)
err := common.SendHTTPGetRequest(path, true, &result)
err := common.SendHTTPGetRequest(path, true, k.Verbose, &result)
if err != nil {
return err
@@ -112,7 +112,7 @@ func (k *Kraken) GetServerTime() error {
func (k *Kraken) GetAssets() error {
var result interface{}
path := fmt.Sprintf("%s/%s/public/%s", KRAKEN_API_URL, KRAKEN_API_VERSION, KRAKEN_ASSETS)
err := common.SendHTTPGetRequest(path, true, &result)
err := common.SendHTTPGetRequest(path, true, k.Verbose, &result)
if err != nil {
return err
@@ -130,7 +130,7 @@ func (k *Kraken) GetAssetPairs() (map[string]KrakenAssetPairs, error) {
response := Response{}
path := fmt.Sprintf("%s/%s/public/%s", KRAKEN_API_URL, KRAKEN_API_VERSION, KRAKEN_ASSET_PAIRS)
err := common.SendHTTPGetRequest(path, true, &response)
err := common.SendHTTPGetRequest(path, true, k.Verbose, &response)
if err != nil {
return nil, err
@@ -150,7 +150,7 @@ func (k *Kraken) GetTicker(symbol string) error {
resp := Response{}
path := fmt.Sprintf("%s/%s/public/%s?%s", KRAKEN_API_URL, KRAKEN_API_VERSION, KRAKEN_TICKER, values.Encode())
err := common.SendHTTPGetRequest(path, true, &resp)
err := common.SendHTTPGetRequest(path, true, k.Verbose, &resp)
if err != nil {
return err
@@ -183,7 +183,7 @@ func (k *Kraken) GetOHLC(symbol string) error {
var result interface{}
path := fmt.Sprintf("%s/%s/public/%s?%s", KRAKEN_API_URL, KRAKEN_API_VERSION, KRAKEN_OHLC, values.Encode())
err := common.SendHTTPGetRequest(path, true, &result)
err := common.SendHTTPGetRequest(path, true, k.Verbose, &result)
if err != nil {
return err
@@ -201,7 +201,7 @@ func (k *Kraken) GetDepth(symbol string) (Orderbook, error) {
var result interface{}
var ob Orderbook
path := fmt.Sprintf("%s/%s/public/%s?%s", KRAKEN_API_URL, KRAKEN_API_VERSION, KRAKEN_DEPTH, values.Encode())
err := common.SendHTTPGetRequest(path, true, &result)
err := common.SendHTTPGetRequest(path, true, k.Verbose, &result)
if err != nil {
return ob, err
@@ -257,7 +257,7 @@ func (k *Kraken) GetTrades(symbol string) error {
var result interface{}
path := fmt.Sprintf("%s/%s/public/%s?%s", KRAKEN_API_URL, KRAKEN_API_VERSION, KRAKEN_TRADES, values.Encode())
err := common.SendHTTPGetRequest(path, true, &result)
err := common.SendHTTPGetRequest(path, true, k.Verbose, &result)
if err != nil {
return err
@@ -273,7 +273,7 @@ func (k *Kraken) GetSpread(symbol string) {
var result interface{}
path := fmt.Sprintf("%s/%s/public/%s?%s", KRAKEN_API_URL, KRAKEN_API_VERSION, KRAKEN_SPREAD, values.Encode())
err := common.SendHTTPGetRequest(path, true, &result)
err := common.SendHTTPGetRequest(path, true, k.Verbose, &result)
if err != nil {
log.Println(err)

View File

@@ -85,7 +85,7 @@ func (l *LakeBTC) GetFee(maker bool) float64 {
func (l *LakeBTC) GetTicker() (map[string]LakeBTCTicker, error) {
response := make(map[string]LakeBTCTickerResponse)
path := fmt.Sprintf("%s/%s", LAKEBTC_API_URL, LAKEBTC_TICKER)
err := common.SendHTTPGetRequest(path, true, &response)
err := common.SendHTTPGetRequest(path, true, l.Verbose, &response)
if err != nil {
return nil, err
}
@@ -126,7 +126,7 @@ func (l *LakeBTC) GetOrderBook(currency string) (LakeBTCOrderbook, error) {
}
path := fmt.Sprintf("%s/%s?symbol=%s", LAKEBTC_API_URL, LAKEBTC_ORDERBOOK, common.StringToLower(currency))
resp := Response{}
err := common.SendHTTPGetRequest(path, true, &resp)
err := common.SendHTTPGetRequest(path, true, l.Verbose, &resp)
if err != nil {
return LakeBTCOrderbook{}, err
}
@@ -165,7 +165,7 @@ func (l *LakeBTC) GetOrderBook(currency string) (LakeBTCOrderbook, error) {
func (l *LakeBTC) GetTradeHistory(currency string) ([]LakeBTCTradeHistory, error) {
path := fmt.Sprintf("%s/%s?symbol=%s", LAKEBTC_API_URL, LAKEBTC_TRADES, common.StringToLower(currency))
resp := []LakeBTCTradeHistory{}
err := common.SendHTTPGetRequest(path, true, &resp)
err := common.SendHTTPGetRequest(path, true, l.Verbose, &resp)
if err != nil {
return nil, err
}

View File

@@ -102,7 +102,7 @@ func (l *Liqui) GetAvailablePairs(nonHidden bool) []string {
func (l *Liqui) GetInfo() (LiquiInfo, error) {
req := fmt.Sprintf("%s/%s/%s/", LIQUI_API_PUBLIC_URL, LIQUI_API_PUBLIC_VERSION, LIQUI_INFO)
resp := LiquiInfo{}
err := common.SendHTTPGetRequest(req, true, &resp)
err := common.SendHTTPGetRequest(req, true, l.Verbose, &resp)
if err != nil {
return resp, err
@@ -118,7 +118,7 @@ func (l *Liqui) GetTicker(symbol string) (map[string]LiquiTicker, error) {
response := Response{}
req := fmt.Sprintf("%s/%s/%s/%s", LIQUI_API_PUBLIC_URL, LIQUI_API_PUBLIC_VERSION, LIQUI_TICKER, symbol)
err := common.SendHTTPGetRequest(req, true, &response.Data)
err := common.SendHTTPGetRequest(req, true, l.Verbose, &response.Data)
if err != nil {
return nil, err
@@ -134,7 +134,7 @@ func (l *Liqui) GetDepth(symbol string) (LiquiOrderbook, error) {
response := Response{}
req := fmt.Sprintf("%s/%s/%s/%s", LIQUI_API_PUBLIC_URL, LIQUI_API_PUBLIC_VERSION, LIQUI_DEPTH, symbol)
err := common.SendHTTPGetRequest(req, true, &response.Data)
err := common.SendHTTPGetRequest(req, true, l.Verbose, &response.Data)
if err != nil {
return LiquiOrderbook{}, err
}
@@ -151,7 +151,7 @@ func (l *Liqui) GetTrades(symbol string) ([]LiquiTrades, error) {
response := Response{}
req := fmt.Sprintf("%s/%s/%s/%s", LIQUI_API_PUBLIC_URL, LIQUI_API_PUBLIC_VERSION, LIQUI_TRADES, symbol)
err := common.SendHTTPGetRequest(req, true, &response.Data)
err := common.SendHTTPGetRequest(req, true, l.Verbose, &response.Data)
if err != nil {
return []LiquiTrades{}, err
}

View File

@@ -80,7 +80,7 @@ func (l *LocalBitcoins) GetFee(maker bool) float64 {
func (l *LocalBitcoins) GetTicker() (map[string]LocalBitcoinsTicker, error) {
result := make(map[string]LocalBitcoinsTicker)
err := common.SendHTTPGetRequest(LOCALBITCOINS_API_URL+LOCALBITCOINS_API_TICKER, true, &result)
err := common.SendHTTPGetRequest(LOCALBITCOINS_API_URL+LOCALBITCOINS_API_TICKER, true, l.Verbose, &result)
if err != nil {
return result, err
@@ -92,7 +92,7 @@ func (l *LocalBitcoins) GetTicker() (map[string]LocalBitcoinsTicker, error) {
func (l *LocalBitcoins) GetTrades(currency string, values url.Values) ([]LocalBitcoinsTrade, error) {
path := common.EncodeURLValues(fmt.Sprintf("%s/%s/trades.json", LOCALBITCOINS_API_URL+LOCALBITCOINS_API_BITCOINCHARTS, currency), values)
result := []LocalBitcoinsTrade{}
err := common.SendHTTPGetRequest(path, true, &result)
err := common.SendHTTPGetRequest(path, true, l.Verbose, &result)
if err != nil {
return result, err
@@ -109,7 +109,7 @@ func (l *LocalBitcoins) GetOrderbook(currency string) (LocalBitcoinsOrderbook, e
path := fmt.Sprintf("%s/%s/orderbook.json", LOCALBITCOINS_API_URL+LOCALBITCOINS_API_BITCOINCHARTS, currency)
resp := response{}
err := common.SendHTTPGetRequest(path, true, &resp)
err := common.SendHTTPGetRequest(path, true, l.Verbose, &resp)
if err != nil {
return LocalBitcoinsOrderbook{}, err
@@ -162,7 +162,7 @@ func (l *LocalBitcoins) GetAccountInfo(username string, self bool) (LocalBitcoin
}
} else {
path := fmt.Sprintf("%s/api/account_info/%s/", LOCALBITCOINS_API_URL, username)
err := common.SendHTTPGetRequest(path, true, &resp)
err := common.SendHTTPGetRequest(path, true, l.Verbose, &resp)
if err != nil {
return resp.Data, err

View File

@@ -8,8 +8,12 @@ import (
// Nonce struct holds the nonce value
type Nonce struct {
// Standard nonce
n int64
mtx sync.Mutex
// Hash table exclusive exchange specific nonce values
boundedCall map[string]int64
boundedMtx sync.Mutex
}
// Inc increments the nonce value
@@ -49,14 +53,32 @@ func (n *Nonce) String() string {
return result
}
// Evaluate returns a nonce while evaluating in a single locked call
func (n *Nonce) Evaluate() string {
n.mtx.Lock()
defer n.mtx.Unlock()
if n.n == 0 {
n.n = time.Now().Unix()
return strconv.FormatInt(n.n, 10)
// Value is a return type for GetValue
type Value int64
// GetValue returns a nonce value and can be set as a higher precision. Values
// stored in an exchange specific hash table using a single locked call.
func (n *Nonce) GetValue(exchName string, nanoPrecision bool) Value {
n.boundedMtx.Lock()
defer n.boundedMtx.Unlock()
if n.boundedCall == nil {
n.boundedCall = make(map[string]int64)
}
n.n = n.n + 1
return strconv.FormatInt(n.n, 10)
if n.boundedCall[exchName] == 0 {
if nanoPrecision {
n.boundedCall[exchName] = time.Now().UnixNano()
return Value(n.boundedCall[exchName])
}
n.boundedCall[exchName] = time.Now().Unix()
return Value(n.boundedCall[exchName])
}
n.boundedCall[exchName]++
return Value(n.boundedCall[exchName])
}
// String is a Value method that changes format to a string
func (v Value) String() string {
return strconv.FormatInt(int64(v), 10)
}

View File

@@ -1,6 +1,7 @@
package nonce
import (
"strconv"
"testing"
"time"
)
@@ -56,6 +57,16 @@ func TestString(t *testing.T) {
}
}
func TestGetValue(t *testing.T) {
var nonce Nonce
timeNowNano := strconv.FormatInt(time.Now().UnixNano(), 10)
nValue := nonce.GetValue("dingdong", true).String()
if timeNowNano == nValue {
t.Error("Test failed - GetValue() error, incorrect values")
}
}
func TestNonceConcurrency(t *testing.T) {
var nonce Nonce
nonce.Set(12312)

View File

@@ -152,7 +152,7 @@ func (o *OKCoin) GetTicker(symbol string) (OKCoinTicker, error) {
vals := url.Values{}
vals.Set("symbol", symbol)
path := common.EncodeURLValues(o.APIUrl+OKCOIN_TICKER, vals)
err := common.SendHTTPGetRequest(path, true, &resp)
err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp)
if err != nil {
return OKCoinTicker{}, err
}
@@ -171,7 +171,7 @@ func (o *OKCoin) GetOrderBook(symbol string, size int64, merge bool) (OKCoinOrde
}
path := common.EncodeURLValues(o.APIUrl+OKCOIN_DEPTH, vals)
err := common.SendHTTPGetRequest(path, true, &resp)
err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp)
if err != nil {
return resp, err
}
@@ -187,7 +187,7 @@ func (o *OKCoin) GetTrades(symbol string, since int64) ([]OKCoinTrades, error) {
}
path := common.EncodeURLValues(o.APIUrl+OKCOIN_TRADES, vals)
err := common.SendHTTPGetRequest(path, true, &result)
err := common.SendHTTPGetRequest(path, true, o.Verbose, &result)
if err != nil {
return nil, err
}
@@ -209,7 +209,7 @@ func (o *OKCoin) GetKline(symbol, klineType string, size, since int64) ([]interf
}
path := common.EncodeURLValues(o.APIUrl+OKCOIN_KLINE, vals)
err := common.SendHTTPGetRequest(path, true, &resp)
err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp)
if err != nil {
return nil, err
}
@@ -223,7 +223,7 @@ func (o *OKCoin) GetFuturesTicker(symbol, contractType string) (OKCoinFuturesTic
vals.Set("symbol", symbol)
vals.Set("contract_type", contractType)
path := common.EncodeURLValues(o.APIUrl+OKCOIN_FUTURES_TICKER, vals)
err := common.SendHTTPGetRequest(path, true, &resp)
err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp)
if err != nil {
return OKCoinFuturesTicker{}, err
}
@@ -244,7 +244,7 @@ func (o *OKCoin) GetFuturesDepth(symbol, contractType string, size int64, merge
}
path := common.EncodeURLValues(o.APIUrl+OKCOIN_FUTURES_DEPTH, vals)
err := common.SendHTTPGetRequest(path, true, &result)
err := common.SendHTTPGetRequest(path, true, o.Verbose, &result)
if err != nil {
return result, err
}
@@ -258,7 +258,7 @@ func (o *OKCoin) GetFuturesTrades(symbol, contractType string) ([]OKCoinFuturesT
vals.Set("contract_type", contractType)
path := common.EncodeURLValues(o.APIUrl+OKCOIN_FUTURES_TRADES, vals)
err := common.SendHTTPGetRequest(path, true, &result)
err := common.SendHTTPGetRequest(path, true, o.Verbose, &result)
if err != nil {
return nil, err
}
@@ -275,7 +275,7 @@ func (o *OKCoin) GetFuturesIndex(symbol string) (float64, error) {
vals.Set("symbol", symbol)
path := common.EncodeURLValues(o.APIUrl+OKCOIN_FUTURES_INDEX, vals)
err := common.SendHTTPGetRequest(path, true, &result)
err := common.SendHTTPGetRequest(path, true, o.Verbose, &result)
if err != nil {
return 0, err
}
@@ -288,7 +288,7 @@ func (o *OKCoin) GetFuturesExchangeRate() (float64, error) {
}
result := Response{}
err := common.SendHTTPGetRequest(o.APIUrl+OKCOIN_EXCHANGE_RATE, true, &result)
err := common.SendHTTPGetRequest(o.APIUrl+OKCOIN_EXCHANGE_RATE, true, o.Verbose, &result)
if err != nil {
return result.Rate, err
}
@@ -304,7 +304,7 @@ func (o *OKCoin) GetFuturesEstimatedPrice(symbol string) (float64, error) {
vals := url.Values{}
vals.Set("symbol", symbol)
path := common.EncodeURLValues(o.APIUrl+OKCOIN_FUTURES_ESTIMATED_PRICE, vals)
err := common.SendHTTPGetRequest(path, true, &result)
err := common.SendHTTPGetRequest(path, true, o.Verbose, &result)
if err != nil {
return result.Price, err
}
@@ -326,7 +326,7 @@ func (o *OKCoin) GetFuturesKline(symbol, klineType, contractType string, size, s
}
path := common.EncodeURLValues(o.APIUrl+OKCOIN_FUTURES_KLINE, vals)
err := common.SendHTTPGetRequest(path, true, &resp)
err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp)
if err != nil {
return nil, err
@@ -341,7 +341,7 @@ func (o *OKCoin) GetFuturesHoldAmount(symbol, contractType string) ([]OKCoinFutu
vals.Set("contract_type", contractType)
path := common.EncodeURLValues(o.APIUrl+OKCOIN_FUTURES_HOLD_AMOUNT, vals)
err := common.SendHTTPGetRequest(path, true, &resp)
err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp)
if err != nil {
return nil, err
@@ -362,7 +362,7 @@ func (o *OKCoin) GetFuturesExplosive(symbol, contractType string, status, curren
vals.Set("page_length", strconv.FormatInt(pageLength, 10))
path := common.EncodeURLValues(o.APIUrl+OKCOIN_FUTURES_EXPLOSIVE, vals)
err := common.SendHTTPGetRequest(path, true, &resp)
err := common.SendHTTPGetRequest(path, true, o.Verbose, &resp)
if err != nil {
return nil, err

View File

@@ -101,7 +101,7 @@ func (p *Poloniex) GetTicker() (map[string]PoloniexTicker, error) {
resp := response{}
path := fmt.Sprintf("%s/public?command=returnTicker", POLONIEX_API_URL)
err := common.SendHTTPGetRequest(path, true, &resp.Data)
err := common.SendHTTPGetRequest(path, true, p.Verbose, &resp.Data)
if err != nil {
return resp.Data, err
@@ -112,7 +112,7 @@ func (p *Poloniex) GetTicker() (map[string]PoloniexTicker, error) {
func (p *Poloniex) GetVolume() (interface{}, error) {
var resp interface{}
path := fmt.Sprintf("%s/public?command=return24hVolume", POLONIEX_API_URL)
err := common.SendHTTPGetRequest(path, true, &resp)
err := common.SendHTTPGetRequest(path, true, p.Verbose, &resp)
if err != nil {
return resp, err
@@ -130,7 +130,7 @@ func (p *Poloniex) GetOrderbook(currencyPair string, depth int) (PoloniexOrderbo
resp := PoloniexOrderbookResponse{}
path := fmt.Sprintf("%s/public?command=returnOrderBook&%s", POLONIEX_API_URL, vals.Encode())
err := common.SendHTTPGetRequest(path, true, &resp)
err := common.SendHTTPGetRequest(path, true, p.Verbose, &resp)
if err != nil {
return PoloniexOrderbook{}, err
@@ -173,7 +173,7 @@ func (p *Poloniex) GetTradeHistory(currencyPair, start, end string) ([]PoloniexT
resp := []PoloniexTradeHistory{}
path := fmt.Sprintf("%s/public?command=returnTradeHistory&%s", POLONIEX_API_URL, vals.Encode())
err := common.SendHTTPGetRequest(path, true, &resp)
err := common.SendHTTPGetRequest(path, true, p.Verbose, &resp)
if err != nil {
return nil, err
@@ -199,7 +199,7 @@ func (p *Poloniex) GetChartData(currencyPair, start, end, period string) ([]Polo
resp := []PoloniexChartData{}
path := fmt.Sprintf("%s/public?command=returnChartData&%s", POLONIEX_API_URL, vals.Encode())
err := common.SendHTTPGetRequest(path, true, &resp)
err := common.SendHTTPGetRequest(path, true, p.Verbose, &resp)
if err != nil {
return nil, err
@@ -213,7 +213,7 @@ func (p *Poloniex) GetCurrencies() (map[string]PoloniexCurrencies, error) {
}
resp := Response{}
path := fmt.Sprintf("%s/public?command=returnCurrencies", POLONIEX_API_URL)
err := common.SendHTTPGetRequest(path, true, &resp.Data)
err := common.SendHTTPGetRequest(path, true, p.Verbose, &resp.Data)
if err != nil {
return resp.Data, err
@@ -224,7 +224,7 @@ func (p *Poloniex) GetCurrencies() (map[string]PoloniexCurrencies, error) {
func (p *Poloniex) GetLoanOrders(currency string) (PoloniexLoanOrders, error) {
resp := PoloniexLoanOrders{}
path := fmt.Sprintf("%s/public?command=returnLoanOrders&currency=%s", POLONIEX_API_URL, currency)
err := common.SendHTTPGetRequest(path, true, &resp)
err := common.SendHTTPGetRequest(path, true, p.Verbose, &resp)
if err != nil {
return resp, err

View File

@@ -80,7 +80,7 @@ func GetEthereumBalance(address []string) (EtherchainBalanceResponse, error) {
"%s/%s/%s", etherchainAPIURL, etherchainAccountMultiple, addresses,
)
result := EtherchainBalanceResponse{}
err := common.SendHTTPGetRequest(url, true, &result)
err := common.SendHTTPGetRequest(url, true, false, &result)
if err != nil {
return result, err
}
@@ -90,17 +90,62 @@ func GetEthereumBalance(address []string) (EtherchainBalanceResponse, error) {
return result, nil
}
<<<<<<< dae90a2eaa109648bdb85f8298d805e00ad4e974
// GetCryptoIDAddress queries CryptoID for an address balance for a
// specified cryptocurrency
func GetCryptoIDAddress(address string, coinType string) (float64, error) {
ok, err := common.IsValidCryptoAddress(address, coinType)
if !ok || err != nil {
return 0, errors.New("invalid address")
=======
// GetBlockrBalanceSingle queries Blockr for an address balance for either a
// LTC or a BTC single address
func GetBlockrBalanceSingle(address string, coinType string) (BlockrAddressBalanceSingle, error) {
valid, _ := common.IsValidCryptoAddress(address, coinType)
if !valid {
return BlockrAddressBalanceSingle{}, fmt.Errorf(
"Not a %s address", common.StringToUpper(coinType),
)
}
url := fmt.Sprintf(
"https://%s.%s/v%s/%s/%s", common.StringToLower(coinType), blockrAPIURL,
blockrAPIVersion, blockrAddressBalance, address,
)
result := BlockrAddressBalanceSingle{}
err := common.SendHTTPGetRequest(url, true, false, &result)
if err != nil {
return result, err
}
if result.Status != "success" {
return result, errors.New(result.Message)
>>>>>>> In the common package added JSONDecode error check. Added verbosity in SendHTTPGetRequest. Updated Nonce package function. Fixed issues in ItBit package and expanded test coverage.
}
<<<<<<< dae90a2eaa109648bdb85f8298d805e00ad4e974
var result interface{}
url := fmt.Sprintf("%s/%s/api.dws?q=getbalance&a=%s", cryptoIDAPIURL, common.StringToLower(coinType), address)
err = common.SendHTTPGetRequest(url, true, &result)
=======
// GetBlockrAddressMulti queries Blockr for an address balance for either a LTC
// or a BTC multiple addresses
func GetBlockrAddressMulti(addresses []string, coinType string) (BlockrAddressBalanceMulti, error) {
for _, add := range addresses {
valid, _ := common.IsValidCryptoAddress(add, coinType)
if !valid {
return BlockrAddressBalanceMulti{}, fmt.Errorf(
"Not a %s address", common.StringToUpper(coinType),
)
}
}
addressesStr := common.JoinStrings(addresses, ",")
url := fmt.Sprintf(
"https://%s.%s/v%s/%s/%s", common.StringToLower(coinType), blockrAPIURL,
blockrAPIVersion, blockrAddressBalance, addressesStr,
)
result := BlockrAddressBalanceMulti{}
err := common.SendHTTPGetRequest(url, true, false, &result)
>>>>>>> In the common package added JSONDecode error check. Added verbosity in SendHTTPGetRequest. Updated Nonce package function. Fixed issues in ItBit package and expanded test coverage.
if err != nil {
return 0, err
}