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:
Krypto Kajun
2025-10-29 04:39:40 -05:00
parent 2fa6d128d7
commit 703f551bd4
2 changed files with 107 additions and 5 deletions

View File

@@ -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
}