mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-20 07:26:46 +00:00
Added BTCMarkets authenticated HTTP functions.
This commit is contained in:
277
btcmarkets.go
277
btcmarkets.go
@@ -2,15 +2,22 @@ package main
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"log"
|
||||
"bytes"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
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"
|
||||
)
|
||||
|
||||
type BTCMarkets struct {
|
||||
@@ -20,6 +27,7 @@ type BTCMarkets struct {
|
||||
Websocket bool
|
||||
RESTPollingDelay time.Duration
|
||||
Fee float64
|
||||
Ticker map[string]BTCMarketsTicker
|
||||
APIKey, APISecret string
|
||||
}
|
||||
|
||||
@@ -32,6 +40,45 @@ type BTCMarketsTicker struct {
|
||||
Timestamp int64
|
||||
}
|
||||
|
||||
type BTCMarketsTrade struct {
|
||||
TradeID int64 `json:"tid"`
|
||||
Amount float64 `json:"amount"`
|
||||
Price float64 `json:"price"`
|
||||
Date int64 `json:"date"`
|
||||
}
|
||||
|
||||
type BTCMarketsOrderbook struct {
|
||||
Currency string `json:"currency"`
|
||||
Instrument string `json:"instrument"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
Asks [][]float64 `json:"asks"`
|
||||
Bids [][]float64 `json:"bids"`
|
||||
}
|
||||
|
||||
type BTCMarketsTradeResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
CreationTime float64 `json:"creationTime"`
|
||||
Description string `json:"description"`
|
||||
Price float64 `json:"price"`
|
||||
Volume float64 `json:"volume"`
|
||||
Fee float64 `json:"fee"`
|
||||
}
|
||||
|
||||
type BTCMarketsOrderResponse struct {
|
||||
ID float64 `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"`
|
||||
}
|
||||
|
||||
func (b *BTCMarkets) SetDefaults() {
|
||||
b.Name = "BTC Markets"
|
||||
b.Enabled = true
|
||||
@@ -39,6 +86,7 @@ func (b *BTCMarkets) SetDefaults() {
|
||||
b.Verbose = false
|
||||
b.Websocket = false
|
||||
b.RESTPollingDelay = 10
|
||||
b.Ticker = make(map[string]BTCMarketsTicker)
|
||||
}
|
||||
|
||||
func (b *BTCMarkets) GetName() (string) {
|
||||
@@ -55,7 +103,15 @@ func (b *BTCMarkets) IsEnabled() (bool) {
|
||||
|
||||
func (b *BTCMarkets) SetAPIKeys(apiKey, apiSecret string) {
|
||||
b.APIKey = apiKey
|
||||
b.APISecret = apiSecret
|
||||
result, err := Base64Decode(apiSecret)
|
||||
|
||||
if err != nil {
|
||||
log.Printf("%s unable to decode secret key.\n", b.GetName())
|
||||
b.Enabled = false
|
||||
return
|
||||
}
|
||||
|
||||
b.APISecret = string(result)
|
||||
}
|
||||
|
||||
func (b *BTCMarkets) GetFee() (float64) {
|
||||
@@ -66,10 +122,15 @@ func (b *BTCMarkets) Run() {
|
||||
if b.Verbose {
|
||||
log.Printf("%s polling delay: %ds.\n", b.GetName(), b.RESTPollingDelay)
|
||||
}
|
||||
|
||||
|
||||
for b.Enabled {
|
||||
go func() {
|
||||
BTCMarketsBTC := b.GetTicker("BTC")
|
||||
BTCMarketsBTC, err := b.GetTicker("BTC")
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
b.Ticker["BTC"] = BTCMarketsBTC
|
||||
BTCMarketsBTCLastUSD, _ := ConvertCurrency(BTCMarketsBTC.LastPrice, "AUD", "USD")
|
||||
BTCMarketsBTCBestBidUSD, _ := ConvertCurrency(BTCMarketsBTC.BestBID, "AUD", "USD")
|
||||
BTCMarketsBTCBestAskUSD, _ := ConvertCurrency(BTCMarketsBTC.BestAsk, "AUD", "USD")
|
||||
@@ -78,7 +139,12 @@ func (b *BTCMarkets) Run() {
|
||||
}()
|
||||
|
||||
go func() {
|
||||
BTCMarketsLTC := b.GetTicker("LTC")
|
||||
BTCMarketsLTC, err := b.GetTicker("LTC")
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
b.Ticker["LTC"] = BTCMarketsLTC
|
||||
BTCMarketsLTCLastUSD, _ := ConvertCurrency(BTCMarketsLTC.LastPrice, "AUD", "USD")
|
||||
BTCMarketsLTCBestBidUSD, _ := ConvertCurrency(BTCMarketsLTC.BestBID, "AUD", "USD")
|
||||
BTCMarketsLTCBestAskUSD, _ := ConvertCurrency(BTCMarketsLTC.BestAsk, "AUD", "USD")
|
||||
@@ -89,44 +155,207 @@ func (b *BTCMarkets) Run() {
|
||||
}
|
||||
}
|
||||
|
||||
func (b *BTCMarkets) GetTicker(symbol string) (BTCMarketsTicker) {
|
||||
func (b *BTCMarkets) GetTicker(symbol string) (BTCMarketsTicker, error) {
|
||||
ticker := BTCMarketsTicker{}
|
||||
path := fmt.Sprintf("/market/%s/AUD/tick", symbol)
|
||||
err := SendHTTPGetRequest(BTCMARKETS_API_URL + path, true, &ticker)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return BTCMarketsTicker{}
|
||||
return BTCMarketsTicker{}, err
|
||||
}
|
||||
return ticker
|
||||
return ticker, nil
|
||||
}
|
||||
|
||||
func (b *BTCMarkets) GetOrderbook(symbol string) {
|
||||
func (b *BTCMarkets) GetOrderbook(symbol string) (BTCMarketsOrderbook, error) {
|
||||
orderbook := BTCMarketsOrderbook{}
|
||||
path := fmt.Sprintf("/market/%s/AUD/orderbook", symbol)
|
||||
err := SendHTTPGetRequest(BTCMARKETS_API_URL + path, true, nil)
|
||||
err := SendHTTPGetRequest(BTCMARKETS_API_URL + path, true, &orderbook)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return BTCMarketsOrderbook{}, err
|
||||
}
|
||||
return orderbook, nil
|
||||
}
|
||||
|
||||
func (b *BTCMarkets) GetTrades(symbol, since string) {
|
||||
func (b *BTCMarkets) GetTrades(symbol, since string) ([]BTCMarketsTrade, error) {
|
||||
trades := []BTCMarketsTrade{}
|
||||
path := ""
|
||||
if len(since) > 0 {
|
||||
path = fmt.Sprintf("/market/%s/AUD/trades?since=%s", symbol, since)
|
||||
} else {
|
||||
path = fmt.Sprintf("/market/%s/AUD/trades", symbol)
|
||||
}
|
||||
err := SendHTTPGetRequest(BTCMARKETS_API_URL + path, true, nil)
|
||||
err := SendHTTPGetRequest(BTCMARKETS_API_URL + path, true, &trades)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return trades, nil
|
||||
}
|
||||
|
||||
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"`
|
||||
|
||||
}
|
||||
order := Order{}
|
||||
order.Currency = currency
|
||||
order.Instrument = instrument
|
||||
order.Price = price
|
||||
order.Volume = amount
|
||||
order.OrderSide = orderSide
|
||||
order.OrderType = orderType
|
||||
order.ClientRequestId = clientReq
|
||||
|
||||
JSONPayload, err := JSONEncode(order)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
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, JSONPayload, &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 resp.ID, nil
|
||||
}
|
||||
|
||||
func (b *BTCMarkets) CancelOrder(orderID []int64) (bool, error) {
|
||||
type CancelOrder struct {
|
||||
OrderIDs []int64 `json:"orderIds"`
|
||||
}
|
||||
orders := CancelOrder{}
|
||||
orders.OrderIDs = append(orders.OrderIDs, orderID...)
|
||||
|
||||
JSONPayload, err := JSONEncode(orders)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
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, JSONPayload, &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)
|
||||
}
|
||||
|
||||
ordersToBeCancelled := len(orderID)
|
||||
ordersCancelled := 0
|
||||
for _, y := range resp.Responses {
|
||||
if y.Success {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
if ordersCancelled == ordersToBeCancelled {
|
||||
return true, nil
|
||||
} else {
|
||||
return false, fmt.Errorf("%s Unable to cancel order(s).", b.GetName())
|
||||
}
|
||||
}
|
||||
|
||||
func (b *BTCMarkets) GetOrders(currency, instrument string, limit, since int64, historic bool) {
|
||||
request := make(map[string]interface{})
|
||||
request["currency"] = currency
|
||||
request["instrument"] = instrument
|
||||
request["limit"] = limit
|
||||
request["since"] = since
|
||||
|
||||
JSONPayload, err := JSONEncode(request)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
path := BTCMARKETS_ORDER_OPEN
|
||||
if historic {
|
||||
path = BTCMARKETS_ORDER_HISTORY
|
||||
}
|
||||
|
||||
err = b.SendAuthenticatedRequest("POST", path, JSONPayload, nil)
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *BTCMarkets) SendAuthenticatedRequest(reqType, path, data string) (error) {
|
||||
nonce := strconv.FormatInt(time.Now().Unix(), 10)
|
||||
func (b *BTCMarkets) GetOrderDetail(orderID []int64) {
|
||||
type OrderDetail struct {
|
||||
OrderIDs []int64 `json:"orderIds"`
|
||||
}
|
||||
orders := OrderDetail{}
|
||||
orders.OrderIDs = append(orders.OrderIDs, orderID...)
|
||||
|
||||
JSONPayload, err := JSONEncode(orders)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
err = b.SendAuthenticatedRequest("POST", BTCMARKETS_ORDER_DETAIL, JSONPayload, nil)
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *BTCMarkets) GetAccountBalance() {
|
||||
type Balance struct {
|
||||
Balance float64 `json:"balance"`
|
||||
PendingFunds float64 `json:"pendingFunds"`
|
||||
Currency string `json:"currency"`
|
||||
}
|
||||
|
||||
balance := []Balance{}
|
||||
err := b.SendAuthenticatedRequest("GET", BTCMARKETS_ACCOUNT_BALANCE, nil, &balance)
|
||||
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *BTCMarkets) SendAuthenticatedRequest(reqType, path string, data []byte, result interface{}) (error) {
|
||||
nonce := strconv.FormatInt(time.Now().UnixNano(), 10)[0:13]
|
||||
request := ""
|
||||
|
||||
if len(data) > 0 {
|
||||
request = path + "\n" + nonce + "\n" + data
|
||||
if data != nil {
|
||||
request = path + "\n" + nonce + "\n" + string(data)
|
||||
} else {
|
||||
request = path + "\n" + nonce + "\n"
|
||||
}
|
||||
@@ -134,18 +363,18 @@ func (b *BTCMarkets) SendAuthenticatedRequest(reqType, path, data string) (error
|
||||
hmac := GetHMAC(HASH_SHA512, []byte(request), []byte(b.APISecret))
|
||||
|
||||
if b.Verbose {
|
||||
log.Printf("Sending %s request to %s path %s with params %s\n", reqType, BTCMARKETS_API_URL + path, path, request)
|
||||
log.Printf("Sending %s request to URL %s with params %s\n", reqType, BTCMARKETS_API_URL + path, request)
|
||||
}
|
||||
|
||||
headers := make(map[string]string)
|
||||
headers["Accept"] = "application/json"
|
||||
headers["Content-Type"] = "application/json"
|
||||
headers["Accept-Charset"] = "UTF-8"
|
||||
headers["Content-Type"] = "application/json"
|
||||
headers["apikey"] = b.APIKey
|
||||
headers["timestamp"] = nonce
|
||||
headers["signature"] = Base64Encode(hmac)
|
||||
|
||||
resp, err := SendHTTPRequest(reqType, BTCMARKETS_API_URL + path, headers, strings.NewReader(""))
|
||||
resp, err := SendHTTPRequest(reqType, BTCMARKETS_API_URL + path, headers, bytes.NewBuffer(data))
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -155,5 +384,11 @@ func (b *BTCMarkets) SendAuthenticatedRequest(reqType, path, data string) (error
|
||||
log.Printf("Recieved raw: %s\n", resp)
|
||||
}
|
||||
|
||||
err = JSONDecode([]byte(resp), &result)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -129,7 +129,7 @@ func (e *Event) CheckCondition() (bool) {
|
||||
} else if bot.exchange.btce.GetName() == e.Exchange {
|
||||
lastPrice = bot.exchange.btce.GetTicker("btc_usd").Last
|
||||
} else if bot.exchange.btcmarkets.GetName() == e.Exchange {
|
||||
lastPrice = bot.exchange.btcmarkets.GetTicker("BTC").LastPrice
|
||||
lastPrice = bot.exchange.btcmarkets.Ticker["BTC"].LastPrice
|
||||
} else if bot.exchange.okcoinChina.GetName() == e.Exchange {
|
||||
lastPrice = bot.exchange.okcoinChina.GetTicker("btc_cny").Last
|
||||
} else if bot.exchange.okcoinIntl.GetName() == e.Exchange {
|
||||
|
||||
Reference in New Issue
Block a user