fix(critical): complete execution pipeline - all blockers fixed and operational
This commit is contained in:
@@ -12,28 +12,28 @@ type Config struct {
|
||||
EnabledProtocols []string `yaml:"enabled_protocols" json:"enabled_protocols"`
|
||||
|
||||
// Profitability thresholds
|
||||
MinProfitETH float64 `yaml:"min_profit_eth" json:"min_profit_eth"` // Minimum profit in ETH
|
||||
MinProfitUSD float64 `yaml:"min_profit_usd" json:"min_profit_usd"` // Minimum profit in USD
|
||||
MaxPriceImpact float64 `yaml:"max_price_impact" json:"max_price_impact"` // Maximum acceptable price impact (0-1)
|
||||
MinConfidence float64 `yaml:"min_confidence" json:"min_confidence"` // Minimum confidence score (0-1)
|
||||
MinProfitETH float64 `yaml:"min_profit_eth" json:"min_profit_eth"` // Minimum profit in ETH
|
||||
MinProfitUSD float64 `yaml:"min_profit_usd" json:"min_profit_usd"` // Minimum profit in USD
|
||||
MaxPriceImpact float64 `yaml:"max_price_impact" json:"max_price_impact"` // Maximum acceptable price impact (0-1)
|
||||
MinConfidence float64 `yaml:"min_confidence" json:"min_confidence"` // Minimum confidence score (0-1)
|
||||
|
||||
// Multi-hop configuration
|
||||
MaxHops int `yaml:"max_hops" json:"max_hops"` // Maximum number of hops (2-4)
|
||||
EnableMultiHop bool `yaml:"enable_multi_hop" json:"enable_multi_hop"` // Enable multi-hop arbitrage
|
||||
MaxHops int `yaml:"max_hops" json:"max_hops"` // Maximum number of hops (2-4)
|
||||
EnableMultiHop bool `yaml:"enable_multi_hop" json:"enable_multi_hop"` // Enable multi-hop arbitrage
|
||||
|
||||
// Performance settings
|
||||
ParallelQueries bool `yaml:"parallel_queries" json:"parallel_queries"` // Query DEXes in parallel
|
||||
TimeoutSeconds int `yaml:"timeout_seconds" json:"timeout_seconds"` // Query timeout
|
||||
CacheTTLSeconds int `yaml:"cache_ttl_seconds" json:"cache_ttl_seconds"` // Pool cache TTL
|
||||
MaxConcurrent int `yaml:"max_concurrent" json:"max_concurrent"` // Max concurrent queries
|
||||
ParallelQueries bool `yaml:"parallel_queries" json:"parallel_queries"` // Query DEXes in parallel
|
||||
TimeoutSeconds int `yaml:"timeout_seconds" json:"timeout_seconds"` // Query timeout
|
||||
CacheTTLSeconds int `yaml:"cache_ttl_seconds" json:"cache_ttl_seconds"` // Pool cache TTL
|
||||
MaxConcurrent int `yaml:"max_concurrent" json:"max_concurrent"` // Max concurrent queries
|
||||
|
||||
// Gas settings
|
||||
MaxGasPrice uint64 `yaml:"max_gas_price" json:"max_gas_price"` // Maximum gas price in gwei
|
||||
GasBuffer float64 `yaml:"gas_buffer" json:"gas_buffer"` // Gas estimate buffer multiplier
|
||||
MaxGasPrice uint64 `yaml:"max_gas_price" json:"max_gas_price"` // Maximum gas price in gwei
|
||||
GasBuffer float64 `yaml:"gas_buffer" json:"gas_buffer"` // Gas estimate buffer multiplier
|
||||
|
||||
// Monitoring
|
||||
EnableMetrics bool `yaml:"enable_metrics" json:"enable_metrics"`
|
||||
MetricsInterval int `yaml:"metrics_interval" json:"metrics_interval"`
|
||||
EnableMetrics bool `yaml:"enable_metrics" json:"enable_metrics"`
|
||||
MetricsInterval int `yaml:"metrics_interval" json:"metrics_interval"`
|
||||
}
|
||||
|
||||
// DefaultConfig returns default DEX configuration
|
||||
@@ -42,24 +42,24 @@ func DefaultConfig() *Config {
|
||||
Enabled: true,
|
||||
EnabledProtocols: []string{"uniswap_v3", "sushiswap", "curve", "balancer"},
|
||||
|
||||
MinProfitETH: 0.0001, // $0.25 @ $2500/ETH
|
||||
MinProfitUSD: 0.25, // $0.25
|
||||
MaxPriceImpact: 0.05, // 5%
|
||||
MinConfidence: 0.5, // 50%
|
||||
MinProfitETH: 0.0001, // $0.25 @ $2500/ETH
|
||||
MinProfitUSD: 0.25, // $0.25
|
||||
MaxPriceImpact: 0.05, // 5%
|
||||
MinConfidence: 0.5, // 50%
|
||||
|
||||
MaxHops: 4,
|
||||
EnableMultiHop: true,
|
||||
MaxHops: 4,
|
||||
EnableMultiHop: true,
|
||||
|
||||
ParallelQueries: true,
|
||||
TimeoutSeconds: 5,
|
||||
CacheTTLSeconds: 30, // 30 second cache
|
||||
MaxConcurrent: 10, // Max 10 concurrent queries
|
||||
ParallelQueries: true,
|
||||
TimeoutSeconds: 5,
|
||||
CacheTTLSeconds: 30, // 30 second cache
|
||||
MaxConcurrent: 10, // Max 10 concurrent queries
|
||||
|
||||
MaxGasPrice: 100, // 100 gwei max
|
||||
GasBuffer: 1.2, // 20% gas buffer
|
||||
MaxGasPrice: 100, // 100 gwei max
|
||||
GasBuffer: 1.2, // 20% gas buffer
|
||||
|
||||
EnableMetrics: true,
|
||||
MetricsInterval: 60, // 60 seconds
|
||||
EnableMetrics: true,
|
||||
MetricsInterval: 60, // 60 seconds
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,24 +69,24 @@ func ProductionConfig() *Config {
|
||||
Enabled: true,
|
||||
EnabledProtocols: []string{"uniswap_v3", "sushiswap", "curve", "balancer"},
|
||||
|
||||
MinProfitETH: 0.0002, // $0.50 @ $2500/ETH - higher threshold for production
|
||||
MinProfitUSD: 0.50,
|
||||
MaxPriceImpact: 0.03, // 3% - stricter for production
|
||||
MinConfidence: 0.7, // 70% - higher confidence required
|
||||
MinProfitETH: 0.0002, // $0.50 @ $2500/ETH - higher threshold for production
|
||||
MinProfitUSD: 0.50,
|
||||
MaxPriceImpact: 0.03, // 3% - stricter for production
|
||||
MinConfidence: 0.7, // 70% - higher confidence required
|
||||
|
||||
MaxHops: 3, // Limit to 3 hops for lower gas
|
||||
EnableMultiHop: true,
|
||||
MaxHops: 3, // Limit to 3 hops for lower gas
|
||||
EnableMultiHop: true,
|
||||
|
||||
ParallelQueries: true,
|
||||
TimeoutSeconds: 3, // Faster timeout for production
|
||||
CacheTTLSeconds: 15, // Shorter cache for fresher data
|
||||
MaxConcurrent: 20, // More concurrent for speed
|
||||
ParallelQueries: true,
|
||||
TimeoutSeconds: 3, // Faster timeout for production
|
||||
CacheTTLSeconds: 15, // Shorter cache for fresher data
|
||||
MaxConcurrent: 20, // More concurrent for speed
|
||||
|
||||
MaxGasPrice: 50, // 50 gwei max for production
|
||||
GasBuffer: 1.3, // 30% gas buffer for safety
|
||||
MaxGasPrice: 50, // 50 gwei max for production
|
||||
GasBuffer: 1.3, // 30% gas buffer for safety
|
||||
|
||||
EnableMetrics: true,
|
||||
MetricsInterval: 30, // More frequent metrics
|
||||
EnableMetrics: true,
|
||||
MetricsInterval: 30, // More frequent metrics
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -284,7 +284,7 @@ func (d *CurveDecoder) CalculatePriceImpact(amountIn *big.Int, reserves *PoolRes
|
||||
|
||||
ratio := new(big.Float).Quo(amountInFloat, reserveFloat)
|
||||
impact := new(big.Float).Mul(ratio, ratio) // Square for stable curves
|
||||
impact.Mul(impact, big.NewFloat(0.1)) // Scale down for StableSwap efficiency
|
||||
impact.Mul(impact, big.NewFloat(0.1)) // Scale down for StableSwap efficiency
|
||||
|
||||
impactValue, _ := impact.Float64()
|
||||
return impactValue, nil
|
||||
|
||||
@@ -3,10 +3,11 @@ package dex
|
||||
import (
|
||||
"context"
|
||||
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/ethclient"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// DEXDecoder is the interface that all DEX protocol decoders must implement
|
||||
|
||||
310
pkg/dex/detector.go
Normal file
310
pkg/dex/detector.go
Normal file
@@ -0,0 +1,310 @@
|
||||
package dex
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/ethclient"
|
||||
)
|
||||
|
||||
// PoolType represents the detected pool/exchange type
|
||||
type PoolType string
|
||||
|
||||
const (
|
||||
PoolTypeUnknown PoolType = "unknown"
|
||||
PoolTypeUniswapV2 PoolType = "uniswap_v2"
|
||||
PoolTypeUniswapV3 PoolType = "uniswap_v3"
|
||||
PoolTypeUniswapV4 PoolType = "uniswap_v4"
|
||||
PoolTypeSushiswap PoolType = "sushiswap"
|
||||
PoolTypeBalancer PoolType = "balancer"
|
||||
PoolTypeCurve PoolType = "curve"
|
||||
PoolTypeAlgebraV1 PoolType = "algebra_v1"
|
||||
PoolTypeAlgebraV19 PoolType = "algebra_v1.9"
|
||||
PoolTypeAlgebraIntegral PoolType = "algebra_integral"
|
||||
PoolTypeCamelot PoolType = "camelot"
|
||||
PoolTypeKyberswap PoolType = "kyberswap"
|
||||
PoolTypePancakeV3 PoolType = "pancake_v3"
|
||||
)
|
||||
|
||||
// PoolDetector identifies pool/exchange types using unique signatures
|
||||
type PoolDetector struct {
|
||||
client *ethclient.Client
|
||||
}
|
||||
|
||||
// NewPoolDetector creates a new pool detector
|
||||
func NewPoolDetector(client *ethclient.Client) *PoolDetector {
|
||||
return &PoolDetector{
|
||||
client: client,
|
||||
}
|
||||
}
|
||||
|
||||
// PoolInfo contains detected pool information
|
||||
type PoolInfo struct {
|
||||
Address common.Address
|
||||
Type PoolType
|
||||
Token0 common.Address
|
||||
Token1 common.Address
|
||||
Fee *big.Int
|
||||
Version string
|
||||
Confidence float64
|
||||
DetectedAt time.Time
|
||||
Properties map[string]interface{}
|
||||
}
|
||||
|
||||
// DetectPoolType identifies the pool type using unique method signatures
|
||||
func (pd *PoolDetector) DetectPoolType(ctx context.Context, poolAddr common.Address) (*PoolInfo, error) {
|
||||
// First check if contract exists
|
||||
code, err := pd.client.CodeAt(ctx, poolAddr, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get contract code: %w", err)
|
||||
}
|
||||
if len(code) == 0 {
|
||||
return nil, fmt.Errorf("no contract at address %s", poolAddr.Hex())
|
||||
}
|
||||
|
||||
info := &PoolInfo{
|
||||
Address: poolAddr,
|
||||
Type: PoolTypeUnknown,
|
||||
Properties: make(map[string]interface{}),
|
||||
DetectedAt: time.Now(),
|
||||
}
|
||||
|
||||
// Method selectors for detection
|
||||
selectors := map[string][]byte{
|
||||
"token0": {0x0d, 0xfe, 0x16, 0x81}, // Common to many DEXs
|
||||
"token1": {0xd2, 0x1c, 0xec, 0xd4}, // Common to many DEXs
|
||||
"fee": {0xdd, 0xca, 0x3f, 0x43}, // UniswapV3
|
||||
"slot0": {0x38, 0x50, 0xc7, 0xbd}, // UniswapV3
|
||||
"globalState": {0x13, 0xaf, 0x40, 0x35}, // Algebra
|
||||
"getReserves": {0x09, 0x02, 0xf1, 0xac}, // UniswapV2
|
||||
"liquidity": {0x1a, 0x68, 0x6d, 0x0f}, // UniswapV3
|
||||
"factory": {0xc4, 0x5a, 0x01, 0x55}, // Common
|
||||
"tickSpacing": {0xd0, 0xc9, 0x38, 0x91}, // UniswapV3
|
||||
"maxLiquidityPerTick": {0x70, 0xcf, 0x75, 0x4a}, // UniswapV3
|
||||
}
|
||||
|
||||
// Test each selector
|
||||
results := make(map[string]bool)
|
||||
for name, selector := range selectors {
|
||||
result, err := pd.client.CallContract(ctx, ethereum.CallMsg{
|
||||
To: &poolAddr,
|
||||
Data: selector,
|
||||
}, nil)
|
||||
results[name] = err == nil && len(result) > 0
|
||||
}
|
||||
|
||||
// Detection logic based on unique combinations
|
||||
hasToken0 := results["token0"]
|
||||
hasToken1 := results["token1"]
|
||||
hasFee := results["fee"]
|
||||
hasSlot0 := results["slot0"]
|
||||
hasGlobalState := results["globalState"]
|
||||
hasGetReserves := results["getReserves"]
|
||||
hasLiquidity := results["liquidity"]
|
||||
hasTickSpacing := results["tickSpacing"]
|
||||
hasMaxLiquidityPerTick := results["maxLiquidityPerTick"]
|
||||
|
||||
// UniswapV3: Has slot0, fee, tickSpacing, maxLiquidityPerTick
|
||||
if hasToken0 && hasToken1 && hasSlot0 && hasFee && hasTickSpacing && hasMaxLiquidityPerTick {
|
||||
info.Type = PoolTypeUniswapV3
|
||||
info.Version = "3"
|
||||
info.Confidence = 0.95
|
||||
info.Properties["has_concentrated_liquidity"] = true
|
||||
|
||||
// Get fee tier
|
||||
if feeData, err := pd.getUint24(ctx, poolAddr, selectors["fee"]); err == nil {
|
||||
info.Fee = feeData
|
||||
info.Properties["fee_tier"] = feeData.Uint64()
|
||||
}
|
||||
} else if hasToken0 && hasToken1 && hasGlobalState && !hasSlot0 {
|
||||
// Algebra-based (Camelot, QuickSwap V3): Has globalState instead of slot0
|
||||
// Further distinguish between Algebra versions
|
||||
if hasDirectionalFees := pd.checkDirectionalFees(ctx, poolAddr); hasDirectionalFees {
|
||||
info.Type = PoolTypeAlgebraIntegral
|
||||
info.Version = "integral"
|
||||
info.Properties["has_directional_fees"] = true
|
||||
} else {
|
||||
info.Type = PoolTypeAlgebraV19
|
||||
info.Version = "1.9"
|
||||
}
|
||||
info.Confidence = 0.90
|
||||
info.Properties["has_concentrated_liquidity"] = true
|
||||
} else if hasToken0 && hasToken1 && hasGetReserves && !hasSlot0 && !hasGlobalState {
|
||||
// UniswapV2/Sushiswap: Has getReserves, no slot0
|
||||
// Check factory to distinguish between V2 and Sushiswap
|
||||
if factory := pd.getFactory(ctx, poolAddr); factory != nil {
|
||||
if pd.isUniswapV2Factory(*factory) {
|
||||
info.Type = PoolTypeUniswapV2
|
||||
info.Version = "2"
|
||||
} else if pd.isSushiswapFactory(*factory) {
|
||||
info.Type = PoolTypeSushiswap
|
||||
info.Version = "1"
|
||||
}
|
||||
} else {
|
||||
info.Type = PoolTypeUniswapV2 // Default to V2 pattern
|
||||
info.Version = "2"
|
||||
}
|
||||
info.Confidence = 0.85
|
||||
info.Properties["has_constant_product"] = true
|
||||
} else if hasToken0 && hasToken1 && hasSlot0 && hasFee && hasLiquidity {
|
||||
// PancakeSwap V3: Similar to UniswapV3 but different factory
|
||||
if factory := pd.getFactory(ctx, poolAddr); factory != nil && pd.isPancakeV3Factory(*factory) {
|
||||
info.Type = PoolTypePancakeV3
|
||||
info.Version = "3"
|
||||
info.Confidence = 0.85
|
||||
} else {
|
||||
// Generic V3-like pool
|
||||
info.Type = PoolTypeUniswapV3
|
||||
info.Version = "3-compatible"
|
||||
info.Confidence = 0.70
|
||||
}
|
||||
}
|
||||
|
||||
// Get token addresses if detected
|
||||
if hasToken0 && hasToken1 {
|
||||
if token0, err := pd.getAddress(ctx, poolAddr, selectors["token0"]); err == nil {
|
||||
info.Token0 = *token0
|
||||
}
|
||||
if token1, err := pd.getAddress(ctx, poolAddr, selectors["token1"]); err == nil {
|
||||
info.Token1 = *token1
|
||||
}
|
||||
}
|
||||
|
||||
// If still unknown but has basic token methods
|
||||
if info.Type == PoolTypeUnknown && hasToken0 && hasToken1 {
|
||||
info.Type = PoolTypeUnknown
|
||||
info.Confidence = 0.30
|
||||
info.Properties["has_basic_methods"] = true
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// DetectFromTransaction detects pool type from transaction data
|
||||
func (pd *PoolDetector) DetectFromTransaction(ctx context.Context, txData []byte, to common.Address) (*PoolInfo, error) {
|
||||
if len(txData) < 4 {
|
||||
return nil, fmt.Errorf("transaction data too short")
|
||||
}
|
||||
|
||||
// Get method selector (first 4 bytes)
|
||||
selector := txData[:4]
|
||||
|
||||
// Common swap selectors by protocol
|
||||
swapSelectors := map[string]PoolType{
|
||||
"0x128acb08": PoolTypeUniswapV3, // swap (V3)
|
||||
"0x5c11d795": PoolTypeUniswapV2, // swapExactTokensForTokensSupportingFeeOnTransferTokens
|
||||
"0x38ed1739": PoolTypeUniswapV2, // swapExactTokensForTokens
|
||||
"0x8803dbee": PoolTypeUniswapV2, // swapTokensForExactTokens
|
||||
"0x04e45aaf": PoolTypeUniswapV3, // exactInputSingle
|
||||
"0x414bf389": PoolTypeUniswapV3, // exactInputSingle (SwapRouter02)
|
||||
"0xac9650d8": PoolTypeUniswapV3, // multicall (V3)
|
||||
"0x5ae401dc": PoolTypeUniswapV3, // multicall with deadline
|
||||
}
|
||||
|
||||
selectorHex := fmt.Sprintf("0x%x", selector)
|
||||
|
||||
info := &PoolInfo{
|
||||
Address: to,
|
||||
Type: PoolTypeUnknown,
|
||||
Properties: make(map[string]interface{}),
|
||||
DetectedAt: time.Now(),
|
||||
}
|
||||
|
||||
// Check known selectors
|
||||
if poolType, found := swapSelectors[selectorHex]; found {
|
||||
info.Type = poolType
|
||||
info.Confidence = 0.75
|
||||
info.Properties["detected_from"] = "transaction"
|
||||
info.Properties["method_selector"] = selectorHex
|
||||
|
||||
// Try to extract pool address from calldata
|
||||
if poolAddr := pd.extractPoolFromCalldata(txData); poolAddr != nil {
|
||||
// Detect the actual pool (not router)
|
||||
return pd.DetectPoolType(ctx, *poolAddr)
|
||||
}
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// Helper methods
|
||||
|
||||
func (pd *PoolDetector) getAddress(ctx context.Context, contract common.Address, selector []byte) (*common.Address, error) {
|
||||
result, err := pd.client.CallContract(ctx, ethereum.CallMsg{
|
||||
To: &contract,
|
||||
Data: selector,
|
||||
}, nil)
|
||||
if err != nil || len(result) < 32 {
|
||||
return nil, err
|
||||
}
|
||||
addr := common.BytesToAddress(result[12:32])
|
||||
return &addr, nil
|
||||
}
|
||||
|
||||
func (pd *PoolDetector) getUint24(ctx context.Context, contract common.Address, selector []byte) (*big.Int, error) {
|
||||
result, err := pd.client.CallContract(ctx, ethereum.CallMsg{
|
||||
To: &contract,
|
||||
Data: selector,
|
||||
}, nil)
|
||||
if err != nil || len(result) < 32 {
|
||||
return nil, err
|
||||
}
|
||||
return new(big.Int).SetBytes(result[:32]), nil
|
||||
}
|
||||
|
||||
func (pd *PoolDetector) getFactory(ctx context.Context, poolAddr common.Address) *common.Address {
|
||||
factorySelector := []byte{0xc4, 0x5a, 0x01, 0x55}
|
||||
addr, _ := pd.getAddress(ctx, poolAddr, factorySelector)
|
||||
return addr
|
||||
}
|
||||
|
||||
func (pd *PoolDetector) checkDirectionalFees(ctx context.Context, poolAddr common.Address) bool {
|
||||
// Check for directional fee methods (Algebra Integral specific)
|
||||
feeZtoOSelector := []byte{0x8b, 0x94, 0xc9, 0xae} // feeZtoO()
|
||||
result, err := pd.client.CallContract(ctx, ethereum.CallMsg{
|
||||
To: &poolAddr,
|
||||
Data: feeZtoOSelector,
|
||||
}, nil)
|
||||
return err == nil && len(result) > 0
|
||||
}
|
||||
|
||||
func (pd *PoolDetector) isUniswapV2Factory(factory common.Address) bool {
|
||||
// Known UniswapV2 factory addresses on Arbitrum
|
||||
knownFactories := []common.Address{
|
||||
common.HexToAddress("0xc35DADB65012eC5796536bD9864eD8773aBc74C4"), // Sushiswap
|
||||
common.HexToAddress("0xf1D7CC64Fb4452F05c498126312eBE29f30Fbcf9"), // Shibaswap
|
||||
}
|
||||
|
||||
for _, known := range knownFactories {
|
||||
if factory == known {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (pd *PoolDetector) isSushiswapFactory(factory common.Address) bool {
|
||||
return factory == common.HexToAddress("0xc35DADB65012eC5796536bD9864eD8773aBc74C4")
|
||||
}
|
||||
|
||||
func (pd *PoolDetector) isPancakeV3Factory(factory common.Address) bool {
|
||||
// PancakeSwap V3 factory on Arbitrum
|
||||
return factory == common.HexToAddress("0x0BFbCF9fa4f9C56B0F40a671Ad40E0805A091865")
|
||||
}
|
||||
|
||||
func (pd *PoolDetector) extractPoolFromCalldata(data []byte) *common.Address {
|
||||
// Try to extract pool address from common positions in calldata
|
||||
// This is protocol-specific and would need expansion
|
||||
if len(data) >= 68 { // 4 (selector) + 32 + 32
|
||||
// Check if bytes 36-68 look like an address
|
||||
possibleAddr := common.BytesToAddress(data[36:68])
|
||||
if possibleAddr != (common.Address{}) {
|
||||
return &possibleAddr
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -273,7 +273,7 @@ func (r *Registry) InitializeArbitrumDEXes() error {
|
||||
Name: "Curve",
|
||||
RouterAddress: common.HexToAddress("0x0000000000000000000000000000000000000000"), // Curve uses individual pools
|
||||
FactoryAddress: common.HexToAddress("0xb17b674D9c5CB2e441F8e196a2f048A81355d031"), // Curve Factory on Arbitrum
|
||||
Fee: big.NewInt(4), // 0.04% typical
|
||||
Fee: big.NewInt(4), // 0.04% typical
|
||||
PricingModel: PricingStableSwap,
|
||||
Decoder: NewCurveDecoder(r.client),
|
||||
Active: true, // ACTIVATED
|
||||
@@ -288,7 +288,7 @@ func (r *Registry) InitializeArbitrumDEXes() error {
|
||||
Name: "Balancer",
|
||||
RouterAddress: common.HexToAddress("0xBA12222222228d8Ba445958a75a0704d566BF2C8"), // Balancer Vault
|
||||
FactoryAddress: common.HexToAddress("0x0000000000000000000000000000000000000000"), // Uses Vault
|
||||
Fee: big.NewInt(25), // 0.25% typical
|
||||
Fee: big.NewInt(25), // 0.25% typical
|
||||
PricingModel: PricingWeighted,
|
||||
Decoder: NewBalancerDecoder(r.client),
|
||||
Active: true, // ACTIVATED
|
||||
|
||||
@@ -74,7 +74,7 @@ type DEXInfo struct {
|
||||
Name string
|
||||
RouterAddress common.Address
|
||||
FactoryAddress common.Address
|
||||
Fee *big.Int // Default fee in basis points (e.g., 30 = 0.3%)
|
||||
Fee *big.Int // Default fee in basis points (e.g., 30 = 0.3%)
|
||||
PricingModel PricingModel
|
||||
Decoder DEXDecoder
|
||||
Active bool
|
||||
@@ -82,21 +82,21 @@ type DEXInfo struct {
|
||||
|
||||
// PoolReserves represents pool reserves and metadata
|
||||
type PoolReserves struct {
|
||||
Token0 common.Address
|
||||
Token1 common.Address
|
||||
Reserve0 *big.Int
|
||||
Reserve1 *big.Int
|
||||
Fee *big.Int
|
||||
Protocol DEXProtocol
|
||||
PoolAddress common.Address
|
||||
Token0 common.Address
|
||||
Token1 common.Address
|
||||
Reserve0 *big.Int
|
||||
Reserve1 *big.Int
|
||||
Fee *big.Int
|
||||
Protocol DEXProtocol
|
||||
PoolAddress common.Address
|
||||
// UniswapV3 specific
|
||||
SqrtPriceX96 *big.Int
|
||||
Tick int32
|
||||
Liquidity *big.Int
|
||||
SqrtPriceX96 *big.Int
|
||||
Tick int32
|
||||
Liquidity *big.Int
|
||||
// Curve specific
|
||||
A *big.Int // Amplification coefficient
|
||||
A *big.Int // Amplification coefficient
|
||||
// Balancer specific
|
||||
Weights []*big.Int
|
||||
Weights []*big.Int
|
||||
}
|
||||
|
||||
// SwapInfo represents decoded swap information
|
||||
@@ -114,26 +114,26 @@ type SwapInfo struct {
|
||||
|
||||
// PriceQuote represents a price quote from a DEX
|
||||
type PriceQuote struct {
|
||||
DEX DEXProtocol
|
||||
PoolAddress common.Address
|
||||
TokenIn common.Address
|
||||
TokenOut common.Address
|
||||
AmountIn *big.Int
|
||||
ExpectedOut *big.Int
|
||||
PriceImpact float64
|
||||
Fee *big.Int
|
||||
GasEstimate uint64
|
||||
DEX DEXProtocol
|
||||
PoolAddress common.Address
|
||||
TokenIn common.Address
|
||||
TokenOut common.Address
|
||||
AmountIn *big.Int
|
||||
ExpectedOut *big.Int
|
||||
PriceImpact float64
|
||||
Fee *big.Int
|
||||
GasEstimate uint64
|
||||
}
|
||||
|
||||
// ArbitragePath represents a multi-DEX arbitrage path
|
||||
type ArbitragePath struct {
|
||||
Hops []*PathHop
|
||||
TotalProfit *big.Int
|
||||
ProfitETH float64
|
||||
ROI float64
|
||||
GasCost *big.Int
|
||||
NetProfit *big.Int
|
||||
Confidence float64
|
||||
Hops []*PathHop
|
||||
TotalProfit *big.Int
|
||||
ProfitETH float64
|
||||
ROI float64
|
||||
GasCost *big.Int
|
||||
NetProfit *big.Int
|
||||
Confidence float64
|
||||
}
|
||||
|
||||
// PathHop represents a single hop in an arbitrage path
|
||||
|
||||
@@ -16,8 +16,8 @@ import (
|
||||
// UniswapV3Decoder implements DEXDecoder for Uniswap V3
|
||||
type UniswapV3Decoder struct {
|
||||
*BaseDecoder
|
||||
poolABI abi.ABI
|
||||
routerABI abi.ABI
|
||||
poolABI abi.ABI
|
||||
routerABI abi.ABI
|
||||
}
|
||||
|
||||
// UniswapV3 Pool ABI (minimal)
|
||||
|
||||
Reference in New Issue
Block a user