feat(core): implement core MEV bot functionality with market scanning and Uniswap V3 pricing
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
@@ -6,19 +6,19 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/fraktal/mev-beta/internal/config"
|
||||
"github.com/fraktal/mev-beta/internal/logger"
|
||||
"github.com/fraktal/mev-beta/internal/ratelimit"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
)
|
||||
|
||||
// FanManager manages fan-in/fan-out patterns for multiple data sources
|
||||
type FanManager struct {
|
||||
config *config.Config
|
||||
logger *logger.Logger
|
||||
rateLimiter *ratelimit.LimiterManager
|
||||
bufferSize int
|
||||
maxWorkers int
|
||||
config *config.Config
|
||||
logger *logger.Logger
|
||||
rateLimiter *ratelimit.LimiterManager
|
||||
bufferSize int
|
||||
maxWorkers int
|
||||
}
|
||||
|
||||
// NewFanManager creates a new fan manager
|
||||
@@ -36,10 +36,10 @@ func NewFanManager(cfg *config.Config, logger *logger.Logger, rateLimiter *ratel
|
||||
func (fm *FanManager) FanOut(ctx context.Context, jobs <-chan *types.Transaction, numWorkers int) <-chan *types.Transaction {
|
||||
// Create the output channel
|
||||
out := make(chan *types.Transaction, fm.bufferSize)
|
||||
|
||||
|
||||
// Create a wait group to wait for all workers
|
||||
var wg sync.WaitGroup
|
||||
|
||||
|
||||
// Start the workers
|
||||
for i := 0; i < numWorkers; i++ {
|
||||
wg.Add(1)
|
||||
@@ -48,13 +48,13 @@ func (fm *FanManager) FanOut(ctx context.Context, jobs <-chan *types.Transaction
|
||||
fm.worker(ctx, jobs, out, workerID)
|
||||
}(i)
|
||||
}
|
||||
|
||||
|
||||
// Close the output channel when all workers are done
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(out)
|
||||
}()
|
||||
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
@@ -66,21 +66,21 @@ func (fm *FanManager) worker(ctx context.Context, jobs <-chan *types.Transaction
|
||||
if !ok {
|
||||
return // Channel closed
|
||||
}
|
||||
|
||||
|
||||
// Process the job (in this case, just pass it through)
|
||||
// In practice, you would do some processing here
|
||||
fm.logger.Debug(fmt.Sprintf("Worker %d processing transaction %s", workerID, job.Hash().Hex()))
|
||||
|
||||
|
||||
// Simulate some work
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
|
||||
|
||||
// Send the result to the output channel
|
||||
select {
|
||||
case out <- job:
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
@@ -91,10 +91,10 @@ func (fm *FanManager) worker(ctx context.Context, jobs <-chan *types.Transaction
|
||||
func (fm *FanManager) FanIn(ctx context.Context, inputs ...<-chan *types.Transaction) <-chan *types.Transaction {
|
||||
// Create the output channel
|
||||
out := make(chan *types.Transaction, fm.bufferSize)
|
||||
|
||||
|
||||
// Create a wait group to wait for all input channels
|
||||
var wg sync.WaitGroup
|
||||
|
||||
|
||||
// Start a goroutine for each input channel
|
||||
for i, input := range inputs {
|
||||
wg.Add(1)
|
||||
@@ -103,13 +103,13 @@ func (fm *FanManager) FanIn(ctx context.Context, inputs ...<-chan *types.Transac
|
||||
fm.fanInWorker(ctx, inputChan, out, inputID)
|
||||
}(i, input)
|
||||
}
|
||||
|
||||
|
||||
// Close the output channel when all input channels are done
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(out)
|
||||
}()
|
||||
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
@@ -121,14 +121,14 @@ func (fm *FanManager) fanInWorker(ctx context.Context, input <-chan *types.Trans
|
||||
if !ok {
|
||||
return // Channel closed
|
||||
}
|
||||
|
||||
|
||||
// Send the job to the output channel
|
||||
select {
|
||||
case out <- job:
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
@@ -139,43 +139,43 @@ func (fm *FanManager) fanInWorker(ctx context.Context, input <-chan *types.Trans
|
||||
func (fm *FanManager) Multiplex(ctx context.Context, transactions <-chan *types.Transaction) []<-chan *types.Transaction {
|
||||
endpoints := fm.rateLimiter.GetEndpoints()
|
||||
outputs := make([]<-chan *types.Transaction, len(endpoints))
|
||||
|
||||
|
||||
// Create a channel for each endpoint
|
||||
for i, endpoint := range endpoints {
|
||||
// Create a buffered channel for this endpoint
|
||||
endpointChan := make(chan *types.Transaction, fm.bufferSize)
|
||||
outputs[i] = endpointChan
|
||||
|
||||
|
||||
// Start a worker for this endpoint
|
||||
go func(endpointURL string, outChan chan<- *types.Transaction) {
|
||||
defer close(outChan)
|
||||
|
||||
|
||||
for {
|
||||
select {
|
||||
case tx, ok := <-transactions:
|
||||
if !ok {
|
||||
return // Input channel closed
|
||||
}
|
||||
|
||||
|
||||
// Wait for rate limiter
|
||||
if err := fm.rateLimiter.WaitForLimit(ctx, endpointURL); err != nil {
|
||||
fm.logger.Error(fmt.Sprintf("Rate limiter error for %s: %v", endpointURL, err))
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
// Send to endpoint-specific channel
|
||||
select {
|
||||
case outChan <- tx:
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}(endpoint, endpointChan)
|
||||
}
|
||||
|
||||
|
||||
return outputs
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user