mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-06-05 23:16:53 +00:00
New communications package
Support for Slack, SMSGlobal, SMTP and Telegram Supersedes: https://github.com/thrasher-/gocryptotrader/pull/126
This commit is contained in:
committed by
Adrian Gallagher
parent
d34fc9aae8
commit
9d0616d8cf
166
communications/base/base.go
Normal file
166
communications/base/base.go
Normal file
@@ -0,0 +1,166 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/common"
|
||||
"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
|
||||
PortfolioStaged Portfolio
|
||||
SettingsStaged Settings
|
||||
ServiceStarted time.Time
|
||||
m sync.Mutex
|
||||
)
|
||||
|
||||
// Orderbook holds the minimal orderbook details to be sent to a communication
|
||||
// medium
|
||||
type Orderbook struct {
|
||||
CurrencyPair string
|
||||
AssetType string
|
||||
TotalAsks float64
|
||||
TotalBids float64
|
||||
LastUpdated string
|
||||
}
|
||||
|
||||
// Ticker holds the minimal orderbook details to be sent to a communication
|
||||
// medium
|
||||
type Ticker struct {
|
||||
CurrencyPair string
|
||||
LastUpdated string
|
||||
}
|
||||
|
||||
// Portfolio holds the minimal portfolio details to be sent to a communication
|
||||
// medium
|
||||
type Portfolio struct {
|
||||
ProfitLoss string
|
||||
}
|
||||
|
||||
// Settings holds the minimal setting details to be sent to a communication
|
||||
// medium
|
||||
type Settings struct {
|
||||
EnabledExchanges string
|
||||
EnabledCommunications string
|
||||
}
|
||||
|
||||
// Base enforces standard variables across communication packages
|
||||
type Base struct {
|
||||
Name string
|
||||
Enabled bool
|
||||
Verbose bool
|
||||
Connected bool
|
||||
}
|
||||
|
||||
// Event is a generalise event type
|
||||
type Event struct {
|
||||
Type string
|
||||
GainLoss string
|
||||
TradeDetails string
|
||||
}
|
||||
|
||||
// IsEnabled returns if the comms package has been enabled in the configuration
|
||||
func (b *Base) IsEnabled() bool {
|
||||
return b.Enabled
|
||||
}
|
||||
|
||||
// IsConnected returns if the package is connected to a server and/or ready to
|
||||
// send
|
||||
func (b *Base) IsConnected() bool {
|
||||
return b.Connected
|
||||
}
|
||||
|
||||
// GetName returns a package name
|
||||
func (b *Base) GetName() string {
|
||||
return b.Name
|
||||
}
|
||||
|
||||
// GetTicker returns staged ticker data
|
||||
func (b *Base) GetTicker(exchangeName string) string {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
tickerPrice, ok := TickerStaged[exchangeName]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
|
||||
var tickerPrices []ticker.Price
|
||||
for _, x := range tickerPrice {
|
||||
for _, y := range x {
|
||||
tickerPrices = append(tickerPrices, y)
|
||||
}
|
||||
}
|
||||
|
||||
var packagedTickers []string
|
||||
for i := range tickerPrices {
|
||||
packagedTickers = append(packagedTickers, fmt.Sprintf(
|
||||
"Currency Pair: %s Ask: %f, Bid: %f High: %f Last: %f Low: %f ATH: %f Volume: %f",
|
||||
tickerPrices[i].CurrencyPair,
|
||||
tickerPrices[i].Ask,
|
||||
tickerPrices[i].Bid,
|
||||
tickerPrices[i].High,
|
||||
tickerPrices[i].Last,
|
||||
tickerPrices[i].Low,
|
||||
tickerPrices[i].PriceATH,
|
||||
tickerPrices[i].Volume))
|
||||
}
|
||||
return common.JoinStrings(packagedTickers, "\n")
|
||||
}
|
||||
|
||||
// GetOrderbook returns staged orderbook data
|
||||
func (b *Base) GetOrderbook(exchangeName string) string {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
orderbook, ok := OrderbookStaged[exchangeName]
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
|
||||
var orderbooks []Orderbook
|
||||
for _, x := range orderbook {
|
||||
for _, y := range x {
|
||||
orderbooks = append(orderbooks, y)
|
||||
}
|
||||
}
|
||||
|
||||
var packagedOrderbooks []string
|
||||
for i := range orderbooks {
|
||||
packagedOrderbooks = append(packagedOrderbooks, fmt.Sprintf(
|
||||
"Currency Pair: %s AssetType: %s, LastUpdated: %s TotalAsks: %f TotalBids: %f",
|
||||
orderbooks[i].CurrencyPair,
|
||||
orderbooks[i].AssetType,
|
||||
orderbooks[i].LastUpdated,
|
||||
orderbooks[i].TotalAsks,
|
||||
orderbooks[i].TotalBids))
|
||||
}
|
||||
return common.JoinStrings(packagedOrderbooks, "\n")
|
||||
}
|
||||
|
||||
// GetPortfolio returns staged portfolio info
|
||||
func (b *Base) GetPortfolio() string {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return fmt.Sprintf("%v", PortfolioStaged)
|
||||
}
|
||||
|
||||
// GetSettings returns stage setting info
|
||||
func (b *Base) GetSettings() string {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
return fmt.Sprintf("%v", SettingsStaged)
|
||||
}
|
||||
|
||||
// GetStatus returns status data
|
||||
func (b *Base) GetStatus() string {
|
||||
return `
|
||||
GoCryptoTrader Service: Online
|
||||
Service Started: ` + ServiceStarted.String()
|
||||
}
|
||||
108
communications/base/base_interface.go
Normal file
108
communications/base/base_interface.go
Normal file
@@ -0,0 +1,108 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-/gocryptotrader/config"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/orderbook"
|
||||
"github.com/thrasher-/gocryptotrader/exchanges/ticker"
|
||||
)
|
||||
|
||||
// IComm is the main interface array across the communication packages
|
||||
type IComm []ICommunicate
|
||||
|
||||
// ICommunicate enforces standard functions across communication packages
|
||||
type ICommunicate interface {
|
||||
Setup(config config.CommunicationsConfig)
|
||||
Connect() error
|
||||
PushEvent(Event) error
|
||||
IsEnabled() bool
|
||||
IsConnected() bool
|
||||
GetName() string
|
||||
}
|
||||
|
||||
// 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)
|
||||
ServiceStarted = time.Now()
|
||||
|
||||
for i := range c {
|
||||
if c[i].IsEnabled() && !c[i].IsConnected() {
|
||||
err := c[i].Connect()
|
||||
if err != nil {
|
||||
log.Printf("Communications: %s failed to connect. Err: %s", c[i].GetName(), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PushEvent pushes triggered events to all enabled communication links
|
||||
func (c IComm) PushEvent(event Event) {
|
||||
for i := range c {
|
||||
if c[i].IsEnabled() && c[i].IsConnected() {
|
||||
err := c[i].PushEvent(event)
|
||||
if err != nil {
|
||||
log.Printf("Communications error - PushEvent() in package %s with %v",
|
||||
c[i].GetName(), event)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GetEnabledCommunicationMediums prints out enabled and connected communication
|
||||
// packages
|
||||
func (c IComm) GetEnabledCommunicationMediums() {
|
||||
var count int
|
||||
for i := range c {
|
||||
if c[i].IsEnabled() && c[i].IsConnected() {
|
||||
log.Printf("Communications: Medium %s is enabled.", c[i].GetName())
|
||||
count++
|
||||
}
|
||||
}
|
||||
if count == 0 {
|
||||
log.Println("Communications: No communication mediums are enabled.")
|
||||
}
|
||||
}
|
||||
|
||||
// StageTickerData stages updated ticker data for the communications package
|
||||
func (c IComm) StageTickerData(exchangeName, assetType string, tickerPrice ticker.Price) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
if _, ok := TickerStaged[exchangeName]; !ok {
|
||||
TickerStaged[exchangeName] = make(map[string]map[string]ticker.Price)
|
||||
}
|
||||
|
||||
if _, ok := TickerStaged[exchangeName][assetType]; !ok {
|
||||
TickerStaged[exchangeName][assetType] = make(map[string]ticker.Price)
|
||||
}
|
||||
|
||||
TickerStaged[exchangeName][assetType][tickerPrice.CurrencyPair] = tickerPrice
|
||||
}
|
||||
|
||||
// StageOrderbookData stages updated orderbook data for the communications
|
||||
// package
|
||||
func (c IComm) StageOrderbookData(exchangeName, assetType string, orderbook orderbook.Base) {
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
if _, ok := OrderbookStaged[exchangeName]; !ok {
|
||||
OrderbookStaged[exchangeName] = make(map[string]map[string]Orderbook)
|
||||
}
|
||||
|
||||
if _, ok := OrderbookStaged[exchangeName][assetType]; !ok {
|
||||
OrderbookStaged[exchangeName][assetType] = make(map[string]Orderbook)
|
||||
}
|
||||
|
||||
_, totalAsks := orderbook.CalculateTotalAsks()
|
||||
_, totalBids := orderbook.CalculateTotalBids()
|
||||
|
||||
OrderbookStaged[exchangeName][assetType][orderbook.CurrencyPair] = Orderbook{
|
||||
CurrencyPair: orderbook.CurrencyPair,
|
||||
TotalAsks: totalAsks,
|
||||
TotalBids: totalBids,
|
||||
LastUpdated: orderbook.LastUpdated.String()}
|
||||
}
|
||||
84
communications/base/base_test.go
Normal file
84
communications/base/base_test.go
Normal file
@@ -0,0 +1,84 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
var (
|
||||
b Base
|
||||
i IComm
|
||||
)
|
||||
|
||||
func TestStart(t *testing.T) {
|
||||
b = Base{
|
||||
Name: "test",
|
||||
Enabled: true,
|
||||
Verbose: true,
|
||||
Connected: true,
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsEnabled(t *testing.T) {
|
||||
if !b.IsEnabled() {
|
||||
t.Error("test failed - base IsEnabled() error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsConnected(t *testing.T) {
|
||||
if !b.IsConnected() {
|
||||
t.Error("test failed - base IsConnected() error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetName(t *testing.T) {
|
||||
if b.GetName() != "test" {
|
||||
t.Error("test failed - base GetName() error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTicker(t *testing.T) {
|
||||
v := b.GetTicker("ANX")
|
||||
if v != "" {
|
||||
t.Error("test failed - base GetTicker() error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetOrderbook(t *testing.T) {
|
||||
v := b.GetOrderbook("ANX")
|
||||
if v != "" {
|
||||
t.Error("test failed - base GetOrderbook() error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPortfolio(t *testing.T) {
|
||||
v := b.GetPortfolio()
|
||||
if v != "{}" {
|
||||
t.Error("test failed - base GetPortfolio() error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSettings(t *testing.T) {
|
||||
v := b.GetSettings()
|
||||
if v != "{ }" {
|
||||
t.Error("test failed - base GetSettings() error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetStatus(t *testing.T) {
|
||||
v := b.GetStatus()
|
||||
if v == "" {
|
||||
t.Error("test failed - base GetStatus() error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetup(t *testing.T) {
|
||||
i.Setup()
|
||||
}
|
||||
|
||||
func TestPushEvent(t *testing.T) {
|
||||
i.PushEvent(Event{})
|
||||
}
|
||||
|
||||
func TestGetEnabledCommunicationMediums(t *testing.T) {
|
||||
i.GetEnabledCommunicationMediums()
|
||||
}
|
||||
Reference in New Issue
Block a user