Files
gocryptotrader/currency/pair.go
Ryan O'Hara-Reid f843b7d277 exchange: upgrade UpdatePair method (#991)
* exchange: upgrade update pair

* exchanges: Add enabled string matching and format handling if discrepency is found.

* linter: fixes

* bithumb: fix tests

* BTSE: api change fix ordering

* huobi: fix tests

* gloriousnits: stage 1

* gloriousnits: stage 2

* currency: more nits

* bitmex: add spot and process pairs before currency package call.

* bitmex: finished correct orderbook matching and other implementations

* linter: fix issue

* currency: Fix linter

* currency: segregate and protect pair store, update tests

* currency/manager: clean code, rm log output

* currency: Add store method and make sure formatting stays nil if not stored.

* gct: check errors

* engine/websocketroutineman: fix tests

* bybit: fix duplication bug

* huobi: fix test

* btse: fix tests?

* ob/buffer: fix tests

* Update currency/manager.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* glorious: nits

* glorious: nits strikes again.

* exchange: add bypassConfigFormatUpgrades to stop formatting

* GLORIOUS LINTER

* Update exchanges/bithumb/bithumb_wrapper.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

* glorious: nits

* exchange: fix pair upgrade issue when duplications are in both avail and enabled pairs

* linter: fix shadow dec

* config: fix test

* Update currency/pair_test.go

Co-authored-by: Scott <gloriousCode@users.noreply.github.com>

Co-authored-by: Ryan O'Hara-Reid <ryan.oharareid@thrasher.io>
Co-authored-by: Scott <gloriousCode@users.noreply.github.com>
2022-09-16 08:59:27 +10:00

140 lines
4.1 KiB
Go

package currency
import (
"errors"
"fmt"
"strings"
)
var errCannotCreatePair = errors.New("cannot create currency pair")
// NewPairDelimiter splits the desired currency string at delimeter, the returns
// a Pair struct
func NewPairDelimiter(currencyPair, delimiter string) (Pair, error) {
if !strings.Contains(currencyPair, delimiter) {
return EMPTYPAIR,
fmt.Errorf("delimiter: [%s] not found in currencypair string", delimiter)
}
result := strings.Split(currencyPair, delimiter)
if len(result) < 2 {
return EMPTYPAIR,
fmt.Errorf("supplied pair: [%s] cannot be split with %s",
currencyPair,
delimiter)
}
if len(result) > 2 {
result[1] = strings.Join(result[1:], delimiter)
}
return Pair{
Delimiter: delimiter,
Base: NewCode(result[0]),
Quote: NewCode(result[1]),
}, nil
}
// NewPairFromStrings returns a CurrencyPair without a delimiter
func NewPairFromStrings(base, quote string) (Pair, error) {
if strings.Contains(base, " ") {
return EMPTYPAIR,
fmt.Errorf("cannot create pair, invalid base currency string [%s]",
base)
}
if strings.Contains(quote, " ") {
return EMPTYPAIR,
fmt.Errorf("cannot create pair, invalid quote currency string [%s]",
quote)
}
return Pair{Base: NewCode(base), Quote: NewCode(quote)}, nil
}
// NewPair returns a currency pair from currency codes
func NewPair(baseCurrency, quoteCurrency Code) Pair {
return Pair{
Base: baseCurrency,
Quote: quoteCurrency,
}
}
// NewPairWithDelimiter returns a CurrencyPair with a delimiter
func NewPairWithDelimiter(base, quote, delimiter string) Pair {
return Pair{
Base: NewCode(base),
Quote: NewCode(quote),
Delimiter: delimiter,
}
}
// NewPairFromIndex returns a CurrencyPair via a currency string and specific
// index
func NewPairFromIndex(currencyPair, index string) (Pair, error) {
i := strings.Index(currencyPair, index)
if i == -1 {
return EMPTYPAIR,
fmt.Errorf("index %s not found in currency pair string", index)
}
if i == 0 {
return NewPairFromStrings(currencyPair[0:len(index)],
currencyPair[len(index):])
}
return NewPairFromStrings(currencyPair[0:i], currencyPair[i:])
}
// NewPairFromString converts currency string into a new CurrencyPair
// with or without delimeter
func NewPairFromString(currencyPair string) (Pair, error) {
for x := range delimiters {
if strings.Contains(currencyPair, delimiters[x]) {
return NewPairDelimiter(currencyPair, delimiters[x])
}
}
if len(currencyPair) < 3 {
return EMPTYPAIR,
fmt.Errorf("%w from %s string too short to be a current pair",
errCannotCreatePair,
currencyPair)
}
return NewPairFromStrings(currencyPair[0:3], currencyPair[3:])
}
// NewPairFromFormattedPairs matches a supplied currency pair to a list of pairs
// with a specific format. This is helpful for exchanges which
// provide currency pairs with no delimiter so we can match it with a list and
// apply the same format
func NewPairFromFormattedPairs(currencyPair string, pairs Pairs, pairFmt PairFormat) (Pair, error) {
for x := range pairs {
if strings.EqualFold(pairFmt.Format(pairs[x]), currencyPair) {
return pairs[x], nil
}
}
return NewPairFromString(currencyPair)
}
// Format formats the given pair as a string
func (f PairFormat) Format(pair Pair) string {
return pair.Format(f).String()
}
// MatchPairsWithNoDelimiter will move along a predictable index on the provided currencyPair
// it will then split on that index and verify whether that currencypair exists in the
// supplied pairs
// this allows for us to match strange currencies with no delimiter where it is difficult to
// infer where the delimiter is located eg BETHERETH is BETHER ETH
func MatchPairsWithNoDelimiter(currencyPair string, pairs Pairs, pairFmt PairFormat) (Pair, error) {
for i := range pairs {
fPair := pairs[i].Format(pairFmt)
maxLen := 6
if len(currencyPair) < maxLen {
maxLen = len(currencyPair)
}
for j := 1; j <= maxLen; j++ {
if fPair.Base.String() == currencyPair[0:j] &&
fPair.Quote.String() == currencyPair[j:] {
return fPair, nil
}
}
}
return EMPTYPAIR, fmt.Errorf("currency %v not found in supplied pairs", currencyPair)
}