From 63191ce3ecdf8853ba8d6c976abd2648e6b59596 Mon Sep 17 00:00:00 2001 From: Adrian Gallagher Date: Fri, 22 Nov 2019 16:07:30 +1100 Subject: [PATCH] Engine QA (#381) * 1) Update Dockerfile/docker-compose.yml 2) Remove inline strings for buy/sell/test pairs 3) Remove dangerous order submission values 4) Fix consistency with audit_events (all other spec files use CamelCase) 5) Update web websocket endpoint 6) Fix main param set (and induce dryrun mode on specific command line params) * Engine QA Link up exchange syncer to cmd params, disarm market selling bombs and fix OKEX endpoints * Fix linter issue after merge * Engine QA changes Template updates Wrapper code cleanup Disarmed order bombs Documentation updates * Daily engine QA Bitstamp improvements Spelling mistakes Add Coinbene exchange to support list Protect API authenticated calls for Coinbene/LBank * Engine QA changes Fix exchange_wrapper_coverage tool Add SupportsAsset to exchange interface Fix inline string usage and add BCH withdrawal support * Engine QA Fix Bitstamp types Inform user of errors when parsing time accross the codebase Change time parsing warnings to errors (as they are) Update markdown docs [with linter fixes] * Engine QA changes 1) Add test for dryrunParamInteraction 2) Disarm OKCoin/OKEX bombs if someone accidently sets canManipulateRealOrders to true and runs all package tests 3) Actually check exchange setup errors for BTSE and Coinbene, plus address this in the wrapper template 4) Hardcode missing/non-retrievable contributors and bump the contributors 5) Convert numbers/strings to meaningful types in Bitstamp and OKEX 6) If WS is supported for the exchange wrapper template, preset authWebsocketSupport var * Fix the shadow people * Link the SyncContinuously paramerino * Also show SyncContinuously in engine.PrintSettings * Address nitterinos and use correct filepath for logs * Bitstamp: Extract ALL THE APM * Fix additional nitterinos * Fix time parsing error for Bittrex --- .github/CONTRIBUTING.md | 57 +- .github/CONTRIBUTING_TEMPLATE.md | 6 +- .github/ISSUE_TEMPLATE.md | 2 +- .github/PULL_REQUEST_TEMPLATE.md | 22 +- CONTRIBUTORS | 3 +- Dockerfile | 14 +- README.md | 7 +- cmd/documentation/documentation.go | 38 + .../exchanges_templates/coinbene.tmpl | 6 +- .../exchanges_templates/lbank.tmpl | 10 +- cmd/exchange_template/exchange_template.go | 24 +- cmd/exchange_template/main_file.tmpl | 90 +- cmd/exchange_template/test_file.tmpl | 44 +- cmd/exchange_template/wrapper_file.tmpl | 291 ++- cmd/exchange_wrapper_coverage/main.go | 8 + .../wrapperconfig.json | 11 +- communications/slack/slack_test.go | 68 +- communications/slack/slack_types.go | 404 +--- config/config_test.go | 9 +- docker-compose.yml | 6 +- docs/EXCHANGE_API.md | 8 +- engine/engine.go | 48 +- engine/engine_types.go | 21 +- engine/events.go | 1 - engine/exchange.go | 27 + engine/exchange_test.go | 83 +- engine/routines.go | 11 +- engine/syncer.go | 28 +- engine/syncer_types.go | 6 +- exchanges/alphapoint/alphapoint_wrapper.go | 17 +- exchanges/anx/anx_test.go | 2 +- exchanges/anx/anx_wrapper.go | 3 +- exchanges/binance/binance.go | 57 +- exchanges/binance/binance_test.go | 2 +- exchanges/binance/binance_types.go | 26 +- exchanges/binance/binance_wrapper.go | 3 +- exchanges/bitfinex/bitfinex_websocket.go | 7 +- exchanges/bitfinex/bitfinex_wrapper.go | 3 +- exchanges/bithumb/bithumb_test.go | 19 +- exchanges/bithumb/bithumb_wrapper.go | 3 +- exchanges/bitmex/bitmex_websocket.go | 12 +- exchanges/bitstamp/bitstamp.go | 176 +- exchanges/bitstamp/bitstamp_test.go | 47 +- exchanges/bitstamp/bitstamp_types.go | 90 +- exchanges/bitstamp/bitstamp_websocket.go | 22 +- exchanges/bitstamp/bitstamp_wrapper.go | 87 +- exchanges/bittrex/bittrex.go | 6 + exchanges/bittrex/bittrex_test.go | 18 + exchanges/bittrex/bittrex_wrapper.go | 17 +- exchanges/btcmarkets/btcmarkets_types.go | 1 + exchanges/btcmarkets/btcmarkets_wrapper.go | 15 +- exchanges/btse/btse.go | 8 +- exchanges/btse/btse_test.go | 34 +- exchanges/btse/btse_websocket.go | 15 +- exchanges/btse/btse_wrapper.go | 30 +- exchanges/coinbasepro/coinbasepro_test.go | 19 +- exchanges/coinbasepro/coinbasepro_wrapper.go | 4 +- exchanges/coinbene/README.md | 10 +- exchanges/coinbene/coinbene.go | 5 + exchanges/coinbene/coinbene_test.go | 6 +- exchanges/coinut/coinut_wrapper.go | 4 +- exchanges/exchange.go | 6 +- exchanges/exchange_test.go | 10 +- exchanges/exmo/exmo_wrapper.go | 3 +- exchanges/gateio/gateio_wrapper.go | 15 +- exchanges/gemini/gemini_test.go | 6 +- exchanges/gemini/gemini_wrapper.go | 3 +- exchanges/hitbtc/hitbtc_websocket.go | 27 +- exchanges/hitbtc/hitbtc_wrapper.go | 19 +- exchanges/huobi/huobi_wrapper.go | 18 +- exchanges/interfaces.go | 1 + exchanges/itbit/itbit_wrapper.go | 17 +- exchanges/kraken/kraken_wrapper.go | 3 +- exchanges/lakebtc/lakebtc_websocket.go | 7 +- exchanges/lakebtc/lakebtc_wrapper.go | 3 +- exchanges/lbank/README.md | 10 +- exchanges/lbank/lbank.go | 8 +- exchanges/lbank/lbank_wrapper.go | 6 +- .../localbitcoins/localbitcoins_wrapper.go | 19 +- exchanges/okcoin/okcoin_test.go | 143 +- exchanges/okex/okex_test.go | 162 +- exchanges/okgroup/README.md | 10 +- exchanges/okgroup/okgroup.go | 31 +- exchanges/okgroup/okgroup_types.go | 60 +- exchanges/okgroup/okgroup_websocket.go | 18 +- exchanges/okgroup/okgroup_wrapper.go | 8 +- exchanges/poloniex/poloniex.go | 20 +- exchanges/poloniex/poloniex_websocket.go | 7 +- exchanges/poloniex/poloniex_wrapper.go | 22 +- exchanges/support.go | 1 + exchanges/yobit/yobit_wrapper.go | 3 +- exchanges/zb/zb_wrapper.go | 22 +- gctrpc/rpc.pb.go | 755 ++++--- gctrpc/rpc.pb.gw.go | 1801 +++++++++++++++-- gctrpc/rpc.proto | 4 +- gctrpc/rpc.swagger.json | 36 +- main.go | 14 +- testdata/http_mock/anx/anx.json | 2 +- testdata/http_mock/binance/binance.json | 2 +- testdata/http_mock/bitstamp/bitstamp.json | 2 +- testdata/http_mock/gemini/gemini.json | 2 +- .../websocket-response-handler.service.ts | 2 +- 102 files changed, 3581 insertions(+), 1848 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index cd01660e8e9..6c539d02eb0 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -17,6 +17,7 @@ In order to maintain a consistent style across the codebase, the following codin - In line with gofmt, for loops and if statements don't require parenthesis. Block style example: + ```go func SendHTTPRequest(method, path string, headers map[string]string, body io.Reader) (string, error) { result := strings.ToUpper(method) @@ -38,51 +39,51 @@ func SendHTTPRequest(method, path string, headers map[string]string, body io.Rea ``` ## Effective Go Guidelines -[CodeLingo](https://codelingo.io) automatically checks every pull request against the following guidelines from [Effective Go](https://golang.org/doc/effective_go.html). +[CodeLingo](https://codelingo.io) automatically checks every pull request against the following guidelines from [Effective Go](https://golang.org/doc/effective_go.html). ### Comment First Word as Subject + Doc comments work best as complete sentences, which allow a wide variety of automated presentations. The first sentence should be a one-sentence summary that starts with the name being declared. - ### Good Package Name -It's helpful if everyone using the package can use the same name -to refer to its contents, which implies that the package name should -be good: short, concise, evocative. By convention, packages are -given lower case, single-word names; there should be no need for -underscores or mixedCaps. Err on the side of brevity, since everyone -using your package will be typing that name. And don't worry about -collisions a priori. The package name is only the default name for -imports; it need not be unique across all source code, and in the -rare case of a collision the importing package can choose a different -name to use locally. In any case, confusion is rare because the file -name in the import determines just which package is being used. +It's helpful if everyone using the package can use the same name +to refer to its contents, which implies that the package name should +be good: short, concise, evocative. By convention, packages are +given lower case, single-word names; there should be no need for +underscores or mixedCaps. Err on the side of brevity, since everyone +using your package will be typing that name. And don't worry about +collisions a priori. The package name is only the default name for +imports; it need not be unique across all source code, and in the +rare case of a collision the importing package can choose a different +name to use locally. In any case, confusion is rare because the file +name in the import determines just which package is being used. ### Package Comment -Every package should have a package comment, a block comment preceding the package clause. -For multi-file packages, the package comment only needs to be present in one file, and any one will do. -The package comment should introduce the package and provide information relevant to the package as a -whole. It will appear first on the godoc page and should set up the detailed documentation that follows. +Every package should have a package comment, a block comment preceding the package clause. +For multi-file packages, the package comment only needs to be present in one file, and any one will do. +The package comment should introduce the package and provide information relevant to the package as a +whole. It will appear first on the godoc page and should set up the detailed documentation that follows. ### Single Method Interface Name -By convention, one-method interfaces are named by the method name plus an -er suffix + +By convention, one-method interfaces are named by the method name plus an -er suffix or similar modification to construct an agent noun: Reader, Writer, Formatter, CloseNotifier etc. -There are a number of such names and it's productive to honor them and the function names they capture. -Read, Write, Close, Flush, String and so on have canonical signatures and meanings. To avoid confusion, -don't give your method one of those names unless it has the same signature and meaning. Conversely, -if your type implements a method with the same meaning as a method on a well-known type, give it the +There are a number of such names and it's productive to honor them and the function names they capture. +Read, Write, Close, Flush, String and so on have canonical signatures and meanings. To avoid confusion, +don't give your method one of those names unless it has the same signature and meaning. Conversely, +if your type implements a method with the same meaning as a method on a well-known type, give it the same name and signature; call your string-converter method String not ToString. - ### Avoid Annotations in Comments + Comments do not need extra formatting such as banners of stars. The generated output -may not even be presented in a fixed-width font, so don't depend on spacing for alignment—godoc, -like gofmt, takes care of that. The comments are uninterpreted plain text, so HTML and other -annotations such as _this_ will reproduce verbatim and should not be used. One adjustment godoc -does do is to display indented text in a fixed-width font, suitable for program snippets. +may not even be presented in a fixed-width font, so don't depend on spacing for alignment—godoc, +like gofmt, takes care of that. The comments are uninterpreted plain text, so HTML and other +annotations such as _this_ will reproduce verbatim and should not be used. One adjustment godoc +does do is to display indented text in a fixed-width font, suitable for program snippets. The package comment for the fmt package uses this to good effect. - diff --git a/.github/CONTRIBUTING_TEMPLATE.md b/.github/CONTRIBUTING_TEMPLATE.md index f4aecf7cc8b..cff2cb3f6f0 100644 --- a/.github/CONTRIBUTING_TEMPLATE.md +++ b/.github/CONTRIBUTING_TEMPLATE.md @@ -17,6 +17,7 @@ In order to maintain a consistent style across the codebase, the following codin - In line with gofmt, for loops and if statements don't require parenthesis. Block style example: + ```go func SendHTTPRequest(method, path string, headers map[string]string, body io.Reader) (string, error) { result := strings.ToUpper(method) @@ -38,9 +39,12 @@ func SendHTTPRequest(method, path string, headers map[string]string, body io.Rea ``` ## Effective Go Guidelines + [CodeLingo](https://codelingo.io) automatically checks every pull request against the following guidelines from [Effective Go](https://golang.org/doc/effective_go.html). {{range .}} + ### {{.title}} + {{.body}} -{{end}} \ No newline at end of file +{{end}} diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index cbf11442755..75073df6057 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -30,4 +30,4 @@ Please provide detailed steps for reproducing the issue. ### Failure Logs -By default, GoCryptoTrader stores its `debug.log` file in `%APPDATA%\GoCryptoTrader` on Windows and `~/.gocryptotrader` on Linux/Unix/macOS. Raw text or a link to a pastebin type site is preferred. \ No newline at end of file +By default and if file logging is enabled, GoCryptoTrader stores its `log.txt` file in `%APPDATA%\GoCryptoTrader\logs` on Windows and `~/.gocryptotrader/logs` on Linux/Unix/macOS. Raw text or a link to a pastebin type site is preferred. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index d3ddb8a0715..edabdd52e40 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,6 +1,6 @@ -# Description +# PR Description -Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change. +Please include a summary of the change, feature or issue which this pull request addresses. Please also include relevant motivation and context. List any dependencies that are required for this change. Fixes # (issue) @@ -13,22 +13,22 @@ Please delete options that are not relevant and add an `x` in `[]` as item is co - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [ ] This change requires a documentation update -# How Has This Been Tested? +## How has this been tested -Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration +Please describe the tests that you ran to verify your changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration and +also consider improving test coverage whilst working on a certain feature or package. -## Please also consider improving test coverage whilst working on a certain package +- [ ] go test ./... -race +- [ ] golangci-lint run +- [ ] Test X -- [ ] Test A -- [ ] Test B - -# Checklist: +## Checklist - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas -- [ ] I have made corresponding changes to the documentation and regenerated documentation via the documentation tool +- [ ] I have made corresponding changes to the documentation and regenerated documentation via the documentation tool - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally and on Travis with my changes -- [ ] Any dependent changes have been merged and published in downstream modules \ No newline at end of file +- [ ] Any dependent changes have been merged and published in downstream modules diff --git a/CONTRIBUTORS b/CONTRIBUTORS index c895892318c..3453fc1875e 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -8,8 +8,8 @@ ermalguni | https://github.com/ermalguni vadimzhukck | https://github.com/vadimzhukck 140am | https://github.com/140am marcofranssen | https://github.com/marcofranssen -cranktakular | https://github.com/cranktakular MadCozBadd | https://github.com/MadCozBadd +cranktakular | https://github.com/cranktakular leilaes | https://github.com/leilaes crackcomm | https://github.com/crackcomm andreygrehov | https://github.com/andreygrehov @@ -30,6 +30,7 @@ frankzougc | https://github.com/frankzougc starit | https://github.com/starit Jimexist | https://github.com/Jimexist lookfirst | https://github.com/lookfirst +idoall | https://github.com/idoall mattkanwisher | https://github.com/mattkanwisher mKurrels | https://github.com/mKurrels m1kola | https://github.com/m1kola diff --git a/Dockerfile b/Dockerfile index 67fa7f9ba91..2524f16bff4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,14 +1,18 @@ -FROM golang:1.12 as build +FROM golang:1.13 as build WORKDIR /go/src/github.com/thrasher-corp/gocryptotrader COPY . . RUN GO111MODULE=on go mod vendor RUN mv -vn config_example.json config.json \ - && GOARCH=386 GOOS=linux CGO_ENABLED=0 go build . \ - && mv gocryptotrader /go/bin/gocryptotrader + && GOARCH=386 GOOS=linux go build . \ + && GOARCH=386 GOOS=linux go build ./cmd/gctcli \ + && mv gocryptotrader /go/bin/gocryptotrader \ + && mv gctcli /go/bin/gctcli FROM alpine:latest -RUN apk update && apk add --no-cache ca-certificates +VOLUME /root/.gocryptotrader +RUN apk update && apk add --no-cache ca-certificates bash COPY --from=build /go/bin/gocryptotrader /app/ +COPY --from=build /go/bin/gctcli /app/ COPY --from=build /go/src/github.com/thrasher-corp/gocryptotrader/config.json /app/ EXPOSE 9050-9053 -CMD ["/app/gocryptotrader"] +ENTRYPOINT [ "/app/gocryptotrader" ] diff --git a/README.md b/README.md index 3f99dcdae81..5aee76a4b33 100644 --- a/README.md +++ b/README.md @@ -138,7 +138,7 @@ Binaries will be published once the codebase reaches a stable condition. |User|Contribution Amount| |--|--| -| [thrasher-](https://github.com/thrasher-) | 548 | +| [thrasher-](https://github.com/thrasher-) | 551 | | [shazbert](https://github.com/shazbert) | 176 | | [gloriousCode](https://github.com/gloriousCode) | 155 | | [xtda](https://github.com/xtda) | 18 | @@ -146,8 +146,8 @@ Binaries will be published once the codebase reaches a stable condition. | [vadimzhukck](https://github.com/vadimzhukck) | 10 | | [140am](https://github.com/140am) | 8 | | [marcofranssen](https://github.com/marcofranssen) | 8 | +| [MadCozBadd](https://github.com/MadCozBadd) | 6 | | [cranktakular](https://github.com/cranktakular) | 5 | -| [MadCozBadd](https://github.com/MadCozBadd) | 3 | | [leilaes](https://github.com/leilaes) | 3 | | [crackcomm](https://github.com/crackcomm) | 3 | | [andreygrehov](https://github.com/andreygrehov) | 2 | @@ -168,8 +168,9 @@ Binaries will be published once the codebase reaches a stable condition. | [starit](https://github.com/starit) | 1 | | [Jimexist](https://github.com/Jimexist) | 1 | | [lookfirst](https://github.com/lookfirst) | 1 | +| [idoall](https://github.com/idoall) | 1 | | [mattkanwisher](https://github.com/mattkanwisher) | 1 | | [mKurrels](https://github.com/mKurrels) | 1 | | [m1kola](https://github.com/m1kola) | 1 | | [cavapoo2](https://github.com/cavapoo2) | 1 | -| [zeldrinn](https://github.com/zeldrinn )| 1 | +| [zeldrinn](https://github.com/zeldrinn) | 1 | diff --git a/cmd/documentation/documentation.go b/cmd/documentation/documentation.go index 0fcba9fb7ae..5267e306ea9 100644 --- a/cmd/documentation/documentation.go +++ b/cmd/documentation/documentation.go @@ -116,6 +116,44 @@ func main() { err) } + // idoall's contributors were forked and merged, so his contributions + // aren't automatically retrievable + contributors = append(contributors, Contributor{ + Login: "idoall", + URL: "https://github.com/idoall", + Contributions: 1, + }) + + // Github API missing contributors + missingAPIContributors := []Contributor{ + { + Login: "mattkanwisher", + URL: "https://github.com/mattkanwisher", + Contributions: 1, + }, + { + Login: "mKurrels", + URL: "https://github.com/mKurrels", + Contributions: 1, + }, + { + Login: "m1kola", + URL: "https://github.com/m1kola", + Contributions: 1, + }, + { + Login: "cavapoo2", + URL: "https://github.com/cavapoo2", + Contributions: 1, + }, + { + Login: "zeldrinn", + URL: "https://github.com/zeldrinn", + Contributions: 1, + }, + } + contributors = append(contributors, missingAPIContributors...) + if *verbose { fmt.Println("Contributor List Fetched") for i := range contributors { diff --git a/cmd/documentation/exchanges_templates/coinbene.tmpl b/cmd/documentation/exchanges_templates/coinbene.tmpl index 4efb55bab12..7dc3b4d43e8 100644 --- a/cmd/documentation/exchanges_templates/coinbene.tmpl +++ b/cmd/documentation/exchanges_templates/coinbene.tmpl @@ -30,9 +30,9 @@ main.go ```go var c exchange.IBotExchange -for i := range bot.exchanges { - if bot.exchanges[i].GetName() == "Coinbene" { - c = bot.exchanges[i] +for i := range Bot.Exchanges { + if Bot.Exchanges[i].GetName() == "Coinbene" { + c = Bot.Exchanges[i] } } diff --git a/cmd/documentation/exchanges_templates/lbank.tmpl b/cmd/documentation/exchanges_templates/lbank.tmpl index 45fb9441c29..890fb91f74a 100644 --- a/cmd/documentation/exchanges_templates/lbank.tmpl +++ b/cmd/documentation/exchanges_templates/lbank.tmpl @@ -29,22 +29,22 @@ main.go ```go var l exchange.IBotExchange -for i := range bot.exchanges { - if bot.exchanges[i].GetName() == "Lbank" { - l = bot.exchanges[i] +for i := range Bot.Exchanges { + if Bot.Exchanges[i].GetName() == "Lbank" { + l = Bot.Exchanges[i] } } // Public calls - wrapper functions // Fetches current ticker information -tick, err := l.GetTickerPrice() +tick, err := l.FetchTicker() if err != nil { // Handle error } // Fetches current orderbook information -ob, err := l.GetOrderbookEx() +ob, err := l.FetchOrderbook() if err != nil { // Handle error } diff --git a/cmd/exchange_template/exchange_template.go b/cmd/exchange_template/exchange_template.go index d01224eb89b..ef976e09fe3 100644 --- a/cmd/exchange_template/exchange_template.go +++ b/cmd/exchange_template/exchange_template.go @@ -24,7 +24,6 @@ const ( packageReadme = "README.md" exchangePackageLocation = "../../exchanges" - exchangeLocation = "../../exchange.go" exchangeConfigPath = "../../testdata/configtest.json" ) @@ -35,7 +34,6 @@ var ( exchangeWrapper string exchangeMain string exchangeReadme string - exchangeJSON string ) type exchange struct { @@ -119,17 +117,22 @@ func main() { newExchConfig.Enabled = true 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, + }, + ConfigFormat: ¤cy.PairFormat{ + Uppercase: true, + }, } configTestFile.Exchanges = append(configTestFile.Exchanges, newExchConfig) - // TODO sorting function so exchanges are in alphabetical order - low priority - err = configTestFile.SaveConfig(exchangeJSON, false) + err = configTestFile.SaveConfig(exchangeConfigPath, false) if err != nil { log.Fatal("GoCryptoTrader: Exchange templating configuration error - cannot save") } @@ -217,12 +220,13 @@ func main() { } fmt.Println("GoCryptoTrader: Exchange templating tool service complete") - fmt.Println("When wrapper is finished add exchange to exchange.go") - fmt.Println("Test exchange.go") - fmt.Println("Update the config_test.go file") - fmt.Println("Test config.go") + fmt.Println("When the exchange code implementation has been completed (REST/Websocket/wrappers and tests), please add the exchange to engine/exchange.go") + fmt.Println("Add the exchange config settings to config_example.json (it will automatically be added to testdata/configtest.json)") + fmt.Println("Increment the available exchanges counter in config/config_test.go") + fmt.Println("Add the exchange name to exchanges/support.go") + fmt.Println("Ensure go test ./... -race passes") fmt.Println("Open a pull request") - fmt.Println("If help is needed please post a message on Slack.") + fmt.Println("If help is needed, please post a message in Slack.") } func newFile(path string) { diff --git a/cmd/exchange_template/main_file.tmpl b/cmd/exchange_template/main_file.tmpl index 151080b5f51..ef86003af80 100644 --- a/cmd/exchange_template/main_file.tmpl +++ b/cmd/exchange_template/main_file.tmpl @@ -2,15 +2,7 @@ package {{.Name}} import ( - "time" - - "github.com/thrasher-corp/gocryptotrader/common" - "github.com/thrasher-corp/gocryptotrader/config" exchange "github.com/thrasher-corp/gocryptotrader/exchanges" - "github.com/thrasher-corp/gocryptotrader/exchanges/request" - "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" - "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler" - log "github.com/thrasher-corp/gocryptotrader/logger" ) // {{.CapitalName}} is the overarching type across this package @@ -20,91 +12,13 @@ type {{.CapitalName}} struct { const ( {{.Name}}APIURL = "" - {{.Name}}APIVersion = "" + {{.Name}}APIVersion = "" // Public endpoints // Authenticated endpoints - ) -// SetDefaults sets the basic defaults for {{.CapitalName}} -func ({{.Variable}} *{{.CapitalName}}) SetDefaults() { - {{.Variable}}.Name = "{{.CapitalName}}" - {{.Variable}}.Enabled = false - {{.Variable}}.Verbose = false - {{.Variable}}.RequestCurrencyPairFormat.Delimiter = "" - {{.Variable}}.RequestCurrencyPairFormat.Uppercase = true - {{.Variable}}.ConfigCurrencyPairFormat.Delimiter = "" - {{.Variable}}.ConfigCurrencyPairFormat.Uppercase = true - {{.Variable}}.AssetTypes = asset.Items{asset.Spot} - {{.Variable}}.SupportsAutoPairUpdating = false - {{.Variable}}.SupportsRESTTickerBatching = false - {{.Variable}}.Requester = request.New({{.Variable}}.Name, - request.NewRateLimit(time.Second, 0), - request.NewRateLimit(time.Second, 0), - common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout)) - {{.Variable}}.API.Endpoints.URLDefault = {{.Name}}APIURL - {{.Variable}}.API.Endpoints.URL = {{.Variable}}.API.Endpoints.URLDefault - {{.Variable}}.Websocket = monitor.New() - {{.Variable}}.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit - {{.Variable}}.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout -} +// Start implementing public and private exchange API funcs below -// Setup takes in the supplied exchange configuration details and sets params -func ({{.Variable}} *{{.CapitalName}}) Setup(exch *config.ExchangeConfig) error { - if !exch.Enabled { - {{.Variable}}.SetEnabled(false) - } else { - {{.Variable}}.Enabled = true - {{.Variable}}.API.AuthenticatedSupport = exch.API.AuthenticatedSupport - {{.Variable}}.API.AuthenticatedWebsocketSupport = exch.API.AuthenticatedWebsocketSupport - {{.Variable}}.SetAPIKeys(exch.API.Credentials.Key, exch.API.Credentials.Secret, "", false) - {{.Variable}}.SetHTTPClientTimeout(exch.HTTPTimeout) - {{.Variable}}.SetHTTPClientUserAgent(exch.HTTPUserAgent) - {{.Variable}}.Verbose = exch.Verbose - {{.Variable}}.Websocket.SetWsStatusAndConnection(exch.Features.Enabled.Websocket) - {{.Variable}}.BaseCurrencies = strings.Split(exch.BaseCurrencies, ",") - {{.Variable}}.AvailablePairs = strings.Split(exch.AvailablePairs, ",") - {{.Variable}}.EnabledPairs = strings.Split(exch.EnabledPairs, ",") - err := {{.Variable}}.SetCurrencyPairFormat() - if err != nil { - log.Fatal(err) - } - err = {{.Variable}}.SetAssetTypes() - if err != nil { - log.Fatal(err) - } - err = {{.Variable}}.SetFeatureDefaults() - if err != nil { - log.Fatal(err) - } - err = {{.Variable}}.SetAPIURL(exch) - if err != nil { - log.Fatal(err) - } - err = {{.Variable}}.SetClientProxyAddress(exch.ProxyAddress) - if err != nil { - log.Fatal(err) - } - - // If the exchange supports websocket, update the below block - // err = {{.Variable}}.Websocket.Setup({{.Variable}}.WsConnect, - // exch.Name, - // exch.Features.Enabled.Websocket, - // {{.Name}}Websocket, - // exch.Features.Enabled.WebsocketURL) - // if err != nil { - // log.Fatal(err) - // } - // {{.Variable}}.WebsocketConn = &wshandler.WebsocketConnection{ - // ExchangeName: {{.Variable}}.Name, - // URL: {{.Variable}}.Websocket.GetWebsocketURL(), - // ProxyURL: {{.Variable}}.Websocket.GetProxyAddress(), - // Verbose: {{.Variable}}.Verbose, - // ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout, - // ResponseMaxLimit: exch.WebsocketResponseMaxLimit, - // } - } -} {{end}} diff --git a/cmd/exchange_template/test_file.tmpl b/cmd/exchange_template/test_file.tmpl index 87ee2bdc84b..989238e8c89 100644 --- a/cmd/exchange_template/test_file.tmpl +++ b/cmd/exchange_template/test_file.tmpl @@ -2,35 +2,51 @@ package {{.Name}} import ( + "log" + "os" "testing" "github.com/thrasher-corp/gocryptotrader/config" ) -// Please supply your own keys here for due diligence testing +// Please supply your own keys here to do authenticated endpoint testing const ( - testAPIKey = "" - testAPISecret = "" + apiKey = "" + apiSecret = "" + canManipulateRealOrders = false ) var {{.Variable}} {{.CapitalName}} -func TestSetDefaults(t *testing.T) { +func TestMain(m *testing.M) { {{.Variable}}.SetDefaults() -} - -func TestSetup(t *testing.T) { cfg := config.GetConfig() - cfg.LoadConfig("../../testdata/configtest.json") - {{.Name}}Config, err := cfg.GetExchangeConfig("{{.CapitalName}}") + err := cfg.LoadConfig("../../testdata/configtest.json", true) + if err != nil { + log.Fatal(err) + } + + exchCfg, err := cfg.GetExchangeConfig("{{.CapitalName}}") if err != nil { - t.Error("{{.CapitalName}} Setup() init error") + log.Fatal(err) } - {{.Name}}Config.API.AuthenticatedSupport = true - {{.Name}}Config.API.Credentials.Key = testAPIKey - {{.Name}}Config.API.Credentials.Secret = testAPISecret + exchCfg.API.AuthenticatedSupport = true + {{ if .WS }} exchCfg.API.AuthenticatedWebsocketSupport = true {{ end }} + exchCfg.API.Credentials.Key = apiKey + exchCfg.API.Credentials.Secret = apiSecret - {{.Variable}}.Setup({{.Name}}Config) + err = {{.Variable}}.Setup(exchCfg) + if err != nil { + log.Fatal(err) + } + + os.Exit(m.Run()) } + +func areTestAPIKeysSet() bool { + return {{.Variable}}.ValidateAPICredentials() +} + +// Implement tests for API endpoints below {{end}} diff --git a/cmd/exchange_template/wrapper_file.tmpl b/cmd/exchange_template/wrapper_file.tmpl index fd86723b2ea..0ed4873fe24 100644 --- a/cmd/exchange_template/wrapper_file.tmpl +++ b/cmd/exchange_template/wrapper_file.tmpl @@ -3,15 +3,150 @@ package {{.Name}} import ( "sync" + "time" "github.com/thrasher-corp/gocryptotrader/common" - "github.com/thrasher-corp/gocryptotrader/currency/pair" - "github.com/thrasher-corp/gocryptotrader/exchanges" + "github.com/thrasher-corp/gocryptotrader/config" + "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/protocol" + "github.com/thrasher-corp/gocryptotrader/exchanges/request" "github.com/thrasher-corp/gocryptotrader/exchanges/ticker" + "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler" log "github.com/thrasher-corp/gocryptotrader/logger" ) +// GetDefaultConfig returns a default exchange config +func ({{.Variable}} *{{.CapitalName}}) GetDefaultConfig() (*config.ExchangeConfig, error) { + {{.Variable}}.SetDefaults() + exchCfg := new(config.ExchangeConfig) + exchCfg.Name = {{.Variable}}.Name + exchCfg.HTTPTimeout = exchange.DefaultHTTPTimeout + exchCfg.BaseCurrencies = {{.Variable}}.BaseCurrencies + + err := {{.Variable}}.SetupDefaults(exchCfg) + if err != nil { + return nil, err + } + + if {{.Variable}}.Features.Supports.RESTCapabilities.AutoPairUpdates { + err = {{.Variable}}.UpdateTradablePairs(true) + if err != nil { + return nil, err + } + } + return exchCfg, nil +} + +// SetDefaults sets the basic defaults for {{.CapitalName}} +func ({{.Variable}} *{{.CapitalName}}) SetDefaults() { + {{.Variable}}.Name = "{{.CapitalName}}" + {{.Variable}}.Enabled = true + {{.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: "-", + }, + } + // Fill out the capabilities/features that the exchange supports + {{.Variable}}.Features = exchange.Features{ + Supports: exchange.FeaturesSupported{ + {{ if .REST }} REST: true, {{ end }} + {{ if .WS }} Websocket: true, {{ end }} + RESTCapabilities: protocol.Features{ + TickerFetching: true, + OrderbookFetching: true, + }, + WebsocketCapabilities: protocol.Features{ + TickerFetching: true, + OrderbookFetching: true, + }, + WithdrawPermissions: exchange.AutoWithdrawCrypto | + exchange.AutoWithdrawFiat, + }, + Enabled: exchange.FeaturesEnabled{ + AutoPairUpdates: true, + }, + } + {{.Variable}}.Requester = request.New({{.Variable}}.Name, + request.NewRateLimit(time.Second, 0), + request.NewRateLimit(time.Second, 0), + common.NewHTTPClientWithTimeout(exchange.DefaultHTTPTimeout)) + {{.Variable}}.API.Endpoints.URLDefault = {{.Name}}APIURL + {{.Variable}}.API.Endpoints.URL = {{.Variable}}.API.Endpoints.URLDefault + {{.Variable}}.Websocket = wshandler.New() + {{.Variable}}.WebsocketResponseMaxLimit = exchange.DefaultWebsocketResponseMaxLimit + {{.Variable}}.WebsocketResponseCheckTimeout = exchange.DefaultWebsocketResponseCheckTimeout + {{.Variable}}.WebsocketOrderbookBufferLimit = exchange.DefaultWebsocketOrderbookBufferLimit +} + +// Setup takes in the supplied exchange configuration details and sets params +func ({{.Variable}} *{{.CapitalName}}) Setup(exch *config.ExchangeConfig) error { + if !exch.Enabled { + {{.Variable}}.SetEnabled(false) + return nil + } + + err := {{.Variable}}.SetupDefaults(exch) + if err != nil { + return err + } + + // If websocket is supported, please fill out the following + /* + err = {{.Variable}}.Websocket.Setup( + &wshandler.WebsocketSetup{ + Enabled: exch.Features.Enabled.Websocket, + Verbose: exch.Verbose, + AuthenticatedWebsocketAPISupport: exch.API.AuthenticatedWebsocketSupport, + WebsocketTimeout: exch.WebsocketTrafficTimeout, + DefaultURL: {{.Name}}WSURL, + ExchangeName: exch.Name, + RunningURL: exch.API.Endpoints.WebsocketURL, + Connector: {{.Variable}}.WsConnect, + Subscriber: {{.Variable}}.Subscribe, + UnSubscriber: {{.Variable}}.Unsubscribe, + Features: &{{.Variable}}.Features.Supports.WebsocketCapabilities, + }) + if err != nil { + return err + } + + {{.Variable}}.WebsocketConn = &wshandler.WebsocketConnection{ + ExchangeName: {{.Variable}}.Name, + URL: {{.Variable}}.Websocket.GetWebsocketURL(), + ProxyURL: {{.Variable}}.Websocket.GetProxyAddress(), + Verbose: {{.Variable}}.Verbose, + ResponseCheckTimeout: exch.WebsocketResponseCheckTimeout, + ResponseMaxLimit: exch.WebsocketResponseMaxLimit, + } + + // NOTE: PLEASE ENSURE YOU SET THE ORDERBOOK BUFFER SETTINGS CORRECTLY + {{.Variable}}.Websocket.Orderbook.Setup( + exch.WebsocketOrderbookBufferLimit, + true, + true, + false, + false, + exch.Name) + */ + return nil +} + // Start starts the {{.CapitalName}} go routine func ({{.Variable}} *{{.CapitalName}}) Start(wg *sync.WaitGroup) { wg.Add(1) @@ -24,38 +159,68 @@ func ({{.Variable}} *{{.CapitalName}}) Start(wg *sync.WaitGroup) { // Run implements the {{.CapitalName}} wrapper func ({{.Variable}} *{{.CapitalName}}) Run() { if {{.Variable}}.Verbose { -{{if .WS}} log.Debugf(log.ExchangeSys, "%s Websocket: %s. (url: %s).\n", {{.Variable}}.Name, common.IsEnabled({{.Variable}}.Websocket.IsEnabled()), {{.Variable}}.Websocket.GetWebsocketURL()) {{end}} - log.Debugf(log.ExchangeSys, "%s polling delay: %ds.\n", {{.Variable}}.Name, {{.Variable}}.RESTPollingDelay) - log.Debugf(log.ExchangeSys, "%s %d currencies enabled: %s.\n", {{.Variable}}.Name, len({{.Variable}}.EnabledPairs), {{.Variable}}.EnabledPairs) + {{ if .WS }} log.Debugf(log.ExchangeSys, + "%s Websocket: %s.", + {{.Variable}}.Name, + common.IsEnabled({{.Variable}}.Websocket.IsEnabled())) {{ end }} + {{.Variable}}.PrintEnabledPairs() + } + + if !{{.Variable}}.GetEnabledFeatures().AutoPairUpdates { + return + } + + err := {{.Variable}}.UpdateTradablePairs(false) + if err != nil { + log.Errorf(log.ExchangeSys, + "%s failed to update tradable pairs. Err: %s", + {{.Variable}}.Name, + err) } } +// FetchTradablePairs returns a list of the exchanges tradable pairs +func ({{.Variable}} *{{.CapitalName}}) FetchTradablePairs(asset asset.Item) ([]string, error) { + // Implement fetching the exchange available pairs if supported + return nil, nil +} + +// UpdateTradablePairs updates the exchanges available pairs and stores +// them in the exchanges config +func ({{.Variable}} *{{.CapitalName}}) UpdateTradablePairs(forceUpdate bool) error { + pairs, err := {{.Variable}}.FetchTradablePairs(asset.Spot) + if err != nil { + return err + } + return {{.Variable}}.UpdatePairs(currency.NewPairsFromStrings(pairs), + asset.Spot, false, forceUpdate) +} + + // UpdateTicker updates and returns the ticker for a currency pair func ({{.Variable}} *{{.CapitalName}}) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Price, error) { + // NOTE: EXAMPLE FOR GETTING TICKER PRICE + /* var tickerPrice ticker.Price - // NOTE EXAMPLE FOR GETTING TICKER PRICE - //tick, err := {{.Variable}}.GetTickers() - //if err != nil { - // return tickerPrice, err - //} - - //for _, x := range {{.Variable}}.GetEnabledPairs(assetType) { - //curr := exchange.FormatExchangeCurrency({{.Variable}}.Name, x) - //for y := range tick { - // if tick[y].Symbol == curr.String() { - // tickerPrice.Pair = x - // tickerPrice.Ask = tick[y].AskPrice - // tickerPrice.Bid = tick[y].BidPrice - // tickerPrice.High = tick[y].HighPrice - // tickerPrice.Last = tick[y].LastPrice - // tickerPrice.Low = tick[y].LowPrice - // tickerPrice.Volume = tick[y].Volume - // ticker.ProcessTicker({{.Variable}}.Name, x, &tickerPrice, assetType) - // } - // } - //} - //return ticker.GetTicker({{.Variable}}.Name, p, assetType) - return tickerPrice, nil // NOTE DO NOT USE AS RETURN + tick, err := {{.Variable}}.GetTicker(p.String()) + if err != nil { + return tickerPrice, 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({{.Variable}}.Name, &tickerPrice, assetType) + if err != nil { + return tickerPrice, err + } + */ + return ticker.GetTicker({{.Variable}}.Name, p, assetType) } // FetchTicker returns the ticker for a currency pair @@ -79,23 +244,39 @@ func ({{.Variable}} *{{.CapitalName}}) FetchOrderbook(currency currency.Pair, as // UpdateOrderbook updates and returns the orderbook for a currency pair func ({{.Variable}} *{{.CapitalName}}) UpdateOrderbook(p currency.Pair, assetType asset.Item) (orderbook.Base, error) { var orderBook orderbook.Base - //NOTE UPDATE ORDERBOOK EXAMPLE - //orderbookNew, err := {{.Variable}}.GetOrderBook(exchange.FormatExchangeCurrency({{.Variable}}.Name, p).String(), 1000) - //if err != nil { - // return orderBook, err - //} + // NOTE: UPDATE ORDERBOOK EXAMPLE + /* + orderbookNew, err := {{.Variable}}.GetOrderBook(exchange.FormatExchangeCurrency({{.Variable}}.Name, p).String(), 1000) + if err != nil { + return orderBook, err + } + + for x := range orderbookNew.Bids { + orderBook.Bids = append(orderBook.Bids, orderbook.Item{ + Amount: orderbookNew.Bids[x].Quantity, + Price: orderbookNew.Bids[x].Price, + }) + } + + for x := range orderbookNew.Asks { + orderBook.Asks = append(orderBook.Asks, orderbook.Item{ + Amount: orderBook.Asks[x].Quantity, + Price: orderBook.Asks[x].Price, + }) + } + */ - //for _, bids := range orderbookNew.Bids { - // orderBook.Bids = append(orderBook.Bids, orderbook.Item{Amount: bids.Quantity, Price: bids.Price}) - //} + + orderBook.Pair = p + orderBook.ExchangeName = {{.Variable}}.Name + orderBook.AssetType = assetType - //for _, asks := range orderbookNew.Asks { - // orderBook.Asks = append(orderBook.Asks, orderbook.Item{Amount: asks.Quantity, Price: asks.Price}) - //} + err := orderBook.Process() + if err != nil { + return orderBook, err + } - //orderbook.ProcessOrderbook(b.Name, p, orderBook, assetType) - //return orderbook.Get({{.Variable}}.Name, p, assetType) - return orderBook, nil // NOTE DO NOT USE AS RETURN + return orderbook.Get({{.Variable}}.Name, p, assetType) } // GetAccountInfo retrieves balances for all enabled currencies for the @@ -116,8 +297,12 @@ func ({{.Variable}} *{{.CapitalName}}) GetExchangeHistory(p currency.Pair, asset } // SubmitOrder submits a new order -func ({{.Variable}} *{{.CapitalName}}) SubmitOrder(p currency.Pair, side order.Side, orderType order.Type, amount, price float64, clientID string) (order.SubmitResponse, error) { - return order.SubmitResponse{}, common.ErrNotYetImplemented +func ({{.Variable}} *{{.CapitalName}}) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) { + var submitOrderResponse order.SubmitResponse + if err := s.Validate(); err != nil { + return submitOrderResponse, err + } + return submitOrderResponse, common.ErrNotYetImplemented } // ModifyOrder will allow of changing orderbook placement and limit to @@ -142,30 +327,30 @@ func ({{.Variable}} *{{.CapitalName}}) GetOrderInfo(orderID string) (order.Detai } // GetDepositAddress returns a deposit address for a specified currency -func ({{.Variable}} *{{.CapitalName}}) GetDepositAddress(cryptocurrency pair.CurrencyItem, accountID string) (string, error) { +func ({{.Variable}} *{{.CapitalName}}) GetDepositAddress(cryptocurrency currency.Code, accountID string) (string, error) { return "", common.ErrNotYetImplemented } // WithdrawCryptocurrencyFunds returns a withdrawal ID when a withdrawal is // submitted -func ({{.Variable}} *{{.CapitalName}}) WithdrawCryptocurrencyFunds(withdrawRequest *exchange.WithdrawRequest) (string, error) { +func ({{.Variable}} *{{.CapitalName}}) WithdrawCryptocurrencyFunds(withdrawRequest *exchange.CryptoWithdrawRequest) (string, error) { return "", common.ErrNotYetImplemented } // WithdrawFiatFunds returns a withdrawal ID when a withdrawal is // submitted -func ({{.Variable}} *{{.CapitalName}}) WithdrawFiatFunds(withdrawRequest *exchange.WithdrawRequest) (string, error) { +func ({{.Variable}} *{{.CapitalName}}) WithdrawFiatFunds(withdrawRequest *exchange.FiatWithdrawRequest) (string, error) { return "", common.ErrNotYetImplemented } // WithdrawFiatFundsToInternationalBank returns a withdrawal ID when a withdrawal is // submitted -func ({{.Variable}} *{{.CapitalName}}) WithdrawFiatFundsToInternationalBank(withdrawRequest *exchange.WithdrawRequest) (string, error) { +func ({{.Variable}} *{{.CapitalName}}) WithdrawFiatFundsToInternationalBank(withdrawRequest *exchange.FiatWithdrawRequest) (string, error) { return "", common.ErrNotYetImplemented } // GetWebsocket returns a pointer to the exchange websocket -func ({{.Variable}} *{{.CapitalName}}) GetWebsocket() (*exchange.Websocket, error) { +func ({{.Variable}} *{{.CapitalName}}) GetWebsocket() (*wshandler.Websocket, error) { return nil, common.ErrNotYetImplemented } @@ -187,20 +372,20 @@ func ({{.Variable}} *{{.CapitalName}}) GetFeeByType(feeBuilder *exchange.FeeBuil // SubscribeToWebsocketChannels appends to ChannelsToSubscribe // which lets websocket.manageSubscriptions handle subscribing -func ({{.Variable}} *{{.CapitalName}}) SubscribeToWebsocketChannels(channels []monitor.WebsocketChannelSubscription) error { +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 []monitor.WebsocketChannelSubscription) error { - {{.Variable}}.Websocket.UnubscribeToChannels(channels) +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() ([]monitor.WebsocketChannelSubscription, error) { +func ({{.Variable}} *{{.CapitalName}}) GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) { return nil, common.ErrNotYetImplemented } diff --git a/cmd/exchange_wrapper_coverage/main.go b/cmd/exchange_wrapper_coverage/main.go index d37808b5a0f..40dba073d36 100644 --- a/cmd/exchange_wrapper_coverage/main.go +++ b/cmd/exchange_wrapper_coverage/main.go @@ -2,7 +2,9 @@ package main import ( "log" + "math/rand" "sync" + "time" "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/currency" @@ -70,6 +72,12 @@ func main() { func testWrappers(e exchange.IBotExchange) []string { p := currency.NewPair(currency.BTC, currency.USD) assetType := asset.Spot + if !e.SupportsAsset(assetType) { + assets := e.GetAssetTypes() + rand.Seed(time.Now().Unix()) + assetType = assets[rand.Intn(len(assets))] + } + var funcs []string _, err := e.FetchTicker(p, assetType) diff --git a/cmd/exchange_wrapper_issues/wrapperconfig.json b/cmd/exchange_wrapper_issues/wrapperconfig.json index ad94b188a1d..3d54a318a89 100644 --- a/cmd/exchange_wrapper_issues/wrapperconfig.json +++ b/cmd/exchange_wrapper_issues/wrapperconfig.json @@ -91,6 +91,11 @@ "clientID": "ClientID", "otpSecret": "-" }, + "coinbene": { + "key": "Key", + "secret": "Secret", + "otpSecret": "-" + }, "coinut": { "key": "Key", "clientID": "ClientID", @@ -136,7 +141,11 @@ "secret": "Secret", "otpSecret": "-" }, - "lbank": {}, + "lbank": { + "key": "Key", + "secret": "Secret", + "otpSecret": "-" + }, "localbitcoins": { "key": "Key", "secret": "Secret", diff --git a/communications/slack/slack_test.go b/communications/slack/slack_test.go index 85e1d6e6280..4996d2b17b6 100644 --- a/communications/slack/slack_test.go +++ b/communications/slack/slack_test.go @@ -15,28 +15,9 @@ const ( var s Slack type group struct { - ID string `json:"id"` - Name string `json:"name"` - IsGroup bool `json:"is_group"` - Created int64 `json:"created"` - Creator string `json:"creator"` - IsArchived bool `json:"is_archived"` - NameNormalised string `json:"name_normalised"` - IsMPIM bool `json:"is_mpim"` - HasPins bool `json:"has_pins"` - IsOpen bool `json:"is_open"` - LastRead string `json:"last_read"` - Members []string `json:"members"` - Topic struct { - Value string `json:"value"` - Creator string `json:"creator"` - LastSet int64 `json:"last_set"` - } `json:"topic"` - Purpose struct { - Value string `json:"value"` - Creator string `json:"creator"` - LastSet int64 `json:"last_set"` - } `json:"purpose"` + ID string `json:"id"` + Name string `json:"name"` + Members []string `json:"members"` } func TestSetup(t *testing.T) { @@ -76,16 +57,7 @@ func TestBuildURL(t *testing.T) { func TestGetChannelsString(t *testing.T) { s.Details.Channels = append(s.Details.Channels, struct { - Created int `json:"created"` - Creator string `json:"creator"` - HasPins bool `json:"has_pins"` ID string `json:"id"` - IsArchived bool `json:"is_archived"` - IsChannel bool `json:"is_channel"` - IsGeneral bool `json:"is_general"` - IsMember bool `json:"is_member"` - IsOrgShared bool `json:"is_org_shared"` - IsShared bool `json:"is_shared"` Name string `json:"name"` NameNormalized string `json:"name_normalized"` PreviousNames []string `json:"previous_names"` @@ -112,28 +84,9 @@ func TestGetUsernameByID(t *testing.T) { } s.Details.Users = append(s.Details.Users, struct { - Deleted bool `json:"deleted"` - ID string `json:"id"` - IsBot bool `json:"is_bot"` - Name string `json:"name"` - Presence string `json:"presence"` - Profile struct { - AvatarHash string `json:"avatar_hash"` - Email string `json:"email"` - Fields interface{} `json:"fields"` - FirstName string `json:"first_name"` - Image192 string `json:"image_192"` - Image24 string `json:"image_24"` - Image32 string `json:"image_32"` - Image48 string `json:"image_48"` - Image512 string `json:"image_512"` - Image72 string `json:"image_72"` - LastName string `json:"last_name"` - RealName string `json:"real_name"` - RealNameNormalized string `json:"real_name_normalized"` - } `json:"profile"` - TeamID string `json:"team_id"` - Updated int `json:"updated"` + ID string `json:"id"` + Name string `json:"name"` + TeamID string `json:"team_id"` }{ ID: "1337", Name: "cranktakular", @@ -186,16 +139,7 @@ func TestGetChannelIDByName(t *testing.T) { } s.Details.Channels = append(s.Details.Channels, struct { - Created int `json:"created"` - Creator string `json:"creator"` - HasPins bool `json:"has_pins"` ID string `json:"id"` - IsArchived bool `json:"is_archived"` - IsChannel bool `json:"is_channel"` - IsGeneral bool `json:"is_general"` - IsMember bool `json:"is_member"` - IsOrgShared bool `json:"is_org_shared"` - IsShared bool `json:"is_shared"` Name string `json:"name"` NameNormalized string `json:"name_normalized"` PreviousNames []string `json:"previous_names"` diff --git a/communications/slack/slack_types.go b/communications/slack/slack_types.go index 07358656b55..e738aab2646 100644 --- a/communications/slack/slack_types.go +++ b/communications/slack/slack_types.go @@ -36,406 +36,32 @@ type PresenceChange struct { // Response is a generalised response type type Response struct { - Bots []struct { - AppID string `json:"app_id"` - Deleted bool `json:"deleted"` - Icons struct { - Image36 string `json:"image_36"` - Image48 string `json:"image_48"` - Image72 string `json:"image_72"` - } `json:"icons"` - ID string `json:"id"` - Name string `json:"name"` - Updated int `json:"updated"` - } `json:"bots"` - CacheTs int `json:"cache_ts"` - CacheTsVersion string `json:"cache_ts_version"` - CacheVersion string `json:"cache_version"` - CanManageSharedChannels bool `json:"can_manage_shared_channels"` - Channels []struct { - Created int `json:"created"` - Creator string `json:"creator"` - HasPins bool `json:"has_pins"` + Channels []struct { ID string `json:"id"` - IsArchived bool `json:"is_archived"` - IsChannel bool `json:"is_channel"` - IsGeneral bool `json:"is_general"` - IsMember bool `json:"is_member"` - IsOrgShared bool `json:"is_org_shared"` - IsShared bool `json:"is_shared"` Name string `json:"name"` NameNormalized string `json:"name_normalized"` PreviousNames []string `json:"previous_names"` } `json:"channels"` - Dnd struct { - DndEnabled bool `json:"dnd_enabled"` - NextDndEndTs int `json:"next_dnd_end_ts"` - NextDndStartTs int `json:"next_dnd_start_ts"` - SnoozeEnabled bool `json:"snooze_enabled"` - } `json:"dnd"` Groups []struct { - ID string `json:"id"` - Name string `json:"name"` - IsGroup bool `json:"is_group"` - Created int64 `json:"created"` - Creator string `json:"creator"` - IsArchived bool `json:"is_archived"` - NameNormalised string `json:"name_normalised"` - IsMPIM bool `json:"is_mpim"` - HasPins bool `json:"has_pins"` - IsOpen bool `json:"is_open"` - LastRead string `json:"last_read"` - Members []string `json:"members"` - Topic struct { - Value string `json:"value"` - Creator string `json:"creator"` - LastSet int64 `json:"last_set"` - } `json:"topic"` - Purpose struct { - Value string `json:"value"` - Creator string `json:"creator"` - LastSet int64 `json:"last_set"` - } `json:"purpose"` + ID string `json:"id"` + Name string `json:"name"` + Members []string `json:"members"` } `json:"groups"` - Ims []struct { - Created int `json:"created"` - HasPins bool `json:"has_pins"` - ID string `json:"id"` - IsIm bool `json:"is_im"` - IsOpen bool `json:"is_open"` - IsOrgShared bool `json:"is_org_shared"` - LastRead string `json:"last_read"` - User string `json:"user"` - } `json:"ims"` - LatestEventTs string `json:"latest_event_ts"` - Ok bool `json:"ok"` - Error string `json:"error"` - ReadOnlyChannels []interface{} `json:"read_only_channels"` - Self struct { - Created int `json:"created"` - ID string `json:"id"` - ManualPresence string `json:"manual_presence"` - Name string `json:"name"` - Prefs struct { - A11yAnimations bool `json:"a11y_animations"` - A11yFontSize string `json:"a11y_font_size"` - AllChannelsLoud bool `json:"all_channels_loud"` - AllNotificationsPrefs string `json:"all_notifications_prefs"` - AllUnreadsSortOrder string `json:"all_unreads_sort_order"` - AllowCallsToSetCurrentStatus bool `json:"allow_calls_to_set_current_status"` - AnalyticsUpsellCoachmarkSeen bool `json:"analytics_upsell_coachmark_seen"` - ArrowHistory bool `json:"arrow_history"` - AtChannelSuppressedChannels string `json:"at_channel_suppressed_channels"` - BoxEnabled bool `json:"box_enabled"` - ChannelSort string `json:"channel_sort"` - ClientLogsPri string `json:"client_logs_pri"` - ColorNamesInList bool `json:"color_names_in_list"` - ConfirmClearAllUnreads bool `json:"confirm_clear_all_unreads"` - ConfirmShCallStart bool `json:"confirm_sh_call_start"` - ConfirmUserMarkedAway bool `json:"confirm_user_marked_away"` - ConvertEmoticons bool `json:"convert_emoticons"` - DisplayDisplayNames bool `json:"display_display_names"` - DisplayRealNamesOverride int `json:"display_real_names_override"` - DndEnabled bool `json:"dnd_enabled"` - DndEndHour string `json:"dnd_end_hour"` - DndStartHour string `json:"dnd_start_hour"` - DropboxEnabled bool `json:"dropbox_enabled"` - EmailAlerts string `json:"email_alerts"` - EmailAlertsSleepUntil int `json:"email_alerts_sleep_until"` - EmailMisc bool `json:"email_misc"` - EmailWeekly bool `json:"email_weekly"` - EmojiAutocompleteBig bool `json:"emoji_autocomplete_big"` - EmojiMode string `json:"emoji_mode"` - EmojiUse string `json:"emoji_use"` - EnableReactEmojiPicker bool `json:"enable_react_emoji_picker"` - EnableUnreadView bool `json:"enable_unread_view"` - EnhancedDebugging bool `json:"enhanced_debugging"` - EnterIsSpecialInTbt bool `json:"enter_is_special_in_tbt"` - EnterpriseMdmCustomMsg string `json:"enterprise_mdm_custom_msg"` - EnterpriseMigrationSeen bool `json:"enterprise_migration_seen"` - ExpandInlineImgs bool `json:"expand_inline_imgs"` - ExpandInternalInlineImgs bool `json:"expand_internal_inline_imgs"` - ExpandNonMediaAttachments bool `json:"expand_non_media_attachments"` - ExpandSnippets bool `json:"expand_snippets"` - FKeySearch bool `json:"f_key_search"` - FlannelServerPool string `json:"flannel_server_pool"` - FrecencyEntJumper string `json:"frecency_ent_jumper"` - FrecencyJumper string `json:"frecency_jumper"` - FullTextExtracts bool `json:"full_text_extracts"` - FullerTimestamps bool `json:"fuller_timestamps"` - GdriveAuthed bool `json:"gdrive_authed"` - GdriveEnabled bool `json:"gdrive_enabled"` - GraphicEmoticons bool `json:"graphic_emoticons"` - GrowlsEnabled bool `json:"growls_enabled"` - GrowthMsgLimitApproachingCtaCount int `json:"growth_msg_limit_approaching_cta_count"` - GrowthMsgLimitApproachingCtaTs int `json:"growth_msg_limit_approaching_cta_ts"` - GrowthMsgLimitLongReachedCtaCount int `json:"growth_msg_limit_long_reached_cta_count"` - GrowthMsgLimitLongReachedCtaLastTs int `json:"growth_msg_limit_long_reached_cta_last_ts"` - GrowthMsgLimitReachedCtaCount int `json:"growth_msg_limit_reached_cta_count"` - GrowthMsgLimitReachedCtaLastTs int `json:"growth_msg_limit_reached_cta_last_ts"` - HasCreatedChannel bool `json:"has_created_channel"` - HasInvited bool `json:"has_invited"` - HasSearched bool `json:"has_searched"` - HasUploaded bool `json:"has_uploaded"` - HideHexSwatch bool `json:"hide_hex_swatch"` - HideUserGroupInfoPane bool `json:"hide_user_group_info_pane"` - HighlightWords string `json:"highlight_words"` - IntroToAppsMessageSeen bool `json:"intro_to_apps_message_seen"` - Jumbomoji bool `json:"jumbomoji"` - KKeyOmnibox bool `json:"k_key_omnibox"` - KKeyOmniboxAutoHideCount int `json:"k_key_omnibox_auto_hide_count"` - LastSeenAtChannelWarning int `json:"last_seen_at_channel_warning"` - LastSnippetType string `json:"last_snippet_type"` - LastTosAcknowledged interface{} `json:"last_tos_acknowledged"` - LoadLato2 bool `json:"load_lato_2"` - Locale string `json:"locale"` - LoudChannels string `json:"loud_channels"` - LoudChannelsSet string `json:"loud_channels_set"` - LsDisabled bool `json:"ls_disabled"` - MacSsbBounce string `json:"mac_ssb_bounce"` - MacSsbBullet bool `json:"mac_ssb_bullet"` - MarkMsgsReadImmediately bool `json:"mark_msgs_read_immediately"` - MeasureCSSUsage bool `json:"measure_css_usage"` - MentionsExcludeAtChannels bool `json:"mentions_exclude_at_channels"` - MentionsExcludeAtUserGroups bool `json:"mentions_exclude_at_user_groups"` - MessagesTheme string `json:"messages_theme"` - MsgPreview bool `json:"msg_preview"` - MsgPreviewPersistent bool `json:"msg_preview_persistent"` - MuteSounds bool `json:"mute_sounds"` - MutedChannels string `json:"muted_channels"` - NeverChannels string `json:"never_channels"` - NewMsgSnd string `json:"new_msg_snd"` - NewxpSeenLastMessage int `json:"newxp_seen_last_message"` - NoCreatedOverlays bool `json:"no_created_overlays"` - NoInvitesWidgetInSidebar bool `json:"no_invites_widget_in_sidebar"` - NoJoinedOverlays bool `json:"no_joined_overlays"` - NoMacelectronBanner bool `json:"no_macelectron_banner"` - NoMacssb1Banner bool `json:"no_macssb1_banner"` - NoMacssb2Banner bool `json:"no_macssb2_banner"` - NoOmniboxInChannels bool `json:"no_omnibox_in_channels"` - NoTextInNotifications bool `json:"no_text_in_notifications"` - NoWinssb1Banner bool `json:"no_winssb1_banner"` - ObeyInlineImgLimit bool `json:"obey_inline_img_limit"` - OnboardingCancelled bool `json:"onboarding_cancelled"` - OnboardingSlackbotConversationStep int `json:"onboarding_slackbot_conversation_step"` - OverloadedMessageEnabled bool `json:"overloaded_message_enabled"` - PagekeysHandled bool `json:"pagekeys_handled"` - PostsFormattingGuide bool `json:"posts_formatting_guide"` - PreferredSkinTone string `json:"preferred_skin_tone"` - PrevNextBtn bool `json:"prev_next_btn"` - PrivacyPolicySeen bool `json:"privacy_policy_seen"` - PromptedForEmailDisabling bool `json:"prompted_for_email_disabling"` - PushAtChannelSuppressedChannels string `json:"push_at_channel_suppressed_channels"` - PushDmAlert bool `json:"push_dm_alert"` - PushEverything bool `json:"push_everything"` - PushIdleWait int `json:"push_idle_wait"` - PushLoudChannels string `json:"push_loud_channels"` - PushLoudChannelsSet string `json:"push_loud_channels_set"` - PushMentionAlert bool `json:"push_mention_alert"` - PushMentionChannels string `json:"push_mention_channels"` - PushShowPreview bool `json:"push_show_preview"` - PushSound string `json:"push_sound"` - QuestsEnabled bool `json:"quests_enabled"` - RequireAt bool `json:"require_at"` - SearchExcludeBots bool `json:"search_exclude_bots"` - SearchExcludeChannels string `json:"search_exclude_channels"` - SearchOnlyCurrentTeam bool `json:"search_only_current_team"` - SearchOnlyMyChannels bool `json:"search_only_my_channels"` - SearchSort string `json:"search_sort"` - SeenAppSpaceCoachmark bool `json:"seen_app_space_coachmark"` - SeenAppSpaceTutorial bool `json:"seen_app_space_tutorial"` - SeenCallsSsMainCoachmark bool `json:"seen_calls_ss_main_coachmark"` - SeenCallsSsWindowCoachmark bool `json:"seen_calls_ss_window_coachmark"` - SeenCallsVideoBetaCoachmark bool `json:"seen_calls_video_beta_coachmark"` - SeenCallsVideoGaCoachmark bool `json:"seen_calls_video_ga_coachmark"` - SeenCustomStatusBadge bool `json:"seen_custom_status_badge"` - SeenCustomStatusCallout bool `json:"seen_custom_status_callout"` - SeenDomainInviteReminder bool `json:"seen_domain_invite_reminder"` - SeenGdriveCoachmark bool `json:"seen_gdrive_coachmark"` - SeenGuestAdminSlackbotAnnouncement bool `json:"seen_guest_admin_slackbot_announcement"` - SeenHighlightsArrowsCoachmark bool `json:"seen_highlights_arrows_coachmark"` - SeenHighlightsCoachmark bool `json:"seen_highlights_coachmark"` - SeenHighlightsWarmWelcome bool `json:"seen_highlights_warm_welcome"` - SeenIntlChannelNamesCoachmark bool `json:"seen_intl_channel_names_coachmark"` - SeenMemberInviteReminder bool `json:"seen_member_invite_reminder"` - SeenOnboardingChannels bool `json:"seen_onboarding_channels"` - SeenOnboardingDirectMessages bool `json:"seen_onboarding_direct_messages"` - SeenOnboardingInvites bool `json:"seen_onboarding_invites"` - SeenOnboardingPrivateGroups bool `json:"seen_onboarding_private_groups"` - SeenOnboardingRecentMentions bool `json:"seen_onboarding_recent_mentions"` - SeenOnboardingSearch bool `json:"seen_onboarding_search"` - SeenOnboardingSlackbotConversation bool `json:"seen_onboarding_slackbot_conversation"` - SeenOnboardingStarredItems bool `json:"seen_onboarding_starred_items"` - SeenOnboardingStart bool `json:"seen_onboarding_start"` - SeenRepliesCoachmark bool `json:"seen_replies_coachmark"` - SeenSingleEmojiMsg bool `json:"seen_single_emoji_msg"` - SeenSsbPrompt bool `json:"seen_ssb_prompt"` - SeenThreadsNotificationBanner bool `json:"seen_threads_notification_banner"` - SeenUnreadViewCoachmark bool `json:"seen_unread_view_coachmark"` - SeenWelcome2 bool `json:"seen_welcome_2"` - SeparatePrivateChannels bool `json:"separate_private_channels"` - SeparateSharedChannels bool `json:"separate_shared_channels"` - ShowAllSkinTones bool `json:"show_all_skin_tones"` - ShowJumperScores bool `json:"show_jumper_scores"` - ShowMemoryInstrument bool `json:"show_memory_instrument"` - ShowTyping bool `json:"show_typing"` - SidebarBehavior string `json:"sidebar_behavior"` - SidebarTheme string `json:"sidebar_theme"` - SidebarThemeCustomValues string `json:"sidebar_theme_custom_values"` - SnippetEditorWrapLongLines bool `json:"snippet_editor_wrap_long_lines"` - SpacesNewXpBannerDismissed bool `json:"spaces_new_xp_banner_dismissed"` - SsEmojis bool `json:"ss_emojis"` - SsbSpaceWindow string `json:"ssb_space_window"` - StartScrollAtOldest bool `json:"start_scroll_at_oldest"` - TabUIReturnSelects bool `json:"tab_ui_return_selects"` - ThreadsEverything bool `json:"threads_everything"` - Time24 bool `json:"time24"` - TwoFactorAuthEnabled bool `json:"two_factor_auth_enabled"` - TwoFactorBackupType interface{} `json:"two_factor_backup_type"` - TwoFactorType interface{} `json:"two_factor_type"` - Tz interface{} `json:"tz"` - UseReactSidebar bool `json:"use_react_sidebar"` - UserColors string `json:"user_colors"` - WebappSpellcheck bool `json:"webapp_spellcheck"` - WelcomeMessageHidden bool `json:"welcome_message_hidden"` - WhatsNewRead int `json:"whats_new_read"` - WinssbRunFromTray bool `json:"winssb_run_from_tray"` - WinssbWindowFlashBehavior string `json:"winssb_window_flash_behavior"` - } `json:"prefs"` + Ok bool `json:"ok"` + Error string `json:"error"` + Self struct { + ID string `json:"id"` + Name string `json:"name"` } `json:"self"` - Subteams struct { - All []interface{} `json:"all"` - Self []interface{} `json:"self"` - } `json:"subteams"` Team struct { - ApproachingMsgLimit bool `json:"approaching_msg_limit"` - AvatarBaseURL string `json:"avatar_base_url"` - Domain string `json:"domain"` - EmailDomain string `json:"email_domain"` - Icon struct { - Image102 string `json:"image_102"` - Image132 string `json:"image_132"` - Image230 string `json:"image_230"` - Image34 string `json:"image_34"` - Image44 string `json:"image_44"` - Image68 string `json:"image_68"` - Image88 string `json:"image_88"` - ImageOriginal string `json:"image_original"` - } `json:"icon"` - ID string `json:"id"` - MessagesCount int `json:"messages_count"` - MsgEditWindowMins int `json:"msg_edit_window_mins"` - Name string `json:"name"` - OverIntegrationsLimit bool `json:"over_integrations_limit"` - OverStorageLimit bool `json:"over_storage_limit"` - Plan string `json:"plan"` - Prefs struct { - AllowCalls bool `json:"allow_calls"` - AllowMessageDeletion bool `json:"allow_message_deletion"` - AllowRetentionOverride bool `json:"allow_retention_override"` - AllowSharedChannelPermsOverride bool `json:"allow_shared_channel_perms_override"` - AuthMode string `json:"auth_mode"` - CallingAppName string `json:"calling_app_name"` - ChannelHandyRxns interface{} `json:"channel_handy_rxns"` - ComplianceExportStart int `json:"compliance_export_start"` - CustomStatusDefaultEmoji string `json:"custom_status_default_emoji"` - CustomStatusPresets [][]string `json:"custom_status_presets"` - DefaultChannels []string `json:"default_channels"` - DefaultRxns []string `json:"default_rxns"` - DisableFileDeleting bool `json:"disable_file_deleting"` - DisableFileEditing bool `json:"disable_file_editing"` - DisableFileUploads string `json:"disable_file_uploads"` - DisallowPublicFileUrls bool `json:"disallow_public_file_urls"` - Discoverable string `json:"discoverable"` - DisplayEmailAddresses bool `json:"display_email_addresses"` - DisplayRealNames bool `json:"display_real_names"` - DmRetentionDuration int `json:"dm_retention_duration"` - DmRetentionType int `json:"dm_retention_type"` - DndEnabled bool `json:"dnd_enabled"` - DndEndHour string `json:"dnd_end_hour"` - DndStartHour string `json:"dnd_start_hour"` - EnterpriseDefaultChannels []interface{} `json:"enterprise_default_channels"` - EnterpriseMandatoryChannels []interface{} `json:"enterprise_mandatory_channels"` - EnterpriseMdmDateEnabled int `json:"enterprise_mdm_date_enabled"` - EnterpriseMdmLevel int `json:"enterprise_mdm_level"` - EnterpriseTeamCreationRequest struct { - IsEnabled bool `json:"is_enabled"` - } `json:"enterprise_team_creation_request"` - FileRetentionDuration int `json:"file_retention_duration"` - FileRetentionType int `json:"file_retention_type"` - GdriveEnabledTeam bool `json:"gdrive_enabled_team"` - GroupRetentionDuration int `json:"group_retention_duration"` - GroupRetentionType int `json:"group_retention_type"` - HideReferers bool `json:"hide_referers"` - InvitesLimit bool `json:"invites_limit"` - InvitesOnlyAdmins bool `json:"invites_only_admins"` - LimitReachedTs int `json:"limit_reached_ts"` - Locale string `json:"locale"` - LoudChannelMentionsLimit int `json:"loud_channel_mentions_limit"` - MsgEditWindowMins int `json:"msg_edit_window_mins"` - RequireAtForMention bool `json:"require_at_for_mention"` - RetentionDuration int `json:"retention_duration"` - RetentionType int `json:"retention_type"` - ShowJoinLeave bool `json:"show_join_leave"` - TeamHandyRxns struct { - List []struct { - Name string `json:"name"` - Title string `json:"title"` - } `json:"list"` - Restrict bool `json:"restrict"` - } `json:"team_handy_rxns"` - UsesCustomizedCustomStatusPresets bool `json:"uses_customized_custom_status_presets"` - WarnBeforeAtChannel string `json:"warn_before_at_channel"` - WhoCanArchiveChannels string `json:"who_can_archive_channels"` - WhoCanAtChannel string `json:"who_can_at_channel"` - WhoCanAtEveryone string `json:"who_can_at_everyone"` - WhoCanChangeTeamProfile string `json:"who_can_change_team_profile"` - WhoCanCreateChannels string `json:"who_can_create_channels"` - WhoCanCreateDeleteUserGroups string `json:"who_can_create_delete_user_groups"` - WhoCanCreateGroups string `json:"who_can_create_groups"` - WhoCanCreateSharedChannels string `json:"who_can_create_shared_channels"` - WhoCanEditUserGroups string `json:"who_can_edit_user_groups"` - WhoCanKickChannels string `json:"who_can_kick_channels"` - WhoCanKickGroups string `json:"who_can_kick_groups"` - WhoCanManageGuests struct { - Type []string `json:"type"` - } `json:"who_can_manage_guests"` - WhoCanManageIntegrations struct { - Type []string `json:"type"` - } `json:"who_can_manage_integrations"` - WhoCanManageSharedChannels struct { - Type []string `json:"type"` - } `json:"who_can_manage_shared_channels"` - WhoCanPostGeneral string `json:"who_can_post_general"` - WhoCanPostInSharedChannels struct { - Type []string `json:"type"` - } `json:"who_can_post_in_shared_channels"` - WhoHasTeamVisibility string `json:"who_has_team_visibility"` - } `json:"prefs"` + Domain string `json:"domain"` + ID string `json:"id"` + Name string `json:"name"` } `json:"team"` URL string `json:"url"` Users []struct { - Deleted bool `json:"deleted"` - ID string `json:"id"` - IsBot bool `json:"is_bot"` - Name string `json:"name"` - Presence string `json:"presence"` - Profile struct { - AvatarHash string `json:"avatar_hash"` - Email string `json:"email"` - Fields interface{} `json:"fields"` - FirstName string `json:"first_name"` - Image192 string `json:"image_192"` - Image24 string `json:"image_24"` - Image32 string `json:"image_32"` - Image48 string `json:"image_48"` - Image512 string `json:"image_512"` - Image72 string `json:"image_72"` - LastName string `json:"last_name"` - RealName string `json:"real_name"` - RealNameNormalized string `json:"real_name_normalized"` - } `json:"profile"` - TeamID string `json:"team_id"` - Updated int `json:"updated"` + ID string `json:"id"` + Name string `json:"name"` + TeamID string `json:"team_id"` } `json:"users"` } diff --git a/config/config_test.go b/config/config_test.go index 7ae37ea84f7..c71f40c5cda 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -18,6 +18,7 @@ const ( // added or removed defaultEnabledExchanges = 28 testFakeExchangeName = "Stampbit" + testPair = "BTC-USD" ) func TestGetCurrencyConfig(t *testing.T) { @@ -668,7 +669,7 @@ func TestCheckPairConfigFormats(t *testing.T) { Index: "USD", }, Available: currency.Pairs{ - currency.NewPairDelimiter("BTC-USD", "-"), + currency.NewPairDelimiter(testPair, "-"), }, Enabled: currency.Pairs{ currency.NewPairDelimiter("BTC~USD", "~"), @@ -1327,7 +1328,7 @@ func TestCheckExchangeConfigValues(t *testing.T) { setupPairs := func(emptyAssets bool) { cfg.Exchanges[0].CurrencyPairs = nil p := currency.Pairs{ - currency.NewPairDelimiter("BTC-USD", "-"), + currency.NewPairDelimiter(testPair, "-"), } cfg.Exchanges[0].PairsLastUpdated = int64ptr(1234567) @@ -1381,12 +1382,12 @@ func TestCheckExchangeConfigValues(t *testing.T) { } pairs := cfg.Exchanges[0].CurrencyPairs.GetPairs(asset.Spot, true) - if len(pairs) == 0 || pairs.Join() != "BTC-USD" { + if len(pairs) == 0 || pairs.Join() != testPair { t.Error("pairs not set properly") } pairs = cfg.Exchanges[0].CurrencyPairs.GetPairs(asset.Spot, false) - if len(pairs) == 0 || pairs.Join() != "BTC-USD" { + if len(pairs) == 0 || pairs.Join() != testPair { t.Error("pairs not set properly") } diff --git a/docker-compose.yml b/docker-compose.yml index 3bbf02970cd..87c18d762c0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,10 +7,12 @@ services: depends_on: - daemon ports: - - "9052:80" + - "9054:80" daemon: build: . ports: - - "9051:9051" - "9050:9050" + - "9051:9051" + - "9052:9052" + - "9053:9053" diff --git a/docs/EXCHANGE_API.md b/docs/EXCHANGE_API.md index 1448fc5ceae..2af913885e2 100644 --- a/docs/EXCHANGE_API.md +++ b/docs/EXCHANGE_API.md @@ -57,14 +57,14 @@ supplied meet the requirements to make an authenticated request. b.API.Credentials.Secret = "your_secret" b.API.Credentials.ClientID = "your_clientid" - order := &exchange.OrderSubmission{ + o := &order.Submit{ Pair: currency.NewPair(currency.BTC, currency.USD), - OrderSide: exchange.SellOrderSide, - OrderType: exchange.LimitOrderType, + OrderSide: order.Sell, + OrderType: order.Limit, Price: 1000000, Amount: 0.1, } - resp, err := b.SubmitOrder(order) + resp, err := b.SubmitOrder(o) if err != nil { // Handle error } diff --git a/engine/engine.go b/engine/engine.go index f69514d28c1..0b16523c910 100644 --- a/engine/engine.go +++ b/engine/engine.go @@ -4,7 +4,9 @@ import ( "errors" "flag" "fmt" + "path/filepath" "runtime" + "strings" "sync" "time" @@ -42,13 +44,10 @@ type Engine struct { // Vars for engine var ( Bot *Engine -) -func init() { - if Bot == nil { - return - } -} + // Stores the set flags + flagSet = make(map[string]bool) +) // New starts a new engine func New() (*Engine, error) { @@ -94,6 +93,7 @@ func NewFromSettings(settings *Settings) (*Engine, error) { b.Settings.ConfigFile = filePath b.Settings.DataDir = settings.DataDir + b.Settings.CheckParamInteraction = settings.CheckParamInteraction err = utils.AdjustGoMaxProcs(settings.GoMaxProcs) if err != nil { @@ -106,6 +106,8 @@ func NewFromSettings(settings *Settings) (*Engine, error) { // ValidateSettings validates and sets all bot settings func ValidateSettings(b *Engine, s *Settings) { + flag.Visit(func(f *flag.Flag) { flagSet[f.Name] = true }) + b.Settings.Verbose = s.Verbose b.Settings.EnableDryRun = s.EnableDryRun b.Settings.EnableAllExchanges = s.EnableAllExchanges @@ -115,26 +117,25 @@ func ValidateSettings(b *Engine, s *Settings) { b.Settings.EnableDatabaseManager = s.EnableDatabaseManager b.Settings.EnableDispatcher = s.EnableDispatcher - // TO-DO: FIXME - if flag.Lookup("grpc") != nil { + if flagSet["grpc"] { b.Settings.EnableGRPC = s.EnableGRPC } else { b.Settings.EnableGRPC = b.Config.RemoteControl.GRPC.Enabled } - if flag.Lookup("grpcproxy") != nil { + if flagSet["grpcproxy"] { b.Settings.EnableGRPCProxy = s.EnableGRPCProxy } else { b.Settings.EnableGRPCProxy = b.Config.RemoteControl.GRPC.GRPCProxyEnabled } - if flag.Lookup("websocketrpc") != nil { + if flagSet["websocketrpc"] { b.Settings.EnableWebsocketRPC = s.EnableWebsocketRPC } else { b.Settings.EnableWebsocketRPC = b.Config.RemoteControl.WebsocketRPC.Enabled } - if flag.Lookup("deprecatedrpc") != nil { + if flagSet["deprecatedrpc"] { b.Settings.EnableDeprecatedRPC = s.EnableDeprecatedRPC } else { b.Settings.EnableDeprecatedRPC = b.Config.RemoteControl.DeprecatedRPC.Enabled @@ -155,9 +156,13 @@ func ValidateSettings(b *Engine, s *Settings) { b.Settings.EnableNTPClient = s.EnableNTPClient b.Settings.EnableOrderManager = s.EnableOrderManager b.Settings.EnableExchangeSyncManager = s.EnableExchangeSyncManager - b.Settings.EnableDepositAddressManager = s.EnableDepositAddressManager b.Settings.EnableTickerSyncing = s.EnableTickerSyncing b.Settings.EnableOrderbookSyncing = s.EnableOrderbookSyncing + b.Settings.EnableTradeSyncing = s.EnableTradeSyncing + b.Settings.SyncWorkers = s.SyncWorkers + b.Settings.SyncTimeout = s.SyncTimeout + b.Settings.SyncContinuously = s.SyncContinuously + b.Settings.EnableDepositAddressManager = s.EnableDepositAddressManager b.Settings.EnableExchangeAutoPairUpdates = s.EnableExchangeAutoPairUpdates b.Settings.EnableExchangeWebsocketSupport = s.EnableExchangeWebsocketSupport b.Settings.EnableExchangeRESTSupport = s.EnableExchangeRESTSupport @@ -231,14 +236,19 @@ func PrintSettings(s *Settings) { log.Debugf(log.Global, "\t Enable order manager: %v", s.EnableOrderManager) log.Debugf(log.Global, "\t Enable exchange sync manager: %v", s.EnableExchangeSyncManager) log.Debugf(log.Global, "\t Enable deposit address manager: %v\n", s.EnableDepositAddressManager) - log.Debugf(log.Global, "\t Enable ticker syncing: %v", s.EnableTickerSyncing) - log.Debugf(log.Global, "\t Enable orderbook syncing: %v", s.EnableOrderbookSyncing) log.Debugf(log.Global, "\t Enable websocket routine: %v\n", s.EnableWebsocketRoutine) log.Debugf(log.Global, "\t Enable NTP client: %v", s.EnableNTPClient) log.Debugf(log.Global, "\t Enable Database manager: %v", s.EnableDatabaseManager) log.Debugf(log.Global, "\t Enable dispatcher: %v", s.EnableDispatcher) log.Debugf(log.Global, "\t Dispatch package max worker amount: %d", s.DispatchMaxWorkerAmount) log.Debugf(log.Global, "\t Dispatch package jobs limit: %d", s.DispatchJobsLimit) + log.Debugf(log.Global, "- EXCHANGE SYNCER SETTINGS:\n") + log.Debugf(log.Global, "\t Exchange sync continuously: %v\n", s.SyncContinuously) + log.Debugf(log.Global, "\t Exchange sync workers: %v\n", s.SyncWorkers) + log.Debugf(log.Global, "\t Enable ticker syncing: %v\n", s.EnableTickerSyncing) + log.Debugf(log.Global, "\t Enable orderbook syncing: %v\n", s.EnableOrderbookSyncing) + log.Debugf(log.Global, "\t Enable trade syncing: %v\n", s.EnableTradeSyncing) + log.Debugf(log.Global, "\t Exchange sync timeout: %v\n", s.SyncTimeout) log.Debugf(log.Global, "- FOREX SETTINGS:") log.Debugf(log.Global, "\t Enable currency conveter: %v", s.EnableCurrencyConverter) log.Debugf(log.Global, "\t Enable currency layer: %v", s.EnableCurrencyLayer) @@ -297,6 +307,10 @@ func (e *Engine) Start() error { e.Uptime = time.Now() log.Debugf(log.Global, "Bot '%s' started.\n", e.Config.Name) log.Debugf(log.Global, "Using data dir: %s\n", e.Settings.DataDir) + if *e.Config.Logging.Enabled && strings.Contains(e.Config.Logging.Output, "file") { + log.Debugf(log.Global, "Using log file: %s\n", + filepath.Join(log.LogPath, e.Config.Logging.LoggerFileConfig.FileName)) + } log.Debugf(log.Global, "Using %d out of %d logical processors for runtime performance\n", runtime.GOMAXPROCS(-1), runtime.NumCPU()) @@ -387,8 +401,10 @@ func (e *Engine) Start() error { exchangeSyncCfg := CurrencyPairSyncerConfig{ SyncTicker: e.Settings.EnableTickerSyncing, SyncOrderbook: e.Settings.EnableOrderbookSyncing, - SyncContinuously: true, - NumWorkers: 15, + SyncTrades: e.Settings.EnableTradeSyncing, + SyncContinuously: e.Settings.SyncContinuously, + NumWorkers: e.Settings.SyncWorkers, + Verbose: e.Settings.Verbose, } e.ExchangeCurrencyPairManager, err = NewCurrencyPairSyncer(exchangeSyncCfg) diff --git a/engine/engine_types.go b/engine/engine_types.go index da1ba5adb72..9f0bbc955de 100644 --- a/engine/engine_types.go +++ b/engine/engine_types.go @@ -4,11 +4,12 @@ import "time" // Settings stores engine params type Settings struct { - ConfigFile string - DataDir string - MigrationDir string - LogFile string - GoMaxProcs int + ConfigFile string + DataDir string + MigrationDir string + LogFile string + GoMaxProcs int + CheckParamInteraction bool // Core Settings EnableDryRun bool @@ -23,8 +24,6 @@ type Settings struct { EnableCommsRelayer bool EnableExchangeSyncManager bool EnableDepositAddressManager bool - EnableTickerSyncing bool - EnableOrderbookSyncing bool EnableEventManager bool EnableOrderManager bool EnableConnectivityMonitor bool @@ -34,6 +33,14 @@ type Settings struct { EventManagerDelay time.Duration Verbose bool + // Exchange syncer settings + EnableTickerSyncing bool + EnableOrderbookSyncing bool + EnableTradeSyncing bool + SyncWorkers int + SyncContinuously bool + SyncTimeout time.Duration + // Forex settings EnableCurrencyConverter bool EnableCurrencyLayer bool diff --git a/engine/events.go b/engine/events.go index 15c8de5427f..bf87a4c3a05 100644 --- a/engine/events.go +++ b/engine/events.go @@ -310,7 +310,6 @@ func EventManger() { // IsValidExchange validates the exchange func IsValidExchange(exchangeName string) bool { - exchangeName = strings.ToLower(exchangeName) cfg := config.GetConfig() for x := range cfg.Exchanges { if strings.EqualFold(cfg.Exchanges[x].Name, exchangeName) && cfg.Exchanges[x].Enabled { diff --git a/engine/exchange.go b/engine/exchange.go index ce0b8f36272..1cc5141a290 100644 --- a/engine/exchange.go +++ b/engine/exchange.go @@ -46,6 +46,20 @@ var ( ErrExchangeFailedToLoad = errors.New("exchange failed to load") ) +func dryrunParamInteraction(param string) { + if !Bot.Settings.CheckParamInteraction { + return + } + + if !Bot.Settings.EnableDryRun && !flagSet["dryrun"] { + log.Warnf(log.Global, + "Command line argument '-%s' induces dry run mode."+ + " Set -dryrun=false if you wish to override this.", + param) + Bot.Settings.EnableDryRun = true + } +} + // CheckExchangeExists returns true whether or not an exchange has already // been loaded func CheckExchangeExists(exchName string) bool { @@ -204,6 +218,7 @@ func LoadExchange(name string, useWG bool, wg *sync.WaitGroup) error { if Bot.Settings.EnableAllPairs { if exchCfg.CurrencyPairs != nil { + dryrunParamInteraction("enableallpairs") assets := exchCfg.CurrencyPairs.GetAssetTypes() for x := range assets { pairs := exchCfg.CurrencyPairs.GetPairs(assets[x], false) @@ -213,10 +228,12 @@ func LoadExchange(name string, useWG bool, wg *sync.WaitGroup) error { } if Bot.Settings.EnableExchangeVerbose { + dryrunParamInteraction("exchangeverbose") exchCfg.Verbose = true } if Bot.Settings.EnableExchangeWebsocketSupport { + dryrunParamInteraction("exchangewebsocketsupport") if exchCfg.Features != nil { if exchCfg.Features.Supports.Websocket { exchCfg.Features.Enabled.Websocket = true @@ -225,6 +242,7 @@ func LoadExchange(name string, useWG bool, wg *sync.WaitGroup) error { } if Bot.Settings.EnableExchangeAutoPairUpdates { + dryrunParamInteraction("exchangeautopairupdates") if exchCfg.Features != nil { if exchCfg.Features.Supports.RESTCapabilities.AutoPairUpdates { exchCfg.Features.Enabled.AutoPairUpdates = true @@ -233,6 +251,7 @@ func LoadExchange(name string, useWG bool, wg *sync.WaitGroup) error { } if Bot.Settings.DisableExchangeAutoPairUpdates { + dryrunParamInteraction("exchangedisableautopairupdates") if exchCfg.Features != nil { if exchCfg.Features.Supports.RESTCapabilities.AutoPairUpdates { exchCfg.Features.Enabled.AutoPairUpdates = false @@ -241,21 +260,29 @@ func LoadExchange(name string, useWG bool, wg *sync.WaitGroup) error { } if Bot.Settings.ExchangeHTTPUserAgent != "" { + dryrunParamInteraction("exchangehttpuseragent") exchCfg.HTTPUserAgent = Bot.Settings.ExchangeHTTPUserAgent } if Bot.Settings.ExchangeHTTPProxy != "" { + dryrunParamInteraction("exchangehttpproxy") exchCfg.ProxyAddress = Bot.Settings.ExchangeHTTPProxy } if Bot.Settings.ExchangeHTTPTimeout != exchange.DefaultHTTPTimeout { + dryrunParamInteraction("exchangehttptimeout") exchCfg.HTTPTimeout = Bot.Settings.ExchangeHTTPTimeout } if Bot.Settings.EnableExchangeHTTPDebugging { + dryrunParamInteraction("exchangehttpdebugging") exchCfg.HTTPDebugging = Bot.Settings.EnableExchangeHTTPDebugging } + if Bot.Settings.EnableAllExchanges { + dryrunParamInteraction("enableallexchanges") + } + exchCfg.Enabled = true err = exch.Setup(exchCfg) if err != nil { diff --git a/engine/exchange_test.go b/engine/exchange_test.go index b7713b82188..18f08032f66 100644 --- a/engine/exchange_test.go +++ b/engine/exchange_test.go @@ -21,21 +21,21 @@ func SetupTest(t *testing.T) { testSetup = true } - if CheckExchangeExists("Bitfinex") { + if CheckExchangeExists(testExchange) { return } - err := LoadExchange("Bitfinex", false, nil) + err := LoadExchange(testExchange, false, nil) if err != nil { t.Errorf("SetupTest: Failed to load exchange: %s", err) } } func CleanupTest(t *testing.T) { - if !CheckExchangeExists("Bitfinex") { + if !CheckExchangeExists(testExchange) { return } - err := UnloadExchange("Bitfinex") + err := UnloadExchange(testExchange) if err != nil { t.Fatalf("CleanupTest: Failed to unload exchange: %s", err) @@ -45,7 +45,7 @@ func CleanupTest(t *testing.T) { func TestCheckExchangeExists(t *testing.T) { SetupTest(t) - if !CheckExchangeExists("Bitfinex") { + if !CheckExchangeExists(testExchange) { t.Errorf("TestGetExchangeExists: Unable to find exchange") } @@ -59,7 +59,7 @@ func TestCheckExchangeExists(t *testing.T) { func TestGetExchangeByName(t *testing.T) { SetupTest(t) - exch := GetExchangeByName("Bitfinex") + exch := GetExchangeByName(testExchange) if exch == nil { t.Errorf("TestGetExchangeByName: Failed to get exchange") } @@ -69,12 +69,12 @@ func TestGetExchangeByName(t *testing.T) { } exch.SetEnabled(false) - bfx := GetExchangeByName("Bitfinex") + bfx := GetExchangeByName(testExchange) if bfx.IsEnabled() { t.Errorf("TestGetExchangeByName: Unexpected result") } - if exch.GetName() != "Bitfinex" { + if exch.GetName() != testExchange { t.Errorf("TestGetExchangeByName: Unexpected result") } @@ -95,7 +95,7 @@ func TestReloadExchange(t *testing.T) { err) } - err = ReloadExchange("Bitfinex") + err = ReloadExchange(testExchange) if err != nil { t.Errorf("TestReloadExchange: Incorrect result: %s", err) @@ -119,7 +119,7 @@ func TestUnloadExchange(t *testing.T) { err) } - err = UnloadExchange("Bitfinex") + err = UnloadExchange(testExchange) if err != nil { t.Errorf("TestUnloadExchange: Failed to get exchange. %s", err) @@ -133,3 +133,66 @@ func TestUnloadExchange(t *testing.T) { CleanupTest(t) } + +func TestDryRunParamInteraction(t *testing.T) { + SetupTest(t) + + // Load bot as per normal, dry run and verbose for Bitfinex should be + // disabled + exchCfg, err := Bot.Config.GetExchangeConfig(testExchange) + if err != nil { + t.Error(err) + } + + if Bot.Settings.EnableDryRun || + exchCfg.Verbose { + t.Error("dryrun and verbose should have been disabled") + } + + // Simulate overiding default settings and ensure that enabling exchange + // verbose mode will be set on Bitfinex + if err = UnloadExchange(testExchange); err != nil { + t.Error(err) + } + + Bot.Settings.CheckParamInteraction = true + Bot.Settings.EnableExchangeVerbose = true + if err = LoadExchange(testExchange, false, nil); err != nil { + t.Error(err) + } + + exchCfg, err = Bot.Config.GetExchangeConfig(testExchange) + if err != nil { + t.Error(err) + } + + if !Bot.Settings.EnableDryRun || + !exchCfg.Verbose { + t.Error("dryrun and verbose should have been enabled") + } + + if err = UnloadExchange(testExchange); err != nil { + t.Error(err) + } + + // Now set dryrun mode to false (via flagset and the previously enabled + // setting), enable exchange verbose mode and verify that verbose mode + // will be set on Bitfinex + Bot.Settings.EnableDryRun = false + Bot.Settings.CheckParamInteraction = true + Bot.Settings.EnableExchangeVerbose = true + flagSet["dryrun"] = true + if err = LoadExchange(testExchange, false, nil); err != nil { + t.Error(err) + } + + exchCfg, err = Bot.Config.GetExchangeConfig(testExchange) + if err != nil { + t.Error(err) + } + + if Bot.Settings.EnableDryRun || + !exchCfg.Verbose { + t.Error("dryrun should be false and verbose should be true") + } +} diff --git a/engine/routines.go b/engine/routines.go index 16320491f5d..87ded1e9c2a 100644 --- a/engine/routines.go +++ b/engine/routines.go @@ -335,11 +335,18 @@ func WebsocketDataHandler(ws *wshandler.Websocket) { // TO-DO: printOrderbookSummary //nolint:gocritic if Bot.Settings.Verbose { - log.Infof(log.WebsocketMgr, "Websocket %s %s orderbook updated\n", ws.GetName(), result.Pair.String()) + log.Infof(log.WebsocketMgr, + "Websocket %s %s orderbook updated\n", + ws.GetName(), + FormatCurrency(result.Pair), + ) } default: if Bot.Settings.Verbose { - log.Warnf(log.WebsocketMgr, "Websocket Unknown type: %s\n", d) + log.Warnf(log.WebsocketMgr, + "Websocket %s Unknown type: %v\n", + ws.GetName(), + d) } } } diff --git a/engine/syncer.go b/engine/syncer.go index 47c88284ab1..6807dd9c7b9 100644 --- a/engine/syncer.go +++ b/engine/syncer.go @@ -17,8 +17,8 @@ const ( SyncItemOrderbook SyncItemTrade - defaultSyncerWorkers = 30 - defaultSyncerTimeout = time.Second * 15 + DefaultSyncerWorkers = 15 + DefaultSyncerTimeout = time.Second * 15 ) var ( @@ -33,7 +33,11 @@ func NewCurrencyPairSyncer(c CurrencyPairSyncerConfig) (*ExchangeCurrencyPairSyn } if c.NumWorkers <= 0 { - c.NumWorkers = defaultSyncerWorkers + c.NumWorkers = DefaultSyncerWorkers + } + + if c.SyncTimeout <= time.Duration(0) { + c.SyncTimeout = DefaultSyncerTimeout } s := ExchangeCurrencyPairSyncer{ @@ -42,6 +46,7 @@ func NewCurrencyPairSyncer(c CurrencyPairSyncerConfig) (*ExchangeCurrencyPairSyn SyncOrderbook: c.SyncOrderbook, SyncTrades: c.SyncTrades, SyncContinuously: c.SyncContinuously, + SyncTimeout: c.SyncTimeout, NumWorkers: c.NumWorkers, }, } @@ -50,9 +55,9 @@ func NewCurrencyPairSyncer(c CurrencyPairSyncerConfig) (*ExchangeCurrencyPairSyn log.Debugf(log.SyncMgr, "Exchange currency pair syncer config: continuous: %v ticker: %v"+ - " orderbook: %v trades: %v workers: %v verbose: %v\n", + " orderbook: %v trades: %v workers: %v verbose: %v timeout: %v\n", s.Cfg.SyncContinuously, s.Cfg.SyncTicker, s.Cfg.SyncOrderbook, - s.Cfg.SyncTrades, s.Cfg.NumWorkers, s.Cfg.Verbose) + s.Cfg.SyncTrades, s.Cfg.NumWorkers, s.Cfg.Verbose, s.Cfg.SyncTimeout) return &s, nil } @@ -354,9 +359,9 @@ func (e *ExchangeCurrencyPairSyncer) worker() { } if e.Cfg.SyncTicker { if !e.isProcessing(exchangeName, c.Pair, c.AssetType, SyncItemTicker) { - if c.Ticker.LastUpdated.IsZero() || time.Since(c.Ticker.LastUpdated) > defaultSyncerTimeout { + if c.Ticker.LastUpdated.IsZero() || time.Since(c.Ticker.LastUpdated) > e.Cfg.SyncTimeout { if c.Ticker.IsUsingWebsocket { - if time.Since(c.Created) < defaultSyncerTimeout { + if time.Since(c.Created) < e.Cfg.SyncTimeout { continue } @@ -385,7 +390,7 @@ func (e *ExchangeCurrencyPairSyncer) worker() { } e.mux.Unlock() - if batchLastDone.IsZero() || time.Since(batchLastDone) > defaultSyncerTimeout { + if batchLastDone.IsZero() || time.Since(batchLastDone) > e.Cfg.SyncTimeout { e.mux.Lock() if e.Cfg.Verbose { log.Debugf(log.SyncMgr, "%s Init'ing REST ticker batching\n", exchangeName) @@ -419,9 +424,9 @@ func (e *ExchangeCurrencyPairSyncer) worker() { if e.Cfg.SyncOrderbook { if !e.isProcessing(exchangeName, c.Pair, c.AssetType, SyncItemOrderbook) { - if c.Orderbook.LastUpdated.IsZero() || time.Since(c.Orderbook.LastUpdated) > defaultSyncerTimeout { + if c.Orderbook.LastUpdated.IsZero() || time.Since(c.Orderbook.LastUpdated) > e.Cfg.SyncTimeout { if c.Orderbook.IsUsingWebsocket { - if time.Since(c.Created) < defaultSyncerTimeout { + if time.Since(c.Created) < e.Cfg.SyncTimeout { continue } if supportsREST { @@ -452,7 +457,7 @@ func (e *ExchangeCurrencyPairSyncer) worker() { } if e.Cfg.SyncTrades { if !e.isProcessing(exchangeName, c.Pair, c.AssetType, SyncItemTrade) { - if c.Trade.LastUpdated.IsZero() || time.Since(c.Trade.LastUpdated) > defaultSyncerTimeout { + if c.Trade.LastUpdated.IsZero() || time.Since(c.Trade.LastUpdated) > e.Cfg.SyncTimeout { e.setProcessing(c.Exchange, c.Pair, c.AssetType, SyncItemTrade, true) e.update(c.Exchange, c.Pair, c.AssetType, SyncItemTrade, nil) } @@ -570,7 +575,6 @@ func (e *ExchangeCurrencyPairSyncer) Start() { if !e.Cfg.SyncContinuously { log.Debugln(log.SyncMgr, "Exchange CurrencyPairSyncer stopping.") e.Stop() - Bot.Stop() return } } diff --git a/engine/syncer_types.go b/engine/syncer_types.go index 54551a9e1b8..4701b503863 100644 --- a/engine/syncer_types.go +++ b/engine/syncer_types.go @@ -14,9 +14,9 @@ type CurrencyPairSyncerConfig struct { SyncOrderbook bool SyncTrades bool SyncContinuously bool - - NumWorkers int - Verbose bool + SyncTimeout time.Duration + NumWorkers int + Verbose bool } // ExchangeSyncerConfig stores the exchange syncer config diff --git a/exchanges/alphapoint/alphapoint_wrapper.go b/exchanges/alphapoint/alphapoint_wrapper.go index a28e4368c86..2eb892006b5 100644 --- a/exchanges/alphapoint/alphapoint_wrapper.go +++ b/exchanges/alphapoint/alphapoint_wrapper.go @@ -153,15 +153,17 @@ func (a *Alphapoint) UpdateOrderbook(p currency.Pair, assetType asset.Item) (ord } for x := range orderbookNew.Bids { - data := orderbookNew.Bids[x] - orderBook.Bids = append(orderBook.Bids, - orderbook.Item{Amount: data.Quantity, Price: data.Price}) + orderBook.Bids = append(orderBook.Bids, orderbook.Item{ + Amount: orderbookNew.Bids[x].Quantity, + Price: orderbookNew.Bids[x].Price, + }) } for x := range orderbookNew.Asks { - data := orderbookNew.Asks[x] - orderBook.Asks = append(orderBook.Asks, - orderbook.Item{Amount: data.Quantity, Price: data.Price}) + orderBook.Asks = append(orderBook.Asks, orderbook.Item{ + Amount: orderbookNew.Asks[x].Quantity, + Price: orderbookNew.Asks[x].Price, + }) } orderBook.Pair = p @@ -188,9 +190,8 @@ func (a *Alphapoint) FetchOrderbook(p currency.Pair, assetType asset.Item) (orde // GetFundingHistory returns funding history, deposits and // withdrawals func (a *Alphapoint) GetFundingHistory() ([]exchange.FundHistory, error) { - var fundHistory []exchange.FundHistory // https://alphapoint.github.io/slate/#generatetreasuryactivityreport - return fundHistory, common.ErrNotYetImplemented + return nil, common.ErrNotYetImplemented } // GetExchangeHistory returns historic trade data since exchange opening. diff --git a/exchanges/anx/anx_test.go b/exchanges/anx/anx_test.go index f2951332d19..e6b29f10fa0 100644 --- a/exchanges/anx/anx_test.go +++ b/exchanges/anx/anx_test.go @@ -233,7 +233,7 @@ func TestSubmitOrder(t *testing.T) { Quote: currency.USD, }, OrderSide: order.Buy, - OrderType: order.Market, + OrderType: order.Limit, Price: 1, Amount: 1, ClientID: "meowOrder", diff --git a/exchanges/anx/anx_wrapper.go b/exchanges/anx/anx_wrapper.go index 6b4b7e5772c..96b657ff30b 100644 --- a/exchanges/anx/anx_wrapper.go +++ b/exchanges/anx/anx_wrapper.go @@ -310,8 +310,7 @@ func (a *ANX) GetAccountInfo() (exchange.AccountInfo, error) { // GetFundingHistory returns funding history, deposits and // withdrawals func (a *ANX) GetFundingHistory() ([]exchange.FundHistory, error) { - var fundHistory []exchange.FundHistory - return fundHistory, common.ErrFunctionNotSupported + return nil, common.ErrFunctionNotSupported } // GetExchangeHistory returns historic trade data since exchange opening. diff --git a/exchanges/binance/binance.go b/exchanges/binance/binance.go index dc841f731dc..2dbbdf94998 100644 --- a/exchanges/binance/binance.go +++ b/exchanges/binance/binance.go @@ -87,8 +87,7 @@ func (b *Binance) GetExchangeInfo() (ExchangeInfo, error) { // symbol: string of currency pair // limit: returned limit amount func (b *Binance) GetOrderBook(obd OrderBookDataRequestParams) (OrderBook, error) { - orderbook, resp := OrderBook{}, OrderBookData{} - + var orderbook OrderBook if err := b.CheckLimit(obd.Limit); err != nil { return orderbook, err } @@ -97,42 +96,44 @@ func (b *Binance) GetOrderBook(obd OrderBookDataRequestParams) (OrderBook, error params.Set("symbol", strings.ToUpper(obd.Symbol)) params.Set("limit", fmt.Sprintf("%d", obd.Limit)) - path := fmt.Sprintf("%s%s?%s", b.API.Endpoints.URL, orderBookDepth, params.Encode()) - + var resp OrderBookData + path := common.EncodeURLValues(b.API.Endpoints.URL+orderBookDepth, params) if err := b.SendHTTPRequest(path, &resp); err != nil { return orderbook, err } - for _, asks := range resp.Asks { - var ASK struct { - Price float64 - Quantity float64 + for x := range resp.Bids { + price, err := strconv.ParseFloat(resp.Bids[x][0], 64) + if err != nil { + return orderbook, err } - for i, ask := range asks.([]interface{}) { - switch i { - case 0: - ASK.Price, _ = strconv.ParseFloat(ask.(string), 64) - case 1: - ASK.Quantity, _ = strconv.ParseFloat(ask.(string), 64) - orderbook.Asks = append(orderbook.Asks, ASK) - } + + amount, err := strconv.ParseFloat(resp.Bids[x][1], 64) + if err != nil { + return orderbook, err } + + orderbook.Bids = append(orderbook.Bids, OrderbookItem{ + Price: price, + Quantity: amount, + }) } - for _, bids := range resp.Bids { - var BID struct { - Price float64 - Quantity float64 + for x := range resp.Asks { + price, err := strconv.ParseFloat(resp.Asks[x][0], 64) + if err != nil { + return orderbook, err } - for i, bid := range bids.([]interface{}) { - switch i { - case 0: - BID.Price, _ = strconv.ParseFloat(bid.(string), 64) - case 1: - BID.Quantity, _ = strconv.ParseFloat(bid.(string), 64) - orderbook.Bids = append(orderbook.Bids, BID) - } + + amount, err := strconv.ParseFloat(resp.Asks[x][1], 64) + if err != nil { + return orderbook, err } + + orderbook.Asks = append(orderbook.Asks, OrderbookItem{ + Price: price, + Quantity: amount, + }) } orderbook.LastUpdateID = resp.LastUpdateID diff --git a/exchanges/binance/binance_test.go b/exchanges/binance/binance_test.go index 779894db10b..0f142019886 100644 --- a/exchanges/binance/binance_test.go +++ b/exchanges/binance/binance_test.go @@ -359,7 +359,7 @@ func TestSubmitOrder(t *testing.T) { Quote: currency.BTC, }, OrderSide: order.Buy, - OrderType: order.Market, + OrderType: order.Limit, Price: 1, Amount: 1000000000, ClientID: "meowOrder", diff --git a/exchanges/binance/binance_types.go b/exchanges/binance/binance_types.go index e3bd8125da7..48a90381fd3 100644 --- a/exchanges/binance/binance_types.go +++ b/exchanges/binance/binance_types.go @@ -59,13 +59,19 @@ type OrderBookDataRequestParams struct { Limit int `json:"limit"` // Default 100; max 1000. Valid limits:[5, 10, 20, 50, 100, 500, 1000] } +// OrderbookItem stores an individual orderbook item +type OrderbookItem struct { + Price float64 + Quantity float64 +} + // OrderBookData is resp data from orderbook endpoint type OrderBookData struct { - Code int `json:"code"` - Msg string `json:"msg"` - LastUpdateID int64 `json:"lastUpdateId"` - Bids []interface{} `json:"bids"` - Asks []interface{} `json:"asks"` + Code int `json:"code"` + Msg string `json:"msg"` + LastUpdateID int64 `json:"lastUpdateId"` + Bids [][]string `json:"bids"` + Asks [][]string `json:"asks"` } // OrderBook actual structured data that can be used for orderbook @@ -73,14 +79,8 @@ type OrderBook struct { LastUpdateID int64 Code int Msg string - Bids []struct { - Price float64 - Quantity float64 - } - Asks []struct { - Price float64 - Quantity float64 - } + Bids []OrderbookItem + Asks []OrderbookItem } // DepthUpdateParams is used as an embedded type for WebsocketDepthStream diff --git a/exchanges/binance/binance_wrapper.go b/exchanges/binance/binance_wrapper.go index 829915fcd75..7d66a87bb3d 100644 --- a/exchanges/binance/binance_wrapper.go +++ b/exchanges/binance/binance_wrapper.go @@ -383,8 +383,7 @@ func (b *Binance) GetAccountInfo() (exchange.AccountInfo, error) { // GetFundingHistory returns funding history, deposits and // withdrawals func (b *Binance) GetFundingHistory() ([]exchange.FundHistory, error) { - var fundHistory []exchange.FundHistory - return fundHistory, common.ErrFunctionNotSupported + return nil, common.ErrFunctionNotSupported } // GetExchangeHistory returns historic trade data since exchange opening. diff --git a/exchanges/bitfinex/bitfinex_websocket.go b/exchanges/bitfinex/bitfinex_websocket.go index 3be37672c99..be6ff69ebd5 100644 --- a/exchanges/bitfinex/bitfinex_websocket.go +++ b/exchanges/bitfinex/bitfinex_websocket.go @@ -14,6 +14,7 @@ import ( "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/websocket/wshandler" "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wsorderbook" @@ -433,10 +434,10 @@ func (b *Bitfinex) WsDataHandler() { } if len(trades) > 0 { - side := "BUY" + side := order.Buy newAmount := trades[0].Amount if newAmount < 0 { - side = "SELL" + side = order.Sell newAmount *= -1 } @@ -447,7 +448,7 @@ func (b *Bitfinex) WsDataHandler() { Amount: newAmount, Exchange: b.Name, AssetType: asset.Spot, - Side: side, + Side: side.String(), } } } diff --git a/exchanges/bitfinex/bitfinex_wrapper.go b/exchanges/bitfinex/bitfinex_wrapper.go index c5aa9cc242e..f5337b757cf 100644 --- a/exchanges/bitfinex/bitfinex_wrapper.go +++ b/exchanges/bitfinex/bitfinex_wrapper.go @@ -349,8 +349,7 @@ func (b *Bitfinex) GetAccountInfo() (exchange.AccountInfo, error) { // GetFundingHistory returns funding history, deposits and // withdrawals func (b *Bitfinex) GetFundingHistory() ([]exchange.FundHistory, error) { - var fundHistory []exchange.FundHistory - return fundHistory, common.ErrFunctionNotSupported + return nil, common.ErrFunctionNotSupported } // GetExchangeHistory returns historic trade data since exchange opening. diff --git a/exchanges/bithumb/bithumb_test.go b/exchanges/bithumb/bithumb_test.go index 05f5ad56500..a4127426fa7 100644 --- a/exchanges/bithumb/bithumb_test.go +++ b/exchanges/bithumb/bithumb_test.go @@ -15,6 +15,7 @@ const ( apiKey = "" apiSecret = "" canManipulateRealOrders = false + testCurrency = "btc" ) var b Bithumb @@ -54,7 +55,7 @@ func TestGetTradablePairs(t *testing.T) { func TestGetTicker(t *testing.T) { t.Parallel() - _, err := b.GetTicker("btc") + _, err := b.GetTicker(testCurrency) if err != nil { t.Error("Bithumb GetTicker() error", err) } @@ -70,7 +71,7 @@ func TestGetAllTickers(t *testing.T) { func TestGetOrderBook(t *testing.T) { t.Parallel() - _, err := b.GetOrderBook("btc") + _, err := b.GetOrderBook(testCurrency) if err != nil { t.Error("Bithumb GetOrderBook() error", err) } @@ -78,7 +79,7 @@ func TestGetOrderBook(t *testing.T) { func TestGetTransactionHistory(t *testing.T) { t.Parallel() - _, err := b.GetTransactionHistory("btc") + _, err := b.GetTransactionHistory(testCurrency) if err != nil { t.Error("Bithumb GetTransactionHistory() error", err) } @@ -90,7 +91,7 @@ func TestGetAccountBalance(t *testing.T) { t.Skip() } - _, err := b.GetAccountBalance("BTC") + _, err := b.GetAccountBalance(testCurrency) if err == nil { t.Error("Bithumb GetAccountBalance() Expected error") } @@ -118,7 +119,7 @@ func TestGetLastTransaction(t *testing.T) { func TestGetOrders(t *testing.T) { t.Parallel() - _, err := b.GetOrders("1337", "bid", "100", "", "BTC") + _, err := b.GetOrders("1337", order.Bid.Lower(), "100", "", testCurrency) if err == nil { t.Error("Bithumb GetOrders() Expected error") } @@ -134,7 +135,7 @@ func TestGetUserTransactions(t *testing.T) { func TestPlaceTrade(t *testing.T) { t.Parallel() - _, err := b.PlaceTrade("btc", "bid", 0, 0) + _, err := b.PlaceTrade(testCurrency, order.Bid.Lower(), 0, 0) if err == nil { t.Error("Bithumb PlaceTrade() Expected error") } @@ -142,7 +143,7 @@ func TestPlaceTrade(t *testing.T) { func TestGetOrderDetails(t *testing.T) { t.Parallel() - _, err := b.GetOrderDetails("1337", "bid", "btc") + _, err := b.GetOrderDetails("1337", order.Bid.Lower(), testCurrency) if err == nil { t.Error("Bithumb GetOrderDetails() Expected error") } @@ -185,7 +186,7 @@ func TestRequestKRWWithdraw(t *testing.T) { func TestMarketBuyOrder(t *testing.T) { t.Parallel() - _, err := b.MarketBuyOrder("btc", 0) + _, err := b.MarketBuyOrder(testCurrency, 0) if err == nil { t.Error("Bithumb MarketBuyOrder() Expected error") } @@ -193,7 +194,7 @@ func TestMarketBuyOrder(t *testing.T) { func TestMarketSellOrder(t *testing.T) { t.Parallel() - _, err := b.MarketSellOrder("btc", 0) + _, err := b.MarketSellOrder(testCurrency, 0) if err == nil { t.Error("Bithumb MarketSellOrder() Expected error") } diff --git a/exchanges/bithumb/bithumb_wrapper.go b/exchanges/bithumb/bithumb_wrapper.go index 2e9b12c1b2e..c4bf45a863c 100644 --- a/exchanges/bithumb/bithumb_wrapper.go +++ b/exchanges/bithumb/bithumb_wrapper.go @@ -291,8 +291,7 @@ func (b *Bithumb) GetAccountInfo() (exchange.AccountInfo, error) { // GetFundingHistory returns funding history, deposits and // withdrawals func (b *Bithumb) GetFundingHistory() ([]exchange.FundHistory, error) { - var fundHistory []exchange.FundHistory - return fundHistory, common.ErrFunctionNotSupported + return nil, common.ErrFunctionNotSupported } // GetExchangeHistory returns historic trade data since exchange opening. diff --git a/exchanges/bitmex/bitmex_websocket.go b/exchanges/bitmex/bitmex_websocket.go index 5b33a6e1361..a31316484ad 100644 --- a/exchanges/bitmex/bitmex_websocket.go +++ b/exchanges/bitmex/bitmex_websocket.go @@ -347,29 +347,21 @@ func (b *Bitmex) processOrderbook(data []OrderBookL2, action string, currencyPai switch action { case bitmexActionInitialData: var newOrderBook orderbook.Base - var bids, asks []orderbook.Item for i := range data { if strings.EqualFold(data[i].Side, order.Sell.String()) { - asks = append(asks, orderbook.Item{ + newOrderBook.Asks = append(newOrderBook.Asks, orderbook.Item{ Price: data[i].Price, Amount: float64(data[i].Size), ID: data[i].ID, }) continue } - bids = append(bids, orderbook.Item{ + newOrderBook.Bids = append(newOrderBook.Bids, orderbook.Item{ Price: data[i].Price, Amount: float64(data[i].Size), ID: data[i].ID, }) } - - if len(bids) == 0 || len(asks) == 0 { - return errors.New("bitmex_websocket.go error - snapshot not initialised correctly") - } - - newOrderBook.Asks = asks - newOrderBook.Bids = bids newOrderBook.AssetType = assetType newOrderBook.Pair = currencyPair newOrderBook.ExchangeName = b.Name diff --git a/exchanges/bitstamp/bitstamp.go b/exchanges/bitstamp/bitstamp.go index 64ecc018b47..202944d6c4a 100644 --- a/exchanges/bitstamp/bitstamp.go +++ b/exchanges/bitstamp/bitstamp.go @@ -7,9 +7,9 @@ import ( "fmt" "net/http" "net/url" - "reflect" "strconv" "strings" + "time" "github.com/thrasher-corp/gocryptotrader/common" "github.com/thrasher-corp/gocryptotrader/common/crypto" @@ -40,6 +40,7 @@ const ( bitstampAPIBitcoinWithdrawal = "bitcoin_withdrawal" bitstampAPILTCWithdrawal = "ltc_withdrawal" bitstampAPIETHWithdrawal = "eth_withdrawal" + bitstampAPIBCHWithdrawal = "bch_withdrawal" bitstampAPIBitcoinDeposit = "bitcoin_deposit_address" bitstampAPILitecoinDeposit = "ltc_address" bitstampAPIEthereumDeposit = "eth_address" @@ -54,6 +55,7 @@ const ( bitstampAuthRate = 8000 bitstampUnauthRate = 8000 + bitstampTimeLayout = "2006-1-2 15:04:05" ) // Bitstamp is the overarching type across the bitstamp package @@ -121,22 +123,17 @@ func getInternationalBankDepositFee(amount float64) float64 { } // CalculateTradingFee returns fee on a currency pair -func (b *Bitstamp) CalculateTradingFee(base, quote currency.Code, purchasePrice, amount float64, balances *Balances) float64 { +func (b *Bitstamp) CalculateTradingFee(base, quote currency.Code, purchasePrice, amount float64, balances Balances) float64 { var fee float64 - - switch base.String() + quote.String() { - case currency.BTC.String() + currency.USD.String(): - fee = balances.BTCUSDFee - case currency.BTC.String() + currency.EUR.String(): - fee = balances.BTCEURFee - case currency.XRP.String() + currency.EUR.String(): - fee = balances.XRPEURFee - case currency.XRP.String() + currency.USD.String(): - fee = balances.XRPUSDFee - case currency.EUR.String() + currency.USD.String(): - fee = balances.EURUSDFee - default: - fee = 0 + if v, ok := balances[base.String()]; ok { + switch quote { + case currency.BTC: + fee = v.BTCFee + case currency.USD: + fee = v.USDFee + case currency.EUR: + fee = v.EURFee + } } return fee * purchasePrice * amount } @@ -259,25 +256,62 @@ func (b *Bitstamp) GetEURUSDConversionRate() (EURUSDConversionRate, error) { } // GetBalance returns full balance of currency held on the exchange -func (b *Bitstamp) GetBalance() (*Balances, error) { - var balance Balances - return &balance, - b.SendAuthenticatedHTTPRequest(bitstampAPIBalance, true, nil, &balance) +func (b *Bitstamp) GetBalance() (Balances, error) { + var balance map[string]string + err := b.SendAuthenticatedHTTPRequest(bitstampAPIBalance, true, nil, &balance) + if err != nil { + return nil, err + } + + balances := make(map[string]Balance) + for k := range balance { + curr := k[0:3] + _, ok := balances[strings.ToUpper(curr)] + if !ok { + avail, _ := strconv.ParseFloat(balance[curr+"_available"], 64) + bal, _ := strconv.ParseFloat(balance[curr+"_balance"], 64) + reserved, _ := strconv.ParseFloat(balance[curr+"_reserved"], 64) + withdrawalFee, _ := strconv.ParseFloat(balance[curr+"_withdrawal_fee"], 64) + currBalance := Balance{ + Available: avail, + Balance: bal, + Reserved: reserved, + WithdrawalFee: withdrawalFee, + } + switch strings.ToUpper(curr) { + case currency.USD.String(): + eurFee, _ := strconv.ParseFloat(balance[curr+"eur_fee"], 64) + currBalance.EURFee = eurFee + case currency.EUR.String(): + usdFee, _ := strconv.ParseFloat(balance[curr+"usd_fee"], 64) + currBalance.USDFee = usdFee + default: + btcFee, _ := strconv.ParseFloat(balance[curr+"btc_fee"], 64) + currBalance.BTCFee = btcFee + eurFee, _ := strconv.ParseFloat(balance[curr+"eur_fee"], 64) + currBalance.EURFee = eurFee + usdFee, _ := strconv.ParseFloat(balance[curr+"usd_fee"], 64) + currBalance.USDFee = usdFee + } + balances[strings.ToUpper(curr)] = currBalance + } + } + return balances, nil } // GetUserTransactions returns an array of transactions func (b *Bitstamp) GetUserTransactions(currencyPair string) ([]UserTransactions, error) { type Response struct { - Date string `json:"datetime"` - TransID int64 `json:"id"` - Type int `json:"type,string"` - USD interface{} `json:"usd"` - EUR float64 `json:"eur"` - XRP float64 `json:"xrp"` - BTC interface{} `json:"btc"` - BTCUSD interface{} `json:"btc_usd"` - Fee float64 `json:"fee,string"` - OrderID int64 `json:"order_id"` + Date string `json:"datetime"` + TransactionID int64 `json:"id"` + Type int `json:"type,string"` + USD interface{} `json:"usd"` + EUR interface{} `json:"eur"` + XRP interface{} `json:"xrp"` + BTC interface{} `json:"btc"` + BTCUSD interface{} `json:"btc_usd"` + Fee float64 `json:"fee,string"` + OrderID int64 `json:"order_id"` } var response []Response @@ -297,41 +331,31 @@ func (b *Bitstamp) GetUserTransactions(currencyPair string) ([]UserTransactions, } } - var transactions []UserTransactions - - for _, y := range response { - tx := UserTransactions{} - tx.Date = y.Date - tx.TransID = y.TransID - tx.Type = y.Type - - /* Hack due to inconsistent JSON values... */ - varType := reflect.TypeOf(y.USD).String() - if varType == bitstampAPIReturnType { - tx.USD, _ = strconv.ParseFloat(y.USD.(string), 64) - } else { - tx.USD = y.USD.(float64) - } - - tx.EUR = y.EUR - tx.XRP = y.XRP - - varType = reflect.TypeOf(y.BTC).String() - if varType == bitstampAPIReturnType { - tx.BTC, _ = strconv.ParseFloat(y.BTC.(string), 64) - } else { - tx.BTC = y.BTC.(float64) - } - - varType = reflect.TypeOf(y.BTCUSD).String() - if varType == bitstampAPIReturnType { - tx.BTCUSD, _ = strconv.ParseFloat(y.BTCUSD.(string), 64) - } else { - tx.BTCUSD = y.BTCUSD.(float64) + processNumber := func(i interface{}) float64 { + switch t := i.(type) { + case float64: + return t + case string: + amt, _ := strconv.ParseFloat(t, 64) + return amt + default: + return 0 } + } - tx.Fee = y.Fee - tx.OrderID = y.OrderID + var transactions []UserTransactions + for x := range response { + tx := UserTransactions{} + tx.Date = response[x].Date + tx.TransactionID = response[x].TransactionID + tx.Type = response[x].Type + tx.EUR = processNumber(response[x].EUR) + tx.XRP = processNumber(response[x].XRP) + tx.USD = processNumber(response[x].USD) + tx.BTC = processNumber(response[x].BTC) + tx.BTCUSD = processNumber(response[x].BTCUSD) + tx.Fee = response[x].Fee + tx.OrderID = response[x].OrderID transactions = append(transactions, tx) } @@ -359,13 +383,17 @@ func (b *Bitstamp) GetOrderStatus(orderID int64) (OrderStatus, error) { } // CancelExistingOrder cancels order by ID -func (b *Bitstamp) CancelExistingOrder(orderID int64) (bool, error) { - result := false +func (b *Bitstamp) CancelExistingOrder(orderID int64) (CancelOrder, error) { var req = url.Values{} req.Add("id", strconv.FormatInt(orderID, 10)) - return result, - b.SendAuthenticatedHTTPRequest(bitstampAPICancelOrder, true, req, &result) + var result CancelOrder + err := b.SendAuthenticatedHTTPRequest(bitstampAPICancelOrder, true, req, &result) + if err != nil { + return result, err + } + + return result, nil } // CancelAllExistingOrders cancels all open orders on the exchange @@ -433,22 +461,24 @@ func (b *Bitstamp) CryptoWithdrawal(amount float64, address, symbol, destTag str var endpoint string switch strings.ToLower(symbol) { - case "btc": + case currency.BTC.Lower().String(): if instant { req.Add("instant", "1") } else { req.Add("instant", "0") } endpoint = bitstampAPIBitcoinWithdrawal - case "ltc": + case currency.LTC.Lower().String(): endpoint = bitstampAPILTCWithdrawal - case "eth": + case currency.ETH.Lower().String(): endpoint = bitstampAPIETHWithdrawal - case "xrp": + case currency.XRP.Lower().String(): if destTag != "" { req.Add("destination_tag", destTag) } endpoint = bitstampAPIXrpWithdrawal + case currency.BCH.Lower().String(): + endpoint = bitstampAPIBCHWithdrawal default: return resp, errors.New("incorrect symbol") } @@ -669,3 +699,7 @@ func (b *Bitstamp) SendAuthenticatedHTTPRequest(path string, v2 bool, values url return common.JSONDecode(interim, result) } + +func parseTime(dateTime string) (time.Time, error) { + return time.Parse(bitstampTimeLayout, dateTime) +} diff --git a/exchanges/bitstamp/bitstamp_test.go b/exchanges/bitstamp/bitstamp_test.go index 8720d655bcd..c541dd8afcb 100644 --- a/exchanges/bitstamp/bitstamp_test.go +++ b/exchanges/bitstamp/bitstamp_test.go @@ -143,9 +143,11 @@ func TestGetFee(t *testing.T) { func TestCalculateTradingFee(t *testing.T) { t.Parallel() - var newBalance = new(Balances) - newBalance.BTCUSDFee = 1 - newBalance.BTCEURFee = 0 + newBalance := make(Balances) + newBalance["BTC"] = Balance{ + USDFee: 1, + EURFee: 0, + } if resp := b.CalculateTradingFee(currency.BTC, currency.USD, 0, 0, newBalance); resp != 0 { t.Error("GetFee() error") @@ -401,15 +403,9 @@ func TestCancelExchangeOrder(t *testing.T) { t.Skip("API keys set, canManipulateRealOrders false, skipping test") } - currencyPair := currency.NewPair(currency.LTC, currency.BTC) - - var orderCancellation = &order.Cancel{ - OrderID: "1", - WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB", - AccountID: "1", - CurrencyPair: currencyPair, + orderCancellation := &order.Cancel{ + OrderID: "1234", } - err := b.CancelOrder(orderCancellation) switch { case !areTestAPIKeysSet() && err == nil && !mockTests: @@ -428,16 +424,7 @@ func TestCancelAllExchangeOrders(t *testing.T) { t.Skip("API keys set, canManipulateRealOrders false, skipping test") } - currencyPair := currency.NewPair(currency.LTC, currency.BTC) - - var orderCancellation = &order.Cancel{ - OrderID: "1", - WalletAddress: "1F5zVDgNjorJ51oGebSvNCrSAHpwGkUdDB", - AccountID: "1", - CurrencyPair: currencyPair, - } - - resp, err := b.CancelAllOrders(orderCancellation) + resp, err := b.CancelAllOrders(&order.Cancel{}) switch { case !areTestAPIKeysSet() && err == nil && !mockTests: t.Error("Expecting an error when no keys are set") @@ -583,3 +570,21 @@ func TestGetDepositAddress(t *testing.T) { t.Error("GetDepositAddress error", err) } } + +func TestParseTime(t *testing.T) { + t.Parallel() + + tm, err := parseTime("2019-10-18 01:55:14") + if err != nil { + t.Error(err) + } + + if tm.Year() != 2019 || + tm.Month() != 10 || + tm.Day() != 18 || + tm.Hour() != 1 || + tm.Minute() != 55 || + tm.Second() != 14 { + t.Error("invalid time values") + } +} diff --git a/exchanges/bitstamp/bitstamp_types.go b/exchanges/bitstamp/bitstamp_types.go index e8d8a676204..8483211ba02 100644 --- a/exchanges/bitstamp/bitstamp_types.go +++ b/exchanges/bitstamp/bitstamp_types.go @@ -1,5 +1,19 @@ package bitstamp +// Transaction types +const ( + Deposit = iota + Withdrawal + MarketTrade + SubAccountTransfer = 14 +) + +// Order side type +const ( + BuyOrder = iota + SellOrder +) + // Ticker holds ticker information type Ticker struct { Last float64 `json:"last,string"` @@ -52,55 +66,51 @@ type EURUSDConversionRate struct { Sell float64 `json:"sell,string"` } -// Balances holds full balance information with the supplied APIKEYS -type Balances struct { - USDBalance float64 `json:"usd_balance,string"` - BTCBalance float64 `json:"btc_balance,string"` - EURBalance float64 `json:"eur_balance,string"` - XRPBalance float64 `json:"xrp_balance,string"` - USDReserved float64 `json:"usd_reserved,string"` - BTCReserved float64 `json:"btc_reserved,string"` - EURReserved float64 `json:"eur_reserved,string"` - XRPReserved float64 `json:"xrp_reserved,string"` - USDAvailable float64 `json:"usd_available,string"` - BTCAvailable float64 `json:"btc_available,string"` - EURAvailable float64 `json:"eur_available,string"` - XRPAvailable float64 `json:"xrp_available,string"` - BTCUSDFee float64 `json:"btcusd_fee,string"` - BTCEURFee float64 `json:"btceur_fee,string"` - EURUSDFee float64 `json:"eurusd_fee,string"` - XRPUSDFee float64 `json:"xrpusd_fee,string"` - XRPEURFee float64 `json:"xrpeur_fee,string"` - XRPBTCFee float64 `json:"xrpbtc_fee,string"` - Fee float64 `json:"fee,string"` +// Balance stores the balance info +type Balance struct { + Available float64 + Balance float64 + Reserved float64 + WithdrawalFee float64 + BTCFee float64 // for cryptocurrency pairs + USDFee float64 + EURFee float64 } +// Balances holds full balance information with the supplied APIKEYS +type Balances map[string]Balance + // UserTransactions holds user transaction information type UserTransactions struct { - Date string `json:"datetime"` - TransID int64 `json:"id"` - Type int `json:"type,string"` - USD float64 `json:"usd"` - EUR float64 `json:"eur"` - BTC float64 `json:"btc"` - XRP float64 `json:"xrp"` - BTCUSD float64 `json:"btc_usd"` - Fee float64 `json:"fee,string"` - OrderID int64 `json:"order_id"` + Date string `json:"datetime"` + TransactionID int64 `json:"id"` + Type int `json:"type,string"` + USD float64 `json:"usd"` + EUR float64 `json:"eur"` + BTC float64 `json:"btc"` + XRP float64 `json:"xrp"` + BTCUSD float64 `json:"btc_usd"` + Fee float64 `json:"fee,string"` + OrderID int64 `json:"order_id"` } // Order holds current open order data type Order struct { - ID int64 `json:"id"` - Date int64 `json:"datetime"` - Type int `json:"type"` - Price float64 `json:"price"` - Amount float64 `json:"amount"` + ID int64 `json:"id,string"` + DateTime string `json:"datetime"` + Type int `json:"type,string"` + Price float64 `json:"price,string"` + Amount float64 `json:"amount,string"` Currency string `json:"currency_pair"` } // OrderStatus holds order status information type OrderStatus struct { + Price float64 `json:"price,string"` + Amount float64 `json:"amount,string"` + Type int `json:"type"` + ID int64 `json:"id,string"` + DateTime string `json:"datetime"` Status string Transactions []struct { TradeID int64 `json:"tid"` @@ -111,6 +121,14 @@ type OrderStatus struct { } } +// CancelOrder holds the order cancellation info +type CancelOrder struct { + Price float64 `json:"price"` + Amount float64 `json:"amount"` + Type int `json:"type"` + ID int64 `json:"id"` +} + // WithdrawalRequests holds request information on withdrawals type WithdrawalRequests struct { OrderID int64 `json:"id"` diff --git a/exchanges/bitstamp/bitstamp_websocket.go b/exchanges/bitstamp/bitstamp_websocket.go index 9cccbb62192..3cee9712de7 100644 --- a/exchanges/bitstamp/bitstamp_websocket.go +++ b/exchanges/bitstamp/bitstamp_websocket.go @@ -225,24 +225,18 @@ func (b *Bitstamp) seedOrderBook() error { } var newOrderBook orderbook.Base - var asks, bids []orderbook.Item - for i := range orderbookSeed.Asks { - var item orderbook.Item - item.Amount = orderbookSeed.Asks[i].Amount - item.Price = orderbookSeed.Asks[i].Price - asks = append(asks, item) + newOrderBook.Asks = append(newOrderBook.Asks, orderbook.Item{ + Price: orderbookSeed.Asks[i].Price, + Amount: orderbookSeed.Asks[i].Amount, + }) } - for i := range orderbookSeed.Bids { - var item orderbook.Item - item.Amount = orderbookSeed.Bids[i].Amount - item.Price = orderbookSeed.Bids[i].Price - bids = append(bids, item) + newOrderBook.Bids = append(newOrderBook.Bids, orderbook.Item{ + Price: orderbookSeed.Bids[i].Price, + Amount: orderbookSeed.Bids[i].Amount, + }) } - - newOrderBook.Asks = asks - newOrderBook.Bids = bids newOrderBook.Pair = p[x] newOrderBook.AssetType = asset.Spot newOrderBook.ExchangeName = b.Name diff --git a/exchanges/bitstamp/bitstamp_wrapper.go b/exchanges/bitstamp/bitstamp_wrapper.go index bd6473840ef..facc2950a68 100644 --- a/exchanges/bitstamp/bitstamp_wrapper.go +++ b/exchanges/bitstamp/bitstamp_wrapper.go @@ -289,13 +289,17 @@ func (b *Bitstamp) UpdateOrderbook(p currency.Pair, assetType asset.Item) (order } for x := range orderbookNew.Bids { - data := orderbookNew.Bids[x] - orderBook.Bids = append(orderBook.Bids, orderbook.Item{Amount: data.Amount, Price: data.Price}) + orderBook.Bids = append(orderBook.Bids, orderbook.Item{ + Amount: orderbookNew.Bids[x].Amount, + Price: orderbookNew.Bids[x].Price, + }) } for x := range orderbookNew.Asks { - data := orderbookNew.Asks[x] - orderBook.Asks = append(orderBook.Asks, orderbook.Item{Amount: data.Amount, Price: data.Price}) + orderBook.Asks = append(orderBook.Asks, orderbook.Item{ + Amount: orderbookNew.Asks[x].Amount, + Price: orderbookNew.Asks[x].Price, + }) } orderBook.Pair = p @@ -320,27 +324,13 @@ func (b *Bitstamp) GetAccountInfo() (exchange.AccountInfo, error) { return response, err } - var currencies = []exchange.AccountCurrencyInfo{ - { - CurrencyName: currency.BTC, - TotalValue: accountBalance.BTCAvailable, - Hold: accountBalance.BTCReserved, - }, - { - CurrencyName: currency.XRP, - TotalValue: accountBalance.XRPAvailable, - Hold: accountBalance.XRPReserved, - }, - { - CurrencyName: currency.USD, - TotalValue: accountBalance.USDAvailable, - Hold: accountBalance.USDReserved, - }, - { - CurrencyName: currency.EUR, - TotalValue: accountBalance.EURAvailable, - Hold: accountBalance.EURReserved, - }, + var currencies []exchange.AccountCurrencyInfo + for k, v := range accountBalance { + currencies = append(currencies, exchange.AccountCurrencyInfo{ + CurrencyName: currency.NewCode(k), + TotalValue: v.Available, + Hold: v.Reserved, + }) } response.Accounts = append(response.Accounts, exchange.Account{ Currencies: currencies, @@ -352,8 +342,7 @@ func (b *Bitstamp) GetAccountInfo() (exchange.AccountInfo, error) { // GetFundingHistory returns funding history, deposits and // withdrawals func (b *Bitstamp) GetFundingHistory() ([]exchange.FundHistory, error) { - var fundHistory []exchange.FundHistory - return fundHistory, common.ErrFunctionNotSupported + return nil, common.ErrFunctionNotSupported } // GetExchangeHistory returns historic trade data since exchange opening. @@ -518,7 +507,6 @@ func (b *Bitstamp) GetWebsocket() (*wshandler.Websocket, error) { // GetActiveOrders retrieves any orders that are active/open func (b *Bitstamp) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, error) { - var orders []order.Detail var currPair string if len(req.Currencies) != 1 { currPair = "all" @@ -531,16 +519,28 @@ func (b *Bitstamp) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, return nil, err } + var orders []order.Detail for i := range resp { - orderDate := time.Unix(resp[i].Date, 0) + orderSide := order.Buy + if resp[i].Type == SellOrder { + orderSide = order.Sell + } + + tm, err := parseTime(resp[i].DateTime) + if err != nil { + log.Errorf(log.ExchangeSys, + "%s GetActiveOrders unable to parse time: %s\n", b.Name, err) + } + orders = append(orders, order.Detail{ - Amount: resp[i].Amount, - ID: strconv.FormatInt(resp[i].ID, 10), - Price: resp[i].Price, - OrderDate: orderDate, - CurrencyPair: currency.NewPairFromStrings(resp[i].Currency[0:3], - resp[i].Currency[len(resp[i].Currency)-3:]), - Exchange: b.Name, + Amount: resp[i].Amount, + ID: strconv.FormatInt(resp[i].ID, 10), + Price: resp[i].Price, + OrderType: order.Limit, + OrderSide: orderSide, + OrderDate: tm, + CurrencyPair: currency.NewPairFromString(resp[i].Currency), + Exchange: b.Name, }) } @@ -563,7 +563,7 @@ func (b *Bitstamp) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, var orders []order.Detail for i := range resp { - if resp[i].Type != 2 { + if resp[i].Type != MarketTrade { continue } var quoteCurrency, baseCurrency currency.Code @@ -575,7 +575,8 @@ func (b *Bitstamp) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, baseCurrency = currency.XRP default: log.Warnf(log.ExchangeSys, - "no base currency found for OrderID '%d'", + "%s No base currency found for OrderID '%d'\n", + b.Name, resp[i].OrderID) } @@ -586,7 +587,8 @@ func (b *Bitstamp) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, quoteCurrency = currency.EUR default: log.Warnf(log.ExchangeSys, - "no quote currency found for orderID '%d'", + "%s No quote currency found for orderID '%d'\n", + b.Name, resp[i].OrderID) } @@ -597,14 +599,15 @@ func (b *Bitstamp) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, b.GetPairFormat(asset.Spot, false).Delimiter) } - orderDate, err := time.Parse("2006-01-02 15:04:05", resp[i].Date) + tm, err := parseTime(resp[i].Date) if err != nil { - return nil, err + log.Errorf(log.ExchangeSys, + "%s GetOrderHistory unable to parse time: %s\n", b.Name, err) } orders = append(orders, order.Detail{ ID: strconv.FormatInt(resp[i].OrderID, 10), - OrderDate: orderDate, + OrderDate: tm, Exchange: b.Name, CurrencyPair: currPair, }) diff --git a/exchanges/bittrex/bittrex.go b/exchanges/bittrex/bittrex.go index 1120bc68f86..4d9489d53ce 100644 --- a/exchanges/bittrex/bittrex.go +++ b/exchanges/bittrex/bittrex.go @@ -7,6 +7,7 @@ import ( "net/url" "strconv" "strings" + "time" "github.com/thrasher-corp/gocryptotrader/common/crypto" "github.com/thrasher-corp/gocryptotrader/currency" @@ -53,6 +54,7 @@ const ( bittrexAuthRate = 0 bittrexUnauthRate = 0 + bittrexTimeLayout = "2006-01-02T15:04:05" ) // Bittrex is the overaching type across the bittrex methods @@ -508,3 +510,7 @@ func (b *Bittrex) GetWithdrawalFee(c currency.Code) (float64, error) { func calculateTradingFee(price, amount float64) float64 { return 0.0025 * price * amount } + +func parseTime(t string) (time.Time, error) { + return time.Parse(bittrexTimeLayout, t) +} diff --git a/exchanges/bittrex/bittrex_test.go b/exchanges/bittrex/bittrex_test.go index 32196f3f837..976fe1653dd 100644 --- a/exchanges/bittrex/bittrex_test.go +++ b/exchanges/bittrex/bittrex_test.go @@ -534,3 +534,21 @@ func TestGetDepositAddress(t *testing.T) { } } } + +func TestParseTime(t *testing.T) { + t.Parallel() + + tm, err := parseTime("2019-11-21T02:08:34.87") + if err != nil { + t.Fatal(err) + } + + if tm.Year() != 2019 || + tm.Month() != 11 || + tm.Day() != 21 || + tm.Hour() != 2 || + tm.Minute() != 8 || + tm.Second() != 34 { + t.Error("invalid time values") + } +} diff --git a/exchanges/bittrex/bittrex_wrapper.go b/exchanges/bittrex/bittrex_wrapper.go index 15cef5ec63f..da8a543bec5 100644 --- a/exchanges/bittrex/bittrex_wrapper.go +++ b/exchanges/bittrex/bittrex_wrapper.go @@ -227,7 +227,11 @@ func (b *Bittrex) UpdateTicker(p currency.Pair, assetType asset.Item) (ticker.Pr if !strings.EqualFold(ticks.Result[j].MarketName, pairs[i].String()) { continue } - tickerTime, _ := time.Parse(time.RFC3339, ticks.Result[j].TimeStamp) + 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, @@ -309,8 +313,7 @@ func (b *Bittrex) UpdateOrderbook(p currency.Pair, assetType asset.Item) (orderb // GetFundingHistory returns funding history, deposits and // withdrawals func (b *Bittrex) GetFundingHistory() ([]exchange.FundHistory, error) { - var fundHistory []exchange.FundHistory - return fundHistory, common.ErrFunctionNotSupported + return nil, common.ErrFunctionNotSupported } // GetExchangeHistory returns historic trade data since exchange opening. @@ -451,9 +454,9 @@ func (b *Bittrex) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, var orders []order.Detail for i := range resp.Result { - orderDate, err := time.Parse(time.RFC3339, resp.Result[i].Opened) + orderDate, err := parseTime(resp.Result[i].Opened) if err != nil { - log.Warnf(log.ExchangeSys, + log.Errorf(log.ExchangeSys, "Exchange %v Func %v Order %v Could not parse date to unix with value of %v", b.Name, "GetActiveOrders", @@ -498,9 +501,9 @@ func (b *Bittrex) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, var orders []order.Detail for i := range resp.Result { - orderDate, err := time.Parse(time.RFC3339, resp.Result[i].TimeStamp) + orderDate, err := parseTime(resp.Result[i].TimeStamp) if err != nil { - log.Warnf(log.ExchangeSys, + log.Errorf(log.ExchangeSys, "Exchange %v Func %v Order %v Could not parse date to unix with value of %v", b.Name, "GetActiveOrders", diff --git a/exchanges/btcmarkets/btcmarkets_types.go b/exchanges/btcmarkets/btcmarkets_types.go index 33e61d788dd..7cccb8b2311 100644 --- a/exchanges/btcmarkets/btcmarkets_types.go +++ b/exchanges/btcmarkets/btcmarkets_types.go @@ -193,6 +193,7 @@ type WsOrderbook struct { MessageType string `json:"messageType"` } +// WsError message received for orderbook errors type WsError struct { MessageType string `json:"messageType"` Code int64 `json:"code"` diff --git a/exchanges/btcmarkets/btcmarkets_wrapper.go b/exchanges/btcmarkets/btcmarkets_wrapper.go index 21025ae33b8..b89f199b311 100644 --- a/exchanges/btcmarkets/btcmarkets_wrapper.go +++ b/exchanges/btcmarkets/btcmarkets_wrapper.go @@ -279,13 +279,17 @@ func (b *BTCMarkets) UpdateOrderbook(p currency.Pair, assetType asset.Item) (ord } for x := range orderbookNew.Bids { - data := orderbookNew.Bids[x] - orderBook.Bids = append(orderBook.Bids, orderbook.Item{Amount: data[1], Price: data[0]}) + orderBook.Bids = append(orderBook.Bids, orderbook.Item{ + Amount: orderbookNew.Bids[x][1], + Price: orderbookNew.Bids[x][0], + }) } for x := range orderbookNew.Asks { - data := orderbookNew.Asks[x] - orderBook.Asks = append(orderBook.Asks, orderbook.Item{Amount: data[1], Price: data[0]}) + orderBook.Asks = append(orderBook.Asks, orderbook.Item{ + Amount: orderbookNew.Asks[x][1], + Price: orderbookNew.Asks[x][0], + }) } orderBook.Pair = p @@ -331,8 +335,7 @@ func (b *BTCMarkets) GetAccountInfo() (exchange.AccountInfo, error) { // GetFundingHistory returns funding history, deposits and // withdrawals func (b *BTCMarkets) GetFundingHistory() ([]exchange.FundHistory, error) { - var fundHistory []exchange.FundHistory - return fundHistory, common.ErrFunctionNotSupported + return nil, common.ErrFunctionNotSupported } // GetExchangeHistory returns historic trade data since exchange opening. diff --git a/exchanges/btse/btse.go b/exchanges/btse/btse.go index 4642ec37597..bf2e2ac671e 100644 --- a/exchanges/btse/btse.go +++ b/exchanges/btse/btse.go @@ -42,6 +42,7 @@ const ( btsePendingOrders = "pending" btseDeleteOrder = "deleteOrder" btseFills = "fills" + btseTimeLayout = "2006-01-02 15:04:04" ) // GetMarketsSummary stores market summary data @@ -238,7 +239,7 @@ func (b *BTSE) SendAuthenticatedHTTPRequest(method, endpoint string, req map[str b.Name, method, path, string(payload)) } return b.SendPayload(method, - btseAPIURL+path, + b.API.Endpoints.URL+path, headers, body, &result, @@ -320,7 +321,6 @@ func calculateTradingFee(isMaker bool) float64 { return fee } -func parseOrderTime(timeStr string) time.Time { - t, _ := time.Parse("2006-01-02 15:04:04", timeStr) - return t +func parseOrderTime(timeStr string) (time.Time, error) { + return time.Parse(btseTimeLayout, timeStr) } diff --git a/exchanges/btse/btse_test.go b/exchanges/btse/btse_test.go index 916bce5473a..d97130b039f 100644 --- a/exchanges/btse/btse_test.go +++ b/exchanges/btse/btse_test.go @@ -17,6 +17,7 @@ const ( apiKey = "" apiSecret = "" canManipulateRealOrders = false + testPair = "BTC-USD" ) var b BTSE @@ -37,7 +38,11 @@ func TestMain(m *testing.M) { btseConfig.API.Credentials.Key = apiKey btseConfig.API.Credentials.Secret = apiSecret - b.Setup(btseConfig) + err = b.Setup(btseConfig) + if err != nil { + log.Fatal(err) + } + os.Exit(m.Run()) } @@ -63,7 +68,7 @@ func TestGetMarkets(t *testing.T) { func TestFetchOrderBook(t *testing.T) { t.Parallel() - _, err := b.FetchOrderBook("BTC-USD") + _, err := b.FetchOrderBook(testPair) if err != nil { t.Error(err) } @@ -71,7 +76,7 @@ func TestFetchOrderBook(t *testing.T) { func TestGetTrades(t *testing.T) { t.Parallel() - _, err := b.GetTrades("BTC-USD") + _, err := b.GetTrades(testPair) if err != nil { t.Error(err) } @@ -79,7 +84,7 @@ func TestGetTrades(t *testing.T) { func TestGetTicker(t *testing.T) { t.Parallel() - _, err := b.GetTicker("BTC-USD") + _, err := b.GetTicker(testPair) if err != nil { t.Error(err) } @@ -87,7 +92,7 @@ func TestGetTicker(t *testing.T) { func TestGetMarketStatistics(t *testing.T) { t.Parallel() - _, err := b.GetMarketStatistics("BTC-USD") + _, err := b.GetMarketStatistics(testPair) if err != nil { t.Error(err) } @@ -117,7 +122,7 @@ func TestGetFills(t *testing.T) { if !areTestAPIKeysSet() { t.Skip("API keys not set, skipping test") } - _, err := b.GetFills("", "BTC-USD", "", "", "", "") + _, err := b.GetFills("", testPair, "", "", "", "") if err != nil { t.Error(err) } @@ -128,7 +133,13 @@ func TestCreateOrder(t *testing.T) { if !areTestAPIKeysSet() || !canManipulateRealOrders { t.Skip("skipping test, either api keys or manipulaterealorders isnt set correctly") } - _, err := b.CreateOrder(0.1, 10000, "sell", "limit", "BTC-USD", "", "") + _, err := b.CreateOrder(0.1, + 10000, + order.Sell.String(), + order.Limit.String(), + testPair, + "", + "") if err != nil { t.Error(err) } @@ -266,9 +277,12 @@ func TestGetFee(t *testing.T) { func TestParseOrderTime(t *testing.T) { expected := int64(1534794360) - actual := parseOrderTime("2018-08-20 19:20:46").Unix() - if expected != actual { - t.Errorf("TestParseOrderTime expected: %d, got %d", expected, actual) + actual, err := parseOrderTime("2018-08-20 19:20:46") + if err != nil { + t.Fatal(err) + } + if expected != actual.Unix() { + t.Errorf("TestParseOrderTime expected: %d, got %d", expected, actual.Unix()) } } diff --git a/exchanges/btse/btse_websocket.go b/exchanges/btse/btse_websocket.go index d362c0bdddc..e12d3eebdf6 100644 --- a/exchanges/btse/btse_websocket.go +++ b/exchanges/btse/btse_websocket.go @@ -103,8 +103,8 @@ func (b *BTSE) WsHandleData() { b.Websocket.DataHandler <- err continue } + var newOB orderbook.Base var price, amount float64 - var asks, bids []orderbook.Item for i := range t.Data.SellQuote { p := strings.Replace(t.Data.SellQuote[i].Price, ",", "", -1) price, err = strconv.ParseFloat(p, 64) @@ -118,7 +118,10 @@ func (b *BTSE) WsHandleData() { b.Websocket.DataHandler <- err continue } - asks = append(asks, orderbook.Item{Price: price, Amount: amount}) + newOB.Asks = append(newOB.Asks, orderbook.Item{ + Price: price, + Amount: amount, + }) } for j := range t.Data.BuyQuote { p := strings.Replace(t.Data.BuyQuote[j].Price, ",", "", -1) @@ -133,11 +136,11 @@ func (b *BTSE) WsHandleData() { b.Websocket.DataHandler <- err continue } - bids = append(bids, orderbook.Item{Price: price, Amount: amount}) + newOB.Bids = append(newOB.Bids, orderbook.Item{ + Price: price, + Amount: amount, + }) } - var newOB orderbook.Base - newOB.Asks = asks - newOB.Bids = bids newOB.AssetType = asset.Spot newOB.Pair = currency.NewPairFromString(t.Topic[strings.Index(t.Topic, ":")+1 : strings.Index(t.Topic, "_")]) newOB.ExchangeName = b.Name diff --git a/exchanges/btse/btse_wrapper.go b/exchanges/btse/btse_wrapper.go index d7e9fca3f73..5a5ca079d56 100644 --- a/exchanges/btse/btse_wrapper.go +++ b/exchanges/btse/btse_wrapper.go @@ -450,7 +450,11 @@ func (b *BTSE) GetOrderInfo(orderID string) (order.Detail, error) { od.Exchange = b.Name od.Amount = o[i].Amount od.ID = o[i].ID - od.OrderDate = parseOrderTime(o[i].CreatedAt) + od.OrderDate, err = parseOrderTime(o[i].CreatedAt) + if err != nil { + log.Errorf(log.ExchangeSys, + "%s GetOrderInfo unable to parse time: %s\n", b.Name, err) + } od.OrderSide = side od.OrderType = order.Type(strings.ToUpper(o[i].Type)) od.Price = o[i].Price @@ -464,7 +468,11 @@ func (b *BTSE) GetOrderInfo(orderID string) (order.Detail, error) { } for i := range fills { - createdAt, _ := time.Parse(time.RFC3339, fills[i].CreatedAt) + createdAt, err := parseOrderTime(fills[i].CreatedAt) + if err != nil { + log.Errorf(log.ExchangeSys, + "%s GetOrderInfo unable to parse time: %s\n", b.Name, err) + } od.Trades = append(od.Trades, order.TradeHistory{ Timestamp: createdAt, TID: fills[i].ID, @@ -521,13 +529,21 @@ func (b *BTSE) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, err side = order.Sell } + tm, err := parseOrderTime(resp[i].CreatedAt) + if err != nil { + log.Errorf(log.ExchangeSys, + "%s GetActiveOrders unable to parse time: %s\n", + b.Name, + err) + } + openOrder := order.Detail{ CurrencyPair: currency.NewPairDelimiter(resp[i].Symbol, b.GetPairFormat(asset.Spot, false).Delimiter), Exchange: b.Name, Amount: resp[i].Amount, ID: resp[i].ID, - OrderDate: parseOrderTime(resp[i].CreatedAt), + OrderDate: tm, OrderSide: side, OrderType: order.Type(strings.ToUpper(resp[i].Type)), Price: resp[i].Price, @@ -544,7 +560,13 @@ func (b *BTSE) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, err } for i := range fills { - createdAt, _ := time.Parse(time.RFC3339, fills[i].CreatedAt) + createdAt, err := parseOrderTime(fills[i].CreatedAt) + if err != nil { + log.Errorf(log.ExchangeSys, + "%s GetActiveOrders unable to parse time: %s\n", + b.Name, + err) + } openOrder.Trades = append(openOrder.Trades, order.TradeHistory{ Timestamp: createdAt, TID: fills[i].ID, diff --git a/exchanges/coinbasepro/coinbasepro_test.go b/exchanges/coinbasepro/coinbasepro_test.go index 315b0433ffe..95d84f4a7ba 100644 --- a/exchanges/coinbasepro/coinbasepro_test.go +++ b/exchanges/coinbasepro/coinbasepro_test.go @@ -22,6 +22,7 @@ const ( apiSecret = "" clientID = "" // passphrase you made at API CREATION canManipulateRealOrders = false + testPair = "BTC-USD" ) func TestSetDefaults(t *testing.T) { @@ -58,28 +59,28 @@ func TestGetProducts(t *testing.T) { } func TestGetTicker(t *testing.T) { - _, err := c.GetTicker("BTC-USD") + _, err := c.GetTicker(testPair) if err != nil { t.Error("GetTicker() error", err) } } func TestGetTrades(t *testing.T) { - _, err := c.GetTrades("BTC-USD") + _, err := c.GetTrades(testPair) if err != nil { t.Error("GetTrades() error", err) } } func TestGetHistoricRates(t *testing.T) { - _, err := c.GetHistoricRates("BTC-USD", 0, 0, 0) + _, err := c.GetHistoricRates(testPair, 0, 0, 0) if err != nil { t.Error("GetHistoricRates() error", err) } } func TestGetStats(t *testing.T) { - _, err := c.GetStats("BTC-USD") + _, err := c.GetStats(testPair) if err != nil { t.Error("GetStats() error", err) } @@ -128,21 +129,23 @@ func TestAuthRequests(t *testing.T) { if err == nil { t.Error("Expecting error") } - orderResponse, err := c.PlaceLimitOrder("", 0.001, 0.001, "buy", "", "", "BTC-USD", "", false) + orderResponse, err := c.PlaceLimitOrder("", 0.001, 0.001, + order.Buy.Lower(), "", "", testPair, "", false) if orderResponse != "" { t.Error("Expecting no data returned") } if err == nil { t.Error("Expecting error") } - marketOrderResponse, err := c.PlaceMarketOrder("", 1, 0, "buy", "BTC-USD", "") + marketOrderResponse, err := c.PlaceMarketOrder("", 1, 0, + order.Buy.Lower(), testPair, "") if marketOrderResponse != "" { t.Error("Expecting no data returned") } if err == nil { t.Error("Expecting error") } - fillsResponse, err := c.GetFills("1337", "BTC-USD") + fillsResponse, err := c.GetFills("1337", testPair) if len(fillsResponse) > 0 { t.Error("Expecting no data returned") } @@ -616,7 +619,7 @@ func TestWsAuth(t *testing.T) { go c.WsHandleData() err = c.Subscribe(wshandler.WebsocketChannelSubscription{ Channel: "user", - Currency: currency.NewPairFromString("BTC-USD"), + Currency: currency.NewPairFromString(testPair), }) if err != nil { t.Error(err) diff --git a/exchanges/coinbasepro/coinbasepro_wrapper.go b/exchanges/coinbasepro/coinbasepro_wrapper.go index dd687b048b8..a66ebf413df 100644 --- a/exchanges/coinbasepro/coinbasepro_wrapper.go +++ b/exchanges/coinbasepro/coinbasepro_wrapper.go @@ -515,7 +515,7 @@ func (c *CoinbasePro) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Deta orderType := order.Type(strings.ToUpper(respOrders[i].Type)) orderDate, err := time.Parse(time.RFC3339, respOrders[i].CreatedAt) if err != nil { - log.Warnf(log.ExchangeSys, + log.Errorf(log.ExchangeSys, "Exchange %v Func %v Order %v Could not parse date to unix with value of %v", c.Name, "GetActiveOrders", @@ -562,7 +562,7 @@ func (c *CoinbasePro) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Deta orderType := order.Type(strings.ToUpper(respOrders[i].Type)) orderDate, err := time.Parse(time.RFC3339, respOrders[i].CreatedAt) if err != nil { - log.Warnf(log.ExchangeSys, + log.Errorf(log.ExchangeSys, "Exchange %v Func %v Order %v Could not parse date to unix with value of %v", c.Name, "GetActiveOrders", diff --git a/exchanges/coinbene/README.md b/exchanges/coinbene/README.md index 44f6ef316ca..e5a7cd7e69f 100644 --- a/exchanges/coinbene/README.md +++ b/exchanges/coinbene/README.md @@ -48,22 +48,22 @@ main.go ```go var c exchange.IBotExchange -for i := range bot.exchanges { - if bot.exchanges[i].GetName() == "Coinbene" { - c = bot.exchanges[i] +for i := range Bot.Exchanges { + if Bot.Exchanges[i].GetName() == "Coinbene" { + c = Bot.Exchanges[i] } } // Public calls - wrapper functions // Fetches current ticker information -tick, err := c.GetTickerPrice() +tick, err := c.FetchTicker() if err != nil { // Handle error } // Fetches current orderbook information -ob, err := c.GetOrderbookEx() +ob, err := c.FetchOrderbook() if err != nil { // Handle error } diff --git a/exchanges/coinbene/coinbene.go b/exchanges/coinbene/coinbene.go index 75c884190b5..4bb0653edee 100644 --- a/exchanges/coinbene/coinbene.go +++ b/exchanges/coinbene/coinbene.go @@ -247,9 +247,14 @@ func (c *Coinbene) SendHTTPRequest(path string, result interface{}) error { // SendAuthHTTPRequest sends an authenticated HTTP request func (c *Coinbene) SendAuthHTTPRequest(method, path, epPath string, params url.Values, result interface{}) error { + if !c.AllowAuthenticatedRequest() { + return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, c.Name) + } + if params == nil { params = url.Values{} } + timestamp := time.Now().UTC().Format("2006-01-02T15:04:05.999Z") var finalBody io.Reader var preSign string diff --git a/exchanges/coinbene/coinbene_test.go b/exchanges/coinbene/coinbene_test.go index f24255a0b3a..b870ce71120 100644 --- a/exchanges/coinbene/coinbene_test.go +++ b/exchanges/coinbene/coinbene_test.go @@ -34,7 +34,11 @@ func TestMain(m *testing.M) { coinbeneConfig.API.AuthenticatedSupport = true coinbeneConfig.API.Credentials.Secret = testAPISecret coinbeneConfig.API.Credentials.Key = testAPIKey - c.Setup(coinbeneConfig) + + err = c.Setup(coinbeneConfig) + if err != nil { + log.Fatal(err) + } os.Exit(m.Run()) } diff --git a/exchanges/coinut/coinut_wrapper.go b/exchanges/coinut/coinut_wrapper.go index 75779a484a6..c5c3e03e314 100644 --- a/exchanges/coinut/coinut_wrapper.go +++ b/exchanges/coinut/coinut_wrapper.go @@ -421,9 +421,7 @@ func (c *COINUT) UpdateOrderbook(p currency.Pair, assetType asset.Item) (orderbo // GetFundingHistory returns funding history, deposits and // withdrawals func (c *COINUT) GetFundingHistory() ([]exchange.FundHistory, error) { - var fundHistory []exchange.FundHistory - - return fundHistory, common.ErrFunctionNotSupported + return nil, common.ErrFunctionNotSupported } // GetExchangeHistory returns historic trade data since exchange opening. diff --git a/exchanges/exchange.go b/exchanges/exchange.go index 42cac14315c..4932817e604 100644 --- a/exchanges/exchange.go +++ b/exchanges/exchange.go @@ -755,10 +755,10 @@ func (e *Base) FormatWithdrawPermissions() string { return NoAPIWithdrawalMethodsText } -// IsAssetTypeSupported whether or not the supplied asset is supported +// SupportsAsset whether or not the supplied asset is supported // by the exchange -func (e *Base) IsAssetTypeSupported(asset asset.Item) bool { - return e.CurrencyPairs.AssetTypes.Contains(asset) +func (e *Base) SupportsAsset(a asset.Item) bool { + return e.CurrencyPairs.AssetTypes.Contains(a) } // PrintEnabledPairs prints the exchanges enabled asset pairs diff --git a/exchanges/exchange_test.go b/exchanges/exchange_test.go index 5aab5f4ab7b..b070e27b474 100644 --- a/exchanges/exchange_test.go +++ b/exchanges/exchange_test.go @@ -550,7 +550,7 @@ func TestGetEnabledPairs(t *testing.T) { } b.CurrencyPairs.StorePairs(asset.Spot, - currency.NewPairsFromStrings([]string{"BTC-USD"}), true) + currency.NewPairsFromStrings([]string{defaultTestCurrencyPair}), true) format := currency.PairFormat{ Delimiter: "-", Index: "", @@ -1321,18 +1321,16 @@ func TestFormatWithdrawPermissions(t *testing.T) { } } -func TestIsAssetTypeSupported(t *testing.T) { +func TestSupportsAsset(t *testing.T) { t.Parallel() - var b Base b.CurrencyPairs.AssetTypes = asset.Items{ asset.Spot, } - - if !b.IsAssetTypeSupported(asset.Spot) { + if !b.SupportsAsset(asset.Spot) { t.Error("spot should be supported") } - if b.IsAssetTypeSupported(asset.Index) { + if b.SupportsAsset(asset.Index) { t.Error("index shouldn't be supported") } } diff --git a/exchanges/exmo/exmo_wrapper.go b/exchanges/exmo/exmo_wrapper.go index c2b79d2b6a0..e228fc7a0c4 100644 --- a/exchanges/exmo/exmo_wrapper.go +++ b/exchanges/exmo/exmo_wrapper.go @@ -313,8 +313,7 @@ func (e *EXMO) GetAccountInfo() (exchange.AccountInfo, error) { // GetFundingHistory returns funding history, deposits and // withdrawals func (e *EXMO) GetFundingHistory() ([]exchange.FundHistory, error) { - var fundHistory []exchange.FundHistory - return fundHistory, common.ErrFunctionNotSupported + return nil, common.ErrFunctionNotSupported } // GetExchangeHistory returns historic trade data since exchange opening. diff --git a/exchanges/gateio/gateio_wrapper.go b/exchanges/gateio/gateio_wrapper.go index f3d894fd7a6..91970c940b5 100644 --- a/exchanges/gateio/gateio_wrapper.go +++ b/exchanges/gateio/gateio_wrapper.go @@ -277,13 +277,17 @@ func (g *Gateio) UpdateOrderbook(p currency.Pair, assetType asset.Item) (orderbo } for x := range orderbookNew.Bids { - data := orderbookNew.Bids[x] - orderBook.Bids = append(orderBook.Bids, orderbook.Item{Amount: data.Amount, Price: data.Price}) + orderBook.Bids = append(orderBook.Bids, orderbook.Item{ + Amount: orderbookNew.Bids[x].Amount, + Price: orderbookNew.Bids[x].Price, + }) } for x := range orderbookNew.Asks { - data := orderbookNew.Asks[x] - orderBook.Asks = append(orderBook.Asks, orderbook.Item{Amount: data.Amount, Price: data.Price}) + orderBook.Asks = append(orderBook.Asks, orderbook.Item{ + Amount: orderbookNew.Asks[x].Amount, + Price: orderbookNew.Asks[x].Price, + }) } orderBook.Pair = p @@ -366,8 +370,7 @@ func (g *Gateio) GetAccountInfo() (exchange.AccountInfo, error) { // GetFundingHistory returns funding history, deposits and // withdrawals func (g *Gateio) GetFundingHistory() ([]exchange.FundHistory, error) { - var fundHistory []exchange.FundHistory - return fundHistory, common.ErrFunctionNotSupported + return nil, common.ErrFunctionNotSupported } // GetExchangeHistory returns historic trade data since exchange opening. diff --git a/exchanges/gemini/gemini_test.go b/exchanges/gemini/gemini_test.go index 9681a402041..dec36bab70f 100644 --- a/exchanges/gemini/gemini_test.go +++ b/exchanges/gemini/gemini_test.go @@ -91,7 +91,11 @@ func TestGetAuctionHistory(t *testing.T) { func TestNewOrder(t *testing.T) { t.Parallel() - _, err := g.NewOrder(testCurrency, 1, 9000, "buy", "exchange limit") + _, err := g.NewOrder(testCurrency, + 1, + 9000000, + order.Sell.Lower(), + "exchange limit") if err != nil && mockTests { t.Error("NewOrder() error", err) } else if err == nil && !mockTests { diff --git a/exchanges/gemini/gemini_wrapper.go b/exchanges/gemini/gemini_wrapper.go index 1596393dea9..16e66d45aee 100644 --- a/exchanges/gemini/gemini_wrapper.go +++ b/exchanges/gemini/gemini_wrapper.go @@ -307,8 +307,7 @@ func (g *Gemini) UpdateOrderbook(p currency.Pair, assetType asset.Item) (orderbo // GetFundingHistory returns funding history, deposits and // withdrawals func (g *Gemini) GetFundingHistory() ([]exchange.FundHistory, error) { - var fundHistory []exchange.FundHistory - return fundHistory, common.ErrFunctionNotSupported + return nil, common.ErrFunctionNotSupported } // GetExchangeHistory returns historic trade data since exchange opening. diff --git a/exchanges/hitbtc/hitbtc_websocket.go b/exchanges/hitbtc/hitbtc_websocket.go index 99d7c2962c2..ea0cf2fd9f1 100644 --- a/exchanges/hitbtc/hitbtc_websocket.go +++ b/exchanges/hitbtc/hitbtc_websocket.go @@ -232,22 +232,23 @@ func (h *HitBTC) WsProcessOrderbookSnapshot(ob WsOrderbook) error { return errors.New("hitbtc.go error - no orderbooks to process") } - var bids []orderbook.Item + var newOrderBook orderbook.Base for i := range ob.Params.Bid { - bids = append(bids, orderbook.Item{Amount: ob.Params.Bid[i].Size, Price: ob.Params.Bid[i].Price}) + newOrderBook.Bids = append(newOrderBook.Bids, orderbook.Item{ + Amount: ob.Params.Bid[i].Size, + Price: ob.Params.Bid[i].Price, + }) } - var asks []orderbook.Item for i := range ob.Params.Ask { - asks = append(asks, orderbook.Item{Amount: ob.Params.Ask[i].Size, Price: ob.Params.Ask[i].Price}) + newOrderBook.Asks = append(newOrderBook.Asks, orderbook.Item{ + Amount: ob.Params.Ask[i].Size, + Price: ob.Params.Ask[i].Price, + }) } p := currency.NewPairFromFormattedPairs(ob.Params.Symbol, h.GetEnabledPairs(asset.Spot), h.GetPairFormat(asset.Spot, true)) - - var newOrderBook orderbook.Base - newOrderBook.Asks = asks - newOrderBook.Bids = bids newOrderBook.AssetType = asset.Spot newOrderBook.Pair = p newOrderBook.ExchangeName = h.Name @@ -274,11 +275,17 @@ func (h *HitBTC) WsProcessOrderbookUpdate(update WsOrderbook) error { var bids, asks []orderbook.Item for i := range update.Params.Bid { - bids = append(bids, orderbook.Item{Price: update.Params.Bid[i].Price, Amount: update.Params.Bid[i].Size}) + bids = append(bids, orderbook.Item{ + Price: update.Params.Bid[i].Price, + Amount: update.Params.Bid[i].Size, + }) } for i := range update.Params.Ask { - asks = append(asks, orderbook.Item{Price: update.Params.Ask[i].Price, Amount: update.Params.Ask[i].Size}) + asks = append(asks, orderbook.Item{ + Price: update.Params.Ask[i].Price, + Amount: update.Params.Ask[i].Size, + }) } p := currency.NewPairFromFormattedPairs(update.Params.Symbol, diff --git a/exchanges/hitbtc/hitbtc_wrapper.go b/exchanges/hitbtc/hitbtc_wrapper.go index 98fe7b7a890..bd82336428e 100644 --- a/exchanges/hitbtc/hitbtc_wrapper.go +++ b/exchanges/hitbtc/hitbtc_wrapper.go @@ -309,13 +309,17 @@ func (h *HitBTC) UpdateOrderbook(currencyPair currency.Pair, assetType asset.Ite } for x := range orderbookNew.Bids { - data := orderbookNew.Bids[x] - orderBook.Bids = append(orderBook.Bids, orderbook.Item{Amount: data.Amount, Price: data.Price}) + orderBook.Bids = append(orderBook.Bids, orderbook.Item{ + Amount: orderbookNew.Bids[x].Amount, + Price: orderbookNew.Bids[x].Price, + }) } for x := range orderbookNew.Asks { - data := orderbookNew.Asks[x] - orderBook.Asks = append(orderBook.Asks, orderbook.Item{Amount: data.Amount, Price: data.Price}) + orderBook.Asks = append(orderBook.Asks, orderbook.Item{ + Amount: orderbookNew.Asks[x].Amount, + Price: orderbookNew.Asks[x].Price, + }) } orderBook.Pair = currencyPair @@ -360,8 +364,7 @@ func (h *HitBTC) GetAccountInfo() (exchange.AccountInfo, error) { // GetFundingHistory returns funding history, deposits and // withdrawals func (h *HitBTC) GetFundingHistory() ([]exchange.FundHistory, error) { - var fundHistory []exchange.FundHistory - return fundHistory, common.ErrFunctionNotSupported + return nil, common.ErrFunctionNotSupported } // GetExchangeHistory returns historic trade data since exchange opening. @@ -379,8 +382,8 @@ func (h *HitBTC) SubmitOrder(s *order.Submit) (order.SubmitResponse, error) { response, err := h.PlaceOrder(s.Pair.String(), s.Price, s.Amount, - strings.ToLower(s.OrderType.String()), - strings.ToLower(s.OrderSide.String())) + s.OrderType.Lower(), + s.OrderSide.Lower()) if response.OrderNumber > 0 { submitOrderResponse.OrderID = strconv.FormatInt(response.OrderNumber, 10) } diff --git a/exchanges/huobi/huobi_wrapper.go b/exchanges/huobi/huobi_wrapper.go index bc91885268d..e83c5e8be4c 100644 --- a/exchanges/huobi/huobi_wrapper.go +++ b/exchanges/huobi/huobi_wrapper.go @@ -4,7 +4,6 @@ import ( "errors" "fmt" "strconv" - "strings" "sync" "time" @@ -350,13 +349,17 @@ func (h *HUOBI) UpdateOrderbook(p currency.Pair, assetType asset.Item) (orderboo } for x := range orderbookNew.Bids { - data := orderbookNew.Bids[x] - orderBook.Bids = append(orderBook.Bids, orderbook.Item{Amount: data[1], Price: data[0]}) + orderBook.Bids = append(orderBook.Bids, orderbook.Item{ + Amount: orderbookNew.Bids[x][1], + Price: orderbookNew.Bids[x][0], + }) } for x := range orderbookNew.Asks { - data := orderbookNew.Asks[x] - orderBook.Asks = append(orderBook.Asks, orderbook.Item{Amount: data[1], Price: data[0]}) + orderBook.Asks = append(orderBook.Asks, orderbook.Item{ + Amount: orderbookNew.Asks[x][1], + Price: orderbookNew.Asks[x][0], + }) } orderBook.Pair = p @@ -452,8 +455,7 @@ func (h *HUOBI) GetAccountInfo() (exchange.AccountInfo, error) { // GetFundingHistory returns funding history, deposits and // withdrawals func (h *HUOBI) GetFundingHistory() ([]exchange.FundHistory, error) { - var fundHistory []exchange.FundHistory - return fundHistory, common.ErrFunctionNotSupported + return nil, common.ErrFunctionNotSupported } // GetExchangeHistory returns historic trade data since exchange opening. @@ -600,7 +602,7 @@ func (h *HUOBI) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, er if req.OrderSide == order.AnySide || req.OrderSide == "" { side = "" } else if req.OrderSide == order.Sell { - side = strings.ToLower(string(req.OrderSide)) + side = req.OrderSide.Lower() } var orders []order.Detail diff --git a/exchanges/interfaces.go b/exchanges/interfaces.go index d90ce72648d..3f5723e30fc 100644 --- a/exchanges/interfaces.go +++ b/exchanges/interfaces.go @@ -66,4 +66,5 @@ type IBotExchange interface { GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error) GetDefaultConfig() (*config.ExchangeConfig, error) GetBase() *Base + SupportsAsset(assetType asset.Item) bool } diff --git a/exchanges/itbit/itbit_wrapper.go b/exchanges/itbit/itbit_wrapper.go index a10a6a09d1b..1168ebc41f5 100644 --- a/exchanges/itbit/itbit_wrapper.go +++ b/exchanges/itbit/itbit_wrapper.go @@ -193,13 +193,12 @@ func (i *ItBit) UpdateOrderbook(p currency.Pair, assetType asset.Item) (orderboo } for x := range orderbookNew.Bids { - data := orderbookNew.Bids[x] var price, amount float64 - price, err = strconv.ParseFloat(data[0], 64) + price, err = strconv.ParseFloat(orderbookNew.Bids[x][0], 64) if err != nil { return orderBook, err } - amount, err = strconv.ParseFloat(data[1], 64) + amount, err = strconv.ParseFloat(orderbookNew.Bids[x][1], 64) if err != nil { return orderBook, err } @@ -211,13 +210,12 @@ func (i *ItBit) UpdateOrderbook(p currency.Pair, assetType asset.Item) (orderboo } for x := range orderbookNew.Asks { - data := orderbookNew.Asks[x] var price, amount float64 - price, err = strconv.ParseFloat(data[0], 64) + price, err = strconv.ParseFloat(orderbookNew.Asks[x][0], 64) if err != nil { return orderBook, err } - amount, err = strconv.ParseFloat(data[1], 64) + amount, err = strconv.ParseFloat(orderbookNew.Asks[x][1], 64) if err != nil { return orderBook, err } @@ -287,8 +285,7 @@ func (i *ItBit) GetAccountInfo() (exchange.AccountInfo, error) { // GetFundingHistory returns funding history, deposits and // withdrawals func (i *ItBit) GetFundingHistory() ([]exchange.FundHistory, error) { - var fundHistory []exchange.FundHistory - return fundHistory, common.ErrFunctionNotSupported + return nil, common.ErrFunctionNotSupported } // GetExchangeHistory returns historic trade data since exchange opening. @@ -444,7 +441,7 @@ func (i *ItBit) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, er side := order.Side(strings.ToUpper(allOrders[j].Side)) orderDate, err := time.Parse(time.RFC3339, allOrders[j].CreatedTime) if err != nil { - log.Warnf(log.ExchangeSys, + log.Errorf(log.ExchangeSys, "Exchange %v Func %v Order %v Could not parse date to unix with value of %v", i.Name, "GetActiveOrders", @@ -498,7 +495,7 @@ func (i *ItBit) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, er side := order.Side(strings.ToUpper(allOrders[j].Side)) orderDate, err := time.Parse(time.RFC3339, allOrders[j].CreatedTime) if err != nil { - log.Warnf(log.ExchangeSys, + log.Errorf(log.ExchangeSys, "Exchange %v Func %v Order %v Could not parse date to unix with value of %v", i.Name, "GetActiveOrders", diff --git a/exchanges/kraken/kraken_wrapper.go b/exchanges/kraken/kraken_wrapper.go index b4282ea1a60..2831e76033f 100644 --- a/exchanges/kraken/kraken_wrapper.go +++ b/exchanges/kraken/kraken_wrapper.go @@ -386,8 +386,7 @@ func (k *Kraken) GetAccountInfo() (exchange.AccountInfo, error) { // GetFundingHistory returns funding history, deposits and // withdrawals func (k *Kraken) GetFundingHistory() ([]exchange.FundHistory, error) { - var fundHistory []exchange.FundHistory - return fundHistory, common.ErrFunctionNotSupported + return nil, common.ErrFunctionNotSupported } // GetExchangeHistory returns historic trade data since exchange opening. diff --git a/exchanges/lakebtc/lakebtc_websocket.go b/exchanges/lakebtc/lakebtc_websocket.go index af662d9cdf6..81879957ce2 100644 --- a/exchanges/lakebtc/lakebtc_websocket.go +++ b/exchanges/lakebtc/lakebtc_websocket.go @@ -10,6 +10,7 @@ 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/websocket/wshandler" log "github.com/thrasher-corp/gocryptotrader/logger" @@ -21,11 +22,9 @@ const ( marketGlobalEndpoint = "market-global" marketSubstring = "market-" globalSubstring = "-global" - tickerBuyString = "buy" tickerHighString = "high" tickerLastString = "last" tickerLowString = "low" - tickerSellString = "sell" tickerVolumeString = "volume" wssSchem = "wss" ) @@ -270,11 +269,11 @@ func (l *LakeBTC) processTicker(ticker string) error { l.Websocket.DataHandler <- wshandler.TickerData{ Exchange: l.Name, - Bid: processTickerItem(tickerData, tickerBuyString), + Bid: processTickerItem(tickerData, order.Buy.Lower()), High: processTickerItem(tickerData, tickerHighString), Last: processTickerItem(tickerData, tickerLastString), Low: processTickerItem(tickerData, tickerLowString), - Ask: processTickerItem(tickerData, tickerSellString), + Ask: processTickerItem(tickerData, order.Sell.Lower()), Volume: processTickerItem(tickerData, tickerVolumeString), AssetType: asset.Spot, Pair: returnCurrency, diff --git a/exchanges/lakebtc/lakebtc_wrapper.go b/exchanges/lakebtc/lakebtc_wrapper.go index a46f184f9ce..3be7eb82849 100644 --- a/exchanges/lakebtc/lakebtc_wrapper.go +++ b/exchanges/lakebtc/lakebtc_wrapper.go @@ -316,8 +316,7 @@ func (l *LakeBTC) GetAccountInfo() (exchange.AccountInfo, error) { // GetFundingHistory returns funding history, deposits and // withdrawals func (l *LakeBTC) GetFundingHistory() ([]exchange.FundHistory, error) { - var fundHistory []exchange.FundHistory - return fundHistory, common.ErrFunctionNotSupported + return nil, common.ErrFunctionNotSupported } // GetExchangeHistory returns historic trade data since exchange opening. diff --git a/exchanges/lbank/README.md b/exchanges/lbank/README.md index 8e025ed5905..78e67672e9b 100644 --- a/exchanges/lbank/README.md +++ b/exchanges/lbank/README.md @@ -47,22 +47,22 @@ main.go ```go var l exchange.IBotExchange -for i := range bot.exchanges { - if bot.exchanges[i].GetName() == "Lbank" { - l = bot.exchanges[i] +for i := range Bot.Exchanges { + if Bot.Exchanges[i].GetName() == "Lbank" { + l = Bot.Exchanges[i] } } // Public calls - wrapper functions // Fetches current ticker information -tick, err := l.GetTickerPrice() +tick, err := l.FetchTicker() if err != nil { // Handle error } // Fetches current orderbook information -ob, err := l.GetOrderbookEx() +ob, err := l.FetchOrderbook() if err != nil { // Handle error } diff --git a/exchanges/lbank/lbank.go b/exchanges/lbank/lbank.go index 143c51a1c4c..f7f7322b48f 100644 --- a/exchanges/lbank/lbank.go +++ b/exchanges/lbank/lbank.go @@ -17,6 +17,7 @@ import ( gctcrypto "github.com/thrasher-corp/gocryptotrader/common/crypto" exchange "github.com/thrasher-corp/gocryptotrader/exchanges" + "github.com/thrasher-corp/gocryptotrader/exchanges/order" "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wshandler" ) @@ -195,7 +196,8 @@ func (l *Lbank) GetUserInfo() (InfoFinalResponse, error) { // CreateOrder creates an order func (l *Lbank) CreateOrder(pair, side string, amount, price float64) (CreateOrderResponse, error) { var resp CreateOrderResponse - if !strings.EqualFold(side, "buy") && !strings.EqualFold(side, "sell") { + if !strings.EqualFold(side, order.Buy.String()) && + !strings.EqualFold(side, order.Sell.String()) { return resp, errors.New("side type invalid can only be 'buy' or 'sell'") } if amount <= 0 { @@ -546,6 +548,10 @@ func (l *Lbank) sign(data string) (string, error) { // SendAuthHTTPRequest sends an authenticated request func (l *Lbank) SendAuthHTTPRequest(method, endpoint string, vals url.Values, result interface{}) error { + if !l.AllowAuthenticatedRequest() { + return fmt.Errorf(exchange.WarningAuthenticatedRequestWithoutCredentialsSet, l.Name) + } + if vals == nil { vals = url.Values{} } diff --git a/exchanges/lbank/lbank_wrapper.go b/exchanges/lbank/lbank_wrapper.go index 24e9e649910..e9fbd8b3971 100644 --- a/exchanges/lbank/lbank_wrapper.go +++ b/exchanges/lbank/lbank_wrapper.go @@ -407,7 +407,7 @@ func (l *Lbank) GetOrderInfo(orderID string) (order.Detail, error) { } resp.Exchange = l.Name resp.CurrencyPair = currency.NewPairFromString(key) - if strings.EqualFold(tempResp.Orders[0].Type, "buy") { + if strings.EqualFold(tempResp.Orders[0].Type, order.Buy.String()) { resp.OrderSide = order.Buy } else { resp.OrderSide = order.Sell @@ -491,7 +491,7 @@ func (l *Lbank) GetActiveOrders(getOrdersRequest *order.GetOrdersRequest) ([]ord } resp.Exchange = l.Name resp.CurrencyPair = currency.NewPairFromString(key) - if strings.EqualFold(tempResp.Orders[0].Type, "buy") { + if strings.EqualFold(tempResp.Orders[0].Type, order.Buy.String()) { resp.OrderSide = order.Buy } else { resp.OrderSide = order.Sell @@ -567,7 +567,7 @@ func (l *Lbank) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest) ([]ord for x := 0; x < len(tempResp.Orders); x++ { resp.Exchange = l.Name resp.CurrencyPair = currency.NewPairFromString(tempResp.Orders[x].Symbol) - if strings.EqualFold(tempResp.Orders[x].Type, "buy") { + if strings.EqualFold(tempResp.Orders[x].Type, order.Buy.String()) { resp.OrderSide = order.Buy } else { resp.OrderSide = order.Sell diff --git a/exchanges/localbitcoins/localbitcoins_wrapper.go b/exchanges/localbitcoins/localbitcoins_wrapper.go index e03ac508f52..1e1bf0a2778 100644 --- a/exchanges/localbitcoins/localbitcoins_wrapper.go +++ b/exchanges/localbitcoins/localbitcoins_wrapper.go @@ -218,13 +218,17 @@ func (l *LocalBitcoins) UpdateOrderbook(p currency.Pair, assetType asset.Item) ( } for x := range orderbookNew.Bids { - data := orderbookNew.Bids[x] - orderBook.Bids = append(orderBook.Bids, orderbook.Item{Amount: data.Amount / data.Price, Price: data.Price}) + orderBook.Bids = append(orderBook.Bids, orderbook.Item{ + Amount: orderbookNew.Bids[x].Amount / orderbookNew.Bids[x].Price, + Price: orderbookNew.Bids[x].Price, + }) } for x := range orderbookNew.Asks { - data := orderbookNew.Asks[x] - orderBook.Asks = append(orderBook.Asks, orderbook.Item{Amount: data.Amount / data.Price, Price: data.Price}) + orderBook.Asks = append(orderBook.Asks, orderbook.Item{ + Amount: orderbookNew.Asks[x].Amount / orderbookNew.Asks[x].Price, + Price: orderbookNew.Asks[x].Price, + }) } orderBook.Pair = p @@ -261,8 +265,7 @@ func (l *LocalBitcoins) GetAccountInfo() (exchange.AccountInfo, error) { // GetFundingHistory returns funding history, deposits and // withdrawals func (l *LocalBitcoins) GetFundingHistory() ([]exchange.FundHistory, error) { - var fundHistory []exchange.FundHistory - return fundHistory, common.ErrFunctionNotSupported + return nil, common.ErrFunctionNotSupported } // GetExchangeHistory returns historic trade data since exchange opening. @@ -434,7 +437,7 @@ func (l *LocalBitcoins) GetActiveOrders(getOrdersRequest *order.GetOrdersRequest for i := range resp { orderDate, err := time.Parse(time.RFC3339, resp[i].Data.CreatedAt) if err != nil { - log.Warnf(log.ExchangeSys, "Exchange %v Func %v Order %v Could not parse date to unix with value of %v", + log.Errorf(log.ExchangeSys, "Exchange %v Func %v Order %v Could not parse date to unix with value of %v", l.Name, "GetActiveOrders", resp[i].Data.Advertisement.ID, @@ -495,7 +498,7 @@ func (l *LocalBitcoins) GetOrderHistory(getOrdersRequest *order.GetOrdersRequest for i := range allTrades { orderDate, err := time.Parse(time.RFC3339, allTrades[i].Data.CreatedAt) if err != nil { - log.Warnf(log.ExchangeSys, + log.Errorf(log.ExchangeSys, "Exchange %v Func %v Order %v Could not parse date to unix with value of %v", l.Name, "GetActiveOrders", diff --git a/exchanges/okcoin/okcoin_test.go b/exchanges/okcoin/okcoin_test.go index 19849b0bd82..5c57708c70d 100644 --- a/exchanges/okcoin/okcoin_test.go +++ b/exchanges/okcoin/okcoin_test.go @@ -146,7 +146,7 @@ func TestGetAccountWalletInformationForCurrency(t *testing.T) { func TestTransferAccountFunds(t *testing.T) { TestSetRealOrderDefaults(t) request := okgroup.TransferAccountFundsRequest{ - Amount: 10, + Amount: -10, Currency: currency.BTC.String(), From: 6, To: 1, @@ -159,7 +159,7 @@ func TestTransferAccountFunds(t *testing.T) { func TestAccountWithdrawRequest(t *testing.T) { TestSetRealOrderDefaults(t) request := okgroup.AccountWithdrawRequest{ - Amount: 10, + Amount: -10, Currency: currency.BTC.String(), TradePwd: "1234", Destination: 4, @@ -285,13 +285,12 @@ func TestGetSpotBillDetailsForCurrencyBadLimit(t *testing.T) { // TestPlaceSpotOrderLimit API endpoint test func TestPlaceSpotOrderLimit(t *testing.T) { TestSetRealOrderDefaults(t) - request := okgroup.PlaceSpotOrderRequest{ - InstrumentID: spotCurrency, - Type: order.Limit.Lower(), - Side: order.Buy.Lower(), - MarginTrading: "1", - Price: "100", - Size: "100", + request := okgroup.PlaceOrderRequest{ + InstrumentID: spotCurrency, + Type: order.Limit.Lower(), + Side: order.Buy.Lower(), + Price: "-100", + Size: "100", } _, err := o.PlaceSpotOrder(&request) @@ -301,13 +300,12 @@ func TestPlaceSpotOrderLimit(t *testing.T) { // TestPlaceSpotOrderMarket API endpoint test func TestPlaceSpotOrderMarket(t *testing.T) { TestSetRealOrderDefaults(t) - request := okgroup.PlaceSpotOrderRequest{ - InstrumentID: spotCurrency, - Type: order.Market.Lower(), - Side: order.Buy.Lower(), - MarginTrading: "1", - Size: "-100", - Notional: "100", + request := okgroup.PlaceOrderRequest{ + InstrumentID: spotCurrency, + Type: order.Market.Lower(), + Side: order.Buy.Lower(), + Size: "-100", + Notional: "100", } _, err := o.PlaceSpotOrder(&request) @@ -317,16 +315,15 @@ func TestPlaceSpotOrderMarket(t *testing.T) { // TestPlaceMultipleSpotOrders API endpoint test func TestPlaceMultipleSpotOrders(t *testing.T) { TestSetRealOrderDefaults(t) - order := okgroup.PlaceSpotOrderRequest{ - InstrumentID: spotCurrency, - Type: order.Limit.Lower(), - Side: order.Buy.Lower(), - MarginTrading: "1", - Size: "100", - Notional: "100", + order := okgroup.PlaceOrderRequest{ + InstrumentID: spotCurrency, + Type: order.Limit.Lower(), + Side: order.Buy.Lower(), + Size: "-100", + Price: "1", } - request := []okgroup.PlaceSpotOrderRequest{ + request := []okgroup.PlaceOrderRequest{ order, } @@ -339,16 +336,15 @@ func TestPlaceMultipleSpotOrders(t *testing.T) { // TestPlaceMultipleSpotOrdersOverCurrencyLimits API logic test func TestPlaceMultipleSpotOrdersOverCurrencyLimits(t *testing.T) { TestSetDefaults(t) - order := okgroup.PlaceSpotOrderRequest{ - InstrumentID: spotCurrency, - Type: order.Limit.Lower(), - Side: order.Buy.Lower(), - MarginTrading: "1", - Size: "100", - Notional: "100", + order := okgroup.PlaceOrderRequest{ + InstrumentID: spotCurrency, + Type: order.Limit.Lower(), + Side: order.Buy.Lower(), + Size: "-100", + Price: "1", } - request := []okgroup.PlaceSpotOrderRequest{ + request := []okgroup.PlaceOrderRequest{ order, order, order, @@ -365,27 +361,29 @@ func TestPlaceMultipleSpotOrdersOverCurrencyLimits(t *testing.T) { // TestPlaceMultipleSpotOrdersOverPairLimits API logic test func TestPlaceMultipleSpotOrdersOverPairLimits(t *testing.T) { TestSetDefaults(t) - order := okgroup.PlaceSpotOrderRequest{ - InstrumentID: spotCurrency, - Type: order.Limit.Lower(), - Side: order.Buy.Lower(), - MarginTrading: "1", - Size: "100", - Notional: "100", + order := okgroup.PlaceOrderRequest{ + InstrumentID: spotCurrency, + Type: order.Limit.Lower(), + Side: order.Buy.Lower(), + Size: "-100", + Price: "1", } - request := []okgroup.PlaceSpotOrderRequest{ + request := []okgroup.PlaceOrderRequest{ order, } - order.InstrumentID = currency.NewPairWithDelimiter(currency.LTC.String(), currency.USD.String(), "-").Lower().String() - request = append(request, order) - order.InstrumentID = currency.NewPairWithDelimiter(currency.DOGE.String(), currency.USD.String(), "-").Lower().String() - request = append(request, order) - order.InstrumentID = currency.NewPairWithDelimiter(currency.XMR.String(), currency.USD.String(), "-").Lower().String() - request = append(request, order) - order.InstrumentID = currency.NewPairWithDelimiter(currency.BCH.String(), currency.USD.String(), "-").Lower().String() - request = append(request, order) + pairs := currency.Pairs{ + currency.NewPair(currency.LTC, currency.USDT), + currency.NewPair(currency.ETH, currency.USDT), + currency.NewPair(currency.BCH, currency.USDT), + currency.NewPair(currency.XMR, currency.USDT), + } + + for x := range pairs { + order.InstrumentID = pairs[x].Format("-", false).String() + request = append(request, order) + } _, errs := o.PlaceMultipleSpotOrders(request) if errs[0].Error() != "up to 4 trading pairs" { @@ -574,7 +572,7 @@ func TestGetMarginAccountSettingsForCurrency(t *testing.T) { func TestOpenMarginLoan(t *testing.T) { TestSetRealOrderDefaults(t) request := okgroup.OpenMarginLoanRequest{ - Amount: 100, + Amount: -100, InstrumentID: spotCurrency, QuoteCurrency: currency.USD.String(), } @@ -587,7 +585,7 @@ func TestOpenMarginLoan(t *testing.T) { func TestRepayMarginLoan(t *testing.T) { TestSetRealOrderDefaults(t) request := okgroup.RepayMarginLoanRequest{ - Amount: 100, + Amount: -100, InstrumentID: spotCurrency, QuoteCurrency: currency.USD.String(), BorrowID: 1, @@ -600,12 +598,12 @@ func TestRepayMarginLoan(t *testing.T) { // TestPlaceMarginOrderLimit API endpoint test func TestPlaceMarginOrderLimit(t *testing.T) { TestSetRealOrderDefaults(t) - request := okgroup.PlaceSpotOrderRequest{ + request := okgroup.PlaceOrderRequest{ InstrumentID: spotCurrency, Type: order.Limit.Lower(), Side: order.Buy.Lower(), MarginTrading: "2", - Price: "100", + Price: "-100", Size: "100", } @@ -616,7 +614,7 @@ func TestPlaceMarginOrderLimit(t *testing.T) { // TestPlaceMarginOrderMarket API endpoint test func TestPlaceMarginOrderMarket(t *testing.T) { TestSetRealOrderDefaults(t) - request := okgroup.PlaceSpotOrderRequest{ + request := okgroup.PlaceOrderRequest{ InstrumentID: spotCurrency, Type: order.Market.Lower(), Side: order.Buy.Lower(), @@ -632,16 +630,16 @@ func TestPlaceMarginOrderMarket(t *testing.T) { // TestPlaceMultipleMarginOrders API endpoint test func TestPlaceMultipleMarginOrders(t *testing.T) { TestSetRealOrderDefaults(t) - order := okgroup.PlaceSpotOrderRequest{ + order := okgroup.PlaceOrderRequest{ InstrumentID: spotCurrency, Type: order.Limit.Lower(), Side: order.Buy.Lower(), MarginTrading: "1", - Size: "100", + Size: "-100", Notional: "100", } - request := []okgroup.PlaceSpotOrderRequest{ + request := []okgroup.PlaceOrderRequest{ order, } @@ -654,16 +652,16 @@ func TestPlaceMultipleMarginOrders(t *testing.T) { // TestPlaceMultipleMarginOrdersOverCurrencyLimits API logic test func TestPlaceMultipleMarginOrdersOverCurrencyLimits(t *testing.T) { TestSetDefaults(t) - order := okgroup.PlaceSpotOrderRequest{ + order := okgroup.PlaceOrderRequest{ InstrumentID: spotCurrency, Type: order.Limit.Lower(), Side: order.Buy.Lower(), MarginTrading: "1", - Size: "100", + Size: "-100", Notional: "100", } - request := []okgroup.PlaceSpotOrderRequest{ + request := []okgroup.PlaceOrderRequest{ order, order, order, @@ -680,27 +678,30 @@ func TestPlaceMultipleMarginOrdersOverCurrencyLimits(t *testing.T) { // TestPlaceMultipleMarginOrdersOverPairLimits API logic test func TestPlaceMultipleMarginOrdersOverPairLimits(t *testing.T) { TestSetDefaults(t) - order := okgroup.PlaceSpotOrderRequest{ + order := okgroup.PlaceOrderRequest{ InstrumentID: spotCurrency, Type: order.Limit.Lower(), Side: order.Buy.Lower(), MarginTrading: "1", - Size: "100", + Size: "-100", Notional: "100", } - request := []okgroup.PlaceSpotOrderRequest{ + request := []okgroup.PlaceOrderRequest{ order, } - order.InstrumentID = currency.NewPairWithDelimiter(currency.LTC.String(), currency.USD.String(), "-").Lower().String() - request = append(request, order) - order.InstrumentID = currency.NewPairWithDelimiter(currency.DOGE.String(), currency.USD.String(), "-").Lower().String() - request = append(request, order) - order.InstrumentID = currency.NewPairWithDelimiter(currency.XMR.String(), currency.USD.String(), "-").Lower().String() - request = append(request, order) - order.InstrumentID = currency.NewPairWithDelimiter(currency.BCH.String(), currency.USD.String(), "-").Lower().String() - request = append(request, order) + pairs := currency.Pairs{ + currency.NewPair(currency.LTC, currency.USDT), + currency.NewPair(currency.ETH, currency.USDT), + currency.NewPair(currency.BCH, currency.USDT), + currency.NewPair(currency.XMR, currency.USDT), + } + + for x := range pairs { + order.InstrumentID = pairs[x].Format("-", false).String() + request = append(request, order) + } _, errs := o.PlaceMultipleMarginOrders(request) if errs[0].Error() != "up to 4 trading pairs" { @@ -1049,7 +1050,7 @@ func TestSubmitOrder(t *testing.T) { }, OrderSide: order.Buy, OrderType: order.Limit, - Price: 1, + Price: -1, Amount: 1, ClientID: "meowOrder", } diff --git a/exchanges/okex/okex_test.go b/exchanges/okex/okex_test.go index 8ae4cb938f8..f033e4c57eb 100644 --- a/exchanges/okex/okex_test.go +++ b/exchanges/okex/okex_test.go @@ -3,6 +3,7 @@ package okex import ( "fmt" "net/http" + "strconv" "strings" "sync" "testing" @@ -154,7 +155,7 @@ func TestTransferAccountFunds(t *testing.T) { Amount: 10, Currency: currency.BTC.String(), From: 6, - To: 1, + To: -1, } _, err := o.TransferAccountFunds(request) @@ -166,7 +167,7 @@ func TestAccountWithdrawRequest(t *testing.T) { TestSetRealOrderDefaults(t) t.Parallel() request := okgroup.AccountWithdrawRequest{ - Amount: 10, + Amount: -1, Currency: currency.BTC.String(), TradePwd: "1234", Destination: 4, @@ -306,13 +307,12 @@ func TestGetSpotBillDetailsForCurrencyBadLimit(t *testing.T) { func TestPlaceSpotOrderLimit(t *testing.T) { TestSetRealOrderDefaults(t) t.Parallel() - request := okgroup.PlaceSpotOrderRequest{ - InstrumentID: spotCurrency, - Type: order.Limit.Lower(), - Side: order.Buy.Lower(), - MarginTrading: "1", - Price: "100", - Size: "100", + request := okgroup.PlaceOrderRequest{ + InstrumentID: spotCurrency, + Type: order.Limit.Lower(), + Side: order.Buy.Lower(), + Price: "-1", + Size: "0.001", } _, err := o.PlaceSpotOrder(&request) @@ -323,13 +323,12 @@ func TestPlaceSpotOrderLimit(t *testing.T) { func TestPlaceSpotOrderMarket(t *testing.T) { TestSetRealOrderDefaults(t) t.Parallel() - request := okgroup.PlaceSpotOrderRequest{ - InstrumentID: spotCurrency, - Type: order.Market.Lower(), - Side: order.Buy.Lower(), - MarginTrading: "1", - Size: "-100", - Notional: "100", + request := okgroup.PlaceOrderRequest{ + InstrumentID: spotCurrency, + Type: order.Market.Lower(), + Side: order.Buy.Lower(), + Size: "-100", + Notional: "100", } _, err := o.PlaceSpotOrder(&request) @@ -340,16 +339,15 @@ func TestPlaceSpotOrderMarket(t *testing.T) { func TestPlaceMultipleSpotOrders(t *testing.T) { TestSetRealOrderDefaults(t) t.Parallel() - order := okgroup.PlaceSpotOrderRequest{ - InstrumentID: spotCurrency, - Type: order.Limit.Lower(), - Side: order.Buy.Lower(), - MarginTrading: "1", - Size: "100", - Notional: "100", + order := okgroup.PlaceOrderRequest{ + InstrumentID: spotCurrency, + Type: order.Limit.Lower(), + Side: order.Buy.Lower(), + Size: "-100", + Price: "1", } - request := []okgroup.PlaceSpotOrderRequest{ + request := []okgroup.PlaceOrderRequest{ order, } @@ -363,16 +361,15 @@ func TestPlaceMultipleSpotOrders(t *testing.T) { func TestPlaceMultipleSpotOrdersOverCurrencyLimits(t *testing.T) { TestSetDefaults(t) t.Parallel() - order := okgroup.PlaceSpotOrderRequest{ - InstrumentID: spotCurrency, - Type: order.Limit.Lower(), - Side: order.Buy.Lower(), - MarginTrading: "1", - Size: "100", - Notional: "100", + order := okgroup.PlaceOrderRequest{ + InstrumentID: spotCurrency, + Type: order.Limit.Lower(), + Side: order.Buy.Lower(), + Size: "-100", + Price: "1", } - request := []okgroup.PlaceSpotOrderRequest{ + request := []okgroup.PlaceOrderRequest{ order, order, order, @@ -390,27 +387,29 @@ func TestPlaceMultipleSpotOrdersOverCurrencyLimits(t *testing.T) { func TestPlaceMultipleSpotOrdersOverPairLimits(t *testing.T) { TestSetDefaults(t) t.Parallel() - order := okgroup.PlaceSpotOrderRequest{ - InstrumentID: spotCurrency, - Type: order.Limit.Lower(), - Side: order.Buy.Lower(), - MarginTrading: "1", - Size: "100", - Notional: "100", + order := okgroup.PlaceOrderRequest{ + InstrumentID: spotCurrency, + Type: order.Limit.Lower(), + Side: order.Buy.Lower(), + Size: "-1", + Price: "1", } - request := []okgroup.PlaceSpotOrderRequest{ + request := []okgroup.PlaceOrderRequest{ order, } - order.InstrumentID = currency.NewPairWithDelimiter(currency.LTC.String(), currency.USDT.String(), "-").Lower().String() - request = append(request, order) - order.InstrumentID = currency.NewPairWithDelimiter(currency.DOGE.String(), currency.USDT.String(), "-").Lower().String() - request = append(request, order) - order.InstrumentID = currency.NewPairWithDelimiter(currency.XMR.String(), currency.USDT.String(), "-").Lower().String() - request = append(request, order) - order.InstrumentID = currency.NewPairWithDelimiter(currency.BCH.String(), currency.USDT.String(), "-").Lower().String() - request = append(request, order) + pairs := currency.Pairs{ + currency.NewPair(currency.LTC, currency.USDT), + currency.NewPair(currency.ETH, currency.USDT), + currency.NewPair(currency.BCH, currency.USDT), + currency.NewPair(currency.XMR, currency.USDT), + } + + for x := range pairs { + order.InstrumentID = pairs[x].Format("-", false).String() + request = append(request, order) + } _, errs := o.PlaceMultipleSpotOrders(request) if errs[0].Error() != "up to 4 trading pairs" { @@ -619,7 +618,7 @@ func TestOpenMarginLoan(t *testing.T) { TestSetRealOrderDefaults(t) t.Parallel() request := okgroup.OpenMarginLoanRequest{ - Amount: 100, + Amount: -100, InstrumentID: spotCurrency, QuoteCurrency: currency.USDT.String(), } @@ -633,7 +632,7 @@ func TestRepayMarginLoan(t *testing.T) { TestSetRealOrderDefaults(t) t.Parallel() request := okgroup.RepayMarginLoanRequest{ - Amount: 100, + Amount: -100, InstrumentID: spotCurrency, QuoteCurrency: currency.USDT.String(), BorrowID: 1, @@ -647,13 +646,13 @@ func TestRepayMarginLoan(t *testing.T) { func TestPlaceMarginOrderLimit(t *testing.T) { TestSetRealOrderDefaults(t) t.Parallel() - request := okgroup.PlaceSpotOrderRequest{ - InstrumentID: spotCurrency, - Type: order.Limit.Lower(), - Side: order.Buy.Lower(), - MarginTrading: "2", - Price: "100", - Size: "100", + request := okgroup.PlaceOrderRequest{ + InstrumentID: spotCurrency, + Type: order.Limit.Lower(), + Side: order.Buy.Lower(), + OrderType: strconv.Itoa(okgroup.NormalOrder), + Price: "-100", + Size: "100", } _, err := o.PlaceMarginOrder(&request) @@ -664,7 +663,7 @@ func TestPlaceMarginOrderLimit(t *testing.T) { func TestPlaceMarginOrderMarket(t *testing.T) { TestSetRealOrderDefaults(t) t.Parallel() - request := okgroup.PlaceSpotOrderRequest{ + request := okgroup.PlaceOrderRequest{ InstrumentID: spotCurrency, Type: order.Market.Lower(), Side: order.Buy.Lower(), @@ -681,16 +680,16 @@ func TestPlaceMarginOrderMarket(t *testing.T) { func TestPlaceMultipleMarginOrders(t *testing.T) { TestSetRealOrderDefaults(t) t.Parallel() - order := okgroup.PlaceSpotOrderRequest{ + order := okgroup.PlaceOrderRequest{ InstrumentID: spotCurrency, Type: order.Limit.Lower(), Side: order.Buy.Lower(), MarginTrading: "1", - Size: "100", + Size: "-100", Notional: "100", } - request := []okgroup.PlaceSpotOrderRequest{ + request := []okgroup.PlaceOrderRequest{ order, } @@ -704,16 +703,16 @@ func TestPlaceMultipleMarginOrders(t *testing.T) { func TestPlaceMultipleMarginOrdersOverCurrencyLimits(t *testing.T) { TestSetDefaults(t) t.Parallel() - order := okgroup.PlaceSpotOrderRequest{ + order := okgroup.PlaceOrderRequest{ InstrumentID: spotCurrency, Type: order.Limit.Lower(), Side: order.Buy.Lower(), MarginTrading: "1", - Size: "100", + Size: "-100", Notional: "100", } - request := []okgroup.PlaceSpotOrderRequest{ + request := []okgroup.PlaceOrderRequest{ order, order, order, @@ -731,27 +730,30 @@ func TestPlaceMultipleMarginOrdersOverCurrencyLimits(t *testing.T) { func TestPlaceMultipleMarginOrdersOverPairLimits(t *testing.T) { TestSetDefaults(t) t.Parallel() - order := okgroup.PlaceSpotOrderRequest{ + order := okgroup.PlaceOrderRequest{ InstrumentID: spotCurrency, Type: order.Limit.Lower(), Side: order.Buy.Lower(), MarginTrading: "1", - Size: "100", + Size: "-100", Notional: "100", } - request := []okgroup.PlaceSpotOrderRequest{ + request := []okgroup.PlaceOrderRequest{ order, } - order.InstrumentID = currency.NewPairWithDelimiter(currency.LTC.String(), currency.USDT.String(), "-").Lower().String() - request = append(request, order) - order.InstrumentID = currency.NewPairWithDelimiter(currency.DOGE.String(), currency.USDT.String(), "-").Lower().String() - request = append(request, order) - order.InstrumentID = currency.NewPairWithDelimiter(currency.XMR.String(), currency.USDT.String(), "-").Lower().String() - request = append(request, order) - order.InstrumentID = currency.NewPairWithDelimiter(currency.BCH.String(), currency.USDT.String(), "-").Lower().String() - request = append(request, order) + pairs := currency.Pairs{ + currency.NewPair(currency.LTC, currency.USDT), + currency.NewPair(currency.ETH, currency.USDT), + currency.NewPair(currency.BCH, currency.USDT), + currency.NewPair(currency.XMR, currency.USDT), + } + + for x := range pairs { + order.InstrumentID = pairs[x].Format("-", false).String() + request = append(request, order) + } _, errs := o.PlaceMultipleMarginOrders(request) if errs[0].Error() != "up to 4 trading pairs" { @@ -935,7 +937,7 @@ func TestPlaceFuturesOrder(t *testing.T) { Leverage: 10, Type: 1, Size: 2, - Price: 432.11, + Price: -432.11, ClientOid: "12233456", }) testStandardErrorHandling(t, err) @@ -951,7 +953,7 @@ func TestPlaceFuturesOrderBatch(t *testing.T) { { ClientOid: "1", MatchPrice: "0", - Price: "100", + Price: "-100", Size: "100", Type: "1", }, @@ -1212,13 +1214,13 @@ func TestPlaceMultipleSwapOrders(t *testing.T) { ClientOID: "hello", MatchPrice: "0", Price: "10", - Size: "1", + Size: "-1", Type: "1", }, { ClientOID: "hello2", MatchPrice: "0", Price: "10", - Size: "1", + Size: "-1", Type: "1", }}, }) @@ -1463,7 +1465,7 @@ func TestPlaceETTOrder(t *testing.T) { QuoteCurrency: spotCurrency, Type: 0, Size: "100", - Amount: 1, + Amount: -1, ETT: "OK06", } diff --git a/exchanges/okgroup/README.md b/exchanges/okgroup/README.md index 32b623afcc5..d9f96ea3673 100644 --- a/exchanges/okgroup/README.md +++ b/exchanges/okgroup/README.md @@ -47,22 +47,22 @@ main.go ```go var o exchange.IBotExchange -for i := range bot.exchanges { - if bot.exchanges[i].GetName() == "OKex" { - y = bot.exchanges[i] +for i := range Bot.Exchanges { + if Bot.Exchanges[i].GetName() == "OKex" { + y = Bot.Exchanges[i] } } // Public calls - wrapper functions // Fetches current ticker information -tick, err := o.GetTickerPrice() +tick, err := o.FetchTicker() if err != nil { // Handle error } // Fetches current orderbook information -ob, err := o.GetOrderbookEx() +ob, err := o.FetchOrderbook() if err != nil { // Handle error } diff --git a/exchanges/okgroup/okgroup.go b/exchanges/okgroup/okgroup.go index 4f1a89428ca..1b24871ea77 100644 --- a/exchanges/okgroup/okgroup.go +++ b/exchanges/okgroup/okgroup.go @@ -103,7 +103,7 @@ type OKGroup struct { // GetAccountCurrencies returns a list of tradable spot instruments and their properties func (o *OKGroup) GetAccountCurrencies() (resp []GetAccountCurrenciesResponse, _ error) { - return resp, o.SendHTTPRequest(http.MethodGet, okGroupAccountSubsection, okGroupGetAccountCurrencies, nil, &resp, false) + return resp, o.SendHTTPRequest(http.MethodGet, okGroupAccountSubsection, okGroupGetAccountCurrencies, nil, &resp, true) } // GetAccountWalletInformation returns a list of wallets and their properties @@ -173,7 +173,7 @@ func (o *OKGroup) GetAccountDepositHistory(currency string) (resp []GetAccountDe if currency != "" { requestURL = fmt.Sprintf("%v/%v", OKGroupGetAccountDepositHistory, currency) } else { - requestURL = okGroupGetWithdrawalHistory + requestURL = OKGroupGetAccountDepositHistory } return resp, o.SendHTTPRequest(http.MethodGet, okGroupAccountSubsection, requestURL, nil, &resp, true) } @@ -198,17 +198,23 @@ func (o *OKGroup) GetSpotBillDetailsForCurrency(request GetSpotBillDetailsForCur // PlaceSpotOrder token trading only supports limit and market orders (more order types will become available in the future). // You can place an order only if you have enough funds. // Once your order is placed, the amount will be put on hold. -func (o *OKGroup) PlaceSpotOrder(request *PlaceSpotOrderRequest) (resp PlaceSpotOrderResponse, _ error) { +func (o *OKGroup) PlaceSpotOrder(request *PlaceOrderRequest) (resp PlaceOrderResponse, _ error) { + if request.OrderType == "" { + request.OrderType = strconv.Itoa(NormalOrder) + } return resp, o.SendHTTPRequest(http.MethodPost, okGroupTokenSubsection, OKGroupOrders, request, &resp, true) } // PlaceMultipleSpotOrders supports placing multiple orders for specific trading pairs // up to 4 trading pairs, maximum 4 orders for each pair -func (o *OKGroup) PlaceMultipleSpotOrders(request []PlaceSpotOrderRequest) (map[string][]PlaceSpotOrderResponse, []error) { +func (o *OKGroup) PlaceMultipleSpotOrders(request []PlaceOrderRequest) (map[string][]PlaceOrderResponse, []error) { currencyPairOrders := make(map[string]int) - resp := make(map[string][]PlaceSpotOrderResponse) + resp := make(map[string][]PlaceOrderResponse) for i := range request { + if request[i].OrderType == "" { + request[i].OrderType = strconv.Itoa(NormalOrder) + } currencyPairOrders[request[i].InstrumentID]++ } @@ -422,14 +428,14 @@ func (o *OKGroup) RepayMarginLoan(request RepayMarginLoanRequest) (resp RepayMar // PlaceMarginOrder OKEx API only supports limit and market orders (more orders will become available in the future). // You can place an order only if you have enough funds. Once your order is placed, the amount will be put on hold. -func (o *OKGroup) PlaceMarginOrder(request *PlaceSpotOrderRequest) (resp PlaceSpotOrderResponse, _ error) { +func (o *OKGroup) PlaceMarginOrder(request *PlaceOrderRequest) (resp PlaceOrderResponse, _ error) { return resp, o.SendHTTPRequest(http.MethodPost, okGroupMarginTradingSubsection, OKGroupOrders, request, &resp, true) } // PlaceMultipleMarginOrders Place multiple orders for specific trading pairs (up to 4 trading pairs, maximum 4 orders each) -func (o *OKGroup) PlaceMultipleMarginOrders(request []PlaceSpotOrderRequest) (map[string][]PlaceSpotOrderResponse, []error) { +func (o *OKGroup) PlaceMultipleMarginOrders(request []PlaceOrderRequest) (map[string][]PlaceOrderResponse, []error) { currencyPairOrders := make(map[string]int) - resp := make(map[string][]PlaceSpotOrderResponse) + resp := make(map[string][]PlaceOrderResponse) for i := range request { currencyPairOrders[request[i].InstrumentID]++ } @@ -556,10 +562,7 @@ func (o *OKGroup) SendHTTPRequest(httpMethod, requestType, requestPath string, d o.Name) } - utcTime := time.Now().UTC() - iso := utcTime.String() - isoBytes := []byte(iso) - iso = string(isoBytes[:10]) + "T" + string(isoBytes[11:23]) + "Z" + utcTime := time.Now().UTC().Format(time.RFC3339) payload := []byte("") if data != nil { @@ -584,11 +587,11 @@ func (o *OKGroup) SendHTTPRequest(httpMethod, requestType, requestPath string, d signPath := fmt.Sprintf("/%v%v%v%v", OKGroupAPIPath, requestType, o.APIVersion, requestPath) hmac := crypto.GetHMAC(crypto.HashSHA256, - []byte(iso+httpMethod+signPath+string(payload)), + []byte(utcTime+httpMethod+signPath+string(payload)), []byte(o.API.Credentials.Secret)) headers["OK-ACCESS-KEY"] = o.API.Credentials.Key headers["OK-ACCESS-SIGN"] = crypto.Base64Encode(hmac) - headers["OK-ACCESS-TIMESTAMP"] = iso + headers["OK-ACCESS-TIMESTAMP"] = utcTime headers["OK-ACCESS-PASSPHRASE"] = o.API.Credentials.ClientID } diff --git a/exchanges/okgroup/okgroup_types.go b/exchanges/okgroup/okgroup_types.go index 076e656fad5..6a64b4a12b6 100644 --- a/exchanges/okgroup/okgroup_types.go +++ b/exchanges/okgroup/okgroup_types.go @@ -6,13 +6,21 @@ import ( "github.com/thrasher-corp/gocryptotrader/currency" ) +// Order types +const ( + NormalOrder = iota + PostOnlyOrder + FillOrKillOrder + ImmediateOrCancelOrder +) + // GetAccountCurrenciesResponse response data for GetAccountCurrencies type GetAccountCurrenciesResponse struct { - CanDeposit int64 `json:"can_deposit"` - CanWithdraw int64 `json:"can_withdraw"` - Currency string `json:"currency"` - MinWithdrawal float64 `json:"min_withdrawal"` Name string `json:"name"` + Currency string `json:"currency"` + CanDeposit int `json:"can_deposit,string"` + CanWithdraw int `json:"can_withdraw,string"` + MinWithdrawal float64 `json:"min_withdrawal,string"` } // WalletInformationResponse response data for WalletInformation @@ -64,22 +72,22 @@ type AccountWithdrawResponse struct { // GetAccountWithdrawalFeeResponse response data for GetAccountWithdrawalFee type GetAccountWithdrawalFeeResponse struct { Currency string `json:"currency"` - MinFee float64 `json:"min_fee"` - MaxFee float64 `json:"max_fee"` + MinFee float64 `json:"min_fee,string"` + MaxFee float64 `json:"max_fee,string"` } // WithdrawalHistoryResponse response data for WithdrawalHistoryResponse type WithdrawalHistoryResponse struct { - Amount float64 `json:"amount"` - Currency string `json:"currency"` - Fee string `json:"fee"` - From string `json:"from"` - Status int64 `json:"status"` - Timestamp time.Time `json:"timestamp"` - To string `json:"to"` - Txid string `json:"txid"` - PaymentID string `json:"payment_id"` - Tag string `json:"tag"` + Amount float64 `json:"amount,string"` + Currency string `json:"currency"` + Fee string `json:"fee"` + From string `json:"from"` + Status int64 `json:"status,string"` + Timestamp time.Time `json:"timestamp"` + To string `json:"to"` + TransactionID string `json:"txid"` + PaymentID string `json:"payment_id"` + Tag string `json:"tag"` } // GetAccountBillDetailsRequest request data for GetAccountBillDetailsRequest @@ -112,11 +120,12 @@ type GetDepositAddressResponse struct { // GetAccountDepositHistoryResponse response data for GetAccountDepositHistory type GetAccountDepositHistoryResponse struct { - Amount float64 `json:"amount"` + Amount float64 `json:"amount,string"` Currency string `json:"currency"` - Status int64 `json:"status"` - Timestamp time.Time `json:"timestamp"` + From string `json:"from"` To string `json:"to"` + Timestamp time.Time `json:"timestamp"` + Status int64 `json:"status,string"` TransactionID string `json:"txid"` } @@ -156,20 +165,21 @@ type SpotBillDetails struct { InstrumentID string `json:"instrument_id"` } -// PlaceSpotOrderRequest request data for PlaceSpotOrder -type PlaceSpotOrderRequest struct { +// PlaceOrderRequest request data for placing an order +type PlaceOrderRequest struct { ClientOID string `json:"client_oid,omitempty"` // the order ID customized by yourself Type string `json:"type"` // limit / market(default: limit) Side string `json:"side"` // buy or sell InstrumentID string `json:"instrument_id"` // trading pair - MarginTrading string `json:"margin_trading"` // order type (The request value is 1) + MarginTrading string `json:"margin_trading"` // margin trading + OrderType string `json:"order_type"` // order type (0: Normal order (Unfilled and 0 imply normal limit order) 1: Post only 2: Fill or Kill 3: Immediate Or Cancel Size string `json:"size"` Notional string `json:"notional,omitempty"` // Price string `json:"price,omitempty"` // price (Limit order only) } -// PlaceSpotOrderResponse response data for PlaceSpotOrder -type PlaceSpotOrderResponse struct { +// PlaceOrderResponse response data for PlaceSpotOrder +type PlaceOrderResponse struct { ClientOid string `json:"client_oid"` OrderID string `json:"order_id"` Result bool `json:"result"` @@ -1497,7 +1507,7 @@ type WebsocketSpotOrderResponse struct { Notional float64 `json:"notional,string"` Size float64 `json:"size,string"` Status string `json:"status"` - MarginTrading int64 `json:"margin_trading"` + MarginTrading int64 `json:"margin_trading,omitempty"` Type string `json:"type"` // Price A member, but part already exists as part of WebsocketDataResponse // InstrumentID A member, but part already exists as part of WebsocketDataResponse diff --git a/exchanges/okgroup/okgroup_websocket.go b/exchanges/okgroup/okgroup_websocket.go index 8aa944addd7..19ee8b79823 100644 --- a/exchanges/okgroup/okgroup_websocket.go +++ b/exchanges/okgroup/okgroup_websocket.go @@ -267,19 +267,21 @@ func (o *OKGroup) WsHandleData(wg *sync.WaitGroup) { // WsLogin sends a login request to websocket to enable access to authenticated endpoints func (o *OKGroup) WsLogin() error { o.Websocket.SetCanUseAuthenticatedEndpoints(true) - utcTime := time.Now().UTC() - unixTime := utcTime.Unix() + unixTime := time.Now().UTC().Unix() signPath := "/users/self/verify" hmac := crypto.GetHMAC(crypto.HashSHA256, - []byte(fmt.Sprintf("%v", unixTime)+http.MethodGet+signPath), - []byte(o.API.Credentials.Secret)) + []byte(strconv.FormatInt(unixTime, 10)+http.MethodGet+signPath), + []byte(o.API.Credentials.Secret), + ) base64 := crypto.Base64Encode(hmac) request := WebsocketEventRequest{ Operation: "login", - Arguments: []string{o.API.Credentials.Key, + Arguments: []string{ + o.API.Credentials.Key, o.API.Credentials.ClientID, - fmt.Sprintf("%v", unixTime), - base64}, + strconv.FormatInt(unixTime, 10), + base64, + }, } err := o.WebsocketConn.SendMessage(request) if err != nil { @@ -470,7 +472,7 @@ func (o *OKGroup) wsProcessCandles(response *WebsocketDataResponse) { timeData, err := time.Parse(time.RFC3339Nano, response.Data[i].WebsocketCandleResponse.Candle[0]) if err != nil { - log.Warnf(log.ExchangeSys, + log.Errorf(log.ExchangeSys, "%v Time data could not be parsed: %v", o.Name, response.Data[i].Candle[0]) diff --git a/exchanges/okgroup/okgroup_wrapper.go b/exchanges/okgroup/okgroup_wrapper.go index d9f1a032e9b..91658ba03b9 100644 --- a/exchanges/okgroup/okgroup_wrapper.go +++ b/exchanges/okgroup/okgroup_wrapper.go @@ -236,7 +236,7 @@ func (o *OKGroup) GetFundingHistory() (resp []exchange.FundHistory, err error) { ExchangeName: o.Name, Status: OrderStatus[accountWithdrawlHistory[i].Status], Timestamp: accountWithdrawlHistory[i].Timestamp, - TransferID: accountWithdrawlHistory[i].Txid, + TransferID: accountWithdrawlHistory[i].TransactionID, TransferType: "withdrawal", }) } @@ -255,11 +255,11 @@ func (o *OKGroup) SubmitOrder(s *order.Submit) (resp order.SubmitResponse, err e return resp, err } - request := PlaceSpotOrderRequest{ + request := PlaceOrderRequest{ ClientOID: s.ClientID, InstrumentID: o.FormatExchangeCurrency(s.Pair, asset.Spot).String(), - Side: strings.ToLower(s.OrderSide.String()), - Type: strings.ToLower(s.OrderType.String()), + Side: s.OrderSide.Lower(), + Type: s.OrderType.Lower(), Size: strconv.FormatFloat(s.Amount, 'f', -1, 64), } if s.OrderType == order.Limit { diff --git a/exchanges/poloniex/poloniex.go b/exchanges/poloniex/poloniex.go index 927f4ff20ec..eb28f57938b 100644 --- a/exchanges/poloniex/poloniex.go +++ b/exchanges/poloniex/poloniex.go @@ -129,25 +129,27 @@ func (p *Poloniex) GetOrderbook(currencyPair string, depth int) (OrderbookAll, e return oba, err } for currency, orderbook := range resp.Data { - ob := Orderbook{} + var ob Orderbook for x := range orderbook.Asks { - data := orderbook.Asks[x] - price, err := strconv.ParseFloat(data[0].(string), 64) + price, err := strconv.ParseFloat(orderbook.Asks[x][0].(string), 64) if err != nil { return oba, err } - amount := data[1].(float64) - ob.Asks = append(ob.Asks, OrderbookItem{Price: price, Amount: amount}) + ob.Asks = append(ob.Asks, OrderbookItem{ + Price: price, + Amount: orderbook.Asks[x][1].(float64), + }) } for x := range orderbook.Bids { - data := orderbook.Bids[x] - price, err := strconv.ParseFloat(data[0].(string), 64) + price, err := strconv.ParseFloat(orderbook.Bids[x][0].(string), 64) if err != nil { return oba, err } - amount := data[1].(float64) - ob.Bids = append(ob.Bids, OrderbookItem{Price: price, Amount: amount}) + ob.Asks = append(ob.Asks, OrderbookItem{ + Price: price, + Amount: orderbook.Bids[x][1].(float64), + }) } oba.Data[currency] = Orderbook{Bids: ob.Bids, Asks: ob.Asks} } diff --git a/exchanges/poloniex/poloniex_websocket.go b/exchanges/poloniex/poloniex_websocket.go index 62e2186c678..648a64c8d61 100644 --- a/exchanges/poloniex/poloniex_websocket.go +++ b/exchanges/poloniex/poloniex_websocket.go @@ -14,6 +14,7 @@ import ( "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/websocket/wshandler" "github.com/thrasher-corp/gocryptotrader/exchanges/websocket/wsorderbook" @@ -186,11 +187,11 @@ func (p *Poloniex) WsHandleData() { trade.Symbol = currencyIDMap[chanID] trade.TradeID, _ = strconv.ParseInt(dataL3[1].(string), 10, 64) // 1 for buy 0 for sell - side := "buy" + side := order.Buy if dataL3[2].(float64) != 1 { - side = "sell" + side = order.Sell } - trade.Side = side + trade.Side = side.Lower() trade.Volume, err = strconv.ParseFloat(dataL3[3].(string), 64) if err != nil { p.Websocket.DataHandler <- err diff --git a/exchanges/poloniex/poloniex_wrapper.go b/exchanges/poloniex/poloniex_wrapper.go index 9bccee98f5f..02ed381866b 100644 --- a/exchanges/poloniex/poloniex_wrapper.go +++ b/exchanges/poloniex/poloniex_wrapper.go @@ -296,21 +296,18 @@ func (p *Poloniex) UpdateOrderbook(currencyPair currency.Pair, assetType asset.I var obItems []orderbook.Item for y := range data.Bids { - obData := data.Bids[y] - obItems = append(obItems, - orderbook.Item{Amount: obData.Amount, Price: obData.Price}) + obItems = append(obItems, orderbook.Item{ + Amount: data.Bids[y].Amount, Price: data.Bids[y].Price}) } - orderBook.Bids = obItems + obItems = []orderbook.Item{} for y := range data.Asks { - obData := data.Asks[y] - obItems = append(obItems, - orderbook.Item{Amount: obData.Amount, Price: obData.Price}) + obItems = append(obItems, orderbook.Item{ + Amount: data.Asks[y].Amount, Price: data.Asks[y].Price}) } - - orderBook.Pair = x orderBook.Asks = obItems + orderBook.Pair = x orderBook.ExchangeName = p.Name orderBook.AssetType = assetType @@ -350,8 +347,7 @@ func (p *Poloniex) GetAccountInfo() (exchange.AccountInfo, error) { // GetFundingHistory returns funding history, deposits and // withdrawals func (p *Poloniex) GetFundingHistory() ([]exchange.FundHistory, error) { - var fundHistory []exchange.FundHistory - return fundHistory, common.ErrFunctionNotSupported + return nil, common.ErrFunctionNotSupported } // GetExchangeHistory returns historic trade data since exchange opening. @@ -507,7 +503,7 @@ func (p *Poloniex) GetActiveOrders(req *order.GetOrdersRequest) ([]order.Detail, orderSide := order.Side(strings.ToUpper(resp.Data[key][i].Type)) orderDate, err := time.Parse(poloniexDateLayout, resp.Data[key][i].Date) if err != nil { - log.Warnf(log.ExchangeSys, + log.Errorf(log.ExchangeSys, "Exchange %v Func %v Order %v Could not parse date to unix with value of %v", p.Name, "GetActiveOrders", @@ -554,7 +550,7 @@ func (p *Poloniex) GetOrderHistory(req *order.GetOrdersRequest) ([]order.Detail, orderDate, err := time.Parse(poloniexDateLayout, resp.Data[key][i].Date) if err != nil { - log.Warnf(log.ExchangeSys, + log.Errorf(log.ExchangeSys, "Exchange %v Func %v Order %v Could not parse date to unix with value of %v", p.Name, "GetActiveOrders", diff --git a/exchanges/support.go b/exchanges/support.go index d9e0e0a12d6..37e0ceed6c0 100644 --- a/exchanges/support.go +++ b/exchanges/support.go @@ -25,6 +25,7 @@ var Exchanges = []string{ "btc markets", "btse", "coinbasepro", + "coinbene", "coinut", "exmo", "gateio", diff --git a/exchanges/yobit/yobit_wrapper.go b/exchanges/yobit/yobit_wrapper.go index bd7ed666663..400383a4748 100644 --- a/exchanges/yobit/yobit_wrapper.go +++ b/exchanges/yobit/yobit_wrapper.go @@ -299,8 +299,7 @@ func (y *Yobit) GetAccountInfo() (exchange.AccountInfo, error) { // GetFundingHistory returns funding history, deposits and // withdrawals func (y *Yobit) GetFundingHistory() ([]exchange.FundHistory, error) { - var fundHistory []exchange.FundHistory - return fundHistory, common.ErrFunctionNotSupported + return nil, common.ErrFunctionNotSupported } // GetExchangeHistory returns historic trade data since exchange opening. diff --git a/exchanges/zb/zb_wrapper.go b/exchanges/zb/zb_wrapper.go index 60108f1554b..2f9608e976d 100644 --- a/exchanges/zb/zb_wrapper.go +++ b/exchanges/zb/zb_wrapper.go @@ -268,23 +268,24 @@ func (z *ZB) FetchOrderbook(p currency.Pair, assetType asset.Item) (orderbook.Ba // UpdateOrderbook updates and returns the orderbook for a currency pair func (z *ZB) UpdateOrderbook(p currency.Pair, assetType asset.Item) (orderbook.Base, error) { var orderBook orderbook.Base - currency := z.FormatExchangeCurrency(p, assetType).String() - - orderbookNew, err := z.GetOrderbook(currency) + orderbookNew, err := z.GetOrderbook(z.FormatExchangeCurrency(p, + assetType).String()) if err != nil { return orderBook, err } for x := range orderbookNew.Bids { - data := orderbookNew.Bids[x] - orderBook.Bids = append(orderBook.Bids, - orderbook.Item{Amount: data[1], Price: data[0]}) + orderBook.Bids = append(orderBook.Bids, orderbook.Item{ + Amount: orderbookNew.Bids[x][1], + Price: orderbookNew.Bids[x][0], + }) } for x := range orderbookNew.Asks { - data := orderbookNew.Asks[x] - orderBook.Asks = append(orderBook.Asks, - orderbook.Item{Amount: data[1], Price: data[0]}) + orderBook.Asks = append(orderBook.Asks, orderbook.Item{ + Amount: orderbookNew.Asks[x][1], + Price: orderbookNew.Asks[x][0], + }) } orderBook.Pair = p @@ -338,8 +339,7 @@ func (z *ZB) GetAccountInfo() (exchange.AccountInfo, error) { // GetFundingHistory returns funding history, deposits and // withdrawals func (z *ZB) GetFundingHistory() ([]exchange.FundHistory, error) { - var fundHistory []exchange.FundHistory - return fundHistory, common.ErrFunctionNotSupported + return nil, common.ErrFunctionNotSupported } // GetExchangeHistory returns historic trade data since exchange opening. diff --git a/gctrpc/rpc.pb.go b/gctrpc/rpc.pb.go index 00cbb677d3c..a5796e2b3d1 100644 --- a/gctrpc/rpc.pb.go +++ b/gctrpc/rpc.pb.go @@ -9,6 +9,8 @@ import ( proto "github.com/golang/protobuf/proto" _ "google.golang.org/genproto/googleapis/api/annotations" grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" math "math" ) @@ -5188,316 +5190,316 @@ func init() { proto.RegisterType((*GetExchangeTickerStreamRequest)(nil), "gctrpc.GetExchangeTickerStreamRequest") proto.RegisterType((*GetAuditEventRequest)(nil), "gctrpc.GetAuditEventRequest") proto.RegisterType((*GetAuditEventResponse)(nil), "gctrpc.GetAuditEventResponse") - proto.RegisterType((*AuditEvent)(nil), "gctrpc.audit_event") + proto.RegisterType((*AuditEvent)(nil), "gctrpc.AuditEvent") } func init() { proto.RegisterFile("rpc.proto", fileDescriptor_77a6da22d6a3feb1) } var fileDescriptor_77a6da22d6a3feb1 = []byte{ - // 4844 bytes of a gzipped FileDescriptorProto + // 4838 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x3c, 0x4d, 0x8f, 0x24, 0x47, - 0x56, 0xca, 0xea, 0x9e, 0xee, 0xae, 0x57, 0xd5, 0x5f, 0xd1, 0x5f, 0x35, 0xd5, 0xdd, 0xf3, 0x91, - 0x5e, 0x8f, 0x67, 0xfc, 0xd1, 0x63, 0x8f, 0x07, 0xd6, 0xac, 0xcd, 0x2e, 0xed, 0x1e, 0xbb, 0xd7, - 0xd8, 0xeb, 0x69, 0xb2, 0x67, 0xc7, 0x92, 0x17, 0xb9, 0xc8, 0xae, 0x8c, 0xea, 0x4e, 0xa6, 0x2a, - 0x33, 0x9d, 0x19, 0xd5, 0x3d, 0x65, 0x40, 0xac, 0x2c, 0x81, 0x38, 0x20, 0x38, 0xac, 0x90, 0x40, - 0xe2, 0xc4, 0x11, 0x89, 0x0b, 0xe2, 0xc4, 0x61, 0xc5, 0x15, 0x71, 0xe4, 0xc2, 0x0f, 0x40, 0xdc, - 0x00, 0x69, 0x25, 0x2e, 0x9c, 0x50, 0xbc, 0xf8, 0xc8, 0x88, 0xcc, 0xac, 0xea, 0xea, 0xdd, 0x59, - 0x73, 0xb1, 0x2b, 0x5f, 0xbc, 0x78, 0xef, 0xc5, 0x8b, 0x17, 0x2f, 0xde, 0x7b, 0xf1, 0x7a, 0xa0, - 0x9e, 0x26, 0xdd, 0xbd, 0x24, 0x8d, 0x59, 0x4c, 0xe6, 0x4e, 0xbb, 0x2c, 0x4d, 0xba, 0xed, 0x9d, - 0xd3, 0x38, 0x3e, 0xed, 0xd3, 0xfb, 0x7e, 0x12, 0xde, 0xf7, 0xa3, 0x28, 0x66, 0x3e, 0x0b, 0xe3, - 0x28, 0x13, 0x58, 0xee, 0x0a, 0x2c, 0x1d, 0x52, 0xf6, 0x51, 0xd4, 0x8b, 0x3d, 0xfa, 0xe5, 0x90, - 0x66, 0xcc, 0xfd, 0x87, 0x59, 0x58, 0xd6, 0xa0, 0x2c, 0x89, 0xa3, 0x8c, 0x92, 0x4d, 0x98, 0x1b, - 0x26, 0x2c, 0x1c, 0xd0, 0x96, 0x73, 0xcb, 0xb9, 0x5b, 0xf7, 0xe4, 0x17, 0xb9, 0x0f, 0x6b, 0xfe, - 0xb9, 0x1f, 0xf6, 0xfd, 0x93, 0x3e, 0xed, 0xd0, 0xe7, 0xdd, 0x33, 0x3f, 0x3a, 0xa5, 0x59, 0xab, - 0x76, 0xcb, 0xb9, 0x3b, 0xe3, 0x11, 0x3d, 0xf4, 0x81, 0x1a, 0x21, 0xaf, 0xc1, 0x2a, 0x8d, 0x38, - 0x28, 0x30, 0xd0, 0x67, 0x10, 0x7d, 0x45, 0x0e, 0xe4, 0xc8, 0x0f, 0x61, 0x33, 0xa0, 0x3d, 0x7f, - 0xd8, 0x67, 0x9d, 0x5e, 0x9c, 0xd2, 0xe7, 0x9d, 0x24, 0x8d, 0xcf, 0xc3, 0x80, 0xa6, 0xad, 0x59, - 0x94, 0x62, 0x5d, 0x8e, 0x7e, 0xc8, 0x07, 0x8f, 0xe4, 0x18, 0x79, 0x00, 0x1b, 0x7a, 0x56, 0xe8, - 0xb3, 0x4e, 0x77, 0x98, 0xa6, 0x34, 0xea, 0x8e, 0x5a, 0xd7, 0x70, 0xd2, 0x9a, 0x9a, 0x14, 0xfa, - 0xec, 0x40, 0x0e, 0x91, 0xcf, 0x60, 0x25, 0x1b, 0x9e, 0x64, 0xa3, 0x8c, 0xd1, 0x41, 0x27, 0x63, - 0x3e, 0x1b, 0x66, 0xad, 0xb9, 0x5b, 0x33, 0x77, 0x1b, 0x0f, 0x5e, 0xdf, 0x13, 0x6a, 0xdc, 0x2b, - 0xa8, 0x64, 0xef, 0x58, 0xe1, 0x1f, 0x23, 0xfa, 0x07, 0x11, 0x4b, 0x47, 0xde, 0x72, 0x66, 0x43, - 0xc9, 0xa7, 0xb0, 0x98, 0x26, 0xdd, 0x0e, 0x8d, 0x82, 0x24, 0x0e, 0x23, 0x96, 0xb5, 0xe6, 0x91, - 0xea, 0xbd, 0x71, 0x54, 0xbd, 0xa4, 0xfb, 0x81, 0xc2, 0x15, 0x24, 0x9b, 0xa9, 0x01, 0x6a, 0xbf, - 0x0f, 0xeb, 0x55, 0x8c, 0xc9, 0x0a, 0xcc, 0x3c, 0xa3, 0x23, 0xb9, 0x3b, 0xfc, 0x27, 0x59, 0x87, - 0x6b, 0xe7, 0x7e, 0x7f, 0x48, 0x71, 0x33, 0x16, 0x3c, 0xf1, 0xf1, 0x9d, 0xda, 0x3b, 0x4e, 0xfb, - 0x09, 0xac, 0x96, 0xd8, 0x54, 0x10, 0xb8, 0x67, 0x12, 0x68, 0x3c, 0x58, 0x53, 0x22, 0x7b, 0x47, - 0x07, 0x6a, 0xae, 0x41, 0xd5, 0xbd, 0x0d, 0x37, 0x0f, 0x29, 0x3b, 0x88, 0x07, 0x83, 0x61, 0x14, - 0x76, 0xd1, 0xc6, 0x3c, 0xda, 0xf7, 0x47, 0x34, 0xcd, 0x94, 0x65, 0x7d, 0x0a, 0xeb, 0x55, 0xe3, - 0xa4, 0x05, 0xf3, 0x72, 0xef, 0x91, 0xff, 0x82, 0xa7, 0x3e, 0xc9, 0x0e, 0xd4, 0xbb, 0x71, 0x14, - 0xd1, 0x2e, 0xa3, 0x81, 0x5c, 0x48, 0x0e, 0x70, 0xff, 0xb8, 0x06, 0xb7, 0xc6, 0xf3, 0x94, 0xa6, - 0xfb, 0x15, 0x6c, 0x76, 0x4d, 0x84, 0x4e, 0x2a, 0x31, 0x5a, 0x0e, 0x6e, 0xc5, 0x81, 0xb1, 0x15, - 0x13, 0x29, 0xed, 0x55, 0x8e, 0x8a, 0x4d, 0xda, 0xe8, 0x56, 0x8d, 0xb5, 0x7b, 0xd0, 0x1e, 0x3f, - 0xa9, 0x42, 0xe5, 0x0f, 0x6c, 0x95, 0xef, 0x28, 0xd1, 0xaa, 0x88, 0x98, 0xba, 0xff, 0x36, 0x6c, - 0x1d, 0xd2, 0x88, 0xa6, 0x61, 0x57, 0x1b, 0x87, 0xd4, 0x39, 0xd7, 0xa0, 0xb6, 0x49, 0xc9, 0x2a, - 0x07, 0xb8, 0x6d, 0x68, 0x95, 0x27, 0x8a, 0xe5, 0xba, 0x9b, 0xb0, 0x7e, 0x48, 0x99, 0x86, 0xeb, - 0x5d, 0xfc, 0xa9, 0x03, 0x1b, 0x38, 0x90, 0x9d, 0x64, 0x23, 0x31, 0x20, 0x55, 0xfd, 0x3b, 0xb0, - 0xaa, 0x49, 0x67, 0xea, 0x18, 0x09, 0x2d, 0xbf, 0x6d, 0x68, 0xb9, 0x3c, 0x33, 0x3f, 0x4c, 0x99, - 0x79, 0x9a, 0xf2, 0x33, 0x29, 0xc1, 0xed, 0x03, 0xd8, 0xa8, 0x44, 0xbd, 0x8a, 0xfd, 0xbb, 0x2d, - 0xd8, 0x3c, 0xa4, 0xcc, 0x30, 0x63, 0xc3, 0x40, 0x1b, 0x06, 0x98, 0xdb, 0x65, 0xc6, 0xfc, 0x94, - 0xe5, 0x76, 0x29, 0x3f, 0xc9, 0xcb, 0xb0, 0xd4, 0x0f, 0x33, 0x46, 0xa3, 0x8e, 0x1f, 0x04, 0x29, - 0xcd, 0x84, 0xcb, 0xab, 0x7b, 0x8b, 0x02, 0xba, 0x2f, 0x80, 0xee, 0x3f, 0x3a, 0x7c, 0x63, 0x0a, - 0xac, 0xa4, 0xb2, 0x3e, 0x81, 0x7a, 0xee, 0x15, 0x84, 0x92, 0xf6, 0x0c, 0x25, 0x55, 0xcd, 0xd9, - 0x2b, 0xb8, 0x86, 0x9c, 0x40, 0xfb, 0xb7, 0x60, 0xe9, 0x45, 0x1f, 0xe8, 0x77, 0xa0, 0x2d, 0x6d, - 0x43, 0x79, 0xe4, 0x4f, 0xfd, 0x01, 0x55, 0x76, 0xd5, 0x86, 0x05, 0xe5, 0xc0, 0x25, 0x0f, 0xfd, - 0xed, 0xee, 0xc2, 0x76, 0xe5, 0x4c, 0x69, 0x58, 0xf7, 0x61, 0xed, 0x90, 0x32, 0xed, 0xe6, 0x15, - 0xc5, 0xb1, 0x5e, 0xc0, 0x7d, 0x88, 0x96, 0x68, 0x4c, 0x90, 0x2a, 0xdc, 0x81, 0x7a, 0x7e, 0x89, - 0x48, 0xdb, 0xd6, 0x00, 0xf7, 0x01, 0x9a, 0xa9, 0x9a, 0xf5, 0xf8, 0xc9, 0x91, 0x47, 0xc5, 0xb4, - 0xeb, 0xb0, 0x10, 0xb3, 0xa4, 0xd3, 0x8d, 0x03, 0x25, 0xfa, 0x7c, 0xcc, 0x92, 0x83, 0x38, 0xa0, - 0xd2, 0x34, 0x8c, 0x39, 0xda, 0x34, 0xfe, 0x46, 0x6c, 0xa5, 0x3d, 0x24, 0xe5, 0xf8, 0x4d, 0xa8, - 0x2b, 0x82, 0x6a, 0x2b, 0xdf, 0x30, 0xb6, 0xb2, 0x6a, 0xce, 0xde, 0x63, 0xc1, 0x51, 0xee, 0xe4, - 0x82, 0x14, 0x20, 0x6b, 0xbf, 0x0b, 0x8b, 0xd6, 0xd0, 0x65, 0x96, 0x5d, 0x37, 0xb7, 0xec, 0x21, - 0x6c, 0x3e, 0x0a, 0x33, 0xf3, 0xc6, 0x9d, 0x66, 0xbb, 0xbe, 0x80, 0xa5, 0x23, 0x3f, 0x4c, 0xb3, - 0xe3, 0x61, 0x92, 0xc4, 0x68, 0xde, 0xaf, 0xc0, 0x72, 0x7e, 0xad, 0x27, 0x7c, 0x4c, 0x4e, 0x5a, - 0xd2, 0x60, 0x9c, 0x41, 0x5e, 0x82, 0x45, 0x75, 0x9d, 0x0b, 0x34, 0x21, 0x52, 0x53, 0x02, 0x11, - 0xc9, 0xfd, 0x7a, 0xd6, 0x52, 0x9d, 0x15, 0x58, 0x10, 0x98, 0x8d, 0x7c, 0x1d, 0x56, 0xe0, 0x6f, - 0xd3, 0x10, 0x6a, 0xf6, 0x75, 0xd0, 0x82, 0xf9, 0x73, 0x9a, 0x9e, 0xc4, 0x19, 0xc5, 0x98, 0x61, - 0xc1, 0x53, 0x9f, 0x5c, 0x90, 0x61, 0x16, 0x46, 0xa7, 0x9d, 0xcc, 0x8f, 0x82, 0x93, 0xf8, 0x39, - 0x46, 0x08, 0x0b, 0x5e, 0x13, 0x81, 0xc7, 0x02, 0x46, 0x6e, 0x43, 0xf3, 0x8c, 0xb1, 0xa4, 0xc3, - 0x43, 0x97, 0x78, 0xc8, 0x64, 0x40, 0xd0, 0xe0, 0xb0, 0x27, 0x02, 0xc4, 0x0f, 0x36, 0xa2, 0x0c, - 0x33, 0x9a, 0xfa, 0xa7, 0x34, 0x62, 0xad, 0x39, 0x71, 0xb0, 0x39, 0xf4, 0x87, 0x0a, 0x48, 0x76, - 0x01, 0x10, 0x2d, 0x49, 0xe3, 0xe7, 0xa3, 0xd6, 0xbc, 0x30, 0x3d, 0x0e, 0x39, 0xe2, 0x00, 0xae, - 0xbf, 0x13, 0x3f, 0xa3, 0x2a, 0xf4, 0x08, 0x69, 0xd6, 0x5a, 0x10, 0xfa, 0xe3, 0xe0, 0x03, 0x0d, - 0x25, 0x1d, 0x1e, 0x77, 0x48, 0xad, 0x77, 0xfc, 0x2c, 0xa3, 0x2c, 0x6b, 0xd5, 0xd1, 0x80, 0x1e, - 0x56, 0x18, 0x50, 0x21, 0xfe, 0x90, 0xf3, 0xf6, 0x71, 0x9a, 0x8e, 0x3f, 0x2c, 0x28, 0x8f, 0xb7, - 0xfc, 0x21, 0x3b, 0xa3, 0x11, 0xe3, 0xb7, 0x07, 0x67, 0x92, 0x84, 0x2d, 0x40, 0xdd, 0xac, 0x58, - 0x03, 0xfb, 0x49, 0xd8, 0xfe, 0x9c, 0x07, 0x17, 0x65, 0xaa, 0x15, 0x26, 0xf8, 0xba, 0xed, 0x4a, - 0x36, 0x95, 0xb0, 0xb6, 0x1d, 0x99, 0xa6, 0x79, 0x01, 0x2b, 0x87, 0x94, 0x3d, 0x09, 0xbb, 0xcf, - 0x68, 0x3a, 0x85, 0x51, 0x92, 0xbb, 0x30, 0xcb, 0x2d, 0x4a, 0x32, 0x58, 0xd7, 0x37, 0xa1, 0x8c, - 0xd8, 0x38, 0x23, 0x0f, 0x31, 0xf8, 0x5e, 0xa0, 0xe6, 0x3a, 0x6c, 0x94, 0x08, 0xbb, 0xa8, 0x7b, - 0x75, 0x84, 0x3c, 0x19, 0x25, 0xd4, 0x7d, 0x0a, 0x4d, 0x73, 0x12, 0x77, 0x1a, 0x01, 0xed, 0x87, - 0x83, 0x90, 0xd1, 0x54, 0x39, 0x0d, 0x0d, 0xe0, 0xf6, 0xc8, 0xb7, 0x48, 0xda, 0x31, 0xfe, 0xe6, - 0xe7, 0xed, 0xcb, 0x61, 0xcc, 0x14, 0x6d, 0xf1, 0xe1, 0xfe, 0x45, 0x0d, 0x96, 0xd4, 0x72, 0xa4, - 0x31, 0x2b, 0x99, 0x9d, 0x4b, 0x65, 0xbe, 0x0d, 0xcd, 0xbe, 0x9f, 0xb1, 0xce, 0x30, 0x09, 0x7c, - 0x15, 0xda, 0xcc, 0x78, 0x0d, 0x0e, 0xfb, 0xa1, 0x00, 0x71, 0x8b, 0x56, 0x91, 0x2b, 0x9e, 0x2d, - 0xc9, 0xbd, 0xd9, 0x35, 0x17, 0x43, 0x60, 0x96, 0xcf, 0x41, 0x6b, 0x77, 0x3c, 0xfc, 0xcd, 0x61, - 0x67, 0xe1, 0xe9, 0x19, 0x5a, 0xb7, 0xe3, 0xe1, 0x6f, 0xbe, 0x83, 0xfd, 0xf8, 0x02, 0x6d, 0xd9, - 0xf1, 0xf8, 0x4f, 0x0e, 0x39, 0x09, 0x03, 0x34, 0x5d, 0xc7, 0xe3, 0x3f, 0x39, 0xc4, 0xcf, 0x9e, - 0xa1, 0xa1, 0x3a, 0x1e, 0xff, 0xc9, 0xa3, 0xfe, 0xf3, 0xb8, 0x3f, 0x1c, 0xd0, 0x56, 0x1d, 0x81, - 0xf2, 0x8b, 0x6c, 0x43, 0x3d, 0x49, 0xc3, 0x2e, 0xed, 0xf8, 0xec, 0x0c, 0x8d, 0xc9, 0xf1, 0x16, - 0x10, 0xb0, 0xcf, 0xce, 0xdc, 0x35, 0x58, 0xd5, 0x1b, 0xad, 0xbd, 0xe7, 0x67, 0x30, 0x2f, 0x21, - 0x13, 0x37, 0xfd, 0x4d, 0x98, 0x67, 0x02, 0xad, 0x55, 0xc3, 0x53, 0xa0, 0x0d, 0xcb, 0xd6, 0xb4, - 0xa7, 0xd0, 0xdc, 0xef, 0x01, 0x31, 0xb9, 0xc9, 0x8d, 0xb8, 0x97, 0xd3, 0x11, 0xee, 0x78, 0xd9, - 0xa6, 0x93, 0xe5, 0x04, 0xbe, 0xc2, 0xcb, 0xe8, 0x71, 0x1a, 0x70, 0x47, 0x12, 0x3f, 0xfb, 0x46, - 0x4d, 0xf3, 0x07, 0xb0, 0xa8, 0x19, 0x7f, 0xc4, 0xe8, 0x80, 0x2b, 0xdc, 0x1f, 0xc4, 0xc3, 0x88, + 0x56, 0xca, 0xea, 0xcf, 0x7a, 0x5d, 0xfd, 0x15, 0xfd, 0x55, 0x53, 0xdd, 0x3d, 0x3d, 0x93, 0x5e, + 0x8f, 0x67, 0x66, 0xbd, 0x3d, 0xf6, 0x78, 0x60, 0xcd, 0xda, 0xec, 0xd2, 0x6e, 0xdb, 0xbd, 0xc6, + 0x5e, 0x4f, 0x93, 0x3d, 0x3b, 0x96, 0xbc, 0xc8, 0x45, 0x76, 0x65, 0x54, 0x77, 0x32, 0x55, 0x99, + 0xe9, 0xcc, 0xa8, 0xee, 0x29, 0x03, 0x62, 0x65, 0x09, 0xc4, 0x01, 0xc1, 0x61, 0x85, 0x04, 0x12, + 0x27, 0x8e, 0x48, 0x5c, 0x10, 0x27, 0x0e, 0x2b, 0xae, 0x88, 0x23, 0x17, 0x7e, 0x00, 0xe2, 0x06, + 0x48, 0x2b, 0x71, 0xe1, 0x84, 0xe2, 0xc5, 0x47, 0x46, 0x64, 0x66, 0x55, 0x57, 0xef, 0xce, 0x0e, + 0x17, 0xbb, 0xf2, 0xc5, 0x8b, 0xf7, 0x5e, 0xbc, 0x78, 0xf1, 0xe2, 0xbd, 0x17, 0xaf, 0x07, 0xea, + 0x69, 0xd2, 0xd9, 0x4f, 0xd2, 0x98, 0xc5, 0x64, 0xf6, 0xac, 0xc3, 0xd2, 0xa4, 0xd3, 0xda, 0x39, + 0x8b, 0xe3, 0xb3, 0x1e, 0x7d, 0xe0, 0x27, 0xe1, 0x03, 0x3f, 0x8a, 0x62, 0xe6, 0xb3, 0x30, 0x8e, + 0x32, 0x81, 0xe5, 0xae, 0xc0, 0xd2, 0x11, 0x65, 0x1f, 0x45, 0xdd, 0xd8, 0xa3, 0x5f, 0x0e, 0x68, + 0xc6, 0xdc, 0x7f, 0x98, 0x86, 0x65, 0x0d, 0xca, 0x92, 0x38, 0xca, 0x28, 0xd9, 0x84, 0xd9, 0x41, + 0xc2, 0xc2, 0x3e, 0x6d, 0x3a, 0xb7, 0x9c, 0xbb, 0x75, 0x4f, 0x7e, 0x91, 0x07, 0xb0, 0xe6, 0x5f, + 0xf8, 0x61, 0xcf, 0x3f, 0xed, 0xd1, 0x36, 0x7d, 0xde, 0x39, 0xf7, 0xa3, 0x33, 0x9a, 0x35, 0x6b, + 0xb7, 0x9c, 0xbb, 0x53, 0x1e, 0xd1, 0x43, 0x1f, 0xa8, 0x11, 0xf2, 0x4d, 0x58, 0xa5, 0x11, 0x07, + 0x05, 0x06, 0xfa, 0x14, 0xa2, 0xaf, 0xc8, 0x81, 0x1c, 0xf9, 0x11, 0x6c, 0x06, 0xb4, 0xeb, 0x0f, + 0x7a, 0xac, 0xdd, 0x8d, 0x53, 0xfa, 0xbc, 0x9d, 0xa4, 0xf1, 0x45, 0x18, 0xd0, 0xb4, 0x39, 0x8d, + 0x52, 0xac, 0xcb, 0xd1, 0x0f, 0xf9, 0xe0, 0xb1, 0x1c, 0x23, 0x0f, 0x61, 0x43, 0xcf, 0x0a, 0x7d, + 0xd6, 0xee, 0x0c, 0xd2, 0x94, 0x46, 0x9d, 0x61, 0x73, 0x06, 0x27, 0xad, 0xa9, 0x49, 0xa1, 0xcf, + 0x0e, 0xe5, 0x10, 0xf9, 0x0c, 0x56, 0xb2, 0xc1, 0x69, 0x36, 0xcc, 0x18, 0xed, 0xb7, 0x33, 0xe6, + 0xb3, 0x41, 0xd6, 0x9c, 0xbd, 0x35, 0x75, 0x77, 0xe1, 0xe1, 0xeb, 0xfb, 0x42, 0x8d, 0xfb, 0x05, + 0x95, 0xec, 0x9f, 0x28, 0xfc, 0x13, 0x44, 0xff, 0x20, 0x62, 0xe9, 0xd0, 0x5b, 0xce, 0x6c, 0x28, + 0xf9, 0x14, 0x16, 0xd3, 0xa4, 0xd3, 0xa6, 0x51, 0x90, 0xc4, 0x61, 0xc4, 0xb2, 0xe6, 0x1c, 0x52, + 0xbd, 0x37, 0x8a, 0xaa, 0x97, 0x74, 0x3e, 0x50, 0xb8, 0x82, 0x64, 0x23, 0x35, 0x40, 0xad, 0xf7, + 0x60, 0xbd, 0x8a, 0x31, 0x59, 0x81, 0xa9, 0x67, 0x74, 0x28, 0x77, 0x87, 0xff, 0x24, 0xeb, 0x30, + 0x73, 0xe1, 0xf7, 0x06, 0x14, 0x37, 0x63, 0xde, 0x13, 0x1f, 0xdf, 0xa9, 0xbd, 0xed, 0xb4, 0x9e, + 0xc0, 0x6a, 0x89, 0x4d, 0x05, 0x81, 0x7b, 0x26, 0x81, 0x85, 0x87, 0x6b, 0x4a, 0x64, 0xef, 0xf8, + 0x50, 0xcd, 0x35, 0xa8, 0xba, 0xb7, 0x61, 0xef, 0x88, 0xb2, 0xc3, 0xb8, 0xdf, 0x1f, 0x44, 0x61, + 0x07, 0x6d, 0xcc, 0xa3, 0x3d, 0x7f, 0x48, 0xd3, 0x4c, 0x59, 0xd6, 0xa7, 0xb0, 0x5e, 0x35, 0x4e, + 0x9a, 0x30, 0x27, 0xf7, 0x1e, 0xf9, 0xcf, 0x7b, 0xea, 0x93, 0xec, 0x40, 0xbd, 0x13, 0x47, 0x11, + 0xed, 0x30, 0x1a, 0xc8, 0x85, 0xe4, 0x00, 0xf7, 0x8f, 0x6b, 0x70, 0x6b, 0x34, 0x4f, 0x69, 0xba, + 0x5f, 0xc1, 0x66, 0xc7, 0x44, 0x68, 0xa7, 0x12, 0xa3, 0xe9, 0xe0, 0x56, 0x1c, 0x1a, 0x5b, 0x31, + 0x96, 0xd2, 0x7e, 0xe5, 0xa8, 0xd8, 0xa4, 0x8d, 0x4e, 0xd5, 0x58, 0xab, 0x0b, 0xad, 0xd1, 0x93, + 0x2a, 0x54, 0xfe, 0xd0, 0x56, 0xf9, 0x8e, 0x12, 0xad, 0x8a, 0x88, 0xa9, 0xfb, 0x6f, 0xc3, 0xd6, + 0x11, 0x8d, 0x68, 0x1a, 0x76, 0xb4, 0x71, 0x48, 0x9d, 0x73, 0x0d, 0x6a, 0x9b, 0x94, 0xac, 0x72, + 0x80, 0xdb, 0x82, 0x66, 0x79, 0xa2, 0x58, 0xae, 0xbb, 0x09, 0xeb, 0x47, 0x94, 0x69, 0xb8, 0xde, + 0xc5, 0x9f, 0x3a, 0xb0, 0x81, 0x03, 0xd9, 0x69, 0x36, 0x14, 0x03, 0x52, 0xd5, 0xbf, 0x03, 0xab, + 0x9a, 0x74, 0xa6, 0x8e, 0x91, 0xd0, 0xf2, 0x5b, 0x86, 0x96, 0xcb, 0x33, 0xf3, 0xc3, 0x94, 0x99, + 0xa7, 0x29, 0x3f, 0x93, 0x12, 0xdc, 0x3a, 0x84, 0x8d, 0x4a, 0xd4, 0xeb, 0xd8, 0xbf, 0xdb, 0x84, + 0xcd, 0x23, 0xca, 0x0c, 0x33, 0x36, 0x0c, 0x74, 0xc1, 0x00, 0x73, 0xbb, 0xcc, 0x98, 0x9f, 0xb2, + 0xdc, 0x2e, 0xe5, 0x27, 0x79, 0x15, 0x96, 0x7a, 0x61, 0xc6, 0x68, 0xd4, 0xf6, 0x83, 0x20, 0xa5, + 0x99, 0x70, 0x79, 0x75, 0x6f, 0x51, 0x40, 0x0f, 0x04, 0xd0, 0xfd, 0x47, 0x87, 0x6f, 0x4c, 0x81, + 0x95, 0x54, 0xd6, 0x27, 0x50, 0xcf, 0xbd, 0x82, 0x50, 0xd2, 0xbe, 0xa1, 0xa4, 0xaa, 0x39, 0xfb, + 0x05, 0xd7, 0x90, 0x13, 0x68, 0xfd, 0x16, 0x2c, 0xbd, 0xe8, 0x03, 0xfd, 0x36, 0xb4, 0xa4, 0x6d, + 0x28, 0x8f, 0xfc, 0xa9, 0xdf, 0xa7, 0xca, 0xae, 0x5a, 0x30, 0xaf, 0x1c, 0xb8, 0xe4, 0xa1, 0xbf, + 0xdd, 0x5d, 0xd8, 0xae, 0x9c, 0x29, 0x0d, 0xeb, 0x01, 0xac, 0x1d, 0x51, 0xa6, 0xdd, 0xbc, 0xa2, + 0x38, 0xd2, 0x0b, 0xb8, 0x8f, 0xd0, 0x12, 0x8d, 0x09, 0x52, 0x85, 0x3b, 0x50, 0xcf, 0x2f, 0x11, + 0x69, 0xdb, 0x1a, 0xe0, 0x3e, 0x44, 0x33, 0x55, 0xb3, 0x1e, 0x3f, 0x39, 0xf6, 0xa8, 0x98, 0x76, + 0x03, 0xe6, 0x63, 0x96, 0xb4, 0x3b, 0x71, 0xa0, 0x44, 0x9f, 0x8b, 0x59, 0x72, 0x18, 0x07, 0x54, + 0x9a, 0x86, 0x31, 0x47, 0x9b, 0xc6, 0xdf, 0x88, 0xad, 0xb4, 0x87, 0xa4, 0x1c, 0xbf, 0x09, 0x75, + 0x45, 0x50, 0x6d, 0xe5, 0xb7, 0x8c, 0xad, 0xac, 0x9a, 0xb3, 0xff, 0x58, 0x70, 0x94, 0x3b, 0x39, + 0x2f, 0x05, 0xc8, 0x5a, 0xef, 0xc0, 0xa2, 0x35, 0x74, 0x95, 0x65, 0xd7, 0xcd, 0x2d, 0x7b, 0x04, + 0x9b, 0xef, 0x87, 0x99, 0x79, 0xe3, 0x4e, 0xb2, 0x5d, 0x5f, 0xc0, 0xd2, 0xb1, 0x1f, 0xa6, 0xd9, + 0xc9, 0x20, 0x49, 0x62, 0x34, 0xef, 0xd7, 0x60, 0x39, 0xbf, 0xd6, 0x13, 0x3e, 0x26, 0x27, 0x2d, + 0x69, 0x30, 0xce, 0x20, 0xaf, 0xc0, 0xa2, 0xba, 0xce, 0x05, 0x9a, 0x10, 0xa9, 0x21, 0x81, 0x88, + 0xe4, 0x7e, 0x3d, 0x6d, 0xa9, 0xce, 0x0a, 0x2c, 0x08, 0x4c, 0x47, 0xbe, 0x0e, 0x2b, 0xf0, 0xb7, + 0x69, 0x08, 0x35, 0xfb, 0x3a, 0x68, 0xc2, 0xdc, 0x05, 0x4d, 0x4f, 0xe3, 0x8c, 0x62, 0xcc, 0x30, + 0xef, 0xa9, 0x4f, 0x2e, 0xc8, 0x20, 0x0b, 0xa3, 0xb3, 0x76, 0xe6, 0x47, 0xc1, 0x69, 0xfc, 0x1c, + 0x23, 0x84, 0x79, 0xaf, 0x81, 0xc0, 0x13, 0x01, 0x23, 0xb7, 0xa1, 0x71, 0xce, 0x58, 0xd2, 0xe6, + 0xa1, 0x4b, 0x3c, 0x60, 0x32, 0x20, 0x58, 0xe0, 0xb0, 0x27, 0x02, 0xc4, 0x0f, 0x36, 0xa2, 0x0c, + 0x32, 0x9a, 0xfa, 0x67, 0x34, 0x62, 0xcd, 0x59, 0x71, 0xb0, 0x39, 0xf4, 0x87, 0x0a, 0x48, 0x76, + 0x01, 0x10, 0x2d, 0x49, 0xe3, 0xe7, 0xc3, 0xe6, 0x9c, 0x30, 0x3d, 0x0e, 0x39, 0xe6, 0x00, 0xae, + 0xbf, 0x53, 0x3f, 0xa3, 0x2a, 0xf4, 0x08, 0x69, 0xd6, 0x9c, 0x17, 0xfa, 0xe3, 0xe0, 0x43, 0x0d, + 0x25, 0x6d, 0x1e, 0x77, 0x48, 0xad, 0xb7, 0xfd, 0x2c, 0xa3, 0x2c, 0x6b, 0xd6, 0xd1, 0x80, 0x1e, + 0x55, 0x18, 0x50, 0x21, 0xfe, 0x90, 0xf3, 0x0e, 0x70, 0x9a, 0x8e, 0x3f, 0x2c, 0x28, 0x8f, 0xb7, + 0xfc, 0x01, 0x3b, 0xa7, 0x11, 0xe3, 0xb7, 0x07, 0x67, 0x92, 0x84, 0x4d, 0x40, 0xdd, 0xac, 0x58, + 0x03, 0x07, 0x49, 0xd8, 0xfa, 0x9c, 0x07, 0x17, 0x65, 0xaa, 0x15, 0x26, 0xf8, 0xba, 0xed, 0x4a, + 0x36, 0x95, 0xb0, 0xb6, 0x1d, 0x99, 0xa6, 0x79, 0x09, 0x2b, 0x47, 0x94, 0x3d, 0x09, 0x3b, 0xcf, + 0x68, 0x3a, 0x81, 0x51, 0x92, 0xbb, 0x30, 0xcd, 0x2d, 0x4a, 0x32, 0x58, 0xd7, 0x37, 0xa1, 0x8c, + 0xd8, 0x38, 0x23, 0x0f, 0x31, 0xf8, 0x5e, 0xa0, 0xe6, 0xda, 0x6c, 0x98, 0x08, 0xbb, 0xa8, 0x7b, + 0x75, 0x84, 0x3c, 0x19, 0x26, 0xd4, 0x7d, 0x0a, 0x0d, 0x73, 0x12, 0x77, 0x1a, 0x01, 0xed, 0x85, + 0xfd, 0x90, 0xd1, 0x54, 0x39, 0x0d, 0x0d, 0xe0, 0xf6, 0xc8, 0xb7, 0x48, 0xda, 0x31, 0xfe, 0xe6, + 0xe7, 0xed, 0xcb, 0x41, 0xcc, 0x14, 0x6d, 0xf1, 0xe1, 0xfe, 0x45, 0x0d, 0x96, 0xd4, 0x72, 0xa4, + 0x31, 0x2b, 0x99, 0x9d, 0x2b, 0x65, 0xbe, 0x0d, 0x8d, 0x9e, 0x9f, 0xb1, 0xf6, 0x20, 0x09, 0x7c, + 0x15, 0xda, 0x4c, 0x79, 0x0b, 0x1c, 0xf6, 0x43, 0x01, 0xe2, 0x16, 0xad, 0x22, 0x57, 0x3c, 0x5b, + 0x92, 0x7b, 0xa3, 0x63, 0x2e, 0x86, 0xc0, 0x34, 0x9f, 0x83, 0xd6, 0xee, 0x78, 0xf8, 0x9b, 0xc3, + 0xce, 0xc3, 0xb3, 0x73, 0xb4, 0x6e, 0xc7, 0xc3, 0xdf, 0x7c, 0x07, 0x7b, 0xf1, 0x25, 0xda, 0xb2, + 0xe3, 0xf1, 0x9f, 0x1c, 0x72, 0x1a, 0x06, 0x68, 0xba, 0x8e, 0xc7, 0x7f, 0x72, 0x88, 0x9f, 0x3d, + 0x43, 0x43, 0x75, 0x3c, 0xfe, 0x93, 0x47, 0xfd, 0x17, 0x71, 0x6f, 0xd0, 0xa7, 0xcd, 0x3a, 0x02, + 0xe5, 0x17, 0xd9, 0x86, 0x7a, 0x92, 0x86, 0x1d, 0xda, 0xf6, 0xd9, 0x39, 0x1a, 0x93, 0xe3, 0xcd, + 0x23, 0xe0, 0x80, 0x9d, 0xbb, 0x6b, 0xb0, 0xaa, 0x37, 0x5a, 0x7b, 0xcf, 0xcf, 0x60, 0x4e, 0x42, + 0xc6, 0x6e, 0xfa, 0x1b, 0x30, 0xc7, 0x04, 0x5a, 0xb3, 0x86, 0xa7, 0x40, 0x1b, 0x96, 0xad, 0x69, + 0x4f, 0xa1, 0xb9, 0xdf, 0x03, 0x62, 0x72, 0x93, 0x1b, 0x71, 0x2f, 0xa7, 0x23, 0xdc, 0xf1, 0xb2, + 0x4d, 0x27, 0xcb, 0x09, 0x7c, 0x85, 0x97, 0xd1, 0xe3, 0x34, 0xe0, 0x8e, 0x24, 0x7e, 0xf6, 0x52, + 0x4d, 0xf3, 0x07, 0xb0, 0xa8, 0x19, 0x7f, 0xc4, 0x68, 0x9f, 0x2b, 0xdc, 0xef, 0xc7, 0x83, 0x88, 0x21, 0x4f, 0xc7, 0x93, 0x5f, 0xdc, 0x02, 0x51, 0xbf, 0xc8, 0xd2, 0xf1, 0xc4, 0x07, 0x59, 0x82, - 0x5a, 0x18, 0xc8, 0xe4, 0xa9, 0x16, 0x06, 0xee, 0xff, 0x3a, 0xb0, 0x6a, 0x2c, 0xe4, 0xca, 0x46, - 0x59, 0xb2, 0xb8, 0x5a, 0x85, 0xc5, 0xdd, 0x83, 0xd9, 0x93, 0x30, 0xe0, 0x39, 0x1b, 0xd7, 0xeb, - 0x86, 0x22, 0x67, 0xad, 0xc3, 0x43, 0x14, 0x8e, 0xea, 0x67, 0xcf, 0xb2, 0xd6, 0xec, 0x44, 0x54, - 0x8e, 0x52, 0x3a, 0x0f, 0xd7, 0xca, 0xe7, 0xc1, 0xd6, 0xe5, 0x5c, 0x51, 0x97, 0x22, 0x5a, 0xd5, - 0xb4, 0xb5, 0xe5, 0x75, 0x01, 0x72, 0xe0, 0xc4, 0x6d, 0xfd, 0x35, 0x80, 0x58, 0x63, 0x4a, 0xfb, - 0xbb, 0x5e, 0x12, 0x5a, 0x9b, 0xa0, 0x81, 0xec, 0x7e, 0x8c, 0xa1, 0x86, 0xc9, 0x5c, 0x2a, 0xff, - 0x81, 0x45, 0x53, 0xd8, 0x22, 0x29, 0xd1, 0xcc, 0x2c, 0x62, 0x6f, 0x23, 0xb1, 0xfd, 0x6e, 0x97, - 0x6f, 0xbd, 0x91, 0x98, 0x4f, 0xbc, 0xc3, 0x9f, 0xc2, 0xbc, 0x9c, 0x21, 0xcd, 0x42, 0x20, 0xd4, - 0xc2, 0x80, 0xbc, 0x0b, 0x60, 0xdc, 0x43, 0x62, 0x5d, 0xdb, 0x4a, 0x06, 0x39, 0x49, 0x59, 0x03, - 0xb2, 0x33, 0xd0, 0xdd, 0x1e, 0xac, 0x55, 0xa0, 0x70, 0x51, 0x74, 0x5a, 0x2d, 0x45, 0x51, 0xdf, - 0xe4, 0x26, 0x34, 0x58, 0xcc, 0xfc, 0x7e, 0x27, 0xbf, 0x21, 0x1c, 0x0f, 0x10, 0xf4, 0x94, 0x43, - 0xd0, 0x41, 0xc5, 0x7d, 0x61, 0xb9, 0xdc, 0x41, 0xc5, 0xfd, 0xc0, 0xf5, 0x31, 0xf0, 0xb2, 0x16, - 0x2d, 0x55, 0x38, 0x69, 0xcb, 0x5e, 0x83, 0x05, 0x5f, 0x4c, 0x51, 0x0b, 0x5b, 0x2e, 0x2c, 0xcc, - 0xd3, 0x08, 0x2e, 0xc1, 0x1b, 0xe8, 0x20, 0x8e, 0x7a, 0xe1, 0xa9, 0xb2, 0x8e, 0x57, 0xd0, 0x59, - 0x29, 0x58, 0x1e, 0x93, 0x04, 0x3e, 0xf3, 0x91, 0x5b, 0xd3, 0xc3, 0xdf, 0xee, 0x1f, 0x39, 0xb0, - 0x72, 0x14, 0xa7, 0xac, 0x17, 0xf7, 0xc3, 0x58, 0x86, 0xf7, 0x3c, 0x1c, 0x51, 0xe1, 0xbf, 0x8c, - 0x23, 0xe5, 0x27, 0xf7, 0x90, 0xdd, 0x38, 0x8c, 0x84, 0xad, 0xd6, 0xa4, 0x82, 0xe2, 0x30, 0xe2, - 0xa6, 0x4a, 0x6e, 0x41, 0x23, 0xa0, 0x59, 0x37, 0x0d, 0x13, 0x9e, 0xce, 0x49, 0xb7, 0x60, 0x82, - 0x38, 0xe1, 0x13, 0xbf, 0xef, 0x47, 0x5d, 0x2a, 0x3d, 0xbb, 0xfa, 0x74, 0x37, 0xd0, 0x5d, 0x69, - 0x49, 0x8c, 0xcc, 0xda, 0x06, 0xcb, 0xa5, 0xfc, 0x2a, 0xd4, 0x13, 0x05, 0x94, 0xe6, 0xd7, 0xd2, - 0x77, 0x75, 0x61, 0x39, 0x5e, 0x8e, 0xea, 0xee, 0xf0, 0xd8, 0x3f, 0xa7, 0x77, 0x3c, 0x1c, 0x0c, - 0xfc, 0x74, 0xa4, 0xb8, 0x45, 0x30, 0x7b, 0x10, 0x87, 0x11, 0x57, 0x14, 0x5f, 0x94, 0x0a, 0xde, - 0xf8, 0x6f, 0x53, 0xf4, 0x9a, 0x25, 0xba, 0xa9, 0xad, 0x19, 0x5b, 0x5b, 0x37, 0x00, 0x12, 0x9a, - 0x76, 0x69, 0xc4, 0xfc, 0x53, 0xb5, 0x62, 0x03, 0xe2, 0x9e, 0x01, 0x79, 0xdc, 0xeb, 0xf5, 0xc3, - 0x88, 0x72, 0xb6, 0x52, 0x98, 0x09, 0xda, 0x1f, 0x2f, 0x83, 0xcd, 0x69, 0xa6, 0xc4, 0xe9, 0x07, - 0xb0, 0xfa, 0x38, 0xaa, 0x60, 0xa4, 0xc8, 0x39, 0x93, 0xc8, 0xd5, 0x4a, 0xe4, 0xbe, 0x0f, 0x4d, - 0x43, 0xf0, 0x8c, 0xbc, 0x03, 0x75, 0x29, 0xa3, 0x4e, 0x14, 0xda, 0xda, 0x1b, 0x94, 0x56, 0xe8, - 0xe5, 0xc8, 0xee, 0x5f, 0x3a, 0xd0, 0xc8, 0x25, 0xcb, 0xc8, 0x43, 0xb8, 0xc6, 0xd5, 0xad, 0xa8, - 0xdc, 0xd0, 0x54, 0x72, 0x9c, 0x3d, 0xfc, 0xaf, 0x88, 0x0b, 0x05, 0x72, 0xfb, 0x18, 0x20, 0x07, - 0x56, 0x84, 0x75, 0xf7, 0xed, 0xb0, 0xee, 0x7a, 0x99, 0xaa, 0x12, 0xcd, 0x88, 0xec, 0xfe, 0x65, - 0x96, 0xa7, 0x7b, 0x15, 0xc6, 0x22, 0x6d, 0xf0, 0x0d, 0x68, 0x88, 0xb3, 0xc0, 0x3d, 0x80, 0x12, - 0xb8, 0x99, 0x97, 0x36, 0xc2, 0xc8, 0x03, 0x3c, 0x1b, 0x38, 0x4e, 0xde, 0x82, 0x45, 0x14, 0xb6, - 0x13, 0x0b, 0x85, 0xc8, 0x83, 0x6d, 0x4f, 0x68, 0x22, 0x8a, 0x54, 0x19, 0x49, 0x60, 0xc3, 0x9a, - 0xd2, 0xc9, 0x84, 0x08, 0xf2, 0x92, 0x7a, 0xcf, 0x08, 0xa5, 0xc7, 0x49, 0x29, 0x94, 0x25, 0x09, - 0xca, 0x31, 0xa1, 0xba, 0xb5, 0x6e, 0x79, 0x84, 0xdc, 0x87, 0xa6, 0xe4, 0x88, 0x9a, 0x91, 0x57, - 0x9c, 0x2d, 0x63, 0x43, 0x4c, 0x44, 0x04, 0x32, 0x80, 0x75, 0x73, 0x82, 0x96, 0xf0, 0x1a, 0x4e, - 0x7c, 0x77, 0x7a, 0x09, 0xa3, 0x92, 0x80, 0xa4, 0x5b, 0x1a, 0x68, 0xff, 0x36, 0xb4, 0xc6, 0x2d, - 0xa8, 0x62, 0xdb, 0x5f, 0xb5, 0xb7, 0x7d, 0xbd, 0xc2, 0x24, 0x33, 0xb3, 0x80, 0xf8, 0x39, 0x6c, - 0x8d, 0x11, 0xe6, 0x0a, 0x55, 0x07, 0xc3, 0x52, 0x4d, 0x6b, 0xfa, 0x73, 0x07, 0xda, 0xfb, 0x41, - 0x50, 0x72, 0x4e, 0x79, 0x91, 0xe0, 0x9b, 0x76, 0xb9, 0xbb, 0xb0, 0x5d, 0x29, 0x90, 0xac, 0x66, - 0x3c, 0x87, 0x5d, 0x8f, 0x0e, 0xe2, 0x73, 0xfa, 0x4d, 0x8b, 0xec, 0xde, 0x82, 0x1b, 0xe3, 0x38, + 0x5a, 0x18, 0xc8, 0xe4, 0xa9, 0x16, 0x06, 0xee, 0xff, 0x3a, 0xb0, 0x6a, 0x2c, 0xe4, 0xda, 0x46, + 0x59, 0xb2, 0xb8, 0x5a, 0x85, 0xc5, 0xdd, 0x83, 0xe9, 0xd3, 0x30, 0xe0, 0x39, 0x1b, 0xd7, 0xeb, + 0x86, 0x22, 0x67, 0xad, 0xc3, 0x43, 0x14, 0x8e, 0xea, 0x67, 0xcf, 0xb2, 0xe6, 0xf4, 0x58, 0x54, + 0x8e, 0x52, 0x3a, 0x0f, 0x33, 0xe5, 0xf3, 0x60, 0xeb, 0x72, 0xb6, 0xa8, 0x4b, 0x11, 0xad, 0x6a, + 0xda, 0xda, 0xf2, 0x3a, 0x00, 0x39, 0x70, 0xec, 0xb6, 0xfe, 0x1a, 0x40, 0xac, 0x31, 0xa5, 0xfd, + 0xdd, 0x28, 0x09, 0xad, 0x4d, 0xd0, 0x40, 0x76, 0x3f, 0xc6, 0x50, 0xc3, 0x64, 0x2e, 0x95, 0xff, + 0xd0, 0xa2, 0x29, 0x6c, 0x91, 0x94, 0x68, 0x66, 0x16, 0xb1, 0xb7, 0x90, 0xd8, 0x41, 0xa7, 0xc3, + 0xb7, 0xde, 0x48, 0xcc, 0xc7, 0xde, 0xe1, 0x4f, 0x61, 0x4e, 0xce, 0x90, 0x66, 0x21, 0x10, 0x6a, + 0x61, 0x40, 0xde, 0x01, 0x30, 0xee, 0x21, 0xb1, 0xae, 0x6d, 0x25, 0x83, 0x9c, 0xa4, 0xac, 0x01, + 0xd9, 0x19, 0xe8, 0x6e, 0x17, 0xd6, 0x2a, 0x50, 0xb8, 0x28, 0x3a, 0xad, 0x96, 0xa2, 0xa8, 0x6f, + 0xb2, 0x07, 0x0b, 0x2c, 0x66, 0x7e, 0xaf, 0x9d, 0xdf, 0x10, 0x8e, 0x07, 0x08, 0x7a, 0xca, 0x21, + 0xe8, 0xa0, 0xe2, 0x9e, 0xb0, 0x5c, 0xee, 0xa0, 0xe2, 0x5e, 0xe0, 0xfa, 0x18, 0x78, 0x59, 0x8b, + 0x96, 0x2a, 0x1c, 0xb7, 0x65, 0xdf, 0x84, 0x79, 0x5f, 0x4c, 0x51, 0x0b, 0x5b, 0x2e, 0x2c, 0xcc, + 0xd3, 0x08, 0x2e, 0xc1, 0x1b, 0xe8, 0x30, 0x8e, 0xba, 0xe1, 0x99, 0xb2, 0x8e, 0xd7, 0xd0, 0x59, + 0x29, 0x58, 0x1e, 0x93, 0x04, 0x3e, 0xf3, 0x91, 0x5b, 0xc3, 0xc3, 0xdf, 0xee, 0x1f, 0x39, 0xb0, + 0x72, 0x1c, 0xa7, 0xac, 0x1b, 0xf7, 0xc2, 0x58, 0x86, 0xf7, 0x3c, 0x1c, 0x51, 0xe1, 0xbf, 0x8c, + 0x23, 0xe5, 0x27, 0xf7, 0x90, 0x9d, 0x38, 0x8c, 0x84, 0xad, 0xd6, 0xa4, 0x82, 0xe2, 0x30, 0xe2, + 0xa6, 0x4a, 0x6e, 0xc1, 0x42, 0x40, 0xb3, 0x4e, 0x1a, 0x26, 0x3c, 0x9d, 0x93, 0x6e, 0xc1, 0x04, + 0x71, 0xc2, 0xa7, 0x7e, 0xcf, 0x8f, 0x3a, 0x54, 0x7a, 0x76, 0xf5, 0xe9, 0x6e, 0xa0, 0xbb, 0xd2, + 0x92, 0x18, 0x99, 0xb5, 0x0d, 0x96, 0x4b, 0xf9, 0x55, 0xa8, 0x27, 0x0a, 0x28, 0xcd, 0xaf, 0xa9, + 0xef, 0xea, 0xc2, 0x72, 0xbc, 0x1c, 0xd5, 0xdd, 0xe1, 0xb1, 0x7f, 0x4e, 0xef, 0x64, 0xd0, 0xef, + 0xfb, 0xe9, 0x50, 0x71, 0x8b, 0x60, 0xfa, 0x30, 0x0e, 0x23, 0xae, 0x28, 0xbe, 0x28, 0x15, 0xbc, + 0xf1, 0xdf, 0xa6, 0xe8, 0x35, 0x4b, 0x74, 0x53, 0x5b, 0x53, 0xb6, 0xb6, 0x6e, 0x02, 0x24, 0x34, + 0xed, 0xd0, 0x88, 0xf9, 0x67, 0x6a, 0xc5, 0x06, 0xc4, 0x3d, 0x07, 0xf2, 0xb8, 0xdb, 0xed, 0x85, + 0x11, 0xe5, 0x6c, 0xa5, 0x30, 0x63, 0xb4, 0x3f, 0x5a, 0x06, 0x9b, 0xd3, 0x54, 0x89, 0xd3, 0x0f, + 0x60, 0xf5, 0x71, 0x54, 0xc1, 0x48, 0x91, 0x73, 0xc6, 0x91, 0xab, 0x95, 0xc8, 0x7d, 0x1f, 0x1a, + 0x86, 0xe0, 0x19, 0x79, 0x1b, 0xea, 0x52, 0x46, 0x9d, 0x28, 0xb4, 0xb4, 0x37, 0x28, 0xad, 0xd0, + 0xcb, 0x91, 0xdd, 0xbf, 0x74, 0x60, 0x21, 0x97, 0x2c, 0x23, 0x8f, 0x60, 0x86, 0xab, 0x5b, 0x51, + 0xb9, 0xa9, 0xa9, 0xe4, 0x38, 0xfb, 0xf8, 0x5f, 0x11, 0x17, 0x0a, 0xe4, 0xd6, 0x09, 0x40, 0x0e, + 0xac, 0x08, 0xeb, 0x1e, 0xd8, 0x61, 0xdd, 0x8d, 0x32, 0x55, 0x25, 0x9a, 0x11, 0xd9, 0xfd, 0xcb, + 0x34, 0x4f, 0xf7, 0x2a, 0x8c, 0x45, 0xda, 0xe0, 0xb7, 0x60, 0x41, 0x9c, 0x05, 0xee, 0x01, 0x94, + 0xc0, 0x8d, 0xbc, 0xb4, 0x11, 0x46, 0x1e, 0xe0, 0xd9, 0xc0, 0x71, 0xf2, 0x26, 0x2c, 0xa2, 0xb0, + 0xed, 0x58, 0x28, 0x44, 0x1e, 0x6c, 0x7b, 0x42, 0x03, 0x51, 0xa4, 0xca, 0x48, 0x02, 0x1b, 0xd6, + 0x94, 0x76, 0x26, 0x44, 0x90, 0x97, 0xd4, 0xbb, 0x46, 0x28, 0x3d, 0x4a, 0x4a, 0xa1, 0x2c, 0x49, + 0x50, 0x8e, 0x09, 0xd5, 0xad, 0x75, 0xca, 0x23, 0xe4, 0x01, 0x34, 0x24, 0x47, 0xd4, 0x8c, 0xbc, + 0xe2, 0x6c, 0x19, 0x17, 0xc4, 0x44, 0x44, 0x20, 0x7d, 0x58, 0x37, 0x27, 0x68, 0x09, 0x67, 0x70, + 0xe2, 0x3b, 0x93, 0x4b, 0x18, 0x95, 0x04, 0x24, 0x9d, 0xd2, 0x40, 0xeb, 0xb7, 0xa1, 0x39, 0x6a, + 0x41, 0x15, 0xdb, 0x7e, 0xdf, 0xde, 0xf6, 0xf5, 0x0a, 0x93, 0xcc, 0xcc, 0x02, 0xe2, 0xe7, 0xb0, + 0x35, 0x42, 0x98, 0x6b, 0x54, 0x1d, 0x0c, 0x4b, 0x35, 0xad, 0xe9, 0xcf, 0x1d, 0x68, 0x1d, 0x04, + 0x41, 0xc9, 0x39, 0xe5, 0x45, 0x82, 0x97, 0xed, 0x72, 0x77, 0x61, 0xbb, 0x52, 0x20, 0x59, 0xcd, + 0x78, 0x0e, 0xbb, 0x1e, 0xed, 0xc7, 0x17, 0xf4, 0x65, 0x8b, 0xec, 0xde, 0x82, 0x9b, 0xa3, 0x38, 0x4b, 0xd9, 0xb0, 0xbc, 0x67, 0x97, 0xc7, 0x75, 0x60, 0xf4, 0x9f, 0x0e, 0x2c, 0xda, 0x85, 0xf3, - 0x17, 0x95, 0x8b, 0xbf, 0x0e, 0x24, 0xa5, 0x19, 0xeb, 0x24, 0x71, 0xbf, 0xcf, 0x53, 0xf2, 0x80, - 0xf6, 0xfd, 0x91, 0x2c, 0xd9, 0xaf, 0xf0, 0x91, 0x23, 0x31, 0xf0, 0x88, 0xc3, 0xc9, 0x16, 0xcc, - 0xfb, 0x49, 0xd8, 0xe1, 0x56, 0x23, 0xf2, 0xf1, 0x39, 0x3f, 0x09, 0x3f, 0xa6, 0x23, 0xe2, 0xc2, - 0xa2, 0x1c, 0xe8, 0xf4, 0xe9, 0x39, 0xed, 0x63, 0xcc, 0x37, 0xe3, 0x35, 0xc4, 0xf0, 0x27, 0x1c, - 0x44, 0xee, 0xc1, 0x4a, 0x92, 0x86, 0xdc, 0xfc, 0xf2, 0xb7, 0x81, 0x79, 0x94, 0x66, 0x59, 0xc2, - 0xd5, 0xea, 0xdc, 0x1f, 0xc1, 0xf5, 0x0a, 0x5d, 0x48, 0x1f, 0xf5, 0x5d, 0x58, 0xb6, 0x5f, 0x18, - 0x94, 0x9f, 0xd2, 0x51, 0xab, 0x35, 0xd1, 0x5b, 0xea, 0x59, 0x74, 0x64, 0xf4, 0x89, 0x38, 0x9e, - 0xcf, 0x74, 0x4d, 0xcb, 0xfd, 0x12, 0xd6, 0x73, 0xe0, 0x41, 0x1c, 0x9d, 0xd3, 0x34, 0xe3, 0xd6, - 0x46, 0x60, 0xb6, 0x97, 0xc6, 0xaa, 0x20, 0x8b, 0xbf, 0x79, 0xdc, 0xc6, 0x62, 0x69, 0x06, 0x35, - 0x16, 0x73, 0x9c, 0xd4, 0x67, 0xea, 0x96, 0xc2, 0xdf, 0x3c, 0x4e, 0x0e, 0x91, 0x08, 0xed, 0xe0, - 0x98, 0x30, 0xd5, 0x86, 0x84, 0x71, 0x2e, 0xee, 0x53, 0x0c, 0x1f, 0x4d, 0x51, 0xe4, 0x1a, 0x7f, - 0x1d, 0x1a, 0x62, 0x8d, 0x7c, 0xa6, 0x5a, 0xdf, 0x8e, 0xb5, 0xbe, 0x82, 0x98, 0x1e, 0xf4, 0x34, - 0xd4, 0xfd, 0xef, 0x1a, 0x34, 0x31, 0x62, 0x7d, 0x44, 0x99, 0x1f, 0xf6, 0x27, 0xc7, 0xd2, 0x22, - 0x06, 0xad, 0xe9, 0x18, 0xf4, 0x25, 0x58, 0x34, 0x0b, 0x22, 0x23, 0x95, 0xcc, 0x1a, 0xe5, 0x90, - 0x11, 0x79, 0x19, 0x96, 0x30, 0xb5, 0xce, 0xb1, 0x84, 0xcd, 0x2c, 0x22, 0x54, 0xa3, 0xd9, 0x89, - 0xc0, 0xb5, 0x42, 0x22, 0xc0, 0x87, 0x31, 0x98, 0xee, 0x64, 0x61, 0xa0, 0xf3, 0x04, 0x84, 0x1c, - 0x87, 0x81, 0x31, 0x8c, 0xb3, 0xe7, 0x8d, 0x61, 0x9c, 0xcd, 0x73, 0xa0, 0x94, 0x8a, 0x87, 0x02, - 0x7c, 0xef, 0x5a, 0x40, 0xa3, 0x6b, 0x2a, 0xe0, 0x93, 0x70, 0x80, 0xaf, 0x61, 0xb2, 0xb8, 0x5d, - 0x17, 0x16, 0x2b, 0xbe, 0xf2, 0x34, 0x0d, 0xcc, 0x34, 0x2d, 0x4f, 0xea, 0x1a, 0x56, 0x52, 0x77, - 0x13, 0x1a, 0x71, 0x42, 0xa3, 0x8e, 0x4c, 0xb1, 0x9b, 0x22, 0x7a, 0xe0, 0xa0, 0xa7, 0x08, 0x91, - 0x25, 0x13, 0xd4, 0x79, 0x36, 0x4d, 0x5e, 0x6a, 0x2b, 0xa6, 0x56, 0x54, 0x8c, 0x4a, 0x04, 0x67, - 0x2e, 0x4b, 0x04, 0xdd, 0x7d, 0x8c, 0x8a, 0x15, 0x63, 0x69, 0x3e, 0xaf, 0xc3, 0x1c, 0xaa, 0x49, - 0x59, 0xce, 0xba, 0x95, 0xc6, 0x48, 0xa3, 0xf0, 0x24, 0x8e, 0xfb, 0x7d, 0x7c, 0x43, 0xc4, 0xa1, - 0x69, 0x44, 0xbf, 0x0e, 0x0b, 0x62, 0x57, 0xb4, 0xd5, 0xcc, 0xe3, 0xf7, 0x47, 0x81, 0xfb, 0x6f, - 0x0e, 0x90, 0xe3, 0xe1, 0xc9, 0x20, 0x9c, 0x9e, 0xda, 0xf4, 0x09, 0x3a, 0x81, 0x59, 0x34, 0x13, - 0x61, 0x8e, 0xf8, 0xbb, 0x60, 0x21, 0xb3, 0x45, 0x0b, 0xc9, 0xb7, 0xf3, 0x5a, 0x75, 0x8e, 0x3e, - 0x67, 0x6e, 0x3e, 0x77, 0xf1, 0xfd, 0x90, 0x46, 0xac, 0x23, 0x8b, 0x2d, 0xdc, 0xc5, 0x23, 0xe0, - 0xa3, 0xc0, 0x3d, 0x86, 0x35, 0x6b, 0x65, 0x52, 0xd3, 0xb7, 0xa1, 0x29, 0x04, 0x48, 0xfa, 0x7e, - 0x57, 0x57, 0xc3, 0x1b, 0x08, 0x3b, 0x42, 0xd0, 0x24, 0x7d, 0xfd, 0x89, 0x03, 0xeb, 0xc7, 0xe1, - 0x60, 0xd8, 0xf7, 0x19, 0xfd, 0x25, 0x68, 0x2c, 0x5f, 0xfe, 0x8c, 0xb5, 0x7c, 0xa5, 0xc9, 0xd9, - 0x5c, 0x93, 0xee, 0xcf, 0x1c, 0xd8, 0x28, 0x88, 0xa2, 0x63, 0x42, 0xdb, 0x98, 0xc6, 0x14, 0x07, - 0x24, 0x92, 0xc1, 0xb4, 0x66, 0x31, 0x7d, 0x09, 0x16, 0x07, 0x61, 0x14, 0x0e, 0x86, 0x83, 0x8e, - 0xd0, 0xbd, 0x90, 0xa9, 0x29, 0x81, 0x47, 0xb8, 0x05, 0x1c, 0xc9, 0x7f, 0x6e, 0x20, 0xcd, 0x4a, - 0x24, 0x01, 0x14, 0x48, 0x6f, 0xc2, 0x7a, 0x1e, 0xb7, 0x77, 0x4e, 0xfd, 0x30, 0xea, 0xf4, 0xe3, - 0x2c, 0x93, 0x7b, 0x4c, 0xf2, 0xb1, 0x43, 0x3f, 0x8c, 0x3e, 0x89, 0xb3, 0xcc, 0x70, 0x02, 0x73, - 0xa6, 0x13, 0xe0, 0x01, 0xcc, 0xca, 0x67, 0x67, 0x7e, 0x9f, 0xbe, 0x1f, 0x0f, 0x4e, 0x5e, 0xac, - 0xee, 0x6f, 0x43, 0x53, 0xd4, 0xdd, 0x98, 0x9f, 0x9e, 0x52, 0xb5, 0x03, 0x0d, 0x84, 0x3d, 0x41, - 0x50, 0xe5, 0x36, 0xfc, 0x97, 0x03, 0xe4, 0x80, 0x87, 0x32, 0xfd, 0xa9, 0xed, 0x81, 0xbb, 0x12, - 0x91, 0x37, 0xe7, 0x16, 0x56, 0x97, 0x90, 0x8f, 0x6c, 0xf3, 0x9b, 0xb1, 0xcc, 0x4f, 0xaf, 0x66, - 0xf6, 0x8a, 0xc5, 0xb1, 0x92, 0x1f, 0x7f, 0x19, 0x96, 0x2e, 0xfc, 0x7e, 0x9f, 0x32, 0xfd, 0xc4, - 0x26, 0x2b, 0xf1, 0x02, 0xaa, 0x72, 0x70, 0xb5, 0xe0, 0x79, 0x63, 0xc1, 0x1b, 0xb0, 0x66, 0xad, - 0x57, 0x46, 0x43, 0x0f, 0x61, 0x53, 0x80, 0xf7, 0xfb, 0xfd, 0xa9, 0xbd, 0xaa, 0xfb, 0xd7, 0x35, - 0xd8, 0x2a, 0x4d, 0xd3, 0x61, 0x83, 0x6d, 0xc6, 0x77, 0xf4, 0x72, 0xab, 0x27, 0xec, 0xc9, 0x4f, - 0x39, 0xab, 0xfd, 0x4f, 0x0e, 0xcc, 0x09, 0xd0, 0xc4, 0xdd, 0xf8, 0x5c, 0x39, 0x04, 0x69, 0x70, - 0x22, 0x23, 0xfa, 0xf6, 0x74, 0xcc, 0xc4, 0xff, 0xcc, 0x67, 0x55, 0xe1, 0x49, 0xe4, 0x8b, 0xea, - 0x77, 0x61, 0xa5, 0x88, 0x70, 0xa5, 0x27, 0x27, 0x51, 0x55, 0xf9, 0xe0, 0x9c, 0x1a, 0xcf, 0xa8, - 0x3f, 0x75, 0x60, 0xf9, 0x20, 0x8e, 0x82, 0x90, 0xdf, 0x98, 0x47, 0x7e, 0xea, 0x0f, 0x32, 0xf9, - 0x92, 0x2f, 0x40, 0xaa, 0xec, 0xae, 0x01, 0x63, 0x0a, 0x9c, 0xbb, 0x00, 0xdd, 0x33, 0xda, 0x7d, - 0xd6, 0x91, 0x15, 0x47, 0xf1, 0xfc, 0xcf, 0x21, 0xef, 0x87, 0x41, 0x46, 0xde, 0x80, 0xb5, 0x7c, - 0xb8, 0xe3, 0x47, 0x41, 0x47, 0x96, 0x1b, 0xf1, 0x75, 0x43, 0xe3, 0xed, 0x47, 0xc1, 0x7e, 0xf6, - 0x2c, 0xe3, 0xb1, 0xa2, 0xae, 0xb2, 0x75, 0x2c, 0x17, 0xbe, 0xac, 0xe1, 0xfb, 0x08, 0x76, 0xff, - 0xc7, 0xc1, 0x1b, 0x50, 0xad, 0x4a, 0xee, 0x76, 0x5e, 0x58, 0xc3, 0x7a, 0xab, 0xb5, 0x65, 0xb5, - 0xc2, 0x96, 0x11, 0x98, 0x0d, 0x19, 0x1d, 0xa8, 0x8b, 0x85, 0xff, 0x26, 0xef, 0xc3, 0x8a, 0x5e, - 0x71, 0x27, 0x41, 0xb5, 0xc8, 0x63, 0xb2, 0x95, 0x27, 0x8e, 0x96, 0xd6, 0xbc, 0xe5, 0x6e, 0x41, - 0x8d, 0xea, 0x78, 0x5d, 0x9b, 0xca, 0x51, 0x77, 0x51, 0xdb, 0xd2, 0x3f, 0x89, 0x2f, 0x21, 0x35, - 0xed, 0x0e, 0x19, 0x0d, 0x64, 0xa8, 0xac, 0xbf, 0xdd, 0xff, 0x70, 0x60, 0x79, 0x3f, 0x08, 0x70, - 0xdd, 0xd3, 0xb8, 0x09, 0xb5, 0xca, 0xda, 0x25, 0xab, 0x9c, 0xf9, 0x39, 0x57, 0xf9, 0x0b, 0x3b, - 0x91, 0x31, 0x4a, 0x70, 0x5d, 0x58, 0xc9, 0xd7, 0x59, 0xbd, 0xbd, 0xee, 0xb7, 0x80, 0x88, 0xf4, - 0xca, 0x52, 0x47, 0x11, 0x6b, 0x03, 0xd6, 0x2c, 0x2c, 0xe9, 0x6b, 0x3e, 0x84, 0xbb, 0x87, 0x94, - 0x1d, 0xa4, 0xa3, 0x84, 0xc5, 0x2a, 0x9c, 0x7d, 0x44, 0x93, 0x38, 0x0b, 0x95, 0xe7, 0xa2, 0x53, - 0x79, 0x9f, 0x7f, 0x76, 0xe0, 0xde, 0x14, 0x84, 0xe4, 0x12, 0xbe, 0x28, 0xd7, 0x97, 0x7e, 0xc3, - 0x6c, 0x6f, 0x99, 0x8a, 0xca, 0x9e, 0x86, 0xc8, 0x2e, 0x03, 0x4d, 0xb2, 0xfd, 0x1e, 0x2c, 0xd9, - 0x83, 0x57, 0x72, 0x15, 0x7d, 0xb8, 0x73, 0x89, 0x10, 0xd3, 0xd8, 0xdc, 0x1d, 0x58, 0xea, 0x5a, - 0x24, 0x24, 0xa3, 0x02, 0xd4, 0x3d, 0x80, 0x57, 0x2e, 0xe5, 0x26, 0xd5, 0x36, 0x36, 0x43, 0x77, - 0xff, 0x6e, 0x16, 0xb6, 0x3e, 0x0b, 0xd9, 0x59, 0x90, 0xfa, 0x17, 0xca, 0xfa, 0xa6, 0x11, 0xb2, - 0x90, 0xbc, 0xd7, 0xca, 0xf5, 0x86, 0x57, 0x61, 0x35, 0x8e, 0x28, 0xe6, 0x18, 0x9d, 0xc4, 0xcf, - 0xb2, 0x8b, 0x38, 0x55, 0x77, 0xe9, 0x72, 0x1c, 0x51, 0x9e, 0x67, 0x1c, 0x49, 0x70, 0xe1, 0x36, - 0x9e, 0x2d, 0xde, 0xc6, 0x2b, 0x30, 0x93, 0x84, 0x91, 0x7c, 0x33, 0xe1, 0x3f, 0xf9, 0xdd, 0xc9, - 0x52, 0x3f, 0x30, 0x28, 0xcb, 0xbb, 0x13, 0xa1, 0x9a, 0xae, 0x59, 0xc5, 0x9f, 0x2f, 0x54, 0xf1, - 0x0d, 0x9d, 0x2c, 0xd8, 0x55, 0x8b, 0x9b, 0xd0, 0x90, 0x3f, 0x3b, 0xcc, 0x3f, 0x95, 0x29, 0x10, - 0x48, 0xd0, 0x13, 0xff, 0xd4, 0x88, 0xd6, 0xc0, 0x8a, 0xd6, 0x76, 0x01, 0x7a, 0x94, 0x76, 0xac, - 0x64, 0xa8, 0xde, 0xa3, 0x54, 0x38, 0x5d, 0x1e, 0x2a, 0x9f, 0xf8, 0xd1, 0xb3, 0x0e, 0xd6, 0x20, - 0x9a, 0x42, 0x1c, 0x0e, 0xf8, 0xd4, 0x1f, 0x60, 0x4c, 0x8c, 0x83, 0x4a, 0xa6, 0x45, 0xa1, 0x51, - 0x0e, 0xdb, 0xcf, 0xab, 0x29, 0x88, 0xd2, 0x0d, 0xd9, 0xa8, 0xb5, 0x94, 0xcf, 0x3f, 0x08, 0xd9, - 0x48, 0xcf, 0x47, 0x9d, 0xa5, 0xa3, 0xd6, 0x72, 0x3e, 0xff, 0x40, 0x80, 0xb8, 0x78, 0xd9, 0x45, - 0xd8, 0xa3, 0xa2, 0x31, 0x64, 0x45, 0xb6, 0x4a, 0x71, 0xc8, 0x41, 0x1c, 0x60, 0x18, 0x79, 0x11, - 0xa6, 0x46, 0x72, 0xba, 0x2a, 0x52, 0x58, 0x0e, 0x54, 0xa6, 0xe1, 0xbe, 0x0a, 0x2b, 0xca, 0x5c, - 0xcc, 0xde, 0xc9, 0x94, 0x66, 0xc3, 0x3e, 0x53, 0xbd, 0x93, 0xe2, 0xcb, 0x7d, 0x0b, 0xbb, 0x22, - 0x3e, 0x89, 0x4f, 0x4f, 0xf3, 0xf4, 0x49, 0x9a, 0xd6, 0x26, 0xcc, 0xf5, 0x11, 0xae, 0xa6, 0x88, - 0x2f, 0x37, 0xc2, 0x7a, 0x4e, 0x61, 0x4a, 0xfe, 0x6a, 0x11, 0x46, 0xbd, 0x58, 0x66, 0x0b, 0xf8, - 0x9b, 0x9f, 0xc5, 0x80, 0x9e, 0x0c, 0x4f, 0x55, 0x0f, 0x14, 0x7e, 0x70, 0xcc, 0x0b, 0x3f, 0x8d, - 0xe4, 0x85, 0x8a, 0xbf, 0x39, 0x26, 0x4d, 0xd3, 0x38, 0x95, 0xb7, 0xa7, 0xf8, 0x70, 0x0f, 0x61, - 0xeb, 0xf8, 0x6a, 0x22, 0x72, 0x42, 0xa2, 0x5a, 0x23, 0x8f, 0x3f, 0x7e, 0xb8, 0x1f, 0x5b, 0x1d, - 0x20, 0xd8, 0x25, 0x30, 0xcd, 0x31, 0x5a, 0x87, 0x6b, 0xe8, 0xcb, 0x15, 0x31, 0xfc, 0xe0, 0x19, - 0x61, 0xab, 0x4c, 0x4d, 0xf7, 0xa0, 0x95, 0x3b, 0x2a, 0x84, 0x27, 0xfc, 0x95, 0x8a, 0x8e, 0x0a, - 0x6b, 0xee, 0x74, 0x2d, 0x15, 0xbf, 0xd4, 0x2e, 0x89, 0xaf, 0x60, 0xcd, 0x14, 0xed, 0x1b, 0xcd, - 0xfa, 0x7f, 0xec, 0x60, 0x85, 0x4c, 0x67, 0x60, 0xc7, 0x2c, 0xa5, 0xfe, 0xe0, 0x1b, 0x7d, 0x10, - 0xff, 0x1e, 0xdc, 0x36, 0xfb, 0xa5, 0xae, 0x2c, 0x89, 0xfb, 0x07, 0xf8, 0x8c, 0x28, 0x1e, 0xf9, - 0xff, 0x1f, 0xe4, 0x7f, 0x0f, 0x6e, 0x18, 0xf2, 0x5f, 0x51, 0x0c, 0xf7, 0xaf, 0x1c, 0xac, 0x22, - 0xee, 0x0f, 0x83, 0x90, 0x59, 0x31, 0x07, 0xf7, 0x4c, 0xcc, 0x4f, 0x59, 0x27, 0xf0, 0x19, 0xd5, - 0x4d, 0x9c, 0x1c, 0xf2, 0xc8, 0x67, 0x58, 0x3c, 0xa1, 0x51, 0x20, 0x06, 0x65, 0x31, 0x80, 0x46, - 0x81, 0x1a, 0x12, 0x99, 0xc3, 0xc9, 0xc8, 0x4a, 0xd4, 0xde, 0xc7, 0x7b, 0x1a, 0x9b, 0x5e, 0xf0, - 0xc4, 0x5f, 0xf3, 0xc4, 0x07, 0x3f, 0xd6, 0x71, 0xaf, 0xc7, 0x8f, 0xdc, 0x35, 0x04, 0xcb, 0x2f, - 0xf7, 0x91, 0x78, 0x94, 0x36, 0x44, 0x93, 0xe7, 0xed, 0x35, 0x98, 0xa3, 0x18, 0x26, 0xcb, 0x53, - 0xa6, 0xeb, 0xfb, 0x3e, 0xc7, 0xed, 0xe0, 0x98, 0x27, 0x51, 0xdc, 0x11, 0x34, 0x0c, 0x30, 0x77, - 0x44, 0xa8, 0x47, 0x59, 0x05, 0xe5, 0xbf, 0xc9, 0x0d, 0x80, 0x30, 0xa0, 0x11, 0x0b, 0x7b, 0x21, - 0x55, 0x1d, 0x08, 0x06, 0x84, 0xdf, 0x4b, 0x03, 0x9a, 0x65, 0xea, 0xf9, 0xae, 0xee, 0xa9, 0x4f, - 0x9e, 0x61, 0xf0, 0xdb, 0x34, 0x63, 0xfe, 0x20, 0x51, 0x97, 0xa4, 0x06, 0x3c, 0xf8, 0xd9, 0xab, - 0xb0, 0x74, 0x18, 0x8b, 0x70, 0xe0, 0x09, 0xbf, 0x05, 0x53, 0xf2, 0x18, 0xe6, 0x65, 0xfb, 0x35, - 0xd9, 0x2c, 0xf5, 0x63, 0xa3, 0xe6, 0xdb, 0x5b, 0x63, 0xfa, 0xb4, 0xdd, 0xb5, 0xaf, 0xff, 0xf5, - 0xdf, 0x7f, 0x52, 0x5b, 0x24, 0x8d, 0xfb, 0xe7, 0x6f, 0xdd, 0x3f, 0xa5, 0x0c, 0xdd, 0xed, 0x29, - 0x2c, 0x5a, 0x1d, 0xb3, 0x64, 0xc7, 0xea, 0x7a, 0x2d, 0x34, 0xd2, 0xb6, 0x77, 0x27, 0xf6, 0xc4, - 0xba, 0xd7, 0x91, 0xc5, 0x1a, 0x59, 0x95, 0x2c, 0xf2, 0x66, 0x58, 0xf2, 0x25, 0x2c, 0x7f, 0x80, - 0x65, 0x78, 0x4d, 0x94, 0xdc, 0xcc, 0x89, 0x55, 0x36, 0x02, 0xb7, 0x6f, 0x8d, 0x47, 0x90, 0x0c, - 0xb7, 0x91, 0xe1, 0x06, 0x59, 0xe3, 0x0c, 0x45, 0x99, 0x5f, 0xf3, 0x24, 0x19, 0xac, 0xc8, 0xd6, - 0xc2, 0x17, 0xca, 0x73, 0x07, 0x79, 0x6e, 0x92, 0x75, 0xce, 0x33, 0x10, 0x0c, 0x72, 0xa6, 0x31, - 0x56, 0x11, 0xcd, 0x56, 0x58, 0x72, 0x63, 0x6c, 0x8f, 0xac, 0x60, 0x79, 0xf3, 0x92, 0x1e, 0x5a, - 0x7b, 0x95, 0xa7, 0x94, 0xe3, 0xea, 0x36, 0x5a, 0xf2, 0x13, 0x71, 0xb5, 0x54, 0x36, 0x6d, 0x93, - 0x57, 0x2e, 0xef, 0x14, 0x17, 0x32, 0xdc, 0x9d, 0xb6, 0xa5, 0xdc, 0xfd, 0x16, 0x0a, 0x73, 0x83, - 0xec, 0x48, 0x61, 0xac, 0x36, 0x72, 0xd5, 0xa8, 0x4e, 0xba, 0xd0, 0x34, 0xfb, 0x5f, 0xc9, 0x76, - 0xc5, 0x4d, 0xa6, 0x99, 0xef, 0x54, 0x0f, 0x4a, 0x86, 0x2d, 0x64, 0x48, 0xc8, 0x8a, 0x64, 0xa8, - 0xdb, 0x65, 0xc9, 0x57, 0xb0, 0x5c, 0xe8, 0x1d, 0x25, 0x6e, 0x61, 0xfb, 0x2a, 0xfa, 0x80, 0xdb, - 0x2f, 0x4d, 0xc4, 0x91, 0x5c, 0x6f, 0x20, 0xd7, 0x96, 0xbb, 0x66, 0xec, 0xb2, 0xe2, 0xfc, 0x1d, - 0xe7, 0x55, 0x92, 0xe1, 0x3e, 0x9b, 0x6d, 0x8e, 0x53, 0xf1, 0xbe, 0x79, 0x49, 0x8f, 0x64, 0x69, - 0xaf, 0x15, 0x4f, 0x3c, 0xad, 0x19, 0xb6, 0x8e, 0x19, 0xcd, 0xb9, 0x18, 0xe6, 0x4d, 0xc3, 0x77, - 0xb7, 0xba, 0xb9, 0x57, 0xf6, 0x17, 0xbb, 0x6d, 0xe4, 0xba, 0x4e, 0x48, 0x81, 0x6b, 0xcc, 0x12, - 0x92, 0x59, 0xbd, 0xcf, 0x92, 0xa9, 0x6d, 0xd5, 0x15, 0xdd, 0xc7, 0x95, 0x2b, 0x35, 0xdb, 0x89, - 0xc7, 0xae, 0x34, 0x66, 0x49, 0x46, 0x9e, 0xc3, 0x92, 0x70, 0x17, 0x2f, 0x7e, 0x67, 0x77, 0x91, - 0xef, 0x96, 0x4b, 0x72, 0x9f, 0x61, 0x6e, 0xec, 0x67, 0x50, 0xd7, 0xf7, 0x31, 0x69, 0x19, 0x8b, - 0xb0, 0x1a, 0x41, 0xdb, 0x63, 0xda, 0xfc, 0x94, 0xb5, 0xba, 0x8b, 0x72, 0x55, 0xa2, 0x69, 0x8f, - 0x13, 0xfe, 0x11, 0x40, 0xde, 0xf7, 0x47, 0xae, 0x97, 0x28, 0x6b, 0xcd, 0xb5, 0xab, 0x86, 0xd4, - 0x5f, 0x38, 0x20, 0xf9, 0x15, 0xb2, 0x64, 0x91, 0x57, 0xe7, 0x4d, 0x87, 0x1f, 0xd6, 0x79, 0x2b, - 0x76, 0x0a, 0xb6, 0xc7, 0xb7, 0x88, 0xa9, 0x4d, 0x71, 0xd5, 0x61, 0xd3, 0x65, 0x26, 0xbe, 0x02, - 0x71, 0x59, 0x18, 0xbd, 0x69, 0x3b, 0x55, 0x5c, 0x2a, 0x2f, 0x8b, 0x72, 0xa3, 0x59, 0xe9, 0xb2, - 0xc8, 0xfb, 0xc9, 0xc8, 0x33, 0xfc, 0x0b, 0x2f, 0xa3, 0xb5, 0x8a, 0x98, 0xb4, 0xca, 0x7d, 0x66, - 0xed, 0x1b, 0xe3, 0x86, 0xb3, 0x6a, 0xfb, 0x96, 0x99, 0x28, 0x1e, 0x2a, 0xb1, 0xe1, 0xa2, 0xa1, - 0xca, 0xda, 0x70, 0xab, 0xef, 0xaa, 0x7d, 0xbd, 0x62, 0x44, 0x52, 0xdf, 0x40, 0xea, 0xcb, 0x64, - 0x51, 0xbb, 0x44, 0xa4, 0x25, 0xf6, 0x44, 0xbf, 0x74, 0x5b, 0x7b, 0x52, 0x6c, 0x87, 0xb2, 0x7c, - 0x60, 0xa9, 0x29, 0xaa, 0xe4, 0x03, 0x75, 0xdb, 0x13, 0xf9, 0x43, 0xbb, 0xbb, 0x4a, 0x75, 0x7b, - 0xb8, 0x13, 0xdb, 0x33, 0x4a, 0xa7, 0x65, 0x6c, 0x0b, 0x87, 0x7b, 0x13, 0x39, 0x5f, 0x27, 0x5b, - 0x45, 0xce, 0xb2, 0x1d, 0x84, 0x7c, 0xed, 0xc0, 0x5a, 0x45, 0xb3, 0x41, 0x2e, 0xc1, 0xf8, 0xd6, - 0x88, 0x5c, 0x82, 0x49, 0xdd, 0x0a, 0x2e, 0x4a, 0xb0, 0xe3, 0xa2, 0x04, 0x7e, 0x10, 0x68, 0x09, - 0x64, 0x62, 0xcd, 0x2d, 0xf3, 0xcf, 0x1c, 0xd8, 0xac, 0x6e, 0x2c, 0x20, 0x2f, 0xeb, 0xbf, 0x19, - 0x99, 0xd4, 0xf2, 0xd0, 0xbe, 0x73, 0x19, 0x9a, 0x94, 0xe6, 0x65, 0x94, 0xe6, 0xa6, 0xdb, 0xe6, - 0xd2, 0xa4, 0x88, 0x5b, 0x25, 0xd0, 0x05, 0x56, 0x63, 0xed, 0xa7, 0x7b, 0x62, 0xc4, 0x16, 0xd5, - 0x1d, 0x0e, 0xed, 0xdb, 0x13, 0x30, 0x6c, 0xf7, 0x45, 0x36, 0xe4, 0x86, 0xe0, 0x7b, 0xb7, 0xee, - 0x01, 0x90, 0x67, 0x34, 0x7f, 0x1a, 0xb7, 0xce, 0x68, 0xe9, 0xb5, 0xdf, 0x3a, 0xa3, 0xe5, 0x07, - 0xf8, 0xd2, 0x19, 0x45, 0x66, 0xf8, 0x18, 0x4f, 0x3e, 0xc7, 0x63, 0x23, 0x9f, 0x02, 0x5a, 0xc5, - 0xa3, 0x9e, 0x55, 0x1d, 0x1b, 0xbb, 0xd8, 0x5f, 0x72, 0x95, 0xe2, 0x85, 0x81, 0x6b, 0xcf, 0x83, - 0x05, 0x85, 0x4e, 0xb6, 0x8a, 0x04, 0x14, 0xe5, 0xca, 0xd7, 0x5c, 0x77, 0x0b, 0x89, 0xae, 0xba, - 0x4d, 0x93, 0x28, 0xa7, 0x79, 0x02, 0x0d, 0xe3, 0xe5, 0x92, 0x68, 0x27, 0x5b, 0x7e, 0xa8, 0x6d, - 0x6f, 0x57, 0x8e, 0xd9, 0xae, 0xc4, 0x5d, 0xe6, 0x0c, 0x32, 0x44, 0xd0, 0x3c, 0x7e, 0x17, 0x16, - 0xad, 0xc7, 0xc3, 0x5c, 0xf9, 0x55, 0xcf, 0x9b, 0xb9, 0xf2, 0x2b, 0x5f, 0x1c, 0x55, 0xa0, 0xe9, - 0xa2, 0xf2, 0x33, 0x89, 0xa2, 0x79, 0x7d, 0x01, 0x75, 0xfd, 0x66, 0x97, 0xeb, 0xbf, 0xf8, 0x8c, - 0x77, 0x19, 0x0f, 0x6b, 0x0f, 0x2e, 0xf8, 0xe4, 0x93, 0x78, 0x70, 0x22, 0xf5, 0x65, 0xbc, 0x48, - 0xe5, 0xfa, 0x2a, 0x3f, 0xcb, 0xe5, 0xfa, 0xaa, 0x7a, 0xc2, 0xb2, 0xf4, 0xd5, 0x45, 0x04, 0xbd, - 0x86, 0x14, 0x96, 0x0b, 0x2f, 0x41, 0x79, 0x58, 0x51, 0xfd, 0xee, 0x95, 0x87, 0x15, 0x63, 0x9e, - 0x90, 0xec, 0xc0, 0x4d, 0xf0, 0xf3, 0xfb, 0xfd, 0xdc, 0xb6, 0x84, 0xbb, 0x17, 0xef, 0x24, 0x96, - 0xdd, 0x5a, 0x0f, 0x42, 0x96, 0xdd, 0xda, 0x8f, 0x2a, 0x25, 0x77, 0x2f, 0x32, 0x45, 0xf2, 0x14, - 0x16, 0x54, 0x81, 0x3e, 0x37, 0xda, 0xc2, 0xd3, 0x44, 0xbb, 0x55, 0x1e, 0x90, 0x54, 0x2d, 0xc3, - 0xf5, 0x83, 0x00, 0xa9, 0xca, 0x8d, 0x30, 0xca, 0xf5, 0xf9, 0x46, 0x94, 0x2b, 0xfd, 0xf9, 0x46, - 0x54, 0xd5, 0xf7, 0xad, 0x8d, 0x10, 0x9e, 0x4b, 0xf3, 0xf8, 0x7b, 0x07, 0xcb, 0x18, 0x93, 0xab, - 0xed, 0xe4, 0xcd, 0x2b, 0x14, 0xe6, 0x85, 0x40, 0x6f, 0x5d, 0xb9, 0x94, 0xef, 0xde, 0x45, 0x31, - 0x5d, 0x77, 0x57, 0x5d, 0xa6, 0x38, 0x2d, 0x10, 0xe8, 0xba, 0xae, 0xcf, 0x85, 0xfe, 0x5b, 0x47, - 0xfc, 0xfd, 0xee, 0x04, 0xba, 0x64, 0x6f, 0x4a, 0x01, 0x94, 0xc0, 0xf7, 0xa7, 0xc6, 0x97, 0xe2, - 0xde, 0x41, 0x71, 0x6f, 0xb9, 0xdb, 0x13, 0xc4, 0xe5, 0xc2, 0xfe, 0x3e, 0x6c, 0xeb, 0xaa, 0xbc, - 0x45, 0xf7, 0xc3, 0x61, 0x14, 0x64, 0x79, 0x5e, 0x3a, 0xa6, 0x74, 0x9f, 0x1b, 0x4e, 0xb1, 0x58, - 0x6b, 0xdf, 0x8f, 0x17, 0x72, 0x54, 0x88, 0xd1, 0xe3, 0xb4, 0x39, 0xf7, 0x04, 0x56, 0xd5, 0xbc, - 0x0f, 0x43, 0x9f, 0xfd, 0xc2, 0x3c, 0x6f, 0x21, 0xcf, 0xb6, 0xbb, 0x61, 0xf2, 0xec, 0x85, 0x3e, - 0xd3, 0x1c, 0x33, 0x7c, 0x64, 0xb5, 0xea, 0xb0, 0x66, 0xf2, 0x5d, 0x59, 0xa1, 0x35, 0x93, 0xef, - 0xea, 0x92, 0xb1, 0x9d, 0x7c, 0x9f, 0x52, 0x26, 0x4a, 0xb8, 0x81, 0x64, 0x70, 0x0e, 0x2b, 0xc7, - 0x63, 0x99, 0x1e, 0xff, 0xdc, 0x4c, 0x65, 0x0c, 0xe4, 0x22, 0xd3, 0xac, 0xc0, 0x94, 0x2f, 0xf6, - 0x5c, 0xbc, 0x28, 0x9b, 0x15, 0x5a, 0x72, 0x73, 0x7c, 0xed, 0xb6, 0xcc, 0xb7, 0xb2, 0xb8, 0x6b, - 0xf3, 0x35, 0x32, 0x24, 0xfc, 0xbb, 0x45, 0xce, 0x77, 0x04, 0xc4, 0xce, 0x92, 0xf0, 0xef, 0x5d, - 0xb4, 0x17, 0xa8, 0xa8, 0xcb, 0x4e, 0x97, 0x22, 0xdd, 0x46, 0xc6, 0xdb, 0xee, 0x66, 0x39, 0x45, - 0xe2, 0xbc, 0x39, 0xeb, 0xdf, 0x83, 0xb5, 0x42, 0xee, 0xfd, 0x82, 0x78, 0x5b, 0xe6, 0x5c, 0x48, - 0xbc, 0x15, 0x73, 0x86, 0x79, 0x70, 0xa1, 0xd8, 0x4a, 0x6e, 0x57, 0xe5, 0x1b, 0x56, 0x2d, 0x73, - 0x52, 0xe6, 0x23, 0xef, 0x0d, 0xb2, 0x59, 0x4a, 0x47, 0x90, 0xc2, 0x9b, 0x0e, 0xf9, 0x53, 0x07, - 0xff, 0xc4, 0x60, 0x4c, 0xad, 0x97, 0xdc, 0xab, 0x4a, 0x78, 0xaf, 0x2c, 0x86, 0xf4, 0x27, 0xe4, - 0x46, 0x31, 0x2b, 0x2e, 0x89, 0x73, 0x86, 0x15, 0x08, 0xb3, 0x62, 0x6b, 0xe5, 0xe4, 0x15, 0xa5, - 0xdc, 0xb1, 0x49, 0x6b, 0x31, 0x15, 0x97, 0x59, 0xa5, 0xe2, 0xf4, 0x63, 0xfb, 0x0f, 0x89, 0x2d, - 0x96, 0x77, 0x2a, 0x56, 0x7d, 0x15, 0xd6, 0x2f, 0x21, 0xeb, 0x5d, 0xb2, 0x5d, 0x58, 0x6f, 0x41, - 0x04, 0x11, 0xd6, 0xe6, 0xc5, 0x5c, 0x2b, 0xac, 0x2d, 0x95, 0x9f, 0xad, 0xb0, 0xb6, 0x5c, 0x01, - 0x2e, 0x85, 0xb5, 0x58, 0xe1, 0xc5, 0xcb, 0xf0, 0x64, 0x0e, 0xff, 0x8d, 0x91, 0xb7, 0xff, 0x2f, - 0x00, 0x00, 0xff, 0xff, 0xb9, 0x45, 0x93, 0xa0, 0x96, 0x44, 0x00, 0x00, + 0x17, 0x95, 0x8b, 0xbf, 0x0e, 0x24, 0xa5, 0x19, 0x6b, 0x27, 0x71, 0xaf, 0xc7, 0x53, 0xf2, 0x80, + 0xf6, 0xfc, 0xa1, 0x2c, 0xd9, 0xaf, 0xf0, 0x91, 0x63, 0x31, 0xf0, 0x3e, 0x87, 0x93, 0x2d, 0x98, + 0xf3, 0x93, 0xb0, 0xcd, 0xad, 0x46, 0xe4, 0xe3, 0xb3, 0x7e, 0x12, 0x7e, 0x4c, 0x87, 0xc4, 0x85, + 0x45, 0x39, 0xd0, 0xee, 0xd1, 0x0b, 0xda, 0xc3, 0x98, 0x6f, 0xca, 0x5b, 0x10, 0xc3, 0x9f, 0x70, + 0x10, 0xb9, 0x07, 0x2b, 0x49, 0x1a, 0x72, 0xf3, 0xcb, 0xdf, 0x06, 0xe6, 0x50, 0x9a, 0x65, 0x09, + 0x57, 0xab, 0x73, 0x7f, 0x04, 0x37, 0x2a, 0x74, 0x21, 0x7d, 0xd4, 0x77, 0x61, 0xd9, 0x7e, 0x61, + 0x50, 0x7e, 0x4a, 0x47, 0xad, 0xd6, 0x44, 0x6f, 0xa9, 0x6b, 0xd1, 0x91, 0xd1, 0x27, 0xe2, 0x78, + 0x3e, 0xd3, 0x35, 0x2d, 0xf7, 0x4b, 0x58, 0xcf, 0x81, 0x87, 0x71, 0x74, 0x41, 0xd3, 0x8c, 0x5b, + 0x1b, 0x81, 0xe9, 0x6e, 0x1a, 0xab, 0x82, 0x2c, 0xfe, 0xe6, 0x71, 0x1b, 0x8b, 0xa5, 0x19, 0xd4, + 0x58, 0xcc, 0x71, 0x52, 0x9f, 0xa9, 0x5b, 0x0a, 0x7f, 0xf3, 0x38, 0x39, 0x44, 0x22, 0xb4, 0x8d, + 0x63, 0xc2, 0x54, 0x17, 0x24, 0x8c, 0x73, 0x71, 0x9f, 0x62, 0xf8, 0x68, 0x8a, 0x22, 0xd7, 0xf8, + 0xeb, 0xb0, 0x20, 0xd6, 0xc8, 0x67, 0xaa, 0xf5, 0xed, 0x58, 0xeb, 0x2b, 0x88, 0xe9, 0x41, 0x57, + 0x43, 0xdd, 0xff, 0xae, 0x41, 0x03, 0x23, 0xd6, 0xf7, 0x29, 0xf3, 0xc3, 0xde, 0xf8, 0x58, 0x5a, + 0xc4, 0xa0, 0x35, 0x1d, 0x83, 0xbe, 0x02, 0x8b, 0x66, 0x41, 0x64, 0xa8, 0x92, 0x59, 0xa3, 0x1c, + 0x32, 0x24, 0xaf, 0xc2, 0x12, 0xa6, 0xd6, 0x39, 0x96, 0xb0, 0x99, 0x45, 0x84, 0x6a, 0x34, 0x3b, + 0x11, 0x98, 0x29, 0x24, 0x02, 0x7c, 0x18, 0x83, 0xe9, 0x76, 0x16, 0x06, 0x3a, 0x4f, 0x40, 0xc8, + 0x49, 0x18, 0x18, 0xc3, 0x38, 0x7b, 0xce, 0x18, 0xc6, 0xd9, 0x3c, 0x07, 0x4a, 0xa9, 0x78, 0x28, + 0xc0, 0xf7, 0xae, 0x79, 0x34, 0xba, 0x86, 0x02, 0x3e, 0x09, 0xfb, 0xf8, 0x1a, 0x26, 0x8b, 0xdb, + 0x75, 0x61, 0xb1, 0xe2, 0x2b, 0x4f, 0xd3, 0xc0, 0x4c, 0xd3, 0xf2, 0xa4, 0x6e, 0xc1, 0x4a, 0xea, + 0xf6, 0x60, 0x21, 0x4e, 0x68, 0xd4, 0x96, 0x29, 0x76, 0x43, 0x44, 0x0f, 0x1c, 0xf4, 0x14, 0x21, + 0xb2, 0x64, 0x82, 0x3a, 0xcf, 0x26, 0xc9, 0x4b, 0x6d, 0xc5, 0xd4, 0x8a, 0x8a, 0x51, 0x89, 0xe0, + 0xd4, 0x55, 0x89, 0xa0, 0x7b, 0x80, 0x51, 0xb1, 0x62, 0x2c, 0xcd, 0xe7, 0x75, 0x98, 0x45, 0x35, + 0x29, 0xcb, 0x59, 0xb7, 0xd2, 0x18, 0x69, 0x14, 0x9e, 0xc4, 0x71, 0xbf, 0x8f, 0x6f, 0x88, 0x38, + 0x34, 0x89, 0xe8, 0x37, 0x60, 0x5e, 0xec, 0x8a, 0xb6, 0x9a, 0x39, 0xfc, 0xfe, 0x28, 0x70, 0xff, + 0xcd, 0x01, 0x72, 0x32, 0x38, 0xed, 0x87, 0x93, 0x53, 0x9b, 0x3c, 0x41, 0x27, 0x30, 0x8d, 0x66, + 0x22, 0xcc, 0x11, 0x7f, 0x17, 0x2c, 0x64, 0xba, 0x68, 0x21, 0xf9, 0x76, 0xce, 0x54, 0xe7, 0xe8, + 0xb3, 0xe6, 0xe6, 0x73, 0x17, 0xdf, 0x0b, 0x69, 0xc4, 0xda, 0xb2, 0xd8, 0xc2, 0x5d, 0x3c, 0x02, + 0x3e, 0x0a, 0xdc, 0x13, 0x58, 0xb3, 0x56, 0x26, 0x35, 0x7d, 0x1b, 0x1a, 0x42, 0x80, 0xa4, 0xe7, + 0x77, 0x74, 0x35, 0x7c, 0x01, 0x61, 0xc7, 0x08, 0x1a, 0xa7, 0xaf, 0x3f, 0x71, 0x60, 0xfd, 0x24, + 0xec, 0x0f, 0x7a, 0x3e, 0xa3, 0xbf, 0x04, 0x8d, 0xe5, 0xcb, 0x9f, 0xb2, 0x96, 0xaf, 0x34, 0x39, + 0x9d, 0x6b, 0xd2, 0xfd, 0x99, 0x03, 0x1b, 0x05, 0x51, 0x74, 0x4c, 0x68, 0x1b, 0xd3, 0x88, 0xe2, + 0x80, 0x44, 0x32, 0x98, 0xd6, 0x2c, 0xa6, 0xaf, 0xc0, 0x62, 0x3f, 0x8c, 0xc2, 0xfe, 0xa0, 0xdf, + 0x16, 0xba, 0x17, 0x32, 0x35, 0x24, 0xf0, 0x18, 0xb7, 0x80, 0x23, 0xf9, 0xcf, 0x0d, 0xa4, 0x69, + 0x89, 0x24, 0x80, 0x02, 0xe9, 0x0d, 0x58, 0xcf, 0xe3, 0xf6, 0xf6, 0x99, 0x1f, 0x46, 0xed, 0x5e, + 0x9c, 0x65, 0x72, 0x8f, 0x49, 0x3e, 0x76, 0xe4, 0x87, 0xd1, 0x27, 0x71, 0x96, 0x19, 0x4e, 0x60, + 0xd6, 0x74, 0x02, 0x3c, 0x80, 0x59, 0xf9, 0xec, 0xdc, 0xef, 0xd1, 0xf7, 0xe2, 0xfe, 0xe9, 0x8b, + 0xd5, 0xfd, 0x6d, 0x68, 0x88, 0xba, 0x1b, 0xf3, 0xd3, 0x33, 0xaa, 0x76, 0x60, 0x01, 0x61, 0x4f, + 0x10, 0x54, 0xb9, 0x0d, 0xff, 0xe5, 0x00, 0x39, 0xe4, 0xa1, 0x4c, 0x6f, 0x62, 0x7b, 0xe0, 0xae, + 0x44, 0xe4, 0xcd, 0xb9, 0x85, 0xd5, 0x25, 0xe4, 0x23, 0xdb, 0xfc, 0xa6, 0x2c, 0xf3, 0xd3, 0xab, + 0x99, 0xbe, 0x66, 0x71, 0xac, 0xe4, 0xc7, 0x5f, 0x85, 0xa5, 0x4b, 0xbf, 0xd7, 0xa3, 0x4c, 0x3f, + 0xb1, 0xc9, 0x4a, 0xbc, 0x80, 0xaa, 0x1c, 0x5c, 0x2d, 0x78, 0xce, 0x58, 0xf0, 0x06, 0xac, 0x59, + 0xeb, 0x95, 0xd1, 0xd0, 0x23, 0xd8, 0x14, 0xe0, 0x83, 0x5e, 0x6f, 0x62, 0xaf, 0xea, 0xfe, 0x75, + 0x0d, 0xb6, 0x4a, 0xd3, 0x74, 0xd8, 0x60, 0x9b, 0xf1, 0x1d, 0xbd, 0xdc, 0xea, 0x09, 0xfb, 0xf2, + 0x53, 0xce, 0x6a, 0xfd, 0x93, 0x03, 0xb3, 0x02, 0x34, 0x76, 0x37, 0x3e, 0x57, 0x0e, 0x41, 0x1a, + 0x9c, 0xc8, 0x88, 0xbe, 0x3d, 0x19, 0x33, 0xf1, 0x3f, 0xf3, 0x59, 0x55, 0x78, 0x12, 0xf9, 0xa2, + 0xfa, 0x5d, 0x58, 0x29, 0x22, 0x5c, 0xeb, 0xc9, 0x49, 0x54, 0x55, 0x3e, 0xb8, 0xa0, 0xc6, 0x33, + 0xea, 0x4f, 0x1d, 0x58, 0x3e, 0x8c, 0xa3, 0x20, 0xe4, 0x37, 0xe6, 0xb1, 0x9f, 0xfa, 0xfd, 0x4c, + 0xbe, 0xe4, 0x0b, 0x90, 0x2a, 0xbb, 0x6b, 0xc0, 0x88, 0x02, 0xe7, 0x2e, 0x40, 0xe7, 0x9c, 0x76, + 0x9e, 0xb5, 0x65, 0xc5, 0x51, 0x3c, 0xff, 0x73, 0xc8, 0x7b, 0x61, 0x90, 0x91, 0x6f, 0xc1, 0x5a, + 0x3e, 0xdc, 0xf6, 0xa3, 0xa0, 0x2d, 0xcb, 0x8d, 0xf8, 0xba, 0xa1, 0xf1, 0x0e, 0xa2, 0xe0, 0x20, + 0x7b, 0x96, 0xf1, 0x58, 0x51, 0x57, 0xd9, 0xda, 0x96, 0x0b, 0x5f, 0xd6, 0xf0, 0x03, 0x04, 0xbb, + 0xff, 0xe3, 0xe0, 0x0d, 0xa8, 0x56, 0x25, 0x77, 0x3b, 0x2f, 0xac, 0x61, 0xbd, 0xd5, 0xda, 0xb2, + 0x5a, 0x61, 0xcb, 0x08, 0x4c, 0x87, 0x8c, 0xf6, 0xd5, 0xc5, 0xc2, 0x7f, 0x93, 0xf7, 0x60, 0x45, + 0xaf, 0xb8, 0x9d, 0xa0, 0x5a, 0xe4, 0x31, 0xd9, 0xca, 0x13, 0x47, 0x4b, 0x6b, 0xde, 0x72, 0xa7, + 0xa0, 0x46, 0x75, 0xbc, 0x66, 0x26, 0x72, 0xd4, 0x1d, 0xd4, 0xb6, 0xf4, 0x4f, 0xe2, 0x4b, 0x48, + 0x4d, 0x3b, 0x03, 0x46, 0x03, 0x19, 0x2a, 0xeb, 0x6f, 0xf7, 0x3f, 0x1c, 0x58, 0x3e, 0x08, 0x02, + 0x5c, 0xf7, 0x24, 0x6e, 0x42, 0xad, 0xb2, 0x76, 0xc5, 0x2a, 0xa7, 0x7e, 0xce, 0x55, 0xfe, 0xc2, + 0x4e, 0x64, 0x84, 0x12, 0x5c, 0x17, 0x56, 0xf2, 0x75, 0x56, 0x6f, 0xaf, 0xfb, 0x0d, 0x20, 0x22, + 0xbd, 0xb2, 0xd4, 0x51, 0xc4, 0xda, 0x80, 0x35, 0x0b, 0x4b, 0xfa, 0x9a, 0x0f, 0xe1, 0xee, 0x11, + 0x65, 0x87, 0xe9, 0x30, 0x61, 0xb1, 0x0a, 0x67, 0xdf, 0xa7, 0x49, 0x9c, 0x85, 0xca, 0x73, 0xd1, + 0x89, 0xbc, 0xcf, 0x3f, 0x3b, 0x70, 0x6f, 0x02, 0x42, 0x72, 0x09, 0x5f, 0x94, 0xeb, 0x4b, 0xbf, + 0x61, 0xb6, 0xb7, 0x4c, 0x44, 0x65, 0x5f, 0x43, 0x64, 0x97, 0x81, 0x26, 0xd9, 0x7a, 0x17, 0x96, + 0xec, 0xc1, 0x6b, 0xb9, 0x8a, 0x1e, 0xdc, 0xb9, 0x42, 0x88, 0x49, 0x6c, 0xee, 0x0e, 0x2c, 0x75, + 0x2c, 0x12, 0x92, 0x51, 0x01, 0xea, 0x1e, 0xc2, 0x6b, 0x57, 0x72, 0x93, 0x6a, 0x1b, 0x99, 0xa1, + 0xbb, 0x7f, 0x37, 0x0d, 0x5b, 0x9f, 0x85, 0xec, 0x3c, 0x48, 0xfd, 0x4b, 0x65, 0x7d, 0x93, 0x08, + 0x59, 0x48, 0xde, 0x6b, 0xe5, 0x7a, 0xc3, 0x7d, 0x58, 0x8d, 0x23, 0x8a, 0x39, 0x46, 0x3b, 0xf1, + 0xb3, 0xec, 0x32, 0x4e, 0xd5, 0x5d, 0xba, 0x1c, 0x47, 0x94, 0xe7, 0x19, 0xc7, 0x12, 0x5c, 0xb8, + 0x8d, 0xa7, 0x8b, 0xb7, 0xf1, 0x0a, 0x4c, 0x25, 0x61, 0x24, 0xdf, 0x4c, 0xf8, 0x4f, 0x7e, 0x77, + 0xb2, 0xd4, 0x0f, 0x0c, 0xca, 0xf2, 0xee, 0x44, 0xa8, 0xa6, 0x6b, 0x56, 0xf1, 0xe7, 0x0a, 0x55, + 0x7c, 0x43, 0x27, 0xf3, 0x76, 0xd5, 0x62, 0x0f, 0x16, 0xe4, 0xcf, 0x36, 0xf3, 0xcf, 0x64, 0x0a, + 0x04, 0x12, 0xf4, 0xc4, 0x3f, 0x33, 0xa2, 0x35, 0xb0, 0xa2, 0xb5, 0x5d, 0x80, 0x2e, 0xa5, 0x6d, + 0x2b, 0x19, 0xaa, 0x77, 0x29, 0x15, 0x4e, 0x97, 0x87, 0xca, 0xa7, 0x7e, 0xf4, 0xac, 0x8d, 0x35, + 0x88, 0x86, 0x10, 0x87, 0x03, 0x3e, 0xf5, 0xfb, 0x18, 0x13, 0xe3, 0xa0, 0x92, 0x69, 0x51, 0x68, + 0x94, 0xc3, 0x0e, 0xf2, 0x6a, 0x0a, 0xa2, 0x74, 0x42, 0x36, 0x6c, 0x2e, 0xe5, 0xf3, 0x0f, 0x43, + 0x36, 0xd4, 0xf3, 0x51, 0x67, 0xe9, 0xb0, 0xb9, 0x9c, 0xcf, 0x3f, 0x14, 0x20, 0x2e, 0x5e, 0x76, + 0x19, 0x76, 0xa9, 0x68, 0x0c, 0x59, 0x91, 0xad, 0x52, 0x1c, 0x72, 0x18, 0x07, 0x18, 0x46, 0x5e, + 0x86, 0xa9, 0x91, 0x9c, 0xae, 0x8a, 0x14, 0x96, 0x03, 0x95, 0x69, 0xb8, 0xf7, 0x61, 0x45, 0x99, + 0x8b, 0xd9, 0x3b, 0x99, 0xd2, 0x6c, 0xd0, 0x63, 0xaa, 0x77, 0x52, 0x7c, 0xb9, 0x6f, 0x62, 0x57, + 0xc4, 0x27, 0xf1, 0xd9, 0x59, 0x9e, 0x3e, 0x49, 0xd3, 0xda, 0x84, 0xd9, 0x1e, 0xc2, 0xd5, 0x14, + 0xf1, 0xe5, 0x46, 0x58, 0xcf, 0x29, 0x4c, 0xc9, 0x5f, 0x2d, 0xc2, 0xa8, 0x1b, 0xcb, 0x6c, 0x01, + 0x7f, 0xf3, 0xb3, 0x18, 0xd0, 0xd3, 0xc1, 0x99, 0xea, 0x81, 0xc2, 0x0f, 0x8e, 0x79, 0xe9, 0xa7, + 0x91, 0xbc, 0x50, 0xf1, 0x37, 0xc7, 0xa4, 0x69, 0x1a, 0xa7, 0xf2, 0xf6, 0x14, 0x1f, 0xee, 0x11, + 0x6c, 0x9d, 0x5c, 0x4f, 0x44, 0x4e, 0x48, 0x54, 0x6b, 0xe4, 0xf1, 0xc7, 0x0f, 0xf7, 0x63, 0xab, + 0x03, 0x04, 0xbb, 0x04, 0x26, 0x39, 0x46, 0xeb, 0x30, 0x83, 0xbe, 0x5c, 0x11, 0xc3, 0x0f, 0x9e, + 0x11, 0x36, 0xcb, 0xd4, 0x74, 0x0f, 0x5a, 0xb9, 0xa3, 0x42, 0x78, 0xc2, 0x5f, 0xa9, 0xe8, 0xa8, + 0xb0, 0xe6, 0x4e, 0xd6, 0x52, 0xf1, 0x4b, 0xed, 0x92, 0xf8, 0x0a, 0xd6, 0x4c, 0xd1, 0x5e, 0x6a, + 0xd6, 0xff, 0x63, 0x07, 0x2b, 0x64, 0x3a, 0x03, 0x3b, 0x61, 0x29, 0xf5, 0xfb, 0x2f, 0xf5, 0x41, + 0xfc, 0x7b, 0x70, 0xdb, 0xec, 0x97, 0xba, 0xb6, 0x24, 0xee, 0x1f, 0xe0, 0x33, 0xa2, 0x78, 0xe4, + 0xff, 0x7f, 0x90, 0xff, 0x5d, 0xb8, 0x69, 0xc8, 0x7f, 0x4d, 0x31, 0xdc, 0xbf, 0x72, 0xb0, 0x8a, + 0x78, 0x30, 0x08, 0x42, 0x66, 0xc5, 0x1c, 0xdc, 0x33, 0x31, 0x3f, 0x65, 0xed, 0xc0, 0x67, 0x54, + 0x37, 0x71, 0x72, 0xc8, 0xfb, 0x3e, 0xc3, 0xe2, 0x09, 0x8d, 0x02, 0x31, 0x28, 0x8b, 0x01, 0x34, + 0x0a, 0xd4, 0x90, 0xc8, 0x1c, 0x4e, 0x87, 0x56, 0xa2, 0xf6, 0x1e, 0xde, 0xd3, 0xd8, 0xf4, 0x82, + 0x27, 0x7e, 0xc6, 0x13, 0x1f, 0xfc, 0x58, 0xc7, 0xdd, 0x2e, 0x3f, 0x72, 0x33, 0x08, 0x96, 0x5f, + 0xee, 0xa1, 0x78, 0x94, 0x36, 0x44, 0x93, 0xe7, 0xed, 0x3e, 0xcc, 0x52, 0x0c, 0x93, 0x8b, 0xaf, + 0xdb, 0x06, 0xae, 0xc4, 0x70, 0x9f, 0x03, 0xe4, 0x50, 0xee, 0x86, 0x50, 0x8b, 0xb2, 0x06, 0xca, + 0x7f, 0x93, 0x9b, 0x00, 0x61, 0x40, 0x23, 0x16, 0x76, 0x43, 0xaa, 0xfa, 0x0f, 0x0c, 0x08, 0xbf, + 0x95, 0xfa, 0x34, 0xcb, 0xd4, 0xe3, 0x5d, 0xdd, 0x53, 0x9f, 0x3c, 0xbf, 0xe0, 0x77, 0x69, 0xc6, + 0xfc, 0x7e, 0xa2, 0xae, 0x48, 0x0d, 0x78, 0xf8, 0xb3, 0xfb, 0xb0, 0x74, 0x14, 0x8b, 0x60, 0xe0, + 0x09, 0xbf, 0x03, 0x53, 0xf2, 0x18, 0xe6, 0x64, 0xf3, 0x35, 0xd9, 0x2c, 0x75, 0x63, 0xa3, 0xde, + 0x5b, 0x5b, 0x23, 0xba, 0xb4, 0xdd, 0xb5, 0xaf, 0xff, 0xf5, 0xdf, 0x7f, 0x52, 0x5b, 0x24, 0x0b, + 0x0f, 0x2e, 0xde, 0x7c, 0x70, 0x46, 0x19, 0x3a, 0xdb, 0x33, 0x58, 0xb4, 0xfa, 0x65, 0xc9, 0x8e, + 0xd5, 0xf3, 0x5a, 0x68, 0xa3, 0x6d, 0xed, 0x8e, 0xed, 0x88, 0x75, 0x6f, 0x20, 0x8b, 0x35, 0xb2, + 0x2a, 0x59, 0xe4, 0xad, 0xb0, 0xe4, 0x4b, 0x58, 0xfe, 0x00, 0x8b, 0xf0, 0x9a, 0x28, 0xd9, 0xcb, + 0x89, 0x55, 0xb6, 0x01, 0xb7, 0x6e, 0x8d, 0x46, 0x90, 0x0c, 0xb7, 0x91, 0xe1, 0x06, 0x59, 0xe3, + 0x0c, 0x45, 0x91, 0x5f, 0xf3, 0x24, 0x19, 0xac, 0xc8, 0xc6, 0xc2, 0x17, 0xca, 0x73, 0x07, 0x79, + 0x6e, 0x92, 0x75, 0xce, 0x33, 0x10, 0x0c, 0x72, 0xa6, 0x31, 0xd6, 0x10, 0xcd, 0x46, 0x58, 0x72, + 0x73, 0x64, 0x87, 0xac, 0x60, 0xb9, 0x77, 0x45, 0x07, 0xad, 0xbd, 0xca, 0x33, 0xca, 0x71, 0x75, + 0x13, 0x2d, 0xf9, 0x89, 0xb8, 0x58, 0x2a, 0x5b, 0xb6, 0xc9, 0x6b, 0x57, 0xf7, 0x89, 0x0b, 0x19, + 0xee, 0x4e, 0xda, 0x50, 0xee, 0x7e, 0x03, 0x85, 0xb9, 0x49, 0x76, 0xa4, 0x30, 0x56, 0x13, 0xb9, + 0x6a, 0x53, 0x27, 0x1d, 0x68, 0x98, 0xdd, 0xaf, 0x64, 0xbb, 0xe2, 0x1e, 0xd3, 0xcc, 0x77, 0xaa, + 0x07, 0x25, 0xc3, 0x26, 0x32, 0x24, 0x64, 0x45, 0x32, 0xd4, 0xcd, 0xb2, 0xe4, 0x2b, 0x58, 0x2e, + 0x74, 0x8e, 0x12, 0xb7, 0xb0, 0x7d, 0x15, 0x5d, 0xc0, 0xad, 0x57, 0xc6, 0xe2, 0x48, 0xae, 0x37, + 0x91, 0x6b, 0xd3, 0x5d, 0x33, 0x76, 0x59, 0x71, 0xfe, 0x8e, 0x73, 0x9f, 0x64, 0xb8, 0xcf, 0x66, + 0x93, 0xe3, 0x44, 0xbc, 0xf7, 0xae, 0xe8, 0x90, 0x2c, 0xed, 0xb5, 0xe2, 0x89, 0xa7, 0x35, 0xc3, + 0xc6, 0x31, 0xa3, 0x35, 0x17, 0x83, 0xbc, 0x49, 0xf8, 0xee, 0x56, 0xb7, 0xf6, 0xca, 0xee, 0x62, + 0xb7, 0x85, 0x5c, 0xd7, 0x09, 0x29, 0x70, 0x8d, 0x59, 0x42, 0x32, 0xab, 0xf3, 0x59, 0x32, 0xb5, + 0xad, 0xba, 0xa2, 0xf7, 0xb8, 0x72, 0xa5, 0x66, 0x33, 0xf1, 0xc8, 0x95, 0xc6, 0x2c, 0xc9, 0xc8, + 0x73, 0x58, 0x12, 0xee, 0xe2, 0xc5, 0xef, 0xec, 0x2e, 0xf2, 0xdd, 0x72, 0x49, 0xee, 0x33, 0xcc, + 0x8d, 0xfd, 0x0c, 0xea, 0xfa, 0x36, 0x26, 0x4d, 0x63, 0x11, 0x56, 0x1b, 0x68, 0x6b, 0x44, 0x93, + 0x9f, 0xb2, 0x56, 0x77, 0x51, 0xae, 0x4a, 0xb4, 0xec, 0x71, 0xc2, 0x3f, 0x02, 0xc8, 0xbb, 0xfe, + 0xc8, 0x8d, 0x12, 0x65, 0xad, 0xb9, 0x56, 0xd5, 0x90, 0xfa, 0xfb, 0x06, 0x24, 0xbf, 0x42, 0x96, + 0x2c, 0xf2, 0xea, 0xbc, 0xe9, 0xe0, 0xc3, 0x3a, 0x6f, 0xc5, 0x3e, 0xc1, 0xd6, 0xe8, 0x06, 0x31, + 0xb5, 0x29, 0xae, 0x3a, 0x6c, 0xba, 0xc8, 0xc4, 0x57, 0x20, 0x2e, 0x0b, 0xa3, 0x33, 0x6d, 0xa7, + 0x8a, 0x4b, 0xe5, 0x65, 0x51, 0x6e, 0x33, 0x2b, 0x5d, 0x16, 0x79, 0x37, 0x19, 0x79, 0x86, 0x7f, + 0xdf, 0x65, 0x34, 0x56, 0x11, 0x93, 0x56, 0xb9, 0xcb, 0xac, 0x75, 0x73, 0xd4, 0x70, 0x56, 0x6d, + 0xdf, 0x32, 0x0f, 0xc5, 0x43, 0x25, 0x36, 0x5c, 0xb4, 0x53, 0x59, 0x1b, 0x6e, 0x75, 0x5d, 0xb5, + 0x6e, 0x54, 0x8c, 0x48, 0xea, 0x1b, 0x48, 0x7d, 0x99, 0x2c, 0x6a, 0x97, 0x88, 0xb4, 0xc4, 0x9e, + 0xe8, 0x77, 0x6e, 0x6b, 0x4f, 0x8a, 0xcd, 0x50, 0x96, 0x0f, 0x2c, 0xb5, 0x44, 0x95, 0x7c, 0xa0, + 0x6e, 0x7a, 0x22, 0x7f, 0x68, 0xf7, 0x56, 0xa9, 0x5e, 0x0f, 0x77, 0x6c, 0x73, 0x46, 0xe9, 0xb4, + 0x8c, 0x6c, 0xe0, 0x70, 0xf7, 0x90, 0xf3, 0x0d, 0xb2, 0x55, 0xe4, 0x2c, 0x9b, 0x41, 0xc8, 0xd7, + 0x0e, 0xac, 0x55, 0xb4, 0x1a, 0xe4, 0x12, 0x8c, 0x6e, 0x8c, 0xc8, 0x25, 0x18, 0xd7, 0xab, 0xe0, + 0xa2, 0x04, 0x3b, 0x2e, 0x4a, 0xe0, 0x07, 0x81, 0x96, 0x40, 0xa6, 0xd5, 0xdc, 0x32, 0xff, 0xcc, + 0x81, 0xcd, 0xea, 0xb6, 0x02, 0xf2, 0xaa, 0xfe, 0x8b, 0x91, 0x71, 0x0d, 0x0f, 0xad, 0x3b, 0x57, + 0xa1, 0x49, 0x69, 0x5e, 0x45, 0x69, 0xf6, 0xdc, 0x16, 0x97, 0x26, 0x45, 0xdc, 0x2a, 0x81, 0x2e, + 0xb1, 0x16, 0x6b, 0x3f, 0xdc, 0x13, 0x23, 0xb6, 0xa8, 0xee, 0x6f, 0x68, 0xdd, 0x1e, 0x83, 0x61, + 0xbb, 0x2f, 0xb2, 0x21, 0x37, 0x04, 0x5f, 0xbb, 0x75, 0x07, 0x80, 0x3c, 0xa3, 0xf9, 0xc3, 0xb8, + 0x75, 0x46, 0x4b, 0x6f, 0xfd, 0xd6, 0x19, 0x2d, 0x3f, 0xbf, 0x97, 0xce, 0x28, 0x32, 0xc3, 0xa7, + 0x78, 0xf2, 0x39, 0x1e, 0x1b, 0xf9, 0x10, 0xd0, 0x2c, 0x1e, 0xf5, 0xac, 0xea, 0xd8, 0xd8, 0xa5, + 0xfe, 0x92, 0xab, 0x14, 0xef, 0x0b, 0x5c, 0x7b, 0x1e, 0xcc, 0x2b, 0x74, 0xb2, 0x55, 0x24, 0xa0, + 0x28, 0x57, 0xbe, 0xe5, 0xba, 0x5b, 0x48, 0x74, 0xd5, 0x6d, 0x98, 0x44, 0x39, 0xcd, 0x53, 0x58, + 0x30, 0xde, 0x2d, 0x89, 0x76, 0xb2, 0xe5, 0x67, 0xda, 0xd6, 0x76, 0xe5, 0x98, 0xed, 0x4a, 0xdc, + 0x65, 0xce, 0x20, 0x43, 0x04, 0xcd, 0xe3, 0x77, 0x61, 0xd1, 0x7a, 0x3a, 0xcc, 0x95, 0x5f, 0xf5, + 0xb8, 0x99, 0x2b, 0xbf, 0xf2, 0xbd, 0x51, 0x05, 0x9a, 0x2e, 0x2a, 0x3f, 0x93, 0x28, 0x9a, 0xd7, + 0x17, 0x50, 0xd7, 0x2f, 0x76, 0xb9, 0xfe, 0x8b, 0x8f, 0x78, 0x57, 0xf1, 0xb0, 0xf6, 0xe0, 0x92, + 0x4f, 0x3e, 0x8d, 0xfb, 0xa7, 0x52, 0x5f, 0xc6, 0x7b, 0x54, 0xae, 0xaf, 0xf2, 0xa3, 0x5c, 0xae, + 0xaf, 0xaa, 0x07, 0x2c, 0x4b, 0x5f, 0x1d, 0x44, 0xd0, 0x6b, 0x48, 0x61, 0xb9, 0xf0, 0x0e, 0x94, + 0x87, 0x15, 0xd5, 0xaf, 0x5e, 0x79, 0x58, 0x31, 0xe2, 0x01, 0xc9, 0x0e, 0xdc, 0x04, 0x3f, 0xbf, + 0xd7, 0xcb, 0x6d, 0x4b, 0xb8, 0x7b, 0xf1, 0x4a, 0x62, 0xd9, 0xad, 0xf5, 0x1c, 0x64, 0xd9, 0xad, + 0xfd, 0xa4, 0x52, 0x72, 0xf7, 0x22, 0x51, 0x24, 0x4f, 0x61, 0x5e, 0x95, 0xe7, 0x73, 0xa3, 0x2d, + 0x3c, 0x4c, 0xb4, 0x9a, 0xe5, 0x01, 0x49, 0xd5, 0x32, 0x5c, 0x3f, 0x08, 0x90, 0xaa, 0xdc, 0x08, + 0xa3, 0x58, 0x9f, 0x6f, 0x44, 0xb9, 0xce, 0x9f, 0x6f, 0x44, 0x55, 0x75, 0xdf, 0xda, 0x08, 0xe1, + 0xb9, 0x34, 0x8f, 0xbf, 0x77, 0xb0, 0x88, 0x31, 0xbe, 0xd6, 0x4e, 0xde, 0xb8, 0x46, 0x59, 0x5e, + 0x08, 0xf4, 0xe6, 0xb5, 0x0b, 0xf9, 0xee, 0x5d, 0x14, 0xd3, 0x75, 0x77, 0xd5, 0x65, 0x8a, 0xd3, + 0x02, 0x81, 0xae, 0xab, 0xfa, 0x5c, 0xe8, 0xbf, 0x75, 0xc4, 0x5f, 0xef, 0x8e, 0xa1, 0x4b, 0xf6, + 0x27, 0x14, 0x40, 0x09, 0xfc, 0x60, 0x62, 0x7c, 0x29, 0xee, 0x1d, 0x14, 0xf7, 0x96, 0xbb, 0x3d, + 0x46, 0x5c, 0x2e, 0xec, 0xef, 0xc3, 0xb6, 0xae, 0xc9, 0x5b, 0x74, 0x3f, 0x1c, 0x44, 0x41, 0x96, + 0xe7, 0xa5, 0x23, 0x0a, 0xf7, 0xb9, 0xe1, 0x14, 0x4b, 0xb5, 0xf6, 0xfd, 0x78, 0x29, 0x47, 0x85, + 0x18, 0x5d, 0x4e, 0x9b, 0x73, 0x4f, 0x60, 0x55, 0xcd, 0xfb, 0x30, 0xf4, 0xd9, 0x2f, 0xcc, 0xf3, + 0x16, 0xf2, 0x6c, 0xb9, 0x1b, 0x26, 0xcf, 0x6e, 0xe8, 0x33, 0xcd, 0x31, 0xc3, 0x27, 0x56, 0xab, + 0x0a, 0x6b, 0x26, 0xdf, 0x95, 0xf5, 0x59, 0x33, 0xf9, 0xae, 0x2e, 0x18, 0xdb, 0xc9, 0xf7, 0x19, + 0x65, 0xa2, 0x80, 0x1b, 0x48, 0x06, 0x17, 0xb0, 0x72, 0x32, 0x92, 0xe9, 0xc9, 0xcf, 0xcd, 0x54, + 0xc6, 0x40, 0x2e, 0x32, 0xcd, 0x0a, 0x4c, 0xf9, 0x62, 0x2f, 0xc4, 0x7b, 0xb2, 0x59, 0x9f, 0x25, + 0x7b, 0xa3, 0x2b, 0xb7, 0x65, 0xbe, 0x95, 0xa5, 0x5d, 0x9b, 0xaf, 0x91, 0x21, 0xe1, 0x5f, 0x2d, + 0x72, 0xbe, 0x43, 0x20, 0x76, 0x96, 0x84, 0x7f, 0xed, 0xa2, 0xbd, 0x40, 0x45, 0x55, 0x76, 0xb2, + 0x14, 0xe9, 0x36, 0x32, 0xde, 0x76, 0x37, 0xcb, 0x29, 0x12, 0xe7, 0xcd, 0x59, 0xff, 0x1e, 0xac, + 0x15, 0x72, 0xef, 0x17, 0xc4, 0xdb, 0x32, 0xe7, 0x42, 0xe2, 0xad, 0x98, 0x33, 0xcc, 0x83, 0x0b, + 0xa5, 0x56, 0x72, 0xbb, 0x2a, 0xdf, 0xb0, 0x2a, 0x99, 0xe3, 0x32, 0x1f, 0x79, 0x6f, 0x90, 0xcd, + 0x52, 0x3a, 0x82, 0x14, 0xde, 0x70, 0xc8, 0x9f, 0x3a, 0xf8, 0x07, 0x06, 0x23, 0x2a, 0xbd, 0xe4, + 0x5e, 0x55, 0xc2, 0x7b, 0x6d, 0x31, 0xa4, 0x3f, 0x21, 0x37, 0x8b, 0x59, 0x71, 0x49, 0x9c, 0x73, + 0xac, 0x40, 0x98, 0xf5, 0x5a, 0x2b, 0x27, 0xaf, 0x28, 0xe4, 0x8e, 0x4c, 0x5a, 0x8b, 0xa9, 0xb8, + 0xcc, 0x2a, 0x15, 0xa7, 0x1f, 0xdb, 0x7f, 0x46, 0x6c, 0xb1, 0xbc, 0x53, 0xb1, 0xea, 0xeb, 0xb0, + 0x7e, 0x05, 0x59, 0xef, 0x92, 0xed, 0xc2, 0x7a, 0x0b, 0x22, 0x88, 0xb0, 0xd6, 0x28, 0xc4, 0x9a, + 0x61, 0x6d, 0xa9, 0xf8, 0x6c, 0x85, 0xb5, 0xe5, 0xfa, 0x6f, 0x29, 0xac, 0xf5, 0x39, 0x0a, 0x5e, + 0x86, 0xa7, 0xb3, 0xf8, 0x2f, 0x8c, 0xbc, 0xf5, 0x7f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x02, 0x27, + 0x05, 0x6d, 0x94, 0x44, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -6146,6 +6148,155 @@ type GoCryptoTraderServer interface { GetAuditEvent(context.Context, *GetAuditEventRequest) (*GetAuditEventResponse, error) } +// UnimplementedGoCryptoTraderServer can be embedded to have forward compatible implementations. +type UnimplementedGoCryptoTraderServer struct { +} + +func (*UnimplementedGoCryptoTraderServer) GetInfo(ctx context.Context, req *GetInfoRequest) (*GetInfoResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetInfo not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetSubsystems(ctx context.Context, req *GetSubsystemsRequest) (*GetSusbsytemsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetSubsystems not implemented") +} +func (*UnimplementedGoCryptoTraderServer) EnableSubsystem(ctx context.Context, req *GenericSubsystemRequest) (*GenericSubsystemResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method EnableSubsystem not implemented") +} +func (*UnimplementedGoCryptoTraderServer) DisableSubsystem(ctx context.Context, req *GenericSubsystemRequest) (*GenericSubsystemResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DisableSubsystem not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetRPCEndpoints(ctx context.Context, req *GetRPCEndpointsRequest) (*GetRPCEndpointsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetRPCEndpoints not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetCommunicationRelayers(ctx context.Context, req *GetCommunicationRelayersRequest) (*GetCommunicationRelayersResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetCommunicationRelayers not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetExchanges(ctx context.Context, req *GetExchangesRequest) (*GetExchangesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetExchanges not implemented") +} +func (*UnimplementedGoCryptoTraderServer) DisableExchange(ctx context.Context, req *GenericExchangeNameRequest) (*GenericExchangeNameResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DisableExchange not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetExchangeInfo(ctx context.Context, req *GenericExchangeNameRequest) (*GetExchangeInfoResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetExchangeInfo not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetExchangeOTPCode(ctx context.Context, req *GenericExchangeNameRequest) (*GetExchangeOTPReponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetExchangeOTPCode not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetExchangeOTPCodes(ctx context.Context, req *GetExchangeOTPsRequest) (*GetExchangeOTPsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetExchangeOTPCodes not implemented") +} +func (*UnimplementedGoCryptoTraderServer) EnableExchange(ctx context.Context, req *GenericExchangeNameRequest) (*GenericExchangeNameResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method EnableExchange not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetTicker(ctx context.Context, req *GetTickerRequest) (*TickerResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetTicker not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetTickers(ctx context.Context, req *GetTickersRequest) (*GetTickersResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetTickers not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetOrderbook(ctx context.Context, req *GetOrderbookRequest) (*OrderbookResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetOrderbook not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetOrderbooks(ctx context.Context, req *GetOrderbooksRequest) (*GetOrderbooksResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetOrderbooks not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetAccountInfo(ctx context.Context, req *GetAccountInfoRequest) (*GetAccountInfoResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetAccountInfo not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetConfig(ctx context.Context, req *GetConfigRequest) (*GetConfigResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetConfig not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetPortfolio(ctx context.Context, req *GetPortfolioRequest) (*GetPortfolioResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetPortfolio not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetPortfolioSummary(ctx context.Context, req *GetPortfolioSummaryRequest) (*GetPortfolioSummaryResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetPortfolioSummary not implemented") +} +func (*UnimplementedGoCryptoTraderServer) AddPortfolioAddress(ctx context.Context, req *AddPortfolioAddressRequest) (*AddPortfolioAddressResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AddPortfolioAddress not implemented") +} +func (*UnimplementedGoCryptoTraderServer) RemovePortfolioAddress(ctx context.Context, req *RemovePortfolioAddressRequest) (*RemovePortfolioAddressResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RemovePortfolioAddress not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetForexProviders(ctx context.Context, req *GetForexProvidersRequest) (*GetForexProvidersResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetForexProviders not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetForexRates(ctx context.Context, req *GetForexRatesRequest) (*GetForexRatesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetForexRates not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetOrders(ctx context.Context, req *GetOrdersRequest) (*GetOrdersResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetOrders not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetOrder(ctx context.Context, req *GetOrderRequest) (*OrderDetails, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetOrder not implemented") +} +func (*UnimplementedGoCryptoTraderServer) SubmitOrder(ctx context.Context, req *SubmitOrderRequest) (*SubmitOrderResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SubmitOrder not implemented") +} +func (*UnimplementedGoCryptoTraderServer) SimulateOrder(ctx context.Context, req *SimulateOrderRequest) (*SimulateOrderResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SimulateOrder not implemented") +} +func (*UnimplementedGoCryptoTraderServer) WhaleBomb(ctx context.Context, req *WhaleBombRequest) (*SimulateOrderResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method WhaleBomb not implemented") +} +func (*UnimplementedGoCryptoTraderServer) CancelOrder(ctx context.Context, req *CancelOrderRequest) (*CancelOrderResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CancelOrder not implemented") +} +func (*UnimplementedGoCryptoTraderServer) CancelAllOrders(ctx context.Context, req *CancelAllOrdersRequest) (*CancelAllOrdersResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method CancelAllOrders not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetEvents(ctx context.Context, req *GetEventsRequest) (*GetEventsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetEvents not implemented") +} +func (*UnimplementedGoCryptoTraderServer) AddEvent(ctx context.Context, req *AddEventRequest) (*AddEventResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method AddEvent not implemented") +} +func (*UnimplementedGoCryptoTraderServer) RemoveEvent(ctx context.Context, req *RemoveEventRequest) (*RemoveEventResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method RemoveEvent not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetCryptocurrencyDepositAddresses(ctx context.Context, req *GetCryptocurrencyDepositAddressesRequest) (*GetCryptocurrencyDepositAddressesResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetCryptocurrencyDepositAddresses not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetCryptocurrencyDepositAddress(ctx context.Context, req *GetCryptocurrencyDepositAddressRequest) (*GetCryptocurrencyDepositAddressResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetCryptocurrencyDepositAddress not implemented") +} +func (*UnimplementedGoCryptoTraderServer) WithdrawCryptocurrencyFunds(ctx context.Context, req *WithdrawCurrencyRequest) (*WithdrawResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method WithdrawCryptocurrencyFunds not implemented") +} +func (*UnimplementedGoCryptoTraderServer) WithdrawFiatFunds(ctx context.Context, req *WithdrawCurrencyRequest) (*WithdrawResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method WithdrawFiatFunds not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetLoggerDetails(ctx context.Context, req *GetLoggerDetailsRequest) (*GetLoggerDetailsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetLoggerDetails not implemented") +} +func (*UnimplementedGoCryptoTraderServer) SetLoggerDetails(ctx context.Context, req *SetLoggerDetailsRequest) (*GetLoggerDetailsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method SetLoggerDetails not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetExchangePairs(ctx context.Context, req *GetExchangePairsRequest) (*GetExchangePairsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetExchangePairs not implemented") +} +func (*UnimplementedGoCryptoTraderServer) EnableExchangePair(ctx context.Context, req *ExchangePairRequest) (*GenericExchangeNameResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method EnableExchangePair not implemented") +} +func (*UnimplementedGoCryptoTraderServer) DisableExchangePair(ctx context.Context, req *ExchangePairRequest) (*GenericExchangeNameResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method DisableExchangePair not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetOrderbookStream(req *GetOrderbookStreamRequest, srv GoCryptoTrader_GetOrderbookStreamServer) error { + return status.Errorf(codes.Unimplemented, "method GetOrderbookStream not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetExchangeOrderbookStream(req *GetExchangeOrderbookStreamRequest, srv GoCryptoTrader_GetExchangeOrderbookStreamServer) error { + return status.Errorf(codes.Unimplemented, "method GetExchangeOrderbookStream not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetTickerStream(req *GetTickerStreamRequest, srv GoCryptoTrader_GetTickerStreamServer) error { + return status.Errorf(codes.Unimplemented, "method GetTickerStream not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetExchangeTickerStream(req *GetExchangeTickerStreamRequest, srv GoCryptoTrader_GetExchangeTickerStreamServer) error { + return status.Errorf(codes.Unimplemented, "method GetExchangeTickerStream not implemented") +} +func (*UnimplementedGoCryptoTraderServer) GetAuditEvent(ctx context.Context, req *GetAuditEventRequest) (*GetAuditEventResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetAuditEvent not implemented") +} + func RegisterGoCryptoTraderServer(s *grpc.Server, srv GoCryptoTraderServer) { s.RegisterService(&_GoCryptoTrader_serviceDesc, srv) } diff --git a/gctrpc/rpc.pb.gw.go b/gctrpc/rpc.pb.gw.go index 1aacb63da0f..6788ff42a5b 100644 --- a/gctrpc/rpc.pb.gw.go +++ b/gctrpc/rpc.pb.gw.go @@ -13,6 +13,7 @@ import ( "io" "net/http" + "github.com/golang/protobuf/descriptor" "github.com/golang/protobuf/proto" "github.com/grpc-ecosystem/grpc-gateway/runtime" "github.com/grpc-ecosystem/grpc-gateway/utilities" @@ -22,11 +23,13 @@ import ( "google.golang.org/grpc/status" ) +// Suppress "imported and not used" errors var _ codes.Code var _ io.Reader var _ status.Status var _ = runtime.String var _ = utilities.NewDoubleArray +var _ = descriptor.ForMessage func request_GoCryptoTrader_GetInfo_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq GetInfoRequest @@ -37,6 +40,15 @@ func request_GoCryptoTrader_GetInfo_0(ctx context.Context, marshaler runtime.Mar } +func local_request_GoCryptoTrader_GetInfo_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetInfoRequest + var metadata runtime.ServerMetadata + + msg, err := server.GetInfo(ctx, &protoReq) + return msg, metadata, err + +} + func request_GoCryptoTrader_GetSubsystems_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq GetSubsystemsRequest var metadata runtime.ServerMetadata @@ -46,6 +58,15 @@ func request_GoCryptoTrader_GetSubsystems_0(ctx context.Context, marshaler runti } +func local_request_GoCryptoTrader_GetSubsystems_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetSubsystemsRequest + var metadata runtime.ServerMetadata + + msg, err := server.GetSubsystems(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_GoCryptoTrader_EnableSubsystem_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -66,6 +87,19 @@ func request_GoCryptoTrader_EnableSubsystem_0(ctx context.Context, marshaler run } +func local_request_GoCryptoTrader_EnableSubsystem_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GenericSubsystemRequest + var metadata runtime.ServerMetadata + + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_EnableSubsystem_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.EnableSubsystem(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_GoCryptoTrader_DisableSubsystem_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -86,6 +120,19 @@ func request_GoCryptoTrader_DisableSubsystem_0(ctx context.Context, marshaler ru } +func local_request_GoCryptoTrader_DisableSubsystem_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GenericSubsystemRequest + var metadata runtime.ServerMetadata + + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_DisableSubsystem_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.DisableSubsystem(ctx, &protoReq) + return msg, metadata, err + +} + func request_GoCryptoTrader_GetRPCEndpoints_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq GetRPCEndpointsRequest var metadata runtime.ServerMetadata @@ -95,6 +142,15 @@ func request_GoCryptoTrader_GetRPCEndpoints_0(ctx context.Context, marshaler run } +func local_request_GoCryptoTrader_GetRPCEndpoints_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetRPCEndpointsRequest + var metadata runtime.ServerMetadata + + msg, err := server.GetRPCEndpoints(ctx, &protoReq) + return msg, metadata, err + +} + func request_GoCryptoTrader_GetCommunicationRelayers_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq GetCommunicationRelayersRequest var metadata runtime.ServerMetadata @@ -104,6 +160,15 @@ func request_GoCryptoTrader_GetCommunicationRelayers_0(ctx context.Context, mars } +func local_request_GoCryptoTrader_GetCommunicationRelayers_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetCommunicationRelayersRequest + var metadata runtime.ServerMetadata + + msg, err := server.GetCommunicationRelayers(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_GoCryptoTrader_GetExchanges_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -124,6 +189,19 @@ func request_GoCryptoTrader_GetExchanges_0(ctx context.Context, marshaler runtim } +func local_request_GoCryptoTrader_GetExchanges_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetExchangesRequest + var metadata runtime.ServerMetadata + + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GetExchanges_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.GetExchanges(ctx, &protoReq) + return msg, metadata, err + +} + func request_GoCryptoTrader_DisableExchange_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq GenericExchangeNameRequest var metadata runtime.ServerMetadata @@ -141,6 +219,23 @@ func request_GoCryptoTrader_DisableExchange_0(ctx context.Context, marshaler run } +func local_request_GoCryptoTrader_DisableExchange_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GenericExchangeNameRequest + 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.DisableExchange(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_GoCryptoTrader_GetExchangeInfo_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -161,6 +256,19 @@ func request_GoCryptoTrader_GetExchangeInfo_0(ctx context.Context, marshaler run } +func local_request_GoCryptoTrader_GetExchangeInfo_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GenericExchangeNameRequest + var metadata runtime.ServerMetadata + + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GetExchangeInfo_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.GetExchangeInfo(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_GoCryptoTrader_GetExchangeOTPCode_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -181,6 +289,19 @@ func request_GoCryptoTrader_GetExchangeOTPCode_0(ctx context.Context, marshaler } +func local_request_GoCryptoTrader_GetExchangeOTPCode_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GenericExchangeNameRequest + var metadata runtime.ServerMetadata + + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GetExchangeOTPCode_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.GetExchangeOTPCode(ctx, &protoReq) + return msg, metadata, err + +} + func request_GoCryptoTrader_GetExchangeOTPCodes_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq GetExchangeOTPsRequest var metadata runtime.ServerMetadata @@ -190,6 +311,15 @@ func request_GoCryptoTrader_GetExchangeOTPCodes_0(ctx context.Context, marshaler } +func local_request_GoCryptoTrader_GetExchangeOTPCodes_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetExchangeOTPsRequest + var metadata runtime.ServerMetadata + + msg, err := server.GetExchangeOTPCodes(ctx, &protoReq) + return msg, metadata, err + +} + func request_GoCryptoTrader_EnableExchange_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq GenericExchangeNameRequest var metadata runtime.ServerMetadata @@ -207,6 +337,23 @@ func request_GoCryptoTrader_EnableExchange_0(ctx context.Context, marshaler runt } +func local_request_GoCryptoTrader_EnableExchange_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GenericExchangeNameRequest + 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.EnableExchange(ctx, &protoReq) + return msg, metadata, err + +} + func request_GoCryptoTrader_GetTicker_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq GetTickerRequest var metadata runtime.ServerMetadata @@ -224,6 +371,23 @@ func request_GoCryptoTrader_GetTicker_0(ctx context.Context, marshaler runtime.M } +func local_request_GoCryptoTrader_GetTicker_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetTickerRequest + 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.GetTicker(ctx, &protoReq) + return msg, metadata, err + +} + func request_GoCryptoTrader_GetTickers_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq GetTickersRequest var metadata runtime.ServerMetadata @@ -233,6 +397,15 @@ func request_GoCryptoTrader_GetTickers_0(ctx context.Context, marshaler runtime. } +func local_request_GoCryptoTrader_GetTickers_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetTickersRequest + var metadata runtime.ServerMetadata + + msg, err := server.GetTickers(ctx, &protoReq) + return msg, metadata, err + +} + func request_GoCryptoTrader_GetOrderbook_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq GetOrderbookRequest var metadata runtime.ServerMetadata @@ -250,6 +423,23 @@ func request_GoCryptoTrader_GetOrderbook_0(ctx context.Context, marshaler runtim } +func local_request_GoCryptoTrader_GetOrderbook_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetOrderbookRequest + 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.GetOrderbook(ctx, &protoReq) + return msg, metadata, err + +} + func request_GoCryptoTrader_GetOrderbooks_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq GetOrderbooksRequest var metadata runtime.ServerMetadata @@ -259,6 +449,15 @@ func request_GoCryptoTrader_GetOrderbooks_0(ctx context.Context, marshaler runti } +func local_request_GoCryptoTrader_GetOrderbooks_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetOrderbooksRequest + var metadata runtime.ServerMetadata + + msg, err := server.GetOrderbooks(ctx, &protoReq) + return msg, metadata, err + +} + var ( filter_GoCryptoTrader_GetAccountInfo_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) @@ -279,6 +478,19 @@ func request_GoCryptoTrader_GetAccountInfo_0(ctx context.Context, marshaler runt } +func local_request_GoCryptoTrader_GetAccountInfo_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetAccountInfoRequest + var metadata runtime.ServerMetadata + + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GetAccountInfo_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.GetAccountInfo(ctx, &protoReq) + return msg, metadata, err + +} + func request_GoCryptoTrader_GetConfig_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq GetConfigRequest var metadata runtime.ServerMetadata @@ -288,6 +500,15 @@ func request_GoCryptoTrader_GetConfig_0(ctx context.Context, marshaler runtime.M } +func local_request_GoCryptoTrader_GetConfig_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetConfigRequest + var metadata runtime.ServerMetadata + + msg, err := server.GetConfig(ctx, &protoReq) + return msg, metadata, err + +} + func request_GoCryptoTrader_GetPortfolio_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq GetPortfolioRequest var metadata runtime.ServerMetadata @@ -297,6 +518,15 @@ func request_GoCryptoTrader_GetPortfolio_0(ctx context.Context, marshaler runtim } +func local_request_GoCryptoTrader_GetPortfolio_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetPortfolioRequest + var metadata runtime.ServerMetadata + + msg, err := server.GetPortfolio(ctx, &protoReq) + return msg, metadata, err + +} + func request_GoCryptoTrader_GetPortfolioSummary_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq GetPortfolioSummaryRequest var metadata runtime.ServerMetadata @@ -306,6 +536,15 @@ func request_GoCryptoTrader_GetPortfolioSummary_0(ctx context.Context, marshaler } +func local_request_GoCryptoTrader_GetPortfolioSummary_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetPortfolioSummaryRequest + var metadata runtime.ServerMetadata + + msg, err := server.GetPortfolioSummary(ctx, &protoReq) + return msg, metadata, err + +} + func request_GoCryptoTrader_AddPortfolioAddress_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq AddPortfolioAddressRequest var metadata runtime.ServerMetadata @@ -323,6 +562,23 @@ func request_GoCryptoTrader_AddPortfolioAddress_0(ctx context.Context, marshaler } +func local_request_GoCryptoTrader_AddPortfolioAddress_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq AddPortfolioAddressRequest + 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.AddPortfolioAddress(ctx, &protoReq) + return msg, metadata, err + +} + func request_GoCryptoTrader_RemovePortfolioAddress_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq RemovePortfolioAddressRequest var metadata runtime.ServerMetadata @@ -340,6 +596,23 @@ func request_GoCryptoTrader_RemovePortfolioAddress_0(ctx context.Context, marsha } +func local_request_GoCryptoTrader_RemovePortfolioAddress_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq RemovePortfolioAddressRequest + 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.RemovePortfolioAddress(ctx, &protoReq) + return msg, metadata, err + +} + func request_GoCryptoTrader_GetForexProviders_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq GetForexProvidersRequest var metadata runtime.ServerMetadata @@ -349,6 +622,15 @@ func request_GoCryptoTrader_GetForexProviders_0(ctx context.Context, marshaler r } +func local_request_GoCryptoTrader_GetForexProviders_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetForexProvidersRequest + var metadata runtime.ServerMetadata + + msg, err := server.GetForexProviders(ctx, &protoReq) + return msg, metadata, err + +} + func request_GoCryptoTrader_GetForexRates_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq GetForexRatesRequest var metadata runtime.ServerMetadata @@ -358,6 +640,15 @@ func request_GoCryptoTrader_GetForexRates_0(ctx context.Context, marshaler runti } +func local_request_GoCryptoTrader_GetForexRates_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetForexRatesRequest + var metadata runtime.ServerMetadata + + msg, err := server.GetForexRates(ctx, &protoReq) + return msg, metadata, err + +} + func request_GoCryptoTrader_GetOrders_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq GetOrdersRequest var metadata runtime.ServerMetadata @@ -375,8 +666,8 @@ func request_GoCryptoTrader_GetOrders_0(ctx context.Context, marshaler runtime.M } -func request_GoCryptoTrader_GetOrder_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetOrderRequest +func local_request_GoCryptoTrader_GetOrders_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetOrdersRequest var metadata runtime.ServerMetadata newReader, berr := utilities.IOReaderFactory(req.Body) @@ -387,13 +678,13 @@ func request_GoCryptoTrader_GetOrder_0(ctx context.Context, marshaler runtime.Ma return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.GetOrder(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := server.GetOrders(ctx, &protoReq) return msg, metadata, err } -func request_GoCryptoTrader_SubmitOrder_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SubmitOrderRequest +func request_GoCryptoTrader_GetOrder_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetOrderRequest var metadata runtime.ServerMetadata newReader, berr := utilities.IOReaderFactory(req.Body) @@ -404,13 +695,13 @@ func request_GoCryptoTrader_SubmitOrder_0(ctx context.Context, marshaler runtime return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.SubmitOrder(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := client.GetOrder(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -func request_GoCryptoTrader_SimulateOrder_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SimulateOrderRequest +func local_request_GoCryptoTrader_GetOrder_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetOrderRequest var metadata runtime.ServerMetadata newReader, berr := utilities.IOReaderFactory(req.Body) @@ -421,13 +712,13 @@ func request_GoCryptoTrader_SimulateOrder_0(ctx context.Context, marshaler runti return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.SimulateOrder(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := server.GetOrder(ctx, &protoReq) return msg, metadata, err } -func request_GoCryptoTrader_WhaleBomb_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq WhaleBombRequest +func request_GoCryptoTrader_SubmitOrder_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq SubmitOrderRequest var metadata runtime.ServerMetadata newReader, berr := utilities.IOReaderFactory(req.Body) @@ -438,13 +729,13 @@ func request_GoCryptoTrader_WhaleBomb_0(ctx context.Context, marshaler runtime.M return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.WhaleBomb(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := client.SubmitOrder(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -func request_GoCryptoTrader_CancelOrder_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq CancelOrderRequest +func local_request_GoCryptoTrader_SubmitOrder_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq SubmitOrderRequest var metadata runtime.ServerMetadata newReader, berr := utilities.IOReaderFactory(req.Body) @@ -455,13 +746,13 @@ func request_GoCryptoTrader_CancelOrder_0(ctx context.Context, marshaler runtime return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.CancelOrder(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := server.SubmitOrder(ctx, &protoReq) return msg, metadata, err } -func request_GoCryptoTrader_CancelAllOrders_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq CancelAllOrdersRequest +func request_GoCryptoTrader_SimulateOrder_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq SimulateOrderRequest var metadata runtime.ServerMetadata newReader, berr := utilities.IOReaderFactory(req.Body) @@ -472,22 +763,30 @@ func request_GoCryptoTrader_CancelAllOrders_0(ctx context.Context, marshaler run return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.CancelAllOrders(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := client.SimulateOrder(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -func request_GoCryptoTrader_GetEvents_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetEventsRequest +func local_request_GoCryptoTrader_SimulateOrder_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq SimulateOrderRequest var metadata runtime.ServerMetadata - msg, err := client.GetEvents(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + 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.SimulateOrder(ctx, &protoReq) return msg, metadata, err } -func request_GoCryptoTrader_AddEvent_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq AddEventRequest +func request_GoCryptoTrader_WhaleBomb_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq WhaleBombRequest var metadata runtime.ServerMetadata newReader, berr := utilities.IOReaderFactory(req.Body) @@ -498,13 +797,13 @@ func request_GoCryptoTrader_AddEvent_0(ctx context.Context, marshaler runtime.Ma return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.AddEvent(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := client.WhaleBomb(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -func request_GoCryptoTrader_RemoveEvent_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq RemoveEventRequest +func local_request_GoCryptoTrader_WhaleBomb_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq WhaleBombRequest var metadata runtime.ServerMetadata newReader, berr := utilities.IOReaderFactory(req.Body) @@ -515,13 +814,13 @@ func request_GoCryptoTrader_RemoveEvent_0(ctx context.Context, marshaler runtime return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.RemoveEvent(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := server.WhaleBomb(ctx, &protoReq) return msg, metadata, err } -func request_GoCryptoTrader_GetCryptocurrencyDepositAddresses_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetCryptocurrencyDepositAddressesRequest +func request_GoCryptoTrader_CancelOrder_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq CancelOrderRequest var metadata runtime.ServerMetadata newReader, berr := utilities.IOReaderFactory(req.Body) @@ -532,13 +831,13 @@ func request_GoCryptoTrader_GetCryptocurrencyDepositAddresses_0(ctx context.Cont return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.GetCryptocurrencyDepositAddresses(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := client.CancelOrder(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -func request_GoCryptoTrader_GetCryptocurrencyDepositAddress_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetCryptocurrencyDepositAddressRequest +func local_request_GoCryptoTrader_CancelOrder_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq CancelOrderRequest var metadata runtime.ServerMetadata newReader, berr := utilities.IOReaderFactory(req.Body) @@ -549,13 +848,13 @@ func request_GoCryptoTrader_GetCryptocurrencyDepositAddress_0(ctx context.Contex return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.GetCryptocurrencyDepositAddress(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := server.CancelOrder(ctx, &protoReq) return msg, metadata, err } -func request_GoCryptoTrader_WithdrawCryptocurrencyFunds_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq WithdrawCurrencyRequest +func request_GoCryptoTrader_CancelAllOrders_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq CancelAllOrdersRequest var metadata runtime.ServerMetadata newReader, berr := utilities.IOReaderFactory(req.Body) @@ -566,13 +865,13 @@ func request_GoCryptoTrader_WithdrawCryptocurrencyFunds_0(ctx context.Context, m return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.WithdrawCryptocurrencyFunds(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := client.CancelAllOrders(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -func request_GoCryptoTrader_WithdrawFiatFunds_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq WithdrawCurrencyRequest +func local_request_GoCryptoTrader_CancelAllOrders_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq CancelAllOrdersRequest var metadata runtime.ServerMetadata newReader, berr := utilities.IOReaderFactory(req.Body) @@ -583,33 +882,48 @@ func request_GoCryptoTrader_WithdrawFiatFunds_0(ctx context.Context, marshaler r return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.WithdrawFiatFunds(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := server.CancelAllOrders(ctx, &protoReq) return msg, metadata, err } -var ( - filter_GoCryptoTrader_GetLoggerDetails_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) +func request_GoCryptoTrader_GetEvents_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetEventsRequest + var metadata runtime.ServerMetadata -func request_GoCryptoTrader_GetLoggerDetails_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetLoggerDetailsRequest + msg, err := client.GetEvents(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_GoCryptoTrader_GetEvents_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetEventsRequest var metadata runtime.ServerMetadata - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + msg, err := server.GetEvents(ctx, &protoReq) + return msg, metadata, err + +} + +func request_GoCryptoTrader_AddEvent_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq AddEventRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GetLoggerDetails_0); err != nil { + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.GetLoggerDetails(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := client.AddEvent(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -func request_GoCryptoTrader_SetLoggerDetails_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SetLoggerDetailsRequest +func local_request_GoCryptoTrader_AddEvent_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq AddEventRequest var metadata runtime.ServerMetadata newReader, berr := utilities.IOReaderFactory(req.Body) @@ -620,13 +934,13 @@ func request_GoCryptoTrader_SetLoggerDetails_0(ctx context.Context, marshaler ru return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.SetLoggerDetails(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := server.AddEvent(ctx, &protoReq) return msg, metadata, err } -func request_GoCryptoTrader_GetExchangePairs_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetExchangePairsRequest +func request_GoCryptoTrader_RemoveEvent_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq RemoveEventRequest var metadata runtime.ServerMetadata newReader, berr := utilities.IOReaderFactory(req.Body) @@ -637,13 +951,13 @@ func request_GoCryptoTrader_GetExchangePairs_0(ctx context.Context, marshaler ru return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.GetExchangePairs(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := client.RemoveEvent(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -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 local_request_GoCryptoTrader_RemoveEvent_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq RemoveEventRequest var metadata runtime.ServerMetadata newReader, berr := utilities.IOReaderFactory(req.Body) @@ -654,13 +968,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 := server.RemoveEvent(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 +func request_GoCryptoTrader_GetCryptocurrencyDepositAddresses_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetCryptocurrencyDepositAddressesRequest var metadata runtime.ServerMetadata newReader, berr := utilities.IOReaderFactory(req.Body) @@ -671,143 +985,1360 @@ func request_GoCryptoTrader_DisableExchangePair_0(ctx context.Context, marshaler return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.DisableExchangePair(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := client.GetCryptocurrencyDepositAddresses(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } -var ( - filter_GoCryptoTrader_GetOrderbookStream_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_GoCryptoTrader_GetOrderbookStream_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (GoCryptoTrader_GetOrderbookStreamClient, runtime.ServerMetadata, error) { - var protoReq GetOrderbookStreamRequest +func local_request_GoCryptoTrader_GetCryptocurrencyDepositAddresses_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetCryptocurrencyDepositAddressesRequest var metadata runtime.ServerMetadata - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GetOrderbookStream_0); err != nil { + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - stream, err := client.GetOrderbookStream(ctx, &protoReq) - if err != nil { - return nil, metadata, err - } - header, err := stream.Header() - if err != nil { - return nil, metadata, err - } - metadata.HeaderMD = header - return stream, metadata, nil + msg, err := server.GetCryptocurrencyDepositAddresses(ctx, &protoReq) + return msg, metadata, err } -var ( - filter_GoCryptoTrader_GetExchangeOrderbookStream_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - -func request_GoCryptoTrader_GetExchangeOrderbookStream_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (GoCryptoTrader_GetExchangeOrderbookStreamClient, runtime.ServerMetadata, error) { - var protoReq GetExchangeOrderbookStreamRequest +func request_GoCryptoTrader_GetCryptocurrencyDepositAddress_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetCryptocurrencyDepositAddressRequest var metadata runtime.ServerMetadata - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GetExchangeOrderbookStream_0); err != nil { + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - stream, err := client.GetExchangeOrderbookStream(ctx, &protoReq) - if err != nil { - return nil, metadata, err + msg, err := client.GetCryptocurrencyDepositAddress(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_GoCryptoTrader_GetCryptocurrencyDepositAddress_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetCryptocurrencyDepositAddressRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) } - header, err := stream.Header() - if err != nil { - return nil, metadata, err + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - metadata.HeaderMD = header - return stream, metadata, nil -} + msg, err := server.GetCryptocurrencyDepositAddress(ctx, &protoReq) + return msg, metadata, err -var ( - filter_GoCryptoTrader_GetTickerStream_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) +} -func request_GoCryptoTrader_GetTickerStream_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (GoCryptoTrader_GetTickerStreamClient, runtime.ServerMetadata, error) { - var protoReq GetTickerStreamRequest +func request_GoCryptoTrader_WithdrawCryptocurrencyFunds_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq WithdrawCurrencyRequest var metadata runtime.ServerMetadata - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GetTickerStream_0); err != nil { + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - stream, err := client.GetTickerStream(ctx, &protoReq) - if err != nil { - return nil, metadata, err + msg, err := client.WithdrawCryptocurrencyFunds(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_GoCryptoTrader_WithdrawCryptocurrencyFunds_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq WithdrawCurrencyRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) } - header, err := stream.Header() - if err != nil { - return nil, metadata, err + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - metadata.HeaderMD = header - return stream, metadata, nil -} + msg, err := server.WithdrawCryptocurrencyFunds(ctx, &protoReq) + return msg, metadata, err -var ( - filter_GoCryptoTrader_GetExchangeTickerStream_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) +} -func request_GoCryptoTrader_GetExchangeTickerStream_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (GoCryptoTrader_GetExchangeTickerStreamClient, runtime.ServerMetadata, error) { - var protoReq GetExchangeTickerStreamRequest +func request_GoCryptoTrader_WithdrawFiatFunds_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq WithdrawCurrencyRequest var metadata runtime.ServerMetadata - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GetExchangeTickerStream_0); err != nil { + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - stream, err := client.GetExchangeTickerStream(ctx, &protoReq) - if err != nil { - return nil, metadata, err + msg, err := client.WithdrawFiatFunds(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_GoCryptoTrader_WithdrawFiatFunds_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq WithdrawCurrencyRequest + var metadata runtime.ServerMetadata + + newReader, berr := utilities.IOReaderFactory(req.Body) + if berr != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr) } - header, err := stream.Header() - if err != nil { - return nil, metadata, err + if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - metadata.HeaderMD = header - return stream, metadata, nil + + msg, err := server.WithdrawFiatFunds(ctx, &protoReq) + return msg, metadata, err } var ( - filter_GoCryptoTrader_GetAuditEvent_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} + filter_GoCryptoTrader_GetLoggerDetails_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} ) -func request_GoCryptoTrader_GetAuditEvent_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq GetAuditEventRequest +func request_GoCryptoTrader_GetLoggerDetails_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + 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_GetAuditEvent_0); err != nil { + if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_GoCryptoTrader_GetLoggerDetails_0); err != nil { return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) } - msg, err := client.GetAuditEvent(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + msg, err := client.GetLoggerDetails(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err } +func local_request_GoCryptoTrader_GetLoggerDetails_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetLoggerDetailsRequest + var metadata runtime.ServerMetadata + + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GetLoggerDetails_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.GetLoggerDetails(ctx, &protoReq) + return msg, metadata, err + +} + +func request_GoCryptoTrader_SetLoggerDetails_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq SetLoggerDetailsRequest + 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.SetLoggerDetails(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_GoCryptoTrader_SetLoggerDetails_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq SetLoggerDetailsRequest + 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.SetLoggerDetails(ctx, &protoReq) + return msg, metadata, err + +} + +func request_GoCryptoTrader_GetExchangePairs_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetExchangePairsRequest + 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.GetExchangePairs(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_GoCryptoTrader_GetExchangePairs_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetExchangePairsRequest + 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.GetExchangePairs(ctx, &protoReq) + return msg, metadata, err + +} + +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 + 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.EnableExchangePair(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 + 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.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) + return msg, metadata, err + +} + +var ( + filter_GoCryptoTrader_GetOrderbookStream_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_GoCryptoTrader_GetOrderbookStream_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (GoCryptoTrader_GetOrderbookStreamClient, runtime.ServerMetadata, error) { + var protoReq GetOrderbookStreamRequest + 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_GetOrderbookStream_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + stream, err := client.GetOrderbookStream(ctx, &protoReq) + if err != nil { + return nil, metadata, err + } + header, err := stream.Header() + if err != nil { + return nil, metadata, err + } + metadata.HeaderMD = header + return stream, metadata, nil + +} + +var ( + filter_GoCryptoTrader_GetExchangeOrderbookStream_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_GoCryptoTrader_GetExchangeOrderbookStream_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (GoCryptoTrader_GetExchangeOrderbookStreamClient, runtime.ServerMetadata, error) { + var protoReq GetExchangeOrderbookStreamRequest + 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_GetExchangeOrderbookStream_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + stream, err := client.GetExchangeOrderbookStream(ctx, &protoReq) + if err != nil { + return nil, metadata, err + } + header, err := stream.Header() + if err != nil { + return nil, metadata, err + } + metadata.HeaderMD = header + return stream, metadata, nil + +} + +var ( + filter_GoCryptoTrader_GetTickerStream_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_GoCryptoTrader_GetTickerStream_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (GoCryptoTrader_GetTickerStreamClient, runtime.ServerMetadata, error) { + var protoReq GetTickerStreamRequest + 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_GetTickerStream_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + stream, err := client.GetTickerStream(ctx, &protoReq) + if err != nil { + return nil, metadata, err + } + header, err := stream.Header() + if err != nil { + return nil, metadata, err + } + metadata.HeaderMD = header + return stream, metadata, nil + +} + +var ( + filter_GoCryptoTrader_GetExchangeTickerStream_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_GoCryptoTrader_GetExchangeTickerStream_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (GoCryptoTrader_GetExchangeTickerStreamClient, runtime.ServerMetadata, error) { + var protoReq GetExchangeTickerStreamRequest + 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_GetExchangeTickerStream_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + stream, err := client.GetExchangeTickerStream(ctx, &protoReq) + if err != nil { + return nil, metadata, err + } + header, err := stream.Header() + if err != nil { + return nil, metadata, err + } + metadata.HeaderMD = header + return stream, metadata, nil + +} + +var ( + filter_GoCryptoTrader_GetAuditEvent_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + +func request_GoCryptoTrader_GetAuditEvent_0(ctx context.Context, marshaler runtime.Marshaler, client GoCryptoTraderClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + 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 { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := client.GetAuditEvent(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err + +} + +func local_request_GoCryptoTrader_GetAuditEvent_0(ctx context.Context, marshaler runtime.Marshaler, server GoCryptoTraderServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq GetAuditEventRequest + var metadata runtime.ServerMetadata + + if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_GoCryptoTrader_GetAuditEvent_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + + msg, err := server.GetAuditEvent(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. +func RegisterGoCryptoTraderHandlerServer(ctx context.Context, mux *runtime.ServeMux, server GoCryptoTraderServer) error { + + mux.Handle("GET", pattern_GoCryptoTrader_GetInfo_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_GetInfo_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_GetInfo_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_GetSubsystems_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_GetSubsystems_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_GetSubsystems_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_EnableSubsystem_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_EnableSubsystem_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_EnableSubsystem_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_DisableSubsystem_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_DisableSubsystem_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_DisableSubsystem_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_GetRPCEndpoints_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_GetRPCEndpoints_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_GetRPCEndpoints_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_GetCommunicationRelayers_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_GetCommunicationRelayers_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_GetCommunicationRelayers_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_GetExchanges_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_GetExchanges_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_GetExchanges_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_GoCryptoTrader_DisableExchange_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_DisableExchange_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_DisableExchange_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_GetExchangeInfo_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_GetExchangeInfo_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_GetExchangeInfo_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_GetExchangeOTPCode_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_GetExchangeOTPCode_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_GetExchangeOTPCode_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_GetExchangeOTPCodes_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_GetExchangeOTPCodes_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_GetExchangeOTPCodes_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_GoCryptoTrader_EnableExchange_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_EnableExchange_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_EnableExchange_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_GoCryptoTrader_GetTicker_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_GetTicker_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_GetTicker_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_GetTickers_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_GetTickers_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_GetTickers_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_GoCryptoTrader_GetOrderbook_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_GetOrderbook_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_GetOrderbook_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_GetOrderbooks_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_GetOrderbooks_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_GetOrderbooks_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_GetAccountInfo_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_GetAccountInfo_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_GetAccountInfo_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_GetConfig_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_GetConfig_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_GetConfig_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_GetPortfolio_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_GetPortfolio_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_GetPortfolio_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_GetPortfolioSummary_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_GetPortfolioSummary_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_GetPortfolioSummary_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_GoCryptoTrader_AddPortfolioAddress_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_AddPortfolioAddress_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_AddPortfolioAddress_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_GoCryptoTrader_RemovePortfolioAddress_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_RemovePortfolioAddress_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_RemovePortfolioAddress_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_GetForexProviders_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_GetForexProviders_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_GetForexProviders_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_GetForexRates_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_GetForexRates_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_GetForexRates_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_GoCryptoTrader_GetOrders_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_GetOrders_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_GetOrders_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_GoCryptoTrader_GetOrder_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_GetOrder_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_GetOrder_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_GoCryptoTrader_SubmitOrder_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_SubmitOrder_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_SubmitOrder_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_GoCryptoTrader_SimulateOrder_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_SimulateOrder_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_SimulateOrder_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_GoCryptoTrader_WhaleBomb_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_WhaleBomb_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_WhaleBomb_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_GoCryptoTrader_CancelOrder_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_CancelOrder_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_CancelOrder_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_GoCryptoTrader_CancelAllOrders_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_CancelAllOrders_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_CancelAllOrders_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_GetEvents_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_GetEvents_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_GetEvents_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_GoCryptoTrader_AddEvent_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_AddEvent_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_AddEvent_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_GoCryptoTrader_RemoveEvent_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_RemoveEvent_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_RemoveEvent_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_GoCryptoTrader_GetCryptocurrencyDepositAddresses_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_GetCryptocurrencyDepositAddresses_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_GetCryptocurrencyDepositAddresses_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_GoCryptoTrader_GetCryptocurrencyDepositAddress_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_GetCryptocurrencyDepositAddress_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_GetCryptocurrencyDepositAddress_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_GoCryptoTrader_WithdrawCryptocurrencyFunds_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_WithdrawCryptocurrencyFunds_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_WithdrawCryptocurrencyFunds_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_GoCryptoTrader_WithdrawFiatFunds_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_WithdrawFiatFunds_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_WithdrawFiatFunds_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_GetLoggerDetails_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_GetLoggerDetails_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_GetLoggerDetails_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_GoCryptoTrader_SetLoggerDetails_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_SetLoggerDetails_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_SetLoggerDetails_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_GoCryptoTrader_GetExchangePairs_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_GetExchangePairs_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_GetExchangePairs_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + mux.Handle("POST", pattern_GoCryptoTrader_EnableExchangePair_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_EnableExchangePair_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()...) + + }) + + mux.Handle("GET", pattern_GoCryptoTrader_GetOrderbookStream_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport") + _, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + }) + + mux.Handle("GET", pattern_GoCryptoTrader_GetExchangeOrderbookStream_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport") + _, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + }) + + mux.Handle("GET", pattern_GoCryptoTrader_GetTickerStream_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport") + _, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + }) + + mux.Handle("GET", pattern_GoCryptoTrader_GetExchangeTickerStream_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport") + _, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + }) + + mux.Handle("GET", pattern_GoCryptoTrader_GetAuditEvent_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_GetAuditEvent_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_GetAuditEvent_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + + }) + + return nil +} + // RegisterGoCryptoTraderHandlerFromEndpoint is same as RegisterGoCryptoTraderHandler but // automatically dials to "endpoint" and closes the connection when "ctx" gets done. func RegisterGoCryptoTraderHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) { diff --git a/gctrpc/rpc.proto b/gctrpc/rpc.proto index 7e42319fcee..079d2747376 100644 --- a/gctrpc/rpc.proto +++ b/gctrpc/rpc.proto @@ -518,10 +518,10 @@ message GetAuditEventRequest { } message GetAuditEventResponse { - repeated audit_event events = 1; + repeated AuditEvent events = 1; } -message audit_event { +message AuditEvent { string type = 1 ; string identifier = 2; string message = 3; diff --git a/gctrpc/rpc.swagger.json b/gctrpc/rpc.swagger.json index c6687dea248..6f754eb17e9 100644 --- a/gctrpc/rpc.swagger.json +++ b/gctrpc/rpc.swagger.json @@ -1283,6 +1283,23 @@ "gctrpcAddPortfolioAddressResponse": { "type": "object" }, + "gctrpcAuditEvent": { + "type": "object", + "properties": { + "type": { + "type": "string" + }, + "identifier": { + "type": "string" + }, + "message": { + "type": "string" + }, + "timestamp": { + "type": "string" + } + } + }, "gctrpcCancelAllOrdersRequest": { "type": "object", "properties": { @@ -1498,7 +1515,7 @@ "events": { "type": "array", "items": { - "$ref": "#/definitions/gctrpcaudit_event" + "$ref": "#/definitions/gctrpcAuditEvent" } } } @@ -2381,23 +2398,6 @@ } } }, - "gctrpcaudit_event": { - "type": "object", - "properties": { - "type": { - "type": "string" - }, - "identifier": { - "type": "string" - }, - "message": { - "type": "string" - }, - "timestamp": { - "type": "string" - } - } - }, "protobufAny": { "type": "object", "properties": { diff --git a/main.go b/main.go index 10816b3eefb..38dab7471ca 100644 --- a/main.go +++ b/main.go @@ -36,8 +36,6 @@ func main() { flag.BoolVar(&settings.EnableCommsRelayer, "enablecommsrelayer", true, "enables available communications relayer") flag.BoolVar(&settings.Verbose, "verbose", false, "increases logging verbosity for GoCryptoTrader") flag.BoolVar(&settings.EnableExchangeSyncManager, "syncmanager", true, "enables to exchange sync manager") - flag.BoolVar(&settings.EnableTickerSyncing, "tickersync", true, "enables ticker syncing for all enabled exchanges") - flag.BoolVar(&settings.EnableOrderbookSyncing, "orderbooksync", true, "enables orderbook syncing for all enabled exchanges") flag.BoolVar(&settings.EnableWebsocketRoutine, "websocketroutine", true, "enables the websocket routine for all loaded exchanges") flag.BoolVar(&settings.EnableCoinmarketcapAnalysis, "coinmarketcap", false, "overrides config and runs currency analysis") flag.BoolVar(&settings.EnableEventManager, "eventmanager", true, "enables the event manager") @@ -51,6 +49,15 @@ func main() { flag.IntVar(&settings.DispatchMaxWorkerAmount, "dispatchworkers", dispatch.DefaultMaxWorkers, "sets the dispatch package max worker generation limit") flag.IntVar(&settings.DispatchJobsLimit, "dispatchjobslimit", dispatch.DefaultJobsLimit, "sets the dispatch package max jobs limit") + // Exchange syncer settings + flag.BoolVar(&settings.EnableTickerSyncing, "tickersync", true, "enables ticker syncing for all enabled exchanges") + flag.BoolVar(&settings.EnableOrderbookSyncing, "orderbooksync", true, "enables orderbook syncing for all enabled exchanges") + flag.BoolVar(&settings.EnableTradeSyncing, "tradesync", false, "enables trade syncing for all enabled exchanges") + flag.IntVar(&settings.SyncWorkers, "syncworkers", engine.DefaultSyncerWorkers, "the amount of workers (goroutines) to use for syncing exchange data") + flag.BoolVar(&settings.SyncContinuously, "synccontinuously", true, "whether to sync exchange data continuously (ticker, orderbook and trade history info") + flag.DurationVar(&settings.SyncTimeout, "synctimeout", engine.DefaultSyncerTimeout, + "the amount of time before the syncer will switch from one protocol to the other (e.g. from REST to websocket)") + // Forex provider settings flag.BoolVar(&settings.EnableCurrencyConverter, "currencyconverter", false, "overrides config and sets up foreign exchange Currency Converter") flag.BoolVar(&settings.EnableCurrencyLayer, "currencylayer", false, "overrides config and sets up foreign exchange Currency Layer") @@ -65,7 +72,7 @@ func main() { flag.BoolVar(&settings.EnableExchangeVerbose, "exchangeverbose", false, "increases exchange logging verbosity") flag.BoolVar(&settings.ExchangePurgeCredentials, "exchangepurgecredentials", false, "purges the stored exchange API credentials") flag.BoolVar(&settings.EnableExchangeHTTPRateLimiter, "ratelimiter", true, "enables the rate limiter for HTTP requests") - flag.IntVar(&settings.MaxHTTPRequestJobsLimit, "maxhttprequestjobslimit", request.DefaultMaxRequestJobs, "sets the max amount of jobs the HTTP request package stores") + flag.IntVar(&settings.MaxHTTPRequestJobsLimit, "requestjobslimit", request.DefaultMaxRequestJobs, "sets the max amount of jobs the HTTP request package stores") flag.IntVar(&settings.RequestTimeoutRetryAttempts, "exchangehttptimeoutretryattempts", request.DefaultTimeoutRetryAttempts, "sets the amount of retry attempts after a HTTP request times out") flag.DurationVar(&settings.ExchangeHTTPTimeout, "exchangehttptimeout", time.Duration(0), "sets the exchangs HTTP timeout value for HTTP requests") flag.StringVar(&settings.ExchangeHTTPUserAgent, "exchangehttpuseragent", "", "sets the exchanges HTTP user agent") @@ -88,6 +95,7 @@ func main() { fmt.Println(core.Version(false)) var err error + settings.CheckParamInteraction = true engine.Bot, err = engine.NewFromSettings(&settings) if engine.Bot == nil || err != nil { log.Errorf(log.Global, "Unable to initialise bot engine. Error: %s\n", err) diff --git a/testdata/http_mock/anx/anx.json b/testdata/http_mock/anx/anx.json index fcf8ca46db3..7875089fe64 100644 --- a/testdata/http_mock/anx/anx.json +++ b/testdata/http_mock/anx/anx.json @@ -2339,7 +2339,7 @@ "timestamp": "1565238020536" }, "queryString": "", - "bodyParams": "{\"nonce\":\"1565238020075\",\"order\":{\"orderType\":\"MARKET\",\"buyTradedCurrency\":true,\"tradedCurrency\":\"BTC\",\"settlementCurrency\":\"USD\",\"tradedCurrencyAmount\":\"1\",\"settlementCurrencyAmount\":\"0\",\"limitPriceInSettlementCurrency\":\"0\",\"replaceExistingOrderUuid\":\"\",\"replaceOnlyIfActive\":false}}", + "bodyParams": "{\"nonce\":\"1565238020075\",\"order\":{\"orderType\":\"LIMIT\",\"buyTradedCurrency\":true,\"tradedCurrency\":\"BTC\",\"settlementCurrency\":\"USD\",\"tradedCurrencyAmount\":\"1\",\"settlementCurrencyAmount\":\"0\",\"limitPriceInSettlementCurrency\":\"1\",\"replaceExistingOrderUuid\":\"\",\"replaceOnlyIfActive\":false}}", "headers": { "Content-Type": [ "application/json" diff --git a/testdata/http_mock/binance/binance.json b/testdata/http_mock/binance/binance.json index 0094c8206ba..3bedf4193b0 100644 --- a/testdata/http_mock/binance/binance.json +++ b/testdata/http_mock/binance/binance.json @@ -45378,7 +45378,7 @@ "POST": [ { "data": {}, - "queryString": "quantity=1000000000\u0026recvWindow=5000\u0026side=BUY\u0026signature=d122bfd46f4dcf8dda98974aed14221916aabc050a6aa30194d124e81ffe7f44\u0026symbol=LTCBTC\u0026timeInForce=GTC\u0026timestamp=1560236466000\u0026type=MARKET", + "queryString": "price=1\u0026quantity=1000000000\u0026recvWindow=5000\u0026side=BUY\u0026symbol=LTCBTC\u0026timeInForce=GTC\u0026timestamp=1572330506000\u0026type=LIMIT\u0026signature=00954d00c69761017b3440e6e26d9bf6b394bea354c658ca09254b8c28995c73", "bodyParams": "", "headers": { "Key": [ diff --git a/testdata/http_mock/bitstamp/bitstamp.json b/testdata/http_mock/bitstamp/bitstamp.json index 900a690e3b2..8032e1f8f82 100644 --- a/testdata/http_mock/bitstamp/bitstamp.json +++ b/testdata/http_mock/bitstamp/bitstamp.json @@ -177,7 +177,7 @@ "error": "Order not found" }, "queryString": "", - "bodyParams": "id=1\u0026key=\u0026nonce=1560467884949723197\u0026signature=79D88FC2BC3AECBFDD27F70EF5DDBB485349F45129C58EE725BAEE0DF7818452", + "bodyParams": "id=1234\u0026key=\u0026nonce=1560467884949723197\u0026signature=79D88FC2BC3AECBFDD27F70EF5DDBB485349F45129C58EE725BAEE0DF7818452", "headers": { "Content-Type": [ "application/x-www-form-urlencoded" diff --git a/testdata/http_mock/gemini/gemini.json b/testdata/http_mock/gemini/gemini.json index b40bab4a183..e0e75a8c5fa 100644 --- a/testdata/http_mock/gemini/gemini.json +++ b/testdata/http_mock/gemini/gemini.json @@ -1903,7 +1903,7 @@ "result": "error" }, "queryString": "", - "bodyParams": "{\"amount\":\"1\",\"nonce\":\"1565757283294274961\",\"price\":\"9000\",\"request\":\"/v1/order/new\",\"side\":\"buy\",\"symbol\":\"btcusd\",\"type\":\"exchange limit\"}", + "bodyParams": "{\"amount\":\"1\",\"nonce\":\"1565757283294274961\",\"price\":\"9000000\",\"request\":\"/v1/order/new\",\"side\":\"sell\",\"symbol\":\"btcusd\",\"type\":\"exchange limit\"}", "headers": { "Cache-Control": [ "no-cache" diff --git a/web/src/app/services/websocket-response-handler/websocket-response-handler.service.ts b/web/src/app/services/websocket-response-handler/websocket-response-handler.service.ts index 4618cf65bdc..ec5603d873a 100644 --- a/web/src/app/services/websocket-response-handler/websocket-response-handler.service.ts +++ b/web/src/app/services/websocket-response-handler/websocket-response-handler.service.ts @@ -5,7 +5,7 @@ import { Observable, Subject } from 'rxjs/Rx'; import { WebsocketService } from './../../services/websocket/websocket.service'; import { WebSocketMessage } from './../../shared/classes/websocket'; -const WEBSOCKET_URL = 'ws://localhost:9050/ws'; +const WEBSOCKET_URL = 'ws://localhost:9051/ws'; @NgModule({ })