fix(critical): integrate multi-hop scanner with swap analyzer
✅ CRITICAL FIX #1: Connected swap analyzer to multi-hop scanner - Modified SubmitBridgeOpportunity() to trigger multi-hop scanner - Scanner uses token graph with 8 high-liquidity Arbitrum pools - Finds real multi-hop arbitrage paths (A→B→C→A) ✅ CRITICAL FIX #2: Lowered profit threshold 1000x - ExecuteArbitrageOpportunity: 0.01 ETH → 0.00001 ETH - Matches aggressive settings (/bin/bash.02 minimum) 🎯 Target: First profitable execution within 24 hours 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1659,12 +1659,105 @@ func (sas *ArbitrageService) SubmitBridgeOpportunity(ctx context.Context, bridge
|
||||
opp.ID = fmt.Sprintf("bridge-%s-%d", opp.TokenIn.Hex(), now.UnixNano())
|
||||
}
|
||||
|
||||
sas.logger.Info("📥 Received bridge arbitrage opportunity",
|
||||
sas.logger.Info("📥 Received bridge arbitrage opportunity - analyzing with multi-hop scanner",
|
||||
"id", opp.ID,
|
||||
"path_length", len(opp.Path),
|
||||
"pools", len(opp.Pools),
|
||||
)
|
||||
|
||||
// ✅ CRITICAL FIX: Use multi-hop scanner to find REAL arbitrage paths
|
||||
// Instead of accepting the single-pool opportunity as-is, scan for multi-hop paths
|
||||
var tokensToScan []common.Address
|
||||
if opp.TokenIn != (common.Address{}) {
|
||||
tokensToScan = append(tokensToScan, opp.TokenIn)
|
||||
}
|
||||
if opp.TokenOut != (common.Address{}) && opp.TokenOut != opp.TokenIn {
|
||||
tokensToScan = append(tokensToScan, opp.TokenOut)
|
||||
}
|
||||
|
||||
// If we have tokens, use multi-hop scanner to find profitable paths
|
||||
if len(tokensToScan) > 0 && sas.multiHopScanner != nil {
|
||||
scanAmount := opp.AmountIn
|
||||
if scanAmount == nil || scanAmount.Sign() == 0 {
|
||||
scanAmount = big.NewInt(100000000000000000) // Default 0.1 ETH scan amount
|
||||
}
|
||||
|
||||
sas.logger.Info("🔍 Scanning for multi-hop arbitrage paths",
|
||||
"tokens", len(tokensToScan),
|
||||
"scanAmount", scanAmount.String(),
|
||||
)
|
||||
|
||||
for _, token := range tokensToScan {
|
||||
paths, err := sas.multiHopScanner.ScanForArbitrage(sas.ctx, token, scanAmount)
|
||||
if err != nil {
|
||||
sas.logger.Debug(fmt.Sprintf("Multi-hop scan failed for token %s: %v", token.Hex(), err))
|
||||
continue
|
||||
}
|
||||
|
||||
if len(paths) > 0 {
|
||||
sas.logger.Info(fmt.Sprintf("✅ Found %d multi-hop arbitrage paths!", len(paths)))
|
||||
|
||||
// Create and execute opportunities for each profitable path
|
||||
for _, path := range paths {
|
||||
if path.NetProfit.Sign() <= 0 {
|
||||
continue // Skip unprofitable paths
|
||||
}
|
||||
|
||||
pathTokens := make([]string, len(path.Tokens))
|
||||
for i, tokenAddr := range path.Tokens {
|
||||
pathTokens[i] = tokenAddr.Hex()
|
||||
}
|
||||
|
||||
poolAddresses := make([]string, len(path.Pools))
|
||||
for i, poolInfo := range path.Pools {
|
||||
poolAddresses[i] = poolInfo.Address.Hex()
|
||||
}
|
||||
|
||||
multiHopOpp := &pkgtypes.ArbitrageOpportunity{
|
||||
ID: fmt.Sprintf("multihop-%s-%d", token.Hex(), now.UnixNano()),
|
||||
Path: pathTokens,
|
||||
Pools: poolAddresses,
|
||||
AmountIn: new(big.Int).Set(scanAmount),
|
||||
RequiredAmount: new(big.Int).Set(scanAmount),
|
||||
Profit: new(big.Int).Set(path.NetProfit),
|
||||
NetProfit: new(big.Int).Set(path.NetProfit),
|
||||
EstimatedProfit: new(big.Int).Set(path.NetProfit),
|
||||
DetectedAt: now,
|
||||
ExpiresAt: now.Add(sas.config.OpportunityTTL),
|
||||
Timestamp: now.Unix(),
|
||||
Urgency: sas.calculateUrgency(path),
|
||||
ROI: path.ROI,
|
||||
TokenIn: path.Tokens[0],
|
||||
TokenOut: path.Tokens[len(path.Tokens)-1],
|
||||
Confidence: 0.7,
|
||||
}
|
||||
|
||||
// Store path
|
||||
sas.storeOpportunityPath(multiHopOpp.ID, path)
|
||||
|
||||
// Save to database
|
||||
if sas.database != nil {
|
||||
if err := sas.database.SaveOpportunity(sas.ctx, multiHopOpp); err != nil {
|
||||
sas.logger.Warn("Failed to save multi-hop opportunity", "error", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Increment stats
|
||||
atomic.AddInt64(&sas.stats.TotalOpportunitiesDetected, 1)
|
||||
|
||||
// Execute opportunity
|
||||
sas.logger.Info(fmt.Sprintf("🚀 Executing multi-hop opportunity: profit=%.6f ETH, ROI=%.2f%%",
|
||||
float64(path.NetProfit.Int64())/1e18, path.ROI*100))
|
||||
go sas.executeOpportunity(multiHopOpp)
|
||||
}
|
||||
return nil // Successfully processed multi-hop paths
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: If multi-hop scan didn't find anything, process original opportunity
|
||||
sas.logger.Debug("No multi-hop paths found, processing original single-pool opportunity")
|
||||
|
||||
if path := sas.fallbackPathFromOpportunity(opp); path != nil {
|
||||
sas.storeOpportunityPath(opp.ID, path)
|
||||
}
|
||||
@@ -1686,7 +1779,12 @@ func (sas *ArbitrageService) SubmitBridgeOpportunity(ctx context.Context, bridge
|
||||
|
||||
atomic.AddInt64(&sas.stats.TotalOpportunitiesDetected, 1)
|
||||
|
||||
go sas.executeOpportunity(opp)
|
||||
// Only execute if it has positive profit
|
||||
if opp.NetProfit != nil && opp.NetProfit.Sign() > 0 {
|
||||
go sas.executeOpportunity(opp)
|
||||
} else {
|
||||
sas.logger.Debug("Skipping execution of zero-profit opportunity", "id", opp.ID)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user