mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-06-08 15:11:07 +00:00
Fixed linter issues, increased code cov & expanded functionality in Gemini.
This commit is contained in:
@@ -16,30 +16,88 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
GEMINI_API_URL = "https://api.gemini.com"
|
||||
GEMINI_API_VERSION = "1"
|
||||
geminiAPIURL = "https://api.gemini.com"
|
||||
geminiSandboxAPIURL = "https://api.sandbox.gemini.com"
|
||||
geminiAPIVersion = "1"
|
||||
|
||||
GEMINI_SYMBOLS = "symbols"
|
||||
GEMINI_TICKER = "pubticker"
|
||||
GEMINI_AUCTION = "auction"
|
||||
GEMINI_AUCTION_HISTORY = "history"
|
||||
GEMINI_ORDERBOOK = "book"
|
||||
GEMINI_TRADES = "trades"
|
||||
GEMINI_ORDERS = "orders"
|
||||
GEMINI_ORDER_NEW = "order/new"
|
||||
GEMINI_ORDER_CANCEL = "order/cancel"
|
||||
GEMINI_ORDER_CANCEL_SESSION = "order/cancel/session"
|
||||
GEMINI_ORDER_CANCEL_ALL = "order/cancel/all"
|
||||
GEMINI_ORDER_STATUS = "order/status"
|
||||
GEMINI_MYTRADES = "mytrades"
|
||||
GEMINI_BALANCES = "balances"
|
||||
GEMINI_HEARTBEAT = "heartbeat"
|
||||
geminiSymbols = "symbols"
|
||||
geminiTicker = "pubticker"
|
||||
geminiAuction = "auction"
|
||||
geminiAuctionHistory = "history"
|
||||
geminiOrderbook = "book"
|
||||
geminiTrades = "trades"
|
||||
geminiOrders = "orders"
|
||||
geminiOrderNew = "order/new"
|
||||
geminiOrderCancel = "order/cancel"
|
||||
geminiOrderCancelSession = "order/cancel/session"
|
||||
geminiOrderCancelAll = "order/cancel/all"
|
||||
geminiOrderStatus = "order/status"
|
||||
geminiMyTrades = "mytrades"
|
||||
geminiBalances = "balances"
|
||||
geminiTradeVolume = "tradevolume"
|
||||
geminiDeposit = "deposit"
|
||||
geminiNewAddress = "newAddress"
|
||||
geminiWithdraw = "withdraw/"
|
||||
geminiHeartbeat = "heartbeat"
|
||||
|
||||
// rate limits per minute
|
||||
geminiPublicRate = 120
|
||||
geminiPrivateRate = 600
|
||||
|
||||
// rates limits per second
|
||||
geminiPublicRateSec = 1
|
||||
geminiPrivateRateSec = 5
|
||||
|
||||
// Too many requests returns this
|
||||
geminiRateError = "429"
|
||||
|
||||
// Assigned API key roles on creation
|
||||
geminiRoleTrader = "trader"
|
||||
geminiRoleFundManager = "fundmanager"
|
||||
)
|
||||
|
||||
// SessionID map guides
|
||||
var (
|
||||
sessionAPIKey map[int]string // map[sessionID]APIKEY
|
||||
sessionAPISecret map[int]string // map[sessionID]APIKEY
|
||||
sessionRole map[string]string // map[sessionID]Roles
|
||||
sessionHeartbeat map[int]bool // map[sessionID]RequiresHeartBeat
|
||||
IsSession bool
|
||||
)
|
||||
|
||||
// Gemini is the overarching type across the Gemini package, create multiple
|
||||
// instances with differing APIkeys for segregation of roles for authenticated
|
||||
// requests & sessions by appending the session function, if sandbox test is
|
||||
// needed append the sandbox function as well.
|
||||
type Gemini struct {
|
||||
exchange.Base
|
||||
}
|
||||
|
||||
// AddSession adds a new session to the gemini base
|
||||
func (g *Gemini) AddSession(sessionID int, apiKey, apiSecret, role string, needsHeartbeat bool) error {
|
||||
if sessionAPIKey == nil {
|
||||
IsSession = true
|
||||
sessionAPIKey = make(map[int]string)
|
||||
sessionAPISecret = make(map[int]string)
|
||||
sessionRole = make(map[string]string)
|
||||
sessionHeartbeat = make(map[int]bool)
|
||||
}
|
||||
_, ok := sessionAPIKey[sessionID]
|
||||
if ok {
|
||||
return errors.New("sessionID already being used")
|
||||
}
|
||||
|
||||
sessionAPIKey[sessionID] = apiKey
|
||||
sessionAPISecret[sessionID] = apiSecret
|
||||
sessionRole[apiKey] = role
|
||||
sessionHeartbeat[sessionID] = needsHeartbeat
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//return session function?
|
||||
|
||||
// SetDefaults sets package defaults for gemini exchange
|
||||
func (g *Gemini) SetDefaults() {
|
||||
g.Name = "Gemini"
|
||||
g.Enabled = false
|
||||
@@ -53,6 +111,7 @@ func (g *Gemini) SetDefaults() {
|
||||
g.AssetTypes = []string{ticker.Spot}
|
||||
}
|
||||
|
||||
// Setup sets exchange configuration paramaters
|
||||
func (g *Gemini) Setup(exch config.ExchangeConfig) {
|
||||
if !exch.Enabled {
|
||||
g.SetEnabled(false)
|
||||
@@ -77,7 +136,35 @@ func (g *Gemini) Setup(exch config.ExchangeConfig) {
|
||||
}
|
||||
}
|
||||
|
||||
func (g *Gemini) GetTicker(currency string) (GeminiTicker, error) {
|
||||
// Session is a session manager for differing APIKeys and roles, use this for all function
|
||||
// calls in this package
|
||||
func (g *Gemini) Session(sessionID int) *Gemini {
|
||||
g.APIUrl = geminiAPIURL
|
||||
_, ok := sessionAPIKey[sessionID]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
g.APIKey = sessionAPIKey[sessionID]
|
||||
g.APISecret = sessionAPISecret[sessionID]
|
||||
return g
|
||||
}
|
||||
|
||||
// Sandbox diverts the apiURL to the sandbox API for testing purposes
|
||||
func (g *Gemini) Sandbox() *Gemini {
|
||||
g.APIUrl = geminiSandboxAPIURL
|
||||
return g
|
||||
}
|
||||
|
||||
// GetSymbols returns all available symbols for trading
|
||||
func (g *Gemini) GetSymbols() ([]string, error) {
|
||||
symbols := []string{}
|
||||
path := fmt.Sprintf("%s/v%s/%s", geminiAPIURL, geminiAPIVersion, geminiSymbols)
|
||||
|
||||
return symbols, common.SendHTTPGetRequest(path, true, &symbols)
|
||||
}
|
||||
|
||||
// GetTicker returns information about recent trading activity for the symbol
|
||||
func (g *Gemini) GetTicker(currencyPair string) (Ticker, error) {
|
||||
|
||||
type TickerResponse struct {
|
||||
Ask float64 `json:"ask,string"`
|
||||
@@ -86,9 +173,9 @@ func (g *Gemini) GetTicker(currency string) (GeminiTicker, error) {
|
||||
Volume map[string]interface{}
|
||||
}
|
||||
|
||||
ticker := GeminiTicker{}
|
||||
ticker := Ticker{}
|
||||
resp := TickerResponse{}
|
||||
path := fmt.Sprintf("%s/v%s/%s/%s", GEMINI_API_URL, GEMINI_API_VERSION, GEMINI_TICKER, currency)
|
||||
path := fmt.Sprintf("%s/v%s/%s/%s", geminiAPIURL, geminiAPIVersion, geminiTicker, currencyPair)
|
||||
|
||||
err := common.SendHTTPGetRequest(path, true, &resp)
|
||||
if err != nil {
|
||||
@@ -99,7 +186,7 @@ func (g *Gemini) GetTicker(currency string) (GeminiTicker, error) {
|
||||
ticker.Bid = resp.Bid
|
||||
ticker.Last = resp.Last
|
||||
|
||||
ticker.Volume.Currency, _ = strconv.ParseFloat(resp.Volume[currency[0:3]].(string), 64)
|
||||
ticker.Volume.Currency, _ = strconv.ParseFloat(resp.Volume[currencyPair[0:3]].(string), 64)
|
||||
ticker.Volume.USD, _ = strconv.ParseFloat(resp.Volume["USD"].(string), 64)
|
||||
|
||||
time, _ := resp.Volume["timestamp"].(float64)
|
||||
@@ -108,59 +195,77 @@ func (g *Gemini) GetTicker(currency string) (GeminiTicker, error) {
|
||||
return ticker, nil
|
||||
}
|
||||
|
||||
func (g *Gemini) GetSymbols() ([]string, error) {
|
||||
symbols := []string{}
|
||||
path := fmt.Sprintf("%s/v%s/%s", GEMINI_API_URL, GEMINI_API_VERSION, GEMINI_SYMBOLS)
|
||||
err := common.SendHTTPGetRequest(path, true, &symbols)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return symbols, nil
|
||||
// GetOrderbook returns the current order book, as two arrays, one of bids, and
|
||||
// one of asks
|
||||
//
|
||||
// params - limit_bids or limit_asks [OPTIONAL] default 50, 0 returns all Values
|
||||
// Type is an integer ie "params.Set("limit_asks", 30)"
|
||||
func (g *Gemini) GetOrderbook(currencyPair string, params url.Values) (Orderbook, error) {
|
||||
path := common.EncodeURLValues(fmt.Sprintf("%s/v%s/%s/%s", geminiAPIURL, geminiAPIVersion, geminiOrderbook, currencyPair), params)
|
||||
orderbook := Orderbook{}
|
||||
|
||||
return orderbook, common.SendHTTPGetRequest(path, true, &orderbook)
|
||||
}
|
||||
|
||||
func (g *Gemini) GetAuction(currency string) (GeminiAuction, error) {
|
||||
path := fmt.Sprintf("%s/v%s/%s/%s", GEMINI_API_URL, GEMINI_API_VERSION, GEMINI_AUCTION, currency)
|
||||
auction := GeminiAuction{}
|
||||
err := common.SendHTTPGetRequest(path, true, &auction)
|
||||
if err != nil {
|
||||
return auction, err
|
||||
}
|
||||
return auction, nil
|
||||
// GetTrades eturn the trades that have executed since the specified timestamp.
|
||||
// Timestamps are either seconds or milliseconds since the epoch (1970-01-01).
|
||||
//
|
||||
// currencyPair - example "btcusd"
|
||||
// params --
|
||||
// since, timestamp [optional]
|
||||
// limit_trades integer Optional. The maximum number of trades to return.
|
||||
// include_breaks boolean Optional. Whether to display broken trades. False by
|
||||
// default. Can be '1' or 'true' to activate
|
||||
func (g *Gemini) GetTrades(currencyPair string, params url.Values) ([]Trade, error) {
|
||||
path := common.EncodeURLValues(fmt.Sprintf("%s/v%s/%s/%s", geminiAPIURL, geminiAPIVersion, geminiTrades, currencyPair), params)
|
||||
trades := []Trade{}
|
||||
|
||||
return trades, common.SendHTTPGetRequest(path, true, &trades)
|
||||
}
|
||||
|
||||
func (g *Gemini) GetAuctionHistory(currency string, params url.Values) ([]GeminiAuctionHistory, error) {
|
||||
path := common.EncodeURLValues(fmt.Sprintf("%s/v%s/%s/%s/%s", GEMINI_API_URL, GEMINI_API_VERSION, GEMINI_AUCTION, currency, GEMINI_AUCTION_HISTORY), params)
|
||||
auctionHist := []GeminiAuctionHistory{}
|
||||
err := common.SendHTTPGetRequest(path, true, &auctionHist)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return auctionHist, nil
|
||||
// GetAuction returns auction infomation
|
||||
func (g *Gemini) GetAuction(currencyPair string) (Auction, error) {
|
||||
path := fmt.Sprintf("%s/v%s/%s/%s", geminiAPIURL, geminiAPIVersion, geminiAuction, currencyPair)
|
||||
auction := Auction{}
|
||||
|
||||
return auction, common.SendHTTPGetRequest(path, true, &auction)
|
||||
}
|
||||
|
||||
func (g *Gemini) GetOrderbook(currency string, params url.Values) (GeminiOrderbook, error) {
|
||||
path := common.EncodeURLValues(fmt.Sprintf("%s/v%s/%s/%s", GEMINI_API_URL, GEMINI_API_VERSION, GEMINI_ORDERBOOK, currency), params)
|
||||
orderbook := GeminiOrderbook{}
|
||||
err := common.SendHTTPGetRequest(path, true, &orderbook)
|
||||
if err != nil {
|
||||
return GeminiOrderbook{}, err
|
||||
}
|
||||
// GetAuctionHistory returns the auction events, optionally including
|
||||
// publications of indicative prices, since the specific timestamp.
|
||||
//
|
||||
// currencyPair - example "btcusd"
|
||||
// params -- [optional]
|
||||
// since - [timestamp] Only returns auction events after the specified
|
||||
// timestamp.
|
||||
// limit_auction_results - [integer] The maximum number of auction
|
||||
// events to return.
|
||||
// include_indicative - [bool] Whether to include publication of
|
||||
// indicative prices and quantities.
|
||||
func (g *Gemini) GetAuctionHistory(currencyPair string, params url.Values) ([]AuctionHistory, error) {
|
||||
path := common.EncodeURLValues(fmt.Sprintf("%s/v%s/%s/%s/%s", geminiAPIURL, geminiAPIVersion, geminiAuction, currencyPair, geminiAuctionHistory), params)
|
||||
auctionHist := []AuctionHistory{}
|
||||
|
||||
return orderbook, nil
|
||||
return auctionHist, common.SendHTTPGetRequest(path, true, &auctionHist)
|
||||
}
|
||||
|
||||
func (g *Gemini) GetTrades(currency string, params url.Values) ([]GeminiTrade, error) {
|
||||
path := common.EncodeURLValues(fmt.Sprintf("%s/v%s/%s/%s", GEMINI_API_URL, GEMINI_API_VERSION, GEMINI_TRADES, currency), params)
|
||||
trades := []GeminiTrade{}
|
||||
err := common.SendHTTPGetRequest(path, true, &trades)
|
||||
if err != nil {
|
||||
return []GeminiTrade{}, err
|
||||
func (g *Gemini) isCorrectSession(role string) error {
|
||||
if !IsSession {
|
||||
return errors.New("session not set")
|
||||
}
|
||||
|
||||
return trades, nil
|
||||
if sessionRole[g.APIKey] != role {
|
||||
return errors.New("incorrect role for APIKEY cannot use this function")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewOrder Only limit orders are supported through the API at present.
|
||||
// returns order ID if successful
|
||||
func (g *Gemini) NewOrder(symbol string, amount, price float64, side, orderType string) (int64, error) {
|
||||
if err := g.isCorrectSession(geminiRoleTrader); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
request := make(map[string]interface{})
|
||||
request["symbol"] = symbol
|
||||
request["amount"] = strconv.FormatFloat(amount, 'f', -1, 64)
|
||||
@@ -168,96 +273,127 @@ func (g *Gemini) NewOrder(symbol string, amount, price float64, side, orderType
|
||||
request["side"] = side
|
||||
request["type"] = orderType
|
||||
|
||||
response := GeminiOrder{}
|
||||
err := g.SendAuthenticatedHTTPRequest("POST", GEMINI_ORDER_NEW, request, &response)
|
||||
response := Order{}
|
||||
err := g.SendAuthenticatedHTTPRequest("POST", geminiOrderNew, request, &response)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return response.OrderID, nil
|
||||
}
|
||||
|
||||
func (g *Gemini) CancelOrder(OrderID int64) (GeminiOrder, error) {
|
||||
// CancelOrder will cancel an order. If the order is already canceled, the
|
||||
// message will succeed but have no effect.
|
||||
func (g *Gemini) CancelOrder(OrderID int64) (Order, error) {
|
||||
request := make(map[string]interface{})
|
||||
request["order_id"] = OrderID
|
||||
|
||||
response := GeminiOrder{}
|
||||
err := g.SendAuthenticatedHTTPRequest("POST", GEMINI_ORDER_CANCEL, request, &response)
|
||||
response := Order{}
|
||||
err := g.SendAuthenticatedHTTPRequest("POST", geminiOrderCancel, request, &response)
|
||||
if err != nil {
|
||||
return GeminiOrder{}, err
|
||||
return Order{}, err
|
||||
}
|
||||
return response, nil
|
||||
}
|
||||
|
||||
func (g *Gemini) CancelOrders(sessions bool) ([]GeminiOrderResult, error) {
|
||||
response := []GeminiOrderResult{}
|
||||
path := GEMINI_ORDER_CANCEL_ALL
|
||||
if sessions {
|
||||
path = GEMINI_ORDER_CANCEL_SESSION
|
||||
// CancelOrders will cancel all outstanding orders created by all sessions owned
|
||||
// by this account, including interactive orders placed through the UI. If
|
||||
// sessions = true will only cancel the order that is called on this session
|
||||
// asssociated with the APIKEY
|
||||
func (g *Gemini) CancelOrders(CancelBySession bool) (OrderResult, error) {
|
||||
response := OrderResult{}
|
||||
path := geminiOrderCancelAll
|
||||
if CancelBySession {
|
||||
path = geminiOrderCancelSession
|
||||
}
|
||||
err := g.SendAuthenticatedHTTPRequest("POST", path, nil, &response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response, nil
|
||||
|
||||
return response, g.SendAuthenticatedHTTPRequest("POST", path, nil, &response)
|
||||
}
|
||||
|
||||
func (g *Gemini) GetOrderStatus(orderID int64) (GeminiOrder, error) {
|
||||
// GetOrderStatus returns the status for an order
|
||||
func (g *Gemini) GetOrderStatus(orderID int64) (Order, error) {
|
||||
request := make(map[string]interface{})
|
||||
request["order_id"] = orderID
|
||||
|
||||
response := GeminiOrder{}
|
||||
err := g.SendAuthenticatedHTTPRequest("POST", GEMINI_ORDER_STATUS, request, &response)
|
||||
if err != nil {
|
||||
return GeminiOrder{}, err
|
||||
}
|
||||
return response, nil
|
||||
response := Order{}
|
||||
|
||||
return response,
|
||||
g.SendAuthenticatedHTTPRequest("POST", geminiOrderStatus, request, &response)
|
||||
}
|
||||
|
||||
func (g *Gemini) GetOrders() ([]GeminiOrder, error) {
|
||||
response := []GeminiOrder{}
|
||||
err := g.SendAuthenticatedHTTPRequest("POST", GEMINI_ORDERS, nil, &response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response, nil
|
||||
// GetOrders returns active orders in the market
|
||||
func (g *Gemini) GetOrders() ([]Order, error) {
|
||||
response := []Order{}
|
||||
|
||||
return response,
|
||||
g.SendAuthenticatedHTTPRequest("POST", geminiOrders, nil, &response)
|
||||
}
|
||||
|
||||
func (g *Gemini) GetTradeHistory(symbol string, timestamp int64) ([]GeminiTradeHistory, error) {
|
||||
// GetTradeHistory returns an array of trades that have been on the exchange
|
||||
//
|
||||
// currencyPair - example "btcusd"
|
||||
// timestamp - [optional] Only return trades on or after this timestamp.
|
||||
func (g *Gemini) GetTradeHistory(currencyPair string, timestamp int64) ([]TradeHistory, error) {
|
||||
response := []TradeHistory{}
|
||||
request := make(map[string]interface{})
|
||||
request["symbol"] = symbol
|
||||
request["timestamp"] = timestamp
|
||||
request["symbol"] = currencyPair
|
||||
|
||||
response := []GeminiTradeHistory{}
|
||||
err := g.SendAuthenticatedHTTPRequest("POST", GEMINI_MYTRADES, request, &response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if timestamp != 0 {
|
||||
request["timestamp"] = timestamp
|
||||
}
|
||||
return response, nil
|
||||
|
||||
return response,
|
||||
g.SendAuthenticatedHTTPRequest("POST", geminiMyTrades, request, &response)
|
||||
}
|
||||
|
||||
func (g *Gemini) GetBalances() ([]GeminiBalance, error) {
|
||||
response := []GeminiBalance{}
|
||||
err := g.SendAuthenticatedHTTPRequest("POST", GEMINI_BALANCES, nil, &response)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response, nil
|
||||
// GetTradeVolume returns a multi-arrayed volume response
|
||||
func (g *Gemini) GetTradeVolume() ([][]TradeVolume, error) {
|
||||
response := [][]TradeVolume{}
|
||||
|
||||
return response,
|
||||
g.SendAuthenticatedHTTPRequest("POST", geminiTradeVolume, nil, &response)
|
||||
}
|
||||
|
||||
func (g *Gemini) PostHeartbeat() (bool, error) {
|
||||
// GetBalances returns available balances in the supported currencies
|
||||
func (g *Gemini) GetBalances() ([]Balance, error) {
|
||||
response := []Balance{}
|
||||
|
||||
return response,
|
||||
g.SendAuthenticatedHTTPRequest("POST", geminiBalances, nil, &response)
|
||||
}
|
||||
|
||||
// GetDepositAddress returns a deposit address
|
||||
func (g *Gemini) GetDepositAddress(depositAddlabel, currency string) (DepositAddress, error) {
|
||||
response := DepositAddress{}
|
||||
|
||||
return response,
|
||||
g.SendAuthenticatedHTTPRequest("POST", geminiDeposit+"/"+currency+"/"+geminiNewAddress, nil, &response)
|
||||
}
|
||||
|
||||
// WithdrawCrypto withdraws crypto currency to a whitelisted address
|
||||
func (g *Gemini) WithdrawCrypto(address, currency string, amount float64) (WithdrawelAddress, error) {
|
||||
response := WithdrawelAddress{}
|
||||
request := make(map[string]interface{})
|
||||
request["address"] = address
|
||||
request["amount"] = strconv.FormatFloat(amount, 'f', -1, 64)
|
||||
|
||||
return response,
|
||||
g.SendAuthenticatedHTTPRequest("POST", geminiWithdraw+currency, nil, &response)
|
||||
}
|
||||
|
||||
// PostHeartbeat sends a maintenance heartbeat to the exchange for all heartbeat
|
||||
// maintaned sessions
|
||||
func (g *Gemini) PostHeartbeat() (string, error) {
|
||||
type Response struct {
|
||||
Result bool `json:"result"`
|
||||
Result string `json:"result"`
|
||||
}
|
||||
|
||||
response := Response{}
|
||||
err := g.SendAuthenticatedHTTPRequest("POST", GEMINI_HEARTBEAT, nil, &response)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return response.Result, nil
|
||||
return response.Result,
|
||||
g.SendAuthenticatedHTTPRequest("POST", geminiHeartbeat, nil, &response)
|
||||
}
|
||||
|
||||
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request to the
|
||||
// exchange and returns an error
|
||||
func (g *Gemini) SendAuthenticatedHTTPRequest(method, path string, params map[string]interface{}, result interface{}) (err error) {
|
||||
if !g.AuthenticatedAPISupport {
|
||||
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, g.Name)
|
||||
@@ -269,8 +405,9 @@ func (g *Gemini) SendAuthenticatedHTTPRequest(method, path string, params map[st
|
||||
g.Nonce.Inc()
|
||||
}
|
||||
|
||||
headers := make(map[string]string)
|
||||
request := make(map[string]interface{})
|
||||
request["request"] = fmt.Sprintf("/v%s/%s", GEMINI_API_VERSION, path)
|
||||
request["request"] = fmt.Sprintf("/v%s/%s", geminiAPIVersion, path)
|
||||
request["nonce"] = g.Nonce.Get()
|
||||
|
||||
if params != nil {
|
||||
@@ -280,7 +417,6 @@ func (g *Gemini) SendAuthenticatedHTTPRequest(method, path string, params map[st
|
||||
}
|
||||
|
||||
PayloadJSON, err := common.JSONEncode(request)
|
||||
|
||||
if err != nil {
|
||||
return errors.New("SendAuthenticatedHTTPRequest: Unable to JSON request")
|
||||
}
|
||||
@@ -291,21 +427,32 @@ func (g *Gemini) SendAuthenticatedHTTPRequest(method, path string, params map[st
|
||||
|
||||
PayloadBase64 := common.Base64Encode(PayloadJSON)
|
||||
hmac := common.GetHMAC(common.HashSHA512_384, []byte(PayloadBase64), []byte(g.APISecret))
|
||||
headers := make(map[string]string)
|
||||
|
||||
headers["X-GEMINI-APIKEY"] = g.APIKey
|
||||
headers["X-GEMINI-PAYLOAD"] = PayloadBase64
|
||||
headers["X-GEMINI-SIGNATURE"] = common.HexEncodeToString(hmac)
|
||||
|
||||
resp, err := common.SendHTTPRequest(method, GEMINI_API_URL+path, headers, strings.NewReader(""))
|
||||
resp, err := common.SendHTTPRequest(method, g.APIUrl+"/v1/"+path, headers, strings.NewReader(""))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if g.Verbose {
|
||||
log.Printf("Received raw: \n%s\n", resp)
|
||||
}
|
||||
|
||||
err = common.JSONDecode([]byte(resp), &result)
|
||||
captureErr := ErrorCapture{}
|
||||
if err = common.JSONDecode([]byte(resp), &captureErr); err == nil {
|
||||
if len(captureErr.Message) != 0 || len(captureErr.Result) != 0 || len(captureErr.Reason) != 0 {
|
||||
if captureErr.Result != "ok" {
|
||||
return errors.New(captureErr.Message)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = common.JSONDecode([]byte(resp), &result)
|
||||
if err != nil {
|
||||
return errors.New("unable to JSON Unmarshal response")
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
Reference in New Issue
Block a user