From db21dafd549260c9dace08ec0b0ec66f6b4ea056 Mon Sep 17 00:00:00 2001 From: Debnil Sur Date: Wed, 21 Oct 2020 17:39:57 -0700 Subject: [PATCH 01/14] Initial commit - test constructor. --- plugins/volumeFilter.go | 26 +++- plugins/volumeFilter_test.go | 227 +++++++++++++++++++++++++++++++++++ 2 files changed, 249 insertions(+), 4 deletions(-) create mode 100644 plugins/volumeFilter_test.go diff --git a/plugins/volumeFilter.go b/plugins/volumeFilter.go index df90eee5f..1bb2025a7 100644 --- a/plugins/volumeFilter.go +++ b/plugins/volumeFilter.go @@ -69,15 +69,15 @@ func makeFilterVolume( if e != nil { return nil, fmt.Errorf("could not convert base asset (%s) from trading pair via the passed in assetDisplayFn: %s", string(tradingPair.Base), e) } + quoteAssetString, e := assetDisplayFn(tradingPair.Quote) if e != nil { return nil, fmt.Errorf("could not convert quote asset (%s) from trading pair via the passed in assetDisplayFn: %s", string(tradingPair.Quote), e) } - marketID := MakeMarketID(exchangeName, baseAssetString, quoteAssetString) - marketIDs := utils.Dedupe(append([]string{marketID}, config.additionalMarketIDs...)) - dailyVolumeByDateQuery, e := queries.MakeDailyVolumeByDateForMarketIdsAction(db, marketIDs, "sell", config.optionalAccountIDs) + + dailyVolumeByDateQuery, e := makeDailyVolumeByDateQuery(db, exchangeName, baseAssetString, quoteAssetString, config.optionalAccountIDs, config.additionalMarketIDs) if e != nil { - return nil, fmt.Errorf("could not make daily volume by date Query: %s", e) + return nil, fmt.Errorf("could not make daily volume by date query: %s", e) } return &volumeFilter{ @@ -90,6 +90,24 @@ func makeFilterVolume( }, nil } +func makeDailyVolumeByDateQuery( + db *sql.DB, + exchangeName string, + baseAsset string, + quoteAsset string, + optionalAccountIDs []string, + additionalMarketIDs []string, +) (*queries.DailyVolumeByDate, error) { + marketID := MakeMarketID(exchangeName, baseAsset, quoteAsset) + marketIDs := utils.Dedupe(append([]string{marketID}, additionalMarketIDs...)) + dailyVolumeByDateQuery, e := queries.MakeDailyVolumeByDateForMarketIdsAction(db, marketIDs, "sell", optionalAccountIDs) + if e != nil { + return nil, fmt.Errorf("could not make daily volume by date action: %s", e) + } + + return dailyVolumeByDateQuery, nil +} + var _ SubmitFilter = &volumeFilter{} // Validate ensures validity diff --git a/plugins/volumeFilter_test.go b/plugins/volumeFilter_test.go new file mode 100644 index 000000000..5ad9d5523 --- /dev/null +++ b/plugins/volumeFilter_test.go @@ -0,0 +1,227 @@ +package plugins + +import ( + "database/sql" + "fmt" + "os" + "testing" + + hProtocol "github.com/stellar/go/protocols/horizon" + "github.com/stellar/kelp/model" + "github.com/stellar/kelp/support/postgresdb" + "github.com/stellar/kelp/support/utils" + "github.com/stretchr/testify/assert" +) + +func connectTestDb() *sql.DB { + postgresDbConfig := &postgresdb.Config{ + Host: "localhost", + Port: 5432, + DbName: "test_database", + User: os.Getenv("POSTGRES_USER"), + SSLEnable: false, + } + + _, e := postgresdb.CreateDatabaseIfNotExists(postgresDbConfig) + if e != nil { + panic(e) + } + + db, e := sql.Open("postgres", postgresDbConfig.MakeConnectString()) + if e != nil { + panic(e) + } + return db +} + +func TestMakeFilterVolume(t *testing.T) { + testAssetDisplayFn := model.AssetDisplayFn(func(asset model.Asset) (string, error) { + sdexAssetMap := map[model.Asset]hProtocol.Asset{ + model.Asset("XLM"): hProtocol.Asset{Type: "native"}, + } + assetString, ok := sdexAssetMap[asset] + if !ok { + return "", fmt.Errorf("cannot recognize the asset %s", string(asset)) + } + return utils.Asset2String(assetString), nil + }) + + testNativeAsset := hProtocol.Asset{Type: "native"} + testEmptyVolumeConfig := &VolumeFilterConfig{} + db := connectTestDb() + + emptyConfigVolumeQuery, e := makeDailyVolumeByDateQuery(db, "", "native", "native", []string{}, []string{}) + if e != nil { + t.Log("could not make empty config volume query") + return + } + + marketIDs := []string{"marketID"} + marketConfigVolumeQuery, e := makeDailyVolumeByDateQuery(db, "", "native", "native", []string{}, marketIDs) + if e != nil { + t.Log("could not make market config volume query") + return + } + + accountIDs := []string{"accountID"} + accountConfigVolumeQuery, e := makeDailyVolumeByDateQuery(db, "", "native", "native", accountIDs, []string{}) + if e != nil { + t.Log("could not make account config volume query") + return + } + + accountMarketConfigVolumeQuery, e := makeDailyVolumeByDateQuery(db, "", "native", "native", accountIDs, marketIDs) + if e != nil { + t.Log("could not make account and market config volume query") + return + } + + testCases := []struct { + name string + configValue string + exchangeName string + tradingPair *model.TradingPair + assetDisplayFn model.AssetDisplayFn + baseAsset hProtocol.Asset + quoteAsset hProtocol.Asset + db *sql.DB + config *VolumeFilterConfig + + wantError error + wantSubmitFilter SubmitFilter + }{ + // Note: config can be additional market IDs, make sure to test additionalMarketIds and optionalAccountIDs + { + name: "failure - display base", + configValue: "", + exchangeName: "", + tradingPair: &model.TradingPair{Base: "FAIL", Quote: ""}, + assetDisplayFn: testAssetDisplayFn, + baseAsset: hProtocol.Asset{}, + quoteAsset: hProtocol.Asset{}, + db: db, + config: &VolumeFilterConfig{}, + wantError: fmt.Errorf("could not convert base asset (FAIL) from trading pair via the passed in assetDisplayFn: cannot recognize the asset FAIL"), + wantSubmitFilter: nil, + }, + { + name: "failure - display quote", + configValue: "", + exchangeName: "", + tradingPair: &model.TradingPair{Base: "XLM", Quote: "FAIL"}, + assetDisplayFn: testAssetDisplayFn, + baseAsset: testNativeAsset, + quoteAsset: hProtocol.Asset{}, + config: &VolumeFilterConfig{}, + wantError: fmt.Errorf("could not convert quote asset (FAIL) from trading pair via the passed in assetDisplayFn: cannot recognize the asset FAIL"), + wantSubmitFilter: nil, + }, + { + name: "failure - query", + configValue: "", + exchangeName: "", + tradingPair: &model.TradingPair{Base: "XLM", Quote: "XLM"}, + assetDisplayFn: testAssetDisplayFn, + baseAsset: testNativeAsset, + quoteAsset: testNativeAsset, + config: &VolumeFilterConfig{}, + db: nil, + wantError: fmt.Errorf("could not make daily volume by date query: could not make daily volume by date action: the provided db should be non-nil"), + wantSubmitFilter: nil, + }, + { + name: "success - empty config", + configValue: "", + exchangeName: "", + tradingPair: &model.TradingPair{Base: "XLM", Quote: "XLM"}, + assetDisplayFn: testAssetDisplayFn, + baseAsset: testNativeAsset, + quoteAsset: testNativeAsset, + config: testEmptyVolumeConfig, + db: db, + wantError: nil, + wantSubmitFilter: &volumeFilter{ + name: "volumeFilter", + baseAsset: testNativeAsset, + quoteAsset: testNativeAsset, + config: testEmptyVolumeConfig, + dailyVolumeByDateQuery: emptyConfigVolumeQuery, + }, + }, + { + name: "success - market ids", + configValue: "", + exchangeName: "", + tradingPair: &model.TradingPair{Base: "XLM", Quote: "XLM"}, + assetDisplayFn: testAssetDisplayFn, + baseAsset: testNativeAsset, + quoteAsset: testNativeAsset, + config: &VolumeFilterConfig{additionalMarketIDs: marketIDs}, + db: db, + wantError: nil, + wantSubmitFilter: &volumeFilter{ + name: "volumeFilter", + baseAsset: testNativeAsset, + quoteAsset: testNativeAsset, + config: &VolumeFilterConfig{additionalMarketIDs: marketIDs}, + dailyVolumeByDateQuery: marketConfigVolumeQuery, + }, + }, + { + name: "success - account ids", + configValue: "", + exchangeName: "", + tradingPair: &model.TradingPair{Base: "XLM", Quote: "XLM"}, + assetDisplayFn: testAssetDisplayFn, + baseAsset: testNativeAsset, + quoteAsset: testNativeAsset, + config: &VolumeFilterConfig{optionalAccountIDs: accountIDs}, + db: db, + wantError: nil, + wantSubmitFilter: &volumeFilter{ + name: "volumeFilter", + baseAsset: testNativeAsset, + quoteAsset: testNativeAsset, + config: &VolumeFilterConfig{optionalAccountIDs: accountIDs}, + dailyVolumeByDateQuery: accountConfigVolumeQuery, + }, + }, + { + name: "success - account and market ids", + configValue: "", + exchangeName: "", + tradingPair: &model.TradingPair{Base: "XLM", Quote: "XLM"}, + assetDisplayFn: testAssetDisplayFn, + baseAsset: testNativeAsset, + quoteAsset: testNativeAsset, + config: &VolumeFilterConfig{optionalAccountIDs: accountIDs, additionalMarketIDs: marketIDs}, + db: db, + wantError: nil, + wantSubmitFilter: &volumeFilter{ + name: "volumeFilter", + baseAsset: testNativeAsset, + quoteAsset: testNativeAsset, + config: &VolumeFilterConfig{optionalAccountIDs: accountIDs, additionalMarketIDs: marketIDs}, + dailyVolumeByDateQuery: accountMarketConfigVolumeQuery, + }, + }, + } + + for _, k := range testCases { + t.Run(k.name, func(t *testing.T) { + actual, e := makeFilterVolume( + k.configValue, + k.exchangeName, + k.tradingPair, + k.assetDisplayFn, + k.baseAsset, + k.quoteAsset, + k.db, + k.config, + ) + + assert.Equal(t, k.wantError, e) + assert.Equal(t, k.wantSubmitFilter, actual) + }) + } +} From 658f921bc2abf44637f8558724f039bfcbc6ade6 Mon Sep 17 00:00:00 2001 From: Debnil Sur Date: Thu, 22 Oct 2020 16:08:19 -0700 Subject: [PATCH 02/14] Add tests to filter fn. --- plugins/volumeFilter_test.go | 216 ++++++++++++++++++++++++++++++++++- 1 file changed, 214 insertions(+), 2 deletions(-) diff --git a/plugins/volumeFilter_test.go b/plugins/volumeFilter_test.go index 5ad9d5523..c0065b45e 100644 --- a/plugins/volumeFilter_test.go +++ b/plugins/volumeFilter_test.go @@ -6,6 +6,8 @@ import ( "os" "testing" + "github.com/stellar/go/txnbuild" + hProtocol "github.com/stellar/go/protocols/horizon" "github.com/stellar/kelp/model" "github.com/stellar/kelp/support/postgresdb" @@ -34,10 +36,12 @@ func connectTestDb() *sql.DB { return db } +var testNativeAsset hProtocol.Asset = hProtocol.Asset{Type: "native"} + func TestMakeFilterVolume(t *testing.T) { testAssetDisplayFn := model.AssetDisplayFn(func(asset model.Asset) (string, error) { sdexAssetMap := map[model.Asset]hProtocol.Asset{ - model.Asset("XLM"): hProtocol.Asset{Type: "native"}, + model.Asset("XLM"): testNativeAsset, } assetString, ok := sdexAssetMap[asset] if !ok { @@ -46,7 +50,6 @@ func TestMakeFilterVolume(t *testing.T) { return utils.Asset2String(assetString), nil }) - testNativeAsset := hProtocol.Asset{Type: "native"} testEmptyVolumeConfig := &VolumeFilterConfig{} db := connectTestDb() @@ -225,3 +228,212 @@ func TestMakeFilterVolume(t *testing.T) { }) } } + +func TestVolumeFilterFn(t *testing.T) { + db := connectTestDb() + dailyVolumeByDateQuery, e := makeDailyVolumeByDateQuery(db, "", "native", "native", []string{}, []string{}) + if e != nil { + t.Log("could not make empty config volume query") + return + } + + emptyFilter := &volumeFilter{ + name: "volumeFilter", + configValue: "", + baseAsset: testNativeAsset, + quoteAsset: testNativeAsset, + config: &VolumeFilterConfig{}, + dailyVolumeByDateQuery: dailyVolumeByDateQuery, + } + + testCases := []struct { + name string + filter *volumeFilter + dailyOTB *VolumeFilterConfig + dailyTBB *VolumeFilterConfig + op *txnbuild.ManageSellOffer + wantOp *txnbuild.ManageSellOffer + wantError error + wantTBB *VolumeFilterConfig + }{ + { + name: "failure - is selling", + filter: emptyFilter, + dailyOTB: nil, + dailyTBB: nil, + op: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.CreditAsset{}}, + wantOp: nil, + wantError: fmt.Errorf("error when running the isSelling check for offer '{Selling:{Code: Issuer:} Buying:{} Amount: Price: OfferID:0 SourceAccount:}': invalid assets, there are more than 2 distinct assets: sdexBase={native }, sdexQuote={native }, selling={ }, buying={}"), + wantTBB: nil, + }, + { + name: "failure - invalid sell price in op", + filter: emptyFilter, + dailyOTB: nil, + dailyTBB: nil, + op: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}}, + wantOp: nil, + wantError: fmt.Errorf("could not convert price () to float: strconv.ParseFloat: parsing \"\": invalid syntax"), + wantTBB: nil, + }, + { + name: "failure - invalid amount in op", + filter: emptyFilter, + dailyOTB: nil, + dailyTBB: nil, + op: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "0.0"}, + wantOp: nil, + wantError: fmt.Errorf("could not convert amount () to float: strconv.ParseFloat: parsing \"\": invalid syntax"), + wantTBB: nil, + }, + { + name: "failure - invalid amount in op", + filter: emptyFilter, + dailyOTB: nil, + dailyTBB: nil, + op: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "0.0"}, + wantOp: nil, + wantError: fmt.Errorf("could not convert amount () to float: strconv.ParseFloat: parsing \"\": invalid syntax"), + wantTBB: nil, + }, + { + name: "success - selling, no filter sell caps", + filter: emptyFilter, + dailyOTB: &VolumeFilterConfig{}, + dailyTBB: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloat(0.0), SellBaseAssetCapInQuoteUnits: createFloat(0.0)}, + op: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "100.0"}, + wantOp: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "100.0"}, + wantError: nil, + wantTBB: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloat(100.0), SellBaseAssetCapInQuoteUnits: createFloat(100.0)}, + }, + { + name: "success - selling, base units sell cap, don't keep selling base", + filter: &volumeFilter{ + name: "volumeFilter", + configValue: "", + baseAsset: testNativeAsset, + quoteAsset: testNativeAsset, + config: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloat(0.0)}, + dailyVolumeByDateQuery: dailyVolumeByDateQuery, + }, + dailyOTB: &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: createFloat(0.0), + SellBaseAssetCapInQuoteUnits: createFloat(0.0), + }, + dailyTBB: &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: createFloat(0.0), + SellBaseAssetCapInQuoteUnits: createFloat(0.0), + }, + op: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "100.0"}, + wantOp: nil, + wantError: nil, + wantTBB: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloat(0.0), SellBaseAssetCapInQuoteUnits: createFloat(0.0)}, + }, + { + name: "success - selling, base units sell cap, keep selling base", + filter: &volumeFilter{ + name: "volumeFilter", + configValue: "", + baseAsset: testNativeAsset, + quoteAsset: testNativeAsset, + config: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloat(1.0), mode: volumeFilterModeExact}, + dailyVolumeByDateQuery: dailyVolumeByDateQuery, + }, + dailyOTB: &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: createFloat(0.0), + SellBaseAssetCapInQuoteUnits: createFloat(0.0), + }, + dailyTBB: &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: createFloat(0.0), + SellBaseAssetCapInQuoteUnits: createFloat(0.0), + }, + op: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "100.0"}, + wantOp: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "1.0000000"}, + wantError: nil, + wantTBB: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloat(1.0), SellBaseAssetCapInQuoteUnits: createFloat(1.0)}, + }, + { + name: "success - selling, quote units sell cap, don't keep selling quote", + filter: &volumeFilter{ + name: "volumeFilter", + configValue: "", + baseAsset: testNativeAsset, + quoteAsset: testNativeAsset, + config: &VolumeFilterConfig{SellBaseAssetCapInQuoteUnits: createFloat(0.0)}, + dailyVolumeByDateQuery: dailyVolumeByDateQuery, + }, + dailyOTB: &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: createFloat(0.0), + SellBaseAssetCapInQuoteUnits: createFloat(0.0), + }, + dailyTBB: &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: createFloat(0.0), + SellBaseAssetCapInQuoteUnits: createFloat(0.0), + }, + op: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "100.0"}, + wantOp: nil, + wantError: nil, + wantTBB: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloat(0.0), SellBaseAssetCapInQuoteUnits: createFloat(0.0)}, + }, + { + name: "success - selling, quote units sell cap, keep selling quote", + filter: &volumeFilter{ + name: "volumeFilter", + configValue: "", + baseAsset: testNativeAsset, + quoteAsset: testNativeAsset, + config: &VolumeFilterConfig{SellBaseAssetCapInQuoteUnits: createFloat(1.0), mode: volumeFilterModeExact}, + dailyVolumeByDateQuery: dailyVolumeByDateQuery, + }, + dailyOTB: &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: createFloat(0.0), + SellBaseAssetCapInQuoteUnits: createFloat(0.0), + }, + dailyTBB: &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: createFloat(0.0), + SellBaseAssetCapInQuoteUnits: createFloat(0.0), + }, + op: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "100.0"}, + wantOp: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "1.0000000"}, + wantError: nil, + wantTBB: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloat(1.0), SellBaseAssetCapInQuoteUnits: createFloat(1.0)}, + }, + { + name: "success - selling, base and quote units sell cap, keep selling base and quote", + filter: &volumeFilter{ + name: "volumeFilter", + configValue: "", + baseAsset: testNativeAsset, + quoteAsset: testNativeAsset, + config: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloat(1.0), SellBaseAssetCapInQuoteUnits: createFloat(1.0), mode: volumeFilterModeExact}, + dailyVolumeByDateQuery: dailyVolumeByDateQuery, + }, + dailyOTB: &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: createFloat(0.0), + SellBaseAssetCapInQuoteUnits: createFloat(0.0), + }, + dailyTBB: &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: createFloat(0.0), + SellBaseAssetCapInQuoteUnits: createFloat(0.0), + }, + op: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "100.0"}, + wantOp: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "1.0000000"}, + wantError: nil, + wantTBB: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloat(1.0), SellBaseAssetCapInQuoteUnits: createFloat(1.0)}, + }, + } + + for _, k := range testCases { + t.Run(k.name, func(t *testing.T) { + tbb := k.dailyTBB + actual, e := k.filter.volumeFilterFn(k.dailyOTB, tbb, k.op) + assert.Equal(t, k.wantError, e) + assert.Equal(t, k.wantOp, actual) + assert.Equal(t, k.wantTBB, tbb) + }) + } +} + +func createFloat(x float64) *float64 { + return &x +} From 91ce0bbc7261654cbc3c35ba183580af89fd33ea Mon Sep 17 00:00:00 2001 From: Debnil Sur Date: Thu, 22 Oct 2020 16:17:53 -0700 Subject: [PATCH 03/14] Rename createFloat to createFloatPtr. --- plugins/volumeFilter.go | 3 +- plugins/volumeFilter_test.go | 66 ++++++++++++++++++------------------ 2 files changed, 34 insertions(+), 35 deletions(-) diff --git a/plugins/volumeFilter.go b/plugins/volumeFilter.go index 1bb2025a7..c00faa030 100644 --- a/plugins/volumeFilter.go +++ b/plugins/volumeFilter.go @@ -69,7 +69,6 @@ func makeFilterVolume( if e != nil { return nil, fmt.Errorf("could not convert base asset (%s) from trading pair via the passed in assetDisplayFn: %s", string(tradingPair.Base), e) } - quoteAssetString, e := assetDisplayFn(tradingPair.Quote) if e != nil { return nil, fmt.Errorf("could not convert quote asset (%s) from trading pair via the passed in assetDisplayFn: %s", string(tradingPair.Quote), e) @@ -77,7 +76,7 @@ func makeFilterVolume( dailyVolumeByDateQuery, e := makeDailyVolumeByDateQuery(db, exchangeName, baseAssetString, quoteAssetString, config.optionalAccountIDs, config.additionalMarketIDs) if e != nil { - return nil, fmt.Errorf("could not make daily volume by date query: %s", e) + return nil, fmt.Errorf("could not make daily volume by date Query: %s", e) } return &volumeFilter{ diff --git a/plugins/volumeFilter_test.go b/plugins/volumeFilter_test.go index c0065b45e..908ebbcf1 100644 --- a/plugins/volumeFilter_test.go +++ b/plugins/volumeFilter_test.go @@ -300,11 +300,11 @@ func TestVolumeFilterFn(t *testing.T) { name: "success - selling, no filter sell caps", filter: emptyFilter, dailyOTB: &VolumeFilterConfig{}, - dailyTBB: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloat(0.0), SellBaseAssetCapInQuoteUnits: createFloat(0.0)}, + dailyTBB: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloatPtr(0.0), SellBaseAssetCapInQuoteUnits: createFloatPtr(0.0)}, op: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "100.0"}, wantOp: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "100.0"}, wantError: nil, - wantTBB: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloat(100.0), SellBaseAssetCapInQuoteUnits: createFloat(100.0)}, + wantTBB: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloatPtr(100.0), SellBaseAssetCapInQuoteUnits: createFloatPtr(100.0)}, }, { name: "success - selling, base units sell cap, don't keep selling base", @@ -313,21 +313,21 @@ func TestVolumeFilterFn(t *testing.T) { configValue: "", baseAsset: testNativeAsset, quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloat(0.0)}, + config: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloatPtr(0.0)}, dailyVolumeByDateQuery: dailyVolumeByDateQuery, }, dailyOTB: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: createFloat(0.0), - SellBaseAssetCapInQuoteUnits: createFloat(0.0), + SellBaseAssetCapInBaseUnits: createFloatPtr(0.0), + SellBaseAssetCapInQuoteUnits: createFloatPtr(0.0), }, dailyTBB: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: createFloat(0.0), - SellBaseAssetCapInQuoteUnits: createFloat(0.0), + SellBaseAssetCapInBaseUnits: createFloatPtr(0.0), + SellBaseAssetCapInQuoteUnits: createFloatPtr(0.0), }, op: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "100.0"}, wantOp: nil, wantError: nil, - wantTBB: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloat(0.0), SellBaseAssetCapInQuoteUnits: createFloat(0.0)}, + wantTBB: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloatPtr(0.0), SellBaseAssetCapInQuoteUnits: createFloatPtr(0.0)}, }, { name: "success - selling, base units sell cap, keep selling base", @@ -336,21 +336,21 @@ func TestVolumeFilterFn(t *testing.T) { configValue: "", baseAsset: testNativeAsset, quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloat(1.0), mode: volumeFilterModeExact}, + config: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloatPtr(1.0), mode: volumeFilterModeExact}, dailyVolumeByDateQuery: dailyVolumeByDateQuery, }, dailyOTB: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: createFloat(0.0), - SellBaseAssetCapInQuoteUnits: createFloat(0.0), + SellBaseAssetCapInBaseUnits: createFloatPtr(0.0), + SellBaseAssetCapInQuoteUnits: createFloatPtr(0.0), }, dailyTBB: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: createFloat(0.0), - SellBaseAssetCapInQuoteUnits: createFloat(0.0), + SellBaseAssetCapInBaseUnits: createFloatPtr(0.0), + SellBaseAssetCapInQuoteUnits: createFloatPtr(0.0), }, op: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "100.0"}, wantOp: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "1.0000000"}, wantError: nil, - wantTBB: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloat(1.0), SellBaseAssetCapInQuoteUnits: createFloat(1.0)}, + wantTBB: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloatPtr(1.0), SellBaseAssetCapInQuoteUnits: createFloatPtr(1.0)}, }, { name: "success - selling, quote units sell cap, don't keep selling quote", @@ -359,21 +359,21 @@ func TestVolumeFilterFn(t *testing.T) { configValue: "", baseAsset: testNativeAsset, quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{SellBaseAssetCapInQuoteUnits: createFloat(0.0)}, + config: &VolumeFilterConfig{SellBaseAssetCapInQuoteUnits: createFloatPtr(0.0)}, dailyVolumeByDateQuery: dailyVolumeByDateQuery, }, dailyOTB: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: createFloat(0.0), - SellBaseAssetCapInQuoteUnits: createFloat(0.0), + SellBaseAssetCapInBaseUnits: createFloatPtr(0.0), + SellBaseAssetCapInQuoteUnits: createFloatPtr(0.0), }, dailyTBB: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: createFloat(0.0), - SellBaseAssetCapInQuoteUnits: createFloat(0.0), + SellBaseAssetCapInBaseUnits: createFloatPtr(0.0), + SellBaseAssetCapInQuoteUnits: createFloatPtr(0.0), }, op: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "100.0"}, wantOp: nil, wantError: nil, - wantTBB: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloat(0.0), SellBaseAssetCapInQuoteUnits: createFloat(0.0)}, + wantTBB: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloatPtr(0.0), SellBaseAssetCapInQuoteUnits: createFloatPtr(0.0)}, }, { name: "success - selling, quote units sell cap, keep selling quote", @@ -382,21 +382,21 @@ func TestVolumeFilterFn(t *testing.T) { configValue: "", baseAsset: testNativeAsset, quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{SellBaseAssetCapInQuoteUnits: createFloat(1.0), mode: volumeFilterModeExact}, + config: &VolumeFilterConfig{SellBaseAssetCapInQuoteUnits: createFloatPtr(1.0), mode: volumeFilterModeExact}, dailyVolumeByDateQuery: dailyVolumeByDateQuery, }, dailyOTB: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: createFloat(0.0), - SellBaseAssetCapInQuoteUnits: createFloat(0.0), + SellBaseAssetCapInBaseUnits: createFloatPtr(0.0), + SellBaseAssetCapInQuoteUnits: createFloatPtr(0.0), }, dailyTBB: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: createFloat(0.0), - SellBaseAssetCapInQuoteUnits: createFloat(0.0), + SellBaseAssetCapInBaseUnits: createFloatPtr(0.0), + SellBaseAssetCapInQuoteUnits: createFloatPtr(0.0), }, op: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "100.0"}, wantOp: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "1.0000000"}, wantError: nil, - wantTBB: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloat(1.0), SellBaseAssetCapInQuoteUnits: createFloat(1.0)}, + wantTBB: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloatPtr(1.0), SellBaseAssetCapInQuoteUnits: createFloatPtr(1.0)}, }, { name: "success - selling, base and quote units sell cap, keep selling base and quote", @@ -405,21 +405,21 @@ func TestVolumeFilterFn(t *testing.T) { configValue: "", baseAsset: testNativeAsset, quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloat(1.0), SellBaseAssetCapInQuoteUnits: createFloat(1.0), mode: volumeFilterModeExact}, + config: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloatPtr(1.0), SellBaseAssetCapInQuoteUnits: createFloatPtr(1.0), mode: volumeFilterModeExact}, dailyVolumeByDateQuery: dailyVolumeByDateQuery, }, dailyOTB: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: createFloat(0.0), - SellBaseAssetCapInQuoteUnits: createFloat(0.0), + SellBaseAssetCapInBaseUnits: createFloatPtr(0.0), + SellBaseAssetCapInQuoteUnits: createFloatPtr(0.0), }, dailyTBB: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: createFloat(0.0), - SellBaseAssetCapInQuoteUnits: createFloat(0.0), + SellBaseAssetCapInBaseUnits: createFloatPtr(0.0), + SellBaseAssetCapInQuoteUnits: createFloatPtr(0.0), }, op: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "100.0"}, wantOp: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "1.0000000"}, wantError: nil, - wantTBB: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloat(1.0), SellBaseAssetCapInQuoteUnits: createFloat(1.0)}, + wantTBB: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloatPtr(1.0), SellBaseAssetCapInQuoteUnits: createFloatPtr(1.0)}, }, } @@ -434,6 +434,6 @@ func TestVolumeFilterFn(t *testing.T) { } } -func createFloat(x float64) *float64 { +func createFloatPtr(x float64) *float64 { return &x } From 2ec938f69ca8e62d76a14d1d09f5278a56792336 Mon Sep 17 00:00:00 2001 From: Debnil Sur Date: Thu, 22 Oct 2020 16:26:40 -0700 Subject: [PATCH 04/14] Fix capitalization error. --- plugins/volumeFilter_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/volumeFilter_test.go b/plugins/volumeFilter_test.go index 908ebbcf1..b1a45fb82 100644 --- a/plugins/volumeFilter_test.go +++ b/plugins/volumeFilter_test.go @@ -129,7 +129,7 @@ func TestMakeFilterVolume(t *testing.T) { quoteAsset: testNativeAsset, config: &VolumeFilterConfig{}, db: nil, - wantError: fmt.Errorf("could not make daily volume by date query: could not make daily volume by date action: the provided db should be non-nil"), + wantError: fmt.Errorf("could not make daily volume by date Query: could not make daily volume by date action: the provided db should be non-nil"), wantSubmitFilter: nil, }, { From 886b8fa505f5f44a6715d142a5ceb5bbc727ca67 Mon Sep 17 00:00:00 2001 From: Debnil Sur Date: Tue, 27 Oct 2020 19:07:44 -0700 Subject: [PATCH 05/14] Rewrite most of the tests - still need to eliminate a couple of structs. --- plugins/volumeFilter.go | 26 +- plugins/volumeFilter_test.go | 656 +++++++++++++++++++---------------- support/utils/functions.go | 1 + 3 files changed, 358 insertions(+), 325 deletions(-) diff --git a/plugins/volumeFilter.go b/plugins/volumeFilter.go index c00faa030..5b8427122 100644 --- a/plugins/volumeFilter.go +++ b/plugins/volumeFilter.go @@ -74,11 +74,15 @@ func makeFilterVolume( return nil, fmt.Errorf("could not convert quote asset (%s) from trading pair via the passed in assetDisplayFn: %s", string(tradingPair.Quote), e) } - dailyVolumeByDateQuery, e := makeDailyVolumeByDateQuery(db, exchangeName, baseAssetString, quoteAssetString, config.optionalAccountIDs, config.additionalMarketIDs) + marketID := MakeMarketID(exchangeName, baseAssetString, quoteAssetString) + marketIDs := utils.Dedupe(append([]string{marketID}, config.additionalMarketIDs...)) + dailyVolumeByDateQuery, e := queries.MakeDailyVolumeByDateForMarketIdsAction(db, marketIDs, "sell", config.optionalAccountIDs) if e != nil { - return nil, fmt.Errorf("could not make daily volume by date Query: %s", e) + return nil, fmt.Errorf("could not make daily volume by date action: %s", e) } + // TODO DS Validate the config, to have exactly one asset cap defined; a valid mode; non-nil market IDs; and non-nil optional account IDs. + return &volumeFilter{ name: "volumeFilter", configValue: configValue, @@ -89,24 +93,6 @@ func makeFilterVolume( }, nil } -func makeDailyVolumeByDateQuery( - db *sql.DB, - exchangeName string, - baseAsset string, - quoteAsset string, - optionalAccountIDs []string, - additionalMarketIDs []string, -) (*queries.DailyVolumeByDate, error) { - marketID := MakeMarketID(exchangeName, baseAsset, quoteAsset) - marketIDs := utils.Dedupe(append([]string{marketID}, additionalMarketIDs...)) - dailyVolumeByDateQuery, e := queries.MakeDailyVolumeByDateForMarketIdsAction(db, marketIDs, "sell", optionalAccountIDs) - if e != nil { - return nil, fmt.Errorf("could not make daily volume by date action: %s", e) - } - - return dailyVolumeByDateQuery, nil -} - var _ SubmitFilter = &volumeFilter{} // Validate ensures validity diff --git a/plugins/volumeFilter_test.go b/plugins/volumeFilter_test.go index b1a45fb82..e5a5a4a3a 100644 --- a/plugins/volumeFilter_test.go +++ b/plugins/volumeFilter_test.go @@ -2,224 +2,293 @@ package plugins import ( "database/sql" - "fmt" - "os" "testing" + "github.com/openlyinc/pointy" + "github.com/stellar/kelp/queries" + "github.com/stellar/kelp/support/utils" + "github.com/stellar/go/txnbuild" hProtocol "github.com/stellar/go/protocols/horizon" "github.com/stellar/kelp/model" - "github.com/stellar/kelp/support/postgresdb" - "github.com/stellar/kelp/support/utils" "github.com/stretchr/testify/assert" ) -func connectTestDb() *sql.DB { - postgresDbConfig := &postgresdb.Config{ - Host: "localhost", - Port: 5432, - DbName: "test_database", - User: os.Getenv("POSTGRES_USER"), - SSLEnable: false, - } +var testNativeAsset hProtocol.Asset = hProtocol.Asset{Type: "native"} - _, e := postgresdb.CreateDatabaseIfNotExists(postgresDbConfig) - if e != nil { - panic(e) - } +func mustMakeTestDailyVolumeQuery(optionalAccountIDs, additionalMarketIDs []string) *queries.DailyVolumeByDate { + marketID := MakeMarketID("", "native", "native") + marketIDs := utils.Dedupe(append([]string{marketID}, additionalMarketIDs...)) - db, e := sql.Open("postgres", postgresDbConfig.MakeConnectString()) + query, e := queries.MakeDailyVolumeByDateForMarketIdsAction(&sql.DB{}, marketIDs, "sell", optionalAccountIDs) if e != nil { panic(e) } - return db -} -var testNativeAsset hProtocol.Asset = hProtocol.Asset{Type: "native"} + return query +} func TestMakeFilterVolume(t *testing.T) { - testAssetDisplayFn := model.AssetDisplayFn(func(asset model.Asset) (string, error) { - sdexAssetMap := map[model.Asset]hProtocol.Asset{ - model.Asset("XLM"): testNativeAsset, - } - assetString, ok := sdexAssetMap[asset] - if !ok { - return "", fmt.Errorf("cannot recognize the asset %s", string(asset)) - } - return utils.Asset2String(assetString), nil - }) - - testEmptyVolumeConfig := &VolumeFilterConfig{} - db := connectTestDb() - - emptyConfigVolumeQuery, e := makeDailyVolumeByDateQuery(db, "", "native", "native", []string{}, []string{}) - if e != nil { - t.Log("could not make empty config volume query") - return - } - - marketIDs := []string{"marketID"} - marketConfigVolumeQuery, e := makeDailyVolumeByDateQuery(db, "", "native", "native", []string{}, marketIDs) - if e != nil { - t.Log("could not make market config volume query") - return - } - - accountIDs := []string{"accountID"} - accountConfigVolumeQuery, e := makeDailyVolumeByDateQuery(db, "", "native", "native", accountIDs, []string{}) - if e != nil { - t.Log("could not make account config volume query") - return - } - - accountMarketConfigVolumeQuery, e := makeDailyVolumeByDateQuery(db, "", "native", "native", accountIDs, marketIDs) - if e != nil { - t.Log("could not make account and market config volume query") - return - } + testAssetDisplayFn := model.MakeSdexMappedAssetDisplayFn(map[model.Asset]hProtocol.Asset{model.Asset("XLM"): testNativeAsset}) testCases := []struct { name string - configValue string - exchangeName string - tradingPair *model.TradingPair assetDisplayFn model.AssetDisplayFn - baseAsset hProtocol.Asset - quoteAsset hProtocol.Asset - db *sql.DB config *VolumeFilterConfig wantError error wantSubmitFilter SubmitFilter }{ - // Note: config can be additional market IDs, make sure to test additionalMarketIds and optionalAccountIDs + // TODO DS Confirm the empty config fails once validation is added to the constructor { - name: "failure - display base", - configValue: "", - exchangeName: "", - tradingPair: &model.TradingPair{Base: "FAIL", Quote: ""}, - assetDisplayFn: testAssetDisplayFn, - baseAsset: hProtocol.Asset{}, - quoteAsset: hProtocol.Asset{}, - db: db, - config: &VolumeFilterConfig{}, - wantError: fmt.Errorf("could not convert base asset (FAIL) from trading pair via the passed in assetDisplayFn: cannot recognize the asset FAIL"), - wantSubmitFilter: nil, + name: "empty config", + config: &VolumeFilterConfig{}, + wantError: nil, + wantSubmitFilter: &volumeFilter{ + name: "volumeFilter", + baseAsset: testNativeAsset, + quoteAsset: testNativeAsset, + config: &VolumeFilterConfig{}, + dailyVolumeByDateQuery: mustMakeTestDailyVolumeQuery([]string{}, []string{}), + }, }, { - name: "failure - display quote", - configValue: "", - exchangeName: "", - tradingPair: &model.TradingPair{Base: "XLM", Quote: "FAIL"}, - assetDisplayFn: testAssetDisplayFn, - baseAsset: testNativeAsset, - quoteAsset: hProtocol.Asset{}, - config: &VolumeFilterConfig{}, - wantError: fmt.Errorf("could not convert quote asset (FAIL) from trading pair via the passed in assetDisplayFn: cannot recognize the asset FAIL"), - wantSubmitFilter: nil, + name: "non nil cap in base, nil cap in quote", + config: &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), + mode: volumeFilterModeExact, + additionalMarketIDs: []string{}, + optionalAccountIDs: []string{}, + }, + wantError: nil, + wantSubmitFilter: &volumeFilter{ + name: "volumeFilter", + baseAsset: testNativeAsset, + quoteAsset: testNativeAsset, + config: &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), + mode: volumeFilterModeExact, + additionalMarketIDs: []string{}, + optionalAccountIDs: []string{}, + }, + dailyVolumeByDateQuery: mustMakeTestDailyVolumeQuery([]string{}, []string{}), + }, }, { - name: "failure - query", - configValue: "", - exchangeName: "", - tradingPair: &model.TradingPair{Base: "XLM", Quote: "XLM"}, - assetDisplayFn: testAssetDisplayFn, - baseAsset: testNativeAsset, - quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{}, - db: nil, - wantError: fmt.Errorf("could not make daily volume by date Query: could not make daily volume by date action: the provided db should be non-nil"), - wantSubmitFilter: nil, + name: "nil cap in base, non nil cap in quote", + config: &VolumeFilterConfig{ + SellBaseAssetCapInQuoteUnits: pointy.Float64(1.0), + mode: volumeFilterModeExact, + additionalMarketIDs: []string{}, + optionalAccountIDs: []string{}, + }, + wantError: nil, + wantSubmitFilter: &volumeFilter{ + name: "volumeFilter", + baseAsset: testNativeAsset, + quoteAsset: testNativeAsset, + config: &VolumeFilterConfig{ + SellBaseAssetCapInQuoteUnits: pointy.Float64(1.0), + mode: volumeFilterModeExact, + additionalMarketIDs: []string{}, + optionalAccountIDs: []string{}, + }, + dailyVolumeByDateQuery: mustMakeTestDailyVolumeQuery([]string{}, []string{}), + }, }, { - name: "success - empty config", - configValue: "", - exchangeName: "", - tradingPair: &model.TradingPair{Base: "XLM", Quote: "XLM"}, - assetDisplayFn: testAssetDisplayFn, - baseAsset: testNativeAsset, - quoteAsset: testNativeAsset, - config: testEmptyVolumeConfig, - db: db, - wantError: nil, + name: "exact mode", + config: &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), + mode: volumeFilterModeExact, + additionalMarketIDs: []string{}, + optionalAccountIDs: []string{}, + }, + wantError: nil, wantSubmitFilter: &volumeFilter{ - name: "volumeFilter", - baseAsset: testNativeAsset, - quoteAsset: testNativeAsset, - config: testEmptyVolumeConfig, - dailyVolumeByDateQuery: emptyConfigVolumeQuery, + name: "volumeFilter", + baseAsset: testNativeAsset, + quoteAsset: testNativeAsset, + config: &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), + mode: volumeFilterModeExact, + additionalMarketIDs: []string{}, + optionalAccountIDs: []string{}, + }, + dailyVolumeByDateQuery: mustMakeTestDailyVolumeQuery([]string{}, []string{}), }, }, { - name: "success - market ids", - configValue: "", - exchangeName: "", - tradingPair: &model.TradingPair{Base: "XLM", Quote: "XLM"}, - assetDisplayFn: testAssetDisplayFn, - baseAsset: testNativeAsset, - quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{additionalMarketIDs: marketIDs}, - db: db, - wantError: nil, + name: "ignore mode", + config: &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), + mode: volumeFilterModeIgnore, + additionalMarketIDs: []string{}, + optionalAccountIDs: []string{}, + }, + wantError: nil, wantSubmitFilter: &volumeFilter{ - name: "volumeFilter", - baseAsset: testNativeAsset, - quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{additionalMarketIDs: marketIDs}, - dailyVolumeByDateQuery: marketConfigVolumeQuery, + name: "volumeFilter", + baseAsset: testNativeAsset, + quoteAsset: testNativeAsset, + config: &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), + mode: volumeFilterModeIgnore, + additionalMarketIDs: []string{}, + optionalAccountIDs: []string{}, + }, + dailyVolumeByDateQuery: mustMakeTestDailyVolumeQuery([]string{}, []string{}), }, }, { - name: "success - account ids", - configValue: "", - exchangeName: "", - tradingPair: &model.TradingPair{Base: "XLM", Quote: "XLM"}, - assetDisplayFn: testAssetDisplayFn, - baseAsset: testNativeAsset, - quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{optionalAccountIDs: accountIDs}, - db: db, - wantError: nil, + name: "1 market id", + config: &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), + mode: volumeFilterModeIgnore, + additionalMarketIDs: []string{"marketID"}, + optionalAccountIDs: []string{}, + }, + wantError: nil, wantSubmitFilter: &volumeFilter{ - name: "volumeFilter", - baseAsset: testNativeAsset, - quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{optionalAccountIDs: accountIDs}, - dailyVolumeByDateQuery: accountConfigVolumeQuery, + name: "volumeFilter", + baseAsset: testNativeAsset, + quoteAsset: testNativeAsset, + config: &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), + mode: volumeFilterModeIgnore, + additionalMarketIDs: []string{"marketID"}, + optionalAccountIDs: []string{}, + }, + dailyVolumeByDateQuery: mustMakeTestDailyVolumeQuery([]string{}, []string{"marketID"}), }, }, { - name: "success - account and market ids", - configValue: "", - exchangeName: "", - tradingPair: &model.TradingPair{Base: "XLM", Quote: "XLM"}, - assetDisplayFn: testAssetDisplayFn, - baseAsset: testNativeAsset, - quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{optionalAccountIDs: accountIDs, additionalMarketIDs: marketIDs}, - db: db, - wantError: nil, + name: "2 market ids", + config: &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), + mode: volumeFilterModeIgnore, + additionalMarketIDs: []string{"marketID1", "marketID2"}, + optionalAccountIDs: []string{}, + }, + wantError: nil, wantSubmitFilter: &volumeFilter{ - name: "volumeFilter", - baseAsset: testNativeAsset, - quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{optionalAccountIDs: accountIDs, additionalMarketIDs: marketIDs}, - dailyVolumeByDateQuery: accountMarketConfigVolumeQuery, + name: "volumeFilter", + baseAsset: testNativeAsset, + quoteAsset: testNativeAsset, + config: &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), + mode: volumeFilterModeIgnore, + additionalMarketIDs: []string{"marketID1", "marketID2"}, + optionalAccountIDs: []string{}, + }, + dailyVolumeByDateQuery: mustMakeTestDailyVolumeQuery([]string{}, []string{"marketID1", "marketID2"}), + }, + }, + { + name: "2 dupe market ids, 1 distinct", + config: &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), + mode: volumeFilterModeIgnore, + additionalMarketIDs: []string{"marketID1", "marketID1", "marketID2"}, + optionalAccountIDs: []string{}, + }, + wantError: nil, + wantSubmitFilter: &volumeFilter{ + name: "volumeFilter", + baseAsset: testNativeAsset, + quoteAsset: testNativeAsset, + config: &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), + mode: volumeFilterModeIgnore, + additionalMarketIDs: []string{"marketID1", "marketID1", "marketID2"}, + optionalAccountIDs: []string{}, + }, + dailyVolumeByDateQuery: mustMakeTestDailyVolumeQuery([]string{}, []string{"marketID1", "marketID1", "marketID2"}), + }, + }, + { + name: "1 account id", + config: &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), + mode: volumeFilterModeIgnore, + additionalMarketIDs: []string{}, + optionalAccountIDs: []string{"accountID"}, + }, + wantError: nil, + wantSubmitFilter: &volumeFilter{ + name: "volumeFilter", + baseAsset: testNativeAsset, + quoteAsset: testNativeAsset, + config: &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), + mode: volumeFilterModeIgnore, + additionalMarketIDs: []string{}, + optionalAccountIDs: []string{"accountID"}, + }, + dailyVolumeByDateQuery: mustMakeTestDailyVolumeQuery([]string{"accountID"}, []string{}), + }, + }, + { + name: "2 account ids", + config: &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), + mode: volumeFilterModeIgnore, + additionalMarketIDs: []string{}, + optionalAccountIDs: []string{"accountID1", "accountID2"}, + }, + wantError: nil, + wantSubmitFilter: &volumeFilter{ + name: "volumeFilter", + baseAsset: testNativeAsset, + quoteAsset: testNativeAsset, + config: &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), + mode: volumeFilterModeIgnore, + additionalMarketIDs: []string{}, + optionalAccountIDs: []string{"accountID1", "accountID2"}, + }, + dailyVolumeByDateQuery: mustMakeTestDailyVolumeQuery([]string{"accountID1", "accountID2"}, []string{}), + }, + }, + { + name: "account and market ids", + config: &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), + mode: volumeFilterModeIgnore, + additionalMarketIDs: []string{"marketID"}, + optionalAccountIDs: []string{"accountID"}, + }, + wantError: nil, + wantSubmitFilter: &volumeFilter{ + name: "volumeFilter", + baseAsset: testNativeAsset, + quoteAsset: testNativeAsset, + config: &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), + mode: volumeFilterModeIgnore, + additionalMarketIDs: []string{"marketID"}, + optionalAccountIDs: []string{"accountID"}, + }, + dailyVolumeByDateQuery: mustMakeTestDailyVolumeQuery([]string{"accountID"}, []string{"marketID"}), }, }, } + configValue := "" + exchangeName := "" + tradingPair := &model.TradingPair{Base: "XLM", Quote: "XLM"} + for _, k := range testCases { t.Run(k.name, func(t *testing.T) { actual, e := makeFilterVolume( - k.configValue, - k.exchangeName, - k.tradingPair, - k.assetDisplayFn, - k.baseAsset, - k.quoteAsset, - k.db, + configValue, + exchangeName, + tradingPair, + testAssetDisplayFn, + testNativeAsset, + testNativeAsset, + &sql.DB{}, k.config, ) @@ -229,13 +298,31 @@ func TestMakeFilterVolume(t *testing.T) { } } -func TestVolumeFilterFn(t *testing.T) { - db := connectTestDb() - dailyVolumeByDateQuery, e := makeDailyVolumeByDateQuery(db, "", "native", "native", []string{}, []string{}) - if e != nil { - t.Log("could not make empty config volume query") - return +func makeManageSellOffer(price, amount string) *txnbuild.ManageSellOffer { + if amount == "" { + return nil + } + + return &txnbuild.ManageSellOffer{ + Buying: txnbuild.NativeAsset{}, + Selling: txnbuild.NativeAsset{}, + Price: price, + Amount: amount, + } +} + +func makeTestVolumeFilterConfig(baseCap, quoteCap float64) *VolumeFilterConfig { + return &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: pointy.Float64(baseCap), + SellBaseAssetCapInQuoteUnits: pointy.Float64(quoteCap), + mode: volumeFilterModeExact, + additionalMarketIDs: []string{}, + optionalAccountIDs: []string{}, } +} + +func TestVolumeFilterFn(t *testing.T) { + dailyVolumeByDateQuery := mustMakeTestDailyVolumeQuery([]string{}, []string{}) emptyFilter := &volumeFilter{ name: "volumeFilter", @@ -247,193 +334,152 @@ func TestVolumeFilterFn(t *testing.T) { } testCases := []struct { - name string - filter *volumeFilter - dailyOTB *VolumeFilterConfig - dailyTBB *VolumeFilterConfig - op *txnbuild.ManageSellOffer - wantOp *txnbuild.ManageSellOffer - wantError error - wantTBB *VolumeFilterConfig + name string + filter *volumeFilter + otbBaseCap float64 + otbQuoteCap float64 + tbbBaseCap float64 + tbbQuoteCap float64 + price string + inputAmount string + wantAmount string + wantError error + wantTbbBaseCap float64 + wantTbbQuoteCap float64 }{ { - name: "failure - is selling", - filter: emptyFilter, - dailyOTB: nil, - dailyTBB: nil, - op: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.CreditAsset{}}, - wantOp: nil, - wantError: fmt.Errorf("error when running the isSelling check for offer '{Selling:{Code: Issuer:} Buying:{} Amount: Price: OfferID:0 SourceAccount:}': invalid assets, there are more than 2 distinct assets: sdexBase={native }, sdexQuote={native }, selling={ }, buying={}"), - wantTBB: nil, - }, - { - name: "failure - invalid sell price in op", - filter: emptyFilter, - dailyOTB: nil, - dailyTBB: nil, - op: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}}, - wantOp: nil, - wantError: fmt.Errorf("could not convert price () to float: strconv.ParseFloat: parsing \"\": invalid syntax"), - wantTBB: nil, - }, - { - name: "failure - invalid amount in op", - filter: emptyFilter, - dailyOTB: nil, - dailyTBB: nil, - op: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "0.0"}, - wantOp: nil, - wantError: fmt.Errorf("could not convert amount () to float: strconv.ParseFloat: parsing \"\": invalid syntax"), - wantTBB: nil, + name: "selling, no filter sell caps", + filter: emptyFilter, + otbBaseCap: 0.0, + otbQuoteCap: 0.0, + tbbBaseCap: 0.0, + tbbQuoteCap: 0.0, + price: "2.0", + inputAmount: "100.0", + wantAmount: "100.0", + wantError: nil, + wantTbbBaseCap: 100.0, + wantTbbQuoteCap: 200.0, }, { - name: "failure - invalid amount in op", - filter: emptyFilter, - dailyOTB: nil, - dailyTBB: nil, - op: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "0.0"}, - wantOp: nil, - wantError: fmt.Errorf("could not convert amount () to float: strconv.ParseFloat: parsing \"\": invalid syntax"), - wantTBB: nil, - }, - { - name: "success - selling, no filter sell caps", - filter: emptyFilter, - dailyOTB: &VolumeFilterConfig{}, - dailyTBB: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloatPtr(0.0), SellBaseAssetCapInQuoteUnits: createFloatPtr(0.0)}, - op: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "100.0"}, - wantOp: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "100.0"}, - wantError: nil, - wantTBB: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloatPtr(100.0), SellBaseAssetCapInQuoteUnits: createFloatPtr(100.0)}, - }, - { - name: "success - selling, base units sell cap, don't keep selling base", + name: "selling, base units sell cap, don't keep selling base", filter: &volumeFilter{ name: "volumeFilter", configValue: "", baseAsset: testNativeAsset, quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloatPtr(0.0)}, + config: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: pointy.Float64(0.0)}, dailyVolumeByDateQuery: dailyVolumeByDateQuery, }, - dailyOTB: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: createFloatPtr(0.0), - SellBaseAssetCapInQuoteUnits: createFloatPtr(0.0), - }, - dailyTBB: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: createFloatPtr(0.0), - SellBaseAssetCapInQuoteUnits: createFloatPtr(0.0), - }, - op: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "100.0"}, - wantOp: nil, - wantError: nil, - wantTBB: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloatPtr(0.0), SellBaseAssetCapInQuoteUnits: createFloatPtr(0.0)}, + otbBaseCap: 0.0, + otbQuoteCap: 0.0, + tbbBaseCap: 0.0, + tbbQuoteCap: 0.0, + price: "2.0", + inputAmount: "100.0", + wantAmount: "", + wantError: nil, + wantTbbBaseCap: 0.0, + wantTbbQuoteCap: 0.0, }, { - name: "success - selling, base units sell cap, keep selling base", + name: "selling, base units sell cap, keep selling base", filter: &volumeFilter{ name: "volumeFilter", configValue: "", baseAsset: testNativeAsset, quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloatPtr(1.0), mode: volumeFilterModeExact}, + config: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), mode: volumeFilterModeExact}, dailyVolumeByDateQuery: dailyVolumeByDateQuery, }, - dailyOTB: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: createFloatPtr(0.0), - SellBaseAssetCapInQuoteUnits: createFloatPtr(0.0), - }, - dailyTBB: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: createFloatPtr(0.0), - SellBaseAssetCapInQuoteUnits: createFloatPtr(0.0), - }, - op: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "100.0"}, - wantOp: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "1.0000000"}, - wantError: nil, - wantTBB: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloatPtr(1.0), SellBaseAssetCapInQuoteUnits: createFloatPtr(1.0)}, + otbBaseCap: 0.0, + otbQuoteCap: 0.0, + tbbBaseCap: 0.0, + tbbQuoteCap: 0.0, + price: "2.0", + inputAmount: "100.0", + wantAmount: "1.0000000", + wantError: nil, + wantTbbBaseCap: 1.0, + wantTbbQuoteCap: 2.0, }, { - name: "success - selling, quote units sell cap, don't keep selling quote", + name: "selling, quote units sell cap, don't keep selling quote", filter: &volumeFilter{ name: "volumeFilter", configValue: "", baseAsset: testNativeAsset, quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{SellBaseAssetCapInQuoteUnits: createFloatPtr(0.0)}, + config: &VolumeFilterConfig{SellBaseAssetCapInQuoteUnits: pointy.Float64(0.0)}, dailyVolumeByDateQuery: dailyVolumeByDateQuery, }, - dailyOTB: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: createFloatPtr(0.0), - SellBaseAssetCapInQuoteUnits: createFloatPtr(0.0), - }, - dailyTBB: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: createFloatPtr(0.0), - SellBaseAssetCapInQuoteUnits: createFloatPtr(0.0), - }, - op: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "100.0"}, - wantOp: nil, - wantError: nil, - wantTBB: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloatPtr(0.0), SellBaseAssetCapInQuoteUnits: createFloatPtr(0.0)}, + otbBaseCap: 0.0, + otbQuoteCap: 0.0, + tbbBaseCap: 0.0, + tbbQuoteCap: 0.0, + price: "2.0", + inputAmount: "100.0", + wantAmount: "", + wantError: nil, + wantTbbBaseCap: 0.0, + wantTbbQuoteCap: 0.0, }, { - name: "success - selling, quote units sell cap, keep selling quote", + name: "selling, quote units sell cap, keep selling quote", filter: &volumeFilter{ name: "volumeFilter", configValue: "", baseAsset: testNativeAsset, quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{SellBaseAssetCapInQuoteUnits: createFloatPtr(1.0), mode: volumeFilterModeExact}, + config: &VolumeFilterConfig{SellBaseAssetCapInQuoteUnits: pointy.Float64(1.0), mode: volumeFilterModeExact}, dailyVolumeByDateQuery: dailyVolumeByDateQuery, }, - dailyOTB: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: createFloatPtr(0.0), - SellBaseAssetCapInQuoteUnits: createFloatPtr(0.0), - }, - dailyTBB: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: createFloatPtr(0.0), - SellBaseAssetCapInQuoteUnits: createFloatPtr(0.0), - }, - op: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "100.0"}, - wantOp: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "1.0000000"}, - wantError: nil, - wantTBB: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloatPtr(1.0), SellBaseAssetCapInQuoteUnits: createFloatPtr(1.0)}, + otbBaseCap: 0.0, + otbQuoteCap: 0.0, + tbbBaseCap: 0.0, + tbbQuoteCap: 0.0, + price: "2.0", + inputAmount: "100.0", + wantAmount: "0.5000000", + wantError: nil, + wantTbbBaseCap: 0.5, + wantTbbQuoteCap: 1.0, }, { - name: "success - selling, base and quote units sell cap, keep selling base and quote", + name: "selling, base and quote units sell cap, keep selling base and quote", filter: &volumeFilter{ name: "volumeFilter", configValue: "", baseAsset: testNativeAsset, quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloatPtr(1.0), SellBaseAssetCapInQuoteUnits: createFloatPtr(1.0), mode: volumeFilterModeExact}, + config: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), SellBaseAssetCapInQuoteUnits: pointy.Float64(1.0), mode: volumeFilterModeExact}, dailyVolumeByDateQuery: dailyVolumeByDateQuery, }, - dailyOTB: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: createFloatPtr(0.0), - SellBaseAssetCapInQuoteUnits: createFloatPtr(0.0), - }, - dailyTBB: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: createFloatPtr(0.0), - SellBaseAssetCapInQuoteUnits: createFloatPtr(0.0), - }, - op: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "100.0"}, - wantOp: &txnbuild.ManageSellOffer{Buying: txnbuild.NativeAsset{}, Selling: txnbuild.NativeAsset{}, Price: "1.0", Amount: "1.0000000"}, - wantError: nil, - wantTBB: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: createFloatPtr(1.0), SellBaseAssetCapInQuoteUnits: createFloatPtr(1.0)}, + otbBaseCap: 0.0, + otbQuoteCap: 0.0, + tbbBaseCap: 0.0, + tbbQuoteCap: 0.0, + price: "2.0", + inputAmount: "100.0", + wantAmount: "0.5000000", + wantError: nil, + wantTbbBaseCap: 0.5, + wantTbbQuoteCap: 1.0, }, } for _, k := range testCases { t.Run(k.name, func(t *testing.T) { - tbb := k.dailyTBB - actual, e := k.filter.volumeFilterFn(k.dailyOTB, tbb, k.op) + dailyOTB := makeTestVolumeFilterConfig(k.otbBaseCap, k.otbQuoteCap) + dailyTBB := makeTestVolumeFilterConfig(k.tbbBaseCap, k.tbbQuoteCap) + wantTBB := makeTestVolumeFilterConfig(k.wantTbbBaseCap, k.wantTbbQuoteCap) + op := makeManageSellOffer(k.price, k.inputAmount) + wantOp := makeManageSellOffer(k.price, k.wantAmount) + + actual, e := k.filter.volumeFilterFn(dailyOTB, dailyTBB, op) assert.Equal(t, k.wantError, e) - assert.Equal(t, k.wantOp, actual) - assert.Equal(t, k.wantTBB, tbb) + assert.Equal(t, wantOp, actual) + assert.Equal(t, wantTBB, dailyTBB) }) } } - -func createFloatPtr(x float64) *float64 { - return &x -} diff --git a/support/utils/functions.go b/support/utils/functions.go index 1f673948f..7edc8c87b 100644 --- a/support/utils/functions.go +++ b/support/utils/functions.go @@ -302,6 +302,7 @@ func assetEqualsExact(hAsset hProtocol.Asset, xAsset txnbuild.Asset) (bool, erro } // IsSelling helper method +// TODO DS Add tests for the various possible errors. func IsSelling(sdexBase hProtocol.Asset, sdexQuote hProtocol.Asset, selling txnbuild.Asset, buying txnbuild.Asset) (bool, error) { sellingBase, e := assetEqualsExact(sdexBase, selling) if e != nil { From 70c56c32bcb77aed2dfdfdd3a1d9c65af2a316b6 Mon Sep 17 00:00:00 2001 From: Debnil Sur Date: Wed, 28 Oct 2020 14:01:46 -0700 Subject: [PATCH 06/14] Change test interface. --- plugins/volumeFilter.go | 26 +- plugins/volumeFilter_test.go | 555 ++++++++++++----------------------- 2 files changed, 204 insertions(+), 377 deletions(-) diff --git a/plugins/volumeFilter.go b/plugins/volumeFilter.go index 5b8427122..e6da19b50 100644 --- a/plugins/volumeFilter.go +++ b/plugins/volumeFilter.go @@ -138,7 +138,7 @@ func (f *volumeFilter) Apply(ops []txnbuild.Operation, sellingOffers []hProtocol } innerFn := func(op *txnbuild.ManageSellOffer) (*txnbuild.ManageSellOffer, error) { - return f.volumeFilterFn(dailyOTB, dailyTBB, op) + return volumeFilterFn(dailyOTB, dailyTBB, op, f.baseAsset, f.quoteAsset, f.config.SellBaseAssetCapInBaseUnits, f.config.SellBaseAssetCapInQuoteUnits, f.config.mode) } ops, e = filterOps(f.name, f.baseAsset, f.quoteAsset, sellingOffers, buyingOffers, ops, innerFn) if e != nil { @@ -147,8 +147,8 @@ func (f *volumeFilter) Apply(ops []txnbuild.Operation, sellingOffers []hProtocol return ops, nil } -func (f *volumeFilter) volumeFilterFn(dailyOTB *VolumeFilterConfig, dailyTBB *VolumeFilterConfig, op *txnbuild.ManageSellOffer) (*txnbuild.ManageSellOffer, error) { - isSell, e := utils.IsSelling(f.baseAsset, f.quoteAsset, op.Selling, op.Buying) +func volumeFilterFn(dailyOTB *VolumeFilterConfig, dailyTBB *VolumeFilterConfig, op *txnbuild.ManageSellOffer, baseAsset, quoteAsset hProtocol.Asset, sellBaseAssetCapInBaseUnits, sellBaseAssetCapInQuoteUnits *float64, mode volumeFilterMode) (*txnbuild.ManageSellOffer, error) { + isSell, e := utils.IsSelling(baseAsset, quoteAsset, op.Selling, op.Buying) if e != nil { return nil, fmt.Errorf("error when running the isSelling check for offer '%+v': %s", *op, e) } @@ -168,12 +168,12 @@ func (f *volumeFilter) volumeFilterFn(dailyOTB *VolumeFilterConfig, dailyTBB *Vo newAmountBeingSold := amountValueUnitsBeingSold var keepSellingBase bool var keepSellingQuote bool - if f.config.SellBaseAssetCapInBaseUnits != nil { + if sellBaseAssetCapInBaseUnits != nil { projectedSoldInBaseUnits := *dailyOTB.SellBaseAssetCapInBaseUnits + *dailyTBB.SellBaseAssetCapInBaseUnits + amountValueUnitsBeingSold - keepSellingBase = projectedSoldInBaseUnits <= *f.config.SellBaseAssetCapInBaseUnits + keepSellingBase = projectedSoldInBaseUnits <= *sellBaseAssetCapInBaseUnits newAmountString := "" - if f.config.mode == volumeFilterModeExact && !keepSellingBase { - newAmount := *f.config.SellBaseAssetCapInBaseUnits - *dailyOTB.SellBaseAssetCapInBaseUnits - *dailyTBB.SellBaseAssetCapInBaseUnits + if mode == volumeFilterModeExact && !keepSellingBase { + newAmount := *sellBaseAssetCapInBaseUnits - *dailyOTB.SellBaseAssetCapInBaseUnits - *dailyTBB.SellBaseAssetCapInBaseUnits if newAmount > 0 { newAmountBeingSold = newAmount opToReturn.Amount = fmt.Sprintf("%.7f", newAmountBeingSold) @@ -181,17 +181,17 @@ func (f *volumeFilter) volumeFilterFn(dailyOTB *VolumeFilterConfig, dailyTBB *Vo newAmountString = ", newAmountString = " + opToReturn.Amount } } - log.Printf("volumeFilter: selling (base units), price=%.8f amount=%.8f, keep = (projectedSoldInBaseUnits) %.7f <= %.7f (config.SellBaseAssetCapInBaseUnits): keepSellingBase = %v%s", sellPrice, amountValueUnitsBeingSold, projectedSoldInBaseUnits, *f.config.SellBaseAssetCapInBaseUnits, keepSellingBase, newAmountString) + log.Printf("volumeFilter: selling (base units), price=%.8f amount=%.8f, keep = (projectedSoldInBaseUnits) %.7f <= %.7f (config.SellBaseAssetCapInBaseUnits): keepSellingBase = %v%s", sellPrice, amountValueUnitsBeingSold, projectedSoldInBaseUnits, *sellBaseAssetCapInBaseUnits, keepSellingBase, newAmountString) } else { keepSellingBase = true } - if f.config.SellBaseAssetCapInQuoteUnits != nil { + if sellBaseAssetCapInQuoteUnits != nil { projectedSoldInQuoteUnits := *dailyOTB.SellBaseAssetCapInQuoteUnits + *dailyTBB.SellBaseAssetCapInQuoteUnits + (newAmountBeingSold * sellPrice) - keepSellingQuote = projectedSoldInQuoteUnits <= *f.config.SellBaseAssetCapInQuoteUnits + keepSellingQuote = projectedSoldInQuoteUnits <= *sellBaseAssetCapInQuoteUnits newAmountString := "" - if f.config.mode == volumeFilterModeExact && !keepSellingQuote { - newAmount := (*f.config.SellBaseAssetCapInQuoteUnits - *dailyOTB.SellBaseAssetCapInQuoteUnits - *dailyTBB.SellBaseAssetCapInQuoteUnits) / sellPrice + if mode == volumeFilterModeExact && !keepSellingQuote { + newAmount := (*sellBaseAssetCapInQuoteUnits - *dailyOTB.SellBaseAssetCapInQuoteUnits - *dailyTBB.SellBaseAssetCapInQuoteUnits) / sellPrice if newAmount > 0 { newAmountBeingSold = newAmount opToReturn.Amount = fmt.Sprintf("%.7f", newAmountBeingSold) @@ -199,7 +199,7 @@ func (f *volumeFilter) volumeFilterFn(dailyOTB *VolumeFilterConfig, dailyTBB *Vo newAmountString = ", newAmountString = " + opToReturn.Amount } } - log.Printf("volumeFilter: selling (quote units), price=%.8f amount=%.8f, keep = (projectedSoldInQuoteUnits) %.7f <= %.7f (config.SellBaseAssetCapInQuoteUnits): keepSellingQuote = %v%s", sellPrice, amountValueUnitsBeingSold, projectedSoldInQuoteUnits, *f.config.SellBaseAssetCapInQuoteUnits, keepSellingQuote, newAmountString) + log.Printf("volumeFilter: selling (quote units), price=%.8f amount=%.8f, keep = (projectedSoldInQuoteUnits) %.7f <= %.7f (config.SellBaseAssetCapInQuoteUnits): keepSellingQuote = %v%s", sellPrice, amountValueUnitsBeingSold, projectedSoldInQuoteUnits, *sellBaseAssetCapInQuoteUnits, keepSellingQuote, newAmountString) } else { keepSellingQuote = true } diff --git a/plugins/volumeFilter_test.go b/plugins/volumeFilter_test.go index e5a5a4a3a..3981b31b4 100644 --- a/plugins/volumeFilter_test.go +++ b/plugins/volumeFilter_test.go @@ -29,249 +29,139 @@ func mustMakeTestDailyVolumeQuery(optionalAccountIDs, additionalMarketIDs []stri return query } +func makeTestVolumeFilterConfig(baseCapInBase, baseCapInQuote float64, additionalMarketIDs, optionalAccountIDs []string, mode volumeFilterMode) *VolumeFilterConfig { + var baseCapInBasePtr *float64 + if baseCapInBase >= 0 { + baseCapInBasePtr = pointy.Float64(baseCapInBase) + } + + var baseCapInQuotePtr *float64 + if baseCapInQuote >= 0 { + baseCapInQuotePtr = pointy.Float64(baseCapInQuote) + } + + return &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: baseCapInBasePtr, + SellBaseAssetCapInQuoteUnits: baseCapInQuotePtr, + mode: mode, + additionalMarketIDs: additionalMarketIDs, + optionalAccountIDs: optionalAccountIDs, + } +} + +func makeTestVolumeFilter(baseCapInBase, baseCapInQuote float64, additionalMarketIDs, optionalAccountIDs []string, mode volumeFilterMode) *volumeFilter { + config := makeTestVolumeFilterConfig(baseCapInBase, baseCapInQuote, additionalMarketIDs, optionalAccountIDs, mode) + query := mustMakeTestDailyVolumeQuery(optionalAccountIDs, additionalMarketIDs) + + return &volumeFilter{ + name: "volumeFilter", + baseAsset: testNativeAsset, + quoteAsset: testNativeAsset, + config: config, + dailyVolumeByDateQuery: query, + } +} + func TestMakeFilterVolume(t *testing.T) { testAssetDisplayFn := model.MakeSdexMappedAssetDisplayFn(map[model.Asset]hProtocol.Asset{model.Asset("XLM"): testNativeAsset}) testCases := []struct { name string - assetDisplayFn model.AssetDisplayFn config *VolumeFilterConfig - - wantError error - wantSubmitFilter SubmitFilter + baseCapInBase float64 + baseCapInQuote float64 + marketIDs []string + accountIDs []string + mode volumeFilterMode }{ // TODO DS Confirm the empty config fails once validation is added to the constructor { - name: "empty config", - config: &VolumeFilterConfig{}, - wantError: nil, - wantSubmitFilter: &volumeFilter{ - name: "volumeFilter", - baseAsset: testNativeAsset, - quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{}, - dailyVolumeByDateQuery: mustMakeTestDailyVolumeQuery([]string{}, []string{}), - }, + name: "empty config", + baseCapInBase: -1., + baseCapInQuote: -1., + marketIDs: []string{}, + accountIDs: []string{}, + mode: volumeFilterModeExact, }, { - name: "non nil cap in base, nil cap in quote", - config: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), - mode: volumeFilterModeExact, - additionalMarketIDs: []string{}, - optionalAccountIDs: []string{}, - }, - wantError: nil, - wantSubmitFilter: &volumeFilter{ - name: "volumeFilter", - baseAsset: testNativeAsset, - quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), - mode: volumeFilterModeExact, - additionalMarketIDs: []string{}, - optionalAccountIDs: []string{}, - }, - dailyVolumeByDateQuery: mustMakeTestDailyVolumeQuery([]string{}, []string{}), - }, + name: "non nil cap in base, nil cap in quote", + baseCapInBase: 1.0, + baseCapInQuote: -1.0, + marketIDs: []string{}, + accountIDs: []string{}, + mode: volumeFilterModeExact, }, { - name: "nil cap in base, non nil cap in quote", - config: &VolumeFilterConfig{ - SellBaseAssetCapInQuoteUnits: pointy.Float64(1.0), - mode: volumeFilterModeExact, - additionalMarketIDs: []string{}, - optionalAccountIDs: []string{}, - }, - wantError: nil, - wantSubmitFilter: &volumeFilter{ - name: "volumeFilter", - baseAsset: testNativeAsset, - quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{ - SellBaseAssetCapInQuoteUnits: pointy.Float64(1.0), - mode: volumeFilterModeExact, - additionalMarketIDs: []string{}, - optionalAccountIDs: []string{}, - }, - dailyVolumeByDateQuery: mustMakeTestDailyVolumeQuery([]string{}, []string{}), - }, + name: "nil cap in base, non nil cap in quote", + baseCapInBase: -1.0, + baseCapInQuote: 1.0, + marketIDs: []string{}, + accountIDs: []string{}, + mode: volumeFilterModeExact, }, { - name: "exact mode", - config: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), - mode: volumeFilterModeExact, - additionalMarketIDs: []string{}, - optionalAccountIDs: []string{}, - }, - wantError: nil, - wantSubmitFilter: &volumeFilter{ - name: "volumeFilter", - baseAsset: testNativeAsset, - quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), - mode: volumeFilterModeExact, - additionalMarketIDs: []string{}, - optionalAccountIDs: []string{}, - }, - dailyVolumeByDateQuery: mustMakeTestDailyVolumeQuery([]string{}, []string{}), - }, + name: "exact mode", + baseCapInBase: 1.0, + baseCapInQuote: -1.0, + marketIDs: []string{}, + accountIDs: []string{}, + mode: volumeFilterModeExact, }, { - name: "ignore mode", - config: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), - mode: volumeFilterModeIgnore, - additionalMarketIDs: []string{}, - optionalAccountIDs: []string{}, - }, - wantError: nil, - wantSubmitFilter: &volumeFilter{ - name: "volumeFilter", - baseAsset: testNativeAsset, - quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), - mode: volumeFilterModeIgnore, - additionalMarketIDs: []string{}, - optionalAccountIDs: []string{}, - }, - dailyVolumeByDateQuery: mustMakeTestDailyVolumeQuery([]string{}, []string{}), - }, + name: "ignore mode", + baseCapInBase: 1.0, + baseCapInQuote: -1.0, + marketIDs: []string{}, + accountIDs: []string{}, + mode: volumeFilterModeIgnore, }, { - name: "1 market id", - config: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), - mode: volumeFilterModeIgnore, - additionalMarketIDs: []string{"marketID"}, - optionalAccountIDs: []string{}, - }, - wantError: nil, - wantSubmitFilter: &volumeFilter{ - name: "volumeFilter", - baseAsset: testNativeAsset, - quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), - mode: volumeFilterModeIgnore, - additionalMarketIDs: []string{"marketID"}, - optionalAccountIDs: []string{}, - }, - dailyVolumeByDateQuery: mustMakeTestDailyVolumeQuery([]string{}, []string{"marketID"}), - }, + name: "1 market id", + baseCapInBase: 1.0, + baseCapInQuote: -1.0, + marketIDs: []string{"marketID"}, + accountIDs: []string{}, + mode: volumeFilterModeExact, }, { - name: "2 market ids", - config: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), - mode: volumeFilterModeIgnore, - additionalMarketIDs: []string{"marketID1", "marketID2"}, - optionalAccountIDs: []string{}, - }, - wantError: nil, - wantSubmitFilter: &volumeFilter{ - name: "volumeFilter", - baseAsset: testNativeAsset, - quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), - mode: volumeFilterModeIgnore, - additionalMarketIDs: []string{"marketID1", "marketID2"}, - optionalAccountIDs: []string{}, - }, - dailyVolumeByDateQuery: mustMakeTestDailyVolumeQuery([]string{}, []string{"marketID1", "marketID2"}), - }, + name: "2 market ids", + baseCapInBase: 1.0, + baseCapInQuote: -1.0, + marketIDs: []string{"marketID1", "marketID2"}, + accountIDs: []string{}, + mode: volumeFilterModeExact, }, { - name: "2 dupe market ids, 1 distinct", - config: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), - mode: volumeFilterModeIgnore, - additionalMarketIDs: []string{"marketID1", "marketID1", "marketID2"}, - optionalAccountIDs: []string{}, - }, - wantError: nil, - wantSubmitFilter: &volumeFilter{ - name: "volumeFilter", - baseAsset: testNativeAsset, - quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), - mode: volumeFilterModeIgnore, - additionalMarketIDs: []string{"marketID1", "marketID1", "marketID2"}, - optionalAccountIDs: []string{}, - }, - dailyVolumeByDateQuery: mustMakeTestDailyVolumeQuery([]string{}, []string{"marketID1", "marketID1", "marketID2"}), - }, + name: "2 dupe market ids, 1 distinct", + baseCapInBase: 1.0, + baseCapInQuote: -1.0, + marketIDs: []string{"marketID1", "marketID1", "marketID2"}, + accountIDs: []string{}, + mode: volumeFilterModeExact, }, { - name: "1 account id", - config: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), - mode: volumeFilterModeIgnore, - additionalMarketIDs: []string{}, - optionalAccountIDs: []string{"accountID"}, - }, - wantError: nil, - wantSubmitFilter: &volumeFilter{ - name: "volumeFilter", - baseAsset: testNativeAsset, - quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), - mode: volumeFilterModeIgnore, - additionalMarketIDs: []string{}, - optionalAccountIDs: []string{"accountID"}, - }, - dailyVolumeByDateQuery: mustMakeTestDailyVolumeQuery([]string{"accountID"}, []string{}), - }, + name: "1 account id", + baseCapInBase: 1.0, + baseCapInQuote: -1.0, + marketIDs: []string{}, + accountIDs: []string{"accountID"}, + mode: volumeFilterModeExact, }, { - name: "2 account ids", - config: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), - mode: volumeFilterModeIgnore, - additionalMarketIDs: []string{}, - optionalAccountIDs: []string{"accountID1", "accountID2"}, - }, - wantError: nil, - wantSubmitFilter: &volumeFilter{ - name: "volumeFilter", - baseAsset: testNativeAsset, - quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), - mode: volumeFilterModeIgnore, - additionalMarketIDs: []string{}, - optionalAccountIDs: []string{"accountID1", "accountID2"}, - }, - dailyVolumeByDateQuery: mustMakeTestDailyVolumeQuery([]string{"accountID1", "accountID2"}, []string{}), - }, + name: "2 account ids", + baseCapInBase: 1.0, + baseCapInQuote: -1.0, + marketIDs: []string{}, + accountIDs: []string{"accountID1", "accountID2"}, + mode: volumeFilterModeExact, }, { - name: "account and market ids", - config: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), - mode: volumeFilterModeIgnore, - additionalMarketIDs: []string{"marketID"}, - optionalAccountIDs: []string{"accountID"}, - }, - wantError: nil, - wantSubmitFilter: &volumeFilter{ - name: "volumeFilter", - baseAsset: testNativeAsset, - quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), - mode: volumeFilterModeIgnore, - additionalMarketIDs: []string{"marketID"}, - optionalAccountIDs: []string{"accountID"}, - }, - dailyVolumeByDateQuery: mustMakeTestDailyVolumeQuery([]string{"accountID"}, []string{"marketID"}), - }, + name: "account and market ids", + baseCapInBase: 1.0, + baseCapInQuote: -1.0, + marketIDs: []string{"marketID"}, + accountIDs: []string{"accountID"}, + mode: volumeFilterModeExact, }, } @@ -280,6 +170,8 @@ func TestMakeFilterVolume(t *testing.T) { tradingPair := &model.TradingPair{Base: "XLM", Quote: "XLM"} for _, k := range testCases { + config := makeTestVolumeFilterConfig(k.baseCapInBase, k.baseCapInQuote, k.marketIDs, k.accountIDs, k.mode) + wantFilter := makeTestVolumeFilter(k.baseCapInBase, k.baseCapInQuote, k.marketIDs, k.accountIDs, k.mode) t.Run(k.name, func(t *testing.T) { actual, e := makeFilterVolume( configValue, @@ -289,11 +181,11 @@ func TestMakeFilterVolume(t *testing.T) { testNativeAsset, testNativeAsset, &sql.DB{}, - k.config, + config, ) - assert.Equal(t, k.wantError, e) - assert.Equal(t, k.wantSubmitFilter, actual) + assert.Nil(t, e) + assert.Equal(t, wantFilter, actual) }) } } @@ -311,173 +203,108 @@ func makeManageSellOffer(price, amount string) *txnbuild.ManageSellOffer { } } -func makeTestVolumeFilterConfig(baseCap, quoteCap float64) *VolumeFilterConfig { - return &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: pointy.Float64(baseCap), - SellBaseAssetCapInQuoteUnits: pointy.Float64(quoteCap), - mode: volumeFilterModeExact, - additionalMarketIDs: []string{}, - optionalAccountIDs: []string{}, - } -} - func TestVolumeFilterFn(t *testing.T) { - dailyVolumeByDateQuery := mustMakeTestDailyVolumeQuery([]string{}, []string{}) - - emptyFilter := &volumeFilter{ - name: "volumeFilter", - configValue: "", - baseAsset: testNativeAsset, - quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{}, - dailyVolumeByDateQuery: dailyVolumeByDateQuery, - } - testCases := []struct { - name string - filter *volumeFilter - otbBaseCap float64 - otbQuoteCap float64 - tbbBaseCap float64 - tbbQuoteCap float64 - price string - inputAmount string - wantAmount string - wantError error - wantTbbBaseCap float64 - wantTbbQuoteCap float64 + name string + filter *volumeFilter + sellBaseCapInBase *float64 + sellBaseCapInQuote *float64 + otbBaseCap float64 + otbQuoteCap float64 + tbbBaseCap float64 + tbbQuoteCap float64 + price string + inputAmount string + wantAmount string + wantTbbBaseCap float64 + wantTbbQuoteCap float64 }{ { - name: "selling, no filter sell caps", - filter: emptyFilter, - otbBaseCap: 0.0, - otbQuoteCap: 0.0, - tbbBaseCap: 0.0, - tbbQuoteCap: 0.0, - price: "2.0", - inputAmount: "100.0", - wantAmount: "100.0", - wantError: nil, - wantTbbBaseCap: 100.0, - wantTbbQuoteCap: 200.0, + name: "selling, base units sell cap, don't keep selling base", + sellBaseCapInBase: pointy.Float64(0.0), + sellBaseCapInQuote: nil, + otbBaseCap: 0.0, + otbQuoteCap: 0.0, + tbbBaseCap: 0.0, + tbbQuoteCap: 0.0, + price: "2.0", + inputAmount: "100.0", + wantAmount: "", + wantTbbBaseCap: 0.0, + wantTbbQuoteCap: 0.0, }, { - name: "selling, base units sell cap, don't keep selling base", - filter: &volumeFilter{ - name: "volumeFilter", - configValue: "", - baseAsset: testNativeAsset, - quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: pointy.Float64(0.0)}, - dailyVolumeByDateQuery: dailyVolumeByDateQuery, - }, - otbBaseCap: 0.0, - otbQuoteCap: 0.0, - tbbBaseCap: 0.0, - tbbQuoteCap: 0.0, - price: "2.0", - inputAmount: "100.0", - wantAmount: "", - wantError: nil, - wantTbbBaseCap: 0.0, - wantTbbQuoteCap: 0.0, + name: "selling, base units sell cap, keep selling base", + sellBaseCapInBase: pointy.Float64(1.0), + sellBaseCapInQuote: nil, + otbBaseCap: 0.0, + otbQuoteCap: 0.0, + tbbBaseCap: 0.0, + tbbQuoteCap: 0.0, + price: "2.0", + inputAmount: "100.0", + wantAmount: "1.0000000", + wantTbbBaseCap: 1.0, + wantTbbQuoteCap: 2.0, }, { - name: "selling, base units sell cap, keep selling base", - filter: &volumeFilter{ - name: "volumeFilter", - configValue: "", - baseAsset: testNativeAsset, - quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), mode: volumeFilterModeExact}, - dailyVolumeByDateQuery: dailyVolumeByDateQuery, - }, - otbBaseCap: 0.0, - otbQuoteCap: 0.0, - tbbBaseCap: 0.0, - tbbQuoteCap: 0.0, - price: "2.0", - inputAmount: "100.0", - wantAmount: "1.0000000", - wantError: nil, - wantTbbBaseCap: 1.0, - wantTbbQuoteCap: 2.0, + name: "selling, quote units sell cap, don't keep selling quote", + sellBaseCapInBase: nil, + sellBaseCapInQuote: pointy.Float64(0), + otbBaseCap: 0.0, + otbQuoteCap: 0.0, + tbbBaseCap: 0.0, + tbbQuoteCap: 0.0, + price: "2.0", + inputAmount: "100.0", + wantAmount: "", + wantTbbBaseCap: 0.0, + wantTbbQuoteCap: 0.0, }, { - name: "selling, quote units sell cap, don't keep selling quote", - filter: &volumeFilter{ - name: "volumeFilter", - configValue: "", - baseAsset: testNativeAsset, - quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{SellBaseAssetCapInQuoteUnits: pointy.Float64(0.0)}, - dailyVolumeByDateQuery: dailyVolumeByDateQuery, - }, - otbBaseCap: 0.0, - otbQuoteCap: 0.0, - tbbBaseCap: 0.0, - tbbQuoteCap: 0.0, - price: "2.0", - inputAmount: "100.0", - wantAmount: "", - wantError: nil, - wantTbbBaseCap: 0.0, - wantTbbQuoteCap: 0.0, + name: "selling, quote units sell cap, keep selling quote", + sellBaseCapInBase: nil, + sellBaseCapInQuote: pointy.Float64(1.), + otbBaseCap: 0.0, + otbQuoteCap: 0.0, + tbbBaseCap: 0.0, + tbbQuoteCap: 0.0, + price: "2.0", + inputAmount: "100.0", + wantAmount: "0.5000000", + wantTbbBaseCap: 0.5, + wantTbbQuoteCap: 1.0, }, { - name: "selling, quote units sell cap, keep selling quote", - filter: &volumeFilter{ - name: "volumeFilter", - configValue: "", - baseAsset: testNativeAsset, - quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{SellBaseAssetCapInQuoteUnits: pointy.Float64(1.0), mode: volumeFilterModeExact}, - dailyVolumeByDateQuery: dailyVolumeByDateQuery, - }, - otbBaseCap: 0.0, - otbQuoteCap: 0.0, - tbbBaseCap: 0.0, - tbbQuoteCap: 0.0, - price: "2.0", - inputAmount: "100.0", - wantAmount: "0.5000000", - wantError: nil, - wantTbbBaseCap: 0.5, - wantTbbQuoteCap: 1.0, - }, - { - name: "selling, base and quote units sell cap, keep selling base and quote", - filter: &volumeFilter{ - name: "volumeFilter", - configValue: "", - baseAsset: testNativeAsset, - quoteAsset: testNativeAsset, - config: &VolumeFilterConfig{SellBaseAssetCapInBaseUnits: pointy.Float64(1.0), SellBaseAssetCapInQuoteUnits: pointy.Float64(1.0), mode: volumeFilterModeExact}, - dailyVolumeByDateQuery: dailyVolumeByDateQuery, - }, - otbBaseCap: 0.0, - otbQuoteCap: 0.0, - tbbBaseCap: 0.0, - tbbQuoteCap: 0.0, - price: "2.0", - inputAmount: "100.0", - wantAmount: "0.5000000", - wantError: nil, - wantTbbBaseCap: 0.5, - wantTbbQuoteCap: 1.0, + name: "selling, base and quote units sell cap, keep selling base and quote", + sellBaseCapInBase: pointy.Float64(1.), + sellBaseCapInQuote: pointy.Float64(1.), + otbBaseCap: 0.0, + otbQuoteCap: 0.0, + tbbBaseCap: 0.0, + tbbQuoteCap: 0.0, + price: "2.0", + inputAmount: "100.0", + wantAmount: "0.5000000", + wantTbbBaseCap: 0.5, + wantTbbQuoteCap: 1.0, }, } for _, k := range testCases { t.Run(k.name, func(t *testing.T) { - dailyOTB := makeTestVolumeFilterConfig(k.otbBaseCap, k.otbQuoteCap) - dailyTBB := makeTestVolumeFilterConfig(k.tbbBaseCap, k.tbbQuoteCap) - wantTBB := makeTestVolumeFilterConfig(k.wantTbbBaseCap, k.wantTbbQuoteCap) + marketIDs := []string{} + accountIDs := []string{} + mode := volumeFilterModeExact + dailyOTB := makeTestVolumeFilterConfig(k.otbBaseCap, k.otbQuoteCap, marketIDs, accountIDs, mode) + dailyTBB := makeTestVolumeFilterConfig(k.tbbBaseCap, k.tbbQuoteCap, marketIDs, accountIDs, mode) + wantTBB := makeTestVolumeFilterConfig(k.wantTbbBaseCap, k.wantTbbQuoteCap, marketIDs, accountIDs, mode) op := makeManageSellOffer(k.price, k.inputAmount) wantOp := makeManageSellOffer(k.price, k.wantAmount) - actual, e := k.filter.volumeFilterFn(dailyOTB, dailyTBB, op) - assert.Equal(t, k.wantError, e) + actual, e := volumeFilterFn(dailyOTB, dailyTBB, op, testNativeAsset, testNativeAsset, k.sellBaseCapInBase, k.sellBaseCapInQuote, volumeFilterModeExact) + + assert.Nil(t, e) assert.Equal(t, wantOp, actual) assert.Equal(t, wantTBB, dailyTBB) }) From 4069820478605c72a1676ac497e3ece716d4954e Mon Sep 17 00:00:00 2001 From: Debnil Sur Date: Wed, 28 Oct 2020 14:39:26 -0700 Subject: [PATCH 07/14] Address review 2 - nikhilsaraf --- plugins/volumeFilter.go | 2 +- plugins/volumeFilter_test.go | 184 ++++++++++++----------------------- 2 files changed, 65 insertions(+), 121 deletions(-) diff --git a/plugins/volumeFilter.go b/plugins/volumeFilter.go index e6da19b50..72f0d3df6 100644 --- a/plugins/volumeFilter.go +++ b/plugins/volumeFilter.go @@ -78,7 +78,7 @@ func makeFilterVolume( marketIDs := utils.Dedupe(append([]string{marketID}, config.additionalMarketIDs...)) dailyVolumeByDateQuery, e := queries.MakeDailyVolumeByDateForMarketIdsAction(db, marketIDs, "sell", config.optionalAccountIDs) if e != nil { - return nil, fmt.Errorf("could not make daily volume by date action: %s", e) + return nil, fmt.Errorf("could not make daily volume by date Query: %s", e) } // TODO DS Validate the config, to have exactly one asset cap defined; a valid mode; non-nil market IDs; and non-nil optional account IDs. diff --git a/plugins/volumeFilter_test.go b/plugins/volumeFilter_test.go index 3981b31b4..6e6b688cf 100644 --- a/plugins/volumeFilter_test.go +++ b/plugins/volumeFilter_test.go @@ -2,6 +2,7 @@ package plugins import ( "database/sql" + "fmt" "testing" "github.com/openlyinc/pointy" @@ -15,20 +16,6 @@ import ( "github.com/stretchr/testify/assert" ) -var testNativeAsset hProtocol.Asset = hProtocol.Asset{Type: "native"} - -func mustMakeTestDailyVolumeQuery(optionalAccountIDs, additionalMarketIDs []string) *queries.DailyVolumeByDate { - marketID := MakeMarketID("", "native", "native") - marketIDs := utils.Dedupe(append([]string{marketID}, additionalMarketIDs...)) - - query, e := queries.MakeDailyVolumeByDateForMarketIdsAction(&sql.DB{}, marketIDs, "sell", optionalAccountIDs) - if e != nil { - panic(e) - } - - return query -} - func makeTestVolumeFilterConfig(baseCapInBase, baseCapInQuote float64, additionalMarketIDs, optionalAccountIDs []string, mode volumeFilterMode) *VolumeFilterConfig { var baseCapInBasePtr *float64 if baseCapInBase >= 0 { @@ -49,144 +36,101 @@ func makeTestVolumeFilterConfig(baseCapInBase, baseCapInQuote float64, additiona } } -func makeTestVolumeFilter(baseCapInBase, baseCapInQuote float64, additionalMarketIDs, optionalAccountIDs []string, mode volumeFilterMode) *volumeFilter { - config := makeTestVolumeFilterConfig(baseCapInBase, baseCapInQuote, additionalMarketIDs, optionalAccountIDs, mode) - query := mustMakeTestDailyVolumeQuery(optionalAccountIDs, additionalMarketIDs) +func makeTestVolumeFilter(config *VolumeFilterConfig, additionalMarketIDs, optionalAccountIDs []string) *volumeFilter { + marketID := MakeMarketID("", "native", "native") + marketIDs := utils.Dedupe(append([]string{marketID}, additionalMarketIDs...)) + + query, e := queries.MakeDailyVolumeByDateForMarketIdsAction(&sql.DB{}, marketIDs, "sell", optionalAccountIDs) + if e != nil { + panic(e) + } return &volumeFilter{ name: "volumeFilter", - baseAsset: testNativeAsset, - quoteAsset: testNativeAsset, + baseAsset: utils.NativeAsset, + quoteAsset: utils.NativeAsset, config: config, dailyVolumeByDateQuery: query, } } func TestMakeFilterVolume(t *testing.T) { - testAssetDisplayFn := model.MakeSdexMappedAssetDisplayFn(map[model.Asset]hProtocol.Asset{model.Asset("XLM"): testNativeAsset}) + testAssetDisplayFn := model.MakeSdexMappedAssetDisplayFn(map[model.Asset]hProtocol.Asset{model.Asset("XLM"): utils.NativeAsset}) testCases := []struct { - name string - config *VolumeFilterConfig - baseCapInBase float64 - baseCapInQuote float64 - marketIDs []string - accountIDs []string - mode volumeFilterMode + name string + marketIDs []string + accountIDs []string }{ // TODO DS Confirm the empty config fails once validation is added to the constructor { - name: "empty config", - baseCapInBase: -1., - baseCapInQuote: -1., - marketIDs: []string{}, - accountIDs: []string{}, - mode: volumeFilterModeExact, - }, - { - name: "non nil cap in base, nil cap in quote", - baseCapInBase: 1.0, - baseCapInQuote: -1.0, - marketIDs: []string{}, - accountIDs: []string{}, - mode: volumeFilterModeExact, - }, - { - name: "nil cap in base, non nil cap in quote", - baseCapInBase: -1.0, - baseCapInQuote: 1.0, - marketIDs: []string{}, - accountIDs: []string{}, - mode: volumeFilterModeExact, - }, - { - name: "exact mode", - baseCapInBase: 1.0, - baseCapInQuote: -1.0, - marketIDs: []string{}, - accountIDs: []string{}, - mode: volumeFilterModeExact, - }, - { - name: "ignore mode", - baseCapInBase: 1.0, - baseCapInQuote: -1.0, - marketIDs: []string{}, - accountIDs: []string{}, - mode: volumeFilterModeIgnore, - }, - { - name: "1 market id", - baseCapInBase: 1.0, - baseCapInQuote: -1.0, - marketIDs: []string{"marketID"}, - accountIDs: []string{}, - mode: volumeFilterModeExact, + name: "1 market id", + marketIDs: []string{"marketID"}, + accountIDs: []string{}, }, { - name: "2 market ids", - baseCapInBase: 1.0, - baseCapInQuote: -1.0, - marketIDs: []string{"marketID1", "marketID2"}, - accountIDs: []string{}, - mode: volumeFilterModeExact, + name: "2 market ids", + marketIDs: []string{"marketID1", "marketID2"}, + accountIDs: []string{}, }, { - name: "2 dupe market ids, 1 distinct", - baseCapInBase: 1.0, - baseCapInQuote: -1.0, - marketIDs: []string{"marketID1", "marketID1", "marketID2"}, - accountIDs: []string{}, - mode: volumeFilterModeExact, + name: "2 dupe market ids, 1 distinct", + marketIDs: []string{"marketID1", "marketID1", "marketID2"}, + accountIDs: []string{}, }, { - name: "1 account id", - baseCapInBase: 1.0, - baseCapInQuote: -1.0, - marketIDs: []string{}, - accountIDs: []string{"accountID"}, - mode: volumeFilterModeExact, + name: "1 account id", + marketIDs: []string{}, + accountIDs: []string{"accountID"}, }, { - name: "2 account ids", - baseCapInBase: 1.0, - baseCapInQuote: -1.0, - marketIDs: []string{}, - accountIDs: []string{"accountID1", "accountID2"}, - mode: volumeFilterModeExact, + name: "2 account ids", + marketIDs: []string{}, + accountIDs: []string{"accountID1", "accountID2"}, }, { - name: "account and market ids", - baseCapInBase: 1.0, - baseCapInQuote: -1.0, - marketIDs: []string{"marketID"}, - accountIDs: []string{"accountID"}, - mode: volumeFilterModeExact, + name: "account and market ids", + marketIDs: []string{"marketID"}, + accountIDs: []string{"accountID"}, }, } configValue := "" exchangeName := "" tradingPair := &model.TradingPair{Base: "XLM", Quote: "XLM"} + modes := []volumeFilterMode{volumeFilterModeExact, volumeFilterModeIgnore} for _, k := range testCases { - config := makeTestVolumeFilterConfig(k.baseCapInBase, k.baseCapInQuote, k.marketIDs, k.accountIDs, k.mode) - wantFilter := makeTestVolumeFilter(k.baseCapInBase, k.baseCapInQuote, k.marketIDs, k.accountIDs, k.mode) - t.Run(k.name, func(t *testing.T) { - actual, e := makeFilterVolume( - configValue, - exchangeName, - tradingPair, - testAssetDisplayFn, - testNativeAsset, - testNativeAsset, - &sql.DB{}, - config, - ) + for _, m := range modes { + baseCapInBaseConfig := makeTestVolumeFilterConfig(1.0, -1.0, k.marketIDs, k.accountIDs, m) + baseCapInQuoteConfig := makeTestVolumeFilterConfig(-1.0, 1.0, k.marketIDs, k.accountIDs, m) - assert.Nil(t, e) - assert.Equal(t, wantFilter, actual) - }) + for _, c := range []*VolumeFilterConfig{baseCapInBaseConfig, baseCapInQuoteConfig} { + var configType string + if c.SellBaseAssetCapInBaseUnits != nil { + configType = "base" + } else { + configType = "quote" + } + + wantFilter := makeTestVolumeFilter(c, k.marketIDs, k.accountIDs) + t.Run(fmt.Sprintf("%s/%s/%s", k.name, configType, m), func(t *testing.T) { + actual, e := makeFilterVolume( + configValue, + exchangeName, + tradingPair, + testAssetDisplayFn, + utils.NativeAsset, + utils.NativeAsset, + &sql.DB{}, + c, + ) + + assert.Nil(t, e) + assert.Equal(t, wantFilter, actual) + }) + } + } } } @@ -302,7 +246,7 @@ func TestVolumeFilterFn(t *testing.T) { op := makeManageSellOffer(k.price, k.inputAmount) wantOp := makeManageSellOffer(k.price, k.wantAmount) - actual, e := volumeFilterFn(dailyOTB, dailyTBB, op, testNativeAsset, testNativeAsset, k.sellBaseCapInBase, k.sellBaseCapInQuote, volumeFilterModeExact) + actual, e := volumeFilterFn(dailyOTB, dailyTBB, op, utils.NativeAsset, utils.NativeAsset, k.sellBaseCapInBase, k.sellBaseCapInQuote, volumeFilterModeExact) assert.Nil(t, e) assert.Equal(t, wantOp, actual) From 8baa8a90a3e7280c92d46654a638263ffe5e2a1a Mon Sep 17 00:00:00 2001 From: Debnil Sur Date: Thu, 29 Oct 2020 09:48:12 -0700 Subject: [PATCH 08/14] Modify volumeFilterFn parameters, change market ID query slice logic --- plugins/volumeFilter.go | 35 +++++++++++++++++++++++------------ plugins/volumeFilter_test.go | 31 +++++++++++++++++++++---------- 2 files changed, 44 insertions(+), 22 deletions(-) diff --git a/plugins/volumeFilter.go b/plugins/volumeFilter.go index 72f0d3df6..30fec468c 100644 --- a/plugins/volumeFilter.go +++ b/plugins/volumeFilter.go @@ -44,6 +44,12 @@ type VolumeFilterConfig struct { // buyBaseAssetCapInQuoteUnits *float64 } +type limitParameters struct { + sellBaseAssetCapInBaseUnits *float64 + sellBaseAssetCapInQuoteUnits *float64 + mode volumeFilterMode +} + type volumeFilter struct { name string configValue string @@ -138,7 +144,12 @@ func (f *volumeFilter) Apply(ops []txnbuild.Operation, sellingOffers []hProtocol } innerFn := func(op *txnbuild.ManageSellOffer) (*txnbuild.ManageSellOffer, error) { - return volumeFilterFn(dailyOTB, dailyTBB, op, f.baseAsset, f.quoteAsset, f.config.SellBaseAssetCapInBaseUnits, f.config.SellBaseAssetCapInQuoteUnits, f.config.mode) + limitParameters := limitParameters{ + sellBaseAssetCapInBaseUnits: f.config.SellBaseAssetCapInBaseUnits, + sellBaseAssetCapInQuoteUnits: f.config.SellBaseAssetCapInQuoteUnits, + mode: f.config.mode, + } + return volumeFilterFn(dailyOTB, dailyTBB, op, f.baseAsset, f.quoteAsset, limitParameters) } ops, e = filterOps(f.name, f.baseAsset, f.quoteAsset, sellingOffers, buyingOffers, ops, innerFn) if e != nil { @@ -147,7 +158,7 @@ func (f *volumeFilter) Apply(ops []txnbuild.Operation, sellingOffers []hProtocol return ops, nil } -func volumeFilterFn(dailyOTB *VolumeFilterConfig, dailyTBB *VolumeFilterConfig, op *txnbuild.ManageSellOffer, baseAsset, quoteAsset hProtocol.Asset, sellBaseAssetCapInBaseUnits, sellBaseAssetCapInQuoteUnits *float64, mode volumeFilterMode) (*txnbuild.ManageSellOffer, error) { +func volumeFilterFn(dailyOTB *VolumeFilterConfig, dailyTBB *VolumeFilterConfig, op *txnbuild.ManageSellOffer, baseAsset hProtocol.Asset, quoteAsset hProtocol.Asset, lp limitParameters) (*txnbuild.ManageSellOffer, error) { isSell, e := utils.IsSelling(baseAsset, quoteAsset, op.Selling, op.Buying) if e != nil { return nil, fmt.Errorf("error when running the isSelling check for offer '%+v': %s", *op, e) @@ -168,12 +179,12 @@ func volumeFilterFn(dailyOTB *VolumeFilterConfig, dailyTBB *VolumeFilterConfig, newAmountBeingSold := amountValueUnitsBeingSold var keepSellingBase bool var keepSellingQuote bool - if sellBaseAssetCapInBaseUnits != nil { + if lp.sellBaseAssetCapInBaseUnits != nil { projectedSoldInBaseUnits := *dailyOTB.SellBaseAssetCapInBaseUnits + *dailyTBB.SellBaseAssetCapInBaseUnits + amountValueUnitsBeingSold - keepSellingBase = projectedSoldInBaseUnits <= *sellBaseAssetCapInBaseUnits + keepSellingBase = projectedSoldInBaseUnits <= *lp.sellBaseAssetCapInBaseUnits newAmountString := "" - if mode == volumeFilterModeExact && !keepSellingBase { - newAmount := *sellBaseAssetCapInBaseUnits - *dailyOTB.SellBaseAssetCapInBaseUnits - *dailyTBB.SellBaseAssetCapInBaseUnits + if lp.mode == volumeFilterModeExact && !keepSellingBase { + newAmount := *lp.sellBaseAssetCapInBaseUnits - *dailyOTB.SellBaseAssetCapInBaseUnits - *dailyTBB.SellBaseAssetCapInBaseUnits if newAmount > 0 { newAmountBeingSold = newAmount opToReturn.Amount = fmt.Sprintf("%.7f", newAmountBeingSold) @@ -181,17 +192,17 @@ func volumeFilterFn(dailyOTB *VolumeFilterConfig, dailyTBB *VolumeFilterConfig, newAmountString = ", newAmountString = " + opToReturn.Amount } } - log.Printf("volumeFilter: selling (base units), price=%.8f amount=%.8f, keep = (projectedSoldInBaseUnits) %.7f <= %.7f (config.SellBaseAssetCapInBaseUnits): keepSellingBase = %v%s", sellPrice, amountValueUnitsBeingSold, projectedSoldInBaseUnits, *sellBaseAssetCapInBaseUnits, keepSellingBase, newAmountString) + log.Printf("volumeFilter: selling (base units), price=%.8f amount=%.8f, keep = (projectedSoldInBaseUnits) %.7f <= %.7f (config.SellBaseAssetCapInBaseUnits): keepSellingBase = %v%s", sellPrice, amountValueUnitsBeingSold, projectedSoldInBaseUnits, *lp.sellBaseAssetCapInBaseUnits, keepSellingBase, newAmountString) } else { keepSellingBase = true } - if sellBaseAssetCapInQuoteUnits != nil { + if lp.sellBaseAssetCapInQuoteUnits != nil { projectedSoldInQuoteUnits := *dailyOTB.SellBaseAssetCapInQuoteUnits + *dailyTBB.SellBaseAssetCapInQuoteUnits + (newAmountBeingSold * sellPrice) - keepSellingQuote = projectedSoldInQuoteUnits <= *sellBaseAssetCapInQuoteUnits + keepSellingQuote = projectedSoldInQuoteUnits <= *lp.sellBaseAssetCapInQuoteUnits newAmountString := "" - if mode == volumeFilterModeExact && !keepSellingQuote { - newAmount := (*sellBaseAssetCapInQuoteUnits - *dailyOTB.SellBaseAssetCapInQuoteUnits - *dailyTBB.SellBaseAssetCapInQuoteUnits) / sellPrice + if lp.mode == volumeFilterModeExact && !keepSellingQuote { + newAmount := (*lp.sellBaseAssetCapInQuoteUnits - *dailyOTB.SellBaseAssetCapInQuoteUnits - *dailyTBB.SellBaseAssetCapInQuoteUnits) / sellPrice if newAmount > 0 { newAmountBeingSold = newAmount opToReturn.Amount = fmt.Sprintf("%.7f", newAmountBeingSold) @@ -199,7 +210,7 @@ func volumeFilterFn(dailyOTB *VolumeFilterConfig, dailyTBB *VolumeFilterConfig, newAmountString = ", newAmountString = " + opToReturn.Amount } } - log.Printf("volumeFilter: selling (quote units), price=%.8f amount=%.8f, keep = (projectedSoldInQuoteUnits) %.7f <= %.7f (config.SellBaseAssetCapInQuoteUnits): keepSellingQuote = %v%s", sellPrice, amountValueUnitsBeingSold, projectedSoldInQuoteUnits, *sellBaseAssetCapInQuoteUnits, keepSellingQuote, newAmountString) + log.Printf("volumeFilter: selling (quote units), price=%.8f amount=%.8f, keep = (projectedSoldInQuoteUnits) %.7f <= %.7f (config.SellBaseAssetCapInQuoteUnits): keepSellingQuote = %v%s", sellPrice, amountValueUnitsBeingSold, projectedSoldInQuoteUnits, *lp.sellBaseAssetCapInQuoteUnits, keepSellingQuote, newAmountString) } else { keepSellingQuote = true } diff --git a/plugins/volumeFilter_test.go b/plugins/volumeFilter_test.go index 6e6b688cf..a70d296ad 100644 --- a/plugins/volumeFilter_test.go +++ b/plugins/volumeFilter_test.go @@ -36,15 +36,14 @@ func makeTestVolumeFilterConfig(baseCapInBase, baseCapInQuote float64, additiona } } -func makeTestVolumeFilter(config *VolumeFilterConfig, additionalMarketIDs, optionalAccountIDs []string) *volumeFilter { - marketID := MakeMarketID("", "native", "native") - marketIDs := utils.Dedupe(append([]string{marketID}, additionalMarketIDs...)) - +func makeTestVolumeFilter(config *VolumeFilterConfig, marketIDs []string, optionalAccountIDs []string) *volumeFilter { query, e := queries.MakeDailyVolumeByDateForMarketIdsAction(&sql.DB{}, marketIDs, "sell", optionalAccountIDs) if e != nil { panic(e) } + fmt.Println(query) + return &volumeFilter{ name: "volumeFilter", baseAsset: utils.NativeAsset, @@ -99,21 +98,24 @@ func TestMakeFilterVolume(t *testing.T) { exchangeName := "" tradingPair := &model.TradingPair{Base: "XLM", Quote: "XLM"} modes := []volumeFilterMode{volumeFilterModeExact, volumeFilterModeIgnore} + firstMarketID := MakeMarketID(exchangeName, "native", "native") for _, k := range testCases { + queryMarketIDs := utils.Dedupe(append([]string{firstMarketID}, k.marketIDs...)) + for _, m := range modes { baseCapInBaseConfig := makeTestVolumeFilterConfig(1.0, -1.0, k.marketIDs, k.accountIDs, m) baseCapInQuoteConfig := makeTestVolumeFilterConfig(-1.0, 1.0, k.marketIDs, k.accountIDs, m) - for _, c := range []*VolumeFilterConfig{baseCapInBaseConfig, baseCapInQuoteConfig} { + for _, config := range []*VolumeFilterConfig{baseCapInBaseConfig, baseCapInQuoteConfig} { var configType string - if c.SellBaseAssetCapInBaseUnits != nil { + if config.SellBaseAssetCapInBaseUnits != nil { configType = "base" } else { configType = "quote" } - wantFilter := makeTestVolumeFilter(c, k.marketIDs, k.accountIDs) + wantFilter := makeTestVolumeFilter(config, queryMarketIDs, k.accountIDs) t.Run(fmt.Sprintf("%s/%s/%s", k.name, configType, m), func(t *testing.T) { actual, e := makeFilterVolume( configValue, @@ -123,10 +125,13 @@ func TestMakeFilterVolume(t *testing.T) { utils.NativeAsset, utils.NativeAsset, &sql.DB{}, - c, + config, ) - assert.Nil(t, e) + if !assert.Nil(t, e) { + return + } + assert.Equal(t, wantFilter, actual) }) } @@ -246,7 +251,13 @@ func TestVolumeFilterFn(t *testing.T) { op := makeManageSellOffer(k.price, k.inputAmount) wantOp := makeManageSellOffer(k.price, k.wantAmount) - actual, e := volumeFilterFn(dailyOTB, dailyTBB, op, utils.NativeAsset, utils.NativeAsset, k.sellBaseCapInBase, k.sellBaseCapInQuote, volumeFilterModeExact) + lp := limitParameters{ + sellBaseAssetCapInBaseUnits: k.sellBaseCapInBase, + sellBaseAssetCapInQuoteUnits: k.sellBaseCapInQuote, + mode: volumeFilterModeExact, + } + + actual, e := volumeFilterFn(dailyOTB, dailyTBB, op, utils.NativeAsset, utils.NativeAsset, lp) assert.Nil(t, e) assert.Equal(t, wantOp, actual) From b39831726a042d3775b5eaf8626b5eb502b7aa3f Mon Sep 17 00:00:00 2001 From: Debnil Sur Date: Thu, 29 Oct 2020 09:49:55 -0700 Subject: [PATCH 09/14] Remove log --- plugins/volumeFilter_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/volumeFilter_test.go b/plugins/volumeFilter_test.go index a70d296ad..5589ad233 100644 --- a/plugins/volumeFilter_test.go +++ b/plugins/volumeFilter_test.go @@ -42,8 +42,6 @@ func makeTestVolumeFilter(config *VolumeFilterConfig, marketIDs []string, option panic(e) } - fmt.Println(query) - return &volumeFilter{ name: "volumeFilter", baseAsset: utils.NativeAsset, From c183e303f5d2fe39b1448203830a9f40ea236e54 Mon Sep 17 00:00:00 2001 From: Debnil Sur Date: Thu, 29 Oct 2020 09:55:43 -0700 Subject: [PATCH 10/14] Factor out action. --- plugins/volumeFilter_test.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/volumeFilter_test.go b/plugins/volumeFilter_test.go index 5589ad233..4c1147b9f 100644 --- a/plugins/volumeFilter_test.go +++ b/plugins/volumeFilter_test.go @@ -36,8 +36,8 @@ func makeTestVolumeFilterConfig(baseCapInBase, baseCapInQuote float64, additiona } } -func makeTestVolumeFilter(config *VolumeFilterConfig, marketIDs []string, optionalAccountIDs []string) *volumeFilter { - query, e := queries.MakeDailyVolumeByDateForMarketIdsAction(&sql.DB{}, marketIDs, "sell", optionalAccountIDs) +func makeTestVolumeFilter(config *VolumeFilterConfig, marketIDs []string, optionalAccountIDs []string, action string) *volumeFilter { + query, e := queries.MakeDailyVolumeByDateForMarketIdsAction(&sql.DB{}, marketIDs, action, optionalAccountIDs) if e != nil { panic(e) } @@ -113,7 +113,8 @@ func TestMakeFilterVolume(t *testing.T) { configType = "quote" } - wantFilter := makeTestVolumeFilter(config, queryMarketIDs, k.accountIDs) + // TODO DS Vary filter action between buy and sell, once buy logic is implemented. + wantFilter := makeTestVolumeFilter(config, queryMarketIDs, k.accountIDs, "sell") t.Run(fmt.Sprintf("%s/%s/%s", k.name, configType, m), func(t *testing.T) { actual, e := makeFilterVolume( configValue, From 3e2b2f1fb41751fb1aae148b125bf464413fffae Mon Sep 17 00:00:00 2001 From: Debnil Sur Date: Thu, 29 Oct 2020 11:50:23 -0700 Subject: [PATCH 11/14] Move query market IDs creation, add comments --- plugins/volumeFilter_test.go | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/plugins/volumeFilter_test.go b/plugins/volumeFilter_test.go index 4c1147b9f..e32cd86dc 100644 --- a/plugins/volumeFilter_test.go +++ b/plugins/volumeFilter_test.go @@ -36,8 +36,9 @@ func makeTestVolumeFilterConfig(baseCapInBase, baseCapInQuote float64, additiona } } -func makeTestVolumeFilter(config *VolumeFilterConfig, marketIDs []string, optionalAccountIDs []string, action string) *volumeFilter { - query, e := queries.MakeDailyVolumeByDateForMarketIdsAction(&sql.DB{}, marketIDs, action, optionalAccountIDs) +func makeWantVolumeFilter(config *VolumeFilterConfig, firstMarketID string, marketIDs []string, optionalAccountIDs []string, action string) *volumeFilter { + queryMarketIDs := utils.Dedupe(append([]string{firstMarketID}, marketIDs...)) + query, e := queries.MakeDailyVolumeByDateForMarketIdsAction(&sql.DB{}, queryMarketIDs, action, optionalAccountIDs) if e != nil { panic(e) } @@ -53,11 +54,17 @@ func makeTestVolumeFilter(config *VolumeFilterConfig, marketIDs []string, option func TestMakeFilterVolume(t *testing.T) { testAssetDisplayFn := model.MakeSdexMappedAssetDisplayFn(map[model.Asset]hProtocol.Asset{model.Asset("XLM"): utils.NativeAsset}) + configValue := "" + exchangeName := "" + tradingPair := &model.TradingPair{Base: "XLM", Quote: "XLM"} + modes := []volumeFilterMode{volumeFilterModeExact, volumeFilterModeIgnore} + firstMarketID := MakeMarketID(exchangeName, "native", "native") testCases := []struct { name string marketIDs []string accountIDs []string + wantFilter *volumeFilter }{ // TODO DS Confirm the empty config fails once validation is added to the constructor { @@ -92,20 +99,15 @@ func TestMakeFilterVolume(t *testing.T) { }, } - configValue := "" - exchangeName := "" - tradingPair := &model.TradingPair{Base: "XLM", Quote: "XLM"} - modes := []volumeFilterMode{volumeFilterModeExact, volumeFilterModeIgnore} - firstMarketID := MakeMarketID(exchangeName, "native", "native") - for _, k := range testCases { - queryMarketIDs := utils.Dedupe(append([]string{firstMarketID}, k.marketIDs...)) - + // this lets us test both types of modes when varying the market and account ids for _, m := range modes { + // this lets us test both constraints within the config baseCapInBaseConfig := makeTestVolumeFilterConfig(1.0, -1.0, k.marketIDs, k.accountIDs, m) baseCapInQuoteConfig := makeTestVolumeFilterConfig(-1.0, 1.0, k.marketIDs, k.accountIDs, m) for _, config := range []*VolumeFilterConfig{baseCapInBaseConfig, baseCapInQuoteConfig} { + // configType is used to represent the type of config when printing test name var configType string if config.SellBaseAssetCapInBaseUnits != nil { configType = "base" @@ -114,7 +116,7 @@ func TestMakeFilterVolume(t *testing.T) { } // TODO DS Vary filter action between buy and sell, once buy logic is implemented. - wantFilter := makeTestVolumeFilter(config, queryMarketIDs, k.accountIDs, "sell") + wantFilter := makeWantVolumeFilter(config, firstMarketID, k.marketIDs, k.accountIDs, "sell") t.Run(fmt.Sprintf("%s/%s/%s", k.name, configType, m), func(t *testing.T) { actual, e := makeFilterVolume( configValue, From d3c5e1a9ed955656811b35333d7372fa2efa0657 Mon Sep 17 00:00:00 2001 From: Debnil Sur Date: Wed, 11 Nov 2020 08:55:38 -0800 Subject: [PATCH 12/14] Pair programming commit. --- plugins/filterFactory.go | 16 ++++ plugins/volumeFilter_test.go | 119 ++++++++++++++++-------------- queries/dailyVolumeByDate_test.go | 8 ++ 3 files changed, 87 insertions(+), 56 deletions(-) diff --git a/plugins/filterFactory.go b/plugins/filterFactory.go index a419be207..3ab4aa872 100644 --- a/plugins/filterFactory.go +++ b/plugins/filterFactory.go @@ -71,6 +71,22 @@ func filterVolume(f *FilterFactory, configInput string) (SubmitFilter, error) { ) } +func makeRawVolumeFilterConfig( + sellBaseAssetCapInBaseUnits *float64, + sellBaseAssetCapInQuoteUnits *float64, + mode volumeFilterMode, + additionalMarketIDs []string, + optionalAccountIDs []string, +) *VolumeFilterConfig { + return &VolumeFilterConfig{ + SellBaseAssetCapInBaseUnits: sellBaseAssetCapInBaseUnits, + SellBaseAssetCapInQuoteUnits: sellBaseAssetCapInQuoteUnits, + mode: mode, + additionalMarketIDs: additionalMarketIDs, + optionalAccountIDs: optionalAccountIDs, + } +} + func makeVolumeFilterConfig(configInput string) (*VolumeFilterConfig, error) { parts := strings.Split(configInput, "/") if len(parts) != 6 { diff --git a/plugins/volumeFilter_test.go b/plugins/volumeFilter_test.go index e32cd86dc..6637cbff7 100644 --- a/plugins/volumeFilter_test.go +++ b/plugins/volumeFilter_test.go @@ -16,29 +16,8 @@ import ( "github.com/stretchr/testify/assert" ) -func makeTestVolumeFilterConfig(baseCapInBase, baseCapInQuote float64, additionalMarketIDs, optionalAccountIDs []string, mode volumeFilterMode) *VolumeFilterConfig { - var baseCapInBasePtr *float64 - if baseCapInBase >= 0 { - baseCapInBasePtr = pointy.Float64(baseCapInBase) - } - - var baseCapInQuotePtr *float64 - if baseCapInQuote >= 0 { - baseCapInQuotePtr = pointy.Float64(baseCapInQuote) - } - - return &VolumeFilterConfig{ - SellBaseAssetCapInBaseUnits: baseCapInBasePtr, - SellBaseAssetCapInQuoteUnits: baseCapInQuotePtr, - mode: mode, - additionalMarketIDs: additionalMarketIDs, - optionalAccountIDs: optionalAccountIDs, - } -} - -func makeWantVolumeFilter(config *VolumeFilterConfig, firstMarketID string, marketIDs []string, optionalAccountIDs []string, action string) *volumeFilter { - queryMarketIDs := utils.Dedupe(append([]string{firstMarketID}, marketIDs...)) - query, e := queries.MakeDailyVolumeByDateForMarketIdsAction(&sql.DB{}, queryMarketIDs, action, optionalAccountIDs) +func makeWantVolumeFilter(config *VolumeFilterConfig, marketIDs []string, accountIDs []string, action string) *volumeFilter { + query, e := queries.MakeDailyVolumeByDateForMarketIdsAction(&sql.DB{}, marketIDs, action, accountIDs) if e != nil { panic(e) } @@ -55,72 +34,100 @@ func makeWantVolumeFilter(config *VolumeFilterConfig, firstMarketID string, mark func TestMakeFilterVolume(t *testing.T) { testAssetDisplayFn := model.MakeSdexMappedAssetDisplayFn(map[model.Asset]hProtocol.Asset{model.Asset("XLM"): utils.NativeAsset}) configValue := "" - exchangeName := "" tradingPair := &model.TradingPair{Base: "XLM", Quote: "XLM"} modes := []volumeFilterMode{volumeFilterModeExact, volumeFilterModeIgnore} - firstMarketID := MakeMarketID(exchangeName, "native", "native") testCases := []struct { - name string - marketIDs []string - accountIDs []string - wantFilter *volumeFilter + name string + exchangeName string + marketIDs []string + accountIDs []string + wantMarketIDs []string + wantFilter *volumeFilter }{ // TODO DS Confirm the empty config fails once validation is added to the constructor { - name: "1 market id", - marketIDs: []string{"marketID"}, - accountIDs: []string{}, + name: "0 market id or account id", + exchangeName: "exchange 2", + marketIDs: []string{}, + accountIDs: []string{}, + wantMarketIDs: []string{"9db20cdd56"}, }, { - name: "2 market ids", - marketIDs: []string{"marketID1", "marketID2"}, - accountIDs: []string{}, + name: "1 market id", + exchangeName: "exchange 1", + marketIDs: []string{"marketID"}, + accountIDs: []string{}, + wantMarketIDs: []string{"6d9862b0e2", "marketID"}, }, { - name: "2 dupe market ids, 1 distinct", - marketIDs: []string{"marketID1", "marketID1", "marketID2"}, - accountIDs: []string{}, + name: "2 market ids", + exchangeName: "exchange 2", + marketIDs: []string{"marketID1", "marketID2"}, + accountIDs: []string{}, + wantMarketIDs: []string{"9db20cdd56", "marketID1", "marketID2"}, }, { - name: "1 account id", - marketIDs: []string{}, - accountIDs: []string{"accountID"}, + name: "2 dupe market ids, 1 distinct", + exchangeName: "exchange 1", + marketIDs: []string{"marketID1", "marketID1", "marketID2"}, + accountIDs: []string{}, + wantMarketIDs: []string{"6d9862b0e2", "marketID1", "marketID2"}, }, { - name: "2 account ids", - marketIDs: []string{}, - accountIDs: []string{"accountID1", "accountID2"}, + name: "1 account id", + exchangeName: "exchange 2", + marketIDs: []string{}, + accountIDs: []string{"accountID"}, + wantMarketIDs: []string{"9db20cdd56"}, }, { - name: "account and market ids", - marketIDs: []string{"marketID"}, - accountIDs: []string{"accountID"}, + name: "2 account ids", + exchangeName: "exchange 1", + marketIDs: []string{}, + accountIDs: []string{"accountID1", "accountID2"}, + wantMarketIDs: []string{"6d9862b0e2"}, + }, + { + name: "account and market ids", + exchangeName: "exchange 2", + marketIDs: []string{"marketID"}, + accountIDs: []string{"accountID"}, + wantMarketIDs: []string{"9db20cdd56", "marketID"}, }, } for _, k := range testCases { // this lets us test both types of modes when varying the market and account ids for _, m := range modes { - // this lets us test both constraints within the config - baseCapInBaseConfig := makeTestVolumeFilterConfig(1.0, -1.0, k.marketIDs, k.accountIDs, m) - baseCapInQuoteConfig := makeTestVolumeFilterConfig(-1.0, 1.0, k.marketIDs, k.accountIDs, m) - + // this lets us run the for-loop below for both base and quote units within the config + baseCapInBaseConfig := makeRawVolumeFilterConfig( + pointy.Float64(1.0), + nil, + m, + k.marketIDs, + k.accountIDs, + ) + baseCapInQuoteConfig := makeRawVolumeFilterConfig( + nil, + pointy.Float64(1.0), + m, + k.marketIDs, + k.accountIDs, + ) for _, config := range []*VolumeFilterConfig{baseCapInBaseConfig, baseCapInQuoteConfig} { // configType is used to represent the type of config when printing test name - var configType string + configType := "quote" if config.SellBaseAssetCapInBaseUnits != nil { configType = "base" - } else { - configType = "quote" } // TODO DS Vary filter action between buy and sell, once buy logic is implemented. - wantFilter := makeWantVolumeFilter(config, firstMarketID, k.marketIDs, k.accountIDs, "sell") + wantFilter := makeWantVolumeFilter(config, k.wantMarketIDs, k.accountIDs, "sell") t.Run(fmt.Sprintf("%s/%s/%s", k.name, configType, m), func(t *testing.T) { actual, e := makeFilterVolume( configValue, - exchangeName, + k.exchangeName, tradingPair, testAssetDisplayFn, utils.NativeAsset, diff --git a/queries/dailyVolumeByDate_test.go b/queries/dailyVolumeByDate_test.go index d9a5d75b2..34ce15586 100644 --- a/queries/dailyVolumeByDate_test.go +++ b/queries/dailyVolumeByDate_test.go @@ -79,6 +79,14 @@ func TestDailyVolumeByDate_QueryRow(t *testing.T) { wantTodayQuote: 10.0, wantTomorrowBase: 0.0, wantTomorrowQuote: 0.0, + }, { + queryByOptionalAccountIDs: []string{"accountID2", "accountID2"}, // duplicate accountIDs should return same as previous test case + wantYesterdayBase: 0.0, + wantYesterdayQuote: 0.0, + wantTodayBase: 100.0, + wantTodayQuote: 10.0, + wantTomorrowBase: 0.0, + wantTomorrowQuote: 0.0, }, { queryByOptionalAccountIDs: []string{"accountID3"}, //accountID3 does not exist wantYesterdayBase: 0.0, From 9379bf501345eb05f06cb5615aeee98c4f171343 Mon Sep 17 00:00:00 2001 From: Debnil Sur Date: Wed, 11 Nov 2020 08:56:01 -0800 Subject: [PATCH 13/14] Delete volume filter fn test. --- plugins/volumeFilter_test.go | 114 ----------------------------------- 1 file changed, 114 deletions(-) diff --git a/plugins/volumeFilter_test.go b/plugins/volumeFilter_test.go index 6637cbff7..1998850a7 100644 --- a/plugins/volumeFilter_test.go +++ b/plugins/volumeFilter_test.go @@ -159,117 +159,3 @@ func makeManageSellOffer(price, amount string) *txnbuild.ManageSellOffer { Amount: amount, } } - -func TestVolumeFilterFn(t *testing.T) { - testCases := []struct { - name string - filter *volumeFilter - sellBaseCapInBase *float64 - sellBaseCapInQuote *float64 - otbBaseCap float64 - otbQuoteCap float64 - tbbBaseCap float64 - tbbQuoteCap float64 - price string - inputAmount string - wantAmount string - wantTbbBaseCap float64 - wantTbbQuoteCap float64 - }{ - { - name: "selling, base units sell cap, don't keep selling base", - sellBaseCapInBase: pointy.Float64(0.0), - sellBaseCapInQuote: nil, - otbBaseCap: 0.0, - otbQuoteCap: 0.0, - tbbBaseCap: 0.0, - tbbQuoteCap: 0.0, - price: "2.0", - inputAmount: "100.0", - wantAmount: "", - wantTbbBaseCap: 0.0, - wantTbbQuoteCap: 0.0, - }, - { - name: "selling, base units sell cap, keep selling base", - sellBaseCapInBase: pointy.Float64(1.0), - sellBaseCapInQuote: nil, - otbBaseCap: 0.0, - otbQuoteCap: 0.0, - tbbBaseCap: 0.0, - tbbQuoteCap: 0.0, - price: "2.0", - inputAmount: "100.0", - wantAmount: "1.0000000", - wantTbbBaseCap: 1.0, - wantTbbQuoteCap: 2.0, - }, - { - name: "selling, quote units sell cap, don't keep selling quote", - sellBaseCapInBase: nil, - sellBaseCapInQuote: pointy.Float64(0), - otbBaseCap: 0.0, - otbQuoteCap: 0.0, - tbbBaseCap: 0.0, - tbbQuoteCap: 0.0, - price: "2.0", - inputAmount: "100.0", - wantAmount: "", - wantTbbBaseCap: 0.0, - wantTbbQuoteCap: 0.0, - }, - { - name: "selling, quote units sell cap, keep selling quote", - sellBaseCapInBase: nil, - sellBaseCapInQuote: pointy.Float64(1.), - otbBaseCap: 0.0, - otbQuoteCap: 0.0, - tbbBaseCap: 0.0, - tbbQuoteCap: 0.0, - price: "2.0", - inputAmount: "100.0", - wantAmount: "0.5000000", - wantTbbBaseCap: 0.5, - wantTbbQuoteCap: 1.0, - }, - { - name: "selling, base and quote units sell cap, keep selling base and quote", - sellBaseCapInBase: pointy.Float64(1.), - sellBaseCapInQuote: pointy.Float64(1.), - otbBaseCap: 0.0, - otbQuoteCap: 0.0, - tbbBaseCap: 0.0, - tbbQuoteCap: 0.0, - price: "2.0", - inputAmount: "100.0", - wantAmount: "0.5000000", - wantTbbBaseCap: 0.5, - wantTbbQuoteCap: 1.0, - }, - } - - for _, k := range testCases { - t.Run(k.name, func(t *testing.T) { - marketIDs := []string{} - accountIDs := []string{} - mode := volumeFilterModeExact - dailyOTB := makeTestVolumeFilterConfig(k.otbBaseCap, k.otbQuoteCap, marketIDs, accountIDs, mode) - dailyTBB := makeTestVolumeFilterConfig(k.tbbBaseCap, k.tbbQuoteCap, marketIDs, accountIDs, mode) - wantTBB := makeTestVolumeFilterConfig(k.wantTbbBaseCap, k.wantTbbQuoteCap, marketIDs, accountIDs, mode) - op := makeManageSellOffer(k.price, k.inputAmount) - wantOp := makeManageSellOffer(k.price, k.wantAmount) - - lp := limitParameters{ - sellBaseAssetCapInBaseUnits: k.sellBaseCapInBase, - sellBaseAssetCapInQuoteUnits: k.sellBaseCapInQuote, - mode: volumeFilterModeExact, - } - - actual, e := volumeFilterFn(dailyOTB, dailyTBB, op, utils.NativeAsset, utils.NativeAsset, lp) - - assert.Nil(t, e) - assert.Equal(t, wantOp, actual) - assert.Equal(t, wantTBB, dailyTBB) - }) - } -} From 88da78cc6a7b1d3ddbd8ebf6c41c1254337b248b Mon Sep 17 00:00:00 2001 From: Debnil Sur Date: Thu, 12 Nov 2020 08:51:56 -0800 Subject: [PATCH 14/14] Remove unused helper, add default configValue --- plugins/volumeFilter_test.go | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/plugins/volumeFilter_test.go b/plugins/volumeFilter_test.go index 1998850a7..2e1f85c82 100644 --- a/plugins/volumeFilter_test.go +++ b/plugins/volumeFilter_test.go @@ -9,8 +9,6 @@ import ( "github.com/stellar/kelp/queries" "github.com/stellar/kelp/support/utils" - "github.com/stellar/go/txnbuild" - hProtocol "github.com/stellar/go/protocols/horizon" "github.com/stellar/kelp/model" "github.com/stretchr/testify/assert" @@ -24,6 +22,7 @@ func makeWantVolumeFilter(config *VolumeFilterConfig, marketIDs []string, accoun return &volumeFilter{ name: "volumeFilter", + configValue: "", baseAsset: utils.NativeAsset, quoteAsset: utils.NativeAsset, config: config, @@ -146,16 +145,3 @@ func TestMakeFilterVolume(t *testing.T) { } } } - -func makeManageSellOffer(price, amount string) *txnbuild.ManageSellOffer { - if amount == "" { - return nil - } - - return &txnbuild.ManageSellOffer{ - Buying: txnbuild.NativeAsset{}, - Selling: txnbuild.NativeAsset{}, - Price: price, - Amount: amount, - } -}