mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-20 07:26:46 +00:00
CI: Fix golangci-lint linter issues, add prealloc linter and bump version depends for Go 1.18 (#915)
* Bump CI versions * Specifically set go version as 1.17.x bumps it to 1.18 * Another * Adjust AppVeyor * Part 1 of linter issues * Part 2 * Fix various linters and improvements * Part 3 * Finishing touches * Tests and EqualFold * Fix nitterinos plus bonus requester jobs bump for exchanges with large number of tests * Fix nitterinos and bump golangci-lint timeout for AppVeyor * Address nits, ensure all books are returned on err due to syncer regression * Fix the wiggins * Fix duplication * Fix nitterinos
This commit is contained in:
@@ -28,13 +28,15 @@ environment:
|
||||
PSQL_SSLMODE: disable
|
||||
PSQL_SKIPSQLCMD: true
|
||||
PSQL_TESTDBNAME: gct_dev_ci
|
||||
stack: go 1.17.x
|
||||
|
||||
stack: go 1.17.8 # this is not actually used on Windows images
|
||||
|
||||
services:
|
||||
- postgresql96
|
||||
|
||||
init:
|
||||
- SET PATH=%POSTGRES_PATH%\bin;%PATH%
|
||||
- set PATH=%POSTGRES_PATH%\bin;%PATH%
|
||||
- set PATH=C:\go118\bin;%PATH%
|
||||
|
||||
install:
|
||||
- set Path=C:\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin;%Path%
|
||||
@@ -53,7 +55,7 @@ before_test:
|
||||
|
||||
test_script:
|
||||
# test back-end
|
||||
- go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.42.1
|
||||
- go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.45.2
|
||||
- '%GOPATH%\bin\golangci-lint.exe run --verbose'
|
||||
- ps: >-
|
||||
if($env:APPVEYOR_SCHEDULED_BUILD -eq 'true') {
|
||||
|
||||
8
.github/dependabot.yml
vendored
8
.github/dependabot.yml
vendored
@@ -1,10 +1,13 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
- package-ecosystem: gomod
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: daily
|
||||
time: "19:30"
|
||||
interval: "weekly"
|
||||
open-pull-requests-limit: 10
|
||||
- package-ecosystem: npm
|
||||
directory: "/web"
|
||||
@@ -12,4 +15,3 @@ updates:
|
||||
interval: "weekly"
|
||||
# deprecated for now as it requires a more in-depth overhaul
|
||||
open-pull-requests-limit: 0
|
||||
|
||||
|
||||
11
.github/workflows/linter.yml
vendored
11
.github/workflows/linter.yml
vendored
@@ -5,8 +5,11 @@ jobs:
|
||||
name: lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
version: v1.42.1
|
||||
go-version: '1.18.x'
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
with:
|
||||
version: v1.45.2
|
||||
|
||||
2
.github/workflows/tests.yml
vendored
2
.github/workflows/tests.yml
vendored
@@ -1,7 +1,7 @@
|
||||
on: [push, pull_request]
|
||||
name: CI
|
||||
env:
|
||||
GO_VERSION: 1.17.x
|
||||
GO_VERSION: 1.18.x
|
||||
jobs:
|
||||
backend-psql:
|
||||
name: GoCryptoTrader back-end with PSQL
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
run:
|
||||
timeout: 6m
|
||||
timeout: 8m
|
||||
issues-exit-code: 1
|
||||
tests: true
|
||||
skip-dirs:
|
||||
- vendor
|
||||
- web/
|
||||
- testdata
|
||||
- database/models/
|
||||
|
||||
linters:
|
||||
disable-all: true
|
||||
@@ -24,12 +25,17 @@ linters:
|
||||
|
||||
# disabled by default linters
|
||||
- asciicheck
|
||||
- bidichk
|
||||
- bodyclose
|
||||
- containedctx
|
||||
# - contextcheck
|
||||
# - cyclop
|
||||
- decorder
|
||||
- depguard
|
||||
- dogsled
|
||||
# - dupl
|
||||
- durationcheck
|
||||
- errchkjson
|
||||
- errname
|
||||
# - errorlint
|
||||
# - exhaustive
|
||||
@@ -58,10 +64,13 @@ linters:
|
||||
- gomodguard
|
||||
- goprintffuncname
|
||||
- gosec
|
||||
- grouper
|
||||
- ifshort
|
||||
# - importas
|
||||
# - interfacer // deprecated by its owner
|
||||
# - ireturn
|
||||
# - lll
|
||||
# - maintidx
|
||||
- makezero
|
||||
# - maligned
|
||||
- misspell
|
||||
@@ -72,7 +81,7 @@ linters:
|
||||
- noctx
|
||||
- nolintlint
|
||||
# - paralleltest
|
||||
# - prealloc
|
||||
- prealloc
|
||||
- predeclared
|
||||
# - promlinter
|
||||
- revive
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.17 as build
|
||||
FROM golang:1.18 as build
|
||||
WORKDIR /go/src/github.com/thrasher-corp/gocryptotrader
|
||||
COPY . .
|
||||
RUN GO111MODULE=on go mod vendor
|
||||
|
||||
2
Makefile
2
Makefile
@@ -1,6 +1,6 @@
|
||||
LDFLAGS = -ldflags "-w -s"
|
||||
GCTPKG = github.com/thrasher-corp/gocryptotrader
|
||||
LINTPKG = github.com/golangci/golangci-lint/cmd/golangci-lint@v1.42.1
|
||||
LINTPKG = github.com/golangci/golangci-lint/cmd/golangci-lint@v1.45.2
|
||||
LINTBIN = $(GOPATH)/bin/golangci-lint
|
||||
GCTLISTENPORT=9050
|
||||
GCTPROFILERLISTENPORT=8085
|
||||
|
||||
@@ -648,7 +648,7 @@ func (bt *BackTest) loadData(cfg *config.Config, exch gctexchange.IBotExchange,
|
||||
if cfg.DataSettings.DatabaseData.Path == "" {
|
||||
cfg.DataSettings.DatabaseData.Path = filepath.Join(gctcommon.GetDefaultDataDir(runtime.GOOS), "database")
|
||||
}
|
||||
gctdatabase.DB.DataPath = filepath.Join(cfg.DataSettings.DatabaseData.Path)
|
||||
gctdatabase.DB.DataPath = cfg.DataSettings.DatabaseData.Path
|
||||
err = gctdatabase.DB.SetConfig(&cfg.DataSettings.DatabaseData.Config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
@@ -21,7 +21,7 @@ func ReadConfigFromFile(path string) (*Config, error) {
|
||||
return nil, errors.New("file not found")
|
||||
}
|
||||
|
||||
fileData, err := ioutil.ReadFile(path)
|
||||
fileData, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/backtester/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/backtester/eventhandlers/strategies/base"
|
||||
"github.com/thrasher-corp/gocryptotrader/backtester/eventhandlers/strategies/top2bottom2"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/file"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
"github.com/thrasher-corp/gocryptotrader/database"
|
||||
"github.com/thrasher-corp/gocryptotrader/database/drivers"
|
||||
@@ -210,7 +211,7 @@ func TestGenerateConfigForDCAAPICandles(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ioutil.WriteFile(filepath.Join(p, "examples", "dca-api-candles.strat"), result, 0770)
|
||||
err = os.WriteFile(filepath.Join(p, "examples", "dca-api-candles.strat"), result, file.DefaultPermissionOctal)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -288,7 +289,7 @@ func TestGenerateConfigForDCAAPICandlesExchangeLevelFunding(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ioutil.WriteFile(filepath.Join(p, "examples", "dca-api-candles-exchange-level-funding.strat"), result, 0770)
|
||||
err = os.WriteFile(filepath.Join(p, "examples", "dca-api-candles-exchange-level-funding.strat"), result, file.DefaultPermissionOctal)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -356,7 +357,7 @@ func TestGenerateConfigForDCAAPITrades(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ioutil.WriteFile(filepath.Join(p, "examples", "dca-api-trades.strat"), result, 0770)
|
||||
err = os.WriteFile(filepath.Join(p, "examples", "dca-api-trades.strat"), result, file.DefaultPermissionOctal)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -429,7 +430,7 @@ func TestGenerateConfigForDCAAPICandlesMultipleCurrencies(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ioutil.WriteFile(filepath.Join(p, "examples", "dca-api-candles-multiple-currencies.strat"), result, 0770)
|
||||
err = os.WriteFile(filepath.Join(p, "examples", "dca-api-candles-multiple-currencies.strat"), result, file.DefaultPermissionOctal)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -503,7 +504,7 @@ func TestGenerateConfigForDCAAPICandlesSimultaneousProcessing(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ioutil.WriteFile(filepath.Join(p, "examples", "dca-api-candles-simultaneous-processing.strat"), result, 0770)
|
||||
err = os.WriteFile(filepath.Join(p, "examples", "dca-api-candles-simultaneous-processing.strat"), result, file.DefaultPermissionOctal)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -566,7 +567,7 @@ func TestGenerateConfigForDCALiveCandles(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ioutil.WriteFile(filepath.Join(p, "examples", "dca-candles-live.strat"), result, 0770)
|
||||
err = os.WriteFile(filepath.Join(p, "examples", "dca-candles-live.strat"), result, file.DefaultPermissionOctal)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -645,7 +646,7 @@ func TestGenerateConfigForRSIAPICustomSettings(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ioutil.WriteFile(filepath.Join(p, "examples", "rsi-api-candles.strat"), result, 0770)
|
||||
err = os.WriteFile(filepath.Join(p, "examples", "rsi-api-candles.strat"), result, file.DefaultPermissionOctal)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -704,7 +705,7 @@ func TestGenerateConfigForDCACSVCandles(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ioutil.WriteFile(filepath.Join(p, "examples", "dca-csv-candles.strat"), result, 0770)
|
||||
err = os.WriteFile(filepath.Join(p, "examples", "dca-csv-candles.strat"), result, file.DefaultPermissionOctal)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -759,7 +760,7 @@ func TestGenerateConfigForDCACSVTrades(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ioutil.WriteFile(filepath.Join(p, "examples", "dca-csv-trades.strat"), result, 0770)
|
||||
err = os.WriteFile(filepath.Join(p, "examples", "dca-csv-trades.strat"), result, file.DefaultPermissionOctal)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -827,7 +828,7 @@ func TestGenerateConfigForDCADatabaseCandles(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ioutil.WriteFile(filepath.Join(p, "examples", "dca-database-candles.strat"), result, 0770)
|
||||
err = os.WriteFile(filepath.Join(p, "examples", "dca-database-candles.strat"), result, file.DefaultPermissionOctal)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@@ -956,7 +957,7 @@ func TestGenerateConfigForTop2Bottom2(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = ioutil.WriteFile(filepath.Join(p, "examples", "t2b2-api-candles-exchange-funding.strat"), result, 0770)
|
||||
err = os.WriteFile(filepath.Join(p, "examples", "t2b2-api-candles-exchange-funding.strat"), result, file.DefaultPermissionOctal)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -19,6 +18,7 @@ import (
|
||||
"github.com/thrasher-corp/gocryptotrader/backtester/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/backtester/eventhandlers/strategies"
|
||||
gctcommon "github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/file"
|
||||
"github.com/thrasher-corp/gocryptotrader/database"
|
||||
dbPSQL "github.com/thrasher-corp/gocryptotrader/database/drivers/postgres"
|
||||
dbsqlite3 "github.com/thrasher-corp/gocryptotrader/database/drivers/sqlite3"
|
||||
@@ -141,7 +141,7 @@ func main() {
|
||||
if path == "" {
|
||||
path = wd
|
||||
}
|
||||
err = ioutil.WriteFile(path, resp, 0770)
|
||||
err = os.WriteFile(path, resp, file.DefaultPermissionOctal)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@@ -235,10 +235,10 @@ func parseExchangeSettings(reader *bufio.Reader, cfg *config.Config) error {
|
||||
func parseStrategySettings(cfg *config.Config, reader *bufio.Reader) error {
|
||||
fmt.Println("Firstly, please select which strategy you wish to use")
|
||||
strats := strategies.GetStrategies()
|
||||
var strategiesToUse []string
|
||||
strategiesToUse := make([]string, len(strats))
|
||||
for i := range strats {
|
||||
fmt.Printf("%v. %s\n", i+1, strats[i].Name())
|
||||
strategiesToUse = append(strategiesToUse, strats[i].Name())
|
||||
strategiesToUse[i] = strats[i].Name()
|
||||
}
|
||||
var err error
|
||||
cfg.StrategySettings.Name, err = parseStratName(quickParse(reader), strategiesToUse)
|
||||
|
||||
@@ -58,7 +58,7 @@ func (d *DataFromKline) AppendResults(ki *gctkline.Item) {
|
||||
if d.addedTimes == nil {
|
||||
d.addedTimes = make(map[time.Time]bool)
|
||||
}
|
||||
var klineData []common.DataEventHandler
|
||||
|
||||
var gctCandles []gctkline.Candle
|
||||
for i := range ki.Candles {
|
||||
if _, ok := d.addedTimes[ki.Candles[i].Time]; !ok {
|
||||
@@ -66,10 +66,11 @@ func (d *DataFromKline) AppendResults(ki *gctkline.Item) {
|
||||
d.addedTimes[ki.Candles[i].Time] = true
|
||||
}
|
||||
}
|
||||
var candleTimes []time.Time
|
||||
|
||||
klineData := make([]common.DataEventHandler, len(gctCandles))
|
||||
candleTimes := make([]time.Time, len(gctCandles))
|
||||
for i := range gctCandles {
|
||||
klineData = append(klineData, &kline.Kline{
|
||||
klineData[i] = &kline.Kline{
|
||||
Base: event.Base{
|
||||
Offset: int64(i + 1),
|
||||
Exchange: ki.Exchange,
|
||||
@@ -84,8 +85,8 @@ func (d *DataFromKline) AppendResults(ki *gctkline.Item) {
|
||||
Close: decimal.NewFromFloat(gctCandles[i].Close),
|
||||
Volume: decimal.NewFromFloat(gctCandles[i].Volume),
|
||||
ValidationIssues: gctCandles[i].ValidationIssues,
|
||||
})
|
||||
candleTimes = append(candleTimes, gctCandles[i].Time)
|
||||
}
|
||||
candleTimes[i] = gctCandles[i].Time
|
||||
}
|
||||
for i := range d.RangeHolder.Ranges {
|
||||
for j := range d.RangeHolder.Ranges[i].Intervals {
|
||||
|
||||
@@ -135,8 +135,7 @@ func TestStreamOpen(t *testing.T) {
|
||||
a := asset.Spot
|
||||
p := currency.NewPair(currency.BTC, currency.USDT)
|
||||
d := DataFromKline{}
|
||||
bad := d.StreamOpen()
|
||||
if len(bad) > 0 {
|
||||
if bad := d.StreamOpen(); len(bad) > 0 {
|
||||
t.Error("expected no stream")
|
||||
}
|
||||
d.SetStream([]common.DataEventHandler{
|
||||
@@ -156,8 +155,7 @@ func TestStreamOpen(t *testing.T) {
|
||||
},
|
||||
})
|
||||
d.Next()
|
||||
open := d.StreamOpen()
|
||||
if len(open) == 0 {
|
||||
if open := d.StreamOpen(); len(open) == 0 {
|
||||
t.Error("expected open")
|
||||
}
|
||||
}
|
||||
@@ -168,8 +166,7 @@ func TestStreamVolume(t *testing.T) {
|
||||
a := asset.Spot
|
||||
p := currency.NewPair(currency.BTC, currency.USDT)
|
||||
d := DataFromKline{}
|
||||
bad := d.StreamVol()
|
||||
if len(bad) > 0 {
|
||||
if bad := d.StreamVol(); len(bad) > 0 {
|
||||
t.Error("expected no stream")
|
||||
}
|
||||
d.SetStream([]common.DataEventHandler{
|
||||
@@ -189,8 +186,7 @@ func TestStreamVolume(t *testing.T) {
|
||||
},
|
||||
})
|
||||
d.Next()
|
||||
open := d.StreamVol()
|
||||
if len(open) == 0 {
|
||||
if open := d.StreamVol(); len(open) == 0 {
|
||||
t.Error("expected volume")
|
||||
}
|
||||
}
|
||||
@@ -201,8 +197,7 @@ func TestStreamClose(t *testing.T) {
|
||||
a := asset.Spot
|
||||
p := currency.NewPair(currency.BTC, currency.USDT)
|
||||
d := DataFromKline{}
|
||||
bad := d.StreamClose()
|
||||
if len(bad) > 0 {
|
||||
if bad := d.StreamClose(); len(bad) > 0 {
|
||||
t.Error("expected no stream")
|
||||
}
|
||||
d.SetStream([]common.DataEventHandler{
|
||||
@@ -222,8 +217,7 @@ func TestStreamClose(t *testing.T) {
|
||||
},
|
||||
})
|
||||
d.Next()
|
||||
open := d.StreamClose()
|
||||
if len(open) == 0 {
|
||||
if open := d.StreamClose(); len(open) == 0 {
|
||||
t.Error("expected close")
|
||||
}
|
||||
}
|
||||
@@ -234,8 +228,7 @@ func TestStreamHigh(t *testing.T) {
|
||||
a := asset.Spot
|
||||
p := currency.NewPair(currency.BTC, currency.USDT)
|
||||
d := DataFromKline{}
|
||||
bad := d.StreamHigh()
|
||||
if len(bad) > 0 {
|
||||
if bad := d.StreamHigh(); len(bad) > 0 {
|
||||
t.Error("expected no stream")
|
||||
}
|
||||
d.SetStream([]common.DataEventHandler{
|
||||
@@ -255,8 +248,7 @@ func TestStreamHigh(t *testing.T) {
|
||||
},
|
||||
})
|
||||
d.Next()
|
||||
open := d.StreamHigh()
|
||||
if len(open) == 0 {
|
||||
if open := d.StreamHigh(); len(open) == 0 {
|
||||
t.Error("expected high")
|
||||
}
|
||||
}
|
||||
@@ -269,8 +261,7 @@ func TestStreamLow(t *testing.T) {
|
||||
d := DataFromKline{
|
||||
RangeHolder: &gctkline.IntervalRangeHolder{},
|
||||
}
|
||||
bad := d.StreamLow()
|
||||
if len(bad) > 0 {
|
||||
if bad := d.StreamLow(); len(bad) > 0 {
|
||||
t.Error("expected no stream")
|
||||
}
|
||||
d.SetStream([]common.DataEventHandler{
|
||||
@@ -290,8 +281,7 @@ func TestStreamLow(t *testing.T) {
|
||||
},
|
||||
})
|
||||
d.Next()
|
||||
open := d.StreamLow()
|
||||
if len(open) == 0 {
|
||||
if open := d.StreamLow(); len(open) == 0 {
|
||||
t.Error("expected low")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,12 +229,11 @@ func (e *Exchange) placeOrder(ctx context.Context, price, amount decimal.Decimal
|
||||
return "", err
|
||||
}
|
||||
var orderID string
|
||||
p, _ := price.Float64()
|
||||
a, _ := amount.Float64()
|
||||
fee, _ := f.ExchangeFee.Float64()
|
||||
p := price.InexactFloat64()
|
||||
fee := f.ExchangeFee.InexactFloat64()
|
||||
o := &gctorder.Submit{
|
||||
Price: p,
|
||||
Amount: a,
|
||||
Amount: amount.InexactFloat64(),
|
||||
Fee: fee,
|
||||
Exchange: f.Exchange,
|
||||
ID: u.String(),
|
||||
@@ -255,11 +254,10 @@ func (e *Exchange) placeOrder(ctx context.Context, price, amount decimal.Decimal
|
||||
return orderID, err
|
||||
}
|
||||
} else {
|
||||
rate, _ := f.Amount.Float64()
|
||||
submitResponse := gctorder.SubmitResponse{
|
||||
IsOrderPlaced: true,
|
||||
OrderID: u.String(),
|
||||
Rate: rate,
|
||||
Rate: f.Amount.InexactFloat64(),
|
||||
Fee: fee,
|
||||
Cost: p,
|
||||
FullyMatched: true,
|
||||
|
||||
@@ -32,11 +32,9 @@ func EstimateSlippagePercentage(maximumSlippageRate, minimumSlippageRate decimal
|
||||
// CalculateSlippageByOrderbook will analyse a provided orderbook and return the result of attempting to
|
||||
// place the order on there
|
||||
func CalculateSlippageByOrderbook(ob *orderbook.Base, side gctorder.Side, amountOfFunds, feeRate decimal.Decimal) (price, amount decimal.Decimal) {
|
||||
funds, _ := amountOfFunds.Float64()
|
||||
fee, _ := feeRate.Float64()
|
||||
result := ob.SimulateOrder(funds, side == gctorder.Buy)
|
||||
result := ob.SimulateOrder(amountOfFunds.InexactFloat64(), side == gctorder.Buy)
|
||||
rate := (result.MinimumPrice - result.MaximumPrice) / result.MaximumPrice
|
||||
price = decimal.NewFromFloat(result.MinimumPrice * (rate + 1))
|
||||
amount = decimal.NewFromFloat(result.Amount * (1 - fee))
|
||||
amount = decimal.NewFromFloat(result.Amount * (1 - feeRate.InexactFloat64()))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -55,10 +55,10 @@ func (c *CurrencyPairStatistic) CalculateResults(riskFreeRate decimal.Decimal) e
|
||||
returnsPerCandle := make([]decimal.Decimal, len(c.Events))
|
||||
benchmarkRates := make([]decimal.Decimal, len(c.Events))
|
||||
|
||||
var allDataEvents []common.DataEventHandler
|
||||
allDataEvents := make([]common.DataEventHandler, len(c.Events))
|
||||
for i := range c.Events {
|
||||
returnsPerCandle[i] = c.Events[i].Holdings.ChangeInTotalValuePercent
|
||||
allDataEvents = append(allDataEvents, c.Events[i].DataEvent)
|
||||
allDataEvents[i] = c.Events[i].DataEvent
|
||||
if i == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ func (s *Strategy) SetDefaults() {
|
||||
// the decision to handle missing data occurs at the strategy level, not all strategies
|
||||
// may wish to modify data
|
||||
func (s *Strategy) massageMissingData(data []decimal.Decimal, t time.Time) ([]float64, error) {
|
||||
var resp []float64
|
||||
resp := make([]float64, len(data))
|
||||
var missingDataStreak int64
|
||||
for i := range data {
|
||||
if data[i].IsZero() && i > int(s.rsiPeriod.IntPart()) {
|
||||
@@ -174,8 +174,7 @@ func (s *Strategy) massageMissingData(data []decimal.Decimal, t time.Time) ([]fl
|
||||
t.Format(gctcommon.SimpleTimeFormat),
|
||||
base.ErrTooMuchBadData)
|
||||
}
|
||||
d, _ := data[i].Float64()
|
||||
resp = append(resp, d)
|
||||
resp[i] = data[i].InexactFloat64()
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
@@ -11,8 +11,7 @@ import (
|
||||
|
||||
func TestGetStrategies(t *testing.T) {
|
||||
t.Parallel()
|
||||
resp := GetStrategies()
|
||||
if len(resp) < 2 {
|
||||
if resp := GetStrategies(); len(resp) < 2 {
|
||||
t.Error("expected at least 2 strategies to be loaded")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ func (s *Strategy) OnSimultaneousSignals(d []data.Handler, f funding.IFundTransf
|
||||
if len(d) < 4 {
|
||||
return nil, errStrategyCurrencyRequirements
|
||||
}
|
||||
var mfiFundEvents []mfiFundEvent
|
||||
mfiFundEvents := make([]mfiFundEvent, 0, len(d))
|
||||
var resp []signal.Event
|
||||
for i := range d {
|
||||
if d == nil {
|
||||
@@ -233,7 +233,7 @@ func (s *Strategy) SetDefaults() {
|
||||
// the decision to handle missing data occurs at the strategy level, not all strategies
|
||||
// may wish to modify data
|
||||
func (s *Strategy) massageMissingData(data []decimal.Decimal, t time.Time) ([]float64, error) {
|
||||
var resp []float64
|
||||
resp := make([]float64, len(data))
|
||||
var missingDataStreak int64
|
||||
for i := range data {
|
||||
if data[i].IsZero() && i > int(s.mfiPeriod.IntPart()) {
|
||||
@@ -248,8 +248,7 @@ func (s *Strategy) massageMissingData(data []decimal.Decimal, t time.Time) ([]fl
|
||||
t.Format(gctcommon.SimpleTimeFormat),
|
||||
base.ErrTooMuchBadData)
|
||||
}
|
||||
d, _ := data[i].Float64()
|
||||
resp = append(resp, d)
|
||||
resp[i] = data[i].InexactFloat64()
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
@@ -65,8 +65,7 @@ func TestEvent_GetTime(t *testing.T) {
|
||||
func TestEvent_IsEvent(t *testing.T) {
|
||||
t.Parallel()
|
||||
e := &Base{}
|
||||
y := e.IsEvent()
|
||||
if !y {
|
||||
if y := e.IsEvent(); !y {
|
||||
t.Error("it is an event")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,7 +199,7 @@ func (f *FundManager) GenerateReport() *Report {
|
||||
UsingExchangeLevelFunding: f.usingExchangeLevelFunding,
|
||||
DisableUSDTracking: f.disableUSDTracking,
|
||||
}
|
||||
var items []ReportItem
|
||||
items := make([]ReportItem, len(f.items))
|
||||
for i := range f.items {
|
||||
item := ReportItem{
|
||||
Exchange: f.items[i].exchange,
|
||||
@@ -243,7 +243,7 @@ func (f *FundManager) GenerateReport() *Report {
|
||||
item.PairedWith = f.items[i].pairedWith.currency
|
||||
}
|
||||
|
||||
items = append(items, item)
|
||||
items[i] = item
|
||||
}
|
||||
report.Items = items
|
||||
return &report
|
||||
|
||||
@@ -46,9 +46,7 @@ func (d *Data) GenerateReport() error {
|
||||
d.HoldingsOverTimeChart = d.CreateHoldingsOverTimeChart()
|
||||
|
||||
tmpl := template.Must(
|
||||
template.ParseFiles(
|
||||
filepath.Join(d.TemplatePath),
|
||||
),
|
||||
template.ParseFiles(d.TemplatePath),
|
||||
)
|
||||
var nickName string
|
||||
if d.Config.Nickname != "" {
|
||||
@@ -89,31 +87,33 @@ func (d *Data) CreateUSDTotalsChart() []TotalsChart {
|
||||
if d.Statistics.FundingStatistics == nil || d.Statistics.FundingStatistics.Report.DisableUSDTracking {
|
||||
return nil
|
||||
}
|
||||
var response []TotalsChart
|
||||
var usdTotalChartPlot []ChartPlot
|
||||
|
||||
usdTotalChartPlot := make([]ChartPlot, len(d.Statistics.FundingStatistics.TotalUSDStatistics.HoldingValues))
|
||||
for i := range d.Statistics.FundingStatistics.TotalUSDStatistics.HoldingValues {
|
||||
usdTotalChartPlot = append(usdTotalChartPlot, ChartPlot{
|
||||
usdTotalChartPlot[i] = ChartPlot{
|
||||
Value: d.Statistics.FundingStatistics.TotalUSDStatistics.HoldingValues[i].Value.InexactFloat64(),
|
||||
UnixMilli: d.Statistics.FundingStatistics.TotalUSDStatistics.HoldingValues[i].Time.UTC().UnixMilli(),
|
||||
})
|
||||
}
|
||||
}
|
||||
response = append(response, TotalsChart{
|
||||
|
||||
response := make([]TotalsChart, len(d.Statistics.FundingStatistics.Items)+1)
|
||||
response[0] = TotalsChart{
|
||||
Name: "Total USD value",
|
||||
DataPoints: usdTotalChartPlot,
|
||||
})
|
||||
}
|
||||
|
||||
for i := range d.Statistics.FundingStatistics.Items {
|
||||
var plots []ChartPlot
|
||||
plots := make([]ChartPlot, len(d.Statistics.FundingStatistics.Items[i].ReportItem.Snapshots))
|
||||
for j := range d.Statistics.FundingStatistics.Items[i].ReportItem.Snapshots {
|
||||
plots = append(plots, ChartPlot{
|
||||
plots[j] = ChartPlot{
|
||||
Value: d.Statistics.FundingStatistics.Items[i].ReportItem.Snapshots[j].USDValue.InexactFloat64(),
|
||||
UnixMilli: d.Statistics.FundingStatistics.Items[i].ReportItem.Snapshots[j].Time.UTC().UnixMilli(),
|
||||
})
|
||||
}
|
||||
}
|
||||
response = append(response, TotalsChart{
|
||||
response[i+1] = TotalsChart{
|
||||
Name: fmt.Sprintf("%v %v %v USD value", d.Statistics.FundingStatistics.Items[i].ReportItem.Exchange, d.Statistics.FundingStatistics.Items[i].ReportItem.Asset, d.Statistics.FundingStatistics.Items[i].ReportItem.Currency),
|
||||
DataPoints: plots,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return response
|
||||
@@ -125,19 +125,19 @@ func (d *Data) CreateHoldingsOverTimeChart() []TotalsChart {
|
||||
if d.Statistics.FundingStatistics == nil {
|
||||
return nil
|
||||
}
|
||||
var response []TotalsChart
|
||||
response := make([]TotalsChart, len(d.Statistics.FundingStatistics.Items))
|
||||
for i := range d.Statistics.FundingStatistics.Items {
|
||||
var plots []ChartPlot
|
||||
plots := make([]ChartPlot, len(d.Statistics.FundingStatistics.Items[i].ReportItem.Snapshots))
|
||||
for j := range d.Statistics.FundingStatistics.Items[i].ReportItem.Snapshots {
|
||||
plots = append(plots, ChartPlot{
|
||||
plots[j] = ChartPlot{
|
||||
Value: d.Statistics.FundingStatistics.Items[i].ReportItem.Snapshots[j].Available.InexactFloat64(),
|
||||
UnixMilli: d.Statistics.FundingStatistics.Items[i].ReportItem.Snapshots[j].Time.UTC().UnixMilli(),
|
||||
})
|
||||
}
|
||||
}
|
||||
response = append(response, TotalsChart{
|
||||
response[i] = TotalsChart{
|
||||
Name: fmt.Sprintf("%v %v %v holdings", d.Statistics.FundingStatistics.Items[i].ReportItem.Exchange, d.Statistics.FundingStatistics.Items[i].ReportItem.Asset, d.Statistics.FundingStatistics.Items[i].ReportItem.Currency),
|
||||
DataPoints: plots,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return response
|
||||
@@ -177,7 +177,7 @@ func (d *Data) enhanceCandles() error {
|
||||
Asset: lookup.Asset,
|
||||
Pair: lookup.Pair,
|
||||
Interval: lookup.Interval,
|
||||
Watermark: fmt.Sprintf("%v - %v - %v", strings.Title(lookup.Exchange), lookup.Asset.String(), strings.ToUpper(lookup.Pair.String())),
|
||||
Watermark: fmt.Sprintf("%s - %s - %s", strings.Title(lookup.Exchange), lookup.Asset.String(), lookup.Pair.Upper()), // nolint // Title usage
|
||||
}
|
||||
|
||||
statsForCandles :=
|
||||
|
||||
@@ -40,7 +40,7 @@ func TestGenerateReport(t *testing.T) {
|
||||
d := Data{
|
||||
Config: &config.Config{},
|
||||
OutputPath: filepath.Join("..", "results"),
|
||||
TemplatePath: filepath.Join("tpl.gohtml"),
|
||||
TemplatePath: "tpl.gohtml",
|
||||
OriginalCandles: []*gctkline.Item{
|
||||
{
|
||||
Candles: []gctkline.Candle{
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/crypto"
|
||||
gctfile "github.com/thrasher-corp/gocryptotrader/common/file"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/log"
|
||||
@@ -304,9 +305,9 @@ func checkExistingExchanges(exchName string) bool {
|
||||
|
||||
// checkMissingExchanges checks if any supported exchanges are missing api checker functionality
|
||||
func checkMissingExchanges() []string {
|
||||
var tempArray []string
|
||||
tempArray := make([]string, len(usageData.Exchanges))
|
||||
for x := range usageData.Exchanges {
|
||||
tempArray = append(tempArray, usageData.Exchanges[x].Name)
|
||||
tempArray[x] = usageData.Exchanges[x].Name
|
||||
}
|
||||
supportedExchs := exchange.Exchanges
|
||||
for z := 0; z < len(supportedExchs); {
|
||||
@@ -322,7 +323,7 @@ func checkMissingExchanges() []string {
|
||||
// readFileData reads the file data from the given json file
|
||||
func readFileData(fileName string) (Config, error) {
|
||||
var c Config
|
||||
data, err := ioutil.ReadFile(fileName)
|
||||
data, err := os.ReadFile(fileName)
|
||||
if err != nil {
|
||||
return c, err
|
||||
}
|
||||
@@ -448,7 +449,7 @@ func checkUpdates(fileName string) error {
|
||||
unsup := checkMissingExchanges()
|
||||
log.Warnf(log.Global, "The following exchanges are not supported by apichecker: %v\n", unsup)
|
||||
log.Debugf(log.Global, "Saving the updates to the following file: %s\n", fileName)
|
||||
return ioutil.WriteFile(fileName, file, 0770)
|
||||
return os.WriteFile(fileName, file, gctfile.DefaultPermissionOctal)
|
||||
}
|
||||
|
||||
// checkChangeLog checks the exchanges which support changelog updates.json
|
||||
@@ -559,9 +560,9 @@ func addExch(exchName, checkType string, data interface{}, isUpdate bool) error
|
||||
return err
|
||||
}
|
||||
}
|
||||
return ioutil.WriteFile(jsonFile, file, 0770)
|
||||
return os.WriteFile(jsonFile, file, gctfile.DefaultPermissionOctal)
|
||||
}
|
||||
return ioutil.WriteFile(testJSONFile, file, 0770)
|
||||
return os.WriteFile(testJSONFile, file, gctfile.DefaultPermissionOctal)
|
||||
}
|
||||
|
||||
// fillData fills exchange data based on the given checkType
|
||||
@@ -749,7 +750,7 @@ func htmlScrapeHitBTC(htmlData *HTMLScrapingData) ([]string, error) {
|
||||
}
|
||||
defer temp.Body.Close()
|
||||
|
||||
a, err := ioutil.ReadAll(temp.Body)
|
||||
a, err := io.ReadAll(temp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -784,7 +785,7 @@ func htmlScrapeBTCMarkets(htmlData *HTMLScrapingData) ([]string, error) {
|
||||
return nil, err
|
||||
}
|
||||
defer temp.Body.Close()
|
||||
tempData, err := ioutil.ReadAll(temp.Body)
|
||||
tempData, err := io.ReadAll(temp.Body)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
@@ -862,7 +863,7 @@ func htmlScrapeANX(htmlData *HTMLScrapingData) ([]string, error) {
|
||||
}
|
||||
defer temp.Body.Close()
|
||||
|
||||
a, err := ioutil.ReadAll(temp.Body)
|
||||
a, err := io.ReadAll(temp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -901,7 +902,7 @@ func htmlScrapeExmo(htmlData *HTMLScrapingData) ([]string, error) {
|
||||
}
|
||||
|
||||
defer httpResp.Body.Close()
|
||||
a, err := ioutil.ReadAll(httpResp.Body)
|
||||
a, err := io.ReadAll(httpResp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1010,7 +1011,7 @@ func htmlScrapeBitstamp(htmlData *HTMLScrapingData) ([]string, error) {
|
||||
}
|
||||
defer temp.Body.Close()
|
||||
|
||||
a, err := ioutil.ReadAll(temp.Body)
|
||||
a, err := io.ReadAll(temp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1145,7 +1146,7 @@ func htmlScrapeLocalBitcoins(htmlData *HTMLScrapingData) ([]string, error) {
|
||||
}
|
||||
defer temp.Body.Close()
|
||||
|
||||
a, err := ioutil.ReadAll(temp.Body)
|
||||
a, err := io.ReadAll(temp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1284,7 +1285,7 @@ func updateFile(name string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ioutil.WriteFile(name, file, 0770)
|
||||
return os.WriteFile(name, file, gctfile.DefaultPermissionOctal)
|
||||
}
|
||||
|
||||
// SendGetReq sends get req
|
||||
@@ -1690,7 +1691,7 @@ func htmlScrapeBitfinex(htmlData *HTMLScrapingData) ([]string, error) {
|
||||
}
|
||||
defer temp.Body.Close()
|
||||
|
||||
a, err := ioutil.ReadAll(temp.Body)
|
||||
a, err := io.ReadAll(temp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1775,7 +1776,7 @@ func sendHTTPGetRequest(path string, headers map[string]string) (*http.Response,
|
||||
req, err := http.NewRequestWithContext(context.TODO(),
|
||||
http.MethodGet,
|
||||
path,
|
||||
nil)
|
||||
http.NoBody)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -2,12 +2,12 @@ package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
||||
gctfile "github.com/thrasher-corp/gocryptotrader/common/file"
|
||||
exchange "github.com/thrasher-corp/gocryptotrader/exchanges"
|
||||
"github.com/thrasher-corp/gocryptotrader/log"
|
||||
)
|
||||
@@ -86,7 +86,7 @@ func removeTestFileVars() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ioutil.WriteFile(testJSONFile, file, 0770)
|
||||
return os.WriteFile(testJSONFile, file, gctfile.DefaultPermissionOctal)
|
||||
}
|
||||
|
||||
func canTestTrello() bool {
|
||||
@@ -439,8 +439,7 @@ func TestUpdate(t *testing.T) {
|
||||
|
||||
func TestCheckMissingExchanges(t *testing.T) {
|
||||
t.Parallel()
|
||||
a := checkMissingExchanges()
|
||||
if len(a) > len(exchange.Exchanges) {
|
||||
if a := checkMissingExchanges(); len(a) > len(exchange.Exchanges) {
|
||||
t.Fatal("invalid response")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ package main
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common/file"
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
@@ -38,7 +38,7 @@ func main() {
|
||||
key = string(result)
|
||||
}
|
||||
|
||||
fileData, err := ioutil.ReadFile(inFile)
|
||||
fileData, err := os.ReadFile(inFile)
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to read input file %s. Error: %s.", inFile, err)
|
||||
}
|
||||
|
||||
@@ -30,8 +30,8 @@ func main() {
|
||||
wg.Wait()
|
||||
log.Println("Done.")
|
||||
|
||||
var cfgs []config.Exchange
|
||||
exchanges := engine.Bot.GetExchanges()
|
||||
cfgs := make([]config.Exchange, 0, len(exchanges))
|
||||
for x := range exchanges {
|
||||
var cfg *config.Exchange
|
||||
cfg, err = exchanges[x].GetDefaultConfig()
|
||||
|
||||
@@ -51,11 +51,11 @@ func seedExchangeFromDefaultList(c *cli.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var allExchanges []exchangeDB.Details
|
||||
allExchanges := make([]exchangeDB.Details, len(exchange.Exchanges))
|
||||
for x := range exchange.Exchanges {
|
||||
allExchanges = append(allExchanges, exchangeDB.Details{
|
||||
allExchanges[x] = exchangeDB.Details{
|
||||
Name: exchange.Exchanges[x],
|
||||
})
|
||||
}
|
||||
}
|
||||
err = exchangeDB.InsertMany(allExchanges)
|
||||
if err != nil {
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/core"
|
||||
@@ -44,7 +43,7 @@ func main() {
|
||||
workingDir, err = os.Getwd()
|
||||
if err != nil {
|
||||
log.Println("error getting current working path")
|
||||
workingDir = filepath.Join(".")
|
||||
workingDir = "."
|
||||
}
|
||||
|
||||
fmt.Println("GoCryptoTrader database seeding tool")
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
@@ -329,7 +328,7 @@ func GetConfiguration() (Config, error) {
|
||||
configFilePath := filepath.Join(toolDir, "config.json")
|
||||
|
||||
if file.Exists(configFilePath) {
|
||||
config, err := ioutil.ReadFile(configFilePath)
|
||||
config, err := os.ReadFile(configFilePath)
|
||||
if err != nil {
|
||||
return c, err
|
||||
}
|
||||
@@ -360,7 +359,7 @@ func GetConfiguration() (Config, error) {
|
||||
return c, err
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(configFilePath, data, 0770); err != nil {
|
||||
if err := os.WriteFile(configFilePath, data, file.DefaultPermissionOctal); err != nil {
|
||||
return c, err
|
||||
}
|
||||
|
||||
@@ -485,7 +484,7 @@ func GetPackageName(name string, capital bool) string {
|
||||
i = len(newStrings) - 1
|
||||
}
|
||||
if capital {
|
||||
return strings.Replace(strings.Title(newStrings[i]), "_", " ", -1)
|
||||
return strings.Replace(strings.Title(newStrings[i]), "_", " ", -1) // nolint // ignore staticcheck strings.Title warning
|
||||
}
|
||||
return newStrings[i]
|
||||
}
|
||||
@@ -540,7 +539,7 @@ func UpdateDocumentation(details DocumentationDetails) {
|
||||
continue
|
||||
}
|
||||
if name == engineFolder {
|
||||
d, err := ioutil.ReadDir(details.Directories[i])
|
||||
d, err := os.ReadDir(details.Directories[i])
|
||||
if err != nil {
|
||||
fmt.Println("Excluding file:", err)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
"github.com/thrasher-corp/gocryptotrader/common/file"
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/core"
|
||||
"github.com/thrasher-corp/gocryptotrader/currency"
|
||||
@@ -138,14 +139,14 @@ func makeExchange(exchangeDirectory string, configTestFile *config.Config, exch
|
||||
if !os.IsNotExist(err) {
|
||||
return nil, errors.New("directory already exists")
|
||||
}
|
||||
err = os.MkdirAll(exchangeDirectory, 0770)
|
||||
err = os.MkdirAll(exchangeDirectory, file.DefaultPermissionOctal)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fmt.Printf("Output directory: %s\n", exchangeDirectory)
|
||||
|
||||
exch.CapitalName = strings.Title(exch.Name)
|
||||
exch.CapitalName = strings.Title(exch.Name) // nolint:staticcheck // Ignore Title usage warning
|
||||
exch.Variable = exch.Name[0:2]
|
||||
newExchConfig := &config.Exchange{}
|
||||
newExchConfig.Name = exch.CapitalName
|
||||
@@ -214,7 +215,7 @@ func makeExchange(exchangeDirectory string, configTestFile *config.Config, exch
|
||||
outputFile := filepath.Join(exchangeDirectory, filename)
|
||||
newFile(outputFile)
|
||||
var f *os.File
|
||||
f, err = os.OpenFile(outputFile, os.O_WRONLY, 0770)
|
||||
f, err = os.OpenFile(outputFile, os.O_WRONLY, file.DefaultPermissionOctal)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -334,18 +334,20 @@ func ({{.Variable}} *{{.CapitalName}}) UpdateOrderbook(ctx context.Context, pair
|
||||
return book, err
|
||||
}
|
||||
|
||||
book.Bids = make([]orderbook.Item, len(orderbookNew.Bids))
|
||||
for x := range orderbookNew.Bids {
|
||||
book.Bids = append(book.Bids, orderbook.Item{
|
||||
book.Bids[x] = orderbook.Item{
|
||||
Amount: orderbookNew.Bids[x].Quantity,
|
||||
Price: orderbookNew.Bids[x].Price,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
book.Asks = make([]orderbook.Item, len(orderbookNew.Asks))
|
||||
for x := range orderbookNew.Asks {
|
||||
book.Asks = append(book.Asks, orderbook.Item{
|
||||
book.Asks[x] = orderbook.Item{
|
||||
Amount: orderBookNew.Asks[x].Quantity,
|
||||
Price: orderBookNew.Asks[x].Price,
|
||||
})
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -283,7 +282,7 @@ func parseOrderType(orderType string) order.Type {
|
||||
}
|
||||
|
||||
func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config) []ExchangeAssetPairResponses {
|
||||
var response []ExchangeAssetPairResponses
|
||||
response := make([]ExchangeAssetPairResponses, 0)
|
||||
testOrderSide := parseOrderSide(config.OrderSubmission.OrderSide)
|
||||
testOrderType := parseOrderType(config.OrderSubmission.OrderType)
|
||||
assetTypes := base.GetAssetTypes(false)
|
||||
@@ -835,13 +834,13 @@ func testWrappers(e exchange.IBotExchange, base *exchange.Base, config *Config)
|
||||
}
|
||||
|
||||
func jsonifyInterface(params []interface{}) json.RawMessage {
|
||||
response, _ := json.MarshalIndent(params, "", " ")
|
||||
response, _ := json.MarshalIndent(params, "", " ") // nolint:errchkjson // TODO: ignore this for now
|
||||
return response
|
||||
}
|
||||
|
||||
func loadConfig() (Config, error) {
|
||||
var config Config
|
||||
keys, err := ioutil.ReadFile("wrapperconfig.json")
|
||||
keys, err := os.ReadFile("wrapperconfig.json")
|
||||
if err != nil {
|
||||
return config, err
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package main
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"math"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -4226,7 +4226,7 @@ func gctScriptUpload(c *cli.Context) error {
|
||||
defer closeConn(conn, cancel)
|
||||
client := gctrpc.NewGoCryptoTraderClient(conn)
|
||||
|
||||
data, err := ioutil.ReadAll(file)
|
||||
data, err := io.ReadAll(file)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -198,7 +198,7 @@ func enableDisableExchangePair(c *cli.Context) error {
|
||||
|
||||
pairList := strings.Split(pairs, ",")
|
||||
|
||||
var validPairs []*gctrpc.CurrencyPair
|
||||
validPairs := make([]*gctrpc.CurrencyPair, len(pairList))
|
||||
for i := range pairList {
|
||||
if !validPair(pairList[i]) {
|
||||
return errInvalidPair
|
||||
@@ -209,11 +209,11 @@ func enableDisableExchangePair(c *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
validPairs = append(validPairs, &gctrpc.CurrencyPair{
|
||||
validPairs[i] = &gctrpc.CurrencyPair{
|
||||
Delimiter: p.Delimiter,
|
||||
Base: p.Base.String(),
|
||||
Quote: p.Quote.String(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
conn, cancel, err := setupClient(c)
|
||||
|
||||
@@ -4,10 +4,10 @@ import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common/file"
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/core"
|
||||
"github.com/thrasher-corp/gocryptotrader/database"
|
||||
@@ -57,7 +57,7 @@ func main() {
|
||||
}
|
||||
|
||||
path := filepath.Join(outputFolder, "sqlboiler.json")
|
||||
err = ioutil.WriteFile(path, jsonOutput, 0770)
|
||||
err = os.WriteFile(path, jsonOutput, file.DefaultPermissionOctal)
|
||||
if err != nil {
|
||||
fmt.Printf("Write failed: %v", err)
|
||||
os.Exit(1)
|
||||
|
||||
25
common/cache/cache_test.go
vendored
25
common/cache/cache_test.go
vendored
@@ -2,6 +2,8 @@ package cache
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common/convert"
|
||||
)
|
||||
|
||||
func TestCache(t *testing.T) {
|
||||
@@ -16,12 +18,11 @@ func TestCache(t *testing.T) {
|
||||
if v == nil {
|
||||
t.Fatal("expected cache to contain \"hello\" key")
|
||||
}
|
||||
if v.(string) != "world" {
|
||||
if convert.InterfaceToStringOrZeroValue(v) != "world" {
|
||||
t.Fatal("expected \"hello\" key to contain value \"world\"")
|
||||
}
|
||||
|
||||
r := lruCache.Remove("hello")
|
||||
if !r {
|
||||
if r := lruCache.Remove("hello"); !r {
|
||||
t.Fatal("expected \"hello\" key to be removed from cache")
|
||||
}
|
||||
|
||||
@@ -77,39 +78,39 @@ func TestAdd(t *testing.T) {
|
||||
if v == nil {
|
||||
t.Fatal("expected cache to contain \"2\" key")
|
||||
}
|
||||
if v.(int) != 2 {
|
||||
if convert.InterfaceToIntOrZeroValue(v) != 2 {
|
||||
t.Fatal("expected \"2\" key to contain value \"2\"")
|
||||
}
|
||||
k, v := lruCache.getNewest()
|
||||
if k.(int) != 2 {
|
||||
if convert.InterfaceToIntOrZeroValue(k) != 2 {
|
||||
t.Fatal("expected latest key to be 2")
|
||||
}
|
||||
if v.(int) != 2 {
|
||||
if convert.InterfaceToIntOrZeroValue(v) != 2 {
|
||||
t.Fatal("expected latest value to be 2")
|
||||
}
|
||||
lruCache.Add(3, 3)
|
||||
k, _ = lruCache.getNewest()
|
||||
if k.(int) != 3 {
|
||||
if convert.InterfaceToIntOrZeroValue(k) != 3 {
|
||||
t.Fatal("expected latest key to be 3")
|
||||
}
|
||||
k, _ = lruCache.getOldest()
|
||||
if k.(int) != 2 {
|
||||
if convert.InterfaceToIntOrZeroValue(k) != 2 {
|
||||
t.Fatal("expected oldest key to be 2")
|
||||
}
|
||||
k, v = lruCache.getOldest()
|
||||
if k.(int) != 2 {
|
||||
if convert.InterfaceToIntOrZeroValue(k) != 2 {
|
||||
t.Fatal("expected oldest key to be 2")
|
||||
}
|
||||
if v.(int) != 2 {
|
||||
if convert.InterfaceToIntOrZeroValue(v) != 2 {
|
||||
t.Fatal("expected latest value to be 2")
|
||||
}
|
||||
lruCache.Add(2, 2)
|
||||
k, _ = lruCache.getNewest()
|
||||
if k.(int) != 2 {
|
||||
if convert.InterfaceToIntOrZeroValue(k) != 2 {
|
||||
t.Fatal("expected latest key to be 2")
|
||||
}
|
||||
k, _ = lruCache.getOldest()
|
||||
if k.(int) != 3 {
|
||||
if convert.InterfaceToIntOrZeroValue(k) != 3 {
|
||||
t.Fatal("expected oldest key to be 3")
|
||||
}
|
||||
}
|
||||
|
||||
20
common/cache/lru.go
vendored
20
common/cache/lru.go
vendored
@@ -24,7 +24,9 @@ func NewLRUCache(capacity uint64) *LRU {
|
||||
func (l *LRU) Add(key, value interface{}) {
|
||||
if f, o := l.items[key]; o {
|
||||
l.l.MoveToFront(f)
|
||||
f.Value.(*item).value = value
|
||||
if v, ok := f.Value.(*item); ok {
|
||||
v.value = value
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -40,7 +42,9 @@ func (l *LRU) Add(key, value interface{}) {
|
||||
func (l *LRU) Get(key interface{}) interface{} {
|
||||
if i, f := l.items[key]; f {
|
||||
l.l.MoveToFront(i)
|
||||
return i.Value.(*item).value
|
||||
if v, ok := i.Value.(*item); ok {
|
||||
return v.value
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -48,7 +52,9 @@ func (l *LRU) Get(key interface{}) interface{} {
|
||||
// GetOldest returns the oldest entry
|
||||
func (l *LRU) getOldest() (key, value interface{}) {
|
||||
if x := l.l.Back(); x != nil {
|
||||
return x.Value.(*item).key, x.Value.(*item).value
|
||||
if v, ok := x.Value.(*item); ok {
|
||||
return v.key, v.value
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -56,7 +62,9 @@ func (l *LRU) getOldest() (key, value interface{}) {
|
||||
// GetNewest returns the newest entry
|
||||
func (l *LRU) getNewest() (key, value interface{}) {
|
||||
if x := l.l.Front(); x != nil {
|
||||
return x.Value.(*item).key, x.Value.(*item).value
|
||||
if v, ok := x.Value.(*item); ok {
|
||||
return v.key, v.value
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -99,5 +107,7 @@ func (l *LRU) removeOldestEntry() {
|
||||
// removeElement element from the cache
|
||||
func (l *LRU) removeElement(e *list.Element) {
|
||||
l.l.Remove(e)
|
||||
delete(l.items, e.Value.(*item).key)
|
||||
if v, ok := e.Value.(*item); ok {
|
||||
delete(l.items, v.key)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
@@ -18,6 +17,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common/file"
|
||||
"github.com/thrasher-corp/gocryptotrader/log"
|
||||
)
|
||||
|
||||
@@ -257,7 +257,7 @@ func SendHTTPRequest(ctx context.Context, method, urlPath string, headers map[st
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
contents, err := ioutil.ReadAll(resp.Body)
|
||||
contents, err := io.ReadAll(resp.Body)
|
||||
|
||||
if verbose {
|
||||
log.Debugf(log.Global, "HTTP status: %s, Code: %v",
|
||||
@@ -348,7 +348,7 @@ func CreateDir(dir string) error {
|
||||
}
|
||||
|
||||
log.Warnf(log.Global, "Directory %s does not exist.. creating.\n", dir)
|
||||
return os.MkdirAll(dir, 0770)
|
||||
return os.MkdirAll(dir, file.DefaultPermissionOctal)
|
||||
}
|
||||
|
||||
// ChangePermission lists all the directories and files in an array
|
||||
@@ -357,8 +357,8 @@ func ChangePermission(directory string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if info.Mode().Perm() != 0770 {
|
||||
return os.Chmod(path, 0770)
|
||||
if info.Mode().Perm() != file.DefaultPermissionOctal {
|
||||
return os.Chmod(path, file.DefaultPermissionOctal)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
@@ -14,6 +14,8 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common/file"
|
||||
)
|
||||
|
||||
func TestSendHTTPRequest(t *testing.T) {
|
||||
@@ -509,7 +511,7 @@ func TestChangePermission(t *testing.T) {
|
||||
if err == nil {
|
||||
t.Fatal("expected an error on non-existent path")
|
||||
}
|
||||
err = os.Mkdir(testDir, 0777)
|
||||
err = os.Mkdir(testDir, 0o777)
|
||||
if err != nil {
|
||||
t.Fatalf("Mkdir failed. Err: %v", err)
|
||||
}
|
||||
@@ -530,7 +532,7 @@ func TestChangePermission(t *testing.T) {
|
||||
if err == nil {
|
||||
t.Fatal("expected an error on non-existent path")
|
||||
}
|
||||
err = os.Mkdir(testDir, 0777)
|
||||
err = os.Mkdir(testDir, 0o777)
|
||||
if err != nil {
|
||||
t.Fatalf("Mkdir failed. Err: %v", err)
|
||||
}
|
||||
@@ -543,8 +545,8 @@ func TestChangePermission(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("os.Stat failed. Err: %v", err)
|
||||
}
|
||||
if a.Mode().Perm() != 0770 {
|
||||
t.Fatalf("expected file permissions differ. expecting 0770 got %#o", a.Mode().Perm())
|
||||
if a.Mode().Perm() != file.DefaultPermissionOctal {
|
||||
t.Fatalf("expected file permissions differ. expecting file.DefaultPermissionOctal got %#o", a.Mode().Perm())
|
||||
}
|
||||
err = os.Remove(testDir)
|
||||
if err != nil {
|
||||
|
||||
@@ -119,8 +119,7 @@ func DecimalToHumanFriendlyString(number decimal.Decimal, rounding int, decPoint
|
||||
neg = true
|
||||
}
|
||||
str := number.String()
|
||||
rnd := strings.Split(str, ".")
|
||||
if len(rnd) == 1 {
|
||||
if rnd := strings.Split(str, "."); len(rnd) == 1 {
|
||||
rounding = 0
|
||||
} else if len(rnd[1]) < rounding {
|
||||
rounding = len(rnd[1])
|
||||
@@ -164,3 +163,27 @@ func numberToHumanFriendlyString(str string, dec int, decPoint, thousandsSep str
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
// InterfaceToFloat64OrZeroValue returns the type assertion value or variable zero value
|
||||
func InterfaceToFloat64OrZeroValue(r interface{}) float64 {
|
||||
if v, ok := r.(float64); ok {
|
||||
return v
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// InterfaceToIntOrZeroValue returns the type assertion value or variable zero value
|
||||
func InterfaceToIntOrZeroValue(r interface{}) int {
|
||||
if v, ok := r.(int); ok {
|
||||
return v
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// InterfaceToStringOrZeroValue returns the type assertion value or variable zero value
|
||||
func InterfaceToStringOrZeroValue(r interface{}) string {
|
||||
if v, ok := r.(string); ok {
|
||||
return v
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -282,3 +282,36 @@ func TestNumberToHumanFriendlyString(t *testing.T) {
|
||||
t.Error("expected no comma")
|
||||
}
|
||||
}
|
||||
|
||||
func TestInterfaceToFloat64OrZeroValue(t *testing.T) {
|
||||
var x interface{}
|
||||
if r := InterfaceToFloat64OrZeroValue(x); r != 0 {
|
||||
t.Errorf("expected 0, got: %v", r)
|
||||
}
|
||||
x = float64(420)
|
||||
if r := InterfaceToFloat64OrZeroValue(x); r != 420 {
|
||||
t.Errorf("expected 420, got: %v", x)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInterfaceToIntOrZeroValue(t *testing.T) {
|
||||
var x interface{}
|
||||
if r := InterfaceToIntOrZeroValue(x); r != 0 {
|
||||
t.Errorf("expected 0, got: %v", r)
|
||||
}
|
||||
x = int(420)
|
||||
if r := InterfaceToIntOrZeroValue(x); r != 420 {
|
||||
t.Errorf("expected 420, got: %v", x)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInterfaceToStringOrZeroValue(t *testing.T) {
|
||||
var x interface{}
|
||||
if r := InterfaceToStringOrZeroValue(x); r != "" {
|
||||
t.Errorf("expected empty string, got: %v", r)
|
||||
}
|
||||
x = string("meow")
|
||||
if r := InterfaceToStringOrZeroValue(x); r != "meow" {
|
||||
t.Errorf("expected meow, got: %v", x)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ func TestGetHMAC(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if string(sha1) != string(expectedSha1) {
|
||||
if !bytes.Equal(sha1, expectedSha1) {
|
||||
t.Errorf("Common GetHMAC error: Expected '%x'. Actual '%x'",
|
||||
expectedSha1, sha1,
|
||||
)
|
||||
@@ -157,7 +157,7 @@ func TestGetHMAC(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if string(sha256) != string(expectedsha256) {
|
||||
if !bytes.Equal(sha256, expectedsha256) {
|
||||
t.Errorf("Common GetHMAC error: Expected '%x'. Actual '%x'",
|
||||
expectedsha256, sha256,
|
||||
)
|
||||
@@ -166,7 +166,7 @@ func TestGetHMAC(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if string(sha512) != string(expectedsha512) {
|
||||
if !bytes.Equal(sha512, expectedsha512) {
|
||||
t.Errorf("Common GetHMAC error: Expected '%x'. Actual '%x'",
|
||||
expectedsha512, sha512,
|
||||
)
|
||||
@@ -175,7 +175,7 @@ func TestGetHMAC(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if string(sha512384) != string(expectedsha512384) {
|
||||
if !bytes.Equal(sha512384, expectedsha512384) {
|
||||
t.Errorf("Common GetHMAC error: Expected '%x'. Actual '%x'",
|
||||
expectedsha512384, sha512384,
|
||||
)
|
||||
@@ -184,7 +184,7 @@ func TestGetHMAC(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if string(md5) != string(expectedmd5) {
|
||||
if !bytes.Equal(md5, expectedmd5) {
|
||||
t.Errorf("Common GetHMAC error: Expected '%x'. Actual '%x'",
|
||||
expectedmd5, md5,
|
||||
)
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common/file"
|
||||
"github.com/thrasher-corp/gocryptotrader/log"
|
||||
)
|
||||
|
||||
@@ -52,7 +53,7 @@ func UnZip(src, dest string) (fileList []string, err error) {
|
||||
continue
|
||||
}
|
||||
|
||||
err = os.MkdirAll(filepath.Dir(fPath), 0770)
|
||||
err = os.MkdirAll(filepath.Dir(fPath), file.DefaultPermissionOctal)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -6,22 +6,25 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// DefaultPermissionOctal is the default file and folder permission octal used throughout GCT
|
||||
const DefaultPermissionOctal fs.FileMode = 0o770
|
||||
|
||||
// Write writes selected data to a file or returns an error if it fails. This
|
||||
// func also ensures that all files are set to this permission (only rw access
|
||||
// for the running user and the group the user is a member of)
|
||||
func Write(file string, data []byte) error {
|
||||
basePath := filepath.Dir(file)
|
||||
if !Exists(basePath) {
|
||||
if err := os.MkdirAll(basePath, 0770); err != nil {
|
||||
if err := os.MkdirAll(basePath, DefaultPermissionOctal); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return ioutil.WriteFile(file, data, 0770)
|
||||
return os.WriteFile(file, data, DefaultPermissionOctal)
|
||||
}
|
||||
|
||||
// Writer creates a writer to a file or returns an error if it fails. This
|
||||
@@ -30,11 +33,11 @@ func Write(file string, data []byte) error {
|
||||
func Writer(file string) (*os.File, error) {
|
||||
basePath := filepath.Dir(file)
|
||||
if !Exists(basePath) {
|
||||
if err := os.MkdirAll(basePath, 0770); err != nil {
|
||||
if err := os.MkdirAll(basePath, DefaultPermissionOctal); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return os.OpenFile(file, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0770)
|
||||
return os.OpenFile(file, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, DefaultPermissionOctal)
|
||||
}
|
||||
|
||||
// Move moves a file from a source path to a destination path
|
||||
@@ -59,7 +62,7 @@ func Move(sourcePath, destPath string) error {
|
||||
|
||||
destDir := filepath.Dir(destPath)
|
||||
if !Exists(destDir) {
|
||||
err = os.MkdirAll(destDir, 0770)
|
||||
err = os.MkdirAll(destDir, DefaultPermissionOctal)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ func TestWrite(t *testing.T) {
|
||||
func TestMove(t *testing.T) {
|
||||
tester := func(in, out string, write bool) error {
|
||||
if write {
|
||||
if err := ioutil.WriteFile(in, []byte("GoCryptoTrader"), 0770); err != nil {
|
||||
if err := os.WriteFile(in, []byte("GoCryptoTrader"), DefaultPermissionOctal); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -65,7 +65,7 @@ func TestMove(t *testing.T) {
|
||||
return err
|
||||
}
|
||||
|
||||
contents, err := ioutil.ReadFile(out)
|
||||
contents, err := os.ReadFile(out)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -124,7 +124,7 @@ func TestExists(t *testing.T) {
|
||||
t.Error("non-existent file should not exist")
|
||||
}
|
||||
tmpFile := filepath.Join(os.TempDir(), "gct-test.txt")
|
||||
if err := ioutil.WriteFile(tmpFile, []byte("hello world"), os.ModeAppend); err != nil {
|
||||
if err := os.WriteFile(tmpFile, []byte("hello world"), os.ModeAppend); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if e := Exists(tmpFile); !e {
|
||||
@@ -258,7 +258,7 @@ func TestWriter(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if data, err := ioutil.ReadFile(got.Name()); err != nil || string(data) != testData {
|
||||
if data, err := os.ReadFile(got.Name()); err != nil || string(data) != testData {
|
||||
t.Errorf("Could not write the file, or contents were wrong: expected = %s, got =%s", testData, string(data))
|
||||
}
|
||||
})
|
||||
@@ -274,7 +274,7 @@ func TestWriterNoPermissionFails(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(temp)
|
||||
err = os.Chmod(temp, 0555)
|
||||
err = os.Chmod(temp, 0o555)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -89,9 +89,9 @@ func InformationRatio(returnsRates, benchmarkRates []float64, averageValues, ave
|
||||
if len(benchmarkRates) != len(returnsRates) {
|
||||
return 0, errInformationBadLength
|
||||
}
|
||||
var diffs []float64
|
||||
diffs := make([]float64, len(returnsRates))
|
||||
for i := range returnsRates {
|
||||
diffs = append(diffs, returnsRates[i]-benchmarkRates[i])
|
||||
diffs[i] = returnsRates[i] - benchmarkRates[i]
|
||||
}
|
||||
stdDev, err := PopulationStandardDeviation(diffs)
|
||||
if err != nil {
|
||||
@@ -135,11 +135,11 @@ func SampleStandardDeviation(values []float64) (float64, error) {
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
var superMean []float64
|
||||
superMean := make([]float64, len(values))
|
||||
var combined float64
|
||||
for i := range values {
|
||||
result := math.Pow(values[i]-mean, 2)
|
||||
superMean = append(superMean, result)
|
||||
superMean[i] = result
|
||||
combined += result
|
||||
}
|
||||
avg := combined / (float64(len(superMean)) - 1)
|
||||
@@ -232,9 +232,9 @@ func SharpeRatio(movementPerCandle []float64, riskFreeRatePerInterval, average f
|
||||
if totalIntervals == 0 {
|
||||
return 0, errZeroValue
|
||||
}
|
||||
var excessReturns []float64
|
||||
excessReturns := make([]float64, len(movementPerCandle))
|
||||
for i := range movementPerCandle {
|
||||
excessReturns = append(excessReturns, movementPerCandle[i]-riskFreeRatePerInterval)
|
||||
excessReturns[i] = movementPerCandle[i] - riskFreeRatePerInterval
|
||||
}
|
||||
standardDeviation, err := PopulationStandardDeviation(excessReturns)
|
||||
if err != nil {
|
||||
@@ -284,9 +284,9 @@ func DecimalInformationRatio(returnsRates, benchmarkRates []decimal.Decimal, ave
|
||||
if len(benchmarkRates) != len(returnsRates) {
|
||||
return decimal.Zero, errInformationBadLength
|
||||
}
|
||||
var diffs []decimal.Decimal
|
||||
diffs := make([]decimal.Decimal, len(returnsRates))
|
||||
for i := range returnsRates {
|
||||
diffs = append(diffs, returnsRates[i].Sub(benchmarkRates[i]))
|
||||
diffs[i] = returnsRates[i].Sub(benchmarkRates[i])
|
||||
}
|
||||
stdDev, err := DecimalPopulationStandardDeviation(diffs)
|
||||
if err != nil && !errors.Is(err, ErrInexactConversion) {
|
||||
@@ -339,11 +339,11 @@ func DecimalSampleStandardDeviation(values []decimal.Decimal) (decimal.Decimal,
|
||||
if err != nil {
|
||||
return decimal.Zero, err
|
||||
}
|
||||
var superMean []decimal.Decimal
|
||||
superMean := make([]decimal.Decimal, len(values))
|
||||
var combined decimal.Decimal
|
||||
for i := range values {
|
||||
pow := values[i].Sub(mean).Pow(decimal.NewFromInt(2))
|
||||
superMean = append(superMean, pow)
|
||||
superMean[i] = pow
|
||||
combined.Add(pow)
|
||||
}
|
||||
avg := combined.Div(decimal.NewFromInt(int64(len(superMean))).Sub(decimal.NewFromInt(1)))
|
||||
@@ -380,9 +380,7 @@ func DecimalGeometricMean(values []decimal.Decimal) (decimal.Decimal, error) {
|
||||
// DecimalPow is lovely because shopspring decimal cannot
|
||||
// handle ^0.x and instead returns 1
|
||||
func DecimalPow(x, y decimal.Decimal) decimal.Decimal {
|
||||
fX, _ := x.Float64()
|
||||
fY, _ := y.Float64()
|
||||
pow := math.Pow(fX, fY)
|
||||
pow := math.Pow(x.InexactFloat64(), y.InexactFloat64())
|
||||
return decimal.NewFromFloat(pow)
|
||||
}
|
||||
|
||||
@@ -405,7 +403,7 @@ func DecimalFinancialGeometricMean(values []decimal.Decimal) (decimal.Decimal, e
|
||||
// as we cannot have negative or zero value geometric numbers
|
||||
// adding a 1 to the percentage movements allows for differentiation between
|
||||
// negative numbers (eg -0.1 translates to 0.9) and positive numbers (eg 0.1 becomes 1.1)
|
||||
modVal, _ := values[i].Add(decimal.NewFromInt(1)).Float64()
|
||||
modVal := values[i].Add(decimal.NewFromInt(1)).InexactFloat64()
|
||||
product *= modVal
|
||||
}
|
||||
prod := 1 / float64(len(values))
|
||||
@@ -461,9 +459,9 @@ func DecimalSharpeRatio(movementPerCandle []decimal.Decimal, riskFreeRatePerInte
|
||||
if totalIntervals.IsZero() {
|
||||
return decimal.Zero, errZeroValue
|
||||
}
|
||||
var excessReturns []decimal.Decimal
|
||||
excessReturns := make([]decimal.Decimal, len(movementPerCandle))
|
||||
for i := range movementPerCandle {
|
||||
excessReturns = append(excessReturns, movementPerCandle[i].Sub(riskFreeRatePerInterval))
|
||||
excessReturns[i] = movementPerCandle[i].Sub(riskFreeRatePerInterval)
|
||||
}
|
||||
standardDeviation, err := DecimalPopulationStandardDeviation(excessReturns)
|
||||
if err != nil && !errors.Is(err, ErrInexactConversion) {
|
||||
|
||||
@@ -184,9 +184,9 @@ func TestInformationRatio(t *testing.T) {
|
||||
t.Error(avgComparison)
|
||||
}
|
||||
|
||||
var eachDiff []float64
|
||||
eachDiff := make([]float64, len(figures))
|
||||
for i := range figures {
|
||||
eachDiff = append(eachDiff, figures[i]-comparisonFigures[i])
|
||||
eachDiff[i] = figures[i] - comparisonFigures[i]
|
||||
}
|
||||
stdDev, err := PopulationStandardDeviation(eachDiff)
|
||||
if err != nil {
|
||||
@@ -583,9 +583,9 @@ func TestDecimalInformationRatio(t *testing.T) {
|
||||
t.Error(avgComparison)
|
||||
}
|
||||
|
||||
var eachDiff []decimal.Decimal
|
||||
eachDiff := make([]decimal.Decimal, len(figures))
|
||||
for i := range figures {
|
||||
eachDiff = append(eachDiff, figures[i].Sub(comparisonFigures[i]))
|
||||
eachDiff[i] = figures[i].Sub(comparisonFigures[i])
|
||||
}
|
||||
stdDev, err := DecimalPopulationStandardDeviation(eachDiff)
|
||||
if err != nil && !errors.Is(err, ErrInexactConversion) {
|
||||
@@ -703,14 +703,13 @@ func TestDecimalStandardDeviation2(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
var superMean []decimal.Decimal
|
||||
superMean := make([]decimal.Decimal, len(r))
|
||||
for i := range r {
|
||||
result := r[i].Sub(mean).Pow(decimal.NewFromInt(2))
|
||||
superMean = append(superMean, result)
|
||||
superMean[i] = result
|
||||
}
|
||||
superMeany := superMean[0].Add(superMean[1].Add(superMean[2].Add(superMean[3].Add(superMean[4].Add(superMean[5]))))).Div(decimal.NewFromInt(5))
|
||||
fSuperMeany, _ := superMeany.Float64()
|
||||
manualCalculation := decimal.NewFromFloat(math.Sqrt(fSuperMeany))
|
||||
manualCalculation := decimal.NewFromFloat(math.Sqrt(superMeany.InexactFloat64()))
|
||||
var codeCalcu decimal.Decimal
|
||||
codeCalcu, err = DecimalSampleStandardDeviation(r)
|
||||
if err != nil {
|
||||
|
||||
@@ -108,8 +108,11 @@ func TestSetup(t *testing.T) {
|
||||
|
||||
for idx, provider := range ic {
|
||||
exp := testConfigs[idx].shouldConnectCalled
|
||||
act := provider.(*CommunicationProvider).ConnectCalled
|
||||
if exp != act {
|
||||
act, ok := provider.(*CommunicationProvider)
|
||||
if !ok {
|
||||
t.Fatal("unable to type assert provider")
|
||||
}
|
||||
if exp != act.ConnectCalled {
|
||||
t.Fatalf("provider should be enabled and not be connected: exp=%v, act=%v", exp, act)
|
||||
}
|
||||
}
|
||||
@@ -139,8 +142,11 @@ func TestPushEvent(t *testing.T) {
|
||||
|
||||
for idx, provider := range ic {
|
||||
exp := testConfigs[idx].PushEventCalled
|
||||
act := provider.(*CommunicationProvider).PushEventCalled
|
||||
if exp != act {
|
||||
act, ok := provider.(*CommunicationProvider)
|
||||
if !ok {
|
||||
t.Fatal("unable to type assert provider")
|
||||
}
|
||||
if exp != act.PushEventCalled {
|
||||
t.Fatalf("provider should be enabled and connected: exp=%v, act=%v", exp, act)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ type Slack struct {
|
||||
WebsocketConn *websocket.Conn
|
||||
Connected bool
|
||||
Shutdown bool
|
||||
sync.Mutex
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// IsConnected returns whether or not the connection is connected
|
||||
@@ -91,9 +91,9 @@ func (s *Slack) BuildURL(token string) string {
|
||||
|
||||
// GetChannelsString returns a list of all channels on the slack workspace
|
||||
func (s *Slack) GetChannelsString() []string {
|
||||
var channels []string
|
||||
channels := make([]string, len(s.Details.Channels))
|
||||
for i := range s.Details.Channels {
|
||||
channels = append(channels, s.Details.Channels[i].NameNormalized)
|
||||
channels[i] = s.Details.Channels[i].NameNormalized
|
||||
}
|
||||
return channels
|
||||
}
|
||||
@@ -355,8 +355,8 @@ func (s *Slack) WebsocketKeepAlive() {
|
||||
|
||||
// WebsocketSend sends a message via the websocket connection
|
||||
func (s *Slack) WebsocketSend(eventType, text string) error {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
newMessage := SendMessage{
|
||||
ID: time.Now().Unix(),
|
||||
Type: eventType,
|
||||
|
||||
@@ -206,7 +206,10 @@ func TestHandlePresenceChange(t *testing.T) {
|
||||
t.Error("slack handlePresenceChange(), unmarshalled malformed json")
|
||||
}
|
||||
|
||||
data, _ := json.Marshal(pres)
|
||||
data, err := json.Marshal(pres)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = s.handlePresenceChange(data)
|
||||
if err != nil {
|
||||
t.Errorf("slack handlePresenceChange() Error: %s", err)
|
||||
@@ -235,7 +238,10 @@ func TestHandleMessageResponse(t *testing.T) {
|
||||
var msg Message
|
||||
msg.User = "1337"
|
||||
msg.Text = "Hello World!"
|
||||
resp, _ := json.Marshal(msg)
|
||||
resp, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = s.handleMessageResponse(resp, data)
|
||||
if err != nil {
|
||||
@@ -243,7 +249,10 @@ func TestHandleMessageResponse(t *testing.T) {
|
||||
}
|
||||
|
||||
msg.Text = "!notacommand"
|
||||
resp, _ = json.Marshal(msg)
|
||||
resp, err = json.Marshal(msg)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = s.handleMessageResponse(resp, data)
|
||||
if err == nil {
|
||||
@@ -286,7 +295,10 @@ func TestHandleReconnectResponse(t *testing.T) {
|
||||
}
|
||||
testURL.URL = "https://www.thrasher.io"
|
||||
|
||||
data, _ := json.Marshal(testURL)
|
||||
data, err := json.Marshal(testURL)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = s.handleReconnectResponse(data)
|
||||
if err != nil || s.ReconnectURL != "https://www.thrasher.io" {
|
||||
|
||||
@@ -42,15 +42,13 @@ func (s *SMSGlobal) Setup(cfg *base.CommunicationsConfig) {
|
||||
s.Password = cfg.SMSGlobalConfig.Password
|
||||
s.SendFrom = cfg.SMSGlobalConfig.From
|
||||
|
||||
var contacts []Contact
|
||||
contacts := make([]Contact, len(cfg.SMSGlobalConfig.Contacts))
|
||||
for x := range cfg.SMSGlobalConfig.Contacts {
|
||||
contacts = append(contacts,
|
||||
Contact{
|
||||
Name: cfg.SMSGlobalConfig.Contacts[x].Name,
|
||||
Number: cfg.SMSGlobalConfig.Contacts[x].Number,
|
||||
Enabled: cfg.SMSGlobalConfig.Contacts[x].Enabled,
|
||||
},
|
||||
)
|
||||
contacts[x] = Contact{
|
||||
Name: cfg.SMSGlobalConfig.Contacts[x].Name,
|
||||
Number: cfg.SMSGlobalConfig.Contacts[x].Number,
|
||||
Enabled: cfg.SMSGlobalConfig.Contacts[x].Enabled,
|
||||
}
|
||||
log.Debugf(log.CommunicationMgr, "SMSGlobal: SMS Contact: %s. Number: %s. Enabled: %v\n",
|
||||
cfg.SMSGlobalConfig.Contacts[x].Name,
|
||||
cfg.SMSGlobalConfig.Contacts[x].Number,
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
@@ -1420,7 +1419,7 @@ func GetFilePath(configFile string) (configPath string, isImplicitDefaultPath bo
|
||||
// config directory as `File` or `EncryptedFile` depending on whether the config
|
||||
// is encrypted
|
||||
func migrateConfig(configFile, targetDir string) (string, error) {
|
||||
data, err := ioutil.ReadFile(configFile)
|
||||
data, err := os.ReadFile(configFile)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -1518,7 +1517,7 @@ func ReadConfig(configReader io.Reader, keyProvider func() ([]byte, error)) (*Co
|
||||
|
||||
// readEncryptedConf reads encrypted configuration and requests key from provider
|
||||
func readEncryptedConfWithKey(reader *bufio.Reader, keyProvider func() ([]byte, error)) (*Config, error) {
|
||||
fileData, err := ioutil.ReadAll(reader)
|
||||
fileData, err := io.ReadAll(reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/common"
|
||||
@@ -137,7 +136,7 @@ func (c *Config) decryptConfigData(configReader io.Reader, key []byte) ([]byte,
|
||||
return nil, err
|
||||
}
|
||||
origKey := key
|
||||
configData, err := ioutil.ReadAll(configReader)
|
||||
configData, err := io.ReadAll(configReader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -179,11 +179,11 @@ func TestEncryptTwiceReusesSaltButNewCipher(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("Problem storing config in file %s: %s\n", enc2, err)
|
||||
}
|
||||
data1, err := ioutil.ReadFile(enc1)
|
||||
data1, err := os.ReadFile(enc1)
|
||||
if err != nil {
|
||||
t.Fatalf("Problem reading file %s: %s\n", enc1, err)
|
||||
}
|
||||
data2, err := ioutil.ReadFile(enc2)
|
||||
data2, err := os.ReadFile(enc2)
|
||||
if err != nil {
|
||||
t.Fatalf("Problem reading file %s: %s\n", enc2, err)
|
||||
}
|
||||
@@ -281,7 +281,7 @@ func TestReadConfigWithPrompt(t *testing.T) {
|
||||
}
|
||||
|
||||
// Verify results
|
||||
data, err := ioutil.ReadFile(testConfigFile)
|
||||
data, err := os.ReadFile(testConfigFile)
|
||||
if err != nil {
|
||||
t.Fatalf("Problem reading saved file at %s: %s\n", testConfigFile, err)
|
||||
}
|
||||
@@ -349,7 +349,7 @@ func TestSaveConfigToFileWithErrorInPasswordPrompt(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
data, err := ioutil.ReadFile(targetFile)
|
||||
data, err := os.ReadFile(targetFile)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -920,7 +920,7 @@ func TestSupportsPair(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
assetType := asset.Spot // nolint // ifshort false positive
|
||||
assetType := asset.Spot
|
||||
if cfg.SupportsPair("asdf",
|
||||
currency.NewPair(currency.BTC, currency.USD), assetType) {
|
||||
t.Error(
|
||||
|
||||
@@ -74,7 +74,7 @@ type Checker struct {
|
||||
shutdown chan struct{}
|
||||
wg sync.WaitGroup
|
||||
connected bool
|
||||
sync.Mutex
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// Shutdown cleanly shutsdown monitor routine
|
||||
@@ -136,12 +136,12 @@ func (c *Checker) connectionTest() {
|
||||
for i := range c.DNSList {
|
||||
err := c.CheckDNS(c.DNSList[i])
|
||||
if err == nil {
|
||||
c.Lock()
|
||||
c.mu.Lock()
|
||||
if !c.connected {
|
||||
log.Debugln(log.Global, ConnRe)
|
||||
c.connected = true
|
||||
}
|
||||
c.Unlock()
|
||||
c.mu.Unlock()
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -149,22 +149,22 @@ func (c *Checker) connectionTest() {
|
||||
for i := range c.DomainList {
|
||||
err := c.CheckHost(c.DomainList[i])
|
||||
if err == nil {
|
||||
c.Lock()
|
||||
c.mu.Lock()
|
||||
if !c.connected {
|
||||
log.Debugln(log.Global, ConnRe)
|
||||
c.connected = true
|
||||
}
|
||||
c.Unlock()
|
||||
c.mu.Unlock()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
c.Lock()
|
||||
c.mu.Lock()
|
||||
if c.connected {
|
||||
log.Warnln(log.Global, ConnLost)
|
||||
c.connected = false
|
||||
}
|
||||
c.Unlock()
|
||||
c.mu.Unlock()
|
||||
}
|
||||
|
||||
// CheckDNS checks current dns for connectivity
|
||||
@@ -185,8 +185,8 @@ func (c *Checker) CheckHost(host string) error {
|
||||
|
||||
// IsConnected returns if there is internet connectivity
|
||||
func (c *Checker) IsConnected() bool {
|
||||
c.Lock()
|
||||
c.mu.Lock()
|
||||
isConnected := c.connected
|
||||
c.Unlock()
|
||||
c.mu.Unlock()
|
||||
return isConnected
|
||||
}
|
||||
|
||||
@@ -354,7 +354,11 @@ func TestBaseCode(t *testing.T) {
|
||||
len(full.UnsetCurrency))
|
||||
}
|
||||
|
||||
if full.LastMainUpdate.(int64) != -62135596800 {
|
||||
lastMainUpdate, ok := full.LastMainUpdate.(int64)
|
||||
if !ok {
|
||||
t.Error("unable to type assert LastMainUpdate")
|
||||
}
|
||||
if lastMainUpdate != -62135596800 {
|
||||
t.Errorf("BaseCode GetFullCurrencyData() error expected -62135596800 but received %d",
|
||||
full.LastMainUpdate)
|
||||
}
|
||||
|
||||
@@ -75,9 +75,9 @@ func (c *Coinmarketcap) GetCryptocurrencyInfo(currencyID ...int64) (CryptoCurren
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
var currStr []string
|
||||
currStr := make([]string, len(currencyID))
|
||||
for i := range currencyID {
|
||||
currStr = append(currStr, strconv.FormatInt(currencyID[i], 10))
|
||||
currStr[i] = strconv.FormatInt(currencyID[i], 10)
|
||||
}
|
||||
|
||||
val := url.Values{}
|
||||
@@ -315,9 +315,9 @@ func (c *Coinmarketcap) GetCryptocurrencyLatestQuotes(currencyID ...int64) (Cryp
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
var currStr []string
|
||||
for _, d := range currencyID {
|
||||
currStr = append(currStr, strconv.FormatInt(d, 10))
|
||||
currStr := make([]string, len(currencyID))
|
||||
for i := range currencyID {
|
||||
currStr[i] = strconv.FormatInt(currencyID[i], 10)
|
||||
}
|
||||
|
||||
val := url.Values{}
|
||||
@@ -387,9 +387,9 @@ func (c *Coinmarketcap) GetExchangeInfo(exchangeID ...int64) (ExchangeInfo, erro
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
var exchStr []string
|
||||
for _, d := range exchangeID {
|
||||
exchStr = append(exchStr, strconv.FormatInt(d, 10))
|
||||
exchStr := make([]string, len(exchangeID))
|
||||
for x := range exchangeID {
|
||||
exchStr[x] = strconv.FormatInt(exchangeID[x], 10)
|
||||
}
|
||||
|
||||
val := url.Values{}
|
||||
@@ -524,9 +524,9 @@ func (c *Coinmarketcap) GetExchangeLatestQuotes(exchangeID ...int64) (ExchangeLa
|
||||
return resp.Data, err
|
||||
}
|
||||
|
||||
var exchStr []string
|
||||
for _, d := range exchangeID {
|
||||
exchStr = append(exchStr, strconv.FormatInt(d, 10))
|
||||
exchStr := make([]string, len(exchangeID))
|
||||
for x := range exchangeID {
|
||||
exchStr[x] = strconv.FormatInt(exchangeID[x], 10)
|
||||
}
|
||||
|
||||
val := url.Values{}
|
||||
|
||||
@@ -38,9 +38,9 @@ func (c *CurrencyConverter) GetRates(baseCurrency, symbols string) (map[string]f
|
||||
return c.Convert(baseCurrency, symbols)
|
||||
}
|
||||
|
||||
var completedStrings []string
|
||||
completedStrings := make([]string, len(splitSymbols))
|
||||
for x := range splitSymbols {
|
||||
completedStrings = append(completedStrings, baseCurrency+"_"+splitSymbols[x])
|
||||
completedStrings[x] = baseCurrency + "_" + splitSymbols[x]
|
||||
}
|
||||
|
||||
if (c.APIKey != "" && c.APIKey != "Key") || len(completedStrings) == 2 {
|
||||
@@ -126,7 +126,7 @@ func (c *CurrencyConverter) GetSupportedCurrencies() ([]string, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var currencies []string
|
||||
currencies := make([]string, 0, len(result.Results))
|
||||
for key := range result.Results {
|
||||
currencies = append(currencies, key)
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ func (c *CurrencyLayer) GetSupportedCurrencies() ([]string, error) {
|
||||
return nil, errors.New(resp.Error.Info)
|
||||
}
|
||||
|
||||
var currencies []string
|
||||
currencies := make([]string, 0, len(resp.Currencies))
|
||||
for key := range resp.Currencies {
|
||||
currencies = append(currencies, key)
|
||||
}
|
||||
|
||||
@@ -229,7 +229,7 @@ func (e *ExchangeRateHost) GetSupportedCurrencies() ([]string, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var symbols []string
|
||||
symbols := make([]string, 0, len(s.Symbols))
|
||||
for x := range s.Symbols {
|
||||
symbols = append(symbols, x)
|
||||
}
|
||||
|
||||
@@ -84,8 +84,7 @@ func TestGetSupportedSymbols(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
_, ok := r.Symbols["AUD"]
|
||||
if !ok {
|
||||
if _, ok := r.Symbols["AUD"]; !ok {
|
||||
t.Error("should contain AUD")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,9 +45,10 @@ func (e *ExchangeRates) cleanCurrencies(baseCurrency, symbols string) string {
|
||||
e.supportedCurrencies = supportedCurrencies
|
||||
}
|
||||
}
|
||||
var cleanedCurrencies []string
|
||||
|
||||
symbols = strings.Replace(symbols, "RUR", "RUB", -1)
|
||||
var s = strings.Split(symbols, ",")
|
||||
cleanedCurrencies := make([]string, 0, len(s))
|
||||
for _, x := range s {
|
||||
// first make sure that the baseCurrency is not in the symbols list
|
||||
// if it is set
|
||||
@@ -244,7 +245,7 @@ func (e *ExchangeRates) GetSupportedCurrencies() ([]string, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var supportedCurrencies []string
|
||||
supportedCurrencies := make([]string, 0, len(symbols))
|
||||
for x := range symbols {
|
||||
supportedCurrencies = append(supportedCurrencies, x)
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ func (f *Fixer) GetSupportedCurrencies() ([]string, error) {
|
||||
return nil, errors.New(resp.Error.Type + resp.Error.Info)
|
||||
}
|
||||
|
||||
var currencies []string
|
||||
currencies := make([]string, 0, len(resp.Map))
|
||||
for key := range resp.Map {
|
||||
currencies = append(currencies, key)
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
@@ -51,7 +51,7 @@ var (
|
||||
func (s *Storage) SetDefaults() {
|
||||
s.defaultBaseCurrency = USD
|
||||
s.baseCurrency = s.defaultBaseCurrency
|
||||
var fiatCurrencies []Code
|
||||
fiatCurrencies := make([]Code, 0, len(symbols))
|
||||
for item := range symbols {
|
||||
if item == USDT.Item {
|
||||
continue
|
||||
@@ -125,7 +125,7 @@ func (s *Storage) RunUpdater(overrides BotOverrides, settings *Config, filePath
|
||||
}
|
||||
}
|
||||
|
||||
var fxSettings []base.Settings
|
||||
fxSettings := make([]base.Settings, 0, len(settings.ForexProviders))
|
||||
var primaryProvider bool
|
||||
for i := range settings.ForexProviders {
|
||||
enabled := (settings.ForexProviders[i].Name == "CurrencyConverter" && overrides.CurrencyConverter) ||
|
||||
@@ -331,7 +331,7 @@ func (s *Storage) ForeignExchangeUpdater() {
|
||||
// SeedCurrencyAnalysisData sets a new instance of a coinmarketcap data.
|
||||
func (s *Storage) SeedCurrencyAnalysisData() error {
|
||||
if s.currencyCodes.LastMainUpdate.IsZero() {
|
||||
b, err := ioutil.ReadFile(s.path)
|
||||
b, err := os.ReadFile(s.path)
|
||||
if err != nil {
|
||||
return s.FetchCurrencyAnalysisData()
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ func Event(id, msgtype, message string) {
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
ctx := context.TODO()
|
||||
ctx = boil.SkipTimestamps(ctx)
|
||||
|
||||
tx, err := database.DB.SQL.BeginTx(ctx, nil)
|
||||
@@ -76,7 +76,7 @@ func GetEvent(startTime, endTime time.Time, order string, limit int) (interface{
|
||||
orderByQuery := qm.OrderBy(orderByQueryString)
|
||||
limitQuery := qm.Limit(limit)
|
||||
|
||||
ctx := context.Background()
|
||||
ctx := context.TODO()
|
||||
if repository.GetSQLDialect() == database.DBSQLite3 {
|
||||
return modelSQLite.AuditEvents(query, orderByQuery, limitQuery).All(ctx, database.DB.SQL)
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ func Series(exchangeName, base, quote string, interval int64, asset string, star
|
||||
queries = append(queries, qm.Where("exchange_name_id = ?", exchangeUUID.String()))
|
||||
if repository.GetSQLDialect() == database.DBSQLite3 {
|
||||
queries = append(queries, qm.Where("timestamp between ? and ?", start.UTC().Format(time.RFC3339), end.UTC().Format(time.RFC3339)))
|
||||
retCandle, errC := modelSQLite.Candles(queries...).All(context.Background(), database.DB.SQL)
|
||||
retCandle, errC := modelSQLite.Candles(queries...).All(context.TODO(), database.DB.SQL)
|
||||
if errC != nil {
|
||||
return out, errC
|
||||
}
|
||||
@@ -68,7 +68,7 @@ func Series(exchangeName, base, quote string, interval int64, asset string, star
|
||||
}
|
||||
} else {
|
||||
queries = append(queries, qm.Where("timestamp between ? and ?", start.UTC(), end.UTC()))
|
||||
retCandle, errC := modelPSQL.Candles(queries...).All(context.Background(), database.DB.SQL)
|
||||
retCandle, errC := modelPSQL.Candles(queries...).All(context.TODO(), database.DB.SQL)
|
||||
if errC != nil {
|
||||
return out, errC
|
||||
}
|
||||
@@ -108,7 +108,7 @@ func DeleteCandles(in *Item) (int64, error) {
|
||||
return 0, errNoCandleData
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
ctx := context.TODO()
|
||||
queries := []qm.QueryMod{
|
||||
qm.Where("base = ?", strings.ToUpper(in.Base)),
|
||||
qm.Where("quote = ?", strings.ToUpper(in.Quote)),
|
||||
@@ -126,7 +126,7 @@ func DeleteCandles(in *Item) (int64, error) {
|
||||
}
|
||||
|
||||
func deleteSQLite(ctx context.Context, queries []qm.QueryMod) (int64, error) {
|
||||
retCandle, err := modelSQLite.Candles(queries...).All(context.Background(), database.DB.SQL)
|
||||
retCandle, err := modelSQLite.Candles(queries...).All(ctx, database.DB.SQL)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -153,7 +153,7 @@ func deleteSQLite(ctx context.Context, queries []qm.QueryMod) (int64, error) {
|
||||
}
|
||||
|
||||
func deletePostgres(ctx context.Context, queries []qm.QueryMod) (int64, error) {
|
||||
retCandle, err := modelPSQL.Candles(queries...).All(context.Background(), database.DB.SQL)
|
||||
retCandle, err := modelPSQL.Candles(queries...).All(ctx, database.DB.SQL)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -189,7 +189,7 @@ func Insert(in *Item) (uint64, error) {
|
||||
return 0, errNoCandleData
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
ctx := context.TODO()
|
||||
tx, err := database.DB.SQL.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
|
||||
@@ -38,7 +38,7 @@ func Setup(db database.IDatabase) (*DBService, error) {
|
||||
|
||||
// Upsert inserts or updates jobs into the database
|
||||
func (db *DBService) Upsert(jobs ...*DataHistoryJob) error {
|
||||
ctx := context.Background()
|
||||
ctx := context.TODO()
|
||||
|
||||
tx, err := db.sql.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
@@ -156,7 +156,7 @@ func (db *DBService) GetPrerequisiteJob(nickname string) (*DataHistoryJob, error
|
||||
// SetRelationshipByID removes a relationship in the event of a changed
|
||||
// relationship during upsertion
|
||||
func (db *DBService) SetRelationshipByID(prerequisiteJobID, followingJobID string, status int64) error {
|
||||
ctx := context.Background()
|
||||
ctx := context.TODO()
|
||||
if strings.EqualFold(prerequisiteJobID, followingJobID) {
|
||||
return errCannotSetSamePrerequisite
|
||||
}
|
||||
@@ -191,7 +191,7 @@ func (db *DBService) SetRelationshipByID(prerequisiteJobID, followingJobID strin
|
||||
// SetRelationshipByNickname removes a relationship in the event of a changed
|
||||
// relationship during upsertion
|
||||
func (db *DBService) SetRelationshipByNickname(prerequisiteNickname, followingNickname string, status int64) error {
|
||||
ctx := context.Background()
|
||||
ctx := context.TODO()
|
||||
if strings.EqualFold(prerequisiteNickname, followingNickname) {
|
||||
return errCannotSetSamePrerequisite
|
||||
}
|
||||
@@ -331,7 +331,7 @@ func upsertPostgres(ctx context.Context, tx *sql.Tx, jobs ...*DataHistoryJob) er
|
||||
return nil
|
||||
}
|
||||
func (db *DBService) getByNicknameSQLite(nickname string) (*DataHistoryJob, error) {
|
||||
result, err := sqlite3.Datahistoryjobs(qm.Where("nickname = ?", strings.ToLower(nickname))).One(context.Background(), db.sql)
|
||||
result, err := sqlite3.Datahistoryjobs(qm.Where("nickname = ?", strings.ToLower(nickname))).One(context.TODO(), db.sql)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -341,7 +341,7 @@ func (db *DBService) getByNicknameSQLite(nickname string) (*DataHistoryJob, erro
|
||||
|
||||
func (db *DBService) getByNicknamePostgres(nickname string) (*DataHistoryJob, error) {
|
||||
query := postgres.Datahistoryjobs(qm.Where("nickname = ?", strings.ToLower(nickname)))
|
||||
result, err := query.One(context.Background(), db.sql)
|
||||
result, err := query.One(context.TODO(), db.sql)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -349,7 +349,7 @@ func (db *DBService) getByNicknamePostgres(nickname string) (*DataHistoryJob, er
|
||||
}
|
||||
|
||||
func (db *DBService) getByIDSQLite(id string) (*DataHistoryJob, error) {
|
||||
result, err := sqlite3.Datahistoryjobs(qm.Where("id = ?", id)).One(context.Background(), db.sql)
|
||||
result, err := sqlite3.Datahistoryjobs(qm.Where("id = ?", id)).One(context.TODO(), db.sql)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -359,7 +359,7 @@ func (db *DBService) getByIDSQLite(id string) (*DataHistoryJob, error) {
|
||||
|
||||
func (db *DBService) getByIDPostgres(id string) (*DataHistoryJob, error) {
|
||||
query := postgres.Datahistoryjobs(qm.Where("id = ?", id))
|
||||
result, err := query.One(context.Background(), db.sql)
|
||||
result, err := query.One(context.TODO(), db.sql)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -368,13 +368,13 @@ func (db *DBService) getByIDPostgres(id string) (*DataHistoryJob, error) {
|
||||
}
|
||||
|
||||
func (db *DBService) getJobsBetweenSQLite(startDate, endDate time.Time) ([]DataHistoryJob, error) {
|
||||
var jobs []DataHistoryJob
|
||||
query := sqlite3.Datahistoryjobs(qm.Where("created BETWEEN ? AND ? ", startDate.UTC().Format(time.RFC3339), endDate.UTC().Format(time.RFC3339)))
|
||||
results, err := query.All(context.Background(), db.sql)
|
||||
results, err := query.All(context.TODO(), db.sql)
|
||||
if err != nil {
|
||||
return jobs, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
jobs := make([]DataHistoryJob, 0, len(results))
|
||||
for i := range results {
|
||||
job, err := db.createSQLiteDataHistoryJobResponse(results[i])
|
||||
if err != nil {
|
||||
@@ -387,13 +387,13 @@ func (db *DBService) getJobsBetweenSQLite(startDate, endDate time.Time) ([]DataH
|
||||
}
|
||||
|
||||
func (db *DBService) getJobsBetweenPostgres(startDate, endDate time.Time) ([]DataHistoryJob, error) {
|
||||
var jobs []DataHistoryJob
|
||||
query := postgres.Datahistoryjobs(qm.Where("created BETWEEN ? AND ? ", startDate, endDate))
|
||||
results, err := query.All(context.Background(), db.sql)
|
||||
results, err := query.All(context.TODO(), db.sql)
|
||||
if err != nil {
|
||||
return jobs, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
jobs := make([]DataHistoryJob, 0, len(results))
|
||||
for i := range results {
|
||||
job, err := db.createPostgresDataHistoryJobResponse(results[i])
|
||||
if err != nil {
|
||||
@@ -410,7 +410,7 @@ func (db *DBService) getJobAndAllResultsSQLite(nickname string) (*DataHistoryJob
|
||||
qm.Load(sqlite3.DatahistoryjobRels.JobDatahistoryjobresults),
|
||||
qm.Load(sqlite3.DatahistoryjobRels.ExchangeName),
|
||||
qm.Where("nickname = ?", strings.ToLower(nickname)))
|
||||
result, err := query.One(context.Background(), db.sql)
|
||||
result, err := query.One(context.TODO(), db.sql)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -422,7 +422,7 @@ func (db *DBService) getJobAndAllResultsPostgres(nickname string) (*DataHistoryJ
|
||||
query := postgres.Datahistoryjobs(
|
||||
qm.Load(postgres.DatahistoryjobRels.JobDatahistoryjobresults),
|
||||
qm.Where("nickname = ?", strings.ToLower(nickname)))
|
||||
result, err := query.One(context.Background(), db.sql)
|
||||
result, err := query.One(context.TODO(), db.sql)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -435,12 +435,12 @@ func (db *DBService) getAllIncompleteJobsAndResultsSQLite() ([]DataHistoryJob, e
|
||||
qm.Load(sqlite3.DatahistoryjobRels.ExchangeName),
|
||||
qm.Load(sqlite3.DatahistoryjobRels.JobDatahistoryjobresults),
|
||||
qm.Where("status = ?", 0))
|
||||
results, err := query.All(context.Background(), db.sql)
|
||||
results, err := query.All(context.TODO(), db.sql)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var jobs []DataHistoryJob
|
||||
jobs := make([]DataHistoryJob, 0, len(results))
|
||||
for i := range results {
|
||||
job, err := db.createSQLiteDataHistoryJobResponse(results[i])
|
||||
if err != nil {
|
||||
@@ -457,12 +457,12 @@ func (db *DBService) getAllIncompleteJobsAndResultsPostgres() ([]DataHistoryJob,
|
||||
query := postgres.Datahistoryjobs(
|
||||
qm.Load(postgres.DatahistoryjobRels.JobDatahistoryjobresults),
|
||||
qm.Where("status = ?", 0))
|
||||
results, err := query.All(context.Background(), db.sql)
|
||||
results, err := query.All(context.TODO(), db.sql)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var jobs []DataHistoryJob
|
||||
jobs := make([]DataHistoryJob, 0, len(results))
|
||||
for i := range results {
|
||||
job, err := db.createPostgresDataHistoryJobResponse(results[i])
|
||||
if err != nil {
|
||||
@@ -475,15 +475,15 @@ func (db *DBService) getAllIncompleteJobsAndResultsPostgres() ([]DataHistoryJob,
|
||||
}
|
||||
|
||||
func (db *DBService) getRelatedUpcomingJobsSQLite(nickname string) ([]*DataHistoryJob, error) {
|
||||
job, err := sqlite3.Datahistoryjobs(qm.Where("nickname = ?", nickname)).One(context.Background(), db.sql)
|
||||
job, err := sqlite3.Datahistoryjobs(qm.Where("nickname = ?", nickname)).One(context.TODO(), db.sql)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
results, err := job.JobDatahistoryjobs().All(context.Background(), db.sql)
|
||||
results, err := job.JobDatahistoryjobs().All(context.TODO(), db.sql)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var resp []*DataHistoryJob
|
||||
resp := make([]*DataHistoryJob, 0, len(results))
|
||||
for i := range results {
|
||||
job, err := db.createSQLiteDataHistoryJobResponse(results[i])
|
||||
if err != nil {
|
||||
@@ -496,11 +496,11 @@ func (db *DBService) getRelatedUpcomingJobsSQLite(nickname string) ([]*DataHisto
|
||||
|
||||
func (db *DBService) getRelatedUpcomingJobsPostgres(nickname string) ([]*DataHistoryJob, error) {
|
||||
q := postgres.Datahistoryjobs(qm.Load(postgres.DatahistoryjobRels.JobDatahistoryjobs), qm.Where("nickname = ?", nickname))
|
||||
jobWithRelations, err := q.One(context.Background(), db.sql)
|
||||
jobWithRelations, err := q.One(context.TODO(), db.sql)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var response []*DataHistoryJob
|
||||
response := make([]*DataHistoryJob, 0, len(jobWithRelations.R.JobDatahistoryjobs))
|
||||
for i := range jobWithRelations.R.JobDatahistoryjobs {
|
||||
job, err := db.getByIDPostgres(jobWithRelations.R.JobDatahistoryjobs[i].ID)
|
||||
if err != nil {
|
||||
@@ -556,11 +556,11 @@ func setRelationshipByIDPostgres(ctx context.Context, tx *sql.Tx, prerequisiteJo
|
||||
}
|
||||
|
||||
func (db *DBService) getPrerequisiteJobSQLite(nickname string) (*DataHistoryJob, error) {
|
||||
result, err := sqlite3.Datahistoryjobs(qm.Where("nickname = ?", nickname)).One(context.Background(), db.sql)
|
||||
result, err := sqlite3.Datahistoryjobs(qm.Where("nickname = ?", nickname)).One(context.TODO(), db.sql)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
job, err := result.PrerequisiteJobDatahistoryjobs().One(context.Background(), db.sql)
|
||||
job, err := result.PrerequisiteJobDatahistoryjobs().One(context.TODO(), db.sql)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -569,11 +569,11 @@ func (db *DBService) getPrerequisiteJobSQLite(nickname string) (*DataHistoryJob,
|
||||
}
|
||||
|
||||
func (db *DBService) getPrerequisiteJobPostgres(nickname string) (*DataHistoryJob, error) {
|
||||
job, err := postgres.Datahistoryjobs(qm.Where("nickname = ?", nickname)).One(context.Background(), db.sql)
|
||||
job, err := postgres.Datahistoryjobs(qm.Where("nickname = ?", nickname)).One(context.TODO(), db.sql)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result, err := job.PrerequisiteJobDatahistoryjobs().One(context.Background(), db.sql)
|
||||
result, err := job.PrerequisiteJobDatahistoryjobs().One(context.TODO(), db.sql)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -631,7 +631,7 @@ func (db *DBService) createSQLiteDataHistoryJobResponse(result *sqlite3.Datahist
|
||||
if result.R != nil && result.R.ExchangeName != nil {
|
||||
exchange = result.R.ExchangeName
|
||||
} else {
|
||||
exchange, err = result.ExchangeName().One(context.Background(), db.sql)
|
||||
exchange, err = result.ExchangeName().One(context.TODO(), db.sql)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not retrieve exchange '%v' %w", result.ExchangeNameID, err)
|
||||
}
|
||||
@@ -639,7 +639,7 @@ func (db *DBService) createSQLiteDataHistoryJobResponse(result *sqlite3.Datahist
|
||||
var secondaryExchangeName string
|
||||
if result.SecondaryExchangeID.String != "" {
|
||||
var secondaryExchangeResult *sqlite3.Exchange
|
||||
secondaryExchangeResult, err = result.SecondaryExchange().One(context.Background(), db.sql)
|
||||
secondaryExchangeResult, err = result.SecondaryExchange().One(context.TODO(), db.sql)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not retrieve secondary exchange '%v' %w", result.SecondaryExchangeID, err)
|
||||
}
|
||||
@@ -661,7 +661,7 @@ func (db *DBService) createSQLiteDataHistoryJobResponse(result *sqlite3.Datahist
|
||||
return nil, err
|
||||
}
|
||||
|
||||
prereqJob, err := result.PrerequisiteJobDatahistoryjobs().One(context.Background(), db.sql)
|
||||
prereqJob, err := result.PrerequisiteJobDatahistoryjobs().One(context.TODO(), db.sql)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
return nil, err
|
||||
}
|
||||
@@ -735,7 +735,7 @@ func (db *DBService) createPostgresDataHistoryJobResponse(result *postgres.Datah
|
||||
if result.R != nil && result.R.ExchangeName != nil {
|
||||
exchange = result.R.ExchangeName
|
||||
} else {
|
||||
exchange, err = result.ExchangeName().One(context.Background(), db.sql)
|
||||
exchange, err = result.ExchangeName().One(context.TODO(), db.sql)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not retrieve exchange '%v' %w", result.ExchangeNameID, err)
|
||||
}
|
||||
@@ -744,7 +744,7 @@ func (db *DBService) createPostgresDataHistoryJobResponse(result *postgres.Datah
|
||||
var secondaryExchangeName string
|
||||
if result.SecondaryExchangeID.String != "" {
|
||||
var secondaryExchangeResult *postgres.Exchange
|
||||
secondaryExchangeResult, err = result.SecondaryExchange().One(context.Background(), db.sql)
|
||||
secondaryExchangeResult, err = result.SecondaryExchange().One(context.TODO(), db.sql)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not retrieve secondary exchange '%v' %w", result.SecondaryExchangeID, err)
|
||||
}
|
||||
@@ -753,7 +753,7 @@ func (db *DBService) createPostgresDataHistoryJobResponse(result *postgres.Datah
|
||||
}
|
||||
}
|
||||
|
||||
prereqJob, err := result.PrerequisiteJobDatahistoryjobs().One(context.Background(), db.sql)
|
||||
prereqJob, err := result.PrerequisiteJobDatahistoryjobs().One(context.TODO(), db.sql)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ func (db *DBService) Upsert(jobs ...*DataHistoryJobResult) error {
|
||||
if len(jobs) == 0 {
|
||||
return nil
|
||||
}
|
||||
ctx := context.Background()
|
||||
ctx := context.TODO()
|
||||
|
||||
tx, err := db.sql.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
@@ -165,11 +165,11 @@ func upsertPostgres(ctx context.Context, tx *sql.Tx, results ...*DataHistoryJobR
|
||||
|
||||
func (db *DBService) getByJobIDSQLite(jobID string) ([]DataHistoryJobResult, error) {
|
||||
query := sqlite3.Datahistoryjobresults(qm.Where("job_id = ?", jobID))
|
||||
results, err := query.All(context.Background(), db.sql)
|
||||
results, err := query.All(context.TODO(), db.sql)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var resp []DataHistoryJobResult
|
||||
resp := make([]DataHistoryJobResult, len(results))
|
||||
for i := range results {
|
||||
var start, end, run time.Time
|
||||
start, err = time.Parse(time.RFC3339, results[i].IntervalStartTime)
|
||||
@@ -184,7 +184,7 @@ func (db *DBService) getByJobIDSQLite(jobID string) ([]DataHistoryJobResult, err
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp = append(resp, DataHistoryJobResult{
|
||||
resp[i] = DataHistoryJobResult{
|
||||
ID: results[i].ID,
|
||||
JobID: results[i].JobID,
|
||||
IntervalStartDate: start,
|
||||
@@ -192,7 +192,7 @@ func (db *DBService) getByJobIDSQLite(jobID string) ([]DataHistoryJobResult, err
|
||||
Status: int64(results[i].Status),
|
||||
Result: results[i].Result.String,
|
||||
Date: run,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
@@ -200,13 +200,13 @@ func (db *DBService) getByJobIDSQLite(jobID string) ([]DataHistoryJobResult, err
|
||||
|
||||
func (db *DBService) getByJobIDPostgres(jobID string) ([]DataHistoryJobResult, error) {
|
||||
query := postgres.Datahistoryjobresults(qm.Where("job_id = ?", jobID))
|
||||
results, err := query.All(context.Background(), db.sql)
|
||||
results, err := query.All(context.TODO(), db.sql)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var resp []DataHistoryJobResult
|
||||
resp := make([]DataHistoryJobResult, len(results))
|
||||
for i := range results {
|
||||
resp = append(resp, DataHistoryJobResult{
|
||||
resp[i] = DataHistoryJobResult{
|
||||
ID: results[i].ID,
|
||||
JobID: results[i].JobID,
|
||||
IntervalStartDate: results[i].IntervalStartTime,
|
||||
@@ -214,20 +214,20 @@ func (db *DBService) getByJobIDPostgres(jobID string) ([]DataHistoryJobResult, e
|
||||
Status: int64(results[i].Status),
|
||||
Result: results[i].Result.String,
|
||||
Date: results[i].RunTime,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (db *DBService) getJobResultsBetweenSQLite(jobID string, startDate, endDate time.Time) ([]DataHistoryJobResult, error) {
|
||||
var results []DataHistoryJobResult
|
||||
query := sqlite3.Datahistoryjobresults(qm.Where("job_id = ? AND run_time BETWEEN ? AND ? ", jobID, startDate.UTC().Format(time.RFC3339), endDate.UTC().Format(time.RFC3339)))
|
||||
resp, err := query.All(context.Background(), db.sql)
|
||||
resp, err := query.All(context.TODO(), db.sql)
|
||||
if err != nil {
|
||||
return results, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
results := make([]DataHistoryJobResult, len(resp))
|
||||
for i := range resp {
|
||||
var start, end, run time.Time
|
||||
start, err = time.Parse(time.RFC3339, resp[i].IntervalStartTime)
|
||||
@@ -242,7 +242,7 @@ func (db *DBService) getJobResultsBetweenSQLite(jobID string, startDate, endDate
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
results = append(results, DataHistoryJobResult{
|
||||
results[i] = DataHistoryJobResult{
|
||||
ID: resp[i].ID,
|
||||
JobID: resp[i].JobID,
|
||||
IntervalStartDate: start,
|
||||
@@ -250,22 +250,22 @@ func (db *DBService) getJobResultsBetweenSQLite(jobID string, startDate, endDate
|
||||
Status: int64(resp[i].Status),
|
||||
Result: resp[i].Result.String,
|
||||
Date: run,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (db *DBService) getJobResultsBetweenPostgres(jobID string, startDate, endDate time.Time) ([]DataHistoryJobResult, error) {
|
||||
var jobs []DataHistoryJobResult
|
||||
query := postgres.Datahistoryjobresults(qm.Where("job_id = ? AND run_time BETWEEN ? AND ? ", jobID, startDate, endDate))
|
||||
results, err := query.All(context.Background(), db.sql)
|
||||
results, err := query.All(context.TODO(), db.sql)
|
||||
if err != nil {
|
||||
return jobs, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
jobs := make([]DataHistoryJobResult, len(results))
|
||||
for i := range results {
|
||||
jobs = append(jobs, DataHistoryJobResult{
|
||||
jobs[i] = DataHistoryJobResult{
|
||||
ID: results[i].ID,
|
||||
JobID: results[i].JobID,
|
||||
IntervalStartDate: results[i].IntervalStartTime,
|
||||
@@ -273,7 +273,7 @@ func (db *DBService) getJobResultsBetweenPostgres(jobID string, startDate, endDa
|
||||
Status: int64(results[i].Status),
|
||||
Result: results[i].Result.String,
|
||||
Date: results[i].RunTime,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return jobs, nil
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/csv"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
@@ -37,7 +38,7 @@ func one(in, clause string) (out Details, err error) {
|
||||
|
||||
whereQM := qm.Where(clause+"= ?", in)
|
||||
if repository.GetSQLDialect() == database.DBSQLite3 {
|
||||
ret, errS := modelSQLite.Exchanges(whereQM).One(context.Background(), database.DB.SQL)
|
||||
ret, errS := modelSQLite.Exchanges(whereQM).One(context.TODO(), database.DB.SQL)
|
||||
if errS != nil {
|
||||
return out, errS
|
||||
}
|
||||
@@ -47,7 +48,7 @@ func one(in, clause string) (out Details, err error) {
|
||||
return out, errS
|
||||
}
|
||||
} else {
|
||||
ret, errS := modelPSQL.Exchanges(whereQM).One(context.Background(), database.DB.SQL)
|
||||
ret, errS := modelPSQL.Exchanges(whereQM).One(context.TODO(), database.DB.SQL)
|
||||
if errS != nil {
|
||||
return out, errS
|
||||
}
|
||||
@@ -67,7 +68,7 @@ func Insert(in Details) error {
|
||||
return database.ErrDatabaseSupportDisabled
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
ctx := context.TODO()
|
||||
tx, err := database.DB.SQL.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -100,7 +101,7 @@ func InsertMany(in []Details) error {
|
||||
return database.ErrDatabaseSupportDisabled
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
ctx := context.TODO()
|
||||
tx, err := database.DB.SQL.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -178,7 +179,11 @@ func UUIDByName(exchange string) (uuid.UUID, error) {
|
||||
exchange = strings.ToLower(exchange)
|
||||
v := exchangeCache.Get(exchange)
|
||||
if v != nil {
|
||||
return v.(uuid.UUID), nil
|
||||
u, ok := v.(uuid.UUID)
|
||||
if !ok {
|
||||
return uuid.UUID{}, errors.New("unable to type assert uuid")
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
ret, err := One(exchange)
|
||||
if err != nil {
|
||||
|
||||
@@ -20,7 +20,7 @@ func Event(id, name, path string, data null.Bytes, executionType, status string,
|
||||
return
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
ctx := context.TODO()
|
||||
ctx = boil.SkipTimestamps(ctx)
|
||||
tx, err := database.DB.SQL.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
|
||||
@@ -34,7 +34,7 @@ func Insert(trades ...Data) error {
|
||||
}
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
ctx := context.TODO()
|
||||
ctx = boil.SkipTimestamps(ctx)
|
||||
|
||||
tx, err := database.DB.SQL.BeginTx(ctx, nil)
|
||||
@@ -65,7 +65,7 @@ func Insert(trades ...Data) error {
|
||||
// VerifyTradeInIntervals will query for ONE trade within each kline interval and verify if data exists
|
||||
// if it does, it will set the range holder property "HasData" to true
|
||||
func VerifyTradeInIntervals(exchangeName, assetType, base, quote string, irh *kline.IntervalRangeHolder) error {
|
||||
ctx := context.Background()
|
||||
ctx := context.TODO()
|
||||
ctx = boil.SkipTimestamps(ctx)
|
||||
|
||||
tx, err := database.DB.SQL.BeginTx(ctx, nil)
|
||||
@@ -237,7 +237,7 @@ func getByUUIDSQLite(uuid string) (Data, error) {
|
||||
var td Data
|
||||
var ts time.Time
|
||||
query := sqlite3.Trades(qm.Where("id = ?", uuid))
|
||||
result, err := query.One(context.Background(), database.DB.SQL)
|
||||
result, err := query.One(context.TODO(), database.DB.SQL)
|
||||
if err != nil {
|
||||
return td, err
|
||||
}
|
||||
@@ -265,7 +265,7 @@ func getByUUIDSQLite(uuid string) (Data, error) {
|
||||
func getByUUIDPostgres(uuid string) (td Data, err error) {
|
||||
query := postgres.Trades(qm.Where("id = ?", uuid))
|
||||
var result *postgres.Trade
|
||||
result, err = query.One(context.Background(), database.DB.SQL)
|
||||
result, err = query.One(context.TODO(), database.DB.SQL)
|
||||
if err != nil {
|
||||
return td, err
|
||||
}
|
||||
@@ -318,7 +318,7 @@ func getInRangeSQLite(exchangeName, assetType, base, quote string, startDate, en
|
||||
q := generateQuery(wheres, startDate, endDate, true)
|
||||
query := sqlite3.Trades(q...)
|
||||
var result []*sqlite3.Trade
|
||||
result, err = query.All(context.Background(), database.DB.SQL)
|
||||
result, err = query.All(context.TODO(), database.DB.SQL)
|
||||
if err != nil {
|
||||
return td, err
|
||||
}
|
||||
@@ -361,7 +361,7 @@ func getInRangePostgres(exchangeName, assetType, base, quote string, startDate,
|
||||
q := generateQuery(wheres, startDate, endDate, false)
|
||||
query := postgres.Trades(q...)
|
||||
var result []*postgres.Trade
|
||||
result, err = query.All(context.Background(), database.DB.SQL)
|
||||
result, err = query.All(context.TODO(), database.DB.SQL)
|
||||
if err != nil {
|
||||
return td, err
|
||||
}
|
||||
@@ -386,7 +386,7 @@ func getInRangePostgres(exchangeName, assetType, base, quote string, startDate,
|
||||
|
||||
// DeleteTrades will remove trades from the database using trade.Data
|
||||
func DeleteTrades(trades ...Data) error {
|
||||
ctx := context.Background()
|
||||
ctx := context.TODO()
|
||||
ctx = boil.SkipTimestamps(ctx)
|
||||
|
||||
tx, err := database.DB.SQL.BeginTx(ctx, nil)
|
||||
@@ -402,9 +402,9 @@ func DeleteTrades(trades ...Data) error {
|
||||
}
|
||||
}()
|
||||
if repository.GetSQLDialect() == database.DBSQLite3 || repository.GetSQLDialect() == database.DBSQLite {
|
||||
err = deleteTradesSQLite(context.Background(), tx, trades...)
|
||||
err = deleteTradesSQLite(context.TODO(), tx, trades...)
|
||||
} else {
|
||||
err = deleteTradesPostgres(context.Background(), tx, trades...)
|
||||
err = deleteTradesPostgres(context.TODO(), tx, trades...)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -414,9 +414,9 @@ func DeleteTrades(trades ...Data) error {
|
||||
}
|
||||
|
||||
func deleteTradesSQLite(ctx context.Context, tx *sql.Tx, trades ...Data) error {
|
||||
var tradeIDs []interface{}
|
||||
tradeIDs := make([]interface{}, len(trades))
|
||||
for i := range trades {
|
||||
tradeIDs = append(tradeIDs, trades[i].ID)
|
||||
tradeIDs[i] = trades[i].ID
|
||||
}
|
||||
query := sqlite3.Trades(qm.WhereIn(`id in ?`, tradeIDs...))
|
||||
_, err := query.DeleteAll(ctx, tx)
|
||||
@@ -424,9 +424,9 @@ func deleteTradesSQLite(ctx context.Context, tx *sql.Tx, trades ...Data) error {
|
||||
}
|
||||
|
||||
func deleteTradesPostgres(ctx context.Context, tx *sql.Tx, trades ...Data) error {
|
||||
var tradeIDs []interface{}
|
||||
tradeIDs := make([]interface{}, len(trades))
|
||||
for i := range trades {
|
||||
tradeIDs = append(tradeIDs, trades[i].ID)
|
||||
tradeIDs[i] = trades[i].ID
|
||||
}
|
||||
query := postgres.Trades(qm.WhereIn(`id in ?`, tradeIDs...))
|
||||
_, err := query.DeleteAll(ctx, tx)
|
||||
|
||||
@@ -267,7 +267,11 @@ func GetEventsByDate(exchange string, start, end time.Time, limit int) ([]*withd
|
||||
}
|
||||
|
||||
func generateWhereQuery(columns, id []string, limit int) []qm.QueryMod {
|
||||
var queries []qm.QueryMod
|
||||
x := len(columns)
|
||||
if limit > 0 {
|
||||
x++
|
||||
}
|
||||
queries := make([]qm.QueryMod, 0, x)
|
||||
if limit > 0 {
|
||||
queries = append(queries, qm.Limit(limit))
|
||||
}
|
||||
|
||||
@@ -285,11 +285,11 @@ func (d *Dispatcher) subscribe(id uuid.UUID) (chan interface{}, error) {
|
||||
|
||||
// Read lock to read route list
|
||||
d.rMtx.RLock()
|
||||
_, ok := d.routes[id]
|
||||
d.rMtx.RUnlock()
|
||||
if !ok {
|
||||
if _, ok := d.routes[id]; !ok {
|
||||
d.rMtx.RUnlock()
|
||||
return nil, errors.New("dispatcher uuid not found in route list")
|
||||
}
|
||||
d.rMtx.RUnlock()
|
||||
|
||||
// Get an unused channel from the channel pool
|
||||
unusedChan, ok := d.outbound.Get().(chan interface{})
|
||||
@@ -314,11 +314,11 @@ func (d *Dispatcher) unsubscribe(id uuid.UUID, usedChan chan interface{}) error
|
||||
|
||||
// Read lock to read route list
|
||||
d.rMtx.RLock()
|
||||
_, ok := d.routes[id]
|
||||
d.rMtx.RUnlock()
|
||||
if !ok {
|
||||
if _, ok := d.routes[id]; !ok {
|
||||
d.rMtx.RUnlock()
|
||||
return errors.New("dispatcher uuid does not reference any channels")
|
||||
}
|
||||
d.rMtx.RUnlock()
|
||||
|
||||
// Lock for write to delete references
|
||||
d.rMtx.Lock()
|
||||
|
||||
@@ -71,7 +71,6 @@ type job struct {
|
||||
type Mux struct {
|
||||
// Reference to the main running dispatch service
|
||||
d *Dispatcher
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
// Pipe defines an outbound object to the desired routine
|
||||
|
||||
@@ -112,8 +112,8 @@ func (m *apiServerManager) newRouter(isREST bool) *mux.Router {
|
||||
if common.ExtractPort(m.websocketListenAddress) == 80 {
|
||||
m.websocketListenAddress = common.ExtractHost(m.websocketListenAddress)
|
||||
} else {
|
||||
m.websocketListenAddress = strings.Join([]string{common.ExtractHost(m.websocketListenAddress),
|
||||
strconv.Itoa(common.ExtractPort(m.websocketListenAddress))}, ":")
|
||||
m.websocketListenAddress = common.ExtractHost(m.websocketListenAddress) + ":" +
|
||||
strconv.Itoa(common.ExtractPort(m.websocketListenAddress))
|
||||
}
|
||||
|
||||
if isREST {
|
||||
@@ -302,11 +302,13 @@ func (m *apiServerManager) getIndex(w http.ResponseWriter, _ *http.Request) {
|
||||
|
||||
// getAllActiveOrderbooks returns all enabled exchanges orderbooks
|
||||
func getAllActiveOrderbooks(m iExchangeManager) []EnabledExchangeOrderbooks {
|
||||
var orderbookData []EnabledExchangeOrderbooks
|
||||
exchanges, err := m.GetExchanges()
|
||||
if err != nil {
|
||||
log.Errorf(log.APIServerMgr, "Cannot get exchanges: %v", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
orderbookData := make([]EnabledExchangeOrderbooks, 0, len(exchanges))
|
||||
for x := range exchanges {
|
||||
assets := exchanges[x].GetAssetTypes(true)
|
||||
exchName := exchanges[x].GetName()
|
||||
@@ -342,11 +344,13 @@ func getAllActiveOrderbooks(m iExchangeManager) []EnabledExchangeOrderbooks {
|
||||
|
||||
// getAllActiveTickers returns all enabled exchanges tickers
|
||||
func getAllActiveTickers(m iExchangeManager) []EnabledExchangeCurrencies {
|
||||
var tickers []EnabledExchangeCurrencies
|
||||
exchanges, err := m.GetExchanges()
|
||||
if err != nil {
|
||||
log.Errorf(log.APIServerMgr, "Cannot get exchanges: %v", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
tickers := make([]EnabledExchangeCurrencies, 0, len(exchanges))
|
||||
for x := range exchanges {
|
||||
assets := exchanges[x].GetAssetTypes(true)
|
||||
exchName := exchanges[x].GetName()
|
||||
@@ -382,11 +386,13 @@ func getAllActiveTickers(m iExchangeManager) []EnabledExchangeCurrencies {
|
||||
|
||||
// getAllActiveAccounts returns all enabled exchanges accounts
|
||||
func getAllActiveAccounts(m iExchangeManager) []AllEnabledExchangeAccounts {
|
||||
var accounts []AllEnabledExchangeAccounts
|
||||
exchanges, err := m.GetExchanges()
|
||||
if err != nil {
|
||||
log.Errorf(log.APIServerMgr, "Cannot get exchanges: %v", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
accounts := make([]AllEnabledExchangeAccounts, 0, len(exchanges))
|
||||
for x := range exchanges {
|
||||
assets := exchanges[x].GetAssetTypes(true)
|
||||
exchName := exchanges[x].GetName()
|
||||
@@ -680,12 +686,17 @@ func (m *apiServerManager) WebsocketClientHandler(w http.ResponseWriter, r *http
|
||||
}
|
||||
|
||||
func wsAuth(client *websocketClient, data interface{}) error {
|
||||
d, ok := data.([]byte)
|
||||
if !ok {
|
||||
return errors.New("unable to type assert data")
|
||||
}
|
||||
|
||||
wsResp := WebsocketEventResponse{
|
||||
Event: "auth",
|
||||
}
|
||||
|
||||
var auth WebsocketAuth
|
||||
err := json.Unmarshal(data.([]byte), &auth)
|
||||
err := json.Unmarshal(d, &auth)
|
||||
if err != nil {
|
||||
wsResp.Error = err.Error()
|
||||
sendErr := client.SendWebsocketMessage(wsResp)
|
||||
@@ -738,11 +749,16 @@ func wsGetConfig(client *websocketClient, _ interface{}) error {
|
||||
}
|
||||
|
||||
func wsSaveConfig(client *websocketClient, data interface{}) error {
|
||||
d, ok := data.([]byte)
|
||||
if !ok {
|
||||
return errors.New("unable to type assert data")
|
||||
}
|
||||
|
||||
wsResp := WebsocketEventResponse{
|
||||
Event: "SaveConfig",
|
||||
}
|
||||
var respCfg config.Config
|
||||
err := json.Unmarshal(data.([]byte), &respCfg)
|
||||
err := json.Unmarshal(d, &respCfg)
|
||||
if err != nil {
|
||||
wsResp.Error = err.Error()
|
||||
sendErr := client.SendWebsocketMessage(wsResp)
|
||||
@@ -794,11 +810,16 @@ func wsGetTickers(client *websocketClient, data interface{}) error {
|
||||
}
|
||||
|
||||
func wsGetTicker(client *websocketClient, data interface{}) error {
|
||||
d, ok := data.([]byte)
|
||||
if !ok {
|
||||
return errors.New("unable to type assert data")
|
||||
}
|
||||
|
||||
wsResp := WebsocketEventResponse{
|
||||
Event: "GetTicker",
|
||||
}
|
||||
var tickerReq WebsocketOrderbookTickerRequest
|
||||
err := json.Unmarshal(data.([]byte), &tickerReq)
|
||||
err := json.Unmarshal(d, &tickerReq)
|
||||
if err != nil {
|
||||
wsResp.Error = err.Error()
|
||||
sendErr := client.SendWebsocketMessage(wsResp)
|
||||
@@ -849,11 +870,16 @@ func wsGetOrderbooks(client *websocketClient, data interface{}) error {
|
||||
}
|
||||
|
||||
func wsGetOrderbook(client *websocketClient, data interface{}) error {
|
||||
d, ok := data.([]byte)
|
||||
if !ok {
|
||||
return errors.New("unable to type assert data")
|
||||
}
|
||||
|
||||
wsResp := WebsocketEventResponse{
|
||||
Event: "GetOrderbook",
|
||||
}
|
||||
var orderbookReq WebsocketOrderbookTickerRequest
|
||||
err := json.Unmarshal(data.([]byte), &orderbookReq)
|
||||
err := json.Unmarshal(d, &orderbookReq)
|
||||
if err != nil {
|
||||
wsResp.Error = err.Error()
|
||||
sendErr := client.SendWebsocketMessage(wsResp)
|
||||
|
||||
@@ -3,7 +3,7 @@ package engine
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
@@ -253,7 +253,7 @@ func TestConfigAllJsonResponse(t *testing.T) {
|
||||
t.Error(err)
|
||||
}
|
||||
resp := makeHTTPGetRequest(t, c)
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
t.Error("Body not readable", err)
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ func (m *DataHistoryManager) retrieveJobs() ([]*DataHistoryJob, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var response []*DataHistoryJob
|
||||
response := make([]*DataHistoryJob, 0, len(dbJobs))
|
||||
for i := range dbJobs {
|
||||
dbJob, err := m.convertDBModelToJob(&dbJobs[i])
|
||||
if err != nil {
|
||||
@@ -1332,13 +1332,13 @@ func (m *DataHistoryManager) GetAllJobStatusBetween(start, end time.Time) ([]*Da
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var results []*DataHistoryJob
|
||||
results := make([]*DataHistoryJob, len(dbJobs))
|
||||
for i := range dbJobs {
|
||||
dbJob, err := m.convertDBModelToJob(&dbJobs[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
results = append(results, dbJob)
|
||||
results[i] = dbJob
|
||||
}
|
||||
return results, nil
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ func (m *ExchangeManager) GetExchanges() ([]exchange.IBotExchange, error) {
|
||||
}
|
||||
m.m.Lock()
|
||||
defer m.m.Unlock()
|
||||
var exchs []exchange.IBotExchange
|
||||
exchs := make([]exchange.IBotExchange, 0, len(m.exchanges))
|
||||
for _, x := range m.exchanges {
|
||||
exchs = append(exchs, x)
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ func TestExchangeManagerGetExchanges(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Error("no exchange manager found")
|
||||
}
|
||||
if exchanges != nil {
|
||||
if len(exchanges) != 0 {
|
||||
t.Error("unexpected value")
|
||||
}
|
||||
b := new(bitfinex.Bitfinex)
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"net"
|
||||
"os"
|
||||
@@ -326,8 +325,8 @@ func (bot *Engine) GetExchangeOTPByName(exchName string) (string, error) {
|
||||
|
||||
// GetAuthAPISupportedExchanges returns a list of auth api enabled exchanges
|
||||
func (bot *Engine) GetAuthAPISupportedExchanges() []string {
|
||||
var exchangeNames []string
|
||||
exchanges := bot.GetExchanges()
|
||||
exchangeNames := make([]string, 0, len(exchanges))
|
||||
for x := range exchanges {
|
||||
if !exchanges[x].GetAuthenticatedAPISupport(exchange.RestAuthentication) &&
|
||||
!exchanges[x].GetAuthenticatedAPISupport(exchange.WebsocketAuthentication) {
|
||||
@@ -443,7 +442,7 @@ func (bot *Engine) MapCurrenciesByExchange(p currency.Pairs, enabledExchangesOnl
|
||||
// GetExchangeNamesByCurrency returns a list of exchanges supporting
|
||||
// a currency pair based on whether the exchange is enabled or not
|
||||
func (bot *Engine) GetExchangeNamesByCurrency(p currency.Pair, enabled bool, assetType asset.Item) []string {
|
||||
var exchanges []string
|
||||
exchanges := make([]string, 0, len(bot.Config.Exchanges))
|
||||
for x := range bot.Config.Exchanges {
|
||||
if enabled != bot.Config.Exchanges[x].Enabled {
|
||||
continue
|
||||
@@ -862,7 +861,7 @@ func checkCerts(certDir string) error {
|
||||
return genCert(certDir)
|
||||
}
|
||||
|
||||
pemData, err := ioutil.ReadFile(certFile)
|
||||
pemData, err := os.ReadFile(certFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to open TLS cert file: %s", err)
|
||||
}
|
||||
|
||||
@@ -755,12 +755,9 @@ func TestGetSpecificOrderbook(t *testing.T) {
|
||||
t.Parallel()
|
||||
e := CreateTestBot(t)
|
||||
|
||||
var bids []orderbook.Item
|
||||
bids = append(bids, orderbook.Item{Price: 1000, Amount: 1})
|
||||
|
||||
base := orderbook.Base{
|
||||
Pair: currency.NewPair(currency.BTC, currency.USD),
|
||||
Bids: bids,
|
||||
Bids: []orderbook.Item{{Price: 1000, Amount: 1}},
|
||||
Exchange: "Bitstamp",
|
||||
Asset: asset.Spot,
|
||||
}
|
||||
|
||||
@@ -383,8 +383,7 @@ func TestExists(t *testing.T) {
|
||||
if err := m.orderStore.add(o); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
b := m.orderStore.exists(o)
|
||||
if !b {
|
||||
if b := m.orderStore.exists(o); !b {
|
||||
t.Error("Expected true")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ func (m *portfolioManager) seedExchangeAccountInfo(accounts []account.Holdings)
|
||||
|
||||
// getExchangeAccountInfo returns all the current enabled exchanges
|
||||
func (m *portfolioManager) getExchangeAccountInfo(exchanges []exchange.IBotExchange) []account.Holdings {
|
||||
var response []account.Holdings
|
||||
response := make([]account.Holdings, 0, len(exchanges))
|
||||
for x := range exchanges {
|
||||
if exchanges[x] == nil || !exchanges[x].IsEnabled() {
|
||||
continue
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
@@ -398,15 +397,16 @@ func (s *RPCServer) GetTicker(ctx context.Context, r *gctrpc.GetTickerRequest) (
|
||||
// enabled currency pairs
|
||||
func (s *RPCServer) GetTickers(ctx context.Context, _ *gctrpc.GetTickersRequest) (*gctrpc.GetTickersResponse, error) {
|
||||
activeTickers := s.GetAllActiveTickers(ctx)
|
||||
var tickers []*gctrpc.Tickers
|
||||
tickers := make([]*gctrpc.Tickers, len(activeTickers))
|
||||
|
||||
for x := range activeTickers {
|
||||
t := &gctrpc.Tickers{
|
||||
Exchange: activeTickers[x].ExchangeName,
|
||||
Tickers: make([]*gctrpc.TickerResponse, len(activeTickers[x].ExchangeValues)),
|
||||
}
|
||||
for y := range activeTickers[x].ExchangeValues {
|
||||
val := activeTickers[x].ExchangeValues[y]
|
||||
t.Tickers = append(t.Tickers, &gctrpc.TickerResponse{
|
||||
t.Tickers[y] = &gctrpc.TickerResponse{
|
||||
Pair: &gctrpc.CurrencyPair{
|
||||
Delimiter: val.Pair.Delimiter,
|
||||
Base: val.Pair.Base.String(),
|
||||
@@ -420,9 +420,9 @@ func (s *RPCServer) GetTickers(ctx context.Context, _ *gctrpc.GetTickersRequest)
|
||||
Ask: val.Ask,
|
||||
Volume: val.Volume,
|
||||
PriceAth: val.PriceATH,
|
||||
})
|
||||
}
|
||||
}
|
||||
tickers = append(tickers, t)
|
||||
tickers[x] = t
|
||||
}
|
||||
|
||||
return &gctrpc.GetTickersResponse{Tickers: tickers}, nil
|
||||
@@ -489,7 +489,7 @@ func (s *RPCServer) GetOrderbooks(ctx context.Context, _ *gctrpc.GetOrderbooksRe
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var obResponse []*gctrpc.Orderbooks
|
||||
obResponse := make([]*gctrpc.Orderbooks, 0, len(exchanges))
|
||||
var obs []*gctrpc.OrderbookResponse
|
||||
for x := range exchanges {
|
||||
if !exchanges[x].IsEnabled() {
|
||||
@@ -523,19 +523,20 @@ func (s *RPCServer) GetOrderbooks(ctx context.Context, _ *gctrpc.GetOrderbooksRe
|
||||
},
|
||||
AssetType: assets[y].String(),
|
||||
LastUpdated: s.unixTimestamp(resp.LastUpdated),
|
||||
Bids: make([]*gctrpc.OrderbookItem, len(resp.Bids)),
|
||||
Asks: make([]*gctrpc.OrderbookItem, len(resp.Asks)),
|
||||
}
|
||||
for i := range resp.Bids {
|
||||
ob.Bids = append(ob.Bids, &gctrpc.OrderbookItem{
|
||||
ob.Bids[i] = &gctrpc.OrderbookItem{
|
||||
Amount: resp.Bids[i].Amount,
|
||||
Price: resp.Bids[i].Price,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for i := range resp.Asks {
|
||||
ob.Asks = append(ob.Asks, &gctrpc.OrderbookItem{
|
||||
ob.Asks[i] = &gctrpc.OrderbookItem{
|
||||
Amount: resp.Asks[i].Amount,
|
||||
Price: resp.Asks[i].Price,
|
||||
})
|
||||
}
|
||||
}
|
||||
obs = append(obs, ob)
|
||||
}
|
||||
@@ -600,7 +601,7 @@ func (s *RPCServer) UpdateAccountInfo(ctx context.Context, r *gctrpc.GetAccountI
|
||||
}
|
||||
|
||||
func createAccountInfoRequest(h account.Holdings) (*gctrpc.GetAccountInfoResponse, error) {
|
||||
var accounts []*gctrpc.Account
|
||||
accounts := make([]*gctrpc.Account, len(h.Accounts))
|
||||
for x := range h.Accounts {
|
||||
var a gctrpc.Account
|
||||
a.Id = h.Accounts[x].ID
|
||||
@@ -621,7 +622,7 @@ func createAccountInfoRequest(h account.Holdings) (*gctrpc.GetAccountInfoRespons
|
||||
Borrowed: y.Borrowed,
|
||||
})
|
||||
}
|
||||
accounts = append(accounts, &a)
|
||||
accounts[x] = &a
|
||||
}
|
||||
|
||||
return &gctrpc.GetAccountInfoResponse{Exchange: h.Exchange, Accounts: accounts}, nil
|
||||
@@ -649,20 +650,20 @@ func (s *RPCServer) GetAccountInfoStream(r *gctrpc.GetAccountInfoRequest, stream
|
||||
return err
|
||||
}
|
||||
|
||||
var accounts []*gctrpc.Account
|
||||
accounts := make([]*gctrpc.Account, len(initAcc.Accounts))
|
||||
for x := range initAcc.Accounts {
|
||||
var subAccounts []*gctrpc.AccountCurrencyInfo
|
||||
subAccounts := make([]*gctrpc.AccountCurrencyInfo, len(initAcc.Accounts[x].Currencies))
|
||||
for y := range initAcc.Accounts[x].Currencies {
|
||||
subAccounts = append(subAccounts, &gctrpc.AccountCurrencyInfo{
|
||||
subAccounts[y] = &gctrpc.AccountCurrencyInfo{
|
||||
Currency: initAcc.Accounts[x].Currencies[y].CurrencyName.String(),
|
||||
TotalValue: initAcc.Accounts[x].Currencies[y].Total,
|
||||
Hold: initAcc.Accounts[x].Currencies[y].Hold,
|
||||
})
|
||||
}
|
||||
}
|
||||
accounts = append(accounts, &gctrpc.Account{
|
||||
accounts[x] = &gctrpc.Account{
|
||||
Id: initAcc.Accounts[x].ID,
|
||||
Currencies: subAccounts,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
err = stream.Send(&gctrpc.GetAccountInfoResponse{
|
||||
@@ -691,37 +692,37 @@ func (s *RPCServer) GetAccountInfoStream(r *gctrpc.GetAccountInfoRequest, stream
|
||||
return errDispatchSystem
|
||||
}
|
||||
|
||||
d := *data.(*interface{})
|
||||
if d == nil {
|
||||
d, ok := data.(*interface{})
|
||||
if !ok {
|
||||
return errors.New("unable to type assert data")
|
||||
}
|
||||
|
||||
acc, ok := d.(account.Holdings)
|
||||
dd := *d
|
||||
acc, ok := dd.(account.Holdings)
|
||||
if !ok {
|
||||
return errors.New("unable to type assert account holdings data")
|
||||
}
|
||||
|
||||
var accounts []*gctrpc.Account
|
||||
accounts := make([]*gctrpc.Account, len(acc.Accounts))
|
||||
for x := range acc.Accounts {
|
||||
var subAccounts []*gctrpc.AccountCurrencyInfo
|
||||
subAccounts := make([]*gctrpc.AccountCurrencyInfo, len(acc.Accounts[x].Currencies))
|
||||
for y := range acc.Accounts[x].Currencies {
|
||||
subAccounts = append(subAccounts, &gctrpc.AccountCurrencyInfo{
|
||||
subAccounts[y] = &gctrpc.AccountCurrencyInfo{
|
||||
Currency: acc.Accounts[x].Currencies[y].CurrencyName.String(),
|
||||
TotalValue: acc.Accounts[x].Currencies[y].Total,
|
||||
Hold: acc.Accounts[x].Currencies[y].Hold,
|
||||
})
|
||||
}
|
||||
}
|
||||
accounts = append(accounts, &gctrpc.Account{
|
||||
accounts[x] = &gctrpc.Account{
|
||||
Id: acc.Accounts[x].ID,
|
||||
Currencies: subAccounts,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
err := stream.Send(&gctrpc.GetAccountInfoResponse{
|
||||
if err := stream.Send(&gctrpc.GetAccountInfoResponse{
|
||||
Exchange: acc.Exchange,
|
||||
Accounts: accounts,
|
||||
})
|
||||
if err != nil {
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -734,15 +735,15 @@ func (s *RPCServer) GetConfig(_ context.Context, _ *gctrpc.GetConfigRequest) (*g
|
||||
|
||||
// GetPortfolio returns the portfoliomanager details
|
||||
func (s *RPCServer) GetPortfolio(_ context.Context, _ *gctrpc.GetPortfolioRequest) (*gctrpc.GetPortfolioResponse, error) {
|
||||
var addrs []*gctrpc.PortfolioAddress
|
||||
botAddrs := s.portfolioManager.GetAddresses()
|
||||
addrs := make([]*gctrpc.PortfolioAddress, len(botAddrs))
|
||||
for x := range botAddrs {
|
||||
addrs = append(addrs, &gctrpc.PortfolioAddress{
|
||||
addrs[x] = &gctrpc.PortfolioAddress{
|
||||
Address: botAddrs[x].Address,
|
||||
CoinType: botAddrs[x].CoinType.String(),
|
||||
Description: botAddrs[x].Description,
|
||||
Balance: botAddrs[x].Balance,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
resp := &gctrpc.GetPortfolioResponse{
|
||||
@@ -838,9 +839,9 @@ func (s *RPCServer) GetForexProviders(_ context.Context, _ *gctrpc.GetForexProvi
|
||||
return nil, fmt.Errorf("forex providers is empty")
|
||||
}
|
||||
|
||||
var forexProviders []*gctrpc.ForexProvider
|
||||
forexProviders := make([]*gctrpc.ForexProvider, len(providers))
|
||||
for x := range providers {
|
||||
forexProviders = append(forexProviders, &gctrpc.ForexProvider{
|
||||
forexProviders[x] = &gctrpc.ForexProvider{
|
||||
Name: providers[x].Name,
|
||||
Enabled: providers[x].Enabled,
|
||||
Verbose: providers[x].Verbose,
|
||||
@@ -848,7 +849,7 @@ func (s *RPCServer) GetForexProviders(_ context.Context, _ *gctrpc.GetForexProvi
|
||||
ApiKey: providers[x].APIKey,
|
||||
ApiKeyLevel: int64(providers[x].APIKeyLvl),
|
||||
PrimaryProvider: providers[x].PrimaryProvider,
|
||||
})
|
||||
}
|
||||
}
|
||||
return &gctrpc.GetForexProvidersResponse{ForexProviders: forexProviders}, nil
|
||||
}
|
||||
@@ -864,7 +865,7 @@ func (s *RPCServer) GetForexRates(_ context.Context, _ *gctrpc.GetForexRatesRequ
|
||||
return nil, fmt.Errorf("forex rates is empty")
|
||||
}
|
||||
|
||||
var forexRates []*gctrpc.ForexRatesConversion
|
||||
forexRates := make([]*gctrpc.ForexRatesConversion, 0, len(rates))
|
||||
for x := range rates {
|
||||
rate, err := rates[x].GetRate()
|
||||
if err != nil {
|
||||
@@ -952,9 +953,9 @@ func (s *RPCServer) GetOrders(ctx context.Context, r *gctrpc.GetOrdersRequest) (
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var orders []*gctrpc.OrderDetails
|
||||
orders := make([]*gctrpc.OrderDetails, len(resp))
|
||||
for x := range resp {
|
||||
var trades []*gctrpc.TradeHistory
|
||||
trades := make([]*gctrpc.TradeHistory, len(resp[x].Trades))
|
||||
for i := range resp[x].Trades {
|
||||
t := &gctrpc.TradeHistory{
|
||||
Id: resp[x].Trades[i].TID,
|
||||
@@ -969,7 +970,7 @@ func (s *RPCServer) GetOrders(ctx context.Context, r *gctrpc.GetOrdersRequest) (
|
||||
if !resp[x].Trades[i].Timestamp.IsZero() {
|
||||
t.CreationTime = s.unixTimestamp(resp[x].Trades[i].Timestamp)
|
||||
}
|
||||
trades = append(trades, t)
|
||||
trades[i] = t
|
||||
}
|
||||
o := &gctrpc.OrderDetails{
|
||||
Exchange: r.Exchange,
|
||||
@@ -994,7 +995,7 @@ func (s *RPCServer) GetOrders(ctx context.Context, r *gctrpc.GetOrdersRequest) (
|
||||
if !resp[x].LastUpdated.IsZero() {
|
||||
o.UpdateTime = s.unixTimestamp(resp[x].LastUpdated)
|
||||
}
|
||||
orders = append(orders, o)
|
||||
orders[x] = o
|
||||
}
|
||||
|
||||
return &gctrpc.GetOrdersResponse{Orders: orders}, nil
|
||||
@@ -1041,9 +1042,9 @@ func (s *RPCServer) GetManagedOrders(_ context.Context, r *gctrpc.GetOrdersReque
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var orders []*gctrpc.OrderDetails
|
||||
orders := make([]*gctrpc.OrderDetails, len(resp))
|
||||
for x := range resp {
|
||||
var trades []*gctrpc.TradeHistory
|
||||
trades := make([]*gctrpc.TradeHistory, len(resp[x].Trades))
|
||||
for i := range resp[x].Trades {
|
||||
t := &gctrpc.TradeHistory{
|
||||
Id: resp[x].Trades[i].TID,
|
||||
@@ -1058,7 +1059,7 @@ func (s *RPCServer) GetManagedOrders(_ context.Context, r *gctrpc.GetOrdersReque
|
||||
if !resp[x].Trades[i].Timestamp.IsZero() {
|
||||
t.CreationTime = s.unixTimestamp(resp[x].Trades[i].Timestamp)
|
||||
}
|
||||
trades = append(trades, t)
|
||||
trades[i] = t
|
||||
}
|
||||
o := &gctrpc.OrderDetails{
|
||||
Exchange: r.Exchange,
|
||||
@@ -1083,7 +1084,7 @@ func (s *RPCServer) GetManagedOrders(_ context.Context, r *gctrpc.GetOrdersReque
|
||||
if !resp[x].LastUpdated.IsZero() {
|
||||
o.UpdateTime = s.unixTimestamp(resp[x].LastUpdated)
|
||||
}
|
||||
orders = append(orders, o)
|
||||
orders[x] = o
|
||||
}
|
||||
|
||||
return &gctrpc.GetOrdersResponse{Orders: orders}, nil
|
||||
@@ -1128,9 +1129,9 @@ func (s *RPCServer) GetOrder(ctx context.Context, r *gctrpc.GetOrderRequest) (*g
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error whilst trying to retrieve info for order %s: %w", r.OrderId, err)
|
||||
}
|
||||
var trades []*gctrpc.TradeHistory
|
||||
trades := make([]*gctrpc.TradeHistory, len(result.Trades))
|
||||
for i := range result.Trades {
|
||||
trades = append(trades, &gctrpc.TradeHistory{
|
||||
trades[i] = &gctrpc.TradeHistory{
|
||||
CreationTime: s.unixTimestamp(result.Trades[i].Timestamp),
|
||||
Id: result.Trades[i].TID,
|
||||
Price: result.Trades[i].Price,
|
||||
@@ -1140,7 +1141,7 @@ func (s *RPCServer) GetOrder(ctx context.Context, r *gctrpc.GetOrderRequest) (*g
|
||||
OrderSide: result.Trades[i].Side.String(),
|
||||
Fee: result.Trades[i].Fee,
|
||||
Total: result.Trades[i].Total,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var creationTime, updateTime int64
|
||||
@@ -1217,14 +1218,14 @@ func (s *RPCServer) SubmitOrder(ctx context.Context, r *gctrpc.SubmitOrderReques
|
||||
return &gctrpc.SubmitOrderResponse{}, err
|
||||
}
|
||||
|
||||
var trades []*gctrpc.Trades
|
||||
trades := make([]*gctrpc.Trades, len(resp.Trades))
|
||||
for i := range resp.Trades {
|
||||
trades = append(trades, &gctrpc.Trades{
|
||||
trades[i] = &gctrpc.Trades{
|
||||
Amount: resp.Trades[i].Amount,
|
||||
Price: resp.Trades[i].Price,
|
||||
Fee: resp.Trades[i].Fee,
|
||||
FeeAsset: resp.Trades[i].FeeAsset,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return &gctrpc.SubmitOrderResponse{
|
||||
@@ -1408,18 +1409,19 @@ func (s *RPCServer) CancelBatchOrders(ctx context.Context, r *gctrpc.CancelBatch
|
||||
}
|
||||
|
||||
status := make(map[string]string)
|
||||
var request []order.Cancel
|
||||
orders := strings.Split(r.OrdersId, ",")
|
||||
for _, orderID := range orders {
|
||||
request := make([]order.Cancel, len(orders))
|
||||
for x := range orders {
|
||||
orderID := orders[x]
|
||||
status[orderID] = order.Cancelled.String()
|
||||
request = append(request, order.Cancel{
|
||||
request[x] = order.Cancel{
|
||||
AccountID: r.AccountId,
|
||||
ID: orderID,
|
||||
Side: order.Side(r.Side),
|
||||
WalletAddress: r.WalletAddress,
|
||||
Pair: pair,
|
||||
AssetType: assetType,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Change to order manager
|
||||
@@ -2118,12 +2120,13 @@ func (s *RPCServer) GetExchangeOrderbookStream(r *gctrpc.GetExchangeOrderbookStr
|
||||
return errDispatchSystem
|
||||
}
|
||||
|
||||
d := *data.(*interface{})
|
||||
if d == nil {
|
||||
d, ok := data.(*interface{})
|
||||
if !ok {
|
||||
return errors.New("unable to type assert data")
|
||||
}
|
||||
|
||||
ob, ok := d.(orderbook.Base)
|
||||
dd := *d
|
||||
ob, ok := dd.(orderbook.Base)
|
||||
if !ok {
|
||||
return errors.New("unable to type assert orderbook data")
|
||||
}
|
||||
@@ -2201,12 +2204,13 @@ func (s *RPCServer) GetTickerStream(r *gctrpc.GetTickerStreamRequest, stream gct
|
||||
return errDispatchSystem
|
||||
}
|
||||
|
||||
d := *data.(*interface{})
|
||||
if d == nil {
|
||||
d, ok := data.(*interface{})
|
||||
if !ok {
|
||||
return errors.New("unable to type assert data")
|
||||
}
|
||||
|
||||
t, ok := d.(ticker.Price)
|
||||
dd := *d
|
||||
t, ok := dd.(ticker.Price)
|
||||
if !ok {
|
||||
return errors.New("unable to type assert ticker data")
|
||||
}
|
||||
@@ -2259,12 +2263,13 @@ func (s *RPCServer) GetExchangeTickerStream(r *gctrpc.GetExchangeTickerStreamReq
|
||||
return errDispatchSystem
|
||||
}
|
||||
|
||||
d := *data.(*interface{})
|
||||
if d == nil {
|
||||
d, ok := data.(*interface{})
|
||||
if !ok {
|
||||
return errors.New("unable to type assert data")
|
||||
}
|
||||
|
||||
t, ok := d.(ticker.Price)
|
||||
dd := *d
|
||||
t, ok := dd.(ticker.Price)
|
||||
if !ok {
|
||||
return errors.New("unable to type assert ticker data")
|
||||
}
|
||||
@@ -2453,16 +2458,16 @@ func (s *RPCServer) GetHistoricCandles(ctx context.Context, r *gctrpc.GetHistori
|
||||
}
|
||||
|
||||
func fillMissingCandlesWithStoredTrades(startTime, endTime time.Time, klineItem *kline.Item) (*kline.Item, error) {
|
||||
var response kline.Item
|
||||
var candleTimes []time.Time
|
||||
candleTimes := make([]time.Time, len(klineItem.Candles))
|
||||
for i := range klineItem.Candles {
|
||||
candleTimes = append(candleTimes, klineItem.Candles[i].Time)
|
||||
candleTimes[i] = klineItem.Candles[i].Time
|
||||
}
|
||||
ranges, err := timeperiods.FindTimeRangesContainingData(startTime, endTime, klineItem.Interval.Duration(), candleTimes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var response kline.Item
|
||||
for i := range ranges {
|
||||
if ranges[i].HasDataInRange {
|
||||
continue
|
||||
@@ -2552,24 +2557,30 @@ func (s *RPCServer) GCTScriptQuery(_ context.Context, r *gctrpc.GCTScriptQueryRe
|
||||
return &gctrpc.GCTScriptQueryResponse{Status: MsgStatusError, Data: err.Error()}, nil
|
||||
}
|
||||
|
||||
if v, f := gctscript.AllVMSync.Load(UUID); f {
|
||||
resp := &gctrpc.GCTScriptQueryResponse{
|
||||
Status: MsgStatusOK,
|
||||
Script: &gctrpc.GCTScript{
|
||||
Name: v.(*gctscript.VM).ShortName(),
|
||||
UUID: v.(*gctscript.VM).ID.String(),
|
||||
Path: v.(*gctscript.VM).Path,
|
||||
NextRun: v.(*gctscript.VM).NextRun.String(),
|
||||
},
|
||||
}
|
||||
data, err := v.(*gctscript.VM).Read()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp.Data = string(data)
|
||||
return resp, nil
|
||||
v, f := gctscript.AllVMSync.Load(UUID)
|
||||
if !f {
|
||||
return &gctrpc.GCTScriptQueryResponse{Status: MsgStatusError, Data: "UUID not found"}, nil
|
||||
}
|
||||
return &gctrpc.GCTScriptQueryResponse{Status: MsgStatusError, Data: "UUID not found"}, nil
|
||||
|
||||
vm, ok := v.(*gctscript.VM)
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert gctscript.VM")
|
||||
}
|
||||
resp := &gctrpc.GCTScriptQueryResponse{
|
||||
Status: MsgStatusOK,
|
||||
Script: &gctrpc.GCTScript{
|
||||
Name: vm.ShortName(),
|
||||
UUID: vm.ID.String(),
|
||||
Path: vm.Path,
|
||||
NextRun: vm.NextRun.String(),
|
||||
},
|
||||
}
|
||||
data, err := vm.Read()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resp.Data = string(data)
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GCTScriptExecute execute a script
|
||||
@@ -2614,15 +2625,21 @@ func (s *RPCServer) GCTScriptStop(_ context.Context, r *gctrpc.GCTScriptStopRequ
|
||||
return &gctrpc.GenericResponse{Status: MsgStatusError, Data: err.Error()}, nil // nolint:nilerr // error is returned in the generic response
|
||||
}
|
||||
|
||||
if v, f := gctscript.AllVMSync.Load(UUID); f {
|
||||
err = v.(*gctscript.VM).Shutdown()
|
||||
status := " terminated"
|
||||
if err != nil {
|
||||
status = " " + err.Error()
|
||||
}
|
||||
return &gctrpc.GenericResponse{Status: MsgStatusOK, Data: v.(*gctscript.VM).ID.String() + status}, nil
|
||||
v, f := gctscript.AllVMSync.Load(UUID)
|
||||
if !f {
|
||||
return &gctrpc.GenericResponse{Status: MsgStatusError, Data: "no running script found"}, nil
|
||||
}
|
||||
return &gctrpc.GenericResponse{Status: MsgStatusError, Data: "no running script found"}, nil
|
||||
|
||||
vm, ok := v.(*gctscript.VM)
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert gctscript.VM")
|
||||
}
|
||||
err = vm.Shutdown()
|
||||
status := " terminated"
|
||||
if err != nil {
|
||||
status = " " + err.Error()
|
||||
}
|
||||
return &gctrpc.GenericResponse{Status: MsgStatusOK, Data: vm.ID.String() + status}, nil
|
||||
}
|
||||
|
||||
// GCTScriptUpload upload a new script to ScriptPath
|
||||
@@ -2642,7 +2659,7 @@ func (s *RPCServer) GCTScriptUpload(_ context.Context, r *gctrpc.GCTScriptUpload
|
||||
return nil, fmt.Errorf("%s script found and overwrite set to false", r.ScriptName)
|
||||
}
|
||||
f := filepath.Join(gctscript.ScriptPath, "version_history")
|
||||
err = os.MkdirAll(f, 0770)
|
||||
err = os.MkdirAll(f, file.DefaultPermissionOctal)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -2726,7 +2743,7 @@ func (s *RPCServer) GCTScriptReadScript(_ context.Context, r *gctrpc.GCTScriptRe
|
||||
if !strings.HasPrefix(filename, filepath.Clean(gctscript.ScriptPath)+string(os.PathSeparator)) {
|
||||
return nil, fmt.Errorf("%s: invalid file path", filename)
|
||||
}
|
||||
data, err := ioutil.ReadFile(filename)
|
||||
data, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -3271,9 +3288,9 @@ func (s *RPCServer) FindMissingSavedCandleIntervals(_ context.Context, r *gctrpc
|
||||
Pair: r.Pair,
|
||||
MissingPeriods: []string{},
|
||||
}
|
||||
var candleTimes []time.Time
|
||||
candleTimes := make([]time.Time, len(klineItem.Candles))
|
||||
for i := range klineItem.Candles {
|
||||
candleTimes = append(candleTimes, klineItem.Candles[i].Time)
|
||||
candleTimes[i] = klineItem.Candles[i].Time
|
||||
}
|
||||
var ranges []timeperiods.TimeRange
|
||||
ranges, err = timeperiods.FindTimeRangesContainingData(start, end, klineItem.Interval.Duration(), candleTimes)
|
||||
@@ -3373,9 +3390,9 @@ func (s *RPCServer) FindMissingSavedTradeIntervals(_ context.Context, r *gctrpc.
|
||||
Pair: r.Pair,
|
||||
MissingPeriods: []string{},
|
||||
}
|
||||
var tradeTimes []time.Time
|
||||
tradeTimes := make([]time.Time, len(trades))
|
||||
for i := range trades {
|
||||
tradeTimes = append(tradeTimes, trades[i].Timestamp)
|
||||
tradeTimes[i] = trades[i].Timestamp
|
||||
}
|
||||
var ranges []timeperiods.TimeRange
|
||||
ranges, err = timeperiods.FindTimeRangesContainingData(start, end, time.Hour, tradeTimes)
|
||||
@@ -3892,9 +3909,9 @@ func (s *RPCServer) GetActiveDataHistoryJobs(_ context.Context, _ *gctrpc.GetInf
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var response []*gctrpc.DataHistoryJob
|
||||
response := make([]*gctrpc.DataHistoryJob, len(jobs))
|
||||
for i := range jobs {
|
||||
response = append(response, &gctrpc.DataHistoryJob{
|
||||
response[i] = &gctrpc.DataHistoryJob{
|
||||
Id: jobs[i].ID.String(),
|
||||
Nickname: jobs[i].Nickname,
|
||||
Exchange: jobs[i].Exchange,
|
||||
@@ -3919,7 +3936,7 @@ func (s *RPCServer) GetActiveDataHistoryJobs(_ context.Context, _ *gctrpc.GetInf
|
||||
SecondaryExchangeName: jobs[i].SecondaryExchangeSource,
|
||||
IssueTolerancePercentage: jobs[i].IssueTolerancePercentage,
|
||||
ReplaceOnIssue: jobs[i].ReplaceOnIssue,
|
||||
})
|
||||
}
|
||||
}
|
||||
return &gctrpc.DataHistoryJobs{Results: response}, nil
|
||||
}
|
||||
@@ -3946,9 +3963,9 @@ func (s *RPCServer) GetDataHistoryJobsBetween(_ context.Context, r *gctrpc.GetDa
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var respJobs []*gctrpc.DataHistoryJob
|
||||
respJobs := make([]*gctrpc.DataHistoryJob, len(jobs))
|
||||
for i := range jobs {
|
||||
respJobs = append(respJobs, &gctrpc.DataHistoryJob{
|
||||
respJobs[i] = &gctrpc.DataHistoryJob{
|
||||
Id: jobs[i].ID.String(),
|
||||
Nickname: jobs[i].Nickname,
|
||||
Exchange: jobs[i].Exchange,
|
||||
@@ -3973,7 +3990,7 @@ func (s *RPCServer) GetDataHistoryJobsBetween(_ context.Context, r *gctrpc.GetDa
|
||||
SecondaryExchangeName: jobs[i].SecondaryExchangeSource,
|
||||
IssueTolerancePercentage: jobs[i].IssueTolerancePercentage,
|
||||
ReplaceOnIssue: jobs[i].ReplaceOnIssue,
|
||||
})
|
||||
}
|
||||
}
|
||||
return &gctrpc.DataHistoryJobs{
|
||||
Results: respJobs,
|
||||
@@ -4309,17 +4326,15 @@ func (s *RPCServer) GetCollateral(ctx context.Context, r *gctrpc.GetCollateralRe
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var calculators []order.CollateralCalculator
|
||||
var acc *account.SubAccount
|
||||
var subAccounts []string
|
||||
|
||||
creds, err := exch.GetBase().GetCredentials(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
subAccounts := make([]string, len(ai.Accounts))
|
||||
var acc *account.SubAccount
|
||||
for i := range ai.Accounts {
|
||||
subAccounts = append(subAccounts, ai.Accounts[i].ID)
|
||||
subAccounts[i] = ai.Accounts[i].ID
|
||||
if ai.Accounts[i].ID == "main" && creds.SubAccount == "" {
|
||||
acc = &ai.Accounts[i]
|
||||
break
|
||||
@@ -4344,6 +4359,7 @@ func (s *RPCServer) GetCollateral(ctx context.Context, r *gctrpc.GetCollateralRe
|
||||
}
|
||||
}
|
||||
|
||||
calculators := make([]order.CollateralCalculator, 0, len(acc.Currencies))
|
||||
for i := range acc.Currencies {
|
||||
total := decimal.NewFromFloat(acc.Currencies[i].Total)
|
||||
free := decimal.NewFromFloat(acc.Currencies[i].AvailableWithoutBorrow)
|
||||
|
||||
@@ -99,7 +99,11 @@ func (m *WithdrawManager) WithdrawalEventByID(id string) (*withdraw.Response, er
|
||||
return nil, ErrNilSubsystem
|
||||
}
|
||||
if v := withdraw.Cache.Get(id); v != nil {
|
||||
return v.(*withdraw.Response), nil
|
||||
wdResp, ok := v.(*withdraw.Response)
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert withdraw.Response")
|
||||
}
|
||||
return wdResp, nil
|
||||
}
|
||||
|
||||
l, err := dbwithdraw.GetEventByUUID(id)
|
||||
|
||||
@@ -26,15 +26,13 @@ func CollectBalances(accountBalances map[string][]Balance, assetType asset.Item)
|
||||
return nil, fmt.Errorf("%s, %w", assetType, asset.ErrNotSupported)
|
||||
}
|
||||
|
||||
accounts = make([]SubAccount, len(accountBalances))
|
||||
i := 0
|
||||
accounts = make([]SubAccount, 0, len(accountBalances))
|
||||
for accountID, balances := range accountBalances {
|
||||
accounts[i] = SubAccount{
|
||||
accounts = append(accounts, SubAccount{
|
||||
ID: accountID,
|
||||
AssetType: assetType,
|
||||
Currencies: balances,
|
||||
}
|
||||
i++
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -42,16 +40,16 @@ func CollectBalances(accountBalances map[string][]Balance, assetType asset.Item)
|
||||
// SubscribeToExchangeAccount subcribes to your exchange account
|
||||
func SubscribeToExchangeAccount(exchange string) (dispatch.Pipe, error) {
|
||||
exchange = strings.ToLower(exchange)
|
||||
service.Lock()
|
||||
service.mu.Lock()
|
||||
|
||||
acc, ok := service.accounts[exchange]
|
||||
if !ok {
|
||||
service.Unlock()
|
||||
service.mu.Unlock()
|
||||
return dispatch.Pipe{},
|
||||
fmt.Errorf("%s exchange account holdings not found", exchange)
|
||||
}
|
||||
|
||||
defer service.Unlock()
|
||||
defer service.mu.Unlock()
|
||||
return service.mux.Subscribe(acc.ID)
|
||||
}
|
||||
|
||||
@@ -80,8 +78,8 @@ func GetHoldings(exch string, assetType asset.Item) (Holdings, error) {
|
||||
return Holdings{}, fmt.Errorf("assetType %v is invalid", assetType)
|
||||
}
|
||||
|
||||
service.Lock()
|
||||
defer service.Unlock()
|
||||
service.mu.Lock()
|
||||
defer service.mu.Unlock()
|
||||
h, ok := service.accounts[exch]
|
||||
if !ok {
|
||||
return Holdings{}, errors.New("exchange account holdings not found")
|
||||
@@ -97,22 +95,22 @@ func GetHoldings(exch string, assetType asset.Item) (Holdings, error) {
|
||||
// Update updates holdings with new account info
|
||||
func (s *Service) Update(a *Holdings) error {
|
||||
exch := strings.ToLower(a.Exchange)
|
||||
s.Lock()
|
||||
s.mu.Lock()
|
||||
acc, ok := s.accounts[exch]
|
||||
if !ok {
|
||||
id, err := s.mux.GetID()
|
||||
if err != nil {
|
||||
s.Unlock()
|
||||
s.mu.Unlock()
|
||||
return err
|
||||
}
|
||||
|
||||
s.accounts[exch] = &Account{h: a, ID: id}
|
||||
s.Unlock()
|
||||
s.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
acc.h.Accounts = a.Accounts
|
||||
defer s.Unlock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
return s.mux.Publish([]uuid.UUID{acc.ID}, acc.h)
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ var (
|
||||
type Service struct {
|
||||
accounts map[string]*Account
|
||||
mux *dispatch.Mux
|
||||
sync.Mutex
|
||||
mu sync.Mutex
|
||||
}
|
||||
|
||||
// Account holds a stream ID and a pointer to the exchange holdings
|
||||
|
||||
@@ -101,14 +101,14 @@ func (a *Alphapoint) UpdateAccountInfo(ctx context.Context, assetType asset.Item
|
||||
return response, err
|
||||
}
|
||||
|
||||
var balances []account.Balance
|
||||
balances := make([]account.Balance, len(acc.Currencies))
|
||||
for i := range acc.Currencies {
|
||||
balances = append(balances, account.Balance{
|
||||
balances[i] = account.Balance{
|
||||
CurrencyName: currency.NewCode(acc.Currencies[i].Name),
|
||||
Total: float64(acc.Currencies[i].Balance),
|
||||
Hold: float64(acc.Currencies[i].Hold),
|
||||
Free: float64(acc.Currencies[i].Balance) - float64(acc.Currencies[i].Hold),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
response.Accounts = append(response.Accounts, account.SubAccount{
|
||||
@@ -181,18 +181,20 @@ func (a *Alphapoint) UpdateOrderbook(ctx context.Context, p currency.Pair, asset
|
||||
return orderBook, err
|
||||
}
|
||||
|
||||
orderBook.Bids = make(orderbook.Items, len(orderbookNew.Bids))
|
||||
for x := range orderbookNew.Bids {
|
||||
orderBook.Bids = append(orderBook.Bids, orderbook.Item{
|
||||
orderBook.Bids[x] = orderbook.Item{
|
||||
Amount: orderbookNew.Bids[x].Quantity,
|
||||
Price: orderbookNew.Bids[x].Price,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
orderBook.Asks = make(orderbook.Items, len(orderbookNew.Asks))
|
||||
for x := range orderbookNew.Asks {
|
||||
orderBook.Asks = append(orderBook.Asks, orderbook.Item{
|
||||
orderBook.Asks[x] = orderbook.Item{
|
||||
Amount: orderbookNew.Asks[x].Quantity,
|
||||
Price: orderbookNew.Asks[x].Price,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
orderBook.Pair = p
|
||||
|
||||
@@ -60,9 +60,9 @@ func (a Item) String() string {
|
||||
|
||||
// Strings converts an asset type array to a string array
|
||||
func (a Items) Strings() []string {
|
||||
var assets []string
|
||||
assets := make([]string, len(a))
|
||||
for x := range a {
|
||||
assets = append(assets, string(a[x]))
|
||||
assets[x] = a[x].String()
|
||||
}
|
||||
return assets
|
||||
}
|
||||
|
||||
@@ -119,16 +119,15 @@ func (b *Binance) GetExchangeInfo(ctx context.Context) (ExchangeInfo, error) {
|
||||
// OrderBookDataRequestParams contains the following members
|
||||
// symbol: string of currency pair
|
||||
// limit: returned limit amount
|
||||
func (b *Binance) GetOrderBook(ctx context.Context, obd OrderBookDataRequestParams) (OrderBook, error) {
|
||||
var orderbook OrderBook
|
||||
func (b *Binance) GetOrderBook(ctx context.Context, obd OrderBookDataRequestParams) (*OrderBook, error) {
|
||||
if err := b.CheckLimit(obd.Limit); err != nil {
|
||||
return orderbook, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
params := url.Values{}
|
||||
symbol, err := b.FormatSymbol(obd.Symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return orderbook, err
|
||||
return nil, err
|
||||
}
|
||||
params.Set("symbol", symbol)
|
||||
params.Set("limit", fmt.Sprintf("%d", obd.Limit))
|
||||
@@ -138,52 +137,54 @@ func (b *Binance) GetOrderBook(ctx context.Context, obd OrderBookDataRequestPara
|
||||
exchange.RestSpotSupplementary,
|
||||
orderBookDepth+"?"+params.Encode(),
|
||||
orderbookLimit(obd.Limit), &resp); err != nil {
|
||||
return orderbook, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
orderbook := OrderBook{
|
||||
Bids: make([]OrderbookItem, len(resp.Bids)),
|
||||
Asks: make([]OrderbookItem, len(resp.Asks)),
|
||||
LastUpdateID: resp.LastUpdateID,
|
||||
}
|
||||
for x := range resp.Bids {
|
||||
price, err := strconv.ParseFloat(resp.Bids[x][0], 64)
|
||||
if err != nil {
|
||||
return orderbook, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
amount, err := strconv.ParseFloat(resp.Bids[x][1], 64)
|
||||
if err != nil {
|
||||
return orderbook, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
orderbook.Bids = append(orderbook.Bids, OrderbookItem{
|
||||
orderbook.Bids[x] = OrderbookItem{
|
||||
Price: price,
|
||||
Quantity: amount,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for x := range resp.Asks {
|
||||
price, err := strconv.ParseFloat(resp.Asks[x][0], 64)
|
||||
if err != nil {
|
||||
return orderbook, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
amount, err := strconv.ParseFloat(resp.Asks[x][1], 64)
|
||||
if err != nil {
|
||||
return orderbook, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
orderbook.Asks = append(orderbook.Asks, OrderbookItem{
|
||||
orderbook.Asks[x] = OrderbookItem{
|
||||
Price: price,
|
||||
Quantity: amount,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
orderbook.LastUpdateID = resp.LastUpdateID
|
||||
return orderbook, nil
|
||||
return &orderbook, nil
|
||||
}
|
||||
|
||||
// GetMostRecentTrades returns recent trade activity
|
||||
// limit: Up to 500 results returned
|
||||
func (b *Binance) GetMostRecentTrades(ctx context.Context, rtr RecentTradeRequestParams) ([]RecentTrade, error) {
|
||||
var resp []RecentTrade
|
||||
|
||||
params := url.Values{}
|
||||
symbol, err := b.FormatSymbol(rtr.Symbol, asset.Spot)
|
||||
if err != nil {
|
||||
@@ -194,6 +195,7 @@ func (b *Binance) GetMostRecentTrades(ctx context.Context, rtr RecentTradeReques
|
||||
|
||||
path := recentTrades + "?" + params.Encode()
|
||||
|
||||
var resp []RecentTrade
|
||||
return resp, b.SendHTTPRequest(ctx,
|
||||
exchange.RestSpotSupplementary, path, spotDefaultRate, &resp)
|
||||
}
|
||||
@@ -356,14 +358,12 @@ func (b *Binance) batchAggregateTrades(ctx context.Context, arg *AggregatedTrade
|
||||
// startTime: startTime filter for kline data
|
||||
// endTime: endTime filter for the kline data
|
||||
func (b *Binance) GetSpotKline(ctx context.Context, arg *KlinesRequestParams) ([]CandleStick, error) {
|
||||
var resp interface{}
|
||||
var klineData []CandleStick
|
||||
|
||||
params := url.Values{}
|
||||
symbol, err := b.FormatSymbol(arg.Symbol, asset.Spot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
params := url.Values{}
|
||||
params.Set("symbol", symbol)
|
||||
params.Set("interval", arg.Interval)
|
||||
if arg.Limit != 0 {
|
||||
@@ -377,6 +377,7 @@ func (b *Binance) GetSpotKline(ctx context.Context, arg *KlinesRequestParams) ([
|
||||
}
|
||||
|
||||
path := candleStick + "?" + params.Encode()
|
||||
var resp interface{}
|
||||
|
||||
err = b.SendHTTPRequest(ctx,
|
||||
exchange.RestSpotSupplementary,
|
||||
@@ -390,6 +391,8 @@ func (b *Binance) GetSpotKline(ctx context.Context, arg *KlinesRequestParams) ([
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert responseData")
|
||||
}
|
||||
|
||||
klineData := make([]CandleStick, len(responseData))
|
||||
for x := range responseData {
|
||||
individualData, ok := responseData[x].([]interface{})
|
||||
if !ok {
|
||||
@@ -432,7 +435,7 @@ func (b *Binance) GetSpotKline(ctx context.Context, arg *KlinesRequestParams) ([
|
||||
if candle.TakerBuyQuoteAssetVolume, err = convert.FloatFromString(individualData[10]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
klineData = append(klineData, candle)
|
||||
klineData[x] = candle
|
||||
}
|
||||
return klineData, nil
|
||||
}
|
||||
|
||||
@@ -82,10 +82,18 @@ func (b *Binance) FuturesExchangeInfo(ctx context.Context) (CExchangeInfo, error
|
||||
}
|
||||
|
||||
// GetFuturesOrderbook gets orderbook data for CoinMarginedFutures,
|
||||
func (b *Binance) GetFuturesOrderbook(ctx context.Context, symbol currency.Pair, limit int64) (OrderBook, error) {
|
||||
var resp OrderBook
|
||||
var data OrderbookData
|
||||
func (b *Binance) GetFuturesOrderbook(ctx context.Context, symbol currency.Pair, limit int64) (*OrderBook, error) {
|
||||
symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
params := url.Values{}
|
||||
params.Set("symbol", symbolValue)
|
||||
if limit > 0 && limit <= 1000 {
|
||||
params.Set("limit", strconv.FormatInt(limit, 10))
|
||||
}
|
||||
|
||||
rateBudget := cFuturesDefaultRate
|
||||
switch {
|
||||
case limit == 5, limit == 10, limit == 20, limit == 50:
|
||||
@@ -97,48 +105,47 @@ func (b *Binance) GetFuturesOrderbook(ctx context.Context, symbol currency.Pair,
|
||||
case limit == 1000:
|
||||
rateBudget = cFuturesOrderbook1000Rate
|
||||
}
|
||||
symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
}
|
||||
params.Set("symbol", symbolValue)
|
||||
if limit > 0 && limit <= 1000 {
|
||||
params.Set("limit", strconv.FormatInt(limit, 10))
|
||||
}
|
||||
|
||||
var data OrderbookData
|
||||
err = b.SendHTTPRequest(ctx, exchange.RestCoinMargined, cfuturesOrderbook+params.Encode(), rateBudget, &data)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var resp OrderBook
|
||||
var price, quantity float64
|
||||
resp.Asks = make([]OrderbookItem, len(data.Asks))
|
||||
for x := range data.Asks {
|
||||
price, err = strconv.ParseFloat(data.Asks[x][0], 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
quantity, err = strconv.ParseFloat(data.Asks[x][1], 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
resp.Asks = append(resp.Asks, OrderbookItem{
|
||||
resp.Asks[x] = OrderbookItem{
|
||||
Price: price,
|
||||
Quantity: quantity,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
resp.Bids = make([]OrderbookItem, len(data.Bids))
|
||||
for y := range data.Bids {
|
||||
price, err = strconv.ParseFloat(data.Bids[y][0], 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
quantity, err = strconv.ParseFloat(data.Bids[y][1], 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
resp.Bids = append(resp.Bids, OrderbookItem{
|
||||
resp.Bids[y] = OrderbookItem{
|
||||
Price: price,
|
||||
Quantity: quantity,
|
||||
})
|
||||
}
|
||||
}
|
||||
return resp, nil
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
// GetFuturesPublicTrades gets recent public trades for CoinMarginedFutures,
|
||||
@@ -232,13 +239,11 @@ func (b *Binance) GetIndexAndMarkPrice(ctx context.Context, symbol, pair string)
|
||||
|
||||
// GetFuturesKlineData gets futures kline data for CoinMarginedFutures,
|
||||
func (b *Binance) GetFuturesKlineData(ctx context.Context, symbol currency.Pair, interval string, limit int64, startTime, endTime time.Time) ([]FuturesCandleStick, error) {
|
||||
var data [][10]interface{}
|
||||
var resp []FuturesCandleStick
|
||||
params := url.Values{}
|
||||
if !symbol.IsEmpty() {
|
||||
symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
params.Set("symbol", symbolValue)
|
||||
}
|
||||
@@ -246,453 +251,462 @@ func (b *Binance) GetFuturesKlineData(ctx context.Context, symbol currency.Pair,
|
||||
params.Set("limit", strconv.FormatInt(limit, 10))
|
||||
}
|
||||
if !common.StringDataCompare(validFuturesIntervals, interval) {
|
||||
return resp, errors.New("invalid interval parsed")
|
||||
return nil, errors.New("invalid interval parsed")
|
||||
}
|
||||
params.Set("interval", interval)
|
||||
if !startTime.IsZero() && !endTime.IsZero() {
|
||||
if startTime.After(endTime) {
|
||||
return resp, errors.New("startTime cannot be after endTime")
|
||||
return nil, errors.New("startTime cannot be after endTime")
|
||||
}
|
||||
params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10))
|
||||
params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10))
|
||||
}
|
||||
|
||||
var data [][10]interface{}
|
||||
rateBudget := getKlineRateBudget(limit)
|
||||
err := b.SendHTTPRequest(ctx, exchange.RestCoinMargined, cfuturesKlineData+params.Encode(), rateBudget, &data)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
var floatData float64
|
||||
var strData string
|
||||
var ok bool
|
||||
var tempData FuturesCandleStick
|
||||
|
||||
resp := make([]FuturesCandleStick, len(data))
|
||||
for x := range data {
|
||||
var floatData float64
|
||||
var strData string
|
||||
var ok bool
|
||||
var tempData FuturesCandleStick
|
||||
floatData, ok = data[x][0].(float64)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for open time")
|
||||
return nil, errors.New("type assertion failed for open time")
|
||||
}
|
||||
tempData.OpenTime = time.Unix(int64(floatData), 0)
|
||||
strData, ok = data[x][1].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for open")
|
||||
return nil, errors.New("type assertion failed for open")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.Open = floatData
|
||||
strData, ok = data[x][2].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for high")
|
||||
return nil, errors.New("type assertion failed for high")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.High = floatData
|
||||
strData, ok = data[x][3].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for low")
|
||||
return nil, errors.New("type assertion failed for low")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.Low = floatData
|
||||
strData, ok = data[x][4].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for close")
|
||||
return nil, errors.New("type assertion failed for close")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.Close = floatData
|
||||
strData, ok = data[x][5].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for volume")
|
||||
return nil, errors.New("type assertion failed for volume")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.Volume = floatData
|
||||
floatData, ok = data[x][6].(float64)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for close time")
|
||||
return nil, errors.New("type assertion failed for close time")
|
||||
}
|
||||
tempData.CloseTime = time.Unix(int64(floatData), 0)
|
||||
strData, ok = data[x][7].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for base asset volume")
|
||||
return nil, errors.New("type assertion failed for base asset volume")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.BaseAssetVolume = floatData
|
||||
floatData, ok = data[x][8].(float64)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for taker buy volume")
|
||||
return nil, errors.New("type assertion failed for taker buy volume")
|
||||
}
|
||||
tempData.TakerBuyVolume = floatData
|
||||
strData, ok = data[x][9].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for taker buy base asset volume")
|
||||
return nil, errors.New("type assertion failed for taker buy base asset volume")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.TakerBuyBaseAssetVolume = floatData
|
||||
resp = append(resp, tempData)
|
||||
resp[x] = tempData
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GetContinuousKlineData gets continuous kline data
|
||||
func (b *Binance) GetContinuousKlineData(ctx context.Context, pair, contractType, interval string, limit int64, startTime, endTime time.Time) ([]FuturesCandleStick, error) {
|
||||
var data [][10]interface{}
|
||||
var resp []FuturesCandleStick
|
||||
params := url.Values{}
|
||||
params.Set("pair", pair)
|
||||
if !common.StringDataCompare(validContractType, contractType) {
|
||||
return resp, errors.New("invalid contractType")
|
||||
return nil, errors.New("invalid contractType")
|
||||
}
|
||||
params.Set("contractType", contractType)
|
||||
if limit > 0 && limit <= 1500 {
|
||||
params.Set("limit", strconv.FormatInt(limit, 10))
|
||||
}
|
||||
if !common.StringDataCompare(validFuturesIntervals, interval) {
|
||||
return resp, errors.New("invalid interval parsed")
|
||||
return nil, errors.New("invalid interval parsed")
|
||||
}
|
||||
params.Set("interval", interval)
|
||||
if !startTime.IsZero() && !endTime.IsZero() {
|
||||
if startTime.After(endTime) {
|
||||
return resp, errors.New("startTime cannot be after endTime")
|
||||
return nil, errors.New("startTime cannot be after endTime")
|
||||
}
|
||||
params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10))
|
||||
params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10))
|
||||
}
|
||||
|
||||
rateBudget := getKlineRateBudget(limit)
|
||||
var data [][10]interface{}
|
||||
err := b.SendHTTPRequest(ctx, exchange.RestCoinMargined, cfuturesContinuousKline+params.Encode(), rateBudget, &data)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
var floatData float64
|
||||
var strData string
|
||||
var ok bool
|
||||
var tempData FuturesCandleStick
|
||||
|
||||
resp := make([]FuturesCandleStick, len(data))
|
||||
for x := range data {
|
||||
var floatData float64
|
||||
var strData string
|
||||
var ok bool
|
||||
var tempData FuturesCandleStick
|
||||
floatData, ok = data[x][0].(float64)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for open time")
|
||||
return nil, errors.New("type assertion failed for open time")
|
||||
}
|
||||
tempData.OpenTime = time.Unix(int64(floatData), 0)
|
||||
strData, ok = data[x][1].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for open")
|
||||
return nil, errors.New("type assertion failed for open")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.Open = floatData
|
||||
strData, ok = data[x][2].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for high")
|
||||
return nil, errors.New("type assertion failed for high")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.High = floatData
|
||||
strData, ok = data[x][3].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for low")
|
||||
return nil, errors.New("type assertion failed for low")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.Low = floatData
|
||||
strData, ok = data[x][4].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for close")
|
||||
return nil, errors.New("type assertion failed for close")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.Close = floatData
|
||||
strData, ok = data[x][5].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for volume")
|
||||
return nil, errors.New("type assertion failed for volume")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.Volume = floatData
|
||||
floatData, ok = data[x][6].(float64)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for close time")
|
||||
return nil, errors.New("type assertion failed for close time")
|
||||
}
|
||||
tempData.CloseTime = time.Unix(int64(floatData), 0)
|
||||
strData, ok = data[x][7].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for base asset volume")
|
||||
return nil, errors.New("type assertion failed for base asset volume")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.BaseAssetVolume = floatData
|
||||
floatData, ok = data[x][8].(float64)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for taker buy volume")
|
||||
return nil, errors.New("type assertion failed for taker buy volume")
|
||||
}
|
||||
tempData.TakerBuyVolume = floatData
|
||||
strData, ok = data[x][9].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for taker buy base asset volume")
|
||||
return nil, errors.New("type assertion failed for taker buy base asset volume")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.TakerBuyBaseAssetVolume = floatData
|
||||
resp = append(resp, tempData)
|
||||
resp[x] = tempData
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GetIndexPriceKlines gets continuous kline data
|
||||
func (b *Binance) GetIndexPriceKlines(ctx context.Context, pair, interval string, limit int64, startTime, endTime time.Time) ([]FuturesCandleStick, error) {
|
||||
var data [][10]interface{}
|
||||
var resp []FuturesCandleStick
|
||||
params := url.Values{}
|
||||
params.Set("pair", pair)
|
||||
if limit > 0 && limit <= 1500 {
|
||||
params.Set("limit", strconv.FormatInt(limit, 10))
|
||||
}
|
||||
if !common.StringDataCompare(validFuturesIntervals, interval) {
|
||||
return resp, errors.New("invalid interval parsed")
|
||||
return nil, errors.New("invalid interval parsed")
|
||||
}
|
||||
params.Set("interval", interval)
|
||||
if !startTime.IsZero() && !endTime.IsZero() {
|
||||
if startTime.After(endTime) {
|
||||
return resp, errors.New("startTime cannot be after endTime")
|
||||
return nil, errors.New("startTime cannot be after endTime")
|
||||
}
|
||||
params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10))
|
||||
params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10))
|
||||
}
|
||||
|
||||
rateBudget := getKlineRateBudget(limit)
|
||||
var data [][10]interface{}
|
||||
err := b.SendHTTPRequest(ctx, exchange.RestCoinMargined, cfuturesIndexKline+params.Encode(), rateBudget, &data)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
var floatData float64
|
||||
var strData string
|
||||
var ok bool
|
||||
var tempData FuturesCandleStick
|
||||
|
||||
resp := make([]FuturesCandleStick, len(data))
|
||||
for x := range data {
|
||||
var floatData float64
|
||||
var strData string
|
||||
var ok bool
|
||||
var tempData FuturesCandleStick
|
||||
floatData, ok = data[x][0].(float64)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for open time")
|
||||
return nil, errors.New("type assertion failed for open time")
|
||||
}
|
||||
tempData.OpenTime = time.Unix(int64(floatData), 0)
|
||||
strData, ok = data[x][1].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for open")
|
||||
return nil, errors.New("type assertion failed for open")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.Open = floatData
|
||||
strData, ok = data[x][2].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for high")
|
||||
return nil, errors.New("type assertion failed for high")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.High = floatData
|
||||
strData, ok = data[x][3].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for low")
|
||||
return nil, errors.New("type assertion failed for low")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.Low = floatData
|
||||
strData, ok = data[x][4].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for close")
|
||||
return nil, errors.New("type assertion failed for close")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.Close = floatData
|
||||
strData, ok = data[x][5].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for volume")
|
||||
return nil, errors.New("type assertion failed for volume")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.Volume = floatData
|
||||
floatData, ok = data[x][6].(float64)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for close time")
|
||||
return nil, errors.New("type assertion failed for close time")
|
||||
}
|
||||
tempData.CloseTime = time.Unix(int64(floatData), 0)
|
||||
strData, ok = data[x][7].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for base asset volume")
|
||||
return nil, errors.New("type assertion failed for base asset volume")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.BaseAssetVolume = floatData
|
||||
floatData, ok = data[x][8].(float64)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for taker buy volume")
|
||||
return nil, errors.New("type assertion failed for taker buy volume")
|
||||
}
|
||||
tempData.TakerBuyVolume = floatData
|
||||
strData, ok = data[x][9].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for taker buy base asset volume")
|
||||
return nil, errors.New("type assertion failed for taker buy base asset volume")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.TakerBuyBaseAssetVolume = floatData
|
||||
resp = append(resp, tempData)
|
||||
resp[x] = tempData
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GetMarkPriceKline gets mark price kline data
|
||||
func (b *Binance) GetMarkPriceKline(ctx context.Context, symbol currency.Pair, interval string, limit int64, startTime, endTime time.Time) ([]FuturesCandleStick, error) {
|
||||
var data [][10]interface{}
|
||||
var resp []FuturesCandleStick
|
||||
params := url.Values{}
|
||||
symbolValue, err := b.FormatSymbol(symbol, asset.CoinMarginedFutures)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
params := url.Values{}
|
||||
params.Set("symbol", symbolValue)
|
||||
if limit > 0 && limit <= 1500 {
|
||||
params.Set("limit", strconv.FormatInt(limit, 10))
|
||||
}
|
||||
if !common.StringDataCompare(validFuturesIntervals, interval) {
|
||||
return resp, errors.New("invalid interval parsed")
|
||||
return nil, errors.New("invalid interval parsed")
|
||||
}
|
||||
params.Set("interval", interval)
|
||||
if !startTime.IsZero() && !endTime.IsZero() {
|
||||
if startTime.After(endTime) {
|
||||
return resp, errors.New("startTime cannot be after endTime")
|
||||
return nil, errors.New("startTime cannot be after endTime")
|
||||
}
|
||||
params.Set("start_time", strconv.FormatInt(startTime.Unix(), 10))
|
||||
params.Set("end_time", strconv.FormatInt(endTime.Unix(), 10))
|
||||
}
|
||||
|
||||
var data [][10]interface{}
|
||||
rateBudget := getKlineRateBudget(limit)
|
||||
err = b.SendHTTPRequest(ctx, exchange.RestCoinMargined, cfuturesMarkPriceKline+params.Encode(), rateBudget, &data)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
var floatData float64
|
||||
var strData string
|
||||
var ok bool
|
||||
var tempData FuturesCandleStick
|
||||
|
||||
resp := make([]FuturesCandleStick, len(data))
|
||||
for x := range data {
|
||||
var floatData float64
|
||||
var strData string
|
||||
var ok bool
|
||||
var tempData FuturesCandleStick
|
||||
floatData, ok = data[x][0].(float64)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for open time")
|
||||
return nil, errors.New("type assertion failed for open time")
|
||||
}
|
||||
tempData.OpenTime = time.Unix(int64(floatData), 0)
|
||||
strData, ok = data[x][1].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for open")
|
||||
return nil, errors.New("type assertion failed for open")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.Open = floatData
|
||||
strData, ok = data[x][2].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for high")
|
||||
return nil, errors.New("type assertion failed for high")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.High = floatData
|
||||
strData, ok = data[x][3].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for low")
|
||||
return nil, errors.New("type assertion failed for low")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.Low = floatData
|
||||
strData, ok = data[x][4].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for close")
|
||||
return nil, errors.New("type assertion failed for close")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.Close = floatData
|
||||
strData, ok = data[x][5].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for volume")
|
||||
return nil, errors.New("type assertion failed for volume")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.Volume = floatData
|
||||
floatData, ok = data[x][6].(float64)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for close time")
|
||||
return nil, errors.New("type assertion failed for close time")
|
||||
}
|
||||
tempData.CloseTime = time.Unix(int64(floatData), 0)
|
||||
strData, ok = data[x][7].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for base asset volume")
|
||||
return nil, errors.New("type assertion failed for base asset volume")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.BaseAssetVolume = floatData
|
||||
floatData, ok = data[x][8].(float64)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for taker buy volume")
|
||||
return nil, errors.New("type assertion failed for taker buy volume")
|
||||
}
|
||||
tempData.TakerBuyVolume = floatData
|
||||
strData, ok = data[x][9].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for taker buy base asset volume")
|
||||
return nil, errors.New("type assertion failed for taker buy base asset volume")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.TakerBuyBaseAssetVolume = floatData
|
||||
resp = append(resp, tempData)
|
||||
resp[x] = tempData
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
@@ -1466,12 +1480,12 @@ func (b *Binance) FuturesPositionsADLEstimate(ctx context.Context, symbol curren
|
||||
|
||||
// FetchCoinMarginExchangeLimits fetches coin margined order execution limits
|
||||
func (b *Binance) FetchCoinMarginExchangeLimits(ctx context.Context) ([]order.MinMaxLevel, error) {
|
||||
var limits []order.MinMaxLevel
|
||||
coinFutures, err := b.FuturesExchangeInfo(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
limits := make([]order.MinMaxLevel, 0, len(coinFutures.Symbols))
|
||||
for x := range coinFutures.Symbols {
|
||||
symbol := strings.Split(coinFutures.Symbols[x].Symbol, currency.UnderscoreDelimiter)
|
||||
var cp currency.Pair
|
||||
|
||||
@@ -36,6 +36,7 @@ func TestMain(m *testing.M) {
|
||||
log.Fatal("Binance setup error", err)
|
||||
}
|
||||
b.setupOrderbookManager()
|
||||
request.MaxRequestJobs = 100
|
||||
b.Websocket.DataHandler = sharedtestvalues.GetWebsocketInterfaceChannelOverride()
|
||||
log.Printf(sharedtestvalues.LiveTesting, b.Name)
|
||||
os.Exit(m.Run())
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
|
||||
"github.com/thrasher-corp/gocryptotrader/config"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/mock"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/request"
|
||||
"github.com/thrasher-corp/gocryptotrader/exchanges/sharedtestvalues"
|
||||
)
|
||||
|
||||
@@ -57,6 +58,7 @@ func TestMain(m *testing.M) {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
request.MaxRequestJobs = 100
|
||||
log.Printf(sharedtestvalues.MockTesting, b.Name)
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
||||
@@ -84,22 +84,22 @@ func (b *Binance) UExchangeInfo(ctx context.Context) (UFuturesExchangeInfo, erro
|
||||
}
|
||||
|
||||
// UFuturesOrderbook gets orderbook data for usdt margined futures
|
||||
func (b *Binance) UFuturesOrderbook(ctx context.Context, symbol currency.Pair, limit int64) (OrderBook, error) {
|
||||
var resp OrderBook
|
||||
var data OrderbookData
|
||||
params := url.Values{}
|
||||
func (b *Binance) UFuturesOrderbook(ctx context.Context, symbol currency.Pair, limit int64) (*OrderBook, error) {
|
||||
symbolValue, err := b.FormatSymbol(symbol, asset.USDTMarginedFutures)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
params := url.Values{}
|
||||
params.Set("symbol", symbolValue)
|
||||
strLimit := strconv.FormatInt(limit, 10)
|
||||
if strLimit != "" {
|
||||
if !common.StringDataCompare(uValidOBLimits, strLimit) {
|
||||
return resp, fmt.Errorf("invalid limit: %v", limit)
|
||||
return nil, fmt.Errorf("invalid limit: %v", limit)
|
||||
}
|
||||
params.Set("limit", strLimit)
|
||||
}
|
||||
|
||||
rateBudget := uFuturesDefaultRate
|
||||
switch {
|
||||
case limit == 5, limit == 10, limit == 20, limit == 50:
|
||||
@@ -111,42 +111,50 @@ func (b *Binance) UFuturesOrderbook(ctx context.Context, symbol currency.Pair, l
|
||||
case limit == 1000:
|
||||
rateBudget = uFuturesOrderbook1000Rate
|
||||
}
|
||||
|
||||
var data OrderbookData
|
||||
err = b.SendHTTPRequest(ctx, exchange.RestUSDTMargined, ufuturesOrderbook+params.Encode(), rateBudget, &data)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
resp.Symbol = symbolValue
|
||||
resp.LastUpdateID = data.LastUpdateID
|
||||
|
||||
resp := OrderBook{
|
||||
Symbol: symbolValue,
|
||||
LastUpdateID: data.LastUpdateID,
|
||||
Bids: make([]OrderbookItem, len(data.Bids)),
|
||||
Asks: make([]OrderbookItem, len(data.Asks)),
|
||||
}
|
||||
|
||||
var price, quantity float64
|
||||
for x := range data.Asks {
|
||||
price, err = strconv.ParseFloat(data.Asks[x][0], 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
quantity, err = strconv.ParseFloat(data.Asks[x][1], 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
resp.Asks = append(resp.Asks, OrderbookItem{
|
||||
resp.Asks[x] = OrderbookItem{
|
||||
Price: price,
|
||||
Quantity: quantity,
|
||||
})
|
||||
}
|
||||
}
|
||||
for y := range data.Bids {
|
||||
price, err = strconv.ParseFloat(data.Bids[y][0], 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
quantity, err = strconv.ParseFloat(data.Bids[y][1], 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
resp.Bids = append(resp.Bids, OrderbookItem{
|
||||
resp.Bids[y] = OrderbookItem{
|
||||
Price: price,
|
||||
Quantity: quantity,
|
||||
})
|
||||
}
|
||||
}
|
||||
return resp, nil
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
// URecentTrades gets recent trades for usdt margined futures
|
||||
@@ -212,16 +220,14 @@ func (b *Binance) UCompressedTrades(ctx context.Context, symbol currency.Pair, f
|
||||
|
||||
// UKlineData gets kline data for usdt margined futures
|
||||
func (b *Binance) UKlineData(ctx context.Context, symbol currency.Pair, interval string, limit int64, startTime, endTime time.Time) ([]FuturesCandleStick, error) {
|
||||
var data [][10]interface{}
|
||||
var resp []FuturesCandleStick
|
||||
params := url.Values{}
|
||||
symbolValue, err := b.FormatSymbol(symbol, asset.USDTMarginedFutures)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
params.Set("symbol", symbolValue)
|
||||
if !common.StringDataCompare(validFuturesIntervals, interval) {
|
||||
return resp, errors.New("invalid interval")
|
||||
return nil, errors.New("invalid interval")
|
||||
}
|
||||
params.Set("interval", interval)
|
||||
if limit > 0 && limit <= 1500 {
|
||||
@@ -229,7 +235,7 @@ func (b *Binance) UKlineData(ctx context.Context, symbol currency.Pair, interval
|
||||
}
|
||||
if !startTime.IsZero() && !endTime.IsZero() {
|
||||
if startTime.After(endTime) {
|
||||
return resp, errors.New("startTime cannot be after endTime")
|
||||
return nil, errors.New("startTime cannot be after endTime")
|
||||
}
|
||||
params.Set("startTime", timeString(startTime))
|
||||
params.Set("endTime", timeString(endTime))
|
||||
@@ -245,71 +251,76 @@ func (b *Binance) UKlineData(ctx context.Context, symbol currency.Pair, interval
|
||||
case limit > 1000:
|
||||
rateBudget = uFuturesKlineMaxRate
|
||||
}
|
||||
|
||||
var data [][10]interface{}
|
||||
err = b.SendHTTPRequest(ctx, exchange.RestUSDTMargined, ufuturesKlineData+params.Encode(), rateBudget, &data)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
var tempData FuturesCandleStick
|
||||
var floatData float64
|
||||
var strData string
|
||||
var ok bool
|
||||
|
||||
resp := make([]FuturesCandleStick, len(data))
|
||||
for x := range data {
|
||||
var tempData FuturesCandleStick
|
||||
var floatData float64
|
||||
var strData string
|
||||
var ok bool
|
||||
|
||||
floatData, ok = data[x][0].(float64)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for opentime")
|
||||
return nil, errors.New("type assertion failed for opentime")
|
||||
}
|
||||
tempData.OpenTime, err = convert.TimeFromUnixTimestampFloat(floatData)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
strData, ok = data[x][1].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for open")
|
||||
return nil, errors.New("type assertion failed for open")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.Open = floatData
|
||||
strData, ok = data[x][2].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for high")
|
||||
return nil, errors.New("type assertion failed for high")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.High = floatData
|
||||
strData, ok = data[x][3].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for low")
|
||||
return nil, errors.New("type assertion failed for low")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.Low = floatData
|
||||
strData, ok = data[x][4].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for close")
|
||||
return nil, errors.New("type assertion failed for close")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.Close = floatData
|
||||
strData, ok = data[x][5].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for volume")
|
||||
return nil, errors.New("type assertion failed for volume")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.Volume = floatData
|
||||
floatData, ok = data[x][6].(float64)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for close time")
|
||||
return nil, errors.New("type assertion failed for close time")
|
||||
}
|
||||
tempData.CloseTime, err = convert.TimeFromUnixTimestampFloat(floatData)
|
||||
if err != nil {
|
||||
@@ -317,28 +328,28 @@ func (b *Binance) UKlineData(ctx context.Context, symbol currency.Pair, interval
|
||||
}
|
||||
strData, ok = data[x][7].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed base asset volume")
|
||||
return nil, errors.New("type assertion failed base asset volume")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.BaseAssetVolume = floatData
|
||||
floatData, ok = data[x][8].(float64)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for taker buy volume")
|
||||
return nil, errors.New("type assertion failed for taker buy volume")
|
||||
}
|
||||
tempData.TakerBuyVolume = floatData
|
||||
strData, ok = data[x][9].(string)
|
||||
if !ok {
|
||||
return resp, errors.New("type assertion failed for taker buy base asset volume")
|
||||
return nil, errors.New("type assertion failed for taker buy base asset volume")
|
||||
}
|
||||
floatData, err = strconv.ParseFloat(strData, 64)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
tempData.TakerBuyBaseAssetVolume = floatData
|
||||
resp = append(resp, tempData)
|
||||
resp[x] = tempData
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
@@ -1139,12 +1150,12 @@ func (b *Binance) GetFundingRates(ctx context.Context, symbol currency.Pair, lim
|
||||
|
||||
// FetchUSDTMarginExchangeLimits fetches USDT margined order execution limits
|
||||
func (b *Binance) FetchUSDTMarginExchangeLimits(ctx context.Context) ([]order.MinMaxLevel, error) {
|
||||
var limits []order.MinMaxLevel
|
||||
usdtFutures, err := b.UExchangeInfo(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
limits := make([]order.MinMaxLevel, 0, len(usdtFutures.Symbols))
|
||||
for x := range usdtFutures.Symbols {
|
||||
var cp currency.Pair
|
||||
cp, err = currency.NewPairFromStrings(usdtFutures.Symbols[x].BaseAsset,
|
||||
|
||||
@@ -482,31 +482,32 @@ func (b *Binance) SeedLocalCache(ctx context.Context, p currency.Pair) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return b.SeedLocalCacheWithBook(p, &ob)
|
||||
return b.SeedLocalCacheWithBook(p, ob)
|
||||
}
|
||||
|
||||
// SeedLocalCacheWithBook seeds the local orderbook cache
|
||||
func (b *Binance) SeedLocalCacheWithBook(p currency.Pair, orderbookNew *OrderBook) error {
|
||||
var newOrderBook orderbook.Base
|
||||
newOrderBook := orderbook.Base{
|
||||
Pair: p,
|
||||
Asset: asset.Spot,
|
||||
Exchange: b.Name,
|
||||
LastUpdateID: orderbookNew.LastUpdateID,
|
||||
VerifyOrderbook: b.CanVerifyOrderbook,
|
||||
Bids: make(orderbook.Items, len(orderbookNew.Bids)),
|
||||
Asks: make(orderbook.Items, len(orderbookNew.Asks)),
|
||||
}
|
||||
for i := range orderbookNew.Bids {
|
||||
newOrderBook.Bids = append(newOrderBook.Bids, orderbook.Item{
|
||||
newOrderBook.Bids[i] = orderbook.Item{
|
||||
Amount: orderbookNew.Bids[i].Quantity,
|
||||
Price: orderbookNew.Bids[i].Price,
|
||||
})
|
||||
}
|
||||
}
|
||||
for i := range orderbookNew.Asks {
|
||||
newOrderBook.Asks = append(newOrderBook.Asks, orderbook.Item{
|
||||
newOrderBook.Asks[i] = orderbook.Item{
|
||||
Amount: orderbookNew.Asks[i].Quantity,
|
||||
Price: orderbookNew.Asks[i].Price,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
newOrderBook.Pair = p
|
||||
newOrderBook.Asset = asset.Spot
|
||||
newOrderBook.Exchange = b.Name
|
||||
newOrderBook.LastUpdateID = orderbookNew.LastUpdateID
|
||||
newOrderBook.VerifyOrderbook = b.CanVerifyOrderbook
|
||||
|
||||
return b.Websocket.Orderbook.LoadSnapshot(&newOrderBook)
|
||||
}
|
||||
|
||||
@@ -626,7 +627,7 @@ func (b *Binance) Unsubscribe(channelsToUnsubscribe []stream.ChannelSubscription
|
||||
|
||||
// ProcessUpdate processes the websocket orderbook update
|
||||
func (b *Binance) ProcessUpdate(cp currency.Pair, a asset.Item, ws *WebsocketDepthStream) error {
|
||||
var updateBid []orderbook.Item
|
||||
updateBid := make([]orderbook.Item, len(ws.UpdateBids))
|
||||
for i := range ws.UpdateBids {
|
||||
price, ok := ws.UpdateBids[i][0].(string)
|
||||
if !ok {
|
||||
@@ -644,10 +645,10 @@ func (b *Binance) ProcessUpdate(cp currency.Pair, a asset.Item, ws *WebsocketDep
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
updateBid = append(updateBid, orderbook.Item{Price: p, Amount: a})
|
||||
updateBid[i] = orderbook.Item{Price: p, Amount: a}
|
||||
}
|
||||
|
||||
var updateAsk []orderbook.Item
|
||||
updateAsk := make([]orderbook.Item, len(ws.UpdateAsks))
|
||||
for i := range ws.UpdateAsks {
|
||||
price, ok := ws.UpdateAsks[i][0].(string)
|
||||
if !ok {
|
||||
@@ -665,7 +666,7 @@ func (b *Binance) ProcessUpdate(cp currency.Pair, a asset.Item, ws *WebsocketDep
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
updateAsk = append(updateAsk, orderbook.Item{Price: p, Amount: a})
|
||||
updateAsk[i] = orderbook.Item{Price: p, Amount: a}
|
||||
}
|
||||
|
||||
return b.Websocket.Orderbook.Update(&buffer.Update{
|
||||
|
||||
@@ -657,7 +657,7 @@ func (b *Binance) UpdateOrderbook(ctx context.Context, p currency.Pair, assetTyp
|
||||
Asset: assetType,
|
||||
VerifyOrderbook: b.CanVerifyOrderbook,
|
||||
}
|
||||
var orderbookNew OrderBook
|
||||
var orderbookNew *OrderBook
|
||||
var err error
|
||||
switch assetType {
|
||||
case asset.Spot, asset.Margin:
|
||||
@@ -673,17 +673,20 @@ func (b *Binance) UpdateOrderbook(ctx context.Context, p currency.Pair, assetTyp
|
||||
if err != nil {
|
||||
return book, err
|
||||
}
|
||||
|
||||
book.Bids = make(orderbook.Items, len(orderbookNew.Bids))
|
||||
for x := range orderbookNew.Bids {
|
||||
book.Bids = append(book.Bids, orderbook.Item{
|
||||
book.Bids[x] = orderbook.Item{
|
||||
Amount: orderbookNew.Bids[x].Quantity,
|
||||
Price: orderbookNew.Bids[x].Price,
|
||||
})
|
||||
}
|
||||
}
|
||||
book.Asks = make(orderbook.Items, len(orderbookNew.Asks))
|
||||
for x := range orderbookNew.Asks {
|
||||
book.Asks = append(book.Asks, orderbook.Item{
|
||||
book.Asks[x] = orderbook.Item{
|
||||
Amount: orderbookNew.Asks[x].Quantity,
|
||||
Price: orderbookNew.Asks[x].Price,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
err = book.Process()
|
||||
@@ -834,15 +837,16 @@ func (b *Binance) GetWithdrawalsHistory(ctx context.Context, c currency.Code) (r
|
||||
|
||||
// GetRecentTrades returns the most recent trades for a currency and asset
|
||||
func (b *Binance) GetRecentTrades(ctx context.Context, p currency.Pair, assetType asset.Item) ([]trade.Data, error) {
|
||||
var resp []trade.Data
|
||||
limit := 1000
|
||||
const limit = 1000
|
||||
tradeData, err := b.GetMostRecentTrades(ctx,
|
||||
RecentTradeRequestParams{p, limit})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp := make([]trade.Data, len(tradeData))
|
||||
for i := range tradeData {
|
||||
resp = append(resp, trade.Data{
|
||||
resp[i] = trade.Data{
|
||||
TID: strconv.FormatInt(tradeData[i].ID, 10),
|
||||
Exchange: b.Name,
|
||||
CurrencyPair: p,
|
||||
@@ -850,7 +854,7 @@ func (b *Binance) GetRecentTrades(ctx context.Context, p currency.Pair, assetTyp
|
||||
Price: tradeData[i].Price,
|
||||
Amount: tradeData[i].Quantity,
|
||||
Timestamp: tradeData[i].Time,
|
||||
})
|
||||
}
|
||||
}
|
||||
if b.IsSaveTradeDataEnabled() {
|
||||
err := trade.AddTradesToBuffer(b.Name, resp...)
|
||||
@@ -874,11 +878,11 @@ func (b *Binance) GetHistoricTrades(ctx context.Context, p currency.Pair, a asse
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var result []trade.Data
|
||||
result := make([]trade.Data, len(trades))
|
||||
exName := b.GetName()
|
||||
for i := range trades {
|
||||
t := trades[i].toTradeData(p, exName, a)
|
||||
result = append(result, *t)
|
||||
result[i] = *t
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@@ -148,7 +148,7 @@ func baseMarginInfo(data []interface{}) (MarginInfoV2, error) {
|
||||
}
|
||||
|
||||
func symbolMarginInfo(data []interface{}) ([]MarginInfoV2, error) {
|
||||
var resp []MarginInfoV2
|
||||
resp := make([]MarginInfoV2, len(data))
|
||||
for x := range data {
|
||||
var tempResp MarginInfoV2
|
||||
tempData, ok := data[x].([]interface{})
|
||||
@@ -183,7 +183,7 @@ func symbolMarginInfo(data []interface{}) ([]MarginInfoV2, error) {
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%w for BestBidAmount", errTypeAssert)
|
||||
}
|
||||
resp = append(resp, tempResp)
|
||||
resp[x] = tempResp
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
@@ -381,7 +381,6 @@ func (b *Bitfinex) GetAccountInfoV2(ctx context.Context) (AccountV2Data, error)
|
||||
|
||||
// GetV2Balances gets v2 balances
|
||||
func (b *Bitfinex) GetV2Balances(ctx context.Context) ([]WalletDataV2, error) {
|
||||
var resp []WalletDataV2
|
||||
var data [][4]interface{}
|
||||
err := b.SendAuthenticatedHTTPRequestV2(ctx,
|
||||
exchange.RestSpot, http.MethodPost,
|
||||
@@ -390,8 +389,9 @@ func (b *Bitfinex) GetV2Balances(ctx context.Context) ([]WalletDataV2, error) {
|
||||
&data,
|
||||
getAccountFees)
|
||||
if err != nil {
|
||||
return resp, err
|
||||
return nil, err
|
||||
}
|
||||
resp := make([]WalletDataV2, len(data))
|
||||
for x := range data {
|
||||
wType, ok := data[x][0].(string)
|
||||
if !ok {
|
||||
@@ -409,12 +409,12 @@ func (b *Bitfinex) GetV2Balances(ctx context.Context) ([]WalletDataV2, error) {
|
||||
if !ok {
|
||||
return resp, fmt.Errorf("%v GetV2Balances: %w for unsettledInterest", b.Name, errTypeAssert)
|
||||
}
|
||||
resp = append(resp, WalletDataV2{
|
||||
resp[x] = WalletDataV2{
|
||||
WalletType: wType,
|
||||
Currency: curr,
|
||||
Balance: bal,
|
||||
UnsettledInterest: unsettledInterest,
|
||||
})
|
||||
}
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
@@ -435,9 +435,6 @@ func (b *Bitfinex) GetMarginPairs(ctx context.Context) ([]string, error) {
|
||||
|
||||
// GetDerivativeStatusInfo gets status data for the queried derivative
|
||||
func (b *Bitfinex) GetDerivativeStatusInfo(ctx context.Context, keys, startTime, endTime string, sort, limit int64) ([]DerivativeDataResponse, error) {
|
||||
var result [][]interface{}
|
||||
var finalResp []DerivativeDataResponse
|
||||
|
||||
params := url.Values{}
|
||||
params.Set("keys", keys)
|
||||
if startTime != "" {
|
||||
@@ -452,12 +449,15 @@ func (b *Bitfinex) GetDerivativeStatusInfo(ctx context.Context, keys, startTime,
|
||||
if limit != 0 {
|
||||
params.Set("limit", strconv.FormatInt(limit, 10))
|
||||
}
|
||||
|
||||
var result [][]interface{}
|
||||
path := bitfinexAPIVersion2 + bitfinexDerivativeData +
|
||||
params.Encode()
|
||||
err := b.SendHTTPRequest(ctx, exchange.RestSpot, path, &result, status)
|
||||
if err != nil {
|
||||
return finalResp, err
|
||||
return nil, err
|
||||
}
|
||||
finalResp := make([]DerivativeDataResponse, len(result))
|
||||
for z := range result {
|
||||
if len(result[z]) < 19 {
|
||||
return finalResp, fmt.Errorf("%v GetDerivativeStatusInfo: invalid response, array length too small, check api docs for updates", b.Name)
|
||||
@@ -507,7 +507,7 @@ func (b *Bitfinex) GetDerivativeStatusInfo(ctx context.Context, keys, startTime,
|
||||
t,
|
||||
)
|
||||
}
|
||||
finalResp = append(finalResp, response)
|
||||
finalResp[z] = response
|
||||
}
|
||||
return finalResp, nil
|
||||
}
|
||||
@@ -526,82 +526,198 @@ func (b *Bitfinex) GetTickerBatch(ctx context.Context) (map[string]Ticker, error
|
||||
|
||||
var tickers = make(map[string]Ticker)
|
||||
for x := range response {
|
||||
symbol, ok := response[x][0].(string)
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert symbol")
|
||||
}
|
||||
|
||||
var t Ticker
|
||||
if len(response[x]) > 11 {
|
||||
tickers[response[x][0].(string)] = Ticker{
|
||||
FlashReturnRate: response[x][1].(float64),
|
||||
Bid: response[x][2].(float64),
|
||||
BidPeriod: int64(response[x][3].(float64)),
|
||||
BidSize: response[x][4].(float64),
|
||||
Ask: response[x][5].(float64),
|
||||
AskPeriod: int64(response[x][6].(float64)),
|
||||
AskSize: response[x][7].(float64),
|
||||
DailyChange: response[x][8].(float64),
|
||||
DailyChangePerc: response[x][9].(float64),
|
||||
Last: response[x][10].(float64),
|
||||
Volume: response[x][11].(float64),
|
||||
High: response[x][12].(float64),
|
||||
Low: response[x][13].(float64),
|
||||
FFRAmountAvailable: response[x][16].(float64),
|
||||
if t.FlashReturnRate, ok = response[x][1].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert flashReturnRate")
|
||||
}
|
||||
if t.Bid, ok = response[x][2].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert bid")
|
||||
}
|
||||
var bidPeriod float64
|
||||
bidPeriod, ok = response[x][3].(float64)
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert bidPeriod")
|
||||
}
|
||||
t.BidPeriod = int64(bidPeriod)
|
||||
if t.BidSize, ok = response[x][4].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert bidSize")
|
||||
}
|
||||
if t.Ask, ok = response[x][5].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert ask")
|
||||
}
|
||||
var askPeriod float64
|
||||
askPeriod, ok = response[x][6].(float64)
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert askPeriod")
|
||||
}
|
||||
t.AskPeriod = int64(askPeriod)
|
||||
if t.AskSize, ok = response[x][7].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert askSize")
|
||||
}
|
||||
if t.DailyChange, ok = response[x][8].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert dailyChange")
|
||||
}
|
||||
if t.DailyChangePerc, ok = response[x][9].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert dailyChangePerc")
|
||||
}
|
||||
if t.Last, ok = response[x][10].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert last")
|
||||
}
|
||||
if t.Volume, ok = response[x][11].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert volume")
|
||||
}
|
||||
if t.High, ok = response[x][12].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert high")
|
||||
}
|
||||
if t.Low, ok = response[x][13].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert low")
|
||||
}
|
||||
if t.FFRAmountAvailable, ok = response[x][16].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert FFRAmountAvailable")
|
||||
}
|
||||
|
||||
tickers[symbol] = t
|
||||
continue
|
||||
}
|
||||
tickers[response[x][0].(string)] = Ticker{
|
||||
Bid: response[x][1].(float64),
|
||||
BidSize: response[x][2].(float64),
|
||||
Ask: response[x][3].(float64),
|
||||
AskSize: response[x][4].(float64),
|
||||
DailyChange: response[x][5].(float64),
|
||||
DailyChangePerc: response[x][6].(float64),
|
||||
Last: response[x][7].(float64),
|
||||
Volume: response[x][8].(float64),
|
||||
High: response[x][9].(float64),
|
||||
Low: response[x][10].(float64),
|
||||
|
||||
if t.Bid, ok = response[x][1].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert bid")
|
||||
}
|
||||
if t.BidSize, ok = response[x][2].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert bid size")
|
||||
}
|
||||
if t.Ask, ok = response[x][3].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert ask")
|
||||
}
|
||||
if t.AskSize, ok = response[x][4].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert ask size")
|
||||
}
|
||||
if t.DailyChange, ok = response[x][5].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert daily change")
|
||||
}
|
||||
if t.DailyChangePerc, ok = response[x][6].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert daily change perc")
|
||||
}
|
||||
if t.Last, ok = response[x][7].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert last")
|
||||
}
|
||||
if t.Volume, ok = response[x][8].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert volume")
|
||||
}
|
||||
if t.High, ok = response[x][9].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert high")
|
||||
}
|
||||
if t.Low, ok = response[x][10].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert low")
|
||||
}
|
||||
tickers[symbol] = t
|
||||
}
|
||||
return tickers, nil
|
||||
}
|
||||
|
||||
// GetTicker returns ticker information for one symbol
|
||||
func (b *Bitfinex) GetTicker(ctx context.Context, symbol string) (Ticker, error) {
|
||||
func (b *Bitfinex) GetTicker(ctx context.Context, symbol string) (*Ticker, error) {
|
||||
var response []interface{}
|
||||
|
||||
path := bitfinexAPIVersion2 + bitfinexTicker + symbol
|
||||
|
||||
err := b.SendHTTPRequest(ctx, exchange.RestSpot, path, &response, tickerFunction)
|
||||
if err != nil {
|
||||
return Ticker{}, err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var t Ticker
|
||||
if len(response) > 10 {
|
||||
return Ticker{
|
||||
FlashReturnRate: response[0].(float64),
|
||||
Bid: response[1].(float64),
|
||||
BidPeriod: int64(response[2].(float64)),
|
||||
BidSize: response[3].(float64),
|
||||
Ask: response[4].(float64),
|
||||
AskPeriod: int64(response[5].(float64)),
|
||||
AskSize: response[6].(float64),
|
||||
DailyChange: response[7].(float64),
|
||||
DailyChangePerc: response[8].(float64),
|
||||
Last: response[9].(float64),
|
||||
Volume: response[10].(float64),
|
||||
High: response[11].(float64),
|
||||
Low: response[12].(float64),
|
||||
FFRAmountAvailable: response[15].(float64),
|
||||
}, nil
|
||||
var ok bool
|
||||
if t.FlashReturnRate, ok = response[0].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert flashReturnRate")
|
||||
}
|
||||
if t.Bid, ok = response[1].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert bid")
|
||||
}
|
||||
var bidPeriod float64
|
||||
bidPeriod, ok = response[2].(float64)
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert bidPeriod")
|
||||
}
|
||||
t.BidPeriod = int64(bidPeriod)
|
||||
if t.BidSize, ok = response[3].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert bidSize")
|
||||
}
|
||||
if t.Ask, ok = response[4].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert ask")
|
||||
}
|
||||
var askPeriod float64
|
||||
askPeriod, ok = response[5].(float64)
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert askPeriod")
|
||||
}
|
||||
t.AskPeriod = int64(askPeriod)
|
||||
if t.AskSize, ok = response[6].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert askSize")
|
||||
}
|
||||
if t.DailyChange, ok = response[7].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert dailyChange")
|
||||
}
|
||||
if t.DailyChangePerc, ok = response[8].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert dailyChangePerc")
|
||||
}
|
||||
if t.Last, ok = response[9].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert last")
|
||||
}
|
||||
if t.Volume, ok = response[10].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert volume")
|
||||
}
|
||||
if t.High, ok = response[11].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert high")
|
||||
}
|
||||
if t.Low, ok = response[12].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert low")
|
||||
}
|
||||
if t.FFRAmountAvailable, ok = response[15].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert FFRAmountAvailable")
|
||||
}
|
||||
return &t, nil
|
||||
}
|
||||
return Ticker{
|
||||
Bid: response[0].(float64),
|
||||
BidSize: response[1].(float64),
|
||||
Ask: response[2].(float64),
|
||||
AskSize: response[3].(float64),
|
||||
DailyChange: response[4].(float64),
|
||||
DailyChangePerc: response[5].(float64),
|
||||
Last: response[6].(float64),
|
||||
Volume: response[7].(float64),
|
||||
High: response[8].(float64),
|
||||
Low: response[9].(float64),
|
||||
}, nil
|
||||
|
||||
var ok bool
|
||||
if t.Bid, ok = response[0].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert bid")
|
||||
}
|
||||
if t.BidSize, ok = response[1].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert bidSize")
|
||||
}
|
||||
if t.Ask, ok = response[2].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert ask")
|
||||
}
|
||||
if t.AskSize, ok = response[3].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert askSize")
|
||||
}
|
||||
if t.DailyChange, ok = response[4].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert dailyChange")
|
||||
}
|
||||
if t.DailyChangePerc, ok = response[5].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert dailyChangePerc")
|
||||
}
|
||||
if t.Last, ok = response[6].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert last")
|
||||
}
|
||||
if t.Volume, ok = response[7].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert volume")
|
||||
}
|
||||
if t.High, ok = response[8].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert high")
|
||||
}
|
||||
if t.Low, ok = response[9].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert low")
|
||||
}
|
||||
return &t, nil
|
||||
}
|
||||
|
||||
// GetTrades gets historic trades that occurred on the exchange
|
||||
@@ -637,7 +753,7 @@ func (b *Bitfinex) GetTrades(ctx context.Context, currencyPair string, limit, ti
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var history []Trade
|
||||
history := make([]Trade, len(resp))
|
||||
for i := range resp {
|
||||
amount, ok := resp[i][2].(float64)
|
||||
if !ok {
|
||||
@@ -649,25 +765,49 @@ func (b *Bitfinex) GetTrades(ctx context.Context, currencyPair string, limit, ti
|
||||
amount *= -1
|
||||
}
|
||||
|
||||
if len(resp[i]) > 4 {
|
||||
history = append(history, Trade{
|
||||
TID: int64(resp[i][0].(float64)),
|
||||
Timestamp: int64(resp[i][1].(float64)),
|
||||
Amount: amount,
|
||||
Rate: resp[i][3].(float64),
|
||||
Period: int64(resp[i][4].(float64)),
|
||||
Type: side,
|
||||
})
|
||||
continue
|
||||
tid, ok := resp[i][0].(float64)
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert trade ID")
|
||||
}
|
||||
timestamp, ok := resp[i][1].(float64)
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert timestamp")
|
||||
}
|
||||
|
||||
history = append(history, Trade{
|
||||
TID: int64(resp[i][0].(float64)),
|
||||
Timestamp: int64(resp[i][1].(float64)),
|
||||
if len(resp[i]) > 4 {
|
||||
var rate float64
|
||||
rate, ok = resp[i][3].(float64)
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert rate")
|
||||
}
|
||||
var period float64
|
||||
period, ok = resp[i][4].(float64)
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert period")
|
||||
}
|
||||
|
||||
history[i] = Trade{
|
||||
TID: int64(tid),
|
||||
Timestamp: int64(timestamp),
|
||||
Amount: amount,
|
||||
Rate: rate,
|
||||
Period: int64(period),
|
||||
Type: side,
|
||||
}
|
||||
continue
|
||||
}
|
||||
price, ok := resp[i][3].(float64)
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert price")
|
||||
}
|
||||
|
||||
history[i] = Trade{
|
||||
TID: int64(tid),
|
||||
Timestamp: int64(timestamp),
|
||||
Amount: amount,
|
||||
Price: resp[i][3].(float64),
|
||||
Price: price,
|
||||
Type: side,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return history, nil
|
||||
@@ -873,19 +1013,33 @@ func (b *Bitfinex) GetCandles(ctx context.Context, symbol, timeFrame string, sta
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var c []Candle
|
||||
candles := make([]Candle, len(response))
|
||||
for i := range response {
|
||||
c = append(c, Candle{
|
||||
Timestamp: time.Unix(int64(response[i][0].(float64)/1000), 0),
|
||||
Open: response[i][1].(float64),
|
||||
Close: response[i][2].(float64),
|
||||
High: response[i][3].(float64),
|
||||
Low: response[i][4].(float64),
|
||||
Volume: response[i][5].(float64),
|
||||
})
|
||||
var c Candle
|
||||
timestamp, ok := response[i][0].(float64)
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert timestamp")
|
||||
}
|
||||
c.Timestamp = time.UnixMilli(int64(timestamp))
|
||||
if c.Open, ok = response[i][1].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert open")
|
||||
}
|
||||
if c.Close, ok = response[i][2].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert close")
|
||||
}
|
||||
if c.High, ok = response[i][3].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert high")
|
||||
}
|
||||
if c.Low, ok = response[i][4].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert low")
|
||||
}
|
||||
if c.Volume, ok = response[i][5].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert volume")
|
||||
}
|
||||
candles[i] = c
|
||||
}
|
||||
|
||||
return c, nil
|
||||
return candles, nil
|
||||
}
|
||||
|
||||
path += "/last"
|
||||
@@ -900,14 +1054,29 @@ func (b *Bitfinex) GetCandles(ctx context.Context, symbol, timeFrame string, sta
|
||||
return nil, errors.New("no data returned")
|
||||
}
|
||||
|
||||
return []Candle{{
|
||||
Timestamp: time.Unix(int64(response[0].(float64))/1000, 0),
|
||||
Open: response[1].(float64),
|
||||
Close: response[2].(float64),
|
||||
High: response[3].(float64),
|
||||
Low: response[4].(float64),
|
||||
Volume: response[5].(float64),
|
||||
}}, nil
|
||||
var c Candle
|
||||
timestamp, ok := response[0].(float64)
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert timestamp")
|
||||
}
|
||||
c.Timestamp = time.UnixMilli(int64(timestamp))
|
||||
if c.Open, ok = response[1].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert open")
|
||||
}
|
||||
if c.Close, ok = response[2].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert close")
|
||||
}
|
||||
if c.High, ok = response[3].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert high")
|
||||
}
|
||||
if c.Low, ok = response[4].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert low")
|
||||
}
|
||||
if c.Volume, ok = response[5].(float64); !ok {
|
||||
return nil, errors.New("unable to type assert volume")
|
||||
}
|
||||
|
||||
return []Candle{c}, nil
|
||||
}
|
||||
|
||||
// GetConfigurations fetchs currency and symbol site configuration data.
|
||||
@@ -983,7 +1152,7 @@ func (b *Bitfinex) GetLeaderboard(ctx context.Context, key, timeframe, symbol st
|
||||
return r
|
||||
}
|
||||
|
||||
var result []LeaderboardEntry
|
||||
result := make([]LeaderboardEntry, len(resp))
|
||||
for x := range resp {
|
||||
r, ok := resp[x].([]interface{})
|
||||
if !ok {
|
||||
@@ -1008,13 +1177,13 @@ func (b *Bitfinex) GetLeaderboard(ctx context.Context, key, timeframe, symbol st
|
||||
if !ok {
|
||||
return nil, errors.New("unable to type assert value")
|
||||
}
|
||||
result = append(result, LeaderboardEntry{
|
||||
result[x] = LeaderboardEntry{
|
||||
Timestamp: time.UnixMilli(int64(tm)),
|
||||
Username: username,
|
||||
Ranking: int(ranking),
|
||||
Value: value,
|
||||
TwitterHandle: parseTwitterHandle(r[9]),
|
||||
})
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@@ -1311,6 +1311,7 @@ func TestWsOrderSnapshot(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWsNotifications(t *testing.T) {
|
||||
b.WsAddSubscriptionChannel(0, "account", "N/A")
|
||||
pressXToJSON := `[0,"n",[1575282446099,"fon-req",null,null,[41238905,null,null,null,-1000,null,null,null,null,null,null,null,null,null,0.002,2,null,null,null,null,null],null,"SUCCESS","Submitting funding bid of 1000.0 USD at 0.2000 for 2 days."]]`
|
||||
err := b.wsHandleData([]byte(pressXToJSON))
|
||||
if err != nil {
|
||||
@@ -1324,6 +1325,90 @@ func TestWsNotifications(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestWSFundingOfferSnapshotAndUpdate(t *testing.T) {
|
||||
b.WsAddSubscriptionChannel(0, "account", "N/A")
|
||||
pressXToJSON := `[0,"fos",[[41237920,"fETH",1573912039000,1573912039000,0.5,0.5,"LIMIT",null,null,0,"ACTIVE",null,null,null,0.0024,2,0,0,null,0,null]]]`
|
||||
if err := b.wsHandleData([]byte(pressXToJSON)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
pressXToJSON = `[0,"fon",[41238747,"fUST",1575026670000,1575026670000,5000,5000,"LIMIT",null,null,0,"ACTIVE",null,null,null,0.006000000000000001,30,0,0,null,0,null]]`
|
||||
if err := b.wsHandleData([]byte(pressXToJSON)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWSFundingCreditSnapshotAndUpdate(t *testing.T) {
|
||||
b.WsAddSubscriptionChannel(0, "account", "N/A")
|
||||
pressXToJSON := `[0,"fcs",[[26223578,"fUST",1,1575052261000,1575296187000,350,0,"ACTIVE",null,null,null,0,30,1575052261000,1575293487000,0,0,null,0,null,0,"tBTCUST"],[26223711,"fUSD",-1,1575291961000,1575296187000,180,0,"ACTIVE",null,null,null,0.002,7,1575282446000,1575295587000,0,0,null,0,null,0,"tETHUSD"]]]`
|
||||
if err := b.wsHandleData([]byte(pressXToJSON)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
pressXToJSON = `[0,"fcu",[26223578,"fUST",1,1575052261000,1575296787000,350,0,"ACTIVE",null,null,null,0,30,1575052261000,1575293487000,0,0,null,0,null,0,"tBTCUST"]]`
|
||||
if err := b.wsHandleData([]byte(pressXToJSON)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWSFundingLoanSnapshotAndUpdate(t *testing.T) {
|
||||
b.WsAddSubscriptionChannel(0, "account", "N/A")
|
||||
pressXToJSON := `[0,"fls",[[2995442,"fUSD",-1,1575291961000,1575295850000,820,0,"ACTIVE",null,null,null,0.002,7,1575282446000,1575295850000,0,0,null,0,null,0]]]`
|
||||
if err := b.wsHandleData([]byte(pressXToJSON)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
pressXToJSON = `[0,"fln",[2995444,"fUSD",-1,1575298742000,1575298742000,1000,0,"ACTIVE",null,null,null,0.002,7,1575298742000,1575298742000,0,0,null,0,null,0]]`
|
||||
if err := b.wsHandleData([]byte(pressXToJSON)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWSWalletSnapshot(t *testing.T) {
|
||||
b.WsAddSubscriptionChannel(0, "account", "N/A")
|
||||
pressXToJSON := `[0,"ws",[["exchange","SAN",19.76,0,null,null,null]]]`
|
||||
if err := b.wsHandleData([]byte(pressXToJSON)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWSBalanceUpdate(t *testing.T) {
|
||||
b.WsAddSubscriptionChannel(0, "account", "N/A")
|
||||
const pressXToJSON = `[0,"bu",[4131.85,4131.85]]`
|
||||
if err := b.wsHandleData([]byte(pressXToJSON)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWSMarginInfoUpdate(t *testing.T) {
|
||||
b.WsAddSubscriptionChannel(0, "account", "N/A")
|
||||
const pressXToJSON = `[0,"miu",["base",[-13.014640000000007,0,49331.70267297,49318.68803297,27]]]`
|
||||
if err := b.wsHandleData([]byte(pressXToJSON)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWSFundingInfoUpdate(t *testing.T) {
|
||||
b.WsAddSubscriptionChannel(0, "account", "N/A")
|
||||
const pressXToJSON = `[0,"fiu",["sym","tETHUSD",[149361.09689202666,149639.26293509,830.0182168075556,895.0658432466332]]]`
|
||||
if err := b.wsHandleData([]byte(pressXToJSON)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWSFundingTrade(t *testing.T) {
|
||||
b.WsAddSubscriptionChannel(0, "account", "N/A")
|
||||
pressXToJSON := `[0,"fte",[636854,"fUSD",1575282446000,41238905,-1000,0.002,7,null]]`
|
||||
if err := b.wsHandleData([]byte(pressXToJSON)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
pressXToJSON = `[0,"ftu",[636854,"fUSD",1575282446000,41238905,-1000,0.002,7,null]]`
|
||||
if err := b.wsHandleData([]byte(pressXToJSON)); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetHistoricCandles(t *testing.T) {
|
||||
currencyPair, err := currency.NewPairFromString("BTCUSD")
|
||||
if err != nil {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user