mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 15:09:42 +00:00
Engine changes
This commit is contained in:
@@ -10,5 +10,5 @@ FROM alpine:latest
|
||||
RUN apk update && apk add --no-cache ca-certificates
|
||||
COPY --from=build /go/bin/gocryptotrader /app/
|
||||
COPY --from=build /go/src/github.com/thrasher-/gocryptotrader/config.json /app/
|
||||
EXPOSE 9050
|
||||
EXPOSE 9050-9053
|
||||
CMD ["/app/gocryptotrader"]
|
||||
|
||||
51
cmd/config_builder/builder.go
Normal file
51
cmd/config_builder/builder.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/engine"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
engine.Bot, err = engine.New()
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to initialise engine. Err: %s", err)
|
||||
}
|
||||
|
||||
log.Printf("Loading exchanges..")
|
||||
var wg sync.WaitGroup
|
||||
for x := range exchange.Exchanges {
|
||||
name := exchange.Exchanges[x]
|
||||
err = engine.LoadExchange(name, true, &wg)
|
||||
if err != nil {
|
||||
log.Printf("Failed to load exchange %s. Err: %s", name, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
wg.Wait()
|
||||
log.Println("Done.")
|
||||
|
||||
var cfgs []config.ExchangeConfig
|
||||
for x := range engine.Bot.Exchanges {
|
||||
var cfg *config.ExchangeConfig
|
||||
cfg, err = engine.Bot.Exchanges[x].GetDefaultConfig()
|
||||
if err != nil {
|
||||
log.Printf("Failed to get exchanges default config. Err: %s", err)
|
||||
continue
|
||||
}
|
||||
log.Printf("Adding %s", engine.Bot.Exchanges[x].GetName())
|
||||
cfgs = append(cfgs, *cfg)
|
||||
}
|
||||
|
||||
data, err := json.MarshalIndent(cfgs, "", " ")
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to marshal cfgs. Err: %s", err)
|
||||
}
|
||||
|
||||
log.Println(string(data))
|
||||
}
|
||||
@@ -33,22 +33,22 @@ main.go
|
||||
```go
|
||||
var a exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "ANX" {
|
||||
a = bot.exchanges[i]
|
||||
for i := range bot.Exchanges {
|
||||
if bot.Exchanges[i].GetName() == "ANX" {
|
||||
a = bot.Exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := a.GetTickerPrice()
|
||||
tick, err := a.FetchTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := a.GetOrderbookEx()
|
||||
ob, err := a.FetchOrderbook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -30,22 +30,22 @@ main.go
|
||||
```go
|
||||
var b exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "Binance" {
|
||||
b = bot.exchanges[i]
|
||||
for i := range bot.Exchanges {
|
||||
if bot.Exchanges[i].GetName() == "Binance" {
|
||||
b = bot.Exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := b.GetTickerPrice()
|
||||
tick, err := b.FetchTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := b.GetOrderbookEx()
|
||||
ob, err := b.FetchOrderbook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -30,22 +30,22 @@ main.go
|
||||
```go
|
||||
var b exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "Bitfinex" {
|
||||
b = bot.exchanges[i]
|
||||
for i := range bot.Exchanges {
|
||||
if bot.Exchanges[i].GetName() == "Bitfinex" {
|
||||
b = bot.Exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := b.GetTickerPrice()
|
||||
tick, err := b.FetchTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := b.GetOrderbookEx()
|
||||
ob, err := b.FetchOrderbook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -29,22 +29,22 @@ main.go
|
||||
```go
|
||||
var b exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "Bitflyer" {
|
||||
b = bot.exchanges[i]
|
||||
for i := range bot.Exchanges {
|
||||
if bot.Exchanges[i].GetName() == "Bitflyer" {
|
||||
b = bot.Exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := b.GetTickerPrice()
|
||||
tick, err := b.FetchTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := b.GetOrderbookEx()
|
||||
ob, err := b.FetchOrderbook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -29,22 +29,22 @@ main.go
|
||||
```go
|
||||
var b exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "Bithumb" {
|
||||
b = bot.exchanges[i]
|
||||
for i := range bot.Exchanges {
|
||||
if bot.Exchanges[i].GetName() == "Bithumb" {
|
||||
b = bot.Exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := b.GetTickerPrice()
|
||||
tick, err := b.FetchTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := b.GetOrderbookEx()
|
||||
ob, err := b.FetchOrderbook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -29,22 +29,22 @@ main.go
|
||||
```go
|
||||
var b exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "Bitmex" {
|
||||
b = bot.exchanges[i]
|
||||
for i := range bot.Exchanges {
|
||||
if bot.Exchanges[i].GetName() == "Bitmex" {
|
||||
b = bot.Exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := b.GetTickerPrice()
|
||||
tick, err := b.FetchTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := b.GetOrderbookEx()
|
||||
ob, err := b.FetchOrderbook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -30,22 +30,22 @@ main.go
|
||||
```go
|
||||
var b exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "Bitstamp" {
|
||||
b = bot.exchanges[i]
|
||||
for i := range bot.Exchanges {
|
||||
if bot.Exchanges[i].GetName() == "Bitstamp" {
|
||||
b = bot.Exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := b.GetTickerPrice()
|
||||
tick, err := b.FetchTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := b.GetOrderbookEx()
|
||||
ob, err := b.FetchOrderbook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -29,22 +29,22 @@ main.go
|
||||
```go
|
||||
var b exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "Bittrex" {
|
||||
b = bot.exchanges[i]
|
||||
for i := range bot.Exchanges {
|
||||
if bot.Exchanges[i].GetName() == "Bittrex" {
|
||||
b = bot.Exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := b.GetTickerPrice()
|
||||
tick, err := b.FetchTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := b.GetOrderbookEx()
|
||||
ob, err := b.FetchOrderbook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -30,22 +30,22 @@ main.go
|
||||
```go
|
||||
var b exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "BTCC" {
|
||||
b = bot.exchanges[i]
|
||||
for i := range bot.Exchanges {
|
||||
if bot.Exchanges[i].GetName() == "BTCC" {
|
||||
b = bot.Exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := b.GetTickerPrice()
|
||||
tick, err := b.FetchTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := b.GetOrderbookEx()
|
||||
ob, err := b.FetchOrderbook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -29,22 +29,22 @@ main.go
|
||||
```go
|
||||
var b exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "BTCMarkets" {
|
||||
b = bot.exchanges[i]
|
||||
for i := range bot.Exchanges {
|
||||
if bot.Exchanges[i].GetName() == "BTCMarkets" {
|
||||
b = bot.Exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := b.GetTickerPrice()
|
||||
tick, err := b.FetchTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := b.GetOrderbookEx()
|
||||
ob, err := b.FetchOrderbook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -30,22 +30,22 @@ main.go
|
||||
```go
|
||||
var c exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "CoinbasePro" {
|
||||
c = bot.exchanges[i]
|
||||
for i := range bot.Exchanges {
|
||||
if bot.Exchanges[i].GetName() == "CoinbasePro" {
|
||||
c = bot.Exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := c.GetTickerPrice()
|
||||
tick, err := c.FetchTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := c.GetOrderbookEx()
|
||||
ob, err := c.FetchOrderbook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -30,22 +30,22 @@ main.go
|
||||
```go
|
||||
var c exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "Coinut" {
|
||||
c = bot.exchanges[i]
|
||||
for i := range bot.Exchanges {
|
||||
if bot.Exchanges[i].GetName() == "Coinut" {
|
||||
c = bot.Exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := c.GetTickerPrice()
|
||||
tick, err := c.FetchTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := c.GetOrderbookEx()
|
||||
ob, err := c.FetchOrderbook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -16,7 +16,7 @@ exchange interface system set by exchange wrapper orderbook functions in
|
||||
Examples below:
|
||||
|
||||
```go
|
||||
ob, err := yobitExchange.GetOrderbookEx()
|
||||
ob, err := yobitExchange.FetchOrderbook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -17,7 +17,7 @@ exchange interface system set by exchange wrapper orderbook functions in
|
||||
Examples below:
|
||||
|
||||
```go
|
||||
tick, err := yobitExchange.GetTickerPrice()
|
||||
tick, err := yobitExchange.FetchTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -29,22 +29,22 @@ main.go
|
||||
```go
|
||||
var e exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "Exmo" {
|
||||
e = bot.exchanges[i]
|
||||
for i := range bot.Exchanges {
|
||||
if bot.Exchanges[i].GetName() == "Exmo" {
|
||||
e = bot.Exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := e.GetTickerPrice()
|
||||
tick, err := e.FetchTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := e.GetOrderbookEx()
|
||||
ob, err := e.FetchOrderbook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -29,22 +29,22 @@ main.go
|
||||
```go
|
||||
var g exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "GateIO" {
|
||||
g = bot.exchanges[i]
|
||||
for i := range bot.Exchanges {
|
||||
if bot.Exchanges[i].GetName() == "GateIO" {
|
||||
g = bot.Exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := g.GetTickerPrice()
|
||||
tick, err := g.FetchTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := g.GetOrderbookEx()
|
||||
ob, err := g.FetchOrderbook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -29,22 +29,22 @@ main.go
|
||||
```go
|
||||
var g exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "Gemini" {
|
||||
g = bot.exchanges[i]
|
||||
for i := range bot.Exchanges {
|
||||
if bot.Exchanges[i].GetName() == "Gemini" {
|
||||
g = bot.Exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := g.GetTickerPrice()
|
||||
tick, err := g.FetchTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := g.GetOrderbookEx()
|
||||
ob, err := g.FetchOrderbook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -30,22 +30,22 @@ main.go
|
||||
```go
|
||||
var h exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "HitBTC" {
|
||||
h = bot.exchanges[i]
|
||||
for i := range bot.Exchanges {
|
||||
if bot.Exchanges[i].GetName() == "HitBTC" {
|
||||
h = bot.Exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := h.GetTickerPrice()
|
||||
tick, err := h.FetchTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := h.GetOrderbookEx()
|
||||
ob, err := h.FetchOrderbook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -29,22 +29,22 @@ main.go
|
||||
```go
|
||||
var h exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "Huobi" {
|
||||
h = bot.exchanges[i]
|
||||
for i := range bot.Exchanges {
|
||||
if bot.Exchanges[i].GetName() == "Huobi" {
|
||||
h = bot.Exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := h.GetTickerPrice()
|
||||
tick, err := h.FetchTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := h.GetOrderbookEx()
|
||||
ob, err := h.FetchOrderbook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -29,22 +29,22 @@ main.go
|
||||
```go
|
||||
var h exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "HuobiHadax" {
|
||||
h = bot.exchanges[i]
|
||||
for i := range bot.Exchanges {
|
||||
if bot.Exchanges[i].GetName() == "HuobiHadax" {
|
||||
h = bot.Exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := h.GetTickerPrice()
|
||||
tick, err := h.FetchTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := h.GetOrderbookEx()
|
||||
ob, err := h.FetchOrderbook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -29,22 +29,22 @@ main.go
|
||||
```go
|
||||
var i exchange.IBotExchange
|
||||
|
||||
for x := range bot.exchanges {
|
||||
if bot.exchanges[x].GetName() == "Itbit" {
|
||||
i = bot.exchanges[x]
|
||||
for x := range bot.Exchanges {
|
||||
if bot.Exchanges[x].GetName() == "Itbit" {
|
||||
i = bot.Exchanges[x]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := i.GetTickerPrice()
|
||||
tick, err := i.FetchTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := i.GetOrderbookEx()
|
||||
ob, err := i.FetchOrderbook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -29,22 +29,22 @@ main.go
|
||||
```go
|
||||
var k exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "Kraken" {
|
||||
k = bot.exchanges[i]
|
||||
for i := range bot.Exchanges {
|
||||
if bot.Exchanges[i].GetName() == "Kraken" {
|
||||
k = bot.Exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := k.GetTickerPrice()
|
||||
tick, err := k.FetchTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := k.GetOrderbookEx()
|
||||
ob, err := k.FetchOrderbook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -29,22 +29,22 @@ main.go
|
||||
```go
|
||||
var l exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "LakeBTC" {
|
||||
l = bot.exchanges[i]
|
||||
for i := range bot.Exchanges {
|
||||
if bot.Exchanges[i].GetName() == "LakeBTC" {
|
||||
l = bot.Exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := l.GetTickerPrice()
|
||||
tick, err := l.FetchTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := l.GetOrderbookEx()
|
||||
ob, err := l.FetchOrderbook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -29,22 +29,22 @@ main.go
|
||||
```go
|
||||
var l exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "LocalBitcoins" {
|
||||
l = bot.exchanges[i]
|
||||
for i := range bot.Exchanges {
|
||||
if bot.Exchanges[i].GetName() == "LocalBitcoins" {
|
||||
l = bot.Exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := l.GetTickerPrice()
|
||||
tick, err := l.FetchTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := l.GetOrderbookEx()
|
||||
ob, err := l.FetchOrderbook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -30,22 +30,22 @@ main.go
|
||||
```go
|
||||
var o exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "OKCoin" {
|
||||
y = bot.exchanges[i]
|
||||
for i := range bot.Exchanges {
|
||||
if bot.Exchanges[i].GetName() == "OKCoin" {
|
||||
y = bot.Exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := o.GetTickerPrice()
|
||||
tick, err := o.FetchTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := o.GetOrderbookEx()
|
||||
ob, err := o.FetchOrderbook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -29,22 +29,22 @@ main.go
|
||||
```go
|
||||
var o exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "OKex" {
|
||||
y = bot.exchanges[i]
|
||||
for i := range bot.Exchanges {
|
||||
if bot.Exchanges[i].GetName() == "OKex" {
|
||||
y = bot.Exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := o.GetTickerPrice()
|
||||
tick, err := o.FetchTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := o.GetOrderbookEx()
|
||||
ob, err := o.FetchOrderbook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -30,22 +30,22 @@ main.go
|
||||
```go
|
||||
var p exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "Poloniex" {
|
||||
y = bot.exchanges[i]
|
||||
for i := range bot.Exchanges {
|
||||
if bot.Exchanges[i].GetName() == "Poloniex" {
|
||||
y = bot.Exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := p.GetTickerPrice()
|
||||
tick, err := p.FetchTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := p.GetOrderbookEx()
|
||||
ob, err := p.FetchOrderbook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -29,22 +29,22 @@ main.go
|
||||
```go
|
||||
var y exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "Yobit" {
|
||||
y = bot.exchanges[i]
|
||||
for i := range bot.Exchanges {
|
||||
if bot.Exchanges[i].GetName() == "Yobit" {
|
||||
y = bot.Exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := y.GetTickerPrice()
|
||||
tick, err := y.FetchTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := y.GetOrderbookEx()
|
||||
ob, err := y.FetchOrderbook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -29,22 +29,22 @@ main.go
|
||||
```go
|
||||
var z exchange.IBotExchange
|
||||
|
||||
for i := range bot.exchanges {
|
||||
if bot.exchanges[i].GetName() == "ZB" {
|
||||
z = bot.exchanges[i]
|
||||
for i := range bot.Exchanges {
|
||||
if bot.Exchanges[i].GetName() == "ZB" {
|
||||
z = bot.Exchanges[i]
|
||||
}
|
||||
}
|
||||
|
||||
// Public calls - wrapper functions
|
||||
|
||||
// Fetches current ticker information
|
||||
tick, err := z.GetTickerPrice()
|
||||
tick, err := z.FetchTicker()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
|
||||
// Fetches current orderbook information
|
||||
ob, err := z.GetOrderbookEx()
|
||||
ob, err := z.FetchOrderbook()
|
||||
if err != nil {
|
||||
// Handle error
|
||||
}
|
||||
@@ -8,6 +8,9 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/assets"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
)
|
||||
@@ -117,10 +120,14 @@ func main() {
|
||||
newExchConfig := config.ExchangeConfig{}
|
||||
newExchConfig.Name = capName
|
||||
newExchConfig.Enabled = true
|
||||
newExchConfig.RESTPollingDelay = 10
|
||||
newExchConfig.APIKey = "Key"
|
||||
newExchConfig.APISecret = "Secret"
|
||||
newExchConfig.AssetTypes = "SPOT"
|
||||
newExchConfig.API.Credentials.Key = "Key"
|
||||
newExchConfig.API.Credentials.Secret = "Secret"
|
||||
|
||||
newExchConfig.CurrencyPairs = ¤cy.PairsManager{
|
||||
AssetTypes: assets.AssetTypes{
|
||||
assets.AssetTypeSpot,
|
||||
},
|
||||
}
|
||||
|
||||
configTestFile.Exchanges = append(configTestFile.Exchanges, newExchConfig)
|
||||
// TODO sorting function so exchanges are in alphabetical order - low priority
|
||||
@@ -32,36 +32,34 @@ func ({{.Variable}} *{{.CapitalName}}) SetDefaults() {
|
||||
{{.Variable}}.Name = "{{.CapitalName}}"
|
||||
{{.Variable}}.Enabled = false
|
||||
{{.Variable}}.Verbose = false
|
||||
{{.Variable}}.RESTPollingDelay = 10
|
||||
{{.Variable}}.RequestCurrencyPairFormat.Delimiter = ""
|
||||
{{.Variable}}.RequestCurrencyPairFormat.Uppercase = true
|
||||
{{.Variable}}.ConfigCurrencyPairFormat.Delimiter = ""
|
||||
{{.Variable}}.ConfigCurrencyPairFormat.Uppercase = true
|
||||
{{.Variable}}.AssetTypes = []string{ticker.Spot}
|
||||
{{.Variable}}.AssetTypes = assets.AssetTypes{assets.AssetTypeSpot}
|
||||
{{.Variable}}.SupportsAutoPairUpdating = false
|
||||
{{.Variable}}.SupportsRESTTickerBatching = false
|
||||
{{.Variable}}.Requester = request.New({{.Variable}}.Name,
|
||||
request.NewRateLimit(time.Second, 0),
|
||||
request.NewRateLimit(time.Second, 0),
|
||||
common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout))
|
||||
{{.Variable}}.APIUrlDefault = {{.Name}}APIURL
|
||||
{{.Variable}}.APIUrl = {{.Variable}}.APIUrlDefault
|
||||
{{.Variable}}.API.Endpoints.URLDefault = {{.Name}}APIURL
|
||||
{{.Variable}}.API.Endpoints.URL = {{.Variable}}.API.Endpoints.URLDefault
|
||||
{{.Variable}}.WebsocketInit()
|
||||
}
|
||||
|
||||
// Setup takes in the supplied exchange configuration details and sets params
|
||||
func ({{.Variable}} *{{.CapitalName}}) Setup(exch *config.ExchangeConfig) {
|
||||
func ({{.Variable}} *{{.CapitalName}}) Setup(exch *config.ExchangeConfig) error {
|
||||
if !exch.Enabled {
|
||||
{{.Variable}}.SetEnabled(false)
|
||||
} else {
|
||||
{{.Variable}}.Enabled = true
|
||||
{{.Variable}}.AuthenticatedAPISupport = exch.AuthenticatedAPISupport
|
||||
{{.Variable}}.SetAPIKeys(exch.APIKey, exch.APISecret, "", false)
|
||||
{{.Variable}}.API.AuthenticatedSupport = exch.API.AuthenticatedSupport
|
||||
{{.Variable}}.SetAPIKeys(exch.API.Credentials.Key, exch.API.Credentials.Secret, "", false)
|
||||
{{.Variable}}.SetHTTPClientTimeout(exch.HTTPTimeout)
|
||||
{{.Variable}}.SetHTTPClientUserAgent(exch.HTTPUserAgent)
|
||||
{{.Variable}}.RESTPollingDelay = exch.RESTPollingDelay
|
||||
{{.Variable}}.Verbose = exch.Verbose
|
||||
{{.Variable}}.Websocket.SetWsStatusAndConnection(exch.Websocket)
|
||||
{{.Variable}}.Websocket.SetWsStatusAndConnection(exch.Features.Enabled.Websocket)
|
||||
{{.Variable}}.BaseCurrencies = common.SplitStrings(exch.BaseCurrencies, ",")
|
||||
{{.Variable}}.AvailablePairs = common.SplitStrings(exch.AvailablePairs, ",")
|
||||
{{.Variable}}.EnabledPairs = common.SplitStrings(exch.EnabledPairs, ",")
|
||||
@@ -73,7 +71,7 @@ func ({{.Variable}} *{{.CapitalName}}) Setup(exch *config.ExchangeConfig) {
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = {{.Variable}}.SetAutoPairDefaults()
|
||||
err = {{.Variable}}.SetFeatureDefaults()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@@ -89,9 +87,9 @@ func ({{.Variable}} *{{.CapitalName}}) Setup(exch *config.ExchangeConfig) {
|
||||
// If the exchange supports websocket, update the below block
|
||||
// err = {{.Variable}}.WebsocketSetup({{.Variable}}.WsConnect,
|
||||
// exch.Name,
|
||||
// exch.Websocket,
|
||||
// exch.Features.Enabled.Websocket,
|
||||
// {{.Name}}Websocket,
|
||||
// exch.WebsocketURL)
|
||||
// exch.Features.Enabled.WebsocketURL)
|
||||
// if err != nil {
|
||||
// log.Fatal(err)
|
||||
// }
|
||||
@@ -27,9 +27,9 @@ func TestSetup(t *testing.T) {
|
||||
t.Error("Test Failed - {{.CapitalName}} Setup() init error")
|
||||
}
|
||||
|
||||
{{.Name}}Config.AuthenticatedAPISupport = true
|
||||
{{.Name}}Config.APIKey = testAPIKey
|
||||
{{.Name}}Config.APISecret = testAPISecret
|
||||
{{.Name}}Config.API.AuthenticatedSupport = true
|
||||
{{.Name}}Config.API.Credentials.Key = testAPIKey
|
||||
{{.Name}}Config.API.Credentials.Secret = testAPISecret
|
||||
|
||||
{{.Variable}}.Setup({{.Name}}Config)
|
||||
}
|
||||
@@ -31,7 +31,7 @@ func ({{.Variable}} *{{.CapitalName}}) Run() {
|
||||
}
|
||||
|
||||
// UpdateTicker updates and returns the ticker for a currency pair
|
||||
func ({{.Variable}} *{{.CapitalName}}) UpdateTicker(p currency.Pair, assetType string) (ticker.Price, error) {
|
||||
func ({{.Variable}} *{{.CapitalName}}) UpdateTicker(p currency.Pair, assetType assets.AssetType) (ticker.Price, error) {
|
||||
var tickerPrice ticker.Price
|
||||
// NOTE EXAMPLE FOR GETTING TICKER PRICE
|
||||
//tick, err := {{.Variable}}.GetTickers()
|
||||
@@ -39,7 +39,7 @@ func ({{.Variable}} *{{.CapitalName}}) UpdateTicker(p currency.Pair, assetType s
|
||||
// return tickerPrice, err
|
||||
//}
|
||||
|
||||
//for _, x := range {{.Variable}}.GetEnabledCurrencies() {
|
||||
//for _, x := range {{.Variable}}.GetEnabledPairs(assetType) {
|
||||
//curr := exchange.FormatExchangeCurrency({{.Variable}}.Name, x)
|
||||
//for y := range tick {
|
||||
// if tick[y].Symbol == curr.String() {
|
||||
@@ -58,8 +58,8 @@ func ({{.Variable}} *{{.CapitalName}}) UpdateTicker(p currency.Pair, assetType s
|
||||
return tickerPrice, nil // NOTE DO NOT USE AS RETURN
|
||||
}
|
||||
|
||||
// GetTickerPrice returns the ticker for a currency pair
|
||||
func ({{.Variable}} *{{.CapitalName}}) GetTickerPrice(p currency.Pair, assetType string) (ticker.Price, error) {
|
||||
// FetchTicker returns the ticker for a currency pair
|
||||
func ({{.Variable}} *{{.CapitalName}}) FetchTicker(p currency.Pair, assetType assets.AssetType) (ticker.Price, error) {
|
||||
tickerNew, err := ticker.GetTicker({{.Variable}}.GetName(), p, assetType)
|
||||
if err != nil {
|
||||
return {{.Variable}}.UpdateTicker(p, assetType)
|
||||
@@ -67,8 +67,8 @@ func ({{.Variable}} *{{.CapitalName}}) GetTickerPrice(p currency.Pair, assetType
|
||||
return tickerNew, nil
|
||||
}
|
||||
|
||||
// GetOrderbookEx returns orderbook base on the currency pair
|
||||
func ({{.Variable}} *{{.CapitalName}}) GetOrderbookEx(currency currency.Pair, assetType string) (orderbook.Base, error) {
|
||||
// FetchOrderbook returns orderbook base on the currency pair
|
||||
func ({{.Variable}} *{{.CapitalName}}) FetchOrderbook(currency currency.Pair, assetType assets.AssetType) (orderbook.Base, error) {
|
||||
ob, err := orderbook.Get({{.Variable}}.GetName(), currency, assetType)
|
||||
if err != nil {
|
||||
return {{.Variable}}.UpdateOrderbook(currency, assetType)
|
||||
@@ -77,7 +77,7 @@ func ({{.Variable}} *{{.CapitalName}}) GetOrderbookEx(currency currency.Pair, as
|
||||
}
|
||||
|
||||
// UpdateOrderbook updates and returns the orderbook for a currency pair
|
||||
func ({{.Variable}} *{{.CapitalName}}) UpdateOrderbook(p currency.Pair, assetType string) (orderbook.Base, error) {
|
||||
func ({{.Variable}} *{{.CapitalName}}) UpdateOrderbook(p currency.Pair, assetType assets.AssetType) (orderbook.Base, error) {
|
||||
var orderBook orderbook.Base
|
||||
//NOTE UPDATE ORDERBOOK EXAMPLE
|
||||
//orderbookNew, err := {{.Variable}}.GetOrderBook(exchange.FormatExchangeCurrency({{.Variable}}.Name, p).String(), 1000)
|
||||
@@ -111,7 +111,7 @@ func ({{.Variable}} *{{.CapitalName}}) GetFundingHistory() ([]exchange.FundHisto
|
||||
}
|
||||
|
||||
// GetExchangeHistory returns historic trade data since exchange opening.
|
||||
func ({{.Variable}} *{{.CapitalName}}) GetExchangeHistory(p currency.Pair, assetType string) ([]exchange.TradeHistory, error) {
|
||||
func ({{.Variable}} *{{.CapitalName}}) GetExchangeHistory(p currency.Pair, assetType assets.AssetType) ([]exchange.TradeHistory, error) {
|
||||
return nil, common.ErrNotYetImplemented
|
||||
}
|
||||
|
||||
174
cmd/exchange_wrapper_coverage/main.go
Normal file
174
cmd/exchange_wrapper_coverage/main.go
Normal file
@@ -0,0 +1,174 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/currency"
|
||||
"github.com/thrasher-/gocryptotrader/engine"
|
||||
exchange "github.com/thrasher-/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/assets"
|
||||
)
|
||||
|
||||
const (
|
||||
totalWrappers = 20
|
||||
)
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
engine.Bot, err = engine.New()
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to initialise engine. Err: %s", err)
|
||||
}
|
||||
|
||||
engine.Bot.Settings = engine.Settings{
|
||||
DisableExchangeAutoPairUpdates: true,
|
||||
}
|
||||
|
||||
log.Printf("Loading exchanges..")
|
||||
var wg sync.WaitGroup
|
||||
for x := range exchange.Exchanges {
|
||||
name := exchange.Exchanges[x]
|
||||
err := engine.LoadExchange(name, true, &wg)
|
||||
if err != nil {
|
||||
log.Printf("Failed to load exchange %s. Err: %s", name, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
wg.Wait()
|
||||
log.Println("Done.")
|
||||
|
||||
log.Printf("Testing exchange wrappers..")
|
||||
results := make(map[string][]string)
|
||||
wg = sync.WaitGroup{}
|
||||
for x := range engine.Bot.Exchanges {
|
||||
wg.Add(1)
|
||||
go func(num int) {
|
||||
name := engine.Bot.Exchanges[num].GetName()
|
||||
results[name] = testWrappers(engine.Bot.Exchanges[num])
|
||||
wg.Done()
|
||||
}(x)
|
||||
}
|
||||
wg.Wait()
|
||||
log.Println("Done.")
|
||||
|
||||
log.Println()
|
||||
for name, funcs := range results {
|
||||
pct := float64(totalWrappers-len(funcs)) / float64(totalWrappers) * 100
|
||||
log.Printf("Exchange %s wrapper coverage [%d/%d - %.2f%%] | Total missing: %d", name, totalWrappers-len(funcs), totalWrappers, pct, len(funcs))
|
||||
log.Printf("\t Wrappers not implemented:")
|
||||
|
||||
for x := range funcs {
|
||||
log.Printf("\t - %s", funcs[x])
|
||||
}
|
||||
log.Println()
|
||||
}
|
||||
}
|
||||
|
||||
func testWrappers(e exchange.IBotExchange) []string {
|
||||
p := currency.NewPair(currency.BTC, currency.USD)
|
||||
assetType := assets.AssetTypeSpot
|
||||
var funcs []string
|
||||
|
||||
_, err := e.FetchTicker(p, assetType)
|
||||
if err == common.ErrNotYetImplemented {
|
||||
funcs = append(funcs, "FetchTicker")
|
||||
}
|
||||
|
||||
_, err = e.UpdateTicker(p, assetType)
|
||||
if err == common.ErrNotYetImplemented {
|
||||
funcs = append(funcs, "UpdateTicker")
|
||||
}
|
||||
|
||||
_, err = e.FetchOrderbook(p, assetType)
|
||||
if err == common.ErrNotYetImplemented {
|
||||
funcs = append(funcs, "FetchOrderbook")
|
||||
}
|
||||
|
||||
_, err = e.UpdateOrderbook(p, assetType)
|
||||
if err == common.ErrNotYetImplemented {
|
||||
funcs = append(funcs, "UpdateOrderbook")
|
||||
}
|
||||
|
||||
_, err = e.FetchTradablePairs(assets.AssetTypeSpot)
|
||||
if err == common.ErrNotYetImplemented {
|
||||
funcs = append(funcs, "FetchTradablePairs")
|
||||
}
|
||||
|
||||
err = e.UpdateTradablePairs(false)
|
||||
if err == common.ErrNotYetImplemented {
|
||||
funcs = append(funcs, "UpdateTradablePairs")
|
||||
}
|
||||
|
||||
_, err = e.GetAccountInfo()
|
||||
if err == common.ErrNotYetImplemented {
|
||||
funcs = append(funcs, "GetAccountInfo")
|
||||
}
|
||||
|
||||
_, err = e.GetExchangeHistory(p, assetType)
|
||||
if err == common.ErrNotYetImplemented {
|
||||
funcs = append(funcs, "GetExchangeHistory")
|
||||
}
|
||||
|
||||
_, err = e.GetFundingHistory()
|
||||
if err == common.ErrNotYetImplemented {
|
||||
funcs = append(funcs, "GetFundingHistory")
|
||||
}
|
||||
|
||||
_, err = e.SubmitOrder(p, exchange.BuyOrderSide, exchange.LimitOrderType, 1000000, 10000000000, "meow")
|
||||
if err == common.ErrNotYetImplemented {
|
||||
funcs = append(funcs, "SubmitOrder")
|
||||
}
|
||||
|
||||
_, err = e.ModifyOrder(&exchange.ModifyOrder{})
|
||||
if err == common.ErrNotYetImplemented {
|
||||
funcs = append(funcs, "ModifyOrder")
|
||||
}
|
||||
|
||||
err = e.CancelOrder(&exchange.OrderCancellation{})
|
||||
if err == common.ErrNotYetImplemented {
|
||||
funcs = append(funcs, "CancelOrder")
|
||||
}
|
||||
|
||||
_, err = e.CancelAllOrders(&exchange.OrderCancellation{})
|
||||
if err == common.ErrNotYetImplemented {
|
||||
funcs = append(funcs, "CancelAllOrders")
|
||||
}
|
||||
|
||||
_, err = e.GetOrderInfo("1")
|
||||
if err == common.ErrNotYetImplemented {
|
||||
funcs = append(funcs, "GetOrderInfo")
|
||||
}
|
||||
|
||||
_, err = e.GetOrderHistory(&exchange.GetOrdersRequest{})
|
||||
if err == common.ErrNotYetImplemented {
|
||||
funcs = append(funcs, "GetOrderHistory")
|
||||
}
|
||||
|
||||
_, err = e.GetActiveOrders(&exchange.GetOrdersRequest{})
|
||||
if err == common.ErrNotYetImplemented {
|
||||
funcs = append(funcs, "GetActiveOrders")
|
||||
}
|
||||
|
||||
_, err = e.GetDepositAddress(currency.BTC, "")
|
||||
if err == common.ErrNotYetImplemented {
|
||||
funcs = append(funcs, "GetDepositAddress")
|
||||
}
|
||||
|
||||
_, err = e.WithdrawCryptocurrencyFunds(&exchange.CryptoWithdrawRequest{})
|
||||
if err == common.ErrNotYetImplemented {
|
||||
funcs = append(funcs, "WithdrawCryptocurrencyFunds")
|
||||
}
|
||||
|
||||
_, err = e.WithdrawFiatFunds(&exchange.FiatWithdrawRequest{})
|
||||
if err == common.ErrNotYetImplemented {
|
||||
funcs = append(funcs, "WithdrawFiatFunds")
|
||||
}
|
||||
_, err = e.WithdrawFiatFundsToInternationalBank(&exchange.FiatWithdrawRequest{})
|
||||
if err == common.ErrNotYetImplemented {
|
||||
funcs = append(funcs, "WithdrawFiatFundsToInternationalBank")
|
||||
}
|
||||
|
||||
return funcs
|
||||
}
|
||||
1502
cmd/gctcli/commands.go
Normal file
1502
cmd/gctcli/commands.go
Normal file
File diff suppressed because it is too large
Load Diff
115
cmd/gctcli/main.go
Normal file
115
cmd/gctcli/main.go
Normal file
@@ -0,0 +1,115 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/core"
|
||||
"github.com/thrasher-/gocryptotrader/gctrpc/auth"
|
||||
"github.com/urfave/cli"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
)
|
||||
|
||||
var (
|
||||
host string
|
||||
username string
|
||||
password string
|
||||
)
|
||||
|
||||
func jsonOutput(in interface{}) {
|
||||
j, err := json.MarshalIndent(in, "", " ")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
fmt.Print(string(j))
|
||||
}
|
||||
|
||||
func setupClient() (*grpc.ClientConn, error) {
|
||||
targetPath := filepath.Join(common.GetDefaultDataDir(runtime.GOOS), "tls", "cert.pem")
|
||||
creds, err := credentials.NewClientTLSFromFile(targetPath, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
opts := []grpc.DialOption{grpc.WithTransportCredentials(creds),
|
||||
grpc.WithPerRPCCredentials(auth.BasicAuth{
|
||||
Username: username,
|
||||
Password: password,
|
||||
}),
|
||||
}
|
||||
conn, err := grpc.Dial(host, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return conn, err
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := cli.NewApp()
|
||||
app.Name = "gctcli"
|
||||
app.Version = core.Version(true)
|
||||
app.Usage = "command line interface for managing the gocryptotrader daemon"
|
||||
app.Flags = []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "rpchost",
|
||||
Value: "localhost:9052",
|
||||
Usage: "the gRPC host to connect to",
|
||||
Destination: &host,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "rpcuser",
|
||||
Value: "admin",
|
||||
Usage: "the gRPC username",
|
||||
Destination: &username,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "rpcpassword",
|
||||
Value: "Password",
|
||||
Usage: "the gRPC password",
|
||||
Destination: &password,
|
||||
},
|
||||
}
|
||||
app.Commands = []cli.Command{
|
||||
getInfoCommand,
|
||||
getExchangesCommand,
|
||||
enableExchangeCommand,
|
||||
disableExchangeCommand,
|
||||
getExchangeInfoCommand,
|
||||
getTickerCommand,
|
||||
getTickersCommand,
|
||||
getOrderbookCommand,
|
||||
getOrderbooksCommand,
|
||||
getAccountInfoCommand,
|
||||
getConfigCommand,
|
||||
getPortfolioCommand,
|
||||
getPortfolioSummaryCommand,
|
||||
addPortfolioAddressCommand,
|
||||
removePortfolioAddressCommand,
|
||||
getForexProvidersCommand,
|
||||
getForexRatesCommand,
|
||||
getOrdersCommand,
|
||||
getOrderCommand,
|
||||
submitOrderCommand,
|
||||
cancelOrderCommand,
|
||||
cancelAllOrdersCommand,
|
||||
getEventsCommand,
|
||||
addEventCommand,
|
||||
removeEventCommand,
|
||||
getCryptocurrencyDepositAddressesCommand,
|
||||
getCryptocurrencyDepositAddressCommand,
|
||||
withdrawCryptocurrencyFundsCommand,
|
||||
withdrawFiatFundsCommand,
|
||||
}
|
||||
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
105
cmd/gen_cert/main.go
Normal file
105
cmd/gen_cert/main.go
Normal file
@@ -0,0 +1,105 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/pem"
|
||||
"log"
|
||||
"math/big"
|
||||
"net"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
)
|
||||
|
||||
func main() {
|
||||
privKey, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to generate private key: %s", err)
|
||||
}
|
||||
|
||||
notBefore := time.Now()
|
||||
notAfter := notBefore.Add(time.Hour * 24 * 365)
|
||||
|
||||
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
|
||||
serialNumber, err := rand.Int(rand.Reader, serialNumberLimit)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to generate serial number: %s", err)
|
||||
}
|
||||
|
||||
host, err := os.Hostname()
|
||||
if err != nil {
|
||||
log.Fatalf("failed to get hostname: %s", err)
|
||||
}
|
||||
|
||||
dnsNames := []string{host}
|
||||
if host != "localhost" {
|
||||
dnsNames = append(dnsNames, "localhost")
|
||||
}
|
||||
|
||||
template := x509.Certificate{
|
||||
SerialNumber: serialNumber,
|
||||
Subject: pkix.Name{
|
||||
Organization: []string{"gocryptotrader"},
|
||||
CommonName: host,
|
||||
},
|
||||
NotBefore: notBefore,
|
||||
NotAfter: notAfter,
|
||||
IsCA: true,
|
||||
BasicConstraintsValid: true,
|
||||
|
||||
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
|
||||
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
|
||||
|
||||
IPAddresses: []net.IP{
|
||||
net.ParseIP("127.0.0.1"),
|
||||
net.ParseIP("::1"),
|
||||
},
|
||||
DNSNames: dnsNames,
|
||||
}
|
||||
|
||||
derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &privKey.PublicKey, privKey)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create certificate: %s", err)
|
||||
}
|
||||
|
||||
certData := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
|
||||
if certData == nil {
|
||||
log.Fatalf("cert data is nil")
|
||||
}
|
||||
|
||||
b, err := x509.MarshalECPrivateKey(privKey)
|
||||
if err != nil {
|
||||
log.Printf("failed to marshal ECDSA private key: %s", err)
|
||||
}
|
||||
|
||||
keyData := pem.EncodeToMemory(&pem.Block{Type: "EC PRIVATE KEY", Bytes: b})
|
||||
if keyData == nil {
|
||||
log.Fatalf("key pem data is nil")
|
||||
}
|
||||
|
||||
err = common.WriteFile("key.pem", keyData)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to write key.pem file %s", err)
|
||||
}
|
||||
log.Printf("wrote key.pem file")
|
||||
|
||||
err = common.WriteFile("cert.pem", certData)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to write cert.pem file %s", err)
|
||||
}
|
||||
log.Printf("wrote cert.pem file")
|
||||
|
||||
log.Printf("testing tls.LoadX509Keypair..")
|
||||
_, err = tls.LoadX509KeyPair("cert.pem", "key.pem")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Printf("ok!")
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -129,19 +130,21 @@ func main() {
|
||||
fmt.Println(string(pubKey))
|
||||
|
||||
type JSONGeneration struct {
|
||||
APIAuthPEMKey string
|
||||
PEMKey string
|
||||
PEMKeySupport bool
|
||||
}
|
||||
|
||||
r := JSONGeneration{
|
||||
APIAuthPEMKey: string(privKey),
|
||||
PEMKey: string(privKey),
|
||||
PEMKeySupport: true,
|
||||
}
|
||||
|
||||
resultk, err := common.JSONEncode(r)
|
||||
resultk, err := json.MarshalIndent(r, "", " ")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
log.Println("Please visit https://github.com/huobiapi/API_Docs_en/wiki/Signing_API_Requests and follow from step 2 onwards.")
|
||||
log.Printf("After completing the above instructions, please copy and paste the below key (including the following ',') into your Huobi exchange config file:\n\n")
|
||||
log.Printf("After completing the above instructions, please copy and paste the below key in the API section (including the following ',') into your Huobi exchange config file:\n\n")
|
||||
fmt.Println(string(resultk[1:len(resultk)-1]) + ",")
|
||||
}
|
||||
57
cmd/otp_gen/otp_gen.go
Normal file
57
cmd/otp_gen/otp_gen.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/pquerna/otp/totp"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
)
|
||||
|
||||
func containsOTP(cfg *config.Config) bool {
|
||||
for x := range cfg.Exchanges {
|
||||
if cfg.Exchanges[x].API.Credentials.OTPSecret != "" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func main() {
|
||||
var inFile string
|
||||
defaultCfg, err := config.GetFilePath("")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
flag.StringVar(&inFile, "infile", defaultCfg, "The config input file to process.")
|
||||
flag.Parse()
|
||||
|
||||
log.Println("GoCryptoTrader: OTP code generator tool.")
|
||||
|
||||
var cfg config.Config
|
||||
err = cfg.LoadConfig(inFile)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
log.Println("Loaded config file.")
|
||||
|
||||
if !containsOTP(&cfg) {
|
||||
log.Println("No exchanges with OTP code stored. Exiting.")
|
||||
}
|
||||
|
||||
for {
|
||||
for x := range cfg.Exchanges {
|
||||
if cfg.Exchanges[x].API.Credentials.OTPSecret != "" {
|
||||
code, err := totp.GenerateCode(cfg.Exchanges[x].API.Credentials.OTPSecret, time.Now())
|
||||
if err != nil {
|
||||
log.Printf("Exchange %s: Failed to generate OTP code. Err: %s", cfg.Exchanges[x].Name, err)
|
||||
continue
|
||||
}
|
||||
log.Printf("%s: %s", cfg.Exchanges[x].Name, code)
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,9 +80,9 @@ func main() {
|
||||
}
|
||||
log.Println("Loaded config file.")
|
||||
|
||||
displayCurrency = cfg.FiatDisplayCurrency
|
||||
displayCurrency = cfg.Currency.FiatDisplayCurrency
|
||||
port := portfolio.Base{}
|
||||
port.SeedPortfolio(cfg.Portfolio)
|
||||
port.Seed(cfg.Portfolio)
|
||||
result := port.GetPortfolioSummary()
|
||||
|
||||
log.Println("Fetched portfolio data.")
|
||||
@@ -132,6 +132,8 @@ func main() {
|
||||
}
|
||||
} else {
|
||||
bf := bitfinex.Bitfinex{}
|
||||
bf.SetDefaults()
|
||||
bf.Verbose = false
|
||||
ticker, errf := bf.GetTicker(y.Coin.String() + currency.USD.String())
|
||||
if errf != nil {
|
||||
log.Println(errf)
|
||||
@@ -8,7 +8,9 @@ import (
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/common/crypto"
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/assets"
|
||||
)
|
||||
|
||||
// Vars for the websocket client
|
||||
@@ -40,9 +42,9 @@ type WebsocketEventResponse struct {
|
||||
// WebsocketOrderbookTickerRequest is a struct used for ticker and orderbook
|
||||
// requests
|
||||
type WebsocketOrderbookTickerRequest struct {
|
||||
Exchange string `json:"exchangeName"`
|
||||
Currency string `json:"currency"`
|
||||
AssetType string `json:"assetType"`
|
||||
Exchange string `json:"exchangeName"`
|
||||
Currency string `json:"currency"`
|
||||
AssetType assets.AssetType `json:"assetType"`
|
||||
}
|
||||
|
||||
// SendWebsocketEvent sends a websocket event message
|
||||
@@ -79,7 +81,7 @@ func main() {
|
||||
log.Fatalf("Failed to load config file: %s", err)
|
||||
}
|
||||
|
||||
listenAddr := cfg.Webserver.ListenAddress
|
||||
listenAddr := cfg.RemoteControl.WebsocketRPC.ListenAddress
|
||||
wsHost := fmt.Sprintf("ws://%s:%d/ws", common.ExtractHost(listenAddr),
|
||||
common.ExtractPort(listenAddr))
|
||||
log.Printf("Connecting to websocket host: %s", wsHost)
|
||||
@@ -95,8 +97,8 @@ func main() {
|
||||
log.Println("Authenticating..")
|
||||
var wsResp WebsocketEventResponse
|
||||
reqData := WebsocketAuth{
|
||||
Username: cfg.Webserver.AdminUsername,
|
||||
Password: common.HexEncodeToString(common.GetSHA256([]byte(cfg.Webserver.AdminPassword))),
|
||||
Username: cfg.RemoteControl.Username,
|
||||
Password: crypto.HexEncodeToString(crypto.GetSHA256([]byte(cfg.RemoteControl.Password))),
|
||||
}
|
||||
err = SendWebsocketEvent("auth", reqData, &wsResp)
|
||||
if err != nil {
|
||||
@@ -155,7 +157,7 @@ func main() {
|
||||
dataReq := WebsocketOrderbookTickerRequest{
|
||||
Exchange: "Bitfinex",
|
||||
Currency: "BTCUSD",
|
||||
AssetType: "SPOT",
|
||||
AssetType: assets.AssetTypeSpot,
|
||||
}
|
||||
|
||||
err = SendWebsocketEvent("GetTicker", dataReq, &wsResp)
|
||||
159
common/common.go
159
common/common.go
@@ -1,22 +1,12 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/md5" // nolint:gosec
|
||||
"crypto/rand"
|
||||
"crypto/sha1" // nolint:gosec
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"encoding/base64"
|
||||
"encoding/csv"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
@@ -34,7 +24,8 @@ import (
|
||||
|
||||
// Vars for common.go operations
|
||||
var (
|
||||
HTTPClient *http.Client
|
||||
HTTPClient *http.Client
|
||||
HTTPUserAgent string
|
||||
|
||||
// ErrNotYetImplemented defines a common error across the code base that
|
||||
// alerts of a function that has not been completed or tied into main code
|
||||
@@ -47,11 +38,6 @@ var (
|
||||
|
||||
// Const declarations for common.go operations
|
||||
const (
|
||||
HashSHA1 = iota
|
||||
HashSHA256
|
||||
HashSHA512
|
||||
HashSHA512_384
|
||||
HashMD5
|
||||
SatoshisPerBTC = 100000000
|
||||
SatoshisPerLTC = 100000000
|
||||
WeiPerEther = 1000000000000000000
|
||||
@@ -71,95 +57,6 @@ func NewHTTPClientWithTimeout(t time.Duration) *http.Client {
|
||||
return h
|
||||
}
|
||||
|
||||
// GetRandomSalt returns a random salt
|
||||
func GetRandomSalt(input []byte, saltLen int) ([]byte, error) {
|
||||
if saltLen <= 0 {
|
||||
return nil, errors.New("salt length is too small")
|
||||
}
|
||||
salt := make([]byte, saltLen)
|
||||
if _, err := io.ReadFull(rand.Reader, salt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result []byte
|
||||
if input != nil {
|
||||
result = input
|
||||
}
|
||||
result = append(result, salt...)
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetMD5 returns a MD5 hash of a byte array
|
||||
func GetMD5(input []byte) []byte {
|
||||
m := md5.New() // nolint:gosec
|
||||
m.Write(input)
|
||||
return m.Sum(nil)
|
||||
}
|
||||
|
||||
// GetSHA512 returns a SHA512 hash of a byte array
|
||||
func GetSHA512(input []byte) []byte {
|
||||
sha := sha512.New()
|
||||
sha.Write(input)
|
||||
return sha.Sum(nil)
|
||||
}
|
||||
|
||||
// GetSHA256 returns a SHA256 hash of a byte array
|
||||
func GetSHA256(input []byte) []byte {
|
||||
sha := sha256.New()
|
||||
sha.Write(input)
|
||||
return sha.Sum(nil)
|
||||
}
|
||||
|
||||
// GetHMAC returns a keyed-hash message authentication code using the desired
|
||||
// hashtype
|
||||
func GetHMAC(hashType int, input, key []byte) []byte {
|
||||
var hasher func() hash.Hash
|
||||
|
||||
switch hashType {
|
||||
case HashSHA1:
|
||||
hasher = sha1.New
|
||||
case HashSHA256:
|
||||
hasher = sha256.New
|
||||
case HashSHA512:
|
||||
hasher = sha512.New
|
||||
case HashSHA512_384:
|
||||
hasher = sha512.New384
|
||||
case HashMD5:
|
||||
hasher = md5.New
|
||||
}
|
||||
|
||||
h := hmac.New(hasher, key)
|
||||
h.Write(input)
|
||||
return h.Sum(nil)
|
||||
}
|
||||
|
||||
// Sha1ToHex takes a string, sha1 hashes it and return a hex string of the
|
||||
// result
|
||||
func Sha1ToHex(data string) string {
|
||||
h := sha1.New() // nolint:gosec
|
||||
h.Write([]byte(data))
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
// HexEncodeToString takes in a hexadecimal byte array and returns a string
|
||||
func HexEncodeToString(input []byte) string {
|
||||
return hex.EncodeToString(input)
|
||||
}
|
||||
|
||||
// Base64Decode takes in a Base64 string and returns a byte array and an error
|
||||
func Base64Decode(input string) ([]byte, error) {
|
||||
result, err := base64.StdEncoding.DecodeString(input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// Base64Encode takes in a byte array then returns an encoded base64 string
|
||||
func Base64Encode(input []byte) string {
|
||||
return base64.StdEncoding.EncodeToString(input)
|
||||
}
|
||||
|
||||
// StringSliceDifference concatenates slices together based on its index and
|
||||
// returns an individual string array
|
||||
func StringSliceDifference(slice1, slice2 []string) []string {
|
||||
@@ -260,27 +157,6 @@ func StringToLower(input string) string {
|
||||
return strings.ToLower(input)
|
||||
}
|
||||
|
||||
// RoundFloat rounds your floating point number to the desired decimal place
|
||||
func RoundFloat(x float64, prec int) float64 {
|
||||
var rounder float64
|
||||
pow := math.Pow(10, float64(prec))
|
||||
intermed := x * pow
|
||||
_, frac := math.Modf(intermed)
|
||||
intermed += .5
|
||||
x = .5
|
||||
if frac < 0.0 {
|
||||
x = -.5
|
||||
intermed--
|
||||
}
|
||||
if frac >= x {
|
||||
rounder = math.Ceil(intermed)
|
||||
} else {
|
||||
rounder = math.Floor(intermed)
|
||||
}
|
||||
|
||||
return rounder / pow
|
||||
}
|
||||
|
||||
// IsEnabled takes in a boolean param and returns a string if it is enabled
|
||||
// or disabled
|
||||
func IsEnabled(isEnabled bool) string {
|
||||
@@ -314,33 +190,6 @@ func YesOrNo(input string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// CalculateAmountWithFee returns a calculated fee included amount on fee
|
||||
func CalculateAmountWithFee(amount, fee float64) float64 {
|
||||
return amount + CalculateFee(amount, fee)
|
||||
}
|
||||
|
||||
// CalculateFee returns a simple fee on amount
|
||||
func CalculateFee(amount, fee float64) float64 {
|
||||
return amount * (fee / 100)
|
||||
}
|
||||
|
||||
// CalculatePercentageGainOrLoss returns the percentage rise over a certain
|
||||
// period
|
||||
func CalculatePercentageGainOrLoss(priceNow, priceThen float64) float64 {
|
||||
return (priceNow - priceThen) / priceThen * 100
|
||||
}
|
||||
|
||||
// CalculatePercentageDifference returns the percentage of difference between
|
||||
// multiple time periods
|
||||
func CalculatePercentageDifference(amount, secondAmount float64) float64 {
|
||||
return (amount - secondAmount) / ((amount + secondAmount) / 2) * 100
|
||||
}
|
||||
|
||||
// CalculateNetProfit returns net profit
|
||||
func CalculateNetProfit(amount, priceThen, priceNow, costs float64) float64 {
|
||||
return (priceNow * amount) - (priceThen * amount) - costs
|
||||
}
|
||||
|
||||
// SendHTTPRequest sends a request using the http package and returns a response
|
||||
// as a string and an error
|
||||
func SendHTTPRequest(method, urlPath string, headers map[string]string, body io.Reader) (string, error) {
|
||||
@@ -361,6 +210,10 @@ func SendHTTPRequest(method, urlPath string, headers map[string]string, body io.
|
||||
req.Header.Add(k, v)
|
||||
}
|
||||
|
||||
if HTTPUserAgent != "" && req.Header.Get("User-Agent") == "" {
|
||||
req.Header.Add("User-Agent", HTTPUserAgent)
|
||||
}
|
||||
|
||||
resp, err := HTTPClient.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/user"
|
||||
@@ -74,142 +73,6 @@ func TestIsValidCryptoAddress(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetRandomSalt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := GetRandomSalt(nil, -1)
|
||||
if err == nil {
|
||||
t.Fatal("Test failed. Expected err on negative salt length")
|
||||
}
|
||||
|
||||
salt, err := GetRandomSalt(nil, 10)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(salt) != 10 {
|
||||
t.Fatal("Test failed. Expected salt of len=10")
|
||||
}
|
||||
|
||||
salt, err = GetRandomSalt([]byte("RAWR"), 12)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(salt) != 16 {
|
||||
t.Fatal("Test failed. Expected salt of len=16")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetMD5(t *testing.T) {
|
||||
t.Parallel()
|
||||
var originalString = []byte("I am testing the MD5 function in common!")
|
||||
var expectedOutput = []byte("18fddf4a41ba90a7352765e62e7a8744")
|
||||
actualOutput := GetMD5(originalString)
|
||||
actualStr := HexEncodeToString(actualOutput)
|
||||
if !bytes.Equal(expectedOutput, []byte(actualStr)) {
|
||||
t.Errorf("Test failed. Expected '%s'. Actual '%s'",
|
||||
expectedOutput, []byte(actualStr))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestGetSHA512(t *testing.T) {
|
||||
t.Parallel()
|
||||
var originalString = []byte("I am testing the GetSHA512 function in common!")
|
||||
var expectedOutput = []byte(
|
||||
`a2273f492ea73fddc4f25c267b34b3b74998bd8a6301149e1e1c835678e3c0b90859fce22e4e7af33bde1711cbb924809aedf5d759d648d61774b7185c5dc02b`,
|
||||
)
|
||||
actualOutput := GetSHA512(originalString)
|
||||
actualStr := HexEncodeToString(actualOutput)
|
||||
if !bytes.Equal(expectedOutput, []byte(actualStr)) {
|
||||
t.Errorf("Test failed. Expected '%x'. Actual '%x'",
|
||||
expectedOutput, []byte(actualStr))
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSHA256(t *testing.T) {
|
||||
t.Parallel()
|
||||
var originalString = []byte("I am testing the GetSHA256 function in common!")
|
||||
var expectedOutput = []byte(
|
||||
"0962813d7a9f739cdcb7f0c0be0c2a13bd630167e6e54468266e4af6b1ad9303",
|
||||
)
|
||||
actualOutput := GetSHA256(originalString)
|
||||
actualStr := HexEncodeToString(actualOutput)
|
||||
if !bytes.Equal(expectedOutput, []byte(actualStr)) {
|
||||
t.Errorf("Test failed. Expected '%x'. Actual '%x'", expectedOutput,
|
||||
[]byte(actualStr))
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetHMAC(t *testing.T) {
|
||||
t.Parallel()
|
||||
expectedSha1 := []byte{
|
||||
74, 253, 245, 154, 87, 168, 110, 182, 172, 101, 177, 49, 142, 2, 253, 165,
|
||||
100, 66, 86, 246,
|
||||
}
|
||||
expectedsha256 := []byte{
|
||||
54, 68, 6, 12, 32, 158, 80, 22, 142, 8, 131, 111, 248, 145, 17, 202, 224,
|
||||
59, 135, 206, 11, 170, 154, 197, 183, 28, 150, 79, 168, 105, 62, 102,
|
||||
}
|
||||
expectedsha512 := []byte{
|
||||
249, 212, 31, 38, 23, 3, 93, 220, 81, 209, 214, 112, 92, 75, 126, 40, 109,
|
||||
95, 247, 182, 210, 54, 217, 224, 199, 252, 129, 226, 97, 201, 245, 220, 37,
|
||||
201, 240, 15, 137, 236, 75, 6, 97, 12, 190, 31, 53, 153, 223, 17, 214, 11,
|
||||
153, 203, 49, 29, 158, 217, 204, 93, 179, 109, 140, 216, 202, 71,
|
||||
}
|
||||
expectedsha512384 := []byte{
|
||||
121, 203, 109, 105, 178, 68, 179, 57, 21, 217, 76, 82, 94, 100, 210, 1, 55,
|
||||
201, 8, 232, 194, 168, 165, 58, 192, 26, 193, 167, 254, 183, 172, 4, 189,
|
||||
158, 158, 150, 173, 33, 119, 125, 94, 13, 125, 89, 241, 184, 166, 128,
|
||||
}
|
||||
expectedmd5 := []byte{
|
||||
113, 64, 132, 129, 213, 68, 231, 99, 252, 15, 175, 109, 198, 132, 139, 39,
|
||||
}
|
||||
|
||||
sha1 := GetHMAC(HashSHA1, []byte("Hello,World"), []byte("1234"))
|
||||
if string(sha1) != string(expectedSha1) {
|
||||
t.Errorf("Test failed. Common GetHMAC error: Expected '%x'. Actual '%x'",
|
||||
expectedSha1, sha1,
|
||||
)
|
||||
}
|
||||
sha256 := GetHMAC(HashSHA256, []byte("Hello,World"), []byte("1234"))
|
||||
if string(sha256) != string(expectedsha256) {
|
||||
t.Errorf("Test failed. Common GetHMAC error: Expected '%x'. Actual '%x'",
|
||||
expectedsha256, sha256,
|
||||
)
|
||||
}
|
||||
sha512 := GetHMAC(HashSHA512, []byte("Hello,World"), []byte("1234"))
|
||||
if string(sha512) != string(expectedsha512) {
|
||||
t.Errorf("Test failed. Common GetHMAC error: Expected '%x'. Actual '%x'",
|
||||
expectedsha512, sha512,
|
||||
)
|
||||
}
|
||||
sha512384 := GetHMAC(HashSHA512_384, []byte("Hello,World"), []byte("1234"))
|
||||
if string(sha512384) != string(expectedsha512384) {
|
||||
t.Errorf("Test failed. Common GetHMAC error: Expected '%x'. Actual '%x'",
|
||||
expectedsha512384, sha512384,
|
||||
)
|
||||
}
|
||||
md5 := GetHMAC(HashMD5, []byte("Hello World"), []byte("1234"))
|
||||
if string(md5) != string(expectedmd5) {
|
||||
t.Errorf("Test failed. Common GetHMAC error: Expected '%x'. Actual '%x'",
|
||||
expectedmd5, md5,
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestSha1Tohex(t *testing.T) {
|
||||
t.Parallel()
|
||||
expectedResult := "fcfbfcd7d31d994ef660f6972399ab5d7a890149"
|
||||
actualResult := Sha1ToHex("Testing Sha1ToHex")
|
||||
if actualResult != expectedResult {
|
||||
t.Errorf("Test failed. Expected '%s'. Actual '%s'",
|
||||
expectedResult, actualResult)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringToLower(t *testing.T) {
|
||||
t.Parallel()
|
||||
upperCaseString := "HEY MAN"
|
||||
@@ -232,44 +95,6 @@ func TestStringToUpper(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestHexEncodeToString(t *testing.T) {
|
||||
t.Parallel()
|
||||
originalInput := []byte("string")
|
||||
expectedOutput := "737472696e67"
|
||||
actualResult := HexEncodeToString(originalInput)
|
||||
if actualResult != expectedOutput {
|
||||
t.Errorf("Test failed. Expected '%s'. Actual '%s'",
|
||||
expectedOutput, actualResult)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBase64Decode(t *testing.T) {
|
||||
t.Parallel()
|
||||
originalInput := "aGVsbG8="
|
||||
expectedOutput := []byte("hello")
|
||||
actualResult, err := Base64Decode(originalInput)
|
||||
if !bytes.Equal(actualResult, expectedOutput) {
|
||||
t.Errorf("Test failed. Expected '%s'. Actual '%s'. Error: %s",
|
||||
expectedOutput, actualResult, err)
|
||||
}
|
||||
|
||||
_, err = Base64Decode("-")
|
||||
if err == nil {
|
||||
t.Error("Test failed. Bad base64 string failed returned nil error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBase64Encode(t *testing.T) {
|
||||
t.Parallel()
|
||||
originalInput := []byte("hello")
|
||||
expectedOutput := "aGVsbG8="
|
||||
actualResult := Base64Encode(originalInput)
|
||||
if actualResult != expectedOutput {
|
||||
t.Errorf("Test failed. Expected '%s'. Actual '%s'",
|
||||
expectedOutput, actualResult)
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringSliceDifference(t *testing.T) {
|
||||
t.Parallel()
|
||||
originalInputOne := []string{"hello"}
|
||||
@@ -429,22 +254,6 @@ func TestReplaceString(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRoundFloat(t *testing.T) {
|
||||
t.Parallel()
|
||||
// mapping of input vs expected result
|
||||
testTable := map[float64]float64{
|
||||
2.3232323: 2.32,
|
||||
-2.3232323: -2.32,
|
||||
}
|
||||
for testInput, expectedOutput := range testTable {
|
||||
actualOutput := RoundFloat(testInput, 2)
|
||||
if actualOutput != expectedOutput {
|
||||
t.Errorf("Test failed. RoundFloat Expected '%f'. Actual '%f'.",
|
||||
expectedOutput, actualOutput)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestYesOrNo(t *testing.T) {
|
||||
t.Parallel()
|
||||
if !YesOrNo("y") {
|
||||
@@ -458,68 +267,6 @@ func TestYesOrNo(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCalculateFee(t *testing.T) {
|
||||
t.Parallel()
|
||||
originalInput := float64(1)
|
||||
fee := float64(1)
|
||||
expectedOutput := float64(0.01)
|
||||
actualResult := CalculateFee(originalInput, fee)
|
||||
if expectedOutput != actualResult {
|
||||
t.Errorf(
|
||||
"Test failed. Expected '%f'. Actual '%f'.", expectedOutput, actualResult)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCalculateAmountWithFee(t *testing.T) {
|
||||
t.Parallel()
|
||||
originalInput := float64(1)
|
||||
fee := float64(1)
|
||||
expectedOutput := float64(1.01)
|
||||
actualResult := CalculateAmountWithFee(originalInput, fee)
|
||||
if expectedOutput != actualResult {
|
||||
t.Errorf(
|
||||
"Test failed. Expected '%f'. Actual '%f'.", expectedOutput, actualResult)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCalculatePercentageGainOrLoss(t *testing.T) {
|
||||
t.Parallel()
|
||||
originalInput := float64(9300)
|
||||
secondInput := float64(9000)
|
||||
expectedOutput := 3.3333333333333335
|
||||
actualResult := CalculatePercentageGainOrLoss(originalInput, secondInput)
|
||||
if expectedOutput != actualResult {
|
||||
t.Errorf(
|
||||
"Test failed. Expected '%f'. Actual '%f'.", expectedOutput, actualResult)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCalculatePercentageDifference(t *testing.T) {
|
||||
t.Parallel()
|
||||
originalInput := float64(10)
|
||||
secondAmount := float64(5)
|
||||
expectedOutput := 66.66666666666666
|
||||
actualResult := CalculatePercentageDifference(originalInput, secondAmount)
|
||||
if expectedOutput != actualResult {
|
||||
t.Errorf(
|
||||
"Test failed. Expected '%f'. Actual '%f'.", expectedOutput, actualResult)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCalculateNetProfit(t *testing.T) {
|
||||
t.Parallel()
|
||||
amount := float64(5)
|
||||
priceThen := float64(1)
|
||||
priceNow := float64(10)
|
||||
costs := float64(1)
|
||||
expectedOutput := float64(44)
|
||||
actualResult := CalculateNetProfit(amount, priceThen, priceNow, costs)
|
||||
if expectedOutput != actualResult {
|
||||
t.Errorf(
|
||||
"Test failed. Expected '%f'. Actual '%f'.", expectedOutput, actualResult)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSendHTTPRequest(t *testing.T) {
|
||||
methodPost := "pOst"
|
||||
methodGet := "GeT"
|
||||
|
||||
113
common/crypto/crypto.go
Normal file
113
common/crypto/crypto.go
Normal file
@@ -0,0 +1,113 @@
|
||||
package crypto
|
||||
|
||||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/md5" // nolint:gosec
|
||||
"crypto/rand"
|
||||
"crypto/sha1" // nolint:gosec
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"hash"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Const declarations for common.go operations
|
||||
const (
|
||||
HashSHA1 = iota
|
||||
HashSHA256
|
||||
HashSHA512
|
||||
HashSHA512_384
|
||||
HashMD5
|
||||
)
|
||||
|
||||
// HexEncodeToString takes in a hexadecimal byte array and returns a string
|
||||
func HexEncodeToString(input []byte) string {
|
||||
return hex.EncodeToString(input)
|
||||
}
|
||||
|
||||
// Base64Decode takes in a Base64 string and returns a byte array and an error
|
||||
func Base64Decode(input string) ([]byte, error) {
|
||||
result, err := base64.StdEncoding.DecodeString(input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// Base64Encode takes in a byte array then returns an encoded base64 string
|
||||
func Base64Encode(input []byte) string {
|
||||
return base64.StdEncoding.EncodeToString(input)
|
||||
}
|
||||
|
||||
// GetRandomSalt returns a random salt
|
||||
func GetRandomSalt(input []byte, saltLen int) ([]byte, error) {
|
||||
if saltLen <= 0 {
|
||||
return nil, errors.New("salt length is too small")
|
||||
}
|
||||
salt := make([]byte, saltLen)
|
||||
if _, err := io.ReadFull(rand.Reader, salt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result []byte
|
||||
if input != nil {
|
||||
result = input
|
||||
}
|
||||
result = append(result, salt...)
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetMD5 returns a MD5 hash of a byte array
|
||||
func GetMD5(input []byte) []byte {
|
||||
m := md5.New() // nolint:gosec
|
||||
m.Write(input)
|
||||
return m.Sum(nil)
|
||||
}
|
||||
|
||||
// GetSHA512 returns a SHA512 hash of a byte array
|
||||
func GetSHA512(input []byte) []byte {
|
||||
sha := sha512.New()
|
||||
sha.Write(input)
|
||||
return sha.Sum(nil)
|
||||
}
|
||||
|
||||
// GetSHA256 returns a SHA256 hash of a byte array
|
||||
func GetSHA256(input []byte) []byte {
|
||||
sha := sha256.New()
|
||||
sha.Write(input)
|
||||
return sha.Sum(nil)
|
||||
}
|
||||
|
||||
// GetHMAC returns a keyed-hash message authentication code using the desired
|
||||
// hashtype
|
||||
func GetHMAC(hashType int, input, key []byte) []byte {
|
||||
var hasher func() hash.Hash
|
||||
|
||||
switch hashType {
|
||||
case HashSHA1:
|
||||
hasher = sha1.New
|
||||
case HashSHA256:
|
||||
hasher = sha256.New
|
||||
case HashSHA512:
|
||||
hasher = sha512.New
|
||||
case HashSHA512_384:
|
||||
hasher = sha512.New384
|
||||
case HashMD5:
|
||||
hasher = md5.New
|
||||
}
|
||||
|
||||
h := hmac.New(hasher, key)
|
||||
h.Write(input)
|
||||
return h.Sum(nil)
|
||||
}
|
||||
|
||||
// Sha1ToHex takes a string, sha1 hashes it and return a hex string of the
|
||||
// result
|
||||
func Sha1ToHex(data string) string {
|
||||
h := sha1.New() // nolint:gosec
|
||||
h.Write([]byte(data))
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
180
common/crypto/crypto_test.go
Normal file
180
common/crypto/crypto_test.go
Normal file
@@ -0,0 +1,180 @@
|
||||
package crypto
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHexEncodeToString(t *testing.T) {
|
||||
t.Parallel()
|
||||
originalInput := []byte("string")
|
||||
expectedOutput := "737472696e67"
|
||||
actualResult := HexEncodeToString(originalInput)
|
||||
if actualResult != expectedOutput {
|
||||
t.Errorf("Test failed. Expected '%s'. Actual '%s'",
|
||||
expectedOutput, actualResult)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBase64Decode(t *testing.T) {
|
||||
t.Parallel()
|
||||
originalInput := "aGVsbG8="
|
||||
expectedOutput := []byte("hello")
|
||||
actualResult, err := Base64Decode(originalInput)
|
||||
if !bytes.Equal(actualResult, expectedOutput) {
|
||||
t.Errorf("Test failed. Expected '%s'. Actual '%s'. Error: %s",
|
||||
expectedOutput, actualResult, err)
|
||||
}
|
||||
|
||||
_, err = Base64Decode("-")
|
||||
if err == nil {
|
||||
t.Error("Test failed. Bad base64 string failed returned nil error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBase64Encode(t *testing.T) {
|
||||
t.Parallel()
|
||||
originalInput := []byte("hello")
|
||||
expectedOutput := "aGVsbG8="
|
||||
actualResult := Base64Encode(originalInput)
|
||||
if actualResult != expectedOutput {
|
||||
t.Errorf("Test failed. Expected '%s'. Actual '%s'",
|
||||
expectedOutput, actualResult)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetRandomSalt(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
_, err := GetRandomSalt(nil, -1)
|
||||
if err == nil {
|
||||
t.Fatal("Test failed. Expected err on negative salt length")
|
||||
}
|
||||
|
||||
salt, err := GetRandomSalt(nil, 10)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(salt) != 10 {
|
||||
t.Fatal("Test failed. Expected salt of len=10")
|
||||
}
|
||||
|
||||
salt, err = GetRandomSalt([]byte("RAWR"), 12)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if len(salt) != 16 {
|
||||
t.Fatal("Test failed. Expected salt of len=16")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetMD5(t *testing.T) {
|
||||
t.Parallel()
|
||||
var originalString = []byte("I am testing the MD5 function in common!")
|
||||
var expectedOutput = []byte("18fddf4a41ba90a7352765e62e7a8744")
|
||||
actualOutput := GetMD5(originalString)
|
||||
actualStr := HexEncodeToString(actualOutput)
|
||||
if !bytes.Equal(expectedOutput, []byte(actualStr)) {
|
||||
t.Errorf("Test failed. Expected '%s'. Actual '%s'",
|
||||
expectedOutput, []byte(actualStr))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestGetSHA512(t *testing.T) {
|
||||
t.Parallel()
|
||||
var originalString = []byte("I am testing the GetSHA512 function in common!")
|
||||
var expectedOutput = []byte(
|
||||
`a2273f492ea73fddc4f25c267b34b3b74998bd8a6301149e1e1c835678e3c0b90859fce22e4e7af33bde1711cbb924809aedf5d759d648d61774b7185c5dc02b`,
|
||||
)
|
||||
actualOutput := GetSHA512(originalString)
|
||||
actualStr := HexEncodeToString(actualOutput)
|
||||
if !bytes.Equal(expectedOutput, []byte(actualStr)) {
|
||||
t.Errorf("Test failed. Expected '%x'. Actual '%x'",
|
||||
expectedOutput, []byte(actualStr))
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSHA256(t *testing.T) {
|
||||
t.Parallel()
|
||||
var originalString = []byte("I am testing the GetSHA256 function in common!")
|
||||
var expectedOutput = []byte(
|
||||
"0962813d7a9f739cdcb7f0c0be0c2a13bd630167e6e54468266e4af6b1ad9303",
|
||||
)
|
||||
actualOutput := GetSHA256(originalString)
|
||||
actualStr := HexEncodeToString(actualOutput)
|
||||
if !bytes.Equal(expectedOutput, []byte(actualStr)) {
|
||||
t.Errorf("Test failed. Expected '%x'. Actual '%x'", expectedOutput,
|
||||
[]byte(actualStr))
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetHMAC(t *testing.T) {
|
||||
t.Parallel()
|
||||
expectedSha1 := []byte{
|
||||
74, 253, 245, 154, 87, 168, 110, 182, 172, 101, 177, 49, 142, 2, 253, 165,
|
||||
100, 66, 86, 246,
|
||||
}
|
||||
expectedsha256 := []byte{
|
||||
54, 68, 6, 12, 32, 158, 80, 22, 142, 8, 131, 111, 248, 145, 17, 202, 224,
|
||||
59, 135, 206, 11, 170, 154, 197, 183, 28, 150, 79, 168, 105, 62, 102,
|
||||
}
|
||||
expectedsha512 := []byte{
|
||||
249, 212, 31, 38, 23, 3, 93, 220, 81, 209, 214, 112, 92, 75, 126, 40, 109,
|
||||
95, 247, 182, 210, 54, 217, 224, 199, 252, 129, 226, 97, 201, 245, 220, 37,
|
||||
201, 240, 15, 137, 236, 75, 6, 97, 12, 190, 31, 53, 153, 223, 17, 214, 11,
|
||||
153, 203, 49, 29, 158, 217, 204, 93, 179, 109, 140, 216, 202, 71,
|
||||
}
|
||||
expectedsha512384 := []byte{
|
||||
121, 203, 109, 105, 178, 68, 179, 57, 21, 217, 76, 82, 94, 100, 210, 1, 55,
|
||||
201, 8, 232, 194, 168, 165, 58, 192, 26, 193, 167, 254, 183, 172, 4, 189,
|
||||
158, 158, 150, 173, 33, 119, 125, 94, 13, 125, 89, 241, 184, 166, 128,
|
||||
}
|
||||
expectedmd5 := []byte{
|
||||
113, 64, 132, 129, 213, 68, 231, 99, 252, 15, 175, 109, 198, 132, 139, 39,
|
||||
}
|
||||
|
||||
sha1 := GetHMAC(HashSHA1, []byte("Hello,World"), []byte("1234"))
|
||||
if string(sha1) != string(expectedSha1) {
|
||||
t.Errorf("Test failed. Common GetHMAC error: Expected '%x'. Actual '%x'",
|
||||
expectedSha1, sha1,
|
||||
)
|
||||
}
|
||||
sha256 := GetHMAC(HashSHA256, []byte("Hello,World"), []byte("1234"))
|
||||
if string(sha256) != string(expectedsha256) {
|
||||
t.Errorf("Test failed. Common GetHMAC error: Expected '%x'. Actual '%x'",
|
||||
expectedsha256, sha256,
|
||||
)
|
||||
}
|
||||
sha512 := GetHMAC(HashSHA512, []byte("Hello,World"), []byte("1234"))
|
||||
if string(sha512) != string(expectedsha512) {
|
||||
t.Errorf("Test failed. Common GetHMAC error: Expected '%x'. Actual '%x'",
|
||||
expectedsha512, sha512,
|
||||
)
|
||||
}
|
||||
sha512384 := GetHMAC(HashSHA512_384, []byte("Hello,World"), []byte("1234"))
|
||||
if string(sha512384) != string(expectedsha512384) {
|
||||
t.Errorf("Test failed. Common GetHMAC error: Expected '%x'. Actual '%x'",
|
||||
expectedsha512384, sha512384,
|
||||
)
|
||||
}
|
||||
md5 := GetHMAC(HashMD5, []byte("Hello World"), []byte("1234"))
|
||||
if string(md5) != string(expectedmd5) {
|
||||
t.Errorf("Test failed. Common GetHMAC error: Expected '%x'. Actual '%x'",
|
||||
expectedmd5, md5,
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestSha1Tohex(t *testing.T) {
|
||||
t.Parallel()
|
||||
expectedResult := "fcfbfcd7d31d994ef660f6972399ab5d7a890149"
|
||||
actualResult := Sha1ToHex("Testing Sha1ToHex")
|
||||
if actualResult != expectedResult {
|
||||
t.Errorf("Test failed. Expected '%s'. Actual '%s'",
|
||||
expectedResult, actualResult)
|
||||
}
|
||||
}
|
||||
51
common/math/math.go
Normal file
51
common/math/math.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package math
|
||||
|
||||
import "math"
|
||||
|
||||
// CalculateAmountWithFee returns a calculated fee included amount on fee
|
||||
func CalculateAmountWithFee(amount, fee float64) float64 {
|
||||
return amount + CalculateFee(amount, fee)
|
||||
}
|
||||
|
||||
// CalculateFee returns a simple fee on amount
|
||||
func CalculateFee(amount, fee float64) float64 {
|
||||
return amount * (fee / 100)
|
||||
}
|
||||
|
||||
// CalculatePercentageGainOrLoss returns the percentage rise over a certain
|
||||
// period
|
||||
func CalculatePercentageGainOrLoss(priceNow, priceThen float64) float64 {
|
||||
return (priceNow - priceThen) / priceThen * 100
|
||||
}
|
||||
|
||||
// CalculatePercentageDifference returns the percentage of difference between
|
||||
// multiple time periods
|
||||
func CalculatePercentageDifference(amount, secondAmount float64) float64 {
|
||||
return (amount - secondAmount) / ((amount + secondAmount) / 2) * 100
|
||||
}
|
||||
|
||||
// CalculateNetProfit returns net profit
|
||||
func CalculateNetProfit(amount, priceThen, priceNow, costs float64) float64 {
|
||||
return (priceNow * amount) - (priceThen * amount) - costs
|
||||
}
|
||||
|
||||
// RoundFloat rounds your floating point number to the desired decimal place
|
||||
func RoundFloat(x float64, prec int) float64 {
|
||||
var rounder float64
|
||||
pow := math.Pow(10, float64(prec))
|
||||
intermed := x * pow
|
||||
_, frac := math.Modf(intermed)
|
||||
intermed += .5
|
||||
x = .5
|
||||
if frac < 0.0 {
|
||||
x = -.5
|
||||
intermed--
|
||||
}
|
||||
if frac >= x {
|
||||
rounder = math.Ceil(intermed)
|
||||
} else {
|
||||
rounder = math.Floor(intermed)
|
||||
}
|
||||
|
||||
return rounder / pow
|
||||
}
|
||||
81
common/math/math_test.go
Normal file
81
common/math/math_test.go
Normal file
@@ -0,0 +1,81 @@
|
||||
package math
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestCalculateFee(t *testing.T) {
|
||||
t.Parallel()
|
||||
originalInput := float64(1)
|
||||
fee := float64(1)
|
||||
expectedOutput := float64(0.01)
|
||||
actualResult := CalculateFee(originalInput, fee)
|
||||
if expectedOutput != actualResult {
|
||||
t.Errorf(
|
||||
"Test failed. Expected '%f'. Actual '%f'.", expectedOutput, actualResult)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCalculateAmountWithFee(t *testing.T) {
|
||||
t.Parallel()
|
||||
originalInput := float64(1)
|
||||
fee := float64(1)
|
||||
expectedOutput := float64(1.01)
|
||||
actualResult := CalculateAmountWithFee(originalInput, fee)
|
||||
if expectedOutput != actualResult {
|
||||
t.Errorf(
|
||||
"Test failed. Expected '%f'. Actual '%f'.", expectedOutput, actualResult)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCalculatePercentageGainOrLoss(t *testing.T) {
|
||||
t.Parallel()
|
||||
originalInput := float64(9300)
|
||||
secondInput := float64(9000)
|
||||
expectedOutput := 3.3333333333333335
|
||||
actualResult := CalculatePercentageGainOrLoss(originalInput, secondInput)
|
||||
if expectedOutput != actualResult {
|
||||
t.Errorf(
|
||||
"Test failed. Expected '%f'. Actual '%f'.", expectedOutput, actualResult)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCalculatePercentageDifference(t *testing.T) {
|
||||
t.Parallel()
|
||||
originalInput := float64(10)
|
||||
secondAmount := float64(5)
|
||||
expectedOutput := 66.66666666666666
|
||||
actualResult := CalculatePercentageDifference(originalInput, secondAmount)
|
||||
if expectedOutput != actualResult {
|
||||
t.Errorf(
|
||||
"Test failed. Expected '%f'. Actual '%f'.", expectedOutput, actualResult)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCalculateNetProfit(t *testing.T) {
|
||||
t.Parallel()
|
||||
amount := float64(5)
|
||||
priceThen := float64(1)
|
||||
priceNow := float64(10)
|
||||
costs := float64(1)
|
||||
expectedOutput := float64(44)
|
||||
actualResult := CalculateNetProfit(amount, priceThen, priceNow, costs)
|
||||
if expectedOutput != actualResult {
|
||||
t.Errorf(
|
||||
"Test failed. Expected '%f'. Actual '%f'.", expectedOutput, actualResult)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRoundFloat(t *testing.T) {
|
||||
t.Parallel()
|
||||
// mapping of input vs expected result
|
||||
testTable := map[float64]float64{
|
||||
2.3232323: 2.32,
|
||||
-2.3232323: -2.32,
|
||||
}
|
||||
for testInput, expectedOutput := range testTable {
|
||||
actualOutput := RoundFloat(testInput, 2)
|
||||
if actualOutput != expectedOutput {
|
||||
t.Errorf("Test failed. RoundFloat Expected '%f'. Actual '%f'.",
|
||||
expectedOutput, actualOutput)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,14 +6,15 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/assets"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
// global vars contain staged update data that will be sent to the communication
|
||||
// mediums
|
||||
var (
|
||||
TickerStaged map[string]map[string]map[string]ticker.Price
|
||||
OrderbookStaged map[string]map[string]map[string]Orderbook
|
||||
TickerStaged map[string]map[assets.AssetType]map[string]ticker.Price
|
||||
OrderbookStaged map[string]map[assets.AssetType]map[string]Orderbook
|
||||
PortfolioStaged Portfolio
|
||||
SettingsStaged Settings
|
||||
ServiceStarted time.Time
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/assets"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
log "github.com/thrasher-/gocryptotrader/logger"
|
||||
@@ -25,8 +26,8 @@ type ICommunicate interface {
|
||||
// Setup sets up communication variables and intiates a connection to the
|
||||
// communication mediums
|
||||
func (c IComm) Setup() {
|
||||
TickerStaged = make(map[string]map[string]map[string]ticker.Price)
|
||||
OrderbookStaged = make(map[string]map[string]map[string]Orderbook)
|
||||
TickerStaged = make(map[string]map[assets.AssetType]map[string]ticker.Price)
|
||||
OrderbookStaged = make(map[string]map[assets.AssetType]map[string]Orderbook)
|
||||
ServiceStarted = time.Now()
|
||||
|
||||
for i := range c {
|
||||
@@ -68,12 +69,12 @@ func (c IComm) GetEnabledCommunicationMediums() {
|
||||
}
|
||||
|
||||
// StageTickerData stages updated ticker data for the communications package
|
||||
func (c IComm) StageTickerData(exchangeName, assetType string, tickerPrice *ticker.Price) {
|
||||
func (c IComm) StageTickerData(exchangeName string, assetType assets.AssetType, tickerPrice *ticker.Price) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
if _, ok := TickerStaged[exchangeName]; !ok {
|
||||
TickerStaged[exchangeName] = make(map[string]map[string]ticker.Price)
|
||||
TickerStaged[exchangeName] = make(map[assets.AssetType]map[string]ticker.Price)
|
||||
}
|
||||
|
||||
if _, ok := TickerStaged[exchangeName][assetType]; !ok {
|
||||
@@ -85,12 +86,12 @@ func (c IComm) StageTickerData(exchangeName, assetType string, tickerPrice *tick
|
||||
|
||||
// StageOrderbookData stages updated orderbook data for the communications
|
||||
// package
|
||||
func (c IComm) StageOrderbookData(exchangeName, assetType string, ob *orderbook.Base) {
|
||||
func (c IComm) StageOrderbookData(exchangeName string, assetType assets.AssetType, ob *orderbook.Base) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
if _, ok := OrderbookStaged[exchangeName]; !ok {
|
||||
OrderbookStaged[exchangeName] = make(map[string]map[string]Orderbook)
|
||||
OrderbookStaged[exchangeName] = make(map[assets.AssetType]map[string]Orderbook)
|
||||
}
|
||||
|
||||
if _, ok := OrderbookStaged[exchangeName][assetType]; !ok {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user