mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-14 07:26:47 +00:00
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
This commit is contained in:
59
.github/CONTRIBUTING.md
vendored
59
.github/CONTRIBUTING.md
vendored
@@ -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).
|
||||
|
||||
|
||||
### 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
|
||||
|
||||
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
|
||||
|
||||
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.
|
||||
The package comment for the fmt package uses this to good effect.
|
||||
|
||||
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.
|
||||
The package comment for the fmt package uses this to good effect.
|
||||
|
||||
6
.github/CONTRIBUTING_TEMPLATE.md
vendored
6
.github/CONTRIBUTING_TEMPLATE.md
vendored
@@ -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}}
|
||||
{{end}}
|
||||
|
||||
2
.github/ISSUE_TEMPLATE.md
vendored
2
.github/ISSUE_TEMPLATE.md
vendored
@@ -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.
|
||||
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.
|
||||
|
||||
22
.github/PULL_REQUEST_TEMPLATE.md
vendored
22
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -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
|
||||
- [ ] Any dependent changes have been merged and published in downstream modules
|
||||
|
||||
@@ -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
|
||||
|
||||
14
Dockerfile
14
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" ]
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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}}
|
||||
|
||||
@@ -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 {
|
||||
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, err := cfg.GetExchangeConfig("{{.CapitalName}}")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
{{.Variable}}.Setup({{.Name}}Config)
|
||||
exchCfg.API.AuthenticatedSupport = true
|
||||
{{ if .WS }} exchCfg.API.AuthenticatedWebsocketSupport = true {{ end }}
|
||||
exchCfg.API.Credentials.Key = apiKey
|
||||
exchCfg.API.Credentials.Secret = apiSecret
|
||||
|
||||
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}}
|
||||
|
||||
@@ -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 _, bids := range orderbookNew.Bids {
|
||||
// orderBook.Bids = append(orderBook.Bids, orderbook.Item{Amount: bids.Quantity, Price: bids.Price})
|
||||
//}
|
||||
for x := range orderbookNew.Bids {
|
||||
orderBook.Bids = append(orderBook.Bids, orderbook.Item{
|
||||
Amount: orderbookNew.Bids[x].Quantity,
|
||||
Price: orderbookNew.Bids[x].Price,
|
||||
})
|
||||
}
|
||||
|
||||
//for _, asks := range orderbookNew.Asks {
|
||||
// orderBook.Asks = append(orderBook.Asks, orderbook.Item{Amount: asks.Quantity, Price: asks.Price})
|
||||
//}
|
||||
for x := range orderbookNew.Asks {
|
||||
orderBook.Asks = append(orderBook.Asks, orderbook.Item{
|
||||
Amount: orderBook.Asks[x].Quantity,
|
||||
Price: orderBook.Asks[x].Price,
|
||||
})
|
||||
}
|
||||
*/
|
||||
|
||||
//orderbook.ProcessOrderbook(b.Name, p, orderBook, assetType)
|
||||
//return orderbook.Get({{.Variable}}.Name, p, assetType)
|
||||
return orderBook, nil // NOTE DO NOT USE AS RETURN
|
||||
|
||||
orderBook.Pair = p
|
||||
orderBook.ExchangeName = {{.Variable}}.Name
|
||||
orderBook.AssetType = assetType
|
||||
|
||||
err := orderBook.Process()
|
||||
if err != nil {
|
||||
return orderBook, err
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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"`
|
||||
|
||||
@@ -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"`
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
var transactions []UserTransactions
|
||||
|
||||
for _, y := range response {
|
||||
for x := 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)
|
||||
}
|
||||
|
||||
tx.Fee = y.Fee
|
||||
tx.OrderID = y.OrderID
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"`
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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"`
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -66,4 +66,5 @@ type IBotExchange interface {
|
||||
GetSubscriptions() ([]wshandler.WebsocketChannelSubscription, error)
|
||||
GetDefaultConfig() (*config.ExchangeConfig, error)
|
||||
GetBase() *Base
|
||||
SupportsAsset(assetType asset.Item) bool
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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{}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -25,6 +25,7 @@ var Exchanges = []string{
|
||||
"btc markets",
|
||||
"btse",
|
||||
"coinbasepro",
|
||||
"coinbene",
|
||||
"coinut",
|
||||
"exmo",
|
||||
"gateio",
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
755
gctrpc/rpc.pb.go
755
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)
|
||||
}
|
||||
|
||||
1531
gctrpc/rpc.pb.gw.go
1531
gctrpc/rpc.pb.gw.go
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
|
||||
@@ -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": {
|
||||
|
||||
14
main.go
14
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)
|
||||
|
||||
2
testdata/http_mock/anx/anx.json
vendored
2
testdata/http_mock/anx/anx.json
vendored
@@ -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"
|
||||
|
||||
2
testdata/http_mock/binance/binance.json
vendored
2
testdata/http_mock/binance/binance.json
vendored
@@ -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": [
|
||||
|
||||
2
testdata/http_mock/bitstamp/bitstamp.json
vendored
2
testdata/http_mock/bitstamp/bitstamp.json
vendored
@@ -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"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user