Merge branch 'test'

# Conflicts:
#	exchanges/btcmarkets/btcmarkets.go
This commit is contained in:
Adrian Gallagher
2017-08-28 12:39:57 +10:00
18 changed files with 1372 additions and 726 deletions

View File

@@ -2,7 +2,7 @@ language: go
go:
- 1.8.x
- master
#- master
before_install:
- go get -t -v ./...

View File

@@ -1,25 +0,0 @@
package anx
import (
"testing"
)
func TestStart(t *testing.T) {
}
func TestRun(t *testing.T) {
}
func TestGetTickerPrice(t *testing.T) {
}
func TestGetOrderbookEx(t *testing.T) {
}
func TestGetExchangeAccountInfo(t *testing.T) {
}

View File

@@ -17,74 +17,70 @@ const (
testAPISecret = ""
)
var b Bitfinex
func TestSetDefaults(t *testing.T) {
t.Parallel()
b.SetDefaults()
setDefaults := Bitfinex{}
setDefaults.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 {

View File

@@ -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
@@ -61,6 +66,7 @@ func (b *Bitstamp) SetDefaults() {
b.ConfigCurrencyPairFormat.Uppercase = true
}
// Setup sets configuration values to bitstamp
func (b *Bitstamp) Setup(exch config.ExchangeConfig) {
if !exch.Enabled {
b.SetEnabled(false)
@@ -81,8 +87,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":
@@ -98,39 +105,50 @@ func (b *Bitstamp) GetFee(currency string) float64 {
}
}
func (b *Bitstamp) GetTicker(currency string, hourly bool) (BitstampTicker, error) {
tickerEndpoint := BITSTAMP_API_TICKER
// GetTicker returns ticker information
func (b *Bitstamp) GetTicker(currency string, hourly bool) (Ticker, error) {
response := Ticker{}
tickerEndpoint := bitstampAPITicker
if hourly {
tickerEndpoint = BITSTAMP_API_TICKER_HOURLY
tickerEndpoint = bitstampAPITickerHourly
}
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)
if err != nil {
return ticker, err
}
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 {
@@ -144,7 +162,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 {
@@ -158,44 +176,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"`
@@ -208,25 +231,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)
@@ -236,14 +263,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)
@@ -257,184 +284,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)
if err != nil {
return response, err
}
return response, nil
return response,
b.SendAuthenticatedHTTPRequest(path, true, req, &response)
}
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
// 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 resp, nil
value := url.Values{}
value.Set("timedelta", strconv.FormatInt(timedelta, 10))
if timedelta == 0 {
value = url.Values{}
}
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
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 resp.ID, nil
return resp.ID,
errors.New("incorrect symbol")
}
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
}
return true, nil
}
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, nil
return resp.Address, errors.New("incorrect cryptocurrency string")
}
// GetUnconfirmedBitcoinDeposits returns unconfirmed transactions
func (b *Bitstamp) GetUnconfirmedBitcoinDeposits() ([]UnconfirmedBTCTransactions, error) {
response := []UnconfirmedBTCTransactions{}
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
}
@@ -442,39 +464,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)
@@ -496,9 +486,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 {
@@ -517,11 +507,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)
}

View File

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

View File

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

View File

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

View File

@@ -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))
@@ -45,6 +47,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 {
@@ -68,6 +71,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 {
@@ -95,11 +99,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
}

View File

@@ -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

View File

@@ -15,37 +15,39 @@ import (
)
const (
BTCC_API_URL = "https://api.btcchina.com/"
BTCC_API_AUTHENTICATED_METHOD = "api_trade_v1.php"
BTCC_API_VER = "2.0.1.3"
BTCC_ORDER_BUY = "buyOrder2"
BTCC_ORDER_SELL = "sellOrder2"
BTCC_ORDER_CANCEL = "cancelOrder"
BTCC_ICEBERG_BUY = "buyIcebergOrder"
BTCC_ICEBERG_SELL = "sellIcebergOrder"
BTCC_ICEBERG_ORDER = "getIcebergOrder"
BTCC_ICEBERG_ORDERS = "getIcebergOrders"
BTCC_ICEBERG_CANCEL = "cancelIcebergOrder"
BTCC_ACCOUNT_INFO = "getAccountInfo"
BTCC_DEPOSITS = "getDeposits"
BTCC_MARKETDEPTH = "getMarketDepth2"
BTCC_ORDER = "getOrder"
BTCC_ORDERS = "getOrders"
BTCC_TRANSACTIONS = "getTransactions"
BTCC_WITHDRAWAL = "getWithdrawal"
BTCC_WITHDRAWALS = "getWithdrawals"
BTCC_WITHDRAWAL_REQUEST = "requestWithdrawal"
BTCC_STOPORDER_BUY = "buyStopOrder"
BTCC_STOPORDER_SELL = "sellStopOrder"
BTCC_STOPORDER_CANCEL = "cancelStopOrder"
BTCC_STOPORDER = "getStopOrder"
BTCC_STOPORDERS = "getStopOrders"
btccAPIUrl = "https://api.btcchina.com/"
btccAPIAuthenticatedMethod = "api_trade_v1.php"
btccAPIVersion = "2.0.1.3"
btccOrderBuy = "buyOrder2"
btccOrderSell = "sellOrder2"
btccOrderCancel = "cancelOrder"
btccIcebergBuy = "buyIcebergOrder"
btccIcebergSell = "sellIcebergOrder"
btccIcebergOrder = "getIcebergOrder"
btccIcebergOrders = "getIcebergOrders"
btccIcebergCancel = "cancelIcebergOrder"
btccAccountInfo = "getAccountInfo"
btccDeposits = "getDeposits"
btccMarketdepth = "getMarketDepth2"
btccOrder = "getOrder"
btccOrders = "getOrders"
btccTransactions = "getTransactions"
btccWithdrawal = "getWithdrawal"
btccWithdrawals = "getWithdrawals"
btccWithdrawalRequest = "requestWithdrawal"
btccStoporderBuy = "buyStopOrder"
btccStoporderSell = "sellStopOrder"
btccStoporderCancel = "cancelStopOrder"
btccStoporder = "getStopOrder"
btccStoporders = "getStopOrders"
)
// BTCC is the main overaching type across the BTCC package
type BTCC struct {
exchange.Base
}
// SetDefaults sets default values for the exchange
func (b *BTCC) SetDefaults() {
b.Name = "BTCC"
b.Enabled = false
@@ -59,7 +61,7 @@ func (b *BTCC) SetDefaults() {
b.ConfigCurrencyPairFormat.Uppercase = true
}
//Setup is run on startup to setup exchange with config values
// Setup is run on startup to setup exchange with config values
func (b *BTCC) Setup(exch config.ExchangeConfig) {
if !exch.Enabled {
b.SetEnabled(false)
@@ -80,36 +82,40 @@ func (b *BTCC) Setup(exch config.ExchangeConfig) {
}
}
// GetFee returns the fees associated with transactions
func (b *BTCC) GetFee() float64 {
return b.Fee
}
func (b *BTCC) GetTicker(symbol string) (BTCCTicker, error) {
type Response struct {
Ticker BTCCTicker
}
// GetTicker returns ticker information
// currencyPair - Example "btccny", "ltccny" or "ltcbtc"
func (b *BTCC) GetTicker(currencyPair string) (Ticker, error) {
resp := Response{}
req := fmt.Sprintf("%sdata/ticker?market=%s", BTCC_API_URL, symbol)
err := common.SendHTTPGetRequest(req, true, &resp)
if err != nil {
return BTCCTicker{}, err
}
return resp.Ticker, nil
req := fmt.Sprintf("%sdata/ticker?market=%s", btccAPIUrl, currencyPair)
return resp.Ticker, common.SendHTTPGetRequest(req, true, &resp)
}
func (b *BTCC) GetTradesLast24h(symbol string) bool {
req := fmt.Sprintf("%sdata/trades?market=%s", BTCC_API_URL, symbol)
err := common.SendHTTPGetRequest(req, true, nil)
if err != nil {
log.Println(err)
return false
}
return true
// GetTradesLast24h returns the trades executed on the exchange over the past
// 24 hours by currency pair
// currencyPair - Example "btccny", "ltccny" or "ltcbtc"
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)
}
func (b *BTCC) GetTradeHistory(symbol string, limit, sinceTid int64, time time.Time) bool {
req := fmt.Sprintf("%sdata/historydata?market=%s", BTCC_API_URL, symbol)
// GetTradeHistory returns trade history data
// currencyPair - Example "btccny", "ltccny" or "ltcbtc"
// limit - limits the returned trades example "10"
// sinceTid - returns trade records starting from id supplied example "5000"
// time - returns trade records starting from unix time 1406794449
func (b *BTCC) GetTradeHistory(currencyPair string, limit, sinceTid int64, time time.Time) ([]Trade, error) {
trades := []Trade{}
req := fmt.Sprintf("%sdata/historydata?market=%s", btccAPIUrl, currencyPair)
v := url.Values{}
if limit > 0 {
@@ -123,37 +129,33 @@ func (b *BTCC) GetTradeHistory(symbol string, limit, sinceTid int64, time time.T
}
req = common.EncodeURLValues(req, v)
err := common.SendHTTPGetRequest(req, true, nil)
if err != nil {
log.Println(err)
return false
}
return true
return trades, common.SendHTTPGetRequest(req, true, &trades)
}
func (b *BTCC) GetOrderBook(symbol string, limit int) (BTCCOrderbook, error) {
result := BTCCOrderbook{}
req := fmt.Sprintf("%sdata/orderbook?market=%s&limit=%d", BTCC_API_URL, symbol, limit)
err := common.SendHTTPGetRequest(req, true, &result)
if err != nil {
return BTCCOrderbook{}, err
// GetOrderBook returns current market order book
// currencyPair - Example "btccny", "ltccny" or "ltcbtc"
// limit - limits the returned trades example "10" if 0 will return full
// orderbook
func (b *BTCC) GetOrderBook(currencyPair string, limit int) (Orderbook, error) {
result := Orderbook{}
req := fmt.Sprintf("%sdata/orderbook?market=%s&limit=%d", btccAPIUrl, currencyPair, limit)
if limit == 0 {
req = fmt.Sprintf("%sdata/orderbook?market=%s", btccAPIUrl, currencyPair)
}
return result, nil
return result, common.SendHTTPGetRequest(req, true, &result)
}
func (b *BTCC) GetAccountInfo(infoType string) {
func (b *BTCC) GetAccountInfo(infoType string) error {
params := make([]interface{}, 0)
if len(infoType) > 0 {
params = append(params, infoType)
}
err := b.SendAuthenticatedHTTPRequest(BTCC_ACCOUNT_INFO, params)
if err != nil {
log.Println(err)
}
return b.SendAuthenticatedHTTPRequest(btccAccountInfo, params)
}
func (b *BTCC) PlaceOrder(buyOrder bool, price, amount float64, market string) {
@@ -165,9 +167,9 @@ func (b *BTCC) PlaceOrder(buyOrder bool, price, amount float64, market string) {
params = append(params, market)
}
req := BTCC_ORDER_BUY
req := btccOrderBuy
if !buyOrder {
req = BTCC_ORDER_SELL
req = btccOrderSell
}
err := b.SendAuthenticatedHTTPRequest(req, params)
@@ -185,7 +187,7 @@ func (b *BTCC) CancelOrder(orderID int64, market string) {
params = append(params, market)
}
err := b.SendAuthenticatedHTTPRequest(BTCC_ORDER_CANCEL, params)
err := b.SendAuthenticatedHTTPRequest(btccOrderCancel, params)
if err != nil {
log.Println(err)
@@ -200,7 +202,7 @@ func (b *BTCC) GetDeposits(currency string, pending bool) {
params = append(params, pending)
}
err := b.SendAuthenticatedHTTPRequest(BTCC_DEPOSITS, params)
err := b.SendAuthenticatedHTTPRequest(btccDeposits, params)
if err != nil {
log.Println(err)
@@ -218,7 +220,7 @@ func (b *BTCC) GetMarketDepth(market string, limit int64) {
params = append(params, market)
}
err := b.SendAuthenticatedHTTPRequest(BTCC_MARKETDEPTH, params)
err := b.SendAuthenticatedHTTPRequest(btccMarketdepth, params)
if err != nil {
log.Println(err)
@@ -237,7 +239,7 @@ func (b *BTCC) GetOrder(orderID int64, market string, detailed bool) {
params = append(params, detailed)
}
err := b.SendAuthenticatedHTTPRequest(BTCC_ORDER, params)
err := b.SendAuthenticatedHTTPRequest(btccOrder, params)
if err != nil {
log.Println(err)
@@ -271,7 +273,7 @@ func (b *BTCC) GetOrders(openonly bool, market string, limit, offset, since int6
params = append(params, detailed)
}
err := b.SendAuthenticatedHTTPRequest(BTCC_ORDERS, params)
err := b.SendAuthenticatedHTTPRequest(btccOrders, params)
if err != nil {
log.Println(err)
@@ -301,7 +303,7 @@ func (b *BTCC) GetTransactions(transType string, limit, offset, since int64, sin
params = append(params, sinceType)
}
err := b.SendAuthenticatedHTTPRequest(BTCC_TRANSACTIONS, params)
err := b.SendAuthenticatedHTTPRequest(btccTransactions, params)
if err != nil {
log.Println(err)
@@ -316,7 +318,7 @@ func (b *BTCC) GetWithdrawal(withdrawalID int64, currency string) {
params = append(params, currency)
}
err := b.SendAuthenticatedHTTPRequest(BTCC_WITHDRAWAL, params)
err := b.SendAuthenticatedHTTPRequest(btccWithdrawal, params)
if err != nil {
log.Println(err)
@@ -331,7 +333,7 @@ func (b *BTCC) GetWithdrawals(currency string, pending bool) {
params = append(params, pending)
}
err := b.SendAuthenticatedHTTPRequest(BTCC_WITHDRAWALS, params)
err := b.SendAuthenticatedHTTPRequest(btccWithdrawals, params)
if err != nil {
log.Println(err)
@@ -343,7 +345,7 @@ func (b *BTCC) RequestWithdrawal(currency string, amount float64) {
params = append(params, currency)
params = append(params, amount)
err := b.SendAuthenticatedHTTPRequest(BTCC_WITHDRAWAL_REQUEST, params)
err := b.SendAuthenticatedHTTPRequest(btccWithdrawalRequest, params)
if err != nil {
log.Println(err)
@@ -361,9 +363,9 @@ func (b *BTCC) IcebergOrder(buyOrder bool, price, amount, discAmount, variance f
params = append(params, market)
}
req := BTCC_ICEBERG_BUY
req := btccIcebergBuy
if !buyOrder {
req = BTCC_ICEBERG_SELL
req = btccIcebergSell
}
err := b.SendAuthenticatedHTTPRequest(req, params)
@@ -381,7 +383,7 @@ func (b *BTCC) GetIcebergOrder(orderID int64, market string) {
params = append(params, market)
}
err := b.SendAuthenticatedHTTPRequest(BTCC_ICEBERG_ORDER, params)
err := b.SendAuthenticatedHTTPRequest(btccIcebergOrder, params)
if err != nil {
log.Println(err)
@@ -403,7 +405,7 @@ func (b *BTCC) GetIcebergOrders(limit, offset int64, market string) {
params = append(params, market)
}
err := b.SendAuthenticatedHTTPRequest(BTCC_ICEBERG_ORDERS, params)
err := b.SendAuthenticatedHTTPRequest(btccIcebergOrders, params)
if err != nil {
log.Println(err)
@@ -418,7 +420,7 @@ func (b *BTCC) CancelIcebergOrder(orderID int64, market string) {
params = append(params, market)
}
err := b.SendAuthenticatedHTTPRequest(BTCC_ICEBERG_CANCEL, params)
err := b.SendAuthenticatedHTTPRequest(btccIcebergCancel, params)
if err != nil {
log.Println(err)
@@ -447,9 +449,9 @@ func (b *BTCC) PlaceStopOrder(buyOder bool, stopPrice, price, amount, trailingAm
params = append(params, market)
}
req := BTCC_STOPORDER_BUY
req := btccStoporderBuy
if !buyOder {
req = BTCC_STOPORDER_SELL
req = btccStoporderSell
}
err := b.SendAuthenticatedHTTPRequest(req, params)
@@ -467,7 +469,7 @@ func (b *BTCC) GetStopOrder(orderID int64, market string) {
params = append(params, market)
}
err := b.SendAuthenticatedHTTPRequest(BTCC_STOPORDER, params)
err := b.SendAuthenticatedHTTPRequest(btccStoporder, params)
if err != nil {
log.Println(err)
@@ -501,7 +503,7 @@ func (b *BTCC) GetStopOrders(status, orderType string, stopPrice float64, limit,
params = append(params, market)
}
err := b.SendAuthenticatedHTTPRequest(BTCC_STOPORDERS, params)
err := b.SendAuthenticatedHTTPRequest(btccStoporders, params)
if err != nil {
log.Println(err)
@@ -516,7 +518,7 @@ func (b *BTCC) CancelStopOrder(orderID int64, market string) {
params = append(params, market)
}
err := b.SendAuthenticatedHTTPRequest(BTCC_STOPORDER_CANCEL, params)
err := b.SendAuthenticatedHTTPRequest(btccStoporderCancel, params)
if err != nil {
log.Println(err)
@@ -579,7 +581,7 @@ func (b *BTCC) SendAuthenticatedHTTPRequest(method string, params []interface{})
postData["method"] = method
postData["params"] = params
postData["id"] = 1
apiURL := BTCC_API_URL + BTCC_API_AUTHENTICATED_METHOD
apiURL := btccAPIUrl + btccAPIAuthenticatedMethod
data, err := common.JSONEncode(postData)
if err != nil {

View File

@@ -0,0 +1,79 @@
package btcc
import (
"testing"
"time"
"github.com/thrasher-/gocryptotrader/config"
)
// Please supply your own APIkeys here to do better tests
const (
apiKey = ""
apiSecret = ""
)
var b BTCC
func TestSetDefaults(t *testing.T) {
b.SetDefaults()
}
func TestSetup(t *testing.T) {
conf := config.ExchangeConfig{
Enabled: true,
}
b.Setup(conf)
conf = config.ExchangeConfig{
Enabled: false,
APIKey: apiKey,
APISecret: apiSecret,
}
b.Setup(conf)
}
func TestGetFee(t *testing.T) {
if b.GetFee() != 0 {
t.Error("Test failed - GetFee() error")
}
}
func TestGetTicker(t *testing.T) {
_, err := b.GetTicker("ltccny")
if err != nil {
t.Error("Test failed - GetTicker() error", err)
}
}
func TestGetTradesLast24h(t *testing.T) {
_, err := b.GetTradesLast24h("ltccny")
if err != nil {
t.Error("Test failed - GetTradesLast24h() error", err)
}
}
func TestGetTradeHistory(t *testing.T) {
_, err := b.GetTradeHistory("ltccny", 0, 0, time.Time{})
if err != nil {
t.Error("Test failed - GetTradeHistory() error", err)
}
}
func TestGetOrderBook(t *testing.T) {
_, err := b.GetOrderBook("ltccny", 100)
if err != nil {
t.Error("Test failed - GetOrderBook() error", err)
}
_, err = b.GetOrderBook("ltccny", 0)
if err != nil {
t.Error("Test failed - GetOrderBook() error", err)
}
}
func TestGetAccountInfo(t *testing.T) {
err := b.GetAccountInfo("")
if err == nil {
t.Error("Test failed - GetAccountInfo() error", err)
}
}

View File

@@ -1,19 +1,45 @@
package btcc
type BTCCTicker struct {
High float64 `json:",string"`
Low float64 `json:",string"`
Buy float64 `json:",string"`
Sell float64 `json:",string"`
Last float64 `json:",string"`
Vol float64 `json:",string"`
Date int64
Vwap float64 `json:",string"`
Prev_close float64 `json:",string"`
Open float64 `json:",string"`
// Response is the generalized response type
type Response struct {
Ticker Ticker `json:"ticker"`
BtcCny Ticker `json:"ticker_btccny"`
LtcCny Ticker `json:"ticker_ltccny"`
LtcBtc Ticker `json:"ticker_ltcbtc"`
}
type BTCCProfile struct {
// Ticker holds basic ticker information
type Ticker struct {
High float64 `json:"high,string"`
Low float64 `json:"low,string"`
Buy float64 `json:"buy,string"`
Sell float64 `json:"sell,string"`
Last float64 `json:"last,string"`
Vol float64 `json:"vol,string"`
Date int64 `json:"date"`
Vwap float64 `json:"vwap,string"`
PrevClose float64 `json:"prev_close,string"`
Open float64 `json:"open,string"`
}
// Trade holds executed trade data
type Trade struct {
Date int64 `json:"date,string"`
Price float64 `json:"price"`
Amount float64 `json:"amount"`
TID int64 `json:"tid,string"`
Type string `json:"type"`
}
// Orderbook holds orderbook data
type Orderbook struct {
Bids [][]float64 `json:"bids"`
Asks [][]float64 `json:"asks"`
Date int64 `json:"date"`
}
// Profile holds profile information
type Profile struct {
Username string
TradePasswordEnabled bool `json:"trade_password_enabled,bool"`
OTPEnabled bool `json:"otp_enabled,bool"`
@@ -29,13 +55,8 @@ type BTCCProfile struct {
APIKeyPermission int64 `json:"api_key_permission"`
}
type BTCCOrderbook struct {
Bids [][]float64 `json:"bids"`
Asks [][]float64 `json:"asks"`
Date int64 `json:"date"`
}
type BTCCCurrencyGeneric struct {
// CurrencyGeneric holds currency information
type CurrencyGeneric struct {
Currency string
Symbol string
Amount string
@@ -43,7 +64,8 @@ type BTCCCurrencyGeneric struct {
AmountDecimal float64 `json:"amount_decimal"`
}
type BTCCOrder struct {
// Order holds order information
type Order struct {
ID int64
Type string
Price float64
@@ -52,16 +74,18 @@ type BTCCOrder struct {
AmountOrig float64 `json:"amount_original"`
Date int64
Status string
Detail BTCCOrderDetail
Detail OrderDetail
}
type BTCCOrderDetail struct {
// OrderDetail holds order detail information
type OrderDetail struct {
Dateline int64
Price float64
Amount float64
}
type BTCCWithdrawal struct {
// Withdrawal holds withdrawal transaction information
type Withdrawal struct {
ID int64
Address string
Currency string
@@ -71,7 +95,8 @@ type BTCCWithdrawal struct {
Status string
}
type BTCCDeposit struct {
// Deposit holds deposit address information
type Deposit struct {
ID int64
Address string
Currency string
@@ -80,17 +105,20 @@ type BTCCDeposit struct {
Status string
}
type BTCCBidAsk struct {
// BidAsk holds bid and ask information
type BidAsk struct {
Price float64
Amount float64
}
type BTCCDepth struct {
Bid []BTCCBidAsk
Ask []BTCCBidAsk
// Depth holds order book depth
type Depth struct {
Bid []BidAsk
Ask []BidAsk
}
type BTCCTransaction struct {
// Transaction holds transaction information
type Transaction struct {
ID int64
Type string
BTCAmount float64 `json:"btc_amount"`
@@ -99,7 +127,8 @@ type BTCCTransaction struct {
Date int64
}
type BTCCIcebergOrder struct {
// IcebergOrder holds iceberg lettuce
type IcebergOrder struct {
ID int64
Type string
Price float64
@@ -112,7 +141,8 @@ type BTCCIcebergOrder struct {
Status string
}
type BTCCStopOrder struct {
// StopOrder holds stop order information
type StopOrder struct {
ID int64
Type string
StopPrice float64 `json:"stop_price"`
@@ -126,19 +156,22 @@ type BTCCStopOrder struct {
OrderID int64 `json:"order_id"`
}
type BTCCWebsocketOrder struct {
// WebsocketOrder holds websocket order information
type WebsocketOrder struct {
Price float64 `json:"price"`
TotalAmount float64 `json:"totalamount"`
Type string `json:"type"`
}
type BTCCWebsocketGroupOrder struct {
Asks []BTCCWebsocketOrder `json:"ask"`
Bids []BTCCWebsocketOrder `json:"bid"`
Market string `json:"market"`
// WebsocketGroupOrder holds websocket group order book information
type WebsocketGroupOrder struct {
Asks []WebsocketOrder `json:"ask"`
Bids []WebsocketOrder `json:"bid"`
Market string `json:"market"`
}
type BTCCWebsocketTrade struct {
// WebsocketTrade holds websocket trade information
type WebsocketTrade struct {
Amount float64 `json:"amount"`
Date float64 `json:"date"`
Market string `json:"market"`
@@ -147,7 +180,8 @@ type BTCCWebsocketTrade struct {
Type string `json:"type"`
}
type BTCCWebsocketTicker struct {
// WebsocketTicker holds websocket ticker information
type WebsocketTicker struct {
Buy float64 `json:"buy"`
Date float64 `json:"date"`
High float64 `json:"high"`

View File

@@ -56,7 +56,7 @@ func (b *BTCC) OnMessage(message []byte, output chan socketio.Message) {
func (b *BTCC) OnTicker(message []byte, output chan socketio.Message) {
type Response struct {
Ticker BTCCWebsocketTicker `json:"ticker"`
Ticker WebsocketTicker `json:"ticker"`
}
var resp Response
err := common.JSONDecode(message, &resp)
@@ -69,7 +69,7 @@ func (b *BTCC) OnTicker(message []byte, output chan socketio.Message) {
func (b *BTCC) OnGroupOrder(message []byte, output chan socketio.Message) {
type Response struct {
GroupOrder BTCCWebsocketGroupOrder `json:"grouporder"`
GroupOrder WebsocketGroupOrder `json:"grouporder"`
}
var resp Response
err := common.JSONDecode(message, &resp)
@@ -81,7 +81,7 @@ func (b *BTCC) OnGroupOrder(message []byte, output chan socketio.Message) {
}
func (b *BTCC) OnTrade(message []byte, output chan socketio.Message) {
trade := BTCCWebsocketTrade{}
trade := WebsocketTrade{}
err := common.JSONDecode(message, &trade)
if err != nil {

View File

@@ -6,7 +6,7 @@ import (
"github.com/thrasher-/gocryptotrader/common"
"github.com/thrasher-/gocryptotrader/currency/pair"
"github.com/thrasher-/gocryptotrader/exchanges"
exchange "github.com/thrasher-/gocryptotrader/exchanges"
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-/gocryptotrader/exchanges/stats"
"github.com/thrasher-/gocryptotrader/exchanges/ticker"

View File

@@ -14,22 +14,36 @@ import (
)
const (
BTCMARKETS_API_URL = "https://api.btcmarkets.net"
BTCMARKETS_API_VERSION = "0"
BTCMARKETS_ACCOUNT_BALANCE = "/account/balance"
BTCMARKETS_ORDER_CREATE = "/order/create"
BTCMARKETS_ORDER_CANCEL = "/order/cancel"
BTCMARKETS_ORDER_HISTORY = "/order/history"
BTCMARKETS_ORDER_OPEN = "/order/open"
BTCMARKETS_ORDER_TRADE_HISTORY = "/order/trade/history"
BTCMARKETS_ORDER_DETAIL = "/order/detail"
btcMarketsAPIURL = "https://api.btcmarkets.net"
btcMarketsAPIVersion = "0"
btcMarketsAccountBalance = "/account/balance"
btcMarketsOrderCreate = "/order/create"
btcMarketsOrderCancel = "/order/cancel"
btcMarketsOrderHistory = "/order/history"
btcMarketsOrderOpen = "/order/open"
btcMarketsOrderTradeHistory = "/order/trade/history"
btcMarketsOrderDetail = "/order/detail"
btcMarketsWithdrawCrypto = "/fundtransfer/withdrawCrypto"
btcMarketsWithdrawAud = "/fundtransfer/withdrawEFT"
//Status Values
orderStatusNew = "New"
orderStatusPlaced = "Placed"
orderStatusFailed = "Failed"
orderStatusError = "Error"
orderStatusCancelled = "Cancelled"
orderStatusPartiallyCancelled = "Partially Cancelled"
orderStatusFullyMatched = "Fully Matched"
orderStatusPartiallyMatched = "Partially Matched"
)
// BTCMarkets is the overarching type across the BTCMarkets package
type BTCMarkets struct {
exchange.Base
Ticker map[string]BTCMarketsTicker
Ticker map[string]Ticker
}
// SetDefaults sets basic defaults
func (b *BTCMarkets) SetDefaults() {
b.Name = "BTC Markets"
b.Enabled = false
@@ -37,13 +51,14 @@ func (b *BTCMarkets) SetDefaults() {
b.Verbose = false
b.Websocket = false
b.RESTPollingDelay = 10
b.Ticker = make(map[string]BTCMarketsTicker)
b.Ticker = make(map[string]Ticker)
b.RequestCurrencyPairFormat.Delimiter = ""
b.RequestCurrencyPairFormat.Uppercase = true
b.ConfigCurrencyPairFormat.Delimiter = ""
b.ConfigCurrencyPairFormat.Uppercase = true
}
// Setup takes in an exchange configuration and sets all paramaters
func (b *BTCMarkets) Setup(exch config.ExchangeConfig) {
if !exch.Enabled {
b.SetEnabled(false)
@@ -64,109 +79,90 @@ func (b *BTCMarkets) Setup(exch config.ExchangeConfig) {
}
}
// GetFee returns the BTCMarkets fee on transactions
func (b *BTCMarkets) GetFee() float64 {
return b.Fee
}
func (b *BTCMarkets) GetTicker(symbol string) (BTCMarketsTicker, error) {
ticker := BTCMarketsTicker{}
path := fmt.Sprintf("/market/%s/AUD/tick", symbol)
err := common.SendHTTPGetRequest(BTCMARKETS_API_URL+path, true, &ticker)
if err != nil {
return BTCMarketsTicker{}, err
}
return ticker, nil
// GetTicker returns a ticker
// symbol - example "btc" or "ltc"
func (b *BTCMarkets) GetTicker(symbol string) (Ticker, error) {
ticker := Ticker{}
path := fmt.Sprintf("/market/%s/AUD/tick", common.StringToUpper(symbol))
return ticker,
common.SendHTTPGetRequest(btcMarketsAPIURL+path, true, &ticker)
}
func (b *BTCMarkets) GetOrderbook(symbol string) (BTCMarketsOrderbook, error) {
orderbook := BTCMarketsOrderbook{}
path := fmt.Sprintf("/market/%s/AUD/orderbook", symbol)
err := common.SendHTTPGetRequest(BTCMARKETS_API_URL+path, true, &orderbook)
if err != nil {
return BTCMarketsOrderbook{}, err
}
return orderbook, nil
// GetOrderbook returns current orderbook
// symbol - example "btc" or "ltc"
func (b *BTCMarkets) GetOrderbook(symbol string) (Orderbook, error) {
orderbook := Orderbook{}
path := fmt.Sprintf("/market/%s/AUD/orderbook", common.StringToUpper(symbol))
return orderbook,
common.SendHTTPGetRequest(btcMarketsAPIURL+path, true, &orderbook)
}
func (b *BTCMarkets) GetTrades(symbol string, values url.Values) ([]BTCMarketsTrade, error) {
trades := []BTCMarketsTrade{}
path := common.EncodeURLValues(fmt.Sprintf("%s/market/%s/AUD/trades", BTCMARKETS_API_URL, symbol), values)
err := common.SendHTTPGetRequest(path, true, &trades)
if err != nil {
return nil, err
}
return trades, nil
// GetTrades returns executed trades on the exchange
// symbol - example "btc" or "ltc"
// values - optional paramater "since" example values.Set(since, "59868345231")
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)
}
func (b *BTCMarkets) Order(currency, instrument string, price, amount int64, orderSide, orderType, clientReq string) (int, error) {
type Order struct {
Currency string `json:"currency"`
Instrument string `json:"instrument"`
Price int64 `json:"price"`
Volume int64 `json:"volume"`
OrderSide string `json:"orderSide"`
OrderType string `json:"ordertype"`
ClientRequestId string `json:"clientRequestId"`
// NewOrder requests a new order and returns an ID
// currency - example "AUD"
// instrument - example "BTC"
// price - example 13000000000 (i.e x 100000000)
// amount - example 100000000 (i.e x 100000000)
// orderside - example "Bid" or "Ask"
// orderType - example "limit"
// clientReq - example "abc-cdf-1000"
func (b *BTCMarkets) NewOrder(currency, instrument string, price, amount int64, orderSide, orderType, clientReq string) (int, error) {
order := OrderToGo{
Currency: common.StringToUpper(currency),
Instrument: common.StringToUpper(instrument),
Price: price * common.SatoshisPerBTC,
Volume: amount * common.SatoshisPerBTC,
OrderSide: orderSide,
OrderType: orderType,
ClientRequestID: clientReq,
}
order := Order{}
order.Currency = currency
order.Instrument = instrument
order.Price = price * common.SatoshisPerBTC
order.Volume = amount * common.SatoshisPerBTC
order.OrderSide = orderSide
order.OrderType = orderType
order.ClientRequestId = clientReq
type Response struct {
Success bool `json:"success"`
ErrorCode int `json:"errorCode"`
ErrorMessage string `json:"errorMessage"`
ID int `json:"id"`
ClientRequestID string `json:"clientRequestId"`
}
var resp Response
err := b.SendAuthenticatedRequest("POST", BTCMARKETS_ORDER_CREATE, order, &resp)
resp := Response{}
err := b.SendAuthenticatedRequest("POST", btcMarketsOrderCreate, order, &resp)
if err != nil {
return 0, err
}
if !resp.Success {
return 0, fmt.Errorf("%s Unable to place order. Error message: %s\n", b.GetName(), resp.ErrorMessage)
return 0, fmt.Errorf("%s Unable to place order. Error message: %s", b.GetName(), resp.ErrorMessage)
}
return resp.ID, nil
}
// CancelOrder cancels an order by its ID
// orderID - id for order example "1337"
func (b *BTCMarkets) CancelOrder(orderID []int64) (bool, error) {
resp := Response{}
type CancelOrder struct {
OrderIDs []int64 `json:"orderIds"`
}
orders := CancelOrder{}
orders.OrderIDs = append(orders.OrderIDs, orderID...)
type Response struct {
Success bool `json:"success"`
ErrorCode int `json:"errorCode"`
ErrorMessage string `json:"errorMessage"`
Responses []struct {
Success bool `json:"success"`
ErrorCode int `json:"errorCode"`
ErrorMessage string `json:"errorMessage"`
ID int64 `json:"id"`
}
ClientRequestID string `json:"clientRequestId"`
}
var resp Response
err := b.SendAuthenticatedRequest("POST", BTCMARKETS_ORDER_CANCEL, orders, &resp)
err := b.SendAuthenticatedRequest("POST", btcMarketsOrderCancel, orders, &resp)
if err != nil {
return false, err
}
if !resp.Success {
return false, fmt.Errorf("%s Unable to cancel order. Error message: %s\n", b.GetName(), resp.ErrorMessage)
return false, fmt.Errorf("%s Unable to cancel order. Error message: %s", b.GetName(), resp.ErrorMessage)
}
ordersToBeCancelled := len(orderID)
@@ -176,39 +172,37 @@ func (b *BTCMarkets) CancelOrder(orderID []int64) (bool, error) {
ordersCancelled++
log.Printf("%s Cancelled order %d.\n", b.GetName(), y.ID)
} else {
log.Printf("%s Unable to cancel order %d. Error message: %s\n", b.GetName(), y.ID, y.ErrorMessage)
log.Printf("%s Unable to cancel order %d. Error message: %s", b.GetName(), y.ID, y.ErrorMessage)
}
}
if ordersCancelled == ordersToBeCancelled {
return true, nil
} else {
return false, fmt.Errorf("%s Unable to cancel order(s).", b.GetName())
}
return false, fmt.Errorf("%s Unable to cancel order(s)", b.GetName())
}
func (b *BTCMarkets) GetOrders(currency, instrument string, limit, since int64, historic bool) ([]BTCMarketsOrder, error) {
// GetOrders returns current order information on the exchange
// currency - example "AUD"
// instrument - example "BTC"
// limit - example "10"
// since - since a time example "33434568724"
// historic - if false just normal Orders open
func (b *BTCMarkets) GetOrders(currency, instrument string, limit, since int64, historic bool) ([]Order, error) {
request := make(map[string]interface{})
request["currency"] = currency
request["instrument"] = instrument
request["currency"] = common.StringToUpper(currency)
request["instrument"] = common.StringToUpper(instrument)
request["limit"] = limit
request["since"] = since
path := BTCMARKETS_ORDER_OPEN
path := btcMarketsOrderOpen
if historic {
path = BTCMARKETS_ORDER_HISTORY
path = btcMarketsOrderHistory
}
type response struct {
Success bool `json:"success"`
ErrorCode int `json:"errorCode"`
ErrorMessage string `json:"errorMessage"`
Orders []BTCMarketsOrder `json:"orders"`
}
resp := Response{}
resp := response{}
err := b.SendAuthenticatedRequest("POST", path, request, &resp)
if err != nil {
return nil, err
}
@@ -231,23 +225,18 @@ func (b *BTCMarkets) GetOrders(currency, instrument string, limit, since int64,
return resp.Orders, nil
}
func (b *BTCMarkets) GetOrderDetail(orderID []int64) ([]BTCMarketsOrder, error) {
// GetOrderDetail returns order information an a specific order
// orderID - example "1337"
func (b *BTCMarkets) GetOrderDetail(orderID []int64) ([]Order, error) {
type OrderDetail struct {
OrderIDs []int64 `json:"orderIds"`
}
orders := OrderDetail{}
orders.OrderIDs = append(orders.OrderIDs, orderID...)
type response struct {
Success bool `json:"success"`
ErrorCode int `json:"errorCode"`
ErrorMessage string `json:"errorMessage"`
Orders []BTCMarketsOrder `json:"orders"`
}
resp := response{}
err := b.SendAuthenticatedRequest("POST", BTCMARKETS_ORDER_DETAIL, orders, &resp)
resp := Response{}
err := b.SendAuthenticatedRequest("POST", btcMarketsOrderDetail, orders, &resp)
if err != nil {
return nil, err
}
@@ -270,10 +259,11 @@ func (b *BTCMarkets) GetOrderDetail(orderID []int64) ([]BTCMarketsOrder, error)
return resp.Orders, nil
}
func (b *BTCMarkets) GetAccountBalance() ([]BTCMarketsAccountBalance, error) {
balance := []BTCMarketsAccountBalance{}
err := b.SendAuthenticatedRequest("GET", BTCMARKETS_ACCOUNT_BALANCE, nil, &balance)
// GetAccountBalance returns the full account balance
func (b *BTCMarkets) GetAccountBalance() ([]AccountBalance, error) {
balance := []AccountBalance{}
err := b.SendAuthenticatedRequest("GET", btcMarketsAccountBalance, nil, &balance)
if err != nil {
return nil, err
}
@@ -286,6 +276,53 @@ func (b *BTCMarkets) GetAccountBalance() ([]BTCMarketsAccountBalance, error) {
return balance, nil
}
// WithdrawCrypto withdraws cryptocurrency into a designated address
func (b *BTCMarkets) WithdrawCrypto(amount int64, currency, address string) (string, error) {
req := WithdrawRequestCrypto{
Amount: amount,
Currency: common.StringToUpper(currency),
Address: address,
}
resp := Response{}
err := b.SendAuthenticatedRequest("POST", btcMarketsWithdrawCrypto, req, &resp)
if err != nil {
return "", err
}
if !resp.Success {
return "", errors.New(resp.ErrorMessage)
}
return resp.Status, nil
}
// WithdrawAUD withdraws AUD into a designated bank address
// Does not return a TxID!
func (b *BTCMarkets) WithdrawAUD(accountName, accountNumber, bankName, bsbNumber, currency string, amount int64) (string, error) {
req := WithdrawRequestAUD{
AccountName: accountName,
AccountNumber: accountNumber,
BankName: bankName,
BSBNumber: bsbNumber,
Amount: amount,
Currency: common.StringToUpper(currency),
}
resp := Response{}
err := b.SendAuthenticatedRequest("POST", btcMarketsWithdrawAud, req, &resp)
if err != nil {
return "", err
}
if !resp.Success {
return "", errors.New(resp.ErrorMessage)
}
return resp.Status, nil
}
// SendAuthenticatedRequest sends an authenticated HTTP request
func (b *BTCMarkets) SendAuthenticatedRequest(reqType, path string, data interface{}, result interface{}) (err error) {
if !b.AuthenticatedAPISupport {
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, b.Name)
@@ -296,7 +333,7 @@ func (b *BTCMarkets) SendAuthenticatedRequest(reqType, path string, data interfa
} else {
b.Nonce.Inc()
}
request := ""
var request string
payload := []byte("")
if data != nil {
@@ -312,7 +349,7 @@ func (b *BTCMarkets) SendAuthenticatedRequest(reqType, path string, data interfa
hmac := common.GetHMAC(common.HashSHA512, []byte(request), []byte(b.APISecret))
if b.Verbose {
log.Printf("Sending %s request to URL %s with params %s\n", reqType, BTCMARKETS_API_URL+path, request)
log.Printf("Sending %s request to URL %s with params %s\n", reqType, btcMarketsAPIURL+path, request)
}
headers := make(map[string]string)
@@ -323,7 +360,7 @@ func (b *BTCMarkets) SendAuthenticatedRequest(reqType, path string, data interfa
headers["timestamp"] = b.Nonce.String()[0:13]
headers["signature"] = common.Base64Encode(hmac)
resp, err := common.SendHTTPRequest(reqType, BTCMARKETS_API_URL+path, headers, bytes.NewBuffer(payload))
resp, err := common.SendHTTPRequest(reqType, btcMarketsAPIURL+path, headers, bytes.NewBuffer(payload))
if err != nil {
return err

View File

@@ -0,0 +1,131 @@
package btcmarkets
import (
"net/url"
"testing"
"github.com/thrasher-/gocryptotrader/config"
)
var bm BTCMarkets
// Please supply your own keys here to do better tests
const (
apiKey = ""
apiSecret = ""
)
func TestSetDefaults(t *testing.T) {
bm.SetDefaults()
}
func TestSetup(t *testing.T) {
conf := config.ExchangeConfig{}
bm.Setup(conf)
conf = config.ExchangeConfig{
APIKey: apiKey,
APISecret: apiSecret,
Enabled: true,
AuthenticatedAPISupport: true,
}
bm.Setup(conf)
}
func TestGetFee(t *testing.T) {
t.Parallel()
if fee := bm.GetFee(); fee == 0 {
t.Error("Test failed - GetFee() error")
}
}
func TestGetTicker(t *testing.T) {
t.Parallel()
_, err := bm.GetTicker("BTC")
if err != nil {
t.Error("Test failed - GetTicker() error", err)
}
}
func TestGetOrderbook(t *testing.T) {
t.Parallel()
_, err := bm.GetOrderbook("BTC")
if err != nil {
t.Error("Test failed - GetOrderbook() error", err)
}
}
func TestGetTrades(t *testing.T) {
t.Parallel()
_, err := bm.GetTrades("BTC", nil)
if err != nil {
t.Error("Test failed - GetTrades() error", err)
}
val := url.Values{}
val.Set("since", "0")
_, err = bm.GetTrades("BTC", val)
if err != nil {
t.Error("Test failed - GetTrades() error", err)
}
}
func TestNewOrder(t *testing.T) {
t.Parallel()
_, err := bm.NewOrder("AUD", "BTC", 0, 0, "Bid", "limit", "testTest")
if err == nil {
t.Error("Test failed - NewOrder() error", err)
}
}
func TestCancelOrder(t *testing.T) {
t.Parallel()
_, err := bm.CancelOrder([]int64{1337})
if err == nil {
t.Error("Test failed - CancelOrder() error", err)
}
}
func TestGetOrders(t *testing.T) {
t.Parallel()
_, err := bm.GetOrders("AUD", "BTC", 10, 0, false)
if err == nil {
t.Error("Test failed - GetOrders() error", err)
}
_, err = bm.GetOrders("AUD", "BTC", 10, 0, true)
if err == nil {
t.Error("Test failed - GetOrders() error", err)
}
}
func TestGetOrderDetail(t *testing.T) {
t.Parallel()
_, err := bm.GetOrderDetail([]int64{1337})
if err == nil {
t.Error("Test failed - GetOrderDetail() error", err)
}
}
func TestGetAccountBalance(t *testing.T) {
t.Parallel()
_, err := bm.GetAccountBalance()
if err == nil {
t.Error("Test failed - GetAccountBalance() error", err)
}
}
func TestWithdrawCrypto(t *testing.T) {
t.Parallel()
_, err := bm.WithdrawCrypto(0, "BTC", "LOLOLOL")
if err == nil {
t.Error("Test failed - WithdrawCrypto() error", err)
}
}
func TestWithdrawAUD(t *testing.T) {
t.Parallel()
_, err := bm.WithdrawAUD("BLA", "1337", "blawest", "1336", "BTC", 10000000)
if err == nil {
t.Error("Test failed - WithdrawAUD() error", err)
}
}

View File

@@ -1,22 +1,35 @@
package btcmarkets
type BTCMarketsTicker struct {
BestBID float64
BestAsk float64
LastPrice float64
Currency string
Instrument string
Timestamp int64
// Response is the genralized response type
type Response struct {
Success bool `json:"success"`
ErrorCode int `json:"errorCode"`
ErrorMessage string `json:"errorMessage"`
ID int `json:"id"`
Responses []struct {
Success bool `json:"success"`
ErrorCode int `json:"errorCode"`
ErrorMessage string `json:"errorMessage"`
ID int64 `json:"id"`
}
ClientRequestID string `json:"clientRequestId"`
Orders []Order `json:"orders"`
Status string `json:"status"`
}
type BTCMarketsTrade struct {
TradeID int64 `json:"tid"`
Amount float64 `json:"amount"`
Price float64 `json:"price"`
Date int64 `json:"date"`
// Ticker holds ticker information
type Ticker struct {
BestBID float64 `json:"bestBid"`
BestAsk float64 `json:"bestAsk"`
LastPrice float64 `json:"lastPrice"`
Currency string `json:"currency"`
Instrument string `json:"instrument"`
Timestamp int64 `json:"timestamp"`
Volume float64 `json:"volume24h"`
}
type BTCMarketsOrderbook struct {
// Orderbook holds current orderbook information returned from the exchange
type Orderbook struct {
Currency string `json:"currency"`
Instrument string `json:"instrument"`
Timestamp int64 `json:"timestamp"`
@@ -24,7 +37,44 @@ type BTCMarketsOrderbook struct {
Bids [][]float64 `json:"bids"`
}
type BTCMarketsTradeResponse struct {
// Trade holds trade information
type Trade struct {
TradeID int64 `json:"tid"`
Amount float64 `json:"amount"`
Price float64 `json:"price"`
Date int64 `json:"date"`
}
// OrderToGo holds order information to be sent to the exchange
type OrderToGo struct {
Currency string `json:"currency"`
Instrument string `json:"instrument"`
Price int64 `json:"price"`
Volume int64 `json:"volume"`
OrderSide string `json:"orderSide"`
OrderType string `json:"ordertype"`
ClientRequestID string `json:"clientRequestId"`
}
// Order holds order information
type Order struct {
ID int64 `json:"id"`
Currency string `json:"currency"`
Instrument string `json:"instrument"`
OrderSide string `json:"orderSide"`
OrderType string `json:"ordertype"`
CreationTime float64 `json:"creationTime"`
Status string `json:"status"`
ErrorMessage string `json:"errorMessage"`
Price float64 `json:"price"`
Volume float64 `json:"volume"`
OpenVolume float64 `json:"openVolume"`
ClientRequestID string `json:"clientRequestId"`
Trades []TradeResponse `json:"trades"`
}
// TradeResponse holds trade information
type TradeResponse struct {
ID int64 `json:"id"`
CreationTime float64 `json:"creationTime"`
Description string `json:"description"`
@@ -33,24 +83,26 @@ type BTCMarketsTradeResponse struct {
Fee float64 `json:"fee"`
}
type BTCMarketsOrder struct {
ID int64 `json:"id"`
Currency string `json:"currency"`
Instrument string `json:"instrument"`
OrderSide string `json:"orderSide"`
OrderType string `json:"ordertype"`
CreationTime float64 `json:"creationTime"`
Status string `json:"status"`
ErrorMessage string `json:"errorMessage"`
Price float64 `json:"price"`
Volume float64 `json:"volume"`
OpenVolume float64 `json:"openVolume"`
ClientRequestId string `json:"clientRequestId"`
Trades []BTCMarketsTradeResponse `json:"trades"`
}
type BTCMarketsAccountBalance struct {
// AccountBalance holds account balance details
type AccountBalance struct {
Balance float64 `json:"balance"`
PendingFunds float64 `json:"pendingFunds"`
Currency string `json:"currency"`
}
// WithdrawRequestCrypto is a generalized withdraw request type
type WithdrawRequestCrypto struct {
Amount int64 `json:"amount"`
Currency string `json:"currency"`
Address string `json:"address"`
}
// WithdrawRequestAUD is a generalized withdraw request type
type WithdrawRequestAUD struct {
Amount int64 `json:"amount"`
Currency string `json:"currency"`
AccountName string `json:"accountName"`
AccountNumber string `json:"accountNumber"`
BankName string `json:"bankName"`
BSBNumber string `json:"bsbNumber"`
}

View File

@@ -14,10 +14,12 @@ import (
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
)
// Start runs ticker monitor in a new routine
func (b *BTCMarkets) Start() {
go b.Run()
}
// Run starts a go routine to monitor ticker price
func (b *BTCMarkets) Run() {
if b.Verbose {
log.Printf("%s polling delay: %ds.\n", b.GetName(), b.RESTPollingDelay)
@@ -71,6 +73,7 @@ func (b *BTCMarkets) Run() {
}
}
// GetTickerPrice returns ticker information
func (b *BTCMarkets) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, error) {
tickerNew, err := ticker.GetTicker(b.GetName(), p)
if err == nil {
@@ -90,6 +93,7 @@ func (b *BTCMarkets) GetTickerPrice(p pair.CurrencyPair) (ticker.TickerPrice, er
return tickerPrice, nil
}
// GetOrderbookEx returns orderbook base on the currency pair
func (b *BTCMarkets) GetOrderbookEx(p pair.CurrencyPair) (orderbook.OrderbookBase, error) {
ob, err := orderbook.GetOrderbook(b.GetName(), p)
if err == nil {
@@ -117,11 +121,12 @@ func (b *BTCMarkets) GetOrderbookEx(p pair.CurrencyPair) (orderbook.OrderbookBas
return orderBook, nil
}
//GetExchangeAccountInfo : Retrieves balances for all enabled currencies for the BTCMarkets exchange
func (e *BTCMarkets) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
// GetExchangeAccountInfo retrieves balances for all enabled currencies for the
// BTCMarkets exchange
func (b *BTCMarkets) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
var response exchange.AccountInfo
response.ExchangeName = e.GetName()
accountBalance, err := e.GetAccountBalance()
response.ExchangeName = b.GetName()
accountBalance, err := b.GetAccountBalance()
if err != nil {
return response, err
}