mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-14 07:26:47 +00:00
Added new tool for deploying new exchange code standard.
This commit is contained in:
committed by
Adrian Gallagher
parent
fa041104b2
commit
7d5fb56c2a
232
tools/exchange_template/exchange_template.go
Normal file
232
tools/exchange_template/exchange_template.go
Normal file
@@ -0,0 +1,232 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"flag"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
)
|
||||
|
||||
const (
|
||||
packageTests = "%s_test.go"
|
||||
packageTypes = "%s_types.go"
|
||||
packageWrapper = "%s_wrapper.go"
|
||||
packageMain = "%s.go"
|
||||
packageReadme = "README.md"
|
||||
|
||||
exchangePackageLocation = "../../exchanges/"
|
||||
exchangeLocation = "../../exchange.go"
|
||||
)
|
||||
|
||||
var (
|
||||
exchangeDirectory string
|
||||
exchangeTest string
|
||||
exchangeTypes string
|
||||
exchangeWrapper string
|
||||
exchangeMain string
|
||||
exchangeReadme string
|
||||
)
|
||||
|
||||
type exchange struct {
|
||||
Name string
|
||||
CapitalName string
|
||||
Variable string
|
||||
REST bool
|
||||
WS bool
|
||||
FIX bool
|
||||
}
|
||||
|
||||
func main() {
|
||||
var newExchangeName string
|
||||
var websocketSupport, restSupport, fixSupport bool
|
||||
|
||||
flag.StringVar(&newExchangeName, "name", "", "-name [string] adds a new exchange")
|
||||
flag.BoolVar(&websocketSupport, "ws", false, "-websocket adds websocket support")
|
||||
flag.BoolVar(&restSupport, "rest", false, "-rest adds REST support")
|
||||
flag.BoolVar(&fixSupport, "fix", false, "-fix adds FIX support?")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
fmt.Println("GoCryptoTrader: Exchange templating tool.")
|
||||
|
||||
if newExchangeName == "" || newExchangeName == " " {
|
||||
log.Fatal(`GoCryptoTrader: Exchange templating tool exchange name not set e.g. "exchange_template -name [newExchangeNameString]"`)
|
||||
}
|
||||
|
||||
if !websocketSupport && !restSupport && !fixSupport {
|
||||
log.Fatal(`GoCryptoTrader: Exchange templating tool support not set e.g. "exchange_template -name [newExchangeNameString] [-fix -ws -rest]"`)
|
||||
}
|
||||
|
||||
fmt.Println("Exchange Name: ", newExchangeName)
|
||||
fmt.Println("Websocket Supported: ", websocketSupport)
|
||||
fmt.Println("REST Supported: ", restSupport)
|
||||
fmt.Println("FIX Supported: ", fixSupport)
|
||||
fmt.Println()
|
||||
fmt.Println("Please check if everything is correct then press enter to continue...")
|
||||
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
choice, _, err := reader.ReadRune()
|
||||
if err != nil {
|
||||
log.Fatal("GoCryptoTrader: Exchange templating tool bufio.reader error ", err)
|
||||
}
|
||||
|
||||
if choice != '\n' {
|
||||
log.Fatal("GoCryptoTrader: Exchange templating tool stopped...")
|
||||
}
|
||||
|
||||
newExchangeName = common.StringToLower(newExchangeName)
|
||||
split := strings.Split(newExchangeName, "")
|
||||
v := split[0]
|
||||
capName := common.StringToUpper(v) + strings.Join(split[1:], "")
|
||||
|
||||
exch := exchange{
|
||||
Name: newExchangeName,
|
||||
CapitalName: capName,
|
||||
Variable: v,
|
||||
REST: restSupport,
|
||||
WS: websocketSupport,
|
||||
FIX: fixSupport,
|
||||
}
|
||||
|
||||
configTestFile := config.GetConfig()
|
||||
err = configTestFile.LoadConfig("../../testdata/configtest.json")
|
||||
if err != nil {
|
||||
log.Fatal("GoCryptoTrader: Exchange templating configuration retrieval error ", err)
|
||||
}
|
||||
// NOTE need to nullify encrypt configuration
|
||||
|
||||
var configTestExchanges []string
|
||||
|
||||
for _, exch := range configTestFile.Exchanges {
|
||||
configTestExchanges = append(configTestExchanges, exch.Name)
|
||||
}
|
||||
|
||||
if common.StringDataContainsUpper(configTestExchanges, capName) {
|
||||
log.Fatal("GoCryptoTrader: Exchange templating configuration error - exchange already exists")
|
||||
}
|
||||
|
||||
newExchConfig := config.ExchangeConfig{}
|
||||
newExchConfig.Name = capName
|
||||
newExchConfig.Enabled = true
|
||||
newExchConfig.RESTPollingDelay = 10
|
||||
newExchConfig.APIKey = "Key"
|
||||
newExchConfig.APISecret = "Secret"
|
||||
newExchConfig.AssetTypes = "SPOT"
|
||||
|
||||
configTestFile.Exchanges = append(configTestFile.Exchanges, newExchConfig)
|
||||
// TODO sorting function so exchanges are in alphabetical order - low priority
|
||||
|
||||
err = configTestFile.SaveConfig("../../testdata/configtest.json")
|
||||
if err != nil {
|
||||
log.Fatal("GoCryptoTrader: Exchange templating configuration error - cannot save")
|
||||
}
|
||||
|
||||
exchangeDirectory = exchangePackageLocation + newExchangeName + "/"
|
||||
exchangeTest = fmt.Sprintf(exchangeDirectory+packageTests, newExchangeName)
|
||||
exchangeTypes = fmt.Sprintf(exchangeDirectory+packageTypes, newExchangeName)
|
||||
exchangeWrapper = fmt.Sprintf(exchangeDirectory+packageWrapper, newExchangeName)
|
||||
exchangeMain = fmt.Sprintf(exchangeDirectory+packageMain, newExchangeName)
|
||||
exchangeReadme = exchangeDirectory + packageReadme
|
||||
|
||||
err = os.Mkdir(exchangeDirectory, 0700)
|
||||
if err != nil {
|
||||
log.Fatal("GoCryptoTrader: Exchange templating tool cannot make directory ", err)
|
||||
}
|
||||
|
||||
tReadme, err := template.New("readme").ParseFiles("readme_file.tmpl")
|
||||
if err != nil {
|
||||
log.Fatal("GoCryptoTrader: Exchange templating tool error ", err)
|
||||
}
|
||||
newFile(exchangeReadme)
|
||||
r1, err := os.OpenFile(exchangeReadme, os.O_WRONLY, 0700)
|
||||
if err != nil {
|
||||
log.Fatal("GoCryptoTrader: Exchange templating tool cannot open file ", err)
|
||||
}
|
||||
tReadme.Execute(r1, exch)
|
||||
|
||||
tMain, err := template.New("main").ParseFiles("main_file.tmpl")
|
||||
if err != nil {
|
||||
log.Fatal("GoCryptoTrader: Exchange templating tool error ", err)
|
||||
}
|
||||
newFile(exchangeMain)
|
||||
m1, err := os.OpenFile(exchangeMain, os.O_WRONLY, 0700)
|
||||
if err != nil {
|
||||
log.Fatal("GoCryptoTrader: Exchange templating tool cannot open file ", err)
|
||||
}
|
||||
tMain.Execute(m1, exch)
|
||||
|
||||
tTest, err := template.New("test").ParseFiles("test_file.tmpl")
|
||||
if err != nil {
|
||||
log.Fatal("GoCryptoTrader: Exchange templating tool error ", err)
|
||||
}
|
||||
newFile(exchangeTest)
|
||||
t1, err := os.OpenFile(exchangeTest, os.O_WRONLY, 0700)
|
||||
if err != nil {
|
||||
log.Fatal("GoCryptoTrader: Exchange templating tool cannot open file ", err)
|
||||
}
|
||||
tTest.Execute(t1, exch)
|
||||
|
||||
tType, err := template.New("type").ParseFiles("type_file.tmpl")
|
||||
if err != nil {
|
||||
log.Fatal("GoCryptoTrader: Exchange templating tool error ", err)
|
||||
}
|
||||
newFile(exchangeTypes)
|
||||
ty1, err := os.OpenFile(exchangeTypes, os.O_WRONLY, 0700)
|
||||
if err != nil {
|
||||
log.Fatal("GoCryptoTrader: Exchange templating tool cannot open file ", err)
|
||||
}
|
||||
tType.Execute(ty1, exch)
|
||||
|
||||
tWrapper, err := template.New("wrapper").ParseFiles("wrapper_file.tmpl")
|
||||
if err != nil {
|
||||
log.Fatal("GoCryptoTrader: Exchange templating tool error ", err)
|
||||
}
|
||||
newFile(exchangeWrapper)
|
||||
w1, err := os.OpenFile(exchangeWrapper, os.O_WRONLY, 0700)
|
||||
if err != nil {
|
||||
log.Fatal("GoCryptoTrader: Exchange templating tool cannot open file ", err)
|
||||
}
|
||||
tWrapper.Execute(w1, exch)
|
||||
|
||||
err = exec.Command("go", "fmt", exchangeDirectory).Run()
|
||||
if err != nil {
|
||||
log.Fatal("GoCryptoTrader: Exchange templating tool go fmt error ", err)
|
||||
}
|
||||
|
||||
err = exec.Command("go", "fmt", exchangeDirectory).Run()
|
||||
if err != nil {
|
||||
log.Fatal("GoCryptoTrader: Exchange templating tool go fmt error ", err)
|
||||
}
|
||||
|
||||
err = exec.Command("go", "test", exchangeDirectory).Run()
|
||||
if err != nil {
|
||||
log.Fatal("GoCryptoTrader: Exchange templating tool testing failed ", err)
|
||||
}
|
||||
|
||||
fmt.Println("GoCryptoTrader: Exchange templating tool service complete")
|
||||
fmt.Println("When wrapper is finished add exchange to exchange.go")
|
||||
fmt.Println("Test exchange.go")
|
||||
fmt.Println("Update the config_test.go file")
|
||||
fmt.Println("Test config.go")
|
||||
fmt.Println("Open a pull request")
|
||||
fmt.Println("If help is needed please post a message on the slack.")
|
||||
}
|
||||
|
||||
func newFile(path string) {
|
||||
_, err := os.Stat(path)
|
||||
|
||||
if os.IsNotExist(err) {
|
||||
var file, err = os.Create(path)
|
||||
defer file.Close()
|
||||
if err != nil {
|
||||
log.Fatal("GoCryptoTrader: Exchange templating tool file creation error ", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
66
tools/exchange_template/main_file.tmpl
Normal file
66
tools/exchange_template/main_file.tmpl
Normal file
@@ -0,0 +1,66 @@
|
||||
{{define "main"}}
|
||||
package {{.Name}}
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
// {{.CapitalName}} is the overarching type across this package
|
||||
type {{.CapitalName}} struct {
|
||||
exchange.Base
|
||||
}
|
||||
|
||||
const (
|
||||
{{.Name}}APIURL = ""
|
||||
{{.Name}}APIVersion = ""
|
||||
|
||||
// Public endpoints
|
||||
|
||||
// Authenticated endpoints
|
||||
|
||||
)
|
||||
|
||||
// SetDefaults sets the basic defaults for {{.CapitalName}}
|
||||
func ({{.Variable}} *{{.CapitalName}}) SetDefaults() {
|
||||
{{.Variable}}.Name = "{{.CapitalName}}"
|
||||
{{.Variable}}.Enabled = false
|
||||
{{.Variable}}.Verbose = false
|
||||
{{.Variable}}.Websocket = false
|
||||
{{.Variable}}.RESTPollingDelay = 10
|
||||
{{.Variable}}.RequestCurrencyPairFormat.Delimiter = ""
|
||||
{{.Variable}}.RequestCurrencyPairFormat.Uppercase = true
|
||||
{{.Variable}}.ConfigCurrencyPairFormat.Delimiter = ""
|
||||
{{.Variable}}.ConfigCurrencyPairFormat.Uppercase = true
|
||||
{{.Variable}}.AssetTypes = []string{ticker.Spot}
|
||||
}
|
||||
|
||||
// Setup takes in the supplied exchange configuration details and sets params
|
||||
func ({{.Variable}} *{{.CapitalName}}) Setup(exch config.ExchangeConfig) {
|
||||
if !exch.Enabled {
|
||||
{{.Variable}}.SetEnabled(false)
|
||||
} else {
|
||||
{{.Variable}}.Enabled = true
|
||||
{{.Variable}}.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
{{.Variable}}.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
|
||||
{{.Variable}}.RESTPollingDelay = exch.RESTPollingDelay
|
||||
{{.Variable}}.Verbose = exch.Verbose
|
||||
{{.Variable}}.Websocket = exch.Websocket
|
||||
{{.Variable}}.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",")
|
||||
{{.Variable}}.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",")
|
||||
{{.Variable}}.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",")
|
||||
err := {{.Variable}}.SetCurrencyPairFormat()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = {{.Variable}}.SetAssetTypes()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
{{end}}
|
||||
31
tools/exchange_template/readme_file.tmpl
Normal file
31
tools/exchange_template/readme_file.tmpl
Normal file
@@ -0,0 +1,31 @@
|
||||
{{- define "readme"}}
|
||||
# GoCryptoTrader {{.CapitalName}} Exchange Wrapper
|
||||
|
||||
<img src="https://github.com/thrasher-/gocryptotrader/blob/master/web/src/assets/page-logo.png?raw=true" width="350px" height="350px" hspace="70">
|
||||
|
||||
An exchange interface wrapper for the GoCryptoTrader application.
|
||||
|
||||
## This is still in active development
|
||||
|
||||
You can track ideas, planned features and what's in progresss on this Trello board: [https://trello.com/b/ZAhMhpOy/gocryptotrader](https://trello.com/b/ZAhMhpOy/gocryptotrader).
|
||||
|
||||
## Current {{.CapitalName}} Exchange Features
|
||||
|
||||
{{if .REST}}+ REST Support {{end}}
|
||||
{{if .WS}}+ Websocket Support {{end}}
|
||||
{{if .FIX}}+ FIX Support {{end}}
|
||||
+ Can be used as a package
|
||||
|
||||
## Notes
|
||||
|
||||
+ Please add notes here with any production issues
|
||||
+ Please provide link to exchange website and API documentation
|
||||
|
||||
## Contributors
|
||||
|
||||
+ Please add your information
|
||||
|
||||
|User|Github|Contribution|
|
||||
|--|--|--|
|
||||
|AliasGoesHere|https://github.com/AliasGoesHere |WHAT-YOU-DID|
|
||||
{{end}}
|
||||
36
tools/exchange_template/test_file.tmpl
Normal file
36
tools/exchange_template/test_file.tmpl
Normal file
@@ -0,0 +1,36 @@
|
||||
{{define "test"}}
|
||||
package {{.Name}}
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
)
|
||||
|
||||
// Please supply your own keys here for due diligence testing
|
||||
const (
|
||||
testAPIKey = ""
|
||||
testAPISecret = ""
|
||||
)
|
||||
|
||||
var {{.Variable}} {{.CapitalName}}
|
||||
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
{{.Variable}}.SetDefaults()
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
cfg := config.GetConfig()
|
||||
cfg.LoadConfig("../../testdata/configtest.json")
|
||||
{{.Name}}Config, err := cfg.GetExchangeConfig("{{.CapitalName}}")
|
||||
if err != nil {
|
||||
t.Error("Test Failed - {{.CapitalName}} Setup() init error")
|
||||
}
|
||||
|
||||
{{.Name}}Config.AuthenticatedAPISupport = true
|
||||
{{.Name}}Config.APIKey = testAPIKey
|
||||
{{.Name}}Config.APISecret = testAPISecret
|
||||
|
||||
{{.Variable}}.Setup({{.Name}}Config)
|
||||
}
|
||||
{{end}}
|
||||
3
tools/exchange_template/type_file.tmpl
Normal file
3
tools/exchange_template/type_file.tmpl
Normal file
@@ -0,0 +1,3 @@
|
||||
{{define "type"}}
|
||||
package {{.Name}}
|
||||
{{end}}
|
||||
103
tools/exchange_template/wrapper_file.tmpl
Normal file
103
tools/exchange_template/wrapper_file.tmpl
Normal file
@@ -0,0 +1,103 @@
|
||||
{{define "wrapper"}}
|
||||
package {{.Name}}
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"log"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/currency/pair"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
// Start starts the {{.CapitalName}} go routine
|
||||
func ({{.Variable}} *{{.CapitalName}}) Start() {
|
||||
go {{.Variable}}.Run()
|
||||
}
|
||||
|
||||
// Run implements the {{.CapitalName}} wrapper
|
||||
func ({{.Variable}} *{{.CapitalName}}) Run() {
|
||||
if {{.Variable}}.Verbose {
|
||||
log.Printf("%s Websocket: %s. (url: %s).\n", {{.Variable}}.GetName(), common.IsEnabled({{.Variable}}.Websocket), {{.Variable}}.WebsocketURL)
|
||||
log.Printf("%s polling delay: %ds.\n", {{.Variable}}.GetName(), {{.Variable}}.RESTPollingDelay)
|
||||
log.Printf("%s %d currencies enabled: %s.\n", {{.Variable}}.GetName(), len({{.Variable}}.EnabledPairs), {{.Variable}}.EnabledPairs)
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func ({{.Variable}} *{{.CapitalName}}) UpdateTicker(p pair.CurrencyPair, assetType string) (ticker.Price, error) {
|
||||
var tickerPrice ticker.Price
|
||||
// NOTE EXAMPLE FOR GETTING TICKER PRICE
|
||||
//tick, err := {{.Variable}}.GetTickers()
|
||||
//if err != nil {
|
||||
// return tickerPrice, err
|
||||
//}
|
||||
|
||||
//for _, x := range {{.Variable}}.GetEnabledCurrencies() {
|
||||
//curr := exchange.FormatExchangeCurrency({{.Variable}}.Name, x)
|
||||
//for y := range tick {
|
||||
// if tick[y].Symbol == curr.String() {
|
||||
// tickerPrice.Pair = x
|
||||
// tickerPrice.Ask = tick[y].AskPrice
|
||||
// tickerPrice.Bid = tick[y].BidPrice
|
||||
// tickerPrice.High = tick[y].HighPrice
|
||||
// tickerPrice.Last = tick[y].LastPrice
|
||||
// tickerPrice.Low = tick[y].LowPrice
|
||||
// tickerPrice.Volume = tick[y].Volume
|
||||
// ticker.ProcessTicker({{.Variable}}.Name, x, tickerPrice, assetType)
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
//return ticker.GetTicker({{.Variable}}.Name, p, assetType)
|
||||
return tickerPrice, nil // NOTE DO NOT USE AS RETURN
|
||||
}
|
||||
|
||||
// GetTickerPrice returns the ticker for a currency pair
|
||||
func ({{.Variable}} *{{.CapitalName}}) GetTickerPrice(p pair.CurrencyPair, assetType string) (ticker.Price, error) {
|
||||
tickerNew, err := ticker.GetTicker({{.Variable}}.GetName(), p, assetType)
|
||||
if err != nil {
|
||||
return {{.Variable}}.UpdateTicker(p, assetType)
|
||||
}
|
||||
return tickerNew, nil
|
||||
}
|
||||
|
||||
// GetOrderbookEx returns orderbook base on the currency pair
|
||||
func ({{.Variable}} *{{.CapitalName}}) GetOrderbookEx(currency pair.CurrencyPair, assetType string) (orderbook.Base, error) {
|
||||
ob, err := orderbook.GetOrderbook({{.Variable}}.GetName(), currency, assetType)
|
||||
if err != nil {
|
||||
return {{.Variable}}.UpdateOrderbook(currency, assetType)
|
||||
}
|
||||
return ob, nil
|
||||
}
|
||||
|
||||
// UpdateOrderbook updates and returns the orderbook for a currency pair
|
||||
func ({{.Variable}} *{{.CapitalName}}) UpdateOrderbook(p pair.CurrencyPair, assetType string) (orderbook.Base, error) {
|
||||
var orderBook orderbook.Base
|
||||
//NOTE UPDATE ORDERBOOK EXAMPLE
|
||||
//orderbookNew, err := {{.Variable}}.GetOrderBook(exchange.FormatExchangeCurrency({{.Variable}}.Name, p).String(), 1000)
|
||||
//if err != nil {
|
||||
// return orderBook, err
|
||||
//}
|
||||
|
||||
//for _, bids := range orderbookNew.Bids {
|
||||
// orderBook.Bids = append(orderBook.Bids, orderbook.Item{Amount: bids.Quantity, Price: bids.Price})
|
||||
//}
|
||||
|
||||
//for _, asks := range orderbookNew.Asks {
|
||||
// orderBook.Asks = append(orderBook.Asks, orderbook.Item{Amount: asks.Quantity, Price: asks.Price})
|
||||
//}
|
||||
|
||||
//orderbook.ProcessOrderbook(b.GetName(), p, orderBook, assetType)
|
||||
//return orderbook.GetOrderbook({{.Variable}}.Name, p, assetType)
|
||||
return orderBook, nil // NOTE DO NOT USE AS RETURN
|
||||
}
|
||||
|
||||
// GetExchangeAccountInfo retrieves balances for all enabled currencies for the
|
||||
// {{.CapitalName}} exchange
|
||||
func ({{.Variable}} *{{.CapitalName}}) GetExchangeAccountInfo() (exchange.AccountInfo, error) {
|
||||
var response exchange.AccountInfo
|
||||
return response, errors.New("not implemented")
|
||||
}
|
||||
{{end}}
|
||||
Reference in New Issue
Block a user