diff --git a/exchanges/bitfinex/bitfinex_test.go b/exchanges/bitfinex/bitfinex_test.go index 998bdd93898..5bffc8ecfcc 100644 --- a/exchanges/bitfinex/bitfinex_test.go +++ b/exchanges/bitfinex/bitfinex_test.go @@ -17,74 +17,70 @@ const ( testAPISecret = "" ) -func TestSetDefaults(t *testing.T) { - t.Parallel() +var b Bitfinex - setDefaults := Bitfinex{} - setDefaults.SetDefaults() +func TestSetDefaults(t *testing.T) { + b.SetDefaults() - if setDefaults.Name != "Bitfinex" || setDefaults.Enabled != false || - setDefaults.Verbose != false || setDefaults.Websocket != false || - setDefaults.RESTPollingDelay != 10 { + if b.Name != "Bitfinex" || b.Enabled != false || + b.Verbose != false || b.Websocket != false || + b.RESTPollingDelay != 10 { t.Error("Test Failed - Bitfinex SetDefaults values not set correctly") } } func TestSetup(t *testing.T) { - t.Parallel() testConfig := config.ExchangeConfig{ Enabled: true, AuthenticatedAPISupport: true, - APIKey: "lamb", - APISecret: "cutlets", + APIKey: testAPIKey, + APISecret: testAPISecret, RESTPollingDelay: time.Duration(10), - Verbose: true, + Verbose: false, Websocket: true, BaseCurrencies: currency.DefaultCurrencies, AvailablePairs: currency.MakecurrencyPairs(currency.DefaultCurrencies), EnabledPairs: currency.MakecurrencyPairs(currency.DefaultCurrencies), } - setup := Bitfinex{} - setup.Setup(testConfig) - if !setup.Enabled || !setup.AuthenticatedAPISupport || setup.APIKey != "lamb" || - setup.APISecret != "cutlets" || setup.RESTPollingDelay != time.Duration(10) || - !setup.Verbose || !setup.Websocket || len(setup.BaseCurrencies) < 1 || - len(setup.AvailablePairs) < 1 || len(setup.EnabledPairs) < 1 { + b.Setup(testConfig) + + if !b.Enabled || !b.AuthenticatedAPISupport || b.APIKey != testAPIKey || + b.APISecret != testAPISecret || b.RESTPollingDelay != time.Duration(10) || + b.Verbose || !b.Websocket || len(b.BaseCurrencies) < 1 || + len(b.AvailablePairs) < 1 || len(b.EnabledPairs) < 1 { t.Error("Test Failed - Bitfinex Setup values not set correctly") } - testConfig.Enabled = false - setup.Setup(testConfig) } func TestGetTicker(t *testing.T) { - bitfinex := Bitfinex{} - _, err := bitfinex.GetTicker("BTCUSD", url.Values{}) + t.Parallel() + _, err := b.GetTicker("BTCUSD", url.Values{}) if err != nil { t.Error("BitfinexGetTicker init error: ", err) } - _, err = bitfinex.GetTicker("wigwham", url.Values{}) + _, err = b.GetTicker("wigwham", url.Values{}) if err == nil { t.Error("Test Failed - GetTicker() error") } } func TestGetStats(t *testing.T) { - BitfinexGetStatsTest := Bitfinex{} - _, err := BitfinexGetStatsTest.GetStats("BTCUSD") + t.Parallel() + _, err := b.GetStats("BTCUSD") if err != nil { t.Error("BitfinexGetStatsTest init error: ", err) } - _, err = BitfinexGetStatsTest.GetStats("wigwham") + _, err = b.GetStats("wigwham") if err == nil { t.Error("Test Failed - GetStats() error") } } func TestGetFundingBook(t *testing.T) { - b := Bitfinex{} + t.Parallel() _, err := b.GetFundingBook("USD") if err != nil { t.Error("Testing Failed - GetFundingBook() error") @@ -96,42 +92,45 @@ func TestGetFundingBook(t *testing.T) { } func TestGetLendbook(t *testing.T) { - BitfinexGetLendbook := Bitfinex{} - _, err := BitfinexGetLendbook.GetLendbook("BTCUSD", url.Values{}) + t.Parallel() + + _, err := b.GetLendbook("BTCUSD", url.Values{}) if err != nil { - t.Error("BitfinexGetLendbook init error: ", err) + t.Error("Testing Failed - GetLendbook() error: ", err) } } func TestGetOrderbook(t *testing.T) { - BitfinexGetOrderbook := Bitfinex{} - _, err := BitfinexGetOrderbook.GetOrderbook("BTCUSD", url.Values{}) + t.Parallel() + + _, err := b.GetOrderbook("BTCUSD", url.Values{}) if err != nil { t.Error("BitfinexGetOrderbook init error: ", err) } } func TestGetTrades(t *testing.T) { - BitfinexGetTrades := Bitfinex{} - _, err := BitfinexGetTrades.GetTrades("BTCUSD", url.Values{}) + t.Parallel() + + _, err := b.GetTrades("BTCUSD", url.Values{}) if err != nil { t.Error("BitfinexGetTrades init error: ", err) } } func TestGetLends(t *testing.T) { - BitfinexGetLends := Bitfinex{} + t.Parallel() - _, err := BitfinexGetLends.GetLends("BTC", url.Values{}) + _, err := b.GetLends("BTC", url.Values{}) if err != nil { t.Error("BitfinexGetLends init error: ", err) } } func TestGetSymbols(t *testing.T) { - BitfinexGetSymbols := Bitfinex{} + t.Parallel() - symbols, err := BitfinexGetSymbols.GetSymbols() + symbols, err := b.GetSymbols() if err != nil { t.Error("BitfinexGetSymbols init error: ", err) } @@ -177,17 +176,16 @@ func TestGetSymbols(t *testing.T) { } func TestGetSymbolsDetails(t *testing.T) { - BitfinexGetSymbolsDetails := Bitfinex{} - _, err := BitfinexGetSymbolsDetails.GetSymbolsDetails() + t.Parallel() + + _, err := b.GetSymbolsDetails() if err != nil { t.Error("BitfinexGetSymbolsDetails init error: ", err) } } func TestGetAccountInfo(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.GetAccountInfo() if err == nil { @@ -196,9 +194,7 @@ func TestGetAccountInfo(t *testing.T) { } func TestGetAccountFees(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.GetAccountFees() if err == nil { @@ -207,9 +203,7 @@ func TestGetAccountFees(t *testing.T) { } func TestGetAccountSummary(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.GetAccountSummary() if err == nil { @@ -218,9 +212,7 @@ func TestGetAccountSummary(t *testing.T) { } func TestNewDeposit(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.NewDeposit("blabla", "testwallet", 1) if err == nil { @@ -229,9 +221,7 @@ func TestNewDeposit(t *testing.T) { } func TestGetKeyPermissions(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.GetKeyPermissions() if err == nil { @@ -240,9 +230,7 @@ func TestGetKeyPermissions(t *testing.T) { } func TestGetMarginInfo(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.GetMarginInfo() if err == nil { @@ -251,9 +239,7 @@ func TestGetMarginInfo(t *testing.T) { } func TestGetAccountBalance(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.GetAccountBalance() if err == nil { @@ -262,9 +248,7 @@ func TestGetAccountBalance(t *testing.T) { } func TestWalletTransfer(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.WalletTransfer(0.01, "bla", "bla", "bla") if err == nil { @@ -273,9 +257,7 @@ func TestWalletTransfer(t *testing.T) { } func TestWithdrawal(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.Withdrawal("LITECOIN", "deposit", "1000", 0.01) if err == nil { @@ -284,9 +266,7 @@ func TestWithdrawal(t *testing.T) { } func TestNewOrder(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.NewOrder("BTCUSD", 1, 2, true, "market", false) if err == nil { @@ -295,9 +275,8 @@ func TestNewOrder(t *testing.T) { } func TestNewOrderMulti(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() + newOrder := []PlaceOrder{ { Symbol: "BTCUSD", @@ -316,9 +295,7 @@ func TestNewOrderMulti(t *testing.T) { } func TestCancelOrder(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.CancelOrder(1337) if err == nil { @@ -327,9 +304,7 @@ func TestCancelOrder(t *testing.T) { } func TestCancelMultipleOrders(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.CancelMultipleOrders([]int64{1337, 1336}) if err == nil { @@ -338,9 +313,7 @@ func TestCancelMultipleOrders(t *testing.T) { } func TestCancelAllOrders(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.CancelAllOrders() if err == nil { @@ -349,9 +322,7 @@ func TestCancelAllOrders(t *testing.T) { } func TestReplaceOrder(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.ReplaceOrder(1337, "BTCUSD", 1, 1, true, "market", false) if err == nil { @@ -360,9 +331,7 @@ func TestReplaceOrder(t *testing.T) { } func TestGetOrderStatus(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.GetOrderStatus(1337) if err == nil { @@ -371,9 +340,7 @@ func TestGetOrderStatus(t *testing.T) { } func TestGetActiveOrders(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.GetActiveOrders() if err == nil { @@ -382,9 +349,7 @@ func TestGetActiveOrders(t *testing.T) { } func TestGetActivePositions(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.GetActivePositions() if err == nil { @@ -393,9 +358,7 @@ func TestGetActivePositions(t *testing.T) { } func TestClaimPosition(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.ClaimPosition(1337) if err == nil { @@ -404,9 +367,7 @@ func TestClaimPosition(t *testing.T) { } func TestGetBalanceHistory(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.GetBalanceHistory("USD", time.Time{}, time.Time{}, 1, "deposit") if err == nil { @@ -415,9 +376,7 @@ func TestGetBalanceHistory(t *testing.T) { } func TestGetMovementHistory(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.GetMovementHistory("USD", "bitcoin", time.Time{}, time.Time{}, 1) if err == nil { @@ -426,9 +385,7 @@ func TestGetMovementHistory(t *testing.T) { } func TestGetTradeHistory(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.GetTradeHistory("BTCUSD", time.Time{}, time.Time{}, 1, 0) if err == nil { @@ -437,9 +394,7 @@ func TestGetTradeHistory(t *testing.T) { } func TestNewOffer(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.NewOffer("BTC", 1, 1, 1, "loan") if err == nil { @@ -448,9 +403,7 @@ func TestNewOffer(t *testing.T) { } func TestCancelOffer(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.CancelOffer(1337) if err == nil { @@ -459,9 +412,7 @@ func TestCancelOffer(t *testing.T) { } func TestGetOfferStatus(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.GetOfferStatus(1337) if err == nil { @@ -470,9 +421,7 @@ func TestGetOfferStatus(t *testing.T) { } func TestGetActiveCredits(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.GetActiveCredits() if err == nil { @@ -481,9 +430,7 @@ func TestGetActiveCredits(t *testing.T) { } func TestGetActiveOffers(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.GetActiveOffers() if err == nil { @@ -492,9 +439,7 @@ func TestGetActiveOffers(t *testing.T) { } func TestGetActiveMarginFunding(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.GetActiveMarginFunding() if err == nil { @@ -503,9 +448,7 @@ func TestGetActiveMarginFunding(t *testing.T) { } func TestGetUnusedMarginFunds(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.GetUnusedMarginFunds() if err == nil { @@ -514,9 +457,7 @@ func TestGetUnusedMarginFunds(t *testing.T) { } func TestGetMarginTotalTakenFunds(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.GetMarginTotalTakenFunds() if err == nil { @@ -525,9 +466,7 @@ func TestGetMarginTotalTakenFunds(t *testing.T) { } func TestCloseMarginFunding(t *testing.T) { - b := Bitfinex{} - b.APIKey = testAPIKey - b.APISecret = testAPISecret + t.Parallel() _, err := b.CloseMarginFunding(1337) if err == nil { diff --git a/exchanges/bitstamp/bitstamp.go b/exchanges/bitstamp/bitstamp.go index 8c4c36888ff..b5ec92a15d4 100644 --- a/exchanges/bitstamp/bitstamp.go +++ b/exchanges/bitstamp/bitstamp.go @@ -16,39 +16,44 @@ import ( ) const ( - BITSTAMP_API_URL = "https://www.bitstamp.net/api" - BITSTAMP_API_VERSION = "2" - BITSTAMP_API_TICKER = "ticker" - BITSTAMP_API_TICKER_HOURLY = "ticker_hour" - BITSTAMP_API_ORDERBOOK = "order_book" - BITSTAMP_API_TRANSACTIONS = "transactions" - BITSTAMP_API_EURUSD = "eur_usd" - BITSTAMP_API_BALANCE = "balance" - BITSTAMP_API_USER_TRANSACTIONS = "user_transactions" - BITSTAMP_API_OPEN_ORDERS = "open_orders" - BITSTAMP_API_ORDER_STATUS = "order_status" - BITSTAMP_API_CANCEL_ORDER = "cancel_order" - BITSTAMP_API_CANCEL_ALL_ORDERS = "cancel_all_orders" - BITSTAMP_API_BUY = "buy" - BITSTAMP_API_SELL = "sell" - BITSTAMP_API_MARKET = "market" - BITSTAMP_API_WITHDRAWAL_REQUESTS = "withdrawal_requests" - BITSTAMP_API_BITCOIN_WITHDRAWAL = "bitcoin_withdrawal" - BITSTAMP_API_BITCOIN_DEPOSIT = "bitcoin_deposit_address" - BITSTAMP_API_UNCONFIRMED_BITCOIN = "unconfirmed_btc" - BITSTAMP_API_RIPPLE_WITHDRAWAL = "ripple_withdrawal" - BITSTAMP_API_RIPPLE_DESPOIT = "ripple_address" - BITSTAMP_API_TRANSFER_TO_MAIN = "transfer-to-main" - BITSTAMP_API_TRANSFER_FROM_MAIN = "transfer-from-main" - BITSTAMP_API_XRP_WITHDRAWAL = "xrp_withdrawal" - BITSTAMP_API_XRP_DESPOIT = "xrp_address" + bitstampAPIURL = "https://www.bitstamp.net/api" + bitstampAPIVersion = "2" + bitstampAPITicker = "ticker" + bitstampAPITickerHourly = "ticker_hour" + bitstampAPIOrderbook = "order_book" + bitstampAPITransactions = "transactions" + bitstampAPIEURUSD = "eur_usd" + bitstampAPIBalance = "balance" + bitstampAPIUserTransactions = "user_transactions" + bitstampAPIOpenOrders = "open_orders" + bitstampAPIOrderStatus = "order_status" + bitstampAPICancelOrder = "cancel_order" + bitstampAPICancelAllOrders = "cancel_all_orders" + bitstampAPIBuy = "buy" + bitstampAPISell = "sell" + bitstampAPIMarket = "market" + bitstampAPIWithdrawalRequests = "withdrawal_requests" + bitstampAPIBitcoinWithdrawal = "bitcoin_withdrawal" + bitstampAPILTCWithdrawal = "ltc_withdrawal" + bitstampAPIETHWithdrawal = "eth_withdrawal" + bitstampAPIBitcoinDeposit = "bitcoin_deposit_address" + bitstampAPILitecoinDeposit = "ltc_address" + bitstampAPIEthereumDeposit = "eth_address" + bitstampAPIUnconfirmedBitcoin = "unconfirmed_btc" + bitstampAPITransferToMain = "transfer-to-main" + bitstampAPITransferFromMain = "transfer-from-main" + bitstampAPIXrpWithdrawal = "xrp_withdrawal" + bitstampAPIXrpDeposit = "xrp_address" + bitstampAPIReturnType = "string" ) +// Bitstamp is the overarching type across the bitstamp package type Bitstamp struct { exchange.Base - Balance BitstampBalances + Balance Balances } +// SetDefaults sets default for Bitstamp func (b *Bitstamp) SetDefaults() { b.Name = "Bitstamp" b.Enabled = false @@ -57,6 +62,7 @@ func (b *Bitstamp) SetDefaults() { b.RESTPollingDelay = 10 } +// Setup sets configuration values to bitstamp func (b *Bitstamp) Setup(exch config.ExchangeConfig) { if !exch.Enabled { b.SetEnabled(false) @@ -73,8 +79,9 @@ func (b *Bitstamp) Setup(exch config.ExchangeConfig) { } } -func (b *Bitstamp) GetFee(currency string) float64 { - switch currency { +// GetFee returns fee on a currency pair +func (b *Bitstamp) GetFee(currencyPair string) float64 { + switch currencyPair { case "BTCUSD": return b.Balance.BTCUSDFee case "BTCEUR": @@ -90,39 +97,50 @@ func (b *Bitstamp) GetFee(currency string) float64 { } } -func (b *Bitstamp) GetTicker(currency string, hourly bool) (BitstampTicker, error) { - tickerEndpoint := BITSTAMP_API_TICKER - if hourly { - tickerEndpoint = BITSTAMP_API_TICKER_HOURLY - } - - path := fmt.Sprintf("%s/v%s/%s/%s/", BITSTAMP_API_URL, BITSTAMP_API_VERSION, tickerEndpoint, common.StringToLower(currency)) - ticker := BitstampTicker{} - - err := common.SendHTTPGetRequest(path, true, &ticker) +// GetTicker returns ticker information +func (b *Bitstamp) GetTicker(currency string, hourly bool) (Ticker, error) { + response := Ticker{} + tickerEndpoint := bitstampAPITicker - if err != nil { - return ticker, err + if hourly { + tickerEndpoint = bitstampAPITickerHourly } - return ticker, nil + path := fmt.Sprintf( + "%s/v%s/%s/%s/", + bitstampAPIURL, + bitstampAPIVersion, + tickerEndpoint, + common.StringToLower(currency), + ) + return response, common.SendHTTPGetRequest(path, true, &response) } -func (b *Bitstamp) GetOrderbook(currency string) (BitstampOrderbook, error) { +// GetOrderbook Returns a JSON dictionary with "bids" and "asks". Each is a list +// of open orders and each order is represented as a list holding the price and +//the amount. +func (b *Bitstamp) GetOrderbook(currency string) (Orderbook, error) { type response struct { - Timestamp int64 `json:"timestamp,string"` - Bids [][]string - Asks [][]string + Timestamp int64 `json:"timestamp,string"` + Bids [][]string `json:"bids"` + Asks [][]string `json:"asks"` } - resp := response{} - path := fmt.Sprintf("%s/v%s/%s/%s/", BITSTAMP_API_URL, BITSTAMP_API_VERSION, BITSTAMP_API_ORDERBOOK, common.StringToLower(currency)) + + path := fmt.Sprintf( + "%s/v%s/%s/%s/", + bitstampAPIURL, + bitstampAPIVersion, + bitstampAPIOrderbook, + common.StringToLower(currency), + ) + err := common.SendHTTPGetRequest(path, true, &resp) if err != nil { - return BitstampOrderbook{}, err + return Orderbook{}, err } - orderbook := BitstampOrderbook{} + orderbook := Orderbook{} orderbook.Timestamp = resp.Timestamp for _, x := range resp.Bids { @@ -136,7 +154,7 @@ func (b *Bitstamp) GetOrderbook(currency string) (BitstampOrderbook, error) { log.Println(err) continue } - orderbook.Bids = append(orderbook.Bids, BitstampOrderbookBase{price, amount}) + orderbook.Bids = append(orderbook.Bids, OrderbookBase{price, amount}) } for _, x := range resp.Asks { @@ -150,44 +168,49 @@ func (b *Bitstamp) GetOrderbook(currency string) (BitstampOrderbook, error) { log.Println(err) continue } - orderbook.Asks = append(orderbook.Asks, BitstampOrderbookBase{price, amount}) + orderbook.Asks = append(orderbook.Asks, OrderbookBase{price, amount}) } return orderbook, nil } -func (b *Bitstamp) GetTransactions(currency string, values url.Values) ([]BitstampTransactions, error) { - path := common.EncodeURLValues(fmt.Sprintf("%s/v%s/%s/%s/", BITSTAMP_API_URL, BITSTAMP_API_VERSION, BITSTAMP_API_TRANSACTIONS, common.StringToLower(currency)), values) - transactions := []BitstampTransactions{} - err := common.SendHTTPGetRequest(path, true, &transactions) - if err != nil { - return nil, err - } - return transactions, nil +// GetTransactions returns transaction information +// value paramater ["time"] = "minute", "hour", "day" will collate your +// response into time intervals. Implementation of value in test code. +func (b *Bitstamp) GetTransactions(currencyPair string, values url.Values) ([]Transactions, error) { + transactions := []Transactions{} + path := common.EncodeURLValues( + fmt.Sprintf( + "%s/v%s/%s/%s/", + bitstampAPIURL, + bitstampAPIVersion, + bitstampAPITransactions, + common.StringToLower(currencyPair), + ), + values, + ) + + return transactions, common.SendHTTPGetRequest(path, true, &transactions) } -func (b *Bitstamp) GetEURUSDConversionRate() (BitstampEURUSDConversionRate, error) { - rate := BitstampEURUSDConversionRate{} - path := fmt.Sprintf("%s/%s", BITSTAMP_API_URL, BITSTAMP_API_EURUSD) - err := common.SendHTTPGetRequest(path, true, &rate) +// GetEURUSDConversionRate returns the conversion rate between Euro and USD +func (b *Bitstamp) GetEURUSDConversionRate() (EURUSDConversionRate, error) { + rate := EURUSDConversionRate{} + path := fmt.Sprintf("%s/%s", bitstampAPIURL, bitstampAPIEURUSD) - if err != nil { - return rate, err - } - return rate, nil + return rate, common.SendHTTPGetRequest(path, true, &rate) } -func (b *Bitstamp) GetBalance() (BitstampBalances, error) { - balance := BitstampBalances{} - err := b.SendAuthenticatedHTTPRequest(BITSTAMP_API_BALANCE, true, url.Values{}, &balance) +// GetBalance returns full balance of currency held on the exchange +func (b *Bitstamp) GetBalance() (Balances, error) { + balance := Balances{} - if err != nil { - return balance, err - } - return balance, nil + return balance, + b.SendAuthenticatedHTTPRequest(bitstampAPIBalance, true, url.Values{}, &balance) } -func (b *Bitstamp) GetUserTransactions(values url.Values) ([]BitstampUserTransactions, error) { +// GetUserTransactions returns an array of transactions +func (b *Bitstamp) GetUserTransactions(currencyPair string) ([]UserTransactions, error) { type Response struct { Date string `json:"datetime"` TransID int64 `json:"id"` @@ -200,25 +223,29 @@ func (b *Bitstamp) GetUserTransactions(values url.Values) ([]BitstampUserTransac Fee float64 `json:"fee,string"` OrderID int64 `json:"order_id"` } - response := []Response{} - err := b.SendAuthenticatedHTTPRequest(BITSTAMP_API_USER_TRANSACTIONS, true, values, &response) - if err != nil { - return nil, err + if currencyPair != "" { + if err := b.SendAuthenticatedHTTPRequest(bitstampAPIUserTransactions, true, url.Values{}, &response); err != nil { + return nil, err + } + } else { + if err := b.SendAuthenticatedHTTPRequest(bitstampAPIUserTransactions+"/"+currencyPair, true, url.Values{}, &response); err != nil { + return nil, err + } } - transactions := []BitstampUserTransactions{} + transactions := []UserTransactions{} for _, y := range response { - tx := BitstampUserTransactions{} + tx := UserTransactions{} tx.Date = y.Date tx.TransID = y.TransID tx.Type = y.Type /* Hack due to inconsistent JSON values... */ varType := reflect.TypeOf(y.USD).String() - if varType == "string" { + if varType == bitstampAPIReturnType { tx.USD, _ = strconv.ParseFloat(y.USD.(string), 64) } else { tx.USD = y.USD.(float64) @@ -228,14 +255,14 @@ func (b *Bitstamp) GetUserTransactions(values url.Values) ([]BitstampUserTransac tx.XRP = y.XRP varType = reflect.TypeOf(y.BTC).String() - if varType == "string" { + if varType == bitstampAPIReturnType { tx.BTC, _ = strconv.ParseFloat(y.BTC.(string), 64) } else { tx.BTC = y.BTC.(float64) } varType = reflect.TypeOf(y.BTCUSD).String() - if varType == "string" { + if varType == bitstampAPIReturnType { tx.BTCUSD, _ = strconv.ParseFloat(y.BTCUSD.(string), 64) } else { tx.BTCUSD = y.BTCUSD.(float64) @@ -249,184 +276,179 @@ func (b *Bitstamp) GetUserTransactions(values url.Values) ([]BitstampUserTransac return transactions, nil } -func (b *Bitstamp) GetOpenOrders(currency string) ([]BitstampOrder, error) { - resp := []BitstampOrder{} - path := fmt.Sprintf("%s/%s", BITSTAMP_API_OPEN_ORDERS, common.StringToLower(currency)) - err := b.SendAuthenticatedHTTPRequest(path, true, nil, &resp) +// GetOpenOrders returns all open orders on the exchange +func (b *Bitstamp) GetOpenOrders(currencyPair string) ([]Order, error) { + resp := []Order{} + path := fmt.Sprintf( + "%s/%s", bitstampAPIOpenOrders, common.StringToLower(currencyPair), + ) - if err != nil { - return nil, err - } - - return resp, nil + return resp, b.SendAuthenticatedHTTPRequest(path, true, nil, &resp) } -func (b *Bitstamp) GetOrderStatus(OrderID int64) (BitstampOrderStatus, error) { - var req = url.Values{} +// GetOrderStatus returns an the status of an order by its ID +func (b *Bitstamp) GetOrderStatus(OrderID int64) (OrderStatus, error) { + resp := OrderStatus{} + req := url.Values{} req.Add("id", strconv.FormatInt(OrderID, 10)) - resp := BitstampOrderStatus{} - - err := b.SendAuthenticatedHTTPRequest(BITSTAMP_API_CANCEL_ORDER, false, req, &resp) - - if err != nil { - return resp, err - } - return resp, nil + return resp, + b.SendAuthenticatedHTTPRequest(bitstampAPIOrderStatus, false, req, &resp) } +// CancelOrder cancels order by ID func (b *Bitstamp) CancelOrder(OrderID int64) (bool, error) { - var req = url.Values{} result := false + var req = url.Values{} req.Add("id", strconv.FormatInt(OrderID, 10)) - err := b.SendAuthenticatedHTTPRequest(BITSTAMP_API_CANCEL_ORDER, true, req, &result) - - if err != nil { - return result, err - } - - return result, nil + return result, + b.SendAuthenticatedHTTPRequest(bitstampAPICancelOrder, true, req, &result) } +// CancelAllOrders cancels all open orders on the exchange func (b *Bitstamp) CancelAllOrders() (bool, error) { result := false - err := b.SendAuthenticatedHTTPRequest(BITSTAMP_API_CANCEL_ALL_ORDERS, false, nil, &result) - - if err != nil { - return result, err - } - return result, nil + return result, + b.SendAuthenticatedHTTPRequest(bitstampAPICancelAllOrders, false, nil, &result) } -func (b *Bitstamp) PlaceOrder(currency string, price float64, amount float64, buy, market bool) (BitstampOrder, error) { +// PlaceOrder places an order on the exchange. +func (b *Bitstamp) PlaceOrder(currencyPair string, price float64, amount float64, buy, market bool) (Order, error) { var req = url.Values{} req.Add("amount", strconv.FormatFloat(amount, 'f', -1, 64)) req.Add("price", strconv.FormatFloat(price, 'f', -1, 64)) - response := BitstampOrder{} - orderType := BITSTAMP_API_BUY - path := "" + response := Order{} + orderType := bitstampAPIBuy if !buy { - orderType = BITSTAMP_API_SELL + orderType = bitstampAPISell } - path = fmt.Sprintf("%s/%s", orderType, common.StringToLower(currency)) + path := fmt.Sprintf("%s/%s", orderType, common.StringToLower(currencyPair)) if market { - path = fmt.Sprintf("%s/%s/%s", orderType, BITSTAMP_API_MARKET, common.StringToLower(currency)) + path = fmt.Sprintf("%s/%s/%s", orderType, bitstampAPIMarket, common.StringToLower(currencyPair)) } - err := b.SendAuthenticatedHTTPRequest(path, true, req, &response) + return response, + b.SendAuthenticatedHTTPRequest(path, true, req, &response) +} - if err != nil { - return response, err +// GetWithdrawalRequests returns withdrawl requests for the account +// timedelta - positive integer with max value 50000000 which returns requests +// from number of seconds ago to now. +func (b *Bitstamp) GetWithdrawalRequests(timedelta int64) ([]WithdrawalRequests, error) { + resp := []WithdrawalRequests{} + if timedelta > 50000000 || timedelta < 0 { + return resp, errors.New("time delta exceeded, max: 50000000 min: 0") } - return response, nil -} + value := url.Values{} + value.Set("timedelta", strconv.FormatInt(timedelta, 10)) -func (b *Bitstamp) GetWithdrawalRequests(values url.Values) ([]BitstampWithdrawalRequests, error) { - resp := []BitstampWithdrawalRequests{} - err := b.SendAuthenticatedHTTPRequest(BITSTAMP_API_WITHDRAWAL_REQUESTS, false, values, &resp) - - if err != nil { - return nil, err + if timedelta == 0 { + value = url.Values{} } - return resp, nil + return resp, + b.SendAuthenticatedHTTPRequest(bitstampAPIWithdrawalRequests, false, value, &resp) } -func (b *Bitstamp) BitcoinWithdrawal(amount float64, address string, instant bool) (string, error) { +// CryptoWithdrawal withdraws a cryptocurrency into a supplied wallet, returns ID +// amount - The amount you want withdrawn +// address - The wallet address of the cryptocurrency +// symbol - the type of crypto ie "ltc", "btc", "eth" +// destTag - only for XRP default to "" +// instant - only for bitcoins +func (b *Bitstamp) CryptoWithdrawal(amount float64, address, symbol, destTag string, instant bool) (string, error) { var req = url.Values{} req.Add("amount", strconv.FormatFloat(amount, 'f', -1, 64)) req.Add("address", address) - if instant { - req.Add("instant", "1") - } else { - req.Add("instant", "0") - } - type response struct { ID string `json:"id"` } - resp := response{} - err := b.SendAuthenticatedHTTPRequest(BITSTAMP_API_BITCOIN_WITHDRAWAL, false, req, &resp) - - if err != nil { - return "", err - } - - return resp.ID, nil -} - -func (b *Bitstamp) GetBitcoinDepositAddress() (string, error) { - address := "" - err := b.SendAuthenticatedHTTPRequest(BITSTAMP_API_BITCOIN_DEPOSIT, false, url.Values{}, &address) - - if err != nil { - return address, err - } - return address, nil -} - -func (b *Bitstamp) GetUnconfirmedBitcoinDeposits() ([]BitstampUnconfirmedBTCTransactions, error) { - response := []BitstampUnconfirmedBTCTransactions{} - err := b.SendAuthenticatedHTTPRequest(BITSTAMP_API_UNCONFIRMED_BITCOIN, false, nil, &response) - - if err != nil { - return nil, err - } - - return response, nil -} - -func (b *Bitstamp) RippleWithdrawal(amount float64, address, currency string) (bool, error) { - var req = url.Values{} - req.Add("amount", strconv.FormatFloat(amount, 'f', -1, 64)) - req.Add("address", address) - req.Add("currency", currency) - err := b.SendAuthenticatedHTTPRequest(BITSTAMP_API_RIPPLE_WITHDRAWAL, false, req, nil) - - if err != nil { - return false, err + switch common.StringToLower(symbol) { + case "btc": + if instant { + req.Add("instant", "1") + } else { + req.Add("instant", "0") + } + return resp.ID, + b.SendAuthenticatedHTTPRequest(bitstampAPIBitcoinWithdrawal, false, req, &resp) + case "ltc": + return resp.ID, + b.SendAuthenticatedHTTPRequest(bitstampAPILTCWithdrawal, true, req, &resp) + case "eth": + return resp.ID, + b.SendAuthenticatedHTTPRequest(bitstampAPIETHWithdrawal, true, req, &resp) + case "xrp": + if destTag != "" { + req.Add("destination_tag", destTag) + } + return resp.ID, + b.SendAuthenticatedHTTPRequest(bitstampAPIXrpWithdrawal, true, req, &resp) } - - return true, nil + return resp.ID, + errors.New("incorrect symbol") } -func (b *Bitstamp) GetRippleDepositAddress() (string, error) { +// GetCryptoDepositAddress returns a depositing address by crypto +// crypto - example "btc", "ltc", "eth", or "xrp" +func (b *Bitstamp) GetCryptoDepositAddress(crypto string) (string, error) { type response struct { - Address string + Address string `json:"address"` } - resp := response{} - err := b.SendAuthenticatedHTTPRequest(BITSTAMP_API_RIPPLE_DESPOIT, false, nil, &resp) - if err != nil { - return "", err - } + switch common.StringToLower(crypto) { + case "btc": + return resp.Address, + b.SendAuthenticatedHTTPRequest(bitstampAPIBitcoinDeposit, false, nil, &resp.Address) + case "ltc": + return resp.Address, + b.SendAuthenticatedHTTPRequest(bitstampAPILitecoinDeposit, true, nil, &resp) + case "eth": + return resp.Address, + b.SendAuthenticatedHTTPRequest(bitstampAPIEthereumDeposit, true, nil, &resp) + case "xrp": + return resp.Address, + b.SendAuthenticatedHTTPRequest(bitstampAPIXrpDeposit, true, nil, &resp) + } + + return resp.Address, errors.New("incorrect cryptocurrency string") +} + +// GetUnconfirmedBitcoinDeposits returns unconfirmed transactions +func (b *Bitstamp) GetUnconfirmedBitcoinDeposits() ([]UnconfirmedBTCTransactions, error) { + response := []UnconfirmedBTCTransactions{} - return resp.Address, nil + return response, + b.SendAuthenticatedHTTPRequest(bitstampAPIUnconfirmedBitcoin, false, nil, &response) } +// TransferAccountBalance transfers funds from either a main or sub account +// amount - to transfers +// currency - which currency to transfer +// subaccount - name of account +// toMain - bool either to or from account func (b *Bitstamp) TransferAccountBalance(amount float64, currency, subAccount string, toMain bool) (bool, error) { var req = url.Values{} req.Add("amount", strconv.FormatFloat(amount, 'f', -1, 64)) req.Add("currency", currency) req.Add("subAccount", subAccount) - path := BITSTAMP_API_TRANSFER_TO_MAIN + path := bitstampAPITransferToMain if !toMain { - path = BITSTAMP_API_TRANSFER_FROM_MAIN + path = bitstampAPITransferFromMain } err := b.SendAuthenticatedHTTPRequest(path, true, req, nil) - if err != nil { return false, err } @@ -434,39 +456,7 @@ func (b *Bitstamp) TransferAccountBalance(amount float64, currency, subAccount s return true, nil } -func (b *Bitstamp) XRPWithdrawal(amount float64, address, destTag string) (string, error) { - var req = url.Values{} - req.Add("amount", strconv.FormatFloat(amount, 'f', -1, 64)) - req.Add("address", address) - if destTag != "" { - req.Add("destination_tag", destTag) - } - - type response struct { - ID string `json:"id"` - } - - resp := response{} - err := b.SendAuthenticatedHTTPRequest(BITSTAMP_API_XRP_WITHDRAWAL, true, req, &resp) - - if err != nil { - return "", err - } - - return resp.ID, nil -} - -func (b *Bitstamp) GetXRPDepositAddress() (BitstampXRPDepositResponse, error) { - resp := BitstampXRPDepositResponse{} - err := b.SendAuthenticatedHTTPRequest(BITSTAMP_API_XRP_DESPOIT, true, nil, &resp) - - if err != nil { - return BitstampXRPDepositResponse{}, err - } - - return resp, nil -} - +// SendAuthenticatedHTTPRequest sends an authenticated request func (b *Bitstamp) SendAuthenticatedHTTPRequest(path string, v2 bool, values url.Values, result interface{}) (err error) { if !b.AuthenticatedAPISupport { return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, b.Name) @@ -488,9 +478,9 @@ func (b *Bitstamp) SendAuthenticatedHTTPRequest(path string, v2 bool, values url values.Set("signature", common.StringToUpper(common.HexEncodeToString(hmac))) if v2 { - path = fmt.Sprintf("%s/v%s/%s/", BITSTAMP_API_URL, BITSTAMP_API_VERSION, path) + path = fmt.Sprintf("%s/v%s/%s/", bitstampAPIURL, bitstampAPIVersion, path) } else { - path = fmt.Sprintf("%s/%s/", BITSTAMP_API_URL, path) + path = fmt.Sprintf("%s/%s/", bitstampAPIURL, path) } if b.Verbose { @@ -509,11 +499,17 @@ func (b *Bitstamp) SendAuthenticatedHTTPRequest(path string, v2 bool, values url log.Printf("Received raw: %s\n", resp) } - err = common.JSONDecode([]byte(resp), &result) - - if err != nil { - return errors.New("unable to JSON Unmarshal response") + /* inconsistent errors, needs to be improved when in production*/ + if common.StringContains(resp, "500 error") { + return errors.New("internal server: code 500") } - return nil + capture := CaptureError{} + if err = common.JSONDecode([]byte(resp), &capture); err == nil { + if capture.Code != nil || capture.Error != nil || capture.Reason != nil || capture.Status != nil { + errstring := fmt.Sprint("Status: ", capture.Status, ", Issue: ", capture.Error, ", Reason: ", capture.Reason, ", Code: ", capture.Code) + return errors.New(errstring) + } + } + return common.JSONDecode([]byte(resp), &result) } diff --git a/exchanges/bitstamp/bitstamp_test.go b/exchanges/bitstamp/bitstamp_test.go new file mode 100644 index 00000000000..e7133de25e9 --- /dev/null +++ b/exchanges/bitstamp/bitstamp_test.go @@ -0,0 +1,346 @@ +package bitstamp + +import ( + "net/url" + "testing" + + "github.com/thrasher-/gocryptotrader/config" +) + +// Please add your private keys and customerID for better tests +const ( + apiKey = "" + apiSecret = "" + customerID = "" +) + +func TestSetDefaults(t *testing.T) { + t.Parallel() + b := Bitstamp{} + b.SetDefaults() + + if b.Name != "Bitstamp" { + t.Error("Test Failed - SetDefaults() error") + } + if b.Enabled != false { + t.Error("Test Failed - SetDefaults() error") + } + if b.Verbose != false { + t.Error("Test Failed - SetDefaults() error") + } + if b.Websocket != false { + t.Error("Test Failed - SetDefaults() error") + } + if b.RESTPollingDelay != 10 { + t.Error("Test Failed - SetDefaults() error") + } +} + +func TestSetup(t *testing.T) { + t.Parallel() + b := Bitstamp{} + conf := config.ExchangeConfig{ + Name: "bla", + Enabled: true, + AuthenticatedAPISupport: true, + } + b.Setup(conf) + + if b.Name != "bla" && b.Enabled != true && b.AuthenticatedAPISupport != true { + t.Error("Test Failed - Setup() error") + } + conf.Enabled = false + b.Setup(conf) +} + +func TestGetFee(t *testing.T) { + t.Parallel() + b := Bitstamp{} + if resp := b.GetFee("BTCUSD"); resp != 0 { + t.Error("Test Failed - GetFee() error") + } + if resp := b.GetFee("BTCEUR"); resp != 0 { + t.Error("Test Failed - GetFee() error") + } + if resp := b.GetFee("XRPEUR"); resp != 0 { + t.Error("Test Failed - GetFee() error") + } + if resp := b.GetFee("XRPUSD"); resp != 0 { + t.Error("Test Failed - GetFee() error") + } + if resp := b.GetFee("EURUSD"); resp != 0 { + t.Error("Test Failed - GetFee() error") + } + if resp := b.GetFee("bla"); resp != 0 { + t.Error("Test Failed - GetFee() error") + } +} + +func TestGetTicker(t *testing.T) { + t.Parallel() + b := Bitstamp{} + _, err := b.GetTicker("BTCUSD", false) + if err != nil { + t.Error("Test Failed - GetTicker() error", err) + } + _, err = b.GetTicker("BTCUSD", true) + if err != nil { + t.Error("Test Failed - GetTicker() error", err) + } +} + +func TestGetOrderbook(t *testing.T) { + t.Parallel() + b := Bitstamp{} + _, err := b.GetOrderbook("BTCUSD") + if err != nil { + t.Error("Test Failed - GetOrderbook() error", err) + } +} + +func TestGetTransactions(t *testing.T) { + t.Parallel() + b := Bitstamp{} + + value := url.Values{} + value.Set("time", "hour") + + _, err := b.GetTransactions("BTCUSD", value) + if err != nil { + t.Error("Test Failed - GetTransactions() error", err) + } + _, err = b.GetTransactions("wigwham", value) + if err == nil { + t.Error("Test Failed - GetTransactions() error") + } +} + +func TestGetEURUSDConversionRate(t *testing.T) { + t.Parallel() + b := Bitstamp{} + _, err := b.GetEURUSDConversionRate() + if err != nil { + t.Error("Test Failed - GetEURUSDConversionRate() error", err) + } +} + +func TestGetBalance(t *testing.T) { + t.Parallel() + b := Bitstamp{} + b.APIKey = apiKey + b.APISecret = apiSecret + b.ClientID = customerID + + _, err := b.GetBalance() + if err == nil { + t.Error("Test Failed - GetBalance() error", err) + } +} + +func TestGetUserTransactions(t *testing.T) { + t.Parallel() + b := Bitstamp{} + b.APIKey = apiKey + b.APISecret = apiSecret + b.ClientID = customerID + + _, err := b.GetUserTransactions("") + if err == nil { + t.Error("Test Failed - GetUserTransactions() error", err) + } + + _, err = b.GetUserTransactions("btcusd") + if err == nil { + t.Error("Test Failed - GetUserTransactions() error", err) + } +} + +func TestGetOpenOrders(t *testing.T) { + t.Parallel() + b := Bitstamp{} + b.APIKey = apiKey + b.APISecret = apiSecret + b.ClientID = customerID + + _, err := b.GetOpenOrders("btcusd") + if err == nil { + t.Error("Test Failed - GetOpenOrders() error", err) + } + _, err = b.GetOpenOrders("wigwham") + if err == nil { + t.Error("Test Failed - GetOpenOrders() error") + } +} + +func TestGetOrderStatus(t *testing.T) { + t.Parallel() + b := Bitstamp{} + b.APIKey = apiKey + b.APISecret = apiSecret + b.ClientID = customerID + + _, err := b.GetOrderStatus(1337) + if err == nil { + t.Error("Test Failed - GetOpenOrders() error") + } +} + +func TestCancelOrder(t *testing.T) { + t.Parallel() + b := Bitstamp{} + b.APIKey = apiKey + b.APISecret = apiSecret + b.ClientID = customerID + + resp, err := b.CancelOrder(1337) + if err == nil || resp != false { + t.Error("Test Failed - CancelOrder() error") + } +} + +func TestCancelAllOrders(t *testing.T) { + t.Parallel() + b := Bitstamp{} + b.APIKey = apiKey + b.APISecret = apiSecret + b.ClientID = customerID + + _, err := b.CancelAllOrders() + if err == nil { + t.Error("Test Failed - CancelAllOrders() error", err) + } +} + +func TestPlaceOrder(t *testing.T) { + t.Parallel() + b := Bitstamp{} + b.APIKey = apiKey + b.APISecret = apiSecret + b.ClientID = customerID + + _, err := b.PlaceOrder("btcusd", 0.01, 1, true, true) + if err == nil { + t.Error("Test Failed - PlaceOrder() error") + } + _, err = b.PlaceOrder("btcusd", 0.01, 1, true, false) + if err == nil { + t.Error("Test Failed - PlaceOrder() error") + } + _, err = b.PlaceOrder("btcusd", 0.01, 1, false, false) + if err == nil { + t.Error("Test Failed - PlaceOrder() error") + } + _, err = b.PlaceOrder("wigwham", 0.01, 1, false, false) + if err == nil { + t.Error("Test Failed - PlaceOrder() error") + } +} + +func TestGetWithdrawalRequests(t *testing.T) { + t.Parallel() + b := Bitstamp{} + b.APIKey = apiKey + b.APISecret = apiSecret + b.ClientID = customerID + + _, err := b.GetWithdrawalRequests(0) + if err == nil { + t.Error("Test Failed - GetWithdrawalRequests() error", err) + } + _, err = b.GetWithdrawalRequests(-1) + if err == nil { + t.Error("Test Failed - GetWithdrawalRequests() error") + } +} + +func TestCryptoWithdrawal(t *testing.T) { + t.Parallel() + b := Bitstamp{} + b.APIKey = apiKey + b.APISecret = apiSecret + b.ClientID = customerID + + _, err := b.CryptoWithdrawal(0, "bla", "btc", "", true) + if err == nil { + t.Error("Test Failed - CryptoWithdrawal() error", err) + } + _, err = b.CryptoWithdrawal(0, "bla", "btc", "", false) + if err == nil { + t.Error("Test Failed - CryptoWithdrawal() error", err) + } + _, err = b.CryptoWithdrawal(0, "bla", "ltc", "", false) + if err == nil { + t.Error("Test Failed - CryptoWithdrawal() error", err) + } + _, err = b.CryptoWithdrawal(0, "bla", "eth", "", false) + if err == nil { + t.Error("Test Failed - CryptoWithdrawal() error", err) + } + _, err = b.CryptoWithdrawal(0, "bla", "xrp", "someplace", false) + if err == nil { + t.Error("Test Failed - CryptoWithdrawal() error", err) + } + _, err = b.CryptoWithdrawal(0, "bla", "ding!", "", false) + if err == nil { + t.Error("Test Failed - CryptoWithdrawal() error", err) + } +} + +func TestGetBitcoinDepositAddress(t *testing.T) { + t.Parallel() + b := Bitstamp{} + b.APIKey = apiKey + b.APISecret = apiSecret + b.ClientID = customerID + + _, err := b.GetCryptoDepositAddress("btc") + if err == nil { + t.Error("Test Failed - GetCryptoDepositAddress() error", err) + } + _, err = b.GetCryptoDepositAddress("LTc") + if err == nil { + t.Error("Test Failed - GetCryptoDepositAddress() error", err) + } + _, err = b.GetCryptoDepositAddress("eth") + if err == nil { + t.Error("Test Failed - GetCryptoDepositAddress() error", err) + } + _, err = b.GetCryptoDepositAddress("xrp") + if err == nil { + t.Error("Test Failed - GetCryptoDepositAddress() error", err) + } + _, err = b.GetCryptoDepositAddress("wigwham") + if err == nil { + t.Error("Test Failed - GetCryptoDepositAddress() error") + } +} + +func TestGetUnconfirmedBitcoinDeposits(t *testing.T) { + t.Parallel() + b := Bitstamp{} + b.APIKey = apiKey + b.APISecret = apiSecret + b.ClientID = customerID + + _, err := b.GetUnconfirmedBitcoinDeposits() + if err == nil { + t.Error("Test Failed - GetUnconfirmedBitcoinDeposits() error", err) + } +} + +func TestTransferAccountBalance(t *testing.T) { + t.Parallel() + b := Bitstamp{} + b.APIKey = apiKey + b.APISecret = apiSecret + b.ClientID = customerID + + _, err := b.TransferAccountBalance(1, "", "", true) + if err == nil { + t.Error("Test Failed - TransferAccountBalance() error", err) + } + _, err = b.TransferAccountBalance(1, "btc", "", false) + if err == nil { + t.Error("Test Failed - TransferAccountBalance() error", err) + } +} diff --git a/exchanges/bitstamp/bitstamp_types.go b/exchanges/bitstamp/bitstamp_types.go index bc90479d8c6..d029b62f414 100644 --- a/exchanges/bitstamp/bitstamp_types.go +++ b/exchanges/bitstamp/bitstamp_types.go @@ -1,6 +1,7 @@ package bitstamp -type BitstampTicker struct { +// Ticker holds ticker information +type Ticker struct { Last float64 `json:"last,string"` High float64 `json:"high,string"` Low float64 `json:"low,string"` @@ -12,38 +13,21 @@ type BitstampTicker struct { Open float64 `json:"open,string"` } -type BitstampBalances struct { - BTCReserved float64 `json:"btc_reserved,string"` - BTCEURFee float64 `json:"btceur_fee,string"` - BTCAvailable float64 `json:"btc_available,string"` - XRPAvailable float64 `json:"xrp_available,string"` - EURAvailable float64 `json:"eur_available,string"` - USDReserved float64 `json:"usd_reserved,string"` - EURReserved float64 `json:"eur_reserved,string"` - XRPEURFee float64 `json:"xrpeur_fee,string"` - XRPReserved float64 `json:"xrp_reserved,string"` - XRPBalance float64 `json:"xrp_balance,string"` - XRPUSDFee float64 `json:"xrpusd_fee,string"` - EURBalance float64 `json:"eur_balance,string"` - BTCBalance float64 `json:"btc_balance,string"` - BTCUSDFee float64 `json:"btcusd_fee,string"` - USDBalance float64 `json:"usd_balance,string"` - USDAvailable float64 `json:"usd_available,string"` - EURUSDFee float64 `json:"eurusd_fee,string"` -} - -type BitstampOrderbookBase struct { +// OrderbookBase holds singular price information +type OrderbookBase struct { Price float64 Amount float64 } -type BitstampOrderbook struct { +// Orderbook holds orderbook information +type Orderbook struct { Timestamp int64 `json:"timestamp,string"` - Bids []BitstampOrderbookBase - Asks []BitstampOrderbookBase + Bids []OrderbookBase + Asks []OrderbookBase } -type BitstampTransactions struct { +// Transactions holds transaction data +type Transactions struct { Date int64 `json:"date,string"` TradeID int64 `json:"tid,string"` Price float64 `json:"price,string"` @@ -51,12 +35,37 @@ type BitstampTransactions struct { Amount float64 `json:"amount,string"` } -type BitstampEURUSDConversionRate struct { +// EURUSDConversionRate holds buy sell conversion rate information +type EURUSDConversionRate struct { Buy float64 `json:"buy,string"` Sell float64 `json:"sell,string"` } -type BitstampUserTransactions struct { +// Balances holds full balance information with the supplied APIKEYS +type Balances struct { + USDBalance float64 `json:"usd_balance,string"` + BTCBalance float64 `json:"btc_balance,string"` + EURBalance float64 `json:"eur_balance,string"` + XRPBalance float64 `json:"xrp_balance,string"` + USDReserved float64 `json:"usd_reserved,string"` + BTCReserved float64 `json:"btc_reserved,string"` + EURReserved float64 `json:"eur_reserved,string"` + XRPReserved float64 `json:"xrp_reserved,string"` + USDAvailable float64 `json:"usd_available,string"` + BTCAvailable float64 `json:"btc_available,string"` + EURAvailable float64 `json:"eur_available,string"` + XRPAvailable float64 `json:"xrp_available,string"` + BTCUSDFee float64 `json:"btcusd_fee,string"` + BTCEURFee float64 `json:"btceur_fee,string"` + EURUSDFee float64 `json:"eurusd_fee,string"` + XRPUSDFee float64 `json:"xrpusd_fee,string"` + XRPEURFee float64 `json:"xrpeur_fee,string"` + XRPBTCFee float64 `json:"xrpbtc_fee,string"` + Fee float64 `json:"fee,string"` +} + +// UserTransactions holds user transaction information +type UserTransactions struct { Date string `json:"datetime"` TransID int64 `json:"id"` Type int `json:"type,string"` @@ -69,7 +78,8 @@ type BitstampUserTransactions struct { OrderID int64 `json:"order_id"` } -type BitstampOrder struct { +// Order holds current open order data +type Order struct { ID int64 `json:"id"` Date string `json:"datetime"` Type int `json:"type"` @@ -77,7 +87,8 @@ type BitstampOrder struct { Amount float64 `json:"amount"` } -type BitstampOrderStatus struct { +// OrderStatus holds order status information +type OrderStatus struct { Status string Transactions []struct { TradeID int64 `json:"tid"` @@ -88,22 +99,30 @@ type BitstampOrderStatus struct { } } -type BitstampWithdrawalRequests struct { - OrderID int64 `json:"id"` - Date string `json:"datetime"` - Type int `json:"type"` - Amount float64 `json:"amount,string"` - Status int `json:"status"` - Data interface{} +// WithdrawalRequests holds request information on withdrawals +type WithdrawalRequests struct { + OrderID int64 `json:"id"` + Date string `json:"datetime"` + Type int `json:"type"` + Amount float64 `json:"amount,string"` + Status int `json:"status"` + Data interface{} + Address string `json:"address"` // Bitcoin withdrawals only + TransactionID string `json:"transaction_id"` // Bitcoin withdrawals only } -type BitstampUnconfirmedBTCTransactions struct { +// UnconfirmedBTCTransactions holds address information about unconfirmed +// transactions +type UnconfirmedBTCTransactions struct { Amount float64 `json:"amount,string"` Address string `json:"address"` Confirmations int `json:"confirmations"` } -type BitstampXRPDepositResponse struct { - Address string `json:"address"` - DestinationTag int64 `json:"destination_tag"` +// CaptureError is used to capture unmarshalled errors +type CaptureError struct { + Status interface{} `json:"status"` + Reason interface{} `json:"reason"` + Code interface{} `json:"code"` + Error interface{} `json:"error"` } diff --git a/exchanges/bitstamp/bitstamp_websocket.go b/exchanges/bitstamp/bitstamp_websocket.go index 6958d1a0e9b..35748654107 100644 --- a/exchanges/bitstamp/bitstamp_websocket.go +++ b/exchanges/bitstamp/bitstamp_websocket.go @@ -7,23 +7,28 @@ import ( "github.com/toorop/go-pusher" ) -type BitstampPusherOrderbook struct { +// PusherOrderbook holds order book information to be pushed +type PusherOrderbook struct { Asks [][]string `json:"asks"` Bids [][]string `json:"bids"` } -type BitstampPusherTrade struct { + +// PusherTrade holds trade information to be pushed +type PusherTrade struct { Price float64 `json:"price"` Amount float64 `json:"amount"` ID int64 `json:"id"` } const ( - BITSTAMP_PUSHER_KEY = "de504dc5763aeef9ff52" + // BitstampPusherKey holds the current pusher key + BitstampPusherKey = "de504dc5763aeef9ff52" ) +// PusherClient starts the push mechanism func (b *Bitstamp) PusherClient() { for b.Enabled && b.Websocket { - pusherClient, err := pusher.NewClient(BITSTAMP_PUSHER_KEY) + pusherClient, err := pusher.NewClient(BitstampPusherKey) if err != nil { log.Printf("%s Unable to connect to Websocket. Error: %s\n", b.GetName(), err) continue @@ -55,13 +60,13 @@ func (b *Bitstamp) PusherClient() { for b.Websocket { select { case data := <-dataChannelTrade: - result := BitstampPusherOrderbook{} + result := PusherOrderbook{} err := common.JSONDecode([]byte(data.Data), &result) if err != nil { log.Println(err) } case trade := <-tradeChannelTrade: - result := BitstampPusherTrade{} + result := PusherTrade{} err := common.JSONDecode([]byte(trade.Data), &result) if err != nil { log.Println(err) diff --git a/exchanges/bitstamp/bitstamp_wrapper.go b/exchanges/bitstamp/bitstamp_wrapper.go index 76710f91b07..c4988c781b8 100644 --- a/exchanges/bitstamp/bitstamp_wrapper.go +++ b/exchanges/bitstamp/bitstamp_wrapper.go @@ -6,16 +6,18 @@ 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/stats" "github.com/thrasher-/gocryptotrader/exchanges/ticker" ) +// Start starts a new go routine run func (b *Bitstamp) Start() { go b.Run() } +// Run starts a new websocket connection runs a new go routine pusher func (b *Bitstamp) Run() { if b.Verbose { log.Printf("%s Websocket: %s.", b.GetName(), common.IsEnabled(b.Websocket)) @@ -44,6 +46,7 @@ func (b *Bitstamp) Run() { } } +// GetTickerPrice returns ticker price information func (b *Bitstamp) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) { tickerNew, err := ticker.GetTicker(b.GetName(), p) if err == nil { @@ -67,6 +70,7 @@ func (b *Bitstamp) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, erro return tickerPrice, nil } +// GetOrderbookEx returns base orderbook information func (b *Bitstamp) GetOrderbookEx(p pair.CurrencyPair) (orderbook.OrderbookBase, error) { ob, err := orderbook.GetOrderbook(b.GetName(), p) if err == nil { @@ -94,11 +98,12 @@ func (b *Bitstamp) GetOrderbookEx(p pair.CurrencyPair) (orderbook.OrderbookBase, return orderBook, nil } -//GetExchangeAccountInfo : Retrieves balances for all enabled currencies for the Bitstamp exchange -func (e *Bitstamp) GetExchangeAccountInfo() (exchange.AccountInfo, error) { +// GetExchangeAccountInfo retrieves balances for all enabled currencies for the +// Bitstamp exchange +func (b *Bitstamp) GetExchangeAccountInfo() (exchange.AccountInfo, error) { var response exchange.AccountInfo - response.ExchangeName = e.GetName() - accountBalance, err := e.GetBalance() + response.ExchangeName = b.GetName() + accountBalance, err := b.GetBalance() if err != nil { return response, err } diff --git a/exchanges/bittrex/bittrex_test.go b/exchanges/bittrex/bittrex_test.go index adfb56ef417..32f7786fa3d 100644 --- a/exchanges/bittrex/bittrex_test.go +++ b/exchanges/bittrex/bittrex_test.go @@ -13,6 +13,7 @@ const ( ) func TestSetDefaults(t *testing.T) { + t.Parallel() b := Bittrex{} b.SetDefaults() if b.GetName() != "Bittrex" { @@ -21,6 +22,7 @@ func TestSetDefaults(t *testing.T) { } func TestSetup(t *testing.T) { + t.Parallel() exch := config.ExchangeConfig{ Name: "Bittrex", APIKey: apiKey, @@ -39,6 +41,7 @@ func TestSetup(t *testing.T) { } func TestGetMarkets(t *testing.T) { + t.Parallel() obj := Bittrex{} _, err := obj.GetMarkets() if err != nil { @@ -47,6 +50,7 @@ func TestGetMarkets(t *testing.T) { } func TestGetCurrencies(t *testing.T) { + t.Parallel() obj := Bittrex{} _, err := obj.GetCurrencies() if err != nil { @@ -55,6 +59,7 @@ func TestGetCurrencies(t *testing.T) { } func TestGetTicker(t *testing.T) { + t.Parallel() invalid := "" btc := "btc-ltc" doge := "btc-DOGE" @@ -75,6 +80,7 @@ func TestGetTicker(t *testing.T) { } func TestGetMarketSummaries(t *testing.T) { + t.Parallel() obj := Bittrex{} _, err := obj.GetMarketSummaries() if err != nil { @@ -83,6 +89,7 @@ func TestGetMarketSummaries(t *testing.T) { } func TestGetMarketSummary(t *testing.T) { + t.Parallel() pairOne := "BTC-LTC" invalid := "WigWham" @@ -98,6 +105,7 @@ func TestGetMarketSummary(t *testing.T) { } func TestGetOrderbook(t *testing.T) { + t.Parallel() obj := Bittrex{} _, err := obj.GetOrderbook("btc-ltc") if err != nil { @@ -110,6 +118,7 @@ func TestGetOrderbook(t *testing.T) { } func TestGetMarketHistory(t *testing.T) { + t.Parallel() obj := Bittrex{} _, err := obj.GetMarketHistory("btc-ltc") if err != nil { @@ -122,6 +131,7 @@ func TestGetMarketHistory(t *testing.T) { } func TestPlaceBuyLimit(t *testing.T) { + t.Parallel() obj := Bittrex{} obj.APIKey = apiKey obj.APISecret = apiSecret @@ -132,6 +142,7 @@ func TestPlaceBuyLimit(t *testing.T) { } func TestPlaceSellLimit(t *testing.T) { + t.Parallel() obj := Bittrex{} obj.APIKey = apiKey obj.APISecret = apiSecret @@ -142,6 +153,7 @@ func TestPlaceSellLimit(t *testing.T) { } func TestGetOpenOrders(t *testing.T) { + t.Parallel() obj := Bittrex{} obj.APIKey = apiKey obj.APISecret = apiSecret @@ -156,6 +168,7 @@ func TestGetOpenOrders(t *testing.T) { } func TestCancelOrder(t *testing.T) { + t.Parallel() obj := Bittrex{} obj.APIKey = apiKey obj.APISecret = apiSecret @@ -166,6 +179,7 @@ func TestCancelOrder(t *testing.T) { } func TestGetAccountBalances(t *testing.T) { + t.Parallel() obj := Bittrex{} obj.APIKey = apiKey obj.APISecret = apiSecret @@ -176,6 +190,7 @@ func TestGetAccountBalances(t *testing.T) { } func TestGetAccountBalanceByCurrency(t *testing.T) { + t.Parallel() obj := Bittrex{} obj.APIKey = apiKey obj.APISecret = apiSecret @@ -186,6 +201,7 @@ func TestGetAccountBalanceByCurrency(t *testing.T) { } func TestGetDepositAddress(t *testing.T) { + t.Parallel() obj := Bittrex{} obj.APIKey = apiKey obj.APISecret = apiSecret @@ -196,6 +212,7 @@ func TestGetDepositAddress(t *testing.T) { } func TestWithdraw(t *testing.T) { + t.Parallel() obj := Bittrex{} obj.APIKey = apiKey obj.APISecret = apiSecret @@ -206,6 +223,7 @@ func TestWithdraw(t *testing.T) { } func TestGetOrder(t *testing.T) { + t.Parallel() obj := Bittrex{} obj.APIKey = apiKey obj.APISecret = apiSecret @@ -220,6 +238,7 @@ func TestGetOrder(t *testing.T) { } func TestGetOrderHistory(t *testing.T) { + t.Parallel() obj := Bittrex{} obj.APIKey = apiKey obj.APISecret = apiSecret @@ -233,7 +252,8 @@ func TestGetOrderHistory(t *testing.T) { } } -func TestGetWithdrawalHistory(t *testing.T) { +func TestGetWithdrawelHistory(t *testing.T) { + t.Parallel() obj := Bittrex{} obj.APIKey = apiKey obj.APISecret = apiSecret @@ -248,6 +268,7 @@ func TestGetWithdrawalHistory(t *testing.T) { } func TestGetDepositHistory(t *testing.T) { + t.Parallel() obj := Bittrex{} obj.APIKey = apiKey obj.APISecret = apiSecret