Skip to content
This repository has been archived by the owner on Feb 1, 2024. It is now read-only.

Lazy load exchangelist, closes #126 #128

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions cmd/exchanges.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"

"github.com/stellar/kelp/plugins"
"github.com/stellar/kelp/support/sdk"

"github.com/spf13/cobra"
)
Expand All @@ -15,6 +16,8 @@ var exchanagesCmd = &cobra.Command{

func init() {
exchanagesCmd.Run = func(ccmd *cobra.Command, args []string) {
// call sdk.GetExchangeList() here so we pre-load exchanges before displaying the table
sdk.GetExchangeList()
fmt.Printf(" Exchange\t\t\tTested\t\tTrading\t\tDescription\n")
fmt.Printf(" --------------------------------------------------------------------------------\n")
exchanges := plugins.Exchanges()
Expand Down
26 changes: 17 additions & 9 deletions plugins/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,15 +165,23 @@ type ExchangeContainer struct {
}

// exchanges is a map of all the exchange integrations available
var exchanges map[string]ExchangeContainer
var exchanges *map[string]ExchangeContainer

func init() {
// getExchanges returns a map of all the exchange integrations available
func getExchanges() map[string]ExchangeContainer {
if exchanges == nil {
loadExchanges()
}
return *exchanges
}

func loadExchanges() {
// marked as tested if key exists in this map (regardless of bool value)
testedCcxtExchanges := map[string]bool{
"binance": true,
}

exchanges = map[string]ExchangeContainer{
exchanges = &map[string]ExchangeContainer{
"kraken": ExchangeContainer{
SortOrder: 0,
Description: "Kraken is a popular centralized cryptocurrency exchange",
Expand All @@ -186,13 +194,13 @@ func init() {
}

// add all CCXT exchanges
sortOrderOffset := len(exchanges)
for i, exchangeName := range sdk.ExchangeList {
sortOrderOffset := len(*exchanges)
for i, exchangeName := range sdk.GetExchangeList() {
key := fmt.Sprintf("ccxt-%s", exchangeName)
_, tested := testedCcxtExchanges[exchangeName]
boundExchangeName := exchangeName

exchanges[key] = ExchangeContainer{
(*exchanges)[key] = ExchangeContainer{
SortOrder: uint16(i + sortOrderOffset),
Description: exchangeName + " is automatically added via ccxt-rest",
TradeEnabled: true,
Expand All @@ -211,7 +219,7 @@ func init() {

// MakeExchange is a factory method to make an exchange based on a given type
func MakeExchange(exchangeType string, simMode bool) (api.Exchange, error) {
if exchange, ok := exchanges[exchangeType]; ok {
if exchange, ok := getExchanges()[exchangeType]; ok {
exchangeAPIKey := api.ExchangeAPIKey{Key: "", Secret: ""}
x, e := exchange.makeFn(exchangeFactoryData{
simMode: simMode,
Expand All @@ -228,7 +236,7 @@ func MakeExchange(exchangeType string, simMode bool) (api.Exchange, error) {

// MakeTradingExchange is a factory method to make an exchange based on a given type
func MakeTradingExchange(exchangeType string, apiKeys []api.ExchangeAPIKey, simMode bool) (api.Exchange, error) {
if exchange, ok := exchanges[exchangeType]; ok {
if exchange, ok := getExchanges()[exchangeType]; ok {
if !exchange.TradeEnabled {
return nil, fmt.Errorf("trading is not enabled on this exchange: %s", exchangeType)
}
Expand All @@ -252,5 +260,5 @@ func MakeTradingExchange(exchangeType string, apiKeys []api.ExchangeAPIKey, simM

// Exchanges returns the list of exchanges
func Exchanges() map[string]ExchangeContainer {
return exchanges
return getExchanges()
}
32 changes: 25 additions & 7 deletions support/sdk/ccxt.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,27 +75,45 @@ func MakeInitializedCcxtExchange(exchangeName string, apiKey api.ExchangeAPIKey)
return c, nil
}

// ExchangeList contains a list of supported exchanges
var ExchangeList []string
// exchangeList contains a list of supported exchanges
var exchangeList *[]string

func init() {
e := networking.JSONRequest(http.DefaultClient, "GET", ccxtBaseURL+pathExchanges, "", map[string]string{}, &ExchangeList, "error")
// GetExchangeList gets a list of all supported exchanges
func GetExchangeList() []string {
if exchangeList == nil {
loadExchangeList()
}
return *exchangeList
}

func loadExchangeList() {
var output []string
e := networking.JSONRequest(http.DefaultClient, "GET", ccxtBaseURL+pathExchanges, "", map[string]string{}, &output, "error")
if e != nil {
panic(fmt.Errorf("error getting list of supported exchanges by CCXT: %s", e))
eMsg1 := strings.Contains(e.Error(), "could not execute http request")
eMsg2 := strings.Contains(e.Error(), "http://localhost:3000/exchanges: dial tcp")
eMsg3 := strings.Contains(e.Error(), "connection refused")
if eMsg1 && eMsg2 && eMsg3 {
log.Printf("ccxt-rest is not running on port 3000 so we cannot include those exchanges")
} else {
panic(fmt.Errorf("error getting list of supported exchanges by CCXT: %s", e))
}
}
exchangeList = &output
}

func (c *Ccxt) initialize(apiKey api.ExchangeAPIKey) error {
// validate that exchange name is in the exchange list
exchangeListed := false
for _, name := range ExchangeList {
el := GetExchangeList()
for _, name := range el {
if name == c.exchangeName {
exchangeListed = true
break
}
}
if !exchangeListed {
return fmt.Errorf("exchange name '%s' is not in the list of %d exchanges available: %v", c.exchangeName, len(ExchangeList), ExchangeList)
return fmt.Errorf("exchange name '%s' is not in the list of %d exchanges available: %v", c.exchangeName, len(el), el)
}

// list all the instances of the exchange
Expand Down