Files
gocryptotrader/btcehttp.go
GloriousCode 7223875230 Now adds a universal way to retrieve all enabled currencies
New endpoint to retrieve values for all enabled currency data for all enabled exchanges and return it as JSON object for front end
2016-07-13 21:43:48 +10:00

545 lines
13 KiB
Go

package main
import (
"errors"
"fmt"
"log"
"net/url"
"strconv"
"strings"
"time"
)
const (
BTCE_API_PUBLIC_URL = "https://btc-e.com/api"
BTCE_API_PRIVATE_URL = "https://btc-e.com/tapi"
BTCE_API_PUBLIC_VERSION = "3"
BTCE_API_PRIVATE_VERSION = "1"
BTCE_INFO = "info"
BTCE_TICKER = "ticker"
BTCE_DEPTH = "depth"
BTCE_TRADES = "trades"
BTCE_ACCOUNT_INFO = "getInfo"
BTCE_TRADE = "Trade"
BTCE_ACTIVE_ORDERS = "ActiveOrders"
BTCE_ORDER_INFO = "OrderInfo"
BTCE_CANCEL_ORDER = "CancelOrder"
BTCE_TRADE_HISTORY = "TradeHistory"
BTCE_TRANSACTION_HISTORY = "TransHistory"
BTCE_WITHDRAW_COIN = "WithdrawCoin"
BTCE_CREATE_COUPON = "CreateCoupon"
BTCE_REDEEM_COUPON = "RedeemCoupon"
)
type BTCE struct {
Name string
Enabled bool
Verbose bool
Websocket bool
RESTPollingDelay time.Duration
AuthenticatedAPISupport bool
APIKey, APISecret string
Fee float64
BaseCurrencies []string
AvailablePairs []string
EnabledPairs []string
Ticker map[string]BTCeTicker
}
type BTCeTicker struct {
High float64
Low float64
Avg float64
Vol float64
Vol_cur float64
Last float64
Buy float64
Sell float64
Updated int64
}
type BTCEOrderbook struct {
Asks [][]float64 `json:"asks"`
Bids [][]float64 `json:"bids"`
}
type BTCETrades struct {
Type string `json:"type"`
Price float64 `json:"bid"`
Amount float64 `json:"amount"`
TID int64 `json:"tid"`
Timestamp int64 `json:"timestamp"`
}
type BTCEResponse struct {
Return interface{} `json:"return"`
Success int `json:"success"`
Error string `json:"error"`
}
func (b *BTCE) SetDefaults() {
b.Name = "BTCE"
b.Enabled = false
b.Fee = 0.2
b.Verbose = false
b.Websocket = false
b.RESTPollingDelay = 10
b.Ticker = make(map[string]BTCeTicker)
}
func (b *BTCE) GetName() string {
return b.Name
}
func (b *BTCE) SetEnabled(enabled bool) {
b.Enabled = enabled
}
func (b *BTCE) IsEnabled() bool {
return b.Enabled
}
func (b *BTCE) Setup(exch Exchanges) {
if !exch.Enabled {
b.SetEnabled(false)
} else {
b.Enabled = true
b.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
b.SetAPIKeys(exch.APIKey, exch.APISecret)
b.RESTPollingDelay = exch.RESTPollingDelay
b.Verbose = exch.Verbose
b.Websocket = exch.Websocket
b.BaseCurrencies = SplitStrings(exch.BaseCurrencies, ",")
b.AvailablePairs = SplitStrings(exch.AvailablePairs, ",")
b.EnabledPairs = SplitStrings(exch.EnabledPairs, ",")
}
}
func (k *BTCE) GetEnabledCurrencies() []string {
return k.EnabledPairs
}
func (b *BTCE) Start() {
go b.Run()
}
func (b *BTCE) SetAPIKeys(apiKey, apiSecret string) {
b.APIKey = apiKey
b.APISecret = apiSecret
}
func (b *BTCE) GetFee() float64 {
return b.Fee
}
func (b *BTCE) Run() {
if b.Verbose {
log.Printf("%s Websocket: %s.", b.GetName(), IsEnabled(b.Websocket))
log.Printf("%s polling delay: %ds.\n", b.GetName(), b.RESTPollingDelay)
log.Printf("%s %d currencies enabled: %s.\n", b.GetName(), len(b.EnabledPairs), b.EnabledPairs)
}
pairs := []string{}
for _, x := range b.EnabledPairs {
x = StringToLower(x[0:3] + "_" + x[3:6])
pairs = append(pairs, x)
}
pairsString := JoinStrings(pairs, "-")
for b.Enabled {
go func() {
ticker, err := b.GetTicker(pairsString)
if err != nil {
log.Println(err)
return
}
for x, y := range ticker {
x = StringToUpper(x[0:3] + x[4:])
log.Printf("BTC-e %s: Last %f High %f Low %f Volume %f\n", x, y.Last, y.High, y.Low, y.Vol_cur)
b.Ticker[x] = y
AddExchangeInfo(b.GetName(), StringToUpper(x[0:3]), StringToUpper(x[4:]), y.Last, y.Vol_cur)
}
}()
time.Sleep(time.Second * b.RESTPollingDelay)
}
}
func (b *BTCE) GetInfo() {
req := fmt.Sprintf("%s/%s/%s/", BTCE_API_PUBLIC_URL, BTCE_API_PUBLIC_VERSION, BTCE_INFO)
err := SendHTTPGetRequest(req, true, nil)
if err != nil {
log.Println(err)
}
}
func (b *BTCE) GetTicker(symbol string) (map[string]BTCeTicker, error) {
type Response struct {
Data map[string]BTCeTicker
}
response := Response{}
req := fmt.Sprintf("%s/%s/%s/%s", BTCE_API_PUBLIC_URL, BTCE_API_PUBLIC_VERSION, BTCE_TICKER, symbol)
err := SendHTTPGetRequest(req, true, &response.Data)
if err != nil {
return nil, err
}
return response.Data, nil
}
/// This getticker is different, so I'll let someone else implement....
/// Or I will, just later...
func (b *BTCE) GetTickerPrice(currency string) TickerPrice {
var tickerPrice TickerPrice
/*ticker, err:= b.GetTicker(currency)
if err != nil {
log.Println(err)
return tickerPrice
}
tickerPrice.Ask = ticker.Buy
tickerPrice.Bid = ticker.Sell
*/
return tickerPrice
}
func (b *BTCE) GetDepth(symbol string) {
type Response struct {
Data map[string]BTCEOrderbook
}
response := Response{}
req := fmt.Sprintf("%s/%s/%s/%s", BTCE_API_PUBLIC_URL, BTCE_API_PUBLIC_VERSION, BTCE_DEPTH, symbol)
err := SendHTTPGetRequest(req, true, &response.Data)
if err != nil {
log.Println(err)
return
}
depth := response.Data[symbol]
log.Println(depth)
}
func (b *BTCE) GetTrades(symbol string) {
type Response struct {
Data map[string][]BTCETrades
}
response := Response{}
req := fmt.Sprintf("%s/%s/%s/%s", BTCE_API_PUBLIC_URL, BTCE_API_PUBLIC_VERSION, BTCE_TRADES, symbol)
err := SendHTTPGetRequest(req, true, &response.Data)
if err != nil {
log.Println(err)
}
trades := response.Data[symbol]
log.Println(trades)
}
type BTCEFunds struct {
BTC float64 `json:"btc"`
CNH float64 `json:"cnh"`
EUR float64 `json:"eur"`
FTC float64 `json:"ftc"`
GBP float64 `json:"gbp"`
LTC float64 `json:"ltc"`
NMC float64 `json:"nmc"`
NVC float64 `json:"nvc"`
PPC float64 `json:"ppc"`
RUR float64 `json:"rur"`
TRC float64 `json:"trc"`
USD float64 `json:"usd"`
XPM float64 `json:"xpm"`
}
type BTCEAccountInfo struct {
Funds BTCEFunds `json:"funds"`
OpenOrders int `json:"open_orders"`
Rights struct {
Info int `json:"info"`
Trade int `json:"trade"`
Withdraw int `json:"withdraw"`
} `json:"rights"`
ServerTime float64 `json:"server_time"`
TransactionCount int `json:"transaction_count"`
}
func (b *BTCE) GetAccountInfo() (BTCEAccountInfo, error) {
var result BTCEAccountInfo
err := b.SendAuthenticatedHTTPRequest(BTCE_ACCOUNT_INFO, url.Values{}, &result)
if err != nil {
return result, err
}
return result, nil
}
type BTCEActiveOrders struct {
Pair string `json:"pair"`
Type string `json:"sell"`
Amount float64 `json:"amount"`
Rate float64 `json:"rate"`
TimestampCreated float64 `json:"time_created"`
Status int `json:"status"`
}
func (b *BTCE) GetActiveOrders(pair string) (map[string]BTCEActiveOrders, error) {
req := url.Values{}
req.Add("pair", pair)
var result map[string]BTCEActiveOrders
err := b.SendAuthenticatedHTTPRequest(BTCE_ACTIVE_ORDERS, req, &result)
if err != nil {
return result, err
}
return result, nil
}
type BTCEOrderInfo struct {
Pair string `json:"pair"`
Type string `json:"sell"`
StartAmount float64 `json:"start_amount"`
Amount float64 `json:"amount"`
Rate float64 `json:"rate"`
TimestampCreated float64 `json:"time_created"`
Status int `json:"status"`
}
func (b *BTCE) GetOrderInfo(OrderID int64) (map[string]BTCEOrderInfo, error) {
req := url.Values{}
req.Add("order_id", strconv.FormatInt(OrderID, 10))
var result map[string]BTCEOrderInfo
err := b.SendAuthenticatedHTTPRequest(BTCE_ORDER_INFO, req, &result)
if err != nil {
return result, err
}
return result, nil
}
type BTCECancelOrder struct {
OrderID float64 `json:"order_id"`
Funds BTCEFunds `json:"funds"`
}
func (b *BTCE) CancelOrder(OrderID int64) (bool, error) {
req := url.Values{}
req.Add("order_id", strconv.FormatInt(OrderID, 10))
var result BTCECancelOrder
err := b.SendAuthenticatedHTTPRequest(BTCE_CANCEL_ORDER, req, &result)
if err != nil {
return false, err
}
return true, nil
}
type BTCETrade struct {
Received float64 `json:"received"`
Remains float64 `json:"remains"`
OrderID float64 `json:"order_id"`
Funds BTCEFunds `json:"funds"`
}
//to-do: convert orderid to int64
func (b *BTCE) Trade(pair, orderType string, amount, price float64) (float64, error) {
req := url.Values{}
req.Add("pair", pair)
req.Add("type", orderType)
req.Add("amount", strconv.FormatFloat(amount, 'f', -1, 64))
req.Add("rate", strconv.FormatFloat(price, 'f', -1, 64))
var result BTCETrade
err := b.SendAuthenticatedHTTPRequest(BTCE_TRADE, req, &result)
if err != nil {
return 0, err
}
return result.OrderID, nil
}
type BTCETransHistory struct {
Type int `json:"type"`
Amount float64 `json:"amount"`
Currency string `json:"currency"`
Description string `json:"desc"`
Status int `json:"status"`
Timestamp float64 `json:"timestamp"`
}
func (b *BTCE) GetTransactionHistory(TIDFrom, Count, TIDEnd int64, order, since, end string) (map[string]BTCETransHistory, error) {
req := url.Values{}
req.Add("from", strconv.FormatInt(TIDFrom, 10))
req.Add("count", strconv.FormatInt(Count, 10))
req.Add("from_id", strconv.FormatInt(TIDFrom, 10))
req.Add("end_id", strconv.FormatInt(TIDEnd, 10))
req.Add("order", order)
req.Add("since", since)
req.Add("end", end)
var result map[string]BTCETransHistory
err := b.SendAuthenticatedHTTPRequest(BTCE_TRANSACTION_HISTORY, req, &result)
if err != nil {
return result, err
}
return result, nil
}
type BTCETradeHistory struct {
Pair string `json:"pair"`
Type string `json:"type"`
Amount float64 `json:"amount"`
Rate float64 `json:"rate"`
OrderID float64 `json:"order_id"`
MyOrder int `json:"is_your_order"`
Timestamp float64 `json:"timestamp"`
}
func (b *BTCE) GetTradeHistory(TIDFrom, Count, TIDEnd int64, order, since, end, pair string) (map[string]BTCETradeHistory, error) {
req := url.Values{}
req.Add("from", strconv.FormatInt(TIDFrom, 10))
req.Add("count", strconv.FormatInt(Count, 10))
req.Add("from_id", strconv.FormatInt(TIDFrom, 10))
req.Add("end_id", strconv.FormatInt(TIDEnd, 10))
req.Add("order", order)
req.Add("since", since)
req.Add("end", end)
req.Add("pair", pair)
var result map[string]BTCETradeHistory
err := b.SendAuthenticatedHTTPRequest(BTCE_TRADE_HISTORY, req, &result)
if err != nil {
return result, err
}
return result, nil
}
type BTCEWithdrawCoins struct {
TID int64 `json:"tId"`
AmountSent float64 `json:"amountSent"`
Funds BTCEFunds `json:"funds"`
}
func (b *BTCE) WithdrawCoins(coin string, amount float64, address string) (BTCEWithdrawCoins, error) {
req := url.Values{}
req.Add("coinName", coin)
req.Add("amount", strconv.FormatFloat(amount, 'f', -1, 64))
req.Add("address", address)
var result BTCEWithdrawCoins
err := b.SendAuthenticatedHTTPRequest(BTCE_WITHDRAW_COIN, req, &result)
if err != nil {
return result, err
}
return result, nil
}
type BTCECreateCoupon struct {
Coupon string `json:"coupon"`
TransID int64 `json:"transID"`
Funds BTCEFunds `json:"funds"`
}
func (b *BTCE) CreateCoupon(currency string, amount float64) (BTCECreateCoupon, error) {
req := url.Values{}
req.Add("currency", currency)
req.Add("amount", strconv.FormatFloat(amount, 'f', -1, 64))
var result BTCECreateCoupon
err := b.SendAuthenticatedHTTPRequest(BTCE_CREATE_COUPON, req, &result)
if err != nil {
return result, err
}
return result, nil
}
type BTCERedeemCoupon struct {
CouponAmount float64 `json:"couponAmount,string"`
CouponCurrency string `json:"couponCurrency"`
TransID int64 `json:"transID"`
}
func (b *BTCE) RedeemCoupon(coupon string) (BTCERedeemCoupon, error) {
req := url.Values{}
req.Add("coupon", coupon)
var result BTCERedeemCoupon
err := b.SendAuthenticatedHTTPRequest(BTCE_REDEEM_COUPON, req, &result)
if err != nil {
return result, err
}
return result, nil
}
func (b *BTCE) SendAuthenticatedHTTPRequest(method string, values url.Values, result interface{}) (err error) {
nonce := strconv.FormatInt(time.Now().Unix(), 10)
values.Set("nonce", nonce)
values.Set("method", method)
encoded := values.Encode()
hmac := GetHMAC(HASH_SHA512, []byte(encoded), []byte(b.APISecret))
if b.Verbose {
log.Printf("Sending POST request to %s calling method %s with params %s\n", BTCE_API_PRIVATE_URL, method, encoded)
}
headers := make(map[string]string)
headers["Key"] = b.APIKey
headers["Sign"] = HexEncodeToString(hmac)
headers["Content-Type"] = "application/x-www-form-urlencoded"
resp, err := SendHTTPRequest("POST", BTCE_API_PRIVATE_URL, headers, strings.NewReader(encoded))
if err != nil {
return err
}
response := BTCEResponse{}
err = JSONDecode([]byte(resp), &response)
if err != nil {
return err
}
if response.Success != 1 {
return errors.New(response.Error)
}
jsonEncoded, err := JSONEncode(response.Return)
if err != nil {
return err
}
err = JSONDecode(jsonEncoded, &result)
if err != nil {
return err
}
return nil
}