Files
gocryptotrader/anxhttp.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

471 lines
12 KiB
Go

package main
import (
"bytes"
"errors"
"fmt"
"log"
"strconv"
"time"
)
const (
ANX_API_URL = "https://anxpro.com/"
ANX_API_VERSION = "3"
ANX_APIKEY = "apiKey"
ANX_DATA_TOKEN = "dataToken"
ANX_ORDER_NEW = "order/new"
ANX_ORDER_INFO = "order/info"
ANX_SEND = "send"
ANX_SUBACCOUNT_NEW = "subaccount/new"
ANX_RECEIVE_ADDRESS = "receive"
ANX_CREATE_ADDRESS = "receive/create"
ANX_TICKER = "money/ticker"
)
type ANX struct {
Name string
Enabled bool
Verbose bool
Websocket bool
RESTPollingDelay time.Duration
AuthenticatedAPISupport bool
APIKey, APISecret string
TakerFee, MakerFee float64
BaseCurrencies []string
AvailablePairs []string
EnabledPairs []string
}
type ANXOrder struct {
OrderType string `json:"orderType"`
BuyTradedCurrency bool `json:"buyTradedCurrency"`
TradedCurrency string `json:"tradedCurrency"`
SettlementCurrency string `json:"settlementCurrency"`
TradedCurrencyAmount string `json:"tradedCurrencyAmount"`
SettlementCurrencyAmount string `json:"settlementCurrencyAmount"`
LimitPriceInSettlementCurrency string `json:"limitPriceInSettlementCurrency"`
ReplaceExistingOrderUUID string `json:"replaceExistingOrderUuid"`
ReplaceOnlyIfActive bool `json:"replaceOnlyIfActive"`
}
type ANXOrderResponse struct {
BuyTradedCurrency bool `json:"buyTradedCurrency"`
ExecutedAverageRate string `json:"executedAverageRate"`
LimitPriceInSettlementCurrency string `json:"limitPriceInSettlementCurrency"`
OrderID string `json:"orderId"`
OrderStatus string `json:"orderStatus"`
OrderType string `json:"orderType"`
ReplaceExistingOrderUUID string `json:"replaceExistingOrderId"`
SettlementCurrency string `json:"settlementCurrency"`
SettlementCurrencyAmount string `json:"settlementCurrencyAmount"`
SettlementCurrencyOutstanding string `json:"settlementCurrencyOutstanding"`
Timestamp int64 `json:"timestamp"`
TradedCurrency string `json:"tradedCurrency"`
TradedCurrencyAmount string `json:"tradedCurrencyAmount"`
TradedCurrencyOutstanding string `json:"tradedCurrencyOutstanding"`
}
type ANXTickerComponent struct {
Currency string `json:"currency"`
Display string `json:"display"`
DisplayShort string `json:"display_short"`
Value float64 `json:"value,string"`
ValueInt int64 `json:"value_int,string"`
}
type ANXTicker struct {
Result string `json:"result"`
Data struct {
High ANXTickerComponent `json:"high"`
Low ANXTickerComponent `json:"low"`
Avg ANXTickerComponent `json:"avg"`
Vwap ANXTickerComponent `json:"vwap"`
Vol ANXTickerComponent `json:"vol"`
Last ANXTickerComponent `json:"last"`
Buy ANXTickerComponent `json:"buy"`
Sell ANXTickerComponent `json:"sell"`
Now float64 `json:"now"`
UpdateTime float64 `json:"dataUpdateTime"`
} `json:"data"`
}
func (a *ANX) SetDefaults() {
a.Name = "ANX"
a.Enabled = false
a.TakerFee = 0.6
a.MakerFee = 0.3
a.Verbose = false
a.Websocket = false
a.RESTPollingDelay = 10
}
//Setup is run on startup to setup exchange with config values
func (a *ANX) Setup(exch Exchanges) {
if !exch.Enabled {
a.SetEnabled(false)
} else {
a.Enabled = true
a.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
a.SetAPIKeys(exch.APIKey, exch.APISecret)
a.RESTPollingDelay = exch.RESTPollingDelay
a.Verbose = exch.Verbose
a.Websocket = exch.Websocket
a.BaseCurrencies = SplitStrings(exch.BaseCurrencies, ",")
a.AvailablePairs = SplitStrings(exch.AvailablePairs, ",")
a.EnabledPairs = SplitStrings(exch.EnabledPairs, ",")
}
}
//Start is run if exchange is enabled, after Setup
func (a *ANX) Start() {
go a.Run()
}
func (a *ANX) GetName() string {
return a.Name
}
func (a *ANX) SetEnabled(enabled bool) {
a.Enabled = enabled
}
func (a *ANX) IsEnabled() bool {
return a.Enabled
}
func (a *ANX) SetAPIKeys(apiKey, apiSecret string) {
if !a.AuthenticatedAPISupport {
return
}
a.APIKey = apiKey
result, err := Base64Decode(apiSecret)
if err != nil {
log.Printf("%s unable to decode secret key. Authenticated API support disabled.", a.GetName())
a.AuthenticatedAPISupport = true
return
}
a.APISecret = string(result)
}
func (a *ANX) GetFee(maker bool) float64 {
if maker {
return a.MakerFee
} else {
return a.TakerFee
}
}
func (a *ANX) Run() {
if a.Verbose {
log.Printf("%s polling delay: %ds.\n", a.GetName(), a.RESTPollingDelay)
log.Printf("%s %d currencies enabled: %s.\n", a.GetName(), len(a.EnabledPairs), a.EnabledPairs)
}
for a.Enabled {
for _, x := range a.EnabledPairs {
currency := x
go func() {
ticker := a.GetTicker(currency)
log.Printf("ANX %s: Last %f High %f Low %f Volume %f\n", currency, ticker.Data.Last.Value, ticker.Data.High.Value, ticker.Data.Low.Value, ticker.Data.Vol.Value)
AddExchangeInfo(a.GetName(), currency[0:3], currency[3:], ticker.Data.Last.Value, ticker.Data.Vol.Value)
}()
}
time.Sleep(time.Second * a.RESTPollingDelay)
}
}
func (a *ANX) GetTicker(currency string) ANXTicker {
var ticker ANXTicker
err := SendHTTPGetRequest(fmt.Sprintf("%sapi/2/%s/%s", ANX_API_URL, currency, ANX_TICKER), true, &ticker)
if err != nil {
log.Println(err)
return ANXTicker{}
}
return ticker
}
func (a *ANX) GetTickerPrice(currency string) TickerPrice {
var tickerPrice TickerPrice
ticker := a.GetTicker(currency)
tickerPrice.Ask = ticker.Data.Buy.Value
tickerPrice.Bid = ticker.Data.Sell.Value
tickerPrice.CryptoCurrency = currency
tickerPrice.Low = ticker.Data.Low.Value
tickerPrice.Last = ticker.Data.Last.Value
tickerPrice.Volume = ticker.Data.Vol.Value
tickerPrice.High = ticker.Data.High.Value
return tickerPrice
}
func (a *ANX) GetEnabledCurrencies() []string {
return a.EnabledPairs
}
func (a *ANX) GetAPIKey(username, password, otp, deviceID string) (string, string) {
request := make(map[string]interface{})
request["nonce"] = strconv.FormatInt(time.Now().UnixNano(), 10)[0:13]
request["username"] = username
request["password"] = password
if otp != "" {
request["otp"] = otp
}
request["deviceId"] = deviceID
type APIKeyResponse struct {
APIKey string `json:"apiKey"`
APISecret string `json:"apiSecret"`
ResultCode string `json:"resultCode"`
Timestamp int64 `json:"timestamp"`
}
var response APIKeyResponse
err := a.SendAuthenticatedHTTPRequest(ANX_APIKEY, request, &response)
if err != nil {
log.Println(err)
return "", ""
}
if response.ResultCode != "OK" {
log.Printf("Response code is not OK: %s\n", response.ResultCode)
return "", ""
}
return response.APIKey, response.APISecret
}
func (a *ANX) GetDataToken() string {
request := make(map[string]interface{})
type DataTokenResponse struct {
ResultCode string `json:"resultCode"`
Timestamp int64 `json:"timestamp"`
Token string `json:"token"`
UUID string `json:"uuid"`
}
var response DataTokenResponse
err := a.SendAuthenticatedHTTPRequest(ANX_DATA_TOKEN, request, &response)
if err != nil {
log.Println(err)
return ""
}
if response.ResultCode != "OK" {
log.Printf("Response code is not OK: %s\n", response.ResultCode)
return ""
}
return response.Token
}
func (a *ANX) NewOrder(orderType string, buy bool, tradedCurrency, tradedCurrencyAmount, settlementCurrency, settlementCurrencyAmount, limitPriceSettlement string,
replace bool, replaceUUID string, replaceIfActive bool) {
request := make(map[string]interface{})
var order ANXOrder
order.OrderType = orderType
order.BuyTradedCurrency = buy
if buy {
order.TradedCurrencyAmount = tradedCurrencyAmount
} else {
order.SettlementCurrencyAmount = settlementCurrencyAmount
}
order.TradedCurrency = tradedCurrency
order.SettlementCurrency = settlementCurrency
order.LimitPriceInSettlementCurrency = limitPriceSettlement
if replace {
order.ReplaceExistingOrderUUID = replaceUUID
order.ReplaceOnlyIfActive = replaceIfActive
}
request["order"] = order
type OrderResponse struct {
OrderID string `json:"orderId"`
Timestamp int64 `json:"timestamp"`
ResultCode string `json:"resultCode"`
}
var response OrderResponse
err := a.SendAuthenticatedHTTPRequest(ANX_ORDER_NEW, request, &response)
if err != nil {
log.Println(err)
return
}
if response.ResultCode != "OK" {
log.Printf("Response code is not OK: %s\n", response.ResultCode)
return
}
}
func (a *ANX) OrderInfo(orderID string) (ANXOrderResponse, error) {
request := make(map[string]interface{})
request["orderId"] = orderID
type OrderInfoResponse struct {
Order ANXOrderResponse `json:"order"`
ResultCode string `json:"resultCode"`
Timestamp int64 `json:"timestamp"`
}
var response OrderInfoResponse
err := a.SendAuthenticatedHTTPRequest(ANX_ORDER_INFO, request, &response)
if err != nil {
log.Println(err)
return ANXOrderResponse{}, err
}
if response.ResultCode != "OK" {
log.Printf("Response code is not OK: %s\n", response.ResultCode)
return ANXOrderResponse{}, errors.New(response.ResultCode)
}
return response.Order, nil
}
func (a *ANX) Send(currency, address, otp, amount string) (string, error) {
request := make(map[string]interface{})
request["ccy"] = currency
request["amount"] = amount
request["address"] = address
if otp != "" {
request["otp"] = otp
}
type SendResponse struct {
TransactionID string `json:"transactionId"`
ResultCode string `json:"resultCode"`
Timestamp int64 `json:"timestamp"`
}
var response SendResponse
err := a.SendAuthenticatedHTTPRequest(ANX_SEND, request, &response)
if err != nil {
return "", err
}
if response.ResultCode != "OK" {
log.Printf("Response code is not OK: %s\n", response.ResultCode)
return "", errors.New(response.ResultCode)
}
return response.TransactionID, nil
}
func (a *ANX) CreateNewSubAccount(currency, name string) (string, error) {
request := make(map[string]interface{})
request["ccy"] = currency
request["customRef"] = name
type SubaccountResponse struct {
SubAccount string `json:"subAccount"`
ResultCode string `json:"resultCode"`
Timestamp int64 `json:"timestamp"`
}
var response SubaccountResponse
err := a.SendAuthenticatedHTTPRequest(ANX_SUBACCOUNT_NEW, request, &response)
if err != nil {
return "", err
}
if response.ResultCode != "OK" {
log.Printf("Response code is not OK: %s\n", response.ResultCode)
return "", errors.New(response.ResultCode)
}
return response.SubAccount, nil
}
func (a *ANX) GetDepositAddress(currency, name string, new bool) (string, error) {
request := make(map[string]interface{})
request["ccy"] = currency
if name != "" {
request["subAccount"] = name
}
type AddressResponse struct {
Address string `json:"address"`
SubAccount string `json:"subAccount"`
ResultCode string `json:"resultCode"`
Timestamp int64 `json:"timestamp"`
}
var response AddressResponse
path := ANX_RECEIVE_ADDRESS
if new {
path = ANX_CREATE_ADDRESS
}
err := a.SendAuthenticatedHTTPRequest(path, request, &response)
if err != nil {
return "", err
}
if response.ResultCode != "OK" {
log.Printf("Response code is not OK: %s\n", response.ResultCode)
return "", errors.New(response.ResultCode)
}
return response.Address, nil
}
func (a *ANX) SendAuthenticatedHTTPRequest(path string, params map[string]interface{}, result interface{}) (err error) {
request := make(map[string]interface{})
request["nonce"] = strconv.FormatInt(time.Now().UnixNano(), 10)[0:13]
path = fmt.Sprintf("api/%s/%s", ANX_API_VERSION, path)
if params != nil {
for key, value := range params {
request[key] = value
}
}
PayloadJson, err := JSONEncode(request)
if err != nil {
return errors.New("SendAuthenticatedHTTPRequest: Unable to JSON request")
}
if a.Verbose {
log.Printf("Request JSON: %s\n", PayloadJson)
}
hmac := GetHMAC(HASH_SHA512, []byte(path+string("\x00")+string(PayloadJson)), []byte(a.APISecret))
headers := make(map[string]string)
headers["Rest-Key"] = a.APIKey
headers["Rest-Sign"] = Base64Encode([]byte(hmac))
headers["Content-Type"] = "application/json"
resp, err := SendHTTPRequest("POST", ANX_API_URL+path, headers, bytes.NewBuffer(PayloadJson))
if a.Verbose {
log.Printf("Recieved raw: \n%s\n", resp)
}
err = JSONDecode([]byte(resp), &result)
if err != nil {
return errors.New("Unable to JSON Unmarshal response.")
}
return nil
}