mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-14 15:09:51 +00:00
* drop common uuid v4 func and imported package as needed * removed common functions regarding json marshal and unmarshal and used the json package directly. WRT unmarshal it was calling reflect and converted to string which is also checked in the JSON package so it was doing a double up, this will be a tiny gain as it was directly used in the requester package for all our outbound requests. * add in string * explicitly throw away return error value * atleast return the error that websocket initialise returns * return error when not connected * fix comment * Adds comments * move package declarations * drop append whenever we call supported * remove unused import * Change incorrect spelling * fix tests * fix go import issue
454 lines
10 KiB
Go
454 lines
10 KiB
Go
package currency
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/thrasher-corp/gocryptotrader/common"
|
|
)
|
|
|
|
func (r Role) String() string {
|
|
switch r {
|
|
case Unset:
|
|
return UnsetRoleString
|
|
case Fiat:
|
|
return FiatCurrencyString
|
|
case Cryptocurrency:
|
|
return CryptocurrencyString
|
|
case Token:
|
|
return TokenString
|
|
case Contract:
|
|
return ContractString
|
|
default:
|
|
return "UNKNOWN"
|
|
}
|
|
}
|
|
|
|
// MarshalJSON conforms Role to the marshaller interface
|
|
func (r Role) MarshalJSON() ([]byte, error) {
|
|
return json.Marshal(r.String())
|
|
}
|
|
|
|
// UnmarshalJSON conforms Role to the unmarshaller interface
|
|
func (r *Role) UnmarshalJSON(d []byte) error {
|
|
var incoming string
|
|
err := json.Unmarshal(d, &incoming)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
switch incoming {
|
|
case UnsetRoleString:
|
|
*r = Unset
|
|
case FiatCurrencyString:
|
|
*r = Fiat
|
|
case CryptocurrencyString:
|
|
*r = Cryptocurrency
|
|
case TokenString:
|
|
*r = Token
|
|
case ContractString:
|
|
*r = Contract
|
|
default:
|
|
return fmt.Errorf("unmarshal error role type %s unsupported for currency",
|
|
incoming)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// HasData returns true if the type contains data
|
|
func (b *BaseCodes) HasData() bool {
|
|
b.mtx.Lock()
|
|
defer b.mtx.Unlock()
|
|
return len(b.Items) != 0
|
|
}
|
|
|
|
// GetFullCurrencyData returns a type that is read to dump to file
|
|
func (b *BaseCodes) GetFullCurrencyData() (File, error) {
|
|
var file File
|
|
for _, i := range b.Items {
|
|
switch i.Role {
|
|
case Unset:
|
|
file.UnsetCurrency = append(file.UnsetCurrency, *i)
|
|
case Fiat:
|
|
file.FiatCurrency = append(file.FiatCurrency, *i)
|
|
case Cryptocurrency:
|
|
file.Cryptocurrency = append(file.Cryptocurrency, *i)
|
|
case Token:
|
|
file.Token = append(file.Token, *i)
|
|
case Contract:
|
|
file.Contracts = append(file.Contracts, *i)
|
|
default:
|
|
return file, errors.New("role undefined")
|
|
}
|
|
}
|
|
|
|
file.LastMainUpdate = b.LastMainUpdate
|
|
return file, nil
|
|
}
|
|
|
|
// GetCurrencies gets the full currency list from the base code type available
|
|
// from the currency system
|
|
func (b *BaseCodes) GetCurrencies() Currencies {
|
|
var currencies Currencies
|
|
b.mtx.Lock()
|
|
for i := range b.Items {
|
|
currencies = append(currencies, Code{
|
|
Item: b.Items[i],
|
|
})
|
|
}
|
|
b.mtx.Unlock()
|
|
return currencies
|
|
}
|
|
|
|
// UpdateCryptocurrency updates or registers a cryptocurrency
|
|
func (b *BaseCodes) UpdateCryptocurrency(fullName, symbol string, id int) error {
|
|
b.mtx.Lock()
|
|
defer b.mtx.Unlock()
|
|
for i := range b.Items {
|
|
if b.Items[i].Symbol != symbol {
|
|
continue
|
|
}
|
|
if b.Items[i].Role != Unset {
|
|
if b.Items[i].Role != Cryptocurrency {
|
|
if b.Items[i].FullName != "" {
|
|
if b.Items[i].FullName != fullName {
|
|
// multiple symbols found, break this and add the
|
|
// full context - this most likely won't occur for
|
|
// fiat but could occur for contracts.
|
|
break
|
|
}
|
|
}
|
|
return fmt.Errorf("role already defined in cryptocurrency %s as [%s]",
|
|
b.Items[i].Symbol,
|
|
b.Items[i].Role)
|
|
}
|
|
b.Items[i].FullName = fullName
|
|
b.Items[i].ID = id
|
|
return nil
|
|
}
|
|
|
|
b.Items[i].Role = Cryptocurrency
|
|
b.Items[i].FullName = fullName
|
|
b.Items[i].ID = id
|
|
return nil
|
|
}
|
|
|
|
b.Items = append(b.Items, &Item{
|
|
FullName: fullName,
|
|
Symbol: symbol,
|
|
ID: id,
|
|
Role: Cryptocurrency,
|
|
})
|
|
return nil
|
|
}
|
|
|
|
// UpdateFiatCurrency updates or registers a fiat currency
|
|
func (b *BaseCodes) UpdateFiatCurrency(fullName, symbol string, id int) error {
|
|
b.mtx.Lock()
|
|
defer b.mtx.Unlock()
|
|
for i := range b.Items {
|
|
if b.Items[i].Symbol != symbol {
|
|
continue
|
|
}
|
|
|
|
if b.Items[i].Role != Unset {
|
|
if b.Items[i].Role != Fiat {
|
|
return fmt.Errorf("role already defined in fiat currency %s as [%s]",
|
|
b.Items[i].Symbol,
|
|
b.Items[i].Role)
|
|
}
|
|
b.Items[i].FullName = fullName
|
|
b.Items[i].ID = id
|
|
return nil
|
|
}
|
|
|
|
b.Items[i].Role = Fiat
|
|
b.Items[i].FullName = fullName
|
|
b.Items[i].ID = id
|
|
return nil
|
|
}
|
|
|
|
b.Items = append(b.Items, &Item{
|
|
FullName: fullName,
|
|
Symbol: symbol,
|
|
ID: id,
|
|
Role: Fiat,
|
|
})
|
|
return nil
|
|
}
|
|
|
|
// UpdateToken updates or registers a token
|
|
func (b *BaseCodes) UpdateToken(fullName, symbol, assocBlockchain string, id int) error {
|
|
b.mtx.Lock()
|
|
defer b.mtx.Unlock()
|
|
for i := range b.Items {
|
|
if b.Items[i].Symbol != symbol {
|
|
continue
|
|
}
|
|
|
|
if b.Items[i].Role != Unset {
|
|
if b.Items[i].Role != Token {
|
|
if b.Items[i].FullName != "" {
|
|
if b.Items[i].FullName != fullName {
|
|
// multiple symbols found, break this and add the
|
|
// full context - this most likely won't occur for
|
|
// fiat but could occur for contracts.
|
|
break
|
|
}
|
|
}
|
|
return fmt.Errorf("role already defined in token %s as [%s]",
|
|
b.Items[i].Symbol,
|
|
b.Items[i].Role)
|
|
}
|
|
b.Items[i].FullName = fullName
|
|
b.Items[i].ID = id
|
|
b.Items[i].AssocChain = assocBlockchain
|
|
return nil
|
|
}
|
|
|
|
b.Items[i].Role = Token
|
|
b.Items[i].FullName = fullName
|
|
b.Items[i].ID = id
|
|
b.Items[i].AssocChain = assocBlockchain
|
|
return nil
|
|
}
|
|
|
|
b.Items = append(b.Items, &Item{
|
|
FullName: fullName,
|
|
Symbol: symbol,
|
|
ID: id,
|
|
Role: Token,
|
|
AssocChain: assocBlockchain,
|
|
})
|
|
return nil
|
|
}
|
|
|
|
// UpdateContract updates or registers a contract
|
|
func (b *BaseCodes) UpdateContract(fullName, symbol, assocExchange string) error {
|
|
b.mtx.Lock()
|
|
defer b.mtx.Unlock()
|
|
for i := range b.Items {
|
|
if b.Items[i].Symbol != symbol {
|
|
continue
|
|
}
|
|
|
|
if b.Items[i].Role != Unset {
|
|
if b.Items[i].Role != Contract {
|
|
return fmt.Errorf("role already defined in contract %s as [%s]",
|
|
b.Items[i].Symbol,
|
|
b.Items[i].Role)
|
|
}
|
|
b.Items[i].FullName = fullName
|
|
if !common.StringDataContains(b.Items[i].AssocExchange, assocExchange) {
|
|
b.Items[i].AssocExchange = append(b.Items[i].AssocExchange,
|
|
assocExchange)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
b.Items[i].Role = Contract
|
|
b.Items[i].FullName = fullName
|
|
if !common.StringDataContains(b.Items[i].AssocExchange, assocExchange) {
|
|
b.Items[i].AssocExchange = append(b.Items[i].AssocExchange,
|
|
assocExchange)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
b.Items = append(b.Items, &Item{
|
|
FullName: fullName,
|
|
Symbol: symbol,
|
|
Role: Contract,
|
|
AssocExchange: []string{assocExchange},
|
|
})
|
|
return nil
|
|
}
|
|
|
|
// Register registers a currency from a string and returns a currency code
|
|
func (b *BaseCodes) Register(c string) Code {
|
|
NewUpperCode := strings.ToUpper(c)
|
|
format := strings.Contains(c, NewUpperCode)
|
|
|
|
b.mtx.Lock()
|
|
defer b.mtx.Unlock()
|
|
for i := range b.Items {
|
|
if b.Items[i].Symbol == NewUpperCode {
|
|
return Code{
|
|
Item: b.Items[i],
|
|
UpperCase: format,
|
|
}
|
|
}
|
|
}
|
|
|
|
newItem := Item{Symbol: NewUpperCode}
|
|
newCode := Code{
|
|
Item: &newItem,
|
|
UpperCase: format,
|
|
}
|
|
|
|
b.Items = append(b.Items, newCode.Item)
|
|
return newCode
|
|
}
|
|
|
|
// RegisterFiat registers a fiat currency from a string and returns a currency
|
|
// code
|
|
func (b *BaseCodes) RegisterFiat(c string) (Code, error) {
|
|
c = strings.ToUpper(c)
|
|
|
|
b.mtx.Lock()
|
|
defer b.mtx.Unlock()
|
|
for i := range b.Items {
|
|
if b.Items[i].Symbol == c {
|
|
if b.Items[i].Role != Unset {
|
|
if b.Items[i].Role != Fiat {
|
|
return Code{}, fmt.Errorf("register fiat error role already defined in fiat %s as [%s]",
|
|
b.Items[i].Symbol,
|
|
b.Items[i].Role)
|
|
}
|
|
return Code{Item: b.Items[i], UpperCase: true}, nil
|
|
}
|
|
b.Items[i].Role = Fiat
|
|
return Code{Item: b.Items[i], UpperCase: true}, nil
|
|
}
|
|
}
|
|
|
|
item := &Item{Symbol: c, Role: Fiat}
|
|
b.Items = append(b.Items, item)
|
|
|
|
return Code{Item: item, UpperCase: true}, nil
|
|
}
|
|
|
|
// LoadItem sets item data
|
|
func (b *BaseCodes) LoadItem(item *Item) error {
|
|
b.mtx.Lock()
|
|
defer b.mtx.Unlock()
|
|
for i := range b.Items {
|
|
if b.Items[i].Symbol == item.Symbol {
|
|
if b.Items[i].Role == Unset {
|
|
b.Items[i].AssocChain = item.AssocChain
|
|
b.Items[i].AssocExchange = item.AssocExchange
|
|
b.Items[i].ID = item.ID
|
|
b.Items[i].Role = item.Role
|
|
b.Items[i].FullName = item.FullName
|
|
return nil
|
|
}
|
|
|
|
if b.Items[i].FullName != "" {
|
|
if b.Items[i].FullName == item.FullName {
|
|
b.Items[i].AssocChain = item.AssocChain
|
|
b.Items[i].AssocExchange = item.AssocExchange
|
|
b.Items[i].ID = item.ID
|
|
b.Items[i].Role = item.Role
|
|
return nil
|
|
}
|
|
break
|
|
}
|
|
|
|
if b.Items[i].ID == item.ID {
|
|
b.Items[i].AssocChain = item.AssocChain
|
|
b.Items[i].AssocExchange = item.AssocExchange
|
|
b.Items[i].FullName = item.FullName
|
|
b.Items[i].ID = item.ID
|
|
b.Items[i].Role = item.Role
|
|
return nil
|
|
}
|
|
|
|
return fmt.Errorf("currency %s not found in currencycode list",
|
|
item.Symbol)
|
|
}
|
|
}
|
|
|
|
b.Items = append(b.Items, item)
|
|
return nil
|
|
}
|
|
|
|
// NewCode returns a new currency registered code
|
|
func NewCode(c string) Code {
|
|
return storage.ValidateCode(c)
|
|
}
|
|
|
|
// String conforms to the stringer interface
|
|
func (i *Item) String() string {
|
|
return i.FullName
|
|
}
|
|
|
|
// String converts the code to string
|
|
func (c Code) String() string {
|
|
if c.Item == nil {
|
|
return ""
|
|
}
|
|
|
|
if c.UpperCase {
|
|
return c.Item.Symbol
|
|
}
|
|
return strings.ToLower(c.Item.Symbol)
|
|
}
|
|
|
|
// Lower converts the code to lowercase formatting
|
|
func (c Code) Lower() Code {
|
|
c.UpperCase = false
|
|
return c
|
|
}
|
|
|
|
// Upper converts the code to uppercase formatting
|
|
func (c Code) Upper() Code {
|
|
c.UpperCase = true
|
|
return c
|
|
}
|
|
|
|
// UnmarshalJSON comforms type to the umarshaler interface
|
|
func (c *Code) UnmarshalJSON(d []byte) error {
|
|
var newcode string
|
|
err := json.Unmarshal(d, &newcode)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
*c = NewCode(newcode)
|
|
return nil
|
|
}
|
|
|
|
// MarshalJSON conforms type to the marshaler interface
|
|
func (c Code) MarshalJSON() ([]byte, error) {
|
|
if c.Item == nil {
|
|
return json.Marshal("")
|
|
}
|
|
return json.Marshal(c.String())
|
|
}
|
|
|
|
// IsEmpty returns true if the code is empty
|
|
func (c Code) IsEmpty() bool {
|
|
if c.Item == nil {
|
|
return true
|
|
}
|
|
return c.Item.Symbol == ""
|
|
}
|
|
|
|
// Match returns if the code supplied is the same as the corresponding code
|
|
func (c Code) Match(check Code) bool {
|
|
return c.Item == check.Item
|
|
}
|
|
|
|
// IsDefaultFiatCurrency checks if the currency passed in matches the default
|
|
// fiat currency
|
|
func (c Code) IsDefaultFiatCurrency() bool {
|
|
return storage.IsDefaultCurrency(c)
|
|
}
|
|
|
|
// IsDefaultCryptocurrency checks if the currency passed in matches the default
|
|
// cryptocurrency
|
|
func (c Code) IsDefaultCryptocurrency() bool {
|
|
return storage.IsDefaultCryptocurrency(c)
|
|
}
|
|
|
|
// IsFiatCurrency checks if the currency passed is an enabled fiat currency
|
|
func (c Code) IsFiatCurrency() bool {
|
|
return storage.IsFiatCurrency(c)
|
|
}
|
|
|
|
// IsCryptocurrency checks if the currency passed is an enabled CRYPTO currency.
|
|
func (c Code) IsCryptocurrency() bool {
|
|
return storage.IsCryptocurrency(c)
|
|
}
|