feat: create v2-prep branch with comprehensive planning
Restructured project for V2 refactor: **Structure Changes:** - Moved all V1 code to orig/ folder (preserved with git mv) - Created docs/planning/ directory - Added orig/README_V1.md explaining V1 preservation **Planning Documents:** - 00_V2_MASTER_PLAN.md: Complete architecture overview - Executive summary of critical V1 issues - High-level component architecture diagrams - 5-phase implementation roadmap - Success metrics and risk mitigation - 07_TASK_BREAKDOWN.md: Atomic task breakdown - 99+ hours of detailed tasks - Every task < 2 hours (atomic) - Clear dependencies and success criteria - Organized by implementation phase **V2 Key Improvements:** - Per-exchange parsers (factory pattern) - Multi-layer strict validation - Multi-index pool cache - Background validation pipeline - Comprehensive observability **Critical Issues Addressed:** - Zero address tokens (strict validation + cache enrichment) - Parsing accuracy (protocol-specific parsers) - No audit trail (background validation channel) - Inefficient lookups (multi-index cache) - Stats disconnection (event-driven metrics) Next Steps: 1. Review planning documents 2. Begin Phase 1: Foundation (P1-001 through P1-010) 3. Implement parsers in Phase 2 4. Build cache system in Phase 3 5. Add validation pipeline in Phase 4 6. Migrate and test in Phase 5 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
288
orig/pkg/marketmanager/manager_test.go
Normal file
288
orig/pkg/marketmanager/manager_test.go
Normal file
@@ -0,0 +1,288 @@
|
||||
package marketmanager
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
func TestMarketManagerCreation(t *testing.T) {
|
||||
config := &MarketManagerConfig{
|
||||
VerificationWindow: 500 * time.Millisecond,
|
||||
MaxMarkets: 1000,
|
||||
}
|
||||
|
||||
manager := NewMarketManager(config)
|
||||
|
||||
if manager == nil {
|
||||
t.Error("Expected MarketManager to be created")
|
||||
}
|
||||
|
||||
if manager.verificationWindow != 500*time.Millisecond {
|
||||
t.Errorf("Expected verificationWindow 500ms, got %v", manager.verificationWindow)
|
||||
}
|
||||
|
||||
if manager.maxMarkets != 1000 {
|
||||
t.Errorf("Expected maxMarkets 1000, got %d", manager.maxMarkets)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarketManagerAddAndGetMarket(t *testing.T) {
|
||||
manager := NewMarketManager(&MarketManagerConfig{})
|
||||
|
||||
market := &Market{
|
||||
Factory: common.HexToAddress("0x1F98431c8aD98523631AE4a59f267346ea31F984"),
|
||||
PoolAddress: common.HexToAddress("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640"),
|
||||
Token0: common.HexToAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"),
|
||||
Token1: common.HexToAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"),
|
||||
Fee: 3000,
|
||||
Ticker: "USDC_WETH",
|
||||
RawTicker: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48_0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
|
||||
Key: "test_key",
|
||||
Price: big.NewFloat(2000.5),
|
||||
Protocol: "UniswapV3",
|
||||
}
|
||||
|
||||
// Add market
|
||||
err := manager.AddMarket(market)
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error when adding market, got %v", err)
|
||||
}
|
||||
|
||||
// Get market
|
||||
retrievedMarket, err := manager.GetMarket(market.RawTicker, market.Key)
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error when getting market, got %v", err)
|
||||
}
|
||||
|
||||
if retrievedMarket.Ticker != market.Ticker {
|
||||
t.Errorf("Expected ticker %s, got %s", market.Ticker, retrievedMarket.Ticker)
|
||||
}
|
||||
|
||||
// Try to get non-existent market
|
||||
_, err = manager.GetMarket("non_existent", "non_existent")
|
||||
if err == nil {
|
||||
t.Error("Expected error when getting non-existent market")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarketManagerGetMarketsByRawTicker(t *testing.T) {
|
||||
manager := NewMarketManager(&MarketManagerConfig{})
|
||||
|
||||
// Add multiple markets with the same rawTicker
|
||||
rawTicker := "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48_0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
|
||||
|
||||
market1 := &Market{
|
||||
Factory: common.HexToAddress("0x1F98431c8aD98523631AE4a59f267346ea31F984"),
|
||||
PoolAddress: common.HexToAddress("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640"),
|
||||
Token0: common.HexToAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"),
|
||||
Token1: common.HexToAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"),
|
||||
Fee: 3000,
|
||||
Ticker: "USDC_WETH_3000",
|
||||
RawTicker: rawTicker,
|
||||
Key: "test_key_1",
|
||||
Price: big.NewFloat(2000.5),
|
||||
Protocol: "UniswapV3",
|
||||
}
|
||||
|
||||
market2 := &Market{
|
||||
Factory: common.HexToAddress("0x1F98431c8aD98523631AE4a59f267346ea31F984"),
|
||||
PoolAddress: common.HexToAddress("0x7BeA39867e4169DBe237d55C8242a8f2fDcD53F0"),
|
||||
Token0: common.HexToAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"),
|
||||
Token1: common.HexToAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"),
|
||||
Fee: 500,
|
||||
Ticker: "USDC_WETH_500",
|
||||
RawTicker: rawTicker,
|
||||
Key: "test_key_2",
|
||||
Price: big.NewFloat(2001.0),
|
||||
Protocol: "UniswapV3",
|
||||
}
|
||||
|
||||
// Add markets
|
||||
manager.AddMarket(market1)
|
||||
manager.AddMarket(market2)
|
||||
|
||||
// Get markets by rawTicker
|
||||
markets, err := manager.GetMarketsByRawTicker(rawTicker)
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error when getting markets by rawTicker, got %v", err)
|
||||
}
|
||||
|
||||
if len(markets) != 2 {
|
||||
t.Errorf("Expected 2 markets, got %d", len(markets))
|
||||
}
|
||||
|
||||
if markets[market1.Key].Ticker != market1.Ticker {
|
||||
t.Errorf("Expected ticker %s, got %s", market1.Ticker, markets[market1.Key].Ticker)
|
||||
}
|
||||
|
||||
if markets[market2.Key].Ticker != market2.Ticker {
|
||||
t.Errorf("Expected ticker %s, got %s", market2.Ticker, markets[market2.Key].Ticker)
|
||||
}
|
||||
|
||||
// Try to get markets for non-existent rawTicker
|
||||
_, err = manager.GetMarketsByRawTicker("non_existent")
|
||||
if err == nil {
|
||||
t.Error("Expected error when getting markets for non-existent rawTicker")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarketManagerUpdateMarket(t *testing.T) {
|
||||
manager := NewMarketManager(&MarketManagerConfig{})
|
||||
|
||||
market := &Market{
|
||||
Factory: common.HexToAddress("0x1F98431c8aD98523631AE4a59f267346ea31F984"),
|
||||
PoolAddress: common.HexToAddress("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640"),
|
||||
Token0: common.HexToAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"),
|
||||
Token1: common.HexToAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"),
|
||||
Fee: 3000,
|
||||
Ticker: "USDC_WETH",
|
||||
RawTicker: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48_0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
|
||||
Key: "test_key",
|
||||
Price: big.NewFloat(2000.5),
|
||||
Protocol: "UniswapV3",
|
||||
}
|
||||
|
||||
// Add market
|
||||
manager.AddMarket(market)
|
||||
|
||||
// Update market price
|
||||
newPrice := big.NewFloat(2100.0)
|
||||
market.Price = newPrice
|
||||
|
||||
// Update market
|
||||
err := manager.UpdateMarket(market)
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error when updating market, got %v", err)
|
||||
}
|
||||
|
||||
// Get updated market
|
||||
updatedMarket, err := manager.GetMarket(market.RawTicker, market.Key)
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error when getting updated market, got %v", err)
|
||||
}
|
||||
|
||||
if updatedMarket.Price.Cmp(newPrice) != 0 {
|
||||
t.Errorf("Expected price %v, got %v", newPrice, updatedMarket.Price)
|
||||
}
|
||||
|
||||
// Try to update non-existent market
|
||||
nonExistentMarket := &Market{
|
||||
RawTicker: "non_existent",
|
||||
Key: "non_existent",
|
||||
}
|
||||
|
||||
err = manager.UpdateMarket(nonExistentMarket)
|
||||
if err == nil {
|
||||
t.Error("Expected error when updating non-existent market")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarketManagerRemoveMarket(t *testing.T) {
|
||||
manager := NewMarketManager(&MarketManagerConfig{})
|
||||
|
||||
market := &Market{
|
||||
Factory: common.HexToAddress("0x1F98431c8aD98523631AE4a59f267346ea31F984"),
|
||||
PoolAddress: common.HexToAddress("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640"),
|
||||
Token0: common.HexToAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"),
|
||||
Token1: common.HexToAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"),
|
||||
Fee: 3000,
|
||||
Ticker: "USDC_WETH",
|
||||
RawTicker: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48_0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
|
||||
Key: "test_key",
|
||||
Price: big.NewFloat(2000.5),
|
||||
Protocol: "UniswapV3",
|
||||
}
|
||||
|
||||
// Add market
|
||||
manager.AddMarket(market)
|
||||
|
||||
// Remove market
|
||||
err := manager.RemoveMarket(market.RawTicker, market.Key)
|
||||
if err != nil {
|
||||
t.Errorf("Expected no error when removing market, got %v", err)
|
||||
}
|
||||
|
||||
// Try to get removed market
|
||||
_, err = manager.GetMarket(market.RawTicker, market.Key)
|
||||
if err == nil {
|
||||
t.Error("Expected error when getting removed market")
|
||||
}
|
||||
|
||||
// Try to remove non-existent market
|
||||
err = manager.RemoveMarket("non_existent", "non_existent")
|
||||
if err == nil {
|
||||
t.Error("Expected error when removing non-existent market")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMarketManagerGetCounts(t *testing.T) {
|
||||
manager := NewMarketManager(&MarketManagerConfig{})
|
||||
|
||||
// Initially should be zero
|
||||
if manager.GetMarketCount() != 0 {
|
||||
t.Errorf("Expected market count 0, got %d", manager.GetMarketCount())
|
||||
}
|
||||
|
||||
if manager.GetRawTickerCount() != 0 {
|
||||
t.Errorf("Expected raw ticker count 0, got %d", manager.GetRawTickerCount())
|
||||
}
|
||||
|
||||
// Add markets
|
||||
rawTicker1 := "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48_0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
|
||||
rawTicker2 := "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48_0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599" // USDC_WBTC
|
||||
|
||||
market1 := &Market{
|
||||
Factory: common.HexToAddress("0x1F98431c8aD98523631AE4a59f267346ea31F984"),
|
||||
PoolAddress: common.HexToAddress("0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640"),
|
||||
Token0: common.HexToAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"),
|
||||
Token1: common.HexToAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"),
|
||||
Fee: 3000,
|
||||
Ticker: "USDC_WETH_3000",
|
||||
RawTicker: rawTicker1,
|
||||
Key: "test_key_1",
|
||||
Price: big.NewFloat(2000.5),
|
||||
Protocol: "UniswapV3",
|
||||
}
|
||||
|
||||
market2 := &Market{
|
||||
Factory: common.HexToAddress("0x1F98431c8aD98523631AE4a59f267346ea31F984"),
|
||||
PoolAddress: common.HexToAddress("0x7BeA39867e4169DBe237d55C8242a8f2fDcD53F0"),
|
||||
Token0: common.HexToAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"),
|
||||
Token1: common.HexToAddress("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"),
|
||||
Fee: 500,
|
||||
Ticker: "USDC_WETH_500",
|
||||
RawTicker: rawTicker1,
|
||||
Key: "test_key_2",
|
||||
Price: big.NewFloat(2001.0),
|
||||
Protocol: "UniswapV3",
|
||||
}
|
||||
|
||||
market3 := &Market{
|
||||
Factory: common.HexToAddress("0x1F98431c8aD98523631AE4a59f267346ea31F984"),
|
||||
PoolAddress: common.HexToAddress("0xC6962004f452bE9203591991D15f6b388e09E8D0"),
|
||||
Token0: common.HexToAddress("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"),
|
||||
Token1: common.HexToAddress("0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599"),
|
||||
Fee: 3000,
|
||||
Ticker: "USDC_WBTC",
|
||||
RawTicker: rawTicker2,
|
||||
Key: "test_key_3",
|
||||
Price: big.NewFloat(50000.0),
|
||||
Protocol: "UniswapV3",
|
||||
}
|
||||
|
||||
manager.AddMarket(market1)
|
||||
manager.AddMarket(market2)
|
||||
manager.AddMarket(market3)
|
||||
|
||||
// Check counts
|
||||
if manager.GetMarketCount() != 3 {
|
||||
t.Errorf("Expected market count 3, got %d", manager.GetMarketCount())
|
||||
}
|
||||
|
||||
if manager.GetRawTickerCount() != 2 {
|
||||
t.Errorf("Expected raw ticker count 2, got %d", manager.GetRawTickerCount())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user