Added unauthenticated Coinbase Exchange HTTP API support.

This commit is contained in:
Adrian Gallagher
2015-03-11 17:50:46 +11:00
parent c7531a6f7e
commit 961d9c4114
4 changed files with 255 additions and 0 deletions

220
coinbase.go Normal file
View File

@@ -0,0 +1,220 @@
package main
import (
"log"
"fmt"
"strconv"
"net/url"
)
const (
COINBASE_API_URL = "https://api.exchange.coinbase.com/"
COINBASE_API_VERISON = "0"
COINBASE_PRODUCTS = "products"
COINBASE_ORDERBOOK = "book"
COINBASE_TICKER = "ticker"
COINBASE_TRADES = "trades"
COINBASE_HISTORY = "candles"
COINBASE_STATS = "stats"
COINBASE_CURRENCIES = "currencies"
)
type Coinbase struct {
Name string
Enabled bool
Verbose bool
Password, APIKey, APISecret string
TakerFee, MakerFee float64
}
type CoinbaseTicker struct {
TradeID int64 `json:"trade_id"`
Price float64 `json:"price,string"`
Size float64 `json:"size,string"`
Time string `json:"time"`
}
type CoinbaseProduct struct {
ID string `json:"id"`
BaseCurrency string `json:"base_currency"`
QuoteCurrency string `json:"quote_currency"`
BaseMinSize float64 `json:"base_min_size"`
BaseMaxSize int64 `json:"base_max_size"`
QuoteIncrement float64 `json:"quote_increment"`
DisplayName string `json:"string"`
}
type CoinbaseOrderbook struct {
Asks [][]interface{} `json:"ask"`
Bids [][]interface{} `json:"bids"`
Sequence int64 `json:"sequence"`
}
type CoinbaseTrade struct {
TradeID int64 `json:"trade_id"`
Price float64 `json:"price,string"`
Size float64 `json:"size,string"`
Time string `json:"time"`
Side string `json:"side"`
}
type CoinbaseStats struct {
Open float64 `json:"open,string"`
High float64 `json:"high,string"`
Low float64 `json:"low,string"`
Volume float64 `json:"volume,string"`
}
type CoinbaseCurrency struct {
ID string
Name string
MinSize float64 `json:"min_size,string"`
}
type CoinbaseHistory struct {
Time int64
Low float64
High float64
Open float64
Close float64
Volume float64
}
func (c *Coinbase) SetDefaults() {
c.Name = "Coinbase"
c.Enabled = true
c.Verbose = false
c.TakerFee = 0.25
c.MakerFee = 0
}
func (c *Coinbase) GetName() (string) {
return c.Name
}
func (c *Coinbase) SetEnabled(enabled bool) {
c.Enabled = enabled
}
func (c *Coinbase) IsEnabled() (bool) {
return c.Enabled
}
func (c *Coinbase) GetFee(maker bool) (float64) {
if maker {
return c.MakerFee
} else {
return c.TakerFee
}
}
func (c *Coinbase) SetAPIKeys(password, apiKey, apiSecret string) {
c.Password = password
c.APIKey = apiKey
c.APISecret = apiSecret
}
func (c *Coinbase) GetProducts() {
products := []CoinbaseProduct{}
err := SendHTTPRequest(COINBASE_API_URL + COINBASE_PRODUCTS, true, &products)
if err != nil {
log.Println(err)
}
log.Println(products)
}
func (c *Coinbase) GetOrderbook(symbol string, level int) {
orderbook := CoinbaseOrderbook{}
path := ""
if level > 0 {
levelStr := strconv.Itoa(level)
path = fmt.Sprintf("%s/%s/%s?level=%s", COINBASE_API_URL + COINBASE_PRODUCTS, symbol, COINBASE_ORDERBOOK, levelStr)
} else {
path = fmt.Sprintf("%s/%s/%s", COINBASE_API_URL + COINBASE_PRODUCTS, symbol, COINBASE_ORDERBOOK)
}
err := SendHTTPRequest(path, true, &orderbook)
if err != nil {
log.Println(err)
}
log.Println(orderbook)
}
func (c *Coinbase) GetTicker(symbol string) (CoinbaseTicker) {
ticker := CoinbaseTicker{}
path := fmt.Sprintf("%s/%s/%s", COINBASE_API_URL + COINBASE_PRODUCTS, symbol, COINBASE_TICKER)
err := SendHTTPRequest(path, true, &ticker)
if err != nil {
log.Println(err)
return CoinbaseTicker{}
}
return ticker
}
func (c *Coinbase) GetTrades(symbol string) {
trades := []CoinbaseTrade{}
path := fmt.Sprintf("%s/%s/%s", COINBASE_API_URL + COINBASE_PRODUCTS, symbol, COINBASE_TRADES)
err := SendHTTPRequest(path, true, &trades)
if err != nil {
log.Println(err)
}
log.Println(trades)
}
func (c *Coinbase) GetHistoricRates(symbol string, start, end, granularity int64) {
history := []CoinbaseHistory{}
values := url.Values{}
if start > 0 {
values.Set("start", strconv.FormatInt(start, 10))
}
if end > 0 {
values.Set("end", strconv.FormatInt(end, 10))
}
if granularity > 0 {
values.Set("granularity", strconv.FormatInt(granularity, 10))
}
path := fmt.Sprintf("%s/%s/%s", COINBASE_API_URL + COINBASE_PRODUCTS, symbol, COINBASE_HISTORY)
encoded := values.Encode()
if (len(encoded) > 0) {
path += encoded
}
err := SendHTTPRequest(path, true, &history)
if err != nil {
log.Println(err)
}
log.Println(history)
}
func (c *Coinbase) GetStats(symbol string) (CoinbaseStats) {
stats := CoinbaseStats{}
path := fmt.Sprintf("%s/%s/%s", COINBASE_API_URL + COINBASE_PRODUCTS, symbol, COINBASE_STATS)
err := SendHTTPRequest(path, true, &stats)
if err != nil {
log.Println(err)
return CoinbaseStats{}
}
return stats
}
func (c *Coinbase) GetCurrencies() {
currencies := []CoinbaseCurrency{}
err := SendHTTPRequest(COINBASE_API_URL + COINBASE_CURRENCIES, true, &currencies)
if err != nil {
log.Println(err)
}
log.Println(currencies)
}

View File

@@ -56,6 +56,16 @@
"Enabled": true,
"Verbose": false
},
{
"Name": "Coinbase",
"Pairs": "BTCUSD",
"ClientID": "Password",
"APIKey": "Key",
"APISecret": "Secret",
"BaseCurrencies": "USD",
"Enabled": true,
"Verbose": false
},
{
"Name": "Huobi",
"Pairs": "BTCCNY,LTCCNY,LTCBTC",

View File

@@ -204,6 +204,7 @@ func IsValidExchange(Exchange string) (bool) {
bot.exchange.btcchina.GetName() == Exchange && bot.exchange.btcchina.IsEnabled() ||
bot.exchange.btce.GetName() == Exchange && bot.exchange.btcchina.IsEnabled() ||
bot.exchange.btcmarkets.GetName() == Exchange && bot.exchange.btcmarkets.IsEnabled() ||
bot.exchange.coinbase.GetName() == Exchange && bot.exchange.coinbase.IsEnabled() ||
bot.exchange.huobi.GetName() == Exchange && bot.exchange.huobi.IsEnabled() ||
bot.exchange.itbit.GetName() == Exchange && bot.exchange.itbit.IsEnabled() ||
bot.exchange.kraken.GetName() == Exchange && bot.exchange.kraken.IsEnabled() ||

24
main.go
View File

@@ -14,6 +14,7 @@ type Exchange struct {
bitfinex Bitfinex
btce BTCE
btcmarkets BTCMarkets
coinbase Coinbase
okcoinChina OKCoin
okcoinIntl OKCoin
itbit ItBit
@@ -80,6 +81,7 @@ func main() {
bot.exchange.bitfinex.SetDefaults()
bot.exchange.btce.SetDefaults()
bot.exchange.btcmarkets.SetDefaults()
bot.exchange.coinbase.SetDefaults()
bot.exchange.okcoinChina.SetURL(OKCOIN_API_URL_CHINA)
bot.exchange.okcoinChina.SetDefaults()
bot.exchange.okcoinIntl.SetURL(OKCOIN_API_URL)
@@ -167,6 +169,21 @@ func main() {
log.Printf("%s Verbose output disabled.\n", exch.Name)
}
}
} else if bot.exchange.coinbase.GetName() == exch.Name {
if !exch.Enabled {
bot.exchange.coinbase.SetEnabled(false)
log.Printf("%s disabled.\n", exch.Name)
} else {
log.Printf("%s enabled.\n", exch.Name)
bot.exchange.coinbase.SetAPIKeys(exch.ClientID, exch.APIKey, exch.APISecret)
if exch.Verbose {
bot.exchange.coinbase.Verbose = true
log.Printf("%s Verbose output enabled.\n", exch.Name)
} else {
log.Printf("%s Verbose output disabled.\n", exch.Name)
}
}
} else if bot.exchange.okcoinChina.GetName() == exch.Name {
if !exch.Enabled {
bot.exchange.okcoinChina.SetEnabled(false)
@@ -269,6 +286,13 @@ func main() {
//temp until proper asynchronous method of getting pricing/order books is coded
for {
//spot
if bot.exchange.coinbase.IsEnabled() {
go func() {
CoinbaseStats := bot.exchange.coinbase.GetStats("BTC-USD")
CoinbaseTicker := bot.exchange.coinbase.GetTicker("BTC-USD")
log.Printf("Coinbase BTC: Last %f High %f Low %f Volume %f\n", CoinbaseTicker.Price, CoinbaseStats.High, CoinbaseStats.Low, CoinbaseStats.Volume)
}()
}
if bot.exchange.kraken.IsEnabled() {
go func() {
KrakenBTC := bot.exchange.kraken.GetTicker("XBTUSD")