Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exchange templates update #2

Open
wants to merge 114 commits into
base: exch_tmpl_fix
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
114 commits
Select commit Hold shift + click to select a range
00f1bee
build(deps): Bump bufbuild/buf-setup-action from 1.29.0 to 1.30.0 (#1…
dependabot[bot] Mar 11, 2024
13ed40a
build(deps): Bump golang.org/x/net from 0.21.0 to 0.22.0 (#1497)
dependabot[bot] Mar 11, 2024
d679a76
build(deps): Bump google.golang.org/grpc from 1.62.0 to 1.62.1 (#1500)
dependabot[bot] Mar 11, 2024
9d1476d
Coinut: Fix websocket not parsing instruments, improve nonce matching…
gbjk Mar 15, 2024
3e4b9be
Tests: Abstract UpdatePairsOnce (#1503)
gbjk Mar 15, 2024
044f2cd
build(deps): Bump google.golang.org/protobuf from 1.32.0 to 1.33.0 an…
dependabot[bot] Mar 15, 2024
3aad665
common/timedmutex: clean and improve (#1486)
shazbert Mar 20, 2024
05dec88
request: fix intermittent race when verbose and reading the body in d…
shazbert Mar 25, 2024
b115b2b
minor exchange template update
samuael Mar 26, 2024
e64ae62
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Mar 26, 2024
917dd6b
Minor fix to test_files template
samuael Mar 26, 2024
9d7bc3e
build(deps): Bump golang.org/x/net from 0.22.0 to 0.24.0 (#1512)
dependabot[bot] Apr 8, 2024
5b2251b
build(deps): Bump bufbuild/buf-setup-action from 1.30.0 to 1.30.1 (#1…
dependabot[bot] Apr 8, 2024
98eae1e
build(deps): Bump google.golang.org/grpc from 1.62.1 to 1.63.0 (#1513)
dependabot[bot] Apr 10, 2024
9657a57
exchanges: shift GetDefaultConfig wrapper function to exchange.go (#1…
shazbert Apr 12, 2024
e823f9e
request/nonce: Refactor to simplify package and prevent consecutive m…
shazbert Apr 12, 2024
b909e15
Bithumb: Enhance test coverage (#1509)
Beadko Apr 15, 2024
6fc6dcd
build(deps): Bump github.com/shopspring/decimal from 1.3.1 to 1.4.0 (…
dependabot[bot] Apr 15, 2024
07af828
build(deps): Bump google.golang.org/grpc from 1.63.0 to 1.63.2 (#1517)
dependabot[bot] Apr 15, 2024
c967d8a
Kraken: Fix wsCancelOrders not erroring with order id (#1505)
gbjk Apr 17, 2024
7b842c2
go: Fix darwin/arm64: toolchain not available version directive (#1523)
gemscng Apr 19, 2024
fdf6014
Currency: Remove Pair Index formatting/parsing (#1520)
gbjk Apr 19, 2024
44d50a3
Kraken: Fix GetLatestFundingRates requiring pair enabled (#1522)
gbjk Apr 19, 2024
694f2f7
gateio: fix spot/futures order issues (#1524)
shazbert Apr 29, 2024
7bad4f7
build(deps): Bump bufbuild/buf-setup-action from 1.30.1 to 1.31.0 (#1…
dependabot[bot] Apr 29, 2024
b46b793
build(deps): Bump github.com/urfave/cli/v2 from 2.27.1 to 2.27.2 (#1527)
dependabot[bot] Apr 29, 2024
1e95ae9
qa: Enforce JSON standard for GCT configs (#1526)
thrasher- Apr 30, 2024
0658b27
build(deps): Bump golangci/golangci-lint-action from 4 to 5 (#1529)
dependabot[bot] May 1, 2024
0676c78
btcmarkets: remove trailing slash on markets/ticker strings and updat…
shazbert May 3, 2024
f1ff951
engine/exchanges: Add GetCurrencyTradeURL wrapper func/gRPC endpoint …
gloriousCode May 3, 2024
a46622a
Bitstamp: Add missing API fields and enhance test coverage (#1510)
Beadko May 6, 2024
da98bd4
build(deps): Bump golang.org/x/text from 0.14.0 to 0.15.0 (#1535)
dependabot[bot] May 6, 2024
3ee65b9
build(deps): Bump google.golang.org/protobuf from 1.33.0 to 1.34.0 (#…
dependabot[bot] May 6, 2024
ece58eb
Bybit: Add support for SOL options (#1533)
gloriousCode May 6, 2024
93c2d01
Test: Internal exchange coverage (#1525)
gbjk May 7, 2024
095394f
build(deps): Bump ikalnytskyi/action-setup-postgres from 5 to 6 (#1537)
dependabot[bot] May 7, 2024
b306095
build(deps): Bump google.golang.org/protobuf from 1.34.0 to 1.34.1 (#…
dependabot[bot] May 13, 2024
b2d7bee
build(deps): Bump golang.org/x/net from 0.24.0 to 0.25.0 (#1540)
dependabot[bot] May 13, 2024
2a92878
build(deps): Bump golangci/golangci-lint-action from 5 to 6 (#1543)
dependabot[bot] May 13, 2024
4cd4fb0
orderbook: Refactor package structure for simplicity and efficiency (…
shazbert May 14, 2024
34ef09d
bugfixes: Backtester credentials, Binance ExecutionLimits, Mock recor…
gloriousCode May 15, 2024
7d1eecf
Tests: Various race fixes and move TestFixtureToDataHandler (#1534)
gbjk May 16, 2024
ca9efe7
currency/manager: remove deadlock potential in concurrent operations …
shazbert May 17, 2024
bd33fc4
build(deps): Bump github.com/grpc-ecosystem/grpc-gateway/v2 (#1547)
dependabot[bot] May 20, 2024
3ae0ecf
build(deps): Bump bufbuild/buf-setup-action from 1.31.0 to 1.32.0 (#1…
dependabot[bot] May 20, 2024
d6bace3
build(deps): Bump bufbuild/buf-setup-action from 1.32.0 to 1.32.1 (#1…
dependabot[bot] May 27, 2024
c37a115
Linter: Spelling fixes (#1554)
gbjk May 28, 2024
aeb4a87
exchanges: Add Deribit exchange support (#1082)
samuael May 29, 2024
f6a95da
exchanges/request: abstract and consolidate rate limiting code to req…
shazbert Jun 3, 2024
abba66f
build(deps): Bump bufbuild/buf-setup-action from 1.32.1 to 1.32.2 (#1…
dependabot[bot] Jun 3, 2024
afb6f75
build(deps): Bump github.com/spf13/viper from 1.18.2 to 1.19.0 (#1560)
dependabot[bot] Jun 3, 2024
1199f38
subscriptions: Encapsulate, replace Pair with Pairs and refactor; imp…
gbjk Jun 7, 2024
e16e16b
Deribit: bug fixes, test fixes and implement GetCurrencyTradeURL (#1558)
gloriousCode Jun 7, 2024
eacf14c
build(deps): Bump golang.org/x/net from 0.25.0 to 0.26.0 (#1562)
dependabot[bot] Jun 10, 2024
06b9980
build(deps): Bump github.com/gorilla/websocket from 1.5.1 to 1.5.2 (#…
dependabot[bot] Jun 10, 2024
4c4b693
gateio: update FuturesAccount and Position structs; rename gateioTime…
shazbert Jun 14, 2024
98f025e
BTSE: Various fixes (#1550)
gbjk Jun 14, 2024
5f05907
build(deps): Bump google.golang.org/protobuf from 1.34.1 to 1.34.2 (#…
dependabot[bot] Jun 17, 2024
2cf2ead
build(deps): Bump bufbuild/buf-setup-action from 1.32.2 to 1.33.0 and…
dependabot[bot] Jun 18, 2024
5946933
build(deps): Bump github.com/gorilla/websocket from 1.5.2 to 1.5.3 (#…
dependabot[bot] Jun 20, 2024
258b60c
build(deps): Bump bufbuild/buf-setup-action from 1.33.0 to 1.34.0 (#1…
dependabot[bot] Jul 1, 2024
b7a2f61
Bybit: Fix WS ticker processing (#1538)
gbjk Jul 3, 2024
48349bc
protocol/order: adds additional fields for trading requirements (#1552)
shazbert Jul 3, 2024
03c1fb7
Bybit: Add missing field min notional (#1574)
shazbert Jul 4, 2024
d4c3a66
build(deps): Bump golang.org/x/net from 0.26.0 to 0.27.0 (#1577)
dependabot[bot] Jul 8, 2024
00c5c95
build(deps): Bump google.golang.org/grpc from 1.64.0 to 1.65.0 (#1576)
dependabot[bot] Jul 8, 2024
c601575
subscriptions: Add templating support and integrate with Binance (#1568)
gbjk Jul 9, 2024
90fee94
currency: Make pairs.Add variadic (#1566)
cranktakular Jul 12, 2024
db59b85
log: allow external definition of log handling (#1561)
shazbert Jul 19, 2024
4f1696f
Subscriptions: Fix subscription.Clone Params and Pairs (#1582)
gbjk Jul 19, 2024
34d9920
Okx: Fix TestGetBlockTrade transient fail (#1583)
gbjk Jul 19, 2024
45ef2b1
Gateio: Add unified account API endpoint support (#1573)
shazbert Jul 23, 2024
425ec0c
orders/gateio: Add GetTradeAmount method to order.Submit type (#1584)
shazbert Jul 23, 2024
d1e3669
Subscriptions: Add List.Clone (#1592)
gbjk Jul 26, 2024
ba3dcc8
Bybit: Fix UpdateAccountInfo coin balance issue, improve GetWalletBal…
thrasher- Jul 29, 2024
0c5d049
Kraken: Simplify REST error and result handling (#1591)
thrasher- Jul 29, 2024
d60ea77
build(deps): Bump github.com/urfave/cli/v2 from 2.27.2 to 2.27.3 (#1594)
dependabot[bot] Jul 29, 2024
1db4622
build(deps): Bump bufbuild/buf-setup-action from 1.34.0 to 1.35.1 (#1…
dependabot[bot] Jul 29, 2024
deaee80
build(deps): Bump github.com/grpc-ecosystem/grpc-gateway/v2 (#1595)
dependabot[bot] Jul 29, 2024
7e83f10
build(deps): Bump golang.org/x/time from 0.5.0 to 0.6.0 (#1602)
dependabot[bot] Aug 5, 2024
b41fe27
Kucoin: Add subscription templating and various fixes (#1579)
gbjk Aug 9, 2024
5f44655
build(deps): Bump golang.org/x/net from 0.27.0 to 0.28.0 (#1607)
dependabot[bot] Aug 12, 2024
1957734
build(deps): Bump bufbuild/buf-setup-action from 1.35.1 to 1.36.0 (#1…
dependabot[bot] Aug 12, 2024
b602d54
build(deps): Bump github.com/urfave/cli/v2 from 2.27.3 to 2.27.4 (#1608)
dependabot[bot] Aug 12, 2024
91ff6c5
orderbook/gateio: add field `UpdatePushedAt` and `InsertedAt` for spe…
shazbert Aug 15, 2024
0becfbd
Kraken: Fix TestGetOpenInterest (#1611)
gbjk Aug 16, 2024
facf291
currency/exchanges: Add bespoke exchange translator and pair matching…
shazbert Aug 16, 2024
225429b
CI/build: Update Go version, linters and fix minor issues (#1612)
thrasher- Aug 16, 2024
17c2ef2
stream/match: Reduce complexity and limit locking when match occurs (…
shazbert Aug 19, 2024
d7907c2
build(deps): Bump bufbuild/buf-setup-action from 1.36.0 to 1.37.0 (#1…
dependabot[bot] Aug 19, 2024
03e9809
build(deps): Bump github.com/grpc-ecosystem/grpc-gateway/v2 (#1621)
dependabot[bot] Aug 19, 2024
1cabba7
common/gateio/stream: add thread-safe counter and overide default Gen…
shazbert Aug 24, 2024
74f4df6
okcoin: Remove exchange implementation (#1626)
thrasher- Aug 24, 2024
f3dda71
build(deps): Bump bufbuild/buf-setup-action from 1.37.0 to 1.38.0 (#1…
dependabot[bot] Aug 26, 2024
15e0eed
tests: Fix various issues (#1634)
thrasher- Aug 27, 2024
649f3df
engine: Add overridable exchanges command line flag (#1630)
thrasher- Aug 27, 2024
2605eab
build(deps): Bump google.golang.org/grpc from 1.65.0 to 1.66.0 (#1637)
dependabot[bot] Sep 2, 2024
7c9e651
build(deps): Bump bufbuild/buf-setup-action from 1.38.0 to 1.39.0 (#1…
dependabot[bot] Sep 2, 2024
cb6b342
exchanges/websocket: update websocket rate limiting to use requester …
shazbert Sep 2, 2024
360afa5
build(deps): Bump golang.org/x/net from 0.28.0 to 0.29.0 (#1643)
dependabot[bot] Sep 9, 2024
4a4d666
build(deps): Bump bufbuild/buf-setup-action from 1.39.0 to 1.40.1 (#1…
dependabot[bot] Sep 9, 2024
a82f0bf
build(deps): Bump github.com/mattn/go-sqlite3 from 1.14.22 to 1.14.23…
dependabot[bot] Sep 9, 2024
46f3080
gateio: fix and optimise time parsing (#1647)
shazbert Sep 12, 2024
22cb0eb
stream: Add verbosity to outbound requests that also returns response…
shazbert Sep 12, 2024
b8e836d
common: Replace StringDataCompare with slices.Contains and cleanup st…
thrasher- Sep 13, 2024
b461c32
stream/okx: allow rate limit definitions to be used by the stream pac…
shazbert Sep 13, 2024
d94b8af
exchanges: Kucoin Update (#1438)
samuael Sep 13, 2024
3ebd2da
CoinbasePro: Skip specific tests due to API deprecation (#1649)
thrasher- Sep 16, 2024
5e663b0
build(deps): Bump bufbuild/buf-setup-action from 1.40.1 to 1.41.0 (#1…
dependabot[bot] Sep 16, 2024
aef8a1f
build(deps): Bump google.golang.org/grpc from 1.66.0 to 1.66.2 (#1651)
dependabot[bot] Sep 16, 2024
c96c0b0
Binance: Fix occassional race failure on TestWsOrderExecutionReport (…
gbjk Sep 19, 2024
007f671
build(deps): Bump bufbuild/buf-setup-action from 1.41.0 to 1.42.0 (#1…
dependabot[bot] Sep 23, 2024
a09fefe
build(deps): Bump google.golang.org/grpc from 1.66.2 to 1.67.0 (#1657)
dependabot[bot] Sep 23, 2024
35b90d1
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Sep 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Tests: Various race fixes and move TestFixtureToDataHandler (thrasher…
…-corp#1534)

* Tests: Move and simplify TestFixtureToDataHandler

* Currency: Fix PairsManager.Load breaking matcher

* Tests: Add multi-instance cache to UpdatePairsOnce

* Kraken: Fix TestUpdateTickers race error

Calling StorePairs on global instance can lead to race

* Bitfinex: Fix TestUpdateTickers racing intermittently

* Currency: Fix concurrent access to PM formats

* Currency: Fix SupportsAsset implementation

This should delegate entirely to PairManager's IsAssetSupported

* Okx: Fix PM intrusion, rm GetPairFromInstrumentID

* Exchange: Fix SetGlobalPairsManager to set asset enabled

* Bitflyer: Fix race on set TestGetCurrURL

TestGetCurrencyTradeURL would fail sometimes due to sequencing of
enabling futures but not having pairs for it.

* Tests: Simplify usage pattern for FixtureToDH
  • Loading branch information
gbjk authored May 16, 2024
commit 7d1eecfa7ef4ba9c0f2ddd153639c38478c9f34d
26 changes: 10 additions & 16 deletions backtester/eventhandlers/exchange/slippage/slippage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"testing"

"github.com/shopspring/decimal"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/thrasher-corp/gocryptotrader/currency"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
"github.com/thrasher-corp/gocryptotrader/exchanges/bitstamp"
Expand All @@ -14,31 +16,23 @@ import (
func TestRandomSlippage(t *testing.T) {
t.Parallel()
resp := EstimateSlippagePercentage(decimal.NewFromInt(80), decimal.NewFromInt(100))
if resp.LessThan(decimal.NewFromFloat(0.8)) || resp.GreaterThan(decimal.NewFromInt(1)) {
t.Error("expected result > 0.8 and < 100")
}
assert.True(t, resp.GreaterThan(decimal.NewFromFloat(0.8)), "result should be more than 0.8")
assert.True(t, resp.LessThan(decimal.NewFromInt(1)), "result should be less than 1")
}

func TestCalculateSlippageByOrderbook(t *testing.T) {
t.Parallel()
b := bitstamp.Bitstamp{}
b.SetDefaults()
err := b.CurrencyPairs.SetAssetEnabled(asset.Spot, true)
if err != nil {
t.Fatal(err)
}

cp := currency.NewPair(currency.BTC, currency.USD)
ob, err := b.FetchOrderbook(context.Background(), cp, asset.Spot)
if err != nil {
t.Error(err)
}
require.NoError(t, err, "FetchOrderbook must not error")

amountOfFunds := decimal.NewFromInt(1000)
feeRate := decimal.NewFromFloat(0.03)
price, amount, err := CalculateSlippageByOrderbook(ob, gctorder.Buy, amountOfFunds, feeRate)
if err != nil {
t.Fatal(err)
}
if price.Mul(amount).Add(price.Mul(amount).Mul(feeRate)).GreaterThan(amountOfFunds) {
t.Error("order size must be less than funds")
}
require.NoError(t, err, "CalculateSlippageByOrderbook must not error")
orderSize := price.Mul(amount).Add(price.Mul(amount).Mul(feeRate))
assert.True(t, orderSize.LessThan(amountOfFunds), "order size must be less than funds")
}
214 changes: 102 additions & 112 deletions currency/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,30 @@ import (
"encoding/json"
"errors"
"fmt"
"slices"
"strings"

"github.com/thrasher-corp/gocryptotrader/common"
"github.com/thrasher-corp/gocryptotrader/common/convert"
"github.com/thrasher-corp/gocryptotrader/exchanges/asset"
)

// Public errors
var (
// ErrAssetAlreadyEnabled defines an error for the pairs management system
// that declares the asset is already enabled.
ErrAssetAlreadyEnabled = errors.New("asset already enabled")
// ErrPairAlreadyEnabled returns when enabling a pair that is already enabled
ErrPairAlreadyEnabled = errors.New("pair already enabled")
// ErrPairNotEnabled returns when looking for a pair that is not enabled
ErrPairNotEnabled = errors.New("pair not enabled")
// ErrPairNotFound is returned when a currency pair is not found
ErrPairNotFound = errors.New("pair not found")
// ErrAssetIsNil is an error when the asset has not been populated by the
// configuration
ErrAssetIsNil = errors.New("asset is nil")
// ErrPairNotContainedInAvailablePairs defines an error when a pair is not
// contained in the available pairs list and is not supported by the
// exchange for that asset type.
ErrAssetAlreadyEnabled = errors.New("asset already enabled")
ErrAssetIsNil = errors.New("asset is nil")
ErrAssetNotFound = errors.New("asset type not found in pair store")
ErrPairAlreadyEnabled = errors.New("pair already enabled")
ErrPairFormatIsNil = errors.New("pair format is nil")
ErrPairManagerNotInitialised = errors.New("pair manager not initialised")
ErrPairNotContainedInAvailablePairs = errors.New("pair not contained in available pairs")
// ErrPairManagerNotInitialised is returned when a pairs manager is requested, but has not been setup
ErrPairManagerNotInitialised = errors.New("pair manager not initialised")
// ErrAssetNotFound is returned when an asset does not exist in the pairstore
ErrAssetNotFound = errors.New("asset type not found in pair store")
// ErrSymbolStringEmpty is an error when a symbol string is empty
ErrSymbolStringEmpty = errors.New("symbol string is empty")
ErrPairNotEnabled = errors.New("pair not enabled")
ErrPairNotFound = errors.New("pair not found")
ErrSymbolStringEmpty = errors.New("symbol string is empty")
)

var (
errPairStoreIsNil = errors.New("pair store is nil")
errPairFormatIsNil = errors.New("pair format is nil")
errPairMatcherIsNil = errors.New("pair matcher is nil")
errPairConfigFormatNil = errors.New("pair config format is nil")
)
Expand Down Expand Up @@ -65,10 +56,9 @@ func (p *PairsManager) Get(a asset.Item) (*PairStore, error) {
defer p.mutex.RUnlock()
c, ok := p.Pairs[a]
if !ok {
return nil,
fmt.Errorf("cannot get pair store, %v %w", a, asset.ErrNotSupported)
return nil, fmt.Errorf("cannot get pair store, %v %w", a, asset.ErrNotSupported)
}
return c.copy()
return c.clone(), nil
}

// Match returns a currency pair based on the supplied symbol and asset type
Expand All @@ -94,24 +84,16 @@ func (p *PairsManager) Store(a asset.Item, ps *PairStore) error {
if !a.IsValid() {
return fmt.Errorf("%s %w", a, asset.ErrNotSupported)
}
cpy, err := ps.copy()
if err != nil {
return err
if ps == nil {
return errPairStoreIsNil
}
p.mutex.Lock()
defer p.mutex.Unlock()
if p.Pairs == nil {
p.Pairs = make(map[asset.Item]*PairStore)
p.Pairs = FullStore{}
}
p.Pairs[a] = cpy
if p.matcher == nil {
p.matcher = make(map[key]*Pair)
}
for x := range cpy.Available {
p.matcher[key{
Symbol: cpy.Available[x].Base.Lower().String() + cpy.Available[x].Quote.Lower().String(),
Asset: a}] = &cpy.Available[x]
}
p.mutex.Unlock()
p.Pairs[a] = ps.clone()
p.reindex()
return nil
}

Expand Down Expand Up @@ -145,9 +127,7 @@ func (p *PairsManager) GetPairs(a asset.Item, enabled bool) (Pairs, error) {
}

if !enabled {
availPairs := make(Pairs, len(pairStore.Available))
copy(availPairs, pairStore.Available)
return availPairs, nil
return slices.Clone(pairStore.Available), nil
}

lenCheck := len(pairStore.Enabled)
Expand All @@ -157,8 +137,7 @@ func (p *PairsManager) GetPairs(a asset.Item, enabled bool) (Pairs, error) {

// NOTE: enabledPairs is declared before the next check for comparison
// reasons within exchange update pairs functionality.
enabledPairs := make(Pairs, lenCheck)
copy(enabledPairs, pairStore.Enabled)
enabledPairs := slices.Clone(pairStore.Enabled)

err := pairStore.Available.ContainsAll(pairStore.Enabled, true)
if err != nil {
Expand All @@ -173,11 +152,9 @@ func (p *PairsManager) StoreFormat(a asset.Item, pFmt *PairFormat, config bool)
return fmt.Errorf("%s %w", a, asset.ErrNotSupported)
}
if pFmt == nil {
return errPairFormatIsNil
return ErrPairFormatIsNil
}

cpy := *pFmt

p.mutex.Lock()
defer p.mutex.Unlock()

Expand All @@ -192,25 +169,49 @@ func (p *PairsManager) StoreFormat(a asset.Item, pFmt *PairFormat, config bool)
}

if config {
pairStore.ConfigFormat = &cpy
pairStore.ConfigFormat = pFmt.clone()
} else {
pairStore.RequestFormat = &cpy
pairStore.RequestFormat = pFmt.clone()
}
return nil
}

// GetFormat returns the pair format in a concurrent safe manner
func (p *PairsManager) GetFormat(a asset.Item, request bool) (PairFormat, error) {
p.mutex.RLock()
defer p.mutex.RUnlock()

var pFmt *PairFormat
if p.UseGlobalFormat {
if request {
pFmt = p.RequestFormat
} else {
pFmt = p.ConfigFormat
}
} else {
ps, err := p.Get(a)
if err != nil {
return EMPTYFORMAT, err
}
if request {
pFmt = ps.RequestFormat
} else {
pFmt = ps.ConfigFormat
}
}
if pFmt == nil {
return EMPTYFORMAT, ErrPairFormatIsNil
}
return *pFmt, nil
}

// StorePairs stores a list of pairs based on the asset type and whether
// they're enabled or not
func (p *PairsManager) StorePairs(a asset.Item, pairs Pairs, enabled bool) error {
if !a.IsValid() {
return fmt.Errorf("%s %w", a, asset.ErrNotSupported)
}

// NOTE: Length check not needed in this scenario as it has the ability to
// remove the entire stored list if needed.
cpy := make(Pairs, len(pairs))
copy(cpy, pairs)

p.mutex.Lock()
defer p.mutex.Unlock()

Expand All @@ -225,18 +226,10 @@ func (p *PairsManager) StorePairs(a asset.Item, pairs Pairs, enabled bool) error
}

if enabled {
pairStore.Enabled = cpy
pairStore.Enabled = slices.Clone(pairs)
} else {
pairStore.Available = cpy

if p.matcher == nil {
p.matcher = make(map[key]*Pair)
}
for x := range pairStore.Available {
p.matcher[key{
Symbol: pairStore.Available[x].Base.Lower().String() + pairStore.Available[x].Quote.Lower().String(),
Asset: a}] = &pairStore.Available[x]
}
pairStore.Available = slices.Clone(pairs)
p.reindex()
}

return nil
Expand Down Expand Up @@ -405,6 +398,15 @@ func (p *PairsManager) IsAssetEnabled(a asset.Item) error {
return nil
}

// IsAssetSupported returns if the asset is supported by an exchange
// Does not imply that the Asset is enabled
func (p *PairsManager) IsAssetSupported(a asset.Item) bool {
p.mutex.RLock()
defer p.mutex.RUnlock()
_, ok := p.Pairs[a]
return ok
}

// SetAssetEnabled sets if an asset is enabled or disabled for first run
func (p *PairsManager) SetAssetEnabled(a asset.Item, enabled bool) error {
if !a.IsValid() {
Expand Down Expand Up @@ -435,34 +437,31 @@ func (p *PairsManager) SetAssetEnabled(a asset.Item, enabled bool) error {
}

// Load sets the pair manager from a seed without copying mutexes
func (p *PairsManager) Load(seed *PairsManager) error {
if seed == nil {
return fmt.Errorf("%w PairsManager", common.ErrNilPointer)
}
func (p *PairsManager) Load(seed *PairsManager) {
p.mutex.Lock()
defer p.mutex.Unlock()
seed.mutex.RLock()
defer seed.mutex.RUnlock()

var pN PairsManager
j, err := json.Marshal(seed)
if err != nil {
return err
}
err = json.Unmarshal(j, &pN)
if err != nil {
return err
}
p.BypassConfigFormatUpgrades = pN.BypassConfigFormatUpgrades
if pN.UseGlobalFormat {
p.UseGlobalFormat = pN.UseGlobalFormat
p.RequestFormat = pN.RequestFormat
p.ConfigFormat = pN.ConfigFormat
}
p.LastUpdated = pN.LastUpdated
p.Pairs = pN.Pairs
p.BypassConfigFormatUpgrades = seed.BypassConfigFormatUpgrades
p.UseGlobalFormat = seed.UseGlobalFormat
p.LastUpdated = seed.LastUpdated
p.Pairs = seed.Pairs.clone()
p.RequestFormat = seed.RequestFormat.clone()
p.ConfigFormat = seed.ConfigFormat.clone()
p.reindex()
}

return nil
// reindex re-indexes the matcher for Available pairs and all assets
// This method does not lock for concurrency
func (p *PairsManager) reindex() {
p.matcher = make(map[key]*Pair)
for a, fs := range p.Pairs {
for i, pair := range fs.Available {
k := key{Symbol: pair.Base.Lower().String() + pair.Quote.Lower().String(), Asset: a}
p.matcher[k] = &fs.Available[i]
}
}
}

func (p *PairsManager) getPairStoreRequiresLock(a asset.Item) (*PairStore, error) {
Expand Down Expand Up @@ -539,39 +538,30 @@ func (fs FullStore) MarshalJSON() ([]byte, error) {
return json.Marshal(temp)
}

// copy copies and segregates pair store from internal and external calls.
func (ps *PairStore) copy() (*PairStore, error) {
// clone returns a deep clone of the PairStore
func (ps *PairStore) clone() *PairStore {
if ps == nil {
return nil, errPairStoreIsNil
return nil
}

var assetEnabled *bool
if ps.AssetEnabled != nil {
assetEnabled = convert.BoolPtr(*ps.AssetEnabled)
}

enabled := make(Pairs, len(ps.Enabled))
copy(enabled, ps.Enabled)

avail := make(Pairs, len(ps.Available))
copy(avail, ps.Available)

var rFmt *PairFormat
if ps.RequestFormat != nil {
cpy := *ps.RequestFormat
rFmt = &cpy
return &PairStore{
AssetEnabled: assetEnabled,
Enabled: slices.Clone(ps.Enabled),
Available: slices.Clone(ps.Available),
RequestFormat: ps.RequestFormat.clone(),
ConfigFormat: ps.ConfigFormat.clone(),
}
}

var cFmt *PairFormat
if ps.ConfigFormat != nil {
cpy := *ps.ConfigFormat
cFmt = &cpy
func (fs FullStore) clone() FullStore {
c := FullStore{}
for a, pairStore := range fs {
c[a] = pairStore.clone()
}

return &PairStore{
AssetEnabled: assetEnabled,
Enabled: enabled,
Available: avail,
RequestFormat: rFmt,
ConfigFormat: cFmt,
}, nil
return c
}
Loading