diff --git a/README.md b/README.md
index f7eb9509..a89d917d 100644
--- a/README.md
+++ b/README.md
@@ -141,14 +141,14 @@ Binaries will be published once the codebase reaches a stable condition.
|User|Contribution Amount|
|--|--|
-| [thrasher-](https://github.com/thrasher-) | 640 |
+| [thrasher-](https://github.com/thrasher-) | 641 |
| [shazbert](https://github.com/shazbert) | 191 |
| [gloriousCode](https://github.com/gloriousCode) | 169 |
-| [dependabot-preview[bot]](https://github.com/apps/dependabot-preview) | 48 |
-| [xtda](https://github.com/xtda) | 43 |
+| [dependabot-preview[bot]](https://github.com/apps/dependabot-preview) | 51 |
+| [xtda](https://github.com/xtda) | 45 |
| [ermalguni](https://github.com/ermalguni) | 14 |
| [vadimzhukck](https://github.com/vadimzhukck) | 10 |
-| [MadCozBadd](https://github.com/MadCozBadd) | 8 |
+| [MadCozBadd](https://github.com/MadCozBadd) | 9 |
| [140am](https://github.com/140am) | 8 |
| [marcofranssen](https://github.com/marcofranssen) | 8 |
| [dackroyd](https://github.com/dackroyd) | 5 |
diff --git a/cmd/config/config.go b/cmd/config/config.go
index b1e28e48..640caf64 100644
--- a/cmd/config/config.go
+++ b/cmd/config/config.go
@@ -1,6 +1,7 @@
package main
import (
+ "encoding/json"
"flag"
"io/ioutil"
"log"
@@ -49,9 +50,9 @@ func main() {
if !config.ConfirmECS(fileData) && !encrypt {
var result interface{}
- errf := config.ConfirmConfigJSON(fileData, result)
+ errf := json.Unmarshal(fileData, &result)
if errf != nil {
- log.Fatal("File isn't in JSON format")
+ log.Fatal(errf)
}
log.Println("File is already decrypted. Encrypting..")
encrypt = true
diff --git a/cmd/exchange_template/exchange_template.go b/cmd/exchange_template/exchange_template.go
index 770167f0..be8da2df 100644
--- a/cmd/exchange_template/exchange_template.go
+++ b/cmd/exchange_template/exchange_template.go
@@ -15,7 +15,6 @@ import (
"github.com/thrasher-corp/gocryptotrader/config"
"github.com/thrasher-corp/gocryptotrader/core"
"github.com/thrasher-corp/gocryptotrader/currency"
- "github.com/thrasher-corp/gocryptotrader/exchanges/asset"
)
const (
@@ -147,9 +146,6 @@ func makeExchange(exch *exchange) error {
newExchConfig.API.Credentials.Key = "Key"
newExchConfig.API.Credentials.Secret = "Secret"
newExchConfig.CurrencyPairs = ¤cy.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- },
UseGlobalFormat: true,
RequestFormat: ¤cy.PairFormat{
Uppercase: true,
diff --git a/cmd/exchange_template/wrapper_file.tmpl b/cmd/exchange_template/wrapper_file.tmpl
index 80b24037..e708df43 100644
--- a/cmd/exchange_template/wrapper_file.tmpl
+++ b/cmd/exchange_template/wrapper_file.tmpl
@@ -17,7 +17,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -30,13 +30,10 @@ func ({{.Variable}} *{{.CapitalName}}) GetDefaultConfig() (*config.ExchangeConfi
exchCfg.HTTPTimeout = exchange.DefaultHTTPTimeout
exchCfg.BaseCurrencies = {{.Variable}}.BaseCurrencies
- err := {{.Variable}}.SetupDefaults(exchCfg)
- if err != nil {
- return nil, err
- }
+ {{.Variable}}.SetupDefaults(exchCfg)
if {{.Variable}}.Features.Supports.RESTCapabilities.AutoPairUpdates {
- err = {{.Variable}}.UpdateTradablePairs(true)
+ err := {{.Variable}}.UpdateTradablePairs(true)
if err != nil {
return nil, err
}
@@ -51,20 +48,46 @@ func ({{.Variable}} *{{.CapitalName}}) SetDefaults() {
{{.Variable}}.Verbose = true
{{.Variable}}.API.CredentialsValidator.RequiresKey = true
{{.Variable}}.API.CredentialsValidator.RequiresSecret = true
- {{.Variable}}.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- },
- UseGlobalFormat: true,
- RequestFormat: ¤cy.PairFormat{
- Uppercase: true,
- Delimiter: "-",
- },
- ConfigFormat: ¤cy.PairFormat{
- Uppercase: true,
- Delimiter: "-",
- },
+
+ // If using only one pair format for request and configuration, across all
+ // supported asset types either SPOT and FUTURES etc. You can use the
+ // example below:
+
+ // Request format denotes what the pair as a string will be, when you send
+ // a request to an exchange.
+ requestFmt := ¤cy.PairFormat{/*Set pair request formatting details here for e.g.*/ Uppercase: true, Delimiter: ":"}
+ // Config format denotes what the pair as a string will be, when saved to
+ // the config.json file.
+ configFmt := ¤cy.PairFormat{/*Set pair request formatting details here*/}
+ err := {{.Variable}}.SetGlobalPairsManager(requestFmt, configFmt, /*multiple assets can be set here using the asset package ie asset.Spot*/)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
}
+
+ // If assets require multiple differences in formating for request and
+ // configuration, another exchange method can be be used e.g. futures
+ // contracts require a dash as a delimiter rather than an underscore. You
+ // can use this example below:
+
+ fmt1 := currency.PairStore{
+ RequestFormat: ¤cy.PairFormat{Uppercase: true},
+ ConfigFormat: ¤cy.PairFormat{Uppercase: true},
+ }
+
+ fmt2 := currency.PairStore{
+ RequestFormat: ¤cy.PairFormat{Uppercase: true},
+ ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: ":"},
+ }
+
+ err = {{.Variable}}.StoreAssetPairFormat(asset.Spot, fmt1)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
+ }
+ err = {{.Variable}}.StoreAssetPairFormat(asset.Margin, fmt2)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
+ }
+
// Fill out the capabilities/features that the exchange supports
{{.Variable}}.Features = exchange.Features{
Supports: exchange.FeaturesSupported{
@@ -91,7 +114,7 @@ func ({{.Variable}} *{{.CapitalName}}) SetDefaults() {
{{.Variable}}.API.Endpoints.URLDefault = {{.Name}}APIURL
{{.Variable}}.API.Endpoints.URL = {{.Variable}}.API.Endpoints.URLDefault
- {{.Variable}}.Websocket = wshandler.New()
+ {{.Variable}}.Websocket = stream.New()
{{.Variable}}.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
{{.Variable}}.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
{{.Variable}}.WebsocketOrderbookBufferLimit = exchange.DefaultWebsocketOrderbookBufferLimit
@@ -104,15 +127,12 @@ func ({{.Variable}} *{{.CapitalName}}) Setup(exch *config.ExchangeConfig) error
return nil
}
- err := {{.Variable}}.SetupDefaults(exch)
- if err != nil {
- return err
- }
+ {{.Variable}}.SetupDefaults(exch)
// If websocket is supported, please fill out the following
/*
err = {{.Variable}}.Websocket.Setup(
- &wshandler.WebsocketSetup{
+ &stream.WebsocketSetup{
Enabled: exch.Features.Enabled.Websocket,
Verbose: exch.Verbose,
AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
@@ -129,7 +149,7 @@ func ({{.Variable}} *{{.CapitalName}}) Setup(exch *config.ExchangeConfig) error
return err
}
- {{.Variable}}.WebsocketConn = &wshandler.WebsocketConnection{
+ {{.Variable}}.WebsocketConn = &stream.WebsocketConnection{
ExchangeName: {{.Variable}}.Name,
URL: {{.Variable}}.Websocket.GetWebsocketURL(),
ProxyURL: {{.Variable}}.Websocket.GetProxyAddress(),
@@ -195,8 +215,13 @@ func ({{.Variable}} *{{.CapitalName}}) UpdateTradablePairs(forceUpdate bool) err
if err != nil {
return err
}
- return {{.Variable}}.UpdatePairs(currency.NewPairsFromStrings(pairs),
- asset.Spot, false, forceUpdate)
+
+ p, err := currency.NewPairsFromStrings(pairs)
+ if err != nil {
+ return err
+ }
+
+ return {{.Variable}}.UpdatePairs(p, asset.Spot, false, forceUpdate)
}
@@ -356,11 +381,6 @@ func ({{.Variable}} *{{.CapitalName}}) WithdrawFiatFundsToInternationalBank(with
return nil, common.ErrNotYetImplemented
}
-// GetWebsocket returns a pointer to the exchange websocket
-func ({{.Variable}} *{{.CapitalName}}) GetWebsocket() (*wshandler.Websocket, error) {
- return nil, common.ErrNotYetImplemented
-}
-
// GetActiveOrders retrieves any orders that are active/open
func ({{.Variable}} *{{.CapitalName}}) GetActiveOrders(getOrdersRequest *order.GetOrdersRequest) ([]order.Detail, error) {
return nil, common.ErrNotYetImplemented
@@ -377,30 +397,6 @@ func ({{.Variable}} *{{.CapitalName}}) GetFeeByType(feeBuilder *exchange.FeeBuil
return 0, common.ErrNotYetImplemented
}
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func ({{.Variable}} *{{.CapitalName}}) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- {{.Variable}}.Websocket.SubscribeToChannels(channels)
- return nil
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func ({{.Variable}} *{{.CapitalName}}) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- {{.Variable}}.Websocket.RemoveSubscribedChannels(channels)
- return nil
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func ({{.Variable}} *{{.CapitalName}}) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return nil, common.ErrNotYetImplemented
-}
-
-// AuthenticateWebsocket sends an authentication message to the websocket
-func ({{.Variable}} *{{.CapitalName}}) AuthenticateWebsocket() error {
- return common.ErrNotYetImplemented
-}
-
// ValidateCredentials validates current credentials used for wrapper
func ({{.Variable}} *{{.CapitalName}}) ValidateCredentials() error {
_, err := {{.Variable}}.UpdateAccountInfo()
diff --git a/cmd/exchange_wrapper_issues/main.go b/cmd/exchange_wrapper_issues/main.go
index 62ae820d..5cb63322 100644
--- a/cmd/exchange_wrapper_issues/main.go
+++ b/cmd/exchange_wrapper_issues/main.go
@@ -296,10 +296,16 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config)
switch {
case currencyPairOverride != "":
- p = currency.NewPairFromString(currencyPairOverride)
+ var err error
+ p, err = currency.NewPairFromString(currencyPairOverride)
+ if err != nil {
+ log.Printf("%v Encountered error: '%v'", base.GetName(), err)
+ continue
+ }
case len(base.Config.CurrencyPairs.Pairs[assetTypes[i]].Enabled) == 0:
if len(base.Config.CurrencyPairs.Pairs[assetTypes[i]].Available) == 0 {
- log.Printf("%v has no enabled or available currencies. Skipping", base.GetName())
+ log.Printf("%v has no enabled or available currencies. Skipping",
+ base.GetName())
continue
}
p = base.Config.CurrencyPairs.Pairs[assetTypes[i]].Available.GetRandomPair()
@@ -308,8 +314,8 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config)
}
responseContainer := ExchangeAssetPairResponses{
- AssetType: assetTypes[i],
- CurrencyPair: p,
+ AssetType: assetTypes[i],
+ Pair: p,
}
log.Printf("Setup config for %v %v %v", base.GetName(), assetTypes[i], p)
@@ -858,7 +864,7 @@ func outputToConsole(exchangeResponses []ExchangeResponses) {
log.Printf("%v Result: %v", exchangeResponses[i].ExchangeName, k)
log.Printf("Function:\t%v", exchangeResponses[i].AssetPairResponses[j].EndpointResponses[k].Function)
log.Printf("AssetType:\t%v", exchangeResponses[i].AssetPairResponses[j].AssetType)
- log.Printf("Currency:\t%v\n", exchangeResponses[i].AssetPairResponses[j].CurrencyPair)
+ log.Printf("Currency:\t%v\n", exchangeResponses[i].AssetPairResponses[j].Pair)
log.Printf("Wrapper Params:\t%s\n", exchangeResponses[i].AssetPairResponses[j].EndpointResponses[k].SentParams)
if exchangeResponses[i].AssetPairResponses[j].EndpointResponses[k].Error != "" {
totalErrors++
diff --git a/cmd/exchange_wrapper_issues/report.tmpl b/cmd/exchange_wrapper_issues/report.tmpl
index 2fcede34..ad380698 100644
--- a/cmd/exchange_wrapper_issues/report.tmpl
+++ b/cmd/exchange_wrapper_issues/report.tmpl
@@ -69,10 +69,10 @@
{{ if eq $length 1 }}
{{ else }}
-
{{ $assetPairResponses.AssetType }} {{ $assetPairResponses.CurrencyPair }} Results
+
{{ $assetPairResponses.AssetType }} {{ $assetPairResponses.Pair}} Results
- {{ $assetPairResponses.AssetType }} {{ $assetPairResponses.CurrencyPair }} Total Errors:
+ {{ $assetPairResponses.AssetType }} {{ $assetPairResponses.Pair}} Total Errors:
{{ $assetPairResponses.ErrorCount }}
@@ -108,18 +108,18 @@
{{ $assetPairResponses.AssetType }}
- {{ $assetPairResponses.CurrencyPair }}
+ {{ $assetPairResponses.Pair}}
|
{{ $endpointResponse.Function }}
|
-
{{ $endpointResponse.SentParams | printf "%s" }}
@@ -131,11 +131,11 @@
|
-
{{ $endpointResponse.Response | printf "%s" }}
diff --git a/cmd/exchange_wrapper_issues/types.go b/cmd/exchange_wrapper_issues/types.go
index 08b7e467..ebf518fe 100644
--- a/cmd/exchange_wrapper_issues/types.go
+++ b/cmd/exchange_wrapper_issues/types.go
@@ -58,7 +58,7 @@ type ExchangeResponses struct {
type ExchangeAssetPairResponses struct {
ErrorCount int64 `json:"errorCount"`
AssetType asset.Item `json:"asset"`
- CurrencyPair currency.Pair `json:"currency"`
+ Pair currency.Pair `json:"currency"`
EndpointResponses []EndpointResponse `json:"responses"`
}
diff --git a/cmd/gctcli/commands.go b/cmd/gctcli/commands.go
index cef30dae..f9374ca9 100644
--- a/cmd/gctcli/commands.go
+++ b/cmd/gctcli/commands.go
@@ -7,9 +7,7 @@ import (
"io/ioutil"
"math"
"os"
- "os/exec"
"path/filepath"
- "runtime"
"strconv"
"strings"
"time"
@@ -566,7 +564,11 @@ func getTicker(c *cli.Context) error {
}
defer conn.Close()
- p := currency.NewPairDelimiter(currencyPair, pairDelimiter)
+ p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter)
+ if err != nil {
+ return err
+ }
+
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetTicker(context.Background(),
&gctrpc.GetTickerRequest{
@@ -679,7 +681,11 @@ func getOrderbook(c *cli.Context) error {
}
defer conn.Close()
- p := currency.NewPairDelimiter(currencyPair, pairDelimiter)
+ p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter)
+ if err != nil {
+ return err
+ }
+
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetOrderbook(context.Background(),
&gctrpc.GetOrderbookRequest{
@@ -1199,7 +1205,11 @@ func getOrders(c *cli.Context) error {
}
defer conn.Close()
- p := currency.NewPairDelimiter(currencyPair, pairDelimiter)
+ p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter)
+ if err != nil {
+ return err
+ }
+
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetOrders(context.Background(), &gctrpc.GetOrdersRequest{
Exchange: exchangeName,
@@ -1407,7 +1417,11 @@ func submitOrder(c *cli.Context) error {
}
defer conn.Close()
- p := currency.NewPairDelimiter(currencyPair, pairDelimiter)
+ p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter)
+ if err != nil {
+ return err
+ }
+
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.SubmitOrder(context.Background(), &gctrpc.SubmitOrderRequest{
Exchange: exchangeName,
@@ -1516,7 +1530,11 @@ func simulateOrder(c *cli.Context) error {
}
defer conn.Close()
- p := currency.NewPairDelimiter(currencyPair, pairDelimiter)
+ p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter)
+ if err != nil {
+ return err
+ }
+
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.SimulateOrder(context.Background(), &gctrpc.SimulateOrderRequest{
Exchange: exchangeName,
@@ -1618,7 +1636,11 @@ func whaleBomb(c *cli.Context) error {
}
defer conn.Close()
- p := currency.NewPairDelimiter(currencyPair, pairDelimiter)
+ p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter)
+ if err != nil {
+ return err
+ }
+
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.WhaleBomb(context.Background(), &gctrpc.WhaleBombRequest{
Exchange: exchangeName,
@@ -1750,7 +1772,11 @@ func cancelOrder(c *cli.Context) error {
if !validPair(currencyPair) {
return errInvalidPair
}
- p = currency.NewPairDelimiter(currencyPair, pairDelimiter)
+ var err error
+ p, err = currency.NewPairDelimiter(currencyPair, pairDelimiter)
+ if err != nil {
+ return err
+ }
}
conn, err := setupClient()
@@ -1985,7 +2011,11 @@ func addEvent(c *cli.Context) error {
}
defer conn.Close()
- p := currency.NewPairDelimiter(currencyPair, pairDelimiter)
+ p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter)
+ if err != nil {
+ return err
+ }
+
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.AddEvent(context.Background(), &gctrpc.AddEventRequest{
Exchange: exchangeName,
@@ -2776,249 +2806,6 @@ func setLoggerDetails(c *cli.Context) error {
return nil
}
-var getExchangePairsCommand = cli.Command{
- Name: "getexchangepairs",
- Usage: "gets an exchanges supported currency pairs (available and enabled) plus asset types",
- ArgsUsage: " ",
- Action: getExchangePairs,
- Flags: []cli.Flag{
- cli.StringFlag{
- Name: "exchange",
- Usage: "the exchange to list of the currency pairs of",
- },
- cli.StringFlag{
- Name: "asset",
- Usage: "the asset type to filter by",
- },
- },
-}
-
-func getExchangePairs(c *cli.Context) error {
- if c.NArg() == 0 && c.NumFlags() == 0 {
- cli.ShowCommandHelp(c, "getexchangepairs")
- return nil
- }
-
- var exchange string
- var asset string
-
- if c.IsSet("exchange") {
- exchange = c.String("exchange")
- } else {
- exchange = c.Args().First()
- }
-
- if !validExchange(exchange) {
- return errInvalidExchange
- }
-
- if c.IsSet("asset") {
- asset = c.String("asset")
- } else {
- asset = c.Args().Get(1)
- }
-
- asset = strings.ToLower(asset)
- if !validAsset(asset) {
- return errInvalidAsset
- }
-
- conn, err := setupClient()
- if err != nil {
- return err
- }
- defer conn.Close()
-
- client := gctrpc.NewGoCryptoTraderClient(conn)
- result, err := client.GetExchangePairs(context.Background(),
- &gctrpc.GetExchangePairsRequest{
- Exchange: exchange,
- Asset: asset,
- },
- )
- if err != nil {
- return err
- }
- jsonOutput(result)
- return nil
-}
-
-var enableExchangePairCommand = cli.Command{
- Name: "enableexchangepair",
- Usage: "enables an exchange currency pair",
- ArgsUsage: " ",
- Action: enableExchangePair,
- Flags: []cli.Flag{
- cli.StringFlag{
- Name: "exchange",
- Usage: "the exchange to enable the currency pair for",
- },
- cli.StringFlag{
- Name: "pair",
- Usage: "the currency pair to enable",
- },
- cli.StringFlag{
- Name: "asset",
- Usage: "the asset type to enable the currency pair for",
- },
- },
-}
-
-func enableExchangePair(c *cli.Context) error {
- if c.NArg() == 0 && c.NumFlags() == 0 {
- cli.ShowCommandHelp(c, "enableexchangepair")
- return nil
- }
-
- var exchange string
- var pair string
- var asset string
-
- if c.IsSet("exchange") {
- exchange = c.String("exchange")
- } else {
- exchange = c.Args().First()
- }
-
- if !validExchange(exchange) {
- return errInvalidExchange
- }
-
- if c.IsSet("pair") {
- pair = c.String("pair")
- } else {
- pair = c.Args().Get(1)
- }
-
- if !validPair(pair) {
- return errInvalidPair
- }
-
- if c.IsSet("asset") {
- asset = c.String("asset")
- } else {
- asset = c.Args().Get(2)
- }
-
- asset = strings.ToLower(asset)
- if !validAsset(asset) {
- return errInvalidAsset
- }
-
- conn, err := setupClient()
- if err != nil {
- return err
- }
- defer conn.Close()
-
- p := currency.NewPairDelimiter(pair, pairDelimiter)
- client := gctrpc.NewGoCryptoTraderClient(conn)
- result, err := client.EnableExchangePair(context.Background(),
- &gctrpc.ExchangePairRequest{
- Exchange: exchange,
- Pair: &gctrpc.CurrencyPair{
- Delimiter: p.Delimiter,
- Base: p.Base.String(),
- Quote: p.Quote.String(),
- },
- AssetType: asset,
- },
- )
- if err != nil {
- return err
- }
- jsonOutput(result)
- return nil
-}
-
-var disableExchangePairCommand = cli.Command{
- Name: "disableexchangepair",
- Usage: "disables a previously enabled exchange currency pair",
- ArgsUsage: " ",
- Action: disableExchangePair,
- Flags: []cli.Flag{
- cli.StringFlag{
- Name: "exchange",
- Usage: "the exchange to disable the currency pair for",
- },
- cli.StringFlag{
- Name: "pair",
- Usage: "the currency pair to disable",
- },
- cli.StringFlag{
- Name: "asset",
- Usage: "the asset type to disable the currency pair for",
- },
- },
-}
-
-func disableExchangePair(c *cli.Context) error {
- if c.NArg() == 0 && c.NumFlags() == 0 {
- cli.ShowCommandHelp(c, "disableexchangepair")
- return nil
- }
-
- var exchange string
- var pair string
- var asset string
-
- if c.IsSet("exchange") {
- exchange = c.String("exchange")
- } else {
- exchange = c.Args().First()
- }
-
- if !validExchange(exchange) {
- return errInvalidExchange
- }
-
- if c.IsSet("pair") {
- pair = c.String("pair")
- } else {
- pair = c.Args().Get(1)
- }
-
- if !validPair(pair) {
- return errInvalidPair
- }
-
- if c.IsSet("asset") {
- asset = c.String("asset")
- } else {
- asset = c.Args().Get(2)
- }
-
- asset = strings.ToLower(asset)
- if !validAsset(asset) {
- return errInvalidAsset
- }
-
- conn, err := setupClient()
- if err != nil {
- return err
- }
- defer conn.Close()
-
- p := currency.NewPairDelimiter(pair, pairDelimiter)
- client := gctrpc.NewGoCryptoTraderClient(conn)
- result, err := client.DisableExchangePair(context.Background(),
- &gctrpc.ExchangePairRequest{
- Exchange: exchange,
- Pair: &gctrpc.CurrencyPair{
- Delimiter: p.Delimiter,
- Base: p.Base.String(),
- Quote: p.Quote.String(),
- },
- AssetType: asset,
- },
- )
- if err != nil {
- return err
- }
- jsonOutput(result)
- return nil
-}
-
var getOrderbookStreamCommand = cli.Command{
Name: "getorderbookstream",
Usage: "gets the orderbook stream for a specific currency pair and exchange",
@@ -3088,7 +2875,10 @@ func getOrderbookStream(c *cli.Context) error {
}
defer conn.Close()
- p := currency.NewPairDelimiter(pair, pairDelimiter)
+ p, err := currency.NewPairDelimiter(pair, pairDelimiter)
+ if err != nil {
+ return err
+ }
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetOrderbookStream(context.Background(),
@@ -3296,7 +3086,10 @@ func getTickerStream(c *cli.Context) error {
}
defer conn.Close()
- p := currency.NewPairDelimiter(pair, pairDelimiter)
+ p, err := currency.NewPairDelimiter(pair, pairDelimiter)
+ if err != nil {
+ return err
+ }
client := gctrpc.NewGoCryptoTraderClient(conn)
result, err := client.GetTickerStream(context.Background(),
@@ -3410,19 +3203,6 @@ func getExchangeTickerStream(c *cli.Context) error {
}
}
-func clearScreen() error {
- switch runtime.GOOS {
- case "windows":
- cmd := exec.Command("cmd", "/c", "cls")
- cmd.Stdout = os.Stdout
- return cmd.Run()
- default:
- cmd := exec.Command("clear")
- cmd.Stdout = os.Stdout
- return cmd.Run()
- }
-}
-
var getAuditEventCommand = cli.Command{
Name: "getauditevent",
Usage: "gets audit events matching query parameters",
@@ -3529,8 +3309,8 @@ func getAuditEvent(c *cli.Context) error {
var uuid, filename, path string
var gctScriptCommand = cli.Command{
- Name: "gctscript",
- Usage: "execute gctscript command",
+ Name: "script",
+ Usage: "execute scripting management command",
ArgsUsage: " ",
Subcommands: []cli.Command{
{
@@ -4022,7 +3802,10 @@ func getHistoricCandles(c *cli.Context) error {
if !validPair(currencyPair) {
return errInvalidPair
}
- p := currency.NewPairDelimiter(currencyPair, pairDelimiter)
+ p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter)
+ if err != nil {
+ return err
+ }
var assetType string
if c.IsSet("asset") {
@@ -4038,7 +3821,6 @@ func getHistoricCandles(c *cli.Context) error {
if c.IsSet("rangesize") {
candleRangeSize = c.Int64("rangesize")
} else if c.Args().Get(3) != "" {
- var err error
candleRangeSize, err = strconv.ParseInt(c.Args().Get(3), 10, 64)
if err != nil {
return err
@@ -4048,7 +3830,6 @@ func getHistoricCandles(c *cli.Context) error {
if c.IsSet("granularity") {
candleGranularity = c.Int64("granularity")
} else if c.Args().Get(4) != "" {
- var err error
candleGranularity, err = strconv.ParseInt(c.Args().Get(4), 10, 64)
if err != nil {
return err
@@ -4151,7 +3932,11 @@ func getHistoricCandlesExtended(c *cli.Context) error {
if !validPair(currencyPair) {
return errInvalidPair
}
- p := currency.NewPairDelimiter(currencyPair, pairDelimiter)
+
+ p, err := currency.NewPairDelimiter(currencyPair, pairDelimiter)
+ if err != nil {
+ return err
+ }
var assetType string
if c.IsSet("asset") {
@@ -4167,7 +3952,6 @@ func getHistoricCandlesExtended(c *cli.Context) error {
if c.IsSet("interval") {
candleGranularity = c.Int64("interval")
} else if c.Args().Get(3) != "" {
- var err error
candleGranularity, err = strconv.ParseInt(c.Args().Get(3), 10, 64)
if err != nil {
return err
diff --git a/cmd/gctcli/helpers.go b/cmd/gctcli/helpers.go
new file mode 100644
index 00000000..8a1872d9
--- /dev/null
+++ b/cmd/gctcli/helpers.go
@@ -0,0 +1,20 @@
+package main
+
+import (
+ "os"
+ "os/exec"
+ "runtime"
+)
+
+func clearScreen() error {
+ switch runtime.GOOS {
+ case "windows":
+ cmd := exec.Command("cmd", "/c", "cls")
+ cmd.Stdout = os.Stdout
+ return cmd.Run()
+ default:
+ cmd := exec.Command("clear")
+ cmd.Stdout = os.Stdout
+ return cmd.Run()
+ }
+}
diff --git a/cmd/gctcli/main.go b/cmd/gctcli/main.go
index 01f2b214..7b08ba54 100644
--- a/cmd/gctcli/main.go
+++ b/cmd/gctcli/main.go
@@ -127,9 +127,7 @@ func main() {
withdrawalRequestCommand,
getLoggerDetailsCommand,
setLoggerDetailsCommand,
- getExchangePairsCommand,
- enableExchangePairCommand,
- disableExchangePairCommand,
+ exchangePairManagerCommand,
getOrderbookStreamCommand,
getExchangeOrderbookStreamCommand,
getTickerStreamCommand,
@@ -138,6 +136,7 @@ func main() {
getHistoricCandlesCommand,
getHistoricCandlesExtendedCommand,
gctScriptCommand,
+ websocketManagerCommand,
}
err := app.Run(os.Args)
diff --git a/cmd/gctcli/pair_management.go b/cmd/gctcli/pair_management.go
new file mode 100644
index 00000000..148ae0fd
--- /dev/null
+++ b/cmd/gctcli/pair_management.go
@@ -0,0 +1,456 @@
+package main
+
+import (
+ "context"
+ "strings"
+
+ "github.com/thrasher-corp/gocryptotrader/currency"
+ "github.com/thrasher-corp/gocryptotrader/gctrpc"
+ "github.com/urfave/cli"
+)
+
+var exchangePairManagerCommand = cli.Command{
+ Name: "pair",
+ Usage: "execute exchange pair management command",
+ ArgsUsage: " ",
+ Subcommands: []cli.Command{
+ {
+ Name: "get",
+ Usage: "returns all enabled and available pairs by asset type",
+ ArgsUsage: "",
+ Flags: []cli.Flag{
+ cli.StringFlag{
+ Name: "exchange",
+ Usage: "the exchange to act on",
+ },
+ cli.StringFlag{
+ Name: "asset",
+ Usage: "asset",
+ },
+ },
+ Action: getExchangePairs,
+ },
+ {
+ Name: "disableasset",
+ Usage: "disables asset type",
+ Flags: []cli.Flag{
+ cli.StringFlag{
+ Name: "exchange",
+ Usage: "the exchange to act on",
+ },
+ cli.StringFlag{
+ Name: "asset",
+ Usage: "asset",
+ },
+ },
+ Action: enableDisableExchangeAsset,
+ },
+ {
+ Name: "enableasset",
+ Usage: "enables asset type",
+ Flags: []cli.Flag{
+ cli.StringFlag{
+ Name: "exchange",
+ Usage: "the exchange to act on",
+ },
+ cli.StringFlag{
+ Name: "asset",
+ Usage: "asset",
+ },
+ cli.BoolTFlag{
+ Name: "enable",
+ Hidden: true,
+ },
+ },
+ Action: enableDisableExchangeAsset,
+ },
+ {
+ Name: "disable",
+ Usage: "disable pairs by asset type",
+ Flags: []cli.Flag{
+ cli.StringFlag{
+ Name: "exchange",
+ Usage: "the exchange to act on",
+ },
+ cli.StringFlag{
+ Name: "pairs",
+ Usage: "either a single currency pair string or comma delimiter string of pairs e.g. \"BTC-USD,XRP-USD\"",
+ },
+ cli.StringFlag{
+ Name: "asset",
+ Usage: "asset",
+ },
+ },
+ Action: enableDisableExchangePair,
+ },
+ {
+ Name: "enable",
+ Usage: "enable pairs by asset type",
+ Flags: []cli.Flag{
+ cli.StringFlag{
+ Name: "exchange",
+ Usage: "the exchange to act on",
+ },
+ cli.StringFlag{
+ Name: "pairs",
+ Usage: "either a single currency pair string or comma delimiter string of pairs e.g. \"BTC-USD,XRP-USD\"",
+ },
+ cli.StringFlag{
+ Name: "asset",
+ Usage: "asset",
+ },
+ cli.BoolTFlag{
+ Name: "enable",
+ Hidden: true,
+ },
+ },
+ Action: enableDisableExchangePair,
+ },
+ {
+ Name: "enableall",
+ Usage: "enable all pairs",
+ Flags: []cli.Flag{
+ cli.StringFlag{
+ Name: "exchange",
+ Usage: "the exchange to act on",
+ },
+ cli.BoolTFlag{
+ Name: "enable",
+ Hidden: true,
+ },
+ },
+ Action: enableDisableAllExchangePairs,
+ },
+ {
+ Name: "disableall",
+ Usage: "dissable all pairs",
+ Flags: []cli.Flag{
+ cli.StringFlag{
+ Name: "exchange",
+ Usage: "the exchange to act on",
+ },
+ },
+ Action: enableDisableAllExchangePairs,
+ },
+ {
+ Name: "update",
+ Usage: "fetches supported pairs from the exchange and updates available pairs and removes unsupported enable pairs",
+ Flags: []cli.Flag{
+ cli.StringFlag{
+ Name: "exchange",
+ Usage: "the exchange to act on",
+ },
+ },
+ Action: updateExchangeSupportedPairs,
+ },
+ {
+ Name: "getassets",
+ Usage: "fetches supported assets",
+ Flags: []cli.Flag{
+ cli.StringFlag{
+ Name: "exchange",
+ Usage: "the exchange to act on",
+ },
+ },
+ Action: getExchangeAssets,
+ },
+ },
+}
+
+func enableDisableExchangePair(c *cli.Context) error {
+ enable := c.BoolT("enable")
+ if c.NArg() == 0 && c.NumFlags() == 0 {
+ if enable {
+ return cli.ShowCommandHelp(c, "enable")
+ }
+
+ return cli.ShowCommandHelp(c, "disable")
+ }
+
+ var exchange string
+ var pairs string
+ var asset string
+
+ if c.IsSet("exchange") {
+ exchange = c.String("exchange")
+ } else {
+ exchange = c.Args().First()
+ }
+
+ if !validExchange(exchange) {
+ return errInvalidExchange
+ }
+
+ if c.IsSet("pairs") {
+ pairs = c.String("pairs")
+ } else {
+ pairs = c.Args().Get(1)
+ }
+
+ if c.IsSet("asset") {
+ asset = c.String("asset")
+ } else {
+ asset = c.Args().Get(2)
+ }
+
+ asset = strings.ToLower(asset)
+ if !validAsset(asset) {
+ return errInvalidAsset
+ }
+
+ pairList := strings.Split(pairs, ",")
+
+ var validPairs []*gctrpc.CurrencyPair
+ for i := range pairList {
+ if !validPair(pairList[i]) {
+ return errInvalidPair
+ }
+
+ p, err := currency.NewPairFromString(pairList[i])
+ if err != nil {
+ return err
+ }
+
+ validPairs = append(validPairs, &gctrpc.CurrencyPair{
+ Delimiter: p.Delimiter,
+ Base: p.Base.String(),
+ Quote: p.Quote.String(),
+ })
+ }
+
+ conn, err := setupClient()
+ if err != nil {
+ return err
+ }
+ defer conn.Close()
+
+ client := gctrpc.NewGoCryptoTraderClient(conn)
+
+ result, err := client.SetExchangePair(context.Background(),
+ &gctrpc.SetExchangePairRequest{
+ Exchange: exchange,
+ Pairs: validPairs,
+ AssetType: asset,
+ Enable: enable,
+ },
+ )
+ if err != nil {
+ return err
+ }
+
+ jsonOutput(result)
+ return nil
+}
+
+func getExchangePairs(c *cli.Context) error {
+ if c.NArg() == 0 && c.NumFlags() == 0 {
+ return cli.ShowSubcommandHelp(c)
+ }
+
+ var exchange string
+ var asset string
+
+ if c.IsSet("exchange") {
+ exchange = c.String("exchange")
+ } else {
+ exchange = c.Args().First()
+ }
+
+ if !validExchange(exchange) {
+ return errInvalidExchange
+ }
+
+ if c.IsSet("asset") {
+ asset = c.String("asset")
+ } else {
+ asset = c.Args().Get(1)
+ }
+
+ asset = strings.ToLower(asset)
+ if !validAsset(asset) {
+ return errInvalidAsset
+ }
+
+ conn, err := setupClient()
+ if err != nil {
+ return err
+ }
+ defer conn.Close()
+
+ client := gctrpc.NewGoCryptoTraderClient(conn)
+ result, err := client.GetExchangePairs(context.Background(),
+ &gctrpc.GetExchangePairsRequest{
+ Exchange: exchange,
+ Asset: asset,
+ },
+ )
+ if err != nil {
+ return err
+ }
+ jsonOutput(result)
+ return nil
+}
+
+func enableDisableExchangeAsset(c *cli.Context) error {
+ enable := c.BoolT("enable")
+ if c.NArg() == 0 && c.NumFlags() == 0 {
+ if enable {
+ return cli.ShowCommandHelp(c, "enableasset")
+ }
+ return cli.ShowCommandHelp(c, "disableasset")
+ }
+
+ var exchange string
+ var asset string
+
+ if c.IsSet("exchange") {
+ exchange = c.String("exchange")
+ } else {
+ exchange = c.Args().First()
+ }
+
+ if !validExchange(exchange) {
+ return errInvalidExchange
+ }
+
+ if c.IsSet("asset") {
+ asset = c.String("asset")
+ } else {
+ asset = c.Args().Get(1)
+ }
+
+ asset = strings.ToLower(asset)
+ if !validAsset(asset) {
+ return errInvalidAsset
+ }
+
+ conn, err := setupClient()
+ if err != nil {
+ return err
+ }
+ defer conn.Close()
+
+ client := gctrpc.NewGoCryptoTraderClient(conn)
+ result, err := client.SetExchangeAsset(context.Background(),
+ &gctrpc.SetExchangeAssetRequest{
+ Exchange: exchange,
+ Asset: asset,
+ Enable: enable,
+ },
+ )
+ if err != nil {
+ return err
+ }
+ jsonOutput(result)
+ return nil
+}
+
+func enableDisableAllExchangePairs(c *cli.Context) error {
+ enable := c.BoolT("enable")
+ if c.NArg() == 0 && c.NumFlags() == 0 {
+ if enable {
+ return cli.ShowCommandHelp(c, "enableall")
+ }
+ return cli.ShowCommandHelp(c, "disableall")
+ }
+
+ var exchange string
+ if c.IsSet("exchange") {
+ exchange = c.String("exchange")
+ } else {
+ exchange = c.Args().First()
+ }
+
+ if !validExchange(exchange) {
+ return errInvalidExchange
+ }
+
+ conn, err := setupClient()
+ if err != nil {
+ return err
+ }
+ defer conn.Close()
+
+ client := gctrpc.NewGoCryptoTraderClient(conn)
+ result, err := client.SetAllExchangePairs(context.Background(),
+ &gctrpc.SetExchangeAllPairsRequest{
+ Exchange: exchange,
+ Enable: enable,
+ },
+ )
+ if err != nil {
+ return err
+ }
+ jsonOutput(result)
+ return nil
+}
+
+func updateExchangeSupportedPairs(c *cli.Context) error {
+ if c.NArg() == 0 && c.NumFlags() == 0 {
+ return cli.ShowSubcommandHelp(c)
+ }
+
+ var exchange string
+ if c.IsSet("exchange") {
+ exchange = c.String("exchange")
+ } else {
+ exchange = c.Args().First()
+ }
+
+ if !validExchange(exchange) {
+ return errInvalidExchange
+ }
+
+ conn, err := setupClient()
+ if err != nil {
+ return err
+ }
+ defer conn.Close()
+
+ client := gctrpc.NewGoCryptoTraderClient(conn)
+ result, err := client.UpdateExchangeSupportedPairs(context.Background(),
+ &gctrpc.UpdateExchangeSupportedPairsRequest{
+ Exchange: exchange,
+ },
+ )
+ if err != nil {
+ return err
+ }
+ jsonOutput(result)
+ return nil
+}
+
+func getExchangeAssets(c *cli.Context) error {
+ if c.NArg() == 0 && c.NumFlags() == 0 {
+ return cli.ShowSubcommandHelp(c)
+ }
+
+ var exchange string
+ if c.IsSet("exchange") {
+ exchange = c.String("exchange")
+ } else {
+ exchange = c.Args().First()
+ }
+
+ if !validExchange(exchange) {
+ return errInvalidExchange
+ }
+
+ conn, err := setupClient()
+ if err != nil {
+ return err
+ }
+ defer conn.Close()
+
+ client := gctrpc.NewGoCryptoTraderClient(conn)
+ result, err := client.GetExchangeAssets(context.Background(),
+ &gctrpc.GetExchangeAssetsRequest{
+ Exchange: exchange,
+ },
+ )
+ if err != nil {
+ return err
+ }
+ jsonOutput(result)
+ return nil
+}
diff --git a/cmd/gctcli/websocket_management.go b/cmd/gctcli/websocket_management.go
new file mode 100644
index 00000000..8b747e9c
--- /dev/null
+++ b/cmd/gctcli/websocket_management.go
@@ -0,0 +1,270 @@
+package main
+
+import (
+ "context"
+ "fmt"
+
+ "github.com/thrasher-corp/gocryptotrader/gctrpc"
+ "github.com/urfave/cli"
+)
+
+var websocketManagerCommand = cli.Command{
+ Name: "websocket",
+ Usage: "execute websocket management command",
+ ArgsUsage: " ",
+ Subcommands: []cli.Command{
+ {
+ Name: "getinfo",
+ Usage: "returns all exchange websocket information",
+ Flags: []cli.Flag{
+ cli.StringFlag{
+ Name: "exchange",
+ Usage: "the exchange to act on",
+ },
+ },
+ Action: getwebsocketInfo,
+ },
+ {
+ Name: "disable",
+ Usage: "disables websocket connection for an exchange",
+ Flags: []cli.Flag{
+ cli.StringFlag{
+ Name: "exchange",
+ Usage: "the exchange to act on",
+ },
+ },
+ Action: enableDisableWebsocket,
+ },
+ {
+ Name: "enable",
+ Usage: "enables websocket connection for an exchange",
+ Flags: []cli.Flag{
+ cli.StringFlag{
+ Name: "exchange",
+ Usage: "the exchange to act on",
+ },
+ cli.BoolTFlag{
+ Name: "enable",
+ Hidden: true,
+ },
+ },
+ Action: enableDisableWebsocket,
+ },
+ {
+ Name: "getsubs",
+ Usage: "returns current subscriptions for an exchange",
+ Flags: []cli.Flag{
+ cli.StringFlag{
+ Name: "exchange",
+ Usage: "the exchange to act on",
+ },
+ },
+ Action: getSubscriptions,
+ },
+ {
+ Name: "setproxy",
+ Usage: "sets exchange websocket proxy, flushes and reroutes connection",
+ Flags: []cli.Flag{
+ cli.StringFlag{
+ Name: "exchange",
+ Usage: "the exchange to act on",
+ },
+ cli.StringFlag{
+ Name: "proxy",
+ Usage: "proxy address to change to, if proxy string is not set, this will stop the utilization of the prior set proxy.",
+ },
+ },
+ Action: setProxy,
+ },
+ {
+ Name: "seturl",
+ Usage: "sets exchange websocket endpoint URL and resets the websocket connection",
+ Flags: []cli.Flag{
+ cli.StringFlag{
+ Name: "exchange",
+ Usage: "the exchange to act on",
+ },
+ cli.StringFlag{
+ Name: "url",
+ Usage: "url string to change to, an empty string will set it back to the packaged defined default",
+ },
+ },
+ Action: setURL,
+ },
+ },
+}
+
+func getwebsocketInfo(c *cli.Context) error {
+ if c.NArg() == 0 && c.NumFlags() == 0 {
+ return cli.ShowSubcommandHelp(c)
+ }
+
+ var exchange string
+ if c.IsSet("exchange") {
+ exchange = c.String("exchange")
+ } else {
+ exchange = c.Args().First()
+ }
+
+ if !validExchange(exchange) {
+ return fmt.Errorf("[%s] is not a valid exchange", exchange)
+ }
+
+ conn, err := setupClient()
+ if err != nil {
+ return err
+ }
+ defer conn.Close()
+
+ client := gctrpc.NewGoCryptoTraderClient(conn)
+ result, err := client.WebsocketGetInfo(context.Background(),
+ &gctrpc.WebsocketGetInfoRequest{Exchange: exchange})
+ if err != nil {
+ return err
+ }
+ jsonOutput(result)
+ return nil
+}
+
+func enableDisableWebsocket(c *cli.Context) error {
+ enable := c.BoolT("enable")
+ if c.NArg() == 0 && c.NumFlags() == 0 {
+ return cli.ShowSubcommandHelp(c)
+ }
+
+ var exchange string
+ if c.IsSet("exchange") {
+ exchange = c.String("exchange")
+ } else {
+ exchange = c.Args().First()
+ }
+
+ if !validExchange(exchange) {
+ return fmt.Errorf("[%s] is not a valid exchange", exchange)
+ }
+
+ conn, err := setupClient()
+ if err != nil {
+ return err
+ }
+ defer conn.Close()
+
+ client := gctrpc.NewGoCryptoTraderClient(conn)
+ result, err := client.WebsocketSetEnabled(context.Background(),
+ &gctrpc.WebsocketSetEnabledRequest{Exchange: exchange, Enable: enable})
+ if err != nil {
+ return err
+ }
+ jsonOutput(result)
+ return nil
+}
+
+func getSubscriptions(c *cli.Context) error {
+ if c.NArg() == 0 && c.NumFlags() == 0 {
+ return cli.ShowSubcommandHelp(c)
+ }
+
+ var exchange string
+ if c.IsSet("exchange") {
+ exchange = c.String("exchange")
+ } else {
+ exchange = c.Args().First()
+ }
+
+ if !validExchange(exchange) {
+ return fmt.Errorf("[%s] is not a valid exchange", exchange)
+ }
+
+ conn, err := setupClient()
+ if err != nil {
+ return err
+ }
+ defer conn.Close()
+
+ client := gctrpc.NewGoCryptoTraderClient(conn)
+ result, err := client.WebsocketGetSubscriptions(context.Background(),
+ &gctrpc.WebsocketGetSubscriptionsRequest{Exchange: exchange})
+ if err != nil {
+ return err
+ }
+ jsonOutput(result)
+ return nil
+}
+
+func setProxy(c *cli.Context) error {
+ if c.NArg() == 0 && c.NumFlags() == 0 {
+ return cli.ShowSubcommandHelp(c)
+ }
+
+ var exchange string
+ if c.IsSet("exchange") {
+ exchange = c.String("exchange")
+ } else {
+ exchange = c.Args().First()
+ }
+
+ if !validExchange(exchange) {
+ return fmt.Errorf("[%s] is not a valid exchange", exchange)
+ }
+
+ var proxy string
+ if c.IsSet("proxy") {
+ proxy = c.String("proxy")
+ } else {
+ proxy = c.Args().Get(1)
+ }
+
+ conn, err := setupClient()
+ if err != nil {
+ return err
+ }
+ defer conn.Close()
+
+ client := gctrpc.NewGoCryptoTraderClient(conn)
+ result, err := client.WebsocketSetProxy(context.Background(),
+ &gctrpc.WebsocketSetProxyRequest{Exchange: exchange, Proxy: proxy})
+ if err != nil {
+ return err
+ }
+ jsonOutput(result)
+ return nil
+}
+
+func setURL(c *cli.Context) error {
+ if c.NArg() == 0 && c.NumFlags() == 0 {
+ return cli.ShowSubcommandHelp(c)
+ }
+
+ var exchange string
+ if c.IsSet("exchange") {
+ exchange = c.String("exchange")
+ } else {
+ exchange = c.Args().First()
+ }
+
+ if !validExchange(exchange) {
+ return fmt.Errorf("[%s] is not a valid exchange", exchange)
+ }
+
+ var url string
+ if c.IsSet("url") {
+ url = c.String("url")
+ } else {
+ url = c.Args().Get(1)
+ }
+
+ conn, err := setupClient()
+ if err != nil {
+ return err
+ }
+ defer conn.Close()
+
+ client := gctrpc.NewGoCryptoTraderClient(conn)
+ result, err := client.WebsocketSetURL(context.Background(),
+ &gctrpc.WebsocketSetURLRequest{Exchange: exchange, Url: url})
+ if err != nil {
+ return err
+ }
+ jsonOutput(result)
+ return nil
+}
diff --git a/common/common.go b/common/common.go
index 67ee52a9..dd587ae0 100644
--- a/common/common.go
+++ b/common/common.go
@@ -361,3 +361,18 @@ func InArray(val, array interface{}) (exists bool, index int) {
}
return
}
+
+// Errors defines multiple errors
+type Errors []error
+
+// Error implements error interface
+func (e Errors) Error() string {
+ if len(e) == 0 {
+ return ""
+ }
+ var r string
+ for i := range e {
+ r += e[i].Error() + ", "
+ }
+ return r[:len(r)-2]
+}
diff --git a/common/common_test.go b/common/common_test.go
index 31006441..391ba2b0 100644
--- a/common/common_test.go
+++ b/common/common_test.go
@@ -1,6 +1,7 @@
package common
import (
+ "errors"
"net/url"
"os"
"os/user"
@@ -547,3 +548,18 @@ func TestInArray(t *testing.T) {
t.Errorf("found a non existent value in the slice")
}
}
+
+func TestErrors(t *testing.T) {
+ var test Errors
+ if test.Error() != "" {
+ t.Fatal("string should be nil")
+ }
+ test = append(test, errors.New("test1"))
+ if test.Error() != "test1" {
+ t.Fatal("does not match error")
+ }
+ test = append(test, errors.New("test2"))
+ if test.Error() != "test1, test2" {
+ t.Fatal("does not match error")
+ }
+}
diff --git a/config/config.go b/config/config.go
index 5467373e..4f3bb2af 100644
--- a/config/config.go
+++ b/config/config.go
@@ -345,71 +345,46 @@ func (c *Config) GetExchangeAssetTypes(exchName string) (asset.Items, error) {
return nil, fmt.Errorf("exchange %s currency pairs is nil", exchName)
}
- return exchCfg.CurrencyPairs.AssetTypes, nil
+ return exchCfg.CurrencyPairs.GetAssetTypes(), nil
}
// SupportsExchangeAssetType returns whether or not the exchange supports the supplied asset type
-func (c *Config) SupportsExchangeAssetType(exchName string, assetType asset.Item) (bool, error) {
+func (c *Config) SupportsExchangeAssetType(exchName string, assetType asset.Item) error {
exchCfg, err := c.GetExchangeConfig(exchName)
if err != nil {
- return false, err
+ return err
}
if exchCfg.CurrencyPairs == nil {
- return false, fmt.Errorf("exchange %s currency pairs is nil", exchName)
+ return fmt.Errorf("exchange %s currency pairs is nil", exchName)
}
if !asset.IsValid(assetType) {
- return false, fmt.Errorf("exchange %s invalid asset types", exchName)
+ return fmt.Errorf("exchange %s invalid asset type %s",
+ exchName,
+ assetType)
}
- return exchCfg.CurrencyPairs.AssetTypes.Contains(assetType), nil
-}
-
-// CheckExchangeAssetsConsistency checks the exchanges supported assets compared to the stored
-// entries and removes any non supported
-func (c *Config) CheckExchangeAssetsConsistency(exchName string) {
- exchCfg, err := c.GetExchangeConfig(exchName)
- if err != nil {
- return
- }
-
- exchangeAssetTypes, err := c.GetExchangeAssetTypes(exchName)
- if err != nil {
- return
- }
-
- storedAssetTypes := exchCfg.CurrencyPairs.GetAssetTypes()
- for x := range storedAssetTypes {
- if !exchangeAssetTypes.Contains(storedAssetTypes[x]) {
- log.Warnf(log.ConfigMgr,
- "%s has non-needed stored asset type %v. Removing..\n",
- exchName, storedAssetTypes[x])
- exchCfg.CurrencyPairs.Delete(storedAssetTypes[x])
- }
+ if !exchCfg.CurrencyPairs.GetAssetTypes().Contains(assetType) {
+ return fmt.Errorf("exchange %s unsupported asset type %s",
+ exchName,
+ assetType)
}
+ return nil
}
// SetPairs sets the exchanges currency pairs
func (c *Config) SetPairs(exchName string, assetType asset.Item, enabled bool, pairs currency.Pairs) error {
- if len(pairs) == 0 {
- return fmt.Errorf("pairs is nil")
- }
-
exchCfg, err := c.GetExchangeConfig(exchName)
if err != nil {
return err
}
- supports, err := c.SupportsExchangeAssetType(exchName, assetType)
+ err = c.SupportsExchangeAssetType(exchName, assetType)
if err != nil {
return err
}
- if !supports {
- return fmt.Errorf("exchange %s does not support asset type %v", exchName, assetType)
- }
-
exchCfg.CurrencyPairs.StorePairs(assetType, pairs, enabled)
return nil
}
@@ -421,16 +396,12 @@ func (c *Config) GetCurrencyPairConfig(exchName string, assetType asset.Item) (*
return nil, err
}
- supports, err := c.SupportsExchangeAssetType(exchName, assetType)
+ err = c.SupportsExchangeAssetType(exchName, assetType)
if err != nil {
return nil, err
}
- if !supports {
- return nil, fmt.Errorf("exchange %s does not support asset type %v", exchName, assetType)
- }
-
- return exchCfg.CurrencyPairs.Get(assetType), nil
+ return exchCfg.CurrencyPairs.Get(assetType)
}
// CheckPairConfigFormats checks to see if the pair config format is valid
@@ -508,60 +479,128 @@ func (c *Config) CheckPairConsistency(exchName string) error {
return err
}
+ var atLeastOneEnabled bool
for x := range assetTypes {
enabledPairs, err := c.GetEnabledPairs(exchName, assetTypes[x])
+ if err == nil {
+ if len(enabledPairs) != 0 {
+ atLeastOneEnabled = true
+ continue
+ }
+ var enabled bool
+ enabled, err = c.AssetTypeEnabled(assetTypes[x], exchName)
+ if err != nil {
+ return err
+ }
+
+ if !enabled {
+ continue
+ }
+
+ var availPairs currency.Pairs
+ availPairs, err = c.GetAvailablePairs(exchName, assetTypes[x])
+ if err != nil {
+ return err
+ }
+
+ err = c.SetPairs(exchName,
+ assetTypes[x],
+ true,
+ currency.Pairs{availPairs.GetRandomPair()})
+ if err != nil {
+ return err
+ }
+ atLeastOneEnabled = true
+ continue
+ }
+
+ // On error an enabled pair is not found in the available pairs list
+ // so remove and report
+ availPairs, err := c.GetAvailablePairs(exchName, assetTypes[x])
if err != nil {
return err
}
- availPairs, _ := c.GetAvailablePairs(exchName, assetTypes[x])
- if len(availPairs) == 0 {
- continue
- }
-
var pairs, pairsRemoved currency.Pairs
- update := false
-
- if len(enabledPairs) > 0 {
- for x := range enabledPairs {
- if !availPairs.Contains(enabledPairs[x], true) {
- update = true
- pairsRemoved = append(pairsRemoved, enabledPairs[x])
- continue
- }
- pairs = append(pairs, enabledPairs[x])
+ for x := range enabledPairs {
+ if !availPairs.Contains(enabledPairs[x], true) {
+ pairsRemoved = append(pairsRemoved, enabledPairs[x])
+ continue
}
- } else {
- update = true
+ pairs = append(pairs, enabledPairs[x])
}
- if !update {
+ if len(pairsRemoved) == 0 {
+ return fmt.Errorf("check pair consistency fault for asset %s, conflict found but no pairs removed",
+ assetTypes[x])
+ }
+
+ // Flush corrupted/misspelled enabled pairs in config
+ err = c.SetPairs(exchName, assetTypes[x], true, pairs)
+ if err != nil {
+ return err
+ }
+
+ log.Warnf(log.ConfigMgr,
+ "Exchange %s: [%v] Removing enabled pair(s) %v from enabled pairs list, as it isn't located in the available pairs list.\n",
+ exchName,
+ assetTypes[x],
+ pairsRemoved.Strings())
+
+ if len(pairs) != 0 {
+ atLeastOneEnabled = true
continue
}
- if len(pairs) == 0 || len(enabledPairs) == 0 {
- newPair := availPairs.GetRandomPair()
- c.SetPairs(exchName, assetTypes[x], true, currency.Pairs{newPair})
- log.Warnf(log.ExchangeSys, "Exchange %s: [%v] No enabled pairs found in available pairs, randomly added %v pair.\n",
- exchName, assetTypes[x], newPair)
- continue
- } else {
- c.SetPairs(exchName, assetTypes[x], true, pairs)
+ enabled, err := c.AssetTypeEnabled(assetTypes[x], exchName)
+ if err != nil {
+ return err
}
- log.Warnf(log.ExchangeSys, "Exchange %s: [%v] Removing enabled pair(s) %v from enabled pairs as it isn't an available pair.\n",
- exchName, assetTypes[x], pairsRemoved.Strings())
+
+ if !enabled {
+ continue
+ }
+
+ err = c.SetPairs(exchName,
+ assetTypes[x],
+ true,
+ currency.Pairs{availPairs.GetRandomPair()})
+ if err != nil {
+ return err
+ }
+ atLeastOneEnabled = true
+ }
+
+ // If no pair is enabled across the entire range of assets, then atleast
+ // enable one and turn on the asset type
+ if !atLeastOneEnabled {
+ avail, err := c.GetAvailablePairs(exchName, assetTypes[0])
+ if err != nil {
+ return err
+ }
+
+ newPair := avail.GetRandomPair()
+ err = c.SetPairs(exchName, assetTypes[0], true, currency.Pairs{newPair})
+ if err != nil {
+ return err
+ }
+ log.Warnf(log.ConfigMgr,
+ "Exchange %s: [%v] No enabled pairs found in available pairs list, randomly added %v pair.\n",
+ exchName,
+ assetTypes[0],
+ newPair)
}
return nil
}
// SupportsPair returns true or not whether the exchange supports the supplied
// pair
-func (c *Config) SupportsPair(exchName string, p currency.Pair, assetType asset.Item) (bool, error) {
+func (c *Config) SupportsPair(exchName string, p currency.Pair, assetType asset.Item) bool {
pairs, err := c.GetAvailablePairs(exchName, assetType)
if err != nil {
- return false, err
+ return false
}
- return pairs.Contains(p, false), nil
+ return pairs.Contains(p, false)
}
// GetPairFormat returns the exchanges pair config storage format
@@ -571,25 +610,31 @@ func (c *Config) GetPairFormat(exchName string, assetType asset.Item) (currency.
return currency.PairFormat{}, err
}
- supports, err := c.SupportsExchangeAssetType(exchName, assetType)
+ err = c.SupportsExchangeAssetType(exchName, assetType)
if err != nil {
return currency.PairFormat{}, err
}
- if !supports {
- return currency.PairFormat{},
- fmt.Errorf("exchange %s does not support asset type %s", exchName,
- assetType)
- }
-
if exchCfg.CurrencyPairs.UseGlobalFormat {
return *exchCfg.CurrencyPairs.ConfigFormat, nil
}
- p := exchCfg.CurrencyPairs.Get(assetType)
+ p, err := exchCfg.CurrencyPairs.Get(assetType)
+ if err != nil {
+ return currency.PairFormat{}, err
+ }
+
if p == nil {
return currency.PairFormat{},
- fmt.Errorf("exchange %s pair store for asset type %s is nil", exchName,
+ fmt.Errorf("exchange %s pair store for asset type %s is nil",
+ exchName,
+ assetType)
+ }
+
+ if p.ConfigFormat == nil {
+ return currency.PairFormat{},
+ fmt.Errorf("exchange %s pair config format for asset type %s is nil",
+ exchName,
assetType)
}
@@ -608,7 +653,11 @@ func (c *Config) GetAvailablePairs(exchName string, assetType asset.Item) (curre
return nil, err
}
- pairs := exchCfg.CurrencyPairs.GetPairs(assetType, false)
+ pairs, err := exchCfg.CurrencyPairs.GetPairs(assetType, false)
+ if err != nil {
+ return nil, err
+ }
+
if pairs == nil {
return nil, nil
}
@@ -618,7 +667,7 @@ func (c *Config) GetAvailablePairs(exchName string, assetType asset.Item) (curre
}
// GetEnabledPairs returns a list of currency pairs for a specifc exchange
-func (c *Config) GetEnabledPairs(exchName string, assetType asset.Item) ([]currency.Pair, error) {
+func (c *Config) GetEnabledPairs(exchName string, assetType asset.Item) (currency.Pairs, error) {
exchCfg, err := c.GetExchangeConfig(exchName)
if err != nil {
return nil, err
@@ -629,13 +678,19 @@ func (c *Config) GetEnabledPairs(exchName string, assetType asset.Item) ([]curre
return nil, err
}
- pairs := exchCfg.CurrencyPairs.GetPairs(assetType, true)
+ pairs, err := exchCfg.CurrencyPairs.GetPairs(assetType, true)
+ if err != nil {
+ return pairs, err
+ }
+
if pairs == nil {
return nil, nil
}
- return pairs.Format(pairFormat.Delimiter, pairFormat.Index,
- pairFormat.Uppercase), nil
+ return pairs.Format(pairFormat.Delimiter,
+ pairFormat.Index,
+ pairFormat.Uppercase),
+ nil
}
// GetEnabledExchanges returns a list of enabled exchanges
@@ -843,16 +898,6 @@ func (c *Config) CheckExchangeConfigValues() error {
c.Exchanges[i].CurrencyPairs.ConfigFormat = c.Exchanges[i].ConfigCurrencyPairFormat
c.Exchanges[i].CurrencyPairs.RequestFormat = c.Exchanges[i].RequestCurrencyPairFormat
- if c.Exchanges[i].AssetTypes == nil {
- c.Exchanges[i].CurrencyPairs.AssetTypes = asset.Items{
- asset.Spot,
- }
- } else {
- c.Exchanges[i].CurrencyPairs.AssetTypes = asset.New(
- strings.ToLower(*c.Exchanges[i].AssetTypes),
- )
- }
-
var availPairs, enabledPairs currency.Pairs
if c.Exchanges[i].AvailablePairs != nil {
availPairs = *c.Exchanges[i].AvailablePairs
@@ -865,8 +910,9 @@ func (c *Config) CheckExchangeConfigValues() error {
c.Exchanges[i].CurrencyPairs.UseGlobalFormat = true
c.Exchanges[i].CurrencyPairs.Store(asset.Spot,
currency.PairStore{
- Available: availPairs,
- Enabled: enabledPairs,
+ AssetEnabled: convert.BoolPtr(true),
+ Available: availPairs,
+ Enabled: enabledPairs,
},
)
@@ -877,6 +923,50 @@ func (c *Config) CheckExchangeConfigValues() error {
c.Exchanges[i].AssetTypes = nil
c.Exchanges[i].AvailablePairs = nil
c.Exchanges[i].EnabledPairs = nil
+ } else {
+ assets := c.Exchanges[i].CurrencyPairs.GetAssetTypes()
+ var atLeastOne bool
+ for index := range assets {
+ err := c.Exchanges[i].CurrencyPairs.IsAssetEnabled(assets[index])
+ if err != nil {
+ // Checks if we have an old config without the ability to
+ // enable disable the entire asset
+ if err.Error() == "cannot ascertain if asset is enabled, variable is nil" {
+ log.Warnf(log.ConfigMgr,
+ "Exchange %s: upgrading config for asset type %s and setting enabled.\n",
+ c.Exchanges[i].Name,
+ assets[index])
+ err = c.Exchanges[i].CurrencyPairs.SetAssetEnabled(assets[index], true)
+ if err != nil {
+ return err
+ }
+ atLeastOne = true
+ }
+ continue
+ }
+ atLeastOne = true
+ }
+
+ if !atLeastOne {
+ if len(assets) == 0 {
+ c.Exchanges[i].Enabled = false
+ log.Warnf(log.ConfigMgr,
+ "%s no assets found, disabling...",
+ c.Exchanges[i].Name)
+ continue
+ }
+
+ // turn on an asset if all disabled
+ log.Warnf(log.ConfigMgr,
+ "%s assets disabled, turning on asset %s",
+ c.Exchanges[i].Name,
+ assets[0])
+
+ err := c.Exchanges[i].CurrencyPairs.SetAssetEnabled(assets[0], true)
+ if err != nil {
+ return err
+ }
+ }
}
if c.Exchanges[i].Enabled {
@@ -885,71 +975,101 @@ func (c *Config) CheckExchangeConfigValues() error {
c.Exchanges[i].Enabled = false
continue
}
- if (c.Exchanges[i].API.AuthenticatedSupport || c.Exchanges[i].API.AuthenticatedWebsocketSupport) && c.Exchanges[i].API.CredentialsValidator != nil {
+ if (c.Exchanges[i].API.AuthenticatedSupport || c.Exchanges[i].API.AuthenticatedWebsocketSupport) &&
+ c.Exchanges[i].API.CredentialsValidator != nil {
var failed bool
- if c.Exchanges[i].API.CredentialsValidator.RequiresKey && (c.Exchanges[i].API.Credentials.Key == "" || c.Exchanges[i].API.Credentials.Key == DefaultAPIKey) {
+ if c.Exchanges[i].API.CredentialsValidator.RequiresKey &&
+ (c.Exchanges[i].API.Credentials.Key == "" || c.Exchanges[i].API.Credentials.Key == DefaultAPIKey) {
failed = true
}
- if c.Exchanges[i].API.CredentialsValidator.RequiresSecret && (c.Exchanges[i].API.Credentials.Secret == "" || c.Exchanges[i].API.Credentials.Secret == DefaultAPISecret) {
+ if c.Exchanges[i].API.CredentialsValidator.RequiresSecret &&
+ (c.Exchanges[i].API.Credentials.Secret == "" || c.Exchanges[i].API.Credentials.Secret == DefaultAPISecret) {
failed = true
}
- if c.Exchanges[i].API.CredentialsValidator.RequiresClientID && (c.Exchanges[i].API.Credentials.ClientID == DefaultAPIClientID || c.Exchanges[i].API.Credentials.ClientID == "") {
+ if c.Exchanges[i].API.CredentialsValidator.RequiresClientID &&
+ (c.Exchanges[i].API.Credentials.ClientID == DefaultAPIClientID || c.Exchanges[i].API.Credentials.ClientID == "") {
failed = true
}
if failed {
c.Exchanges[i].API.AuthenticatedSupport = false
c.Exchanges[i].API.AuthenticatedWebsocketSupport = false
- log.Warnf(log.ExchangeSys, WarningExchangeAuthAPIDefaultOrEmptyValues, c.Exchanges[i].Name)
+ log.Warnf(log.ConfigMgr, WarningExchangeAuthAPIDefaultOrEmptyValues, c.Exchanges[i].Name)
}
}
- if !c.Exchanges[i].Features.Supports.RESTCapabilities.AutoPairUpdates && !c.Exchanges[i].Features.Supports.WebsocketCapabilities.AutoPairUpdates {
+ if !c.Exchanges[i].Features.Supports.RESTCapabilities.AutoPairUpdates &&
+ !c.Exchanges[i].Features.Supports.WebsocketCapabilities.AutoPairUpdates {
lastUpdated := convert.UnixTimestampToTime(c.Exchanges[i].CurrencyPairs.LastUpdated)
lastUpdated = lastUpdated.AddDate(0, 0, pairsLastUpdatedWarningThreshold)
if lastUpdated.Unix() <= time.Now().Unix() {
- log.Warnf(log.ExchangeSys, WarningPairsLastUpdatedThresholdExceeded, c.Exchanges[i].Name, pairsLastUpdatedWarningThreshold)
+ log.Warnf(log.ConfigMgr,
+ WarningPairsLastUpdatedThresholdExceeded,
+ c.Exchanges[i].Name,
+ pairsLastUpdatedWarningThreshold)
}
}
if c.Exchanges[i].HTTPTimeout <= 0 {
- log.Warnf(log.ExchangeSys, "Exchange %s HTTP Timeout value not set, defaulting to %v.\n", c.Exchanges[i].Name, defaultHTTPTimeout)
+ log.Warnf(log.ConfigMgr,
+ "Exchange %s HTTP Timeout value not set, defaulting to %v.\n",
+ c.Exchanges[i].Name,
+ defaultHTTPTimeout)
c.Exchanges[i].HTTPTimeout = defaultHTTPTimeout
}
if c.Exchanges[i].WebsocketResponseCheckTimeout <= 0 {
- log.Warnf(log.ExchangeSys, "Exchange %s Websocket response check timeout value not set, defaulting to %v.",
- c.Exchanges[i].Name, defaultWebsocketResponseCheckTimeout)
+ log.Warnf(log.ConfigMgr,
+ "Exchange %s Websocket response check timeout value not set, defaulting to %v.",
+ c.Exchanges[i].Name,
+ defaultWebsocketResponseCheckTimeout)
c.Exchanges[i].WebsocketResponseCheckTimeout = defaultWebsocketResponseCheckTimeout
}
if c.Exchanges[i].WebsocketResponseMaxLimit <= 0 {
- log.Warnf(log.ExchangeSys, "Exchange %s Websocket response max limit value not set, defaulting to %v.",
- c.Exchanges[i].Name, defaultWebsocketResponseMaxLimit)
+ log.Warnf(log.ConfigMgr,
+ "Exchange %s Websocket response max limit value not set, defaulting to %v.",
+ c.Exchanges[i].Name,
+ defaultWebsocketResponseMaxLimit)
c.Exchanges[i].WebsocketResponseMaxLimit = defaultWebsocketResponseMaxLimit
}
if c.Exchanges[i].WebsocketTrafficTimeout <= 0 {
- log.Warnf(log.ExchangeSys, "Exchange %s Websocket response traffic timeout value not set, defaulting to %v.",
- c.Exchanges[i].Name, defaultWebsocketTrafficTimeout)
+ log.Warnf(log.ConfigMgr,
+ "Exchange %s Websocket response traffic timeout value not set, defaulting to %v.",
+ c.Exchanges[i].Name,
+ defaultWebsocketTrafficTimeout)
c.Exchanges[i].WebsocketTrafficTimeout = defaultWebsocketTrafficTimeout
}
if c.Exchanges[i].WebsocketOrderbookBufferLimit <= 0 {
- log.Warnf(log.ExchangeSys, "Exchange %s Websocket orderbook buffer limit value not set, defaulting to %v.",
- c.Exchanges[i].Name, defaultWebsocketOrderbookBufferLimit)
+ log.Warnf(log.ConfigMgr,
+ "Exchange %s Websocket orderbook buffer limit value not set, defaulting to %v.",
+ c.Exchanges[i].Name,
+ defaultWebsocketOrderbookBufferLimit)
c.Exchanges[i].WebsocketOrderbookBufferLimit = defaultWebsocketOrderbookBufferLimit
}
err := c.CheckPairConsistency(c.Exchanges[i].Name)
if err != nil {
- log.Errorf(log.ExchangeSys, "Exchange %s: CheckPairConsistency error: %s\n", c.Exchanges[i].Name, err)
+ log.Errorf(log.ConfigMgr,
+ "Exchange %s: CheckPairConsistency error: %s\n",
+ c.Exchanges[i].Name,
+ err)
c.Exchanges[i].Enabled = false
continue
}
-
- c.CheckExchangeAssetsConsistency(c.Exchanges[i].Name)
-
+ for x := range c.Exchanges[i].BankAccounts {
+ if !c.Exchanges[i].BankAccounts[x].Enabled {
+ continue
+ }
+ err := c.Exchanges[i].BankAccounts[x].Validate()
+ if err != nil {
+ c.Exchanges[i].BankAccounts[x].Enabled = false
+ log.Warnln(log.ConfigMgr, err.Error())
+ }
+ }
exchanges++
}
}
+
if exchanges == 0 {
return errors.New(ErrNoEnabledExchanges)
}
@@ -1104,8 +1224,8 @@ func (c *Config) RetrieveConfigCurrencyPairs(enabledOnly bool, assetType asset.I
continue
}
- supports, _ := c.SupportsExchangeAssetType(c.Exchanges[x].Name, assetType)
- if !supports {
+ err := c.SupportsExchangeAssetType(c.Exchanges[x].Name, assetType)
+ if err != nil {
continue
}
@@ -1118,13 +1238,12 @@ func (c *Config) RetrieveConfigCurrencyPairs(enabledOnly bool, assetType asset.I
}
for x := range c.Exchanges {
- supports, _ := c.SupportsExchangeAssetType(c.Exchanges[x].Name, assetType)
- if !supports {
+ err := c.SupportsExchangeAssetType(c.Exchanges[x].Name, assetType)
+ if err != nil {
continue
}
var pairs []currency.Pair
- var err error
if !c.Exchanges[x].Enabled && enabledOnly {
pairs, err = c.GetEnabledPairs(c.Exchanges[x].Name, assetType)
} else {
@@ -1475,7 +1594,7 @@ func (c *Config) ReadConfig(configPath string, dryrun bool) error {
}
if !ConfirmECS(fileData) {
- err = ConfirmConfigJSON(fileData, &c)
+ err = json.Unmarshal(fileData, c)
if err != nil {
return err
}
@@ -1493,38 +1612,39 @@ func (c *Config) ReadConfig(configPath string, dryrun bool) error {
return c.SaveConfig(defaultPath, dryrun)
}
}
- } else {
- errCounter := 0
- for {
- if errCounter >= maxAuthFailures {
- return errors.New("failed to decrypt config after 3 attempts")
- }
- key, err := PromptForConfigKey(IsInitialSetup)
- if err != nil {
- log.Errorf(log.ConfigMgr, "PromptForConfigKey err: %s", err)
- errCounter++
- continue
- }
+ return nil
+ }
- var f []byte
- f = append(f, fileData...)
- data, err := DecryptConfigFile(f, key)
- if err != nil {
- log.Errorf(log.ConfigMgr, "DecryptConfigFile err: %s", err)
- errCounter++
- continue
- }
-
- err = ConfirmConfigJSON(data, &c)
- if err != nil {
- if errCounter < maxAuthFailures {
- log.Error(log.ConfigMgr, "Invalid password.")
- }
- errCounter++
- continue
- }
- break
+ errCounter := 0
+ for {
+ if errCounter >= maxAuthFailures {
+ return errors.New("failed to decrypt config after 3 attempts")
}
+ key, err := PromptForConfigKey(IsInitialSetup)
+ if err != nil {
+ log.Errorf(log.ConfigMgr, "PromptForConfigKey err: %s", err)
+ errCounter++
+ continue
+ }
+
+ var f []byte
+ f = append(f, fileData...)
+ data, err := DecryptConfigFile(f, key)
+ if err != nil {
+ log.Errorf(log.ConfigMgr, "DecryptConfigFile err: %s", err)
+ errCounter++
+ continue
+ }
+
+ err = json.Unmarshal(data, c)
+ if err != nil {
+ if errCounter < maxAuthFailures {
+ log.Error(log.ConfigMgr, "Invalid password.")
+ }
+ errCounter++
+ continue
+ }
+ break
}
return nil
}
@@ -1611,12 +1731,16 @@ func (c *Config) CheckRemoteControlConfig() {
func (c *Config) CheckConfig() error {
err := c.CheckLoggerConfig()
if err != nil {
- log.Errorf(log.ConfigMgr, "Failed to configure logger, some logging features unavailable: %s\n", err)
+ log.Errorf(log.ConfigMgr,
+ "Failed to configure logger, some logging features unavailable: %s\n",
+ err)
}
err = c.checkDatabaseConfig()
if err != nil {
- log.Errorf(log.DatabaseMgr, "Failed to configure database: %v", err)
+ log.Errorf(log.DatabaseMgr,
+ "Failed to configure database: %v",
+ err)
}
err = c.CheckExchangeConfigValues()
@@ -1626,7 +1750,9 @@ func (c *Config) CheckConfig() error {
err = c.checkGCTScriptConfig()
if err != nil {
- log.Errorf(log.Global, "Failed to configure gctscript, feature has been disabled: %s\n", err)
+ log.Errorf(log.Global,
+ "Failed to configure gctscript, feature has been disabled: %s\n",
+ err)
}
c.CheckConnectionMonitorConfig()
@@ -1641,7 +1767,9 @@ func (c *Config) CheckConfig() error {
}
if c.GlobalHTTPTimeout <= 0 {
- log.Warnf(log.ConfigMgr, "Global HTTP Timeout value not set, defaulting to %v.\n", defaultHTTPTimeout)
+ log.Warnf(log.ConfigMgr,
+ "Global HTTP Timeout value not set, defaulting to %v.\n",
+ defaultHTTPTimeout)
c.GlobalHTTPTimeout = defaultHTTPTimeout
}
@@ -1703,3 +1831,17 @@ func (c *Config) RemoveExchange(exchName string) bool {
}
return false
}
+
+// AssetTypeEnabled checks to see if the asset type is enabled in configuration
+func (c *Config) AssetTypeEnabled(a asset.Item, exch string) (bool, error) {
+ cfg, err := c.GetExchangeConfig(exch)
+ if err != nil {
+ return false, err
+ }
+
+ err = cfg.CurrencyPairs.IsAssetEnabled(a)
+ if err != nil {
+ return false, nil
+ }
+ return true, nil
+}
diff --git a/config/config_encryption.go b/config/config_encryption.go
index bf32e0e1..c2ba139a 100644
--- a/config/config_encryption.go
+++ b/config/config_encryption.go
@@ -5,7 +5,6 @@ import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
- "encoding/json"
"errors"
"fmt"
"io"
@@ -167,11 +166,6 @@ func DecryptConfigFile(configData, key []byte) ([]byte, error) {
return result, nil
}
-// ConfirmConfigJSON confirms JSON in file
-func ConfirmConfigJSON(file []byte, result interface{}) error {
- return json.Unmarshal(file, &result)
-}
-
// ConfirmSalt checks whether the encrypted data contains a salt
func ConfirmSalt(file []byte) bool {
return bytes.Contains(file, []byte(SaltPrefix))
diff --git a/config/config_encryption_test.go b/config/config_encryption_test.go
index 3eabe392..23ceef30 100644
--- a/config/config_encryption_test.go
+++ b/config/config_encryption_test.go
@@ -1,7 +1,6 @@
package config
import (
- "io/ioutil"
"testing"
)
@@ -84,19 +83,6 @@ func TestDecryptConfigFile(t *testing.T) {
}
}
-func TestConfirmConfigJSON(t *testing.T) {
- var result interface{}
- testConfirmJSON, err := ioutil.ReadFile(TestFile)
- if err != nil {
- t.Errorf("testConfirmJSON: %s", err)
- }
-
- err = ConfirmConfigJSON(testConfirmJSON, &result)
- if err != nil || result == nil {
- t.Errorf("testConfirmJSON: %s", err)
- }
-}
-
func TestConfirmECS(t *testing.T) {
t.Parallel()
diff --git a/config/config_test.go b/config/config_test.go
index 286bba71..82a814c4 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -5,6 +5,7 @@ import (
"testing"
"github.com/thrasher-corp/gocryptotrader/common"
+ "github.com/thrasher-corp/gocryptotrader/common/convert"
"github.com/thrasher-corp/gocryptotrader/connchecker"
"github.com/thrasher-corp/gocryptotrader/currency"
"github.com/thrasher-corp/gocryptotrader/database"
@@ -21,6 +22,7 @@ const (
defaultEnabledExchanges = 28
testFakeExchangeName = "Stampbit"
testPair = "BTC-USD"
+ testString = "test"
)
func TestGetCurrencyConfig(t *testing.T) {
@@ -32,6 +34,22 @@ func TestGetCurrencyConfig(t *testing.T) {
_ = cfg.GetCurrencyConfig()
}
+func TestGetClientBankAccounts(t *testing.T) {
+ cfg := GetConfig()
+ err := cfg.LoadConfig(TestFile, true)
+ if err != nil {
+ t.Fatal("GetExchangeBankAccounts LoadConfig error", err)
+ }
+ _, err = cfg.GetClientBankAccounts("Kraken", "USD")
+ if err != nil {
+ t.Error("GetExchangeBankAccounts error", err)
+ }
+ _, err = cfg.GetClientBankAccounts("noob exchange", "USD")
+ if err == nil {
+ t.Fatal("error cannot be nil")
+ }
+}
+
func TestGetExchangeBankAccounts(t *testing.T) {
cfg := GetConfig()
err := cfg.LoadConfig(TestFile, true)
@@ -48,6 +66,17 @@ func TestGetExchangeBankAccounts(t *testing.T) {
}
}
+func TestCheckBankAccountConfig(t *testing.T) {
+ cfg := GetConfig()
+ err := cfg.LoadConfig(TestFile, true)
+ if err != nil {
+ t.Error("GetExchangeBankAccounts LoadConfig error", err)
+ }
+
+ cfg.BankAccounts[0].Enabled = true
+ cfg.CheckBankAccountConfig()
+}
+
func TestUpdateExchangeBankAccounts(t *testing.T) {
cfg := GetConfig()
err := cfg.LoadConfig(TestFile, true)
@@ -84,7 +113,7 @@ func TestUpdateClientBankAccounts(t *testing.T) {
if err != nil {
t.Error("UpdateClientBankAccounts LoadConfig error", err)
}
- b := banking.Account{Enabled: false, BankName: "test", AccountNumber: "0234"}
+ b := banking.Account{Enabled: false, BankName: testString, AccountNumber: "0234"}
err = cfg.UpdateClientBankAccounts(&b)
if err != nil {
t.Error("UpdateClientBankAccounts error", err)
@@ -185,7 +214,7 @@ func TestPurgeExchangeCredentials(t *testing.T) {
var c Config
c.Exchanges = []ExchangeConfig{
{
- Name: "test",
+ Name: testString,
API: APIConfig{
AuthenticatedSupport: true,
AuthenticatedWebsocketSupport: true,
@@ -219,7 +248,7 @@ func TestPurgeExchangeCredentials(t *testing.T) {
c.PurgeExchangeAPICredentials()
- exchCfg, err := c.GetExchangeConfig("test")
+ exchCfg, err := c.GetExchangeConfig(testString)
if err != nil {
t.Error(err)
}
@@ -257,8 +286,8 @@ func TestUpdateCommunicationsConfig(t *testing.T) {
if err != nil {
t.Error("UpdateCommunicationsConfig LoadConfig error", err)
}
- cfg.UpdateCommunicationsConfig(&CommunicationsConfig{SlackConfig: SlackConfig{Name: "TEST"}})
- if cfg.Communications.SlackConfig.Name != "TEST" {
+ cfg.UpdateCommunicationsConfig(&CommunicationsConfig{SlackConfig: SlackConfig{Name: testString}})
+ if cfg.Communications.SlackConfig.Name != testString {
t.Error("UpdateCommunicationsConfig LoadConfig error")
}
}
@@ -308,7 +337,7 @@ func TestCheckCommunicationsConfig(t *testing.T) {
cfg.SMS = &SMSGlobalConfig{}
cfg.Communications.SMSGlobalConfig.Name = ""
cfg.CheckCommunicationsConfig()
- if cfg.Communications.SMSGlobalConfig.Password != "test" {
+ if cfg.Communications.SMSGlobalConfig.Password != testString {
t.Error("CheckCommunicationsConfig error:", err)
}
@@ -389,9 +418,9 @@ func TestGetExchangeAssetTypes(t *testing.T) {
ExchangeConfig{
Name: testFakeExchangeName,
CurrencyPairs: ¤cy.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- asset.Futures,
+ Pairs: map[asset.Item]*currency.PairStore{
+ asset.Spot: new(currency.PairStore),
+ asset.Futures: new(currency.PairStore),
},
},
},
@@ -403,7 +432,7 @@ func TestGetExchangeAssetTypes(t *testing.T) {
t.Error(err)
}
- if assets.JoinToString(",") != "spot,futures" {
+ if !assets.Contains(asset.Spot) || !assets.Contains(asset.Futures) {
t.Error("unexpected results")
}
@@ -417,7 +446,7 @@ func TestGetExchangeAssetTypes(t *testing.T) {
func TestSupportsExchangeAssetType(t *testing.T) {
t.Parallel()
var c Config
- _, err := c.SupportsExchangeAssetType("void", asset.Spot)
+ err := c.SupportsExchangeAssetType("void", asset.Spot)
if err == nil {
t.Error("Expected error for non-existent exchange")
}
@@ -426,73 +455,30 @@ func TestSupportsExchangeAssetType(t *testing.T) {
ExchangeConfig{
Name: testFakeExchangeName,
CurrencyPairs: ¤cy.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- asset.Futures,
+ Pairs: map[asset.Item]*currency.PairStore{
+ asset.Spot: new(currency.PairStore),
},
},
},
)
- supports, err := c.SupportsExchangeAssetType(testFakeExchangeName, asset.Spot)
+ err = c.SupportsExchangeAssetType(testFakeExchangeName, asset.Spot)
if err != nil {
t.Error(err)
}
- if !supports {
- t.Error("exchange should support spot asset item")
- }
-
- _, err = c.SupportsExchangeAssetType(testFakeExchangeName, "asdf")
+ err = c.SupportsExchangeAssetType(testFakeExchangeName, "asdf")
if err == nil {
t.Error("Expected error from invalid asset item")
}
c.Exchanges[0].CurrencyPairs = nil
- _, err = c.SupportsExchangeAssetType(testFakeExchangeName, asset.Spot)
+ err = c.SupportsExchangeAssetType(testFakeExchangeName, asset.Spot)
if err == nil {
t.Error("Expected error from nil pair manager")
}
}
-func TestCheckExchangeAssetsConsistency(t *testing.T) {
- t.Parallel()
- var c Config
- // Test for non-existent exchange
- c.CheckExchangeAssetsConsistency("void")
-
- c.Exchanges = append(c.Exchanges,
- ExchangeConfig{
- Name: testFakeExchangeName,
- },
- )
-
- // Tests for nil currency pairs store but valid exchange name
- c.CheckExchangeAssetsConsistency(testFakeExchangeName)
-
- // Simulate testing a diff between stored asset types (config loading)
- // and pair store
- c.Exchanges[0].CurrencyPairs = ¤cy.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- asset.Futures,
- asset.Index,
- },
- }
- c.Exchanges[0].CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
- c.Exchanges[0].CurrencyPairs.Pairs[asset.PerpetualContract] = ¤cy.PairStore{}
- c.CheckExchangeAssetsConsistency(testFakeExchangeName)
-
- supports, err := c.SupportsExchangeAssetType(testFakeExchangeName, asset.PerpetualContract)
- if err != nil {
- t.Error(err)
- }
-
- if supports {
- t.Error("perpetual contract should have been removed from the pair manager")
- }
-}
-
func TestSetPairs(t *testing.T) {
t.Parallel()
@@ -524,9 +510,8 @@ func TestSetPairs(t *testing.T) {
}
c.Exchanges[0].CurrencyPairs = ¤cy.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- asset.Futures,
+ Pairs: map[asset.Item]*currency.PairStore{
+ asset.Spot: new(currency.PairStore),
},
}
@@ -562,10 +547,6 @@ func TestGetCurrencyPairConfig(t *testing.T) {
}
pm := ¤cy.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- asset.Futures,
- },
Pairs: map[asset.Item]*currency.PairStore{
asset.Spot: {
RequestFormat: ¤cy.PairFormat{
@@ -610,11 +591,6 @@ func TestCheckPairConfigFormats(t *testing.T) {
c.Exchanges = append(c.Exchanges,
ExchangeConfig{
Name: testFakeExchangeName,
- CurrencyPairs: ¤cy.PairsManager{
- AssetTypes: asset.Items{
- asset.Item("wrong"),
- },
- },
},
)
@@ -622,23 +598,40 @@ func TestCheckPairConfigFormats(t *testing.T) {
t.Error("nil pair store should return an error")
}
- c.Exchanges[0].CurrencyPairs.AssetTypes = asset.Items{asset.Spot}
- c.Exchanges[0].CurrencyPairs.Pairs = map[asset.Item]*currency.PairStore{
- asset.Spot: {
- RequestFormat: ¤cy.PairFormat{},
- ConfigFormat: ¤cy.PairFormat{},
+ c.Exchanges[0].CurrencyPairs = ¤cy.PairsManager{
+ Pairs: map[asset.Item]*currency.PairStore{
+ asset.Spot: {},
+ asset.Futures: {},
},
- asset.Futures: {
- RequestFormat: ¤cy.PairFormat{},
- ConfigFormat: ¤cy.PairFormat{},
+ }
+ if err := c.CheckPairConfigFormats(testFakeExchangeName); err == nil {
+ t.Error("error cannot be nil")
+ }
+
+ c.Exchanges[0].CurrencyPairs = ¤cy.PairsManager{
+ Pairs: map[asset.Item]*currency.PairStore{
+ asset.Spot: {
+ RequestFormat: ¤cy.PairFormat{},
+ ConfigFormat: ¤cy.PairFormat{},
+ },
+ asset.Futures: {
+ RequestFormat: ¤cy.PairFormat{},
+ ConfigFormat: ¤cy.PairFormat{},
+ },
},
}
if err := c.CheckPairConfigFormats(testFakeExchangeName); err != nil {
t.Error("nil pairs should be okay to continue")
}
-
+ avail, err := currency.NewPairDelimiter(testPair, "-")
+ if err != nil {
+ t.Fatal(err)
+ }
+ enabled, err := currency.NewPairDelimiter("BTC~USD", "~")
+ if err != nil {
+ t.Fatal(err)
+ }
// Test having a pair index and delimiter set at the same time throws an error
- c.Exchanges[0].CurrencyPairs.AssetTypes = asset.Items{asset.Spot}
c.Exchanges[0].CurrencyPairs.Pairs = map[asset.Item]*currency.PairStore{
asset.Spot: {
RequestFormat: ¤cy.PairFormat{
@@ -651,10 +644,10 @@ func TestCheckPairConfigFormats(t *testing.T) {
Index: "USD",
},
Available: currency.Pairs{
- currency.NewPairDelimiter(testPair, "-"),
+ avail,
},
Enabled: currency.Pairs{
- currency.NewPairDelimiter("BTC~USD", "~"),
+ enabled,
},
},
}
@@ -698,11 +691,6 @@ func TestCheckPairConsistency(t *testing.T) {
c.Exchanges = append(c.Exchanges,
ExchangeConfig{
Name: testFakeExchangeName,
- CurrencyPairs: ¤cy.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- },
- },
},
)
@@ -711,33 +699,71 @@ func TestCheckPairConsistency(t *testing.T) {
t.Error("nil pair store should return an error")
}
- c.Exchanges[0].CurrencyPairs.Pairs = map[asset.Item]*currency.PairStore{
- asset.Spot: {
- RequestFormat: ¤cy.PairFormat{
- Uppercase: false,
- Delimiter: "_",
- },
- ConfigFormat: ¤cy.PairFormat{
- Uppercase: true,
- Delimiter: "_",
- },
- Enabled: currency.Pairs{
- currency.NewPairDelimiter("BTC_USD", "_"),
+ enabled, err := currency.NewPairDelimiter("BTC_USD", "_")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ c.Exchanges[0].CurrencyPairs = ¤cy.PairsManager{
+ Pairs: map[asset.Item]*currency.PairStore{
+ asset.Spot: {
+ RequestFormat: ¤cy.PairFormat{
+ Uppercase: false,
+ Delimiter: "_",
+ },
+ ConfigFormat: ¤cy.PairFormat{
+ Uppercase: true,
+ Delimiter: "_",
+ },
+ Enabled: currency.Pairs{
+ enabled,
+ },
},
},
}
// Test for nil avail pairs
- if err := c.CheckPairConsistency(testFakeExchangeName); err != nil {
- t.Error("nil available pairs should continue")
+ err = c.CheckPairConsistency(testFakeExchangeName)
+ if err != nil {
+ t.Error(err)
+ }
+
+ p1, err := currency.NewPairDelimiter("LTC_USD", "_")
+ if err != nil {
+ t.Fatal(err)
}
// Test that enabled pair is not found in the available pairs
c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].Available = currency.Pairs{
- currency.NewPairDelimiter("LTC_USD", "_"),
+ p1,
}
+
+ // LTC_USD is only found in the available pairs list and should therefor
+ // be added to the enabled pairs list due to the atLestOneEnabled code
+ err = c.CheckPairConsistency(testFakeExchangeName)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ for _, item := range c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].Enabled {
+ if !item.Equal(p1) {
+ t.Fatal("LTC_USD should be contained in the enabled pairs list")
+ }
+ }
+
+ p2, err := currency.NewPairDelimiter("BTC_USD", "_")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // Add the BTC_USD pair and see result
+ c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].Available = currency.Pairs{
+ p1,
+ p2,
+ }
+
if err := c.CheckPairConsistency(testFakeExchangeName); err != nil {
- t.Error("unexpected result")
+ t.Fatal(err)
}
// Test that an empty enabled pair is populated with an available pair
@@ -746,10 +772,14 @@ func TestCheckPairConsistency(t *testing.T) {
t.Error("unexpected result")
}
+ if len(c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].Enabled) != 1 {
+ t.Fatal("should be populated with atleast one currency pair")
+ }
+
// Test that an invalid enabled pair is removed from the list
c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].Enabled = currency.Pairs{
- currency.NewPairDelimiter("LTC_USD", "_"),
- currency.NewPairDelimiter("BTC_USD", "_"),
+ p1,
+ p2,
}
if err := c.CheckPairConsistency(testFakeExchangeName); err != nil {
t.Error("unexpected result")
@@ -760,6 +790,48 @@ func TestCheckPairConsistency(t *testing.T) {
if err := c.CheckPairConsistency(testFakeExchangeName); err != nil {
t.Error("unexpected result")
}
+
+ c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].AssetEnabled = convert.BoolPtr(true)
+ c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].Enabled = currency.Pairs{}
+
+ // Test no conflict and atleast one on enabled asset type
+ if err := c.CheckPairConsistency(testFakeExchangeName); err != nil {
+ t.Error("unexpected result")
+ }
+
+ c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].AssetEnabled = convert.BoolPtr(true)
+ c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].Enabled = currency.Pairs{currency.NewPair(currency.DASH, currency.USD)}
+
+ // Test with conflict and atleast one on enabled asset type
+ if err := c.CheckPairConsistency(testFakeExchangeName); err != nil {
+ t.Error("unexpected result")
+ }
+
+ c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].AssetEnabled = convert.BoolPtr(false)
+ c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].Enabled = currency.Pairs{}
+
+ // Test no conflict and atleast one on disabled asset type
+ if err := c.CheckPairConsistency(testFakeExchangeName); err != nil {
+ t.Error("unexpected result")
+ }
+
+ c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].Enabled = currency.Pairs{
+ currency.NewPair(currency.DASH, currency.USD),
+ p1,
+ p2,
+ }
+
+ // Test with conflict and atleast one on disabled asset type
+ if err := c.CheckPairConsistency(testFakeExchangeName); err != nil {
+ t.Error("unexpected result")
+ }
+
+ c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].AssetEnabled = nil
+
+ // assetType enabled failure check
+ if err := c.CheckPairConsistency(testFakeExchangeName); err != nil {
+ t.Error("unexpected result")
+ }
}
func TestSupportsPair(t *testing.T) {
@@ -772,17 +844,15 @@ func TestSupportsPair(t *testing.T) {
}
assetType := asset.Spot
- _, err = cfg.SupportsPair("asdf",
- currency.NewPair(currency.BTC, currency.USD), assetType)
- if err == nil {
+ if cfg.SupportsPair("asdf",
+ currency.NewPair(currency.BTC, currency.USD), assetType) {
t.Error(
"TestSupportsPair. Expected error from Non-existent exchange",
)
}
- _, err = cfg.SupportsPair("Bitfinex",
- currency.NewPair(currency.BTC, currency.USD), assetType)
- if err != nil {
+ if !cfg.SupportsPair("Bitfinex",
+ currency.NewPair(currency.BTC, currency.USD), assetType) {
t.Errorf(
"TestSupportsPair. Incorrect values. Err: %s", err,
)
@@ -809,7 +879,26 @@ func TestGetPairFormat(t *testing.T) {
}
c.Exchanges[0].CurrencyPairs = ¤cy.PairsManager{
- AssetTypes: asset.Items{asset.Spot},
+ UseGlobalFormat: false,
+ RequestFormat: ¤cy.PairFormat{
+ Uppercase: false,
+ Delimiter: "_",
+ },
+ ConfigFormat: ¤cy.PairFormat{
+ Uppercase: true,
+ Delimiter: "_",
+ },
+ Pairs: map[asset.Item]*currency.PairStore{
+ asset.Spot: nil,
+ },
+ }
+
+ _, err = c.GetPairFormat(testFakeExchangeName, asset.Spot)
+ if err == nil {
+ t.Error("Expected error from nil pair manager")
+ }
+
+ c.Exchanges[0].CurrencyPairs = ¤cy.PairsManager{
UseGlobalFormat: true,
RequestFormat: ¤cy.PairFormat{
Uppercase: false,
@@ -819,6 +908,9 @@ func TestGetPairFormat(t *testing.T) {
Uppercase: true,
Delimiter: "_",
},
+ Pairs: map[asset.Item]*currency.PairStore{
+ asset.Spot: new(currency.PairStore),
+ },
}
_, err = c.GetPairFormat(testFakeExchangeName, asset.Item("invalid"))
if err == nil {
@@ -876,12 +968,8 @@ func TestGetAvailablePairs(t *testing.T) {
c.Exchanges = append(c.Exchanges,
ExchangeConfig{
- Name: testFakeExchangeName,
- CurrencyPairs: ¤cy.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- },
- },
+ Name: testFakeExchangeName,
+ CurrencyPairs: ¤cy.PairsManager{},
},
)
@@ -923,12 +1011,8 @@ func TestGetEnabledPairs(t *testing.T) {
c.Exchanges = append(c.Exchanges,
ExchangeConfig{
- Name: testFakeExchangeName,
- CurrencyPairs: ¤cy.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- },
- },
+ Name: testFakeExchangeName,
+ CurrencyPairs: ¤cy.PairsManager{},
},
)
@@ -953,6 +1037,11 @@ func TestGetEnabledPairs(t *testing.T) {
c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].Enabled = currency.Pairs{
currency.NewPair(currency.BTC, currency.USD),
}
+
+ c.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].Available = currency.Pairs{
+ currency.NewPair(currency.BTC, currency.USD),
+ }
+
_, err = c.GetEnabledPairs(testFakeExchangeName, asset.Spot)
if err != nil {
t.Error(err)
@@ -1183,16 +1272,15 @@ func TestCheckExchangeConfigValues(t *testing.T) {
// Test API settings migration
sptr := func(s string) *string { return &s }
- bptr := func(b bool) *bool { return &b }
int64ptr := func(i int64) *int64 { return &i }
cfg.Exchanges[0].APIKey = sptr("awesomeKey")
cfg.Exchanges[0].APISecret = sptr("meowSecret")
cfg.Exchanges[0].ClientID = sptr("clientIDerino")
cfg.Exchanges[0].APIAuthPEMKey = sptr("-----BEGIN EC PRIVATE KEY-----\nASDF\n-----END EC PRIVATE KEY-----\n")
- cfg.Exchanges[0].APIAuthPEMKeySupport = bptr(true)
- cfg.Exchanges[0].AuthenticatedAPISupport = bptr(true)
- cfg.Exchanges[0].AuthenticatedWebsocketAPISupport = bptr(true)
+ cfg.Exchanges[0].APIAuthPEMKeySupport = convert.BoolPtr(true)
+ cfg.Exchanges[0].AuthenticatedAPISupport = convert.BoolPtr(true)
+ cfg.Exchanges[0].AuthenticatedWebsocketAPISupport = convert.BoolPtr(true)
cfg.Exchanges[0].WebsocketURL = sptr("wss://1337")
cfg.Exchanges[0].APIURL = sptr(APIURLNonDefaultMessage)
cfg.Exchanges[0].APIURLSecondary = sptr(APIURLNonDefaultMessage)
@@ -1230,8 +1318,8 @@ func TestCheckExchangeConfigValues(t *testing.T) {
// Test feature and endpoint migrations migrations
cfg.Exchanges[0].Features = nil
- cfg.Exchanges[0].SupportsAutoPairUpdates = bptr(true)
- cfg.Exchanges[0].Websocket = bptr(true)
+ cfg.Exchanges[0].SupportsAutoPairUpdates = convert.BoolPtr(true)
+ cfg.Exchanges[0].Websocket = convert.BoolPtr(true)
cfg.Exchanges[0].API.Endpoints.URL = ""
cfg.Exchanges[0].API.Endpoints.URLSecondary = ""
cfg.Exchanges[0].API.Endpoints.WebsocketURL = ""
@@ -1253,11 +1341,16 @@ func TestCheckExchangeConfigValues(t *testing.T) {
t.Error("unexpected values")
}
+ p1, err := currency.NewPairDelimiter(testPair, "-")
+ if err != nil {
+ t.Fatal(err)
+ }
+
// Test currency pair migration
setupPairs := func(emptyAssets bool) {
cfg.Exchanges[0].CurrencyPairs = nil
p := currency.Pairs{
- currency.NewPairDelimiter(testPair, "-"),
+ p1,
}
cfg.Exchanges[0].PairsLastUpdated = int64ptr(1234567)
@@ -1305,17 +1398,25 @@ func TestCheckExchangeConfigValues(t *testing.T) {
t.Error("unexpected request format values")
}
- if cfg.Exchanges[0].CurrencyPairs.AssetTypes.JoinToString(",") != "spot" ||
+ if !cfg.Exchanges[0].CurrencyPairs.GetAssetTypes().Contains(asset.Spot) ||
!cfg.Exchanges[0].CurrencyPairs.UseGlobalFormat {
t.Error("unexpected results")
}
- pairs := cfg.Exchanges[0].CurrencyPairs.GetPairs(asset.Spot, true)
+ pairs, err := cfg.Exchanges[0].CurrencyPairs.GetPairs(asset.Spot, true)
+ if err != nil {
+ t.Fatal(err)
+ }
+
if len(pairs) == 0 || pairs.Join() != testPair {
t.Error("pairs not set properly")
}
- pairs = cfg.Exchanges[0].CurrencyPairs.GetPairs(asset.Spot, false)
+ pairs, err = cfg.Exchanges[0].CurrencyPairs.GetPairs(asset.Spot, false)
+ if err != nil {
+ t.Fatal(err)
+ }
+
if len(pairs) == 0 || pairs.Join() != testPair {
t.Error("pairs not set properly")
}
@@ -1334,24 +1435,10 @@ func TestCheckExchangeConfigValues(t *testing.T) {
cfg.Exchanges[0].Features.Supports.RESTCapabilities.AutoPairUpdates = false
cfg.Exchanges[0].Features.Supports.WebsocketCapabilities.AutoPairUpdates = false
cfg.Exchanges[0].CurrencyPairs.LastUpdated = 0
- cfg.CheckExchangeConfigValues()
-
- // Test exchange pair consistency error
- cfg.Exchanges[0].CurrencyPairs.UseGlobalFormat = false
- backup := cfg.Exchanges[0].CurrencyPairs.Pairs[asset.Spot]
- cfg.Exchanges[0].CurrencyPairs.Pairs[asset.Spot] = nil
err = cfg.CheckExchangeConfigValues()
if err != nil {
t.Error(err)
}
- if cfg.Exchanges[0].Enabled {
- t.Error("exchange should have been disabled")
- }
-
- // Restore to previous state
- cfg.Exchanges[0].Enabled = true
- cfg.Exchanges[0].CurrencyPairs.UseGlobalFormat = true
- cfg.Exchanges[0].CurrencyPairs.Pairs[asset.Spot] = backup
// Test websocket and HTTP timeout values
cfg.Exchanges[0].WebsocketResponseMaxLimit = 0
@@ -1419,6 +1506,10 @@ func TestCheckExchangeConfigValues(t *testing.T) {
!cfg.Exchanges[0].API.AuthenticatedWebsocketSupport {
t.Error("Expected AuthenticatedAPISupport and AuthenticatedWebsocketAPISupport to be false from invalid API keys")
}
+
+ // Make a sneaky copy for bank account testing
+ cpy := append(cfg.Exchanges[:0:0], cfg.Exchanges...)
+
// Test empty exchange name for an enabled exchange
cfg.Exchanges[0].Enabled = true
cfg.Exchanges[0].Name = ""
@@ -1436,6 +1527,82 @@ func TestCheckExchangeConfigValues(t *testing.T) {
if err == nil {
t.Error("Expected error from no enabled exchanges")
}
+
+ cfg.Exchanges = cpy
+ // Check bank account validation for exchange
+ cfg.Exchanges[0].BankAccounts = []banking.Account{
+ {
+ Enabled: true,
+ },
+ }
+
+ err = cfg.CheckExchangeConfigValues()
+ if err != nil {
+ t.Error(err)
+ }
+
+ if cfg.Exchanges[0].BankAccounts[0].Enabled {
+ t.Fatal("bank aaccount details not provided this should disable")
+ }
+
+ // Test international bank
+ cfg.Exchanges[0].BankAccounts[0].Enabled = true
+ cfg.Exchanges[0].BankAccounts[0].BankName = testString
+ cfg.Exchanges[0].BankAccounts[0].BankAddress = testString
+ cfg.Exchanges[0].BankAccounts[0].BankPostalCode = testString
+ cfg.Exchanges[0].BankAccounts[0].BankPostalCity = testString
+ cfg.Exchanges[0].BankAccounts[0].BankCountry = testString
+ cfg.Exchanges[0].BankAccounts[0].AccountName = testString
+ cfg.Exchanges[0].BankAccounts[0].SupportedCurrencies = "monopoly moneys"
+ cfg.Exchanges[0].BankAccounts[0].IBAN = "some iban"
+ cfg.Exchanges[0].BankAccounts[0].SWIFTCode = "some swifty"
+
+ err = cfg.CheckExchangeConfigValues()
+ if err != nil {
+ t.Error(err)
+ }
+
+ if !cfg.Exchanges[0].BankAccounts[0].Enabled {
+ t.Fatal("bank aaccount details provided this should not disable")
+ }
+
+ // Test aussie bank
+ cfg.Exchanges[0].BankAccounts[0].Enabled = true
+ cfg.Exchanges[0].BankAccounts[0].BankName = testString
+ cfg.Exchanges[0].BankAccounts[0].BankAddress = testString
+ cfg.Exchanges[0].BankAccounts[0].BankPostalCode = testString
+ cfg.Exchanges[0].BankAccounts[0].BankPostalCity = testString
+ cfg.Exchanges[0].BankAccounts[0].BankCountry = testString
+ cfg.Exchanges[0].BankAccounts[0].AccountName = testString
+ cfg.Exchanges[0].BankAccounts[0].SupportedCurrencies = "AUD"
+ cfg.Exchanges[0].BankAccounts[0].BSBNumber = "some BSB nonsense"
+ cfg.Exchanges[0].BankAccounts[0].IBAN = ""
+ cfg.Exchanges[0].BankAccounts[0].SWIFTCode = ""
+
+ err = cfg.CheckExchangeConfigValues()
+ if err != nil {
+ t.Error(err)
+ }
+
+ if !cfg.Exchanges[0].BankAccounts[0].Enabled {
+ t.Fatal("bank account details provided this should not disable")
+ }
+
+ cfg.Exchanges = nil
+ cfg.Exchanges = append(cfg.Exchanges, cpy[0])
+
+ cfg.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].Enabled = nil
+ cfg.Exchanges[0].CurrencyPairs.Pairs[asset.Spot].AssetEnabled = convert.BoolPtr(false)
+ err = cfg.CheckExchangeConfigValues()
+ if err != nil {
+ t.Error(err)
+ }
+
+ cfg.Exchanges[0].CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
+ err = cfg.CheckExchangeConfigValues()
+ if err == nil {
+ t.Error("err cannot be nil")
+ }
}
func TestRetrieveConfigCurrencyPairs(t *testing.T) {
diff --git a/config_example.json b/config_example.json
index 1b5216a2..1bd16444 100644
--- a/config_example.json
+++ b/config_example.json
@@ -449,7 +449,7 @@
"websocketCapabilities": {}
},
"enabled": {
- "autoPairUpdates": false,
+ "autoPairUpdates": true,
"websocketAPI": false
}
},
diff --git a/currency/code.go b/currency/code.go
index 634f2100..18aa61f8 100644
--- a/currency/code.go
+++ b/currency/code.go
@@ -6,8 +6,6 @@ import (
"fmt"
"strings"
"unicode"
-
- "github.com/thrasher-corp/gocryptotrader/common"
)
func (r Role) String() string {
@@ -68,24 +66,24 @@ func (b *BaseCodes) HasData() bool {
// GetFullCurrencyData returns a type that is read to dump to file
func (b *BaseCodes) GetFullCurrencyData() (File, error) {
var file File
- for _, i := range b.Items {
- switch i.Role {
+ for i := range b.Items {
+ switch b.Items[i].Role {
case Unset:
- file.UnsetCurrency = append(file.UnsetCurrency, *i)
+ file.UnsetCurrency = append(file.UnsetCurrency, *b.Items[i])
case Fiat:
- file.FiatCurrency = append(file.FiatCurrency, *i)
+ file.FiatCurrency = append(file.FiatCurrency, *b.Items[i])
case Cryptocurrency:
- file.Cryptocurrency = append(file.Cryptocurrency, *i)
+ file.Cryptocurrency = append(file.Cryptocurrency, *b.Items[i])
case Token:
- file.Token = append(file.Token, *i)
+ file.Token = append(file.Token, *b.Items[i])
case Contract:
- file.Contracts = append(file.Contracts, *i)
+ file.Contracts = append(file.Contracts, *b.Items[i])
default:
return file, errors.New("role undefined")
}
}
- file.LastMainUpdate = b.LastMainUpdate
+ file.LastMainUpdate = b.LastMainUpdate.Unix()
return file, nil
}
@@ -103,50 +101,11 @@ func (b *BaseCodes) GetCurrencies() Currencies {
return currencies
}
-// UpdateCryptocurrency updates or registers a cryptocurrency
-func (b *BaseCodes) UpdateCryptocurrency(fullName, symbol string, id int) error {
- b.mtx.Lock()
- defer b.mtx.Unlock()
- for i := range b.Items {
- if b.Items[i].Symbol != symbol {
- continue
- }
- if b.Items[i].Role != Unset {
- if b.Items[i].Role != Cryptocurrency {
- if b.Items[i].FullName != "" {
- if b.Items[i].FullName != fullName {
- // multiple symbols found, break this and add the
- // full context - this most likely won't occur for
- // fiat but could occur for contracts.
- break
- }
- }
- return fmt.Errorf("role already defined in cryptocurrency %s as [%s]",
- b.Items[i].Symbol,
- b.Items[i].Role)
- }
- b.Items[i].FullName = fullName
- b.Items[i].ID = id
- return nil
- }
-
- b.Items[i].Role = Cryptocurrency
- b.Items[i].FullName = fullName
- b.Items[i].ID = id
- return nil
+// UpdateCurrency updates or registers a currency/contract
+func (b *BaseCodes) UpdateCurrency(fullName, symbol, blockchain string, id int, r Role) error {
+ if r == Unset {
+ return fmt.Errorf("role cannot be unset in update currency for %s", symbol)
}
-
- b.Items = append(b.Items, &Item{
- FullName: fullName,
- Symbol: symbol,
- ID: id,
- Role: Cryptocurrency,
- })
- return nil
-}
-
-// UpdateFiatCurrency updates or registers a fiat currency
-func (b *BaseCodes) UpdateFiatCurrency(fullName, symbol string, id int) error {
b.mtx.Lock()
defer b.mtx.Unlock()
for i := range b.Items {
@@ -154,115 +113,31 @@ func (b *BaseCodes) UpdateFiatCurrency(fullName, symbol string, id int) error {
continue
}
- if b.Items[i].Role != Unset {
- if b.Items[i].Role != Fiat {
- return fmt.Errorf("role already defined in fiat currency %s as [%s]",
- b.Items[i].Symbol,
- b.Items[i].Role)
- }
+ if b.Items[i].Role == Unset {
b.Items[i].FullName = fullName
+ b.Items[i].Role = r
+ b.Items[i].AssocChain = blockchain
b.Items[i].ID = id
return nil
}
- b.Items[i].Role = Fiat
+ if b.Items[i].Role != r {
+ // Captures same name currencies and duplicates to different roles
+ break
+ }
+
b.Items[i].FullName = fullName
+ b.Items[i].AssocChain = blockchain
b.Items[i].ID = id
return nil
}
b.Items = append(b.Items, &Item{
- FullName: fullName,
- Symbol: symbol,
- ID: id,
- Role: Fiat,
- })
- return nil
-}
-
-// UpdateToken updates or registers a token
-func (b *BaseCodes) UpdateToken(fullName, symbol, assocBlockchain string, id int) error {
- b.mtx.Lock()
- defer b.mtx.Unlock()
- for i := range b.Items {
- if b.Items[i].Symbol != symbol {
- continue
- }
-
- if b.Items[i].Role != Unset {
- if b.Items[i].Role != Token {
- if b.Items[i].FullName != "" {
- if b.Items[i].FullName != fullName {
- // multiple symbols found, break this and add the
- // full context - this most likely won't occur for
- // fiat but could occur for contracts.
- break
- }
- }
- return fmt.Errorf("role already defined in token %s as [%s]",
- b.Items[i].Symbol,
- b.Items[i].Role)
- }
- b.Items[i].FullName = fullName
- b.Items[i].ID = id
- b.Items[i].AssocChain = assocBlockchain
- return nil
- }
-
- b.Items[i].Role = Token
- b.Items[i].FullName = fullName
- b.Items[i].ID = id
- b.Items[i].AssocChain = assocBlockchain
- return nil
- }
-
- b.Items = append(b.Items, &Item{
- FullName: fullName,
Symbol: symbol,
+ FullName: fullName,
+ Role: r,
+ AssocChain: blockchain,
ID: id,
- Role: Token,
- AssocChain: assocBlockchain,
- })
- return nil
-}
-
-// UpdateContract updates or registers a contract
-func (b *BaseCodes) UpdateContract(fullName, symbol, assocExchange string) error {
- b.mtx.Lock()
- defer b.mtx.Unlock()
- for i := range b.Items {
- if b.Items[i].Symbol != symbol {
- continue
- }
-
- if b.Items[i].Role != Unset {
- if b.Items[i].Role != Contract {
- return fmt.Errorf("role already defined in contract %s as [%s]",
- b.Items[i].Symbol,
- b.Items[i].Role)
- }
- b.Items[i].FullName = fullName
- if !common.StringDataContains(b.Items[i].AssocExchange, assocExchange) {
- b.Items[i].AssocExchange = append(b.Items[i].AssocExchange,
- assocExchange)
- }
- return nil
- }
-
- b.Items[i].Role = Contract
- b.Items[i].FullName = fullName
- if !common.StringDataContains(b.Items[i].AssocExchange, assocExchange) {
- b.Items[i].AssocExchange = append(b.Items[i].AssocExchange,
- assocExchange)
- }
- return nil
- }
-
- b.Items = append(b.Items, &Item{
- FullName: fullName,
- Symbol: symbol,
- Role: Contract,
- AssocExchange: []string{assocExchange},
})
return nil
}
@@ -293,42 +168,38 @@ func (b *BaseCodes) Register(c string) Code {
}
}
- newItem := Item{Symbol: NewUpperCode}
- newCode := Code{
- Item: &newItem,
+ newItem := &Item{Symbol: NewUpperCode}
+ b.Items = append(b.Items, newItem)
+
+ return Code{
+ Item: newItem,
UpperCase: format,
}
-
- b.Items = append(b.Items, newCode.Item)
- return newCode
}
// RegisterFiat registers a fiat currency from a string and returns a currency
// code
-func (b *BaseCodes) RegisterFiat(c string) (Code, error) {
+func (b *BaseCodes) RegisterFiat(c string) Code {
c = strings.ToUpper(c)
b.mtx.Lock()
defer b.mtx.Unlock()
for i := range b.Items {
if b.Items[i].Symbol == c {
- if b.Items[i].Role != Unset {
- if b.Items[i].Role != Fiat {
- return Code{}, fmt.Errorf("register fiat error role already defined in fiat %s as [%s]",
- b.Items[i].Symbol,
- b.Items[i].Role)
- }
- return Code{Item: b.Items[i], UpperCase: true}, nil
+ if b.Items[i].Role == Unset {
+ b.Items[i].Role = Fiat
}
- b.Items[i].Role = Fiat
- return Code{Item: b.Items[i], UpperCase: true}, nil
+
+ if b.Items[i].Role != Fiat {
+ continue
+ }
+ return Code{Item: b.Items[i], UpperCase: true}
}
}
item := &Item{Symbol: c, Role: Fiat}
b.Items = append(b.Items, item)
-
- return Code{Item: item, UpperCase: true}, nil
+ return Code{Item: item, UpperCase: true}
}
// LoadItem sets item data
@@ -336,41 +207,18 @@ func (b *BaseCodes) LoadItem(item *Item) error {
b.mtx.Lock()
defer b.mtx.Unlock()
for i := range b.Items {
- if b.Items[i].Symbol == item.Symbol {
- if b.Items[i].Role == Unset {
- b.Items[i].AssocChain = item.AssocChain
- b.Items[i].AssocExchange = item.AssocExchange
- b.Items[i].ID = item.ID
- b.Items[i].Role = item.Role
- b.Items[i].FullName = item.FullName
- return nil
- }
-
- if b.Items[i].FullName != "" {
- if b.Items[i].FullName == item.FullName {
- b.Items[i].AssocChain = item.AssocChain
- b.Items[i].AssocExchange = item.AssocExchange
- b.Items[i].ID = item.ID
- b.Items[i].Role = item.Role
- return nil
- }
- break
- }
-
- if b.Items[i].ID == item.ID {
- b.Items[i].AssocChain = item.AssocChain
- b.Items[i].AssocExchange = item.AssocExchange
- b.Items[i].FullName = item.FullName
- b.Items[i].ID = item.ID
- b.Items[i].Role = item.Role
- return nil
- }
-
- return fmt.Errorf("currency %s not found in currencycode list",
- item.Symbol)
+ if b.Items[i].Symbol != item.Symbol ||
+ (b.Items[i].Role != Unset &&
+ item.Role != Unset &&
+ b.Items[i].Role != item.Role) {
+ continue
}
+ b.Items[i].AssocChain = item.AssocChain
+ b.Items[i].ID = item.ID
+ b.Items[i].Role = item.Role
+ b.Items[i].FullName = item.FullName
+ return nil
}
-
b.Items = append(b.Items, item)
return nil
}
diff --git a/currency/code_test.go b/currency/code_test.go
index 1568a7e4..7ebb0aca 100644
--- a/currency/code_test.go
+++ b/currency/code_test.go
@@ -176,41 +176,51 @@ func TestBaseCode(t *testing.T) {
false)
}
- err := main.UpdateContract("Bitcoin Perpetual", "XBTUSD", "Bitmex")
+ main.Register("XBTUSD")
+
+ err := main.UpdateCurrency("Bitcoin Perpetual",
+ "XBTUSD",
+ "",
+ 0,
+ Contract)
if err != nil {
- t.Error("BaseCode UpdateContract error", err)
+ t.Fatal(err)
}
- err = main.UpdateCryptocurrency("Bitcoin", "BTC", 1337)
+ main.Register("BTC")
+ err = main.UpdateCurrency("Bitcoin", "BTC", "", 1337, Cryptocurrency)
if err != nil {
- t.Error("BaseCode UpdateContract error", err)
+ t.Fatal(err)
}
- err = main.UpdateFiatCurrency("Unreal Dollar", "AUD", 1111)
+ main.Register("AUD")
+ err = main.UpdateCurrency("Unreal Dollar", "AUD", "", 1111, Fiat)
if err != nil {
- t.Error("BaseCode UpdateContract error", err)
+ t.Fatal(err)
}
+
if main.Items[5].FullName != "Unreal Dollar" {
t.Error("Expected fullname to update for AUD")
}
- err = main.UpdateFiatCurrency("Australian Dollar", "AUD", 1336)
+ err = main.UpdateCurrency("Australian Dollar", "AUD", "", 1336, Fiat)
if err != nil {
- t.Error("BaseCode UpdateContract error", err)
+ t.Fatal(err)
}
main.Items[5].Role = Unset
- err = main.UpdateFiatCurrency("Australian Dollar", "AUD", 1336)
+ err = main.UpdateCurrency("Australian Dollar", "AUD", "", 1336, Fiat)
if err != nil {
- t.Error("BaseCode UpdateContract error", err)
+ t.Fatal(err)
}
if main.Items[5].Role != Fiat {
t.Error("Expected role to change to Fiat")
}
- err = main.UpdateToken("Populous", "PPT", "ETH", 1335)
+ main.Register("PPT")
+ err = main.UpdateCurrency("Populous", "PPT", "ETH", 1335, Token)
if err != nil {
- t.Error("BaseCode UpdateContract error", err)
+ t.Fatal(err)
}
contract := main.Register("XBTUSD")
@@ -235,15 +245,12 @@ func TestBaseCode(t *testing.T) {
true)
}
- err = main.LoadItem(&Item{
+ main.LoadItem(&Item{
ID: 0,
FullName: "Cardano",
Role: Cryptocurrency,
Symbol: "ADA",
})
- if err != nil {
- t.Error("BaseCode LoadItem() error", err)
- }
full, err := main.GetFullCurrencyData()
if err != nil {
@@ -275,8 +282,8 @@ func TestBaseCode(t *testing.T) {
len(full.UnsetCurrency))
}
- if !full.LastMainUpdate.IsZero() {
- t.Errorf("BaseCode GetFullCurrencyData() error expected 0 but received %s",
+ if full.LastMainUpdate.(int64) != -62135596800 {
+ t.Errorf("BaseCode GetFullCurrencyData() error expected -62135596800 but received %d",
full.LastMainUpdate)
}
@@ -295,41 +302,35 @@ func TestBaseCode(t *testing.T) {
}
main.Items[0].FullName = "Hello"
- err = main.UpdateCryptocurrency("MEWOW", "CATS", 1338)
+ err = main.UpdateCurrency("MEWOW", "CATS", "", 1338, Cryptocurrency)
if err != nil {
- t.Error("BaseCode UpdateContract error", err)
+ t.Fatal(err)
}
if main.Items[0].FullName != "MEWOW" {
t.Error("Fullname not updated")
}
- err = main.UpdateCryptocurrency("MEWOW", "CATS", 1338)
+ err = main.UpdateCurrency("MEWOW", "CATS", "", 1338, Cryptocurrency)
if err != nil {
- t.Error("BaseCode UpdateContract error", err)
+ t.Fatal(err)
+ }
+ err = main.UpdateCurrency("WOWCATS", "CATS", "", 3, Token)
+ if err != nil {
+ t.Fatal(err)
}
- main.Items[0].Role = Cryptocurrency
- err = main.UpdateCryptocurrency("MEWOW", "CATS", 3)
- if err != nil {
- t.Error("BaseCode UpdateContract error", err)
- }
- if main.Items[0].ID != 3 {
+ // Creates a new item under a different currency role
+ if main.Items[9].ID != 3 {
t.Error("ID not updated")
}
main.Items[0].Role = Unset
- err = main.UpdateCryptocurrency("MEWOW", "CATS", 1338)
+ err = main.UpdateCurrency("MEWOW", "CATS", "", 1338, Cryptocurrency)
if err != nil {
- t.Error("BaseCode UpdateContract error", err)
+ t.Fatal(err)
}
if main.Items[0].ID != 1338 {
t.Error("ID not updated")
}
-
- main.Items[0].Role = Token
- err = main.UpdateCryptocurrency("MEWOW", "CATS", 3)
- if err == nil {
- t.Error("Expecting cryptocurrency to already exist")
- }
}
func TestCodeString(t *testing.T) {
diff --git a/currency/code_types.go b/currency/code_types.go
index c1b934ef..47800d4c 100644
--- a/currency/code_types.go
+++ b/currency/code_types.go
@@ -41,12 +41,11 @@ type Code struct {
// Item defines a sub type containing the main attributes of a designated
// currency code pointer
type Item struct {
- ID int `json:"id"`
- FullName string `json:"fullName"`
- Symbol string `json:"symbol"`
- Role Role `json:"role"`
- AssocChain string `json:"associatedBlockchain"`
- AssocExchange []string `json:"associatedExchanges"`
+ ID int `json:"id,omitempty"`
+ FullName string `json:"fullName,omitempty"`
+ Symbol string `json:"symbol"`
+ Role Role `json:"-"`
+ AssocChain string `json:"associatedBlockchain,omitempty"`
}
// Const declarations for individual currencies/tokens/fiat
diff --git a/currency/coinmarketcap/coinmarketcap.go b/currency/coinmarketcap/coinmarketcap.go
index d664c181..e158ed28 100644
--- a/currency/coinmarketcap/coinmarketcap.go
+++ b/currency/coinmarketcap/coinmarketcap.go
@@ -8,7 +8,6 @@ package coinmarketcap
import (
"context"
"errors"
- "fmt"
"net/http"
"net/url"
"strconv"
@@ -17,6 +16,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/common"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
+ "github.com/thrasher-corp/gocryptotrader/log"
)
// SetDefaults sets default values for the exchange
@@ -62,8 +62,8 @@ func (c *Coinmarketcap) GetCryptocurrencyInfo(currencyID ...int64) (CryptoCurren
}
var currStr []string
- for _, d := range currencyID {
- currStr = append(currStr, strconv.FormatInt(d, 10))
+ for i := range currencyID {
+ currStr = append(currStr, strconv.FormatInt(currencyID[i], 10))
}
val := url.Values{}
@@ -667,7 +667,6 @@ func (c *Coinmarketcap) GetPriceConversion(amount float64, currencyID int64, atH
func (c *Coinmarketcap) SendHTTPRequest(method, endpoint string, v url.Values, result interface{}) error {
headers := make(map[string]string)
headers["Accept"] = "application/json"
- headers["Accept-Encoding"] = "deflate, gzip"
headers["X-CMC_PRO_API_KEY"] = c.APIkey
path := c.APIUrl + c.APIVersion + endpoint
@@ -710,7 +709,8 @@ func (c *Coinmarketcap) SetAccountPlan(s string) error {
case "enterprise":
c.Plan = Enterprise
default:
- return fmt.Errorf("account plan %s not found", s)
+ log.Warnf(log.Global, "account plan %s not found, defaulting to basic", s)
+ c.Plan = Basic
}
return nil
}
diff --git a/currency/coinmarketcap/coinmarketcap_test.go b/currency/coinmarketcap/coinmarketcap_test.go
index 4d878d73..93d54c5a 100644
--- a/currency/coinmarketcap/coinmarketcap_test.go
+++ b/currency/coinmarketcap/coinmarketcap_test.go
@@ -44,11 +44,6 @@ func TestSetup(t *testing.T) {
if err := c.Setup(cfg); err != nil {
t.Error(err)
}
-
- cfg.AccountPlan = "meow"
- if err := c.Setup(cfg); err == nil {
- t.Error("expected err when invalid account plan is specified")
- }
}
func TestCheckAccountPlan(t *testing.T) {
@@ -405,8 +400,4 @@ func TestSetAccountPlan(t *testing.T) {
}
}
}
-
- if err := c.SetAccountPlan("bra"); err == nil {
- t.Error("SetAccountPlan() error cannot be nil")
- }
}
diff --git a/currency/conversion.go b/currency/conversion.go
index 363366f7..edeec928 100644
--- a/currency/conversion.go
+++ b/currency/conversion.go
@@ -110,22 +110,14 @@ func (c *ConversionRates) Update(m map[string]float64) error {
var list []Code // Verification list, cross check all currencies coming in
var mainBaseCurrency Code
-
for key, val := range m {
- code1, err := storage.ValidateFiatCode(key[:3])
- if err != nil {
- return err
- }
+ code1 := storage.ValidateFiatCode(key[:3])
if mainBaseCurrency == (Code{}) {
mainBaseCurrency = code1
}
- code2, err := storage.ValidateFiatCode(key[3:])
- if err != nil {
- return err
- }
-
+ code2 := storage.ValidateFiatCode(key[3:])
if code1 == code2 { // Get rid of same conversions
continue
}
diff --git a/currency/currencies.go b/currency/currencies.go
index 2647fbc1..caa6cb97 100644
--- a/currency/currencies.go
+++ b/currency/currencies.go
@@ -23,8 +23,8 @@ type Currencies []Code
// Strings returns an array of currency strings
func (c Currencies) Strings() []string {
var list []string
- for _, d := range c {
- list = append(list, d.String())
+ for i := range c {
+ list = append(list, c[i].String())
}
return list
}
@@ -53,8 +53,9 @@ func (c *Currencies) UnmarshalJSON(d []byte) error {
}
var allTheCurrencies Currencies
- for _, data := range strings.Split(configCurrencies, ",") {
- allTheCurrencies = append(allTheCurrencies, NewCode(data))
+ curr := strings.Split(configCurrencies, ",")
+ for i := range curr {
+ allTheCurrencies = append(allTheCurrencies, NewCode(curr[i]))
}
*c = allTheCurrencies
@@ -72,17 +73,14 @@ func (c Currencies) Match(other Currencies) bool {
return false
}
- for _, d := range c {
- var found bool
- for i := range other {
- if d == other[i] {
- found = true
- break
+match:
+ for x := range c {
+ for y := range other {
+ if c[x] == other[y] {
+ continue match
}
}
- if !found {
- return false
- }
+ return false
}
return true
}
diff --git a/currency/currencies_test.go b/currency/currencies_test.go
index d97df832..f6d950c9 100644
--- a/currency/currencies_test.go
+++ b/currency/currencies_test.go
@@ -47,3 +47,18 @@ func TestCurrenciesMarshalJSON(t *testing.T) {
expected, string(encoded))
}
}
+
+func TestMatch(t *testing.T) {
+ matchString := []string{"btc", "usd", "ltc", "bro", "things"}
+ c := NewCurrenciesFromStringArray(matchString)
+
+ if !c.Match(NewCurrenciesFromStringArray(matchString)) {
+ t.Fatal("should match")
+ }
+ if c.Match(NewCurrenciesFromStringArray([]string{"btc", "usd", "ltc", "bro"})) {
+ t.Fatal("should not match")
+ }
+ if c.Match(NewCurrenciesFromStringArray([]string{"btc", "usd", "ltc", "bro", "garbo"})) {
+ t.Fatal("should not match")
+ }
+}
diff --git a/currency/currency.go b/currency/currency.go
index 475f4642..3415bf42 100644
--- a/currency/currency.go
+++ b/currency/currency.go
@@ -71,9 +71,14 @@ func GetTotalMarketCryptocurrencies() ([]Code, error) {
return storage.GetTotalMarketCryptocurrencies()
}
-// RunStorageUpdater runs a new foreign exchange updater instance
-func RunStorageUpdater(o BotOverrides, m *MainConfiguration, filepath string, v bool) error {
- return storage.RunUpdater(o, m, filepath, v)
+// RunStorageUpdater runs a new foreign exchange updater instance
+func RunStorageUpdater(o BotOverrides, m *MainConfiguration, filepath string) error {
+ return storage.RunUpdater(o, m, filepath)
+}
+
+// ShutdownStorageUpdater cleanly shuts down and saves to currency.json
+func ShutdownStorageUpdater() error {
+ return storage.Shutdown()
}
// CopyPairFormat copies the pair format from a list of pairs once matched
@@ -100,17 +105,23 @@ func FormatPairs(pairs []string, delimiter, index string) (Pairs, error) {
continue
}
var p Pair
+ var err error
if delimiter != "" {
- p = NewPairDelimiter(pairs[x], delimiter)
+ p, err = NewPairDelimiter(pairs[x], delimiter)
+ if err != nil {
+ return nil, err
+ }
} else {
if index != "" {
- var err error
p, err = NewPairFromIndex(pairs[x], index)
if err != nil {
return Pairs{}, err
}
} else {
- p = NewPairFromStrings(pairs[x][0:3], pairs[x][3:])
+ p, err = NewPairFromStrings(pairs[x][0:3], pairs[x][3:])
+ if err != nil {
+ return Pairs{}, err
+ }
}
}
result = append(result, p)
diff --git a/currency/currency_types.go b/currency/currency_types.go
index 641a6e1a..83b5b077 100644
--- a/currency/currency_types.go
+++ b/currency/currency_types.go
@@ -53,10 +53,24 @@ type FXSettings struct {
// File defines a full currency file generated by the currency storage
// analysis system
type File struct {
- LastMainUpdate time.Time `json:"lastMainUpdate"`
- Cryptocurrency []Item `json:"cryptocurrencies"`
- FiatCurrency []Item `json:"fiatCurrencies"`
- UnsetCurrency []Item `json:"unsetCurrencies"`
- Contracts []Item `json:"contracts"`
- Token []Item `json:"tokens"`
+ LastMainUpdate interface{} `json:"lastMainUpdate"`
+ Cryptocurrency []Item `json:"cryptocurrencies"`
+ FiatCurrency []Item `json:"fiatCurrencies"`
+ UnsetCurrency []Item `json:"unsetCurrencies"`
+ Contracts []Item `json:"contracts"`
+ Token []Item `json:"tokens"`
}
+
+// Const here are packaged defined delimiters
+const (
+ UnderscoreDelimiter = "_"
+ DashDelimiter = "-"
+ ForwardSlashDelimiter = "/"
+ ColonDelimiter = ":"
+)
+
+// delimiters is a delimiter list
+var delimiters = []string{UnderscoreDelimiter,
+ DashDelimiter,
+ ForwardSlashDelimiter,
+ ColonDelimiter}
diff --git a/currency/manager.go b/currency/manager.go
index c77aaa36..9485d93c 100644
--- a/currency/manager.go
+++ b/currency/manager.go
@@ -2,14 +2,16 @@ package currency
import (
"errors"
+ "fmt"
+ "github.com/thrasher-corp/gocryptotrader/common/convert"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
)
// GetAssetTypes returns a list of stored asset types
func (p *PairsManager) GetAssetTypes() asset.Items {
- p.m.Lock()
- defer p.m.Unlock()
+ p.m.RLock()
+ defer p.m.RUnlock()
var assetTypes asset.Items
for k := range p.Pairs {
assetTypes = append(assetTypes, k)
@@ -18,28 +20,23 @@ func (p *PairsManager) GetAssetTypes() asset.Items {
}
// Get gets the currency pair config based on the asset type
-func (p *PairsManager) Get(a asset.Item) *PairStore {
- p.m.Lock()
- defer p.m.Unlock()
+func (p *PairsManager) Get(a asset.Item) (*PairStore, error) {
+ p.m.RLock()
+ defer p.m.RUnlock()
c, ok := p.Pairs[a]
if !ok {
- return nil
+ return nil,
+ fmt.Errorf("cannot get pair store, asset type %s not supported", a)
}
- return c
+ return c, nil
}
// Store stores a new currency pair config based on its asset type
func (p *PairsManager) Store(a asset.Item, ps PairStore) {
p.m.Lock()
-
if p.Pairs == nil {
p.Pairs = make(map[asset.Item]*PairStore)
}
-
- if !p.AssetTypes.Contains(a) {
- p.AssetTypes = append(p.AssetTypes, a)
- }
-
p.Pairs[a] = &ps
p.m.Unlock()
}
@@ -51,37 +48,35 @@ func (p *PairsManager) Delete(a asset.Item) {
if p.Pairs == nil {
return
}
-
- _, ok := p.Pairs[a]
- if !ok {
- return
- }
-
delete(p.Pairs, a)
}
// GetPairs gets a list of stored pairs based on the asset type and whether
// they're enabled or not
-func (p *PairsManager) GetPairs(a asset.Item, enabled bool) Pairs {
- p.m.Lock()
- defer p.m.Unlock()
+func (p *PairsManager) GetPairs(a asset.Item, enabled bool) (Pairs, error) {
+ p.m.RLock()
+ defer p.m.RUnlock()
if p.Pairs == nil {
- return nil
+ return nil, nil
}
c, ok := p.Pairs[a]
if !ok {
- return nil
+ return nil, nil
}
- var pairs Pairs
if enabled {
- pairs = c.Enabled
- } else {
- pairs = c.Available
+ for i := range c.Enabled {
+ if !c.Available.Contains(c.Enabled[i], true) {
+ return c.Enabled,
+ fmt.Errorf("enabled pair %s of asset type %s not contained in available list",
+ c.Enabled[i],
+ a)
+ }
+ }
+ return c.Enabled, nil
}
-
- return pairs
+ return c.Available, nil
}
// StorePairs stores a list of pairs based on the asset type and whether
@@ -96,7 +91,8 @@ func (p *PairsManager) StorePairs(a asset.Item, pairs Pairs, enabled bool) {
c, ok := p.Pairs[a]
if !ok {
- c = new(PairStore)
+ p.Pairs[a] = new(PairStore)
+ c = p.Pairs[a]
}
if enabled {
@@ -104,8 +100,6 @@ func (p *PairsManager) StorePairs(a asset.Item, pairs Pairs, enabled bool) {
} else {
c.Available = pairs
}
-
- p.Pairs[a] = c
}
// DisablePair removes the pair from the enabled pairs list if found
@@ -113,17 +107,9 @@ func (p *PairsManager) DisablePair(a asset.Item, pair Pair) error {
p.m.Lock()
defer p.m.Unlock()
- if p.Pairs == nil {
- return errors.New("pair manager not initialised")
- }
-
- c, ok := p.Pairs[a]
- if !ok {
- return errors.New("asset type not found")
- }
-
- if c == nil {
- return errors.New("currency store is nil")
+ c, err := p.getPairStore(a)
+ if err != nil {
+ return err
}
if !c.Enabled.Contains(pair, true) {
@@ -140,27 +126,82 @@ func (p *PairsManager) EnablePair(a asset.Item, pair Pair) error {
p.m.Lock()
defer p.m.Unlock()
- if p.Pairs == nil {
- return errors.New("pair manager not initialised")
- }
-
- c, ok := p.Pairs[a]
- if !ok {
- return errors.New("asset type not found")
- }
-
- if c == nil {
- return errors.New("currency store is nil")
+ c, err := p.getPairStore(a)
+ if err != nil {
+ return err
}
if !c.Available.Contains(pair, true) {
- return errors.New("specified pair was not found in the list of available pairs")
+ return fmt.Errorf("%s pair was not found in the list of available pairs",
+ pair)
}
if c.Enabled.Contains(pair, true) {
- return errors.New("specified pair is already enabled")
+ return fmt.Errorf("%s pair is already enabled", pair)
}
c.Enabled = c.Enabled.Add(pair)
return nil
}
+
+// IsAssetEnabled checks to see if an asset is enabled
+func (p *PairsManager) IsAssetEnabled(a asset.Item) error {
+ p.m.RLock()
+ defer p.m.RUnlock()
+
+ c, err := p.getPairStore(a)
+ if err != nil {
+ return err
+ }
+
+ if c.AssetEnabled == nil {
+ return errors.New("cannot ascertain if asset is enabled, variable is nil")
+ }
+
+ if !*c.AssetEnabled {
+ return errors.New("asset not enabled")
+ }
+ return nil
+}
+
+// SetAssetEnabled sets if an asset is enabled or disabled for first run
+func (p *PairsManager) SetAssetEnabled(a asset.Item, enabled bool) error {
+ p.m.Lock()
+ defer p.m.Unlock()
+
+ c, err := p.getPairStore(a)
+ if err != nil {
+ return err
+ }
+
+ if c.AssetEnabled == nil {
+ c.AssetEnabled = convert.BoolPtr(enabled)
+ return nil
+ }
+
+ if !*c.AssetEnabled && !enabled {
+ return errors.New("asset already disabled")
+ } else if *c.AssetEnabled && enabled {
+ return errors.New("asset already enabled")
+ }
+
+ *c.AssetEnabled = enabled
+ return nil
+}
+
+func (p *PairsManager) getPairStore(a asset.Item) (*PairStore, error) {
+ if p.Pairs == nil {
+ return nil, errors.New("pair manager not initialised")
+ }
+
+ c, ok := p.Pairs[a]
+ if !ok {
+ return nil, errors.New("asset type not found")
+ }
+
+ if c == nil {
+ return nil, errors.New("currency store is nil")
+ }
+
+ return c, nil
+}
diff --git a/currency/manager_test.go b/currency/manager_test.go
index 2d2f0bbd..554c4f00 100644
--- a/currency/manager_test.go
+++ b/currency/manager_test.go
@@ -8,11 +8,21 @@ import (
var p PairsManager
-func initTest() {
+func initTest(t *testing.T) {
+ spotAvailable, err := NewPairsFromStrings([]string{"BTC-USD", "LTC-USD"})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ spotEnabled, err := NewPairsFromStrings([]string{"BTC-USD"})
+ if err != nil {
+ t.Fatal(err)
+ }
+
p.Store(asset.Spot,
PairStore{
- Available: NewPairsFromStrings([]string{"BTC-USD", "LTC-USD"}),
- Enabled: NewPairsFromStrings([]string{"BTC-USD"}),
+ Available: spotAvailable,
+ Enabled: spotEnabled,
RequestFormat: &PairFormat{
Uppercase: true,
},
@@ -25,7 +35,7 @@ func initTest() {
}
func TestGetAssetTypes(t *testing.T) {
- initTest()
+ initTest(t)
a := p.GetAssetTypes()
if len(a) == 0 {
@@ -38,22 +48,34 @@ func TestGetAssetTypes(t *testing.T) {
}
func TestGet(t *testing.T) {
- initTest()
+ initTest(t)
- if p.Get(asset.Spot) == nil {
- t.Error("Spot assets shouldn't be nil")
+ _, err := p.Get(asset.Spot)
+ if err != nil {
+ t.Error(err)
}
- if p.Get(asset.Futures) != nil {
+ _, err = p.Get(asset.Futures)
+ if err == nil {
t.Error("Futures should be nil")
}
}
func TestStore(t *testing.T) {
+ availPairs, err := NewPairsFromStrings([]string{"BTC-USD", "LTC-USD"})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ enabledPairs, err := NewPairsFromStrings([]string{"BTC-USD"})
+ if err != nil {
+ t.Fatal(err)
+ }
+
p.Store(asset.Futures,
PairStore{
- Available: NewPairsFromStrings([]string{"BTC-USD", "LTC-USD"}),
- Enabled: NewPairsFromStrings([]string{"BTC-USD"}),
+ Available: availPairs,
+ Enabled: enabledPairs,
RequestFormat: &PairFormat{
Uppercase: true,
},
@@ -64,7 +86,12 @@ func TestStore(t *testing.T) {
},
)
- if p.Get(asset.Futures) == nil {
+ f, err := p.Get(asset.Futures)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if f == nil {
t.Error("Futures assets shouldn't be nil")
}
}
@@ -73,67 +100,131 @@ func TestDelete(t *testing.T) {
p.Pairs = nil
p.Delete(asset.Spot)
- p.Store(asset.Spot,
- PairStore{
- Available: NewPairsFromStrings([]string{"BTC-USD"}),
- },
- )
+ btcusdPairs, err := NewPairsFromStrings([]string{"BTC-USD"})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ p.Store(asset.Spot, PairStore{
+ Available: btcusdPairs,
+ })
+
p.Delete(asset.UpsideProfitContract)
- if p.Get(asset.Spot) == nil {
+ spotPS, err := p.Get(asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if spotPS == nil {
t.Error("AssetTypeSpot should exist")
}
p.Delete(asset.Spot)
- if p.Get(asset.Spot) != nil {
+
+ if _, err := p.Get(asset.Spot); err == nil {
t.Error("Delete should have deleted AssetTypeSpot")
}
}
func TestGetPairs(t *testing.T) {
p.Pairs = nil
- pairs := p.GetPairs(asset.Spot, true)
+ pairs, err := p.GetPairs(asset.Spot, true)
+ if err != nil {
+ t.Fatal(err)
+ }
+
if pairs != nil {
t.Fatal("pairs shouldn't be populated")
}
- initTest()
- pairs = p.GetPairs(asset.Spot, true)
+ initTest(t)
+ pairs, err = p.GetPairs(asset.Spot, true)
+ if err != nil {
+ t.Fatal(err)
+ }
if pairs == nil {
t.Fatal("pairs should be populated")
}
- pairs = p.GetPairs("blah", true)
+ pairs, err = p.GetPairs("blah", true)
+ if err != nil {
+ t.Fatal(err)
+ }
+
if pairs != nil {
t.Fatal("pairs shouldn't be populated")
}
+
+ superfluous := NewPair(DASH, USDT)
+ newPairs := p.Pairs[asset.Spot].Enabled.Add(superfluous)
+ p.Pairs[asset.Spot].Enabled = newPairs
+
+ _, err = p.GetPairs(asset.Spot, true)
+ if err == nil {
+ t.Fatal("error cannot be nil")
+ }
}
func TestStorePairs(t *testing.T) {
p.Pairs = nil
- p.StorePairs(asset.Spot, NewPairsFromStrings([]string{"ETH-USD"}), false)
- pairs := p.GetPairs(asset.Spot, false)
- if !pairs.Contains(NewPairFromString("ETH-USD"), true) {
+
+ ethusdPairs, err := NewPairsFromStrings([]string{"ETH-USD"})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ p.StorePairs(asset.Spot, ethusdPairs, false)
+ pairs, err := p.GetPairs(asset.Spot, false)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ ethusd, err := NewPairFromString("ETH-USD")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if !pairs.Contains(ethusd, true) {
t.Errorf("TestStorePairs failed, unexpected result")
}
- initTest()
- p.StorePairs(asset.Spot, NewPairsFromStrings([]string{"ETH-USD"}), false)
- pairs = p.GetPairs(asset.Spot, false)
+ initTest(t)
+ p.StorePairs(asset.Spot, ethusdPairs, false)
+ pairs, err = p.GetPairs(asset.Spot, false)
+ if err != nil {
+ t.Fatal(err)
+ }
+
if pairs == nil {
t.Errorf("pairs should be populated")
}
- if !pairs.Contains(NewPairFromString("ETH-USD"), true) {
+ if !pairs.Contains(ethusd, true) {
t.Errorf("TestStorePairs failed, unexpected result")
}
- p.StorePairs(asset.Futures, NewPairsFromStrings([]string{"ETH-KRW"}), true)
- pairs = p.GetPairs(asset.Futures, true)
+ ethkrwPairs, err := NewPairsFromStrings([]string{"ETH-KRW"})
+ if err != nil {
+ t.Error(err)
+ }
+
+ p.StorePairs(asset.Futures, ethkrwPairs, true)
+ p.StorePairs(asset.Futures, ethkrwPairs, false)
+ pairs, err = p.GetPairs(asset.Futures, true)
+ if err != nil {
+ t.Fatal(err)
+ }
+
if pairs == nil {
t.Errorf("pairs futures should be populated")
}
- if !pairs.Contains(NewPairFromString("ETH-KRW"), true) {
+ ethkrw, err := NewPairFromString("ETH-KRW")
+ if err != nil {
+ t.Error(err)
+ }
+
+ if !pairs.Contains(ethkrw, true) {
t.Errorf("TestStorePairs failed, unexpected result")
}
}
@@ -146,7 +237,7 @@ func TestDisablePair(t *testing.T) {
}
// Test asset type which doesn't exist
- initTest()
+ initTest(t)
if err := p.DisablePair(asset.Futures, Pair{}); err == nil {
t.Error("unexpected result")
}
@@ -158,7 +249,7 @@ func TestDisablePair(t *testing.T) {
}
// Test disabling a pair which isn't enabled
- initTest()
+ initTest(t)
if err := p.DisablePair(asset.Spot, NewPair(LTC, USD)); err == nil {
t.Error("unexpected result")
}
@@ -177,7 +268,7 @@ func TestEnablePair(t *testing.T) {
}
// Test asset type which doesn't exist
- initTest()
+ initTest(t)
if err := p.EnablePair(asset.Futures, Pair{}); err == nil {
t.Error("unexpected result")
}
@@ -189,7 +280,7 @@ func TestEnablePair(t *testing.T) {
}
// Test enabling a pair which isn't in the list of available pairs
- initTest()
+ initTest(t)
if err := p.EnablePair(asset.Spot, NewPair(ETH, USD)); err == nil {
t.Error("unexpected result")
}
@@ -204,3 +295,55 @@ func TestEnablePair(t *testing.T) {
t.Error("unexpected result")
}
}
+
+func TestIsAssetEnabled_SetAssetEnabled(t *testing.T) {
+ p.Pairs = nil
+ // Test enabling a pair when the pair manager is not initialised
+ err := p.IsAssetEnabled(asset.Spot)
+ if err == nil {
+ t.Error("unexpected result")
+ }
+
+ err = p.SetAssetEnabled(asset.Spot, true)
+ if err == nil {
+ t.Fatal("unexpected result")
+ }
+
+ // Test asset type which doesn't exist
+ initTest(t)
+
+ err = p.IsAssetEnabled(asset.Spot)
+ if err == nil {
+ t.Error("unexpected result")
+ }
+
+ err = p.SetAssetEnabled(asset.Spot, false)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ err = p.SetAssetEnabled(asset.Spot, false)
+ if err == nil {
+ t.Fatal("unexpected result")
+ }
+
+ err = p.IsAssetEnabled(asset.Spot)
+ if err == nil {
+ t.Error("unexpected result")
+ }
+
+ err = p.SetAssetEnabled(asset.Spot, true)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ err = p.SetAssetEnabled(asset.Spot, true)
+ if err == nil {
+ t.Fatal("unexpected result")
+ }
+
+ err = p.IsAssetEnabled(asset.Spot)
+ if err != nil {
+ t.Error("unexpected result")
+ }
+}
diff --git a/currency/manager_types.go b/currency/manager_types.go
index 456cea10..ad2540ca 100644
--- a/currency/manager_types.go
+++ b/currency/manager_types.go
@@ -12,13 +12,13 @@ type PairsManager struct {
ConfigFormat *PairFormat `json:"configFormat,omitempty"`
UseGlobalFormat bool `json:"useGlobalFormat,omitempty"`
LastUpdated int64 `json:"lastUpdated,omitempty"`
- AssetTypes asset.Items `json:"assetTypes"`
Pairs map[asset.Item]*PairStore `json:"pairs"`
- m sync.Mutex
+ m sync.RWMutex
}
// PairStore stores a currency pair store
type PairStore struct {
+ AssetEnabled *bool `json:"assetEnabled"`
Enabled Pairs `json:"enabled"`
Available Pairs `json:"available"`
RequestFormat *PairFormat `json:"requestFormat,omitempty"`
diff --git a/currency/pair.go b/currency/pair.go
index bf4ff95b..ccc9e985 100644
--- a/currency/pair.go
+++ b/currency/pair.go
@@ -1,15 +1,24 @@
package currency
import (
- "encoding/json"
"fmt"
"strings"
)
// NewPairDelimiter splits the desired currency string at delimeter, the returns
// a Pair struct
-func NewPairDelimiter(currencyPair, delimiter string) Pair {
+func NewPairDelimiter(currencyPair, delimiter string) (Pair, error) {
+ if !strings.Contains(currencyPair, delimiter) {
+ return Pair{},
+ fmt.Errorf("delimiter: [%s] not found in currencypair string", delimiter)
+ }
result := strings.Split(currencyPair, delimiter)
+ if len(result) < 2 {
+ return Pair{},
+ fmt.Errorf("supplied pair: [%s] cannot be split with %s",
+ currencyPair,
+ delimiter)
+ }
if len(result) > 2 {
result[1] = strings.Join(result[1:], delimiter)
}
@@ -17,15 +26,24 @@ func NewPairDelimiter(currencyPair, delimiter string) Pair {
Delimiter: delimiter,
Base: NewCode(result[0]),
Quote: NewCode(result[1]),
- }
+ }, nil
}
// NewPairFromStrings returns a CurrencyPair without a delimiter
-func NewPairFromStrings(baseCurrency, quoteCurrency string) Pair {
- return Pair{
- Base: NewCode(baseCurrency),
- Quote: NewCode(quoteCurrency),
+func NewPairFromStrings(base, quote string) (Pair, error) {
+ if strings.Contains(base, " ") {
+ return Pair{},
+ fmt.Errorf("cannot create pair, invalid base currency string [%s]",
+ base)
}
+
+ if strings.Contains(quote, " ") {
+ return Pair{},
+ fmt.Errorf("cannot create pair, invalid quote currency string [%s]",
+ quote)
+ }
+
+ return Pair{Base: NewCode(base), Quote: NewCode(quote)}, nil
}
// NewPair returns a currency pair from currency codes
@@ -55,23 +73,24 @@ func NewPairFromIndex(currencyPair, index string) (Pair, error) {
}
if i == 0 {
return NewPairFromStrings(currencyPair[0:len(index)],
- currencyPair[len(index):]),
- nil
+ currencyPair[len(index):])
}
- return NewPairFromStrings(currencyPair[0:i], currencyPair[i:]), nil
+ return NewPairFromStrings(currencyPair[0:i], currencyPair[i:])
}
// NewPairFromString converts currency string into a new CurrencyPair
// with or without delimeter
-func NewPairFromString(currencyPair string) Pair {
- delimiters := []string{"_", "-", "/", ":"}
- var delimiter string
- for _, x := range delimiters {
- if strings.Contains(currencyPair, x) {
- delimiter = x
- return NewPairDelimiter(currencyPair, delimiter)
+func NewPairFromString(currencyPair string) (Pair, error) {
+ for x := range delimiters {
+ if strings.Contains(currencyPair, delimiters[x]) {
+ return NewPairDelimiter(currencyPair, delimiters[x])
}
}
+ if len(currencyPair) < 3 {
+ return Pair{},
+ fmt.Errorf("cannot create pair from %s string",
+ currencyPair)
+ }
return NewPairFromStrings(currencyPair[0:3], currencyPair[3:])
}
@@ -79,129 +98,12 @@ func NewPairFromString(currencyPair string) Pair {
// with a specific format. This is helpful for exchanges which
// provide currency pairs with no delimiter so we can match it with a list and
// apply the same format
-func NewPairFromFormattedPairs(currencyPair string, pairs Pairs, pairFmt PairFormat) Pair {
+func NewPairFromFormattedPairs(currencyPair string, pairs Pairs, pairFmt PairFormat) (Pair, error) {
for x := range pairs {
- if strings.EqualFold(pairs[x].Format(pairFmt.Delimiter,
- pairFmt.Uppercase).String(), currencyPair) {
- return pairs[x]
+ fPair := pairs[x].Format(pairFmt.Delimiter, pairFmt.Uppercase)
+ if strings.EqualFold(fPair.String(), currencyPair) {
+ return pairs[x], nil
}
}
return NewPairFromString(currencyPair)
}
-
-// String returns a currency pair string
-func (p Pair) String() string {
- return p.Base.String() + p.Delimiter + p.Quote.String()
-}
-
-// Lower converts the pair object to lowercase
-func (p Pair) Lower() Pair {
- return Pair{
- Delimiter: p.Delimiter,
- Base: p.Base.Lower(),
- Quote: p.Quote.Lower(),
- }
-}
-
-// Upper converts the pair object to uppercase
-func (p Pair) Upper() Pair {
- return Pair{
- Delimiter: p.Delimiter,
- Base: p.Base.Upper(),
- Quote: p.Quote.Upper(),
- }
-}
-
-// UnmarshalJSON comforms type to the umarshaler interface
-func (p *Pair) UnmarshalJSON(d []byte) error {
- var pair string
- err := json.Unmarshal(d, &pair)
- if err != nil {
- return err
- }
-
- *p = NewPairFromString(pair)
- return nil
-}
-
-// MarshalJSON conforms type to the marshaler interface
-func (p Pair) MarshalJSON() ([]byte, error) {
- return json.Marshal(p.String())
-}
-
-// Format changes the currency based on user preferences overriding the default
-// String() display
-func (p Pair) Format(delimiter string, uppercase bool) Pair {
- p.Delimiter = delimiter
-
- if uppercase {
- return p.Upper()
- }
- return p.Lower()
-}
-
-// Equal compares two currency pairs and returns whether or not they are equal
-func (p Pair) Equal(cPair Pair) bool {
- return strings.EqualFold(p.Base.String(), cPair.Base.String()) &&
- strings.EqualFold(p.Quote.String(), cPair.Quote.String())
-}
-
-// EqualIncludeReciprocal compares two currency pairs and returns whether or not
-// they are the same including reciprocal currencies.
-func (p Pair) EqualIncludeReciprocal(cPair Pair) bool {
- if p.Base.Item == cPair.Base.Item &&
- p.Quote.Item == cPair.Quote.Item ||
- p.Base.Item == cPair.Quote.Item &&
- p.Quote.Item == cPair.Base.Item {
- return true
- }
- return false
-}
-
-// IsCryptoPair checks to see if the pair is a crypto pair e.g. BTCLTC
-func (p Pair) IsCryptoPair() bool {
- return storage.IsCryptocurrency(p.Base) &&
- storage.IsCryptocurrency(p.Quote)
-}
-
-// IsCryptoFiatPair checks to see if the pair is a crypto fiat pair e.g. BTCUSD
-func (p Pair) IsCryptoFiatPair() bool {
- return storage.IsCryptocurrency(p.Base) &&
- storage.IsFiatCurrency(p.Quote) ||
- storage.IsFiatCurrency(p.Base) &&
- storage.IsCryptocurrency(p.Quote)
-}
-
-// IsFiatPair checks to see if the pair is a fiat pair e.g. EURUSD
-func (p Pair) IsFiatPair() bool {
- return storage.IsFiatCurrency(p.Base) && storage.IsFiatCurrency(p.Quote)
-}
-
-// IsInvalid checks invalid pair if base and quote are the same
-func (p Pair) IsInvalid() bool {
- return p.Base.Item == p.Quote.Item
-}
-
-// Swap turns the currency pair into its reciprocal
-func (p Pair) Swap() Pair {
- p.Base, p.Quote = p.Quote, p.Base
- return p
-}
-
-// IsEmpty returns whether or not the pair is empty or is missing a currency
-// code
-func (p Pair) IsEmpty() bool {
- return p.Base.IsEmpty() || p.Quote.IsEmpty()
-}
-
-// ContainsCurrency checks to see if a pair contains a specific currency
-func (p Pair) ContainsCurrency(c Code) bool {
- return p.Base.Item == c.Item || p.Quote.Item == c.Item
-}
-
-// Pair holds currency pair information
-type Pair struct {
- Delimiter string `json:"delimiter"`
- Base Code `json:"base"`
- Quote Code `json:"quote"`
-}
diff --git a/currency/pair_methods.go b/currency/pair_methods.go
new file mode 100644
index 00000000..f377d07c
--- /dev/null
+++ b/currency/pair_methods.go
@@ -0,0 +1,117 @@
+package currency
+
+import (
+ "encoding/json"
+ "strings"
+)
+
+// String returns a currency pair string
+func (p Pair) String() string {
+ return p.Base.String() + p.Delimiter + p.Quote.String()
+}
+
+// Lower converts the pair object to lowercase
+func (p Pair) Lower() Pair {
+ return Pair{
+ Delimiter: p.Delimiter,
+ Base: p.Base.Lower(),
+ Quote: p.Quote.Lower(),
+ }
+}
+
+// Upper converts the pair object to uppercase
+func (p Pair) Upper() Pair {
+ return Pair{
+ Delimiter: p.Delimiter,
+ Base: p.Base.Upper(),
+ Quote: p.Quote.Upper(),
+ }
+}
+
+// UnmarshalJSON comforms type to the umarshaler interface
+func (p *Pair) UnmarshalJSON(d []byte) error {
+ var pair string
+ err := json.Unmarshal(d, &pair)
+ if err != nil {
+ return err
+ }
+
+ newPair, err := NewPairFromString(pair)
+ if err != nil {
+ return err
+ }
+
+ p.Base = newPair.Base
+ p.Quote = newPair.Quote
+ p.Delimiter = newPair.Delimiter
+ return nil
+}
+
+// MarshalJSON conforms type to the marshaler interface
+func (p Pair) MarshalJSON() ([]byte, error) {
+ return json.Marshal(p.String())
+}
+
+// Format changes the currency based on user preferences overriding the default
+// String() display
+func (p Pair) Format(delimiter string, uppercase bool) Pair {
+ newP := Pair{Base: p.Base, Quote: p.Quote, Delimiter: delimiter}
+ if uppercase {
+ return newP.Upper()
+ }
+ return newP.Lower()
+}
+
+// Equal compares two currency pairs and returns whether or not they are equal
+func (p Pair) Equal(cPair Pair) bool {
+ return strings.EqualFold(p.Base.String(), cPair.Base.String()) &&
+ strings.EqualFold(p.Quote.String(), cPair.Quote.String())
+}
+
+// EqualIncludeReciprocal compares two currency pairs and returns whether or not
+// they are the same including reciprocal currencies.
+func (p Pair) EqualIncludeReciprocal(cPair Pair) bool {
+ if (p.Base.Item == cPair.Base.Item && p.Quote.Item == cPair.Quote.Item) ||
+ (p.Base.Item == cPair.Quote.Item && p.Quote.Item == cPair.Base.Item) {
+ return true
+ }
+ return false
+}
+
+// IsCryptoPair checks to see if the pair is a crypto pair e.g. BTCLTC
+func (p Pair) IsCryptoPair() bool {
+ return storage.IsCryptocurrency(p.Base) &&
+ storage.IsCryptocurrency(p.Quote)
+}
+
+// IsCryptoFiatPair checks to see if the pair is a crypto fiat pair e.g. BTCUSD
+func (p Pair) IsCryptoFiatPair() bool {
+ return (storage.IsCryptocurrency(p.Base) && storage.IsFiatCurrency(p.Quote)) ||
+ (storage.IsFiatCurrency(p.Base) && storage.IsCryptocurrency(p.Quote))
+}
+
+// IsFiatPair checks to see if the pair is a fiat pair e.g. EURUSD
+func (p Pair) IsFiatPair() bool {
+ return storage.IsFiatCurrency(p.Base) && storage.IsFiatCurrency(p.Quote)
+}
+
+// IsInvalid checks invalid pair if base and quote are the same
+func (p Pair) IsInvalid() bool {
+ return p.Base.Item == p.Quote.Item
+}
+
+// Swap turns the currency pair into its reciprocal
+func (p Pair) Swap() Pair {
+ return Pair{Base: p.Quote, Quote: p.Base}
+}
+
+// IsEmpty returns whether or not the pair is empty or is missing a currency
+// code
+func (p Pair) IsEmpty() bool {
+ return p.Base.IsEmpty() && p.Quote.IsEmpty()
+}
+
+// ContainsCurrency checks to see if a pair contains a specific currency
+func (p Pair) ContainsCurrency(c Code) bool {
+ return p.Base.Item == c.Item || p.Quote.Item == c.Item
+}
diff --git a/currency/pair_test.go b/currency/pair_test.go
index f429f27a..56511f4f 100644
--- a/currency/pair_test.go
+++ b/currency/pair_test.go
@@ -12,21 +12,35 @@ const (
func TestLower(t *testing.T) {
t.Parallel()
- pair := NewPairFromString(defaultPair)
+ pair, err := NewPairFromString(defaultPair)
+ if err != nil {
+ t.Fatal(err)
+ }
actual := pair.Lower()
- expected := NewPairFromString(defaultPair).Lower()
- if actual != expected {
+ expected, err := NewPairFromString(defaultPair)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if actual.String() != expected.Lower().String() {
t.Errorf("Lower(): %s was not equal to expected value: %s",
- actual, expected)
+ actual,
+ expected.Lower())
}
}
func TestUpper(t *testing.T) {
t.Parallel()
- pair := NewPairFromString(defaultPair)
+ pair, err := NewPairFromString(defaultPair)
+ if err != nil {
+ t.Fatal(err)
+ }
actual := pair.Upper()
- expected := NewPairFromString(defaultPair)
- if actual != expected {
+ expected, err := NewPairFromString(defaultPair)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if actual.String() != expected.String() {
t.Errorf("Upper(): %s was not equal to expected value: %s",
actual, expected)
}
@@ -34,7 +48,10 @@ func TestUpper(t *testing.T) {
func TestPairUnmarshalJSON(t *testing.T) {
var unmarshalHere Pair
- configPair := NewPairDelimiter("btc_usd", "_")
+ configPair, err := NewPairDelimiter("btc_usd", "_")
+ if err != nil {
+ t.Fatal(err)
+ }
encoded, err := json.Marshal(configPair)
if err != nil {
@@ -59,9 +76,9 @@ func TestPairUnmarshalJSON(t *testing.T) {
func TestPairMarshalJSON(t *testing.T) {
quickstruct := struct {
- Pair Pair `json:"superPair"`
+ Pair *Pair `json:"superPair"`
}{
- Pair{Base: BTC, Quote: USD, Delimiter: "-"},
+ &Pair{Base: BTC, Quote: USD, Delimiter: "-"},
}
encoded, err := json.Marshal(quickstruct)
@@ -158,7 +175,14 @@ func TestPair(t *testing.T) {
func TestDisplay(t *testing.T) {
t.Parallel()
- pair := NewPairDelimiter(defaultPairWDelimiter, "-")
+ _, err := NewPairDelimiter(defaultPairWDelimiter, "wow")
+ if err == nil {
+ t.Fatal("error cannot be nil")
+ }
+ pair, err := NewPairDelimiter(defaultPairWDelimiter, "-")
+ if err != nil {
+ t.Fatal(err)
+ }
actual := pair.String()
expected := defaultPairWDelimiter
if actual != expected {
@@ -319,7 +343,24 @@ func TestNewPairWithDelimiter(t *testing.T) {
func TestNewPairDelimiter(t *testing.T) {
t.Parallel()
- pair := NewPairDelimiter(defaultPairWDelimiter, "-")
+ _, err := NewPairDelimiter("", "")
+ if err == nil {
+ t.Fatal("error cannot be nil")
+ }
+ _, err = NewPairDelimiter("BTC_USD", "wow")
+ if err == nil {
+ t.Fatal("error cannot be nil")
+ }
+
+ _, err = NewPairDelimiter("BTC_USD", " ")
+ if err == nil {
+ t.Fatal("error cannot be nil")
+ }
+
+ pair, err := NewPairDelimiter(defaultPairWDelimiter, "-")
+ if err != nil {
+ t.Fatal(err)
+ }
actual := pair.String()
expected := defaultPairWDelimiter
if actual != expected {
@@ -338,7 +379,10 @@ func TestNewPairDelimiter(t *testing.T) {
)
}
- pair = NewPairDelimiter("BTC-MOVE-0626", "-")
+ pair, err = NewPairDelimiter("BTC-MOVE-0626", "-")
+ if err != nil {
+ t.Fatal(err)
+ }
actual = pair.String()
expected = "BTC-MOVE-0626"
if actual != expected {
@@ -348,7 +392,10 @@ func TestNewPairDelimiter(t *testing.T) {
)
}
- pair = NewPairDelimiter("fBTC-USDT", "-")
+ pair, err = NewPairDelimiter("fBTC-USDT", "-")
+ if err != nil {
+ t.Fatal(err)
+ }
actual = pair.String()
expected = "fBTC-USDT"
if actual != expected {
@@ -404,7 +451,10 @@ func TestNewPairFromIndex(t *testing.T) {
func TestNewPairFromString(t *testing.T) {
t.Parallel()
pairStr := defaultPairWDelimiter
- pair := NewPairFromString(pairStr)
+ pair, err := NewPairFromString(pairStr)
+ if err != nil {
+ t.Fatal(err)
+ }
actual := pair.String()
expected := defaultPairWDelimiter
if actual != expected {
@@ -415,7 +465,10 @@ func TestNewPairFromString(t *testing.T) {
}
pairStr = defaultPair
- pair = NewPairFromString(pairStr)
+ pair, err = NewPairFromString(pairStr)
+ if err != nil {
+ t.Fatal(err)
+ }
actual = pair.String()
expected = defaultPair
if actual != expected {
@@ -428,23 +481,45 @@ func TestNewPairFromString(t *testing.T) {
func TestNewPairFromFormattedPairs(t *testing.T) {
t.Parallel()
+ p1, err := NewPairDelimiter("BTC-USDT", "-")
+ if err != nil {
+ t.Fatal(err)
+ }
+ p2, err := NewPairDelimiter("LTC-USD", "-")
+ if err != nil {
+ t.Fatal(err)
+ }
pairs := Pairs{
- NewPairDelimiter("BTC-USDT", "-"),
- NewPairDelimiter("LTC-USD", "-"),
+ p1,
+ p2,
+ }
+
+ p, err := NewPairFromFormattedPairs("BTCUSDT", pairs, PairFormat{
+ Uppercase: true,
+ })
+ if err != nil {
+ t.Fatal(err)
}
- p := NewPairFromFormattedPairs("BTCUSDT", pairs, PairFormat{Uppercase: true})
if p.String() != "BTC-USDT" {
t.Error("TestNewPairFromFormattedPairs: Expected currency was not found")
}
- p = NewPairFromFormattedPairs("btcusdt", pairs, PairFormat{Uppercase: false})
+ p, err = NewPairFromFormattedPairs("btcusdt", pairs, PairFormat{Uppercase: false})
+ if err != nil {
+ t.Fatal(err)
+ }
+
if p.String() != "BTC-USDT" {
t.Error("TestNewPairFromFormattedPairs: Expected currency was not found")
}
// Now a wrong one, will default to NewPairFromString
- p = NewPairFromFormattedPairs("ethusdt", pairs, PairFormat{})
+ p, err = NewPairFromFormattedPairs("ethusdt", pairs, PairFormat{})
+ if err != nil {
+ t.Fatal(err)
+ }
+
if p.String() != "ethusdt" && p.Base.String() != "eth" {
t.Error("TestNewPairFromFormattedPairs: Expected currency was not found")
}
@@ -514,29 +589,43 @@ func TestCopyPairFormat(t *testing.T) {
t.Error("TestCopyPairFormat: Expected pair was not found")
}
- result = CopyPairFormat(NewPair(ETH, USD), pairs, true)
+ np := NewPair(ETH, USD)
+ result = CopyPairFormat(np, pairs, true)
if result.String() != "" {
t.Error("TestCopyPairFormat: Unexpected non empty pair returned")
}
}
func TestFindPairDifferences(t *testing.T) {
- pairList := NewPairsFromStrings([]string{defaultPairWDelimiter, "ETH-USD", "LTC-USD"})
+ pairList, err := NewPairsFromStrings([]string{defaultPairWDelimiter, "ETH-USD", "LTC-USD"})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ dash, err := NewPairsFromStrings([]string{"DASH-USD"})
+ if err != nil {
+ t.Fatal(err)
+ }
// Test new pair update
- newPairs, removedPairs := pairList.FindDifferences(NewPairsFromStrings([]string{"DASH-USD"}))
+ newPairs, removedPairs := pairList.FindDifferences(dash)
if len(newPairs) != 1 && len(removedPairs) != 3 {
t.Error("TestFindPairDifferences: Unexpected values")
}
+ emptyPairsList, err := NewPairsFromStrings([]string{""})
+ if err != nil {
+ t.Fatal(err)
+ }
+
// Test that we don't allow empty strings for new pairs
- newPairs, removedPairs = pairList.FindDifferences(NewPairsFromStrings([]string{""}))
+ newPairs, removedPairs = pairList.FindDifferences(emptyPairsList)
if len(newPairs) != 0 && len(removedPairs) != 3 {
t.Error("TestFindPairDifferences: Unexpected values")
}
// Test that we don't allow empty strings for new pairs
- newPairs, removedPairs = NewPairsFromStrings([]string{""}).FindDifferences(pairList)
+ newPairs, removedPairs = emptyPairsList.FindDifferences(pairList)
if len(newPairs) != 3 && len(removedPairs) != 0 {
t.Error("TestFindPairDifferences: Unexpected values")
}
diff --git a/currency/pair_types.go b/currency/pair_types.go
new file mode 100644
index 00000000..263da25f
--- /dev/null
+++ b/currency/pair_types.go
@@ -0,0 +1,12 @@
+package currency
+
+// Pair holds currency pair information
+type Pair struct {
+ ID string `json:"id"`
+ Delimiter string `json:"delimiter,omitempty"`
+ Base Code `json:"base,omitempty"`
+ Quote Code `json:"quote,omitempty"`
+}
+
+// Pairs defines a list of pairs
+type Pairs []Pair
diff --git a/currency/pairs.go b/currency/pairs.go
index effe2167..8abbd948 100644
--- a/currency/pairs.go
+++ b/currency/pairs.go
@@ -10,16 +10,21 @@ import (
// NewPairsFromStrings takes in currency pair strings and returns a currency
// pair list
-func NewPairsFromStrings(pairs []string) Pairs {
- var ps Pairs
- for _, p := range pairs {
- if p == "" {
+func NewPairsFromStrings(pairs []string) (Pairs, error) {
+ var newPairs Pairs
+ for i := range pairs {
+ if pairs[i] == "" {
continue
}
- ps = append(ps, NewPairFromString(p))
+ newPair, err := NewPairFromString(pairs[i])
+ if err != nil {
+ return nil, err
+ }
+
+ newPairs = append(newPairs, newPair)
}
- return ps
+ return newPairs, nil
}
// Strings returns a slice of strings referring to each currency pair
@@ -79,8 +84,13 @@ func (p *Pairs) UnmarshalJSON(d []byte) error {
}
var allThePairs Pairs
- for _, data := range strings.Split(pairs, ",") {
- allThePairs = append(allThePairs, NewPairFromString(data))
+ oldPairs := strings.Split(pairs, ",")
+ for i := range oldPairs {
+ pair, err := NewPairFromString(oldPairs[i])
+ if err != nil {
+ return err
+ }
+ allThePairs = append(allThePairs, pair)
}
*p = allThePairs
@@ -101,21 +111,16 @@ func (p Pairs) Upper() Pairs {
return upper
}
-// Slice exposes the underlying type
-func (p Pairs) Slice() []Pair {
- return p
-}
-
// Contains checks to see if a specified pair exists inside a currency pair
// array
func (p Pairs) Contains(check Pair, exact bool) bool {
- for _, pair := range p.Slice() {
+ for i := range p {
if exact {
- if pair.Equal(check) {
+ if p[i].Equal(check) {
return true
}
} else {
- if pair.EqualIncludeReciprocal(check) {
+ if p[i].EqualIncludeReciprocal(check) {
return true
}
}
@@ -127,11 +132,11 @@ func (p Pairs) Contains(check Pair, exact bool) bool {
// and removes it from the list of pairs
func (p Pairs) RemovePairsByFilter(filter Code) Pairs {
var pairs Pairs
- for _, pair := range p.Slice() {
- if pair.ContainsCurrency(filter) {
+ for i := range p {
+ if p[i].ContainsCurrency(filter) {
continue
}
- pairs = append(pairs, pair)
+ pairs = append(pairs, p[i])
}
return pairs
}
@@ -167,12 +172,12 @@ func (p Pairs) FindDifferences(pairs Pairs) (newPairs, removedPairs Pairs) {
newPairs = append(newPairs, pairs[x])
}
}
- for _, oldPair := range p {
- if oldPair.String() == "" {
+ for x := range p {
+ if p[x].String() == "" {
continue
}
- if !pairs.Contains(oldPair, true) {
- removedPairs = append(removedPairs, oldPair)
+ if !pairs.Contains(p[x], true) {
+ removedPairs = append(removedPairs, p[x])
}
}
return
@@ -188,6 +193,3 @@ func (p Pairs) GetRandomPair() Pair {
return p[rand.Intn(pairsLen)]
}
-
-// Pairs defines a list of pairs
-type Pairs []Pair
diff --git a/currency/pairs_test.go b/currency/pairs_test.go
index 1af69a8f..87429817 100644
--- a/currency/pairs_test.go
+++ b/currency/pairs_test.go
@@ -6,7 +6,10 @@ import (
)
func TestPairsUpper(t *testing.T) {
- pairs := NewPairsFromStrings([]string{"btc_usd", "btc_aud", "btc_ltc"})
+ pairs, err := NewPairsFromStrings([]string{"btc_usd", "btc_aud", "btc_ltc"})
+ if err != nil {
+ t.Fatal(err)
+ }
expected := "BTC_USD,BTC_AUD,BTC_LTC"
if pairs.Upper().Join() != expected {
@@ -16,7 +19,10 @@ func TestPairsUpper(t *testing.T) {
}
func TestPairsString(t *testing.T) {
- pairs := NewPairsFromStrings([]string{"btc_usd", "btc_aud", "btc_ltc"})
+ pairs, err := NewPairsFromStrings([]string{"btc_usd", "btc_aud", "btc_ltc"})
+ if err != nil {
+ t.Fatal(err)
+ }
expected := []string{"btc_usd", "btc_aud", "btc_ltc"}
for i, p := range pairs {
@@ -28,7 +34,10 @@ func TestPairsString(t *testing.T) {
}
func TestPairsJoin(t *testing.T) {
- pairs := NewPairsFromStrings([]string{"btc_usd", "btc_aud", "btc_ltc"})
+ pairs, err := NewPairsFromStrings([]string{"btc_usd", "btc_aud", "btc_ltc"})
+ if err != nil {
+ t.Fatal(err)
+ }
expected := "btc_usd,btc_aud,btc_ltc"
if pairs.Join() != expected {
@@ -38,7 +47,10 @@ func TestPairsJoin(t *testing.T) {
}
func TestPairsFormat(t *testing.T) {
- pairs := NewPairsFromStrings([]string{"btc_usd", "btc_aud", "btc_ltc"})
+ pairs, err := NewPairsFromStrings([]string{"btc_usd", "btc_aud", "btc_ltc"})
+ if err != nil {
+ t.Fatal(err)
+ }
expected := "BTC-USD,BTC-AUD,BTC-LTC"
if pairs.Format("-", "", true).Join() != expected {
@@ -57,7 +69,10 @@ func TestPairsFormat(t *testing.T) {
expected, pairs.Format(":", "KRW", true).Join())
}
- pairs = NewPairsFromStrings([]string{"DASHKRW", "BTCKRW"})
+ pairs, err = NewPairsFromStrings([]string{"DASHKRW", "BTCKRW"})
+ if err != nil {
+ t.Fatal(err)
+ }
expected = "dash-krw,btc-krw"
if pairs.Format("-", "KRW", false).Join() != expected {
t.Errorf("Pairs Join() error expected %s but received %s",
@@ -106,10 +121,15 @@ func TestPairsUnmarshalJSON(t *testing.T) {
}
func TestPairsMarshalJSON(t *testing.T) {
+ pairs, err := NewPairsFromStrings([]string{"btc_usd", "btc_aud", "btc_ltc"})
+ if err != nil {
+ t.Fatal(err)
+ }
+
quickstruct := struct {
Pairs Pairs `json:"soManyPairs"`
}{
- Pairs: NewPairsFromStrings([]string{"btc_usd", "btc_aud", "btc_ltc"}),
+ Pairs: pairs,
}
encoded, err := json.Marshal(quickstruct)
@@ -176,12 +196,21 @@ func TestContains(t *testing.T) {
var pairs = Pairs{
NewPair(BTC, USD),
NewPair(LTC, USD),
+ NewPair(USD, ZRX),
}
if !pairs.Contains(NewPair(BTC, USD), true) {
t.Errorf("TestContains: Expected pair was not found")
}
+ if pairs.Contains(NewPair(USD, BTC), true) {
+ t.Errorf("TestContains: Unexpected pair was found")
+ }
+
+ if !pairs.Contains(NewPair(USD, BTC), false) {
+ t.Errorf("TestContains: Expected pair was not found")
+ }
+
if pairs.Contains(NewPair(ETH, USD), false) {
t.Errorf("TestContains: Non-existent pair was found")
}
diff --git a/currency/storage.go b/currency/storage.go
index 43b59f2c..4f5c7d60 100644
--- a/currency/storage.go
+++ b/currency/storage.go
@@ -23,8 +23,14 @@ func init() {
func (s *Storage) SetDefaults() {
s.defaultBaseCurrency = USD
s.baseCurrency = s.defaultBaseCurrency
- s.SetDefaultFiatCurrencies(USD, AUD, EUR, CNY)
- s.SetDefaultCryptocurrencies(BTC, LTC, ETH, DOGE, DASH, XRP, XMR)
+ err := s.SetDefaultFiatCurrencies(USD, AUD, EUR, CNY)
+ if err != nil {
+ log.Errorf(log.Global, "Currency Storage: Setting default fiat currencies error: %s", err)
+ }
+ err = s.SetDefaultCryptocurrencies(BTC, LTC, ETH, DOGE, DASH, XRP, XMR)
+ if err != nil {
+ log.Errorf(log.Global, "Currency Storage: Setting default cryptocurrencies error: %s", err)
+ }
s.SetupConversionRates()
s.fiatExchangeMarkets = forexprovider.NewDefaultFXProvider()
}
@@ -33,8 +39,9 @@ func (s *Storage) SetDefaults() {
// dump file and keep foreign exchange rates updated as fast as possible without
// triggering rate limiters, it will also run a full cryptocurrency check
// through coin market cap and expose analytics for exchange services
-func (s *Storage) RunUpdater(overrides BotOverrides, settings *MainConfiguration, filePath string, verbose bool) error {
+func (s *Storage) RunUpdater(overrides BotOverrides, settings *MainConfiguration, filePath string) error {
s.mtx.Lock()
+ s.shutdown = make(chan struct{})
if !settings.Cryptocurrencies.HasData() {
s.mtx.Unlock()
@@ -48,17 +55,17 @@ func (s *Storage) RunUpdater(overrides BotOverrides, settings *MainConfiguration
}
s.baseCurrency = settings.FiatDisplayCurrency
log.Debugf(log.Global,
- "Fiat display currency: %s.\n", s.baseCurrency)
+ "Fiat display currency: %s.\n",
+ s.baseCurrency)
if settings.CryptocurrencyProvider.Enabled {
- log.Debugln(
- log.Global,
+ log.Debugln(log.Global,
"Setting up currency analysis system with Coinmarketcap...")
c := &coinmarketcap.Coinmarketcap{}
c.SetDefaults()
err := c.Setup(coinmarketcap.Settings{
Name: settings.CryptocurrencyProvider.Name,
- Enabled: true,
+ Enabled: settings.CryptocurrencyProvider.Enabled,
AccountPlan: settings.CryptocurrencyProvider.AccountPlan,
APIkey: settings.CryptocurrencyProvider.APIkey,
Verbose: settings.CryptocurrencyProvider.Verbose,
@@ -174,16 +181,34 @@ func (s *Storage) SetupConversionRates() {
// SetDefaultFiatCurrencies assigns the default fiat currency list and adds it
// to the running list
-func (s *Storage) SetDefaultFiatCurrencies(c ...Code) {
+func (s *Storage) SetDefaultFiatCurrencies(c ...Code) error {
+ for i := range c {
+ err := s.currencyCodes.UpdateCurrency("", c[i].String(), "", 0, Fiat)
+ if err != nil {
+ return err
+ }
+ }
s.defaultFiatCurrencies = append(s.defaultFiatCurrencies, c...)
s.fiatCurrencies = append(s.fiatCurrencies, c...)
+ return nil
}
// SetDefaultCryptocurrencies assigns the default cryptocurrency list and adds
// it to the running list
-func (s *Storage) SetDefaultCryptocurrencies(c ...Code) {
+func (s *Storage) SetDefaultCryptocurrencies(c ...Code) error {
+ for i := range c {
+ err := s.currencyCodes.UpdateCurrency("",
+ c[i].String(),
+ "",
+ 0,
+ Cryptocurrency)
+ if err != nil {
+ return err
+ }
+ }
s.defaultCryptoCurrencies = append(s.defaultCryptoCurrencies, c...)
s.cryptocurrencies = append(s.cryptocurrencies, c...)
+ return nil
}
// SetupForexProviders sets up a new instance of the forex providers
@@ -228,7 +253,7 @@ func (s *Storage) ForeignExchangeUpdater() {
for {
select {
- case <-s.shutdownC:
+ case <-s.shutdown:
return
case <-SeedForeignExchangeTick.C:
@@ -248,36 +273,29 @@ func (s *Storage) ForeignExchangeUpdater() {
// SeedCurrencyAnalysisData sets a new instance of a coinmarketcap data.
func (s *Storage) SeedCurrencyAnalysisData() error {
- b, err := ioutil.ReadFile(s.path)
- if err != nil {
- err = s.FetchCurrencyAnalysisData()
+ if s.currencyCodes.LastMainUpdate.IsZero() {
+ b, err := ioutil.ReadFile(s.path)
if err != nil {
- return s.WriteCurrencyDataToFile(s.path, false)
+ return s.FetchCurrencyAnalysisData()
+ }
+ var f *File
+ err = json.Unmarshal(b, &f)
+ if err != nil {
+ return err
+ }
+ err = s.LoadFileCurrencyData(f)
+ if err != nil {
+ return err
}
-
- return s.WriteCurrencyDataToFile(s.path, true)
- }
-
- var fromFile File
- err = json.Unmarshal(b, &fromFile)
- if err != nil {
- return err
- }
-
- err = s.LoadFileCurrencyData(&fromFile)
- if err != nil {
- return err
}
// Based on update delay update the file
- if fromFile.LastMainUpdate.After(fromFile.LastMainUpdate.Add(s.currencyFileUpdateDelay)) ||
- fromFile.LastMainUpdate.IsZero() {
- err = s.FetchCurrencyAnalysisData()
+ if time.Now().After(s.currencyCodes.LastMainUpdate.Add(s.currencyFileUpdateDelay)) ||
+ s.currencyCodes.LastMainUpdate.IsZero() {
+ err := s.FetchCurrencyAnalysisData()
if err != nil {
- return s.WriteCurrencyDataToFile(s.path, false)
+ return err
}
-
- return s.WriteCurrencyDataToFile(s.path, true)
}
return nil
@@ -304,7 +322,7 @@ func (s *Storage) WriteCurrencyDataToFile(path string, mainUpdate bool) error {
if mainUpdate {
t := time.Now()
- data.LastMainUpdate = t
+ data.LastMainUpdate = t.Unix()
s.currencyCodes.LastMainUpdate = t
}
@@ -320,41 +338,62 @@ func (s *Storage) WriteCurrencyDataToFile(path string, mainUpdate bool) error {
// LoadFileCurrencyData loads currencies into the currency codes
func (s *Storage) LoadFileCurrencyData(f *File) error {
for i := range f.Contracts {
- err := s.currencyCodes.LoadItem(&f.Contracts[i])
+ contract := f.Contracts[i]
+ contract.Role = Contract
+ err := s.currencyCodes.LoadItem(&contract)
if err != nil {
return err
}
}
for i := range f.Cryptocurrency {
- err := s.currencyCodes.LoadItem(&f.Cryptocurrency[i])
+ crypto := f.Cryptocurrency[i]
+ crypto.Role = Cryptocurrency
+ err := s.currencyCodes.LoadItem(&crypto)
if err != nil {
return err
}
}
for i := range f.Token {
- err := s.currencyCodes.LoadItem(&f.Token[i])
+ token := f.Token[i]
+ token.Role = Token
+ err := s.currencyCodes.LoadItem(&token)
if err != nil {
return err
}
}
for i := range f.FiatCurrency {
- err := s.currencyCodes.LoadItem(&f.FiatCurrency[i])
+ fiat := f.FiatCurrency[i]
+ fiat.Role = Fiat
+ err := s.currencyCodes.LoadItem(&fiat)
if err != nil {
return err
}
}
for i := range f.UnsetCurrency {
- err := s.currencyCodes.LoadItem(&f.UnsetCurrency[i])
+ unset := f.UnsetCurrency[i]
+ unset.Role = Unset
+ err := s.currencyCodes.LoadItem(&unset)
if err != nil {
return err
}
}
- s.currencyCodes.LastMainUpdate = f.LastMainUpdate
+ switch t := f.LastMainUpdate.(type) {
+ case string:
+ parseT, err := time.Parse(time.RFC3339Nano, t)
+ if err != nil {
+ return err
+ }
+ s.currencyCodes.LastMainUpdate = parseT
+ case float64:
+ s.currencyCodes.LastMainUpdate = time.Unix(int64(t), 0)
+ default:
+ return errors.New("unhandled type conversion for LastMainUpdate time")
+ }
return nil
}
@@ -372,19 +411,22 @@ func (s *Storage) UpdateCurrencies() error {
}
if m[x].Platform.Symbol != "" {
- err := s.currencyCodes.UpdateToken(m[x].Name,
+ err = s.currencyCodes.UpdateCurrency(m[x].Name,
m[x].Symbol,
m[x].Platform.Symbol,
- m[x].ID)
+ m[x].ID,
+ Token)
if err != nil {
return err
}
continue
}
- err := s.currencyCodes.UpdateCryptocurrency(m[x].Name,
+ err = s.currencyCodes.UpdateCurrency(m[x].Name,
m[x].Symbol,
- m[x].ID)
+ "",
+ m[x].ID,
+ Cryptocurrency)
if err != nil {
return err
}
@@ -452,8 +494,7 @@ func (s *Storage) GetExchangeRates() (Conversions, error) {
func (s *Storage) SeedForeignExchangeRates() error {
s.fxRates.mtx.Lock()
defer s.fxRates.mtx.Unlock()
- rates, err := s.fiatExchangeMarkets.GetCurrencyData(
- s.baseCurrency.String(),
+ rates, err := s.fiatExchangeMarkets.GetCurrencyData(s.baseCurrency.String(),
s.fiatCurrencies.Strings())
if err != nil {
return err
@@ -463,15 +504,7 @@ func (s *Storage) SeedForeignExchangeRates() error {
// UpdateForeignExchangeRates sets exchange rates on the FX map
func (s *Storage) updateExchangeRates(m map[string]float64) error {
- err := s.fxRates.Update(m)
- if err != nil {
- return err
- }
-
- if s.path != "" {
- return s.WriteCurrencyDataToFile(s.path, false)
- }
- return nil
+ return s.fxRates.Update(m)
}
// SetupCryptoProvider sets congiguration parameters and starts a new instance
@@ -502,9 +535,9 @@ func (s *Storage) GetTotalMarketCryptocurrencies() (Currencies, error) {
// IsDefaultCurrency returns if a currency is a default currency
func (s *Storage) IsDefaultCurrency(c Code) bool {
- t, _ := GetTranslation(c)
for i := range s.defaultFiatCurrencies {
- if s.defaultFiatCurrencies[i].Match(c) || s.defaultFiatCurrencies[i].Match(t) {
+ if s.defaultFiatCurrencies[i].Match(c) ||
+ s.defaultFiatCurrencies[i].Match(GetTranslation(c)) {
return true
}
}
@@ -514,9 +547,9 @@ func (s *Storage) IsDefaultCurrency(c Code) bool {
// IsDefaultCryptocurrency returns if a cryptocurrency is a default
// cryptocurrency
func (s *Storage) IsDefaultCryptocurrency(c Code) bool {
- t, _ := GetTranslation(c)
- for _, d := range s.defaultCryptoCurrencies {
- if d.Match(c) || d.Match(t) {
+ for i := range s.defaultCryptoCurrencies {
+ if s.defaultCryptoCurrencies[i].Match(c) ||
+ s.defaultCryptoCurrencies[i].Match(GetTranslation(c)) {
return true
}
}
@@ -534,9 +567,9 @@ func (s *Storage) IsFiatCurrency(c Code) bool {
return false
}
- t, _ := GetTranslation(c)
- for _, d := range s.fiatCurrencies {
- if d.Match(c) || d.Match(t) {
+ for i := range s.fiatCurrencies {
+ if s.fiatCurrencies[i].Match(c) ||
+ s.fiatCurrencies[i].Match(GetTranslation(c)) {
return true
}
}
@@ -555,9 +588,9 @@ func (s *Storage) IsCryptocurrency(c Code) bool {
return false
}
- t, _ := GetTranslation(c)
- for _, d := range s.cryptocurrencies {
- if d.Match(c) || d.Match(t) {
+ for i := range s.cryptocurrencies {
+ if s.cryptocurrencies[i].Match(c) ||
+ s.cryptocurrencies[i].Match(GetTranslation(c)) {
return true
}
}
@@ -573,15 +606,12 @@ func (s *Storage) ValidateCode(newCode string) Code {
// ValidateFiatCode validates a fiat currency string and returns a currency
// code
-func (s *Storage) ValidateFiatCode(newCode string) (Code, error) {
- c, err := s.currencyCodes.RegisterFiat(newCode)
- if err != nil {
- return c, err
- }
+func (s *Storage) ValidateFiatCode(newCode string) Code {
+ c := s.currencyCodes.RegisterFiat(newCode)
if !s.fiatCurrencies.Contains(c) {
s.fiatCurrencies = append(s.fiatCurrencies, c)
}
- return c, nil
+ return c
}
// ValidateCryptoCode validates a cryptocurrency string and returns a currency
@@ -637,9 +667,9 @@ func (s *Storage) GetBaseCurrency() Code {
// UpdateEnabledCryptoCurrencies appends new cryptocurrencies to the enabled
// currency list
func (s *Storage) UpdateEnabledCryptoCurrencies(c Currencies) {
- for _, i := range c {
- if !s.cryptocurrencies.Contains(i) {
- s.cryptocurrencies = append(s.cryptocurrencies, i)
+ for i := range c {
+ if !s.cryptocurrencies.Contains(c[i]) {
+ s.cryptocurrencies = append(s.cryptocurrencies, c[i])
}
}
}
@@ -647,9 +677,10 @@ func (s *Storage) UpdateEnabledCryptoCurrencies(c Currencies) {
// UpdateEnabledFiatCurrencies appends new fiat currencies to the enabled
// currency list
func (s *Storage) UpdateEnabledFiatCurrencies(c Currencies) {
- for _, i := range c {
- if !s.fiatCurrencies.Contains(i) && !s.cryptocurrencies.Contains(i) {
- s.fiatCurrencies = append(s.fiatCurrencies, i)
+ for i := range c {
+ if !s.fiatCurrencies.Contains(c[i]) &&
+ !s.cryptocurrencies.Contains(c[i]) {
+ s.fiatCurrencies = append(s.fiatCurrencies, c[i])
}
}
}
@@ -709,3 +740,10 @@ func (s *Storage) NewConversion(from, to Code) (Conversion, error) {
func (s *Storage) IsVerbose() bool {
return s.Verbose
}
+
+// Shutdown shuts down the currency storage system and saves to currency.json
+func (s *Storage) Shutdown() error {
+ close(s.shutdown)
+ s.wg.Wait()
+ return s.WriteCurrencyDataToFile(s.path, true)
+}
diff --git a/currency/storage_test.go b/currency/storage_test.go
index b9e562bf..699f3d7d 100644
--- a/currency/storage_test.go
+++ b/currency/storage_test.go
@@ -6,7 +6,7 @@ func TestRunUpdater(t *testing.T) {
var newStorage Storage
emptyMainConfig := MainConfiguration{}
- err := newStorage.RunUpdater(BotOverrides{}, &emptyMainConfig, "", false)
+ err := newStorage.RunUpdater(BotOverrides{}, &emptyMainConfig, "")
if err == nil {
t.Fatal("storage RunUpdater() error cannot be nil")
}
@@ -16,12 +16,12 @@ func TestRunUpdater(t *testing.T) {
FiatDisplayCurrency: USD,
}
- err = newStorage.RunUpdater(BotOverrides{}, &mainConfig, "", false)
+ err = newStorage.RunUpdater(BotOverrides{}, &mainConfig, "")
if err == nil {
t.Fatal("storage RunUpdater() error cannot be nil")
}
- err = newStorage.RunUpdater(BotOverrides{}, &mainConfig, "/bla", false)
+ err = newStorage.RunUpdater(BotOverrides{}, &mainConfig, "/bla")
if err != nil {
t.Fatal("storage RunUpdater() error", err)
}
diff --git a/currency/storage_types.go b/currency/storage_types.go
index 032be5db..64020db0 100644
--- a/currency/storage_types.go
+++ b/currency/storage_types.go
@@ -56,7 +56,7 @@ type Storage struct {
foreignExchangeUpdateDelay time.Duration
mtx sync.Mutex
wg sync.WaitGroup
- shutdownC chan struct{}
+ shutdown chan struct{}
updaterRunning bool
Verbose bool
}
diff --git a/currency/translation.go b/currency/translation.go
index c2db7430..5b9075b0 100644
--- a/currency/translation.go
+++ b/currency/translation.go
@@ -2,12 +2,12 @@ package currency
// GetTranslation returns similar strings for a particular currency if not found
// returns the code back
-func GetTranslation(currency Code) (Code, bool) {
+func GetTranslation(currency Code) Code {
val, ok := translations[currency]
if !ok {
- return currency, ok
+ return currency
}
- return val, ok
+ return val
}
var translations = map[Code]Code{
diff --git a/currency/translation_test.go b/currency/translation_test.go
index 5124597b..95415b38 100644
--- a/currency/translation_test.go
+++ b/currency/translation_test.go
@@ -5,29 +5,21 @@ import "testing"
func TestGetTranslation(t *testing.T) {
currencyPair := NewPair(BTC, USD)
expected := XBT
- actual, ok := GetTranslation(currencyPair.Base)
- if !ok {
- t.Error("GetTranslation: failed to retrieve translation for BTC")
- }
-
+ actual := GetTranslation(currencyPair.Base)
if expected != actual {
t.Error("GetTranslation: translation result was different to expected result")
}
currencyPair.Base = NEO
- _, ok = GetTranslation(currencyPair.Base)
- if ok {
+ actual = GetTranslation(currencyPair.Base)
+ if actual != currencyPair.Base {
t.Error("GetTranslation: no error on non translatable currency")
}
expected = BTC
currencyPair.Base = XBT
- actual, ok = GetTranslation(currencyPair.Base)
- if !ok {
- t.Error("GetTranslation: failed to retrieve translation for BTC")
- }
-
+ actual = GetTranslation(currencyPair.Base)
if expected != actual {
t.Error("GetTranslation: translation result was different to expected result")
}
diff --git a/docs/ADD_NEW_EXCHANGE.md b/docs/ADD_NEW_EXCHANGE.md
index 169c44c8..ae69630a 100644
--- a/docs/ADD_NEW_EXCHANGE.md
+++ b/docs/ADD_NEW_EXCHANGE.md
@@ -49,7 +49,7 @@ Find out which asset types are supported by the exchange and add them to the pai
config.GetDefaultFilePath()
```
-```go
+```js
{
"name": "FTX",
"enabled": true,
@@ -61,37 +61,35 @@ config.GetDefaultFilePath()
"websocketOrderbookBufferLimit": 5,
"baseCurrencies": "USD",
"currencyPairs": {
- "assetTypes": [
- "spot",
- "futures"
- ],
- "pairs": {
- "futures": {
- "enabled": "BTC-PERP",
- "available": "BTC-PERP",
- "requestFormat": {
- "uppercase": true,
- "delimiter": "-"
- },
- "configFormat": {
- "uppercase": true,
- "delimiter": "-"
- }
+ "pairs": {
+ "futures": {
+ "assetEnabled": true,
+ "enabled": "BTC-PERP",
+ "available": "BTC-PERP",
+ "requestFormat": {
+ "uppercase": true,
+ "delimiter": "-"
},
- "spot": {
- "enabled": "BTC/USD",
- "available": "BTC/USD",
- "requestFormat": {
- "uppercase": true,
- "delimiter": "/"
- },
- "configFormat": {
- "uppercase": true,
- "delimiter": "/"
- }
+ "configFormat": {
+ "uppercase": true,
+ "delimiter": "-"
+ }
+ },
+ "spot": {
+ "assetEnabled": true,
+ "enabled": "BTC/USD",
+ "available": "BTC/USD",
+ "requestFormat": {
+ "uppercase": true,
+ "delimiter": "/"
+ },
+ "configFormat": {
+ "uppercase": true,
+ "delimiter": "/"
}
}
- },
+ }
+ },
"api": {
"authenticatedSupport": false,
"authenticatedWebsocketApiSupport": false,
@@ -177,6 +175,16 @@ Similar to the configs, spot support is inbuilt but other asset types will need
Delimiter: "-",
},
}
+
+ err := f.StoreAssetPairFormat(asset.Spot, spot)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
+ }
+
+ err = f.StoreAssetPairFormat(asset.Futures, futures)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
+ }
```
### Document the addition of the new exchange (FTX exchange is used as an example below):
@@ -645,16 +653,6 @@ The currency package contains many helper functions to format and process curren
### Websocket addition if exchange supports it:
-#### Add websocket to exchange struct in ftx.go
-
-```go
-// FTX is the overarching type across this package
-type FTX struct {
- exchange.Base
- WebsocketConn *wshandler.WebsocketConnection // Add this line
-}
-```
-
#### Websocket Setup:
- Set the websocket url in ftx_websocket.go that is provided in the documentation:
@@ -672,27 +670,35 @@ func (f *FTX) WsConnect() error {
return errors.New(wshandler.WebsocketNotEnabled)
}
var dialer websocket.Dialer
- err := f.WebsocketConn.Dial(&dialer, http.Header{})
+ err := f.Websocket.Conn.Dial(&dialer, http.Header{})
if err != nil {
return err
}
- f.WebsocketConn.SetupPingHandler(wshandler.WebsocketPingHandler{
+ // Can set up custom ping handler per websocket connection.
+ f.Websocket.Conn.SetupPingHandler(wshandler.WebsocketPingHandler{
MessageType: websocket.PingMessage,
Delay: ftxWebsocketTimer,
})
if f.Verbose {
log.Debugf(log.ExchangeSys, "%s Connected to Websocket.\n", f.Name)
}
+ // This reader routine is called prior to initiating a subscription for
+ // efficient processing.
go f.wsReadData()
if f.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
- err := f.WsAuth()
+ err = f.WsAuth()
if err != nil {
f.Websocket.DataHandler <- err
f.Websocket.SetCanUseAuthenticatedEndpoints(false)
}
}
- f.GenerateDefaultSubscriptions()
- return nil
+ // Generates the default subscription set, based off enabled pairs.
+ subs, err := f.GenerateDefaultSubscriptions()
+ if err != nil {
+ return err
+ }
+ // Finally subscribes to each individual channel.
+ return f.Websocket.SubscribeToChannels(subs)
}
```
@@ -700,22 +706,44 @@ func (f *FTX) WsConnect() error {
```go
// GenerateDefaultSubscriptions generates default subscription
-func (f *FTX) GenerateDefaultSubscriptions() {
- var channels = []string{wsTicker, wsTrades, wsOrderbook, wsMarkets, wsFills, wsOrders}
- var subscriptions []wshandler.WebsocketChannelSubscription
- for a := range f.CurrencyPairs.AssetTypes {
- pairs := f.GetEnabledPairs(f.CurrencyPairs.AssetTypes[a])
+func (f *FTX) GenerateDefaultSubscriptions() ([]stream.ChannelSubscription, error) {
+ var subscriptions []stream.ChannelSubscription
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
+ Channel: wsMarkets,
+ })
+ // Ranges over available channels, pairs and asset types to produce a full
+ // subscription list.
+ var channels = []string{wsTicker, wsTrades, wsOrderbook}
+ assets := f.GetAssetTypes()
+ for a := range assets {
+ pairs, err := f.GetEnabledPairs(assets[a])
+ if err != nil {
+ return nil, err
+ }
for z := range pairs {
- newPair := currency.NewPairWithDelimiter(pairs[z].Base.String(), pairs[z].Quote.String(), "-")
+ newPair := currency.NewPairWithDelimiter(pairs[z].Base.String(),
+ pairs[z].Quote.String(),
+ "-")
for x := range channels {
- subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
- Channel: channels[x],
- Currency: newPair,
- })
+ subscriptions = append(subscriptions,
+ stream.ChannelSubscription{
+ Channel: channels[x],
+ Currency: newPair,
+ Asset: assets[a],
+ })
}
}
}
- f.Websocket.SubscribeToChannels(subscriptions)
+ // Appends authenticated channels to the subscription list
+ if f.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
+ var authchan = []string{wsOrders, wsFills}
+ for x := range authchan {
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
+ Channel: authchan[x],
+ })
+ }
+ }
+ return subscriptions, nil
}
```
@@ -753,22 +781,47 @@ type WsSub struct {
```go
// Subscribe sends a websocket message to receive data from the channel
-func (f *FTX) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
- var sub WsSub
- a, err := f.GetPairAssetType(channelToSubscribe.Currency)
- if err != nil {
- return err
+func (f *FTX) Subscribe(channelsToSubscribe []stream.ChannelSubscription) error {
+ // For subscriptions we try to batch as much as possible to limit the amount
+ // of connection usage but sometimes this is not supported on the exchange
+ // API.
+ var errs common.Errors // This is an array of errors useful in the event that one channel subscription errors but we can subscribe to the next iteration.
+channels:
+ for i := range channelsToSubscribe {
+ // Type we declared above to send via our websocket connection.
+ var sub WsSub
+ sub.Channel = channelsToSubscribe[i].Channel
+ sub.Operation = subscribe
+
+ switch channelsToSubscribe[i].Channel {
+ case wsFills, wsOrders, wsMarkets:
+ // Authenticated wsFills && wsOrders or wsMarkets which is a channel subscription for the full set of tradable markets do not need a currency pair association.
+ default:
+ a, err := f.GetPairAssetType(channelsToSubscribe[i].Currency)
+ if err != nil {
+ errs = append(errs, err)
+ continue channels
+ }
+ // Ensures our outbound currency pair is formatted correctly, sometimes our configuration format is different from what our request format needs to be.
+ formattedPair, err := f.FormatExchangeCurrency(channelsToSubscribe[i].Currency, a)
+ if err != nil {
+ errs = append(errs, err)
+ continue channels
+ }
+ sub.Market = formattedPair.String()
+ }
+ err := f.Websocket.Conn.SendJSONMessage(sub)
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ // When we have a successful subscription, we can alert our internal management system of the success.
+ f.Websocket.AddSuccessfulSubscriptions(channelsToSubscribe[i])
}
- switch channelToSubscribe.Channel {
- case wsFills, wsOrders:
- sub.Operation = "subscribe"
- sub.Channel = channelToSubscribe.Channel
- default:
- sub.Operation = "subscribe"
- sub.Channel = channelToSubscribe.Channel
- sub.Market = f.FormatExchangeCurrency(channelToSubscribe.Currency, a).String()
+ if errs != nil {
+ return errs
}
- return f.WebsocketConn.SendJSONMessage(sub)
+ return nil
}
```
@@ -782,7 +835,7 @@ Run gocryptotrader with the following settings enabled in config
},
"enabled": {
"autoPairUpdates": true,
- "websocketAPI": true
+ "websocketAPI": true // <- Change this to true if it is false
```
#### Handle websocket data:
@@ -800,13 +853,12 @@ func (f *FTX) wsReadData() {
case <-f.Websocket.ShutdownC:
return
default:
- resp, err := f.WebsocketConn.ReadMessage()
- if err != nil {
- f.Websocket.ReadMessageErrors <- err
+ resp := f.Websocket.Conn.ReadMessage()
+ if resp.Raw == nil {
return
}
- f.Websocket.TrafficAlert <- struct{}{}
- err = f.wsHandleData(resp.Raw)
+
+ err := f.wsHandleData(resp.Raw)
if err != nil {
f.Websocket.DataHandler <- err
}
@@ -963,7 +1015,7 @@ func (f *FTX) WsAuth() error {
Time: intNonce,
},
}
- return f.WebsocketConn.SendJSONMessage(req)
+ return f.Websocket.Conn.SendJSONMessage(req)
}
```
@@ -971,16 +1023,42 @@ func (f *FTX) WsAuth() error {
```go
// Unsubscribe sends a websocket message to stop receiving data from the channel
-func (f *FTX) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
- var unSub WsSub
- a, err := f.GetPairAssetType(channelToSubscribe.Currency)
- if err != nil {
- return err
+func (f *FTX) Unsubscribe(channelsToUnsubscribe []stream.ChannelSubscription) error {
+ // As with subscribing we want to batch as much as possible, but sometimes this cannot be achieved due to API shortfalls.
+ var errs common.Errors
+channels:
+ for i := range channelsToUnsubscribe {
+ var unSub WsSub
+ unSub.Operation = unsubscribe
+ unSub.Channel = channelsToUnsubscribe[i].Channel
+ switch channelsToUnsubscribe[i].Channel {
+ case wsFills, wsOrders, wsMarkets:
+ default:
+ a, err := f.GetPairAssetType(channelsToUnsubscribe[i].Currency)
+ if err != nil {
+ errs = append(errs, err)
+ continue channels
+ }
+
+ formattedPair, err := f.FormatExchangeCurrency(channelsToUnsubscribe[i].Currency, a)
+ if err != nil {
+ errs = append(errs, err)
+ continue channels
+ }
+ unSub.Market = formattedPair.String()
+ }
+ err := f.Websocket.Conn.SendJSONMessage(unSub)
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ // When we have a successful unsubscription, we can alert our internal management system of the success.
+ f.Websocket.RemoveSuccessfulUnsubscriptions(channelsToUnsubscribe[i])
}
- unSub.Operation = "unsubscribe"
- unSub.Channel = channelToSubscribe.Channel
- unSub.Market = f.FormatExchangeCurrency(channelToSubscribe.Currency, a).String()
- return f.WebsocketConn.SendJSONMessage(unSub)
+ if errs != nil {
+ return errs
+ }
+ return nil
}
```
@@ -989,24 +1067,53 @@ func (f *FTX) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscript
Add websocket functionality if supported to Setup:
```go
- err = f.Websocket.Setup(
- &wshandler.WebsocketSetup{
- Enabled: exch.Features.Enabled.Websocket,
- Verbose: exch.Verbose,
- AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
- WebsocketTimeout: exch.WebsocketTrafficTimeout,
- DefaultURL: ftxWSURL,
- ExchangeName: exch.Name,
- RunningURL: exch.API.Endpoints.WebsocketURL,
- Connector: f.WsConnect,
- Subscriber: f.Subscribe,
- UnSubscriber: f.Unsubscribe,
- Features: &f.Features.Supports.WebsocketCapabilities,
- })
+// Setup takes in the supplied exchange configuration details and sets params
+func (f *FTX) Setup(exch *config.ExchangeConfig) error {
+ if !exch.Enabled {
+ f.SetEnabled(false)
+ return nil
+ }
+
+ err := f.SetupDefaults(exch)
if err != nil {
return err
- }
- ```
+ }
+
+ // Websocket details setup below
+ err = f.Websocket.Setup(&stream.WebsocketSetup{
+ Enabled: exch.Features.Enabled.Websocket,
+ Verbose: exch.Verbose,
+ AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
+ WebsocketTimeout: exch.WebsocketTrafficTimeout,
+ DefaultURL: ftxWSURL, // Default ws endpoint so we can roll back via CLI if needed.
+ ExchangeName: exch.Name, // Sets websocket name to the exchange name.
+ RunningURL: exch.API.Endpoints.WebsocketURL,
+ Connector: f.WsConnect, // Connector function outlined above.
+ Subscriber: f.Subscribe, // Subscriber function outlined above.
+ UnSubscriber: f.Unsubscribe, // Unsubscriber function outlined above.
+ GenerateSubscriptions: f.GenerateDefaultSubscriptions, // GenerateDefaultSubscriptions function outlined above.
+ Features: &f.Features.Supports.WebsocketCapabilities, // Defines the capabilities of the websocket outlined in supported features struct. This allows the websocket connection to be flushed appropriately if we have a pair/asset enable/disable change. This is outlined below.
+
+ // Orderbook buffer specific variables for processing orderbook updates via websocket feed.
+ OrderbookBufferLimit: exch.WebsocketOrderbookBufferLimit,
+ // Other orderbook buffer vars:
+ // BufferEnabled bool
+ // SortBuffer bool
+ // SortBufferByUpdateIDs bool
+ // UpdateEntriesByID bool
+ })
+ if err != nil {
+ return err
+ }
+ // Sets up a new connection for the websocket, there are two separate connections denoted by the ConnectionSetup struct auth bool.
+ return f.Websocket.SetupNewConnection(stream.ConnectionSetup{
+ ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
+ ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
+ // RateLimit int64 rudimentary rate limit that sleeps connection in milliseconds before sending designated payload
+ // Authenticated bool sets if the connection is dedicated for an authenticated websocket stream which can be accessed from the Websocket field variable AuthConn e.g. f.Websocket.AuthConn
+ })
+}
+```
Below are the features supported by FTX API protocol:
@@ -1053,32 +1160,35 @@ Below are the features supported by FTX API protocol:
Initially the functions return nil or common.ErrNotYetImplemented
```go
-// GetWebsocket returns a pointer to the exchange websocket
-func (f *FTX) GetWebsocket() (*wshandler.Websocket, error) {
- return f.Websocket, nil
-}
-
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func (f *FTX) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- f.Websocket.SubscribeToChannels(channels)
- return nil
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func (f *FTX) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- f.Websocket.RemoveSubscribedChannels(channels)
- return nil
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func (f *FTX) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return f.Websocket.GetSubscriptions(), nil
-}
-
// AuthenticateWebsocket sends an authentication message to the websocket
func (f *FTX) AuthenticateWebsocket() error {
return f.WsAuth()
}
-```
\ No newline at end of file
+```
+
+
+## Last but not least - Live testing
+
+### Live testing websocket via [gctcli](../cmd/gctcli/main.go)
+
+Please test all `websocket` commands below whilst a GoCryptoTrader instance is running and with the exchange websocket setting enabled:
+
+- `getinfo` to ensure fetching websocket information is possible (that the websocket connection is enabled, connected and is running).
+- `disable/enable` to ensure disabling/enabling a websocket connection disconnects/connects accordingly.
+- `getsubs` to ensure the subscriptions are in sync with the exchange's config settings or by manual subscriptions added/removed via `gctcli`.
+- `setproxy` to ensure that a proxy can be set and resets the websocket connection accordingly.
+- `seturl` to ensure that a new websocket URL can be set in the event of an API endpoint change whilst an instance of GoCryptoTrader is already running.
+
+Please test all `pair` commands to disable and enable different assets types to witness subscriptions and unsubscriptions:
+
+- `get` to ensure correct enabled and disabled pairs for a supported asset type.
+- `disableasset` to ensure disabling of entire asset class and associated unsubscriptions.
+- `enableasset` to ensure correct enabling of entire asset class and associated subscriptions.
+- `disable` to ensure correct disabling of pair(s) and and associated unsubscriptions.
+- `enable` to ensure correct enabling of pair(s) and associated subscriptions.
+- `enableall` to ensure correct enabling of all pairs for an asset type and associated subscriptions.
+- `disableall` to ensure correct disabling of all pairs for an asset type and associated unsubscriptions.
+
+## Open a PR
+
+Submitting a PR is easy and all are welcome additions to the public repository. Submit via github.com/thrasher-corp/gocryptotrader or contact our team via slack for more information.
\ No newline at end of file
diff --git a/engine/engine.go b/engine/engine.go
index e01ec2d8..303c3dbc 100644
--- a/engine/engine.go
+++ b/engine/engine.go
@@ -385,8 +385,7 @@ func (e *Engine) Start() error {
CurrencyDelay: e.Config.Currency.CurrencyFileUpdateDuration,
FxRateDelay: e.Config.Currency.ForeignExchangeUpdateDuration,
},
- e.Settings.DataDir,
- e.Settings.Verbose)
+ e.Settings.DataDir)
if err != nil {
gctlog.Errorf(gctlog.Global, "Currency updater system failed to start %v", err)
}
@@ -514,6 +513,10 @@ func (e *Engine) Stop() {
}
}
+ if err := currency.ShutdownStorageUpdater(); err != nil {
+ gctlog.Errorf(gctlog.Global, "Currency storage system. Error: %v", err)
+ }
+
if !e.Settings.EnableDryRun {
err := e.Config.SaveConfig(e.Settings.ConfigFile, false)
if err != nil {
diff --git a/engine/events.go b/engine/events.go
index 993b5101..f614f9fb 100644
--- a/engine/events.go
+++ b/engine/events.go
@@ -72,7 +72,7 @@ var Events []*Event
// Add adds an event to the Events chain and returns an index/eventID
// and an error
-func Add(exchange, item string, condition EventConditionParams, currencyPair currency.Pair, asset asset.Item, action string) (int64, error) {
+func Add(exchange, item string, condition EventConditionParams, p currency.Pair, a asset.Item, action string) (int64, error) {
err := IsValidEvent(exchange, item, condition, action)
if err != nil {
return 0, err
@@ -89,8 +89,8 @@ func Add(exchange, item string, condition EventConditionParams, currencyPair cur
evt.Exchange = exchange
evt.Item = item
evt.Condition = condition
- evt.Pair = currencyPair
- evt.Asset = asset
+ evt.Pair = p
+ evt.Asset = a
evt.Action = action
evt.Executed = false
Events = append(Events, evt)
@@ -99,8 +99,8 @@ func Add(exchange, item string, condition EventConditionParams, currencyPair cur
// Remove deletes and event by its ID
func Remove(eventID int64) bool {
- for i, x := range Events {
- if x.ID == eventID {
+ for i := range Events {
+ if Events[i].ID == eventID {
Events = append(Events[:i], Events[i+1:]...)
return true
}
@@ -112,9 +112,8 @@ func Remove(eventID int64) bool {
// events that have been executed.
func GetEventCounter() (total, executed int) {
total = len(Events)
-
- for _, x := range Events {
- if x.Executed {
+ for i := range Events {
+ if Events[i].Executed {
executed++
}
}
@@ -126,11 +125,10 @@ func (e *Event) ExecuteAction() bool {
if strings.Contains(e.Action, ",") {
action := strings.Split(e.Action, ",")
if action[0] == ActionSMSNotify {
- message := fmt.Sprintf("Event triggered: %s\n", e.String())
if action[1] == "ALL" {
Bot.CommsManager.PushEvent(base.Event{
Type: "event",
- Message: message,
+ Message: "Event triggered: " + e.String(),
})
}
}
diff --git a/engine/events_test.go b/engine/events_test.go
index ea1d9ce8..5846d3ca 100644
--- a/engine/events_test.go
+++ b/engine/events_test.go
@@ -138,10 +138,11 @@ func TestProcessTicker(t *testing.T) {
// now populate it with a 0 entry
tick := ticker.Price{
- Pair: currency.NewPair(currency.BTC, currency.USD),
- Last: 0,
+ Pair: currency.NewPair(currency.BTC, currency.USD),
+ ExchangeName: e.Exchange,
+ AssetType: e.Asset,
}
- if err := ticker.ProcessTicker(e.Exchange, &tick, e.Asset); err != nil {
+ if err := ticker.ProcessTicker(&tick); err != nil {
t.Fatal("unexpected result:", err)
}
if r := e.processTicker(); r {
@@ -150,7 +151,7 @@ func TestProcessTicker(t *testing.T) {
// now populate it with a number > 0
tick.Last = 1337
- if err := ticker.ProcessTicker(e.Exchange, &tick, e.Asset); err != nil {
+ if err := ticker.ProcessTicker(&tick); err != nil {
t.Fatal("unexpected result:", err)
}
if r := e.processTicker(); !r {
diff --git a/engine/exchange.go b/engine/exchange.go
index e42ca7c3..5c677ef9 100644
--- a/engine/exchange.go
+++ b/engine/exchange.go
@@ -6,6 +6,7 @@ import (
"sync"
"github.com/thrasher-corp/gocryptotrader/common"
+ "github.com/thrasher-corp/gocryptotrader/currency"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/binance"
"github.com/thrasher-corp/gocryptotrader/exchanges/bitfinex"
@@ -237,7 +238,11 @@ func LoadExchange(name string, useWG bool, wg *sync.WaitGroup) error {
dryrunParamInteraction("enableallpairs")
assets := exchCfg.CurrencyPairs.GetAssetTypes()
for x := range assets {
- pairs := exchCfg.CurrencyPairs.GetPairs(assets[x], false)
+ var pairs currency.Pairs
+ pairs, err = exchCfg.CurrencyPairs.GetPairs(assets[x], false)
+ if err != nil {
+ return err
+ }
exchCfg.CurrencyPairs.StorePairs(assets[x], pairs, true)
}
}
diff --git a/engine/fake_exchange_test.go b/engine/fake_exchange_test.go
index d7f00df6..26905ceb 100644
--- a/engine/fake_exchange_test.go
+++ b/engine/fake_exchange_test.go
@@ -12,8 +12,8 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -89,11 +89,11 @@ func (h *FakePassingExchange) FetchTradablePairs(_ asset.Item) ([]string, error)
}
func (h *FakePassingExchange) UpdateTradablePairs(_ bool) error { return nil }
-func (h *FakePassingExchange) GetEnabledPairs(_ asset.Item) currency.Pairs {
- return currency.Pairs{}
+func (h *FakePassingExchange) GetEnabledPairs(_ asset.Item) (currency.Pairs, error) {
+ return currency.Pairs{}, nil
}
-func (h *FakePassingExchange) GetAvailablePairs(_ asset.Item) currency.Pairs {
- return currency.Pairs{}
+func (h *FakePassingExchange) GetAvailablePairs(_ asset.Item) (currency.Pairs, error) {
+ return currency.Pairs{}, nil
}
func (h *FakePassingExchange) FetchAccountInfo() (account.Holdings, error) {
return account.Holdings{}, nil
@@ -142,6 +142,11 @@ func (h *FakePassingExchange) GetOrderHistory(_ *order.GetOrdersRequest) ([]orde
return nil, nil
}
func (h *FakePassingExchange) GetActiveOrders(_ *order.GetOrdersRequest) ([]order.Detail, error) {
+ pair, err := currency.NewPairFromString("BTCUSD")
+ if err != nil {
+ return nil, err
+ }
+
return []order.Detail{
{
Price: 1337,
@@ -153,25 +158,25 @@ func (h *FakePassingExchange) GetActiveOrders(_ *order.GetOrdersRequest) ([]orde
Status: order.Active,
AssetType: asset.Spot,
Date: time.Now(),
- Pair: currency.NewPairFromString("BTCUSD"),
+ Pair: pair,
},
}, nil
}
-func (h *FakePassingExchange) SetHTTPClientUserAgent(_ string) {}
-func (h *FakePassingExchange) GetHTTPClientUserAgent() string { return "" }
-func (h *FakePassingExchange) SetClientProxyAddress(_ string) error { return nil }
-func (h *FakePassingExchange) SupportsWebsocket() bool { return true }
-func (h *FakePassingExchange) SupportsREST() bool { return true }
-func (h *FakePassingExchange) IsWebsocketEnabled() bool { return true }
-func (h *FakePassingExchange) GetWebsocket() (*wshandler.Websocket, error) { return nil, nil }
-func (h *FakePassingExchange) SubscribeToWebsocketChannels(_ []wshandler.WebsocketChannelSubscription) error {
+func (h *FakePassingExchange) SetHTTPClientUserAgent(_ string) {}
+func (h *FakePassingExchange) GetHTTPClientUserAgent() string { return "" }
+func (h *FakePassingExchange) SetClientProxyAddress(_ string) error { return nil }
+func (h *FakePassingExchange) SupportsWebsocket() bool { return true }
+func (h *FakePassingExchange) SupportsREST() bool { return true }
+func (h *FakePassingExchange) IsWebsocketEnabled() bool { return true }
+func (h *FakePassingExchange) GetWebsocket() (*stream.Websocket, error) { return nil, nil }
+func (h *FakePassingExchange) SubscribeToWebsocketChannels(_ []stream.ChannelSubscription) error {
return nil
}
-func (h *FakePassingExchange) UnsubscribeToWebsocketChannels(_ []wshandler.WebsocketChannelSubscription) error {
+func (h *FakePassingExchange) UnsubscribeToWebsocketChannels(_ []stream.ChannelSubscription) error {
return nil
}
func (h *FakePassingExchange) AuthenticateWebsocket() error { return nil }
-func (h *FakePassingExchange) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
+func (h *FakePassingExchange) GetSubscriptions() ([]stream.ChannelSubscription, error) {
return nil, nil
}
func (h *FakePassingExchange) GetDefaultConfig() (*config.ExchangeConfig, error) { return nil, nil }
diff --git a/engine/helpers.go b/engine/helpers.go
index cab09c92..93d873fa 100644
--- a/engine/helpers.go
+++ b/engine/helpers.go
@@ -292,8 +292,7 @@ func MapCurrenciesByExchange(p currency.Pairs, enabledExchangesOnly bool, assetT
continue
}
exchName := Bot.Config.Exchanges[y].Name
- success, err := Bot.Config.SupportsPair(exchName, p[x], assetType)
- if err != nil || !success {
+ if !Bot.Config.SupportsPair(exchName, p[x], assetType) {
continue
}
@@ -324,14 +323,10 @@ func GetExchangeNamesByCurrency(p currency.Pair, enabled bool, assetType asset.I
}
exchName := Bot.Config.Exchanges[x].Name
- success, err := Bot.Config.SupportsPair(exchName, p, assetType)
- if err != nil {
+ if !Bot.Config.SupportsPair(exchName, p, assetType) {
continue
}
-
- if success {
- exchanges = append(exchanges, exchName)
- }
+ exchanges = append(exchanges, exchName)
}
return exchanges
}
@@ -404,19 +399,18 @@ func GetRelatableCurrencies(p currency.Pair, incOrig, incUSDT bool) currency.Pai
addPair(p)
}
- first, ok := currency.GetTranslation(p.Base)
- if ok {
+ first := currency.GetTranslation(p.Base)
+ if first != p.Base {
addPair(currency.NewPair(first, p.Quote))
- var second currency.Code
- second, ok = currency.GetTranslation(p.Quote)
- if ok {
+ second := currency.GetTranslation(p.Quote)
+ if second != p.Quote {
addPair(currency.NewPair(first, second))
}
}
- second, ok := currency.GetTranslation(p.Quote)
- if ok {
+ second := currency.GetTranslation(p.Quote)
+ if second != p.Quote {
addPair(currency.NewPair(p.Base, second))
}
}
@@ -483,8 +477,8 @@ func GetCollatedExchangeAccountInfoByCoin(accounts []account.Holdings) map[curre
// GetExchangeHighestPriceByCurrencyPair returns the exchange with the highest
// price for a given currency pair and asset type
-func GetExchangeHighestPriceByCurrencyPair(p currency.Pair, assetType asset.Item) (string, error) {
- result := stats.SortExchangesByPrice(p, assetType, true)
+func GetExchangeHighestPriceByCurrencyPair(p currency.Pair, a asset.Item) (string, error) {
+ result := stats.SortExchangesByPrice(p, a, true)
if len(result) == 0 {
return "", fmt.Errorf("no stats for supplied currency pair and asset type")
}
@@ -717,7 +711,14 @@ func GetAllActiveTickers() []EnabledExchangeCurrencies {
exchangeTicker.ExchangeName = exchName
for y := range assets {
- currencies := exchanges[x].GetEnabledPairs(assets[y])
+ currencies, err := exchanges[x].GetEnabledPairs(assets[y])
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "Exchange %s could not retrieve enabled currencies. Err: %s\n",
+ exchName,
+ err)
+ continue
+ }
for z := range currencies {
tp, err := exchanges[x].FetchTicker(currencies[z], assets[y])
if err != nil {
@@ -739,19 +740,25 @@ func GetAllEnabledExchangeAccountInfo() AllEnabledExchangeAccounts {
var response AllEnabledExchangeAccounts
exchanges := GetExchanges()
for x := range exchanges {
- if !exchanges[x].GetAuthenticatedAPISupport(exchange.RestAuthentication) {
- if Bot.Settings.Verbose {
- log.Debugf(log.ExchangeSys, "GetAllEnabledExchangeAccountInfo: Skippping %s due to disabled authenticated API support.\n", exchanges[x].GetName())
+ if exchanges[x] != nil && exchanges[x].IsEnabled() {
+ if !exchanges[x].GetAuthenticatedAPISupport(exchange.RestAuthentication) {
+ if Bot.Settings.Verbose {
+ log.Debugf(log.ExchangeSys,
+ "GetAllEnabledExchangeAccountInfo: Skippping %s due to disabled authenticated API support.\n",
+ exchanges[x].GetName())
+ }
+ continue
}
- continue
+ accountInfo, err := exchanges[x].FetchAccountInfo()
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "Error encountered retrieving exchange account info for %s. Error %s\n",
+ exchanges[x].GetName(),
+ err)
+ continue
+ }
+ response.Data = append(response.Data, accountInfo)
}
- accountInfo, err := exchanges[x].FetchAccountInfo()
- if err != nil {
- log.Errorf(log.ExchangeSys, "Error encountered retrieving exchange account info for %s. Error %s\n",
- exchanges[x].GetName(), err)
- continue
- }
- response.Data = append(response.Data, accountInfo)
}
return response
}
diff --git a/engine/helpers_test.go b/engine/helpers_test.go
index b4a83283..30e404d1 100644
--- a/engine/helpers_test.go
+++ b/engine/helpers_test.go
@@ -171,136 +171,225 @@ func TestGetSpecificAvailablePairs(t *testing.T) {
assetType := asset.Spot
result := GetSpecificAvailablePairs(true, true, true, false, assetType)
- if !result.Contains(currency.NewPairFromStrings("BTC", "USD"), true) {
+ btsusd, err := currency.NewPairFromStrings("BTC", "USD")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if !result.Contains(btsusd, true) {
t.Fatal("Unexpected result")
}
- if !result.Contains(currency.NewPairFromStrings("BTC", "USDT"), false) {
+ btcusdt, err := currency.NewPairFromStrings("BTC", "USDT")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if !result.Contains(btcusdt, false) {
t.Fatal("Unexpected result")
}
result = GetSpecificAvailablePairs(true, true, false, false, assetType)
- if result.Contains(currency.NewPairFromStrings("BTC", "USDT"), false) {
+ if result.Contains(btcusdt, false) {
t.Fatal("Unexpected result")
}
+ ltcbtc, err := currency.NewPairFromStrings("LTC", "BTC")
+ if err != nil {
+ t.Fatal(err)
+ }
+
result = GetSpecificAvailablePairs(true, false, false, true, assetType)
- if !result.Contains(currency.NewPairFromStrings("LTC", "BTC"), false) {
+ if !result.Contains(ltcbtc, false) {
t.Fatal("Unexpected result")
}
}
func TestIsRelatablePairs(t *testing.T) {
SetupTestHelpers(t)
+ xbtusd, err := currency.NewPairFromStrings("XBT", "USD")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ btcusd, err := currency.NewPairFromStrings("BTC", "USD")
+ if err != nil {
+ t.Fatal(err)
+ }
// Test relational pairs with similar names
- result := IsRelatablePairs(currency.NewPairFromStrings("XBT", "USD"),
- currency.NewPairFromStrings("BTC", "USD"), false)
+ result := IsRelatablePairs(xbtusd, btcusd, false)
if !result {
t.Fatal("Unexpected result")
}
// Test relational pairs with similar names reversed
- result = IsRelatablePairs(currency.NewPairFromStrings("BTC", "USD"),
- currency.NewPairFromStrings("XBT", "USD"), false)
+ result = IsRelatablePairs(btcusd, xbtusd, false)
if !result {
t.Fatal("Unexpected result")
}
+ btcusdt, err := currency.NewPairFromStrings("BTC", "USDT")
+ if err != nil {
+ t.Fatal(err)
+ }
+
// Test relational pairs with similar names but with Tether support disabled
- result = IsRelatablePairs(currency.NewPairFromStrings("XBT", "USD"),
- currency.NewPairFromStrings("BTC", "USDT"), false)
+ result = IsRelatablePairs(xbtusd, btcusdt, false)
if result {
t.Fatal("Unexpected result")
}
+ xbtusdt, err := currency.NewPairFromStrings("XBT", "USDT")
+ if err != nil {
+ t.Fatal(err)
+ }
+
// Test relational pairs with similar names but with Tether support enabled
- result = IsRelatablePairs(currency.NewPairFromStrings("XBT", "USDT"),
- currency.NewPairFromStrings("BTC", "USD"), true)
+ result = IsRelatablePairs(xbtusdt, btcusd, true)
if !result {
t.Fatal("Unexpected result")
}
+ aeusdt, err := currency.NewPairFromStrings("AE", "USDT")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ usdtae, err := currency.NewPairDelimiter("USDT-AE", "-")
+ if err != nil {
+ t.Fatal(err)
+ }
+
// Test relational pairs with different ordering, a delimiter and with
// Tether support enabled
- result = IsRelatablePairs(currency.NewPairFromStrings("AE", "USDT"),
- currency.NewPairDelimiter("USDT-AE", "-"), true)
+ result = IsRelatablePairs(aeusdt, usdtae, true)
if !result {
t.Fatal("Unexpected result")
}
// Test relational pairs with different ordering, a delimiter and with
// Tether support disabled
- result = IsRelatablePairs(currency.NewPairFromStrings("AE", "USDT"),
- currency.NewPairDelimiter("USDT-AE", "-"), false)
+ result = IsRelatablePairs(aeusdt, usdtae, false)
if !result {
t.Fatal("Unexpected result")
}
+ xbteur, err := currency.NewPairFromStrings("XBT", "EUR")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ btcaud, err := currency.NewPairFromStrings("BTC", "AUD")
+ if err != nil {
+ t.Fatal(err)
+ }
+
// Test relationl pairs with similar names and different fiat currencies
- result = IsRelatablePairs(currency.NewPairFromStrings("XBT", "EUR"),
- currency.NewPairFromStrings("BTC", "AUD"), false)
+ result = IsRelatablePairs(xbteur, btcaud, false)
if !result {
t.Fatal("Unexpected result")
}
+ usdbtc, err := currency.NewPairFromStrings("USD", "BTC")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ btceur, err := currency.NewPairFromStrings("BTC", "EUR")
+ if err != nil {
+ t.Fatal(err)
+ }
+
// Test relationl pairs with similar names, different fiat currencies and
// with different ordering
- result = IsRelatablePairs(currency.NewPairFromStrings("USD", "BTC"),
- currency.NewPairFromStrings("BTC", "EUR"), false)
+ result = IsRelatablePairs(usdbtc, btceur, false)
if !result { // Is this really expected result???
t.Fatal("Unexpected result")
}
// Test relationl pairs with similar names, different fiat currencies and
// with Tether enabled
- result = IsRelatablePairs(currency.NewPairFromStrings("USD", "BTC"),
- currency.NewPairFromStrings("BTC", "USDT"), true)
+ result = IsRelatablePairs(usdbtc, btcusdt, true)
if !result {
t.Fatal("Unexpected result")
}
+ ltcbtc, err := currency.NewPairFromStrings("LTC", "BTC")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ btcltc, err := currency.NewPairFromStrings("BTC", "LTC")
+ if err != nil {
+ t.Fatal(err)
+ }
+
// Test relationl crypto pairs with similar names
- result = IsRelatablePairs(currency.NewPairFromStrings("LTC", "BTC"),
- currency.NewPairFromStrings("BTC", "LTC"), false)
+ result = IsRelatablePairs(ltcbtc, btcltc, false)
if !result {
t.Fatal("Unexpected result")
}
+ ltceth, err := currency.NewPairFromStrings("LTC", "ETH")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ btceth, err := currency.NewPairFromStrings("BTC", "ETH")
+ if err != nil {
+ t.Fatal(err)
+ }
+
// Test relationl crypto pairs with similar different pairs
- result = IsRelatablePairs(currency.NewPairFromStrings("LTC", "ETH"),
- currency.NewPairFromStrings("BTC", "ETH"), false)
+ result = IsRelatablePairs(ltceth, btceth, false)
if result {
t.Fatal("Unexpected result")
}
// Test relationl crypto pairs with similar different pairs and with USDT
// enabled
- result = IsRelatablePairs(currency.NewPairFromStrings("USDT", "USD"),
- currency.NewPairFromStrings("BTC", "USD"), true)
+ usdtusd, err := currency.NewPairFromStrings("USDT", "USD")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ result = IsRelatablePairs(usdtusd, btcusd, true)
if result {
t.Fatal("Unexpected result")
}
+ xbtltc, err := currency.NewPairFromStrings("XBT", "LTC")
+ if err != nil {
+ t.Fatal(err)
+ }
+
// Test relationl crypto pairs with with similar names
- result = IsRelatablePairs(currency.NewPairFromStrings("XBT", "LTC"),
- currency.NewPairFromStrings("BTC", "LTC"), false)
+ result = IsRelatablePairs(xbtltc, btcltc, false)
if !result {
t.Fatal("Unexpected result")
}
+ ltcxbt, err := currency.NewPairFromStrings("LTC", "XBT")
+ if err != nil {
+ t.Fatal(err)
+ }
+
// Test relationl crypto pairs with different ordering and similar names
- result = IsRelatablePairs(currency.NewPairFromStrings("LTC", "XBT"),
- currency.NewPairFromStrings("BTC", "LTC"), false)
+ result = IsRelatablePairs(ltcxbt, btcltc, false)
if !result {
t.Fatal("Unexpected result")
}
// Test edge case between two pairs when currency translations were causing
// non-relational pairs to be relatable
- result = IsRelatablePairs(currency.NewPairFromStrings("EUR", "USD"),
- currency.NewPairFromStrings("BTC", "USD"), false)
+ eurusd, err := currency.NewPairFromStrings("EUR", "USD")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ result = IsRelatablePairs(eurusd, btcusd, false)
if result {
t.Fatal("Unexpected result")
}
@@ -308,44 +397,80 @@ func TestIsRelatablePairs(t *testing.T) {
func TestGetRelatableCryptocurrencies(t *testing.T) {
SetupTestHelpers(t)
- p := GetRelatableCryptocurrencies(currency.NewPairFromStrings("BTC", "LTC"))
- if p.Contains(currency.NewPairFromStrings("BTC", "LTC"), true) {
+ btcltc, err := currency.NewPairFromStrings("BTC", "LTC")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ btcbtc, err := currency.NewPairFromStrings("BTC", "BTC")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ ltcltc, err := currency.NewPairFromStrings("LTC", "LTC")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ btceth, err := currency.NewPairFromStrings("BTC", "ETH")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ p := GetRelatableCryptocurrencies(btcltc)
+ if p.Contains(btcltc, true) {
t.Fatal("Unexpected result")
}
- if p.Contains(currency.NewPairFromStrings("BTC", "BTC"), true) {
+ if p.Contains(btcbtc, true) {
t.Fatal("Unexpected result")
}
- if p.Contains(currency.NewPairFromStrings("LTC", "LTC"), true) {
+ if p.Contains(ltcltc, true) {
t.Fatal("Unexpected result")
}
- if !p.Contains(currency.NewPairFromStrings("BTC", "ETH"), true) {
+ if !p.Contains(btceth, true) {
t.Fatal("Unexpected result")
}
- p = GetRelatableCryptocurrencies(currency.NewPairFromStrings("BTC", "LTC"))
- if p.Contains(currency.NewPairFromStrings("BTC", "LTC"), true) {
+ p = GetRelatableCryptocurrencies(btcltc)
+ if p.Contains(btcltc, true) {
t.Fatal("Unexpected result")
}
- if p.Contains(currency.NewPairFromStrings("BTC", "BTC"), true) {
+ if p.Contains(btcbtc, true) {
t.Fatal("Unexpected result")
}
- if p.Contains(currency.NewPairFromStrings("LTC", "LTC"), true) {
+ if p.Contains(ltcltc, true) {
t.Fatal("Unexpected result")
}
- if !p.Contains(currency.NewPairFromStrings("BTC", "ETH"), true) {
+ if !p.Contains(btceth, true) {
t.Fatal("Unexpected result")
}
}
func TestGetRelatableFiatCurrencies(t *testing.T) {
SetupTestHelpers(t)
- p := GetRelatableFiatCurrencies(currency.NewPairFromStrings("BTC", "USD"))
- if !p.Contains(currency.NewPairFromStrings("BTC", "EUR"), true) {
+
+ btsusd, err := currency.NewPairFromStrings("BTC", "USD")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ btceur, err := currency.NewPairFromStrings("BTC", "EUR")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ p := GetRelatableFiatCurrencies(btsusd)
+ if !p.Contains(btceur, true) {
t.Fatal("Unexpected result")
}
- p = GetRelatableFiatCurrencies(currency.NewPairFromStrings("BTC", "USD"))
- if !p.Contains(currency.NewPairFromStrings("BTC", "ZAR"), true) {
+ btczar, err := currency.NewPairFromStrings("BTC", "ZAR")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ p = GetRelatableFiatCurrencies(btsusd)
+ if !p.Contains(btczar, true) {
t.Fatal("Unexpected result")
}
}
@@ -373,21 +498,36 @@ func TestGetExchangeNamesByCurrency(t *testing.T) {
SetupTestHelpers(t)
assetType := asset.Spot
- result := GetExchangeNamesByCurrency(currency.NewPairFromStrings("BTC", "USD"),
+ btsusd, err := currency.NewPairFromStrings("BTC", "USD")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ btcjpy, err := currency.NewPairFromStrings("BTC", "JPY")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ blahjpy, err := currency.NewPairFromStrings("blah", "JPY")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ result := GetExchangeNamesByCurrency(btsusd,
true,
assetType)
if !common.StringDataCompare(result, "Bitstamp") {
t.Fatal("Unexpected result")
}
- result = GetExchangeNamesByCurrency(currency.NewPairFromStrings("BTC", "JPY"),
+ result = GetExchangeNamesByCurrency(btcjpy,
true,
assetType)
if !common.StringDataCompare(result, "Bitflyer") {
t.Fatal("Unexpected result")
}
- result = GetExchangeNamesByCurrency(currency.NewPairFromStrings("blah", "JPY"),
+ result = GetExchangeNamesByCurrency(blahjpy,
true,
assetType)
if len(result) > 0 {
@@ -415,9 +555,12 @@ func TestGetSpecificOrderbook(t *testing.T) {
t.Fatal("Unexpected result", err)
}
- ob, err := GetSpecificOrderbook(currency.NewPairFromString("BTCUSD"),
- "Bitstamp",
- asset.Spot)
+ btsusd, err := currency.NewPairFromStrings("BTC", "USD")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ ob, err := GetSpecificOrderbook(btsusd, "Bitstamp", asset.Spot)
if err != nil {
t.Fatal(err)
}
@@ -426,9 +569,12 @@ func TestGetSpecificOrderbook(t *testing.T) {
t.Fatal("Unexpected result")
}
- _, err = GetSpecificOrderbook(currency.NewPairFromStrings("ETH", "LTC"),
- "Bitstamp",
- asset.Spot)
+ ethltc, err := currency.NewPairFromStrings("ETH", "LTC")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ _, err = GetSpecificOrderbook(ethltc, "Bitstamp", asset.Spot)
if err == nil {
t.Fatal("Unexpected result")
}
@@ -440,16 +586,21 @@ func TestGetSpecificTicker(t *testing.T) {
SetupTestHelpers(t)
LoadExchange("Bitstamp", false, nil)
- p := currency.NewPairFromStrings("BTC", "USD")
- err := ticker.ProcessTicker("Bitstamp",
- &ticker.Price{Pair: p, Last: 1000},
- asset.Spot)
+ p, err := currency.NewPairFromStrings("BTC", "USD")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ err = ticker.ProcessTicker(&ticker.Price{
+ Pair: p,
+ Last: 1000,
+ AssetType: asset.Spot,
+ ExchangeName: "Bitstamp"})
if err != nil {
t.Fatal("ProcessTicker error", err)
}
- tick, err := GetSpecificTicker(currency.NewPairFromStrings("BTC", "USD"), "Bitstamp",
- asset.Spot)
+ tick, err := GetSpecificTicker(p, "Bitstamp", asset.Spot)
if err != nil {
t.Fatal(err)
}
@@ -458,8 +609,12 @@ func TestGetSpecificTicker(t *testing.T) {
t.Fatal("Unexpected result")
}
- _, err = GetSpecificTicker(currency.NewPairFromStrings("ETH", "LTC"), "Bitstamp",
- asset.Spot)
+ ethltc, err := currency.NewPairFromStrings("ETH", "LTC")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ _, err = GetSpecificTicker(ethltc, "Bitstamp", asset.Spot)
if err == nil {
t.Fatal("Unexpected result")
}
@@ -530,7 +685,11 @@ func TestGetCollatedExchangeAccountInfoByCoin(t *testing.T) {
func TestGetExchangeHighestPriceByCurrencyPair(t *testing.T) {
SetupTestHelpers(t)
- p := currency.NewPairFromStrings("BTC", "USD")
+ p, err := currency.NewPairFromStrings("BTC", "USD")
+ if err != nil {
+ t.Fatal(err)
+ }
+
stats.Add("Bitfinex", p, asset.Spot, 1000, 10000)
stats.Add("Bitstamp", p, asset.Spot, 1337, 10000)
exchangeName, err := GetExchangeHighestPriceByCurrencyPair(p, asset.Spot)
@@ -542,8 +701,12 @@ func TestGetExchangeHighestPriceByCurrencyPair(t *testing.T) {
t.Error("Unexpected result")
}
- _, err = GetExchangeHighestPriceByCurrencyPair(currency.NewPairFromStrings("BTC", "AUD"),
- asset.Spot)
+ btcaud, err := currency.NewPairFromStrings("BTC", "AUD")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ _, err = GetExchangeHighestPriceByCurrencyPair(btcaud, asset.Spot)
if err == nil {
t.Error("Unexpected result")
}
@@ -552,7 +715,11 @@ func TestGetExchangeHighestPriceByCurrencyPair(t *testing.T) {
func TestGetExchangeLowestPriceByCurrencyPair(t *testing.T) {
SetupTestHelpers(t)
- p := currency.NewPairFromStrings("BTC", "USD")
+ p, err := currency.NewPairFromStrings("BTC", "USD")
+ if err != nil {
+ t.Fatal(err)
+ }
+
stats.Add("Bitfinex", p, asset.Spot, 1000, 10000)
stats.Add("Bitstamp", p, asset.Spot, 1337, 10000)
exchangeName, err := GetExchangeLowestPriceByCurrencyPair(p, asset.Spot)
@@ -564,8 +731,12 @@ func TestGetExchangeLowestPriceByCurrencyPair(t *testing.T) {
t.Error("Unexpected result")
}
- _, err = GetExchangeLowestPriceByCurrencyPair(currency.NewPairFromStrings("BTC", "AUD"),
- asset.Spot)
+ btcaud, err := currency.NewPairFromStrings("BTC", "AUD")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ _, err = GetExchangeLowestPriceByCurrencyPair(btcaud, asset.Spot)
if err == nil {
t.Error("Unexpected reuslt")
}
diff --git a/engine/orders.go b/engine/orders.go
index ca91e898..15578ca5 100644
--- a/engine/orders.go
+++ b/engine/orders.go
@@ -389,18 +389,45 @@ func (o *orderManager) Submit(newOrder *order.Submit) (*orderSubmitResponse, err
func (o *orderManager) processOrders() {
authExchanges := GetAuthAPISupportedExchanges()
for x := range authExchanges {
- log.Debugf(log.OrderMgr, "Order manager: Processing orders for exchange %v.", authExchanges[x])
+ log.Debugf(log.OrderMgr,
+ "Order manager: Processing orders for exchange %v.",
+ authExchanges[x])
+
exch := GetExchangeByName(authExchanges[x])
supportedAssets := exch.GetAssetTypes()
for y := range supportedAssets {
+ pairs, err := exch.GetEnabledPairs(supportedAssets[y])
+ if err != nil {
+ log.Errorf(log.OrderMgr,
+ "Order manager: Unable to get enabled pairs for %s and asset type %s: %s",
+ authExchanges[x],
+ supportedAssets[y],
+ err)
+ continue
+ }
+
+ if len(pairs) == 0 {
+ if Bot.Settings.Verbose {
+ log.Debugf(log.OrderMgr,
+ "Order manager: No pairs enabled for %s and asset type %s, skipping...",
+ authExchanges[x],
+ supportedAssets[y])
+ }
+ continue
+ }
+
req := order.GetOrdersRequest{
Side: order.AnySide,
Type: order.AnyType,
- Pairs: exch.GetEnabledPairs(supportedAssets[y]),
+ Pairs: pairs,
}
result, err := exch.GetActiveOrders(&req)
if err != nil {
- log.Warnf(log.OrderMgr, "Order manager: Unable to get active orders: %s", err)
+ log.Warnf(log.OrderMgr,
+ "Order manager: Unable to get active orders for %s and asset type %s: %s",
+ authExchanges[x],
+ supportedAssets[y],
+ err)
continue
}
diff --git a/engine/orders_test.go b/engine/orders_test.go
index 1e8a0838..f799ace1 100644
--- a/engine/orders_test.go
+++ b/engine/orders_test.go
@@ -254,6 +254,11 @@ func TestCancelOrder(t *testing.T) {
t.Error("Expected error due to no order found")
}
+ pair, err := currency.NewPairFromString("BTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
+
cancel := &order.Cancel{
Exchange: fakePassExchange,
ID: "TestCancelOrder",
@@ -261,7 +266,7 @@ func TestCancelOrder(t *testing.T) {
Status: order.New,
AssetType: asset.Spot,
Date: time.Now(),
- Pair: currency.NewPairFromString("BTCUSD"),
+ Pair: pair,
}
err = Bot.OrderManager.Cancel(cancel)
if err != nil {
@@ -326,9 +331,14 @@ func TestSubmit(t *testing.T) {
t.Error("Expected error from validation")
}
+ pair, err := currency.NewPairFromString("BTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
+
Bot.OrderManager.cfg.EnforceLimitConfig = true
Bot.OrderManager.cfg.AllowMarketOrders = false
- o.Pair = currency.NewPairFromString("BTCUSD")
+ o.Pair = pair
o.AssetType = asset.Spot
o.Side = order.Buy
o.Amount = 1
@@ -351,8 +361,13 @@ func TestSubmit(t *testing.T) {
t.Error("Expected fail due to order exchange not found in allowed list")
}
+ failPair, err := currency.NewPairFromString("BTCAUD")
+ if err != nil {
+ t.Fatal(err)
+ }
+
Bot.OrderManager.cfg.AllowedExchanges = nil
- Bot.OrderManager.cfg.AllowedPairs = currency.Pairs{currency.NewPairFromString("BTCAUD")}
+ Bot.OrderManager.cfg.AllowedPairs = currency.Pairs{failPair}
_, err = Bot.OrderManager.Submit(o)
if err == nil {
t.Error("Expected fail due to order pair not found in allowed list")
diff --git a/engine/restful_server.go b/engine/restful_server.go
index f2f3fc02..cd6cb7e1 100644
--- a/engine/restful_server.go
+++ b/engine/restful_server.go
@@ -66,7 +66,14 @@ func GetAllActiveOrderbooks() []EnabledExchangeOrderbooks {
exchangeOB.ExchangeName = exchName
for y := range assets {
- currencies := exchanges[x].GetEnabledPairs(assets[y])
+ currencies, err := exchanges[x].GetEnabledPairs(assets[y])
+ if err != nil {
+ log.Errorf(log.RESTSys,
+ "Exchange %s could not retrieve enabled currencies. Err: %s\n",
+ exchName,
+ err)
+ continue
+ }
for z := range currencies {
ob, err := exchanges[x].FetchOrderbook(currencies[z], assets[y])
if err != nil {
diff --git a/engine/routines.go b/engine/routines.go
index bc9e60a4..e2d13354 100644
--- a/engine/routines.go
+++ b/engine/routines.go
@@ -8,12 +8,11 @@ import (
"github.com/thrasher-corp/gocryptotrader/common"
"github.com/thrasher-corp/gocryptotrader/currency"
- "github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/stats"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
)
@@ -57,26 +56,29 @@ func printConvertCurrencyFormat(origCurrency currency.Code, origPrice float64) s
)
}
-func printTickerSummary(result *ticker.Price, p currency.Pair, assetType asset.Item, exchangeName, protocol string, err error) {
+func printTickerSummary(result *ticker.Price, protocol string, err error) {
if err != nil {
- log.Errorf(log.Ticker, "Failed to get %s %s %s %s ticker. Error: %s\n",
- exchangeName,
+ if err == common.ErrNotYetImplemented {
+ log.Warnf(log.Ticker, "Failed to get %s ticker. Error: %s\n",
+ protocol,
+ err)
+ return
+ }
+ log.Errorf(log.Ticker, "Failed to get %s ticker. Error: %s\n",
protocol,
- p,
- assetType,
err)
return
}
- stats.Add(exchangeName, p, assetType, result.Last, result.Volume)
- if p.Quote.IsFiatCurrency() &&
- p.Quote != Bot.Config.Currency.FiatDisplayCurrency {
- origCurrency := p.Quote.Upper()
+ stats.Add(result.ExchangeName, result.Pair, result.AssetType, result.Last, result.Volume)
+ if result.Pair.Quote.IsFiatCurrency() &&
+ result.Pair.Quote != Bot.Config.Currency.FiatDisplayCurrency {
+ origCurrency := result.Pair.Quote.Upper()
log.Infof(log.Ticker, "%s %s %s %s: TICKER: Last %s Ask %s Bid %s High %s Low %s Volume %.8f\n",
- exchangeName,
+ result.ExchangeName,
protocol,
- FormatCurrency(p),
- strings.ToUpper(assetType.String()),
+ FormatCurrency(result.Pair),
+ strings.ToUpper(result.AssetType.String()),
printConvertCurrencyFormat(origCurrency, result.Last),
printConvertCurrencyFormat(origCurrency, result.Ask),
printConvertCurrencyFormat(origCurrency, result.Bid),
@@ -84,13 +86,13 @@ func printTickerSummary(result *ticker.Price, p currency.Pair, assetType asset.I
printConvertCurrencyFormat(origCurrency, result.Low),
result.Volume)
} else {
- if p.Quote.IsFiatCurrency() &&
- p.Quote == Bot.Config.Currency.FiatDisplayCurrency {
+ if result.Pair.Quote.IsFiatCurrency() &&
+ result.Pair.Quote == Bot.Config.Currency.FiatDisplayCurrency {
log.Infof(log.Ticker, "%s %s %s %s: TICKER: Last %s Ask %s Bid %s High %s Low %s Volume %.8f\n",
- exchangeName,
+ result.ExchangeName,
protocol,
- FormatCurrency(p),
- strings.ToUpper(assetType.String()),
+ FormatCurrency(result.Pair),
+ strings.ToUpper(result.AssetType.String()),
printCurrencyFormat(result.Last),
printCurrencyFormat(result.Ask),
printCurrencyFormat(result.Bid),
@@ -99,10 +101,10 @@ func printTickerSummary(result *ticker.Price, p currency.Pair, assetType asset.I
result.Volume)
} else {
log.Infof(log.Ticker, "%s %s %s %s: TICKER: Last %.8f Ask %.8f Bid %.8f High %.8f Low %.8f Volume %.8f\n",
- exchangeName,
+ result.ExchangeName,
protocol,
- FormatCurrency(p),
- strings.ToUpper(assetType.String()),
+ FormatCurrency(result.Pair),
+ strings.ToUpper(result.AssetType.String()),
result.Last,
result.Ask,
result.Bid,
@@ -113,13 +115,16 @@ func printTickerSummary(result *ticker.Price, p currency.Pair, assetType asset.I
}
}
-func printOrderbookSummary(result *orderbook.Base, p currency.Pair, assetType asset.Item, exchangeName, protocol string, err error) {
+func printOrderbookSummary(result *orderbook.Base, protocol string, err error) {
if err != nil {
- log.Errorf(log.OrderBook, "Failed to get %s %s %s orderbook of type %s. Error: %s\n",
- exchangeName,
+ if err == common.ErrNotYetImplemented {
+ log.Warnf(log.Ticker, "Failed to get %s ticker. Error: %s\n",
+ protocol,
+ err)
+ return
+ }
+ log.Errorf(log.OrderBook, "Failed to get %s orderbook. Error: %s\n",
protocol,
- p,
- assetType,
err)
return
}
@@ -127,53 +132,53 @@ func printOrderbookSummary(result *orderbook.Base, p currency.Pair, assetType as
bidsAmount, bidsValue := result.TotalBidsAmount()
asksAmount, asksValue := result.TotalAsksAmount()
- if p.Quote.IsFiatCurrency() &&
- p.Quote != Bot.Config.Currency.FiatDisplayCurrency {
- origCurrency := p.Quote.Upper()
+ if result.Pair.Quote.IsFiatCurrency() &&
+ result.Pair.Quote != Bot.Config.Currency.FiatDisplayCurrency {
+ origCurrency := result.Pair.Quote.Upper()
log.Infof(log.OrderBook, "%s %s %s %s: ORDERBOOK: Bids len: %d Amount: %f %s. Total value: %s Asks len: %d Amount: %f %s. Total value: %s\n",
- exchangeName,
+ result.ExchangeName,
protocol,
- FormatCurrency(p),
- strings.ToUpper(assetType.String()),
+ FormatCurrency(result.Pair),
+ strings.ToUpper(result.AssetType.String()),
len(result.Bids),
bidsAmount,
- p.Base,
+ result.Pair.Base,
printConvertCurrencyFormat(origCurrency, bidsValue),
len(result.Asks),
asksAmount,
- p.Base,
+ result.Pair.Base,
printConvertCurrencyFormat(origCurrency, asksValue),
)
} else {
- if p.Quote.IsFiatCurrency() &&
- p.Quote == Bot.Config.Currency.FiatDisplayCurrency {
+ if result.Pair.Quote.IsFiatCurrency() &&
+ result.Pair.Quote == Bot.Config.Currency.FiatDisplayCurrency {
log.Infof(log.OrderBook, "%s %s %s %s: ORDERBOOK: Bids len: %d Amount: %f %s. Total value: %s Asks len: %d Amount: %f %s. Total value: %s\n",
- exchangeName,
+ result.ExchangeName,
protocol,
- FormatCurrency(p),
- strings.ToUpper(assetType.String()),
+ FormatCurrency(result.Pair),
+ strings.ToUpper(result.AssetType.String()),
len(result.Bids),
bidsAmount,
- p.Base,
+ result.Pair.Base,
printCurrencyFormat(bidsValue),
len(result.Asks),
asksAmount,
- p.Base,
+ result.Pair.Base,
printCurrencyFormat(asksValue),
)
} else {
log.Infof(log.OrderBook, "%s %s %s %s: ORDERBOOK: Bids len: %d Amount: %f %s. Total value: %f Asks len: %d Amount: %f %s. Total value: %f\n",
- exchangeName,
+ result.ExchangeName,
protocol,
- FormatCurrency(p),
- strings.ToUpper(assetType.String()),
+ FormatCurrency(result.Pair),
+ strings.ToUpper(result.AssetType.String()),
len(result.Bids),
bidsAmount,
- p.Base,
+ result.Pair.Base,
bidsValue,
len(result.Asks),
asksAmount,
- p.Base,
+ result.Pair.Base,
asksValue,
)
}
@@ -212,28 +217,27 @@ func WebsocketRoutine() {
)
}
- // TO-DO: expose IsConnected() and IsConnecting so this can be simplified
- if exchanges[i].IsWebsocketEnabled() {
- ws, err := exchanges[i].GetWebsocket()
- if err != nil {
- log.Errorf(
- log.WebsocketMgr,
- "Exchange %s GetWebsocket error: %s\n",
- exchanges[i].GetName(),
- err,
- )
- return
- }
+ ws, err := exchanges[i].GetWebsocket()
+ if err != nil {
+ log.Errorf(
+ log.WebsocketMgr,
+ "Exchange %s GetWebsocket error: %s\n",
+ exchanges[i].GetName(),
+ err,
+ )
+ return
+ }
- // Exchange sync manager might have already started ws
- // service or is in the process of connecting, so check
- if ws.IsConnected() || ws.IsConnecting() {
- return
- }
+ // Exchange sync manager might have already started ws
+ // service or is in the process of connecting, so check
+ if ws.IsConnected() || ws.IsConnecting() {
+ return
+ }
- // Data handler routine
- go WebsocketDataReceiver(ws)
+ // Data handler routine
+ go WebsocketDataReceiver(ws)
+ if ws.IsEnabled() {
err = ws.Connect()
if err != nil {
log.Errorf(log.WebsocketMgr, "%v\n", err)
@@ -254,7 +258,7 @@ var wg sync.WaitGroup
// WebsocketDataReceiver handles websocket data coming from a websocket feed
// associated with an exchange
-func WebsocketDataReceiver(ws *wshandler.Websocket) {
+func WebsocketDataReceiver(ws *stream.Websocket) {
wg.Add(1)
defer wg.Done()
@@ -262,7 +266,7 @@ func WebsocketDataReceiver(ws *wshandler.Websocket) {
select {
case <-shutdowner:
return
- case data := <-ws.DataHandler:
+ case data := <-ws.ToRoutine:
err := WebsocketDataHandler(ws.GetName(), data)
if err != nil {
log.Error(log.WebsocketMgr, err)
@@ -278,12 +282,13 @@ func WebsocketDataHandler(exchName string, data interface{}) error {
return fmt.Errorf("routines.go - exchange %s nil data sent to websocket",
exchName)
}
+
switch d := data.(type) {
case string:
log.Info(log.WebsocketMgr, d)
case error:
return fmt.Errorf("routines.go exchange %s websocket error - %s", exchName, data)
- case wshandler.TradeData:
+ case stream.TradeData:
if Bot.Settings.Verbose {
log.Infof(log.WebsocketMgr, "%s websocket %s %s trade updated %+v",
exchName,
@@ -291,7 +296,7 @@ func WebsocketDataHandler(exchName string, data interface{}) error {
d.AssetType,
d)
}
- case wshandler.FundingData:
+ case stream.FundingData:
if Bot.Settings.Verbose {
log.Infof(log.WebsocketMgr, "%s websocket %s %s funding updated %+v",
exchName,
@@ -307,9 +312,9 @@ func WebsocketDataHandler(exchName string, data interface{}) error {
SyncItemTicker,
nil)
}
- err := ticker.ProcessTicker(exchName, d, d.AssetType)
- printTickerSummary(d, d.Pair, d.AssetType, exchName, "websocket", err)
- case wshandler.KlineData:
+ err := ticker.ProcessTicker(d)
+ printTickerSummary(d, "websocket", err)
+ case stream.KlineData:
if Bot.Settings.Verbose {
log.Infof(log.WebsocketMgr, "%s websocket %s %s kline updated %+v",
exchName,
@@ -317,22 +322,15 @@ func WebsocketDataHandler(exchName string, data interface{}) error {
d.AssetType,
d)
}
- case wshandler.WebsocketOrderbookUpdate:
+ case *orderbook.Base:
if Bot.Settings.EnableExchangeSyncManager && Bot.ExchangeCurrencyPairManager != nil {
Bot.ExchangeCurrencyPairManager.update(exchName,
d.Pair,
- d.Asset,
+ d.AssetType,
SyncItemOrderbook,
nil)
}
-
- if Bot.Settings.Verbose {
- log.Infof(log.WebsocketMgr,
- "%s websocket %s %s orderbook updated",
- exchName,
- FormatCurrency(d.Pair),
- d.Asset)
- }
+ printOrderbookSummary(d, "websocket", nil)
case *order.Detail:
if !Bot.OrderManager.orderStore.exists(d) {
err := Bot.OrderManager.orderStore.Add(d)
@@ -356,7 +354,7 @@ func WebsocketDataHandler(exchName string, data interface{}) error {
od.UpdateOrderFromModify(d)
case order.ClassificationError:
return errors.New(d.Error())
- case wshandler.UnhandledMessageWarning:
+ case stream.UnhandledMessageWarning:
log.Warn(log.WebsocketMgr, d.Message)
default:
if Bot.Settings.Verbose {
diff --git a/engine/routines_test.go b/engine/routines_test.go
index ac200633..b54d1645 100644
--- a/engine/routines_test.go
+++ b/engine/routines_test.go
@@ -5,19 +5,16 @@ import (
"testing"
"time"
+ "github.com/thrasher-corp/gocryptotrader/currency"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
)
func TestWebsocketDataHandlerProcess(t *testing.T) {
- ws := wshandler.New()
- err := ws.Setup(&wshandler.WebsocketSetup{Enabled: true})
- if err != nil {
- t.Error(err)
- }
- ws.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
+ ws := sharedtestvalues.NewTestWebsocket()
go WebsocketDataReceiver(ws)
ws.DataHandler <- "string"
time.Sleep(time.Second)
@@ -36,11 +33,11 @@ func TestHandleData(t *testing.T) {
if err == nil {
t.Error("Expected nil data error")
}
- err = WebsocketDataHandler(exchName, wshandler.TradeData{})
+ err = WebsocketDataHandler(exchName, stream.TradeData{})
if err != nil {
t.Error(err)
}
- err = WebsocketDataHandler(exchName, wshandler.FundingData{})
+ err = WebsocketDataHandler(exchName, stream.FundingData{})
if err != nil {
t.Error(err)
}
@@ -48,11 +45,7 @@ func TestHandleData(t *testing.T) {
if err != nil {
t.Error(err)
}
- err = WebsocketDataHandler(exchName, wshandler.KlineData{})
- if err != nil {
- t.Error(err)
- }
- err = WebsocketDataHandler(exchName, wshandler.WebsocketOrderbookUpdate{})
+ err = WebsocketDataHandler(exchName, stream.KlineData{})
if err != nil {
t.Error(err)
}
@@ -107,7 +100,9 @@ func TestHandleData(t *testing.T) {
t.Error(err)
}
- err = WebsocketDataHandler(exchName, wshandler.UnhandledMessageWarning{Message: "there's an issue here's a tissue"})
+ err = WebsocketDataHandler(exchName, stream.UnhandledMessageWarning{
+ Message: "there's an issue here's a tissue"},
+ )
if err != nil {
t.Error(err)
}
@@ -124,4 +119,16 @@ func TestHandleData(t *testing.T) {
if err.Error() != classificationError.Error() {
t.Errorf("Problem formatting error. Expected %v Received %v", classificationError.Error(), err.Error())
}
+
+ err = WebsocketDataHandler(exchName, &orderbook.Base{
+ ExchangeName: fakePassExchange,
+ Pair: currency.NewPair(currency.BTC, currency.USD),
+ })
+ if err != nil {
+ t.Error(err)
+ }
+ err = WebsocketDataHandler(exchName, "this is a test string")
+ if err != nil {
+ t.Error(err)
+ }
}
diff --git a/engine/rpcserver.go b/engine/rpcserver.go
index 75d4787d..c66b8b2f 100644
--- a/engine/rpcserver.go
+++ b/engine/rpcserver.go
@@ -2,6 +2,7 @@ package engine
import (
"context"
+ "encoding/json"
"errors"
"fmt"
"io/ioutil"
@@ -52,6 +53,11 @@ const (
errDispatchSystem = "dispatch system offline"
)
+var (
+ errExchangeNotLoaded = errors.New("exchange is not loaded/doesn't exist")
+ errExchangeBaseNotFound = errors.New("cannot get exchange base")
+)
+
// RPCServer struct
type RPCServer struct{}
@@ -165,7 +171,7 @@ func StartRPCRESTProxy() {
}
// GetInfo returns info about the current GoCryptoTrader session
-func (s *RPCServer) GetInfo(ctx context.Context, r *gctrpc.GetInfoRequest) (*gctrpc.GetInfoResponse, error) {
+func (s *RPCServer) GetInfo(_ context.Context, r *gctrpc.GetInfoRequest) (*gctrpc.GetInfoResponse, error) {
d := time.Since(Bot.Uptime)
resp := gctrpc.GetInfoResponse{
Uptime: d.String(),
@@ -187,24 +193,32 @@ func (s *RPCServer) GetInfo(ctx context.Context, r *gctrpc.GetInfoRequest) (*gct
}
// GetSubsystems returns a list of subsystems and their status
-func (s *RPCServer) GetSubsystems(ctx context.Context, r *gctrpc.GetSubsystemsRequest) (*gctrpc.GetSusbsytemsResponse, error) {
+func (s *RPCServer) GetSubsystems(_ context.Context, r *gctrpc.GetSubsystemsRequest) (*gctrpc.GetSusbsytemsResponse, error) {
return &gctrpc.GetSusbsytemsResponse{SubsystemsStatus: GetSubsystemsStatus()}, nil
}
// EnableSubsystem enables a engine subsytem
-func (s *RPCServer) EnableSubsystem(ctx context.Context, r *gctrpc.GenericSubsystemRequest) (*gctrpc.GenericSubsystemResponse, error) {
+func (s *RPCServer) EnableSubsystem(_ context.Context, r *gctrpc.GenericSubsystemRequest) (*gctrpc.GenericResponse, error) {
err := SetSubsystem(r.Subsystem, true)
- return &gctrpc.GenericSubsystemResponse{}, err
+ if err != nil {
+ return nil, err
+ }
+ return &gctrpc.GenericResponse{Status: MsgStatusSuccess,
+ Data: fmt.Sprintf("subsystem %s enabled", r.Subsystem)}, nil
}
// DisableSubsystem disables a engine subsytem
-func (s *RPCServer) DisableSubsystem(ctx context.Context, r *gctrpc.GenericSubsystemRequest) (*gctrpc.GenericSubsystemResponse, error) {
+func (s *RPCServer) DisableSubsystem(_ context.Context, r *gctrpc.GenericSubsystemRequest) (*gctrpc.GenericResponse, error) {
err := SetSubsystem(r.Subsystem, false)
- return &gctrpc.GenericSubsystemResponse{}, err
+ if err != nil {
+ return nil, err
+ }
+ return &gctrpc.GenericResponse{Status: MsgStatusSuccess,
+ Data: fmt.Sprintf("subsystem %s disabled", r.Subsystem)}, nil
}
// GetRPCEndpoints returns a list of API endpoints
-func (s *RPCServer) GetRPCEndpoints(ctx context.Context, r *gctrpc.GetRPCEndpointsRequest) (*gctrpc.GetRPCEndpointsResponse, error) {
+func (s *RPCServer) GetRPCEndpoints(_ context.Context, r *gctrpc.GetRPCEndpointsRequest) (*gctrpc.GetRPCEndpointsResponse, error) {
endpoints := GetRPCEndpoints()
var resp gctrpc.GetRPCEndpointsResponse
resp.Endpoints = make(map[string]*gctrpc.RPCEndpoint)
@@ -218,7 +232,7 @@ func (s *RPCServer) GetRPCEndpoints(ctx context.Context, r *gctrpc.GetRPCEndpoin
}
// GetCommunicationRelayers returns the status of the engines communication relayers
-func (s *RPCServer) GetCommunicationRelayers(ctx context.Context, r *gctrpc.GetCommunicationRelayersRequest) (*gctrpc.GetCommunicationRelayersResponse, error) {
+func (s *RPCServer) GetCommunicationRelayers(_ context.Context, r *gctrpc.GetCommunicationRelayersRequest) (*gctrpc.GetCommunicationRelayersResponse, error) {
relayers, err := Bot.CommsManager.GetStatus()
if err != nil {
return nil, err
@@ -237,38 +251,44 @@ func (s *RPCServer) GetCommunicationRelayers(ctx context.Context, r *gctrpc.GetC
// GetExchanges returns a list of exchanges
// Param is whether or not you wish to list enabled exchanges
-func (s *RPCServer) GetExchanges(ctx context.Context, r *gctrpc.GetExchangesRequest) (*gctrpc.GetExchangesResponse, error) {
+func (s *RPCServer) GetExchanges(_ context.Context, r *gctrpc.GetExchangesRequest) (*gctrpc.GetExchangesResponse, error) {
exchanges := strings.Join(GetExchangeNames(r.Enabled), ",")
return &gctrpc.GetExchangesResponse{Exchanges: exchanges}, nil
}
// DisableExchange disables an exchange
-func (s *RPCServer) DisableExchange(ctx context.Context, r *gctrpc.GenericExchangeNameRequest) (*gctrpc.GenericExchangeNameResponse, error) {
+func (s *RPCServer) DisableExchange(_ context.Context, r *gctrpc.GenericExchangeNameRequest) (*gctrpc.GenericResponse, error) {
err := UnloadExchange(r.Exchange)
- return &gctrpc.GenericExchangeNameResponse{}, err
+ if err != nil {
+ return nil, err
+ }
+ return &gctrpc.GenericResponse{Status: MsgStatusSuccess}, nil
}
// EnableExchange enables an exchange
-func (s *RPCServer) EnableExchange(ctx context.Context, r *gctrpc.GenericExchangeNameRequest) (*gctrpc.GenericExchangeNameResponse, error) {
+func (s *RPCServer) EnableExchange(_ context.Context, r *gctrpc.GenericExchangeNameRequest) (*gctrpc.GenericResponse, error) {
err := LoadExchange(r.Exchange, false, nil)
- return &gctrpc.GenericExchangeNameResponse{}, err
+ if err != nil {
+ return nil, err
+ }
+ return &gctrpc.GenericResponse{Status: MsgStatusSuccess}, nil
}
// GetExchangeOTPCode retrieves an exchanges OTP code
-func (s *RPCServer) GetExchangeOTPCode(ctx context.Context, r *gctrpc.GenericExchangeNameRequest) (*gctrpc.GetExchangeOTPReponse, error) {
+func (s *RPCServer) GetExchangeOTPCode(_ context.Context, r *gctrpc.GenericExchangeNameRequest) (*gctrpc.GetExchangeOTPReponse, error) {
result, err := GetExchangeoOTPByName(r.Exchange)
return &gctrpc.GetExchangeOTPReponse{OtpCode: result}, err
}
// GetExchangeOTPCodes retrieves OTP codes for all exchanges which have an
// OTP secret installed
-func (s *RPCServer) GetExchangeOTPCodes(ctx context.Context, r *gctrpc.GetExchangeOTPsRequest) (*gctrpc.GetExchangeOTPsResponse, error) {
+func (s *RPCServer) GetExchangeOTPCodes(_ context.Context, r *gctrpc.GetExchangeOTPsRequest) (*gctrpc.GetExchangeOTPsResponse, error) {
result, err := GetExchangeOTPs()
return &gctrpc.GetExchangeOTPsResponse{OtpCodes: result}, err
}
// GetExchangeInfo gets info for a specific exchange
-func (s *RPCServer) GetExchangeInfo(ctx context.Context, r *gctrpc.GenericExchangeNameRequest) (*gctrpc.GetExchangeInfoResponse, error) {
+func (s *RPCServer) GetExchangeInfo(_ context.Context, r *gctrpc.GenericExchangeNameRequest) (*gctrpc.GetExchangeInfoResponse, error) {
exchCfg, err := Bot.Config.GetExchangeConfig(r.Exchange)
if err != nil {
return nil, err
@@ -286,11 +306,16 @@ func (s *RPCServer) GetExchangeInfo(ctx context.Context, r *gctrpc.GenericExchan
}
resp.SupportedAssets = make(map[string]*gctrpc.PairsSupported)
- for x := range exchCfg.CurrencyPairs.AssetTypes {
- a := exchCfg.CurrencyPairs.AssetTypes[x]
- resp.SupportedAssets[a.String()] = &gctrpc.PairsSupported{
- EnabledPairs: exchCfg.CurrencyPairs.Get(a).Enabled.Join(),
- AvailablePairs: exchCfg.CurrencyPairs.Get(a).Available.Join(),
+ assets := exchCfg.CurrencyPairs.GetAssetTypes()
+ for i := range assets {
+ ps, err := exchCfg.CurrencyPairs.Get(assets[i])
+ if err != nil {
+ return nil, err
+ }
+
+ resp.SupportedAssets[assets[i].String()] = &gctrpc.PairsSupported{
+ EnabledPairs: ps.Enabled.Join(),
+ AvailablePairs: ps.Available.Join(),
}
}
return resp, nil
@@ -298,13 +323,12 @@ func (s *RPCServer) GetExchangeInfo(ctx context.Context, r *gctrpc.GenericExchan
// GetTicker returns the ticker for a specified exchange, currency pair and
// asset type
-func (s *RPCServer) GetTicker(ctx context.Context, r *gctrpc.GetTickerRequest) (*gctrpc.TickerResponse, error) {
- t, err := GetSpecificTicker(
- currency.Pair{
- Delimiter: r.Pair.Delimiter,
- Base: currency.NewCode(r.Pair.Base),
- Quote: currency.NewCode(r.Pair.Quote),
- },
+func (s *RPCServer) GetTicker(_ context.Context, r *gctrpc.GetTickerRequest) (*gctrpc.TickerResponse, error) {
+ t, err := GetSpecificTicker(currency.Pair{
+ Delimiter: r.Pair.Delimiter,
+ Base: currency.NewCode(r.Pair.Base),
+ Quote: currency.NewCode(r.Pair.Quote),
+ },
r.Exchange,
asset.Item(r.AssetType),
)
@@ -329,7 +353,7 @@ func (s *RPCServer) GetTicker(ctx context.Context, r *gctrpc.GetTickerRequest) (
// GetTickers returns a list of tickers for all enabled exchanges and all
// enabled currency pairs
-func (s *RPCServer) GetTickers(ctx context.Context, r *gctrpc.GetTickersRequest) (*gctrpc.GetTickersResponse, error) {
+func (s *RPCServer) GetTickers(_ context.Context, r *gctrpc.GetTickersRequest) (*gctrpc.GetTickersResponse, error) {
activeTickers := GetAllActiveTickers()
var tickers []*gctrpc.Tickers
@@ -362,13 +386,12 @@ func (s *RPCServer) GetTickers(ctx context.Context, r *gctrpc.GetTickersRequest)
// GetOrderbook returns an orderbook for a specific exchange, currency pair
// and asset type
-func (s *RPCServer) GetOrderbook(ctx context.Context, r *gctrpc.GetOrderbookRequest) (*gctrpc.OrderbookResponse, error) {
- ob, err := GetSpecificOrderbook(
- currency.Pair{
- Delimiter: r.Pair.Delimiter,
- Base: currency.NewCode(r.Pair.Base),
- Quote: currency.NewCode(r.Pair.Quote),
- },
+func (s *RPCServer) GetOrderbook(_ context.Context, r *gctrpc.GetOrderbookRequest) (*gctrpc.OrderbookResponse, error) {
+ ob, err := GetSpecificOrderbook(currency.Pair{
+ Delimiter: r.Pair.Delimiter,
+ Base: currency.NewCode(r.Pair.Base),
+ Quote: currency.NewCode(r.Pair.Quote),
+ },
r.Exchange,
asset.Item(r.AssetType),
)
@@ -405,7 +428,7 @@ func (s *RPCServer) GetOrderbook(ctx context.Context, r *gctrpc.GetOrderbookRequ
// GetOrderbooks returns a list of orderbooks for all enabled exchanges and all
// enabled currency pairs
-func (s *RPCServer) GetOrderbooks(ctx context.Context, r *gctrpc.GetOrderbooksRequest) (*gctrpc.GetOrderbooksResponse, error) {
+func (s *RPCServer) GetOrderbooks(_ context.Context, r *gctrpc.GetOrderbooksRequest) (*gctrpc.GetOrderbooksResponse, error) {
activeOrderbooks := GetAllActiveOrderbooks()
var orderbooks []*gctrpc.Orderbooks
@@ -448,10 +471,10 @@ func (s *RPCServer) GetOrderbooks(ctx context.Context, r *gctrpc.GetOrderbooksRe
}
// GetAccountInfo returns an account balance for a specific exchange
-func (s *RPCServer) GetAccountInfo(ctx context.Context, r *gctrpc.GetAccountInfoRequest) (*gctrpc.GetAccountInfoResponse, error) {
+func (s *RPCServer) GetAccountInfo(_ context.Context, r *gctrpc.GetAccountInfoRequest) (*gctrpc.GetAccountInfoResponse, error) {
exch := GetExchangeByName(r.Exchange)
if exch == nil {
- return nil, errors.New("exchange is not loaded/doesn't exist")
+ return nil, errExchangeNotLoaded
}
resp, err := exch.FetchAccountInfo()
@@ -484,7 +507,7 @@ func (s *RPCServer) GetAccountInfoStream(r *gctrpc.GetAccountInfoRequest, stream
exch := GetExchangeByName(r.Exchange)
if exch == nil {
- return errors.New("exchange is not loaded/doesn't exist")
+ return errExchangeNotLoaded
}
initAcc, err := exch.FetchAccountInfo()
@@ -558,12 +581,12 @@ func (s *RPCServer) GetAccountInfoStream(r *gctrpc.GetAccountInfoRequest, stream
}
// GetConfig returns the bots config
-func (s *RPCServer) GetConfig(ctx context.Context, r *gctrpc.GetConfigRequest) (*gctrpc.GetConfigResponse, error) {
+func (s *RPCServer) GetConfig(_ context.Context, r *gctrpc.GetConfigRequest) (*gctrpc.GetConfigResponse, error) {
return &gctrpc.GetConfigResponse{}, common.ErrNotYetImplemented
}
// GetPortfolio returns the portfolio details
-func (s *RPCServer) GetPortfolio(ctx context.Context, r *gctrpc.GetPortfolioRequest) (*gctrpc.GetPortfolioResponse, error) {
+func (s *RPCServer) GetPortfolio(_ context.Context, r *gctrpc.GetPortfolioRequest) (*gctrpc.GetPortfolioResponse, error) {
var addrs []*gctrpc.PortfolioAddress
botAddrs := Bot.Portfolio.Addresses
@@ -584,7 +607,7 @@ func (s *RPCServer) GetPortfolio(ctx context.Context, r *gctrpc.GetPortfolioRequ
}
// GetPortfolioSummary returns the portfolio summary
-func (s *RPCServer) GetPortfolioSummary(ctx context.Context, r *gctrpc.GetPortfolioSummaryRequest) (*gctrpc.GetPortfolioSummaryResponse, error) {
+func (s *RPCServer) GetPortfolioSummary(_ context.Context, r *gctrpc.GetPortfolioSummaryRequest) (*gctrpc.GetPortfolioSummaryResponse, error) {
result := Bot.Portfolio.GetPortfolioSummary()
var resp gctrpc.GetPortfolioSummaryResponse
@@ -640,22 +663,30 @@ func (s *RPCServer) GetPortfolioSummary(ctx context.Context, r *gctrpc.GetPortfo
}
// AddPortfolioAddress adds an address to the portfolio manager
-func (s *RPCServer) AddPortfolioAddress(ctx context.Context, r *gctrpc.AddPortfolioAddressRequest) (*gctrpc.AddPortfolioAddressResponse, error) {
- err := Bot.Portfolio.AddAddress(r.Address, r.Description, currency.NewCode(r.CoinType), r.Balance)
+func (s *RPCServer) AddPortfolioAddress(_ context.Context, r *gctrpc.AddPortfolioAddressRequest) (*gctrpc.GenericResponse, error) {
+ err := Bot.Portfolio.AddAddress(r.Address,
+ r.Description,
+ currency.NewCode(r.CoinType),
+ r.Balance)
if err != nil {
return nil, err
}
- return &gctrpc.AddPortfolioAddressResponse{}, err
+ return &gctrpc.GenericResponse{Status: MsgStatusSuccess}, nil
}
// RemovePortfolioAddress removes an address from the portfolio manager
-func (s *RPCServer) RemovePortfolioAddress(ctx context.Context, r *gctrpc.RemovePortfolioAddressRequest) (*gctrpc.RemovePortfolioAddressResponse, error) {
- err := Bot.Portfolio.RemoveAddress(r.Address, r.Description, currency.NewCode(r.CoinType))
- return &gctrpc.RemovePortfolioAddressResponse{}, err
+func (s *RPCServer) RemovePortfolioAddress(_ context.Context, r *gctrpc.RemovePortfolioAddressRequest) (*gctrpc.GenericResponse, error) {
+ err := Bot.Portfolio.RemoveAddress(r.Address,
+ r.Description,
+ currency.NewCode(r.CoinType))
+ if err != nil {
+ return nil, err
+ }
+ return &gctrpc.GenericResponse{Status: MsgStatusSuccess}, nil
}
// GetForexProviders returns a list of available forex providers
-func (s *RPCServer) GetForexProviders(ctx context.Context, r *gctrpc.GetForexProvidersRequest) (*gctrpc.GetForexProvidersResponse, error) {
+func (s *RPCServer) GetForexProviders(_ context.Context, r *gctrpc.GetForexProvidersRequest) (*gctrpc.GetForexProvidersResponse, error) {
providers := Bot.Config.GetForexProviders()
if len(providers) == 0 {
return nil, fmt.Errorf("forex providers is empty")
@@ -677,7 +708,7 @@ func (s *RPCServer) GetForexProviders(ctx context.Context, r *gctrpc.GetForexPro
}
// GetForexRates returns a list of forex rates
-func (s *RPCServer) GetForexRates(ctx context.Context, r *gctrpc.GetForexRatesRequest) (*gctrpc.GetForexRatesResponse, error) {
+func (s *RPCServer) GetForexRates(_ context.Context, r *gctrpc.GetForexRatesRequest) (*gctrpc.GetForexRatesResponse, error) {
rates, err := currency.GetExchangeRates()
if err != nil {
return nil, err
@@ -712,10 +743,10 @@ func (s *RPCServer) GetForexRates(ctx context.Context, r *gctrpc.GetForexRatesRe
// GetOrders returns all open orders, filtered by exchange, currency pair or
// asset type
-func (s *RPCServer) GetOrders(ctx context.Context, r *gctrpc.GetOrdersRequest) (*gctrpc.GetOrdersResponse, error) {
+func (s *RPCServer) GetOrders(_ context.Context, r *gctrpc.GetOrdersRequest) (*gctrpc.GetOrdersResponse, error) {
exch := GetExchangeByName(r.Exchange)
if exch == nil {
- return nil, errors.New("exchange is not loaded/doesn't exist")
+ return nil, errExchangeNotLoaded
}
resp, err := exch.GetActiveOrders(&order.GetOrdersRequest{
@@ -749,10 +780,10 @@ func (s *RPCServer) GetOrders(ctx context.Context, r *gctrpc.GetOrdersRequest) (
}
// GetOrder returns order information based on exchange and order ID
-func (s *RPCServer) GetOrder(ctx context.Context, r *gctrpc.GetOrderRequest) (*gctrpc.OrderDetails, error) {
+func (s *RPCServer) GetOrder(_ context.Context, r *gctrpc.GetOrderRequest) (*gctrpc.OrderDetails, error) {
exch := GetExchangeByName(r.Exchange)
if exch == nil {
- return nil, errors.New("exchange is not loaded/doesn't exist")
+ return nil, errExchangeNotLoaded
}
result, err := exch.GetOrderInfo(r.OrderId)
if err != nil {
@@ -791,14 +822,18 @@ func (s *RPCServer) GetOrder(ctx context.Context, r *gctrpc.GetOrderRequest) (*g
// SubmitOrder submits an order specified by exchange, currency pair and asset
// type
-func (s *RPCServer) SubmitOrder(ctx context.Context, r *gctrpc.SubmitOrderRequest) (*gctrpc.SubmitOrderResponse, error) {
+func (s *RPCServer) SubmitOrder(_ context.Context, r *gctrpc.SubmitOrderRequest) (*gctrpc.SubmitOrderResponse, error) {
exch := GetExchangeByName(r.Exchange)
if exch == nil {
- return nil, errors.New("exchange is not loaded/doesn't exist")
+ return nil, errExchangeNotLoaded
}
- p := currency.NewPairFromStrings(r.Pair.Base, r.Pair.Quote)
- resp, err := Bot.OrderManager.Submit(&order.Submit{
+ p, err := currency.NewPairFromStrings(r.Pair.Base, r.Pair.Quote)
+ if err != nil {
+ return nil, err
+ }
+
+ submission := &order.Submit{
Pair: p,
Side: order.Side(r.Side),
Type: order.Type(r.OrderType),
@@ -806,8 +841,9 @@ func (s *RPCServer) SubmitOrder(ctx context.Context, r *gctrpc.SubmitOrderReques
Price: r.Price,
ClientID: r.ClientId,
Exchange: r.Exchange,
- })
+ }
+ resp, err := exch.SubmitOrder(submission)
if err != nil {
return &gctrpc.SubmitOrderResponse{}, err
}
@@ -820,13 +856,17 @@ func (s *RPCServer) SubmitOrder(ctx context.Context, r *gctrpc.SubmitOrderReques
// SimulateOrder simulates an order specified by exchange, currency pair and asset
// type
-func (s *RPCServer) SimulateOrder(ctx context.Context, r *gctrpc.SimulateOrderRequest) (*gctrpc.SimulateOrderResponse, error) {
+func (s *RPCServer) SimulateOrder(_ context.Context, r *gctrpc.SimulateOrderRequest) (*gctrpc.SimulateOrderResponse, error) {
exch := GetExchangeByName(r.Exchange)
if exch == nil {
- return nil, errors.New("exchange is not loaded/doesn't exist")
+ return nil, errExchangeNotLoaded
+ }
+
+ p, err := currency.NewPairFromStrings(r.Pair.Base, r.Pair.Quote)
+ if err != nil {
+ return nil, err
}
- p := currency.NewPairFromStrings(r.Pair.Base, r.Pair.Quote)
o, err := exch.FetchOrderbook(p, asset.Spot)
if err != nil {
return nil, err
@@ -857,13 +897,17 @@ func (s *RPCServer) SimulateOrder(ctx context.Context, r *gctrpc.SimulateOrderRe
// WhaleBomb finds the amount required to reach a specific price target for a given exchange, pair
// and asset type
-func (s *RPCServer) WhaleBomb(ctx context.Context, r *gctrpc.WhaleBombRequest) (*gctrpc.SimulateOrderResponse, error) {
+func (s *RPCServer) WhaleBomb(_ context.Context, r *gctrpc.WhaleBombRequest) (*gctrpc.SimulateOrderResponse, error) {
exch := GetExchangeByName(r.Exchange)
if exch == nil {
- return nil, errors.New("exchange is not loaded/doesn't exist")
+ return nil, errExchangeNotLoaded
+ }
+
+ p, err := currency.NewPairFromStrings(r.Pair.Base, r.Pair.Quote)
+ if err != nil {
+ return nil, err
}
- p := currency.NewPairFromStrings(r.Pair.Base, r.Pair.Quote)
o, err := exch.FetchOrderbook(p, asset.Spot)
if err != nil {
return nil, err
@@ -894,35 +938,43 @@ func (s *RPCServer) WhaleBomb(ctx context.Context, r *gctrpc.WhaleBombRequest) (
// CancelOrder cancels an order specified by exchange, currency pair and asset
// type
-func (s *RPCServer) CancelOrder(ctx context.Context, r *gctrpc.CancelOrderRequest) (*gctrpc.CancelOrderResponse, error) {
+func (s *RPCServer) CancelOrder(_ context.Context, r *gctrpc.CancelOrderRequest) (*gctrpc.GenericResponse, error) {
exch := GetExchangeByName(r.Exchange)
if exch == nil {
- return nil, errors.New("exchange is not loaded/doesn't exist")
+ return nil, errExchangeNotLoaded
}
- err := exch.CancelOrder(&order.Cancel{
+ p, err := currency.NewPairFromStrings(r.Pair.Base, r.Pair.Quote)
+ if err != nil {
+ return nil, err
+ }
+
+ err = exch.CancelOrder(&order.Cancel{
AccountID: r.AccountId,
ID: r.OrderId,
Side: order.Side(r.Side),
WalletAddress: r.WalletAddress,
- Pair: currency.NewPairFromStrings(r.Pair.Base, r.Pair.Quote),
+ Pair: p,
})
-
- return &gctrpc.CancelOrderResponse{}, err
+ if err != nil {
+ return nil, err
+ }
+ return &gctrpc.GenericResponse{Status: MsgStatusSuccess,
+ Data: fmt.Sprintf("order %s cancelled", r.OrderId)}, nil
}
// CancelAllOrders cancels all orders, filterable by exchange
-func (s *RPCServer) CancelAllOrders(ctx context.Context, r *gctrpc.CancelAllOrdersRequest) (*gctrpc.CancelAllOrdersResponse, error) {
+func (s *RPCServer) CancelAllOrders(_ context.Context, r *gctrpc.CancelAllOrdersRequest) (*gctrpc.CancelAllOrdersResponse, error) {
return &gctrpc.CancelAllOrdersResponse{}, common.ErrNotYetImplemented
}
// GetEvents returns the stored events list
-func (s *RPCServer) GetEvents(ctx context.Context, r *gctrpc.GetEventsRequest) (*gctrpc.GetEventsResponse, error) {
+func (s *RPCServer) GetEvents(_ context.Context, r *gctrpc.GetEventsRequest) (*gctrpc.GetEventsResponse, error) {
return &gctrpc.GetEventsResponse{}, common.ErrNotYetImplemented
}
// AddEvent adds an event
-func (s *RPCServer) AddEvent(ctx context.Context, r *gctrpc.AddEventRequest) (*gctrpc.AddEventResponse, error) {
+func (s *RPCServer) AddEvent(_ context.Context, r *gctrpc.AddEventRequest) (*gctrpc.AddEventResponse, error) {
evtCondition := EventConditionParams{
CheckBids: r.ConditionParams.CheckBids,
CheckBidsAndAsks: r.ConditionParams.CheckBidsAndAsks,
@@ -943,17 +995,20 @@ func (s *RPCServer) AddEvent(ctx context.Context, r *gctrpc.AddEventRequest) (*g
}
// RemoveEvent removes an event, specified by an event ID
-func (s *RPCServer) RemoveEvent(ctx context.Context, r *gctrpc.RemoveEventRequest) (*gctrpc.RemoveEventResponse, error) {
- Remove(r.Id)
- return &gctrpc.RemoveEventResponse{}, nil
+func (s *RPCServer) RemoveEvent(_ context.Context, r *gctrpc.RemoveEventRequest) (*gctrpc.GenericResponse, error) {
+ if !Remove(r.Id) {
+ return nil, fmt.Errorf("event %d not removed", r.Id)
+ }
+ return &gctrpc.GenericResponse{Status: MsgStatusSuccess,
+ Data: fmt.Sprintf("event %d removed", r.Id)}, nil
}
// GetCryptocurrencyDepositAddresses returns a list of cryptocurrency deposit
// addresses specified by an exchange
-func (s *RPCServer) GetCryptocurrencyDepositAddresses(ctx context.Context, r *gctrpc.GetCryptocurrencyDepositAddressesRequest) (*gctrpc.GetCryptocurrencyDepositAddressesResponse, error) {
+func (s *RPCServer) GetCryptocurrencyDepositAddresses(_ context.Context, r *gctrpc.GetCryptocurrencyDepositAddressesRequest) (*gctrpc.GetCryptocurrencyDepositAddressesResponse, error) {
exch := GetExchangeByName(r.Exchange)
if exch == nil {
- return nil, errors.New("exchange is not loaded/doesn't exist")
+ return nil, errExchangeNotLoaded
}
result, err := GetCryptocurrencyDepositAddressesByExchange(r.Exchange)
@@ -962,10 +1017,10 @@ func (s *RPCServer) GetCryptocurrencyDepositAddresses(ctx context.Context, r *gc
// GetCryptocurrencyDepositAddress returns a cryptocurrency deposit address
// specified by exchange and cryptocurrency
-func (s *RPCServer) GetCryptocurrencyDepositAddress(ctx context.Context, r *gctrpc.GetCryptocurrencyDepositAddressRequest) (*gctrpc.GetCryptocurrencyDepositAddressResponse, error) {
+func (s *RPCServer) GetCryptocurrencyDepositAddress(_ context.Context, r *gctrpc.GetCryptocurrencyDepositAddressRequest) (*gctrpc.GetCryptocurrencyDepositAddressResponse, error) {
exch := GetExchangeByName(r.Exchange)
if exch == nil {
- return nil, errors.New("exchange is not loaded/doesn't exist")
+ return nil, errExchangeNotLoaded
}
addr, err := GetExchangeCryptocurrencyDepositAddress(r.Exchange, "", currency.NewCode(r.Cryptocurrency))
@@ -974,10 +1029,10 @@ func (s *RPCServer) GetCryptocurrencyDepositAddress(ctx context.Context, r *gctr
// WithdrawCryptocurrencyFunds withdraws cryptocurrency funds specified by
// exchange
-func (s *RPCServer) WithdrawCryptocurrencyFunds(ctx context.Context, r *gctrpc.WithdrawCryptoRequest) (*gctrpc.WithdrawResponse, error) {
+func (s *RPCServer) WithdrawCryptocurrencyFunds(_ context.Context, r *gctrpc.WithdrawCryptoRequest) (*gctrpc.WithdrawResponse, error) {
exch := GetExchangeByName(r.Exchange)
if exch == nil {
- return nil, errors.New("exchange is not loaded/doesn't exist")
+ return nil, errExchangeNotLoaded
}
request := &withdraw.Request{
@@ -1004,17 +1059,20 @@ func (s *RPCServer) WithdrawCryptocurrencyFunds(ctx context.Context, r *gctrpc.W
}
// WithdrawFiatFunds withdraws fiat funds specified by exchange
-func (s *RPCServer) WithdrawFiatFunds(ctx context.Context, r *gctrpc.WithdrawFiatRequest) (*gctrpc.WithdrawResponse, error) {
+func (s *RPCServer) WithdrawFiatFunds(_ context.Context, r *gctrpc.WithdrawFiatRequest) (*gctrpc.WithdrawResponse, error) {
exch := GetExchangeByName(r.Exchange)
if exch == nil {
- return nil, errors.New("exchange is not loaded/doesn't exist")
+ return nil, errExchangeNotLoaded
}
var bankAccount *banking.Account
-
bankAccount, err := banking.GetBankAccountByID(r.BankAccountId)
if err != nil {
- bankAccount, err = exch.GetBase().GetExchangeBankAccounts(r.BankAccountId, r.Currency)
+ base := exch.GetBase()
+ if base == nil {
+ return nil, errExchangeBaseNotFound
+ }
+ bankAccount, err = base.GetExchangeBankAccounts(r.BankAccountId, r.Currency)
if err != nil {
return nil, err
}
@@ -1041,7 +1099,7 @@ func (s *RPCServer) WithdrawFiatFunds(ctx context.Context, r *gctrpc.WithdrawFia
}
// WithdrawalEventByID returns previous withdrawal request details
-func (s *RPCServer) WithdrawalEventByID(ctx context.Context, r *gctrpc.WithdrawalEventByIDRequest) (*gctrpc.WithdrawalEventByIDResponse, error) {
+func (s *RPCServer) WithdrawalEventByID(_ context.Context, r *gctrpc.WithdrawalEventByIDRequest) (*gctrpc.WithdrawalEventByIDResponse, error) {
if !Bot.Config.Database.Enabled {
return nil, database.ErrDatabaseSupportDisabled
}
@@ -1103,7 +1161,7 @@ func (s *RPCServer) WithdrawalEventByID(ctx context.Context, r *gctrpc.Withdrawa
}
// WithdrawalEventsByExchange returns previous withdrawal request details by exchange
-func (s *RPCServer) WithdrawalEventsByExchange(ctx context.Context, r *gctrpc.WithdrawalEventsByExchangeRequest) (*gctrpc.WithdrawalEventsByExchangeResponse, error) {
+func (s *RPCServer) WithdrawalEventsByExchange(_ context.Context, r *gctrpc.WithdrawalEventsByExchangeRequest) (*gctrpc.WithdrawalEventsByExchangeResponse, error) {
if !Bot.Config.Database.Enabled {
return nil, database.ErrDatabaseSupportDisabled
}
@@ -1124,7 +1182,7 @@ func (s *RPCServer) WithdrawalEventsByExchange(ctx context.Context, r *gctrpc.Wi
}
// WithdrawalEventsByDate returns previous withdrawal request details by exchange
-func (s *RPCServer) WithdrawalEventsByDate(ctx context.Context, r *gctrpc.WithdrawalEventsByDateRequest) (*gctrpc.WithdrawalEventsByExchangeResponse, error) {
+func (s *RPCServer) WithdrawalEventsByDate(_ context.Context, r *gctrpc.WithdrawalEventsByDateRequest) (*gctrpc.WithdrawalEventsByExchangeResponse, error) {
UTCStartTime, err := time.Parse(common.SimpleTimeFormat, r.Start)
if err != nil {
return nil, err
@@ -1143,7 +1201,7 @@ func (s *RPCServer) WithdrawalEventsByDate(ctx context.Context, r *gctrpc.Withdr
}
// GetLoggerDetails returns a loggers details
-func (s *RPCServer) GetLoggerDetails(ctx context.Context, r *gctrpc.GetLoggerDetailsRequest) (*gctrpc.GetLoggerDetailsResponse, error) {
+func (s *RPCServer) GetLoggerDetails(_ context.Context, r *gctrpc.GetLoggerDetailsRequest) (*gctrpc.GetLoggerDetailsResponse, error) {
levels, err := log.Level(r.Logger)
if err != nil {
return nil, err
@@ -1158,7 +1216,7 @@ func (s *RPCServer) GetLoggerDetails(ctx context.Context, r *gctrpc.GetLoggerDet
}
// SetLoggerDetails sets a loggers details
-func (s *RPCServer) SetLoggerDetails(ctx context.Context, r *gctrpc.SetLoggerDetailsRequest) (*gctrpc.GetLoggerDetailsResponse, error) {
+func (s *RPCServer) SetLoggerDetails(_ context.Context, r *gctrpc.SetLoggerDetailsRequest) (*gctrpc.GetLoggerDetailsResponse, error) {
levels, err := log.SetLevel(r.Logger, r.Level)
if err != nil {
return nil, err
@@ -1173,7 +1231,7 @@ func (s *RPCServer) SetLoggerDetails(ctx context.Context, r *gctrpc.SetLoggerDet
}
// GetExchangePairs returns a list of exchange supported assets and related pairs
-func (s *RPCServer) GetExchangePairs(ctx context.Context, r *gctrpc.GetExchangePairsRequest) (*gctrpc.GetExchangePairsResponse, error) {
+func (s *RPCServer) GetExchangePairs(_ context.Context, r *gctrpc.GetExchangePairsRequest) (*gctrpc.GetExchangePairsResponse, error) {
exchCfg, err := Bot.Config.GetExchangeConfig(r.Exchange)
if err != nil {
return nil, err
@@ -1188,84 +1246,105 @@ func (s *RPCServer) GetExchangePairs(ctx context.Context, r *gctrpc.GetExchangeP
resp.SupportedAssets = make(map[string]*gctrpc.PairsSupported)
assetTypes := exchCfg.CurrencyPairs.GetAssetTypes()
for x := range assetTypes {
- a := assetTypes[x]
- if r.Asset != "" && !strings.EqualFold(a.String(), r.Asset) {
+ if r.Asset != "" && !strings.EqualFold(assetTypes[x].String(), r.Asset) {
continue
}
- resp.SupportedAssets[a.String()] = &gctrpc.PairsSupported{
- AvailablePairs: exchCfg.CurrencyPairs.Get(a).Available.Join(),
- EnabledPairs: exchCfg.CurrencyPairs.Get(a).Enabled.Join(),
+
+ ps, err := exchCfg.CurrencyPairs.Get(assetTypes[x])
+ if err != nil {
+ return nil, err
+ }
+
+ resp.SupportedAssets[assetTypes[x].String()] = &gctrpc.PairsSupported{
+ AvailablePairs: ps.Available.Join(),
+ EnabledPairs: ps.Enabled.Join(),
}
}
return &resp, nil
}
-// EnableExchangePair enables the specified pair on an exchange
-func (s *RPCServer) EnableExchangePair(ctx context.Context, r *gctrpc.ExchangePairRequest) (*gctrpc.GenericExchangeNameResponse, error) {
+// SetExchangePair enables/disabled the specified pair(s) on an exchange
+func (s *RPCServer) SetExchangePair(_ context.Context, r *gctrpc.SetExchangePairRequest) (*gctrpc.GenericResponse, error) {
exchCfg, err := Bot.Config.GetExchangeConfig(r.Exchange)
if err != nil {
return nil, err
}
- if r.AssetType != "" &&
- !exchCfg.CurrencyPairs.GetAssetTypes().Contains(asset.Item(r.AssetType)) {
+ if r.AssetType == "" {
+ return nil, errors.New("asset type must be specified")
+ }
+
+ if !exchCfg.CurrencyPairs.GetAssetTypes().Contains(asset.Item(r.AssetType)) {
return nil, errors.New("specified asset type does not exist")
}
- // Default to spot asset type unless set
- a := asset.Spot
- if r.AssetType != "" {
- a = asset.Item(r.AssetType)
+ a := asset.Item(r.AssetType)
+
+ exch := GetExchangeByName(r.Exchange)
+ if exch == nil {
+ return nil, errExchangeNotLoaded
+ }
+
+ base := exch.GetBase()
+ if base == nil {
+ return nil, errExchangeBaseNotFound
}
pairFmt, err := Bot.Config.GetPairFormat(r.Exchange, a)
if err != nil {
return nil, err
}
+ var pass bool
+ var newErrors common.Errors
+ for i := range r.Pairs {
+ var p currency.Pair
+ p, err = currency.NewPairFromStrings(r.Pairs[i].Base, r.Pairs[i].Quote)
+ if err != nil {
+ return nil, err
+ }
- p := currency.NewPairFromStrings(r.Pair.Base, r.Pair.Quote).Format(
- pairFmt.Delimiter, pairFmt.Uppercase)
- err = exchCfg.CurrencyPairs.EnablePair(a, p)
- if err != nil {
- return nil, err
- }
- err = GetExchangeByName(r.Exchange).GetBase().CurrencyPairs.EnablePair(
- asset.Item(r.AssetType), p)
- return &gctrpc.GenericExchangeNameResponse{}, err
-}
+ if r.Enable {
+ err = exchCfg.CurrencyPairs.EnablePair(a,
+ p.Format(pairFmt.Delimiter, pairFmt.Uppercase))
+ if err != nil {
+ newErrors = append(newErrors, err)
+ continue
+ }
+ err = base.CurrencyPairs.EnablePair(asset.Item(r.AssetType), p)
+ if err != nil {
+ newErrors = append(newErrors, err)
+ continue
+ }
+ pass = true
+ continue
+ }
-// DisableExchangePair disables the specified pair on an exchange
-func (s *RPCServer) DisableExchangePair(ctx context.Context, r *gctrpc.ExchangePairRequest) (*gctrpc.GenericExchangeNameResponse, error) {
- exchCfg, err := Bot.Config.GetExchangeConfig(r.Exchange)
- if err != nil {
- return nil, err
+ err = exchCfg.CurrencyPairs.DisablePair(asset.Item(r.AssetType),
+ p.Format(pairFmt.Delimiter, pairFmt.Uppercase))
+ if err != nil {
+ newErrors = append(newErrors, err)
+ continue
+ }
+ err = base.CurrencyPairs.DisablePair(asset.Item(r.AssetType), p)
+ if err != nil {
+ newErrors = append(newErrors, err)
+ continue
+ }
+ pass = true
}
- if r.AssetType != "" &&
- !exchCfg.CurrencyPairs.GetAssetTypes().Contains(asset.Item(r.AssetType)) {
- return nil, errors.New("specified asset type does not exist")
+ if exch.IsWebsocketEnabled() && pass && base.Websocket.IsConnected() {
+ err = exch.FlushWebsocketChannels()
+ if err != nil {
+ newErrors = append(newErrors, err)
+ }
}
- // Default to spot asset type unless set
- a := asset.Spot
- if r.AssetType != "" {
- a = asset.Item(r.AssetType)
+ if newErrors != nil {
+ return nil, newErrors
}
- pairFmt, err := Bot.Config.GetPairFormat(r.Exchange, a)
- if err != nil {
- return nil, err
- }
-
- p := currency.NewPairFromStrings(r.Pair.Base, r.Pair.Quote).Format(
- pairFmt.Delimiter, pairFmt.Uppercase)
- err = exchCfg.CurrencyPairs.DisablePair(asset.Item(r.AssetType), p)
- if err != nil {
- return nil, err
- }
- err = GetExchangeByName(r.Exchange).GetBase().CurrencyPairs.DisablePair(
- asset.Item(r.AssetType), p)
- return &gctrpc.GenericExchangeNameResponse{}, err
+ return &gctrpc.GenericResponse{Status: MsgStatusSuccess}, nil
}
// GetOrderbookStream streams the requested updated orderbook
@@ -1282,7 +1361,10 @@ func (s *RPCServer) GetOrderbookStream(r *gctrpc.GetOrderbookStreamRequest, stre
return errors.New(errAssetTypeUnset)
}
- p := currency.NewPairFromStrings(r.Pair.Base, r.Pair.Quote)
+ p, err := currency.NewPairFromStrings(r.Pair.Base, r.Pair.Quote)
+ if err != nil {
+ return err
+ }
pipe, err := orderbook.SubscribeOrderbook(r.Exchange, p, asset.Item(r.AssetType))
if err != nil {
@@ -1388,7 +1470,10 @@ func (s *RPCServer) GetTickerStream(r *gctrpc.GetTickerStreamRequest, stream gct
return errors.New(errAssetTypeUnset)
}
- p := currency.NewPairFromStrings(r.Pair.Base, r.Pair.Quote)
+ p, err := currency.NewPairFromStrings(r.Pair.Base, r.Pair.Quote)
+ if err != nil {
+ return err
+ }
pipe, err := ticker.SubscribeTicker(r.Exchange, p, asset.Item(r.AssetType))
if err != nil {
@@ -1465,7 +1550,7 @@ func (s *RPCServer) GetExchangeTickerStream(r *gctrpc.GetExchangeTickerStreamReq
}
// GetAuditEvent returns matching audit events from database
-func (s *RPCServer) GetAuditEvent(ctx context.Context, r *gctrpc.GetAuditEventRequest) (*gctrpc.GetAuditEventResponse, error) {
+func (s *RPCServer) GetAuditEvent(_ context.Context, r *gctrpc.GetAuditEventRequest) (*gctrpc.GetAuditEventResponse, error) {
UTCStartTime, err := time.Parse(common.SimpleTimeFormat, r.StartDate)
if err != nil {
return nil, err
@@ -1513,7 +1598,7 @@ func (s *RPCServer) GetAuditEvent(ctx context.Context, r *gctrpc.GetAuditEventRe
}
// GetHistoricCandles returns historical candles for a given exchange
-func (s *RPCServer) GetHistoricCandles(ctx context.Context, req *gctrpc.GetHistoricCandlesRequest) (*gctrpc.GetHistoricCandlesResponse, error) {
+func (s *RPCServer) GetHistoricCandles(_ context.Context, req *gctrpc.GetHistoricCandlesRequest) (*gctrpc.GetHistoricCandlesResponse, error) {
if req.Exchange == "" {
return nil, errors.New(errExchangeNameUnset)
}
@@ -1577,7 +1662,7 @@ func (s *RPCServer) GetHistoricCandles(ctx context.Context, req *gctrpc.GetHisto
}
// GCTScriptStatus returns a slice of current running scripts that includes next run time and uuid
-func (s *RPCServer) GCTScriptStatus(ctx context.Context, r *gctrpc.GCTScriptStatusRequest) (*gctrpc.GCTScriptStatusResponse, error) {
+func (s *RPCServer) GCTScriptStatus(_ context.Context, r *gctrpc.GCTScriptStatusRequest) (*gctrpc.GCTScriptStatusResponse, error) {
if !gctscript.GCTScriptConfig.Enabled {
return &gctrpc.GCTScriptStatusResponse{Status: gctscript.ErrScriptingDisabled.Error()}, nil
}
@@ -1605,7 +1690,7 @@ func (s *RPCServer) GCTScriptStatus(ctx context.Context, r *gctrpc.GCTScriptStat
}
// GCTScriptQuery queries a running script and returns script running information
-func (s *RPCServer) GCTScriptQuery(ctx context.Context, r *gctrpc.GCTScriptQueryRequest) (*gctrpc.GCTScriptQueryResponse, error) {
+func (s *RPCServer) GCTScriptQuery(_ context.Context, r *gctrpc.GCTScriptQueryRequest) (*gctrpc.GCTScriptQueryResponse, error) {
if !gctscript.GCTScriptConfig.Enabled {
return &gctrpc.GCTScriptQueryResponse{Status: gctscript.ErrScriptingDisabled.Error()}, nil
}
@@ -1636,9 +1721,9 @@ func (s *RPCServer) GCTScriptQuery(ctx context.Context, r *gctrpc.GCTScriptQuery
}
// GCTScriptExecute execute a script
-func (s *RPCServer) GCTScriptExecute(ctx context.Context, r *gctrpc.GCTScriptExecuteRequest) (*gctrpc.GCTScriptGenericResponse, error) {
+func (s *RPCServer) GCTScriptExecute(_ context.Context, r *gctrpc.GCTScriptExecuteRequest) (*gctrpc.GenericResponse, error) {
if !gctscript.GCTScriptConfig.Enabled {
- return &gctrpc.GCTScriptGenericResponse{Status: gctscript.ErrScriptingDisabled.Error()}, nil
+ return &gctrpc.GenericResponse{Status: gctscript.ErrScriptingDisabled.Error()}, nil
}
if r.Script.Path == "" {
@@ -1647,13 +1732,13 @@ func (s *RPCServer) GCTScriptExecute(ctx context.Context, r *gctrpc.GCTScriptExe
gctVM := gctscript.New()
if gctVM == nil {
- return &gctrpc.GCTScriptGenericResponse{Status: MsgStatusError, Data: "unable to create VM instance"}, nil
+ return &gctrpc.GenericResponse{Status: MsgStatusError, Data: "unable to create VM instance"}, nil
}
script := filepath.Join(r.Script.Path, r.Script.Name)
err := gctVM.Load(script)
if err != nil {
- return &gctrpc.GCTScriptGenericResponse{
+ return &gctrpc.GenericResponse{
Status: MsgStatusError,
Data: err.Error(),
}, nil
@@ -1661,21 +1746,21 @@ func (s *RPCServer) GCTScriptExecute(ctx context.Context, r *gctrpc.GCTScriptExe
go gctVM.CompileAndRun()
- return &gctrpc.GCTScriptGenericResponse{
+ return &gctrpc.GenericResponse{
Status: MsgStatusOK,
Data: gctVM.ShortName() + " (" + gctVM.ID.String() + ") executed",
}, nil
}
// GCTScriptStop terminate a running script
-func (s *RPCServer) GCTScriptStop(ctx context.Context, r *gctrpc.GCTScriptStopRequest) (*gctrpc.GCTScriptGenericResponse, error) {
+func (s *RPCServer) GCTScriptStop(_ context.Context, r *gctrpc.GCTScriptStopRequest) (*gctrpc.GenericResponse, error) {
if !gctscript.GCTScriptConfig.Enabled {
- return &gctrpc.GCTScriptGenericResponse{Status: gctscript.ErrScriptingDisabled.Error()}, nil
+ return &gctrpc.GenericResponse{Status: gctscript.ErrScriptingDisabled.Error()}, nil
}
UUID, err := uuid.FromString(r.Script.UUID)
if err != nil {
- return &gctrpc.GCTScriptGenericResponse{Status: MsgStatusError, Data: err.Error()}, nil
+ return &gctrpc.GenericResponse{Status: MsgStatusError, Data: err.Error()}, nil
}
if v, f := gctscript.AllVMSync.Load(UUID); f {
@@ -1684,15 +1769,15 @@ func (s *RPCServer) GCTScriptStop(ctx context.Context, r *gctrpc.GCTScriptStopRe
if err != nil {
status = " " + err.Error()
}
- return &gctrpc.GCTScriptGenericResponse{Status: MsgStatusOK, Data: v.(*gctscript.VM).ID.String() + status}, nil
+ return &gctrpc.GenericResponse{Status: MsgStatusOK, Data: v.(*gctscript.VM).ID.String() + status}, nil
}
- return &gctrpc.GCTScriptGenericResponse{Status: MsgStatusError, Data: "no running script found"}, nil
+ return &gctrpc.GenericResponse{Status: MsgStatusError, Data: "no running script found"}, nil
}
// GCTScriptUpload upload a new script to ScriptPath
-func (s *RPCServer) GCTScriptUpload(ctx context.Context, r *gctrpc.GCTScriptUploadRequest) (*gctrpc.GCTScriptGenericResponse, error) {
+func (s *RPCServer) GCTScriptUpload(_ context.Context, r *gctrpc.GCTScriptUploadRequest) (*gctrpc.GenericResponse, error) {
if !gctscript.GCTScriptConfig.Enabled {
- return &gctrpc.GCTScriptGenericResponse{Status: gctscript.ErrScriptingDisabled.Error()}, nil
+ return &gctrpc.GenericResponse{Status: gctscript.ErrScriptingDisabled.Error()}, nil
}
fPath := filepath.Join(gctscript.ScriptPath, r.ScriptName)
@@ -1743,7 +1828,7 @@ func (s *RPCServer) GCTScriptUpload(ctx context.Context, r *gctrpc.GCTScriptUplo
files, errExtract := archive.UnZip(fPath, filepath.Join(gctscript.ScriptPath, r.ScriptName[:len(r.ScriptName)-4]))
if errExtract != nil {
log.Errorf(log.Global, "Failed to archive zip file %v", errExtract)
- return &gctrpc.GCTScriptGenericResponse{Status: MsgStatusError, Data: errExtract.Error()}, nil
+ return &gctrpc.GenericResponse{Status: MsgStatusError, Data: errExtract.Error()}, nil
}
var failedFiles []string
for x := range files {
@@ -1761,7 +1846,7 @@ func (s *RPCServer) GCTScriptUpload(ctx context.Context, r *gctrpc.GCTScriptUplo
if err != nil {
log.Errorf(log.GCTScriptMgr, "Failed to remove file %v (%v), manual deletion required", filepath.Base(fPath), err)
}
- return &gctrpc.GCTScriptGenericResponse{Status: ErrScriptFailedValidation, Data: strings.Join(failedFiles, ", ")}, nil
+ return &gctrpc.GenericResponse{Status: ErrScriptFailedValidation, Data: strings.Join(failedFiles, ", ")}, nil
}
} else {
err = gctscript.Validate(fPath)
@@ -1770,18 +1855,18 @@ func (s *RPCServer) GCTScriptUpload(ctx context.Context, r *gctrpc.GCTScriptUplo
if errRemove != nil {
log.Errorf(log.GCTScriptMgr, "Failed to remove file %v, manual deletion required: %v", filepath.Base(fPath), errRemove)
}
- return &gctrpc.GCTScriptGenericResponse{Status: ErrScriptFailedValidation, Data: err.Error()}, nil
+ return &gctrpc.GenericResponse{Status: ErrScriptFailedValidation, Data: err.Error()}, nil
}
}
- return &gctrpc.GCTScriptGenericResponse{
+ return &gctrpc.GenericResponse{
Status: MsgStatusOK,
Data: fmt.Sprintf("script %s written", newFile.Name()),
}, nil
}
// GCTScriptReadScript read a script and return contents
-func (s *RPCServer) GCTScriptReadScript(ctx context.Context, r *gctrpc.GCTScriptReadScriptRequest) (*gctrpc.GCTScriptQueryResponse, error) {
+func (s *RPCServer) GCTScriptReadScript(_ context.Context, r *gctrpc.GCTScriptReadScriptRequest) (*gctrpc.GCTScriptQueryResponse, error) {
if !gctscript.GCTScriptConfig.Enabled {
return &gctrpc.GCTScriptQueryResponse{Status: gctscript.ErrScriptingDisabled.Error()}, nil
}
@@ -1832,39 +1917,296 @@ func (s *RPCServer) GCTScriptListAll(context.Context, *gctrpc.GCTScriptListAllRe
}
// GCTScriptStopAll stops all running scripts
-func (s *RPCServer) GCTScriptStopAll(context.Context, *gctrpc.GCTScriptStopAllRequest) (*gctrpc.GCTScriptGenericResponse, error) {
+func (s *RPCServer) GCTScriptStopAll(context.Context, *gctrpc.GCTScriptStopAllRequest) (*gctrpc.GenericResponse, error) {
if !gctscript.GCTScriptConfig.Enabled {
- return &gctrpc.GCTScriptGenericResponse{Status: gctscript.ErrScriptingDisabled.Error()}, nil
+ return &gctrpc.GenericResponse{Status: gctscript.ErrScriptingDisabled.Error()}, nil
}
err := gctscript.ShutdownAll()
if err != nil {
- return &gctrpc.GCTScriptGenericResponse{Status: "error", Data: err.Error()}, nil
+ return &gctrpc.GenericResponse{Status: "error", Data: err.Error()}, nil
}
- return &gctrpc.GCTScriptGenericResponse{
+ return &gctrpc.GenericResponse{
Status: MsgStatusOK,
Data: "all running scripts have been stopped",
}, nil
}
// GCTScriptAutoLoadToggle adds or removes an entry to the autoload list
-func (s *RPCServer) GCTScriptAutoLoadToggle(ctx context.Context, r *gctrpc.GCTScriptAutoLoadRequest) (*gctrpc.GCTScriptGenericResponse, error) {
+func (s *RPCServer) GCTScriptAutoLoadToggle(_ context.Context, r *gctrpc.GCTScriptAutoLoadRequest) (*gctrpc.GenericResponse, error) {
if !gctscript.GCTScriptConfig.Enabled {
- return &gctrpc.GCTScriptGenericResponse{Status: gctscript.ErrScriptingDisabled.Error()}, nil
+ return &gctrpc.GenericResponse{Status: gctscript.ErrScriptingDisabled.Error()}, nil
}
if r.Status {
err := gctscript.Autoload(r.Script, true)
if err != nil {
- return &gctrpc.GCTScriptGenericResponse{Status: "error", Data: err.Error()}, nil
+ return &gctrpc.GenericResponse{Status: "error", Data: err.Error()}, nil
}
- return &gctrpc.GCTScriptGenericResponse{Status: "success", Data: "script " + r.Script + " removed from autoload list"}, nil
+ return &gctrpc.GenericResponse{Status: "success", Data: "script " + r.Script + " removed from autoload list"}, nil
}
err := gctscript.Autoload(r.Script, false)
if err != nil {
- return &gctrpc.GCTScriptGenericResponse{Status: "error", Data: err.Error()}, nil
+ return &gctrpc.GenericResponse{Status: "error", Data: err.Error()}, nil
}
- return &gctrpc.GCTScriptGenericResponse{Status: "success", Data: "script " + r.Script + " added to autoload list"}, nil
+ return &gctrpc.GenericResponse{Status: "success", Data: "script " + r.Script + " added to autoload list"}, nil
+}
+
+// SetExchangeAsset enables or disables an exchanges asset type
+func (s *RPCServer) SetExchangeAsset(_ context.Context, r *gctrpc.SetExchangeAssetRequest) (*gctrpc.GenericResponse, error) {
+ exch := GetExchangeByName(r.Exchange)
+ if exch == nil {
+ return nil, errExchangeNotLoaded
+ }
+
+ exchCfg, err := Bot.Config.GetExchangeConfig(r.Exchange)
+ if err != nil {
+ return nil, err
+ }
+
+ base := exch.GetBase()
+ if base == nil {
+ return nil, errExchangeBaseNotFound
+ }
+
+ if r.Asset == "" {
+ return nil, errors.New("asset type must be specified")
+ }
+
+ a := asset.Item(r.Asset)
+ err = base.CurrencyPairs.SetAssetEnabled(a, r.Enable)
+ if err != nil {
+ return nil, err
+ }
+ err = exchCfg.CurrencyPairs.SetAssetEnabled(a, r.Enable)
+ if err != nil {
+ return nil, err
+ }
+
+ return &gctrpc.GenericResponse{Status: MsgStatusSuccess}, nil
+}
+
+// SetAllExchangePairs enables or disables an exchanges pairs
+func (s *RPCServer) SetAllExchangePairs(_ context.Context, r *gctrpc.SetExchangeAllPairsRequest) (*gctrpc.GenericResponse, error) {
+ exch := GetExchangeByName(r.Exchange)
+ if exch == nil {
+ return nil, errExchangeNotLoaded
+ }
+
+ exchCfg, err := Bot.Config.GetExchangeConfig(r.Exchange)
+ if err != nil {
+ return nil, err
+ }
+
+ base := exch.GetBase()
+ if base == nil {
+ return nil, errExchangeBaseNotFound
+ }
+
+ assets := base.CurrencyPairs.GetAssetTypes()
+
+ if r.Enable {
+ for i := range assets {
+ var pairs currency.Pairs
+ pairs, err = base.CurrencyPairs.GetPairs(assets[i], false)
+ if err != nil {
+ return nil, err
+ }
+ exchCfg.CurrencyPairs.StorePairs(assets[i], pairs, true)
+ base.CurrencyPairs.StorePairs(assets[i], pairs, true)
+ }
+ } else {
+ for i := range assets {
+ exchCfg.CurrencyPairs.StorePairs(assets[i], nil, true)
+ base.CurrencyPairs.StorePairs(assets[i], nil, true)
+ }
+ }
+
+ if exch.IsWebsocketEnabled() && base.Websocket.IsConnected() {
+ err = exch.FlushWebsocketChannels()
+ if err != nil {
+ return nil, err
+ }
+ }
+
+ return &gctrpc.GenericResponse{Status: MsgStatusSuccess}, nil
+}
+
+// UpdateExchangeSupportedPairs forces an update of the supported pairs which
+// will update the available pairs list and remove any assets that are disabled
+// by the exchange
+func (s *RPCServer) UpdateExchangeSupportedPairs(_ context.Context, r *gctrpc.UpdateExchangeSupportedPairsRequest) (*gctrpc.GenericResponse, error) {
+ exch := GetExchangeByName(r.Exchange)
+ if exch == nil {
+ return nil, errExchangeNotLoaded
+ }
+
+ base := exch.GetBase()
+ if base == nil {
+ return nil, errExchangeBaseNotFound
+ }
+
+ if !base.GetEnabledFeatures().AutoPairUpdates {
+ return nil,
+ errors.New("cannot auto pair update for exchange, a manual update is needed")
+ }
+
+ err := exch.UpdateTradablePairs(false)
+ if err != nil {
+ return nil, err
+ }
+
+ if exch.IsWebsocketEnabled() {
+ err = exch.FlushWebsocketChannels()
+ if err != nil {
+ return nil, err
+ }
+ }
+ return &gctrpc.GenericResponse{Status: MsgStatusSuccess}, nil
+}
+
+// GetExchangeAssets returns the supported asset types
+func (s *RPCServer) GetExchangeAssets(_ context.Context, r *gctrpc.GetExchangeAssetsRequest) (*gctrpc.GetExchangeAssetsResponse, error) {
+ exch := GetExchangeByName(r.Exchange)
+ if exch == nil {
+ return nil, errExchangeNotLoaded
+ }
+
+ return &gctrpc.GetExchangeAssetsResponse{
+ Assets: exch.GetAssetTypes().JoinToString(","),
+ }, nil
+}
+
+// WebsocketGetInfo returns websocket connection information
+func (s *RPCServer) WebsocketGetInfo(_ context.Context, r *gctrpc.WebsocketGetInfoRequest) (*gctrpc.WebsocketGetInfoResponse, error) {
+ exch := GetExchangeByName(r.Exchange)
+ if exch == nil {
+ return nil, errExchangeNotLoaded
+ }
+
+ w, err := exch.GetWebsocket()
+ if err != nil {
+ return nil, err
+ }
+
+ return &gctrpc.WebsocketGetInfoResponse{
+ Exchange: exch.GetName(),
+ Supported: exch.SupportsWebsocket(),
+ Enabled: exch.IsWebsocketEnabled(),
+ Authenticated: w.CanUseAuthenticatedEndpoints(),
+ RunningUrl: w.GetWebsocketURL(),
+ ProxyAddress: w.GetProxyAddress(),
+ }, nil
+}
+
+// WebsocketSetEnabled enables or disables the websocket client
+func (s *RPCServer) WebsocketSetEnabled(_ context.Context, r *gctrpc.WebsocketSetEnabledRequest) (*gctrpc.GenericResponse, error) {
+ exch := GetExchangeByName(r.Exchange)
+ if exch == nil {
+ return nil, errExchangeNotLoaded
+ }
+
+ w, err := exch.GetWebsocket()
+ if err != nil {
+ return nil, fmt.Errorf("websocket not supported for exchange %s", r.Exchange)
+ }
+
+ exchCfg, err := Bot.Config.GetExchangeConfig(r.Exchange)
+ if err != nil {
+ return nil, err
+ }
+
+ if r.Enable {
+ err = w.Enable()
+ if err != nil {
+ return nil, err
+ }
+
+ exchCfg.Features.Enabled.Websocket = true
+ return &gctrpc.GenericResponse{Status: MsgStatusSuccess, Data: "websocket enabled"}, nil
+ }
+
+ err = w.Disable()
+ if err != nil {
+ return nil, err
+ }
+ exchCfg.Features.Enabled.Websocket = false
+ return &gctrpc.GenericResponse{Status: MsgStatusSuccess, Data: "websocket disabled"}, nil
+}
+
+// WebsocketGetSubscriptions returns websocket subscription analysis
+func (s *RPCServer) WebsocketGetSubscriptions(_ context.Context, r *gctrpc.WebsocketGetSubscriptionsRequest) (*gctrpc.WebsocketGetSubscriptionsResponse, error) {
+ exch := GetExchangeByName(r.Exchange)
+ if exch == nil {
+ return nil, errExchangeNotLoaded
+ }
+
+ w, err := exch.GetWebsocket()
+ if err != nil {
+ return nil, fmt.Errorf("websocket not supported for exchange %s", r.Exchange)
+ }
+
+ payload := new(gctrpc.WebsocketGetSubscriptionsResponse)
+ payload.Exchange = exch.GetName()
+ subs := w.GetSubscriptions()
+ for i := range subs {
+ params, err := json.Marshal(subs[i].Params)
+ if err != nil {
+ return nil, err
+ }
+ payload.Subscriptions = append(payload.Subscriptions,
+ &gctrpc.WebsocketSubscription{
+ Channel: subs[i].Channel,
+ Currency: subs[i].Currency.String(),
+ Asset: subs[i].Asset.String(),
+ Params: string(params),
+ })
+ }
+ return payload, nil
+}
+
+// WebsocketSetProxy sets client websocket connection proxy
+func (s *RPCServer) WebsocketSetProxy(_ context.Context, r *gctrpc.WebsocketSetProxyRequest) (*gctrpc.GenericResponse, error) {
+ exch := GetExchangeByName(r.Exchange)
+ if exch == nil {
+ return nil, errExchangeNotLoaded
+ }
+
+ w, err := exch.GetWebsocket()
+ if err != nil {
+ return nil, fmt.Errorf("websocket not supported for exchange %s", r.Exchange)
+ }
+
+ err = w.SetProxyAddress(r.Proxy)
+ if err != nil {
+ return nil, err
+ }
+ return &gctrpc.GenericResponse{Status: MsgStatusSuccess,
+ Data: fmt.Sprintf("new proxy has been set [%s] for %s websocket connection",
+ r.Exchange,
+ r.Proxy)}, nil
+}
+
+// WebsocketSetURL sets exchange websocket client connection URL
+func (s *RPCServer) WebsocketSetURL(_ context.Context, r *gctrpc.WebsocketSetURLRequest) (*gctrpc.GenericResponse, error) {
+ exch := GetExchangeByName(r.Exchange)
+ if exch == nil {
+ return nil, errExchangeNotLoaded
+ }
+
+ w, err := exch.GetWebsocket()
+ if err != nil {
+ return nil, fmt.Errorf("websocket not supported for exchange %s", r.Exchange)
+ }
+
+ err = w.SetWebsocketURL(r.Url, false, true)
+ if err != nil {
+ return nil, err
+ }
+ return &gctrpc.GenericResponse{Status: MsgStatusSuccess,
+ Data: fmt.Sprintf("new URL has been set [%s] for %s websocket connection",
+ r.Exchange,
+ r.Url)}, nil
}
diff --git a/engine/syncer.go b/engine/syncer.go
index a634da41..bf4f8e8d 100644
--- a/engine/syncer.go
+++ b/engine/syncer.go
@@ -200,16 +200,18 @@ func (e *ExchangeCurrencyPairSyncer) update(exchangeName string, p currency.Pair
}
switch syncType {
- case SyncItemOrderbook, SyncItemTrade, SyncItemTicker:
- if !e.Cfg.SyncOrderbook && syncType == SyncItemOrderbook {
+ case SyncItemOrderbook:
+ if !e.Cfg.SyncOrderbook {
return
}
- if !e.Cfg.SyncTicker && syncType == SyncItemTicker {
+ case SyncItemTicker:
+ if !e.Cfg.SyncTicker {
return
}
- if !e.Cfg.SyncTrades && syncType == SyncItemTrade {
+ case SyncItemTrade:
+ if !e.Cfg.SyncTrades {
return
}
default:
@@ -236,7 +238,10 @@ func (e *ExchangeCurrencyPairSyncer) update(exchangeName string, p currency.Pair
if atomic.LoadInt32(&e.initSyncCompleted) != 1 && !origHadData {
removedCounter++
log.Debugf(log.SyncMgr, "%s ticker sync complete %v [%d/%d].\n",
- exchangeName, FormatCurrency(p).String(), removedCounter, createdCounter)
+ exchangeName,
+ FormatCurrency(p).String(),
+ removedCounter,
+ createdCounter)
e.initSyncWG.Done()
}
@@ -251,7 +256,10 @@ func (e *ExchangeCurrencyPairSyncer) update(exchangeName string, p currency.Pair
if atomic.LoadInt32(&e.initSyncCompleted) != 1 && !origHadData {
removedCounter++
log.Debugf(log.SyncMgr, "%s orderbook sync complete %v [%d/%d].\n",
- exchangeName, FormatCurrency(p).String(), removedCounter, createdCounter)
+ exchangeName,
+ FormatCurrency(p).String(),
+ removedCounter,
+ createdCounter)
e.initSyncWG.Done()
}
@@ -266,7 +274,10 @@ func (e *ExchangeCurrencyPairSyncer) update(exchangeName string, p currency.Pair
if atomic.LoadInt32(&e.initSyncCompleted) != 1 && !origHadData {
removedCounter++
log.Debugf(log.SyncMgr, "%s trade sync complete %v [%d/%d].\n",
- exchangeName, FormatCurrency(p).String(), removedCounter, createdCounter)
+ exchangeName,
+ FormatCurrency(p).String(),
+ removedCounter,
+ createdCounter)
e.initSyncWG.Done()
}
}
@@ -276,7 +287,8 @@ func (e *ExchangeCurrencyPairSyncer) update(exchangeName string, p currency.Pair
func (e *ExchangeCurrencyPairSyncer) worker() {
cleanup := func() {
- log.Debugln(log.SyncMgr, "Exchange CurrencyPairSyncer worker shutting down.")
+ log.Debugln(log.SyncMgr,
+ "Exchange CurrencyPairSyncer worker shutting down.")
}
defer cleanup()
@@ -293,8 +305,10 @@ func (e *ExchangeCurrencyPairSyncer) worker() {
if exchanges[x].SupportsWebsocket() && exchanges[x].IsWebsocketEnabled() {
ws, err := exchanges[x].GetWebsocket()
if err != nil {
- log.Errorf(log.SyncMgr, "%s unable to get websocket pointer. Err: %s\n",
- exchangeName, err)
+ log.Errorf(log.SyncMgr,
+ "%s unable to get websocket pointer. Err: %s\n",
+ exchangeName,
+ err)
usingREST = true
}
@@ -308,7 +322,17 @@ func (e *ExchangeCurrencyPairSyncer) worker() {
}
for y := range assetTypes {
- enabledPairs := exchanges[x].GetEnabledPairs(assetTypes[y])
+ if exchanges[x].GetBase().CurrencyPairs.IsAssetEnabled(assetTypes[y]) != nil {
+ continue
+ }
+ enabledPairs, err := exchanges[x].GetEnabledPairs(assetTypes[y])
+ if err != nil {
+ log.Errorf(log.SyncMgr,
+ "%s failed to get enabled pairs. Err: %s\n",
+ exchangeName,
+ err)
+ continue
+ }
for i := range enabledPairs {
if atomic.LoadInt32(&e.shutdown) == 1 {
return
@@ -410,7 +434,7 @@ func (e *ExchangeCurrencyPairSyncer) worker() {
} else {
result, err = exchanges[x].UpdateTicker(c.Pair, c.AssetType)
}
- printTickerSummary(result, c.Pair, c.AssetType, exchangeName, "REST", err)
+ printTickerSummary(result, "REST", err)
if err == nil {
if Bot.Config.RemoteControl.WebsocketRPC.Enabled {
relayWebsocketEvent(result, "ticker_update", c.AssetType.String(), exchangeName)
@@ -449,7 +473,7 @@ func (e *ExchangeCurrencyPairSyncer) worker() {
e.setProcessing(c.Exchange, c.Pair, c.AssetType, SyncItemOrderbook, true)
result, err := exchanges[x].UpdateOrderbook(c.Pair, c.AssetType)
- printOrderbookSummary(result, c.Pair, c.AssetType, exchangeName, "REST", err)
+ printOrderbookSummary(result, "REST", err)
if err == nil {
if Bot.Config.RemoteControl.WebsocketRPC.Enabled {
relayWebsocketEvent(result, "orderbook_update", c.AssetType.String(), exchangeName)
@@ -497,8 +521,10 @@ func (e *ExchangeCurrencyPairSyncer) Start() {
if supportsWebsocket && exchanges[x].IsWebsocketEnabled() {
ws, err := exchanges[x].GetWebsocket()
if err != nil {
- log.Errorf(log.SyncMgr, "%s failed to get websocket. Err: %s\n",
- exchangeName, err)
+ log.Errorf(log.SyncMgr,
+ "%s failed to get websocket. Err: %s\n",
+ exchangeName,
+ err)
usingREST = true
}
@@ -507,8 +533,10 @@ func (e *ExchangeCurrencyPairSyncer) Start() {
err = ws.Connect()
if err != nil {
- log.Errorf(log.SyncMgr, "%s websocket failed to connect. Err: %s\n",
- exchangeName, err)
+ log.Errorf(log.SyncMgr,
+ "%s websocket failed to connect. Err: %s\n",
+ exchangeName,
+ err)
usingREST = true
} else {
usingWebsocket = true
@@ -521,7 +549,22 @@ func (e *ExchangeCurrencyPairSyncer) Start() {
}
for y := range assetTypes {
- enabledPairs := exchanges[x].GetEnabledPairs(assetTypes[y])
+ if exchanges[x].GetBase().CurrencyPairs.IsAssetEnabled(assetTypes[y]) != nil {
+ log.Warnf(log.SyncMgr,
+ "%s asset type %s is disabled, fetching enabled pairs is paused",
+ exchangeName,
+ assetTypes[y])
+ continue
+ }
+
+ enabledPairs, err := exchanges[x].GetEnabledPairs(assetTypes[y])
+ if err != nil {
+ log.Errorf(log.SyncMgr,
+ "%s failed to get enabled pairs. Err: %s\n",
+ exchangeName,
+ err)
+ continue
+ }
for i := range enabledPairs {
if e.exists(exchangeName, enabledPairs[i], assetTypes[y]) {
continue
diff --git a/engine/websocket.go b/engine/websocket.go
index e277e788..99cef467 100644
--- a/engine/websocket.go
+++ b/engine/websocket.go
@@ -351,8 +351,14 @@ func wsGetTicker(client *WebsocketClient, data interface{}) error {
return err
}
- result, err := GetSpecificTicker(currency.NewPairFromString(tickerReq.Currency),
- tickerReq.Exchange, asset.Item(tickerReq.AssetType))
+ p, err := currency.NewPairFromString(tickerReq.Currency)
+ if err != nil {
+ return err
+ }
+
+ result, err := GetSpecificTicker(p,
+ tickerReq.Exchange,
+ asset.Item(tickerReq.AssetType))
if err != nil {
wsResp.Error = err.Error()
@@ -383,7 +389,12 @@ func wsGetOrderbook(client *WebsocketClient, data interface{}) error {
return err
}
- result, err := GetSpecificOrderbook(currency.NewPairFromString(orderbookReq.Currency),
+ p, err := currency.NewPairFromString(orderbookReq.Currency)
+ if err != nil {
+ return err
+ }
+
+ result, err := GetSpecificOrderbook(p,
orderbookReq.Exchange, asset.Item(orderbookReq.AssetType))
if err != nil {
diff --git a/exchanges/alphapoint/alphapoint_websocket.go b/exchanges/alphapoint/alphapoint_websocket.go
index dfb65979..54a9c913 100644
--- a/exchanges/alphapoint/alphapoint_websocket.go
+++ b/exchanges/alphapoint/alphapoint_websocket.go
@@ -40,7 +40,6 @@ func (a *Alphapoint) WebsocketClient() {
for a.Enabled {
msgType, resp, err := a.WebsocketConn.ReadMessage()
if err != nil {
- a.Websocket.ReadMessageErrors <- err
log.Error(log.ExchangeSys, err)
break
}
diff --git a/exchanges/alphapoint/alphapoint_wrapper.go b/exchanges/alphapoint/alphapoint_wrapper.go
index 0eb6fe15..bb2eaeb7 100644
--- a/exchanges/alphapoint/alphapoint_wrapper.go
+++ b/exchanges/alphapoint/alphapoint_wrapper.go
@@ -16,7 +16,6 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -35,10 +34,6 @@ func (a *Alphapoint) SetDefaults() {
a.API.CredentialsValidator.RequiresKey = true
a.API.CredentialsValidator.RequiresSecret = true
- a.CurrencyPairs.AssetTypes = asset.Items{
- asset.Spot,
- }
-
a.Features = exchange.Features{
Supports: exchange.FeaturesSupported{
REST: true,
@@ -129,23 +124,24 @@ func (a *Alphapoint) FetchAccountInfo() (account.Holdings, error) {
// UpdateTicker updates and returns the ticker for a currency pair
func (a *Alphapoint) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
- tickerPrice := new(ticker.Price)
tick, err := a.GetTicker(p.String())
if err != nil {
- return tickerPrice, err
+ return nil, err
}
- tickerPrice.Pair = p
- tickerPrice.Ask = tick.Ask
- tickerPrice.Bid = tick.Bid
- tickerPrice.Low = tick.Low
- tickerPrice.High = tick.High
- tickerPrice.Volume = tick.Volume
- tickerPrice.Last = tick.Last
-
- err = ticker.ProcessTicker(a.Name, tickerPrice, assetType)
+ err = ticker.ProcessTicker(&ticker.Price{
+ Pair: p,
+ Ask: tick.Ask,
+ Bid: tick.Bid,
+ Low: tick.Low,
+ High: tick.High,
+ Volume: tick.Volume,
+ Last: tick.Last,
+ ExchangeName: a.Name,
+ AssetType: assetType,
+ })
if err != nil {
- return tickerPrice, err
+ return nil, err
}
return ticker.GetTicker(a.Name, p, assetType)
@@ -313,11 +309,6 @@ func (a *Alphapoint) WithdrawFiatFundsToInternationalBank(withdrawRequest *withd
return "", common.ErrNotYetImplemented
}
-// GetWebsocket returns a pointer to the exchange websocket
-func (a *Alphapoint) GetWebsocket() (*wshandler.Websocket, error) {
- return nil, common.ErrNotYetImplemented
-}
-
// GetFeeByType returns an estimate of fee based on type of transaction
func (a *Alphapoint) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
return 0, common.ErrFunctionNotSupported
@@ -406,28 +397,6 @@ func (a *Alphapoint) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detai
return orders, nil
}
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func (a *Alphapoint) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- return common.ErrFunctionNotSupported
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func (a *Alphapoint) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- return common.ErrFunctionNotSupported
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func (a *Alphapoint) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return nil, common.ErrFunctionNotSupported
-}
-
-// AuthenticateWebsocket sends an authentication message to the websocket
-func (a *Alphapoint) AuthenticateWebsocket() error {
- return common.ErrFunctionNotSupported
-}
-
// ValidateCredentials validates current credentials used for wrapper
// functionality
func (a *Alphapoint) ValidateCredentials() error {
diff --git a/exchanges/asset/asset.go b/exchanges/asset/asset.go
index 43947812..5e80d0f7 100644
--- a/exchanges/asset/asset.go
+++ b/exchanges/asset/asset.go
@@ -14,6 +14,7 @@ type Items []Item
const (
Spot = Item("spot")
Margin = Item("margin")
+ MarginFunding = Item("marginfunding")
Index = Item("index")
Binary = Item("binary")
PerpetualContract = Item("perpetualcontract")
@@ -26,6 +27,7 @@ const (
var supported = Items{
Spot,
Margin,
+ MarginFunding,
Index,
Binary,
PerpetualContract,
@@ -66,7 +68,6 @@ func (a Items) Contains(i Item) bool {
return true
}
}
-
return false
}
diff --git a/exchanges/binance/binance.go b/exchanges/binance/binance.go
index 66fcf280..33987279 100644
--- a/exchanges/binance/binance.go
+++ b/exchanges/binance/binance.go
@@ -17,9 +17,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/common/crypto"
"github.com/thrasher-corp/gocryptotrader/currency"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
- "github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
)
@@ -63,7 +61,6 @@ const (
// Binance is the overarching type across the Bithumb package
type Binance struct {
exchange.Base
- WebsocketConn *wshandler.WebsocketConnection
// Valid string list that is required by the exchange
validLimits []int
@@ -569,17 +566,6 @@ func (b *Binance) CheckLimit(limit int) error {
return errors.New("incorrect limit values - valid values are 5, 10, 20, 50, 100, 500, 1000")
}
-// CheckSymbol checks value against a variable list
-func (b *Binance) CheckSymbol(symbol string, assetType asset.Item) error {
- enPairs := b.GetAvailablePairs(assetType)
- for x := range enPairs {
- if b.FormatExchangeCurrency(enPairs[x], assetType).String() == symbol {
- return nil
- }
- }
- return errors.New("incorrect symbol values - please check available pairs in configuration")
-}
-
// SetValues sets the default valid values
func (b *Binance) SetValues() {
b.validLimits = []int{5, 10, 20, 50, 100, 500, 1000, 5000}
diff --git a/exchanges/binance/binance_live_test.go b/exchanges/binance/binance_live_test.go
index 643af815..b20f29e4 100644
--- a/exchanges/binance/binance_live_test.go
+++ b/exchanges/binance/binance_live_test.go
@@ -29,6 +29,7 @@ func TestMain(m *testing.M) {
binanceConfig.API.Credentials.Key = apiKey
binanceConfig.API.Credentials.Secret = apiSecret
b.SetDefaults()
+ b.Websocket = sharedtestvalues.NewTestWebsocket()
err = b.Setup(binanceConfig)
if err != nil {
log.Fatal("Binance setup error", err)
diff --git a/exchanges/binance/binance_mock_test.go b/exchanges/binance/binance_mock_test.go
index 55974656..0bec281b 100644
--- a/exchanges/binance/binance_mock_test.go
+++ b/exchanges/binance/binance_mock_test.go
@@ -33,6 +33,7 @@ func TestMain(m *testing.M) {
binanceConfig.API.Credentials.Key = apiKey
binanceConfig.API.Credentials.Secret = apiSecret
b.SetDefaults()
+ b.Websocket = sharedtestvalues.NewTestWebsocket()
err = b.Setup(binanceConfig)
if err != nil {
log.Fatal("Binance setup error", err)
@@ -45,7 +46,6 @@ func TestMain(m *testing.M) {
b.HTTPClient = newClient
b.API.Endpoints.URL = serverDetails
- b.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
log.Printf(sharedtestvalues.MockTesting, b.Name, b.API.Endpoints.URL)
os.Exit(m.Run())
}
diff --git a/exchanges/binance/binance_test.go b/exchanges/binance/binance_test.go
index bfd2fb69..6fa58ab7 100644
--- a/exchanges/binance/binance_test.go
+++ b/exchanges/binance/binance_test.go
@@ -206,7 +206,7 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
var feeBuilder = setFeeBuilder()
b.GetFeeByType(feeBuilder)
- if !areTestAPIKeysSet() {
+ if !areTestAPIKeysSet() || mockTests {
if feeBuilder.FeeType != exchange.OfflineTradeFee {
t.Errorf("Expected %v, received %v", exchange.OfflineTradeFee, feeBuilder.FeeType)
}
@@ -439,6 +439,7 @@ func TestCancelExchangeOrder(t *testing.T) {
WalletAddress: core.BitcoinDonationAddress,
AccountID: "1",
Pair: currency.NewPair(currency.LTC, currency.BTC),
+ AssetType: asset.Spot,
}
err := b.CancelOrder(orderCancellation)
@@ -904,10 +905,13 @@ func TestExecutionTypeToOrderStatus(t *testing.T) {
}
func TestGetHistoricCandles(t *testing.T) {
- currencyPair := currency.NewPairFromString("BTCUSDT")
+ currencyPair, err := currency.NewPairFromString("BTCUSDT")
+ if err != nil {
+ t.Fatal(err)
+ }
startTime := time.Unix(1546300800, 0)
end := time.Unix(1577836799, 0)
- _, err := b.GetHistoricCandles(currencyPair, asset.Spot, startTime, end, kline.OneDay)
+ _, err = b.GetHistoricCandles(currencyPair, asset.Spot, startTime, end, kline.OneDay)
if err != nil {
t.Fatal(err)
}
@@ -919,10 +923,13 @@ func TestGetHistoricCandles(t *testing.T) {
}
func TestGetHistoricCandlesExtended(t *testing.T) {
- currencyPair := currency.NewPairFromString("BTCUSDT")
+ currencyPair, err := currency.NewPairFromString("BTCUSDT")
+ if err != nil {
+ t.Fatal(err)
+ }
startTime := time.Unix(1546300800, 0)
end := time.Unix(1577836799, 0)
- _, err := b.GetHistoricCandlesExtended(currencyPair, asset.Spot, startTime, end, kline.OneDay)
+ _, err = b.GetHistoricCandlesExtended(currencyPair, asset.Spot, startTime, end, kline.OneDay)
if err != nil {
t.Fatal(err)
}
diff --git a/exchanges/binance/binance_types.go b/exchanges/binance/binance_types.go
index 9a9aff26..b3516e33 100644
--- a/exchanges/binance/binance_types.go
+++ b/exchanges/binance/binance_types.go
@@ -25,15 +25,19 @@ type ExchangeInfo struct {
} `json:"rateLimits"`
ExchangeFilters interface{} `json:"exchangeFilters"`
Symbols []struct {
- Symbol string `json:"symbol"`
- Status string `json:"status"`
- BaseAsset string `json:"baseAsset"`
- BaseAssetPrecision int `json:"baseAssetPrecision"`
- QuoteAsset string `json:"quoteAsset"`
- QuotePrecision int `json:"quotePrecision"`
- OrderTypes []string `json:"orderTypes"`
- IcebergAllowed bool `json:"icebergAllowed"`
- Filters []struct {
+ Symbol string `json:"symbol"`
+ Status string `json:"status"`
+ BaseAsset string `json:"baseAsset"`
+ BaseAssetPrecision int `json:"baseAssetPrecision"`
+ QuoteAsset string `json:"quoteAsset"`
+ QuotePrecision int `json:"quotePrecision"`
+ OrderTypes []string `json:"orderTypes"`
+ IcebergAllowed bool `json:"icebergAllowed"`
+ OCOAllowed bool `json:"ocoAllowed"`
+ QuoteOrderQtyMarketAllowed bool `json:"quoteOrderQtyMarketAllowed"`
+ IsSpotTradingAllowed bool `json:"isSpotTradingAllowed"`
+ IsMarginTradingAllowed bool `json:"isMarginTradingAllowed"`
+ Filters []struct {
FilterType string `json:"filterType"`
MinPrice float64 `json:"minPrice,string"`
MaxPrice float64 `json:"maxPrice,string"`
@@ -594,89 +598,111 @@ type UserAccountStream struct {
}
type wsAccountInfo struct {
- CanDeposit bool `json:"D"`
- CanTrade bool `json:"T"`
- CanWithdraw bool `json:"W"`
- EventTime int64 `json:"E"`
- LastUpdated int64 `json:"u"`
- BuyerCommission float64 `json:"b"`
- MakerCommission float64 `json:"m"`
- SellerCommission float64 `json:"s"`
- TakerCommission float64 `json:"t"`
- EventType string `json:"e"`
- Currencies []struct {
- Asset string `json:"a"`
- Available float64 `json:"f,string"`
- Locked float64 `json:"l,string"`
- } `json:"B"`
+ Stream string `json:"stream"`
+ Data struct {
+ CanDeposit bool `json:"D"`
+ CanTrade bool `json:"T"`
+ CanWithdraw bool `json:"W"`
+ EventTime int64 `json:"E"`
+ LastUpdated int64 `json:"u"`
+ BuyerCommission float64 `json:"b"`
+ MakerCommission float64 `json:"m"`
+ SellerCommission float64 `json:"s"`
+ TakerCommission float64 `json:"t"`
+ EventType string `json:"e"`
+ Currencies []struct {
+ Asset string `json:"a"`
+ Available float64 `json:"f,string"`
+ Locked float64 `json:"l,string"`
+ } `json:"B"`
+ } `json:"data"`
}
type wsAccountPosition struct {
- Currencies []struct {
- Asset string `json:"a"`
- Available float64 `json:"f,string"`
- Locked float64 `json:"l,string"`
- } `json:"B"`
- EventTime int64 `json:"E"`
- LastUpdated int64 `json:"u"`
- EventType string `json:"e"`
+ Stream string `json:"stream"`
+ Data struct {
+ Currencies []struct {
+ Asset string `json:"a"`
+ Available float64 `json:"f,string"`
+ Locked float64 `json:"l,string"`
+ } `json:"B"`
+ EventTime int64 `json:"E"`
+ LastUpdated int64 `json:"u"`
+ EventType string `json:"e"`
+ } `json:"data"`
}
type wsBalanceUpdate struct {
- EventTime int64 `json:"E"`
- ClearTime int64 `json:"T"`
- BalanceDelta float64 `json:"d,string"`
- Asset string `json:"a"`
- EventType string `json:"e"`
+ Stream string `json:"stream"`
+ Data struct {
+ EventTime int64 `json:"E"`
+ ClearTime int64 `json:"T"`
+ BalanceDelta float64 `json:"d,string"`
+ Asset string `json:"a"`
+ EventType string `json:"e"`
+ } `json:"data"`
}
type wsOrderUpdate struct {
- ClientOrderID string `json:"C"`
- EventTime int64 `json:"E"`
- IcebergQuantity float64 `json:"F,string"`
- LastExecutedPrice float64 `json:"L,string"`
- CommissionAsset float64 `json:"N"`
- OrderCreationTime int64 `json:"O"`
- StopPrice float64 `json:"P,string"`
- QuoteOrderQuantity float64 `json:"Q,string"`
- Side string `json:"S"`
- TransactionTime int64 `json:"T"`
- OrderStatus string `json:"X"`
- LastQuoteAssetTransactedQuantity float64 `json:"Y,string"`
- CumulativeQuoteTransactedQuantity float64 `json:"Z,string"`
- CancelledClientOrderID string `json:"c"`
- EventType string `json:"e"`
- TimeInForce string `json:"f"`
- OrderListID int64 `json:"g"`
- OrderID int64 `json:"i"`
- LastExecutedQuantity float64 `json:"l,string"`
- IsMaker bool `json:"m"`
- Commission float64 `json:"n,string"`
- OrderType string `json:"o"`
- Price float64 `json:"p,string"`
- Quantity float64 `json:"q,string"`
- RejectionReason string `json:"r"`
- Symbol string `json:"s"`
- TradeID int64 `json:"t"`
- IsOnOrderBook bool `json:"w"`
- CurrentExecutionType string `json:"x"`
- CumulativeFilledQuantity float64 `json:"z,string"`
+ Stream string `json:"stream"`
+ Data struct {
+ ClientOrderID string `json:"C"`
+ EventTime int64 `json:"E"`
+ IcebergQuantity float64 `json:"F,string"`
+ LastExecutedPrice float64 `json:"L,string"`
+ CommissionAsset float64 `json:"N"`
+ OrderCreationTime int64 `json:"O"`
+ StopPrice float64 `json:"P,string"`
+ QuoteOrderQuantity float64 `json:"Q,string"`
+ Side string `json:"S"`
+ TransactionTime int64 `json:"T"`
+ OrderStatus string `json:"X"`
+ LastQuoteAssetTransactedQuantity float64 `json:"Y,string"`
+ CumulativeQuoteTransactedQuantity float64 `json:"Z,string"`
+ CancelledClientOrderID string `json:"c"`
+ EventType string `json:"e"`
+ TimeInForce string `json:"f"`
+ OrderListID int64 `json:"g"`
+ OrderID int64 `json:"i"`
+ LastExecutedQuantity float64 `json:"l,string"`
+ IsMaker bool `json:"m"`
+ Commission float64 `json:"n,string"`
+ OrderType string `json:"o"`
+ Price float64 `json:"p,string"`
+ Quantity float64 `json:"q,string"`
+ RejectionReason string `json:"r"`
+ Symbol string `json:"s"`
+ TradeID int64 `json:"t"`
+ IsOnOrderBook bool `json:"w"`
+ CurrentExecutionType string `json:"x"`
+ CumulativeFilledQuantity float64 `json:"z,string"`
+ } `json:"data"`
}
-type wsListStauts struct {
- ListClientOrderID string `json:"C"`
- EventTime int64 `json:"E"`
- ListOrderStatus string `json:"L"`
- Orders []struct {
- ClientOrderID string `json:"c"`
- OrderID int64 `json:"i"`
- Symbol string `json:"s"`
- } `json:"O"`
- TransactionTime int64 `json:"T"`
- ContingencyType string `json:"c"`
- EventType string `json:"e"`
- OrderListID int64 `json:"g"`
- ListStatusType string `json:"l"`
- RejectionReason string `json:"r"`
- Symbol string `json:"s"`
+type wsListStatus struct {
+ Stream string `json:"stream"`
+ Data struct {
+ ListClientOrderID string `json:"C"`
+ EventTime int64 `json:"E"`
+ ListOrderStatus string `json:"L"`
+ Orders []struct {
+ ClientOrderID string `json:"c"`
+ OrderID int64 `json:"i"`
+ Symbol string `json:"s"`
+ } `json:"O"`
+ TransactionTime int64 `json:"T"`
+ ContingencyType string `json:"c"`
+ EventType string `json:"e"`
+ OrderListID int64 `json:"g"`
+ ListStatusType string `json:"l"`
+ RejectionReason string `json:"r"`
+ Symbol string `json:"s"`
+ } `json:"data"`
+}
+
+// WsPayload defines the payload through the websocket connection
+type WsPayload struct {
+ Method string `json:"method"`
+ Params []string `json:"params"`
+ ID int64 `json:"id"`
}
diff --git a/exchanges/binance/binance_websocket.go b/exchanges/binance/binance_websocket.go
index 260af14d..2b58b288 100644
--- a/exchanges/binance/binance_websocket.go
+++ b/exchanges/binance/binance_websocket.go
@@ -14,23 +14,23 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wsorderbook"
"github.com/thrasher-corp/gocryptotrader/log"
)
const (
- binanceDefaultWebsocketURL = "wss://stream.binance.com:9443"
+ binanceDefaultWebsocketURL = "wss://stream.binance.com:9443/stream"
pingDelay = time.Minute * 9
)
var listenKey string
-// WsConnect intiates a websocket connection
+// WsConnect initiates a websocket connection
func (b *Binance) WsConnect() error {
if !b.Websocket.IsEnabled() || !b.IsEnabled() {
- return errors.New(wshandler.WebsocketNotEnabled)
+ return errors.New(stream.WebsocketNotEnabled)
}
var dialer websocket.Dialer
@@ -39,54 +39,43 @@ func (b *Binance) WsConnect() error {
listenKey, err = b.GetWsAuthStreamKey()
if err != nil {
b.Websocket.SetCanUseAuthenticatedEndpoints(false)
- log.Errorf(log.ExchangeSys, "%v unable to connect to authenticated Websocket. Error: %s", b.Name, err)
+ log.Errorf(log.ExchangeSys,
+ "%v unable to connect to authenticated Websocket. Error: %s",
+ b.Name,
+ err)
+ } else {
+ // cleans on failed connection
+ clean := strings.Split(b.Websocket.GetWebsocketURL(), "?streams=")
+ authPayload := clean[0] + "?streams=" + listenKey
+ err = b.Websocket.SetWebsocketURL(authPayload, false, false)
+ if err != nil {
+ return err
+ }
}
}
- pairs := b.GetEnabledPairs(asset.Spot).Strings()
- tick := strings.ToLower(
- strings.Replace(
- strings.Join(pairs, "@ticker/"), "-", "", -1)) + "@ticker"
- trade := strings.ToLower(
- strings.Replace(
- strings.Join(pairs, "@trade/"), "-", "", -1)) + "@trade"
- kline := strings.ToLower(
- strings.Replace(
- strings.Join(pairs, "@kline_1m/"), "-", "", -1)) + "@kline_1m"
- depth := strings.ToLower(
- strings.Replace(
- strings.Join(pairs, "@depth/"), "-", "", -1)) + "@depth"
-
- wsurl := b.Websocket.GetWebsocketURL() +
- "/stream?streams=" +
- tick +
- "/" +
- trade +
- "/" +
- kline +
- "/" +
- depth
- if listenKey != "" {
- wsurl += "/" +
- listenKey
- }
-
- b.WebsocketConn.URL = wsurl
- b.WebsocketConn.Verbose = b.Verbose
-
- err = b.WebsocketConn.Dial(&dialer, http.Header{})
+ err = b.Websocket.Conn.Dial(&dialer, http.Header{})
if err != nil {
return fmt.Errorf("%v - Unable to connect to Websocket. Error: %s",
b.Name,
err)
}
- b.WebsocketConn.SetupPingHandler(wshandler.WebsocketPingHandler{
+
+ if b.Websocket.CanUseAuthenticatedEndpoints() {
+ go b.KeepAuthKeyAlive()
+ }
+
+ b.Websocket.Conn.SetupPingHandler(stream.PingHandler{
UseGorillaHandler: true,
MessageType: websocket.PongMessage,
Delay: pingDelay,
})
- enabledPairs := b.GetEnabledPairs(asset.Spot)
+ enabledPairs, err := b.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return err
+ }
+
for i := range enabledPairs {
err = b.SeedLocalCache(enabledPairs[i])
if err != nil {
@@ -95,17 +84,19 @@ func (b *Binance) WsConnect() error {
}
go b.wsReadData()
- go b.KeepAuthKeyAlive()
- return nil
+
+ subs, err := b.GenerateSubscriptions()
+ if err != nil {
+ return err
+ }
+ return b.Websocket.SubscribeToChannels(subs)
}
// KeepAuthKeyAlive will continuously send messages to
// keep the WS auth key active
func (b *Binance) KeepAuthKeyAlive() {
b.Websocket.Wg.Add(1)
- defer func() {
- b.Websocket.Wg.Done()
- }()
+ defer b.Websocket.Wg.Done()
ticks := time.NewTicker(time.Minute * 30)
for {
select {
@@ -116,7 +107,8 @@ func (b *Binance) KeepAuthKeyAlive() {
err := b.MaintainWsAuthStreamKey()
if err != nil {
b.Websocket.DataHandler <- err
- log.Warnf(log.ExchangeSys, b.Name+" - Unable to renew auth websocket token, may experience shutdown")
+ log.Warnf(log.ExchangeSys,
+ b.Name+" - Unable to renew auth websocket token, may experience shutdown")
}
}
}
@@ -125,25 +117,16 @@ func (b *Binance) KeepAuthKeyAlive() {
// wsReadData receives and passes on websocket messages for processing
func (b *Binance) wsReadData() {
b.Websocket.Wg.Add(1)
- defer func() {
- b.Websocket.Wg.Done()
- }()
- for {
- select {
- case <-b.Websocket.ShutdownC:
- return
+ defer b.Websocket.Wg.Done()
- default:
- resp, err := b.WebsocketConn.ReadMessage()
- if err != nil {
- b.Websocket.ReadMessageErrors <- err
- return
- }
- b.Websocket.TrafficAlert <- struct{}{}
- err = b.wsHandleData(resp.Raw)
- if err != nil {
- b.Websocket.DataHandler <- err
- }
+ for {
+ resp := b.Websocket.Conn.ReadMessage()
+ if resp.Raw == nil {
+ return
+ }
+ err := b.wsHandleData(resp.Raw)
+ if err != nil {
+ b.Websocket.DataHandler <- err
}
}
}
@@ -163,112 +146,122 @@ func (b *Binance) wsHandleData(respRaw []byte) error {
return nil
}
}
- if e, ok := multiStreamData["e"].(string); ok {
- switch e {
- case "outboundAccountInfo":
- var data wsAccountInfo
- err := json.Unmarshal(respRaw, &data)
- if err != nil {
- return fmt.Errorf("%v - Could not convert to outboundAccountInfo structure %s",
- b.Name,
- err)
- }
- b.Websocket.DataHandler <- data
- case "outboundAccountPosition":
- var data wsAccountPosition
- err := json.Unmarshal(respRaw, &data)
- if err != nil {
- return fmt.Errorf("%v - Could not convert to outboundAccountPosition structure %s",
- b.Name,
- err)
- }
- b.Websocket.DataHandler <- data
- case "balanceUpdate":
- var data wsBalanceUpdate
- err := json.Unmarshal(respRaw, &data)
- if err != nil {
- return fmt.Errorf("%v - Could not convert to balanceUpdate structure %s",
- b.Name,
- err)
- }
- b.Websocket.DataHandler <- data
- case "executionReport":
- var data wsOrderUpdate
- err := json.Unmarshal(respRaw, &data)
- if err != nil {
- return fmt.Errorf("%v - Could not convert to executionReport structure %s",
- b.Name,
- err)
- }
- var orderID = strconv.FormatInt(data.OrderID, 10)
- oType, err := order.StringToOrderType(data.OrderType)
- if err != nil {
- b.Websocket.DataHandler <- order.ClassificationError{
- Exchange: b.Name,
- OrderID: orderID,
- Err: err,
+ if newdata, ok := multiStreamData["data"].(map[string]interface{}); ok {
+ if e, ok := newdata["e"].(string); ok {
+ switch e {
+ case "outboundAccountInfo":
+ var data wsAccountInfo
+ err := json.Unmarshal(respRaw, &data)
+ if err != nil {
+ return fmt.Errorf("%v - Could not convert to outboundAccountInfo structure %s",
+ b.Name,
+ err)
}
- }
- var oSide order.Side
- oSide, err = order.StringToOrderSide(data.Side)
- if err != nil {
- b.Websocket.DataHandler <- order.ClassificationError{
- Exchange: b.Name,
- OrderID: orderID,
- Err: err,
+ b.Websocket.DataHandler <- data
+ case "outboundAccountPosition":
+ var data wsAccountPosition
+ err := json.Unmarshal(respRaw, &data)
+ if err != nil {
+ return fmt.Errorf("%v - Could not convert to outboundAccountPosition structure %s",
+ b.Name,
+ err)
}
- }
- var oStatus order.Status
- oStatus, err = stringToOrderStatus(data.CurrentExecutionType)
- if err != nil {
- b.Websocket.DataHandler <- order.ClassificationError{
- Exchange: b.Name,
- OrderID: orderID,
- Err: err,
+ b.Websocket.DataHandler <- data
+ case "balanceUpdate":
+ var data wsBalanceUpdate
+ err := json.Unmarshal(respRaw, &data)
+ if err != nil {
+ return fmt.Errorf("%v - Could not convert to balanceUpdate structure %s",
+ b.Name,
+ err)
}
+ b.Websocket.DataHandler <- data
+ case "executionReport":
+ var data wsOrderUpdate
+ err := json.Unmarshal(respRaw, &data)
+ if err != nil {
+ return fmt.Errorf("%v - Could not convert to executionReport structure %s",
+ b.Name,
+ err)
+ }
+ var orderID = strconv.FormatInt(data.Data.OrderID, 10)
+ oType, err := order.StringToOrderType(data.Data.OrderType)
+ if err != nil {
+ b.Websocket.DataHandler <- order.ClassificationError{
+ Exchange: b.Name,
+ OrderID: orderID,
+ Err: err,
+ }
+ }
+ var oSide order.Side
+ oSide, err = order.StringToOrderSide(data.Data.Side)
+ if err != nil {
+ b.Websocket.DataHandler <- order.ClassificationError{
+ Exchange: b.Name,
+ OrderID: orderID,
+ Err: err,
+ }
+ }
+ var oStatus order.Status
+ oStatus, err = stringToOrderStatus(data.Data.CurrentExecutionType)
+ if err != nil {
+ b.Websocket.DataHandler <- order.ClassificationError{
+ Exchange: b.Name,
+ OrderID: orderID,
+ Err: err,
+ }
+ }
+ var p currency.Pair
+ var a asset.Item
+ p, a, err = b.GetRequestFormattedPairAndAssetType(data.Data.Symbol)
+ if err != nil {
+ return err
+ }
+ b.Websocket.DataHandler <- &order.Detail{
+ Price: data.Data.Price,
+ Amount: data.Data.Quantity,
+ ExecutedAmount: data.Data.CumulativeFilledQuantity,
+ RemainingAmount: data.Data.Quantity - data.Data.CumulativeFilledQuantity,
+ Exchange: b.Name,
+ ID: orderID,
+ Type: oType,
+ Side: oSide,
+ Status: oStatus,
+ AssetType: a,
+ Date: time.Unix(0, data.Data.OrderCreationTime*int64(time.Millisecond)),
+ Pair: p,
+ }
+ case "listStatus":
+ var data wsListStatus
+ err := json.Unmarshal(respRaw, &data)
+ if err != nil {
+ return fmt.Errorf("%v - Could not convert to listStatus structure %s",
+ b.Name,
+ err)
+ }
+ b.Websocket.DataHandler <- data
}
- var p currency.Pair
- var a asset.Item
- p, a, err = b.GetRequestFormattedPairAndAssetType(data.Symbol)
- if err != nil {
- return err
- }
- b.Websocket.DataHandler <- &order.Detail{
- Price: data.Price,
- Amount: data.Quantity,
- ExecutedAmount: data.CumulativeFilledQuantity,
- RemainingAmount: data.Quantity - data.CumulativeFilledQuantity,
- Exchange: b.Name,
- ID: orderID,
- Type: oType,
- Side: oSide,
- Status: oStatus,
- AssetType: a,
- Date: time.Unix(0, data.OrderCreationTime*int64(time.Millisecond)),
- Pair: p,
- }
- case "listStatus":
- var data wsListStauts
- err := json.Unmarshal(respRaw, &data)
- if err != nil {
- return fmt.Errorf("%v - Could not convert to listStatus structure %s",
- b.Name,
- err)
- }
- b.Websocket.DataHandler <- data
- default:
- b.Websocket.DataHandler <- wshandler.UnhandledMessageWarning{Message: b.Name + wshandler.UnhandledMessage + string(respRaw)}
- return nil
}
}
- if stream, ok := multiStreamData["stream"].(string); ok {
- streamType := strings.Split(stream, "@")
+ if wsStream, ok := multiStreamData["stream"].(string); ok {
+ streamType := strings.Split(wsStream, "@")
if len(streamType) > 1 {
if data, ok := multiStreamData["data"]; ok {
rawData, err := json.Marshal(data)
if err != nil {
return err
}
+
+ pairs, err := b.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return err
+ }
+
+ format, err := b.GetPairFormat(asset.Spot, true)
+ if err != nil {
+ return err
+ }
+
switch streamType[1] {
case "trade":
var trade TradeStream
@@ -293,14 +286,18 @@ func (b *Binance) wsHandleData(respRaw []byte) error {
err)
}
- b.Websocket.DataHandler <- wshandler.TradeData{
- CurrencyPair: currency.NewPairFromFormattedPairs(trade.Symbol, b.GetEnabledPairs(asset.Spot),
- b.GetPairFormat(asset.Spot, true)),
- Timestamp: time.Unix(0, trade.TimeStamp*int64(time.Millisecond)),
- Price: price,
- Amount: amount,
- Exchange: b.Name,
- AssetType: asset.Spot,
+ pair, err := currency.NewPairFromFormattedPairs(trade.Symbol, pairs, format)
+ if err != nil {
+ return err
+ }
+
+ b.Websocket.DataHandler <- stream.TradeData{
+ CurrencyPair: pair,
+ Timestamp: time.Unix(0, trade.TimeStamp*int64(time.Millisecond)),
+ Price: price,
+ Amount: amount,
+ Exchange: b.Name,
+ AssetType: asset.Spot,
}
case "ticker":
var t TickerStream
@@ -311,6 +308,11 @@ func (b *Binance) wsHandleData(respRaw []byte) error {
err.Error())
}
+ pair, err := currency.NewPairFromFormattedPairs(t.Symbol, pairs, format)
+ if err != nil {
+ return err
+ }
+
b.Websocket.DataHandler <- &ticker.Price{
ExchangeName: b.Name,
Open: t.OpenPrice,
@@ -324,8 +326,7 @@ func (b *Binance) wsHandleData(respRaw []byte) error {
Last: t.LastPrice,
LastUpdated: time.Unix(0, t.EventTime*int64(time.Millisecond)),
AssetType: asset.Spot,
- Pair: currency.NewPairFromFormattedPairs(t.Symbol, b.GetEnabledPairs(asset.Spot),
- b.GetPairFormat(asset.Spot, true)),
+ Pair: pair,
}
case "kline_1m", "kline_3m", "kline_5m", "kline_15m", "kline_30m", "kline_1h", "kline_2h", "kline_4h",
"kline_6h", "kline_8h", "kline_12h", "kline_1d", "kline_3d", "kline_1w", "kline_1M":
@@ -337,10 +338,14 @@ func (b *Binance) wsHandleData(respRaw []byte) error {
err)
}
- b.Websocket.DataHandler <- wshandler.KlineData{
- Timestamp: time.Unix(0, kline.EventTime*int64(time.Millisecond)),
- Pair: currency.NewPairFromFormattedPairs(kline.Symbol, b.GetEnabledPairs(asset.Spot),
- b.GetPairFormat(asset.Spot, true)),
+ pair, err := currency.NewPairFromFormattedPairs(kline.Symbol, pairs, format)
+ if err != nil {
+ return err
+ }
+
+ b.Websocket.DataHandler <- stream.KlineData{
+ Timestamp: time.Unix(0, kline.EventTime*int64(time.Millisecond)),
+ Pair: pair,
AssetType: asset.Spot,
Exchange: b.Name,
StartTime: time.Unix(0, kline.Kline.StartTime*int64(time.Millisecond)),
@@ -361,22 +366,16 @@ func (b *Binance) wsHandleData(respRaw []byte) error {
err)
}
- err = b.UpdateLocalCache(&depth)
+ err = b.UpdateLocalBuffer(&depth)
if err != nil {
return fmt.Errorf("%v - UpdateLocalCache error: %s",
b.Name,
err)
}
-
- currencyPair := currency.NewPairFromFormattedPairs(depth.Pair, b.GetEnabledPairs(asset.Spot),
- b.GetPairFormat(asset.Spot, true))
- b.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
- Pair: currencyPair,
- Asset: asset.Spot,
- Exchange: b.Name,
- }
default:
- b.Websocket.DataHandler <- wshandler.UnhandledMessageWarning{Message: b.Name + wshandler.UnhandledMessage + string(respRaw)}
+ b.Websocket.DataHandler <- stream.UnhandledMessageWarning{
+ Message: b.Name + stream.UnhandledMessage + string(respRaw),
+ }
}
}
}
@@ -403,11 +402,15 @@ func stringToOrderStatus(status string) (order.Status, error) {
// SeedLocalCache seeds depth data
func (b *Binance) SeedLocalCache(p currency.Pair) error {
- ob, err := b.GetOrderBook(
- OrderBookDataRequestParams{
- Symbol: b.FormatExchangeCurrency(p, asset.Spot).String(),
- Limit: 1000,
- })
+ fPair, err := b.FormatExchangeCurrency(p, asset.Spot)
+ if err != nil {
+ return err
+ }
+
+ ob, err := b.GetOrderBook(OrderBookDataRequestParams{
+ Symbol: fPair.String(),
+ Limit: 1000,
+ })
if err != nil {
return err
}
@@ -439,11 +442,34 @@ func (b *Binance) SeedLocalCacheWithBook(p currency.Pair, orderbookNew *OrderBoo
return b.Websocket.Orderbook.LoadSnapshot(&newOrderBook)
}
-// UpdateLocalCache updates and returns the most recent iteration of the orderbook
-func (b *Binance) UpdateLocalCache(wsdp *WebsocketDepthStream) error {
- currencyPair := currency.NewPairFromFormattedPairs(wsdp.Pair, b.GetEnabledPairs(asset.Spot),
- b.GetPairFormat(asset.Spot, true))
+// UpdateLocalBuffer updates and returns the most recent iteration of the orderbook
+func (b *Binance) UpdateLocalBuffer(wsdp *WebsocketDepthStream) error {
+ enabledPairs, err := b.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return err
+ }
+
+ format, err := b.GetPairFormat(asset.Spot, true)
+ if err != nil {
+ return err
+ }
+
+ currencyPair, err := currency.NewPairFromFormattedPairs(wsdp.Pair,
+ enabledPairs,
+ format)
+ if err != nil {
+ return err
+ }
+
currentBook := b.Websocket.Orderbook.GetOrderbook(currencyPair, asset.Spot)
+ if currentBook == nil {
+ // Used when a pair/s is enabled while connected
+ err = b.SeedLocalCache(currencyPair)
+ if err != nil {
+ return err
+ }
+ currentBook = b.Websocket.Orderbook.GetOrderbook(currencyPair, asset.Spot)
+ }
// Drop any event where u is <= lastUpdateId in the snapshot.
// The first processed event should have U <= lastUpdateId+1 AND u >= lastUpdateId+1.
@@ -479,7 +505,7 @@ func (b *Binance) UpdateLocalCache(wsdp *WebsocketDepthStream) error {
updateAsk = append(updateAsk, orderbook.Item{Price: p, Amount: a})
}
- return b.Websocket.Orderbook.Update(&wsorderbook.WebsocketOrderbookUpdate{
+ return b.Websocket.Orderbook.Update(&buffer.Update{
Bids: updateBid,
Asks: updateAsk,
Pair: currencyPair,
@@ -487,3 +513,62 @@ func (b *Binance) UpdateLocalCache(wsdp *WebsocketDepthStream) error {
Asset: asset.Spot,
})
}
+
+// GenerateSubscriptions generates the default subscription set
+func (b *Binance) GenerateSubscriptions() ([]stream.ChannelSubscription, error) {
+ var channels = []string{"@ticker", "@trade", "@kline_1m", "@depth@100ms"}
+ var subscriptions []stream.ChannelSubscription
+ assets := b.GetAssetTypes()
+ for x := range assets {
+ pairs, err := b.GetEnabledPairs(assets[x])
+ if err != nil {
+ return nil, err
+ }
+
+ for y := range pairs {
+ for z := range channels {
+ lp := pairs[y].Lower()
+ lp.Delimiter = ""
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
+ Channel: lp.String() + channels[z],
+ Currency: pairs[y],
+ Asset: assets[x],
+ })
+ }
+ }
+ }
+ return subscriptions, nil
+}
+
+// Subscribe subscribes to a set of channels
+func (b *Binance) Subscribe(channelsToSubscribe []stream.ChannelSubscription) error {
+ payload := WsPayload{
+ Method: "SUBSCRIBE",
+ }
+
+ for i := range channelsToSubscribe {
+ payload.Params = append(payload.Params, channelsToSubscribe[i].Channel)
+ }
+ err := b.Websocket.Conn.SendJSONMessage(payload)
+ if err != nil {
+ return err
+ }
+ b.Websocket.AddSuccessfulSubscriptions(channelsToSubscribe...)
+ return nil
+}
+
+// Unsubscribe unsubscribes from a set of channels
+func (b *Binance) Unsubscribe(channelsToUnsubscribe []stream.ChannelSubscription) error {
+ payload := WsPayload{
+ Method: "UNSUBSCRIBE",
+ }
+ for i := range channelsToUnsubscribe {
+ payload.Params = append(payload.Params, channelsToUnsubscribe[i].Channel)
+ }
+ err := b.Websocket.Conn.SendJSONMessage(payload)
+ if err != nil {
+ return err
+ }
+ b.Websocket.RemoveSuccessfulUnsubscriptions(channelsToUnsubscribe...)
+ return nil
+}
diff --git a/exchanges/binance/binance_wrapper.go b/exchanges/binance/binance_wrapper.go
index d29c9039..ce6e5891 100644
--- a/exchanges/binance/binance_wrapper.go
+++ b/exchanges/binance/binance_wrapper.go
@@ -18,8 +18,8 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -56,21 +56,23 @@ func (b *Binance) SetDefaults() {
b.API.CredentialsValidator.RequiresSecret = true
b.SetValues()
- b.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- },
-
- UseGlobalFormat: true,
- RequestFormat: ¤cy.PairFormat{
- Uppercase: true,
- },
+ fmt1 := currency.PairStore{
+ RequestFormat: ¤cy.PairFormat{Uppercase: true},
ConfigFormat: ¤cy.PairFormat{
- Delimiter: "-",
+ Delimiter: currency.DashDelimiter,
Uppercase: true,
},
}
+ err := b.StoreAssetPairFormat(asset.Spot, fmt1)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
+ }
+ err = b.StoreAssetPairFormat(asset.Margin, fmt1)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
+ }
+
b.Features = exchange.Features{
Supports: exchange.FeaturesSupported{
REST: true,
@@ -145,7 +147,7 @@ func (b *Binance) SetDefaults() {
b.API.Endpoints.URLDefault = apiURL
b.API.Endpoints.URL = b.API.Endpoints.URLDefault
- b.Websocket = wshandler.New()
+ b.Websocket = stream.New()
b.API.Endpoints.WebsocketURL = binanceDefaultWebsocketURL
b.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
b.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
@@ -164,40 +166,31 @@ func (b *Binance) Setup(exch *config.ExchangeConfig) error {
return err
}
- err = b.Websocket.Setup(
- &wshandler.WebsocketSetup{
- Enabled: exch.Features.Enabled.Websocket,
- Verbose: exch.Verbose,
- AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
- WebsocketTimeout: exch.WebsocketTrafficTimeout,
- DefaultURL: binanceDefaultWebsocketURL,
- ExchangeName: exch.Name,
- RunningURL: exch.API.Endpoints.WebsocketURL,
- Connector: b.WsConnect,
- Features: &b.Features.Supports.WebsocketCapabilities,
- })
-
+ err = b.Websocket.Setup(&stream.WebsocketSetup{
+ Enabled: exch.Features.Enabled.Websocket,
+ Verbose: exch.Verbose,
+ AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
+ WebsocketTimeout: exch.WebsocketTrafficTimeout,
+ DefaultURL: binanceDefaultWebsocketURL,
+ ExchangeName: exch.Name,
+ RunningURL: exch.API.Endpoints.WebsocketURL,
+ Connector: b.WsConnect,
+ Subscriber: b.Subscribe,
+ UnSubscriber: b.Unsubscribe,
+ GenerateSubscriptions: b.GenerateSubscriptions,
+ Features: &b.Features.Supports.WebsocketCapabilities,
+ OrderbookBufferLimit: exch.WebsocketOrderbookBufferLimit,
+ SortBuffer: true,
+ SortBufferByUpdateIDs: true,
+ })
if err != nil {
return err
}
- b.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: b.Name,
- URL: b.Websocket.GetWebsocketURL(),
- ProxyURL: b.Websocket.GetProxyAddress(),
- Verbose: b.Verbose,
+ return b.Websocket.SetupNewConnection(stream.ConnectionSetup{
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
- }
-
- b.Websocket.Orderbook.Setup(
- exch.WebsocketOrderbookBufferLimit,
- false,
- true,
- true,
- false,
- exch.Name)
- return nil
+ })
}
// Start starts the Binance go routine
@@ -221,30 +214,59 @@ func (b *Binance) Run() {
}
forceUpdate := false
- delim := b.GetPairFormat(asset.Spot, false).Delimiter
- if !common.StringDataContains(b.GetEnabledPairs(asset.Spot).Strings(), delim) ||
- !common.StringDataContains(b.GetAvailablePairs(asset.Spot).Strings(), delim) {
- enabledPairs := currency.NewPairsFromStrings(
- []string{currency.BTC.String() + delim + currency.USDT.String()},
- )
- log.Warn(log.ExchangeSys,
- "Available pairs for Binance reset due to config upgrade, please enable the ones you would like to use again")
- forceUpdate = true
+ format, err := b.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ log.Errorf(log.ExchangeSys, "%s failed to get enabled currencies. Err %s\n",
+ b.Name,
+ err)
+ return
+ }
+ pairs, err := b.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ log.Errorf(log.ExchangeSys, "%s failed to get enabled currencies. Err %s\n",
+ b.Name,
+ err)
+ return
+ }
- err := b.UpdatePairs(enabledPairs, asset.Spot, true, true)
+ avail, err := b.GetAvailablePairs(asset.Spot)
+ if err != nil {
+ log.Errorf(log.ExchangeSys, "%s failed to get available currencies. Err %s\n",
+ b.Name,
+ err)
+ return
+ }
+
+ if !common.StringDataContains(pairs.Strings(), format.Delimiter) ||
+ !common.StringDataContains(avail.Strings(), format.Delimiter) {
+ var enabledPairs currency.Pairs
+ enabledPairs, err = currency.NewPairsFromStrings([]string{
+ currency.BTC.String() +
+ format.Delimiter +
+ currency.USDT.String()})
if err != nil {
- log.Errorf(log.ExchangeSys,
- "%s failed to update currencies. Err: %s\n",
+ log.Errorf(log.ExchangeSys, "%s failed to update currencies. Err %s\n",
b.Name,
err)
+ } else {
+ log.Warn(log.ExchangeSys,
+ "Available pairs for Binance reset due to config upgrade, please enable the ones you would like to use again")
+ forceUpdate = true
+
+ err = b.UpdatePairs(enabledPairs, asset.Spot, true, true)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update currencies. Err: %s\n",
+ b.Name,
+ err)
+ }
}
}
if !b.GetEnabledFeatures().AutoPairUpdates && !forceUpdate {
return
}
-
- err := b.UpdateTradablePairs(forceUpdate)
+ err = b.UpdateTradablePairs(forceUpdate)
if err != nil {
log.Errorf(log.ExchangeSys,
"%s failed to update tradable pairs. Err: %s",
@@ -254,36 +276,55 @@ func (b *Binance) Run() {
}
// FetchTradablePairs returns a list of the exchanges tradable pairs
-func (b *Binance) FetchTradablePairs(asset asset.Item) ([]string, error) {
- var validCurrencyPairs []string
-
+func (b *Binance) FetchTradablePairs(a asset.Item) ([]string, error) {
info, err := b.GetExchangeInfo()
if err != nil {
return nil, err
}
+ format, err := b.GetPairFormat(a, false)
+ if err != nil {
+ return nil, err
+ }
+
+ var pairs []string
for x := range info.Symbols {
if info.Symbols[x].Status == "TRADING" {
- validCurrencyPairs = append(validCurrencyPairs, info.Symbols[x].BaseAsset+
- b.GetPairFormat(asset, false).Delimiter+
- info.Symbols[x].QuoteAsset)
+ pair := info.Symbols[x].BaseAsset +
+ format.Delimiter +
+ info.Symbols[x].QuoteAsset
+ if a == asset.Spot && info.Symbols[x].IsSpotTradingAllowed {
+ pairs = append(pairs, pair)
+ }
+ if a == asset.Margin && info.Symbols[x].IsMarginTradingAllowed {
+ pairs = append(pairs, pair)
+ }
}
}
- return validCurrencyPairs, nil
+ return pairs, nil
}
// UpdateTradablePairs updates the exchanges available pairs and stores
// them in the exchanges config
func (b *Binance) UpdateTradablePairs(forceUpdate bool) error {
- pairs, err := b.FetchTradablePairs(asset.Spot)
- if err != nil {
- return err
- }
+ assetTypes := b.GetAssetTypes()
+ for i := range assetTypes {
+ p, err := b.FetchTradablePairs(assetTypes[i])
+ if err != nil {
+ return err
+ }
- return b.UpdatePairs(currency.NewPairsFromStrings(pairs),
- asset.Spot,
- false,
- forceUpdate)
+ pairs, err := currency.NewPairsFromStrings(p)
+ if err != nil {
+ return err
+ }
+
+ err = b.UpdatePairs(pairs, assetTypes[i], false, forceUpdate)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
}
// UpdateTicker updates and returns the ticker for a currency pair
@@ -292,28 +333,39 @@ func (b *Binance) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.P
if err != nil {
return nil, err
}
- pairs := b.GetEnabledPairs(assetType)
+
+ pairs, err := b.GetEnabledPairs(assetType)
+ if err != nil {
+ return nil, err
+ }
+
for i := range pairs {
for y := range tick {
- pairFmt := b.FormatExchangeCurrency(pairs[i], assetType).String()
- if tick[y].Symbol != pairFmt {
+ pairFmt, err := b.FormatExchangeCurrency(pairs[i], assetType)
+ if err != nil {
+ return nil, err
+ }
+
+ if tick[y].Symbol != pairFmt.String() {
continue
}
- tickerPrice := &ticker.Price{
- Last: tick[y].LastPrice,
- High: tick[y].HighPrice,
- Low: tick[y].LowPrice,
- Bid: tick[y].BidPrice,
- Ask: tick[y].AskPrice,
- Volume: tick[y].Volume,
- QuoteVolume: tick[y].QuoteVolume,
- Open: tick[y].OpenPrice,
- Close: tick[y].PrevClosePrice,
- Pair: pairs[i],
- }
- err = ticker.ProcessTicker(b.Name, tickerPrice, assetType)
+
+ err = ticker.ProcessTicker(&ticker.Price{
+ Last: tick[y].LastPrice,
+ High: tick[y].HighPrice,
+ Low: tick[y].LowPrice,
+ Bid: tick[y].BidPrice,
+ Ask: tick[y].AskPrice,
+ Volume: tick[y].Volume,
+ QuoteVolume: tick[y].QuoteVolume,
+ Open: tick[y].OpenPrice,
+ Close: tick[y].PrevClosePrice,
+ Pair: pairs[i],
+ ExchangeName: b.Name,
+ AssetType: assetType,
+ })
if err != nil {
- log.Error(log.Ticker, err)
+ return nil, err
}
}
}
@@ -340,13 +392,19 @@ func (b *Binance) FetchOrderbook(p currency.Pair, assetType asset.Item) (*orderb
// UpdateOrderbook updates and returns the orderbook for a currency pair
func (b *Binance) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
- orderBook := new(orderbook.Base)
- orderbookNew, err := b.GetOrderBook(OrderBookDataRequestParams{Symbol: b.FormatExchangeCurrency(p,
- assetType).String(), Limit: 1000})
+ fpair, err := b.FormatExchangeCurrency(p, assetType)
if err != nil {
- return orderBook, err
+ return nil, err
}
+ orderbookNew, err := b.GetOrderBook(OrderBookDataRequestParams{
+ Symbol: fpair.String(),
+ Limit: 1000})
+ if err != nil {
+ return nil, err
+ }
+
+ orderBook := new(orderbook.Base)
for x := range orderbookNew.Bids {
orderBook.Bids = append(orderBook.Bids,
orderbook.Item{
@@ -499,8 +557,12 @@ func (b *Binance) CancelOrder(order *order.Cancel) error {
return err
}
- _, err = b.CancelExistingOrder(b.FormatExchangeCurrency(order.Pair,
- order.AssetType).String(),
+ fpair, err := b.FormatExchangeCurrency(order.Pair, order.AssetType)
+ if err != nil {
+ return err
+ }
+
+ _, err = b.CancelExistingOrder(fpair.String(),
orderIDInt,
order.AccountID)
return err
@@ -567,11 +629,6 @@ func (b *Binance) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdraw
return nil, common.ErrFunctionNotSupported
}
-// GetWebsocket returns a pointer to the exchange websocket
-func (b *Binance) GetWebsocket() (*wshandler.Websocket, error) {
- return b.Websocket, nil
-}
-
// GetFeeByType returns an estimate of fee based on type of transaction
func (b *Binance) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (!b.AllowAuthenticatedRequest() || b.SkipAuthCheck) && // Todo check connection status
@@ -589,8 +646,13 @@ func (b *Binance) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail,
var orders []order.Detail
for x := range req.Pairs {
- resp, err := b.OpenOrders(b.FormatExchangeCurrency(req.Pairs[x],
- asset.Spot).String())
+ fpair, err := b.FormatExchangeCurrency(req.Pairs[x],
+ asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+
+ resp, err := b.OpenOrders(fpair.String())
if err != nil {
return nil, err
}
@@ -600,6 +662,11 @@ func (b *Binance) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail,
orderType := order.Type(strings.ToUpper(resp[i].Type))
orderDate := time.Unix(0, int64(resp[i].Time)*int64(time.Millisecond))
+ pair, err := currency.NewPairFromString(resp[i].Symbol)
+ if err != nil {
+ return nil, err
+ }
+
orders = append(orders, order.Detail{
Amount: resp[i].OrigQty,
Date: orderDate,
@@ -609,7 +676,7 @@ func (b *Binance) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail,
Type: orderType,
Price: resp[i].Price,
Status: order.Status(resp[i].Status),
- Pair: currency.NewPairFromString(resp[i].Symbol),
+ Pair: pair,
})
}
}
@@ -629,8 +696,11 @@ func (b *Binance) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
var orders []order.Detail
for x := range req.Pairs {
- resp, err := b.AllOrders(b.FormatExchangeCurrency(req.Pairs[x],
- asset.Spot).String(),
+ fpair, err := b.FormatExchangeCurrency(req.Pairs[x], asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+ resp, err := b.AllOrders(fpair.String(),
"",
"1000")
if err != nil {
@@ -646,6 +716,11 @@ func (b *Binance) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
continue
}
+ pair, err := currency.NewPairFromString(resp[i].Symbol)
+ if err != nil {
+ return nil, err
+ }
+
orders = append(orders, order.Detail{
Amount: resp[i].OrigQty,
Date: orderDate,
@@ -654,7 +729,7 @@ func (b *Binance) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
Side: orderSide,
Type: orderType,
Price: resp[i].Price,
- Pair: currency.NewPairFromString(resp[i].Symbol),
+ Pair: pair,
Status: order.Status(resp[i].Status),
})
}
@@ -666,28 +741,6 @@ func (b *Binance) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
return orders, nil
}
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func (b *Binance) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- return common.ErrFunctionNotSupported
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func (b *Binance) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- return common.ErrFunctionNotSupported
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func (b *Binance) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return b.Websocket.GetSubscriptions(), nil
-}
-
-// AuthenticateWebsocket sends an authentication message to the websocket
-func (b *Binance) AuthenticateWebsocket() error {
- return common.ErrFunctionNotSupported
-}
-
// ValidateCredentials validates current credentials used for wrapper
// functionality
func (b *Binance) ValidateCredentials() error {
@@ -718,9 +771,13 @@ func (b *Binance) GetHistoricCandles(pair currency.Pair, a asset.Item, start, en
return kline.Item{}, errors.New(kline.ErrRequestExceedsExchangeLimits)
}
+ fpair, err := b.FormatExchangeCurrency(pair, a)
+ if err != nil {
+ return kline.Item{}, err
+ }
req := KlinesRequestParams{
Interval: b.FormatExchangeKlineInterval(interval),
- Symbol: b.FormatExchangeCurrency(pair, a).String(),
+ Symbol: fpair.String(),
StartTime: start.Unix() * 1000,
EndTime: end.Unix() * 1000,
Limit: int(b.Features.Enabled.Kline.ResultLimit),
@@ -768,11 +825,16 @@ func (b *Binance) GetHistoricCandlesExtended(pair currency.Pair, a asset.Item, s
Interval: interval,
}
+ formattedPair, err := b.FormatExchangeCurrency(pair, a)
+ if err != nil {
+ return kline.Item{}, err
+ }
+
dates := kline.CalcDateRanges(start, end, interval, b.Features.Enabled.Kline.ResultLimit)
for x := range dates {
req := KlinesRequestParams{
Interval: b.FormatExchangeKlineInterval(interval),
- Symbol: b.FormatExchangeCurrency(pair, a).String(),
+ Symbol: formattedPair.String(),
StartTime: dates[x].Start.UTC().Unix() * 1000,
EndTime: dates[x].End.UTC().Unix() * 1000,
Limit: int(b.Features.Enabled.Kline.ResultLimit),
diff --git a/exchanges/bitfinex/bitfinex.go b/exchanges/bitfinex/bitfinex.go
index 82cef9d4..dc079db9 100644
--- a/exchanges/bitfinex/bitfinex.go
+++ b/exchanges/bitfinex/bitfinex.go
@@ -17,7 +17,6 @@ import (
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -83,9 +82,7 @@ const (
// Bitfinex is the overarching type across the bitfinex package
type Bitfinex struct {
exchange.Base
- WebsocketConn *wshandler.WebsocketConnection
- AuthenticatedWebsocketConn *wshandler.WebsocketConnection
- WebsocketSubdChannels map[int]WebsocketChanInfo
+ WebsocketSubdChannels map[int]WebsocketChanInfo
}
// GetPlatformStatus returns the Bifinex platform status
@@ -778,7 +775,7 @@ func (b *Bitfinex) WithdrawFIAT(withdrawalType, walletType string, withdrawReque
// Major Upgrade needed on this function to include all query params
func (b *Bitfinex) NewOrder(currencyPair, orderType string, amount, price float64, buy, hidden bool) (Order, error) {
if !common.StringDataCompare(AcceptedOrderType, orderType) {
- return Order{}, errors.New("order type not accepted")
+ return Order{}, fmt.Errorf("order type %s not accepted", orderType)
}
response := Order{}
diff --git a/exchanges/bitfinex/bitfinex_test.go b/exchanges/bitfinex/bitfinex_test.go
index 0efd5788..139ebe08 100644
--- a/exchanges/bitfinex/bitfinex_test.go
+++ b/exchanges/bitfinex/bitfinex_test.go
@@ -16,7 +16,6 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/portfolio/banking"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -42,6 +41,7 @@ func TestMain(m *testing.M) {
if err != nil {
log.Fatal("Bitfinex Setup() init error")
}
+ b.Websocket = sharedtestvalues.NewTestWebsocket()
err = b.Setup(bfxConfig)
if err != nil {
log.Fatal("Bitfinex setup error", err)
@@ -58,11 +58,32 @@ func TestMain(m *testing.M) {
b.API.AuthenticatedWebsocketSupport = true
}
b.WebsocketSubdChannels = make(map[int]WebsocketChanInfo)
- b.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- b.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
os.Exit(m.Run())
}
+func TestAppendOptionalDelimiter(t *testing.T) {
+ t.Parallel()
+ curr1, err := currency.NewPairFromString("BTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ b.appendOptionalDelimiter(&curr1)
+ if curr1.Delimiter != "" {
+ t.Errorf("Expected no delimiter, received %v", curr1.Delimiter)
+ }
+ curr2, err := currency.NewPairFromString("DUSK:USD")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ curr2.Delimiter = ""
+ b.appendOptionalDelimiter(&curr2)
+ if curr2.Delimiter != ":" {
+ t.Errorf("Expected \":\" as a delimiter, received %v", curr2.Delimiter)
+ }
+}
+
func TestGetPlatformStatus(t *testing.T) {
t.Parallel()
result, err := b.GetPlatformStatus()
@@ -320,7 +341,7 @@ func TestNewOrder(t *testing.T) {
_, err := b.NewOrder("BTCUSD",
order.Limit.Lower(),
- 1,
+ -1,
2,
false,
true)
@@ -330,27 +351,17 @@ func TestNewOrder(t *testing.T) {
}
func TestUpdateTicker(t *testing.T) {
- _, err := b.UpdateTicker(currency.NewPairFromString("BTCUSD"), asset.Spot)
+ pair, err := currency.NewPairFromString("BTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ _, err = b.UpdateTicker(pair, asset.Spot)
if err != nil {
t.Error(err)
}
}
-func TestAppendOptionalDelimiter(t *testing.T) {
- t.Parallel()
- curr1 := currency.NewPairFromString("BTCUSD")
- b.appendOptionalDelimiter(&curr1)
- if curr1.Delimiter != "" {
- t.Errorf("Expected no delimiter, received %v", curr1.Delimiter)
- }
- curr2 := currency.NewPairFromString("DUSK:USD")
- curr2.Delimiter = ""
- b.appendOptionalDelimiter(&curr2)
- if curr2.Delimiter != ":" {
- t.Errorf("Expected \"-\" as a delimiter, received %v", curr2.Delimiter)
- }
-}
-
func TestNewOrderMulti(t *testing.T) {
if !b.ValidateAPICredentials() {
t.SkipNow()
@@ -762,19 +773,20 @@ func TestSubmitOrder(t *testing.T) {
var orderSubmission = &order.Submit{
Pair: currency.Pair{
Delimiter: "_",
- Base: currency.BTC,
+ Base: currency.XRP,
Quote: currency.USD,
},
- Side: order.Buy,
- Type: order.Limit,
- Price: 1,
- Amount: 1,
- ClientID: "meowOrder",
+ AssetType: asset.Spot,
+ Side: order.Sell,
+ Type: order.Limit,
+ Price: 1000,
+ Amount: 20,
+ ClientID: "meowOrder",
}
response, err := b.SubmitOrder(orderSubmission)
if areTestAPIKeysSet() && err != nil {
- t.Errorf("Could not cancel orders: %v", err)
+ t.Errorf("Could not place order: %v", err)
}
if areTestAPIKeysSet() && !response.IsOrderPlaced {
t.Error("Order not placed")
@@ -944,21 +956,12 @@ func TestGetDepositAddress(t *testing.T) {
}
func setupWs() {
- b.AuthenticatedWebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: b.Name,
- URL: authenticatedBitfinexWebsocketEndpoint,
- Verbose: b.Verbose,
- ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
- ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
- }
var dialer websocket.Dialer
- err := b.AuthenticatedWebsocketConn.Dial(&dialer, http.Header{})
+ err := b.Websocket.AuthConn.Dial(&dialer, http.Header{})
if err != nil {
log.Fatal(err)
}
- b.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- b.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
- go b.wsReadData(b.AuthenticatedWebsocketConn)
+ go b.wsReadData(b.Websocket.AuthConn)
go b.WsDataHandler()
}
@@ -1001,12 +1004,13 @@ func TestWsPlaceOrder(t *testing.T) {
if !wsAuthExecuted {
runAuth(t)
}
+
_, err := b.WsNewOrder(&WsNewOrderRequest{
- CustomID: 1337,
- Type: order.Buy.String(),
- Symbol: "tBTCUSD",
- Amount: 10,
- Price: -10,
+ GroupID: 1,
+ Type: "EXCHANGE LIMIT",
+ Symbol: "tXRPUSD",
+ Amount: -20,
+ Price: 1000,
})
if err != nil {
t.Error(err)
@@ -1169,6 +1173,24 @@ func TestWsTickerResponse(t *testing.T) {
if err != nil {
t.Error(err)
}
+ b.WebsocketSubdChannels[123412] = WebsocketChanInfo{Pair: "XAUTF0:USTF0", Channel: wsTicker}
+ pressXToJSON = `[123412,[61.304,2228.36155358,61.305,1323.2442970500003,0.395,0.0065,61.371,50973.3020771,62.5,57.421]]`
+ err = b.wsHandleData([]byte(pressXToJSON))
+ if err != nil {
+ t.Error(err)
+ }
+ b.WebsocketSubdChannels[123413] = WebsocketChanInfo{Pair: "trade:1m:tXRPUSD", Channel: wsTicker}
+ pressXToJSON = `[123413,[61.304,2228.36155358,61.305,1323.2442970500003,0.395,0.0065,61.371,50973.3020771,62.5,57.421]]`
+ err = b.wsHandleData([]byte(pressXToJSON))
+ if err != nil {
+ t.Error(err)
+ }
+ b.WebsocketSubdChannels[123414] = WebsocketChanInfo{Pair: "trade:1m:fZRX:p30", Channel: wsTicker}
+ pressXToJSON = `[123414,[61.304,2228.36155358,61.305,1323.2442970500003,0.395,0.0065,61.371,50973.3020771,62.5,57.421]]`
+ err = b.wsHandleData([]byte(pressXToJSON))
+ if err != nil {
+ t.Error(err)
+ }
}
func TestWsCandleResponse(t *testing.T) {
@@ -1186,6 +1208,7 @@ func TestWsCandleResponse(t *testing.T) {
}
func TestWsOrderSnapshot(t *testing.T) {
+ b.WsAddSubscriptionChannel(0, "account", "N/A")
pressXToJSON := `[0,"os",[[34930659963,null,1574955083558,"tETHUSD",1574955083558,1574955083573,0.201104,0.201104,"EXCHANGE LIMIT",null,null,null,0,"ACTIVE",null,null,120,0,0,0,null,null,null,0,0,null,null,null,"BFX",null,null,null]]]`
err := b.wsHandleData([]byte(pressXToJSON))
if err != nil {
@@ -1213,9 +1236,12 @@ func TestWsNotifications(t *testing.T) {
}
func TestGetHistoricCandles(t *testing.T) {
- currencyPair := currency.NewPairFromString("BTCUSD")
+ currencyPair, err := currency.NewPairFromString("BTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
startTime := time.Now().Add(-time.Hour * 24)
- _, err := b.GetHistoricCandles(currencyPair, asset.Spot, startTime, time.Now(), kline.OneMin)
+ _, err = b.GetHistoricCandles(currencyPair, asset.Spot, startTime, time.Now(), kline.OneMin)
if err != nil {
t.Fatal(err)
}
@@ -1227,9 +1253,12 @@ func TestGetHistoricCandles(t *testing.T) {
}
func TestGetHistoricCandlesExtended(t *testing.T) {
- currencyPair := currency.NewPairFromString("TBTCUSD")
+ currencyPair, err := currency.NewPairFromString("TBTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
startTime := time.Now().Add(-time.Hour * 24)
- _, err := b.GetHistoricCandlesExtended(currencyPair, asset.Spot, startTime, time.Now(), kline.OneHour)
+ _, err = b.GetHistoricCandlesExtended(currencyPair, asset.Spot, startTime, time.Now(), kline.OneHour)
if err != nil {
t.Fatal(err)
}
@@ -1241,42 +1270,95 @@ func TestGetHistoricCandlesExtended(t *testing.T) {
}
func TestFixCasing(t *testing.T) {
- ret := b.fixCasing(currency.NewPairFromString("BTCUSD"), asset.Spot)
+ pair, err := currency.NewPairFromString("BTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
+ ret, err := b.fixCasing(pair, asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
if ret != "tBTCUSD" {
t.Errorf("unexpected result: %v", ret)
}
-
- ret = b.fixCasing(currency.NewPairFromString("TBTCUSD"), asset.Spot)
+ pair, err = currency.NewPairFromString("TBTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
+ ret, err = b.fixCasing(pair, asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
if ret != "tBTCUSD" {
t.Errorf("unexpected result: %v", ret)
}
-
- ret = b.fixCasing(currency.NewPairFromString("tBTCUSD"), asset.Spot)
+ pair, err = currency.NewPairFromString("tBTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
+ ret, err = b.fixCasing(pair, asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err != nil {
+ t.Fatal(err)
+ }
if ret != "tBTCUSD" {
t.Errorf("unexpected result: %v", ret)
}
-
- ret = b.fixCasing(currency.NewPairFromString("BTCUSD"), asset.Margin)
+ pair, err = currency.NewPairFromString("BTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
+ ret, err = b.fixCasing(pair, asset.Margin)
+ if err != nil {
+ t.Fatal(err)
+ }
if ret != "fBTCUSD" {
t.Errorf("unexpected result: %v", ret)
}
-
- ret = b.fixCasing(currency.NewPairFromString("BTCUSD"), asset.Spot)
+ pair, err = currency.NewPairFromString("BTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
+ ret, err = b.fixCasing(pair, asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
if ret != "tBTCUSD" {
t.Errorf("unexpected result: %v", ret)
}
-
- ret = b.fixCasing(currency.NewPairFromString("FUNETH"), asset.Spot)
+ pair, err = currency.NewPairFromString("FUNETH")
+ if err != nil {
+ t.Fatal(err)
+ }
+ ret, err = b.fixCasing(pair, asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
if ret != "tFUNETH" {
t.Errorf("unexpected result: %v", ret)
}
-
- ret = b.fixCasing(currency.NewPairFromString("TNBUSD"), asset.Spot)
+ pair, err = currency.NewPairFromString("TNBUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
+ ret, err = b.fixCasing(pair, asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
if ret != "tTNBUSD" {
t.Errorf("unexpected result: %v", ret)
}
- ret = b.fixCasing(currency.NewPairFromString("tTNBUSD"), asset.Spot)
+ pair, err = currency.NewPairFromString("tTNBUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
+ ret, err = b.fixCasing(pair, asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
if ret != "tTNBUSD" {
t.Errorf("unexpected result: %v", ret)
}
diff --git a/exchanges/bitfinex/bitfinex_types.go b/exchanges/bitfinex/bitfinex_types.go
index 6752c973..e79a1f32 100644
--- a/exchanges/bitfinex/bitfinex_types.go
+++ b/exchanges/bitfinex/bitfinex_types.go
@@ -374,9 +374,11 @@ type WebsocketChanInfo struct {
// WebsocketBook holds booking information
type WebsocketBook struct {
- Price float64
ID int64
+ Price float64
Amount float64
+ Rate float64
+ Period int64
}
// WebsocketTrade holds trade information
diff --git a/exchanges/bitfinex/bitfinex_websocket.go b/exchanges/bitfinex/bitfinex_websocket.go
index 13dd78c0..5a227627 100644
--- a/exchanges/bitfinex/bitfinex_websocket.go
+++ b/exchanges/bitfinex/bitfinex_websocket.go
@@ -10,69 +10,74 @@ import (
"time"
"github.com/gorilla/websocket"
+ "github.com/thrasher-corp/gocryptotrader/common"
"github.com/thrasher-corp/gocryptotrader/common/crypto"
"github.com/thrasher-corp/gocryptotrader/currency"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wsorderbook"
"github.com/thrasher-corp/gocryptotrader/log"
)
-var comms = make(chan wshandler.WebsocketResponse)
+var comms = make(chan stream.Response)
// WsConnect starts a new websocket connection
func (b *Bitfinex) WsConnect() error {
if !b.Websocket.IsEnabled() || !b.IsEnabled() {
- return errors.New(wshandler.WebsocketNotEnabled)
+ return errors.New(stream.WebsocketNotEnabled)
}
var dialer websocket.Dialer
- err := b.WebsocketConn.Dial(&dialer, http.Header{})
+ err := b.Websocket.Conn.Dial(&dialer, http.Header{})
if err != nil {
- return fmt.Errorf("%v unable to connect to Websocket. Error: %s", b.Name, err)
+ return fmt.Errorf("%v unable to connect to Websocket. Error: %s",
+ b.Name,
+ err)
}
- go b.wsReadData(b.WebsocketConn)
+ go b.wsReadData(b.Websocket.Conn)
if b.Websocket.CanUseAuthenticatedEndpoints() {
- err = b.AuthenticatedWebsocketConn.Dial(&dialer, http.Header{})
+ err = b.Websocket.AuthConn.Dial(&dialer, http.Header{})
if err != nil {
- log.Errorf(log.ExchangeSys, "%v unable to connect to authenticated Websocket. Error: %s", b.Name, err)
+ log.Errorf(log.ExchangeSys,
+ "%v unable to connect to authenticated Websocket. Error: %s",
+ b.Name,
+ err)
b.Websocket.SetCanUseAuthenticatedEndpoints(false)
}
- go b.wsReadData(b.AuthenticatedWebsocketConn)
+ go b.wsReadData(b.Websocket.AuthConn)
err = b.WsSendAuth()
if err != nil {
- log.Errorf(log.ExchangeSys, "%v - authentication failed: %v\n", b.Name, err)
+ log.Errorf(log.ExchangeSys,
+ "%v - authentication failed: %v\n",
+ b.Name,
+ err)
b.Websocket.SetCanUseAuthenticatedEndpoints(false)
}
}
- b.GenerateDefaultSubscriptions()
+ subs, err := b.GenerateDefaultSubscriptions()
+ if err != nil {
+ return err
+ }
go b.WsDataHandler()
- return nil
+ return b.Websocket.SubscribeToChannels(subs)
}
// wsReadData receives and passes on websocket messages for processing
-func (b *Bitfinex) wsReadData(ws *wshandler.WebsocketConnection) {
+func (b *Bitfinex) wsReadData(ws stream.Connection) {
b.Websocket.Wg.Add(1)
defer b.Websocket.Wg.Done()
for {
- select {
- case <-b.Websocket.ShutdownC:
+ resp := ws.ReadMessage()
+ if resp.Raw == nil {
return
- default:
- resp, err := ws.ReadMessage()
- if err != nil {
- b.Websocket.ReadMessageErrors <- err
- return
- }
- b.Websocket.TrafficAlert <- struct{}{}
- comms <- resp
}
+ comms <- resp
}
}
@@ -82,8 +87,6 @@ func (b *Bitfinex) WsDataHandler() {
defer b.Websocket.Wg.Done()
for {
select {
- case <-b.Websocket.ShutdownC:
- return
case resp := <-comms:
if resp.Type == websocket.TextMessage {
err := b.wsHandleData(resp.Raw)
@@ -91,6 +94,8 @@ func (b *Bitfinex) WsDataHandler() {
b.Websocket.DataHandler <- err
}
}
+ case <-b.Websocket.ShutdownC:
+ return
}
}
}
@@ -106,12 +111,21 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
event := d["event"]
switch event {
case "subscribed":
- if symbol, ok := d["pair"].(string); ok {
+ if symbol, ok := d["symbol"].(string); ok {
b.WsAddSubscriptionChannel(int(d["chanId"].(float64)),
d["channel"].(string),
symbol,
)
} else if key, ok := d["key"].(string); ok {
+ // Capture trading subscriptions
+ contents := strings.Split(d["key"].(string), ":")
+ if len(contents) > 3 {
+ // Edge case to parse margin strings.
+ // map[chanId:139136 channel:candles event:subscribed key:trade:1m:tXAUTF0:USTF0]
+ if contents[2][0] == 't' {
+ key = contents[2] + ":" + contents[3]
+ }
+ }
b.WsAddSubscriptionChannel(int(d["chanId"].(float64)),
d["channel"].(string),
key,
@@ -134,6 +148,7 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
return nil
}
}
+
chanID := int(d[0].(float64))
chanInfo, ok := b.WebsocketSubdChannels[chanID]
if !ok && chanID != 0 {
@@ -141,67 +156,122 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
chanID)
}
+ var chanAsset = asset.Spot
+ var pair currency.Pair
+ pairInfo := strings.Split(chanInfo.Pair, ":")
+ switch {
+ case len(pairInfo) >= 3:
+ newPair := pairInfo[2]
+ if newPair[0] == 'f' {
+ chanAsset = asset.MarginFunding
+ }
+
+ pair, err = currency.NewPairFromString(newPair[1:])
+ if err != nil {
+ return err
+ }
+ case len(pairInfo) == 1:
+ newPair := pairInfo[0]
+ if newPair[0] == 'f' {
+ chanAsset = asset.MarginFunding
+ }
+
+ pair, err = currency.NewPairFromString(newPair[1:])
+ if err != nil {
+ return err
+ }
+ case chanInfo.Pair != "":
+ if strings.Contains(chanInfo.Pair, ":") {
+ chanAsset = asset.Margin
+ }
+
+ pair, err = currency.NewPairFromString(chanInfo.Pair[1:])
+ if err != nil {
+ return err
+ }
+ }
+
switch chanInfo.Channel {
case wsBook:
var newOrderbook []WebsocketBook
- curr := currency.NewPairFromString(chanInfo.Pair)
- if obSnapBundle, ok := d[1].([]interface{}); ok {
- switch id := obSnapBundle[0].(type) {
- case []interface{}:
- for i := range obSnapBundle {
- data := obSnapBundle[i].([]interface{})
+ obSnapBundle, ok := d[1].([]interface{})
+ if !ok {
+ return errors.New("orderbook interface cast failed")
+ }
+
+ switch id := obSnapBundle[0].(type) {
+ case []interface{}:
+ for i := range obSnapBundle {
+ data := obSnapBundle[i].([]interface{})
+ if len(data) == 4 {
+ newOrderbook = append(newOrderbook, WebsocketBook{
+ ID: int64(data[0].(float64)),
+ Period: int64(data[1].(float64)),
+ Rate: data[2].(float64),
+ Amount: data[3].(float64)})
+ } else {
newOrderbook = append(newOrderbook, WebsocketBook{
ID: int64(data[0].(float64)),
Price: data[1].(float64),
Amount: data[2].(float64)})
}
- err := b.WsInsertSnapshot(curr,
- asset.Spot,
- newOrderbook)
- if err != nil {
- return fmt.Errorf("bitfinex_websocket.go inserting snapshot error: %s",
- err)
- }
- case float64:
+ }
+ err := b.WsInsertSnapshot(pair, chanAsset, newOrderbook)
+ if err != nil {
+ return fmt.Errorf("bitfinex_websocket.go inserting snapshot error: %s",
+ err)
+ }
+ case float64:
+ if len(obSnapBundle) == 4 {
+ newOrderbook = append(newOrderbook, WebsocketBook{
+ ID: int64(id),
+ Period: int64(obSnapBundle[1].(float64)),
+ Rate: obSnapBundle[2].(float64),
+ Amount: obSnapBundle[3].(float64)})
+ } else {
newOrderbook = append(newOrderbook, WebsocketBook{
ID: int64(id),
Price: obSnapBundle[1].(float64),
Amount: obSnapBundle[2].(float64)})
- err := b.WsUpdateOrderbook(curr,
- asset.Spot,
- newOrderbook)
- if err != nil {
- return fmt.Errorf("bitfinex_websocket.go inserting snapshot error: %s",
- err)
- }
+ }
+
+ err := b.WsUpdateOrderbook(pair, chanAsset, newOrderbook)
+ if err != nil {
+ return fmt.Errorf("bitfinex_websocket.go updating orderbook error: %s",
+ err)
}
}
+
return nil
case wsCandles:
- curr := currency.NewPairFromString(chanInfo.Pair)
if candleBundle, ok := d[1].([]interface{}); ok {
if len(candleBundle) == 0 {
return nil
}
+
switch candleData := candleBundle[0].(type) {
case []interface{}:
- b.Websocket.DataHandler <- wshandler.KlineData{
- Timestamp: time.Unix(0, int64(candleData[0].(float64))),
- Exchange: b.Name,
- AssetType: asset.Spot,
- Pair: curr,
- OpenPrice: candleData[1].(float64),
- ClosePrice: candleData[2].(float64),
- HighPrice: candleData[3].(float64),
- LowPrice: candleData[4].(float64),
- Volume: candleData[5].(float64),
+ for i := range candleBundle {
+ element := candleBundle[i].([]interface{})
+ b.Websocket.DataHandler <- stream.KlineData{
+ Timestamp: time.Unix(0, int64(element[0].(float64))*int64(time.Millisecond)),
+ Exchange: b.Name,
+ AssetType: chanAsset,
+ Pair: pair,
+ OpenPrice: element[1].(float64),
+ ClosePrice: element[2].(float64),
+ HighPrice: element[3].(float64),
+ LowPrice: element[4].(float64),
+ Volume: element[5].(float64),
+ }
}
+
case float64:
- b.Websocket.DataHandler <- wshandler.KlineData{
- Timestamp: time.Unix(0, int64(candleData)),
+ b.Websocket.DataHandler <- stream.KlineData{
+ Timestamp: time.Unix(0, int64(candleData)*int64(time.Millisecond)),
Exchange: b.Name,
- AssetType: asset.Spot,
- Pair: curr,
+ AssetType: chanAsset,
+ Pair: pair,
OpenPrice: candleBundle[1].(float64),
ClosePrice: candleBundle[2].(float64),
HighPrice: candleBundle[3].(float64),
@@ -221,8 +291,8 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
Volume: tickerData[7].(float64),
High: tickerData[8].(float64),
Low: tickerData[9].(float64),
- AssetType: asset.Spot,
- Pair: currency.NewPairFromString(chanInfo.Pair),
+ AssetType: chanAsset,
+ Pair: pair,
}
return nil
case wsTrades:
@@ -233,22 +303,20 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
for i := range snapshot {
elem := snapshot[i].([]interface{})
if len(elem) == 5 {
- trades = append(trades,
- WebsocketTrade{
- ID: int64(elem[0].(float64)),
- Timestamp: int64(elem[1].(float64)),
- Amount: elem[2].(float64),
- Rate: elem[3].(float64),
- Period: int64(elem[4].(float64)),
- })
+ trades = append(trades, WebsocketTrade{
+ ID: int64(elem[0].(float64)),
+ Timestamp: int64(elem[1].(float64)),
+ Amount: elem[2].(float64),
+ Rate: elem[3].(float64),
+ Period: int64(elem[4].(float64)),
+ })
} else {
- trades = append(trades,
- WebsocketTrade{
- ID: int64(elem[0].(float64)),
- Timestamp: int64(elem[1].(float64)),
- Amount: elem[2].(float64),
- Price: elem[3].(float64),
- })
+ trades = append(trades, WebsocketTrade{
+ ID: int64(elem[0].(float64)),
+ Timestamp: int64(elem[1].(float64)),
+ Amount: elem[2].(float64),
+ Price: elem[3].(float64),
+ })
}
}
case 3:
@@ -260,11 +328,22 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
return nil
}
data := d[2].([]interface{})
- trades = append(trades, WebsocketTrade{
- ID: int64(data[0].(float64)),
- Timestamp: int64(data[1].(float64)),
- Price: data[3].(float64),
- Amount: data[2].(float64)})
+ if len(data) == 5 {
+ trades = append(trades, WebsocketTrade{
+ ID: int64(data[0].(float64)),
+ Timestamp: int64(data[1].(float64)),
+ Amount: data[2].(float64),
+ Rate: data[3].(float64),
+ Period: int64(data[4].(float64)),
+ })
+ } else {
+ trades = append(trades, WebsocketTrade{
+ ID: int64(data[0].(float64)),
+ Timestamp: int64(data[1].(float64)),
+ Amount: data[2].(float64),
+ Price: data[3].(float64),
+ })
+ }
}
for i := range trades {
@@ -276,29 +355,30 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
}
if trades[i].Rate > 0 {
- b.Websocket.DataHandler <- wshandler.FundingData{
- CurrencyPair: currency.NewPairFromString(chanInfo.Pair),
+ b.Websocket.DataHandler <- stream.FundingData{
+ CurrencyPair: pair,
Timestamp: time.Unix(0, trades[i].Timestamp*int64(time.Millisecond)),
Amount: newAmount,
Exchange: b.Name,
- AssetType: asset.Spot,
+ AssetType: chanAsset,
Side: side,
Rate: trades[i].Rate,
Period: trades[i].Period,
}
- return nil
+ continue
}
- b.Websocket.DataHandler <- wshandler.TradeData{
- CurrencyPair: currency.NewPairFromString(chanInfo.Pair),
+ b.Websocket.DataHandler <- stream.TradeData{
+ CurrencyPair: pair,
Timestamp: time.Unix(0, trades[i].Timestamp*int64(time.Millisecond)),
Price: trades[i].Price,
Amount: newAmount,
Exchange: b.Name,
- AssetType: asset.Spot,
+ AssetType: chanAsset,
Side: side,
}
}
+ return nil
}
if authResp, ok := d[1].(string); ok {
@@ -315,8 +395,7 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
strings.Contains(channelName, wsFundingOrderCancelRequest):
if data[0] != nil && data[0].(float64) > 0 {
id := int64(data[0].(float64))
- if b.WebsocketConn.IsIDWaitingForResponse(id) {
- b.AuthenticatedWebsocketConn.SetResponseIDAndData(id, respRaw)
+ if b.Websocket.Match.IncomingWithData(id, respRaw) {
return nil
}
b.wsHandleFundingOffer(data)
@@ -326,19 +405,23 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
strings.Contains(channelName, wsOrderCancelRequest):
if data[2] != nil && data[2].(float64) > 0 {
id := int64(data[2].(float64))
- if b.WebsocketConn.IsIDWaitingForResponse(id) {
- b.AuthenticatedWebsocketConn.SetResponseIDAndData(id, respRaw)
+ if b.Websocket.Match.IncomingWithData(id, respRaw) {
return nil
}
b.wsHandleOrder(data)
}
default:
- return fmt.Errorf("%s - Unexpected data returned %s", b.Name, respRaw)
+ return fmt.Errorf("%s - Unexpected data returned %s",
+ b.Name,
+ respRaw)
}
}
- if notification[5] != nil && strings.EqualFold(notification[5].(string), wsError) {
- return fmt.Errorf("%s - Error %s", b.Name, notification[6].(string))
+ if notification[5] != nil &&
+ strings.EqualFold(notification[5].(string), wsError) {
+ return fmt.Errorf("%s - Error %s",
+ b.Name,
+ notification[6].(string))
}
case wsOrderSnapshot:
if snapBundle, ok := d[2].([]interface{}); ok && len(snapBundle) > 0 {
@@ -634,7 +717,9 @@ func (b *Bitfinex) wsHandleData(respRaw []byte) error {
}
}
default:
- b.Websocket.DataHandler <- wshandler.UnhandledMessageWarning{Message: b.Name + wshandler.UnhandledMessage + string(respRaw)}
+ b.Websocket.DataHandler <- stream.UnhandledMessageWarning{
+ Message: b.Name + stream.UnhandledMessage + string(respRaw),
+ }
return nil
}
}
@@ -781,20 +866,13 @@ func (b *Bitfinex) WsInsertSnapshot(p currency.Pair, assetType asset.Item, books
newOrderBook.Pair = p
newOrderBook.ExchangeName = b.Name
- err := b.Websocket.Orderbook.LoadSnapshot(&newOrderBook)
- if err != nil {
- return fmt.Errorf("bitfinex.go error - %s", err)
- }
- b.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{Pair: p,
- Asset: assetType,
- Exchange: b.Name}
- return nil
+ return b.Websocket.Orderbook.LoadSnapshot(&newOrderBook)
}
// WsUpdateOrderbook updates the orderbook list, removing and adding to the
// orderbook sides
func (b *Bitfinex) WsUpdateOrderbook(p currency.Pair, assetType asset.Item, book []WebsocketBook) error {
- orderbookUpdate := wsorderbook.WebsocketOrderbookUpdate{
+ orderbookUpdate := buffer.Update{
Asset: assetType,
Pair: p,
}
@@ -833,97 +911,115 @@ func (b *Bitfinex) WsUpdateOrderbook(p currency.Pair, assetType asset.Item, book
}
}
}
- err := b.Websocket.Orderbook.Update(&orderbookUpdate)
- if err != nil {
- return err
- }
-
- b.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{Pair: p,
- Asset: assetType,
- Exchange: b.Name}
-
- return nil
+ return b.Websocket.Orderbook.Update(&orderbookUpdate)
}
// GenerateDefaultSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions()
-func (b *Bitfinex) GenerateDefaultSubscriptions() {
+func (b *Bitfinex) GenerateDefaultSubscriptions() ([]stream.ChannelSubscription, error) {
var channels = []string{
wsBook,
wsTrades,
wsTicker,
wsCandles,
}
- var subscriptions []wshandler.WebsocketChannelSubscription
- for i := range channels {
- enabledPairs := b.GetEnabledPairs(asset.Spot)
- for j := range enabledPairs {
- if strings.HasPrefix(enabledPairs[j].Base.String(), "f") {
- log.Warnf(log.WebsocketMgr,
- "%v - Websocket does not support funding currency %v, skipping",
- b.Name, enabledPairs[j])
- continue
- }
- b.appendOptionalDelimiter(&enabledPairs[j])
- params := make(map[string]interface{})
- if channels[i] == wsBook {
- params["prec"] = "R0"
- params["len"] = "100"
- }
- subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
- Channel: channels[i],
- Currency: enabledPairs[j],
- Params: params,
- })
+ var subscriptions []stream.ChannelSubscription
+ assets := b.GetAssetTypes()
+ for i := range assets {
+ enabledPairs, err := b.GetEnabledPairs(assets[i])
+ if err != nil {
+ return nil, err
+ }
+
+ for j := range channels {
+ for k := range enabledPairs {
+ params := make(map[string]interface{})
+ if channels[j] == wsBook {
+ params["prec"] = "R0"
+ params["len"] = "100"
+ }
+
+ if channels[j] == wsCandles {
+ // TODO: Add ability to select timescale && funding period
+ var fundingPeriod string
+ prefix := "t"
+ if assets[i] == asset.MarginFunding {
+ prefix = "f"
+ fundingPeriod = ":p30"
+ }
+ params["key"] = "trade:1m:" + prefix + enabledPairs[k].String() + fundingPeriod
+ } else {
+ params["symbol"] = enabledPairs[k].String()
+ }
+
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
+ Channel: channels[j],
+ Currency: enabledPairs[k],
+ Params: params,
+ Asset: assets[i],
+ })
+ }
}
}
- b.Websocket.SubscribeToChannels(subscriptions)
+
+ return subscriptions, nil
}
// Subscribe sends a websocket message to receive data from the channel
-func (b *Bitfinex) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
- req := make(map[string]interface{})
- req["event"] = "subscribe"
- req["channel"] = channelToSubscribe.Channel
+func (b *Bitfinex) Subscribe(channelsToSubscribe []stream.ChannelSubscription) error {
+ var errs common.Errors
+ for i := range channelsToSubscribe {
+ req := make(map[string]interface{})
+ req["event"] = "subscribe"
+ req["channel"] = channelsToSubscribe[i].Channel
- if channelToSubscribe.Currency.String() != "" {
- if channelToSubscribe.Channel == wsCandles {
- // TODO: Add ability to select timescale
- req["key"] = fmt.Sprintf("trade:1D:%v",
- b.FormatExchangeCurrency(channelToSubscribe.Currency, asset.Spot).String())
- } else {
- req["symbol"] = b.FormatExchangeCurrency(channelToSubscribe.Currency,
- asset.Spot).String()
- }
- }
-
- if len(channelToSubscribe.Params) > 0 {
- for k, v := range channelToSubscribe.Params {
+ for k, v := range channelsToSubscribe[i].Params {
req[k] = v
}
- }
- return b.WebsocketConn.SendJSONMessage(req)
+ err := b.Websocket.Conn.SendJSONMessage(req)
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ b.Websocket.AddSuccessfulSubscriptions(channelsToSubscribe[i])
+ }
+ if errs != nil {
+ return errs
+ }
+ return nil
}
// Unsubscribe sends a websocket message to stop receiving data from the channel
-func (b *Bitfinex) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
- req := make(map[string]interface{})
- req["event"] = "unsubscribe"
- req["channel"] = channelToSubscribe.Channel
+func (b *Bitfinex) Unsubscribe(channelsToUnsubscribe []stream.ChannelSubscription) error {
+ var errs common.Errors
+ for i := range channelsToUnsubscribe {
+ req := make(map[string]interface{})
+ req["event"] = "unsubscribe"
+ req["channel"] = channelsToUnsubscribe[i].Channel
- if len(channelToSubscribe.Params) > 0 {
- for k, v := range channelToSubscribe.Params {
+ for k, v := range channelsToUnsubscribe[i].Params {
req[k] = v
}
+
+ err := b.Websocket.Conn.SendJSONMessage(req)
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ b.Websocket.RemoveSuccessfulUnsubscriptions(channelsToUnsubscribe[i])
}
- return b.WebsocketConn.SendJSONMessage(req)
+ if errs != nil {
+ return errs
+ }
+ return nil
}
// WsSendAuth sends a autheticated event payload
func (b *Bitfinex) WsSendAuth() error {
if !b.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
- return fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", b.Name)
+ return fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled",
+ b.Name)
}
nonce := strconv.FormatInt(time.Now().Unix(), 10)
payload := "AUTH" + nonce
@@ -931,15 +1027,13 @@ func (b *Bitfinex) WsSendAuth() error {
Event: "auth",
APIKey: b.API.Credentials.Key,
AuthPayload: payload,
- AuthSig: crypto.HexEncodeToString(
- crypto.GetHMAC(
- crypto.HashSHA512_384,
- []byte(payload),
- []byte(b.API.Credentials.Secret))),
+ AuthSig: crypto.HexEncodeToString(crypto.GetHMAC(crypto.HashSHA512_384,
+ []byte(payload),
+ []byte(b.API.Credentials.Secret))),
AuthNonce: nonce,
DeadManSwitch: 0,
}
- err := b.AuthenticatedWebsocketConn.SendJSONMessage(request)
+ err := b.Websocket.AuthConn.SendJSONMessage(request)
if err != nil {
b.Websocket.SetCanUseAuthenticatedEndpoints(false)
return err
@@ -954,7 +1048,8 @@ func (b *Bitfinex) WsAddSubscriptionChannel(chanID int, channel, pair string) {
b.WebsocketSubdChannels[chanID] = chanInfo
if b.Verbose {
- log.Debugf(log.ExchangeSys, "%s Subscribed to Channel: %s Pair: %s ChannelID: %d\n",
+ log.Debugf(log.ExchangeSys,
+ "%s Subscribed to Channel: %s Pair: %s ChannelID: %d\n",
b.Name,
channel,
pair,
@@ -964,9 +1059,9 @@ func (b *Bitfinex) WsAddSubscriptionChannel(chanID int, channel, pair string) {
// WsNewOrder authenticated new order request
func (b *Bitfinex) WsNewOrder(data *WsNewOrderRequest) (string, error) {
- data.CustomID = b.AuthenticatedWebsocketConn.GenerateMessageID(false)
+ data.CustomID = b.Websocket.AuthConn.GenerateMessageID(false)
request := makeRequestInterface(wsOrderNew, data)
- resp, err := b.AuthenticatedWebsocketConn.SendMessageReturnResponse(data.CustomID, request)
+ resp, err := b.Websocket.AuthConn.SendMessageReturnResponse(data.CustomID, request)
if err != nil {
return "", err
}
@@ -997,7 +1092,7 @@ func (b *Bitfinex) WsNewOrder(data *WsNewOrderRequest) (string, error) {
// WsModifyOrder authenticated modify order request
func (b *Bitfinex) WsModifyOrder(data *WsUpdateOrderRequest) error {
request := makeRequestInterface(wsOrderUpdate, data)
- resp, err := b.AuthenticatedWebsocketConn.SendMessageReturnResponse(data.OrderID, request)
+ resp, err := b.Websocket.AuthConn.SendMessageReturnResponse(data.OrderID, request)
if err != nil {
return err
}
@@ -1026,7 +1121,7 @@ func (b *Bitfinex) WsCancelMultiOrders(orderIDs []int64) error {
OrderID: orderIDs,
}
request := makeRequestInterface(wsCancelMultipleOrders, cancel)
- return b.AuthenticatedWebsocketConn.SendJSONMessage(request)
+ return b.Websocket.AuthConn.SendJSONMessage(request)
}
// WsCancelOrder authenticated cancel order request
@@ -1035,7 +1130,7 @@ func (b *Bitfinex) WsCancelOrder(orderID int64) error {
OrderID: orderID,
}
request := makeRequestInterface(wsOrderCancel, cancel)
- resp, err := b.AuthenticatedWebsocketConn.SendMessageReturnResponse(orderID, request)
+ resp, err := b.Websocket.AuthConn.SendMessageReturnResponse(orderID, request)
if err != nil {
return err
}
@@ -1061,13 +1156,13 @@ func (b *Bitfinex) WsCancelOrder(orderID int64) error {
func (b *Bitfinex) WsCancelAllOrders() error {
cancelAll := WsCancelAllOrdersRequest{All: 1}
request := makeRequestInterface(wsCancelMultipleOrders, cancelAll)
- return b.AuthenticatedWebsocketConn.SendJSONMessage(request)
+ return b.Websocket.AuthConn.SendJSONMessage(request)
}
// WsNewOffer authenticated new offer request
func (b *Bitfinex) WsNewOffer(data *WsNewOfferRequest) error {
request := makeRequestInterface(wsFundingOrderNew, data)
- return b.AuthenticatedWebsocketConn.SendJSONMessage(request)
+ return b.Websocket.AuthConn.SendJSONMessage(request)
}
// WsCancelOffer authenticated cancel offer request
@@ -1076,7 +1171,7 @@ func (b *Bitfinex) WsCancelOffer(orderID int64) error {
OrderID: orderID,
}
request := makeRequestInterface(wsFundingOrderCancel, cancel)
- resp, err := b.AuthenticatedWebsocketConn.SendMessageReturnResponse(orderID, request)
+ resp, err := b.Websocket.AuthConn.SendMessageReturnResponse(orderID, request)
if err != nil {
return err
}
diff --git a/exchanges/bitfinex/bitfinex_wrapper.go b/exchanges/bitfinex/bitfinex_wrapper.go
index 7b94995b..f31a94ec 100644
--- a/exchanges/bitfinex/bitfinex_wrapper.go
+++ b/exchanges/bitfinex/bitfinex_wrapper.go
@@ -19,8 +19,8 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -57,17 +57,27 @@ func (b *Bitfinex) SetDefaults() {
b.API.CredentialsValidator.RequiresKey = true
b.API.CredentialsValidator.RequiresSecret = true
- b.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- },
- UseGlobalFormat: true,
- RequestFormat: ¤cy.PairFormat{
- Uppercase: true,
- },
- ConfigFormat: ¤cy.PairFormat{
- Uppercase: true,
- },
+ fmt1 := currency.PairStore{
+ RequestFormat: ¤cy.PairFormat{Uppercase: true},
+ ConfigFormat: ¤cy.PairFormat{Uppercase: true},
+ }
+
+ fmt2 := currency.PairStore{
+ RequestFormat: ¤cy.PairFormat{Uppercase: true},
+ ConfigFormat: ¤cy.PairFormat{Uppercase: true, Delimiter: ":"},
+ }
+
+ err := b.StoreAssetPairFormat(asset.Spot, fmt1)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
+ }
+ err = b.StoreAssetPairFormat(asset.Margin, fmt2)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
+ }
+ err = b.StoreAssetPairFormat(asset.MarginFunding, fmt1)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
}
b.Features = exchange.Features{
@@ -111,7 +121,6 @@ func (b *Bitfinex) SetDefaults() {
OrderbookFetching: true,
AccountInfo: true,
Subscribe: true,
- Unsubscribe: true,
AuthenticatedEndpoints: true,
MessageCorrelation: true,
DeadMansSwitch: true,
@@ -155,7 +164,7 @@ func (b *Bitfinex) SetDefaults() {
b.API.Endpoints.URLDefault = bitfinexAPIURLBase
b.API.Endpoints.URL = b.API.Endpoints.URLDefault
b.API.Endpoints.WebsocketURL = publicBitfinexWebsocketEndpoint
- b.Websocket = wshandler.New()
+ b.Websocket = stream.New()
b.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
b.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
b.WebsocketOrderbookBufferLimit = exchange.DefaultWebsocketOrderbookBufferLimit
@@ -173,49 +182,41 @@ func (b *Bitfinex) Setup(exch *config.ExchangeConfig) error {
return err
}
- err = b.Websocket.Setup(
- &wshandler.WebsocketSetup{
- Enabled: exch.Features.Enabled.Websocket,
- Verbose: exch.Verbose,
- AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
- WebsocketTimeout: exch.WebsocketTrafficTimeout,
- DefaultURL: publicBitfinexWebsocketEndpoint,
- ExchangeName: exch.Name,
- RunningURL: exch.API.Endpoints.WebsocketURL,
- Connector: b.WsConnect,
- Subscriber: b.Subscribe,
- UnSubscriber: b.Unsubscribe,
- Features: &b.Features.Supports.WebsocketCapabilities,
- })
+ err = b.Websocket.Setup(&stream.WebsocketSetup{
+ Enabled: exch.Features.Enabled.Websocket,
+ Verbose: exch.Verbose,
+ AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
+ WebsocketTimeout: exch.WebsocketTrafficTimeout,
+ DefaultURL: publicBitfinexWebsocketEndpoint,
+ ExchangeName: exch.Name,
+ RunningURL: exch.API.Endpoints.WebsocketURL,
+ Connector: b.WsConnect,
+ Subscriber: b.Subscribe,
+ UnSubscriber: b.Unsubscribe,
+ GenerateSubscriptions: b.GenerateDefaultSubscriptions,
+ Features: &b.Features.Supports.WebsocketCapabilities,
+ OrderbookBufferLimit: exch.WebsocketOrderbookBufferLimit,
+ UpdateEntriesByID: true,
+ })
if err != nil {
return err
}
- b.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: b.Name,
- URL: b.Websocket.GetWebsocketURL(),
- ProxyURL: b.Websocket.GetProxyAddress(),
- Verbose: b.Verbose,
- ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
- ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
- }
- b.AuthenticatedWebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: b.Name,
- URL: authenticatedBitfinexWebsocketEndpoint,
- ProxyURL: b.Websocket.GetProxyAddress(),
- Verbose: b.Verbose,
+ err = b.Websocket.SetupNewConnection(stream.ConnectionSetup{
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
+ URL: publicBitfinexWebsocketEndpoint,
+ })
+ if err != nil {
+ return err
}
- b.Websocket.Orderbook.Setup(
- exch.WebsocketOrderbookBufferLimit,
- false,
- false,
- false,
- true,
- exch.Name)
- return nil
+ return b.Websocket.SetupNewConnection(stream.ConnectionSetup{
+ ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
+ ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
+ URL: authenticatedBitfinexWebsocketEndpoint,
+ Authenticated: true,
+ })
}
// Start starts the Bitfinex go routine
@@ -244,7 +245,9 @@ func (b *Bitfinex) Run() {
err := b.UpdateTradablePairs(false)
if err != nil {
log.Errorf(log.ExchangeSys,
- "%s failed to update tradable pairs. Err: %s", b.Name, err)
+ "%s failed to update tradable pairs. Err: %s",
+ b.Name,
+ err)
}
}
@@ -265,6 +268,13 @@ func (b *Bitfinex) FetchTradablePairs(a asset.Item) ([]string, error) {
symbols = append(symbols, k[1:])
}
case asset.Margin:
+ for k := range items {
+ if !strings.Contains(k, ":") {
+ continue
+ }
+ symbols = append(symbols, k[1:])
+ }
+ case asset.MarginFunding:
for k := range items {
if !strings.HasPrefix(k, "f") {
continue
@@ -281,15 +291,19 @@ func (b *Bitfinex) FetchTradablePairs(a asset.Item) ([]string, error) {
// UpdateTradablePairs updates the exchanges available pairs and stores
// them in the exchanges config
func (b *Bitfinex) UpdateTradablePairs(forceUpdate bool) error {
- for i := range b.CurrencyPairs.AssetTypes {
- pairs, err := b.FetchTradablePairs(b.CurrencyPairs.AssetTypes[i])
+ assets := b.CurrencyPairs.GetAssetTypes()
+ for i := range assets {
+ pairs, err := b.FetchTradablePairs(assets[i])
if err != nil {
return err
}
- err = b.UpdatePairs(currency.NewPairsFromStrings(pairs),
- b.CurrencyPairs.AssetTypes[i],
- false,
- forceUpdate)
+
+ p, err := currency.NewPairsFromStrings(pairs)
+ if err != nil {
+ return err
+ }
+
+ err = b.UpdatePairs(p, assets[i], false, forceUpdate)
if err != nil {
return err
}
@@ -299,34 +313,40 @@ func (b *Bitfinex) UpdateTradablePairs(forceUpdate bool) error {
// UpdateTicker updates and returns the ticker for a currency pair
func (b *Bitfinex) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
- enabledPairs := b.GetEnabledPairs(assetType)
+ enabledPairs, err := b.GetEnabledPairs(assetType)
+ if err != nil {
+ return nil, err
+ }
+
tickerNew, err := b.GetTickerBatch()
if err != nil {
return nil, err
}
+
for k, v := range tickerNew {
- if strings.HasPrefix(k, "f") {
- continue
- }
- pair := currency.NewPairFromString(k[1:]) // Remove prefix
- if !enabledPairs.Contains(p, true) {
- continue
- }
- tick := ticker.Price{
- Last: v.Last,
- High: v.High,
- Low: v.Low,
- Bid: v.Bid,
- Ask: v.Ask,
- Volume: v.Volume,
- Pair: pair,
- }
- err = ticker.ProcessTicker(b.Name, &tick, assetType)
+ pair, err := currency.NewPairFromString(k[1:]) // Remove prefix
if err != nil {
- log.Error(log.Ticker, err)
+ return nil, err
+ }
+
+ if !enabledPairs.Contains(pair, true) {
+ continue
+ }
+
+ err = ticker.ProcessTicker(&ticker.Price{
+ Last: v.Last,
+ High: v.High,
+ Low: v.Low,
+ Bid: v.Bid,
+ Ask: v.Ask,
+ Volume: v.Volume,
+ Pair: pair,
+ AssetType: assetType,
+ ExchangeName: b.Name})
+ if err != nil {
+ return nil, err
}
}
-
return ticker.GetTicker(b.Name, p, assetType)
}
@@ -354,7 +374,7 @@ func (b *Bitfinex) FetchOrderbook(p currency.Pair, assetType asset.Item) (*order
func (b *Bitfinex) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
b.appendOptionalDelimiter(&p)
var prefix = "t"
- if assetType == asset.Margin {
+ if assetType == asset.MarginFunding {
prefix = "f"
}
@@ -459,11 +479,17 @@ func (b *Bitfinex) SubmitOrder(o *order.Submit) (order.SubmitResponse, error) {
if err != nil {
return submitOrderResponse, err
}
+
+ fpair, err := b.FormatExchangeCurrency(o.Pair, o.AssetType)
+ if err != nil {
+ return submitOrderResponse, err
+ }
+
if b.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
submitOrderResponse.OrderID, err = b.WsNewOrder(&WsNewOrderRequest{
- CustomID: b.AuthenticatedWebsocketConn.GenerateMessageID(false),
+ CustomID: b.Websocket.AuthConn.GenerateMessageID(false),
Type: o.Type.String(),
- Symbol: b.FormatExchangeCurrency(o.Pair, asset.Spot).String(),
+ Symbol: fpair.String(),
Amount: o.Amount,
Price: o.Price,
})
@@ -473,18 +499,22 @@ func (b *Bitfinex) SubmitOrder(o *order.Submit) (order.SubmitResponse, error) {
} else {
var response Order
isBuying := o.Side == order.Buy
- b.appendOptionalDelimiter(&o.Pair)
- response, err = b.NewOrder(o.Pair.String(),
- o.Type.String(),
+ b.appendOptionalDelimiter(&fpair)
+ orderType := o.Type.Lower()
+ if o.AssetType == asset.Spot {
+ orderType = "exchange " + orderType
+ }
+ response, err = b.NewOrder(fpair.String(),
+ orderType,
o.Amount,
o.Price,
- false,
- isBuying)
+ isBuying,
+ false)
if err != nil {
return submitOrderResponse, err
}
- if response.OrderID > 0 {
- submitOrderResponse.OrderID = strconv.FormatInt(response.OrderID, 10)
+ if response.ID > 0 {
+ submitOrderResponse.OrderID = strconv.FormatInt(response.ID, 10)
}
if response.RemainingAmount == 0 {
submitOrderResponse.FullyMatched = true
@@ -615,11 +645,6 @@ func (b *Bitfinex) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdra
}, nil
}
-// GetWebsocket returns a pointer to the exchange websocket
-func (b *Bitfinex) GetWebsocket() (*wshandler.Websocket, error) {
- return b.Websocket, nil
-}
-
// GetFeeByType returns an estimate of fee based on type of transaction
func (b *Bitfinex) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if !b.AllowAuthenticatedRequest() && // Todo check connection status
@@ -639,23 +664,27 @@ func (b *Bitfinex) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail,
for i := range resp {
orderSide := order.Side(strings.ToUpper(resp[i].Side))
- timestamp, err := strconv.ParseInt(resp[i].Timestamp, 10, 64)
+ timestamp, err := strconv.ParseFloat(resp[i].Timestamp, 64)
if err != nil {
log.Warnf(log.ExchangeSys,
"Unable to convert timestamp '%s', leaving blank",
resp[i].Timestamp)
}
- orderDate := time.Unix(timestamp, 0)
+
+ pair, err := currency.NewPairFromString(resp[i].Symbol)
+ if err != nil {
+ return nil, err
+ }
orderDetail := order.Detail{
Amount: resp[i].OriginalAmount,
- Date: orderDate,
+ Date: time.Unix(int64(timestamp), 0),
Exchange: b.Name,
- ID: strconv.FormatInt(resp[i].OrderID, 10),
+ ID: strconv.FormatInt(resp[i].ID, 10),
Side: orderSide,
Price: resp[i].Price,
RemainingAmount: resp[i].RemainingAmount,
- Pair: currency.NewPairFromString(resp[i].Symbol),
+ Pair: pair,
ExecutedAmount: resp[i].ExecutedAmount,
}
@@ -706,16 +735,21 @@ func (b *Bitfinex) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
}
orderDate := time.Unix(timestamp, 0)
+ pair, err := currency.NewPairFromString(resp[i].Symbol)
+ if err != nil {
+ return nil, err
+ }
+
orderDetail := order.Detail{
Amount: resp[i].OriginalAmount,
Date: orderDate,
Exchange: b.Name,
- ID: strconv.FormatInt(resp[i].OrderID, 10),
+ ID: strconv.FormatInt(resp[i].ID, 10),
Side: orderSide,
Price: resp[i].Price,
RemainingAmount: resp[i].RemainingAmount,
ExecutedAmount: resp[i].ExecutedAmount,
- Pair: currency.NewPairFromString(resp[i].Symbol),
+ Pair: pair,
}
switch {
@@ -751,31 +785,6 @@ func (b *Bitfinex) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
return orders, nil
}
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func (b *Bitfinex) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- for i := range channels {
- b.appendOptionalDelimiter(&channels[i].Currency)
- }
- b.Websocket.SubscribeToChannels(channels)
- return nil
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func (b *Bitfinex) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- for i := range channels {
- b.appendOptionalDelimiter(&channels[i].Currency)
- }
- b.Websocket.RemoveSubscribedChannels(channels)
- return nil
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func (b *Bitfinex) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return b.Websocket.GetSubscriptions(), nil
-}
-
// AuthenticateWebsocket sends an authentication message to the websocket
func (b *Bitfinex) AuthenticateWebsocket() error {
return b.WsSendAuth()
@@ -822,7 +831,12 @@ func (b *Bitfinex) GetHistoricCandles(pair currency.Pair, a asset.Item, start, e
return kline.Item{}, errors.New(kline.ErrRequestExceedsExchangeLimits)
}
- candles, err := b.GetCandles(b.fixCasing(pair, a), b.FormatExchangeKlineInterval(interval),
+ cf, err := b.fixCasing(pair, a)
+ if err != nil {
+ return kline.Item{}, err
+ }
+
+ candles, err := b.GetCandles(cf, b.FormatExchangeKlineInterval(interval),
start.Unix()*1000, end.Unix()*1000,
b.Features.Enabled.Kline.ResultLimit, true)
if err != nil {
@@ -866,8 +880,13 @@ func (b *Bitfinex) GetHistoricCandlesExtended(pair currency.Pair, a asset.Item,
}
dates := kline.CalcDateRanges(start, end, interval, b.Features.Enabled.Kline.ResultLimit)
+ cf, err := b.fixCasing(pair, a)
+ if err != nil {
+ return kline.Item{}, err
+ }
+
for x := range dates {
- candles, err := b.GetCandles(b.fixCasing(pair, a), b.FormatExchangeKlineInterval(interval),
+ candles, err := b.GetCandles(cf, b.FormatExchangeKlineInterval(interval),
dates[x].Start.Unix()*1000, dates[x].End.Unix()*1000,
b.Features.Enabled.Kline.ResultLimit, true)
if err != nil {
@@ -890,7 +909,7 @@ func (b *Bitfinex) GetHistoricCandlesExtended(pair currency.Pair, a asset.Item,
return ret, nil
}
-func (b *Bitfinex) fixCasing(in currency.Pair, a asset.Item) string {
+func (b *Bitfinex) fixCasing(in currency.Pair, a asset.Item) (string, error) {
var checkString [2]byte
if a == asset.Spot {
checkString[0] = 't'
@@ -900,13 +919,18 @@ func (b *Bitfinex) fixCasing(in currency.Pair, a asset.Item) string {
checkString[1] = 'F'
}
+ fmt, err := b.FormatExchangeCurrency(in, a)
+ if err != nil {
+ return "", err
+ }
+
y := in.Base.String()
if (y[0] != checkString[0] && y[0] != checkString[1]) ||
(y[0] == checkString[1] && y[1] == checkString[1]) || in.Base == currency.TNB {
- return string(checkString[0]) + b.FormatExchangeCurrency(in, a).Upper().String()
+ return string(checkString[0]) + fmt.Upper().String(), nil
}
- runes := []rune(b.FormatExchangeCurrency(in, a).Upper().String())
+ runes := []rune(fmt.Upper().String())
runes[0] = unicode.ToLower(runes[0])
- return string(runes)
+ return string(runes), nil
}
diff --git a/exchanges/bitflyer/bitflyer_test.go b/exchanges/bitflyer/bitflyer_test.go
index 01718bdd..bd735157 100644
--- a/exchanges/bitflyer/bitflyer_test.go
+++ b/exchanges/bitflyer/bitflyer_test.go
@@ -133,7 +133,10 @@ func TestGetExchangeStatus(t *testing.T) {
func TestCheckFXString(t *testing.T) {
t.Parallel()
- p := currency.NewPairDelimiter("FXBTC_JPY", "_")
+ p, err := currency.NewPairDelimiter("FXBTC_JPY", "_")
+ if err != nil {
+ t.Fatal(err)
+ }
p = b.CheckFXString(p)
if p.Base.String() != "FX_BTC" {
t.Error("Bitflyer - CheckFXString() error")
@@ -144,15 +147,19 @@ func TestFetchTicker(t *testing.T) {
t.Parallel()
var p currency.Pair
- currencies := b.GetAvailablePairs(asset.Spot)
- for _, pair := range currencies {
- if pair.String() == "FXBTC_JPY" {
- p = pair
+ currencies, err := b.GetAvailablePairs(asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ for i := range currencies {
+ if currencies[i].String() == "FXBTC_JPY" {
+ p = currencies[i]
break
}
}
- _, err := b.FetchTicker(p, asset.Spot)
+ _, err = b.FetchTicker(p, asset.Spot)
if err != nil {
t.Error("Bitflyer - FetchTicker() error", err)
}
diff --git a/exchanges/bitflyer/bitflyer_wrapper.go b/exchanges/bitflyer/bitflyer_wrapper.go
index aff31ac4..038b42a0 100644
--- a/exchanges/bitflyer/bitflyer_wrapper.go
+++ b/exchanges/bitflyer/bitflyer_wrapper.go
@@ -17,7 +17,6 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -53,20 +52,20 @@ func (b *Bitflyer) SetDefaults() {
b.API.CredentialsValidator.RequiresKey = true
b.API.CredentialsValidator.RequiresSecret = true
- b.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- asset.Futures,
- },
- UseGlobalFormat: true,
- RequestFormat: ¤cy.PairFormat{
- Delimiter: "_",
- Uppercase: true,
- },
- ConfigFormat: ¤cy.PairFormat{
- Delimiter: "_",
- Uppercase: true,
- },
+ requestFmt := ¤cy.PairFormat{
+ Delimiter: currency.UnderscoreDelimiter,
+ Uppercase: true,
+ }
+ configFmt := ¤cy.PairFormat{
+ Delimiter: currency.UnderscoreDelimiter,
+ Uppercase: true,
+ }
+ err := b.SetGlobalPairsManager(requestFmt,
+ configFmt,
+ asset.Spot,
+ asset.Futures)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
}
b.Features = exchange.Features{
@@ -105,7 +104,6 @@ func (b *Bitflyer) Setup(exch *config.ExchangeConfig) error {
b.SetEnabled(false)
return nil
}
-
return b.SetupDefaults(exch)
}
@@ -141,6 +139,11 @@ func (b *Bitflyer) FetchTradablePairs(assetType asset.Item) ([]string, error) {
return nil, err
}
+ format, err := b.GetPairFormat(assetType, false)
+ if err != nil {
+ return nil, err
+ }
+
var products []string
for i := range pairs {
if pairs[i].Alias != "" && assetType == asset.Futures {
@@ -148,7 +151,7 @@ func (b *Bitflyer) FetchTradablePairs(assetType asset.Item) ([]string, error) {
} else if pairs[i].Alias == "" &&
assetType == asset.Spot &&
strings.Contains(pairs[i].ProductCode,
- b.GetPairFormat(assetType, false).Delimiter) {
+ format.Delimiter) {
products = append(products, pairs[i].ProductCode)
}
}
@@ -158,17 +161,19 @@ func (b *Bitflyer) FetchTradablePairs(assetType asset.Item) ([]string, error) {
// UpdateTradablePairs updates the exchanges available pairs and stores
// them in the exchanges config
func (b *Bitflyer) UpdateTradablePairs(forceUpdate bool) error {
- for x := range b.CurrencyPairs.AssetTypes {
- a := b.CurrencyPairs.AssetTypes[x]
- pairs, err := b.FetchTradablePairs(a)
+ assets := b.CurrencyPairs.GetAssetTypes()
+ for x := range assets {
+ pairs, err := b.FetchTradablePairs(assets[x])
if err != nil {
return err
}
- err = b.UpdatePairs(currency.NewPairsFromStrings(pairs),
- a,
- false,
- forceUpdate)
+ p, err := currency.NewPairsFromStrings(pairs)
+ if err != nil {
+ return err
+ }
+
+ err = b.UpdatePairs(p, assets[x], false, forceUpdate)
if err != nil {
return err
}
@@ -178,23 +183,21 @@ func (b *Bitflyer) UpdateTradablePairs(forceUpdate bool) error {
// UpdateTicker updates and returns the ticker for a currency pair
func (b *Bitflyer) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
- tickerPrice := new(ticker.Price)
-
- p = b.CheckFXString(p)
-
- tickerNew, err := b.GetTicker(p.String())
+ tickerNew, err := b.GetTicker(b.CheckFXString(p).String())
if err != nil {
- return tickerPrice, err
+ return nil, err
}
- tickerPrice.Pair = p
- tickerPrice.Ask = tickerNew.BestAsk
- tickerPrice.Bid = tickerNew.BestBid
- tickerPrice.Last = tickerNew.Last
- tickerPrice.Volume = tickerNew.Volume
- err = ticker.ProcessTicker(b.Name, tickerPrice, assetType)
+ err = ticker.ProcessTicker(&ticker.Price{
+ Pair: p,
+ Ask: tickerNew.BestAsk,
+ Bid: tickerNew.BestBid,
+ Last: tickerNew.Last,
+ Volume: tickerNew.Volume,
+ ExchangeName: b.Name,
+ AssetType: assetType})
if err != nil {
- return tickerPrice, err
+ return nil, err
}
return ticker.GetTicker(b.Name, p, assetType)
@@ -231,9 +234,7 @@ func (b *Bitflyer) FetchOrderbook(p currency.Pair, assetType asset.Item) (*order
func (b *Bitflyer) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
orderBook := new(orderbook.Base)
- p = b.CheckFXString(p)
-
- orderbookNew, err := b.GetOrderBook(p.String())
+ orderbookNew, err := b.GetOrderBook(b.CheckFXString(p).String())
if err != nil {
return orderBook, err
}
@@ -337,11 +338,6 @@ func (b *Bitflyer) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdra
return nil, common.ErrNotYetImplemented
}
-// GetWebsocket returns a pointer to the exchange websocket
-func (b *Bitflyer) GetWebsocket() (*wshandler.Websocket, error) {
- return nil, common.ErrNotYetImplemented
-}
-
// GetActiveOrders retrieves any orders that are active/open
func (b *Bitflyer) GetActiveOrders(getOrdersRequest *order.GetOrdersRequest) ([]order.Detail, error) {
return nil, common.ErrNotYetImplemented
@@ -362,28 +358,6 @@ func (b *Bitflyer) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error
return b.GetFee(feeBuilder)
}
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func (b *Bitflyer) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- return common.ErrFunctionNotSupported
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func (b *Bitflyer) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- return common.ErrFunctionNotSupported
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func (b *Bitflyer) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return nil, common.ErrFunctionNotSupported
-}
-
-// AuthenticateWebsocket sends an authentication message to the websocket
-func (b *Bitflyer) AuthenticateWebsocket() error {
- return common.ErrFunctionNotSupported
-}
-
// ValidateCredentials validates current credentials used for wrapper
// functionality
func (b *Bitflyer) ValidateCredentials() error {
diff --git a/exchanges/bithumb/bithumb_test.go b/exchanges/bithumb/bithumb_test.go
index c27e3755..e763fc93 100644
--- a/exchanges/bithumb/bithumb_test.go
+++ b/exchanges/bithumb/bithumb_test.go
@@ -207,6 +207,20 @@ func TestMarketSellOrder(t *testing.T) {
}
}
+func TestUpdateTicker(t *testing.T) {
+ cp := currency.NewPair(currency.QTUM, currency.KRW)
+ _, err := b.UpdateTicker(cp, asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ cp = currency.NewPair(currency.DASH, currency.KRW)
+ _, err = b.UpdateTicker(cp, asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
func setFeeBuilder() *exchange.FeeBuilder {
return &exchange.FeeBuilder{
Amount: 1,
@@ -436,8 +450,11 @@ func TestGetAccountInfo(t *testing.T) {
func TestModifyOrder(t *testing.T) {
t.Parallel()
- curr := currency.NewPairFromString("BTCUSD")
- _, err := b.ModifyOrder(&order.Modify{
+ curr, err := currency.NewPairFromString("BTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = b.ModifyOrder(&order.Modify{
ID: "1337",
Price: 100,
Amount: 1000,
@@ -535,18 +552,24 @@ func TestGetCandleStick(t *testing.T) {
}
func TestGetHistoricCandles(t *testing.T) {
- currencyPair := currency.NewPairFromString("BTC_KRW")
+ currencyPair, err := currency.NewPairFromString("BTC_KRW")
+ if err != nil {
+ t.Fatal(err)
+ }
startTime := time.Now().Add(-time.Hour * 24)
- _, err := b.GetHistoricCandles(currencyPair, asset.Spot, startTime, time.Now(), kline.OneDay)
+ _, err = b.GetHistoricCandles(currencyPair, asset.Spot, startTime, time.Now(), kline.OneDay)
if err != nil {
t.Fatal(err)
}
}
func TestGetHistoricCandlesExtended(t *testing.T) {
- currencyPair := currency.NewPairFromString("BTC_KRW")
+ currencyPair, err := currency.NewPairFromString("BTC_KRW")
+ if err != nil {
+ t.Fatal(err)
+ }
startTime := time.Now().Add(-time.Hour * 24)
- _, err := b.GetHistoricCandlesExtended(currencyPair, asset.Spot, startTime, time.Now(), kline.OneDay)
+ _, err = b.GetHistoricCandlesExtended(currencyPair, asset.Spot, startTime, time.Now(), kline.OneDay)
if err != nil {
t.Fatal(err)
}
diff --git a/exchanges/bithumb/bithumb_wrapper.go b/exchanges/bithumb/bithumb_wrapper.go
index 3baeab20..32701678 100644
--- a/exchanges/bithumb/bithumb_wrapper.go
+++ b/exchanges/bithumb/bithumb_wrapper.go
@@ -20,7 +20,6 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -56,20 +55,11 @@ func (b *Bithumb) SetDefaults() {
b.API.CredentialsValidator.RequiresKey = true
b.API.CredentialsValidator.RequiresSecret = true
- b.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- },
-
- UseGlobalFormat: true,
- RequestFormat: ¤cy.PairFormat{
- Uppercase: true,
- Delimiter: "_",
- },
- ConfigFormat: ¤cy.PairFormat{
- Uppercase: true,
- Index: "KRW",
- },
+ requestFmt := ¤cy.PairFormat{Uppercase: true, Delimiter: currency.UnderscoreDelimiter}
+ configFmt := ¤cy.PairFormat{Uppercase: true, Index: "KRW"}
+ err := b.SetGlobalPairsManager(requestFmt, configFmt, asset.Spot)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
}
b.Features = exchange.Features{
@@ -135,7 +125,6 @@ func (b *Bithumb) Setup(exch *config.ExchangeConfig) error {
b.SetEnabled(false)
return nil
}
-
return b.SetupDefaults(exch)
}
@@ -186,34 +175,46 @@ func (b *Bithumb) UpdateTradablePairs(forceUpdate bool) error {
return err
}
- return b.UpdatePairs(currency.NewPairsFromStrings(pairs), asset.Spot, false, forceUpdate)
+ p, err := currency.NewPairsFromStrings(pairs)
+ if err != nil {
+ return err
+ }
+
+ return b.UpdatePairs(p, asset.Spot, false, forceUpdate)
}
// UpdateTicker updates and returns the ticker for a currency pair
func (b *Bithumb) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
- tickerPrice := new(ticker.Price)
tickers, err := b.GetAllTickers()
if err != nil {
- return tickerPrice, err
+ return nil, err
}
- pairs := b.GetEnabledPairs(assetType)
+ pairs, err := b.GetEnabledPairs(assetType)
+ if err != nil {
+ return nil, err
+ }
+
for i := range pairs {
curr := pairs[i].Base.String()
t, ok := tickers[curr]
if !ok {
- continue
+ return nil,
+ fmt.Errorf("enabled pair %s [%s] not found in returned ticker map %v",
+ pairs[i], pairs, tickers)
}
- tp := ticker.Price{
- High: t.MaxPrice,
- Low: t.MinPrice,
- Volume: t.UnitsTraded24Hr,
- Open: t.OpeningPrice,
- Close: t.ClosingPrice,
- Pair: pairs[i],
- }
- err = ticker.ProcessTicker(b.Name, &tp, assetType)
+
+ err = ticker.ProcessTicker(&ticker.Price{
+ High: t.MaxPrice,
+ Low: t.MinPrice,
+ Volume: t.UnitsTraded24Hr,
+ Open: t.OpeningPrice,
+ Close: t.ClosingPrice,
+ Pair: pairs[i],
+ ExchangeName: b.Name,
+ AssetType: assetType,
+ })
if err != nil {
- log.Error(log.Ticker, err)
+ return nil, err
}
}
return ticker.GetTicker(b.Name, p, assetType)
@@ -398,7 +399,11 @@ func (b *Bithumb) CancelAllOrders(orderCancellation *order.Cancel) (order.Cancel
}
var allOrders []OrderData
- currs := b.GetEnabledPairs(asset.Spot)
+ currs, err := b.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return cancelAllOrdersResponse, err
+ }
+
for i := range currs {
orders, err := b.GetOrders("",
orderCancellation.Side.String(),
@@ -484,11 +489,6 @@ func (b *Bithumb) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdraw
return nil, common.ErrFunctionNotSupported
}
-// GetWebsocket returns a pointer to the exchange websocket
-func (b *Bithumb) GetWebsocket() (*wshandler.Websocket, error) {
- return nil, common.ErrFunctionNotSupported
-}
-
// GetFeeByType returns an estimate of fee based on type of transaction
func (b *Bithumb) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if !b.AllowAuthenticatedRequest() && // Todo check connection status
@@ -506,6 +506,11 @@ func (b *Bithumb) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail,
return nil, err
}
+ format, err := b.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return nil, err
+ }
+
for i := range resp.Data {
if resp.Data[i].Status != "placed" {
continue
@@ -522,7 +527,7 @@ func (b *Bithumb) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail,
Status: order.Active,
Pair: currency.NewPairWithDelimiter(resp.Data[i].OrderCurrency,
resp.Data[i].PaymentCurrency,
- b.GetPairFormat(asset.Spot, false).Delimiter),
+ format.Delimiter),
}
if resp.Data[i].Type == "bid" {
@@ -549,6 +554,11 @@ func (b *Bithumb) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
return nil, err
}
+ format, err := b.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return nil, err
+ }
+
for i := range resp.Data {
if resp.Data[i].Status == "placed" {
continue
@@ -564,7 +574,7 @@ func (b *Bithumb) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
RemainingAmount: resp.Data[i].UnitsRemaining,
Pair: currency.NewPairWithDelimiter(resp.Data[i].OrderCurrency,
resp.Data[i].PaymentCurrency,
- b.GetPairFormat(asset.Spot, false).Delimiter),
+ format.Delimiter),
}
if resp.Data[i].Type == "bid" {
@@ -582,28 +592,6 @@ func (b *Bithumb) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
return orders, nil
}
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func (b *Bithumb) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- return common.ErrFunctionNotSupported
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func (b *Bithumb) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- return common.ErrFunctionNotSupported
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func (b *Bithumb) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return nil, common.ErrFunctionNotSupported
-}
-
-// AuthenticateWebsocket sends an authentication message to the websocket
-func (b *Bithumb) AuthenticateWebsocket() error {
- return common.ErrFunctionNotSupported
-}
-
// ValidateCredentials validates current credentials used for wrapper
// functionality
func (b *Bithumb) ValidateCredentials() error {
@@ -624,7 +612,13 @@ func (b *Bithumb) GetHistoricCandles(pair currency.Pair, a asset.Item, start, en
}
}
- candle, err := b.GetCandleStick(b.FormatExchangeCurrency(pair, a).String(), b.FormatExchangeKlineInterval(interval))
+ formattedPair, err := b.FormatExchangeCurrency(pair, a)
+ if err != nil {
+ return kline.Item{}, err
+ }
+
+ candle, err := b.GetCandleStick(formattedPair.String(),
+ b.FormatExchangeKlineInterval(interval))
if err != nil {
return kline.Item{}, err
}
diff --git a/exchanges/bitmex/bitmex.go b/exchanges/bitmex/bitmex.go
index c2cdffbf..fe475b80 100644
--- a/exchanges/bitmex/bitmex.go
+++ b/exchanges/bitmex/bitmex.go
@@ -14,13 +14,11 @@ import (
"github.com/thrasher-corp/gocryptotrader/currency"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
)
// Bitmex is the overarching type across this package
type Bitmex struct {
exchange.Base
- WebsocketConn *wshandler.WebsocketConnection
}
const (
diff --git a/exchanges/bitmex/bitmex_test.go b/exchanges/bitmex/bitmex_test.go
index 82baab39..69fbb020 100644
--- a/exchanges/bitmex/bitmex_test.go
+++ b/exchanges/bitmex/bitmex_test.go
@@ -16,7 +16,7 @@ import (
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -45,13 +45,11 @@ func TestMain(m *testing.M) {
bitmexConfig.API.AuthenticatedWebsocketSupport = true
bitmexConfig.API.Credentials.Key = apiKey
bitmexConfig.API.Credentials.Secret = apiSecret
-
+ b.Websocket = sharedtestvalues.NewTestWebsocket()
err = b.Setup(bitmexConfig)
if err != nil {
log.Fatal("Bitmex setup error", err)
}
- b.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- b.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
os.Exit(m.Run())
}
@@ -678,17 +676,10 @@ func TestGetDepositAddress(t *testing.T) {
// TestWsAuth dials websocket, sends login request.
func TestWsAuth(t *testing.T) {
if !b.Websocket.IsEnabled() && !b.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
- t.Skip(wshandler.WebsocketNotEnabled)
- }
- b.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: b.Name,
- URL: b.Websocket.GetWebsocketURL(),
- Verbose: b.Verbose,
- ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
- ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
+ t.Skip(stream.WebsocketNotEnabled)
}
var dialer websocket.Dialer
- err := b.WebsocketConn.Dial(&dialer, http.Header{})
+ err := b.Websocket.Conn.Dial(&dialer, http.Header{})
if err != nil {
t.Fatal(err)
}
@@ -710,6 +701,13 @@ func TestWsAuth(t *testing.T) {
timer.Stop()
}
+func TestUpdateTradablePairs(t *testing.T) {
+ err := b.UpdateTradablePairs(true)
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
func TestWsPositionUpdate(t *testing.T) {
pressXToJSON := []byte(`{"table":"position",
"action":"update",
@@ -800,7 +798,6 @@ func TestWSPositionUpdateHandling(t *testing.T) {
}
func TestWSOrderbookHandling(t *testing.T) {
- b.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
pressXToJSON := []byte(`{
"table":"orderBookL2_25",
"keys":["symbol","id","side"],
@@ -871,7 +868,6 @@ func TestWSOrderbookHandling(t *testing.T) {
}
func TestWSDeleveragePositionUpdateHandling(t *testing.T) {
- b.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
pressXToJSON := []byte(`{"table":"position",
"action":"update",
"data":[{
diff --git a/exchanges/bitmex/bitmex_websocket.go b/exchanges/bitmex/bitmex_websocket.go
index 0b3789a2..59e0ac17 100644
--- a/exchanges/bitmex/bitmex_websocket.go
+++ b/exchanges/bitmex/bitmex_websocket.go
@@ -16,8 +16,8 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wsorderbook"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer"
"github.com/thrasher-corp/gocryptotrader/log"
)
@@ -67,67 +67,72 @@ const (
// WsConnect initiates a new websocket connection
func (b *Bitmex) WsConnect() error {
if !b.Websocket.IsEnabled() || !b.IsEnabled() {
- return errors.New(wshandler.WebsocketNotEnabled)
+ return errors.New(stream.WebsocketNotEnabled)
}
var dialer websocket.Dialer
- err := b.WebsocketConn.Dial(&dialer, http.Header{})
+ err := b.Websocket.Conn.Dial(&dialer, http.Header{})
if err != nil {
return err
}
- p, err := b.WebsocketConn.ReadMessage()
- if err != nil {
- b.Websocket.ReadMessageErrors <- err
- return err
+ resp := b.Websocket.Conn.ReadMessage()
+ if resp.Raw == nil {
+ return errors.New("connection closed")
}
- b.Websocket.TrafficAlert <- struct{}{}
var welcomeResp WebsocketWelcome
- err = json.Unmarshal(p.Raw, &welcomeResp)
+ err = json.Unmarshal(resp.Raw, &welcomeResp)
if err != nil {
return err
}
if b.Verbose {
- log.Debugf(log.ExchangeSys, "Successfully connected to Bitmex %s at time: %s Limit: %d",
+ log.Debugf(log.ExchangeSys,
+ "Successfully connected to Bitmex %s at time: %s Limit: %d",
welcomeResp.Info,
welcomeResp.Timestamp,
welcomeResp.Limit.Remaining)
}
go b.wsReadData()
- b.GenerateDefaultSubscriptions()
+ subs, err := b.GenerateDefaultSubscriptions()
+ if err != nil {
+ return err
+ }
+
+ err = b.Websocket.SubscribeToChannels(subs)
+ if err != nil {
+ return err
+ }
+
err = b.websocketSendAuth()
if err != nil {
- log.Errorf(log.ExchangeSys, "%v - authentication failed: %v\n", b.Name, err)
+ log.Errorf(log.ExchangeSys,
+ "%v - authentication failed: %v\n",
+ b.Name,
+ err)
+ } else {
+ authsubs, err := b.GenerateAuthenticatedSubscriptions()
+ if err != nil {
+ return err
+ }
+ return b.Websocket.SubscribeToChannels(authsubs)
}
- b.GenerateAuthenticatedSubscriptions()
return nil
}
// wsReadData receives and passes on websocket messages for processing
func (b *Bitmex) wsReadData() {
b.Websocket.Wg.Add(1)
-
- defer func() {
- b.Websocket.Wg.Done()
- }()
+ defer b.Websocket.Wg.Done()
for {
- select {
- case <-b.Websocket.ShutdownC:
+ resp := b.Websocket.Conn.ReadMessage()
+ if resp.Raw == nil {
return
-
- default:
- resp, err := b.WebsocketConn.ReadMessage()
- if err != nil {
- b.Websocket.DataHandler <- err
- return
- }
- b.Websocket.TrafficAlert <- struct{}{}
- err = b.wsHandleData(resp.Raw)
- if err != nil {
- b.Websocket.DataHandler <- err
- }
+ }
+ err := b.wsHandleData(resp.Raw)
+ if err != nil {
+ b.Websocket.DataHandler <- err
}
}
}
@@ -188,7 +193,12 @@ func (b *Bitmex) wsHandleData(respRaw []byte) error {
if len(orderbooks.Data) == 0 {
return fmt.Errorf("%s - Empty orderbook data received: %s", b.Name, respRaw)
}
- p := currency.NewPairFromString(orderbooks.Data[0].Symbol)
+ var p currency.Pair
+ p, err = currency.NewPairFromString(orderbooks.Data[0].Symbol)
+ if err != nil {
+ return err
+ }
+
var a asset.Item
a, err = b.GetPairAssetType(p)
if err != nil {
@@ -210,13 +220,14 @@ func (b *Bitmex) wsHandleData(respRaw []byte) error {
return err
}
- if trades.Action == bitmexActionInitialData {
- return nil
- }
-
for i := range trades.Data {
+ var p currency.Pair
+ p, err = currency.NewPairFromString(trades.Data[i].Symbol)
+ if err != nil {
+ return err
+ }
+
var a asset.Item
- p := currency.NewPairFromString(trades.Data[i].Symbol)
a, err = b.GetPairAssetType(p)
if err != nil {
return err
@@ -230,7 +241,7 @@ func (b *Bitmex) wsHandleData(respRaw []byte) error {
}
}
- b.Websocket.DataHandler <- wshandler.TradeData{
+ b.Websocket.DataHandler <- stream.TradeData{
Timestamp: trades.Data[i].Timestamp,
Price: trades.Data[i].Price,
Amount: float64(trades.Data[i].Size),
@@ -271,7 +282,12 @@ func (b *Bitmex) wsHandleData(respRaw []byte) error {
}
for i := range response.Data {
- p := currency.NewPairFromString(response.Data[i].Symbol)
+ var p currency.Pair
+ p, err = currency.NewPairFromString(response.Data[i].Symbol)
+ if err != nil {
+ return err
+ }
+
var a asset.Item
a, err = b.GetPairAssetType(p)
if err != nil {
@@ -459,7 +475,7 @@ func (b *Bitmex) wsHandleData(respRaw []byte) error {
}
b.Websocket.DataHandler <- response
default:
- b.Websocket.DataHandler <- wshandler.UnhandledMessageWarning{Message: b.Name + wshandler.UnhandledMessage + string(respRaw)}
+ b.Websocket.DataHandler <- stream.UnhandledMessageWarning{Message: b.Name + stream.UnhandledMessage + string(respRaw)}
return nil
}
}
@@ -467,7 +483,7 @@ func (b *Bitmex) wsHandleData(respRaw []byte) error {
}
// ProcessOrderbook processes orderbook updates
-func (b *Bitmex) processOrderbook(data []OrderBookL2, action string, currencyPair currency.Pair, assetType asset.Item) error {
+func (b *Bitmex) processOrderbook(data []OrderBookL2, action string, p currency.Pair, a asset.Item) error {
if len(data) < 1 {
return errors.New("bitmex_websocket.go error - no orderbook data")
}
@@ -490,8 +506,8 @@ func (b *Bitmex) processOrderbook(data []OrderBookL2, action string, currencyPai
ID: data[i].ID,
})
}
- newOrderBook.AssetType = assetType
- newOrderBook.Pair = currencyPair
+ newOrderBook.AssetType = a
+ newOrderBook.Pair = p
newOrderBook.ExchangeName = b.Name
err := b.Websocket.Orderbook.LoadSnapshot(&newOrderBook)
@@ -499,11 +515,6 @@ func (b *Bitmex) processOrderbook(data []OrderBookL2, action string, currencyPai
return fmt.Errorf("bitmex_websocket.go process orderbook error - %s",
err)
}
- b.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
- Pair: currencyPair,
- Asset: assetType,
- Exchange: b.Name,
- }
default:
var asks, bids []orderbook.Item
for i := range data {
@@ -520,40 +531,42 @@ func (b *Bitmex) processOrderbook(data []OrderBookL2, action string, currencyPai
})
}
- err := b.Websocket.Orderbook.Update(&wsorderbook.WebsocketOrderbookUpdate{
+ err := b.Websocket.Orderbook.Update(&buffer.Update{
Bids: bids,
Asks: asks,
- Pair: currencyPair,
- Asset: assetType,
+ Pair: p,
+ Asset: a,
Action: action,
})
if err != nil {
return err
}
-
- b.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
- Pair: currencyPair,
- Asset: assetType,
- Exchange: b.Name,
- }
}
return nil
}
// GenerateDefaultSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions()
-func (b *Bitmex) GenerateDefaultSubscriptions() {
+func (b *Bitmex) GenerateDefaultSubscriptions() ([]stream.ChannelSubscription, error) {
assets := b.GetAssetTypes()
var allPairs currency.Pairs
-
+ var associatedAssets []asset.Item
for x := range assets {
- contracts := b.GetEnabledPairs(assets[x])
+ contracts, err := b.GetEnabledPairs(assets[x])
+ if err != nil {
+ return nil, err
+ }
for y := range contracts {
allPairs = allPairs.Add(contracts[y])
+ associatedAssets = append(associatedAssets, assets[x])
}
}
+ if len(allPairs) != len(associatedAssets) {
+ return nil, fmt.Errorf("%s generate default subscriptions: pair and asset type len mismatch", b.Name)
+ }
+
channels := []string{bitmexWSOrderbookL2, bitmexWSTrade}
- subscriptions := []wshandler.WebsocketChannelSubscription{
+ subscriptions := []stream.ChannelSubscription{
{
Channel: bitmexWSAnnouncement,
},
@@ -561,25 +574,29 @@ func (b *Bitmex) GenerateDefaultSubscriptions() {
for i := range channels {
for j := range allPairs {
- subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
Channel: channels[i] + ":" + allPairs[j].String(),
Currency: allPairs[j],
+ Asset: associatedAssets[j],
})
}
}
- b.Websocket.SubscribeToChannels(subscriptions)
+ return subscriptions, nil
}
// GenerateAuthenticatedSubscriptions Adds authenticated subscriptions to websocket to be handled by ManageSubscriptions()
-func (b *Bitmex) GenerateAuthenticatedSubscriptions() {
+func (b *Bitmex) GenerateAuthenticatedSubscriptions() ([]stream.ChannelSubscription, error) {
if !b.Websocket.CanUseAuthenticatedEndpoints() {
- return
+ return nil, nil
+ }
+ contracts, err := b.GetEnabledPairs(asset.PerpetualContract)
+ if err != nil {
+ return nil, err
}
- contracts := b.GetEnabledPairs(asset.PerpetualContract)
channels := []string{bitmexWSExecution,
bitmexWSPosition,
}
- subscriptions := []wshandler.WebsocketChannelSubscription{
+ subscriptions := []stream.ChannelSubscription{
{
Channel: bitmexWSAffiliate,
},
@@ -601,31 +618,48 @@ func (b *Bitmex) GenerateAuthenticatedSubscriptions() {
}
for i := range channels {
for j := range contracts {
- subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
Channel: channels[i] + ":" + contracts[j].String(),
Currency: contracts[j],
+ Asset: asset.PerpetualContract,
})
}
}
- b.Websocket.SubscribeToChannels(subscriptions)
+ return subscriptions, nil
}
// Subscribe subscribes to a websocket channel
-func (b *Bitmex) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
+func (b *Bitmex) Subscribe(channelsToSubscribe []stream.ChannelSubscription) error {
var subscriber WebsocketRequest
subscriber.Command = "subscribe"
- subscriber.Arguments = append(subscriber.Arguments, channelToSubscribe.Channel)
- return b.WebsocketConn.SendJSONMessage(subscriber)
+
+ for i := range channelsToSubscribe {
+ subscriber.Arguments = append(subscriber.Arguments,
+ channelsToSubscribe[i].Channel)
+ }
+ err := b.Websocket.Conn.SendJSONMessage(subscriber)
+ if err != nil {
+ return err
+ }
+ b.Websocket.AddSuccessfulSubscriptions(channelsToSubscribe...)
+ return nil
}
// Unsubscribe sends a websocket message to stop receiving data from the channel
-func (b *Bitmex) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
- var subscriber WebsocketRequest
- subscriber.Command = "unsubscribe"
- subscriber.Arguments = append(subscriber.Arguments,
- channelToSubscribe.Params["args"],
- channelToSubscribe.Channel+":"+channelToSubscribe.Currency.String())
- return b.WebsocketConn.SendJSONMessage(subscriber)
+func (b *Bitmex) Unsubscribe(channelsToUnsubscribe []stream.ChannelSubscription) error {
+ var unsubscriber WebsocketRequest
+ unsubscriber.Command = "unsubscribe"
+
+ for i := range channelsToUnsubscribe {
+ unsubscriber.Arguments = append(unsubscriber.Arguments,
+ channelsToUnsubscribe[i].Channel)
+ }
+ err := b.Websocket.Conn.SendJSONMessage(unsubscriber)
+ if err != nil {
+ return err
+ }
+ b.Websocket.RemoveSuccessfulUnsubscriptions(channelsToUnsubscribe...)
+ return nil
}
// WebsocketSendAuth sends an authenticated subscription
@@ -645,7 +679,7 @@ func (b *Bitmex) websocketSendAuth() error {
sendAuth.Command = "authKeyExpires"
sendAuth.Arguments = append(sendAuth.Arguments, b.API.Credentials.Key, timestamp,
signature)
- err := b.WebsocketConn.SendJSONMessage(sendAuth)
+ err := b.Websocket.Conn.SendJSONMessage(sendAuth)
if err != nil {
b.Websocket.SetCanUseAuthenticatedEndpoints(false)
return err
diff --git a/exchanges/bitmex/bitmex_wrapper.go b/exchanges/bitmex/bitmex_wrapper.go
index 68a38f93..b5c6ad6d 100644
--- a/exchanges/bitmex/bitmex_wrapper.go
+++ b/exchanges/bitmex/bitmex_wrapper.go
@@ -18,8 +18,8 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -55,41 +55,17 @@ func (b *Bitmex) SetDefaults() {
b.API.CredentialsValidator.RequiresKey = true
b.API.CredentialsValidator.RequiresSecret = true
- b.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.PerpetualContract,
- asset.Futures,
- asset.DownsideProfitContract,
- asset.UpsideProfitContract,
- },
+ requestFmt := ¤cy.PairFormat{Uppercase: true}
+ configFmt := ¤cy.PairFormat{Uppercase: true}
+ err := b.SetGlobalPairsManager(requestFmt,
+ configFmt,
+ asset.PerpetualContract,
+ asset.Futures,
+ asset.Index)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
}
- // Same format used for perpetual contracts and futures
- fmt1 := currency.PairStore{
- RequestFormat: ¤cy.PairFormat{
- Uppercase: true,
- },
- ConfigFormat: ¤cy.PairFormat{
- Uppercase: true,
- },
- }
- b.CurrencyPairs.Store(asset.PerpetualContract, fmt1)
- b.CurrencyPairs.Store(asset.Futures, fmt1)
-
- // Upside and Downside profit contracts use the same format
- fmt2 := currency.PairStore{
- RequestFormat: ¤cy.PairFormat{
- Delimiter: "_",
- Uppercase: true,
- },
- ConfigFormat: ¤cy.PairFormat{
- Delimiter: "_",
- Uppercase: true,
- },
- }
- b.CurrencyPairs.Store(asset.DownsideProfitContract, fmt2)
- b.CurrencyPairs.Store(asset.UpsideProfitContract, fmt2)
-
b.Features = exchange.Features{
Supports: exchange.FeaturesSupported{
REST: true,
@@ -144,7 +120,7 @@ func (b *Bitmex) SetDefaults() {
b.API.Endpoints.URLDefault = bitmexAPIURL
b.API.Endpoints.URL = b.API.Endpoints.URLDefault
b.API.Endpoints.WebsocketURL = bitmexWSURL
- b.Websocket = wshandler.New()
+ b.Websocket = stream.New()
b.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
b.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
b.WebsocketOrderbookBufferLimit = exchange.DefaultWebsocketOrderbookBufferLimit
@@ -162,41 +138,30 @@ func (b *Bitmex) Setup(exch *config.ExchangeConfig) error {
return err
}
- err = b.Websocket.Setup(
- &wshandler.WebsocketSetup{
- Enabled: exch.Features.Enabled.Websocket,
- Verbose: exch.Verbose,
- AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
- WebsocketTimeout: exch.WebsocketTrafficTimeout,
- DefaultURL: bitmexWSURL,
- ExchangeName: exch.Name,
- RunningURL: exch.API.Endpoints.WebsocketURL,
- Connector: b.WsConnect,
- Subscriber: b.Subscribe,
- UnSubscriber: b.Unsubscribe,
- Features: &b.Features.Supports.WebsocketCapabilities,
- })
+ err = b.Websocket.Setup(&stream.WebsocketSetup{
+ Enabled: exch.Features.Enabled.Websocket,
+ Verbose: exch.Verbose,
+ AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
+ WebsocketTimeout: exch.WebsocketTrafficTimeout,
+ DefaultURL: bitmexWSURL,
+ ExchangeName: exch.Name,
+ RunningURL: exch.API.Endpoints.WebsocketURL,
+ Connector: b.WsConnect,
+ Subscriber: b.Subscribe,
+ UnSubscriber: b.Unsubscribe,
+ GenerateSubscriptions: b.GenerateDefaultSubscriptions,
+ Features: &b.Features.Supports.WebsocketCapabilities,
+ OrderbookBufferLimit: exch.WebsocketOrderbookBufferLimit,
+ UpdateEntriesByID: true,
+ })
if err != nil {
return err
}
- b.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: b.Name,
- URL: b.Websocket.GetWebsocketURL(),
- ProxyURL: b.Websocket.GetProxyAddress(),
- Verbose: b.Verbose,
+ return b.Websocket.SetupNewConnection(stream.ConnectionSetup{
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
- }
-
- b.Websocket.Orderbook.Setup(
- exch.WebsocketOrderbookBufferLimit,
- false,
- false,
- false,
- true,
- exch.Name)
- return nil
+ })
}
// Start starts the Bitmex go routine
@@ -211,7 +176,11 @@ func (b *Bitmex) Start(wg *sync.WaitGroup) {
// Run implements the Bitmex wrapper
func (b *Bitmex) Run() {
if b.Verbose {
- log.Debugf(log.ExchangeSys, "%s Websocket: %s. (url: %s).\n", b.Name, common.IsEnabled(b.Websocket.IsEnabled()), b.API.Endpoints.WebsocketURL)
+ log.Debugf(log.ExchangeSys,
+ "%s Websocket: %s. (url: %s).\n",
+ b.Name,
+ common.IsEnabled(b.Websocket.IsEnabled()),
+ b.API.Endpoints.WebsocketURL)
b.PrintEnabledPairs()
}
@@ -226,8 +195,8 @@ func (b *Bitmex) Run() {
}
// FetchTradablePairs returns a list of the exchanges tradable pairs
-func (b *Bitmex) FetchTradablePairs(_ asset.Item) ([]string, error) {
- marketInfo, err := b.GetActiveInstruments(&GenericRequestParams{})
+func (b *Bitmex) FetchTradablePairs(asset asset.Item) ([]string, error) {
+ marketInfo, err := b.GetActiveAndIndexInstruments()
if err != nil {
return nil, err
}
@@ -248,72 +217,78 @@ func (b *Bitmex) UpdateTradablePairs(forceUpdate bool) error {
return err
}
- var assetPairs []string
- for x := range b.CurrencyPairs.AssetTypes {
- switch b.CurrencyPairs.AssetTypes[x] {
- case asset.PerpetualContract:
- for y := range pairs {
- if strings.Contains(pairs[y], "USD") {
- assetPairs = append(assetPairs, pairs[y])
- }
- }
- case asset.Futures:
- for y := range pairs {
- if strings.Contains(pairs[y], "20") {
- assetPairs = append(assetPairs, pairs[y])
- }
- }
- case asset.DownsideProfitContract:
- for y := range pairs {
- if strings.Contains(pairs[y], "_D") {
- assetPairs = append(assetPairs, pairs[y])
- }
- }
- case asset.UpsideProfitContract:
- for y := range pairs {
- if strings.Contains(pairs[y], "_U") {
- assetPairs = append(assetPairs, pairs[y])
- }
- }
+ // Zerovalue current list which will remove old asset pairs when contract
+ // types expire or become obsolete
+ var assetPairs = map[asset.Item][]string{
+ asset.Index: {},
+ asset.PerpetualContract: {},
+ asset.Futures: {},
+ }
+
+ for x := range pairs {
+ if strings.Contains(pairs[x], ".") {
+ assetPairs[asset.Index] = append(assetPairs[asset.Index], pairs[x])
+ continue
}
- err = b.UpdatePairs(currency.NewPairsFromStrings(assetPairs), b.CurrencyPairs.AssetTypes[x], false, false)
- if err != nil {
- log.Warnf(log.ExchangeSys, "%s failed to update available pairs. Err: %v", b.Name, err)
+ if strings.Contains(pairs[x], "USD") {
+ assetPairs[asset.PerpetualContract] = append(assetPairs[asset.PerpetualContract],
+ pairs[x])
+ continue
}
- assetPairs = nil
+
+ assetPairs[asset.Futures] = append(assetPairs[asset.Futures], pairs[x])
}
+
+ for a, values := range assetPairs {
+ p, err := currency.NewPairsFromStrings(values)
+ if err != nil {
+ return err
+ }
+
+ err = b.UpdatePairs(p, a, false, false)
+ if err != nil {
+ log.Warnf(log.ExchangeSys,
+ "%s failed to update available pairs. Err: %v",
+ b.Name,
+ err)
+ }
+ }
+
return nil
}
// UpdateTicker updates and returns the ticker for a currency pair
func (b *Bitmex) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
- tickerPrice := new(ticker.Price)
- tick, err := b.GetActiveInstruments(&GenericRequestParams{})
+ tick, err := b.GetActiveAndIndexInstruments()
if err != nil {
- return tickerPrice, err
+ return nil, err
}
- pairs := b.GetEnabledPairs(assetType)
- for i := range pairs {
- for j := range tick {
- if !pairs[i].Equal(tick[j].Symbol) {
- continue
- }
- tickerPrice = &ticker.Price{
- Last: tick[j].LastPrice,
- High: tick[j].HighPrice,
- Low: tick[j].LowPrice,
- Bid: tick[j].BidPrice,
- Ask: tick[j].AskPrice,
- Volume: tick[j].Volume24h,
- Close: tick[j].PrevClosePrice,
- Pair: tick[j].Symbol,
- LastUpdated: tick[j].Timestamp,
- }
- err = ticker.ProcessTicker(b.Name, tickerPrice, assetType)
- if err != nil {
- log.Error(log.Ticker, err)
- }
+
+ pairs, err := b.GetEnabledPairs(assetType)
+ if err != nil {
+ return nil, err
+ }
+
+ for j := range tick {
+ if !pairs.Contains(tick[j].Symbol, true) {
+ continue
+ }
+
+ err = ticker.ProcessTicker(&ticker.Price{
+ Last: tick[j].LastPrice,
+ High: tick[j].HighPrice,
+ Low: tick[j].LowPrice,
+ Bid: tick[j].BidPrice,
+ Ask: tick[j].AskPrice,
+ Volume: tick[j].Volume24h,
+ Close: tick[j].PrevClosePrice,
+ Pair: tick[j].Symbol,
+ LastUpdated: tick[j].Timestamp,
+ ExchangeName: b.Name,
+ AssetType: assetType})
+ if err != nil {
+ return nil, err
}
}
return ticker.GetTicker(b.Name, p, assetType)
@@ -339,25 +314,34 @@ func (b *Bitmex) FetchOrderbook(p currency.Pair, assetType asset.Item) (*orderbo
// UpdateOrderbook updates and returns the orderbook for a currency pair
func (b *Bitmex) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
- orderBook := new(orderbook.Base)
-
- orderbookNew, err := b.GetOrderbook(OrderBookGetL2Params{
- Symbol: b.FormatExchangeCurrency(p, assetType).String(),
- Depth: 500})
- if err != nil {
- return orderBook, err
+ if assetType == asset.Index {
+ return nil, common.ErrFunctionNotSupported
}
- for _, ob := range orderbookNew {
- if strings.EqualFold(ob.Side, order.Sell.String()) {
- orderBook.Asks = append(orderBook.Asks,
- orderbook.Item{Amount: float64(ob.Size), Price: ob.Price})
+ fpair, err := b.FormatExchangeCurrency(p, assetType)
+ if err != nil {
+ return nil, err
+ }
+
+ orderbookNew, err := b.GetOrderbook(OrderBookGetL2Params{
+ Symbol: fpair.String(),
+ Depth: 500})
+ if err != nil {
+ return nil, err
+ }
+
+ orderBook := new(orderbook.Base)
+ for i := range orderbookNew {
+ if strings.EqualFold(orderbookNew[i].Side, order.Sell.String()) {
+ orderBook.Asks = append(orderBook.Asks, orderbook.Item{
+ Amount: float64(orderbookNew[i].Size),
+ Price: orderbookNew[i].Price})
continue
}
- if strings.EqualFold(ob.Side, order.Buy.String()) {
- orderBook.Bids = append(orderBook.Bids,
- orderbook.Item{Amount: float64(ob.Size), Price: ob.Price})
- continue
+ if strings.EqualFold(orderbookNew[i].Side, order.Buy.String()) {
+ orderBook.Bids = append(orderBook.Bids, orderbook.Item{
+ Amount: float64(orderbookNew[i].Size),
+ Price: orderbookNew[i].Price})
}
}
@@ -561,11 +545,6 @@ func (b *Bitmex) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdraw.
return nil, common.ErrFunctionNotSupported
}
-// GetWebsocket returns a pointer to the exchange websocket
-func (b *Bitmex) GetWebsocket() (*wshandler.Websocket, error) {
- return b.Websocket, nil
-}
-
// GetFeeByType returns an estimate of fee based on type of transaction
func (b *Bitmex) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if !b.AllowAuthenticatedRequest() && // Todo check connection status
@@ -587,6 +566,11 @@ func (b *Bitmex) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
return nil, err
}
+ format, err := b.GetPairFormat(asset.PerpetualContract, false)
+ if err != nil {
+ return nil, err
+ }
+
for i := range resp {
orderSide := orderSideMap[resp[i].Side]
orderType := orderTypeMap[resp[i].OrdType]
@@ -604,7 +588,7 @@ func (b *Bitmex) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
Status: order.Status(resp[i].OrdStatus),
Pair: currency.NewPairWithDelimiter(resp[i].Symbol,
resp[i].SettlCurrency,
- b.GetPairFormat(asset.PerpetualContract, false).Delimiter),
+ format.Delimiter),
}
orders = append(orders, orderDetail)
@@ -628,6 +612,11 @@ func (b *Bitmex) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, e
return nil, err
}
+ format, err := b.GetPairFormat(asset.PerpetualContract, false)
+ if err != nil {
+ return nil, err
+ }
+
for i := range resp {
orderSide := orderSideMap[resp[i].Side]
orderType := orderTypeMap[resp[i].OrdType]
@@ -645,7 +634,7 @@ func (b *Bitmex) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, e
Status: order.Status(resp[i].OrdStatus),
Pair: currency.NewPairWithDelimiter(resp[i].Symbol,
resp[i].SettlCurrency,
- b.GetPairFormat(asset.PerpetualContract, false).Delimiter),
+ format.Delimiter),
}
orders = append(orders, orderDetail)
@@ -658,25 +647,6 @@ func (b *Bitmex) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, e
return orders, nil
}
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func (b *Bitmex) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- b.Websocket.SubscribeToChannels(channels)
- return nil
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func (b *Bitmex) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- b.Websocket.RemoveSubscribedChannels(channels)
- return nil
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func (b *Bitmex) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return b.Websocket.GetSubscriptions(), nil
-}
-
// AuthenticateWebsocket sends an authentication message to the websocket
func (b *Bitmex) AuthenticateWebsocket() error {
return b.websocketSendAuth()
diff --git a/exchanges/bitstamp/bitstamp.go b/exchanges/bitstamp/bitstamp.go
index 384a61f1..ca88a128 100644
--- a/exchanges/bitstamp/bitstamp.go
+++ b/exchanges/bitstamp/bitstamp.go
@@ -18,7 +18,6 @@ import (
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
)
@@ -64,7 +63,6 @@ const (
// Bitstamp is the overarching type across the bitstamp package
type Bitstamp struct {
exchange.Base
- WebsocketConn *wshandler.WebsocketConnection
}
// GetFee returns an estimate of fee based on type of transaction
diff --git a/exchanges/bitstamp/bitstamp_live_test.go b/exchanges/bitstamp/bitstamp_live_test.go
index 5c6cebb0..96150d1e 100644
--- a/exchanges/bitstamp/bitstamp_live_test.go
+++ b/exchanges/bitstamp/bitstamp_live_test.go
@@ -30,12 +30,11 @@ func TestMain(m *testing.M) {
bitstampConfig.API.Credentials.Secret = apiSecret
bitstampConfig.API.Credentials.ClientID = customerID
b.SetDefaults()
+ b.Websocket = sharedtestvalues.NewTestWebsocket()
err = b.Setup(bitstampConfig)
if err != nil {
log.Fatal("Bitstamp setup error", err)
}
- b.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- b.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
log.Printf(sharedtestvalues.LiveTesting, b.Name, b.API.Endpoints.URL)
os.Exit(m.Run())
}
diff --git a/exchanges/bitstamp/bitstamp_mock_test.go b/exchanges/bitstamp/bitstamp_mock_test.go
index 136f8a85..eabbfc88 100644
--- a/exchanges/bitstamp/bitstamp_mock_test.go
+++ b/exchanges/bitstamp/bitstamp_mock_test.go
@@ -34,6 +34,7 @@ func TestMain(m *testing.M) {
bitstampConfig.API.Credentials.Secret = apiSecret
bitstampConfig.API.Credentials.ClientID = customerID
b.SetDefaults()
+ b.Websocket = sharedtestvalues.NewTestWebsocket()
err = b.Setup(bitstampConfig)
if err != nil {
log.Fatal("Bitstamp setup error", err)
@@ -46,8 +47,6 @@ func TestMain(m *testing.M) {
b.HTTPClient = newClient
b.API.Endpoints.URL = serverDetails + "/api"
- b.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- b.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
log.Printf(sharedtestvalues.MockTesting, b.Name, b.API.Endpoints.URL)
os.Exit(m.Run())
}
diff --git a/exchanges/bitstamp/bitstamp_test.go b/exchanges/bitstamp/bitstamp_test.go
index 7824c752..b8bfd573 100644
--- a/exchanges/bitstamp/bitstamp_test.go
+++ b/exchanges/bitstamp/bitstamp_test.go
@@ -678,21 +678,27 @@ func TestBitstamp_OHLC(t *testing.T) {
}
func TestBitstamp_GetHistoricCandles(t *testing.T) {
- currencyPair := currency.NewPairFromString("btcusd")
+ currencyPair, err := currency.NewPairFromString("btcusd")
+ if err != nil {
+ t.Fatal(err)
+ }
start := time.Unix(1546300800, 0)
end := time.Unix(1577836799, 0)
- _, err := b.GetHistoricCandles(currencyPair, asset.Spot, start, end, kline.OneDay)
+ _, err = b.GetHistoricCandles(currencyPair, asset.Spot, start, end, kline.OneDay)
if err != nil {
t.Fatal(err)
}
}
func TestBitstamp_GetHistoricCandlesExtended(t *testing.T) {
- currencyPair := currency.NewPairFromString("btcusd")
+ currencyPair, err := currency.NewPairFromString("btcusd")
+ if err != nil {
+ t.Fatal(err)
+ }
start := time.Unix(1546300800, 0)
end := time.Unix(1577836799, 0)
- _, err := b.GetHistoricCandlesExtended(currencyPair, asset.Spot, start, end, kline.OneDay)
+ _, err = b.GetHistoricCandlesExtended(currencyPair, asset.Spot, start, end, kline.OneDay)
if err != nil {
t.Fatal(err)
}
diff --git a/exchanges/bitstamp/bitstamp_websocket.go b/exchanges/bitstamp/bitstamp_websocket.go
index f91d5c88..7d8b72ce 100644
--- a/exchanges/bitstamp/bitstamp_websocket.go
+++ b/exchanges/bitstamp/bitstamp_websocket.go
@@ -9,11 +9,12 @@ import (
"time"
"github.com/gorilla/websocket"
+ "github.com/thrasher-corp/gocryptotrader/common"
"github.com/thrasher-corp/gocryptotrader/currency"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/log"
)
@@ -24,10 +25,10 @@ const (
// WsConnect connects to a websocket feed
func (b *Bitstamp) WsConnect() error {
if !b.Websocket.IsEnabled() || !b.IsEnabled() {
- return errors.New(wshandler.WebsocketNotEnabled)
+ return errors.New(stream.WebsocketNotEnabled)
}
var dialer websocket.Dialer
- err := b.WebsocketConn.Dial(&dialer, http.Header{})
+ err := b.Websocket.Conn.Dial(&dialer, http.Header{})
if err != nil {
return err
}
@@ -38,33 +39,27 @@ func (b *Bitstamp) WsConnect() error {
if err != nil {
b.Websocket.DataHandler <- err
}
- b.generateDefaultSubscriptions()
+ subs, err := b.generateDefaultSubscriptions()
+ if err != nil {
+ return err
+ }
go b.wsReadData()
-
- return nil
+ return b.Websocket.SubscribeToChannels(subs)
}
// wsReadData receives and passes on websocket messages for processing
func (b *Bitstamp) wsReadData() {
b.Websocket.Wg.Add(1)
- defer func() {
- b.Websocket.Wg.Done()
- }()
+ defer b.Websocket.Wg.Done()
+
for {
- select {
- case <-b.Websocket.ShutdownC:
+ resp := b.Websocket.Conn.ReadMessage()
+ if resp.Raw == nil {
return
- default:
- resp, err := b.WebsocketConn.ReadMessage()
- if err != nil {
- b.Websocket.ReadMessageErrors <- err
- return
- }
- b.Websocket.TrafficAlert <- struct{}{}
- err = b.wsHandleData(resp.Raw)
- if err != nil {
- b.Websocket.DataHandler <- err
- }
+ }
+ err := b.wsHandleData(resp.Raw)
+ if err != nil {
+ b.Websocket.DataHandler <- err
}
}
}
@@ -97,7 +92,11 @@ func (b *Bitstamp) wsHandleData(respRaw []byte) error {
return err
}
currencyPair := strings.Split(wsResponse.Channel, "_")
- p := currency.NewPairFromString(strings.ToUpper(currencyPair[2]))
+ p, err := currency.NewPairFromString(strings.ToUpper(currencyPair[2]))
+ if err != nil {
+ return err
+ }
+
err = b.wsUpdateOrderbook(wsOrderBookTemp.Data, p, asset.Spot)
if err != nil {
return err
@@ -109,7 +108,11 @@ func (b *Bitstamp) wsHandleData(respRaw []byte) error {
return err
}
currencyPair := strings.Split(wsResponse.Channel, "_")
- p := currency.NewPairFromString(strings.ToUpper(currencyPair[2]))
+ p, err := currency.NewPairFromString(strings.ToUpper(currencyPair[2]))
+ if err != nil {
+ return err
+ }
+
side := order.Buy
if wsTradeTemp.Data.Type == -1 {
side = order.Sell
@@ -119,7 +122,7 @@ func (b *Bitstamp) wsHandleData(respRaw []byte) error {
if err != nil {
return err
}
- b.Websocket.DataHandler <- wshandler.TradeData{
+ b.Websocket.DataHandler <- stream.TradeData{
Timestamp: time.Unix(wsTradeTemp.Data.Timestamp, 0),
CurrencyPair: p,
AssetType: a,
@@ -134,45 +137,73 @@ func (b *Bitstamp) wsHandleData(respRaw []byte) error {
log.Debugf(log.ExchangeSys, "%v - Websocket order acknowledgement", b.Name)
}
default:
- b.Websocket.DataHandler <- wshandler.UnhandledMessageWarning{Message: b.Name + wshandler.UnhandledMessage + string(respRaw)}
+ b.Websocket.DataHandler <- stream.UnhandledMessageWarning{Message: b.Name + stream.UnhandledMessage + string(respRaw)}
}
return nil
}
-func (b *Bitstamp) generateDefaultSubscriptions() {
+func (b *Bitstamp) generateDefaultSubscriptions() ([]stream.ChannelSubscription, error) {
var channels = []string{"live_trades_", "order_book_"}
- enabledCurrencies := b.GetEnabledPairs(asset.Spot)
- var subscriptions []wshandler.WebsocketChannelSubscription
+ enabledCurrencies, err := b.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+ var subscriptions []stream.ChannelSubscription
for i := range channels {
for j := range enabledCurrencies {
- subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
Channel: channels[i] + enabledCurrencies[j].Lower().String(),
+ Asset: asset.Spot,
})
}
}
- b.Websocket.SubscribeToChannels(subscriptions)
+ return subscriptions, nil
}
// Subscribe sends a websocket message to receive data from the channel
-func (b *Bitstamp) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
- req := websocketEventRequest{
- Event: "bts:subscribe",
- Data: websocketData{
- Channel: channelToSubscribe.Channel,
- },
+func (b *Bitstamp) Subscribe(channelsToSubscribe []stream.ChannelSubscription) error {
+ var errs common.Errors
+ for i := range channelsToSubscribe {
+ req := websocketEventRequest{
+ Event: "bts:subscribe",
+ Data: websocketData{
+ Channel: channelsToSubscribe[i].Channel,
+ },
+ }
+ err := b.Websocket.Conn.SendJSONMessage(req)
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ b.Websocket.AddSuccessfulSubscriptions(channelsToSubscribe[i])
}
- return b.WebsocketConn.SendJSONMessage(req)
+ if errs != nil {
+ return errs
+ }
+ return nil
}
// Unsubscribe sends a websocket message to stop receiving data from the channel
-func (b *Bitstamp) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
- req := websocketEventRequest{
- Event: "bts:unsubscribe",
- Data: websocketData{
- Channel: channelToSubscribe.Channel,
- },
+func (b *Bitstamp) Unsubscribe(channelsToUnsubscribe []stream.ChannelSubscription) error {
+ var errs common.Errors
+ for i := range channelsToUnsubscribe {
+ req := websocketEventRequest{
+ Event: "bts:unsubscribe",
+ Data: websocketData{
+ Channel: channelsToUnsubscribe[i].Channel,
+ },
+ }
+ err := b.Websocket.Conn.SendJSONMessage(req)
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ b.Websocket.RemoveSuccessfulUnsubscriptions(channelsToUnsubscribe[i])
}
- return b.WebsocketConn.SendJSONMessage(req)
+ if errs != nil {
+ return errs
+ }
+ return nil
}
func (b *Bitstamp) wsUpdateOrderbook(update websocketOrderBook, p currency.Pair, assetType asset.Item) error {
@@ -207,29 +238,22 @@ func (b *Bitstamp) wsUpdateOrderbook(update websocketOrderBook, p currency.Pair,
bids = append(bids, orderbook.Item{Price: target, Amount: amount})
}
- err := b.Websocket.Orderbook.LoadSnapshot(&orderbook.Base{
+ return b.Websocket.Orderbook.LoadSnapshot(&orderbook.Base{
Bids: bids,
Asks: asks,
Pair: p,
LastUpdated: time.Unix(update.Timestamp, 0),
- AssetType: asset.Spot,
+ AssetType: assetType,
ExchangeName: b.Name,
})
+}
+
+func (b *Bitstamp) seedOrderBook() error {
+ p, err := b.GetEnabledPairs(asset.Spot)
if err != nil {
return err
}
- b.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
- Pair: p,
- Asset: assetType,
- Exchange: b.Name,
- }
-
- return nil
-}
-
-func (b *Bitstamp) seedOrderBook() error {
- p := b.GetEnabledPairs(asset.Spot)
for x := range p {
orderbookSeed, err := b.GetOrderbook(p[x].String())
if err != nil {
@@ -257,12 +281,6 @@ func (b *Bitstamp) seedOrderBook() error {
if err != nil {
return err
}
-
- b.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
- Pair: p[x],
- Asset: asset.Spot,
- Exchange: b.Name,
- }
}
return nil
}
diff --git a/exchanges/bitstamp/bitstamp_wrapper.go b/exchanges/bitstamp/bitstamp_wrapper.go
index 79b2d1ca..1ab4624c 100644
--- a/exchanges/bitstamp/bitstamp_wrapper.go
+++ b/exchanges/bitstamp/bitstamp_wrapper.go
@@ -18,8 +18,8 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -56,17 +56,11 @@ func (b *Bitstamp) SetDefaults() {
b.API.CredentialsValidator.RequiresSecret = true
b.API.CredentialsValidator.RequiresClientID = true
- b.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- },
- UseGlobalFormat: true,
- RequestFormat: ¤cy.PairFormat{
- Uppercase: true,
- },
- ConfigFormat: ¤cy.PairFormat{
- Uppercase: true,
- },
+ requestFmt := ¤cy.PairFormat{Uppercase: true}
+ configFmt := ¤cy.PairFormat{Uppercase: true}
+ err := b.SetGlobalPairsManager(requestFmt, configFmt, asset.Spot)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
}
b.Features = exchange.Features{
@@ -137,7 +131,7 @@ func (b *Bitstamp) SetDefaults() {
b.API.Endpoints.URLDefault = bitstampAPIURL
b.API.Endpoints.URL = b.API.Endpoints.URLDefault
b.API.Endpoints.WebsocketURL = bitstampWSURL
- b.Websocket = wshandler.New()
+ b.Websocket = stream.New()
b.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
b.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
b.WebsocketOrderbookBufferLimit = exchange.DefaultWebsocketOrderbookBufferLimit
@@ -155,34 +149,30 @@ func (b *Bitstamp) Setup(exch *config.ExchangeConfig) error {
return err
}
- err = b.Websocket.Setup(
- &wshandler.WebsocketSetup{
- Enabled: exch.Features.Enabled.Websocket,
- Verbose: exch.Verbose,
- AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
- WebsocketTimeout: exch.WebsocketTrafficTimeout,
- DefaultURL: bitstampWSURL,
- ExchangeName: exch.Name,
- RunningURL: exch.API.Endpoints.WebsocketURL,
- Connector: b.WsConnect,
- Subscriber: b.Subscribe,
- UnSubscriber: b.Unsubscribe,
- Features: &b.Features.Supports.WebsocketCapabilities,
- })
+ err = b.Websocket.Setup(&stream.WebsocketSetup{
+ Enabled: exch.Features.Enabled.Websocket,
+ Verbose: exch.Verbose,
+ AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
+ WebsocketTimeout: exch.WebsocketTrafficTimeout,
+ DefaultURL: bitstampWSURL,
+ ExchangeName: exch.Name,
+ RunningURL: exch.API.Endpoints.WebsocketURL,
+ Connector: b.WsConnect,
+ Subscriber: b.Subscribe,
+ UnSubscriber: b.Unsubscribe,
+ GenerateSubscriptions: b.generateDefaultSubscriptions,
+ Features: &b.Features.Supports.WebsocketCapabilities,
+ OrderbookBufferLimit: exch.WebsocketOrderbookBufferLimit,
+ })
if err != nil {
return err
}
- b.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: b.Name,
+ return b.Websocket.SetupNewConnection(stream.ConnectionSetup{
URL: b.Websocket.GetWebsocketURL(),
- ProxyURL: b.Websocket.GetProxyAddress(),
- Verbose: b.Verbose,
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
- }
-
- return nil
+ })
}
// Start starts the Bitstamp go routine
@@ -245,32 +235,35 @@ func (b *Bitstamp) UpdateTradablePairs(forceUpdate bool) error {
return err
}
- return b.UpdatePairs(currency.NewPairsFromStrings(pairs), asset.Spot, false, forceUpdate)
+ p, err := currency.NewPairsFromStrings(pairs)
+ if err != nil {
+ return err
+ }
+
+ return b.UpdatePairs(p, asset.Spot, false, forceUpdate)
}
// UpdateTicker updates and returns the ticker for a currency pair
func (b *Bitstamp) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
- tickerPrice := new(ticker.Price)
tick, err := b.GetTicker(p.String(), false)
if err != nil {
- return tickerPrice, err
+ return nil, err
}
- tickerPrice = &ticker.Price{
- Last: tick.Last,
- High: tick.High,
- Low: tick.Low,
- Bid: tick.Bid,
- Ask: tick.Ask,
- Volume: tick.Volume,
- Open: tick.Open,
- Pair: p,
- LastUpdated: time.Unix(tick.Timestamp, 0),
- }
-
- err = ticker.ProcessTicker(b.Name, tickerPrice, assetType)
+ err = ticker.ProcessTicker(&ticker.Price{
+ Last: tick.Last,
+ High: tick.High,
+ Low: tick.Low,
+ Bid: tick.Bid,
+ Ask: tick.Ask,
+ Volume: tick.Volume,
+ Open: tick.Open,
+ Pair: p,
+ LastUpdated: time.Unix(tick.Timestamp, 0),
+ ExchangeName: b.Name,
+ AssetType: assetType})
if err != nil {
- return tickerPrice, err
+ return nil, err
}
return ticker.GetTicker(b.Name, p, assetType)
@@ -548,11 +541,6 @@ func (b *Bitstamp) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdra
}, nil
}
-// GetWebsocket returns a pointer to the exchange websocket
-func (b *Bitstamp) GetWebsocket() (*wshandler.Websocket, error) {
- return b.Websocket, nil
-}
-
// GetActiveOrders retrieves any orders that are active/open
func (b *Bitstamp) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
var currPair string
@@ -580,6 +568,11 @@ func (b *Bitstamp) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail,
"%s GetActiveOrders unable to parse time: %s\n", b.Name, err)
}
+ pair, err := currency.NewPairFromString(resp[i].Currency)
+ if err != nil {
+ return nil, err
+ }
+
orders = append(orders, order.Detail{
Amount: resp[i].Amount,
ID: strconv.FormatInt(resp[i].ID, 10),
@@ -587,7 +580,7 @@ func (b *Bitstamp) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail,
Type: order.Limit,
Side: orderSide,
Date: tm,
- Pair: currency.NewPairFromString(resp[i].Currency),
+ Pair: pair,
Exchange: b.Name,
})
}
@@ -604,6 +597,12 @@ func (b *Bitstamp) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
if len(req.Pairs) == 1 {
currPair = req.Pairs[0].String()
}
+
+ format, err := b.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return nil, err
+ }
+
resp, err := b.GetUserTransactions(currPair)
if err != nil {
return nil, err
@@ -644,7 +643,7 @@ func (b *Bitstamp) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
if quoteCurrency.String() != "" && baseCurrency.String() != "" {
currPair = currency.NewPairWithDelimiter(baseCurrency.String(),
quoteCurrency.String(),
- b.GetPairFormat(asset.Spot, false).Delimiter)
+ format.Delimiter)
}
tm, err := parseTime(resp[i].Date)
@@ -666,30 +665,6 @@ func (b *Bitstamp) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
return orders, nil
}
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func (b *Bitstamp) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- b.Websocket.SubscribeToChannels(channels)
- return nil
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func (b *Bitstamp) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- b.Websocket.RemoveSubscribedChannels(channels)
- return nil
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func (b *Bitstamp) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return b.Websocket.GetSubscriptions(), nil
-}
-
-// AuthenticateWebsocket sends an authentication message to the websocket
-func (b *Bitstamp) AuthenticateWebsocket() error {
- return common.ErrFunctionNotSupported
-}
-
// ValidateCredentials validates current credentials used for wrapper
// functionality
func (b *Bitstamp) ValidateCredentials() error {
@@ -712,8 +687,13 @@ func (b *Bitstamp) GetHistoricCandles(pair currency.Pair, a asset.Item, start, e
Interval: interval,
}
+ formattedPair, err := b.FormatExchangeCurrency(pair, a)
+ if err != nil {
+ return kline.Item{}, err
+ }
+
candles, err := b.OHLC(
- b.FormatExchangeCurrency(pair, a).Lower().String(),
+ formattedPair.Lower().String(),
start,
end,
b.FormatExchangeKlineInterval(interval),
@@ -759,9 +739,14 @@ func (b *Bitstamp) GetHistoricCandlesExtended(pair currency.Pair, a asset.Item,
}
dates := kline.CalcDateRanges(start, end, interval, b.Features.Enabled.Kline.ResultLimit)
+ formattedPair, err := b.FormatExchangeCurrency(pair, a)
+ if err != nil {
+ return kline.Item{}, err
+ }
+
for x := range dates {
candles, err := b.OHLC(
- b.FormatExchangeCurrency(pair, a).Lower().String(),
+ formattedPair.Lower().String(),
dates[x].Start,
dates[x].End,
b.FormatExchangeKlineInterval(interval),
diff --git a/exchanges/bittrex/bittrex_test.go b/exchanges/bittrex/bittrex_test.go
index 0eea30a0..196db8d7 100644
--- a/exchanges/bittrex/bittrex_test.go
+++ b/exchanges/bittrex/bittrex_test.go
@@ -343,14 +343,19 @@ func TestFormatWithdrawPermissions(t *testing.T) {
}
func TestGetActiveOrders(t *testing.T) {
+ p, err := currency.NewPairFromString(currPair)
+ if err != nil {
+ t.Fatal(err)
+ }
+
var getOrdersRequest = order.GetOrdersRequest{
Type: order.AnyType,
- Pairs: []currency.Pair{currency.NewPairFromString(currPair)},
+ Pairs: []currency.Pair{p},
}
getOrdersRequest.Pairs[0].Delimiter = "-"
- _, err := b.GetActiveOrders(&getOrdersRequest)
+ _, err = b.GetActiveOrders(&getOrdersRequest)
if areTestAPIKeysSet() && err != nil {
t.Errorf("Could not get open orders: %s", err)
} else if !areTestAPIKeysSet() && err == nil {
diff --git a/exchanges/bittrex/bittrex_wrapper.go b/exchanges/bittrex/bittrex_wrapper.go
index 032aa1f7..1cdf6fe3 100644
--- a/exchanges/bittrex/bittrex_wrapper.go
+++ b/exchanges/bittrex/bittrex_wrapper.go
@@ -18,7 +18,6 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -54,19 +53,11 @@ func (b *Bittrex) SetDefaults() {
b.API.CredentialsValidator.RequiresKey = true
b.API.CredentialsValidator.RequiresSecret = true
- b.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- },
- UseGlobalFormat: true,
- RequestFormat: ¤cy.PairFormat{
- Delimiter: "-",
- Uppercase: true,
- },
- ConfigFormat: ¤cy.PairFormat{
- Delimiter: "-",
- Uppercase: true,
- },
+ requestFmt := ¤cy.PairFormat{Delimiter: currency.DashDelimiter, Uppercase: true}
+ configFmt := ¤cy.PairFormat{Delimiter: currency.DashDelimiter, Uppercase: true}
+ err := b.SetGlobalPairsManager(requestFmt, configFmt, asset.Spot)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
}
b.Features = exchange.Features{
@@ -113,7 +104,6 @@ func (b *Bittrex) Setup(exch *config.ExchangeConfig) error {
b.SetEnabled(false)
return nil
}
-
return b.SetupDefaults(exch)
}
@@ -133,24 +123,53 @@ func (b *Bittrex) Run() {
}
forceUpdate := false
- delim := b.GetPairFormat(asset.Spot, false).Delimiter
- if !common.StringDataContains(b.GetEnabledPairs(asset.Spot).Strings(), delim) ||
- !common.StringDataContains(b.GetAvailablePairs(asset.Spot).Strings(), delim) {
+ format, err := b.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update currencies. Err: %s\n",
+ b.Name,
+ err)
+ return
+ }
+
+ pairs, err := b.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update currencies. Err: %s\n",
+ b.Name,
+ err)
+ return
+ }
+
+ avail, err := b.GetAvailablePairs(asset.Spot)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update currencies. Err: %s\n",
+ b.Name,
+ err)
+ return
+ }
+
+ if !common.StringDataContains(pairs.Strings(), format.Delimiter) ||
+ !common.StringDataContains(avail.Strings(), format.Delimiter) {
forceUpdate = true
log.Warn(log.ExchangeSys, "Available pairs for Bittrex reset due to config upgrade, please enable the ones you would like again")
-
- err := b.UpdatePairs(currency.NewPairsFromStrings(
- []string{currency.USDT.String() + delim + currency.BTC.String()},
- ),
- asset.Spot,
- true,
- true,
- )
+ pairs, err = currency.NewPairsFromStrings([]string{currency.USDT.String() +
+ format.Delimiter +
+ currency.BTC.String()})
if err != nil {
log.Errorf(log.ExchangeSys,
"%s failed to update currencies. Err: %s\n",
b.Name,
err)
+ } else {
+ err = b.UpdatePairs(pairs, asset.Spot, true, true)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update currencies. Err: %s\n",
+ b.Name,
+ err)
+ }
}
}
@@ -158,7 +177,7 @@ func (b *Bittrex) Run() {
return
}
- err := b.UpdateTradablePairs(forceUpdate)
+ err = b.UpdateTradablePairs(forceUpdate)
if err != nil {
log.Errorf(log.ExchangeSys,
"%s failed to update tradable pairs. Err: %s",
@@ -192,8 +211,12 @@ func (b *Bittrex) UpdateTradablePairs(forceUpdate bool) error {
if err != nil {
return err
}
+ p, err := currency.NewPairsFromStrings(pairs)
+ if err != nil {
+ return err
+ }
- return b.UpdatePairs(currency.NewPairsFromStrings(pairs), asset.Spot, false, forceUpdate)
+ return b.UpdatePairs(p, asset.Spot, false, forceUpdate)
}
// UpdateAccountInfo Retrieves balances for all enabled currencies for the
@@ -239,41 +262,46 @@ func (b *Bittrex) FetchAccountInfo() (account.Holdings, error) {
// UpdateTicker updates and returns the ticker for a currency pair
func (b *Bittrex) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
- tickerPrice := new(ticker.Price)
ticks, err := b.GetMarketSummaries()
if err != nil {
- return tickerPrice, err
- }
- pairs := b.GetEnabledPairs(assetType)
- for i := range pairs {
- for j := range ticks.Result {
- if !strings.EqualFold(ticks.Result[j].MarketName, pairs[i].String()) {
- continue
- }
- tickerTime, err := parseTime(ticks.Result[j].TimeStamp)
- if err != nil {
- log.Errorf(log.ExchangeSys,
- "%s UpdateTicker unable to parse time: %s\n", b.Name, err)
- }
- tickerPrice = &ticker.Price{
- Last: ticks.Result[j].Last,
- High: ticks.Result[j].High,
- Low: ticks.Result[j].Low,
- Bid: ticks.Result[j].Bid,
- Ask: ticks.Result[j].Ask,
- Volume: ticks.Result[j].BaseVolume,
- QuoteVolume: ticks.Result[j].Volume,
- Close: ticks.Result[j].PrevDay,
- Pair: pairs[i],
- LastUpdated: tickerTime,
- }
- err = ticker.ProcessTicker(b.Name, tickerPrice, assetType)
- if err != nil {
- log.Error(log.Ticker, err)
- }
- }
+ return nil, err
}
+ pairs, err := b.GetEnabledPairs(assetType)
+ if err != nil {
+ return nil, err
+ }
+
+ for j := range ticks.Result {
+ cp, err := currency.NewPairFromString(ticks.Result[j].MarketName)
+ if err != nil {
+ return nil, err
+ }
+ if !pairs.Contains(cp, true) {
+ continue
+ }
+ tickerTime, err := parseTime(ticks.Result[j].TimeStamp)
+ if err != nil {
+ return nil, err
+ }
+
+ err = ticker.ProcessTicker(&ticker.Price{
+ Last: ticks.Result[j].Last,
+ High: ticks.Result[j].High,
+ Low: ticks.Result[j].Low,
+ Bid: ticks.Result[j].Bid,
+ Ask: ticks.Result[j].Ask,
+ Volume: ticks.Result[j].BaseVolume,
+ QuoteVolume: ticks.Result[j].Volume,
+ Close: ticks.Result[j].PrevDay,
+ Pair: cp,
+ LastUpdated: tickerTime,
+ ExchangeName: b.Name,
+ AssetType: assetType})
+ if err != nil {
+ return nil, err
+ }
+ }
return ticker.GetTicker(b.Name, p, assetType)
}
@@ -297,12 +325,17 @@ func (b *Bittrex) FetchOrderbook(p currency.Pair, assetType asset.Item) (*orderb
// UpdateOrderbook updates and returns the orderbook for a currency pair
func (b *Bittrex) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
- orderBook := new(orderbook.Base)
- orderbookNew, err := b.GetOrderbook(b.FormatExchangeCurrency(p, assetType).String())
+ fpair, err := b.FormatExchangeCurrency(p, assetType)
if err != nil {
- return orderBook, err
+ return nil, err
}
+ orderbookNew, err := b.GetOrderbook(fpair.String())
+ if err != nil {
+ return nil, err
+ }
+
+ orderBook := new(orderbook.Base)
for x := range orderbookNew.Result.Buy {
orderBook.Bids = append(orderBook.Bids,
orderbook.Item{
@@ -453,11 +486,6 @@ func (b *Bittrex) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdraw
return nil, common.ErrFunctionNotSupported
}
-// GetWebsocket returns a pointer to the exchange websocket
-func (b *Bittrex) GetWebsocket() (*wshandler.Websocket, error) {
- return nil, common.ErrNotYetImplemented
-}
-
// GetFeeByType returns an estimate of fee based on type of transaction
func (b *Bittrex) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if !b.AllowAuthenticatedRequest() && // Todo check connection status
@@ -474,6 +502,11 @@ func (b *Bittrex) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail,
currPair = req.Pairs[0].String()
}
+ format, err := b.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return nil, err
+ }
+
resp, err := b.GetOpenOrders(currPair)
if err != nil {
return nil, err
@@ -491,8 +524,16 @@ func (b *Bittrex) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail,
resp.Result[i].Opened)
}
- pair := currency.NewPairDelimiter(resp.Result[i].Exchange,
- b.GetPairFormat(asset.Spot, false).Delimiter)
+ pair, err := currency.NewPairDelimiter(resp.Result[i].Exchange,
+ format.Delimiter)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "Exchange %v Func %v Order %v Could not parse currency pair %v",
+ b.Name,
+ "GetActiveOrders",
+ resp.Result[i].OrderUUID,
+ err)
+ }
orderType := order.Type(strings.ToUpper(resp.Result[i].Type))
orders = append(orders, order.Detail{
@@ -521,6 +562,11 @@ func (b *Bittrex) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
currPair = req.Pairs[0].String()
}
+ format, err := b.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return nil, err
+ }
+
resp, err := b.GetOrderHistoryForCurrency(currPair)
if err != nil {
return nil, err
@@ -533,13 +579,21 @@ func (b *Bittrex) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
log.Errorf(log.ExchangeSys,
"Exchange %v Func %v Order %v Could not parse date to unix with value of %v",
b.Name,
- "GetActiveOrders",
+ "GetOrderHistory",
resp.Result[i].OrderUUID,
resp.Result[i].Opened)
}
- pair := currency.NewPairDelimiter(resp.Result[i].Exchange,
- b.GetPairFormat(asset.Spot, false).Delimiter)
+ pair, err := currency.NewPairDelimiter(resp.Result[i].Exchange,
+ format.Delimiter)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "Exchange %v Func %v Order %v Could not parse currency pair %v",
+ b.Name,
+ "GetOrderHistory",
+ resp.Result[i].OrderUUID,
+ err)
+ }
orderType := order.Type(strings.ToUpper(resp.Result[i].Type))
orders = append(orders, order.Detail{
@@ -561,28 +615,6 @@ func (b *Bittrex) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
return orders, nil
}
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func (b *Bittrex) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- return common.ErrFunctionNotSupported
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func (b *Bittrex) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- return common.ErrFunctionNotSupported
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func (b *Bittrex) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return nil, common.ErrFunctionNotSupported
-}
-
-// AuthenticateWebsocket sends an authentication message to the websocket
-func (b *Bittrex) AuthenticateWebsocket() error {
- return common.ErrFunctionNotSupported
-}
-
// ValidateCredentials validates current credentials used for wrapper
// functionality
func (b *Bittrex) ValidateCredentials() error {
diff --git a/exchanges/btcmarkets/btcmarkets.go b/exchanges/btcmarkets/btcmarkets.go
index 870dc56c..02988dff 100644
--- a/exchanges/btcmarkets/btcmarkets.go
+++ b/exchanges/btcmarkets/btcmarkets.go
@@ -18,7 +18,6 @@ import (
"github.com/thrasher-corp/gocryptotrader/currency"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
)
const (
@@ -72,13 +71,12 @@ const (
heartbeat = "heartbeat"
tick = "tick"
wsOB = "orderbookUpdate"
- tradeEndPoint = "tradeEndPoint"
+ tradeEndPoint = "trade"
)
// BTCMarkets is the overarching type across the BTCMarkets package
type BTCMarkets struct {
exchange.Base
- WebsocketConn *wshandler.WebsocketConnection
}
// GetMarkets returns the BTCMarkets instruments
@@ -191,7 +189,7 @@ func (b *BTCMarkets) GetMarketCandles(marketID, timeWindow string, from, to time
}
// GetTickers gets multiple tickers
-func (b *BTCMarkets) GetTickers(marketIDs []currency.Pair) ([]Ticker, error) {
+func (b *BTCMarkets) GetTickers(marketIDs currency.Pairs) ([]Ticker, error) {
var tickers []Ticker
params := url.Values{}
for x := range marketIDs {
@@ -761,7 +759,11 @@ func (b *BTCMarkets) GetFee(feeBuilder *exchange.FeeBuilder) (float64, error) {
return fee, err
}
for x := range temp.FeeByMarkets {
- if currency.NewPairFromString(temp.FeeByMarkets[x].MarketID) == feeBuilder.Pair {
+ p, err := currency.NewPairFromString(temp.FeeByMarkets[x].MarketID)
+ if err != nil {
+ return 0, err
+ }
+ if p == feeBuilder.Pair {
fee = temp.FeeByMarkets[x].MakerFeeRate
if !feeBuilder.IsMaker {
fee = temp.FeeByMarkets[x].TakerFeeRate
diff --git a/exchanges/btcmarkets/btcmarkets_test.go b/exchanges/btcmarkets/btcmarkets_test.go
index b0df0e52..46acc76d 100644
--- a/exchanges/btcmarkets/btcmarkets_test.go
+++ b/exchanges/btcmarkets/btcmarkets_test.go
@@ -44,21 +44,17 @@ func TestMain(m *testing.M) {
bConfig.API.Credentials.Key = apiKey
bConfig.API.Credentials.Secret = apiSecret
bConfig.API.AuthenticatedSupport = true
-
+ b.Websocket = sharedtestvalues.NewTestWebsocket()
err = b.Setup(bConfig)
if err != nil {
log.Fatal(err)
}
- b.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- b.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
-
err = b.ValidateCredentials()
if err != nil {
fmt.Println("API credentials are invalid:", err)
b.API.AuthenticatedSupport = false
b.API.AuthenticatedWebsocketSupport = false
}
-
os.Exit(m.Run())
}
@@ -108,8 +104,11 @@ func TestGetMarketCandles(t *testing.T) {
func TestGetTickers(t *testing.T) {
t.Parallel()
- temp := currency.NewPairsFromStrings([]string{LTCAUD, BTCAUD})
- _, err := b.GetTickers(temp)
+ temp, err := currency.NewPairsFromStrings([]string{LTCAUD, BTCAUD})
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = b.GetTickers(temp)
if err != nil {
t.Error(err)
}
@@ -720,8 +719,11 @@ func TestWsOrders(t *testing.T) {
}
func TestBTCMarkets_GetHistoricCandles(t *testing.T) {
- p := currency.NewPairFromString(BTCAUD)
- _, err := b.GetHistoricCandles(p, asset.Spot, time.Now().Add(-time.Hour*24).UTC(), time.Now().UTC(), kline.OneHour)
+ p, err := currency.NewPairFromString(BTCAUD)
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = b.GetHistoricCandles(p, asset.Spot, time.Now().Add(-time.Hour*24).UTC(), time.Now().UTC(), kline.OneHour)
if err != nil {
t.Fatal(err)
}
@@ -736,8 +738,11 @@ func TestBTCMarkets_GetHistoricCandles(t *testing.T) {
func TestBTCMarkets_GetHistoricCandlesExtended(t *testing.T) {
start := time.Now().AddDate(0, 0, -1001)
end := time.Now()
- p := currency.NewPairFromString(BTCAUD)
- _, err := b.GetHistoricCandlesExtended(p, asset.Spot, start, end, kline.OneDay)
+ p, err := currency.NewPairFromString(BTCAUD)
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = b.GetHistoricCandlesExtended(p, asset.Spot, start, end, kline.OneDay)
if err != nil {
t.Fatal(err)
}
diff --git a/exchanges/btcmarkets/btcmarkets_types.go b/exchanges/btcmarkets/btcmarkets_types.go
index 0592296f..8c9c77a6 100644
--- a/exchanges/btcmarkets/btcmarkets_types.go
+++ b/exchanges/btcmarkets/btcmarkets_types.go
@@ -337,21 +337,14 @@ type TradingFeeResponse struct {
FeeByMarkets []TradingFeeData `json:"FeeByMarkets"`
}
-// WsSubscribe message sent via ws to subscribe
+// WsSubscribe defines a subscription message used in the Subscribe function
type WsSubscribe struct {
MarketIDs []string `json:"marketIds,omitempty"`
- Channels []string `json:"channels"`
- MessageType string `json:"messageType"`
-}
-
-// WsAuthSubscribe message sent via login to subscribe
-type WsAuthSubscribe struct {
- MarketIDs []string `json:"marketIds,omitempty"`
- Channels []string `json:"channels"`
- Key string `json:"key"`
- Signature string `json:"signature"`
- Timestamp string `json:"timestamp"`
- MessageType string `json:"messageType"`
+ Channels []string `json:"channels,omitempty"`
+ Key string `json:"key,omitempty"`
+ Signature string `json:"signature,omitempty"`
+ Timestamp string `json:"timestamp,omitempty"`
+ MessageType string `json:"messageType,omitempty"`
}
// WsMessageType message sent via ws to determine type
@@ -380,6 +373,7 @@ type WsTrade struct {
TradeID int64 `json:"tradeId"`
Price float64 `json:"price,string"`
Volume float64 `json:"volume,string"`
+ Side string `json:"side"`
MessageType string `json:"messageType"`
}
diff --git a/exchanges/btcmarkets/btcmarkets_websocket.go b/exchanges/btcmarkets/btcmarkets_websocket.go
index a5f187a5..7fe37656 100644
--- a/exchanges/btcmarkets/btcmarkets_websocket.go
+++ b/exchanges/btcmarkets/btcmarkets_websocket.go
@@ -12,13 +12,12 @@ import (
"github.com/thrasher-corp/gocryptotrader/common"
"github.com/thrasher-corp/gocryptotrader/common/crypto"
"github.com/thrasher-corp/gocryptotrader/currency"
- exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wsorderbook"
"github.com/thrasher-corp/gocryptotrader/log"
)
@@ -29,10 +28,10 @@ const (
// WsConnect connects to a websocket feed
func (b *BTCMarkets) WsConnect() error {
if !b.Websocket.IsEnabled() || !b.IsEnabled() {
- return errors.New(wshandler.WebsocketNotEnabled)
+ return errors.New(stream.WebsocketNotEnabled)
}
var dialer websocket.Dialer
- err := b.WebsocketConn.Dial(&dialer, http.Header{})
+ err := b.Websocket.Conn.Dial(&dialer, http.Header{})
if err != nil {
return err
}
@@ -40,35 +39,26 @@ func (b *BTCMarkets) WsConnect() error {
log.Debugf(log.ExchangeSys, "%s Connected to Websocket.\n", b.Name)
}
go b.wsReadData()
- if b.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
- b.createChannels()
+ subs, err := b.generateDefaultSubscriptions()
+ if err != nil {
+ return err
}
- b.generateDefaultSubscriptions()
- return nil
+ return b.Websocket.SubscribeToChannels(subs)
}
// wsReadData receives and passes on websocket messages for processing
func (b *BTCMarkets) wsReadData() {
b.Websocket.Wg.Add(1)
- defer func() {
- b.Websocket.Wg.Done()
- }()
+ defer b.Websocket.Wg.Done()
for {
- select {
- case <-b.Websocket.ShutdownC:
+ resp := b.Websocket.Conn.ReadMessage()
+ if resp.Raw == nil {
return
- default:
- resp, err := b.WebsocketConn.ReadMessage()
- if err != nil {
- b.Websocket.ReadMessageErrors <- err
- return
- }
- b.Websocket.TrafficAlert <- struct{}{}
- err = b.wsHandleData(resp.Raw)
- if err != nil {
- b.Websocket.DataHandler <- err
- }
+ }
+ err := b.wsHandleData(resp.Raw)
+ if err != nil {
+ b.Websocket.DataHandler <- err
}
}
}
@@ -91,7 +81,11 @@ func (b *BTCMarkets) wsHandleData(respRaw []byte) error {
return err
}
- p := currency.NewPairFromString(ob.Currency)
+ p, err := currency.NewPairFromString(ob.Currency)
+ if err != nil {
+ return err
+ }
+
var bids, asks []orderbook.Item
for x := range ob.Bids {
var price, amount float64
@@ -135,7 +129,7 @@ func (b *BTCMarkets) wsHandleData(respRaw []byte) error {
ExchangeName: b.Name,
})
} else {
- err = b.Websocket.Orderbook.Update(&wsorderbook.WebsocketOrderbookUpdate{
+ err = b.Websocket.Orderbook.Update(&buffer.Update{
UpdateTime: ob.Timestamp,
Asset: asset.Spot,
Bids: bids,
@@ -147,26 +141,31 @@ func (b *BTCMarkets) wsHandleData(respRaw []byte) error {
if err != nil {
return err
}
- b.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
- Pair: p,
- Asset: asset.Spot,
- Exchange: b.Name,
- }
case tradeEndPoint:
var trade WsTrade
err := json.Unmarshal(respRaw, &trade)
if err != nil {
return err
}
- p := currency.NewPairFromString(trade.Currency)
- b.Websocket.DataHandler <- wshandler.TradeData{
+
+ p, err := currency.NewPairFromString(trade.Currency)
+ if err != nil {
+ return err
+ }
+
+ side := order.Buy
+ if trade.Side == "Ask" {
+ side = order.Sell
+ }
+
+ b.Websocket.DataHandler <- stream.TradeData{
Timestamp: trade.Timestamp,
CurrencyPair: p,
AssetType: asset.Spot,
Exchange: b.Name,
Price: trade.Price,
Amount: trade.Volume,
- Side: order.UnknownSide,
+ Side: side,
EventType: order.UnknownType,
}
case tick:
@@ -176,7 +175,10 @@ func (b *BTCMarkets) wsHandleData(respRaw []byte) error {
return err
}
- p := currency.NewPairFromString(tick.Currency)
+ p, err := currency.NewPairFromString(tick.Currency)
+ if err != nil {
+ return err
+ }
b.Websocket.DataHandler <- &ticker.Price{
ExchangeName: b.Name,
@@ -247,12 +249,16 @@ func (b *BTCMarkets) wsHandleData(respRaw []byte) error {
Err: err,
}
}
- p := currency.NewPairFromString(orderData.MarketID)
- var a asset.Item
- a, err = b.GetPairAssetType(p)
+
+ p, err := currency.NewPairFromString(orderData.MarketID)
if err != nil {
- return err
+ b.Websocket.DataHandler <- order.ClassificationError{
+ Exchange: b.Name,
+ OrderID: orderID,
+ Err: err,
+ }
}
+
b.Websocket.DataHandler <- &order.Detail{
Price: price,
Amount: originalAmount,
@@ -263,7 +269,7 @@ func (b *BTCMarkets) wsHandleData(respRaw []byte) error {
Type: oType,
Side: oSide,
Status: oStatus,
- AssetType: a,
+ AssetType: asset.Spot,
Date: orderData.Timestamp,
Trades: trades,
Pair: p,
@@ -276,91 +282,80 @@ func (b *BTCMarkets) wsHandleData(respRaw []byte) error {
}
return fmt.Errorf("%v websocket error. Code: %v Message: %v", b.Name, wsErr.Code, wsErr.Message)
default:
- b.Websocket.DataHandler <- wshandler.UnhandledMessageWarning{Message: b.Name + wshandler.UnhandledMessage + string(respRaw)}
+ b.Websocket.DataHandler <- stream.UnhandledMessageWarning{Message: b.Name + stream.UnhandledMessage + string(respRaw)}
return nil
}
return nil
}
-func (b *BTCMarkets) generateDefaultSubscriptions() {
- var channels = []string{tick, tradeEndPoint, wsOB}
- enabledCurrencies := b.GetEnabledPairs(asset.Spot)
- var subscriptions []wshandler.WebsocketChannelSubscription
+func (b *BTCMarkets) generateDefaultSubscriptions() ([]stream.ChannelSubscription, error) {
+ var channels = []string{wsOB, tick, tradeEndPoint}
+ enabledCurrencies, err := b.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+ var subscriptions []stream.ChannelSubscription
for i := range channels {
for j := range enabledCurrencies {
- subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
Channel: channels[i],
Currency: enabledCurrencies[j],
+ Asset: asset.Spot,
})
}
}
- b.Websocket.SubscribeToChannels(subscriptions)
+
+ var authChannels = []string{fundChange, heartbeat, orderChange}
+ if b.Websocket.CanUseAuthenticatedEndpoints() {
+ for i := range authChannels {
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
+ Channel: authChannels[i],
+ })
+ }
+ }
+ return subscriptions, nil
}
// Subscribe sends a websocket message to receive data from the channel
-func (b *BTCMarkets) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
- unauthChannels := []string{tick, tradeEndPoint, wsOB}
- authChannels := []string{fundChange, heartbeat, orderChange}
- switch {
- case common.StringDataCompare(unauthChannels, channelToSubscribe.Channel):
- req := WsSubscribe{
- MarketIDs: []string{b.FormatExchangeCurrency(channelToSubscribe.Currency, asset.Spot).String()},
- Channels: []string{channelToSubscribe.Channel},
- MessageType: subscribe,
- }
- err := b.WebsocketConn.SendJSONMessage(req)
- if err != nil {
- return err
- }
- case common.StringDataCompare(authChannels, channelToSubscribe.Channel):
- message, ok := channelToSubscribe.Params["AuthSub"].(WsAuthSubscribe)
- if !ok {
- return errors.New("invalid params data")
- }
- tempAuthData := b.generateAuthSubscriptions()
- message.Channels = append(message.Channels, channelToSubscribe.Channel, heartbeat)
- message.Key = tempAuthData.Key
- message.Signature = tempAuthData.Signature
- message.Timestamp = tempAuthData.Timestamp
- err := b.WebsocketConn.SendJSONMessage(message)
- if err != nil {
- return err
+func (b *BTCMarkets) Subscribe(channelsToSubscribe []stream.ChannelSubscription) error {
+ var authChannels = []string{fundChange, heartbeat, orderChange}
+
+ var payload WsSubscribe
+ payload.MessageType = subscribe
+
+ for i := range channelsToSubscribe {
+ payload.Channels = append(payload.Channels,
+ channelsToSubscribe[i].Channel)
+
+ if channelsToSubscribe[i].Currency.String() != "" {
+ if !common.StringDataCompare(payload.MarketIDs,
+ channelsToSubscribe[i].Currency.String()) {
+ payload.MarketIDs = append(payload.MarketIDs,
+ channelsToSubscribe[i].Currency.String())
+ }
}
}
+
+ for i := range authChannels {
+ if !common.StringDataCompare(payload.Channels, authChannels[i]) {
+ continue
+ }
+ signTime := strconv.FormatInt(time.Now().UTC().UnixNano()/1000000, 10)
+ strToSign := "/users/self/subscribe" + "\n" + signTime
+ tempSign := crypto.GetHMAC(crypto.HashSHA512,
+ []byte(strToSign),
+ []byte(b.API.Credentials.Secret))
+ sign := crypto.Base64Encode(tempSign)
+ payload.Key = b.API.Credentials.Key
+ payload.Signature = sign
+ payload.Timestamp = signTime
+ break
+ }
+
+ err := b.Websocket.Conn.SendJSONMessage(payload)
+ if err != nil {
+ return err
+ }
+ b.Websocket.AddSuccessfulSubscriptions(channelsToSubscribe...)
return nil
}
-
-// Login logs in allowing private ws events
-func (b *BTCMarkets) generateAuthSubscriptions() WsAuthSubscribe {
- var authSubInfo WsAuthSubscribe
- signTime := strconv.FormatInt(time.Now().UTC().UnixNano()/1000000, 10)
- strToSign := "/users/self/subscribe" + "\n" + signTime
- tempSign := crypto.GetHMAC(crypto.HashSHA512,
- []byte(strToSign),
- []byte(b.API.Credentials.Secret))
- sign := crypto.Base64Encode(tempSign)
- authSubInfo.Key = b.API.Credentials.Key
- authSubInfo.Signature = sign
- authSubInfo.Timestamp = signTime
- return authSubInfo
-}
-
-// createChannels creates channels that need to be
-func (b *BTCMarkets) createChannels() {
- tempChannels := []string{orderChange, fundChange}
- var channels []wshandler.WebsocketChannelSubscription
- pairArray := b.GetEnabledPairs(asset.Spot)
- for y := range tempChannels {
- for x := range pairArray {
- var authSub WsAuthSubscribe
- var channel wshandler.WebsocketChannelSubscription
- channel.Params = make(map[string]interface{})
- channel.Channel = tempChannels[y]
- authSub.MarketIDs = append(authSub.MarketIDs, b.FormatExchangeCurrency(pairArray[x], asset.Spot).String())
- authSub.MessageType = subscribe
- channel.Params["AuthSub"] = authSub
- channels = append(channels, channel)
- }
- }
- b.Websocket.SubscribeToChannels(channels)
-}
diff --git a/exchanges/btcmarkets/btcmarkets_wrapper.go b/exchanges/btcmarkets/btcmarkets_wrapper.go
index 20abdf82..d37372a6 100644
--- a/exchanges/btcmarkets/btcmarkets_wrapper.go
+++ b/exchanges/btcmarkets/btcmarkets_wrapper.go
@@ -19,8 +19,8 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -59,19 +59,11 @@ func (b *BTCMarkets) SetDefaults() {
b.API.Endpoints.URLDefault = btcMarketsAPIURL
b.API.Endpoints.URL = b.API.Endpoints.URLDefault
- b.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- },
- UseGlobalFormat: true,
- RequestFormat: ¤cy.PairFormat{
- Delimiter: "-",
- Uppercase: true,
- },
- ConfigFormat: ¤cy.PairFormat{
- Delimiter: "-",
- Uppercase: true,
- },
+ requestFmt := ¤cy.PairFormat{Delimiter: currency.DashDelimiter, Uppercase: true}
+ configFmt := ¤cy.PairFormat{Delimiter: currency.DashDelimiter, Uppercase: true}
+ err := b.SetGlobalPairsManager(requestFmt, configFmt, asset.Spot)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
}
b.Features = exchange.Features{
@@ -131,7 +123,7 @@ func (b *BTCMarkets) SetDefaults() {
request.WithLimiter(SetRateLimit()))
b.API.Endpoints.WebsocketURL = btcMarketsWSURL
- b.Websocket = wshandler.New()
+ b.Websocket = stream.New()
b.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
b.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
b.WebsocketOrderbookBufferLimit = exchange.DefaultWebsocketOrderbookBufferLimit
@@ -149,41 +141,30 @@ func (b *BTCMarkets) Setup(exch *config.ExchangeConfig) error {
return err
}
- err = b.Websocket.Setup(
- &wshandler.WebsocketSetup{
- Enabled: exch.Features.Enabled.Websocket,
- Verbose: exch.Verbose,
- AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
- WebsocketTimeout: exch.WebsocketTrafficTimeout,
- DefaultURL: btcMarketsWSURL,
- ExchangeName: exch.Name,
- RunningURL: exch.API.Endpoints.WebsocketURL,
- Connector: b.WsConnect,
- Subscriber: b.Subscribe,
- Features: &b.Features.Supports.WebsocketCapabilities,
- })
+ err = b.Websocket.Setup(&stream.WebsocketSetup{
+ Enabled: exch.Features.Enabled.Websocket,
+ Verbose: exch.Verbose,
+ AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
+ WebsocketTimeout: exch.WebsocketTrafficTimeout,
+ DefaultURL: btcMarketsWSURL,
+ ExchangeName: exch.Name,
+ RunningURL: exch.API.Endpoints.WebsocketURL,
+ Connector: b.WsConnect,
+ Subscriber: b.Subscribe,
+ GenerateSubscriptions: b.generateDefaultSubscriptions,
+ Features: &b.Features.Supports.WebsocketCapabilities,
+ OrderbookBufferLimit: exch.WebsocketOrderbookBufferLimit,
+ BufferEnabled: true,
+ SortBuffer: true,
+ })
if err != nil {
return err
}
- b.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: b.Name,
- URL: b.Websocket.GetWebsocketURL(),
- ProxyURL: b.Websocket.GetProxyAddress(),
- Verbose: b.Verbose,
+ return b.Websocket.SetupNewConnection(stream.ConnectionSetup{
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
- }
-
- b.Websocket.Orderbook.Setup(
- exch.WebsocketOrderbookBufferLimit,
- true,
- true,
- false,
- false,
- exch.Name)
-
- return nil
+ })
}
// Start starts the BTC Markets go routine
@@ -205,10 +186,34 @@ func (b *BTCMarkets) Run() {
btcMarketsWSURL)
b.PrintEnabledPairs()
}
+
forceUpdate := false
- delim := b.GetPairFormat(asset.Spot, false).Delimiter
- if !common.StringDataContains(b.GetEnabledPairs(asset.Spot).Strings(), delim) ||
- !common.StringDataContains(b.GetAvailablePairs(asset.Spot).Strings(), delim) {
+ pairs, err := b.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s Failed to update enabled currencies Err:%s\n",
+ b.Name,
+ err)
+ return
+ }
+ format, err := b.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s Failed to update enabled currencies.\n",
+ b.Name)
+ return
+ }
+
+ avail, err := b.GetAvailablePairs(asset.Spot)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s Failed to update enabled currencies.\n",
+ b.Name)
+ return
+ }
+
+ if !common.StringDataContains(pairs.Strings(), format.Delimiter) ||
+ !common.StringDataContains(avail.Strings(), format.Delimiter) {
log.Warnln(log.ExchangeSys, "Available pairs for BTC Markets reset due to config upgrade, please enable the pairs you would like again.")
forceUpdate = true
}
@@ -216,10 +221,10 @@ func (b *BTCMarkets) Run() {
enabledPairs := currency.Pairs{currency.Pair{
Base: currency.BTC.Lower(),
Quote: currency.AUD.Lower(),
- Delimiter: delim,
+ Delimiter: format.Delimiter,
},
}
- err := b.UpdatePairs(enabledPairs, asset.Spot, true, true)
+ err = b.UpdatePairs(enabledPairs, asset.Spot, true, true)
if err != nil {
log.Errorf(log.ExchangeSys,
"%s Failed to update enabled currencies.\n",
@@ -231,7 +236,7 @@ func (b *BTCMarkets) Run() {
return
}
- err := b.UpdateTradablePairs(forceUpdate)
+ err = b.UpdateTradablePairs(forceUpdate)
if err != nil {
log.Errorf(log.ExchangeSys,
"%s failed to update tradable pairs. Err: %s",
@@ -264,28 +269,49 @@ func (b *BTCMarkets) UpdateTradablePairs(forceUpdate bool) error {
if err != nil {
return err
}
+ p, err := currency.NewPairsFromStrings(pairs)
+ if err != nil {
+ return err
+ }
- return b.UpdatePairs(currency.NewPairsFromStrings(pairs), asset.Spot, false, forceUpdate)
+ return b.UpdatePairs(p, asset.Spot, false, forceUpdate)
}
// UpdateTicker updates and returns the ticker for a currency pair
func (b *BTCMarkets) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
- allPairs := b.GetEnabledPairs(assetType)
- tickers, err := b.GetTickers(allPairs.Slice())
+ allPairs, err := b.GetEnabledPairs(assetType)
if err != nil {
return nil, err
}
+
+ tickers, err := b.GetTickers(allPairs)
+ if err != nil {
+ return nil, err
+ }
+
+ if len(allPairs) != len(tickers) {
+ return nil, errors.New("enabled pairs differ from returned tickers")
+ }
+
for x := range tickers {
- var resp ticker.Price
- resp.Pair = currency.NewPairFromString(tickers[x].MarketID)
- resp.Last = tickers[x].LastPrice
- resp.High = tickers[x].High24h
- resp.Low = tickers[x].Low24h
- resp.Bid = tickers[x].BestBID
- resp.Ask = tickers[x].BestAsk
- resp.Volume = tickers[x].Volume
- resp.LastUpdated = time.Now()
- err = ticker.ProcessTicker(b.Name, &resp, assetType)
+ var newP currency.Pair
+ newP, err = currency.NewPairFromString(tickers[x].MarketID)
+ if err != nil {
+ return nil, err
+ }
+
+ err = ticker.ProcessTicker(&ticker.Price{
+ Pair: newP,
+ Last: tickers[x].LastPrice,
+ High: tickers[x].High24h,
+ Low: tickers[x].Low24h,
+ Bid: tickers[x].BestBID,
+ Ask: tickers[x].BestAsk,
+ Volume: tickers[x].Volume,
+ LastUpdated: time.Now(),
+ ExchangeName: b.Name,
+ AssetType: assetType,
+ })
if err != nil {
return nil, err
}
@@ -313,11 +339,17 @@ func (b *BTCMarkets) FetchOrderbook(p currency.Pair, assetType asset.Item) (*ord
// UpdateOrderbook updates and returns the orderbook for a currency pair
func (b *BTCMarkets) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
- orderBook := new(orderbook.Base)
- tempResp, err := b.GetOrderbook(b.FormatExchangeCurrency(p, assetType).String(), 2)
+ fpair, err := b.FormatExchangeCurrency(p, assetType)
if err != nil {
- return orderBook, err
+ return nil, err
}
+
+ tempResp, err := b.GetOrderbook(fpair.String(), 2)
+ if err != nil {
+ return nil, err
+ }
+
+ orderBook := new(orderbook.Base)
for x := range tempResp.Bids {
orderBook.Bids = append(orderBook.Bids, orderbook.Item{
Amount: tempResp.Bids[x].Volume,
@@ -401,7 +433,12 @@ func (b *BTCMarkets) SubmitOrder(s *order.Submit) (order.SubmitResponse, error)
s.Side = order.Bid
}
- tempResp, err := b.NewOrder(b.FormatExchangeCurrency(s.Pair, asset.Spot).String(),
+ fpair, err := b.FormatExchangeCurrency(s.Pair, asset.Spot)
+ if err != nil {
+ return resp, err
+ }
+
+ tempResp, err := b.NewOrder(fpair.String(),
s.Price,
s.Amount,
s.Type.String(),
@@ -468,9 +505,15 @@ func (b *BTCMarkets) GetOrderInfo(orderID string) (order.Detail, error) {
if err != nil {
return resp, err
}
+
+ p, err := currency.NewPairFromString(o.MarketID)
+ if err != nil {
+ return order.Detail{}, err
+ }
+
resp.Exchange = b.Name
resp.ID = orderID
- resp.Pair = currency.NewPairFromString(o.MarketID)
+ resp.Pair = p
resp.Price = o.Price
resp.Date = o.CreationTime
resp.ExecutedAmount = o.Amount - o.OpenAmount
@@ -569,11 +612,6 @@ func (b *BTCMarkets) WithdrawFiatFundsToInternationalBank(withdrawRequest *withd
return nil, common.ErrFunctionNotSupported
}
-// GetWebsocket returns a pointer to the exchange websocket
-func (b *BTCMarkets) GetWebsocket() (*wshandler.Websocket, error) {
- return b.Websocket, nil
-}
-
// GetFeeByType returns an estimate of fee based on type of transaction
func (b *BTCMarkets) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if !b.AllowAuthenticatedRequest() && // Todo check connection status
@@ -586,7 +624,10 @@ func (b *BTCMarkets) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, err
// GetActiveOrders retrieves any orders that are active/open
func (b *BTCMarkets) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
if len(req.Pairs) == 0 {
- allPairs := b.GetEnabledPairs(asset.Spot)
+ allPairs, err := b.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return nil, err
+ }
for a := range allPairs {
req.Pairs = append(req.Pairs,
allPairs[a])
@@ -595,7 +636,11 @@ func (b *BTCMarkets) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detai
var resp []order.Detail
for x := range req.Pairs {
- tempData, err := b.GetOrders(b.FormatExchangeCurrency(req.Pairs[x], asset.Spot).String(), -1, -1, -1, true)
+ fpair, err := b.FormatExchangeCurrency(req.Pairs[x], asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+ tempData, err := b.GetOrders(fpair.String(), -1, -1, -1, true)
if err != nil {
return resp, err
}
@@ -666,7 +711,12 @@ func (b *BTCMarkets) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detai
}
}
for y := range req.Pairs {
- orders, err := b.GetOrders(b.FormatExchangeCurrency(req.Pairs[y], asset.Spot).String(), -1, -1, -1, false)
+ fpair, err := b.FormatExchangeCurrency(req.Pairs[y], asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+
+ orders, err := b.GetOrders(fpair.String(), -1, -1, -1, false)
if err != nil {
return resp, err
}
@@ -697,8 +747,14 @@ func (b *BTCMarkets) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detai
case orderAccepted:
continue
}
+
+ p, err := currency.NewPairFromString(tempData.Orders[c].MarketID)
+ if err != nil {
+ return nil, err
+ }
+
tempResp.Exchange = b.Name
- tempResp.Pair = currency.NewPairFromString(tempData.Orders[c].MarketID)
+ tempResp.Pair = p
tempResp.Side = order.Bid
if tempData.Orders[c].Side == ask {
tempResp.Side = order.Ask
@@ -713,28 +769,6 @@ func (b *BTCMarkets) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detai
return resp, nil
}
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func (b *BTCMarkets) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- return common.ErrFunctionNotSupported
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func (b *BTCMarkets) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- return common.ErrFunctionNotSupported
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func (b *BTCMarkets) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return nil, common.ErrFunctionNotSupported
-}
-
-// AuthenticateWebsocket sends an authentication message to the websocket
-func (b *BTCMarkets) AuthenticateWebsocket() error {
- return common.ErrFunctionNotSupported
-}
-
// ValidateCredentials validates current credentials used for wrapper
// functionality
func (b *BTCMarkets) ValidateCredentials() error {
@@ -776,7 +810,12 @@ func (b *BTCMarkets) GetHistoricCandles(pair currency.Pair, a asset.Item, start,
return kline.Item{}, errors.New(kline.ErrRequestExceedsExchangeLimits)
}
- candles, err := b.GetMarketCandles(b.FormatExchangeCurrency(pair, a).String(),
+ formattedPair, err := b.FormatExchangeCurrency(pair, a)
+ if err != nil {
+ return kline.Item{}, err
+ }
+
+ candles, err := b.GetMarketCandles(formattedPair.String(),
b.FormatExchangeKlineInterval(interval),
start,
end,
@@ -789,7 +828,7 @@ func (b *BTCMarkets) GetHistoricCandles(pair currency.Pair, a asset.Item, start,
}
ret := kline.Item{
Exchange: b.Name,
- Pair: b.FormatExchangeCurrency(pair, a),
+ Pair: formattedPair,
Asset: asset.Spot,
Interval: interval,
}
diff --git a/exchanges/btse/btse.go b/exchanges/btse/btse.go
index 24914e4c..5c93d016 100644
--- a/exchanges/btse/btse.go
+++ b/exchanges/btse/btse.go
@@ -15,19 +15,18 @@ import (
"github.com/thrasher-corp/gocryptotrader/currency"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
)
// BTSE is the overarching type across this package
type BTSE struct {
exchange.Base
- WebsocketConn *wshandler.WebsocketConnection
}
const (
- btseAPIURL = "https://api.btse.com"
- btseAPIPath = "/spot/v2/"
+ btseAPIURL = "https://api.btse.com"
+ btseSPOTAPIPath = "/spot/v2/"
+ btseFuturesAPIPath = "/futures/api/v2.1/"
// Public endpoints
btseMarketOverview = "market_summary"
@@ -50,34 +49,40 @@ const (
// GetMarketsSummary stores market summary data
func (b *BTSE) GetMarketsSummary() (*HighLevelMarketData, error) {
var m HighLevelMarketData
- return &m, b.SendHTTPRequest(http.MethodGet, btseMarketOverview, &m)
+ return &m, b.SendHTTPRequest(http.MethodGet, btseMarketOverview, &m, true)
}
-// GetMarkets returns a list of markets available on BTSE
-func (b *BTSE) GetMarkets() ([]Market, error) {
- var m []Market
- return m, b.SendHTTPRequest(http.MethodGet, btseMarkets, &m)
+// GetSpotMarkets returns a list of spot markets available on BTSE
+func (b *BTSE) GetSpotMarkets() ([]SpotMarket, error) {
+ var m []SpotMarket
+ return m, b.SendHTTPRequest(http.MethodGet, btseMarkets, &m, true)
+}
+
+// GetFuturesMarkets returns a list of futures markets available on BTSE
+func (b *BTSE) GetFuturesMarkets() ([]FuturesMarket, error) {
+ var m []FuturesMarket
+ return m, b.SendHTTPRequest(http.MethodGet, btseMarketOverview, &m, false)
}
// FetchOrderBook gets orderbook data for a given pair
func (b *BTSE) FetchOrderBook(symbol string) (*Orderbook, error) {
var o Orderbook
endpoint := fmt.Sprintf("%s/%s", btseOrderbook, symbol)
- return &o, b.SendHTTPRequest(http.MethodGet, endpoint, &o)
+ return &o, b.SendHTTPRequest(http.MethodGet, endpoint, &o, true)
}
// GetTrades returns a list of trades for the specified symbol
func (b *BTSE) GetTrades(symbol string) ([]Trade, error) {
var t []Trade
endpoint := fmt.Sprintf("%s/%s", btseTrades, symbol)
- return t, b.SendHTTPRequest(http.MethodGet, endpoint, &t)
+ return t, b.SendHTTPRequest(http.MethodGet, endpoint, &t, true)
}
// GetTicker returns the ticker for a specified symbol
func (b *BTSE) GetTicker(symbol string) (*Ticker, error) {
var t Ticker
endpoint := fmt.Sprintf("%s/%s", btseTicker, symbol)
- err := b.SendHTTPRequest(http.MethodGet, endpoint, &t)
+ err := b.SendHTTPRequest(http.MethodGet, endpoint, &t, true)
if err != nil {
return nil, err
}
@@ -88,19 +93,19 @@ func (b *BTSE) GetTicker(symbol string) (*Ticker, error) {
func (b *BTSE) GetMarketStatistics(symbol string) (*MarketStatistics, error) {
var m MarketStatistics
endpoint := fmt.Sprintf("%s/%s", btseStats, symbol)
- return &m, b.SendHTTPRequest(http.MethodGet, endpoint, &m)
+ return &m, b.SendHTTPRequest(http.MethodGet, endpoint, &m, true)
}
// GetServerTime returns the exchanges server time
func (b *BTSE) GetServerTime() (*ServerTime, error) {
var s ServerTime
- return &s, b.SendHTTPRequest(http.MethodGet, btseTime, &s)
+ return &s, b.SendHTTPRequest(http.MethodGet, btseTime, &s, true)
}
// GetAccountBalance returns the users account balance
func (b *BTSE) GetAccountBalance() ([]CurrencyBalance, error) {
var a []CurrencyBalance
- return a, b.SendAuthenticatedHTTPRequest(http.MethodGet, btseAccount, nil, &a)
+ return a, b.SendAuthenticatedHTTPRequest(http.MethodGet, btseAccount, nil, &a, true)
}
// CreateOrder creates an order
@@ -129,7 +134,7 @@ func (b *BTSE) CreateOrder(amount, price float64, side, orderType, symbol, timeI
}
var r orderResp
- return &r.ID, b.SendAuthenticatedHTTPRequest(http.MethodPost, btseOrder, req, &r)
+ return &r.ID, b.SendAuthenticatedHTTPRequest(http.MethodPost, btseOrder, req, &r, true)
}
// GetOrders returns all pending orders
@@ -139,7 +144,7 @@ func (b *BTSE) GetOrders(symbol string) ([]OpenOrder, error) {
req["symbol"] = symbol
}
var o []OpenOrder
- return o, b.SendAuthenticatedHTTPRequest(http.MethodGet, btsePendingOrders, req, &o)
+ return o, b.SendAuthenticatedHTTPRequest(http.MethodGet, btsePendingOrders, req, &o, true)
}
// CancelExistingOrder cancels an order
@@ -148,7 +153,7 @@ func (b *BTSE) CancelExistingOrder(orderID, symbol string) (*CancelOrder, error)
req := make(map[string]interface{})
req["order_id"] = orderID
req["symbol"] = symbol
- return &c, b.SendAuthenticatedHTTPRequest(http.MethodPost, btseDeleteOrder, req, &c)
+ return &c, b.SendAuthenticatedHTTPRequest(http.MethodPost, btseDeleteOrder, req, &c, true)
}
// GetFills gets all filled orders
@@ -184,14 +189,18 @@ func (b *BTSE) GetFills(orderID, symbol, before, after, limit, username string)
}
var o []FilledOrder
- return o, b.SendAuthenticatedHTTPRequest(http.MethodPost, btseFills, req, &o)
+ return o, b.SendAuthenticatedHTTPRequest(http.MethodPost, btseFills, req, &o, true)
}
// SendHTTPRequest sends an HTTP request to the desired endpoint
-func (b *BTSE) SendHTTPRequest(method, endpoint string, result interface{}) error {
+func (b *BTSE) SendHTTPRequest(method, endpoint string, result interface{}, spotEndpoint bool) error {
+ p := btseSPOTAPIPath
+ if !spotEndpoint {
+ p = btseFuturesAPIPath
+ }
return b.SendPayload(context.Background(), &request.Item{
Method: method,
- Path: b.API.Endpoints.URL + btseAPIPath + endpoint,
+ Path: b.API.Endpoints.URL + p + endpoint,
Result: result,
Verbose: b.Verbose,
HTTPDebugging: b.HTTPDebugging,
@@ -200,12 +209,18 @@ func (b *BTSE) SendHTTPRequest(method, endpoint string, result interface{}) erro
}
// SendAuthenticatedHTTPRequest sends an authenticated HTTP request to the desired endpoint
-func (b *BTSE) SendAuthenticatedHTTPRequest(method, endpoint string, req map[string]interface{}, result interface{}) error {
+func (b *BTSE) SendAuthenticatedHTTPRequest(method, endpoint string, req map[string]interface{}, result interface{}, spotEndpoint bool) error {
if !b.AllowAuthenticatedRequest() {
return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet,
b.Name)
}
- path := btseAPIPath + endpoint
+
+ p := btseSPOTAPIPath
+ if !spotEndpoint {
+ p = btseFuturesAPIPath
+ }
+
+ path := p + endpoint
headers := make(map[string]string)
headers["btse-api"] = b.API.Credentials.Key
nonce := strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond), 10)
diff --git a/exchanges/btse/btse_test.go b/exchanges/btse/btse_test.go
index ab190711..6582fd38 100644
--- a/exchanges/btse/btse_test.go
+++ b/exchanges/btse/btse_test.go
@@ -39,13 +39,11 @@ func TestMain(m *testing.M) {
btseConfig.API.AuthenticatedSupport = true
btseConfig.API.Credentials.Key = apiKey
btseConfig.API.Credentials.Secret = apiSecret
-
+ b.Websocket = sharedtestvalues.NewTestWebsocket()
err = b.Setup(btseConfig)
if err != nil {
log.Fatal(err)
}
- b.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- b.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
os.Exit(m.Run())
}
@@ -61,9 +59,17 @@ func TestGetMarketsSummary(t *testing.T) {
}
}
-func TestGetMarkets(t *testing.T) {
+func TestGetSpotMarkets(t *testing.T) {
t.Parallel()
- _, err := b.GetMarkets()
+ _, err := b.GetSpotMarkets()
+ if err != nil {
+ t.Error(err)
+ }
+}
+
+func TestGetFuturesMarkets(t *testing.T) {
+ t.Parallel()
+ _, err := b.GetFuturesMarkets()
if err != nil {
t.Error(err)
}
@@ -411,3 +417,16 @@ func TestStatusToStandardStatus(t *testing.T) {
}
}
}
+
+func TestFetchTradablePairs(t *testing.T) {
+ assets := b.GetAssetTypes()
+ for i := range assets {
+ data, err := b.FetchTradablePairs(assets[i])
+ if err != nil {
+ t.Fatal(err)
+ }
+ if len(data) == 0 {
+ t.Fatal("data cannot be zero")
+ }
+ }
+}
diff --git a/exchanges/btse/btse_types.go b/exchanges/btse/btse_types.go
index e6d9b935..133fcc4b 100644
--- a/exchanges/btse/btse_types.go
+++ b/exchanges/btse/btse_types.go
@@ -21,8 +21,8 @@ type OverviewData struct {
// HighLevelMarketData stores market overview data
type HighLevelMarketData map[string]OverviewData
-// Market stores market data
-type Market struct {
+// SpotMarket stores market data
+type SpotMarket struct {
Symbol string `json:"symbol"`
ID string `json:"id"`
BaseCurrency string `json:"base_currency"`
@@ -35,6 +35,41 @@ type Market struct {
Status string `json:"status"`
}
+// FuturesMarket stores market data
+type FuturesMarket struct {
+ Symbol string `json:"symbol"`
+ Last float64 `json:"last"`
+ LowestAsk float64 `json:"lowestAsk"`
+ HighestBid float64 `json:"highestBid"`
+ OpenInterest float64 `json:"openInterest"`
+ OpenInterestUSD float64 `json:"openInterestUSD"`
+ PercentageChange float64 `json:"percentageChange"`
+ Volume float64 `json:"volume"`
+ High24Hr float64 `json:"high24Hr"`
+ Low24Hr float64 `json:"low24Hr"`
+ Base string `json:"base"`
+ Quote string `json:"quote"`
+ ContractStart int64 `json:"contractStart"`
+ ContractEnd int64 `json:"contractEnd"`
+ Active bool `json:"active"`
+ TimeBasedContract bool `json:"timeBasedContract"`
+ OpenTime int64 `json:"openTime"`
+ CloseTime int64 `json:"closeTime"`
+ StartMatching int64 `json:"startMatching"`
+ InactiveTime int64 `json:"inactiveTime"`
+ FundingRate float64 `json:"fundingRate"`
+ ContractSize float64 `json:"contractSize"`
+ MaxPosition int64 `json:"maxPosition"`
+ MinValidPrice float64 `json:"minValidPrice"`
+ MinPriceIncrement float64 `json:"minPriceIncrement"`
+ MinOrderSize int32 `json:"minOrderSize"`
+ MaxOrderSize int32 `json:"maxOrderSize"`
+ MinRiskLimit int32 `json:"minRiskLimit"`
+ MaxRiskLimit int32 `json:"maxRiskLimit"`
+ MinSizeIncrement float64 `json:"minSizeIncrement"`
+ AvailableSettlement []string `json:"availableSettlement"`
+}
+
// Trade stores trade data
type Trade struct {
SerialID string `json:"serial_id"`
diff --git a/exchanges/btse/btse_websocket.go b/exchanges/btse/btse_websocket.go
index 5402dd79..743b70e8 100644
--- a/exchanges/btse/btse_websocket.go
+++ b/exchanges/btse/btse_websocket.go
@@ -16,25 +16,25 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
)
const (
btseWebsocket = "wss://ws.btse.com/spotWS"
- btseWebsocketTimer = 57 * time.Second
+ btseWebsocketTimer = time.Second * 57
)
// WsConnect connects the websocket client
func (b *BTSE) WsConnect() error {
if !b.Websocket.IsEnabled() || !b.IsEnabled() {
- return errors.New(wshandler.WebsocketNotEnabled)
+ return errors.New(stream.WebsocketNotEnabled)
}
var dialer websocket.Dialer
- err := b.WebsocketConn.Dial(&dialer, http.Header{})
+ err := b.Websocket.Conn.Dial(&dialer, http.Header{})
if err != nil {
return err
}
- b.WebsocketConn.SetupPingHandler(wshandler.WebsocketPingHandler{
+ b.Websocket.Conn.SetupPingHandler(stream.PingHandler{
MessageType: websocket.PingMessage,
Delay: btseWebsocketTimer,
})
@@ -48,17 +48,19 @@ func (b *BTSE) WsConnect() error {
}
}
- b.GenerateDefaultSubscriptions()
- return nil
+ subs, err := b.GenerateDefaultSubscriptions()
+ if err != nil {
+ return err
+ }
+ return b.Websocket.SubscribeToChannels(subs)
}
// WsAuthenticate Send an authentication message to receive auth data
func (b *BTSE) WsAuthenticate() error {
nonce := strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond), 10)
path := "/spotWS" + nonce
- hmac := crypto.GetHMAC(
- crypto.HashSHA512_384,
- []byte((path + nonce)),
+ hmac := crypto.GetHMAC(crypto.HashSHA512_384,
+ []byte((path)),
[]byte(b.API.Credentials.Secret),
)
sign := crypto.HexEncodeToString(hmac)
@@ -66,7 +68,7 @@ func (b *BTSE) WsAuthenticate() error {
Operation: "authKeyExpires",
Arguments: []string{b.API.Credentials.Key, nonce, sign},
}
- return b.WebsocketConn.SendJSONMessage(req)
+ return b.Websocket.Conn.SendJSONMessage(req)
}
func stringToOrderStatus(status string) (order.Status, error) {
@@ -93,27 +95,16 @@ func stringToOrderStatus(status string) (order.Status, error) {
// wsReadData receives and passes on websocket messages for processing
func (b *BTSE) wsReadData() {
b.Websocket.Wg.Add(1)
-
- defer func() {
- b.Websocket.Wg.Done()
- }()
+ defer b.Websocket.Wg.Done()
for {
- select {
- case <-b.Websocket.ShutdownC:
+ resp := b.Websocket.Conn.ReadMessage()
+ if resp.Raw == nil {
return
-
- default:
- resp, err := b.WebsocketConn.ReadMessage()
- if err != nil {
- b.Websocket.ReadMessageErrors <- err
- return
- }
- b.Websocket.TrafficAlert <- struct{}{}
- err = b.wsHandleData(resp.Raw)
- if err != nil {
- b.Websocket.DataHandler <- err
- }
+ }
+ err := b.wsHandleData(resp.Raw)
+ if err != nil {
+ b.Websocket.DataHandler <- err
}
}
}
@@ -123,6 +114,13 @@ func (b *BTSE) wsHandleData(respRaw []byte) error {
var result Result
err := json.Unmarshal(respRaw, &result)
if err != nil {
+ if strings.Contains(string(respRaw), "UNLOGIN_USER connect success") ||
+ strings.Contains(string(respRaw), "authenticated successfully") {
+ return nil
+ } else if strings.Contains(string(respRaw), "AUTHENTICATE ERROR") {
+ b.Websocket.SetCanUseAuthenticatedEndpoints(false)
+ return errors.New("authentication failure")
+ }
return err
}
switch {
@@ -160,12 +158,19 @@ func (b *BTSE) wsHandleData(respRaw []byte) error {
Err: err,
}
}
- p := currency.NewPairFromString(notification.Data[i].Symbol)
+
+ var p currency.Pair
+ p, err = currency.NewPairFromString(notification.Data[i].Symbol)
+ if err != nil {
+ return err
+ }
+
var a asset.Item
a, err = b.GetPairAssetType(p)
if err != nil {
return err
}
+
b.Websocket.DataHandler <- &order.Detail{
Price: notification.Data[i].Price,
Amount: notification.Data[i].Size,
@@ -192,13 +197,21 @@ func (b *BTSE) wsHandleData(respRaw []byte) error {
if tradeHistory.Data[x].Gain == -1 {
side = order.Sell
}
- p := currency.NewPairFromString(strings.Replace(tradeHistory.Topic, "tradeHistory:", "", 1))
+
+ var p currency.Pair
+ p, err = currency.NewPairFromString(strings.Replace(tradeHistory.Topic,
+ "tradeHistory:",
+ "",
+ 1))
+ if err != nil {
+ return err
+ }
var a asset.Item
a, err = b.GetPairAssetType(p)
if err != nil {
return err
}
- b.Websocket.DataHandler <- wshandler.TradeData{
+ b.Websocket.DataHandler <- stream.TradeData{
Timestamp: time.Unix(0, tradeHistory.Data[x].TransactionTime*int64(time.Millisecond)),
CurrencyPair: p,
AssetType: a,
@@ -248,7 +261,10 @@ func (b *BTSE) wsHandleData(respRaw []byte) error {
Amount: amount,
})
}
- p := currency.NewPairFromString(t.Topic[strings.Index(t.Topic, ":")+1 : strings.Index(t.Topic, "_")])
+ p, err := currency.NewPairFromString(t.Topic[strings.Index(t.Topic, ":")+1 : strings.Index(t.Topic, "_")])
+ if err != nil {
+ return err
+ }
var a asset.Item
a, err = b.GetPairAssetType(p)
if err != nil {
@@ -261,50 +277,65 @@ func (b *BTSE) wsHandleData(respRaw []byte) error {
if err != nil {
return err
}
- b.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{Pair: newOB.Pair,
- Asset: a,
- Exchange: b.Name}
default:
- b.Websocket.DataHandler <- wshandler.UnhandledMessageWarning{Message: b.Name + wshandler.UnhandledMessage + string(respRaw)}
+ b.Websocket.DataHandler <- stream.UnhandledMessageWarning{Message: b.Name + stream.UnhandledMessage + string(respRaw)}
return nil
}
return nil
}
// GenerateDefaultSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions()
-func (b *BTSE) GenerateDefaultSubscriptions() {
+func (b *BTSE) GenerateDefaultSubscriptions() ([]stream.ChannelSubscription, error) {
var channels = []string{"orderBookApi:%s_0", "tradeHistory:%s"}
- pairs := b.GetEnabledPairs(asset.Spot)
- var subscriptions []wshandler.WebsocketChannelSubscription
+ pairs, err := b.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+ var subscriptions []stream.ChannelSubscription
if b.Websocket.CanUseAuthenticatedEndpoints() {
- subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
Channel: "notificationApi",
})
}
for i := range channels {
for j := range pairs {
- subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
Channel: fmt.Sprintf(channels[i], pairs[j]),
Currency: pairs[j],
+ Asset: asset.Spot,
})
}
}
- b.Websocket.SubscribeToChannels(subscriptions)
+ return subscriptions, nil
}
// Subscribe sends a websocket message to receive data from the channel
-func (b *BTSE) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
+func (b *BTSE) Subscribe(channelsToSubscribe []stream.ChannelSubscription) error {
var sub wsSub
sub.Operation = "subscribe"
- sub.Arguments = []string{channelToSubscribe.Channel}
-
- return b.WebsocketConn.SendJSONMessage(sub)
+ for i := range channelsToSubscribe {
+ sub.Arguments = append(sub.Arguments, channelsToSubscribe[i].Channel)
+ }
+ err := b.Websocket.Conn.SendJSONMessage(sub)
+ if err != nil {
+ return err
+ }
+ b.Websocket.AddSuccessfulSubscriptions(channelsToSubscribe...)
+ return nil
}
// Unsubscribe sends a websocket message to stop receiving data from the channel
-func (b *BTSE) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
+func (b *BTSE) Unsubscribe(channelsToUnsubscribe []stream.ChannelSubscription) error {
var unSub wsSub
unSub.Operation = "unsubscribe"
- unSub.Arguments = []string{channelToSubscribe.Channel}
- return b.WebsocketConn.SendJSONMessage(unSub)
+ for i := range channelsToUnsubscribe {
+ unSub.Arguments = append(unSub.Arguments,
+ channelsToUnsubscribe[i].Channel)
+ }
+ err := b.Websocket.Conn.SendJSONMessage(unSub)
+ if err != nil {
+ return err
+ }
+ b.Websocket.RemoveSuccessfulUnsubscriptions(channelsToUnsubscribe...)
+ return nil
}
diff --git a/exchanges/btse/btse_wrapper.go b/exchanges/btse/btse_wrapper.go
index 9efd9ca3..a9ed0c92 100644
--- a/exchanges/btse/btse_wrapper.go
+++ b/exchanges/btse/btse_wrapper.go
@@ -19,8 +19,8 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -56,11 +56,7 @@ func (b *BTSE) SetDefaults() {
b.API.CredentialsValidator.RequiresKey = true
b.API.CredentialsValidator.RequiresSecret = true
- b.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- },
- UseGlobalFormat: true,
+ fmt1 := currency.PairStore{
RequestFormat: ¤cy.PairFormat{
Uppercase: true,
Delimiter: "-",
@@ -70,6 +66,23 @@ func (b *BTSE) SetDefaults() {
Delimiter: "-",
},
}
+ err := b.StoreAssetPairFormat(asset.Spot, fmt1)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
+ }
+
+ fmt2 := currency.PairStore{
+ RequestFormat: ¤cy.PairFormat{
+ Uppercase: true,
+ },
+ ConfigFormat: ¤cy.PairFormat{
+ Uppercase: true,
+ },
+ }
+ err = b.StoreAssetPairFormat(asset.Futures, fmt2)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
+ }
b.Features = exchange.Features{
Supports: exchange.FeaturesSupported{
@@ -112,7 +125,7 @@ func (b *BTSE) SetDefaults() {
b.API.Endpoints.URLDefault = btseAPIURL
b.API.Endpoints.URL = b.API.Endpoints.URLDefault
- b.Websocket = wshandler.New()
+ b.Websocket = stream.New()
b.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
b.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
b.WebsocketOrderbookBufferLimit = exchange.DefaultWebsocketOrderbookBufferLimit
@@ -130,41 +143,29 @@ func (b *BTSE) Setup(exch *config.ExchangeConfig) error {
return err
}
- err = b.Websocket.Setup(
- &wshandler.WebsocketSetup{
- Enabled: exch.Features.Enabled.Websocket,
- Verbose: exch.Verbose,
- AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
- WebsocketTimeout: exch.WebsocketTrafficTimeout,
- DefaultURL: btseWebsocket,
- ExchangeName: exch.Name,
- RunningURL: exch.API.Endpoints.WebsocketURL,
- Connector: b.WsConnect,
- Subscriber: b.Subscribe,
- UnSubscriber: b.Unsubscribe,
- Features: &b.Features.Supports.WebsocketCapabilities,
- })
+ err = b.Websocket.Setup(&stream.WebsocketSetup{
+ Enabled: exch.Features.Enabled.Websocket,
+ Verbose: exch.Verbose,
+ AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
+ WebsocketTimeout: exch.WebsocketTrafficTimeout,
+ DefaultURL: btseWebsocket,
+ ExchangeName: exch.Name,
+ RunningURL: exch.API.Endpoints.WebsocketURL,
+ Connector: b.WsConnect,
+ Subscriber: b.Subscribe,
+ UnSubscriber: b.Unsubscribe,
+ GenerateSubscriptions: b.GenerateDefaultSubscriptions,
+ Features: &b.Features.Supports.WebsocketCapabilities,
+ OrderbookBufferLimit: exch.WebsocketOrderbookBufferLimit,
+ })
if err != nil {
return err
}
- b.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: b.Name,
- URL: b.Websocket.GetWebsocketURL(),
- ProxyURL: b.Websocket.GetProxyAddress(),
- Verbose: b.Verbose,
+ return b.Websocket.SetupNewConnection(stream.ConnectionSetup{
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
- }
-
- b.Websocket.Orderbook.Setup(
- exch.WebsocketOrderbookBufferLimit,
- false,
- false,
- false,
- false,
- exch.Name)
- return nil
+ })
}
// Start starts the BTSE go routine
@@ -194,61 +195,96 @@ func (b *BTSE) Run() {
}
// FetchTradablePairs returns a list of the exchanges tradable pairs
-func (b *BTSE) FetchTradablePairs(asset asset.Item) ([]string, error) {
- m, err := b.GetMarkets()
- if err != nil {
- return nil, err
+func (b *BTSE) FetchTradablePairs(a asset.Item) ([]string, error) {
+ var currencies []string
+ if a == asset.Spot {
+ m, err := b.GetSpotMarkets()
+ if err != nil {
+ return nil, err
+ }
+
+ for x := range m {
+ if m[x].Status != "active" {
+ continue
+ }
+ currencies = append(currencies, m[x].Symbol)
+ }
+ } else if a == asset.Futures {
+ m, err := b.GetFuturesMarkets()
+ if err != nil {
+ return nil, err
+ }
+
+ for x := range m {
+ if !m[x].Active {
+ continue
+ }
+ currencies = append(currencies, m[x].Symbol)
+ }
}
- var currencies []string
- for x := range m {
- if m[x].Status != "active" {
- continue
- }
- currencies = append(currencies, m[x].Symbol)
- }
return currencies, nil
}
// UpdateTradablePairs updates the exchanges available pairs and stores
// them in the exchanges config
func (b *BTSE) UpdateTradablePairs(forceUpdate bool) error {
- pairs, err := b.FetchTradablePairs(asset.Spot)
- if err != nil {
- return err
- }
+ a := b.GetAssetTypes()
+ for i := range a {
+ pairs, err := b.FetchTradablePairs(a[i])
+ if err != nil {
+ return err
+ }
- return b.UpdatePairs(currency.NewPairsFromStrings(pairs), asset.Spot, false, forceUpdate)
+ p, err := currency.NewPairsFromStrings(pairs)
+ if err != nil {
+ return err
+ }
+
+ err = b.UpdatePairs(p, a[i], false, forceUpdate)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
}
// UpdateTicker updates and returns the ticker for a currency pair
func (b *BTSE) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
- tickerPrice := new(ticker.Price)
-
- t, err := b.GetTicker(b.FormatExchangeCurrency(p,
- assetType).String())
- if err != nil {
- return tickerPrice, err
+ if assetType == asset.Futures {
+ // Futures REST implementation needs to be done before this can be
+ // removed
+ return nil, common.ErrNotYetImplemented
}
- s, err := b.GetMarketStatistics(b.FormatExchangeCurrency(p,
- assetType).String())
+ fpair, err := b.FormatExchangeCurrency(p, assetType)
if err != nil {
- return tickerPrice, err
+ return nil, err
}
- tickerPrice.Pair = p
- tickerPrice.Ask = t.Ask
- tickerPrice.Bid = t.Bid
- tickerPrice.Low = s.Low
- tickerPrice.Last = t.Price
- tickerPrice.Volume = s.Volume
- tickerPrice.High = s.High
- tickerPrice.LastUpdated = s.Time
-
- err = ticker.ProcessTicker(b.Name, tickerPrice, assetType)
+ t, err := b.GetTicker(fpair.String())
if err != nil {
- return tickerPrice, err
+ return nil, err
+ }
+
+ s, err := b.GetMarketStatistics(fpair.String())
+ if err != nil {
+ return nil, err
+ }
+
+ err = ticker.ProcessTicker(&ticker.Price{
+ Pair: p,
+ Ask: t.Ask,
+ Bid: t.Bid,
+ Low: s.Low,
+ Last: t.Price,
+ Volume: s.Volume,
+ High: s.High,
+ LastUpdated: s.Time,
+ ExchangeName: b.Name,
+ AssetType: assetType})
+ if err != nil {
+ return nil, err
}
return ticker.GetTicker(b.Name, p, assetType)
}
@@ -273,11 +309,22 @@ func (b *BTSE) FetchOrderbook(p currency.Pair, assetType asset.Item) (*orderbook
// UpdateOrderbook updates and returns the orderbook for a currency pair
func (b *BTSE) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
- orderBook := new(orderbook.Base)
- a, err := b.FetchOrderBook(b.FormatExchangeCurrency(p, assetType).String())
- if err != nil {
- return orderBook, err
+ if assetType == asset.Futures {
+ // Futures REST implementation needs to be done before this can be
+ // removed
+ return nil, common.ErrNotYetImplemented
}
+
+ fpair, err := b.FormatExchangeCurrency(p, assetType)
+ if err != nil {
+ return nil, err
+ }
+ a, err := b.FetchOrderBook(fpair.String())
+ if err != nil {
+ return nil, err
+ }
+
+ orderBook := new(orderbook.Base)
for x := range a.BuyQuote {
orderBook.Bids = append(orderBook.Bids, orderbook.Item{
Price: a.BuyQuote[x].Price,
@@ -360,11 +407,16 @@ func (b *BTSE) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
return resp, err
}
+ fpair, err := b.FormatExchangeCurrency(s.Pair, s.AssetType)
+ if err != nil {
+ return resp, err
+ }
+
r, err := b.CreateOrder(s.Amount,
s.Price,
s.Side.String(),
s.Type.String(),
- b.FormatExchangeCurrency(s.Pair, asset.Spot).String(),
+ fpair.String(),
goodTillCancel,
s.ClientID)
if err != nil {
@@ -389,9 +441,13 @@ func (b *BTSE) ModifyOrder(action *order.Modify) (string, error) {
// CancelOrder cancels an order by its corresponding ID number
func (b *BTSE) CancelOrder(order *order.Cancel) error {
- r, err := b.CancelExistingOrder(order.ID,
- b.FormatExchangeCurrency(order.Pair,
- asset.Spot).String())
+ fpair, err := b.FormatExchangeCurrency(order.Pair,
+ order.AssetType)
+ if err != nil {
+ return err
+ }
+
+ r, err := b.CancelExistingOrder(order.ID, fpair.String())
if err != nil {
return err
}
@@ -411,19 +467,28 @@ func (b *BTSE) CancelOrder(order *order.Cancel) error {
// If not specified, all orders of all markets will be cancelled
func (b *BTSE) CancelAllOrders(orderCancellation *order.Cancel) (order.CancelAllResponse, error) {
var resp order.CancelAllResponse
- markets, err := b.GetMarkets()
+ markets, err := b.GetSpotMarkets()
+ if err != nil {
+ return resp, err
+ }
+
+ format, err := b.GetPairFormat(orderCancellation.AssetType, false)
if err != nil {
return resp, err
}
resp.Status = make(map[string]string)
for x := range markets {
- strPair := b.FormatExchangeCurrency(orderCancellation.Pair,
- orderCancellation.AssetType).String()
+ fair, err := b.FormatExchangeCurrency(orderCancellation.Pair,
+ orderCancellation.AssetType)
+ if err != nil {
+ return resp, err
+ }
+
checkPair := currency.NewPairWithDelimiter(markets[x].BaseCurrency,
markets[x].QuoteCurrency,
- b.GetPairFormat(asset.Spot, false).Delimiter).String()
- if strPair != "" && strPair != checkPair {
+ format.Delimiter).String()
+ if fair.String() != checkPair {
continue
} else {
orders, err := b.GetOrders(checkPair)
@@ -455,6 +520,11 @@ func (b *BTSE) GetOrderInfo(orderID string) (order.Detail, error) {
return od, errors.New("no orders found")
}
+ format, err := b.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return order.Detail{}, err
+ }
+
for i := range o {
if o[i].ID != orderID {
continue
@@ -465,8 +535,14 @@ func (b *BTSE) GetOrderInfo(orderID string) (order.Detail, error) {
side = order.Sell
}
- od.Pair = currency.NewPairDelimiter(o[i].Symbol,
- b.GetPairFormat(asset.Spot, false).Delimiter)
+ od.Pair, err = currency.NewPairDelimiter(o[i].Symbol,
+ format.Delimiter)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s GetOrderInfo unable to parse currency pair: %s\n",
+ b.Name,
+ err)
+ }
od.Exchange = b.Name
od.Amount = o[i].Amount
od.ID = o[i].ID
@@ -530,11 +606,6 @@ func (b *BTSE) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdraw.Re
return nil, common.ErrFunctionNotSupported
}
-// GetWebsocket returns a pointer to the exchange websocket
-func (b *BTSE) GetWebsocket() (*wshandler.Websocket, error) {
- return b.Websocket, nil
-}
-
// GetActiveOrders retrieves any orders that are active/open
func (b *BTSE) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
resp, err := b.GetOrders("")
@@ -542,6 +613,11 @@ func (b *BTSE) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, err
return nil, err
}
+ format, err := b.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return nil, err
+ }
+
var orders []order.Detail
for i := range resp {
var side = order.Buy
@@ -557,9 +633,17 @@ func (b *BTSE) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, err
err)
}
+ p, err := currency.NewPairDelimiter(resp[i].Symbol,
+ format.Delimiter)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s GetActiveOrders unable to parse currency pair: %s\n",
+ b.Name,
+ err)
+ }
+
openOrder := order.Detail{
- Pair: currency.NewPairDelimiter(resp[i].Symbol,
- b.GetPairFormat(asset.Spot, false).Delimiter),
+ Pair: p,
Exchange: b.Name,
Amount: resp[i].Amount,
ID: resp[i].ID,
@@ -621,30 +705,6 @@ func (b *BTSE) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
return b.GetFee(feeBuilder)
}
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func (b *BTSE) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- b.Websocket.SubscribeToChannels(channels)
- return nil
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func (b *BTSE) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- b.Websocket.RemoveSubscribedChannels(channels)
- return nil
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func (b *BTSE) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return b.Websocket.GetSubscriptions(), nil
-}
-
-// AuthenticateWebsocket sends an authentication message to the websocket
-func (b *BTSE) AuthenticateWebsocket() error {
- return common.ErrFunctionNotSupported
-}
-
// ValidateCredentials validates current credentials used for wrapper
// functionality
func (b *BTSE) ValidateCredentials() error {
diff --git a/exchanges/coinbasepro/coinbasepro.go b/exchanges/coinbasepro/coinbasepro.go
index 63d08cdf..11a6effb 100644
--- a/exchanges/coinbasepro/coinbasepro.go
+++ b/exchanges/coinbasepro/coinbasepro.go
@@ -18,7 +18,6 @@ import (
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
)
@@ -57,7 +56,6 @@ const (
// CoinbasePro is the overarching type across the coinbasepro package
type CoinbasePro struct {
exchange.Base
- WebsocketConn *wshandler.WebsocketConnection
}
// GetProducts returns supported currency pairs on the exchange with specific
diff --git a/exchanges/coinbasepro/coinbasepro_test.go b/exchanges/coinbasepro/coinbasepro_test.go
index 0237027f..d3dd077b 100644
--- a/exchanges/coinbasepro/coinbasepro_test.go
+++ b/exchanges/coinbasepro/coinbasepro_test.go
@@ -17,7 +17,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/portfolio/banking"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -49,12 +49,11 @@ func TestMain(m *testing.M) {
gdxConfig.API.Credentials.ClientID = clientID
gdxConfig.API.AuthenticatedSupport = true
gdxConfig.API.AuthenticatedWebsocketSupport = true
+ c.Websocket = sharedtestvalues.NewTestWebsocket()
err = c.Setup(gdxConfig)
if err != nil {
log.Fatal("CoinbasePro setup error", err)
}
- c.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- c.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
os.Exit(m.Run())
}
@@ -593,26 +592,24 @@ func TestGetDepositAddress(t *testing.T) {
// TestWsAuth dials websocket, sends login request.
func TestWsAuth(t *testing.T) {
if !c.Websocket.IsEnabled() && !c.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
- t.Skip(wshandler.WebsocketNotEnabled)
- }
- c.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: c.Name,
- URL: c.Websocket.GetWebsocketURL(),
- Verbose: c.Verbose,
- ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
- ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
+ t.Skip(stream.WebsocketNotEnabled)
}
var dialer websocket.Dialer
- err := c.WebsocketConn.Dial(&dialer, http.Header{})
+ err := c.Websocket.Conn.Dial(&dialer, http.Header{})
if err != nil {
t.Fatal(err)
}
- c.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- c.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
go c.wsReadData()
- err = c.Subscribe(wshandler.WebsocketChannelSubscription{
- Channel: "user",
- Currency: currency.NewPairFromString(testPair),
+
+ p, err := currency.NewPairFromString(testPair)
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = c.Subscribe([]stream.ChannelSubscription{
+ {
+ Channel: "user",
+ Currency: p,
+ },
})
if err != nil {
t.Error(err)
@@ -947,3 +944,64 @@ func TestParseTime(t *testing.T) {
t.Error("unexpected result")
}
}
+
+func TestCheckInterval(t *testing.T) {
+ interval := time.Minute
+ i, err := checkInterval(interval)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if i != 60 {
+ t.Fatal("incorrect return")
+ }
+ interval = time.Minute * 5
+ i, err = checkInterval(interval)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if i != 300 {
+ t.Fatal("incorrect return")
+ }
+
+ interval = time.Minute * 15
+ i, err = checkInterval(interval)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if i != 900 {
+ t.Fatal("incorrect return")
+ }
+
+ interval = time.Hour
+ i, err = checkInterval(interval)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if i != 3600 {
+ t.Fatal("incorrect return")
+ }
+
+ interval = time.Hour * 6
+ i, err = checkInterval(interval)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if i != 21600 {
+ t.Fatal("incorrect return")
+ }
+
+ interval = time.Hour * 24
+ i, err = checkInterval(interval)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if i != 86400 {
+ t.Fatal("incorrect return")
+ }
+
+ interval = time.Hour * 1337
+ _, err = checkInterval(interval)
+ if err == nil {
+ t.Fatal("error cannot be nil")
+ }
+}
diff --git a/exchanges/coinbasepro/coinbasepro_types.go b/exchanges/coinbasepro/coinbasepro_types.go
index b8cb052f..e02f0556 100644
--- a/exchanges/coinbasepro/coinbasepro_types.go
+++ b/exchanges/coinbasepro/coinbasepro_types.go
@@ -353,7 +353,7 @@ type FillResponse struct {
// WebsocketSubscribe takes in subscription information
type WebsocketSubscribe struct {
Type string `json:"type"`
- ProductID string `json:"product_id,omitempty"`
+ ProductIDs []string `json:"product_ids,omitempty"`
Channels []WsChannels `json:"channels,omitempty"`
Signature string `json:"signature,omitempty"`
Key string `json:"key,omitempty"`
@@ -364,7 +364,7 @@ type WebsocketSubscribe struct {
// WsChannels defines outgoing channels for subscription purposes
type WsChannels struct {
Name string `json:"name"`
- ProductIDs []string `json:"product_ids"`
+ ProductIDs []string `json:"product_ids,omitempty"`
}
// wsOrderReceived holds websocket received values
diff --git a/exchanges/coinbasepro/coinbasepro_websocket.go b/exchanges/coinbasepro/coinbasepro_websocket.go
index c785cf4a..6dad3340 100644
--- a/exchanges/coinbasepro/coinbasepro_websocket.go
+++ b/exchanges/coinbasepro/coinbasepro_websocket.go
@@ -9,6 +9,7 @@ import (
"time"
"github.com/gorilla/websocket"
+ "github.com/thrasher-corp/gocryptotrader/common"
"github.com/thrasher-corp/gocryptotrader/common/convert"
"github.com/thrasher-corp/gocryptotrader/common/crypto"
"github.com/thrasher-corp/gocryptotrader/currency"
@@ -16,9 +17,9 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wsorderbook"
)
const (
@@ -28,18 +29,20 @@ const (
// WsConnect initiates a websocket connection
func (c *CoinbasePro) WsConnect() error {
if !c.Websocket.IsEnabled() || !c.IsEnabled() {
- return errors.New(wshandler.WebsocketNotEnabled)
+ return errors.New(stream.WebsocketNotEnabled)
}
var dialer websocket.Dialer
- err := c.WebsocketConn.Dial(&dialer, http.Header{})
+ err := c.Websocket.Conn.Dial(&dialer, http.Header{})
if err != nil {
return err
}
- c.GenerateDefaultSubscriptions()
+ subs, err := c.GenerateDefaultSubscriptions()
+ if err != nil {
+ return err
+ }
go c.wsReadData()
-
- return nil
+ return c.Websocket.SubscribeToChannels(subs)
}
// wsReadData receives and passes on websocket messages for processing
@@ -51,20 +54,13 @@ func (c *CoinbasePro) wsReadData() {
}()
for {
- select {
- case <-c.Websocket.ShutdownC:
+ resp := c.Websocket.Conn.ReadMessage()
+ if resp.Raw == nil {
return
- default:
- resp, err := c.WebsocketConn.ReadMessage()
- if err != nil {
- c.Websocket.ReadMessageErrors <- err
- return
- }
- c.Websocket.TrafficAlert <- struct{}{}
- err = c.wsHandleData(resp.Raw)
- if err != nil {
- c.Websocket.DataHandler <- err
- }
+ }
+ err := c.wsHandleData(resp.Raw)
+ if err != nil {
+ c.Websocket.DataHandler <- err
}
}
}
@@ -233,7 +229,7 @@ func (c *CoinbasePro) wsHandleData(respRaw []byte) error {
},
}
default:
- c.Websocket.DataHandler <- wshandler.UnhandledMessageWarning{Message: c.Name + wshandler.UnhandledMessage + string(respRaw)}
+ c.Websocket.DataHandler <- stream.UnhandledMessageWarning{Message: c.Name + stream.UnhandledMessage + string(respRaw)}
return nil
}
return nil
@@ -289,23 +285,16 @@ func (c *CoinbasePro) ProcessSnapshot(snapshot *WebsocketOrderbookSnapshot) erro
orderbook.Item{Price: price, Amount: amount})
}
- pair := currency.NewPairFromString(snapshot.ProductID)
- base.AssetType = asset.Spot
- base.Pair = pair
- base.ExchangeName = c.Name
-
- err := c.Websocket.Orderbook.LoadSnapshot(&base)
+ pair, err := currency.NewPairFromString(snapshot.ProductID)
if err != nil {
return err
}
- c.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
- Pair: pair,
- Asset: asset.Spot,
- Exchange: c.Name,
- }
+ base.AssetType = asset.Spot
+ base.Pair = pair
+ base.ExchangeName = c.Name
- return nil
+ return c.Websocket.Orderbook.LoadSnapshot(&base)
}
// ProcessUpdate updates the orderbook local cache
@@ -313,8 +302,14 @@ func (c *CoinbasePro) ProcessUpdate(update WebsocketL2Update) error {
var asks, bids []orderbook.Item
for i := range update.Changes {
- price, _ := strconv.ParseFloat(update.Changes[i][1].(string), 64)
- volume, _ := strconv.ParseFloat(update.Changes[i][2].(string), 64)
+ price, err := strconv.ParseFloat(update.Changes[i][1].(string), 64)
+ if err != nil {
+ return err
+ }
+ volume, err := strconv.ParseFloat(update.Changes[i][2].(string), 64)
+ if err != nil {
+ return err
+ }
if update.Changes[i][0].(string) == order.Buy.Lower() {
bids = append(bids, orderbook.Item{Price: price, Amount: volume})
@@ -327,91 +322,123 @@ func (c *CoinbasePro) ProcessUpdate(update WebsocketL2Update) error {
return errors.New("coinbasepro_websocket.go error - no data in websocket update")
}
- p := currency.NewPairFromString(update.ProductID)
+ p, err := currency.NewPairFromString(update.ProductID)
+ if err != nil {
+ return err
+ }
+
timestamp, err := time.Parse(time.RFC3339, update.Time)
if err != nil {
return err
}
- err = c.Websocket.Orderbook.Update(&wsorderbook.WebsocketOrderbookUpdate{
+ return c.Websocket.Orderbook.Update(&buffer.Update{
Bids: bids,
Asks: asks,
Pair: p,
UpdateTime: timestamp,
Asset: asset.Spot,
})
- if err != nil {
- return err
- }
-
- c.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
- Pair: p,
- Asset: asset.Spot,
- Exchange: c.Name,
- }
-
- return nil
}
// GenerateDefaultSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions()
-func (c *CoinbasePro) GenerateDefaultSubscriptions() {
+func (c *CoinbasePro) GenerateDefaultSubscriptions() ([]stream.ChannelSubscription, error) {
var channels = []string{"heartbeat", "level2", "ticker", "user"}
- enabledCurrencies := c.GetEnabledPairs(asset.Spot)
- var subscriptions []wshandler.WebsocketChannelSubscription
+ enabledCurrencies, err := c.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+ var subscriptions []stream.ChannelSubscription
for i := range channels {
- if (channels[i] == "user" || channels[i] == "full") && !c.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
+ if (channels[i] == "user" || channels[i] == "full") &&
+ !c.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
continue
}
for j := range enabledCurrencies {
- subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
- Channel: channels[i],
- Currency: c.FormatExchangeCurrency(enabledCurrencies[j],
- asset.Spot),
+ fpair, err := c.FormatExchangeCurrency(enabledCurrencies[j],
+ asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
+ Channel: channels[i],
+ Currency: fpair,
+ Asset: asset.Spot,
})
}
}
- c.Websocket.SubscribeToChannels(subscriptions)
+ return subscriptions, nil
}
// Subscribe sends a websocket message to receive data from the channel
-func (c *CoinbasePro) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
+func (c *CoinbasePro) Subscribe(channelsToSubscribe []stream.ChannelSubscription) error {
subscribe := WebsocketSubscribe{
Type: "subscribe",
- Channels: []WsChannels{
- {
- Name: channelToSubscribe.Channel,
- ProductIDs: []string{
- c.FormatExchangeCurrency(channelToSubscribe.Currency,
- asset.Spot).String(),
- },
- },
- },
}
- if channelToSubscribe.Channel == "user" || channelToSubscribe.Channel == "full" {
- n := strconv.FormatInt(time.Now().Unix(), 10)
- message := n + http.MethodGet + "/users/self/verify"
- hmac := crypto.GetHMAC(crypto.HashSHA256, []byte(message),
- []byte(c.API.Credentials.Secret))
- subscribe.Signature = crypto.Base64Encode(hmac)
- subscribe.Key = c.API.Credentials.Key
- subscribe.Passphrase = c.API.Credentials.ClientID
- subscribe.Timestamp = n
+
+subscriptions:
+ for i := range channelsToSubscribe {
+ p := channelsToSubscribe[i].Currency.String()
+ if !common.StringDataCompare(subscribe.ProductIDs, p) && p != "" {
+ subscribe.ProductIDs = append(subscribe.ProductIDs, p)
+ }
+
+ for j := range subscribe.Channels {
+ if subscribe.Channels[j].Name == channelsToSubscribe[i].Channel {
+ continue subscriptions
+ }
+ }
+
+ subscribe.Channels = append(subscribe.Channels, WsChannels{
+ Name: channelsToSubscribe[i].Channel,
+ })
+
+ if channelsToSubscribe[i].Channel == "user" ||
+ channelsToSubscribe[i].Channel == "full" {
+ n := strconv.FormatInt(time.Now().Unix(), 10)
+ message := n + http.MethodGet + "/users/self/verify"
+ hmac := crypto.GetHMAC(crypto.HashSHA256, []byte(message),
+ []byte(c.API.Credentials.Secret))
+ subscribe.Signature = crypto.Base64Encode(hmac)
+ subscribe.Key = c.API.Credentials.Key
+ subscribe.Passphrase = c.API.Credentials.ClientID
+ subscribe.Timestamp = n
+ }
}
- return c.WebsocketConn.SendJSONMessage(subscribe)
+ err := c.Websocket.Conn.SendJSONMessage(subscribe)
+ if err != nil {
+ return err
+ }
+ c.Websocket.AddSuccessfulSubscriptions(channelsToSubscribe...)
+ return nil
}
// Unsubscribe sends a websocket message to stop receiving data from the channel
-func (c *CoinbasePro) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
- subscribe := WebsocketSubscribe{
+func (c *CoinbasePro) Unsubscribe(channelsToUnsubscribe []stream.ChannelSubscription) error {
+ unsubscribe := WebsocketSubscribe{
Type: "unsubscribe",
- Channels: []WsChannels{
- {
- Name: channelToSubscribe.Channel,
- ProductIDs: []string{
- c.FormatExchangeCurrency(channelToSubscribe.Currency,
- asset.Spot).String(),
- },
- },
- },
}
- return c.WebsocketConn.SendJSONMessage(subscribe)
+
+unsubscriptions:
+ for i := range channelsToUnsubscribe {
+ p := channelsToUnsubscribe[i].Currency.String()
+ if !common.StringDataCompare(unsubscribe.ProductIDs, p) && p != "" {
+ unsubscribe.ProductIDs = append(unsubscribe.ProductIDs, p)
+ }
+
+ for j := range unsubscribe.Channels {
+ if unsubscribe.Channels[j].Name == channelsToUnsubscribe[i].Channel {
+ continue unsubscriptions
+ }
+ }
+
+ unsubscribe.Channels = append(unsubscribe.Channels, WsChannels{
+ Name: channelsToUnsubscribe[i].Channel,
+ })
+ }
+ err := c.Websocket.Conn.SendJSONMessage(unsubscribe)
+ if err != nil {
+ return err
+ }
+ c.Websocket.RemoveSuccessfulUnsubscriptions(channelsToUnsubscribe...)
+ return nil
}
diff --git a/exchanges/coinbasepro/coinbasepro_wrapper.go b/exchanges/coinbasepro/coinbasepro_wrapper.go
index 868cd5ea..b707fb98 100644
--- a/exchanges/coinbasepro/coinbasepro_wrapper.go
+++ b/exchanges/coinbasepro/coinbasepro_wrapper.go
@@ -19,8 +19,8 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -58,19 +58,11 @@ func (c *CoinbasePro) SetDefaults() {
c.API.CredentialsValidator.RequiresClientID = true
c.API.CredentialsValidator.RequiresBase64DecodeSecret = true
- c.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- },
- UseGlobalFormat: true,
- RequestFormat: ¤cy.PairFormat{
- Delimiter: "-",
- Uppercase: true,
- },
- ConfigFormat: ¤cy.PairFormat{
- Delimiter: "-",
- Uppercase: true,
- },
+ requestFmt := ¤cy.PairFormat{Delimiter: currency.DashDelimiter, Uppercase: true}
+ configFmt := ¤cy.PairFormat{Delimiter: currency.DashDelimiter, Uppercase: true}
+ err := c.SetGlobalPairsManager(requestFmt, configFmt, asset.Spot)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
}
c.Features = exchange.Features{
@@ -141,7 +133,7 @@ func (c *CoinbasePro) SetDefaults() {
c.API.Endpoints.URLDefault = coinbaseproAPIURL
c.API.Endpoints.URL = c.API.Endpoints.URLDefault
c.API.Endpoints.WebsocketURL = coinbaseproWebsocketURL
- c.Websocket = wshandler.New()
+ c.Websocket = stream.New()
c.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
c.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
c.WebsocketOrderbookBufferLimit = exchange.DefaultWebsocketOrderbookBufferLimit
@@ -159,41 +151,31 @@ func (c *CoinbasePro) Setup(exch *config.ExchangeConfig) error {
return err
}
- err = c.Websocket.Setup(
- &wshandler.WebsocketSetup{
- Enabled: exch.Features.Enabled.Websocket,
- Verbose: exch.Verbose,
- AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
- WebsocketTimeout: exch.WebsocketTrafficTimeout,
- DefaultURL: coinbaseproWebsocketURL,
- ExchangeName: exch.Name,
- RunningURL: exch.API.Endpoints.WebsocketURL,
- Connector: c.WsConnect,
- Subscriber: c.Subscribe,
- UnSubscriber: c.Unsubscribe,
- Features: &c.Features.Supports.WebsocketCapabilities,
- })
+ err = c.Websocket.Setup(&stream.WebsocketSetup{
+ Enabled: exch.Features.Enabled.Websocket,
+ Verbose: exch.Verbose,
+ AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
+ WebsocketTimeout: exch.WebsocketTrafficTimeout,
+ DefaultURL: coinbaseproWebsocketURL,
+ ExchangeName: exch.Name,
+ RunningURL: exch.API.Endpoints.WebsocketURL,
+ Connector: c.WsConnect,
+ Subscriber: c.Subscribe,
+ UnSubscriber: c.Unsubscribe,
+ GenerateSubscriptions: c.GenerateDefaultSubscriptions,
+ Features: &c.Features.Supports.WebsocketCapabilities,
+ OrderbookBufferLimit: exch.WebsocketOrderbookBufferLimit,
+ BufferEnabled: true,
+ SortBuffer: true,
+ })
if err != nil {
return err
}
- c.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: c.Name,
- URL: c.Websocket.GetWebsocketURL(),
- ProxyURL: c.Websocket.GetProxyAddress(),
- Verbose: c.Verbose,
+ return c.Websocket.SetupNewConnection(stream.ConnectionSetup{
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
- }
-
- c.Websocket.Orderbook.Setup(
- exch.WebsocketOrderbookBufferLimit,
- true,
- true,
- false,
- false,
- exch.Name)
- return nil
+ })
}
// Start starts the coinbasepro go routine
@@ -217,21 +199,55 @@ func (c *CoinbasePro) Run() {
}
forceUpdate := false
- delim := c.GetPairFormat(asset.Spot, false).Delimiter
- if !common.StringDataContains(c.CurrencyPairs.GetPairs(asset.Spot,
- true).Strings(), delim) ||
- !common.StringDataContains(c.CurrencyPairs.GetPairs(asset.Spot,
- false).Strings(), delim) {
- enabledPairs := currency.NewPairsFromStrings(
- []string{currency.BTC.String() + delim + currency.USD.String()},
- )
- log.Warn(log.ExchangeSys,
- "Enabled pairs for CoinbasePro reset due to config upgrade, please enable the ones you would like to use again")
- forceUpdate = true
+ format, err := c.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update currencies. Err: %s\n",
+ c.Name,
+ err)
+ return
+ }
+ enabled, err := c.CurrencyPairs.GetPairs(asset.Spot, true)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update currencies. Err: %s\n",
+ c.Name,
+ err)
+ return
+ }
- err := c.UpdatePairs(enabledPairs, asset.Spot, true, true)
+ avail, err := c.CurrencyPairs.GetPairs(asset.Spot, false)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update currencies. Err: %s\n",
+ c.Name,
+ err)
+ return
+ }
+
+ if !common.StringDataContains(enabled.Strings(), format.Delimiter) ||
+ !common.StringDataContains(avail.Strings(), format.Delimiter) {
+ var p currency.Pairs
+ p, err = currency.NewPairsFromStrings([]string{currency.BTC.String() +
+ format.Delimiter +
+ currency.USD.String()})
if err != nil {
- log.Errorf(log.ExchangeSys, "%s failed to update currencies. Err: %s\n", c.Name, err)
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update currencies. Err: %s\n",
+ c.Name,
+ err)
+ } else {
+ log.Warn(log.ExchangeSys,
+ "Enabled pairs for CoinbasePro reset due to config upgrade, please enable the ones you would like to use again")
+ forceUpdate = true
+
+ err = c.UpdatePairs(p, asset.Spot, true, true)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update currencies. Err: %s\n",
+ c.Name,
+ err)
+ }
}
}
@@ -239,7 +255,7 @@ func (c *CoinbasePro) Run() {
return
}
- err := c.UpdateTradablePairs(forceUpdate)
+ err = c.UpdateTradablePairs(forceUpdate)
if err != nil {
log.Errorf(log.ExchangeSys, "%s failed to update tradable pairs. Err: %s", c.Name, err)
}
@@ -252,10 +268,15 @@ func (c *CoinbasePro) FetchTradablePairs(asset asset.Item) ([]string, error) {
return nil, err
}
+ format, err := c.GetPairFormat(asset, false)
+ if err != nil {
+ return nil, err
+ }
+
var products []string
for x := range pairs {
products = append(products, pairs[x].BaseCurrency+
- c.GetPairFormat(asset, false).Delimiter+
+ format.Delimiter+
pairs[x].QuoteCurrency)
}
@@ -270,7 +291,12 @@ func (c *CoinbasePro) UpdateTradablePairs(forceUpdate bool) error {
return err
}
- return c.UpdatePairs(currency.NewPairsFromStrings(pairs), asset.Spot, false, forceUpdate)
+ p, err := currency.NewPairsFromStrings(pairs)
+ if err != nil {
+ return err
+ }
+
+ return c.UpdatePairs(p, asset.Spot, false, forceUpdate)
}
// UpdateAccountInfo retrieves balances for all enabled currencies for the
@@ -317,28 +343,34 @@ func (c *CoinbasePro) FetchAccountInfo() (account.Holdings, error) {
// UpdateTicker updates and returns the ticker for a currency pair
func (c *CoinbasePro) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
- tick, err := c.GetTicker(c.FormatExchangeCurrency(p, assetType).String())
+ fpair, err := c.FormatExchangeCurrency(p, assetType)
if err != nil {
return nil, err
}
- stats, err := c.GetStats(c.FormatExchangeCurrency(p, assetType).String())
+
+ tick, err := c.GetTicker(fpair.String())
+ if err != nil {
+ return nil, err
+ }
+ stats, err := c.GetStats(fpair.String())
if err != nil {
return nil, err
}
tickerPrice := &ticker.Price{
- Last: stats.Last,
- High: stats.High,
- Low: stats.Low,
- Bid: tick.Bid,
- Ask: tick.Ask,
- Volume: tick.Volume,
- Open: stats.Open,
- Pair: p,
- LastUpdated: tick.Time,
- }
+ Last: stats.Last,
+ High: stats.High,
+ Low: stats.Low,
+ Bid: tick.Bid,
+ Ask: tick.Ask,
+ Volume: tick.Volume,
+ Open: stats.Open,
+ Pair: p,
+ LastUpdated: tick.Time,
+ ExchangeName: c.Name,
+ AssetType: assetType}
- err = ticker.ProcessTicker(c.Name, tickerPrice, assetType)
+ err = ticker.ProcessTicker(tickerPrice)
if err != nil {
return tickerPrice, err
}
@@ -366,15 +398,18 @@ func (c *CoinbasePro) FetchOrderbook(p currency.Pair, assetType asset.Item) (*or
// UpdateOrderbook updates and returns the orderbook for a currency pair
func (c *CoinbasePro) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
- orderBook := new(orderbook.Base)
- orderbookNew, err := c.GetOrderbook(c.FormatExchangeCurrency(p,
- assetType).String(), 2)
+ fpair, err := c.FormatExchangeCurrency(p, assetType)
if err != nil {
- return orderBook, err
+ return nil, err
+ }
+
+ orderbookNew, err := c.GetOrderbook(fpair.String(), 2)
+ if err != nil {
+ return nil, err
}
obNew := orderbookNew.(OrderbookL1L2)
-
+ orderBook := new(orderbook.Base)
for x := range obNew.Bids {
orderBook.Bids = append(orderBook.Bids, orderbook.Item{Amount: obNew.Bids[x].Amount, Price: obNew.Bids[x].Price})
}
@@ -413,15 +448,19 @@ func (c *CoinbasePro) SubmitOrder(s *order.Submit) (order.SubmitResponse, error)
return submitOrderResponse, err
}
+ fpair, err := c.FormatExchangeCurrency(s.Pair, asset.Spot)
+ if err != nil {
+ return submitOrderResponse, err
+ }
+
var response string
- var err error
switch s.Type {
case order.Market:
response, err = c.PlaceMarketOrder("",
s.Amount,
s.Amount,
s.Side.Lower(),
- c.FormatExchangeCurrency(s.Pair, asset.Spot).String(),
+ fpair.String(),
"")
case order.Limit:
response, err = c.PlaceLimitOrder("",
@@ -430,7 +469,7 @@ func (c *CoinbasePro) SubmitOrder(s *order.Submit) (order.SubmitResponse, error)
s.Side.Lower(),
"",
"",
- c.FormatExchangeCurrency(s.Pair, asset.Spot).String(),
+ fpair.String(),
"",
false)
default:
@@ -491,10 +530,15 @@ func (c *CoinbasePro) GetOrderInfo(orderID string) (order.Detail, error) {
if errOss != nil {
return order.Detail{}, fmt.Errorf("error parsing order side: %s", errOss)
}
+ p, errP := currency.NewPairDelimiter(genOrderDetail.ProductID, "-")
+ if errP != nil {
+ return order.Detail{}, fmt.Errorf("error parsing order side: %s", errP)
+ }
+
response := order.Detail{
Exchange: c.GetName(),
ID: genOrderDetail.ID,
- Pair: currency.NewPairDelimiter(genOrderDetail.ProductID, "-"),
+ Pair: p,
Side: ss,
Type: tt,
Date: od,
@@ -587,11 +631,6 @@ func (c *CoinbasePro) WithdrawFiatFundsToInternationalBank(withdrawRequest *with
}, nil
}
-// GetWebsocket returns a pointer to the exchange websocket
-func (c *CoinbasePro) GetWebsocket() (*wshandler.Websocket, error) {
- return c.Websocket, nil
-}
-
// GetFeeByType returns an estimate of fee based on type of transaction
func (c *CoinbasePro) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if !c.AllowAuthenticatedRequest() && // Todo check connection status
@@ -605,18 +644,32 @@ func (c *CoinbasePro) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, er
func (c *CoinbasePro) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
var respOrders []GeneralizedOrderResponse
for i := range req.Pairs {
+ fpair, err := c.FormatExchangeCurrency(req.Pairs[i], asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+
resp, err := c.GetOrders([]string{"open", "pending", "active"},
- c.FormatExchangeCurrency(req.Pairs[i], asset.Spot).String())
+ fpair.String())
if err != nil {
return nil, err
}
respOrders = append(respOrders, resp...)
}
+ format, err := c.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return nil, err
+ }
+
var orders []order.Detail
for i := range respOrders {
- curr := currency.NewPairDelimiter(respOrders[i].ProductID,
- c.GetPairFormat(asset.Spot, false).Delimiter)
+ var curr currency.Pair
+ curr, err = currency.NewPairDelimiter(respOrders[i].ProductID,
+ format.Delimiter)
+ if err != nil {
+ return nil, err
+ }
orderSide := order.Side(strings.ToUpper(respOrders[i].Side))
orderType := order.Type(strings.ToUpper(respOrders[i].Type))
orders = append(orders, order.Detail{
@@ -642,18 +695,31 @@ func (c *CoinbasePro) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Deta
func (c *CoinbasePro) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error) {
var respOrders []GeneralizedOrderResponse
for i := range req.Pairs {
+ fpair, err := c.FormatExchangeCurrency(req.Pairs[i], asset.Spot)
+ if err != nil {
+ return nil, err
+ }
resp, err := c.GetOrders([]string{"done", "settled"},
- c.FormatExchangeCurrency(req.Pairs[i], asset.Spot).String())
+ fpair.String())
if err != nil {
return nil, err
}
respOrders = append(respOrders, resp...)
}
+ format, err := c.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return nil, err
+ }
+
var orders []order.Detail
for i := range respOrders {
- curr := currency.NewPairDelimiter(respOrders[i].ProductID,
- c.GetPairFormat(asset.Spot, false).Delimiter)
+ var curr currency.Pair
+ curr, err = currency.NewPairDelimiter(respOrders[i].ProductID,
+ format.Delimiter)
+ if err != nil {
+ return nil, err
+ }
orderSide := order.Side(strings.ToUpper(respOrders[i].Side))
orderType := order.Type(strings.ToUpper(respOrders[i].Type))
orders = append(orders, order.Detail{
@@ -674,28 +740,23 @@ func (c *CoinbasePro) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Deta
return orders, nil
}
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func (c *CoinbasePro) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- c.Websocket.SubscribeToChannels(channels)
- return nil
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func (c *CoinbasePro) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- c.Websocket.RemoveSubscribedChannels(channels)
- return nil
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func (c *CoinbasePro) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return c.Websocket.GetSubscriptions(), nil
-}
-
-// AuthenticateWebsocket sends an authentication message to the websocket
-func (c *CoinbasePro) AuthenticateWebsocket() error {
- return common.ErrFunctionNotSupported
+// checkInterval checks allowable interval
+func checkInterval(i time.Duration) (int64, error) {
+ switch i.Seconds() {
+ case 60:
+ return 60, nil
+ case 300:
+ return 300, nil
+ case 900:
+ return 900, nil
+ case 3600:
+ return 3600, nil
+ case 21600:
+ return 21600, nil
+ case 86400:
+ return 86400, nil
+ }
+ return 0, fmt.Errorf("interval not allowed %v", i.Seconds())
}
// GetHistoricCandles returns a set of candle between two time periods for a
@@ -722,7 +783,13 @@ func (c *CoinbasePro) GetHistoricCandles(p currency.Pair, a asset.Item, start, e
if err != nil {
return kline.Item{}, err
}
- history, err := c.GetHistoricRates(c.FormatExchangeCurrency(p, a).String(),
+
+ formatP, err := c.FormatExchangeCurrency(p, a)
+ if err != nil {
+ return kline.Item{}, err
+ }
+
+ history, err := c.GetHistoricRates(formatP.String(),
start.Format(time.RFC3339),
end.Format(time.RFC3339),
gran)
@@ -765,8 +832,14 @@ func (c *CoinbasePro) GetHistoricCandlesExtended(p currency.Pair, a asset.Item,
return kline.Item{}, err
}
dates := kline.CalcDateRanges(start, end, interval, c.Features.Enabled.Kline.ResultLimit)
+
+ formattedPair, err := c.FormatExchangeCurrency(p, a)
+ if err != nil {
+ return kline.Item{}, err
+ }
+
for x := range dates {
- history, err := c.GetHistoricRates(c.FormatExchangeCurrency(p, a).String(),
+ history, err := c.GetHistoricRates(formattedPair.String(),
dates[x].Start.Format(time.RFC3339),
dates[x].End.Format(time.RFC3339),
gran)
diff --git a/exchanges/coinbene/coinbene.go b/exchanges/coinbene/coinbene.go
index ffc4d028..9080d838 100644
--- a/exchanges/coinbene/coinbene.go
+++ b/exchanges/coinbene/coinbene.go
@@ -18,13 +18,11 @@ import (
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
)
// Coinbene is the overarching type across this package
type Coinbene struct {
exchange.Base
- WebsocketConn *wshandler.WebsocketConnection
}
const (
@@ -35,10 +33,11 @@ const (
coinbeneAPIVersion = "v2"
// Public endpoints
- coinbeneGetTicker = "/market/ticker/one"
- coinbeneGetTickers = "/market/tickers"
- coinbeneGetOrderBook = "/market/orderBook"
- coinbeneGetKlines = "/market/klines"
+ coinbeneGetTicker = "/market/ticker/one"
+ coinbeneGetTickersSpot = "/market/ticker/list"
+ coinbeneGetTickers = "/market/tickers"
+ coinbeneGetOrderBook = "/market/orderBook"
+ coinbeneGetKlines = "/market/klines"
// TODO: Implement function ---
coinbeneSpotKlines = "/market/instruments/candles"
coinbeneSpotExchangeRate = "/market/rate/list"
@@ -65,12 +64,15 @@ const (
coinbeneListSwapPositions = "/position/list"
coinbenePositionFeeRate = "/position/feeRate"
- limitOrder = "1"
- marketOrder = "2"
- buyDirection = "1"
- openLong = "openLong"
- openShort = "openShort"
- sellDirection = "2"
+ limitOrder = "1"
+ marketOrder = "2"
+ postOnlyOrder = "8"
+ fillOrKillOrder = "9"
+ iosOrder = "10"
+ buyDirection = "1"
+ openLong = "openLong"
+ openShort = "openShort"
+ sellDirection = "2"
)
// GetAllPairs gets all pairs on the exchange
@@ -162,7 +164,7 @@ func (c *Coinbene) GetTickers() ([]TickerData, error) {
TickerData []TickerData `json:"data"`
}{}
- path := c.API.Endpoints.URL + coinbeneAPIVersion + coinbeneGetTicker
+ path := c.API.Endpoints.URL + coinbeneAPIVersion + coinbeneGetTickersSpot
return resp.TickerData, c.SendHTTPRequest(path, spotTickerList, &resp)
}
@@ -266,9 +268,15 @@ func (c *Coinbene) PlaceSpotOrder(price, quantity float64, symbol, direction,
params.Set("orderType", limitOrder)
case order.Market.Lower():
params.Set("orderType", marketOrder)
+ case order.PostOnly.Lower():
+ params.Set("orderType", postOnlyOrder)
+ case order.FillOrKill.Lower():
+ params.Set("orderType", fillOrKillOrder)
+ case order.IOS.Lower():
+ params.Set("orderType", iosOrder)
default:
return resp,
- errors.New("invalid order type, must be either 'limit' or 'market'")
+ errors.New("invalid order type, must be either 'limit', 'market', 'postOnly', 'fillOrKill', 'ios'")
}
params.Set("symbol", symbol)
diff --git a/exchanges/coinbene/coinbene_test.go b/exchanges/coinbene/coinbene_test.go
index d2ffb463..01baac97 100644
--- a/exchanges/coinbene/coinbene_test.go
+++ b/exchanges/coinbene/coinbene_test.go
@@ -40,13 +40,11 @@ func TestMain(m *testing.M) {
coinbeneConfig.API.AuthenticatedSupport = true
coinbeneConfig.API.Credentials.Secret = testAPISecret
coinbeneConfig.API.Credentials.Key = testAPIKey
-
+ c.Websocket = sharedtestvalues.NewTestWebsocket()
err = c.Setup(coinbeneConfig)
if err != nil {
log.Fatal(err)
}
- c.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- c.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
os.Exit(m.Run())
}
@@ -288,7 +286,11 @@ func TestGetSwapOrderbook(t *testing.T) {
func TestGetKlines(t *testing.T) {
t.Parallel()
- _, err := c.GetKlines(currency.NewPairFromString(spotTestPair).String(),
+ p, err := currency.NewPairFromString(spotTestPair)
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = c.GetKlines(p.String(),
time.Now().Add(-time.Hour*1), time.Now(), "1")
if err != nil {
t.Fatal(err)
@@ -297,7 +299,11 @@ func TestGetKlines(t *testing.T) {
func TestGetSwapKlines(t *testing.T) {
t.Parallel()
- _, err := c.GetSwapKlines(currency.NewPairFromString(swapTestPair).String(),
+ p, err := currency.NewPairFromString(swapTestPair)
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = c.GetSwapKlines(p.String(),
time.Now().Add(-time.Hour*1), time.Now(), "1")
if err != nil {
t.Error(err)
@@ -480,8 +486,8 @@ func TestWsUnsubscribe(t *testing.T) {
func TestWsLogin(t *testing.T) {
pressXToJSON := []byte(`{"event":"login","success":true}`)
err := c.wsHandleData(pressXToJSON)
- if err != nil {
- t.Error(err)
+ if err == nil {
+ t.Error("error cannot be nil as this will initiate an auth subscription")
}
pressXToJSON = []byte(`{"event":"login","success":false}`)
@@ -692,14 +698,20 @@ func TestWsUserOrder(t *testing.T) {
}
func TestGetHistoricCandles(t *testing.T) {
- currencyPair := currency.NewPairFromString(spotTestPair)
+ currencyPair, err := currency.NewPairFromString(spotTestPair)
+ if err != nil {
+ t.Fatal(err)
+ }
startTime := time.Now().Add(-time.Hour * 24)
- _, err := c.GetHistoricCandles(currencyPair, asset.Spot, startTime, time.Now(), kline.OneHour)
+ _, err = c.GetHistoricCandles(currencyPair, asset.Spot, startTime, time.Now(), kline.OneHour)
if err != nil {
t.Fatal(err)
}
- currencyPairSwap := currency.NewPairFromString(swapTestPair)
+ currencyPairSwap, err := currency.NewPairFromString(swapTestPair)
+ if err != nil {
+ t.Fatal(err)
+ }
_, err = c.GetHistoricCandles(currencyPairSwap, asset.PerpetualSwap, startTime, time.Now(), kline.OneHour)
if err != nil {
t.Fatal(err)
@@ -707,9 +719,12 @@ func TestGetHistoricCandles(t *testing.T) {
}
func TestGetHistoricCandlesExtended(t *testing.T) {
- currencyPair := currency.NewPairFromString(spotTestPair)
+ currencyPair, err := currency.NewPairFromString(spotTestPair)
+ if err != nil {
+ t.Fatal(err)
+ }
startTime := time.Now().Add(-time.Hour * 24)
- _, err := c.GetHistoricCandlesExtended(currencyPair, asset.Spot, startTime, time.Now(), kline.OneHour)
+ _, err = c.GetHistoricCandlesExtended(currencyPair, asset.Spot, startTime, time.Now(), kline.OneHour)
if err != nil {
t.Fatal(err)
}
diff --git a/exchanges/coinbene/coinbene_websocket.go b/exchanges/coinbene/coinbene_websocket.go
index 26e9359c..bc364ce2 100644
--- a/exchanges/coinbene/coinbene_websocket.go
+++ b/exchanges/coinbene/coinbene_websocket.go
@@ -16,9 +16,9 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wsorderbook"
)
const (
@@ -27,15 +27,13 @@ const (
topic = "topic"
)
-var comms = make(chan wshandler.WebsocketResponse)
-
// WsConnect connects to websocket
func (c *Coinbene) WsConnect() error {
if !c.Websocket.IsEnabled() || !c.IsEnabled() {
- return errors.New(wshandler.WebsocketNotEnabled)
+ return errors.New(stream.WebsocketNotEnabled)
}
var dialer websocket.Dialer
- err := c.WebsocketConn.Dial(&dialer, http.Header{})
+ err := c.Websocket.Conn.Dial(&dialer, http.Header{})
if err != nil {
return err
}
@@ -48,38 +46,44 @@ func (c *Coinbene) WsConnect() error {
c.Websocket.SetCanUseAuthenticatedEndpoints(false)
}
}
- c.GenerateDefaultSubscriptions()
-
- return nil
+ subs, err := c.GenerateDefaultSubscriptions()
+ if err != nil {
+ return err
+ }
+ return c.Websocket.SubscribeToChannels(subs)
}
// GenerateDefaultSubscriptions generates stuff
-func (c *Coinbene) GenerateDefaultSubscriptions() {
+func (c *Coinbene) GenerateDefaultSubscriptions() ([]stream.ChannelSubscription, error) {
var channels = []string{"orderBook.%s.100", "tradeList.%s", "ticker.%s", "kline.%s"}
- var subscriptions []wshandler.WebsocketChannelSubscription
- pairs := c.GetEnabledPairs(asset.PerpetualSwap)
+ var subscriptions []stream.ChannelSubscription
+ pairs, err := c.GetEnabledPairs(asset.PerpetualSwap)
+ if err != nil {
+ return nil, err
+ }
for x := range channels {
for y := range pairs {
pairs[y].Delimiter = ""
- subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
Channel: fmt.Sprintf(channels[x], pairs[y]),
Currency: pairs[y],
+ Asset: asset.PerpetualSwap,
})
}
}
- c.Websocket.SubscribeToChannels(subscriptions)
+ return subscriptions, nil
}
// GenerateAuthSubs generates auth subs
-func (c *Coinbene) GenerateAuthSubs() {
- var subscriptions []wshandler.WebsocketChannelSubscription
- var sub wshandler.WebsocketChannelSubscription
+func (c *Coinbene) GenerateAuthSubs() ([]stream.ChannelSubscription, error) {
+ var subscriptions []stream.ChannelSubscription
+ var sub stream.ChannelSubscription
var userChannels = []string{"user.account", "user.position", "user.order"}
for z := range userChannels {
sub.Channel = userChannels[z]
subscriptions = append(subscriptions, sub)
}
- c.Websocket.SubscribeToChannels(subscriptions)
+ return subscriptions, nil
}
// wsReadData receives and passes on websocket messages for processing
@@ -87,27 +91,20 @@ func (c *Coinbene) wsReadData() {
c.Websocket.Wg.Add(1)
defer c.Websocket.Wg.Done()
for {
- select {
- case <-c.Websocket.ShutdownC:
+ resp := c.Websocket.Conn.ReadMessage()
+ if resp.Raw == nil {
return
- default:
- resp, err := c.WebsocketConn.ReadMessage()
- if err != nil {
- c.Websocket.ReadMessageErrors <- err
- return
- }
- err = c.wsHandleData(resp.Raw)
- if err != nil {
- c.Websocket.DataHandler <- err
- }
+ }
+ err := c.wsHandleData(resp.Raw)
+ if err != nil {
+ c.Websocket.DataHandler <- err
}
}
}
func (c *Coinbene) wsHandleData(respRaw []byte) error {
- c.Websocket.TrafficAlert <- struct{}{}
- if string(respRaw) == wshandler.Ping {
- err := c.WebsocketConn.SendRawMessage(websocket.TextMessage, []byte(wshandler.Pong))
+ if string(respRaw) == stream.Ping {
+ err := c.Websocket.Conn.SendRawMessage(websocket.TextMessage, []byte(stream.Pong))
if err != nil {
return err
}
@@ -128,8 +125,12 @@ func (c *Coinbene) wsHandleData(respRaw []byte) error {
if ok && strings.Contains(result[event].(string), "login") {
if result["success"].(bool) {
c.Websocket.SetCanUseAuthenticatedEndpoints(true)
- c.GenerateAuthSubs()
- return nil
+ var authsubs []stream.ChannelSubscription
+ authsubs, err = c.GenerateAuthSubs()
+ if err != nil {
+ return err
+ }
+ return c.Websocket.SubscribeToChannels(authsubs)
}
c.Websocket.SetCanUseAuthenticatedEndpoints(false)
return fmt.Errorf("message: %s. code: %v", result["message"], result["code"])
@@ -141,17 +142,35 @@ func (c *Coinbene) wsHandleData(respRaw []byte) error {
if err != nil {
return err
}
+
+ var format currency.PairFormat
+ format, err = c.GetPairFormat(asset.PerpetualSwap, true)
+ if err != nil {
+ return err
+ }
+
+ var pairs currency.Pairs
+ pairs, err = c.GetEnabledPairs(asset.PerpetualSwap)
+ if err != nil {
+ return err
+ }
+
for x := range wsTicker.Data {
+ var p currency.Pair
+ p, err = currency.NewPairFromFormattedPairs(wsTicker.Data[x].Symbol,
+ pairs,
+ format)
+ if err != nil {
+ return err
+ }
c.Websocket.DataHandler <- &ticker.Price{
- Volume: wsTicker.Data[x].Volume24h,
- Last: wsTicker.Data[x].LastPrice,
- High: wsTicker.Data[x].High24h,
- Low: wsTicker.Data[x].Low24h,
- Bid: wsTicker.Data[x].BestBidPrice,
- Ask: wsTicker.Data[x].BestAskPrice,
- Pair: currency.NewPairFromFormattedPairs(wsTicker.Data[x].Symbol,
- c.GetEnabledPairs(asset.PerpetualSwap),
- c.GetPairFormat(asset.PerpetualSwap, true)),
+ Volume: wsTicker.Data[x].Volume24h,
+ Last: wsTicker.Data[x].LastPrice,
+ High: wsTicker.Data[x].High24h,
+ Low: wsTicker.Data[x].Low24h,
+ Bid: wsTicker.Data[x].BestBidPrice,
+ Ask: wsTicker.Data[x].BestAskPrice,
+ Pair: p,
ExchangeName: c.Name,
AssetType: asset.PerpetualSwap,
LastUpdated: wsTicker.Data[x].Timestamp,
@@ -182,16 +201,33 @@ func (c *Coinbene) wsHandleData(respRaw []byte) error {
if tradeList.Data[0][1] == "s" {
tSide = order.Sell
}
- c.Websocket.DataHandler <- wshandler.TradeData{
- CurrencyPair: currency.NewPairFromFormattedPairs(p,
- c.GetEnabledPairs(asset.PerpetualSwap),
- c.GetPairFormat(asset.PerpetualSwap, true)),
- Timestamp: t,
- Price: price,
- Amount: amount,
- Exchange: c.Name,
- AssetType: asset.PerpetualSwap,
- Side: tSide,
+
+ var format currency.PairFormat
+ format, err = c.GetPairFormat(asset.PerpetualSwap, true)
+ if err != nil {
+ return err
+ }
+
+ var pairs currency.Pairs
+ pairs, err = c.GetEnabledPairs(asset.PerpetualSwap)
+ if err != nil {
+ return err
+ }
+
+ var newP currency.Pair
+ newP, err = currency.NewPairFromFormattedPairs(p, pairs, format)
+ if err != nil {
+ return err
+ }
+
+ c.Websocket.DataHandler <- stream.TradeData{
+ CurrencyPair: newP,
+ Timestamp: t,
+ Price: price,
+ Amount: amount,
+ Exchange: c.Name,
+ AssetType: asset.PerpetualSwap,
+ Side: tSide,
}
case strings.Contains(result[topic].(string), "orderBook"):
orderBook := struct {
@@ -209,9 +245,25 @@ func (c *Coinbene) wsHandleData(respRaw []byte) error {
return err
}
p := strings.Replace(orderBook.Topic, "orderBook.", "", 1)
- cp := currency.NewPairFromFormattedPairs(p,
- c.GetEnabledPairs(asset.PerpetualSwap),
- c.GetPairFormat(asset.PerpetualSwap, true))
+
+ var format currency.PairFormat
+ format, err = c.GetPairFormat(asset.PerpetualSwap, true)
+ if err != nil {
+ return err
+ }
+
+ var pairs currency.Pairs
+ pairs, err = c.GetEnabledPairs(asset.PerpetualSwap)
+ if err != nil {
+ return err
+ }
+
+ var newP currency.Pair
+ newP, err = currency.NewPairFromFormattedPairs(p, pairs, format)
+ if err != nil {
+ return err
+ }
+
var amount, price float64
var asks, bids []orderbook.Item
for i := range orderBook.Data[0].Asks {
@@ -247,23 +299,19 @@ func (c *Coinbene) wsHandleData(respRaw []byte) error {
newOB.Asks = asks
newOB.Bids = bids
newOB.AssetType = asset.PerpetualSwap
- newOB.Pair = cp
+ newOB.Pair = newP
newOB.ExchangeName = c.Name
newOB.LastUpdated = orderBook.Data[0].Timestamp
err = c.Websocket.Orderbook.LoadSnapshot(&newOB)
if err != nil {
return err
}
- c.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{Pair: newOB.Pair,
- Asset: asset.PerpetualSwap,
- Exchange: c.Name,
- }
} else if orderBook.Action == "update" {
- newOB := wsorderbook.WebsocketOrderbookUpdate{
+ newOB := buffer.Update{
Asks: asks,
Bids: bids,
Asset: asset.PerpetualSwap,
- Pair: cp,
+ Pair: newP,
UpdateID: orderBook.Data[0].Version,
UpdateTime: orderBook.Data[0].Timestamp,
}
@@ -271,10 +319,6 @@ func (c *Coinbene) wsHandleData(respRaw []byte) error {
if err != nil {
return err
}
- c.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{Pair: newOB.Pair,
- Asset: asset.PerpetualSwap,
- Exchange: c.Name,
- }
}
case strings.Contains(result[topic].(string), "kline"):
var kline WsKline
@@ -291,15 +335,33 @@ func (c *Coinbene) wsHandleData(respRaw []byte) error {
}
tempKline = append(tempKline, tempFloat)
}
- p := currency.NewPairFromFormattedPairs(kline.Data[0][0].(string),
- c.GetEnabledPairs(asset.PerpetualSwap),
- c.GetPairFormat(asset.PerpetualSwap, true))
+
+ var format currency.PairFormat
+ format, err = c.GetPairFormat(asset.PerpetualSwap, true)
+ if err != nil {
+ return err
+ }
+
+ var pairs currency.Pairs
+ pairs, err = c.GetEnabledPairs(asset.PerpetualSwap)
+ if err != nil {
+ return err
+ }
+
+ var newP currency.Pair
+ newP, err = currency.NewPairFromFormattedPairs(kline.Data[0][0].(string),
+ pairs,
+ format)
+ if err != nil {
+ return err
+ }
+
if tempKline == nil && len(tempKline) < 5 {
return errors.New(c.Name + " - received bad data ")
}
- c.Websocket.DataHandler <- wshandler.KlineData{
+ c.Websocket.DataHandler <- stream.KlineData{
Timestamp: time.Unix(int64(kline.Data[0][1].(float64)), 0),
- Pair: p,
+ Pair: newP,
AssetType: asset.PerpetualSwap,
Exchange: c.Name,
OpenPrice: tempKline[0],
@@ -328,6 +390,17 @@ func (c *Coinbene) wsHandleData(respRaw []byte) error {
if err != nil {
return err
}
+
+ format, err := c.GetPairFormat(asset.PerpetualSwap, true)
+ if err != nil {
+ return err
+ }
+
+ pairs, err := c.GetEnabledPairs(asset.PerpetualSwap)
+ if err != nil {
+ return err
+ }
+
for i := range orders.Data {
oType, err := order.StringToOrderType(orders.Data[i].OrderType)
if err != nil {
@@ -345,6 +418,14 @@ func (c *Coinbene) wsHandleData(respRaw []byte) error {
Err: err,
}
}
+
+ newP, err := currency.NewPairFromFormattedPairs(orders.Data[i].Symbol,
+ pairs,
+ format)
+ if err != nil {
+ return err
+ }
+
c.Websocket.DataHandler <- &order.Detail{
Price: orders.Data[i].OrderPrice,
Amount: orders.Data[i].Quantity,
@@ -358,32 +439,46 @@ func (c *Coinbene) wsHandleData(respRaw []byte) error {
AssetType: asset.PerpetualSwap,
Date: orders.Data[i].OrderTime,
Leverage: strconv.FormatInt(orders.Data[i].Leverage, 10),
- Pair: currency.NewPairFromFormattedPairs(orders.Data[i].Symbol,
- c.GetEnabledPairs(asset.PerpetualSwap),
- c.GetPairFormat(asset.PerpetualSwap, true)),
+ Pair: newP,
}
}
default:
- c.Websocket.DataHandler <- wshandler.UnhandledMessageWarning{Message: c.Name + wshandler.UnhandledMessage + string(respRaw)}
+ c.Websocket.DataHandler <- stream.UnhandledMessageWarning{
+ Message: c.Name + stream.UnhandledMessage + string(respRaw),
+ }
return nil
}
return nil
}
// Subscribe sends a websocket message to receive data from the channel
-func (c *Coinbene) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
+func (c *Coinbene) Subscribe(channelsToSubscribe []stream.ChannelSubscription) error {
var sub WsSub
sub.Operation = "subscribe"
- sub.Arguments = []string{channelToSubscribe.Channel}
- return c.WebsocketConn.SendJSONMessage(sub)
+ for i := range channelsToSubscribe {
+ sub.Arguments = append(sub.Arguments, channelsToSubscribe[i].Channel)
+ }
+ err := c.Websocket.Conn.SendJSONMessage(sub)
+ if err != nil {
+ return err
+ }
+ c.Websocket.AddSuccessfulSubscriptions(channelsToSubscribe...)
+ return nil
}
// Unsubscribe sends a websocket message to receive data from the channel
-func (c *Coinbene) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
- var sub WsSub
- sub.Operation = "unsubscribe"
- sub.Arguments = []string{channelToSubscribe.Channel}
- return c.WebsocketConn.SendJSONMessage(sub)
+func (c *Coinbene) Unsubscribe(channelToUnsubscribe []stream.ChannelSubscription) error {
+ var unsub WsSub
+ unsub.Operation = "unsubscribe"
+ for i := range channelToUnsubscribe {
+ unsub.Arguments = append(unsub.Arguments, channelToUnsubscribe[i].Channel)
+ }
+ err := c.Websocket.Conn.SendJSONMessage(unsub)
+ if err != nil {
+ return err
+ }
+ c.Websocket.RemoveSuccessfulUnsubscriptions(channelToUnsubscribe...)
+ return nil
}
// Login logs in
@@ -397,5 +492,5 @@ func (c *Coinbene) Login() error {
sign := crypto.HexEncodeToString(tempSign)
sub.Operation = "login"
sub.Arguments = []string{c.API.Credentials.Key, expTime, sign}
- return c.WebsocketConn.SendJSONMessage(sub)
+ return c.Websocket.Conn.SendJSONMessage(sub)
}
diff --git a/exchanges/coinbene/coinbene_wrapper.go b/exchanges/coinbene/coinbene_wrapper.go
index 9e1d0fa0..d4a931bd 100644
--- a/exchanges/coinbene/coinbene_wrapper.go
+++ b/exchanges/coinbene/coinbene_wrapper.go
@@ -19,8 +19,8 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -56,33 +56,32 @@ func (c *Coinbene) SetDefaults() {
c.API.CredentialsValidator.RequiresKey = true
c.API.CredentialsValidator.RequiresSecret = true
- c.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- asset.PerpetualSwap,
+ err := c.StoreAssetPairFormat(asset.Spot, currency.PairStore{
+ RequestFormat: ¤cy.PairFormat{
+ Uppercase: true,
+ Delimiter: currency.ForwardSlashDelimiter,
},
+ ConfigFormat: ¤cy.PairFormat{
+ Uppercase: true,
+ Delimiter: currency.ForwardSlashDelimiter,
+ },
+ })
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
}
- c.CurrencyPairs.Store(asset.Spot, currency.PairStore{
- RequestFormat: ¤cy.PairFormat{
- Uppercase: true,
- Delimiter: "/",
- },
- ConfigFormat: ¤cy.PairFormat{
- Uppercase: true,
- Delimiter: "/",
- },
- })
-
- c.CurrencyPairs.Store(asset.PerpetualSwap, currency.PairStore{
+ err = c.StoreAssetPairFormat(asset.PerpetualSwap, currency.PairStore{
RequestFormat: ¤cy.PairFormat{
Uppercase: true,
},
ConfigFormat: ¤cy.PairFormat{
Uppercase: true,
- Delimiter: "/",
+ Delimiter: currency.ForwardSlashDelimiter,
},
})
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
+ }
c.Features = exchange.Features{
Supports: exchange.FeaturesSupported{
@@ -149,7 +148,7 @@ func (c *Coinbene) SetDefaults() {
c.API.Endpoints.URLDefault = coinbeneAPIURL
c.API.Endpoints.URL = c.API.Endpoints.URLDefault
c.API.Endpoints.WebsocketURL = wsContractURL
- c.Websocket = wshandler.New()
+ c.Websocket = stream.New()
c.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
c.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
c.WebsocketOrderbookBufferLimit = exchange.DefaultWebsocketOrderbookBufferLimit
@@ -167,42 +166,31 @@ func (c *Coinbene) Setup(exch *config.ExchangeConfig) error {
return err
}
- err = c.Websocket.Setup(
- &wshandler.WebsocketSetup{
- Enabled: exch.Features.Enabled.Websocket,
- Verbose: exch.Verbose,
- AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
- WebsocketTimeout: exch.WebsocketTrafficTimeout,
- DefaultURL: wsContractURL,
- ExchangeName: exch.Name,
- RunningURL: exch.API.Endpoints.WebsocketURL,
- Connector: c.WsConnect,
- Subscriber: c.Subscribe,
- UnSubscriber: c.Unsubscribe,
- Features: &c.Features.Supports.WebsocketCapabilities,
- })
+ err = c.Websocket.Setup(&stream.WebsocketSetup{
+ Enabled: exch.Features.Enabled.Websocket,
+ Verbose: exch.Verbose,
+ AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
+ WebsocketTimeout: exch.WebsocketTrafficTimeout,
+ DefaultURL: wsContractURL,
+ ExchangeName: exch.Name,
+ RunningURL: exch.API.Endpoints.WebsocketURL,
+ Connector: c.WsConnect,
+ Subscriber: c.Subscribe,
+ UnSubscriber: c.Unsubscribe,
+ GenerateSubscriptions: c.GenerateDefaultSubscriptions,
+ Features: &c.Features.Supports.WebsocketCapabilities,
+ OrderbookBufferLimit: exch.WebsocketOrderbookBufferLimit,
+ BufferEnabled: true,
+ SortBuffer: true,
+ })
if err != nil {
return err
}
- c.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: c.Name,
- URL: c.Websocket.GetWebsocketURL(),
- ProxyURL: c.Websocket.GetProxyAddress(),
- Verbose: c.Verbose,
+ return c.Websocket.SetupNewConnection(stream.ConnectionSetup{
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
- }
-
- c.Websocket.Orderbook.Setup(
- exch.WebsocketOrderbookBufferLimit,
- true,
- true,
- false,
- false,
- exch.Name)
-
- return nil
+ })
}
// Start starts the Coinbene go routine
@@ -257,6 +245,11 @@ func (c *Coinbene) FetchTradablePairs(a asset.Item) ([]string, error) {
currencies = append(currencies, pairs[x].Symbol)
}
case asset.PerpetualSwap:
+ format, err := c.GetPairFormat(a, false)
+ if err != nil {
+ return nil, err
+ }
+
tickers, err := c.GetSwapTickers()
if err != nil {
return nil, err
@@ -264,10 +257,11 @@ func (c *Coinbene) FetchTradablePairs(a asset.Item) ([]string, error) {
for t := range tickers {
idx := strings.Index(t, currency.USDT.String())
if idx == 0 {
- return nil, fmt.Errorf("%s SWAP currency does not contain USDT", c.Name)
+ return nil,
+ fmt.Errorf("%s SWAP currency does not contain USDT", c.Name)
}
currencies = append(currencies,
- t[0:idx]+c.GetPairFormat(a, false).Delimiter+t[idx:])
+ t[0:idx]+format.Delimiter+t[idx:])
}
}
return currencies, nil
@@ -282,8 +276,13 @@ func (c *Coinbene) UpdateTradablePairs(forceUpdate bool) error {
if err != nil {
return err
}
- err = c.UpdatePairs(currency.NewPairsFromStrings(pairs),
- assets[x], false, forceUpdate)
+
+ p, err := currency.NewPairsFromStrings(pairs)
+ if err != nil {
+ return err
+ }
+
+ err = c.UpdatePairs(p, assets[x], false, forceUpdate)
if err != nil {
return err
}
@@ -293,30 +292,44 @@ func (c *Coinbene) UpdateTradablePairs(forceUpdate bool) error {
// UpdateTicker updates and returns the ticker for a currency pair
func (c *Coinbene) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
- resp := new(ticker.Price)
if !c.SupportsAsset(assetType) {
return nil,
fmt.Errorf("%s does not support asset type %s", c.Name, assetType)
}
+ allPairs, err := c.GetEnabledPairs(assetType)
+ if err != nil {
+ return nil, err
+ }
+
switch assetType {
case asset.Spot:
- allPairs := c.GetEnabledPairs(assetType)
- for x := range allPairs {
- tempResp, err := c.GetTicker(c.FormatExchangeCurrency(allPairs[x],
- assetType).String())
+ tickers, err := c.GetTickers()
+ if err != nil {
+ return nil, err
+ }
+
+ for i := range tickers {
+ var newP currency.Pair
+ newP, err = currency.NewPairFromString(tickers[i].Symbol)
if err != nil {
return nil, err
}
- resp.Pair = allPairs[x]
- resp.Last = tempResp.LatestPrice
- resp.High = tempResp.DailyHigh
- resp.Low = tempResp.DailyLow
- resp.Bid = tempResp.BestBid
- resp.Ask = tempResp.BestAsk
- resp.Volume = tempResp.DailyVolume
- resp.LastUpdated = time.Now()
- err = ticker.ProcessTicker(c.Name, resp, assetType)
+
+ if !allPairs.Contains(newP, true) {
+ continue
+ }
+
+ err = ticker.ProcessTicker(&ticker.Price{
+ Pair: newP,
+ Last: tickers[i].LatestPrice,
+ High: tickers[i].DailyHigh,
+ Low: tickers[i].DailyLow,
+ Bid: tickers[i].BestBid,
+ Ask: tickers[i].BestAsk,
+ Volume: tickers[i].DailyVolume,
+ ExchangeName: c.Name,
+ AssetType: assetType})
if err != nil {
return nil, err
}
@@ -327,24 +340,31 @@ func (c *Coinbene) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.
return nil, err
}
- allPairs := c.GetEnabledPairs(assetType)
for x := range allPairs {
- tick, ok := tickers[c.FormatExchangeCurrency(allPairs[x],
- assetType).String()]
+ fpair, err := c.FormatExchangeCurrency(allPairs[x], assetType)
+ if err != nil {
+ return nil, err
+ }
+
+ tick, ok := tickers[fpair.String()]
if !ok {
log.Warnf(log.ExchangeSys,
- "%s SWAP ticker item was not found", c.Name)
+ "%s SWAP ticker item was not found",
+ c.Name)
continue
}
- resp.Pair = allPairs[x]
- resp.Last = tick.LastPrice
- resp.High = tick.High24Hour
- resp.Low = tick.Low24Hour
- resp.Bid = tick.BestBidPrice
- resp.Ask = tick.BestAskPrice
- resp.Volume = tick.Volume24Hour
- resp.LastUpdated = tick.Timestamp
- err = ticker.ProcessTicker(c.Name, resp, assetType)
+
+ err = ticker.ProcessTicker(&ticker.Price{
+ Pair: allPairs[x],
+ Last: tick.LastPrice,
+ High: tick.High24Hour,
+ Low: tick.Low24Hour,
+ Bid: tick.BestBidPrice,
+ Ask: tick.BestAskPrice,
+ Volume: tick.Volume24Hour,
+ LastUpdated: tick.Timestamp,
+ ExchangeName: c.Name,
+ AssetType: assetType})
if err != nil {
return nil, err
}
@@ -368,15 +388,15 @@ func (c *Coinbene) FetchTicker(p currency.Pair, assetType asset.Item) (*ticker.P
}
// FetchOrderbook returns orderbook base on the currency pair
-func (c *Coinbene) FetchOrderbook(currency currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
+func (c *Coinbene) FetchOrderbook(p currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
if !c.SupportsAsset(assetType) {
return nil,
fmt.Errorf("%s does not support asset type %s", c.Name, assetType)
}
- ob, err := orderbook.Get(c.Name, currency, assetType)
+ ob, err := orderbook.Get(c.Name, p, assetType)
if err != nil {
- return c.UpdateOrderbook(currency, assetType)
+ return c.UpdateOrderbook(p, assetType)
}
return ob, nil
}
@@ -389,18 +409,19 @@ func (c *Coinbene) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orde
fmt.Errorf("%s does not support asset type %s", c.Name, assetType)
}
- var tempResp Orderbook
- var err error
+ fpair, err := c.FormatExchangeCurrency(p, assetType)
+ if err != nil {
+ return nil, err
+ }
+ var tempResp Orderbook
switch assetType {
case asset.Spot:
- tempResp, err = c.GetOrderbook(
- c.FormatExchangeCurrency(p, assetType).String(),
+ tempResp, err = c.GetOrderbook(fpair.String(),
100, // TO-DO: Update this once we support configurable orderbook depth
)
case asset.PerpetualSwap:
- tempResp, err = c.GetSwapOrderbook(
- c.FormatExchangeCurrency(p, assetType).String(),
+ tempResp, err = c.GetSwapOrderbook(fpair.String(),
100, // TO-DO: Update this once we support configurable orderbook depth
)
}
@@ -501,13 +522,15 @@ func (c *Coinbene) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
fmt.Errorf("%s orderside is not supported by this exchange",
s.Side)
}
- if s.Type != order.Limit {
- return resp, fmt.Errorf("only limit order is supported by this exchange")
+
+ fpair, err := c.FormatExchangeCurrency(s.Pair, asset.Spot)
+ if err != nil {
+ return resp, err
}
tempResp, err := c.PlaceSpotOrder(s.Price,
s.Amount,
- c.FormatExchangeCurrency(s.Pair, asset.Spot).String(),
+ fpair.String(),
s.Side.String(),
s.Type.String(),
s.ClientID,
@@ -535,13 +558,17 @@ func (c *Coinbene) CancelOrder(order *order.Cancel) error {
// CancelAllOrders cancels all orders associated with a currency pair
func (c *Coinbene) CancelAllOrders(orderCancellation *order.Cancel) (order.CancelAllResponse, error) {
var resp order.CancelAllResponse
- orders, err := c.FetchOpenSpotOrders(
- c.FormatExchangeCurrency(orderCancellation.Pair,
- asset.Spot).String(),
- )
+ fpair, err := c.FormatExchangeCurrency(orderCancellation.Pair,
+ orderCancellation.AssetType)
if err != nil {
return resp, err
}
+
+ orders, err := c.FetchOpenSpotOrders(fpair.String())
+ if err != nil {
+ return resp, err
+ }
+
tempMap := make(map[string]string)
for x := range orders {
_, err := c.CancelSpotOrder(orders[x].OrderID)
@@ -597,11 +624,6 @@ func (c *Coinbene) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdra
return nil, common.ErrFunctionNotSupported
}
-// GetWebsocket returns a pointer to the exchange websocket
-func (c *Coinbene) GetWebsocket() (*wshandler.Websocket, error) {
- return c.Websocket, nil
-}
-
// GetActiveOrders retrieves any orders that are active/open
func (c *Coinbene) GetActiveOrders(getOrdersRequest *order.GetOrdersRequest) ([]order.Detail, error) {
if len(getOrdersRequest.Pairs) == 0 {
@@ -610,21 +632,24 @@ func (c *Coinbene) GetActiveOrders(getOrdersRequest *order.GetOrdersRequest) ([]
return nil, err
}
for a := range allPairs {
- getOrdersRequest.Pairs = append(getOrdersRequest.Pairs,
- currency.NewPairFromString(allPairs[a].Symbol))
+ p, err := currency.NewPairFromString(allPairs[a].Symbol)
+ if err != nil {
+ return nil, err
+ }
+ getOrdersRequest.Pairs = append(getOrdersRequest.Pairs, p)
}
}
- var err error
var resp []order.Detail
-
for x := range getOrdersRequest.Pairs {
+ fpair, err := c.FormatExchangeCurrency(getOrdersRequest.Pairs[x],
+ asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+
var tempData OrdersInfo
- tempData, err = c.FetchOpenSpotOrders(
- c.FormatExchangeCurrency(
- getOrdersRequest.Pairs[x],
- asset.Spot).String(),
- )
+ tempData, err = c.FetchOpenSpotOrders(fpair.String())
if err != nil {
return nil, err
}
@@ -658,23 +683,26 @@ func (c *Coinbene) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest) ([]
if err != nil {
return nil, err
}
+
for a := range allPairs {
- getOrdersRequest.Pairs = append(getOrdersRequest.Pairs,
- currency.NewPairFromString(allPairs[a].Symbol))
+ p, err := currency.NewPairFromString(allPairs[a].Symbol)
+ if err != nil {
+ return nil, err
+ }
+ getOrdersRequest.Pairs = append(getOrdersRequest.Pairs, p)
}
}
var resp []order.Detail
var tempData OrdersInfo
- var err error
-
for x := range getOrdersRequest.Pairs {
- tempData, err = c.FetchClosedOrders(
- c.FormatExchangeCurrency(
- getOrdersRequest.Pairs[x],
- asset.Spot).String(),
- "",
- )
+ fpair, err := c.FormatExchangeCurrency(getOrdersRequest.Pairs[x],
+ asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+
+ tempData, err = c.FetchClosedOrders(fpair.String(), "")
if err != nil {
return nil, err
}
@@ -702,40 +730,20 @@ func (c *Coinbene) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest) ([]
// GetFeeByType returns an estimate of fee based on the type of transaction
func (c *Coinbene) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
- var fee float64
- tempData, err := c.GetPairInfo(
- c.FormatExchangeCurrency(
- feeBuilder.Pair, asset.Spot).String(),
- )
+ fpair, err := c.FormatExchangeCurrency(feeBuilder.Pair, asset.Spot)
if err != nil {
- return fee, err
+ return 0, err
}
- switch feeBuilder.IsMaker {
- case true:
- fee = feeBuilder.PurchasePrice * feeBuilder.Amount * tempData.MakerFeeRate
- case false:
- fee = feeBuilder.PurchasePrice * feeBuilder.Amount * tempData.TakerFeeRate
+
+ tempData, err := c.GetPairInfo(fpair.String())
+ if err != nil {
+ return 0, err
}
- return fee, nil
-}
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func (c *Coinbene) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- c.Websocket.SubscribeToChannels(channels)
- return nil
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func (c *Coinbene) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- c.Websocket.RemoveSubscribedChannels(channels)
- return nil
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func (c *Coinbene) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return c.Websocket.GetSubscriptions(), nil
+ if feeBuilder.IsMaker {
+ return feeBuilder.PurchasePrice * feeBuilder.Amount * tempData.MakerFeeRate, nil
+ }
+ return feeBuilder.PurchasePrice * feeBuilder.Amount * tempData.TakerFeeRate, nil
}
// AuthenticateWebsocket sends an authentication message to the websocket
@@ -774,14 +782,18 @@ func (c *Coinbene) GetHistoricCandles(pair currency.Pair, a asset.Item, start, e
}
}
+ formattedPair, err := c.FormatExchangeCurrency(pair, asset.PerpetualSwap)
+ if err != nil {
+ return kline.Item{}, err
+ }
+
var candles CandleResponse
- var err error
if a == asset.PerpetualSwap {
- candles, err = c.GetSwapKlines(c.FormatExchangeCurrency(pair, asset.PerpetualSwap).String(),
+ candles, err = c.GetSwapKlines(formattedPair.String(),
start, end,
c.FormatExchangeKlineInterval(interval))
} else {
- candles, err = c.GetKlines(c.FormatExchangeCurrency(pair, asset.Spot).String(),
+ candles, err = c.GetKlines(formattedPair.String(),
start, end,
c.FormatExchangeKlineInterval(interval))
}
diff --git a/exchanges/coinut/coinut.go b/exchanges/coinut/coinut.go
index 9c77dde1..c4e6916f 100644
--- a/exchanges/coinut/coinut.go
+++ b/exchanges/coinut/coinut.go
@@ -17,7 +17,6 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
)
@@ -42,6 +41,8 @@ const (
coinutStatusOK = "OK"
coinutMaxNonce = 16777215 // See https://github.com/coinut/api/wiki/Websocket-API#nonce
+
+ wsRateLimitInMilliseconds = 33
)
var (
@@ -52,7 +53,6 @@ var (
// COINUT is the overarching type across the coinut package
type COINUT struct {
exchange.Base
- WebsocketConn *wshandler.WebsocketConnection
instrumentMap instrumentMap
}
diff --git a/exchanges/coinut/coinut_test.go b/exchanges/coinut/coinut_test.go
index 6e95e983..b1f31fb0 100644
--- a/exchanges/coinut/coinut_test.go
+++ b/exchanges/coinut/coinut_test.go
@@ -14,7 +14,7 @@ import (
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -43,6 +43,7 @@ func TestMain(m *testing.M) {
coinutCfg.API.AuthenticatedWebsocketSupport = true
coinutCfg.API.Credentials.Key = apiKey
coinutCfg.API.Credentials.ClientID = clientID
+ c.Websocket = sharedtestvalues.NewTestWebsocket()
err = c.Setup(coinutCfg)
if err != nil {
log.Fatal("Coinut setup error", err)
@@ -51,8 +52,6 @@ func TestMain(m *testing.M) {
if err != nil {
log.Fatal("Coinut setup error ", err)
}
- c.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- c.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
os.Exit(m.Run())
}
@@ -62,27 +61,17 @@ func setupWSTestAuth(t *testing.T) {
}
if !c.Websocket.IsEnabled() && !c.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
- t.Skip(wshandler.WebsocketNotEnabled)
+ t.Skip(stream.WebsocketNotEnabled)
}
if areTestAPIKeysSet() {
c.Websocket.SetCanUseAuthenticatedEndpoints(true)
}
- c.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: c.Name,
- URL: coinutWebsocketURL,
- Verbose: c.Verbose,
- RateLimit: coinutWebsocketRateLimit,
- ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
- ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
- }
var dialer websocket.Dialer
- err := c.WebsocketConn.Dial(&dialer, http.Header{})
+ err := c.Websocket.Conn.Dial(&dialer, http.Header{})
if err != nil {
t.Fatal(err)
}
- c.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- c.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
go c.wsReadData()
err = c.wsAuthenticate()
if err != nil {
diff --git a/exchanges/coinut/coinut_websocket.go b/exchanges/coinut/coinut_websocket.go
index bd271d12..f7bc0740 100644
--- a/exchanges/coinut/coinut_websocket.go
+++ b/exchanges/coinut/coinut_websocket.go
@@ -10,15 +10,16 @@ import (
"time"
"github.com/gorilla/websocket"
+ "github.com/thrasher-corp/gocryptotrader/common"
"github.com/thrasher-corp/gocryptotrader/common/crypto"
"github.com/thrasher-corp/gocryptotrader/currency"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wsorderbook"
"github.com/thrasher-corp/gocryptotrader/log"
)
@@ -39,10 +40,10 @@ var (
// WsConnect intiates a websocket connection
func (c *COINUT) WsConnect() error {
if !c.Websocket.IsEnabled() || !c.IsEnabled() {
- return errors.New(wshandler.WebsocketNotEnabled)
+ return errors.New(stream.WebsocketNotEnabled)
}
var dialer websocket.Dialer
- err := c.WebsocketConn.Dial(&dialer, http.Header{})
+ err := c.Websocket.Conn.Dial(&dialer, http.Header{})
if err != nil {
return err
}
@@ -59,7 +60,15 @@ func (c *COINUT) WsConnect() error {
c.Websocket.SetCanUseAuthenticatedEndpoints(false)
log.Error(log.WebsocketMgr, err)
}
- c.GenerateDefaultSubscriptions()
+ subs, err := c.GenerateDefaultSubscriptions()
+ if err != nil {
+ return err
+ }
+
+ err = c.Websocket.SubscribeToChannels(subs)
+ if err != nil {
+ return err
+ }
// define bi-directional communication
channels = make(map[string]chan []byte)
@@ -71,61 +80,49 @@ func (c *COINUT) WsConnect() error {
// wsReadData receives and passes on websocket messages for processing
func (c *COINUT) wsReadData() {
c.Websocket.Wg.Add(1)
-
- defer func() {
- c.Websocket.Wg.Done()
- }()
+ defer c.Websocket.Wg.Done()
for {
- select {
- case <-c.Websocket.ShutdownC:
+ resp := c.Websocket.Conn.ReadMessage()
+ if resp.Raw == nil {
return
+ }
- default:
- resp, err := c.WebsocketConn.ReadMessage()
+ if strings.HasPrefix(string(resp.Raw), "[") {
+ var incoming []wsResponse
+ err := json.Unmarshal(resp.Raw, &incoming)
if err != nil {
- c.Websocket.ReadMessageErrors <- err
- return
+ c.Websocket.DataHandler <- err
+ continue
}
- c.Websocket.TrafficAlert <- struct{}{}
-
- if strings.HasPrefix(string(resp.Raw), "[") {
- var incoming []wsResponse
- err = json.Unmarshal(resp.Raw, &incoming)
+ for i := range incoming {
+ if incoming[i].Nonce > 0 {
+ if c.Websocket.Match.IncomingWithData(incoming[i].Nonce, resp.Raw) {
+ break
+ }
+ }
+ var individualJSON []byte
+ individualJSON, err = json.Marshal(incoming[i])
if err != nil {
c.Websocket.DataHandler <- err
continue
}
- for i := range incoming {
- if incoming[i].Nonce > 0 {
- if c.WebsocketConn.IsIDWaitingForResponse(incoming[i].Nonce) {
- c.WebsocketConn.SetResponseIDAndData(incoming[i].Nonce, resp.Raw)
- break
- }
- }
- var individualJSON []byte
- individualJSON, err = json.Marshal(incoming[i])
- if err != nil {
- c.Websocket.DataHandler <- err
- continue
- }
- err = c.wsHandleData(individualJSON)
- if err != nil {
- c.Websocket.DataHandler <- err
- }
- }
- } else {
- var incoming wsResponse
- err = json.Unmarshal(resp.Raw, &incoming)
- if err != nil {
- c.Websocket.DataHandler <- err
- continue
- }
- err = c.wsHandleData(resp.Raw)
+ err = c.wsHandleData(individualJSON)
if err != nil {
c.Websocket.DataHandler <- err
}
}
+ } else {
+ var incoming wsResponse
+ err := json.Unmarshal(resp.Raw, &incoming)
+ if err != nil {
+ c.Websocket.DataHandler <- err
+ continue
+ }
+ err = c.wsHandleData(resp.Raw)
+ if err != nil {
+ c.Websocket.DataHandler <- err
+ }
}
}
}
@@ -153,11 +150,16 @@ func (c *COINUT) wsHandleData(respRaw []byte) error {
return err
}
if strings.Contains(string(respRaw), "client_ord_id") {
- if c.WebsocketConn.IsIDWaitingForResponse(incoming.Nonce) {
- c.WebsocketConn.SetResponseIDAndData(incoming.Nonce, respRaw)
+ if c.Websocket.Match.IncomingWithData(incoming.Nonce, respRaw) {
return nil
}
}
+
+ format, err := c.GetPairFormat(asset.Spot, true)
+ if err != nil {
+ return err
+ }
+
switch incoming.Reply {
case "hb":
channels["hb"] <- respRaw
@@ -167,9 +169,16 @@ func (c *COINUT) wsHandleData(respRaw []byte) error {
if err != nil {
return err
}
+
+ var endpointFailure []byte
if login.APIKey != c.API.Credentials.Key {
- c.API.AuthenticatedWebsocketSupport = false
+ endpointFailure = []byte("failed to authenticate")
}
+
+ if c.Websocket.Match.IncomingWithData(login.Nonce, endpointFailure) {
+ return nil
+ }
+
case "user_balance":
var userBalance WsUserBalanceResponse
err := json.Unmarshal(respRaw, &userBalance)
@@ -231,7 +240,18 @@ func (c *COINUT) wsHandleData(respRaw []byte) error {
if err != nil {
return err
}
+ pairs, err := c.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return err
+ }
currencyPair := c.instrumentMap.LookupInstrument(wsTicker.InstID)
+ p, err := currency.NewPairFromFormattedPairs(currencyPair,
+ pairs,
+ format)
+ if err != nil {
+ return err
+ }
+
c.Websocket.DataHandler <- &ticker.Price{
ExchangeName: c.Name,
Volume: wsTicker.Volume24,
@@ -243,9 +263,7 @@ func (c *COINUT) wsHandleData(respRaw []byte) error {
Last: wsTicker.Last,
LastUpdated: time.Unix(0, wsTicker.Timestamp),
AssetType: asset.Spot,
- Pair: currency.NewPairFromFormattedPairs(currencyPair,
- c.GetEnabledPairs(asset.Spot),
- c.GetPairFormat(asset.Spot, true)),
+ Pair: p,
}
case "inst_order_book":
var orderbookSnapshot WsOrderbookSnapshot
@@ -257,14 +275,6 @@ func (c *COINUT) wsHandleData(respRaw []byte) error {
if err != nil {
return err
}
- currencyPair := c.instrumentMap.LookupInstrument(orderbookSnapshot.InstID)
- c.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
- Exchange: c.Name,
- Asset: asset.Spot,
- Pair: currency.NewPairFromFormattedPairs(currencyPair,
- c.GetEnabledPairs(asset.Spot),
- c.GetPairFormat(asset.Spot, true)),
- }
case "inst_order_book_update":
var orderbookUpdate WsOrderbookUpdate
err := json.Unmarshal(respRaw, &orderbookUpdate)
@@ -275,14 +285,6 @@ func (c *COINUT) wsHandleData(respRaw []byte) error {
if err != nil {
return err
}
- currencyPair := c.instrumentMap.LookupInstrument(orderbookUpdate.InstID)
- c.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
- Exchange: c.Name,
- Asset: asset.Spot,
- Pair: currency.NewPairFromFormattedPairs(currencyPair,
- c.GetEnabledPairs(asset.Spot),
- c.GetPairFormat(asset.Spot, true)),
- }
case "inst_trade":
var tradeSnap WsTradeSnapshot
err := json.Unmarshal(respRaw, &tradeSnap)
@@ -296,7 +298,19 @@ func (c *COINUT) wsHandleData(respRaw []byte) error {
if err != nil {
return err
}
+
+ pairs, err := c.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return err
+ }
currencyPair := c.instrumentMap.LookupInstrument(tradeUpdate.InstID)
+ p, err := currency.NewPairFromFormattedPairs(currencyPair,
+ pairs,
+ format)
+ if err != nil {
+ return err
+ }
+
tSide, err := order.StringToOrderSide(tradeUpdate.Side)
if err != nil {
c.Websocket.DataHandler <- order.ClassificationError{
@@ -304,15 +318,14 @@ func (c *COINUT) wsHandleData(respRaw []byte) error {
Err: err,
}
}
- c.Websocket.DataHandler <- wshandler.TradeData{
- Timestamp: time.Unix(tradeUpdate.Timestamp, 0),
- CurrencyPair: currency.NewPairFromFormattedPairs(currencyPair,
- c.GetEnabledPairs(asset.Spot),
- c.GetPairFormat(asset.Spot, true)),
- AssetType: asset.Spot,
- Exchange: c.Name,
- Price: tradeUpdate.Price,
- Side: tSide,
+
+ c.Websocket.DataHandler <- stream.TradeData{
+ Timestamp: time.Unix(tradeUpdate.Timestamp, 0),
+ CurrencyPair: p,
+ AssetType: asset.Spot,
+ Exchange: c.Name,
+ Price: tradeUpdate.Price,
+ Side: tSide,
}
case "order_filled", "order_rejected", "order_accepted":
var orderContainer wsOrderContainer
@@ -326,7 +339,7 @@ func (c *COINUT) wsHandleData(respRaw []byte) error {
}
c.Websocket.DataHandler <- o
default:
- c.Websocket.DataHandler <- wshandler.UnhandledMessageWarning{Message: c.Name + wshandler.UnhandledMessage + string(respRaw)}
+ c.Websocket.DataHandler <- stream.UnhandledMessageWarning{Message: c.Name + stream.UnhandledMessage + string(respRaw)}
return nil
}
return nil
@@ -444,7 +457,7 @@ func (c *COINUT) WsGetInstruments() (Instruments, error) {
SecurityType: strings.ToUpper(asset.Spot.String()),
Nonce: getNonce(),
}
- resp, err := c.WebsocketConn.SendMessageReturnResponse(request.Nonce, request)
+ resp, err := c.Websocket.Conn.SendMessageReturnResponse(request.Nonce, request)
if err != nil {
return list, err
}
@@ -482,11 +495,25 @@ func (c *COINUT) WsProcessOrderbookSnapshot(ob *WsOrderbookSnapshot) error {
var newOrderBook orderbook.Base
newOrderBook.Asks = asks
newOrderBook.Bids = bids
- newOrderBook.Pair = currency.NewPairFromFormattedPairs(
+
+ pairs, err := c.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return err
+ }
+
+ format, err := c.GetPairFormat(asset.Spot, true)
+ if err != nil {
+ return err
+ }
+
+ newOrderBook.Pair, err = currency.NewPairFromFormattedPairs(
c.instrumentMap.LookupInstrument(ob.InstID),
- c.GetEnabledPairs(asset.Spot),
- c.GetPairFormat(asset.Spot, true),
- )
+ pairs,
+ format)
+ if err != nil {
+ return err
+ }
+
newOrderBook.AssetType = asset.Spot
newOrderBook.ExchangeName = c.Name
@@ -495,12 +522,25 @@ func (c *COINUT) WsProcessOrderbookSnapshot(ob *WsOrderbookSnapshot) error {
// WsProcessOrderbookUpdate process an orderbook update
func (c *COINUT) WsProcessOrderbookUpdate(update *WsOrderbookUpdate) error {
- p := currency.NewPairFromFormattedPairs(
+ pairs, err := c.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return err
+ }
+
+ format, err := c.GetPairFormat(asset.Spot, true)
+ if err != nil {
+ return err
+ }
+
+ p, err := currency.NewPairFromFormattedPairs(
c.instrumentMap.LookupInstrument(update.InstID),
- c.GetEnabledPairs(asset.Spot),
- c.GetPairFormat(asset.Spot, true),
- )
- bufferUpdate := &wsorderbook.WebsocketOrderbookUpdate{
+ pairs,
+ format)
+ if err != nil {
+ return err
+ }
+
+ bufferUpdate := &buffer.Update{
Pair: p,
UpdateID: update.TransID,
Asset: asset.Spot,
@@ -514,67 +554,109 @@ func (c *COINUT) WsProcessOrderbookUpdate(update *WsOrderbookUpdate) error {
}
// GenerateDefaultSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions()
-func (c *COINUT) GenerateDefaultSubscriptions() {
+func (c *COINUT) GenerateDefaultSubscriptions() ([]stream.ChannelSubscription, error) {
var channels = []string{"inst_tick", "inst_order_book"}
- var subscriptions []wshandler.WebsocketChannelSubscription
- enabledCurrencies := c.GetEnabledPairs(asset.Spot)
+ var subscriptions []stream.ChannelSubscription
+ enabledCurrencies, err := c.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return nil, err
+ }
for i := range channels {
for j := range enabledCurrencies {
- subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
Channel: channels[i],
Currency: enabledCurrencies[j],
+ Asset: asset.Spot,
})
}
}
- c.Websocket.SubscribeToChannels(subscriptions)
+ return subscriptions, nil
}
// Subscribe sends a websocket message to receive data from the channel
-func (c *COINUT) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
- subscribe := wsRequest{
- Request: channelToSubscribe.Channel,
- InstrumentID: c.instrumentMap.LookupID(c.FormatExchangeCurrency(channelToSubscribe.Currency,
- asset.Spot).String()),
- Subscribe: true,
- Nonce: getNonce(),
+func (c *COINUT) Subscribe(channelsToSubscribe []stream.ChannelSubscription) error {
+ var errs common.Errors
+ for i := range channelsToSubscribe {
+ fpair, err := c.FormatExchangeCurrency(channelsToSubscribe[i].Currency, asset.Spot)
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+
+ subscribe := wsRequest{
+ Request: channelsToSubscribe[i].Channel,
+ InstrumentID: c.instrumentMap.LookupID(fpair.String()),
+ Subscribe: true,
+ Nonce: getNonce(),
+ }
+ err = c.Websocket.Conn.SendJSONMessage(subscribe)
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ c.Websocket.AddSuccessfulSubscriptions(channelsToSubscribe[i])
}
- return c.WebsocketConn.SendJSONMessage(subscribe)
+ if errs != nil {
+ return errs
+ }
+ return nil
}
// Unsubscribe sends a websocket message to stop receiving data from the channel
-func (c *COINUT) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
- subscribe := wsRequest{
- Request: channelToSubscribe.Channel,
- InstrumentID: c.instrumentMap.LookupID(c.FormatExchangeCurrency(channelToSubscribe.Currency,
- asset.Spot).String()),
- Subscribe: false,
- Nonce: getNonce(),
+func (c *COINUT) Unsubscribe(channelToUnsubscribe []stream.ChannelSubscription) error {
+ var errs common.Errors
+ for i := range channelToUnsubscribe {
+ fpair, err := c.FormatExchangeCurrency(channelToUnsubscribe[i].Currency, asset.Spot)
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+
+ subscribe := wsRequest{
+ Request: channelToUnsubscribe[i].Channel,
+ InstrumentID: c.instrumentMap.LookupID(fpair.String()),
+ Subscribe: false,
+ Nonce: getNonce(),
+ }
+ resp, err := c.Websocket.Conn.SendMessageReturnResponse(subscribe.Nonce,
+ subscribe)
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ var response map[string]interface{}
+ err = json.Unmarshal(resp, &response)
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ if response["status"].([]interface{})[0] != "OK" {
+ errs = append(errs, fmt.Errorf("%v unsubscribe failed for channel %v",
+ c.Name,
+ channelToUnsubscribe[i].Channel))
+ continue
+ }
+ c.Websocket.RemoveSuccessfulUnsubscriptions(channelToUnsubscribe[i])
}
- resp, err := c.WebsocketConn.SendMessageReturnResponse(subscribe.Nonce, subscribe)
- if err != nil {
- return err
- }
- var response map[string]interface{}
- err = json.Unmarshal(resp, &response)
- if err != nil {
- return err
- }
- if response["status"].([]interface{})[0] != "OK" {
- return fmt.Errorf("%v unsubscribe failed for channel %v", c.Name, channelToSubscribe.Channel)
+ if errs != nil {
+ return errs
}
return nil
}
func (c *COINUT) wsAuthenticate() error {
if !c.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
- return fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", c.Name)
+ return fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled",
+ c.Name)
}
timestamp := time.Now().Unix()
nonce := getNonce()
payload := c.API.Credentials.ClientID + "|" +
strconv.FormatInt(timestamp, 10) + "|" +
strconv.FormatInt(nonce, 10)
- hmac := crypto.GetHMAC(crypto.HashSHA256, []byte(payload), []byte(c.API.Credentials.Key))
+ hmac := crypto.GetHMAC(crypto.HashSHA256,
+ []byte(payload),
+ []byte(c.API.Credentials.Key))
loginRequest := struct {
Request string `json:"request"`
Username string `json:"username"`
@@ -589,18 +671,14 @@ func (c *COINUT) wsAuthenticate() error {
Timestamp: timestamp,
}
- resp, err := c.WebsocketConn.SendMessageReturnResponse(loginRequest.Nonce, loginRequest)
+ resp, err := c.Websocket.Conn.SendMessageReturnResponse(loginRequest.Nonce,
+ loginRequest)
if err != nil {
return err
}
- var response map[string]interface{}
- err = json.Unmarshal(resp, &response)
- if err != nil {
- return err
- }
- if response["status"].([]interface{})[0] != "OK" {
+ if resp != nil {
c.Websocket.SetCanUseAuthenticatedEndpoints(false)
- return fmt.Errorf("%v failed to authenticate", c.Name)
+ return fmt.Errorf("%v %s", c.Name, resp)
}
c.Websocket.SetCanUseAuthenticatedEndpoints(true)
return nil
@@ -614,7 +692,8 @@ func (c *COINUT) wsGetAccountBalance() (*UserBalance, error) {
Request: "user_balance",
Nonce: getNonce(),
}
- resp, err := c.WebsocketConn.SendMessageReturnResponse(accBalance.Nonce, accBalance)
+ resp, err := c.Websocket.Conn.SendMessageReturnResponse(accBalance.Nonce,
+ accBalance)
if err != nil {
return nil, err
}
@@ -633,11 +712,16 @@ func (c *COINUT) wsSubmitOrder(o *WsSubmitOrderParameters) (*order.Detail, error
if !c.Websocket.CanUseAuthenticatedEndpoints() {
return nil, fmt.Errorf("%v not authorised to submit order", c.Name)
}
- curr := c.FormatExchangeCurrency(o.Currency, asset.Spot).String()
+
+ curr, err := c.FormatExchangeCurrency(o.Currency, asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+
var orderSubmissionRequest WsSubmitOrderRequest
orderSubmissionRequest.Request = "new_order"
orderSubmissionRequest.Nonce = getNonce()
- orderSubmissionRequest.InstrumentID = c.instrumentMap.LookupID(curr)
+ orderSubmissionRequest.InstrumentID = c.instrumentMap.LookupID(curr.String())
orderSubmissionRequest.Quantity = o.Amount
orderSubmissionRequest.Price = o.Price
orderSubmissionRequest.Side = string(o.Side)
@@ -645,7 +729,8 @@ func (c *COINUT) wsSubmitOrder(o *WsSubmitOrderParameters) (*order.Detail, error
if o.OrderID > 0 {
orderSubmissionRequest.OrderID = o.OrderID
}
- resp, err := c.WebsocketConn.SendMessageReturnResponse(orderSubmissionRequest.Nonce, orderSubmissionRequest)
+ resp, err := c.Websocket.Conn.SendMessageReturnResponse(orderSubmissionRequest.Nonce,
+ orderSubmissionRequest)
if err != nil {
return nil, err
}
@@ -666,25 +751,31 @@ func (c *COINUT) wsSubmitOrders(orders []WsSubmitOrderParameters) ([]order.Detai
var errs []error
var ordersResponse []order.Detail
if !c.Websocket.CanUseAuthenticatedEndpoints() {
- errs = append(errs, fmt.Errorf("%v not authorised to submit orders", c.Name))
+ errs = append(errs, fmt.Errorf("%v not authorised to submit orders",
+ c.Name))
return nil, errs
}
orderRequest := WsSubmitOrdersRequest{}
for i := range orders {
- curr := c.FormatExchangeCurrency(orders[i].Currency, asset.Spot).String()
+ curr, err := c.FormatExchangeCurrency(orders[i].Currency, asset.Spot)
+ if err != nil {
+ return nil, []error{err}
+ }
+
orderRequest.Orders = append(orderRequest.Orders,
WsSubmitOrdersRequestData{
Quantity: orders[i].Amount,
Price: orders[i].Price,
Side: string(orders[i].Side),
- InstrumentID: c.instrumentMap.LookupID(curr),
+ InstrumentID: c.instrumentMap.LookupID(curr.String()),
ClientOrderID: i + 1,
})
}
orderRequest.Nonce = getNonce()
orderRequest.Request = "new_orders"
- resp, err := c.WebsocketConn.SendMessageReturnResponse(orderRequest.Nonce, orderRequest)
+ resp, err := c.Websocket.Conn.SendMessageReturnResponse(orderRequest.Nonce,
+ orderRequest)
if err != nil {
errs = append(errs, err)
return nil, errs
@@ -710,14 +801,16 @@ func (c *COINUT) wsSubmitOrders(orders []WsSubmitOrderParameters) ([]order.Detai
func (c *COINUT) wsGetOpenOrders(curr string) (*WsUserOpenOrdersResponse, error) {
var response *WsUserOpenOrdersResponse
if !c.Websocket.CanUseAuthenticatedEndpoints() {
- return response, fmt.Errorf("%v not authorised to get open orders", c.Name)
+ return response, fmt.Errorf("%v not authorised to get open orders",
+ c.Name)
}
var openOrdersRequest WsGetOpenOrdersRequest
openOrdersRequest.Request = "user_open_orders"
openOrdersRequest.Nonce = getNonce()
openOrdersRequest.InstrumentID = c.instrumentMap.LookupID(curr)
- resp, err := c.WebsocketConn.SendMessageReturnResponse(openOrdersRequest.Nonce, openOrdersRequest)
+ resp, err := c.Websocket.Conn.SendMessageReturnResponse(openOrdersRequest.Nonce,
+ openOrdersRequest)
if err != nil {
return response, err
}
@@ -738,14 +831,20 @@ func (c *COINUT) wsCancelOrder(cancellation *WsCancelOrderParameters) (*CancelOr
if !c.Websocket.CanUseAuthenticatedEndpoints() {
return response, fmt.Errorf("%v not authorised to cancel order", c.Name)
}
- curr := c.FormatExchangeCurrency(cancellation.Currency, asset.Spot).String()
+
+ curr, err := c.FormatExchangeCurrency(cancellation.Currency, asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+
var cancellationRequest WsCancelOrderRequest
cancellationRequest.Request = "cancel_order"
- cancellationRequest.InstrumentID = c.instrumentMap.LookupID(curr)
+ cancellationRequest.InstrumentID = c.instrumentMap.LookupID(curr.String())
cancellationRequest.OrderID = cancellation.OrderID
cancellationRequest.Nonce = getNonce()
- resp, err := c.WebsocketConn.SendMessageReturnResponse(cancellationRequest.Nonce, cancellationRequest)
+ resp, err := c.Websocket.Conn.SendMessageReturnResponse(cancellationRequest.Nonce,
+ cancellationRequest)
if err != nil {
return response, err
}
@@ -771,16 +870,23 @@ func (c *COINUT) wsCancelOrders(cancellations []WsCancelOrderParameters) (*Cance
}
var cancelOrderRequest WsCancelOrdersRequest
for i := range cancellations {
- curr := c.FormatExchangeCurrency(cancellations[i].Currency, asset.Spot).String()
- cancelOrderRequest.Entries = append(cancelOrderRequest.Entries, WsCancelOrdersRequestEntry{
- InstID: c.instrumentMap.LookupID(curr),
- OrderID: cancellations[i].OrderID,
- })
+ var curr currency.Pair
+ curr, err = c.FormatExchangeCurrency(cancellations[i].Currency,
+ asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+ cancelOrderRequest.Entries = append(cancelOrderRequest.Entries,
+ WsCancelOrdersRequestEntry{
+ InstID: c.instrumentMap.LookupID(curr.String()),
+ OrderID: cancellations[i].OrderID,
+ })
}
cancelOrderRequest.Request = "cancel_orders"
cancelOrderRequest.Nonce = getNonce()
- resp, err := c.WebsocketConn.SendMessageReturnResponse(cancelOrderRequest.Nonce, cancelOrderRequest)
+ resp, err := c.Websocket.Conn.SendMessageReturnResponse(cancelOrderRequest.Nonce,
+ cancelOrderRequest)
if err != nil {
return response, err
}
@@ -794,17 +900,24 @@ func (c *COINUT) wsCancelOrders(cancellations []WsCancelOrderParameters) (*Cance
func (c *COINUT) wsGetTradeHistory(p currency.Pair, start, limit int64) (*WsTradeHistoryResponse, error) {
var response *WsTradeHistoryResponse
if !c.Websocket.CanUseAuthenticatedEndpoints() {
- return response, fmt.Errorf("%v not authorised to get trade history", c.Name)
+ return response, fmt.Errorf("%v not authorised to get trade history",
+ c.Name)
}
- curr := c.FormatExchangeCurrency(p, asset.Spot).String()
+
+ curr, err := c.FormatExchangeCurrency(p, asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+
var request WsTradeHistoryRequest
request.Request = "trade_history"
- request.InstID = c.instrumentMap.LookupID(curr)
+ request.InstID = c.instrumentMap.LookupID(curr.String())
request.Nonce = getNonce()
request.Start = start
request.Limit = limit
- resp, err := c.WebsocketConn.SendMessageReturnResponse(request.Nonce, request)
+ resp, err := c.Websocket.Conn.SendMessageReturnResponse(request.Nonce,
+ request)
if err != nil {
return response, err
}
diff --git a/exchanges/coinut/coinut_wrapper.go b/exchanges/coinut/coinut_wrapper.go
index fed59a71..51b3b59a 100644
--- a/exchanges/coinut/coinut_wrapper.go
+++ b/exchanges/coinut/coinut_wrapper.go
@@ -20,8 +20,8 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -57,18 +57,11 @@ func (c *COINUT) SetDefaults() {
c.API.CredentialsValidator.RequiresKey = true
c.API.CredentialsValidator.RequiresClientID = true
- c.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- },
- UseGlobalFormat: true,
- RequestFormat: ¤cy.PairFormat{
- Uppercase: true,
- },
- ConfigFormat: ¤cy.PairFormat{
- Uppercase: true,
- Delimiter: "-",
- },
+ requestFmt := ¤cy.PairFormat{Uppercase: true}
+ configFmt := ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter}
+ err := c.SetGlobalPairsManager(requestFmt, configFmt, asset.Spot)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
}
c.Features = exchange.Features{
@@ -122,7 +115,7 @@ func (c *COINUT) SetDefaults() {
c.API.Endpoints.URLDefault = coinutAPIURL
c.API.Endpoints.URL = c.API.Endpoints.URLDefault
c.API.Endpoints.WebsocketURL = coinutWebsocketURL
- c.Websocket = wshandler.New()
+ c.Websocket = stream.New()
c.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
c.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
c.WebsocketOrderbookBufferLimit = exchange.DefaultWebsocketOrderbookBufferLimit
@@ -141,41 +134,33 @@ func (c *COINUT) Setup(exch *config.ExchangeConfig) error {
return err
}
- err = c.Websocket.Setup(
- &wshandler.WebsocketSetup{
- Enabled: exch.Features.Enabled.Websocket,
- Verbose: exch.Verbose,
- AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
- WebsocketTimeout: exch.WebsocketTrafficTimeout,
- DefaultURL: coinutWebsocketURL,
- ExchangeName: exch.Name,
- RunningURL: exch.API.Endpoints.WebsocketURL,
- Connector: c.WsConnect,
- Subscriber: c.Subscribe,
- UnSubscriber: c.Unsubscribe,
- Features: &c.Features.Supports.WebsocketCapabilities,
- })
+ err = c.Websocket.Setup(&stream.WebsocketSetup{
+ Enabled: exch.Features.Enabled.Websocket,
+ Verbose: exch.Verbose,
+ AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
+ WebsocketTimeout: exch.WebsocketTrafficTimeout,
+ DefaultURL: coinutWebsocketURL,
+ ExchangeName: exch.Name,
+ RunningURL: exch.API.Endpoints.WebsocketURL,
+ Connector: c.WsConnect,
+ Subscriber: c.Subscribe,
+ UnSubscriber: c.Unsubscribe,
+ GenerateSubscriptions: c.GenerateDefaultSubscriptions,
+ Features: &c.Features.Supports.WebsocketCapabilities,
+ OrderbookBufferLimit: exch.WebsocketOrderbookBufferLimit,
+ BufferEnabled: true,
+ SortBuffer: true,
+ SortBufferByUpdateIDs: true,
+ })
if err != nil {
return err
}
- c.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: c.Name,
- URL: c.Websocket.GetWebsocketURL(),
- ProxyURL: c.Websocket.GetProxyAddress(),
- Verbose: c.Verbose,
+ return c.Websocket.SetupNewConnection(stream.ConnectionSetup{
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
- }
-
- c.Websocket.Orderbook.Setup(
- exch.WebsocketOrderbookBufferLimit,
- true,
- true,
- true,
- false,
- exch.Name)
- return nil
+ RateLimit: wsRateLimitInMilliseconds,
+ })
}
// Start starts the COINUT go routine
@@ -195,21 +180,55 @@ func (c *COINUT) Run() {
}
forceUpdate := false
- delim := c.GetPairFormat(asset.Spot, false).Delimiter
- if !common.StringDataContains(c.CurrencyPairs.GetPairs(asset.Spot,
- true).Strings(), delim) ||
- !common.StringDataContains(c.CurrencyPairs.GetPairs(asset.Spot,
- false).Strings(), delim) {
- enabledPairs := currency.NewPairsFromStrings(
- []string{currency.LTC.String() + delim + currency.USDT.String()},
- )
- log.Warn(log.ExchangeSys,
- "Enabled pairs for Coinut reset due to config upgrade, please enable the ones you would like to use again")
- forceUpdate = true
+ format, err := c.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update currencies. Err: %s\n",
+ c.Name,
+ err)
+ return
+ }
- err := c.UpdatePairs(enabledPairs, asset.Spot, true, true)
+ enabled, err := c.CurrencyPairs.GetPairs(asset.Spot, true)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update currencies. Err: %s\n",
+ c.Name,
+ err)
+ return
+ }
+ avail, err := c.CurrencyPairs.GetPairs(asset.Spot, false)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update currencies. Err: %s\n",
+ c.Name,
+ err)
+ return
+ }
+
+ if !common.StringDataContains(enabled.Strings(), format.Delimiter) ||
+ !common.StringDataContains(avail.Strings(), format.Delimiter) {
+ var p currency.Pairs
+ p, err = currency.NewPairsFromStrings([]string{currency.LTC.String() +
+ format.Delimiter +
+ currency.USDT.String()})
if err != nil {
- log.Errorf(log.ExchangeSys, "%s failed to update currencies. Err: %s\n", c.Name, err)
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update currencies. Err: %s\n",
+ c.Name,
+ err)
+ } else {
+ log.Warn(log.ExchangeSys,
+ "Enabled pairs for Coinut reset due to config upgrade, please enable the ones you would like to use again")
+ forceUpdate = true
+
+ err = c.UpdatePairs(p, asset.Spot, true, true)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update currencies. Err: %s\n",
+ c.Name,
+ err)
+ }
}
}
@@ -217,7 +236,7 @@ func (c *COINUT) Run() {
return
}
- err := c.UpdateTradablePairs(forceUpdate)
+ err = c.UpdateTradablePairs(forceUpdate)
if err != nil {
log.Errorf(log.ExchangeSys, "%s failed to update tradable pairs. Err: %s", c.Name, err)
}
@@ -239,11 +258,17 @@ func (c *COINUT) FetchTradablePairs(asset asset.Item) ([]string, error) {
return nil, err
}
}
+
+ format, err := c.GetPairFormat(asset, false)
+ if err != nil {
+ return nil, err
+ }
+
instruments = resp.Instruments
var pairs []string
for i := range instruments {
c.instrumentMap.Seed(instruments[i][0].Base+instruments[i][0].Quote, instruments[i][0].InstrumentID)
- p := instruments[i][0].Base + c.GetPairFormat(asset, false).Delimiter + instruments[i][0].Quote
+ p := instruments[i][0].Base + format.Delimiter + instruments[i][0].Quote
pairs = append(pairs, p)
}
@@ -258,8 +283,11 @@ func (c *COINUT) UpdateTradablePairs(forceUpdate bool) error {
return err
}
- return c.UpdatePairs(currency.NewPairsFromStrings(pairs),
- asset.Spot, false, forceUpdate)
+ p, err := currency.NewPairsFromStrings(pairs)
+ if err != nil {
+ return err
+ }
+ return c.UpdatePairs(p, asset.Spot, false, forceUpdate)
}
// UpdateAccountInfo retrieves balances for all enabled currencies for the
@@ -365,35 +393,39 @@ func (c *COINUT) FetchAccountInfo() (account.Holdings, error) {
// UpdateTicker updates and returns the ticker for a currency pair
func (c *COINUT) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
- tickerPrice := new(ticker.Price)
err := c.loadInstrumentsIfNotLoaded()
if err != nil {
- return tickerPrice, err
+ return nil, err
}
- instID := c.instrumentMap.LookupID(c.FormatExchangeCurrency(p,
- assetType).String())
+ fpair, err := c.FormatExchangeCurrency(p, assetType)
+ if err != nil {
+ return nil, err
+ }
+
+ instID := c.instrumentMap.LookupID(fpair.String())
if instID == 0 {
- return tickerPrice, errors.New("unable to lookup instrument ID")
+ return nil, errors.New("unable to lookup instrument ID")
}
var tick Ticker
tick, err = c.GetInstrumentTicker(instID)
if err != nil {
- return tickerPrice, err
+ return nil, err
}
- tickerPrice = &ticker.Price{
- Last: tick.Last,
- High: tick.High24,
- Low: tick.Low24,
- Bid: tick.HighestBuy,
- Ask: tick.LowestSell,
- Volume: tick.Volume24,
- Pair: p,
- LastUpdated: time.Unix(0, tick.Timestamp),
- }
- err = ticker.ProcessTicker(c.Name, tickerPrice, assetType)
+
+ err = ticker.ProcessTicker(&ticker.Price{
+ Last: tick.Last,
+ High: tick.High24,
+ Low: tick.Low24,
+ Bid: tick.HighestBuy,
+ Ask: tick.LowestSell,
+ Volume: tick.Volume24,
+ Pair: p,
+ LastUpdated: time.Unix(0, tick.Timestamp),
+ ExchangeName: c.Name,
+ AssetType: assetType})
if err != nil {
- return tickerPrice, err
+ return nil, err
}
return ticker.GetTicker(c.Name, p, assetType)
@@ -425,8 +457,12 @@ func (c *COINUT) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderb
return orderBook, err
}
- instID := c.instrumentMap.LookupID(c.FormatExchangeCurrency(p,
- assetType).String())
+ fpair, err := c.FormatExchangeCurrency(p, assetType)
+ if err != nil {
+ return nil, err
+ }
+
+ instID := c.instrumentMap.LookupID(fpair.String())
if instID == 0 {
return orderBook, errLookupInstrumentID
}
@@ -499,8 +535,12 @@ func (c *COINUT) SubmitOrder(o *order.Submit) (order.SubmitResponse, error) {
return submitOrderResponse, err
}
- currencyID := c.instrumentMap.LookupID(c.FormatExchangeCurrency(o.Pair,
- asset.Spot).String())
+ fpair, err := c.FormatExchangeCurrency(o.Pair, asset.Spot)
+ if err != nil {
+ return submitOrderResponse, err
+ }
+
+ currencyID := c.instrumentMap.LookupID(fpair.String())
if currencyID == 0 {
return submitOrderResponse, errLookupInstrumentID
}
@@ -555,10 +595,13 @@ func (c *COINUT) CancelOrder(o *order.Cancel) error {
return err
}
- currencyID := c.instrumentMap.LookupID(c.FormatExchangeCurrency(
- o.Pair,
- asset.Spot).String(),
- )
+ fpair, err := c.FormatExchangeCurrency(o.Pair, asset.Spot)
+ if err != nil {
+ return err
+ }
+
+ currencyID := c.instrumentMap.LookupID(fpair.String())
+
if c.Websocket.CanUseAuthenticatedWebsocketForWrapper() {
var resp *CancelOrdersResponse
resp, err = c.wsCancelOrder(&WsCancelOrderParameters{
@@ -599,7 +642,12 @@ func (c *COINUT) CancelAllOrders(details *order.Cancel) (order.CancelAllResponse
}
var ordersToCancel []WsCancelOrderParameters
for i := range openOrders.Orders {
- if openOrders.Orders[i].InstrumentID == c.instrumentMap.LookupID(c.FormatExchangeCurrency(details.Pair, asset.Spot).String()) {
+ var fpair currency.Pair
+ fpair, err = c.FormatExchangeCurrency(details.Pair, asset.Spot)
+ if err != nil {
+ return cancelAllOrdersResponse, err
+ }
+ if openOrders.Orders[i].InstrumentID == c.instrumentMap.LookupID(fpair.String()) {
ordersToCancel = append(ordersToCancel, WsCancelOrderParameters{
Currency: details.Pair,
OrderID: openOrders.Orders[i].OrderID,
@@ -619,7 +667,11 @@ func (c *COINUT) CancelAllOrders(details *order.Cancel) (order.CancelAllResponse
var allTheOrders []OrderResponse
ids := c.instrumentMap.GetInstrumentIDs()
for x := range ids {
- if ids[x] == c.instrumentMap.LookupID(c.FormatExchangeCurrency(details.Pair, asset.Spot).String()) {
+ fpair, err := c.FormatExchangeCurrency(details.Pair, asset.Spot)
+ if err != nil {
+ return cancelAllOrdersResponse, err
+ }
+ if ids[x] == c.instrumentMap.LookupID(fpair.String()) {
openOrders, err := c.GetOpenOrders(ids[x])
if err != nil {
return cancelAllOrdersResponse, err
@@ -682,11 +734,6 @@ func (c *COINUT) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdraw.
return nil, common.ErrFunctionNotSupported
}
-// GetWebsocket returns a pointer to the exchange websocket
-func (c *COINUT) GetWebsocket() (*wshandler.Websocket, error) {
- return c.Websocket, nil
-}
-
// GetFeeByType returns an estimate of fee based on type of transaction
func (c *COINUT) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if !c.AllowAuthenticatedRequest() && // Todo check connection status
@@ -706,7 +753,11 @@ func (c *COINUT) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
var currenciesToCheck []string
if len(req.Pairs) == 0 {
for i := range req.Pairs {
- currenciesToCheck = append(currenciesToCheck, c.FormatExchangeCurrency(req.Pairs[i], asset.Spot).String())
+ fpair, err := c.FormatExchangeCurrency(req.Pairs[i], asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+ currenciesToCheck = append(currenciesToCheck, fpair.String())
}
} else {
for k := range c.instrumentMap.Instruments {
@@ -720,10 +771,20 @@ func (c *COINUT) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
return nil, err
}
for i := range openOrders.Orders {
+ p, err := currency.NewPairFromString(currenciesToCheck[x])
+ if err != nil {
+ return nil, err
+ }
+
+ fpair, err := c.FormatExchangeCurrency(p, asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+
orders = append(orders, order.Detail{
Exchange: c.Name,
ID: strconv.FormatInt(openOrders.Orders[i].OrderID, 10),
- Pair: c.FormatExchangeCurrency(currency.NewPairFromString(currenciesToCheck[x]), asset.Spot),
+ Pair: fpair,
Side: order.Side(openOrders.Orders[i].Side),
Date: time.Unix(0, openOrders.Orders[i].Timestamp),
Status: order.Active,
@@ -737,15 +798,28 @@ func (c *COINUT) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
} else {
var instrumentsToUse []int64
for x := range req.Pairs {
- curr := c.FormatExchangeCurrency(req.Pairs[x],
- asset.Spot).String()
+ curr, err := c.FormatExchangeCurrency(req.Pairs[x],
+ asset.Spot)
+ if err != nil {
+ return nil, err
+ }
instrumentsToUse = append(instrumentsToUse,
- c.instrumentMap.LookupID(curr))
+ c.instrumentMap.LookupID(curr.String()))
}
if len(instrumentsToUse) == 0 {
instrumentsToUse = c.instrumentMap.GetInstrumentIDs()
}
+ pairs, err := c.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+
+ format, err := c.GetPairFormat(asset.Spot, true)
+ if err != nil {
+ return nil, err
+ }
+
for x := range instrumentsToUse {
openOrders, err := c.GetOpenOrders(instrumentsToUse[x])
if err != nil {
@@ -753,9 +827,13 @@ func (c *COINUT) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
}
for y := range openOrders.Orders {
curr := c.instrumentMap.LookupInstrument(instrumentsToUse[x])
- p := currency.NewPairFromFormattedPairs(curr,
- c.GetEnabledPairs(asset.Spot),
- c.GetPairFormat(asset.Spot, true))
+ p, err := currency.NewPairFromFormattedPairs(curr,
+ pairs,
+ format)
+ if err != nil {
+ return nil, err
+ }
+
orderSide := order.Side(strings.ToUpper(openOrders.Orders[y].Side))
orderDate := time.Unix(openOrders.Orders[y].Timestamp, 0)
orders = append(orders, order.Detail{
@@ -793,10 +871,15 @@ func (c *COINUT) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, e
}
for x := range trades.Trades {
curr := c.instrumentMap.LookupInstrument(trades.Trades[x].InstrumentID)
+ p, err := currency.NewPairFromString(curr)
+ if err != nil {
+ return nil, err
+ }
+
allOrders = append(allOrders, order.Detail{
Exchange: c.Name,
ID: strconv.FormatInt(trades.Trades[x].OrderID, 10),
- Pair: currency.NewPairFromString(curr),
+ Pair: p,
Side: order.Side(trades.Trades[x].Side),
Date: time.Unix(0, trades.Trades[x].Timestamp),
Status: order.Filled,
@@ -814,9 +897,13 @@ func (c *COINUT) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, e
} else {
var instrumentsToUse []int64
for x := range req.Pairs {
- curr := c.FormatExchangeCurrency(req.Pairs[x],
- asset.Spot).String()
- instrumentID := c.instrumentMap.LookupID(curr)
+ curr, err := c.FormatExchangeCurrency(req.Pairs[x],
+ asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+
+ instrumentID := c.instrumentMap.LookupID(curr.String())
if instrumentID > 0 {
instrumentsToUse = append(instrumentsToUse, instrumentID)
}
@@ -824,6 +911,17 @@ func (c *COINUT) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, e
if len(instrumentsToUse) == 0 {
instrumentsToUse = c.instrumentMap.GetInstrumentIDs()
}
+
+ pairs, err := c.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+
+ format, err := c.GetPairFormat(asset.Spot, true)
+ if err != nil {
+ return nil, err
+ }
+
for x := range instrumentsToUse {
orders, err := c.GetTradeHistory(instrumentsToUse[x], -1, -1)
if err != nil {
@@ -831,9 +929,13 @@ func (c *COINUT) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, e
}
for y := range orders.Trades {
curr := c.instrumentMap.LookupInstrument(instrumentsToUse[x])
- p := currency.NewPairFromFormattedPairs(curr,
- c.GetEnabledPairs(asset.Spot),
- c.GetPairFormat(asset.Spot, true))
+ p, err := currency.NewPairFromFormattedPairs(curr,
+ pairs,
+ format)
+ if err != nil {
+ return nil, err
+ }
+
orderSide := order.Side(strings.ToUpper(orders.Trades[y].Order.Side))
orderDate := time.Unix(orders.Trades[y].Order.Timestamp, 0)
allOrders = append(allOrders, order.Detail{
@@ -854,25 +956,6 @@ func (c *COINUT) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, e
return allOrders, nil
}
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func (c *COINUT) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- c.Websocket.SubscribeToChannels(channels)
- return nil
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func (c *COINUT) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- c.Websocket.RemoveSubscribedChannels(channels)
- return nil
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func (c *COINUT) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return c.Websocket.GetSubscriptions(), nil
-}
-
// AuthenticateWebsocket sends an authentication message to the websocket
func (c *COINUT) AuthenticateWebsocket() error {
return c.wsAuthenticate()
diff --git a/exchanges/exchange.go b/exchanges/exchange.go
index e22de1b2..b1f1cef7 100644
--- a/exchanges/exchange.go
+++ b/exchanges/exchange.go
@@ -10,6 +10,7 @@ import (
"strings"
"time"
+ "github.com/thrasher-corp/gocryptotrader/common"
"github.com/thrasher-corp/gocryptotrader/common/crypto"
"github.com/thrasher-corp/gocryptotrader/config"
"github.com/thrasher-corp/gocryptotrader/currency"
@@ -17,6 +18,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/banking"
)
@@ -197,19 +199,9 @@ func (e *Base) GetLastPairsUpdateTime() int64 {
return e.CurrencyPairs.LastUpdated
}
-// SetAssetTypes checks the exchange asset types (whether it supports SPOT,
-// Binary or Futures) and sets it to a default setting if it doesn't exist
-func (e *Base) SetAssetTypes() {
- if e.Config.CurrencyPairs.AssetTypes.JoinToString(",") == "" {
- e.Config.CurrencyPairs.AssetTypes = e.CurrencyPairs.AssetTypes
- } else if e.Config.CurrencyPairs.AssetTypes.JoinToString(",") != e.CurrencyPairs.AssetTypes.JoinToString(",") {
- e.Config.CurrencyPairs.AssetTypes = e.CurrencyPairs.AssetTypes
- }
-}
-
// GetAssetTypes returns the available asset types for an individual exchange
func (e *Base) GetAssetTypes() asset.Items {
- return e.CurrencyPairs.AssetTypes
+ return e.CurrencyPairs.GetAssetTypes()
}
// GetPairAssetType returns the associated asset type for the currency pair
@@ -218,7 +210,11 @@ func (e *Base) GetAssetTypes() asset.Items {
func (e *Base) GetPairAssetType(c currency.Pair) (asset.Item, error) {
assetTypes := e.GetAssetTypes()
for i := range assetTypes {
- if e.GetAvailablePairs(assetTypes[i]).Contains(c, true) {
+ avail, err := e.GetAvailablePairs(assetTypes[i])
+ if err != nil {
+ return "", err
+ }
+ if avail.Contains(c, true) {
return assetTypes[i], nil
}
}
@@ -262,35 +258,53 @@ func (e *Base) SetCurrencyPairFormat() {
assetTypes := e.GetAssetTypes()
for x := range assetTypes {
- if e.Config.CurrencyPairs.Get(assetTypes[x]) == nil {
- r := e.CurrencyPairs.Get(assetTypes[x])
- if r == nil {
+ if _, err := e.Config.CurrencyPairs.Get(assetTypes[x]); err != nil {
+ ps, err := e.CurrencyPairs.Get(assetTypes[x])
+ if err != nil {
continue
}
- e.Config.CurrencyPairs.Store(assetTypes[x], *e.CurrencyPairs.Get(assetTypes[x]))
+ e.Config.CurrencyPairs.Store(assetTypes[x], *ps)
}
}
}
// SetConfigPairs sets the exchanges currency pairs to the pairs set in the config
-func (e *Base) SetConfigPairs() {
- assetTypes := e.GetAssetTypes()
+func (e *Base) SetConfigPairs() error {
+ assetTypes := e.Config.CurrencyPairs.GetAssetTypes()
+ exchangeAssets := e.CurrencyPairs.GetAssetTypes()
for x := range assetTypes {
- cfgPS := e.Config.CurrencyPairs.Get(assetTypes[x])
- if cfgPS == nil {
- continue
+ if !exchangeAssets.Contains(assetTypes[x]) {
+ log.Warnf(log.ExchangeSys,
+ "%s exchange asset type %s unsupported, please manually remove from configuration",
+ e.Name,
+ assetTypes[x])
}
+ cfgPS, err := e.Config.CurrencyPairs.Get(assetTypes[x])
+ if err != nil {
+ return err
+ }
+
+ var enabledAsset bool
+ if e.Config.CurrencyPairs.IsAssetEnabled(assetTypes[x]) == nil {
+ enabledAsset = true
+ }
+ e.CurrencyPairs.SetAssetEnabled(assetTypes[x], enabledAsset)
+
if e.Config.CurrencyPairs.UseGlobalFormat {
e.CurrencyPairs.StorePairs(assetTypes[x], cfgPS.Available, false)
e.CurrencyPairs.StorePairs(assetTypes[x], cfgPS.Enabled, true)
continue
}
- exchPS := e.CurrencyPairs.Get(assetTypes[x])
+ exchPS, err := e.CurrencyPairs.Get(assetTypes[x])
+ if err != nil {
+ return err
+ }
cfgPS.ConfigFormat = exchPS.ConfigFormat
cfgPS.RequestFormat = exchPS.RequestFormat
e.CurrencyPairs.StorePairs(assetTypes[x], cfgPS.Available, false)
e.CurrencyPairs.StorePairs(assetTypes[x], cfgPS.Enabled, true)
}
+ return nil
}
// GetAuthenticatedAPISupport returns whether the exchange supports
@@ -322,26 +336,63 @@ func (e *Base) GetSupportedFeatures() FeaturesSupported {
// GetPairFormat returns the pair format based on the exchange and
// asset type
-func (e *Base) GetPairFormat(assetType asset.Item, requestFormat bool) currency.PairFormat {
+func (e *Base) GetPairFormat(assetType asset.Item, requestFormat bool) (currency.PairFormat, error) {
if e.CurrencyPairs.UseGlobalFormat {
if requestFormat {
- return *e.CurrencyPairs.RequestFormat
+ if e.CurrencyPairs.RequestFormat == nil {
+ return currency.PairFormat{},
+ errors.New("global request format is nil")
+ }
+ return *e.CurrencyPairs.RequestFormat, nil
}
- return *e.CurrencyPairs.ConfigFormat
+
+ if e.CurrencyPairs.ConfigFormat == nil {
+ return currency.PairFormat{},
+ errors.New("global config format is nil")
+ }
+ return *e.CurrencyPairs.ConfigFormat, nil
+ }
+
+ ps, err := e.CurrencyPairs.Get(assetType)
+ if err != nil {
+ return currency.PairFormat{}, err
}
if requestFormat {
- return *e.CurrencyPairs.Get(assetType).RequestFormat
+ if ps.RequestFormat == nil {
+ return currency.PairFormat{},
+ errors.New("asset type request format is nil")
+ }
+ return *ps.RequestFormat, nil
}
- return *e.CurrencyPairs.Get(assetType).ConfigFormat
+
+ if ps.ConfigFormat == nil {
+ return currency.PairFormat{},
+ errors.New("asset type config format is nil")
+ }
+ return *ps.ConfigFormat, nil
}
// GetEnabledPairs is a method that returns the enabled currency pairs of
-// the exchange by asset type
-func (e *Base) GetEnabledPairs(assetType asset.Item) currency.Pairs {
- format := e.GetPairFormat(assetType, false)
- pairs := e.CurrencyPairs.GetPairs(assetType, true)
- return pairs.Format(format.Delimiter, format.Index, format.Uppercase)
+// the exchange by asset type, if the asset type is disabled this will return no
+// enabled pairs
+func (e *Base) GetEnabledPairs(a asset.Item) (currency.Pairs, error) {
+ err := e.CurrencyPairs.IsAssetEnabled(a)
+ if err != nil {
+ return nil, nil
+ }
+ format, err := e.GetPairFormat(a, false)
+ if err != nil {
+ return nil, err
+ }
+ enabledpairs, err := e.CurrencyPairs.GetPairs(a, true)
+ if err != nil {
+ return nil, err
+ }
+ return enabledpairs.Format(format.Delimiter,
+ format.Index,
+ format.Uppercase),
+ nil
}
// GetRequestFormattedPairAndAssetType is a method that returns the enabled currency pair of
@@ -350,8 +401,16 @@ func (e *Base) GetRequestFormattedPairAndAssetType(p string) (currency.Pair, ass
assetTypes := e.GetAssetTypes()
var response currency.Pair
for i := range assetTypes {
- format := e.GetPairFormat(assetTypes[i], true)
- pairs := e.CurrencyPairs.GetPairs(assetTypes[i], true)
+ format, err := e.GetPairFormat(assetTypes[i], true)
+ if err != nil {
+ return response, assetTypes[i], err
+ }
+
+ pairs, err := e.CurrencyPairs.GetPairs(assetTypes[i], true)
+ if err != nil {
+ return response, assetTypes[i], err
+ }
+
for j := range pairs {
formattedPair := pairs[j].Format(format.Delimiter, format.Uppercase)
if strings.EqualFold(formattedPair.String(), p) {
@@ -364,29 +423,57 @@ func (e *Base) GetRequestFormattedPairAndAssetType(p string) (currency.Pair, ass
// GetAvailablePairs is a method that returns the available currency pairs
// of the exchange by asset type
-func (e *Base) GetAvailablePairs(assetType asset.Item) currency.Pairs {
- format := e.GetPairFormat(assetType, false)
- pairs := e.CurrencyPairs.GetPairs(assetType, false)
- return pairs.Format(format.Delimiter, format.Index, format.Uppercase)
+func (e *Base) GetAvailablePairs(assetType asset.Item) (currency.Pairs, error) {
+ format, err := e.GetPairFormat(assetType, false)
+ if err != nil {
+ return nil, err
+ }
+ pairs, err := e.CurrencyPairs.GetPairs(assetType, false)
+ if err != nil {
+ return nil, err
+ }
+ return pairs.Format(format.Delimiter, format.Index, format.Uppercase), nil
}
// SupportsPair returns true or not whether a currency pair exists in the
// exchange available currencies or not
-func (e *Base) SupportsPair(p currency.Pair, enabledPairs bool, assetType asset.Item) bool {
+func (e *Base) SupportsPair(p currency.Pair, enabledPairs bool, assetType asset.Item) error {
if enabledPairs {
- return e.GetEnabledPairs(assetType).Contains(p, false)
+ pairs, err := e.GetEnabledPairs(assetType)
+ if err != nil {
+ return err
+ }
+ if pairs.Contains(p, false) {
+ return nil
+ }
+ return errors.New("pair not supported")
}
- return e.GetAvailablePairs(assetType).Contains(p, false)
+
+ avail, err := e.GetAvailablePairs(assetType)
+ if err != nil {
+ return err
+ }
+ if avail.Contains(p, false) {
+ return nil
+ }
+ return errors.New("pair not supported")
}
// FormatExchangeCurrencies returns a string containing
// the exchanges formatted currency pairs
func (e *Base) FormatExchangeCurrencies(pairs []currency.Pair, assetType asset.Item) (string, error) {
var currencyItems strings.Builder
- pairFmt := e.GetPairFormat(assetType, true)
+ pairFmt, err := e.GetPairFormat(assetType, true)
+ if err != nil {
+ return "", err
+ }
for x := range pairs {
- currencyItems.WriteString(e.FormatExchangeCurrency(pairs[x], assetType).String())
+ format, err := e.FormatExchangeCurrency(pairs[x], assetType)
+ if err != nil {
+ return "", err
+ }
+ currencyItems.WriteString(format.String())
if x == len(pairs)-1 {
continue
}
@@ -401,9 +488,12 @@ func (e *Base) FormatExchangeCurrencies(pairs []currency.Pair, assetType asset.I
// FormatExchangeCurrency is a method that formats and returns a currency pair
// based on the user currency display preferences
-func (e *Base) FormatExchangeCurrency(p currency.Pair, assetType asset.Item) currency.Pair {
- pairFmt := e.GetPairFormat(assetType, true)
- return p.Format(pairFmt.Delimiter, pairFmt.Uppercase)
+func (e *Base) FormatExchangeCurrency(p currency.Pair, assetType asset.Item) (currency.Pair, error) {
+ pairFmt, err := e.GetPairFormat(assetType, true)
+ if err != nil {
+ return currency.Pair{}, err
+ }
+ return p.Format(pairFmt.Delimiter, pairFmt.Uppercase), nil
}
// SetEnabled is a method that sets if the exchange is enabled
@@ -464,18 +554,26 @@ func (e *Base) SetupDefaults(exch *config.ExchangeConfig) error {
e.HTTPDebugging = exch.HTTPDebugging
e.SetHTTPClientUserAgent(exch.HTTPUserAgent)
- e.SetAssetTypes()
e.SetCurrencyPairFormat()
- e.SetConfigPairs()
- e.SetFeatureDefaults()
- e.SetAPIURL()
- e.SetAPICredentialDefaults()
- e.SetClientProxyAddress(exch.ProxyAddress)
- e.BaseCurrencies = exch.BaseCurrencies
- if e.Features.Supports.Websocket {
- return e.Websocket.Initialise()
+ err := e.SetConfigPairs()
+ if err != nil {
+ return err
}
+
+ e.SetFeatureDefaults()
+ err = e.SetAPIURL()
+ if err != nil {
+ return err
+ }
+
+ e.SetAPICredentialDefaults()
+
+ err = e.SetClientProxyAddress(exch.ProxyAddress)
+ if err != nil {
+ return err
+ }
+ e.BaseCurrencies = exch.BaseCurrencies
return nil
}
@@ -564,7 +662,11 @@ func (e *Base) SetPairs(pairs currency.Pairs, assetType asset.Item, enabled bool
return fmt.Errorf("%s SetPairs error - pairs is empty", e.Name)
}
- pairFmt := e.GetPairFormat(assetType, false)
+ pairFmt, err := e.GetPairFormat(assetType, false)
+ if err != nil {
+ return err
+ }
+
var newPairs currency.Pairs
for x := range pairs {
newPairs = append(newPairs, pairs[x].Format(pairFmt.Delimiter,
@@ -579,10 +681,6 @@ func (e *Base) SetPairs(pairs currency.Pairs, assetType asset.Item, enabled bool
// UpdatePairs updates the exchange currency pairs for either enabledPairs or
// availablePairs
func (e *Base) UpdatePairs(exchangeProducts currency.Pairs, assetType asset.Item, enabled, force bool) error {
- if len(exchangeProducts) == 0 {
- return fmt.Errorf("%s UpdatePairs error - exchangeProducts is empty", e.Name)
- }
-
exchangeProducts = exchangeProducts.Upper()
var products currency.Pairs
for x := range exchangeProducts {
@@ -592,37 +690,71 @@ func (e *Base) UpdatePairs(exchangeProducts currency.Pairs, assetType asset.Item
products = append(products, exchangeProducts[x])
}
- var newPairs, removedPairs currency.Pairs
var updateType string
- targetPairs := e.CurrencyPairs.GetPairs(assetType, enabled)
+ targetPairs, err := e.CurrencyPairs.GetPairs(assetType, enabled)
+ if err != nil {
+ return err
+ }
if enabled {
- newPairs, removedPairs = targetPairs.FindDifferences(products)
updateType = "enabled"
} else {
- newPairs, removedPairs = targetPairs.FindDifferences(products)
updateType = "available"
}
+ newPairs, removedPairs := targetPairs.FindDifferences(products)
if force || len(newPairs) > 0 || len(removedPairs) > 0 {
if force {
log.Debugf(log.ExchangeSys,
- "%s forced update of %s [%v] pairs.", e.Name, updateType,
+ "%s forced update of %s [%v] pairs.",
+ e.Name,
+ updateType,
strings.ToUpper(assetType.String()))
} else {
if len(newPairs) > 0 {
log.Debugf(log.ExchangeSys,
- "%s Updating pairs [%v] - New: %s.\n", e.Name,
- strings.ToUpper(assetType.String()), newPairs)
+ "%s Updating %s pairs [%v] - Added: %s.\n",
+ e.Name,
+ updateType,
+ strings.ToUpper(assetType.String()),
+ newPairs)
}
if len(removedPairs) > 0 {
log.Debugf(log.ExchangeSys,
- "%s Updating pairs [%v] - Removed: %s.\n", e.Name,
- strings.ToUpper(assetType.String()), removedPairs)
+ "%s Updating %s pairs [%v] - Removed: %s.\n",
+ e.Name,
+ updateType,
+ strings.ToUpper(assetType.String()),
+ removedPairs)
}
}
+
e.Config.CurrencyPairs.StorePairs(assetType, products, enabled)
e.CurrencyPairs.StorePairs(assetType, products, enabled)
+
+ if !enabled {
+ // If available pairs are changed we will remove currency pair items
+ // that are still included in the enabled pairs list.
+ enabledPairs, err := e.CurrencyPairs.GetPairs(assetType, true)
+ if err == nil {
+ return nil
+ }
+ _, remove := enabledPairs.FindDifferences(products)
+ for i := range remove {
+ enabledPairs = enabledPairs.Remove(remove[i])
+ }
+
+ if len(remove) > 0 {
+ log.Debugf(log.ExchangeSys,
+ "%s Checked and updated enabled pairs [%v] - Removed: %s.\n",
+ e.Name,
+ strings.ToUpper(assetType.String()),
+ remove)
+
+ e.Config.CurrencyPairs.StorePairs(assetType, enabledPairs, true)
+ e.CurrencyPairs.StorePairs(assetType, enabledPairs, true)
+ }
+ }
}
return nil
}
@@ -675,27 +807,12 @@ func (e *Base) GetAPIURLSecondaryDefault() string {
return e.API.Endpoints.URLSecondaryDefault
}
-// SupportsWebsocket returns whether or not the exchange supports
-// websocket
-func (e *Base) SupportsWebsocket() bool {
- return e.Features.Supports.Websocket
-}
-
// SupportsREST returns whether or not the exchange supports
// REST
func (e *Base) SupportsREST() bool {
return e.Features.Supports.REST
}
-// IsWebsocketEnabled returns whether or not the exchange has its
-// websocket client enabled
-func (e *Base) IsWebsocketEnabled() bool {
- if e.Websocket != nil {
- return e.Websocket.IsEnabled()
- }
- return false
-}
-
// GetWithdrawPermissions passes through the exchange's withdraw permissions
func (e *Base) GetWithdrawPermissions() uint32 {
return e.Features.Supports.WithdrawPermissions
@@ -767,7 +884,8 @@ func (e *Base) FormatWithdrawPermissions() string {
// SupportsAsset whether or not the supplied asset is supported
// by the exchange
func (e *Base) SupportsAsset(a asset.Item) bool {
- return e.CurrencyPairs.AssetTypes.Contains(a)
+ _, ok := e.CurrencyPairs.Pairs[a]
+ return ok
}
// PrintEnabledPairs prints the exchanges enabled asset pairs
@@ -804,6 +922,135 @@ func (e *Base) EnableRateLimiter() error {
return e.Requester.EnableRateLimiter()
}
+// StoreAssetPairFormat initialises and stores a defined asset format
+func (e *Base) StoreAssetPairFormat(a asset.Item, f currency.PairStore) error {
+ if a.String() == "" {
+ return fmt.Errorf("%s cannot add to pairs manager, no asset provided",
+ e.Name)
+ }
+
+ if f.RequestFormat == nil {
+ return fmt.Errorf("%s cannot add to pairs manager, request pair format not provided",
+ e.Name)
+ }
+
+ if f.ConfigFormat == nil {
+ return fmt.Errorf("%s cannot add to pairs manager, config pair format not provided",
+ e.Name)
+ }
+
+ if e.CurrencyPairs.Pairs == nil {
+ e.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
+ }
+
+ e.CurrencyPairs.Pairs[a] = &f
+ return nil
+}
+
+// SetGlobalPairsManager sets defined asset and pairs management system with
+// with global formatting
+func (e *Base) SetGlobalPairsManager(request, config *currency.PairFormat, assets ...asset.Item) error {
+ if request == nil {
+ return fmt.Errorf("%s cannot set pairs manager, request pair format not provided",
+ e.Name)
+ }
+
+ if config == nil {
+ return fmt.Errorf("%s cannot set pairs manager, config pair format not provided",
+ e.Name)
+ }
+
+ if len(assets) == 0 {
+ return fmt.Errorf("%s cannot set pairs manager, no assets provided",
+ e.Name)
+ }
+
+ e.CurrencyPairs.UseGlobalFormat = true
+ e.CurrencyPairs.RequestFormat = request
+ e.CurrencyPairs.ConfigFormat = config
+
+ if e.CurrencyPairs.Pairs != nil {
+ return fmt.Errorf("%s cannot set pairs manager, pairs already set",
+ e.Name)
+ }
+
+ e.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
+
+ for i := range assets {
+ if assets[i].String() == "" {
+ e.CurrencyPairs.Pairs = nil
+ return fmt.Errorf("%s cannot set pairs manager, asset is empty string",
+ e.Name)
+ }
+ e.CurrencyPairs.Pairs[assets[i]] = new(currency.PairStore)
+ }
+
+ return nil
+}
+
+// GetWebsocket returns a pointer to the exchange websocket
+func (e *Base) GetWebsocket() (*stream.Websocket, error) {
+ if e.Websocket == nil {
+ return nil, common.ErrFunctionNotSupported
+ }
+ return e.Websocket, nil
+}
+
+// SupportsWebsocket returns whether or not the exchange supports
+// websocket
+func (e *Base) SupportsWebsocket() bool {
+ return e.Features.Supports.Websocket
+}
+
+// IsWebsocketEnabled returns whether or not the exchange has its
+// websocket client enabled
+func (e *Base) IsWebsocketEnabled() bool {
+ if e.Websocket == nil {
+ return false
+ }
+ return e.Websocket.IsEnabled()
+}
+
+// FlushWebsocketChannels refreshes websocket channel subscriptions based on
+// websocket features. Used in the event of a pair/asset or subscription change.
+func (e *Base) FlushWebsocketChannels() error {
+ if e.Websocket == nil {
+ return nil
+ }
+ return e.Websocket.FlushChannels()
+}
+
+// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
+// which lets websocket.manageSubscriptions handle subscribing
+func (e *Base) SubscribeToWebsocketChannels(channels []stream.ChannelSubscription) error {
+ if e.Websocket == nil {
+ return common.ErrFunctionNotSupported
+ }
+ return e.Websocket.SubscribeToChannels(channels)
+}
+
+// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
+// which lets websocket.manageSubscriptions handle unsubscribing
+func (e *Base) UnsubscribeToWebsocketChannels(channels []stream.ChannelSubscription) error {
+ if e.Websocket == nil {
+ return common.ErrFunctionNotSupported
+ }
+ return e.Websocket.UnsubscribeChannels(channels)
+}
+
+// GetSubscriptions returns a copied list of subscriptions
+func (e *Base) GetSubscriptions() ([]stream.ChannelSubscription, error) {
+ if e.Websocket == nil {
+ return nil, common.ErrFunctionNotSupported
+ }
+ return e.Websocket.GetSubscriptions(), nil
+}
+
+// AuthenticateWebsocket sends an authentication message to the websocket
+func (e *Base) AuthenticateWebsocket() error {
+ return common.ErrFunctionNotSupported
+}
+
// KlineIntervalEnabled returns if requested interval is enabled on exchange
func (e *Base) KlineIntervalEnabled(in kline.Interval) bool {
return e.Features.Enabled.Kline.Intervals[in.Word()]
diff --git a/exchanges/exchange_test.go b/exchanges/exchange_test.go
index e61a4d28..29b03388 100644
--- a/exchanges/exchange_test.go
+++ b/exchanges/exchange_test.go
@@ -2,17 +2,20 @@ package exchange
import (
"net/http"
+ "os"
"strings"
"testing"
"time"
+ "github.com/thrasher-corp/gocryptotrader/common/convert"
"github.com/thrasher-corp/gocryptotrader/config"
"github.com/thrasher-corp/gocryptotrader/currency"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
+ "github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/banking"
)
@@ -21,6 +24,13 @@ const (
defaultTestCurrencyPair = "BTC-USD"
)
+func TestMain(m *testing.M) {
+ c := log.GenDefaultSettings()
+ log.GlobalLogConfig = &c
+ log.SetupGlobalLogger()
+ os.Exit(m.Run())
+}
+
func TestSupportsRESTTickerBatchUpdates(t *testing.T) {
t.Parallel()
@@ -98,7 +108,7 @@ func TestSetClientProxyAddress(t *testing.T) {
Name: "rawr",
Requester: requester}
- newBase.Websocket = wshandler.New()
+ newBase.Websocket = stream.New()
err := newBase.SetClientProxyAddress(":invalid")
if err == nil {
t.Error("SetClientProxyAddress parsed invalid URL")
@@ -108,18 +118,18 @@ func TestSetClientProxyAddress(t *testing.T) {
t.Error("SetClientProxyAddress error", err)
}
- err = newBase.SetClientProxyAddress("www.valid.com")
+ err = newBase.SetClientProxyAddress("http://www.valid.com")
if err != nil {
t.Error("SetClientProxyAddress error", err)
}
// calling this again will cause the ws check to fail
- err = newBase.SetClientProxyAddress("www.valid.com")
+ err = newBase.SetClientProxyAddress("http://www.valid.com")
if err == nil {
t.Error("trying to set the same proxy addr should thrown an err for ws")
}
- if newBase.Websocket.GetProxyAddress() != "www.valid.com" {
+ if newBase.Websocket.GetProxyAddress() != "http://www.valid.com" {
t.Error("SetClientProxyAddress error", err)
}
}
@@ -253,46 +263,15 @@ func TestGetLastPairsUpdateTime(t *testing.T) {
}
}
-func TestSetAssetTypes(t *testing.T) {
- t.Parallel()
-
- b := Base{
- Config: &config.ExchangeConfig{
- CurrencyPairs: ¤cy.PairsManager{},
- },
- CurrencyPairs: currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- asset.Binary,
- asset.Futures,
- },
- },
- }
- b.SetAssetTypes()
- if len(b.GetAssetTypes()) != 3 {
- t.Error("incorrect assets len")
- }
-
- b.CurrencyPairs.AssetTypes = append(b.CurrencyPairs.AssetTypes,
- asset.PerpetualSwap)
- b.Config.CurrencyPairs.AssetTypes = asset.Items{
- asset.Index,
- }
- b.SetAssetTypes()
- if len(b.GetAssetTypes()) != 4 {
- t.Error("incorrect assets len")
- }
-}
-
func TestGetAssetTypes(t *testing.T) {
t.Parallel()
testExchange := Base{
CurrencyPairs: currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- asset.Binary,
- asset.Futures,
+ Pairs: map[asset.Item]*currency.PairStore{
+ asset.Spot: new(currency.PairStore),
+ asset.Binary: new(currency.PairStore),
+ asset.Futures: new(currency.PairStore),
},
},
}
@@ -347,14 +326,17 @@ func TestSetCurrencyPairFormat(t *testing.T) {
b.CurrencyPairs.RequestFormat = pFmt
b.CurrencyPairs.ConfigFormat = pFmt
b.SetCurrencyPairFormat()
- if b.GetPairFormat(asset.Spot, true).Delimiter != "#" {
+ spot, err := b.GetPairFormat(asset.Spot, true)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if spot.Delimiter != "#" {
t.Error("incorrect pair format delimiter")
}
// Test individual asset type formatting logic
b.CurrencyPairs.UseGlobalFormat = false
- // This will generate a nil pair store
- b.CurrencyPairs.AssetTypes = asset.Items{asset.Index}
// Store non-nil pair stores
b.CurrencyPairs.Store(asset.Spot, currency.PairStore{
ConfigFormat: ¤cy.PairFormat{
@@ -367,10 +349,18 @@ func TestSetCurrencyPairFormat(t *testing.T) {
},
})
b.SetCurrencyPairFormat()
- if b.GetPairFormat(asset.Spot, false).Delimiter != "~" {
+ spot, err = b.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if spot.Delimiter != "~" {
t.Error("incorrect pair format delimiter")
}
- if b.GetPairFormat(asset.Futures, false).Delimiter != ":)" {
+ futures, err := b.GetPairFormat(asset.Futures, false)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if futures.Delimiter != ":)" {
t.Error("incorrect pair format delimiter")
}
}
@@ -386,7 +376,6 @@ func TestLoadConfigPairs(t *testing.T) {
b := Base{
CurrencyPairs: currency.PairsManager{
UseGlobalFormat: true,
- AssetTypes: asset.Items{asset.Spot},
RequestFormat: ¤cy.PairFormat{
Delimiter: ">",
Uppercase: false,
@@ -408,7 +397,10 @@ func TestLoadConfigPairs(t *testing.T) {
}
// Test a nil PairsManager
- b.SetConfigPairs()
+ err := b.SetConfigPairs()
+ if err != nil {
+ t.Fatal(err)
+ }
// Now setup a proper PairsManager
b.Config.CurrencyPairs = ¤cy.PairsManager{
@@ -421,33 +413,51 @@ func TestLoadConfigPairs(t *testing.T) {
Delimiter: "!",
Uppercase: true,
},
- AssetTypes: asset.Items{asset.Spot},
Pairs: map[asset.Item]*currency.PairStore{
asset.Spot: {
- Enabled: pairs,
- Available: pairs,
- RequestFormat: ¤cy.PairFormat{},
- ConfigFormat: ¤cy.PairFormat{},
+ AssetEnabled: convert.BoolPtr(true),
+ Enabled: pairs,
+ Available: pairs,
},
},
}
// Test UseGlobalFormat setting of pairs
b.SetCurrencyPairFormat()
- b.SetConfigPairs()
+ err = b.SetConfigPairs()
+ if err != nil {
+ t.Fatal(err)
+ }
// Test four things:
// 1) Config pairs are set
// 2) pair format is set for RequestFormat
// 3) pair format is set for ConfigFormat
// 4) Config global format delimiter is updated based off exchange.Base
- pFmt := b.GetPairFormat(asset.Spot, false)
- p := b.GetEnabledPairs(asset.Spot)[0].Format(pFmt.Delimiter,
- pFmt.Uppercase).String()
+ pFmt, err := b.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ t.Fatal(err)
+ }
+ pairs, err = b.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ p := pairs[0].Format(pFmt.Delimiter, pFmt.Uppercase).String()
if p != "BTC^USD" {
t.Errorf("incorrect value, expected BTC^USD")
}
- p = b.FormatExchangeCurrency(b.GetAvailablePairs(asset.Spot)[0],
- asset.Spot).String()
+
+ avail, err := b.GetAvailablePairs(asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ format, err := b.FormatExchangeCurrency(avail[0], asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ p = format.String()
if p != "btc>usd" {
t.Error("incorrect value, expected btc>usd")
}
@@ -459,7 +469,10 @@ func TestLoadConfigPairs(t *testing.T) {
}
// Test !UseGlobalFormat setting of pairs
- exchPS := b.CurrencyPairs.Get(asset.Spot)
+ exchPS, err := b.CurrencyPairs.Get(asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
exchPS.RequestFormat.Delimiter = "~"
exchPS.RequestFormat.Uppercase = false
exchPS.ConfigFormat.Delimiter = "/"
@@ -476,18 +489,36 @@ func TestLoadConfigPairs(t *testing.T) {
// 2) pair format is set for RequestFormat
// 3) pair format is set for ConfigFormat
// 4) Config pair store formats are the same as the exchanges
- pFmt = b.GetPairFormat(asset.Spot, false)
- p = b.GetEnabledPairs(asset.Spot)[2].Format(pFmt.Delimiter,
- pFmt.Uppercase).String()
+ pFmt, err = b.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ t.Fatal(err)
+ }
+ pairs, err = b.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
+ p = pairs[2].Format(pFmt.Delimiter, pFmt.Uppercase).String()
if p != "xrp/usd" {
t.Error("incorrect value, expected xrp/usd")
}
- p = b.FormatExchangeCurrency(b.GetAvailablePairs(asset.Spot)[2],
- asset.Spot).String()
+
+ avail, err = b.GetAvailablePairs(asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ format, err = b.FormatExchangeCurrency(avail[2], asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
+ p = format.String()
if p != "xrp~usd" {
t.Error("incorrect value, expected xrp~usd")
}
- ps := b.Config.CurrencyPairs.Get(asset.Spot)
+ ps, err := b.Config.CurrencyPairs.Get(asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
if ps.RequestFormat.Delimiter != "~" ||
ps.RequestFormat.Uppercase ||
ps.ConfigFormat.Delimiter != "/" ||
@@ -570,11 +601,17 @@ func TestGetPairFormat(t *testing.T) {
b.CurrencyPairs.RequestFormat = ¤cy.PairFormat{
Delimiter: "~",
}
- pFmt := b.GetPairFormat(asset.Spot, true)
+ pFmt, err := b.GetPairFormat(asset.Spot, true)
+ if err != nil {
+ t.Fatal(err)
+ }
if pFmt.Delimiter != "~" && !pFmt.Uppercase {
t.Error("incorrect pair format values")
}
- pFmt = b.GetPairFormat(asset.Spot, false)
+ pFmt, err = b.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ t.Fatal(err)
+ }
if pFmt.Delimiter != "" && pFmt.Uppercase {
t.Error("incorrect pair format values")
}
@@ -588,11 +625,17 @@ func TestGetPairFormat(t *testing.T) {
Uppercase: true,
},
})
- pFmt = b.GetPairFormat(asset.Spot, false)
+ pFmt, err = b.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ t.Fatal(err)
+ }
if pFmt.Delimiter != "" && pFmt.Uppercase {
t.Error("incorrect pair format values")
}
- pFmt = b.GetPairFormat(asset.Spot, true)
+ pFmt, err = b.GetPairFormat(asset.Spot, true)
+ if err != nil {
+ t.Fatal(err)
+ }
if pFmt.Delimiter != "~" && !pFmt.Uppercase {
t.Error("incorrect pair format values")
}
@@ -605,70 +648,116 @@ func TestGetEnabledPairs(t *testing.T) {
Name: "TESTNAME",
}
- b.CurrencyPairs.StorePairs(asset.Spot,
- currency.NewPairsFromStrings([]string{defaultTestCurrencyPair}), true)
+ defaultPairs, err := currency.NewPairsFromStrings([]string{defaultTestCurrencyPair})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ b.CurrencyPairs.StorePairs(asset.Spot, defaultPairs, true)
+ b.CurrencyPairs.StorePairs(asset.Spot, defaultPairs, false)
format := currency.PairFormat{
Delimiter: "-",
Index: "",
Uppercase: true,
}
- assetType := asset.Spot
+ err = b.CurrencyPairs.SetAssetEnabled(asset.Spot, true)
+ if err != nil {
+ t.Fatal(err)
+ }
+
b.CurrencyPairs.UseGlobalFormat = true
b.CurrencyPairs.RequestFormat = &format
b.CurrencyPairs.ConfigFormat = &format
- c := b.GetEnabledPairs(assetType)
+ c, err := b.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
+
if c[0].String() != defaultTestCurrencyPair {
t.Error("Exchange GetAvailablePairs() incorrect string")
}
format.Delimiter = "~"
b.CurrencyPairs.RequestFormat = &format
- c = b.GetEnabledPairs(assetType)
+ c, err = b.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
if c[0].String() != "BTC~USD" {
t.Error("Exchange GetAvailablePairs() incorrect string")
}
format.Delimiter = ""
b.CurrencyPairs.ConfigFormat = &format
- c = b.GetEnabledPairs(assetType)
+ c, err = b.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
if c[0].String() != "BTCUSD" {
t.Error("Exchange GetAvailablePairs() incorrect string")
}
- b.CurrencyPairs.StorePairs(asset.Spot,
- currency.NewPairsFromStrings([]string{"BTCDOGE"}), true)
+ btcdoge, err := currency.NewPairsFromStrings([]string{"BTCDOGE"})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ b.CurrencyPairs.StorePairs(asset.Spot, btcdoge, true)
+ b.CurrencyPairs.StorePairs(asset.Spot, btcdoge, false)
format.Index = currency.BTC.String()
b.CurrencyPairs.ConfigFormat = &format
- c = b.GetEnabledPairs(assetType)
+ c, err = b.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
if c[0].Base != currency.BTC && c[0].Quote != currency.DOGE {
t.Error("Exchange GetAvailablePairs() incorrect string")
}
- b.CurrencyPairs.StorePairs(asset.Spot,
- currency.NewPairsFromStrings([]string{"BTC_USD"}), true)
+ btcusdUnderscore, err := currency.NewPairsFromStrings([]string{"BTC_USD"})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ b.CurrencyPairs.StorePairs(asset.Spot, btcusdUnderscore, true)
+ b.CurrencyPairs.StorePairs(asset.Spot, btcusdUnderscore, false)
b.CurrencyPairs.RequestFormat.Delimiter = ""
b.CurrencyPairs.ConfigFormat.Delimiter = "_"
- c = b.GetEnabledPairs(assetType)
+ c, err = b.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
if c[0].Base != currency.BTC && c[0].Quote != currency.USD {
t.Error("Exchange GetAvailablePairs() incorrect string")
}
- b.CurrencyPairs.StorePairs(asset.Spot,
- currency.NewPairsFromStrings([]string{"BTCDOGE"}), true)
+ b.CurrencyPairs.StorePairs(asset.Spot, btcdoge, true)
+ b.CurrencyPairs.StorePairs(asset.Spot, btcdoge, false)
b.CurrencyPairs.RequestFormat.Delimiter = ""
b.CurrencyPairs.ConfigFormat.Delimiter = ""
b.CurrencyPairs.ConfigFormat.Index = currency.BTC.String()
- c = b.GetEnabledPairs(assetType)
+ c, err = b.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
if c[0].Base != currency.BTC && c[0].Quote != currency.DOGE {
t.Error("Exchange GetAvailablePairs() incorrect string")
}
- b.CurrencyPairs.StorePairs(asset.Spot,
- currency.NewPairsFromStrings([]string{"BTCUSD"}), true)
+ btcusd, err := currency.NewPairsFromStrings([]string{"BTCUSD"})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ b.CurrencyPairs.StorePairs(asset.Spot, btcusd, true)
+ b.CurrencyPairs.StorePairs(asset.Spot, btcusd, false)
b.CurrencyPairs.ConfigFormat.Index = ""
- c = b.GetEnabledPairs(assetType)
+ c, err = b.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
if c[0].Base != currency.BTC && c[0].Quote != currency.USD {
t.Error("Exchange GetAvailablePairs() incorrect string")
}
@@ -681,8 +770,12 @@ func TestGetAvailablePairs(t *testing.T) {
Name: "TESTNAME",
}
- b.CurrencyPairs.StorePairs(asset.Spot,
- currency.NewPairsFromStrings([]string{defaultTestCurrencyPair}), false)
+ defaultPairs, err := currency.NewPairsFromStrings([]string{defaultTestCurrencyPair})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ b.CurrencyPairs.StorePairs(asset.Spot, defaultPairs, false)
format := currency.PairFormat{
Delimiter: "-",
Index: "",
@@ -694,57 +787,96 @@ func TestGetAvailablePairs(t *testing.T) {
b.CurrencyPairs.RequestFormat = &format
b.CurrencyPairs.ConfigFormat = &format
- c := b.GetAvailablePairs(assetType)
+ c, err := b.GetAvailablePairs(assetType)
+ if err != nil {
+ t.Fatal(err)
+ }
+
if c[0].String() != defaultTestCurrencyPair {
t.Error("Exchange GetAvailablePairs() incorrect string")
}
format.Delimiter = "~"
b.CurrencyPairs.RequestFormat = &format
- c = b.GetAvailablePairs(assetType)
+ c, err = b.GetAvailablePairs(assetType)
+ if err != nil {
+ t.Fatal(err)
+ }
+
if c[0].String() != "BTC~USD" {
t.Error("Exchange GetAvailablePairs() incorrect string")
}
format.Delimiter = ""
b.CurrencyPairs.ConfigFormat = &format
- c = b.GetAvailablePairs(assetType)
+ c, err = b.GetAvailablePairs(assetType)
+ if err != nil {
+ t.Fatal(err)
+ }
+
if c[0].String() != "BTCUSD" {
t.Error("Exchange GetAvailablePairs() incorrect string")
}
- b.CurrencyPairs.StorePairs(asset.Spot,
- currency.NewPairsFromStrings([]string{"BTCDOGE"}), false)
+ dogePairs, err := currency.NewPairsFromStrings([]string{"BTCDOGE"})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ b.CurrencyPairs.StorePairs(asset.Spot, dogePairs, false)
format.Index = currency.BTC.String()
b.CurrencyPairs.ConfigFormat = &format
- c = b.GetAvailablePairs(assetType)
+ c, err = b.GetAvailablePairs(assetType)
+ if err != nil {
+ t.Fatal(err)
+ }
+
if c[0].Base != currency.BTC && c[0].Quote != currency.DOGE {
t.Error("Exchange GetAvailablePairs() incorrect string")
}
- b.CurrencyPairs.StorePairs(asset.Spot,
- currency.NewPairsFromStrings([]string{"BTC_USD"}), false)
+ btcusdUnderscore, err := currency.NewPairsFromStrings([]string{"BTC_USD"})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ b.CurrencyPairs.StorePairs(asset.Spot, btcusdUnderscore, false)
b.CurrencyPairs.RequestFormat.Delimiter = ""
b.CurrencyPairs.ConfigFormat.Delimiter = "_"
- c = b.GetAvailablePairs(assetType)
+ c, err = b.GetAvailablePairs(assetType)
+ if err != nil {
+ t.Fatal(err)
+ }
+
if c[0].Base != currency.BTC && c[0].Quote != currency.USD {
t.Error("Exchange GetAvailablePairs() incorrect string")
}
- b.CurrencyPairs.StorePairs(asset.Spot,
- currency.NewPairsFromStrings([]string{"BTCDOGE"}), false)
+ b.CurrencyPairs.StorePairs(asset.Spot, dogePairs, false)
b.CurrencyPairs.RequestFormat.Delimiter = ""
b.CurrencyPairs.ConfigFormat.Delimiter = "_"
b.CurrencyPairs.ConfigFormat.Index = currency.BTC.String()
- c = b.GetAvailablePairs(assetType)
+ c, err = b.GetAvailablePairs(assetType)
+ if err != nil {
+ t.Fatal(err)
+ }
+
if c[0].Base != currency.BTC && c[0].Quote != currency.DOGE {
t.Error("Exchange GetAvailablePairs() incorrect string")
}
- b.CurrencyPairs.StorePairs(asset.Spot,
- currency.NewPairsFromStrings([]string{"BTCUSD"}), false)
+ btcusd, err := currency.NewPairsFromStrings([]string{"BTCUSD"})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ b.CurrencyPairs.StorePairs(asset.Spot, btcusd, false)
b.CurrencyPairs.ConfigFormat.Index = ""
- c = b.GetAvailablePairs(assetType)
+ c, err = b.GetAvailablePairs(assetType)
+ if err != nil {
+ t.Fatal(err)
+ }
+
if c[0].Base != currency.BTC && c[0].Quote != currency.USD {
t.Error("Exchange GetAvailablePairs() incorrect string")
}
@@ -755,13 +887,29 @@ func TestSupportsPair(t *testing.T) {
b := Base{
Name: "TESTNAME",
+ CurrencyPairs: currency.PairsManager{
+ Pairs: map[asset.Item]*currency.PairStore{
+ asset.Spot: {
+ AssetEnabled: convert.BoolPtr(true),
+ },
+ },
+ },
}
- b.CurrencyPairs.StorePairs(asset.Spot,
- currency.NewPairsFromStrings([]string{
- defaultTestCurrencyPair, "ETH-USD"}), false)
- b.CurrencyPairs.StorePairs(asset.Spot,
- currency.NewPairsFromStrings([]string{defaultTestCurrencyPair}), true)
+ pairs, err := currency.NewPairsFromStrings([]string{defaultTestCurrencyPair,
+ "ETH-USD"})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ b.CurrencyPairs.StorePairs(asset.Spot, pairs, false)
+
+ defaultpairs, err := currency.NewPairsFromStrings([]string{defaultTestCurrencyPair})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ b.CurrencyPairs.StorePairs(asset.Spot, defaultpairs, true)
format := ¤cy.PairFormat{
Delimiter: "-",
@@ -773,15 +921,20 @@ func TestSupportsPair(t *testing.T) {
b.CurrencyPairs.ConfigFormat = format
assetType := asset.Spot
- if !b.SupportsPair(currency.NewPair(currency.BTC, currency.USD), true, assetType) {
+ if b.SupportsPair(currency.NewPair(currency.BTC, currency.USD), true, assetType) != nil {
t.Error("Exchange SupportsPair() incorrect value")
}
- if !b.SupportsPair(currency.NewPair(currency.ETH, currency.USD), false, assetType) {
+ if b.SupportsPair(currency.NewPair(currency.ETH, currency.USD), false, assetType) != nil {
t.Error("Exchange SupportsPair() incorrect value")
}
- if b.SupportsPair(currency.NewPairFromStrings("ASD", "ASDF"), true, assetType) {
+ asdasdf, err := currency.NewPairFromStrings("ASD", "ASDF")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if b.SupportsPair(asdasdf, true, assetType) == nil {
t.Error("Exchange SupportsPair() incorrect value")
}
}
@@ -805,10 +958,17 @@ func TestFormatExchangeCurrencies(t *testing.T) {
},
},
}
-
+ p1, err := currency.NewPairDelimiter("BTC_USD", "_")
+ if err != nil {
+ t.Fatal(err)
+ }
+ p2, err := currency.NewPairDelimiter("LTC_BTC", "_")
+ if err != nil {
+ t.Fatal(err)
+ }
var pairs = []currency.Pair{
- currency.NewPairDelimiter("BTC_USD", "_"),
- currency.NewPairDelimiter("LTC_BTC", "_"),
+ p1,
+ p2,
}
actual, err := e.FormatExchangeCurrencies(pairs, asset.Spot)
@@ -839,7 +999,10 @@ func TestFormatExchangeCurrency(t *testing.T) {
p := currency.NewPair(currency.BTC, currency.USD)
expected := defaultTestCurrencyPair
- actual := b.FormatExchangeCurrency(p, asset.Spot)
+ actual, err := b.FormatExchangeCurrency(p, asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
if actual.String() != expected {
t.Errorf("Exchange TestFormatExchangeCurrency %s != %s",
@@ -919,24 +1082,23 @@ func TestSetupDefaults(t *testing.T) {
AuthenticatedSupport: true,
},
}
- if err := b.SetupDefaults(&cfg); err != nil {
- t.Error(err)
- }
+ b.SetupDefaults(&cfg)
if cfg.HTTPTimeout.String() != "15s" {
t.Error("HTTP timeout should be set to 15s")
}
// Test custom HTTP timeout is set
cfg.HTTPTimeout = time.Second * 30
- if err := b.SetupDefaults(&cfg); err != nil {
- t.Error(err)
- }
+ b.SetupDefaults(&cfg)
if cfg.HTTPTimeout.String() != "30s" {
t.Error("HTTP timeout should be set to 30s")
}
// Test asset types
- p := currency.NewPairDelimiter(defaultTestCurrencyPair, "-")
+ p, err := currency.NewPairDelimiter(defaultTestCurrencyPair, "-")
+ if err != nil {
+ t.Fatal(err)
+ }
b.CurrencyPairs.Store(asset.Spot,
currency.PairStore{
Enabled: currency.Pairs{
@@ -944,23 +1106,35 @@ func TestSetupDefaults(t *testing.T) {
},
},
)
- if err := b.SetupDefaults(&cfg); err != nil {
- t.Error(err)
+ b.SetupDefaults(&cfg)
+ ps, err := cfg.CurrencyPairs.Get(asset.Spot)
+ if err != nil {
+ t.Fatal(err)
}
- ps := cfg.CurrencyPairs.Get(asset.Spot)
if !ps.Enabled.Contains(p, true) {
t.Error("default pair should be stored in the configs pair store")
}
// Test websocket support
- b.Websocket = wshandler.New()
+ b.Websocket = stream.New()
b.Features.Supports.Websocket = true
- if err := b.SetupDefaults(&cfg); err != nil {
- t.Error(err)
- }
- b.Websocket.Setup(&wshandler.WebsocketSetup{
- Enabled: true,
+ b.SetupDefaults(&cfg)
+ err = b.Websocket.Setup(&stream.WebsocketSetup{
+ Enabled: false,
+ WebsocketTimeout: time.Second * 30,
+ Features: &protocol.Features{},
+ DefaultURL: "ws://something.com",
+ RunningURL: "ws://something.com",
+ ExchangeName: "test",
+ Connector: func() error { return nil },
})
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = b.Websocket.Enable()
+ if err != nil {
+ t.Fatal(err)
+ }
if !b.IsWebsocketEnabled() {
t.Error("websocket should be enabled")
}
@@ -1081,7 +1255,11 @@ func TestSetPairs(t *testing.T) {
ConfigFormat: ¤cy.PairFormat{
Uppercase: true,
},
- Pairs: map[asset.Item]*currency.PairStore{},
+ Pairs: map[asset.Item]*currency.PairStore{
+ asset.Spot: {
+ AssetEnabled: convert.BoolPtr(true),
+ },
+ },
},
},
}
@@ -1098,7 +1276,22 @@ func TestSetPairs(t *testing.T) {
t.Error(err)
}
- if p := b.GetEnabledPairs(asset.Spot); len(p) != 1 {
+ err = b.SetPairs(pairs, asset.Spot, false)
+ if err != nil {
+ t.Error(err)
+ }
+
+ err = b.SetConfigPairs()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ p, err := b.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if len(p) != 1 {
t.Error("pairs shouldn't be nil")
}
}
@@ -1115,14 +1308,34 @@ func TestUpdatePairs(t *testing.T) {
t.Fatal("TestUpdatePairs failed to load config")
}
- UAC := Base{Name: defaultTestExchange}
+ UAC := Base{
+ Name: defaultTestExchange,
+ CurrencyPairs: currency.PairsManager{
+ Pairs: map[asset.Item]*currency.PairStore{
+ asset.Spot: {
+ AssetEnabled: convert.BoolPtr(true),
+ },
+ },
+ },
+ }
UAC.Config = exchCfg
- exchangeProducts := currency.NewPairsFromStrings([]string{"ltc", "btc", "usd", "aud", ""})
+ exchangeProducts, err := currency.NewPairsFromStrings([]string{"ltcusd",
+ "btcusd",
+ "usdbtc",
+ "audusd"})
+ if err != nil {
+ t.Fatal(err)
+ }
err = UAC.UpdatePairs(exchangeProducts, asset.Spot, true, false)
if err != nil {
t.Errorf("TestUpdatePairs error: %s", err)
}
+ err = UAC.UpdatePairs(exchangeProducts, asset.Spot, false, false)
+ if err != nil {
+ t.Errorf("TestUpdatePairs error: %s", err)
+ }
+
// Test updating the same new products, diff should be 0
err = UAC.UpdatePairs(exchangeProducts, asset.Spot, true, false)
if err != nil {
@@ -1130,14 +1343,24 @@ func TestUpdatePairs(t *testing.T) {
}
// Test force updating to only one product
- exchangeProducts = currency.NewPairsFromStrings([]string{"btc"})
+ exchangeProducts, err = currency.NewPairsFromStrings([]string{"btcusd"})
+ if err != nil {
+ t.Fatal(err)
+ }
+
err = UAC.UpdatePairs(exchangeProducts, asset.Spot, true, true)
if err != nil {
t.Errorf("TestUpdatePairs error: %s", err)
}
// Test updating exchange products
- exchangeProducts = currency.NewPairsFromStrings([]string{"ltc", "btc", "usd", "aud"})
+ exchangeProducts, err = currency.NewPairsFromStrings([]string{"ltcusd",
+ "btcusd",
+ "usdbtc",
+ "audbtc"})
+ if err != nil {
+ t.Fatal(err)
+ }
UAC.Name = defaultTestExchange
err = UAC.UpdatePairs(exchangeProducts, asset.Spot, false, false)
if err != nil {
@@ -1151,28 +1374,30 @@ func TestUpdatePairs(t *testing.T) {
}
// Test force updating to only one product
- exchangeProducts = currency.NewPairsFromStrings([]string{"btc"})
+ exchangeProducts, err = currency.NewPairsFromStrings([]string{"btcusd"})
+ if err != nil {
+ t.Fatal(err)
+ }
err = UAC.UpdatePairs(exchangeProducts, asset.Spot, false, true)
if err != nil {
t.Errorf("Forced Exchange UpdatePairs() error: %s", err)
}
// Test update currency pairs with btc excluded
- exchangeProducts = currency.NewPairsFromStrings([]string{"ltc", "eth"})
+ exchangeProducts, err = currency.NewPairsFromStrings([]string{"ltcusd", "ethusd"})
+ if err != nil {
+ t.Fatal(err)
+ }
err = UAC.UpdatePairs(exchangeProducts, asset.Spot, false, false)
if err != nil {
t.Errorf("Forced Exchange UpdatePairs() error: %s", err)
}
- // Test that empty exchange products should return an error
- exchangeProducts = nil
- err = UAC.UpdatePairs(exchangeProducts, asset.Spot, false, false)
- if err == nil {
- t.Errorf("empty available pairs should return an error")
- }
-
// Test empty pair
- p := currency.NewPairDelimiter(defaultTestCurrencyPair, "-")
+ p, err := currency.NewPairDelimiter(defaultTestCurrencyPair, "-")
+ if err != nil {
+ t.Fatal(err)
+ }
pairs := currency.Pairs{
currency.Pair{},
p,
@@ -1181,11 +1406,20 @@ func TestUpdatePairs(t *testing.T) {
if err != nil {
t.Errorf("Forced Exchange UpdatePairs() error: %s", err)
}
+ err = UAC.UpdatePairs(pairs, asset.Spot, false, true)
+ if err != nil {
+ t.Errorf("Forced Exchange UpdatePairs() error: %s", err)
+ }
UAC.CurrencyPairs.UseGlobalFormat = true
UAC.CurrencyPairs.ConfigFormat = ¤cy.PairFormat{
Delimiter: "-",
}
- if !UAC.GetEnabledPairs(asset.Spot).Contains(p, true) {
+
+ uacPairs, err := UAC.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !uacPairs.Contains(p, true) {
t.Fatal("expected currency pair not found")
}
}
@@ -1298,8 +1532,16 @@ func TestIsWebsocketEnabled(t *testing.T) {
t.Error("exchange doesn't support websocket")
}
- b.Websocket = wshandler.New()
- err := b.Websocket.Setup(&wshandler.WebsocketSetup{Enabled: true})
+ b.Websocket = stream.New()
+ err := b.Websocket.Setup(&stream.WebsocketSetup{
+ Enabled: true,
+ WebsocketTimeout: time.Second * 30,
+ Features: &protocol.Features{},
+ DefaultURL: "ws://something.com",
+ RunningURL: "ws://something.com",
+ ExchangeName: "test",
+ Connector: func() error { return nil },
+ })
if err != nil {
t.Error(err)
}
@@ -1380,8 +1622,8 @@ func TestFormatWithdrawPermissions(t *testing.T) {
func TestSupportsAsset(t *testing.T) {
t.Parallel()
var b Base
- b.CurrencyPairs.AssetTypes = asset.Items{
- asset.Spot,
+ b.CurrencyPairs.Pairs = map[asset.Item]*currency.PairStore{
+ asset.Spot: {},
}
if !b.SupportsAsset(asset.Spot) {
t.Error("spot should be supported")
@@ -1426,9 +1668,12 @@ func TestGetAssetType(t *testing.T) {
if err == nil {
t.Fatal("error cannot be nil")
}
- b.CurrencyPairs.AssetTypes = asset.Items{asset.Spot}
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
+ AssetEnabled: convert.BoolPtr(true),
+ Enabled: currency.Pairs{
+ currency.NewPair(currency.BTC, currency.USD),
+ },
Available: currency.Pairs{
currency.NewPair(currency.BTC, currency.USD),
},
@@ -1460,11 +1705,14 @@ func TestGetFormattedPairAndAssetType(t *testing.T) {
b.CurrencyPairs.ConfigFormat = pFmt
b.CurrencyPairs.Pairs = make(map[asset.Item]*currency.PairStore)
b.CurrencyPairs.Pairs[asset.Spot] = ¤cy.PairStore{
+ AssetEnabled: convert.BoolPtr(true),
Enabled: currency.Pairs{
currency.NewPair(currency.BTC, currency.USD),
},
+ Available: currency.Pairs{
+ currency.NewPair(currency.BTC, currency.USD),
+ },
}
- b.CurrencyPairs.AssetTypes = asset.Items{asset.Spot}
p, a, err := b.GetRequestFormattedPairAndAssetType("btc#usd")
if err != nil {
t.Error(err)
@@ -1481,6 +1729,85 @@ func TestGetFormattedPairAndAssetType(t *testing.T) {
}
}
+func TestStoreAssetPairFormat(t *testing.T) {
+ b := Base{
+ Config: &config.ExchangeConfig{Name: "kitties"},
+ }
+
+ err := b.StoreAssetPairFormat(asset.Item(""), currency.PairStore{})
+ if err == nil {
+ t.Error("error cannot be nil")
+ }
+
+ err = b.StoreAssetPairFormat(asset.Spot, currency.PairStore{})
+ if err == nil {
+ t.Error("error cannot be nil")
+ }
+
+ err = b.StoreAssetPairFormat(asset.Spot, currency.PairStore{
+ RequestFormat: ¤cy.PairFormat{Uppercase: true}})
+ if err == nil {
+ t.Error("error cannot be nil")
+ }
+
+ err = b.StoreAssetPairFormat(asset.Spot, currency.PairStore{
+ RequestFormat: ¤cy.PairFormat{Uppercase: true},
+ ConfigFormat: ¤cy.PairFormat{Uppercase: true}})
+ if err != nil {
+ t.Error(err)
+ }
+
+ err = b.StoreAssetPairFormat(asset.Futures, currency.PairStore{
+ RequestFormat: ¤cy.PairFormat{Uppercase: true},
+ ConfigFormat: ¤cy.PairFormat{Uppercase: true}})
+ if err != nil {
+ t.Error(err)
+ }
+}
+
+func TestSetGlobalPairsManager(t *testing.T) {
+ b := Base{
+ Config: &config.ExchangeConfig{Name: "kitties"},
+ }
+
+ err := b.SetGlobalPairsManager(nil, nil, "")
+ if err == nil {
+ t.Error("error cannot be nil")
+ }
+
+ err = b.SetGlobalPairsManager(¤cy.PairFormat{Uppercase: true}, nil, "")
+ if err == nil {
+ t.Error("error cannot be nil")
+ }
+
+ err = b.SetGlobalPairsManager(¤cy.PairFormat{Uppercase: true},
+ ¤cy.PairFormat{Uppercase: true})
+ if err == nil {
+ t.Error("error cannot be nil")
+ }
+
+ err = b.SetGlobalPairsManager(¤cy.PairFormat{Uppercase: true},
+ ¤cy.PairFormat{Uppercase: true}, "")
+ if err == nil {
+ t.Error("error cannot be nil")
+ }
+
+ err = b.SetGlobalPairsManager(¤cy.PairFormat{Uppercase: true},
+ ¤cy.PairFormat{Uppercase: true}, asset.Spot, asset.Binary)
+ if err != nil {
+ t.Error(err)
+ }
+
+ if !b.SupportsAsset(asset.Binary) || !b.SupportsAsset(asset.Spot) {
+ t.Fatal("global pairs manager not set correctly")
+ }
+
+ err = b.SetGlobalPairsManager(¤cy.PairFormat{Uppercase: true},
+ ¤cy.PairFormat{Uppercase: true}, asset.Spot, asset.Binary)
+ if err == nil {
+ t.Error("error cannot be nil")
+ }
+}
func Test_FormatExchangeKlineInterval(t *testing.T) {
testCases := []struct {
name string
diff --git a/exchanges/exchange_types.go b/exchanges/exchange_types.go
index 15f5d253..38c9cbe2 100644
--- a/exchanges/exchange_types.go
+++ b/exchanges/exchange_types.go
@@ -8,7 +8,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
)
// Endpoint authentication types
@@ -212,7 +212,7 @@ type Base struct {
WebsocketResponseCheckTimeout time.Duration
WebsocketResponseMaxLimit time.Duration
WebsocketOrderbookBufferLimit int64
- Websocket *wshandler.Websocket
+ Websocket *stream.Websocket
*request.Requester
Config *config.ExchangeConfig
}
diff --git a/exchanges/exmo/exmo_wrapper.go b/exchanges/exmo/exmo_wrapper.go
index 16d9f474..23c4858b 100644
--- a/exchanges/exmo/exmo_wrapper.go
+++ b/exchanges/exmo/exmo_wrapper.go
@@ -20,7 +20,6 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -56,20 +55,18 @@ func (e *EXMO) SetDefaults() {
e.API.CredentialsValidator.RequiresKey = true
e.API.CredentialsValidator.RequiresSecret = true
- e.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- },
- UseGlobalFormat: true,
- RequestFormat: ¤cy.PairFormat{
- Delimiter: "_",
- Uppercase: true,
- Separator: ",",
- },
- ConfigFormat: ¤cy.PairFormat{
- Delimiter: "_",
- Uppercase: true,
- },
+ requestFmt := ¤cy.PairFormat{
+ Delimiter: currency.UnderscoreDelimiter,
+ Uppercase: true,
+ Separator: ",",
+ }
+ configFmt := ¤cy.PairFormat{
+ Delimiter: currency.UnderscoreDelimiter,
+ Uppercase: true,
+ }
+ err := e.SetGlobalPairsManager(requestFmt, configFmt, asset.Spot)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
}
e.Features = exchange.Features{
@@ -120,7 +117,6 @@ func (e *EXMO) Setup(exch *config.ExchangeConfig) error {
e.SetEnabled(false)
return nil
}
-
return e.SetupDefaults(exch)
}
@@ -172,37 +168,45 @@ func (e *EXMO) UpdateTradablePairs(forceUpdate bool) error {
return err
}
- return e.UpdatePairs(currency.NewPairsFromStrings(pairs), asset.Spot, false, forceUpdate)
+ p, err := currency.NewPairsFromStrings(pairs)
+ if err != nil {
+ return err
+ }
+
+ return e.UpdatePairs(p, asset.Spot, false, forceUpdate)
}
// UpdateTicker updates and returns the ticker for a currency pair
func (e *EXMO) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
- tickerPrice := new(ticker.Price)
result, err := e.GetTicker()
if err != nil {
- return tickerPrice, err
+ return nil, err
}
if _, ok := result[p.String()]; !ok {
- return tickerPrice, err
+ return nil, err
+ }
+ pairs, err := e.GetEnabledPairs(assetType)
+ if err != nil {
+ return nil, err
}
- pairs := e.GetEnabledPairs(assetType)
for i := range pairs {
for j := range result {
if !strings.EqualFold(pairs[i].String(), j) {
continue
}
- tickerPrice = &ticker.Price{
- Pair: pairs[i],
- Last: result[j].Last,
- Ask: result[j].Sell,
- High: result[j].High,
- Bid: result[j].Buy,
- Low: result[j].Low,
- Volume: result[j].Volume,
- }
- err = ticker.ProcessTicker(e.Name, tickerPrice, assetType)
+
+ err = ticker.ProcessTicker(&ticker.Price{
+ Pair: pairs[i],
+ Last: result[j].Last,
+ Ask: result[j].Sell,
+ High: result[j].High,
+ Bid: result[j].Buy,
+ Low: result[j].Low,
+ Volume: result[j].Volume,
+ ExchangeName: e.Name,
+ AssetType: assetType})
if err != nil {
- log.Error(log.Ticker, err)
+ return nil, err
}
}
}
@@ -229,7 +233,11 @@ func (e *EXMO) FetchOrderbook(p currency.Pair, assetType asset.Item) (*orderbook
// UpdateOrderbook updates and returns the orderbook for a currency pair
func (e *EXMO) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
- enabledPairs := e.GetEnabledPairs(assetType)
+ enabledPairs, err := e.GetEnabledPairs(assetType)
+ if err != nil {
+ return nil, err
+ }
+
pairsCollated, err := e.FormatExchangeCurrencies(enabledPairs, assetType)
if err != nil {
return nil, err
@@ -241,7 +249,12 @@ func (e *EXMO) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderboo
}
for i := range enabledPairs {
- data, ok := result[e.FormatExchangeCurrency(enabledPairs[i], assetType).String()]
+ curr, err := e.FormatExchangeCurrency(enabledPairs[i], assetType)
+ if err != nil {
+ return nil, err
+ }
+
+ data, ok := result[curr.String()]
if !ok {
continue
}
@@ -473,11 +486,6 @@ func (e *EXMO) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdraw.Re
return nil, common.ErrFunctionNotSupported
}
-// GetWebsocket returns a pointer to the exchange websocket
-func (e *EXMO) GetWebsocket() (*wshandler.Websocket, error) {
- return nil, common.ErrFunctionNotSupported
-}
-
// GetFeeByType returns an estimate of fee based on type of transaction
func (e *EXMO) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if !e.AllowAuthenticatedRequest() && // Todo check connection status
@@ -496,7 +504,11 @@ func (e *EXMO) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, err
var orders []order.Detail
for i := range resp {
- symbol := currency.NewPairDelimiter(resp[i].Pair, "_")
+ var symbol currency.Pair
+ symbol, err = currency.NewPairDelimiter(resp[i].Pair, "_")
+ if err != nil {
+ return nil, err
+ }
orderDate := time.Unix(resp[i].Created, 0)
orderSide := order.Side(strings.ToUpper(resp[i].Type))
orders = append(orders, order.Detail{
@@ -524,7 +536,12 @@ func (e *EXMO) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, err
var allTrades []UserTrades
for i := range req.Pairs {
- resp, err := e.GetUserTrades(e.FormatExchangeCurrency(req.Pairs[i], asset.Spot).String(), "", "10000")
+ fpair, err := e.FormatExchangeCurrency(req.Pairs[i], asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+
+ resp, err := e.GetUserTrades(fpair.String(), "", "10000")
if err != nil {
return nil, err
}
@@ -535,7 +552,10 @@ func (e *EXMO) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, err
var orders []order.Detail
for i := range allTrades {
- symbol := currency.NewPairDelimiter(allTrades[i].Pair, "_")
+ symbol, err := currency.NewPairDelimiter(allTrades[i].Pair, "_")
+ if err != nil {
+ return nil, err
+ }
orderDate := time.Unix(allTrades[i].Date, 0)
orderSide := order.Side(strings.ToUpper(allTrades[i].Type))
orders = append(orders, order.Detail{
@@ -554,28 +574,6 @@ func (e *EXMO) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, err
return orders, nil
}
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func (e *EXMO) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- return common.ErrFunctionNotSupported
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func (e *EXMO) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- return common.ErrFunctionNotSupported
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func (e *EXMO) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return nil, common.ErrFunctionNotSupported
-}
-
-// AuthenticateWebsocket sends an authentication message to the websocket
-func (e *EXMO) AuthenticateWebsocket() error {
- return common.ErrFunctionNotSupported
-}
-
// ValidateCredentials validates current credentials used for wrapper
// functionality
func (e *EXMO) ValidateCredentials() error {
diff --git a/exchanges/ftx/ftx.go b/exchanges/ftx/ftx.go
index a86d0f0f..3fc09af6 100644
--- a/exchanges/ftx/ftx.go
+++ b/exchanges/ftx/ftx.go
@@ -17,13 +17,11 @@ import (
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
)
// FTX is the overarching type across this package
type FTX struct {
exchange.Base
- WebsocketConn *wshandler.WebsocketConnection
}
const (
diff --git a/exchanges/ftx/ftx_test.go b/exchanges/ftx/ftx_test.go
index d1753249..22ae4db4 100644
--- a/exchanges/ftx/ftx_test.go
+++ b/exchanges/ftx/ftx_test.go
@@ -49,7 +49,7 @@ func TestMain(m *testing.M) {
exchCfg.API.AuthenticatedWebsocketSupport = true
exchCfg.API.Credentials.Key = apiKey
exchCfg.API.Credentials.Secret = apiSecret
-
+ f.Websocket = sharedtestvalues.NewTestWebsocket()
err = f.Setup(exchCfg)
if err != nil {
log.Fatal(err)
@@ -855,10 +855,13 @@ func TestGetFundingHistory(t *testing.T) {
func TestGetHistoricCandles(t *testing.T) {
t.Parallel()
- currencyPair := currency.NewPairFromString(spotPair)
+ currencyPair, err := currency.NewPairFromString(spotPair)
+ if err != nil {
+ t.Fatal(err)
+ }
start := time.Date(2019, 11, 12, 0, 0, 0, 0, time.UTC)
end := start.AddDate(0, 0, 5)
- _, err := f.GetHistoricCandles(currencyPair, asset.Spot, start, end, kline.OneDay)
+ _, err = f.GetHistoricCandles(currencyPair, asset.Spot, start, end, kline.OneDay)
if err != nil {
t.Fatal(err)
}
@@ -866,10 +869,13 @@ func TestGetHistoricCandles(t *testing.T) {
func TestGetHistoricCandlesExtended(t *testing.T) {
t.Parallel()
- currencyPair := currency.NewPairFromString(spotPair)
+ currencyPair, err := currency.NewPairFromString(spotPair)
+ if err != nil {
+ t.Fatal(err)
+ }
start := time.Date(2019, 11, 12, 0, 0, 0, 0, time.UTC)
end := start.AddDate(0, 0, 5)
- _, err := f.GetHistoricCandlesExtended(currencyPair, asset.Spot, start, end, kline.OneMin)
+ _, err = f.GetHistoricCandlesExtended(currencyPair, asset.Spot, start, end, kline.OneMin)
if err != nil {
t.Fatal(err)
}
@@ -1093,7 +1099,10 @@ func TestAcceptOTCQuote(t *testing.T) {
func TestGetExchangeHistory(t *testing.T) {
t.Parallel()
- p := currency.NewPairFromString("ADA-PERP")
+ p, err := currency.NewPairFromString("ADA-PERP")
+ if err != nil {
+ t.Fatal(err)
+ }
a, err := f.GetPairAssetType(p)
if err != nil {
t.Error(err)
diff --git a/exchanges/ftx/ftx_websocket.go b/exchanges/ftx/ftx_websocket.go
index 34703676..97fd83e1 100644
--- a/exchanges/ftx/ftx_websocket.go
+++ b/exchanges/ftx/ftx_websocket.go
@@ -11,15 +11,16 @@ import (
"time"
"github.com/gorilla/websocket"
+ "github.com/thrasher-corp/gocryptotrader/common"
"github.com/thrasher-corp/gocryptotrader/common/crypto"
"github.com/thrasher-corp/gocryptotrader/currency"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wsorderbook"
"github.com/thrasher-corp/gocryptotrader/log"
)
@@ -43,31 +44,35 @@ var obSuccess = make(map[currency.Pair]bool)
// WsConnect connects to a websocket feed
func (f *FTX) WsConnect() error {
if !f.Websocket.IsEnabled() || !f.IsEnabled() {
- return errors.New(wshandler.WebsocketNotEnabled)
+ return errors.New(stream.WebsocketNotEnabled)
}
var dialer websocket.Dialer
- err := f.WebsocketConn.Dial(&dialer, http.Header{})
+ err := f.Websocket.Conn.Dial(&dialer, http.Header{})
if err != nil {
return err
}
- f.WebsocketConn.SetupPingHandler(wshandler.WebsocketPingHandler{
+ f.Websocket.Conn.SetupPingHandler(stream.PingHandler{
MessageType: websocket.PingMessage,
Delay: ftxWebsocketTimer,
})
if f.Verbose {
log.Debugf(log.ExchangeSys, "%s Connected to Websocket.\n", f.Name)
}
- f.GenerateDefaultSubscriptions()
+
go f.wsReadData()
if f.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
- err := f.WsAuth()
+ err = f.WsAuth()
if err != nil {
f.Websocket.DataHandler <- err
f.Websocket.SetCanUseAuthenticatedEndpoints(false)
}
- f.GenerateAuthSubscriptions()
}
- return nil
+
+ subs, err := f.GenerateDefaultSubscriptions()
+ if err != nil {
+ return err
+ }
+ return f.Websocket.SubscribeToChannels(subs)
}
// WsAuth sends an authentication message to receive auth data
@@ -87,81 +92,138 @@ func (f *FTX) WsAuth() error {
Time: intNonce,
},
}
- return f.WebsocketConn.SendJSONMessage(req)
+ return f.Websocket.Conn.SendJSONMessage(req)
}
// Subscribe sends a websocket message to receive data from the channel
-func (f *FTX) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
- var sub WsSub
- switch channelToSubscribe.Channel {
- case wsFills, wsOrders, wsMarkets:
+func (f *FTX) Subscribe(channelsToSubscribe []stream.ChannelSubscription) error {
+ var errs common.Errors
+channels:
+ for i := range channelsToSubscribe {
+ var sub WsSub
+ sub.Channel = channelsToSubscribe[i].Channel
sub.Operation = subscribe
- sub.Channel = channelToSubscribe.Channel
- default:
- a, err := f.GetPairAssetType(channelToSubscribe.Currency)
- if err != nil {
- return err
+
+ switch channelsToSubscribe[i].Channel {
+ case wsFills, wsOrders, wsMarkets:
+ default:
+ a, err := f.GetPairAssetType(channelsToSubscribe[i].Currency)
+ if err != nil {
+ errs = append(errs, err)
+ continue channels
+ }
+
+ formattedPair, err := f.FormatExchangeCurrency(channelsToSubscribe[i].Currency, a)
+ if err != nil {
+ errs = append(errs, err)
+ continue channels
+ }
+ sub.Market = formattedPair.String()
}
- sub.Operation = subscribe
- sub.Channel = channelToSubscribe.Channel
- sub.Market = f.FormatExchangeCurrency(channelToSubscribe.Currency, a).String()
+ err := f.Websocket.Conn.SendJSONMessage(sub)
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ f.Websocket.AddSuccessfulSubscriptions(channelsToSubscribe[i])
}
- return f.WebsocketConn.SendJSONMessage(sub)
+ if errs != nil {
+ return errs
+ }
+ return nil
+}
+
+// Unsubscribe sends a websocket message to stop receiving data from the channel
+func (f *FTX) Unsubscribe(channelsToUnsubscribe []stream.ChannelSubscription) error {
+ var errs common.Errors
+channels:
+ for i := range channelsToUnsubscribe {
+ var unSub WsSub
+ unSub.Operation = unsubscribe
+ unSub.Channel = channelsToUnsubscribe[i].Channel
+ switch channelsToUnsubscribe[i].Channel {
+ case wsFills, wsOrders, wsMarkets:
+ default:
+ a, err := f.GetPairAssetType(channelsToUnsubscribe[i].Currency)
+ if err != nil {
+ errs = append(errs, err)
+ continue channels
+ }
+
+ formattedPair, err := f.FormatExchangeCurrency(channelsToUnsubscribe[i].Currency, a)
+ if err != nil {
+ errs = append(errs, err)
+ continue channels
+ }
+ unSub.Market = formattedPair.String()
+ }
+ err := f.Websocket.Conn.SendJSONMessage(unSub)
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ f.Websocket.RemoveSuccessfulUnsubscriptions(channelsToUnsubscribe[i])
+ }
+ if errs != nil {
+ return errs
+ }
+ return nil
}
// GenerateDefaultSubscriptions generates default subscription
-func (f *FTX) GenerateDefaultSubscriptions() {
- var subscriptions []wshandler.WebsocketChannelSubscription
- subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
+func (f *FTX) GenerateDefaultSubscriptions() ([]stream.ChannelSubscription, error) {
+ var subscriptions []stream.ChannelSubscription
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
Channel: wsMarkets,
})
var channels = []string{wsTicker, wsTrades, wsOrderbook}
- for a := range f.CurrencyPairs.AssetTypes {
- pairs := f.GetEnabledPairs(f.CurrencyPairs.AssetTypes[a])
+ assets := f.GetAssetTypes()
+ for a := range assets {
+ pairs, err := f.GetEnabledPairs(assets[a])
+ if err != nil {
+ return nil, err
+ }
for z := range pairs {
- newPair := currency.NewPairWithDelimiter(pairs[z].Base.String(), pairs[z].Quote.String(), "-")
+ newPair := currency.NewPairWithDelimiter(pairs[z].Base.String(),
+ pairs[z].Quote.String(),
+ "-")
for x := range channels {
- subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
- Channel: channels[x],
- Currency: newPair,
- })
+ subscriptions = append(subscriptions,
+ stream.ChannelSubscription{
+ Channel: channels[x],
+ Currency: newPair,
+ Asset: assets[a],
+ })
}
}
}
- f.Websocket.SubscribeToChannels(subscriptions)
-}
-
-// GenerateAuthSubscriptions generates default subscription
-func (f *FTX) GenerateAuthSubscriptions() {
- var subscriptions []wshandler.WebsocketChannelSubscription
- var channels = []string{wsOrders, wsFills}
- for x := range channels {
- subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
- Channel: channels[x],
- })
+ if f.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
+ var authchan = []string{wsOrders, wsFills}
+ for x := range authchan {
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
+ Channel: authchan[x],
+ })
+ }
}
- f.Websocket.SubscribeToChannels(subscriptions)
+ return subscriptions, nil
}
// wsReadData gets and passes on websocket messages for processing
func (f *FTX) wsReadData() {
f.Websocket.Wg.Add(1)
-
defer f.Websocket.Wg.Done()
for {
select {
case <-f.Websocket.ShutdownC:
return
-
default:
- resp, err := f.WebsocketConn.ReadMessage()
- if err != nil {
- f.Websocket.ReadMessageErrors <- err
+ resp := f.Websocket.Conn.ReadMessage()
+ if resp.Raw == nil {
return
}
- f.Websocket.TrafficAlert <- struct{}{}
- err = f.wsHandleData(resp.Raw)
+
+ err := f.wsHandleData(resp.Raw)
if err != nil {
f.Websocket.DataHandler <- err
}
@@ -187,7 +249,10 @@ func (f *FTX) wsHandleData(respRaw []byte) error {
var a asset.Item
market, ok := result["market"]
if ok {
- p = currency.NewPairFromString(market.(string))
+ p, err = currency.NewPairFromString(market.(string))
+ if err != nil {
+ return err
+ }
a, err = f.GetPairAssetType(p)
if err != nil {
return err
@@ -220,7 +285,10 @@ func (f *FTX) wsHandleData(respRaw []byte) error {
}
err = f.WsProcessUpdateOB(&resultData.OBData, p, a)
if err != nil {
- f.wsResubToOB(p)
+ err2 := f.wsResubToOB(p)
+ if err2 != nil {
+ f.Websocket.DataHandler <- err2
+ }
return err
}
case wsTrades:
@@ -238,7 +306,7 @@ func (f *FTX) wsHandleData(respRaw []byte) error {
Err: err,
}
}
- f.Websocket.DataHandler <- wshandler.TradeData{
+ f.Websocket.DataHandler <- stream.TradeData{
Timestamp: resultData.TradeData[z].Time,
CurrencyPair: p,
AssetType: a,
@@ -254,7 +322,11 @@ func (f *FTX) wsHandleData(respRaw []byte) error {
if err != nil {
return err
}
- pair := currency.NewPairFromString(resultData.OrderData.Market)
+ var pair currency.Pair
+ pair, err = currency.NewPairFromString(resultData.OrderData.Market)
+ if err != nil {
+ return err
+ }
var assetType asset.Item
assetType, err = f.GetPairAssetType(pair)
if err != nil {
@@ -301,7 +373,7 @@ func (f *FTX) wsHandleData(respRaw []byte) error {
}
f.Websocket.DataHandler <- resultData.FillsData
default:
- f.Websocket.DataHandler <- wshandler.UnhandledMessageWarning{Message: f.Name + wshandler.UnhandledMessage + string(respRaw)}
+ f.Websocket.DataHandler <- stream.UnhandledMessageWarning{Message: f.Name + stream.UnhandledMessage + string(respRaw)}
}
case wsPartial:
switch result["channel"] {
@@ -310,7 +382,10 @@ func (f *FTX) wsHandleData(respRaw []byte) error {
var a asset.Item
market, ok := result["market"]
if ok {
- p = currency.NewPairFromString(market.(string))
+ p, err = currency.NewPairFromString(market.(string))
+ if err != nil {
+ return err
+ }
a, err = f.GetPairAssetType(p)
if err != nil {
return err
@@ -323,7 +398,10 @@ func (f *FTX) wsHandleData(respRaw []byte) error {
}
err = f.WsProcessPartialOB(&resultData.OBData, p, a)
if err != nil {
- f.wsResubToOB(p)
+ err2 := f.wsResubToOB(p)
+ if err2 != nil {
+ f.Websocket.DataHandler <- err2
+ }
return err
}
// reset obchecksum failure blockage for pair
@@ -337,27 +415,16 @@ func (f *FTX) wsHandleData(respRaw []byte) error {
f.Websocket.DataHandler <- resultData.Data
}
case "error":
- f.Websocket.DataHandler <- wshandler.UnhandledMessageWarning{Message: f.Name + wshandler.UnhandledMessage + string(respRaw)}
+ f.Websocket.DataHandler <- stream.UnhandledMessageWarning{
+ Message: f.Name + stream.UnhandledMessage + string(respRaw),
+ }
}
return nil
}
-// Unsubscribe sends a websocket message to stop receiving data from the channel
-func (f *FTX) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
- var unSub WsSub
- a, err := f.GetPairAssetType(channelToSubscribe.Currency)
- if err != nil {
- return err
- }
- unSub.Operation = unsubscribe
- unSub.Channel = channelToSubscribe.Channel
- unSub.Market = f.FormatExchangeCurrency(channelToSubscribe.Currency, a).String()
- return f.WebsocketConn.SendJSONMessage(unSub)
-}
-
// WsProcessUpdateOB processes an update on the orderbook
func (f *FTX) WsProcessUpdateOB(data *WsOrderbookData, p currency.Pair, a asset.Item) error {
- update := wsorderbook.WebsocketOrderbookUpdate{
+ update := buffer.Update{
Asset: a,
Pair: p,
UpdateTime: timestampFromFloat64(data.Time),
@@ -391,27 +458,25 @@ func (f *FTX) WsProcessUpdateOB(data *WsOrderbookData, p currency.Pair, a asset.
p)
return errors.New("checksum failed")
}
- f.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
- Exchange: f.Name,
- Asset: a,
- Pair: p,
- }
-
return nil
}
-func (f *FTX) wsResubToOB(p currency.Pair) {
+func (f *FTX) wsResubToOB(p currency.Pair) error {
if ok := obSuccess[p]; ok {
- return
+ return nil
}
obSuccess[p] = true
- channelToResubscribe := wshandler.WebsocketChannelSubscription{
+ channelToResubscribe := &stream.ChannelSubscription{
Channel: wsOrderbook,
Currency: p,
}
- f.Websocket.ResubscribeToChannel(channelToResubscribe)
+ err := f.Websocket.ResubscribeToChannel(channelToResubscribe)
+ if err != nil {
+ return fmt.Errorf("%s resubscribe to orderbook failure %s", f.Name, err)
+ }
+ return nil
}
// WsProcessPartialOB creates an OB from websocket data
@@ -445,17 +510,7 @@ func (f *FTX) WsProcessPartialOB(data *WsOrderbookData, p currency.Pair, a asset
Pair: p,
ExchangeName: f.Name,
}
-
- if err := f.Websocket.Orderbook.LoadSnapshot(&newOrderBook); err != nil {
- return err
- }
-
- f.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
- Exchange: f.Name,
- Asset: a,
- Pair: p,
- }
- return nil
+ return f.Websocket.Orderbook.LoadSnapshot(&newOrderBook)
}
// CalcPartialOBChecksum calculates checksum of partial OB data received from WS
diff --git a/exchanges/ftx/ftx_wrapper.go b/exchanges/ftx/ftx_wrapper.go
index 7dcdfed2..89591206 100644
--- a/exchanges/ftx/ftx_wrapper.go
+++ b/exchanges/ftx/ftx_wrapper.go
@@ -18,8 +18,8 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -53,12 +53,7 @@ func (f *FTX) SetDefaults() {
f.Verbose = true
f.API.CredentialsValidator.RequiresKey = true
f.API.CredentialsValidator.RequiresSecret = true
- f.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- asset.Futures,
- },
- }
+
spot := currency.PairStore{
RequestFormat: ¤cy.PairFormat{
Uppercase: true,
@@ -79,8 +74,17 @@ func (f *FTX) SetDefaults() {
Delimiter: "-",
},
}
- f.CurrencyPairs.Store(asset.Spot, spot)
- f.CurrencyPairs.Store(asset.Futures, futures)
+
+ err := f.StoreAssetPairFormat(asset.Spot, spot)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
+ }
+
+ err = f.StoreAssetPairFormat(asset.Futures, futures)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
+ }
+
f.Features = exchange.Features{
Supports: exchange.FeaturesSupported{
REST: true,
@@ -139,7 +143,7 @@ func (f *FTX) SetDefaults() {
f.API.Endpoints.URLDefault = ftxAPIURL
f.API.Endpoints.URL = f.API.Endpoints.URLDefault
- f.Websocket = wshandler.New()
+ f.Websocket = stream.New()
f.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
f.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
f.WebsocketOrderbookBufferLimit = exchange.DefaultWebsocketOrderbookBufferLimit
@@ -157,41 +161,28 @@ func (f *FTX) Setup(exch *config.ExchangeConfig) error {
return err
}
- err = f.Websocket.Setup(
- &wshandler.WebsocketSetup{
- Enabled: exch.Features.Enabled.Websocket,
- Verbose: exch.Verbose,
- AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
- WebsocketTimeout: exch.WebsocketTrafficTimeout,
- DefaultURL: ftxWSURL,
- ExchangeName: exch.Name,
- RunningURL: exch.API.Endpoints.WebsocketURL,
- Connector: f.WsConnect,
- Subscriber: f.Subscribe,
- UnSubscriber: f.Unsubscribe,
- Features: &f.Features.Supports.WebsocketCapabilities,
- })
+ err = f.Websocket.Setup(&stream.WebsocketSetup{
+ Enabled: exch.Features.Enabled.Websocket,
+ Verbose: exch.Verbose,
+ AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
+ WebsocketTimeout: exch.WebsocketTrafficTimeout,
+ DefaultURL: ftxWSURL,
+ ExchangeName: exch.Name,
+ RunningURL: exch.API.Endpoints.WebsocketURL,
+ Connector: f.WsConnect,
+ Subscriber: f.Subscribe,
+ UnSubscriber: f.Unsubscribe,
+ GenerateSubscriptions: f.GenerateDefaultSubscriptions,
+ Features: &f.Features.Supports.WebsocketCapabilities,
+ OrderbookBufferLimit: exch.WebsocketOrderbookBufferLimit,
+ })
if err != nil {
return err
}
-
- f.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: f.Name,
- URL: f.Websocket.GetWebsocketURL(),
- ProxyURL: f.Websocket.GetProxyAddress(),
- Verbose: f.Verbose,
+ return f.Websocket.SetupNewConnection(stream.ConnectionSetup{
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
- }
-
- f.Websocket.Orderbook.Setup(
- exch.WebsocketOrderbookBufferLimit,
- false,
- false,
- false,
- false,
- exch.Name)
- return nil
+ })
}
// Start starts the FTX go routine
@@ -256,13 +247,17 @@ func (f *FTX) FetchTradablePairs(a asset.Item) ([]string, error) {
// UpdateTradablePairs updates the exchanges available pairs and stores
// them in the exchanges config
func (f *FTX) UpdateTradablePairs(forceUpdate bool) error {
- for x := range f.CurrencyPairs.AssetTypes {
- pairs, err := f.FetchTradablePairs(f.CurrencyPairs.AssetTypes[x])
+ assets := f.GetAssetTypes()
+ for x := range assets {
+ pairs, err := f.FetchTradablePairs(assets[x])
if err != nil {
return err
}
- err = f.UpdatePairs(currency.NewPairsFromStrings(pairs),
- f.CurrencyPairs.AssetTypes[x], false, forceUpdate)
+ p, err := currency.NewPairsFromStrings(pairs)
+ if err != nil {
+ return err
+ }
+ err = f.UpdatePairs(p, assets[x], false, forceUpdate)
if err != nil {
return err
}
@@ -272,26 +267,41 @@ func (f *FTX) UpdateTradablePairs(forceUpdate bool) error {
// UpdateTicker updates and returns the ticker for a currency pair
func (f *FTX) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
- allPairs := f.GetEnabledPairs(assetType)
+ allPairs, err := f.GetEnabledPairs(assetType)
+ if err != nil {
+ return nil, err
+ }
+
if !allPairs.Contains(p, true) {
allPairs = append(allPairs, p)
}
+
markets, err := f.GetMarkets()
if err != nil {
return nil, err
}
for a := range allPairs {
+ formattedPair, err := f.FormatExchangeCurrency(allPairs[a], assetType)
+ if err != nil {
+ return nil, err
+ }
+
for x := range markets {
- if markets[x].Name != f.FormatExchangeCurrency(allPairs[a], assetType).String() {
+ if markets[x].Name != formattedPair.String() {
continue
}
var resp ticker.Price
- resp.Pair = currency.NewPairFromString(markets[x].Name)
+ resp.Pair, err = currency.NewPairFromString(markets[x].Name)
+ if err != nil {
+ return nil, err
+ }
resp.Last = markets[x].Last
resp.Bid = markets[x].Bid
resp.Ask = markets[x].Ask
resp.LastUpdated = time.Now()
- err = ticker.ProcessTicker(f.Name, &resp, assetType)
+ resp.AssetType = assetType
+ resp.ExchangeName = f.Name
+ err = ticker.ProcessTicker(&resp)
if err != nil {
return nil, err
}
@@ -321,7 +331,11 @@ func (f *FTX) FetchOrderbook(currency currency.Pair, assetType asset.Item) (*ord
// UpdateOrderbook updates and returns the orderbook for a currency pair
func (f *FTX) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
orderBook := new(orderbook.Base)
- tempResp, err := f.GetOrderbook(f.FormatExchangeCurrency(p, assetType).String(), 0)
+ formattedPair, err := f.FormatExchangeCurrency(p, assetType)
+ if err != nil {
+ return nil, err
+ }
+ tempResp, err := f.GetOrderbook(formattedPair.String(), 0)
if err != nil {
return orderBook, err
}
@@ -424,9 +438,15 @@ func (f *FTX) GetFundingHistory() ([]exchange.FundHistory, error) {
// GetExchangeHistory returns historic trade data within the timeframe provided.
func (f *FTX) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestampStart, timestampEnd time.Time) ([]exchange.TradeHistory, error) {
- marketName := f.FormatExchangeCurrency(p, assetType).String()
+ marketName, err := f.FormatExchangeCurrency(p, assetType)
+ if err != nil {
+ return nil, err
+ }
var resp []exchange.TradeHistory
- trades, err := f.GetTrades(marketName, time.Unix(timestampStart.Unix(), 0), time.Unix(timestampEnd.Unix(), 0), 100)
+ trades, err := f.GetTrades(marketName.String(),
+ time.Unix(timestampStart.Unix(), 0),
+ time.Unix(timestampEnd.Unix(), 0),
+ 100)
if err != nil {
return nil, err
}
@@ -453,7 +473,10 @@ func (f *FTX) GetExchangeHistory(p currency.Pair, assetType asset.Item, timestam
if len(trades) != 100 {
break
}
- trades, err = f.GetTrades(marketName, time.Unix(timestampStart.Unix(), 0), time.Unix(trades[len(trades)-1].Time.Unix(), 0), 100)
+ trades, err = f.GetTrades(marketName.String(),
+ time.Unix(timestampStart.Unix(), 0),
+ time.Unix(trades[len(trades)-1].Time.Unix(), 0),
+ 100)
if err != nil {
return resp, err
}
@@ -475,7 +498,12 @@ func (f *FTX) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
s.Side = order.Bid
}
- tempResp, err := f.Order(f.FormatExchangeCurrency(s.Pair, s.AssetType).String(),
+ formattedPair, err := f.FormatExchangeCurrency(s.Pair, s.AssetType)
+ if err != nil {
+ return resp, err
+ }
+
+ tempResp, err := f.Order(formattedPair.String(),
s.Side.String(),
s.Type.String(),
"",
@@ -533,11 +561,16 @@ func (f *FTX) CancelOrder(order *order.Cancel) error {
// CancelAllOrders cancels all orders associated with a currency pair
func (f *FTX) CancelAllOrders(orderCancellation *order.Cancel) (order.CancelAllResponse, error) {
var resp order.CancelAllResponse
- tempMap := make(map[string]string)
- orders, err := f.GetOpenOrders(f.FormatExchangeCurrency(orderCancellation.Pair, orderCancellation.AssetType).String())
+ formattedPair, err := f.FormatExchangeCurrency(orderCancellation.Pair, orderCancellation.AssetType)
if err != nil {
return resp, err
}
+ orders, err := f.GetOpenOrders(formattedPair.String())
+ if err != nil {
+ return resp, err
+ }
+
+ tempMap := make(map[string]string)
for x := range orders {
_, err := f.DeleteOrder(strconv.FormatInt(orders[x].ID, 10))
if err != nil {
@@ -598,7 +631,10 @@ func (f *FTX) GetOrderInfo(orderID string) (order.Detail, error) {
if err != nil {
return resp, err
}
- p := currency.NewPairFromString(orderData.Market)
+ p, err := currency.NewPairFromString(orderData.Market)
+ if err != nil {
+ return resp, err
+ }
assetType, err := f.GetPairAssetType(p)
if err != nil {
return resp, err
@@ -669,7 +705,7 @@ func (f *FTX) WithdrawFiatFundsToInternationalBank(_ *withdraw.Request) (*withdr
}
// GetWebsocket returns a pointer to the exchange websocket
-func (f *FTX) GetWebsocket() (*wshandler.Websocket, error) {
+func (f *FTX) GetWebsocket() (*stream.Websocket, error) {
return f.Websocket, nil
}
@@ -681,12 +717,24 @@ func (f *FTX) GetActiveOrders(getOrdersRequest *order.GetOrdersRequest) ([]order
if err != nil {
return resp, err
}
+
+ formattedPair, err := f.FormatExchangeCurrency(getOrdersRequest.Pairs[x], assetType)
+ if err != nil {
+ return nil, err
+ }
+
var tempResp order.Detail
- orderData, err := f.GetOpenOrders(f.FormatExchangeCurrency(getOrdersRequest.Pairs[x], assetType).String())
+ orderData, err := f.GetOpenOrders(formattedPair.String())
if err != nil {
return resp, err
}
for y := range orderData {
+ var p currency.Pair
+ p, err = currency.NewPairFromString(orderData[y].Market)
+ if err != nil {
+ return nil, err
+ }
+
tempResp.ID = strconv.FormatInt(orderData[y].ID, 10)
tempResp.Amount = orderData[y].Size
tempResp.AssetType = assetType
@@ -694,7 +742,7 @@ func (f *FTX) GetActiveOrders(getOrdersRequest *order.GetOrdersRequest) ([]order
tempResp.Date = orderData[y].CreatedAt
tempResp.Exchange = f.Name
tempResp.ExecutedAmount = orderData[y].Size - orderData[y].RemainingSize
- tempResp.Pair = currency.NewPairFromString(orderData[y].Market)
+ tempResp.Pair = p
tempResp.Price = orderData[y].Price
tempResp.RemainingAmount = orderData[y].RemainingSize
var orderVars OrderVars
@@ -713,18 +761,25 @@ func (f *FTX) GetActiveOrders(getOrdersRequest *order.GetOrdersRequest) ([]order
tempResp.Fee = orderVars.Fee
resp = append(resp, tempResp)
}
- triggerOrderData, err := f.GetOpenTriggerOrders(f.FormatExchangeCurrency(getOrdersRequest.Pairs[x], assetType).String(), getOrdersRequest.Type.String())
+
+ triggerOrderData, err := f.GetOpenTriggerOrders(formattedPair.String(),
+ getOrdersRequest.Type.String())
if err != nil {
return resp, err
}
for z := range triggerOrderData {
+ var p currency.Pair
+ p, err = currency.NewPairFromString(triggerOrderData[z].Market)
+ if err != nil {
+ return nil, err
+ }
tempResp.ID = strconv.FormatInt(triggerOrderData[z].ID, 10)
tempResp.Amount = triggerOrderData[z].Size
tempResp.AssetType = assetType
tempResp.Date = triggerOrderData[z].CreatedAt
tempResp.Exchange = f.Name
tempResp.ExecutedAmount = triggerOrderData[z].FilledSize
- tempResp.Pair = currency.NewPairFromString(triggerOrderData[z].Market)
+ tempResp.Pair = p
tempResp.Price = triggerOrderData[z].AvgFillPrice
tempResp.RemainingAmount = triggerOrderData[z].Size - triggerOrderData[z].FilledSize
tempResp.TriggerPrice = triggerOrderData[z].TriggerPrice
@@ -757,12 +812,24 @@ func (f *FTX) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest) ([]order
if err != nil {
return resp, err
}
- orderData, err := f.FetchOrderHistory(f.FormatExchangeCurrency(getOrdersRequest.Pairs[x], assetType).String(),
+
+ formattedPair, err := f.FormatExchangeCurrency(getOrdersRequest.Pairs[x],
+ assetType)
+ if err != nil {
+ return nil, err
+ }
+
+ orderData, err := f.FetchOrderHistory(formattedPair.String(),
getOrdersRequest.StartTicks, getOrdersRequest.EndTicks, "")
if err != nil {
return resp, err
}
for y := range orderData {
+ var p currency.Pair
+ p, err = currency.NewPairFromString(orderData[y].Market)
+ if err != nil {
+ return nil, err
+ }
tempResp.ID = strconv.FormatInt(orderData[y].ID, 10)
tempResp.Amount = orderData[y].Size
tempResp.AssetType = assetType
@@ -770,7 +837,7 @@ func (f *FTX) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest) ([]order
tempResp.Date = orderData[y].CreatedAt
tempResp.Exchange = f.Name
tempResp.ExecutedAmount = orderData[y].Size - orderData[y].RemainingSize
- tempResp.Pair = currency.NewPairFromString(orderData[y].Market)
+ tempResp.Pair = p
tempResp.Price = orderData[y].Price
tempResp.RemainingAmount = orderData[y].RemainingSize
var orderVars OrderVars
@@ -789,19 +856,28 @@ func (f *FTX) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest) ([]order
tempResp.Fee = orderVars.Fee
resp = append(resp, tempResp)
}
- triggerOrderData, err := f.GetTriggerOrderHistory(f.FormatExchangeCurrency(getOrdersRequest.Pairs[x], assetType).String(),
- getOrdersRequest.StartTicks, getOrdersRequest.EndTicks, strings.ToLower(getOrdersRequest.Side.String()), strings.ToLower(getOrdersRequest.Type.String()), "")
+ triggerOrderData, err := f.GetTriggerOrderHistory(formattedPair.String(),
+ getOrdersRequest.StartTicks,
+ getOrdersRequest.EndTicks,
+ strings.ToLower(getOrdersRequest.Side.String()),
+ strings.ToLower(getOrdersRequest.Type.String()),
+ "")
if err != nil {
return resp, err
}
for z := range triggerOrderData {
+ var p currency.Pair
+ p, err = currency.NewPairFromString(triggerOrderData[z].Market)
+ if err != nil {
+ return nil, err
+ }
tempResp.ID = strconv.FormatInt(triggerOrderData[z].ID, 10)
tempResp.Amount = triggerOrderData[z].Size
tempResp.AssetType = assetType
tempResp.Date = triggerOrderData[z].CreatedAt
tempResp.Exchange = f.Name
tempResp.ExecutedAmount = triggerOrderData[z].FilledSize
- tempResp.Pair = currency.NewPairFromString(triggerOrderData[z].Market)
+ tempResp.Pair = p
tempResp.Price = triggerOrderData[z].AvgFillPrice
tempResp.RemainingAmount = triggerOrderData[z].Size - triggerOrderData[z].FilledSize
tempResp.TriggerPrice = triggerOrderData[z].TriggerPrice
@@ -831,21 +907,14 @@ func (f *FTX) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
// which lets websocket.manageSubscriptions handle subscribing
-func (f *FTX) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- f.Websocket.SubscribeToChannels(channels)
- return nil
+func (f *FTX) SubscribeToWebsocketChannels(channels []stream.ChannelSubscription) error {
+ return f.Websocket.SubscribeToChannels(channels)
}
// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
// which lets websocket.manageSubscriptions handle unsubscribing
-func (f *FTX) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- f.Websocket.RemoveSubscribedChannels(channels)
- return nil
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func (f *FTX) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return f.Websocket.GetSubscriptions(), nil
+func (f *FTX) UnsubscribeToWebsocketChannels(channels []stream.ChannelSubscription) error {
+ return f.Websocket.UnsubscribeChannels(channels)
}
// AuthenticateWebsocket sends an authentication message to the websocket
@@ -868,7 +937,12 @@ func (f *FTX) GetHistoricCandles(p currency.Pair, a asset.Item, start, end time.
}
}
- ohlcData, err := f.GetHistoricalData(f.FormatExchangeCurrency(p, a).String(),
+ formattedPair, err := f.FormatExchangeCurrency(p, a)
+ if err != nil {
+ return kline.Item{}, err
+ }
+
+ ohlcData, err := f.GetHistoricalData(formattedPair.String(),
f.FormatExchangeKlineInterval(interval),
strconv.FormatInt(int64(f.Features.Enabled.Kline.ResultLimit), 10),
start, end)
@@ -912,8 +986,14 @@ func (f *FTX) GetHistoricCandlesExtended(p currency.Pair, a asset.Item, start, e
}
dates := kline.CalcDateRanges(start, end, interval, f.Features.Enabled.Kline.ResultLimit)
+
+ formattedPair, err := f.FormatExchangeCurrency(p, a)
+ if err != nil {
+ return kline.Item{}, err
+ }
+
for x := range dates {
- ohlcData, err := f.GetHistoricalData(f.FormatExchangeCurrency(p, a).String(),
+ ohlcData, err := f.GetHistoricalData(formattedPair.String(),
f.FormatExchangeKlineInterval(interval),
strconv.FormatInt(int64(f.Features.Enabled.Kline.ResultLimit), 10),
dates[x].Start, dates[x].End)
diff --git a/exchanges/gateio/gateio.go b/exchanges/gateio/gateio.go
index ba22b045..b0f19d2c 100644
--- a/exchanges/gateio/gateio.go
+++ b/exchanges/gateio/gateio.go
@@ -15,7 +15,6 @@ import (
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -44,7 +43,6 @@ const (
// Gateio is the overarching type across this package
type Gateio struct {
- WebsocketConn *wshandler.WebsocketConnection
exchange.Base
}
diff --git a/exchanges/gateio/gateio_test.go b/exchanges/gateio/gateio_test.go
index 394c3139..daa1c993 100644
--- a/exchanges/gateio/gateio_test.go
+++ b/exchanges/gateio/gateio_test.go
@@ -18,7 +18,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -48,7 +48,7 @@ func TestMain(m *testing.M) {
gConf.API.AuthenticatedWebsocketSupport = true
gConf.API.Credentials.Key = apiKey
gConf.API.Credentials.Secret = apiSecret
-
+ g.Websocket = sharedtestvalues.NewTestWebsocket()
err = g.Setup(gConf)
if err != nil {
log.Fatal("GateIO setup error", err)
@@ -76,14 +76,14 @@ func TestGetMarketInfo(t *testing.T) {
func TestSpotNewOrder(t *testing.T) {
t.Parallel()
- if !areTestAPIKeysSet() && !canManipulateRealOrders {
+ if !areTestAPIKeysSet() || !canManipulateRealOrders {
t.Skip()
}
_, err := g.SpotNewOrder(SpotNewOrderRequestParams{
Symbol: "btc_usdt",
- Amount: 1.1,
- Price: 10.1,
+ Amount: -1,
+ Price: 100000,
Type: order.Sell.Lower(),
})
if err != nil {
@@ -94,7 +94,7 @@ func TestSpotNewOrder(t *testing.T) {
func TestCancelExistingOrder(t *testing.T) {
t.Parallel()
- if !areTestAPIKeysSet() && !canManipulateRealOrders {
+ if !areTestAPIKeysSet() || !canManipulateRealOrders {
t.Skip()
}
@@ -485,29 +485,18 @@ func TestGetOrderInfo(t *testing.T) {
// TestWsGetBalance dials websocket, sends balance request.
func TestWsGetBalance(t *testing.T) {
if !g.Websocket.IsEnabled() && !g.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
- t.Skip(wshandler.WebsocketNotEnabled)
- }
- g.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: g.Name,
- URL: gateioWebsocketEndpoint,
- Verbose: g.Verbose,
- RateLimit: gateioWebsocketRateLimit,
- ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
- ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
+ t.Skip(stream.WebsocketNotEnabled)
}
var dialer websocket.Dialer
- err := g.WebsocketConn.Dial(&dialer, http.Header{})
+ err := g.Websocket.Conn.Dial(&dialer, http.Header{})
if err != nil {
t.Fatal(err)
}
go g.wsReadData()
- resp, err := g.wsServerSignIn()
+ err = g.wsServerSignIn()
if err != nil {
t.Fatal(err)
}
- if resp.Result.Status != "success" {
- t.Fatal("Unsuccessful login")
- }
_, err = g.wsGetBalance([]string{"EOS", "BTC"})
if err != nil {
t.Error(err)
@@ -521,30 +510,19 @@ func TestWsGetBalance(t *testing.T) {
// TestWsGetOrderInfo dials websocket, sends order info request.
func TestWsGetOrderInfo(t *testing.T) {
if !g.Websocket.IsEnabled() && !g.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
- t.Skip(wshandler.WebsocketNotEnabled)
- }
- g.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: g.Name,
- URL: gateioWebsocketEndpoint,
- Verbose: g.Verbose,
- RateLimit: gateioWebsocketRateLimit,
- ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
- ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
+ t.Skip(stream.WebsocketNotEnabled)
}
var dialer websocket.Dialer
- err := g.WebsocketConn.Dial(&dialer, http.Header{})
+ err := g.Websocket.Conn.Dial(&dialer, http.Header{})
if err != nil {
t.Fatal(err)
}
go g.wsReadData()
- resp, err := g.wsServerSignIn()
+ err = g.wsServerSignIn()
if err != nil {
t.Fatal(err)
}
- if resp.Result.Status != "success" {
- t.Fatal("Unsuccessful login")
- }
- _, err = g.wsGetOrderInfo("EOS_USDT", 0, 1000)
+ _, err = g.wsGetOrderInfo("EOS_USDT", 0, 100)
if err != nil {
t.Error(err)
}
@@ -554,47 +532,34 @@ func setupWSTestAuth(t *testing.T) {
if wsSetupRan {
return
}
- if !g.Websocket.IsEnabled() && !g.API.AuthenticatedWebsocketSupport {
- t.Skip(wshandler.WebsocketNotEnabled)
+ if !g.Websocket.IsEnabled() && !g.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
+ t.Skip(stream.WebsocketNotEnabled)
}
- g.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: g.Name,
- URL: gateioWebsocketEndpoint,
- Verbose: g.Verbose,
- RateLimit: gateioWebsocketRateLimit,
- ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
- ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
- }
- var dialer websocket.Dialer
- err := g.WebsocketConn.Dial(&dialer, http.Header{})
-
- g.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- g.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
+ err := g.Websocket.Connect()
if err != nil {
t.Fatal(err)
}
- go g.wsReadData()
wsSetupRan = true
}
-// TestWsUnsubscribe dials websocket, sends an unsubscribe request.
-func TestWsUnsubscribe(t *testing.T) {
- setupWSTestAuth(t)
- err := g.Unsubscribe(wshandler.WebsocketChannelSubscription{
- Channel: "ticker.subscribe",
- Currency: currency.NewPairWithDelimiter(currency.BTC.String(), currency.USDT.String(), "_"),
- })
- if err != nil {
- t.Error(err)
- }
-}
-
// TestWsSubscribe dials websocket, sends a subscribe request.
func TestWsSubscribe(t *testing.T) {
setupWSTestAuth(t)
- err := g.Subscribe(wshandler.WebsocketChannelSubscription{
- Channel: "ticker.subscribe",
- Currency: currency.NewPairWithDelimiter(currency.BTC.String(), currency.USDT.String(), "_"),
+ err := g.Subscribe([]stream.ChannelSubscription{
+ {
+ Channel: "ticker.subscribe",
+ Currency: currency.NewPairWithDelimiter(currency.BTC.String(), currency.USDT.String(), "_"),
+ },
+ })
+ if err != nil {
+ t.Error(err)
+ }
+
+ err = g.Unsubscribe([]stream.ChannelSubscription{
+ {
+ Channel: "ticker.subscribe",
+ Currency: currency.NewPairWithDelimiter(currency.BTC.String(), currency.USDT.String(), "_"),
+ },
})
if err != nil {
t.Error(err)
@@ -603,12 +568,12 @@ func TestWsSubscribe(t *testing.T) {
func TestWsTicker(t *testing.T) {
pressXToJSON := []byte(`{
- "method": "ticker.update",
- "params":
+ "method": "ticker.update",
+ "params":
[
- "BTC_USDT",
+ "BTC_USDT",
{
- "period": 86400,
+ "period": 86400,
"open": "0",
"close": "0",
"high": "0",
@@ -630,9 +595,9 @@ func TestWsTicker(t *testing.T) {
func TestWsTrade(t *testing.T) {
pressXToJSON := []byte(`{
"method": "trades.update",
- "params":
+ "params":
[
- "BTC_USDT",
+ "BTC_USDT",
[
{
"id": 7172173,
@@ -654,23 +619,23 @@ func TestWsTrade(t *testing.T) {
func TestWsDepth(t *testing.T) {
pressXToJSON := []byte(`{
- "method": "depth.update",
+ "method": "depth.update",
"params": [
- true,
+ true,
{
"asks": [
- [
+ [
"8000.00",
"9.6250"
]
],
- "bids": [
- [
+ "bids": [
+ [
"8000.00",
"9.6250"
- ]
+ ]
]
- },
+ },
"BTC_USDT"
],
"id": null
@@ -736,7 +701,7 @@ func TestWsOrderUpdate(t *testing.T) {
func TestWsBalanceUpdate(t *testing.T) {
pressXToJSON := []byte(`{
- "method": "balance.update",
+ "method": "balance.update",
"params": [{"EOS": {"available": "96.765323611874", "freeze": "11"}}],
"id": 1234
}`)
@@ -765,18 +730,24 @@ func TestParseTime(t *testing.T) {
}
func TestGetHistoricCandles(t *testing.T) {
- currencyPair := currency.NewPairFromString("BTC_USDT")
+ currencyPair, err := currency.NewPairFromString("BTC_USDT")
+ if err != nil {
+ t.Fatal(err)
+ }
startTime := time.Now().Add(-time.Hour * 6)
- _, err := g.GetHistoricCandles(currencyPair, asset.Spot, startTime, time.Now(), kline.OneMin)
+ _, err = g.GetHistoricCandles(currencyPair, asset.Spot, startTime, time.Now(), kline.OneMin)
if err != nil {
t.Fatal(err)
}
}
func TestGetHistoricCandlesExtended(t *testing.T) {
- currencyPair := currency.NewPairFromString("BTC_USDT")
+ currencyPair, err := currency.NewPairFromString("BTC_USDT")
+ if err != nil {
+ t.Fatal(err)
+ }
startTime := time.Now().Add(-time.Hour * 6)
- _, err := g.GetHistoricCandlesExtended(currencyPair, asset.Spot, startTime, time.Now(), kline.OneMin)
+ _, err = g.GetHistoricCandlesExtended(currencyPair, asset.Spot, startTime, time.Now(), kline.OneMin)
if err != nil {
t.Fatal(err)
}
@@ -812,3 +783,26 @@ func Test_FormatExchangeKlineInterval(t *testing.T) {
})
}
}
+
+func TestGenerateDefaultSubscriptions(t *testing.T) {
+ err := g.CurrencyPairs.EnablePair(asset.Spot, currency.NewPair(
+ currency.LTC,
+ currency.USDT,
+ ))
+ if err != nil {
+ t.Fatal(err)
+ }
+ subs, err := g.GenerateDefaultSubscriptions()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ payload, err := g.generatePayload(subs)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if len(payload) != 4 {
+ t.Fatal("unexpected payload length")
+ }
+}
diff --git a/exchanges/gateio/gateio_types.go b/exchanges/gateio/gateio_types.go
index a8483a73..184923b4 100644
--- a/exchanges/gateio/gateio_types.go
+++ b/exchanges/gateio/gateio_types.go
@@ -5,6 +5,7 @@ import (
"time"
"github.com/thrasher-corp/gocryptotrader/currency"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
)
// TimeInterval Interval represents interval enum.
@@ -379,9 +380,10 @@ var WithdrawalFees = map[currency.Code]float64{
// WebsocketRequest defines the initial request in JSON
type WebsocketRequest struct {
- ID int64 `json:"id"`
- Method string `json:"method"`
- Params []interface{} `json:"params"`
+ ID int64 `json:"id"`
+ Method string `json:"method"`
+ Params []interface{} `json:"params"`
+ Channels []stream.ChannelSubscription `json:"-"` // used for tracking associated channel subs on batched requests
}
// WebsocketResponse defines a websocket response from gateio
@@ -437,6 +439,7 @@ type WebsocketBalanceCurrency struct {
// WebSocketOrderQueryResult data returned from a websocket ordre query holds slice of WebSocketOrderQueryRecords
type WebSocketOrderQueryResult struct {
+ Error WebsocketError `json:"error"`
Limit int `json:"limit"`
Offset int `json:"offset"`
Total int `json:"total"`
@@ -462,7 +465,10 @@ type WebSocketOrderQueryRecords struct {
// WebsocketAuthenticationResponse contains the result of a login request
type WebsocketAuthenticationResponse struct {
- Error string `json:"error,omitempty"`
+ Error struct {
+ Code int `json:"code"`
+ Message string `json:"message"`
+ } `json:"error"`
Result struct {
Status string `json:"status"`
} `json:"result"`
@@ -478,7 +484,7 @@ type wsGetBalanceRequest struct {
// WsGetBalanceResponse stores WS GetBalance response
type WsGetBalanceResponse struct {
- Error interface{} `json:"error"`
+ Error WebsocketError `json:"error"`
Result map[string]WsGetBalanceResponseData `json:"result"`
ID int64 `json:"id"`
}
diff --git a/exchanges/gateio/gateio_websocket.go b/exchanges/gateio/gateio_websocket.go
index ac2bd682..40a400c3 100644
--- a/exchanges/gateio/gateio_websocket.go
+++ b/exchanges/gateio/gateio_websocket.go
@@ -10,6 +10,7 @@ import (
"time"
"github.com/gorilla/websocket"
+ "github.com/thrasher-corp/gocryptotrader/common"
"github.com/thrasher-corp/gocryptotrader/common/convert"
"github.com/thrasher-corp/gocryptotrader/common/crypto"
"github.com/thrasher-corp/gocryptotrader/currency"
@@ -17,10 +18,9 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wsorderbook"
- "github.com/thrasher-corp/gocryptotrader/log"
)
const (
@@ -31,77 +31,87 @@ const (
// WsConnect initiates a websocket connection
func (g *Gateio) WsConnect() error {
if !g.Websocket.IsEnabled() || !g.IsEnabled() {
- return errors.New(wshandler.WebsocketNotEnabled)
+ return errors.New(stream.WebsocketNotEnabled)
}
var dialer websocket.Dialer
- err := g.WebsocketConn.Dial(&dialer, http.Header{})
+ err := g.Websocket.Conn.Dial(&dialer, http.Header{})
if err != nil {
return err
}
go g.wsReadData()
- _, err = g.wsServerSignIn()
- if err != nil {
- log.Errorf(log.ExchangeSys, "%v - authentication failed: %v\n", g.Name, err)
- g.Websocket.SetCanUseAuthenticatedEndpoints(false)
+
+ if g.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
+ err = g.wsServerSignIn()
+ if err != nil {
+ g.Websocket.DataHandler <- err
+ g.Websocket.SetCanUseAuthenticatedEndpoints(false)
+ } else {
+ var authsubs []stream.ChannelSubscription
+ authsubs, err = g.GenerateAuthenticatedSubscriptions()
+ if err != nil {
+ g.Websocket.DataHandler <- err
+ g.Websocket.SetCanUseAuthenticatedEndpoints(false)
+ } else {
+ err = g.Websocket.SubscribeToChannels(authsubs)
+ if err != nil {
+ g.Websocket.DataHandler <- err
+ g.Websocket.SetCanUseAuthenticatedEndpoints(false)
+ }
+ }
+ }
}
- g.GenerateAuthenticatedSubscriptions()
- g.GenerateDefaultSubscriptions()
- return nil
+
+ subs, err := g.GenerateDefaultSubscriptions()
+ if err != nil {
+ return err
+ }
+ return g.Websocket.SubscribeToChannels(subs)
}
-func (g *Gateio) wsServerSignIn() (*WebsocketAuthenticationResponse, error) {
- if !g.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
- return nil, fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", g.Name)
- }
+func (g *Gateio) wsServerSignIn() error {
nonce := int(time.Now().Unix() * 1000)
sigTemp := g.GenerateSignature(strconv.Itoa(nonce))
signature := crypto.Base64Encode(sigTemp)
signinWsRequest := WebsocketRequest{
- ID: g.WebsocketConn.GenerateMessageID(true),
+ ID: g.Websocket.Conn.GenerateMessageID(false),
Method: "server.sign",
Params: []interface{}{g.API.Credentials.Key, signature, nonce},
}
- resp, err := g.WebsocketConn.SendMessageReturnResponse(signinWsRequest.ID, signinWsRequest)
+ resp, err := g.Websocket.Conn.SendMessageReturnResponse(signinWsRequest.ID,
+ signinWsRequest)
if err != nil {
g.Websocket.SetCanUseAuthenticatedEndpoints(false)
- return nil, err
+ return err
}
var response WebsocketAuthenticationResponse
err = json.Unmarshal(resp, &response)
if err != nil {
g.Websocket.SetCanUseAuthenticatedEndpoints(false)
- return nil, err
+ return err
}
if response.Result.Status == "success" {
g.Websocket.SetCanUseAuthenticatedEndpoints(true)
+ return nil
}
- return &response, nil
+
+ return fmt.Errorf("%s cannot authenticate websocket connection: %s",
+ g.Name,
+ response.Result.Status)
}
// wsReadData receives and passes on websocket messages for processing
func (g *Gateio) wsReadData() {
g.Websocket.Wg.Add(1)
-
- defer func() {
- g.Websocket.Wg.Done()
- }()
+ defer g.Websocket.Wg.Done()
for {
- select {
- case <-g.Websocket.ShutdownC:
+ resp := g.Websocket.Conn.ReadMessage()
+ if resp.Raw == nil {
return
-
- default:
- resp, err := g.WebsocketConn.ReadMessage()
- if err != nil {
- g.Websocket.ReadMessageErrors <- err
- return
- }
- g.Websocket.TrafficAlert <- struct{}{}
- err = g.wsHandleData(resp.Raw)
- if err != nil {
- g.Websocket.DataHandler <- err
- }
+ }
+ err := g.wsHandleData(resp.Raw)
+ if err != nil {
+ g.Websocket.DataHandler <- err
}
}
}
@@ -114,8 +124,7 @@ func (g *Gateio) wsHandleData(respRaw []byte) error {
}
if result.ID > 0 {
- if g.WebsocketConn.IsIDWaitingForResponse(result.ID) {
- g.WebsocketConn.SetResponseIDAndData(result.ID, respRaw)
+ if g.Websocket.Match.IncomingWithData(result.ID, respRaw) {
return nil
}
}
@@ -125,8 +134,7 @@ func (g *Gateio) wsHandleData(respRaw []byte) error {
g.Websocket.SetCanUseAuthenticatedEndpoints(false)
return fmt.Errorf("%v - authentication failed: %v", g.Name, err)
}
- return fmt.Errorf("%v error %s",
- g.Name, result.Error.Message)
+ return fmt.Errorf("%v error %s", g.Name, result.Error.Message)
}
switch {
@@ -142,6 +150,12 @@ func (g *Gateio) wsHandleData(respRaw []byte) error {
return err
}
+ var p currency.Pair
+ p, err = currency.NewPairFromString(c)
+ if err != nil {
+ return err
+ }
+
g.Websocket.DataHandler <- &ticker.Price{
ExchangeName: g.Name,
Open: wsTicker.Open,
@@ -152,7 +166,7 @@ func (g *Gateio) wsHandleData(respRaw []byte) error {
Low: wsTicker.Low,
Last: wsTicker.Last,
AssetType: asset.Spot,
- Pair: currency.NewPairFromString(c),
+ Pair: p,
}
case strings.Contains(result.Method, "trades"):
@@ -167,6 +181,12 @@ func (g *Gateio) wsHandleData(respRaw []byte) error {
return err
}
+ var p currency.Pair
+ p, err = currency.NewPairFromString(c)
+ if err != nil {
+ return err
+ }
+
for i := range trades {
var tSide order.Side
tSide, err = order.StringToOrderSide(trades[i].Type)
@@ -176,9 +196,9 @@ func (g *Gateio) wsHandleData(respRaw []byte) error {
Err: err,
}
}
- g.Websocket.DataHandler <- wshandler.TradeData{
+ g.Websocket.DataHandler <- stream.TradeData{
Timestamp: time.Now(),
- CurrencyPair: currency.NewPairFromString(c),
+ CurrencyPair: p,
AssetType: asset.Spot,
Exchange: g.Name,
Price: trades[i].Price,
@@ -244,7 +264,13 @@ func (g *Gateio) wsHandleData(respRaw []byte) error {
if err != nil {
return err
}
- p := currency.NewPairFromString(invalidJSON["market"].(string))
+
+ var p currency.Pair
+ p, err = currency.NewPairFromString(invalidJSON["market"].(string))
+ if err != nil {
+ return err
+ }
+
var a asset.Item
a, err = g.GetPairAssetType(p)
if err != nil {
@@ -324,6 +350,12 @@ func (g *Gateio) wsHandleData(respRaw []byte) error {
g.Websocket.DataHandler <- errors.New("gatio websocket error - cannot access ask or bid data")
}
+ var p currency.Pair
+ p, err = currency.NewPairFromString(c)
+ if err != nil {
+ return err
+ }
+
if IsSnapshot {
if !askOk {
g.Websocket.DataHandler <- errors.New("gatio websocket error - cannot access ask data")
@@ -337,7 +369,7 @@ func (g *Gateio) wsHandleData(respRaw []byte) error {
newOrderBook.Asks = asks
newOrderBook.Bids = bids
newOrderBook.AssetType = asset.Spot
- newOrderBook.Pair = currency.NewPairFromString(c)
+ newOrderBook.Pair = p
newOrderBook.ExchangeName = g.Name
err = g.Websocket.Orderbook.LoadSnapshot(&newOrderBook)
@@ -345,25 +377,17 @@ func (g *Gateio) wsHandleData(respRaw []byte) error {
return err
}
} else {
- err = g.Websocket.Orderbook.Update(
- &wsorderbook.WebsocketOrderbookUpdate{
- Asks: asks,
- Bids: bids,
- Pair: currency.NewPairFromString(c),
- UpdateTime: time.Now(),
- Asset: asset.Spot,
- })
+ err = g.Websocket.Orderbook.Update(&buffer.Update{
+ Asks: asks,
+ Bids: bids,
+ Pair: p,
+ UpdateTime: time.Now(),
+ Asset: asset.Spot,
+ })
if err != nil {
return err
}
}
-
- g.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
- Pair: currency.NewPairFromString(c),
- Asset: asset.Spot,
- Exchange: g.Name,
- }
-
case strings.Contains(result.Method, "kline"):
var data []interface{}
err = json.Unmarshal(result.Params[0], &data)
@@ -391,9 +415,14 @@ func (g *Gateio) wsHandleData(respRaw []byte) error {
return err
}
- g.Websocket.DataHandler <- wshandler.KlineData{
+ p, err := currency.NewPairFromString(data[7].(string))
+ if err != nil {
+ return err
+ }
+
+ g.Websocket.DataHandler <- stream.KlineData{
Timestamp: time.Now(),
- Pair: currency.NewPairFromString(data[7].(string)),
+ Pair: p,
AssetType: asset.Spot,
Exchange: g.Name,
OpenPrice: open,
@@ -403,36 +432,48 @@ func (g *Gateio) wsHandleData(respRaw []byte) error {
Volume: volume,
}
default:
- g.Websocket.DataHandler <- wshandler.UnhandledMessageWarning{Message: g.Name + wshandler.UnhandledMessage + string(respRaw)}
+ g.Websocket.DataHandler <- stream.UnhandledMessageWarning{
+ Message: g.Name + stream.UnhandledMessage + string(respRaw),
+ }
return nil
}
return nil
}
-// GenerateAuthenticatedSubscriptions Adds authenticated subscriptions to websocket to be handled by ManageSubscriptions()
-func (g *Gateio) GenerateAuthenticatedSubscriptions() {
+// GenerateAuthenticatedSubscriptions returns authenticated subscriptions
+func (g *Gateio) GenerateAuthenticatedSubscriptions() ([]stream.ChannelSubscription, error) {
if !g.Websocket.CanUseAuthenticatedEndpoints() {
- return
+ return nil, nil
}
var channels = []string{"balance.subscribe", "order.subscribe"}
- var subscriptions []wshandler.WebsocketChannelSubscription
- enabledCurrencies := g.GetEnabledPairs(asset.Spot)
+ var subscriptions []stream.ChannelSubscription
+ enabledCurrencies, err := g.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return nil, err
+ }
for i := range channels {
for j := range enabledCurrencies {
- subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
Channel: channels[i],
Currency: enabledCurrencies[j],
+ Asset: asset.Spot,
})
}
}
- g.Websocket.SubscribeToChannels(subscriptions)
+ return subscriptions, nil
}
-// GenerateDefaultSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions()
-func (g *Gateio) GenerateDefaultSubscriptions() {
- var channels = []string{"ticker.subscribe", "trades.subscribe", "depth.subscribe", "kline.subscribe"}
- var subscriptions []wshandler.WebsocketChannelSubscription
- enabledCurrencies := g.GetEnabledPairs(asset.Spot)
+// GenerateDefaultSubscriptions returns default subscriptions
+func (g *Gateio) GenerateDefaultSubscriptions() ([]stream.ChannelSubscription, error) {
+ var channels = []string{"ticker.subscribe",
+ "trades.subscribe",
+ "depth.subscribe",
+ "kline.subscribe"}
+ var subscriptions []stream.ChannelSubscription
+ enabledCurrencies, err := g.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return nil, err
+ }
for i := range channels {
for j := range enabledCurrencies {
params := make(map[string]interface{})
@@ -442,66 +483,157 @@ func (g *Gateio) GenerateDefaultSubscriptions() {
} else if strings.EqualFold(channels[i], "kline.subscribe") {
params["interval"] = 1800
}
- subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
+
+ fpair, err := g.FormatExchangeCurrency(enabledCurrencies[j],
+ asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
Channel: channels[i],
- Currency: enabledCurrencies[j],
+ Currency: fpair.Upper(),
Params: params,
+ Asset: asset.Spot,
})
}
}
- g.Websocket.SubscribeToChannels(subscriptions)
+ return subscriptions, nil
}
// Subscribe sends a websocket message to receive data from the channel
-func (g *Gateio) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
- params := []interface{}{g.FormatExchangeCurrency(channelToSubscribe.Currency,
- asset.Spot).Upper()}
-
- for i := range channelToSubscribe.Params {
- params = append(params, channelToSubscribe.Params[i])
- }
-
- subscribe := WebsocketRequest{
- ID: g.WebsocketConn.GenerateMessageID(true),
- Method: channelToSubscribe.Channel,
- Params: params,
- }
-
- resp, err := g.WebsocketConn.SendMessageReturnResponse(subscribe.ID, subscribe)
+func (g *Gateio) Subscribe(channelsToSubscribe []stream.ChannelSubscription) error {
+ payloads, err := g.generatePayload(channelsToSubscribe)
if err != nil {
return err
}
- var response WebsocketAuthenticationResponse
- err = json.Unmarshal(resp, &response)
- if err != nil {
- return err
+
+ var errs common.Errors
+ for k := range payloads {
+ resp, err := g.Websocket.Conn.SendMessageReturnResponse(payloads[k].ID, payloads[k])
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ var response WebsocketAuthenticationResponse
+ err = json.Unmarshal(resp, &response)
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ if response.Result.Status != "success" {
+ errs = append(errs, fmt.Errorf("%v could not subscribe to %v",
+ g.Name,
+ payloads[k].Method))
+ continue
+ }
+ g.Websocket.AddSuccessfulSubscriptions(payloads[k].Channels...)
}
- if response.Result.Status != "success" {
- return fmt.Errorf("%v could not subscribe to %v", g.Name, channelToSubscribe.Channel)
+ if errs != nil {
+ return errs
}
return nil
}
+func (g *Gateio) generatePayload(channelsToSubscribe []stream.ChannelSubscription) ([]WebsocketRequest, error) {
+ if len(channelsToSubscribe) == 0 {
+ return nil, errors.New("cannot generate payload, no channels supplied")
+ }
+
+ var payloads []WebsocketRequest
+channels:
+ for i := range channelsToSubscribe {
+ // Ensures params are in order
+ params := []interface{}{channelsToSubscribe[i].Currency}
+ if strings.EqualFold(channelsToSubscribe[i].Channel, "depth.subscribe") {
+ params = append(params,
+ channelsToSubscribe[i].Params["limit"],
+ channelsToSubscribe[i].Params["interval"])
+ } else if strings.EqualFold(channelsToSubscribe[i].Channel, "kline.subscribe") {
+ params = append(params, channelsToSubscribe[i].Params["interval"])
+ }
+
+ for j := range payloads {
+ if payloads[j].Method == channelsToSubscribe[i].Channel {
+ switch {
+ case strings.EqualFold(channelsToSubscribe[i].Channel, "depth.subscribe"):
+ if len(payloads[j].Params) == 3 {
+ // If more than one currency pair we need to send as
+ // matrix
+ _, ok := payloads[j].Params[0].(currency.Pair)
+ if ok {
+ var bucket = payloads[j].Params
+ payloads[j].Params = nil
+ payloads[j].Params = append(payloads[j].Params, bucket)
+ }
+ }
+
+ payloads[j].Params = append(payloads[j].Params, params)
+ case strings.EqualFold(channelsToSubscribe[i].Channel, "kline.subscribe"):
+ // Can only subscribe one market at the same time, market
+ // list is not supported currently. For multiple
+ // subscriptions, only the last one takes effect.
+ default:
+ payloads[j].Params = append(payloads[j].Params, params...)
+ }
+ payloads[j].Channels = append(payloads[j].Channels, channelsToSubscribe[i])
+ continue channels
+ }
+ }
+
+ payloads = append(payloads, WebsocketRequest{
+ ID: g.Websocket.Conn.GenerateMessageID(false),
+ Method: channelsToSubscribe[i].Channel,
+ Params: params,
+ Channels: []stream.ChannelSubscription{channelsToSubscribe[i]},
+ })
+ }
+ return payloads, nil
+}
+
// Unsubscribe sends a websocket message to stop receiving data from the channel
-func (g *Gateio) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
- unsbuscribeText := strings.Replace(channelToSubscribe.Channel, "subscribe", "unsubscribe", 1)
- subscribe := WebsocketRequest{
- ID: g.WebsocketConn.GenerateMessageID(true),
- Method: unsbuscribeText,
- Params: []interface{}{g.FormatExchangeCurrency(channelToSubscribe.Currency,
- asset.Spot).Upper(), 1800},
- }
- resp, err := g.WebsocketConn.SendMessageReturnResponse(subscribe.ID, subscribe)
- if err != nil {
- return err
- }
- var response WebsocketAuthenticationResponse
- err = json.Unmarshal(resp, &response)
- if err != nil {
- return err
- }
- if response.Result.Status != "success" {
- return fmt.Errorf("%v could not subscribe to %v", g.Name, channelToSubscribe.Channel)
+func (g *Gateio) Unsubscribe(channelsToUnsubscribe []stream.ChannelSubscription) error {
+ // NOTE: This function does not take in parameters, it cannot unsubscribe a
+ // single item but a full channel. i.e. if you subscribe to ticker BTC_USDT
+ // & LTC_USDT this function will unsubscribe both. This function will be
+ // kept unlinked to the websocket subsystem and a full connection flush will
+ // occur when currency items are disabled.
+ var channelsThusFar []string
+ for i := range channelsToUnsubscribe {
+ if common.StringDataCompare(channelsThusFar,
+ channelsToUnsubscribe[i].Channel) {
+ continue
+ }
+
+ channelsThusFar = append(channelsThusFar,
+ channelsToUnsubscribe[i].Channel)
+
+ unsubscribeText := strings.Replace(channelsToUnsubscribe[i].Channel,
+ "subscribe",
+ "unsubscribe",
+ 1)
+
+ unsubscribe := WebsocketRequest{
+ ID: g.Websocket.Conn.GenerateMessageID(false),
+ Method: unsubscribeText,
+ Params: []interface{}{channelsToUnsubscribe[i].Currency.String()},
+ }
+
+ resp, err := g.Websocket.Conn.SendMessageReturnResponse(unsubscribe.ID,
+ unsubscribe)
+ if err != nil {
+ return err
+ }
+ var response WebsocketAuthenticationResponse
+ err = json.Unmarshal(resp, &response)
+ if err != nil {
+ return err
+ }
+ if response.Result.Status != "success" {
+ return fmt.Errorf("%v could not subscribe to %v",
+ g.Name,
+ channelsToUnsubscribe[i].Channel)
+ }
}
return nil
}
@@ -511,11 +643,11 @@ func (g *Gateio) wsGetBalance(currencies []string) (*WsGetBalanceResponse, error
return nil, fmt.Errorf("%v not authorised to get balance", g.Name)
}
balanceWsRequest := wsGetBalanceRequest{
- ID: g.WebsocketConn.GenerateMessageID(false),
+ ID: g.Websocket.Conn.GenerateMessageID(false),
Method: "balance.query",
Params: currencies,
}
- resp, err := g.WebsocketConn.SendMessageReturnResponse(balanceWsRequest.ID, balanceWsRequest)
+ resp, err := g.Websocket.Conn.SendMessageReturnResponse(balanceWsRequest.ID, balanceWsRequest)
if err != nil {
return nil, err
}
@@ -525,6 +657,12 @@ func (g *Gateio) wsGetBalance(currencies []string) (*WsGetBalanceResponse, error
return &balance, err
}
+ if balance.Error.Message != "" {
+ return nil, fmt.Errorf("%s websocket error: %s",
+ g.Name,
+ balance.Error.Message)
+ }
+
return &balance, nil
}
@@ -533,7 +671,7 @@ func (g *Gateio) wsGetOrderInfo(market string, offset, limit int) (*WebSocketOrd
return nil, fmt.Errorf("%v not authorised to get order info", g.Name)
}
ord := WebsocketRequest{
- ID: g.WebsocketConn.GenerateMessageID(true),
+ ID: g.Websocket.Conn.GenerateMessageID(false),
Method: "order.query",
Params: []interface{}{
market,
@@ -541,14 +679,23 @@ func (g *Gateio) wsGetOrderInfo(market string, offset, limit int) (*WebSocketOrd
limit,
},
}
- resp, err := g.WebsocketConn.SendMessageReturnResponse(ord.ID, ord)
+
+ resp, err := g.Websocket.Conn.SendMessageReturnResponse(ord.ID, ord)
if err != nil {
return nil, err
}
+
var orderQuery WebSocketOrderQueryResult
err = json.Unmarshal(resp, &orderQuery)
if err != nil {
return &orderQuery, err
}
+
+ if orderQuery.Error.Message != "" {
+ return nil, fmt.Errorf("%s websocket error: %s",
+ g.Name,
+ orderQuery.Error.Message)
+ }
+
return &orderQuery, nil
}
diff --git a/exchanges/gateio/gateio_wrapper.go b/exchanges/gateio/gateio_wrapper.go
index d240aa05..60e59104 100644
--- a/exchanges/gateio/gateio_wrapper.go
+++ b/exchanges/gateio/gateio_wrapper.go
@@ -20,8 +20,8 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -57,18 +57,11 @@ func (g *Gateio) SetDefaults() {
g.API.CredentialsValidator.RequiresKey = true
g.API.CredentialsValidator.RequiresSecret = true
- g.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- },
- UseGlobalFormat: true,
- RequestFormat: ¤cy.PairFormat{
- Delimiter: "_",
- },
- ConfigFormat: ¤cy.PairFormat{
- Delimiter: "_",
- Uppercase: true,
- },
+ requestFmt := ¤cy.PairFormat{Delimiter: currency.UnderscoreDelimiter}
+ configFmt := ¤cy.PairFormat{Delimiter: currency.UnderscoreDelimiter, Uppercase: true}
+ err := g.SetGlobalPairsManager(requestFmt, configFmt, asset.Spot)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
}
g.Features = exchange.Features{
@@ -99,8 +92,7 @@ func (g *Gateio) SetDefaults() {
OrderbookFetching: true,
TradeFetching: true,
KlineFetching: true,
- Subscribe: true,
- Unsubscribe: true,
+ FullPayloadSubscribe: true,
AuthenticatedEndpoints: true,
MessageCorrelation: true,
GetOrder: true,
@@ -139,7 +131,7 @@ func (g *Gateio) SetDefaults() {
g.API.Endpoints.URLSecondaryDefault = gateioMarketURL
g.API.Endpoints.URLSecondary = g.API.Endpoints.URLSecondaryDefault
g.API.Endpoints.WebsocketURL = gateioWebsocketEndpoint
- g.Websocket = wshandler.New()
+ g.Websocket = stream.New()
g.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
g.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
g.WebsocketOrderbookBufferLimit = exchange.DefaultWebsocketOrderbookBufferLimit
@@ -157,42 +149,30 @@ func (g *Gateio) Setup(exch *config.ExchangeConfig) error {
return err
}
- err = g.Websocket.Setup(
- &wshandler.WebsocketSetup{
- Enabled: exch.Features.Enabled.Websocket,
- Verbose: exch.Verbose,
- AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
- WebsocketTimeout: exch.WebsocketTrafficTimeout,
- DefaultURL: gateioWebsocketEndpoint,
- ExchangeName: exch.Name,
- RunningURL: exch.API.Endpoints.WebsocketURL,
- Connector: g.WsConnect,
- Subscriber: g.Subscribe,
- UnSubscriber: g.Unsubscribe,
- Features: &g.Features.Supports.WebsocketCapabilities,
- })
+ err = g.Websocket.Setup(&stream.WebsocketSetup{
+ Enabled: exch.Features.Enabled.Websocket,
+ Verbose: exch.Verbose,
+ AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
+ WebsocketTimeout: exch.WebsocketTrafficTimeout,
+ DefaultURL: gateioWebsocketEndpoint,
+ ExchangeName: exch.Name,
+ RunningURL: exch.API.Endpoints.WebsocketURL,
+ Connector: g.WsConnect,
+ Subscriber: g.Subscribe,
+ GenerateSubscriptions: g.GenerateDefaultSubscriptions,
+ Features: &g.Features.Supports.WebsocketCapabilities,
+ OrderbookBufferLimit: exch.WebsocketOrderbookBufferLimit,
+ BufferEnabled: true,
+ })
if err != nil {
return err
}
- g.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: g.Name,
- URL: g.Websocket.GetWebsocketURL(),
- ProxyURL: g.Websocket.GetProxyAddress(),
- Verbose: g.Verbose,
+ return g.Websocket.SetupNewConnection(stream.ConnectionSetup{
+ RateLimit: gateioWebsocketRateLimit,
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
- RateLimit: gateioWebsocketRateLimit,
- }
-
- g.Websocket.Orderbook.Setup(
- exch.WebsocketOrderbookBufferLimit,
- true,
- false,
- false,
- false,
- exch.Name)
- return nil
+ })
}
// Start starts the GateIO go routine
@@ -233,35 +213,42 @@ func (g *Gateio) UpdateTradablePairs(forceUpdate bool) error {
return err
}
- return g.UpdatePairs(currency.NewPairsFromStrings(pairs), asset.Spot, false, forceUpdate)
+ p, err := currency.NewPairsFromStrings(pairs)
+ if err != nil {
+ return err
+ }
+ return g.UpdatePairs(p, asset.Spot, false, forceUpdate)
}
// UpdateTicker updates and returns the ticker for a currency pair
func (g *Gateio) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
- tickerPrice := new(ticker.Price)
result, err := g.GetTickers()
if err != nil {
- return tickerPrice, err
+ return nil, err
+ }
+ pairs, err := g.GetEnabledPairs(assetType)
+ if err != nil {
+ return nil, err
}
- pairs := g.GetEnabledPairs(assetType)
for i := range pairs {
for k := range result {
if !strings.EqualFold(k, pairs[i].String()) {
continue
}
- tickerPrice = &ticker.Price{
- Last: result[k].Last,
- High: result[k].High,
- Low: result[k].Low,
- Volume: result[k].BaseVolume,
- QuoteVolume: result[k].QuoteVolume,
- Open: result[k].Open,
- Close: result[k].Close,
- Pair: pairs[i],
- }
- err = ticker.ProcessTicker(g.Name, tickerPrice, assetType)
+
+ err = ticker.ProcessTicker(&ticker.Price{
+ Last: result[k].Last,
+ High: result[k].High,
+ Low: result[k].Low,
+ Volume: result[k].BaseVolume,
+ QuoteVolume: result[k].QuoteVolume,
+ Open: result[k].Open,
+ Close: result[k].Close,
+ Pair: pairs[i],
+ ExchangeName: g.Name,
+ AssetType: assetType})
if err != nil {
- log.Error(log.Ticker, err)
+ return nil, err
}
}
}
@@ -290,9 +277,12 @@ func (g *Gateio) FetchOrderbook(p currency.Pair, assetType asset.Item) (*orderbo
// UpdateOrderbook updates and returns the orderbook for a currency pair
func (g *Gateio) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
orderBook := new(orderbook.Base)
- curr := g.FormatExchangeCurrency(p, assetType).String()
+ curr, err := g.FormatExchangeCurrency(p, assetType)
+ if err != nil {
+ return nil, err
+ }
- orderbookNew, err := g.GetOrderbook(curr)
+ orderbookNew, err := g.GetOrderbook(curr.String())
if err != nil {
return orderBook, err
}
@@ -479,8 +469,13 @@ func (g *Gateio) CancelOrder(order *order.Cancel) error {
if err != nil {
return err
}
- _, err = g.CancelExistingOrder(orderIDInt,
- g.FormatExchangeCurrency(order.Pair, order.AssetType).String())
+
+ fpair, err := g.FormatExchangeCurrency(order.Pair, order.AssetType)
+ if err != nil {
+ return err
+ }
+
+ _, err = g.CancelExistingOrder(orderIDInt, fpair.String())
return err
}
@@ -516,6 +511,12 @@ func (g *Gateio) GetOrderInfo(orderID string) (order.Detail, error) {
if err != nil {
return orderDetail, errors.New("failed to get open orders")
}
+
+ format, err := g.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return orderDetail, err
+ }
+
for x := range orders.Orders {
if orders.Orders[x].OrderNumber != orderID {
continue
@@ -528,8 +529,11 @@ func (g *Gateio) GetOrderInfo(orderID string) (order.Detail, error) {
orderDetail.Date = time.Unix(orders.Orders[x].Timestamp, 0)
orderDetail.Status = order.Status(orders.Orders[x].Status)
orderDetail.Price = orders.Orders[x].Rate
- orderDetail.Pair = currency.NewPairDelimiter(orders.Orders[x].CurrencyPair,
- g.GetPairFormat(asset.Spot, false).Delimiter)
+ orderDetail.Pair, err = currency.NewPairDelimiter(orders.Orders[x].CurrencyPair,
+ format.Delimiter)
+ if err != nil {
+ return orderDetail, err
+ }
if strings.EqualFold(orders.Orders[x].Type, order.Ask.String()) {
orderDetail.Side = order.Ask
} else if strings.EqualFold(orders.Orders[x].Type, order.Bid.String()) {
@@ -572,11 +576,6 @@ func (g *Gateio) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdraw.
return nil, common.ErrFunctionNotSupported
}
-// GetWebsocket returns a pointer to the exchange websocket
-func (g *Gateio) GetWebsocket() (*wshandler.Websocket, error) {
- return g.Websocket, nil
-}
-
// GetFeeByType returns an estimate of fee based on type of transaction
func (g *Gateio) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if !g.AllowAuthenticatedRequest() && // Todo check connection status
@@ -609,11 +608,15 @@ func (g *Gateio) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
if resp.WebSocketOrderQueryRecords[j].OrderType == 1 {
orderType = order.Limit
}
+ p, err := currency.NewPairFromString(resp.WebSocketOrderQueryRecords[j].Market)
+ if err != nil {
+ return nil, err
+ }
orders = append(orders, order.Detail{
Exchange: g.Name,
AccountID: strconv.FormatInt(resp.WebSocketOrderQueryRecords[j].User, 10),
ID: strconv.FormatInt(resp.WebSocketOrderQueryRecords[j].ID, 10),
- Pair: currency.NewPairFromString(resp.WebSocketOrderQueryRecords[j].Market),
+ Pair: p,
Side: orderSide,
Type: orderType,
Date: convert.TimeFromUnixTimestampDecimal(resp.WebSocketOrderQueryRecords[j].Ctime),
@@ -634,13 +637,21 @@ func (g *Gateio) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
return nil, err
}
+ format, err := g.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return nil, err
+ }
+
for i := range resp.Orders {
if resp.Orders[i].Status != "open" {
continue
}
-
- symbol := currency.NewPairDelimiter(resp.Orders[i].CurrencyPair,
- g.GetPairFormat(asset.Spot, false).Delimiter)
+ var symbol currency.Pair
+ symbol, err = currency.NewPairDelimiter(resp.Orders[i].CurrencyPair,
+ format.Delimiter)
+ if err != nil {
+ return nil, err
+ }
side := order.Side(strings.ToUpper(resp.Orders[i].Type))
orderDate := time.Unix(resp.Orders[i].Timestamp, 0)
orders = append(orders, order.Detail{
@@ -673,16 +684,24 @@ func (g *Gateio) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, e
trades = append(trades, resp.Trades...)
}
+ format, err := g.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return nil, err
+ }
+
var orders []order.Detail
- for _, trade := range trades {
- symbol := currency.NewPairDelimiter(trade.Pair,
- g.GetPairFormat(asset.Spot, false).Delimiter)
- side := order.Side(strings.ToUpper(trade.Type))
- orderDate := time.Unix(trade.TimeUnix, 0)
+ for i := range trades {
+ var symbol currency.Pair
+ symbol, err = currency.NewPairDelimiter(trades[i].Pair, format.Delimiter)
+ if err != nil {
+ return nil, err
+ }
+ side := order.Side(strings.ToUpper(trades[i].Type))
+ orderDate := time.Unix(trades[i].TimeUnix, 0)
orders = append(orders, order.Detail{
- ID: strconv.FormatInt(trade.OrderID, 10),
- Amount: trade.Amount,
- Price: trade.Rate,
+ ID: strconv.FormatInt(trades[i].OrderID, 10),
+ Amount: trades[i].Amount,
+ Price: trades[i].Rate,
Date: orderDate,
Side: side,
Exchange: g.Name,
@@ -695,29 +714,9 @@ func (g *Gateio) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, e
return orders, nil
}
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func (g *Gateio) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- g.Websocket.SubscribeToChannels(channels)
- return nil
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func (g *Gateio) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- g.Websocket.RemoveSubscribedChannels(channels)
- return nil
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func (g *Gateio) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return g.Websocket.GetSubscriptions(), nil
-}
-
// AuthenticateWebsocket sends an authentication message to the websocket
func (g *Gateio) AuthenticateWebsocket() error {
- _, err := g.wsServerSignIn()
- return err
+ return g.wsServerSignIn()
}
// ValidateCredentials validates current credentials used for wrapper
@@ -741,8 +740,13 @@ func (g *Gateio) GetHistoricCandles(pair currency.Pair, a asset.Item, start, end
}
hours := end.Sub(start).Hours()
+ formattedPair, err := g.FormatExchangeCurrency(pair, a)
+ if err != nil {
+ return kline.Item{}, err
+ }
+
params := KlinesRequestParams{
- Symbol: g.FormatExchangeCurrency(pair, a).String(),
+ Symbol: formattedPair.String(),
GroupSec: g.FormatExchangeKlineInterval(interval),
HourSize: int(hours),
}
diff --git a/exchanges/gemini/gemini.go b/exchanges/gemini/gemini.go
index b5e72a55..98cf8eed 100644
--- a/exchanges/gemini/gemini.go
+++ b/exchanges/gemini/gemini.go
@@ -14,7 +14,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/common/crypto"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/log"
)
@@ -58,11 +58,10 @@ const (
// AddSession, if sandbox test is needed append a new session with with the same
// API keys and change the IsSandbox variable to true.
type Gemini struct {
- WebsocketConn *wshandler.WebsocketConnection
- AuthenticatedWebsocketConn *wshandler.WebsocketConnection
exchange.Base
Role string
RequiresHeartBeat bool
+ connections []stream.Connection
}
// GetSymbols returns all available symbols for trading
diff --git a/exchanges/gemini/gemini_live_test.go b/exchanges/gemini/gemini_live_test.go
index 1b75e0dd..66f4e67f 100644
--- a/exchanges/gemini/gemini_live_test.go
+++ b/exchanges/gemini/gemini_live_test.go
@@ -29,13 +29,12 @@ func TestMain(m *testing.M) {
geminiConfig.API.Credentials.Key = apiKey
geminiConfig.API.Credentials.Secret = apiSecret
g.SetDefaults()
+ g.Websocket = sharedtestvalues.NewTestWebsocket()
err = g.Setup(geminiConfig)
if err != nil {
log.Fatal("Gemini setup error", err)
}
g.API.Endpoints.URL = geminiSandboxAPIURL
- g.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- g.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
log.Printf(sharedtestvalues.LiveTesting, g.Name, g.API.Endpoints.URL)
os.Exit(m.Run())
}
diff --git a/exchanges/gemini/gemini_mock_test.go b/exchanges/gemini/gemini_mock_test.go
index 37a9b91a..0f7833b4 100644
--- a/exchanges/gemini/gemini_mock_test.go
+++ b/exchanges/gemini/gemini_mock_test.go
@@ -33,6 +33,7 @@ func TestMain(m *testing.M) {
geminiConfig.API.Credentials.Key = apiKey
geminiConfig.API.Credentials.Secret = apiSecret
g.SetDefaults()
+ g.Websocket = sharedtestvalues.NewTestWebsocket()
err = g.Setup(geminiConfig)
if err != nil {
log.Fatal("Gemini setup error", err)
@@ -45,8 +46,6 @@ func TestMain(m *testing.M) {
g.HTTPClient = newClient
g.API.Endpoints.URL = serverDetails
- g.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- g.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
log.Printf(sharedtestvalues.MockTesting, g.Name, g.API.Endpoints.URL)
os.Exit(m.Run())
}
diff --git a/exchanges/gemini/gemini_test.go b/exchanges/gemini/gemini_test.go
index 1e4c509d..92f730e8 100644
--- a/exchanges/gemini/gemini_test.go
+++ b/exchanges/gemini/gemini_test.go
@@ -12,7 +12,7 @@ import (
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -550,7 +550,7 @@ func TestWsAuth(t *testing.T) {
if !g.Websocket.IsEnabled() &&
!g.API.AuthenticatedWebsocketSupport ||
!areTestAPIKeysSet() {
- t.Skip(wshandler.WebsocketNotEnabled)
+ t.Skip(stream.WebsocketNotEnabled)
}
var dialer websocket.Dialer
go g.wsReadData()
@@ -571,18 +571,27 @@ func TestWsAuth(t *testing.T) {
}
func TestWsMissingRole(t *testing.T) {
+ pair, err := currency.NewPairFromString("BTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
+
pressXToJSON := []byte(`{
"result":"error",
"reason":"MissingRole",
"message":"To access this endpoint, you need to log in to the website and go to the settings page to assign one of these roles [FundManager] to API key wujB3szN54gtJ4QDhqRJ which currently has roles [Trader]"
}`)
- err := g.wsHandleData(pressXToJSON, currency.NewPairFromString("BTCUSD"))
+ err = g.wsHandleData(pressXToJSON, pair)
if err == nil {
t.Error("Expected error")
}
}
func TestWsOrderEventSubscriptionResponse(t *testing.T) {
+ pair, err := currency.NewPairFromString("BTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
pressXToJSON := []byte(`[ {
"type" : "accepted",
"order_id" : "372456298",
@@ -601,7 +610,7 @@ func TestWsOrderEventSubscriptionResponse(t *testing.T) {
"original_amount" : "14.0296",
"price" : "1059.54"
} ]`)
- err := g.wsHandleData(pressXToJSON, currency.NewPairFromString("BTCUSD"))
+ err = g.wsHandleData(pressXToJSON, pair)
if err != nil {
t.Error(err)
}
@@ -623,7 +632,7 @@ func TestWsOrderEventSubscriptionResponse(t *testing.T) {
"price": "3592.00",
"socket_sequence": 13
}]`)
- err = g.wsHandleData(pressXToJSON, currency.NewPairFromString("BTCUSD"))
+ err = g.wsHandleData(pressXToJSON, pair)
if err != nil {
t.Error(err)
}
@@ -644,7 +653,7 @@ func TestWsOrderEventSubscriptionResponse(t *testing.T) {
"total_spend": "200.00",
"socket_sequence": 29
}]`)
- err = g.wsHandleData(pressXToJSON, currency.NewPairFromString("BTCUSD"))
+ err = g.wsHandleData(pressXToJSON, pair)
if err != nil {
t.Error(err)
}
@@ -665,7 +674,7 @@ func TestWsOrderEventSubscriptionResponse(t *testing.T) {
"original_amount": "25",
"socket_sequence": 26
}]`)
- err = g.wsHandleData(pressXToJSON, currency.NewPairFromString("BTCUSD"))
+ err = g.wsHandleData(pressXToJSON, pair)
if err != nil {
t.Error(err)
}
@@ -687,13 +696,17 @@ func TestWsOrderEventSubscriptionResponse(t *testing.T) {
"original_amount" : "500",
"socket_sequence" : 32307
} ]`)
- err = g.wsHandleData(pressXToJSON, currency.NewPairFromString("BTCUSD"))
+ err = g.wsHandleData(pressXToJSON, pair)
if err != nil {
t.Error(err)
}
}
func TestWsSubAck(t *testing.T) {
+ pair, err := currency.NewPairFromString("BTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
pressXToJSON := []byte(`{
"type": "subscription_ack",
"accountId": 5365,
@@ -709,13 +722,17 @@ func TestWsSubAck(t *testing.T) {
"closed"
]
}`)
- err := g.wsHandleData(pressXToJSON, currency.NewPairFromString("BTCUSD"))
+ err = g.wsHandleData(pressXToJSON, pair)
if err != nil {
t.Error(err)
}
}
func TestWsHeartbeat(t *testing.T) {
+ pair, err := currency.NewPairFromString("BTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
pressXToJSON := []byte(`{
"type": "heartbeat",
"timestampms": 1547742998508,
@@ -723,13 +740,17 @@ func TestWsHeartbeat(t *testing.T) {
"trace_id": "b8biknoqppr32kc7gfgg",
"socket_sequence": 37
}`)
- err := g.wsHandleData(pressXToJSON, currency.NewPairFromString("BTCUSD"))
+ err = g.wsHandleData(pressXToJSON, pair)
if err != nil {
t.Error(err)
}
}
func TestWsUnsubscribe(t *testing.T) {
+ pair, err := currency.NewPairFromString("BTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
pressXToJSON := []byte(`{
"type": "unsubscribe",
"subscriptions": [{
@@ -745,13 +766,17 @@ func TestWsUnsubscribe(t *testing.T) {
]}
]
}`)
- err := g.wsHandleData(pressXToJSON, currency.NewPairFromString("BTCUSD"))
+ err = g.wsHandleData(pressXToJSON, pair)
if err != nil {
t.Error(err)
}
}
func TestWsTradeData(t *testing.T) {
+ pair, err := currency.NewPairFromString("BTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
pressXToJSON := []byte(`{
"type": "update",
"eventId": 5375547515,
@@ -768,13 +793,17 @@ func TestWsTradeData(t *testing.T) {
}
]
}`)
- err := g.wsHandleData(pressXToJSON, currency.NewPairFromString("BTCUSD"))
+ err = g.wsHandleData(pressXToJSON, pair)
if err != nil {
t.Error(err)
}
}
func TestWsAuctionData(t *testing.T) {
+ pair, err := currency.NewPairFromString("BTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
pressXToJSON := []byte(`{
"eventId": 371469414,
"socket_sequence":4009,
@@ -801,13 +830,17 @@ func TestWsAuctionData(t *testing.T) {
],
"type": "update"
}`)
- err := g.wsHandleData(pressXToJSON, currency.NewPairFromString("BTCUSD"))
+ err = g.wsHandleData(pressXToJSON, pair)
if err != nil {
t.Error(err)
}
}
func TestWsBlockTrade(t *testing.T) {
+ pair, err := currency.NewPairFromString("BTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
pressXToJSON := []byte(`{
"type":"update",
"eventId":1111597035,
@@ -823,13 +856,17 @@ func TestWsBlockTrade(t *testing.T) {
}
]
}`)
- err := g.wsHandleData(pressXToJSON, currency.NewPairFromString("BTCUSD"))
+ err = g.wsHandleData(pressXToJSON, pair)
if err != nil {
t.Error(err)
}
}
func TestWsCandles(t *testing.T) {
+ pair, err := currency.NewPairFromString("BTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
pressXToJSON := []byte(`{
"type": "candles_15m_updates",
"symbol": "BTCUSD",
@@ -852,13 +889,17 @@ func TestWsCandles(t *testing.T) {
]
]
}`)
- err := g.wsHandleData(pressXToJSON, currency.NewPairFromString("BTCUSD"))
+ err = g.wsHandleData(pressXToJSON, pair)
if err != nil {
t.Error(err)
}
}
func TestWsAuctions(t *testing.T) {
+ pair, err := currency.NewPairFromString("BTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
pressXToJSON := []byte(`{
"eventId": 372481811,
"socket_sequence":23,
@@ -875,7 +916,7 @@ func TestWsAuctions(t *testing.T) {
],
"type": "update"
}`)
- err := g.wsHandleData(pressXToJSON, currency.NewPairFromString("BTCUSD"))
+ err = g.wsHandleData(pressXToJSON, pair)
if err != nil {
t.Error(err)
}
@@ -900,7 +941,7 @@ func TestWsAuctions(t *testing.T) {
}
]
}`)
- err = g.wsHandleData(pressXToJSON, currency.NewPairFromString("BTCUSD"))
+ err = g.wsHandleData(pressXToJSON, pair)
if err != nil {
t.Error(err)
}
@@ -932,13 +973,17 @@ func TestWsAuctions(t *testing.T) {
}
]
}`)
- err = g.wsHandleData(pressXToJSON, currency.NewPairFromString("BTCUSD"))
+ err = g.wsHandleData(pressXToJSON, pair)
if err != nil {
t.Error(err)
}
}
func TestWsMarketData(t *testing.T) {
+ pair, err := currency.NewPairFromString("BTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
pressXToJSON := []byte(`{
"type": "update",
"eventId": 5375461993,
@@ -962,7 +1007,7 @@ func TestWsMarketData(t *testing.T) {
}
]
} `)
- err := g.wsHandleData(pressXToJSON, currency.NewPairFromString("BTCUSD"))
+ err = g.wsHandleData(pressXToJSON, pair)
if err != nil {
t.Error(err)
}
@@ -990,7 +1035,7 @@ func TestWsMarketData(t *testing.T) {
}
]
} `)
- err = g.wsHandleData(pressXToJSON, currency.NewPairFromString("BTCUSD"))
+ err = g.wsHandleData(pressXToJSON, pair)
if err != nil {
t.Error(err)
}
@@ -1012,7 +1057,7 @@ func TestWsMarketData(t *testing.T) {
}
]
} `)
- err = g.wsHandleData(pressXToJSON, currency.NewPairFromString("BTCUSD"))
+ err = g.wsHandleData(pressXToJSON, pair)
if err != nil {
t.Error(err)
}
diff --git a/exchanges/gemini/gemini_websocket.go b/exchanges/gemini/gemini_websocket.go
index af5d0e34..0915f38e 100644
--- a/exchanges/gemini/gemini_websocket.go
+++ b/exchanges/gemini/gemini_websocket.go
@@ -18,8 +18,8 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wsorderbook"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer"
"github.com/thrasher-corp/gocryptotrader/log"
)
@@ -39,7 +39,7 @@ var responseCheckTimeout time.Duration
// WsConnect initiates a websocket connection
func (g *Gemini) WsConnect() error {
if !g.Websocket.IsEnabled() || !g.IsEnabled() {
- return errors.New(wshandler.WebsocketNotEnabled)
+ return errors.New(stream.WebsocketNotEnabled)
}
var dialer websocket.Dialer
@@ -61,31 +61,36 @@ func (g *Gemini) WsConnect() error {
// WsSubscribe subscribes to the full websocket suite on gemini exchange
func (g *Gemini) WsSubscribe(dialer *websocket.Dialer) error {
- enabledCurrencies := g.GetEnabledPairs(asset.Spot)
+ enabledCurrencies, err := g.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return err
+ }
for i := range enabledCurrencies {
val := url.Values{}
val.Set("heartbeat", "true")
+ val.Set("bids", "true")
+ val.Set("offers", "true")
+ val.Set("trades", "true")
endpoint := fmt.Sprintf("%s%s/%s?%s",
g.API.Endpoints.WebsocketURL,
geminiWsMarketData,
enabledCurrencies[i].String(),
val.Encode())
- connection := &wshandler.WebsocketConnection{
- ExchangeName: g.Name,
- URL: endpoint,
- Verbose: g.Verbose,
- ResponseCheckTimeout: responseCheckTimeout,
- ResponseMaxLimit: responseMaxLimit,
+ connection := &stream.WebsocketConnection{
+ ExchangeName: g.Name,
+ URL: endpoint,
+ Verbose: g.Verbose,
+ ResponseMaxLimit: responseMaxLimit,
+ Traffic: g.Websocket.TrafficAlert,
+ Match: g.Websocket.Match,
}
err := connection.Dial(dialer, http.Header{})
if err != nil {
return fmt.Errorf("%v Websocket connection %v error. Error %v",
g.Name, endpoint, err)
}
+ g.connections = append(g.connections, connection)
go g.wsFunnelConnectionData(connection, enabledCurrencies[i])
- if len(enabledCurrencies)-1 == i {
- return nil
- }
}
return nil
}
@@ -115,38 +120,31 @@ func (g *Gemini) WsSecureSubscribe(dialer *websocket.Dialer, url string) error {
headers.Add("X-GEMINI-SIGNATURE", crypto.HexEncodeToString(hmac))
headers.Add("Cache-Control", "no-cache")
- g.AuthenticatedWebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: g.Name,
- URL: endpoint,
- Verbose: g.Verbose,
- ResponseCheckTimeout: responseCheckTimeout,
- ResponseMaxLimit: responseMaxLimit,
+ g.Websocket.AuthConn = &stream.WebsocketConnection{
+ ExchangeName: g.Name,
+ URL: endpoint,
+ Verbose: g.Verbose,
+ ResponseMaxLimit: responseMaxLimit,
+ Match: g.Websocket.Match,
}
- err = g.AuthenticatedWebsocketConn.Dial(dialer, headers)
+ err = g.Websocket.AuthConn.Dial(dialer, headers)
if err != nil {
return fmt.Errorf("%v Websocket connection %v error. Error %v", g.Name, endpoint, err)
}
- go g.wsFunnelConnectionData(g.AuthenticatedWebsocketConn, currency.Pair{})
+ go g.wsFunnelConnectionData(g.Websocket.AuthConn, currency.Pair{})
return nil
}
// wsFunnelConnectionData receives data from multiple connections and passes it to wsReadData
-func (g *Gemini) wsFunnelConnectionData(ws *wshandler.WebsocketConnection, c currency.Pair) {
+func (g *Gemini) wsFunnelConnectionData(ws stream.Connection, c currency.Pair) {
g.Websocket.Wg.Add(1)
defer g.Websocket.Wg.Done()
for {
- select {
- case <-g.Websocket.ShutdownC:
+ resp := ws.ReadMessage()
+ if resp.Raw == nil {
return
- default:
- resp, err := ws.ReadMessage()
- if err != nil {
- g.Websocket.DataHandler <- err
- return
- }
- g.Websocket.TrafficAlert <- struct{}{}
- comms <- ReadData{Raw: resp.Raw, Currency: c}
}
+ comms <- ReadData{Raw: resp.Raw, Currency: c}
}
}
@@ -157,6 +155,14 @@ func (g *Gemini) wsReadData() {
for {
select {
case <-g.Websocket.ShutdownC:
+ for i := range g.connections {
+ err := g.connections[i].Shutdown()
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
+ }
+ g.connections[i] = nil
+ }
+ g.connections = nil
return
case resp := <-comms:
// Gemini likes to send empty arrays
@@ -207,7 +213,16 @@ func (g *Gemini) wsHandleData(respRaw []byte, curr currency.Pair) error {
Err: err,
}
}
- p := currency.NewPairFromString(result[i].Symbol)
+
+ p, err := currency.NewPairFromString(result[i].Symbol)
+ if err != nil {
+ g.Websocket.DataHandler <- order.ClassificationError{
+ Exchange: g.Name,
+ OrderID: result[i].OrderID,
+ Err: err,
+ }
+ }
+
var a asset.Item
a, err = g.GetPairAssetType(p)
if err != nil {
@@ -260,12 +275,7 @@ func (g *Gemini) wsHandleData(respRaw []byte, curr currency.Pair) error {
}
g.Websocket.DataHandler <- result
case "heartbeat":
- var result WsHeartbeatResponse
- err := json.Unmarshal(respRaw, &result)
- if err != nil {
- return err
- }
- g.Websocket.DataHandler <- result
+ return nil
case "update":
if curr.IsEmpty() {
return fmt.Errorf("%v - `update` response error. Currency is empty %s",
@@ -290,7 +300,7 @@ func (g *Gemini) wsHandleData(respRaw []byte, curr currency.Pair) error {
return err
}
for i := range candle.Changes {
- g.Websocket.DataHandler <- wshandler.KlineData{
+ g.Websocket.DataHandler <- stream.KlineData{
Timestamp: time.Unix(int64(candle.Changes[i][0])*1000, 0),
Pair: curr,
AssetType: asset.Spot,
@@ -305,7 +315,7 @@ func (g *Gemini) wsHandleData(respRaw []byte, curr currency.Pair) error {
}
default:
- g.Websocket.DataHandler <- wshandler.UnhandledMessageWarning{Message: g.Name + wshandler.UnhandledMessage + string(respRaw)}
+ g.Websocket.DataHandler <- stream.UnhandledMessageWarning{Message: g.Name + stream.UnhandledMessage + string(respRaw)}
return nil
}
} else if _, ok := result["result"]; ok {
@@ -318,7 +328,7 @@ func (g *Gemini) wsHandleData(respRaw []byte, curr currency.Pair) error {
}
return fmt.Errorf("%v Unhandled websocket error %s", g.Name, respRaw)
default:
- g.Websocket.DataHandler <- wshandler.UnhandledMessageWarning{Message: g.Name + wshandler.UnhandledMessage + string(respRaw)}
+ g.Websocket.DataHandler <- stream.UnhandledMessageWarning{Message: g.Name + stream.UnhandledMessage + string(respRaw)}
return nil
}
}
@@ -349,7 +359,8 @@ func stringToOrderType(oType string) (order.Type, error) {
case "exchange limit", "auction-only limit", "indication-of-interest limit":
return order.Limit, nil
case "market buy", "market sell", "block_trade":
- // block trades are conducted off order-book, so their type is market, but would be considered a hidden trade
+ // block trades are conducted off order-book, so their type is market,
+ // but would be considered a hidden trade
return order.Market, nil
default:
return order.UnknownType, errors.New(oType + " not recognised as order type")
@@ -388,9 +399,6 @@ func (g *Gemini) wsProcessUpdate(result WsMarketUpdateResponse, pair currency.Pa
g.Websocket.DataHandler <- err
return
}
- g.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{Pair: pair,
- Asset: asset.Spot,
- Exchange: g.Name}
} else {
var asks, bids []orderbook.Item
for i := range result.Events {
@@ -403,8 +411,8 @@ func (g *Gemini) wsProcessUpdate(result WsMarketUpdateResponse, pair currency.Pa
Err: err,
}
}
- g.Websocket.DataHandler <- wshandler.TradeData{
- Timestamp: time.Unix(0, result.Timestamp),
+ g.Websocket.DataHandler <- stream.TradeData{
+ Timestamp: time.Unix(0, result.TimestampMS*int64(time.Millisecond)),
CurrencyPair: pair,
AssetType: asset.Spot,
Exchange: g.Name,
@@ -429,18 +437,15 @@ func (g *Gemini) wsProcessUpdate(result WsMarketUpdateResponse, pair currency.Pa
if len(asks) == 0 && len(bids) == 0 {
return
}
- err := g.Websocket.Orderbook.Update(&wsorderbook.WebsocketOrderbookUpdate{
+ err := g.Websocket.Orderbook.Update(&buffer.Update{
Asks: asks,
Bids: bids,
Pair: pair,
- UpdateTime: time.Unix(0, result.TimestampMS),
+ UpdateTime: time.Unix(0, result.TimestampMS*int64(time.Millisecond)),
Asset: asset.Spot,
})
if err != nil {
g.Websocket.DataHandler <- fmt.Errorf("%v %v", g.Name, err)
}
- g.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{Pair: pair,
- Asset: asset.Spot,
- Exchange: g.Name}
}
}
diff --git a/exchanges/gemini/gemini_wrapper.go b/exchanges/gemini/gemini_wrapper.go
index 4af50c81..b555f09b 100644
--- a/exchanges/gemini/gemini_wrapper.go
+++ b/exchanges/gemini/gemini_wrapper.go
@@ -19,8 +19,8 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -39,7 +39,7 @@ func (g *Gemini) GetDefaultConfig() (*config.ExchangeConfig, error) {
}
if g.Features.Supports.RESTCapabilities.AutoPairUpdates {
- err = g.UpdateTradablePairs(true)
+ err := g.UpdateTradablePairs(true)
if err != nil {
return nil, err
}
@@ -56,17 +56,11 @@ func (g *Gemini) SetDefaults() {
g.API.CredentialsValidator.RequiresKey = true
g.API.CredentialsValidator.RequiresSecret = true
- g.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- },
- UseGlobalFormat: true,
- RequestFormat: ¤cy.PairFormat{
- Uppercase: true,
- },
- ConfigFormat: ¤cy.PairFormat{
- Uppercase: true,
- },
+ requestFmt := ¤cy.PairFormat{Uppercase: true}
+ configFmt := ¤cy.PairFormat{Uppercase: true}
+ err := g.SetGlobalPairsManager(requestFmt, configFmt, asset.Spot)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
}
g.Features = exchange.Features{
@@ -95,8 +89,6 @@ func (g *Gemini) SetDefaults() {
TradeFetching: true,
AuthenticatedEndpoints: true,
MessageSequenceNumbers: true,
- Subscribe: true,
- Unsubscribe: true,
KlineFetching: true,
},
WithdrawPermissions: exchange.AutoWithdrawCryptoWithAPIPermission |
@@ -115,7 +107,7 @@ func (g *Gemini) SetDefaults() {
g.API.Endpoints.URLDefault = geminiAPIURL
g.API.Endpoints.URL = g.API.Endpoints.URLDefault
g.API.Endpoints.WebsocketURL = geminiWebsocketEndpoint
- g.Websocket = wshandler.New()
+ g.Websocket = stream.New()
g.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
g.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
g.WebsocketOrderbookBufferLimit = exchange.DefaultWebsocketOrderbookBufferLimit
@@ -137,39 +129,20 @@ func (g *Gemini) Setup(exch *config.ExchangeConfig) error {
g.API.Endpoints.URL = geminiSandboxAPIURL
}
- err = g.Websocket.Setup(
- &wshandler.WebsocketSetup{
- Enabled: exch.Features.Enabled.Websocket,
- Verbose: exch.Verbose,
- AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
- WebsocketTimeout: exch.WebsocketTrafficTimeout,
- DefaultURL: geminiWebsocketEndpoint,
- ExchangeName: exch.Name,
- RunningURL: exch.API.Endpoints.WebsocketURL,
- Connector: g.WsConnect,
- Features: &g.Features.Supports.WebsocketCapabilities,
- })
- if err != nil {
- return err
- }
-
- g.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: g.Name,
- URL: g.Websocket.GetWebsocketURL(),
- ProxyURL: g.Websocket.GetProxyAddress(),
- Verbose: g.Verbose,
- ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
- ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
- }
-
- g.Websocket.Orderbook.Setup(
- exch.WebsocketOrderbookBufferLimit,
- true,
- true,
- false,
- false,
- exch.Name)
- return nil
+ return g.Websocket.Setup(&stream.WebsocketSetup{
+ Enabled: exch.Features.Enabled.Websocket,
+ Verbose: exch.Verbose,
+ AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
+ WebsocketTimeout: exch.WebsocketTrafficTimeout,
+ DefaultURL: geminiWebsocketEndpoint,
+ ExchangeName: exch.Name,
+ RunningURL: exch.API.Endpoints.WebsocketURL,
+ Connector: g.WsConnect,
+ Features: &g.Features.Supports.WebsocketCapabilities,
+ OrderbookBufferLimit: exch.WebsocketOrderbookBufferLimit,
+ BufferEnabled: true,
+ SortBuffer: true,
+ })
}
// Start starts the Gemini go routine
@@ -210,7 +183,12 @@ func (g *Gemini) UpdateTradablePairs(forceUpdate bool) error {
return err
}
- return g.UpdatePairs(currency.NewPairsFromStrings(pairs), asset.Spot, false, forceUpdate)
+ p, err := currency.NewPairsFromStrings(pairs)
+ if err != nil {
+ return err
+ }
+
+ return g.UpdatePairs(p, asset.Spot, false, forceUpdate)
}
// UpdateAccountInfo Retrieves balances for all enabled currencies for the
@@ -256,23 +234,23 @@ func (g *Gemini) FetchAccountInfo() (account.Holdings, error) {
// UpdateTicker updates and returns the ticker for a currency pair
func (g *Gemini) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
- tickerPrice := new(ticker.Price)
tick, err := g.GetTicker(p.String())
if err != nil {
- return tickerPrice, err
+ return nil, err
}
- tickerPrice = &ticker.Price{
- High: tick.High,
- Low: tick.Low,
- Bid: tick.Bid,
- Ask: tick.Ask,
- Open: tick.Open,
- Close: tick.Close,
- Pair: p,
- }
- err = ticker.ProcessTicker(g.Name, tickerPrice, assetType)
+
+ err = ticker.ProcessTicker(&ticker.Price{
+ High: tick.High,
+ Low: tick.Low,
+ Bid: tick.Bid,
+ Ask: tick.Ask,
+ Open: tick.Open,
+ Close: tick.Close,
+ Pair: p,
+ ExchangeName: g.Name,
+ AssetType: assetType})
if err != nil {
- return tickerPrice, err
+ return nil, err
}
return ticker.GetTicker(g.Name, p, assetType)
@@ -347,8 +325,12 @@ func (g *Gemini) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
errors.New("only limit orders are enabled through this exchange")
}
- response, err := g.NewOrder(
- g.FormatExchangeCurrency(s.Pair, asset.Spot).String(),
+ fpair, err := g.FormatExchangeCurrency(s.Pair, asset.Spot)
+ if err != nil {
+ return submitOrderResponse, err
+ }
+
+ response, err := g.NewOrder(fpair.String(),
s.Amount,
s.Price,
s.Side.String(),
@@ -442,11 +424,6 @@ func (g *Gemini) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdraw.
return nil, common.ErrFunctionNotSupported
}
-// GetWebsocket returns a pointer to the exchange websocket
-func (g *Gemini) GetWebsocket() (*wshandler.Websocket, error) {
- return g.Websocket, nil
-}
-
// GetFeeByType returns an estimate of fee based on type of transaction
func (g *Gemini) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (!g.AllowAuthenticatedRequest() || g.SkipAuthCheck) && // Todo check connection status
@@ -463,10 +440,18 @@ func (g *Gemini) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
return nil, err
}
+ format, err := g.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return nil, err
+ }
+
var orders []order.Detail
for i := range resp {
- symbol := currency.NewPairDelimiter(resp[i].Symbol,
- g.GetPairFormat(asset.Spot, false).Delimiter)
+ var symbol currency.Pair
+ symbol, err = currency.NewPairDelimiter(resp[i].Symbol, format.Delimiter)
+ if err != nil {
+ return nil, err
+ }
var orderType order.Type
if resp[i].Type == "exchange limit" {
orderType = order.Limit
@@ -507,9 +492,12 @@ func (g *Gemini) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, e
var trades []TradeHistory
for j := range req.Pairs {
- resp, err := g.GetTradeHistory(g.FormatExchangeCurrency(req.Pairs[j],
- asset.Spot).String(),
- req.StartTicks.Unix())
+ fpair, err := g.FormatExchangeCurrency(req.Pairs[j], asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+
+ resp, err := g.GetTradeHistory(fpair.String(), req.StartTicks.Unix())
if err != nil {
return nil, err
}
@@ -521,6 +509,11 @@ func (g *Gemini) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, e
}
}
+ format, err := g.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return nil, err
+ }
+
var orders []order.Detail
for i := range trades {
side := order.Side(strings.ToUpper(trades[i].Type))
@@ -536,7 +529,7 @@ func (g *Gemini) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, e
Price: trades[i].Price,
Pair: currency.NewPairWithDelimiter(trades[i].BaseCurrency,
trades[i].QuoteCurrency,
- g.GetPairFormat(asset.Spot, false).Delimiter),
+ format.Delimiter),
})
}
@@ -545,28 +538,6 @@ func (g *Gemini) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, e
return orders, nil
}
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func (g *Gemini) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- return common.ErrFunctionNotSupported
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func (g *Gemini) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- return common.ErrFunctionNotSupported
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func (g *Gemini) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return nil, common.ErrFunctionNotSupported
-}
-
-// AuthenticateWebsocket sends an authentication message to the websocket
-func (g *Gemini) AuthenticateWebsocket() error {
- return common.ErrFunctionNotSupported
-}
-
// ValidateCredentials validates current credentials used for wrapper
// functionality
func (g *Gemini) ValidateCredentials() error {
diff --git a/exchanges/hitbtc/hitbtc.go b/exchanges/hitbtc/hitbtc.go
index 1141ea1d..6b36f1f1 100644
--- a/exchanges/hitbtc/hitbtc.go
+++ b/exchanges/hitbtc/hitbtc.go
@@ -14,7 +14,6 @@ import (
"github.com/thrasher-corp/gocryptotrader/currency"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
)
const (
@@ -47,7 +46,6 @@ const (
// HitBTC is the overarching type across the hitbtc package
type HitBTC struct {
exchange.Base
- WebsocketConn *wshandler.WebsocketConnection
}
// Public Market Data
diff --git a/exchanges/hitbtc/hitbtc_test.go b/exchanges/hitbtc/hitbtc_test.go
index aaaf7b2b..f2835502 100644
--- a/exchanges/hitbtc/hitbtc_test.go
+++ b/exchanges/hitbtc/hitbtc_test.go
@@ -17,7 +17,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -46,14 +46,11 @@ func TestMain(m *testing.M) {
hitbtcConfig.API.AuthenticatedWebsocketSupport = true
hitbtcConfig.API.Credentials.Key = apiKey
hitbtcConfig.API.Credentials.Secret = apiSecret
-
+ h.Websocket = sharedtestvalues.NewTestWebsocket()
err = h.Setup(hitbtcConfig)
if err != nil {
log.Fatal("HitBTC setup error", err)
}
-
- h.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- h.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
os.Exit(m.Run())
}
@@ -79,10 +76,13 @@ func TestGetChartCandles(t *testing.T) {
}
func TestGetHistoricCandles(t *testing.T) {
- currencyPair := currency.NewPairFromString("BTCUSD")
+ currencyPair, err := currency.NewPairFromString("BTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
startTime := time.Now().Add(-time.Hour * 24)
end := time.Now()
- _, err := h.GetHistoricCandles(currencyPair, asset.Spot, startTime, end, kline.OneMin)
+ _, err = h.GetHistoricCandles(currencyPair, asset.Spot, startTime, end, kline.OneMin)
if err != nil {
t.Fatal(err)
}
@@ -94,10 +94,13 @@ func TestGetHistoricCandles(t *testing.T) {
}
func TestGetHistoricCandlesExtended(t *testing.T) {
- currencyPair := currency.NewPairFromString("BTCUSD")
+ currencyPair, err := currency.NewPairFromString("BTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
startTime := time.Unix(1546300800, 0)
end := time.Unix(1577836799, 0)
- _, err := h.GetHistoricCandlesExtended(currencyPair, asset.Spot, startTime, end, kline.OneHour)
+ _, err = h.GetHistoricCandlesExtended(currencyPair, asset.Spot, startTime, end, kline.OneHour)
if err != nil {
t.Fatal(err)
}
@@ -142,8 +145,12 @@ func TestGetFeeByTypeOfflineTradeFee(t *testing.T) {
}
func TestUpdateTicker(t *testing.T) {
- h.CurrencyPairs.StorePairs(asset.Spot, currency.NewPairsFromStrings([]string{"BTC-USD", "XRP-USD"}), true)
- _, err := h.UpdateTicker(currency.NewPair(currency.BTC, currency.USD), asset.Spot)
+ pairs, err := currency.NewPairsFromStrings([]string{"BTC-USD", "XRP-USD"})
+ if err != nil {
+ t.Fatal(err)
+ }
+ h.CurrencyPairs.StorePairs(asset.Spot, pairs, true)
+ _, err = h.UpdateTicker(currency.NewPair(currency.BTC, currency.USD), asset.Spot)
if err != nil {
t.Error(err)
}
@@ -438,19 +445,11 @@ func setupWsAuth(t *testing.T) {
return
}
if !h.Websocket.IsEnabled() && !h.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
- t.Skip(wshandler.WebsocketNotEnabled)
- }
- h.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- h.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
- h.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: h.Name,
- URL: hitbtcWebsocketAddress,
- Verbose: h.Verbose,
- ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
- ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
+ t.Skip(stream.WebsocketNotEnabled)
}
+
var dialer websocket.Dialer
- err := h.WebsocketConn.Dial(&dialer, http.Header{})
+ err := h.Websocket.Conn.Dial(&dialer, http.Header{})
if err != nil {
t.Fatal(err)
}
diff --git a/exchanges/hitbtc/hitbtc_types.go b/exchanges/hitbtc/hitbtc_types.go
index 183c8052..38eb426a 100644
--- a/exchanges/hitbtc/hitbtc_types.go
+++ b/exchanges/hitbtc/hitbtc_types.go
@@ -300,23 +300,25 @@ type ResponseError struct {
// WsRequest defines a request obj for the JSON-RPC and gets a websocket
// response
type WsRequest struct {
- Method string `json:"method"`
- Params interface{} `json:"params,omitempty"`
- ID interface{} `json:"id"`
+ Method string `json:"method"`
+ Params Params `json:"params,omitempty"`
+ ID int64 `json:"id"`
}
// WsNotification defines a notification obj for the JSON-RPC this does not get
// a websocket response
type WsNotification struct {
- JSONRPCVersion string `json:"jsonrpc,omitempty"`
- Method string `json:"method"`
- Params interface{} `json:"params"`
+ JSONRPCVersion string `json:"jsonrpc,omitempty"`
+ Method string `json:"method"`
+ Params Params `json:"params"`
}
-type params struct {
- Symbol string `json:"symbol,omitempty"`
- Period string `json:"period,omitempty"`
- Limit int64 `json:"limit,omitempty"`
+// Params is params
+type Params struct {
+ Symbol string `json:"symbol,omitempty"`
+ Period string `json:"period,omitempty"`
+ Limit int64 `json:"limit,omitempty"`
+ Symbols []string `json:"symbols,omitempty"`
}
// WsTicker defines websocket ticker feed return params
@@ -369,6 +371,7 @@ type WsTrade struct {
type WsLoginRequest struct {
Method string `json:"method"`
Params WsLoginData `json:"params"`
+ ID int64 `json:"id,omitempty"`
}
// WsLoginData sets credentials for WsLoginRequest
diff --git a/exchanges/hitbtc/hitbtc_websocket.go b/exchanges/hitbtc/hitbtc_websocket.go
index a5867de1..aed37f5b 100644
--- a/exchanges/hitbtc/hitbtc_websocket.go
+++ b/exchanges/hitbtc/hitbtc_websocket.go
@@ -10,6 +10,7 @@ import (
"time"
"github.com/gorilla/websocket"
+ "github.com/thrasher-corp/gocryptotrader/common"
"github.com/thrasher-corp/gocryptotrader/common/crypto"
"github.com/thrasher-corp/gocryptotrader/currency"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
@@ -17,9 +18,9 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/nonce"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wsorderbook"
"github.com/thrasher-corp/gocryptotrader/log"
)
@@ -35,10 +36,10 @@ var requestID nonce.Nonce
// WsConnect starts a new connection with the websocket API
func (h *HitBTC) WsConnect() error {
if !h.Websocket.IsEnabled() || !h.IsEnabled() {
- return errors.New(wshandler.WebsocketNotEnabled)
+ return errors.New(stream.WebsocketNotEnabled)
}
var dialer websocket.Dialer
- err := h.WebsocketConn.Dial(&dialer, http.Header{})
+ err := h.Websocket.Conn.Dial(&dialer, http.Header{})
if err != nil {
return err
}
@@ -48,35 +49,27 @@ func (h *HitBTC) WsConnect() error {
log.Errorf(log.ExchangeSys, "%v - authentication failed: %v\n", h.Name, err)
}
- h.GenerateDefaultSubscriptions()
-
- return nil
+ subs, err := h.GenerateDefaultSubscriptions()
+ if err != nil {
+ return err
+ }
+ return h.Websocket.SubscribeToChannels(subs)
}
// wsReadData receives and passes on websocket messages for processing
func (h *HitBTC) wsReadData() {
h.Websocket.Wg.Add(1)
-
- defer func() {
- h.Websocket.Wg.Done()
- }()
+ defer h.Websocket.Wg.Done()
for {
- select {
- case <-h.Websocket.ShutdownC:
+ resp := h.Websocket.Conn.ReadMessage()
+ if resp.Raw == nil {
return
- default:
- resp, err := h.WebsocketConn.ReadMessage()
- if err != nil {
- h.Websocket.ReadMessageErrors <- err
- return
- }
- h.Websocket.TrafficAlert <- struct{}{}
+ }
- err = h.wsHandleData(resp.Raw)
- if err != nil {
- h.Websocket.DataHandler <- err
- }
+ err := h.wsHandleData(resp.Raw)
+ if err != nil {
+ h.Websocket.DataHandler <- err
}
}
}
@@ -91,8 +84,7 @@ func (h *HitBTC) wsGetTableName(respRaw []byte) (string, error) {
h.Websocket.SetCanUseAuthenticatedEndpoints(false)
}
if init.ID > 0 {
- if h.WebsocketConn.IsIDWaitingForResponse(init.ID) {
- h.WebsocketConn.SetResponseIDAndData(init.ID, respRaw)
+ if h.Websocket.Match.IncomingWithData(init.ID, respRaw) {
return "", nil
}
}
@@ -132,7 +124,7 @@ func (h *HitBTC) wsGetTableName(respRaw []byte) (string, error) {
return "trading", nil
}
}
- h.Websocket.DataHandler <- wshandler.UnhandledMessageWarning{Message: h.Name + wshandler.UnhandledMessage + string(respRaw)}
+ h.Websocket.DataHandler <- stream.UnhandledMessageWarning{Message: h.Name + stream.UnhandledMessage + string(respRaw)}
return "", nil
}
@@ -150,6 +142,24 @@ func (h *HitBTC) wsHandleData(respRaw []byte) error {
if err != nil {
return err
}
+
+ pairs, err := h.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return err
+ }
+
+ format, err := h.GetPairFormat(asset.Spot, true)
+ if err != nil {
+ return err
+ }
+
+ p, err := currency.NewPairFromFormattedPairs(wsTicker.Params.Symbol,
+ pairs,
+ format)
+ if err != nil {
+ return err
+ }
+
h.Websocket.DataHandler <- &ticker.Price{
ExchangeName: h.Name,
Open: wsTicker.Params.Open,
@@ -162,8 +172,7 @@ func (h *HitBTC) wsHandleData(respRaw []byte) error {
Last: wsTicker.Params.Last,
LastUpdated: wsTicker.Params.Timestamp,
AssetType: asset.Spot,
- Pair: currency.NewPairFromFormattedPairs(wsTicker.Params.Symbol,
- h.GetEnabledPairs(asset.Spot), h.GetPairFormat(asset.Spot, true)),
+ Pair: p,
}
case "snapshotOrderbook":
var obSnapshot WsOrderbook
@@ -252,7 +261,7 @@ func (h *HitBTC) wsHandleData(respRaw []byte) error {
return err
}
default:
- h.Websocket.DataHandler <- wshandler.UnhandledMessageWarning{Message: h.Name + wshandler.UnhandledMessage + string(respRaw)}
+ h.Websocket.DataHandler <- stream.UnhandledMessageWarning{Message: h.Name + stream.UnhandledMessage + string(respRaw)}
return nil
}
return nil
@@ -279,24 +288,28 @@ func (h *HitBTC) WsProcessOrderbookSnapshot(ob WsOrderbook) error {
})
}
- p := currency.NewPairFromFormattedPairs(ob.Params.Symbol,
- h.GetEnabledPairs(asset.Spot), h.GetPairFormat(asset.Spot, true))
- newOrderBook.AssetType = asset.Spot
- newOrderBook.Pair = p
- newOrderBook.ExchangeName = h.Name
-
- err := h.Websocket.Orderbook.LoadSnapshot(&newOrderBook)
+ pairs, err := h.GetEnabledPairs(asset.Spot)
if err != nil {
return err
}
- h.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
- Exchange: h.Name,
- Asset: asset.Spot,
- Pair: p,
+ format, err := h.GetPairFormat(asset.Spot, true)
+ if err != nil {
+ return err
}
- return nil
+ p, err := currency.NewPairFromFormattedPairs(ob.Params.Symbol,
+ pairs,
+ format)
+ if err != nil {
+ h.Websocket.DataHandler <- err
+ return err
+ }
+ newOrderBook.AssetType = asset.Spot
+ newOrderBook.Pair = p
+ newOrderBook.ExchangeName = h.Name
+
+ return h.Websocket.Orderbook.LoadSnapshot(&newOrderBook)
}
func (h *HitBTC) wsHandleOrderData(o *wsOrderData) error {
@@ -336,7 +349,16 @@ func (h *HitBTC) wsHandleOrderData(o *wsOrderData) error {
Err: err,
}
}
- p := currency.NewPairFromString(o.Symbol)
+
+ p, err := currency.NewPairFromString(o.Symbol)
+ if err != nil {
+ h.Websocket.DataHandler <- order.ClassificationError{
+ Exchange: h.Name,
+ OrderID: o.ID,
+ Err: err,
+ }
+ }
+
var a asset.Item
a, err = h.GetPairAssetType(p)
if err != nil {
@@ -364,7 +386,9 @@ func (h *HitBTC) wsHandleOrderData(o *wsOrderData) error {
// WsProcessOrderbookUpdate updates a local cache
func (h *HitBTC) WsProcessOrderbookUpdate(update WsOrderbook) error {
if len(update.Params.Bid) == 0 && len(update.Params.Ask) == 0 {
- return errors.New("hitbtc_websocket.go error - no data")
+ // Periodically HitBTC sends empty updates which includes a sequence
+ // can return this as nil.
+ return nil
}
var bids, asks []orderbook.Item
@@ -382,105 +406,132 @@ func (h *HitBTC) WsProcessOrderbookUpdate(update WsOrderbook) error {
})
}
- p := currency.NewPairFromFormattedPairs(update.Params.Symbol,
- h.GetEnabledPairs(asset.Spot), h.GetPairFormat(asset.Spot, true))
- err := h.Websocket.Orderbook.Update(&wsorderbook.WebsocketOrderbookUpdate{
+ pairs, err := h.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return err
+ }
+
+ format, err := h.GetPairFormat(asset.Spot, true)
+ if err != nil {
+ return err
+ }
+
+ p, err := currency.NewPairFromFormattedPairs(update.Params.Symbol,
+ pairs,
+ format)
+ if err != nil {
+ return err
+ }
+
+ return h.Websocket.Orderbook.Update(&buffer.Update{
Asks: asks,
Bids: bids,
Pair: p,
UpdateID: update.Params.Sequence,
Asset: asset.Spot,
})
- if err != nil {
- return err
- }
+}
- h.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
- Exchange: h.Name,
- Asset: asset.Spot,
- Pair: p,
+// GenerateDefaultSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions()
+func (h *HitBTC) GenerateDefaultSubscriptions() ([]stream.ChannelSubscription, error) {
+ var channels = []string{"subscribeTicker",
+ "subscribeOrderbook",
+ "subscribeTrades",
+ "subscribeCandles"}
+
+ var subscriptions []stream.ChannelSubscription
+ if h.Websocket.CanUseAuthenticatedEndpoints() {
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
+ Channel: "subscribeReports",
+ })
+ }
+ enabledCurrencies, err := h.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+ for i := range channels {
+ for j := range enabledCurrencies {
+ fpair, err := h.FormatExchangeCurrency(enabledCurrencies[j], asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+
+ enabledCurrencies[j].Delimiter = ""
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
+ Channel: channels[i],
+ Currency: fpair,
+ Asset: asset.Spot,
+ })
+ }
+ }
+ return subscriptions, nil
+}
+
+// Subscribe sends a websocket message to receive data from the channel
+func (h *HitBTC) Subscribe(channelsToSubscribe []stream.ChannelSubscription) error {
+ var errs common.Errors
+ for i := range channelsToSubscribe {
+ subscribe := WsRequest{
+ Method: channelsToSubscribe[i].Channel,
+ ID: h.Websocket.Conn.GenerateMessageID(false),
+ }
+
+ if channelsToSubscribe[i].Currency.String() != "" {
+ subscribe.Params.Symbol = channelsToSubscribe[i].Currency.String()
+ }
+ if strings.EqualFold(channelsToSubscribe[i].Channel, "subscribeTrades") {
+ subscribe.Params.Limit = 100
+ } else if strings.EqualFold(channelsToSubscribe[i].Channel, "subscribeCandles") {
+ subscribe.Params.Period = "M30"
+ subscribe.Params.Limit = 100
+ }
+
+ err := h.Websocket.Conn.SendJSONMessage(subscribe)
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ h.Websocket.AddSuccessfulSubscriptions(channelsToSubscribe[i])
+ }
+ if errs != nil {
+ return errs
}
return nil
}
-// GenerateDefaultSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions()
-func (h *HitBTC) GenerateDefaultSubscriptions() {
- var channels = []string{"subscribeTicker", "subscribeOrderbook", "subscribeTrades", "subscribeCandles"}
- var subscriptions []wshandler.WebsocketChannelSubscription
- if h.Websocket.CanUseAuthenticatedEndpoints() {
- subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
- Channel: "subscribeReports",
- })
- }
- enabledCurrencies := h.GetEnabledPairs(asset.Spot)
- for i := range channels {
- for j := range enabledCurrencies {
- enabledCurrencies[j].Delimiter = ""
- subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
- Channel: channels[i],
- Currency: enabledCurrencies[j],
- })
- }
- }
- h.Websocket.SubscribeToChannels(subscriptions)
-}
-
-// Subscribe sends a websocket message to receive data from the channel
-func (h *HitBTC) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
- subscribe := WsNotification{
- Method: channelToSubscribe.Channel,
- }
- if channelToSubscribe.Currency.String() != "" {
- subscribe.Params = params{
- Symbol: h.FormatExchangeCurrency(channelToSubscribe.Currency,
- asset.Spot).String(),
- }
- }
- if strings.EqualFold(channelToSubscribe.Channel, "subscribeTrades") {
- subscribe.Params = params{
- Symbol: h.FormatExchangeCurrency(channelToSubscribe.Currency,
- asset.Spot).String(),
- Limit: 100,
- }
- } else if strings.EqualFold(channelToSubscribe.Channel, "subscribeCandles") {
- subscribe.Params = params{
- Symbol: h.FormatExchangeCurrency(channelToSubscribe.Currency,
- asset.Spot).String(),
- Period: "M30",
- Limit: 100,
- }
- }
-
- return h.WebsocketConn.SendJSONMessage(subscribe)
-}
-
// Unsubscribe sends a websocket message to stop receiving data from the channel
-func (h *HitBTC) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
- unsubscribeChannel := strings.Replace(channelToSubscribe.Channel, "subscribe", "unsubscribe", 1)
- subscribe := WsNotification{
- JSONRPCVersion: rpcVersion,
- Method: unsubscribeChannel,
- Params: params{
- Symbol: h.FormatExchangeCurrency(channelToSubscribe.Currency,
- asset.Spot).String(),
- },
- }
- if strings.EqualFold(unsubscribeChannel, "unsubscribeTrades") {
- subscribe.Params = params{
- Symbol: h.FormatExchangeCurrency(channelToSubscribe.Currency,
- asset.Spot).String(),
- Limit: 100,
- }
- } else if strings.EqualFold(unsubscribeChannel, "unsubscribeCandles") {
- subscribe.Params = params{
- Symbol: h.FormatExchangeCurrency(channelToSubscribe.Currency,
- asset.Spot).String(),
- Period: "M30",
- Limit: 100,
- }
- }
+func (h *HitBTC) Unsubscribe(channelsToUnsubscribe []stream.ChannelSubscription) error {
+ var errs common.Errors
+ for i := range channelsToUnsubscribe {
+ unsubscribeChannel := strings.Replace(channelsToUnsubscribe[i].Channel,
+ "subscribe",
+ "unsubscribe",
+ 1)
- return h.WebsocketConn.SendJSONMessage(subscribe)
+ unsubscribe := WsNotification{
+ JSONRPCVersion: rpcVersion,
+ Method: unsubscribeChannel,
+ }
+
+ unsubscribe.Params.Symbol = channelsToUnsubscribe[i].Currency.String()
+ if strings.EqualFold(unsubscribeChannel, "unsubscribeTrades") {
+ unsubscribe.Params.Limit = 100
+ } else if strings.EqualFold(unsubscribeChannel, "unsubscribeCandles") {
+ unsubscribe.Params.Period = "M30"
+ unsubscribe.Params.Limit = 100
+ }
+
+ err := h.Websocket.Conn.SendJSONMessage(unsubscribe)
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ h.Websocket.RemoveSuccessfulUnsubscriptions(channelsToUnsubscribe[i])
+ }
+ if errs != nil {
+ return errs
+ }
+ return nil
}
// Unsubscribe sends a websocket message to stop receiving data from the channel
@@ -499,13 +550,15 @@ func (h *HitBTC) wsLogin() error {
Nonce: n,
Signature: crypto.HexEncodeToString(hmac),
},
+ ID: h.Websocket.Conn.GenerateMessageID(false),
}
- err := h.WebsocketConn.SendJSONMessage(request)
+ err := h.Websocket.Conn.SendJSONMessage(request)
if err != nil {
h.Websocket.SetCanUseAuthenticatedEndpoints(false)
return err
}
+
return nil
}
@@ -514,19 +567,25 @@ func (h *HitBTC) wsPlaceOrder(pair currency.Pair, side string, price, quantity f
if !h.Websocket.CanUseAuthenticatedEndpoints() {
return nil, fmt.Errorf("%v not authenticated, cannot place order", h.Name)
}
- id := h.WebsocketConn.GenerateMessageID(false)
+
+ id := h.Websocket.Conn.GenerateMessageID(false)
+ fpair, err := h.FormatExchangeCurrency(pair, asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+
request := WsSubmitOrderRequest{
Method: "newOrder",
Params: WsSubmitOrderRequestData{
ClientOrderID: id,
- Symbol: h.FormatExchangeCurrency(pair, asset.Spot).String(),
+ Symbol: fpair.String(),
Side: strings.ToLower(side),
Price: price,
Quantity: quantity,
},
ID: id,
}
- resp, err := h.WebsocketConn.SendMessageReturnResponse(id, request)
+ resp, err := h.Websocket.Conn.SendMessageReturnResponse(id, request)
if err != nil {
return nil, fmt.Errorf("%v %v", h.Name, err)
}
@@ -551,9 +610,9 @@ func (h *HitBTC) wsCancelOrder(clientOrderID string) (*WsCancelOrderResponse, er
Params: WsCancelOrderRequestData{
ClientOrderID: clientOrderID,
},
- ID: h.WebsocketConn.GenerateMessageID(false),
+ ID: h.Websocket.Conn.GenerateMessageID(false),
}
- resp, err := h.WebsocketConn.SendMessageReturnResponse(request.ID, request)
+ resp, err := h.Websocket.Conn.SendMessageReturnResponse(request.ID, request)
if err != nil {
return nil, fmt.Errorf("%v %v", h.Name, err)
}
@@ -581,9 +640,9 @@ func (h *HitBTC) wsReplaceOrder(clientOrderID string, quantity, price float64) (
Quantity: quantity,
Price: price,
},
- ID: h.WebsocketConn.GenerateMessageID(false),
+ ID: h.Websocket.Conn.GenerateMessageID(false),
}
- resp, err := h.WebsocketConn.SendMessageReturnResponse(request.ID, request)
+ resp, err := h.Websocket.Conn.SendMessageReturnResponse(request.ID, request)
if err != nil {
return nil, fmt.Errorf("%v %v", h.Name, err)
}
@@ -601,14 +660,14 @@ func (h *HitBTC) wsReplaceOrder(clientOrderID string, quantity, price float64) (
// wsGetActiveOrders sends a websocket message to get all active orders
func (h *HitBTC) wsGetActiveOrders() (*wsActiveOrdersResponse, error) {
if !h.Websocket.CanUseAuthenticatedEndpoints() {
- return nil, fmt.Errorf("%v not authenticated, cannot place order", h.Name)
+ return nil, fmt.Errorf("%v not authenticated, cannot get active orders", h.Name)
}
request := WsReplaceOrderRequest{
Method: "getOrders",
Params: WsReplaceOrderRequestData{},
- ID: h.WebsocketConn.GenerateMessageID(false),
+ ID: h.Websocket.Conn.GenerateMessageID(false),
}
- resp, err := h.WebsocketConn.SendMessageReturnResponse(request.ID, request)
+ resp, err := h.Websocket.Conn.SendMessageReturnResponse(request.ID, request)
if err != nil {
return nil, fmt.Errorf("%v %v", h.Name, err)
}
@@ -631,9 +690,9 @@ func (h *HitBTC) wsGetTradingBalance() (*WsGetTradingBalanceResponse, error) {
request := WsReplaceOrderRequest{
Method: "getTradingBalance",
Params: WsReplaceOrderRequestData{},
- ID: h.WebsocketConn.GenerateMessageID(false),
+ ID: h.Websocket.Conn.GenerateMessageID(false),
}
- resp, err := h.WebsocketConn.SendMessageReturnResponse(request.ID, request)
+ resp, err := h.Websocket.Conn.SendMessageReturnResponse(request.ID, request)
if err != nil {
return nil, fmt.Errorf("%v %v", h.Name, err)
}
@@ -655,9 +714,9 @@ func (h *HitBTC) wsGetCurrencies(currencyItem currency.Code) (*WsGetCurrenciesRe
Params: WsGetCurrenciesRequestParameters{
Currency: currencyItem,
},
- ID: h.WebsocketConn.GenerateMessageID(false),
+ ID: h.Websocket.Conn.GenerateMessageID(false),
}
- resp, err := h.WebsocketConn.SendMessageReturnResponse(request.ID, request)
+ resp, err := h.Websocket.Conn.SendMessageReturnResponse(request.ID, request)
if err != nil {
return nil, fmt.Errorf("%v %v", h.Name, err)
}
@@ -673,15 +732,20 @@ func (h *HitBTC) wsGetCurrencies(currencyItem currency.Code) (*WsGetCurrenciesRe
}
// wsGetSymbols sends a websocket message to get trading balance
-func (h *HitBTC) wsGetSymbols(currencyItem currency.Pair) (*WsGetSymbolsResponse, error) {
+func (h *HitBTC) wsGetSymbols(c currency.Pair) (*WsGetSymbolsResponse, error) {
+ fpair, err := h.FormatExchangeCurrency(c, asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+
request := WsGetSymbolsRequest{
Method: "getSymbol",
Params: WsGetSymbolsRequestParameters{
- Symbol: h.FormatExchangeCurrency(currencyItem, asset.Spot).String(),
+ Symbol: fpair.String(),
},
- ID: h.WebsocketConn.GenerateMessageID(false),
+ ID: h.Websocket.Conn.GenerateMessageID(false),
}
- resp, err := h.WebsocketConn.SendMessageReturnResponse(request.ID, request)
+ resp, err := h.Websocket.Conn.SendMessageReturnResponse(request.ID, request)
if err != nil {
return nil, fmt.Errorf("%v %v", h.Name, err)
}
@@ -697,18 +761,23 @@ func (h *HitBTC) wsGetSymbols(currencyItem currency.Pair) (*WsGetSymbolsResponse
}
// wsGetSymbols sends a websocket message to get trading balance
-func (h *HitBTC) wsGetTrades(currencyItem currency.Pair, limit int64, sort, by string) (*WsGetTradesResponse, error) {
+func (h *HitBTC) wsGetTrades(c currency.Pair, limit int64, sort, by string) (*WsGetTradesResponse, error) {
+ fpair, err := h.FormatExchangeCurrency(c, asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+
request := WsGetTradesRequest{
Method: "getTrades",
Params: WsGetTradesRequestParameters{
- Symbol: h.FormatExchangeCurrency(currencyItem, asset.Spot).String(),
+ Symbol: fpair.String(),
Limit: limit,
Sort: sort,
By: by,
},
- ID: h.WebsocketConn.GenerateMessageID(false),
+ ID: h.Websocket.Conn.GenerateMessageID(false),
}
- resp, err := h.WebsocketConn.SendMessageReturnResponse(request.ID, request)
+ resp, err := h.Websocket.Conn.SendMessageReturnResponse(request.ID, request)
if err != nil {
return nil, fmt.Errorf("%v %v", h.Name, err)
}
diff --git a/exchanges/hitbtc/hitbtc_wrapper.go b/exchanges/hitbtc/hitbtc_wrapper.go
index cfbdcb32..f23872d2 100644
--- a/exchanges/hitbtc/hitbtc_wrapper.go
+++ b/exchanges/hitbtc/hitbtc_wrapper.go
@@ -19,8 +19,8 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -56,18 +56,11 @@ func (h *HitBTC) SetDefaults() {
h.API.CredentialsValidator.RequiresKey = true
h.API.CredentialsValidator.RequiresSecret = true
- h.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- },
- UseGlobalFormat: true,
- RequestFormat: ¤cy.PairFormat{
- Uppercase: true,
- },
- ConfigFormat: ¤cy.PairFormat{
- Delimiter: "-",
- Uppercase: true,
- },
+ requestFmt := ¤cy.PairFormat{Uppercase: true}
+ configFmt := ¤cy.PairFormat{Delimiter: currency.DashDelimiter, Uppercase: true}
+ err := h.SetGlobalPairsManager(requestFmt, configFmt, asset.Spot)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
}
h.Features = exchange.Features{
@@ -139,7 +132,7 @@ func (h *HitBTC) SetDefaults() {
h.API.Endpoints.URLDefault = apiURL
h.API.Endpoints.URL = h.API.Endpoints.URLDefault
h.API.Endpoints.WebsocketURL = hitbtcWebsocketAddress
- h.Websocket = wshandler.New()
+ h.Websocket = stream.New()
h.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
h.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
h.WebsocketOrderbookBufferLimit = exchange.DefaultWebsocketOrderbookBufferLimit
@@ -157,42 +150,33 @@ func (h *HitBTC) Setup(exch *config.ExchangeConfig) error {
return err
}
- err = h.Websocket.Setup(
- &wshandler.WebsocketSetup{
- Enabled: exch.Features.Enabled.Websocket,
- Verbose: exch.Verbose,
- AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
- WebsocketTimeout: exch.WebsocketTrafficTimeout,
- DefaultURL: hitbtcWebsocketAddress,
- ExchangeName: exch.Name,
- RunningURL: exch.API.Endpoints.WebsocketURL,
- Connector: h.WsConnect,
- Subscriber: h.Subscribe,
- UnSubscriber: h.Unsubscribe,
- Features: &h.Features.Supports.WebsocketCapabilities,
- })
+ err = h.Websocket.Setup(&stream.WebsocketSetup{
+ Enabled: exch.Features.Enabled.Websocket,
+ Verbose: exch.Verbose,
+ AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
+ WebsocketTimeout: exch.WebsocketTrafficTimeout,
+ DefaultURL: hitbtcWebsocketAddress,
+ ExchangeName: exch.Name,
+ RunningURL: exch.API.Endpoints.WebsocketURL,
+ Connector: h.WsConnect,
+ Subscriber: h.Subscribe,
+ UnSubscriber: h.Unsubscribe,
+ GenerateSubscriptions: h.GenerateDefaultSubscriptions,
+ Features: &h.Features.Supports.WebsocketCapabilities,
+ OrderbookBufferLimit: exch.WebsocketOrderbookBufferLimit,
+ BufferEnabled: true,
+ SortBuffer: true,
+ SortBufferByUpdateIDs: true,
+ })
if err != nil {
return err
}
- h.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: h.Name,
- URL: h.Websocket.GetWebsocketURL(),
- ProxyURL: h.Websocket.GetProxyAddress(),
- Verbose: h.Verbose,
+ return h.Websocket.SetupNewConnection(stream.ConnectionSetup{
RateLimit: rateLimit,
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
- }
-
- h.Websocket.Orderbook.Setup(
- exch.WebsocketOrderbookBufferLimit,
- true,
- true,
- true,
- false,
- exch.Name)
- return nil
+ })
}
// Start starts the HitBTC go routine
@@ -212,16 +196,52 @@ func (h *HitBTC) Run() {
}
forceUpdate := false
- delim := h.GetPairFormat(asset.Spot, false).Delimiter
- if !common.StringDataContains(h.GetEnabledPairs(asset.Spot).Strings(), delim) ||
- !common.StringDataContains(h.GetAvailablePairs(asset.Spot).Strings(), delim) {
- enabledPairs := []string{currency.BTC.String() + delim + currency.USD.String()}
- log.Warn(log.ExchangeSys, "Available pairs for HitBTC reset due to config upgrade, please enable the ones you would like again.")
- forceUpdate = true
+ format, err := h.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update tradable pairs. Err: %s",
+ h.Name,
+ err)
+ return
+ }
+ enabled, err := h.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update tradable pairs. Err: %s",
+ h.Name,
+ err)
+ return
+ }
- err := h.UpdatePairs(currency.NewPairsFromStrings(enabledPairs), asset.Spot, true, true)
+ avail, err := h.GetAvailablePairs(asset.Spot)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update tradable pairs. Err: %s",
+ h.Name,
+ err)
+ return
+ }
+
+ if !common.StringDataContains(enabled.Strings(), format.Delimiter) ||
+ !common.StringDataContains(avail.Strings(), format.Delimiter) {
+ enabledPairs := []string{currency.BTC.String() + format.Delimiter + currency.USD.String()}
+ log.Warn(log.ExchangeSys,
+ "Available pairs for HitBTC reset due to config upgrade, please enable the ones you would like again.")
+ forceUpdate = true
+ var p currency.Pairs
+ p, err = currency.NewPairsFromStrings(enabledPairs)
if err != nil {
- log.Errorf(log.ExchangeSys, "%s failed to update enabled currencies.\n", h.Name)
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update tradable pairs. Err: %s",
+ h.Name,
+ err)
+ return
+ }
+ err = h.UpdatePairs(p, asset.Spot, true, true)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update enabled currencies.\n",
+ h.Name)
}
}
@@ -229,9 +249,12 @@ func (h *HitBTC) Run() {
return
}
- err := h.UpdateTradablePairs(forceUpdate)
+ err = h.UpdateTradablePairs(forceUpdate)
if err != nil {
- log.Errorf(log.ExchangeSys, "%s failed to update tradable pairs. Err: %s", h.Name, err)
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update tradable pairs. Err: %s",
+ h.Name,
+ err)
}
}
@@ -242,10 +265,16 @@ func (h *HitBTC) FetchTradablePairs(asset asset.Item) ([]string, error) {
return nil, err
}
+ format, err := h.GetPairFormat(asset, false)
+ if err != nil {
+ return nil, err
+ }
+
var pairs []string
for x := range symbols {
pairs = append(pairs, symbols[x].BaseCurrency+
- h.GetPairFormat(asset, false).Delimiter+symbols[x].QuoteCurrency)
+ format.Delimiter+
+ symbols[x].QuoteCurrency)
}
return pairs, nil
}
@@ -258,24 +287,34 @@ func (h *HitBTC) UpdateTradablePairs(forceUpdate bool) error {
return err
}
- return h.UpdatePairs(currency.NewPairsFromStrings(pairs), asset.Spot, false, forceUpdate)
+ p, err := currency.NewPairsFromStrings(pairs)
+ if err != nil {
+ return err
+ }
+ return h.UpdatePairs(p, asset.Spot, false, forceUpdate)
}
// UpdateTicker updates and returns the ticker for a currency pair
-func (h *HitBTC) UpdateTicker(currencyPair currency.Pair, assetType asset.Item) (*ticker.Price, error) {
- tickerPrice := new(ticker.Price)
+func (h *HitBTC) UpdateTicker(p currency.Pair, a asset.Item) (*ticker.Price, error) {
tick, err := h.GetTickers()
if err != nil {
- return tickerPrice, err
+ return nil, err
+ }
+ pairs, err := h.GetEnabledPairs(a)
+ if err != nil {
+ return nil, err
}
- pairs := h.GetEnabledPairs(assetType)
for i := range pairs {
for j := range tick {
- pairFmt := h.FormatExchangeCurrency(pairs[i], assetType).String()
- if tick[j].Symbol != pairFmt {
+ pairFmt, err := h.FormatExchangeCurrency(pairs[i], a)
+ if err != nil {
+ return nil, err
+ }
+
+ if tick[j].Symbol != pairFmt.String() {
found := false
if strings.Contains(tick[j].Symbol, "USDT") {
- if pairFmt == tick[j].Symbol[0:len(tick[j].Symbol)-1] {
+ if pairFmt.String() == tick[j].Symbol[0:len(tick[j].Symbol)-1] {
found = true
}
}
@@ -283,25 +322,26 @@ func (h *HitBTC) UpdateTicker(currencyPair currency.Pair, assetType asset.Item)
continue
}
}
- tickerPrice := &ticker.Price{
- Last: tick[j].Last,
- High: tick[j].High,
- Low: tick[j].Low,
- Bid: tick[j].Bid,
- Ask: tick[j].Ask,
- Volume: tick[j].Volume,
- QuoteVolume: tick[j].VolumeQuote,
- Open: tick[j].Open,
- Pair: pairs[i],
- LastUpdated: tick[j].Timestamp,
- }
- err = ticker.ProcessTicker(h.Name, tickerPrice, assetType)
+
+ err = ticker.ProcessTicker(&ticker.Price{
+ Last: tick[j].Last,
+ High: tick[j].High,
+ Low: tick[j].Low,
+ Bid: tick[j].Bid,
+ Ask: tick[j].Ask,
+ Volume: tick[j].Volume,
+ QuoteVolume: tick[j].VolumeQuote,
+ Open: tick[j].Open,
+ Pair: pairs[i],
+ LastUpdated: tick[j].Timestamp,
+ ExchangeName: h.Name,
+ AssetType: a})
if err != nil {
- log.Error(log.Ticker, err)
+ return nil, err
}
}
}
- return ticker.GetTicker(h.Name, currencyPair, assetType)
+ return ticker.GetTicker(h.Name, p, a)
}
// FetchTicker returns the ticker for a currency pair
@@ -323,13 +363,18 @@ func (h *HitBTC) FetchOrderbook(p currency.Pair, assetType asset.Item) (*orderbo
}
// UpdateOrderbook updates and returns the orderbook for a currency pair
-func (h *HitBTC) UpdateOrderbook(currencyPair currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
- orderBook := new(orderbook.Base)
- orderbookNew, err := h.GetOrderbook(h.FormatExchangeCurrency(currencyPair, assetType).String(), 1000)
+func (h *HitBTC) UpdateOrderbook(c currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
+ fpair, err := h.FormatExchangeCurrency(c, assetType)
if err != nil {
- return orderBook, err
+ return nil, err
}
+ orderbookNew, err := h.GetOrderbook(fpair.String(), 1000)
+ if err != nil {
+ return nil, err
+ }
+
+ orderBook := new(orderbook.Base)
for x := range orderbookNew.Bids {
orderBook.Bids = append(orderBook.Bids, orderbook.Item{
Amount: orderbookNew.Bids[x].Amount,
@@ -344,7 +389,7 @@ func (h *HitBTC) UpdateOrderbook(currencyPair currency.Pair, assetType asset.Ite
})
}
- orderBook.Pair = currencyPair
+ orderBook.Pair = c
orderBook.ExchangeName = h.Name
orderBook.AssetType = assetType
@@ -353,7 +398,7 @@ func (h *HitBTC) UpdateOrderbook(currencyPair currency.Pair, assetType asset.Ite
return orderBook, err
}
- return orderbook.Get(h.Name, currencyPair, assetType)
+ return orderbook.Get(h.Name, c, assetType)
}
// UpdateAccountInfo retrieves balances for all enabled currencies for the
@@ -527,11 +572,6 @@ func (h *HitBTC) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdraw.
return nil, common.ErrFunctionNotSupported
}
-// GetWebsocket returns a pointer to the exchange websocket
-func (h *HitBTC) GetWebsocket() (*wshandler.Websocket, error) {
- return h.Websocket, nil
-}
-
// GetFeeByType returns an estimate of fee based on type of transaction
func (h *HitBTC) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if !h.AllowAuthenticatedRequest() && // Todo check connection status
@@ -556,10 +596,19 @@ func (h *HitBTC) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
allOrders = append(allOrders, resp...)
}
+ format, err := h.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return nil, err
+ }
+
var orders []order.Detail
for i := range allOrders {
- symbol := currency.NewPairDelimiter(allOrders[i].Symbol,
- h.GetPairFormat(asset.Spot, false).Delimiter)
+ var symbol currency.Pair
+ symbol, err = currency.NewPairDelimiter(allOrders[i].Symbol,
+ format.Delimiter)
+ if err != nil {
+ return nil, err
+ }
side := order.Side(strings.ToUpper(allOrders[i].Side))
orders = append(orders, order.Detail{
ID: allOrders[i].ID,
@@ -593,10 +642,19 @@ func (h *HitBTC) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, e
allOrders = append(allOrders, resp...)
}
+ format, err := h.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return nil, err
+ }
+
var orders []order.Detail
for i := range allOrders {
- symbol := currency.NewPairDelimiter(allOrders[i].Symbol,
- h.GetPairFormat(asset.Spot, false).Delimiter)
+ var symbol currency.Pair
+ symbol, err = currency.NewPairDelimiter(allOrders[i].Symbol,
+ format.Delimiter)
+ if err != nil {
+ return nil, err
+ }
side := order.Side(strings.ToUpper(allOrders[i].Side))
orders = append(orders, order.Detail{
ID: allOrders[i].ID,
@@ -614,25 +672,6 @@ func (h *HitBTC) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, e
return orders, nil
}
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func (h *HitBTC) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- h.Websocket.SubscribeToChannels(channels)
- return nil
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func (h *HitBTC) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- h.Websocket.RemoveSubscribedChannels(channels)
- return nil
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func (h *HitBTC) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return h.Websocket.GetSubscriptions(), nil
-}
-
// AuthenticateWebsocket sends an authentication message to the websocket
func (h *HitBTC) AuthenticateWebsocket() error {
return h.wsLogin()
@@ -666,7 +705,13 @@ func (h *HitBTC) GetHistoricCandles(pair currency.Pair, a asset.Item, start, end
Interval: interval,
}
}
- data, err := h.GetCandles(h.FormatExchangeCurrency(pair, a).String(),
+
+ formattedPair, err := h.FormatExchangeCurrency(pair, a)
+ if err != nil {
+ return kline.Item{}, err
+ }
+
+ data, err := h.GetCandles(formattedPair.String(),
strconv.FormatInt(int64(h.Features.Enabled.Kline.ResultLimit), 10),
h.FormatExchangeKlineInterval(interval),
start, end)
@@ -711,8 +756,13 @@ func (h *HitBTC) GetHistoricCandlesExtended(pair currency.Pair, a asset.Item, st
}
dates := kline.CalcDateRanges(start, end, interval, h.Features.Enabled.Kline.ResultLimit)
+ formattedPair, err := h.FormatExchangeCurrency(pair, a)
+ if err != nil {
+ return kline.Item{}, err
+ }
+
for y := range dates {
- data, err := h.GetCandles(h.FormatExchangeCurrency(pair, a).String(),
+ data, err := h.GetCandles(formattedPair.String(),
strconv.FormatInt(int64(h.Features.Enabled.Kline.ResultLimit), 10),
h.FormatExchangeKlineInterval(interval),
dates[y].Start, dates[y].End)
diff --git a/exchanges/huobi/huobi.go b/exchanges/huobi/huobi.go
index 3f543fae..c0fc5d8a 100644
--- a/exchanges/huobi/huobi.go
+++ b/exchanges/huobi/huobi.go
@@ -16,7 +16,6 @@ import (
"github.com/thrasher-corp/gocryptotrader/currency"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
)
const (
@@ -62,9 +61,7 @@ const (
// HUOBI is the overarching type across this package
type HUOBI struct {
exchange.Base
- AccountID string
- WebsocketConn *wshandler.WebsocketConnection
- AuthenticatedWebsocketConn *wshandler.WebsocketConnection
+ AccountID string
}
// GetSpotKline returns kline data
diff --git a/exchanges/huobi/huobi_test.go b/exchanges/huobi/huobi_test.go
index 6bf3148b..03d692c1 100644
--- a/exchanges/huobi/huobi_test.go
+++ b/exchanges/huobi/huobi_test.go
@@ -17,7 +17,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -47,13 +47,11 @@ func TestMain(m *testing.M) {
hConfig.API.AuthenticatedWebsocketSupport = true
hConfig.API.Credentials.Key = apiKey
hConfig.API.Credentials.Secret = apiSecret
-
+ h.Websocket = sharedtestvalues.NewTestWebsocket()
err = h.Setup(hConfig)
if err != nil {
log.Fatal("Huobi setup error", err)
}
- h.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- h.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
os.Exit(m.Run())
}
@@ -62,26 +60,10 @@ func setupWsTests(t *testing.T) {
return
}
if !h.Websocket.IsEnabled() && !h.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
- t.Skip(wshandler.WebsocketNotEnabled)
+ t.Skip(stream.WebsocketNotEnabled)
}
comms = make(chan WsMessage, sharedtestvalues.WebsocketChannelOverrideCapacity)
- h.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- h.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
go h.wsReadData()
- h.AuthenticatedWebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: h.Name,
- URL: wsAccountsOrdersURL,
- Verbose: h.Verbose,
- ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
- ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
- }
- h.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: h.Name,
- URL: wsMarketURL,
- Verbose: h.Verbose,
- ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
- ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
- }
var dialer websocket.Dialer
err := h.wsAuthenticatedDial(&dialer)
if err != nil {
@@ -108,9 +90,12 @@ func TestGetSpotKline(t *testing.T) {
}
func TestGetHistoricCandles(t *testing.T) {
- currencyPair := currency.NewPairFromString("BTCUSDT")
+ currencyPair, err := currency.NewPairFromString("BTCUSDT")
+ if err != nil {
+ t.Fatal(err)
+ }
startTime := time.Now().Add(-time.Hour * 1)
- _, err := h.GetHistoricCandles(currencyPair, asset.Spot, startTime, time.Now(), kline.OneMin)
+ _, err = h.GetHistoricCandles(currencyPair, asset.Spot, startTime, time.Now(), kline.OneMin)
if err != nil {
t.Fatal(err)
}
@@ -127,9 +112,12 @@ func TestGetHistoricCandles(t *testing.T) {
}
func TestGetHistoricCandlesExtended(t *testing.T) {
- currencyPair := currency.NewPairFromString("BTCUSDT")
+ currencyPair, err := currency.NewPairFromString("BTCUSDT")
+ if err != nil {
+ t.Fatal(err)
+ }
startTime := time.Now().Add(-time.Hour * 1)
- _, err := h.GetHistoricCandlesExtended(currencyPair, asset.Spot, startTime, time.Now(), kline.OneMin)
+ _, err = h.GetHistoricCandlesExtended(currencyPair, asset.Spot, startTime, time.Now(), kline.OneMin)
if err != nil {
t.Fatal(err)
}
@@ -663,24 +651,22 @@ func TestQueryWithdrawQuota(t *testing.T) {
// TestWsGetAccountsList connects to WS, logs in, gets account list
func TestWsGetAccountsList(t *testing.T) {
setupWsTests(t)
- resp, err := h.wsGetAccountsList()
+ _, err := h.wsGetAccountsList()
if err != nil {
t.Fatal(err)
}
- if resp.ErrorCode > 0 {
- t.Error(resp.ErrorMessage)
- }
}
// TestWsGetOrderList connects to WS, logs in, gets order list
func TestWsGetOrderList(t *testing.T) {
setupWsTests(t)
- resp, err := h.wsGetOrdersList(1, currency.NewPairFromString("ethbtc"))
+ p, err := currency.NewPairFromString("ethbtc")
if err != nil {
t.Fatal(err)
}
- if resp.ErrorCode > 0 {
- t.Error(resp.ErrorMessage)
+ _, err = h.wsGetOrdersList(1, p)
+ if err != nil {
+ t.Fatal(err)
}
}
@@ -688,13 +674,10 @@ func TestWsGetOrderList(t *testing.T) {
func TestWsGetOrderDetails(t *testing.T) {
setupWsTests(t)
orderID := "123"
- resp, err := h.wsGetOrderDetails(orderID)
+ _, err := h.wsGetOrderDetails(orderID)
if err != nil {
t.Fatal(err)
}
- if resp.ErrorCode > 0 && resp.ErrorCode != 10022 {
- t.Error(resp.ErrorMessage)
- }
}
func TestWsSubResponse(t *testing.T) {
diff --git a/exchanges/huobi/huobi_types.go b/exchanges/huobi/huobi_types.go
index b2e6cdb6..b435b0c3 100644
--- a/exchanges/huobi/huobi_types.go
+++ b/exchanges/huobi/huobi_types.go
@@ -315,18 +315,19 @@ type WsRequest struct {
// WsResponse defines a response from the websocket connection when there
// is an error
type WsResponse struct {
- Op string `json:"op"`
- TS int64 `json:"ts"`
- Status string `json:"status"`
- ErrorCode int64 `json:"err-code"`
- ErrorMessage string `json:"err-msg"`
- Ping int64 `json:"ping"`
- Channel string `json:"ch"`
- Rep string `json:"rep"`
- Topic string `json:"topic"`
- Subscribed string `json:"subbed"`
- UnSubscribed string `json:"unsubbed"`
- ClientID int64 `json:"cid,string"`
+ Op string `json:"op"`
+ TS int64 `json:"ts"`
+ Status string `json:"status"`
+ // ErrorCode returns either an integer or a string
+ ErrorCode interface{} `json:"err-code"`
+ ErrorMessage string `json:"err-msg"`
+ Ping int64 `json:"ping"`
+ Channel string `json:"ch"`
+ Rep string `json:"rep"`
+ Topic string `json:"topic"`
+ Subscribed string `json:"subbed"`
+ UnSubscribed string `json:"unsubbed"`
+ ClientID int64 `json:"cid,string"`
}
// WsHeartBeat defines a heartbeat request
@@ -359,7 +360,7 @@ type WsKline struct {
Amount float64 `json:"amount"`
Volume float64 `json:"vol"`
Count int64 `json:"count"`
- }
+ } `json:"tick"`
}
// WsTick stores websocket ticker data
@@ -577,7 +578,7 @@ type WsPong struct {
Pong int64 `json:"pong"`
}
-type wsKLineResponseThing struct {
+type wsKlineResponse struct {
Data []struct {
Amount float64 `json:"amount"`
Close float64 `json:"close"`
@@ -591,3 +592,8 @@ type wsKLineResponseThing struct {
Rep string `json:"rep"`
Status string `json:"status"`
}
+
+type authenticationPing struct {
+ OP string `json:"op"`
+ TS int64 `json:"ts"`
+}
diff --git a/exchanges/huobi/huobi_websocket.go b/exchanges/huobi/huobi_websocket.go
index 4f773411..9bebc259 100644
--- a/exchanges/huobi/huobi_websocket.go
+++ b/exchanges/huobi/huobi_websocket.go
@@ -11,14 +11,15 @@ import (
"time"
"github.com/gorilla/websocket"
+ "github.com/thrasher-corp/gocryptotrader/common"
"github.com/thrasher-corp/gocryptotrader/common/crypto"
"github.com/thrasher-corp/gocryptotrader/currency"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
)
@@ -57,7 +58,7 @@ var comms = make(chan WsMessage)
// WsConnect initiates a new websocket connection
func (h *HUOBI) WsConnect() error {
if !h.Websocket.IsEnabled() || !h.IsEnabled() {
- return errors.New(wshandler.WebsocketNotEnabled)
+ return errors.New(stream.WebsocketNotEnabled)
}
var dialer websocket.Dialer
err := h.wsDial(&dialer)
@@ -66,58 +67,61 @@ func (h *HUOBI) WsConnect() error {
}
err = h.wsAuthenticatedDial(&dialer)
if err != nil {
- log.Errorf(log.ExchangeSys, "%v - authenticated dial failed: %v\n", h.Name, err)
+ log.Errorf(log.ExchangeSys,
+ "%v - authenticated dial failed: %v\n",
+ h.Name,
+ err)
}
err = h.wsLogin()
if err != nil {
- log.Errorf(log.ExchangeSys, "%v - authentication failed: %v\n", h.Name, err)
+ log.Errorf(log.ExchangeSys,
+ "%v - authentication failed: %v\n",
+ h.Name,
+ err)
h.Websocket.SetCanUseAuthenticatedEndpoints(false)
}
go h.wsReadData()
- h.GenerateDefaultSubscriptions()
-
- return nil
-}
-
-func (h *HUOBI) wsDial(dialer *websocket.Dialer) error {
- err := h.WebsocketConn.Dial(dialer, http.Header{})
+ subs, err := h.GenerateDefaultSubscriptions()
if err != nil {
return err
}
- go h.wsFunnelConnectionData(h.WebsocketConn, wsMarketURL)
+ return h.Websocket.SubscribeToChannels(subs)
+}
+
+func (h *HUOBI) wsDial(dialer *websocket.Dialer) error {
+ err := h.Websocket.Conn.Dial(dialer, http.Header{})
+ if err != nil {
+ return err
+ }
+ go h.wsFunnelConnectionData(h.Websocket.Conn, wsMarketURL)
return nil
}
func (h *HUOBI) wsAuthenticatedDial(dialer *websocket.Dialer) error {
if !h.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
- return fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", h.Name)
+ return fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled",
+ h.Name)
}
- err := h.AuthenticatedWebsocketConn.Dial(dialer, http.Header{})
+ err := h.Websocket.AuthConn.Dial(dialer, http.Header{})
if err != nil {
return err
}
- go h.wsFunnelConnectionData(h.AuthenticatedWebsocketConn, wsAccountsOrdersURL)
+ go h.wsFunnelConnectionData(h.Websocket.AuthConn, wsAccountsOrdersURL)
return nil
}
-// wsFunnelConnectionData manages data from multiple endpoints and passes it to a channel
-func (h *HUOBI) wsFunnelConnectionData(ws *wshandler.WebsocketConnection, url string) {
+// wsFunnelConnectionData manages data from multiple endpoints and passes it to
+// a channel
+func (h *HUOBI) wsFunnelConnectionData(ws stream.Connection, url string) {
h.Websocket.Wg.Add(1)
defer h.Websocket.Wg.Done()
for {
- select {
- case <-h.Websocket.ShutdownC:
+ resp := ws.ReadMessage()
+ if resp.Raw == nil {
return
- default:
- resp, err := ws.ReadMessage()
- if err != nil {
- h.Websocket.DataHandler <- err
- return
- }
- h.Websocket.TrafficAlert <- struct{}{}
- comms <- WsMessage{Raw: resp.Raw, URL: url}
}
+ comms <- WsMessage{Raw: resp.Raw, URL: url}
}
}
@@ -126,14 +130,10 @@ func (h *HUOBI) wsReadData() {
h.Websocket.Wg.Add(1)
defer h.Websocket.Wg.Done()
for {
- select {
- case <-h.Websocket.ShutdownC:
- return
- case resp := <-comms:
- err := h.wsHandleData(resp.Raw)
- if err != nil {
- h.Websocket.DataHandler <- err
- }
+ resp := <-comms
+ err := h.wsHandleData(resp.Raw)
+ if err != nil {
+ h.Websocket.DataHandler <- err
}
}
}
@@ -149,7 +149,8 @@ func stringToOrderStatus(status string) (order.Status, error) {
case "partial-canceled":
return order.PartiallyCancelled, nil
default:
- return order.UnknownStatus, errors.New(status + " not recognised as order status")
+ return order.UnknownStatus,
+ errors.New(status + " not recognised as order status")
}
}
@@ -161,7 +162,8 @@ func stringToOrderSide(side string) (order.Side, error) {
return order.Sell, nil
}
- return order.UnknownSide, errors.New(side + " not recognised as order side")
+ return order.UnknownSide,
+ errors.New(side + " not recognised as order side")
}
func stringToOrderType(oType string) (order.Type, error) {
@@ -172,7 +174,8 @@ func stringToOrderType(oType string) (order.Type, error) {
return order.Market, nil
}
- return order.UnknownType, errors.New(oType + " not recognised as order type")
+ return order.UnknownType,
+ errors.New(oType + " not recognised as order type")
}
func (h *HUOBI) wsHandleData(respRaw []byte) error {
@@ -192,13 +195,32 @@ func (h *HUOBI) wsHandleData(respRaw []byte) error {
h.sendPingResponse(init.Ping)
return nil
}
- if init.ErrorMessage == "api-signature-not-valid" {
- h.Websocket.SetCanUseAuthenticatedEndpoints(false)
- return errors.New(h.Name + " - invalid credentials. Authenticated requests disabled")
+
+ if init.Op == "ping" {
+ authPing := authenticationPing{
+ OP: "pong",
+ TS: init.TS,
+ }
+ err := h.Websocket.AuthConn.SendJSONMessage(authPing)
+ if err != nil {
+ log.Error(log.ExchangeSys, err)
+ }
+ return nil
}
+
+ if init.ErrorMessage != "" {
+ if init.ErrorMessage == "api-signature-not-valid" {
+ h.Websocket.SetCanUseAuthenticatedEndpoints(false)
+ return errors.New(h.Name +
+ " - invalid credentials. Authenticated requests disabled")
+ }
+
+ codes, _ := init.ErrorCode.(string)
+ return errors.New(h.Name + " Code:" + codes + " Message:" + init.ErrorMessage)
+ }
+
if init.ClientID > 0 {
- if h.WebsocketConn.IsIDWaitingForResponse(init.ClientID) {
- h.WebsocketConn.SetResponseIDAndData(init.ClientID, respRaw)
+ if h.Websocket.Match.IncomingWithData(init.ClientID, respRaw) {
return nil
}
}
@@ -206,12 +228,8 @@ func (h *HUOBI) wsHandleData(respRaw []byte) error {
switch {
case strings.EqualFold(init.Op, authOp):
h.Websocket.SetCanUseAuthenticatedEndpoints(true)
- err := json.Unmarshal(respRaw, &init)
- if err != nil {
- return err
- }
- h.Websocket.DataHandler <- init
-
+ // Auth captured
+ return nil
case strings.EqualFold(init.Topic, "accounts"):
var response WsAuthenticatedAccountsResponse
err := json.Unmarshal(respRaw, &response)
@@ -229,7 +247,8 @@ func (h *HUOBI) wsHandleData(respRaw []byte) error {
}
data := strings.Split(response.Topic, ".")
if len(data) < 2 {
- return errors.New(h.Name + " - currency could not be extracted from response")
+ return errors.New(h.Name +
+ " - currency could not be extracted from response")
}
orderID := strconv.FormatInt(response.Data.OrderID, 10)
var oSide order.Side
@@ -299,27 +318,6 @@ func (h *HUOBI) wsHandleData(respRaw []byte) error {
if err != nil {
return err
}
- case strings.Contains(init.Rep, "kline"):
- var kline wsKLineResponseThing
- err := json.Unmarshal(respRaw, &kline)
- if err != nil {
- return err
- }
- var curr = strings.Split(init.Rep, ".")
- for i := range kline.Data {
- h.Websocket.DataHandler <- wshandler.KlineData{
- Timestamp: time.Now(),
- Exchange: h.Name,
- AssetType: asset.Spot,
- Pair: currency.NewPairFromFormattedPairs(curr[1],
- h.GetEnabledPairs(asset.Spot), h.GetPairFormat(asset.Spot, true)),
- OpenPrice: kline.Data[i].Open,
- ClosePrice: kline.Data[i].Close,
- HighPrice: kline.Data[i].High,
- LowPrice: kline.Data[i].Low,
- Volume: kline.Data[i].Volume,
- }
- }
case strings.Contains(init.Channel, "kline"):
var kline WsKline
err := json.Unmarshal(respRaw, &kline)
@@ -327,17 +325,23 @@ func (h *HUOBI) wsHandleData(respRaw []byte) error {
return err
}
data := strings.Split(kline.Channel, ".")
- h.Websocket.DataHandler <- wshandler.KlineData{
- Timestamp: time.Unix(0, kline.Timestamp*int64(time.Millisecond)),
- Exchange: h.Name,
- AssetType: asset.Spot,
- Pair: currency.NewPairFromFormattedPairs(data[1],
- h.GetEnabledPairs(asset.Spot), h.GetPairFormat(asset.Spot, true)),
+ var p currency.Pair
+ var a asset.Item
+ p, a, err = h.GetRequestFormattedPairAndAssetType(data[1])
+ if err != nil {
+ return err
+ }
+ h.Websocket.DataHandler <- stream.KlineData{
+ Timestamp: time.Unix(0, kline.Timestamp*int64(time.Millisecond)),
+ Exchange: h.Name,
+ AssetType: a,
+ Pair: p,
OpenPrice: kline.Tick.Open,
ClosePrice: kline.Tick.Close,
HighPrice: kline.Tick.High,
LowPrice: kline.Tick.Low,
Volume: kline.Tick.Volume,
+ Interval: data[3],
}
case strings.Contains(init.Channel, "trade.detail"):
var trade WsTrade
@@ -346,12 +350,28 @@ func (h *HUOBI) wsHandleData(respRaw []byte) error {
return err
}
data := strings.Split(trade.Channel, ".")
- h.Websocket.DataHandler <- wshandler.TradeData{
- Exchange: h.Name,
- AssetType: asset.Spot,
- CurrencyPair: currency.NewPairFromFormattedPairs(data[1],
- h.GetEnabledPairs(asset.Spot), h.GetPairFormat(asset.Spot, true)),
- Timestamp: time.Unix(0, trade.Tick.Timestamp*int64(time.Millisecond)),
+ var p currency.Pair
+ var a asset.Item
+ p, a, err = h.GetRequestFormattedPairAndAssetType(data[1])
+ if err != nil {
+ return err
+ }
+
+ for i := range trade.Tick.Data {
+ side := order.Buy
+ if trade.Tick.Data[i].Direction != "buy" {
+ side = order.Sell
+ }
+ h.Websocket.DataHandler <- stream.TradeData{
+ Exchange: h.Name,
+ AssetType: a,
+ CurrencyPair: p,
+ Timestamp: time.Unix(0,
+ trade.Tick.Data[i].Timestamp*int64(time.Millisecond)),
+ Amount: trade.Tick.Data[i].Amount,
+ Price: trade.Tick.Data[i].Price,
+ Side: side,
+ }
}
case strings.Contains(init.Channel, "detail"),
strings.Contains(init.Rep, "detail"):
@@ -367,6 +387,14 @@ func (h *HUOBI) wsHandleData(respRaw []byte) error {
if wsTicker.Rep != "" {
data = strings.Split(wsTicker.Rep, ".")
}
+
+ var p currency.Pair
+ var a asset.Item
+ p, a, err = h.GetRequestFormattedPairAndAssetType(data[1])
+ if err != nil {
+ return err
+ }
+
h.Websocket.DataHandler <- &ticker.Price{
ExchangeName: h.Name,
Open: wsTicker.Tick.Open,
@@ -376,19 +404,20 @@ func (h *HUOBI) wsHandleData(respRaw []byte) error {
High: wsTicker.Tick.High,
Low: wsTicker.Tick.Low,
LastUpdated: time.Unix(0, wsTicker.Timestamp*int64(time.Millisecond)),
- AssetType: asset.Spot,
- Pair: currency.NewPairFromFormattedPairs(data[1],
- h.GetEnabledPairs(asset.Spot), h.GetPairFormat(asset.Spot, true)),
+ AssetType: a,
+ Pair: p,
}
default:
- h.Websocket.DataHandler <- wshandler.UnhandledMessageWarning{Message: h.Name + wshandler.UnhandledMessage + string(respRaw)}
+ h.Websocket.DataHandler <- stream.UnhandledMessageWarning{
+ Message: h.Name + stream.UnhandledMessage + string(respRaw),
+ }
return nil
}
return nil
}
func (h *HUOBI) sendPingResponse(pong int64) {
- err := h.WebsocketConn.SendJSONMessage(WsPong{Pong: pong})
+ err := h.Websocket.Conn.SendJSONMessage(WsPong{Pong: pong})
if err != nil {
log.Error(log.ExchangeSys, err)
}
@@ -396,9 +425,22 @@ func (h *HUOBI) sendPingResponse(pong int64) {
// WsProcessOrderbook processes new orderbook data
func (h *HUOBI) WsProcessOrderbook(update *WsDepth, symbol string) error {
- p := currency.NewPairFromFormattedPairs(symbol,
- h.GetEnabledPairs(asset.Spot),
- h.GetPairFormat(asset.Spot, true))
+ pairs, err := h.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return err
+ }
+
+ format, err := h.GetPairFormat(asset.Spot, true)
+ if err != nil {
+ return err
+ }
+
+ p, err := currency.NewPairFromFormattedPairs(symbol,
+ pairs,
+ format)
+ if err != nil {
+ return err
+ }
var bids, asks []orderbook.Item
for i := range update.Tick.Bids {
@@ -422,59 +464,100 @@ func (h *HUOBI) WsProcessOrderbook(update *WsDepth, symbol string) error {
newOrderBook.AssetType = asset.Spot
newOrderBook.ExchangeName = h.Name
- err := h.Websocket.Orderbook.LoadSnapshot(&newOrderBook)
- if err != nil {
- return err
- }
-
- h.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
- Pair: p,
- Exchange: h.Name,
- Asset: asset.Spot,
- }
- return nil
+ return h.Websocket.Orderbook.LoadSnapshot(&newOrderBook)
}
// GenerateDefaultSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions()
-func (h *HUOBI) GenerateDefaultSubscriptions() {
- var channels = []string{wsMarketKline, wsMarketDepth, wsMarketTrade, wsMarketTicker}
- var subscriptions []wshandler.WebsocketChannelSubscription
+func (h *HUOBI) GenerateDefaultSubscriptions() ([]stream.ChannelSubscription, error) {
+ var channels = []string{wsMarketKline,
+ wsMarketDepth,
+ wsMarketTrade,
+ wsMarketTicker}
+ var subscriptions []stream.ChannelSubscription
if h.Websocket.CanUseAuthenticatedEndpoints() {
channels = append(channels, "orders.%v", "orders.%v.update")
- subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
Channel: "accounts",
})
}
- enabledCurrencies := h.GetEnabledPairs(asset.Spot)
+ enabledCurrencies, err := h.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return nil, err
+ }
for i := range channels {
for j := range enabledCurrencies {
enabledCurrencies[j].Delimiter = ""
- channel := fmt.Sprintf(channels[i], enabledCurrencies[j].Lower().String())
- subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
+ channel := fmt.Sprintf(channels[i],
+ enabledCurrencies[j].Lower().String())
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
Channel: channel,
Currency: enabledCurrencies[j],
})
}
}
- h.Websocket.SubscribeToChannels(subscriptions)
+ return subscriptions, nil
}
// Subscribe sends a websocket message to receive data from the channel
-func (h *HUOBI) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
- if strings.Contains(channelToSubscribe.Channel, "orders.") ||
- strings.Contains(channelToSubscribe.Channel, "accounts") {
- return h.wsAuthenticatedSubscribe("sub", wsAccountsOrdersEndPoint+channelToSubscribe.Channel, channelToSubscribe.Channel)
+func (h *HUOBI) Subscribe(channelsToSubscribe []stream.ChannelSubscription) error {
+ var errs common.Errors
+ for i := range channelsToSubscribe {
+ if strings.Contains(channelsToSubscribe[i].Channel, "orders.") ||
+ strings.Contains(channelsToSubscribe[i].Channel, "accounts") {
+ err := h.wsAuthenticatedSubscribe("sub",
+ wsAccountsOrdersEndPoint+channelsToSubscribe[i].Channel,
+ channelsToSubscribe[i].Channel)
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ h.Websocket.AddSuccessfulSubscriptions(channelsToSubscribe[i])
+ continue
+ }
+ err := h.Websocket.Conn.SendJSONMessage(WsRequest{
+ Subscribe: channelsToSubscribe[i].Channel,
+ })
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ h.Websocket.AddSuccessfulSubscriptions(channelsToSubscribe[i])
}
- return h.WebsocketConn.SendJSONMessage(WsRequest{Subscribe: channelToSubscribe.Channel})
+ if errs != nil {
+ return errs
+ }
+ return nil
}
// Unsubscribe sends a websocket message to stop receiving data from the channel
-func (h *HUOBI) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
- if strings.Contains(channelToSubscribe.Channel, "orders.") ||
- strings.Contains(channelToSubscribe.Channel, "accounts") {
- return h.wsAuthenticatedSubscribe("unsub", wsAccountsOrdersEndPoint+channelToSubscribe.Channel, channelToSubscribe.Channel)
+func (h *HUOBI) Unsubscribe(channelsToUnsubscribe []stream.ChannelSubscription) error {
+ var errs common.Errors
+ for i := range channelsToUnsubscribe {
+ if strings.Contains(channelsToUnsubscribe[i].Channel, "orders.") ||
+ strings.Contains(channelsToUnsubscribe[i].Channel, "accounts") {
+ err := h.wsAuthenticatedSubscribe("unsub",
+ wsAccountsOrdersEndPoint+channelsToUnsubscribe[i].Channel,
+ channelsToUnsubscribe[i].Channel)
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ h.Websocket.RemoveSuccessfulUnsubscriptions(channelsToUnsubscribe[i])
+ continue
+ }
+ err := h.Websocket.Conn.SendJSONMessage(WsRequest{
+ Unsubscribe: channelsToUnsubscribe[i].Channel,
+ })
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ h.Websocket.RemoveSuccessfulUnsubscriptions(channelsToUnsubscribe[i])
}
- return h.WebsocketConn.SendJSONMessage(WsRequest{Unsubscribe: channelToSubscribe.Channel})
+ if errs != nil {
+ return errs
+ }
+ return nil
}
func (h *HUOBI) wsGenerateSignature(timestamp, endpoint string) []byte {
@@ -504,7 +587,7 @@ func (h *HUOBI) wsLogin() error {
}
hmac := h.wsGenerateSignature(timestamp, wsAccountsOrdersEndPoint)
request.Signature = crypto.Base64Encode(hmac)
- err := h.AuthenticatedWebsocketConn.SendJSONMessage(request)
+ err := h.Websocket.AuthConn.SendJSONMessage(request)
if err != nil {
h.Websocket.SetCanUseAuthenticatedEndpoints(false)
return err
@@ -526,7 +609,7 @@ func (h *HUOBI) wsAuthenticatedSubscribe(operation, endpoint, topic string) erro
}
hmac := h.wsGenerateSignature(timestamp, endpoint)
request.Signature = crypto.Base64Encode(hmac)
- return h.AuthenticatedWebsocketConn.SendJSONMessage(request)
+ return h.Websocket.AuthConn.SendJSONMessage(request)
}
func (h *HUOBI) wsGetAccountsList() (*WsAuthenticatedAccountsListResponse, error) {
@@ -544,20 +627,34 @@ func (h *HUOBI) wsGetAccountsList() (*WsAuthenticatedAccountsListResponse, error
}
hmac := h.wsGenerateSignature(timestamp, wsAccountListEndpoint)
request.Signature = crypto.Base64Encode(hmac)
- request.ClientID = h.AuthenticatedWebsocketConn.GenerateMessageID(true)
- resp, err := h.AuthenticatedWebsocketConn.SendMessageReturnResponse(request.ClientID, request)
+ request.ClientID = h.Websocket.AuthConn.GenerateMessageID(true)
+ resp, err := h.Websocket.AuthConn.SendMessageReturnResponse(request.ClientID, request)
if err != nil {
return nil, err
}
var response WsAuthenticatedAccountsListResponse
err = json.Unmarshal(resp, &response)
- return &response, err
+ if err != nil {
+ return nil, err
+ }
+
+ code, _ := response.ErrorCode.(int)
+ if code != 0 {
+ return nil, errors.New(response.ErrorMessage)
+ }
+ return &response, nil
}
func (h *HUOBI) wsGetOrdersList(accountID int64, pair currency.Pair) (*WsAuthenticatedOrdersResponse, error) {
if !h.Websocket.CanUseAuthenticatedEndpoints() {
return nil, fmt.Errorf("%v not authenticated cannot get orders list", h.Name)
}
+
+ fpair, err := h.FormatExchangeCurrency(pair, asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+
timestamp := time.Now().UTC().Format(wsDateTimeFormatting)
request := WsAuthenticatedOrdersListRequest{
Op: requestOp,
@@ -567,19 +664,30 @@ func (h *HUOBI) wsGetOrdersList(accountID int64, pair currency.Pair) (*WsAuthent
Timestamp: timestamp,
Topic: wsOrdersList,
AccountID: accountID,
- Symbol: h.FormatExchangeCurrency(pair, asset.Spot).String(),
+ Symbol: fpair.String(),
States: "submitted,partial-filled",
}
+
hmac := h.wsGenerateSignature(timestamp, wsOrdersListEndpoint)
request.Signature = crypto.Base64Encode(hmac)
- request.ClientID = h.AuthenticatedWebsocketConn.GenerateMessageID(true)
- resp, err := h.AuthenticatedWebsocketConn.SendMessageReturnResponse(request.ClientID, request)
+ request.ClientID = h.Websocket.AuthConn.GenerateMessageID(true)
+
+ resp, err := h.Websocket.AuthConn.SendMessageReturnResponse(request.ClientID, request)
if err != nil {
return nil, err
}
+
var response WsAuthenticatedOrdersResponse
err = json.Unmarshal(resp, &response)
- return &response, err
+ if err != nil {
+ return nil, err
+ }
+
+ code, _ := response.ErrorCode.(int)
+ if code != 0 {
+ return nil, errors.New(response.ErrorMessage)
+ }
+ return &response, nil
}
func (h *HUOBI) wsGetOrderDetails(orderID string) (*WsAuthenticatedOrderDetailResponse, error) {
@@ -598,12 +706,20 @@ func (h *HUOBI) wsGetOrderDetails(orderID string) (*WsAuthenticatedOrderDetailRe
}
hmac := h.wsGenerateSignature(timestamp, wsOrdersDetailEndpoint)
request.Signature = crypto.Base64Encode(hmac)
- request.ClientID = h.AuthenticatedWebsocketConn.GenerateMessageID(true)
- resp, err := h.AuthenticatedWebsocketConn.SendMessageReturnResponse(request.ClientID, request)
+ request.ClientID = h.Websocket.AuthConn.GenerateMessageID(true)
+ resp, err := h.Websocket.AuthConn.SendMessageReturnResponse(request.ClientID, request)
if err != nil {
return nil, err
}
var response WsAuthenticatedOrderDetailResponse
err = json.Unmarshal(resp, &response)
- return &response, err
+ if err != nil {
+ return nil, err
+ }
+
+ code, _ := response.ErrorCode.(int)
+ if code != 0 {
+ return nil, errors.New(response.ErrorMessage)
+ }
+ return &response, nil
}
diff --git a/exchanges/huobi/huobi_wrapper.go b/exchanges/huobi/huobi_wrapper.go
index 7d9f2889..65a1a825 100644
--- a/exchanges/huobi/huobi_wrapper.go
+++ b/exchanges/huobi/huobi_wrapper.go
@@ -19,8 +19,8 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -56,19 +56,11 @@ func (h *HUOBI) SetDefaults() {
h.API.CredentialsValidator.RequiresKey = true
h.API.CredentialsValidator.RequiresSecret = true
- h.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- },
-
- UseGlobalFormat: true,
- RequestFormat: ¤cy.PairFormat{
- Uppercase: false,
- },
- ConfigFormat: ¤cy.PairFormat{
- Delimiter: "-",
- Uppercase: true,
- },
+ requestFmt := ¤cy.PairFormat{}
+ configFmt := ¤cy.PairFormat{Delimiter: currency.DashDelimiter, Uppercase: true}
+ err := h.SetGlobalPairsManager(requestFmt, configFmt, asset.Spot)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
}
h.Features = exchange.Features{
@@ -138,7 +130,7 @@ func (h *HUOBI) SetDefaults() {
h.API.Endpoints.URLDefault = huobiAPIURL
h.API.Endpoints.URL = h.API.Endpoints.URLDefault
h.API.Endpoints.WebsocketURL = wsMarketURL
- h.Websocket = wshandler.New()
+ h.Websocket = stream.New()
h.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
h.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
h.WebsocketOrderbookBufferLimit = exchange.DefaultWebsocketOrderbookBufferLimit
@@ -156,51 +148,41 @@ func (h *HUOBI) Setup(exch *config.ExchangeConfig) error {
return err
}
- err = h.Websocket.Setup(
- &wshandler.WebsocketSetup{
- Enabled: exch.Features.Enabled.Websocket,
- Verbose: exch.Verbose,
- AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
- WebsocketTimeout: exch.WebsocketTrafficTimeout,
- DefaultURL: wsMarketURL,
- ExchangeName: exch.Name,
- RunningURL: exch.API.Endpoints.WebsocketURL,
- Connector: h.WsConnect,
- Subscriber: h.Subscribe,
- UnSubscriber: h.Unsubscribe,
- Features: &h.Features.Supports.WebsocketCapabilities,
- })
+ err = h.Websocket.Setup(&stream.WebsocketSetup{
+ Enabled: exch.Features.Enabled.Websocket,
+ Verbose: exch.Verbose,
+ AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
+ WebsocketTimeout: exch.WebsocketTrafficTimeout,
+ DefaultURL: wsMarketURL,
+ ExchangeName: exch.Name,
+ RunningURL: exch.API.Endpoints.WebsocketURL,
+ Connector: h.WsConnect,
+ Subscriber: h.Subscribe,
+ UnSubscriber: h.Unsubscribe,
+ GenerateSubscriptions: h.GenerateDefaultSubscriptions,
+ Features: &h.Features.Supports.WebsocketCapabilities,
+ OrderbookBufferLimit: exch.WebsocketOrderbookBufferLimit,
+ })
if err != nil {
return err
}
- h.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: h.Name,
- URL: wsMarketURL,
- ProxyURL: h.Websocket.GetProxyAddress(),
- Verbose: h.Verbose,
- RateLimit: rateLimit,
- ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
- ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
- }
- h.AuthenticatedWebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: h.Name,
- URL: wsAccountsOrdersURL,
- ProxyURL: h.Websocket.GetProxyAddress(),
- Verbose: h.Verbose,
+ err = h.Websocket.SetupNewConnection(stream.ConnectionSetup{
RateLimit: rateLimit,
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
+ })
+ if err != nil {
+ return err
}
- h.Websocket.Orderbook.Setup(
- exch.WebsocketOrderbookBufferLimit,
- false,
- false,
- false,
- false,
- exch.Name)
- return nil
+ return h.Websocket.SetupNewConnection(stream.ConnectionSetup{
+ RateLimit: rateLimit,
+ ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
+ ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
+ URL: wsAccountsOrdersURL,
+ Authenticated: true,
+ })
}
// Start starts the HUOBI go routine
@@ -224,14 +206,31 @@ func (h *HUOBI) Run() {
}
var forceUpdate bool
- if common.StringDataContains(h.GetEnabledPairs(asset.Spot).Strings(), currency.CNY.String()) ||
- common.StringDataContains(h.GetAvailablePairs(asset.Spot).Strings(), currency.CNY.String()) {
+ enabled, err := h.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s Failed to update enabled currencies. Err:%s\n",
+ h.Name,
+ err)
+ }
+
+ avail, err := h.GetAvailablePairs(asset.Spot)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s Failed to update enabled currencies. Err:%s\n",
+ h.Name,
+ err)
+ }
+
+ if common.StringDataContains(enabled.Strings(), currency.CNY.String()) ||
+ common.StringDataContains(avail.Strings(), currency.CNY.String()) {
forceUpdate = true
}
if common.StringDataContains(h.BaseCurrencies.Strings(), currency.CNY.String()) {
cfg := config.GetConfig()
- exchCfg, err := cfg.GetExchangeConfig(h.Name)
+ var exchCfg *config.ExchangeConfig
+ exchCfg, err = cfg.GetExchangeConfig(h.Name)
if err != nil {
log.Errorf(log.ExchangeSys,
"%s failed to get exchange config. %s\n",
@@ -244,20 +243,31 @@ func (h *HUOBI) Run() {
}
if forceUpdate {
- enabledPairs := currency.Pairs{currency.Pair{
- Base: currency.BTC.Lower(),
- Quote: currency.USDT.Lower(),
- Delimiter: h.GetPairFormat(asset.Spot, false).Delimiter,
- },
+ var format currency.PairFormat
+ format, err = h.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to get exchange config. %s\n",
+ h.Name,
+ err)
+ return
+ }
+ enabledPairs := currency.Pairs{
+ currency.Pair{
+ Base: currency.BTC.Lower(),
+ Quote: currency.USDT.Lower(),
+ Delimiter: format.Delimiter,
+ },
}
log.Warn(log.ExchangeSys,
"Available and enabled pairs for Huobi reset due to config upgrade, please enable the ones you would like again")
- err := h.UpdatePairs(enabledPairs, asset.Spot, true, true)
+ err = h.UpdatePairs(enabledPairs, asset.Spot, true, true)
if err != nil {
log.Errorf(log.ExchangeSys,
- "%s Failed to update enabled currencies.\n",
- h.Name)
+ "%s Failed to update enabled currencies. Err:%s\n",
+ h.Name,
+ err)
}
}
@@ -265,7 +275,7 @@ func (h *HUOBI) Run() {
return
}
- err := h.UpdateTradablePairs(forceUpdate)
+ err = h.UpdateTradablePairs(forceUpdate)
if err != nil {
log.Errorf(log.ExchangeSys,
"%s failed to update tradable pairs. Err: %s",
@@ -281,13 +291,18 @@ func (h *HUOBI) FetchTradablePairs(asset asset.Item) ([]string, error) {
return nil, err
}
+ format, err := h.GetPairFormat(asset, false)
+ if err != nil {
+ return nil, err
+ }
+
var pairs []string
for x := range symbols {
if symbols[x].State != "online" {
continue
}
pairs = append(pairs, symbols[x].BaseCurrency+
- h.GetPairFormat(asset, false).Delimiter+
+ format.Delimiter+
symbols[x].QuoteCurrency)
}
@@ -302,37 +317,45 @@ func (h *HUOBI) UpdateTradablePairs(forceUpdate bool) error {
return err
}
- return h.UpdatePairs(currency.NewPairsFromStrings(pairs),
- asset.Spot,
- false,
- forceUpdate)
+ p, err := currency.NewPairsFromStrings(pairs)
+ if err != nil {
+ return err
+ }
+ return h.UpdatePairs(p, asset.Spot, false, forceUpdate)
}
// UpdateTicker updates and returns the ticker for a currency pair
func (h *HUOBI) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
- tickerPrice := new(ticker.Price)
tickers, err := h.GetTickers()
if err != nil {
- return tickerPrice, err
+ return nil, err
+ }
+ pairs, err := h.GetEnabledPairs(assetType)
+ if err != nil {
+ return nil, err
}
- pairs := h.GetEnabledPairs(assetType)
for i := range pairs {
for j := range tickers.Data {
- pairFmt := h.FormatExchangeCurrency(pairs[i], assetType).String()
- if pairFmt != tickers.Data[j].Symbol {
+ pairFmt, err := h.FormatExchangeCurrency(pairs[i], assetType)
+ if err != nil {
+ return nil, err
+ }
+
+ if pairFmt.String() != tickers.Data[j].Symbol {
continue
}
- tickerPrice := &ticker.Price{
- High: tickers.Data[j].High,
- Low: tickers.Data[j].Low,
- Volume: tickers.Data[j].Volume,
- Open: tickers.Data[j].Open,
- Close: tickers.Data[j].Close,
- Pair: pairs[i],
- }
- err = ticker.ProcessTicker(h.Name, tickerPrice, assetType)
+
+ err = ticker.ProcessTicker(&ticker.Price{
+ High: tickers.Data[j].High,
+ Low: tickers.Data[j].Low,
+ Volume: tickers.Data[j].Volume,
+ Open: tickers.Data[j].Open,
+ Close: tickers.Data[j].Close,
+ Pair: pairs[i],
+ ExchangeName: h.Name,
+ AssetType: assetType})
if err != nil {
- log.Error(log.Ticker, err)
+ return nil, err
}
}
}
@@ -360,15 +383,19 @@ func (h *HUOBI) FetchOrderbook(p currency.Pair, assetType asset.Item) (*orderboo
// UpdateOrderbook updates and returns the orderbook for a currency pair
func (h *HUOBI) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
- orderBook := new(orderbook.Base)
+ fpair, err := h.FormatExchangeCurrency(p, assetType)
+ if err != nil {
+ return nil, err
+ }
orderbookNew, err := h.GetDepth(OrderBookDataRequestParams{
- Symbol: h.FormatExchangeCurrency(p, assetType).String(),
+ Symbol: fpair.String(),
Type: OrderBookDataRequestParamsTypeStep0,
})
if err != nil {
- return orderBook, err
+ return nil, err
}
+ orderBook := new(orderbook.Base)
for x := range orderbookNew.Bids {
orderBook.Bids = append(orderBook.Bids, orderbook.Item{
Amount: orderbookNew.Bids[x][1],
@@ -533,11 +560,16 @@ func (h *HUOBI) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
return submitOrderResponse, err
}
+ p, err := h.FormatExchangeCurrency(s.Pair, s.AssetType)
+ if err != nil {
+ return submitOrderResponse, err
+ }
+
var formattedType SpotNewOrderRequestParamsType
var params = SpotNewOrderRequestParams{
Amount: s.Amount,
Source: "api",
- Symbol: h.FormatExchangeCurrency(s.Pair, s.AssetType).String(),
+ Symbol: p.String(),
AccountID: int(accountID),
}
@@ -590,10 +622,18 @@ func (h *HUOBI) CancelOrder(order *order.Cancel) error {
// CancelAllOrders cancels all orders associated with a currency pair
func (h *HUOBI) CancelAllOrders(orderCancellation *order.Cancel) (order.CancelAllResponse, error) {
var cancelAllOrdersResponse order.CancelAllResponse
- enabledPairs := h.GetEnabledPairs(asset.Spot)
+ enabledPairs, err := h.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return cancelAllOrdersResponse, err
+ }
for i := range enabledPairs {
+ fpair, err := h.FormatExchangeCurrency(enabledPairs[i], asset.Spot)
+ if err != nil {
+ return cancelAllOrdersResponse, err
+ }
+
resp, err := h.CancelOpenOrdersBatch(orderCancellation.AccountID,
- h.FormatExchangeCurrency(enabledPairs[i], asset.Spot).String())
+ fpair.String())
if err != nil {
return cancelAllOrdersResponse, err
}
@@ -683,7 +723,6 @@ func (h *HUOBI) GetOrderInfo(orderID string) (order.Detail, error) {
if err != nil {
return orderDetail, err
}
-
orderDetail = order.Detail{
Exchange: h.Name,
ID: orderID,
@@ -732,11 +771,6 @@ func (h *HUOBI) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdraw.R
return nil, common.ErrFunctionNotSupported
}
-// GetWebsocket returns a pointer to the exchange websocket
-func (h *HUOBI) GetWebsocket() (*wshandler.Websocket, error) {
- return h.Websocket, nil
-}
-
// GetFeeByType returns an estimate of fee based on type of transaction
func (h *HUOBI) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if !h.AllowAuthenticatedRequest() && // Todo check connection status
@@ -814,8 +848,13 @@ func (h *HUOBI) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, er
}
} else {
for i := range req.Pairs {
+ p, err := h.FormatExchangeCurrency(req.Pairs[i], asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+
resp, err := h.GetOpenOrders(h.API.Credentials.ClientID,
- h.FormatExchangeCurrency(req.Pairs[i], asset.Spot).String(),
+ p.String(),
side,
500)
if err != nil {
@@ -857,8 +896,13 @@ func (h *HUOBI) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, er
states := "partial-canceled,filled,canceled"
var orders []order.Detail
for i := range req.Pairs {
+ p, err := h.FormatExchangeCurrency(req.Pairs[i], asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+
resp, err := h.GetOrders(
- h.FormatExchangeCurrency(req.Pairs[i], asset.Spot).String(),
+ p.String(),
"",
"",
"",
@@ -911,25 +955,6 @@ func setOrderSideAndType(requestType string, orderDetail *order.Detail) {
}
}
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func (h *HUOBI) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- h.Websocket.SubscribeToChannels(channels)
- return nil
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func (h *HUOBI) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- h.Websocket.RemoveSubscribedChannels(channels)
- return nil
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func (h *HUOBI) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return h.Websocket.GetSubscriptions(), nil
-}
-
// AuthenticateWebsocket sends an authentication message to the websocket
func (h *HUOBI) AuthenticateWebsocket() error {
return h.wsLogin()
@@ -969,9 +994,14 @@ func (h *HUOBI) GetHistoricCandles(pair currency.Pair, a asset.Item, start, end
}
}
+ formattedPair, err := h.FormatExchangeCurrency(pair, a)
+ if err != nil {
+ return kline.Item{}, err
+ }
+
klineParams := KlinesRequestParams{
Period: h.FormatExchangeKlineInterval(interval),
- Symbol: h.FormatExchangeCurrency(pair, a).String(),
+ Symbol: formattedPair.String(),
}
candles, err := h.GetSpotKline(klineParams)
diff --git a/exchanges/interfaces.go b/exchanges/interfaces.go
index b0acce07..72afb5bb 100644
--- a/exchanges/interfaces.go
+++ b/exchanges/interfaces.go
@@ -11,8 +11,8 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -32,8 +32,8 @@ type IBotExchange interface {
UpdateOrderbook(p currency.Pair, a asset.Item) (*orderbook.Base, error)
FetchTradablePairs(a asset.Item) ([]string, error)
UpdateTradablePairs(forceUpdate bool) error
- GetEnabledPairs(a asset.Item) currency.Pairs
- GetAvailablePairs(a asset.Item) currency.Pairs
+ GetEnabledPairs(a asset.Item) (currency.Pairs, error)
+ GetAvailablePairs(a asset.Item) (currency.Pairs, error)
FetchAccountInfo() (account.Holdings, error)
UpdateAccountInfo() (account.Holdings, error)
GetAuthenticatedAPISupport(endpoint uint8) bool
@@ -62,14 +62,8 @@ type IBotExchange interface {
SetHTTPClientUserAgent(ua string)
GetHTTPClientUserAgent() string
SetClientProxyAddress(addr string) error
- SupportsWebsocket() bool
SupportsREST() bool
- IsWebsocketEnabled() bool
- GetWebsocket() (*wshandler.Websocket, error)
- SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error
- UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error
- AuthenticateWebsocket() error
- GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error)
+ GetSubscriptions() ([]stream.ChannelSubscription, error)
GetDefaultConfig() (*config.ExchangeConfig, error)
GetBase() *Base
SupportsAsset(assetType asset.Item) bool
@@ -77,4 +71,16 @@ type IBotExchange interface {
GetHistoricCandlesExtended(p currency.Pair, a asset.Item, timeStart, timeEnd time.Time, interval kline.Interval) (kline.Item, error)
DisableRateLimiter() error
EnableRateLimiter() error
+
+ // Websocket specific wrapper functionality
+ // GetWebsocket returns a pointer to the websocket
+ GetWebsocket() (*stream.Websocket, error)
+ IsWebsocketEnabled() bool
+ SupportsWebsocket() bool
+ SubscribeToWebsocketChannels(channels []stream.ChannelSubscription) error
+ UnsubscribeToWebsocketChannels(channels []stream.ChannelSubscription) error
+ // FlushWebsocketChannels checks and flushes subscriptions if there is a
+ // pair,asset, url/proxy or subscription change
+ FlushWebsocketChannels() error
+ AuthenticateWebsocket() error
}
diff --git a/exchanges/itbit/itbit_wrapper.go b/exchanges/itbit/itbit_wrapper.go
index 59a6871b..db157315 100644
--- a/exchanges/itbit/itbit_wrapper.go
+++ b/exchanges/itbit/itbit_wrapper.go
@@ -20,7 +20,6 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -56,17 +55,11 @@ func (i *ItBit) SetDefaults() {
i.API.CredentialsValidator.RequiresClientID = true
i.API.CredentialsValidator.RequiresSecret = true
- i.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- },
- UseGlobalFormat: true,
- RequestFormat: ¤cy.PairFormat{
- Uppercase: true,
- },
- ConfigFormat: ¤cy.PairFormat{
- Uppercase: true,
- },
+ requestFmt := ¤cy.PairFormat{Uppercase: true}
+ configFmt := ¤cy.PairFormat{Uppercase: true}
+ err := i.SetGlobalPairsManager(requestFmt, configFmt, asset.Spot)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
}
i.Features = exchange.Features{
@@ -110,7 +103,6 @@ func (i *ItBit) Setup(exch *config.ExchangeConfig) error {
i.SetEnabled(false)
return nil
}
-
return i.SetupDefaults(exch)
}
@@ -143,25 +135,30 @@ func (i *ItBit) UpdateTradablePairs(forceUpdate bool) error {
// UpdateTicker updates and returns the ticker for a currency pair
func (i *ItBit) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
- tickerPrice := new(ticker.Price)
- tick, err := i.GetTicker(i.FormatExchangeCurrency(p, assetType).String())
+ fpair, err := i.FormatExchangeCurrency(p, assetType)
if err != nil {
- return tickerPrice, err
+ return nil, err
}
- tickerPrice = &ticker.Price{
- Last: tick.LastPrice,
- High: tick.High24h,
- Low: tick.Low24h,
- Bid: tick.Bid,
- Ask: tick.Ask,
- Volume: tick.Volume24h,
- Open: tick.OpenToday,
- Pair: p,
- LastUpdated: tick.ServertimeUTC,
- }
- err = ticker.ProcessTicker(i.Name, tickerPrice, assetType)
+
+ tick, err := i.GetTicker(fpair.String())
if err != nil {
- return tickerPrice, err
+ return nil, err
+ }
+
+ err = ticker.ProcessTicker(&ticker.Price{
+ Last: tick.LastPrice,
+ High: tick.High24h,
+ Low: tick.Low24h,
+ Bid: tick.Bid,
+ Ask: tick.Ask,
+ Volume: tick.Volume24h,
+ Open: tick.OpenToday,
+ Pair: p,
+ LastUpdated: tick.ServertimeUTC,
+ ExchangeName: i.Name,
+ AssetType: assetType})
+ if err != nil {
+ return nil, err
}
return ticker.GetTicker(i.Name, p, assetType)
@@ -187,12 +184,17 @@ func (i *ItBit) FetchOrderbook(p currency.Pair, assetType asset.Item) (*orderboo
// UpdateOrderbook updates and returns the orderbook for a currency pair
func (i *ItBit) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
- orderBook := new(orderbook.Base)
- orderbookNew, err := i.GetOrderbook(i.FormatExchangeCurrency(p, assetType).String())
+ fpair, err := i.FormatExchangeCurrency(p, assetType)
if err != nil {
- return orderBook, err
+ return nil, err
}
+ orderbookNew, err := i.GetOrderbook(fpair.String())
+ if err != nil {
+ return nil, err
+ }
+
+ orderBook := new(orderbook.Base)
for x := range orderbookNew.Bids {
var price, amount float64
price, err = strconv.ParseFloat(orderbookNew.Bids[x][0], 64)
@@ -424,11 +426,6 @@ func (i *ItBit) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdraw.R
return nil, common.ErrFunctionNotSupported
}
-// GetWebsocket returns a pointer to the exchange websocket
-func (i *ItBit) GetWebsocket() (*wshandler.Websocket, error) {
- return nil, common.ErrFunctionNotSupported
-}
-
// GetFeeByType returns an estimate of fee based on type of transaction
func (i *ItBit) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if !i.AllowAuthenticatedRequest() && // Todo check connection status
@@ -447,17 +444,27 @@ func (i *ItBit) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, er
var allOrders []Order
for x := range wallets {
- resp, err := i.GetOrders(wallets[x].ID, "", "open", 0, 0)
+ var resp []Order
+ resp, err = i.GetOrders(wallets[x].ID, "", "open", 0, 0)
if err != nil {
return nil, err
}
allOrders = append(allOrders, resp...)
}
+ format, err := i.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return nil, err
+ }
+
var orders []order.Detail
for j := range allOrders {
- symbol := currency.NewPairDelimiter(allOrders[j].Instrument,
- i.GetPairFormat(asset.Spot, false).Delimiter)
+ var symbol currency.Pair
+ symbol, err := currency.NewPairDelimiter(allOrders[j].Instrument,
+ format.Delimiter)
+ if err != nil {
+ return nil, err
+ }
side := order.Side(strings.ToUpper(allOrders[j].Side))
orderDate, err := time.Parse(time.RFC3339, allOrders[j].CreatedTime)
if err != nil {
@@ -497,21 +504,31 @@ func (i *ItBit) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, er
var allOrders []Order
for x := range wallets {
- resp, err := i.GetOrders(wallets[x].ID, "", "", 0, 0)
+ var resp []Order
+ resp, err = i.GetOrders(wallets[x].ID, "", "", 0, 0)
if err != nil {
return nil, err
}
allOrders = append(allOrders, resp...)
}
+ format, err := i.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return nil, err
+ }
+
var orders []order.Detail
for j := range allOrders {
if allOrders[j].Type == "open" {
continue
}
+ var symbol currency.Pair
+ symbol, err = currency.NewPairDelimiter(allOrders[j].Instrument,
+ format.Delimiter)
+ if err != nil {
+ return nil, err
+ }
- symbol := currency.NewPairDelimiter(allOrders[j].Instrument,
- i.GetPairFormat(asset.Spot, false).Delimiter)
side := order.Side(strings.ToUpper(allOrders[j].Side))
orderDate, err := time.Parse(time.RFC3339, allOrders[j].CreatedTime)
if err != nil {
@@ -541,28 +558,6 @@ func (i *ItBit) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, er
return orders, nil
}
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func (i *ItBit) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- return common.ErrFunctionNotSupported
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func (i *ItBit) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- return common.ErrFunctionNotSupported
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func (i *ItBit) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return nil, common.ErrFunctionNotSupported
-}
-
-// AuthenticateWebsocket sends an authentication message to the websocket
-func (i *ItBit) AuthenticateWebsocket() error {
- return common.ErrFunctionNotSupported
-}
-
// ValidateCredentials validates current credentials used for wrapper
// functionality
func (i *ItBit) ValidateCredentials() error {
diff --git a/exchanges/kraken/kraken.go b/exchanges/kraken/kraken.go
index 1398b141..af51ebb0 100644
--- a/exchanges/kraken/kraken.go
+++ b/exchanges/kraken/kraken.go
@@ -16,7 +16,6 @@ import (
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
)
@@ -64,9 +63,7 @@ var (
// Kraken is the overarching type across the alphapoint package
type Kraken struct {
exchange.Base
- WebsocketConn *wshandler.WebsocketConnection
- AuthenticatedWebsocketConn *wshandler.WebsocketConnection
- wsRequestMtx sync.Mutex
+ wsRequestMtx sync.Mutex
}
// GetServerTime returns current server time
diff --git a/exchanges/kraken/kraken_test.go b/exchanges/kraken/kraken_test.go
index 02ef59f1..9ae3ca07 100644
--- a/exchanges/kraken/kraken_test.go
+++ b/exchanges/kraken/kraken_test.go
@@ -18,7 +18,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -48,12 +48,11 @@ func TestMain(m *testing.M) {
krakenConfig.API.Credentials.Key = apiKey
krakenConfig.API.Credentials.Secret = apiSecret
krakenConfig.API.Endpoints.WebsocketURL = k.API.Endpoints.WebsocketURL
+ k.Websocket = sharedtestvalues.NewTestWebsocket()
err = k.Setup(krakenConfig)
if err != nil {
log.Fatal(err)
}
- k.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- k.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
os.Exit(m.Run())
}
@@ -697,31 +696,14 @@ func setupWsTests(t *testing.T) {
return
}
if !k.Websocket.IsEnabled() && !k.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
- t.Skip(wshandler.WebsocketNotEnabled)
- }
- k.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- comms = make(chan wshandler.WebsocketResponse, sharedtestvalues.WebsocketChannelOverrideCapacity)
- k.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
- k.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: k.Name,
- URL: krakenWSURL,
- Verbose: k.Verbose,
- ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
- ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
- }
- k.AuthenticatedWebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: k.Name,
- URL: krakenAuthWSURL,
- Verbose: k.Verbose,
- ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
- ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
+ t.Skip(stream.WebsocketNotEnabled)
}
var dialer websocket.Dialer
- err := k.WebsocketConn.Dial(&dialer, http.Header{})
+ err := k.Websocket.Conn.Dial(&dialer, http.Header{})
if err != nil {
t.Fatal(err)
}
- err = k.AuthenticatedWebsocketConn.Dial(&dialer, http.Header{})
+ err = k.Websocket.AuthConn.Dial(&dialer, http.Header{})
if err != nil {
t.Fatal(err)
}
@@ -731,10 +713,10 @@ func setupWsTests(t *testing.T) {
t.Error(err)
}
authToken = token
-
- go k.wsFunnelConnectionData(k.WebsocketConn)
- go k.wsFunnelConnectionData(k.AuthenticatedWebsocketConn)
- go k.wsReadData()
+ comms := make(chan stream.Response)
+ go k.wsFunnelConnectionData(k.Websocket.Conn, comms)
+ go k.wsFunnelConnectionData(k.Websocket.AuthConn, comms)
+ go k.wsReadData(comms)
go k.wsPingHandler()
wsSetupRan = true
}
@@ -742,9 +724,11 @@ func setupWsTests(t *testing.T) {
// TestWebsocketSubscribe tests returning a message with an id
func TestWebsocketSubscribe(t *testing.T) {
setupWsTests(t)
- err := k.Subscribe(wshandler.WebsocketChannelSubscription{
- Channel: defaultSubscribedChannels[0],
- Currency: currency.NewPairWithDelimiter("XBT", "USD", "/"),
+ err := k.Subscribe([]stream.ChannelSubscription{
+ {
+ Channel: defaultSubscribedChannels[0],
+ Currency: currency.NewPairWithDelimiter("XBT", "USD", "/"),
+ },
})
if err != nil {
t.Error(err)
@@ -1426,8 +1410,11 @@ func TestParseTime(t *testing.T) {
}
func TestGetHistoricCandles(t *testing.T) {
- currencyPair := currency.NewPairFromString("XBTUSD")
- _, err := k.GetHistoricCandles(currencyPair, asset.Spot, time.Now().AddDate(0, 0, -1), time.Now(), kline.OneMin)
+ currencyPair, err := currency.NewPairFromString("XBTUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = k.GetHistoricCandles(currencyPair, asset.Spot, time.Now().AddDate(0, 0, -1), time.Now(), kline.OneMin)
if err != nil {
t.Fatal(err)
}
@@ -1439,8 +1426,11 @@ func TestGetHistoricCandles(t *testing.T) {
}
func TestGetHistoricCandlesExtended(t *testing.T) {
- currencyPair := currency.NewPairFromString("XBTUSD")
- _, err := k.GetHistoricCandlesExtended(currencyPair, asset.Spot, time.Now().AddDate(0, -6, 0), time.Now(), kline.OneDay)
+ currencyPair, err := currency.NewPairFromString("XBTUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = k.GetHistoricCandlesExtended(currencyPair, asset.Spot, time.Now().AddDate(0, -6, 0), time.Now(), kline.OneDay)
if err != nil {
t.Fatal(err)
}
diff --git a/exchanges/kraken/kraken_types.go b/exchanges/kraken/kraken_types.go
index 2077ce82..d9e7aafd 100644
--- a/exchanges/kraken/kraken_types.go
+++ b/exchanges/kraken/kraken_types.go
@@ -5,6 +5,7 @@ import (
"time"
"github.com/thrasher-corp/gocryptotrader/currency"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
)
type assetTranslatorStore struct {
@@ -400,10 +401,11 @@ type WithdrawStatusResponse struct {
// WebsocketSubscriptionEventRequest handles WS subscription events
type WebsocketSubscriptionEventRequest struct {
- Event string `json:"event"` // subscribe
- RequestID int64 `json:"reqid,omitempty"` // Optional, client originated ID reflected in response message.
- Pairs []string `json:"pair,omitempty"` // Array of currency pairs (pair1,pair2,pair3).
- Subscription WebsocketSubscriptionData `json:"subscription,omitempty"`
+ Event string `json:"event"` // subscribe
+ RequestID int64 `json:"reqid,omitempty"` // Optional, client originated ID reflected in response message.
+ Pairs []string `json:"pair,omitempty"` // Array of currency pairs (pair1,pair2,pair3).
+ Subscription WebsocketSubscriptionData `json:"subscription,omitempty"`
+ Channels []stream.ChannelSubscription `json:"-"` // Keeps track of associated subscriptions in batched outgoings
}
// WebsocketBaseEventRequest Just has an "event" property
diff --git a/exchanges/kraken/kraken_websocket.go b/exchanges/kraken/kraken_websocket.go
index 4db9b84b..7031181b 100644
--- a/exchanges/kraken/kraken_websocket.go
+++ b/exchanges/kraken/kraken_websocket.go
@@ -10,15 +10,16 @@ import (
"time"
"github.com/gorilla/websocket"
+ "github.com/thrasher-corp/gocryptotrader/common"
"github.com/thrasher-corp/gocryptotrader/common/convert"
"github.com/thrasher-corp/gocryptotrader/currency"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wsorderbook"
"github.com/thrasher-corp/gocryptotrader/log"
)
@@ -49,89 +50,110 @@ const (
krakenWsPingDelay = time.Second * 27
)
-// orderbookMutex Ensures if two entries arrive at once, only one can be processed at a time
+// orderbookMutex Ensures if two entries arrive at once, only one can be
+// processed at a time
var subscriptionChannelPair []WebsocketChannelData
-var comms = make(chan wshandler.WebsocketResponse)
var authToken string
-var pingRequest = WebsocketBaseEventRequest{Event: wshandler.Ping}
+var pingRequest = WebsocketBaseEventRequest{Event: stream.Ping}
// Channels require a topic and a currency
// Format [[ticker,but-t4u],[orderbook,nce-btt]]
-var defaultSubscribedChannels = []string{krakenWsTicker, krakenWsTrade, krakenWsOrderbook, krakenWsOHLC, krakenWsSpread}
+var defaultSubscribedChannels = []string{krakenWsTicker,
+ krakenWsTrade,
+ krakenWsOrderbook,
+ krakenWsOHLC,
+ krakenWsSpread}
var authenticatedChannels = []string{krakenWsOwnTrades, krakenWsOpenOrders}
// WsConnect initiates a websocket connection
func (k *Kraken) WsConnect() error {
if !k.Websocket.IsEnabled() || !k.IsEnabled() {
- return errors.New(wshandler.WebsocketNotEnabled)
+ return errors.New(stream.WebsocketNotEnabled)
}
+
var dialer websocket.Dialer
- err := k.WebsocketConn.Dial(&dialer, http.Header{})
+ err := k.Websocket.Conn.Dial(&dialer, http.Header{})
if err != nil {
return err
}
+
+ comms := make(chan stream.Response)
+ go k.wsReadData(comms)
+ go k.wsFunnelConnectionData(k.Websocket.Conn, comms)
+
if k.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
authToken, err = k.GetWebsocketToken()
if err != nil {
k.Websocket.SetCanUseAuthenticatedEndpoints(false)
- log.Errorf(log.ExchangeSys, "%v - authentication failed: %v\n", k.Name, err)
+ log.Errorf(log.ExchangeSys,
+ "%v - authentication failed: %v\n",
+ k.Name,
+ err)
+ } else {
+ err = k.Websocket.AuthConn.Dial(&dialer, http.Header{})
+ if err != nil {
+ k.Websocket.SetCanUseAuthenticatedEndpoints(false)
+ log.Errorf(log.ExchangeSys,
+ "%v - failed to connect to authenticated endpoint: %v\n",
+ k.Name,
+ err)
+ } else {
+ go k.wsFunnelConnectionData(k.Websocket.AuthConn, comms)
+ var authsubs []stream.ChannelSubscription
+ authsubs, err = k.GenerateAuthenticatedSubscriptions()
+ if err != nil {
+ return err
+ }
+ err = k.Websocket.SubscribeToChannels(authsubs)
+ if err != nil {
+ return err
+ }
+ }
}
- err = k.AuthenticatedWebsocketConn.Dial(&dialer, http.Header{})
- if err != nil {
- k.Websocket.SetCanUseAuthenticatedEndpoints(false)
- log.Errorf(log.ExchangeSys, "%v - failed to connect to authenticated endpoint: %v\n", k.Name, err)
- }
- go k.wsFunnelConnectionData(k.AuthenticatedWebsocketConn)
- k.GenerateAuthenticatedSubscriptions()
}
- go k.wsFunnelConnectionData(k.WebsocketConn)
- go k.wsReadData()
err = k.wsPingHandler()
if err != nil {
- log.Errorf(log.ExchangeSys, "%v - failed setup ping handler. Websocket may disconnect unexpectedly. %v\n", k.Name, err)
+ log.Errorf(log.ExchangeSys,
+ "%v - failed setup ping handler. Websocket may disconnect unexpectedly. %v\n",
+ k.Name,
+ err)
}
- k.GenerateDefaultSubscriptions()
-
- return nil
+ gensubs, err := k.GenerateDefaultSubscriptions()
+ if err != nil {
+ return err
+ }
+ return k.Websocket.SubscribeToChannels(gensubs)
}
// wsFunnelConnectionData funnels both auth and public ws data into one manageable place
-func (k *Kraken) wsFunnelConnectionData(ws *wshandler.WebsocketConnection) {
+func (k *Kraken) wsFunnelConnectionData(ws stream.Connection, comms chan stream.Response) {
k.Websocket.Wg.Add(1)
defer k.Websocket.Wg.Done()
for {
- select {
- case <-k.Websocket.ShutdownC:
+ resp := ws.ReadMessage()
+ if resp.Raw == nil {
return
- default:
- resp, err := ws.ReadMessage()
- if err != nil {
- k.Websocket.DataHandler <- err
- return
- }
- k.Websocket.TrafficAlert <- struct{}{}
- comms <- resp
}
+ comms <- resp
}
}
// wsReadData receives and passes on websocket messages for processing
-func (k *Kraken) wsReadData() {
+func (k *Kraken) wsReadData(comms chan stream.Response) {
k.Websocket.Wg.Add(1)
- defer func() {
- k.Websocket.Wg.Done()
- }()
+ defer k.Websocket.Wg.Done()
for {
select {
case <-k.Websocket.ShutdownC:
return
- default:
- resp := <-comms
+ case resp := <-comms:
err := k.wsHandleData(resp.Raw)
if err != nil {
- k.Websocket.DataHandler <- fmt.Errorf("%s - unhandled websocket data: %v", k.Name, err)
+ k.Websocket.DataHandler <- fmt.Errorf("%s - unhandled websocket data: %v",
+ k.Name,
+ err)
}
}
}
@@ -160,34 +182,49 @@ func (k *Kraken) wsHandleData(respRaw []byte) error {
var eventResponse map[string]interface{}
err := json.Unmarshal(respRaw, &eventResponse)
if err != nil {
- return fmt.Errorf("%s - err %s could not parse websocket data: %s", k.Name, err, respRaw)
+ return fmt.Errorf("%s - err %s could not parse websocket data: %s",
+ k.Name,
+ err,
+ respRaw)
}
if event, ok := eventResponse["event"]; ok {
switch event {
- case wshandler.Pong, krakenWsHeartbeat, krakenWsCancelOrderStatus:
+ case stream.Pong, krakenWsHeartbeat, krakenWsCancelOrderStatus:
return nil
case krakenWsSystemStatus:
var systemStatus wsSystemStatus
err := json.Unmarshal(respRaw, &systemStatus)
if err != nil {
- return fmt.Errorf("%s - err %s unable to parse system status response: %s", k.Name, err, respRaw)
+ return fmt.Errorf("%s - err %s unable to parse system status response: %s",
+ k.Name,
+ err,
+ respRaw)
}
if systemStatus.Status != "online" {
k.Websocket.DataHandler <- fmt.Errorf("%v Websocket status '%v'",
- k.Name, systemStatus.Status)
+ k.Name,
+ systemStatus.Status)
}
if systemStatus.Version > krakenWSSupportedVersion {
- log.Warnf(log.ExchangeSys, "%v New version of Websocket API released. Was %v Now %v",
- k.Name, krakenWSSupportedVersion, systemStatus.Version)
+ log.Warnf(log.ExchangeSys,
+ "%v New version of Websocket API released. Was %v Now %v",
+ k.Name,
+ krakenWSSupportedVersion,
+ systemStatus.Version)
}
case krakenWsAddOrderStatus:
var status WsAddOrderResponse
err := json.Unmarshal(respRaw, &status)
if err != nil {
- return fmt.Errorf("%s - err %s unable to parse add order response: %s", k.Name, err, respRaw)
+ return fmt.Errorf("%s - err %s unable to parse add order response: %s",
+ k.Name,
+ err,
+ respRaw)
}
if status.ErrorMessage != "" {
- return fmt.Errorf("%s - err %s", k.Name, status.ErrorMessage)
+ return fmt.Errorf("%s - err %s",
+ k.Name,
+ status.ErrorMessage)
}
k.Websocket.DataHandler <- &order.Detail{
Exchange: k.Name,
@@ -198,20 +235,27 @@ func (k *Kraken) wsHandleData(respRaw []byte) error {
var sub wsSubscription
err := json.Unmarshal(respRaw, &sub)
if err != nil {
- return fmt.Errorf("%s - err %s unable to parse subscription response: %s", k.Name, err, respRaw)
+ return fmt.Errorf("%s - err %s unable to parse subscription response: %s",
+ k.Name,
+ err,
+ respRaw)
}
if sub.Status != "subscribed" && sub.Status != "unsubscribed" {
- return fmt.Errorf("%v %v %v", k.Name, sub.RequestID, sub.ErrorMessage)
+ return fmt.Errorf("%v %v %v",
+ k.Name,
+ sub.RequestID,
+ sub.ErrorMessage)
}
k.addNewSubscriptionChannelData(&sub)
if sub.RequestID > 0 {
- if k.WebsocketConn.IsIDWaitingForResponse(sub.RequestID) {
- k.WebsocketConn.SetResponseIDAndData(sub.RequestID, respRaw)
+ if k.Websocket.Match.IncomingWithData(sub.RequestID, respRaw) {
return nil
}
}
default:
- k.Websocket.DataHandler <- wshandler.UnhandledMessageWarning{Message: k.Name + wshandler.UnhandledMessage + string(respRaw)}
+ k.Websocket.DataHandler <- stream.UnhandledMessageWarning{
+ Message: k.Name + stream.UnhandledMessage + string(respRaw),
+ }
}
return nil
}
@@ -225,7 +269,7 @@ func (k *Kraken) wsPingHandler() error {
if err != nil {
return err
}
- k.WebsocketConn.SetupPingHandler(wshandler.WebsocketPingHandler{
+ k.Websocket.Conn.SetupPingHandler(stream.PingHandler{
Message: message,
Delay: krakenWsPingDelay,
MessageType: websocket.TextMessage,
@@ -366,7 +410,16 @@ func (k *Kraken) wsProcessOpenOrders(ownOrders interface{}) error {
Err: err,
}
}
- p := currency.NewPairFromString(val.Description.Pair)
+
+ p, err := currency.NewPairFromString(val.Description.Pair)
+ if err != nil {
+ k.Websocket.DataHandler <- order.ClassificationError{
+ Exchange: k.Name,
+ OrderID: key,
+ Err: err,
+ }
+ }
+
var a asset.Item
a, err = k.GetPairAssetType(p)
if err != nil {
@@ -409,7 +462,12 @@ func (k *Kraken) addNewSubscriptionChannelData(response *wsSubscription) {
// We change the / to - to maintain compatibility with REST/config
var pair currency.Pair
if response.Pair != "" {
- pair = currency.NewPairFromString(response.Pair)
+ var err error
+ pair, err = currency.NewPairFromString(response.Pair)
+ if err != nil {
+ log.Errorf(log.ExchangeSys, "%s exchange error: %s", k.Name, err)
+ return
+ }
pair.Delimiter = k.CurrencyPairs.RequestFormat.Delimiter
}
subscriptionChannelPair = append(subscriptionChannelPair, WebsocketChannelData{
@@ -525,7 +583,13 @@ func (k *Kraken) wsProcessTrades(channelData *WebsocketChannelData, data []inter
if trade[3].(string) == "s" {
tSide = order.Sell
}
- k.Websocket.DataHandler <- wshandler.TradeData{
+
+ var tType = order.Market
+ if trade[4].(string) == "l" {
+ tType = order.Limit
+ }
+
+ k.Websocket.DataHandler <- stream.TradeData{
AssetType: asset.Spot,
CurrencyPair: channelData.Pair,
Exchange: k.Name,
@@ -533,6 +597,7 @@ func (k *Kraken) wsProcessTrades(channelData *WebsocketChannelData, data []inter
Amount: amount,
Timestamp: convert.TimeFromUnixTimestampDecimal(timeData),
Side: tSide,
+ EventType: tType,
}
}
}
@@ -554,9 +619,10 @@ func (k *Kraken) wsProcessOrderBook(channelData *WebsocketChannelData, data map[
defer k.wsRequestMtx.Unlock()
err := k.wsProcessOrderBookUpdate(channelData, askData, bidData)
if err != nil {
- subscriptionToRemove := wshandler.WebsocketChannelSubscription{
+ subscriptionToRemove := &stream.ChannelSubscription{
Channel: krakenWsOrderbook,
Currency: channelData.Pair,
+ Asset: asset.Spot,
}
k.Websocket.ResubscribeToChannel(subscriptionToRemove)
return err
@@ -625,21 +691,12 @@ func (k *Kraken) wsProcessOrderBookPartial(channelData *WebsocketChannelData, as
}
base.LastUpdated = highestLastUpdate
base.ExchangeName = k.Name
- err := k.Websocket.Orderbook.LoadSnapshot(&base)
- if err != nil {
- return err
- }
- k.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
- Exchange: k.Name,
- Asset: asset.Spot,
- Pair: channelData.Pair,
- }
- return nil
+ return k.Websocket.Orderbook.LoadSnapshot(&base)
}
// wsProcessOrderBookUpdate updates an orderbook entry for a given currency pair
func (k *Kraken) wsProcessOrderBookUpdate(channelData *WebsocketChannelData, askData, bidData []interface{}) error {
- update := wsorderbook.WebsocketOrderbookUpdate{
+ update := buffer.Update{
Asset: asset.Spot,
Pair: channelData.Pair,
}
@@ -701,17 +758,7 @@ func (k *Kraken) wsProcessOrderBookUpdate(channelData *WebsocketChannelData, ask
}
}
update.UpdateTime = highestLastUpdate
- err := k.Websocket.Orderbook.Update(&update)
- if err != nil {
- k.Websocket.DataHandler <- err
- return err
- }
- k.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
- Exchange: k.Name,
- Asset: asset.Spot,
- Pair: channelData.Pair,
- }
- return nil
+ return k.Websocket.Orderbook.Update(&update)
}
// wsProcessCandles converts candle data and sends it to the data handler
@@ -751,7 +798,7 @@ func (k *Kraken) wsProcessCandles(channelData *WebsocketChannelData, data []inte
return err
}
- k.Websocket.DataHandler <- wshandler.KlineData{
+ k.Websocket.DataHandler <- stream.KlineData{
AssetType: asset.Spot,
Pair: channelData.Pair,
Timestamp: time.Now(),
@@ -770,78 +817,177 @@ func (k *Kraken) wsProcessCandles(channelData *WebsocketChannelData, data []inte
}
// GenerateDefaultSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions()
-func (k *Kraken) GenerateDefaultSubscriptions() {
- enabledCurrencies := k.GetEnabledPairs(asset.Spot)
- var subscriptions []wshandler.WebsocketChannelSubscription
+func (k *Kraken) GenerateDefaultSubscriptions() ([]stream.ChannelSubscription, error) {
+ enabledCurrencies, err := k.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+ var subscriptions []stream.ChannelSubscription
for i := range defaultSubscribedChannels {
for j := range enabledCurrencies {
enabledCurrencies[j].Delimiter = "/"
- subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
Channel: defaultSubscribedChannels[i],
Currency: enabledCurrencies[j],
+ Asset: asset.Spot,
})
}
}
- k.Websocket.SubscribeToChannels(subscriptions)
+ return subscriptions, nil
}
// GenerateAuthenticatedSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions()
-func (k *Kraken) GenerateAuthenticatedSubscriptions() {
- var subscriptions []wshandler.WebsocketChannelSubscription
+func (k *Kraken) GenerateAuthenticatedSubscriptions() ([]stream.ChannelSubscription, error) {
+ var subscriptions []stream.ChannelSubscription
for i := range authenticatedChannels {
params := make(map[string]interface{})
- subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
Channel: authenticatedChannels[i],
Params: params,
})
}
- k.Websocket.SubscribeToChannels(subscriptions)
+ return subscriptions, nil
}
// Subscribe sends a websocket message to receive data from the channel
-func (k *Kraken) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
- resp := WebsocketSubscriptionEventRequest{
- Event: krakenWsSubscribe,
- Subscription: WebsocketSubscriptionData{
- Name: channelToSubscribe.Channel,
- },
- RequestID: k.WebsocketConn.GenerateMessageID(false),
- }
- if channelToSubscribe.Channel == "book" {
- // TODO: Add ability to make depth customisable
- resp.Subscription.Depth = 1000
- }
- if !channelToSubscribe.Currency.IsEmpty() {
- resp.Pairs = []string{channelToSubscribe.Currency.String()}
- }
- if channelToSubscribe.Params != nil {
- resp.Subscription.Token = authToken
+func (k *Kraken) Subscribe(channelsToSubscribe []stream.ChannelSubscription) error {
+ var subs []WebsocketSubscriptionEventRequest
+channels:
+ for x := range channelsToSubscribe {
+ for y := range subs {
+ if subs[y].Subscription.Name == channelsToSubscribe[x].Channel {
+ subs[y].Pairs = append(subs[y].Pairs,
+ channelsToSubscribe[x].Currency.String())
+ subs[y].Channels = append(subs[y].Channels, channelsToSubscribe[x])
+ continue channels
+ }
+ }
+
+ var id int64
+ if common.StringDataContains(authenticatedChannels, channelsToSubscribe[x].Channel) {
+ id = k.Websocket.AuthConn.GenerateMessageID(false)
+ } else {
+ id = k.Websocket.Conn.GenerateMessageID(false)
+ }
+
+ resp := WebsocketSubscriptionEventRequest{
+ Event: krakenWsSubscribe,
+ Subscription: WebsocketSubscriptionData{
+ Name: channelsToSubscribe[x].Channel,
+ },
+ RequestID: id,
+ }
+ if channelsToSubscribe[x].Channel == "book" {
+ // TODO: Add ability to make depth customisable
+ resp.Subscription.Depth = 1000
+ }
+ if !channelsToSubscribe[x].Currency.IsEmpty() {
+ resp.Pairs = []string{channelsToSubscribe[x].Currency.String()}
+ }
+ if channelsToSubscribe[x].Params != nil {
+ resp.Subscription.Token = authToken
+ }
+
+ resp.Channels = append(resp.Channels, channelsToSubscribe[x])
+ subs = append(subs, resp)
}
- _, err := k.WebsocketConn.SendMessageReturnResponse(resp.RequestID, resp)
- return err
+ var errs common.Errors
+ for i := range subs {
+ if common.StringDataContains(authenticatedChannels, subs[i].Subscription.Name) {
+ _, err := k.Websocket.AuthConn.SendMessageReturnResponse(subs[i].RequestID, subs[i])
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ k.Websocket.AddSuccessfulSubscriptions(subs[i].Channels...)
+ continue
+ }
+
+ _, err := k.Websocket.Conn.SendMessageReturnResponse(subs[i].RequestID, subs[i])
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ k.Websocket.AddSuccessfulSubscriptions(subs[i].Channels...)
+ }
+ if errs != nil {
+ return errs
+ }
+ return nil
}
// Unsubscribe sends a websocket message to stop receiving data from the channel
-func (k *Kraken) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
- resp := WebsocketSubscriptionEventRequest{
- Event: krakenWsUnsubscribe,
- Pairs: []string{channelToSubscribe.Currency.String()},
- Subscription: WebsocketSubscriptionData{
- Name: channelToSubscribe.Channel,
- },
- RequestID: k.WebsocketConn.GenerateMessageID(false),
+func (k *Kraken) Unsubscribe(channelsToUnsubscribe []stream.ChannelSubscription) error {
+ var unsubs []WebsocketSubscriptionEventRequest
+channels:
+ for x := range channelsToUnsubscribe {
+ for y := range unsubs {
+ if unsubs[y].Subscription.Name == channelsToUnsubscribe[x].Channel {
+ unsubs[y].Pairs = append(unsubs[y].Pairs,
+ channelsToUnsubscribe[x].Currency.String())
+ unsubs[y].Channels = append(unsubs[y].Channels,
+ channelsToUnsubscribe[x])
+ continue channels
+ }
+ }
+ var depth int64
+ if channelsToUnsubscribe[x].Channel == "book" {
+ // TODO: Add ability to make depth customisable
+ depth = 1000
+ }
+
+ var id int64
+ if common.StringDataContains(authenticatedChannels, channelsToUnsubscribe[x].Channel) {
+ id = k.Websocket.AuthConn.GenerateMessageID(false)
+ } else {
+ id = k.Websocket.Conn.GenerateMessageID(false)
+ }
+
+ unsub := WebsocketSubscriptionEventRequest{
+ Event: krakenWsUnsubscribe,
+ Pairs: []string{channelsToUnsubscribe[x].Currency.String()},
+ Subscription: WebsocketSubscriptionData{
+ Name: channelsToUnsubscribe[x].Channel,
+ Depth: depth,
+ },
+ RequestID: id,
+ }
+ unsub.Channels = append(unsub.Channels, channelsToUnsubscribe[x])
+ unsubs = append(unsubs, unsub)
}
- _, err := k.WebsocketConn.SendMessageReturnResponse(resp.RequestID, resp)
- return err
+
+ var errs common.Errors
+ for i := range unsubs {
+ if common.StringDataContains(authenticatedChannels, unsubs[i].Subscription.Name) {
+ _, err := k.Websocket.AuthConn.SendMessageReturnResponse(unsubs[i].RequestID, unsubs[i])
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ k.Websocket.RemoveSuccessfulUnsubscriptions(unsubs[i].Channels...)
+ continue
+ }
+
+ _, err := k.Websocket.Conn.SendMessageReturnResponse(unsubs[i].RequestID, unsubs[i])
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ k.Websocket.RemoveSuccessfulUnsubscriptions(unsubs[i].Channels...)
+ }
+ if errs != nil {
+ return errs
+ }
+ return nil
}
func (k *Kraken) wsAddOrder(request *WsAddOrderRequest) (string, error) {
- id := k.AuthenticatedWebsocketConn.GenerateMessageID(false)
+ id := k.Websocket.AuthConn.GenerateMessageID(false)
request.UserReferenceID = strconv.FormatInt(id, 10)
request.Event = krakenWsAddOrder
request.Token = authToken
- jsonResp, err := k.AuthenticatedWebsocketConn.SendMessageReturnResponse(id, request)
+ jsonResp, err := k.Websocket.AuthConn.SendMessageReturnResponse(id, request)
if err != nil {
return "", err
}
@@ -862,5 +1008,5 @@ func (k *Kraken) wsCancelOrders(orderIDs []string) error {
Token: authToken,
TransactionIDs: orderIDs,
}
- return k.AuthenticatedWebsocketConn.SendJSONMessage(request)
+ return k.Websocket.AuthConn.SendJSONMessage(request)
}
diff --git a/exchanges/kraken/kraken_wrapper.go b/exchanges/kraken/kraken_wrapper.go
index 1e39c9e4..c55af9fc 100644
--- a/exchanges/kraken/kraken_wrapper.go
+++ b/exchanges/kraken/kraken_wrapper.go
@@ -19,8 +19,8 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -57,21 +57,18 @@ func (k *Kraken) SetDefaults() {
k.API.CredentialsValidator.RequiresSecret = true
k.API.CredentialsValidator.RequiresBase64DecodeSecret = true
- k.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- },
-
- UseGlobalFormat: true,
- RequestFormat: ¤cy.PairFormat{
- Uppercase: true,
- Separator: ",",
- },
- ConfigFormat: ¤cy.PairFormat{
- Uppercase: true,
- Delimiter: "-",
- Separator: ",",
- },
+ requestFmt := ¤cy.PairFormat{
+ Uppercase: true,
+ Separator: ",",
+ }
+ configFmt := ¤cy.PairFormat{
+ Uppercase: true,
+ Delimiter: currency.DashDelimiter,
+ Separator: ",",
+ }
+ err := k.SetGlobalPairsManager(requestFmt, configFmt, asset.Spot)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
}
k.Features = exchange.Features{
@@ -149,7 +146,7 @@ func (k *Kraken) SetDefaults() {
k.API.Endpoints.URLDefault = krakenAPIURL
k.API.Endpoints.URL = k.API.Endpoints.URLDefault
- k.Websocket = wshandler.New()
+ k.Websocket = stream.New()
k.API.Endpoints.WebsocketURL = krakenWSURL
k.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
k.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
@@ -173,52 +170,44 @@ func (k *Kraken) Setup(exch *config.ExchangeConfig) error {
return err
}
- err = k.Websocket.Setup(
- &wshandler.WebsocketSetup{
- Enabled: exch.Features.Enabled.Websocket,
- Verbose: exch.Verbose,
- AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
- WebsocketTimeout: exch.WebsocketTrafficTimeout,
- DefaultURL: krakenWSURL,
- ExchangeName: exch.Name,
- RunningURL: exch.API.Endpoints.WebsocketURL,
- Connector: k.WsConnect,
- Subscriber: k.Subscribe,
- UnSubscriber: k.Unsubscribe,
- Features: &k.Features.Supports.WebsocketCapabilities,
- })
+ err = k.Websocket.Setup(&stream.WebsocketSetup{
+ Enabled: exch.Features.Enabled.Websocket,
+ Verbose: exch.Verbose,
+ AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
+ WebsocketTimeout: exch.WebsocketTrafficTimeout,
+ DefaultURL: krakenWSURL,
+ ExchangeName: exch.Name,
+ RunningURL: exch.API.Endpoints.WebsocketURL,
+ Connector: k.WsConnect,
+ Subscriber: k.Subscribe,
+ UnSubscriber: k.Unsubscribe,
+ GenerateSubscriptions: k.GenerateDefaultSubscriptions,
+ Features: &k.Features.Supports.WebsocketCapabilities,
+ OrderbookBufferLimit: exch.WebsocketOrderbookBufferLimit,
+ BufferEnabled: true,
+ SortBuffer: true,
+ })
if err != nil {
return err
}
- k.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: k.Name,
- URL: k.Websocket.GetWebsocketURL(),
- ProxyURL: k.Websocket.GetProxyAddress(),
- Verbose: k.Verbose,
+ err = k.Websocket.SetupNewConnection(stream.ConnectionSetup{
RateLimit: krakenWsRateLimit,
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
+ URL: krakenWSURL,
+ })
+ if err != nil {
+ return err
}
- k.AuthenticatedWebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: k.Name,
+ return k.Websocket.SetupNewConnection(stream.ConnectionSetup{
+ RateLimit: krakenWsRateLimit,
+ ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
+ ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
URL: krakenAuthWSURL,
- ProxyURL: k.Websocket.GetProxyAddress(),
- Verbose: k.Verbose,
- RateLimit: krakenWsRateLimit,
- ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
- ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
- }
-
- k.Websocket.Orderbook.Setup(
- exch.WebsocketOrderbookBufferLimit,
- true,
- true,
- false,
- false,
- exch.Name)
- return nil
+ Authenticated: true,
+ })
}
// Start starts the Kraken go routine
@@ -237,22 +226,55 @@ func (k *Kraken) Run() {
}
forceUpdate := false
- delim := k.GetPairFormat(asset.Spot, false).Delimiter
- if !common.StringDataContains(k.GetEnabledPairs(asset.Spot).Strings(), delim) ||
- !common.StringDataContains(k.GetAvailablePairs(asset.Spot).Strings(), delim) ||
- common.StringDataContains(k.GetAvailablePairs(asset.Spot).Strings(), "ZUSD") {
- enabledPairs := currency.NewPairsFromStrings(
- []string{currency.XBT.String() + delim + currency.USD.String()},
- )
- log.Warn(log.ExchangeSys, "Available pairs for Kraken reset due to config upgrade, please enable the ones you would like again")
- forceUpdate = true
+ format, err := k.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update tradable pairs. Err: %s",
+ k.Name,
+ err)
+ return
+ }
+ enabled, err := k.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update tradable pairs. Err: %s",
+ k.Name,
+ err)
+ return
+ }
- err := k.UpdatePairs(enabledPairs, asset.Spot, true, true)
+ avail, err := k.GetAvailablePairs(asset.Spot)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update tradable pairs. Err: %s",
+ k.Name,
+ err)
+ return
+ }
+
+ if !common.StringDataContains(enabled.Strings(), format.Delimiter) ||
+ !common.StringDataContains(avail.Strings(), format.Delimiter) ||
+ common.StringDataContains(avail.Strings(), "ZUSD") {
+ var p currency.Pairs
+ p, err = currency.NewPairsFromStrings([]string{currency.XBT.String() +
+ format.Delimiter +
+ currency.USD.String()})
if err != nil {
log.Errorf(log.ExchangeSys,
"%s failed to update currencies. Err: %s\n",
k.Name,
err)
+ } else {
+ log.Warn(log.ExchangeSys, "Available pairs for Kraken reset due to config upgrade, please enable the ones you would like again")
+ forceUpdate = true
+
+ err = k.UpdatePairs(p, asset.Spot, true, true)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update currencies. Err: %s\n",
+ k.Name,
+ err)
+ }
}
}
@@ -260,7 +282,7 @@ func (k *Kraken) Run() {
return
}
- err := k.UpdateTradablePairs(forceUpdate)
+ err = k.UpdateTradablePairs(forceUpdate)
if err != nil {
log.Errorf(log.ExchangeSys,
"%s failed to update tradable pairs. Err: %s",
@@ -282,6 +304,11 @@ func (k *Kraken) FetchTradablePairs(asset asset.Item) ([]string, error) {
return nil, err
}
+ format, err := k.GetPairFormat(asset, false)
+ if err != nil {
+ return nil, err
+ }
+
var products []string
for i := range pairs {
if strings.Contains(pairs[i].Altname, ".d") {
@@ -305,8 +332,7 @@ func (k *Kraken) FetchTradablePairs(asset asset.Item) ([]string, error) {
pairs[i].Quote)
continue
}
- products = append(products,
- base+k.GetPairFormat(asset, false).Delimiter+quote)
+ products = append(products, base+format.Delimiter+quote)
}
return products, nil
}
@@ -319,48 +345,57 @@ func (k *Kraken) UpdateTradablePairs(forceUpdate bool) error {
return err
}
- return k.UpdatePairs(currency.NewPairsFromStrings(pairs), asset.Spot, false, forceUpdate)
+ p, err := currency.NewPairsFromStrings(pairs)
+ if err != nil {
+ return err
+ }
+ return k.UpdatePairs(p, asset.Spot, false, forceUpdate)
}
// UpdateTicker updates and returns the ticker for a currency pair
func (k *Kraken) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
- tickerPrice := new(ticker.Price)
- pairs := k.GetEnabledPairs(assetType)
+ pairs, err := k.GetEnabledPairs(assetType)
+ if err != nil {
+ return nil, err
+ }
pairsCollated, err := k.FormatExchangeCurrencies(pairs, assetType)
if err != nil {
- return tickerPrice, err
+ return nil, err
}
tickers, err := k.GetTickers(pairsCollated)
if err != nil {
- return tickerPrice, err
+ return nil, err
}
for i := range pairs {
for c, t := range tickers {
- pairFmt := k.FormatExchangeCurrency(pairs[i], assetType).String()
- if !strings.EqualFold(pairFmt, c) {
+ pairFmt, err := k.FormatExchangeCurrency(pairs[i], assetType)
+ if err != nil {
+ return nil, err
+ }
+ if !strings.EqualFold(pairFmt.String(), c) {
altCurrency := assetTranslator.LookupAltname(c)
if altCurrency == "" {
continue
}
- if !strings.EqualFold(pairFmt, altCurrency) {
- continue
+ if !strings.EqualFold(pairFmt.String(), altCurrency) {
+ continue // This looks dodge
}
}
- tickerPrice = &ticker.Price{
- Last: t.Last,
- High: t.High,
- Low: t.Low,
- Bid: t.Bid,
- Ask: t.Ask,
- Volume: t.Volume,
- Open: t.Open,
- Pair: pairs[i],
- }
- err = ticker.ProcessTicker(k.Name, tickerPrice, assetType)
+ err = ticker.ProcessTicker(&ticker.Price{
+ Last: t.Last,
+ High: t.High,
+ Low: t.Low,
+ Bid: t.Bid,
+ Ask: t.Ask,
+ Volume: t.Volume,
+ Open: t.Open,
+ Pair: pairs[i],
+ ExchangeName: k.Name,
+ AssetType: assetType})
if err != nil {
- log.Error(log.Ticker, err)
+ return nil, err
}
}
}
@@ -387,19 +422,29 @@ func (k *Kraken) FetchOrderbook(p currency.Pair, assetType asset.Item) (*orderbo
// UpdateOrderbook updates and returns the orderbook for a currency pair
func (k *Kraken) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
- orderBook := new(orderbook.Base)
- orderbookNew, err := k.GetDepth(k.FormatExchangeCurrency(p,
- assetType).String())
+ fpair, err := k.FormatExchangeCurrency(p, assetType)
if err != nil {
- return orderBook, err
+ return nil, err
}
+ orderbookNew, err := k.GetDepth(fpair.String())
+ if err != nil {
+ return nil, err
+ }
+
+ var orderBook = new(orderbook.Base)
for x := range orderbookNew.Bids {
- orderBook.Bids = append(orderBook.Bids, orderbook.Item{Amount: orderbookNew.Bids[x].Amount, Price: orderbookNew.Bids[x].Price})
+ orderBook.Bids = append(orderBook.Bids, orderbook.Item{
+ Amount: orderbookNew.Bids[x].Amount,
+ Price: orderbookNew.Bids[x].Price,
+ })
}
for x := range orderbookNew.Asks {
- orderBook.Asks = append(orderBook.Asks, orderbook.Item{Amount: orderbookNew.Asks[x].Amount, Price: orderbookNew.Asks[x].Price})
+ orderBook.Asks = append(orderBook.Asks, orderbook.Item{
+ Amount: orderbookNew.Asks[x].Amount,
+ Price: orderbookNew.Asks[x].Price,
+ })
}
orderBook.Pair = p
@@ -569,6 +614,16 @@ func (k *Kraken) GetOrderInfo(orderID string) (order.Detail, error) {
return orderDetail, err
}
if orderInfo, ok := openOrders.Open[orderID]; ok {
+ avail, err := k.GetAvailablePairs(asset.Spot)
+ if err != nil {
+ return orderDetail, err
+ }
+
+ fmt, err := k.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return orderDetail, err
+ }
+
var trades []order.TradeHistory
for i := range orderInfo.Trades {
trades = append(trades, order.TradeHistory{
@@ -588,11 +643,16 @@ func (k *Kraken) GetOrderInfo(orderID string) (order.Detail, error) {
return orderDetail, err
}
+ p, err := currency.NewPairFromFormattedPairs(orderInfo.Description.Pair,
+ avail,
+ fmt)
+ if err != nil {
+ return orderDetail, err
+ }
orderDetail = order.Detail{
- Exchange: k.Name,
- ID: orderID,
- Pair: currency.NewPairFromFormattedPairs(orderInfo.Description.Pair,
- k.GetAvailablePairs(asset.Spot), k.GetPairFormat(asset.Spot, true)),
+ Exchange: k.Name,
+ ID: orderID,
+ Pair: p,
Side: side,
Type: oType,
Date: convert.TimeFromUnixTimestampDecimal(orderInfo.OpenTime),
@@ -666,11 +726,6 @@ func (k *Kraken) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdraw.
}, nil
}
-// GetWebsocket returns a pointer to the exchange websocket
-func (k *Kraken) GetWebsocket() (*wshandler.Websocket, error) {
- return k.Websocket, nil
-}
-
// GetFeeByType returns an estimate of fee based on type of transaction
func (k *Kraken) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if !k.AllowAuthenticatedRequest() && // Todo check connection status
@@ -687,8 +742,25 @@ func (k *Kraken) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
return nil, err
}
+ avail, err := k.GetAvailablePairs(asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+
+ fmt, err := k.GetPairFormat(asset.Spot, true)
+ if err != nil {
+ return nil, err
+ }
+
var orders []order.Detail
for i := range resp.Open {
+ p, err := currency.NewPairFromFormattedPairs(resp.Open[i].Description.Pair,
+ avail,
+ fmt)
+ if err != nil {
+ return nil, err
+ }
+
side := order.Side(strings.ToUpper(resp.Open[i].Description.Type))
orderType := order.Type(strings.ToUpper(resp.Open[i].Description.OrderType))
orders = append(orders, order.Detail{
@@ -701,8 +773,7 @@ func (k *Kraken) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, e
Price: resp.Open[i].Description.Price,
Side: side,
Type: orderType,
- Pair: currency.NewPairFromFormattedPairs(resp.Open[i].Description.Pair,
- k.GetAvailablePairs(asset.Spot), k.GetPairFormat(asset.Spot, true)),
+ Pair: p,
})
}
@@ -723,6 +794,16 @@ func (k *Kraken) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest) ([]or
req.End = strconv.FormatInt(getOrdersRequest.EndTicks.Unix(), 10)
}
+ avail, err := k.GetAvailablePairs(asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+
+ fmt, err := k.GetPairFormat(asset.Spot, true)
+ if err != nil {
+ return nil, err
+ }
+
resp, err := k.GetClosedOrders(req)
if err != nil {
return nil, err
@@ -730,6 +811,13 @@ func (k *Kraken) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest) ([]or
var orders []order.Detail
for i := range resp.Closed {
+ p, err := currency.NewPairFromFormattedPairs(resp.Closed[i].Description.Pair,
+ avail,
+ fmt)
+ if err != nil {
+ return nil, err
+ }
+
side := order.Side(strings.ToUpper(resp.Closed[i].Description.Type))
orderType := order.Type(strings.ToUpper(resp.Closed[i].Description.OrderType))
orders = append(orders, order.Detail{
@@ -743,8 +831,7 @@ func (k *Kraken) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest) ([]or
Price: resp.Closed[i].Description.Price,
Side: side,
Type: orderType,
- Pair: currency.NewPairFromFormattedPairs(resp.Closed[i].Description.Pair,
- k.GetAvailablePairs(asset.Spot), k.GetPairFormat(asset.Spot, true)),
+ Pair: p,
})
}
@@ -753,25 +840,6 @@ func (k *Kraken) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest) ([]or
return orders, nil
}
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func (k *Kraken) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- k.Websocket.SubscribeToChannels(channels)
- return nil
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func (k *Kraken) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- k.Websocket.RemoveSubscribedChannels(channels)
- return nil
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func (k *Kraken) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return k.Websocket.GetSubscriptions(), nil
-}
-
// AuthenticateWebsocket sends an authentication message to the websocket
func (k *Kraken) AuthenticateWebsocket() error {
resp, err := k.GetWebsocketToken()
@@ -807,7 +875,13 @@ func (k *Kraken) GetHistoricCandles(pair currency.Pair, a asset.Item, start, end
Asset: a,
Interval: interval,
}
- candles, err := k.GetOHLC(assetTranslator.LookupCurrency(k.FormatExchangeCurrency(pair, a).Upper().String()), k.FormatExchangeKlineInterval(interval))
+
+ formattedPair, err := k.FormatExchangeCurrency(pair, a)
+ if err != nil {
+ return kline.Item{}, err
+ }
+
+ candles, err := k.GetOHLC(assetTranslator.LookupCurrency(formattedPair.Upper().String()), k.FormatExchangeKlineInterval(interval))
if err != nil {
return kline.Item{}, err
}
@@ -848,7 +922,12 @@ func (k *Kraken) GetHistoricCandlesExtended(pair currency.Pair, a asset.Item, st
Interval: interval,
}
- candles, err := k.GetOHLC(assetTranslator.LookupCurrency(k.FormatExchangeCurrency(pair, a).Upper().String()), k.FormatExchangeKlineInterval(interval))
+ formattedPair, err := k.FormatExchangeCurrency(pair, a)
+ if err != nil {
+ return kline.Item{}, err
+ }
+
+ candles, err := k.GetOHLC(assetTranslator.LookupCurrency(formattedPair.Upper().String()), k.FormatExchangeKlineInterval(interval))
if err != nil {
return kline.Item{}, err
}
diff --git a/exchanges/lakebtc/lakebtc_test.go b/exchanges/lakebtc/lakebtc_test.go
index 460f35b9..d1d38320 100644
--- a/exchanges/lakebtc/lakebtc_test.go
+++ b/exchanges/lakebtc/lakebtc_test.go
@@ -14,7 +14,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -36,18 +36,17 @@ func TestMain(m *testing.M) {
}
lakebtcConfig, err := cfg.GetExchangeConfig("LakeBTC")
if err != nil {
- log.Fatal("LakeBTC Setup() init error")
+ log.Fatal("LakeBTC Setup() init error", err)
}
lakebtcConfig.API.AuthenticatedSupport = true
lakebtcConfig.API.Credentials.Key = apiKey
lakebtcConfig.API.Credentials.Secret = apiSecret
lakebtcConfig.Features.Enabled.Websocket = true
+ l.Websocket = sharedtestvalues.NewTestWebsocket()
err = l.Setup(lakebtcConfig)
if err != nil {
log.Fatal("LakeBTC setup error", err)
}
- l.API.Endpoints.WebsocketURL = lakeBTCWSURL
-
os.Exit(m.Run())
}
@@ -441,10 +440,8 @@ func TestGetDepositAddress(t *testing.T) {
// TestWsConn websocket connection test
func TestWsConn(t *testing.T) {
if !l.Websocket.IsEnabled() {
- t.Skip(wshandler.WebsocketNotEnabled)
+ t.Skip(stream.WebsocketNotEnabled)
}
- l.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- l.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
err := l.WsConnect()
if err != nil {
t.Fatal(err)
@@ -453,8 +450,6 @@ func TestWsConn(t *testing.T) {
// TestWsTradeProcessing logic test
func TestWsTradeProcessing(t *testing.T) {
- l.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- l.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
json := `{"trades":[{"type":"sell","date":1564985787,"price":"11913.02","amount":"0.49"}]}`
err := l.processTrades(json, "market-btcusd-global")
if err != nil {
@@ -464,9 +459,6 @@ func TestWsTradeProcessing(t *testing.T) {
// TestWsTickerProcessing logic test
func TestWsTickerProcessing(t *testing.T) {
- const testChanSize = 26
- l.Websocket.DataHandler = make(chan interface{}, testChanSize)
- l.Websocket.TrafficAlert = make(chan struct{}, testChanSize)
json := `{"btcusd":{"low":"10990.05","high":"11966.24","last":"11903.29","volume":"1803.967079","sell":"11912.39","buy":"11902.2"},"btceur":{"low":"9886.87","high":"10732.72","last":"10691.44","volume":"87.994478","sell":"10711.62","buy":"10691.44"},"btchkd":{"low":null,"high":null,"last":"51776.98","volume":null,"sell":"93307.37","buy":"93177.56"},"btcjpy":{"low":"1176039.0","high":"1272246.0","last":"1265680.0","volume":"129.021421","sell":"1266764.0","buy":"1265680.0"},"btcgbp":{"low":"9157.12","high":"9953.43","last":"9941.28","volume":"10.4997","sell":"10007.89","buy":"9941.28"},"btcaud":{"low":"16102.57","high":"17594.22","last":"17548.16","volume":"7.338316","sell":"17616.67","buy":"17549.69"},"btccad":{"low":"14541.69","high":"15834.87","last":"15763.54","volume":"30.480309","sell":"15793.45","buy":"15756.13"},"btcsgd":{"low":"15133.82","high":"16501.62","last":"16455.53","volume":"4.044026","sell":"16484.37","buy":"16462.18"},"btcchf":{"low":"10800.58","high":"11526.24","last":"11526.24","volume":"0.1765","sell":"11675.34","buy":"11632.02"},"btcnzd":{"low":null,"high":null,"last":"8340.98","volume":null,"sell":"18315.49","buy":"18221.37"},"btcngn":{"low":null,"high":null,"last":"600000.0","volume":null,"sell":null,"buy":null},"eurusd":{"low":"1.1088","high":"1.1138","last":"1.1125","volume":"2680.105249","sell":"1.1142","buy":"1.1121"},"gbpusd":{"low":"1.1934","high":"1.1958","last":"1.1934","volume":"1493.923823","sell":"1.1979","buy":"1.1903"},"usdjpy":{"low":"105.26","high":"107.25","last":"106.33","volume":"114490.2179","sell":"106.34","buy":"106.27"},"usdhkd":{"low":null,"high":null,"last":"7.851","volume":null,"sell":"7.8328","buy":"7.8286"},"usdcad":{"low":"1.3225","high":"1.3272","last":"1.3255","volume":"11033.9877","sell":"1.3258","buy":"1.3238"},"usdsgd":{"low":"1.3776","high":"1.3839","last":"1.3838","volume":"2523.75","sell":"1.3838","buy":"1.3819"},"audusd":{"low":"0.6764","high":"0.6853","last":"0.6771","volume":"5442.608321","sell":"0.6782","buy":"0.6762"},"nzdusd":{"low":null,"high":null,"last":"0.6758","volume":null,"sell":"0.6532","buy":"0.6504"},"usdchf":{"low":"0.9838","high":"0.9838","last":"0.9838","volume":"108.3352","sell":"0.9801","buy":"0.9773"},"usdngn":{"low":null,"high":null,"last":"200.0","volume":null,"sell":null,"buy":null},"ethbtc":{"low":"0.0205","high":"0.025","last":"0.0205","volume":null,"sell":"0.03","buy":"0.0194"},"ltcbtc":{"low":null,"high":null,"last":"0.0114","volume":null,"sell":"0.009","buy":"0.0073"},"bchbtc":{"low":null,"high":null,"last":"0.0544","volume":null,"sell":"0.0322","buy":"0.0274"},"xrpbtc":{"low":"0.000042","high":"0.000042","last":"0.000042","volume":null,"sell":"0.000037","buy":"0.000022"},"baceth":{"low":"0.000035","high":"0.000035","last":"0.000035","volume":null,"sell":"0.0015","buy":null}}`
err := l.processTicker(json)
if err != nil {
@@ -476,16 +468,20 @@ func TestWsTickerProcessing(t *testing.T) {
func TestGetCurrencyFromChannel(t *testing.T) {
curr := currency.NewPair(currency.LTC, currency.BTC)
- result := l.getCurrencyFromChannel(marketSubstring + curr.String() + globalSubstring)
- if curr != result {
+ result, err := l.getCurrencyFromChannel(marketSubstring +
+ curr.String() +
+ globalSubstring)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if !curr.Equal(result) {
t.Errorf("currency result is not equal. Expected %v", curr)
}
}
// TestWsOrderbookProcessing logic test
func TestWsOrderbookProcessing(t *testing.T) {
- l.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- l.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
json := `{"asks":[["11905.66","0.0019"],["11905.73","0.0015"],["11906.43","0.0013"],["11906.62","0.0019"],["11907.25","11.087"],["11907.66","0.0006"],["11907.73","0.3113"],["11907.84","0.0006"],["11908.37","0.0016"],["11908.86","10.3786"],["11909.54","4.2955"],["11910.15","0.0012"],["11910.56","13.5505"],["11911.06","0.0011"],["11911.37","0.0023"]],"bids":[["11905.55","0.0171"],["11904.43","0.0225"],["11903.31","0.0223"],["11902.2","0.0027"],["11901.92","1.002"],["11901.6","0.0015"],["11901.49","0.0012"],["11901.08","0.0227"],["11900.93","0.0009"],["11900.53","1.662"],["11900.08","0.001"],["11900.01","3.6745"],["11899.96","0.003"],["11899.91","0.0006"],["11899.44","0.0013"]]}`
err := l.processOrderbook(json, "market-btcusd-global")
if err != nil {
diff --git a/exchanges/lakebtc/lakebtc_types.go b/exchanges/lakebtc/lakebtc_types.go
index f0949b85..4dde4310 100644
--- a/exchanges/lakebtc/lakebtc_types.go
+++ b/exchanges/lakebtc/lakebtc_types.go
@@ -125,8 +125,8 @@ type WebsocketConn struct {
// WsOrderbookUpdate contains orderbook data from websocket
type WsOrderbookUpdate struct {
- Asks [][]string `json:"asks"`
- Bids [][]string `json:"bids"`
+ Asks [][2]string `json:"asks"`
+ Bids [][2]string `json:"bids"`
}
// WsTrades contains trade data from websocket
@@ -141,3 +141,12 @@ type WsTrade struct {
Price float64 `json:"price,string"`
Amount float64 `json:"amount,string"`
}
+
+type wsTicker struct {
+ Low float64 `json:"low,string"`
+ High float64 `json:"high,string"`
+ Last float64 `json:"last,string"`
+ Volume float64 `json:"volume,string"`
+ Sell float64 `json:"sell,string"`
+ Buy float64 `json:"buy,string"`
+}
diff --git a/exchanges/lakebtc/lakebtc_websocket.go b/exchanges/lakebtc/lakebtc_websocket.go
index 7af6622f..f197ba79 100644
--- a/exchanges/lakebtc/lakebtc_websocket.go
+++ b/exchanges/lakebtc/lakebtc_websocket.go
@@ -8,18 +8,19 @@ import (
"strings"
"time"
+ "github.com/thrasher-corp/gocryptotrader/common"
"github.com/thrasher-corp/gocryptotrader/currency"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/toorop/go-pusher"
)
const (
- lakeBTCWSURL = "ws.lakebtc.com:8085"
+ lakeBTCWSURL = "wss://ws.lakebtc.com:8085"
marketGlobalEndpoint = "market-global"
marketSubstring = "market-"
globalSubstring = "-global"
@@ -33,10 +34,14 @@ const (
// WsConnect initiates a new websocket connection
func (l *LakeBTC) WsConnect() error {
if !l.Websocket.IsEnabled() || !l.IsEnabled() {
- return errors.New(wshandler.WebsocketNotEnabled)
+ return errors.New(stream.WebsocketNotEnabled)
}
+
+ url := strings.Split(lakeBTCWSURL, "://")
var err error
- l.WebsocketConn.Client, err = pusher.NewCustomClient(strings.ToLower(l.Name), lakeBTCWSURL, wssSchem)
+ l.WebsocketConn.Client, err = pusher.NewCustomClient(strings.ToLower(l.Name),
+ url[1],
+ wssSchem)
if err != nil {
return err
}
@@ -44,13 +49,17 @@ func (l *LakeBTC) WsConnect() error {
if err != nil {
return err
}
- l.GenerateDefaultSubscriptions()
+
err = l.listenToEndpoints()
if err != nil {
return err
}
go l.wsHandleIncomingData()
- return nil
+ subs, err := l.GenerateDefaultSubscriptions()
+ if err != nil {
+ return err
+ }
+ return l.Websocket.SubscribeToChannels(subs)
}
func (l *LakeBTC) listenToEndpoints() error {
@@ -71,9 +80,12 @@ func (l *LakeBTC) listenToEndpoints() error {
}
// GenerateDefaultSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions()
-func (l *LakeBTC) GenerateDefaultSubscriptions() {
- var subscriptions []wshandler.WebsocketChannelSubscription
- enabledCurrencies := l.GetEnabledPairs(asset.Spot)
+func (l *LakeBTC) GenerateDefaultSubscriptions() ([]stream.ChannelSubscription, error) {
+ var subscriptions []stream.ChannelSubscription
+ enabledCurrencies, err := l.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return nil, err
+ }
for j := range enabledCurrencies {
enabledCurrencies[j].Delimiter = ""
@@ -81,23 +93,54 @@ func (l *LakeBTC) GenerateDefaultSubscriptions() {
enabledCurrencies[j].Lower().String() +
globalSubstring
- subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
Channel: channel,
Currency: enabledCurrencies[j],
+ Asset: asset.Spot,
})
}
- l.Websocket.SubscribeToChannels(subscriptions)
+ return subscriptions, nil
}
// Subscribe sends a websocket message to receive data from the channel
-func (l *LakeBTC) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
- return l.WebsocketConn.Client.Subscribe(channelToSubscribe.Channel)
+func (l *LakeBTC) Subscribe(channelsToSubscribe []stream.ChannelSubscription) error {
+ var errs common.Errors
+ for i := range channelsToSubscribe {
+ err := l.WebsocketConn.Client.Subscribe(channelsToSubscribe[i].Channel)
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ l.Websocket.AddSuccessfulSubscriptions(channelsToSubscribe[i])
+ }
+ if errs != nil {
+ return errs
+ }
+ return nil
+}
+
+// Unsubscribe sends a websocket message to unsubscribe from the channel
+func (l *LakeBTC) Unsubscribe(channelsToUnsubscribe []stream.ChannelSubscription) error {
+ var errs common.Errors
+ for i := range channelsToUnsubscribe {
+ err := l.WebsocketConn.Client.Unsubscribe(channelsToUnsubscribe[i].Channel)
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ l.Websocket.RemoveSuccessfulUnsubscriptions(channelsToUnsubscribe[i])
+ }
+ if errs != nil {
+ return errs
+ }
+ return nil
}
// wsHandleIncomingData services incoming data from the websocket connection
func (l *LakeBTC) wsHandleIncomingData() {
l.Websocket.Wg.Add(1)
defer l.Websocket.Wg.Done()
+
for {
select {
case <-l.Websocket.ShutdownC:
@@ -107,14 +150,11 @@ func (l *LakeBTC) wsHandleIncomingData() {
log.Debugf(log.ExchangeSys,
"%v Websocket message received: %v", l.Name, data)
}
- l.Websocket.TrafficAlert <- struct{}{}
err := l.processTicker(data.Data)
if err != nil {
l.Websocket.DataHandler <- err
- return
}
case data := <-l.WebsocketConn.Trade:
- l.Websocket.TrafficAlert <- struct{}{}
if l.Verbose {
log.Debugf(log.ExchangeSys,
"%v Websocket message received: %v", l.Name, data)
@@ -122,10 +162,8 @@ func (l *LakeBTC) wsHandleIncomingData() {
err := l.processTrades(data.Data, data.Channel)
if err != nil {
l.Websocket.DataHandler <- err
- return
}
case data := <-l.WebsocketConn.Orderbook:
- l.Websocket.TrafficAlert <- struct{}{}
if l.Verbose {
log.Debugf(log.ExchangeSys,
"%v Websocket message received: %v", l.Name, data)
@@ -133,9 +171,12 @@ func (l *LakeBTC) wsHandleIncomingData() {
err := l.processOrderbook(data.Data, data.Channel)
if err != nil {
l.Websocket.DataHandler <- err
- return
}
}
+ select {
+ case l.Websocket.TrafficAlert <- struct{}{}:
+ default:
+ }
}
}
@@ -145,7 +186,11 @@ func (l *LakeBTC) processTrades(data, channel string) error {
if err != nil {
return err
}
- curr := l.getCurrencyFromChannel(channel)
+ curr, err := l.getCurrencyFromChannel(channel)
+ if err != nil {
+ return err
+ }
+
for i := range tradeData.Trades {
tSide, err := order.StringToOrderSide(tradeData.Trades[i].Type)
if err != nil {
@@ -154,7 +199,7 @@ func (l *LakeBTC) processTrades(data, channel string) error {
Err: err,
}
}
- l.Websocket.DataHandler <- wshandler.TradeData{
+ l.Websocket.DataHandler <- stream.TradeData{
Timestamp: time.Unix(tradeData.Trades[i].Date, 0),
CurrencyPair: curr,
AssetType: asset.Spot,
@@ -175,7 +220,10 @@ func (l *LakeBTC) processOrderbook(obUpdate, channel string) error {
return err
}
- p := l.getCurrencyFromChannel(channel)
+ p, err := l.getCurrencyFromChannel(channel)
+ if err != nil {
+ return err
+ }
book := orderbook.Base{
Pair: p,
@@ -188,13 +236,11 @@ func (l *LakeBTC) processOrderbook(obUpdate, channel string) error {
var amount, price float64
amount, err = strconv.ParseFloat(update.Asks[i][1], 64)
if err != nil {
- l.Websocket.DataHandler <- fmt.Errorf("%v error parsing ticker data 'low' %v", l.Name, update.Asks[i])
- continue
+ return err
}
price, err = strconv.ParseFloat(update.Asks[i][0], 64)
if err != nil {
- l.Websocket.DataHandler <- fmt.Errorf("%v error parsing orderbook price %v", l.Name, update.Asks[i])
- continue
+ return err
}
book.Asks = append(book.Asks, orderbook.Item{
Amount: amount,
@@ -206,13 +252,11 @@ func (l *LakeBTC) processOrderbook(obUpdate, channel string) error {
var amount, price float64
amount, err = strconv.ParseFloat(update.Bids[i][1], 64)
if err != nil {
- l.Websocket.DataHandler <- fmt.Errorf("%v error parsing ticker data 'low' %v", l.Name, update.Bids[i])
- continue
+ return err
}
price, err = strconv.ParseFloat(update.Bids[i][0], 64)
if err != nil {
- l.Websocket.DataHandler <- fmt.Errorf("%v error parsing orderbook price %v", l.Name, update.Bids[i])
- continue
+ return err
}
book.Bids = append(book.Bids, orderbook.Item{
Amount: amount,
@@ -220,67 +264,46 @@ func (l *LakeBTC) processOrderbook(obUpdate, channel string) error {
})
}
- err = l.Websocket.Orderbook.LoadSnapshot(&book)
- if err != nil {
- return err
- }
-
- l.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
- Pair: p,
- Asset: asset.Spot,
- Exchange: l.Name,
- }
-
- return nil
+ return l.Websocket.Orderbook.LoadSnapshot(&book)
}
-func (l *LakeBTC) getCurrencyFromChannel(channel string) currency.Pair {
+func (l *LakeBTC) getCurrencyFromChannel(channel string) (currency.Pair, error) {
curr := strings.Replace(channel, marketSubstring, "", 1)
curr = strings.Replace(curr, globalSubstring, "", 1)
return currency.NewPairFromString(curr)
}
-func (l *LakeBTC) processTicker(wsTicker string) error {
- var tUpdate map[string]interface{}
- err := json.Unmarshal([]byte(wsTicker), &tUpdate)
+func (l *LakeBTC) processTicker(data string) error {
+ var tUpdate map[string]wsTicker
+ err := json.Unmarshal([]byte(data), &tUpdate)
if err != nil {
l.Websocket.DataHandler <- err
return err
}
- enabled := l.GetEnabledPairs(asset.Spot)
+ enabled, err := l.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return err
+ }
+
for k, v := range tUpdate {
- returnCurrency := currency.NewPairFromString(k)
+ returnCurrency, err := currency.NewPairFromString(k)
+ if err != nil {
+ return err
+ }
+
if !enabled.Contains(returnCurrency, true) {
continue
}
- tickerData := v.(map[string]interface{})
- processTickerItem := func(tick map[string]interface{}, item string) float64 {
- if tick[item] == nil {
- return 0
- }
-
- p, err := strconv.ParseFloat(tick[item].(string), 64)
- if err != nil {
- l.Websocket.DataHandler <- fmt.Errorf("%s error parsing ticker data '%s' %v",
- l.Name,
- item,
- tickerData)
- return 0
- }
-
- return p
- }
-
l.Websocket.DataHandler <- &ticker.Price{
ExchangeName: l.Name,
- Bid: processTickerItem(tickerData, order.Buy.Lower()),
- High: processTickerItem(tickerData, tickerHighString),
- Last: processTickerItem(tickerData, tickerLastString),
- Low: processTickerItem(tickerData, tickerLowString),
- Ask: processTickerItem(tickerData, order.Sell.Lower()),
- Volume: processTickerItem(tickerData, tickerVolumeString),
+ Bid: v.Buy,
+ High: v.High,
+ Last: v.Last,
+ Low: v.Low,
+ Ask: v.Sell,
+ Volume: v.Volume,
AssetType: asset.Spot,
Pair: returnCurrency,
}
diff --git a/exchanges/lakebtc/lakebtc_wrapper.go b/exchanges/lakebtc/lakebtc_wrapper.go
index ec0007c7..1b4aee13 100644
--- a/exchanges/lakebtc/lakebtc_wrapper.go
+++ b/exchanges/lakebtc/lakebtc_wrapper.go
@@ -19,8 +19,8 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -56,18 +56,11 @@ func (l *LakeBTC) SetDefaults() {
l.API.CredentialsValidator.RequiresKey = true
l.API.CredentialsValidator.RequiresSecret = true
- l.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- },
-
- UseGlobalFormat: true,
- RequestFormat: ¤cy.PairFormat{
- Uppercase: true,
- },
- ConfigFormat: ¤cy.PairFormat{
- Uppercase: true,
- },
+ requestFmt := ¤cy.PairFormat{Uppercase: true}
+ configFmt := ¤cy.PairFormat{Uppercase: true}
+ err := l.SetGlobalPairsManager(requestFmt, configFmt, asset.Spot)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
}
l.Features = exchange.Features{
@@ -95,6 +88,7 @@ func (l *LakeBTC) SetDefaults() {
TradeFetching: true,
OrderbookFetching: true,
Subscribe: true,
+ Unsubscribe: true,
},
WithdrawPermissions: exchange.AutoWithdrawCrypto |
exchange.WithdrawFiatViaWebsiteOnly,
@@ -109,7 +103,7 @@ func (l *LakeBTC) SetDefaults() {
l.API.Endpoints.URLDefault = lakeBTCAPIURL
l.API.Endpoints.URL = l.API.Endpoints.URLDefault
- l.Websocket = wshandler.New()
+ l.Websocket = stream.New()
l.API.Endpoints.WebsocketURL = lakeBTCWSURL
l.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
l.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
@@ -128,31 +122,21 @@ func (l *LakeBTC) Setup(exch *config.ExchangeConfig) error {
return err
}
- err = l.Websocket.Setup(
- &wshandler.WebsocketSetup{
- Enabled: exch.Features.Enabled.Websocket,
- Verbose: exch.Verbose,
- AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
- WebsocketTimeout: exch.WebsocketTrafficTimeout,
- DefaultURL: lakeBTCWSURL,
- ExchangeName: exch.Name,
- RunningURL: exch.API.Endpoints.WebsocketURL,
- Connector: l.WsConnect,
- Subscriber: l.Subscribe,
- Features: &l.Features.Supports.WebsocketCapabilities,
- })
- if err != nil {
- return err
- }
-
- l.Websocket.Orderbook.Setup(
- exch.WebsocketOrderbookBufferLimit,
- false,
- false,
- false,
- false,
- exch.Name)
- return nil
+ return l.Websocket.Setup(&stream.WebsocketSetup{
+ Enabled: exch.Features.Enabled.Websocket,
+ Verbose: exch.Verbose,
+ AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
+ WebsocketTimeout: exch.WebsocketTrafficTimeout,
+ DefaultURL: lakeBTCWSURL,
+ ExchangeName: exch.Name,
+ RunningURL: exch.API.Endpoints.WebsocketURL,
+ Connector: l.WsConnect,
+ Subscriber: l.Subscribe,
+ UnSubscriber: l.Unsubscribe,
+ GenerateSubscriptions: l.GenerateDefaultSubscriptions,
+ Features: &l.Features.Supports.WebsocketCapabilities,
+ OrderbookBufferLimit: exch.WebsocketOrderbookBufferLimit,
+ })
}
// Start starts the LakeBTC go routine
@@ -203,7 +187,11 @@ func (l *LakeBTC) UpdateTradablePairs(forceUpdate bool) error {
return err
}
- return l.UpdatePairs(currency.NewPairsFromStrings(pairs), asset.Spot, false, forceUpdate)
+ p, err := currency.NewPairsFromStrings(pairs)
+ if err != nil {
+ return err
+ }
+ return l.UpdatePairs(p, asset.Spot, false, forceUpdate)
}
// UpdateTicker updates and returns the ticker for a currency pair
@@ -213,9 +201,18 @@ func (l *LakeBTC) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.P
return nil, err
}
- pairs := l.GetEnabledPairs(assetType)
+ pairs, err := l.GetEnabledPairs(assetType)
+ if err != nil {
+ return nil, err
+ }
+
for i := range pairs {
- c, ok := ticks[l.FormatExchangeCurrency(pairs[i], assetType).String()]
+ fpair, err := l.FormatExchangeCurrency(pairs[i], assetType)
+ if err != nil {
+ return nil, err
+ }
+
+ c, ok := ticks[fpair.String()]
if !ok {
continue
}
@@ -228,10 +225,12 @@ func (l *LakeBTC) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.P
tickerPrice.High = c.High
tickerPrice.Low = c.Low
tickerPrice.Last = c.Last
+ tickerPrice.ExchangeName = l.Name
+ tickerPrice.AssetType = assetType
- err = ticker.ProcessTicker(l.Name, tickerPrice, assetType)
+ err = ticker.ProcessTicker(tickerPrice)
if err != nil {
- log.Error(log.Ticker, err)
+ return nil, err
}
}
return ticker.GetTicker(l.Name, p, assetType)
@@ -447,11 +446,6 @@ func (l *LakeBTC) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdraw
return nil, common.ErrFunctionNotSupported
}
-// GetWebsocket returns a pointer to the exchange websocket
-func (l *LakeBTC) GetWebsocket() (*wshandler.Websocket, error) {
- return l.Websocket, nil
-}
-
// GetFeeByType returns an estimate of fee based on type of transaction
func (l *LakeBTC) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if !l.AllowAuthenticatedRequest() && // Todo check connection status
@@ -468,10 +462,19 @@ func (l *LakeBTC) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail,
return nil, err
}
+ format, err := l.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return nil, err
+ }
+
var orders []order.Detail
for i := range resp {
- symbol := currency.NewPairDelimiter(resp[i].Symbol,
- l.GetPairFormat(asset.Spot, false).Delimiter)
+ var symbol currency.Pair
+ symbol, err = currency.NewPairDelimiter(resp[i].Symbol,
+ format.Delimiter)
+ if err != nil {
+ return nil, err
+ }
orderDate := time.Unix(resp[i].At, 0)
side := order.Side(strings.ToUpper(resp[i].Type))
@@ -501,14 +504,21 @@ func (l *LakeBTC) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
return nil, err
}
+ format, err := l.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return nil, err
+ }
+
var orders []order.Detail
for i := range resp {
if resp[i].State == "active" {
continue
}
-
- symbol := currency.NewPairDelimiter(resp[i].Symbol,
- l.GetPairFormat(asset.Spot, false).Delimiter)
+ var symbol currency.Pair
+ symbol, err = currency.NewPairDelimiter(resp[i].Symbol, format.Delimiter)
+ if err != nil {
+ return nil, err
+ }
orderDate := time.Unix(resp[i].At, 0)
side := order.Side(strings.ToUpper(resp[i].Type))
@@ -530,28 +540,6 @@ func (l *LakeBTC) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
return orders, nil
}
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func (l *LakeBTC) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- return common.ErrFunctionNotSupported
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func (l *LakeBTC) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- return common.ErrFunctionNotSupported
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func (l *LakeBTC) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return nil, common.ErrFunctionNotSupported
-}
-
-// AuthenticateWebsocket sends an authentication message to the websocket
-func (l *LakeBTC) AuthenticateWebsocket() error {
- return common.ErrFunctionNotSupported
-}
-
// ValidateCredentials validates current credentials used for wrapper
// functionality
func (l *LakeBTC) ValidateCredentials() error {
diff --git a/exchanges/lbank/lbank.go b/exchanges/lbank/lbank.go
index c7c5ac45..b1d1c995 100644
--- a/exchanges/lbank/lbank.go
+++ b/exchanges/lbank/lbank.go
@@ -20,14 +20,14 @@ import (
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
)
// Lbank is the overarching type across this package
type Lbank struct {
exchange.Base
privateKey *rsa.PrivateKey
- WebsocketConn *wshandler.WebsocketConnection
+ WebsocketConn *stream.WebsocketConnection
}
const (
diff --git a/exchanges/lbank/lbank_test.go b/exchanges/lbank/lbank_test.go
index 2772c056..47c6a4e2 100644
--- a/exchanges/lbank/lbank_test.go
+++ b/exchanges/lbank/lbank_test.go
@@ -410,8 +410,11 @@ func TestGetOrderHistory(t *testing.T) {
func TestGetHistoricCandles(t *testing.T) {
t.Parallel()
- pair := currency.NewPairFromString(testCurrencyPair)
- _, err := l.GetHistoricCandles(pair, asset.Spot, time.Now().Add(-24*time.Hour), time.Now(), kline.OneMin)
+ pair, err := currency.NewPairFromString(testCurrencyPair)
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = l.GetHistoricCandles(pair, asset.Spot, time.Now().Add(-24*time.Hour), time.Now(), kline.OneMin)
if err != nil {
t.Fatal(err)
}
@@ -427,8 +430,11 @@ func TestGetHistoricCandlesExtended(t *testing.T) {
startTime := time.Now().Add(-time.Hour)
end := time.Now()
- pair := currency.NewPairFromString(testCurrencyPair)
- _, err := l.GetHistoricCandlesExtended(pair, asset.Spot, startTime, end, kline.OneMin)
+ pair, err := currency.NewPairFromString(testCurrencyPair)
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = l.GetHistoricCandlesExtended(pair, asset.Spot, startTime, end, kline.OneMin)
if err != nil {
t.Fatal(err)
}
diff --git a/exchanges/lbank/lbank_wrapper.go b/exchanges/lbank/lbank_wrapper.go
index 4653a872..53dea512 100644
--- a/exchanges/lbank/lbank_wrapper.go
+++ b/exchanges/lbank/lbank_wrapper.go
@@ -19,7 +19,6 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -55,18 +54,11 @@ func (l *Lbank) SetDefaults() {
l.API.CredentialsValidator.RequiresKey = true
l.API.CredentialsValidator.RequiresSecret = true
- l.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- },
-
- UseGlobalFormat: true,
- RequestFormat: ¤cy.PairFormat{
- Delimiter: "_",
- },
- ConfigFormat: ¤cy.PairFormat{
- Delimiter: "_",
- },
+ requestFmt := ¤cy.PairFormat{Delimiter: currency.UnderscoreDelimiter}
+ configFmt := ¤cy.PairFormat{Delimiter: currency.UnderscoreDelimiter}
+ err := l.SetGlobalPairsManager(requestFmt, configFmt, asset.Spot)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
}
l.Features = exchange.Features{
@@ -184,33 +176,40 @@ func (l *Lbank) UpdateTradablePairs(forceUpdate bool) error {
return err
}
- return l.UpdatePairs(currency.NewPairsFromStrings(pairs), asset.Spot, false, forceUpdate)
+ p, err := currency.NewPairsFromStrings(pairs)
+ if err != nil {
+ return err
+ }
+ return l.UpdatePairs(p, asset.Spot, false, forceUpdate)
}
// UpdateTicker updates and returns the ticker for a currency pair
func (l *Lbank) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
- tickerPrice := new(ticker.Price)
tickerInfo, err := l.GetTickers()
if err != nil {
- return tickerPrice, err
+ return nil, err
+ }
+ pairs, err := l.GetEnabledPairs(assetType)
+ if err != nil {
+ return nil, err
}
- pairs := l.GetEnabledPairs(assetType)
for i := range pairs {
for j := range tickerInfo {
if !pairs[i].Equal(tickerInfo[j].Symbol) {
continue
}
- tickerPrice = &ticker.Price{
- Last: tickerInfo[j].Ticker.Latest,
- High: tickerInfo[j].Ticker.High,
- Low: tickerInfo[j].Ticker.Low,
- Volume: tickerInfo[j].Ticker.Volume,
- Pair: tickerInfo[j].Symbol,
- LastUpdated: time.Unix(0, tickerInfo[j].Timestamp),
- }
- err = ticker.ProcessTicker(l.Name, tickerPrice, assetType)
+
+ err = ticker.ProcessTicker(&ticker.Price{
+ Last: tickerInfo[j].Ticker.Latest,
+ High: tickerInfo[j].Ticker.High,
+ Low: tickerInfo[j].Ticker.Low,
+ Volume: tickerInfo[j].Ticker.Volume,
+ Pair: tickerInfo[j].Symbol,
+ LastUpdated: time.Unix(0, tickerInfo[j].Timestamp),
+ ExchangeName: l.Name,
+ AssetType: assetType})
if err != nil {
- log.Error(log.Ticker, err)
+ return nil, err
}
}
}
@@ -219,8 +218,12 @@ func (l *Lbank) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Pri
// FetchTicker returns the ticker for a currency pair
func (l *Lbank) FetchTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
- tickerNew, err := ticker.GetTicker(l.Name,
- l.FormatExchangeCurrency(p, assetType), assetType)
+ fpair, err := l.FormatExchangeCurrency(p, assetType)
+ if err != nil {
+ return nil, err
+ }
+
+ tickerNew, err := ticker.GetTicker(l.Name, fpair, assetType)
if err != nil {
return l.UpdateTicker(p, assetType)
}
@@ -239,7 +242,11 @@ func (l *Lbank) FetchOrderbook(currency currency.Pair, assetType asset.Item) (*o
// UpdateOrderbook updates and returns the orderbook for a currency pair
func (l *Lbank) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
orderBook := new(orderbook.Base)
- a, err := l.GetMarketDepths(l.FormatExchangeCurrency(p, assetType).String(), "60", "1")
+ fpair, err := l.FormatExchangeCurrency(p, assetType)
+ if err != nil {
+ return nil, err
+ }
+ a, err := l.GetMarketDepths(fpair.String(), "60", "1")
if err != nil {
return orderBook, err
}
@@ -336,8 +343,14 @@ func (l *Lbank) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
fmt.Errorf("%s order side is not supported by the exchange",
s.Side)
}
+
+ fpair, err := l.FormatExchangeCurrency(s.Pair, asset.Spot)
+ if err != nil {
+ return resp, err
+ }
+
tempResp, err := l.CreateOrder(
- l.FormatExchangeCurrency(s.Pair, asset.Spot).String(),
+ fpair.String(),
s.Side.String(),
s.Amount,
s.Price)
@@ -360,8 +373,11 @@ func (l *Lbank) ModifyOrder(action *order.Modify) (string, error) {
// CancelOrder cancels an order by its corresponding ID number
func (l *Lbank) CancelOrder(order *order.Cancel) error {
- _, err := l.RemoveOrder(l.FormatExchangeCurrency(order.Pair,
- order.AssetType).String(), order.ID)
+ fpair, err := l.FormatExchangeCurrency(order.Pair, order.AssetType)
+ if err != nil {
+ return err
+ }
+ _, err = l.RemoveOrder(fpair.String(), order.ID)
return err
}
@@ -440,7 +456,11 @@ func (l *Lbank) GetOrderInfo(orderID string) (order.Detail, error) {
return resp, err
}
resp.Exchange = l.Name
- resp.Pair = currency.NewPairFromString(key)
+ resp.Pair, err = currency.NewPairFromString(key)
+ if err != nil {
+ return order.Detail{}, err
+ }
+
if strings.EqualFold(tempResp.Orders[0].Type, order.Buy.String()) {
resp.Side = order.Buy
} else {
@@ -508,11 +528,6 @@ func (l *Lbank) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdraw.R
return nil, common.ErrFunctionNotSupported
}
-// GetWebsocket returns a pointer to the exchange websocket
-func (l *Lbank) GetWebsocket() (*wshandler.Websocket, error) {
- return nil, common.ErrNotYetImplemented
-}
-
// GetActiveOrders retrieves any orders that are active/open
func (l *Lbank) GetActiveOrders(getOrdersRequest *order.GetOrdersRequest) ([]order.Detail, error) {
var finalResp []order.Detail
@@ -529,7 +544,11 @@ func (l *Lbank) GetActiveOrders(getOrdersRequest *order.GetOrdersRequest) ([]ord
return finalResp, err
}
resp.Exchange = l.Name
- resp.Pair = currency.NewPairFromString(key)
+ resp.Pair, err = currency.NewPairFromString(key)
+ if err != nil {
+ return nil, err
+ }
+
if strings.EqualFold(tempResp.Orders[0].Type, order.Buy.String()) {
resp.Side = order.Buy
} else {
@@ -587,25 +606,37 @@ func (l *Lbank) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest) ([]ord
var resp order.Detail
var tempCurr currency.Pairs
if len(getOrdersRequest.Pairs) == 0 {
- tempCurr = l.GetEnabledPairs(asset.Spot)
+ var err error
+ tempCurr, err = l.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return nil, err
+ }
} else {
tempCurr = getOrdersRequest.Pairs
}
for a := range tempCurr {
- p := l.FormatExchangeCurrency(tempCurr[a], asset.Spot).String()
+ fpair, err := l.FormatExchangeCurrency(tempCurr[a], asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+
b := int64(1)
- tempResp, err := l.QueryOrderHistory(p, strconv.FormatInt(b, 10), "200")
+ tempResp, err := l.QueryOrderHistory(fpair.String(), strconv.FormatInt(b, 10), "200")
if err != nil {
return finalResp, err
}
for len(tempResp.Orders) != 0 {
- tempResp, err = l.QueryOrderHistory(p, strconv.FormatInt(b, 10), "200")
+ tempResp, err = l.QueryOrderHistory(fpair.String(), strconv.FormatInt(b, 10), "200")
if err != nil {
return finalResp, err
}
for x := 0; x < len(tempResp.Orders); x++ {
resp.Exchange = l.Name
- resp.Pair = currency.NewPairFromString(tempResp.Orders[x].Symbol)
+ resp.Pair, err = currency.NewPairFromString(tempResp.Orders[x].Symbol)
+ if err != nil {
+ return nil, err
+ }
+
if strings.EqualFold(tempResp.Orders[x].Type, order.Buy.String()) {
resp.Side = order.Buy
} else {
@@ -674,18 +705,28 @@ func (l *Lbank) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
// GetAllOpenOrderID returns all open orders by currency pairs
func (l *Lbank) getAllOpenOrderID() (map[string][]string, error) {
- allPairs := l.GetEnabledPairs(asset.Spot)
+ allPairs, err := l.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return nil, err
+ }
resp := make(map[string][]string)
for a := range allPairs {
- p := l.FormatExchangeCurrency(allPairs[a], asset.Spot).String()
+ fpair, err := l.FormatExchangeCurrency(allPairs[a], asset.Spot)
+ if err != nil {
+ return nil, err
+ }
b := int64(1)
- tempResp, err := l.GetOpenOrders(p, strconv.FormatInt(b, 10), "200")
+ tempResp, err := l.GetOpenOrders(fpair.String(),
+ strconv.FormatInt(b, 10),
+ "200")
if err != nil {
return resp, err
}
tempData := len(tempResp.Orders)
for tempData != 0 {
- tempResp, err = l.GetOpenOrders(p, strconv.FormatInt(b, 10), "200")
+ tempResp, err = l.GetOpenOrders(fpair.String(),
+ strconv.FormatInt(b, 10),
+ "200")
if err != nil {
return resp, err
}
@@ -695,7 +736,8 @@ func (l *Lbank) getAllOpenOrderID() (map[string][]string, error) {
}
for c := 0; c < tempData; c++ {
- resp[p] = append(resp[p], tempResp.Orders[c].OrderID)
+ resp[fpair.String()] = append(resp[fpair.String()],
+ tempResp.Orders[c].OrderID)
}
tempData = len(tempResp.Orders)
b++
@@ -704,28 +746,6 @@ func (l *Lbank) getAllOpenOrderID() (map[string][]string, error) {
return resp, nil
}
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func (l *Lbank) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- return common.ErrNotYetImplemented
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func (l *Lbank) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- return common.ErrNotYetImplemented
-}
-
-// AuthenticateWebsocket authenticates it
-func (l *Lbank) AuthenticateWebsocket() error {
- return common.ErrNotYetImplemented
-}
-
-// GetSubscriptions gets subscriptions
-func (l *Lbank) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return nil, common.ErrNotYetImplemented
-}
-
// ValidateCredentials validates current credentials used for wrapper
// functionality
func (l *Lbank) ValidateCredentials() error {
@@ -758,7 +778,12 @@ func (l *Lbank) GetHistoricCandles(pair currency.Pair, a asset.Item, start, end
}
}
- data, err := l.GetKlines(l.FormatExchangeCurrency(pair, a).String(),
+ formattedPair, err := l.FormatExchangeCurrency(pair, a)
+ if err != nil {
+ return kline.Item{}, err
+ }
+
+ data, err := l.GetKlines(formattedPair.String(),
strconv.FormatInt(int64(l.Features.Enabled.Kline.ResultLimit), 10),
l.FormatExchangeKlineInterval(interval),
strconv.FormatInt(start.Unix(), 10))
@@ -803,8 +828,13 @@ func (l *Lbank) GetHistoricCandlesExtended(pair currency.Pair, a asset.Item, sta
}
dates := kline.CalcDateRanges(start, end, interval, l.Features.Enabled.Kline.ResultLimit)
+ formattedPair, err := l.FormatExchangeCurrency(pair, a)
+ if err != nil {
+ return kline.Item{}, err
+ }
+
for x := range dates {
- data, err := l.GetKlines(l.FormatExchangeCurrency(pair, a).String(),
+ data, err := l.GetKlines(formattedPair.String(),
strconv.FormatInt(int64(l.Features.Enabled.Kline.ResultLimit), 10),
l.FormatExchangeKlineInterval(interval),
strconv.FormatInt(dates[x].Start.UTC().Unix(), 10))
diff --git a/exchanges/localbitcoins/localbitcoins_wrapper.go b/exchanges/localbitcoins/localbitcoins_wrapper.go
index bbd6c3d2..e9ac3184 100644
--- a/exchanges/localbitcoins/localbitcoins_wrapper.go
+++ b/exchanges/localbitcoins/localbitcoins_wrapper.go
@@ -21,7 +21,6 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -57,18 +56,11 @@ func (l *LocalBitcoins) SetDefaults() {
l.API.CredentialsValidator.RequiresKey = true
l.API.CredentialsValidator.RequiresSecret = true
- l.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- },
-
- UseGlobalFormat: true,
- RequestFormat: ¤cy.PairFormat{
- Uppercase: true,
- },
- ConfigFormat: ¤cy.PairFormat{
- Uppercase: true,
- },
+ requestFmt := ¤cy.PairFormat{Uppercase: true}
+ configFmt := ¤cy.PairFormat{Uppercase: true}
+ err := l.SetGlobalPairsManager(requestFmt, configFmt, asset.Spot)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
}
l.Features = exchange.Features{
@@ -110,7 +102,6 @@ func (l *LocalBitcoins) Setup(exch *config.ExchangeConfig) error {
l.SetEnabled(false)
return nil
}
-
return l.SetupDefaults(exch)
}
@@ -161,18 +152,24 @@ func (l *LocalBitcoins) UpdateTradablePairs(forceUpdate bool) error {
if err != nil {
return err
}
- return l.UpdatePairs(currency.NewPairsFromStrings(pairs), asset.Spot, false, forceUpdate)
+ p, err := currency.NewPairsFromStrings(pairs)
+ if err != nil {
+ return err
+ }
+ return l.UpdatePairs(p, asset.Spot, false, forceUpdate)
}
// UpdateTicker updates and returns the ticker for a currency pair
func (l *LocalBitcoins) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
- tickerPrice := new(ticker.Price)
tick, err := l.GetTicker()
if err != nil {
- return tickerPrice, err
+ return nil, err
}
- pairs := l.GetEnabledPairs(assetType)
+ pairs, err := l.GetEnabledPairs(assetType)
+ if err != nil {
+ return nil, err
+ }
for i := range pairs {
curr := pairs[i].Quote.String()
if _, ok := tick[curr]; !ok {
@@ -182,10 +179,12 @@ func (l *LocalBitcoins) UpdateTicker(p currency.Pair, assetType asset.Item) (*ti
tp.Pair = pairs[i]
tp.Last = tick[curr].Avg24h
tp.Volume = tick[curr].VolumeBTC
+ tp.ExchangeName = l.Name
+ tp.AssetType = assetType
- err = ticker.ProcessTicker(l.Name, &tp, assetType)
+ err = ticker.ProcessTicker(&tp)
if err != nil {
- log.Error(log.Ticker, err)
+ return nil, err
}
}
@@ -432,11 +431,6 @@ func (l *LocalBitcoins) WithdrawFiatFundsToInternationalBank(withdrawRequest *wi
return nil, common.ErrFunctionNotSupported
}
-// GetWebsocket returns a pointer to the exchange websocket
-func (l *LocalBitcoins) GetWebsocket() (*wshandler.Websocket, error) {
- return nil, common.ErrFunctionNotSupported
-}
-
// GetFeeByType returns an estimate of fee based on type of transaction
func (l *LocalBitcoins) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (!l.AllowAuthenticatedRequest() || l.SkipAuthCheck) && // Todo check connection status
@@ -453,6 +447,11 @@ func (l *LocalBitcoins) GetActiveOrders(getOrdersRequest *order.GetOrdersRequest
return nil, err
}
+ format, err := l.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return nil, err
+ }
+
var orders []order.Detail
for i := range resp {
orderDate, err := time.Parse(time.RFC3339, resp[i].Data.CreatedAt)
@@ -480,7 +479,7 @@ func (l *LocalBitcoins) GetActiveOrders(getOrdersRequest *order.GetOrdersRequest
Side: side,
Pair: currency.NewPairWithDelimiter(currency.BTC.String(),
resp[i].Data.Currency,
- l.GetPairFormat(asset.Spot, false).Delimiter),
+ format.Delimiter),
Exchange: l.Name,
})
}
@@ -514,6 +513,11 @@ func (l *LocalBitcoins) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest
}
allTrades = append(allTrades, resp...)
+ format, err := l.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return nil, err
+ }
+
var orders []order.Detail
for i := range allTrades {
orderDate, err := time.Parse(time.RFC3339, allTrades[i].Data.CreatedAt)
@@ -557,7 +561,7 @@ func (l *LocalBitcoins) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest
Status: order.Status(status),
Pair: currency.NewPairWithDelimiter(currency.BTC.String(),
allTrades[i].Data.Currency,
- l.GetPairFormat(asset.Spot, false).Delimiter),
+ format.Delimiter),
Exchange: l.Name,
})
}
@@ -569,28 +573,6 @@ func (l *LocalBitcoins) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest
return orders, nil
}
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func (l *LocalBitcoins) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- return common.ErrFunctionNotSupported
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func (l *LocalBitcoins) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- return common.ErrFunctionNotSupported
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func (l *LocalBitcoins) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return nil, common.ErrFunctionNotSupported
-}
-
-// AuthenticateWebsocket sends an authentication message to the websocket
-func (l *LocalBitcoins) AuthenticateWebsocket() error {
- return common.ErrFunctionNotSupported
-}
-
// ValidateCredentials validates current credentials used for wrapper
// functionality
func (l *LocalBitcoins) ValidateCredentials() error {
diff --git a/exchanges/okcoin/okcoin_test.go b/exchanges/okcoin/okcoin_test.go
index 35dc8a68..9669a609 100644
--- a/exchanges/okcoin/okcoin_test.go
+++ b/exchanges/okcoin/okcoin_test.go
@@ -6,7 +6,6 @@ import (
"net/http"
"os"
"strings"
- "sync"
"testing"
"time"
@@ -21,7 +20,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/okgroup"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -69,14 +68,12 @@ func TestMain(m *testing.M) {
okcoinConfig.API.Credentials.Secret = apiSecret
okcoinConfig.API.Credentials.ClientID = passphrase
okcoinConfig.API.Endpoints.WebsocketURL = o.API.Endpoints.WebsocketURL
+ o.Websocket = sharedtestvalues.NewTestWebsocket()
err = o.Setup(okcoinConfig)
if err != nil {
log.Fatal("OKCoin setup error", err)
}
testSetupRan = true
- o.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- o.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
-
os.Exit(m.Run())
}
@@ -752,33 +749,27 @@ func TestGetMarginTransactionDetails(t *testing.T) {
// Will log in if credentials are present
func TestSendWsMessages(t *testing.T) {
if !o.Websocket.IsEnabled() && !o.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
- t.Skip(wshandler.WebsocketNotEnabled)
+ t.Skip(stream.WebsocketNotEnabled)
}
var ok bool
- o.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: o.Name,
- URL: o.Websocket.GetWebsocketURL(),
- Verbose: o.Verbose,
- ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
- ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
- }
var dialer websocket.Dialer
- err := o.WebsocketConn.Dial(&dialer, http.Header{})
+ err := o.Websocket.Conn.Dial(&dialer, http.Header{})
if err != nil {
t.Fatal(err)
}
- wg := sync.WaitGroup{}
- wg.Add(1)
- go o.WsReadData(&wg)
- wg.Wait()
-
- subscription := wshandler.WebsocketChannelSubscription{
- Channel: "badChannel",
+ go o.WsReadData()
+ subscriptions := []stream.ChannelSubscription{
+ {
+ Channel: "badChannel",
+ },
+ }
+ err = o.Subscribe(subscriptions)
+ if err != nil {
+ t.Fatal(err)
}
- o.Subscribe(subscription)
response := <-o.Websocket.DataHandler
if err, ok = response.(error); ok && err != nil {
- if !strings.Contains(response.(error).Error(), subscription.Channel) {
+ if !strings.Contains(response.(error).Error(), subscriptions[0].Channel) {
t.Error("Expecting OKEX error - 30040 message: Channel badChannel doesn't exist")
}
}
@@ -1099,18 +1090,24 @@ func TestGetOrderbook(t *testing.T) {
}
func TestGetHistoricCandles(t *testing.T) {
- currencyPair := currency.NewPairFromString("BTCUSDT")
+ currencyPair, err := currency.NewPairFromString("BTCUSDT")
+ if err != nil {
+ t.Fatal(err)
+ }
startTime := time.Unix(1588636800, 0)
- _, err := o.GetHistoricCandles(currencyPair, asset.Spot, startTime, time.Now(), kline.OneMin)
+ _, err = o.GetHistoricCandles(currencyPair, asset.Spot, startTime, time.Now(), kline.OneMin)
if err != nil {
t.Fatal(err)
}
}
func TestGetHistoricCandlesExtended(t *testing.T) {
- currencyPair := currency.NewPairFromString("BTCUSDT")
+ currencyPair, err := currency.NewPairFromString("BTCUSDT")
+ if err != nil {
+ t.Fatal(err)
+ }
startTime := time.Unix(1588636800, 0)
- _, err := o.GetHistoricCandlesExtended(currencyPair, asset.Spot, startTime, time.Now(), kline.OneMin)
+ _, err = o.GetHistoricCandlesExtended(currencyPair, asset.Spot, startTime, time.Now(), kline.OneMin)
if err != nil {
t.Fatal(err)
}
diff --git a/exchanges/okcoin/okcoin_wrapper.go b/exchanges/okcoin/okcoin_wrapper.go
index 934493b0..a65fe8a9 100644
--- a/exchanges/okcoin/okcoin_wrapper.go
+++ b/exchanges/okcoin/okcoin_wrapper.go
@@ -15,8 +15,8 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/okgroup"
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
)
@@ -55,23 +55,9 @@ func (o *OKCoin) SetDefaults() {
o.API.CredentialsValidator.RequiresSecret = true
o.API.CredentialsValidator.RequiresClientID = true
- o.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- asset.Margin,
- },
-
- UseGlobalFormat: true,
- RequestFormat: ¤cy.PairFormat{
- Uppercase: true,
- Delimiter: "-",
- },
-
- ConfigFormat: ¤cy.PairFormat{
- Uppercase: true,
- Delimiter: "-",
- },
- }
+ requestFmt := ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter}
+ configFmt := ¤cy.PairFormat{Uppercase: true, Delimiter: currency.DashDelimiter}
+ o.SetGlobalPairsManager(requestFmt, configFmt, asset.Spot, asset.Margin)
o.Features = exchange.Features{
Supports: exchange.FeaturesSupported{
@@ -152,7 +138,7 @@ func (o *OKCoin) SetDefaults() {
o.API.Endpoints.URL = okCoinAPIURL
o.API.Endpoints.WebsocketURL = okCoinWebsocketURL
o.APIVersion = okCoinAPIVersion
- o.Websocket = wshandler.New()
+ o.Websocket = stream.New()
o.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
o.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
o.WebsocketOrderbookBufferLimit = exchange.DefaultWebsocketOrderbookBufferLimit
@@ -178,25 +164,56 @@ func (o *OKCoin) Run() {
}
forceUpdate := false
- delim := o.GetPairFormat(asset.Spot, false).Delimiter
- if !common.StringDataContains(o.CurrencyPairs.GetPairs(asset.Spot,
- true).Strings(), delim) ||
- !common.StringDataContains(o.CurrencyPairs.GetPairs(asset.Spot,
- false).Strings(), delim) {
- enabledPairs := currency.NewPairsFromStrings(
- []string{currency.BTC.String() + delim + currency.USD.String()},
- )
- log.Warnf(log.ExchangeSys,
- "Enabled pairs for %v reset due to config upgrade, please enable the ones you would like again.\n",
- o.Name)
- forceUpdate = true
+ format, err := o.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update currencies. Err: %s\n",
+ o.Name,
+ err)
+ return
+ }
+ enabled, err := o.CurrencyPairs.GetPairs(asset.Spot, true)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update currencies. Err: %s\n",
+ o.Name,
+ err)
+ return
+ }
- err := o.UpdatePairs(enabledPairs, asset.Spot, true, true)
+ avail, err := o.CurrencyPairs.GetPairs(asset.Spot, false)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update currencies. Err: %s\n",
+ o.Name,
+ err)
+ return
+ }
+
+ if !common.StringDataContains(enabled.Strings(), format.Delimiter) ||
+ !common.StringDataContains(avail.Strings(), format.Delimiter) {
+ var p currency.Pairs
+ p, err = currency.NewPairsFromStrings([]string{currency.BTC.String() +
+ format.Delimiter +
+ currency.USD.String()})
if err != nil {
log.Errorf(log.ExchangeSys,
"%s failed to update currencies.\n",
o.Name)
- return
+ } else {
+ log.Warnf(log.ExchangeSys,
+ "Enabled pairs for %v reset due to config upgrade, please enable the ones you would like again.\n",
+ o.Name)
+ forceUpdate = true
+
+ err = o.UpdatePairs(p, asset.Spot, true, true)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update currencies. Err: %s\n",
+ o.Name,
+ err)
+ return
+ }
}
}
@@ -204,7 +221,7 @@ func (o *OKCoin) Run() {
return
}
- err := o.UpdateTradablePairs(forceUpdate)
+ err = o.UpdateTradablePairs(forceUpdate)
if err != nil {
log.Errorf(log.ExchangeSys,
"%s failed to update tradable pairs. Err: %s",
@@ -220,10 +237,15 @@ func (o *OKCoin) FetchTradablePairs(asset asset.Item) ([]string, error) {
return nil, err
}
+ format, err := o.GetPairFormat(asset, false)
+ if err != nil {
+ return nil, err
+ }
+
var pairs []string
for x := range prods {
pairs = append(pairs, prods[x].BaseCurrency+
- o.GetPairFormat(asset, false).Delimiter+
+ format.Delimiter+
prods[x].QuoteCurrency)
}
@@ -237,40 +259,45 @@ func (o *OKCoin) UpdateTradablePairs(forceUpdate bool) error {
if err != nil {
return err
}
-
- return o.UpdatePairs(currency.NewPairsFromStrings(pairs),
- asset.Spot, false, forceUpdate)
+ p, err := currency.NewPairsFromStrings(pairs)
+ if err != nil {
+ return err
+ }
+ return o.UpdatePairs(p, asset.Spot, false, forceUpdate)
}
// UpdateTicker updates and returns the ticker for a currency pair
func (o *OKCoin) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
- var tickerData ticker.Price
if assetType == asset.Spot {
resp, err := o.GetSpotAllTokenPairsInformation()
if err != nil {
return nil, err
}
- pairs := o.GetEnabledPairs(assetType)
+ pairs, err := o.GetEnabledPairs(assetType)
+ if err != nil {
+ return nil, err
+ }
for i := range pairs {
for j := range resp {
if !pairs[i].Equal(resp[j].InstrumentID) {
continue
}
- tickerData = ticker.Price{
- Last: resp[j].Last,
- High: resp[j].High24h,
- Low: resp[j].Low24h,
- Bid: resp[j].BestBid,
- Ask: resp[j].BestAsk,
- Volume: resp[j].BaseVolume24h,
- QuoteVolume: resp[j].QuoteVolume24h,
- Open: resp[j].Open24h,
- Pair: pairs[i],
- LastUpdated: resp[j].Timestamp,
- }
- err = ticker.ProcessTicker(o.Name, &tickerData, assetType)
+
+ err = ticker.ProcessTicker(&ticker.Price{
+ Last: resp[j].Last,
+ High: resp[j].High24h,
+ Low: resp[j].Low24h,
+ Bid: resp[j].BestBid,
+ Ask: resp[j].BestAsk,
+ Volume: resp[j].BaseVolume24h,
+ QuoteVolume: resp[j].QuoteVolume24h,
+ Open: resp[j].Open24h,
+ Pair: pairs[i],
+ LastUpdated: resp[j].Timestamp,
+ ExchangeName: o.Name,
+ AssetType: assetType})
if err != nil {
- log.Error(log.Ticker, err)
+ return nil, err
}
}
}
@@ -295,12 +322,17 @@ func (o *OKCoin) GetHistoricCandles(pair currency.Pair, a asset.Item, start, end
}
}
+ formattedPair, err := o.FormatExchangeCurrency(pair, a)
+ if err != nil {
+ return kline.Item{}, err
+ }
+
req := &okgroup.GetMarketDataRequest{
Asset: a,
Start: start.UTC().Format(time.RFC3339),
End: end.UTC().Format(time.RFC3339),
Granularity: o.FormatExchangeKlineInterval(interval),
- InstrumentID: o.FormatExchangeCurrency(pair, a).String(),
+ InstrumentID: formattedPair.String(),
}
candles, err := o.GetMarketData(req)
@@ -371,13 +403,18 @@ func (o *OKCoin) GetHistoricCandlesExtended(pair currency.Pair, a asset.Item, st
}
dates := kline.CalcDateRanges(start, end, interval, o.Features.Enabled.Kline.ResultLimit)
+ formattedPair, err := o.FormatExchangeCurrency(pair, a)
+ if err != nil {
+ return kline.Item{}, err
+ }
+
for x := range dates {
req := &okgroup.GetMarketDataRequest{
Asset: a,
Start: dates[x].Start.UTC().Format(time.RFC3339),
End: dates[x].End.UTC().Format(time.RFC3339),
Granularity: o.FormatExchangeKlineInterval(interval),
- InstrumentID: o.FormatExchangeCurrency(pair, a).String(),
+ InstrumentID: formattedPair.String(),
}
candles, err := o.GetMarketData(req)
diff --git a/exchanges/okex/okex_test.go b/exchanges/okex/okex_test.go
index b617be77..9985f346 100644
--- a/exchanges/okex/okex_test.go
+++ b/exchanges/okex/okex_test.go
@@ -8,7 +8,6 @@ import (
"os"
"strconv"
"strings"
- "sync"
"testing"
"time"
@@ -23,7 +22,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/okgroup"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -70,13 +69,11 @@ func TestMain(m *testing.M) {
okexConfig.API.Credentials.Secret = apiSecret
okexConfig.API.Credentials.ClientID = passphrase
okexConfig.API.Endpoints.WebsocketURL = o.API.Endpoints.WebsocketURL
+ o.Websocket = sharedtestvalues.NewTestWebsocket()
err = o.Setup(okexConfig)
if err != nil {
log.Fatal("Okex setup error", err)
}
- o.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- o.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
-
os.Exit(m.Run())
}
@@ -532,9 +529,12 @@ func TestGetSpotMarketData(t *testing.T) {
}
func TestGetHistoricCandles(t *testing.T) {
- currencyPair := currency.NewPairFromString("BTCUSDT")
+ currencyPair, err := currency.NewPairFromString("BTCUSDT")
+ if err != nil {
+ t.Fatal(err)
+ }
startTime := time.Unix(1588636800, 0)
- _, err := o.GetHistoricCandles(currencyPair, asset.Spot, startTime, time.Now(), kline.OneMin)
+ _, err = o.GetHistoricCandles(currencyPair, asset.Spot, startTime, time.Now(), kline.OneMin)
if err != nil {
t.Fatal(err)
}
@@ -549,7 +549,10 @@ func TestGetHistoricCandles(t *testing.T) {
t.Fatal("unexpected result")
}
- swapPair := currency.NewPairFromString("BTC-USD_SWAP")
+ swapPair, err := currency.NewPairFromString("BTC-USD_SWAP")
+ if err != nil {
+ t.Fatal(err)
+ }
_, err = o.GetHistoricCandles(swapPair, asset.PerpetualSwap, startTime, time.Now(), kline.OneDay)
if err != nil {
t.Fatal(err)
@@ -557,9 +560,12 @@ func TestGetHistoricCandles(t *testing.T) {
}
func TestGetHistoricCandlesExtended(t *testing.T) {
- currencyPair := currency.NewPairFromString("BTCUSDT")
+ currencyPair, err := currency.NewPairFromString("BTCUSDT")
+ if err != nil {
+ t.Fatal(err)
+ }
startTime := time.Unix(1588636800, 0)
- _, err := o.GetHistoricCandlesExtended(currencyPair, asset.Spot, startTime, time.Now(), kline.OneMin)
+ _, err = o.GetHistoricCandlesExtended(currencyPair, asset.Spot, startTime, time.Now(), kline.OneMin)
if err != nil {
t.Fatal(err)
}
@@ -1461,33 +1467,27 @@ func TestGetETTSettlementPriceHistory(t *testing.T) {
// Will log in if credentials are present
func TestSendWsMessages(t *testing.T) {
if !o.Websocket.IsEnabled() && !o.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
- t.Skip(wshandler.WebsocketNotEnabled)
+ t.Skip(stream.WebsocketNotEnabled)
}
var ok bool
- o.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: o.Name,
- URL: o.Websocket.GetWebsocketURL(),
- Verbose: o.Verbose,
- ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
- ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
- }
var dialer websocket.Dialer
- err := o.WebsocketConn.Dial(&dialer, http.Header{})
+ err := o.Websocket.Conn.Dial(&dialer, http.Header{})
if err != nil {
t.Fatal(err)
}
- wg := sync.WaitGroup{}
- wg.Add(1)
- go o.WsReadData(&wg)
- wg.Wait()
-
- subscription := wshandler.WebsocketChannelSubscription{
- Channel: "badChannel",
+ go o.WsReadData()
+ subscriptions := []stream.ChannelSubscription{
+ {
+ Channel: "badChannel",
+ },
+ }
+ err = o.Subscribe(subscriptions)
+ if err != nil {
+ t.Fatal(err)
}
- o.Subscribe(subscription)
response := <-o.Websocket.DataHandler
if err, ok = response.(error); ok && err != nil {
- if !strings.Contains(response.(error).Error(), subscription.Channel) {
+ if !strings.Contains(response.(error).Error(), subscriptions[0].Channel) {
t.Error("Expecting OKEX error - 30040 message: Channel badChannel doesn't exist")
}
}
@@ -1821,6 +1821,13 @@ func TestGetOrderbook(t *testing.T) {
}
}
+func TestUpdateTradablePairs(t *testing.T) {
+ err := o.UpdateTradablePairs(true)
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
func TestWsSubscribe(t *testing.T) {
pressXToJSON := []byte(`{"event":"subscribe","channel":"spot/ticker:ETH-USDT"}`)
err := o.WsHandleData(pressXToJSON)
diff --git a/exchanges/okex/okex_wrapper.go b/exchanges/okex/okex_wrapper.go
index 2f83ac16..989dee68 100644
--- a/exchanges/okex/okex_wrapper.go
+++ b/exchanges/okex/okex_wrapper.go
@@ -17,16 +17,11 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/okgroup"
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
)
-const (
- delimiterDash = "-"
- delimiterUnderscore = "_"
-)
-
// GetDefaultConfig returns a default exchange config
func (o *OKEX) GetDefaultConfig() (*config.ExchangeConfig, error) {
o.SetDefaults()
@@ -61,32 +56,43 @@ func (o *OKEX) SetDefaults() {
o.API.CredentialsValidator.RequiresSecret = true
o.API.CredentialsValidator.RequiresClientID = true
- o.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- asset.Futures,
- asset.PerpetualSwap,
- asset.Index,
- },
- }
// Same format used for perpetual swap and futures
- fmt1 := currency.PairStore{
+ futures := currency.PairStore{
RequestFormat: ¤cy.PairFormat{
Uppercase: true,
- Delimiter: delimiterDash,
+ Delimiter: currency.DashDelimiter,
},
ConfigFormat: ¤cy.PairFormat{
Uppercase: true,
- Delimiter: delimiterUnderscore,
+ Delimiter: currency.UnderscoreDelimiter,
},
}
- o.CurrencyPairs.Store(asset.PerpetualSwap, fmt1)
- o.CurrencyPairs.Store(asset.Futures, fmt1)
+
+ swap := currency.PairStore{
+ RequestFormat: ¤cy.PairFormat{
+ Uppercase: true,
+ Delimiter: currency.DashDelimiter,
+ },
+ ConfigFormat: ¤cy.PairFormat{
+ Uppercase: true,
+ Delimiter: currency.UnderscoreDelimiter,
+ },
+ }
+
+ err := o.StoreAssetPairFormat(asset.PerpetualSwap, swap)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
+ }
+
+ err = o.StoreAssetPairFormat(asset.Futures, futures)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
+ }
index := currency.PairStore{
RequestFormat: ¤cy.PairFormat{
Uppercase: true,
- Delimiter: delimiterDash,
+ Delimiter: currency.DashDelimiter,
},
ConfigFormat: ¤cy.PairFormat{
Uppercase: true,
@@ -96,15 +102,23 @@ func (o *OKEX) SetDefaults() {
spot := currency.PairStore{
RequestFormat: ¤cy.PairFormat{
Uppercase: true,
- Delimiter: delimiterDash,
+ Delimiter: currency.DashDelimiter,
},
ConfigFormat: ¤cy.PairFormat{
Uppercase: true,
- Delimiter: delimiterDash,
+ Delimiter: currency.DashDelimiter,
},
}
- o.CurrencyPairs.Store(asset.Spot, spot)
- o.CurrencyPairs.Store(asset.Index, index)
+
+ err = o.StoreAssetPairFormat(asset.Spot, spot)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
+ }
+
+ err = o.StoreAssetPairFormat(asset.Index, index)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
+ }
o.Features = exchange.Features{
Supports: exchange.FeaturesSupported{
@@ -184,7 +198,7 @@ func (o *OKEX) SetDefaults() {
o.API.Endpoints.URLDefault = okExAPIURL
o.API.Endpoints.URL = okExAPIURL
o.API.Endpoints.WebsocketURL = OkExWebsocketURL
- o.Websocket = wshandler.New()
+ o.Websocket = stream.New()
o.APIVersion = okExAPIVersion
o.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
o.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
@@ -210,24 +224,57 @@ func (o *OKEX) Run() {
o.API.Endpoints.WebsocketURL)
}
- delim := o.GetPairFormat(asset.Spot, false).Delimiter
- forceUpdate := false
- if !common.StringDataContains(o.GetEnabledPairs(asset.Spot).Strings(), delim) ||
- !common.StringDataContains(o.GetAvailablePairs(asset.Spot).Strings(), delim) {
- forceUpdate = true
- enabledPairs := currency.NewPairsFromStrings(
- []string{currency.BTC.String() + delim + currency.USDT.String()},
- )
- log.Warnf(log.ExchangeSys,
- "Enabled pairs for %v reset due to config upgrade, please enable the ones you would like again.",
- o.Name)
+ format, err := o.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update tradable pairs. Err: %s",
+ o.Name,
+ err)
+ return
+ }
- err := o.UpdatePairs(enabledPairs, asset.Spot, true, forceUpdate)
+ forceUpdate := false
+ enabled, err := o.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update tradable pairs. Err: %s",
+ o.Name,
+ err)
+ return
+ }
+
+ avail, err := o.GetAvailablePairs(asset.Spot)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update tradable pairs. Err: %s",
+ o.Name,
+ err)
+ return
+ }
+
+ if !common.StringDataContains(enabled.Strings(), format.Delimiter) ||
+ !common.StringDataContains(avail.Strings(), format.Delimiter) {
+ forceUpdate = true
+ var p currency.Pairs
+ p, err = currency.NewPairsFromStrings([]string{currency.BTC.String() +
+ format.Delimiter +
+ currency.USDT.String()})
if err != nil {
log.Errorf(log.ExchangeSys,
"%s failed to update currencies.\n",
o.Name)
- return
+ } else {
+ log.Warnf(log.ExchangeSys,
+ "Enabled pairs for %v reset due to config upgrade, please enable the ones you would like again.",
+ o.Name)
+
+ err = o.UpdatePairs(p, asset.Spot, true, forceUpdate)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update currencies.\n",
+ o.Name)
+ return
+ }
}
}
@@ -235,7 +282,7 @@ func (o *OKEX) Run() {
return
}
- err := o.UpdateTradablePairs(forceUpdate)
+ err = o.UpdateTradablePairs(forceUpdate)
if err != nil {
log.Errorf(log.ExchangeSys,
"%s failed to update tradable pairs. Err: %s",
@@ -247,6 +294,12 @@ func (o *OKEX) Run() {
// FetchTradablePairs returns a list of the exchanges tradable pairs
func (o *OKEX) FetchTradablePairs(i asset.Item) ([]string, error) {
var pairs []string
+
+ format, err := o.GetPairFormat(i, false)
+ if err != nil {
+ return nil, err
+ }
+
switch i {
case asset.Spot:
prods, err := o.GetSpotTokenPairDetails()
@@ -258,7 +311,7 @@ func (o *OKEX) FetchTradablePairs(i asset.Item) ([]string, error) {
pairs = append(pairs,
currency.NewPairWithDelimiter(prods[x].BaseCurrency,
prods[x].QuoteCurrency,
- o.GetPairFormat(i, false).Delimiter).String())
+ format.Delimiter).String())
}
return pairs, nil
case asset.Futures:
@@ -268,9 +321,8 @@ func (o *OKEX) FetchTradablePairs(i asset.Item) ([]string, error) {
}
for x := range prods {
- p := strings.Split(prods[x].InstrumentID, delimiterDash)
- pairs = append(pairs,
- p[0]+delimiterDash+p[1]+o.GetPairFormat(i, false).Delimiter+p[2])
+ p := strings.Split(prods[x].InstrumentID, currency.DashDelimiter)
+ pairs = append(pairs, p[0]+currency.DashDelimiter+p[1]+format.Delimiter+p[2])
}
return pairs, nil
@@ -283,9 +335,9 @@ func (o *OKEX) FetchTradablePairs(i asset.Item) ([]string, error) {
for x := range prods {
pairs = append(pairs,
prods[x].UnderlyingIndex+
- delimiterDash+
+ currency.DashDelimiter+
prods[x].QuoteCurrency+
- o.GetPairFormat(i, false).Delimiter+
+ format.Delimiter+
"SWAP")
}
return pairs, nil
@@ -300,34 +352,62 @@ func (o *OKEX) FetchTradablePairs(i asset.Item) ([]string, error) {
// UpdateTradablePairs updates the exchanges available pairs and stores
// them in the exchanges config
func (o *OKEX) UpdateTradablePairs(forceUpdate bool) error {
- for x := range o.CurrencyPairs.AssetTypes {
- if o.CurrencyPairs.AssetTypes[x] == asset.Index {
+ assets := o.CurrencyPairs.GetAssetTypes()
+ for x := range assets {
+ if assets[x] == asset.Index {
// Update from futures
continue
}
- pairs, err := o.FetchTradablePairs(o.CurrencyPairs.AssetTypes[x])
+ pairs, err := o.FetchTradablePairs(assets[x])
if err != nil {
return err
}
- if o.CurrencyPairs.AssetTypes[x] == asset.Futures {
+ if assets[x] == asset.Futures {
var indexPairs []string
+ var futuresContracts []string
for i := range pairs {
- indexPairs = append(indexPairs,
- strings.Split(pairs[i], delimiterUnderscore)[0])
+ item := strings.Split(pairs[i], currency.UnderscoreDelimiter)[0]
+ futuresContracts = append(futuresContracts, pairs[i])
+ if common.StringDataContains(indexPairs, item) {
+ continue
+ }
+ indexPairs = append(indexPairs, item)
}
- err = o.UpdatePairs(currency.NewPairsFromStrings(indexPairs),
- asset.Index,
- false,
- forceUpdate)
+ var indexPair currency.Pairs
+ indexPair, err = currency.NewPairsFromStrings(indexPairs)
if err != nil {
return err
}
+
+ err = o.UpdatePairs(indexPair, asset.Index, false, forceUpdate)
+ if err != nil {
+ return err
+ }
+
+ var futurePairs currency.Pairs
+ for i := range futuresContracts {
+ var c currency.Pair
+ c, err = currency.NewPairDelimiter(futuresContracts[i], currency.UnderscoreDelimiter)
+ if err != nil {
+ return err
+ }
+ futurePairs = append(futurePairs, c)
+ }
+
+ err = o.UpdatePairs(futurePairs, asset.Futures, false, forceUpdate)
+ if err != nil {
+ return err
+ }
+ continue
+ }
+ p, err := currency.NewPairsFromStrings(pairs)
+ if err != nil {
+ return err
}
- err = o.UpdatePairs(currency.NewPairsFromStrings(pairs),
- o.CurrencyPairs.AssetTypes[x], false, forceUpdate)
+ err = o.UpdatePairs(p, assets[x], false, forceUpdate)
if err != nil {
return err
}
@@ -344,25 +424,32 @@ func (o *OKEX) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Pric
if err != nil {
return tickerPrice, err
}
+
+ enabled, err := o.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+
for j := range resp {
- if !o.GetEnabledPairs(assetType).Contains(resp[j].InstrumentID, true) {
+ if !enabled.Contains(resp[j].InstrumentID, true) {
continue
}
- tickerPrice = &ticker.Price{
- Last: resp[j].Last,
- High: resp[j].High24h,
- Low: resp[j].Low24h,
- Bid: resp[j].BestBid,
- Ask: resp[j].BestAsk,
- Volume: resp[j].BaseVolume24h,
- QuoteVolume: resp[j].QuoteVolume24h,
- Open: resp[j].Open24h,
- Pair: resp[j].InstrumentID,
- LastUpdated: resp[j].Timestamp,
- }
- err = ticker.ProcessTicker(o.Name, tickerPrice, assetType)
+
+ err = ticker.ProcessTicker(&ticker.Price{
+ Last: resp[j].Last,
+ High: resp[j].High24h,
+ Low: resp[j].Low24h,
+ Bid: resp[j].BestBid,
+ Ask: resp[j].BestAsk,
+ Volume: resp[j].BaseVolume24h,
+ QuoteVolume: resp[j].QuoteVolume24h,
+ Open: resp[j].Open24h,
+ Pair: resp[j].InstrumentID,
+ LastUpdated: resp[j].Timestamp,
+ ExchangeName: o.Name,
+ AssetType: assetType})
if err != nil {
- log.Error(log.Ticker, err)
+ return nil, err
}
}
@@ -372,27 +459,33 @@ func (o *OKEX) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Pric
return nil, err
}
+ enabled, err := o.GetEnabledPairs(asset.PerpetualSwap)
+ if err != nil {
+ return nil, err
+ }
+
for j := range resp {
- p := strings.Split(resp[j].InstrumentID, delimiterDash)
- nC := currency.NewPairWithDelimiter(p[0]+delimiterDash+p[1],
+ p := strings.Split(resp[j].InstrumentID, currency.DashDelimiter)
+ nC := currency.NewPairWithDelimiter(p[0]+currency.DashDelimiter+p[1],
p[2],
- delimiterUnderscore)
- if !o.GetEnabledPairs(assetType).Contains(nC, true) {
+ currency.UnderscoreDelimiter)
+ if !enabled.Contains(nC, true) {
continue
}
- tickerPrice = &ticker.Price{
- Last: resp[j].Last,
- High: resp[j].High24H,
- Low: resp[j].Low24H,
- Bid: resp[j].BestBid,
- Ask: resp[j].BestAsk,
- Volume: resp[j].Volume24H,
- Pair: nC,
- LastUpdated: resp[j].Timestamp,
- }
- err = ticker.ProcessTicker(o.Name, tickerPrice, assetType)
+
+ err = ticker.ProcessTicker(&ticker.Price{
+ Last: resp[j].Last,
+ High: resp[j].High24H,
+ Low: resp[j].Low24H,
+ Bid: resp[j].BestBid,
+ Ask: resp[j].BestAsk,
+ Volume: resp[j].Volume24H,
+ Pair: nC,
+ LastUpdated: resp[j].Timestamp,
+ ExchangeName: o.Name,
+ AssetType: assetType})
if err != nil {
- log.Error(log.Ticker, err)
+ return nil, err
}
}
@@ -402,27 +495,33 @@ func (o *OKEX) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Pric
return nil, err
}
+ enabled, err := o.GetEnabledPairs(asset.Futures)
+ if err != nil {
+ return nil, err
+ }
+
for j := range resp {
- p := strings.Split(resp[j].InstrumentID, delimiterDash)
- nC := currency.NewPairWithDelimiter(p[0]+delimiterDash+p[1],
+ p := strings.Split(resp[j].InstrumentID, currency.DashDelimiter)
+ nC := currency.NewPairWithDelimiter(p[0]+currency.DashDelimiter+p[1],
p[2],
- delimiterUnderscore)
- if !o.GetEnabledPairs(assetType).Contains(nC, true) {
+ currency.UnderscoreDelimiter)
+ if !enabled.Contains(nC, true) {
continue
}
- tickerPrice = &ticker.Price{
- Last: resp[j].Last,
- High: resp[j].High24h,
- Low: resp[j].Low24h,
- Bid: resp[j].BestBid,
- Ask: resp[j].BestAsk,
- Volume: resp[j].Volume24h,
- Pair: nC,
- LastUpdated: resp[j].Timestamp,
- }
- err = ticker.ProcessTicker(o.Name, tickerPrice, assetType)
+
+ err = ticker.ProcessTicker(&ticker.Price{
+ Last: resp[j].Last,
+ High: resp[j].High24h,
+ Low: resp[j].Low24h,
+ Bid: resp[j].BestBid,
+ Ask: resp[j].BestAsk,
+ Volume: resp[j].Volume24h,
+ Pair: nC,
+ LastUpdated: resp[j].Timestamp,
+ ExchangeName: o.Name,
+ AssetType: assetType})
if err != nil {
- log.Error(log.Ticker, err)
+ return nil, err
}
}
}
@@ -450,12 +549,17 @@ func (o *OKEX) GetHistoricCandles(pair currency.Pair, a asset.Item, start, end t
}
}
+ formattedPair, err := o.FormatExchangeCurrency(pair, a)
+ if err != nil {
+ return kline.Item{}, err
+ }
+
req := &okgroup.GetMarketDataRequest{
Asset: a,
Start: start.UTC().Format(time.RFC3339),
End: end.UTC().Format(time.RFC3339),
Granularity: o.FormatExchangeKlineInterval(interval),
- InstrumentID: o.FormatExchangeCurrency(pair, a).String(),
+ InstrumentID: formattedPair.String(),
}
candles, err := o.GetMarketData(req)
@@ -527,13 +631,17 @@ func (o *OKEX) GetHistoricCandlesExtended(pair currency.Pair, a asset.Item, star
}
dates := kline.CalcDateRanges(start, end, interval, o.Features.Enabled.Kline.ResultLimit)
+ formattedPair, err := o.FormatExchangeCurrency(pair, a)
+ if err != nil {
+ return kline.Item{}, err
+ }
for x := range dates {
req := &okgroup.GetMarketDataRequest{
Asset: a,
Start: dates[x].Start.UTC().Format(time.RFC3339),
End: dates[x].End.UTC().Format(time.RFC3339),
Granularity: o.FormatExchangeKlineInterval(interval),
- InstrumentID: o.FormatExchangeCurrency(pair, a).String(),
+ InstrumentID: formattedPair.String(),
}
candles, err := o.GetMarketData(req)
diff --git a/exchanges/okgroup/okgroup.go b/exchanges/okgroup/okgroup.go
index c0eb4c1d..9137f9c0 100644
--- a/exchanges/okgroup/okgroup.go
+++ b/exchanges/okgroup/okgroup.go
@@ -18,7 +18,6 @@ import (
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
)
@@ -89,8 +88,7 @@ var errMissValue = errors.New("warning - resp value is missing from exchange")
// OKGroup is the overaching type across the all of OKEx's exchange methods
type OKGroup struct {
exchange.Base
- ExchangeName string
- WebsocketConn *wshandler.WebsocketConnection
+ ExchangeName string
// Spot and contract market error codes as per https://www.okex.com/rest_request.html
ErrorCodes map[string]error
// Stores for corresponding variable checks
diff --git a/exchanges/okgroup/okgroup_types.go b/exchanges/okgroup/okgroup_types.go
index 3f70b66d..66d6a611 100644
--- a/exchanges/okgroup/okgroup_types.go
+++ b/exchanges/okgroup/okgroup_types.go
@@ -1317,19 +1317,22 @@ type WebsocketDataResponse struct {
type WebsocketTickerData struct {
Table string `json:"table"`
Data []struct {
- BaseVolume24h float64 `json:"base_volume_24h,string"`
- BestAsk float64 `json:"best_ask,string"`
- BestAskSize float64 `json:"best_ask_size,string"`
- BestBid float64 `json:"best_bid,string"`
- BestBidSize float64 `json:"best_bid_size,string"`
- High24h float64 `json:"high_24h,string"`
- InstrumentID string `json:"instrument_id"`
- Last float64 `json:"last,string"`
- LastQty float64 `json:"last_qty,string"`
- Low24h float64 `json:"low_24h,string"`
- Open24h float64 `json:"open_24h,string"`
- QuoteVolume24h float64 `json:"quote_volume_24h,string"`
- Timestamp time.Time `json:"timestamp"`
+ BaseVolume24h float64 `json:"base_volume_24h,string"`
+ BestAsk float64 `json:"best_ask,string"`
+ BestAskSize float64 `json:"best_ask_size,string"`
+ BestBid float64 `json:"best_bid,string"`
+ BestBidSize float64 `json:"best_bid_size,string"`
+ High24h float64 `json:"high_24h,string"`
+ InstrumentID string `json:"instrument_id"`
+ Last float64 `json:"last,string"`
+ LastQty float64 `json:"last_qty,string"`
+ Low24h float64 `json:"low_24h,string"`
+ Open24h float64 `json:"open_24h,string"`
+ QuoteVolume24h float64 `json:"quote_volume_24h,string"`
+ Timestamp time.Time `json:"timestamp"`
+ ContractVolume24h float64 `json:"volume_24h,string"`
+ TokenVolume24h float64 `json:"volume_token_24h,string"`
+ OpenInterest float64 `json:"open_interest,string"`
} `json:"data"`
}
@@ -1343,6 +1346,8 @@ type WebsocketTradeResponse struct {
Side string `json:"side"`
Timestamp time.Time `json:"timestamp"`
TradeID string `json:"trade_id"`
+ // Quantity - Futures amount is sent as a separate json field
+ Quantity float64 `json:"qty,string"`
} `json:"data"`
}
diff --git a/exchanges/okgroup/okgroup_websocket.go b/exchanges/okgroup/okgroup_websocket.go
index e2a69298..9e97877b 100644
--- a/exchanges/okgroup/okgroup_websocket.go
+++ b/exchanges/okgroup/okgroup_websocket.go
@@ -18,9 +18,9 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wsorderbook"
"github.com/thrasher-corp/gocryptotrader/log"
)
@@ -147,6 +147,8 @@ const (
delimiterColon = ":"
delimiterDash = "-"
delimiterUnderscore = "_"
+
+ maxConnByteLen = 4096
)
// orderbookMutex Ensures if two entries arrive at once, only one can be
@@ -176,10 +178,12 @@ var defaultSwapSubscribedChannels = []string{okGroupWsSwapDepth,
// WsConnect initiates a websocket connection
func (o *OKGroup) WsConnect() error {
if !o.Websocket.IsEnabled() || !o.IsEnabled() {
- return errors.New(wshandler.WebsocketNotEnabled)
+ return errors.New(stream.WebsocketNotEnabled)
}
var dialer websocket.Dialer
- err := o.WebsocketConn.Dial(&dialer, http.Header{})
+ dialer.ReadBufferSize = 8192
+ dialer.WriteBufferSize = 8192
+ err := o.Websocket.Conn.Dial(&dialer, http.Header{})
if err != nil {
return err
}
@@ -187,9 +191,8 @@ func (o *OKGroup) WsConnect() error {
log.Debugf(log.ExchangeSys, "Successful connection to %v\n",
o.Websocket.GetWebsocketURL())
}
- wg := sync.WaitGroup{}
- wg.Add(1)
- go o.WsReadData(&wg)
+
+ go o.WsReadData()
if o.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
err = o.WsLogin()
if err != nil {
@@ -200,10 +203,11 @@ func (o *OKGroup) WsConnect() error {
}
}
- o.GenerateDefaultSubscriptions()
- // Ensures that we start the routines and we dont race when shutdown occurs
- wg.Wait()
- return nil
+ subs, err := o.GenerateDefaultSubscriptions()
+ if err != nil {
+ return err
+ }
+ return o.Websocket.SubscribeToChannels(subs)
}
// WsLogin sends a login request to websocket to enable access to authenticated endpoints
@@ -225,7 +229,7 @@ func (o *OKGroup) WsLogin() error {
base64,
},
}
- err := o.WebsocketConn.SendJSONMessage(request)
+ _, err := o.Websocket.Conn.SendMessageReturnResponse("login", request)
if err != nil {
o.Websocket.SetCanUseAuthenticatedEndpoints(false)
return err
@@ -234,28 +238,18 @@ func (o *OKGroup) WsLogin() error {
}
// WsReadData receives and passes on websocket messages for processing
-func (o *OKGroup) WsReadData(wg *sync.WaitGroup) {
+func (o *OKGroup) WsReadData() {
o.Websocket.Wg.Add(1)
- defer func() {
- o.Websocket.Wg.Done()
- }()
- wg.Done()
+ defer o.Websocket.Wg.Done()
for {
- select {
- case <-o.Websocket.ShutdownC:
+ resp := o.Websocket.Conn.ReadMessage()
+ if resp.Raw == nil {
return
- default:
- resp, err := o.WebsocketConn.ReadMessage()
- if err != nil {
- o.Websocket.ReadMessageErrors <- err
- return
- }
- o.Websocket.TrafficAlert <- struct{}{}
- err = o.WsHandleData(resp.Raw)
- if err != nil {
- o.Websocket.DataHandler <- err
- }
+ }
+ err := o.WsHandleData(resp.Raw)
+ if err != nil {
+ o.Websocket.DataHandler <- err
}
}
}
@@ -283,7 +277,9 @@ func (o *OKGroup) WsHandleData(respRaw []byte) error {
case okGroupWsOrder:
return o.wsProcessOrder(respRaw)
}
- o.Websocket.DataHandler <- wshandler.UnhandledMessageWarning{Message: o.Name + wshandler.UnhandledMessage + string(respRaw)}
+ o.Websocket.DataHandler <- stream.UnhandledMessageWarning{
+ Message: o.Name + stream.UnhandledMessage + string(respRaw),
+ }
return nil
}
@@ -299,7 +295,9 @@ func (o *OKGroup) WsHandleData(respRaw []byte) error {
err = json.Unmarshal(respRaw, &eventResponse)
if err == nil && eventResponse.Event != "" {
if eventResponse.Event == "login" {
- o.Websocket.SetCanUseAuthenticatedEndpoints(eventResponse.Success)
+ if o.Websocket.Match.Incoming("login") {
+ o.Websocket.SetCanUseAuthenticatedEndpoints(eventResponse.Success)
+ }
}
if o.Verbose {
log.Debug(log.ExchangeSys,
@@ -365,6 +363,16 @@ func (o *OKGroup) wsProcessOrder(respRaw []byte) error {
Err: err,
}
}
+
+ pair, err := currency.NewPairFromString(resp.Data[i].InstrumentID)
+ if err != nil {
+ o.Websocket.DataHandler <- order.ClassificationError{
+ Exchange: o.Name,
+ OrderID: resp.Data[i].OrderID,
+ Err: err,
+ }
+ }
+
o.Websocket.DataHandler <- &order.Detail{
ImmediateOrCancel: resp.Data[i].OrderType == 3,
FillOrKill: resp.Data[i].OrderType == 2,
@@ -380,7 +388,7 @@ func (o *OKGroup) wsProcessOrder(respRaw []byte) error {
Status: oStatus,
AssetType: o.GetAssetTypeFromTableName(resp.Table),
Date: resp.Data[i].CreatedAt,
- Pair: currency.NewPairFromString(resp.Data[i].InstrumentID),
+ Pair: pair,
}
}
return nil
@@ -393,23 +401,36 @@ func (o *OKGroup) wsProcessTickers(respRaw []byte) error {
if err != nil {
return err
}
+ a := o.GetAssetTypeFromTableName(response.Table)
for i := range response.Data {
- a := o.GetAssetTypeFromTableName(response.Table)
+ f := strings.Split(response.Data[i].InstrumentID, delimiterDash)
+
var c currency.Pair
switch a {
case asset.Futures, asset.PerpetualSwap:
- f := strings.Split(response.Data[i].InstrumentID, delimiterDash)
- c = currency.NewPairWithDelimiter(f[0]+delimiterDash+f[1], f[2], delimiterUnderscore)
+ c = currency.NewPairWithDelimiter(f[0]+delimiterDash+f[1],
+ f[2],
+ delimiterUnderscore)
default:
- f := strings.Split(response.Data[i].InstrumentID, delimiterDash)
c = currency.NewPairWithDelimiter(f[0], f[1], delimiterDash)
}
+
+ baseVolume := response.Data[i].BaseVolume24h
+ if response.Data[i].ContractVolume24h != 0 {
+ baseVolume = response.Data[i].ContractVolume24h
+ }
+
+ quoteVolume := response.Data[i].QuoteVolume24h
+ if response.Data[i].TokenVolume24h != 0 {
+ quoteVolume = response.Data[i].TokenVolume24h
+ }
+
o.Websocket.DataHandler <- &ticker.Price{
ExchangeName: o.Name,
Open: response.Data[i].Open24h,
Close: response.Data[i].Last,
- Volume: response.Data[i].BaseVolume24h,
- QuoteVolume: response.Data[i].QuoteVolume24h,
+ Volume: baseVolume,
+ QuoteVolume: quoteVolume,
High: response.Data[i].High24h,
Low: response.Data[i].Low24h,
Bid: response.Data[i].BestBid,
@@ -430,17 +451,21 @@ func (o *OKGroup) wsProcessTrades(respRaw []byte) error {
if err != nil {
return err
}
+
+ a := o.GetAssetTypeFromTableName(response.Table)
for i := range response.Data {
- a := o.GetAssetTypeFromTableName(response.Table)
+ f := strings.Split(response.Data[i].InstrumentID, delimiterDash)
+
var c currency.Pair
switch a {
case asset.Futures, asset.PerpetualSwap:
- f := strings.Split(response.Data[i].InstrumentID, delimiterDash)
- c = currency.NewPairWithDelimiter(f[0]+delimiterDash+f[1], f[2], delimiterUnderscore)
+ c = currency.NewPairWithDelimiter(f[0]+delimiterDash+f[1],
+ f[2],
+ delimiterUnderscore)
default:
- f := strings.Split(response.Data[i].InstrumentID, delimiterDash)
c = currency.NewPairWithDelimiter(f[0], f[1], delimiterDash)
}
+
tSide, err := order.StringToOrderSide(response.Data[i].Side)
if err != nil {
o.Websocket.DataHandler <- order.ClassificationError{
@@ -448,8 +473,14 @@ func (o *OKGroup) wsProcessTrades(respRaw []byte) error {
Err: err,
}
}
- o.Websocket.DataHandler <- wshandler.TradeData{
- Amount: response.Data[i].Size,
+
+ amount := response.Data[i].Size
+ if response.Data[i].Quantity != 0 {
+ amount = response.Data[i].Quantity
+ }
+
+ o.Websocket.DataHandler <- stream.TradeData{
+ Amount: amount,
AssetType: o.GetAssetTypeFromTableName(response.Table),
CurrencyPair: c,
Exchange: o.Name,
@@ -468,15 +499,18 @@ func (o *OKGroup) wsProcessCandles(respRaw []byte) error {
if err != nil {
return err
}
+
+ a := o.GetAssetTypeFromTableName(response.Table)
for i := range response.Data {
- a := o.GetAssetTypeFromTableName(response.Table)
+ f := strings.Split(response.Data[i].InstrumentID, delimiterDash)
+
var c currency.Pair
switch a {
case asset.Futures, asset.PerpetualSwap:
- f := strings.Split(response.Data[i].InstrumentID, delimiterDash)
- c = currency.NewPairWithDelimiter(f[0]+delimiterDash+f[1], f[2], delimiterUnderscore)
+ c = currency.NewPairWithDelimiter(f[0]+delimiterDash+f[1],
+ f[2],
+ delimiterUnderscore)
default:
- f := strings.Split(response.Data[i].InstrumentID, delimiterDash)
c = currency.NewPairWithDelimiter(f[0], f[1], delimiterDash)
}
@@ -489,13 +523,9 @@ func (o *OKGroup) wsProcessCandles(respRaw []byte) error {
}
candleIndex := strings.LastIndex(response.Table, okGroupWsCandle)
- secondIndex := strings.LastIndex(response.Table, "0s")
- candleInterval := ""
- if candleIndex > 0 || secondIndex > 0 {
- candleInterval = response.Table[candleIndex+len(okGroupWsCandle) : secondIndex]
- }
+ candleInterval := response.Table[candleIndex+len(okGroupWsCandle):]
- klineData := wshandler.KlineData{
+ klineData := stream.KlineData{
AssetType: o.GetAssetTypeFromTableName(response.Table),
Pair: c,
Exchange: o.Name,
@@ -522,7 +552,6 @@ func (o *OKGroup) wsProcessCandles(respRaw []byte) error {
if err != nil {
return err
}
-
o.Websocket.DataHandler <- klineData
}
return nil
@@ -537,22 +566,27 @@ func (o *OKGroup) WsProcessOrderBook(respRaw []byte) error {
}
orderbookMutex.Lock()
defer orderbookMutex.Unlock()
+ a := o.GetAssetTypeFromTableName(response.Table)
for i := range response.Data {
- a := o.GetAssetTypeFromTableName(response.Table)
+ f := strings.Split(response.Data[i].InstrumentID, delimiterDash)
+
var c currency.Pair
switch a {
case asset.Futures, asset.PerpetualSwap:
- f := strings.Split(response.Data[i].InstrumentID, delimiterDash)
- c = currency.NewPairWithDelimiter(f[0]+delimiterDash+f[1], f[2], delimiterUnderscore)
+ c = currency.NewPairWithDelimiter(f[0]+delimiterDash+f[1],
+ f[2],
+ delimiterUnderscore)
default:
- f := strings.Split(response.Data[i].InstrumentID, delimiterDash)
c = currency.NewPairWithDelimiter(f[0], f[1], delimiterDash)
}
if response.Action == okGroupWsOrderbookPartial {
err := o.WsProcessPartialOrderBook(&response.Data[i], c, a)
if err != nil {
- o.wsResubscribeToOrderbook(&response)
+ err2 := o.wsResubscribeToOrderbook(&response)
+ if err2 != nil {
+ o.Websocket.DataHandler <- err2
+ }
return err
}
} else if response.Action == okGroupWsOrderbookUpdate {
@@ -561,7 +595,10 @@ func (o *OKGroup) WsProcessOrderBook(respRaw []byte) error {
}
err := o.WsProcessUpdateOrderbook(&response.Data[i], c, a)
if err != nil {
- o.wsResubscribeToOrderbook(&response)
+ err2 := o.wsResubscribeToOrderbook(&response)
+ if err2 != nil {
+ o.Websocket.DataHandler <- err2
+ }
return err
}
}
@@ -569,28 +606,34 @@ func (o *OKGroup) WsProcessOrderBook(respRaw []byte) error {
return nil
}
-func (o *OKGroup) wsResubscribeToOrderbook(response *WebsocketOrderBooksData) {
+func (o *OKGroup) wsResubscribeToOrderbook(response *WebsocketOrderBooksData) error {
+ a := o.GetAssetTypeFromTableName(response.Table)
for i := range response.Data {
- a := o.GetAssetTypeFromTableName(response.Table)
+ f := strings.Split(response.Data[i].InstrumentID, delimiterDash)
+
var c currency.Pair
switch a {
case asset.Futures, asset.PerpetualSwap:
- f := strings.Split(response.Data[i].InstrumentID, delimiterDash)
c = currency.NewPairWithDelimiter(f[0]+delimiterDash+f[1], f[2], delimiterDash)
default:
- f := strings.Split(response.Data[i].InstrumentID, delimiterDash)
c = currency.NewPairWithDelimiter(f[0], f[1], delimiterDash)
}
- channelToResubscribe := wshandler.WebsocketChannelSubscription{
+ channelToResubscribe := &stream.ChannelSubscription{
Channel: response.Table,
Currency: c,
+ Asset: a,
+ }
+ err := o.Websocket.ResubscribeToChannel(channelToResubscribe)
+ if err != nil {
+ return fmt.Errorf("%s resubscribe to orderbook error %s", o.Name, err)
}
- o.Websocket.ResubscribeToChannel(channelToResubscribe)
}
+ return nil
}
-// AppendWsOrderbookItems adds websocket orderbook data bid/asks into an orderbook item array
+// AppendWsOrderbookItems adds websocket orderbook data bid/asks into an
+// orderbook item array
func (o *OKGroup) AppendWsOrderbookItems(entries [][]interface{}) ([]orderbook.Item, error) {
var items []orderbook.Item
for j := range entries {
@@ -607,8 +650,8 @@ func (o *OKGroup) AppendWsOrderbookItems(entries [][]interface{}) ([]orderbook.I
return items, nil
}
-// WsProcessPartialOrderBook takes websocket orderbook data and creates an orderbook
-// Calculates checksum to ensure it is valid
+// WsProcessPartialOrderBook takes websocket orderbook data and creates an
+// orderbook Calculates checksum to ensure it is valid
func (o *OKGroup) WsProcessPartialOrderBook(wsEventData *WebsocketOrderBook, instrument currency.Pair, a asset.Item) error {
signedChecksum := o.CalculatePartialOrderbookChecksum(wsEventData)
if signedChecksum != wsEventData.Checksum {
@@ -642,24 +685,14 @@ func (o *OKGroup) WsProcessPartialOrderBook(wsEventData *WebsocketOrderBook, ins
Pair: instrument,
ExchangeName: o.Name,
}
-
- err = o.Websocket.Orderbook.LoadSnapshot(&newOrderBook)
- if err != nil {
- return err
- }
-
- o.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
- Exchange: o.Name,
- Asset: a,
- Pair: instrument,
- }
- return nil
+ return o.Websocket.Orderbook.LoadSnapshot(&newOrderBook)
}
// WsProcessUpdateOrderbook updates an existing orderbook using websocket data
-// After merging WS data, it will sort, validate and finally update the existing orderbook
+// After merging WS data, it will sort, validate and finally update the existing
+// orderbook
func (o *OKGroup) WsProcessUpdateOrderbook(wsEventData *WebsocketOrderBook, instrument currency.Pair, a asset.Item) error {
- update := wsorderbook.WebsocketOrderbookUpdate{
+ update := buffer.Update{
Asset: a,
Pair: instrument,
UpdateTime: wsEventData.Timestamp,
@@ -690,13 +723,6 @@ func (o *OKGroup) WsProcessUpdateOrderbook(wsEventData *WebsocketOrderBook, inst
wsEventData.InstrumentID)
return errors.New("checksum failed")
}
-
- o.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
- Exchange: o.Name,
- Asset: a,
- Pair: instrument,
- }
-
return nil
}
@@ -750,95 +776,134 @@ func (o *OKGroup) CalculateUpdateOrderbookChecksum(orderbookData *orderbook.Base
// GenerateDefaultSubscriptions Adds default subscriptions to websocket to be
// handled by ManageSubscriptions()
-func (o *OKGroup) GenerateDefaultSubscriptions() {
- var subscriptions []wshandler.WebsocketChannelSubscription
+func (o *OKGroup) GenerateDefaultSubscriptions() ([]stream.ChannelSubscription, error) {
+ var subscriptions []stream.ChannelSubscription
assets := o.GetAssetTypes()
for x := range assets {
- enabledCurrencies := o.GetEnabledPairs(assets[x])
- if len(enabledCurrencies) == 0 {
- continue
+ pairs, err := o.GetEnabledPairs(assets[x])
+ if err != nil {
+ return nil, err
}
switch assets[x] {
case asset.Spot:
- for i := range enabledCurrencies {
- for y := range defaultSpotSubscribedChannels {
- subscriptions = append(subscriptions,
- wshandler.WebsocketChannelSubscription{
- Channel: defaultSpotSubscribedChannels[y],
- Currency: o.FormatExchangeCurrency(enabledCurrencies[i],
- asset.Spot),
- })
- }
+ channels := defaultSpotSubscribedChannels
+ if o.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
+ channels = append(channels,
+ okGroupWsSpotMarginAccount,
+ okGroupWsSpotAccount,
+ okGroupWsSpotOrder)
}
- if o.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
- subscriptions = append(subscriptions,
- wshandler.WebsocketChannelSubscription{
- Channel: okGroupWsSpotMarginAccount,
- },
- wshandler.WebsocketChannelSubscription{
- Channel: okGroupWsSpotAccount,
- },
- wshandler.WebsocketChannelSubscription{
- Channel: okGroupWsSpotOrder,
- })
+ for i := range pairs {
+ p, err := o.FormatExchangeCurrency(pairs[i], asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+ for y := range channels {
+ subscriptions = append(subscriptions,
+ stream.ChannelSubscription{
+ Channel: channels[y],
+ Currency: p,
+ Asset: asset.Spot,
+ })
+ }
}
case asset.Futures:
- for i := range enabledCurrencies {
- for y := range defaultFuturesSubscribedChannels {
+ channels := defaultFuturesSubscribedChannels
+ if o.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
+ channels = append(channels,
+ okGroupWsFuturesAccount,
+ okGroupWsFuturesPosition,
+ okGroupWsFuturesOrder)
+ }
+ var futuresAccountPairs currency.Pairs
+ var futuresAccountCodes currency.Currencies
+
+ for i := range pairs {
+ p, err := o.FormatExchangeCurrency(pairs[i], asset.Futures)
+ if err != nil {
+ return nil, err
+ }
+ for y := range channels {
+ if channels[y] == okGroupWsFuturesAccount {
+ currencyString := strings.Split(pairs[i].String(),
+ currency.UnderscoreDelimiter)[0]
+ newP, err := currency.NewPairFromString(currencyString)
+ if err != nil {
+ return nil, err
+ }
+
+ if !futuresAccountCodes.Contains(newP.Base) {
+ // subscribe to coin-margin futures trading mode
+ subscriptions = append(subscriptions,
+ stream.ChannelSubscription{
+ Channel: channels[y],
+ Currency: currency.NewPair(newP.Base, currency.Code{}),
+ Asset: asset.Futures,
+ })
+ futuresAccountCodes = append(futuresAccountCodes, newP.Base)
+ }
+
+ if newP.Quote != currency.USDT {
+ // Only allows subscription to USDT margined pair
+ continue
+ }
+
+ if !futuresAccountPairs.Contains(newP, true) {
+ subscriptions = append(subscriptions,
+ stream.ChannelSubscription{
+ Channel: channels[y],
+ Currency: newP,
+ Asset: asset.Futures,
+ })
+ futuresAccountPairs = futuresAccountPairs.Add(newP)
+ }
+
+ continue
+ }
subscriptions = append(subscriptions,
- wshandler.WebsocketChannelSubscription{
- Channel: defaultFuturesSubscribedChannels[y],
- Currency: o.FormatExchangeCurrency(enabledCurrencies[i],
- asset.Futures),
+ stream.ChannelSubscription{
+ Channel: channels[y],
+ Currency: p,
+ Asset: asset.Futures,
})
}
}
-
- if o.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
- subscriptions = append(subscriptions,
- wshandler.WebsocketChannelSubscription{
- Channel: okGroupWsFuturesAccount,
- },
- wshandler.WebsocketChannelSubscription{
- Channel: okGroupWsFuturesPosition,
- },
- wshandler.WebsocketChannelSubscription{
- Channel: okGroupWsFuturesOrder,
- })
- }
case asset.PerpetualSwap:
- for i := range enabledCurrencies {
- for y := range defaultSwapSubscribedChannels {
+ channels := defaultSwapSubscribedChannels
+ if o.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
+ channels = append(channels,
+ okGroupWsSwapAccount,
+ okGroupWsSwapPosition,
+ okGroupWsSwapOrder)
+ }
+ for i := range pairs {
+ p, err := o.FormatExchangeCurrency(pairs[i], asset.PerpetualSwap)
+ if err != nil {
+ return nil, err
+ }
+ for y := range channels {
subscriptions = append(subscriptions,
- wshandler.WebsocketChannelSubscription{
- Channel: defaultSwapSubscribedChannels[y],
- Currency: o.FormatExchangeCurrency(enabledCurrencies[i],
- asset.PerpetualSwap),
+ stream.ChannelSubscription{
+ Channel: channels[y],
+ Currency: p,
+ Asset: asset.PerpetualSwap,
})
}
}
-
- if o.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
- subscriptions = append(subscriptions,
- wshandler.WebsocketChannelSubscription{
- Channel: okGroupWsSwapAccount,
- },
- wshandler.WebsocketChannelSubscription{
- Channel: okGroupWsSwapPosition,
- },
- wshandler.WebsocketChannelSubscription{
- Channel: okGroupWsSwapOrder,
- })
- }
case asset.Index:
- for i := range enabledCurrencies {
+ for i := range pairs {
+ p, err := o.FormatExchangeCurrency(pairs[i], asset.Index)
+ if err != nil {
+ return nil, err
+ }
for y := range defaultIndexSubscribedChannels {
subscriptions = append(subscriptions,
- wshandler.WebsocketChannelSubscription{
+ stream.ChannelSubscription{
Channel: defaultIndexSubscribedChannels[y],
- Currency: o.FormatExchangeCurrency(enabledCurrencies[i], asset.Index),
+ Currency: p,
+ Asset: asset.Index,
})
}
}
@@ -846,35 +911,84 @@ func (o *OKGroup) GenerateDefaultSubscriptions() {
o.Websocket.DataHandler <- errors.New("unhandled asset type")
}
}
-
- o.Websocket.SubscribeToChannels(subscriptions)
+ return subscriptions, nil
}
// Subscribe sends a websocket message to receive data from the channel
-func (o *OKGroup) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
- c := channelToSubscribe.Currency.String()
- request := WebsocketEventRequest{
- Operation: "subscribe",
- Arguments: []string{channelToSubscribe.Channel + delimiterColon + c},
- }
- if strings.EqualFold(channelToSubscribe.Channel, okGroupWsSpotAccount) {
- request.Arguments = []string{channelToSubscribe.Channel +
- delimiterColon +
- channelToSubscribe.Currency.Base.String()}
- }
-
- return o.WebsocketConn.SendJSONMessage(request)
+func (o *OKGroup) Subscribe(channelsToSubscribe []stream.ChannelSubscription) error {
+ return o.handleSubscriptions("subscribe", channelsToSubscribe)
}
// Unsubscribe sends a websocket message to stop receiving data from the channel
-func (o *OKGroup) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
+func (o *OKGroup) Unsubscribe(channelsToUnsubscribe []stream.ChannelSubscription) error {
+ return o.handleSubscriptions("unsubscribe", channelsToUnsubscribe)
+}
+
+func (o *OKGroup) handleSubscriptions(operation string, subs []stream.ChannelSubscription) error {
request := WebsocketEventRequest{
- Operation: "unsubscribe",
- Arguments: []string{channelToSubscribe.Channel +
- delimiterColon +
- channelToSubscribe.Currency.String()},
+ Operation: operation,
}
- return o.WebsocketConn.SendJSONMessage(request)
+
+ var channels []stream.ChannelSubscription
+ for i := 0; i < len(subs); i++ {
+ // Temp type to evaluate max byte len after a marshal on batched unsubs
+ temp := WebsocketEventRequest{
+ Operation: operation,
+ }
+ temp.Arguments = make([]string, len(request.Arguments))
+ copy(temp.Arguments, request.Arguments)
+
+ arg := subs[i].Channel + delimiterColon
+ if strings.EqualFold(subs[i].Channel, okGroupWsSpotAccount) {
+ arg += subs[i].Currency.Base.String()
+ } else {
+ arg += subs[i].Currency.String()
+ }
+
+ temp.Arguments = append(temp.Arguments, arg)
+ chunk, err := json.Marshal(request)
+ if err != nil {
+ return err
+ }
+
+ if len(chunk) > maxConnByteLen {
+ // If temp chunk exceeds max byte length determined by the exchange,
+ // commit last payload.
+ i-- // reverse position in range to reuse channel unsubscription on
+ // next iteration
+ err = o.Websocket.Conn.SendJSONMessage(request)
+ if err != nil {
+ return err
+ }
+
+ if operation == "unsubscribe" {
+ o.Websocket.RemoveSuccessfulUnsubscriptions(channels...)
+ } else {
+ o.Websocket.AddSuccessfulSubscriptions(channels...)
+ }
+
+ // Drop prior unsubs and chunked payload args on successful unsubscription
+ channels = nil
+ request.Arguments = nil
+ continue
+ }
+ // Add pending chained items
+ channels = append(channels, subs[i])
+ request.Arguments = temp.Arguments
+ }
+
+ // Commit left overs to payload
+ err := o.Websocket.Conn.SendJSONMessage(request)
+ if err != nil {
+ return err
+ }
+
+ if operation == "unsubscribe" {
+ o.Websocket.RemoveSuccessfulUnsubscriptions(channels...)
+ } else {
+ o.Websocket.AddSuccessfulSubscriptions(channels...)
+ }
+ return nil
}
// GetWsChannelWithoutOrderType takes WebsocketDataResponse.Table and returns
diff --git a/exchanges/okgroup/okgroup_wrapper.go b/exchanges/okgroup/okgroup_wrapper.go
index d26ee67a..225cbd77 100644
--- a/exchanges/okgroup/okgroup_wrapper.go
+++ b/exchanges/okgroup/okgroup_wrapper.go
@@ -15,7 +15,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -35,7 +35,7 @@ func (o *OKGroup) Setup(exch *config.ExchangeConfig) error {
return err
}
- err = o.Websocket.Setup(&wshandler.WebsocketSetup{
+ err = o.Websocket.Setup(&stream.WebsocketSetup{
Enabled: exch.Features.Enabled.Websocket,
Verbose: exch.Verbose,
AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
@@ -46,30 +46,19 @@ func (o *OKGroup) Setup(exch *config.ExchangeConfig) error {
Connector: o.WsConnect,
Subscriber: o.Subscribe,
UnSubscriber: o.Unsubscribe,
+ GenerateSubscriptions: o.GenerateDefaultSubscriptions,
Features: &o.Features.Supports.WebsocketCapabilities,
+ OrderbookBufferLimit: exch.WebsocketOrderbookBufferLimit,
})
if err != nil {
return err
}
- o.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: o.Name,
- URL: o.Websocket.GetWebsocketURL(),
- ProxyURL: o.Websocket.GetProxyAddress(),
- Verbose: o.Verbose,
+ return o.Websocket.SetupNewConnection(stream.ConnectionSetup{
RateLimit: okGroupWsRateLimit,
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
- }
-
- o.Websocket.Orderbook.Setup(
- exch.WebsocketOrderbookBufferLimit,
- false,
- false,
- false,
- false,
- exch.Name)
- return nil
+ })
}
// FetchOrderbook returns orderbook base on the currency pair
@@ -88,8 +77,13 @@ func (o *OKGroup) UpdateOrderbook(p currency.Pair, a asset.Item) (*orderbook.Bas
return orderBook, errors.New("no orderbooks for index")
}
+ fpair, err := o.FormatExchangeCurrency(p, a)
+ if err != nil {
+ return nil, err
+ }
+
orderbookNew, err := o.GetOrderBook(GetOrderBookRequest{
- InstrumentID: o.FormatExchangeCurrency(p, a).String(),
+ InstrumentID: fpair.String(),
}, a)
if err != nil {
return orderBook, err
@@ -268,15 +262,20 @@ func (o *OKGroup) GetExchangeHistory(p currency.Pair, assetType asset.Item, time
}
// SubmitOrder submits a new order
-func (o *OKGroup) SubmitOrder(s *order.Submit) (resp order.SubmitResponse, err error) {
- err = s.Validate()
+func (o *OKGroup) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) {
+ err := s.Validate()
if err != nil {
- return resp, err
+ return order.SubmitResponse{}, err
+ }
+
+ fpair, err := o.FormatExchangeCurrency(s.Pair, s.AssetType)
+ if err != nil {
+ return order.SubmitResponse{}, err
}
request := PlaceOrderRequest{
ClientOID: s.ClientID,
- InstrumentID: o.FormatExchangeCurrency(s.Pair, asset.Spot).String(),
+ InstrumentID: fpair.String(),
Side: s.Side.Lower(),
Type: s.Type.Lower(),
Size: strconv.FormatFloat(s.Amount, 'f', -1, 64),
@@ -287,15 +286,17 @@ func (o *OKGroup) SubmitOrder(s *order.Submit) (resp order.SubmitResponse, err e
orderResponse, err := o.PlaceSpotOrder(&request)
if err != nil {
- return
+ return order.SubmitResponse{}, err
}
+ var resp order.SubmitResponse
resp.IsOrderPlaced = orderResponse.Result
resp.OrderID = orderResponse.OrderID
if s.Type == order.Market {
resp.FullyMatched = true
}
- return
+
+ return resp, nil
}
// ModifyOrder will allow of changing orderbook placement and limit to
@@ -310,11 +311,18 @@ func (o *OKGroup) CancelOrder(orderCancellation *order.Cancel) (err error) {
if err != nil {
return
}
+
+ fpair, err := o.FormatExchangeCurrency(orderCancellation.Pair,
+ orderCancellation.AssetType)
+ if err != nil {
+ return
+ }
+
orderCancellationResponse, err := o.CancelSpotOrder(CancelSpotOrderRequest{
- InstrumentID: o.FormatExchangeCurrency(orderCancellation.Pair,
- asset.Spot).String(),
- OrderID: orderID,
+ InstrumentID: fpair.String(),
+ OrderID: orderID,
})
+
if !orderCancellationResponse.Result {
err = fmt.Errorf("order %d failed to be cancelled",
orderCancellationResponse.OrderID)
@@ -324,26 +332,32 @@ func (o *OKGroup) CancelOrder(orderCancellation *order.Cancel) (err error) {
}
// CancelAllOrders cancels all orders associated with a currency pair
-func (o *OKGroup) CancelAllOrders(orderCancellation *order.Cancel) (resp order.CancelAllResponse, err error) {
+func (o *OKGroup) CancelAllOrders(orderCancellation *order.Cancel) (order.CancelAllResponse, error) {
orderIDs := strings.Split(orderCancellation.ID, ",")
+ resp := order.CancelAllResponse{}
resp.Status = make(map[string]string)
var orderIDNumbers []int64
for i := range orderIDs {
- orderIDNumber, strConvErr := strconv.ParseInt(orderIDs[i], 10, 64)
- if strConvErr != nil {
- resp.Status[orderIDs[i]] = strConvErr.Error()
+ orderIDNumber, err := strconv.ParseInt(orderIDs[i], 10, 64)
+ if err != nil {
+ resp.Status[orderIDs[i]] = err.Error()
continue
}
orderIDNumbers = append(orderIDNumbers, orderIDNumber)
}
+ fpair, err := o.FormatExchangeCurrency(orderCancellation.Pair,
+ orderCancellation.AssetType)
+ if err != nil {
+ return resp, err
+ }
+
cancelOrdersResponse, err := o.CancelMultipleSpotOrders(CancelMultipleSpotOrdersRequest{
- InstrumentID: o.FormatExchangeCurrency(orderCancellation.Pair,
- asset.Spot).String(),
- OrderIDs: orderIDNumbers,
+ InstrumentID: fpair.String(),
+ OrderIDs: orderIDNumbers,
})
if err != nil {
- return
+ return resp, err
}
for x := range cancelOrdersResponse {
@@ -352,7 +366,7 @@ func (o *OKGroup) CancelAllOrders(orderCancellation *order.Cancel) (resp order.C
}
}
- return
+ return resp, err
}
// GetOrderInfo returns information on a current open order
@@ -361,10 +375,20 @@ func (o *OKGroup) GetOrderInfo(orderID string) (resp order.Detail, err error) {
if err != nil {
return
}
+
+ format, err := o.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return resp, err
+ }
+
+ p, err := currency.NewPairDelimiter(mOrder.InstrumentID, format.Delimiter)
+ if err != nil {
+ return resp, err
+ }
+
resp = order.Detail{
- Amount: mOrder.Size,
- Pair: currency.NewPairDelimiter(mOrder.InstrumentID,
- o.GetPairFormat(asset.Spot, false).Delimiter),
+ Amount: mOrder.Size,
+ Pair: p,
Exchange: o.Name,
Date: mOrder.Timestamp,
ExecutedAmount: mOrder.FilledSize,
@@ -424,9 +448,12 @@ func (o *OKGroup) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdraw
// GetActiveOrders retrieves any orders that are active/open
func (o *OKGroup) GetActiveOrders(req *order.GetOrdersRequest) (resp []order.Detail, err error) {
for x := range req.Pairs {
+ fpair, err := o.FormatExchangeCurrency(req.Pairs[x], asset.Spot)
+ if err != nil {
+ return nil, err
+ }
spotOpenOrders, err := o.GetSpotOpenOrders(GetSpotOpenOrdersRequest{
- InstrumentID: o.FormatExchangeCurrency(req.Pairs[x],
- asset.Spot).String(),
+ InstrumentID: fpair.String(),
})
if err != nil {
return resp, err
@@ -454,10 +481,13 @@ func (o *OKGroup) GetActiveOrders(req *order.GetOrdersRequest) (resp []order.Det
// Can Limit response to specific order status
func (o *OKGroup) GetOrderHistory(req *order.GetOrdersRequest) (resp []order.Detail, err error) {
for x := range req.Pairs {
+ fpair, err := o.FormatExchangeCurrency(req.Pairs[x], asset.Spot)
+ if err != nil {
+ return nil, err
+ }
spotOpenOrders, err := o.GetSpotOrders(GetSpotOrdersRequest{
- Status: strings.Join([]string{"filled", "cancelled", "failure"}, "|"),
- InstrumentID: o.FormatExchangeCurrency(req.Pairs[x],
- asset.Spot).String(),
+ Status: strings.Join([]string{"filled", "cancelled", "failure"}, "|"),
+ InstrumentID: fpair.String(),
})
if err != nil {
return resp, err
@@ -481,11 +511,6 @@ func (o *OKGroup) GetOrderHistory(req *order.GetOrdersRequest) (resp []order.Det
return
}
-// GetWebsocket returns a pointer to the exchange websocket
-func (o *OKGroup) GetWebsocket() (*wshandler.Websocket, error) {
- return o.Websocket, nil
-}
-
// GetFeeByType returns an estimate of fee based on type of transaction
func (o *OKGroup) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if !o.AllowAuthenticatedRequest() && // Todo check connection status
@@ -500,25 +525,6 @@ func (o *OKGroup) GetWithdrawCapabilities() uint32 {
return o.GetWithdrawPermissions()
}
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func (o *OKGroup) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- o.Websocket.SubscribeToChannels(channels)
- return nil
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func (o *OKGroup) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- o.Websocket.RemoveSubscribedChannels(channels)
- return nil
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func (o *OKGroup) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return o.Websocket.GetSubscriptions(), nil
-}
-
// AuthenticateWebsocket sends an authentication message to the websocket
func (o *OKGroup) AuthenticateWebsocket() error {
return o.WsLogin()
diff --git a/exchanges/order/order_test.go b/exchanges/order/order_test.go
index 3e83148f..35182379 100644
--- a/exchanges/order/order_test.go
+++ b/exchanges/order/order_test.go
@@ -12,72 +12,67 @@ import (
func TestValidate(t *testing.T) {
testPair := currency.NewPair(currency.BTC, currency.LTC)
tester := []struct {
- Pair currency.Pair
- Side
- Type
- Amount float64
- Price float64
ExpectedErr error
+ Submit *Submit
}{
+ {
+ ExpectedErr: ErrSubmissionIsNil,
+ Submit: nil,
+ }, // nil struct
{
ExpectedErr: ErrPairIsEmpty,
+ Submit: &Submit{},
}, // empty pair
{
- Pair: testPair,
+
ExpectedErr: ErrSideIsInvalid,
+ Submit: &Submit{Pair: testPair},
}, // valid pair but invalid order side
{
- Pair: testPair,
- Side: Buy,
ExpectedErr: ErrTypeIsInvalid,
+ Submit: &Submit{Pair: testPair,
+ Side: Buy},
}, // valid pair and order side but invalid order type
{
- Pair: testPair,
- Side: Sell,
ExpectedErr: ErrTypeIsInvalid,
+ Submit: &Submit{Pair: testPair,
+ Side: Sell},
}, // valid pair and order side but invalid order type
{
- Pair: testPair,
- Side: Bid,
ExpectedErr: ErrTypeIsInvalid,
+ Submit: &Submit{Pair: testPair,
+ Side: Bid},
}, // valid pair and order side but invalid order type
{
- Pair: testPair,
- Side: Ask,
ExpectedErr: ErrTypeIsInvalid,
+ Submit: &Submit{Pair: testPair,
+ Side: Ask},
}, // valid pair and order side but invalid order type
{
- Pair: testPair,
- Side: Ask,
- Type: Market,
ExpectedErr: ErrAmountIsInvalid,
+ Submit: &Submit{Pair: testPair,
+ Side: Ask,
+ Type: Market},
}, // valid pair, order side, type but invalid amount
{
- Pair: testPair,
- Side: Ask,
- Type: Limit,
- Amount: 1,
ExpectedErr: ErrPriceMustBeSetIfLimitOrder,
+ Submit: &Submit{Pair: testPair,
+ Side: Ask,
+ Type: Limit,
+ Amount: 1},
}, // valid pair, order side, type, amount but invalid price
{
- Pair: testPair,
- Side: Ask,
- Type: Limit,
- Amount: 1,
- Price: 1000,
ExpectedErr: nil,
+ Submit: &Submit{Pair: testPair,
+ Side: Ask,
+ Type: Limit,
+ Amount: 1,
+ Price: 1000},
}, // valid order!
}
for x := range tester {
- s := Submit{
- Pair: tester[x].Pair,
- Side: tester[x].Side,
- Type: tester[x].Type,
- Amount: tester[x].Amount,
- Price: tester[x].Price,
- }
- if err := s.Validate(); err != tester[x].ExpectedErr {
+ if err := tester[x].Submit.Validate(); err != tester[x].ExpectedErr {
t.Errorf("Unexpected result. Got: %s, want: %s", err, tester[x].ExpectedErr)
}
}
@@ -465,10 +460,16 @@ var stringsToOrderType = []struct {
{"stop", Stop, nil},
{"STOP", Stop, nil},
{"sToP", Stop, nil},
+ {"sToP LiMit", StopLimit, nil},
+ {"ExchangE sToP Limit", StopLimit, nil},
{"trailing_stop", TrailingStop, nil},
{"TRAILING_STOP", TrailingStop, nil},
{"tRaIlInG_sToP", TrailingStop, nil},
{"tRaIlInG sToP", TrailingStop, nil},
+ {"fOk", FillOrKill, nil},
+ {"exchange fOk", FillOrKill, nil},
+ {"ios", IOS, nil},
+ {"post_ONly", PostOnly, nil},
{"any", AnyType, nil},
{"ANY", AnyType, nil},
{"aNy", AnyType, nil},
@@ -532,6 +533,9 @@ var stringsToOrderStatus = []struct {
{"insufficient_balance", InsufficientBalance, nil},
{"INSUFFICIENT_BALANCE", InsufficientBalance, nil},
{"iNsUfFiCiEnT_bAlAnCe", InsufficientBalance, nil},
+ {"PARTIALLY_CANCELLEd", PartiallyCancelled, nil},
+ {"partially canceLLed", PartiallyCancelled, nil},
+ {"opeN", Open, nil},
{"woahMan", UnknownStatus, errors.New("woahMan not recognised as order status")},
}
@@ -583,6 +587,12 @@ func TestUpdateOrderFromModify(t *testing.T) {
Trades: nil,
}
updated := time.Now()
+
+ pair, err := currency.NewPairFromString("BTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
+
om := Modify{
ImmediateOrCancel: true,
HiddenOrder: true,
@@ -609,7 +619,7 @@ func TestUpdateOrderFromModify(t *testing.T) {
Status: "1",
AssetType: "1",
LastUpdated: updated,
- Pair: currency.NewPairFromString("BTCUSD"),
+ Pair: pair,
Trades: []TradeHistory{},
}
@@ -769,6 +779,12 @@ func TestUpdateOrderFromDetail(t *testing.T) {
Trades: nil,
}
updated := time.Now()
+
+ pair, err := currency.NewPairFromString("BTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
+
om := Detail{
ImmediateOrCancel: true,
HiddenOrder: true,
@@ -795,7 +811,7 @@ func TestUpdateOrderFromDetail(t *testing.T) {
Status: "1",
AssetType: "1",
LastUpdated: updated,
- Pair: currency.NewPairFromString("BTCUSD"),
+ Pair: pair,
Trades: []TradeHistory{},
}
@@ -922,3 +938,14 @@ func TestUpdateOrderFromDetail(t *testing.T) {
t.Error("Failed to update trades")
}
}
+
+func TestClassificationError_Error(t *testing.T) {
+ class := ClassificationError{OrderID: "1337", Exchange: "test", Err: errors.New("test error")}
+ if class.Error() != "test - OrderID: 1337 classification error: test error" {
+ t.Fatal("unexpected output")
+ }
+ class.OrderID = ""
+ if class.Error() != "test - classification error: test error" {
+ t.Fatal("unexpected output")
+ }
+}
diff --git a/exchanges/order/order_types.go b/exchanges/order/order_types.go
index 3c443205..e70b78db 100644
--- a/exchanges/order/order_types.go
+++ b/exchanges/order/order_types.go
@@ -2,7 +2,6 @@ package order
import (
"errors"
- "fmt"
"time"
"github.com/thrasher-corp/gocryptotrader/currency"
@@ -222,9 +221,13 @@ const (
AnyType Type = "ANY"
Limit Type = "LIMIT"
Market Type = "MARKET"
+ PostOnly Type = "POST_ONLY"
ImmediateOrCancel Type = "IMMEDIATE_OR_CANCEL"
Stop Type = "STOP"
+ StopLimit Type = "STOP LIMIT"
TrailingStop Type = "TRAILING_STOP"
+ FillOrKill Type = "FOK"
+ IOS Type = "IOS"
UnknownType Type = "UNKNOWN"
)
@@ -263,15 +266,3 @@ type ClassificationError struct {
OrderID string
Err error
}
-
-func (o *ClassificationError) Error() string {
- if o.OrderID != "" {
- return fmt.Sprintf("%s - OrderID: %s classification error: %v",
- o.Exchange,
- o.OrderID,
- o.Err)
- }
- return fmt.Sprintf("%s - classification error: %v",
- o.Exchange,
- o.Err)
-}
diff --git a/exchanges/order/orders.go b/exchanges/order/orders.go
index cab3812f..44154981 100644
--- a/exchanges/order/orders.go
+++ b/exchanges/order/orders.go
@@ -2,6 +2,7 @@ package order
import (
"errors"
+ "fmt"
"sort"
"strings"
"time"
@@ -582,20 +583,36 @@ func StringToOrderSide(side string) (Side, error) {
// and returning a real Type
func StringToOrderType(oType string) (Type, error) {
switch {
- case strings.EqualFold(oType, Limit.String()):
+ case strings.EqualFold(oType, Limit.String()),
+ strings.EqualFold(oType, "EXCHANGE LIMIT"):
return Limit, nil
- case strings.EqualFold(oType, Market.String()):
+ case strings.EqualFold(oType, Market.String()),
+ strings.EqualFold(oType, "EXCHANGE MARKET"):
return Market, nil
case strings.EqualFold(oType, ImmediateOrCancel.String()),
- strings.EqualFold(oType, "immediate or cancel"):
+ strings.EqualFold(oType, "immediate or cancel"),
+ strings.EqualFold(oType, "IOC"),
+ strings.EqualFold(oType, "EXCHANGE IOC"):
return ImmediateOrCancel, nil
case strings.EqualFold(oType, Stop.String()),
strings.EqualFold(oType, "stop loss"),
- strings.EqualFold(oType, "stop_loss"):
+ strings.EqualFold(oType, "stop_loss"),
+ strings.EqualFold(oType, "EXCHANGE STOP"):
return Stop, nil
+ case strings.EqualFold(oType, StopLimit.String()),
+ strings.EqualFold(oType, "EXCHANGE STOP LIMIT"):
+ return StopLimit, nil
case strings.EqualFold(oType, TrailingStop.String()),
- strings.EqualFold(oType, "trailing stop"):
+ strings.EqualFold(oType, "trailing stop"),
+ strings.EqualFold(oType, "EXCHANGE TRAILING STOP"):
return TrailingStop, nil
+ case strings.EqualFold(oType, FillOrKill.String()),
+ strings.EqualFold(oType, "EXCHANGE FOK"):
+ return FillOrKill, nil
+ case strings.EqualFold(oType, IOS.String()):
+ return IOS, nil
+ case strings.EqualFold(oType, PostOnly.String()):
+ return PostOnly, nil
case strings.EqualFold(oType, AnyType.String()):
return AnyType, nil
default:
@@ -647,3 +664,15 @@ func StringToOrderStatus(status string) (Status, error) {
return UnknownStatus, errors.New(status + " not recognised as order status")
}
}
+
+func (o *ClassificationError) Error() string {
+ if o.OrderID != "" {
+ return fmt.Sprintf("%s - OrderID: %s classification error: %v",
+ o.Exchange,
+ o.OrderID,
+ o.Err)
+ }
+ return fmt.Sprintf("%s - classification error: %v",
+ o.Exchange,
+ o.Err)
+}
diff --git a/exchanges/orderbook/orderbook.go b/exchanges/orderbook/orderbook.go
index aad84f22..66acf0f9 100644
--- a/exchanges/orderbook/orderbook.go
+++ b/exchanges/orderbook/orderbook.go
@@ -31,12 +31,12 @@ func SubscribeOrderbook(exchange string, p currency.Pair, a asset.Item) (dispatc
defer service.RUnlock()
book, ok := service.Books[exchange][p.Base.Item][p.Quote.Item][a]
if !ok {
- return dispatch.Pipe{}, fmt.Errorf("orderbook item not found for %s %s %s",
- exchange,
- p,
- a)
+ return dispatch.Pipe{},
+ fmt.Errorf("orderbook item not found for %s %s %s",
+ exchange,
+ p,
+ a)
}
-
return service.mux.Subscribe(book.Main)
}
@@ -50,65 +50,46 @@ func SubscribeToExchangeOrderbooks(exchange string) (dispatch.Pipe, error) {
return dispatch.Pipe{}, fmt.Errorf("%s exchange orderbooks not found",
exchange)
}
-
return service.mux.Subscribe(id)
}
// Update stores orderbook data
func (s *Service) Update(b *Base) error {
- var ids []uuid.UUID
-
+ name := strings.ToLower(b.ExchangeName)
s.Lock()
- switch {
- case s.Books[b.ExchangeName] == nil:
- s.Books[b.ExchangeName] = make(map[*currency.Item]map[*currency.Item]map[asset.Item]*Book)
- s.Books[b.ExchangeName][b.Pair.Base.Item] = make(map[*currency.Item]map[asset.Item]*Book)
- s.Books[b.ExchangeName][b.Pair.Base.Item][b.Pair.Quote.Item] = make(map[asset.Item]*Book)
- err := s.SetNewData(b)
- if err != nil {
- s.Unlock()
- return err
- }
-
- case s.Books[b.ExchangeName][b.Pair.Base.Item] == nil:
- s.Books[b.ExchangeName][b.Pair.Base.Item] = make(map[*currency.Item]map[asset.Item]*Book)
- s.Books[b.ExchangeName][b.Pair.Base.Item][b.Pair.Quote.Item] = make(map[asset.Item]*Book)
- err := s.SetNewData(b)
- if err != nil {
- s.Unlock()
- return err
- }
-
- case s.Books[b.ExchangeName][b.Pair.Base.Item][b.Pair.Quote.Item] == nil:
- s.Books[b.ExchangeName][b.Pair.Base.Item][b.Pair.Quote.Item] = make(map[asset.Item]*Book)
- err := s.SetNewData(b)
- if err != nil {
- s.Unlock()
- return err
- }
-
- case s.Books[b.ExchangeName][b.Pair.Base.Item][b.Pair.Quote.Item][b.AssetType] == nil:
- err := s.SetNewData(b)
- if err != nil {
- s.Unlock()
- return err
- }
-
- default:
- book := s.Books[b.ExchangeName][b.Pair.Base.Item][b.Pair.Quote.Item][b.AssetType]
+ book, ok := s.Books[name][b.Pair.Base.Item][b.Pair.Quote.Item][b.AssetType]
+ if ok {
book.b.Bids = b.Bids
book.b.Asks = b.Asks
book.b.LastUpdated = b.LastUpdated
- ids = book.Assoc
- ids = append(ids, book.Main)
+ ids := append(book.Assoc, book.Main)
+ s.Unlock()
+ return s.mux.Publish(ids, b)
+ }
+
+ switch {
+ case s.Books[name] == nil:
+ s.Books[name] = make(map[*currency.Item]map[*currency.Item]map[asset.Item]*Book)
+ fallthrough
+ case s.Books[name][b.Pair.Base.Item] == nil:
+ s.Books[name][b.Pair.Base.Item] = make(map[*currency.Item]map[asset.Item]*Book)
+ fallthrough
+ case s.Books[name][b.Pair.Base.Item][b.Pair.Quote.Item] == nil:
+ s.Books[name][b.Pair.Base.Item][b.Pair.Quote.Item] = make(map[asset.Item]*Book)
+ }
+
+ err := s.SetNewData(b, name)
+ if err != nil {
+ s.Unlock()
+ return err
}
s.Unlock()
- return s.mux.Publish(ids, b)
+ return nil
}
// SetNewData sets new data
-func (s *Service) SetNewData(b *Base) error {
- ids, err := s.GetAssociations(b)
+func (s *Service) SetNewData(b *Base, fmtName string) error {
+ ids, err := s.GetAssociations(b, fmtName)
if err != nil {
return err
}
@@ -126,7 +107,7 @@ func (s *Service) SetNewData(b *Base) error {
cpyBook.Asks = make([]Item, len(b.Asks))
copy(cpyBook.Asks, b.Asks)
- s.Books[b.ExchangeName][b.Pair.Base.Item][b.Pair.Quote.Item][b.AssetType] = &Book{
+ s.Books[fmtName][b.Pair.Base.Item][b.Pair.Quote.Item][b.AssetType] = &Book{
b: &cpyBook,
Main: singleID,
Assoc: ids}
@@ -134,20 +115,20 @@ func (s *Service) SetNewData(b *Base) error {
}
// GetAssociations links a singular book with it's dispatch associations
-func (s *Service) GetAssociations(b *Base) ([]uuid.UUID, error) {
+func (s *Service) GetAssociations(b *Base, fmtName string) ([]uuid.UUID, error) {
if b == nil {
return nil, errors.New("orderbook is nil")
}
var ids []uuid.UUID
- exchangeID, ok := s.Exchange[b.ExchangeName]
+ exchangeID, ok := s.Exchange[fmtName]
if !ok {
var err error
exchangeID, err = s.mux.GetID()
if err != nil {
return nil, err
}
- s.Exchange[b.ExchangeName] = exchangeID
+ s.Exchange[fmtName] = exchangeID
}
ids = append(ids, exchangeID)
@@ -247,8 +228,6 @@ func (b *Base) Process() error {
return errors.New(errExchangeNameUnset)
}
- b.ExchangeName = strings.ToLower(b.ExchangeName)
-
if b.Pair.IsEmpty() {
return errors.New(errPairNotSet)
}
diff --git a/exchanges/orderbook/orderbook_test.go b/exchanges/orderbook/orderbook_test.go
index 8915da03..01e8ad97 100644
--- a/exchanges/orderbook/orderbook_test.go
+++ b/exchanges/orderbook/orderbook_test.go
@@ -125,7 +125,7 @@ func TestSubscribeToExchangeOrderbooks(t *testing.T) {
err = b.Process()
if err != nil {
- t.Error("", err)
+ t.Error(err)
}
_, err = SubscribeToExchangeOrderbooks("SubscribeToExchangeOrderbooks")
@@ -158,7 +158,10 @@ func TestVerify(t *testing.T) {
func TestCalculateTotalBids(t *testing.T) {
t.Parallel()
- curr := currency.NewPairFromStrings("BTC", "USD")
+ curr, err := currency.NewPairFromStrings("BTC", "USD")
+ if err != nil {
+ t.Fatal(err)
+ }
base := Base{
Pair: curr,
Bids: []Item{{Price: 100, Amount: 10}},
@@ -173,7 +176,10 @@ func TestCalculateTotalBids(t *testing.T) {
func TestCalculateTotaAsks(t *testing.T) {
t.Parallel()
- curr := currency.NewPairFromStrings("BTC", "USD")
+ curr, err := currency.NewPairFromStrings("BTC", "USD")
+ if err != nil {
+ t.Fatal(err)
+ }
base := Base{
Pair: curr,
Asks: []Item{{Price: 100, Amount: 10}},
@@ -187,7 +193,10 @@ func TestCalculateTotaAsks(t *testing.T) {
func TestUpdate(t *testing.T) {
t.Parallel()
- curr := currency.NewPairFromStrings("BTC", "USD")
+ curr, err := currency.NewPairFromStrings("BTC", "USD")
+ if err != nil {
+ t.Fatal(err)
+ }
timeNow := time.Now()
base := Base{
Pair: curr,
@@ -217,7 +226,10 @@ func TestUpdate(t *testing.T) {
}
func TestGetOrderbook(t *testing.T) {
- c := currency.NewPairFromStrings("BTC", "USD")
+ c, err := currency.NewPairFromStrings("BTC", "USD")
+ if err != nil {
+ t.Fatal(err)
+ }
base := &Base{
Pair: c,
Asks: []Item{{Price: 100, Amount: 10}},
@@ -226,7 +238,7 @@ func TestGetOrderbook(t *testing.T) {
AssetType: asset.Spot,
}
- err := base.Process()
+ err = base.Process()
if err != nil {
t.Fatal(err)
}
@@ -251,7 +263,10 @@ func TestGetOrderbook(t *testing.T) {
t.Fatal("TestGetOrderbook retrieved non-existent orderbook using invalid first currency")
}
- newCurrency := currency.NewPairFromStrings("BTC", "AUD")
+ newCurrency, err := currency.NewPairFromStrings("BTC", "AUD")
+ if err != nil {
+ t.Fatal(err)
+ }
_, err = Get("Exchange", newCurrency, asset.Spot)
if err == nil {
t.Fatal("TestGetOrderbook retrieved non-existent orderbook using invalid second currency")
@@ -270,7 +285,10 @@ func TestGetOrderbook(t *testing.T) {
}
func TestCreateNewOrderbook(t *testing.T) {
- c := currency.NewPairFromStrings("BTC", "USD")
+ c, err := currency.NewPairFromStrings("BTC", "USD")
+ if err != nil {
+ t.Fatal(err)
+ }
base := &Base{
Pair: c,
Asks: []Item{{Price: 100, Amount: 10}},
@@ -279,7 +297,7 @@ func TestCreateNewOrderbook(t *testing.T) {
AssetType: asset.Spot,
}
- err := base.Process()
+ err = base.Process()
if err != nil {
t.Fatal(err)
}
@@ -305,7 +323,10 @@ func TestCreateNewOrderbook(t *testing.T) {
}
func TestProcessOrderbook(t *testing.T) {
- c := currency.NewPairFromStrings("BTC", "USD")
+ c, err := currency.NewPairFromStrings("BTC", "USD")
+ if err != nil {
+ t.Fatal(err)
+ }
base := Base{
Asks: []Item{{Price: 100, Amount: 10}},
Bids: []Item{{Price: 200, Amount: 10}},
@@ -314,7 +335,7 @@ func TestProcessOrderbook(t *testing.T) {
// test for empty pair
base.Pair = currency.Pair{}
- err := base.Process()
+ err = base.Process()
if err == nil {
t.Error("empty pair should throw an err")
}
@@ -341,7 +362,10 @@ func TestProcessOrderbook(t *testing.T) {
}
// now test for processing a pair with a different quote currency
- c = currency.NewPairFromStrings("BTC", "GBP")
+ c, err = currency.NewPairFromStrings("BTC", "GBP")
+ if err != nil {
+ t.Fatal(err)
+ }
base.Pair = c
err = base.Process()
if err != nil {
@@ -356,7 +380,10 @@ func TestProcessOrderbook(t *testing.T) {
}
// now test for processing a pair which has a different base currency
- c = currency.NewPairFromStrings("LTC", "GBP")
+ c, err = currency.NewPairFromStrings("LTC", "GBP")
+ if err != nil {
+ t.Fatal(err)
+ }
base.Pair = c
err = base.Process()
if err != nil {
@@ -491,14 +518,14 @@ func TestProcessOrderbook(t *testing.T) {
}
func TestSetNewData(t *testing.T) {
- err := service.SetNewData(nil)
+ err := service.SetNewData(nil, "")
if err == nil {
t.Error("error cannot be nil")
}
}
func TestGetAssociations(t *testing.T) {
- _, err := service.GetAssociations(nil)
+ _, err := service.GetAssociations(nil, "")
if err == nil {
t.Error("error cannot be nil")
}
diff --git a/exchanges/poloniex/poloniex.go b/exchanges/poloniex/poloniex.go
index f1205e96..618f31cd 100644
--- a/exchanges/poloniex/poloniex.go
+++ b/exchanges/poloniex/poloniex.go
@@ -16,7 +16,6 @@ import (
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
)
const (
@@ -54,7 +53,6 @@ const (
// Poloniex is the overarching type across the poloniex package
type Poloniex struct {
exchange.Base
- WebsocketConn *wshandler.WebsocketConnection
}
// GetTicker returns current ticker information
diff --git a/exchanges/poloniex/poloniex_live_test.go b/exchanges/poloniex/poloniex_live_test.go
index 36c5afee..8eabea2a 100644
--- a/exchanges/poloniex/poloniex_live_test.go
+++ b/exchanges/poloniex/poloniex_live_test.go
@@ -29,6 +29,7 @@ func TestMain(m *testing.M) {
poloniexConfig.API.Credentials.Key = apiKey
poloniexConfig.API.Credentials.Secret = apiSecret
p.SetDefaults()
+ p.Websocket = sharedtestvalues.NewTestWebsocket()
err = p.Setup(poloniexConfig)
if err != nil {
log.Fatal("Poloniex setup error", err)
diff --git a/exchanges/poloniex/poloniex_mock_test.go b/exchanges/poloniex/poloniex_mock_test.go
index 0df790ae..ad2cecdd 100644
--- a/exchanges/poloniex/poloniex_mock_test.go
+++ b/exchanges/poloniex/poloniex_mock_test.go
@@ -33,6 +33,7 @@ func TestMain(m *testing.M) {
poloniexConfig.API.Credentials.Key = apiKey
poloniexConfig.API.Credentials.Secret = apiSecret
p.SetDefaults()
+ p.Websocket = sharedtestvalues.NewTestWebsocket()
err = p.Setup(poloniexConfig)
if err != nil {
log.Fatal("Poloniex setup error", err)
@@ -45,8 +46,6 @@ func TestMain(m *testing.M) {
p.HTTPClient = newClient
p.API.Endpoints.URL = serverDetails
- p.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- p.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
log.Printf(sharedtestvalues.MockTesting, p.Name, p.API.Endpoints.URL)
os.Exit(m.Run())
}
diff --git a/exchanges/poloniex/poloniex_test.go b/exchanges/poloniex/poloniex_test.go
index 700a1ba1..25e74ee4 100644
--- a/exchanges/poloniex/poloniex_test.go
+++ b/exchanges/poloniex/poloniex_test.go
@@ -14,7 +14,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -259,7 +259,7 @@ func TestSubmitOrder(t *testing.T) {
var orderSubmission = &order.Submit{
Pair: currency.Pair{
- Delimiter: delimiterUnderscore,
+ Delimiter: currency.UnderscoreDelimiter,
Base: currency.BTC,
Quote: currency.LTC,
},
@@ -422,22 +422,13 @@ func TestGetDepositAddress(t *testing.T) {
func TestWsAuth(t *testing.T) {
t.Parallel()
if !p.Websocket.IsEnabled() && !p.API.AuthenticatedWebsocketSupport || !areTestAPIKeysSet() {
- t.Skip(wshandler.WebsocketNotEnabled)
- }
- p.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: p.Name,
- URL: p.Websocket.GetWebsocketURL(),
- Verbose: p.Verbose,
- ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
- ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
+ t.Skip(stream.WebsocketNotEnabled)
}
var dialer websocket.Dialer
- err := p.WebsocketConn.Dial(&dialer, http.Header{})
+ err := p.Websocket.Conn.Dial(&dialer, http.Header{})
if err != nil {
t.Fatal(err)
}
- p.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- p.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
go p.wsReadData()
err = p.wsSendAuthorisedCommand("subscribe")
if err != nil {
@@ -534,8 +525,11 @@ func TestWsHandleAccountData(t *testing.T) {
}
func TestGetHistoricCandles(t *testing.T) {
- currencyPair := currency.NewPairFromString("BTCLTC")
- _, err := p.GetHistoricCandles(currencyPair, asset.Spot, time.Unix(1588741402, 0), time.Unix(1588745003, 0), kline.FiveMin)
+ currencyPair, err := currency.NewPairFromString("BTCLTC")
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = p.GetHistoricCandles(currencyPair, asset.Spot, time.Unix(1588741402, 0), time.Unix(1588745003, 0), kline.FiveMin)
if err != nil {
t.Fatal(err)
}
@@ -552,8 +546,11 @@ func TestGetHistoricCandles(t *testing.T) {
}
func TestGetHistoricCandlesExtended(t *testing.T) {
- currencyPair := currency.NewPairFromString("BTCLTC")
- _, err := p.GetHistoricCandlesExtended(currencyPair, asset.Spot, time.Unix(1588741402, 0), time.Unix(1588745003, 0), kline.FiveMin)
+ currencyPair, err := currency.NewPairFromString("BTCLTC")
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = p.GetHistoricCandlesExtended(currencyPair, asset.Spot, time.Unix(1588741402, 0), time.Unix(1588745003, 0), kline.FiveMin)
if err != nil {
t.Fatal(err)
}
diff --git a/exchanges/poloniex/poloniex_websocket.go b/exchanges/poloniex/poloniex_websocket.go
index d671f71f..d02a2f5e 100644
--- a/exchanges/poloniex/poloniex_websocket.go
+++ b/exchanges/poloniex/poloniex_websocket.go
@@ -17,9 +17,9 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wsorderbook"
)
const (
@@ -28,7 +28,6 @@ const (
wsTickerDataID = 1002
ws24HourExchangeVolumeID = 1003
wsHeartbeat = 1010
- delimiterUnderscore = "_"
)
var (
@@ -39,23 +38,26 @@ var (
// WsConnect initiates a websocket connection
func (p *Poloniex) WsConnect() error {
if !p.Websocket.IsEnabled() || !p.IsEnabled() {
- return errors.New(wshandler.WebsocketNotEnabled)
+ return errors.New(stream.WebsocketNotEnabled)
}
var dialer websocket.Dialer
- err := p.WebsocketConn.Dial(&dialer, http.Header{})
+ err := p.Websocket.Conn.Dial(&dialer, http.Header{})
if err != nil {
return err
}
- err2 := p.getCurrencyIDMap()
- if err2 != nil {
- return err2
+ err = p.getCurrencyIDMap()
+ if err != nil {
+ return err
}
go p.wsReadData()
- p.GenerateDefaultSubscriptions()
+ subs, err := p.GenerateDefaultSubscriptions()
+ if err != nil {
+ return err
+ }
- return nil
+ return p.Websocket.SubscribeToChannels(subs)
}
func (p *Poloniex) getCurrencyIDMap() error {
@@ -86,26 +88,16 @@ func checkSubscriptionSuccess(data []interface{}) bool {
// wsReadData handles data from the websocket connection
func (p *Poloniex) wsReadData() {
p.Websocket.Wg.Add(1)
-
- defer func() {
- p.Websocket.Wg.Done()
- }()
+ defer p.Websocket.Wg.Done()
for {
- select {
- case <-p.Websocket.ShutdownC:
+ resp := p.Websocket.Conn.ReadMessage()
+ if resp.Raw == nil {
return
- default:
- resp, err := p.WebsocketConn.ReadMessage()
- if err != nil {
- p.Websocket.ReadMessageErrors <- err
- return
- }
- p.Websocket.TrafficAlert <- struct{}{}
- err = p.wsHandleData(resp.Raw)
- if err != nil {
- p.Websocket.DataHandler <- err
- }
+ }
+ err := p.wsHandleData(resp.Raw)
+ if err != nil {
+ p.Websocket.DataHandler <- err
}
}
}
@@ -189,14 +181,20 @@ func (p *Poloniex) wsHandleData(respRaw []byte) error {
}
var currPair currency.Pair
if currPairFromMap, ok := currencyIDMap[notification[1].(float64)]; ok {
- currPair = currency.NewPairFromString(currPairFromMap)
+ currPair, err = currency.NewPairFromString(currPairFromMap)
+ if err != nil {
+ return err
+ }
} else {
// It is better to still log an order which you can recheck later, rather than error out
p.Websocket.DataHandler <- fmt.Errorf(p.Name+
" - Unknown currency pair ID. "+
"Currency will appear as the pair ID: '%v'",
notification[1].(float64))
- currPair = currency.NewPairFromString(strconv.FormatFloat(notification[1].(float64), 'f', -1, 64))
+ currPair, err = currency.NewPairFromString(strconv.FormatFloat(notification[1].(float64), 'f', -1, 64))
+ if err != nil {
+ return err
+ }
}
var a asset.Item
a, err = p.GetPairAssetType(currPair)
@@ -303,12 +301,6 @@ func (p *Poloniex) wsHandleData(respRaw []byte) error {
if err != nil {
return err
}
-
- p.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
- Exchange: p.Name,
- Asset: asset.Spot,
- Pair: currency.NewPairFromString(currencyPair),
- }
case "o":
currencyPair := currencyIDMap[channelID]
dataL3 := dataL2.([]interface{})
@@ -318,12 +310,6 @@ func (p *Poloniex) wsHandleData(respRaw []byte) error {
if err != nil {
return err
}
-
- p.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
- Exchange: p.Name,
- Asset: asset.Spot,
- Pair: currency.NewPairFromString(currencyPair),
- }
case "t":
currencyPair := currencyIDMap[channelID]
var trade WsTrade
@@ -347,15 +333,20 @@ func (p *Poloniex) wsHandleData(respRaw []byte) error {
}
trade.Timestamp = int64(dataL3[5].(float64))
- p.Websocket.DataHandler <- wshandler.TradeData{
+ pair, err := currency.NewPairFromString(currencyPair)
+ if err != nil {
+ return err
+ }
+
+ p.Websocket.DataHandler <- stream.TradeData{
Timestamp: time.Unix(trade.Timestamp, 0),
- CurrencyPair: currency.NewPairFromString(currencyPair),
+ CurrencyPair: pair,
Side: side,
Amount: trade.Volume,
Price: trade.Price,
}
default:
- p.Websocket.DataHandler <- wshandler.UnhandledMessageWarning{Message: p.Name + wshandler.UnhandledMessage + string(respRaw)}
+ p.Websocket.DataHandler <- stream.UnhandledMessageWarning{Message: p.Name + stream.UnhandledMessage + string(respRaw)}
return nil
}
}
@@ -368,14 +359,31 @@ func (p *Poloniex) wsHandleData(respRaw []byte) error {
func (p *Poloniex) wsHandleTickerData(data []interface{}) error {
tickerData := data[2].([]interface{})
var t WsTicker
- currencyPair := currency.NewPairDelimiter(currencyIDMap[tickerData[0].(float64)], delimiterUnderscore)
- if !p.GetEnabledPairs(asset.Spot).Contains(currencyPair, true) {
- // Ticker subscription receives all currencies, no specific subscription
- // There should be no error associated with receiving data of disabled currency ticker data
+ currencyPair, err := currency.NewPairDelimiter(currencyIDMap[tickerData[0].(float64)],
+ currency.UnderscoreDelimiter)
+ if err != nil {
+ return err
+ }
+
+ enabled, err := p.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return err
+ }
+
+ if !enabled.Contains(currencyPair, true) {
+ var avail currency.Pairs
+ avail, err = p.GetAvailablePairs(asset.Spot)
+ if err != nil {
+ return err
+ }
+
+ if !avail.Contains(currencyPair, true) {
+ return fmt.Errorf("currency pair %s not found in available pair list",
+ currencyPair)
+ }
return nil
}
- var err error
t.LastPrice, err = strconv.ParseFloat(tickerData[1].(string), 64)
if err != nil {
return err
@@ -477,7 +485,12 @@ func (p *Poloniex) WsProcessOrderbookSnapshot(ob []interface{}, symbol string) e
newOrderBook.Asks = asks
newOrderBook.Bids = bids
newOrderBook.AssetType = asset.Spot
- newOrderBook.Pair = currency.NewPairFromString(symbol)
+
+ var err error
+ newOrderBook.Pair, err = currency.NewPairFromString(symbol)
+ if err != nil {
+ return err
+ }
newOrderBook.ExchangeName = p.Name
return p.Websocket.Orderbook.LoadSnapshot(&newOrderBook)
@@ -485,7 +498,10 @@ func (p *Poloniex) WsProcessOrderbookSnapshot(ob []interface{}, symbol string) e
// WsProcessOrderbookUpdate processes new orderbook updates
func (p *Poloniex) WsProcessOrderbookUpdate(sequenceNumber int64, target []interface{}, symbol string) error {
- cP := currency.NewPairFromString(symbol)
+ cP, err := currency.NewPairFromString(symbol)
+ if err != nil {
+ return err
+ }
price, err := strconv.ParseFloat(target[2].(string), 64)
if err != nil {
return err
@@ -494,7 +510,7 @@ func (p *Poloniex) WsProcessOrderbookUpdate(sequenceNumber int64, target []inter
if err != nil {
return err
}
- update := &wsorderbook.WebsocketOrderbookUpdate{
+ update := &buffer.Update{
Pair: cP,
Asset: asset.Spot,
UpdateID: sequenceNumber,
@@ -508,64 +524,114 @@ func (p *Poloniex) WsProcessOrderbookUpdate(sequenceNumber int64, target []inter
}
// GenerateDefaultSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions()
-func (p *Poloniex) GenerateDefaultSubscriptions() {
- var subscriptions []wshandler.WebsocketChannelSubscription
- subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
+func (p *Poloniex) GenerateDefaultSubscriptions() ([]stream.ChannelSubscription, error) {
+ var subscriptions []stream.ChannelSubscription
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
Channel: strconv.FormatInt(wsTickerDataID, 10),
})
if p.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
- subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
Channel: strconv.FormatInt(wsAccountNotificationID, 10),
})
}
- enabledCurrencies := p.GetEnabledPairs(asset.Spot)
+ enabledCurrencies, err := p.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return nil, err
+ }
for j := range enabledCurrencies {
- enabledCurrencies[j].Delimiter = delimiterUnderscore
- subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
+ enabledCurrencies[j].Delimiter = currency.UnderscoreDelimiter
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
Channel: "orderbook",
Currency: enabledCurrencies[j],
+ Asset: asset.Spot,
})
}
- p.Websocket.SubscribeToChannels(subscriptions)
+ return subscriptions, nil
}
// Subscribe sends a websocket message to receive data from the channel
-func (p *Poloniex) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
- subscriptionRequest := WsCommand{
- Command: "subscribe",
+func (p *Poloniex) Subscribe(sub []stream.ChannelSubscription) error {
+ var errs common.Errors
+channels:
+ for i := range sub {
+ subscriptionRequest := WsCommand{
+ Command: "subscribe",
+ }
+ switch {
+ case strings.EqualFold(strconv.FormatInt(wsAccountNotificationID, 10),
+ sub[i].Channel):
+ err := p.wsSendAuthorisedCommand("subscribe")
+ if err != nil {
+ errs = append(errs, err)
+ continue channels
+ }
+ p.Websocket.AddSuccessfulSubscriptions(sub[i])
+ continue channels
+ case strings.EqualFold(strconv.FormatInt(wsTickerDataID, 10),
+ sub[i].Channel):
+ subscriptionRequest.Channel = wsTickerDataID
+ default:
+ subscriptionRequest.Channel = sub[i].Currency.String()
+ }
+
+ err := p.Websocket.Conn.SendJSONMessage(subscriptionRequest)
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+
+ p.Websocket.AddSuccessfulSubscriptions(sub[i])
}
- switch {
- case strings.EqualFold(strconv.FormatInt(wsAccountNotificationID, 10), channelToSubscribe.Channel):
- return p.wsSendAuthorisedCommand("subscribe")
- case strings.EqualFold(strconv.FormatInt(wsTickerDataID, 10), channelToSubscribe.Channel):
- subscriptionRequest.Channel = wsTickerDataID
- default:
- subscriptionRequest.Channel = channelToSubscribe.Currency.String()
+ if errs != nil {
+ return errs
}
- return p.WebsocketConn.SendJSONMessage(subscriptionRequest)
+ return nil
}
// Unsubscribe sends a websocket message to stop receiving data from the channel
-func (p *Poloniex) Unsubscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
- unsubscriptionRequest := WsCommand{
- Command: "unsubscribe",
+func (p *Poloniex) Unsubscribe(unsub []stream.ChannelSubscription) error {
+ var errs common.Errors
+channels:
+ for i := range unsub {
+ unsubscriptionRequest := WsCommand{
+ Command: "unsubscribe",
+ }
+ switch {
+ case strings.EqualFold(strconv.FormatInt(wsAccountNotificationID, 10),
+ unsub[i].Channel):
+ err := p.wsSendAuthorisedCommand("unsubscribe")
+ if err != nil {
+ errs = append(errs, err)
+ continue channels
+ }
+ p.Websocket.RemoveSuccessfulUnsubscriptions(unsub[i])
+ continue channels
+ case strings.EqualFold(strconv.FormatInt(wsTickerDataID, 10),
+ unsub[i].Channel):
+ unsubscriptionRequest.Channel = wsTickerDataID
+ default:
+ unsubscriptionRequest.Channel = unsub[i].Currency.String()
+ }
+ err := p.Websocket.Conn.SendJSONMessage(unsubscriptionRequest)
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ p.Websocket.RemoveSuccessfulUnsubscriptions(unsub[i])
}
- switch {
- case strings.EqualFold(strconv.FormatInt(wsAccountNotificationID, 10), channelToSubscribe.Channel):
- return p.wsSendAuthorisedCommand("unsubscribe")
- case strings.EqualFold(strconv.FormatInt(wsTickerDataID, 10), channelToSubscribe.Channel):
- unsubscriptionRequest.Channel = wsTickerDataID
- default:
- unsubscriptionRequest.Channel = channelToSubscribe.Currency.String()
+ if errs != nil {
+ return errs
}
- return p.WebsocketConn.SendJSONMessage(unsubscriptionRequest)
+ return nil
}
func (p *Poloniex) wsSendAuthorisedCommand(command string) error {
nonce := fmt.Sprintf("nonce=%v", time.Now().UnixNano())
- hmac := crypto.GetHMAC(crypto.HashSHA512, []byte(nonce), []byte(p.API.Credentials.Secret))
+ hmac := crypto.GetHMAC(crypto.HashSHA512,
+ []byte(nonce),
+ []byte(p.API.Credentials.Secret))
request := WsAuthorisationRequest{
Command: command,
Channel: 1000,
@@ -573,5 +639,5 @@ func (p *Poloniex) wsSendAuthorisedCommand(command string) error {
Key: p.API.Credentials.Key,
Payload: nonce,
}
- return p.WebsocketConn.SendJSONMessage(request)
+ return p.Websocket.Conn.SendJSONMessage(request)
}
diff --git a/exchanges/poloniex/poloniex_wrapper.go b/exchanges/poloniex/poloniex_wrapper.go
index a8b5926e..fa6a02c4 100644
--- a/exchanges/poloniex/poloniex_wrapper.go
+++ b/exchanges/poloniex/poloniex_wrapper.go
@@ -18,8 +18,8 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -55,19 +55,19 @@ func (p *Poloniex) SetDefaults() {
p.API.CredentialsValidator.RequiresKey = true
p.API.CredentialsValidator.RequiresSecret = true
- p.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- },
- UseGlobalFormat: true,
- RequestFormat: ¤cy.PairFormat{
- Delimiter: delimiterUnderscore,
- Uppercase: true,
- },
- ConfigFormat: ¤cy.PairFormat{
- Delimiter: delimiterUnderscore,
- Uppercase: true,
- },
+ requestFmt := ¤cy.PairFormat{
+ Delimiter: currency.UnderscoreDelimiter,
+ Uppercase: true,
+ }
+
+ configFmt := ¤cy.PairFormat{
+ Delimiter: currency.UnderscoreDelimiter,
+ Uppercase: true,
+ }
+
+ err := p.SetGlobalPairsManager(requestFmt, configFmt, asset.Spot)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
}
p.Features = exchange.Features{
@@ -133,7 +133,7 @@ func (p *Poloniex) SetDefaults() {
p.API.Endpoints.URLDefault = poloniexAPIURL
p.API.Endpoints.URL = p.API.Endpoints.URLDefault
p.API.Endpoints.WebsocketURL = poloniexWebsocketAddress
- p.Websocket = wshandler.New()
+ p.Websocket = stream.New()
p.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
p.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
p.WebsocketOrderbookBufferLimit = exchange.DefaultWebsocketOrderbookBufferLimit
@@ -151,41 +151,31 @@ func (p *Poloniex) Setup(exch *config.ExchangeConfig) error {
return err
}
- err = p.Websocket.Setup(
- &wshandler.WebsocketSetup{
- Enabled: exch.Features.Enabled.Websocket,
- Verbose: exch.Verbose,
- AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
- WebsocketTimeout: exch.WebsocketTrafficTimeout,
- DefaultURL: poloniexWebsocketAddress,
- ExchangeName: exch.Name,
- RunningURL: exch.API.Endpoints.WebsocketURL,
- Connector: p.WsConnect,
- Subscriber: p.Subscribe,
- UnSubscriber: p.Unsubscribe,
- Features: &p.Features.Supports.WebsocketCapabilities,
- })
+ err = p.Websocket.Setup(&stream.WebsocketSetup{
+ Enabled: exch.Features.Enabled.Websocket,
+ Verbose: exch.Verbose,
+ AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
+ WebsocketTimeout: exch.WebsocketTrafficTimeout,
+ DefaultURL: poloniexWebsocketAddress,
+ ExchangeName: exch.Name,
+ RunningURL: exch.API.Endpoints.WebsocketURL,
+ Connector: p.WsConnect,
+ Subscriber: p.Subscribe,
+ UnSubscriber: p.Unsubscribe,
+ GenerateSubscriptions: p.GenerateDefaultSubscriptions,
+ Features: &p.Features.Supports.WebsocketCapabilities,
+ OrderbookBufferLimit: exch.WebsocketOrderbookBufferLimit,
+ SortBuffer: true,
+ SortBufferByUpdateIDs: true,
+ })
if err != nil {
return err
}
- p.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: p.Name,
- URL: p.Websocket.GetWebsocketURL(),
- ProxyURL: p.Websocket.GetProxyAddress(),
- Verbose: p.Verbose,
+ return p.Websocket.SetupNewConnection(stream.ConnectionSetup{
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
- }
-
- p.Websocket.Orderbook.Setup(
- exch.WebsocketOrderbookBufferLimit,
- false,
- true,
- true,
- false,
- exch.Name)
- return nil
+ })
}
// Start starts the Poloniex go routine
@@ -200,13 +190,28 @@ func (p *Poloniex) Start(wg *sync.WaitGroup) {
// Run implements the Poloniex wrapper
func (p *Poloniex) Run() {
if p.Verbose {
- log.Debugf(log.ExchangeSys, "%s Websocket: %s (url: %s).\n", p.Name, common.IsEnabled(p.Websocket.IsEnabled()), poloniexWebsocketAddress)
+ log.Debugf(log.ExchangeSys,
+ "%s Websocket: %s (url: %s).\n",
+ p.Name,
+ common.IsEnabled(p.Websocket.IsEnabled()),
+ poloniexWebsocketAddress)
p.PrintEnabledPairs()
}
forceUpdate := false
- if common.StringDataCompare(p.GetAvailablePairs(asset.Spot).Strings(), "BTC_USDT") {
- log.Warnf(log.ExchangeSys, "%s contains invalid pair, forcing upgrade of available currencies.\n",
+
+ avail, err := p.GetAvailablePairs(asset.Spot)
+ if err != nil {
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update tradable pairs. Err: %s",
+ p.Name,
+ err)
+ return
+ }
+
+ if common.StringDataCompare(avail.Strings(), "BTC_USDT") {
+ log.Warnf(log.ExchangeSys,
+ "%s contains invalid pair, forcing upgrade of available currencies.\n",
p.Name)
forceUpdate = true
}
@@ -215,9 +220,12 @@ func (p *Poloniex) Run() {
return
}
- err := p.UpdateTradablePairs(forceUpdate)
+ err = p.UpdateTradablePairs(forceUpdate)
if err != nil {
- log.Errorf(log.ExchangeSys, "%s failed to update tradable pairs. Err: %s", p.Name, err)
+ log.Errorf(log.ExchangeSys,
+ "%s failed to update tradable pairs. Err: %s",
+ p.Name,
+ err)
}
}
@@ -243,37 +251,47 @@ func (p *Poloniex) UpdateTradablePairs(forceUpgrade bool) error {
if err != nil {
return err
}
-
- return p.UpdatePairs(currency.NewPairsFromStrings(pairs), asset.Spot, false, forceUpgrade)
+ ps, err := currency.NewPairsFromStrings(pairs)
+ if err != nil {
+ return err
+ }
+ return p.UpdatePairs(ps, asset.Spot, false, forceUpgrade)
}
// UpdateTicker updates and returns the ticker for a currency pair
func (p *Poloniex) UpdateTicker(currencyPair currency.Pair, assetType asset.Item) (*ticker.Price, error) {
- tickerPrice := new(ticker.Price)
tick, err := p.GetTicker()
if err != nil {
- return tickerPrice, err
+ return nil, err
}
- enabledPairs := p.GetEnabledPairs(assetType)
+ enabledPairs, err := p.GetEnabledPairs(assetType)
+ if err != nil {
+ return nil, err
+ }
for i := range enabledPairs {
- var tp ticker.Price
- curr := p.FormatExchangeCurrency(enabledPairs[i], assetType).String()
+ fpair, err := p.FormatExchangeCurrency(enabledPairs[i], assetType)
+ if err != nil {
+ return nil, err
+ }
+ curr := fpair.String()
if _, ok := tick[curr]; !ok {
continue
}
- tp.Pair = enabledPairs[i]
- tp.Ask = tick[curr].LowestAsk
- tp.Bid = tick[curr].HighestBid
- tp.High = tick[curr].High24Hr
- tp.Last = tick[curr].Last
- tp.Low = tick[curr].Low24Hr
- tp.Volume = tick[curr].BaseVolume
- tp.QuoteVolume = tick[curr].QuoteVolume
- err = ticker.ProcessTicker(p.Name, &tp, assetType)
+ err = ticker.ProcessTicker(&ticker.Price{
+ Pair: enabledPairs[i],
+ Ask: tick[curr].LowestAsk,
+ Bid: tick[curr].HighestBid,
+ High: tick[curr].High24Hr,
+ Last: tick[curr].Last,
+ Low: tick[curr].Low24Hr,
+ Volume: tick[curr].BaseVolume,
+ QuoteVolume: tick[curr].QuoteVolume,
+ ExchangeName: p.Name,
+ AssetType: assetType})
if err != nil {
- log.Error(log.Ticker, err)
+ return nil, err
}
}
return ticker.GetTicker(p.Name, currencyPair, assetType)
@@ -304,9 +322,16 @@ func (p *Poloniex) UpdateOrderbook(currencyPair currency.Pair, assetType asset.I
return nil, err
}
- enabledPairs := p.GetEnabledPairs(assetType)
+ enabledPairs, err := p.GetEnabledPairs(assetType)
+ if err != nil {
+ return nil, err
+ }
for i := range enabledPairs {
- data, ok := orderbookNew.Data[p.FormatExchangeCurrency(enabledPairs[i], assetType).String()]
+ fpair, err := p.FormatExchangeCurrency(enabledPairs[i], assetType)
+ if err != nil {
+ return nil, err
+ }
+ data, ok := orderbookNew.Data[fpair.String()]
if !ok {
continue
}
@@ -516,11 +541,6 @@ func (p *Poloniex) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdra
return nil, common.ErrFunctionNotSupported
}
-// GetWebsocket returns a pointer to the exchange websocket
-func (p *Poloniex) GetWebsocket() (*wshandler.Websocket, error) {
- return p.Websocket, nil
-}
-
// GetFeeByType returns an estimate of fee based on type of transaction
func (p *Poloniex) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if (!p.AllowAuthenticatedRequest() || p.SkipAuthCheck) && // Todo check connection status
@@ -537,11 +557,18 @@ func (p *Poloniex) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail,
return nil, err
}
+ format, err := p.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return nil, err
+ }
+
var orders []order.Detail
for key := range resp.Data {
- symbol := currency.NewPairDelimiter(key,
- p.GetPairFormat(asset.Spot, false).Delimiter)
-
+ var symbol currency.Pair
+ symbol, err = currency.NewPairDelimiter(key, format.Delimiter)
+ if err != nil {
+ return nil, err
+ }
for i := range resp.Data[key] {
orderSide := order.Side(strings.ToUpper(resp.Data[key][i].Type))
orderDate, err := time.Parse(common.SimpleTimeFormat, resp.Data[key][i].Date)
@@ -583,10 +610,18 @@ func (p *Poloniex) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
return nil, err
}
+ format, err := p.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return nil, err
+ }
+
var orders []order.Detail
for key := range resp.Data {
- symbol := currency.NewPairDelimiter(key,
- p.GetPairFormat(asset.Spot, false).Delimiter)
+ var symbol currency.Pair
+ symbol, err = currency.NewPairDelimiter(key, format.Delimiter)
+ if err != nil {
+ return nil, err
+ }
for i := range resp.Data[key] {
orderSide := order.Side(strings.ToUpper(resp.Data[key][i].Type))
@@ -619,30 +654,6 @@ func (p *Poloniex) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail,
return orders, nil
}
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func (p *Poloniex) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- p.Websocket.SubscribeToChannels(channels)
- return nil
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func (p *Poloniex) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- p.Websocket.RemoveSubscribedChannels(channels)
- return nil
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func (p *Poloniex) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return p.Websocket.GetSubscriptions(), nil
-}
-
-// AuthenticateWebsocket sends an authentication message to the websocket
-func (p *Poloniex) AuthenticateWebsocket() error {
- return common.ErrFunctionNotSupported
-}
-
// ValidateCredentials validates current credentials used for wrapper
// functionality
func (p *Poloniex) ValidateCredentials() error {
@@ -658,7 +669,12 @@ func (p *Poloniex) GetHistoricCandles(pair currency.Pair, a asset.Item, start, e
}
}
- candles, err := p.GetChartData(p.FormatExchangeCurrency(pair, a).String(),
+ formattedPair, err := p.FormatExchangeCurrency(pair, a)
+ if err != nil {
+ return kline.Item{}, err
+ }
+
+ candles, err := p.GetChartData(formattedPair.String(),
start, end,
p.FormatExchangeKlineInterval(interval))
if err != nil {
diff --git a/exchanges/protocol/features.go b/exchanges/protocol/features.go
index 821907a2..ef12bfc4 100644
--- a/exchanges/protocol/features.go
+++ b/exchanges/protocol/features.go
@@ -3,35 +3,38 @@ package protocol
// Features holds all variables for the exchanges supported features
// for a protocol (e.g REST or Websocket)
type Features struct {
- TickerBatching bool `json:"tickerBatching,omitempty"`
- AutoPairUpdates bool `json:"autoPairUpdates,omitempty"`
- AccountBalance bool `json:"accountBalance,omitempty"`
- CryptoDeposit bool `json:"cryptoDeposit,omitempty"`
- CryptoWithdrawal bool `json:"cryptoWithdrawal,omitempty"`
- FiatWithdraw bool `json:"fiatWithdraw,omitempty"`
- GetOrder bool `json:"getOrder,omitempty"`
- GetOrders bool `json:"getOrders,omitempty"`
- CancelOrders bool `json:"cancelOrders,omitempty"`
- CancelOrder bool `json:"cancelOrder,omitempty"`
- SubmitOrder bool `json:"submitOrder,omitempty"`
- SubmitOrders bool `json:"submitOrders,omitempty"`
- ModifyOrder bool `json:"modifyOrder,omitempty"`
- DepositHistory bool `json:"depositHistory,omitempty"`
- WithdrawalHistory bool `json:"withdrawalHistory,omitempty"`
- TradeHistory bool `json:"tradeHistory,omitempty"`
- UserTradeHistory bool `json:"userTradeHistory,omitempty"`
- TradeFee bool `json:"tradeFee,omitempty"`
- FiatDepositFee bool `json:"fiatDepositFee,omitempty"`
- FiatWithdrawalFee bool `json:"fiatWithdrawalFee,omitempty"`
- CryptoDepositFee bool `json:"cryptoDepositFee,omitempty"`
- CryptoWithdrawalFee bool `json:"cryptoWithdrawalFee,omitempty"`
- TickerFetching bool `json:"tickerFetching,omitempty"`
- KlineFetching bool `json:"klineFetching,omitempty"`
- TradeFetching bool `json:"tradeFetching,omitempty"`
- OrderbookFetching bool `json:"orderbookFetching,omitempty"`
- AccountInfo bool `json:"accountInfo,omitempty"`
- FiatDeposit bool `json:"fiatDeposit,omitempty"`
- DeadMansSwitch bool `json:"deadMansSwitch,omitempty"`
+ TickerBatching bool `json:"tickerBatching,omitempty"`
+ AutoPairUpdates bool `json:"autoPairUpdates,omitempty"`
+ AccountBalance bool `json:"accountBalance,omitempty"`
+ CryptoDeposit bool `json:"cryptoDeposit,omitempty"`
+ CryptoWithdrawal bool `json:"cryptoWithdrawal,omitempty"`
+ FiatWithdraw bool `json:"fiatWithdraw,omitempty"`
+ GetOrder bool `json:"getOrder,omitempty"`
+ GetOrders bool `json:"getOrders,omitempty"`
+ CancelOrders bool `json:"cancelOrders,omitempty"`
+ CancelOrder bool `json:"cancelOrder,omitempty"`
+ SubmitOrder bool `json:"submitOrder,omitempty"`
+ SubmitOrders bool `json:"submitOrders,omitempty"`
+ ModifyOrder bool `json:"modifyOrder,omitempty"`
+ DepositHistory bool `json:"depositHistory,omitempty"`
+ WithdrawalHistory bool `json:"withdrawalHistory,omitempty"`
+ TradeHistory bool `json:"tradeHistory,omitempty"`
+ UserTradeHistory bool `json:"userTradeHistory,omitempty"`
+ TradeFee bool `json:"tradeFee,omitempty"`
+ FiatDepositFee bool `json:"fiatDepositFee,omitempty"`
+ FiatWithdrawalFee bool `json:"fiatWithdrawalFee,omitempty"`
+ CryptoDepositFee bool `json:"cryptoDepositFee,omitempty"`
+ CryptoWithdrawalFee bool `json:"cryptoWithdrawalFee,omitempty"`
+ TickerFetching bool `json:"tickerFetching,omitempty"`
+ KlineFetching bool `json:"klineFetching,omitempty"`
+ TradeFetching bool `json:"tradeFetching,omitempty"`
+ OrderbookFetching bool `json:"orderbookFetching,omitempty"`
+ AccountInfo bool `json:"accountInfo,omitempty"`
+ FiatDeposit bool `json:"fiatDeposit,omitempty"`
+ DeadMansSwitch bool `json:"deadMansSwitch,omitempty"`
+ // FullPayloadSubscribe flushes and changes full subscription on websocket
+ // connection by subscribing with full default stream channel list
+ FullPayloadSubscribe bool `json:"fullPayloadSubscribe,omitempty"`
Subscribe bool `json:"subscribe,omitempty"`
Unsubscribe bool `json:"unsubscribe,omitempty"`
AuthenticatedEndpoints bool `json:"authenticatedEndpoints,omitempty"`
diff --git a/exchanges/sharedtestvalues/sharedtestvalues.go b/exchanges/sharedtestvalues/sharedtestvalues.go
index 254e9156..3bd871a9 100644
--- a/exchanges/sharedtestvalues/sharedtestvalues.go
+++ b/exchanges/sharedtestvalues/sharedtestvalues.go
@@ -1,6 +1,10 @@
package sharedtestvalues
-import "time"
+import (
+ "time"
+
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
+)
// This package is only to be referenced in test files
const (
@@ -29,3 +33,17 @@ func GetWebsocketInterfaceChannelOverride() chan interface{} {
func GetWebsocketStructChannelOverride() chan struct{} {
return make(chan struct{}, WebsocketChannelOverrideCapacity)
}
+
+// NewTestWebsocket returns a test websocket object
+func NewTestWebsocket() *stream.Websocket {
+ return &stream.Websocket{
+ Init: true,
+ DataHandler: make(chan interface{}, 75),
+ ToRoutine: make(chan interface{}, 1000),
+ TrafficAlert: make(chan struct{}),
+ ReadMessageErrors: make(chan error),
+ Subscribe: make(chan []stream.ChannelSubscription, 10),
+ Unsubscribe: make(chan []stream.ChannelSubscription, 10),
+ Match: stream.NewMatch(),
+ }
+}
diff --git a/exchanges/stats/stats.go b/exchanges/stats/stats.go
index f9805eed..85b145dc 100644
--- a/exchanges/stats/stats.go
+++ b/exchanges/stats/stats.go
@@ -1,6 +1,7 @@
package stats
import (
+ "errors"
"sort"
"github.com/thrasher-corp/gocryptotrader/currency"
@@ -50,40 +51,48 @@ func (b ByVolume) Swap(i, j int) {
}
// Add adds or updates the item stats
-func Add(exchange string, p currency.Pair, assetType asset.Item, price, volume float64) {
+func Add(exchange string, p currency.Pair, a asset.Item, price, volume float64) error {
if exchange == "" ||
- assetType == "" ||
+ a == "" ||
price == 0 ||
volume == 0 ||
p.Base.IsEmpty() ||
p.Quote.IsEmpty() {
- return
+ return errors.New("cannot add or update, invalid params")
}
if p.Base == currency.XBT {
- newPair := currency.NewPairFromStrings(currency.BTC.String(), p.Quote.String())
- Append(exchange, newPair, assetType, price, volume)
+ newPair, err := currency.NewPairFromStrings(currency.BTC.String(),
+ p.Quote.String())
+ if err != nil {
+ return err
+ }
+ Append(exchange, newPair, a, price, volume)
}
if p.Quote == currency.USDT {
- newPair := currency.NewPairFromStrings(p.Base.String(), currency.USD.String())
- Append(exchange, newPair, assetType, price, volume)
+ newPair, err := currency.NewPairFromStrings(p.Base.String(), currency.USD.String())
+ if err != nil {
+ return err
+ }
+ Append(exchange, newPair, a, price, volume)
}
- Append(exchange, p, assetType, price, volume)
+ Append(exchange, p, a, price, volume)
+ return nil
}
// Append adds or updates the item stats for a specific
// currency pair and asset type
-func Append(exchange string, p currency.Pair, assetType asset.Item, price, volume float64) {
- if AlreadyExists(exchange, p, assetType, price, volume) {
+func Append(exchange string, p currency.Pair, a asset.Item, price, volume float64) {
+ if AlreadyExists(exchange, p, a, price, volume) {
return
}
i := Item{
Exchange: exchange,
Pair: p,
- AssetType: assetType,
+ AssetType: a,
Price: price,
Volume: volume,
}
diff --git a/exchanges/stats/stats_test.go b/exchanges/stats/stats_test.go
index 06aea628..ad8c80a2 100644
--- a/exchanges/stats/stats_test.go
+++ b/exchanges/stats/stats_test.go
@@ -12,7 +12,10 @@ const (
)
func TestLenByPrice(t *testing.T) {
- p := currency.NewPairFromStrings("BTC", "USD")
+ p, err := currency.NewPairFromStrings("BTC", "USD")
+ if err != nil {
+ t.Fatal(err)
+ }
Items = []Item{
{
Exchange: testExchange,
@@ -29,8 +32,10 @@ func TestLenByPrice(t *testing.T) {
}
func TestLessByPrice(t *testing.T) {
- p := currency.NewPairFromStrings("BTC", "USD")
-
+ p, err := currency.NewPairFromStrings("BTC", "USD")
+ if err != nil {
+ t.Fatal(err)
+ }
Items = []Item{
{
Exchange: "alphapoint",
@@ -57,8 +62,10 @@ func TestLessByPrice(t *testing.T) {
}
func TestSwapByPrice(t *testing.T) {
- p := currency.NewPairFromStrings("BTC", "USD")
-
+ p, err := currency.NewPairFromStrings("BTC", "USD")
+ if err != nil {
+ t.Fatal(err)
+ }
Items = []Item{
{
Exchange: "bitstamp",
@@ -107,27 +114,42 @@ func TestSwapByVolume(t *testing.T) {
func TestAdd(t *testing.T) {
Items = Items[:0]
- p := currency.NewPairFromStrings("BTC", "USD")
- Add(testExchange, p, asset.Spot, 1200, 42)
+ p, err := currency.NewPairFromStrings("BTC", "USD")
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = Add(testExchange, p, asset.Spot, 1200, 42)
+ if err != nil {
+ t.Fatal(err)
+ }
if len(Items) < 1 {
t.Error("stats Add did not add exchange info.")
}
- Add("", p, "", 0, 0)
+ err = Add("", p, "", 0, 0)
+ if err == nil {
+ t.Fatal("error cannot be nil")
+ }
if len(Items) != 1 {
t.Error("stats Add did not add exchange info.")
}
p.Base = currency.XBT
- Add(testExchange, p, asset.Spot, 1201, 43)
+ err = Add(testExchange, p, asset.Spot, 1201, 43)
+ if err != nil {
+ t.Fatal(err)
+ }
if Items[1].Pair.String() != "XBTUSD" {
t.Fatal("stats Add did not add exchange info.")
}
- p = currency.NewPairFromStrings("ETH", "USDT")
+ p, err = currency.NewPairFromStrings("ETH", "USDT")
+ if err != nil {
+ t.Fatal(err)
+ }
Add(testExchange, p, asset.Spot, 300, 1000)
if Items[2].Pair.String() != "ETHUSD" {
@@ -136,7 +158,10 @@ func TestAdd(t *testing.T) {
}
func TestAppend(t *testing.T) {
- p := currency.NewPairFromStrings("BTC", "USD")
+ p, err := currency.NewPairFromStrings("BTC", "USD")
+ if err != nil {
+ t.Fatal(err)
+ }
Append("sillyexchange", p, asset.Spot, 1234, 45)
if len(Items) < 2 {
t.Error("stats Append did not add exchange values.")
@@ -149,7 +174,10 @@ func TestAppend(t *testing.T) {
}
func TestAlreadyExists(t *testing.T) {
- p := currency.NewPairFromStrings("BTC", "USD")
+ p, err := currency.NewPairFromStrings("BTC", "USD")
+ if err != nil {
+ t.Fatal(err)
+ }
if !AlreadyExists(testExchange, p, asset.Spot, 1200, 42) {
t.Error("stats AlreadyExists exchange does not exist.")
}
@@ -160,7 +188,10 @@ func TestAlreadyExists(t *testing.T) {
}
func TestSortExchangesByVolume(t *testing.T) {
- p := currency.NewPairFromStrings("BTC", "USD")
+ p, err := currency.NewPairFromStrings("BTC", "USD")
+ if err != nil {
+ t.Fatal(err)
+ }
topVolume := SortExchangesByVolume(p, asset.Spot, true)
if topVolume[0].Exchange != "sillyexchange" {
t.Error("stats SortExchangesByVolume incorrectly sorted values.")
@@ -173,7 +204,10 @@ func TestSortExchangesByVolume(t *testing.T) {
}
func TestSortExchangesByPrice(t *testing.T) {
- p := currency.NewPairFromStrings("BTC", "USD")
+ p, err := currency.NewPairFromStrings("BTC", "USD")
+ if err != nil {
+ t.Fatal(err)
+ }
topPrice := SortExchangesByPrice(p, asset.Spot, true)
if topPrice[0].Exchange != "sillyexchange" {
t.Error("stats SortExchangesByPrice incorrectly sorted values.")
diff --git a/exchanges/websocket/wsorderbook/wsorderbook.go b/exchanges/stream/buffer/buffer.go
similarity index 81%
rename from exchanges/websocket/wsorderbook/wsorderbook.go
rename to exchanges/stream/buffer/buffer.go
index 169eb0a2..7ef4d90e 100644
--- a/exchanges/websocket/wsorderbook/wsorderbook.go
+++ b/exchanges/stream/buffer/buffer.go
@@ -1,4 +1,4 @@
-package wsorderbook
+package buffer
import (
"errors"
@@ -11,21 +11,22 @@ import (
)
// Setup sets private variables
-func (w *WebsocketOrderbookLocal) Setup(obBufferLimit int, bufferEnabled, sortBuffer, sortBufferByUpdateIDs, updateEntriesByID bool, exchangeName string) {
+func (w *Orderbook) Setup(obBufferLimit int, bufferEnabled, sortBuffer, sortBufferByUpdateIDs, updateEntriesByID bool, exchangeName string, dataHandler chan interface{}) {
w.obBufferLimit = obBufferLimit
w.bufferEnabled = bufferEnabled
w.sortBuffer = sortBuffer
w.sortBufferByUpdateIDs = sortBufferByUpdateIDs
w.updateEntriesByID = updateEntriesByID
w.exchangeName = exchangeName
+ w.dataHandler = dataHandler
}
-// Update updates a local cache using bid targets and ask targets then updates
+// Update updates a local buffer using bid targets and ask targets then updates
// main orderbook
// Volume == 0; deletion at price target
// Price target not found; append of price target
// Price target found; amend volume of price target
-func (w *WebsocketOrderbookLocal) Update(u *WebsocketOrderbookUpdate) error {
+func (w *Orderbook) Update(u *Update) error {
if (u.Bids == nil && u.Asks == nil) || (len(u.Bids) == 0 && len(u.Asks) == 0) {
return fmt.Errorf("%v cannot have bids and ask targets both nil",
w.exchangeName)
@@ -52,19 +53,23 @@ func (w *WebsocketOrderbookLocal) Update(u *WebsocketOrderbookUpdate) error {
if err != nil {
return err
}
+
if w.bufferEnabled {
// Reset the buffer
w.buffer[u.Pair][u.Asset] = nil
}
+
+ // Process in data handler
+ w.dataHandler <- obLookup
return nil
}
-func (w *WebsocketOrderbookLocal) processBufferUpdate(o *orderbook.Base, u *WebsocketOrderbookUpdate) bool {
+func (w *Orderbook) processBufferUpdate(o *orderbook.Base, u *Update) bool {
if w.buffer == nil {
- w.buffer = make(map[currency.Pair]map[asset.Item][]*WebsocketOrderbookUpdate)
+ w.buffer = make(map[currency.Pair]map[asset.Item][]*Update)
}
if w.buffer[u.Pair] == nil {
- w.buffer[u.Pair] = make(map[asset.Item][]*WebsocketOrderbookUpdate)
+ w.buffer[u.Pair] = make(map[asset.Item][]*Update)
}
bufferLookup := w.buffer[u.Pair][u.Asset]
if len(bufferLookup) <= w.obBufferLimit {
@@ -93,7 +98,7 @@ func (w *WebsocketOrderbookLocal) processBufferUpdate(o *orderbook.Base, u *Webs
return true
}
-func (w *WebsocketOrderbookLocal) processObUpdate(o *orderbook.Base, u *WebsocketOrderbookUpdate) {
+func (w *Orderbook) processObUpdate(o *orderbook.Base, u *Update) {
o.LastUpdateID = u.UpdateID
if w.updateEntriesByID {
@@ -104,7 +109,7 @@ func (w *WebsocketOrderbookLocal) processObUpdate(o *orderbook.Base, u *Websocke
}
}
-func (w *WebsocketOrderbookLocal) updateAsksByPrice(o *orderbook.Base, u *WebsocketOrderbookUpdate) {
+func (w *Orderbook) updateAsksByPrice(o *orderbook.Base, u *Update) {
updates:
for j := range u.Asks {
for k := range o.Asks {
@@ -127,7 +132,7 @@ updates:
})
}
-func (w *WebsocketOrderbookLocal) updateBidsByPrice(o *orderbook.Base, u *WebsocketOrderbookUpdate) {
+func (w *Orderbook) updateBidsByPrice(o *orderbook.Base, u *Update) {
updates:
for j := range u.Bids {
for k := range o.Bids {
@@ -152,7 +157,7 @@ updates:
// updateByIDAndAction will receive an action to execute against the orderbook
// it will then match by IDs instead of price to perform the action
-func (w *WebsocketOrderbookLocal) updateByIDAndAction(o *orderbook.Base, u *WebsocketOrderbookUpdate) {
+func (w *Orderbook) updateByIDAndAction(o *orderbook.Base, u *Update) {
switch u.Action {
case "update":
for x := range u.Bids {
@@ -227,7 +232,7 @@ func (w *WebsocketOrderbookLocal) updateByIDAndAction(o *orderbook.Base, u *Webs
// LoadSnapshot loads initial snapshot of ob data, overwrite allows full
// ob to be completely rewritten because the exchange is a doing a full
// update not an incremental one
-func (w *WebsocketOrderbookLocal) LoadSnapshot(newOrderbook *orderbook.Base) error {
+func (w *Orderbook) LoadSnapshot(newOrderbook *orderbook.Base) error {
if len(newOrderbook.Asks) == 0 || len(newOrderbook.Bids) == 0 {
return fmt.Errorf("%v snapshot ask and bids are nil", w.exchangeName)
}
@@ -254,21 +259,27 @@ func (w *WebsocketOrderbookLocal) LoadSnapshot(newOrderbook *orderbook.Base) err
}
w.ob[newOrderbook.Pair][newOrderbook.AssetType] = newOrderbook
- return newOrderbook.Process()
+ err := newOrderbook.Process()
+ if err != nil {
+ return err
+ }
+
+ w.dataHandler <- newOrderbook
+ return nil
}
// GetOrderbook use sparingly. Modifying anything here will ruin hash
// calculation and cause problems
-func (w *WebsocketOrderbookLocal) GetOrderbook(p currency.Pair, a asset.Item) *orderbook.Base {
+func (w *Orderbook) GetOrderbook(p currency.Pair, a asset.Item) *orderbook.Base {
w.m.Lock()
ob := w.ob[p][a]
w.m.Unlock()
return ob
}
-// FlushCache flushes w.ob data to be garbage collected and refreshed when a
+// FlushBuffer flushes w.ob data to be garbage collected and refreshed when a
// connection is lost and reconnected
-func (w *WebsocketOrderbookLocal) FlushCache() {
+func (w *Orderbook) FlushBuffer() {
w.m.Lock()
w.ob = nil
w.buffer = nil
diff --git a/exchanges/websocket/wsorderbook/wsorderbook_test.go b/exchanges/stream/buffer/buffer_test.go
similarity index 92%
rename from exchanges/websocket/wsorderbook/wsorderbook_test.go
rename to exchanges/stream/buffer/buffer_test.go
index 0393712e..a62649b2 100644
--- a/exchanges/websocket/wsorderbook/wsorderbook_test.go
+++ b/exchanges/stream/buffer/buffer_test.go
@@ -1,4 +1,4 @@
-package wsorderbook
+package buffer
import (
"fmt"
@@ -20,13 +20,13 @@ var itemArray = [][]orderbook.Item{
{{Price: 5000, Amount: 1, ID: 5}},
}
-var cp = currency.NewPairFromString("BTCUSD")
+var cp, _ = currency.NewPairFromString("BTCUSD")
const (
exchangeName = "exchangeTest"
)
-func createSnapshot() (obl *WebsocketOrderbookLocal, asks, bids []orderbook.Item, err error) {
+func createSnapshot() (obl *Orderbook, asks, bids []orderbook.Item, err error) {
var snapShot1 orderbook.Base
snapShot1.ExchangeName = exchangeName
asks = []orderbook.Item{
@@ -39,7 +39,7 @@ func createSnapshot() (obl *WebsocketOrderbookLocal, asks, bids []orderbook.Item
snapShot1.Bids = bids
snapShot1.AssetType = asset.Spot
snapShot1.Pair = cp
- obl = &WebsocketOrderbookLocal{exchangeName: exchangeName}
+ obl = &Orderbook{exchangeName: exchangeName, dataHandler: make(chan interface{}, 100)}
err = obl.LoadSnapshot(&snapShot1)
return
}
@@ -69,7 +69,7 @@ func BenchmarkUpdateBidsByPrice(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
bidAsks := bidAskGenerator()
- update := &WebsocketOrderbookUpdate{
+ update := &Update{
Bids: bidAsks,
Asks: bidAsks,
Pair: cp,
@@ -88,7 +88,7 @@ func BenchmarkUpdateAsksByPrice(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
bidAsks := bidAskGenerator()
- update := &WebsocketOrderbookUpdate{
+ update := &Update{
Bids: bidAsks,
Asks: bidAsks,
Pair: cp,
@@ -115,7 +115,7 @@ func BenchmarkBufferPerformance(b *testing.B) {
ID: 1337,
}
obl.ob[cp][asset.Spot].Bids = append(obl.ob[cp][asset.Spot].Bids, dummyItem)
- update := &WebsocketOrderbookUpdate{
+ update := &Update{
Bids: bids,
Asks: asks,
Pair: cp,
@@ -150,7 +150,7 @@ func BenchmarkBufferSortingPerformance(b *testing.B) {
ID: 1337,
}
obl.ob[cp][asset.Spot].Bids = append(obl.ob[cp][asset.Spot].Bids, dummyItem)
- update := &WebsocketOrderbookUpdate{
+ update := &Update{
Bids: bids,
Asks: asks,
Pair: cp,
@@ -186,7 +186,7 @@ func BenchmarkBufferSortingByIDPerformance(b *testing.B) {
ID: 1337,
}
obl.ob[cp][asset.Spot].Bids = append(obl.ob[cp][asset.Spot].Bids, dummyItem)
- update := &WebsocketOrderbookUpdate{
+ update := &Update{
Bids: bids,
Asks: asks,
Pair: cp,
@@ -220,7 +220,7 @@ func BenchmarkNoBufferPerformance(b *testing.B) {
ID: 1337,
}
obl.ob[cp][asset.Spot].Bids = append(obl.ob[cp][asset.Spot].Bids, dummyItem)
- update := &WebsocketOrderbookUpdate{
+ update := &Update{
Bids: bids,
Asks: asks,
Pair: cp,
@@ -245,7 +245,7 @@ func TestUpdates(t *testing.T) {
t.Error(err)
}
- obl.updateAsksByPrice(obl.ob[cp][asset.Spot], &WebsocketOrderbookUpdate{
+ obl.updateAsksByPrice(obl.ob[cp][asset.Spot], &Update{
Bids: itemArray[5],
Asks: itemArray[5],
Pair: cp,
@@ -256,7 +256,7 @@ func TestUpdates(t *testing.T) {
t.Error(err)
}
- obl.updateAsksByPrice(obl.ob[cp][asset.Spot], &WebsocketOrderbookUpdate{
+ obl.updateAsksByPrice(obl.ob[cp][asset.Spot], &Update{
Bids: itemArray[0],
Asks: itemArray[0],
Pair: cp,
@@ -283,7 +283,7 @@ func TestHittingTheBuffer(t *testing.T) {
for i := range itemArray {
asks := itemArray[i]
bids := itemArray[i]
- err = obl.Update(&WebsocketOrderbookUpdate{
+ err = obl.Update(&Update{
Bids: bids,
Asks: asks,
Pair: cp,
@@ -317,7 +317,7 @@ func TestInsertWithIDs(t *testing.T) {
for i := range itemArray {
asks := itemArray[i]
bids := itemArray[i]
- err = obl.Update(&WebsocketOrderbookUpdate{
+ err = obl.Update(&Update{
Bids: bids,
Asks: asks,
Pair: cp,
@@ -352,7 +352,7 @@ func TestSortIDs(t *testing.T) {
for i := range itemArray {
asks := itemArray[i]
bids := itemArray[i]
- err = obl.Update(&WebsocketOrderbookUpdate{
+ err = obl.Update(&Update{
Bids: bids,
Asks: asks,
Pair: cp,
@@ -397,7 +397,7 @@ func TestDeleteWithIDs(t *testing.T) {
for i := range itemArray {
asks := itemArray[i]
bids := itemArray[i]
- err = obl.Update(&WebsocketOrderbookUpdate{
+ err = obl.Update(&Update{
Bids: bids,
Asks: asks,
Pair: cp,
@@ -430,7 +430,7 @@ func TestUpdateWithIDs(t *testing.T) {
for i := range itemArray {
asks := itemArray[i]
bids := itemArray[i]
- err = obl.Update(&WebsocketOrderbookUpdate{
+ err = obl.Update(&Update{
Bids: bids,
Asks: asks,
Pair: cp,
@@ -469,7 +469,7 @@ func TestOutOfOrderIDs(t *testing.T) {
obl.obBufferLimit = 5
for i := range itemArray {
asks := itemArray[i]
- err = obl.Update(&WebsocketOrderbookUpdate{
+ err = obl.Update(&Update{
Asks: asks,
Pair: cp,
UpdateID: outOFOrderIDs[i],
@@ -498,7 +498,7 @@ func TestOrderbookLastUpdateID(t *testing.T) {
for i := range itemArray {
asks := itemArray[i]
- err = obl.Update(&WebsocketOrderbookUpdate{
+ err = obl.Update(&Update{
Asks: asks,
Pair: cp,
UpdateID: int64(i) + 1,
@@ -517,7 +517,7 @@ func TestOrderbookLastUpdateID(t *testing.T) {
// TestRunUpdateWithoutSnapshot logic test
func TestRunUpdateWithoutSnapshot(t *testing.T) {
- var obl WebsocketOrderbookLocal
+ var obl Orderbook
var snapShot1 orderbook.Base
asks := []orderbook.Item{
{Price: 4000, Amount: 1, ID: 8},
@@ -531,7 +531,7 @@ func TestRunUpdateWithoutSnapshot(t *testing.T) {
snapShot1.AssetType = asset.Spot
snapShot1.Pair = cp
obl.exchangeName = exchangeName
- err := obl.Update(&WebsocketOrderbookUpdate{
+ err := obl.Update(&Update{
Bids: bids,
Asks: asks,
Pair: cp,
@@ -548,14 +548,14 @@ func TestRunUpdateWithoutSnapshot(t *testing.T) {
// TestRunUpdateWithoutAnyUpdates logic test
func TestRunUpdateWithoutAnyUpdates(t *testing.T) {
- var obl WebsocketOrderbookLocal
+ var obl Orderbook
var snapShot1 orderbook.Base
snapShot1.Asks = []orderbook.Item{}
snapShot1.Bids = []orderbook.Item{}
snapShot1.AssetType = asset.Spot
snapShot1.Pair = cp
obl.exchangeName = exchangeName
- err := obl.Update(&WebsocketOrderbookUpdate{
+ err := obl.Update(&Update{
Bids: snapShot1.Asks,
Asks: snapShot1.Bids,
Pair: cp,
@@ -573,7 +573,7 @@ func TestRunUpdateWithoutAnyUpdates(t *testing.T) {
// TestRunSnapshotWithNoData logic test
func TestRunSnapshotWithNoData(t *testing.T) {
- var obl WebsocketOrderbookLocal
+ var obl Orderbook
var snapShot1 orderbook.Base
snapShot1.Asks = []orderbook.Item{}
snapShot1.Bids = []orderbook.Item{}
@@ -592,7 +592,8 @@ func TestRunSnapshotWithNoData(t *testing.T) {
// TestLoadSnapshot logic test
func TestLoadSnapshot(t *testing.T) {
- var obl WebsocketOrderbookLocal
+ var obl Orderbook
+ obl.dataHandler = make(chan interface{}, 100)
var snapShot1 orderbook.Base
snapShot1.ExchangeName = "SnapshotWithOverride"
asks := []orderbook.Item{
@@ -611,8 +612,8 @@ func TestLoadSnapshot(t *testing.T) {
}
}
-// TestFlushCache logic test
-func TestFlushCache(t *testing.T) {
+// TestFlushbuffer logic test
+func TestFlushbuffer(t *testing.T) {
obl, _, _, err := createSnapshot()
if err != nil {
t.Fatal(err)
@@ -620,7 +621,7 @@ func TestFlushCache(t *testing.T) {
if obl.ob[cp][asset.Spot] == nil {
t.Error("expected ob to have ask entries")
}
- obl.FlushCache()
+ obl.FlushBuffer()
if obl.ob[cp][asset.Spot] != nil {
t.Error("expected ob be flushed")
}
@@ -628,7 +629,8 @@ func TestFlushCache(t *testing.T) {
// TestInsertingSnapShots logic test
func TestInsertingSnapShots(t *testing.T) {
- var obl WebsocketOrderbookLocal
+ var obl Orderbook
+ obl.dataHandler = make(chan interface{}, 100)
var snapShot1 orderbook.Base
snapShot1.ExchangeName = "WSORDERBOOKTEST1"
asks := []orderbook.Item{
@@ -700,7 +702,10 @@ func TestInsertingSnapShots(t *testing.T) {
snapShot2.Asks = asks
snapShot2.Bids = bids
snapShot2.AssetType = asset.Spot
- snapShot2.Pair = currency.NewPairFromString("LTCUSD")
+ snapShot2.Pair, err = currency.NewPairFromString("LTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
err = obl.LoadSnapshot(&snapShot2)
if err != nil {
t.Fatal(err)
@@ -738,7 +743,10 @@ func TestInsertingSnapShots(t *testing.T) {
snapShot3.Asks = asks
snapShot3.Bids = bids
snapShot3.AssetType = "FUTURES"
- snapShot3.Pair = currency.NewPairFromString("LTCUSD")
+ snapShot3.Pair, err = currency.NewPairFromString("LTCUSD")
+ if err != nil {
+ t.Fatal(err)
+ }
err = obl.LoadSnapshot(&snapShot3)
if err != nil {
t.Fatal(err)
@@ -772,8 +780,8 @@ func TestGetOrderbook(t *testing.T) {
}
func TestSetup(t *testing.T) {
- w := WebsocketOrderbookLocal{}
- w.Setup(1, true, true, true, true, "hi")
+ w := Orderbook{}
+ w.Setup(1, true, true, true, true, "hi", make(chan interface{}))
if w.obBufferLimit != 1 ||
!w.bufferEnabled ||
!w.sortBuffer ||
@@ -791,7 +799,7 @@ func TestEnsureMultipleUpdatesViaPrice(t *testing.T) {
}
asks := bidAskGenerator()
- obl.updateAsksByPrice(obl.ob[cp][asset.Spot], &WebsocketOrderbookUpdate{
+ obl.updateAsksByPrice(obl.ob[cp][asset.Spot], &Update{
Bids: asks,
Asks: asks,
Pair: cp,
diff --git a/exchanges/websocket/wsorderbook/wsorderbook_types.go b/exchanges/stream/buffer/buffer_types.go
similarity index 65%
rename from exchanges/websocket/wsorderbook/wsorderbook_types.go
rename to exchanges/stream/buffer/buffer_types.go
index 2ae77a29..93020b85 100644
--- a/exchanges/websocket/wsorderbook/wsorderbook_types.go
+++ b/exchanges/stream/buffer/buffer_types.go
@@ -1,4 +1,4 @@
-package wsorderbook
+package buffer
import (
"sync"
@@ -9,22 +9,23 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
)
-// WebsocketOrderbookLocal defines a local cache of orderbooks for amending,
-// appending and deleting changes and updates the main store in wsorderbook.go
-type WebsocketOrderbookLocal struct {
+// Orderbook defines a local cache of orderbooks for amending, appending
+// and deleting changes and updates the main store for a stream
+type Orderbook struct {
ob map[currency.Pair]map[asset.Item]*orderbook.Base
- buffer map[currency.Pair]map[asset.Item][]*WebsocketOrderbookUpdate
+ buffer map[currency.Pair]map[asset.Item][]*Update
obBufferLimit int
bufferEnabled bool
sortBuffer bool
sortBufferByUpdateIDs bool // When timestamps aren't provided, an id can help sort
updateEntriesByID bool // Use the update IDs to match ob entries
exchangeName string
+ dataHandler chan interface{}
m sync.Mutex
}
-// WebsocketOrderbookUpdate stores orderbook updates and dictates what features to use when processing
-type WebsocketOrderbookUpdate struct {
+// Update stores orderbook updates and dictates what features to use when processing
+type Update struct {
UpdateID int64 // Used when no time is provided
UpdateTime time.Time
Asset asset.Item
diff --git a/exchanges/stream/stream_match.go b/exchanges/stream/stream_match.go
new file mode 100644
index 00000000..ecf30583
--- /dev/null
+++ b/exchanges/stream/stream_match.go
@@ -0,0 +1,81 @@
+package stream
+
+import (
+ "errors"
+ "sync"
+)
+
+// NewMatch returns a new matcher
+func NewMatch() *Match {
+ return &Match{
+ m: make(map[interface{}]chan []byte),
+ }
+}
+
+// Match is a distributed subtype that handles the matching of requests and
+// responses in a timely manner, reducing the need to differentiate between
+// connections. Stream systems fan in all incoming payloads to one routine for
+// processing.
+type Match struct {
+ m map[interface{}]chan []byte
+ sync.Mutex
+}
+
+// Incoming matches with request, disregarding the returned payload
+func (m *Match) Incoming(signature interface{}) bool {
+ return m.IncomingWithData(signature, nil)
+}
+
+// IncomingWithData matches with requests and takes in the returned payload, to
+// be processed outside of a stream processing routine
+func (m *Match) IncomingWithData(signature interface{}, data []byte) bool {
+ m.Lock()
+ defer m.Unlock()
+ ch, ok := m.m[signature]
+ if ok {
+ select {
+ case ch <- data:
+ default:
+ // this shouldn't occur but if it does continue to process as normal
+ return false
+ }
+ return true
+ }
+ return false
+}
+
+// Sets the signature response channel for incoming data
+func (m *Match) set(signature interface{}) (matcher, error) {
+ var ch chan []byte
+ m.Lock()
+ _, ok := m.m[signature]
+ if ok {
+ m.Unlock()
+ return matcher{}, errors.New("signature collision")
+ }
+ // This is buffered so we don't need to wait for receiver.
+ ch = make(chan []byte, 1)
+ m.m[signature] = ch
+ m.Unlock()
+
+ return matcher{
+ C: ch,
+ sig: signature,
+ m: m,
+ }, nil
+}
+
+// matcher defines a payload matching return mechanism
+type matcher struct {
+ C chan []byte
+ sig interface{}
+ m *Match
+}
+
+// Cleanup closes underlying channel and deletes signature from map
+func (m *matcher) Cleanup() {
+ m.m.Lock()
+ close(m.C)
+ delete(m.m.m, m.sig)
+ m.m.Unlock()
+}
diff --git a/exchanges/stream/stream_match_test.go b/exchanges/stream/stream_match_test.go
new file mode 100644
index 00000000..743a2d94
--- /dev/null
+++ b/exchanges/stream/stream_match_test.go
@@ -0,0 +1,50 @@
+package stream
+
+import (
+ "fmt"
+ "testing"
+)
+
+func TestMatch(t *testing.T) {
+ bm := &Match{}
+ if bm.Incoming("wow") {
+ t.Fatal("Should not have matched")
+ }
+
+ nm := NewMatch()
+ // try to match with unset signature
+ if nm.Incoming("hello") {
+ t.Fatal("should not be able to match")
+ }
+
+ m, err := nm.set("hello")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ _, err = nm.set("hello")
+ if err == nil {
+ t.Fatal("error cannot be nil as this collision cannot occur")
+ }
+
+ if m.sig != "hello" {
+ t.Fatal(err)
+ }
+
+ // try and match with initial payload
+ if !nm.Incoming("hello") {
+ t.Fatal("should of matched")
+ }
+
+ // put in secondary payload with conflicting signature
+ if nm.Incoming("hello") {
+ fmt.Println("should not have been able to match")
+ }
+
+ data := <-m.C
+ if data != nil {
+ t.Fatal("wow")
+ }
+
+ m.Cleanup()
+}
diff --git a/exchanges/stream/stream_types.go b/exchanges/stream/stream_types.go
new file mode 100644
index 00000000..311d26a6
--- /dev/null
+++ b/exchanges/stream/stream_types.go
@@ -0,0 +1,111 @@
+package stream
+
+import (
+ "net/http"
+ "time"
+
+ "github.com/gorilla/websocket"
+ "github.com/thrasher-corp/gocryptotrader/currency"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/asset"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/order"
+)
+
+// Connection defines a streaming services connection
+type Connection interface {
+ Dial(*websocket.Dialer, http.Header) error
+ ReadMessage() Response
+ SendJSONMessage(interface{}) error
+ SetupPingHandler(PingHandler)
+ GenerateMessageID(highPrecision bool) int64
+ SendMessageReturnResponse(signature interface{}, request interface{}) ([]byte, error)
+ SendRawMessage(messageType int, message []byte) error
+ SetURL(string)
+ SetProxy(string)
+ GetURL() string
+ Shutdown() error
+}
+
+// Response defines generalised data from the stream connection
+type Response struct {
+ Type int
+ Raw []byte
+}
+
+// ChannelSubscription container for streaming subscriptions
+type ChannelSubscription struct {
+ Channel string
+ Currency currency.Pair
+ Asset asset.Item
+ Params map[string]interface{}
+}
+
+// ConnectionSetup defines variables for an individual stream connection
+type ConnectionSetup struct {
+ ResponseCheckTimeout time.Duration
+ ResponseMaxLimit time.Duration
+ RateLimit int64
+ URL string
+ Authenticated bool
+}
+
+// PingHandler container for ping handler settings
+type PingHandler struct {
+ Websocket bool
+ UseGorillaHandler bool
+ MessageType int
+ Message []byte
+ Delay time.Duration
+}
+
+// TradeData defines trade data
+type TradeData struct {
+ Timestamp time.Time
+ CurrencyPair currency.Pair
+ AssetType asset.Item
+ Exchange string
+ EventType order.Type
+ Price float64
+ Amount float64
+ Side order.Side
+}
+
+// FundingData defines funding data
+type FundingData struct {
+ Timestamp time.Time
+ CurrencyPair currency.Pair
+ AssetType asset.Item
+ Exchange string
+ Amount float64
+ Rate float64
+ Period int64
+ Side order.Side
+}
+
+// KlineData defines kline feed
+type KlineData struct {
+ Timestamp time.Time
+ Pair currency.Pair
+ AssetType asset.Item
+ Exchange string
+ StartTime time.Time
+ CloseTime time.Time
+ Interval string
+ OpenPrice float64
+ ClosePrice float64
+ HighPrice float64
+ LowPrice float64
+ Volume float64
+}
+
+// WebsocketPositionUpdated reflects a change in orders/contracts on an exchange
+type WebsocketPositionUpdated struct {
+ Timestamp time.Time
+ Pair currency.Pair
+ AssetType asset.Item
+ Exchange string
+}
+
+// UnhandledMessageWarning defines a container for unhandled message warnings
+type UnhandledMessageWarning struct {
+ Message string
+}
diff --git a/exchanges/stream/websocket.go b/exchanges/stream/websocket.go
new file mode 100644
index 00000000..6ee1e0c7
--- /dev/null
+++ b/exchanges/stream/websocket.go
@@ -0,0 +1,935 @@
+package stream
+
+import (
+ "errors"
+ "fmt"
+ "net"
+ "net/url"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/gorilla/websocket"
+ "github.com/thrasher-corp/gocryptotrader/config"
+ "github.com/thrasher-corp/gocryptotrader/log"
+)
+
+const (
+ defaultJobBuffer = 1000
+ // defaultTrafficPeriod defines a period of pause for the traffic monitor,
+ // as there are periods with large incoming traffic alerts which requires a
+ // timer reset, this limits work on this routine to a more effective rate
+ // of check.
+ defaultTrafficPeriod = time.Second
+)
+
+// New initialises the websocket struct
+func New() *Websocket {
+ return &Websocket{
+ Init: true,
+ DataHandler: make(chan interface{}),
+ ToRoutine: make(chan interface{}, defaultJobBuffer),
+ TrafficAlert: make(chan struct{}),
+ ReadMessageErrors: make(chan error),
+ Subscribe: make(chan []ChannelSubscription),
+ Unsubscribe: make(chan []ChannelSubscription),
+ Match: NewMatch(),
+ }
+}
+
+// Setup sets main variables for websocket connection
+func (w *Websocket) Setup(s *WebsocketSetup) error {
+ if w == nil {
+ return errors.New("websocket is nil")
+ }
+
+ if !w.Init {
+ return fmt.Errorf("%s Websocket already initialised",
+ s.ExchangeName)
+ }
+
+ w.verbose = s.Verbose
+ if s.Features == nil {
+ return errors.New("websocket features is unset")
+ }
+
+ w.features = s.Features
+
+ if w.features.Subscribe && s.Subscriber == nil {
+ return errors.New("features have been set yet channel subscriber is not set")
+ }
+ w.Subscriber = s.Subscriber
+
+ if w.features.Unsubscribe && s.UnSubscriber == nil {
+ return errors.New("features have been set yet channel unsubscriber is not set")
+ }
+ w.Unsubscriber = s.UnSubscriber
+
+ w.GenerateSubs = s.GenerateSubscriptions
+
+ w.enabled = s.Enabled
+ if s.DefaultURL == "" {
+ return errors.New("default url is empty")
+ }
+ w.defaultURL = s.DefaultURL
+ if s.RunningURL == "" {
+ return errors.New("running URL cannot be nil")
+ }
+ err := w.SetWebsocketURL(s.RunningURL, false, false)
+ if err != nil {
+ return err
+ }
+
+ if s.RunningURLAuth != "" {
+ err = w.SetWebsocketURL(s.RunningURLAuth, true, false)
+ if err != nil {
+ return err
+ }
+ }
+
+ w.connector = s.Connector
+ if s.ExchangeName == "" {
+ return errors.New("exchange name unset")
+ }
+ w.exchangeName = s.ExchangeName
+
+ if s.WebsocketTimeout < time.Second {
+ return fmt.Errorf("traffic timeout cannot be less than %s", time.Second)
+ }
+
+ w.trafficTimeout = s.WebsocketTimeout
+ if s.Features == nil {
+ return errors.New("feature set is nil")
+ }
+
+ w.ShutdownC = make(chan struct{})
+ w.Wg = new(sync.WaitGroup)
+
+ w.SetCanUseAuthenticatedEndpoints(s.AuthenticatedWebsocketAPISupport)
+ err = w.Initialise()
+ if err != nil {
+ return err
+ }
+
+ w.Orderbook.Setup(s.OrderbookBufferLimit,
+ s.BufferEnabled,
+ s.SortBuffer,
+ s.SortBufferByUpdateIDs,
+ s.UpdateEntriesByID,
+ w.exchangeName,
+ w.DataHandler)
+ return nil
+}
+
+// SetupNewConnection sets up an auth or unauth streaming connection
+func (w *Websocket) SetupNewConnection(c ConnectionSetup) error {
+ if w == nil {
+ return errors.New("setting up new connection error: websocket is nil")
+ }
+ if c == (ConnectionSetup{}) {
+ return errors.New("setting up new connection error: websocket connection configuration empty")
+ }
+
+ if w.exchangeName == "" {
+ return errors.New("setting up new connection error: exchange name not set, please call setup first")
+ }
+
+ if w.TrafficAlert == nil {
+ return errors.New("setting up new connection error: traffic alert is nil, please call setup first")
+ }
+
+ if w.ReadMessageErrors == nil {
+ return errors.New("setting up new connection error: read message errors is nil, please call setup first")
+ }
+
+ connectionURL := w.GetWebsocketURL()
+ if c.URL != "" {
+ connectionURL = c.URL
+ }
+
+ newConn := &WebsocketConnection{
+ ExchangeName: w.exchangeName,
+ URL: connectionURL,
+ ProxyURL: w.GetProxyAddress(),
+ Verbose: w.verbose,
+ ResponseMaxLimit: c.ResponseMaxLimit,
+ Traffic: w.TrafficAlert,
+ readMessageErrors: w.ReadMessageErrors,
+ ShutdownC: w.ShutdownC,
+ Wg: w.Wg,
+ Match: w.Match,
+ RateLimit: c.RateLimit,
+ }
+
+ if c.Authenticated {
+ w.AuthConn = newConn
+ } else {
+ w.Conn = newConn
+ }
+
+ return nil
+}
+
+// Connect initiates a websocket connection by using a package defined connection
+// function
+func (w *Websocket) Connect() error {
+ if w.connector == nil {
+ return errors.New("websocket connect function not set, cannot continue")
+ }
+ w.m.Lock()
+ defer w.m.Unlock()
+
+ if !w.IsEnabled() {
+ return errors.New(WebsocketNotEnabled)
+ }
+ if w.IsConnecting() {
+ return fmt.Errorf("%v Websocket already attempting to connect",
+ w.exchangeName)
+ }
+ if w.IsConnected() {
+ return fmt.Errorf("%v Websocket already connected",
+ w.exchangeName)
+ }
+ w.setConnectingStatus(true)
+
+ w.dataMonitor()
+
+ err := w.trafficMonitor()
+ if err != nil {
+ return err
+ }
+
+ // flush any subscriptions from last connection if needed
+ w.subscriptionMutex.Lock()
+ w.subscriptions = nil
+ w.subscriptionMutex.Unlock()
+
+ err = w.connector()
+ if err != nil {
+ w.setConnectingStatus(false)
+ return fmt.Errorf("%v Error connecting %s",
+ w.exchangeName, err)
+ }
+
+ w.setConnectedStatus(true)
+ w.setConnectingStatus(false)
+ w.setInit(true)
+
+ if !w.IsConnectionMonitorRunning() {
+ go w.connectionMonitor()
+ }
+
+ return nil
+}
+
+// Disable disables the exchange websocket protocol
+func (w *Websocket) Disable() error {
+ if !w.IsConnected() || !w.IsEnabled() {
+ return fmt.Errorf("websocket is already disabled for exchange %s",
+ w.exchangeName)
+ }
+
+ w.setEnabled(false)
+ return nil
+}
+
+// Enable enables the exchange websocket protocol
+func (w *Websocket) Enable() error {
+ if w.IsConnected() || w.IsEnabled() {
+ return fmt.Errorf("websocket is already enabled for exchange %s",
+ w.exchangeName)
+ }
+
+ w.setEnabled(true)
+ return w.Connect()
+}
+
+// dataMonitor monitors job throughput and logs if there is a back log of data
+func (w *Websocket) dataMonitor() {
+ if w.IsDataMonitorRunning() {
+ return
+ }
+ w.setDataMonitorRunning(true)
+ w.Wg.Add(1)
+
+ go func() {
+ defer func() {
+ for {
+ // Bleeds data from the websocket connection if needed
+ select {
+ case <-w.DataHandler:
+ default:
+ w.setDataMonitorRunning(false)
+ w.Wg.Done()
+ return
+ }
+ }
+ }()
+
+ for {
+ select {
+ case <-w.ShutdownC:
+ return
+ case d := <-w.DataHandler:
+ select {
+ case w.ToRoutine <- d:
+ case <-w.ShutdownC:
+ return
+ default:
+ log.Warnf(log.WebsocketMgr,
+ "%s exchange backlog in websocket processing detected",
+ w.exchangeName)
+ select {
+ case w.ToRoutine <- d:
+ case <-w.ShutdownC:
+ return
+ }
+ }
+ }
+ }
+ }()
+}
+
+// connectionMonitor ensures that the WS keeps connecting
+func (w *Websocket) connectionMonitor() {
+ if w.IsConnectionMonitorRunning() {
+ return
+ }
+ w.setConnectionMonitorRunning(true)
+ timer := time.NewTimer(connectionMonitorDelay)
+
+ for {
+ if w.verbose {
+ log.Debugf(log.WebsocketMgr,
+ "%v websocket: running connection monitor cycle\n",
+ w.exchangeName)
+ }
+ if !w.IsEnabled() {
+ if w.verbose {
+ log.Debugf(log.WebsocketMgr,
+ "%v websocket: connectionMonitor - websocket disabled, shutting down\n",
+ w.exchangeName)
+ }
+ if w.IsConnected() {
+ err := w.Shutdown()
+ if err != nil {
+ log.Error(log.WebsocketMgr, err)
+ }
+ }
+ if w.verbose {
+ log.Debugf(log.WebsocketMgr,
+ "%v websocket: connection monitor exiting\n",
+ w.exchangeName)
+ }
+ timer.Stop()
+ w.setConnectionMonitorRunning(false)
+ return
+ }
+ select {
+ case err := <-w.ReadMessageErrors:
+ // check if this error is a disconnection error
+ if isDisconnectionError(err) {
+ w.setInit(false)
+ log.Warnf(log.WebsocketMgr,
+ "%v websocket has been disconnected. Reason: %v",
+ w.exchangeName, err)
+ w.setConnectedStatus(false)
+ } else {
+ // pass off non disconnect errors to datahandler to manage
+ w.DataHandler <- err
+ }
+ case <-timer.C:
+ if !w.IsConnecting() && !w.IsConnected() {
+ err := w.Connect()
+ if err != nil {
+ log.Error(log.WebsocketMgr, err)
+ }
+ }
+ if !timer.Stop() {
+ select {
+ case <-timer.C:
+ default:
+ }
+ }
+ timer.Reset(connectionMonitorDelay)
+ }
+ }
+}
+
+// Shutdown attempts to shut down a websocket connection and associated routines
+// by using a package defined shutdown function
+func (w *Websocket) Shutdown() error {
+ w.m.Lock()
+ defer w.m.Unlock()
+
+ if !w.IsConnected() {
+ return fmt.Errorf("%v websocket: cannot shutdown a disconnected websocket",
+ w.exchangeName)
+ }
+
+ if w.IsConnecting() {
+ return fmt.Errorf("%v websocket: cannot shutdown, in the process of reconnection",
+ w.exchangeName)
+ }
+
+ if w.verbose {
+ log.Debugf(log.WebsocketMgr,
+ "%v websocket: shutting down websocket\n",
+ w.exchangeName)
+ }
+
+ defer w.Orderbook.FlushBuffer()
+
+ if w.Conn != nil {
+ if err := w.Conn.Shutdown(); err != nil {
+ return err
+ }
+ }
+
+ if w.AuthConn != nil {
+ if err := w.AuthConn.Shutdown(); err != nil {
+ return err
+ }
+ }
+
+ // flush any subscriptions from last connection if needed
+ w.subscriptionMutex.Lock()
+ w.subscriptions = nil
+ w.subscriptionMutex.Unlock()
+
+ close(w.ShutdownC)
+ w.Wg.Wait()
+ w.ShutdownC = make(chan struct{})
+ w.setConnectedStatus(false)
+ w.setConnectingStatus(false)
+ if w.verbose {
+ log.Debugf(log.WebsocketMgr,
+ "%v websocket: completed websocket shutdown\n",
+ w.exchangeName)
+ }
+ return nil
+}
+
+// FlushChannels flushes channel subscriptions when there is a pair/asset change
+func (w *Websocket) FlushChannels() error {
+ if !w.IsEnabled() {
+ return fmt.Errorf("%s websocket: service not enabled", w.exchangeName)
+ }
+
+ if !w.IsConnected() {
+ return fmt.Errorf("%s websocket: service not connected", w.exchangeName)
+ }
+
+ if w.features.Subscribe {
+ newsubs, err := w.GenerateSubs()
+ if err != nil {
+ return err
+ }
+
+ subs, unsubs := w.GetChannelDifference(newsubs)
+ if w.features.Unsubscribe {
+ if len(unsubs) != 0 {
+ err := w.UnsubscribeChannels(unsubs)
+ if err != nil {
+ return err
+ }
+ }
+
+ if len(subs) != 0 {
+ return w.SubscribeToChannels(subs)
+ }
+
+ return nil
+ } else if len(unsubs) == 0 {
+ if len(subs) == 0 {
+ return nil
+ }
+ return w.SubscribeToChannels(subs)
+ }
+ // FullPayloadSubscribe means that the endpoint requires all
+ // subscriptions to be sent via the websocket connection e.g. if you are
+ // subscribed to ticker and orderbook but require trades as well, you
+ // would need to send ticker, orderbook and trades channel subscription
+ // messages.
+ } else if w.features.FullPayloadSubscribe {
+ newsubs, err := w.GenerateSubs()
+ if err != nil {
+ return err
+ }
+
+ if len(newsubs) != 0 {
+ return w.SubscribeToChannels(newsubs)
+ }
+ return nil
+ }
+
+ err := w.Shutdown()
+ if err != nil {
+ return err
+ }
+ return w.Connect()
+}
+
+// trafficMonitor uses a timer of WebsocketTrafficLimitTime and once it expires,
+// it will reconnect if the TrafficAlert channel has not received any data. The
+// trafficTimer will reset on each traffic alert
+func (w *Websocket) trafficMonitor() error {
+ if w.IsTrafficMonitorRunning() {
+ return errors.New("traffic monitor already running")
+ }
+ w.setTrafficMonitorRunning(true)
+ w.Wg.Add(1)
+
+ go func() {
+ var trafficTimer = time.NewTimer(w.trafficTimeout)
+ pause := make(chan struct{})
+ for {
+ select {
+ case <-w.ShutdownC:
+ if w.verbose {
+ log.Debugf(log.WebsocketMgr,
+ "%v websocket: trafficMonitor shutdown message received\n",
+ w.exchangeName)
+ }
+ trafficTimer.Stop()
+ w.setTrafficMonitorRunning(false)
+ w.Wg.Done()
+ return
+ case <-w.TrafficAlert:
+ if !trafficTimer.Stop() {
+ select {
+ case <-trafficTimer.C:
+ default:
+ }
+ }
+ w.setConnectedStatus(true)
+ trafficTimer.Reset(w.trafficTimeout)
+ case <-trafficTimer.C: // Falls through when timer runs out
+ if w.verbose {
+ log.Warnf(log.WebsocketMgr,
+ "%v websocket: has not received a traffic alert in %v. Reconnecting",
+ w.exchangeName,
+ w.trafficTimeout)
+ }
+ trafficTimer.Stop()
+ w.Wg.Done()
+ err := w.Shutdown()
+ if err != nil {
+ log.Errorf(log.WebsocketMgr,
+ "%v websocket: trafficMonitor shutdown err: %s",
+ w.exchangeName, err)
+ }
+ w.setTrafficMonitorRunning(false)
+ return
+ }
+
+ // Routine pausing mechanism
+ go func(p chan struct{}) {
+ time.Sleep(defaultTrafficPeriod)
+ p <- struct{}{}
+ }(pause)
+ select {
+ case <-w.ShutdownC:
+ trafficTimer.Stop()
+ w.setTrafficMonitorRunning(false)
+ w.Wg.Done()
+ return
+ case <-pause:
+ }
+ }
+ }()
+ return nil
+}
+
+func (w *Websocket) setConnectedStatus(b bool) {
+ w.connectionMutex.Lock()
+ w.connected = b
+ w.connectionMutex.Unlock()
+}
+
+// IsConnected returns status of connection
+func (w *Websocket) IsConnected() bool {
+ w.connectionMutex.RLock()
+ defer w.connectionMutex.RUnlock()
+ return w.connected
+}
+
+func (w *Websocket) setConnectingStatus(b bool) {
+ w.connectionMutex.Lock()
+ w.connecting = b
+ w.connectionMutex.Unlock()
+}
+
+// IsConnecting returns status of connecting
+func (w *Websocket) IsConnecting() bool {
+ w.connectionMutex.RLock()
+ defer w.connectionMutex.RUnlock()
+ return w.connecting
+}
+
+func (w *Websocket) setEnabled(b bool) {
+ w.connectionMutex.Lock()
+ w.enabled = b
+ w.connectionMutex.Unlock()
+}
+
+// IsEnabled returns status of enabled
+func (w *Websocket) IsEnabled() bool {
+ w.connectionMutex.RLock()
+ defer w.connectionMutex.RUnlock()
+ return w.enabled
+}
+
+func (w *Websocket) setInit(b bool) {
+ w.connectionMutex.Lock()
+ w.Init = b
+ w.connectionMutex.Unlock()
+}
+
+// IsInit returns status of init
+func (w *Websocket) IsInit() bool {
+ w.connectionMutex.RLock()
+ defer w.connectionMutex.RUnlock()
+ return w.Init
+}
+
+func (w *Websocket) setTrafficMonitorRunning(b bool) {
+ w.connectionMutex.Lock()
+ w.trafficMonitorRunning = b
+ w.connectionMutex.Unlock()
+}
+
+// IsTrafficMonitorRunning returns status of the traffic monitor
+func (w *Websocket) IsTrafficMonitorRunning() bool {
+ w.connectionMutex.RLock()
+ defer w.connectionMutex.RUnlock()
+ return w.trafficMonitorRunning
+}
+
+func (w *Websocket) setConnectionMonitorRunning(b bool) {
+ w.connectionMutex.Lock()
+ w.connectionMonitorRunning = b
+ w.connectionMutex.Unlock()
+}
+
+// IsConnectionMonitorRunning returns status of connection monitor
+func (w *Websocket) IsConnectionMonitorRunning() bool {
+ w.connectionMutex.RLock()
+ defer w.connectionMutex.RUnlock()
+ return w.connectionMonitorRunning
+}
+
+func (w *Websocket) setDataMonitorRunning(b bool) {
+ w.connectionMutex.Lock()
+ w.dataMonitorRunning = b
+ w.connectionMutex.Unlock()
+}
+
+// IsDataMonitorRunning returns status of data monitor
+func (w *Websocket) IsDataMonitorRunning() bool {
+ w.connectionMutex.RLock()
+ defer w.connectionMutex.RUnlock()
+ return w.dataMonitorRunning
+}
+
+// CanUseAuthenticatedWebsocketForWrapper Handles a common check to
+// verify whether a wrapper can use an authenticated websocket endpoint
+func (w *Websocket) CanUseAuthenticatedWebsocketForWrapper() bool {
+ if w.IsConnected() && w.CanUseAuthenticatedEndpoints() {
+ return true
+ } else if w.IsConnected() && !w.CanUseAuthenticatedEndpoints() {
+ log.Infof(log.WebsocketMgr,
+ WebsocketNotAuthenticatedUsingRest,
+ w.exchangeName)
+ }
+ return false
+}
+
+// SetWebsocketURL sets websocket URL and can refresh underlying connections
+func (w *Websocket) SetWebsocketURL(url string, auth, reconnect bool) error {
+ defaultVals := url == "" || url == config.WebsocketURLNonDefaultMessage
+ if auth {
+ if defaultVals {
+ url = w.defaultURLAuth
+ }
+
+ err := checkWebsocketURL(url)
+ if err != nil {
+ return err
+ }
+ w.runningURLAuth = url
+
+ if w.verbose {
+ log.Debugf(log.WebsocketMgr,
+ "%s websocket: setting authenticated websocket URL: %s\n",
+ w.exchangeName,
+ url)
+ }
+
+ if w.AuthConn != nil {
+ w.AuthConn.SetURL(url)
+ }
+ } else {
+ if defaultVals {
+ url = w.defaultURL
+ }
+ err := checkWebsocketURL(url)
+ if err != nil {
+ return err
+ }
+ w.runningURL = url
+
+ if w.verbose {
+ log.Debugf(log.WebsocketMgr,
+ "%s websocket: setting unauthenticated websocket URL: %s\n",
+ w.exchangeName,
+ url)
+ }
+
+ if w.Conn != nil {
+ w.Conn.SetURL(url)
+ }
+ }
+
+ if w.IsConnected() && reconnect {
+ log.Debugf(log.WebsocketMgr,
+ "%s websocket: flushing websocket connection to %s\n",
+ w.exchangeName,
+ url)
+ return w.Shutdown()
+ }
+ return nil
+}
+
+// GetWebsocketURL returns the running websocket URL
+func (w *Websocket) GetWebsocketURL() string {
+ return w.runningURL
+}
+
+// Initialise verifies status and connects
+func (w *Websocket) Initialise() error {
+ if w.IsEnabled() {
+ if w.IsInit() {
+ return nil
+ }
+ return fmt.Errorf("%v websocket: already initialised", w.exchangeName)
+ }
+ w.setEnabled(w.enabled)
+ return nil
+}
+
+// SetProxyAddress sets websocket proxy address
+func (w *Websocket) SetProxyAddress(proxyAddr string) error {
+ if proxyAddr != "" {
+ _, err := url.ParseRequestURI(proxyAddr)
+ if err != nil {
+ return fmt.Errorf("%v websocket: cannot set proxy address error '%v'",
+ w.exchangeName,
+ err)
+ }
+
+ if w.proxyAddr == proxyAddr {
+ return fmt.Errorf("%v websocket: cannot set proxy address to the same address '%v'",
+ w.exchangeName,
+ w.proxyAddr)
+ }
+
+ log.Debugf(log.ExchangeSys,
+ "%s websocket: setting websocket proxy: %s\n",
+ w.exchangeName,
+ proxyAddr)
+ } else {
+ log.Debugf(log.ExchangeSys,
+ "%s websocket: removing websocket proxy\n",
+ w.exchangeName)
+ }
+
+ if w.Conn != nil {
+ w.Conn.SetProxy(proxyAddr)
+ }
+ if w.AuthConn != nil {
+ w.AuthConn.SetProxy(proxyAddr)
+ }
+
+ w.proxyAddr = proxyAddr
+ if w.IsInit() && w.IsEnabled() {
+ if w.IsConnected() {
+ err := w.Shutdown()
+ if err != nil {
+ return err
+ }
+ }
+ return w.Connect()
+ }
+ return nil
+}
+
+// GetProxyAddress returns the current websocket proxy
+func (w *Websocket) GetProxyAddress() string {
+ return w.proxyAddr
+}
+
+// GetName returns exchange name
+func (w *Websocket) GetName() string {
+ return w.exchangeName
+}
+
+// GetChannelDifference finds the difference between the subscribed channels
+// and the new subscription list when pairs are disabled or enabled.
+func (w *Websocket) GetChannelDifference(genSubs []ChannelSubscription) (sub, unsub []ChannelSubscription) {
+ w.subscriptionMutex.Lock()
+ defer w.subscriptionMutex.Unlock()
+
+oldsubs:
+ for x := range w.subscriptions {
+ for y := range genSubs {
+ if w.subscriptions[x].Equal(&genSubs[y]) {
+ continue oldsubs
+ }
+ }
+ unsub = append(unsub, w.subscriptions[x])
+ }
+
+newsubs:
+ for x := range genSubs {
+ for y := range w.subscriptions {
+ if genSubs[x].Equal(&w.subscriptions[y]) {
+ continue newsubs
+ }
+ }
+ sub = append(sub, genSubs[x])
+ }
+ return
+}
+
+// UnsubscribeChannels unsubscribes from a websocket channel
+func (w *Websocket) UnsubscribeChannels(channels []ChannelSubscription) error {
+ if len(channels) == 0 {
+ return fmt.Errorf("%s websocket: channels not populated cannot remove",
+ w.exchangeName)
+ }
+ w.subscriptionMutex.Lock()
+ defer w.subscriptionMutex.Unlock()
+
+channels:
+ for x := range channels {
+ for y := range w.subscriptions {
+ if channels[x].Equal(&w.subscriptions[y]) {
+ continue channels
+ }
+ }
+ return fmt.Errorf("%s websocket: subscription not found in list: %+v",
+ w.exchangeName,
+ channels[x])
+ }
+ return w.Unsubscriber(channels)
+}
+
+// ResubscribeToChannel resubscribes to channel
+func (w *Websocket) ResubscribeToChannel(subscribedChannel *ChannelSubscription) error {
+ err := w.UnsubscribeChannels([]ChannelSubscription{*subscribedChannel})
+ if err != nil {
+ return err
+ }
+ return w.SubscribeToChannels([]ChannelSubscription{*subscribedChannel})
+}
+
+// SubscribeToChannels appends supplied channels to channelsToSubscribe
+func (w *Websocket) SubscribeToChannels(channels []ChannelSubscription) error {
+ if len(channels) == 0 {
+ return fmt.Errorf("%s websocket: cannot subscribe no channels supplied",
+ w.exchangeName)
+ }
+ w.subscriptionMutex.Lock()
+ defer w.subscriptionMutex.Unlock()
+ for x := range channels {
+ for y := range w.subscriptions {
+ if channels[x].Equal(&w.subscriptions[y]) {
+ return fmt.Errorf("%s websocket: %v already subscribed",
+ w.exchangeName,
+ channels[x])
+ }
+ }
+ }
+ return w.Subscriber(channels)
+}
+
+// AddSuccessfulSubscriptions adds subscriptions to the subscription lists that
+// has been successfully subscribed
+func (w *Websocket) AddSuccessfulSubscriptions(channels ...ChannelSubscription) {
+ w.subscriptions = append(w.subscriptions, channels...)
+}
+
+// RemoveSuccessfulUnsubscriptions removes subscriptions from the subscription
+// list that has been successfulling unsubscribed
+func (w *Websocket) RemoveSuccessfulUnsubscriptions(channels ...ChannelSubscription) {
+ for x := range channels {
+ for y := range w.subscriptions {
+ if channels[x].Equal(&w.subscriptions[y]) {
+ w.subscriptions[y] = w.subscriptions[len(w.subscriptions)-1]
+ w.subscriptions[len(w.subscriptions)-1] = ChannelSubscription{}
+ w.subscriptions = w.subscriptions[:len(w.subscriptions)-1]
+ break
+ }
+ }
+ }
+}
+
+// Equal two WebsocketChannelSubscription to determine equality
+func (w *ChannelSubscription) Equal(s *ChannelSubscription) bool {
+ return strings.EqualFold(w.Channel, s.Channel) &&
+ w.Currency.Equal(s.Currency)
+}
+
+// GetSubscriptions returns a copied list of subscriptions
+// subscriptions is a private member and cannot be manipulated
+func (w *Websocket) GetSubscriptions() []ChannelSubscription {
+ w.subscriptionMutex.Lock()
+ defer w.subscriptionMutex.Unlock()
+ return append(w.subscriptions[:0:0], w.subscriptions...)
+}
+
+// SetCanUseAuthenticatedEndpoints sets canUseAuthenticatedEndpoints val in
+// a thread safe manner
+func (w *Websocket) SetCanUseAuthenticatedEndpoints(val bool) {
+ w.subscriptionMutex.Lock()
+ defer w.subscriptionMutex.Unlock()
+ w.canUseAuthenticatedEndpoints = val
+}
+
+// CanUseAuthenticatedEndpoints gets canUseAuthenticatedEndpoints val in
+// a thread safe manner
+func (w *Websocket) CanUseAuthenticatedEndpoints() bool {
+ w.subscriptionMutex.Lock()
+ defer w.subscriptionMutex.Unlock()
+ return w.canUseAuthenticatedEndpoints
+}
+
+// isDisconnectionError Determines if the error sent over chan ReadMessageErrors is a disconnection error
+func isDisconnectionError(err error) bool {
+ if websocket.IsUnexpectedCloseError(err) {
+ return true
+ }
+ switch e := err.(type) {
+ case *websocket.CloseError:
+ return true
+ case *net.OpError:
+ if e.Err.Error() == "use of closed network connection" {
+ return false
+ }
+ return true
+ }
+ return false
+}
+
+// checkWebsocketURL checks for a valid websocket url
+func checkWebsocketURL(s string) error {
+ u, err := url.Parse(s)
+ if err != nil {
+ return err
+ }
+ if u.Scheme != "ws" && u.Scheme != "wss" {
+ return fmt.Errorf("cannot set invalid websocket URL %s", s)
+ }
+ return nil
+}
diff --git a/exchanges/stream/websocket_connection.go b/exchanges/stream/websocket_connection.go
new file mode 100644
index 00000000..8e1179ee
--- /dev/null
+++ b/exchanges/stream/websocket_connection.go
@@ -0,0 +1,314 @@
+package stream
+
+import (
+ "bytes"
+ "compress/flate"
+ "compress/gzip"
+ "crypto/rand"
+ "fmt"
+ "io/ioutil"
+ "math/big"
+ "net"
+ "net/http"
+ "net/url"
+ "sync/atomic"
+ "time"
+
+ "github.com/gorilla/websocket"
+ "github.com/thrasher-corp/gocryptotrader/log"
+)
+
+// SendMessageReturnResponse will send a WS message to the connection and wait
+// for response
+func (w *WebsocketConnection) SendMessageReturnResponse(signature, request interface{}) ([]byte, error) {
+ m, err := w.Match.set(signature)
+ if err != nil {
+ return nil, err
+ }
+ defer m.Cleanup()
+
+ err = w.SendJSONMessage(request)
+ if err != nil {
+ return nil, err
+ }
+
+ timer := time.NewTimer(w.ResponseMaxLimit)
+
+ select {
+ case payload := <-m.C:
+ return payload, nil
+ case <-timer.C:
+ timer.Stop()
+ return nil, fmt.Errorf("%s websocket connection: timeout waiting for response with signature: %v",
+ w.ExchangeName,
+ signature)
+ }
+}
+
+// Dial sets proxy urls and then connects to the websocket
+func (w *WebsocketConnection) Dial(dialer *websocket.Dialer, headers http.Header) error {
+ if w.ProxyURL != "" {
+ proxy, err := url.Parse(w.ProxyURL)
+ if err != nil {
+ return err
+ }
+ dialer.Proxy = http.ProxyURL(proxy)
+ }
+
+ var err error
+ var conStatus *http.Response
+
+ w.Connection, conStatus, err = dialer.Dial(w.URL, headers)
+ if err != nil {
+ if conStatus != nil {
+ return fmt.Errorf("%s websocket connection: %v %v %v Error: %v",
+ w.ExchangeName,
+ w.URL,
+ conStatus,
+ conStatus.StatusCode,
+ err)
+ }
+ return fmt.Errorf("%s websocket connection: %v Error: %v",
+ w.ExchangeName,
+ w.URL,
+ err)
+ }
+ defer conStatus.Body.Close()
+
+ if w.Verbose {
+ log.Infof(log.WebsocketMgr,
+ "%v Websocket connected to %s\n",
+ w.ExchangeName,
+ w.URL)
+ }
+ select {
+ case w.Traffic <- struct{}{}:
+ default:
+ }
+ w.setConnectedStatus(true)
+ return nil
+}
+
+// SendJSONMessage sends a JSON encoded message over the connection
+func (w *WebsocketConnection) SendJSONMessage(data interface{}) error {
+ if !w.IsConnected() {
+ return fmt.Errorf("%s websocket connection: cannot send message to a disconnected websocket",
+ w.ExchangeName)
+ }
+
+ w.writeControl.Lock()
+ defer w.writeControl.Unlock()
+
+ if w.Verbose {
+ log.Debugf(log.WebsocketMgr,
+ "%s websocket connection: sending message to websocket %+v\n",
+ w.ExchangeName,
+ data)
+ }
+
+ if w.RateLimit > 0 {
+ time.Sleep(time.Duration(w.RateLimit) * time.Millisecond)
+ if !w.IsConnected() {
+ return fmt.Errorf("%v websocket connection: cannot send message to a disconnected websocket",
+ w.ExchangeName)
+ }
+ }
+ return w.Connection.WriteJSON(data)
+}
+
+// SendRawMessage sends a message over the connection without JSON encoding it
+func (w *WebsocketConnection) SendRawMessage(messageType int, message []byte) error {
+ if !w.IsConnected() {
+ return fmt.Errorf("%v websocket connection: cannot send message to a disconnected websocket",
+ w.ExchangeName)
+ }
+
+ w.writeControl.Lock()
+ defer w.writeControl.Unlock()
+
+ if w.Verbose {
+ log.Debugf(log.WebsocketMgr,
+ "%v websocket connection: sending message [%s]\n",
+ w.ExchangeName,
+ message)
+ }
+ if w.RateLimit > 0 {
+ time.Sleep(time.Duration(w.RateLimit) * time.Millisecond)
+ if !w.IsConnected() {
+ return fmt.Errorf("%v websocket connection: cannot send message to a disconnected websocket",
+ w.ExchangeName)
+ }
+ }
+ if !w.IsConnected() {
+ return fmt.Errorf("%v websocket connection: cannot send message to a disconnected websocket",
+ w.ExchangeName)
+ }
+ return w.Connection.WriteMessage(messageType, message)
+}
+
+// SetupPingHandler will automatically send ping or pong messages based on
+// WebsocketPingHandler configuration
+func (w *WebsocketConnection) SetupPingHandler(handler PingHandler) {
+ if handler.UseGorillaHandler {
+ h := func(msg string) error {
+ err := w.Connection.WriteControl(handler.MessageType,
+ []byte(msg),
+ time.Now().Add(handler.Delay))
+ if err == websocket.ErrCloseSent {
+ return nil
+ } else if e, ok := err.(net.Error); ok && e.Temporary() {
+ return nil
+ }
+ return err
+ }
+ w.Connection.SetPingHandler(h)
+ return
+ }
+ w.Wg.Add(1)
+ defer w.Wg.Done()
+ go func() {
+ ticker := time.NewTicker(handler.Delay)
+ for {
+ select {
+ case <-w.ShutdownC:
+ ticker.Stop()
+ return
+ case <-ticker.C:
+ err := w.SendRawMessage(handler.MessageType, handler.Message)
+ if err != nil {
+ log.Errorf(log.WebsocketMgr,
+ "%v websocket connection: ping handler failed to send message [%s]",
+ w.ExchangeName,
+ handler.Message)
+ return
+ }
+ }
+ }
+ }()
+}
+
+func (w *WebsocketConnection) setConnectedStatus(b bool) {
+ if b {
+ atomic.StoreInt32(&w.connected, 1)
+ return
+ }
+ atomic.StoreInt32(&w.connected, 0)
+}
+
+// IsConnected exposes websocket connection status
+func (w *WebsocketConnection) IsConnected() bool {
+ return atomic.LoadInt32(&w.connected) == 1
+}
+
+// ReadMessage reads messages, can handle text, gzip and binary
+func (w *WebsocketConnection) ReadMessage() Response {
+ mType, resp, err := w.Connection.ReadMessage()
+ if err != nil {
+ if isDisconnectionError(err) {
+ w.setConnectedStatus(false)
+ w.readMessageErrors <- err
+ }
+ return Response{}
+ }
+
+ select {
+ case w.Traffic <- struct{}{}:
+ default: // causes contention, just bypass if there is no receiver.
+ }
+
+ var standardMessage []byte
+ switch mType {
+ case websocket.TextMessage:
+ standardMessage = resp
+ case websocket.BinaryMessage:
+ standardMessage, err = w.parseBinaryResponse(resp)
+ if err != nil {
+ log.Errorf(log.WebsocketMgr,
+ "%v websocket connection: parseBinaryResponse error: %v",
+ w.ExchangeName,
+ err)
+ return Response{}
+ }
+ }
+ if w.Verbose {
+ log.Debugf(log.WebsocketMgr,
+ "%v websocket connection: message received: %v",
+ w.ExchangeName,
+ string(standardMessage))
+ }
+ return Response{Raw: standardMessage, Type: mType}
+}
+
+// parseBinaryResponse parses a websocket binary response into a usable byte array
+func (w *WebsocketConnection) parseBinaryResponse(resp []byte) ([]byte, error) {
+ var standardMessage []byte
+ var err error
+ // Detect GZIP
+ if resp[0] == 31 && resp[1] == 139 {
+ b := bytes.NewReader(resp)
+ var gReader *gzip.Reader
+ gReader, err = gzip.NewReader(b)
+ if err != nil {
+ return standardMessage, err
+ }
+ standardMessage, err = ioutil.ReadAll(gReader)
+ if err != nil {
+ return standardMessage, err
+ }
+ err = gReader.Close()
+ if err != nil {
+ return standardMessage, err
+ }
+ } else {
+ reader := flate.NewReader(bytes.NewReader(resp))
+ standardMessage, err = ioutil.ReadAll(reader)
+ if err != nil {
+ return standardMessage, err
+ }
+ err = reader.Close()
+ if err != nil {
+ return standardMessage, err
+ }
+ }
+ return standardMessage, nil
+}
+
+// GenerateMessageID Creates a messageID to checkout
+func (w *WebsocketConnection) GenerateMessageID(highPrec bool) int64 {
+ var min int64 = 1e8
+ var max int64 = 2e8
+ if highPrec {
+ max = 2e12
+ min = 1e12
+ }
+ // utlization of hard coded positive numbers and default crypto/rand
+ // io.reader will panic on error instead of returning
+ randomNumber, err := rand.Int(rand.Reader, big.NewInt(max-min+1))
+ if err != nil {
+ panic(err)
+ }
+ return randomNumber.Int64() + min
+}
+
+// Shutdown shuts down and closes specific connection
+func (w *WebsocketConnection) Shutdown() error {
+ if w == nil || w.Connection == nil {
+ return nil
+ }
+ return w.Connection.UnderlyingConn().Close()
+}
+
+// SetURL sets connection URL
+func (w *WebsocketConnection) SetURL(url string) {
+ w.URL = url
+}
+
+// SetProxy sets connection proxy
+func (w *WebsocketConnection) SetProxy(proxy string) {
+ w.ProxyURL = proxy
+}
+
+// GetURL returns the connection URL
+func (w *WebsocketConnection) GetURL() string {
+ return w.URL
+}
diff --git a/exchanges/stream/websocket_test.go b/exchanges/stream/websocket_test.go
new file mode 100644
index 00000000..995115e7
--- /dev/null
+++ b/exchanges/stream/websocket_test.go
@@ -0,0 +1,957 @@
+package stream
+
+import (
+ "bytes"
+ "compress/flate"
+ "compress/gzip"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "net"
+ "net/http"
+ "strconv"
+ "strings"
+ "sync"
+ "testing"
+ "time"
+
+ "github.com/gorilla/websocket"
+ "github.com/thrasher-corp/gocryptotrader/currency"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
+)
+
+const (
+ websocketTestURL = "wss://www.bitmex.com/realtime"
+ useProxyTests = false // Disabled by default. Freely available proxy servers that work all the time are difficult to find
+ proxyURL = "http://212.186.171.4:80" // Replace with a usable proxy server
+)
+
+var dialer websocket.Dialer
+
+type testStruct struct {
+ Error error
+ WC WebsocketConnection
+}
+
+type testRequest struct {
+ Event string `json:"event"`
+ RequestID int64 `json:"reqid,omitempty"`
+ Pairs []string `json:"pair"`
+ Subscription testRequestData `json:"subscription,omitempty"`
+}
+
+// testRequestData contains details on WS channel
+type testRequestData struct {
+ Name string `json:"name,omitempty"`
+ Interval int64 `json:"interval,omitempty"`
+ Depth int64 `json:"depth,omitempty"`
+}
+
+type testResponse struct {
+ RequestID int64 `json:"reqid,omitempty"`
+}
+
+var defaultSetup = &WebsocketSetup{
+ Enabled: true,
+ AuthenticatedWebsocketAPISupport: true,
+ WebsocketTimeout: time.Second * 5,
+ DefaultURL: "testDefaultURL",
+ ExchangeName: "exchangeName",
+ RunningURL: "wss://testRunningURL",
+ Connector: func() error { return nil },
+ Subscriber: func(_ []ChannelSubscription) error { return nil },
+ UnSubscriber: func(_ []ChannelSubscription) error { return nil },
+ GenerateSubscriptions: func() ([]ChannelSubscription, error) {
+ return []ChannelSubscription{
+ {Channel: "TestSub"},
+ {Channel: "TestSub2"},
+ {Channel: "TestSub3"},
+ {Channel: "TestSub4"},
+ }, nil
+ },
+ Features: &protocol.Features{Subscribe: true, Unsubscribe: true},
+}
+
+func TestTrafficMonitorTimeout(t *testing.T) {
+ ws := *New()
+ err := ws.Setup(defaultSetup)
+ if err != nil {
+ t.Fatal(err)
+ }
+ ws.trafficTimeout = time.Second
+ ws.ShutdownC = make(chan struct{})
+ err = ws.trafficMonitor()
+ if err != nil {
+ t.Fatal(err)
+ }
+ // try to add another traffic monitor
+ err = ws.trafficMonitor()
+ if err == nil {
+ t.Fatal("expected not allowed")
+ }
+ // Deploy traffic alert
+ ws.TrafficAlert <- struct{}{}
+ time.Sleep(time.Second * 2)
+ ws.Wg.Wait()
+ if ws.IsTrafficMonitorRunning() {
+ t.Error("should be ded")
+ }
+}
+
+func TestIsDisconnectionError(t *testing.T) {
+ isADisconnectionError := isDisconnectionError(errors.New("errorText"))
+ if isADisconnectionError {
+ t.Error("Its not")
+ }
+ isADisconnectionError = isDisconnectionError(&websocket.CloseError{
+ Code: 1006,
+ Text: "errorText",
+ })
+ if !isADisconnectionError {
+ t.Error("It is")
+ }
+
+ isADisconnectionError = isDisconnectionError(&net.OpError{
+ Op: "",
+ Net: "",
+ Source: nil,
+ Addr: nil,
+ Err: errors.New("errorText"),
+ })
+ if !isADisconnectionError {
+ t.Error("It is")
+ }
+}
+
+func TestConnectionMessageErrors(t *testing.T) {
+ ws := *New()
+ err := ws.Setup(defaultSetup)
+ if err != nil {
+ t.Fatal(err)
+ }
+ ws.trafficTimeout = time.Minute
+ ws.connector = func() error { return nil }
+
+ err = ws.Connect()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ ws.TrafficAlert <- struct{}{}
+
+ timer := time.NewTimer(900 * time.Millisecond)
+ ws.ReadMessageErrors <- errors.New("errorText")
+ select {
+ case err := <-ws.ToRoutine:
+ if err.(error).Error() != "errorText" {
+ t.Errorf("Expected 'errorText', received %v", err)
+ }
+ case <-timer.C:
+ t.Error("Timeout waiting for datahandler to receive error")
+ }
+ ws.ReadMessageErrors <- &websocket.CloseError{
+ Code: 1006,
+ Text: "errorText",
+ }
+outer:
+ for {
+ select {
+ case <-ws.ToRoutine:
+ t.Fatal("Error is a disconnection error")
+ case <-timer.C:
+ break outer
+ }
+ }
+}
+
+func TestWebsocket(t *testing.T) {
+ ws := Websocket{}
+ err := ws.Setup(&WebsocketSetup{
+ ExchangeName: "test",
+ Enabled: true,
+ })
+ if err != nil && err.Error() != "test Websocket already initialised" {
+ t.Errorf("Expected 'test Websocket already initialised', received %v", err)
+ }
+
+ ws = *New()
+ err = ws.SetProxyAddress("garbagio")
+ if err == nil {
+ t.Error("error cannot be nil")
+ }
+ err = ws.SetProxyAddress("https://192.168.0.1:1337")
+ if err != nil {
+ t.Error("SetProxyAddress", err)
+ }
+ // removing proxy
+ err = ws.SetProxyAddress("")
+ if err != nil {
+ t.Error(err)
+ }
+ // reinstate proxy
+ err = ws.SetProxyAddress("http://localhost:1337")
+ if err != nil {
+ t.Error(err)
+ }
+ // conflict proxy
+ err = ws.SetProxyAddress("http://localhost:1337")
+ if err == nil {
+ t.Error("error cannot be nil")
+ }
+ err = ws.Setup(defaultSetup)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if ws.GetName() != "exchangeName" {
+ t.Error("WebsocketSetup")
+ }
+
+ if !ws.IsEnabled() {
+ t.Error("WebsocketSetup")
+ }
+
+ ws.setEnabled(false)
+ if ws.IsEnabled() {
+ t.Error("WebsocketSetup")
+ }
+ ws.setEnabled(true)
+ if !ws.IsEnabled() {
+ t.Error("WebsocketSetup")
+ }
+
+ if ws.GetProxyAddress() != "http://localhost:1337" {
+ t.Error("WebsocketSetup")
+ }
+
+ if ws.GetWebsocketURL() != "wss://testRunningURL" {
+ t.Error("WebsocketSetup")
+ }
+ if ws.trafficTimeout != time.Second*5 {
+ t.Error("WebsocketSetup")
+ }
+ // -- Not connected shutdown
+ err = ws.Shutdown()
+ if err == nil {
+ t.Fatal("should not be connected to able to shut down")
+ }
+ // -- Normal connect
+ err = ws.Connect()
+ if err != nil {
+ t.Fatal("WebsocketSetup", err)
+ }
+ err = ws.SetWebsocketURL("ws://demos.kaazing.com/echo", false, false)
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = ws.SetWebsocketURL("ws://demos.kaazing.com/echo", true, false)
+ if err != nil {
+ t.Fatal(err)
+ }
+ // -- Already connected connect
+ err = ws.Connect()
+ if err == nil {
+ t.Fatal("should not connect, already connected")
+ }
+ // -- Normal shutdown
+ err = ws.Shutdown()
+ if err != nil {
+ t.Fatal("WebsocketSetup", err)
+ }
+ ws.Wg.Wait()
+}
+
+// TestSubscribe logic test
+func TestSubscribeUnsubscribe(t *testing.T) {
+ ws := *New()
+ err := ws.Setup(defaultSetup)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ fnSub := func(subs []ChannelSubscription) error {
+ ws.AddSuccessfulSubscriptions(subs...)
+ return nil
+ }
+ fnUnsub := func(unsubs []ChannelSubscription) error {
+ ws.RemoveSuccessfulUnsubscriptions(unsubs...)
+ return nil
+ }
+ ws.Subscriber = fnSub
+ ws.Unsubscriber = fnUnsub
+
+ err = ws.UnsubscribeChannels(nil)
+ if err == nil {
+ t.Fatal("error cannot be nil")
+ }
+
+ // Generate test sub
+ subs, err := ws.GenerateSubs()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // unsub when no subscribed channel
+ err = ws.UnsubscribeChannels(subs)
+ if err == nil {
+ t.Fatal("error cannot be nil")
+ }
+
+ err = ws.SubscribeToChannels(subs)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ // subscribe when already subscribed
+ err = ws.SubscribeToChannels(subs)
+ if err == nil {
+ t.Fatal("error cannot be nil")
+ }
+
+ err = ws.UnsubscribeChannels(subs)
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestResubscribe(t *testing.T) {
+ ws := *New()
+ err := ws.Setup(defaultSetup)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ fnSub := func(subs []ChannelSubscription) error {
+ ws.AddSuccessfulSubscriptions(subs...)
+ return nil
+ }
+ fnUnsub := func(unsubs []ChannelSubscription) error {
+ ws.RemoveSuccessfulUnsubscriptions(unsubs...)
+ return nil
+ }
+ ws.Subscriber = fnSub
+ ws.Unsubscriber = fnUnsub
+
+ channel := []ChannelSubscription{{Channel: "resubTest"}}
+ err = ws.ResubscribeToChannel(&channel[0])
+ if err == nil {
+ t.Fatal("error cannot be nil")
+ }
+
+ err = ws.SubscribeToChannels(channel)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ err = ws.ResubscribeToChannel(&channel[0])
+ if err != nil {
+ t.Fatal("error cannot be nil")
+ }
+}
+
+// TestConnectionMonitorNoConnection logic test
+func TestConnectionMonitorNoConnection(t *testing.T) {
+ ws := *New()
+ ws.DataHandler = make(chan interface{}, 1)
+ ws.ShutdownC = make(chan struct{}, 1)
+ ws.exchangeName = "hello"
+ ws.trafficTimeout = 1
+ go ws.connectionMonitor()
+ time.Sleep(time.Second)
+ if ws.IsConnectionMonitorRunning() {
+ t.Fatal("Should have exited")
+ }
+}
+
+// TestSliceCopyDoesntImpactBoth logic test
+func TestGetSubscriptions(t *testing.T) {
+ w := Websocket{
+ subscriptions: []ChannelSubscription{
+ {
+ Channel: "hello3",
+ },
+ },
+ }
+ if !strings.EqualFold("hello3", w.GetSubscriptions()[0].Channel) {
+ t.Error("Subscriptions was not copied properly")
+ }
+}
+
+// TestSetCanUseAuthenticatedEndpoints logic test
+func TestSetCanUseAuthenticatedEndpoints(t *testing.T) {
+ ws := *New()
+ result := ws.CanUseAuthenticatedEndpoints()
+ if result {
+ t.Error("expected `canUseAuthenticatedEndpoints` to be false")
+ }
+ ws.SetCanUseAuthenticatedEndpoints(true)
+ result = ws.CanUseAuthenticatedEndpoints()
+ if !result {
+ t.Error("expected `canUseAuthenticatedEndpoints` to be true")
+ }
+}
+
+// TestDial logic test
+func TestDial(t *testing.T) {
+ var testCases = []testStruct{
+ {Error: nil,
+ WC: WebsocketConnection{
+ ExchangeName: "test1",
+ Verbose: true,
+ URL: websocketTestURL,
+ RateLimit: 10,
+ ResponseMaxLimit: 7000000000,
+ },
+ },
+ {Error: errors.New(" Error: malformed ws or wss URL"),
+ WC: WebsocketConnection{
+ ExchangeName: "test2",
+ Verbose: true,
+ URL: "",
+ ResponseMaxLimit: 7000000000,
+ },
+ },
+ {Error: nil,
+ WC: WebsocketConnection{
+ ExchangeName: "test3",
+ Verbose: true,
+ URL: websocketTestURL,
+ ProxyURL: proxyURL,
+ ResponseMaxLimit: 7000000000,
+ },
+ },
+ }
+ for i := range testCases {
+ testData := &testCases[i]
+ t.Run(testData.WC.ExchangeName, func(t *testing.T) {
+ if testData.WC.ProxyURL != "" && !useProxyTests {
+ t.Skip("Proxy testing not enabled, skipping")
+ }
+ err := testData.WC.Dial(&dialer, http.Header{})
+ if err != nil {
+ if testData.Error != nil && strings.Contains(err.Error(), testData.Error.Error()) {
+ return
+ }
+ t.Fatal(err)
+ }
+ })
+ }
+}
+
+// TestSendMessage logic test
+func TestSendMessage(t *testing.T) {
+ var testCases = []testStruct{
+ {Error: nil, WC: WebsocketConnection{
+ ExchangeName: "test1",
+ Verbose: true,
+ URL: websocketTestURL,
+ RateLimit: 10,
+ ResponseMaxLimit: 7000000000,
+ },
+ },
+ {Error: errors.New(" Error: malformed ws or wss URL"),
+ WC: WebsocketConnection{
+ ExchangeName: "test2",
+ Verbose: true,
+ URL: "",
+ ResponseMaxLimit: 7000000000,
+ },
+ },
+ {Error: nil,
+ WC: WebsocketConnection{
+ ExchangeName: "test3",
+ Verbose: true,
+ URL: websocketTestURL,
+ ProxyURL: proxyURL,
+ ResponseMaxLimit: 7000000000,
+ },
+ },
+ }
+ for i := range testCases {
+ testData := &testCases[i]
+ t.Run(testData.WC.ExchangeName, func(t *testing.T) {
+ if testData.WC.ProxyURL != "" && !useProxyTests {
+ t.Skip("Proxy testing not enabled, skipping")
+ }
+ err := testData.WC.Dial(&dialer, http.Header{})
+ if err != nil {
+ if testData.Error != nil && strings.Contains(err.Error(), testData.Error.Error()) {
+ return
+ }
+ t.Fatal(err)
+ }
+ err = testData.WC.SendJSONMessage(Ping)
+ if err != nil {
+ t.Error(err)
+ }
+ err = testData.WC.SendRawMessage(websocket.TextMessage, []byte(Ping))
+ if err != nil {
+ t.Error(err)
+ }
+ })
+ }
+}
+
+// TestSendMessageWithResponse logic test
+func TestSendMessageWithResponse(t *testing.T) {
+ wc := &WebsocketConnection{
+ Verbose: true,
+ URL: "wss://echo.websocket.org",
+ ResponseMaxLimit: time.Second * 5,
+ Match: NewMatch(),
+ }
+ if wc.ProxyURL != "" && !useProxyTests {
+ t.Skip("Proxy testing not enabled, skipping")
+ }
+
+ err := wc.Dial(&dialer, http.Header{})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ go readMessages(wc, t)
+
+ request := testRequest{
+ Event: "subscribe",
+ Pairs: []string{currency.NewPairWithDelimiter("XBT", "USD", "/").String()},
+ Subscription: testRequestData{
+ Name: "ticker",
+ },
+ RequestID: wc.GenerateMessageID(false),
+ }
+
+ _, err = wc.SendMessageReturnResponse(request.RequestID, request)
+ if err != nil {
+ t.Error(err)
+ }
+}
+
+// readMessages helper func
+func readMessages(wc *WebsocketConnection, t *testing.T) {
+ timer := time.NewTimer(20 * time.Second)
+ for {
+ select {
+ case <-timer.C:
+ return
+ default:
+ resp := wc.ReadMessage()
+ if resp.Raw == nil {
+ t.Error("connection has closed")
+ return
+ }
+ var incoming testResponse
+ err := json.Unmarshal(resp.Raw, &incoming)
+ if err != nil {
+ t.Error(err)
+ return
+ }
+ if incoming.RequestID > 0 {
+ wc.Match.IncomingWithData(incoming.RequestID, resp.Raw)
+ return
+ }
+ }
+ }
+}
+
+// TestSetupPingHandler logic test
+func TestSetupPingHandler(t *testing.T) {
+ wc := &WebsocketConnection{
+ URL: "wss://echo.websocket.org",
+ ResponseMaxLimit: time.Second * 5,
+ Match: NewMatch(),
+ Wg: &sync.WaitGroup{},
+ }
+
+ if wc.ProxyURL != "" && !useProxyTests {
+ t.Skip("Proxy testing not enabled, skipping")
+ }
+ wc.ShutdownC = make(chan struct{})
+ err := wc.Dial(&dialer, http.Header{})
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ wc.SetupPingHandler(PingHandler{
+ UseGorillaHandler: true,
+ MessageType: websocket.PingMessage,
+ Delay: 1000,
+ })
+
+ err = wc.Connection.Close()
+ if err != nil {
+ t.Error(err)
+ }
+
+ err = wc.Dial(&dialer, http.Header{})
+ if err != nil {
+ t.Fatal(err)
+ }
+ wc.SetupPingHandler(PingHandler{
+ MessageType: websocket.TextMessage,
+ Message: []byte(Ping),
+ Delay: 200,
+ })
+ time.Sleep(time.Millisecond * 500)
+ close(wc.ShutdownC)
+ wc.Wg.Wait()
+}
+
+// TestParseBinaryResponse logic test
+func TestParseBinaryResponse(t *testing.T) {
+ wc := &WebsocketConnection{
+ URL: "wss://echo.websocket.org",
+ ResponseMaxLimit: time.Second * 5,
+ Match: NewMatch(),
+ }
+
+ var b bytes.Buffer
+ w := gzip.NewWriter(&b)
+ _, err := w.Write([]byte("hello"))
+ if err != nil {
+ t.Error(err)
+ }
+ err = w.Close()
+ if err != nil {
+ t.Error(err)
+ }
+ var resp []byte
+ resp, err = wc.parseBinaryResponse(b.Bytes())
+ if err != nil {
+ t.Error(err)
+ }
+ if !strings.EqualFold(string(resp), "hello") {
+ t.Errorf("GZip conversion failed. Received: '%v', Expected: 'hello'", string(resp))
+ }
+
+ var b2 bytes.Buffer
+ w2, err2 := flate.NewWriter(&b2, 1)
+ if err2 != nil {
+ t.Error(err2)
+ }
+ _, err2 = w2.Write([]byte("hello"))
+ if err2 != nil {
+ t.Error(err)
+ }
+ err2 = w2.Close()
+ if err2 != nil {
+ t.Error(err)
+ }
+ resp2, err3 := wc.parseBinaryResponse(b2.Bytes())
+ if err3 != nil {
+ t.Error(err3)
+ }
+ if !strings.EqualFold(string(resp2), "hello") {
+ t.Errorf("GZip conversion failed. Received: '%v', Expected: 'hello'", string(resp2))
+ }
+}
+
+// TestCanUseAuthenticatedWebsocketForWrapper logic test
+func TestCanUseAuthenticatedWebsocketForWrapper(t *testing.T) {
+ ws := &Websocket{}
+ resp := ws.CanUseAuthenticatedWebsocketForWrapper()
+ if resp {
+ t.Error("Expected false, `connected` is false")
+ }
+ ws.setConnectedStatus(true)
+ resp = ws.CanUseAuthenticatedWebsocketForWrapper()
+ if resp {
+ t.Error("Expected false, `connected` is true and `CanUseAuthenticatedEndpoints` is false")
+ }
+ ws.canUseAuthenticatedEndpoints = true
+ resp = ws.CanUseAuthenticatedWebsocketForWrapper()
+ if !resp {
+ t.Error("Expected true, `connected` and `CanUseAuthenticatedEndpoints` is true")
+ }
+}
+
+func TestGenerateMessageID(t *testing.T) {
+ wc := WebsocketConnection{}
+ var id int64
+ for i := 0; i < 10; i++ {
+ newID := wc.GenerateMessageID(true)
+ if id == newID {
+ t.Fatal("ID generation is not unique")
+ }
+ id = newID
+ }
+}
+
+// BenchmarkGenerateMessageID-8 2850018 408 ns/op 56 B/op 4 allocs/op
+func BenchmarkGenerateMessageID_High(b *testing.B) {
+ wc := WebsocketConnection{}
+ for i := 0; i < b.N; i++ {
+ _ = wc.GenerateMessageID(true)
+ }
+}
+
+// BenchmarkGenerateMessageID_Low-8 2591596 447 ns/op 56 B/op 4 allocs/op
+func BenchmarkGenerateMessageID_Low(b *testing.B) {
+ wc := WebsocketConnection{}
+ for i := 0; i < b.N; i++ {
+ _ = wc.GenerateMessageID(false)
+ }
+}
+
+func TestCheckWebsocketURL(t *testing.T) {
+ err := checkWebsocketURL("")
+ if err == nil {
+ t.Fatal("error cannot be nil")
+ }
+
+ err = checkWebsocketURL("wowowow:wowowowo")
+ if err == nil {
+ t.Fatal("error cannot be nil")
+ }
+
+ err = checkWebsocketURL("://")
+ if err == nil {
+ t.Fatal("error cannot be nil")
+ }
+
+ err = checkWebsocketURL("http://www.google.com")
+ if err == nil {
+ t.Fatal("error cannot be nil")
+ }
+
+ err = checkWebsocketURL("wss://websocketconnection.place")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ err = checkWebsocketURL("ws://websocketconnection.place")
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestGetChannelDifference(t *testing.T) {
+ web := Websocket{}
+
+ newChans := []ChannelSubscription{
+ {
+ Channel: "Test1",
+ },
+ {
+ Channel: "Test2",
+ },
+ {
+ Channel: "Test3",
+ },
+ }
+ subs, unsubs := web.GetChannelDifference(newChans)
+ if len(subs) != 3 {
+ t.Fatal("error mismatch")
+ }
+
+ if len(unsubs) != 0 {
+ t.Fatal("error mismatch")
+ }
+
+ web.subscriptions = subs
+
+ flushedSubs := []ChannelSubscription{
+ {
+ Channel: "Test2",
+ },
+ }
+
+ subs, unsubs = web.GetChannelDifference(flushedSubs)
+ if len(subs) != 0 {
+ t.Fatal("error mismatch")
+ }
+ if len(unsubs) != 2 {
+ t.Fatal("error mismatch")
+ }
+
+ flushedSubs = []ChannelSubscription{
+ {
+ Channel: "Test2",
+ },
+ {
+ Channel: "Test4",
+ },
+ }
+
+ subs, unsubs = web.GetChannelDifference(flushedSubs)
+ if len(subs) != 1 {
+ t.Fatal("error mismatch")
+ }
+ if len(unsubs) != 2 {
+ t.Fatal("error mismatch")
+ }
+}
+
+// GenSubs defines a theoretical exchange with pair management
+type GenSubs struct {
+ EnabledPairs currency.Pairs
+ subscribos []ChannelSubscription
+ unsubscribos []ChannelSubscription
+}
+
+// generateSubs default subs created from the enabled pairs list
+func (g *GenSubs) generateSubs() ([]ChannelSubscription, error) {
+ var superduperchannelsubs []ChannelSubscription
+ for i := range g.EnabledPairs {
+ superduperchannelsubs = append(superduperchannelsubs, ChannelSubscription{
+ Channel: "TEST:" + strconv.FormatInt(int64(i), 10),
+ Currency: g.EnabledPairs[i],
+ })
+ }
+ return superduperchannelsubs, nil
+}
+
+func (g *GenSubs) SUBME(subs []ChannelSubscription) error {
+ if len(subs) == 0 {
+ return errors.New("WOW")
+ }
+ g.subscribos = subs
+ return nil
+}
+
+func (g *GenSubs) UNSUBME(unsubs []ChannelSubscription) error {
+ if len(unsubs) == 0 {
+ return errors.New("WOW")
+ }
+ g.unsubscribos = unsubs
+ return nil
+}
+
+// sneaky connect func
+func connect() error { return nil }
+
+func TestFlushChannels(t *testing.T) {
+ // Enabled pairs/setup system
+ newgen := GenSubs{EnabledPairs: []currency.Pair{
+ currency.NewPair(currency.BTC, currency.AUD),
+ currency.NewPair(currency.BTC, currency.USDT),
+ }}
+ web := Websocket{enabled: true,
+ connected: true,
+ connector: connect,
+ ShutdownC: make(chan struct{}),
+ Subscriber: newgen.SUBME,
+ Unsubscriber: newgen.UNSUBME,
+ Wg: new(sync.WaitGroup),
+ features: &protocol.Features{
+ // No features
+ }}
+ web.GenerateSubs = newgen.generateSubs
+ subs, err := web.GenerateSubs()
+ if err != nil {
+ t.Fatal(err)
+ }
+ web.subscriptions = subs
+ // Disable pair and flush system
+ newgen.EnabledPairs = []currency.Pair{
+ currency.NewPair(currency.BTC, currency.AUD)}
+ err = web.FlushChannels()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ web.features.FullPayloadSubscribe = true
+ err = web.FlushChannels()
+ if err != nil {
+ t.Fatal(err)
+ }
+ web.features.FullPayloadSubscribe = false
+ web.features.Subscribe = true
+ err = web.FlushChannels()
+ if err != nil {
+ t.Fatal(err)
+ }
+ web.setConnectedStatus(true)
+ web.features.Unsubscribe = true
+ err = web.FlushChannels()
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestDisable(t *testing.T) {
+ web := Websocket{
+ enabled: true,
+ connected: true,
+ ShutdownC: make(chan struct{}),
+ }
+ err := web.Disable()
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = web.Disable()
+ if err == nil {
+ t.Fatal("should already be disabled")
+ }
+}
+
+func TestEnable(t *testing.T) {
+ web := Websocket{
+ connector: connect,
+ Wg: new(sync.WaitGroup),
+ ShutdownC: make(chan struct{}),
+ }
+ err := web.Enable()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ err = web.Enable()
+ if err == nil {
+ t.Fatal("should already be enabled")
+ }
+
+ fmt.Print()
+}
+
+func TestSetupNewConnection(t *testing.T) {
+ web := Websocket{
+ connector: connect,
+ Wg: new(sync.WaitGroup),
+ ShutdownC: make(chan struct{}),
+ Init: true,
+ TrafficAlert: make(chan struct{}),
+ ReadMessageErrors: make(chan error),
+ }
+
+ err := web.Setup(defaultSetup)
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = web.SetupNewConnection(ConnectionSetup{})
+ if err == nil {
+ t.Fatal("error cannot be nil")
+ }
+ err = web.SetupNewConnection(ConnectionSetup{URL: "urlstring"})
+ if err != nil {
+ t.Fatal(err)
+ }
+ err = web.SetupNewConnection(ConnectionSetup{URL: "urlstring",
+ Authenticated: true})
+ if err != nil {
+ t.Fatal(err)
+ }
+}
+
+func TestWebsocketConnectionShutdown(t *testing.T) {
+ wc := WebsocketConnection{}
+ err := wc.Shutdown()
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ err = wc.Dial(&websocket.Dialer{}, nil)
+ if err == nil {
+ t.Fatal("error cannot be nil")
+ }
+
+ wc.URL = "wss://echo.websocket.org"
+
+ err = wc.Dial(&websocket.Dialer{}, nil)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ err = wc.Shutdown()
+ if err != nil {
+ t.Fatal(err)
+ }
+}
diff --git a/exchanges/stream/websocket_types.go b/exchanges/stream/websocket_types.go
new file mode 100644
index 00000000..06f08518
--- /dev/null
+++ b/exchanges/stream/websocket_types.go
@@ -0,0 +1,132 @@
+package stream
+
+import (
+ "sync"
+ "time"
+
+ "github.com/gorilla/websocket"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream/buffer"
+)
+
+// Websocket functionality list and state consts
+const (
+ // WebsocketNotEnabled alerts of a disabled websocket
+ WebsocketNotEnabled = "exchange_websocket_not_enabled"
+ // connection monitor time delays and limits
+ connectionMonitorDelay = 2 * time.Second
+ WebsocketNotAuthenticatedUsingRest = "%v - Websocket not authenticated, using REST\n"
+ Ping = "ping"
+ Pong = "pong"
+ UnhandledMessage = " - Unhandled websocket message: "
+)
+
+// Websocket defines a return type for websocket connections via the interface
+// wrapper for routine processing in routines.go
+type Websocket struct {
+ canUseAuthenticatedEndpoints bool
+ enabled bool
+ Init bool
+ connected bool
+ connecting bool
+ verbose bool
+ connectionMonitorRunning bool
+ trafficMonitorRunning bool
+ dataMonitorRunning bool
+ trafficTimeout time.Duration
+ proxyAddr string
+ defaultURL string
+ defaultURLAuth string
+ runningURL string
+ runningURLAuth string
+ exchangeName string
+ m sync.Mutex
+ connectionMutex sync.RWMutex
+ connector func() error
+
+ subscriptionMutex sync.Mutex
+ subscriptions []ChannelSubscription
+ Subscribe chan []ChannelSubscription
+ Unsubscribe chan []ChannelSubscription
+
+ // Subscriber function for package defined websocket subscriber
+ // functionality
+ Subscriber func([]ChannelSubscription) error
+ // Unsubscriber function for packaged defined websocket unsubscriber
+ // functionality
+ Unsubscriber func([]ChannelSubscription) error
+ // GenerateSubs function for package defined websocket generate
+ // subscriptions functionality
+ GenerateSubs func() ([]ChannelSubscription, error)
+
+ DataHandler chan interface{}
+ ToRoutine chan interface{}
+
+ Match *Match
+
+ // shutdown synchronises shutdown event across routines
+ ShutdownC chan struct{}
+ Wg *sync.WaitGroup
+
+ // Orderbook is a local buffer of orderbooks
+ Orderbook buffer.Orderbook
+
+ // trafficAlert monitors if there is a halt in traffic throughput
+ TrafficAlert chan struct{}
+ // ReadMessageErrors will received all errors from ws.ReadMessage() and
+ // verify if its a disconnection
+ ReadMessageErrors chan error
+ features *protocol.Features
+
+ // Standard stream connection
+ Conn Connection
+ // Authenticated stream connection
+ AuthConn Connection
+}
+
+// WebsocketSetup defines variables for setting up a websocket connection
+type WebsocketSetup struct {
+ Enabled bool
+ Verbose bool
+ AuthenticatedWebsocketAPISupport bool
+ WebsocketTimeout time.Duration
+ DefaultURL string
+ ExchangeName string
+ RunningURL string
+ RunningURLAuth string
+ Connector func() error
+ Subscriber func([]ChannelSubscription) error
+ UnSubscriber func([]ChannelSubscription) error
+ GenerateSubscriptions func() ([]ChannelSubscription, error)
+ Features *protocol.Features
+ // Local orderbook buffer config values
+ OrderbookBufferLimit int
+ BufferEnabled bool
+ SortBuffer bool
+ SortBufferByUpdateIDs bool
+ UpdateEntriesByID bool
+}
+
+// WebsocketConnection contains all the data needed to send a message to a WS
+// connection
+type WebsocketConnection struct {
+ Verbose bool
+ connected int32
+
+ // Gorilla websocket does not allow more than one goroutine to utilise
+ // writes methods
+ writeControl sync.Mutex
+
+ RateLimit int64
+ ExchangeName string
+ URL string
+ ProxyURL string
+ Wg *sync.WaitGroup
+ Connection *websocket.Conn
+ ShutdownC chan struct{}
+
+ Match *Match
+ ResponseMaxLimit time.Duration
+ Traffic chan struct{}
+ readMessageErrors chan error
+}
diff --git a/exchanges/ticker/ticker.go b/exchanges/ticker/ticker.go
index ea418b84..7f7947cc 100644
--- a/exchanges/ticker/ticker.go
+++ b/exchanges/ticker/ticker.go
@@ -33,7 +33,6 @@ func SubscribeTicker(exchange string, p currency.Pair, a asset.Item) (dispatch.P
p,
a)
}
-
return service.mux.Subscribe(tick.Main)
}
@@ -80,25 +79,22 @@ func GetTicker(exchange string, p currency.Pair, tickerType asset.Item) (*Price,
// ProcessTicker processes incoming tickers, creating or updating the Tickers
// list
-func ProcessTicker(exchangeName string, tickerNew *Price, assetType asset.Item) error {
- if exchangeName == "" {
+func ProcessTicker(tickerNew *Price) error {
+ if tickerNew.ExchangeName == "" {
return fmt.Errorf(errExchangeNameUnset)
}
- tickerNew.ExchangeName = strings.ToLower(exchangeName)
-
if tickerNew.Pair.IsEmpty() {
- return fmt.Errorf("%s %s", exchangeName, errPairNotSet)
+ return fmt.Errorf("%s %s", tickerNew.ExchangeName, errPairNotSet)
}
- if assetType == "" {
- return fmt.Errorf("%s %s %s", exchangeName,
+ if tickerNew.AssetType == "" {
+ return fmt.Errorf("%s %s %s",
+ tickerNew.ExchangeName,
tickerNew.Pair,
errAssetTypeNotSet)
}
- tickerNew.AssetType = assetType
-
if tickerNew.LastUpdated.IsZero() {
tickerNew.LastUpdated = time.Now()
}
@@ -108,46 +104,11 @@ func ProcessTicker(exchangeName string, tickerNew *Price, assetType asset.Item)
// Update updates ticker price
func (s *Service) Update(p *Price) error {
- var ids []uuid.UUID
-
+ name := strings.ToLower(p.ExchangeName)
s.Lock()
- switch {
- case s.Tickers[p.ExchangeName] == nil:
- s.Tickers[p.ExchangeName] = make(map[*currency.Item]map[*currency.Item]map[asset.Item]*Ticker)
- s.Tickers[p.ExchangeName][p.Pair.Base.Item] = make(map[*currency.Item]map[asset.Item]*Ticker)
- s.Tickers[p.ExchangeName][p.Pair.Base.Item][p.Pair.Quote.Item] = make(map[asset.Item]*Ticker)
- err := s.SetItemID(p)
- if err != nil {
- s.Unlock()
- return err
- }
- case s.Tickers[p.ExchangeName][p.Pair.Base.Item] == nil:
- s.Tickers[p.ExchangeName][p.Pair.Base.Item] = make(map[*currency.Item]map[asset.Item]*Ticker)
- s.Tickers[p.ExchangeName][p.Pair.Base.Item][p.Pair.Quote.Item] = make(map[asset.Item]*Ticker)
- err := s.SetItemID(p)
- if err != nil {
- s.Unlock()
- return err
- }
-
- case s.Tickers[p.ExchangeName][p.Pair.Base.Item][p.Pair.Quote.Item] == nil:
- s.Tickers[p.ExchangeName][p.Pair.Base.Item][p.Pair.Quote.Item] = make(map[asset.Item]*Ticker)
- err := s.SetItemID(p)
- if err != nil {
- s.Unlock()
- return err
- }
-
- case s.Tickers[p.ExchangeName][p.Pair.Base.Item][p.Pair.Quote.Item][p.AssetType] == nil:
- err := s.SetItemID(p)
- if err != nil {
- s.Unlock()
- return err
- }
-
- default:
- ticker := s.Tickers[p.ExchangeName][p.Pair.Base.Item][p.Pair.Quote.Item][p.AssetType]
+ ticker, ok := s.Tickers[name][p.Pair.Base.Item][p.Pair.Quote.Item][p.AssetType]
+ if ok {
ticker.Last = p.Last
ticker.High = p.High
ticker.Low = p.Low
@@ -159,20 +120,39 @@ func (s *Service) Update(p *Price) error {
ticker.Open = p.Open
ticker.Close = p.Close
ticker.LastUpdated = p.LastUpdated
- ids = ticker.Assoc
- ids = append(ids, ticker.Main)
+ ids := append(ticker.Assoc, ticker.Main)
+ s.Unlock()
+ return s.mux.Publish(ids, p)
}
+
+ switch {
+ case s.Tickers[name] == nil:
+ s.Tickers[name] = make(map[*currency.Item]map[*currency.Item]map[asset.Item]*Ticker)
+ fallthrough
+ case s.Tickers[name][p.Pair.Base.Item] == nil:
+ s.Tickers[name][p.Pair.Base.Item] = make(map[*currency.Item]map[asset.Item]*Ticker)
+ fallthrough
+ case s.Tickers[name][p.Pair.Base.Item][p.Pair.Quote.Item] == nil:
+ s.Tickers[name][p.Pair.Base.Item][p.Pair.Quote.Item] = make(map[asset.Item]*Ticker)
+ }
+
+ err := s.SetItemID(p, name)
+ if err != nil {
+ s.Unlock()
+ return err
+ }
+
s.Unlock()
- return s.mux.Publish(ids, p)
+ return nil
}
// SetItemID retrieves and sets dispatch mux publish IDs
-func (s *Service) SetItemID(p *Price) error {
+func (s *Service) SetItemID(p *Price, fmtName string) error {
if p == nil {
return errors.New(errTickerPriceIsNil)
}
- ids, err := s.GetAssociations(p)
+ ids, err := s.GetAssociations(p, fmtName)
if err != nil {
return err
}
@@ -181,26 +161,26 @@ func (s *Service) SetItemID(p *Price) error {
return err
}
- s.Tickers[p.ExchangeName][p.Pair.Base.Item][p.Pair.Quote.Item][p.AssetType] = &Ticker{Price: *p,
+ s.Tickers[fmtName][p.Pair.Base.Item][p.Pair.Quote.Item][p.AssetType] = &Ticker{Price: *p,
Main: singleID,
Assoc: ids}
return nil
}
// GetAssociations links a singular book with it's dispatch associations
-func (s *Service) GetAssociations(p *Price) ([]uuid.UUID, error) {
+func (s *Service) GetAssociations(p *Price, fmtName string) ([]uuid.UUID, error) {
if p == nil || *p == (Price{}) {
return nil, errors.New(errTickerPriceIsNil)
}
var ids []uuid.UUID
- exchangeID, ok := s.Exchange[p.ExchangeName]
+ exchangeID, ok := s.Exchange[fmtName]
if !ok {
var err error
exchangeID, err = s.mux.GetID()
if err != nil {
return nil, err
}
- s.Exchange[p.ExchangeName] = exchangeID
+ s.Exchange[fmtName] = exchangeID
}
ids = append(ids, exchangeID)
diff --git a/exchanges/ticker/ticker_test.go b/exchanges/ticker/ticker_test.go
index a947b33e..feff25d7 100644
--- a/exchanges/ticker/ticker_test.go
+++ b/exchanges/ticker/ticker_test.go
@@ -37,32 +37,48 @@ func TestSubscribeTicker(t *testing.T) {
// force error
service.mux = nil
- err = ProcessTicker("subscribetest", &Price{Pair: p}, asset.Spot)
+ err = ProcessTicker(&Price{
+ Pair: p,
+ ExchangeName: "subscribetest",
+ AssetType: asset.Spot})
if err == nil {
t.Error("error cannot be nil")
}
sillyP := p
sillyP.Base = currency.GALA_NEO
- err = ProcessTicker("subscribetest", &Price{Pair: sillyP}, asset.Spot)
+ err = ProcessTicker(&Price{
+ Pair: sillyP,
+ ExchangeName: "subscribetest",
+ AssetType: asset.Spot})
if err == nil {
t.Error("error cannot be nil")
}
sillyP.Quote = currency.AAA
- err = ProcessTicker("subscribetest", &Price{Pair: sillyP}, asset.Spot)
+ err = ProcessTicker(&Price{
+ Pair: sillyP,
+ ExchangeName: "subscribetest",
+ AssetType: asset.Spot})
if err == nil {
t.Error("error cannot be nil")
}
- err = ProcessTicker("subscribetest", &Price{Pair: sillyP}, "silly")
+ err = ProcessTicker(&Price{
+ Pair: sillyP,
+ ExchangeName: "subscribetest",
+ AssetType: "silly",
+ })
if err == nil {
t.Error("error cannot be nil")
}
// reinstate mux
service.mux = cpyMux
- err = ProcessTicker("subscribetest", &Price{Pair: p}, asset.Spot)
+ err = ProcessTicker(&Price{
+ Pair: p,
+ ExchangeName: "subscribetest",
+ AssetType: asset.Spot})
if err != nil {
t.Error("error cannot be nil")
}
@@ -81,7 +97,10 @@ func TestSubscribeToExchangeTickers(t *testing.T) {
p := currency.NewPair(currency.BTC, currency.USD)
- err = ProcessTicker("subscribeExchangeTest", &Price{Pair: p}, asset.Spot)
+ err = ProcessTicker(&Price{
+ Pair: p,
+ ExchangeName: "subscribeExchangeTest",
+ AssetType: asset.Spot})
if err != nil {
t.Error(err)
}
@@ -93,19 +112,24 @@ func TestSubscribeToExchangeTickers(t *testing.T) {
}
func TestGetTicker(t *testing.T) {
- newPair := currency.NewPairFromStrings("BTC", "USD")
+ newPair, err := currency.NewPairFromStrings("BTC", "USD")
+ if err != nil {
+ t.Fatal(err)
+ }
priceStruct := Price{
- Pair: newPair,
- Last: 1200,
- High: 1298,
- Low: 1148,
- Bid: 1195,
- Ask: 1220,
- Volume: 5,
- PriceATH: 1337,
+ Pair: newPair,
+ Last: 1200,
+ High: 1298,
+ Low: 1148,
+ Bid: 1195,
+ Ask: 1220,
+ Volume: 5,
+ PriceATH: 1337,
+ ExchangeName: "bitfinex",
+ AssetType: asset.Spot,
}
- err := ProcessTicker("bitfinex", &priceStruct, asset.Spot)
+ err = ProcessTicker(&priceStruct)
if err != nil {
t.Fatal("ProcessTicker error", err)
}
@@ -129,7 +153,11 @@ func TestGetTicker(t *testing.T) {
t.Fatal("TestGetTicker returned ticker for invalid first currency")
}
- btcltcPair := currency.NewPairFromStrings("BTC", "LTC")
+ btcltcPair, err := currency.NewPairFromStrings("BTC", "LTC")
+ if err != nil {
+ t.Fatal(err)
+ }
+
_, err = GetTicker("bitfinex", btcltcPair, asset.Spot)
if err == nil {
t.Fatal("TestGetTicker returned ticker for invalid second currency")
@@ -137,7 +165,8 @@ func TestGetTicker(t *testing.T) {
priceStruct.PriceATH = 9001
priceStruct.Pair.Base = currency.ETH
- err = ProcessTicker("bitfinex", &priceStruct, "futures_3m")
+ priceStruct.AssetType = "futures_3m"
+ err = ProcessTicker(&priceStruct)
if err != nil {
t.Fatal("ProcessTicker error", err)
}
@@ -156,13 +185,14 @@ func TestGetTicker(t *testing.T) {
t.Error("Ticker GetTicker error cannot be nil")
}
- err = ProcessTicker("bitfinex", &priceStruct, "meowCats")
+ priceStruct.AssetType = "meowCats"
+ err = ProcessTicker(&priceStruct)
if err != nil {
t.Fatal("ProcessTicker error", err)
}
// process update again
- err = ProcessTicker("bitfinex", &priceStruct, "meowCats")
+ err = ProcessTicker(&priceStruct)
if err != nil {
t.Fatal("ProcessTicker error", err)
}
@@ -170,7 +200,11 @@ func TestGetTicker(t *testing.T) {
func TestProcessTicker(t *testing.T) { // non-appending function to tickers
exchName := "bitstamp"
- newPair := currency.NewPairFromStrings("BTC", "USD")
+ newPair, err := currency.NewPairFromStrings("BTC", "USD")
+ if err != nil {
+ t.Fatal(err)
+ }
+
priceStruct := Price{
Last: 1200,
High: 1298,
@@ -181,26 +215,28 @@ func TestProcessTicker(t *testing.T) { // non-appending function to tickers
PriceATH: 1337,
}
- err := ProcessTicker("", &priceStruct, asset.Spot)
+ err = ProcessTicker(&priceStruct)
if err == nil {
t.Fatal("empty exchange should throw an err")
}
+ priceStruct.ExchangeName = exchName
+
// test for empty pair
- err = ProcessTicker(exchName, &priceStruct, asset.Spot)
+ err = ProcessTicker(&priceStruct)
if err == nil {
t.Fatal("empty pair should throw an err")
}
// test for empty asset type
priceStruct.Pair = newPair
- err = ProcessTicker(exchName, &priceStruct, "")
+ err = ProcessTicker(&priceStruct)
if err == nil {
t.Fatal("ProcessTicker error cannot be nil")
}
-
+ priceStruct.AssetType = asset.Spot
// now process a valid ticker
- err = ProcessTicker(exchName, &priceStruct, asset.Spot)
+ err = ProcessTicker(&priceStruct)
if err != nil {
t.Fatal("ProcessTicker error", err)
}
@@ -213,9 +249,13 @@ func TestProcessTicker(t *testing.T) { // non-appending function to tickers
}
// now test for processing a pair with a different quote currency
- newPair = currency.NewPairFromStrings("BTC", "AUD")
+ newPair, err = currency.NewPairFromStrings("BTC", "AUD")
+ if err != nil {
+ t.Fatal(err)
+ }
+
priceStruct.Pair = newPair
- err = ProcessTicker(exchName, &priceStruct, asset.Spot)
+ err = ProcessTicker(&priceStruct)
if err != nil {
t.Fatal("ProcessTicker error", err)
}
@@ -229,9 +269,13 @@ func TestProcessTicker(t *testing.T) { // non-appending function to tickers
}
// now test for processing a pair which has a different base currency
- newPair = currency.NewPairFromStrings("LTC", "AUD")
+ newPair, err = currency.NewPairFromStrings("LTC", "AUD")
+ if err != nil {
+ t.Fatal(err)
+ }
+
priceStruct.Pair = newPair
- err = ProcessTicker(exchName, &priceStruct, asset.Spot)
+ err = ProcessTicker(&priceStruct)
if err != nil {
t.Fatal("ProcessTicker error", err)
}
@@ -266,16 +310,21 @@ func TestProcessTicker(t *testing.T) { // non-appending function to tickers
wg.Add(1)
go func() {
newName := "Exchange" + strconv.FormatInt(rand.Int63(), 10)
- newPairs := currency.NewPairFromStrings("BTC"+strconv.FormatInt(rand.Int63(), 10),
+ newPairs, err := currency.NewPairFromStrings("BTC"+strconv.FormatInt(rand.Int63(), 10),
"USD"+strconv.FormatInt(rand.Int63(), 10))
+ if err != nil {
+ log.Fatal(err)
+ }
tp := Price{
- Pair: newPairs,
- Last: rand.Float64(),
+ Pair: newPairs,
+ Last: rand.Float64(),
+ ExchangeName: newName,
+ AssetType: asset.Spot,
}
sm.Lock()
- err = ProcessTicker(newName, &tp, asset.Spot)
+ err = ProcessTicker(&tp)
if err != nil {
t.Error(err)
catastrophicFailure = true
@@ -319,12 +368,12 @@ func TestProcessTicker(t *testing.T) { // non-appending function to tickers
}
func TestSetItemID(t *testing.T) {
- err := service.SetItemID(nil)
+ err := service.SetItemID(nil, "")
if err == nil {
t.Error("error cannot be nil")
}
- err = service.SetItemID(&Price{})
+ err = service.SetItemID(&Price{}, "")
if err == nil {
t.Error("error cannot be nil")
}
@@ -332,7 +381,7 @@ func TestSetItemID(t *testing.T) {
p := currency.NewPair(currency.CYC, currency.CYG)
service.mux = nil
- err = service.SetItemID(&Price{Pair: p, ExchangeName: "SetItemID"})
+ err = service.SetItemID(&Price{Pair: p, ExchangeName: "SetItemID"}, "setitemid")
if err == nil {
t.Error("error cannot be nil")
}
@@ -341,7 +390,7 @@ func TestSetItemID(t *testing.T) {
}
func TestGetAssociation(t *testing.T) {
- _, err := service.GetAssociations(nil)
+ _, err := service.GetAssociations(nil, "")
if err == nil {
t.Error("error cannot be nil")
}
@@ -350,7 +399,7 @@ func TestGetAssociation(t *testing.T) {
service.mux = nil
- _, err = service.GetAssociations(&Price{Pair: p, ExchangeName: "GetAssociation"})
+ _, err = service.GetAssociations(&Price{Pair: p, ExchangeName: "GetAssociation"}, "getassociation")
if err == nil {
t.Error("error cannot be nil")
}
diff --git a/exchanges/websocket/wshandler/wshandler.go b/exchanges/websocket/wshandler/wshandler.go
deleted file mode 100644
index c29e4a29..00000000
--- a/exchanges/websocket/wshandler/wshandler.go
+++ /dev/null
@@ -1,898 +0,0 @@
-package wshandler
-
-import (
- "bytes"
- "compress/flate"
- "compress/gzip"
- "errors"
- "fmt"
- "io/ioutil"
- "net"
- "net/http"
- "net/url"
- "strings"
- "sync"
- "time"
-
- "github.com/gorilla/websocket"
- "github.com/thrasher-corp/gocryptotrader/config"
- "github.com/thrasher-corp/gocryptotrader/log"
-)
-
-// New initialises the websocket struct
-func New() *Websocket {
- return &Websocket{
- defaultURL: "",
- enabled: false,
- proxyAddr: "",
- runningURL: "",
- init: true,
- }
-}
-
-// Setup sets main variables for websocket connection
-func (w *Websocket) Setup(setupData *WebsocketSetup) error {
- w.DataHandler = make(chan interface{}, 1)
- w.TrafficAlert = make(chan struct{}, 1)
- w.verbose = setupData.Verbose
- w.SetChannelSubscriber(setupData.Subscriber)
- w.SetChannelUnsubscriber(setupData.UnSubscriber)
- w.enabled = setupData.Enabled
- w.SetDefaultURL(setupData.DefaultURL)
- w.SetConnector(setupData.Connector)
- w.SetWebsocketURL(setupData.RunningURL)
- w.SetExchangeName(setupData.ExchangeName)
- w.SetCanUseAuthenticatedEndpoints(setupData.AuthenticatedWebsocketAPISupport)
- w.trafficTimeout = setupData.WebsocketTimeout
- w.features = setupData.Features
- err := w.Initialise()
- if err != nil {
- return err
- }
-
- return nil
-}
-
-// Connect initiates a websocket connection by using a package defined connection
-// function
-func (w *Websocket) Connect() error {
- w.m.Lock()
- defer w.m.Unlock()
-
- if !w.IsEnabled() {
- return errors.New(WebsocketNotEnabled)
- }
- if w.IsConnecting() {
- return fmt.Errorf("%v Websocket already attempting to connect",
- w.exchangeName)
- }
- if w.IsConnected() {
- return fmt.Errorf("%v Websocket already connected",
- w.exchangeName)
- }
- w.setConnectingStatus(true)
- w.ShutdownC = make(chan struct{}, 1)
- w.ReadMessageErrors = make(chan error, 1)
- err := w.connector()
- if err != nil {
- w.setConnectingStatus(false)
- return fmt.Errorf("%v Error connecting %s",
- w.exchangeName, err)
- }
-
- w.setConnectedStatus(true)
- w.setConnectingStatus(false)
- w.setInit(true)
-
- var anotherWG sync.WaitGroup
- anotherWG.Add(1)
- go w.trafficMonitor(&anotherWG)
- anotherWG.Wait()
- if !w.IsConnectionMonitorRunning() {
- go w.connectionMonitor()
- }
- if w.features.Subscribe || w.features.Unsubscribe {
- w.Wg.Add(1)
- go w.manageSubscriptions()
- }
-
- return nil
-}
-
-// connectionMonitor ensures that the WS keeps connecting
-func (w *Websocket) connectionMonitor() {
- if w.IsConnectionMonitorRunning() {
- return
- }
- w.setConnectionMonitorRunning(true)
- timer := time.NewTimer(connectionMonitorDelay)
-
- defer func() {
- if !timer.Stop() {
- select {
- case <-timer.C:
- default:
- }
- }
- w.setConnectionMonitorRunning(false)
- if w.verbose {
- log.Debugf(log.WebsocketMgr, "%v websocket connection monitor exiting",
- w.exchangeName)
- }
- }()
-
- for {
- if w.verbose {
- log.Debugf(log.WebsocketMgr, "%v running connection monitor cycle",
- w.exchangeName)
- }
- if !w.IsEnabled() {
- if w.verbose {
- log.Debugf(log.WebsocketMgr, "%v connectionMonitor: websocket disabled, shutting down", w.exchangeName)
- }
- if w.IsConnected() {
- err := w.Shutdown()
- if err != nil {
- log.Error(log.WebsocketMgr, err)
- }
- }
- if w.verbose {
- log.Debugf(log.WebsocketMgr, "%v websocket connection monitor exiting",
- w.exchangeName)
- }
- return
- }
- select {
- case err := <-w.ReadMessageErrors:
- // check if this error is a disconnection error
- if isDisconnectionError(err) {
- w.setConnectedStatus(false)
- w.setConnectingStatus(false)
- w.setInit(false)
- if w.verbose {
- log.Debugf(log.WebsocketMgr, "%v websocket has been disconnected. Reason: %v",
- w.exchangeName, err)
- }
- err = w.Connect()
- if err != nil {
- log.Error(log.WebsocketMgr, err)
- }
- } else {
- // pass off non disconnect errors to datahandler to manage
- w.DataHandler <- err
- }
- case <-timer.C:
- if !w.IsConnecting() && !w.IsConnected() {
- err := w.Connect()
- if err != nil {
- log.Error(log.WebsocketMgr, err)
- }
- }
- if !timer.Stop() {
- select {
- case <-timer.C:
- default:
- }
- }
- timer.Reset(connectionMonitorDelay)
- }
- }
-}
-
-// Shutdown attempts to shut down a websocket connection and associated routines
-// by using a package defined shutdown function
-func (w *Websocket) Shutdown() error {
- w.m.Lock()
- defer func() {
- w.Orderbook.FlushCache()
- w.m.Unlock()
- }()
- if !w.IsConnected() {
- return fmt.Errorf("%v cannot shutdown a disconnected websocket", w.exchangeName)
- }
- if w.verbose {
- log.Debugf(log.WebsocketMgr, "%v shutting down websocket channels", w.exchangeName)
- }
- close(w.ShutdownC)
- w.Wg.Wait()
- w.setConnectedStatus(false)
- w.setConnectingStatus(false)
- if w.verbose {
- log.Debugf(log.WebsocketMgr, "%v completed websocket channel shutdown", w.exchangeName)
- }
- return nil
-}
-
-// trafficMonitor uses a timer of WebsocketTrafficLimitTime and once it expires
-// Will reconnect if the TrafficAlert channel has not received any data
-// The trafficTimer will reset on each traffic alert
-func (w *Websocket) trafficMonitor(wg *sync.WaitGroup) {
- w.Wg.Add(1)
- wg.Done()
- trafficTimer := time.NewTimer(w.trafficTimeout)
- defer func() {
- if !trafficTimer.Stop() {
- select {
- case <-trafficTimer.C:
- default:
- }
- }
- w.setTrafficMonitorRunning(false)
- w.Wg.Done()
- }()
- if w.IsTrafficMonitorRunning() {
- return
- }
- w.setTrafficMonitorRunning(true)
- for {
- select {
- case <-w.ShutdownC:
- if w.verbose {
- log.Debugf(log.WebsocketMgr, "%v trafficMonitor shutdown message received", w.exchangeName)
- }
- return
- case <-w.TrafficAlert:
- if !trafficTimer.Stop() {
- select {
- case <-trafficTimer.C:
- default:
- }
- }
- trafficTimer.Reset(w.trafficTimeout)
- case <-trafficTimer.C: // Falls through when timer runs out
- if w.verbose {
- log.Warnf(log.WebsocketMgr, "%v has not received a traffic alert in %v. Reconnecting", w.exchangeName, w.trafficTimeout)
- }
- go w.Shutdown()
- }
- }
-}
-
-func (w *Websocket) setConnectedStatus(b bool) {
- w.connectionMutex.Lock()
- w.connected = b
- w.connectionMutex.Unlock()
-}
-
-// IsConnected returns status of connection
-func (w *Websocket) IsConnected() bool {
- w.connectionMutex.RLock()
- isConnected := w.connected
- w.connectionMutex.RUnlock()
- return isConnected
-}
-
-func (w *Websocket) setConnectingStatus(b bool) {
- w.connectionMutex.Lock()
- w.connecting = b
- w.connectionMutex.Unlock()
-}
-
-// IsConnecting returns status of connecting
-func (w *Websocket) IsConnecting() bool {
- w.connectionMutex.RLock()
- isConnecting := w.connecting
- w.connectionMutex.RUnlock()
- return isConnecting
-}
-
-func (w *Websocket) setEnabled(b bool) {
- w.connectionMutex.Lock()
- w.enabled = b
- w.connectionMutex.Unlock()
-}
-
-// IsEnabled returns status of enabled
-func (w *Websocket) IsEnabled() bool {
- w.connectionMutex.RLock()
- isEnabled := w.enabled
- w.connectionMutex.RUnlock()
- return isEnabled
-}
-
-func (w *Websocket) setInit(b bool) {
- w.connectionMutex.Lock()
- w.init = b
- w.connectionMutex.Unlock()
-}
-
-// IsInit returns status of init
-func (w *Websocket) IsInit() bool {
- w.connectionMutex.RLock()
- isInit := w.init
- w.connectionMutex.RUnlock()
- return isInit
-}
-
-func (w *Websocket) setTrafficMonitorRunning(b bool) {
- w.connectionMutex.Lock()
- w.trafficMonitorRunning = b
- w.connectionMutex.Unlock()
-}
-
-// IsTrafficMonitorRunning returns status of the traffic monitor
-func (w *Websocket) IsTrafficMonitorRunning() bool {
- w.connectionMutex.RLock()
- trafficMonRunning := w.trafficMonitorRunning
- w.connectionMutex.RUnlock()
- return trafficMonRunning
-}
-
-func (w *Websocket) setConnectionMonitorRunning(b bool) {
- w.connectionMutex.Lock()
- w.connectionMonitorRunning = b
- w.connectionMutex.Unlock()
-}
-
-// IsConnectionMonitorRunning returns status of connection monitor
-func (w *Websocket) IsConnectionMonitorRunning() bool {
- w.connectionMutex.RLock()
- isConnMonRunning := w.connectionMonitorRunning
- w.connectionMutex.RUnlock()
- return isConnMonRunning
-}
-
-// CanUseAuthenticatedWebsocketForWrapper Handles a common check to
-// verify whether a wrapper can use an authenticated websocket endpoint
-func (w *Websocket) CanUseAuthenticatedWebsocketForWrapper() bool {
- if w.IsConnected() && w.CanUseAuthenticatedEndpoints() {
- return true
- } else if w.IsConnected() && !w.CanUseAuthenticatedEndpoints() {
- log.Infof(log.WebsocketMgr, WebsocketNotAuthenticatedUsingRest, w.exchangeName)
- }
- return false
-}
-
-// SetWebsocketURL sets websocket URL
-func (w *Websocket) SetWebsocketURL(websocketURL string) {
- if websocketURL == "" || websocketURL == config.WebsocketURLNonDefaultMessage {
- w.runningURL = w.defaultURL
- return
- }
- w.runningURL = websocketURL
-}
-
-// GetWebsocketURL returns the running websocket URL
-func (w *Websocket) GetWebsocketURL() string {
- return w.runningURL
-}
-
-// Initialise verifies status and connects
-func (w *Websocket) Initialise() error {
- if w.IsEnabled() {
- if w.IsInit() {
- return nil
- }
- return fmt.Errorf("%v Websocket already initialised",
- w.exchangeName)
- }
- w.setEnabled(w.enabled)
- return nil
-}
-
-// SetProxyAddress sets websocket proxy address
-func (w *Websocket) SetProxyAddress(proxyAddr string) error {
- if w.proxyAddr == proxyAddr {
- return fmt.Errorf("%v Cannot set proxy address to the same address '%v'", w.exchangeName, w.proxyAddr)
- }
-
- w.proxyAddr = proxyAddr
- if !w.IsInit() && w.IsEnabled() {
- if w.IsConnected() {
- err := w.Shutdown()
- if err != nil {
- return err
- }
- }
- return w.Connect()
- }
- return nil
-}
-
-// GetProxyAddress returns the current websocket proxy
-func (w *Websocket) GetProxyAddress() string {
- return w.proxyAddr
-}
-
-// SetDefaultURL sets default websocket URL
-func (w *Websocket) SetDefaultURL(defaultURL string) {
- w.defaultURL = defaultURL
-}
-
-// GetDefaultURL returns the default websocket URL
-func (w *Websocket) GetDefaultURL() string {
- return w.defaultURL
-}
-
-// SetConnector sets connection function
-func (w *Websocket) SetConnector(connector func() error) {
- w.connector = connector
-}
-
-// SetExchangeName sets exchange name
-func (w *Websocket) SetExchangeName(exchName string) {
- w.exchangeName = exchName
-}
-
-// GetName returns exchange name
-func (w *Websocket) GetName() string {
- return w.exchangeName
-}
-
-// SetChannelSubscriber sets the function to use the base subscribe func
-func (w *Websocket) SetChannelSubscriber(subscriber func(channelToSubscribe WebsocketChannelSubscription) error) {
- w.channelSubscriber = subscriber
-}
-
-// SetChannelUnsubscriber sets the function to use the base unsubscribe func
-func (w *Websocket) SetChannelUnsubscriber(unsubscriber func(channelToUnsubscribe WebsocketChannelSubscription) error) {
- w.channelUnsubscriber = unsubscriber
-}
-
-// ManageSubscriptions ensures the subscriptions specified continue to be subscribed to
-func (w *Websocket) manageSubscriptions() {
- if !w.features.Subscribe && !w.features.Unsubscribe {
- w.DataHandler <- fmt.Errorf("%v does not support channel subscriptions, exiting ManageSubscriptions()", w.exchangeName)
- return
- }
- defer func() {
- if w.verbose {
- log.Debugf(log.WebsocketMgr, "%v ManageSubscriptions exiting", w.exchangeName)
- }
- w.Wg.Done()
- }()
- for {
- select {
- case <-w.ShutdownC:
- w.subscriptionMutex.Lock()
- w.subscribedChannels = []WebsocketChannelSubscription{}
- w.subscriptionMutex.Unlock()
- if w.verbose {
- log.Debugf(log.WebsocketMgr, "%v shutdown manageSubscriptions", w.exchangeName)
- }
- return
- default:
- time.Sleep(manageSubscriptionsDelay)
- if !w.IsConnected() {
- w.subscriptionMutex.Lock()
- w.subscribedChannels = []WebsocketChannelSubscription{}
- w.subscriptionMutex.Unlock()
-
- continue
- }
- if w.verbose {
- log.Debugf(log.WebsocketMgr, "%v checking subscriptions", w.exchangeName)
- }
- // Subscribe to channels Pending a subscription
- if w.features.Subscribe {
- err := w.appendSubscribedChannels()
- if err != nil {
- w.DataHandler <- err
- }
- }
- if w.features.Unsubscribe {
- err := w.unsubscribeToChannels()
- if err != nil {
- w.DataHandler <- err
- }
- }
- }
- }
-}
-
-// appendSubscribedChannels compares channelsToSubscribe to subscribedChannels
-// and subscribes to any channels not present in subscribedChannels
-func (w *Websocket) appendSubscribedChannels() error {
- w.subscriptionMutex.Lock()
- defer w.subscriptionMutex.Unlock()
- for i := range w.channelsToSubscribe {
- channelIsSubscribed := false
- for j := 0; j < len(w.subscribedChannels); j++ {
- if w.subscribedChannels[j].Equal(&w.channelsToSubscribe[i]) {
- channelIsSubscribed = true
- break
- }
- }
- if !channelIsSubscribed {
- if w.verbose {
- log.Debugf(log.WebsocketMgr, "%v Subscribing to %v %v", w.exchangeName, w.channelsToSubscribe[i].Channel, w.channelsToSubscribe[i].Currency.String())
- }
- err := w.channelSubscriber(w.channelsToSubscribe[i])
- if err != nil {
- return err
- }
- w.subscribedChannels = append(w.subscribedChannels, w.channelsToSubscribe[i])
- }
- }
- return nil
-}
-
-// unsubscribeToChannels compares subscribedChannels to channelsToSubscribe
-// and unsubscribes to any channels not present in channelsToSubscribe
-func (w *Websocket) unsubscribeToChannels() error {
- w.subscriptionMutex.Lock()
- defer w.subscriptionMutex.Unlock()
- for i := range w.subscribedChannels {
- subscriptionFound := false
- for j := 0; j < len(w.channelsToSubscribe); j++ {
- if w.channelsToSubscribe[j].Equal(&w.subscribedChannels[i]) {
- subscriptionFound = true
- break
- }
- }
- if !subscriptionFound {
- err := w.channelUnsubscriber(w.subscribedChannels[i])
- if err != nil {
- return err
- }
- }
- }
- // Now that the slices should match, assign rather than looping and appending the differences
- w.subscribedChannels = append(w.channelsToSubscribe[:0:0], w.channelsToSubscribe...) //nolint:gocritic
-
- return nil
-}
-
-// RemoveSubscribedChannels removes supplied channels from channelsToSubscribe
-func (w *Websocket) RemoveSubscribedChannels(channels []WebsocketChannelSubscription) {
- for i := range channels {
- w.removeChannelToSubscribe(channels[i])
- }
-}
-
-// removeChannelToSubscribe removes an entry from w.channelsToSubscribe
-// so an unsubscribe event can be triggered
-func (w *Websocket) removeChannelToSubscribe(subscribedChannel WebsocketChannelSubscription) {
- w.subscriptionMutex.Lock()
- defer w.subscriptionMutex.Unlock()
- channelLength := len(w.channelsToSubscribe)
- i := 0
- for j := 0; j < len(w.channelsToSubscribe); j++ {
- if !w.channelsToSubscribe[j].Equal(&subscribedChannel) {
- w.channelsToSubscribe[i] = w.channelsToSubscribe[j]
- i++
- }
- }
- w.channelsToSubscribe = w.channelsToSubscribe[:i]
- if channelLength == len(w.channelsToSubscribe) {
- w.DataHandler <- fmt.Errorf("%v removeChannelToSubscribe() Channel %v Currency %v could not be removed because it was not found",
- w.exchangeName,
- subscribedChannel.Channel,
- subscribedChannel.Currency)
- }
-}
-
-// ResubscribeToChannel calls unsubscribe func and
-// removes it from subscribedChannels to trigger a subscribe event
-func (w *Websocket) ResubscribeToChannel(subscribedChannel WebsocketChannelSubscription) {
- w.subscriptionMutex.Lock()
- defer w.subscriptionMutex.Unlock()
- err := w.channelUnsubscriber(subscribedChannel)
- if err != nil {
- w.DataHandler <- err
- }
- // Remove the channel from the list of subscribed channels
- // ManageSubscriptions will automatically resubscribe
- i := 0
- for j := 0; j < len(w.subscribedChannels); j++ {
- if !w.subscribedChannels[j].Equal(&subscribedChannel) {
- w.subscribedChannels[i] = w.subscribedChannels[j]
- i++
- }
- }
- w.subscribedChannels = w.subscribedChannels[:i]
-}
-
-// SubscribeToChannels appends supplied channels to channelsToSubscribe
-func (w *Websocket) SubscribeToChannels(channels []WebsocketChannelSubscription) {
- for i := range channels {
- channelFound := false
- for j := range w.channelsToSubscribe {
- if w.channelsToSubscribe[j].Equal(&channels[i]) {
- channelFound = true
- }
- }
- if !channelFound {
- w.channelsToSubscribe = append(w.channelsToSubscribe, channels[i])
- }
- }
-}
-
-// Equal two WebsocketChannelSubscription to determine equality
-func (w *WebsocketChannelSubscription) Equal(subscribedChannel *WebsocketChannelSubscription) bool {
- return strings.EqualFold(w.Channel, subscribedChannel.Channel) &&
- strings.EqualFold(w.Currency.String(), subscribedChannel.Currency.String())
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-// subscriptions is a private member and cannot be manipulated
-func (w *Websocket) GetSubscriptions() []WebsocketChannelSubscription {
- return append(w.subscribedChannels[:0:0], w.subscribedChannels...)
-}
-
-// SetCanUseAuthenticatedEndpoints sets canUseAuthenticatedEndpoints val in
-// a thread safe manner
-func (w *Websocket) SetCanUseAuthenticatedEndpoints(val bool) {
- w.subscriptionMutex.Lock()
- defer w.subscriptionMutex.Unlock()
- w.canUseAuthenticatedEndpoints = val
-}
-
-// CanUseAuthenticatedEndpoints gets canUseAuthenticatedEndpoints val in
-// a thread safe manner
-func (w *Websocket) CanUseAuthenticatedEndpoints() bool {
- w.subscriptionMutex.Lock()
- canUseAuthEndpoints := w.canUseAuthenticatedEndpoints
- w.subscriptionMutex.Unlock()
- return canUseAuthEndpoints
-}
-
-// SetResponseIDAndData adds data to IDResponses with locks and a nil check
-func (w *WebsocketConnection) SetResponseIDAndData(id int64, data []byte) {
- w.Lock()
- defer w.Unlock()
- if w.IDResponses == nil {
- w.IDResponses = make(map[int64][]byte)
- }
- w.IDResponses[id] = data
-}
-
-// Dial sets proxy urls and then connects to the websocket
-func (w *WebsocketConnection) Dial(dialer *websocket.Dialer, headers http.Header) error {
- if w.ProxyURL != "" {
- proxy, err := url.Parse(w.ProxyURL)
- if err != nil {
- return err
- }
- dialer.Proxy = http.ProxyURL(proxy)
- }
- var err error
- var conStatus *http.Response
- w.Connection, conStatus, err = dialer.Dial(w.URL, headers)
- if conStatus != nil {
- conStatus.Body.Close()
- }
- if err != nil {
- if conStatus != nil {
- return fmt.Errorf("%v %v %v Error: %v", w.URL, conStatus, conStatus.StatusCode, err)
- }
- return fmt.Errorf("%v Error: %v", w.URL, err)
- }
- if w.Verbose {
- log.Infof(log.WebsocketMgr, "%v Websocket connected to %s", w.ExchangeName, w.URL)
- }
- w.setConnectedStatus(true)
- return nil
-}
-
-// SendJSONMessage sends a JSON encoded message over the connection
-func (w *WebsocketConnection) SendJSONMessage(data interface{}) error {
- w.Lock()
- defer w.Unlock()
- if !w.IsConnected() {
- return fmt.Errorf("%v cannot send message to a disconnected websocket", w.ExchangeName)
- }
- if w.Verbose {
- log.Debugf(log.WebsocketMgr,
- "%v sending message to websocket %+v", w.ExchangeName, data)
- }
- if w.RateLimit > 0 {
- time.Sleep(time.Duration(w.RateLimit) * time.Millisecond)
- }
- return w.Connection.WriteJSON(data)
-}
-
-// SendRawMessage sends a message over the connection without JSON encoding it
-func (w *WebsocketConnection) SendRawMessage(messageType int, message []byte) error {
- w.Lock()
- defer w.Unlock()
- if !w.IsConnected() {
- return fmt.Errorf("%v cannot send message to a disconnected websocket", w.ExchangeName)
- }
- if w.Verbose {
- log.Debugf(log.WebsocketMgr,
- "%v sending message to websocket %s", w.ExchangeName, message)
- }
- if w.RateLimit > 0 {
- time.Sleep(time.Duration(w.RateLimit) * time.Millisecond)
- }
- return w.Connection.WriteMessage(messageType, message)
-}
-
-// SetupPingHandler will automatically send ping or pong messages based on
-// WebsocketPingHandler configuration
-func (w *WebsocketConnection) SetupPingHandler(handler WebsocketPingHandler) {
- if handler.UseGorillaHandler {
- h := func(msg string) error {
- err := w.Connection.WriteControl(handler.MessageType, []byte(msg), time.Now().Add(handler.Delay))
- if err == websocket.ErrCloseSent {
- return nil
- } else if e, ok := err.(net.Error); ok && e.Temporary() {
- return nil
- }
- return err
- }
- w.Connection.SetPingHandler(h)
- return
- }
- w.Wg.Add(1)
- defer w.Wg.Done()
- go func() {
- ticker := time.NewTicker(handler.Delay)
- for {
- select {
- case <-w.Shutdown:
- ticker.Stop()
- return
- case <-ticker.C:
- err := w.SendRawMessage(handler.MessageType, handler.Message)
- if err != nil {
- log.Errorf(log.WebsocketMgr,
- "%v failed to send message to websocket %s", w.ExchangeName, handler.Message)
- return
- }
- }
- }
- }()
-}
-
-// SendMessageReturnResponse will send a WS message to the connection
-// It will then run a goroutine to await a JSON response
-// If there is no response it will return an error
-func (w *WebsocketConnection) SendMessageReturnResponse(id int64, request interface{}) ([]byte, error) {
- err := w.SendJSONMessage(request)
- if err != nil {
- return nil, err
- }
- w.SetResponseIDAndData(id, nil)
- var wg sync.WaitGroup
- wg.Add(1)
- go w.WaitForResult(id, &wg)
- defer func() {
- delete(w.IDResponses, id)
- }()
- wg.Wait()
- if _, ok := w.IDResponses[id]; !ok {
- return nil, fmt.Errorf("timeout waiting for response with ID %v", id)
- }
-
- return w.IDResponses[id], nil
-}
-
-// IsIDWaitingForResponse will verify whether the websocket is awaiting
-// a response with a correlating ID. If true, the datahandler won't process
-// the data, and instead will be processed by the wrapper function
-func (w *WebsocketConnection) IsIDWaitingForResponse(id int64) bool {
- w.Lock()
- defer w.Unlock()
- for k := range w.IDResponses {
- if k == id && w.IDResponses[k] == nil {
- return true
- }
- }
- return false
-}
-
-// WaitForResult will keep checking w.IDResponses for a response ID
-// If the timer expires, it will return without
-func (w *WebsocketConnection) WaitForResult(id int64, wg *sync.WaitGroup) {
- defer wg.Done()
- timer := time.NewTimer(w.ResponseMaxLimit)
- for {
- select {
- case <-timer.C:
- return
- default:
- w.Lock()
- for k := range w.IDResponses {
- if k == id && w.IDResponses[k] != nil {
- w.Unlock()
- if !timer.Stop() {
- select {
- case <-timer.C:
- default:
- }
- }
- return
- }
- }
- w.Unlock()
- time.Sleep(w.ResponseCheckTimeout)
- }
- }
-}
-
-func (w *WebsocketConnection) setConnectedStatus(b bool) {
- w.connectionMutex.Lock()
- w.connected = b
- w.connectionMutex.Unlock()
-}
-
-// IsConnected exposes websocket connection status
-func (w *WebsocketConnection) IsConnected() bool {
- w.connectionMutex.RLock()
- isConnected := w.connected
- w.connectionMutex.RUnlock()
- return isConnected
-}
-
-// ReadMessage reads messages, can handle text, gzip and binary
-func (w *WebsocketConnection) ReadMessage() (WebsocketResponse, error) {
- mType, resp, err := w.Connection.ReadMessage()
- if err != nil {
- if isDisconnectionError(err) {
- w.setConnectedStatus(false)
- }
- return WebsocketResponse{}, err
- }
- var standardMessage []byte
- switch mType {
- case websocket.TextMessage:
- standardMessage = resp
- case websocket.BinaryMessage:
- standardMessage, err = w.parseBinaryResponse(resp)
- if err != nil {
- return WebsocketResponse{}, err
- }
- }
- if w.Verbose {
- log.Debugf(log.WebsocketMgr, "%v Websocket message received: %v",
- w.ExchangeName,
- string(standardMessage))
- }
- return WebsocketResponse{Raw: standardMessage, Type: mType}, nil
-}
-
-// parseBinaryResponse parses a websocket binary response into a usable byte array
-func (w *WebsocketConnection) parseBinaryResponse(resp []byte) ([]byte, error) {
- var standardMessage []byte
- var err error
- // Detect GZIP
- if resp[0] == 31 && resp[1] == 139 {
- b := bytes.NewReader(resp)
- var gReader *gzip.Reader
- gReader, err = gzip.NewReader(b)
- if err != nil {
- return standardMessage, err
- }
- standardMessage, err = ioutil.ReadAll(gReader)
- if err != nil {
- return standardMessage, err
- }
- err = gReader.Close()
- if err != nil {
- return standardMessage, err
- }
- } else {
- reader := flate.NewReader(bytes.NewReader(resp))
- standardMessage, err = ioutil.ReadAll(reader)
- if err != nil {
- return standardMessage, err
- }
- err = reader.Close()
- if err != nil {
- return standardMessage, err
- }
- }
- return standardMessage, nil
-}
-
-// GenerateMessageID Creates a messageID to checkout
-func (w *WebsocketConnection) GenerateMessageID(useNano bool) int64 {
- if useNano {
- return time.Now().UnixNano()
- }
- return time.Now().Unix()
-}
-
-// isDisconnectionError Determines if the error sent over chan ReadMessageErrors is a disconnection error
-func isDisconnectionError(err error) bool {
- if websocket.IsUnexpectedCloseError(err) {
- return true
- }
- switch err.(type) {
- case *websocket.CloseError, *net.OpError:
- return true
- }
- return false
-}
diff --git a/exchanges/websocket/wshandler/wshandler_test.go b/exchanges/websocket/wshandler/wshandler_test.go
deleted file mode 100644
index d59c55e8..00000000
--- a/exchanges/websocket/wshandler/wshandler_test.go
+++ /dev/null
@@ -1,771 +0,0 @@
-package wshandler
-
-import (
- "bytes"
- "compress/flate"
- "compress/gzip"
- "encoding/json"
- "errors"
- "net"
- "net/http"
- "os"
- "strings"
- "sync"
- "testing"
- "time"
-
- "github.com/gorilla/websocket"
- "github.com/thrasher-corp/gocryptotrader/currency"
- "github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
-)
-
-func TestTrafficMonitorTimeout(t *testing.T) {
- ws := New()
- err := ws.Setup(
- &WebsocketSetup{
- Enabled: true,
- AuthenticatedWebsocketAPISupport: true,
- WebsocketTimeout: 10000,
- DefaultURL: "testDefaultURL",
- ExchangeName: "exchangeName",
- RunningURL: "testRunningURL",
- Connector: func() error { return nil },
- Subscriber: func(test WebsocketChannelSubscription) error { return nil },
- UnSubscriber: func(test WebsocketChannelSubscription) error { return nil },
- })
- if err != nil {
- t.Error(err)
- }
- ws.setConnectedStatus(true)
- ws.TrafficAlert = make(chan struct{}, 2)
- ws.ShutdownC = make(chan struct{})
- var anotherWG sync.WaitGroup
- anotherWG.Add(1)
- go ws.trafficMonitor(&anotherWG)
- anotherWG.Wait()
- ws.TrafficAlert <- struct{}{}
- trafficTimer := time.NewTimer(5 * time.Second)
- select {
- case <-trafficTimer.C:
- t.Error("should be exiting")
- default:
- ws.Wg.Wait()
- }
-}
-
-func TestIsDisconnectionError(t *testing.T) {
- isADisconnectionError := isDisconnectionError(errors.New("errorText"))
- if isADisconnectionError {
- t.Error("Its not")
- }
- isADisconnectionError = isDisconnectionError(&websocket.CloseError{
- Code: 1006,
- Text: "errorText",
- })
- if !isADisconnectionError {
- t.Error("It is")
- }
-
- isADisconnectionError = isDisconnectionError(&net.OpError{
- Op: "",
- Net: "",
- Source: nil,
- Addr: nil,
- Err: errors.New("errorText"),
- })
- if !isADisconnectionError {
- t.Error("It is")
- }
-}
-
-func TestConnectionMessageErrors(t *testing.T) {
- ws := New()
- ws.connected = true
- ws.enabled = true
- ws.ReadMessageErrors = make(chan error)
- ws.DataHandler = make(chan interface{})
- ws.ShutdownC = make(chan struct{})
- ws.connector = func() error { return nil }
- ws.features = &protocol.Features{}
- go ws.connectionMonitor()
- timer := time.NewTimer(900 * time.Millisecond)
- ws.ReadMessageErrors <- errors.New("errorText")
- select {
- case err := <-ws.DataHandler:
- if err.(error).Error() != "errorText" {
- t.Errorf("Expected 'errorText', received %v", err)
- }
- case <-timer.C:
- t.Error("Timeout waiting for datahandler to receive error")
- }
- timer = time.NewTimer(900 * time.Millisecond)
- ws.ReadMessageErrors <- &websocket.CloseError{
- Code: 1006,
- Text: "errorText",
- }
-outer:
- for {
- select {
- case <-ws.DataHandler:
- t.Fatal("Error is a disconnection error")
- case <-timer.C:
- break outer
- }
- }
-}
-
-func TestWebsocket(t *testing.T) {
- ws := Websocket{}
- ws.setInit(true)
- err := ws.Setup(&WebsocketSetup{
- ExchangeName: "test",
- Enabled: true,
- })
- if err != nil && err.Error() != "test Websocket already initialised" {
- t.Errorf("Expected 'test Websocket already initialised', received %v", err)
- }
-
- ws = *New()
- err = ws.SetProxyAddress("testProxy")
- if err != nil {
- t.Error("SetProxyAddress", err)
- }
-
- err = ws.Setup(
- &WebsocketSetup{
- Enabled: true,
- AuthenticatedWebsocketAPISupport: true,
- WebsocketTimeout: 2,
- DefaultURL: "testDefaultURL",
- ExchangeName: "exchangeName",
- RunningURL: "testRunningURL",
- Connector: func() error { return nil },
- Subscriber: func(test WebsocketChannelSubscription) error { return nil },
- UnSubscriber: func(test WebsocketChannelSubscription) error { return nil },
- Features: &protocol.Features{},
- })
- if err != nil {
- t.Error(err)
- }
-
- if ws.GetName() != "exchangeName" {
- t.Error("WebsocketSetup")
- }
-
- if !ws.IsEnabled() {
- t.Error("WebsocketSetup")
- }
-
- ws.setEnabled(false)
- if ws.IsEnabled() {
- t.Error("WebsocketSetup")
- }
-
- ws.setEnabled(true)
- if !ws.IsEnabled() {
- t.Error("WebsocketSetup")
- }
-
- if ws.GetProxyAddress() != "testProxy" {
- t.Error("WebsocketSetup")
- }
-
- if ws.GetDefaultURL() != "testDefaultURL" {
- t.Error("WebsocketSetup")
- }
-
- if ws.GetWebsocketURL() != "testRunningURL" {
- t.Error("WebsocketSetup")
- }
-
- if ws.trafficTimeout != time.Duration(2) {
- t.Error("WebsocketSetup")
- }
- // -- Not connected shutdown
- err = ws.Shutdown()
- if err == nil {
- t.Fatal("should not be connected to able to shut down")
- }
- ws.Wg.Wait()
- // -- Normal connect
- err = ws.Connect()
- if err != nil {
- t.Fatal("WebsocketSetup", err)
- }
- ws.SetWebsocketURL("ws://demos.kaazing.com/echo")
- // -- Already connected connect
- err = ws.Connect()
- if err == nil {
- t.Fatal("should not connect, already connected")
- }
- // -- Normal shutdown
- err = ws.Shutdown()
- if err != nil {
- t.Fatal("WebsocketSetup", err)
- }
- ws.Wg.Wait()
-}
-
-// placeholderSubscriber basic function to test subscriptions
-func placeholderSubscriber(channelToSubscribe WebsocketChannelSubscription) error {
- return nil
-}
-
-// TestSubscribe logic test
-func TestSubscribe(t *testing.T) {
- w := Websocket{
- channelsToSubscribe: []WebsocketChannelSubscription{
- {
- Channel: "hello",
- },
- },
- subscribedChannels: []WebsocketChannelSubscription{},
- }
- w.SetChannelSubscriber(placeholderSubscriber)
- err := w.appendSubscribedChannels()
- if err != nil {
- t.Error(err)
- }
- if len(w.subscribedChannels) != 1 {
- t.Errorf("Subscription did not occur")
- }
-}
-
-// TestSubscribe logic test
-func TestSubscribeToChannels(t *testing.T) {
- w := Websocket{
- channelsToSubscribe: []WebsocketChannelSubscription{
- {
- Channel: "hello",
- },
- },
- subscribedChannels: []WebsocketChannelSubscription{},
- }
- w.SetChannelSubscriber(placeholderSubscriber)
- w.SubscribeToChannels([]WebsocketChannelSubscription{{Channel: "hello"}, {Channel: "hello2"}})
- if len(w.channelsToSubscribe) != 2 {
- t.Errorf("Subscription did not occur")
- }
-}
-
-// TestUnsubscribe logic test
-func TestUnsubscribe(t *testing.T) {
- w := Websocket{
- channelsToSubscribe: []WebsocketChannelSubscription{},
- subscribedChannels: []WebsocketChannelSubscription{
- {
- Channel: "hello",
- },
- },
- }
- w.SetChannelUnsubscriber(placeholderSubscriber)
- err := w.unsubscribeToChannels()
- if err != nil {
- t.Error(err)
- }
- if len(w.subscribedChannels) != 0 {
- t.Errorf("Unsubscription did not occur")
- }
-}
-
-// TestSubscriptionWithExistingEntry logic test
-func TestSubscriptionWithExistingEntry(t *testing.T) {
- w := Websocket{
- channelsToSubscribe: []WebsocketChannelSubscription{
- {
- Channel: "hello",
- },
- },
- subscribedChannels: []WebsocketChannelSubscription{
- {
- Channel: "hello",
- },
- },
- }
- w.SetChannelSubscriber(placeholderSubscriber)
- err := w.appendSubscribedChannels()
- if err != nil {
- t.Error(err)
- }
- if len(w.subscribedChannels) != 1 {
- t.Errorf("Subscription should not have occurred")
- }
-}
-
-// TestUnsubscriptionWithExistingEntry logic test
-func TestUnsubscriptionWithExistingEntry(t *testing.T) {
- w := Websocket{
- channelsToSubscribe: []WebsocketChannelSubscription{
- {
- Channel: "hello",
- },
- },
- subscribedChannels: []WebsocketChannelSubscription{
- {
- Channel: "hello",
- },
- },
- }
- w.SetChannelUnsubscriber(placeholderSubscriber)
- err := w.unsubscribeToChannels()
- if err != nil {
- t.Error(err)
- }
- if len(w.subscribedChannels) != 1 {
- t.Errorf("Unsubscription should not have occurred")
- }
-}
-
-// TestManageSubscriptionsStartStop logic test
-func TestManageSubscriptionsStartStop(t *testing.T) {
- w := Websocket{
- ShutdownC: make(chan struct{}),
- features: &protocol.Features{Subscribe: true, Unsubscribe: true},
- }
- w.Wg.Add(1)
- go w.manageSubscriptions()
- close(w.ShutdownC)
- w.Wg.Wait()
-}
-
-// TestManageSubscriptions logic test
-func TestManageSubscriptions(t *testing.T) {
- w := Websocket{
- ShutdownC: make(chan struct{}),
- features: &protocol.Features{Subscribe: true, Unsubscribe: true},
- subscribedChannels: []WebsocketChannelSubscription{
- {
- Channel: "hello",
- },
- },
- }
- w.SetChannelUnsubscriber(placeholderSubscriber)
- w.SetChannelSubscriber(placeholderSubscriber)
- w.setConnectedStatus(true)
- go w.manageSubscriptions()
- time.Sleep(8 * time.Second)
- w.setConnectedStatus(false)
- time.Sleep(manageSubscriptionsDelay)
- w.subscriptionMutex.Lock()
- if len(w.subscribedChannels) > 0 {
- t.Error("Expected empty subscribed channels")
- }
- w.subscriptionMutex.Unlock()
-}
-
-// TestConnectionMonitorNoConnection logic test
-func TestConnectionMonitorNoConnection(t *testing.T) {
- ws := New()
- ws.DataHandler = make(chan interface{}, 1)
- ws.ShutdownC = make(chan struct{}, 1)
- ws.exchangeName = "hello"
- ws.trafficTimeout = 1
- go ws.connectionMonitor()
- if ws.IsConnectionMonitorRunning() {
- t.Fatal("Should have exited")
- }
-}
-
-// TestRemoveChannelToSubscribe logic test
-func TestRemoveChannelToSubscribe(t *testing.T) {
- subscription := WebsocketChannelSubscription{
- Channel: "hello",
- }
- w := Websocket{
- channelsToSubscribe: []WebsocketChannelSubscription{
- subscription,
- },
- }
- w.SetChannelUnsubscriber(placeholderSubscriber)
- w.removeChannelToSubscribe(subscription)
- if len(w.subscribedChannels) != 0 {
- t.Errorf("Unsubscription did not occur")
- }
-}
-
-// TestRemoveChannelToSubscribeWithNoSubscription logic test
-func TestRemoveChannelToSubscribeWithNoSubscription(t *testing.T) {
- subscription := WebsocketChannelSubscription{
- Channel: "hello",
- }
- w := Websocket{
- channelsToSubscribe: []WebsocketChannelSubscription{},
- }
- w.DataHandler = make(chan interface{}, 1)
- w.SetChannelUnsubscriber(placeholderSubscriber)
- go w.removeChannelToSubscribe(subscription)
- err := <-w.DataHandler
- if !strings.Contains(err.(error).Error(), "could not be removed because it was not found") {
- t.Error("Expected not found error")
- }
-}
-
-// TestResubscribeToChannel logic test
-func TestResubscribeToChannel(t *testing.T) {
- subscription := WebsocketChannelSubscription{
- Channel: "hello",
- }
- w := Websocket{
- channelsToSubscribe: []WebsocketChannelSubscription{},
- }
- w.DataHandler = make(chan interface{}, 1)
- w.SetChannelUnsubscriber(placeholderSubscriber)
- w.SetChannelSubscriber(placeholderSubscriber)
- w.ResubscribeToChannel(subscription)
-}
-
-// TestSliceCopyDoesntImpactBoth logic test
-func TestSliceCopyDoesntImpactBoth(t *testing.T) {
- w := Websocket{
- channelsToSubscribe: []WebsocketChannelSubscription{
- {
- Channel: "hello1",
- },
- {
- Channel: "hello2",
- },
- },
- subscribedChannels: []WebsocketChannelSubscription{
- {
- Channel: "hello3",
- },
- },
- }
- w.SetChannelUnsubscriber(placeholderSubscriber)
- err := w.unsubscribeToChannels()
- if err != nil {
- t.Error(err)
- }
- if len(w.subscribedChannels) != 2 {
- t.Errorf("Unsubscription did not occur")
- }
- w.subscribedChannels[0].Channel = "test"
- if strings.EqualFold(w.subscribedChannels[0].Channel, w.channelsToSubscribe[0].Channel) {
- t.Errorf("Slice has not been copied appropriately")
- }
-}
-
-// TestSliceCopyDoesntImpactBoth logic test
-func TestGetSubscriptions(t *testing.T) {
- w := Websocket{
- subscribedChannels: []WebsocketChannelSubscription{
- {
- Channel: "hello3",
- },
- },
- }
-
- subs := w.GetSubscriptions()
- subs[0].Channel = "noHELLO"
- if strings.EqualFold(w.subscribedChannels[0].Channel, subs[0].Channel) {
- t.Error("Subscriptions was not copied properly")
- }
-}
-
-// TestSetCanUseAuthenticatedEndpoints logic test
-func TestSetCanUseAuthenticatedEndpoints(t *testing.T) {
- ws := New()
- result := ws.CanUseAuthenticatedEndpoints()
- if result {
- t.Error("expected `canUseAuthenticatedEndpoints` to be false")
- }
- ws.SetCanUseAuthenticatedEndpoints(true)
- result = ws.CanUseAuthenticatedEndpoints()
- if !result {
- t.Error("expected `canUseAuthenticatedEndpoints` to be true")
- }
-}
-
-func TestRemoveSubscribedChannels(t *testing.T) {
- w := Websocket{
- channelsToSubscribe: []WebsocketChannelSubscription{
- {
- Channel: "hello3",
- },
- },
- }
-
- w.RemoveSubscribedChannels([]WebsocketChannelSubscription{{Channel: "hello3"}})
- if len(w.channelsToSubscribe) == 1 {
- t.Error("Did not remove subscription")
- }
-}
-
-const (
- websocketTestURL = "wss://www.bitmex.com/realtime"
- returnResponseURL = "wss://ws.kraken.com"
- useProxyTests = false // Disabled by default. Freely available proxy servers that work all the time are difficult to find
- proxyURL = "http://212.186.171.4:80" // Replace with a usable proxy server
-)
-
-var wc *WebsocketConnection
-var dialer websocket.Dialer
-
-type testStruct struct {
- Error error
- WC WebsocketConnection
-}
-
-type testRequest struct {
- Event string `json:"event"`
- RequestID int64 `json:"reqid,omitempty"`
- Pairs []string `json:"pair"`
- Subscription testRequestData `json:"subscription,omitempty"`
-}
-
-// testRequestData contains details on WS channel
-type testRequestData struct {
- Name string `json:"name,omitempty"`
- Interval int64 `json:"interval,omitempty"`
- Depth int64 `json:"depth,omitempty"`
-}
-
-type testResponse struct {
- RequestID int64 `json:"reqid,omitempty"`
-}
-
-// TestMain setup test
-func TestMain(m *testing.M) {
- wc = &WebsocketConnection{
- ExchangeName: "test",
- URL: returnResponseURL,
- ResponseMaxLimit: 7000000000,
- ResponseCheckTimeout: 30000000,
- }
- os.Exit(m.Run())
-}
-
-// TestDial logic test
-func TestDial(t *testing.T) {
- var testCases = []testStruct{
- {Error: nil, WC: WebsocketConnection{ExchangeName: "test1", Verbose: true, URL: websocketTestURL, RateLimit: 10, ResponseCheckTimeout: 30000000, ResponseMaxLimit: 7000000000}},
- {Error: errors.New(" Error: malformed ws or wss URL"), WC: WebsocketConnection{ExchangeName: "test2", Verbose: true, URL: "", ResponseCheckTimeout: 30000000, ResponseMaxLimit: 7000000000}},
- {Error: nil, WC: WebsocketConnection{ExchangeName: "test3", Verbose: true, URL: websocketTestURL, ProxyURL: proxyURL, ResponseCheckTimeout: 30000000, ResponseMaxLimit: 7000000000}},
- }
- for i := range testCases {
- testData := &testCases[i]
- t.Run(testData.WC.ExchangeName, func(t *testing.T) {
- if testData.WC.ProxyURL != "" && !useProxyTests {
- t.Skip("Proxy testing not enabled, skipping")
- }
- err := testData.WC.Dial(&dialer, http.Header{})
- if err != nil {
- if testData.Error != nil && err.Error() == testData.Error.Error() {
- return
- }
- t.Fatal(err)
- }
- })
- }
-}
-
-// TestSendMessage logic test
-func TestSendMessage(t *testing.T) {
- var testCases = []testStruct{
- {Error: nil, WC: WebsocketConnection{ExchangeName: "test1", Verbose: true, URL: websocketTestURL, RateLimit: 10, ResponseCheckTimeout: 30000000, ResponseMaxLimit: 7000000000}},
- {Error: errors.New(" Error: malformed ws or wss URL"), WC: WebsocketConnection{ExchangeName: "test2", Verbose: true, URL: "", ResponseCheckTimeout: 30000000, ResponseMaxLimit: 7000000000}},
- {Error: nil, WC: WebsocketConnection{ExchangeName: "test3", Verbose: true, URL: websocketTestURL, ProxyURL: proxyURL, ResponseCheckTimeout: 30000000, ResponseMaxLimit: 7000000000}},
- }
- for i := range testCases {
- testData := &testCases[i]
- t.Run(testData.WC.ExchangeName, func(t *testing.T) {
- if testData.WC.ProxyURL != "" && !useProxyTests {
- t.Skip("Proxy testing not enabled, skipping")
- }
- err := testData.WC.Dial(&dialer, http.Header{})
- if err != nil {
- if testData.Error != nil && err.Error() == testData.Error.Error() {
- return
- }
- t.Fatal(err)
- }
- err = testData.WC.SendJSONMessage(Ping)
- if err != nil {
- t.Error(err)
- }
- err = testData.WC.SendRawMessage(websocket.TextMessage, []byte(Ping))
- if err != nil {
- t.Error(err)
- }
- })
- }
-}
-
-// TestSendMessageWithResponse logic test
-func TestSendMessageWithResponse(t *testing.T) {
- if wc.ProxyURL != "" && !useProxyTests {
- t.Skip("Proxy testing not enabled, skipping")
- }
- err := wc.Dial(&dialer, http.Header{})
- if err != nil {
- t.Fatal(err)
- }
- go readMessages(wc, t)
-
- request := testRequest{
- Event: "subscribe",
- Pairs: []string{currency.NewPairWithDelimiter("XBT", "USD", "/").String()},
- Subscription: testRequestData{
- Name: "ticker",
- },
- RequestID: wc.GenerateMessageID(false),
- }
- _, err = wc.SendMessageReturnResponse(request.RequestID, request)
- if err != nil {
- t.Error(err)
- }
-}
-
-// TestSetupPingHandler logic test
-func TestSetupPingHandler(t *testing.T) {
- if wc.ProxyURL != "" && !useProxyTests {
- t.Skip("Proxy testing not enabled, skipping")
- }
- wc.Shutdown = make(chan struct{})
- err := wc.Dial(&dialer, http.Header{})
- if err != nil {
- t.Fatal(err)
- }
-
- wc.SetupPingHandler(WebsocketPingHandler{
- UseGorillaHandler: true,
- MessageType: websocket.PingMessage,
- Delay: 1000,
- })
-
- err = wc.Connection.Close()
- if err != nil {
- t.Error(err)
- }
-
- err = wc.Dial(&dialer, http.Header{})
- if err != nil {
- t.Fatal(err)
- }
- wc.SetupPingHandler(WebsocketPingHandler{
- MessageType: websocket.TextMessage,
- Message: []byte(Ping),
- Delay: 200,
- })
- time.Sleep(time.Millisecond * 500)
- close(wc.Shutdown)
- wc.Wg.Wait()
-}
-
-// TestParseBinaryResponse logic test
-func TestParseBinaryResponse(t *testing.T) {
- var b bytes.Buffer
- w := gzip.NewWriter(&b)
- _, err := w.Write([]byte("hello"))
- if err != nil {
- t.Error(err)
- }
- err = w.Close()
- if err != nil {
- t.Error(err)
- }
- var resp []byte
- resp, err = wc.parseBinaryResponse(b.Bytes())
- if err != nil {
- t.Error(err)
- }
- if !strings.EqualFold(string(resp), "hello") {
- t.Errorf("GZip conversion failed. Received: '%v', Expected: 'hello'", string(resp))
- }
-
- var b2 bytes.Buffer
- w2, err2 := flate.NewWriter(&b2, 1)
- if err2 != nil {
- t.Error(err2)
- }
- _, err2 = w2.Write([]byte("hello"))
- if err2 != nil {
- t.Error(err)
- }
- err2 = w2.Close()
- if err2 != nil {
- t.Error(err)
- }
- resp2, err3 := wc.parseBinaryResponse(b2.Bytes())
- if err3 != nil {
- t.Error(err3)
- }
- if !strings.EqualFold(string(resp2), "hello") {
- t.Errorf("GZip conversion failed. Received: '%v', Expected: 'hello'", string(resp2))
- }
-}
-
-// TestSetResponseIDAndData logic test
-func TestSetResponseIDAndData(t *testing.T) {
- wc.IDResponses = nil
- wc.SetResponseIDAndData(0, nil)
- wc.SetResponseIDAndData(1, []byte("hi"))
- if len(wc.IDResponses) != 2 {
- t.Error("Expected 2 entries")
- }
-}
-
-// TestIsIDWaitingForResponse logic test
-func TestIsIDWaitingForResponse(t *testing.T) {
- wc.IDResponses = nil
- wc.SetResponseIDAndData(0, nil)
- wc.SetResponseIDAndData(1, []byte("hi"))
- if len(wc.IDResponses) != 2 {
- t.Error("Expected 2 entries")
- }
- if !wc.IsIDWaitingForResponse(0) {
- t.Error("Expected true")
- }
- if wc.IsIDWaitingForResponse(2) {
- t.Error("Expected false")
- }
- if wc.IsIDWaitingForResponse(1337) {
- t.Error("Expected false")
- }
-}
-
-// readMessages helper func
-func readMessages(wc *WebsocketConnection, t *testing.T) {
- timer := time.NewTimer(20 * time.Second)
- for {
- select {
- case <-timer.C:
- return
- default:
- resp, err := wc.ReadMessage()
- if err != nil {
- t.Error(err)
- return
- }
- var incoming testResponse
- err = json.Unmarshal(resp.Raw, &incoming)
- if err != nil {
- t.Error(err)
- return
- }
- if incoming.RequestID > 0 {
- wc.SetResponseIDAndData(incoming.RequestID, resp.Raw)
- return
- }
- }
- }
-}
-
-// TestCanUseAuthenticatedWebsocketForWrapper logic test
-func TestCanUseAuthenticatedWebsocketForWrapper(t *testing.T) {
- ws := &Websocket{}
- resp := ws.CanUseAuthenticatedWebsocketForWrapper()
- if resp {
- t.Error("Expected false, `connected` is false")
- }
- ws.setConnectedStatus(true)
- resp = ws.CanUseAuthenticatedWebsocketForWrapper()
- if resp {
- t.Error("Expected false, `connected` is true and `CanUseAuthenticatedEndpoints` is false")
- }
- ws.canUseAuthenticatedEndpoints = true
- resp = ws.CanUseAuthenticatedWebsocketForWrapper()
- if !resp {
- t.Error("Expected true, `connected` and `CanUseAuthenticatedEndpoints` is true")
- }
-}
diff --git a/exchanges/websocket/wshandler/wshandler_types.go b/exchanges/websocket/wshandler/wshandler_types.go
deleted file mode 100644
index b9180413..00000000
--- a/exchanges/websocket/wshandler/wshandler_types.go
+++ /dev/null
@@ -1,183 +0,0 @@
-package wshandler
-
-import (
- "sync"
- "time"
-
- "github.com/gorilla/websocket"
- "github.com/thrasher-corp/gocryptotrader/currency"
- "github.com/thrasher-corp/gocryptotrader/exchanges/asset"
- "github.com/thrasher-corp/gocryptotrader/exchanges/order"
- "github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wsorderbook"
-)
-
-// Websocket functionality list and state consts
-const (
- // WebsocketNotEnabled alerts of a disabled websocket
- WebsocketNotEnabled = "exchange_websocket_not_enabled"
- manageSubscriptionsDelay = 5 * time.Second
- // connection monitor time delays and limits
- connectionMonitorDelay = 2 * time.Second
- WebsocketNotAuthenticatedUsingRest = "%v - Websocket not authenticated, using REST"
- Ping = "ping"
- Pong = "pong"
- UnhandledMessage = " - Unhandled websocket message: "
-)
-
-// Websocket defines a return type for websocket connections via the interface
-// wrapper for routine processing in routines.go
-type Websocket struct {
- canUseAuthenticatedEndpoints bool
- enabled bool
- init bool
- connected bool
- connecting bool
- trafficMonitorRunning bool
- verbose bool
- connectionMonitorRunning bool
- trafficTimeout time.Duration
- proxyAddr string
- defaultURL string
- runningURL string
- exchangeName string
- m sync.Mutex
- subscriptionMutex sync.Mutex
- connectionMutex sync.RWMutex
- connector func() error
- subscribedChannels []WebsocketChannelSubscription
- channelsToSubscribe []WebsocketChannelSubscription
- channelSubscriber func(channelToSubscribe WebsocketChannelSubscription) error
- channelUnsubscriber func(channelToUnsubscribe WebsocketChannelSubscription) error
- DataHandler chan interface{}
- // ShutdownC is the main shutdown channel which controls all websocket go funcs
- ShutdownC chan struct{}
- // Orderbook is a local cache of orderbooks
- Orderbook wsorderbook.WebsocketOrderbookLocal
- // Wg defines a wait group for websocket routines for cleanly shutting down
- // routines
- Wg sync.WaitGroup
- // TrafficAlert monitors if there is a halt in traffic throughput
- TrafficAlert chan struct{}
- // ReadMessageErrors will received all errors from ws.ReadMessage() and verify if its a disconnection
- ReadMessageErrors chan error
- features *protocol.Features
-}
-
-// WebsocketSetup defines variables for setting up a websocket connection
-type WebsocketSetup struct {
- Enabled bool
- Verbose bool
- AuthenticatedWebsocketAPISupport bool
- WebsocketTimeout time.Duration
- DefaultURL string
- ExchangeName string
- RunningURL string
- Connector func() error
- Subscriber func(channelToSubscribe WebsocketChannelSubscription) error
- UnSubscriber func(channelToUnsubscribe WebsocketChannelSubscription) error
- Features *protocol.Features
-}
-
-// WebsocketChannelSubscription container for websocket subscriptions
-// Currently only a one at a time thing to avoid complexity
-type WebsocketChannelSubscription struct {
- Channel string
- Currency currency.Pair
- Params map[string]interface{}
-}
-
-// WebsocketResponse defines generalised data from the websocket connection
-type WebsocketResponse struct {
- Type int
- Raw []byte
-}
-
-// WebsocketOrderbookUpdate defines a websocket event in which the orderbook
-// has been updated in the orderbook package
-type WebsocketOrderbookUpdate struct {
- Pair currency.Pair
- Asset asset.Item
- Exchange string
-}
-
-// TradeData defines trade data
-type TradeData struct {
- Timestamp time.Time
- CurrencyPair currency.Pair
- AssetType asset.Item
- Exchange string
- EventType order.Type
- Price float64
- Amount float64
- Side order.Side
-}
-
-// FundingData defines funding data
-type FundingData struct {
- Timestamp time.Time
- CurrencyPair currency.Pair
- AssetType asset.Item
- Exchange string
- Amount float64
- Rate float64
- Period int64
- Side order.Side
-}
-
-// KlineData defines kline feed
-type KlineData struct {
- Timestamp time.Time
- Pair currency.Pair
- AssetType asset.Item
- Exchange string
- StartTime time.Time
- CloseTime time.Time
- Interval string
- OpenPrice float64
- ClosePrice float64
- HighPrice float64
- LowPrice float64
- Volume float64
-}
-
-// WebsocketPositionUpdated reflects a change in orders/contracts on an exchange
-type WebsocketPositionUpdated struct {
- Timestamp time.Time
- Pair currency.Pair
- AssetType asset.Item
- Exchange string
-}
-
-// WebsocketConnection contains all the data needed to send a message to a WS
-type WebsocketConnection struct {
- sync.Mutex
- Verbose bool
- connected bool
- connectionMutex sync.RWMutex
- RateLimit float64
- ExchangeName string
- URL string
- ProxyURL string
- Wg sync.WaitGroup
- Connection *websocket.Conn
- Shutdown chan struct{}
- // These are the request IDs and the corresponding response JSON
- IDResponses map[int64][]byte
- ResponseCheckTimeout time.Duration
- ResponseMaxLimit time.Duration
- TrafficTimeout time.Duration
-}
-
-// WebsocketPingHandler container for ping handler settings
-type WebsocketPingHandler struct {
- UseGorillaHandler bool
- MessageType int
- Message []byte
- Delay time.Duration
-}
-
-// UnhandledMessageWarning is used for unhandled websocket messages
-type UnhandledMessageWarning struct {
- Message string
-}
diff --git a/exchanges/yobit/yobit_wrapper.go b/exchanges/yobit/yobit_wrapper.go
index 76a91a47..354644f3 100644
--- a/exchanges/yobit/yobit_wrapper.go
+++ b/exchanges/yobit/yobit_wrapper.go
@@ -20,7 +20,6 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -56,20 +55,11 @@ func (y *Yobit) SetDefaults() {
y.API.CredentialsValidator.RequiresKey = true
y.API.CredentialsValidator.RequiresSecret = true
- y.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- },
- UseGlobalFormat: true,
- RequestFormat: ¤cy.PairFormat{
- Delimiter: "_",
- Uppercase: false,
- Separator: "-",
- },
- ConfigFormat: ¤cy.PairFormat{
- Delimiter: "_",
- Uppercase: true,
- },
+ requestFmt := ¤cy.PairFormat{Delimiter: currency.UnderscoreDelimiter, Separator: currency.DashDelimiter}
+ configFmt := ¤cy.PairFormat{Delimiter: currency.UnderscoreDelimiter, Uppercase: true}
+ err := y.SetGlobalPairsManager(requestFmt, configFmt, asset.Spot)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
}
y.Features = exchange.Features{
@@ -119,7 +109,6 @@ func (y *Yobit) Setup(exch *config.ExchangeConfig) error {
y.SetEnabled(false)
return nil
}
-
return y.SetupDefaults(exch)
}
@@ -173,13 +162,19 @@ func (y *Yobit) UpdateTradablePairs(forceUpdate bool) error {
if err != nil {
return err
}
-
- return y.UpdatePairs(currency.NewPairsFromStrings(pairs), asset.Spot, false, forceUpdate)
+ p, err := currency.NewPairsFromStrings(pairs)
+ if err != nil {
+ return err
+ }
+ return y.UpdatePairs(p, asset.Spot, false, forceUpdate)
}
// UpdateTicker updates and returns the ticker for a currency pair
func (y *Yobit) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
- enabledPairs := y.GetEnabledPairs(assetType)
+ enabledPairs, err := y.GetEnabledPairs(assetType)
+ if err != nil {
+ return nil, err
+ }
pairsCollated, err := y.FormatExchangeCurrencies(enabledPairs, assetType)
if err != nil {
return nil, err
@@ -191,24 +186,29 @@ func (y *Yobit) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Pri
}
for i := range enabledPairs {
- curr := y.FormatExchangeCurrency(enabledPairs[i], assetType).Lower().String()
+ fpair, err := y.FormatExchangeCurrency(enabledPairs[i], assetType)
+ if err != nil {
+ return nil, err
+ }
+ curr := fpair.Lower().String()
if _, ok := result[curr]; !ok {
continue
}
- resultCurr := result[curr]
- tickerPrice := new(ticker.Price)
- tickerPrice.Pair = enabledPairs[i]
- tickerPrice.Last = resultCurr.Last
- tickerPrice.Ask = resultCurr.Sell
- tickerPrice.Bid = resultCurr.Buy
- tickerPrice.Last = resultCurr.Last
- tickerPrice.Low = resultCurr.Low
- tickerPrice.QuoteVolume = resultCurr.VolumeCurrent
- tickerPrice.Volume = resultCurr.Vol
- err = ticker.ProcessTicker(y.Name, tickerPrice, assetType)
+ resultCurr := result[curr]
+ err = ticker.ProcessTicker(&ticker.Price{
+ Pair: enabledPairs[i],
+ Last: resultCurr.Last,
+ Ask: resultCurr.Sell,
+ Bid: resultCurr.Buy,
+ Low: resultCurr.Low,
+ QuoteVolume: resultCurr.VolumeCurrent,
+ Volume: resultCurr.Vol,
+ ExchangeName: y.Name,
+ AssetType: assetType,
+ })
if err != nil {
- log.Error(log.Ticker, err)
+ return nil, err
}
}
return ticker.GetTicker(y.Name, p, assetType)
@@ -235,7 +235,11 @@ func (y *Yobit) FetchOrderbook(p currency.Pair, assetType asset.Item) (*orderboo
// UpdateOrderbook updates and returns the orderbook for a currency pair
func (y *Yobit) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
orderBook := new(orderbook.Base)
- orderbookNew, err := y.GetDepth(y.FormatExchangeCurrency(p, assetType).String())
+ fpair, err := y.FormatExchangeCurrency(p, assetType)
+ if err != nil {
+ return nil, err
+ }
+ orderbookNew, err := y.GetDepth(fpair.String())
if err != nil {
return orderBook, err
}
@@ -376,10 +380,16 @@ func (y *Yobit) CancelAllOrders(_ *order.Cancel) (order.CancelAllResponse, error
}
var allActiveOrders []map[string]ActiveOrders
- enabledPairs := y.GetEnabledPairs(asset.Spot)
+ enabledPairs, err := y.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return cancelAllOrdersResponse, err
+ }
for i := range enabledPairs {
- fCurr := y.FormatExchangeCurrency(enabledPairs[i], asset.Spot).String()
- activeOrdersForPair, err := y.GetOpenOrders(fCurr)
+ fCurr, err := y.FormatExchangeCurrency(enabledPairs[i], asset.Spot)
+ if err != nil {
+ return cancelAllOrdersResponse, err
+ }
+ activeOrdersForPair, err := y.GetOpenOrders(fCurr.String())
if err != nil {
return cancelAllOrdersResponse, err
}
@@ -446,11 +456,6 @@ func (y *Yobit) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdraw.R
return nil, common.ErrFunctionNotSupported
}
-// GetWebsocket returns a pointer to the exchange websocket
-func (y *Yobit) GetWebsocket() (*wshandler.Websocket, error) {
- return nil, common.ErrFunctionNotSupported
-}
-
// GetFeeByType returns an estimate of fee based on type of transaction
func (y *Yobit) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if !y.AllowAuthenticatedRequest() && // Todo check connection status
@@ -463,16 +468,28 @@ func (y *Yobit) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
// GetActiveOrders retrieves any orders that are active/open
func (y *Yobit) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) {
var orders []order.Detail
+
+ format, err := y.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return nil, err
+ }
+
for x := range req.Pairs {
- fCurr := y.FormatExchangeCurrency(req.Pairs[x], asset.Spot).String()
- resp, err := y.GetOpenOrders(fCurr)
+ fCurr, err := y.FormatExchangeCurrency(req.Pairs[x], asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+ resp, err := y.GetOpenOrders(fCurr.String())
if err != nil {
return nil, err
}
for id := range resp {
- symbol := currency.NewPairDelimiter(resp[id].Pair,
- y.GetPairFormat(asset.Spot, false).Delimiter)
+ var symbol currency.Pair
+ symbol, err = currency.NewPairDelimiter(resp[id].Pair, format.Delimiter)
+ if err != nil {
+ return nil, err
+ }
orderDate := time.Unix(int64(resp[id].TimestampCreated), 0)
side := order.Side(strings.ToUpper(resp[id].Type))
orders = append(orders, order.Detail{
@@ -497,13 +514,17 @@ func (y *Yobit) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, er
func (y *Yobit) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error) {
var allOrders []TradeHistory
for x := range req.Pairs {
+ fpair, err := y.FormatExchangeCurrency(req.Pairs[x], asset.Spot)
+ if err != nil {
+ return nil, err
+ }
resp, err := y.GetTradeHistory(0,
10000,
math.MaxInt64,
req.StartTicks.Unix(),
req.EndTicks.Unix(),
"DESC",
- y.FormatExchangeCurrency(req.Pairs[x], asset.Spot).String())
+ fpair.String())
if err != nil {
return nil, err
}
@@ -513,10 +534,18 @@ func (y *Yobit) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, er
}
}
+ format, err := y.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return nil, err
+ }
+
var orders []order.Detail
for i := range allOrders {
- symbol := currency.NewPairDelimiter(allOrders[i].Pair,
- y.GetPairFormat(asset.Spot, false).Delimiter)
+ var symbol currency.Pair
+ symbol, err = currency.NewPairDelimiter(allOrders[i].Pair, format.Delimiter)
+ if err != nil {
+ return nil, err
+ }
orderDate := time.Unix(int64(allOrders[i].Timestamp), 0)
side := order.Side(strings.ToUpper(allOrders[i].Type))
orders = append(orders, order.Detail{
@@ -535,28 +564,6 @@ func (y *Yobit) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, er
return orders, nil
}
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func (y *Yobit) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- return common.ErrFunctionNotSupported
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func (y *Yobit) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- return common.ErrFunctionNotSupported
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func (y *Yobit) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return nil, common.ErrFunctionNotSupported
-}
-
-// AuthenticateWebsocket sends an authentication message to the websocket
-func (y *Yobit) AuthenticateWebsocket() error {
- return common.ErrFunctionNotSupported
-}
-
// ValidateCredentials validates current credentials used for wrapper
// functionality
func (y *Yobit) ValidateCredentials() error {
diff --git a/exchanges/zb/zb.go b/exchanges/zb/zb.go
index e4a7080d..55cc7ede 100644
--- a/exchanges/zb/zb.go
+++ b/exchanges/zb/zb.go
@@ -16,7 +16,6 @@ import (
"github.com/thrasher-corp/gocryptotrader/currency"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
)
const (
@@ -42,7 +41,6 @@ const (
// 47.91.169.147 api.zb.com
// 47.52.55.212 trade.zb.com
type ZB struct {
- WebsocketConn *wshandler.WebsocketConnection
exchange.Base
}
diff --git a/exchanges/zb/zb_test.go b/exchanges/zb/zb_test.go
index d7ad8c46..e0667bc6 100644
--- a/exchanges/zb/zb_test.go
+++ b/exchanges/zb/zb_test.go
@@ -20,7 +20,7 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/kline"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -49,12 +49,11 @@ func TestMain(m *testing.M) {
zbConfig.API.AuthenticatedWebsocketSupport = true
zbConfig.API.Credentials.Key = apiKey
zbConfig.API.Credentials.Secret = apiSecret
+ z.Websocket = sharedtestvalues.NewTestWebsocket()
err = z.Setup(zbConfig)
if err != nil {
log.Fatal("ZB setup error", err)
}
- z.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
- z.Websocket.TrafficAlert = sharedtestvalues.GetWebsocketStructChannelOverride()
os.Exit(m.Run())
}
@@ -63,22 +62,13 @@ func setupWsAuth(t *testing.T) {
return
}
if !z.Websocket.IsEnabled() && !z.API.AuthenticatedWebsocketSupport || !z.ValidateAPICredentials() || !canManipulateRealOrders {
- t.Skip(wshandler.WebsocketNotEnabled)
- }
- z.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: z.Name,
- URL: zbWebsocketAPI,
- Verbose: z.Verbose,
- ResponseMaxLimit: exchange.DefaultWebsocketResponseMaxLimit,
- ResponseCheckTimeout: exchange.DefaultWebsocketResponseCheckTimeout,
+ t.Skip(stream.WebsocketNotEnabled)
}
var dialer websocket.Dialer
- err := z.WebsocketConn.Dial(&dialer, http.Header{})
+ err := z.Websocket.Conn.Dial(&dialer, http.Header{})
if err != nil {
t.Fatal(err)
}
- z.Websocket.DataHandler = make(chan interface{}, 11)
- z.Websocket.TrafficAlert = make(chan struct{}, 11)
go z.wsReadData()
wsSetupRan = true
}
@@ -841,9 +831,12 @@ func TestWsCreateSubUserResponse(t *testing.T) {
}
func TestGetHistoricCandles(t *testing.T) {
- currencyPair := currency.NewPairFromString("btc_usdt")
+ currencyPair, err := currency.NewPairFromString("btc_usdt")
+ if err != nil {
+ t.Fatal(err)
+ }
startTime := time.Now().Add(-time.Hour * 1)
- _, err := z.GetHistoricCandles(currencyPair, asset.Spot, startTime, time.Now(), kline.OneHour)
+ _, err = z.GetHistoricCandles(currencyPair, asset.Spot, startTime, time.Now(), kline.OneHour)
if err != nil {
t.Fatal(err)
}
@@ -855,10 +848,13 @@ func TestGetHistoricCandles(t *testing.T) {
}
func TestGetHistoricCandlesExtended(t *testing.T) {
- currencyPair := currency.NewPairFromString("btc_usdt")
+ currencyPair, err := currency.NewPairFromString("btc_usdt")
+ if err != nil {
+ t.Fatal(err)
+ }
start := time.Now().AddDate(0, -2, 0)
end := time.Now()
- _, err := z.GetHistoricCandlesExtended(currencyPair, asset.Spot, start, end, kline.OneHour)
+ _, err = z.GetHistoricCandlesExtended(currencyPair, asset.Spot, start, end, kline.OneHour)
if err != nil {
t.Fatal(err)
}
diff --git a/exchanges/zb/zb_websocket.go b/exchanges/zb/zb_websocket.go
index 8ad8fb45..bc453faf 100644
--- a/exchanges/zb/zb_websocket.go
+++ b/exchanges/zb/zb_websocket.go
@@ -11,14 +11,15 @@ import (
"time"
"github.com/gorilla/websocket"
+ "github.com/thrasher-corp/gocryptotrader/common"
"github.com/thrasher-corp/gocryptotrader/common/crypto"
"github.com/thrasher-corp/gocryptotrader/currency"
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/order"
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
)
@@ -31,43 +32,36 @@ const (
// WsConnect initiates a websocket connection
func (z *ZB) WsConnect() error {
if !z.Websocket.IsEnabled() || !z.IsEnabled() {
- return errors.New(wshandler.WebsocketNotEnabled)
+ return errors.New(stream.WebsocketNotEnabled)
}
var dialer websocket.Dialer
- err := z.WebsocketConn.Dial(&dialer, http.Header{})
+ err := z.Websocket.Conn.Dial(&dialer, http.Header{})
if err != nil {
return err
}
+ subs, err := z.GenerateDefaultSubscriptions()
+ if err != nil {
+ return err
+ }
go z.wsReadData()
- z.GenerateDefaultSubscriptions()
-
- return nil
+ return z.Websocket.SubscribeToChannels(subs)
}
// wsReadData handles all the websocket data coming from the websocket
// connection
func (z *ZB) wsReadData() {
z.Websocket.Wg.Add(1)
- defer func() {
- z.Websocket.Wg.Done()
- }()
+ defer z.Websocket.Wg.Done()
for {
- select {
- case <-z.Websocket.ShutdownC:
+ resp := z.Websocket.Conn.ReadMessage()
+ if resp.Raw == nil {
return
- default:
- resp, err := z.WebsocketConn.ReadMessage()
- if err != nil {
- z.Websocket.ReadMessageErrors <- err
- return
- }
- z.Websocket.TrafficAlert <- struct{}{}
- err = z.wsHandleData(resp.Raw)
- if err != nil {
- z.Websocket.DataHandler <- err
- }
+ }
+ err := z.wsHandleData(resp.Raw)
+ if err != nil {
+ z.Websocket.DataHandler <- err
}
}
}
@@ -80,14 +74,17 @@ func (z *ZB) wsHandleData(respRaw []byte) error {
return err
}
if result.No > 0 {
- if z.WebsocketConn.IsIDWaitingForResponse(result.No) {
- z.WebsocketConn.SetResponseIDAndData(result.No, fixedJSON)
+ if z.Websocket.Match.IncomingWithData(result.No, fixedJSON) {
return nil
}
}
if result.Code > 0 && result.Code != 1000 {
- return fmt.Errorf("%v request failed, message: %v, error code: %v", z.Name, result.Message, wsErrCodes[result.Code])
+ return fmt.Errorf("%v request failed, message: %v, error code: %v",
+ z.Name,
+ result.Message,
+ wsErrCodes[result.Code])
}
+
switch {
case strings.Contains(result.Channel, "markets"):
var markets Markets
@@ -95,7 +92,6 @@ func (z *ZB) wsHandleData(respRaw []byte) error {
if err != nil {
return err
}
-
case strings.Contains(result.Channel, "ticker"):
cPair := strings.Split(result.Channel, "_")
var wsTicker WsTicker
@@ -104,6 +100,11 @@ func (z *ZB) wsHandleData(respRaw []byte) error {
return err
}
+ p, err := currency.NewPairFromString(cPair[0])
+ if err != nil {
+ return err
+ }
+
z.Websocket.DataHandler <- &ticker.Price{
ExchangeName: z.Name,
Close: wsTicker.Data.Last,
@@ -115,9 +116,8 @@ func (z *ZB) wsHandleData(respRaw []byte) error {
Ask: wsTicker.Data.Sell,
LastUpdated: time.Unix(0, wsTicker.Date*int64(time.Millisecond)),
AssetType: asset.Spot,
- Pair: currency.NewPairFromString(cPair[0]),
+ Pair: p,
}
-
case strings.Contains(result.Channel, "depth"):
var depth WsDepth
err := json.Unmarshal(fixedJSON, &depth)
@@ -142,7 +142,11 @@ func (z *ZB) wsHandleData(respRaw []byte) error {
}
channelInfo := strings.Split(result.Channel, "_")
- cPair := currency.NewPairFromString(channelInfo[0])
+ cPair, err := currency.NewPairFromString(channelInfo[0])
+ if err != nil {
+ return err
+ }
+
var newOrderBook orderbook.Base
newOrderBook.Asks = asks
newOrderBook.Bids = bids
@@ -154,12 +158,6 @@ func (z *ZB) wsHandleData(respRaw []byte) error {
if err != nil {
return err
}
-
- z.Websocket.DataHandler <- wshandler.WebsocketOrderbookUpdate{
- Pair: cPair,
- Asset: asset.Spot,
- Exchange: z.Name,
- }
case strings.Contains(result.Channel, "_order"):
cPair := strings.Split(result.Channel, "_")
var o WsSubmitOrderResponse
@@ -168,9 +166,17 @@ func (z *ZB) wsHandleData(respRaw []byte) error {
return err
}
if !o.Success {
- return fmt.Errorf("%s - Order %v failed to be placed. %s", z.Name, o.Data.EntrustID, respRaw)
+ return fmt.Errorf("%s - Order %v failed to be placed. %s",
+ z.Name,
+ o.Data.EntrustID,
+ respRaw)
}
- p := currency.NewPairFromString(cPair[0])
+
+ p, err := currency.NewPairFromString(cPair[0])
+ if err != nil {
+ return err
+ }
+
var a asset.Item
a, err = z.GetPairAssetType(p)
if err != nil {
@@ -190,12 +196,21 @@ func (z *ZB) wsHandleData(respRaw []byte) error {
return err
}
if !o.Success {
- return fmt.Errorf("%s - Order %v failed to be cancelled. %s", z.Name, o.Data.EntrustID, respRaw)
+ return fmt.Errorf("%s - Order %v failed to be cancelled. %s",
+ z.Name,
+ o.Data.EntrustID,
+ respRaw)
}
+
+ p, err := currency.NewPairFromString(cPair[0])
+ if err != nil {
+ return err
+ }
+
z.Websocket.DataHandler <- &order.Modify{
Exchange: z.Name,
ID: strconv.FormatInt(o.Data.EntrustID, 10),
- Pair: currency.NewPairFromString(cPair[0]),
+ Pair: p,
Status: order.Cancelled,
}
case strings.Contains(result.Channel, "trades"):
@@ -204,65 +219,86 @@ func (z *ZB) wsHandleData(respRaw []byte) error {
if err != nil {
return err
}
- // Most up to date trade
- if len(trades.Data) == 0 {
- return errors.New(z.Name + " - Empty websocket trade data received: " + string(fixedJSON))
- }
- t := trades.Data[len(trades.Data)-1]
- channelInfo := strings.Split(result.Channel, "_")
- cPair := currency.NewPairFromString(channelInfo[0])
- tSide, err := order.StringToOrderSide(t.TradeType)
- if err != nil {
- z.Websocket.DataHandler <- order.ClassificationError{
- Exchange: z.Name,
- Err: err,
+ for i := range trades.Data {
+ channelInfo := strings.Split(result.Channel, "_")
+ cPair, err := currency.NewPairFromString(channelInfo[0])
+ if err != nil {
+ return err
+ }
+
+ tSide, err := order.StringToOrderSide(trades.Data[i].TradeType)
+ if err != nil {
+ z.Websocket.DataHandler <- order.ClassificationError{
+ Exchange: z.Name,
+ Err: err,
+ }
+ }
+
+ z.Websocket.DataHandler <- stream.TradeData{
+ Timestamp: time.Unix(trades.Data[i].Date, 0),
+ CurrencyPair: cPair,
+ AssetType: asset.Spot,
+ Exchange: z.Name,
+ Price: trades.Data[i].Price,
+ Amount: trades.Data[i].Amount,
+ Side: tSide,
}
}
- z.Websocket.DataHandler <- wshandler.TradeData{
- Timestamp: time.Unix(t.Date, 0),
- CurrencyPair: cPair,
- AssetType: asset.Spot,
- Exchange: z.Name,
- Price: t.Price,
- Amount: t.Amount,
- Side: tSide,
- }
default:
- z.Websocket.DataHandler <- wshandler.UnhandledMessageWarning{Message: z.Name + wshandler.UnhandledMessage + string(respRaw)}
- return nil
+ z.Websocket.DataHandler <- stream.UnhandledMessageWarning{
+ Message: z.Name +
+ stream.UnhandledMessage +
+ string(respRaw)}
}
return nil
}
// GenerateDefaultSubscriptions Adds default subscriptions to websocket to be handled by ManageSubscriptions()
-func (z *ZB) GenerateDefaultSubscriptions() {
- var subscriptions []wshandler.WebsocketChannelSubscription
- // Tickerdata is its own channel
- subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
+func (z *ZB) GenerateDefaultSubscriptions() ([]stream.ChannelSubscription, error) {
+ var subscriptions []stream.ChannelSubscription
+ // market configuration is its own channel
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
Channel: "markets",
})
channels := []string{"%s_ticker", "%s_depth", "%s_trades"}
- enabledCurrencies := z.GetEnabledPairs(asset.Spot)
+ enabledCurrencies, err := z.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+
for i := range channels {
for j := range enabledCurrencies {
enabledCurrencies[j].Delimiter = ""
- subscriptions = append(subscriptions, wshandler.WebsocketChannelSubscription{
+ subscriptions = append(subscriptions, stream.ChannelSubscription{
Channel: fmt.Sprintf(channels[i], enabledCurrencies[j].Lower().String()),
Currency: enabledCurrencies[j].Lower(),
+ Asset: asset.Spot,
})
}
}
- z.Websocket.SubscribeToChannels(subscriptions)
+ return subscriptions, nil
}
// Subscribe sends a websocket message to receive data from the channel
-func (z *ZB) Subscribe(channelToSubscribe wshandler.WebsocketChannelSubscription) error {
- subscriptionRequest := Subscription{
- Event: zWebsocketAddChannel,
- Channel: channelToSubscribe.Channel,
+func (z *ZB) Subscribe(channelsToSubscribe []stream.ChannelSubscription) error {
+ var errs common.Errors
+ for i := range channelsToSubscribe {
+ subscriptionRequest := Subscription{
+ Event: zWebsocketAddChannel,
+ Channel: channelsToSubscribe[i].Channel,
+ }
+ err := z.Websocket.Conn.SendJSONMessage(subscriptionRequest)
+ if err != nil {
+ errs = append(errs, err)
+ continue
+ }
+ z.Websocket.AddSuccessfulSubscriptions(channelsToSubscribe[i])
}
- return z.WebsocketConn.SendJSONMessage(subscriptionRequest)
+ if errs != nil {
+ return errs
+ }
+ return nil
}
func (z *ZB) wsGenerateSignature(request interface{}) string {
@@ -303,9 +339,9 @@ func (z *ZB) wsAddSubUser(username, password string) (*WsGetSubUserListResponse,
request.Channel = "addSubUser"
request.Event = zWebsocketAddChannel
request.Accesskey = z.API.Credentials.Key
- request.No = z.WebsocketConn.GenerateMessageID(true)
+ request.No = z.Websocket.Conn.GenerateMessageID(true)
request.Sign = z.wsGenerateSignature(request)
- resp, err := z.WebsocketConn.SendMessageReturnResponse(request.No, request)
+ resp, err := z.Websocket.Conn.SendMessageReturnResponse(request.No, request)
if err != nil {
return nil, err
}
@@ -315,7 +351,11 @@ func (z *ZB) wsAddSubUser(username, password string) (*WsGetSubUserListResponse,
return nil, err
}
if genericResponse.Code > 0 && genericResponse.Code != 1000 {
- return nil, fmt.Errorf("%v request failed, message: %v, error code: %v", z.Name, genericResponse.Message, wsErrCodes[genericResponse.Code])
+ return nil,
+ fmt.Errorf("%v request failed, message: %v, error code: %v",
+ z.Name,
+ genericResponse.Message,
+ wsErrCodes[genericResponse.Code])
}
var response WsGetSubUserListResponse
err = json.Unmarshal(resp, &response)
@@ -327,16 +367,17 @@ func (z *ZB) wsAddSubUser(username, password string) (*WsGetSubUserListResponse,
func (z *ZB) wsGetSubUserList() (*WsGetSubUserListResponse, error) {
if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
- return nil, fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name)
+ return nil,
+ fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name)
}
request := WsAuthenticatedRequest{}
request.Channel = "getSubUserList"
request.Event = zWebsocketAddChannel
request.Accesskey = z.API.Credentials.Key
- request.No = z.WebsocketConn.GenerateMessageID(true)
+ request.No = z.Websocket.Conn.GenerateMessageID(true)
request.Sign = z.wsGenerateSignature(request)
- resp, err := z.WebsocketConn.SendMessageReturnResponse(request.No, request)
+ resp, err := z.Websocket.Conn.SendMessageReturnResponse(request.No, request)
if err != nil {
return nil, err
}
@@ -346,28 +387,33 @@ func (z *ZB) wsGetSubUserList() (*WsGetSubUserListResponse, error) {
return nil, err
}
if response.Code > 0 && response.Code != 1000 {
- return &response, fmt.Errorf("%v request failed, message: %v, error code: %v", z.Name, response.Message, wsErrCodes[response.Code])
+ return &response,
+ fmt.Errorf("%v request failed, message: %v, error code: %v",
+ z.Name,
+ response.Message,
+ wsErrCodes[response.Code])
}
return &response, nil
}
func (z *ZB) wsDoTransferFunds(pair currency.Code, amount float64, fromUserName, toUserName string) (*WsRequestResponse, error) {
if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
- return nil, fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name)
+ return nil,
+ fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name)
}
request := WsDoTransferFundsRequest{
Amount: amount,
Currency: pair,
FromUserName: fromUserName,
ToUserName: toUserName,
- No: z.WebsocketConn.GenerateMessageID(true),
+ No: z.Websocket.Conn.GenerateMessageID(true),
}
request.Channel = "doTransferFunds"
request.Event = zWebsocketAddChannel
request.Accesskey = z.API.Credentials.Key
request.Sign = z.wsGenerateSignature(request)
- resp, err := z.WebsocketConn.SendMessageReturnResponse(request.No, request)
+ resp, err := z.Websocket.Conn.SendMessageReturnResponse(request.No, request)
if err != nil {
return nil, err
}
@@ -377,14 +423,19 @@ func (z *ZB) wsDoTransferFunds(pair currency.Code, amount float64, fromUserName,
return nil, err
}
if response.Code > 0 && response.Code != 1000 {
- return &response, fmt.Errorf("%v request failed, message: %v, error code: %v", z.Name, response.Message, wsErrCodes[response.Code])
+ return &response,
+ fmt.Errorf("%v request failed, message: %v, error code: %v",
+ z.Name,
+ response.Message,
+ wsErrCodes[response.Code])
}
return &response, nil
}
func (z *ZB) wsCreateSubUserKey(assetPerm, entrustPerm, leverPerm, moneyPerm bool, keyName, toUserID string) (*WsRequestResponse, error) {
if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
- return nil, fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name)
+ return nil,
+ fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name)
}
request := WsCreateSubUserKeyRequest{
AssetPerm: assetPerm,
@@ -392,7 +443,7 @@ func (z *ZB) wsCreateSubUserKey(assetPerm, entrustPerm, leverPerm, moneyPerm boo
KeyName: keyName,
LeverPerm: leverPerm,
MoneyPerm: moneyPerm,
- No: z.WebsocketConn.GenerateMessageID(true),
+ No: z.Websocket.Conn.GenerateMessageID(true),
ToUserID: toUserID,
}
request.Channel = "createSubUserKey"
@@ -400,7 +451,7 @@ func (z *ZB) wsCreateSubUserKey(assetPerm, entrustPerm, leverPerm, moneyPerm boo
request.Accesskey = z.API.Credentials.Key
request.Sign = z.wsGenerateSignature(request)
- resp, err := z.WebsocketConn.SendMessageReturnResponse(request.No, request)
+ resp, err := z.Websocket.Conn.SendMessageReturnResponse(request.No, request)
if err != nil {
return nil, err
}
@@ -410,27 +461,32 @@ func (z *ZB) wsCreateSubUserKey(assetPerm, entrustPerm, leverPerm, moneyPerm boo
return nil, err
}
if response.Code > 0 && response.Code != 1000 {
- return &response, fmt.Errorf("%v request failed, message: %v, error code: %v", z.Name, response.Message, wsErrCodes[response.Code])
+ return &response,
+ fmt.Errorf("%v request failed, message: %v, error code: %v",
+ z.Name,
+ response.Message,
+ wsErrCodes[response.Code])
}
return &response, nil
}
func (z *ZB) wsSubmitOrder(pair currency.Pair, amount, price float64, tradeType int64) (*WsSubmitOrderResponse, error) {
if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
- return nil, fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name)
+ return nil,
+ fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name)
}
request := WsSubmitOrderRequest{
Amount: amount,
Price: price,
TradeType: tradeType,
- No: z.WebsocketConn.GenerateMessageID(true),
+ No: z.Websocket.Conn.GenerateMessageID(true),
}
request.Channel = pair.String() + "_order"
request.Event = zWebsocketAddChannel
request.Accesskey = z.API.Credentials.Key
request.Sign = z.wsGenerateSignature(request)
- resp, err := z.WebsocketConn.SendMessageReturnResponse(request.No, request)
+ resp, err := z.Websocket.Conn.SendMessageReturnResponse(request.No, request)
if err != nil {
return nil, err
}
@@ -440,25 +496,30 @@ func (z *ZB) wsSubmitOrder(pair currency.Pair, amount, price float64, tradeType
return nil, err
}
if response.Code > 0 && response.Code != 1000 {
- return &response, fmt.Errorf("%v request failed, message: %v, error code: %v", z.Name, response.Message, wsErrCodes[response.Code])
+ return &response,
+ fmt.Errorf("%v request failed, message: %v, error code: %v",
+ z.Name,
+ response.Message,
+ wsErrCodes[response.Code])
}
return &response, nil
}
func (z *ZB) wsCancelOrder(pair currency.Pair, orderID int64) (*WsCancelOrderResponse, error) {
if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
- return nil, fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name)
+ return nil,
+ fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name)
}
request := WsCancelOrderRequest{
ID: orderID,
- No: z.WebsocketConn.GenerateMessageID(true),
+ No: z.Websocket.Conn.GenerateMessageID(true),
}
request.Channel = pair.String() + "_cancelorder"
request.Event = zWebsocketAddChannel
request.Accesskey = z.API.Credentials.Key
request.Sign = z.wsGenerateSignature(request)
- resp, err := z.WebsocketConn.SendMessageReturnResponse(request.No, request)
+ resp, err := z.Websocket.Conn.SendMessageReturnResponse(request.No, request)
if err != nil {
return nil, err
}
@@ -468,25 +529,30 @@ func (z *ZB) wsCancelOrder(pair currency.Pair, orderID int64) (*WsCancelOrderRes
return nil, err
}
if response.Code > 0 && response.Code != 1000 {
- return &response, fmt.Errorf("%v request failed, message: %v, error code: %v", z.Name, response.Message, wsErrCodes[response.Code])
+ return &response,
+ fmt.Errorf("%v request failed, message: %v, error code: %v",
+ z.Name,
+ response.Message,
+ wsErrCodes[response.Code])
}
return &response, nil
}
func (z *ZB) wsGetOrder(pair currency.Pair, orderID int64) (*WsGetOrderResponse, error) {
if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
- return nil, fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name)
+ return nil,
+ fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name)
}
request := WsGetOrderRequest{
ID: orderID,
- No: z.WebsocketConn.GenerateMessageID(true),
+ No: z.Websocket.Conn.GenerateMessageID(true),
}
request.Channel = pair.String() + "_getorder"
request.Event = zWebsocketAddChannel
request.Accesskey = z.API.Credentials.Key
request.Sign = z.wsGenerateSignature(request)
- resp, err := z.WebsocketConn.SendMessageReturnResponse(request.No, request)
+ resp, err := z.Websocket.Conn.SendMessageReturnResponse(request.No, request)
if err != nil {
return nil, err
}
@@ -496,25 +562,30 @@ func (z *ZB) wsGetOrder(pair currency.Pair, orderID int64) (*WsGetOrderResponse,
return nil, err
}
if response.Code > 0 && response.Code != 1000 {
- return &response, fmt.Errorf("%v request failed, message: %v, error code: %v", z.Name, response.Message, wsErrCodes[response.Code])
+ return &response,
+ fmt.Errorf("%v request failed, message: %v, error code: %v",
+ z.Name,
+ response.Message,
+ wsErrCodes[response.Code])
}
return &response, nil
}
func (z *ZB) wsGetOrders(pair currency.Pair, pageIndex, tradeType int64) (*WsGetOrdersResponse, error) {
if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
- return nil, fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name)
+ return nil,
+ fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name)
}
request := WsGetOrdersRequest{
PageIndex: pageIndex,
TradeType: tradeType,
- No: z.WebsocketConn.GenerateMessageID(true),
+ No: z.Websocket.Conn.GenerateMessageID(true),
}
request.Channel = pair.String() + "_getorders"
request.Event = zWebsocketAddChannel
request.Accesskey = z.API.Credentials.Key
request.Sign = z.wsGenerateSignature(request)
- resp, err := z.WebsocketConn.SendMessageReturnResponse(request.No, request)
+ resp, err := z.Websocket.Conn.SendMessageReturnResponse(request.No, request)
if err != nil {
return nil, err
}
@@ -524,26 +595,31 @@ func (z *ZB) wsGetOrders(pair currency.Pair, pageIndex, tradeType int64) (*WsGet
return nil, err
}
if response.Code > 0 && response.Code != 1000 {
- return &response, fmt.Errorf("%v request failed, message: %v, error code: %v", z.Name, response.Message, wsErrCodes[response.Code])
+ return &response,
+ fmt.Errorf("%v request failed, message: %v, error code: %v",
+ z.Name,
+ response.Message,
+ wsErrCodes[response.Code])
}
return &response, nil
}
func (z *ZB) wsGetOrdersIgnoreTradeType(pair currency.Pair, pageIndex, pageSize int64) (*WsGetOrdersIgnoreTradeTypeResponse, error) {
if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
- return nil, fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name)
+ return nil,
+ fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name)
}
request := WsGetOrdersIgnoreTradeTypeRequest{
PageIndex: pageIndex,
PageSize: pageSize,
- No: z.WebsocketConn.GenerateMessageID(true),
+ No: z.Websocket.Conn.GenerateMessageID(true),
}
request.Channel = pair.String() + "_getordersignoretradetype"
request.Event = zWebsocketAddChannel
request.Accesskey = z.API.Credentials.Key
request.Sign = z.wsGenerateSignature(request)
- resp, err := z.WebsocketConn.SendMessageReturnResponse(request.No, request)
+ resp, err := z.Websocket.Conn.SendMessageReturnResponse(request.No, request)
if err != nil {
return nil, err
}
@@ -553,24 +629,29 @@ func (z *ZB) wsGetOrdersIgnoreTradeType(pair currency.Pair, pageIndex, pageSize
return nil, err
}
if response.Code > 0 && response.Code != 1000 {
- return &response, fmt.Errorf("%v request failed, message: %v, error code: %v", z.Name, response.Message, wsErrCodes[response.Code])
+ return &response,
+ fmt.Errorf("%v request failed, message: %v, error code: %v",
+ z.Name,
+ response.Message,
+ wsErrCodes[response.Code])
}
return &response, nil
}
func (z *ZB) wsGetAccountInfoRequest() (*WsGetAccountInfoResponse, error) {
if !z.GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
- return nil, fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name)
+ return nil,
+ fmt.Errorf("%v AuthenticatedWebsocketAPISupport not enabled", z.Name)
}
request := WsAuthenticatedRequest{
Channel: "getaccountinfo",
Event: zWebsocketAddChannel,
Accesskey: z.API.Credentials.Key,
- No: z.WebsocketConn.GenerateMessageID(true),
+ No: z.Websocket.Conn.GenerateMessageID(true),
}
request.Sign = z.wsGenerateSignature(request)
- resp, err := z.WebsocketConn.SendMessageReturnResponse(request.No, request)
+ resp, err := z.Websocket.Conn.SendMessageReturnResponse(request.No, request)
if err != nil {
return nil, err
}
@@ -580,7 +661,11 @@ func (z *ZB) wsGetAccountInfoRequest() (*WsGetAccountInfoResponse, error) {
return nil, err
}
if response.Code > 0 && response.Code != 1000 {
- return &response, fmt.Errorf("%v request failed, message: %v, error code: %v", z.Name, response.Message, wsErrCodes[response.Code])
+ return &response,
+ fmt.Errorf("%v request failed, message: %v, error code: %v",
+ z.Name,
+ response.Message,
+ wsErrCodes[response.Code])
}
return &response, nil
}
diff --git a/exchanges/zb/zb_wrapper.go b/exchanges/zb/zb_wrapper.go
index c5a003d6..f4778160 100644
--- a/exchanges/zb/zb_wrapper.go
+++ b/exchanges/zb/zb_wrapper.go
@@ -19,8 +19,8 @@ import (
"github.com/thrasher-corp/gocryptotrader/exchanges/orderbook"
"github.com/thrasher-corp/gocryptotrader/exchanges/protocol"
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
+ "github.com/thrasher-corp/gocryptotrader/exchanges/stream"
"github.com/thrasher-corp/gocryptotrader/exchanges/ticker"
- "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler"
"github.com/thrasher-corp/gocryptotrader/log"
"github.com/thrasher-corp/gocryptotrader/portfolio/withdraw"
)
@@ -56,19 +56,11 @@ func (z *ZB) SetDefaults() {
z.API.CredentialsValidator.RequiresKey = true
z.API.CredentialsValidator.RequiresSecret = true
- z.CurrencyPairs = currency.PairsManager{
- AssetTypes: asset.Items{
- asset.Spot,
- },
-
- UseGlobalFormat: true,
- RequestFormat: ¤cy.PairFormat{
- Delimiter: "_",
- },
- ConfigFormat: ¤cy.PairFormat{
- Delimiter: "_",
- Uppercase: true,
- },
+ requestFmt := ¤cy.PairFormat{Delimiter: currency.UnderscoreDelimiter}
+ configFmt := ¤cy.PairFormat{Delimiter: currency.UnderscoreDelimiter, Uppercase: true}
+ err := z.SetGlobalPairsManager(requestFmt, configFmt, asset.Spot)
+ if err != nil {
+ log.Errorln(log.ExchangeSys, err)
}
z.Features = exchange.Features{
@@ -142,7 +134,7 @@ func (z *ZB) SetDefaults() {
z.API.Endpoints.URLSecondaryDefault = zbMarketURL
z.API.Endpoints.URLSecondary = z.API.Endpoints.URLSecondaryDefault
z.API.Endpoints.WebsocketURL = zbWebsocketAPI
- z.Websocket = wshandler.New()
+ z.Websocket = stream.New()
z.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit
z.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout
}
@@ -159,33 +151,30 @@ func (z *ZB) Setup(exch *config.ExchangeConfig) error {
return err
}
- err = z.Websocket.Setup(
- &wshandler.WebsocketSetup{
- Enabled: exch.Features.Enabled.Websocket,
- Verbose: exch.Verbose,
- AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
- WebsocketTimeout: exch.WebsocketTrafficTimeout,
- DefaultURL: zbWebsocketAPI,
- ExchangeName: exch.Name,
- RunningURL: exch.API.Endpoints.WebsocketURL,
- Connector: z.WsConnect,
- Subscriber: z.Subscribe,
- Features: &z.Features.Supports.WebsocketCapabilities,
- })
+ err = z.Websocket.Setup(&stream.WebsocketSetup{
+ Enabled: exch.Features.Enabled.Websocket,
+ Verbose: exch.Verbose,
+ AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport,
+ WebsocketTimeout: exch.WebsocketTrafficTimeout,
+ DefaultURL: zbWebsocketAPI,
+ ExchangeName: exch.Name,
+ RunningURL: exch.API.Endpoints.WebsocketURL,
+ Connector: z.WsConnect,
+ GenerateSubscriptions: z.GenerateDefaultSubscriptions,
+ Subscriber: z.Subscribe,
+ Features: &z.Features.Supports.WebsocketCapabilities,
+ OrderbookBufferLimit: exch.WebsocketOrderbookBufferLimit,
+ })
if err != nil {
return err
}
- z.WebsocketConn = &wshandler.WebsocketConnection{
- ExchangeName: z.Name,
+ return z.Websocket.SetupNewConnection(stream.ConnectionSetup{
URL: z.Websocket.GetWebsocketURL(),
- ProxyURL: z.Websocket.GetProxyAddress(),
- Verbose: z.Verbose,
RateLimit: zbWebsocketRateLimit,
ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout,
ResponseMaxLimit: exch.WebsocketResponseMaxLimit,
- }
- return nil
+ })
}
// Start starts the OKEX go routine
@@ -235,19 +224,24 @@ func (z *ZB) UpdateTradablePairs(forceUpdate bool) error {
if err != nil {
return err
}
- return z.UpdatePairs(currency.NewPairsFromStrings(pairs), asset.Spot, false, forceUpdate)
+ p, err := currency.NewPairsFromStrings(pairs)
+ if err != nil {
+ return err
+ }
+ return z.UpdatePairs(p, asset.Spot, false, forceUpdate)
}
// UpdateTicker updates and returns the ticker for a currency pair
func (z *ZB) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price, error) {
- tickerPrice := new(ticker.Price)
-
result, err := z.GetTickers()
if err != nil {
- return tickerPrice, err
+ return nil, err
}
- enabledPairs := z.GetEnabledPairs(assetType)
+ enabledPairs, err := z.GetEnabledPairs(assetType)
+ if err != nil {
+ return nil, err
+ }
for x := range enabledPairs {
// We can't use either pair format here, so format it to lower-
// case and without any delimiter
@@ -255,18 +249,19 @@ func (z *ZB) UpdateTicker(p currency.Pair, assetType asset.Item) (*ticker.Price,
if _, ok := result[curr]; !ok {
continue
}
- var tp ticker.Price
- tp.Pair = enabledPairs[x]
- tp.High = result[curr].High
- tp.Last = result[curr].Last
- tp.Ask = result[curr].Sell
- tp.Bid = result[curr].Buy
- tp.Low = result[curr].Low
- tp.Volume = result[curr].Volume
- err = ticker.ProcessTicker(z.Name, &tp, assetType)
+ err = ticker.ProcessTicker(&ticker.Price{
+ Pair: enabledPairs[x],
+ High: result[curr].High,
+ Last: result[curr].Last,
+ Ask: result[curr].Sell,
+ Bid: result[curr].Buy,
+ Low: result[curr].Low,
+ Volume: result[curr].Volume,
+ ExchangeName: z.Name,
+ AssetType: assetType})
if err != nil {
- log.Error(log.Ticker, err)
+ return nil, err
}
}
@@ -294,9 +289,12 @@ func (z *ZB) FetchOrderbook(p currency.Pair, assetType asset.Item) (*orderbook.B
// UpdateOrderbook updates and returns the orderbook for a currency pair
func (z *ZB) UpdateOrderbook(p currency.Pair, assetType asset.Item) (*orderbook.Base, error) {
orderBook := new(orderbook.Base)
- curr := z.FormatExchangeCurrency(p, assetType).String()
+ currFormat, err := z.FormatExchangeCurrency(p, assetType)
+ if err != nil {
+ return nil, err
+ }
- orderbookNew, err := z.GetOrderbook(curr)
+ orderbookNew, err := z.GetOrderbook(currFormat.String())
if err != nil {
return orderBook, err
}
@@ -473,8 +471,11 @@ func (z *ZB) CancelOrder(o *order.Cancel) error {
}
return nil
}
- return z.CancelExistingOrder(orderIDInt, z.FormatExchangeCurrency(o.Pair,
- o.AssetType).String())
+ fpair, err := z.FormatExchangeCurrency(o.Pair, o.AssetType)
+ if err != nil {
+ return err
+ }
+ return z.CancelExistingOrder(orderIDInt, fpair.String())
}
// CancelAllOrders cancels all orders associated with a currency pair
@@ -483,11 +484,18 @@ func (z *ZB) CancelAllOrders(_ *order.Cancel) (order.CancelAllResponse, error) {
Status: make(map[string]string),
}
var allOpenOrders []Order
- enabledPairs := z.GetEnabledPairs(asset.Spot)
+ enabledPairs, err := z.GetEnabledPairs(asset.Spot)
+ if err != nil {
+ return cancelAllOrdersResponse, err
+ }
+
for x := range enabledPairs {
- fPair := z.FormatExchangeCurrency(enabledPairs[x], asset.Spot).String()
+ fPair, err := z.FormatExchangeCurrency(enabledPairs[x], asset.Spot)
+ if err != nil {
+ return cancelAllOrdersResponse, err
+ }
for y := int64(1); ; y++ {
- openOrders, err := z.GetUnfinishedOrdersIgnoreTradeType(fPair, y, 10)
+ openOrders, err := z.GetUnfinishedOrdersIgnoreTradeType(fPair.String(), y, 10)
if err != nil {
if strings.Contains(err.Error(), "3001") {
break
@@ -508,9 +516,15 @@ func (z *ZB) CancelAllOrders(_ *order.Cancel) (order.CancelAllResponse, error) {
}
for i := range allOpenOrders {
- err := z.CancelOrder(&order.Cancel{
+ p, err := currency.NewPairFromString(allOpenOrders[i].Currency)
+ if err != nil {
+ cancelAllOrdersResponse.Status[strconv.FormatInt(allOpenOrders[i].ID, 10)] = err.Error()
+ continue
+ }
+
+ err = z.CancelOrder(&order.Cancel{
ID: strconv.FormatInt(allOpenOrders[i].ID, 10),
- Pair: currency.NewPairFromString(allOpenOrders[i].Currency),
+ Pair: p,
})
if err != nil {
cancelAllOrdersResponse.Status[strconv.FormatInt(allOpenOrders[i].ID, 10)] = err.Error()
@@ -560,11 +574,6 @@ func (z *ZB) WithdrawFiatFundsToInternationalBank(withdrawRequest *withdraw.Requ
return nil, common.ErrFunctionNotSupported
}
-// GetWebsocket returns a pointer to the exchange websocket
-func (z *ZB) GetWebsocket() (*wshandler.Websocket, error) {
- return z.Websocket, nil
-}
-
// GetFeeByType returns an estimate of fee based on type of transaction
func (z *ZB) GetFeeByType(feeBuilder *exchange.FeeBuilder) (float64, error) {
if !z.AllowAuthenticatedRequest() && // Todo check connection status
@@ -580,8 +589,11 @@ func (z *ZB) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error
var allOrders []Order
for x := range req.Pairs {
for i := int64(1); ; i++ {
- fPair := z.FormatExchangeCurrency(req.Pairs[x], asset.Spot).String()
- resp, err := z.GetUnfinishedOrdersIgnoreTradeType(fPair, i, 10)
+ fPair, err := z.FormatExchangeCurrency(req.Pairs[x], asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+ resp, err := z.GetUnfinishedOrdersIgnoreTradeType(fPair.String(), i, 10)
if err != nil {
if strings.Contains(err.Error(), "3001") {
break
@@ -601,10 +613,19 @@ func (z *ZB) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error
}
}
+ format, err := z.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return nil, err
+ }
+
var orders []order.Detail
for i := range allOrders {
- symbol := currency.NewPairDelimiter(allOrders[i].Currency,
- z.GetPairFormat(asset.Spot, false).Delimiter)
+ var symbol currency.Pair
+ symbol, err = currency.NewPairDelimiter(allOrders[i].Currency,
+ format.Delimiter)
+ if err != nil {
+ return nil, err
+ }
orderDate := time.Unix(int64(allOrders[i].TradeDate), 0)
orderSide := orderSideMap[allOrders[i].Type]
orders = append(orders, order.Detail{
@@ -653,8 +674,11 @@ func (z *ZB) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error
}
for x := range req.Pairs {
for y := int64(1); ; y++ {
- fPair := z.FormatExchangeCurrency(req.Pairs[x], asset.Spot).String()
- resp, err := z.GetOrders(fPair, y, side)
+ fPair, err := z.FormatExchangeCurrency(req.Pairs[x], asset.Spot)
+ if err != nil {
+ return nil, err
+ }
+ resp, err := z.GetOrders(fPair.String(), y, side)
if err != nil {
return nil, err
}
@@ -669,9 +693,18 @@ func (z *ZB) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error
}
}
+ format, err := z.GetPairFormat(asset.Spot, false)
+ if err != nil {
+ return nil, err
+ }
+
for i := range allOrders {
- symbol := currency.NewPairDelimiter(allOrders[i].Currency,
- z.GetPairFormat(asset.Spot, false).Delimiter)
+ var symbol currency.Pair
+ symbol, err = currency.NewPairDelimiter(allOrders[i].Currency,
+ format.Delimiter)
+ if err != nil {
+ return nil, err
+ }
orderDate := time.Unix(int64(allOrders[i].TradeDate), 0)
orderSide := orderSideMap[allOrders[i].Type]
orders = append(orders, order.Detail{
@@ -689,29 +722,6 @@ func (z *ZB) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, error
return orders, nil
}
-// SubscribeToWebsocketChannels appends to ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle subscribing
-func (z *ZB) SubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- z.Websocket.SubscribeToChannels(channels)
- return nil
-}
-
-// UnsubscribeToWebsocketChannels removes from ChannelsToSubscribe
-// which lets websocket.manageSubscriptions handle unsubscribing
-func (z *ZB) UnsubscribeToWebsocketChannels(channels []wshandler.WebsocketChannelSubscription) error {
- return common.ErrFunctionNotSupported
-}
-
-// GetSubscriptions returns a copied list of subscriptions
-func (z *ZB) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) {
- return z.Websocket.GetSubscriptions(), nil
-}
-
-// AuthenticateWebsocket sends an authentication message to the websocket
-func (z *ZB) AuthenticateWebsocket() error {
- return common.ErrFunctionNotSupported
-}
-
// ValidateCredentials validates current credentials used for wrapper
// functionality
func (z *ZB) ValidateCredentials() error {
@@ -745,9 +755,14 @@ func (z *ZB) GetHistoricCandles(pair currency.Pair, a asset.Item, start, end tim
}
}
+ formattedPair, err := z.FormatExchangeCurrency(pair, a)
+ if err != nil {
+ return kline.Item{}, err
+ }
+
klineParams := KlinesRequestParams{
Type: z.FormatExchangeKlineInterval(interval),
- Symbol: z.FormatExchangeCurrency(pair, a).String(),
+ Symbol: formattedPair.String(),
}
candles, err := z.GetSpotKline(klineParams)
diff --git a/gctrpc/rpc.pb.go b/gctrpc/rpc.pb.go
index 8a2594f1..d926f207 100644
--- a/gctrpc/rpc.pb.go
+++ b/gctrpc/rpc.pb.go
@@ -1,79 +1,63 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
-// versions:
-// protoc-gen-go v1.22.0-devel
-// protoc v3.12.3
// source: rpc.proto
package gctrpc
import (
context "context"
+ fmt "fmt"
proto "github.com/golang/protobuf/proto"
timestamp "github.com/golang/protobuf/ptypes/timestamp"
_ "google.golang.org/genproto/googleapis/api/annotations"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
- protoreflect "google.golang.org/protobuf/reflect/protoreflect"
- protoimpl "google.golang.org/protobuf/runtime/protoimpl"
- reflect "reflect"
- sync "sync"
+ math "math"
)
-const (
- // Verify that this generated code is sufficiently up-to-date.
- _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
- // Verify that runtime/protoimpl is sufficiently up-to-date.
- _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
-)
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
-// This is a compile-time assertion that a sufficiently up-to-date version
-// of the legacy proto package is being used.
-const _ = proto.ProtoPackageIsVersion4
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type GetInfoRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetInfoRequest) Reset() {
- *x = GetInfoRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[0]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetInfoRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetInfoRequest) ProtoMessage() {}
-
-func (x *GetInfoRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[0]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetInfoRequest.ProtoReflect.Descriptor instead.
+func (m *GetInfoRequest) Reset() { *m = GetInfoRequest{} }
+func (m *GetInfoRequest) String() string { return proto.CompactTextString(m) }
+func (*GetInfoRequest) ProtoMessage() {}
func (*GetInfoRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{0}
+ return fileDescriptor_77a6da22d6a3feb1, []int{0}
}
+func (m *GetInfoRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetInfoRequest.Unmarshal(m, b)
+}
+func (m *GetInfoRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetInfoRequest.Marshal(b, m, deterministic)
+}
+func (m *GetInfoRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetInfoRequest.Merge(m, src)
+}
+func (m *GetInfoRequest) XXX_Size() int {
+ return xxx_messageInfo_GetInfoRequest.Size(m)
+}
+func (m *GetInfoRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetInfoRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetInfoRequest proto.InternalMessageInfo
+
type GetInfoResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
Uptime string `protobuf:"bytes,1,opt,name=uptime,proto3" json:"uptime,omitempty"`
AvailableExchanges int64 `protobuf:"varint,2,opt,name=available_exchanges,json=availableExchanges,proto3" json:"available_exchanges,omitempty"`
EnabledExchanges int64 `protobuf:"varint,3,opt,name=enabled_exchanges,json=enabledExchanges,proto3" json:"enabled_exchanges,omitempty"`
@@ -81,10860 +65,7559 @@ type GetInfoResponse struct {
DefaultFiatCurrency string `protobuf:"bytes,5,opt,name=default_fiat_currency,json=defaultFiatCurrency,proto3" json:"default_fiat_currency,omitempty"`
SubsystemStatus map[string]bool `protobuf:"bytes,6,rep,name=subsystem_status,json=subsystemStatus,proto3" json:"subsystem_status,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
RpcEndpoints map[string]*RPCEndpoint `protobuf:"bytes,7,rep,name=rpc_endpoints,json=rpcEndpoints,proto3" json:"rpc_endpoints,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetInfoResponse) Reset() {
- *x = GetInfoResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[1]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetInfoResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetInfoResponse) ProtoMessage() {}
-
-func (x *GetInfoResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[1]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetInfoResponse.ProtoReflect.Descriptor instead.
+func (m *GetInfoResponse) Reset() { *m = GetInfoResponse{} }
+func (m *GetInfoResponse) String() string { return proto.CompactTextString(m) }
+func (*GetInfoResponse) ProtoMessage() {}
func (*GetInfoResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{1}
+ return fileDescriptor_77a6da22d6a3feb1, []int{1}
}
-func (x *GetInfoResponse) GetUptime() string {
- if x != nil {
- return x.Uptime
+func (m *GetInfoResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetInfoResponse.Unmarshal(m, b)
+}
+func (m *GetInfoResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetInfoResponse.Marshal(b, m, deterministic)
+}
+func (m *GetInfoResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetInfoResponse.Merge(m, src)
+}
+func (m *GetInfoResponse) XXX_Size() int {
+ return xxx_messageInfo_GetInfoResponse.Size(m)
+}
+func (m *GetInfoResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetInfoResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetInfoResponse proto.InternalMessageInfo
+
+func (m *GetInfoResponse) GetUptime() string {
+ if m != nil {
+ return m.Uptime
}
return ""
}
-func (x *GetInfoResponse) GetAvailableExchanges() int64 {
- if x != nil {
- return x.AvailableExchanges
+func (m *GetInfoResponse) GetAvailableExchanges() int64 {
+ if m != nil {
+ return m.AvailableExchanges
}
return 0
}
-func (x *GetInfoResponse) GetEnabledExchanges() int64 {
- if x != nil {
- return x.EnabledExchanges
+func (m *GetInfoResponse) GetEnabledExchanges() int64 {
+ if m != nil {
+ return m.EnabledExchanges
}
return 0
}
-func (x *GetInfoResponse) GetDefaultForexProvider() string {
- if x != nil {
- return x.DefaultForexProvider
+func (m *GetInfoResponse) GetDefaultForexProvider() string {
+ if m != nil {
+ return m.DefaultForexProvider
}
return ""
}
-func (x *GetInfoResponse) GetDefaultFiatCurrency() string {
- if x != nil {
- return x.DefaultFiatCurrency
+func (m *GetInfoResponse) GetDefaultFiatCurrency() string {
+ if m != nil {
+ return m.DefaultFiatCurrency
}
return ""
}
-func (x *GetInfoResponse) GetSubsystemStatus() map[string]bool {
- if x != nil {
- return x.SubsystemStatus
+func (m *GetInfoResponse) GetSubsystemStatus() map[string]bool {
+ if m != nil {
+ return m.SubsystemStatus
}
return nil
}
-func (x *GetInfoResponse) GetRpcEndpoints() map[string]*RPCEndpoint {
- if x != nil {
- return x.RpcEndpoints
+func (m *GetInfoResponse) GetRpcEndpoints() map[string]*RPCEndpoint {
+ if m != nil {
+ return m.RpcEndpoints
}
return nil
}
type GetCommunicationRelayersRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetCommunicationRelayersRequest) Reset() {
- *x = GetCommunicationRelayersRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[2]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetCommunicationRelayersRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetCommunicationRelayersRequest) ProtoMessage() {}
-
-func (x *GetCommunicationRelayersRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[2]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetCommunicationRelayersRequest.ProtoReflect.Descriptor instead.
+func (m *GetCommunicationRelayersRequest) Reset() { *m = GetCommunicationRelayersRequest{} }
+func (m *GetCommunicationRelayersRequest) String() string { return proto.CompactTextString(m) }
+func (*GetCommunicationRelayersRequest) ProtoMessage() {}
func (*GetCommunicationRelayersRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{2}
+ return fileDescriptor_77a6da22d6a3feb1, []int{2}
}
+func (m *GetCommunicationRelayersRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetCommunicationRelayersRequest.Unmarshal(m, b)
+}
+func (m *GetCommunicationRelayersRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetCommunicationRelayersRequest.Marshal(b, m, deterministic)
+}
+func (m *GetCommunicationRelayersRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetCommunicationRelayersRequest.Merge(m, src)
+}
+func (m *GetCommunicationRelayersRequest) XXX_Size() int {
+ return xxx_messageInfo_GetCommunicationRelayersRequest.Size(m)
+}
+func (m *GetCommunicationRelayersRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetCommunicationRelayersRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetCommunicationRelayersRequest proto.InternalMessageInfo
+
type CommunicationRelayer struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
- Connected bool `protobuf:"varint,2,opt,name=connected,proto3" json:"connected,omitempty"`
+ Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
+ Connected bool `protobuf:"varint,2,opt,name=connected,proto3" json:"connected,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *CommunicationRelayer) Reset() {
- *x = CommunicationRelayer{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[3]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *CommunicationRelayer) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*CommunicationRelayer) ProtoMessage() {}
-
-func (x *CommunicationRelayer) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[3]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use CommunicationRelayer.ProtoReflect.Descriptor instead.
+func (m *CommunicationRelayer) Reset() { *m = CommunicationRelayer{} }
+func (m *CommunicationRelayer) String() string { return proto.CompactTextString(m) }
+func (*CommunicationRelayer) ProtoMessage() {}
func (*CommunicationRelayer) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{3}
+ return fileDescriptor_77a6da22d6a3feb1, []int{3}
}
-func (x *CommunicationRelayer) GetEnabled() bool {
- if x != nil {
- return x.Enabled
+func (m *CommunicationRelayer) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_CommunicationRelayer.Unmarshal(m, b)
+}
+func (m *CommunicationRelayer) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_CommunicationRelayer.Marshal(b, m, deterministic)
+}
+func (m *CommunicationRelayer) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_CommunicationRelayer.Merge(m, src)
+}
+func (m *CommunicationRelayer) XXX_Size() int {
+ return xxx_messageInfo_CommunicationRelayer.Size(m)
+}
+func (m *CommunicationRelayer) XXX_DiscardUnknown() {
+ xxx_messageInfo_CommunicationRelayer.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_CommunicationRelayer proto.InternalMessageInfo
+
+func (m *CommunicationRelayer) GetEnabled() bool {
+ if m != nil {
+ return m.Enabled
}
return false
}
-func (x *CommunicationRelayer) GetConnected() bool {
- if x != nil {
- return x.Connected
+func (m *CommunicationRelayer) GetConnected() bool {
+ if m != nil {
+ return m.Connected
}
return false
}
type GetCommunicationRelayersResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
CommunicationRelayers map[string]*CommunicationRelayer `protobuf:"bytes,1,rep,name=communication_relayers,json=communicationRelayers,proto3" json:"communication_relayers,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetCommunicationRelayersResponse) Reset() {
- *x = GetCommunicationRelayersResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[4]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetCommunicationRelayersResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetCommunicationRelayersResponse) ProtoMessage() {}
-
-func (x *GetCommunicationRelayersResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[4]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetCommunicationRelayersResponse.ProtoReflect.Descriptor instead.
+func (m *GetCommunicationRelayersResponse) Reset() { *m = GetCommunicationRelayersResponse{} }
+func (m *GetCommunicationRelayersResponse) String() string { return proto.CompactTextString(m) }
+func (*GetCommunicationRelayersResponse) ProtoMessage() {}
func (*GetCommunicationRelayersResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{4}
+ return fileDescriptor_77a6da22d6a3feb1, []int{4}
}
-func (x *GetCommunicationRelayersResponse) GetCommunicationRelayers() map[string]*CommunicationRelayer {
- if x != nil {
- return x.CommunicationRelayers
+func (m *GetCommunicationRelayersResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetCommunicationRelayersResponse.Unmarshal(m, b)
+}
+func (m *GetCommunicationRelayersResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetCommunicationRelayersResponse.Marshal(b, m, deterministic)
+}
+func (m *GetCommunicationRelayersResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetCommunicationRelayersResponse.Merge(m, src)
+}
+func (m *GetCommunicationRelayersResponse) XXX_Size() int {
+ return xxx_messageInfo_GetCommunicationRelayersResponse.Size(m)
+}
+func (m *GetCommunicationRelayersResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetCommunicationRelayersResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetCommunicationRelayersResponse proto.InternalMessageInfo
+
+func (m *GetCommunicationRelayersResponse) GetCommunicationRelayers() map[string]*CommunicationRelayer {
+ if m != nil {
+ return m.CommunicationRelayers
}
return nil
}
type GenericSubsystemRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Subsystem string `protobuf:"bytes,1,opt,name=subsystem,proto3" json:"subsystem,omitempty"`
+ Subsystem string `protobuf:"bytes,1,opt,name=subsystem,proto3" json:"subsystem,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GenericSubsystemRequest) Reset() {
- *x = GenericSubsystemRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[5]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GenericSubsystemRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GenericSubsystemRequest) ProtoMessage() {}
-
-func (x *GenericSubsystemRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[5]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GenericSubsystemRequest.ProtoReflect.Descriptor instead.
+func (m *GenericSubsystemRequest) Reset() { *m = GenericSubsystemRequest{} }
+func (m *GenericSubsystemRequest) String() string { return proto.CompactTextString(m) }
+func (*GenericSubsystemRequest) ProtoMessage() {}
func (*GenericSubsystemRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{5}
+ return fileDescriptor_77a6da22d6a3feb1, []int{5}
}
-func (x *GenericSubsystemRequest) GetSubsystem() string {
- if x != nil {
- return x.Subsystem
+func (m *GenericSubsystemRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GenericSubsystemRequest.Unmarshal(m, b)
+}
+func (m *GenericSubsystemRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GenericSubsystemRequest.Marshal(b, m, deterministic)
+}
+func (m *GenericSubsystemRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GenericSubsystemRequest.Merge(m, src)
+}
+func (m *GenericSubsystemRequest) XXX_Size() int {
+ return xxx_messageInfo_GenericSubsystemRequest.Size(m)
+}
+func (m *GenericSubsystemRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GenericSubsystemRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GenericSubsystemRequest proto.InternalMessageInfo
+
+func (m *GenericSubsystemRequest) GetSubsystem() string {
+ if m != nil {
+ return m.Subsystem
}
return ""
}
-type GenericSubsystemResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-}
-
-func (x *GenericSubsystemResponse) Reset() {
- *x = GenericSubsystemResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[6]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GenericSubsystemResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GenericSubsystemResponse) ProtoMessage() {}
-
-func (x *GenericSubsystemResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[6]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GenericSubsystemResponse.ProtoReflect.Descriptor instead.
-func (*GenericSubsystemResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{6}
-}
-
type GetSubsystemsRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetSubsystemsRequest) Reset() {
- *x = GetSubsystemsRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[7]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetSubsystemsRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetSubsystemsRequest) ProtoMessage() {}
-
-func (x *GetSubsystemsRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[7]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetSubsystemsRequest.ProtoReflect.Descriptor instead.
+func (m *GetSubsystemsRequest) Reset() { *m = GetSubsystemsRequest{} }
+func (m *GetSubsystemsRequest) String() string { return proto.CompactTextString(m) }
+func (*GetSubsystemsRequest) ProtoMessage() {}
func (*GetSubsystemsRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{7}
+ return fileDescriptor_77a6da22d6a3feb1, []int{6}
}
+func (m *GetSubsystemsRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetSubsystemsRequest.Unmarshal(m, b)
+}
+func (m *GetSubsystemsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetSubsystemsRequest.Marshal(b, m, deterministic)
+}
+func (m *GetSubsystemsRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetSubsystemsRequest.Merge(m, src)
+}
+func (m *GetSubsystemsRequest) XXX_Size() int {
+ return xxx_messageInfo_GetSubsystemsRequest.Size(m)
+}
+func (m *GetSubsystemsRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetSubsystemsRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetSubsystemsRequest proto.InternalMessageInfo
+
type GetSusbsytemsResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- SubsystemsStatus map[string]bool `protobuf:"bytes,1,rep,name=subsystems_status,json=subsystemsStatus,proto3" json:"subsystems_status,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
+ SubsystemsStatus map[string]bool `protobuf:"bytes,1,rep,name=subsystems_status,json=subsystemsStatus,proto3" json:"subsystems_status,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetSusbsytemsResponse) Reset() {
- *x = GetSusbsytemsResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[8]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetSusbsytemsResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetSusbsytemsResponse) ProtoMessage() {}
-
-func (x *GetSusbsytemsResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[8]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetSusbsytemsResponse.ProtoReflect.Descriptor instead.
+func (m *GetSusbsytemsResponse) Reset() { *m = GetSusbsytemsResponse{} }
+func (m *GetSusbsytemsResponse) String() string { return proto.CompactTextString(m) }
+func (*GetSusbsytemsResponse) ProtoMessage() {}
func (*GetSusbsytemsResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{8}
+ return fileDescriptor_77a6da22d6a3feb1, []int{7}
}
-func (x *GetSusbsytemsResponse) GetSubsystemsStatus() map[string]bool {
- if x != nil {
- return x.SubsystemsStatus
+func (m *GetSusbsytemsResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetSusbsytemsResponse.Unmarshal(m, b)
+}
+func (m *GetSusbsytemsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetSusbsytemsResponse.Marshal(b, m, deterministic)
+}
+func (m *GetSusbsytemsResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetSusbsytemsResponse.Merge(m, src)
+}
+func (m *GetSusbsytemsResponse) XXX_Size() int {
+ return xxx_messageInfo_GetSusbsytemsResponse.Size(m)
+}
+func (m *GetSusbsytemsResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetSusbsytemsResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetSusbsytemsResponse proto.InternalMessageInfo
+
+func (m *GetSusbsytemsResponse) GetSubsystemsStatus() map[string]bool {
+ if m != nil {
+ return m.SubsystemsStatus
}
return nil
}
type GetRPCEndpointsRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetRPCEndpointsRequest) Reset() {
- *x = GetRPCEndpointsRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[9]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetRPCEndpointsRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetRPCEndpointsRequest) ProtoMessage() {}
-
-func (x *GetRPCEndpointsRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[9]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetRPCEndpointsRequest.ProtoReflect.Descriptor instead.
+func (m *GetRPCEndpointsRequest) Reset() { *m = GetRPCEndpointsRequest{} }
+func (m *GetRPCEndpointsRequest) String() string { return proto.CompactTextString(m) }
+func (*GetRPCEndpointsRequest) ProtoMessage() {}
func (*GetRPCEndpointsRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{9}
+ return fileDescriptor_77a6da22d6a3feb1, []int{8}
}
+func (m *GetRPCEndpointsRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetRPCEndpointsRequest.Unmarshal(m, b)
+}
+func (m *GetRPCEndpointsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetRPCEndpointsRequest.Marshal(b, m, deterministic)
+}
+func (m *GetRPCEndpointsRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetRPCEndpointsRequest.Merge(m, src)
+}
+func (m *GetRPCEndpointsRequest) XXX_Size() int {
+ return xxx_messageInfo_GetRPCEndpointsRequest.Size(m)
+}
+func (m *GetRPCEndpointsRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetRPCEndpointsRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetRPCEndpointsRequest proto.InternalMessageInfo
+
type RPCEndpoint struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Started bool `protobuf:"varint,1,opt,name=started,proto3" json:"started,omitempty"`
- ListenAddress string `protobuf:"bytes,2,opt,name=listen_address,json=listenAddress,proto3" json:"listen_address,omitempty"`
+ Started bool `protobuf:"varint,1,opt,name=started,proto3" json:"started,omitempty"`
+ ListenAddress string `protobuf:"bytes,2,opt,name=listen_address,json=listenAddress,proto3" json:"listen_address,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *RPCEndpoint) Reset() {
- *x = RPCEndpoint{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[10]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *RPCEndpoint) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*RPCEndpoint) ProtoMessage() {}
-
-func (x *RPCEndpoint) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[10]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use RPCEndpoint.ProtoReflect.Descriptor instead.
+func (m *RPCEndpoint) Reset() { *m = RPCEndpoint{} }
+func (m *RPCEndpoint) String() string { return proto.CompactTextString(m) }
+func (*RPCEndpoint) ProtoMessage() {}
func (*RPCEndpoint) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{10}
+ return fileDescriptor_77a6da22d6a3feb1, []int{9}
}
-func (x *RPCEndpoint) GetStarted() bool {
- if x != nil {
- return x.Started
+func (m *RPCEndpoint) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_RPCEndpoint.Unmarshal(m, b)
+}
+func (m *RPCEndpoint) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_RPCEndpoint.Marshal(b, m, deterministic)
+}
+func (m *RPCEndpoint) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_RPCEndpoint.Merge(m, src)
+}
+func (m *RPCEndpoint) XXX_Size() int {
+ return xxx_messageInfo_RPCEndpoint.Size(m)
+}
+func (m *RPCEndpoint) XXX_DiscardUnknown() {
+ xxx_messageInfo_RPCEndpoint.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_RPCEndpoint proto.InternalMessageInfo
+
+func (m *RPCEndpoint) GetStarted() bool {
+ if m != nil {
+ return m.Started
}
return false
}
-func (x *RPCEndpoint) GetListenAddress() string {
- if x != nil {
- return x.ListenAddress
+func (m *RPCEndpoint) GetListenAddress() string {
+ if m != nil {
+ return m.ListenAddress
}
return ""
}
type GetRPCEndpointsResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Endpoints map[string]*RPCEndpoint `protobuf:"bytes,1,rep,name=endpoints,proto3" json:"endpoints,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+ Endpoints map[string]*RPCEndpoint `protobuf:"bytes,1,rep,name=endpoints,proto3" json:"endpoints,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetRPCEndpointsResponse) Reset() {
- *x = GetRPCEndpointsResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[11]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetRPCEndpointsResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetRPCEndpointsResponse) ProtoMessage() {}
-
-func (x *GetRPCEndpointsResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[11]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetRPCEndpointsResponse.ProtoReflect.Descriptor instead.
+func (m *GetRPCEndpointsResponse) Reset() { *m = GetRPCEndpointsResponse{} }
+func (m *GetRPCEndpointsResponse) String() string { return proto.CompactTextString(m) }
+func (*GetRPCEndpointsResponse) ProtoMessage() {}
func (*GetRPCEndpointsResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{11}
+ return fileDescriptor_77a6da22d6a3feb1, []int{10}
}
-func (x *GetRPCEndpointsResponse) GetEndpoints() map[string]*RPCEndpoint {
- if x != nil {
- return x.Endpoints
+func (m *GetRPCEndpointsResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetRPCEndpointsResponse.Unmarshal(m, b)
+}
+func (m *GetRPCEndpointsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetRPCEndpointsResponse.Marshal(b, m, deterministic)
+}
+func (m *GetRPCEndpointsResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetRPCEndpointsResponse.Merge(m, src)
+}
+func (m *GetRPCEndpointsResponse) XXX_Size() int {
+ return xxx_messageInfo_GetRPCEndpointsResponse.Size(m)
+}
+func (m *GetRPCEndpointsResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetRPCEndpointsResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetRPCEndpointsResponse proto.InternalMessageInfo
+
+func (m *GetRPCEndpointsResponse) GetEndpoints() map[string]*RPCEndpoint {
+ if m != nil {
+ return m.Endpoints
}
return nil
}
type GenericExchangeNameRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GenericExchangeNameRequest) Reset() {
- *x = GenericExchangeNameRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[12]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GenericExchangeNameRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GenericExchangeNameRequest) ProtoMessage() {}
-
-func (x *GenericExchangeNameRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[12]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GenericExchangeNameRequest.ProtoReflect.Descriptor instead.
+func (m *GenericExchangeNameRequest) Reset() { *m = GenericExchangeNameRequest{} }
+func (m *GenericExchangeNameRequest) String() string { return proto.CompactTextString(m) }
+func (*GenericExchangeNameRequest) ProtoMessage() {}
func (*GenericExchangeNameRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{12}
+ return fileDescriptor_77a6da22d6a3feb1, []int{11}
}
-func (x *GenericExchangeNameRequest) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *GenericExchangeNameRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GenericExchangeNameRequest.Unmarshal(m, b)
+}
+func (m *GenericExchangeNameRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GenericExchangeNameRequest.Marshal(b, m, deterministic)
+}
+func (m *GenericExchangeNameRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GenericExchangeNameRequest.Merge(m, src)
+}
+func (m *GenericExchangeNameRequest) XXX_Size() int {
+ return xxx_messageInfo_GenericExchangeNameRequest.Size(m)
+}
+func (m *GenericExchangeNameRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GenericExchangeNameRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GenericExchangeNameRequest proto.InternalMessageInfo
+
+func (m *GenericExchangeNameRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
-type GenericExchangeNameResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-}
-
-func (x *GenericExchangeNameResponse) Reset() {
- *x = GenericExchangeNameResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[13]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GenericExchangeNameResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GenericExchangeNameResponse) ProtoMessage() {}
-
-func (x *GenericExchangeNameResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[13]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GenericExchangeNameResponse.ProtoReflect.Descriptor instead.
-func (*GenericExchangeNameResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{13}
-}
-
type GetExchangesRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
+ Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetExchangesRequest) Reset() {
- *x = GetExchangesRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[14]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetExchangesRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetExchangesRequest) ProtoMessage() {}
-
-func (x *GetExchangesRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[14]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetExchangesRequest.ProtoReflect.Descriptor instead.
+func (m *GetExchangesRequest) Reset() { *m = GetExchangesRequest{} }
+func (m *GetExchangesRequest) String() string { return proto.CompactTextString(m) }
+func (*GetExchangesRequest) ProtoMessage() {}
func (*GetExchangesRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{14}
+ return fileDescriptor_77a6da22d6a3feb1, []int{12}
}
-func (x *GetExchangesRequest) GetEnabled() bool {
- if x != nil {
- return x.Enabled
+func (m *GetExchangesRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetExchangesRequest.Unmarshal(m, b)
+}
+func (m *GetExchangesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetExchangesRequest.Marshal(b, m, deterministic)
+}
+func (m *GetExchangesRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetExchangesRequest.Merge(m, src)
+}
+func (m *GetExchangesRequest) XXX_Size() int {
+ return xxx_messageInfo_GetExchangesRequest.Size(m)
+}
+func (m *GetExchangesRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetExchangesRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetExchangesRequest proto.InternalMessageInfo
+
+func (m *GetExchangesRequest) GetEnabled() bool {
+ if m != nil {
+ return m.Enabled
}
return false
}
type GetExchangesResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchanges string `protobuf:"bytes,1,opt,name=exchanges,proto3" json:"exchanges,omitempty"`
+ Exchanges string `protobuf:"bytes,1,opt,name=exchanges,proto3" json:"exchanges,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetExchangesResponse) Reset() {
- *x = GetExchangesResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[15]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetExchangesResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetExchangesResponse) ProtoMessage() {}
-
-func (x *GetExchangesResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[15]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetExchangesResponse.ProtoReflect.Descriptor instead.
+func (m *GetExchangesResponse) Reset() { *m = GetExchangesResponse{} }
+func (m *GetExchangesResponse) String() string { return proto.CompactTextString(m) }
+func (*GetExchangesResponse) ProtoMessage() {}
func (*GetExchangesResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{15}
+ return fileDescriptor_77a6da22d6a3feb1, []int{13}
}
-func (x *GetExchangesResponse) GetExchanges() string {
- if x != nil {
- return x.Exchanges
+func (m *GetExchangesResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetExchangesResponse.Unmarshal(m, b)
+}
+func (m *GetExchangesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetExchangesResponse.Marshal(b, m, deterministic)
+}
+func (m *GetExchangesResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetExchangesResponse.Merge(m, src)
+}
+func (m *GetExchangesResponse) XXX_Size() int {
+ return xxx_messageInfo_GetExchangesResponse.Size(m)
+}
+func (m *GetExchangesResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetExchangesResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetExchangesResponse proto.InternalMessageInfo
+
+func (m *GetExchangesResponse) GetExchanges() string {
+ if m != nil {
+ return m.Exchanges
}
return ""
}
type GetExchangeOTPReponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- OtpCode string `protobuf:"bytes,1,opt,name=otp_code,json=otpCode,proto3" json:"otp_code,omitempty"`
+ OtpCode string `protobuf:"bytes,1,opt,name=otp_code,json=otpCode,proto3" json:"otp_code,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetExchangeOTPReponse) Reset() {
- *x = GetExchangeOTPReponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[16]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetExchangeOTPReponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetExchangeOTPReponse) ProtoMessage() {}
-
-func (x *GetExchangeOTPReponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[16]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetExchangeOTPReponse.ProtoReflect.Descriptor instead.
+func (m *GetExchangeOTPReponse) Reset() { *m = GetExchangeOTPReponse{} }
+func (m *GetExchangeOTPReponse) String() string { return proto.CompactTextString(m) }
+func (*GetExchangeOTPReponse) ProtoMessage() {}
func (*GetExchangeOTPReponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{16}
+ return fileDescriptor_77a6da22d6a3feb1, []int{14}
}
-func (x *GetExchangeOTPReponse) GetOtpCode() string {
- if x != nil {
- return x.OtpCode
+func (m *GetExchangeOTPReponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetExchangeOTPReponse.Unmarshal(m, b)
+}
+func (m *GetExchangeOTPReponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetExchangeOTPReponse.Marshal(b, m, deterministic)
+}
+func (m *GetExchangeOTPReponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetExchangeOTPReponse.Merge(m, src)
+}
+func (m *GetExchangeOTPReponse) XXX_Size() int {
+ return xxx_messageInfo_GetExchangeOTPReponse.Size(m)
+}
+func (m *GetExchangeOTPReponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetExchangeOTPReponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetExchangeOTPReponse proto.InternalMessageInfo
+
+func (m *GetExchangeOTPReponse) GetOtpCode() string {
+ if m != nil {
+ return m.OtpCode
}
return ""
}
type GetExchangeOTPsRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetExchangeOTPsRequest) Reset() {
- *x = GetExchangeOTPsRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[17]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetExchangeOTPsRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetExchangeOTPsRequest) ProtoMessage() {}
-
-func (x *GetExchangeOTPsRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[17]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetExchangeOTPsRequest.ProtoReflect.Descriptor instead.
+func (m *GetExchangeOTPsRequest) Reset() { *m = GetExchangeOTPsRequest{} }
+func (m *GetExchangeOTPsRequest) String() string { return proto.CompactTextString(m) }
+func (*GetExchangeOTPsRequest) ProtoMessage() {}
func (*GetExchangeOTPsRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{17}
+ return fileDescriptor_77a6da22d6a3feb1, []int{15}
}
+func (m *GetExchangeOTPsRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetExchangeOTPsRequest.Unmarshal(m, b)
+}
+func (m *GetExchangeOTPsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetExchangeOTPsRequest.Marshal(b, m, deterministic)
+}
+func (m *GetExchangeOTPsRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetExchangeOTPsRequest.Merge(m, src)
+}
+func (m *GetExchangeOTPsRequest) XXX_Size() int {
+ return xxx_messageInfo_GetExchangeOTPsRequest.Size(m)
+}
+func (m *GetExchangeOTPsRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetExchangeOTPsRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetExchangeOTPsRequest proto.InternalMessageInfo
+
type GetExchangeOTPsResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- OtpCodes map[string]string `protobuf:"bytes,1,rep,name=otp_codes,json=otpCodes,proto3" json:"otp_codes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+ OtpCodes map[string]string `protobuf:"bytes,1,rep,name=otp_codes,json=otpCodes,proto3" json:"otp_codes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetExchangeOTPsResponse) Reset() {
- *x = GetExchangeOTPsResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[18]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetExchangeOTPsResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetExchangeOTPsResponse) ProtoMessage() {}
-
-func (x *GetExchangeOTPsResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[18]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetExchangeOTPsResponse.ProtoReflect.Descriptor instead.
+func (m *GetExchangeOTPsResponse) Reset() { *m = GetExchangeOTPsResponse{} }
+func (m *GetExchangeOTPsResponse) String() string { return proto.CompactTextString(m) }
+func (*GetExchangeOTPsResponse) ProtoMessage() {}
func (*GetExchangeOTPsResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{18}
+ return fileDescriptor_77a6da22d6a3feb1, []int{16}
}
-func (x *GetExchangeOTPsResponse) GetOtpCodes() map[string]string {
- if x != nil {
- return x.OtpCodes
+func (m *GetExchangeOTPsResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetExchangeOTPsResponse.Unmarshal(m, b)
+}
+func (m *GetExchangeOTPsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetExchangeOTPsResponse.Marshal(b, m, deterministic)
+}
+func (m *GetExchangeOTPsResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetExchangeOTPsResponse.Merge(m, src)
+}
+func (m *GetExchangeOTPsResponse) XXX_Size() int {
+ return xxx_messageInfo_GetExchangeOTPsResponse.Size(m)
+}
+func (m *GetExchangeOTPsResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetExchangeOTPsResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetExchangeOTPsResponse proto.InternalMessageInfo
+
+func (m *GetExchangeOTPsResponse) GetOtpCodes() map[string]string {
+ if m != nil {
+ return m.OtpCodes
}
return nil
}
type DisableExchangeRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *DisableExchangeRequest) Reset() {
- *x = DisableExchangeRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[19]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *DisableExchangeRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*DisableExchangeRequest) ProtoMessage() {}
-
-func (x *DisableExchangeRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[19]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use DisableExchangeRequest.ProtoReflect.Descriptor instead.
+func (m *DisableExchangeRequest) Reset() { *m = DisableExchangeRequest{} }
+func (m *DisableExchangeRequest) String() string { return proto.CompactTextString(m) }
+func (*DisableExchangeRequest) ProtoMessage() {}
func (*DisableExchangeRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{19}
+ return fileDescriptor_77a6da22d6a3feb1, []int{17}
}
-func (x *DisableExchangeRequest) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *DisableExchangeRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_DisableExchangeRequest.Unmarshal(m, b)
+}
+func (m *DisableExchangeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_DisableExchangeRequest.Marshal(b, m, deterministic)
+}
+func (m *DisableExchangeRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_DisableExchangeRequest.Merge(m, src)
+}
+func (m *DisableExchangeRequest) XXX_Size() int {
+ return xxx_messageInfo_DisableExchangeRequest.Size(m)
+}
+func (m *DisableExchangeRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_DisableExchangeRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_DisableExchangeRequest proto.InternalMessageInfo
+
+func (m *DisableExchangeRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
type PairsSupported struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- AvailablePairs string `protobuf:"bytes,1,opt,name=available_pairs,json=availablePairs,proto3" json:"available_pairs,omitempty"`
- EnabledPairs string `protobuf:"bytes,2,opt,name=enabled_pairs,json=enabledPairs,proto3" json:"enabled_pairs,omitempty"`
+ AvailablePairs string `protobuf:"bytes,1,opt,name=available_pairs,json=availablePairs,proto3" json:"available_pairs,omitempty"`
+ EnabledPairs string `protobuf:"bytes,2,opt,name=enabled_pairs,json=enabledPairs,proto3" json:"enabled_pairs,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *PairsSupported) Reset() {
- *x = PairsSupported{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[20]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *PairsSupported) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*PairsSupported) ProtoMessage() {}
-
-func (x *PairsSupported) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[20]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use PairsSupported.ProtoReflect.Descriptor instead.
+func (m *PairsSupported) Reset() { *m = PairsSupported{} }
+func (m *PairsSupported) String() string { return proto.CompactTextString(m) }
+func (*PairsSupported) ProtoMessage() {}
func (*PairsSupported) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{20}
+ return fileDescriptor_77a6da22d6a3feb1, []int{18}
}
-func (x *PairsSupported) GetAvailablePairs() string {
- if x != nil {
- return x.AvailablePairs
+func (m *PairsSupported) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_PairsSupported.Unmarshal(m, b)
+}
+func (m *PairsSupported) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_PairsSupported.Marshal(b, m, deterministic)
+}
+func (m *PairsSupported) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_PairsSupported.Merge(m, src)
+}
+func (m *PairsSupported) XXX_Size() int {
+ return xxx_messageInfo_PairsSupported.Size(m)
+}
+func (m *PairsSupported) XXX_DiscardUnknown() {
+ xxx_messageInfo_PairsSupported.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_PairsSupported proto.InternalMessageInfo
+
+func (m *PairsSupported) GetAvailablePairs() string {
+ if m != nil {
+ return m.AvailablePairs
}
return ""
}
-func (x *PairsSupported) GetEnabledPairs() string {
- if x != nil {
- return x.EnabledPairs
+func (m *PairsSupported) GetEnabledPairs() string {
+ if m != nil {
+ return m.EnabledPairs
}
return ""
}
type GetExchangeInfoResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
- Enabled bool `protobuf:"varint,2,opt,name=enabled,proto3" json:"enabled,omitempty"`
- Verbose bool `protobuf:"varint,3,opt,name=verbose,proto3" json:"verbose,omitempty"`
- UsingSandbox bool `protobuf:"varint,4,opt,name=using_sandbox,json=usingSandbox,proto3" json:"using_sandbox,omitempty"`
- HttpTimeout string `protobuf:"bytes,5,opt,name=http_timeout,json=httpTimeout,proto3" json:"http_timeout,omitempty"`
- HttpUseragent string `protobuf:"bytes,6,opt,name=http_useragent,json=httpUseragent,proto3" json:"http_useragent,omitempty"`
- HttpProxy string `protobuf:"bytes,7,opt,name=http_proxy,json=httpProxy,proto3" json:"http_proxy,omitempty"`
- BaseCurrencies string `protobuf:"bytes,8,opt,name=base_currencies,json=baseCurrencies,proto3" json:"base_currencies,omitempty"`
- SupportedAssets map[string]*PairsSupported `protobuf:"bytes,9,rep,name=supported_assets,json=supportedAssets,proto3" json:"supported_assets,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
- AuthenticatedApi bool `protobuf:"varint,10,opt,name=authenticated_api,json=authenticatedApi,proto3" json:"authenticated_api,omitempty"`
+ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+ Enabled bool `protobuf:"varint,2,opt,name=enabled,proto3" json:"enabled,omitempty"`
+ Verbose bool `protobuf:"varint,3,opt,name=verbose,proto3" json:"verbose,omitempty"`
+ UsingSandbox bool `protobuf:"varint,4,opt,name=using_sandbox,json=usingSandbox,proto3" json:"using_sandbox,omitempty"`
+ HttpTimeout string `protobuf:"bytes,5,opt,name=http_timeout,json=httpTimeout,proto3" json:"http_timeout,omitempty"`
+ HttpUseragent string `protobuf:"bytes,6,opt,name=http_useragent,json=httpUseragent,proto3" json:"http_useragent,omitempty"`
+ HttpProxy string `protobuf:"bytes,7,opt,name=http_proxy,json=httpProxy,proto3" json:"http_proxy,omitempty"`
+ BaseCurrencies string `protobuf:"bytes,8,opt,name=base_currencies,json=baseCurrencies,proto3" json:"base_currencies,omitempty"`
+ SupportedAssets map[string]*PairsSupported `protobuf:"bytes,9,rep,name=supported_assets,json=supportedAssets,proto3" json:"supported_assets,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+ AuthenticatedApi bool `protobuf:"varint,10,opt,name=authenticated_api,json=authenticatedApi,proto3" json:"authenticated_api,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetExchangeInfoResponse) Reset() {
- *x = GetExchangeInfoResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[21]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetExchangeInfoResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetExchangeInfoResponse) ProtoMessage() {}
-
-func (x *GetExchangeInfoResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[21]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetExchangeInfoResponse.ProtoReflect.Descriptor instead.
+func (m *GetExchangeInfoResponse) Reset() { *m = GetExchangeInfoResponse{} }
+func (m *GetExchangeInfoResponse) String() string { return proto.CompactTextString(m) }
+func (*GetExchangeInfoResponse) ProtoMessage() {}
func (*GetExchangeInfoResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{21}
+ return fileDescriptor_77a6da22d6a3feb1, []int{19}
}
-func (x *GetExchangeInfoResponse) GetName() string {
- if x != nil {
- return x.Name
+func (m *GetExchangeInfoResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetExchangeInfoResponse.Unmarshal(m, b)
+}
+func (m *GetExchangeInfoResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetExchangeInfoResponse.Marshal(b, m, deterministic)
+}
+func (m *GetExchangeInfoResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetExchangeInfoResponse.Merge(m, src)
+}
+func (m *GetExchangeInfoResponse) XXX_Size() int {
+ return xxx_messageInfo_GetExchangeInfoResponse.Size(m)
+}
+func (m *GetExchangeInfoResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetExchangeInfoResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetExchangeInfoResponse proto.InternalMessageInfo
+
+func (m *GetExchangeInfoResponse) GetName() string {
+ if m != nil {
+ return m.Name
}
return ""
}
-func (x *GetExchangeInfoResponse) GetEnabled() bool {
- if x != nil {
- return x.Enabled
+func (m *GetExchangeInfoResponse) GetEnabled() bool {
+ if m != nil {
+ return m.Enabled
}
return false
}
-func (x *GetExchangeInfoResponse) GetVerbose() bool {
- if x != nil {
- return x.Verbose
+func (m *GetExchangeInfoResponse) GetVerbose() bool {
+ if m != nil {
+ return m.Verbose
}
return false
}
-func (x *GetExchangeInfoResponse) GetUsingSandbox() bool {
- if x != nil {
- return x.UsingSandbox
+func (m *GetExchangeInfoResponse) GetUsingSandbox() bool {
+ if m != nil {
+ return m.UsingSandbox
}
return false
}
-func (x *GetExchangeInfoResponse) GetHttpTimeout() string {
- if x != nil {
- return x.HttpTimeout
+func (m *GetExchangeInfoResponse) GetHttpTimeout() string {
+ if m != nil {
+ return m.HttpTimeout
}
return ""
}
-func (x *GetExchangeInfoResponse) GetHttpUseragent() string {
- if x != nil {
- return x.HttpUseragent
+func (m *GetExchangeInfoResponse) GetHttpUseragent() string {
+ if m != nil {
+ return m.HttpUseragent
}
return ""
}
-func (x *GetExchangeInfoResponse) GetHttpProxy() string {
- if x != nil {
- return x.HttpProxy
+func (m *GetExchangeInfoResponse) GetHttpProxy() string {
+ if m != nil {
+ return m.HttpProxy
}
return ""
}
-func (x *GetExchangeInfoResponse) GetBaseCurrencies() string {
- if x != nil {
- return x.BaseCurrencies
+func (m *GetExchangeInfoResponse) GetBaseCurrencies() string {
+ if m != nil {
+ return m.BaseCurrencies
}
return ""
}
-func (x *GetExchangeInfoResponse) GetSupportedAssets() map[string]*PairsSupported {
- if x != nil {
- return x.SupportedAssets
+func (m *GetExchangeInfoResponse) GetSupportedAssets() map[string]*PairsSupported {
+ if m != nil {
+ return m.SupportedAssets
}
return nil
}
-func (x *GetExchangeInfoResponse) GetAuthenticatedApi() bool {
- if x != nil {
- return x.AuthenticatedApi
+func (m *GetExchangeInfoResponse) GetAuthenticatedApi() bool {
+ if m != nil {
+ return m.AuthenticatedApi
}
return false
}
type GetTickerRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
- Pair *CurrencyPair `protobuf:"bytes,2,opt,name=pair,proto3" json:"pair,omitempty"`
- AssetType string `protobuf:"bytes,3,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Pair *CurrencyPair `protobuf:"bytes,2,opt,name=pair,proto3" json:"pair,omitempty"`
+ AssetType string `protobuf:"bytes,3,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetTickerRequest) Reset() {
- *x = GetTickerRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[22]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetTickerRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetTickerRequest) ProtoMessage() {}
-
-func (x *GetTickerRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[22]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetTickerRequest.ProtoReflect.Descriptor instead.
+func (m *GetTickerRequest) Reset() { *m = GetTickerRequest{} }
+func (m *GetTickerRequest) String() string { return proto.CompactTextString(m) }
+func (*GetTickerRequest) ProtoMessage() {}
func (*GetTickerRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{22}
+ return fileDescriptor_77a6da22d6a3feb1, []int{20}
}
-func (x *GetTickerRequest) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *GetTickerRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetTickerRequest.Unmarshal(m, b)
+}
+func (m *GetTickerRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetTickerRequest.Marshal(b, m, deterministic)
+}
+func (m *GetTickerRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetTickerRequest.Merge(m, src)
+}
+func (m *GetTickerRequest) XXX_Size() int {
+ return xxx_messageInfo_GetTickerRequest.Size(m)
+}
+func (m *GetTickerRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetTickerRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetTickerRequest proto.InternalMessageInfo
+
+func (m *GetTickerRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
-func (x *GetTickerRequest) GetPair() *CurrencyPair {
- if x != nil {
- return x.Pair
+func (m *GetTickerRequest) GetPair() *CurrencyPair {
+ if m != nil {
+ return m.Pair
}
return nil
}
-func (x *GetTickerRequest) GetAssetType() string {
- if x != nil {
- return x.AssetType
+func (m *GetTickerRequest) GetAssetType() string {
+ if m != nil {
+ return m.AssetType
}
return ""
}
type CurrencyPair struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Delimiter string `protobuf:"bytes,1,opt,name=delimiter,proto3" json:"delimiter,omitempty"`
- Base string `protobuf:"bytes,2,opt,name=base,proto3" json:"base,omitempty"`
- Quote string `protobuf:"bytes,3,opt,name=quote,proto3" json:"quote,omitempty"`
+ Delimiter string `protobuf:"bytes,1,opt,name=delimiter,proto3" json:"delimiter,omitempty"`
+ Base string `protobuf:"bytes,2,opt,name=base,proto3" json:"base,omitempty"`
+ Quote string `protobuf:"bytes,3,opt,name=quote,proto3" json:"quote,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *CurrencyPair) Reset() {
- *x = CurrencyPair{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[23]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *CurrencyPair) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*CurrencyPair) ProtoMessage() {}
-
-func (x *CurrencyPair) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[23]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use CurrencyPair.ProtoReflect.Descriptor instead.
+func (m *CurrencyPair) Reset() { *m = CurrencyPair{} }
+func (m *CurrencyPair) String() string { return proto.CompactTextString(m) }
+func (*CurrencyPair) ProtoMessage() {}
func (*CurrencyPair) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{23}
+ return fileDescriptor_77a6da22d6a3feb1, []int{21}
}
-func (x *CurrencyPair) GetDelimiter() string {
- if x != nil {
- return x.Delimiter
+func (m *CurrencyPair) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_CurrencyPair.Unmarshal(m, b)
+}
+func (m *CurrencyPair) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_CurrencyPair.Marshal(b, m, deterministic)
+}
+func (m *CurrencyPair) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_CurrencyPair.Merge(m, src)
+}
+func (m *CurrencyPair) XXX_Size() int {
+ return xxx_messageInfo_CurrencyPair.Size(m)
+}
+func (m *CurrencyPair) XXX_DiscardUnknown() {
+ xxx_messageInfo_CurrencyPair.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_CurrencyPair proto.InternalMessageInfo
+
+func (m *CurrencyPair) GetDelimiter() string {
+ if m != nil {
+ return m.Delimiter
}
return ""
}
-func (x *CurrencyPair) GetBase() string {
- if x != nil {
- return x.Base
+func (m *CurrencyPair) GetBase() string {
+ if m != nil {
+ return m.Base
}
return ""
}
-func (x *CurrencyPair) GetQuote() string {
- if x != nil {
- return x.Quote
+func (m *CurrencyPair) GetQuote() string {
+ if m != nil {
+ return m.Quote
}
return ""
}
type TickerResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Pair *CurrencyPair `protobuf:"bytes,1,opt,name=pair,proto3" json:"pair,omitempty"`
- LastUpdated int64 `protobuf:"varint,2,opt,name=last_updated,json=lastUpdated,proto3" json:"last_updated,omitempty"`
- CurrencyPair string `protobuf:"bytes,3,opt,name=currency_pair,json=currencyPair,proto3" json:"currency_pair,omitempty"`
- Last float64 `protobuf:"fixed64,4,opt,name=last,proto3" json:"last,omitempty"`
- High float64 `protobuf:"fixed64,5,opt,name=high,proto3" json:"high,omitempty"`
- Low float64 `protobuf:"fixed64,6,opt,name=low,proto3" json:"low,omitempty"`
- Bid float64 `protobuf:"fixed64,7,opt,name=bid,proto3" json:"bid,omitempty"`
- Ask float64 `protobuf:"fixed64,8,opt,name=ask,proto3" json:"ask,omitempty"`
- Volume float64 `protobuf:"fixed64,9,opt,name=volume,proto3" json:"volume,omitempty"`
- PriceAth float64 `protobuf:"fixed64,10,opt,name=price_ath,json=priceAth,proto3" json:"price_ath,omitempty"`
+ Pair *CurrencyPair `protobuf:"bytes,1,opt,name=pair,proto3" json:"pair,omitempty"`
+ LastUpdated int64 `protobuf:"varint,2,opt,name=last_updated,json=lastUpdated,proto3" json:"last_updated,omitempty"`
+ CurrencyPair string `protobuf:"bytes,3,opt,name=currency_pair,json=currencyPair,proto3" json:"currency_pair,omitempty"`
+ Last float64 `protobuf:"fixed64,4,opt,name=last,proto3" json:"last,omitempty"`
+ High float64 `protobuf:"fixed64,5,opt,name=high,proto3" json:"high,omitempty"`
+ Low float64 `protobuf:"fixed64,6,opt,name=low,proto3" json:"low,omitempty"`
+ Bid float64 `protobuf:"fixed64,7,opt,name=bid,proto3" json:"bid,omitempty"`
+ Ask float64 `protobuf:"fixed64,8,opt,name=ask,proto3" json:"ask,omitempty"`
+ Volume float64 `protobuf:"fixed64,9,opt,name=volume,proto3" json:"volume,omitempty"`
+ PriceAth float64 `protobuf:"fixed64,10,opt,name=price_ath,json=priceAth,proto3" json:"price_ath,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *TickerResponse) Reset() {
- *x = TickerResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[24]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *TickerResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*TickerResponse) ProtoMessage() {}
-
-func (x *TickerResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[24]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use TickerResponse.ProtoReflect.Descriptor instead.
+func (m *TickerResponse) Reset() { *m = TickerResponse{} }
+func (m *TickerResponse) String() string { return proto.CompactTextString(m) }
+func (*TickerResponse) ProtoMessage() {}
func (*TickerResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{24}
+ return fileDescriptor_77a6da22d6a3feb1, []int{22}
}
-func (x *TickerResponse) GetPair() *CurrencyPair {
- if x != nil {
- return x.Pair
+func (m *TickerResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_TickerResponse.Unmarshal(m, b)
+}
+func (m *TickerResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_TickerResponse.Marshal(b, m, deterministic)
+}
+func (m *TickerResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_TickerResponse.Merge(m, src)
+}
+func (m *TickerResponse) XXX_Size() int {
+ return xxx_messageInfo_TickerResponse.Size(m)
+}
+func (m *TickerResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_TickerResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_TickerResponse proto.InternalMessageInfo
+
+func (m *TickerResponse) GetPair() *CurrencyPair {
+ if m != nil {
+ return m.Pair
}
return nil
}
-func (x *TickerResponse) GetLastUpdated() int64 {
- if x != nil {
- return x.LastUpdated
+func (m *TickerResponse) GetLastUpdated() int64 {
+ if m != nil {
+ return m.LastUpdated
}
return 0
}
-func (x *TickerResponse) GetCurrencyPair() string {
- if x != nil {
- return x.CurrencyPair
+func (m *TickerResponse) GetCurrencyPair() string {
+ if m != nil {
+ return m.CurrencyPair
}
return ""
}
-func (x *TickerResponse) GetLast() float64 {
- if x != nil {
- return x.Last
+func (m *TickerResponse) GetLast() float64 {
+ if m != nil {
+ return m.Last
}
return 0
}
-func (x *TickerResponse) GetHigh() float64 {
- if x != nil {
- return x.High
+func (m *TickerResponse) GetHigh() float64 {
+ if m != nil {
+ return m.High
}
return 0
}
-func (x *TickerResponse) GetLow() float64 {
- if x != nil {
- return x.Low
+func (m *TickerResponse) GetLow() float64 {
+ if m != nil {
+ return m.Low
}
return 0
}
-func (x *TickerResponse) GetBid() float64 {
- if x != nil {
- return x.Bid
+func (m *TickerResponse) GetBid() float64 {
+ if m != nil {
+ return m.Bid
}
return 0
}
-func (x *TickerResponse) GetAsk() float64 {
- if x != nil {
- return x.Ask
+func (m *TickerResponse) GetAsk() float64 {
+ if m != nil {
+ return m.Ask
}
return 0
}
-func (x *TickerResponse) GetVolume() float64 {
- if x != nil {
- return x.Volume
+func (m *TickerResponse) GetVolume() float64 {
+ if m != nil {
+ return m.Volume
}
return 0
}
-func (x *TickerResponse) GetPriceAth() float64 {
- if x != nil {
- return x.PriceAth
+func (m *TickerResponse) GetPriceAth() float64 {
+ if m != nil {
+ return m.PriceAth
}
return 0
}
type GetTickersRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetTickersRequest) Reset() {
- *x = GetTickersRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[25]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetTickersRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetTickersRequest) ProtoMessage() {}
-
-func (x *GetTickersRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[25]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetTickersRequest.ProtoReflect.Descriptor instead.
+func (m *GetTickersRequest) Reset() { *m = GetTickersRequest{} }
+func (m *GetTickersRequest) String() string { return proto.CompactTextString(m) }
+func (*GetTickersRequest) ProtoMessage() {}
func (*GetTickersRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{25}
+ return fileDescriptor_77a6da22d6a3feb1, []int{23}
}
+func (m *GetTickersRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetTickersRequest.Unmarshal(m, b)
+}
+func (m *GetTickersRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetTickersRequest.Marshal(b, m, deterministic)
+}
+func (m *GetTickersRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetTickersRequest.Merge(m, src)
+}
+func (m *GetTickersRequest) XXX_Size() int {
+ return xxx_messageInfo_GetTickersRequest.Size(m)
+}
+func (m *GetTickersRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetTickersRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetTickersRequest proto.InternalMessageInfo
+
type Tickers struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
- Tickers []*TickerResponse `protobuf:"bytes,2,rep,name=tickers,proto3" json:"tickers,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Tickers []*TickerResponse `protobuf:"bytes,2,rep,name=tickers,proto3" json:"tickers,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *Tickers) Reset() {
- *x = Tickers{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[26]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *Tickers) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Tickers) ProtoMessage() {}
-
-func (x *Tickers) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[26]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use Tickers.ProtoReflect.Descriptor instead.
+func (m *Tickers) Reset() { *m = Tickers{} }
+func (m *Tickers) String() string { return proto.CompactTextString(m) }
+func (*Tickers) ProtoMessage() {}
func (*Tickers) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{26}
+ return fileDescriptor_77a6da22d6a3feb1, []int{24}
}
-func (x *Tickers) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *Tickers) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Tickers.Unmarshal(m, b)
+}
+func (m *Tickers) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Tickers.Marshal(b, m, deterministic)
+}
+func (m *Tickers) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Tickers.Merge(m, src)
+}
+func (m *Tickers) XXX_Size() int {
+ return xxx_messageInfo_Tickers.Size(m)
+}
+func (m *Tickers) XXX_DiscardUnknown() {
+ xxx_messageInfo_Tickers.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Tickers proto.InternalMessageInfo
+
+func (m *Tickers) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
-func (x *Tickers) GetTickers() []*TickerResponse {
- if x != nil {
- return x.Tickers
+func (m *Tickers) GetTickers() []*TickerResponse {
+ if m != nil {
+ return m.Tickers
}
return nil
}
type GetTickersResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Tickers []*Tickers `protobuf:"bytes,1,rep,name=tickers,proto3" json:"tickers,omitempty"`
+ Tickers []*Tickers `protobuf:"bytes,1,rep,name=tickers,proto3" json:"tickers,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetTickersResponse) Reset() {
- *x = GetTickersResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[27]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetTickersResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetTickersResponse) ProtoMessage() {}
-
-func (x *GetTickersResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[27]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetTickersResponse.ProtoReflect.Descriptor instead.
+func (m *GetTickersResponse) Reset() { *m = GetTickersResponse{} }
+func (m *GetTickersResponse) String() string { return proto.CompactTextString(m) }
+func (*GetTickersResponse) ProtoMessage() {}
func (*GetTickersResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{27}
+ return fileDescriptor_77a6da22d6a3feb1, []int{25}
}
-func (x *GetTickersResponse) GetTickers() []*Tickers {
- if x != nil {
- return x.Tickers
+func (m *GetTickersResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetTickersResponse.Unmarshal(m, b)
+}
+func (m *GetTickersResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetTickersResponse.Marshal(b, m, deterministic)
+}
+func (m *GetTickersResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetTickersResponse.Merge(m, src)
+}
+func (m *GetTickersResponse) XXX_Size() int {
+ return xxx_messageInfo_GetTickersResponse.Size(m)
+}
+func (m *GetTickersResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetTickersResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetTickersResponse proto.InternalMessageInfo
+
+func (m *GetTickersResponse) GetTickers() []*Tickers {
+ if m != nil {
+ return m.Tickers
}
return nil
}
type GetOrderbookRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
- Pair *CurrencyPair `protobuf:"bytes,2,opt,name=pair,proto3" json:"pair,omitempty"`
- AssetType string `protobuf:"bytes,3,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Pair *CurrencyPair `protobuf:"bytes,2,opt,name=pair,proto3" json:"pair,omitempty"`
+ AssetType string `protobuf:"bytes,3,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetOrderbookRequest) Reset() {
- *x = GetOrderbookRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[28]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetOrderbookRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetOrderbookRequest) ProtoMessage() {}
-
-func (x *GetOrderbookRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[28]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetOrderbookRequest.ProtoReflect.Descriptor instead.
+func (m *GetOrderbookRequest) Reset() { *m = GetOrderbookRequest{} }
+func (m *GetOrderbookRequest) String() string { return proto.CompactTextString(m) }
+func (*GetOrderbookRequest) ProtoMessage() {}
func (*GetOrderbookRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{28}
+ return fileDescriptor_77a6da22d6a3feb1, []int{26}
}
-func (x *GetOrderbookRequest) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *GetOrderbookRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetOrderbookRequest.Unmarshal(m, b)
+}
+func (m *GetOrderbookRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetOrderbookRequest.Marshal(b, m, deterministic)
+}
+func (m *GetOrderbookRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetOrderbookRequest.Merge(m, src)
+}
+func (m *GetOrderbookRequest) XXX_Size() int {
+ return xxx_messageInfo_GetOrderbookRequest.Size(m)
+}
+func (m *GetOrderbookRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetOrderbookRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetOrderbookRequest proto.InternalMessageInfo
+
+func (m *GetOrderbookRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
-func (x *GetOrderbookRequest) GetPair() *CurrencyPair {
- if x != nil {
- return x.Pair
+func (m *GetOrderbookRequest) GetPair() *CurrencyPair {
+ if m != nil {
+ return m.Pair
}
return nil
}
-func (x *GetOrderbookRequest) GetAssetType() string {
- if x != nil {
- return x.AssetType
+func (m *GetOrderbookRequest) GetAssetType() string {
+ if m != nil {
+ return m.AssetType
}
return ""
}
type OrderbookItem struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Amount float64 `protobuf:"fixed64,1,opt,name=amount,proto3" json:"amount,omitempty"`
- Price float64 `protobuf:"fixed64,2,opt,name=price,proto3" json:"price,omitempty"`
- Id int64 `protobuf:"varint,3,opt,name=id,proto3" json:"id,omitempty"`
+ Amount float64 `protobuf:"fixed64,1,opt,name=amount,proto3" json:"amount,omitempty"`
+ Price float64 `protobuf:"fixed64,2,opt,name=price,proto3" json:"price,omitempty"`
+ Id int64 `protobuf:"varint,3,opt,name=id,proto3" json:"id,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *OrderbookItem) Reset() {
- *x = OrderbookItem{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[29]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *OrderbookItem) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*OrderbookItem) ProtoMessage() {}
-
-func (x *OrderbookItem) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[29]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use OrderbookItem.ProtoReflect.Descriptor instead.
+func (m *OrderbookItem) Reset() { *m = OrderbookItem{} }
+func (m *OrderbookItem) String() string { return proto.CompactTextString(m) }
+func (*OrderbookItem) ProtoMessage() {}
func (*OrderbookItem) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{29}
+ return fileDescriptor_77a6da22d6a3feb1, []int{27}
}
-func (x *OrderbookItem) GetAmount() float64 {
- if x != nil {
- return x.Amount
+func (m *OrderbookItem) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_OrderbookItem.Unmarshal(m, b)
+}
+func (m *OrderbookItem) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_OrderbookItem.Marshal(b, m, deterministic)
+}
+func (m *OrderbookItem) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_OrderbookItem.Merge(m, src)
+}
+func (m *OrderbookItem) XXX_Size() int {
+ return xxx_messageInfo_OrderbookItem.Size(m)
+}
+func (m *OrderbookItem) XXX_DiscardUnknown() {
+ xxx_messageInfo_OrderbookItem.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_OrderbookItem proto.InternalMessageInfo
+
+func (m *OrderbookItem) GetAmount() float64 {
+ if m != nil {
+ return m.Amount
}
return 0
}
-func (x *OrderbookItem) GetPrice() float64 {
- if x != nil {
- return x.Price
+func (m *OrderbookItem) GetPrice() float64 {
+ if m != nil {
+ return m.Price
}
return 0
}
-func (x *OrderbookItem) GetId() int64 {
- if x != nil {
- return x.Id
+func (m *OrderbookItem) GetId() int64 {
+ if m != nil {
+ return m.Id
}
return 0
}
type OrderbookResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Pair *CurrencyPair `protobuf:"bytes,1,opt,name=pair,proto3" json:"pair,omitempty"`
- CurrencyPair string `protobuf:"bytes,2,opt,name=currency_pair,json=currencyPair,proto3" json:"currency_pair,omitempty"`
- Bids []*OrderbookItem `protobuf:"bytes,3,rep,name=bids,proto3" json:"bids,omitempty"`
- Asks []*OrderbookItem `protobuf:"bytes,4,rep,name=asks,proto3" json:"asks,omitempty"`
- LastUpdated int64 `protobuf:"varint,5,opt,name=last_updated,json=lastUpdated,proto3" json:"last_updated,omitempty"`
- AssetType string `protobuf:"bytes,6,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"`
+ Pair *CurrencyPair `protobuf:"bytes,1,opt,name=pair,proto3" json:"pair,omitempty"`
+ CurrencyPair string `protobuf:"bytes,2,opt,name=currency_pair,json=currencyPair,proto3" json:"currency_pair,omitempty"`
+ Bids []*OrderbookItem `protobuf:"bytes,3,rep,name=bids,proto3" json:"bids,omitempty"`
+ Asks []*OrderbookItem `protobuf:"bytes,4,rep,name=asks,proto3" json:"asks,omitempty"`
+ LastUpdated int64 `protobuf:"varint,5,opt,name=last_updated,json=lastUpdated,proto3" json:"last_updated,omitempty"`
+ AssetType string `protobuf:"bytes,6,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *OrderbookResponse) Reset() {
- *x = OrderbookResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[30]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *OrderbookResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*OrderbookResponse) ProtoMessage() {}
-
-func (x *OrderbookResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[30]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use OrderbookResponse.ProtoReflect.Descriptor instead.
+func (m *OrderbookResponse) Reset() { *m = OrderbookResponse{} }
+func (m *OrderbookResponse) String() string { return proto.CompactTextString(m) }
+func (*OrderbookResponse) ProtoMessage() {}
func (*OrderbookResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{30}
+ return fileDescriptor_77a6da22d6a3feb1, []int{28}
}
-func (x *OrderbookResponse) GetPair() *CurrencyPair {
- if x != nil {
- return x.Pair
+func (m *OrderbookResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_OrderbookResponse.Unmarshal(m, b)
+}
+func (m *OrderbookResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_OrderbookResponse.Marshal(b, m, deterministic)
+}
+func (m *OrderbookResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_OrderbookResponse.Merge(m, src)
+}
+func (m *OrderbookResponse) XXX_Size() int {
+ return xxx_messageInfo_OrderbookResponse.Size(m)
+}
+func (m *OrderbookResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_OrderbookResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_OrderbookResponse proto.InternalMessageInfo
+
+func (m *OrderbookResponse) GetPair() *CurrencyPair {
+ if m != nil {
+ return m.Pair
}
return nil
}
-func (x *OrderbookResponse) GetCurrencyPair() string {
- if x != nil {
- return x.CurrencyPair
+func (m *OrderbookResponse) GetCurrencyPair() string {
+ if m != nil {
+ return m.CurrencyPair
}
return ""
}
-func (x *OrderbookResponse) GetBids() []*OrderbookItem {
- if x != nil {
- return x.Bids
+func (m *OrderbookResponse) GetBids() []*OrderbookItem {
+ if m != nil {
+ return m.Bids
}
return nil
}
-func (x *OrderbookResponse) GetAsks() []*OrderbookItem {
- if x != nil {
- return x.Asks
+func (m *OrderbookResponse) GetAsks() []*OrderbookItem {
+ if m != nil {
+ return m.Asks
}
return nil
}
-func (x *OrderbookResponse) GetLastUpdated() int64 {
- if x != nil {
- return x.LastUpdated
+func (m *OrderbookResponse) GetLastUpdated() int64 {
+ if m != nil {
+ return m.LastUpdated
}
return 0
}
-func (x *OrderbookResponse) GetAssetType() string {
- if x != nil {
- return x.AssetType
+func (m *OrderbookResponse) GetAssetType() string {
+ if m != nil {
+ return m.AssetType
}
return ""
}
type GetOrderbooksRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetOrderbooksRequest) Reset() {
- *x = GetOrderbooksRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[31]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetOrderbooksRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetOrderbooksRequest) ProtoMessage() {}
-
-func (x *GetOrderbooksRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[31]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetOrderbooksRequest.ProtoReflect.Descriptor instead.
+func (m *GetOrderbooksRequest) Reset() { *m = GetOrderbooksRequest{} }
+func (m *GetOrderbooksRequest) String() string { return proto.CompactTextString(m) }
+func (*GetOrderbooksRequest) ProtoMessage() {}
func (*GetOrderbooksRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{31}
+ return fileDescriptor_77a6da22d6a3feb1, []int{29}
}
+func (m *GetOrderbooksRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetOrderbooksRequest.Unmarshal(m, b)
+}
+func (m *GetOrderbooksRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetOrderbooksRequest.Marshal(b, m, deterministic)
+}
+func (m *GetOrderbooksRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetOrderbooksRequest.Merge(m, src)
+}
+func (m *GetOrderbooksRequest) XXX_Size() int {
+ return xxx_messageInfo_GetOrderbooksRequest.Size(m)
+}
+func (m *GetOrderbooksRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetOrderbooksRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetOrderbooksRequest proto.InternalMessageInfo
+
type Orderbooks struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
- Orderbooks []*OrderbookResponse `protobuf:"bytes,2,rep,name=orderbooks,proto3" json:"orderbooks,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Orderbooks []*OrderbookResponse `protobuf:"bytes,2,rep,name=orderbooks,proto3" json:"orderbooks,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *Orderbooks) Reset() {
- *x = Orderbooks{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[32]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *Orderbooks) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Orderbooks) ProtoMessage() {}
-
-func (x *Orderbooks) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[32]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use Orderbooks.ProtoReflect.Descriptor instead.
+func (m *Orderbooks) Reset() { *m = Orderbooks{} }
+func (m *Orderbooks) String() string { return proto.CompactTextString(m) }
+func (*Orderbooks) ProtoMessage() {}
func (*Orderbooks) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{32}
+ return fileDescriptor_77a6da22d6a3feb1, []int{30}
}
-func (x *Orderbooks) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *Orderbooks) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Orderbooks.Unmarshal(m, b)
+}
+func (m *Orderbooks) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Orderbooks.Marshal(b, m, deterministic)
+}
+func (m *Orderbooks) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Orderbooks.Merge(m, src)
+}
+func (m *Orderbooks) XXX_Size() int {
+ return xxx_messageInfo_Orderbooks.Size(m)
+}
+func (m *Orderbooks) XXX_DiscardUnknown() {
+ xxx_messageInfo_Orderbooks.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Orderbooks proto.InternalMessageInfo
+
+func (m *Orderbooks) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
-func (x *Orderbooks) GetOrderbooks() []*OrderbookResponse {
- if x != nil {
- return x.Orderbooks
+func (m *Orderbooks) GetOrderbooks() []*OrderbookResponse {
+ if m != nil {
+ return m.Orderbooks
}
return nil
}
type GetOrderbooksResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Orderbooks []*Orderbooks `protobuf:"bytes,1,rep,name=orderbooks,proto3" json:"orderbooks,omitempty"`
+ Orderbooks []*Orderbooks `protobuf:"bytes,1,rep,name=orderbooks,proto3" json:"orderbooks,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetOrderbooksResponse) Reset() {
- *x = GetOrderbooksResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[33]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetOrderbooksResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetOrderbooksResponse) ProtoMessage() {}
-
-func (x *GetOrderbooksResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[33]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetOrderbooksResponse.ProtoReflect.Descriptor instead.
+func (m *GetOrderbooksResponse) Reset() { *m = GetOrderbooksResponse{} }
+func (m *GetOrderbooksResponse) String() string { return proto.CompactTextString(m) }
+func (*GetOrderbooksResponse) ProtoMessage() {}
func (*GetOrderbooksResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{33}
+ return fileDescriptor_77a6da22d6a3feb1, []int{31}
}
-func (x *GetOrderbooksResponse) GetOrderbooks() []*Orderbooks {
- if x != nil {
- return x.Orderbooks
+func (m *GetOrderbooksResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetOrderbooksResponse.Unmarshal(m, b)
+}
+func (m *GetOrderbooksResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetOrderbooksResponse.Marshal(b, m, deterministic)
+}
+func (m *GetOrderbooksResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetOrderbooksResponse.Merge(m, src)
+}
+func (m *GetOrderbooksResponse) XXX_Size() int {
+ return xxx_messageInfo_GetOrderbooksResponse.Size(m)
+}
+func (m *GetOrderbooksResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetOrderbooksResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetOrderbooksResponse proto.InternalMessageInfo
+
+func (m *GetOrderbooksResponse) GetOrderbooks() []*Orderbooks {
+ if m != nil {
+ return m.Orderbooks
}
return nil
}
type GetAccountInfoRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetAccountInfoRequest) Reset() {
- *x = GetAccountInfoRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[34]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetAccountInfoRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetAccountInfoRequest) ProtoMessage() {}
-
-func (x *GetAccountInfoRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[34]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetAccountInfoRequest.ProtoReflect.Descriptor instead.
+func (m *GetAccountInfoRequest) Reset() { *m = GetAccountInfoRequest{} }
+func (m *GetAccountInfoRequest) String() string { return proto.CompactTextString(m) }
+func (*GetAccountInfoRequest) ProtoMessage() {}
func (*GetAccountInfoRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{34}
+ return fileDescriptor_77a6da22d6a3feb1, []int{32}
}
-func (x *GetAccountInfoRequest) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *GetAccountInfoRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetAccountInfoRequest.Unmarshal(m, b)
+}
+func (m *GetAccountInfoRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetAccountInfoRequest.Marshal(b, m, deterministic)
+}
+func (m *GetAccountInfoRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetAccountInfoRequest.Merge(m, src)
+}
+func (m *GetAccountInfoRequest) XXX_Size() int {
+ return xxx_messageInfo_GetAccountInfoRequest.Size(m)
+}
+func (m *GetAccountInfoRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetAccountInfoRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetAccountInfoRequest proto.InternalMessageInfo
+
+func (m *GetAccountInfoRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
type Account struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
- Currencies []*AccountCurrencyInfo `protobuf:"bytes,2,rep,name=currencies,proto3" json:"currencies,omitempty"`
+ Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+ Currencies []*AccountCurrencyInfo `protobuf:"bytes,2,rep,name=currencies,proto3" json:"currencies,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *Account) Reset() {
- *x = Account{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[35]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *Account) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Account) ProtoMessage() {}
-
-func (x *Account) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[35]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use Account.ProtoReflect.Descriptor instead.
+func (m *Account) Reset() { *m = Account{} }
+func (m *Account) String() string { return proto.CompactTextString(m) }
+func (*Account) ProtoMessage() {}
func (*Account) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{35}
+ return fileDescriptor_77a6da22d6a3feb1, []int{33}
}
-func (x *Account) GetId() string {
- if x != nil {
- return x.Id
+func (m *Account) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Account.Unmarshal(m, b)
+}
+func (m *Account) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Account.Marshal(b, m, deterministic)
+}
+func (m *Account) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Account.Merge(m, src)
+}
+func (m *Account) XXX_Size() int {
+ return xxx_messageInfo_Account.Size(m)
+}
+func (m *Account) XXX_DiscardUnknown() {
+ xxx_messageInfo_Account.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Account proto.InternalMessageInfo
+
+func (m *Account) GetId() string {
+ if m != nil {
+ return m.Id
}
return ""
}
-func (x *Account) GetCurrencies() []*AccountCurrencyInfo {
- if x != nil {
- return x.Currencies
+func (m *Account) GetCurrencies() []*AccountCurrencyInfo {
+ if m != nil {
+ return m.Currencies
}
return nil
}
type AccountCurrencyInfo struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Currency string `protobuf:"bytes,1,opt,name=currency,proto3" json:"currency,omitempty"`
- TotalValue float64 `protobuf:"fixed64,2,opt,name=total_value,json=totalValue,proto3" json:"total_value,omitempty"`
- Hold float64 `protobuf:"fixed64,3,opt,name=hold,proto3" json:"hold,omitempty"`
+ Currency string `protobuf:"bytes,1,opt,name=currency,proto3" json:"currency,omitempty"`
+ TotalValue float64 `protobuf:"fixed64,2,opt,name=total_value,json=totalValue,proto3" json:"total_value,omitempty"`
+ Hold float64 `protobuf:"fixed64,3,opt,name=hold,proto3" json:"hold,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *AccountCurrencyInfo) Reset() {
- *x = AccountCurrencyInfo{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[36]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *AccountCurrencyInfo) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*AccountCurrencyInfo) ProtoMessage() {}
-
-func (x *AccountCurrencyInfo) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[36]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use AccountCurrencyInfo.ProtoReflect.Descriptor instead.
+func (m *AccountCurrencyInfo) Reset() { *m = AccountCurrencyInfo{} }
+func (m *AccountCurrencyInfo) String() string { return proto.CompactTextString(m) }
+func (*AccountCurrencyInfo) ProtoMessage() {}
func (*AccountCurrencyInfo) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{36}
+ return fileDescriptor_77a6da22d6a3feb1, []int{34}
}
-func (x *AccountCurrencyInfo) GetCurrency() string {
- if x != nil {
- return x.Currency
+func (m *AccountCurrencyInfo) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_AccountCurrencyInfo.Unmarshal(m, b)
+}
+func (m *AccountCurrencyInfo) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_AccountCurrencyInfo.Marshal(b, m, deterministic)
+}
+func (m *AccountCurrencyInfo) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_AccountCurrencyInfo.Merge(m, src)
+}
+func (m *AccountCurrencyInfo) XXX_Size() int {
+ return xxx_messageInfo_AccountCurrencyInfo.Size(m)
+}
+func (m *AccountCurrencyInfo) XXX_DiscardUnknown() {
+ xxx_messageInfo_AccountCurrencyInfo.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_AccountCurrencyInfo proto.InternalMessageInfo
+
+func (m *AccountCurrencyInfo) GetCurrency() string {
+ if m != nil {
+ return m.Currency
}
return ""
}
-func (x *AccountCurrencyInfo) GetTotalValue() float64 {
- if x != nil {
- return x.TotalValue
+func (m *AccountCurrencyInfo) GetTotalValue() float64 {
+ if m != nil {
+ return m.TotalValue
}
return 0
}
-func (x *AccountCurrencyInfo) GetHold() float64 {
- if x != nil {
- return x.Hold
+func (m *AccountCurrencyInfo) GetHold() float64 {
+ if m != nil {
+ return m.Hold
}
return 0
}
type GetAccountInfoResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
- Accounts []*Account `protobuf:"bytes,2,rep,name=accounts,proto3" json:"accounts,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Accounts []*Account `protobuf:"bytes,2,rep,name=accounts,proto3" json:"accounts,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetAccountInfoResponse) Reset() {
- *x = GetAccountInfoResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[37]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetAccountInfoResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetAccountInfoResponse) ProtoMessage() {}
-
-func (x *GetAccountInfoResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[37]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetAccountInfoResponse.ProtoReflect.Descriptor instead.
+func (m *GetAccountInfoResponse) Reset() { *m = GetAccountInfoResponse{} }
+func (m *GetAccountInfoResponse) String() string { return proto.CompactTextString(m) }
+func (*GetAccountInfoResponse) ProtoMessage() {}
func (*GetAccountInfoResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{37}
+ return fileDescriptor_77a6da22d6a3feb1, []int{35}
}
-func (x *GetAccountInfoResponse) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *GetAccountInfoResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetAccountInfoResponse.Unmarshal(m, b)
+}
+func (m *GetAccountInfoResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetAccountInfoResponse.Marshal(b, m, deterministic)
+}
+func (m *GetAccountInfoResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetAccountInfoResponse.Merge(m, src)
+}
+func (m *GetAccountInfoResponse) XXX_Size() int {
+ return xxx_messageInfo_GetAccountInfoResponse.Size(m)
+}
+func (m *GetAccountInfoResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetAccountInfoResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetAccountInfoResponse proto.InternalMessageInfo
+
+func (m *GetAccountInfoResponse) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
-func (x *GetAccountInfoResponse) GetAccounts() []*Account {
- if x != nil {
- return x.Accounts
+func (m *GetAccountInfoResponse) GetAccounts() []*Account {
+ if m != nil {
+ return m.Accounts
}
return nil
}
type GetConfigRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetConfigRequest) Reset() {
- *x = GetConfigRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[38]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetConfigRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetConfigRequest) ProtoMessage() {}
-
-func (x *GetConfigRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[38]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetConfigRequest.ProtoReflect.Descriptor instead.
+func (m *GetConfigRequest) Reset() { *m = GetConfigRequest{} }
+func (m *GetConfigRequest) String() string { return proto.CompactTextString(m) }
+func (*GetConfigRequest) ProtoMessage() {}
func (*GetConfigRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{38}
+ return fileDescriptor_77a6da22d6a3feb1, []int{36}
}
+func (m *GetConfigRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetConfigRequest.Unmarshal(m, b)
+}
+func (m *GetConfigRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetConfigRequest.Marshal(b, m, deterministic)
+}
+func (m *GetConfigRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetConfigRequest.Merge(m, src)
+}
+func (m *GetConfigRequest) XXX_Size() int {
+ return xxx_messageInfo_GetConfigRequest.Size(m)
+}
+func (m *GetConfigRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetConfigRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetConfigRequest proto.InternalMessageInfo
+
type GetConfigResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
+ Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetConfigResponse) Reset() {
- *x = GetConfigResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[39]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetConfigResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetConfigResponse) ProtoMessage() {}
-
-func (x *GetConfigResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[39]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetConfigResponse.ProtoReflect.Descriptor instead.
+func (m *GetConfigResponse) Reset() { *m = GetConfigResponse{} }
+func (m *GetConfigResponse) String() string { return proto.CompactTextString(m) }
+func (*GetConfigResponse) ProtoMessage() {}
func (*GetConfigResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{39}
+ return fileDescriptor_77a6da22d6a3feb1, []int{37}
}
-func (x *GetConfigResponse) GetData() []byte {
- if x != nil {
- return x.Data
+func (m *GetConfigResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetConfigResponse.Unmarshal(m, b)
+}
+func (m *GetConfigResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetConfigResponse.Marshal(b, m, deterministic)
+}
+func (m *GetConfigResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetConfigResponse.Merge(m, src)
+}
+func (m *GetConfigResponse) XXX_Size() int {
+ return xxx_messageInfo_GetConfigResponse.Size(m)
+}
+func (m *GetConfigResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetConfigResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetConfigResponse proto.InternalMessageInfo
+
+func (m *GetConfigResponse) GetData() []byte {
+ if m != nil {
+ return m.Data
}
return nil
}
type PortfolioAddress struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
- CoinType string `protobuf:"bytes,2,opt,name=coin_type,json=coinType,proto3" json:"coin_type,omitempty"`
- Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"`
- Balance float64 `protobuf:"fixed64,4,opt,name=balance,proto3" json:"balance,omitempty"`
+ Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
+ CoinType string `protobuf:"bytes,2,opt,name=coin_type,json=coinType,proto3" json:"coin_type,omitempty"`
+ Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"`
+ Balance float64 `protobuf:"fixed64,4,opt,name=balance,proto3" json:"balance,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *PortfolioAddress) Reset() {
- *x = PortfolioAddress{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[40]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *PortfolioAddress) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*PortfolioAddress) ProtoMessage() {}
-
-func (x *PortfolioAddress) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[40]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use PortfolioAddress.ProtoReflect.Descriptor instead.
+func (m *PortfolioAddress) Reset() { *m = PortfolioAddress{} }
+func (m *PortfolioAddress) String() string { return proto.CompactTextString(m) }
+func (*PortfolioAddress) ProtoMessage() {}
func (*PortfolioAddress) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{40}
+ return fileDescriptor_77a6da22d6a3feb1, []int{38}
}
-func (x *PortfolioAddress) GetAddress() string {
- if x != nil {
- return x.Address
+func (m *PortfolioAddress) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_PortfolioAddress.Unmarshal(m, b)
+}
+func (m *PortfolioAddress) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_PortfolioAddress.Marshal(b, m, deterministic)
+}
+func (m *PortfolioAddress) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_PortfolioAddress.Merge(m, src)
+}
+func (m *PortfolioAddress) XXX_Size() int {
+ return xxx_messageInfo_PortfolioAddress.Size(m)
+}
+func (m *PortfolioAddress) XXX_DiscardUnknown() {
+ xxx_messageInfo_PortfolioAddress.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_PortfolioAddress proto.InternalMessageInfo
+
+func (m *PortfolioAddress) GetAddress() string {
+ if m != nil {
+ return m.Address
}
return ""
}
-func (x *PortfolioAddress) GetCoinType() string {
- if x != nil {
- return x.CoinType
+func (m *PortfolioAddress) GetCoinType() string {
+ if m != nil {
+ return m.CoinType
}
return ""
}
-func (x *PortfolioAddress) GetDescription() string {
- if x != nil {
- return x.Description
+func (m *PortfolioAddress) GetDescription() string {
+ if m != nil {
+ return m.Description
}
return ""
}
-func (x *PortfolioAddress) GetBalance() float64 {
- if x != nil {
- return x.Balance
+func (m *PortfolioAddress) GetBalance() float64 {
+ if m != nil {
+ return m.Balance
}
return 0
}
type GetPortfolioRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetPortfolioRequest) Reset() {
- *x = GetPortfolioRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[41]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetPortfolioRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetPortfolioRequest) ProtoMessage() {}
-
-func (x *GetPortfolioRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[41]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetPortfolioRequest.ProtoReflect.Descriptor instead.
+func (m *GetPortfolioRequest) Reset() { *m = GetPortfolioRequest{} }
+func (m *GetPortfolioRequest) String() string { return proto.CompactTextString(m) }
+func (*GetPortfolioRequest) ProtoMessage() {}
func (*GetPortfolioRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{41}
+ return fileDescriptor_77a6da22d6a3feb1, []int{39}
}
+func (m *GetPortfolioRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetPortfolioRequest.Unmarshal(m, b)
+}
+func (m *GetPortfolioRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetPortfolioRequest.Marshal(b, m, deterministic)
+}
+func (m *GetPortfolioRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetPortfolioRequest.Merge(m, src)
+}
+func (m *GetPortfolioRequest) XXX_Size() int {
+ return xxx_messageInfo_GetPortfolioRequest.Size(m)
+}
+func (m *GetPortfolioRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetPortfolioRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetPortfolioRequest proto.InternalMessageInfo
+
type GetPortfolioResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Portfolio []*PortfolioAddress `protobuf:"bytes,1,rep,name=portfolio,proto3" json:"portfolio,omitempty"`
+ Portfolio []*PortfolioAddress `protobuf:"bytes,1,rep,name=portfolio,proto3" json:"portfolio,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetPortfolioResponse) Reset() {
- *x = GetPortfolioResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[42]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetPortfolioResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetPortfolioResponse) ProtoMessage() {}
-
-func (x *GetPortfolioResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[42]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetPortfolioResponse.ProtoReflect.Descriptor instead.
+func (m *GetPortfolioResponse) Reset() { *m = GetPortfolioResponse{} }
+func (m *GetPortfolioResponse) String() string { return proto.CompactTextString(m) }
+func (*GetPortfolioResponse) ProtoMessage() {}
func (*GetPortfolioResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{42}
+ return fileDescriptor_77a6da22d6a3feb1, []int{40}
}
-func (x *GetPortfolioResponse) GetPortfolio() []*PortfolioAddress {
- if x != nil {
- return x.Portfolio
+func (m *GetPortfolioResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetPortfolioResponse.Unmarshal(m, b)
+}
+func (m *GetPortfolioResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetPortfolioResponse.Marshal(b, m, deterministic)
+}
+func (m *GetPortfolioResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetPortfolioResponse.Merge(m, src)
+}
+func (m *GetPortfolioResponse) XXX_Size() int {
+ return xxx_messageInfo_GetPortfolioResponse.Size(m)
+}
+func (m *GetPortfolioResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetPortfolioResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetPortfolioResponse proto.InternalMessageInfo
+
+func (m *GetPortfolioResponse) GetPortfolio() []*PortfolioAddress {
+ if m != nil {
+ return m.Portfolio
}
return nil
}
type GetPortfolioSummaryRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetPortfolioSummaryRequest) Reset() {
- *x = GetPortfolioSummaryRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[43]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetPortfolioSummaryRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetPortfolioSummaryRequest) ProtoMessage() {}
-
-func (x *GetPortfolioSummaryRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[43]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetPortfolioSummaryRequest.ProtoReflect.Descriptor instead.
+func (m *GetPortfolioSummaryRequest) Reset() { *m = GetPortfolioSummaryRequest{} }
+func (m *GetPortfolioSummaryRequest) String() string { return proto.CompactTextString(m) }
+func (*GetPortfolioSummaryRequest) ProtoMessage() {}
func (*GetPortfolioSummaryRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{43}
+ return fileDescriptor_77a6da22d6a3feb1, []int{41}
}
+func (m *GetPortfolioSummaryRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetPortfolioSummaryRequest.Unmarshal(m, b)
+}
+func (m *GetPortfolioSummaryRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetPortfolioSummaryRequest.Marshal(b, m, deterministic)
+}
+func (m *GetPortfolioSummaryRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetPortfolioSummaryRequest.Merge(m, src)
+}
+func (m *GetPortfolioSummaryRequest) XXX_Size() int {
+ return xxx_messageInfo_GetPortfolioSummaryRequest.Size(m)
+}
+func (m *GetPortfolioSummaryRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetPortfolioSummaryRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetPortfolioSummaryRequest proto.InternalMessageInfo
+
type Coin struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Coin string `protobuf:"bytes,1,opt,name=coin,proto3" json:"coin,omitempty"`
- Balance float64 `protobuf:"fixed64,2,opt,name=balance,proto3" json:"balance,omitempty"`
- Address string `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"`
- Percentage float64 `protobuf:"fixed64,4,opt,name=percentage,proto3" json:"percentage,omitempty"`
+ Coin string `protobuf:"bytes,1,opt,name=coin,proto3" json:"coin,omitempty"`
+ Balance float64 `protobuf:"fixed64,2,opt,name=balance,proto3" json:"balance,omitempty"`
+ Address string `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"`
+ Percentage float64 `protobuf:"fixed64,4,opt,name=percentage,proto3" json:"percentage,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *Coin) Reset() {
- *x = Coin{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[44]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *Coin) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Coin) ProtoMessage() {}
-
-func (x *Coin) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[44]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use Coin.ProtoReflect.Descriptor instead.
+func (m *Coin) Reset() { *m = Coin{} }
+func (m *Coin) String() string { return proto.CompactTextString(m) }
+func (*Coin) ProtoMessage() {}
func (*Coin) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{44}
+ return fileDescriptor_77a6da22d6a3feb1, []int{42}
}
-func (x *Coin) GetCoin() string {
- if x != nil {
- return x.Coin
+func (m *Coin) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Coin.Unmarshal(m, b)
+}
+func (m *Coin) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Coin.Marshal(b, m, deterministic)
+}
+func (m *Coin) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Coin.Merge(m, src)
+}
+func (m *Coin) XXX_Size() int {
+ return xxx_messageInfo_Coin.Size(m)
+}
+func (m *Coin) XXX_DiscardUnknown() {
+ xxx_messageInfo_Coin.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Coin proto.InternalMessageInfo
+
+func (m *Coin) GetCoin() string {
+ if m != nil {
+ return m.Coin
}
return ""
}
-func (x *Coin) GetBalance() float64 {
- if x != nil {
- return x.Balance
+func (m *Coin) GetBalance() float64 {
+ if m != nil {
+ return m.Balance
}
return 0
}
-func (x *Coin) GetAddress() string {
- if x != nil {
- return x.Address
+func (m *Coin) GetAddress() string {
+ if m != nil {
+ return m.Address
}
return ""
}
-func (x *Coin) GetPercentage() float64 {
- if x != nil {
- return x.Percentage
+func (m *Coin) GetPercentage() float64 {
+ if m != nil {
+ return m.Percentage
}
return 0
}
type OfflineCoinSummary struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
- Balance float64 `protobuf:"fixed64,2,opt,name=balance,proto3" json:"balance,omitempty"`
- Percentage float64 `protobuf:"fixed64,3,opt,name=percentage,proto3" json:"percentage,omitempty"`
+ Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
+ Balance float64 `protobuf:"fixed64,2,opt,name=balance,proto3" json:"balance,omitempty"`
+ Percentage float64 `protobuf:"fixed64,3,opt,name=percentage,proto3" json:"percentage,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *OfflineCoinSummary) Reset() {
- *x = OfflineCoinSummary{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[45]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *OfflineCoinSummary) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*OfflineCoinSummary) ProtoMessage() {}
-
-func (x *OfflineCoinSummary) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[45]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use OfflineCoinSummary.ProtoReflect.Descriptor instead.
+func (m *OfflineCoinSummary) Reset() { *m = OfflineCoinSummary{} }
+func (m *OfflineCoinSummary) String() string { return proto.CompactTextString(m) }
+func (*OfflineCoinSummary) ProtoMessage() {}
func (*OfflineCoinSummary) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{45}
+ return fileDescriptor_77a6da22d6a3feb1, []int{43}
}
-func (x *OfflineCoinSummary) GetAddress() string {
- if x != nil {
- return x.Address
+func (m *OfflineCoinSummary) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_OfflineCoinSummary.Unmarshal(m, b)
+}
+func (m *OfflineCoinSummary) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_OfflineCoinSummary.Marshal(b, m, deterministic)
+}
+func (m *OfflineCoinSummary) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_OfflineCoinSummary.Merge(m, src)
+}
+func (m *OfflineCoinSummary) XXX_Size() int {
+ return xxx_messageInfo_OfflineCoinSummary.Size(m)
+}
+func (m *OfflineCoinSummary) XXX_DiscardUnknown() {
+ xxx_messageInfo_OfflineCoinSummary.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_OfflineCoinSummary proto.InternalMessageInfo
+
+func (m *OfflineCoinSummary) GetAddress() string {
+ if m != nil {
+ return m.Address
}
return ""
}
-func (x *OfflineCoinSummary) GetBalance() float64 {
- if x != nil {
- return x.Balance
+func (m *OfflineCoinSummary) GetBalance() float64 {
+ if m != nil {
+ return m.Balance
}
return 0
}
-func (x *OfflineCoinSummary) GetPercentage() float64 {
- if x != nil {
- return x.Percentage
+func (m *OfflineCoinSummary) GetPercentage() float64 {
+ if m != nil {
+ return m.Percentage
}
return 0
}
type OnlineCoinSummary struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Balance float64 `protobuf:"fixed64,1,opt,name=balance,proto3" json:"balance,omitempty"`
- Percentage float64 `protobuf:"fixed64,2,opt,name=percentage,proto3" json:"percentage,omitempty"`
+ Balance float64 `protobuf:"fixed64,1,opt,name=balance,proto3" json:"balance,omitempty"`
+ Percentage float64 `protobuf:"fixed64,2,opt,name=percentage,proto3" json:"percentage,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *OnlineCoinSummary) Reset() {
- *x = OnlineCoinSummary{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[46]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *OnlineCoinSummary) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*OnlineCoinSummary) ProtoMessage() {}
-
-func (x *OnlineCoinSummary) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[46]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use OnlineCoinSummary.ProtoReflect.Descriptor instead.
+func (m *OnlineCoinSummary) Reset() { *m = OnlineCoinSummary{} }
+func (m *OnlineCoinSummary) String() string { return proto.CompactTextString(m) }
+func (*OnlineCoinSummary) ProtoMessage() {}
func (*OnlineCoinSummary) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{46}
+ return fileDescriptor_77a6da22d6a3feb1, []int{44}
}
-func (x *OnlineCoinSummary) GetBalance() float64 {
- if x != nil {
- return x.Balance
+func (m *OnlineCoinSummary) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_OnlineCoinSummary.Unmarshal(m, b)
+}
+func (m *OnlineCoinSummary) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_OnlineCoinSummary.Marshal(b, m, deterministic)
+}
+func (m *OnlineCoinSummary) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_OnlineCoinSummary.Merge(m, src)
+}
+func (m *OnlineCoinSummary) XXX_Size() int {
+ return xxx_messageInfo_OnlineCoinSummary.Size(m)
+}
+func (m *OnlineCoinSummary) XXX_DiscardUnknown() {
+ xxx_messageInfo_OnlineCoinSummary.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_OnlineCoinSummary proto.InternalMessageInfo
+
+func (m *OnlineCoinSummary) GetBalance() float64 {
+ if m != nil {
+ return m.Balance
}
return 0
}
-func (x *OnlineCoinSummary) GetPercentage() float64 {
- if x != nil {
- return x.Percentage
+func (m *OnlineCoinSummary) GetPercentage() float64 {
+ if m != nil {
+ return m.Percentage
}
return 0
}
type OfflineCoins struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Addresses []*OfflineCoinSummary `protobuf:"bytes,1,rep,name=addresses,proto3" json:"addresses,omitempty"`
+ Addresses []*OfflineCoinSummary `protobuf:"bytes,1,rep,name=addresses,proto3" json:"addresses,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *OfflineCoins) Reset() {
- *x = OfflineCoins{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[47]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *OfflineCoins) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*OfflineCoins) ProtoMessage() {}
-
-func (x *OfflineCoins) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[47]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use OfflineCoins.ProtoReflect.Descriptor instead.
+func (m *OfflineCoins) Reset() { *m = OfflineCoins{} }
+func (m *OfflineCoins) String() string { return proto.CompactTextString(m) }
+func (*OfflineCoins) ProtoMessage() {}
func (*OfflineCoins) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{47}
+ return fileDescriptor_77a6da22d6a3feb1, []int{45}
}
-func (x *OfflineCoins) GetAddresses() []*OfflineCoinSummary {
- if x != nil {
- return x.Addresses
+func (m *OfflineCoins) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_OfflineCoins.Unmarshal(m, b)
+}
+func (m *OfflineCoins) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_OfflineCoins.Marshal(b, m, deterministic)
+}
+func (m *OfflineCoins) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_OfflineCoins.Merge(m, src)
+}
+func (m *OfflineCoins) XXX_Size() int {
+ return xxx_messageInfo_OfflineCoins.Size(m)
+}
+func (m *OfflineCoins) XXX_DiscardUnknown() {
+ xxx_messageInfo_OfflineCoins.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_OfflineCoins proto.InternalMessageInfo
+
+func (m *OfflineCoins) GetAddresses() []*OfflineCoinSummary {
+ if m != nil {
+ return m.Addresses
}
return nil
}
type OnlineCoins struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Coins map[string]*OnlineCoinSummary `protobuf:"bytes,1,rep,name=coins,proto3" json:"coins,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+ Coins map[string]*OnlineCoinSummary `protobuf:"bytes,1,rep,name=coins,proto3" json:"coins,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *OnlineCoins) Reset() {
- *x = OnlineCoins{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[48]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *OnlineCoins) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*OnlineCoins) ProtoMessage() {}
-
-func (x *OnlineCoins) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[48]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use OnlineCoins.ProtoReflect.Descriptor instead.
+func (m *OnlineCoins) Reset() { *m = OnlineCoins{} }
+func (m *OnlineCoins) String() string { return proto.CompactTextString(m) }
+func (*OnlineCoins) ProtoMessage() {}
func (*OnlineCoins) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{48}
+ return fileDescriptor_77a6da22d6a3feb1, []int{46}
}
-func (x *OnlineCoins) GetCoins() map[string]*OnlineCoinSummary {
- if x != nil {
- return x.Coins
+func (m *OnlineCoins) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_OnlineCoins.Unmarshal(m, b)
+}
+func (m *OnlineCoins) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_OnlineCoins.Marshal(b, m, deterministic)
+}
+func (m *OnlineCoins) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_OnlineCoins.Merge(m, src)
+}
+func (m *OnlineCoins) XXX_Size() int {
+ return xxx_messageInfo_OnlineCoins.Size(m)
+}
+func (m *OnlineCoins) XXX_DiscardUnknown() {
+ xxx_messageInfo_OnlineCoins.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_OnlineCoins proto.InternalMessageInfo
+
+func (m *OnlineCoins) GetCoins() map[string]*OnlineCoinSummary {
+ if m != nil {
+ return m.Coins
}
return nil
}
type GetPortfolioSummaryResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- CoinTotals []*Coin `protobuf:"bytes,1,rep,name=coin_totals,json=coinTotals,proto3" json:"coin_totals,omitempty"`
- CoinsOffline []*Coin `protobuf:"bytes,2,rep,name=coins_offline,json=coinsOffline,proto3" json:"coins_offline,omitempty"`
- CoinsOfflineSummary map[string]*OfflineCoins `protobuf:"bytes,3,rep,name=coins_offline_summary,json=coinsOfflineSummary,proto3" json:"coins_offline_summary,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
- CoinsOnline []*Coin `protobuf:"bytes,4,rep,name=coins_online,json=coinsOnline,proto3" json:"coins_online,omitempty"`
- CoinsOnlineSummary map[string]*OnlineCoins `protobuf:"bytes,5,rep,name=coins_online_summary,json=coinsOnlineSummary,proto3" json:"coins_online_summary,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+ CoinTotals []*Coin `protobuf:"bytes,1,rep,name=coin_totals,json=coinTotals,proto3" json:"coin_totals,omitempty"`
+ CoinsOffline []*Coin `protobuf:"bytes,2,rep,name=coins_offline,json=coinsOffline,proto3" json:"coins_offline,omitempty"`
+ CoinsOfflineSummary map[string]*OfflineCoins `protobuf:"bytes,3,rep,name=coins_offline_summary,json=coinsOfflineSummary,proto3" json:"coins_offline_summary,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+ CoinsOnline []*Coin `protobuf:"bytes,4,rep,name=coins_online,json=coinsOnline,proto3" json:"coins_online,omitempty"`
+ CoinsOnlineSummary map[string]*OnlineCoins `protobuf:"bytes,5,rep,name=coins_online_summary,json=coinsOnlineSummary,proto3" json:"coins_online_summary,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetPortfolioSummaryResponse) Reset() {
- *x = GetPortfolioSummaryResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[49]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetPortfolioSummaryResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetPortfolioSummaryResponse) ProtoMessage() {}
-
-func (x *GetPortfolioSummaryResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[49]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetPortfolioSummaryResponse.ProtoReflect.Descriptor instead.
+func (m *GetPortfolioSummaryResponse) Reset() { *m = GetPortfolioSummaryResponse{} }
+func (m *GetPortfolioSummaryResponse) String() string { return proto.CompactTextString(m) }
+func (*GetPortfolioSummaryResponse) ProtoMessage() {}
func (*GetPortfolioSummaryResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{49}
+ return fileDescriptor_77a6da22d6a3feb1, []int{47}
}
-func (x *GetPortfolioSummaryResponse) GetCoinTotals() []*Coin {
- if x != nil {
- return x.CoinTotals
+func (m *GetPortfolioSummaryResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetPortfolioSummaryResponse.Unmarshal(m, b)
+}
+func (m *GetPortfolioSummaryResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetPortfolioSummaryResponse.Marshal(b, m, deterministic)
+}
+func (m *GetPortfolioSummaryResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetPortfolioSummaryResponse.Merge(m, src)
+}
+func (m *GetPortfolioSummaryResponse) XXX_Size() int {
+ return xxx_messageInfo_GetPortfolioSummaryResponse.Size(m)
+}
+func (m *GetPortfolioSummaryResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetPortfolioSummaryResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetPortfolioSummaryResponse proto.InternalMessageInfo
+
+func (m *GetPortfolioSummaryResponse) GetCoinTotals() []*Coin {
+ if m != nil {
+ return m.CoinTotals
}
return nil
}
-func (x *GetPortfolioSummaryResponse) GetCoinsOffline() []*Coin {
- if x != nil {
- return x.CoinsOffline
+func (m *GetPortfolioSummaryResponse) GetCoinsOffline() []*Coin {
+ if m != nil {
+ return m.CoinsOffline
}
return nil
}
-func (x *GetPortfolioSummaryResponse) GetCoinsOfflineSummary() map[string]*OfflineCoins {
- if x != nil {
- return x.CoinsOfflineSummary
+func (m *GetPortfolioSummaryResponse) GetCoinsOfflineSummary() map[string]*OfflineCoins {
+ if m != nil {
+ return m.CoinsOfflineSummary
}
return nil
}
-func (x *GetPortfolioSummaryResponse) GetCoinsOnline() []*Coin {
- if x != nil {
- return x.CoinsOnline
+func (m *GetPortfolioSummaryResponse) GetCoinsOnline() []*Coin {
+ if m != nil {
+ return m.CoinsOnline
}
return nil
}
-func (x *GetPortfolioSummaryResponse) GetCoinsOnlineSummary() map[string]*OnlineCoins {
- if x != nil {
- return x.CoinsOnlineSummary
+func (m *GetPortfolioSummaryResponse) GetCoinsOnlineSummary() map[string]*OnlineCoins {
+ if m != nil {
+ return m.CoinsOnlineSummary
}
return nil
}
type AddPortfolioAddressRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
- CoinType string `protobuf:"bytes,2,opt,name=coin_type,json=coinType,proto3" json:"coin_type,omitempty"`
- Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"`
- Balance float64 `protobuf:"fixed64,4,opt,name=balance,proto3" json:"balance,omitempty"`
- SupportedExchanges string `protobuf:"bytes,5,opt,name=supported_exchanges,json=supportedExchanges,proto3" json:"supported_exchanges,omitempty"`
- ColdStorage bool `protobuf:"varint,6,opt,name=cold_storage,json=coldStorage,proto3" json:"cold_storage,omitempty"`
+ Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
+ CoinType string `protobuf:"bytes,2,opt,name=coin_type,json=coinType,proto3" json:"coin_type,omitempty"`
+ Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"`
+ Balance float64 `protobuf:"fixed64,4,opt,name=balance,proto3" json:"balance,omitempty"`
+ SupportedExchanges string `protobuf:"bytes,5,opt,name=supported_exchanges,json=supportedExchanges,proto3" json:"supported_exchanges,omitempty"`
+ ColdStorage bool `protobuf:"varint,6,opt,name=cold_storage,json=coldStorage,proto3" json:"cold_storage,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *AddPortfolioAddressRequest) Reset() {
- *x = AddPortfolioAddressRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[50]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *AddPortfolioAddressRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*AddPortfolioAddressRequest) ProtoMessage() {}
-
-func (x *AddPortfolioAddressRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[50]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use AddPortfolioAddressRequest.ProtoReflect.Descriptor instead.
+func (m *AddPortfolioAddressRequest) Reset() { *m = AddPortfolioAddressRequest{} }
+func (m *AddPortfolioAddressRequest) String() string { return proto.CompactTextString(m) }
+func (*AddPortfolioAddressRequest) ProtoMessage() {}
func (*AddPortfolioAddressRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{50}
+ return fileDescriptor_77a6da22d6a3feb1, []int{48}
}
-func (x *AddPortfolioAddressRequest) GetAddress() string {
- if x != nil {
- return x.Address
+func (m *AddPortfolioAddressRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_AddPortfolioAddressRequest.Unmarshal(m, b)
+}
+func (m *AddPortfolioAddressRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_AddPortfolioAddressRequest.Marshal(b, m, deterministic)
+}
+func (m *AddPortfolioAddressRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_AddPortfolioAddressRequest.Merge(m, src)
+}
+func (m *AddPortfolioAddressRequest) XXX_Size() int {
+ return xxx_messageInfo_AddPortfolioAddressRequest.Size(m)
+}
+func (m *AddPortfolioAddressRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_AddPortfolioAddressRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_AddPortfolioAddressRequest proto.InternalMessageInfo
+
+func (m *AddPortfolioAddressRequest) GetAddress() string {
+ if m != nil {
+ return m.Address
}
return ""
}
-func (x *AddPortfolioAddressRequest) GetCoinType() string {
- if x != nil {
- return x.CoinType
+func (m *AddPortfolioAddressRequest) GetCoinType() string {
+ if m != nil {
+ return m.CoinType
}
return ""
}
-func (x *AddPortfolioAddressRequest) GetDescription() string {
- if x != nil {
- return x.Description
+func (m *AddPortfolioAddressRequest) GetDescription() string {
+ if m != nil {
+ return m.Description
}
return ""
}
-func (x *AddPortfolioAddressRequest) GetBalance() float64 {
- if x != nil {
- return x.Balance
+func (m *AddPortfolioAddressRequest) GetBalance() float64 {
+ if m != nil {
+ return m.Balance
}
return 0
}
-func (x *AddPortfolioAddressRequest) GetSupportedExchanges() string {
- if x != nil {
- return x.SupportedExchanges
+func (m *AddPortfolioAddressRequest) GetSupportedExchanges() string {
+ if m != nil {
+ return m.SupportedExchanges
}
return ""
}
-func (x *AddPortfolioAddressRequest) GetColdStorage() bool {
- if x != nil {
- return x.ColdStorage
+func (m *AddPortfolioAddressRequest) GetColdStorage() bool {
+ if m != nil {
+ return m.ColdStorage
}
return false
}
-type AddPortfolioAddressResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-}
-
-func (x *AddPortfolioAddressResponse) Reset() {
- *x = AddPortfolioAddressResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[51]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *AddPortfolioAddressResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*AddPortfolioAddressResponse) ProtoMessage() {}
-
-func (x *AddPortfolioAddressResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[51]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use AddPortfolioAddressResponse.ProtoReflect.Descriptor instead.
-func (*AddPortfolioAddressResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{51}
-}
-
type RemovePortfolioAddressRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
- CoinType string `protobuf:"bytes,2,opt,name=coin_type,json=coinType,proto3" json:"coin_type,omitempty"`
- Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"`
+ Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
+ CoinType string `protobuf:"bytes,2,opt,name=coin_type,json=coinType,proto3" json:"coin_type,omitempty"`
+ Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *RemovePortfolioAddressRequest) Reset() {
- *x = RemovePortfolioAddressRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[52]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *RemovePortfolioAddressRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*RemovePortfolioAddressRequest) ProtoMessage() {}
-
-func (x *RemovePortfolioAddressRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[52]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use RemovePortfolioAddressRequest.ProtoReflect.Descriptor instead.
+func (m *RemovePortfolioAddressRequest) Reset() { *m = RemovePortfolioAddressRequest{} }
+func (m *RemovePortfolioAddressRequest) String() string { return proto.CompactTextString(m) }
+func (*RemovePortfolioAddressRequest) ProtoMessage() {}
func (*RemovePortfolioAddressRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{52}
+ return fileDescriptor_77a6da22d6a3feb1, []int{49}
}
-func (x *RemovePortfolioAddressRequest) GetAddress() string {
- if x != nil {
- return x.Address
+func (m *RemovePortfolioAddressRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_RemovePortfolioAddressRequest.Unmarshal(m, b)
+}
+func (m *RemovePortfolioAddressRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_RemovePortfolioAddressRequest.Marshal(b, m, deterministic)
+}
+func (m *RemovePortfolioAddressRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_RemovePortfolioAddressRequest.Merge(m, src)
+}
+func (m *RemovePortfolioAddressRequest) XXX_Size() int {
+ return xxx_messageInfo_RemovePortfolioAddressRequest.Size(m)
+}
+func (m *RemovePortfolioAddressRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_RemovePortfolioAddressRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_RemovePortfolioAddressRequest proto.InternalMessageInfo
+
+func (m *RemovePortfolioAddressRequest) GetAddress() string {
+ if m != nil {
+ return m.Address
}
return ""
}
-func (x *RemovePortfolioAddressRequest) GetCoinType() string {
- if x != nil {
- return x.CoinType
+func (m *RemovePortfolioAddressRequest) GetCoinType() string {
+ if m != nil {
+ return m.CoinType
}
return ""
}
-func (x *RemovePortfolioAddressRequest) GetDescription() string {
- if x != nil {
- return x.Description
+func (m *RemovePortfolioAddressRequest) GetDescription() string {
+ if m != nil {
+ return m.Description
}
return ""
}
-type RemovePortfolioAddressResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-}
-
-func (x *RemovePortfolioAddressResponse) Reset() {
- *x = RemovePortfolioAddressResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[53]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *RemovePortfolioAddressResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*RemovePortfolioAddressResponse) ProtoMessage() {}
-
-func (x *RemovePortfolioAddressResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[53]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use RemovePortfolioAddressResponse.ProtoReflect.Descriptor instead.
-func (*RemovePortfolioAddressResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{53}
-}
-
type GetForexProvidersRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetForexProvidersRequest) Reset() {
- *x = GetForexProvidersRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[54]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetForexProvidersRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetForexProvidersRequest) ProtoMessage() {}
-
-func (x *GetForexProvidersRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[54]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetForexProvidersRequest.ProtoReflect.Descriptor instead.
+func (m *GetForexProvidersRequest) Reset() { *m = GetForexProvidersRequest{} }
+func (m *GetForexProvidersRequest) String() string { return proto.CompactTextString(m) }
+func (*GetForexProvidersRequest) ProtoMessage() {}
func (*GetForexProvidersRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{54}
+ return fileDescriptor_77a6da22d6a3feb1, []int{50}
}
+func (m *GetForexProvidersRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetForexProvidersRequest.Unmarshal(m, b)
+}
+func (m *GetForexProvidersRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetForexProvidersRequest.Marshal(b, m, deterministic)
+}
+func (m *GetForexProvidersRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetForexProvidersRequest.Merge(m, src)
+}
+func (m *GetForexProvidersRequest) XXX_Size() int {
+ return xxx_messageInfo_GetForexProvidersRequest.Size(m)
+}
+func (m *GetForexProvidersRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetForexProvidersRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetForexProvidersRequest proto.InternalMessageInfo
+
type ForexProvider struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
- Enabled bool `protobuf:"varint,2,opt,name=enabled,proto3" json:"enabled,omitempty"`
- Verbose bool `protobuf:"varint,3,opt,name=verbose,proto3" json:"verbose,omitempty"`
- RestPollingDelay string `protobuf:"bytes,4,opt,name=rest_polling_delay,json=restPollingDelay,proto3" json:"rest_polling_delay,omitempty"`
- ApiKey string `protobuf:"bytes,5,opt,name=api_key,json=apiKey,proto3" json:"api_key,omitempty"`
- ApiKeyLevel int64 `protobuf:"varint,6,opt,name=api_key_level,json=apiKeyLevel,proto3" json:"api_key_level,omitempty"`
- PrimaryProvider bool `protobuf:"varint,7,opt,name=primary_provider,json=primaryProvider,proto3" json:"primary_provider,omitempty"`
+ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+ Enabled bool `protobuf:"varint,2,opt,name=enabled,proto3" json:"enabled,omitempty"`
+ Verbose bool `protobuf:"varint,3,opt,name=verbose,proto3" json:"verbose,omitempty"`
+ RestPollingDelay string `protobuf:"bytes,4,opt,name=rest_polling_delay,json=restPollingDelay,proto3" json:"rest_polling_delay,omitempty"`
+ ApiKey string `protobuf:"bytes,5,opt,name=api_key,json=apiKey,proto3" json:"api_key,omitempty"`
+ ApiKeyLevel int64 `protobuf:"varint,6,opt,name=api_key_level,json=apiKeyLevel,proto3" json:"api_key_level,omitempty"`
+ PrimaryProvider bool `protobuf:"varint,7,opt,name=primary_provider,json=primaryProvider,proto3" json:"primary_provider,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *ForexProvider) Reset() {
- *x = ForexProvider{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[55]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *ForexProvider) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*ForexProvider) ProtoMessage() {}
-
-func (x *ForexProvider) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[55]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use ForexProvider.ProtoReflect.Descriptor instead.
+func (m *ForexProvider) Reset() { *m = ForexProvider{} }
+func (m *ForexProvider) String() string { return proto.CompactTextString(m) }
+func (*ForexProvider) ProtoMessage() {}
func (*ForexProvider) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{55}
+ return fileDescriptor_77a6da22d6a3feb1, []int{51}
}
-func (x *ForexProvider) GetName() string {
- if x != nil {
- return x.Name
+func (m *ForexProvider) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_ForexProvider.Unmarshal(m, b)
+}
+func (m *ForexProvider) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_ForexProvider.Marshal(b, m, deterministic)
+}
+func (m *ForexProvider) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_ForexProvider.Merge(m, src)
+}
+func (m *ForexProvider) XXX_Size() int {
+ return xxx_messageInfo_ForexProvider.Size(m)
+}
+func (m *ForexProvider) XXX_DiscardUnknown() {
+ xxx_messageInfo_ForexProvider.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ForexProvider proto.InternalMessageInfo
+
+func (m *ForexProvider) GetName() string {
+ if m != nil {
+ return m.Name
}
return ""
}
-func (x *ForexProvider) GetEnabled() bool {
- if x != nil {
- return x.Enabled
+func (m *ForexProvider) GetEnabled() bool {
+ if m != nil {
+ return m.Enabled
}
return false
}
-func (x *ForexProvider) GetVerbose() bool {
- if x != nil {
- return x.Verbose
+func (m *ForexProvider) GetVerbose() bool {
+ if m != nil {
+ return m.Verbose
}
return false
}
-func (x *ForexProvider) GetRestPollingDelay() string {
- if x != nil {
- return x.RestPollingDelay
+func (m *ForexProvider) GetRestPollingDelay() string {
+ if m != nil {
+ return m.RestPollingDelay
}
return ""
}
-func (x *ForexProvider) GetApiKey() string {
- if x != nil {
- return x.ApiKey
+func (m *ForexProvider) GetApiKey() string {
+ if m != nil {
+ return m.ApiKey
}
return ""
}
-func (x *ForexProvider) GetApiKeyLevel() int64 {
- if x != nil {
- return x.ApiKeyLevel
+func (m *ForexProvider) GetApiKeyLevel() int64 {
+ if m != nil {
+ return m.ApiKeyLevel
}
return 0
}
-func (x *ForexProvider) GetPrimaryProvider() bool {
- if x != nil {
- return x.PrimaryProvider
+func (m *ForexProvider) GetPrimaryProvider() bool {
+ if m != nil {
+ return m.PrimaryProvider
}
return false
}
type GetForexProvidersResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- ForexProviders []*ForexProvider `protobuf:"bytes,1,rep,name=forex_providers,json=forexProviders,proto3" json:"forex_providers,omitempty"`
+ ForexProviders []*ForexProvider `protobuf:"bytes,1,rep,name=forex_providers,json=forexProviders,proto3" json:"forex_providers,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetForexProvidersResponse) Reset() {
- *x = GetForexProvidersResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[56]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetForexProvidersResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetForexProvidersResponse) ProtoMessage() {}
-
-func (x *GetForexProvidersResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[56]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetForexProvidersResponse.ProtoReflect.Descriptor instead.
+func (m *GetForexProvidersResponse) Reset() { *m = GetForexProvidersResponse{} }
+func (m *GetForexProvidersResponse) String() string { return proto.CompactTextString(m) }
+func (*GetForexProvidersResponse) ProtoMessage() {}
func (*GetForexProvidersResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{56}
+ return fileDescriptor_77a6da22d6a3feb1, []int{52}
}
-func (x *GetForexProvidersResponse) GetForexProviders() []*ForexProvider {
- if x != nil {
- return x.ForexProviders
+func (m *GetForexProvidersResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetForexProvidersResponse.Unmarshal(m, b)
+}
+func (m *GetForexProvidersResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetForexProvidersResponse.Marshal(b, m, deterministic)
+}
+func (m *GetForexProvidersResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetForexProvidersResponse.Merge(m, src)
+}
+func (m *GetForexProvidersResponse) XXX_Size() int {
+ return xxx_messageInfo_GetForexProvidersResponse.Size(m)
+}
+func (m *GetForexProvidersResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetForexProvidersResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetForexProvidersResponse proto.InternalMessageInfo
+
+func (m *GetForexProvidersResponse) GetForexProviders() []*ForexProvider {
+ if m != nil {
+ return m.ForexProviders
}
return nil
}
type GetForexRatesRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetForexRatesRequest) Reset() {
- *x = GetForexRatesRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[57]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetForexRatesRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetForexRatesRequest) ProtoMessage() {}
-
-func (x *GetForexRatesRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[57]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetForexRatesRequest.ProtoReflect.Descriptor instead.
+func (m *GetForexRatesRequest) Reset() { *m = GetForexRatesRequest{} }
+func (m *GetForexRatesRequest) String() string { return proto.CompactTextString(m) }
+func (*GetForexRatesRequest) ProtoMessage() {}
func (*GetForexRatesRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{57}
+ return fileDescriptor_77a6da22d6a3feb1, []int{53}
}
+func (m *GetForexRatesRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetForexRatesRequest.Unmarshal(m, b)
+}
+func (m *GetForexRatesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetForexRatesRequest.Marshal(b, m, deterministic)
+}
+func (m *GetForexRatesRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetForexRatesRequest.Merge(m, src)
+}
+func (m *GetForexRatesRequest) XXX_Size() int {
+ return xxx_messageInfo_GetForexRatesRequest.Size(m)
+}
+func (m *GetForexRatesRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetForexRatesRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetForexRatesRequest proto.InternalMessageInfo
+
type ForexRatesConversion struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- From string `protobuf:"bytes,1,opt,name=from,proto3" json:"from,omitempty"`
- To string `protobuf:"bytes,2,opt,name=to,proto3" json:"to,omitempty"`
- Rate float64 `protobuf:"fixed64,3,opt,name=rate,proto3" json:"rate,omitempty"`
- InverseRate float64 `protobuf:"fixed64,4,opt,name=inverse_rate,json=inverseRate,proto3" json:"inverse_rate,omitempty"`
+ From string `protobuf:"bytes,1,opt,name=from,proto3" json:"from,omitempty"`
+ To string `protobuf:"bytes,2,opt,name=to,proto3" json:"to,omitempty"`
+ Rate float64 `protobuf:"fixed64,3,opt,name=rate,proto3" json:"rate,omitempty"`
+ InverseRate float64 `protobuf:"fixed64,4,opt,name=inverse_rate,json=inverseRate,proto3" json:"inverse_rate,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *ForexRatesConversion) Reset() {
- *x = ForexRatesConversion{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[58]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *ForexRatesConversion) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*ForexRatesConversion) ProtoMessage() {}
-
-func (x *ForexRatesConversion) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[58]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use ForexRatesConversion.ProtoReflect.Descriptor instead.
+func (m *ForexRatesConversion) Reset() { *m = ForexRatesConversion{} }
+func (m *ForexRatesConversion) String() string { return proto.CompactTextString(m) }
+func (*ForexRatesConversion) ProtoMessage() {}
func (*ForexRatesConversion) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{58}
+ return fileDescriptor_77a6da22d6a3feb1, []int{54}
}
-func (x *ForexRatesConversion) GetFrom() string {
- if x != nil {
- return x.From
+func (m *ForexRatesConversion) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_ForexRatesConversion.Unmarshal(m, b)
+}
+func (m *ForexRatesConversion) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_ForexRatesConversion.Marshal(b, m, deterministic)
+}
+func (m *ForexRatesConversion) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_ForexRatesConversion.Merge(m, src)
+}
+func (m *ForexRatesConversion) XXX_Size() int {
+ return xxx_messageInfo_ForexRatesConversion.Size(m)
+}
+func (m *ForexRatesConversion) XXX_DiscardUnknown() {
+ xxx_messageInfo_ForexRatesConversion.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ForexRatesConversion proto.InternalMessageInfo
+
+func (m *ForexRatesConversion) GetFrom() string {
+ if m != nil {
+ return m.From
}
return ""
}
-func (x *ForexRatesConversion) GetTo() string {
- if x != nil {
- return x.To
+func (m *ForexRatesConversion) GetTo() string {
+ if m != nil {
+ return m.To
}
return ""
}
-func (x *ForexRatesConversion) GetRate() float64 {
- if x != nil {
- return x.Rate
+func (m *ForexRatesConversion) GetRate() float64 {
+ if m != nil {
+ return m.Rate
}
return 0
}
-func (x *ForexRatesConversion) GetInverseRate() float64 {
- if x != nil {
- return x.InverseRate
+func (m *ForexRatesConversion) GetInverseRate() float64 {
+ if m != nil {
+ return m.InverseRate
}
return 0
}
type GetForexRatesResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- ForexRates []*ForexRatesConversion `protobuf:"bytes,1,rep,name=forex_rates,json=forexRates,proto3" json:"forex_rates,omitempty"`
+ ForexRates []*ForexRatesConversion `protobuf:"bytes,1,rep,name=forex_rates,json=forexRates,proto3" json:"forex_rates,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetForexRatesResponse) Reset() {
- *x = GetForexRatesResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[59]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetForexRatesResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetForexRatesResponse) ProtoMessage() {}
-
-func (x *GetForexRatesResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[59]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetForexRatesResponse.ProtoReflect.Descriptor instead.
+func (m *GetForexRatesResponse) Reset() { *m = GetForexRatesResponse{} }
+func (m *GetForexRatesResponse) String() string { return proto.CompactTextString(m) }
+func (*GetForexRatesResponse) ProtoMessage() {}
func (*GetForexRatesResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{59}
+ return fileDescriptor_77a6da22d6a3feb1, []int{55}
}
-func (x *GetForexRatesResponse) GetForexRates() []*ForexRatesConversion {
- if x != nil {
- return x.ForexRates
+func (m *GetForexRatesResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetForexRatesResponse.Unmarshal(m, b)
+}
+func (m *GetForexRatesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetForexRatesResponse.Marshal(b, m, deterministic)
+}
+func (m *GetForexRatesResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetForexRatesResponse.Merge(m, src)
+}
+func (m *GetForexRatesResponse) XXX_Size() int {
+ return xxx_messageInfo_GetForexRatesResponse.Size(m)
+}
+func (m *GetForexRatesResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetForexRatesResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetForexRatesResponse proto.InternalMessageInfo
+
+func (m *GetForexRatesResponse) GetForexRates() []*ForexRatesConversion {
+ if m != nil {
+ return m.ForexRates
}
return nil
}
type OrderDetails struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
- Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
- BaseCurrency string `protobuf:"bytes,3,opt,name=base_currency,json=baseCurrency,proto3" json:"base_currency,omitempty"`
- QuoteCurrency string `protobuf:"bytes,4,opt,name=quote_currency,json=quoteCurrency,proto3" json:"quote_currency,omitempty"`
- AssetType string `protobuf:"bytes,5,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"`
- OrderSide string `protobuf:"bytes,6,opt,name=order_side,json=orderSide,proto3" json:"order_side,omitempty"`
- OrderType string `protobuf:"bytes,7,opt,name=order_type,json=orderType,proto3" json:"order_type,omitempty"`
- CreationTime int64 `protobuf:"varint,8,opt,name=creation_time,json=creationTime,proto3" json:"creation_time,omitempty"`
- Status string `protobuf:"bytes,9,opt,name=status,proto3" json:"status,omitempty"`
- Price float64 `protobuf:"fixed64,10,opt,name=price,proto3" json:"price,omitempty"`
- Amount float64 `protobuf:"fixed64,11,opt,name=amount,proto3" json:"amount,omitempty"`
- OpenVolume float64 `protobuf:"fixed64,12,opt,name=open_volume,json=openVolume,proto3" json:"open_volume,omitempty"`
- Fee float64 `protobuf:"fixed64,13,opt,name=fee,proto3" json:"fee,omitempty"`
- Trades []*TradeHistory `protobuf:"bytes,14,rep,name=trades,proto3" json:"trades,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
+ BaseCurrency string `protobuf:"bytes,3,opt,name=base_currency,json=baseCurrency,proto3" json:"base_currency,omitempty"`
+ QuoteCurrency string `protobuf:"bytes,4,opt,name=quote_currency,json=quoteCurrency,proto3" json:"quote_currency,omitempty"`
+ AssetType string `protobuf:"bytes,5,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"`
+ OrderSide string `protobuf:"bytes,6,opt,name=order_side,json=orderSide,proto3" json:"order_side,omitempty"`
+ OrderType string `protobuf:"bytes,7,opt,name=order_type,json=orderType,proto3" json:"order_type,omitempty"`
+ CreationTime int64 `protobuf:"varint,8,opt,name=creation_time,json=creationTime,proto3" json:"creation_time,omitempty"`
+ Status string `protobuf:"bytes,9,opt,name=status,proto3" json:"status,omitempty"`
+ Price float64 `protobuf:"fixed64,10,opt,name=price,proto3" json:"price,omitempty"`
+ Amount float64 `protobuf:"fixed64,11,opt,name=amount,proto3" json:"amount,omitempty"`
+ OpenVolume float64 `protobuf:"fixed64,12,opt,name=open_volume,json=openVolume,proto3" json:"open_volume,omitempty"`
+ Fee float64 `protobuf:"fixed64,13,opt,name=fee,proto3" json:"fee,omitempty"`
+ Trades []*TradeHistory `protobuf:"bytes,14,rep,name=trades,proto3" json:"trades,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *OrderDetails) Reset() {
- *x = OrderDetails{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[60]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *OrderDetails) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*OrderDetails) ProtoMessage() {}
-
-func (x *OrderDetails) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[60]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use OrderDetails.ProtoReflect.Descriptor instead.
+func (m *OrderDetails) Reset() { *m = OrderDetails{} }
+func (m *OrderDetails) String() string { return proto.CompactTextString(m) }
+func (*OrderDetails) ProtoMessage() {}
func (*OrderDetails) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{60}
+ return fileDescriptor_77a6da22d6a3feb1, []int{56}
}
-func (x *OrderDetails) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *OrderDetails) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_OrderDetails.Unmarshal(m, b)
+}
+func (m *OrderDetails) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_OrderDetails.Marshal(b, m, deterministic)
+}
+func (m *OrderDetails) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_OrderDetails.Merge(m, src)
+}
+func (m *OrderDetails) XXX_Size() int {
+ return xxx_messageInfo_OrderDetails.Size(m)
+}
+func (m *OrderDetails) XXX_DiscardUnknown() {
+ xxx_messageInfo_OrderDetails.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_OrderDetails proto.InternalMessageInfo
+
+func (m *OrderDetails) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
-func (x *OrderDetails) GetId() string {
- if x != nil {
- return x.Id
+func (m *OrderDetails) GetId() string {
+ if m != nil {
+ return m.Id
}
return ""
}
-func (x *OrderDetails) GetBaseCurrency() string {
- if x != nil {
- return x.BaseCurrency
+func (m *OrderDetails) GetBaseCurrency() string {
+ if m != nil {
+ return m.BaseCurrency
}
return ""
}
-func (x *OrderDetails) GetQuoteCurrency() string {
- if x != nil {
- return x.QuoteCurrency
+func (m *OrderDetails) GetQuoteCurrency() string {
+ if m != nil {
+ return m.QuoteCurrency
}
return ""
}
-func (x *OrderDetails) GetAssetType() string {
- if x != nil {
- return x.AssetType
+func (m *OrderDetails) GetAssetType() string {
+ if m != nil {
+ return m.AssetType
}
return ""
}
-func (x *OrderDetails) GetOrderSide() string {
- if x != nil {
- return x.OrderSide
+func (m *OrderDetails) GetOrderSide() string {
+ if m != nil {
+ return m.OrderSide
}
return ""
}
-func (x *OrderDetails) GetOrderType() string {
- if x != nil {
- return x.OrderType
+func (m *OrderDetails) GetOrderType() string {
+ if m != nil {
+ return m.OrderType
}
return ""
}
-func (x *OrderDetails) GetCreationTime() int64 {
- if x != nil {
- return x.CreationTime
+func (m *OrderDetails) GetCreationTime() int64 {
+ if m != nil {
+ return m.CreationTime
}
return 0
}
-func (x *OrderDetails) GetStatus() string {
- if x != nil {
- return x.Status
+func (m *OrderDetails) GetStatus() string {
+ if m != nil {
+ return m.Status
}
return ""
}
-func (x *OrderDetails) GetPrice() float64 {
- if x != nil {
- return x.Price
+func (m *OrderDetails) GetPrice() float64 {
+ if m != nil {
+ return m.Price
}
return 0
}
-func (x *OrderDetails) GetAmount() float64 {
- if x != nil {
- return x.Amount
+func (m *OrderDetails) GetAmount() float64 {
+ if m != nil {
+ return m.Amount
}
return 0
}
-func (x *OrderDetails) GetOpenVolume() float64 {
- if x != nil {
- return x.OpenVolume
+func (m *OrderDetails) GetOpenVolume() float64 {
+ if m != nil {
+ return m.OpenVolume
}
return 0
}
-func (x *OrderDetails) GetFee() float64 {
- if x != nil {
- return x.Fee
+func (m *OrderDetails) GetFee() float64 {
+ if m != nil {
+ return m.Fee
}
return 0
}
-func (x *OrderDetails) GetTrades() []*TradeHistory {
- if x != nil {
- return x.Trades
+func (m *OrderDetails) GetTrades() []*TradeHistory {
+ if m != nil {
+ return m.Trades
}
return nil
}
type TradeHistory struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- CreationTime int64 `protobuf:"varint,1,opt,name=creation_time,json=creationTime,proto3" json:"creation_time,omitempty"`
- Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
- Price float64 `protobuf:"fixed64,3,opt,name=price,proto3" json:"price,omitempty"`
- Amount float64 `protobuf:"fixed64,4,opt,name=amount,proto3" json:"amount,omitempty"`
- Exchange string `protobuf:"bytes,5,opt,name=exchange,proto3" json:"exchange,omitempty"`
- AssetType string `protobuf:"bytes,6,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"`
- OrderSide string `protobuf:"bytes,7,opt,name=order_side,json=orderSide,proto3" json:"order_side,omitempty"`
- Fee float64 `protobuf:"fixed64,8,opt,name=fee,proto3" json:"fee,omitempty"`
+ CreationTime int64 `protobuf:"varint,1,opt,name=creation_time,json=creationTime,proto3" json:"creation_time,omitempty"`
+ Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
+ Price float64 `protobuf:"fixed64,3,opt,name=price,proto3" json:"price,omitempty"`
+ Amount float64 `protobuf:"fixed64,4,opt,name=amount,proto3" json:"amount,omitempty"`
+ Exchange string `protobuf:"bytes,5,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ AssetType string `protobuf:"bytes,6,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"`
+ OrderSide string `protobuf:"bytes,7,opt,name=order_side,json=orderSide,proto3" json:"order_side,omitempty"`
+ Fee float64 `protobuf:"fixed64,8,opt,name=fee,proto3" json:"fee,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *TradeHistory) Reset() {
- *x = TradeHistory{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[61]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *TradeHistory) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*TradeHistory) ProtoMessage() {}
-
-func (x *TradeHistory) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[61]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use TradeHistory.ProtoReflect.Descriptor instead.
+func (m *TradeHistory) Reset() { *m = TradeHistory{} }
+func (m *TradeHistory) String() string { return proto.CompactTextString(m) }
+func (*TradeHistory) ProtoMessage() {}
func (*TradeHistory) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{61}
+ return fileDescriptor_77a6da22d6a3feb1, []int{57}
}
-func (x *TradeHistory) GetCreationTime() int64 {
- if x != nil {
- return x.CreationTime
+func (m *TradeHistory) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_TradeHistory.Unmarshal(m, b)
+}
+func (m *TradeHistory) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_TradeHistory.Marshal(b, m, deterministic)
+}
+func (m *TradeHistory) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_TradeHistory.Merge(m, src)
+}
+func (m *TradeHistory) XXX_Size() int {
+ return xxx_messageInfo_TradeHistory.Size(m)
+}
+func (m *TradeHistory) XXX_DiscardUnknown() {
+ xxx_messageInfo_TradeHistory.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_TradeHistory proto.InternalMessageInfo
+
+func (m *TradeHistory) GetCreationTime() int64 {
+ if m != nil {
+ return m.CreationTime
}
return 0
}
-func (x *TradeHistory) GetId() string {
- if x != nil {
- return x.Id
+func (m *TradeHistory) GetId() string {
+ if m != nil {
+ return m.Id
}
return ""
}
-func (x *TradeHistory) GetPrice() float64 {
- if x != nil {
- return x.Price
+func (m *TradeHistory) GetPrice() float64 {
+ if m != nil {
+ return m.Price
}
return 0
}
-func (x *TradeHistory) GetAmount() float64 {
- if x != nil {
- return x.Amount
+func (m *TradeHistory) GetAmount() float64 {
+ if m != nil {
+ return m.Amount
}
return 0
}
-func (x *TradeHistory) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *TradeHistory) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
-func (x *TradeHistory) GetAssetType() string {
- if x != nil {
- return x.AssetType
+func (m *TradeHistory) GetAssetType() string {
+ if m != nil {
+ return m.AssetType
}
return ""
}
-func (x *TradeHistory) GetOrderSide() string {
- if x != nil {
- return x.OrderSide
+func (m *TradeHistory) GetOrderSide() string {
+ if m != nil {
+ return m.OrderSide
}
return ""
}
-func (x *TradeHistory) GetFee() float64 {
- if x != nil {
- return x.Fee
+func (m *TradeHistory) GetFee() float64 {
+ if m != nil {
+ return m.Fee
}
return 0
}
type GetOrdersRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
- AssetType string `protobuf:"bytes,2,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"`
- Pair *CurrencyPair `protobuf:"bytes,3,opt,name=pair,proto3" json:"pair,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ AssetType string `protobuf:"bytes,2,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"`
+ Pair *CurrencyPair `protobuf:"bytes,3,opt,name=pair,proto3" json:"pair,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetOrdersRequest) Reset() {
- *x = GetOrdersRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[62]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetOrdersRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetOrdersRequest) ProtoMessage() {}
-
-func (x *GetOrdersRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[62]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetOrdersRequest.ProtoReflect.Descriptor instead.
+func (m *GetOrdersRequest) Reset() { *m = GetOrdersRequest{} }
+func (m *GetOrdersRequest) String() string { return proto.CompactTextString(m) }
+func (*GetOrdersRequest) ProtoMessage() {}
func (*GetOrdersRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{62}
+ return fileDescriptor_77a6da22d6a3feb1, []int{58}
}
-func (x *GetOrdersRequest) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *GetOrdersRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetOrdersRequest.Unmarshal(m, b)
+}
+func (m *GetOrdersRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetOrdersRequest.Marshal(b, m, deterministic)
+}
+func (m *GetOrdersRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetOrdersRequest.Merge(m, src)
+}
+func (m *GetOrdersRequest) XXX_Size() int {
+ return xxx_messageInfo_GetOrdersRequest.Size(m)
+}
+func (m *GetOrdersRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetOrdersRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetOrdersRequest proto.InternalMessageInfo
+
+func (m *GetOrdersRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
-func (x *GetOrdersRequest) GetAssetType() string {
- if x != nil {
- return x.AssetType
+func (m *GetOrdersRequest) GetAssetType() string {
+ if m != nil {
+ return m.AssetType
}
return ""
}
-func (x *GetOrdersRequest) GetPair() *CurrencyPair {
- if x != nil {
- return x.Pair
+func (m *GetOrdersRequest) GetPair() *CurrencyPair {
+ if m != nil {
+ return m.Pair
}
return nil
}
type GetOrdersResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Orders []*OrderDetails `protobuf:"bytes,1,rep,name=orders,proto3" json:"orders,omitempty"`
+ Orders []*OrderDetails `protobuf:"bytes,1,rep,name=orders,proto3" json:"orders,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetOrdersResponse) Reset() {
- *x = GetOrdersResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[63]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetOrdersResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetOrdersResponse) ProtoMessage() {}
-
-func (x *GetOrdersResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[63]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetOrdersResponse.ProtoReflect.Descriptor instead.
+func (m *GetOrdersResponse) Reset() { *m = GetOrdersResponse{} }
+func (m *GetOrdersResponse) String() string { return proto.CompactTextString(m) }
+func (*GetOrdersResponse) ProtoMessage() {}
func (*GetOrdersResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{63}
+ return fileDescriptor_77a6da22d6a3feb1, []int{59}
}
-func (x *GetOrdersResponse) GetOrders() []*OrderDetails {
- if x != nil {
- return x.Orders
+func (m *GetOrdersResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetOrdersResponse.Unmarshal(m, b)
+}
+func (m *GetOrdersResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetOrdersResponse.Marshal(b, m, deterministic)
+}
+func (m *GetOrdersResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetOrdersResponse.Merge(m, src)
+}
+func (m *GetOrdersResponse) XXX_Size() int {
+ return xxx_messageInfo_GetOrdersResponse.Size(m)
+}
+func (m *GetOrdersResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetOrdersResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetOrdersResponse proto.InternalMessageInfo
+
+func (m *GetOrdersResponse) GetOrders() []*OrderDetails {
+ if m != nil {
+ return m.Orders
}
return nil
}
type GetOrderRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
- OrderId string `protobuf:"bytes,2,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ OrderId string `protobuf:"bytes,2,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetOrderRequest) Reset() {
- *x = GetOrderRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[64]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetOrderRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetOrderRequest) ProtoMessage() {}
-
-func (x *GetOrderRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[64]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetOrderRequest.ProtoReflect.Descriptor instead.
+func (m *GetOrderRequest) Reset() { *m = GetOrderRequest{} }
+func (m *GetOrderRequest) String() string { return proto.CompactTextString(m) }
+func (*GetOrderRequest) ProtoMessage() {}
func (*GetOrderRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{64}
+ return fileDescriptor_77a6da22d6a3feb1, []int{60}
}
-func (x *GetOrderRequest) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *GetOrderRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetOrderRequest.Unmarshal(m, b)
+}
+func (m *GetOrderRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetOrderRequest.Marshal(b, m, deterministic)
+}
+func (m *GetOrderRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetOrderRequest.Merge(m, src)
+}
+func (m *GetOrderRequest) XXX_Size() int {
+ return xxx_messageInfo_GetOrderRequest.Size(m)
+}
+func (m *GetOrderRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetOrderRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetOrderRequest proto.InternalMessageInfo
+
+func (m *GetOrderRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
-func (x *GetOrderRequest) GetOrderId() string {
- if x != nil {
- return x.OrderId
+func (m *GetOrderRequest) GetOrderId() string {
+ if m != nil {
+ return m.OrderId
}
return ""
}
type SubmitOrderRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
- Pair *CurrencyPair `protobuf:"bytes,2,opt,name=pair,proto3" json:"pair,omitempty"`
- Side string `protobuf:"bytes,3,opt,name=side,proto3" json:"side,omitempty"`
- OrderType string `protobuf:"bytes,4,opt,name=order_type,json=orderType,proto3" json:"order_type,omitempty"`
- Amount float64 `protobuf:"fixed64,5,opt,name=amount,proto3" json:"amount,omitempty"`
- Price float64 `protobuf:"fixed64,6,opt,name=price,proto3" json:"price,omitempty"`
- ClientId string `protobuf:"bytes,7,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Pair *CurrencyPair `protobuf:"bytes,2,opt,name=pair,proto3" json:"pair,omitempty"`
+ Side string `protobuf:"bytes,3,opt,name=side,proto3" json:"side,omitempty"`
+ OrderType string `protobuf:"bytes,4,opt,name=order_type,json=orderType,proto3" json:"order_type,omitempty"`
+ Amount float64 `protobuf:"fixed64,5,opt,name=amount,proto3" json:"amount,omitempty"`
+ Price float64 `protobuf:"fixed64,6,opt,name=price,proto3" json:"price,omitempty"`
+ ClientId string `protobuf:"bytes,7,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *SubmitOrderRequest) Reset() {
- *x = SubmitOrderRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[65]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *SubmitOrderRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*SubmitOrderRequest) ProtoMessage() {}
-
-func (x *SubmitOrderRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[65]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use SubmitOrderRequest.ProtoReflect.Descriptor instead.
+func (m *SubmitOrderRequest) Reset() { *m = SubmitOrderRequest{} }
+func (m *SubmitOrderRequest) String() string { return proto.CompactTextString(m) }
+func (*SubmitOrderRequest) ProtoMessage() {}
func (*SubmitOrderRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{65}
+ return fileDescriptor_77a6da22d6a3feb1, []int{61}
}
-func (x *SubmitOrderRequest) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *SubmitOrderRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_SubmitOrderRequest.Unmarshal(m, b)
+}
+func (m *SubmitOrderRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_SubmitOrderRequest.Marshal(b, m, deterministic)
+}
+func (m *SubmitOrderRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_SubmitOrderRequest.Merge(m, src)
+}
+func (m *SubmitOrderRequest) XXX_Size() int {
+ return xxx_messageInfo_SubmitOrderRequest.Size(m)
+}
+func (m *SubmitOrderRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_SubmitOrderRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SubmitOrderRequest proto.InternalMessageInfo
+
+func (m *SubmitOrderRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
-func (x *SubmitOrderRequest) GetPair() *CurrencyPair {
- if x != nil {
- return x.Pair
+func (m *SubmitOrderRequest) GetPair() *CurrencyPair {
+ if m != nil {
+ return m.Pair
}
return nil
}
-func (x *SubmitOrderRequest) GetSide() string {
- if x != nil {
- return x.Side
+func (m *SubmitOrderRequest) GetSide() string {
+ if m != nil {
+ return m.Side
}
return ""
}
-func (x *SubmitOrderRequest) GetOrderType() string {
- if x != nil {
- return x.OrderType
+func (m *SubmitOrderRequest) GetOrderType() string {
+ if m != nil {
+ return m.OrderType
}
return ""
}
-func (x *SubmitOrderRequest) GetAmount() float64 {
- if x != nil {
- return x.Amount
+func (m *SubmitOrderRequest) GetAmount() float64 {
+ if m != nil {
+ return m.Amount
}
return 0
}
-func (x *SubmitOrderRequest) GetPrice() float64 {
- if x != nil {
- return x.Price
+func (m *SubmitOrderRequest) GetPrice() float64 {
+ if m != nil {
+ return m.Price
}
return 0
}
-func (x *SubmitOrderRequest) GetClientId() string {
- if x != nil {
- return x.ClientId
+func (m *SubmitOrderRequest) GetClientId() string {
+ if m != nil {
+ return m.ClientId
}
return ""
}
type SubmitOrderResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- OrderPlaced bool `protobuf:"varint,1,opt,name=order_placed,json=orderPlaced,proto3" json:"order_placed,omitempty"`
- OrderId string `protobuf:"bytes,2,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"`
+ OrderPlaced bool `protobuf:"varint,1,opt,name=order_placed,json=orderPlaced,proto3" json:"order_placed,omitempty"`
+ OrderId string `protobuf:"bytes,2,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *SubmitOrderResponse) Reset() {
- *x = SubmitOrderResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[66]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *SubmitOrderResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*SubmitOrderResponse) ProtoMessage() {}
-
-func (x *SubmitOrderResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[66]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use SubmitOrderResponse.ProtoReflect.Descriptor instead.
+func (m *SubmitOrderResponse) Reset() { *m = SubmitOrderResponse{} }
+func (m *SubmitOrderResponse) String() string { return proto.CompactTextString(m) }
+func (*SubmitOrderResponse) ProtoMessage() {}
func (*SubmitOrderResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{66}
+ return fileDescriptor_77a6da22d6a3feb1, []int{62}
}
-func (x *SubmitOrderResponse) GetOrderPlaced() bool {
- if x != nil {
- return x.OrderPlaced
+func (m *SubmitOrderResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_SubmitOrderResponse.Unmarshal(m, b)
+}
+func (m *SubmitOrderResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_SubmitOrderResponse.Marshal(b, m, deterministic)
+}
+func (m *SubmitOrderResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_SubmitOrderResponse.Merge(m, src)
+}
+func (m *SubmitOrderResponse) XXX_Size() int {
+ return xxx_messageInfo_SubmitOrderResponse.Size(m)
+}
+func (m *SubmitOrderResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_SubmitOrderResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SubmitOrderResponse proto.InternalMessageInfo
+
+func (m *SubmitOrderResponse) GetOrderPlaced() bool {
+ if m != nil {
+ return m.OrderPlaced
}
return false
}
-func (x *SubmitOrderResponse) GetOrderId() string {
- if x != nil {
- return x.OrderId
+func (m *SubmitOrderResponse) GetOrderId() string {
+ if m != nil {
+ return m.OrderId
}
return ""
}
type SimulateOrderRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
- Pair *CurrencyPair `protobuf:"bytes,2,opt,name=pair,proto3" json:"pair,omitempty"`
- Amount float64 `protobuf:"fixed64,3,opt,name=amount,proto3" json:"amount,omitempty"`
- Side string `protobuf:"bytes,4,opt,name=side,proto3" json:"side,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Pair *CurrencyPair `protobuf:"bytes,2,opt,name=pair,proto3" json:"pair,omitempty"`
+ Amount float64 `protobuf:"fixed64,3,opt,name=amount,proto3" json:"amount,omitempty"`
+ Side string `protobuf:"bytes,4,opt,name=side,proto3" json:"side,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *SimulateOrderRequest) Reset() {
- *x = SimulateOrderRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[67]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *SimulateOrderRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*SimulateOrderRequest) ProtoMessage() {}
-
-func (x *SimulateOrderRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[67]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use SimulateOrderRequest.ProtoReflect.Descriptor instead.
+func (m *SimulateOrderRequest) Reset() { *m = SimulateOrderRequest{} }
+func (m *SimulateOrderRequest) String() string { return proto.CompactTextString(m) }
+func (*SimulateOrderRequest) ProtoMessage() {}
func (*SimulateOrderRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{67}
+ return fileDescriptor_77a6da22d6a3feb1, []int{63}
}
-func (x *SimulateOrderRequest) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *SimulateOrderRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_SimulateOrderRequest.Unmarshal(m, b)
+}
+func (m *SimulateOrderRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_SimulateOrderRequest.Marshal(b, m, deterministic)
+}
+func (m *SimulateOrderRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_SimulateOrderRequest.Merge(m, src)
+}
+func (m *SimulateOrderRequest) XXX_Size() int {
+ return xxx_messageInfo_SimulateOrderRequest.Size(m)
+}
+func (m *SimulateOrderRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_SimulateOrderRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SimulateOrderRequest proto.InternalMessageInfo
+
+func (m *SimulateOrderRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
-func (x *SimulateOrderRequest) GetPair() *CurrencyPair {
- if x != nil {
- return x.Pair
+func (m *SimulateOrderRequest) GetPair() *CurrencyPair {
+ if m != nil {
+ return m.Pair
}
return nil
}
-func (x *SimulateOrderRequest) GetAmount() float64 {
- if x != nil {
- return x.Amount
+func (m *SimulateOrderRequest) GetAmount() float64 {
+ if m != nil {
+ return m.Amount
}
return 0
}
-func (x *SimulateOrderRequest) GetSide() string {
- if x != nil {
- return x.Side
+func (m *SimulateOrderRequest) GetSide() string {
+ if m != nil {
+ return m.Side
}
return ""
}
type SimulateOrderResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Orders []*OrderbookItem `protobuf:"bytes,1,rep,name=orders,proto3" json:"orders,omitempty"`
- Amount float64 `protobuf:"fixed64,2,opt,name=amount,proto3" json:"amount,omitempty"`
- MinimumPrice float64 `protobuf:"fixed64,3,opt,name=minimum_price,json=minimumPrice,proto3" json:"minimum_price,omitempty"`
- MaximumPrice float64 `protobuf:"fixed64,4,opt,name=maximum_price,json=maximumPrice,proto3" json:"maximum_price,omitempty"`
- PercentageGainLoss float64 `protobuf:"fixed64,5,opt,name=percentage_gain_loss,json=percentageGainLoss,proto3" json:"percentage_gain_loss,omitempty"`
- Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"`
+ Orders []*OrderbookItem `protobuf:"bytes,1,rep,name=orders,proto3" json:"orders,omitempty"`
+ Amount float64 `protobuf:"fixed64,2,opt,name=amount,proto3" json:"amount,omitempty"`
+ MinimumPrice float64 `protobuf:"fixed64,3,opt,name=minimum_price,json=minimumPrice,proto3" json:"minimum_price,omitempty"`
+ MaximumPrice float64 `protobuf:"fixed64,4,opt,name=maximum_price,json=maximumPrice,proto3" json:"maximum_price,omitempty"`
+ PercentageGainLoss float64 `protobuf:"fixed64,5,opt,name=percentage_gain_loss,json=percentageGainLoss,proto3" json:"percentage_gain_loss,omitempty"`
+ Status string `protobuf:"bytes,6,opt,name=status,proto3" json:"status,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *SimulateOrderResponse) Reset() {
- *x = SimulateOrderResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[68]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *SimulateOrderResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*SimulateOrderResponse) ProtoMessage() {}
-
-func (x *SimulateOrderResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[68]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use SimulateOrderResponse.ProtoReflect.Descriptor instead.
+func (m *SimulateOrderResponse) Reset() { *m = SimulateOrderResponse{} }
+func (m *SimulateOrderResponse) String() string { return proto.CompactTextString(m) }
+func (*SimulateOrderResponse) ProtoMessage() {}
func (*SimulateOrderResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{68}
+ return fileDescriptor_77a6da22d6a3feb1, []int{64}
}
-func (x *SimulateOrderResponse) GetOrders() []*OrderbookItem {
- if x != nil {
- return x.Orders
+func (m *SimulateOrderResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_SimulateOrderResponse.Unmarshal(m, b)
+}
+func (m *SimulateOrderResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_SimulateOrderResponse.Marshal(b, m, deterministic)
+}
+func (m *SimulateOrderResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_SimulateOrderResponse.Merge(m, src)
+}
+func (m *SimulateOrderResponse) XXX_Size() int {
+ return xxx_messageInfo_SimulateOrderResponse.Size(m)
+}
+func (m *SimulateOrderResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_SimulateOrderResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SimulateOrderResponse proto.InternalMessageInfo
+
+func (m *SimulateOrderResponse) GetOrders() []*OrderbookItem {
+ if m != nil {
+ return m.Orders
}
return nil
}
-func (x *SimulateOrderResponse) GetAmount() float64 {
- if x != nil {
- return x.Amount
+func (m *SimulateOrderResponse) GetAmount() float64 {
+ if m != nil {
+ return m.Amount
}
return 0
}
-func (x *SimulateOrderResponse) GetMinimumPrice() float64 {
- if x != nil {
- return x.MinimumPrice
+func (m *SimulateOrderResponse) GetMinimumPrice() float64 {
+ if m != nil {
+ return m.MinimumPrice
}
return 0
}
-func (x *SimulateOrderResponse) GetMaximumPrice() float64 {
- if x != nil {
- return x.MaximumPrice
+func (m *SimulateOrderResponse) GetMaximumPrice() float64 {
+ if m != nil {
+ return m.MaximumPrice
}
return 0
}
-func (x *SimulateOrderResponse) GetPercentageGainLoss() float64 {
- if x != nil {
- return x.PercentageGainLoss
+func (m *SimulateOrderResponse) GetPercentageGainLoss() float64 {
+ if m != nil {
+ return m.PercentageGainLoss
}
return 0
}
-func (x *SimulateOrderResponse) GetStatus() string {
- if x != nil {
- return x.Status
+func (m *SimulateOrderResponse) GetStatus() string {
+ if m != nil {
+ return m.Status
}
return ""
}
type WhaleBombRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
- Pair *CurrencyPair `protobuf:"bytes,2,opt,name=pair,proto3" json:"pair,omitempty"`
- PriceTarget float64 `protobuf:"fixed64,3,opt,name=price_target,json=priceTarget,proto3" json:"price_target,omitempty"`
- Side string `protobuf:"bytes,4,opt,name=side,proto3" json:"side,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Pair *CurrencyPair `protobuf:"bytes,2,opt,name=pair,proto3" json:"pair,omitempty"`
+ PriceTarget float64 `protobuf:"fixed64,3,opt,name=price_target,json=priceTarget,proto3" json:"price_target,omitempty"`
+ Side string `protobuf:"bytes,4,opt,name=side,proto3" json:"side,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *WhaleBombRequest) Reset() {
- *x = WhaleBombRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[69]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *WhaleBombRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*WhaleBombRequest) ProtoMessage() {}
-
-func (x *WhaleBombRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[69]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use WhaleBombRequest.ProtoReflect.Descriptor instead.
+func (m *WhaleBombRequest) Reset() { *m = WhaleBombRequest{} }
+func (m *WhaleBombRequest) String() string { return proto.CompactTextString(m) }
+func (*WhaleBombRequest) ProtoMessage() {}
func (*WhaleBombRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{69}
+ return fileDescriptor_77a6da22d6a3feb1, []int{65}
}
-func (x *WhaleBombRequest) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *WhaleBombRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_WhaleBombRequest.Unmarshal(m, b)
+}
+func (m *WhaleBombRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_WhaleBombRequest.Marshal(b, m, deterministic)
+}
+func (m *WhaleBombRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_WhaleBombRequest.Merge(m, src)
+}
+func (m *WhaleBombRequest) XXX_Size() int {
+ return xxx_messageInfo_WhaleBombRequest.Size(m)
+}
+func (m *WhaleBombRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_WhaleBombRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_WhaleBombRequest proto.InternalMessageInfo
+
+func (m *WhaleBombRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
-func (x *WhaleBombRequest) GetPair() *CurrencyPair {
- if x != nil {
- return x.Pair
+func (m *WhaleBombRequest) GetPair() *CurrencyPair {
+ if m != nil {
+ return m.Pair
}
return nil
}
-func (x *WhaleBombRequest) GetPriceTarget() float64 {
- if x != nil {
- return x.PriceTarget
+func (m *WhaleBombRequest) GetPriceTarget() float64 {
+ if m != nil {
+ return m.PriceTarget
}
return 0
}
-func (x *WhaleBombRequest) GetSide() string {
- if x != nil {
- return x.Side
+func (m *WhaleBombRequest) GetSide() string {
+ if m != nil {
+ return m.Side
}
return ""
}
type CancelOrderRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
- AccountId string `protobuf:"bytes,2,opt,name=account_id,json=accountId,proto3" json:"account_id,omitempty"`
- OrderId string `protobuf:"bytes,3,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"`
- Pair *CurrencyPair `protobuf:"bytes,4,opt,name=pair,proto3" json:"pair,omitempty"`
- AssetType string `protobuf:"bytes,5,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"`
- WalletAddress string `protobuf:"bytes,6,opt,name=wallet_address,json=walletAddress,proto3" json:"wallet_address,omitempty"`
- Side string `protobuf:"bytes,7,opt,name=side,proto3" json:"side,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ AccountId string `protobuf:"bytes,2,opt,name=account_id,json=accountId,proto3" json:"account_id,omitempty"`
+ OrderId string `protobuf:"bytes,3,opt,name=order_id,json=orderId,proto3" json:"order_id,omitempty"`
+ Pair *CurrencyPair `protobuf:"bytes,4,opt,name=pair,proto3" json:"pair,omitempty"`
+ AssetType string `protobuf:"bytes,5,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"`
+ WalletAddress string `protobuf:"bytes,6,opt,name=wallet_address,json=walletAddress,proto3" json:"wallet_address,omitempty"`
+ Side string `protobuf:"bytes,7,opt,name=side,proto3" json:"side,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *CancelOrderRequest) Reset() {
- *x = CancelOrderRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[70]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *CancelOrderRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*CancelOrderRequest) ProtoMessage() {}
-
-func (x *CancelOrderRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[70]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use CancelOrderRequest.ProtoReflect.Descriptor instead.
+func (m *CancelOrderRequest) Reset() { *m = CancelOrderRequest{} }
+func (m *CancelOrderRequest) String() string { return proto.CompactTextString(m) }
+func (*CancelOrderRequest) ProtoMessage() {}
func (*CancelOrderRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{70}
+ return fileDescriptor_77a6da22d6a3feb1, []int{66}
}
-func (x *CancelOrderRequest) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *CancelOrderRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_CancelOrderRequest.Unmarshal(m, b)
+}
+func (m *CancelOrderRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_CancelOrderRequest.Marshal(b, m, deterministic)
+}
+func (m *CancelOrderRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_CancelOrderRequest.Merge(m, src)
+}
+func (m *CancelOrderRequest) XXX_Size() int {
+ return xxx_messageInfo_CancelOrderRequest.Size(m)
+}
+func (m *CancelOrderRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_CancelOrderRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_CancelOrderRequest proto.InternalMessageInfo
+
+func (m *CancelOrderRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
-func (x *CancelOrderRequest) GetAccountId() string {
- if x != nil {
- return x.AccountId
+func (m *CancelOrderRequest) GetAccountId() string {
+ if m != nil {
+ return m.AccountId
}
return ""
}
-func (x *CancelOrderRequest) GetOrderId() string {
- if x != nil {
- return x.OrderId
+func (m *CancelOrderRequest) GetOrderId() string {
+ if m != nil {
+ return m.OrderId
}
return ""
}
-func (x *CancelOrderRequest) GetPair() *CurrencyPair {
- if x != nil {
- return x.Pair
+func (m *CancelOrderRequest) GetPair() *CurrencyPair {
+ if m != nil {
+ return m.Pair
}
return nil
}
-func (x *CancelOrderRequest) GetAssetType() string {
- if x != nil {
- return x.AssetType
+func (m *CancelOrderRequest) GetAssetType() string {
+ if m != nil {
+ return m.AssetType
}
return ""
}
-func (x *CancelOrderRequest) GetWalletAddress() string {
- if x != nil {
- return x.WalletAddress
+func (m *CancelOrderRequest) GetWalletAddress() string {
+ if m != nil {
+ return m.WalletAddress
}
return ""
}
-func (x *CancelOrderRequest) GetSide() string {
- if x != nil {
- return x.Side
+func (m *CancelOrderRequest) GetSide() string {
+ if m != nil {
+ return m.Side
}
return ""
}
-type CancelOrderResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-}
-
-func (x *CancelOrderResponse) Reset() {
- *x = CancelOrderResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[71]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *CancelOrderResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*CancelOrderResponse) ProtoMessage() {}
-
-func (x *CancelOrderResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[71]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use CancelOrderResponse.ProtoReflect.Descriptor instead.
-func (*CancelOrderResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{71}
-}
-
type CancelAllOrdersRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *CancelAllOrdersRequest) Reset() {
- *x = CancelAllOrdersRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[72]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *CancelAllOrdersRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*CancelAllOrdersRequest) ProtoMessage() {}
-
-func (x *CancelAllOrdersRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[72]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use CancelAllOrdersRequest.ProtoReflect.Descriptor instead.
+func (m *CancelAllOrdersRequest) Reset() { *m = CancelAllOrdersRequest{} }
+func (m *CancelAllOrdersRequest) String() string { return proto.CompactTextString(m) }
+func (*CancelAllOrdersRequest) ProtoMessage() {}
func (*CancelAllOrdersRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{72}
+ return fileDescriptor_77a6da22d6a3feb1, []int{67}
}
-func (x *CancelAllOrdersRequest) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *CancelAllOrdersRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_CancelAllOrdersRequest.Unmarshal(m, b)
+}
+func (m *CancelAllOrdersRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_CancelAllOrdersRequest.Marshal(b, m, deterministic)
+}
+func (m *CancelAllOrdersRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_CancelAllOrdersRequest.Merge(m, src)
+}
+func (m *CancelAllOrdersRequest) XXX_Size() int {
+ return xxx_messageInfo_CancelAllOrdersRequest.Size(m)
+}
+func (m *CancelAllOrdersRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_CancelAllOrdersRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_CancelAllOrdersRequest proto.InternalMessageInfo
+
+func (m *CancelAllOrdersRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
type CancelAllOrdersResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Orders []*CancelAllOrdersResponse_Orders `protobuf:"bytes,1,rep,name=orders,proto3" json:"orders,omitempty"`
+ Orders []*CancelAllOrdersResponse_Orders `protobuf:"bytes,1,rep,name=orders,proto3" json:"orders,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *CancelAllOrdersResponse) Reset() {
- *x = CancelAllOrdersResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[73]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *CancelAllOrdersResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*CancelAllOrdersResponse) ProtoMessage() {}
-
-func (x *CancelAllOrdersResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[73]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use CancelAllOrdersResponse.ProtoReflect.Descriptor instead.
+func (m *CancelAllOrdersResponse) Reset() { *m = CancelAllOrdersResponse{} }
+func (m *CancelAllOrdersResponse) String() string { return proto.CompactTextString(m) }
+func (*CancelAllOrdersResponse) ProtoMessage() {}
func (*CancelAllOrdersResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{73}
+ return fileDescriptor_77a6da22d6a3feb1, []int{68}
}
-func (x *CancelAllOrdersResponse) GetOrders() []*CancelAllOrdersResponse_Orders {
- if x != nil {
- return x.Orders
+func (m *CancelAllOrdersResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_CancelAllOrdersResponse.Unmarshal(m, b)
+}
+func (m *CancelAllOrdersResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_CancelAllOrdersResponse.Marshal(b, m, deterministic)
+}
+func (m *CancelAllOrdersResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_CancelAllOrdersResponse.Merge(m, src)
+}
+func (m *CancelAllOrdersResponse) XXX_Size() int {
+ return xxx_messageInfo_CancelAllOrdersResponse.Size(m)
+}
+func (m *CancelAllOrdersResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_CancelAllOrdersResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_CancelAllOrdersResponse proto.InternalMessageInfo
+
+func (m *CancelAllOrdersResponse) GetOrders() []*CancelAllOrdersResponse_Orders {
+ if m != nil {
+ return m.Orders
+ }
+ return nil
+}
+
+type CancelAllOrdersResponse_Orders struct {
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ OrderStatus map[string]string `protobuf:"bytes,2,rep,name=order_status,json=orderStatus,proto3" json:"order_status,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *CancelAllOrdersResponse_Orders) Reset() { *m = CancelAllOrdersResponse_Orders{} }
+func (m *CancelAllOrdersResponse_Orders) String() string { return proto.CompactTextString(m) }
+func (*CancelAllOrdersResponse_Orders) ProtoMessage() {}
+func (*CancelAllOrdersResponse_Orders) Descriptor() ([]byte, []int) {
+ return fileDescriptor_77a6da22d6a3feb1, []int{68, 0}
+}
+
+func (m *CancelAllOrdersResponse_Orders) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_CancelAllOrdersResponse_Orders.Unmarshal(m, b)
+}
+func (m *CancelAllOrdersResponse_Orders) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_CancelAllOrdersResponse_Orders.Marshal(b, m, deterministic)
+}
+func (m *CancelAllOrdersResponse_Orders) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_CancelAllOrdersResponse_Orders.Merge(m, src)
+}
+func (m *CancelAllOrdersResponse_Orders) XXX_Size() int {
+ return xxx_messageInfo_CancelAllOrdersResponse_Orders.Size(m)
+}
+func (m *CancelAllOrdersResponse_Orders) XXX_DiscardUnknown() {
+ xxx_messageInfo_CancelAllOrdersResponse_Orders.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_CancelAllOrdersResponse_Orders proto.InternalMessageInfo
+
+func (m *CancelAllOrdersResponse_Orders) GetExchange() string {
+ if m != nil {
+ return m.Exchange
+ }
+ return ""
+}
+
+func (m *CancelAllOrdersResponse_Orders) GetOrderStatus() map[string]string {
+ if m != nil {
+ return m.OrderStatus
}
return nil
}
type GetEventsRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetEventsRequest) Reset() {
- *x = GetEventsRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[74]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetEventsRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetEventsRequest) ProtoMessage() {}
-
-func (x *GetEventsRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[74]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetEventsRequest.ProtoReflect.Descriptor instead.
+func (m *GetEventsRequest) Reset() { *m = GetEventsRequest{} }
+func (m *GetEventsRequest) String() string { return proto.CompactTextString(m) }
+func (*GetEventsRequest) ProtoMessage() {}
func (*GetEventsRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{74}
+ return fileDescriptor_77a6da22d6a3feb1, []int{69}
}
+func (m *GetEventsRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetEventsRequest.Unmarshal(m, b)
+}
+func (m *GetEventsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetEventsRequest.Marshal(b, m, deterministic)
+}
+func (m *GetEventsRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetEventsRequest.Merge(m, src)
+}
+func (m *GetEventsRequest) XXX_Size() int {
+ return xxx_messageInfo_GetEventsRequest.Size(m)
+}
+func (m *GetEventsRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetEventsRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetEventsRequest proto.InternalMessageInfo
+
type ConditionParams struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Condition string `protobuf:"bytes,1,opt,name=condition,proto3" json:"condition,omitempty"`
- Price float64 `protobuf:"fixed64,2,opt,name=price,proto3" json:"price,omitempty"`
- CheckBids bool `protobuf:"varint,3,opt,name=check_bids,json=checkBids,proto3" json:"check_bids,omitempty"`
- CheckBidsAndAsks bool `protobuf:"varint,4,opt,name=check_bids_and_asks,json=checkBidsAndAsks,proto3" json:"check_bids_and_asks,omitempty"`
- OrderbookAmount float64 `protobuf:"fixed64,5,opt,name=orderbook_amount,json=orderbookAmount,proto3" json:"orderbook_amount,omitempty"`
+ Condition string `protobuf:"bytes,1,opt,name=condition,proto3" json:"condition,omitempty"`
+ Price float64 `protobuf:"fixed64,2,opt,name=price,proto3" json:"price,omitempty"`
+ CheckBids bool `protobuf:"varint,3,opt,name=check_bids,json=checkBids,proto3" json:"check_bids,omitempty"`
+ CheckBidsAndAsks bool `protobuf:"varint,4,opt,name=check_bids_and_asks,json=checkBidsAndAsks,proto3" json:"check_bids_and_asks,omitempty"`
+ OrderbookAmount float64 `protobuf:"fixed64,5,opt,name=orderbook_amount,json=orderbookAmount,proto3" json:"orderbook_amount,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *ConditionParams) Reset() {
- *x = ConditionParams{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[75]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *ConditionParams) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*ConditionParams) ProtoMessage() {}
-
-func (x *ConditionParams) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[75]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use ConditionParams.ProtoReflect.Descriptor instead.
+func (m *ConditionParams) Reset() { *m = ConditionParams{} }
+func (m *ConditionParams) String() string { return proto.CompactTextString(m) }
+func (*ConditionParams) ProtoMessage() {}
func (*ConditionParams) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{75}
+ return fileDescriptor_77a6da22d6a3feb1, []int{70}
}
-func (x *ConditionParams) GetCondition() string {
- if x != nil {
- return x.Condition
+func (m *ConditionParams) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_ConditionParams.Unmarshal(m, b)
+}
+func (m *ConditionParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_ConditionParams.Marshal(b, m, deterministic)
+}
+func (m *ConditionParams) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_ConditionParams.Merge(m, src)
+}
+func (m *ConditionParams) XXX_Size() int {
+ return xxx_messageInfo_ConditionParams.Size(m)
+}
+func (m *ConditionParams) XXX_DiscardUnknown() {
+ xxx_messageInfo_ConditionParams.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_ConditionParams proto.InternalMessageInfo
+
+func (m *ConditionParams) GetCondition() string {
+ if m != nil {
+ return m.Condition
}
return ""
}
-func (x *ConditionParams) GetPrice() float64 {
- if x != nil {
- return x.Price
+func (m *ConditionParams) GetPrice() float64 {
+ if m != nil {
+ return m.Price
}
return 0
}
-func (x *ConditionParams) GetCheckBids() bool {
- if x != nil {
- return x.CheckBids
+func (m *ConditionParams) GetCheckBids() bool {
+ if m != nil {
+ return m.CheckBids
}
return false
}
-func (x *ConditionParams) GetCheckBidsAndAsks() bool {
- if x != nil {
- return x.CheckBidsAndAsks
+func (m *ConditionParams) GetCheckBidsAndAsks() bool {
+ if m != nil {
+ return m.CheckBidsAndAsks
}
return false
}
-func (x *ConditionParams) GetOrderbookAmount() float64 {
- if x != nil {
- return x.OrderbookAmount
+func (m *ConditionParams) GetOrderbookAmount() float64 {
+ if m != nil {
+ return m.OrderbookAmount
}
return 0
}
type GetEventsResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
- Exchange string `protobuf:"bytes,2,opt,name=exchange,proto3" json:"exchange,omitempty"`
- Item string `protobuf:"bytes,3,opt,name=item,proto3" json:"item,omitempty"`
- ConditionParams *ConditionParams `protobuf:"bytes,4,opt,name=condition_params,json=conditionParams,proto3" json:"condition_params,omitempty"`
- Pair *CurrencyPair `protobuf:"bytes,5,opt,name=pair,proto3" json:"pair,omitempty"`
- Action string `protobuf:"bytes,6,opt,name=action,proto3" json:"action,omitempty"`
- Executed bool `protobuf:"varint,7,opt,name=executed,proto3" json:"executed,omitempty"`
+ Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
+ Exchange string `protobuf:"bytes,2,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Item string `protobuf:"bytes,3,opt,name=item,proto3" json:"item,omitempty"`
+ ConditionParams *ConditionParams `protobuf:"bytes,4,opt,name=condition_params,json=conditionParams,proto3" json:"condition_params,omitempty"`
+ Pair *CurrencyPair `protobuf:"bytes,5,opt,name=pair,proto3" json:"pair,omitempty"`
+ Action string `protobuf:"bytes,6,opt,name=action,proto3" json:"action,omitempty"`
+ Executed bool `protobuf:"varint,7,opt,name=executed,proto3" json:"executed,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetEventsResponse) Reset() {
- *x = GetEventsResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[76]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetEventsResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetEventsResponse) ProtoMessage() {}
-
-func (x *GetEventsResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[76]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetEventsResponse.ProtoReflect.Descriptor instead.
+func (m *GetEventsResponse) Reset() { *m = GetEventsResponse{} }
+func (m *GetEventsResponse) String() string { return proto.CompactTextString(m) }
+func (*GetEventsResponse) ProtoMessage() {}
func (*GetEventsResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{76}
+ return fileDescriptor_77a6da22d6a3feb1, []int{71}
}
-func (x *GetEventsResponse) GetId() int64 {
- if x != nil {
- return x.Id
+func (m *GetEventsResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetEventsResponse.Unmarshal(m, b)
+}
+func (m *GetEventsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetEventsResponse.Marshal(b, m, deterministic)
+}
+func (m *GetEventsResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetEventsResponse.Merge(m, src)
+}
+func (m *GetEventsResponse) XXX_Size() int {
+ return xxx_messageInfo_GetEventsResponse.Size(m)
+}
+func (m *GetEventsResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetEventsResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetEventsResponse proto.InternalMessageInfo
+
+func (m *GetEventsResponse) GetId() int64 {
+ if m != nil {
+ return m.Id
}
return 0
}
-func (x *GetEventsResponse) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *GetEventsResponse) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
-func (x *GetEventsResponse) GetItem() string {
- if x != nil {
- return x.Item
+func (m *GetEventsResponse) GetItem() string {
+ if m != nil {
+ return m.Item
}
return ""
}
-func (x *GetEventsResponse) GetConditionParams() *ConditionParams {
- if x != nil {
- return x.ConditionParams
+func (m *GetEventsResponse) GetConditionParams() *ConditionParams {
+ if m != nil {
+ return m.ConditionParams
}
return nil
}
-func (x *GetEventsResponse) GetPair() *CurrencyPair {
- if x != nil {
- return x.Pair
+func (m *GetEventsResponse) GetPair() *CurrencyPair {
+ if m != nil {
+ return m.Pair
}
return nil
}
-func (x *GetEventsResponse) GetAction() string {
- if x != nil {
- return x.Action
+func (m *GetEventsResponse) GetAction() string {
+ if m != nil {
+ return m.Action
}
return ""
}
-func (x *GetEventsResponse) GetExecuted() bool {
- if x != nil {
- return x.Executed
+func (m *GetEventsResponse) GetExecuted() bool {
+ if m != nil {
+ return m.Executed
}
return false
}
type AddEventRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
- Item string `protobuf:"bytes,2,opt,name=item,proto3" json:"item,omitempty"`
- ConditionParams *ConditionParams `protobuf:"bytes,3,opt,name=condition_params,json=conditionParams,proto3" json:"condition_params,omitempty"`
- Pair *CurrencyPair `protobuf:"bytes,4,opt,name=pair,proto3" json:"pair,omitempty"`
- AssetType string `protobuf:"bytes,5,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"`
- Action string `protobuf:"bytes,6,opt,name=action,proto3" json:"action,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Item string `protobuf:"bytes,2,opt,name=item,proto3" json:"item,omitempty"`
+ ConditionParams *ConditionParams `protobuf:"bytes,3,opt,name=condition_params,json=conditionParams,proto3" json:"condition_params,omitempty"`
+ Pair *CurrencyPair `protobuf:"bytes,4,opt,name=pair,proto3" json:"pair,omitempty"`
+ AssetType string `protobuf:"bytes,5,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"`
+ Action string `protobuf:"bytes,6,opt,name=action,proto3" json:"action,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *AddEventRequest) Reset() {
- *x = AddEventRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[77]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *AddEventRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*AddEventRequest) ProtoMessage() {}
-
-func (x *AddEventRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[77]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use AddEventRequest.ProtoReflect.Descriptor instead.
+func (m *AddEventRequest) Reset() { *m = AddEventRequest{} }
+func (m *AddEventRequest) String() string { return proto.CompactTextString(m) }
+func (*AddEventRequest) ProtoMessage() {}
func (*AddEventRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{77}
+ return fileDescriptor_77a6da22d6a3feb1, []int{72}
}
-func (x *AddEventRequest) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *AddEventRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_AddEventRequest.Unmarshal(m, b)
+}
+func (m *AddEventRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_AddEventRequest.Marshal(b, m, deterministic)
+}
+func (m *AddEventRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_AddEventRequest.Merge(m, src)
+}
+func (m *AddEventRequest) XXX_Size() int {
+ return xxx_messageInfo_AddEventRequest.Size(m)
+}
+func (m *AddEventRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_AddEventRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_AddEventRequest proto.InternalMessageInfo
+
+func (m *AddEventRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
-func (x *AddEventRequest) GetItem() string {
- if x != nil {
- return x.Item
+func (m *AddEventRequest) GetItem() string {
+ if m != nil {
+ return m.Item
}
return ""
}
-func (x *AddEventRequest) GetConditionParams() *ConditionParams {
- if x != nil {
- return x.ConditionParams
+func (m *AddEventRequest) GetConditionParams() *ConditionParams {
+ if m != nil {
+ return m.ConditionParams
}
return nil
}
-func (x *AddEventRequest) GetPair() *CurrencyPair {
- if x != nil {
- return x.Pair
+func (m *AddEventRequest) GetPair() *CurrencyPair {
+ if m != nil {
+ return m.Pair
}
return nil
}
-func (x *AddEventRequest) GetAssetType() string {
- if x != nil {
- return x.AssetType
+func (m *AddEventRequest) GetAssetType() string {
+ if m != nil {
+ return m.AssetType
}
return ""
}
-func (x *AddEventRequest) GetAction() string {
- if x != nil {
- return x.Action
+func (m *AddEventRequest) GetAction() string {
+ if m != nil {
+ return m.Action
}
return ""
}
type AddEventResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
+ Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *AddEventResponse) Reset() {
- *x = AddEventResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[78]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *AddEventResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*AddEventResponse) ProtoMessage() {}
-
-func (x *AddEventResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[78]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use AddEventResponse.ProtoReflect.Descriptor instead.
+func (m *AddEventResponse) Reset() { *m = AddEventResponse{} }
+func (m *AddEventResponse) String() string { return proto.CompactTextString(m) }
+func (*AddEventResponse) ProtoMessage() {}
func (*AddEventResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{78}
+ return fileDescriptor_77a6da22d6a3feb1, []int{73}
}
-func (x *AddEventResponse) GetId() int64 {
- if x != nil {
- return x.Id
+func (m *AddEventResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_AddEventResponse.Unmarshal(m, b)
+}
+func (m *AddEventResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_AddEventResponse.Marshal(b, m, deterministic)
+}
+func (m *AddEventResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_AddEventResponse.Merge(m, src)
+}
+func (m *AddEventResponse) XXX_Size() int {
+ return xxx_messageInfo_AddEventResponse.Size(m)
+}
+func (m *AddEventResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_AddEventResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_AddEventResponse proto.InternalMessageInfo
+
+func (m *AddEventResponse) GetId() int64 {
+ if m != nil {
+ return m.Id
}
return 0
}
type RemoveEventRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
+ Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *RemoveEventRequest) Reset() {
- *x = RemoveEventRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[79]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *RemoveEventRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*RemoveEventRequest) ProtoMessage() {}
-
-func (x *RemoveEventRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[79]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use RemoveEventRequest.ProtoReflect.Descriptor instead.
+func (m *RemoveEventRequest) Reset() { *m = RemoveEventRequest{} }
+func (m *RemoveEventRequest) String() string { return proto.CompactTextString(m) }
+func (*RemoveEventRequest) ProtoMessage() {}
func (*RemoveEventRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{79}
+ return fileDescriptor_77a6da22d6a3feb1, []int{74}
}
-func (x *RemoveEventRequest) GetId() int64 {
- if x != nil {
- return x.Id
+func (m *RemoveEventRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_RemoveEventRequest.Unmarshal(m, b)
+}
+func (m *RemoveEventRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_RemoveEventRequest.Marshal(b, m, deterministic)
+}
+func (m *RemoveEventRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_RemoveEventRequest.Merge(m, src)
+}
+func (m *RemoveEventRequest) XXX_Size() int {
+ return xxx_messageInfo_RemoveEventRequest.Size(m)
+}
+func (m *RemoveEventRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_RemoveEventRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_RemoveEventRequest proto.InternalMessageInfo
+
+func (m *RemoveEventRequest) GetId() int64 {
+ if m != nil {
+ return m.Id
}
return 0
}
-type RemoveEventResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-}
-
-func (x *RemoveEventResponse) Reset() {
- *x = RemoveEventResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[80]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *RemoveEventResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*RemoveEventResponse) ProtoMessage() {}
-
-func (x *RemoveEventResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[80]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use RemoveEventResponse.ProtoReflect.Descriptor instead.
-func (*RemoveEventResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{80}
-}
-
type GetCryptocurrencyDepositAddressesRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetCryptocurrencyDepositAddressesRequest) Reset() {
- *x = GetCryptocurrencyDepositAddressesRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[81]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+func (m *GetCryptocurrencyDepositAddressesRequest) Reset() {
+ *m = GetCryptocurrencyDepositAddressesRequest{}
}
-
-func (x *GetCryptocurrencyDepositAddressesRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetCryptocurrencyDepositAddressesRequest) ProtoMessage() {}
-
-func (x *GetCryptocurrencyDepositAddressesRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[81]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetCryptocurrencyDepositAddressesRequest.ProtoReflect.Descriptor instead.
+func (m *GetCryptocurrencyDepositAddressesRequest) String() string { return proto.CompactTextString(m) }
+func (*GetCryptocurrencyDepositAddressesRequest) ProtoMessage() {}
func (*GetCryptocurrencyDepositAddressesRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{81}
+ return fileDescriptor_77a6da22d6a3feb1, []int{75}
}
-func (x *GetCryptocurrencyDepositAddressesRequest) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *GetCryptocurrencyDepositAddressesRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetCryptocurrencyDepositAddressesRequest.Unmarshal(m, b)
+}
+func (m *GetCryptocurrencyDepositAddressesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetCryptocurrencyDepositAddressesRequest.Marshal(b, m, deterministic)
+}
+func (m *GetCryptocurrencyDepositAddressesRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetCryptocurrencyDepositAddressesRequest.Merge(m, src)
+}
+func (m *GetCryptocurrencyDepositAddressesRequest) XXX_Size() int {
+ return xxx_messageInfo_GetCryptocurrencyDepositAddressesRequest.Size(m)
+}
+func (m *GetCryptocurrencyDepositAddressesRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetCryptocurrencyDepositAddressesRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetCryptocurrencyDepositAddressesRequest proto.InternalMessageInfo
+
+func (m *GetCryptocurrencyDepositAddressesRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
type GetCryptocurrencyDepositAddressesResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Addresses map[string]string `protobuf:"bytes,1,rep,name=addresses,proto3" json:"addresses,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+ Addresses map[string]string `protobuf:"bytes,1,rep,name=addresses,proto3" json:"addresses,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetCryptocurrencyDepositAddressesResponse) Reset() {
- *x = GetCryptocurrencyDepositAddressesResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[82]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+func (m *GetCryptocurrencyDepositAddressesResponse) Reset() {
+ *m = GetCryptocurrencyDepositAddressesResponse{}
}
-
-func (x *GetCryptocurrencyDepositAddressesResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetCryptocurrencyDepositAddressesResponse) ProtoMessage() {}
-
-func (x *GetCryptocurrencyDepositAddressesResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[82]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetCryptocurrencyDepositAddressesResponse.ProtoReflect.Descriptor instead.
+func (m *GetCryptocurrencyDepositAddressesResponse) String() string { return proto.CompactTextString(m) }
+func (*GetCryptocurrencyDepositAddressesResponse) ProtoMessage() {}
func (*GetCryptocurrencyDepositAddressesResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{82}
+ return fileDescriptor_77a6da22d6a3feb1, []int{76}
}
-func (x *GetCryptocurrencyDepositAddressesResponse) GetAddresses() map[string]string {
- if x != nil {
- return x.Addresses
+func (m *GetCryptocurrencyDepositAddressesResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetCryptocurrencyDepositAddressesResponse.Unmarshal(m, b)
+}
+func (m *GetCryptocurrencyDepositAddressesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetCryptocurrencyDepositAddressesResponse.Marshal(b, m, deterministic)
+}
+func (m *GetCryptocurrencyDepositAddressesResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetCryptocurrencyDepositAddressesResponse.Merge(m, src)
+}
+func (m *GetCryptocurrencyDepositAddressesResponse) XXX_Size() int {
+ return xxx_messageInfo_GetCryptocurrencyDepositAddressesResponse.Size(m)
+}
+func (m *GetCryptocurrencyDepositAddressesResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetCryptocurrencyDepositAddressesResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetCryptocurrencyDepositAddressesResponse proto.InternalMessageInfo
+
+func (m *GetCryptocurrencyDepositAddressesResponse) GetAddresses() map[string]string {
+ if m != nil {
+ return m.Addresses
}
return nil
}
type GetCryptocurrencyDepositAddressRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
- Cryptocurrency string `protobuf:"bytes,2,opt,name=cryptocurrency,proto3" json:"cryptocurrency,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Cryptocurrency string `protobuf:"bytes,2,opt,name=cryptocurrency,proto3" json:"cryptocurrency,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetCryptocurrencyDepositAddressRequest) Reset() {
- *x = GetCryptocurrencyDepositAddressRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[83]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+func (m *GetCryptocurrencyDepositAddressRequest) Reset() {
+ *m = GetCryptocurrencyDepositAddressRequest{}
}
-
-func (x *GetCryptocurrencyDepositAddressRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetCryptocurrencyDepositAddressRequest) ProtoMessage() {}
-
-func (x *GetCryptocurrencyDepositAddressRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[83]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetCryptocurrencyDepositAddressRequest.ProtoReflect.Descriptor instead.
+func (m *GetCryptocurrencyDepositAddressRequest) String() string { return proto.CompactTextString(m) }
+func (*GetCryptocurrencyDepositAddressRequest) ProtoMessage() {}
func (*GetCryptocurrencyDepositAddressRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{83}
+ return fileDescriptor_77a6da22d6a3feb1, []int{77}
}
-func (x *GetCryptocurrencyDepositAddressRequest) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *GetCryptocurrencyDepositAddressRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetCryptocurrencyDepositAddressRequest.Unmarshal(m, b)
+}
+func (m *GetCryptocurrencyDepositAddressRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetCryptocurrencyDepositAddressRequest.Marshal(b, m, deterministic)
+}
+func (m *GetCryptocurrencyDepositAddressRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetCryptocurrencyDepositAddressRequest.Merge(m, src)
+}
+func (m *GetCryptocurrencyDepositAddressRequest) XXX_Size() int {
+ return xxx_messageInfo_GetCryptocurrencyDepositAddressRequest.Size(m)
+}
+func (m *GetCryptocurrencyDepositAddressRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetCryptocurrencyDepositAddressRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetCryptocurrencyDepositAddressRequest proto.InternalMessageInfo
+
+func (m *GetCryptocurrencyDepositAddressRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
-func (x *GetCryptocurrencyDepositAddressRequest) GetCryptocurrency() string {
- if x != nil {
- return x.Cryptocurrency
+func (m *GetCryptocurrencyDepositAddressRequest) GetCryptocurrency() string {
+ if m != nil {
+ return m.Cryptocurrency
}
return ""
}
type GetCryptocurrencyDepositAddressResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
+ Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetCryptocurrencyDepositAddressResponse) Reset() {
- *x = GetCryptocurrencyDepositAddressResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[84]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+func (m *GetCryptocurrencyDepositAddressResponse) Reset() {
+ *m = GetCryptocurrencyDepositAddressResponse{}
}
-
-func (x *GetCryptocurrencyDepositAddressResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetCryptocurrencyDepositAddressResponse) ProtoMessage() {}
-
-func (x *GetCryptocurrencyDepositAddressResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[84]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetCryptocurrencyDepositAddressResponse.ProtoReflect.Descriptor instead.
+func (m *GetCryptocurrencyDepositAddressResponse) String() string { return proto.CompactTextString(m) }
+func (*GetCryptocurrencyDepositAddressResponse) ProtoMessage() {}
func (*GetCryptocurrencyDepositAddressResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{84}
+ return fileDescriptor_77a6da22d6a3feb1, []int{78}
}
-func (x *GetCryptocurrencyDepositAddressResponse) GetAddress() string {
- if x != nil {
- return x.Address
+func (m *GetCryptocurrencyDepositAddressResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetCryptocurrencyDepositAddressResponse.Unmarshal(m, b)
+}
+func (m *GetCryptocurrencyDepositAddressResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetCryptocurrencyDepositAddressResponse.Marshal(b, m, deterministic)
+}
+func (m *GetCryptocurrencyDepositAddressResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetCryptocurrencyDepositAddressResponse.Merge(m, src)
+}
+func (m *GetCryptocurrencyDepositAddressResponse) XXX_Size() int {
+ return xxx_messageInfo_GetCryptocurrencyDepositAddressResponse.Size(m)
+}
+func (m *GetCryptocurrencyDepositAddressResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetCryptocurrencyDepositAddressResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetCryptocurrencyDepositAddressResponse proto.InternalMessageInfo
+
+func (m *GetCryptocurrencyDepositAddressResponse) GetAddress() string {
+ if m != nil {
+ return m.Address
}
return ""
}
type WithdrawFiatRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
- Currency string `protobuf:"bytes,2,opt,name=currency,proto3" json:"currency,omitempty"`
- Amount float64 `protobuf:"fixed64,3,opt,name=amount,proto3" json:"amount,omitempty"`
- Description string `protobuf:"bytes,4,opt,name=description,proto3" json:"description,omitempty"`
- BankAccountId string `protobuf:"bytes,5,opt,name=bank_account_id,json=bankAccountId,proto3" json:"bank_account_id,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Currency string `protobuf:"bytes,2,opt,name=currency,proto3" json:"currency,omitempty"`
+ Amount float64 `protobuf:"fixed64,3,opt,name=amount,proto3" json:"amount,omitempty"`
+ Description string `protobuf:"bytes,4,opt,name=description,proto3" json:"description,omitempty"`
+ BankAccountId string `protobuf:"bytes,5,opt,name=bank_account_id,json=bankAccountId,proto3" json:"bank_account_id,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *WithdrawFiatRequest) Reset() {
- *x = WithdrawFiatRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[85]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *WithdrawFiatRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*WithdrawFiatRequest) ProtoMessage() {}
-
-func (x *WithdrawFiatRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[85]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use WithdrawFiatRequest.ProtoReflect.Descriptor instead.
+func (m *WithdrawFiatRequest) Reset() { *m = WithdrawFiatRequest{} }
+func (m *WithdrawFiatRequest) String() string { return proto.CompactTextString(m) }
+func (*WithdrawFiatRequest) ProtoMessage() {}
func (*WithdrawFiatRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{85}
+ return fileDescriptor_77a6da22d6a3feb1, []int{79}
}
-func (x *WithdrawFiatRequest) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *WithdrawFiatRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_WithdrawFiatRequest.Unmarshal(m, b)
+}
+func (m *WithdrawFiatRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_WithdrawFiatRequest.Marshal(b, m, deterministic)
+}
+func (m *WithdrawFiatRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_WithdrawFiatRequest.Merge(m, src)
+}
+func (m *WithdrawFiatRequest) XXX_Size() int {
+ return xxx_messageInfo_WithdrawFiatRequest.Size(m)
+}
+func (m *WithdrawFiatRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_WithdrawFiatRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_WithdrawFiatRequest proto.InternalMessageInfo
+
+func (m *WithdrawFiatRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
-func (x *WithdrawFiatRequest) GetCurrency() string {
- if x != nil {
- return x.Currency
+func (m *WithdrawFiatRequest) GetCurrency() string {
+ if m != nil {
+ return m.Currency
}
return ""
}
-func (x *WithdrawFiatRequest) GetAmount() float64 {
- if x != nil {
- return x.Amount
+func (m *WithdrawFiatRequest) GetAmount() float64 {
+ if m != nil {
+ return m.Amount
}
return 0
}
-func (x *WithdrawFiatRequest) GetDescription() string {
- if x != nil {
- return x.Description
+func (m *WithdrawFiatRequest) GetDescription() string {
+ if m != nil {
+ return m.Description
}
return ""
}
-func (x *WithdrawFiatRequest) GetBankAccountId() string {
- if x != nil {
- return x.BankAccountId
+func (m *WithdrawFiatRequest) GetBankAccountId() string {
+ if m != nil {
+ return m.BankAccountId
}
return ""
}
type WithdrawCryptoRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
- Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"`
- AddressTag string `protobuf:"bytes,3,opt,name=address_tag,json=addressTag,proto3" json:"address_tag,omitempty"`
- Currency string `protobuf:"bytes,4,opt,name=currency,proto3" json:"currency,omitempty"`
- Amount float64 `protobuf:"fixed64,5,opt,name=amount,proto3" json:"amount,omitempty"`
- Fee float64 `protobuf:"fixed64,6,opt,name=fee,proto3" json:"fee,omitempty"`
- Description string `protobuf:"bytes,7,opt,name=description,proto3" json:"description,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"`
+ AddressTag string `protobuf:"bytes,3,opt,name=address_tag,json=addressTag,proto3" json:"address_tag,omitempty"`
+ Currency string `protobuf:"bytes,4,opt,name=currency,proto3" json:"currency,omitempty"`
+ Amount float64 `protobuf:"fixed64,5,opt,name=amount,proto3" json:"amount,omitempty"`
+ Fee float64 `protobuf:"fixed64,6,opt,name=fee,proto3" json:"fee,omitempty"`
+ Description string `protobuf:"bytes,7,opt,name=description,proto3" json:"description,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *WithdrawCryptoRequest) Reset() {
- *x = WithdrawCryptoRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[86]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *WithdrawCryptoRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*WithdrawCryptoRequest) ProtoMessage() {}
-
-func (x *WithdrawCryptoRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[86]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use WithdrawCryptoRequest.ProtoReflect.Descriptor instead.
+func (m *WithdrawCryptoRequest) Reset() { *m = WithdrawCryptoRequest{} }
+func (m *WithdrawCryptoRequest) String() string { return proto.CompactTextString(m) }
+func (*WithdrawCryptoRequest) ProtoMessage() {}
func (*WithdrawCryptoRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{86}
+ return fileDescriptor_77a6da22d6a3feb1, []int{80}
}
-func (x *WithdrawCryptoRequest) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *WithdrawCryptoRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_WithdrawCryptoRequest.Unmarshal(m, b)
+}
+func (m *WithdrawCryptoRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_WithdrawCryptoRequest.Marshal(b, m, deterministic)
+}
+func (m *WithdrawCryptoRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_WithdrawCryptoRequest.Merge(m, src)
+}
+func (m *WithdrawCryptoRequest) XXX_Size() int {
+ return xxx_messageInfo_WithdrawCryptoRequest.Size(m)
+}
+func (m *WithdrawCryptoRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_WithdrawCryptoRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_WithdrawCryptoRequest proto.InternalMessageInfo
+
+func (m *WithdrawCryptoRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
-func (x *WithdrawCryptoRequest) GetAddress() string {
- if x != nil {
- return x.Address
+func (m *WithdrawCryptoRequest) GetAddress() string {
+ if m != nil {
+ return m.Address
}
return ""
}
-func (x *WithdrawCryptoRequest) GetAddressTag() string {
- if x != nil {
- return x.AddressTag
+func (m *WithdrawCryptoRequest) GetAddressTag() string {
+ if m != nil {
+ return m.AddressTag
}
return ""
}
-func (x *WithdrawCryptoRequest) GetCurrency() string {
- if x != nil {
- return x.Currency
+func (m *WithdrawCryptoRequest) GetCurrency() string {
+ if m != nil {
+ return m.Currency
}
return ""
}
-func (x *WithdrawCryptoRequest) GetAmount() float64 {
- if x != nil {
- return x.Amount
+func (m *WithdrawCryptoRequest) GetAmount() float64 {
+ if m != nil {
+ return m.Amount
}
return 0
}
-func (x *WithdrawCryptoRequest) GetFee() float64 {
- if x != nil {
- return x.Fee
+func (m *WithdrawCryptoRequest) GetFee() float64 {
+ if m != nil {
+ return m.Fee
}
return 0
}
-func (x *WithdrawCryptoRequest) GetDescription() string {
- if x != nil {
- return x.Description
+func (m *WithdrawCryptoRequest) GetDescription() string {
+ if m != nil {
+ return m.Description
}
return ""
}
type WithdrawResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
- Status string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"`
+ Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+ Status string `protobuf:"bytes,2,opt,name=status,proto3" json:"status,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *WithdrawResponse) Reset() {
- *x = WithdrawResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[87]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *WithdrawResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*WithdrawResponse) ProtoMessage() {}
-
-func (x *WithdrawResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[87]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use WithdrawResponse.ProtoReflect.Descriptor instead.
+func (m *WithdrawResponse) Reset() { *m = WithdrawResponse{} }
+func (m *WithdrawResponse) String() string { return proto.CompactTextString(m) }
+func (*WithdrawResponse) ProtoMessage() {}
func (*WithdrawResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{87}
+ return fileDescriptor_77a6da22d6a3feb1, []int{81}
}
-func (x *WithdrawResponse) GetId() string {
- if x != nil {
- return x.Id
+func (m *WithdrawResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_WithdrawResponse.Unmarshal(m, b)
+}
+func (m *WithdrawResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_WithdrawResponse.Marshal(b, m, deterministic)
+}
+func (m *WithdrawResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_WithdrawResponse.Merge(m, src)
+}
+func (m *WithdrawResponse) XXX_Size() int {
+ return xxx_messageInfo_WithdrawResponse.Size(m)
+}
+func (m *WithdrawResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_WithdrawResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_WithdrawResponse proto.InternalMessageInfo
+
+func (m *WithdrawResponse) GetId() string {
+ if m != nil {
+ return m.Id
}
return ""
}
-func (x *WithdrawResponse) GetStatus() string {
- if x != nil {
- return x.Status
+func (m *WithdrawResponse) GetStatus() string {
+ if m != nil {
+ return m.Status
}
return ""
}
type WithdrawalEventByIDRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+ Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *WithdrawalEventByIDRequest) Reset() {
- *x = WithdrawalEventByIDRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[88]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *WithdrawalEventByIDRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*WithdrawalEventByIDRequest) ProtoMessage() {}
-
-func (x *WithdrawalEventByIDRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[88]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use WithdrawalEventByIDRequest.ProtoReflect.Descriptor instead.
+func (m *WithdrawalEventByIDRequest) Reset() { *m = WithdrawalEventByIDRequest{} }
+func (m *WithdrawalEventByIDRequest) String() string { return proto.CompactTextString(m) }
+func (*WithdrawalEventByIDRequest) ProtoMessage() {}
func (*WithdrawalEventByIDRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{88}
+ return fileDescriptor_77a6da22d6a3feb1, []int{82}
}
-func (x *WithdrawalEventByIDRequest) GetId() string {
- if x != nil {
- return x.Id
+func (m *WithdrawalEventByIDRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_WithdrawalEventByIDRequest.Unmarshal(m, b)
+}
+func (m *WithdrawalEventByIDRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_WithdrawalEventByIDRequest.Marshal(b, m, deterministic)
+}
+func (m *WithdrawalEventByIDRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_WithdrawalEventByIDRequest.Merge(m, src)
+}
+func (m *WithdrawalEventByIDRequest) XXX_Size() int {
+ return xxx_messageInfo_WithdrawalEventByIDRequest.Size(m)
+}
+func (m *WithdrawalEventByIDRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_WithdrawalEventByIDRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_WithdrawalEventByIDRequest proto.InternalMessageInfo
+
+func (m *WithdrawalEventByIDRequest) GetId() string {
+ if m != nil {
+ return m.Id
}
return ""
}
type WithdrawalEventByIDResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Event *WithdrawalEventResponse `protobuf:"bytes,2,opt,name=event,proto3" json:"event,omitempty"`
+ Event *WithdrawalEventResponse `protobuf:"bytes,2,opt,name=event,proto3" json:"event,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *WithdrawalEventByIDResponse) Reset() {
- *x = WithdrawalEventByIDResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[89]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *WithdrawalEventByIDResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*WithdrawalEventByIDResponse) ProtoMessage() {}
-
-func (x *WithdrawalEventByIDResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[89]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use WithdrawalEventByIDResponse.ProtoReflect.Descriptor instead.
+func (m *WithdrawalEventByIDResponse) Reset() { *m = WithdrawalEventByIDResponse{} }
+func (m *WithdrawalEventByIDResponse) String() string { return proto.CompactTextString(m) }
+func (*WithdrawalEventByIDResponse) ProtoMessage() {}
func (*WithdrawalEventByIDResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{89}
+ return fileDescriptor_77a6da22d6a3feb1, []int{83}
}
-func (x *WithdrawalEventByIDResponse) GetEvent() *WithdrawalEventResponse {
- if x != nil {
- return x.Event
+func (m *WithdrawalEventByIDResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_WithdrawalEventByIDResponse.Unmarshal(m, b)
+}
+func (m *WithdrawalEventByIDResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_WithdrawalEventByIDResponse.Marshal(b, m, deterministic)
+}
+func (m *WithdrawalEventByIDResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_WithdrawalEventByIDResponse.Merge(m, src)
+}
+func (m *WithdrawalEventByIDResponse) XXX_Size() int {
+ return xxx_messageInfo_WithdrawalEventByIDResponse.Size(m)
+}
+func (m *WithdrawalEventByIDResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_WithdrawalEventByIDResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_WithdrawalEventByIDResponse proto.InternalMessageInfo
+
+func (m *WithdrawalEventByIDResponse) GetEvent() *WithdrawalEventResponse {
+ if m != nil {
+ return m.Event
}
return nil
}
type WithdrawalEventsByExchangeRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
- Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
- Limit int32 `protobuf:"varint,3,opt,name=limit,proto3" json:"limit,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
+ Limit int32 `protobuf:"varint,3,opt,name=limit,proto3" json:"limit,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *WithdrawalEventsByExchangeRequest) Reset() {
- *x = WithdrawalEventsByExchangeRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[90]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *WithdrawalEventsByExchangeRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*WithdrawalEventsByExchangeRequest) ProtoMessage() {}
-
-func (x *WithdrawalEventsByExchangeRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[90]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use WithdrawalEventsByExchangeRequest.ProtoReflect.Descriptor instead.
+func (m *WithdrawalEventsByExchangeRequest) Reset() { *m = WithdrawalEventsByExchangeRequest{} }
+func (m *WithdrawalEventsByExchangeRequest) String() string { return proto.CompactTextString(m) }
+func (*WithdrawalEventsByExchangeRequest) ProtoMessage() {}
func (*WithdrawalEventsByExchangeRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{90}
+ return fileDescriptor_77a6da22d6a3feb1, []int{84}
}
-func (x *WithdrawalEventsByExchangeRequest) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *WithdrawalEventsByExchangeRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_WithdrawalEventsByExchangeRequest.Unmarshal(m, b)
+}
+func (m *WithdrawalEventsByExchangeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_WithdrawalEventsByExchangeRequest.Marshal(b, m, deterministic)
+}
+func (m *WithdrawalEventsByExchangeRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_WithdrawalEventsByExchangeRequest.Merge(m, src)
+}
+func (m *WithdrawalEventsByExchangeRequest) XXX_Size() int {
+ return xxx_messageInfo_WithdrawalEventsByExchangeRequest.Size(m)
+}
+func (m *WithdrawalEventsByExchangeRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_WithdrawalEventsByExchangeRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_WithdrawalEventsByExchangeRequest proto.InternalMessageInfo
+
+func (m *WithdrawalEventsByExchangeRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
-func (x *WithdrawalEventsByExchangeRequest) GetId() string {
- if x != nil {
- return x.Id
+func (m *WithdrawalEventsByExchangeRequest) GetId() string {
+ if m != nil {
+ return m.Id
}
return ""
}
-func (x *WithdrawalEventsByExchangeRequest) GetLimit() int32 {
- if x != nil {
- return x.Limit
+func (m *WithdrawalEventsByExchangeRequest) GetLimit() int32 {
+ if m != nil {
+ return m.Limit
}
return 0
}
type WithdrawalEventsByDateRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
- Start string `protobuf:"bytes,2,opt,name=start,proto3" json:"start,omitempty"`
- End string `protobuf:"bytes,3,opt,name=end,proto3" json:"end,omitempty"`
- Limit int32 `protobuf:"varint,4,opt,name=limit,proto3" json:"limit,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Start string `protobuf:"bytes,2,opt,name=start,proto3" json:"start,omitempty"`
+ End string `protobuf:"bytes,3,opt,name=end,proto3" json:"end,omitempty"`
+ Limit int32 `protobuf:"varint,4,opt,name=limit,proto3" json:"limit,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *WithdrawalEventsByDateRequest) Reset() {
- *x = WithdrawalEventsByDateRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[91]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *WithdrawalEventsByDateRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*WithdrawalEventsByDateRequest) ProtoMessage() {}
-
-func (x *WithdrawalEventsByDateRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[91]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use WithdrawalEventsByDateRequest.ProtoReflect.Descriptor instead.
+func (m *WithdrawalEventsByDateRequest) Reset() { *m = WithdrawalEventsByDateRequest{} }
+func (m *WithdrawalEventsByDateRequest) String() string { return proto.CompactTextString(m) }
+func (*WithdrawalEventsByDateRequest) ProtoMessage() {}
func (*WithdrawalEventsByDateRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{91}
+ return fileDescriptor_77a6da22d6a3feb1, []int{85}
}
-func (x *WithdrawalEventsByDateRequest) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *WithdrawalEventsByDateRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_WithdrawalEventsByDateRequest.Unmarshal(m, b)
+}
+func (m *WithdrawalEventsByDateRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_WithdrawalEventsByDateRequest.Marshal(b, m, deterministic)
+}
+func (m *WithdrawalEventsByDateRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_WithdrawalEventsByDateRequest.Merge(m, src)
+}
+func (m *WithdrawalEventsByDateRequest) XXX_Size() int {
+ return xxx_messageInfo_WithdrawalEventsByDateRequest.Size(m)
+}
+func (m *WithdrawalEventsByDateRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_WithdrawalEventsByDateRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_WithdrawalEventsByDateRequest proto.InternalMessageInfo
+
+func (m *WithdrawalEventsByDateRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
-func (x *WithdrawalEventsByDateRequest) GetStart() string {
- if x != nil {
- return x.Start
+func (m *WithdrawalEventsByDateRequest) GetStart() string {
+ if m != nil {
+ return m.Start
}
return ""
}
-func (x *WithdrawalEventsByDateRequest) GetEnd() string {
- if x != nil {
- return x.End
+func (m *WithdrawalEventsByDateRequest) GetEnd() string {
+ if m != nil {
+ return m.End
}
return ""
}
-func (x *WithdrawalEventsByDateRequest) GetLimit() int32 {
- if x != nil {
- return x.Limit
+func (m *WithdrawalEventsByDateRequest) GetLimit() int32 {
+ if m != nil {
+ return m.Limit
}
return 0
}
type WithdrawalEventsByExchangeResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Event []*WithdrawalEventResponse `protobuf:"bytes,2,rep,name=event,proto3" json:"event,omitempty"`
+ Event []*WithdrawalEventResponse `protobuf:"bytes,2,rep,name=event,proto3" json:"event,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *WithdrawalEventsByExchangeResponse) Reset() {
- *x = WithdrawalEventsByExchangeResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[92]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *WithdrawalEventsByExchangeResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*WithdrawalEventsByExchangeResponse) ProtoMessage() {}
-
-func (x *WithdrawalEventsByExchangeResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[92]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use WithdrawalEventsByExchangeResponse.ProtoReflect.Descriptor instead.
+func (m *WithdrawalEventsByExchangeResponse) Reset() { *m = WithdrawalEventsByExchangeResponse{} }
+func (m *WithdrawalEventsByExchangeResponse) String() string { return proto.CompactTextString(m) }
+func (*WithdrawalEventsByExchangeResponse) ProtoMessage() {}
func (*WithdrawalEventsByExchangeResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{92}
+ return fileDescriptor_77a6da22d6a3feb1, []int{86}
}
-func (x *WithdrawalEventsByExchangeResponse) GetEvent() []*WithdrawalEventResponse {
- if x != nil {
- return x.Event
+func (m *WithdrawalEventsByExchangeResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_WithdrawalEventsByExchangeResponse.Unmarshal(m, b)
+}
+func (m *WithdrawalEventsByExchangeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_WithdrawalEventsByExchangeResponse.Marshal(b, m, deterministic)
+}
+func (m *WithdrawalEventsByExchangeResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_WithdrawalEventsByExchangeResponse.Merge(m, src)
+}
+func (m *WithdrawalEventsByExchangeResponse) XXX_Size() int {
+ return xxx_messageInfo_WithdrawalEventsByExchangeResponse.Size(m)
+}
+func (m *WithdrawalEventsByExchangeResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_WithdrawalEventsByExchangeResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_WithdrawalEventsByExchangeResponse proto.InternalMessageInfo
+
+func (m *WithdrawalEventsByExchangeResponse) GetEvent() []*WithdrawalEventResponse {
+ if m != nil {
+ return m.Event
}
return nil
}
type WithdrawalEventResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
- Exchange *WithdrawlExchangeEvent `protobuf:"bytes,3,opt,name=exchange,proto3" json:"exchange,omitempty"`
- Request *WithdrawalRequestEvent `protobuf:"bytes,4,opt,name=request,proto3" json:"request,omitempty"`
- CreatedAt *timestamp.Timestamp `protobuf:"bytes,5,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
- UpdatedAt *timestamp.Timestamp `protobuf:"bytes,6,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
+ Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
+ Exchange *WithdrawlExchangeEvent `protobuf:"bytes,3,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Request *WithdrawalRequestEvent `protobuf:"bytes,4,opt,name=request,proto3" json:"request,omitempty"`
+ CreatedAt *timestamp.Timestamp `protobuf:"bytes,5,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"`
+ UpdatedAt *timestamp.Timestamp `protobuf:"bytes,6,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *WithdrawalEventResponse) Reset() {
- *x = WithdrawalEventResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[93]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *WithdrawalEventResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*WithdrawalEventResponse) ProtoMessage() {}
-
-func (x *WithdrawalEventResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[93]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use WithdrawalEventResponse.ProtoReflect.Descriptor instead.
+func (m *WithdrawalEventResponse) Reset() { *m = WithdrawalEventResponse{} }
+func (m *WithdrawalEventResponse) String() string { return proto.CompactTextString(m) }
+func (*WithdrawalEventResponse) ProtoMessage() {}
func (*WithdrawalEventResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{93}
+ return fileDescriptor_77a6da22d6a3feb1, []int{87}
}
-func (x *WithdrawalEventResponse) GetId() string {
- if x != nil {
- return x.Id
+func (m *WithdrawalEventResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_WithdrawalEventResponse.Unmarshal(m, b)
+}
+func (m *WithdrawalEventResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_WithdrawalEventResponse.Marshal(b, m, deterministic)
+}
+func (m *WithdrawalEventResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_WithdrawalEventResponse.Merge(m, src)
+}
+func (m *WithdrawalEventResponse) XXX_Size() int {
+ return xxx_messageInfo_WithdrawalEventResponse.Size(m)
+}
+func (m *WithdrawalEventResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_WithdrawalEventResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_WithdrawalEventResponse proto.InternalMessageInfo
+
+func (m *WithdrawalEventResponse) GetId() string {
+ if m != nil {
+ return m.Id
}
return ""
}
-func (x *WithdrawalEventResponse) GetExchange() *WithdrawlExchangeEvent {
- if x != nil {
- return x.Exchange
+func (m *WithdrawalEventResponse) GetExchange() *WithdrawlExchangeEvent {
+ if m != nil {
+ return m.Exchange
}
return nil
}
-func (x *WithdrawalEventResponse) GetRequest() *WithdrawalRequestEvent {
- if x != nil {
- return x.Request
+func (m *WithdrawalEventResponse) GetRequest() *WithdrawalRequestEvent {
+ if m != nil {
+ return m.Request
}
return nil
}
-func (x *WithdrawalEventResponse) GetCreatedAt() *timestamp.Timestamp {
- if x != nil {
- return x.CreatedAt
+func (m *WithdrawalEventResponse) GetCreatedAt() *timestamp.Timestamp {
+ if m != nil {
+ return m.CreatedAt
}
return nil
}
-func (x *WithdrawalEventResponse) GetUpdatedAt() *timestamp.Timestamp {
- if x != nil {
- return x.UpdatedAt
+func (m *WithdrawalEventResponse) GetUpdatedAt() *timestamp.Timestamp {
+ if m != nil {
+ return m.UpdatedAt
}
return nil
}
type WithdrawlExchangeEvent struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
- Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
- Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"`
+ Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
+ Id string `protobuf:"bytes,2,opt,name=id,proto3" json:"id,omitempty"`
+ Status string `protobuf:"bytes,3,opt,name=status,proto3" json:"status,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *WithdrawlExchangeEvent) Reset() {
- *x = WithdrawlExchangeEvent{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[94]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *WithdrawlExchangeEvent) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*WithdrawlExchangeEvent) ProtoMessage() {}
-
-func (x *WithdrawlExchangeEvent) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[94]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use WithdrawlExchangeEvent.ProtoReflect.Descriptor instead.
+func (m *WithdrawlExchangeEvent) Reset() { *m = WithdrawlExchangeEvent{} }
+func (m *WithdrawlExchangeEvent) String() string { return proto.CompactTextString(m) }
+func (*WithdrawlExchangeEvent) ProtoMessage() {}
func (*WithdrawlExchangeEvent) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{94}
+ return fileDescriptor_77a6da22d6a3feb1, []int{88}
}
-func (x *WithdrawlExchangeEvent) GetName() string {
- if x != nil {
- return x.Name
+func (m *WithdrawlExchangeEvent) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_WithdrawlExchangeEvent.Unmarshal(m, b)
+}
+func (m *WithdrawlExchangeEvent) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_WithdrawlExchangeEvent.Marshal(b, m, deterministic)
+}
+func (m *WithdrawlExchangeEvent) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_WithdrawlExchangeEvent.Merge(m, src)
+}
+func (m *WithdrawlExchangeEvent) XXX_Size() int {
+ return xxx_messageInfo_WithdrawlExchangeEvent.Size(m)
+}
+func (m *WithdrawlExchangeEvent) XXX_DiscardUnknown() {
+ xxx_messageInfo_WithdrawlExchangeEvent.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_WithdrawlExchangeEvent proto.InternalMessageInfo
+
+func (m *WithdrawlExchangeEvent) GetName() string {
+ if m != nil {
+ return m.Name
}
return ""
}
-func (x *WithdrawlExchangeEvent) GetId() string {
- if x != nil {
- return x.Id
+func (m *WithdrawlExchangeEvent) GetId() string {
+ if m != nil {
+ return m.Id
}
return ""
}
-func (x *WithdrawlExchangeEvent) GetStatus() string {
- if x != nil {
- return x.Status
+func (m *WithdrawlExchangeEvent) GetStatus() string {
+ if m != nil {
+ return m.Status
}
return ""
}
type WithdrawalRequestEvent struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Currency string `protobuf:"bytes,2,opt,name=currency,proto3" json:"currency,omitempty"`
- Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"`
- Amount float64 `protobuf:"fixed64,4,opt,name=amount,proto3" json:"amount,omitempty"`
- Type int32 `protobuf:"varint,5,opt,name=type,proto3" json:"type,omitempty"`
- Fiat *FiatWithdrawalEvent `protobuf:"bytes,6,opt,name=fiat,proto3" json:"fiat,omitempty"`
- Crypto *CryptoWithdrawalEvent `protobuf:"bytes,7,opt,name=crypto,proto3" json:"crypto,omitempty"`
+ Currency string `protobuf:"bytes,2,opt,name=currency,proto3" json:"currency,omitempty"`
+ Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"`
+ Amount float64 `protobuf:"fixed64,4,opt,name=amount,proto3" json:"amount,omitempty"`
+ Type int32 `protobuf:"varint,5,opt,name=type,proto3" json:"type,omitempty"`
+ Fiat *FiatWithdrawalEvent `protobuf:"bytes,6,opt,name=fiat,proto3" json:"fiat,omitempty"`
+ Crypto *CryptoWithdrawalEvent `protobuf:"bytes,7,opt,name=crypto,proto3" json:"crypto,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *WithdrawalRequestEvent) Reset() {
- *x = WithdrawalRequestEvent{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[95]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *WithdrawalRequestEvent) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*WithdrawalRequestEvent) ProtoMessage() {}
-
-func (x *WithdrawalRequestEvent) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[95]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use WithdrawalRequestEvent.ProtoReflect.Descriptor instead.
+func (m *WithdrawalRequestEvent) Reset() { *m = WithdrawalRequestEvent{} }
+func (m *WithdrawalRequestEvent) String() string { return proto.CompactTextString(m) }
+func (*WithdrawalRequestEvent) ProtoMessage() {}
func (*WithdrawalRequestEvent) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{95}
+ return fileDescriptor_77a6da22d6a3feb1, []int{89}
}
-func (x *WithdrawalRequestEvent) GetCurrency() string {
- if x != nil {
- return x.Currency
+func (m *WithdrawalRequestEvent) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_WithdrawalRequestEvent.Unmarshal(m, b)
+}
+func (m *WithdrawalRequestEvent) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_WithdrawalRequestEvent.Marshal(b, m, deterministic)
+}
+func (m *WithdrawalRequestEvent) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_WithdrawalRequestEvent.Merge(m, src)
+}
+func (m *WithdrawalRequestEvent) XXX_Size() int {
+ return xxx_messageInfo_WithdrawalRequestEvent.Size(m)
+}
+func (m *WithdrawalRequestEvent) XXX_DiscardUnknown() {
+ xxx_messageInfo_WithdrawalRequestEvent.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_WithdrawalRequestEvent proto.InternalMessageInfo
+
+func (m *WithdrawalRequestEvent) GetCurrency() string {
+ if m != nil {
+ return m.Currency
}
return ""
}
-func (x *WithdrawalRequestEvent) GetDescription() string {
- if x != nil {
- return x.Description
+func (m *WithdrawalRequestEvent) GetDescription() string {
+ if m != nil {
+ return m.Description
}
return ""
}
-func (x *WithdrawalRequestEvent) GetAmount() float64 {
- if x != nil {
- return x.Amount
+func (m *WithdrawalRequestEvent) GetAmount() float64 {
+ if m != nil {
+ return m.Amount
}
return 0
}
-func (x *WithdrawalRequestEvent) GetType() int32 {
- if x != nil {
- return x.Type
+func (m *WithdrawalRequestEvent) GetType() int32 {
+ if m != nil {
+ return m.Type
}
return 0
}
-func (x *WithdrawalRequestEvent) GetFiat() *FiatWithdrawalEvent {
- if x != nil {
- return x.Fiat
+func (m *WithdrawalRequestEvent) GetFiat() *FiatWithdrawalEvent {
+ if m != nil {
+ return m.Fiat
}
return nil
}
-func (x *WithdrawalRequestEvent) GetCrypto() *CryptoWithdrawalEvent {
- if x != nil {
- return x.Crypto
+func (m *WithdrawalRequestEvent) GetCrypto() *CryptoWithdrawalEvent {
+ if m != nil {
+ return m.Crypto
}
return nil
}
type FiatWithdrawalEvent struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- BankName string `protobuf:"bytes,1,opt,name=bank_name,json=bankName,proto3" json:"bank_name,omitempty"`
- AccountName string `protobuf:"bytes,2,opt,name=account_name,json=accountName,proto3" json:"account_name,omitempty"`
- AccountNumber string `protobuf:"bytes,3,opt,name=account_number,json=accountNumber,proto3" json:"account_number,omitempty"`
- Bsb string `protobuf:"bytes,4,opt,name=bsb,proto3" json:"bsb,omitempty"`
- Swift string `protobuf:"bytes,5,opt,name=swift,proto3" json:"swift,omitempty"`
- Iban string `protobuf:"bytes,6,opt,name=iban,proto3" json:"iban,omitempty"`
+ BankName string `protobuf:"bytes,1,opt,name=bank_name,json=bankName,proto3" json:"bank_name,omitempty"`
+ AccountName string `protobuf:"bytes,2,opt,name=account_name,json=accountName,proto3" json:"account_name,omitempty"`
+ AccountNumber string `protobuf:"bytes,3,opt,name=account_number,json=accountNumber,proto3" json:"account_number,omitempty"`
+ Bsb string `protobuf:"bytes,4,opt,name=bsb,proto3" json:"bsb,omitempty"`
+ Swift string `protobuf:"bytes,5,opt,name=swift,proto3" json:"swift,omitempty"`
+ Iban string `protobuf:"bytes,6,opt,name=iban,proto3" json:"iban,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *FiatWithdrawalEvent) Reset() {
- *x = FiatWithdrawalEvent{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[96]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *FiatWithdrawalEvent) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*FiatWithdrawalEvent) ProtoMessage() {}
-
-func (x *FiatWithdrawalEvent) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[96]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use FiatWithdrawalEvent.ProtoReflect.Descriptor instead.
+func (m *FiatWithdrawalEvent) Reset() { *m = FiatWithdrawalEvent{} }
+func (m *FiatWithdrawalEvent) String() string { return proto.CompactTextString(m) }
+func (*FiatWithdrawalEvent) ProtoMessage() {}
func (*FiatWithdrawalEvent) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{96}
+ return fileDescriptor_77a6da22d6a3feb1, []int{90}
}
-func (x *FiatWithdrawalEvent) GetBankName() string {
- if x != nil {
- return x.BankName
+func (m *FiatWithdrawalEvent) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_FiatWithdrawalEvent.Unmarshal(m, b)
+}
+func (m *FiatWithdrawalEvent) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_FiatWithdrawalEvent.Marshal(b, m, deterministic)
+}
+func (m *FiatWithdrawalEvent) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_FiatWithdrawalEvent.Merge(m, src)
+}
+func (m *FiatWithdrawalEvent) XXX_Size() int {
+ return xxx_messageInfo_FiatWithdrawalEvent.Size(m)
+}
+func (m *FiatWithdrawalEvent) XXX_DiscardUnknown() {
+ xxx_messageInfo_FiatWithdrawalEvent.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_FiatWithdrawalEvent proto.InternalMessageInfo
+
+func (m *FiatWithdrawalEvent) GetBankName() string {
+ if m != nil {
+ return m.BankName
}
return ""
}
-func (x *FiatWithdrawalEvent) GetAccountName() string {
- if x != nil {
- return x.AccountName
+func (m *FiatWithdrawalEvent) GetAccountName() string {
+ if m != nil {
+ return m.AccountName
}
return ""
}
-func (x *FiatWithdrawalEvent) GetAccountNumber() string {
- if x != nil {
- return x.AccountNumber
+func (m *FiatWithdrawalEvent) GetAccountNumber() string {
+ if m != nil {
+ return m.AccountNumber
}
return ""
}
-func (x *FiatWithdrawalEvent) GetBsb() string {
- if x != nil {
- return x.Bsb
+func (m *FiatWithdrawalEvent) GetBsb() string {
+ if m != nil {
+ return m.Bsb
}
return ""
}
-func (x *FiatWithdrawalEvent) GetSwift() string {
- if x != nil {
- return x.Swift
+func (m *FiatWithdrawalEvent) GetSwift() string {
+ if m != nil {
+ return m.Swift
}
return ""
}
-func (x *FiatWithdrawalEvent) GetIban() string {
- if x != nil {
- return x.Iban
+func (m *FiatWithdrawalEvent) GetIban() string {
+ if m != nil {
+ return m.Iban
}
return ""
}
type CryptoWithdrawalEvent struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
- AddressTag string `protobuf:"bytes,2,opt,name=address_tag,json=addressTag,proto3" json:"address_tag,omitempty"`
- Fee float64 `protobuf:"fixed64,3,opt,name=fee,proto3" json:"fee,omitempty"`
+ Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
+ AddressTag string `protobuf:"bytes,2,opt,name=address_tag,json=addressTag,proto3" json:"address_tag,omitempty"`
+ Fee float64 `protobuf:"fixed64,3,opt,name=fee,proto3" json:"fee,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *CryptoWithdrawalEvent) Reset() {
- *x = CryptoWithdrawalEvent{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[97]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *CryptoWithdrawalEvent) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*CryptoWithdrawalEvent) ProtoMessage() {}
-
-func (x *CryptoWithdrawalEvent) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[97]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use CryptoWithdrawalEvent.ProtoReflect.Descriptor instead.
+func (m *CryptoWithdrawalEvent) Reset() { *m = CryptoWithdrawalEvent{} }
+func (m *CryptoWithdrawalEvent) String() string { return proto.CompactTextString(m) }
+func (*CryptoWithdrawalEvent) ProtoMessage() {}
func (*CryptoWithdrawalEvent) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{97}
+ return fileDescriptor_77a6da22d6a3feb1, []int{91}
}
-func (x *CryptoWithdrawalEvent) GetAddress() string {
- if x != nil {
- return x.Address
+func (m *CryptoWithdrawalEvent) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_CryptoWithdrawalEvent.Unmarshal(m, b)
+}
+func (m *CryptoWithdrawalEvent) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_CryptoWithdrawalEvent.Marshal(b, m, deterministic)
+}
+func (m *CryptoWithdrawalEvent) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_CryptoWithdrawalEvent.Merge(m, src)
+}
+func (m *CryptoWithdrawalEvent) XXX_Size() int {
+ return xxx_messageInfo_CryptoWithdrawalEvent.Size(m)
+}
+func (m *CryptoWithdrawalEvent) XXX_DiscardUnknown() {
+ xxx_messageInfo_CryptoWithdrawalEvent.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_CryptoWithdrawalEvent proto.InternalMessageInfo
+
+func (m *CryptoWithdrawalEvent) GetAddress() string {
+ if m != nil {
+ return m.Address
}
return ""
}
-func (x *CryptoWithdrawalEvent) GetAddressTag() string {
- if x != nil {
- return x.AddressTag
+func (m *CryptoWithdrawalEvent) GetAddressTag() string {
+ if m != nil {
+ return m.AddressTag
}
return ""
}
-func (x *CryptoWithdrawalEvent) GetFee() float64 {
- if x != nil {
- return x.Fee
+func (m *CryptoWithdrawalEvent) GetFee() float64 {
+ if m != nil {
+ return m.Fee
}
return 0
}
type GetLoggerDetailsRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Logger string `protobuf:"bytes,1,opt,name=logger,proto3" json:"logger,omitempty"`
+ Logger string `protobuf:"bytes,1,opt,name=logger,proto3" json:"logger,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetLoggerDetailsRequest) Reset() {
- *x = GetLoggerDetailsRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[98]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetLoggerDetailsRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetLoggerDetailsRequest) ProtoMessage() {}
-
-func (x *GetLoggerDetailsRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[98]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetLoggerDetailsRequest.ProtoReflect.Descriptor instead.
+func (m *GetLoggerDetailsRequest) Reset() { *m = GetLoggerDetailsRequest{} }
+func (m *GetLoggerDetailsRequest) String() string { return proto.CompactTextString(m) }
+func (*GetLoggerDetailsRequest) ProtoMessage() {}
func (*GetLoggerDetailsRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{98}
+ return fileDescriptor_77a6da22d6a3feb1, []int{92}
}
-func (x *GetLoggerDetailsRequest) GetLogger() string {
- if x != nil {
- return x.Logger
+func (m *GetLoggerDetailsRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetLoggerDetailsRequest.Unmarshal(m, b)
+}
+func (m *GetLoggerDetailsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetLoggerDetailsRequest.Marshal(b, m, deterministic)
+}
+func (m *GetLoggerDetailsRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetLoggerDetailsRequest.Merge(m, src)
+}
+func (m *GetLoggerDetailsRequest) XXX_Size() int {
+ return xxx_messageInfo_GetLoggerDetailsRequest.Size(m)
+}
+func (m *GetLoggerDetailsRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetLoggerDetailsRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetLoggerDetailsRequest proto.InternalMessageInfo
+
+func (m *GetLoggerDetailsRequest) GetLogger() string {
+ if m != nil {
+ return m.Logger
}
return ""
}
type GetLoggerDetailsResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Info bool `protobuf:"varint,1,opt,name=info,proto3" json:"info,omitempty"`
- Debug bool `protobuf:"varint,2,opt,name=debug,proto3" json:"debug,omitempty"`
- Warn bool `protobuf:"varint,3,opt,name=warn,proto3" json:"warn,omitempty"`
- Error bool `protobuf:"varint,4,opt,name=error,proto3" json:"error,omitempty"`
+ Info bool `protobuf:"varint,1,opt,name=info,proto3" json:"info,omitempty"`
+ Debug bool `protobuf:"varint,2,opt,name=debug,proto3" json:"debug,omitempty"`
+ Warn bool `protobuf:"varint,3,opt,name=warn,proto3" json:"warn,omitempty"`
+ Error bool `protobuf:"varint,4,opt,name=error,proto3" json:"error,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetLoggerDetailsResponse) Reset() {
- *x = GetLoggerDetailsResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[99]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetLoggerDetailsResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetLoggerDetailsResponse) ProtoMessage() {}
-
-func (x *GetLoggerDetailsResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[99]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetLoggerDetailsResponse.ProtoReflect.Descriptor instead.
+func (m *GetLoggerDetailsResponse) Reset() { *m = GetLoggerDetailsResponse{} }
+func (m *GetLoggerDetailsResponse) String() string { return proto.CompactTextString(m) }
+func (*GetLoggerDetailsResponse) ProtoMessage() {}
func (*GetLoggerDetailsResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{99}
+ return fileDescriptor_77a6da22d6a3feb1, []int{93}
}
-func (x *GetLoggerDetailsResponse) GetInfo() bool {
- if x != nil {
- return x.Info
+func (m *GetLoggerDetailsResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetLoggerDetailsResponse.Unmarshal(m, b)
+}
+func (m *GetLoggerDetailsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetLoggerDetailsResponse.Marshal(b, m, deterministic)
+}
+func (m *GetLoggerDetailsResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetLoggerDetailsResponse.Merge(m, src)
+}
+func (m *GetLoggerDetailsResponse) XXX_Size() int {
+ return xxx_messageInfo_GetLoggerDetailsResponse.Size(m)
+}
+func (m *GetLoggerDetailsResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetLoggerDetailsResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetLoggerDetailsResponse proto.InternalMessageInfo
+
+func (m *GetLoggerDetailsResponse) GetInfo() bool {
+ if m != nil {
+ return m.Info
}
return false
}
-func (x *GetLoggerDetailsResponse) GetDebug() bool {
- if x != nil {
- return x.Debug
+func (m *GetLoggerDetailsResponse) GetDebug() bool {
+ if m != nil {
+ return m.Debug
}
return false
}
-func (x *GetLoggerDetailsResponse) GetWarn() bool {
- if x != nil {
- return x.Warn
+func (m *GetLoggerDetailsResponse) GetWarn() bool {
+ if m != nil {
+ return m.Warn
}
return false
}
-func (x *GetLoggerDetailsResponse) GetError() bool {
- if x != nil {
- return x.Error
+func (m *GetLoggerDetailsResponse) GetError() bool {
+ if m != nil {
+ return m.Error
}
return false
}
type SetLoggerDetailsRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Logger string `protobuf:"bytes,1,opt,name=logger,proto3" json:"logger,omitempty"`
- Level string `protobuf:"bytes,2,opt,name=level,proto3" json:"level,omitempty"`
+ Logger string `protobuf:"bytes,1,opt,name=logger,proto3" json:"logger,omitempty"`
+ Level string `protobuf:"bytes,2,opt,name=level,proto3" json:"level,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *SetLoggerDetailsRequest) Reset() {
- *x = SetLoggerDetailsRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[100]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *SetLoggerDetailsRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*SetLoggerDetailsRequest) ProtoMessage() {}
-
-func (x *SetLoggerDetailsRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[100]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use SetLoggerDetailsRequest.ProtoReflect.Descriptor instead.
+func (m *SetLoggerDetailsRequest) Reset() { *m = SetLoggerDetailsRequest{} }
+func (m *SetLoggerDetailsRequest) String() string { return proto.CompactTextString(m) }
+func (*SetLoggerDetailsRequest) ProtoMessage() {}
func (*SetLoggerDetailsRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{100}
+ return fileDescriptor_77a6da22d6a3feb1, []int{94}
}
-func (x *SetLoggerDetailsRequest) GetLogger() string {
- if x != nil {
- return x.Logger
+func (m *SetLoggerDetailsRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_SetLoggerDetailsRequest.Unmarshal(m, b)
+}
+func (m *SetLoggerDetailsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_SetLoggerDetailsRequest.Marshal(b, m, deterministic)
+}
+func (m *SetLoggerDetailsRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_SetLoggerDetailsRequest.Merge(m, src)
+}
+func (m *SetLoggerDetailsRequest) XXX_Size() int {
+ return xxx_messageInfo_SetLoggerDetailsRequest.Size(m)
+}
+func (m *SetLoggerDetailsRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_SetLoggerDetailsRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SetLoggerDetailsRequest proto.InternalMessageInfo
+
+func (m *SetLoggerDetailsRequest) GetLogger() string {
+ if m != nil {
+ return m.Logger
}
return ""
}
-func (x *SetLoggerDetailsRequest) GetLevel() string {
- if x != nil {
- return x.Level
+func (m *SetLoggerDetailsRequest) GetLevel() string {
+ if m != nil {
+ return m.Level
}
return ""
}
type GetExchangePairsRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
- Asset string `protobuf:"bytes,2,opt,name=asset,proto3" json:"asset,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Asset string `protobuf:"bytes,2,opt,name=asset,proto3" json:"asset,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetExchangePairsRequest) Reset() {
- *x = GetExchangePairsRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[101]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetExchangePairsRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetExchangePairsRequest) ProtoMessage() {}
-
-func (x *GetExchangePairsRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[101]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetExchangePairsRequest.ProtoReflect.Descriptor instead.
+func (m *GetExchangePairsRequest) Reset() { *m = GetExchangePairsRequest{} }
+func (m *GetExchangePairsRequest) String() string { return proto.CompactTextString(m) }
+func (*GetExchangePairsRequest) ProtoMessage() {}
func (*GetExchangePairsRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{101}
+ return fileDescriptor_77a6da22d6a3feb1, []int{95}
}
-func (x *GetExchangePairsRequest) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *GetExchangePairsRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetExchangePairsRequest.Unmarshal(m, b)
+}
+func (m *GetExchangePairsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetExchangePairsRequest.Marshal(b, m, deterministic)
+}
+func (m *GetExchangePairsRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetExchangePairsRequest.Merge(m, src)
+}
+func (m *GetExchangePairsRequest) XXX_Size() int {
+ return xxx_messageInfo_GetExchangePairsRequest.Size(m)
+}
+func (m *GetExchangePairsRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetExchangePairsRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetExchangePairsRequest proto.InternalMessageInfo
+
+func (m *GetExchangePairsRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
-func (x *GetExchangePairsRequest) GetAsset() string {
- if x != nil {
- return x.Asset
+func (m *GetExchangePairsRequest) GetAsset() string {
+ if m != nil {
+ return m.Asset
}
return ""
}
type GetExchangePairsResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- SupportedAssets map[string]*PairsSupported `protobuf:"bytes,1,rep,name=supported_assets,json=supportedAssets,proto3" json:"supported_assets,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+ SupportedAssets map[string]*PairsSupported `protobuf:"bytes,1,rep,name=supported_assets,json=supportedAssets,proto3" json:"supported_assets,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetExchangePairsResponse) Reset() {
- *x = GetExchangePairsResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[102]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetExchangePairsResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetExchangePairsResponse) ProtoMessage() {}
-
-func (x *GetExchangePairsResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[102]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetExchangePairsResponse.ProtoReflect.Descriptor instead.
+func (m *GetExchangePairsResponse) Reset() { *m = GetExchangePairsResponse{} }
+func (m *GetExchangePairsResponse) String() string { return proto.CompactTextString(m) }
+func (*GetExchangePairsResponse) ProtoMessage() {}
func (*GetExchangePairsResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{102}
+ return fileDescriptor_77a6da22d6a3feb1, []int{96}
}
-func (x *GetExchangePairsResponse) GetSupportedAssets() map[string]*PairsSupported {
- if x != nil {
- return x.SupportedAssets
+func (m *GetExchangePairsResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetExchangePairsResponse.Unmarshal(m, b)
+}
+func (m *GetExchangePairsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetExchangePairsResponse.Marshal(b, m, deterministic)
+}
+func (m *GetExchangePairsResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetExchangePairsResponse.Merge(m, src)
+}
+func (m *GetExchangePairsResponse) XXX_Size() int {
+ return xxx_messageInfo_GetExchangePairsResponse.Size(m)
+}
+func (m *GetExchangePairsResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetExchangePairsResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetExchangePairsResponse proto.InternalMessageInfo
+
+func (m *GetExchangePairsResponse) GetSupportedAssets() map[string]*PairsSupported {
+ if m != nil {
+ return m.SupportedAssets
}
return nil
}
-type ExchangePairRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
- AssetType string `protobuf:"bytes,2,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"`
- Pair *CurrencyPair `protobuf:"bytes,3,opt,name=pair,proto3" json:"pair,omitempty"`
+type SetExchangePairRequest struct {
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ AssetType string `protobuf:"bytes,2,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"`
+ Pairs []*CurrencyPair `protobuf:"bytes,3,rep,name=pairs,proto3" json:"pairs,omitempty"`
+ Enable bool `protobuf:"varint,4,opt,name=enable,proto3" json:"enable,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *ExchangePairRequest) Reset() {
- *x = ExchangePairRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[103]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+func (m *SetExchangePairRequest) Reset() { *m = SetExchangePairRequest{} }
+func (m *SetExchangePairRequest) String() string { return proto.CompactTextString(m) }
+func (*SetExchangePairRequest) ProtoMessage() {}
+func (*SetExchangePairRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_77a6da22d6a3feb1, []int{97}
}
-func (x *ExchangePairRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
+func (m *SetExchangePairRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_SetExchangePairRequest.Unmarshal(m, b)
+}
+func (m *SetExchangePairRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_SetExchangePairRequest.Marshal(b, m, deterministic)
+}
+func (m *SetExchangePairRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_SetExchangePairRequest.Merge(m, src)
+}
+func (m *SetExchangePairRequest) XXX_Size() int {
+ return xxx_messageInfo_SetExchangePairRequest.Size(m)
+}
+func (m *SetExchangePairRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_SetExchangePairRequest.DiscardUnknown(m)
}
-func (*ExchangePairRequest) ProtoMessage() {}
+var xxx_messageInfo_SetExchangePairRequest proto.InternalMessageInfo
-func (x *ExchangePairRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[103]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use ExchangePairRequest.ProtoReflect.Descriptor instead.
-func (*ExchangePairRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{103}
-}
-
-func (x *ExchangePairRequest) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *SetExchangePairRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
-func (x *ExchangePairRequest) GetAssetType() string {
- if x != nil {
- return x.AssetType
+func (m *SetExchangePairRequest) GetAssetType() string {
+ if m != nil {
+ return m.AssetType
}
return ""
}
-func (x *ExchangePairRequest) GetPair() *CurrencyPair {
- if x != nil {
- return x.Pair
+func (m *SetExchangePairRequest) GetPairs() []*CurrencyPair {
+ if m != nil {
+ return m.Pairs
}
return nil
}
+func (m *SetExchangePairRequest) GetEnable() bool {
+ if m != nil {
+ return m.Enable
+ }
+ return false
+}
+
type GetOrderbookStreamRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
- Pair *CurrencyPair `protobuf:"bytes,2,opt,name=pair,proto3" json:"pair,omitempty"`
- AssetType string `protobuf:"bytes,3,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Pair *CurrencyPair `protobuf:"bytes,2,opt,name=pair,proto3" json:"pair,omitempty"`
+ AssetType string `protobuf:"bytes,3,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetOrderbookStreamRequest) Reset() {
- *x = GetOrderbookStreamRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[104]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetOrderbookStreamRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetOrderbookStreamRequest) ProtoMessage() {}
-
-func (x *GetOrderbookStreamRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[104]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetOrderbookStreamRequest.ProtoReflect.Descriptor instead.
+func (m *GetOrderbookStreamRequest) Reset() { *m = GetOrderbookStreamRequest{} }
+func (m *GetOrderbookStreamRequest) String() string { return proto.CompactTextString(m) }
+func (*GetOrderbookStreamRequest) ProtoMessage() {}
func (*GetOrderbookStreamRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{104}
+ return fileDescriptor_77a6da22d6a3feb1, []int{98}
}
-func (x *GetOrderbookStreamRequest) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *GetOrderbookStreamRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetOrderbookStreamRequest.Unmarshal(m, b)
+}
+func (m *GetOrderbookStreamRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetOrderbookStreamRequest.Marshal(b, m, deterministic)
+}
+func (m *GetOrderbookStreamRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetOrderbookStreamRequest.Merge(m, src)
+}
+func (m *GetOrderbookStreamRequest) XXX_Size() int {
+ return xxx_messageInfo_GetOrderbookStreamRequest.Size(m)
+}
+func (m *GetOrderbookStreamRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetOrderbookStreamRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetOrderbookStreamRequest proto.InternalMessageInfo
+
+func (m *GetOrderbookStreamRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
-func (x *GetOrderbookStreamRequest) GetPair() *CurrencyPair {
- if x != nil {
- return x.Pair
+func (m *GetOrderbookStreamRequest) GetPair() *CurrencyPair {
+ if m != nil {
+ return m.Pair
}
return nil
}
-func (x *GetOrderbookStreamRequest) GetAssetType() string {
- if x != nil {
- return x.AssetType
+func (m *GetOrderbookStreamRequest) GetAssetType() string {
+ if m != nil {
+ return m.AssetType
}
return ""
}
type GetExchangeOrderbookStreamRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetExchangeOrderbookStreamRequest) Reset() {
- *x = GetExchangeOrderbookStreamRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[105]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetExchangeOrderbookStreamRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetExchangeOrderbookStreamRequest) ProtoMessage() {}
-
-func (x *GetExchangeOrderbookStreamRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[105]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetExchangeOrderbookStreamRequest.ProtoReflect.Descriptor instead.
+func (m *GetExchangeOrderbookStreamRequest) Reset() { *m = GetExchangeOrderbookStreamRequest{} }
+func (m *GetExchangeOrderbookStreamRequest) String() string { return proto.CompactTextString(m) }
+func (*GetExchangeOrderbookStreamRequest) ProtoMessage() {}
func (*GetExchangeOrderbookStreamRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{105}
+ return fileDescriptor_77a6da22d6a3feb1, []int{99}
}
-func (x *GetExchangeOrderbookStreamRequest) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *GetExchangeOrderbookStreamRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetExchangeOrderbookStreamRequest.Unmarshal(m, b)
+}
+func (m *GetExchangeOrderbookStreamRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetExchangeOrderbookStreamRequest.Marshal(b, m, deterministic)
+}
+func (m *GetExchangeOrderbookStreamRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetExchangeOrderbookStreamRequest.Merge(m, src)
+}
+func (m *GetExchangeOrderbookStreamRequest) XXX_Size() int {
+ return xxx_messageInfo_GetExchangeOrderbookStreamRequest.Size(m)
+}
+func (m *GetExchangeOrderbookStreamRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetExchangeOrderbookStreamRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetExchangeOrderbookStreamRequest proto.InternalMessageInfo
+
+func (m *GetExchangeOrderbookStreamRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
type GetTickerStreamRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
- Pair *CurrencyPair `protobuf:"bytes,2,opt,name=pair,proto3" json:"pair,omitempty"`
- AssetType string `protobuf:"bytes,3,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Pair *CurrencyPair `protobuf:"bytes,2,opt,name=pair,proto3" json:"pair,omitempty"`
+ AssetType string `protobuf:"bytes,3,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetTickerStreamRequest) Reset() {
- *x = GetTickerStreamRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[106]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetTickerStreamRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetTickerStreamRequest) ProtoMessage() {}
-
-func (x *GetTickerStreamRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[106]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetTickerStreamRequest.ProtoReflect.Descriptor instead.
+func (m *GetTickerStreamRequest) Reset() { *m = GetTickerStreamRequest{} }
+func (m *GetTickerStreamRequest) String() string { return proto.CompactTextString(m) }
+func (*GetTickerStreamRequest) ProtoMessage() {}
func (*GetTickerStreamRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{106}
+ return fileDescriptor_77a6da22d6a3feb1, []int{100}
}
-func (x *GetTickerStreamRequest) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *GetTickerStreamRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetTickerStreamRequest.Unmarshal(m, b)
+}
+func (m *GetTickerStreamRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetTickerStreamRequest.Marshal(b, m, deterministic)
+}
+func (m *GetTickerStreamRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetTickerStreamRequest.Merge(m, src)
+}
+func (m *GetTickerStreamRequest) XXX_Size() int {
+ return xxx_messageInfo_GetTickerStreamRequest.Size(m)
+}
+func (m *GetTickerStreamRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetTickerStreamRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetTickerStreamRequest proto.InternalMessageInfo
+
+func (m *GetTickerStreamRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
-func (x *GetTickerStreamRequest) GetPair() *CurrencyPair {
- if x != nil {
- return x.Pair
+func (m *GetTickerStreamRequest) GetPair() *CurrencyPair {
+ if m != nil {
+ return m.Pair
}
return nil
}
-func (x *GetTickerStreamRequest) GetAssetType() string {
- if x != nil {
- return x.AssetType
+func (m *GetTickerStreamRequest) GetAssetType() string {
+ if m != nil {
+ return m.AssetType
}
return ""
}
type GetExchangeTickerStreamRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetExchangeTickerStreamRequest) Reset() {
- *x = GetExchangeTickerStreamRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[107]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetExchangeTickerStreamRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetExchangeTickerStreamRequest) ProtoMessage() {}
-
-func (x *GetExchangeTickerStreamRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[107]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetExchangeTickerStreamRequest.ProtoReflect.Descriptor instead.
+func (m *GetExchangeTickerStreamRequest) Reset() { *m = GetExchangeTickerStreamRequest{} }
+func (m *GetExchangeTickerStreamRequest) String() string { return proto.CompactTextString(m) }
+func (*GetExchangeTickerStreamRequest) ProtoMessage() {}
func (*GetExchangeTickerStreamRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{107}
+ return fileDescriptor_77a6da22d6a3feb1, []int{101}
}
-func (x *GetExchangeTickerStreamRequest) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *GetExchangeTickerStreamRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetExchangeTickerStreamRequest.Unmarshal(m, b)
+}
+func (m *GetExchangeTickerStreamRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetExchangeTickerStreamRequest.Marshal(b, m, deterministic)
+}
+func (m *GetExchangeTickerStreamRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetExchangeTickerStreamRequest.Merge(m, src)
+}
+func (m *GetExchangeTickerStreamRequest) XXX_Size() int {
+ return xxx_messageInfo_GetExchangeTickerStreamRequest.Size(m)
+}
+func (m *GetExchangeTickerStreamRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetExchangeTickerStreamRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetExchangeTickerStreamRequest proto.InternalMessageInfo
+
+func (m *GetExchangeTickerStreamRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
type GetAuditEventRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- StartDate string `protobuf:"bytes,1,opt,name=start_date,json=startDate,proto3" json:"start_date,omitempty"`
- EndDate string `protobuf:"bytes,2,opt,name=end_date,json=endDate,proto3" json:"end_date,omitempty"`
- OrderBy string `protobuf:"bytes,3,opt,name=order_by,json=orderBy,proto3" json:"order_by,omitempty"`
- Limit int32 `protobuf:"varint,4,opt,name=limit,proto3" json:"limit,omitempty"`
- Offset int32 `protobuf:"varint,5,opt,name=offset,proto3" json:"offset,omitempty"`
+ StartDate string `protobuf:"bytes,1,opt,name=start_date,json=startDate,proto3" json:"start_date,omitempty"`
+ EndDate string `protobuf:"bytes,2,opt,name=end_date,json=endDate,proto3" json:"end_date,omitempty"`
+ OrderBy string `protobuf:"bytes,3,opt,name=order_by,json=orderBy,proto3" json:"order_by,omitempty"`
+ Limit int32 `protobuf:"varint,4,opt,name=limit,proto3" json:"limit,omitempty"`
+ Offset int32 `protobuf:"varint,5,opt,name=offset,proto3" json:"offset,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetAuditEventRequest) Reset() {
- *x = GetAuditEventRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[108]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetAuditEventRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetAuditEventRequest) ProtoMessage() {}
-
-func (x *GetAuditEventRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[108]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetAuditEventRequest.ProtoReflect.Descriptor instead.
+func (m *GetAuditEventRequest) Reset() { *m = GetAuditEventRequest{} }
+func (m *GetAuditEventRequest) String() string { return proto.CompactTextString(m) }
+func (*GetAuditEventRequest) ProtoMessage() {}
func (*GetAuditEventRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{108}
+ return fileDescriptor_77a6da22d6a3feb1, []int{102}
}
-func (x *GetAuditEventRequest) GetStartDate() string {
- if x != nil {
- return x.StartDate
+func (m *GetAuditEventRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetAuditEventRequest.Unmarshal(m, b)
+}
+func (m *GetAuditEventRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetAuditEventRequest.Marshal(b, m, deterministic)
+}
+func (m *GetAuditEventRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetAuditEventRequest.Merge(m, src)
+}
+func (m *GetAuditEventRequest) XXX_Size() int {
+ return xxx_messageInfo_GetAuditEventRequest.Size(m)
+}
+func (m *GetAuditEventRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetAuditEventRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetAuditEventRequest proto.InternalMessageInfo
+
+func (m *GetAuditEventRequest) GetStartDate() string {
+ if m != nil {
+ return m.StartDate
}
return ""
}
-func (x *GetAuditEventRequest) GetEndDate() string {
- if x != nil {
- return x.EndDate
+func (m *GetAuditEventRequest) GetEndDate() string {
+ if m != nil {
+ return m.EndDate
}
return ""
}
-func (x *GetAuditEventRequest) GetOrderBy() string {
- if x != nil {
- return x.OrderBy
+func (m *GetAuditEventRequest) GetOrderBy() string {
+ if m != nil {
+ return m.OrderBy
}
return ""
}
-func (x *GetAuditEventRequest) GetLimit() int32 {
- if x != nil {
- return x.Limit
+func (m *GetAuditEventRequest) GetLimit() int32 {
+ if m != nil {
+ return m.Limit
}
return 0
}
-func (x *GetAuditEventRequest) GetOffset() int32 {
- if x != nil {
- return x.Offset
+func (m *GetAuditEventRequest) GetOffset() int32 {
+ if m != nil {
+ return m.Offset
}
return 0
}
type GetAuditEventResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Events []*AuditEvent `protobuf:"bytes,1,rep,name=events,proto3" json:"events,omitempty"`
+ Events []*AuditEvent `protobuf:"bytes,1,rep,name=events,proto3" json:"events,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetAuditEventResponse) Reset() {
- *x = GetAuditEventResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[109]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetAuditEventResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetAuditEventResponse) ProtoMessage() {}
-
-func (x *GetAuditEventResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[109]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetAuditEventResponse.ProtoReflect.Descriptor instead.
+func (m *GetAuditEventResponse) Reset() { *m = GetAuditEventResponse{} }
+func (m *GetAuditEventResponse) String() string { return proto.CompactTextString(m) }
+func (*GetAuditEventResponse) ProtoMessage() {}
func (*GetAuditEventResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{109}
+ return fileDescriptor_77a6da22d6a3feb1, []int{103}
}
-func (x *GetAuditEventResponse) GetEvents() []*AuditEvent {
- if x != nil {
- return x.Events
+func (m *GetAuditEventResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetAuditEventResponse.Unmarshal(m, b)
+}
+func (m *GetAuditEventResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetAuditEventResponse.Marshal(b, m, deterministic)
+}
+func (m *GetAuditEventResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetAuditEventResponse.Merge(m, src)
+}
+func (m *GetAuditEventResponse) XXX_Size() int {
+ return xxx_messageInfo_GetAuditEventResponse.Size(m)
+}
+func (m *GetAuditEventResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetAuditEventResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetAuditEventResponse proto.InternalMessageInfo
+
+func (m *GetAuditEventResponse) GetEvents() []*AuditEvent {
+ if m != nil {
+ return m.Events
}
return nil
}
type GetHistoricCandlesRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
- Pair *CurrencyPair `protobuf:"bytes,2,opt,name=pair,proto3" json:"pair,omitempty"`
- AssetType string `protobuf:"bytes,3,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"`
- Start int64 `protobuf:"varint,4,opt,name=start,proto3" json:"start,omitempty"`
- End int64 `protobuf:"varint,5,opt,name=end,proto3" json:"end,omitempty"`
- TimeInterval int64 `protobuf:"varint,6,opt,name=time_interval,json=timeInterval,proto3" json:"time_interval,omitempty"`
- ExRequest bool `protobuf:"varint,7,opt,name=ex_request,json=exRequest,proto3" json:"ex_request,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Pair *CurrencyPair `protobuf:"bytes,2,opt,name=pair,proto3" json:"pair,omitempty"`
+ AssetType string `protobuf:"bytes,3,opt,name=asset_type,json=assetType,proto3" json:"asset_type,omitempty"`
+ Start int64 `protobuf:"varint,4,opt,name=start,proto3" json:"start,omitempty"`
+ End int64 `protobuf:"varint,5,opt,name=end,proto3" json:"end,omitempty"`
+ TimeInterval int64 `protobuf:"varint,6,opt,name=time_interval,json=timeInterval,proto3" json:"time_interval,omitempty"`
+ ExRequest bool `protobuf:"varint,7,opt,name=ex_request,json=exRequest,proto3" json:"ex_request,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetHistoricCandlesRequest) Reset() {
- *x = GetHistoricCandlesRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[110]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetHistoricCandlesRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetHistoricCandlesRequest) ProtoMessage() {}
-
-func (x *GetHistoricCandlesRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[110]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetHistoricCandlesRequest.ProtoReflect.Descriptor instead.
+func (m *GetHistoricCandlesRequest) Reset() { *m = GetHistoricCandlesRequest{} }
+func (m *GetHistoricCandlesRequest) String() string { return proto.CompactTextString(m) }
+func (*GetHistoricCandlesRequest) ProtoMessage() {}
func (*GetHistoricCandlesRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{110}
+ return fileDescriptor_77a6da22d6a3feb1, []int{104}
}
-func (x *GetHistoricCandlesRequest) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *GetHistoricCandlesRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetHistoricCandlesRequest.Unmarshal(m, b)
+}
+func (m *GetHistoricCandlesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetHistoricCandlesRequest.Marshal(b, m, deterministic)
+}
+func (m *GetHistoricCandlesRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetHistoricCandlesRequest.Merge(m, src)
+}
+func (m *GetHistoricCandlesRequest) XXX_Size() int {
+ return xxx_messageInfo_GetHistoricCandlesRequest.Size(m)
+}
+func (m *GetHistoricCandlesRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetHistoricCandlesRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetHistoricCandlesRequest proto.InternalMessageInfo
+
+func (m *GetHistoricCandlesRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
-func (x *GetHistoricCandlesRequest) GetPair() *CurrencyPair {
- if x != nil {
- return x.Pair
+func (m *GetHistoricCandlesRequest) GetPair() *CurrencyPair {
+ if m != nil {
+ return m.Pair
}
return nil
}
-func (x *GetHistoricCandlesRequest) GetAssetType() string {
- if x != nil {
- return x.AssetType
+func (m *GetHistoricCandlesRequest) GetAssetType() string {
+ if m != nil {
+ return m.AssetType
}
return ""
}
-func (x *GetHistoricCandlesRequest) GetStart() int64 {
- if x != nil {
- return x.Start
+func (m *GetHistoricCandlesRequest) GetStart() int64 {
+ if m != nil {
+ return m.Start
}
return 0
}
-func (x *GetHistoricCandlesRequest) GetEnd() int64 {
- if x != nil {
- return x.End
+func (m *GetHistoricCandlesRequest) GetEnd() int64 {
+ if m != nil {
+ return m.End
}
return 0
}
-func (x *GetHistoricCandlesRequest) GetTimeInterval() int64 {
- if x != nil {
- return x.TimeInterval
+func (m *GetHistoricCandlesRequest) GetTimeInterval() int64 {
+ if m != nil {
+ return m.TimeInterval
}
return 0
}
-func (x *GetHistoricCandlesRequest) GetExRequest() bool {
- if x != nil {
- return x.ExRequest
+func (m *GetHistoricCandlesRequest) GetExRequest() bool {
+ if m != nil {
+ return m.ExRequest
}
return false
}
type GetHistoricCandlesResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
- Pair *CurrencyPair `protobuf:"bytes,2,opt,name=pair,proto3" json:"pair,omitempty"`
- Start int64 `protobuf:"varint,3,opt,name=start,proto3" json:"start,omitempty"`
- End int64 `protobuf:"varint,4,opt,name=end,proto3" json:"end,omitempty"`
- Interval string `protobuf:"bytes,6,opt,name=interval,proto3" json:"interval,omitempty"`
- Candle []*Candle `protobuf:"bytes,5,rep,name=candle,proto3" json:"candle,omitempty"`
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Pair *CurrencyPair `protobuf:"bytes,2,opt,name=pair,proto3" json:"pair,omitempty"`
+ Start int64 `protobuf:"varint,3,opt,name=start,proto3" json:"start,omitempty"`
+ End int64 `protobuf:"varint,4,opt,name=end,proto3" json:"end,omitempty"`
+ Interval string `protobuf:"bytes,6,opt,name=interval,proto3" json:"interval,omitempty"`
+ Candle []*Candle `protobuf:"bytes,5,rep,name=candle,proto3" json:"candle,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GetHistoricCandlesResponse) Reset() {
- *x = GetHistoricCandlesResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[111]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GetHistoricCandlesResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GetHistoricCandlesResponse) ProtoMessage() {}
-
-func (x *GetHistoricCandlesResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[111]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GetHistoricCandlesResponse.ProtoReflect.Descriptor instead.
+func (m *GetHistoricCandlesResponse) Reset() { *m = GetHistoricCandlesResponse{} }
+func (m *GetHistoricCandlesResponse) String() string { return proto.CompactTextString(m) }
+func (*GetHistoricCandlesResponse) ProtoMessage() {}
func (*GetHistoricCandlesResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{111}
+ return fileDescriptor_77a6da22d6a3feb1, []int{105}
}
-func (x *GetHistoricCandlesResponse) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *GetHistoricCandlesResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetHistoricCandlesResponse.Unmarshal(m, b)
+}
+func (m *GetHistoricCandlesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetHistoricCandlesResponse.Marshal(b, m, deterministic)
+}
+func (m *GetHistoricCandlesResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetHistoricCandlesResponse.Merge(m, src)
+}
+func (m *GetHistoricCandlesResponse) XXX_Size() int {
+ return xxx_messageInfo_GetHistoricCandlesResponse.Size(m)
+}
+func (m *GetHistoricCandlesResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetHistoricCandlesResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetHistoricCandlesResponse proto.InternalMessageInfo
+
+func (m *GetHistoricCandlesResponse) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
-func (x *GetHistoricCandlesResponse) GetPair() *CurrencyPair {
- if x != nil {
- return x.Pair
+func (m *GetHistoricCandlesResponse) GetPair() *CurrencyPair {
+ if m != nil {
+ return m.Pair
}
return nil
}
-func (x *GetHistoricCandlesResponse) GetStart() int64 {
- if x != nil {
- return x.Start
+func (m *GetHistoricCandlesResponse) GetStart() int64 {
+ if m != nil {
+ return m.Start
}
return 0
}
-func (x *GetHistoricCandlesResponse) GetEnd() int64 {
- if x != nil {
- return x.End
+func (m *GetHistoricCandlesResponse) GetEnd() int64 {
+ if m != nil {
+ return m.End
}
return 0
}
-func (x *GetHistoricCandlesResponse) GetInterval() string {
- if x != nil {
- return x.Interval
+func (m *GetHistoricCandlesResponse) GetInterval() string {
+ if m != nil {
+ return m.Interval
}
return ""
}
-func (x *GetHistoricCandlesResponse) GetCandle() []*Candle {
- if x != nil {
- return x.Candle
+func (m *GetHistoricCandlesResponse) GetCandle() []*Candle {
+ if m != nil {
+ return m.Candle
}
return nil
}
type Candle struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Time int64 `protobuf:"varint,1,opt,name=time,proto3" json:"time,omitempty"`
- Low float64 `protobuf:"fixed64,2,opt,name=low,proto3" json:"low,omitempty"`
- High float64 `protobuf:"fixed64,3,opt,name=high,proto3" json:"high,omitempty"`
- Open float64 `protobuf:"fixed64,4,opt,name=open,proto3" json:"open,omitempty"`
- Close float64 `protobuf:"fixed64,5,opt,name=close,proto3" json:"close,omitempty"`
- Volume float64 `protobuf:"fixed64,6,opt,name=volume,proto3" json:"volume,omitempty"`
+ Time int64 `protobuf:"varint,1,opt,name=time,proto3" json:"time,omitempty"`
+ Low float64 `protobuf:"fixed64,2,opt,name=low,proto3" json:"low,omitempty"`
+ High float64 `protobuf:"fixed64,3,opt,name=high,proto3" json:"high,omitempty"`
+ Open float64 `protobuf:"fixed64,4,opt,name=open,proto3" json:"open,omitempty"`
+ Close float64 `protobuf:"fixed64,5,opt,name=close,proto3" json:"close,omitempty"`
+ Volume float64 `protobuf:"fixed64,6,opt,name=volume,proto3" json:"volume,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *Candle) Reset() {
- *x = Candle{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[112]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *Candle) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*Candle) ProtoMessage() {}
-
-func (x *Candle) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[112]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use Candle.ProtoReflect.Descriptor instead.
+func (m *Candle) Reset() { *m = Candle{} }
+func (m *Candle) String() string { return proto.CompactTextString(m) }
+func (*Candle) ProtoMessage() {}
func (*Candle) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{112}
+ return fileDescriptor_77a6da22d6a3feb1, []int{106}
}
-func (x *Candle) GetTime() int64 {
- if x != nil {
- return x.Time
+func (m *Candle) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_Candle.Unmarshal(m, b)
+}
+func (m *Candle) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_Candle.Marshal(b, m, deterministic)
+}
+func (m *Candle) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_Candle.Merge(m, src)
+}
+func (m *Candle) XXX_Size() int {
+ return xxx_messageInfo_Candle.Size(m)
+}
+func (m *Candle) XXX_DiscardUnknown() {
+ xxx_messageInfo_Candle.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_Candle proto.InternalMessageInfo
+
+func (m *Candle) GetTime() int64 {
+ if m != nil {
+ return m.Time
}
return 0
}
-func (x *Candle) GetLow() float64 {
- if x != nil {
- return x.Low
+func (m *Candle) GetLow() float64 {
+ if m != nil {
+ return m.Low
}
return 0
}
-func (x *Candle) GetHigh() float64 {
- if x != nil {
- return x.High
+func (m *Candle) GetHigh() float64 {
+ if m != nil {
+ return m.High
}
return 0
}
-func (x *Candle) GetOpen() float64 {
- if x != nil {
- return x.Open
+func (m *Candle) GetOpen() float64 {
+ if m != nil {
+ return m.Open
}
return 0
}
-func (x *Candle) GetClose() float64 {
- if x != nil {
- return x.Close
+func (m *Candle) GetClose() float64 {
+ if m != nil {
+ return m.Close
}
return 0
}
-func (x *Candle) GetVolume() float64 {
- if x != nil {
- return x.Volume
+func (m *Candle) GetVolume() float64 {
+ if m != nil {
+ return m.Volume
}
return 0
}
type AuditEvent struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"`
- Identifier string `protobuf:"bytes,2,opt,name=identifier,proto3" json:"identifier,omitempty"`
- Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"`
- Timestamp string `protobuf:"bytes,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+ Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"`
+ Identifier string `protobuf:"bytes,2,opt,name=identifier,proto3" json:"identifier,omitempty"`
+ Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"`
+ Timestamp string `protobuf:"bytes,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *AuditEvent) Reset() {
- *x = AuditEvent{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[113]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *AuditEvent) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*AuditEvent) ProtoMessage() {}
-
-func (x *AuditEvent) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[113]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use AuditEvent.ProtoReflect.Descriptor instead.
+func (m *AuditEvent) Reset() { *m = AuditEvent{} }
+func (m *AuditEvent) String() string { return proto.CompactTextString(m) }
+func (*AuditEvent) ProtoMessage() {}
func (*AuditEvent) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{113}
+ return fileDescriptor_77a6da22d6a3feb1, []int{107}
}
-func (x *AuditEvent) GetType() string {
- if x != nil {
- return x.Type
+func (m *AuditEvent) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_AuditEvent.Unmarshal(m, b)
+}
+func (m *AuditEvent) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_AuditEvent.Marshal(b, m, deterministic)
+}
+func (m *AuditEvent) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_AuditEvent.Merge(m, src)
+}
+func (m *AuditEvent) XXX_Size() int {
+ return xxx_messageInfo_AuditEvent.Size(m)
+}
+func (m *AuditEvent) XXX_DiscardUnknown() {
+ xxx_messageInfo_AuditEvent.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_AuditEvent proto.InternalMessageInfo
+
+func (m *AuditEvent) GetType() string {
+ if m != nil {
+ return m.Type
}
return ""
}
-func (x *AuditEvent) GetIdentifier() string {
- if x != nil {
- return x.Identifier
+func (m *AuditEvent) GetIdentifier() string {
+ if m != nil {
+ return m.Identifier
}
return ""
}
-func (x *AuditEvent) GetMessage() string {
- if x != nil {
- return x.Message
+func (m *AuditEvent) GetMessage() string {
+ if m != nil {
+ return m.Message
}
return ""
}
-func (x *AuditEvent) GetTimestamp() string {
- if x != nil {
- return x.Timestamp
+func (m *AuditEvent) GetTimestamp() string {
+ if m != nil {
+ return m.Timestamp
}
return ""
}
type GCTScript struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- UUID string `protobuf:"bytes,1,opt,name=UUID,proto3" json:"UUID,omitempty"`
- Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
- Path string `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"`
- NextRun string `protobuf:"bytes,4,opt,name=next_run,json=nextRun,proto3" json:"next_run,omitempty"`
+ UUID string `protobuf:"bytes,1,opt,name=UUID,proto3" json:"UUID,omitempty"`
+ Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
+ Path string `protobuf:"bytes,3,opt,name=path,proto3" json:"path,omitempty"`
+ NextRun string `protobuf:"bytes,4,opt,name=next_run,json=nextRun,proto3" json:"next_run,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GCTScript) Reset() {
- *x = GCTScript{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[114]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GCTScript) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GCTScript) ProtoMessage() {}
-
-func (x *GCTScript) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[114]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GCTScript.ProtoReflect.Descriptor instead.
+func (m *GCTScript) Reset() { *m = GCTScript{} }
+func (m *GCTScript) String() string { return proto.CompactTextString(m) }
+func (*GCTScript) ProtoMessage() {}
func (*GCTScript) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{114}
+ return fileDescriptor_77a6da22d6a3feb1, []int{108}
}
-func (x *GCTScript) GetUUID() string {
- if x != nil {
- return x.UUID
+func (m *GCTScript) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GCTScript.Unmarshal(m, b)
+}
+func (m *GCTScript) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GCTScript.Marshal(b, m, deterministic)
+}
+func (m *GCTScript) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GCTScript.Merge(m, src)
+}
+func (m *GCTScript) XXX_Size() int {
+ return xxx_messageInfo_GCTScript.Size(m)
+}
+func (m *GCTScript) XXX_DiscardUnknown() {
+ xxx_messageInfo_GCTScript.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GCTScript proto.InternalMessageInfo
+
+func (m *GCTScript) GetUUID() string {
+ if m != nil {
+ return m.UUID
}
return ""
}
-func (x *GCTScript) GetName() string {
- if x != nil {
- return x.Name
+func (m *GCTScript) GetName() string {
+ if m != nil {
+ return m.Name
}
return ""
}
-func (x *GCTScript) GetPath() string {
- if x != nil {
- return x.Path
+func (m *GCTScript) GetPath() string {
+ if m != nil {
+ return m.Path
}
return ""
}
-func (x *GCTScript) GetNextRun() string {
- if x != nil {
- return x.NextRun
+func (m *GCTScript) GetNextRun() string {
+ if m != nil {
+ return m.NextRun
}
return ""
}
type GCTScriptExecuteRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Script *GCTScript `protobuf:"bytes,1,opt,name=script,proto3" json:"script,omitempty"`
+ Script *GCTScript `protobuf:"bytes,1,opt,name=script,proto3" json:"script,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GCTScriptExecuteRequest) Reset() {
- *x = GCTScriptExecuteRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[115]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GCTScriptExecuteRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GCTScriptExecuteRequest) ProtoMessage() {}
-
-func (x *GCTScriptExecuteRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[115]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GCTScriptExecuteRequest.ProtoReflect.Descriptor instead.
+func (m *GCTScriptExecuteRequest) Reset() { *m = GCTScriptExecuteRequest{} }
+func (m *GCTScriptExecuteRequest) String() string { return proto.CompactTextString(m) }
+func (*GCTScriptExecuteRequest) ProtoMessage() {}
func (*GCTScriptExecuteRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{115}
+ return fileDescriptor_77a6da22d6a3feb1, []int{109}
}
-func (x *GCTScriptExecuteRequest) GetScript() *GCTScript {
- if x != nil {
- return x.Script
+func (m *GCTScriptExecuteRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GCTScriptExecuteRequest.Unmarshal(m, b)
+}
+func (m *GCTScriptExecuteRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GCTScriptExecuteRequest.Marshal(b, m, deterministic)
+}
+func (m *GCTScriptExecuteRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GCTScriptExecuteRequest.Merge(m, src)
+}
+func (m *GCTScriptExecuteRequest) XXX_Size() int {
+ return xxx_messageInfo_GCTScriptExecuteRequest.Size(m)
+}
+func (m *GCTScriptExecuteRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GCTScriptExecuteRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GCTScriptExecuteRequest proto.InternalMessageInfo
+
+func (m *GCTScriptExecuteRequest) GetScript() *GCTScript {
+ if m != nil {
+ return m.Script
}
return nil
}
type GCTScriptStopRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Script *GCTScript `protobuf:"bytes,1,opt,name=script,proto3" json:"script,omitempty"`
+ Script *GCTScript `protobuf:"bytes,1,opt,name=script,proto3" json:"script,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GCTScriptStopRequest) Reset() {
- *x = GCTScriptStopRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[116]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GCTScriptStopRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GCTScriptStopRequest) ProtoMessage() {}
-
-func (x *GCTScriptStopRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[116]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GCTScriptStopRequest.ProtoReflect.Descriptor instead.
+func (m *GCTScriptStopRequest) Reset() { *m = GCTScriptStopRequest{} }
+func (m *GCTScriptStopRequest) String() string { return proto.CompactTextString(m) }
+func (*GCTScriptStopRequest) ProtoMessage() {}
func (*GCTScriptStopRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{116}
+ return fileDescriptor_77a6da22d6a3feb1, []int{110}
}
-func (x *GCTScriptStopRequest) GetScript() *GCTScript {
- if x != nil {
- return x.Script
+func (m *GCTScriptStopRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GCTScriptStopRequest.Unmarshal(m, b)
+}
+func (m *GCTScriptStopRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GCTScriptStopRequest.Marshal(b, m, deterministic)
+}
+func (m *GCTScriptStopRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GCTScriptStopRequest.Merge(m, src)
+}
+func (m *GCTScriptStopRequest) XXX_Size() int {
+ return xxx_messageInfo_GCTScriptStopRequest.Size(m)
+}
+func (m *GCTScriptStopRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GCTScriptStopRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GCTScriptStopRequest proto.InternalMessageInfo
+
+func (m *GCTScriptStopRequest) GetScript() *GCTScript {
+ if m != nil {
+ return m.Script
}
return nil
}
type GCTScriptStopAllRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GCTScriptStopAllRequest) Reset() {
- *x = GCTScriptStopAllRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[117]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GCTScriptStopAllRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GCTScriptStopAllRequest) ProtoMessage() {}
-
-func (x *GCTScriptStopAllRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[117]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GCTScriptStopAllRequest.ProtoReflect.Descriptor instead.
+func (m *GCTScriptStopAllRequest) Reset() { *m = GCTScriptStopAllRequest{} }
+func (m *GCTScriptStopAllRequest) String() string { return proto.CompactTextString(m) }
+func (*GCTScriptStopAllRequest) ProtoMessage() {}
func (*GCTScriptStopAllRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{117}
+ return fileDescriptor_77a6da22d6a3feb1, []int{111}
}
+func (m *GCTScriptStopAllRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GCTScriptStopAllRequest.Unmarshal(m, b)
+}
+func (m *GCTScriptStopAllRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GCTScriptStopAllRequest.Marshal(b, m, deterministic)
+}
+func (m *GCTScriptStopAllRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GCTScriptStopAllRequest.Merge(m, src)
+}
+func (m *GCTScriptStopAllRequest) XXX_Size() int {
+ return xxx_messageInfo_GCTScriptStopAllRequest.Size(m)
+}
+func (m *GCTScriptStopAllRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GCTScriptStopAllRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GCTScriptStopAllRequest proto.InternalMessageInfo
+
type GCTScriptStatusRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GCTScriptStatusRequest) Reset() {
- *x = GCTScriptStatusRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[118]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GCTScriptStatusRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GCTScriptStatusRequest) ProtoMessage() {}
-
-func (x *GCTScriptStatusRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[118]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GCTScriptStatusRequest.ProtoReflect.Descriptor instead.
+func (m *GCTScriptStatusRequest) Reset() { *m = GCTScriptStatusRequest{} }
+func (m *GCTScriptStatusRequest) String() string { return proto.CompactTextString(m) }
+func (*GCTScriptStatusRequest) ProtoMessage() {}
func (*GCTScriptStatusRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{118}
+ return fileDescriptor_77a6da22d6a3feb1, []int{112}
}
+func (m *GCTScriptStatusRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GCTScriptStatusRequest.Unmarshal(m, b)
+}
+func (m *GCTScriptStatusRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GCTScriptStatusRequest.Marshal(b, m, deterministic)
+}
+func (m *GCTScriptStatusRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GCTScriptStatusRequest.Merge(m, src)
+}
+func (m *GCTScriptStatusRequest) XXX_Size() int {
+ return xxx_messageInfo_GCTScriptStatusRequest.Size(m)
+}
+func (m *GCTScriptStatusRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GCTScriptStatusRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GCTScriptStatusRequest proto.InternalMessageInfo
+
type GCTScriptListAllRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GCTScriptListAllRequest) Reset() {
- *x = GCTScriptListAllRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[119]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GCTScriptListAllRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GCTScriptListAllRequest) ProtoMessage() {}
-
-func (x *GCTScriptListAllRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[119]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GCTScriptListAllRequest.ProtoReflect.Descriptor instead.
+func (m *GCTScriptListAllRequest) Reset() { *m = GCTScriptListAllRequest{} }
+func (m *GCTScriptListAllRequest) String() string { return proto.CompactTextString(m) }
+func (*GCTScriptListAllRequest) ProtoMessage() {}
func (*GCTScriptListAllRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{119}
+ return fileDescriptor_77a6da22d6a3feb1, []int{113}
}
+func (m *GCTScriptListAllRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GCTScriptListAllRequest.Unmarshal(m, b)
+}
+func (m *GCTScriptListAllRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GCTScriptListAllRequest.Marshal(b, m, deterministic)
+}
+func (m *GCTScriptListAllRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GCTScriptListAllRequest.Merge(m, src)
+}
+func (m *GCTScriptListAllRequest) XXX_Size() int {
+ return xxx_messageInfo_GCTScriptListAllRequest.Size(m)
+}
+func (m *GCTScriptListAllRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GCTScriptListAllRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GCTScriptListAllRequest proto.InternalMessageInfo
+
type GCTScriptUploadRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- ScriptName string `protobuf:"bytes,1,opt,name=script_name,json=scriptName,proto3" json:"script_name,omitempty"`
- ScriptData string `protobuf:"bytes,2,opt,name=script_data,json=scriptData,proto3" json:"script_data,omitempty"`
- Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"`
- Archived bool `protobuf:"varint,4,opt,name=archived,proto3" json:"archived,omitempty"`
- Overwrite bool `protobuf:"varint,5,opt,name=overwrite,proto3" json:"overwrite,omitempty"`
+ ScriptName string `protobuf:"bytes,1,opt,name=script_name,json=scriptName,proto3" json:"script_name,omitempty"`
+ ScriptData string `protobuf:"bytes,2,opt,name=script_data,json=scriptData,proto3" json:"script_data,omitempty"`
+ Data []byte `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"`
+ Archived bool `protobuf:"varint,4,opt,name=archived,proto3" json:"archived,omitempty"`
+ Overwrite bool `protobuf:"varint,5,opt,name=overwrite,proto3" json:"overwrite,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GCTScriptUploadRequest) Reset() {
- *x = GCTScriptUploadRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[120]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GCTScriptUploadRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GCTScriptUploadRequest) ProtoMessage() {}
-
-func (x *GCTScriptUploadRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[120]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GCTScriptUploadRequest.ProtoReflect.Descriptor instead.
+func (m *GCTScriptUploadRequest) Reset() { *m = GCTScriptUploadRequest{} }
+func (m *GCTScriptUploadRequest) String() string { return proto.CompactTextString(m) }
+func (*GCTScriptUploadRequest) ProtoMessage() {}
func (*GCTScriptUploadRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{120}
+ return fileDescriptor_77a6da22d6a3feb1, []int{114}
}
-func (x *GCTScriptUploadRequest) GetScriptName() string {
- if x != nil {
- return x.ScriptName
+func (m *GCTScriptUploadRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GCTScriptUploadRequest.Unmarshal(m, b)
+}
+func (m *GCTScriptUploadRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GCTScriptUploadRequest.Marshal(b, m, deterministic)
+}
+func (m *GCTScriptUploadRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GCTScriptUploadRequest.Merge(m, src)
+}
+func (m *GCTScriptUploadRequest) XXX_Size() int {
+ return xxx_messageInfo_GCTScriptUploadRequest.Size(m)
+}
+func (m *GCTScriptUploadRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GCTScriptUploadRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GCTScriptUploadRequest proto.InternalMessageInfo
+
+func (m *GCTScriptUploadRequest) GetScriptName() string {
+ if m != nil {
+ return m.ScriptName
}
return ""
}
-func (x *GCTScriptUploadRequest) GetScriptData() string {
- if x != nil {
- return x.ScriptData
+func (m *GCTScriptUploadRequest) GetScriptData() string {
+ if m != nil {
+ return m.ScriptData
}
return ""
}
-func (x *GCTScriptUploadRequest) GetData() []byte {
- if x != nil {
- return x.Data
+func (m *GCTScriptUploadRequest) GetData() []byte {
+ if m != nil {
+ return m.Data
}
return nil
}
-func (x *GCTScriptUploadRequest) GetArchived() bool {
- if x != nil {
- return x.Archived
+func (m *GCTScriptUploadRequest) GetArchived() bool {
+ if m != nil {
+ return m.Archived
}
return false
}
-func (x *GCTScriptUploadRequest) GetOverwrite() bool {
- if x != nil {
- return x.Overwrite
+func (m *GCTScriptUploadRequest) GetOverwrite() bool {
+ if m != nil {
+ return m.Overwrite
}
return false
}
type GCTScriptReadScriptRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Script *GCTScript `protobuf:"bytes,1,opt,name=script,proto3" json:"script,omitempty"`
+ Script *GCTScript `protobuf:"bytes,1,opt,name=script,proto3" json:"script,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GCTScriptReadScriptRequest) Reset() {
- *x = GCTScriptReadScriptRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[121]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GCTScriptReadScriptRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GCTScriptReadScriptRequest) ProtoMessage() {}
-
-func (x *GCTScriptReadScriptRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[121]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GCTScriptReadScriptRequest.ProtoReflect.Descriptor instead.
+func (m *GCTScriptReadScriptRequest) Reset() { *m = GCTScriptReadScriptRequest{} }
+func (m *GCTScriptReadScriptRequest) String() string { return proto.CompactTextString(m) }
+func (*GCTScriptReadScriptRequest) ProtoMessage() {}
func (*GCTScriptReadScriptRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{121}
+ return fileDescriptor_77a6da22d6a3feb1, []int{115}
}
-func (x *GCTScriptReadScriptRequest) GetScript() *GCTScript {
- if x != nil {
- return x.Script
+func (m *GCTScriptReadScriptRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GCTScriptReadScriptRequest.Unmarshal(m, b)
+}
+func (m *GCTScriptReadScriptRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GCTScriptReadScriptRequest.Marshal(b, m, deterministic)
+}
+func (m *GCTScriptReadScriptRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GCTScriptReadScriptRequest.Merge(m, src)
+}
+func (m *GCTScriptReadScriptRequest) XXX_Size() int {
+ return xxx_messageInfo_GCTScriptReadScriptRequest.Size(m)
+}
+func (m *GCTScriptReadScriptRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GCTScriptReadScriptRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GCTScriptReadScriptRequest proto.InternalMessageInfo
+
+func (m *GCTScriptReadScriptRequest) GetScript() *GCTScript {
+ if m != nil {
+ return m.Script
}
return nil
}
type GCTScriptQueryRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Script *GCTScript `protobuf:"bytes,1,opt,name=script,proto3" json:"script,omitempty"`
+ Script *GCTScript `protobuf:"bytes,1,opt,name=script,proto3" json:"script,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GCTScriptQueryRequest) Reset() {
- *x = GCTScriptQueryRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[122]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GCTScriptQueryRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GCTScriptQueryRequest) ProtoMessage() {}
-
-func (x *GCTScriptQueryRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[122]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GCTScriptQueryRequest.ProtoReflect.Descriptor instead.
+func (m *GCTScriptQueryRequest) Reset() { *m = GCTScriptQueryRequest{} }
+func (m *GCTScriptQueryRequest) String() string { return proto.CompactTextString(m) }
+func (*GCTScriptQueryRequest) ProtoMessage() {}
func (*GCTScriptQueryRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{122}
+ return fileDescriptor_77a6da22d6a3feb1, []int{116}
}
-func (x *GCTScriptQueryRequest) GetScript() *GCTScript {
- if x != nil {
- return x.Script
+func (m *GCTScriptQueryRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GCTScriptQueryRequest.Unmarshal(m, b)
+}
+func (m *GCTScriptQueryRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GCTScriptQueryRequest.Marshal(b, m, deterministic)
+}
+func (m *GCTScriptQueryRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GCTScriptQueryRequest.Merge(m, src)
+}
+func (m *GCTScriptQueryRequest) XXX_Size() int {
+ return xxx_messageInfo_GCTScriptQueryRequest.Size(m)
+}
+func (m *GCTScriptQueryRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GCTScriptQueryRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GCTScriptQueryRequest proto.InternalMessageInfo
+
+func (m *GCTScriptQueryRequest) GetScript() *GCTScript {
+ if m != nil {
+ return m.Script
}
return nil
}
type GCTScriptAutoLoadRequest struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Script string `protobuf:"bytes,1,opt,name=script,proto3" json:"script,omitempty"`
- Status bool `protobuf:"varint,2,opt,name=status,proto3" json:"status,omitempty"`
+ Script string `protobuf:"bytes,1,opt,name=script,proto3" json:"script,omitempty"`
+ Status bool `protobuf:"varint,2,opt,name=status,proto3" json:"status,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GCTScriptAutoLoadRequest) Reset() {
- *x = GCTScriptAutoLoadRequest{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[123]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GCTScriptAutoLoadRequest) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GCTScriptAutoLoadRequest) ProtoMessage() {}
-
-func (x *GCTScriptAutoLoadRequest) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[123]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GCTScriptAutoLoadRequest.ProtoReflect.Descriptor instead.
+func (m *GCTScriptAutoLoadRequest) Reset() { *m = GCTScriptAutoLoadRequest{} }
+func (m *GCTScriptAutoLoadRequest) String() string { return proto.CompactTextString(m) }
+func (*GCTScriptAutoLoadRequest) ProtoMessage() {}
func (*GCTScriptAutoLoadRequest) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{123}
+ return fileDescriptor_77a6da22d6a3feb1, []int{117}
}
-func (x *GCTScriptAutoLoadRequest) GetScript() string {
- if x != nil {
- return x.Script
+func (m *GCTScriptAutoLoadRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GCTScriptAutoLoadRequest.Unmarshal(m, b)
+}
+func (m *GCTScriptAutoLoadRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GCTScriptAutoLoadRequest.Marshal(b, m, deterministic)
+}
+func (m *GCTScriptAutoLoadRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GCTScriptAutoLoadRequest.Merge(m, src)
+}
+func (m *GCTScriptAutoLoadRequest) XXX_Size() int {
+ return xxx_messageInfo_GCTScriptAutoLoadRequest.Size(m)
+}
+func (m *GCTScriptAutoLoadRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GCTScriptAutoLoadRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GCTScriptAutoLoadRequest proto.InternalMessageInfo
+
+func (m *GCTScriptAutoLoadRequest) GetScript() string {
+ if m != nil {
+ return m.Script
}
return ""
}
-func (x *GCTScriptAutoLoadRequest) GetStatus() bool {
- if x != nil {
- return x.Status
+func (m *GCTScriptAutoLoadRequest) GetStatus() bool {
+ if m != nil {
+ return m.Status
}
return false
}
type GCTScriptStatusResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Status string `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"`
- Scripts []*GCTScript `protobuf:"bytes,2,rep,name=scripts,proto3" json:"scripts,omitempty"`
+ Status string `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"`
+ Scripts []*GCTScript `protobuf:"bytes,2,rep,name=scripts,proto3" json:"scripts,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GCTScriptStatusResponse) Reset() {
- *x = GCTScriptStatusResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[124]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GCTScriptStatusResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GCTScriptStatusResponse) ProtoMessage() {}
-
-func (x *GCTScriptStatusResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[124]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GCTScriptStatusResponse.ProtoReflect.Descriptor instead.
+func (m *GCTScriptStatusResponse) Reset() { *m = GCTScriptStatusResponse{} }
+func (m *GCTScriptStatusResponse) String() string { return proto.CompactTextString(m) }
+func (*GCTScriptStatusResponse) ProtoMessage() {}
func (*GCTScriptStatusResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{124}
+ return fileDescriptor_77a6da22d6a3feb1, []int{118}
}
-func (x *GCTScriptStatusResponse) GetStatus() string {
- if x != nil {
- return x.Status
+func (m *GCTScriptStatusResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GCTScriptStatusResponse.Unmarshal(m, b)
+}
+func (m *GCTScriptStatusResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GCTScriptStatusResponse.Marshal(b, m, deterministic)
+}
+func (m *GCTScriptStatusResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GCTScriptStatusResponse.Merge(m, src)
+}
+func (m *GCTScriptStatusResponse) XXX_Size() int {
+ return xxx_messageInfo_GCTScriptStatusResponse.Size(m)
+}
+func (m *GCTScriptStatusResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GCTScriptStatusResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GCTScriptStatusResponse proto.InternalMessageInfo
+
+func (m *GCTScriptStatusResponse) GetStatus() string {
+ if m != nil {
+ return m.Status
}
return ""
}
-func (x *GCTScriptStatusResponse) GetScripts() []*GCTScript {
- if x != nil {
- return x.Scripts
+func (m *GCTScriptStatusResponse) GetScripts() []*GCTScript {
+ if m != nil {
+ return m.Scripts
}
return nil
}
type GCTScriptQueryResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Status string `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"`
- Script *GCTScript `protobuf:"bytes,2,opt,name=script,proto3" json:"script,omitempty"`
- Data string `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"`
+ Status string `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"`
+ Script *GCTScript `protobuf:"bytes,2,opt,name=script,proto3" json:"script,omitempty"`
+ Data string `protobuf:"bytes,3,opt,name=data,proto3" json:"data,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GCTScriptQueryResponse) Reset() {
- *x = GCTScriptQueryResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[125]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
-}
-
-func (x *GCTScriptQueryResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
-}
-
-func (*GCTScriptQueryResponse) ProtoMessage() {}
-
-func (x *GCTScriptQueryResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[125]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GCTScriptQueryResponse.ProtoReflect.Descriptor instead.
+func (m *GCTScriptQueryResponse) Reset() { *m = GCTScriptQueryResponse{} }
+func (m *GCTScriptQueryResponse) String() string { return proto.CompactTextString(m) }
+func (*GCTScriptQueryResponse) ProtoMessage() {}
func (*GCTScriptQueryResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{125}
+ return fileDescriptor_77a6da22d6a3feb1, []int{119}
}
-func (x *GCTScriptQueryResponse) GetStatus() string {
- if x != nil {
- return x.Status
+func (m *GCTScriptQueryResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GCTScriptQueryResponse.Unmarshal(m, b)
+}
+func (m *GCTScriptQueryResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GCTScriptQueryResponse.Marshal(b, m, deterministic)
+}
+func (m *GCTScriptQueryResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GCTScriptQueryResponse.Merge(m, src)
+}
+func (m *GCTScriptQueryResponse) XXX_Size() int {
+ return xxx_messageInfo_GCTScriptQueryResponse.Size(m)
+}
+func (m *GCTScriptQueryResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GCTScriptQueryResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GCTScriptQueryResponse proto.InternalMessageInfo
+
+func (m *GCTScriptQueryResponse) GetStatus() string {
+ if m != nil {
+ return m.Status
}
return ""
}
-func (x *GCTScriptQueryResponse) GetScript() *GCTScript {
- if x != nil {
- return x.Script
+func (m *GCTScriptQueryResponse) GetScript() *GCTScript {
+ if m != nil {
+ return m.Script
}
return nil
}
-func (x *GCTScriptQueryResponse) GetData() string {
- if x != nil {
- return x.Data
+func (m *GCTScriptQueryResponse) GetData() string {
+ if m != nil {
+ return m.Data
}
return ""
}
-type GCTScriptGenericResponse struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Status string `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"`
- Data string `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
+type GenericResponse struct {
+ Status string `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"`
+ Data string `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *GCTScriptGenericResponse) Reset() {
- *x = GCTScriptGenericResponse{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[126]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+func (m *GenericResponse) Reset() { *m = GenericResponse{} }
+func (m *GenericResponse) String() string { return proto.CompactTextString(m) }
+func (*GenericResponse) ProtoMessage() {}
+func (*GenericResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_77a6da22d6a3feb1, []int{120}
}
-func (x *GCTScriptGenericResponse) String() string {
- return protoimpl.X.MessageStringOf(x)
+func (m *GenericResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GenericResponse.Unmarshal(m, b)
+}
+func (m *GenericResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GenericResponse.Marshal(b, m, deterministic)
+}
+func (m *GenericResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GenericResponse.Merge(m, src)
+}
+func (m *GenericResponse) XXX_Size() int {
+ return xxx_messageInfo_GenericResponse.Size(m)
+}
+func (m *GenericResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GenericResponse.DiscardUnknown(m)
}
-func (*GCTScriptGenericResponse) ProtoMessage() {}
+var xxx_messageInfo_GenericResponse proto.InternalMessageInfo
-func (x *GCTScriptGenericResponse) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[126]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use GCTScriptGenericResponse.ProtoReflect.Descriptor instead.
-func (*GCTScriptGenericResponse) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{126}
-}
-
-func (x *GCTScriptGenericResponse) GetStatus() string {
- if x != nil {
- return x.Status
+func (m *GenericResponse) GetStatus() string {
+ if m != nil {
+ return m.Status
}
return ""
}
-func (x *GCTScriptGenericResponse) GetData() string {
- if x != nil {
- return x.Data
+func (m *GenericResponse) GetData() string {
+ if m != nil {
+ return m.Data
}
return ""
}
-type CancelAllOrdersResponse_Orders struct {
- state protoimpl.MessageState
- sizeCache protoimpl.SizeCache
- unknownFields protoimpl.UnknownFields
-
- Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
- OrderStatus map[string]string `protobuf:"bytes,2,rep,name=order_status,json=orderStatus,proto3" json:"order_status,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
+type SetExchangeAssetRequest struct {
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Asset string `protobuf:"bytes,2,opt,name=asset,proto3" json:"asset,omitempty"`
+ Enable bool `protobuf:"varint,3,opt,name=enable,proto3" json:"enable,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-func (x *CancelAllOrdersResponse_Orders) Reset() {
- *x = CancelAllOrdersResponse_Orders{}
- if protoimpl.UnsafeEnabled {
- mi := &file_rpc_proto_msgTypes[137]
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- ms.StoreMessageInfo(mi)
- }
+func (m *SetExchangeAssetRequest) Reset() { *m = SetExchangeAssetRequest{} }
+func (m *SetExchangeAssetRequest) String() string { return proto.CompactTextString(m) }
+func (*SetExchangeAssetRequest) ProtoMessage() {}
+func (*SetExchangeAssetRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_77a6da22d6a3feb1, []int{121}
}
-func (x *CancelAllOrdersResponse_Orders) String() string {
- return protoimpl.X.MessageStringOf(x)
+func (m *SetExchangeAssetRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_SetExchangeAssetRequest.Unmarshal(m, b)
+}
+func (m *SetExchangeAssetRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_SetExchangeAssetRequest.Marshal(b, m, deterministic)
+}
+func (m *SetExchangeAssetRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_SetExchangeAssetRequest.Merge(m, src)
+}
+func (m *SetExchangeAssetRequest) XXX_Size() int {
+ return xxx_messageInfo_SetExchangeAssetRequest.Size(m)
+}
+func (m *SetExchangeAssetRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_SetExchangeAssetRequest.DiscardUnknown(m)
}
-func (*CancelAllOrdersResponse_Orders) ProtoMessage() {}
+var xxx_messageInfo_SetExchangeAssetRequest proto.InternalMessageInfo
-func (x *CancelAllOrdersResponse_Orders) ProtoReflect() protoreflect.Message {
- mi := &file_rpc_proto_msgTypes[137]
- if protoimpl.UnsafeEnabled && x != nil {
- ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
- if ms.LoadMessageInfo() == nil {
- ms.StoreMessageInfo(mi)
- }
- return ms
- }
- return mi.MessageOf(x)
-}
-
-// Deprecated: Use CancelAllOrdersResponse_Orders.ProtoReflect.Descriptor instead.
-func (*CancelAllOrdersResponse_Orders) Descriptor() ([]byte, []int) {
- return file_rpc_proto_rawDescGZIP(), []int{73, 0}
-}
-
-func (x *CancelAllOrdersResponse_Orders) GetExchange() string {
- if x != nil {
- return x.Exchange
+func (m *SetExchangeAssetRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
return ""
}
-func (x *CancelAllOrdersResponse_Orders) GetOrderStatus() map[string]string {
- if x != nil {
- return x.OrderStatus
+func (m *SetExchangeAssetRequest) GetAsset() string {
+ if m != nil {
+ return m.Asset
+ }
+ return ""
+}
+
+func (m *SetExchangeAssetRequest) GetEnable() bool {
+ if m != nil {
+ return m.Enable
+ }
+ return false
+}
+
+type SetExchangeAllPairsRequest struct {
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Enable bool `protobuf:"varint,2,opt,name=enable,proto3" json:"enable,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *SetExchangeAllPairsRequest) Reset() { *m = SetExchangeAllPairsRequest{} }
+func (m *SetExchangeAllPairsRequest) String() string { return proto.CompactTextString(m) }
+func (*SetExchangeAllPairsRequest) ProtoMessage() {}
+func (*SetExchangeAllPairsRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_77a6da22d6a3feb1, []int{122}
+}
+
+func (m *SetExchangeAllPairsRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_SetExchangeAllPairsRequest.Unmarshal(m, b)
+}
+func (m *SetExchangeAllPairsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_SetExchangeAllPairsRequest.Marshal(b, m, deterministic)
+}
+func (m *SetExchangeAllPairsRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_SetExchangeAllPairsRequest.Merge(m, src)
+}
+func (m *SetExchangeAllPairsRequest) XXX_Size() int {
+ return xxx_messageInfo_SetExchangeAllPairsRequest.Size(m)
+}
+func (m *SetExchangeAllPairsRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_SetExchangeAllPairsRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_SetExchangeAllPairsRequest proto.InternalMessageInfo
+
+func (m *SetExchangeAllPairsRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
+ }
+ return ""
+}
+
+func (m *SetExchangeAllPairsRequest) GetEnable() bool {
+ if m != nil {
+ return m.Enable
+ }
+ return false
+}
+
+type UpdateExchangeSupportedPairsRequest struct {
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *UpdateExchangeSupportedPairsRequest) Reset() { *m = UpdateExchangeSupportedPairsRequest{} }
+func (m *UpdateExchangeSupportedPairsRequest) String() string { return proto.CompactTextString(m) }
+func (*UpdateExchangeSupportedPairsRequest) ProtoMessage() {}
+func (*UpdateExchangeSupportedPairsRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_77a6da22d6a3feb1, []int{123}
+}
+
+func (m *UpdateExchangeSupportedPairsRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_UpdateExchangeSupportedPairsRequest.Unmarshal(m, b)
+}
+func (m *UpdateExchangeSupportedPairsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_UpdateExchangeSupportedPairsRequest.Marshal(b, m, deterministic)
+}
+func (m *UpdateExchangeSupportedPairsRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_UpdateExchangeSupportedPairsRequest.Merge(m, src)
+}
+func (m *UpdateExchangeSupportedPairsRequest) XXX_Size() int {
+ return xxx_messageInfo_UpdateExchangeSupportedPairsRequest.Size(m)
+}
+func (m *UpdateExchangeSupportedPairsRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_UpdateExchangeSupportedPairsRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_UpdateExchangeSupportedPairsRequest proto.InternalMessageInfo
+
+func (m *UpdateExchangeSupportedPairsRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
+ }
+ return ""
+}
+
+type GetExchangeAssetsRequest struct {
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *GetExchangeAssetsRequest) Reset() { *m = GetExchangeAssetsRequest{} }
+func (m *GetExchangeAssetsRequest) String() string { return proto.CompactTextString(m) }
+func (*GetExchangeAssetsRequest) ProtoMessage() {}
+func (*GetExchangeAssetsRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_77a6da22d6a3feb1, []int{124}
+}
+
+func (m *GetExchangeAssetsRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetExchangeAssetsRequest.Unmarshal(m, b)
+}
+func (m *GetExchangeAssetsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetExchangeAssetsRequest.Marshal(b, m, deterministic)
+}
+func (m *GetExchangeAssetsRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetExchangeAssetsRequest.Merge(m, src)
+}
+func (m *GetExchangeAssetsRequest) XXX_Size() int {
+ return xxx_messageInfo_GetExchangeAssetsRequest.Size(m)
+}
+func (m *GetExchangeAssetsRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetExchangeAssetsRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetExchangeAssetsRequest proto.InternalMessageInfo
+
+func (m *GetExchangeAssetsRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
+ }
+ return ""
+}
+
+type GetExchangeAssetsResponse struct {
+ Assets string `protobuf:"bytes,1,opt,name=assets,proto3" json:"assets,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *GetExchangeAssetsResponse) Reset() { *m = GetExchangeAssetsResponse{} }
+func (m *GetExchangeAssetsResponse) String() string { return proto.CompactTextString(m) }
+func (*GetExchangeAssetsResponse) ProtoMessage() {}
+func (*GetExchangeAssetsResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_77a6da22d6a3feb1, []int{125}
+}
+
+func (m *GetExchangeAssetsResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_GetExchangeAssetsResponse.Unmarshal(m, b)
+}
+func (m *GetExchangeAssetsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_GetExchangeAssetsResponse.Marshal(b, m, deterministic)
+}
+func (m *GetExchangeAssetsResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_GetExchangeAssetsResponse.Merge(m, src)
+}
+func (m *GetExchangeAssetsResponse) XXX_Size() int {
+ return xxx_messageInfo_GetExchangeAssetsResponse.Size(m)
+}
+func (m *GetExchangeAssetsResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_GetExchangeAssetsResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_GetExchangeAssetsResponse proto.InternalMessageInfo
+
+func (m *GetExchangeAssetsResponse) GetAssets() string {
+ if m != nil {
+ return m.Assets
+ }
+ return ""
+}
+
+type WebsocketGetInfoRequest struct {
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *WebsocketGetInfoRequest) Reset() { *m = WebsocketGetInfoRequest{} }
+func (m *WebsocketGetInfoRequest) String() string { return proto.CompactTextString(m) }
+func (*WebsocketGetInfoRequest) ProtoMessage() {}
+func (*WebsocketGetInfoRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_77a6da22d6a3feb1, []int{126}
+}
+
+func (m *WebsocketGetInfoRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_WebsocketGetInfoRequest.Unmarshal(m, b)
+}
+func (m *WebsocketGetInfoRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_WebsocketGetInfoRequest.Marshal(b, m, deterministic)
+}
+func (m *WebsocketGetInfoRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_WebsocketGetInfoRequest.Merge(m, src)
+}
+func (m *WebsocketGetInfoRequest) XXX_Size() int {
+ return xxx_messageInfo_WebsocketGetInfoRequest.Size(m)
+}
+func (m *WebsocketGetInfoRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_WebsocketGetInfoRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_WebsocketGetInfoRequest proto.InternalMessageInfo
+
+func (m *WebsocketGetInfoRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
+ }
+ return ""
+}
+
+type WebsocketGetInfoResponse struct {
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Supported bool `protobuf:"varint,2,opt,name=supported,proto3" json:"supported,omitempty"`
+ Enabled bool `protobuf:"varint,3,opt,name=enabled,proto3" json:"enabled,omitempty"`
+ AuthenticatedSupported bool `protobuf:"varint,4,opt,name=authenticated_supported,json=authenticatedSupported,proto3" json:"authenticated_supported,omitempty"`
+ Authenticated bool `protobuf:"varint,5,opt,name=authenticated,proto3" json:"authenticated,omitempty"`
+ RunningUrl string `protobuf:"bytes,6,opt,name=running_url,json=runningUrl,proto3" json:"running_url,omitempty"`
+ ProxyAddress string `protobuf:"bytes,7,opt,name=proxy_address,json=proxyAddress,proto3" json:"proxy_address,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *WebsocketGetInfoResponse) Reset() { *m = WebsocketGetInfoResponse{} }
+func (m *WebsocketGetInfoResponse) String() string { return proto.CompactTextString(m) }
+func (*WebsocketGetInfoResponse) ProtoMessage() {}
+func (*WebsocketGetInfoResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_77a6da22d6a3feb1, []int{127}
+}
+
+func (m *WebsocketGetInfoResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_WebsocketGetInfoResponse.Unmarshal(m, b)
+}
+func (m *WebsocketGetInfoResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_WebsocketGetInfoResponse.Marshal(b, m, deterministic)
+}
+func (m *WebsocketGetInfoResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_WebsocketGetInfoResponse.Merge(m, src)
+}
+func (m *WebsocketGetInfoResponse) XXX_Size() int {
+ return xxx_messageInfo_WebsocketGetInfoResponse.Size(m)
+}
+func (m *WebsocketGetInfoResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_WebsocketGetInfoResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_WebsocketGetInfoResponse proto.InternalMessageInfo
+
+func (m *WebsocketGetInfoResponse) GetExchange() string {
+ if m != nil {
+ return m.Exchange
+ }
+ return ""
+}
+
+func (m *WebsocketGetInfoResponse) GetSupported() bool {
+ if m != nil {
+ return m.Supported
+ }
+ return false
+}
+
+func (m *WebsocketGetInfoResponse) GetEnabled() bool {
+ if m != nil {
+ return m.Enabled
+ }
+ return false
+}
+
+func (m *WebsocketGetInfoResponse) GetAuthenticatedSupported() bool {
+ if m != nil {
+ return m.AuthenticatedSupported
+ }
+ return false
+}
+
+func (m *WebsocketGetInfoResponse) GetAuthenticated() bool {
+ if m != nil {
+ return m.Authenticated
+ }
+ return false
+}
+
+func (m *WebsocketGetInfoResponse) GetRunningUrl() string {
+ if m != nil {
+ return m.RunningUrl
+ }
+ return ""
+}
+
+func (m *WebsocketGetInfoResponse) GetProxyAddress() string {
+ if m != nil {
+ return m.ProxyAddress
+ }
+ return ""
+}
+
+type WebsocketSetEnabledRequest struct {
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Enable bool `protobuf:"varint,2,opt,name=enable,proto3" json:"enable,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *WebsocketSetEnabledRequest) Reset() { *m = WebsocketSetEnabledRequest{} }
+func (m *WebsocketSetEnabledRequest) String() string { return proto.CompactTextString(m) }
+func (*WebsocketSetEnabledRequest) ProtoMessage() {}
+func (*WebsocketSetEnabledRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_77a6da22d6a3feb1, []int{128}
+}
+
+func (m *WebsocketSetEnabledRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_WebsocketSetEnabledRequest.Unmarshal(m, b)
+}
+func (m *WebsocketSetEnabledRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_WebsocketSetEnabledRequest.Marshal(b, m, deterministic)
+}
+func (m *WebsocketSetEnabledRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_WebsocketSetEnabledRequest.Merge(m, src)
+}
+func (m *WebsocketSetEnabledRequest) XXX_Size() int {
+ return xxx_messageInfo_WebsocketSetEnabledRequest.Size(m)
+}
+func (m *WebsocketSetEnabledRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_WebsocketSetEnabledRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_WebsocketSetEnabledRequest proto.InternalMessageInfo
+
+func (m *WebsocketSetEnabledRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
+ }
+ return ""
+}
+
+func (m *WebsocketSetEnabledRequest) GetEnable() bool {
+ if m != nil {
+ return m.Enable
+ }
+ return false
+}
+
+type WebsocketGetSubscriptionsRequest struct {
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *WebsocketGetSubscriptionsRequest) Reset() { *m = WebsocketGetSubscriptionsRequest{} }
+func (m *WebsocketGetSubscriptionsRequest) String() string { return proto.CompactTextString(m) }
+func (*WebsocketGetSubscriptionsRequest) ProtoMessage() {}
+func (*WebsocketGetSubscriptionsRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_77a6da22d6a3feb1, []int{129}
+}
+
+func (m *WebsocketGetSubscriptionsRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_WebsocketGetSubscriptionsRequest.Unmarshal(m, b)
+}
+func (m *WebsocketGetSubscriptionsRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_WebsocketGetSubscriptionsRequest.Marshal(b, m, deterministic)
+}
+func (m *WebsocketGetSubscriptionsRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_WebsocketGetSubscriptionsRequest.Merge(m, src)
+}
+func (m *WebsocketGetSubscriptionsRequest) XXX_Size() int {
+ return xxx_messageInfo_WebsocketGetSubscriptionsRequest.Size(m)
+}
+func (m *WebsocketGetSubscriptionsRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_WebsocketGetSubscriptionsRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_WebsocketGetSubscriptionsRequest proto.InternalMessageInfo
+
+func (m *WebsocketGetSubscriptionsRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
+ }
+ return ""
+}
+
+type WebsocketSubscription struct {
+ Channel string `protobuf:"bytes,1,opt,name=channel,proto3" json:"channel,omitempty"`
+ Currency string `protobuf:"bytes,2,opt,name=currency,proto3" json:"currency,omitempty"`
+ Asset string `protobuf:"bytes,3,opt,name=asset,proto3" json:"asset,omitempty"`
+ Params string `protobuf:"bytes,4,opt,name=params,proto3" json:"params,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *WebsocketSubscription) Reset() { *m = WebsocketSubscription{} }
+func (m *WebsocketSubscription) String() string { return proto.CompactTextString(m) }
+func (*WebsocketSubscription) ProtoMessage() {}
+func (*WebsocketSubscription) Descriptor() ([]byte, []int) {
+ return fileDescriptor_77a6da22d6a3feb1, []int{130}
+}
+
+func (m *WebsocketSubscription) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_WebsocketSubscription.Unmarshal(m, b)
+}
+func (m *WebsocketSubscription) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_WebsocketSubscription.Marshal(b, m, deterministic)
+}
+func (m *WebsocketSubscription) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_WebsocketSubscription.Merge(m, src)
+}
+func (m *WebsocketSubscription) XXX_Size() int {
+ return xxx_messageInfo_WebsocketSubscription.Size(m)
+}
+func (m *WebsocketSubscription) XXX_DiscardUnknown() {
+ xxx_messageInfo_WebsocketSubscription.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_WebsocketSubscription proto.InternalMessageInfo
+
+func (m *WebsocketSubscription) GetChannel() string {
+ if m != nil {
+ return m.Channel
+ }
+ return ""
+}
+
+func (m *WebsocketSubscription) GetCurrency() string {
+ if m != nil {
+ return m.Currency
+ }
+ return ""
+}
+
+func (m *WebsocketSubscription) GetAsset() string {
+ if m != nil {
+ return m.Asset
+ }
+ return ""
+}
+
+func (m *WebsocketSubscription) GetParams() string {
+ if m != nil {
+ return m.Params
+ }
+ return ""
+}
+
+type WebsocketGetSubscriptionsResponse struct {
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Subscriptions []*WebsocketSubscription `protobuf:"bytes,2,rep,name=subscriptions,proto3" json:"subscriptions,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *WebsocketGetSubscriptionsResponse) Reset() { *m = WebsocketGetSubscriptionsResponse{} }
+func (m *WebsocketGetSubscriptionsResponse) String() string { return proto.CompactTextString(m) }
+func (*WebsocketGetSubscriptionsResponse) ProtoMessage() {}
+func (*WebsocketGetSubscriptionsResponse) Descriptor() ([]byte, []int) {
+ return fileDescriptor_77a6da22d6a3feb1, []int{131}
+}
+
+func (m *WebsocketGetSubscriptionsResponse) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_WebsocketGetSubscriptionsResponse.Unmarshal(m, b)
+}
+func (m *WebsocketGetSubscriptionsResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_WebsocketGetSubscriptionsResponse.Marshal(b, m, deterministic)
+}
+func (m *WebsocketGetSubscriptionsResponse) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_WebsocketGetSubscriptionsResponse.Merge(m, src)
+}
+func (m *WebsocketGetSubscriptionsResponse) XXX_Size() int {
+ return xxx_messageInfo_WebsocketGetSubscriptionsResponse.Size(m)
+}
+func (m *WebsocketGetSubscriptionsResponse) XXX_DiscardUnknown() {
+ xxx_messageInfo_WebsocketGetSubscriptionsResponse.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_WebsocketGetSubscriptionsResponse proto.InternalMessageInfo
+
+func (m *WebsocketGetSubscriptionsResponse) GetExchange() string {
+ if m != nil {
+ return m.Exchange
+ }
+ return ""
+}
+
+func (m *WebsocketGetSubscriptionsResponse) GetSubscriptions() []*WebsocketSubscription {
+ if m != nil {
+ return m.Subscriptions
}
return nil
}
-var File_rpc_proto protoreflect.FileDescriptor
-
-var file_rpc_proto_rawDesc = []byte{
- 0x0a, 0x09, 0x72, 0x70, 0x63, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x67, 0x63, 0x74,
- 0x72, 0x70, 0x63, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x61, 0x70, 0x69, 0x2f,
- 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74,
- 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
- 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f,
- 0x74, 0x6f, 0x22, 0x10, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71,
- 0x75, 0x65, 0x73, 0x74, 0x22, 0xb4, 0x04, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f,
- 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x70, 0x74, 0x69,
- 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x70, 0x74, 0x69, 0x6d, 0x65,
- 0x12, 0x2f, 0x0a, 0x13, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x65, 0x78,
- 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x61,
- 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65,
- 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x65, 0x78, 0x63,
- 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x65, 0x6e,
- 0x61, 0x62, 0x6c, 0x65, 0x64, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x34,
- 0x0a, 0x16, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x66, 0x6f, 0x72, 0x65, 0x78, 0x5f,
- 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14,
- 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x46, 0x6f, 0x72, 0x65, 0x78, 0x50, 0x72, 0x6f, 0x76,
- 0x69, 0x64, 0x65, 0x72, 0x12, 0x32, 0x0a, 0x15, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f,
- 0x66, 0x69, 0x61, 0x74, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x05, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x13, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x46, 0x69, 0x61, 0x74,
- 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x57, 0x0a, 0x10, 0x73, 0x75, 0x62, 0x73,
- 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x06, 0x20, 0x03,
- 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x49,
- 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x75, 0x62, 0x73,
- 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
- 0x52, 0x0f, 0x73, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x75,
- 0x73, 0x12, 0x4e, 0x0a, 0x0d, 0x72, 0x70, 0x63, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e,
- 0x74, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70,
- 0x63, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
- 0x65, 0x2e, 0x52, 0x70, 0x63, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x45, 0x6e,
- 0x74, 0x72, 0x79, 0x52, 0x0c, 0x72, 0x70, 0x63, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74,
- 0x73, 0x1a, 0x42, 0x0a, 0x14, 0x53, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x53, 0x74,
- 0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76,
- 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
- 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x54, 0x0a, 0x11, 0x52, 0x70, 0x63, 0x45, 0x6e, 0x64, 0x70,
- 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
- 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x29, 0x0a, 0x05,
- 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x67, 0x63,
- 0x74, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74,
- 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x21, 0x0a, 0x1f, 0x47,
- 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52,
- 0x65, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x4e,
- 0x0a, 0x14, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52,
- 0x65, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65,
- 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64,
- 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20,
- 0x01, 0x28, 0x08, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x22, 0x86,
- 0x02, 0x0a, 0x20, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74,
- 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
- 0x6e, 0x73, 0x65, 0x12, 0x7a, 0x0a, 0x16, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20,
- 0x03, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74,
- 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6c,
- 0x61, 0x79, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x43, 0x6f,
- 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x79,
- 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x15, 0x63, 0x6f, 0x6d, 0x6d, 0x75, 0x6e,
- 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x1a,
- 0x66, 0x0a, 0x1a, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e,
- 0x52, 0x65, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a,
- 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12,
- 0x32, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c,
- 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63,
- 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x52, 0x05, 0x76, 0x61,
- 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x37, 0x0a, 0x17, 0x47, 0x65, 0x6e, 0x65, 0x72,
- 0x69, 0x63, 0x53, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65,
- 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
- 0x22, 0x1a, 0x0a, 0x18, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x75, 0x62, 0x73, 0x79,
- 0x73, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x0a, 0x14,
- 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x52, 0x65, 0x71,
- 0x75, 0x65, 0x73, 0x74, 0x22, 0xbe, 0x01, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x53, 0x75, 0x73, 0x62,
- 0x73, 0x79, 0x74, 0x65, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x60,
- 0x0a, 0x11, 0x73, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x5f, 0x73, 0x74, 0x61,
- 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x67, 0x63, 0x74, 0x72,
- 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x73, 0x62, 0x73, 0x79, 0x74, 0x65, 0x6d, 0x73,
- 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74,
- 0x65, 0x6d, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x10,
- 0x73, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
- 0x1a, 0x43, 0x0a, 0x15, 0x53, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x53, 0x74,
- 0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76,
- 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
- 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x18, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x52, 0x50, 0x43, 0x45,
- 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22,
- 0x4e, 0x0a, 0x0b, 0x52, 0x50, 0x43, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x18,
- 0x0a, 0x07, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52,
- 0x07, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x6c, 0x69, 0x73, 0x74,
- 0x65, 0x6e, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x0d, 0x6c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22,
- 0xba, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x52, 0x50, 0x43, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69,
- 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4c, 0x0a, 0x09, 0x65,
- 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e,
- 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x50, 0x43, 0x45, 0x6e,
- 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e,
- 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09,
- 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x1a, 0x51, 0x0a, 0x0e, 0x45, 0x6e, 0x64,
- 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b,
- 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x29, 0x0a,
- 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x67,
- 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x50, 0x43, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e,
- 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x38, 0x0a, 0x1a,
- 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e,
- 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78,
- 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78,
- 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x22, 0x1d, 0x0a, 0x1b, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69,
- 0x63, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x73,
- 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x2f, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68,
- 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07,
- 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65,
- 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0x34, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63,
- 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c,
- 0x0a, 0x09, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x09, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x22, 0x32, 0x0a, 0x15,
- 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x54, 0x50, 0x52, 0x65,
- 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x74, 0x70, 0x5f, 0x63, 0x6f, 0x64,
- 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x74, 0x70, 0x43, 0x6f, 0x64, 0x65,
- 0x22, 0x18, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f,
- 0x54, 0x50, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xa2, 0x01, 0x0a, 0x17, 0x47,
- 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x54, 0x50, 0x73, 0x52, 0x65,
- 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x09, 0x6f, 0x74, 0x70, 0x5f, 0x63, 0x6f,
- 0x64, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x63, 0x74, 0x72,
- 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x54,
- 0x50, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4f, 0x74, 0x70, 0x43, 0x6f,
- 0x64, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x08, 0x6f, 0x74, 0x70, 0x43, 0x6f, 0x64,
- 0x65, 0x73, 0x1a, 0x3b, 0x0a, 0x0d, 0x4f, 0x74, 0x70, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x45, 0x6e,
- 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22,
- 0x34, 0x0a, 0x16, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e,
- 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63,
- 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63,
- 0x68, 0x61, 0x6e, 0x67, 0x65, 0x22, 0x5e, 0x0a, 0x0e, 0x50, 0x61, 0x69, 0x72, 0x73, 0x53, 0x75,
- 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x76, 0x61, 0x69, 0x6c,
- 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x70, 0x61, 0x69, 0x72, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x0e, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x50, 0x61, 0x69, 0x72, 0x73,
- 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x5f, 0x70, 0x61, 0x69, 0x72,
- 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64,
- 0x50, 0x61, 0x69, 0x72, 0x73, 0x22, 0x82, 0x04, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63,
- 0x68, 0x61, 0x6e, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
- 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12,
- 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x62, 0x6f, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08,
- 0x52, 0x07, 0x76, 0x65, 0x72, 0x62, 0x6f, 0x73, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x75, 0x73, 0x69,
- 0x6e, 0x67, 0x5f, 0x73, 0x61, 0x6e, 0x64, 0x62, 0x6f, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08,
- 0x52, 0x0c, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x53, 0x61, 0x6e, 0x64, 0x62, 0x6f, 0x78, 0x12, 0x21,
- 0x0a, 0x0c, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x05,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x68, 0x74, 0x74, 0x70, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75,
- 0x74, 0x12, 0x25, 0x0a, 0x0e, 0x68, 0x74, 0x74, 0x70, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x61, 0x67,
- 0x65, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x68, 0x74, 0x74, 0x70, 0x55,
- 0x73, 0x65, 0x72, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x68, 0x74, 0x74, 0x70,
- 0x5f, 0x70, 0x72, 0x6f, 0x78, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x68, 0x74,
- 0x74, 0x70, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x62, 0x61, 0x73, 0x65, 0x5f,
- 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x0e, 0x62, 0x61, 0x73, 0x65, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x69, 0x65, 0x73,
- 0x12, 0x5f, 0x0a, 0x10, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x73,
- 0x73, 0x65, 0x74, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x67, 0x63, 0x74,
- 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x49,
- 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x75, 0x70, 0x70,
- 0x6f, 0x72, 0x74, 0x65, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79,
- 0x52, 0x0f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74,
- 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74,
- 0x65, 0x64, 0x5f, 0x61, 0x70, 0x69, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x61, 0x75,
- 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x64, 0x41, 0x70, 0x69, 0x1a, 0x5a,
- 0x0a, 0x14, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74,
- 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75,
- 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63,
- 0x2e, 0x50, 0x61, 0x69, 0x72, 0x73, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x52,
- 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x77, 0x0a, 0x10, 0x47, 0x65,
- 0x74, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a,
- 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61,
- 0x69, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70,
- 0x63, 0x2e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x61, 0x69, 0x72, 0x52, 0x04,
- 0x70, 0x61, 0x69, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x79,
- 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x54,
- 0x79, 0x70, 0x65, 0x22, 0x56, 0x0a, 0x0c, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x50,
- 0x61, 0x69, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x64, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x65, 0x72,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x64, 0x65, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x65,
- 0x72, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x04, 0x62, 0x61, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x18, 0x03,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x22, 0x95, 0x02, 0x0a, 0x0e,
- 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x28,
- 0x0a, 0x04, 0x70, 0x61, 0x69, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67,
- 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x61,
- 0x69, 0x72, 0x52, 0x04, 0x70, 0x61, 0x69, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x6c, 0x61, 0x73, 0x74,
- 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b,
- 0x6c, 0x61, 0x73, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x63,
- 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x70, 0x61, 0x69, 0x72, 0x18, 0x03, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x61, 0x69, 0x72,
- 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x61, 0x73, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x04,
- 0x6c, 0x61, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x69, 0x67, 0x68, 0x18, 0x05, 0x20, 0x01,
- 0x28, 0x01, 0x52, 0x04, 0x68, 0x69, 0x67, 0x68, 0x12, 0x10, 0x0a, 0x03, 0x6c, 0x6f, 0x77, 0x18,
- 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x03, 0x6c, 0x6f, 0x77, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x69,
- 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x01, 0x52, 0x03, 0x62, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03,
- 0x61, 0x73, 0x6b, 0x18, 0x08, 0x20, 0x01, 0x28, 0x01, 0x52, 0x03, 0x61, 0x73, 0x6b, 0x12, 0x16,
- 0x0a, 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x01, 0x52, 0x06,
- 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x72, 0x69, 0x63, 0x65, 0x5f,
- 0x61, 0x74, 0x68, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x70, 0x72, 0x69, 0x63, 0x65,
- 0x41, 0x74, 0x68, 0x22, 0x13, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72,
- 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x57, 0x0a, 0x07, 0x54, 0x69, 0x63, 0x6b,
- 0x65, 0x72, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12,
- 0x30, 0x0a, 0x07, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b,
- 0x32, 0x16, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72,
- 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x07, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x72,
- 0x73, 0x22, 0x3f, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x73, 0x52,
- 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x29, 0x0a, 0x07, 0x74, 0x69, 0x63, 0x6b, 0x65,
- 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70,
- 0x63, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x73, 0x52, 0x07, 0x74, 0x69, 0x63, 0x6b, 0x65,
- 0x72, 0x73, 0x22, 0x7a, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f,
- 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63,
- 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63,
- 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x69, 0x72, 0x18, 0x02, 0x20,
- 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x75, 0x72,
- 0x72, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x61, 0x69, 0x72, 0x52, 0x04, 0x70, 0x61, 0x69, 0x72, 0x12,
- 0x1d, 0x0a, 0x0a, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x22, 0x4d,
- 0x0a, 0x0d, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x49, 0x74, 0x65, 0x6d, 0x12,
- 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52,
- 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x12, 0x0e, 0x0a,
- 0x02, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x22, 0xfa, 0x01,
- 0x0a, 0x11, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f,
- 0x6e, 0x73, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x69, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x75, 0x72, 0x72, 0x65,
- 0x6e, 0x63, 0x79, 0x50, 0x61, 0x69, 0x72, 0x52, 0x04, 0x70, 0x61, 0x69, 0x72, 0x12, 0x23, 0x0a,
- 0x0d, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x70, 0x61, 0x69, 0x72, 0x18, 0x02,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x61,
- 0x69, 0x72, 0x12, 0x29, 0x0a, 0x04, 0x62, 0x69, 0x64, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b,
- 0x32, 0x15, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62,
- 0x6f, 0x6f, 0x6b, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x04, 0x62, 0x69, 0x64, 0x73, 0x12, 0x29, 0x0a,
- 0x04, 0x61, 0x73, 0x6b, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x67, 0x63,
- 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x49, 0x74,
- 0x65, 0x6d, 0x52, 0x04, 0x61, 0x73, 0x6b, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6c, 0x61, 0x73, 0x74,
- 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b,
- 0x6c, 0x61, 0x73, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x61,
- 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x22, 0x16, 0x0a, 0x14, 0x47, 0x65,
- 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65,
- 0x73, 0x74, 0x22, 0x63, 0x0a, 0x0a, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x73,
- 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x39, 0x0a, 0x0a,
- 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b,
- 0x32, 0x19, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62,
- 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x6f, 0x72, 0x64,
- 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x22, 0x4b, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x4f, 0x72,
- 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
- 0x12, 0x32, 0x0a, 0x0a, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x18, 0x01,
- 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x72,
- 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x52, 0x0a, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62,
- 0x6f, 0x6f, 0x6b, 0x73, 0x22, 0x33, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75,
- 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a,
- 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x22, 0x56, 0x0a, 0x07, 0x41, 0x63, 0x63,
- 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x02, 0x69, 0x64, 0x12, 0x3b, 0x0a, 0x0a, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x69,
- 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70,
- 0x63, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63,
- 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x69, 0x65,
- 0x73, 0x22, 0x66, 0x0a, 0x13, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x75, 0x72, 0x72,
- 0x65, 0x6e, 0x63, 0x79, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x75, 0x72, 0x72,
- 0x65, 0x6e, 0x63, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x75, 0x72, 0x72,
- 0x65, 0x6e, 0x63, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x76, 0x61,
- 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0a, 0x74, 0x6f, 0x74, 0x61, 0x6c,
- 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x6c, 0x64, 0x18, 0x03, 0x20,
- 0x01, 0x28, 0x01, 0x52, 0x04, 0x68, 0x6f, 0x6c, 0x64, 0x22, 0x61, 0x0a, 0x16, 0x47, 0x65, 0x74,
- 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f,
- 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12,
- 0x2b, 0x0a, 0x08, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28,
- 0x0b, 0x32, 0x0f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75,
- 0x6e, 0x74, 0x52, 0x08, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x22, 0x12, 0x0a, 0x10,
- 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
- 0x22, 0x27, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x73,
- 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20,
- 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0x85, 0x01, 0x0a, 0x10, 0x50, 0x6f,
- 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18,
- 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6f, 0x69, 0x6e,
- 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x69,
- 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
- 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63,
- 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e,
- 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63,
- 0x65, 0x22, 0x15, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69,
- 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x4e, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x50,
- 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
- 0x12, 0x36, 0x0a, 0x09, 0x70, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x18, 0x01, 0x20,
- 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x6f, 0x72,
- 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x09, 0x70,
- 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x22, 0x1c, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x50,
- 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52,
- 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x6e, 0x0a, 0x04, 0x43, 0x6f, 0x69, 0x6e, 0x12, 0x12,
- 0x0a, 0x04, 0x63, 0x6f, 0x69, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f,
- 0x69, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20,
- 0x01, 0x28, 0x01, 0x52, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x18, 0x0a, 0x07,
- 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61,
- 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e,
- 0x74, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0a, 0x70, 0x65, 0x72, 0x63,
- 0x65, 0x6e, 0x74, 0x61, 0x67, 0x65, 0x22, 0x68, 0x0a, 0x12, 0x4f, 0x66, 0x66, 0x6c, 0x69, 0x6e,
- 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x18, 0x0a, 0x07,
- 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61,
- 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63,
- 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65,
- 0x12, 0x1e, 0x0a, 0x0a, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x61, 0x67, 0x65, 0x18, 0x03,
- 0x20, 0x01, 0x28, 0x01, 0x52, 0x0a, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x61, 0x67, 0x65,
- 0x22, 0x4d, 0x0a, 0x11, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x75,
- 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x07, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12,
- 0x1e, 0x0a, 0x0a, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20,
- 0x01, 0x28, 0x01, 0x52, 0x0a, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x61, 0x67, 0x65, 0x22,
- 0x48, 0x0a, 0x0c, 0x4f, 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x12,
- 0x38, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03,
- 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x66, 0x66, 0x6c,
- 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x09,
- 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x22, 0x98, 0x01, 0x0a, 0x0b, 0x4f, 0x6e,
- 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x12, 0x34, 0x0a, 0x05, 0x63, 0x6f, 0x69,
- 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70,
- 0x63, 0x2e, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x2e, 0x43, 0x6f,
- 0x69, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x05, 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x1a,
- 0x53, 0x0a, 0x0a, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a,
- 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12,
- 0x2f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19,
- 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f,
- 0x69, 0x6e, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
- 0x3a, 0x02, 0x38, 0x01, 0x22, 0xcb, 0x04, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x72, 0x74,
- 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70,
- 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x0b, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x74, 0x6f, 0x74,
- 0x61, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x67, 0x63, 0x74, 0x72,
- 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x69, 0x6e, 0x54, 0x6f, 0x74,
- 0x61, 0x6c, 0x73, 0x12, 0x31, 0x0a, 0x0d, 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x5f, 0x6f, 0x66, 0x66,
- 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x67, 0x63, 0x74,
- 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x0c, 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x4f,
- 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x70, 0x0a, 0x15, 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x5f,
- 0x6f, 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x18,
- 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47,
- 0x65, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x53, 0x75, 0x6d, 0x6d, 0x61,
- 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x73,
- 0x4f, 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x45, 0x6e,
- 0x74, 0x72, 0x79, 0x52, 0x13, 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x4f, 0x66, 0x66, 0x6c, 0x69, 0x6e,
- 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x2f, 0x0a, 0x0c, 0x63, 0x6f, 0x69, 0x6e,
- 0x73, 0x5f, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c,
- 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x69, 0x6e, 0x52, 0x0b, 0x63, 0x6f,
- 0x69, 0x6e, 0x73, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x12, 0x6d, 0x0a, 0x14, 0x63, 0x6f, 0x69,
- 0x6e, 0x73, 0x5f, 0x6f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x5f, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72,
- 0x79, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63,
- 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x53, 0x75, 0x6d,
- 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x43, 0x6f, 0x69,
- 0x6e, 0x73, 0x4f, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x45,
- 0x6e, 0x74, 0x72, 0x79, 0x52, 0x12, 0x63, 0x6f, 0x69, 0x6e, 0x73, 0x4f, 0x6e, 0x6c, 0x69, 0x6e,
- 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x1a, 0x5c, 0x0a, 0x18, 0x43, 0x6f, 0x69, 0x6e,
- 0x73, 0x4f, 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x45,
- 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2a, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18,
- 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f,
- 0x66, 0x66, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c,
- 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x5a, 0x0a, 0x17, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x4f,
- 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x45, 0x6e, 0x74, 0x72,
- 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03,
- 0x6b, 0x65, 0x79, 0x12, 0x29, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01,
- 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x6e, 0x6c, 0x69,
- 0x6e, 0x65, 0x43, 0x6f, 0x69, 0x6e, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02,
- 0x38, 0x01, 0x22, 0xe3, 0x01, 0x0a, 0x1a, 0x41, 0x64, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f,
- 0x6c, 0x69, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
- 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x63,
- 0x6f, 0x69, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
- 0x63, 0x6f, 0x69, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63,
- 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64,
- 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x61,
- 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x07, 0x62, 0x61, 0x6c,
- 0x61, 0x6e, 0x63, 0x65, 0x12, 0x2f, 0x0a, 0x13, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65,
- 0x64, 0x5f, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x12, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x45, 0x78, 0x63, 0x68,
- 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6c, 0x64, 0x5f, 0x73, 0x74,
- 0x6f, 0x72, 0x61, 0x67, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x63, 0x6f, 0x6c,
- 0x64, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x22, 0x1d, 0x0a, 0x1b, 0x41, 0x64, 0x64, 0x50,
- 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52,
- 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x78, 0x0a, 0x1d, 0x52, 0x65, 0x6d, 0x6f, 0x76,
- 0x65, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
- 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72,
- 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65,
- 0x73, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6f, 0x69, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18,
- 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6f, 0x69, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12,
- 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
- 0x6e, 0x22, 0x20, 0x0a, 0x1e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x66,
- 0x6f, 0x6c, 0x69, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
- 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x65, 0x78, 0x50,
- 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22,
- 0xed, 0x01, 0x0a, 0x0d, 0x46, 0x6f, 0x72, 0x65, 0x78, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65,
- 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12,
- 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x62, 0x6f, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08,
- 0x52, 0x07, 0x76, 0x65, 0x72, 0x62, 0x6f, 0x73, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x72, 0x65, 0x73,
- 0x74, 0x5f, 0x70, 0x6f, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x18,
- 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x72, 0x65, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x6c, 0x69,
- 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x17, 0x0a, 0x07, 0x61, 0x70, 0x69, 0x5f, 0x6b,
- 0x65, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x70, 0x69, 0x4b, 0x65, 0x79,
- 0x12, 0x22, 0x0a, 0x0d, 0x61, 0x70, 0x69, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x6c, 0x65, 0x76, 0x65,
- 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x61, 0x70, 0x69, 0x4b, 0x65, 0x79, 0x4c,
- 0x65, 0x76, 0x65, 0x6c, 0x12, 0x29, 0x0a, 0x10, 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x5f,
- 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f,
- 0x70, 0x72, 0x69, 0x6d, 0x61, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x22,
- 0x5b, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x65, 0x78, 0x50, 0x72, 0x6f, 0x76, 0x69,
- 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x0f,
- 0x66, 0x6f, 0x72, 0x65, 0x78, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18,
- 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x46,
- 0x6f, 0x72, 0x65, 0x78, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x0e, 0x66, 0x6f,
- 0x72, 0x65, 0x78, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x22, 0x16, 0x0a, 0x14,
- 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x65, 0x78, 0x52, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71,
- 0x75, 0x65, 0x73, 0x74, 0x22, 0x71, 0x0a, 0x14, 0x46, 0x6f, 0x72, 0x65, 0x78, 0x52, 0x61, 0x74,
- 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04,
- 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x72, 0x6f, 0x6d,
- 0x12, 0x0e, 0x0a, 0x02, 0x74, 0x6f, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x74, 0x6f,
- 0x12, 0x12, 0x0a, 0x04, 0x72, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x04,
- 0x72, 0x61, 0x74, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x65, 0x5f,
- 0x72, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, 0x69, 0x6e, 0x76, 0x65,
- 0x72, 0x73, 0x65, 0x52, 0x61, 0x74, 0x65, 0x22, 0x56, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x46, 0x6f,
- 0x72, 0x65, 0x78, 0x52, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
- 0x12, 0x3d, 0x0a, 0x0b, 0x66, 0x6f, 0x72, 0x65, 0x78, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x73, 0x18,
- 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x46,
- 0x6f, 0x72, 0x65, 0x78, 0x52, 0x61, 0x74, 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73,
- 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x66, 0x6f, 0x72, 0x65, 0x78, 0x52, 0x61, 0x74, 0x65, 0x73, 0x22,
- 0xaf, 0x03, 0x0a, 0x0c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73,
- 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x0e, 0x0a, 0x02,
- 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x23, 0x0a, 0x0d,
- 0x62, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x03, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x0c, 0x62, 0x61, 0x73, 0x65, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63,
- 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x71, 0x75, 0x6f, 0x74, 0x65, 0x5f, 0x63, 0x75, 0x72, 0x72, 0x65,
- 0x6e, 0x63, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x71, 0x75, 0x6f, 0x74, 0x65,
- 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x73, 0x73, 0x65,
- 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x73,
- 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x72, 0x64, 0x65, 0x72,
- 0x5f, 0x73, 0x69, 0x64, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x72, 0x64,
- 0x65, 0x72, 0x53, 0x69, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f,
- 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x72, 0x64, 0x65,
- 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f,
- 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x63, 0x72,
- 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74,
- 0x61, 0x74, 0x75, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74,
- 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28,
- 0x01, 0x52, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75,
- 0x6e, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x01, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74,
- 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x18,
- 0x0c, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0a, 0x6f, 0x70, 0x65, 0x6e, 0x56, 0x6f, 0x6c, 0x75, 0x6d,
- 0x65, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x65, 0x65, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x01, 0x52, 0x03,
- 0x66, 0x65, 0x65, 0x12, 0x2c, 0x0a, 0x06, 0x74, 0x72, 0x61, 0x64, 0x65, 0x73, 0x18, 0x0e, 0x20,
- 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61,
- 0x64, 0x65, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x06, 0x74, 0x72, 0x61, 0x64, 0x65,
- 0x73, 0x22, 0xdd, 0x01, 0x0a, 0x0c, 0x54, 0x72, 0x61, 0x64, 0x65, 0x48, 0x69, 0x73, 0x74, 0x6f,
- 0x72, 0x79, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74,
- 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74,
- 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65,
- 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x12, 0x16, 0x0a,
- 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x06, 0x61,
- 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67,
- 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67,
- 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18,
- 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65,
- 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x73, 0x69, 0x64, 0x65, 0x18, 0x07,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x53, 0x69, 0x64, 0x65, 0x12,
- 0x10, 0x0a, 0x03, 0x66, 0x65, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x01, 0x52, 0x03, 0x66, 0x65,
- 0x65, 0x22, 0x77, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65,
- 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67,
- 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67,
- 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18,
- 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65,
- 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x69, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14,
- 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79,
- 0x50, 0x61, 0x69, 0x72, 0x52, 0x04, 0x70, 0x61, 0x69, 0x72, 0x22, 0x41, 0x0a, 0x11, 0x47, 0x65,
- 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
- 0x2c, 0x0a, 0x06, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
- 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x44, 0x65,
- 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x06, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x22, 0x48, 0x0a,
- 0x0f, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
- 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x19, 0x0a, 0x08,
- 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
- 0x6f, 0x72, 0x64, 0x65, 0x72, 0x49, 0x64, 0x22, 0xd8, 0x01, 0x0a, 0x12, 0x53, 0x75, 0x62, 0x6d,
- 0x69, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a,
- 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61,
- 0x69, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70,
- 0x63, 0x2e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x61, 0x69, 0x72, 0x52, 0x04,
- 0x70, 0x61, 0x69, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x04, 0x73, 0x69, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x72, 0x64, 0x65,
- 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x72,
- 0x64, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e,
- 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12,
- 0x14, 0x0a, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05,
- 0x70, 0x72, 0x69, 0x63, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f,
- 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
- 0x49, 0x64, 0x22, 0x53, 0x0a, 0x13, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4f, 0x72, 0x64, 0x65,
- 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x72, 0x64,
- 0x65, 0x72, 0x5f, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52,
- 0x0b, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x50, 0x6c, 0x61, 0x63, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x08,
- 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
- 0x6f, 0x72, 0x64, 0x65, 0x72, 0x49, 0x64, 0x22, 0x88, 0x01, 0x0a, 0x14, 0x53, 0x69, 0x6d, 0x75,
- 0x6c, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
- 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x28, 0x0a, 0x04,
- 0x70, 0x61, 0x69, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x63, 0x74,
- 0x72, 0x70, 0x63, 0x2e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x61, 0x69, 0x72,
- 0x52, 0x04, 0x70, 0x61, 0x69, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74,
- 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x12,
- 0x0a, 0x04, 0x73, 0x69, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x69,
- 0x64, 0x65, 0x22, 0xf2, 0x01, 0x0a, 0x15, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x4f,
- 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2d, 0x0a, 0x06,
- 0x6f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x67,
- 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x49,
- 0x74, 0x65, 0x6d, 0x52, 0x06, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x61,
- 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x06, 0x61, 0x6d, 0x6f,
- 0x75, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x69, 0x6e, 0x69, 0x6d, 0x75, 0x6d, 0x5f, 0x70,
- 0x72, 0x69, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x6d, 0x69, 0x6e, 0x69,
- 0x6d, 0x75, 0x6d, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x61, 0x78, 0x69,
- 0x6d, 0x75, 0x6d, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52,
- 0x0c, 0x6d, 0x61, 0x78, 0x69, 0x6d, 0x75, 0x6d, 0x50, 0x72, 0x69, 0x63, 0x65, 0x12, 0x30, 0x0a,
- 0x14, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x61, 0x67, 0x65, 0x5f, 0x67, 0x61, 0x69, 0x6e,
- 0x5f, 0x6c, 0x6f, 0x73, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x52, 0x12, 0x70, 0x65, 0x72,
- 0x63, 0x65, 0x6e, 0x74, 0x61, 0x67, 0x65, 0x47, 0x61, 0x69, 0x6e, 0x4c, 0x6f, 0x73, 0x73, 0x12,
- 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x8f, 0x01, 0x0a, 0x10, 0x57, 0x68, 0x61, 0x6c,
- 0x65, 0x42, 0x6f, 0x6d, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08,
- 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
- 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x69, 0x72,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e,
- 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x61, 0x69, 0x72, 0x52, 0x04, 0x70, 0x61,
- 0x69, 0x72, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x74, 0x61, 0x72, 0x67,
- 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, 0x70, 0x72, 0x69, 0x63, 0x65, 0x54,
- 0x61, 0x72, 0x67, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x64, 0x65, 0x18, 0x04, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x69, 0x64, 0x65, 0x22, 0xee, 0x01, 0x0a, 0x12, 0x43, 0x61,
- 0x6e, 0x63, 0x65, 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
- 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1d, 0x0a, 0x0a,
- 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6f,
- 0x72, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f,
- 0x72, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x69, 0x72, 0x18, 0x04,
- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x75,
- 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x61, 0x69, 0x72, 0x52, 0x04, 0x70, 0x61, 0x69, 0x72,
- 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12,
- 0x25, 0x0a, 0x0e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73,
- 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x41,
- 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x64, 0x65, 0x18, 0x07,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x69, 0x64, 0x65, 0x22, 0x15, 0x0a, 0x13, 0x43, 0x61,
- 0x6e, 0x63, 0x65, 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
- 0x65, 0x22, 0x34, 0x0a, 0x16, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x6c, 0x6c, 0x4f, 0x72,
- 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65,
- 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65,
- 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x22, 0x9c, 0x02, 0x0a, 0x17, 0x43, 0x61, 0x6e, 0x63,
- 0x65, 0x6c, 0x41, 0x6c, 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
- 0x6e, 0x73, 0x65, 0x12, 0x3e, 0x0a, 0x06, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20,
- 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6e,
- 0x63, 0x65, 0x6c, 0x41, 0x6c, 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70,
- 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x06, 0x6f, 0x72, 0x64,
- 0x65, 0x72, 0x73, 0x1a, 0xc0, 0x01, 0x0a, 0x06, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x12, 0x1a,
- 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x5a, 0x0a, 0x0c, 0x6f, 0x72,
- 0x64, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b,
- 0x32, 0x37, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c,
- 0x41, 0x6c, 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
- 0x65, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x53, 0x74,
- 0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0b, 0x6f, 0x72, 0x64, 0x65, 0x72,
- 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x1a, 0x3e, 0x0a, 0x10, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x53,
- 0x74, 0x61, 0x74, 0x75, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
- 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05,
- 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c,
- 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x12, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65,
- 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xbe, 0x01, 0x0a, 0x0f, 0x43,
- 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x1c,
- 0x0a, 0x09, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x09, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05,
- 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x70, 0x72, 0x69,
- 0x63, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x62, 0x69, 0x64, 0x73,
- 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x42, 0x69, 0x64,
- 0x73, 0x12, 0x2d, 0x0a, 0x13, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x62, 0x69, 0x64, 0x73, 0x5f,
- 0x61, 0x6e, 0x64, 0x5f, 0x61, 0x73, 0x6b, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10,
- 0x63, 0x68, 0x65, 0x63, 0x6b, 0x42, 0x69, 0x64, 0x73, 0x41, 0x6e, 0x64, 0x41, 0x73, 0x6b, 0x73,
- 0x12, 0x29, 0x0a, 0x10, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x5f, 0x61, 0x6d,
- 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0f, 0x6f, 0x72, 0x64, 0x65,
- 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xf5, 0x01, 0x0a, 0x11,
- 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
- 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69,
- 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x12, 0x0a,
- 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x69, 0x74, 0x65,
- 0x6d, 0x12, 0x42, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70,
- 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x63,
- 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61,
- 0x72, 0x61, 0x6d, 0x73, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x50,
- 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x69, 0x72, 0x18, 0x05, 0x20,
- 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x75, 0x72,
- 0x72, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x61, 0x69, 0x72, 0x52, 0x04, 0x70, 0x61, 0x69, 0x72, 0x12,
- 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x65, 0x63, 0x75,
- 0x74, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x65, 0x78, 0x65, 0x63, 0x75,
- 0x74, 0x65, 0x64, 0x22, 0xe6, 0x01, 0x0a, 0x0f, 0x41, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74,
- 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61,
- 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61,
- 0x6e, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x12, 0x42, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x64, 0x69,
- 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28,
- 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x64, 0x69,
- 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x64,
- 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x12, 0x28, 0x0a, 0x04, 0x70,
- 0x61, 0x69, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72,
- 0x70, 0x63, 0x2e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x61, 0x69, 0x72, 0x52,
- 0x04, 0x70, 0x61, 0x69, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74,
- 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74,
- 0x54, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x22, 0x0a, 0x10,
- 0x41, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
- 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64,
- 0x22, 0x24, 0x0a, 0x12, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52,
- 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x22, 0x15, 0x0a, 0x13, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65,
- 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x46, 0x0a,
- 0x28, 0x47, 0x65, 0x74, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e,
- 0x63, 0x79, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
- 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63,
- 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63,
- 0x68, 0x61, 0x6e, 0x67, 0x65, 0x22, 0xc9, 0x01, 0x0a, 0x29, 0x47, 0x65, 0x74, 0x43, 0x72, 0x79,
- 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x44, 0x65, 0x70, 0x6f, 0x73,
- 0x69, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f,
- 0x6e, 0x73, 0x65, 0x12, 0x5e, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73,
- 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e,
- 0x47, 0x65, 0x74, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63,
- 0x79, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65,
- 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
- 0x73, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73,
- 0x73, 0x65, 0x73, 0x1a, 0x3c, 0x0a, 0x0e, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73,
- 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38,
- 0x01, 0x22, 0x6c, 0x0a, 0x26, 0x47, 0x65, 0x74, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x63, 0x75,
- 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x41, 0x64, 0x64,
- 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65,
- 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65,
- 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x26, 0x0a, 0x0e, 0x63, 0x72, 0x79, 0x70, 0x74,
- 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x0e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x22,
- 0x43, 0x0a, 0x27, 0x47, 0x65, 0x74, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72,
- 0x65, 0x6e, 0x63, 0x79, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65,
- 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64,
- 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64,
- 0x72, 0x65, 0x73, 0x73, 0x22, 0xaf, 0x01, 0x0a, 0x13, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61,
- 0x77, 0x46, 0x69, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08,
- 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
- 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x75, 0x72, 0x72,
- 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x75, 0x72, 0x72,
- 0x65, 0x6e, 0x63, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03,
- 0x20, 0x01, 0x28, 0x01, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x20, 0x0a, 0x0b,
- 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x26,
- 0x0a, 0x0f, 0x62, 0x61, 0x6e, 0x6b, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69,
- 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x62, 0x61, 0x6e, 0x6b, 0x41, 0x63, 0x63,
- 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x22, 0xd6, 0x01, 0x0a, 0x15, 0x57, 0x69, 0x74, 0x68, 0x64,
- 0x72, 0x61, 0x77, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
- 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x18, 0x0a, 0x07,
- 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61,
- 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73,
- 0x73, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x64, 0x64,
- 0x72, 0x65, 0x73, 0x73, 0x54, 0x61, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65,
- 0x6e, 0x63, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65,
- 0x6e, 0x63, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20,
- 0x01, 0x28, 0x01, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x66,
- 0x65, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x03, 0x66, 0x65, 0x65, 0x12, 0x20, 0x0a,
- 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22,
- 0x3a, 0x0a, 0x10, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f,
- 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x2c, 0x0a, 0x1a, 0x57,
- 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x79,
- 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x54, 0x0a, 0x1b, 0x57, 0x69, 0x74,
- 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x44,
- 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e,
- 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63,
- 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74,
- 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22,
- 0x65, 0x0a, 0x21, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65,
- 0x6e, 0x74, 0x73, 0x42, 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71,
- 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65,
- 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65,
- 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64,
- 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52,
- 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x22, 0x79, 0x0a, 0x1d, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72,
- 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x44, 0x61, 0x74, 0x65,
- 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61,
- 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61,
- 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64,
- 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c,
- 0x69, 0x6d, 0x69, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69,
- 0x74, 0x22, 0x5b, 0x0a, 0x22, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45,
- 0x76, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52,
- 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x35, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74,
- 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e,
- 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52,
- 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x95,
- 0x02, 0x0a, 0x17, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65,
- 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x3a, 0x0a, 0x08, 0x65, 0x78,
- 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67,
- 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x6c, 0x45,
- 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x08, 0x65, 0x78,
- 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x38, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73,
- 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63,
- 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65,
- 0x73, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
- 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x05,
- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
- 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
- 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75,
- 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
- 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64,
- 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x22, 0x54, 0x0a, 0x16, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72,
- 0x61, 0x77, 0x6c, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74,
- 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
- 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x03,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xea, 0x01, 0x0a,
- 0x16, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65,
- 0x73, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65,
- 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65,
- 0x6e, 0x63, 0x79, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69,
- 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69,
- 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18,
- 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x06, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x12, 0x0a,
- 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x74, 0x79, 0x70,
- 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x66, 0x69, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x1b, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x46, 0x69, 0x61, 0x74, 0x57, 0x69, 0x74,
- 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x04, 0x66, 0x69,
- 0x61, 0x74, 0x12, 0x35, 0x0a, 0x06, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x18, 0x07, 0x20, 0x01,
- 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x72, 0x79, 0x70,
- 0x74, 0x6f, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e,
- 0x74, 0x52, 0x06, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x22, 0xb8, 0x01, 0x0a, 0x13, 0x46, 0x69,
- 0x61, 0x74, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e,
- 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x62, 0x61, 0x6e, 0x6b, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x62, 0x61, 0x6e, 0x6b, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21,
- 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x4e, 0x61, 0x6d,
- 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x6e, 0x75, 0x6d,
- 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x63, 0x63, 0x6f, 0x75,
- 0x6e, 0x74, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x10, 0x0a, 0x03, 0x62, 0x73, 0x62, 0x18,
- 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x62, 0x73, 0x62, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x77,
- 0x69, 0x66, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x77, 0x69, 0x66, 0x74,
- 0x12, 0x12, 0x0a, 0x04, 0x69, 0x62, 0x61, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
- 0x69, 0x62, 0x61, 0x6e, 0x22, 0x64, 0x0a, 0x15, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x57, 0x69,
- 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x18, 0x0a,
- 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
- 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x64, 0x64, 0x72, 0x65,
- 0x73, 0x73, 0x5f, 0x74, 0x61, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x64,
- 0x64, 0x72, 0x65, 0x73, 0x73, 0x54, 0x61, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x65, 0x65, 0x18,
- 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x03, 0x66, 0x65, 0x65, 0x22, 0x31, 0x0a, 0x17, 0x47, 0x65,
- 0x74, 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65,
- 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x22, 0x6e, 0x0a,
- 0x18, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c,
- 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x69, 0x6e, 0x66,
- 0x6f, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x14, 0x0a,
- 0x05, 0x64, 0x65, 0x62, 0x75, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x64, 0x65,
- 0x62, 0x75, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x77, 0x61, 0x72, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28,
- 0x08, 0x52, 0x04, 0x77, 0x61, 0x72, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72,
- 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x47, 0x0a,
- 0x17, 0x53, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c,
- 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x6f, 0x67, 0x67,
- 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6c, 0x6f, 0x67, 0x67, 0x65, 0x72,
- 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x05, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x22, 0x4b, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63,
- 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x69, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
- 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20,
- 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a,
- 0x05, 0x61, 0x73, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x73,
- 0x73, 0x65, 0x74, 0x22, 0xd8, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61,
- 0x6e, 0x67, 0x65, 0x50, 0x61, 0x69, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
- 0x12, 0x60, 0x0a, 0x10, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x73,
- 0x73, 0x65, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x67, 0x63, 0x74,
- 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50,
- 0x61, 0x69, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x53, 0x75, 0x70,
- 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x41, 0x73, 0x73, 0x65, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72,
- 0x79, 0x52, 0x0f, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x41, 0x73, 0x73, 0x65,
- 0x74, 0x73, 0x1a, 0x5a, 0x0a, 0x14, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x41,
- 0x73, 0x73, 0x65, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65,
- 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x2c, 0x0a, 0x05,
- 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x63,
- 0x74, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x61, 0x69, 0x72, 0x73, 0x53, 0x75, 0x70, 0x70, 0x6f, 0x72,
- 0x74, 0x65, 0x64, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x7a,
- 0x0a, 0x13, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x69, 0x72, 0x52, 0x65,
- 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67,
- 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67,
- 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18,
- 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65,
- 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x69, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14,
- 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79,
- 0x50, 0x61, 0x69, 0x72, 0x52, 0x04, 0x70, 0x61, 0x69, 0x72, 0x22, 0x80, 0x01, 0x0a, 0x19, 0x47,
- 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x53, 0x74, 0x72, 0x65, 0x61,
- 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68,
- 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68,
- 0x61, 0x6e, 0x67, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x69, 0x72, 0x18, 0x02, 0x20, 0x01,
- 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x75, 0x72, 0x72,
- 0x65, 0x6e, 0x63, 0x79, 0x50, 0x61, 0x69, 0x72, 0x52, 0x04, 0x70, 0x61, 0x69, 0x72, 0x12, 0x1d,
- 0x0a, 0x0a, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3f, 0x0a,
- 0x21, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x72, 0x64, 0x65,
- 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65,
- 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x22, 0x7d,
- 0x0a, 0x16, 0x47, 0x65, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61,
- 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68,
- 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68,
- 0x61, 0x6e, 0x67, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x69, 0x72, 0x18, 0x02, 0x20, 0x01,
- 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x75, 0x72, 0x72,
- 0x65, 0x6e, 0x63, 0x79, 0x50, 0x61, 0x69, 0x72, 0x52, 0x04, 0x70, 0x61, 0x69, 0x72, 0x12, 0x1d,
- 0x0a, 0x0a, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x22, 0x3c, 0x0a,
- 0x1e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x54, 0x69, 0x63, 0x6b,
- 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
- 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x08, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x22, 0x99, 0x01, 0x0a, 0x14,
- 0x47, 0x65, 0x74, 0x41, 0x75, 0x64, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71,
- 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x64, 0x61,
- 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x44,
- 0x61, 0x74, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x18,
- 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x44, 0x61, 0x74, 0x65, 0x12, 0x19,
- 0x0a, 0x08, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x62, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x07, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x42, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d,
- 0x69, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12,
- 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52,
- 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x43, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x41, 0x75,
- 0x64, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
- 0x12, 0x2a, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b,
- 0x32, 0x12, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x45,
- 0x76, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xec, 0x01, 0x0a,
- 0x19, 0x47, 0x65, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x43, 0x61, 0x6e, 0x64,
- 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78,
- 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78,
- 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x69, 0x72, 0x18, 0x02,
- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x75,
- 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x61, 0x69, 0x72, 0x52, 0x04, 0x70, 0x61, 0x69, 0x72,
- 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03,
- 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12,
- 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05,
- 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x05, 0x20, 0x01,
- 0x28, 0x03, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x69, 0x6d, 0x65, 0x5f,
- 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c,
- 0x74, 0x69, 0x6d, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x1d, 0x0a, 0x0a,
- 0x65, 0x78, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08,
- 0x52, 0x09, 0x65, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xce, 0x01, 0x0a, 0x1a,
- 0x47, 0x65, 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x43, 0x61, 0x6e, 0x64, 0x6c,
- 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78,
- 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78,
- 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x28, 0x0a, 0x04, 0x70, 0x61, 0x69, 0x72, 0x18, 0x02,
- 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x75,
- 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x50, 0x61, 0x69, 0x72, 0x52, 0x04, 0x70, 0x61, 0x69, 0x72,
- 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52,
- 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x04, 0x20,
- 0x01, 0x28, 0x03, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x74, 0x65,
- 0x72, 0x76, 0x61, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x65,
- 0x72, 0x76, 0x61, 0x6c, 0x12, 0x26, 0x0a, 0x06, 0x63, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x18, 0x05,
- 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61,
- 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x06, 0x63, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x22, 0x84, 0x01, 0x0a,
- 0x06, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6c,
- 0x6f, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x03, 0x6c, 0x6f, 0x77, 0x12, 0x12, 0x0a,
- 0x04, 0x68, 0x69, 0x67, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x04, 0x68, 0x69, 0x67,
- 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6f, 0x70, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52,
- 0x04, 0x6f, 0x70, 0x65, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x18, 0x05,
- 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x76,
- 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x06, 0x76, 0x6f, 0x6c,
- 0x75, 0x6d, 0x65, 0x22, 0x78, 0x0a, 0x0a, 0x41, 0x75, 0x64, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e,
- 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52,
- 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66,
- 0x69, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x69, 0x64, 0x65, 0x6e, 0x74,
- 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
- 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12,
- 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01,
- 0x28, 0x09, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x62, 0x0a,
- 0x09, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x55, 0x55,
- 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x55, 0x55, 0x49, 0x44, 0x12, 0x12,
- 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61,
- 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
- 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x19, 0x0a, 0x08, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x72,
- 0x75, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x78, 0x74, 0x52, 0x75,
- 0x6e, 0x22, 0x44, 0x0a, 0x17, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x45, 0x78,
- 0x65, 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x06,
- 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x67,
- 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52,
- 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, 0x41, 0x0a, 0x14, 0x47, 0x43, 0x54, 0x53, 0x63,
- 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
- 0x29, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
- 0x11, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69,
- 0x70, 0x74, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, 0x19, 0x0a, 0x17, 0x47, 0x43,
- 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x6f, 0x70, 0x41, 0x6c, 0x6c, 0x52, 0x65,
- 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x18, 0x0a, 0x16, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69,
- 0x70, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22,
- 0x19, 0x0a, 0x17, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4c, 0x69, 0x73, 0x74,
- 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xa8, 0x01, 0x0a, 0x16, 0x47,
- 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65,
- 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x5f,
- 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x63, 0x72, 0x69,
- 0x70, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
- 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x63, 0x72,
- 0x69, 0x70, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18,
- 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x1a, 0x0a, 0x08, 0x61,
- 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61,
- 0x72, 0x63, 0x68, 0x69, 0x76, 0x65, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x6f, 0x76, 0x65, 0x72, 0x77,
- 0x72, 0x69, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6f, 0x76, 0x65, 0x72,
- 0x77, 0x72, 0x69, 0x74, 0x65, 0x22, 0x47, 0x0a, 0x1a, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69,
- 0x70, 0x74, 0x52, 0x65, 0x61, 0x64, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75,
- 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x01, 0x20,
- 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54,
- 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x22, 0x42,
- 0x0a, 0x15, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x51, 0x75, 0x65, 0x72, 0x79,
- 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70,
- 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63,
- 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69,
- 0x70, 0x74, 0x22, 0x4a, 0x0a, 0x18, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x41,
- 0x75, 0x74, 0x6f, 0x4c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x16,
- 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
- 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
- 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x5e,
- 0x0a, 0x17, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75,
- 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61,
- 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75,
- 0x73, 0x12, 0x2b, 0x0a, 0x07, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x18, 0x02, 0x20, 0x03,
- 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53,
- 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x07, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x73, 0x22, 0x6f,
- 0x0a, 0x16, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x51, 0x75, 0x65, 0x72, 0x79,
- 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74,
- 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
- 0x12, 0x29, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
- 0x32, 0x11, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72,
- 0x69, 0x70, 0x74, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x64,
- 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22,
- 0x46, 0x0a, 0x18, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x47, 0x65, 0x6e, 0x65,
- 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73,
- 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61,
- 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, 0x28,
- 0x09, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x32, 0xcd, 0x38, 0x0a, 0x0e, 0x47, 0x6f, 0x43, 0x72,
- 0x79, 0x70, 0x74, 0x6f, 0x54, 0x72, 0x61, 0x64, 0x65, 0x72, 0x12, 0x4f, 0x0a, 0x07, 0x47, 0x65,
- 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47,
- 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e,
- 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65,
- 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x13, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0d, 0x12, 0x0b,
- 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x67, 0x0a, 0x0d, 0x47,
- 0x65, 0x74, 0x53, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x12, 0x1c, 0x2e, 0x67,
- 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74,
- 0x65, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x63, 0x74,
- 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x75, 0x73, 0x62, 0x73, 0x79, 0x74, 0x65, 0x6d,
- 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02,
- 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x73, 0x75, 0x62, 0x73, 0x79, 0x73,
- 0x74, 0x65, 0x6d, 0x73, 0x12, 0x71, 0x0a, 0x0f, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x53, 0x75,
- 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63,
- 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65,
- 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70,
- 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74,
- 0x65, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93,
- 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x75,
- 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x73, 0x0a, 0x10, 0x44, 0x69, 0x73, 0x61, 0x62,
- 0x6c, 0x65, 0x53, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x1f, 0x2e, 0x67, 0x63,
- 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x75, 0x62, 0x73,
- 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67,
- 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x75, 0x62,
- 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c,
- 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x69, 0x73, 0x61,
- 0x62, 0x6c, 0x65, 0x73, 0x75, 0x62, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x12, 0x6f, 0x0a, 0x0f,
- 0x47, 0x65, 0x74, 0x52, 0x50, 0x43, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12,
- 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x50, 0x43, 0x45,
- 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
- 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x50, 0x43, 0x45,
- 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
- 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65,
- 0x74, 0x72, 0x70, 0x63, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x93, 0x01,
- 0x0a, 0x18, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69,
- 0x6f, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x12, 0x27, 0x2e, 0x67, 0x63, 0x74,
- 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
- 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75,
- 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74,
- 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x6c,
- 0x61, 0x79, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82,
- 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x63, 0x6f,
- 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x72, 0x65, 0x6c, 0x61, 0x79,
- 0x65, 0x72, 0x73, 0x12, 0x63, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e,
- 0x67, 0x65, 0x73, 0x12, 0x1b, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74,
- 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
- 0x1a, 0x1c, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63,
- 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18,
- 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65,
- 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x7a, 0x0a, 0x0f, 0x44, 0x69, 0x73, 0x61,
- 0x62, 0x6c, 0x65, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x22, 0x2e, 0x67, 0x63,
- 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x45, 0x78, 0x63, 0x68,
- 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
- 0x23, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63,
- 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70,
- 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x22, 0x13, 0x2f, 0x76,
- 0x31, 0x2f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67,
- 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x73, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61,
- 0x6e, 0x67, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63,
- 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65,
- 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x63,
- 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65,
- 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3,
- 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, 0x78, 0x63,
- 0x68, 0x61, 0x6e, 0x67, 0x65, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x73, 0x0a, 0x12, 0x47, 0x65, 0x74,
- 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x54, 0x50, 0x43, 0x6f, 0x64, 0x65, 0x12,
- 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63,
- 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75,
- 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74,
- 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x54, 0x50, 0x52, 0x65, 0x70, 0x6f, 0x6e,
- 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x76, 0x31, 0x2f,
- 0x67, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6f, 0x74, 0x70, 0x12, 0x73,
- 0x0a, 0x13, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x54, 0x50,
- 0x43, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47,
- 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x54, 0x50, 0x73, 0x52, 0x65,
- 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47,
- 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x54, 0x50, 0x73, 0x52, 0x65,
- 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13,
- 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6f,
- 0x74, 0x70, 0x73, 0x12, 0x78, 0x0a, 0x0e, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x78, 0x63,
- 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47,
- 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x61,
- 0x6d, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x67, 0x63, 0x74, 0x72,
- 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e,
- 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d,
- 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x6e, 0x61, 0x62,
- 0x6c, 0x65, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x57, 0x0a,
- 0x09, 0x47, 0x65, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x12, 0x18, 0x2e, 0x67, 0x63, 0x74,
- 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x52, 0x65, 0x71,
- 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x69,
- 0x63, 0x6b, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3,
- 0xe4, 0x93, 0x02, 0x12, 0x22, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x74, 0x69, 0x63,
- 0x6b, 0x65, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x5b, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x54, 0x69, 0x63,
- 0x6b, 0x65, 0x72, 0x73, 0x12, 0x19, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65,
- 0x74, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
- 0x1a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x69, 0x63, 0x6b,
- 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x16, 0x82, 0xd3, 0xe4,
- 0x93, 0x02, 0x10, 0x12, 0x0e, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x74, 0x69, 0x63, 0x6b,
- 0x65, 0x72, 0x73, 0x12, 0x63, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62,
- 0x6f, 0x6f, 0x6b, 0x12, 0x1b, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74,
- 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
- 0x1a, 0x19, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62,
- 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4,
- 0x93, 0x02, 0x15, 0x22, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x6f, 0x72, 0x64, 0x65,
- 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x3a, 0x01, 0x2a, 0x12, 0x67, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4f,
- 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x63, 0x74, 0x72,
- 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x73,
- 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63,
- 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x52, 0x65,
- 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11,
- 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b,
- 0x73, 0x12, 0x6b, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49,
- 0x6e, 0x66, 0x6f, 0x12, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74,
- 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65,
- 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41,
- 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
- 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x76, 0x31, 0x2f,
- 0x67, 0x65, 0x74, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x69, 0x6e, 0x66, 0x6f, 0x12, 0x79,
- 0x0a, 0x14, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f,
- 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e,
- 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65,
- 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47,
- 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x65, 0x73,
- 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f,
- 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x69, 0x6e, 0x66,
- 0x6f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x30, 0x01, 0x12, 0x57, 0x0a, 0x09, 0x47, 0x65, 0x74,
- 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e,
- 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
- 0x1a, 0x19, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e,
- 0x66, 0x69, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, 0x82, 0xd3, 0xe4,
- 0x93, 0x02, 0x0f, 0x12, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x63, 0x6f, 0x6e, 0x66,
- 0x69, 0x67, 0x12, 0x63, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c,
- 0x69, 0x6f, 0x12, 0x1b, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x50,
- 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
- 0x1c, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x72, 0x74,
- 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82,
- 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x70, 0x6f,
- 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x12, 0x7f, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x50, 0x6f,
- 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x22,
- 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x72, 0x74, 0x66,
- 0x6f, 0x6c, 0x69, 0x6f, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65,
- 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x50,
- 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x53, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x52,
- 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x12,
- 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x70, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69,
- 0x6f, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x79, 0x12, 0x82, 0x01, 0x0a, 0x13, 0x41, 0x64, 0x64,
- 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
- 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x50, 0x6f, 0x72,
- 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71,
- 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64,
- 0x64, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
- 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02,
- 0x1c, 0x22, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x64, 0x64, 0x70, 0x6f, 0x72, 0x74, 0x66, 0x6f,
- 0x6c, 0x69, 0x6f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x8e, 0x01,
- 0x0a, 0x16, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69,
- 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x25, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70,
- 0x63, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50, 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69,
- 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
- 0x26, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x50,
- 0x6f, 0x72, 0x74, 0x66, 0x6f, 0x6c, 0x69, 0x6f, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52,
- 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x22,
- 0x1a, 0x2f, 0x76, 0x31, 0x2f, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x66,
- 0x6f, 0x6c, 0x69, 0x6f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x77,
- 0x0a, 0x11, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x65, 0x78, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64,
- 0x65, 0x72, 0x73, 0x12, 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74,
- 0x46, 0x6f, 0x72, 0x65, 0x78, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65,
- 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47,
- 0x65, 0x74, 0x46, 0x6f, 0x72, 0x65, 0x78, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73,
- 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17,
- 0x12, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x66, 0x6f, 0x72, 0x65, 0x78, 0x70, 0x72,
- 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0x67, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x46, 0x6f,
- 0x72, 0x65, 0x78, 0x52, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70,
- 0x63, 0x2e, 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x65, 0x78, 0x52, 0x61, 0x74, 0x65, 0x73, 0x52,
- 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e,
- 0x47, 0x65, 0x74, 0x46, 0x6f, 0x72, 0x65, 0x78, 0x52, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73,
- 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f,
- 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x66, 0x6f, 0x72, 0x65, 0x78, 0x72, 0x61, 0x74, 0x65, 0x73,
- 0x12, 0x5a, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x12, 0x18, 0x2e,
- 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73,
- 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63,
- 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
- 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x22, 0x0d, 0x2f, 0x76, 0x31, 0x2f,
- 0x67, 0x65, 0x74, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x52, 0x0a, 0x08,
- 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x17, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70,
- 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
- 0x74, 0x1a, 0x14, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72,
- 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x22,
- 0x0c, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x01, 0x2a,
- 0x12, 0x62, 0x0a, 0x0b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12,
- 0x1a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4f,
- 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x67, 0x63,
- 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72,
- 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14,
- 0x22, 0x0f, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x6f, 0x72, 0x64, 0x65,
- 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x6a, 0x0a, 0x0d, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65,
- 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53,
- 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75,
- 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x69, 0x6d,
- 0x75, 0x6c, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
- 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x22, 0x11, 0x2f, 0x76, 0x31, 0x2f,
- 0x73, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x3a, 0x01, 0x2a,
- 0x12, 0x5e, 0x0a, 0x09, 0x57, 0x68, 0x61, 0x6c, 0x65, 0x42, 0x6f, 0x6d, 0x62, 0x12, 0x18, 0x2e,
- 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x68, 0x61, 0x6c, 0x65, 0x42, 0x6f, 0x6d, 0x62,
- 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63,
- 0x2e, 0x53, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x52, 0x65,
- 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x22, 0x0d,
- 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x68, 0x61, 0x6c, 0x65, 0x62, 0x6f, 0x6d, 0x62, 0x3a, 0x01, 0x2a,
- 0x12, 0x62, 0x0a, 0x0b, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12,
- 0x1a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4f,
- 0x72, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x67, 0x63,
- 0x74, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72,
- 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14,
- 0x22, 0x0f, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x6f, 0x72, 0x64, 0x65,
- 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x72, 0x0a, 0x0f, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x6c,
- 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63,
- 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x6c, 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73,
- 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63,
- 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x6c, 0x6c, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x73,
- 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18,
- 0x22, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x61, 0x6c, 0x6c, 0x6f,
- 0x72, 0x64, 0x65, 0x72, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x57, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x45,
- 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47,
- 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
- 0x19, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e,
- 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93,
- 0x02, 0x0f, 0x12, 0x0d, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, 0x76, 0x65, 0x6e, 0x74,
- 0x73, 0x12, 0x56, 0x0a, 0x08, 0x41, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x17, 0x2e,
- 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52,
- 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e,
- 0x41, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
- 0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x22, 0x0c, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x64,
- 0x64, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x3a, 0x01, 0x2a, 0x12, 0x62, 0x0a, 0x0b, 0x52, 0x65, 0x6d,
- 0x6f, 0x76, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70,
- 0x63, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71,
- 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65,
- 0x6d, 0x6f, 0x76, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
- 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x22, 0x0f, 0x2f, 0x76, 0x31, 0x2f, 0x72,
- 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x3a, 0x01, 0x2a, 0x12, 0xb2, 0x01,
- 0x0a, 0x21, 0x47, 0x65, 0x74, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65,
- 0x6e, 0x63, 0x79, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
- 0x73, 0x65, 0x73, 0x12, 0x30, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74,
- 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x44, 0x65,
- 0x70, 0x6f, 0x73, 0x69, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x52, 0x65,
- 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47,
- 0x65, 0x74, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79,
- 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73,
- 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x28, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x22,
- 0x22, 0x1d, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x64,
- 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x3a,
- 0x01, 0x2a, 0x12, 0xaa, 0x01, 0x0a, 0x1f, 0x47, 0x65, 0x74, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f,
- 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x41,
- 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x2e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e,
- 0x47, 0x65, 0x74, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63,
- 0x79, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52,
- 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e,
- 0x47, 0x65, 0x74, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63,
- 0x79, 0x44, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x52,
- 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x22,
- 0x1b, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x64, 0x65,
- 0x70, 0x6f, 0x73, 0x69, 0x74, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x3a, 0x01, 0x2a, 0x12,
- 0x6c, 0x0a, 0x11, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x46, 0x69, 0x61, 0x74, 0x46,
- 0x75, 0x6e, 0x64, 0x73, 0x12, 0x1b, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69,
- 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x46, 0x69, 0x61, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
- 0x74, 0x1a, 0x18, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64,
- 0x72, 0x61, 0x77, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4,
- 0x93, 0x02, 0x1a, 0x22, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61,
- 0x77, 0x66, 0x69, 0x61, 0x74, 0x66, 0x75, 0x6e, 0x64, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x8b, 0x01,
- 0x0a, 0x1b, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x43, 0x72, 0x79, 0x70, 0x74, 0x6f,
- 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x46, 0x75, 0x6e, 0x64, 0x73, 0x12, 0x1d, 0x2e,
- 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x43,
- 0x72, 0x79, 0x70, 0x74, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x67,
- 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x52, 0x65,
- 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x33, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2d, 0x22, 0x28,
- 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x69, 0x74, 0x68, 0x64,
- 0x72, 0x61, 0x77, 0x63, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x66, 0x75, 0x6e, 0x64, 0x73, 0x77, 0x66,
- 0x69, 0x61, 0x74, 0x66, 0x75, 0x6e, 0x64, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x82, 0x01, 0x0a, 0x13,
- 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42,
- 0x79, 0x49, 0x44, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74,
- 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x79, 0x49, 0x44,
- 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63,
- 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74,
- 0x42, 0x79, 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3,
- 0xe4, 0x93, 0x02, 0x1c, 0x22, 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72,
- 0x61, 0x77, 0x61, 0x6c, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x62, 0x79, 0x69, 0x64, 0x3a, 0x01, 0x2a,
- 0x12, 0x97, 0x01, 0x0a, 0x1a, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45,
- 0x76, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x12,
- 0x29, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61,
- 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x45, 0x78, 0x63, 0x68, 0x61,
- 0x6e, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x67, 0x63, 0x74,
- 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76,
- 0x65, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x65,
- 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x22, 0x17,
- 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x65, 0x76,
- 0x65, 0x6e, 0x74, 0x62, 0x79, 0x69, 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x91, 0x01, 0x0a, 0x16, 0x57,
- 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x42,
- 0x79, 0x44, 0x61, 0x74, 0x65, 0x12, 0x25, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57,
- 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x42,
- 0x79, 0x44, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x67,
- 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x57, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c,
- 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x42, 0x79, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65,
- 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e,
- 0x22, 0x19, 0x2f, 0x76, 0x31, 0x2f, 0x77, 0x69, 0x74, 0x68, 0x64, 0x72, 0x61, 0x77, 0x61, 0x6c,
- 0x65, 0x76, 0x65, 0x6e, 0x74, 0x62, 0x79, 0x64, 0x61, 0x74, 0x65, 0x3a, 0x01, 0x2a, 0x12, 0x73,
- 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69,
- 0x6c, 0x73, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4c,
- 0x6f, 0x67, 0x67, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75,
- 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74,
- 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x65, 0x73,
- 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f,
- 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x6c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x64, 0x65, 0x74, 0x61,
- 0x69, 0x6c, 0x73, 0x12, 0x76, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x72,
- 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63,
- 0x2e, 0x53, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c,
- 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70,
- 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4c, 0x6f, 0x67, 0x67, 0x65, 0x72, 0x44, 0x65, 0x74, 0x61, 0x69,
- 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93,
- 0x02, 0x19, 0x22, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x74, 0x6c, 0x6f, 0x67, 0x67, 0x65,
- 0x72, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x3a, 0x01, 0x2a, 0x12, 0x76, 0x0a, 0x10, 0x47,
- 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x69, 0x72, 0x73, 0x12,
- 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68,
- 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x69, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
- 0x1a, 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63,
- 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x69, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
- 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x22, 0x14, 0x2f, 0x76, 0x31, 0x2f,
- 0x67, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x70, 0x61, 0x69, 0x72, 0x73,
- 0x3a, 0x01, 0x2a, 0x12, 0x79, 0x0a, 0x12, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x78, 0x63,
- 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x69, 0x72, 0x12, 0x1b, 0x2e, 0x67, 0x63, 0x74, 0x72,
- 0x70, 0x63, 0x2e, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x69, 0x72, 0x52,
- 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e,
- 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e,
- 0x61, 0x6d, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4,
- 0x93, 0x02, 0x1b, 0x22, 0x16, 0x2f, 0x76, 0x31, 0x2f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x65,
- 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x70, 0x61, 0x69, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x7b,
- 0x0a, 0x13, 0x44, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67,
- 0x65, 0x50, 0x61, 0x69, 0x72, 0x12, 0x1b, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x45,
- 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x69, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65,
- 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x6e, 0x65,
- 0x72, 0x69, 0x63, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x52,
- 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x22,
- 0x17, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x65, 0x78, 0x63, 0x68,
- 0x61, 0x6e, 0x67, 0x65, 0x70, 0x61, 0x69, 0x72, 0x3a, 0x01, 0x2a, 0x12, 0x74, 0x0a, 0x12, 0x47,
- 0x65, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x53, 0x74, 0x72, 0x65, 0x61,
- 0x6d, 0x12, 0x21, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x72,
- 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71,
- 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x72,
- 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
- 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12, 0x16, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74,
- 0x6f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x30,
- 0x01, 0x12, 0x8c, 0x01, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67,
- 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d,
- 0x12, 0x29, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x78, 0x63,
- 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x53, 0x74,
- 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x67, 0x63,
- 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x52, 0x65,
- 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x12, 0x1e,
- 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6f,
- 0x72, 0x64, 0x65, 0x72, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x30, 0x01,
- 0x12, 0x68, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x53, 0x74, 0x72,
- 0x65, 0x61, 0x6d, 0x12, 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74,
- 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75,
- 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x69, 0x63,
- 0x6b, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4,
- 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x74, 0x69, 0x63, 0x6b,
- 0x65, 0x72, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x30, 0x01, 0x12, 0x80, 0x01, 0x0a, 0x17, 0x47,
- 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72,
- 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x26, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e,
- 0x47, 0x65, 0x74, 0x45, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65,
- 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16,
- 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x72, 0x52, 0x65,
- 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x23, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x12, 0x1b,
- 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x65, 0x78, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x74,
- 0x69, 0x63, 0x6b, 0x65, 0x72, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x30, 0x01, 0x12, 0x67, 0x0a,
- 0x0d, 0x47, 0x65, 0x74, 0x41, 0x75, 0x64, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1c,
- 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x75, 0x64, 0x69, 0x74,
- 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67,
- 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x75, 0x64, 0x69, 0x74, 0x45, 0x76,
- 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4,
- 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x61, 0x75, 0x64, 0x69,
- 0x74, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x74, 0x0a, 0x10, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72,
- 0x69, 0x70, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74,
- 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x45, 0x78, 0x65,
- 0x63, 0x75, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x63,
- 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x47, 0x65,
- 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82,
- 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63,
- 0x72, 0x69, 0x70, 0x74, 0x2f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x12, 0x74, 0x0a, 0x0f,
- 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x12,
- 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69,
- 0x70, 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
- 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69,
- 0x70, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
- 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x22, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x67,
- 0x63, 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x3a,
- 0x01, 0x2a, 0x12, 0x78, 0x0a, 0x13, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52,
- 0x65, 0x61, 0x64, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72,
- 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x61, 0x64,
- 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e,
- 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74,
- 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82,
- 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63,
- 0x72, 0x69, 0x70, 0x74, 0x2f, 0x72, 0x65, 0x61, 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x70, 0x0a, 0x0f,
- 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12,
- 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69,
- 0x70, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
- 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69,
- 0x70, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
- 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63,
- 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x6c,
- 0x0a, 0x0e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x51, 0x75, 0x65, 0x72, 0x79,
- 0x12, 0x1d, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72,
- 0x69, 0x70, 0x74, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
- 0x1e, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69,
- 0x70, 0x74, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
- 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74,
- 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x6e, 0x0a, 0x0d,
- 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x6f, 0x70, 0x12, 0x1c, 0x2e,
- 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74,
- 0x53, 0x74, 0x6f, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x63,
- 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x47, 0x65,
- 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82,
- 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63,
- 0x72, 0x69, 0x70, 0x74, 0x2f, 0x73, 0x74, 0x6f, 0x70, 0x3a, 0x01, 0x2a, 0x12, 0x74, 0x0a, 0x10,
- 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x6f, 0x70, 0x41, 0x6c, 0x6c,
- 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72,
- 0x69, 0x70, 0x74, 0x53, 0x74, 0x6f, 0x70, 0x41, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
- 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63,
- 0x72, 0x69, 0x70, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f,
- 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x22, 0x12, 0x2f, 0x76, 0x31,
- 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, 0x73, 0x74, 0x6f, 0x70, 0x3a,
- 0x01, 0x2a, 0x12, 0x73, 0x0a, 0x10, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4c,
- 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c, 0x12, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e,
- 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x6c, 0x6c,
- 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63,
- 0x2e, 0x47, 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73,
- 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17,
- 0x22, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f,
- 0x73, 0x74, 0x6f, 0x70, 0x3a, 0x01, 0x2a, 0x12, 0x80, 0x01, 0x0a, 0x17, 0x47, 0x43, 0x54, 0x53,
- 0x63, 0x72, 0x69, 0x70, 0x74, 0x41, 0x75, 0x74, 0x6f, 0x4c, 0x6f, 0x61, 0x64, 0x54, 0x6f, 0x67,
- 0x67, 0x6c, 0x65, 0x12, 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x43, 0x54,
- 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x41, 0x75, 0x74, 0x6f, 0x4c, 0x6f, 0x61, 0x64, 0x52, 0x65,
- 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47,
- 0x43, 0x54, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x52,
- 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x22,
- 0x16, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x63, 0x74, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x2f, 0x61,
- 0x75, 0x74, 0x6f, 0x6c, 0x6f, 0x61, 0x64, 0x3a, 0x01, 0x2a, 0x12, 0x7b, 0x0a, 0x12, 0x47, 0x65,
- 0x74, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73,
- 0x12, 0x21, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x48, 0x69, 0x73,
- 0x74, 0x6f, 0x72, 0x69, 0x63, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75,
- 0x65, 0x73, 0x74, 0x1a, 0x22, 0x2e, 0x67, 0x63, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74,
- 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63, 0x43, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x52,
- 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x12,
- 0x16, 0x2f, 0x76, 0x31, 0x2f, 0x67, 0x65, 0x74, 0x68, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x69, 0x63,
- 0x63, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+type WebsocketSetProxyRequest struct {
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Proxy string `protobuf:"bytes,2,opt,name=proxy,proto3" json:"proxy,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
}
-var (
- file_rpc_proto_rawDescOnce sync.Once
- file_rpc_proto_rawDescData = file_rpc_proto_rawDesc
-)
-
-func file_rpc_proto_rawDescGZIP() []byte {
- file_rpc_proto_rawDescOnce.Do(func() {
- file_rpc_proto_rawDescData = protoimpl.X.CompressGZIP(file_rpc_proto_rawDescData)
- })
- return file_rpc_proto_rawDescData
+func (m *WebsocketSetProxyRequest) Reset() { *m = WebsocketSetProxyRequest{} }
+func (m *WebsocketSetProxyRequest) String() string { return proto.CompactTextString(m) }
+func (*WebsocketSetProxyRequest) ProtoMessage() {}
+func (*WebsocketSetProxyRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_77a6da22d6a3feb1, []int{132}
}
-var file_rpc_proto_msgTypes = make([]protoimpl.MessageInfo, 141)
-var file_rpc_proto_goTypes = []interface{}{
- (*GetInfoRequest)(nil), // 0: gctrpc.GetInfoRequest
- (*GetInfoResponse)(nil), // 1: gctrpc.GetInfoResponse
- (*GetCommunicationRelayersRequest)(nil), // 2: gctrpc.GetCommunicationRelayersRequest
- (*CommunicationRelayer)(nil), // 3: gctrpc.CommunicationRelayer
- (*GetCommunicationRelayersResponse)(nil), // 4: gctrpc.GetCommunicationRelayersResponse
- (*GenericSubsystemRequest)(nil), // 5: gctrpc.GenericSubsystemRequest
- (*GenericSubsystemResponse)(nil), // 6: gctrpc.GenericSubsystemResponse
- (*GetSubsystemsRequest)(nil), // 7: gctrpc.GetSubsystemsRequest
- (*GetSusbsytemsResponse)(nil), // 8: gctrpc.GetSusbsytemsResponse
- (*GetRPCEndpointsRequest)(nil), // 9: gctrpc.GetRPCEndpointsRequest
- (*RPCEndpoint)(nil), // 10: gctrpc.RPCEndpoint
- (*GetRPCEndpointsResponse)(nil), // 11: gctrpc.GetRPCEndpointsResponse
- (*GenericExchangeNameRequest)(nil), // 12: gctrpc.GenericExchangeNameRequest
- (*GenericExchangeNameResponse)(nil), // 13: gctrpc.GenericExchangeNameResponse
- (*GetExchangesRequest)(nil), // 14: gctrpc.GetExchangesRequest
- (*GetExchangesResponse)(nil), // 15: gctrpc.GetExchangesResponse
- (*GetExchangeOTPReponse)(nil), // 16: gctrpc.GetExchangeOTPReponse
- (*GetExchangeOTPsRequest)(nil), // 17: gctrpc.GetExchangeOTPsRequest
- (*GetExchangeOTPsResponse)(nil), // 18: gctrpc.GetExchangeOTPsResponse
- (*DisableExchangeRequest)(nil), // 19: gctrpc.DisableExchangeRequest
- (*PairsSupported)(nil), // 20: gctrpc.PairsSupported
- (*GetExchangeInfoResponse)(nil), // 21: gctrpc.GetExchangeInfoResponse
- (*GetTickerRequest)(nil), // 22: gctrpc.GetTickerRequest
- (*CurrencyPair)(nil), // 23: gctrpc.CurrencyPair
- (*TickerResponse)(nil), // 24: gctrpc.TickerResponse
- (*GetTickersRequest)(nil), // 25: gctrpc.GetTickersRequest
- (*Tickers)(nil), // 26: gctrpc.Tickers
- (*GetTickersResponse)(nil), // 27: gctrpc.GetTickersResponse
- (*GetOrderbookRequest)(nil), // 28: gctrpc.GetOrderbookRequest
- (*OrderbookItem)(nil), // 29: gctrpc.OrderbookItem
- (*OrderbookResponse)(nil), // 30: gctrpc.OrderbookResponse
- (*GetOrderbooksRequest)(nil), // 31: gctrpc.GetOrderbooksRequest
- (*Orderbooks)(nil), // 32: gctrpc.Orderbooks
- (*GetOrderbooksResponse)(nil), // 33: gctrpc.GetOrderbooksResponse
- (*GetAccountInfoRequest)(nil), // 34: gctrpc.GetAccountInfoRequest
- (*Account)(nil), // 35: gctrpc.Account
- (*AccountCurrencyInfo)(nil), // 36: gctrpc.AccountCurrencyInfo
- (*GetAccountInfoResponse)(nil), // 37: gctrpc.GetAccountInfoResponse
- (*GetConfigRequest)(nil), // 38: gctrpc.GetConfigRequest
- (*GetConfigResponse)(nil), // 39: gctrpc.GetConfigResponse
- (*PortfolioAddress)(nil), // 40: gctrpc.PortfolioAddress
- (*GetPortfolioRequest)(nil), // 41: gctrpc.GetPortfolioRequest
- (*GetPortfolioResponse)(nil), // 42: gctrpc.GetPortfolioResponse
- (*GetPortfolioSummaryRequest)(nil), // 43: gctrpc.GetPortfolioSummaryRequest
- (*Coin)(nil), // 44: gctrpc.Coin
- (*OfflineCoinSummary)(nil), // 45: gctrpc.OfflineCoinSummary
- (*OnlineCoinSummary)(nil), // 46: gctrpc.OnlineCoinSummary
- (*OfflineCoins)(nil), // 47: gctrpc.OfflineCoins
- (*OnlineCoins)(nil), // 48: gctrpc.OnlineCoins
- (*GetPortfolioSummaryResponse)(nil), // 49: gctrpc.GetPortfolioSummaryResponse
- (*AddPortfolioAddressRequest)(nil), // 50: gctrpc.AddPortfolioAddressRequest
- (*AddPortfolioAddressResponse)(nil), // 51: gctrpc.AddPortfolioAddressResponse
- (*RemovePortfolioAddressRequest)(nil), // 52: gctrpc.RemovePortfolioAddressRequest
- (*RemovePortfolioAddressResponse)(nil), // 53: gctrpc.RemovePortfolioAddressResponse
- (*GetForexProvidersRequest)(nil), // 54: gctrpc.GetForexProvidersRequest
- (*ForexProvider)(nil), // 55: gctrpc.ForexProvider
- (*GetForexProvidersResponse)(nil), // 56: gctrpc.GetForexProvidersResponse
- (*GetForexRatesRequest)(nil), // 57: gctrpc.GetForexRatesRequest
- (*ForexRatesConversion)(nil), // 58: gctrpc.ForexRatesConversion
- (*GetForexRatesResponse)(nil), // 59: gctrpc.GetForexRatesResponse
- (*OrderDetails)(nil), // 60: gctrpc.OrderDetails
- (*TradeHistory)(nil), // 61: gctrpc.TradeHistory
- (*GetOrdersRequest)(nil), // 62: gctrpc.GetOrdersRequest
- (*GetOrdersResponse)(nil), // 63: gctrpc.GetOrdersResponse
- (*GetOrderRequest)(nil), // 64: gctrpc.GetOrderRequest
- (*SubmitOrderRequest)(nil), // 65: gctrpc.SubmitOrderRequest
- (*SubmitOrderResponse)(nil), // 66: gctrpc.SubmitOrderResponse
- (*SimulateOrderRequest)(nil), // 67: gctrpc.SimulateOrderRequest
- (*SimulateOrderResponse)(nil), // 68: gctrpc.SimulateOrderResponse
- (*WhaleBombRequest)(nil), // 69: gctrpc.WhaleBombRequest
- (*CancelOrderRequest)(nil), // 70: gctrpc.CancelOrderRequest
- (*CancelOrderResponse)(nil), // 71: gctrpc.CancelOrderResponse
- (*CancelAllOrdersRequest)(nil), // 72: gctrpc.CancelAllOrdersRequest
- (*CancelAllOrdersResponse)(nil), // 73: gctrpc.CancelAllOrdersResponse
- (*GetEventsRequest)(nil), // 74: gctrpc.GetEventsRequest
- (*ConditionParams)(nil), // 75: gctrpc.ConditionParams
- (*GetEventsResponse)(nil), // 76: gctrpc.GetEventsResponse
- (*AddEventRequest)(nil), // 77: gctrpc.AddEventRequest
- (*AddEventResponse)(nil), // 78: gctrpc.AddEventResponse
- (*RemoveEventRequest)(nil), // 79: gctrpc.RemoveEventRequest
- (*RemoveEventResponse)(nil), // 80: gctrpc.RemoveEventResponse
- (*GetCryptocurrencyDepositAddressesRequest)(nil), // 81: gctrpc.GetCryptocurrencyDepositAddressesRequest
- (*GetCryptocurrencyDepositAddressesResponse)(nil), // 82: gctrpc.GetCryptocurrencyDepositAddressesResponse
- (*GetCryptocurrencyDepositAddressRequest)(nil), // 83: gctrpc.GetCryptocurrencyDepositAddressRequest
- (*GetCryptocurrencyDepositAddressResponse)(nil), // 84: gctrpc.GetCryptocurrencyDepositAddressResponse
- (*WithdrawFiatRequest)(nil), // 85: gctrpc.WithdrawFiatRequest
- (*WithdrawCryptoRequest)(nil), // 86: gctrpc.WithdrawCryptoRequest
- (*WithdrawResponse)(nil), // 87: gctrpc.WithdrawResponse
- (*WithdrawalEventByIDRequest)(nil), // 88: gctrpc.WithdrawalEventByIDRequest
- (*WithdrawalEventByIDResponse)(nil), // 89: gctrpc.WithdrawalEventByIDResponse
- (*WithdrawalEventsByExchangeRequest)(nil), // 90: gctrpc.WithdrawalEventsByExchangeRequest
- (*WithdrawalEventsByDateRequest)(nil), // 91: gctrpc.WithdrawalEventsByDateRequest
- (*WithdrawalEventsByExchangeResponse)(nil), // 92: gctrpc.WithdrawalEventsByExchangeResponse
- (*WithdrawalEventResponse)(nil), // 93: gctrpc.WithdrawalEventResponse
- (*WithdrawlExchangeEvent)(nil), // 94: gctrpc.WithdrawlExchangeEvent
- (*WithdrawalRequestEvent)(nil), // 95: gctrpc.WithdrawalRequestEvent
- (*FiatWithdrawalEvent)(nil), // 96: gctrpc.FiatWithdrawalEvent
- (*CryptoWithdrawalEvent)(nil), // 97: gctrpc.CryptoWithdrawalEvent
- (*GetLoggerDetailsRequest)(nil), // 98: gctrpc.GetLoggerDetailsRequest
- (*GetLoggerDetailsResponse)(nil), // 99: gctrpc.GetLoggerDetailsResponse
- (*SetLoggerDetailsRequest)(nil), // 100: gctrpc.SetLoggerDetailsRequest
- (*GetExchangePairsRequest)(nil), // 101: gctrpc.GetExchangePairsRequest
- (*GetExchangePairsResponse)(nil), // 102: gctrpc.GetExchangePairsResponse
- (*ExchangePairRequest)(nil), // 103: gctrpc.ExchangePairRequest
- (*GetOrderbookStreamRequest)(nil), // 104: gctrpc.GetOrderbookStreamRequest
- (*GetExchangeOrderbookStreamRequest)(nil), // 105: gctrpc.GetExchangeOrderbookStreamRequest
- (*GetTickerStreamRequest)(nil), // 106: gctrpc.GetTickerStreamRequest
- (*GetExchangeTickerStreamRequest)(nil), // 107: gctrpc.GetExchangeTickerStreamRequest
- (*GetAuditEventRequest)(nil), // 108: gctrpc.GetAuditEventRequest
- (*GetAuditEventResponse)(nil), // 109: gctrpc.GetAuditEventResponse
- (*GetHistoricCandlesRequest)(nil), // 110: gctrpc.GetHistoricCandlesRequest
- (*GetHistoricCandlesResponse)(nil), // 111: gctrpc.GetHistoricCandlesResponse
- (*Candle)(nil), // 112: gctrpc.Candle
- (*AuditEvent)(nil), // 113: gctrpc.AuditEvent
- (*GCTScript)(nil), // 114: gctrpc.GCTScript
- (*GCTScriptExecuteRequest)(nil), // 115: gctrpc.GCTScriptExecuteRequest
- (*GCTScriptStopRequest)(nil), // 116: gctrpc.GCTScriptStopRequest
- (*GCTScriptStopAllRequest)(nil), // 117: gctrpc.GCTScriptStopAllRequest
- (*GCTScriptStatusRequest)(nil), // 118: gctrpc.GCTScriptStatusRequest
- (*GCTScriptListAllRequest)(nil), // 119: gctrpc.GCTScriptListAllRequest
- (*GCTScriptUploadRequest)(nil), // 120: gctrpc.GCTScriptUploadRequest
- (*GCTScriptReadScriptRequest)(nil), // 121: gctrpc.GCTScriptReadScriptRequest
- (*GCTScriptQueryRequest)(nil), // 122: gctrpc.GCTScriptQueryRequest
- (*GCTScriptAutoLoadRequest)(nil), // 123: gctrpc.GCTScriptAutoLoadRequest
- (*GCTScriptStatusResponse)(nil), // 124: gctrpc.GCTScriptStatusResponse
- (*GCTScriptQueryResponse)(nil), // 125: gctrpc.GCTScriptQueryResponse
- (*GCTScriptGenericResponse)(nil), // 126: gctrpc.GCTScriptGenericResponse
- nil, // 127: gctrpc.GetInfoResponse.SubsystemStatusEntry
- nil, // 128: gctrpc.GetInfoResponse.RpcEndpointsEntry
- nil, // 129: gctrpc.GetCommunicationRelayersResponse.CommunicationRelayersEntry
- nil, // 130: gctrpc.GetSusbsytemsResponse.SubsystemsStatusEntry
- nil, // 131: gctrpc.GetRPCEndpointsResponse.EndpointsEntry
- nil, // 132: gctrpc.GetExchangeOTPsResponse.OtpCodesEntry
- nil, // 133: gctrpc.GetExchangeInfoResponse.SupportedAssetsEntry
- nil, // 134: gctrpc.OnlineCoins.CoinsEntry
- nil, // 135: gctrpc.GetPortfolioSummaryResponse.CoinsOfflineSummaryEntry
- nil, // 136: gctrpc.GetPortfolioSummaryResponse.CoinsOnlineSummaryEntry
- (*CancelAllOrdersResponse_Orders)(nil), // 137: gctrpc.CancelAllOrdersResponse.Orders
- nil, // 138: gctrpc.CancelAllOrdersResponse.Orders.OrderStatusEntry
- nil, // 139: gctrpc.GetCryptocurrencyDepositAddressesResponse.AddressesEntry
- nil, // 140: gctrpc.GetExchangePairsResponse.SupportedAssetsEntry
- (*timestamp.Timestamp)(nil), // 141: google.protobuf.Timestamp
+func (m *WebsocketSetProxyRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_WebsocketSetProxyRequest.Unmarshal(m, b)
}
-var file_rpc_proto_depIdxs = []int32{
- 127, // 0: gctrpc.GetInfoResponse.subsystem_status:type_name -> gctrpc.GetInfoResponse.SubsystemStatusEntry
- 128, // 1: gctrpc.GetInfoResponse.rpc_endpoints:type_name -> gctrpc.GetInfoResponse.RpcEndpointsEntry
- 129, // 2: gctrpc.GetCommunicationRelayersResponse.communication_relayers:type_name -> gctrpc.GetCommunicationRelayersResponse.CommunicationRelayersEntry
- 130, // 3: gctrpc.GetSusbsytemsResponse.subsystems_status:type_name -> gctrpc.GetSusbsytemsResponse.SubsystemsStatusEntry
- 131, // 4: gctrpc.GetRPCEndpointsResponse.endpoints:type_name -> gctrpc.GetRPCEndpointsResponse.EndpointsEntry
- 132, // 5: gctrpc.GetExchangeOTPsResponse.otp_codes:type_name -> gctrpc.GetExchangeOTPsResponse.OtpCodesEntry
- 133, // 6: gctrpc.GetExchangeInfoResponse.supported_assets:type_name -> gctrpc.GetExchangeInfoResponse.SupportedAssetsEntry
- 23, // 7: gctrpc.GetTickerRequest.pair:type_name -> gctrpc.CurrencyPair
- 23, // 8: gctrpc.TickerResponse.pair:type_name -> gctrpc.CurrencyPair
- 24, // 9: gctrpc.Tickers.tickers:type_name -> gctrpc.TickerResponse
- 26, // 10: gctrpc.GetTickersResponse.tickers:type_name -> gctrpc.Tickers
- 23, // 11: gctrpc.GetOrderbookRequest.pair:type_name -> gctrpc.CurrencyPair
- 23, // 12: gctrpc.OrderbookResponse.pair:type_name -> gctrpc.CurrencyPair
- 29, // 13: gctrpc.OrderbookResponse.bids:type_name -> gctrpc.OrderbookItem
- 29, // 14: gctrpc.OrderbookResponse.asks:type_name -> gctrpc.OrderbookItem
- 30, // 15: gctrpc.Orderbooks.orderbooks:type_name -> gctrpc.OrderbookResponse
- 32, // 16: gctrpc.GetOrderbooksResponse.orderbooks:type_name -> gctrpc.Orderbooks
- 36, // 17: gctrpc.Account.currencies:type_name -> gctrpc.AccountCurrencyInfo
- 35, // 18: gctrpc.GetAccountInfoResponse.accounts:type_name -> gctrpc.Account
- 40, // 19: gctrpc.GetPortfolioResponse.portfolio:type_name -> gctrpc.PortfolioAddress
- 45, // 20: gctrpc.OfflineCoins.addresses:type_name -> gctrpc.OfflineCoinSummary
- 134, // 21: gctrpc.OnlineCoins.coins:type_name -> gctrpc.OnlineCoins.CoinsEntry
- 44, // 22: gctrpc.GetPortfolioSummaryResponse.coin_totals:type_name -> gctrpc.Coin
- 44, // 23: gctrpc.GetPortfolioSummaryResponse.coins_offline:type_name -> gctrpc.Coin
- 135, // 24: gctrpc.GetPortfolioSummaryResponse.coins_offline_summary:type_name -> gctrpc.GetPortfolioSummaryResponse.CoinsOfflineSummaryEntry
- 44, // 25: gctrpc.GetPortfolioSummaryResponse.coins_online:type_name -> gctrpc.Coin
- 136, // 26: gctrpc.GetPortfolioSummaryResponse.coins_online_summary:type_name -> gctrpc.GetPortfolioSummaryResponse.CoinsOnlineSummaryEntry
- 55, // 27: gctrpc.GetForexProvidersResponse.forex_providers:type_name -> gctrpc.ForexProvider
- 58, // 28: gctrpc.GetForexRatesResponse.forex_rates:type_name -> gctrpc.ForexRatesConversion
- 61, // 29: gctrpc.OrderDetails.trades:type_name -> gctrpc.TradeHistory
- 23, // 30: gctrpc.GetOrdersRequest.pair:type_name -> gctrpc.CurrencyPair
- 60, // 31: gctrpc.GetOrdersResponse.orders:type_name -> gctrpc.OrderDetails
- 23, // 32: gctrpc.SubmitOrderRequest.pair:type_name -> gctrpc.CurrencyPair
- 23, // 33: gctrpc.SimulateOrderRequest.pair:type_name -> gctrpc.CurrencyPair
- 29, // 34: gctrpc.SimulateOrderResponse.orders:type_name -> gctrpc.OrderbookItem
- 23, // 35: gctrpc.WhaleBombRequest.pair:type_name -> gctrpc.CurrencyPair
- 23, // 36: gctrpc.CancelOrderRequest.pair:type_name -> gctrpc.CurrencyPair
- 137, // 37: gctrpc.CancelAllOrdersResponse.orders:type_name -> gctrpc.CancelAllOrdersResponse.Orders
- 75, // 38: gctrpc.GetEventsResponse.condition_params:type_name -> gctrpc.ConditionParams
- 23, // 39: gctrpc.GetEventsResponse.pair:type_name -> gctrpc.CurrencyPair
- 75, // 40: gctrpc.AddEventRequest.condition_params:type_name -> gctrpc.ConditionParams
- 23, // 41: gctrpc.AddEventRequest.pair:type_name -> gctrpc.CurrencyPair
- 139, // 42: gctrpc.GetCryptocurrencyDepositAddressesResponse.addresses:type_name -> gctrpc.GetCryptocurrencyDepositAddressesResponse.AddressesEntry
- 93, // 43: gctrpc.WithdrawalEventByIDResponse.event:type_name -> gctrpc.WithdrawalEventResponse
- 93, // 44: gctrpc.WithdrawalEventsByExchangeResponse.event:type_name -> gctrpc.WithdrawalEventResponse
- 94, // 45: gctrpc.WithdrawalEventResponse.exchange:type_name -> gctrpc.WithdrawlExchangeEvent
- 95, // 46: gctrpc.WithdrawalEventResponse.request:type_name -> gctrpc.WithdrawalRequestEvent
- 141, // 47: gctrpc.WithdrawalEventResponse.created_at:type_name -> google.protobuf.Timestamp
- 141, // 48: gctrpc.WithdrawalEventResponse.updated_at:type_name -> google.protobuf.Timestamp
- 96, // 49: gctrpc.WithdrawalRequestEvent.fiat:type_name -> gctrpc.FiatWithdrawalEvent
- 97, // 50: gctrpc.WithdrawalRequestEvent.crypto:type_name -> gctrpc.CryptoWithdrawalEvent
- 140, // 51: gctrpc.GetExchangePairsResponse.supported_assets:type_name -> gctrpc.GetExchangePairsResponse.SupportedAssetsEntry
- 23, // 52: gctrpc.ExchangePairRequest.pair:type_name -> gctrpc.CurrencyPair
- 23, // 53: gctrpc.GetOrderbookStreamRequest.pair:type_name -> gctrpc.CurrencyPair
- 23, // 54: gctrpc.GetTickerStreamRequest.pair:type_name -> gctrpc.CurrencyPair
- 113, // 55: gctrpc.GetAuditEventResponse.events:type_name -> gctrpc.AuditEvent
- 23, // 56: gctrpc.GetHistoricCandlesRequest.pair:type_name -> gctrpc.CurrencyPair
- 23, // 57: gctrpc.GetHistoricCandlesResponse.pair:type_name -> gctrpc.CurrencyPair
- 112, // 58: gctrpc.GetHistoricCandlesResponse.candle:type_name -> gctrpc.Candle
- 114, // 59: gctrpc.GCTScriptExecuteRequest.script:type_name -> gctrpc.GCTScript
- 114, // 60: gctrpc.GCTScriptStopRequest.script:type_name -> gctrpc.GCTScript
- 114, // 61: gctrpc.GCTScriptReadScriptRequest.script:type_name -> gctrpc.GCTScript
- 114, // 62: gctrpc.GCTScriptQueryRequest.script:type_name -> gctrpc.GCTScript
- 114, // 63: gctrpc.GCTScriptStatusResponse.scripts:type_name -> gctrpc.GCTScript
- 114, // 64: gctrpc.GCTScriptQueryResponse.script:type_name -> gctrpc.GCTScript
- 10, // 65: gctrpc.GetInfoResponse.RpcEndpointsEntry.value:type_name -> gctrpc.RPCEndpoint
- 3, // 66: gctrpc.GetCommunicationRelayersResponse.CommunicationRelayersEntry.value:type_name -> gctrpc.CommunicationRelayer
- 10, // 67: gctrpc.GetRPCEndpointsResponse.EndpointsEntry.value:type_name -> gctrpc.RPCEndpoint
- 20, // 68: gctrpc.GetExchangeInfoResponse.SupportedAssetsEntry.value:type_name -> gctrpc.PairsSupported
- 46, // 69: gctrpc.OnlineCoins.CoinsEntry.value:type_name -> gctrpc.OnlineCoinSummary
- 47, // 70: gctrpc.GetPortfolioSummaryResponse.CoinsOfflineSummaryEntry.value:type_name -> gctrpc.OfflineCoins
- 48, // 71: gctrpc.GetPortfolioSummaryResponse.CoinsOnlineSummaryEntry.value:type_name -> gctrpc.OnlineCoins
- 138, // 72: gctrpc.CancelAllOrdersResponse.Orders.order_status:type_name -> gctrpc.CancelAllOrdersResponse.Orders.OrderStatusEntry
- 20, // 73: gctrpc.GetExchangePairsResponse.SupportedAssetsEntry.value:type_name -> gctrpc.PairsSupported
- 0, // 74: gctrpc.GoCryptoTrader.GetInfo:input_type -> gctrpc.GetInfoRequest
- 7, // 75: gctrpc.GoCryptoTrader.GetSubsystems:input_type -> gctrpc.GetSubsystemsRequest
- 5, // 76: gctrpc.GoCryptoTrader.EnableSubsystem:input_type -> gctrpc.GenericSubsystemRequest
- 5, // 77: gctrpc.GoCryptoTrader.DisableSubsystem:input_type -> gctrpc.GenericSubsystemRequest
- 9, // 78: gctrpc.GoCryptoTrader.GetRPCEndpoints:input_type -> gctrpc.GetRPCEndpointsRequest
- 2, // 79: gctrpc.GoCryptoTrader.GetCommunicationRelayers:input_type -> gctrpc.GetCommunicationRelayersRequest
- 14, // 80: gctrpc.GoCryptoTrader.GetExchanges:input_type -> gctrpc.GetExchangesRequest
- 12, // 81: gctrpc.GoCryptoTrader.DisableExchange:input_type -> gctrpc.GenericExchangeNameRequest
- 12, // 82: gctrpc.GoCryptoTrader.GetExchangeInfo:input_type -> gctrpc.GenericExchangeNameRequest
- 12, // 83: gctrpc.GoCryptoTrader.GetExchangeOTPCode:input_type -> gctrpc.GenericExchangeNameRequest
- 17, // 84: gctrpc.GoCryptoTrader.GetExchangeOTPCodes:input_type -> gctrpc.GetExchangeOTPsRequest
- 12, // 85: gctrpc.GoCryptoTrader.EnableExchange:input_type -> gctrpc.GenericExchangeNameRequest
- 22, // 86: gctrpc.GoCryptoTrader.GetTicker:input_type -> gctrpc.GetTickerRequest
- 25, // 87: gctrpc.GoCryptoTrader.GetTickers:input_type -> gctrpc.GetTickersRequest
- 28, // 88: gctrpc.GoCryptoTrader.GetOrderbook:input_type -> gctrpc.GetOrderbookRequest
- 31, // 89: gctrpc.GoCryptoTrader.GetOrderbooks:input_type -> gctrpc.GetOrderbooksRequest
- 34, // 90: gctrpc.GoCryptoTrader.GetAccountInfo:input_type -> gctrpc.GetAccountInfoRequest
- 34, // 91: gctrpc.GoCryptoTrader.GetAccountInfoStream:input_type -> gctrpc.GetAccountInfoRequest
- 38, // 92: gctrpc.GoCryptoTrader.GetConfig:input_type -> gctrpc.GetConfigRequest
- 41, // 93: gctrpc.GoCryptoTrader.GetPortfolio:input_type -> gctrpc.GetPortfolioRequest
- 43, // 94: gctrpc.GoCryptoTrader.GetPortfolioSummary:input_type -> gctrpc.GetPortfolioSummaryRequest
- 50, // 95: gctrpc.GoCryptoTrader.AddPortfolioAddress:input_type -> gctrpc.AddPortfolioAddressRequest
- 52, // 96: gctrpc.GoCryptoTrader.RemovePortfolioAddress:input_type -> gctrpc.RemovePortfolioAddressRequest
- 54, // 97: gctrpc.GoCryptoTrader.GetForexProviders:input_type -> gctrpc.GetForexProvidersRequest
- 57, // 98: gctrpc.GoCryptoTrader.GetForexRates:input_type -> gctrpc.GetForexRatesRequest
- 62, // 99: gctrpc.GoCryptoTrader.GetOrders:input_type -> gctrpc.GetOrdersRequest
- 64, // 100: gctrpc.GoCryptoTrader.GetOrder:input_type -> gctrpc.GetOrderRequest
- 65, // 101: gctrpc.GoCryptoTrader.SubmitOrder:input_type -> gctrpc.SubmitOrderRequest
- 67, // 102: gctrpc.GoCryptoTrader.SimulateOrder:input_type -> gctrpc.SimulateOrderRequest
- 69, // 103: gctrpc.GoCryptoTrader.WhaleBomb:input_type -> gctrpc.WhaleBombRequest
- 70, // 104: gctrpc.GoCryptoTrader.CancelOrder:input_type -> gctrpc.CancelOrderRequest
- 72, // 105: gctrpc.GoCryptoTrader.CancelAllOrders:input_type -> gctrpc.CancelAllOrdersRequest
- 74, // 106: gctrpc.GoCryptoTrader.GetEvents:input_type -> gctrpc.GetEventsRequest
- 77, // 107: gctrpc.GoCryptoTrader.AddEvent:input_type -> gctrpc.AddEventRequest
- 79, // 108: gctrpc.GoCryptoTrader.RemoveEvent:input_type -> gctrpc.RemoveEventRequest
- 81, // 109: gctrpc.GoCryptoTrader.GetCryptocurrencyDepositAddresses:input_type -> gctrpc.GetCryptocurrencyDepositAddressesRequest
- 83, // 110: gctrpc.GoCryptoTrader.GetCryptocurrencyDepositAddress:input_type -> gctrpc.GetCryptocurrencyDepositAddressRequest
- 85, // 111: gctrpc.GoCryptoTrader.WithdrawFiatFunds:input_type -> gctrpc.WithdrawFiatRequest
- 86, // 112: gctrpc.GoCryptoTrader.WithdrawCryptocurrencyFunds:input_type -> gctrpc.WithdrawCryptoRequest
- 88, // 113: gctrpc.GoCryptoTrader.WithdrawalEventByID:input_type -> gctrpc.WithdrawalEventByIDRequest
- 90, // 114: gctrpc.GoCryptoTrader.WithdrawalEventsByExchange:input_type -> gctrpc.WithdrawalEventsByExchangeRequest
- 91, // 115: gctrpc.GoCryptoTrader.WithdrawalEventsByDate:input_type -> gctrpc.WithdrawalEventsByDateRequest
- 98, // 116: gctrpc.GoCryptoTrader.GetLoggerDetails:input_type -> gctrpc.GetLoggerDetailsRequest
- 100, // 117: gctrpc.GoCryptoTrader.SetLoggerDetails:input_type -> gctrpc.SetLoggerDetailsRequest
- 101, // 118: gctrpc.GoCryptoTrader.GetExchangePairs:input_type -> gctrpc.GetExchangePairsRequest
- 103, // 119: gctrpc.GoCryptoTrader.EnableExchangePair:input_type -> gctrpc.ExchangePairRequest
- 103, // 120: gctrpc.GoCryptoTrader.DisableExchangePair:input_type -> gctrpc.ExchangePairRequest
- 104, // 121: gctrpc.GoCryptoTrader.GetOrderbookStream:input_type -> gctrpc.GetOrderbookStreamRequest
- 105, // 122: gctrpc.GoCryptoTrader.GetExchangeOrderbookStream:input_type -> gctrpc.GetExchangeOrderbookStreamRequest
- 106, // 123: gctrpc.GoCryptoTrader.GetTickerStream:input_type -> gctrpc.GetTickerStreamRequest
- 107, // 124: gctrpc.GoCryptoTrader.GetExchangeTickerStream:input_type -> gctrpc.GetExchangeTickerStreamRequest
- 108, // 125: gctrpc.GoCryptoTrader.GetAuditEvent:input_type -> gctrpc.GetAuditEventRequest
- 115, // 126: gctrpc.GoCryptoTrader.GCTScriptExecute:input_type -> gctrpc.GCTScriptExecuteRequest
- 120, // 127: gctrpc.GoCryptoTrader.GCTScriptUpload:input_type -> gctrpc.GCTScriptUploadRequest
- 121, // 128: gctrpc.GoCryptoTrader.GCTScriptReadScript:input_type -> gctrpc.GCTScriptReadScriptRequest
- 118, // 129: gctrpc.GoCryptoTrader.GCTScriptStatus:input_type -> gctrpc.GCTScriptStatusRequest
- 122, // 130: gctrpc.GoCryptoTrader.GCTScriptQuery:input_type -> gctrpc.GCTScriptQueryRequest
- 116, // 131: gctrpc.GoCryptoTrader.GCTScriptStop:input_type -> gctrpc.GCTScriptStopRequest
- 117, // 132: gctrpc.GoCryptoTrader.GCTScriptStopAll:input_type -> gctrpc.GCTScriptStopAllRequest
- 119, // 133: gctrpc.GoCryptoTrader.GCTScriptListAll:input_type -> gctrpc.GCTScriptListAllRequest
- 123, // 134: gctrpc.GoCryptoTrader.GCTScriptAutoLoadToggle:input_type -> gctrpc.GCTScriptAutoLoadRequest
- 110, // 135: gctrpc.GoCryptoTrader.GetHistoricCandles:input_type -> gctrpc.GetHistoricCandlesRequest
- 1, // 136: gctrpc.GoCryptoTrader.GetInfo:output_type -> gctrpc.GetInfoResponse
- 8, // 137: gctrpc.GoCryptoTrader.GetSubsystems:output_type -> gctrpc.GetSusbsytemsResponse
- 6, // 138: gctrpc.GoCryptoTrader.EnableSubsystem:output_type -> gctrpc.GenericSubsystemResponse
- 6, // 139: gctrpc.GoCryptoTrader.DisableSubsystem:output_type -> gctrpc.GenericSubsystemResponse
- 11, // 140: gctrpc.GoCryptoTrader.GetRPCEndpoints:output_type -> gctrpc.GetRPCEndpointsResponse
- 4, // 141: gctrpc.GoCryptoTrader.GetCommunicationRelayers:output_type -> gctrpc.GetCommunicationRelayersResponse
- 15, // 142: gctrpc.GoCryptoTrader.GetExchanges:output_type -> gctrpc.GetExchangesResponse
- 13, // 143: gctrpc.GoCryptoTrader.DisableExchange:output_type -> gctrpc.GenericExchangeNameResponse
- 21, // 144: gctrpc.GoCryptoTrader.GetExchangeInfo:output_type -> gctrpc.GetExchangeInfoResponse
- 16, // 145: gctrpc.GoCryptoTrader.GetExchangeOTPCode:output_type -> gctrpc.GetExchangeOTPReponse
- 18, // 146: gctrpc.GoCryptoTrader.GetExchangeOTPCodes:output_type -> gctrpc.GetExchangeOTPsResponse
- 13, // 147: gctrpc.GoCryptoTrader.EnableExchange:output_type -> gctrpc.GenericExchangeNameResponse
- 24, // 148: gctrpc.GoCryptoTrader.GetTicker:output_type -> gctrpc.TickerResponse
- 27, // 149: gctrpc.GoCryptoTrader.GetTickers:output_type -> gctrpc.GetTickersResponse
- 30, // 150: gctrpc.GoCryptoTrader.GetOrderbook:output_type -> gctrpc.OrderbookResponse
- 33, // 151: gctrpc.GoCryptoTrader.GetOrderbooks:output_type -> gctrpc.GetOrderbooksResponse
- 37, // 152: gctrpc.GoCryptoTrader.GetAccountInfo:output_type -> gctrpc.GetAccountInfoResponse
- 37, // 153: gctrpc.GoCryptoTrader.GetAccountInfoStream:output_type -> gctrpc.GetAccountInfoResponse
- 39, // 154: gctrpc.GoCryptoTrader.GetConfig:output_type -> gctrpc.GetConfigResponse
- 42, // 155: gctrpc.GoCryptoTrader.GetPortfolio:output_type -> gctrpc.GetPortfolioResponse
- 49, // 156: gctrpc.GoCryptoTrader.GetPortfolioSummary:output_type -> gctrpc.GetPortfolioSummaryResponse
- 51, // 157: gctrpc.GoCryptoTrader.AddPortfolioAddress:output_type -> gctrpc.AddPortfolioAddressResponse
- 53, // 158: gctrpc.GoCryptoTrader.RemovePortfolioAddress:output_type -> gctrpc.RemovePortfolioAddressResponse
- 56, // 159: gctrpc.GoCryptoTrader.GetForexProviders:output_type -> gctrpc.GetForexProvidersResponse
- 59, // 160: gctrpc.GoCryptoTrader.GetForexRates:output_type -> gctrpc.GetForexRatesResponse
- 63, // 161: gctrpc.GoCryptoTrader.GetOrders:output_type -> gctrpc.GetOrdersResponse
- 60, // 162: gctrpc.GoCryptoTrader.GetOrder:output_type -> gctrpc.OrderDetails
- 66, // 163: gctrpc.GoCryptoTrader.SubmitOrder:output_type -> gctrpc.SubmitOrderResponse
- 68, // 164: gctrpc.GoCryptoTrader.SimulateOrder:output_type -> gctrpc.SimulateOrderResponse
- 68, // 165: gctrpc.GoCryptoTrader.WhaleBomb:output_type -> gctrpc.SimulateOrderResponse
- 71, // 166: gctrpc.GoCryptoTrader.CancelOrder:output_type -> gctrpc.CancelOrderResponse
- 73, // 167: gctrpc.GoCryptoTrader.CancelAllOrders:output_type -> gctrpc.CancelAllOrdersResponse
- 76, // 168: gctrpc.GoCryptoTrader.GetEvents:output_type -> gctrpc.GetEventsResponse
- 78, // 169: gctrpc.GoCryptoTrader.AddEvent:output_type -> gctrpc.AddEventResponse
- 80, // 170: gctrpc.GoCryptoTrader.RemoveEvent:output_type -> gctrpc.RemoveEventResponse
- 82, // 171: gctrpc.GoCryptoTrader.GetCryptocurrencyDepositAddresses:output_type -> gctrpc.GetCryptocurrencyDepositAddressesResponse
- 84, // 172: gctrpc.GoCryptoTrader.GetCryptocurrencyDepositAddress:output_type -> gctrpc.GetCryptocurrencyDepositAddressResponse
- 87, // 173: gctrpc.GoCryptoTrader.WithdrawFiatFunds:output_type -> gctrpc.WithdrawResponse
- 87, // 174: gctrpc.GoCryptoTrader.WithdrawCryptocurrencyFunds:output_type -> gctrpc.WithdrawResponse
- 89, // 175: gctrpc.GoCryptoTrader.WithdrawalEventByID:output_type -> gctrpc.WithdrawalEventByIDResponse
- 92, // 176: gctrpc.GoCryptoTrader.WithdrawalEventsByExchange:output_type -> gctrpc.WithdrawalEventsByExchangeResponse
- 92, // 177: gctrpc.GoCryptoTrader.WithdrawalEventsByDate:output_type -> gctrpc.WithdrawalEventsByExchangeResponse
- 99, // 178: gctrpc.GoCryptoTrader.GetLoggerDetails:output_type -> gctrpc.GetLoggerDetailsResponse
- 99, // 179: gctrpc.GoCryptoTrader.SetLoggerDetails:output_type -> gctrpc.GetLoggerDetailsResponse
- 102, // 180: gctrpc.GoCryptoTrader.GetExchangePairs:output_type -> gctrpc.GetExchangePairsResponse
- 13, // 181: gctrpc.GoCryptoTrader.EnableExchangePair:output_type -> gctrpc.GenericExchangeNameResponse
- 13, // 182: gctrpc.GoCryptoTrader.DisableExchangePair:output_type -> gctrpc.GenericExchangeNameResponse
- 30, // 183: gctrpc.GoCryptoTrader.GetOrderbookStream:output_type -> gctrpc.OrderbookResponse
- 30, // 184: gctrpc.GoCryptoTrader.GetExchangeOrderbookStream:output_type -> gctrpc.OrderbookResponse
- 24, // 185: gctrpc.GoCryptoTrader.GetTickerStream:output_type -> gctrpc.TickerResponse
- 24, // 186: gctrpc.GoCryptoTrader.GetExchangeTickerStream:output_type -> gctrpc.TickerResponse
- 109, // 187: gctrpc.GoCryptoTrader.GetAuditEvent:output_type -> gctrpc.GetAuditEventResponse
- 126, // 188: gctrpc.GoCryptoTrader.GCTScriptExecute:output_type -> gctrpc.GCTScriptGenericResponse
- 126, // 189: gctrpc.GoCryptoTrader.GCTScriptUpload:output_type -> gctrpc.GCTScriptGenericResponse
- 125, // 190: gctrpc.GoCryptoTrader.GCTScriptReadScript:output_type -> gctrpc.GCTScriptQueryResponse
- 124, // 191: gctrpc.GoCryptoTrader.GCTScriptStatus:output_type -> gctrpc.GCTScriptStatusResponse
- 125, // 192: gctrpc.GoCryptoTrader.GCTScriptQuery:output_type -> gctrpc.GCTScriptQueryResponse
- 126, // 193: gctrpc.GoCryptoTrader.GCTScriptStop:output_type -> gctrpc.GCTScriptGenericResponse
- 126, // 194: gctrpc.GoCryptoTrader.GCTScriptStopAll:output_type -> gctrpc.GCTScriptGenericResponse
- 124, // 195: gctrpc.GoCryptoTrader.GCTScriptListAll:output_type -> gctrpc.GCTScriptStatusResponse
- 126, // 196: gctrpc.GoCryptoTrader.GCTScriptAutoLoadToggle:output_type -> gctrpc.GCTScriptGenericResponse
- 111, // 197: gctrpc.GoCryptoTrader.GetHistoricCandles:output_type -> gctrpc.GetHistoricCandlesResponse
- 136, // [136:198] is the sub-list for method output_type
- 74, // [74:136] is the sub-list for method input_type
- 74, // [74:74] is the sub-list for extension type_name
- 74, // [74:74] is the sub-list for extension extendee
- 0, // [0:74] is the sub-list for field type_name
+func (m *WebsocketSetProxyRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_WebsocketSetProxyRequest.Marshal(b, m, deterministic)
+}
+func (m *WebsocketSetProxyRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_WebsocketSetProxyRequest.Merge(m, src)
+}
+func (m *WebsocketSetProxyRequest) XXX_Size() int {
+ return xxx_messageInfo_WebsocketSetProxyRequest.Size(m)
+}
+func (m *WebsocketSetProxyRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_WebsocketSetProxyRequest.DiscardUnknown(m)
}
-func init() { file_rpc_proto_init() }
-func file_rpc_proto_init() {
- if File_rpc_proto != nil {
- return
+var xxx_messageInfo_WebsocketSetProxyRequest proto.InternalMessageInfo
+
+func (m *WebsocketSetProxyRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
}
- if !protoimpl.UnsafeEnabled {
- file_rpc_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetInfoRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetInfoResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetCommunicationRelayersRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*CommunicationRelayer); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetCommunicationRelayersResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GenericSubsystemRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GenericSubsystemResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetSubsystemsRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetSusbsytemsResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetRPCEndpointsRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*RPCEndpoint); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetRPCEndpointsResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GenericExchangeNameRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GenericExchangeNameResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetExchangesRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetExchangesResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetExchangeOTPReponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetExchangeOTPsRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetExchangeOTPsResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*DisableExchangeRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*PairsSupported); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetExchangeInfoResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetTickerRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*CurrencyPair); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*TickerResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetTickersRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*Tickers); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetTickersResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetOrderbookRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*OrderbookItem); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*OrderbookResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetOrderbooksRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*Orderbooks); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetOrderbooksResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetAccountInfoRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*Account); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[36].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*AccountCurrencyInfo); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetAccountInfoResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetConfigRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetConfigResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*PortfolioAddress); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetPortfolioRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetPortfolioResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetPortfolioSummaryRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*Coin); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*OfflineCoinSummary); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*OnlineCoinSummary); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*OfflineCoins); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*OnlineCoins); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetPortfolioSummaryResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*AddPortfolioAddressRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*AddPortfolioAddressResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*RemovePortfolioAddressRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[53].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*RemovePortfolioAddressResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[54].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetForexProvidersRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[55].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*ForexProvider); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[56].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetForexProvidersResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[57].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetForexRatesRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[58].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*ForexRatesConversion); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[59].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetForexRatesResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[60].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*OrderDetails); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[61].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*TradeHistory); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[62].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetOrdersRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[63].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetOrdersResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[64].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetOrderRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[65].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*SubmitOrderRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[66].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*SubmitOrderResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[67].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*SimulateOrderRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[68].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*SimulateOrderResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[69].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*WhaleBombRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[70].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*CancelOrderRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[71].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*CancelOrderResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[72].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*CancelAllOrdersRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[73].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*CancelAllOrdersResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[74].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetEventsRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[75].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*ConditionParams); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[76].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetEventsResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[77].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*AddEventRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[78].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*AddEventResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[79].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*RemoveEventRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[80].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*RemoveEventResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[81].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetCryptocurrencyDepositAddressesRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[82].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetCryptocurrencyDepositAddressesResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[83].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetCryptocurrencyDepositAddressRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[84].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetCryptocurrencyDepositAddressResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[85].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*WithdrawFiatRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[86].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*WithdrawCryptoRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[87].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*WithdrawResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[88].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*WithdrawalEventByIDRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[89].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*WithdrawalEventByIDResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[90].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*WithdrawalEventsByExchangeRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[91].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*WithdrawalEventsByDateRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[92].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*WithdrawalEventsByExchangeResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[93].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*WithdrawalEventResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[94].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*WithdrawlExchangeEvent); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[95].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*WithdrawalRequestEvent); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[96].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*FiatWithdrawalEvent); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[97].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*CryptoWithdrawalEvent); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[98].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetLoggerDetailsRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[99].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetLoggerDetailsResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[100].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*SetLoggerDetailsRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[101].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetExchangePairsRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[102].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetExchangePairsResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[103].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*ExchangePairRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[104].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetOrderbookStreamRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[105].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetExchangeOrderbookStreamRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[106].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetTickerStreamRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[107].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetExchangeTickerStreamRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[108].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetAuditEventRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[109].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetAuditEventResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[110].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetHistoricCandlesRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[111].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GetHistoricCandlesResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[112].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*Candle); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[113].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*AuditEvent); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[114].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GCTScript); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[115].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GCTScriptExecuteRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[116].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GCTScriptStopRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[117].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GCTScriptStopAllRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[118].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GCTScriptStatusRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[119].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GCTScriptListAllRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[120].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GCTScriptUploadRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[121].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GCTScriptReadScriptRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[122].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GCTScriptQueryRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[123].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GCTScriptAutoLoadRequest); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[124].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GCTScriptStatusResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[125].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GCTScriptQueryResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[126].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*GCTScriptGenericResponse); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
- file_rpc_proto_msgTypes[137].Exporter = func(v interface{}, i int) interface{} {
- switch v := v.(*CancelAllOrdersResponse_Orders); i {
- case 0:
- return &v.state
- case 1:
- return &v.sizeCache
- case 2:
- return &v.unknownFields
- default:
- return nil
- }
- }
+ return ""
+}
+
+func (m *WebsocketSetProxyRequest) GetProxy() string {
+ if m != nil {
+ return m.Proxy
}
- type x struct{}
- out := protoimpl.TypeBuilder{
- File: protoimpl.DescBuilder{
- GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
- RawDescriptor: file_rpc_proto_rawDesc,
- NumEnums: 0,
- NumMessages: 141,
- NumExtensions: 0,
- NumServices: 1,
- },
- GoTypes: file_rpc_proto_goTypes,
- DependencyIndexes: file_rpc_proto_depIdxs,
- MessageInfos: file_rpc_proto_msgTypes,
- }.Build()
- File_rpc_proto = out.File
- file_rpc_proto_rawDesc = nil
- file_rpc_proto_goTypes = nil
- file_rpc_proto_depIdxs = nil
+ return ""
+}
+
+type WebsocketSetURLRequest struct {
+ Exchange string `protobuf:"bytes,1,opt,name=exchange,proto3" json:"exchange,omitempty"`
+ Url string `protobuf:"bytes,2,opt,name=url,proto3" json:"url,omitempty"`
+ XXX_NoUnkeyedLiteral struct{} `json:"-"`
+ XXX_unrecognized []byte `json:"-"`
+ XXX_sizecache int32 `json:"-"`
+}
+
+func (m *WebsocketSetURLRequest) Reset() { *m = WebsocketSetURLRequest{} }
+func (m *WebsocketSetURLRequest) String() string { return proto.CompactTextString(m) }
+func (*WebsocketSetURLRequest) ProtoMessage() {}
+func (*WebsocketSetURLRequest) Descriptor() ([]byte, []int) {
+ return fileDescriptor_77a6da22d6a3feb1, []int{133}
+}
+
+func (m *WebsocketSetURLRequest) XXX_Unmarshal(b []byte) error {
+ return xxx_messageInfo_WebsocketSetURLRequest.Unmarshal(m, b)
+}
+func (m *WebsocketSetURLRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
+ return xxx_messageInfo_WebsocketSetURLRequest.Marshal(b, m, deterministic)
+}
+func (m *WebsocketSetURLRequest) XXX_Merge(src proto.Message) {
+ xxx_messageInfo_WebsocketSetURLRequest.Merge(m, src)
+}
+func (m *WebsocketSetURLRequest) XXX_Size() int {
+ return xxx_messageInfo_WebsocketSetURLRequest.Size(m)
+}
+func (m *WebsocketSetURLRequest) XXX_DiscardUnknown() {
+ xxx_messageInfo_WebsocketSetURLRequest.DiscardUnknown(m)
+}
+
+var xxx_messageInfo_WebsocketSetURLRequest proto.InternalMessageInfo
+
+func (m *WebsocketSetURLRequest) GetExchange() string {
+ if m != nil {
+ return m.Exchange
+ }
+ return ""
+}
+
+func (m *WebsocketSetURLRequest) GetUrl() string {
+ if m != nil {
+ return m.Url
+ }
+ return ""
+}
+
+func init() {
+ proto.RegisterType((*GetInfoRequest)(nil), "gctrpc.GetInfoRequest")
+ proto.RegisterType((*GetInfoResponse)(nil), "gctrpc.GetInfoResponse")
+ proto.RegisterMapType((map[string]*RPCEndpoint)(nil), "gctrpc.GetInfoResponse.RpcEndpointsEntry")
+ proto.RegisterMapType((map[string]bool)(nil), "gctrpc.GetInfoResponse.SubsystemStatusEntry")
+ proto.RegisterType((*GetCommunicationRelayersRequest)(nil), "gctrpc.GetCommunicationRelayersRequest")
+ proto.RegisterType((*CommunicationRelayer)(nil), "gctrpc.CommunicationRelayer")
+ proto.RegisterType((*GetCommunicationRelayersResponse)(nil), "gctrpc.GetCommunicationRelayersResponse")
+ proto.RegisterMapType((map[string]*CommunicationRelayer)(nil), "gctrpc.GetCommunicationRelayersResponse.CommunicationRelayersEntry")
+ proto.RegisterType((*GenericSubsystemRequest)(nil), "gctrpc.GenericSubsystemRequest")
+ proto.RegisterType((*GetSubsystemsRequest)(nil), "gctrpc.GetSubsystemsRequest")
+ proto.RegisterType((*GetSusbsytemsResponse)(nil), "gctrpc.GetSusbsytemsResponse")
+ proto.RegisterMapType((map[string]bool)(nil), "gctrpc.GetSusbsytemsResponse.SubsystemsStatusEntry")
+ proto.RegisterType((*GetRPCEndpointsRequest)(nil), "gctrpc.GetRPCEndpointsRequest")
+ proto.RegisterType((*RPCEndpoint)(nil), "gctrpc.RPCEndpoint")
+ proto.RegisterType((*GetRPCEndpointsResponse)(nil), "gctrpc.GetRPCEndpointsResponse")
+ proto.RegisterMapType((map[string]*RPCEndpoint)(nil), "gctrpc.GetRPCEndpointsResponse.EndpointsEntry")
+ proto.RegisterType((*GenericExchangeNameRequest)(nil), "gctrpc.GenericExchangeNameRequest")
+ proto.RegisterType((*GetExchangesRequest)(nil), "gctrpc.GetExchangesRequest")
+ proto.RegisterType((*GetExchangesResponse)(nil), "gctrpc.GetExchangesResponse")
+ proto.RegisterType((*GetExchangeOTPReponse)(nil), "gctrpc.GetExchangeOTPReponse")
+ proto.RegisterType((*GetExchangeOTPsRequest)(nil), "gctrpc.GetExchangeOTPsRequest")
+ proto.RegisterType((*GetExchangeOTPsResponse)(nil), "gctrpc.GetExchangeOTPsResponse")
+ proto.RegisterMapType((map[string]string)(nil), "gctrpc.GetExchangeOTPsResponse.OtpCodesEntry")
+ proto.RegisterType((*DisableExchangeRequest)(nil), "gctrpc.DisableExchangeRequest")
+ proto.RegisterType((*PairsSupported)(nil), "gctrpc.PairsSupported")
+ proto.RegisterType((*GetExchangeInfoResponse)(nil), "gctrpc.GetExchangeInfoResponse")
+ proto.RegisterMapType((map[string]*PairsSupported)(nil), "gctrpc.GetExchangeInfoResponse.SupportedAssetsEntry")
+ proto.RegisterType((*GetTickerRequest)(nil), "gctrpc.GetTickerRequest")
+ proto.RegisterType((*CurrencyPair)(nil), "gctrpc.CurrencyPair")
+ proto.RegisterType((*TickerResponse)(nil), "gctrpc.TickerResponse")
+ proto.RegisterType((*GetTickersRequest)(nil), "gctrpc.GetTickersRequest")
+ proto.RegisterType((*Tickers)(nil), "gctrpc.Tickers")
+ proto.RegisterType((*GetTickersResponse)(nil), "gctrpc.GetTickersResponse")
+ proto.RegisterType((*GetOrderbookRequest)(nil), "gctrpc.GetOrderbookRequest")
+ proto.RegisterType((*OrderbookItem)(nil), "gctrpc.OrderbookItem")
+ proto.RegisterType((*OrderbookResponse)(nil), "gctrpc.OrderbookResponse")
+ proto.RegisterType((*GetOrderbooksRequest)(nil), "gctrpc.GetOrderbooksRequest")
+ proto.RegisterType((*Orderbooks)(nil), "gctrpc.Orderbooks")
+ proto.RegisterType((*GetOrderbooksResponse)(nil), "gctrpc.GetOrderbooksResponse")
+ proto.RegisterType((*GetAccountInfoRequest)(nil), "gctrpc.GetAccountInfoRequest")
+ proto.RegisterType((*Account)(nil), "gctrpc.Account")
+ proto.RegisterType((*AccountCurrencyInfo)(nil), "gctrpc.AccountCurrencyInfo")
+ proto.RegisterType((*GetAccountInfoResponse)(nil), "gctrpc.GetAccountInfoResponse")
+ proto.RegisterType((*GetConfigRequest)(nil), "gctrpc.GetConfigRequest")
+ proto.RegisterType((*GetConfigResponse)(nil), "gctrpc.GetConfigResponse")
+ proto.RegisterType((*PortfolioAddress)(nil), "gctrpc.PortfolioAddress")
+ proto.RegisterType((*GetPortfolioRequest)(nil), "gctrpc.GetPortfolioRequest")
+ proto.RegisterType((*GetPortfolioResponse)(nil), "gctrpc.GetPortfolioResponse")
+ proto.RegisterType((*GetPortfolioSummaryRequest)(nil), "gctrpc.GetPortfolioSummaryRequest")
+ proto.RegisterType((*Coin)(nil), "gctrpc.Coin")
+ proto.RegisterType((*OfflineCoinSummary)(nil), "gctrpc.OfflineCoinSummary")
+ proto.RegisterType((*OnlineCoinSummary)(nil), "gctrpc.OnlineCoinSummary")
+ proto.RegisterType((*OfflineCoins)(nil), "gctrpc.OfflineCoins")
+ proto.RegisterType((*OnlineCoins)(nil), "gctrpc.OnlineCoins")
+ proto.RegisterMapType((map[string]*OnlineCoinSummary)(nil), "gctrpc.OnlineCoins.CoinsEntry")
+ proto.RegisterType((*GetPortfolioSummaryResponse)(nil), "gctrpc.GetPortfolioSummaryResponse")
+ proto.RegisterMapType((map[string]*OfflineCoins)(nil), "gctrpc.GetPortfolioSummaryResponse.CoinsOfflineSummaryEntry")
+ proto.RegisterMapType((map[string]*OnlineCoins)(nil), "gctrpc.GetPortfolioSummaryResponse.CoinsOnlineSummaryEntry")
+ proto.RegisterType((*AddPortfolioAddressRequest)(nil), "gctrpc.AddPortfolioAddressRequest")
+ proto.RegisterType((*RemovePortfolioAddressRequest)(nil), "gctrpc.RemovePortfolioAddressRequest")
+ proto.RegisterType((*GetForexProvidersRequest)(nil), "gctrpc.GetForexProvidersRequest")
+ proto.RegisterType((*ForexProvider)(nil), "gctrpc.ForexProvider")
+ proto.RegisterType((*GetForexProvidersResponse)(nil), "gctrpc.GetForexProvidersResponse")
+ proto.RegisterType((*GetForexRatesRequest)(nil), "gctrpc.GetForexRatesRequest")
+ proto.RegisterType((*ForexRatesConversion)(nil), "gctrpc.ForexRatesConversion")
+ proto.RegisterType((*GetForexRatesResponse)(nil), "gctrpc.GetForexRatesResponse")
+ proto.RegisterType((*OrderDetails)(nil), "gctrpc.OrderDetails")
+ proto.RegisterType((*TradeHistory)(nil), "gctrpc.TradeHistory")
+ proto.RegisterType((*GetOrdersRequest)(nil), "gctrpc.GetOrdersRequest")
+ proto.RegisterType((*GetOrdersResponse)(nil), "gctrpc.GetOrdersResponse")
+ proto.RegisterType((*GetOrderRequest)(nil), "gctrpc.GetOrderRequest")
+ proto.RegisterType((*SubmitOrderRequest)(nil), "gctrpc.SubmitOrderRequest")
+ proto.RegisterType((*SubmitOrderResponse)(nil), "gctrpc.SubmitOrderResponse")
+ proto.RegisterType((*SimulateOrderRequest)(nil), "gctrpc.SimulateOrderRequest")
+ proto.RegisterType((*SimulateOrderResponse)(nil), "gctrpc.SimulateOrderResponse")
+ proto.RegisterType((*WhaleBombRequest)(nil), "gctrpc.WhaleBombRequest")
+ proto.RegisterType((*CancelOrderRequest)(nil), "gctrpc.CancelOrderRequest")
+ proto.RegisterType((*CancelAllOrdersRequest)(nil), "gctrpc.CancelAllOrdersRequest")
+ proto.RegisterType((*CancelAllOrdersResponse)(nil), "gctrpc.CancelAllOrdersResponse")
+ proto.RegisterType((*CancelAllOrdersResponse_Orders)(nil), "gctrpc.CancelAllOrdersResponse.Orders")
+ proto.RegisterMapType((map[string]string)(nil), "gctrpc.CancelAllOrdersResponse.Orders.OrderStatusEntry")
+ proto.RegisterType((*GetEventsRequest)(nil), "gctrpc.GetEventsRequest")
+ proto.RegisterType((*ConditionParams)(nil), "gctrpc.ConditionParams")
+ proto.RegisterType((*GetEventsResponse)(nil), "gctrpc.GetEventsResponse")
+ proto.RegisterType((*AddEventRequest)(nil), "gctrpc.AddEventRequest")
+ proto.RegisterType((*AddEventResponse)(nil), "gctrpc.AddEventResponse")
+ proto.RegisterType((*RemoveEventRequest)(nil), "gctrpc.RemoveEventRequest")
+ proto.RegisterType((*GetCryptocurrencyDepositAddressesRequest)(nil), "gctrpc.GetCryptocurrencyDepositAddressesRequest")
+ proto.RegisterType((*GetCryptocurrencyDepositAddressesResponse)(nil), "gctrpc.GetCryptocurrencyDepositAddressesResponse")
+ proto.RegisterMapType((map[string]string)(nil), "gctrpc.GetCryptocurrencyDepositAddressesResponse.AddressesEntry")
+ proto.RegisterType((*GetCryptocurrencyDepositAddressRequest)(nil), "gctrpc.GetCryptocurrencyDepositAddressRequest")
+ proto.RegisterType((*GetCryptocurrencyDepositAddressResponse)(nil), "gctrpc.GetCryptocurrencyDepositAddressResponse")
+ proto.RegisterType((*WithdrawFiatRequest)(nil), "gctrpc.WithdrawFiatRequest")
+ proto.RegisterType((*WithdrawCryptoRequest)(nil), "gctrpc.WithdrawCryptoRequest")
+ proto.RegisterType((*WithdrawResponse)(nil), "gctrpc.WithdrawResponse")
+ proto.RegisterType((*WithdrawalEventByIDRequest)(nil), "gctrpc.WithdrawalEventByIDRequest")
+ proto.RegisterType((*WithdrawalEventByIDResponse)(nil), "gctrpc.WithdrawalEventByIDResponse")
+ proto.RegisterType((*WithdrawalEventsByExchangeRequest)(nil), "gctrpc.WithdrawalEventsByExchangeRequest")
+ proto.RegisterType((*WithdrawalEventsByDateRequest)(nil), "gctrpc.WithdrawalEventsByDateRequest")
+ proto.RegisterType((*WithdrawalEventsByExchangeResponse)(nil), "gctrpc.WithdrawalEventsByExchangeResponse")
+ proto.RegisterType((*WithdrawalEventResponse)(nil), "gctrpc.WithdrawalEventResponse")
+ proto.RegisterType((*WithdrawlExchangeEvent)(nil), "gctrpc.WithdrawlExchangeEvent")
+ proto.RegisterType((*WithdrawalRequestEvent)(nil), "gctrpc.WithdrawalRequestEvent")
+ proto.RegisterType((*FiatWithdrawalEvent)(nil), "gctrpc.FiatWithdrawalEvent")
+ proto.RegisterType((*CryptoWithdrawalEvent)(nil), "gctrpc.CryptoWithdrawalEvent")
+ proto.RegisterType((*GetLoggerDetailsRequest)(nil), "gctrpc.GetLoggerDetailsRequest")
+ proto.RegisterType((*GetLoggerDetailsResponse)(nil), "gctrpc.GetLoggerDetailsResponse")
+ proto.RegisterType((*SetLoggerDetailsRequest)(nil), "gctrpc.SetLoggerDetailsRequest")
+ proto.RegisterType((*GetExchangePairsRequest)(nil), "gctrpc.GetExchangePairsRequest")
+ proto.RegisterType((*GetExchangePairsResponse)(nil), "gctrpc.GetExchangePairsResponse")
+ proto.RegisterMapType((map[string]*PairsSupported)(nil), "gctrpc.GetExchangePairsResponse.SupportedAssetsEntry")
+ proto.RegisterType((*SetExchangePairRequest)(nil), "gctrpc.SetExchangePairRequest")
+ proto.RegisterType((*GetOrderbookStreamRequest)(nil), "gctrpc.GetOrderbookStreamRequest")
+ proto.RegisterType((*GetExchangeOrderbookStreamRequest)(nil), "gctrpc.GetExchangeOrderbookStreamRequest")
+ proto.RegisterType((*GetTickerStreamRequest)(nil), "gctrpc.GetTickerStreamRequest")
+ proto.RegisterType((*GetExchangeTickerStreamRequest)(nil), "gctrpc.GetExchangeTickerStreamRequest")
+ proto.RegisterType((*GetAuditEventRequest)(nil), "gctrpc.GetAuditEventRequest")
+ proto.RegisterType((*GetAuditEventResponse)(nil), "gctrpc.GetAuditEventResponse")
+ proto.RegisterType((*GetHistoricCandlesRequest)(nil), "gctrpc.GetHistoricCandlesRequest")
+ proto.RegisterType((*GetHistoricCandlesResponse)(nil), "gctrpc.GetHistoricCandlesResponse")
+ proto.RegisterType((*Candle)(nil), "gctrpc.Candle")
+ proto.RegisterType((*AuditEvent)(nil), "gctrpc.AuditEvent")
+ proto.RegisterType((*GCTScript)(nil), "gctrpc.GCTScript")
+ proto.RegisterType((*GCTScriptExecuteRequest)(nil), "gctrpc.GCTScriptExecuteRequest")
+ proto.RegisterType((*GCTScriptStopRequest)(nil), "gctrpc.GCTScriptStopRequest")
+ proto.RegisterType((*GCTScriptStopAllRequest)(nil), "gctrpc.GCTScriptStopAllRequest")
+ proto.RegisterType((*GCTScriptStatusRequest)(nil), "gctrpc.GCTScriptStatusRequest")
+ proto.RegisterType((*GCTScriptListAllRequest)(nil), "gctrpc.GCTScriptListAllRequest")
+ proto.RegisterType((*GCTScriptUploadRequest)(nil), "gctrpc.GCTScriptUploadRequest")
+ proto.RegisterType((*GCTScriptReadScriptRequest)(nil), "gctrpc.GCTScriptReadScriptRequest")
+ proto.RegisterType((*GCTScriptQueryRequest)(nil), "gctrpc.GCTScriptQueryRequest")
+ proto.RegisterType((*GCTScriptAutoLoadRequest)(nil), "gctrpc.GCTScriptAutoLoadRequest")
+ proto.RegisterType((*GCTScriptStatusResponse)(nil), "gctrpc.GCTScriptStatusResponse")
+ proto.RegisterType((*GCTScriptQueryResponse)(nil), "gctrpc.GCTScriptQueryResponse")
+ proto.RegisterType((*GenericResponse)(nil), "gctrpc.GenericResponse")
+ proto.RegisterType((*SetExchangeAssetRequest)(nil), "gctrpc.SetExchangeAssetRequest")
+ proto.RegisterType((*SetExchangeAllPairsRequest)(nil), "gctrpc.SetExchangeAllPairsRequest")
+ proto.RegisterType((*UpdateExchangeSupportedPairsRequest)(nil), "gctrpc.UpdateExchangeSupportedPairsRequest")
+ proto.RegisterType((*GetExchangeAssetsRequest)(nil), "gctrpc.GetExchangeAssetsRequest")
+ proto.RegisterType((*GetExchangeAssetsResponse)(nil), "gctrpc.GetExchangeAssetsResponse")
+ proto.RegisterType((*WebsocketGetInfoRequest)(nil), "gctrpc.WebsocketGetInfoRequest")
+ proto.RegisterType((*WebsocketGetInfoResponse)(nil), "gctrpc.WebsocketGetInfoResponse")
+ proto.RegisterType((*WebsocketSetEnabledRequest)(nil), "gctrpc.WebsocketSetEnabledRequest")
+ proto.RegisterType((*WebsocketGetSubscriptionsRequest)(nil), "gctrpc.WebsocketGetSubscriptionsRequest")
+ proto.RegisterType((*WebsocketSubscription)(nil), "gctrpc.WebsocketSubscription")
+ proto.RegisterType((*WebsocketGetSubscriptionsResponse)(nil), "gctrpc.WebsocketGetSubscriptionsResponse")
+ proto.RegisterType((*WebsocketSetProxyRequest)(nil), "gctrpc.WebsocketSetProxyRequest")
+ proto.RegisterType((*WebsocketSetURLRequest)(nil), "gctrpc.WebsocketSetURLRequest")
+}
+
+func init() {
+ proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1)
+}
+
+var fileDescriptor_77a6da22d6a3feb1 = []byte{
+ // 6423 bytes of a gzipped FileDescriptorProto
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x7c, 0x4d, 0x8c, 0x1c, 0xc7,
+ 0x75, 0x30, 0x7a, 0x66, 0xf6, 0x67, 0xde, 0xfe, 0xb2, 0xf6, 0x6f, 0x38, 0x5c, 0x72, 0xc9, 0x92,
+ 0x45, 0x91, 0xfa, 0x59, 0x4a, 0x94, 0x64, 0xcb, 0xf2, 0xdf, 0xb7, 0x5c, 0x4a, 0x6b, 0xda, 0xb4,
+ 0x44, 0xf7, 0x2e, 0x25, 0x40, 0xfe, 0xa0, 0x49, 0xcf, 0x74, 0xed, 0x6e, 0x9b, 0x3d, 0xdd, 0xa3,
+ 0xee, 0x9e, 0x5d, 0xae, 0x8d, 0xc0, 0x86, 0x91, 0x04, 0x01, 0x1c, 0x24, 0x08, 0x0c, 0xc3, 0x09,
+ 0x90, 0x53, 0x4e, 0x41, 0x2e, 0x06, 0x82, 0x1c, 0x82, 0x1c, 0x8c, 0x5c, 0x83, 0x00, 0xb9, 0x04,
+ 0x08, 0x7c, 0xc9, 0x29, 0x41, 0x0e, 0x41, 0x92, 0x43, 0x80, 0x5c, 0x72, 0x0a, 0xea, 0xd5, 0x4f,
+ 0x57, 0x75, 0xf7, 0xcc, 0xce, 0xca, 0xb4, 0x72, 0x21, 0xa7, 0x5f, 0xbd, 0x7a, 0xef, 0xd5, 0xab,
+ 0x57, 0xaf, 0x5e, 0xbd, 0x7a, 0xb5, 0xd0, 0x4c, 0x06, 0xbd, 0xed, 0x41, 0x12, 0x67, 0x31, 0x99,
+ 0x3e, 0xea, 0x65, 0xc9, 0xa0, 0xd7, 0xde, 0x3c, 0x8a, 0xe3, 0xa3, 0x90, 0xdd, 0xf1, 0x06, 0xc1,
+ 0x1d, 0x2f, 0x8a, 0xe2, 0xcc, 0xcb, 0x82, 0x38, 0x4a, 0x05, 0x56, 0x7b, 0x4b, 0xb6, 0xe2, 0x57,
+ 0x77, 0x78, 0x78, 0x27, 0x0b, 0xfa, 0x2c, 0xcd, 0xbc, 0xfe, 0x40, 0x20, 0xd0, 0x65, 0x58, 0xdc,
+ 0x63, 0xd9, 0x83, 0xe8, 0x30, 0x76, 0xd9, 0x27, 0x43, 0x96, 0x66, 0xf4, 0x2f, 0x1b, 0xb0, 0xa4,
+ 0x41, 0xe9, 0x20, 0x8e, 0x52, 0x46, 0xd6, 0x61, 0x7a, 0x38, 0xe0, 0x5d, 0x5b, 0xce, 0x75, 0xe7,
+ 0x56, 0xd3, 0x95, 0x5f, 0xe4, 0x0e, 0xac, 0x78, 0x27, 0x5e, 0x10, 0x7a, 0xdd, 0x90, 0x75, 0xd8,
+ 0xd3, 0xde, 0xb1, 0x17, 0x1d, 0xb1, 0xb4, 0x55, 0xbb, 0xee, 0xdc, 0xaa, 0xbb, 0x44, 0x37, 0xbd,
+ 0xa3, 0x5a, 0xc8, 0x4b, 0x70, 0x89, 0x45, 0x1c, 0xe4, 0x1b, 0xe8, 0x75, 0x44, 0x5f, 0x96, 0x0d,
+ 0x39, 0xf2, 0x1b, 0xb0, 0xee, 0xb3, 0x43, 0x6f, 0x18, 0x66, 0x9d, 0xc3, 0x38, 0x61, 0x4f, 0x3b,
+ 0x83, 0x24, 0x3e, 0x09, 0x7c, 0x96, 0xb4, 0x1a, 0x28, 0xc5, 0xaa, 0x6c, 0x7d, 0x97, 0x37, 0x3e,
+ 0x92, 0x6d, 0xe4, 0x2e, 0xac, 0xe9, 0x5e, 0x81, 0x97, 0x75, 0x7a, 0xc3, 0x24, 0x61, 0x51, 0xef,
+ 0xac, 0x35, 0x85, 0x9d, 0x56, 0x54, 0xa7, 0xc0, 0xcb, 0x76, 0x65, 0x13, 0xf9, 0x10, 0x96, 0xd3,
+ 0x61, 0x37, 0x3d, 0x4b, 0x33, 0xd6, 0xef, 0xa4, 0x99, 0x97, 0x0d, 0xd3, 0xd6, 0xf4, 0xf5, 0xfa,
+ 0xad, 0xb9, 0xbb, 0x2f, 0x6f, 0x0b, 0x3d, 0x6f, 0x17, 0x54, 0xb2, 0xbd, 0xaf, 0xf0, 0xf7, 0x11,
+ 0xfd, 0x9d, 0x28, 0x4b, 0xce, 0xdc, 0xa5, 0xd4, 0x86, 0x92, 0xf7, 0x60, 0x21, 0x19, 0xf4, 0x3a,
+ 0x2c, 0xf2, 0x07, 0x71, 0x10, 0x65, 0x69, 0x6b, 0x06, 0xa9, 0xde, 0x1e, 0x45, 0xd5, 0x1d, 0xf4,
+ 0xde, 0x51, 0xb8, 0x82, 0xe4, 0x7c, 0x62, 0x80, 0xda, 0xf7, 0x60, 0xb5, 0x8a, 0x31, 0x59, 0x86,
+ 0xfa, 0x13, 0x76, 0x26, 0x67, 0x87, 0xff, 0x24, 0xab, 0x30, 0x75, 0xe2, 0x85, 0x43, 0x86, 0x93,
+ 0x31, 0xeb, 0x8a, 0x8f, 0xb7, 0x6b, 0x6f, 0x39, 0xed, 0x03, 0xb8, 0x54, 0x62, 0x53, 0x41, 0xe0,
+ 0xb6, 0x49, 0x60, 0xee, 0xee, 0x8a, 0x12, 0xd9, 0x7d, 0xb4, 0xab, 0xfa, 0x1a, 0x54, 0xe9, 0x0d,
+ 0xd8, 0xda, 0x63, 0xd9, 0x6e, 0xdc, 0xef, 0x0f, 0xa3, 0xa0, 0x87, 0x46, 0xe8, 0xb2, 0xd0, 0x3b,
+ 0x63, 0x49, 0xaa, 0x2c, 0xeb, 0x3d, 0x58, 0xad, 0x6a, 0x27, 0x2d, 0x98, 0x91, 0x73, 0x8f, 0xfc,
+ 0x67, 0x5d, 0xf5, 0x49, 0x36, 0xa1, 0xd9, 0x8b, 0xa3, 0x88, 0xf5, 0x32, 0xe6, 0xcb, 0x81, 0xe4,
+ 0x00, 0xfa, 0x3b, 0x35, 0xb8, 0x3e, 0x9a, 0xa7, 0x34, 0xdd, 0xef, 0xc1, 0x7a, 0xcf, 0x44, 0xe8,
+ 0x24, 0x12, 0xa3, 0xe5, 0xe0, 0x54, 0xec, 0x1a, 0x53, 0x31, 0x96, 0xd2, 0x76, 0x65, 0xab, 0x98,
+ 0xa4, 0xb5, 0x5e, 0x55, 0x5b, 0xfb, 0x10, 0xda, 0xa3, 0x3b, 0x55, 0xa8, 0xfc, 0xae, 0xad, 0xf2,
+ 0x4d, 0x25, 0x5a, 0x15, 0x11, 0x53, 0xf7, 0x5f, 0x80, 0x8d, 0x3d, 0x16, 0xb1, 0x24, 0xe8, 0x69,
+ 0xe3, 0x90, 0x3a, 0xe7, 0x1a, 0xd4, 0x36, 0x29, 0x59, 0xe5, 0x00, 0xba, 0x0e, 0xab, 0x7b, 0x2c,
+ 0xd3, 0x9d, 0xf4, 0x4c, 0xfd, 0xc2, 0x81, 0x35, 0x6c, 0x48, 0xbb, 0xe9, 0x99, 0x68, 0x90, 0xea,
+ 0xfc, 0x0d, 0xb8, 0xa4, 0xbb, 0xa7, 0x6a, 0xa9, 0x08, 0x4d, 0xbe, 0x6e, 0x68, 0xb2, 0xdc, 0x33,
+ 0x5f, 0x30, 0xa9, 0xb9, 0x62, 0xf2, 0x75, 0x27, 0xc1, 0xed, 0x5d, 0x58, 0xab, 0x44, 0xbd, 0x88,
+ 0x8d, 0xd3, 0x16, 0xac, 0xef, 0xb1, 0xcc, 0x30, 0x55, 0xc3, 0x08, 0xe7, 0x0c, 0x30, 0xb7, 0xbd,
+ 0x34, 0xf3, 0x92, 0x2c, 0xb7, 0x3d, 0xf9, 0x49, 0x9e, 0x87, 0xc5, 0x30, 0x48, 0x33, 0x16, 0x75,
+ 0x3c, 0xdf, 0x4f, 0x58, 0x2a, 0xdc, 0x5a, 0xd3, 0x5d, 0x10, 0xd0, 0x1d, 0x01, 0xa4, 0x7f, 0xed,
+ 0x70, 0xe5, 0x17, 0x58, 0x49, 0x65, 0x3d, 0x84, 0x66, 0xbe, 0xf2, 0x85, 0x92, 0xb6, 0x0d, 0x25,
+ 0x55, 0xf5, 0xd9, 0x2e, 0x2c, 0xff, 0x9c, 0x40, 0xfb, 0xdb, 0xb0, 0xf8, 0xac, 0x17, 0xed, 0x5b,
+ 0xd0, 0x96, 0x86, 0xa3, 0xbc, 0xee, 0x7b, 0x5e, 0x9f, 0x29, 0xdb, 0x69, 0xc3, 0xac, 0x72, 0xd2,
+ 0x92, 0x87, 0xfe, 0xa6, 0x77, 0x60, 0x65, 0x8f, 0x65, 0xda, 0x57, 0xab, 0x2e, 0x23, 0x97, 0x32,
+ 0x7d, 0x03, 0x4d, 0xcd, 0xe8, 0x20, 0x75, 0xb4, 0x09, 0xcd, 0x7c, 0x27, 0x90, 0x06, 0xaa, 0x01,
+ 0xf4, 0x2e, 0xda, 0xa1, 0xea, 0xf5, 0xfe, 0xc1, 0x23, 0x97, 0x89, 0x6e, 0x97, 0x61, 0x36, 0xce,
+ 0x06, 0x9d, 0x5e, 0xec, 0x2b, 0xd9, 0x66, 0xe2, 0x6c, 0xb0, 0x1b, 0xfb, 0x4c, 0xce, 0xbd, 0xd1,
+ 0x47, 0xcf, 0xfd, 0x9f, 0x8a, 0xb9, 0xb2, 0x9b, 0xa4, 0x1c, 0xdf, 0x80, 0xa6, 0x22, 0xa8, 0xe6,
+ 0xea, 0x15, 0x63, 0xae, 0xaa, 0xfa, 0x6c, 0xbf, 0x2f, 0x38, 0xca, 0xa9, 0x9a, 0x95, 0x02, 0xa4,
+ 0xed, 0x2f, 0xc1, 0x82, 0xd5, 0x74, 0x9e, 0xe9, 0x36, 0xcd, 0x39, 0x79, 0x03, 0xd6, 0xef, 0x07,
+ 0xa9, 0xb9, 0x6d, 0x4e, 0x32, 0x1f, 0x1f, 0xc3, 0xe2, 0x23, 0x2f, 0x48, 0xd2, 0xfd, 0xe1, 0x60,
+ 0x10, 0xa3, 0xfd, 0xbe, 0x00, 0x4b, 0xf9, 0xde, 0x3c, 0xe0, 0x6d, 0xb2, 0xd3, 0xa2, 0x06, 0x63,
+ 0x0f, 0xf2, 0x1c, 0x2c, 0xa8, 0x3d, 0x59, 0xa0, 0x09, 0x91, 0xe6, 0x25, 0x10, 0x91, 0xe8, 0x8f,
+ 0x1a, 0x96, 0xea, 0xac, 0xe8, 0x80, 0x40, 0x23, 0xf2, 0x74, 0x6c, 0x80, 0xbf, 0x4d, 0x43, 0xa8,
+ 0xd9, 0x3e, 0xbd, 0x05, 0x33, 0x27, 0x2c, 0xe9, 0xc6, 0x29, 0xc3, 0x8d, 0x7f, 0xd6, 0x55, 0x9f,
+ 0x5c, 0x90, 0x61, 0x1a, 0x44, 0x47, 0x9d, 0xd4, 0x8b, 0xfc, 0x6e, 0xfc, 0x14, 0xb7, 0xf9, 0x59,
+ 0x77, 0x1e, 0x81, 0xfb, 0x02, 0x46, 0x6e, 0xc0, 0xfc, 0x71, 0x96, 0x0d, 0x3a, 0x3c, 0xfe, 0x88,
+ 0x87, 0x99, 0xdc, 0xd5, 0xe7, 0x38, 0xec, 0x40, 0x80, 0xf8, 0xca, 0x45, 0x94, 0x61, 0xca, 0x12,
+ 0xef, 0x88, 0x45, 0x59, 0x6b, 0x5a, 0xac, 0x5c, 0x0e, 0x7d, 0xac, 0x80, 0xe4, 0x2a, 0x00, 0xa2,
+ 0x0d, 0x92, 0xf8, 0xe9, 0x59, 0x6b, 0x46, 0x98, 0x1e, 0x87, 0x3c, 0xe2, 0x00, 0xae, 0xbf, 0xae,
+ 0x97, 0x32, 0x15, 0x3f, 0x04, 0x2c, 0x6d, 0xcd, 0x0a, 0xfd, 0x71, 0xf0, 0xae, 0x86, 0x92, 0x0e,
+ 0x0f, 0x1e, 0xa4, 0xd6, 0x3b, 0x5e, 0x9a, 0xb2, 0x2c, 0x6d, 0x35, 0xd1, 0x80, 0xde, 0xa8, 0x30,
+ 0xa0, 0x42, 0x10, 0x21, 0xfb, 0xed, 0x60, 0x37, 0x1d, 0x44, 0x58, 0x50, 0x1e, 0x34, 0x79, 0xc3,
+ 0xec, 0x98, 0x45, 0x19, 0xdf, 0x02, 0x38, 0x93, 0x41, 0xd0, 0x02, 0xd4, 0xcd, 0xb2, 0xd5, 0xb0,
+ 0x33, 0x08, 0xda, 0x1f, 0xf1, 0x08, 0xa1, 0x4c, 0xb5, 0xc2, 0x04, 0x5f, 0xb6, 0x7d, 0xc5, 0xba,
+ 0x12, 0xd6, 0xb6, 0x23, 0xd3, 0x34, 0x4f, 0x61, 0x79, 0x8f, 0x65, 0x07, 0x41, 0xef, 0x09, 0x4b,
+ 0x26, 0x30, 0x4a, 0x72, 0x0b, 0x1a, 0xdc, 0xa2, 0x24, 0x83, 0x55, 0xbd, 0x9d, 0xc9, 0xb0, 0x8b,
+ 0x33, 0x72, 0x11, 0x83, 0xcf, 0x05, 0x6a, 0xae, 0x93, 0x9d, 0x0d, 0x84, 0x5d, 0x34, 0xdd, 0x26,
+ 0x42, 0x0e, 0xce, 0x06, 0x8c, 0x7e, 0x00, 0xf3, 0x66, 0x27, 0xee, 0x34, 0x7c, 0x16, 0x06, 0xfd,
+ 0x20, 0x63, 0x89, 0x72, 0x1a, 0x1a, 0xc0, 0xed, 0x91, 0x4f, 0x91, 0xb4, 0x63, 0xfc, 0xcd, 0xd7,
+ 0xdb, 0x27, 0xc3, 0x38, 0x53, 0xb4, 0xc5, 0x07, 0xfd, 0x69, 0x0d, 0x16, 0xd5, 0x70, 0xa4, 0x31,
+ 0x2b, 0x99, 0x9d, 0x73, 0x65, 0xbe, 0x01, 0xf3, 0xa1, 0x97, 0x66, 0x9d, 0xe1, 0xc0, 0xf7, 0x54,
+ 0x7c, 0x52, 0x77, 0xe7, 0x38, 0xec, 0xb1, 0x00, 0x71, 0x8b, 0x56, 0xe1, 0x27, 0xae, 0x2d, 0xc9,
+ 0x7d, 0xbe, 0x67, 0x0e, 0x86, 0x40, 0x83, 0xf7, 0x41, 0x6b, 0x77, 0x5c, 0xfc, 0xcd, 0x61, 0xc7,
+ 0xc1, 0xd1, 0x31, 0x5a, 0xb7, 0xe3, 0xe2, 0x6f, 0x3e, 0x83, 0x61, 0x7c, 0x8a, 0xb6, 0xec, 0xb8,
+ 0xfc, 0x27, 0x87, 0x74, 0x03, 0x1f, 0x4d, 0xd7, 0x71, 0xf9, 0x4f, 0x0e, 0xf1, 0xd2, 0x27, 0x68,
+ 0xa8, 0x8e, 0xcb, 0x7f, 0xf2, 0xd0, 0xfd, 0x24, 0x0e, 0x87, 0x7d, 0xd6, 0x6a, 0x22, 0x50, 0x7e,
+ 0x91, 0x2b, 0xd0, 0x1c, 0x24, 0x41, 0x8f, 0x75, 0xbc, 0xec, 0x18, 0x8d, 0xc9, 0x71, 0x67, 0x11,
+ 0xb0, 0x93, 0x1d, 0xd3, 0x15, 0xb8, 0xa4, 0x27, 0x5a, 0x7b, 0xcf, 0x0f, 0x61, 0x46, 0x42, 0xc6,
+ 0x4e, 0xfa, 0xab, 0x30, 0x93, 0x09, 0xb4, 0x56, 0x0d, 0x57, 0x81, 0x36, 0x2c, 0x5b, 0xd3, 0xae,
+ 0x42, 0xa3, 0x5f, 0x03, 0x62, 0x72, 0x93, 0x13, 0x71, 0x3b, 0xa7, 0x23, 0xdc, 0xf1, 0x92, 0x4d,
+ 0x27, 0xcd, 0x09, 0x7c, 0x0f, 0x37, 0xa3, 0xf7, 0x13, 0x9f, 0x3b, 0x92, 0xf8, 0xc9, 0x67, 0x6a,
+ 0x9a, 0xdf, 0x82, 0x05, 0xcd, 0xf8, 0x41, 0xc6, 0xfa, 0x5c, 0xe1, 0x5e, 0x3f, 0x1e, 0x46, 0x19,
+ 0xf2, 0x74, 0x5c, 0xf9, 0xc5, 0x2d, 0x10, 0xf5, 0x8b, 0x2c, 0x1d, 0x57, 0x7c, 0x90, 0x45, 0xa8,
+ 0x05, 0xbe, 0x3c, 0x01, 0xd5, 0x02, 0x9f, 0xfe, 0x8f, 0x03, 0x97, 0x8c, 0x81, 0x5c, 0xd8, 0x28,
+ 0x4b, 0x16, 0x57, 0xab, 0xb0, 0xb8, 0xdb, 0xd0, 0xe8, 0x06, 0x3e, 0x3f, 0x78, 0x71, 0xbd, 0xae,
+ 0x29, 0x72, 0xd6, 0x38, 0x5c, 0x44, 0xe1, 0xa8, 0x5e, 0xfa, 0x24, 0x6d, 0x35, 0xc6, 0xa2, 0x72,
+ 0x94, 0xd2, 0x7a, 0x98, 0x2a, 0xaf, 0x07, 0x5b, 0x97, 0xd3, 0x45, 0x5d, 0x8a, 0x70, 0x54, 0xd3,
+ 0xd6, 0x96, 0xd7, 0x03, 0xc8, 0x81, 0x63, 0xa7, 0xf5, 0x8b, 0x00, 0xb1, 0xc6, 0x94, 0xf6, 0x77,
+ 0xb9, 0x24, 0xb4, 0x36, 0x41, 0x03, 0x99, 0x7e, 0x13, 0x43, 0x0d, 0x93, 0xb9, 0x54, 0xfe, 0x5d,
+ 0x8b, 0xa6, 0xb0, 0x45, 0x52, 0xa2, 0x99, 0x5a, 0xc4, 0x5e, 0x47, 0x62, 0x3b, 0xbd, 0x1e, 0x9f,
+ 0x7a, 0xe3, 0x74, 0x3d, 0x76, 0x0f, 0xff, 0x00, 0x66, 0x64, 0x0f, 0x69, 0x16, 0x02, 0xa1, 0x16,
+ 0xf8, 0xe4, 0x4b, 0x00, 0xc6, 0x3e, 0x24, 0xc6, 0x75, 0x45, 0xc9, 0x20, 0x3b, 0x29, 0x6b, 0x40,
+ 0x76, 0x06, 0x3a, 0x3d, 0x84, 0x95, 0x0a, 0x14, 0x2e, 0x8a, 0x3e, 0x1b, 0x4b, 0x51, 0xd4, 0x37,
+ 0xd9, 0x82, 0xb9, 0x2c, 0xce, 0xbc, 0xb0, 0x93, 0xef, 0x10, 0x8e, 0x0b, 0x08, 0xfa, 0x80, 0x43,
+ 0xd0, 0x41, 0xc5, 0xa1, 0xb0, 0x5c, 0xee, 0xa0, 0xe2, 0xd0, 0xa7, 0x1e, 0x06, 0x5e, 0xd6, 0xa0,
+ 0xa5, 0x0a, 0xc7, 0x4d, 0xd9, 0x4b, 0x30, 0xeb, 0x89, 0x2e, 0x6a, 0x60, 0x4b, 0x85, 0x81, 0xb9,
+ 0x1a, 0x81, 0x12, 0xdc, 0x81, 0x76, 0xe3, 0xe8, 0x30, 0x38, 0x52, 0xd6, 0xf1, 0x02, 0x3a, 0x2b,
+ 0x05, 0xcb, 0x63, 0x12, 0xdf, 0xcb, 0x3c, 0xe4, 0x36, 0xef, 0xe2, 0x6f, 0xfa, 0xdb, 0x0e, 0x2c,
+ 0x3f, 0x8a, 0x93, 0xec, 0x30, 0x0e, 0x83, 0x58, 0xc6, 0xef, 0x3c, 0x1c, 0x51, 0xf1, 0xbd, 0x8c,
+ 0x23, 0xe5, 0x27, 0xf7, 0x90, 0xbd, 0x38, 0x88, 0x84, 0xad, 0xd6, 0xa4, 0x82, 0xe2, 0x20, 0xe2,
+ 0xa6, 0x4a, 0xae, 0xc3, 0x9c, 0xcf, 0xd2, 0x5e, 0x12, 0x0c, 0xf8, 0x99, 0x4c, 0xba, 0x05, 0x13,
+ 0xc4, 0x09, 0x77, 0xbd, 0xd0, 0x8b, 0x7a, 0x4c, 0x7a, 0x76, 0xf5, 0x49, 0xd7, 0xd0, 0x5d, 0x69,
+ 0x49, 0x8c, 0xe3, 0xb1, 0x0d, 0x96, 0x43, 0xf9, 0x3c, 0x34, 0x07, 0x0a, 0x28, 0xcd, 0xaf, 0xa5,
+ 0xf7, 0xea, 0xc2, 0x70, 0xdc, 0x1c, 0x95, 0x6e, 0xf2, 0xe0, 0x3e, 0xa7, 0xb7, 0x3f, 0xec, 0xf7,
+ 0xbd, 0xe4, 0x4c, 0x71, 0x8b, 0xa0, 0xb1, 0x1b, 0x07, 0x11, 0x57, 0x14, 0x1f, 0x94, 0x0a, 0xde,
+ 0xf8, 0x6f, 0x53, 0xf4, 0x9a, 0x25, 0xba, 0xa9, 0xad, 0xba, 0xad, 0xad, 0x6b, 0x00, 0x03, 0x96,
+ 0xf4, 0x58, 0x94, 0x79, 0x47, 0x6a, 0xc4, 0x06, 0x84, 0x1e, 0x03, 0x79, 0xff, 0xf0, 0x30, 0x0c,
+ 0x22, 0xc6, 0xd9, 0x4a, 0x61, 0xc6, 0x68, 0x7f, 0xb4, 0x0c, 0x36, 0xa7, 0x7a, 0x89, 0xd3, 0xb7,
+ 0xe0, 0xd2, 0xfb, 0x51, 0x05, 0x23, 0x45, 0xce, 0x19, 0x47, 0xae, 0x56, 0x22, 0xf7, 0x75, 0x98,
+ 0x37, 0x04, 0x4f, 0xc9, 0x5b, 0xd0, 0x94, 0x32, 0xea, 0x83, 0x42, 0x5b, 0x7b, 0x83, 0xd2, 0x08,
+ 0xdd, 0x1c, 0x99, 0xfe, 0x91, 0x03, 0x73, 0xb9, 0x64, 0x29, 0x79, 0x03, 0xa6, 0xb8, 0xba, 0x15,
+ 0x95, 0x6b, 0x9a, 0x4a, 0x8e, 0xb3, 0x8d, 0xff, 0x8a, 0xb8, 0x50, 0x20, 0xb7, 0xf7, 0x01, 0x72,
+ 0x60, 0x45, 0x58, 0x77, 0xc7, 0x0e, 0xeb, 0x2e, 0x97, 0xa9, 0x2a, 0xd1, 0x8c, 0xc8, 0xee, 0xef,
+ 0x1a, 0x70, 0xa5, 0xd2, 0x58, 0xa4, 0x0d, 0xbe, 0x02, 0x73, 0x62, 0x2d, 0x70, 0x0f, 0xa0, 0x04,
+ 0x9e, 0xcf, 0xf3, 0x13, 0x41, 0xe4, 0x02, 0xae, 0x0d, 0x6c, 0x27, 0xaf, 0xc1, 0x02, 0x0a, 0xdb,
+ 0x89, 0x85, 0x42, 0xe4, 0xc2, 0xb6, 0x3b, 0xcc, 0x23, 0x8a, 0x54, 0x19, 0x19, 0xc0, 0x9a, 0xd5,
+ 0xa5, 0x93, 0x0a, 0x11, 0xe4, 0x26, 0xf5, 0x65, 0x23, 0x94, 0x1e, 0x25, 0xa5, 0x50, 0x96, 0x24,
+ 0x28, 0xdb, 0x84, 0xea, 0x56, 0x7a, 0xe5, 0x16, 0x72, 0x07, 0xe6, 0x25, 0x47, 0xd4, 0x8c, 0xdc,
+ 0xe2, 0x6c, 0x19, 0xe7, 0x44, 0x47, 0x44, 0x20, 0x7d, 0x58, 0x35, 0x3b, 0x68, 0x09, 0xa7, 0xb0,
+ 0xe3, 0x97, 0x26, 0x97, 0x30, 0x2a, 0x09, 0x48, 0x7a, 0xa5, 0x86, 0xf6, 0xff, 0x87, 0xd6, 0xa8,
+ 0x01, 0x55, 0x4c, 0xfb, 0x8b, 0xf6, 0xb4, 0xaf, 0x56, 0x98, 0x64, 0x6a, 0x66, 0x01, 0x3f, 0x82,
+ 0x8d, 0x11, 0xc2, 0x5c, 0x20, 0xad, 0x60, 0x58, 0xaa, 0x69, 0x4d, 0xff, 0xec, 0x40, 0x7b, 0xc7,
+ 0xf7, 0x4b, 0xce, 0x29, 0x4f, 0x12, 0x7c, 0xc6, 0x2e, 0x97, 0xdc, 0x81, 0x95, 0xfc, 0x8c, 0x96,
+ 0xe7, 0x1b, 0xc4, 0xe1, 0x91, 0xe8, 0xa6, 0x3c, 0xf7, 0x7c, 0x83, 0x1b, 0x47, 0xe8, 0x77, 0xd2,
+ 0x2c, 0xe6, 0xc7, 0x45, 0x8c, 0x55, 0x66, 0xb9, 0x39, 0x84, 0xfe, 0xbe, 0x00, 0xd1, 0xa7, 0x70,
+ 0xd5, 0x65, 0xfd, 0xf8, 0x84, 0x7d, 0xd6, 0xe3, 0xa4, 0x6d, 0x68, 0xed, 0x31, 0x3b, 0xed, 0xad,
+ 0x63, 0xa5, 0xff, 0x70, 0x60, 0xc1, 0x4e, 0x88, 0x3f, 0xab, 0xe3, 0xf9, 0xcb, 0x40, 0x12, 0x96,
+ 0x66, 0x9d, 0x41, 0x1c, 0x86, 0xfc, 0x94, 0xee, 0xb3, 0xd0, 0x3b, 0x93, 0xa9, 0xf8, 0x65, 0xde,
+ 0xf2, 0x48, 0x34, 0xdc, 0xe7, 0x70, 0xb2, 0x01, 0x33, 0xde, 0x20, 0xe8, 0x70, 0x43, 0x12, 0x5a,
+ 0x9e, 0xf6, 0x06, 0xc1, 0x37, 0xd9, 0x19, 0xa1, 0xb0, 0x20, 0x1b, 0x3a, 0x21, 0x3b, 0x61, 0x21,
+ 0xaa, 0xb6, 0xee, 0xce, 0x89, 0xe6, 0x87, 0x1c, 0x44, 0x6e, 0xc3, 0xf2, 0x20, 0x09, 0xb8, 0x45,
+ 0xe6, 0x39, 0xff, 0x19, 0x94, 0x66, 0x49, 0xc2, 0xd5, 0xe8, 0xe8, 0x77, 0xe0, 0x72, 0x85, 0x2e,
+ 0xa4, 0xdb, 0xfa, 0x2a, 0x2c, 0xd9, 0x37, 0x07, 0xca, 0x75, 0xe9, 0x40, 0xd6, 0xea, 0xe8, 0x2e,
+ 0x1e, 0x5a, 0x74, 0x64, 0x40, 0x8a, 0x38, 0xae, 0x97, 0xe9, 0x34, 0x17, 0xfd, 0x04, 0x56, 0x73,
+ 0xe0, 0x6e, 0x1c, 0x9d, 0xb0, 0x24, 0xe5, 0x06, 0x48, 0xa0, 0x71, 0x98, 0xc4, 0x2a, 0xd1, 0x8a,
+ 0xbf, 0x79, 0x28, 0x97, 0xc5, 0x72, 0x92, 0x6b, 0x59, 0xcc, 0x71, 0x12, 0x2f, 0x53, 0x1b, 0x17,
+ 0xfe, 0xe6, 0xd6, 0x16, 0x20, 0x11, 0xd6, 0xc1, 0x36, 0x61, 0xbd, 0x73, 0x12, 0xc6, 0xb9, 0xd0,
+ 0x0f, 0x30, 0xa2, 0x34, 0x45, 0x91, 0x63, 0xfc, 0x0a, 0xcc, 0x89, 0x31, 0xf2, 0x9e, 0x6a, 0x7c,
+ 0x9b, 0xd6, 0xf8, 0x0a, 0x62, 0xba, 0x70, 0xa8, 0xa1, 0xf4, 0xe7, 0x75, 0x98, 0xc7, 0x20, 0xf6,
+ 0x3e, 0xcb, 0xbc, 0x20, 0x1c, 0x1f, 0x5e, 0x8b, 0xb0, 0xb4, 0xa6, 0xc3, 0xd2, 0xe7, 0x60, 0xc1,
+ 0xcc, 0x91, 0x9c, 0xa9, 0xf3, 0xad, 0x91, 0x21, 0x39, 0x23, 0xcf, 0xc3, 0x22, 0x9e, 0xb6, 0x73,
+ 0x2c, 0x61, 0x33, 0x0b, 0x08, 0xd5, 0x68, 0xf6, 0xd9, 0x60, 0xaa, 0x70, 0x36, 0xe0, 0xcd, 0x18,
+ 0x5f, 0x77, 0xd2, 0xc0, 0xd7, 0x47, 0x07, 0x84, 0xec, 0x07, 0xbe, 0xd1, 0x8c, 0xbd, 0x67, 0x8c,
+ 0x66, 0xec, 0xcd, 0x8f, 0x45, 0x09, 0x13, 0x17, 0x00, 0x78, 0x8f, 0x35, 0x8b, 0x46, 0x37, 0xaf,
+ 0x80, 0x07, 0x41, 0x1f, 0x6f, 0xb9, 0x64, 0x42, 0xbb, 0x29, 0x2c, 0x56, 0x7c, 0xe5, 0x27, 0x37,
+ 0x30, 0x4f, 0x6e, 0xf9, 0x39, 0x6f, 0xce, 0x3a, 0xe7, 0x6d, 0xc1, 0x5c, 0x3c, 0x60, 0x51, 0x47,
+ 0x9e, 0xba, 0xe7, 0x45, 0x40, 0xc1, 0x41, 0x1f, 0x88, 0x93, 0xf7, 0x32, 0xd4, 0x0f, 0x19, 0x6b,
+ 0x2d, 0x88, 0x33, 0xfa, 0x21, 0xe3, 0x2b, 0x6b, 0x3a, 0x4b, 0x3c, 0x9f, 0xa5, 0xad, 0x45, 0x9c,
+ 0x3d, 0xed, 0xbc, 0x0f, 0x38, 0xf4, 0xeb, 0x01, 0x77, 0x42, 0x67, 0xae, 0xc4, 0xa1, 0xff, 0xe4,
+ 0xc0, 0xbc, 0xd9, 0x50, 0x1e, 0x9c, 0x53, 0x31, 0xb8, 0xe2, 0xd4, 0xe9, 0x41, 0xd5, 0xab, 0x07,
+ 0xd5, 0xb0, 0x06, 0x65, 0x1a, 0xc5, 0x54, 0xc1, 0x28, 0xc6, 0x1f, 0xea, 0x0a, 0x13, 0x37, 0x53,
+ 0x9c, 0x38, 0xa9, 0x8d, 0x59, 0xad, 0x0d, 0x99, 0x65, 0x42, 0x9b, 0x4c, 0x27, 0x39, 0xca, 0xdb,
+ 0xfc, 0x6b, 0x45, 0xfe, 0xea, 0xec, 0x5c, 0x3f, 0xef, 0xec, 0x4c, 0x77, 0xf0, 0x20, 0xa1, 0x18,
+ 0xcb, 0xe5, 0xf5, 0x32, 0x4c, 0xa3, 0xb0, 0x6a, 0x65, 0xad, 0x5a, 0x27, 0x3f, 0xb9, 0x68, 0x5c,
+ 0x89, 0x43, 0xbf, 0x8e, 0x77, 0xa7, 0xd8, 0x34, 0x89, 0xe8, 0x97, 0x61, 0x56, 0xe8, 0x46, 0x4f,
+ 0xcd, 0x0c, 0x7e, 0x3f, 0xf0, 0xe9, 0x2f, 0x1d, 0x20, 0xfb, 0xc3, 0x6e, 0x3f, 0x98, 0x9c, 0xda,
+ 0xe4, 0x39, 0x0d, 0x02, 0x0d, 0x9c, 0x0d, 0xb1, 0x5c, 0xf1, 0x77, 0x61, 0x05, 0x35, 0x8a, 0x2b,
+ 0x28, 0xb7, 0x8c, 0xa9, 0xea, 0xb4, 0xc6, 0xb4, 0x69, 0x47, 0x7c, 0x83, 0x0b, 0x03, 0x16, 0x65,
+ 0x1d, 0x99, 0x9f, 0xe2, 0x1b, 0x1c, 0x02, 0x1e, 0xf8, 0x74, 0x1f, 0x56, 0xac, 0x91, 0x49, 0x4d,
+ 0xdf, 0x80, 0x79, 0x21, 0xc0, 0x20, 0xf4, 0x7a, 0xfa, 0x02, 0x61, 0x0e, 0x61, 0x8f, 0x10, 0x34,
+ 0x4e, 0x5f, 0xbf, 0xeb, 0xc0, 0xea, 0x7e, 0xd0, 0x1f, 0x86, 0x5e, 0xc6, 0x7e, 0x0d, 0x1a, 0xcb,
+ 0x87, 0x5f, 0xb7, 0x86, 0xaf, 0x34, 0xd9, 0xc8, 0x35, 0x49, 0xff, 0xcb, 0x81, 0xb5, 0x82, 0x28,
+ 0x3a, 0x8c, 0xb6, 0x8d, 0x69, 0x44, 0x3e, 0x45, 0x22, 0x19, 0x4c, 0x6b, 0x16, 0xd3, 0xe7, 0x60,
+ 0xa1, 0x1f, 0x44, 0x41, 0x7f, 0xd8, 0xef, 0x98, 0x6b, 0x78, 0x5e, 0x02, 0x1f, 0xe1, 0x14, 0x70,
+ 0x24, 0xef, 0xa9, 0x81, 0xd4, 0x90, 0x48, 0x02, 0x28, 0x90, 0x5e, 0x85, 0xd5, 0xfc, 0xa8, 0xd3,
+ 0x39, 0xf2, 0x82, 0xa8, 0x13, 0xc6, 0x69, 0x2a, 0xe7, 0x98, 0xe4, 0x6d, 0x7b, 0x5e, 0x10, 0x3d,
+ 0x8c, 0xd3, 0xd4, 0x70, 0x92, 0xd3, 0xa6, 0x93, 0xa4, 0x7f, 0xe0, 0xc0, 0xf2, 0x87, 0xc7, 0x5e,
+ 0xc8, 0xee, 0xc5, 0xfd, 0xee, 0xb3, 0xd5, 0xfd, 0x0d, 0x98, 0x17, 0xa9, 0xca, 0xcc, 0x4b, 0x8e,
+ 0x98, 0x9a, 0x81, 0x39, 0x84, 0x1d, 0x20, 0xa8, 0x72, 0x1a, 0xfe, 0xd3, 0x01, 0xb2, 0xcb, 0xa3,
+ 0xbf, 0x70, 0x62, 0x7b, 0xe0, 0xae, 0x44, 0xa4, 0x1a, 0x72, 0x0b, 0x6b, 0x4a, 0xc8, 0x03, 0xdb,
+ 0xfc, 0xea, 0x96, 0xf9, 0xe9, 0xd1, 0x34, 0x2e, 0x98, 0x4f, 0x2c, 0xed, 0x73, 0xcf, 0xc3, 0xe2,
+ 0xa9, 0x17, 0x86, 0x2c, 0xd3, 0xd7, 0x8e, 0xf2, 0xf2, 0x42, 0x40, 0x55, 0xda, 0x42, 0x0d, 0x78,
+ 0xc6, 0x18, 0xf0, 0x1b, 0xb0, 0x2e, 0xc6, 0xbb, 0x13, 0x86, 0x13, 0xbb, 0x4f, 0xfa, 0x27, 0x35,
+ 0xd8, 0x28, 0x75, 0xd3, 0xf1, 0x93, 0x6d, 0xaf, 0x37, 0xf5, 0xb8, 0xaa, 0x3b, 0x6c, 0xcb, 0x4f,
+ 0xd9, 0xab, 0xfd, 0x37, 0x0e, 0x4c, 0x0b, 0xd0, 0x58, 0xb5, 0x7f, 0xa4, 0x56, 0xbe, 0xb4, 0x2c,
+ 0x71, 0x5a, 0xfc, 0xc2, 0x64, 0xcc, 0xc4, 0x7f, 0xe6, 0x9d, 0xb2, 0x70, 0x19, 0xf2, 0x3a, 0xf9,
+ 0xab, 0xb0, 0x5c, 0x44, 0xb8, 0xd0, 0x75, 0x9c, 0xc8, 0x38, 0xbd, 0x73, 0xc2, 0x8c, 0x3b, 0xe4,
+ 0x5f, 0x38, 0xb0, 0xb4, 0x1b, 0x47, 0x7e, 0xc0, 0x77, 0xd7, 0x47, 0x5e, 0xe2, 0xf5, 0x53, 0x59,
+ 0xaa, 0x20, 0x40, 0xea, 0x4a, 0x42, 0x03, 0x46, 0x24, 0x7f, 0xaf, 0x02, 0xf4, 0x8e, 0x59, 0xef,
+ 0x49, 0x47, 0x66, 0x63, 0x45, 0x7d, 0x03, 0x87, 0xdc, 0x0b, 0xfc, 0x94, 0xbc, 0x02, 0x2b, 0x79,
+ 0x73, 0xc7, 0x8b, 0xfc, 0x8e, 0x4c, 0xc5, 0xe2, 0xcd, 0x8f, 0xc6, 0xdb, 0x89, 0xfc, 0x9d, 0xf4,
+ 0x49, 0xca, 0x83, 0x66, 0x9d, 0x81, 0xec, 0x58, 0xbe, 0x7a, 0x49, 0xc3, 0x77, 0x10, 0x4c, 0xff,
+ 0xdb, 0xc1, 0xad, 0x4e, 0x8d, 0x4a, 0xce, 0x76, 0x9e, 0x74, 0xc4, 0x5c, 0xb4, 0x35, 0x65, 0xb5,
+ 0xc2, 0x94, 0x11, 0x68, 0x04, 0x19, 0xeb, 0xab, 0x1d, 0x84, 0xff, 0x26, 0xf7, 0x60, 0x59, 0x8f,
+ 0xb8, 0x33, 0x40, 0xb5, 0xc8, 0xf5, 0xb0, 0x91, 0x1f, 0xaa, 0x2d, 0xad, 0xb9, 0x4b, 0xbd, 0x82,
+ 0x1a, 0xd5, 0x3a, 0x9a, 0x9a, 0xc8, 0x23, 0xf7, 0x50, 0xdb, 0xd2, 0x11, 0x89, 0x2f, 0x21, 0x35,
+ 0xeb, 0x0d, 0x33, 0xe6, 0xcb, 0x33, 0x83, 0xfe, 0xa6, 0xff, 0xea, 0xc0, 0xd2, 0x8e, 0xef, 0xe3,
+ 0xb8, 0x27, 0xf1, 0x07, 0x6a, 0x94, 0xb5, 0x73, 0x46, 0x59, 0xff, 0x94, 0xa3, 0xfc, 0x95, 0xbd,
+ 0xc5, 0x08, 0x25, 0x50, 0x0a, 0xcb, 0xf9, 0x38, 0xab, 0xa7, 0x97, 0x7e, 0x0e, 0x88, 0x38, 0xbf,
+ 0x5a, 0xea, 0x28, 0x62, 0xbd, 0x0b, 0xb7, 0xf6, 0x58, 0xb6, 0x9b, 0x9c, 0x0d, 0xb2, 0x58, 0x05,
+ 0xf0, 0xf7, 0xd9, 0x20, 0x4e, 0x03, 0xe5, 0x8b, 0xd8, 0x44, 0x6e, 0xe6, 0x6f, 0x1d, 0xb8, 0x3d,
+ 0x01, 0x21, 0x29, 0xeb, 0xc7, 0xe5, 0x24, 0xdb, 0xff, 0x33, 0x0b, 0x75, 0x26, 0xa2, 0xb2, 0xad,
+ 0x21, 0xb2, 0x96, 0x42, 0x93, 0x6c, 0x7f, 0x19, 0x16, 0xed, 0xc6, 0x0b, 0xf9, 0x84, 0x10, 0x6e,
+ 0x9e, 0x23, 0xc4, 0x24, 0xc6, 0x75, 0x13, 0x16, 0x7b, 0x16, 0x09, 0xc9, 0xa8, 0x00, 0xa5, 0xbb,
+ 0xf0, 0xc2, 0xb9, 0xdc, 0xa4, 0xda, 0x46, 0x66, 0x1c, 0xe8, 0xcf, 0x1d, 0x58, 0xf9, 0x30, 0xc8,
+ 0x8e, 0xfd, 0xc4, 0x3b, 0x7d, 0x37, 0xf0, 0x26, 0xb2, 0x7e, 0xf3, 0x82, 0xa0, 0x56, 0xb8, 0x20,
+ 0x18, 0x15, 0x0f, 0x15, 0x92, 0x17, 0x8d, 0x72, 0x92, 0xe6, 0x26, 0x2c, 0x75, 0xbd, 0xe8, 0x49,
+ 0xc7, 0xd8, 0x68, 0x85, 0x59, 0x2f, 0x70, 0xb0, 0xba, 0x3d, 0xf0, 0xe9, 0x3f, 0x3a, 0xb0, 0xa6,
+ 0x24, 0x16, 0x83, 0x9f, 0x44, 0x66, 0x43, 0x03, 0x35, 0x3b, 0xe7, 0xb2, 0x05, 0x73, 0xf2, 0x67,
+ 0x27, 0xf3, 0x8e, 0xa4, 0xe3, 0x02, 0x09, 0x3a, 0xf0, 0x8e, 0xac, 0xe1, 0x36, 0x46, 0x0e, 0xd7,
+ 0x8e, 0x7e, 0xe5, 0xe9, 0x65, 0x3a, 0x3f, 0xcb, 0x15, 0x14, 0x30, 0x53, 0xce, 0xde, 0xbc, 0x0d,
+ 0xcb, 0x6a, 0x5c, 0x15, 0x6b, 0x53, 0x9c, 0xce, 0xf2, 0x28, 0xab, 0x66, 0x45, 0x59, 0x2f, 0x43,
+ 0x5b, 0xf5, 0xf5, 0x42, 0x5c, 0xb7, 0xf7, 0xce, 0x1e, 0xdc, 0x2f, 0xaf, 0x5d, 0xa4, 0x42, 0x0f,
+ 0xe0, 0x4a, 0x25, 0xb6, 0x64, 0xfa, 0x26, 0x4c, 0x31, 0x0e, 0x94, 0x21, 0xd8, 0x96, 0x5a, 0x60,
+ 0x85, 0x3e, 0xfa, 0xb6, 0x4c, 0x60, 0x53, 0x06, 0x37, 0x0a, 0x18, 0xe9, 0xbd, 0xb3, 0x0b, 0xd4,
+ 0xaa, 0x54, 0x1d, 0x45, 0xf1, 0xea, 0x1e, 0xe7, 0x64, 0xca, 0x15, 0x1f, 0xf4, 0x0c, 0xae, 0x96,
+ 0xd9, 0xdc, 0xf7, 0xb2, 0x89, 0x58, 0xac, 0xc2, 0x14, 0xd6, 0x71, 0xa9, 0xb5, 0x8b, 0x1f, 0x7c,
+ 0xb6, 0x58, 0xa4, 0x42, 0x37, 0xfe, 0x33, 0x67, 0xdd, 0x30, 0x59, 0x7f, 0x07, 0xe8, 0xb8, 0x11,
+ 0x96, 0xd5, 0x57, 0xbf, 0x80, 0xfa, 0x7e, 0x5a, 0x83, 0x8d, 0x11, 0x28, 0x25, 0xcd, 0xbc, 0x6d,
+ 0x0c, 0x51, 0xec, 0x31, 0xd7, 0x8a, 0x5c, 0x42, 0x25, 0x97, 0xa0, 0x94, 0xab, 0xe0, 0x2d, 0x98,
+ 0x49, 0x84, 0xa6, 0xe4, 0x36, 0x73, 0xad, 0x2c, 0xa0, 0x54, 0xa5, 0xe8, 0xaa, 0xd0, 0xc9, 0x17,
+ 0x01, 0x30, 0x75, 0xc0, 0xfc, 0x8e, 0x97, 0xc9, 0x9d, 0xb8, 0xbd, 0x2d, 0x2a, 0x89, 0xb7, 0x55,
+ 0x25, 0xf1, 0xf6, 0x81, 0xaa, 0x24, 0x76, 0x9b, 0x12, 0x7b, 0x07, 0xbb, 0xca, 0xeb, 0x5f, 0xde,
+ 0x75, 0xfa, 0xfc, 0xae, 0x12, 0x7b, 0x27, 0xa3, 0x07, 0xb0, 0x5e, 0x3d, 0xa6, 0xca, 0x04, 0x66,
+ 0x51, 0x53, 0xf9, 0x82, 0xa9, 0x5b, 0x0b, 0xe6, 0xdf, 0x9c, 0x9c, 0xac, 0x3d, 0xde, 0xb1, 0xee,
+ 0xed, 0xfc, 0x5c, 0xf3, 0xa8, 0x4c, 0x09, 0x81, 0x86, 0xde, 0xaa, 0xa7, 0x5c, 0xfc, 0x4d, 0xee,
+ 0x40, 0xe3, 0x30, 0xd0, 0xfa, 0xd0, 0xf7, 0xb6, 0xdc, 0x0f, 0x17, 0x2d, 0x01, 0x11, 0xc9, 0x9b,
+ 0x30, 0x2d, 0x36, 0x01, 0xf4, 0x1f, 0x73, 0x77, 0xaf, 0xea, 0x08, 0x01, 0xa1, 0xc5, 0x4e, 0x12,
+ 0x99, 0xfe, 0x95, 0x03, 0x2b, 0x15, 0x44, 0xf9, 0x69, 0x1c, 0x5d, 0xae, 0xa1, 0xc5, 0x59, 0x0e,
+ 0x78, 0x8f, 0x6b, 0xf2, 0x06, 0xcc, 0x2b, 0x57, 0x8c, 0xed, 0x42, 0x15, 0x73, 0x12, 0x86, 0x28,
+ 0xcf, 0xc3, 0xa2, 0x46, 0x19, 0xf6, 0xbb, 0x4c, 0xd5, 0xb1, 0x2c, 0x28, 0x24, 0x04, 0x62, 0x39,
+ 0x4a, 0xda, 0x95, 0xbe, 0x93, 0xff, 0xc4, 0x65, 0x78, 0x1a, 0x1c, 0xaa, 0x2a, 0x2d, 0xf1, 0x81,
+ 0x51, 0x55, 0xd7, 0x53, 0x21, 0x0b, 0xfe, 0xa6, 0x3e, 0xac, 0x55, 0x8e, 0x6d, 0x4c, 0x12, 0xbd,
+ 0xe0, 0xd0, 0x6b, 0x25, 0x87, 0x2e, 0x9d, 0x73, 0x3d, 0x4f, 0x2d, 0xbd, 0x86, 0x45, 0x6c, 0x0f,
+ 0xe3, 0xa3, 0xa3, 0x3c, 0x75, 0x23, 0x8d, 0x7e, 0x1d, 0xa6, 0x43, 0x84, 0xab, 0x12, 0x77, 0xf1,
+ 0x45, 0x23, 0xcc, 0xb5, 0x17, 0xba, 0xe4, 0x97, 0xcc, 0x41, 0x74, 0x18, 0xcb, 0x4c, 0x05, 0xfe,
+ 0xe6, 0x43, 0xf6, 0x59, 0x77, 0x78, 0xa4, 0x6a, 0x52, 0xf1, 0x83, 0x63, 0x9e, 0x7a, 0x49, 0x24,
+ 0x63, 0x7c, 0xfc, 0xcd, 0x31, 0x59, 0x92, 0xc4, 0x89, 0x0c, 0xe8, 0xc5, 0x07, 0xdd, 0x83, 0x8d,
+ 0xfd, 0x8b, 0x89, 0x88, 0x4e, 0x0c, 0x33, 0xe9, 0xd2, 0xd9, 0xe1, 0x07, 0xfd, 0xa6, 0x55, 0xb0,
+ 0x87, 0x45, 0x5d, 0x13, 0x7a, 0x4e, 0x0c, 0x2f, 0x15, 0x31, 0xfc, 0xa0, 0xbf, 0x74, 0x50, 0x0d,
+ 0x05, 0x6a, 0xba, 0x26, 0xb8, 0x5c, 0x00, 0x27, 0x62, 0xb6, 0x37, 0x2b, 0x0a, 0xe0, 0xac, 0xbe,
+ 0x93, 0x55, 0xc0, 0xfd, 0x5a, 0x8b, 0xda, 0x7e, 0xe6, 0xc0, 0xfa, 0xbe, 0x2d, 0xde, 0x33, 0xc8,
+ 0x3a, 0xbe, 0x08, 0x53, 0xa2, 0x98, 0xb2, 0x6e, 0x67, 0x0d, 0xad, 0x10, 0x5f, 0xa0, 0xf0, 0x79,
+ 0x15, 0xb7, 0x2f, 0xd2, 0x12, 0xe4, 0x17, 0xfd, 0xa1, 0x83, 0x77, 0x1b, 0x3a, 0x37, 0xb4, 0x9f,
+ 0x25, 0xcc, 0xeb, 0x7f, 0xa6, 0xd5, 0x4d, 0x5f, 0x83, 0x1b, 0x66, 0xf1, 0xeb, 0x85, 0x25, 0xa1,
+ 0xbf, 0x89, 0x35, 0x21, 0xa2, 0x62, 0xeb, 0xff, 0x40, 0xfe, 0x2f, 0xc3, 0x35, 0x43, 0xfe, 0x0b,
+ 0x8a, 0x41, 0xff, 0xd8, 0xc1, 0xfb, 0x9f, 0x9d, 0xa1, 0x1f, 0x64, 0xd6, 0x21, 0xe9, 0x2a, 0x00,
+ 0x46, 0x14, 0x1d, 0xbe, 0x79, 0xe9, 0xb2, 0x7a, 0x0e, 0xe1, 0x01, 0x0a, 0xb9, 0x0c, 0xb3, 0x2c,
+ 0xf2, 0x45, 0xa3, 0x8c, 0x42, 0x59, 0xe4, 0xab, 0x26, 0x91, 0xea, 0xe8, 0x9e, 0x59, 0x29, 0xa4,
+ 0x7b, 0x67, 0xd5, 0xb1, 0x08, 0x37, 0x8e, 0xf8, 0xf0, 0x90, 0x2f, 0x48, 0xb1, 0xa3, 0xc8, 0x2f,
+ 0xba, 0x2b, 0x2a, 0x8c, 0x0c, 0xd1, 0xe4, 0x6a, 0x7c, 0x11, 0xa6, 0x31, 0xd0, 0x28, 0x95, 0x2a,
+ 0x19, 0xb8, 0x12, 0x83, 0xfe, 0xbb, 0xb0, 0x30, 0x71, 0x91, 0x10, 0xf4, 0x76, 0xbd, 0xc8, 0x0f,
+ 0x27, 0x3a, 0xce, 0x3d, 0xb3, 0x19, 0xca, 0x23, 0xb5, 0x06, 0x1e, 0x39, 0xed, 0x48, 0x4d, 0x94,
+ 0x90, 0x61, 0xa4, 0xf6, 0x1c, 0x2c, 0x64, 0x41, 0x9f, 0x75, 0x82, 0x28, 0x63, 0xc9, 0x89, 0xa7,
+ 0xae, 0x0d, 0xe7, 0x39, 0xf0, 0x81, 0x84, 0x71, 0x5e, 0xec, 0x69, 0x47, 0x85, 0x3d, 0xe2, 0xf4,
+ 0xdf, 0x64, 0x4f, 0x55, 0xde, 0xe6, 0xef, 0x1d, 0x2c, 0x89, 0x29, 0x0d, 0x77, 0x82, 0x2a, 0xa5,
+ 0xc9, 0xc7, 0xab, 0x07, 0x54, 0xaf, 0x18, 0x50, 0x23, 0x1f, 0x50, 0x1b, 0x66, 0xad, 0xb1, 0x34,
+ 0x5d, 0xfd, 0x4d, 0x6e, 0xc2, 0x74, 0x0f, 0x85, 0x93, 0xb5, 0x05, 0x8b, 0x46, 0x2a, 0xcc, 0x0f,
+ 0x99, 0x2b, 0x5b, 0xe9, 0x6f, 0x39, 0x30, 0x2d, 0x40, 0x18, 0x77, 0xe4, 0x77, 0x3f, 0xf8, 0x5b,
+ 0x55, 0x8c, 0xd6, 0xf2, 0x8a, 0x51, 0x55, 0x57, 0x5a, 0x37, 0xea, 0x4a, 0x09, 0x34, 0xe2, 0x01,
+ 0x8b, 0x54, 0xfd, 0x29, 0xff, 0xcd, 0x07, 0xd1, 0x0b, 0xe3, 0x94, 0xc9, 0xe3, 0x8e, 0xf8, 0x30,
+ 0x6a, 0x49, 0xa7, 0xcd, 0x5a, 0x52, 0xfa, 0x14, 0x20, 0x37, 0x2e, 0x1d, 0x01, 0xc9, 0x70, 0x0d,
+ 0x23, 0xa0, 0x6b, 0x00, 0x81, 0xcf, 0xa2, 0x2c, 0x38, 0x0c, 0x98, 0xaa, 0x49, 0x34, 0x20, 0x7c,
+ 0x97, 0xef, 0xb3, 0x34, 0x55, 0x05, 0x3d, 0x4d, 0x57, 0x7d, 0x92, 0x4d, 0x68, 0xea, 0x37, 0x6b,
+ 0xea, 0x56, 0x42, 0x03, 0x68, 0x17, 0x9a, 0x7b, 0xbb, 0x07, 0xfb, 0x18, 0x95, 0x71, 0xc6, 0x8f,
+ 0x1f, 0x3f, 0xb8, 0xaf, 0x18, 0xf3, 0xdf, 0x3a, 0x76, 0xac, 0x19, 0xb1, 0x23, 0xe1, 0x73, 0x99,
+ 0x1d, 0xab, 0xdc, 0x15, 0xff, 0xcd, 0xd7, 0x65, 0xc4, 0x9e, 0x66, 0x9d, 0x64, 0xa8, 0x0e, 0xad,
+ 0x33, 0xfc, 0xdb, 0x1d, 0x46, 0xf4, 0x3e, 0x6c, 0x68, 0x1e, 0xef, 0x88, 0x4c, 0x92, 0x5a, 0x21,
+ 0xb7, 0x61, 0x5a, 0x44, 0x84, 0xb2, 0x32, 0xf3, 0x92, 0xde, 0xef, 0x54, 0x07, 0x57, 0x22, 0xd0,
+ 0x1d, 0x58, 0xd5, 0xc0, 0xfd, 0x2c, 0x1e, 0x7c, 0x0a, 0x12, 0x97, 0x0d, 0x41, 0x38, 0x89, 0x9d,
+ 0x50, 0x05, 0xb4, 0xf8, 0xe6, 0x21, 0x6f, 0xe2, 0x91, 0xaf, 0x6a, 0x31, 0x3b, 0x3d, 0x0c, 0xd2,
+ 0xcc, 0xe8, 0xf4, 0x67, 0x8e, 0xd1, 0xeb, 0xf1, 0x20, 0x8c, 0x3d, 0x5f, 0x49, 0xb5, 0x05, 0x73,
+ 0x82, 0xa9, 0x19, 0x33, 0x82, 0x00, 0x61, 0x48, 0x98, 0x23, 0x60, 0x99, 0x5d, 0xcd, 0x44, 0xb8,
+ 0xef, 0x65, 0x9e, 0x2e, 0xc0, 0xab, 0xe7, 0x05, 0x78, 0xdc, 0xe4, 0xbd, 0xa4, 0x77, 0x1c, 0x9c,
+ 0x30, 0x5f, 0x6e, 0x75, 0xfa, 0x9b, 0xcf, 0x73, 0x7c, 0xc2, 0x92, 0xd3, 0x24, 0xc8, 0x84, 0xd5,
+ 0xcd, 0xba, 0x39, 0x80, 0xee, 0x41, 0x3b, 0xd7, 0x07, 0xf3, 0x7c, 0xf5, 0xeb, 0xc2, 0x3a, 0xbc,
+ 0x07, 0x6b, 0x1a, 0xf8, 0xed, 0x21, 0xd3, 0xf5, 0x70, 0x17, 0xa1, 0xf1, 0x0d, 0x68, 0x69, 0xe0,
+ 0xce, 0x30, 0x8b, 0x1f, 0x1a, 0x8a, 0x5b, 0xb7, 0xc8, 0x34, 0x55, 0x9f, 0xc2, 0x81, 0x7e, 0x56,
+ 0x9f, 0x4f, 0x3e, 0xb6, 0xe6, 0x54, 0x4c, 0x5c, 0xfe, 0xe8, 0x52, 0xbf, 0xaf, 0x32, 0xaf, 0xa3,
+ 0x5f, 0x82, 0x19, 0x41, 0x54, 0x25, 0xca, 0x2b, 0x44, 0x55, 0x18, 0x34, 0x36, 0xa6, 0x58, 0x8e,
+ 0xf7, 0x1c, 0xf2, 0xb9, 0x22, 0x6a, 0xe7, 0x28, 0xc2, 0x9a, 0xe3, 0xa6, 0x2c, 0xb2, 0xfc, 0x0a,
+ 0x2c, 0xc9, 0x27, 0x45, 0xe7, 0x72, 0x52, 0xdd, 0x6b, 0x46, 0xf7, 0x1e, 0x86, 0xbf, 0x6a, 0xc3,
+ 0xc6, 0x58, 0xef, 0x53, 0x47, 0xad, 0x46, 0x60, 0x55, 0xb7, 0x02, 0xab, 0x47, 0xd0, 0x36, 0x99,
+ 0x84, 0xe1, 0xc4, 0xd1, 0x71, 0x4e, 0xb1, 0x66, 0x51, 0xdc, 0x81, 0xe7, 0x44, 0x8d, 0xb3, 0x22,
+ 0xaa, 0x43, 0xcd, 0x49, 0x49, 0xd3, 0xcf, 0x5b, 0x11, 0xb6, 0x88, 0x72, 0x27, 0xe9, 0xf7, 0x3a,
+ 0x6e, 0xe1, 0xc5, 0x7e, 0xb9, 0xea, 0x75, 0x40, 0x2e, 0xf2, 0xc3, 0xf8, 0x45, 0xdf, 0x84, 0x8d,
+ 0x0f, 0x59, 0x37, 0x8d, 0x7b, 0x4f, 0x58, 0x66, 0xbf, 0xff, 0x1d, 0xcb, 0xeb, 0x27, 0x35, 0x68,
+ 0x95, 0xfb, 0x4d, 0xb0, 0x7d, 0xe2, 0x33, 0x44, 0xa9, 0x11, 0xf5, 0x90, 0x53, 0x03, 0xcc, 0x6a,
+ 0xa4, 0xba, 0x5d, 0x8d, 0xf4, 0x05, 0xd8, 0xb0, 0x9f, 0xbe, 0xe4, 0x54, 0x84, 0x03, 0x59, 0xb7,
+ 0x9a, 0xf3, 0xd7, 0x4f, 0x9f, 0x83, 0x05, 0xab, 0x45, 0xba, 0x14, 0x1b, 0xc8, 0xbd, 0x58, 0x32,
+ 0x8c, 0xa2, 0x20, 0x3a, 0xea, 0x0c, 0x13, 0xb5, 0x0d, 0x83, 0x04, 0x3d, 0x4e, 0x42, 0x1e, 0x75,
+ 0xe0, 0xf3, 0x20, 0x7d, 0x19, 0x27, 0xf2, 0x79, 0xf3, 0x08, 0x54, 0x4f, 0x00, 0x1f, 0x41, 0x5b,
+ 0x2b, 0x85, 0xdb, 0x95, 0x90, 0xfd, 0x57, 0x31, 0xa7, 0xaf, 0xc2, 0x75, 0x53, 0xcd, 0xfb, 0xc3,
+ 0xae, 0x4e, 0x3c, 0x4c, 0x64, 0x13, 0xdf, 0x87, 0xb5, 0x5c, 0x22, 0xa3, 0x33, 0xd7, 0x34, 0x47,
+ 0x89, 0x58, 0xa8, 0x4e, 0xd3, 0xf2, 0x73, 0x6c, 0x36, 0x44, 0xaf, 0xae, 0x7a, 0x61, 0x75, 0x19,
+ 0x97, 0x3c, 0x4d, 0x57, 0x7e, 0xf1, 0xa0, 0xe4, 0xc6, 0x18, 0xe9, 0x27, 0xb0, 0x96, 0x5d, 0x58,
+ 0x48, 0xcd, 0x4e, 0xd2, 0xcf, 0xe9, 0x2c, 0x48, 0xe5, 0xd8, 0x5c, 0xbb, 0x0f, 0x7d, 0x68, 0x98,
+ 0xea, 0x3e, 0xcb, 0xf0, 0x51, 0xd7, 0x84, 0xae, 0x44, 0xbc, 0x08, 0x93, 0xae, 0x04, 0x3f, 0xe8,
+ 0xbb, 0xb0, 0x6e, 0x52, 0x7b, 0xec, 0x3e, 0x9c, 0x84, 0xd6, 0x32, 0xd4, 0xb9, 0x5d, 0x09, 0x4a,
+ 0xfc, 0xe7, 0xdd, 0x1f, 0x7f, 0x0d, 0x16, 0xf7, 0x62, 0x91, 0xea, 0xc0, 0x22, 0x9e, 0x84, 0xbc,
+ 0x0f, 0x33, 0x72, 0x29, 0x91, 0xf5, 0xd2, 0xbb, 0x70, 0xe4, 0xd1, 0xde, 0x18, 0xf1, 0x5e, 0x9c,
+ 0xae, 0xfc, 0xe8, 0x1f, 0xfe, 0xe5, 0x27, 0xb5, 0x05, 0x32, 0x77, 0xe7, 0xe4, 0xb5, 0x3b, 0x47,
+ 0x2c, 0xc3, 0x14, 0xc4, 0x11, 0x2c, 0x58, 0xaf, 0x7a, 0xc9, 0xa6, 0xf5, 0x32, 0xb7, 0xf0, 0xd8,
+ 0xb7, 0x7d, 0x75, 0xec, 0xbb, 0x5d, 0x7a, 0x19, 0x59, 0xac, 0x90, 0x4b, 0x92, 0x45, 0xfe, 0x60,
+ 0x97, 0x1c, 0xc3, 0x92, 0x30, 0x76, 0x4d, 0x94, 0x6c, 0xe5, 0xc4, 0x2a, 0x1f, 0x24, 0x9b, 0x43,
+ 0xb1, 0x76, 0x09, 0x7a, 0x05, 0xf9, 0xac, 0x91, 0x15, 0xce, 0x47, 0xac, 0x03, 0xcd, 0x8a, 0x7c,
+ 0x17, 0x96, 0xe5, 0xa3, 0xc8, 0x67, 0xc1, 0x6a, 0x13, 0x59, 0xad, 0x93, 0x55, 0xce, 0xca, 0x17,
+ 0x74, 0x73, 0x5e, 0x31, 0xd6, 0xf0, 0x98, 0x8f, 0x73, 0xc9, 0xb5, 0x91, 0xaf, 0x76, 0x05, 0xa7,
+ 0xad, 0x73, 0x5e, 0xf5, 0xda, 0x83, 0x3b, 0x62, 0x1c, 0x57, 0x3f, 0xec, 0x25, 0x3f, 0x11, 0xc9,
+ 0x95, 0xca, 0xa7, 0xe2, 0xe4, 0x85, 0xf3, 0xdf, 0xa7, 0x0b, 0x19, 0x6e, 0x4d, 0xfa, 0x90, 0x9d,
+ 0x7e, 0x0e, 0x85, 0xb9, 0x46, 0x36, 0xa5, 0x30, 0xd6, 0xe3, 0x75, 0xf5, 0x3c, 0x9e, 0xf4, 0x60,
+ 0xde, 0x7c, 0xb0, 0x4b, 0xae, 0x54, 0xe4, 0x72, 0x34, 0xf3, 0xcd, 0xea, 0x46, 0xc9, 0xb0, 0x85,
+ 0x0c, 0x09, 0x59, 0x96, 0x0c, 0x75, 0x01, 0x2e, 0x89, 0x60, 0xa9, 0xf0, 0xd8, 0x95, 0xd0, 0xc2,
+ 0xac, 0x55, 0xbc, 0x4c, 0x1e, 0x3d, 0xb3, 0xd7, 0x90, 0x53, 0x8b, 0xae, 0x18, 0x33, 0xab, 0xb8,
+ 0xbd, 0xed, 0xbc, 0x48, 0x52, 0x9c, 0x5b, 0xf3, 0x2d, 0xe6, 0x44, 0xfc, 0xb6, 0xce, 0x79, 0xc8,
+ 0x59, 0x9a, 0x5f, 0xc5, 0x13, 0xd7, 0x63, 0x8a, 0xef, 0xdb, 0x8c, 0x17, 0xc4, 0xbb, 0xb1, 0x3f,
+ 0xd9, 0x38, 0xaf, 0x56, 0xbf, 0x40, 0x96, 0x8f, 0xa0, 0x69, 0x1b, 0xb9, 0xae, 0x12, 0x52, 0xe0,
+ 0x1a, 0x67, 0x03, 0x92, 0x5a, 0x0f, 0xb4, 0x25, 0x53, 0xdb, 0x92, 0x2b, 0x9e, 0x48, 0x57, 0x8e,
+ 0xd4, 0x7c, 0xf3, 0x3c, 0x72, 0xa4, 0x71, 0x36, 0x48, 0x49, 0x08, 0x8b, 0xc2, 0x21, 0x3c, 0x9b,
+ 0xd9, 0xbc, 0x8a, 0xbc, 0x36, 0x28, 0xc9, 0x5d, 0x82, 0x39, 0x99, 0x1f, 0x42, 0x53, 0xe7, 0x96,
+ 0x48, 0xcb, 0x10, 0xdc, 0x7a, 0xa1, 0xda, 0x1e, 0xf1, 0xfe, 0x50, 0x59, 0x25, 0x5d, 0x90, 0x23,
+ 0x11, 0xaf, 0x09, 0x39, 0xe1, 0xef, 0x00, 0xe4, 0x0f, 0x12, 0xc9, 0xe5, 0x12, 0x65, 0xad, 0xad,
+ 0x76, 0x55, 0x93, 0x24, 0xbf, 0x8e, 0xe4, 0x97, 0xc9, 0xa2, 0x45, 0x5e, 0xad, 0x2b, 0x9d, 0x4a,
+ 0xb3, 0xd6, 0x55, 0xf1, 0x09, 0x63, 0x7b, 0xf4, 0xdb, 0x35, 0x35, 0x11, 0x54, 0x2d, 0x2a, 0x5d,
+ 0xe3, 0xc1, 0x47, 0x20, 0xb6, 0x00, 0xe3, 0xd1, 0xdc, 0x66, 0x15, 0x97, 0xca, 0x2d, 0xa0, 0xfc,
+ 0x02, 0xae, 0xb4, 0x05, 0xe4, 0x0f, 0xdd, 0xc8, 0x13, 0xfc, 0xfb, 0x31, 0xc6, 0x9b, 0x2f, 0x62,
+ 0xd2, 0x2a, 0x3f, 0x80, 0x6b, 0x5f, 0x1b, 0xd5, 0x9c, 0x56, 0xdb, 0xb4, 0xbc, 0x62, 0xc0, 0x85,
+ 0x74, 0x26, 0xd2, 0x71, 0x79, 0x2f, 0x91, 0xca, 0xfb, 0x55, 0x59, 0x5e, 0x47, 0x96, 0x6d, 0xd2,
+ 0x2a, 0xb3, 0x4c, 0x91, 0xc1, 0xab, 0x8e, 0xb4, 0x35, 0xf1, 0xc8, 0xcc, 0xb2, 0x35, 0xeb, 0x2d,
+ 0x5a, 0xfb, 0x72, 0x45, 0x8b, 0xe4, 0xb2, 0x86, 0x5c, 0x96, 0xc8, 0x82, 0xf6, 0xba, 0x48, 0x4b,
+ 0x98, 0x83, 0x7e, 0x42, 0x60, 0x99, 0x43, 0xf1, 0x89, 0x98, 0xe5, 0x66, 0x4b, 0x0f, 0xc5, 0x4a,
+ 0x6e, 0x56, 0x3f, 0x05, 0x23, 0x3f, 0xb0, 0x5f, 0x9c, 0xa9, 0x17, 0x30, 0x74, 0xec, 0x93, 0x15,
+ 0xc1, 0xf2, 0xb9, 0x09, 0x9e, 0xb5, 0xd0, 0x2d, 0xe4, 0x7c, 0x99, 0x6c, 0x14, 0x39, 0xcb, 0x27,
+ 0x32, 0xe4, 0x04, 0x56, 0x2a, 0x1e, 0x84, 0xe4, 0x02, 0x8c, 0x7e, 0x2d, 0x32, 0xda, 0x3b, 0x50,
+ 0x64, 0xba, 0x49, 0x91, 0xa9, 0xe7, 0xfb, 0x9a, 0xa9, 0x8c, 0xd5, 0xf9, 0x3a, 0xf8, 0x01, 0xac,
+ 0x57, 0xbf, 0xd1, 0x20, 0xcf, 0xeb, 0x3f, 0x8d, 0x31, 0xee, 0x0d, 0xc7, 0x68, 0xee, 0xcf, 0x23,
+ 0xf7, 0x2d, 0xda, 0xe6, 0xdc, 0x13, 0xa4, 0x51, 0x25, 0xc0, 0x29, 0x16, 0x5a, 0xd9, 0xcf, 0x13,
+ 0xc8, 0x75, 0x43, 0xa7, 0x95, 0xaf, 0x38, 0xda, 0x37, 0xc6, 0x60, 0xd8, 0xce, 0x91, 0xac, 0x49,
+ 0x9d, 0x63, 0x4d, 0xbf, 0x7e, 0xe7, 0x20, 0x3d, 0x40, 0x5e, 0xfe, 0x6f, 0x79, 0x80, 0xd2, 0x8b,
+ 0x06, 0xcb, 0x03, 0x94, 0x1f, 0x19, 0x94, 0x3c, 0x00, 0x32, 0xc3, 0x07, 0x07, 0xe4, 0x23, 0x5c,
+ 0x19, 0xb2, 0xca, 0xaf, 0x55, 0x74, 0x24, 0x69, 0xd5, 0xca, 0xb0, 0xeb, 0xf8, 0x4a, 0x8e, 0x58,
+ 0x14, 0x0f, 0x72, 0xed, 0xb9, 0x30, 0xab, 0xd0, 0xc9, 0x46, 0x91, 0x80, 0xa2, 0x5c, 0x59, 0x91,
+ 0x4d, 0x37, 0x90, 0xe8, 0x25, 0x3a, 0x6f, 0x12, 0xe5, 0x34, 0xbb, 0x30, 0x67, 0x54, 0x1f, 0x13,
+ 0xed, 0xc2, 0xcb, 0xc5, 0xd6, 0xed, 0x2b, 0x95, 0x6d, 0xb6, 0xa3, 0xa2, 0x4b, 0x9c, 0x41, 0x8a,
+ 0x08, 0x9a, 0xc7, 0x77, 0x61, 0xc1, 0x2a, 0x00, 0xce, 0x95, 0x5f, 0x55, 0xa2, 0x9c, 0x2b, 0xbf,
+ 0xb2, 0x6a, 0x58, 0x85, 0xab, 0x14, 0x95, 0x9f, 0x4a, 0x14, 0xcd, 0xeb, 0x63, 0x68, 0xea, 0xba,
+ 0xdb, 0x5c, 0xff, 0xc5, 0x52, 0xdc, 0xf3, 0x78, 0x58, 0x73, 0x70, 0xca, 0x3b, 0x77, 0xe3, 0x7e,
+ 0x57, 0xd0, 0x9f, 0x33, 0xaa, 0x68, 0x73, 0x7d, 0x95, 0x4b, 0x6b, 0x47, 0x2f, 0x16, 0x4b, 0x57,
+ 0x3d, 0xec, 0xa8, 0xe5, 0x4f, 0x60, 0xa9, 0x50, 0xe0, 0x99, 0x07, 0x29, 0xd5, 0xe5, 0xac, 0x79,
+ 0x90, 0x32, 0xa2, 0x32, 0xd4, 0x0e, 0x03, 0x05, 0x3f, 0x2f, 0x0c, 0x73, 0xbb, 0x12, 0xde, 0x5c,
+ 0x54, 0x76, 0x58, 0x36, 0x6b, 0xd5, 0x79, 0x5a, 0x36, 0x6b, 0xd7, 0x4a, 0x96, 0xbc, 0xb9, 0xb8,
+ 0x50, 0x21, 0x1f, 0xc0, 0xac, 0xaa, 0xbb, 0xcb, 0x0d, 0xb6, 0x50, 0x71, 0xd8, 0x6e, 0x95, 0x1b,
+ 0x24, 0x55, 0xcb, 0x68, 0x3d, 0xdf, 0x47, 0xaa, 0x72, 0x12, 0x8c, 0x5a, 0xbd, 0x7c, 0x12, 0xca,
+ 0x05, 0x7c, 0x13, 0x4e, 0x82, 0xf0, 0x58, 0x9a, 0xfe, 0x5f, 0x38, 0x78, 0xd1, 0x37, 0xbe, 0xae,
+ 0x8e, 0xbc, 0x7a, 0x81, 0x12, 0x3c, 0x21, 0xcc, 0x6b, 0x17, 0x2e, 0xda, 0xa3, 0xb7, 0x50, 0x4c,
+ 0x4a, 0xaf, 0xaa, 0x7d, 0x12, 0xbb, 0xf9, 0x02, 0x5d, 0x57, 0xf0, 0x71, 0xa1, 0xff, 0xdc, 0x11,
+ 0x7f, 0x73, 0x6c, 0x0c, 0x5d, 0xb2, 0x3d, 0xa1, 0x00, 0x4a, 0xe0, 0x3b, 0x13, 0xe3, 0x4b, 0x71,
+ 0x6f, 0xa2, 0xb8, 0xd7, 0xe9, 0x95, 0x31, 0xe2, 0x72, 0x61, 0x43, 0xb8, 0x64, 0xd6, 0xdf, 0xbd,
+ 0x3b, 0x8c, 0x7c, 0xe3, 0x4c, 0x55, 0x51, 0x9a, 0x97, 0x9b, 0x49, 0xb1, 0x5a, 0x4c, 0x05, 0x2c,
+ 0x14, 0x5d, 0xff, 0xa9, 0x6c, 0x3d, 0x0c, 0xbc, 0xec, 0x90, 0x53, 0xe5, 0xdc, 0x7e, 0xec, 0xe4,
+ 0xa5, 0x5f, 0xf6, 0x30, 0x04, 0xe3, 0xab, 0x45, 0xda, 0x56, 0x85, 0xdd, 0x18, 0xd6, 0xaf, 0x23,
+ 0xeb, 0x57, 0xe8, 0x2d, 0x93, 0xb5, 0xfc, 0x4f, 0x0c, 0x1d, 0x65, 0xb0, 0xa5, 0xf9, 0x91, 0x51,
+ 0x7c, 0x68, 0x14, 0xa2, 0xe5, 0xdb, 0xff, 0xe8, 0x9a, 0xb6, 0x3c, 0xfe, 0x18, 0x53, 0xc9, 0x66,
+ 0x87, 0x02, 0xa7, 0x1a, 0x11, 0xcd, 0xbb, 0x7b, 0x16, 0xf8, 0x5c, 0x88, 0x9f, 0x39, 0xa5, 0xda,
+ 0x39, 0xa3, 0xaa, 0x8b, 0xdc, 0x1e, 0xc1, 0xa7, 0x5c, 0xdb, 0xd6, 0x7e, 0x71, 0x12, 0xd4, 0x0b,
+ 0x48, 0xf6, 0x87, 0x56, 0x8d, 0x92, 0x59, 0xea, 0x96, 0x47, 0x29, 0x63, 0x4b, 0xe1, 0x2e, 0x24,
+ 0x91, 0x3c, 0xfd, 0xd3, 0xcb, 0x95, 0x12, 0xf9, 0x5e, 0x26, 0x0f, 0xca, 0xcb, 0xc5, 0xb2, 0x17,
+ 0x33, 0xe1, 0x52, 0x59, 0xa0, 0xd2, 0xbe, 0x3e, 0x1a, 0xa1, 0x2a, 0xf3, 0x72, 0xc4, 0x32, 0x51,
+ 0xc1, 0xe2, 0x4b, 0x06, 0x27, 0xb0, 0xbc, 0x3f, 0x92, 0xe9, 0xfe, 0xa7, 0x66, 0x2a, 0xa3, 0x53,
+ 0x8a, 0x4c, 0xd3, 0x02, 0x53, 0x3e, 0xd8, 0x13, 0x51, 0xe3, 0x6f, 0x16, 0xa8, 0x90, 0xad, 0xd1,
+ 0xa5, 0x2b, 0x65, 0xbe, 0x95, 0xb5, 0x2d, 0x36, 0x5f, 0xe3, 0xa8, 0x8c, 0x55, 0x1f, 0x22, 0x4c,
+ 0x58, 0x2a, 0x54, 0x9e, 0xe4, 0x5b, 0x5f, 0x75, 0x49, 0xca, 0x84, 0x99, 0x8f, 0xd4, 0x66, 0xc6,
+ 0x79, 0x65, 0x98, 0x84, 0x28, 0x54, 0x70, 0x90, 0x1b, 0x55, 0x07, 0x3f, 0xab, 0x40, 0x62, 0xdc,
+ 0x11, 0x54, 0xf2, 0x24, 0xeb, 0xa5, 0x73, 0xa1, 0x3a, 0x36, 0xfd, 0x9e, 0xb8, 0x71, 0x1f, 0x51,
+ 0x40, 0x42, 0x6e, 0x57, 0x65, 0x1b, 0x2e, 0x2c, 0x86, 0x74, 0xc1, 0xe4, 0x5a, 0x31, 0x25, 0x51,
+ 0x12, 0xe7, 0x18, 0xd3, 0x3f, 0x66, 0x19, 0x88, 0x95, 0x10, 0xa9, 0xa8, 0x0f, 0x19, 0x99, 0x3d,
+ 0x28, 0xe6, 0x41, 0xe4, 0xf1, 0x5e, 0x71, 0xfa, 0xa1, 0xfd, 0xa7, 0xe6, 0x2c, 0x96, 0x37, 0x2b,
+ 0x46, 0x7d, 0x11, 0xd6, 0xcf, 0x21, 0xeb, 0xab, 0xe4, 0x4a, 0x61, 0xbc, 0x05, 0x11, 0xc4, 0x09,
+ 0xc0, 0xb8, 0x98, 0x37, 0x4f, 0x00, 0xa5, 0x9a, 0x16, 0xeb, 0x04, 0x50, 0x2e, 0x2b, 0x29, 0x9d,
+ 0x00, 0x3c, 0x8e, 0x82, 0x4e, 0x83, 0x3c, 0x81, 0xe5, 0xe2, 0x05, 0xb9, 0xb1, 0x7c, 0xaa, 0xaf,
+ 0xce, 0xcf, 0x4d, 0xfa, 0xc8, 0x73, 0x4d, 0x2f, 0x13, 0x29, 0xfd, 0x3b, 0xf2, 0x0d, 0x07, 0x79,
+ 0x02, 0x4b, 0x85, 0x3b, 0x6b, 0x63, 0x0a, 0x2b, 0x2f, 0xb3, 0x47, 0xb3, 0xb2, 0x17, 0xa8, 0x66,
+ 0x35, 0xc4, 0xde, 0x7c, 0xd1, 0x3c, 0x85, 0x95, 0x8a, 0x6b, 0x67, 0xe3, 0xdc, 0x3c, 0xf2, 0x4e,
+ 0xba, 0x5d, 0x16, 0xca, 0xba, 0x7e, 0xb5, 0x73, 0x5b, 0x39, 0xef, 0x84, 0x09, 0xce, 0x03, 0x63,
+ 0x98, 0xf2, 0x6f, 0xc9, 0x96, 0x29, 0x5a, 0x37, 0xfd, 0xed, 0xad, 0x91, 0xed, 0x95, 0xce, 0x57,
+ 0xb3, 0x94, 0xb7, 0xb1, 0x21, 0x2c, 0xda, 0xa2, 0x1a, 0x69, 0x95, 0xaa, 0x1b, 0xf3, 0x73, 0x47,
+ 0x68, 0xaf, 0x10, 0xcd, 0xee, 0x13, 0xa4, 0xcd, 0x60, 0xc1, 0xaa, 0x65, 0x30, 0x8c, 0xb3, 0xa2,
+ 0x4a, 0x62, 0xc2, 0x14, 0xa1, 0x39, 0xa6, 0x78, 0xc0, 0xd5, 0x68, 0x9a, 0xa6, 0x2c, 0x99, 0x20,
+ 0x5b, 0x95, 0x9c, 0xf2, 0xba, 0x88, 0x4f, 0xcd, 0x2c, 0x35, 0x98, 0xc9, 0x52, 0x8b, 0x0a, 0x66,
+ 0x76, 0x11, 0xc6, 0xf9, 0xb3, 0x76, 0x0e, 0xd3, 0x53, 0xa3, 0x80, 0x40, 0x15, 0x23, 0x1c, 0xc4,
+ 0x47, 0x47, 0x21, 0x33, 0xd2, 0x0c, 0x23, 0xaa, 0x15, 0x46, 0x8f, 0xf4, 0x06, 0x32, 0xbd, 0x42,
+ 0xd7, 0x6d, 0xa6, 0xde, 0x30, 0x8b, 0xd5, 0xda, 0xf8, 0x3e, 0x6e, 0x28, 0x85, 0x5a, 0x2a, 0x6b,
+ 0x43, 0xa9, 0x2e, 0x2b, 0x6b, 0xd3, 0x71, 0x28, 0x23, 0x76, 0x96, 0x63, 0x89, 0xd7, 0x93, 0x6c,
+ 0xbe, 0x8b, 0x91, 0x82, 0x75, 0xe9, 0x6d, 0x45, 0x0a, 0x55, 0x05, 0x04, 0x13, 0xde, 0x07, 0x19,
+ 0x7b, 0xa7, 0xb8, 0xe7, 0x4c, 0x61, 0x65, 0x9f, 0xf1, 0x29, 0xb3, 0x03, 0x04, 0x5a, 0xc5, 0xce,
+ 0x2e, 0x25, 0x38, 0xd7, 0xf3, 0x88, 0x84, 0x59, 0xca, 0x32, 0x2f, 0x0c, 0xad, 0xe8, 0x80, 0xfc,
+ 0xbe, 0x03, 0x9b, 0xe3, 0x2a, 0x0a, 0xc8, 0x4b, 0x8a, 0xf4, 0x04, 0x75, 0x07, 0xa3, 0xe5, 0x90,
+ 0x87, 0x2d, 0x72, 0x9d, 0xcb, 0x21, 0x6a, 0xf1, 0xf5, 0xe5, 0x8c, 0xa2, 0x24, 0x04, 0x12, 0x89,
+ 0x2c, 0xbb, 0xcc, 0x80, 0x54, 0xc5, 0x40, 0x56, 0xe5, 0x82, 0x95, 0xc8, 0xaa, 0xae, 0x51, 0x28,
+ 0x25, 0xb2, 0x2c, 0xed, 0xa7, 0x7c, 0x55, 0x15, 0x4b, 0x0e, 0xf2, 0xa9, 0x1e, 0x51, 0xc4, 0x90,
+ 0x07, 0x67, 0xa3, 0xaa, 0x15, 0xec, 0x39, 0x3f, 0x55, 0x58, 0xea, 0x0a, 0x35, 0x85, 0x95, 0x8a,
+ 0x2b, 0x7d, 0xe3, 0xc0, 0x32, 0xf2, 0xbe, 0x7f, 0xc2, 0x39, 0xd7, 0x1c, 0xb9, 0xb9, 0x49, 0xea,
+ 0x3f, 0x73, 0xe0, 0xf2, 0xc8, 0x8b, 0x73, 0x72, 0xab, 0x6a, 0x48, 0x55, 0x95, 0x01, 0xed, 0xdb,
+ 0x13, 0x60, 0xda, 0x59, 0x4c, 0x72, 0xb5, 0xa8, 0x05, 0xeb, 0x2e, 0x9d, 0xf4, 0xe1, 0x52, 0xe9,
+ 0x2e, 0x9d, 0x5c, 0xaf, 0x52, 0x86, 0x79, 0xcd, 0x3e, 0xe1, 0x1e, 0x6f, 0xaa, 0x02, 0x2f, 0xdb,
+ 0xc9, 0x11, 0x2c, 0x15, 0x2e, 0xdb, 0xf3, 0xcd, 0xaf, 0xfa, 0x16, 0x7e, 0xc2, 0x6b, 0x65, 0x93,
+ 0xd5, 0x30, 0x09, 0xbb, 0xd3, 0xf8, 0x24, 0xe5, 0xf5, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xfa,
+ 0x35, 0xc5, 0x70, 0x58, 0x5f, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@@ -10951,16 +7634,16 @@ const _ = grpc.SupportPackageIsVersion6
type GoCryptoTraderClient interface {
GetInfo(ctx context.Context, in *GetInfoRequest, opts ...grpc.CallOption) (*GetInfoResponse, error)
GetSubsystems(ctx context.Context, in *GetSubsystemsRequest, opts ...grpc.CallOption) (*GetSusbsytemsResponse, error)
- EnableSubsystem(ctx context.Context, in *GenericSubsystemRequest, opts ...grpc.CallOption) (*GenericSubsystemResponse, error)
- DisableSubsystem(ctx context.Context, in *GenericSubsystemRequest, opts ...grpc.CallOption) (*GenericSubsystemResponse, error)
+ EnableSubsystem(ctx context.Context, in *GenericSubsystemRequest, opts ...grpc.CallOption) (*GenericResponse, error)
+ DisableSubsystem(ctx context.Context, in *GenericSubsystemRequest, opts ...grpc.CallOption) (*GenericResponse, error)
GetRPCEndpoints(ctx context.Context, in *GetRPCEndpointsRequest, opts ...grpc.CallOption) (*GetRPCEndpointsResponse, error)
GetCommunicationRelayers(ctx context.Context, in *GetCommunicationRelayersRequest, opts ...grpc.CallOption) (*GetCommunicationRelayersResponse, error)
GetExchanges(ctx context.Context, in *GetExchangesRequest, opts ...grpc.CallOption) (*GetExchangesResponse, error)
- DisableExchange(ctx context.Context, in *GenericExchangeNameRequest, opts ...grpc.CallOption) (*GenericExchangeNameResponse, error)
+ DisableExchange(ctx context.Context, in *GenericExchangeNameRequest, opts ...grpc.CallOption) (*GenericResponse, error)
GetExchangeInfo(ctx context.Context, in *GenericExchangeNameRequest, opts ...grpc.CallOption) (*GetExchangeInfoResponse, error)
GetExchangeOTPCode(ctx context.Context, in *GenericExchangeNameRequest, opts ...grpc.CallOption) (*GetExchangeOTPReponse, error)
GetExchangeOTPCodes(ctx context.Context, in *GetExchangeOTPsRequest, opts ...grpc.CallOption) (*GetExchangeOTPsResponse, error)
- EnableExchange(ctx context.Context, in *GenericExchangeNameRequest, opts ...grpc.CallOption) (*GenericExchangeNameResponse, error)
+ EnableExchange(ctx context.Context, in *GenericExchangeNameRequest, opts ...grpc.CallOption) (*GenericResponse, error)
GetTicker(ctx context.Context, in *GetTickerRequest, opts ...grpc.CallOption) (*TickerResponse, error)
GetTickers(ctx context.Context, in *GetTickersRequest, opts ...grpc.CallOption) (*GetTickersResponse, error)
GetOrderbook(ctx context.Context, in *GetOrderbookRequest, opts ...grpc.CallOption) (*OrderbookResponse, error)
@@ -10970,8 +7653,8 @@ type GoCryptoTraderClient interface {
GetConfig(ctx context.Context, in *GetConfigRequest, opts ...grpc.CallOption) (*GetConfigResponse, error)
GetPortfolio(ctx context.Context, in *GetPortfolioRequest, opts ...grpc.CallOption) (*GetPortfolioResponse, error)
GetPortfolioSummary(ctx context.Context, in *GetPortfolioSummaryRequest, opts ...grpc.CallOption) (*GetPortfolioSummaryResponse, error)
- AddPortfolioAddress(ctx context.Context, in *AddPortfolioAddressRequest, opts ...grpc.CallOption) (*AddPortfolioAddressResponse, error)
- RemovePortfolioAddress(ctx context.Context, in *RemovePortfolioAddressRequest, opts ...grpc.CallOption) (*RemovePortfolioAddressResponse, error)
+ AddPortfolioAddress(ctx context.Context, in *AddPortfolioAddressRequest, opts ...grpc.CallOption) (*GenericResponse, error)
+ RemovePortfolioAddress(ctx context.Context, in *RemovePortfolioAddressRequest, opts ...grpc.CallOption) (*GenericResponse, error)
GetForexProviders(ctx context.Context, in *GetForexProvidersRequest, opts ...grpc.CallOption) (*GetForexProvidersResponse, error)
GetForexRates(ctx context.Context, in *GetForexRatesRequest, opts ...grpc.CallOption) (*GetForexRatesResponse, error)
GetOrders(ctx context.Context, in *GetOrdersRequest, opts ...grpc.CallOption) (*GetOrdersResponse, error)
@@ -10979,11 +7662,11 @@ type GoCryptoTraderClient interface {
SubmitOrder(ctx context.Context, in *SubmitOrderRequest, opts ...grpc.CallOption) (*SubmitOrderResponse, error)
SimulateOrder(ctx context.Context, in *SimulateOrderRequest, opts ...grpc.CallOption) (*SimulateOrderResponse, error)
WhaleBomb(ctx context.Context, in *WhaleBombRequest, opts ...grpc.CallOption) (*SimulateOrderResponse, error)
- CancelOrder(ctx context.Context, in *CancelOrderRequest, opts ...grpc.CallOption) (*CancelOrderResponse, error)
+ CancelOrder(ctx context.Context, in *CancelOrderRequest, opts ...grpc.CallOption) (*GenericResponse, error)
CancelAllOrders(ctx context.Context, in *CancelAllOrdersRequest, opts ...grpc.CallOption) (*CancelAllOrdersResponse, error)
GetEvents(ctx context.Context, in *GetEventsRequest, opts ...grpc.CallOption) (*GetEventsResponse, error)
AddEvent(ctx context.Context, in *AddEventRequest, opts ...grpc.CallOption) (*AddEventResponse, error)
- RemoveEvent(ctx context.Context, in *RemoveEventRequest, opts ...grpc.CallOption) (*RemoveEventResponse, error)
+ RemoveEvent(ctx context.Context, in *RemoveEventRequest, opts ...grpc.CallOption) (*GenericResponse, error)
GetCryptocurrencyDepositAddresses(ctx context.Context, in *GetCryptocurrencyDepositAddressesRequest, opts ...grpc.CallOption) (*GetCryptocurrencyDepositAddressesResponse, error)
GetCryptocurrencyDepositAddress(ctx context.Context, in *GetCryptocurrencyDepositAddressRequest, opts ...grpc.CallOption) (*GetCryptocurrencyDepositAddressResponse, error)
WithdrawFiatFunds(ctx context.Context, in *WithdrawFiatRequest, opts ...grpc.CallOption) (*WithdrawResponse, error)
@@ -10994,23 +7677,31 @@ type GoCryptoTraderClient interface {
GetLoggerDetails(ctx context.Context, in *GetLoggerDetailsRequest, opts ...grpc.CallOption) (*GetLoggerDetailsResponse, error)
SetLoggerDetails(ctx context.Context, in *SetLoggerDetailsRequest, opts ...grpc.CallOption) (*GetLoggerDetailsResponse, error)
GetExchangePairs(ctx context.Context, in *GetExchangePairsRequest, opts ...grpc.CallOption) (*GetExchangePairsResponse, error)
- EnableExchangePair(ctx context.Context, in *ExchangePairRequest, opts ...grpc.CallOption) (*GenericExchangeNameResponse, error)
- DisableExchangePair(ctx context.Context, in *ExchangePairRequest, opts ...grpc.CallOption) (*GenericExchangeNameResponse, error)
+ SetExchangePair(ctx context.Context, in *SetExchangePairRequest, opts ...grpc.CallOption) (*GenericResponse, error)
GetOrderbookStream(ctx context.Context, in *GetOrderbookStreamRequest, opts ...grpc.CallOption) (GoCryptoTrader_GetOrderbookStreamClient, error)
GetExchangeOrderbookStream(ctx context.Context, in *GetExchangeOrderbookStreamRequest, opts ...grpc.CallOption) (GoCryptoTrader_GetExchangeOrderbookStreamClient, error)
GetTickerStream(ctx context.Context, in *GetTickerStreamRequest, opts ...grpc.CallOption) (GoCryptoTrader_GetTickerStreamClient, error)
GetExchangeTickerStream(ctx context.Context, in *GetExchangeTickerStreamRequest, opts ...grpc.CallOption) (GoCryptoTrader_GetExchangeTickerStreamClient, error)
GetAuditEvent(ctx context.Context, in *GetAuditEventRequest, opts ...grpc.CallOption) (*GetAuditEventResponse, error)
- GCTScriptExecute(ctx context.Context, in *GCTScriptExecuteRequest, opts ...grpc.CallOption) (*GCTScriptGenericResponse, error)
- GCTScriptUpload(ctx context.Context, in *GCTScriptUploadRequest, opts ...grpc.CallOption) (*GCTScriptGenericResponse, error)
+ GCTScriptExecute(ctx context.Context, in *GCTScriptExecuteRequest, opts ...grpc.CallOption) (*GenericResponse, error)
+ GCTScriptUpload(ctx context.Context, in *GCTScriptUploadRequest, opts ...grpc.CallOption) (*GenericResponse, error)
GCTScriptReadScript(ctx context.Context, in *GCTScriptReadScriptRequest, opts ...grpc.CallOption) (*GCTScriptQueryResponse, error)
GCTScriptStatus(ctx context.Context, in *GCTScriptStatusRequest, opts ...grpc.CallOption) (*GCTScriptStatusResponse, error)
GCTScriptQuery(ctx context.Context, in *GCTScriptQueryRequest, opts ...grpc.CallOption) (*GCTScriptQueryResponse, error)
- GCTScriptStop(ctx context.Context, in *GCTScriptStopRequest, opts ...grpc.CallOption) (*GCTScriptGenericResponse, error)
- GCTScriptStopAll(ctx context.Context, in *GCTScriptStopAllRequest, opts ...grpc.CallOption) (*GCTScriptGenericResponse, error)
+ GCTScriptStop(ctx context.Context, in *GCTScriptStopRequest, opts ...grpc.CallOption) (*GenericResponse, error)
+ GCTScriptStopAll(ctx context.Context, in *GCTScriptStopAllRequest, opts ...grpc.CallOption) (*GenericResponse, error)
GCTScriptListAll(ctx context.Context, in *GCTScriptListAllRequest, opts ...grpc.CallOption) (*GCTScriptStatusResponse, error)
- GCTScriptAutoLoadToggle(ctx context.Context, in *GCTScriptAutoLoadRequest, opts ...grpc.CallOption) (*GCTScriptGenericResponse, error)
+ GCTScriptAutoLoadToggle(ctx context.Context, in *GCTScriptAutoLoadRequest, opts ...grpc.CallOption) (*GenericResponse, error)
GetHistoricCandles(ctx context.Context, in *GetHistoricCandlesRequest, opts ...grpc.CallOption) (*GetHistoricCandlesResponse, error)
+ SetExchangeAsset(ctx context.Context, in *SetExchangeAssetRequest, opts ...grpc.CallOption) (*GenericResponse, error)
+ SetAllExchangePairs(ctx context.Context, in *SetExchangeAllPairsRequest, opts ...grpc.CallOption) (*GenericResponse, error)
+ UpdateExchangeSupportedPairs(ctx context.Context, in *UpdateExchangeSupportedPairsRequest, opts ...grpc.CallOption) (*GenericResponse, error)
+ GetExchangeAssets(ctx context.Context, in *GetExchangeAssetsRequest, opts ...grpc.CallOption) (*GetExchangeAssetsResponse, error)
+ WebsocketGetInfo(ctx context.Context, in *WebsocketGetInfoRequest, opts ...grpc.CallOption) (*WebsocketGetInfoResponse, error)
+ WebsocketSetEnabled(ctx context.Context, in *WebsocketSetEnabledRequest, opts ...grpc.CallOption) (*GenericResponse, error)
+ WebsocketGetSubscriptions(ctx context.Context, in *WebsocketGetSubscriptionsRequest, opts ...grpc.CallOption) (*WebsocketGetSubscriptionsResponse, error)
+ WebsocketSetProxy(ctx context.Context, in *WebsocketSetProxyRequest, opts ...grpc.CallOption) (*GenericResponse, error)
+ WebsocketSetURL(ctx context.Context, in *WebsocketSetURLRequest, opts ...grpc.CallOption) (*GenericResponse, error)
}
type goCryptoTraderClient struct {
@@ -11039,8 +7730,8 @@ func (c *goCryptoTraderClient) GetSubsystems(ctx context.Context, in *GetSubsyst
return out, nil
}
-func (c *goCryptoTraderClient) EnableSubsystem(ctx context.Context, in *GenericSubsystemRequest, opts ...grpc.CallOption) (*GenericSubsystemResponse, error) {
- out := new(GenericSubsystemResponse)
+func (c *goCryptoTraderClient) EnableSubsystem(ctx context.Context, in *GenericSubsystemRequest, opts ...grpc.CallOption) (*GenericResponse, error) {
+ out := new(GenericResponse)
err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/EnableSubsystem", in, out, opts...)
if err != nil {
return nil, err
@@ -11048,8 +7739,8 @@ func (c *goCryptoTraderClient) EnableSubsystem(ctx context.Context, in *GenericS
return out, nil
}
-func (c *goCryptoTraderClient) DisableSubsystem(ctx context.Context, in *GenericSubsystemRequest, opts ...grpc.CallOption) (*GenericSubsystemResponse, error) {
- out := new(GenericSubsystemResponse)
+func (c *goCryptoTraderClient) DisableSubsystem(ctx context.Context, in *GenericSubsystemRequest, opts ...grpc.CallOption) (*GenericResponse, error) {
+ out := new(GenericResponse)
err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/DisableSubsystem", in, out, opts...)
if err != nil {
return nil, err
@@ -11084,8 +7775,8 @@ func (c *goCryptoTraderClient) GetExchanges(ctx context.Context, in *GetExchange
return out, nil
}
-func (c *goCryptoTraderClient) DisableExchange(ctx context.Context, in *GenericExchangeNameRequest, opts ...grpc.CallOption) (*GenericExchangeNameResponse, error) {
- out := new(GenericExchangeNameResponse)
+func (c *goCryptoTraderClient) DisableExchange(ctx context.Context, in *GenericExchangeNameRequest, opts ...grpc.CallOption) (*GenericResponse, error) {
+ out := new(GenericResponse)
err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/DisableExchange", in, out, opts...)
if err != nil {
return nil, err
@@ -11120,8 +7811,8 @@ func (c *goCryptoTraderClient) GetExchangeOTPCodes(ctx context.Context, in *GetE
return out, nil
}
-func (c *goCryptoTraderClient) EnableExchange(ctx context.Context, in *GenericExchangeNameRequest, opts ...grpc.CallOption) (*GenericExchangeNameResponse, error) {
- out := new(GenericExchangeNameResponse)
+func (c *goCryptoTraderClient) EnableExchange(ctx context.Context, in *GenericExchangeNameRequest, opts ...grpc.CallOption) (*GenericResponse, error) {
+ out := new(GenericResponse)
err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/EnableExchange", in, out, opts...)
if err != nil {
return nil, err
@@ -11233,8 +7924,8 @@ func (c *goCryptoTraderClient) GetPortfolioSummary(ctx context.Context, in *GetP
return out, nil
}
-func (c *goCryptoTraderClient) AddPortfolioAddress(ctx context.Context, in *AddPortfolioAddressRequest, opts ...grpc.CallOption) (*AddPortfolioAddressResponse, error) {
- out := new(AddPortfolioAddressResponse)
+func (c *goCryptoTraderClient) AddPortfolioAddress(ctx context.Context, in *AddPortfolioAddressRequest, opts ...grpc.CallOption) (*GenericResponse, error) {
+ out := new(GenericResponse)
err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/AddPortfolioAddress", in, out, opts...)
if err != nil {
return nil, err
@@ -11242,8 +7933,8 @@ func (c *goCryptoTraderClient) AddPortfolioAddress(ctx context.Context, in *AddP
return out, nil
}
-func (c *goCryptoTraderClient) RemovePortfolioAddress(ctx context.Context, in *RemovePortfolioAddressRequest, opts ...grpc.CallOption) (*RemovePortfolioAddressResponse, error) {
- out := new(RemovePortfolioAddressResponse)
+func (c *goCryptoTraderClient) RemovePortfolioAddress(ctx context.Context, in *RemovePortfolioAddressRequest, opts ...grpc.CallOption) (*GenericResponse, error) {
+ out := new(GenericResponse)
err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/RemovePortfolioAddress", in, out, opts...)
if err != nil {
return nil, err
@@ -11314,8 +8005,8 @@ func (c *goCryptoTraderClient) WhaleBomb(ctx context.Context, in *WhaleBombReque
return out, nil
}
-func (c *goCryptoTraderClient) CancelOrder(ctx context.Context, in *CancelOrderRequest, opts ...grpc.CallOption) (*CancelOrderResponse, error) {
- out := new(CancelOrderResponse)
+func (c *goCryptoTraderClient) CancelOrder(ctx context.Context, in *CancelOrderRequest, opts ...grpc.CallOption) (*GenericResponse, error) {
+ out := new(GenericResponse)
err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/CancelOrder", in, out, opts...)
if err != nil {
return nil, err
@@ -11350,8 +8041,8 @@ func (c *goCryptoTraderClient) AddEvent(ctx context.Context, in *AddEventRequest
return out, nil
}
-func (c *goCryptoTraderClient) RemoveEvent(ctx context.Context, in *RemoveEventRequest, opts ...grpc.CallOption) (*RemoveEventResponse, error) {
- out := new(RemoveEventResponse)
+func (c *goCryptoTraderClient) RemoveEvent(ctx context.Context, in *RemoveEventRequest, opts ...grpc.CallOption) (*GenericResponse, error) {
+ out := new(GenericResponse)
err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/RemoveEvent", in, out, opts...)
if err != nil {
return nil, err
@@ -11449,18 +8140,9 @@ func (c *goCryptoTraderClient) GetExchangePairs(ctx context.Context, in *GetExch
return out, nil
}
-func (c *goCryptoTraderClient) EnableExchangePair(ctx context.Context, in *ExchangePairRequest, opts ...grpc.CallOption) (*GenericExchangeNameResponse, error) {
- out := new(GenericExchangeNameResponse)
- err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/EnableExchangePair", in, out, opts...)
- if err != nil {
- return nil, err
- }
- return out, nil
-}
-
-func (c *goCryptoTraderClient) DisableExchangePair(ctx context.Context, in *ExchangePairRequest, opts ...grpc.CallOption) (*GenericExchangeNameResponse, error) {
- out := new(GenericExchangeNameResponse)
- err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/DisableExchangePair", in, out, opts...)
+func (c *goCryptoTraderClient) SetExchangePair(ctx context.Context, in *SetExchangePairRequest, opts ...grpc.CallOption) (*GenericResponse, error) {
+ out := new(GenericResponse)
+ err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/SetExchangePair", in, out, opts...)
if err != nil {
return nil, err
}
@@ -11604,8 +8286,8 @@ func (c *goCryptoTraderClient) GetAuditEvent(ctx context.Context, in *GetAuditEv
return out, nil
}
-func (c *goCryptoTraderClient) GCTScriptExecute(ctx context.Context, in *GCTScriptExecuteRequest, opts ...grpc.CallOption) (*GCTScriptGenericResponse, error) {
- out := new(GCTScriptGenericResponse)
+func (c *goCryptoTraderClient) GCTScriptExecute(ctx context.Context, in *GCTScriptExecuteRequest, opts ...grpc.CallOption) (*GenericResponse, error) {
+ out := new(GenericResponse)
err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/GCTScriptExecute", in, out, opts...)
if err != nil {
return nil, err
@@ -11613,8 +8295,8 @@ func (c *goCryptoTraderClient) GCTScriptExecute(ctx context.Context, in *GCTScri
return out, nil
}
-func (c *goCryptoTraderClient) GCTScriptUpload(ctx context.Context, in *GCTScriptUploadRequest, opts ...grpc.CallOption) (*GCTScriptGenericResponse, error) {
- out := new(GCTScriptGenericResponse)
+func (c *goCryptoTraderClient) GCTScriptUpload(ctx context.Context, in *GCTScriptUploadRequest, opts ...grpc.CallOption) (*GenericResponse, error) {
+ out := new(GenericResponse)
err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/GCTScriptUpload", in, out, opts...)
if err != nil {
return nil, err
@@ -11649,8 +8331,8 @@ func (c *goCryptoTraderClient) GCTScriptQuery(ctx context.Context, in *GCTScript
return out, nil
}
-func (c *goCryptoTraderClient) GCTScriptStop(ctx context.Context, in *GCTScriptStopRequest, opts ...grpc.CallOption) (*GCTScriptGenericResponse, error) {
- out := new(GCTScriptGenericResponse)
+func (c *goCryptoTraderClient) GCTScriptStop(ctx context.Context, in *GCTScriptStopRequest, opts ...grpc.CallOption) (*GenericResponse, error) {
+ out := new(GenericResponse)
err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/GCTScriptStop", in, out, opts...)
if err != nil {
return nil, err
@@ -11658,8 +8340,8 @@ func (c *goCryptoTraderClient) GCTScriptStop(ctx context.Context, in *GCTScriptS
return out, nil
}
-func (c *goCryptoTraderClient) GCTScriptStopAll(ctx context.Context, in *GCTScriptStopAllRequest, opts ...grpc.CallOption) (*GCTScriptGenericResponse, error) {
- out := new(GCTScriptGenericResponse)
+func (c *goCryptoTraderClient) GCTScriptStopAll(ctx context.Context, in *GCTScriptStopAllRequest, opts ...grpc.CallOption) (*GenericResponse, error) {
+ out := new(GenericResponse)
err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/GCTScriptStopAll", in, out, opts...)
if err != nil {
return nil, err
@@ -11676,8 +8358,8 @@ func (c *goCryptoTraderClient) GCTScriptListAll(ctx context.Context, in *GCTScri
return out, nil
}
-func (c *goCryptoTraderClient) GCTScriptAutoLoadToggle(ctx context.Context, in *GCTScriptAutoLoadRequest, opts ...grpc.CallOption) (*GCTScriptGenericResponse, error) {
- out := new(GCTScriptGenericResponse)
+func (c *goCryptoTraderClient) GCTScriptAutoLoadToggle(ctx context.Context, in *GCTScriptAutoLoadRequest, opts ...grpc.CallOption) (*GenericResponse, error) {
+ out := new(GenericResponse)
err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/GCTScriptAutoLoadToggle", in, out, opts...)
if err != nil {
return nil, err
@@ -11694,20 +8376,101 @@ func (c *goCryptoTraderClient) GetHistoricCandles(ctx context.Context, in *GetHi
return out, nil
}
+func (c *goCryptoTraderClient) SetExchangeAsset(ctx context.Context, in *SetExchangeAssetRequest, opts ...grpc.CallOption) (*GenericResponse, error) {
+ out := new(GenericResponse)
+ err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/SetExchangeAsset", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *goCryptoTraderClient) SetAllExchangePairs(ctx context.Context, in *SetExchangeAllPairsRequest, opts ...grpc.CallOption) (*GenericResponse, error) {
+ out := new(GenericResponse)
+ err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/SetAllExchangePairs", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *goCryptoTraderClient) UpdateExchangeSupportedPairs(ctx context.Context, in *UpdateExchangeSupportedPairsRequest, opts ...grpc.CallOption) (*GenericResponse, error) {
+ out := new(GenericResponse)
+ err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/UpdateExchangeSupportedPairs", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *goCryptoTraderClient) GetExchangeAssets(ctx context.Context, in *GetExchangeAssetsRequest, opts ...grpc.CallOption) (*GetExchangeAssetsResponse, error) {
+ out := new(GetExchangeAssetsResponse)
+ err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/GetExchangeAssets", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *goCryptoTraderClient) WebsocketGetInfo(ctx context.Context, in *WebsocketGetInfoRequest, opts ...grpc.CallOption) (*WebsocketGetInfoResponse, error) {
+ out := new(WebsocketGetInfoResponse)
+ err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/WebsocketGetInfo", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *goCryptoTraderClient) WebsocketSetEnabled(ctx context.Context, in *WebsocketSetEnabledRequest, opts ...grpc.CallOption) (*GenericResponse, error) {
+ out := new(GenericResponse)
+ err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/WebsocketSetEnabled", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *goCryptoTraderClient) WebsocketGetSubscriptions(ctx context.Context, in *WebsocketGetSubscriptionsRequest, opts ...grpc.CallOption) (*WebsocketGetSubscriptionsResponse, error) {
+ out := new(WebsocketGetSubscriptionsResponse)
+ err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/WebsocketGetSubscriptions", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *goCryptoTraderClient) WebsocketSetProxy(ctx context.Context, in *WebsocketSetProxyRequest, opts ...grpc.CallOption) (*GenericResponse, error) {
+ out := new(GenericResponse)
+ err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/WebsocketSetProxy", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (c *goCryptoTraderClient) WebsocketSetURL(ctx context.Context, in *WebsocketSetURLRequest, opts ...grpc.CallOption) (*GenericResponse, error) {
+ out := new(GenericResponse)
+ err := c.cc.Invoke(ctx, "/gctrpc.GoCryptoTrader/WebsocketSetURL", in, out, opts...)
+ if err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
// GoCryptoTraderServer is the server API for GoCryptoTrader service.
type GoCryptoTraderServer interface {
GetInfo(context.Context, *GetInfoRequest) (*GetInfoResponse, error)
GetSubsystems(context.Context, *GetSubsystemsRequest) (*GetSusbsytemsResponse, error)
- EnableSubsystem(context.Context, *GenericSubsystemRequest) (*GenericSubsystemResponse, error)
- DisableSubsystem(context.Context, *GenericSubsystemRequest) (*GenericSubsystemResponse, error)
+ EnableSubsystem(context.Context, *GenericSubsystemRequest) (*GenericResponse, error)
+ DisableSubsystem(context.Context, *GenericSubsystemRequest) (*GenericResponse, error)
GetRPCEndpoints(context.Context, *GetRPCEndpointsRequest) (*GetRPCEndpointsResponse, error)
GetCommunicationRelayers(context.Context, *GetCommunicationRelayersRequest) (*GetCommunicationRelayersResponse, error)
GetExchanges(context.Context, *GetExchangesRequest) (*GetExchangesResponse, error)
- DisableExchange(context.Context, *GenericExchangeNameRequest) (*GenericExchangeNameResponse, error)
+ DisableExchange(context.Context, *GenericExchangeNameRequest) (*GenericResponse, error)
GetExchangeInfo(context.Context, *GenericExchangeNameRequest) (*GetExchangeInfoResponse, error)
GetExchangeOTPCode(context.Context, *GenericExchangeNameRequest) (*GetExchangeOTPReponse, error)
GetExchangeOTPCodes(context.Context, *GetExchangeOTPsRequest) (*GetExchangeOTPsResponse, error)
- EnableExchange(context.Context, *GenericExchangeNameRequest) (*GenericExchangeNameResponse, error)
+ EnableExchange(context.Context, *GenericExchangeNameRequest) (*GenericResponse, error)
GetTicker(context.Context, *GetTickerRequest) (*TickerResponse, error)
GetTickers(context.Context, *GetTickersRequest) (*GetTickersResponse, error)
GetOrderbook(context.Context, *GetOrderbookRequest) (*OrderbookResponse, error)
@@ -11717,8 +8480,8 @@ type GoCryptoTraderServer interface {
GetConfig(context.Context, *GetConfigRequest) (*GetConfigResponse, error)
GetPortfolio(context.Context, *GetPortfolioRequest) (*GetPortfolioResponse, error)
GetPortfolioSummary(context.Context, *GetPortfolioSummaryRequest) (*GetPortfolioSummaryResponse, error)
- AddPortfolioAddress(context.Context, *AddPortfolioAddressRequest) (*AddPortfolioAddressResponse, error)
- RemovePortfolioAddress(context.Context, *RemovePortfolioAddressRequest) (*RemovePortfolioAddressResponse, error)
+ AddPortfolioAddress(context.Context, *AddPortfolioAddressRequest) (*GenericResponse, error)
+ RemovePortfolioAddress(context.Context, *RemovePortfolioAddressRequest) (*GenericResponse, error)
GetForexProviders(context.Context, *GetForexProvidersRequest) (*GetForexProvidersResponse, error)
GetForexRates(context.Context, *GetForexRatesRequest) (*GetForexRatesResponse, error)
GetOrders(context.Context, *GetOrdersRequest) (*GetOrdersResponse, error)
@@ -11726,11 +8489,11 @@ type GoCryptoTraderServer interface {
SubmitOrder(context.Context, *SubmitOrderRequest) (*SubmitOrderResponse, error)
SimulateOrder(context.Context, *SimulateOrderRequest) (*SimulateOrderResponse, error)
WhaleBomb(context.Context, *WhaleBombRequest) (*SimulateOrderResponse, error)
- CancelOrder(context.Context, *CancelOrderRequest) (*CancelOrderResponse, error)
+ CancelOrder(context.Context, *CancelOrderRequest) (*GenericResponse, error)
CancelAllOrders(context.Context, *CancelAllOrdersRequest) (*CancelAllOrdersResponse, error)
GetEvents(context.Context, *GetEventsRequest) (*GetEventsResponse, error)
AddEvent(context.Context, *AddEventRequest) (*AddEventResponse, error)
- RemoveEvent(context.Context, *RemoveEventRequest) (*RemoveEventResponse, error)
+ RemoveEvent(context.Context, *RemoveEventRequest) (*GenericResponse, error)
GetCryptocurrencyDepositAddresses(context.Context, *GetCryptocurrencyDepositAddressesRequest) (*GetCryptocurrencyDepositAddressesResponse, error)
GetCryptocurrencyDepositAddress(context.Context, *GetCryptocurrencyDepositAddressRequest) (*GetCryptocurrencyDepositAddressResponse, error)
WithdrawFiatFunds(context.Context, *WithdrawFiatRequest) (*WithdrawResponse, error)
@@ -11741,215 +8504,247 @@ type GoCryptoTraderServer interface {
GetLoggerDetails(context.Context, *GetLoggerDetailsRequest) (*GetLoggerDetailsResponse, error)
SetLoggerDetails(context.Context, *SetLoggerDetailsRequest) (*GetLoggerDetailsResponse, error)
GetExchangePairs(context.Context, *GetExchangePairsRequest) (*GetExchangePairsResponse, error)
- EnableExchangePair(context.Context, *ExchangePairRequest) (*GenericExchangeNameResponse, error)
- DisableExchangePair(context.Context, *ExchangePairRequest) (*GenericExchangeNameResponse, error)
+ SetExchangePair(context.Context, *SetExchangePairRequest) (*GenericResponse, error)
GetOrderbookStream(*GetOrderbookStreamRequest, GoCryptoTrader_GetOrderbookStreamServer) error
GetExchangeOrderbookStream(*GetExchangeOrderbookStreamRequest, GoCryptoTrader_GetExchangeOrderbookStreamServer) error
GetTickerStream(*GetTickerStreamRequest, GoCryptoTrader_GetTickerStreamServer) error
GetExchangeTickerStream(*GetExchangeTickerStreamRequest, GoCryptoTrader_GetExchangeTickerStreamServer) error
GetAuditEvent(context.Context, *GetAuditEventRequest) (*GetAuditEventResponse, error)
- GCTScriptExecute(context.Context, *GCTScriptExecuteRequest) (*GCTScriptGenericResponse, error)
- GCTScriptUpload(context.Context, *GCTScriptUploadRequest) (*GCTScriptGenericResponse, error)
+ GCTScriptExecute(context.Context, *GCTScriptExecuteRequest) (*GenericResponse, error)
+ GCTScriptUpload(context.Context, *GCTScriptUploadRequest) (*GenericResponse, error)
GCTScriptReadScript(context.Context, *GCTScriptReadScriptRequest) (*GCTScriptQueryResponse, error)
GCTScriptStatus(context.Context, *GCTScriptStatusRequest) (*GCTScriptStatusResponse, error)
GCTScriptQuery(context.Context, *GCTScriptQueryRequest) (*GCTScriptQueryResponse, error)
- GCTScriptStop(context.Context, *GCTScriptStopRequest) (*GCTScriptGenericResponse, error)
- GCTScriptStopAll(context.Context, *GCTScriptStopAllRequest) (*GCTScriptGenericResponse, error)
+ GCTScriptStop(context.Context, *GCTScriptStopRequest) (*GenericResponse, error)
+ GCTScriptStopAll(context.Context, *GCTScriptStopAllRequest) (*GenericResponse, error)
GCTScriptListAll(context.Context, *GCTScriptListAllRequest) (*GCTScriptStatusResponse, error)
- GCTScriptAutoLoadToggle(context.Context, *GCTScriptAutoLoadRequest) (*GCTScriptGenericResponse, error)
+ GCTScriptAutoLoadToggle(context.Context, *GCTScriptAutoLoadRequest) (*GenericResponse, error)
GetHistoricCandles(context.Context, *GetHistoricCandlesRequest) (*GetHistoricCandlesResponse, error)
+ SetExchangeAsset(context.Context, *SetExchangeAssetRequest) (*GenericResponse, error)
+ SetAllExchangePairs(context.Context, *SetExchangeAllPairsRequest) (*GenericResponse, error)
+ UpdateExchangeSupportedPairs(context.Context, *UpdateExchangeSupportedPairsRequest) (*GenericResponse, error)
+ GetExchangeAssets(context.Context, *GetExchangeAssetsRequest) (*GetExchangeAssetsResponse, error)
+ WebsocketGetInfo(context.Context, *WebsocketGetInfoRequest) (*WebsocketGetInfoResponse, error)
+ WebsocketSetEnabled(context.Context, *WebsocketSetEnabledRequest) (*GenericResponse, error)
+ WebsocketGetSubscriptions(context.Context, *WebsocketGetSubscriptionsRequest) (*WebsocketGetSubscriptionsResponse, error)
+ WebsocketSetProxy(context.Context, *WebsocketSetProxyRequest) (*GenericResponse, error)
+ WebsocketSetURL(context.Context, *WebsocketSetURLRequest) (*GenericResponse, error)
}
// UnimplementedGoCryptoTraderServer can be embedded to have forward compatible implementations.
type UnimplementedGoCryptoTraderServer struct {
}
-func (*UnimplementedGoCryptoTraderServer) GetInfo(context.Context, *GetInfoRequest) (*GetInfoResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GetInfo(ctx context.Context, req *GetInfoRequest) (*GetInfoResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetInfo not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetSubsystems(context.Context, *GetSubsystemsRequest) (*GetSusbsytemsResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GetSubsystems(ctx context.Context, req *GetSubsystemsRequest) (*GetSusbsytemsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetSubsystems not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) EnableSubsystem(context.Context, *GenericSubsystemRequest) (*GenericSubsystemResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) EnableSubsystem(ctx context.Context, req *GenericSubsystemRequest) (*GenericResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method EnableSubsystem not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) DisableSubsystem(context.Context, *GenericSubsystemRequest) (*GenericSubsystemResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) DisableSubsystem(ctx context.Context, req *GenericSubsystemRequest) (*GenericResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method DisableSubsystem not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetRPCEndpoints(context.Context, *GetRPCEndpointsRequest) (*GetRPCEndpointsResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GetRPCEndpoints(ctx context.Context, req *GetRPCEndpointsRequest) (*GetRPCEndpointsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetRPCEndpoints not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetCommunicationRelayers(context.Context, *GetCommunicationRelayersRequest) (*GetCommunicationRelayersResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GetCommunicationRelayers(ctx context.Context, req *GetCommunicationRelayersRequest) (*GetCommunicationRelayersResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetCommunicationRelayers not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetExchanges(context.Context, *GetExchangesRequest) (*GetExchangesResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GetExchanges(ctx context.Context, req *GetExchangesRequest) (*GetExchangesResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetExchanges not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) DisableExchange(context.Context, *GenericExchangeNameRequest) (*GenericExchangeNameResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) DisableExchange(ctx context.Context, req *GenericExchangeNameRequest) (*GenericResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method DisableExchange not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetExchangeInfo(context.Context, *GenericExchangeNameRequest) (*GetExchangeInfoResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GetExchangeInfo(ctx context.Context, req *GenericExchangeNameRequest) (*GetExchangeInfoResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetExchangeInfo not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetExchangeOTPCode(context.Context, *GenericExchangeNameRequest) (*GetExchangeOTPReponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GetExchangeOTPCode(ctx context.Context, req *GenericExchangeNameRequest) (*GetExchangeOTPReponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetExchangeOTPCode not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetExchangeOTPCodes(context.Context, *GetExchangeOTPsRequest) (*GetExchangeOTPsResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GetExchangeOTPCodes(ctx context.Context, req *GetExchangeOTPsRequest) (*GetExchangeOTPsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetExchangeOTPCodes not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) EnableExchange(context.Context, *GenericExchangeNameRequest) (*GenericExchangeNameResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) EnableExchange(ctx context.Context, req *GenericExchangeNameRequest) (*GenericResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method EnableExchange not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetTicker(context.Context, *GetTickerRequest) (*TickerResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GetTicker(ctx context.Context, req *GetTickerRequest) (*TickerResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetTicker not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetTickers(context.Context, *GetTickersRequest) (*GetTickersResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GetTickers(ctx context.Context, req *GetTickersRequest) (*GetTickersResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetTickers not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetOrderbook(context.Context, *GetOrderbookRequest) (*OrderbookResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GetOrderbook(ctx context.Context, req *GetOrderbookRequest) (*OrderbookResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetOrderbook not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetOrderbooks(context.Context, *GetOrderbooksRequest) (*GetOrderbooksResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GetOrderbooks(ctx context.Context, req *GetOrderbooksRequest) (*GetOrderbooksResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetOrderbooks not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetAccountInfo(context.Context, *GetAccountInfoRequest) (*GetAccountInfoResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GetAccountInfo(ctx context.Context, req *GetAccountInfoRequest) (*GetAccountInfoResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetAccountInfo not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetAccountInfoStream(*GetAccountInfoRequest, GoCryptoTrader_GetAccountInfoStreamServer) error {
+func (*UnimplementedGoCryptoTraderServer) GetAccountInfoStream(req *GetAccountInfoRequest, srv GoCryptoTrader_GetAccountInfoStreamServer) error {
return status.Errorf(codes.Unimplemented, "method GetAccountInfoStream not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetConfig(context.Context, *GetConfigRequest) (*GetConfigResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GetConfig(ctx context.Context, req *GetConfigRequest) (*GetConfigResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetConfig not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetPortfolio(context.Context, *GetPortfolioRequest) (*GetPortfolioResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GetPortfolio(ctx context.Context, req *GetPortfolioRequest) (*GetPortfolioResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetPortfolio not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetPortfolioSummary(context.Context, *GetPortfolioSummaryRequest) (*GetPortfolioSummaryResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GetPortfolioSummary(ctx context.Context, req *GetPortfolioSummaryRequest) (*GetPortfolioSummaryResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetPortfolioSummary not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) AddPortfolioAddress(context.Context, *AddPortfolioAddressRequest) (*AddPortfolioAddressResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) AddPortfolioAddress(ctx context.Context, req *AddPortfolioAddressRequest) (*GenericResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method AddPortfolioAddress not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) RemovePortfolioAddress(context.Context, *RemovePortfolioAddressRequest) (*RemovePortfolioAddressResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) RemovePortfolioAddress(ctx context.Context, req *RemovePortfolioAddressRequest) (*GenericResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method RemovePortfolioAddress not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetForexProviders(context.Context, *GetForexProvidersRequest) (*GetForexProvidersResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GetForexProviders(ctx context.Context, req *GetForexProvidersRequest) (*GetForexProvidersResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetForexProviders not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetForexRates(context.Context, *GetForexRatesRequest) (*GetForexRatesResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GetForexRates(ctx context.Context, req *GetForexRatesRequest) (*GetForexRatesResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetForexRates not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetOrders(context.Context, *GetOrdersRequest) (*GetOrdersResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GetOrders(ctx context.Context, req *GetOrdersRequest) (*GetOrdersResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetOrders not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetOrder(context.Context, *GetOrderRequest) (*OrderDetails, error) {
+func (*UnimplementedGoCryptoTraderServer) GetOrder(ctx context.Context, req *GetOrderRequest) (*OrderDetails, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetOrder not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) SubmitOrder(context.Context, *SubmitOrderRequest) (*SubmitOrderResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) SubmitOrder(ctx context.Context, req *SubmitOrderRequest) (*SubmitOrderResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method SubmitOrder not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) SimulateOrder(context.Context, *SimulateOrderRequest) (*SimulateOrderResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) SimulateOrder(ctx context.Context, req *SimulateOrderRequest) (*SimulateOrderResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method SimulateOrder not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) WhaleBomb(context.Context, *WhaleBombRequest) (*SimulateOrderResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) WhaleBomb(ctx context.Context, req *WhaleBombRequest) (*SimulateOrderResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method WhaleBomb not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) CancelOrder(context.Context, *CancelOrderRequest) (*CancelOrderResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) CancelOrder(ctx context.Context, req *CancelOrderRequest) (*GenericResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method CancelOrder not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) CancelAllOrders(context.Context, *CancelAllOrdersRequest) (*CancelAllOrdersResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) CancelAllOrders(ctx context.Context, req *CancelAllOrdersRequest) (*CancelAllOrdersResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method CancelAllOrders not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetEvents(context.Context, *GetEventsRequest) (*GetEventsResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GetEvents(ctx context.Context, req *GetEventsRequest) (*GetEventsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetEvents not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) AddEvent(context.Context, *AddEventRequest) (*AddEventResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) AddEvent(ctx context.Context, req *AddEventRequest) (*AddEventResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method AddEvent not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) RemoveEvent(context.Context, *RemoveEventRequest) (*RemoveEventResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) RemoveEvent(ctx context.Context, req *RemoveEventRequest) (*GenericResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method RemoveEvent not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetCryptocurrencyDepositAddresses(context.Context, *GetCryptocurrencyDepositAddressesRequest) (*GetCryptocurrencyDepositAddressesResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GetCryptocurrencyDepositAddresses(ctx context.Context, req *GetCryptocurrencyDepositAddressesRequest) (*GetCryptocurrencyDepositAddressesResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetCryptocurrencyDepositAddresses not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetCryptocurrencyDepositAddress(context.Context, *GetCryptocurrencyDepositAddressRequest) (*GetCryptocurrencyDepositAddressResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GetCryptocurrencyDepositAddress(ctx context.Context, req *GetCryptocurrencyDepositAddressRequest) (*GetCryptocurrencyDepositAddressResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetCryptocurrencyDepositAddress not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) WithdrawFiatFunds(context.Context, *WithdrawFiatRequest) (*WithdrawResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) WithdrawFiatFunds(ctx context.Context, req *WithdrawFiatRequest) (*WithdrawResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method WithdrawFiatFunds not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) WithdrawCryptocurrencyFunds(context.Context, *WithdrawCryptoRequest) (*WithdrawResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) WithdrawCryptocurrencyFunds(ctx context.Context, req *WithdrawCryptoRequest) (*WithdrawResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method WithdrawCryptocurrencyFunds not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) WithdrawalEventByID(context.Context, *WithdrawalEventByIDRequest) (*WithdrawalEventByIDResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) WithdrawalEventByID(ctx context.Context, req *WithdrawalEventByIDRequest) (*WithdrawalEventByIDResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method WithdrawalEventByID not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) WithdrawalEventsByExchange(context.Context, *WithdrawalEventsByExchangeRequest) (*WithdrawalEventsByExchangeResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) WithdrawalEventsByExchange(ctx context.Context, req *WithdrawalEventsByExchangeRequest) (*WithdrawalEventsByExchangeResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method WithdrawalEventsByExchange not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) WithdrawalEventsByDate(context.Context, *WithdrawalEventsByDateRequest) (*WithdrawalEventsByExchangeResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) WithdrawalEventsByDate(ctx context.Context, req *WithdrawalEventsByDateRequest) (*WithdrawalEventsByExchangeResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method WithdrawalEventsByDate not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetLoggerDetails(context.Context, *GetLoggerDetailsRequest) (*GetLoggerDetailsResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GetLoggerDetails(ctx context.Context, req *GetLoggerDetailsRequest) (*GetLoggerDetailsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetLoggerDetails not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) SetLoggerDetails(context.Context, *SetLoggerDetailsRequest) (*GetLoggerDetailsResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) SetLoggerDetails(ctx context.Context, req *SetLoggerDetailsRequest) (*GetLoggerDetailsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method SetLoggerDetails not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetExchangePairs(context.Context, *GetExchangePairsRequest) (*GetExchangePairsResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GetExchangePairs(ctx context.Context, req *GetExchangePairsRequest) (*GetExchangePairsResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetExchangePairs not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) EnableExchangePair(context.Context, *ExchangePairRequest) (*GenericExchangeNameResponse, error) {
- return nil, status.Errorf(codes.Unimplemented, "method EnableExchangePair not implemented")
+func (*UnimplementedGoCryptoTraderServer) SetExchangePair(ctx context.Context, req *SetExchangePairRequest) (*GenericResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method SetExchangePair not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) DisableExchangePair(context.Context, *ExchangePairRequest) (*GenericExchangeNameResponse, error) {
- return nil, status.Errorf(codes.Unimplemented, "method DisableExchangePair not implemented")
-}
-func (*UnimplementedGoCryptoTraderServer) GetOrderbookStream(*GetOrderbookStreamRequest, GoCryptoTrader_GetOrderbookStreamServer) error {
+func (*UnimplementedGoCryptoTraderServer) GetOrderbookStream(req *GetOrderbookStreamRequest, srv GoCryptoTrader_GetOrderbookStreamServer) error {
return status.Errorf(codes.Unimplemented, "method GetOrderbookStream not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetExchangeOrderbookStream(*GetExchangeOrderbookStreamRequest, GoCryptoTrader_GetExchangeOrderbookStreamServer) error {
+func (*UnimplementedGoCryptoTraderServer) GetExchangeOrderbookStream(req *GetExchangeOrderbookStreamRequest, srv GoCryptoTrader_GetExchangeOrderbookStreamServer) error {
return status.Errorf(codes.Unimplemented, "method GetExchangeOrderbookStream not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetTickerStream(*GetTickerStreamRequest, GoCryptoTrader_GetTickerStreamServer) error {
+func (*UnimplementedGoCryptoTraderServer) GetTickerStream(req *GetTickerStreamRequest, srv GoCryptoTrader_GetTickerStreamServer) error {
return status.Errorf(codes.Unimplemented, "method GetTickerStream not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetExchangeTickerStream(*GetExchangeTickerStreamRequest, GoCryptoTrader_GetExchangeTickerStreamServer) error {
+func (*UnimplementedGoCryptoTraderServer) GetExchangeTickerStream(req *GetExchangeTickerStreamRequest, srv GoCryptoTrader_GetExchangeTickerStreamServer) error {
return status.Errorf(codes.Unimplemented, "method GetExchangeTickerStream not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetAuditEvent(context.Context, *GetAuditEventRequest) (*GetAuditEventResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GetAuditEvent(ctx context.Context, req *GetAuditEventRequest) (*GetAuditEventResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetAuditEvent not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GCTScriptExecute(context.Context, *GCTScriptExecuteRequest) (*GCTScriptGenericResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GCTScriptExecute(ctx context.Context, req *GCTScriptExecuteRequest) (*GenericResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GCTScriptExecute not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GCTScriptUpload(context.Context, *GCTScriptUploadRequest) (*GCTScriptGenericResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GCTScriptUpload(ctx context.Context, req *GCTScriptUploadRequest) (*GenericResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GCTScriptUpload not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GCTScriptReadScript(context.Context, *GCTScriptReadScriptRequest) (*GCTScriptQueryResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GCTScriptReadScript(ctx context.Context, req *GCTScriptReadScriptRequest) (*GCTScriptQueryResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GCTScriptReadScript not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GCTScriptStatus(context.Context, *GCTScriptStatusRequest) (*GCTScriptStatusResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GCTScriptStatus(ctx context.Context, req *GCTScriptStatusRequest) (*GCTScriptStatusResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GCTScriptStatus not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GCTScriptQuery(context.Context, *GCTScriptQueryRequest) (*GCTScriptQueryResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GCTScriptQuery(ctx context.Context, req *GCTScriptQueryRequest) (*GCTScriptQueryResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GCTScriptQuery not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GCTScriptStop(context.Context, *GCTScriptStopRequest) (*GCTScriptGenericResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GCTScriptStop(ctx context.Context, req *GCTScriptStopRequest) (*GenericResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GCTScriptStop not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GCTScriptStopAll(context.Context, *GCTScriptStopAllRequest) (*GCTScriptGenericResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GCTScriptStopAll(ctx context.Context, req *GCTScriptStopAllRequest) (*GenericResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GCTScriptStopAll not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GCTScriptListAll(context.Context, *GCTScriptListAllRequest) (*GCTScriptStatusResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GCTScriptListAll(ctx context.Context, req *GCTScriptListAllRequest) (*GCTScriptStatusResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GCTScriptListAll not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GCTScriptAutoLoadToggle(context.Context, *GCTScriptAutoLoadRequest) (*GCTScriptGenericResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GCTScriptAutoLoadToggle(ctx context.Context, req *GCTScriptAutoLoadRequest) (*GenericResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GCTScriptAutoLoadToggle not implemented")
}
-func (*UnimplementedGoCryptoTraderServer) GetHistoricCandles(context.Context, *GetHistoricCandlesRequest) (*GetHistoricCandlesResponse, error) {
+func (*UnimplementedGoCryptoTraderServer) GetHistoricCandles(ctx context.Context, req *GetHistoricCandlesRequest) (*GetHistoricCandlesResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetHistoricCandles not implemented")
}
+func (*UnimplementedGoCryptoTraderServer) SetExchangeAsset(ctx context.Context, req *SetExchangeAssetRequest) (*GenericResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method SetExchangeAsset not implemented")
+}
+func (*UnimplementedGoCryptoTraderServer) SetAllExchangePairs(ctx context.Context, req *SetExchangeAllPairsRequest) (*GenericResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method SetAllExchangePairs not implemented")
+}
+func (*UnimplementedGoCryptoTraderServer) UpdateExchangeSupportedPairs(ctx context.Context, req *UpdateExchangeSupportedPairsRequest) (*GenericResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method UpdateExchangeSupportedPairs not implemented")
+}
+func (*UnimplementedGoCryptoTraderServer) GetExchangeAssets(ctx context.Context, req *GetExchangeAssetsRequest) (*GetExchangeAssetsResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method GetExchangeAssets not implemented")
+}
+func (*UnimplementedGoCryptoTraderServer) WebsocketGetInfo(ctx context.Context, req *WebsocketGetInfoRequest) (*WebsocketGetInfoResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method WebsocketGetInfo not implemented")
+}
+func (*UnimplementedGoCryptoTraderServer) WebsocketSetEnabled(ctx context.Context, req *WebsocketSetEnabledRequest) (*GenericResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method WebsocketSetEnabled not implemented")
+}
+func (*UnimplementedGoCryptoTraderServer) WebsocketGetSubscriptions(ctx context.Context, req *WebsocketGetSubscriptionsRequest) (*WebsocketGetSubscriptionsResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method WebsocketGetSubscriptions not implemented")
+}
+func (*UnimplementedGoCryptoTraderServer) WebsocketSetProxy(ctx context.Context, req *WebsocketSetProxyRequest) (*GenericResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method WebsocketSetProxy not implemented")
+}
+func (*UnimplementedGoCryptoTraderServer) WebsocketSetURL(ctx context.Context, req *WebsocketSetURLRequest) (*GenericResponse, error) {
+ return nil, status.Errorf(codes.Unimplemented, "method WebsocketSetURL not implemented")
+}
func RegisterGoCryptoTraderServer(s *grpc.Server, srv GoCryptoTraderServer) {
s.RegisterService(&_GoCryptoTrader_serviceDesc, srv)
@@ -12768,38 +9563,20 @@ func _GoCryptoTrader_GetExchangePairs_Handler(srv interface{}, ctx context.Conte
return interceptor(ctx, in, info, handler)
}
-func _GoCryptoTrader_EnableExchangePair_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
- in := new(ExchangePairRequest)
+func _GoCryptoTrader_SetExchangePair_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(SetExchangePairRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
- return srv.(GoCryptoTraderServer).EnableExchangePair(ctx, in)
+ return srv.(GoCryptoTraderServer).SetExchangePair(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
- FullMethod: "/gctrpc.GoCryptoTrader/EnableExchangePair",
+ FullMethod: "/gctrpc.GoCryptoTrader/SetExchangePair",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
- return srv.(GoCryptoTraderServer).EnableExchangePair(ctx, req.(*ExchangePairRequest))
- }
- return interceptor(ctx, in, info, handler)
-}
-
-func _GoCryptoTrader_DisableExchangePair_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
- in := new(ExchangePairRequest)
- if err := dec(in); err != nil {
- return nil, err
- }
- if interceptor == nil {
- return srv.(GoCryptoTraderServer).DisableExchangePair(ctx, in)
- }
- info := &grpc.UnaryServerInfo{
- Server: srv,
- FullMethod: "/gctrpc.GoCryptoTrader/DisableExchangePair",
- }
- handler := func(ctx context.Context, req interface{}) (interface{}, error) {
- return srv.(GoCryptoTraderServer).DisableExchangePair(ctx, req.(*ExchangePairRequest))
+ return srv.(GoCryptoTraderServer).SetExchangePair(ctx, req.(*SetExchangePairRequest))
}
return interceptor(ctx, in, info, handler)
}
@@ -13086,6 +9863,168 @@ func _GoCryptoTrader_GetHistoricCandles_Handler(srv interface{}, ctx context.Con
return interceptor(ctx, in, info, handler)
}
+func _GoCryptoTrader_SetExchangeAsset_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(SetExchangeAssetRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(GoCryptoTraderServer).SetExchangeAsset(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/gctrpc.GoCryptoTrader/SetExchangeAsset",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(GoCryptoTraderServer).SetExchangeAsset(ctx, req.(*SetExchangeAssetRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _GoCryptoTrader_SetAllExchangePairs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(SetExchangeAllPairsRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(GoCryptoTraderServer).SetAllExchangePairs(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/gctrpc.GoCryptoTrader/SetAllExchangePairs",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(GoCryptoTraderServer).SetAllExchangePairs(ctx, req.(*SetExchangeAllPairsRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _GoCryptoTrader_UpdateExchangeSupportedPairs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(UpdateExchangeSupportedPairsRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(GoCryptoTraderServer).UpdateExchangeSupportedPairs(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/gctrpc.GoCryptoTrader/UpdateExchangeSupportedPairs",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(GoCryptoTraderServer).UpdateExchangeSupportedPairs(ctx, req.(*UpdateExchangeSupportedPairsRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _GoCryptoTrader_GetExchangeAssets_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(GetExchangeAssetsRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(GoCryptoTraderServer).GetExchangeAssets(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/gctrpc.GoCryptoTrader/GetExchangeAssets",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(GoCryptoTraderServer).GetExchangeAssets(ctx, req.(*GetExchangeAssetsRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _GoCryptoTrader_WebsocketGetInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(WebsocketGetInfoRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(GoCryptoTraderServer).WebsocketGetInfo(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/gctrpc.GoCryptoTrader/WebsocketGetInfo",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(GoCryptoTraderServer).WebsocketGetInfo(ctx, req.(*WebsocketGetInfoRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _GoCryptoTrader_WebsocketSetEnabled_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(WebsocketSetEnabledRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(GoCryptoTraderServer).WebsocketSetEnabled(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/gctrpc.GoCryptoTrader/WebsocketSetEnabled",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(GoCryptoTraderServer).WebsocketSetEnabled(ctx, req.(*WebsocketSetEnabledRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _GoCryptoTrader_WebsocketGetSubscriptions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(WebsocketGetSubscriptionsRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(GoCryptoTraderServer).WebsocketGetSubscriptions(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/gctrpc.GoCryptoTrader/WebsocketGetSubscriptions",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(GoCryptoTraderServer).WebsocketGetSubscriptions(ctx, req.(*WebsocketGetSubscriptionsRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _GoCryptoTrader_WebsocketSetProxy_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(WebsocketSetProxyRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(GoCryptoTraderServer).WebsocketSetProxy(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/gctrpc.GoCryptoTrader/WebsocketSetProxy",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(GoCryptoTraderServer).WebsocketSetProxy(ctx, req.(*WebsocketSetProxyRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
+func _GoCryptoTrader_WebsocketSetURL_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
+ in := new(WebsocketSetURLRequest)
+ if err := dec(in); err != nil {
+ return nil, err
+ }
+ if interceptor == nil {
+ return srv.(GoCryptoTraderServer).WebsocketSetURL(ctx, in)
+ }
+ info := &grpc.UnaryServerInfo{
+ Server: srv,
+ FullMethod: "/gctrpc.GoCryptoTrader/WebsocketSetURL",
+ }
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) {
+ return srv.(GoCryptoTraderServer).WebsocketSetURL(ctx, req.(*WebsocketSetURLRequest))
+ }
+ return interceptor(ctx, in, info, handler)
+}
+
var _GoCryptoTrader_serviceDesc = grpc.ServiceDesc{
ServiceName: "gctrpc.GoCryptoTrader",
HandlerType: (*GoCryptoTraderServer)(nil),
@@ -13267,12 +10206,8 @@ var _GoCryptoTrader_serviceDesc = grpc.ServiceDesc{
Handler: _GoCryptoTrader_GetExchangePairs_Handler,
},
{
- MethodName: "EnableExchangePair",
- Handler: _GoCryptoTrader_EnableExchangePair_Handler,
- },
- {
- MethodName: "DisableExchangePair",
- Handler: _GoCryptoTrader_DisableExchangePair_Handler,
+ MethodName: "SetExchangePair",
+ Handler: _GoCryptoTrader_SetExchangePair_Handler,
},
{
MethodName: "GetAuditEvent",
@@ -13318,6 +10253,42 @@ var _GoCryptoTrader_serviceDesc = grpc.ServiceDesc{
MethodName: "GetHistoricCandles",
Handler: _GoCryptoTrader_GetHistoricCandles_Handler,
},
+ {
+ MethodName: "SetExchangeAsset",
+ Handler: _GoCryptoTrader_SetExchangeAsset_Handler,
+ },
+ {
+ MethodName: "SetAllExchangePairs",
+ Handler: _GoCryptoTrader_SetAllExchangePairs_Handler,
+ },
+ {
+ MethodName: "UpdateExchangeSupportedPairs",
+ Handler: _GoCryptoTrader_UpdateExchangeSupportedPairs_Handler,
+ },
+ {
+ MethodName: "GetExchangeAssets",
+ Handler: _GoCryptoTrader_GetExchangeAssets_Handler,
+ },
+ {
+ MethodName: "WebsocketGetInfo",
+ Handler: _GoCryptoTrader_WebsocketGetInfo_Handler,
+ },
+ {
+ MethodName: "WebsocketSetEnabled",
+ Handler: _GoCryptoTrader_WebsocketSetEnabled_Handler,
+ },
+ {
+ MethodName: "WebsocketGetSubscriptions",
+ Handler: _GoCryptoTrader_WebsocketGetSubscriptions_Handler,
+ },
+ {
+ MethodName: "WebsocketSetProxy",
+ Handler: _GoCryptoTrader_WebsocketSetProxy_Handler,
+ },
+ {
+ MethodName: "WebsocketSetURL",
+ Handler: _GoCryptoTrader_WebsocketSetURL_Handler,
+ },
},
Streams: []grpc.StreamDesc{
{
diff --git a/gctrpc/rpc.pb.gw.go b/gctrpc/rpc.pb.gw.go
index 97f3615a..ae8bcfd6 100644
--- a/gctrpc/rpc.pb.gw.go
+++ b/gctrpc/rpc.pb.gw.go
@@ -91,10 +91,7 @@ func local_request_GoCryptoTrader_EnableSubsystem_0(ctx context.Context, marshal
var protoReq GenericSubsystemRequest
var metadata runtime.ServerMetadata
- if err := req.ParseForm(); err != nil {
- return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
- }
- if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_EnableSubsystem_0); err != nil {
+ if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_EnableSubsystem_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@@ -127,10 +124,7 @@ func local_request_GoCryptoTrader_DisableSubsystem_0(ctx context.Context, marsha
var protoReq GenericSubsystemRequest
var metadata runtime.ServerMetadata
- if err := req.ParseForm(); err != nil {
- return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
- }
- if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_DisableSubsystem_0); err != nil {
+ if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_DisableSubsystem_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@@ -199,10 +193,7 @@ func local_request_GoCryptoTrader_GetExchanges_0(ctx context.Context, marshaler
var protoReq GetExchangesRequest
var metadata runtime.ServerMetadata
- if err := req.ParseForm(); err != nil {
- return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
- }
- if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GetExchanges_0); err != nil {
+ if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GetExchanges_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@@ -269,10 +260,7 @@ func local_request_GoCryptoTrader_GetExchangeInfo_0(ctx context.Context, marshal
var protoReq GenericExchangeNameRequest
var metadata runtime.ServerMetadata
- if err := req.ParseForm(); err != nil {
- return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
- }
- if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GetExchangeInfo_0); err != nil {
+ if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GetExchangeInfo_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@@ -305,10 +293,7 @@ func local_request_GoCryptoTrader_GetExchangeOTPCode_0(ctx context.Context, mars
var protoReq GenericExchangeNameRequest
var metadata runtime.ServerMetadata
- if err := req.ParseForm(); err != nil {
- return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
- }
- if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GetExchangeOTPCode_0); err != nil {
+ if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GetExchangeOTPCode_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@@ -497,10 +482,7 @@ func local_request_GoCryptoTrader_GetAccountInfo_0(ctx context.Context, marshale
var protoReq GetAccountInfoRequest
var metadata runtime.ServerMetadata
- if err := req.ParseForm(); err != nil {
- return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
- }
- if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GetAccountInfo_0); err != nil {
+ if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GetAccountInfo_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@@ -1281,10 +1263,7 @@ func local_request_GoCryptoTrader_GetLoggerDetails_0(ctx context.Context, marsha
var protoReq GetLoggerDetailsRequest
var metadata runtime.ServerMetadata
- if err := req.ParseForm(); err != nil {
- return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
- }
- if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GetLoggerDetails_0); err != nil {
+ if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GetLoggerDetails_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@@ -1361,8 +1340,8 @@ func local_request_GoCryptoTrader_GetExchangePairs_0(ctx context.Context, marsha
}
-func request_GoCryptoTrader_EnableExchangePair_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
- var protoReq ExchangePairRequest
+func request_GoCryptoTrader_SetExchangePair_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq SetExchangePairRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
@@ -1373,13 +1352,13 @@ func request_GoCryptoTrader_EnableExchangePair_0(ctx context.Context, marshaler
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
- msg, err := client.EnableExchangePair(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ msg, err := client.SetExchangePair(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
-func local_request_GoCryptoTrader_EnableExchangePair_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
- var protoReq ExchangePairRequest
+func local_request_GoCryptoTrader_SetExchangePair_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq SetExchangePairRequest
var metadata runtime.ServerMetadata
newReader, berr := utilities.IOReaderFactory(req.Body)
@@ -1390,41 +1369,7 @@ func local_request_GoCryptoTrader_EnableExchangePair_0(ctx context.Context, mars
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
- msg, err := server.EnableExchangePair(ctx, &protoReq)
- return msg, metadata, err
-
-}
-
-func request_GoCryptoTrader_DisableExchangePair_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
- var protoReq ExchangePairRequest
- var metadata runtime.ServerMetadata
-
- newReader, berr := utilities.IOReaderFactory(req.Body)
- if berr != nil {
- return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
- }
- if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
- return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
- }
-
- msg, err := client.DisableExchangePair(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
- return msg, metadata, err
-
-}
-
-func local_request_GoCryptoTrader_DisableExchangePair_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
- var protoReq ExchangePairRequest
- var metadata runtime.ServerMetadata
-
- newReader, berr := utilities.IOReaderFactory(req.Body)
- if berr != nil {
- return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
- }
- if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
- return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
- }
-
- msg, err := server.DisableExchangePair(ctx, &protoReq)
+ msg, err := server.SetExchangePair(ctx, &protoReq)
return msg, metadata, err
}
@@ -1565,10 +1510,7 @@ func local_request_GoCryptoTrader_GetAuditEvent_0(ctx context.Context, marshaler
var protoReq GetAuditEventRequest
var metadata runtime.ServerMetadata
- if err := req.ParseForm(); err != nil {
- return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
- }
- if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GetAuditEvent_0); err != nil {
+ if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GetAuditEvent_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@@ -1601,10 +1543,7 @@ func local_request_GoCryptoTrader_GCTScriptExecute_0(ctx context.Context, marsha
var protoReq GCTScriptExecuteRequest
var metadata runtime.ServerMetadata
- if err := req.ParseForm(); err != nil {
- return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
- }
- if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GCTScriptExecute_0); err != nil {
+ if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GCTScriptExecute_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@@ -1723,10 +1662,7 @@ func local_request_GoCryptoTrader_GCTScriptQuery_0(ctx context.Context, marshale
var protoReq GCTScriptQueryRequest
var metadata runtime.ServerMetadata
- if err := req.ParseForm(); err != nil {
- return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
- }
- if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GCTScriptQuery_0); err != nil {
+ if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GCTScriptQuery_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@@ -1895,10 +1831,7 @@ func local_request_GoCryptoTrader_GetHistoricCandles_0(ctx context.Context, mars
var protoReq GetHistoricCandlesRequest
var metadata runtime.ServerMetadata
- if err := req.ParseForm(); err != nil {
- return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
- }
- if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GetHistoricCandles_0); err != nil {
+ if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GetHistoricCandles_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@@ -1907,6 +1840,303 @@ func local_request_GoCryptoTrader_GetHistoricCandles_0(ctx context.Context, mars
}
+var (
+ filter_GoCryptoTrader_SetExchangeAsset_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
+)
+
+func request_GoCryptoTrader_SetExchangeAsset_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq SetExchangeAssetRequest
+ var metadata runtime.ServerMetadata
+
+ if err := req.ParseForm(); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+ if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_SetExchangeAsset_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.SetExchangeAsset(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_GoCryptoTrader_SetExchangeAsset_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq SetExchangeAssetRequest
+ var metadata runtime.ServerMetadata
+
+ if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_SetExchangeAsset_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.SetExchangeAsset(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+var (
+ filter_GoCryptoTrader_SetAllExchangePairs_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
+)
+
+func request_GoCryptoTrader_SetAllExchangePairs_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq SetExchangeAllPairsRequest
+ var metadata runtime.ServerMetadata
+
+ if err := req.ParseForm(); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+ if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_SetAllExchangePairs_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.SetAllExchangePairs(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_GoCryptoTrader_SetAllExchangePairs_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq SetExchangeAllPairsRequest
+ var metadata runtime.ServerMetadata
+
+ if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_SetAllExchangePairs_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.SetAllExchangePairs(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+var (
+ filter_GoCryptoTrader_UpdateExchangeSupportedPairs_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
+)
+
+func request_GoCryptoTrader_UpdateExchangeSupportedPairs_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq UpdateExchangeSupportedPairsRequest
+ var metadata runtime.ServerMetadata
+
+ if err := req.ParseForm(); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+ if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_UpdateExchangeSupportedPairs_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.UpdateExchangeSupportedPairs(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_GoCryptoTrader_UpdateExchangeSupportedPairs_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq UpdateExchangeSupportedPairsRequest
+ var metadata runtime.ServerMetadata
+
+ if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_UpdateExchangeSupportedPairs_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.UpdateExchangeSupportedPairs(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+var (
+ filter_GoCryptoTrader_GetExchangeAssets_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
+)
+
+func request_GoCryptoTrader_GetExchangeAssets_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq GetExchangeAssetsRequest
+ var metadata runtime.ServerMetadata
+
+ if err := req.ParseForm(); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+ if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GetExchangeAssets_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.GetExchangeAssets(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_GoCryptoTrader_GetExchangeAssets_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq GetExchangeAssetsRequest
+ var metadata runtime.ServerMetadata
+
+ if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GetExchangeAssets_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.GetExchangeAssets(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+var (
+ filter_GoCryptoTrader_WebsocketGetInfo_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
+)
+
+func request_GoCryptoTrader_WebsocketGetInfo_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq WebsocketGetInfoRequest
+ var metadata runtime.ServerMetadata
+
+ if err := req.ParseForm(); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+ if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_WebsocketGetInfo_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.WebsocketGetInfo(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_GoCryptoTrader_WebsocketGetInfo_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq WebsocketGetInfoRequest
+ var metadata runtime.ServerMetadata
+
+ if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_WebsocketGetInfo_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.WebsocketGetInfo(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+var (
+ filter_GoCryptoTrader_WebsocketSetEnabled_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
+)
+
+func request_GoCryptoTrader_WebsocketSetEnabled_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq WebsocketSetEnabledRequest
+ var metadata runtime.ServerMetadata
+
+ if err := req.ParseForm(); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+ if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_WebsocketSetEnabled_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.WebsocketSetEnabled(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_GoCryptoTrader_WebsocketSetEnabled_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq WebsocketSetEnabledRequest
+ var metadata runtime.ServerMetadata
+
+ if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_WebsocketSetEnabled_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.WebsocketSetEnabled(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+var (
+ filter_GoCryptoTrader_WebsocketGetSubscriptions_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
+)
+
+func request_GoCryptoTrader_WebsocketGetSubscriptions_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq WebsocketGetSubscriptionsRequest
+ var metadata runtime.ServerMetadata
+
+ if err := req.ParseForm(); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+ if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_WebsocketGetSubscriptions_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.WebsocketGetSubscriptions(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_GoCryptoTrader_WebsocketGetSubscriptions_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq WebsocketGetSubscriptionsRequest
+ var metadata runtime.ServerMetadata
+
+ if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_WebsocketGetSubscriptions_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.WebsocketGetSubscriptions(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+var (
+ filter_GoCryptoTrader_WebsocketSetProxy_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
+)
+
+func request_GoCryptoTrader_WebsocketSetProxy_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq WebsocketSetProxyRequest
+ var metadata runtime.ServerMetadata
+
+ if err := req.ParseForm(); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+ if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_WebsocketSetProxy_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.WebsocketSetProxy(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_GoCryptoTrader_WebsocketSetProxy_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq WebsocketSetProxyRequest
+ var metadata runtime.ServerMetadata
+
+ if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_WebsocketSetProxy_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.WebsocketSetProxy(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
+var (
+ filter_GoCryptoTrader_WebsocketSetURL_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
+)
+
+func request_GoCryptoTrader_WebsocketSetURL_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq WebsocketSetURLRequest
+ var metadata runtime.ServerMetadata
+
+ if err := req.ParseForm(); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+ if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_WebsocketSetURL_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := client.WebsocketSetURL(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
+ return msg, metadata, err
+
+}
+
+func local_request_GoCryptoTrader_WebsocketSetURL_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
+ var protoReq WebsocketSetURLRequest
+ var metadata runtime.ServerMetadata
+
+ if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_WebsocketSetURL_0); err != nil {
+ return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
+ }
+
+ msg, err := server.WebsocketSetURL(ctx, &protoReq)
+ return msg, metadata, err
+
+}
+
// RegisterGoCryptoTraderHandlerServer registers the http handlers for service GoCryptoTrader to "mux".
// UnaryRPC :call GoCryptoTraderServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
@@ -2799,7 +3029,7 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve
})
- mux.Handle("POST", pattern_GoCryptoTrader_EnableExchangePair_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ mux.Handle("POST", pattern_GoCryptoTrader_SetExchangePair_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
@@ -2808,34 +3038,14 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
- resp, md, err := local_request_GoCryptoTrader_EnableExchangePair_0(rctx, inboundMarshaler, server, req, pathParams)
+ resp, md, err := local_request_GoCryptoTrader_SetExchangePair_0(rctx, inboundMarshaler, server, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
- forward_GoCryptoTrader_EnableExchangePair_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
- })
-
- mux.Handle("POST", pattern_GoCryptoTrader_DisableExchangePair_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
- ctx, cancel := context.WithCancel(req.Context())
- defer cancel()
- inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
- rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
- if err != nil {
- runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
- return
- }
- resp, md, err := local_request_GoCryptoTrader_DisableExchangePair_0(rctx, inboundMarshaler, server, req, pathParams)
- ctx = runtime.NewServerMetadataContext(ctx, md)
- if err != nil {
- runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
- return
- }
-
- forward_GoCryptoTrader_DisableExchangePair_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+ forward_GoCryptoTrader_SetExchangePair_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
@@ -3087,6 +3297,186 @@ func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.Serve
})
+ mux.Handle("GET", pattern_GoCryptoTrader_SetExchangeAsset_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_GoCryptoTrader_SetExchangeAsset_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_GoCryptoTrader_SetExchangeAsset_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_GoCryptoTrader_SetAllExchangePairs_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_GoCryptoTrader_SetAllExchangePairs_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_GoCryptoTrader_SetAllExchangePairs_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_GoCryptoTrader_UpdateExchangeSupportedPairs_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_GoCryptoTrader_UpdateExchangeSupportedPairs_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_GoCryptoTrader_UpdateExchangeSupportedPairs_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_GoCryptoTrader_GetExchangeAssets_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_GoCryptoTrader_GetExchangeAssets_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_GoCryptoTrader_GetExchangeAssets_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_GoCryptoTrader_WebsocketGetInfo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_GoCryptoTrader_WebsocketGetInfo_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_GoCryptoTrader_WebsocketGetInfo_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_GoCryptoTrader_WebsocketSetEnabled_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_GoCryptoTrader_WebsocketSetEnabled_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_GoCryptoTrader_WebsocketSetEnabled_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_GoCryptoTrader_WebsocketGetSubscriptions_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_GoCryptoTrader_WebsocketGetSubscriptions_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_GoCryptoTrader_WebsocketGetSubscriptions_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_GoCryptoTrader_WebsocketSetProxy_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_GoCryptoTrader_WebsocketSetProxy_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_GoCryptoTrader_WebsocketSetProxy_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_GoCryptoTrader_WebsocketSetURL_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := local_request_GoCryptoTrader_WebsocketSetURL_0(rctx, inboundMarshaler, server, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_GoCryptoTrader_WebsocketSetURL_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
return nil
}
@@ -4028,7 +4418,7 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve
})
- mux.Handle("POST", pattern_GoCryptoTrader_EnableExchangePair_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ mux.Handle("POST", pattern_GoCryptoTrader_SetExchangePair_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
@@ -4037,34 +4427,14 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
- resp, md, err := request_GoCryptoTrader_EnableExchangePair_0(rctx, inboundMarshaler, client, req, pathParams)
+ resp, md, err := request_GoCryptoTrader_SetExchangePair_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
- forward_GoCryptoTrader_EnableExchangePair_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
-
- })
-
- mux.Handle("POST", pattern_GoCryptoTrader_DisableExchangePair_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
- ctx, cancel := context.WithCancel(req.Context())
- defer cancel()
- inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
- rctx, err := runtime.AnnotateContext(ctx, mux, req)
- if err != nil {
- runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
- return
- }
- resp, md, err := request_GoCryptoTrader_DisableExchangePair_0(rctx, inboundMarshaler, client, req, pathParams)
- ctx = runtime.NewServerMetadataContext(ctx, md)
- if err != nil {
- runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
- return
- }
-
- forward_GoCryptoTrader_DisableExchangePair_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+ forward_GoCryptoTrader_SetExchangePair_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
@@ -4368,6 +4738,186 @@ func RegisterGoCryptoTraderHandlerClient(ctx context.Context, mux *runtime.Serve
})
+ mux.Handle("GET", pattern_GoCryptoTrader_SetExchangeAsset_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_GoCryptoTrader_SetExchangeAsset_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_GoCryptoTrader_SetExchangeAsset_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_GoCryptoTrader_SetAllExchangePairs_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_GoCryptoTrader_SetAllExchangePairs_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_GoCryptoTrader_SetAllExchangePairs_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_GoCryptoTrader_UpdateExchangeSupportedPairs_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_GoCryptoTrader_UpdateExchangeSupportedPairs_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_GoCryptoTrader_UpdateExchangeSupportedPairs_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_GoCryptoTrader_GetExchangeAssets_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_GoCryptoTrader_GetExchangeAssets_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_GoCryptoTrader_GetExchangeAssets_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_GoCryptoTrader_WebsocketGetInfo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_GoCryptoTrader_WebsocketGetInfo_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_GoCryptoTrader_WebsocketGetInfo_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_GoCryptoTrader_WebsocketSetEnabled_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_GoCryptoTrader_WebsocketSetEnabled_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_GoCryptoTrader_WebsocketSetEnabled_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_GoCryptoTrader_WebsocketGetSubscriptions_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_GoCryptoTrader_WebsocketGetSubscriptions_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_GoCryptoTrader_WebsocketGetSubscriptions_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_GoCryptoTrader_WebsocketSetProxy_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_GoCryptoTrader_WebsocketSetProxy_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_GoCryptoTrader_WebsocketSetProxy_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
+ mux.Handle("GET", pattern_GoCryptoTrader_WebsocketSetURL_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
+ ctx, cancel := context.WithCancel(req.Context())
+ defer cancel()
+ inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
+ rctx, err := runtime.AnnotateContext(ctx, mux, req)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+ resp, md, err := request_GoCryptoTrader_WebsocketSetURL_0(rctx, inboundMarshaler, client, req, pathParams)
+ ctx = runtime.NewServerMetadataContext(ctx, md)
+ if err != nil {
+ runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
+ return
+ }
+
+ forward_GoCryptoTrader_WebsocketSetURL_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
+
+ })
+
return nil
}
@@ -4462,9 +5012,7 @@ var (
pattern_GoCryptoTrader_GetExchangePairs_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "getexchangepairs"}, "", runtime.AssumeColonVerbOpt(true)))
- pattern_GoCryptoTrader_EnableExchangePair_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "enableexchangepair"}, "", runtime.AssumeColonVerbOpt(true)))
-
- pattern_GoCryptoTrader_DisableExchangePair_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "disableexchangepair"}, "", runtime.AssumeColonVerbOpt(true)))
+ pattern_GoCryptoTrader_SetExchangePair_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "setexchangepair"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_GoCryptoTrader_GetOrderbookStream_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "getorderbookstream"}, "", runtime.AssumeColonVerbOpt(true)))
@@ -4495,6 +5043,24 @@ var (
pattern_GoCryptoTrader_GCTScriptAutoLoadToggle_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "gctscript", "autoload"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_GoCryptoTrader_GetHistoricCandles_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "gethistoriccandles"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_GoCryptoTrader_SetExchangeAsset_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "setexchangeasset"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_GoCryptoTrader_SetAllExchangePairs_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "setallexchangepairs"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_GoCryptoTrader_UpdateExchangeSupportedPairs_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "updateexchangesupportedpairs"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_GoCryptoTrader_GetExchangeAssets_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "getexchangeassets"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_GoCryptoTrader_WebsocketGetInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "websocketgetinfo"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_GoCryptoTrader_WebsocketSetEnabled_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "websocketsetenabled"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_GoCryptoTrader_WebsocketGetSubscriptions_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "websocketgetsubscriptions"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_GoCryptoTrader_WebsocketSetProxy_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "websocketsetproxy"}, "", runtime.AssumeColonVerbOpt(true)))
+
+ pattern_GoCryptoTrader_WebsocketSetURL_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "websocketseturl"}, "", runtime.AssumeColonVerbOpt(true)))
)
var (
@@ -4588,9 +5154,7 @@ var (
forward_GoCryptoTrader_GetExchangePairs_0 = runtime.ForwardResponseMessage
- forward_GoCryptoTrader_EnableExchangePair_0 = runtime.ForwardResponseMessage
-
- forward_GoCryptoTrader_DisableExchangePair_0 = runtime.ForwardResponseMessage
+ forward_GoCryptoTrader_SetExchangePair_0 = runtime.ForwardResponseMessage
forward_GoCryptoTrader_GetOrderbookStream_0 = runtime.ForwardResponseStream
@@ -4621,4 +5185,22 @@ var (
forward_GoCryptoTrader_GCTScriptAutoLoadToggle_0 = runtime.ForwardResponseMessage
forward_GoCryptoTrader_GetHistoricCandles_0 = runtime.ForwardResponseMessage
+
+ forward_GoCryptoTrader_SetExchangeAsset_0 = runtime.ForwardResponseMessage
+
+ forward_GoCryptoTrader_SetAllExchangePairs_0 = runtime.ForwardResponseMessage
+
+ forward_GoCryptoTrader_UpdateExchangeSupportedPairs_0 = runtime.ForwardResponseMessage
+
+ forward_GoCryptoTrader_GetExchangeAssets_0 = runtime.ForwardResponseMessage
+
+ forward_GoCryptoTrader_WebsocketGetInfo_0 = runtime.ForwardResponseMessage
+
+ forward_GoCryptoTrader_WebsocketSetEnabled_0 = runtime.ForwardResponseMessage
+
+ forward_GoCryptoTrader_WebsocketGetSubscriptions_0 = runtime.ForwardResponseMessage
+
+ forward_GoCryptoTrader_WebsocketSetProxy_0 = runtime.ForwardResponseMessage
+
+ forward_GoCryptoTrader_WebsocketSetURL_0 = runtime.ForwardResponseMessage
)
diff --git a/gctrpc/rpc.proto b/gctrpc/rpc.proto
index b5e0e3c7..fe9292ce 100644
--- a/gctrpc/rpc.proto
+++ b/gctrpc/rpc.proto
@@ -32,8 +32,6 @@ message GenericSubsystemRequest {
string subsystem = 1;
}
-message GenericSubsystemResponse {}
-
message GetSubsystemsRequest {}
message GetSusbsytemsResponse {
@@ -55,8 +53,6 @@ message GenericExchangeNameRequest {
string exchange = 1;
}
-message GenericExchangeNameResponse {}
-
message GetExchangesRequest {
bool enabled = 1;
}
@@ -249,16 +245,12 @@ message AddPortfolioAddressRequest {
bool cold_storage = 6;
}
-message AddPortfolioAddressResponse {}
-
message RemovePortfolioAddressRequest {
string address = 1;
string coin_type = 2;
string description = 3;
}
-message RemovePortfolioAddressResponse {}
-
message GetForexProvidersRequest {}
message ForexProvider {
@@ -379,8 +371,6 @@ message CancelOrderRequest {
string side = 7;
}
-message CancelOrderResponse {}
-
message CancelAllOrdersRequest {
string exchange = 1;
}
@@ -431,8 +421,6 @@ message RemoveEventRequest {
int64 id = 1;
}
-message RemoveEventResponse {}
-
message GetCryptocurrencyDepositAddressesRequest {
string exchange = 1;
}
@@ -561,10 +549,11 @@ message GetExchangePairsResponse {
map supported_assets = 1;
}
-message ExchangePairRequest {
+message SetExchangePairRequest {
string exchange = 1;
string asset_type = 2;
- CurrencyPair pair = 3;
+ repeated CurrencyPair pairs = 3;
+ bool enable = 4;
}
message GetOrderbookStreamRequest {
@@ -685,11 +674,79 @@ message GCTScriptQueryResponse{
string data = 3;
}
-message GCTScriptGenericResponse {
+message GenericResponse {
string status = 1;
string data = 2;
}
+message SetExchangeAssetRequest {
+ string exchange = 1;
+ string asset = 2;
+ bool enable = 3;
+}
+
+message SetExchangeAllPairsRequest {
+ string exchange = 1;
+ bool enable = 2;
+}
+
+message UpdateExchangeSupportedPairsRequest {
+ string exchange = 1;
+}
+
+message GetExchangeAssetsRequest {
+ string exchange = 1;
+}
+
+message GetExchangeAssetsResponse {
+ string assets = 1;
+}
+
+message WebsocketGetInfoRequest {
+ string exchange = 1;
+}
+
+message WebsocketGetInfoResponse {
+ string exchange = 1;
+ bool supported = 2;
+ bool enabled = 3;
+ bool authenticated_supported = 4;
+ bool authenticated = 5;
+ string running_url = 6;
+ string proxy_address = 7;
+}
+
+message WebsocketSetEnabledRequest {
+ string exchange = 1;
+ bool enable = 2;
+}
+
+message WebsocketGetSubscriptionsRequest {
+ string exchange = 1;
+}
+
+message WebsocketSubscription {
+ string channel = 1;
+ string currency = 2;
+ string asset = 3;
+ string params = 4;
+}
+
+message WebsocketGetSubscriptionsResponse {
+ string exchange = 1;
+ repeated WebsocketSubscription subscriptions = 2;
+}
+
+message WebsocketSetProxyRequest {
+ string exchange = 1;
+ string proxy = 2;
+}
+
+message WebsocketSetURLRequest {
+ string exchange = 1;
+ string url = 2;
+}
+
service GoCryptoTrader {
rpc GetInfo (GetInfoRequest) returns (GetInfoResponse) {
option (google.api.http) = {
@@ -703,13 +760,13 @@ service GoCryptoTrader {
};
}
- rpc EnableSubsystem (GenericSubsystemRequest) returns (GenericSubsystemResponse) {
+ rpc EnableSubsystem (GenericSubsystemRequest) returns (GenericResponse) {
option (google.api.http) = {
get: "/v1/enablesubsystem"
};
}
- rpc DisableSubsystem (GenericSubsystemRequest) returns (GenericSubsystemResponse) {
+ rpc DisableSubsystem (GenericSubsystemRequest) returns (GenericResponse) {
option (google.api.http) = {
get: "/v1/disablesubsystem"
};
@@ -733,7 +790,7 @@ service GoCryptoTrader {
};
}
- rpc DisableExchange (GenericExchangeNameRequest) returns (GenericExchangeNameResponse) {
+ rpc DisableExchange (GenericExchangeNameRequest) returns (GenericResponse) {
option (google.api.http) = {
post: "/v1/disableexchange"
body: "*"
@@ -758,7 +815,7 @@ service GoCryptoTrader {
};
}
- rpc EnableExchange (GenericExchangeNameRequest) returns (GenericExchangeNameResponse) {
+ rpc EnableExchange (GenericExchangeNameRequest) returns (GenericResponse) {
option (google.api.http) = {
post: "/v1/enableexchange"
body: "*"
@@ -822,14 +879,14 @@ service GoCryptoTrader {
}
- rpc AddPortfolioAddress (AddPortfolioAddressRequest) returns (AddPortfolioAddressResponse) {
+ rpc AddPortfolioAddress (AddPortfolioAddressRequest) returns (GenericResponse) {
option (google.api.http) = {
post: "/v1/addportfolioaddress"
body: "*"
};
}
- rpc RemovePortfolioAddress (RemovePortfolioAddressRequest) returns (RemovePortfolioAddressResponse) {
+ rpc RemovePortfolioAddress (RemovePortfolioAddressRequest) returns (GenericResponse) {
option (google.api.http) = {
post: "/v1/removeportfolioaddress"
body: "*"
@@ -883,7 +940,7 @@ service GoCryptoTrader {
};
}
- rpc CancelOrder (CancelOrderRequest) returns (CancelOrderResponse) {
+ rpc CancelOrder (CancelOrderRequest) returns (GenericResponse) {
option (google.api.http) = {
post: "/v1/cancelorder"
body: "*"
@@ -910,7 +967,7 @@ service GoCryptoTrader {
};
}
- rpc RemoveEvent(RemoveEventRequest) returns (RemoveEventResponse) {
+ rpc RemoveEvent(RemoveEventRequest) returns (GenericResponse) {
option (google.api.http) = {
post: "/v1/removeevent"
body: "*"
@@ -987,16 +1044,9 @@ service GoCryptoTrader {
};
}
- rpc EnableExchangePair(ExchangePairRequest) returns (GenericExchangeNameResponse) {
+ rpc SetExchangePair(SetExchangePairRequest) returns (GenericResponse) {
option (google.api.http) = {
- post: "/v1/enableexchangepair",
- body: "*"
- };
- }
-
- rpc DisableExchangePair(ExchangePairRequest) returns (GenericExchangeNameResponse) {
- option (google.api.http) = {
- post: "/v1/disableexchangepair",
+ post: "/v1/setexchangepair",
body: "*"
};
}
@@ -1031,13 +1081,13 @@ service GoCryptoTrader {
};
}
- rpc GCTScriptExecute(GCTScriptExecuteRequest) returns (GCTScriptGenericResponse) {
+ rpc GCTScriptExecute(GCTScriptExecuteRequest) returns (GenericResponse) {
option (google.api.http) = {
get: "/v1/gctscript/execute",
};
}
- rpc GCTScriptUpload(GCTScriptUploadRequest) returns (GCTScriptGenericResponse) {
+ rpc GCTScriptUpload(GCTScriptUploadRequest) returns (GenericResponse) {
option (google.api.http) = {
post: "/v1/gctscript/upload",
body: "*"
@@ -1063,14 +1113,14 @@ service GoCryptoTrader {
};
}
- rpc GCTScriptStop(GCTScriptStopRequest) returns (GCTScriptGenericResponse) {
+ rpc GCTScriptStop(GCTScriptStopRequest) returns (GenericResponse) {
option (google.api.http) = {
post: "/v1/gctscript/stop",
body: "*"
};
}
- rpc GCTScriptStopAll(GCTScriptStopAllRequest) returns (GCTScriptGenericResponse) {
+ rpc GCTScriptStopAll(GCTScriptStopAllRequest) returns (GenericResponse) {
option (google.api.http) = {
post: "/v1/gctscript/stop",
body: "*"
@@ -1083,7 +1133,7 @@ service GoCryptoTrader {
body: "*"
};
}
- rpc GCTScriptAutoLoadToggle(GCTScriptAutoLoadRequest) returns (GCTScriptGenericResponse) {
+ rpc GCTScriptAutoLoadToggle(GCTScriptAutoLoadRequest) returns (GenericResponse) {
option (google.api.http) = {
post: "/v1/gctscript/autoload",
body: "*"
@@ -1095,4 +1145,58 @@ service GoCryptoTrader {
get: "/v1/gethistoriccandles"
};
}
-}
+
+ rpc SetExchangeAsset(SetExchangeAssetRequest) returns (GenericResponse) {
+ option (google.api.http) = {
+ get: "/v1/setexchangeasset"
+ };
+ }
+
+ rpc SetAllExchangePairs(SetExchangeAllPairsRequest) returns (GenericResponse) {
+ option (google.api.http) = {
+ get: "/v1/setallexchangepairs"
+ };
+ }
+
+ rpc UpdateExchangeSupportedPairs(UpdateExchangeSupportedPairsRequest) returns (GenericResponse) {
+ option (google.api.http) = {
+ get: "/v1/updateexchangesupportedpairs"
+ };
+ }
+
+ rpc GetExchangeAssets(GetExchangeAssetsRequest) returns (GetExchangeAssetsResponse) {
+ option (google.api.http) = {
+ get: "/v1/getexchangeassets"
+ };
+ }
+
+ rpc WebsocketGetInfo(WebsocketGetInfoRequest) returns (WebsocketGetInfoResponse) {
+ option (google.api.http) = {
+ get: "/v1/websocketgetinfo"
+ };
+ }
+
+ rpc WebsocketSetEnabled(WebsocketSetEnabledRequest) returns (GenericResponse) {
+ option (google.api.http) = {
+ get: "/v1/websocketsetenabled"
+ };
+ }
+
+ rpc WebsocketGetSubscriptions(WebsocketGetSubscriptionsRequest) returns (WebsocketGetSubscriptionsResponse) {
+ option (google.api.http) = {
+ get: "/v1/websocketgetsubscriptions"
+ };
+ }
+
+ rpc WebsocketSetProxy(WebsocketSetProxyRequest) returns (GenericResponse) {
+ option (google.api.http) = {
+ get: "/v1/websocketsetproxy"
+ };
+ }
+
+ rpc WebsocketSetURL(WebsocketSetURLRequest) returns (GenericResponse) {
+ option (google.api.http) = {
+ get: "/v1/websocketseturl"
+ };
+ }
+}
\ No newline at end of file
diff --git a/gctrpc/rpc.swagger.json b/gctrpc/rpc.swagger.json
index 057a7351..45b0f0f6 100644
--- a/gctrpc/rpc.swagger.json
+++ b/gctrpc/rpc.swagger.json
@@ -13,7 +13,7 @@
"paths": {
"/v1/addevent": {
"post": {
- "operationId": "GoCryptoTrader_AddEvent",
+ "operationId": "AddEvent",
"responses": {
"200": {
"description": "A successful response.",
@@ -45,12 +45,12 @@
},
"/v1/addportfolioaddress": {
"post": {
- "operationId": "GoCryptoTrader_AddPortfolioAddress",
+ "operationId": "AddPortfolioAddress",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
- "$ref": "#/definitions/gctrpcAddPortfolioAddressResponse"
+ "$ref": "#/definitions/gctrpcGenericResponse"
}
},
"default": {
@@ -77,7 +77,7 @@
},
"/v1/cancelallorders": {
"post": {
- "operationId": "GoCryptoTrader_CancelAllOrders",
+ "operationId": "CancelAllOrders",
"responses": {
"200": {
"description": "A successful response.",
@@ -109,12 +109,12 @@
},
"/v1/cancelorder": {
"post": {
- "operationId": "GoCryptoTrader_CancelOrder",
+ "operationId": "CancelOrder",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
- "$ref": "#/definitions/gctrpcCancelOrderResponse"
+ "$ref": "#/definitions/gctrpcGenericResponse"
}
},
"default": {
@@ -141,12 +141,12 @@
},
"/v1/disableexchange": {
"post": {
- "operationId": "GoCryptoTrader_DisableExchange",
+ "operationId": "DisableExchange",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
- "$ref": "#/definitions/gctrpcGenericExchangeNameResponse"
+ "$ref": "#/definitions/gctrpcGenericResponse"
}
},
"default": {
@@ -171,46 +171,14 @@
]
}
},
- "/v1/disableexchangepair": {
- "post": {
- "operationId": "GoCryptoTrader_DisableExchangePair",
- "responses": {
- "200": {
- "description": "A successful response.",
- "schema": {
- "$ref": "#/definitions/gctrpcGenericExchangeNameResponse"
- }
- },
- "default": {
- "description": "An unexpected error response",
- "schema": {
- "$ref": "#/definitions/runtimeError"
- }
- }
- },
- "parameters": [
- {
- "name": "body",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/gctrpcExchangePairRequest"
- }
- }
- ],
- "tags": [
- "GoCryptoTrader"
- ]
- }
- },
"/v1/disablesubsystem": {
"get": {
- "operationId": "GoCryptoTrader_DisableSubsystem",
+ "operationId": "DisableSubsystem",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
- "$ref": "#/definitions/gctrpcGenericSubsystemResponse"
+ "$ref": "#/definitions/gctrpcGenericResponse"
}
},
"default": {
@@ -235,12 +203,12 @@
},
"/v1/enableexchange": {
"post": {
- "operationId": "GoCryptoTrader_EnableExchange",
+ "operationId": "EnableExchange",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
- "$ref": "#/definitions/gctrpcGenericExchangeNameResponse"
+ "$ref": "#/definitions/gctrpcGenericResponse"
}
},
"default": {
@@ -265,46 +233,14 @@
]
}
},
- "/v1/enableexchangepair": {
- "post": {
- "operationId": "GoCryptoTrader_EnableExchangePair",
- "responses": {
- "200": {
- "description": "A successful response.",
- "schema": {
- "$ref": "#/definitions/gctrpcGenericExchangeNameResponse"
- }
- },
- "default": {
- "description": "An unexpected error response",
- "schema": {
- "$ref": "#/definitions/runtimeError"
- }
- }
- },
- "parameters": [
- {
- "name": "body",
- "in": "body",
- "required": true,
- "schema": {
- "$ref": "#/definitions/gctrpcExchangePairRequest"
- }
- }
- ],
- "tags": [
- "GoCryptoTrader"
- ]
- }
- },
"/v1/enablesubsystem": {
"get": {
- "operationId": "GoCryptoTrader_EnableSubsystem",
+ "operationId": "EnableSubsystem",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
- "$ref": "#/definitions/gctrpcGenericSubsystemResponse"
+ "$ref": "#/definitions/gctrpcGenericResponse"
}
},
"default": {
@@ -329,12 +265,12 @@
},
"/v1/gctscript/autoload": {
"post": {
- "operationId": "GoCryptoTrader_GCTScriptAutoLoadToggle",
+ "operationId": "GCTScriptAutoLoadToggle",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
- "$ref": "#/definitions/gctrpcGCTScriptGenericResponse"
+ "$ref": "#/definitions/gctrpcGenericResponse"
}
},
"default": {
@@ -361,12 +297,12 @@
},
"/v1/gctscript/execute": {
"get": {
- "operationId": "GoCryptoTrader_GCTScriptExecute",
+ "operationId": "GCTScriptExecute",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
- "$ref": "#/definitions/gctrpcGCTScriptGenericResponse"
+ "$ref": "#/definitions/gctrpcGenericResponse"
}
},
"default": {
@@ -409,7 +345,7 @@
},
"/v1/gctscript/query": {
"get": {
- "operationId": "GoCryptoTrader_GCTScriptQuery",
+ "operationId": "GCTScriptQuery",
"responses": {
"200": {
"description": "A successful response.",
@@ -457,7 +393,7 @@
},
"/v1/gctscript/read": {
"post": {
- "operationId": "GoCryptoTrader_GCTScriptReadScript",
+ "operationId": "GCTScriptReadScript",
"responses": {
"200": {
"description": "A successful response.",
@@ -489,7 +425,7 @@
},
"/v1/gctscript/status": {
"get": {
- "operationId": "GoCryptoTrader_GCTScriptStatus",
+ "operationId": "GCTScriptStatus",
"responses": {
"200": {
"description": "A successful response.",
@@ -511,7 +447,7 @@
},
"/v1/gctscript/stop": {
"post": {
- "operationId": "GoCryptoTrader_GCTScriptListAll",
+ "operationId": "GCTScriptListAll",
"responses": {
"200": {
"description": "A successful response.",
@@ -543,12 +479,12 @@
},
"/v1/gctscript/upload": {
"post": {
- "operationId": "GoCryptoTrader_GCTScriptUpload",
+ "operationId": "GCTScriptUpload",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
- "$ref": "#/definitions/gctrpcGCTScriptGenericResponse"
+ "$ref": "#/definitions/gctrpcGenericResponse"
}
},
"default": {
@@ -575,7 +511,7 @@
},
"/v1/getaccountinfo": {
"get": {
- "operationId": "GoCryptoTrader_GetAccountInfo",
+ "operationId": "GetAccountInfo",
"responses": {
"200": {
"description": "A successful response.",
@@ -605,7 +541,7 @@
},
"/v1/getaccountinfostream": {
"get": {
- "operationId": "GoCryptoTrader_GetAccountInfoStream",
+ "operationId": "GetAccountInfoStream",
"responses": {
"200": {
"description": "A successful response.(streaming responses)",
@@ -644,7 +580,7 @@
},
"/v1/getauditevent": {
"get": {
- "operationId": "GoCryptoTrader_GetAuditEvent",
+ "operationId": "GetAuditEvent",
"responses": {
"200": {
"description": "A successful response.",
@@ -700,7 +636,7 @@
},
"/v1/getcommunicationrelayers": {
"get": {
- "operationId": "GoCryptoTrader_GetCommunicationRelayers",
+ "operationId": "GetCommunicationRelayers",
"responses": {
"200": {
"description": "A successful response.",
@@ -722,7 +658,7 @@
},
"/v1/getconfig": {
"get": {
- "operationId": "GoCryptoTrader_GetConfig",
+ "operationId": "GetConfig",
"responses": {
"200": {
"description": "A successful response.",
@@ -744,7 +680,7 @@
},
"/v1/getcryptodepositaddress": {
"post": {
- "operationId": "GoCryptoTrader_GetCryptocurrencyDepositAddress",
+ "operationId": "GetCryptocurrencyDepositAddress",
"responses": {
"200": {
"description": "A successful response.",
@@ -776,7 +712,7 @@
},
"/v1/getcryptodepositaddresses": {
"post": {
- "operationId": "GoCryptoTrader_GetCryptocurrencyDepositAddresses",
+ "operationId": "GetCryptocurrencyDepositAddresses",
"responses": {
"200": {
"description": "A successful response.",
@@ -808,7 +744,7 @@
},
"/v1/getevents": {
"get": {
- "operationId": "GoCryptoTrader_GetEvents",
+ "operationId": "GetEvents",
"responses": {
"200": {
"description": "A successful response.",
@@ -828,9 +764,39 @@
]
}
},
+ "/v1/getexchangeassets": {
+ "get": {
+ "operationId": "GetExchangeAssets",
+ "responses": {
+ "200": {
+ "description": "A successful response.",
+ "schema": {
+ "$ref": "#/definitions/gctrpcGetExchangeAssetsResponse"
+ }
+ },
+ "default": {
+ "description": "An unexpected error response",
+ "schema": {
+ "$ref": "#/definitions/runtimeError"
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "exchange",
+ "in": "query",
+ "required": false,
+ "type": "string"
+ }
+ ],
+ "tags": [
+ "GoCryptoTrader"
+ ]
+ }
+ },
"/v1/getexchangeinfo": {
"get": {
- "operationId": "GoCryptoTrader_GetExchangeInfo",
+ "operationId": "GetExchangeInfo",
"responses": {
"200": {
"description": "A successful response.",
@@ -860,7 +826,7 @@
},
"/v1/getexchangeorderbookstream": {
"get": {
- "operationId": "GoCryptoTrader_GetExchangeOrderbookStream",
+ "operationId": "GetExchangeOrderbookStream",
"responses": {
"200": {
"description": "A successful response.(streaming responses)",
@@ -899,7 +865,7 @@
},
"/v1/getexchangeotp": {
"get": {
- "operationId": "GoCryptoTrader_GetExchangeOTPCode",
+ "operationId": "GetExchangeOTPCode",
"responses": {
"200": {
"description": "A successful response.",
@@ -929,7 +895,7 @@
},
"/v1/getexchangeotps": {
"get": {
- "operationId": "GoCryptoTrader_GetExchangeOTPCodes",
+ "operationId": "GetExchangeOTPCodes",
"responses": {
"200": {
"description": "A successful response.",
@@ -951,7 +917,7 @@
},
"/v1/getexchangepairs": {
"post": {
- "operationId": "GoCryptoTrader_GetExchangePairs",
+ "operationId": "GetExchangePairs",
"responses": {
"200": {
"description": "A successful response.",
@@ -983,7 +949,7 @@
},
"/v1/getexchanges": {
"get": {
- "operationId": "GoCryptoTrader_GetExchanges",
+ "operationId": "GetExchanges",
"responses": {
"200": {
"description": "A successful response.",
@@ -1014,7 +980,7 @@
},
"/v1/getexchangetickerstream": {
"get": {
- "operationId": "GoCryptoTrader_GetExchangeTickerStream",
+ "operationId": "GetExchangeTickerStream",
"responses": {
"200": {
"description": "A successful response.(streaming responses)",
@@ -1053,7 +1019,7 @@
},
"/v1/getforexproviders": {
"get": {
- "operationId": "GoCryptoTrader_GetForexProviders",
+ "operationId": "GetForexProviders",
"responses": {
"200": {
"description": "A successful response.",
@@ -1075,7 +1041,7 @@
},
"/v1/getforexrates": {
"get": {
- "operationId": "GoCryptoTrader_GetForexRates",
+ "operationId": "GetForexRates",
"responses": {
"200": {
"description": "A successful response.",
@@ -1097,7 +1063,7 @@
},
"/v1/gethistoriccandles": {
"get": {
- "operationId": "GoCryptoTrader_GetHistoricCandles",
+ "operationId": "GetHistoricCandles",
"responses": {
"200": {
"description": "A successful response.",
@@ -1179,7 +1145,7 @@
},
"/v1/getinfo": {
"get": {
- "operationId": "GoCryptoTrader_GetInfo",
+ "operationId": "GetInfo",
"responses": {
"200": {
"description": "A successful response.",
@@ -1201,7 +1167,7 @@
},
"/v1/getloggerdetails": {
"get": {
- "operationId": "GoCryptoTrader_GetLoggerDetails",
+ "operationId": "GetLoggerDetails",
"responses": {
"200": {
"description": "A successful response.",
@@ -1231,7 +1197,7 @@
},
"/v1/getorder": {
"post": {
- "operationId": "GoCryptoTrader_GetOrder",
+ "operationId": "GetOrder",
"responses": {
"200": {
"description": "A successful response.",
@@ -1263,7 +1229,7 @@
},
"/v1/getorderbook": {
"post": {
- "operationId": "GoCryptoTrader_GetOrderbook",
+ "operationId": "GetOrderbook",
"responses": {
"200": {
"description": "A successful response.",
@@ -1295,7 +1261,7 @@
},
"/v1/getorderbooks": {
"get": {
- "operationId": "GoCryptoTrader_GetOrderbooks",
+ "operationId": "GetOrderbooks",
"responses": {
"200": {
"description": "A successful response.",
@@ -1317,7 +1283,7 @@
},
"/v1/getorderbookstream": {
"get": {
- "operationId": "GoCryptoTrader_GetOrderbookStream",
+ "operationId": "GetOrderbookStream",
"responses": {
"200": {
"description": "A successful response.(streaming responses)",
@@ -1380,7 +1346,7 @@
},
"/v1/getorders": {
"post": {
- "operationId": "GoCryptoTrader_GetOrders",
+ "operationId": "GetOrders",
"responses": {
"200": {
"description": "A successful response.",
@@ -1412,7 +1378,7 @@
},
"/v1/getportfolio": {
"get": {
- "operationId": "GoCryptoTrader_GetPortfolio",
+ "operationId": "GetPortfolio",
"responses": {
"200": {
"description": "A successful response.",
@@ -1434,7 +1400,7 @@
},
"/v1/getportfoliosummary": {
"get": {
- "operationId": "GoCryptoTrader_GetPortfolioSummary",
+ "operationId": "GetPortfolioSummary",
"responses": {
"200": {
"description": "A successful response.",
@@ -1456,7 +1422,7 @@
},
"/v1/getrpcendpoints": {
"get": {
- "operationId": "GoCryptoTrader_GetRPCEndpoints",
+ "operationId": "GetRPCEndpoints",
"responses": {
"200": {
"description": "A successful response.",
@@ -1478,7 +1444,7 @@
},
"/v1/getsubsystems": {
"get": {
- "operationId": "GoCryptoTrader_GetSubsystems",
+ "operationId": "GetSubsystems",
"responses": {
"200": {
"description": "A successful response.",
@@ -1500,7 +1466,7 @@
},
"/v1/getticker": {
"post": {
- "operationId": "GoCryptoTrader_GetTicker",
+ "operationId": "GetTicker",
"responses": {
"200": {
"description": "A successful response.",
@@ -1532,7 +1498,7 @@
},
"/v1/gettickers": {
"get": {
- "operationId": "GoCryptoTrader_GetTickers",
+ "operationId": "GetTickers",
"responses": {
"200": {
"description": "A successful response.",
@@ -1554,7 +1520,7 @@
},
"/v1/gettickerstream": {
"get": {
- "operationId": "GoCryptoTrader_GetTickerStream",
+ "operationId": "GetTickerStream",
"responses": {
"200": {
"description": "A successful response.(streaming responses)",
@@ -1617,12 +1583,12 @@
},
"/v1/removeevent": {
"post": {
- "operationId": "GoCryptoTrader_RemoveEvent",
+ "operationId": "RemoveEvent",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
- "$ref": "#/definitions/gctrpcRemoveEventResponse"
+ "$ref": "#/definitions/gctrpcGenericResponse"
}
},
"default": {
@@ -1649,12 +1615,12 @@
},
"/v1/removeportfolioaddress": {
"post": {
- "operationId": "GoCryptoTrader_RemovePortfolioAddress",
+ "operationId": "RemovePortfolioAddress",
"responses": {
"200": {
"description": "A successful response.",
"schema": {
- "$ref": "#/definitions/gctrpcRemovePortfolioAddressResponse"
+ "$ref": "#/definitions/gctrpcGenericResponse"
}
},
"default": {
@@ -1679,9 +1645,121 @@
]
}
},
+ "/v1/setallexchangepairs": {
+ "get": {
+ "operationId": "SetAllExchangePairs",
+ "responses": {
+ "200": {
+ "description": "A successful response.",
+ "schema": {
+ "$ref": "#/definitions/gctrpcGenericResponse"
+ }
+ },
+ "default": {
+ "description": "An unexpected error response",
+ "schema": {
+ "$ref": "#/definitions/runtimeError"
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "exchange",
+ "in": "query",
+ "required": false,
+ "type": "string"
+ },
+ {
+ "name": "enable",
+ "in": "query",
+ "required": false,
+ "type": "boolean",
+ "format": "boolean"
+ }
+ ],
+ "tags": [
+ "GoCryptoTrader"
+ ]
+ }
+ },
+ "/v1/setexchangeasset": {
+ "get": {
+ "operationId": "SetExchangeAsset",
+ "responses": {
+ "200": {
+ "description": "A successful response.",
+ "schema": {
+ "$ref": "#/definitions/gctrpcGenericResponse"
+ }
+ },
+ "default": {
+ "description": "An unexpected error response",
+ "schema": {
+ "$ref": "#/definitions/runtimeError"
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "exchange",
+ "in": "query",
+ "required": false,
+ "type": "string"
+ },
+ {
+ "name": "asset",
+ "in": "query",
+ "required": false,
+ "type": "string"
+ },
+ {
+ "name": "enable",
+ "in": "query",
+ "required": false,
+ "type": "boolean",
+ "format": "boolean"
+ }
+ ],
+ "tags": [
+ "GoCryptoTrader"
+ ]
+ }
+ },
+ "/v1/setexchangepair": {
+ "post": {
+ "operationId": "SetExchangePair",
+ "responses": {
+ "200": {
+ "description": "A successful response.",
+ "schema": {
+ "$ref": "#/definitions/gctrpcGenericResponse"
+ }
+ },
+ "default": {
+ "description": "An unexpected error response",
+ "schema": {
+ "$ref": "#/definitions/runtimeError"
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "body",
+ "in": "body",
+ "required": true,
+ "schema": {
+ "$ref": "#/definitions/gctrpcSetExchangePairRequest"
+ }
+ }
+ ],
+ "tags": [
+ "GoCryptoTrader"
+ ]
+ }
+ },
"/v1/setloggerdetails": {
"post": {
- "operationId": "GoCryptoTrader_SetLoggerDetails",
+ "operationId": "SetLoggerDetails",
"responses": {
"200": {
"description": "A successful response.",
@@ -1713,7 +1791,7 @@
},
"/v1/simulateorder": {
"post": {
- "operationId": "GoCryptoTrader_SimulateOrder",
+ "operationId": "SimulateOrder",
"responses": {
"200": {
"description": "A successful response.",
@@ -1745,7 +1823,7 @@
},
"/v1/submitorder": {
"post": {
- "operationId": "GoCryptoTrader_SubmitOrder",
+ "operationId": "SubmitOrder",
"responses": {
"200": {
"description": "A successful response.",
@@ -1775,9 +1853,208 @@
]
}
},
+ "/v1/updateexchangesupportedpairs": {
+ "get": {
+ "operationId": "UpdateExchangeSupportedPairs",
+ "responses": {
+ "200": {
+ "description": "A successful response.",
+ "schema": {
+ "$ref": "#/definitions/gctrpcGenericResponse"
+ }
+ },
+ "default": {
+ "description": "An unexpected error response",
+ "schema": {
+ "$ref": "#/definitions/runtimeError"
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "exchange",
+ "in": "query",
+ "required": false,
+ "type": "string"
+ }
+ ],
+ "tags": [
+ "GoCryptoTrader"
+ ]
+ }
+ },
+ "/v1/websocketgetinfo": {
+ "get": {
+ "operationId": "WebsocketGetInfo",
+ "responses": {
+ "200": {
+ "description": "A successful response.",
+ "schema": {
+ "$ref": "#/definitions/gctrpcWebsocketGetInfoResponse"
+ }
+ },
+ "default": {
+ "description": "An unexpected error response",
+ "schema": {
+ "$ref": "#/definitions/runtimeError"
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "exchange",
+ "in": "query",
+ "required": false,
+ "type": "string"
+ }
+ ],
+ "tags": [
+ "GoCryptoTrader"
+ ]
+ }
+ },
+ "/v1/websocketgetsubscriptions": {
+ "get": {
+ "operationId": "WebsocketGetSubscriptions",
+ "responses": {
+ "200": {
+ "description": "A successful response.",
+ "schema": {
+ "$ref": "#/definitions/gctrpcWebsocketGetSubscriptionsResponse"
+ }
+ },
+ "default": {
+ "description": "An unexpected error response",
+ "schema": {
+ "$ref": "#/definitions/runtimeError"
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "exchange",
+ "in": "query",
+ "required": false,
+ "type": "string"
+ }
+ ],
+ "tags": [
+ "GoCryptoTrader"
+ ]
+ }
+ },
+ "/v1/websocketsetenabled": {
+ "get": {
+ "operationId": "WebsocketSetEnabled",
+ "responses": {
+ "200": {
+ "description": "A successful response.",
+ "schema": {
+ "$ref": "#/definitions/gctrpcGenericResponse"
+ }
+ },
+ "default": {
+ "description": "An unexpected error response",
+ "schema": {
+ "$ref": "#/definitions/runtimeError"
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "exchange",
+ "in": "query",
+ "required": false,
+ "type": "string"
+ },
+ {
+ "name": "enable",
+ "in": "query",
+ "required": false,
+ "type": "boolean",
+ "format": "boolean"
+ }
+ ],
+ "tags": [
+ "GoCryptoTrader"
+ ]
+ }
+ },
+ "/v1/websocketsetproxy": {
+ "get": {
+ "operationId": "WebsocketSetProxy",
+ "responses": {
+ "200": {
+ "description": "A successful response.",
+ "schema": {
+ "$ref": "#/definitions/gctrpcGenericResponse"
+ }
+ },
+ "default": {
+ "description": "An unexpected error response",
+ "schema": {
+ "$ref": "#/definitions/runtimeError"
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "exchange",
+ "in": "query",
+ "required": false,
+ "type": "string"
+ },
+ {
+ "name": "proxy",
+ "in": "query",
+ "required": false,
+ "type": "string"
+ }
+ ],
+ "tags": [
+ "GoCryptoTrader"
+ ]
+ }
+ },
+ "/v1/websocketseturl": {
+ "get": {
+ "operationId": "WebsocketSetURL",
+ "responses": {
+ "200": {
+ "description": "A successful response.",
+ "schema": {
+ "$ref": "#/definitions/gctrpcGenericResponse"
+ }
+ },
+ "default": {
+ "description": "An unexpected error response",
+ "schema": {
+ "$ref": "#/definitions/runtimeError"
+ }
+ }
+ },
+ "parameters": [
+ {
+ "name": "exchange",
+ "in": "query",
+ "required": false,
+ "type": "string"
+ },
+ {
+ "name": "url",
+ "in": "query",
+ "required": false,
+ "type": "string"
+ }
+ ],
+ "tags": [
+ "GoCryptoTrader"
+ ]
+ }
+ },
"/v1/whalebomb": {
"post": {
- "operationId": "GoCryptoTrader_WhaleBomb",
+ "operationId": "WhaleBomb",
"responses": {
"200": {
"description": "A successful response.",
@@ -1809,7 +2086,7 @@
},
"/v1/withdrawaleventbydate": {
"post": {
- "operationId": "GoCryptoTrader_WithdrawalEventsByDate",
+ "operationId": "WithdrawalEventsByDate",
"responses": {
"200": {
"description": "A successful response.",
@@ -1841,7 +2118,7 @@
},
"/v1/withdrawaleventbyid": {
"post": {
- "operationId": "GoCryptoTrader_WithdrawalEventsByExchange",
+ "operationId": "WithdrawalEventsByExchange",
"responses": {
"200": {
"description": "A successful response.",
@@ -1873,7 +2150,7 @@
},
"/v1/withdrawfiatfunds": {
"post": {
- "operationId": "GoCryptoTrader_WithdrawFiatFunds",
+ "operationId": "WithdrawFiatFunds",
"responses": {
"200": {
"description": "A successful response.",
@@ -1905,7 +2182,7 @@
},
"/v1/withdrawithdrawcryptofundswfiatfunds": {
"post": {
- "operationId": "GoCryptoTrader_WithdrawCryptocurrencyFunds",
+ "operationId": "WithdrawCryptocurrencyFunds",
"responses": {
"200": {
"description": "A successful response.",
@@ -2038,9 +2315,6 @@
}
}
},
- "gctrpcAddPortfolioAddressResponse": {
- "type": "object"
- },
"gctrpcAuditEvent": {
"type": "object",
"properties": {
@@ -2103,9 +2377,6 @@
}
}
},
- "gctrpcCancelOrderResponse": {
- "type": "object"
- },
"gctrpcCandle": {
"type": "object",
"properties": {
@@ -2220,20 +2491,6 @@
}
}
},
- "gctrpcExchangePairRequest": {
- "type": "object",
- "properties": {
- "exchange": {
- "type": "string"
- },
- "asset_type": {
- "type": "string"
- },
- "pair": {
- "$ref": "#/definitions/gctrpcCurrencyPair"
- }
- }
- },
"gctrpcFiatWithdrawalEvent": {
"type": "object",
"properties": {
@@ -2335,17 +2592,6 @@
}
}
},
- "gctrpcGCTScriptGenericResponse": {
- "type": "object",
- "properties": {
- "status": {
- "type": "string"
- },
- "data": {
- "type": "string"
- }
- }
- },
"gctrpcGCTScriptListAllRequest": {
"type": "object"
},
@@ -2427,11 +2673,16 @@
}
}
},
- "gctrpcGenericExchangeNameResponse": {
- "type": "object"
- },
- "gctrpcGenericSubsystemResponse": {
- "type": "object"
+ "gctrpcGenericResponse": {
+ "type": "object",
+ "properties": {
+ "status": {
+ "type": "string"
+ },
+ "data": {
+ "type": "string"
+ }
+ }
},
"gctrpcGetAccountInfoResponse": {
"type": "object",
@@ -2544,6 +2795,14 @@
}
}
},
+ "gctrpcGetExchangeAssetsResponse": {
+ "type": "object",
+ "properties": {
+ "assets": {
+ "type": "string"
+ }
+ }
+ },
"gctrpcGetExchangeInfoResponse": {
"type": "object",
"properties": {
@@ -3113,9 +3372,6 @@
}
}
},
- "gctrpcRemoveEventResponse": {
- "type": "object"
- },
"gctrpcRemovePortfolioAddressRequest": {
"type": "object",
"properties": {
@@ -3130,8 +3386,26 @@
}
}
},
- "gctrpcRemovePortfolioAddressResponse": {
- "type": "object"
+ "gctrpcSetExchangePairRequest": {
+ "type": "object",
+ "properties": {
+ "exchange": {
+ "type": "string"
+ },
+ "asset_type": {
+ "type": "string"
+ },
+ "pairs": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gctrpcCurrencyPair"
+ }
+ },
+ "enable": {
+ "type": "boolean",
+ "format": "boolean"
+ }
+ }
},
"gctrpcSetLoggerDetailsRequest": {
"type": "object",
@@ -3322,6 +3596,67 @@
}
}
},
+ "gctrpcWebsocketGetInfoResponse": {
+ "type": "object",
+ "properties": {
+ "exchange": {
+ "type": "string"
+ },
+ "supported": {
+ "type": "boolean",
+ "format": "boolean"
+ },
+ "enabled": {
+ "type": "boolean",
+ "format": "boolean"
+ },
+ "authenticated_supported": {
+ "type": "boolean",
+ "format": "boolean"
+ },
+ "authenticated": {
+ "type": "boolean",
+ "format": "boolean"
+ },
+ "running_url": {
+ "type": "string"
+ },
+ "proxy_address": {
+ "type": "string"
+ }
+ }
+ },
+ "gctrpcWebsocketGetSubscriptionsResponse": {
+ "type": "object",
+ "properties": {
+ "exchange": {
+ "type": "string"
+ },
+ "subscriptions": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/gctrpcWebsocketSubscription"
+ }
+ }
+ }
+ },
+ "gctrpcWebsocketSubscription": {
+ "type": "object",
+ "properties": {
+ "channel": {
+ "type": "string"
+ },
+ "currency": {
+ "type": "string"
+ },
+ "asset": {
+ "type": "string"
+ },
+ "params": {
+ "type": "string"
+ }
+ }
+ },
"gctrpcWhaleBombRequest": {
"type": "object",
"properties": {
diff --git a/gctscript/README.md b/gctscript/README.md
index 53ea2d41..e0e383cc 100644
--- a/gctscript/README.md
+++ b/gctscript/README.md
@@ -78,8 +78,8 @@ With an example configuration being:
```
- Start/Execute:
```shell script
- gctcli gctscript execute
- gctcli gctscript execute "timer.gct" "~/gctscript"
+ gctcli script execute
+ gctcli script execute "timer.gct" "~/gctscript"
{
"status": "ok",
@@ -88,8 +88,8 @@ With an example configuration being:
```
- Stop:
```shell script
- gctcli gctscript stop
- gctcli gctscript stop 821bd73e-02b1-4974-9463-874cb49f130d
+ gctcli script stop
+ gctcli script stop 821bd73e-02b1-4974-9463-874cb49f130d
{
"status": "ok",
@@ -98,7 +98,7 @@ With an example configuration being:
```
- Status:
```shell script
- gctcli gctscript status
+ gctcli script status
{
"status": "ok",
@@ -113,8 +113,8 @@ With an example configuration being:
```
- Read file:
```shell script
- gctcli gctscript read
- gctcli gctscript read "timer.gct"
+ gctcli script read
+ gctcli script read "timer.gct"
{
"status": "ok",
@@ -127,8 +127,8 @@ With an example configuration being:
```
- Query running script:
```shell script
- gctcli gctscript query
- gctcli gctscript query 821bd73e-02b1-4974-9463-874cb49f130d
+ gctcli script query
+ gctcli script query 821bd73e-02b1-4974-9463-874cb49f130d
{
"status": "ok",
"script": {
@@ -143,7 +143,7 @@ With an example configuration being:
```
- Add script to autoload:
```shell script
- gctcli gctscript autoload add timer
+ gctcli script autoload add timer
{
"status": "success",
"data": "script timer added to autoload list"
@@ -151,7 +151,7 @@ With an example configuration being:
```
- Remove script from autoload:
```shell script
- gctcli gctscript autoload remove timer
+ gctcli script autoload remove timer
{
"status": "success",
"data": "script timer removed from autoload list"
diff --git a/gctscript/modules/gct/exchange.go b/gctscript/modules/gct/exchange.go
index 5b2d5d4d..c108f30c 100644
--- a/gctscript/modules/gct/exchange.go
+++ b/gctscript/modules/gct/exchange.go
@@ -54,10 +54,13 @@ func ExchangeOrderbook(args ...objects.Object) (objects.Object, error) {
return nil, fmt.Errorf(ErrParameterConvertFailed, assetTypeParam)
}
- pairs := currency.NewPairDelimiter(currencyPair, delimiter)
+ pair, err := currency.NewPairDelimiter(currencyPair, delimiter)
+ if err != nil {
+ return nil, err
+ }
assetType := asset.Item(assetTypeParam)
- ob, err := wrappers.GetWrapper().Orderbook(exchangeName, pairs, assetType)
+ ob, err := wrappers.GetWrapper().Orderbook(exchangeName, pair, assetType)
if err != nil {
return nil, err
}
@@ -113,10 +116,14 @@ func ExchangeTicker(args ...objects.Object) (objects.Object, error) {
return nil, fmt.Errorf(ErrParameterConvertFailed, assetTypeParam)
}
- pairs := currency.NewPairDelimiter(currencyPair, delimiter)
+ pair, err := currency.NewPairDelimiter(currencyPair, delimiter)
+ if err != nil {
+ return nil, err
+ }
+
assetType := asset.Item(assetTypeParam)
- tx, err := wrappers.GetWrapper().Ticker(exchangeName, pairs, assetType)
+ tx, err := wrappers.GetWrapper().Ticker(exchangeName, pair, assetType)
if err != nil {
return nil, err
}
@@ -188,8 +195,9 @@ func ExchangePairs(args ...objects.Object) (objects.Object, error) {
}
r := objects.Array{}
- for x := range rtnValue.Slice() {
- r.Value = append(r.Value, &objects.String{Value: rtnValue.Slice()[x].String()})
+ pairs := *(*[]currency.Pair)(rtnValue)
+ for x := range pairs {
+ r.Value = append(r.Value, &objects.String{Value: pairs[x].String()})
}
return &r, nil
}
@@ -346,7 +354,10 @@ func ExchangeOrderSubmit(args ...objects.Object) (objects.Object, error) {
if !ok {
return nil, fmt.Errorf(ErrParameterConvertFailed, orderClientID)
}
- pair := currency.NewPairDelimiter(currencyPair, delimiter)
+ pair, err := currency.NewPairDelimiter(currencyPair, delimiter)
+ if err != nil {
+ return nil, err
+ }
tempSubmit := &order.Submit{
Pair: pair,
@@ -357,7 +368,7 @@ func ExchangeOrderSubmit(args ...objects.Object) (objects.Object, error) {
ClientID: orderClientID,
}
- err := tempSubmit.Validate()
+ err = tempSubmit.Validate()
if err != nil {
return nil, err
}
@@ -550,10 +561,13 @@ func exchangeOHLCV(args ...objects.Object) (objects.Object, error) {
if err != nil {
return nil, err
}
- pairs := currency.NewPairDelimiter(currencyPair, delimiter)
+ pair, err := currency.NewPairDelimiter(currencyPair, delimiter)
+ if err != nil {
+ return nil, err
+ }
assetType := asset.Item(assetTypeParam)
- ret, err := wrappers.GetWrapper().OHLCV(exchangeName, pairs, assetType, startTime, endTime, kline.Interval(interval))
+ ret, err := wrappers.GetWrapper().OHLCV(exchangeName, pair, assetType, startTime, endTime, kline.Interval(interval))
if err != nil {
return nil, err
}
diff --git a/gctscript/wrappers/gct/exchange/exchange.go b/gctscript/wrappers/gct/exchange/exchange.go
index 8e8ac49d..b46996e6 100644
--- a/gctscript/wrappers/gct/exchange/exchange.go
+++ b/gctscript/wrappers/gct/exchange/exchange.go
@@ -70,10 +70,15 @@ func (e Exchange) Pairs(exch string, enabledOnly bool, item asset.Item) (*curren
return nil, err
}
- if enabledOnly {
- return &x.CurrencyPairs.Get(item).Enabled, nil
+ ps, err := x.CurrencyPairs.Get(item)
+ if err != nil {
+ return nil, err
}
- return &x.CurrencyPairs.Get(item).Available, nil
+
+ if enabledOnly {
+ return &ps.Enabled, nil
+ }
+ return &ps.Available, nil
}
// QueryOrder returns details of a valid exchange order
diff --git a/gctscript/wrappers/gct/exchange/exchange_test.go b/gctscript/wrappers/gct/exchange/exchange_test.go
index c846b33c..16a4cb69 100644
--- a/gctscript/wrappers/gct/exchange/exchange_test.go
+++ b/gctscript/wrappers/gct/exchange/exchange_test.go
@@ -89,8 +89,11 @@ func TestExchange_IsEnabled(t *testing.T) {
func TestExchange_Ticker(t *testing.T) {
t.Parallel()
- c := currency.NewPairDelimiter(pairs, delimiter)
- _, err := exchangeTest.Ticker(exchName, c, assetType)
+ c, err := currency.NewPairDelimiter(pairs, delimiter)
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = exchangeTest.Ticker(exchName, c, assetType)
if err != nil {
t.Fatal(err)
}
@@ -98,8 +101,11 @@ func TestExchange_Ticker(t *testing.T) {
func TestExchange_Orderbook(t *testing.T) {
t.Parallel()
- c := currency.NewPairDelimiter(pairs, delimiter)
- _, err := exchangeTest.Orderbook(exchName, c, assetType)
+ c, err := currency.NewPairDelimiter(pairs, delimiter)
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = exchangeTest.Orderbook(exchName, c, assetType)
if err != nil {
t.Fatal(err)
}
@@ -141,8 +147,13 @@ func TestExchange_SubmitOrder(t *testing.T) {
if !configureExchangeKeys() {
t.Skip("no exchange configured test skipped")
}
+
+ c, err := currency.NewPairDelimiter(pairs, delimiter)
+ if err != nil {
+ t.Fatal(err)
+ }
tempOrder := &order.Submit{
- Pair: currency.NewPairDelimiter(pairs, delimiter),
+ Pair: c,
Type: orderType,
Side: orderSide,
TriggerPrice: 0,
@@ -152,7 +163,7 @@ func TestExchange_SubmitOrder(t *testing.T) {
ClientID: orderClientID,
Exchange: exchName,
}
- _, err := exchangeTest.SubmitOrder(tempOrder)
+ _, err = exchangeTest.SubmitOrder(tempOrder)
if err != nil {
t.Fatal(err)
}
diff --git a/gctscript/wrappers/validator/validator.go b/gctscript/wrappers/validator/validator.go
index c8f63fb8..228947b2 100644
--- a/gctscript/wrappers/validator/validator.go
+++ b/gctscript/wrappers/validator/validator.go
@@ -96,7 +96,12 @@ func (w Wrapper) Pairs(exch string, _ bool, _ asset.Item) (*currency.Pairs, erro
return nil, errTestFailed
}
- pairs := currency.NewPairsFromStrings([]string{"btc_usd", "btc_aud", "btc_ltc"})
+ pairs, err := currency.NewPairsFromStrings([]string{"btc_usd",
+ "btc_aud",
+ "btc_ltc"})
+ if err != nil {
+ return nil, err
+ }
return &pairs, nil
}
@@ -105,11 +110,17 @@ func (w Wrapper) QueryOrder(exch, _ string) (*order.Detail, error) {
if exch == exchError.String() {
return nil, errTestFailed
}
+
+ pair, err := currency.NewPairFromString("BTCAUD")
+ if err != nil {
+ return nil, err
+ }
+
return &order.Detail{
Exchange: exch,
AccountID: "hello",
ID: "1",
- Pair: currency.NewPairFromString("BTCAUD"),
+ Pair: pair,
Side: "ask",
Type: "limit",
Date: time.Now(),
@@ -121,7 +132,6 @@ func (w Wrapper) QueryOrder(exch, _ string) (*order.Detail, error) {
Fee: 0,
Trades: []order.TradeHistory{
{
- Timestamp: time.Now(),
TID: "",
Price: 1,
Amount: 2,
@@ -179,12 +189,11 @@ func (w Wrapper) AccountInformation(exch string) (account.Holdings, error) {
{
CurrencyName: currency.Code{
Item: ¤cy.Item{
- ID: 0,
- FullName: "Bitcoin",
- Symbol: "BTC",
- Role: 1,
- AssocChain: "",
- AssocExchange: nil,
+ ID: 0,
+ FullName: "Bitcoin",
+ Symbol: "BTC",
+ Role: 1,
+ AssocChain: "",
},
},
TotalValue: 100,
diff --git a/gctscript/wrappers/validator/validator_test.go b/gctscript/wrappers/validator/validator_test.go
index 679f22dc..eaa457d5 100644
--- a/gctscript/wrappers/validator/validator_test.go
+++ b/gctscript/wrappers/validator/validator_test.go
@@ -27,8 +27,8 @@ const (
)
var (
- currencyPair = currency.NewPairFromString("BTCAUD")
- testWrapper = Wrapper{}
+ currencyPair, _ = currency.NewPairFromString("BTCAUD")
+ testWrapper = Wrapper{}
)
func TestWrapper_Exchanges(t *testing.T) {
@@ -101,8 +101,11 @@ func TestWrapper_DepositAddress(t *testing.T) {
func TestWrapper_Orderbook(t *testing.T) {
t.Parallel()
- c := currency.NewPairDelimiter(pairs, delimiter)
- _, err := testWrapper.Orderbook(exchName, c, assetType)
+ c, err := currency.NewPairDelimiter(pairs, delimiter)
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = testWrapper.Orderbook(exchName, c, assetType)
if err != nil {
t.Fatal(err)
}
@@ -146,9 +149,12 @@ func TestWrapper_QueryOrder(t *testing.T) {
func TestWrapper_SubmitOrder(t *testing.T) {
t.Parallel()
-
+ c, err := currency.NewPairDelimiter(pairs, delimiter)
+ if err != nil {
+ t.Fatal(err)
+ }
tempOrder := &order.Submit{
- Pair: currency.NewPairDelimiter(pairs, delimiter),
+ Pair: c,
Type: orderType,
Side: orderSide,
TriggerPrice: 0,
@@ -158,7 +164,7 @@ func TestWrapper_SubmitOrder(t *testing.T) {
ClientID: orderClientID,
Exchange: "true",
}
- _, err := testWrapper.SubmitOrder(tempOrder)
+ _, err = testWrapper.SubmitOrder(tempOrder)
if err != nil {
t.Fatal(err)
}
@@ -171,8 +177,11 @@ func TestWrapper_SubmitOrder(t *testing.T) {
func TestWrapper_Ticker(t *testing.T) {
t.Parallel()
- c := currency.NewPairDelimiter(pairs, delimiter)
- _, err := testWrapper.Ticker(exchName, c, assetType)
+ c, err := currency.NewPairDelimiter(pairs, delimiter)
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = testWrapper.Ticker(exchName, c, assetType)
if err != nil {
t.Fatal(err)
}
@@ -208,8 +217,11 @@ func TestWrapper_WithdrawalFiatFunds(t *testing.T) {
}
func TestWrapper_OHLCV(t *testing.T) {
- c := currency.NewPairDelimiter(pairs, delimiter)
- _, err := testWrapper.OHLCV("test", c, asset.Spot, time.Now().Add(-24*time.Hour), time.Now(), kline.OneDay)
+ c, err := currency.NewPairDelimiter(pairs, delimiter)
+ if err != nil {
+ t.Fatal(err)
+ }
+ _, err = testWrapper.OHLCV("test", c, asset.Spot, time.Now().Add(-24*time.Hour), time.Now(), kline.OneDay)
if err != nil {
t.Fatal(err)
}
diff --git a/go.mod b/go.mod
index ae5b296e..ccbc52a2 100644
--- a/go.mod
+++ b/go.mod
@@ -1,9 +1,12 @@
module github.com/thrasher-corp/gocryptotrader
-go 1.12
+go 1.13
require (
+ github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
github.com/d5/tengo/v2 v2.6.0
+ github.com/friendsofgo/errors v0.9.2 // indirect
+ github.com/fsnotify/fsnotify v1.4.9 // indirect
github.com/gofrs/uuid v3.3.0+incompatible
github.com/golang/protobuf v1.4.2
github.com/google/go-querystring v1.0.0
@@ -14,8 +17,12 @@ require (
github.com/kat-co/vala v0.0.0-20170210184112-42e1d8b61f12
github.com/lib/pq v1.7.1
github.com/mattn/go-sqlite3 v1.14.0
+ github.com/mitchellh/mapstructure v1.3.2 // indirect
+ github.com/pelletier/go-toml v1.8.0 // indirect
github.com/pkg/errors v0.9.1
github.com/pquerna/otp v1.2.0
+ github.com/spf13/afero v1.3.1 // indirect
+ github.com/spf13/cast v1.3.1 // indirect
github.com/spf13/viper v1.7.0
github.com/stretchr/testify v1.5.1 // indirect
github.com/thrasher-corp/gct-ta v0.0.0-20200623072738-f2b55b7f9f41
@@ -23,13 +30,17 @@ require (
github.com/thrasher-corp/sqlboiler v1.0.1-0.20191001234224-71e17f37a85e
github.com/toorop/go-pusher v0.0.0-20180521062818-4521e2eb39fb
github.com/urfave/cli v1.22.4
+ github.com/volatiletech/inflect v0.0.1 // indirect
github.com/volatiletech/null v8.0.0+incompatible
+ github.com/volatiletech/sqlboiler v3.7.1+incompatible // indirect
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e
+ golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae // indirect
+ golang.org/x/text v0.3.3 // indirect
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013
google.golang.org/grpc v1.30.0
- google.golang.org/protobuf v1.25.0
+ google.golang.org/protobuf v1.25.0 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
- gopkg.in/yaml.v2 v2.2.7 // indirect
+ gopkg.in/ini.v1 v1.57.0 // indirect
)
diff --git a/go.sum b/go.sum
index a19e2446..1561db47 100644
--- a/go.sum
+++ b/go.sum
@@ -53,6 +53,8 @@ github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
+github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
+github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/d5/tengo/v2 v2.6.0 h1:D0cJtpiBzaLJ/Smv6nnUc/LIfO46oKwDx85NZtIRNRI=
github.com/d5/tengo/v2 v2.6.0/go.mod h1:XRGjEs5I9jYIKTxly6HCF8oiiilk5E/RYXOZ5b0DZC8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -67,8 +69,12 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ericlagergren/decimal v0.0.0-20180907214518-0bb163153a5d/go.mod h1:1yj25TwtUlJ+pfOu9apAVaM1RWfZGg+aFpd4hPQZekQ=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
+github.com/friendsofgo/errors v0.9.2 h1:X6NYxef4efCBdwI7BgS820zFaN7Cphrmb+Pljdzjtgk=
+github.com/friendsofgo/errors v0.9.2/go.mod h1:yCvFW5AkDIL9qn7suHVLiI/gH228n7PC4Pn44IGoTOI=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
+github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
@@ -108,6 +114,7 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.0 h1:/QaMHBdZ26BB3SSst0Iwl10Epc+xhTquomWX0oZEB6w=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
@@ -152,6 +159,7 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
+github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
@@ -166,6 +174,7 @@ github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -174,8 +183,6 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
-github.com/lib/pq v1.7.0 h1:h93mCPfUSkaul3Ka/VG8uZdmW1uMHDGxzu0NWHuJmHY=
-github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.7.1 h1:FvD5XTVTDt+KON6oIoOmHq6B6HzGuYEhuTMpEG0yuBQ=
github.com/lib/pq v1.7.1/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
@@ -196,6 +203,8 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/mitchellh/mapstructure v1.3.2 h1:mRS76wmkOn3KkKAyXDu42V+6ebnXWIztFSYGN7GeoRg=
+github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@@ -205,10 +214,13 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.4.0 h1:u3Z1r+oOXJIkxqw34zVhyPgjBsm6X2wn21NWs/HfSeg=
github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
+github.com/pelletier/go-toml v1.8.0 h1:Keo9qb7iRJs2voHvunFtuuYFsbWeOBh8/P9v/kVMFtw=
+github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bAOTRnLElKs=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
@@ -248,8 +260,13 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
+github.com/spf13/afero v1.3.1 h1:GPTpEAuNr98px18yNQ66JllNil98wfRZ/5Ukny8FeQA=
+github.com/spf13/afero v1.3.1/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
+github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
+github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
+github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
@@ -285,10 +302,14 @@ github.com/urfave/cli v1.22.4 h1:u7tSpNPPswAFymm8IehJhy4uJMlUuU/GmqSkvJ1InXA=
github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/volatiletech/inflect v0.0.0-20170731032912-e7201282ae8d h1:gI4/tqP6lCY5k6Sg+4k9qSoBXmPwG+xXgMpK7jivD4M=
github.com/volatiletech/inflect v0.0.0-20170731032912-e7201282ae8d/go.mod h1:jspfvgf53t5NLUT4o9L1IX0kIBNKamGq1tWc/MgWK9Q=
+github.com/volatiletech/inflect v0.0.1 h1:2a6FcMQyhmPZcLa+uet3VJ8gLn/9svWhJxJYwvE8KsU=
+github.com/volatiletech/inflect v0.0.1/go.mod h1:IBti31tG6phkHitLlr5j7shC5SOo//x0AjDzaJU1PLA=
github.com/volatiletech/null v8.0.0+incompatible h1:7wP8m5d/gZ6kW/9GnrLtMCRre2dlEnaQ9Km5OXlK4zg=
github.com/volatiletech/null v8.0.0+incompatible/go.mod h1:0wD98JzdqB+rLyZ70fN05VDbXbafIb0KU0MdVhCzmOQ=
github.com/volatiletech/sqlboiler v3.5.0+incompatible h1:n160O7UQLpZVRnJY6VH5eRNkt7sQdQBZGCCZ3CUy1+g=
github.com/volatiletech/sqlboiler v3.5.0+incompatible/go.mod h1:jLfDkkHWPbS2cWRLkyC20vQWaIQsASEY7gM7zSo11Yw=
+github.com/volatiletech/sqlboiler v3.7.1+incompatible h1:dm9/NjDskQVwAarmpeZ2UqLn1NKE8M3WHSHBS4jw2x8=
+github.com/volatiletech/sqlboiler v3.7.1+incompatible/go.mod h1:jLfDkkHWPbS2cWRLkyC20vQWaIQsASEY7gM7zSo11Yw=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
@@ -304,6 +325,7 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4 h1:QmwruyY+bKbDDL0BaglrbZABEali68eoMFhTZpCjYVA=
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -370,12 +392,17 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190927073244-c990c680b611/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae h1:Ih9Yo4hSPImZOpfGuA4bR/ORKTAbhZo2AbWNRCnevdo=
+golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -421,6 +448,7 @@ google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBr
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884 h1:fiNLklpBwWK1mth30Hlwk+fcdBmIALlgF5iy77O37Ig=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
@@ -453,14 +481,17 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/ini.v1 v1.57.0 h1:9unxIsFcTt4I55uWluz+UmL95q4kdJ0buvQ1ZIqVQww=
+gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.3 h1:fvjTMHxHEw/mxHbtzPi3JCcKXQRAnQTBRo6YCJSVHKI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
-gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/testdata/configtest.json b/testdata/configtest.json
index b452a883..95cc256c 100644
--- a/testdata/configtest.json
+++ b/testdata/configtest.json
@@ -507,8 +507,8 @@
],
"pairs": {
"spot": {
- "enabled": "BTCKRW,ETHKRW,DASHKRW,LTCKRW,ETCKRW,XRPKRW,BCHKRW,XMRKRW,ZECKRW,QTUMKRW,BTGKRW,EOSKRW",
- "available": "BHPKRW,STEEMKRW,GTOKRW,ETCKRW,STRATKRW,FXKRW,LTCKRW,MIXKRW,THETAKRW,QTUMKRW,ADAKRW,MCOKRW,INSKRW,RDNKRW,CONKRW,FABKRW,ETHKRW,HDACKRW,BTCKRW,POWRKRW,CMTKRW,LBAKRW,ETHOSKRW,HCKRW,ETZKRW,PPTKRW,XVGKRW,WTCKRW,TMTGKRW,LOOMKRW,WETKRW,ABTKRW,ITCKRW,GXCKRW,ORBSKRW,ICXKRW,BSVKRW,MXCKRW,MITHKRW,ZECKRW,AEKRW,SALTKRW,ARNKRW,TRUEKRW,ENJKRW,GNTKRW,PLYKRW,XMRKRW,REPKRW,ZRXKRW,BTGKRW,APISKRW,QKCKRW,LRCKRW,DVPKRW,DADKRW,CHRKRW,BCHKRW,NPXSKRW,PIVXKRW,AMOKRW,RNTKRW,XEMKRW,FCTKRW,WOMKRW,WAXPKRW,DACKRW,OMGKRW,PCMKRW,CROKRW,FNBKRW,ANKRKRW,EOSKRW,KNCKRW,OCNKRW,MTLKRW,XSRKRW,VALORKRW,TRVKRW,AUTOKRW,HYCKRW,AOAKRW,BTTKRW,MBLKRW,VETKRW,XRPKRW,ZILKRW,ELFKRW,LAMBKRW,POLYKRW,IOSTKRW,BZNTKRW,DASHKRW,CTXCKRW,BATKRW,FZZKRW,PAYKRW,BCDKRW,SNTKRW,WAVESKRW,XLMKRW,LINKKRW,OGOKRW,WICCKRW,TRXKRW"
+ "enabled": "BTCKRW,ETHKRW,DASHKRW,LTCKRW,ETCKRW,XRPKRW,BCHKRW,ZECKRW,QTUMKRW,BTGKRW,EOSKRW",
+ "available": "BHPKRW,STEEMKRW,GTOKRW,ETCKRW,STRATKRW,FXKRW,LTCKRW,MIXKRW,THETAKRW,QTUMKRW,ADAKRW,MCOKRW,INSKRW,RDNKRW,CONKRW,FABKRW,ETHKRW,HDACKRW,BTCKRW,POWRKRW,CMTKRW,LBAKRW,ETHOSKRW,HCKRW,ETZKRW,PPTKRW,XVGKRW,WTCKRW,TMTGKRW,LOOMKRW,WETKRW,ABTKRW,ITCKRW,GXCKRW,ORBSKRW,ICXKRW,BSVKRW,MXCKRW,MITHKRW,ZECKRW,AEKRW,SALTKRW,ARNKRW,TRUEKRW,ENJKRW,GNTKRW,PLYKRW,REPKRW,ZRXKRW,BTGKRW,APISKRW,QKCKRW,LRCKRW,DVPKRW,DADKRW,CHRKRW,BCHKRW,NPXSKRW,PIVXKRW,AMOKRW,RNTKRW,XEMKRW,FCTKRW,WOMKRW,WAXPKRW,DACKRW,OMGKRW,PCMKRW,CROKRW,FNBKRW,ANKRKRW,EOSKRW,KNCKRW,OCNKRW,MTLKRW,XSRKRW,VALORKRW,TRVKRW,AUTOKRW,HYCKRW,AOAKRW,BTTKRW,MBLKRW,VETKRW,XRPKRW,ZILKRW,ELFKRW,LAMBKRW,POLYKRW,IOSTKRW,BZNTKRW,DASHKRW,CTXCKRW,BATKRW,FZZKRW,PAYKRW,BCDKRW,SNTKRW,WAVESKRW,XLMKRW,LINKKRW,OGOKRW,WICCKRW,TRXKRW"
}
}
},
|