diff --git a/config/config.go b/config/config.go index 5a156b51..d944cddf 100644 --- a/config/config.go +++ b/config/config.go @@ -104,6 +104,7 @@ type ExchangeConfig struct { Enabled bool Verbose bool Websocket bool + UseSandbox bool RESTPollingDelay time.Duration AuthenticatedAPISupport bool APIKey string diff --git a/exchanges/gdax/gdax.go b/exchanges/gdax/gdax.go index bbf7cc33..9f9cf279 100644 --- a/exchanges/gdax/gdax.go +++ b/exchanges/gdax/gdax.go @@ -16,6 +16,7 @@ import ( const ( gdaxAPIURL = "https://api.gdax.com/" + gdaxSandboxAPIURL = "https://public.sandbox.gdax.com" gdaxAPIVersion = "0" gdaxProducts = "products" gdaxOrderbook = "book" @@ -69,6 +70,7 @@ func (g *GDAX) SetDefaults() { g.ConfigCurrencyPairFormat.Delimiter = "" g.ConfigCurrencyPairFormat.Uppercase = true g.AssetTypes = []string{ticker.Spot} + g.APIUrl = gdaxAPIURL } // Setup initialises the exchange parameters with the current configuration @@ -85,6 +87,9 @@ func (g *GDAX) Setup(exch config.ExchangeConfig) { g.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",") g.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",") g.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",") + if exch.UseSandbox { + g.APIUrl = gdaxSandboxAPIURL + } err := g.SetCurrencyPairFormat() if err != nil { log.Fatal(err) @@ -110,17 +115,17 @@ func (g *GDAX) GetProducts() ([]Product, error) { products := []Product{} return products, - common.SendHTTPGetRequest(gdaxAPIURL+gdaxProducts, true, g.Verbose, &products) + common.SendHTTPGetRequest(g.APIUrl+gdaxProducts, true, g.Verbose, &products) } // GetOrderbook returns orderbook by currency pair and level func (g *GDAX) GetOrderbook(symbol string, level int) (interface{}, error) { orderbook := OrderbookResponse{} - path := fmt.Sprintf("%s/%s/%s", gdaxAPIURL+gdaxProducts, symbol, gdaxOrderbook) + path := fmt.Sprintf("%s/%s/%s", g.APIUrl+gdaxProducts, symbol, gdaxOrderbook) if level > 0 { levelStr := strconv.Itoa(level) - path = fmt.Sprintf("%s/%s/%s?level=%s", gdaxAPIURL+gdaxProducts, symbol, gdaxOrderbook, levelStr) + path = fmt.Sprintf("%s/%s/%s?level=%s", g.APIUrl+gdaxProducts, symbol, gdaxOrderbook, levelStr) } if err := common.SendHTTPGetRequest(path, true, g.Verbose, &orderbook); err != nil { @@ -190,7 +195,7 @@ func (g *GDAX) GetOrderbook(symbol string, level int) (interface{}, error) { func (g *GDAX) GetTicker(currencyPair string) (Ticker, error) { ticker := Ticker{} path := fmt.Sprintf( - "%s/%s/%s", gdaxAPIURL+gdaxProducts, currencyPair, gdaxTicker) + "%s/%s/%s", g.APIUrl+gdaxProducts, currencyPair, gdaxTicker) log.Println(path) return ticker, common.SendHTTPGetRequest(path, true, g.Verbose, &ticker) @@ -201,7 +206,7 @@ func (g *GDAX) GetTicker(currencyPair string) (Ticker, error) { func (g *GDAX) GetTrades(currencyPair string) ([]Trade, error) { trades := []Trade{} path := fmt.Sprintf( - "%s/%s/%s", gdaxAPIURL+gdaxProducts, currencyPair, gdaxTrades) + "%s/%s/%s", g.APIUrl+gdaxProducts, currencyPair, gdaxTrades) return trades, common.SendHTTPGetRequest(path, true, g.Verbose, &trades) } @@ -226,7 +231,7 @@ func (g *GDAX) GetHistoricRates(currencyPair string, start, end, granularity int } path := common.EncodeURLValues( - fmt.Sprintf("%s/%s/%s", gdaxAPIURL+gdaxProducts, currencyPair, gdaxHistory), + fmt.Sprintf("%s/%s/%s", g.APIUrl+gdaxProducts, currencyPair, gdaxHistory), values) if err := common.SendHTTPGetRequest(path, true, g.Verbose, &resp); err != nil { @@ -253,7 +258,7 @@ func (g *GDAX) GetHistoricRates(currencyPair string, start, end, granularity int func (g *GDAX) GetStats(currencyPair string) (Stats, error) { stats := Stats{} path := fmt.Sprintf( - "%s/%s/%s", gdaxAPIURL+gdaxProducts, currencyPair, gdaxStats) + "%s/%s/%s", g.APIUrl+gdaxProducts, currencyPair, gdaxStats) return stats, common.SendHTTPGetRequest(path, true, g.Verbose, &stats) } @@ -264,7 +269,7 @@ func (g *GDAX) GetCurrencies() ([]Currency, error) { currencies := []Currency{} return currencies, - common.SendHTTPGetRequest(gdaxAPIURL+gdaxCurrencies, true, g.Verbose, ¤cies) + common.SendHTTPGetRequest(g.APIUrl+gdaxCurrencies, true, g.Verbose, ¤cies) } // GetServerTime returns the API server time @@ -272,7 +277,7 @@ func (g *GDAX) GetServerTime() (ServerTime, error) { serverTime := ServerTime{} return serverTime, - common.SendHTTPGetRequest(gdaxAPIURL+gdaxTime, true, g.Verbose, &serverTime) + common.SendHTTPGetRequest(g.APIUrl+gdaxTime, true, g.Verbose, &serverTime) } // GetAccounts returns a list of trading accounts associated with the APIKEYS @@ -487,7 +492,7 @@ func (g *GDAX) GetOrders(status []string, currencyPair string) ([]GeneralizedOrd params.Set("product_id", currencyPair) } - path := common.EncodeURLValues(gdaxAPIURL+gdaxOrders, params) + path := common.EncodeURLValues(g.APIUrl+gdaxOrders, params) path = common.GetURIPath(path) return resp, @@ -517,7 +522,7 @@ func (g *GDAX) GetFills(orderID, currencyPair string) ([]FillResponse, error) { return resp, errors.New("no parameters set") } - path := common.EncodeURLValues(gdaxAPIURL+gdaxFills, params) + path := common.EncodeURLValues(g.APIUrl+gdaxFills, params) uri := common.GetURIPath(path) return resp, @@ -533,7 +538,7 @@ func (g *GDAX) GetFundingRecords(status string) ([]Funding, error) { params := url.Values{} params.Set("status", status) - path := common.EncodeURLValues(gdaxAPIURL+gdaxFunding, params) + path := common.EncodeURLValues(g.APIUrl+gdaxFunding, params) uri := common.GetURIPath(path) return resp, @@ -782,7 +787,7 @@ func (g *GDAX) SendAuthenticatedHTTPRequest(method, path string, params map[stri headers["CB-ACCESS-PASSPHRASE"] = g.ClientID headers["Content-Type"] = "application/json" - resp, err := common.SendHTTPRequest(method, gdaxAPIURL+path, headers, bytes.NewBuffer(payload)) + resp, err := common.SendHTTPRequest(method, g.APIUrl+path, headers, bytes.NewBuffer(payload)) if err != nil { return err } diff --git a/exchanges/gemini/gemini.go b/exchanges/gemini/gemini.go index e21844f4..eefd5320 100644 --- a/exchanges/gemini/gemini.go +++ b/exchanges/gemini/gemini.go @@ -125,6 +125,9 @@ func (g *Gemini) Setup(exch config.ExchangeConfig) { g.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",") g.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",") g.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",") + if exch.UseSandbox { + g.APIUrl = geminiSandboxAPIURL + } err := g.SetCurrencyPairFormat() if err != nil { log.Fatal(err) @@ -139,7 +142,7 @@ func (g *Gemini) Setup(exch config.ExchangeConfig) { // 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) + path := fmt.Sprintf("%s/v%s/%s", g.APIUrl, geminiAPIVersion, geminiSymbols) return symbols, common.SendHTTPGetRequest(path, true, g.Verbose, &symbols) } @@ -156,7 +159,7 @@ func (g *Gemini) GetTicker(currencyPair string) (Ticker, error) { ticker := Ticker{} resp := TickerResponse{} - path := fmt.Sprintf("%s/v%s/%s/%s", geminiAPIURL, geminiAPIVersion, geminiTicker, currencyPair) + path := fmt.Sprintf("%s/v%s/%s/%s", g.APIUrl, geminiAPIVersion, geminiTicker, currencyPair) err := common.SendHTTPGetRequest(path, true, g.Verbose, &resp) if err != nil { @@ -182,7 +185,7 @@ func (g *Gemini) GetTicker(currencyPair string) (Ticker, error) { // 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) + path := common.EncodeURLValues(fmt.Sprintf("%s/v%s/%s/%s", g.APIUrl, geminiAPIVersion, geminiOrderbook, currencyPair), params) orderbook := Orderbook{} return orderbook, common.SendHTTPGetRequest(path, true, g.Verbose, &orderbook) @@ -198,7 +201,7 @@ func (g *Gemini) GetOrderbook(currencyPair string, params url.Values) (Orderbook // 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) + path := common.EncodeURLValues(fmt.Sprintf("%s/v%s/%s/%s", g.APIUrl, geminiAPIVersion, geminiTrades, currencyPair), params) trades := []Trade{} return trades, common.SendHTTPGetRequest(path, true, g.Verbose, &trades) @@ -206,7 +209,7 @@ func (g *Gemini) GetTrades(currencyPair string, params url.Values) ([]Trade, err // GetAuction returns auction information func (g *Gemini) GetAuction(currencyPair string) (Auction, error) { - path := fmt.Sprintf("%s/v%s/%s/%s", geminiAPIURL, geminiAPIVersion, geminiAuction, currencyPair) + path := fmt.Sprintf("%s/v%s/%s/%s", g.APIUrl, geminiAPIVersion, geminiAuction, currencyPair) auction := Auction{} return auction, common.SendHTTPGetRequest(path, true, g.Verbose, &auction) @@ -224,7 +227,7 @@ func (g *Gemini) GetAuction(currencyPair string) (Auction, error) { // 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) + path := common.EncodeURLValues(fmt.Sprintf("%s/v%s/%s/%s/%s", g.APIUrl, geminiAPIVersion, geminiAuction, currencyPair, geminiAuctionHistory), params) auctionHist := []AuctionHistory{} return auctionHist, common.SendHTTPGetRequest(path, true, g.Verbose, &auctionHist)