package parsers import ( "context" "fmt" "sync" "github.com/ethereum/go-ethereum/core/types" mevtypes "github.com/your-org/mev-bot/pkg/types" ) // factory implements the Factory interface type factory struct { parsers map[mevtypes.ProtocolType]Parser mu sync.RWMutex } // NewFactory creates a new parser factory func NewFactory() Factory { return &factory{ parsers: make(map[mevtypes.ProtocolType]Parser), } } // RegisterParser registers a parser for a protocol func (f *factory) RegisterParser(protocol mevtypes.ProtocolType, parser Parser) error { if protocol == mevtypes.ProtocolUnknown { return fmt.Errorf("cannot register parser for unknown protocol") } if parser == nil { return fmt.Errorf("parser cannot be nil") } f.mu.Lock() defer f.mu.Unlock() if _, exists := f.parsers[protocol]; exists { return fmt.Errorf("parser for protocol %s already registered", protocol) } f.parsers[protocol] = parser return nil } // GetParser returns a parser for the given protocol func (f *factory) GetParser(protocol mevtypes.ProtocolType) (Parser, error) { f.mu.RLock() defer f.mu.RUnlock() parser, exists := f.parsers[protocol] if !exists { return nil, fmt.Errorf("no parser registered for protocol %s", protocol) } return parser, nil } // ParseLog routes a log to the appropriate parser func (f *factory) ParseLog(ctx context.Context, log types.Log, tx *types.Transaction) (*mevtypes.SwapEvent, error) { f.mu.RLock() defer f.mu.RUnlock() // Try each registered parser for _, parser := range f.parsers { if parser.SupportsLog(log) { return parser.ParseLog(ctx, log, tx) } } return nil, mevtypes.ErrUnsupportedProtocol } // ParseTransaction parses all swap events from a transaction func (f *factory) ParseTransaction(ctx context.Context, tx *types.Transaction, receipt *types.Receipt) ([]*mevtypes.SwapEvent, error) { if receipt == nil { return nil, fmt.Errorf("receipt cannot be nil") } f.mu.RLock() defer f.mu.RUnlock() var allEvents []*mevtypes.SwapEvent // Try each log with all parsers for _, log := range receipt.Logs { for _, parser := range f.parsers { if parser.SupportsLog(*log) { event, err := parser.ParseLog(ctx, *log, tx) if err != nil { // Log error but continue with other parsers continue } if event != nil { allEvents = append(allEvents, event) } break // Found parser for this log, move to next log } } } return allEvents, nil }