Files
gocryptotrader/portfolio/portfolio_test.go
Samuael A 2ac165a477 exchanges: Add OKX support (#1005)
* public endpoints methods added

* Completing mapping REST endpoints

* Binanceus Wrapper methods -Partially

* Binanceus Wrapper methods -Partially

* BinaWra functions with test funs; Not Completed

* Finalizing wrapper methods & test

* Fix & Complete wrapper functions

* Finalizing wrapper methods & test

* Adding Stream Datas

* WS Test functions

* CI: Fix golangci-lint linter issues

* CI: Fix reverting unnessesary changes and type conversion issues

* CI: Fix reverting unnessesary changes and type conversion issues

* Adding Public endpoints and tests

* Adding Market and Public Endpoints

* Adding Public endoints

* Public Trading Endpoints & Authenticated Trade order methods

* Adding Authenticated Methods and Tests

* Adding algo and Funding Authenticated endpoints

* Adding funding trading endpoints and correspondint tests

* adding authenticated endpoints

* Completing Block Trading endpoints and added subaccount endpoints

* Completing sub account and grid Trading endpoints

* Adding Rate Limit and missing endpoints

* Wrapper and Websocket handlers

* Fixing Websocket Test and Push Data Handler Issues

* Fixing Websocket Test and Push Data Handler Issues

* Fixing linter issues, package dependency, and other slight tempos

* Fixing linter and slight tempos

* Update on test functions, and Rest and Websocket Endpoint handlers

* Remove okex, adding comments, and slight fixes on endpoints.

* Fixing linter issues and adding comments

* Slight code changes, updating documentation, and n and linter issues

* Fix context and configuration endpoint issues

* slight fixes on config and test files

* adding some missing test and fix linter issues

* fix linter issue

* Slight fixes on code structure, shorthand exp,and ot and other

* Fix slight linter issue

* Slight code fixes and fixing linter issues

* fixing linter iissues

* fixing linter iissues

* slight linter issue fix

* slight linter issue fix

* Fix on models, type convert funcs and endpoints

* Adding Error messages map and update of models

* Fix on error message string and linter issues

* Fix slight linter issue

* Fix slight linter issue

* Fixing type converts, models, and linter issues

* Adding Ws fixes

* Slight fix on websocket and other issues

* Adding slight websocket fixes

* Remove 'books5' channel default subscription

* Small changes on default subscription and checksum

* Fix slight websocket tempos

* Fix Wrapper function tempost and linter issues

* Resolving slight naming and other issues

* Resolve slight pointer issues

* resolve slight linter issues

* Resolve config files issue

* Update websocket and wrapper funcs with test and docs

* fixs on websocket multiplexer, types, and other slight issues

* fix slight linter issues

* slight update on web-socket orderbook and tickers

* fix slight issues and websocket runtime errors

* Slight unit test fix and assing simple semaphore

* FIx race issue

* Update on authenticated endpoints

* Fix wsSetupRun check in websocket 'setupWsAuth' func

* Update wsSetupRun check in websocket 'setupWsAuth' func

* Slight update on websocket handling

* Fix some race conditions

* fix slight tempos

* fix authenticated test issues

* Update on conditional statements

* slight update on unit test

* fix unit test tempos

* Fix slight tempos

* Change check map from struct valued to bool valued

* slight fix trial

* Slight unit test update

* Fix websocket timeout error

* Updating websocket subscription endpoints, and unit tests

* update unit tests

* Slight issue on wrapper method 'GetActiveOrders'

* Overall code update

* Addressing missing review comments

* Fix unit test tempo and linter issue

* Monor fix

* Slight update

* Slight unit test fix

* Slight fixes

* Slight fixes

* Fixing on missing review comments

* Adding WS Fixes

* slight fix

* Monor fix on unit test

* Minor convert issue

* Minor change on WS

* Monor logic fix

* Fix code structure and logic issues

* Fixing small typos

* fix slight data format issue

* Update on trade and order wrapper methods

* Adding slight update

* fix on order detail

* Slight update on FetchTradablePairs wrapper method

* Slight update on wrapper

* Update on deserialization and other slight issues

* Final update

* Resolve missing review comments

* Slight update on config and unit test

* minor fix on GetDepositAddress param

* Minor fix
2022-12-09 11:44:29 +11:00

641 lines
15 KiB
Go

package portfolio
import (
"errors"
"testing"
"github.com/thrasher-corp/gocryptotrader/core"
"github.com/thrasher-corp/gocryptotrader/currency"
)
const (
testBTCAddress = "0x1D01TH0R53"
)
func TestGetEthereumBalance(t *testing.T) {
t.Parallel()
b := Base{}
address := "0xb794f5ea0ba39494ce839613fffba74279579268"
nonsenseAddress := "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
response, err := b.GetEthereumBalance(address)
if err != nil {
t.Errorf("Portfolio GetEthereumBalance() Error: %s", err)
}
if response.Address != "0xb794f5ea0ba39494ce839613fffba74279579268" {
t.Error("Portfolio GetEthereumBalance() address invalid")
}
_, err = b.GetEthereumBalance(nonsenseAddress)
if !errors.Is(err, errNotEthAddress) {
t.Errorf("received '%v', expected '%v'", err, errNotEthAddress)
}
}
func TestGetCryptoIDBalance(t *testing.T) {
t.Parallel()
b := Base{}
ltcAddress := "LX2LMYXtuv5tiYEMztSSoEZcafFPYJFRK1"
_, err := b.GetCryptoIDAddress(ltcAddress, currency.LTC)
if err != nil {
t.Fatalf("TestGetCryptoIDBalance error: %s", err)
}
}
func TestGetAddressBalance(t *testing.T) {
t.Parallel()
ltcAddress := "LdP8Qox1VAhCzLJNqrr74YovaWYyNBUWvL"
ltc := currency.LTC
description := "Description of Wallet"
balance := float64(1000)
b := Base{}
err := b.AddAddress(ltcAddress, description, ltc, balance)
if err != nil {
t.Error(err)
}
addBalance, _ := b.GetAddressBalance("LdP8Qox1VAhCzLJNqrr74YovaWYyNBUWvL",
description,
ltc)
if addBalance != balance {
t.Error("Incorrect value")
}
addBalance, found := b.GetAddressBalance("WigWham",
description,
ltc)
if addBalance != 0 {
t.Error("Incorrect value")
}
if found {
t.Error("Incorrect value")
}
}
func TestGetRippleBalance(t *testing.T) {
t.Parallel()
b := Base{}
nonsenseAddress := "Wigwham"
_, err := b.GetRippleBalance(nonsenseAddress)
if err == nil {
t.Error("error cannot be nil on a bad address")
}
rippleAddress := "r962iS5subzbVeXZN8MTzyEuuaQKo5qksh"
_, err = b.GetRippleBalance(rippleAddress)
if err != nil {
t.Error(err)
}
}
func TestExchangeExists(t *testing.T) {
t.Parallel()
newBase := Base{}
err := newBase.AddAddress("someaddress",
currency.LTC.String(),
currency.NewCode("LTCWALLETTEST"),
0.02)
if err != nil {
t.Error(err)
}
if !newBase.ExchangeExists("someaddress") {
t.Error("expected exchange to exist")
}
if newBase.ExchangeExists("bla") {
t.Error("expected exchange to not exist")
}
}
func TestAddressExists(t *testing.T) {
t.Parallel()
newBase := Base{}
err := newBase.AddAddress("someaddress",
currency.LTC.String(),
currency.NewCode("LTCWALLETTEST"),
0.02)
if err != nil {
t.Error(err)
}
if !newBase.AddressExists("someaddress") {
t.Error("expected address to exist")
}
if newBase.AddressExists("bla") {
t.Error("expected address to not exist")
}
}
func TestExchangeAddressExists(t *testing.T) {
t.Parallel()
newBase := Base{}
err := newBase.AddAddress("someaddress",
currency.LTC.String(),
currency.LTC,
0.02)
if err != nil {
t.Error(err)
}
if !newBase.ExchangeAddressExists("someaddress", currency.LTC) {
t.Error("expected exchange address to exist")
}
if newBase.ExchangeAddressExists("TEST", currency.LTC) {
t.Error("expected exchange address to not exist")
}
}
func TestAddExchangeAddress(t *testing.T) {
t.Parallel()
newBase := Base{}
newBase.AddExchangeAddress("Okx", currency.BTC, 100)
newBase.AddExchangeAddress("Okx", currency.BTC, 200)
if !newBase.ExchangeAddressExists("Okx", currency.BTC) {
t.Error("address doesn't exist")
}
}
func TestUpdateAddressBalance(t *testing.T) {
t.Parallel()
newBase := Base{}
err := newBase.AddAddress("someaddress",
currency.LTC.String(),
currency.NewCode("LTCWALLETTEST"),
0.02)
if err != nil {
t.Error(err)
}
newBase.UpdateAddressBalance("someaddress", 0.03)
value := newBase.GetPortfolioSummary()
if !value.Totals[0].Coin.Equal(currency.LTC) &&
value.Totals[0].Balance != 0.03 {
t.Error("UpdateUpdateAddressBalance error")
}
}
func TestRemoveAddress(t *testing.T) {
t.Parallel()
var newBase Base
if err := newBase.RemoveAddress("", "MEOW", currency.LTC); err == nil {
t.Error("invalid address should throw an error")
}
if err := newBase.RemoveAddress("Gibson", "", currency.NewCode("")); err == nil {
t.Error("invalid coin type should throw an error")
}
if err := newBase.RemoveAddress("HIDDENERINO", "MEOW", currency.LTC); err == nil {
t.Error("non-existent address should throw an error")
}
err := newBase.AddAddress("someaddr",
currency.LTC.String(),
currency.NewCode("LTCWALLETTEST"),
420)
if err != nil {
t.Error(err)
}
if !newBase.AddressExists("someaddr") {
t.Error("address does not exist")
}
err = newBase.RemoveAddress("someaddr",
currency.LTC.String(),
currency.NewCode("LTCWALLETTEST"))
if err != nil {
t.Error(err)
}
if newBase.AddressExists("someaddr") {
t.Error("address should not exist")
}
}
func TestRemoveExchangeAddress(t *testing.T) {
t.Parallel()
newBase := Base{}
exchangeName := "BallerExchange"
coinType := currency.LTC
newBase.AddExchangeAddress(exchangeName, coinType, 420)
if !newBase.ExchangeAddressExists(exchangeName, coinType) {
t.Error("address does not exist")
}
newBase.RemoveExchangeAddress(exchangeName, coinType)
if newBase.ExchangeAddressExists(exchangeName, coinType) {
t.Error("address should not exist")
}
}
func TestUpdateExchangeAddressBalance(t *testing.T) {
t.Parallel()
newBase := Base{}
newBase.AddExchangeAddress("someaddress", currency.LTC, 0.02)
b := Base{}
b.Seed(newBase)
b.UpdateExchangeAddressBalance("someaddress", currency.LTC, 0.04)
value := b.GetPortfolioSummary()
if !value.Totals[0].Coin.Equal(currency.LTC) && value.Totals[0].Balance != 0.04 {
t.Error("incorrect portfolio balance")
}
}
func TestAddAddress(t *testing.T) {
t.Parallel()
var newBase Base
if err := newBase.AddAddress("", "MEOW", currency.LTC, 1); err == nil {
t.Error("invalid address should throw an error")
}
if err := newBase.AddAddress("Gibson", "", currency.NewCode(""), 1); err == nil {
t.Error("invalid coin type should throw an error")
}
// test adding an exchange address
err := newBase.AddAddress("COINUT", ExchangeAddress, currency.LTC, 0)
if err != nil {
t.Errorf("failed to add address: %v", err)
}
// add a test portfolio address and amount
err = newBase.AddAddress("Gibson",
currency.LTC.String(),
currency.NewCode("LTCWALLETTEST"),
0.02)
if err != nil {
t.Error(err)
}
// test updating the balance and make sure it's reflected
err = newBase.AddAddress("Gibson", currency.LTC.String(),
currency.NewCode("LTCWALLETTEST"), 0.05)
if err != nil {
t.Error(err)
}
b, _ := newBase.GetAddressBalance("Gibson", "LTC",
currency.NewCode("LTCWALLETTEST"))
if b != 0.05 {
t.Error("invalid portfolio amount")
}
nb := Base{}
nb.Seed(newBase)
if !nb.AddressExists("Gibson") {
t.Error("AddAddress error")
}
// Test updating balance to <= 0, expected result is to remove the address.
// Fail if address still exists.
err = newBase.AddAddress("Gibson",
currency.LTC.String(),
currency.NewCode("LTCWALLETTEST"),
-1)
if err != nil {
t.Error(err)
}
if newBase.AddressExists("Gibson") {
t.Error("AddAddress error")
}
}
func TestUpdatePortfolio(t *testing.T) {
t.Parallel()
newBase := Base{}
err := newBase.UpdatePortfolio([]string{"Testy"}, currency.LTC)
if err == nil {
t.Error("UpdatePortfolio error cannot be nil")
}
err = newBase.UpdatePortfolio([]string{
"LdP8Qox1VAhCzLJNqrr74YovaWYyNBUWvL",
"LVa8wZ983PvWtdwXZ8viK6SocMENLCXkEy"},
currency.LTC,
)
if err != nil {
t.Error("UpdatePortfolio error", err)
}
err = newBase.UpdatePortfolio(
[]string{"Testy"}, currency.LTC,
)
if err == nil {
t.Error("UpdatePortfolio error cannot be nil")
}
err = newBase.UpdatePortfolio([]string{
"0xb794f5ea0ba39494ce839613fffba74279579268"},
currency.ETH)
if err != nil {
t.Error(err)
}
err = newBase.UpdatePortfolio([]string{
"TESTY"},
currency.ETH)
if err == nil {
t.Error("UpdatePortfolio error cannot be nil")
}
err = newBase.UpdatePortfolio([]string{ExchangeAddress,
PersonalAddress},
currency.LTC)
if err != nil {
t.Error(err)
}
err = newBase.UpdatePortfolio([]string{
"r962iS5subzbVeXZN8MTzyEuuaQKo5qksh"},
currency.XRP)
if err != nil {
t.Error(err)
}
err = newBase.UpdatePortfolio([]string{
"TESTY"},
currency.XRP)
if err == nil {
t.Error("error cannot be nil")
}
}
func TestGetPortfolioByExchange(t *testing.T) {
t.Parallel()
newBase := Base{}
newBase.AddExchangeAddress("Okx", currency.LTC, 0.07)
newBase.AddExchangeAddress("Bitfinex", currency.LTC, 0.05)
err := newBase.AddAddress("someaddress", "LTC", currency.NewCode(PersonalAddress), 0.03)
if err != nil {
t.Fatal(err)
}
value := newBase.GetPortfolioByExchange("Okx")
result, ok := value[currency.LTC]
if !ok {
t.Error("missing portfolio entry")
}
if result != 0.07 {
t.Error("incorrect result")
}
value = newBase.GetPortfolioByExchange("Bitfinex")
result, ok = value[currency.LTC]
if !ok {
t.Error("missing portfolio entry")
}
if result != 0.05 {
t.Error("incorrect result")
}
}
func TestGetExchangePortfolio(t *testing.T) {
t.Parallel()
newBase := Base{}
err := newBase.AddAddress("Okx", ExchangeAddress, currency.LTC, 0.03)
if err != nil {
t.Fatal(err)
}
err = newBase.AddAddress("Bitfinex", ExchangeAddress, currency.LTC, 0.05)
if err != nil {
t.Fatal(err)
}
err = newBase.AddAddress("someaddress", PersonalAddress, currency.LTC, 0.03)
if err != nil {
t.Fatal(err)
}
value := newBase.GetExchangePortfolio()
result, ok := value[currency.LTC]
if !ok {
t.Error("missing portfolio entry")
}
if result != 0.08 {
t.Error("result != 0.08")
}
}
func TestGetPersonalPortfolio(t *testing.T) {
t.Parallel()
newBase := Base{}
err := newBase.AddAddress("someaddress", PersonalAddress, currency.N2O, 0.02)
if err != nil {
t.Fatal(err)
}
err = newBase.AddAddress("anotheraddress", PersonalAddress, currency.N2O, 0.03)
if err != nil {
t.Fatal(err)
}
err = newBase.AddAddress("Exchange", ExchangeAddress, currency.N2O, 0.01)
if err != nil {
t.Fatal(err)
}
value := newBase.GetPersonalPortfolio()
result, ok := value[currency.N2O]
if !ok {
t.Error("GetPersonalPortfolio error")
}
if result != 0.05 {
t.Error("GetPersonalPortfolio result != 0.05")
}
}
func TestGetPortfolioSummary(t *testing.T) {
t.Parallel()
newBase := Base{}
// Personal holdings
err := newBase.AddAddress("someaddress", PersonalAddress, currency.LTC, 1)
if err != nil {
t.Fatal(err)
}
err = newBase.AddAddress("someaddress2", PersonalAddress, currency.LTC, 2)
if err != nil {
t.Fatal(err)
}
err = newBase.AddAddress("someaddress3", PersonalAddress, currency.BTC, 100)
if err != nil {
t.Fatal(err)
}
err = newBase.AddAddress("0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae",
PersonalAddress, currency.ETH, 865346880000000000)
if err != nil {
t.Fatal(err)
}
err = newBase.AddAddress("0x9edc81c813b26165f607a8d1b8db87a02f34307f",
PersonalAddress, currency.ETH, 165346880000000000)
if err != nil {
t.Fatal(err)
}
// Exchange holdings
newBase.AddExchangeAddress("Bitfinex", currency.LTC, 20)
newBase.AddExchangeAddress("Bitfinex", currency.BTC, 100)
newBase.AddExchangeAddress("Okx", currency.ETH, 42)
value := newBase.GetPortfolioSummary()
getTotalsVal := func(c currency.Code) Coin {
for x := range value.Totals {
if value.Totals[x].Coin.Equal(c) {
return value.Totals[x]
}
}
return Coin{}
}
if !getTotalsVal(currency.LTC).Coin.Equal(currency.LTC) {
t.Error("mismatched currency")
}
if getTotalsVal(currency.ETH).Coin.Equal(currency.LTC) {
t.Error("mismatched currency")
}
if getTotalsVal(currency.LTC).Balance != 23 {
t.Error("incorrect balance")
}
if getTotalsVal(currency.BTC).Balance != 200 {
t.Error("incorrect balance")
}
}
func TestGetPortfolioGroupedCoin(t *testing.T) {
t.Parallel()
newBase := Base{}
err := newBase.AddAddress("someaddress", currency.LTC.String(), currency.LTC, 0.02)
if err != nil {
t.Fatal(err)
}
err = newBase.AddAddress("Exchange", ExchangeAddress, currency.LTC, 0.05)
if err != nil {
t.Fatal(err)
}
value := newBase.GetPortfolioGroupedCoin()
if value[currency.LTC][0] != "someaddress" && len(value[currency.LTC][0]) != 1 {
t.Error("incorrect balance")
}
}
func TestSeed(t *testing.T) {
t.Parallel()
newBase := Base{}
err := newBase.AddAddress("someaddress", currency.LTC.String(), currency.LTC, 0.02)
if err != nil {
t.Fatal(err)
}
if !newBase.AddressExists("someaddress") {
t.Error("Seed error")
}
}
func TestIsExchangeSupported(t *testing.T) {
t.Parallel()
newBase := seedPortFolioForTest(t)
ret := newBase.IsExchangeSupported("BTC Markets", core.BitcoinDonationAddress)
if !ret {
t.Fatal("expected IsExchangeSupported() to return true")
}
ret = newBase.IsExchangeSupported("Kraken", core.BitcoinDonationAddress)
if ret {
t.Fatal("expected IsExchangeSupported() to return false")
}
}
func TestIsColdStorage(t *testing.T) {
t.Parallel()
newBase := seedPortFolioForTest(t)
ret := newBase.IsColdStorage(core.BitcoinDonationAddress)
if !ret {
t.Fatal("expected IsColdStorage() to return true")
}
ret = newBase.IsColdStorage(testBTCAddress)
if ret {
t.Fatal("expected IsColdStorage() to return false")
}
ret = newBase.IsColdStorage("hello")
if ret {
t.Fatal("expected IsColdStorage() to return false")
}
}
func TestIsWhiteListed(t *testing.T) {
t.Parallel()
b := seedPortFolioForTest(t)
ret := b.IsWhiteListed(core.BitcoinDonationAddress)
if !ret {
t.Fatal("expected IsWhiteListed() to return true")
}
ret = b.IsWhiteListed(testBTCAddress)
if ret {
t.Fatal("expected IsWhiteListed() to return false")
}
ret = b.IsWhiteListed("hello")
if ret {
t.Fatal("expected IsWhiteListed() to return false")
}
}
func TestStartPortfolioWatcher(t *testing.T) {
t.Parallel()
newBase := Base{}
err := newBase.AddAddress("LX2LMYXtuv5tiYEMztSSoEZcafFPYJFRK1",
currency.LTC.String(),
currency.NewCode(PersonalAddress),
0.02)
if err != nil {
t.Error(err)
}
err = newBase.AddAddress("Testy",
currency.LTC.String(),
currency.NewCode(PersonalAddress),
0.02)
if err != nil {
t.Error(err)
}
if !newBase.AddressExists("LX2LMYXtuv5tiYEMztSSoEZcafFPYJFRK1") {
t.Error("address does not exist")
}
go newBase.StartPortfolioWatcher()
}
func seedPortFolioForTest(t *testing.T) *Base {
t.Helper()
newBase := Base{}
err := newBase.AddAddress(core.BitcoinDonationAddress, "test", currency.BTC, 1500)
if err != nil {
t.Fatalf("failed to add portfolio address with reason: %v, unable to continue tests", err)
}
newBase.Addresses[0].WhiteListed = true
newBase.Addresses[0].ColdStorage = true
newBase.Addresses[0].SupportedExchanges = "BTC Markets,Binance"
err = newBase.AddAddress(testBTCAddress, "test", currency.BTC, 1500)
if err != nil {
t.Fatalf("failed to add portfolio address with reason: %v, unable to continue tests", err)
}
newBase.Addresses[1].SupportedExchanges = "BTC Markets,Binance"
b := Base{}
b.Seed(newBase)
if len(b.Addresses) == 0 {
t.Error("failed to seed")
}
return &b
}