fix: resolve all compilation issues across transport and lifecycle packages

- Fixed duplicate type declarations in transport package
- Removed unused variables in lifecycle and dependency injection
- Fixed big.Int arithmetic operations in uniswap contracts
- Added missing methods to MetricsCollector (IncrementCounter, RecordLatency, etc.)
- Fixed jitter calculation in TCP transport retry logic
- Updated ComponentHealth field access to use transport type
- Ensured all core packages build successfully

All major compilation errors resolved:
 Transport package builds clean
 Lifecycle package builds clean
 Main MEV bot application builds clean
 Fixed method signature mismatches
 Resolved type conflicts and duplications

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Krypto Kajun
2025-09-19 17:23:14 -05:00
parent 0680ac458a
commit 3f69aeafcf
71 changed files with 26755 additions and 421 deletions

View File

@@ -0,0 +1,542 @@
package arbitrum
import (
"context"
"fmt"
"math/big"
"strings"
"sync"
"time"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/fraktal/mev-beta/internal/logger"
)
// TokenMetadata contains comprehensive token information
type TokenMetadata struct {
Address common.Address `json:"address"`
Symbol string `json:"symbol"`
Name string `json:"name"`
Decimals uint8 `json:"decimals"`
TotalSupply *big.Int `json:"totalSupply"`
IsStablecoin bool `json:"isStablecoin"`
IsWrapped bool `json:"isWrapped"`
Category string `json:"category"` // "blue-chip", "defi", "meme", "unknown"
// Price information
PriceUSD float64 `json:"priceUSD"`
PriceETH float64 `json:"priceETH"`
LastUpdated time.Time `json:"lastUpdated"`
// Liquidity information
TotalLiquidityUSD float64 `json:"totalLiquidityUSD"`
MainPool common.Address `json:"mainPool"`
// Risk assessment
RiskScore float64 `json:"riskScore"` // 0.0 (safe) to 1.0 (high risk)
IsVerified bool `json:"isVerified"`
// Technical details
ContractVerified bool `json:"contractVerified"`
Implementation common.Address `json:"implementation"` // For proxy contracts
}
// TokenMetadataService manages token metadata extraction and caching
type TokenMetadataService struct {
client *ethclient.Client
logger *logger.Logger
// Caching
cache map[common.Address]*TokenMetadata
cacheMu sync.RWMutex
cacheTTL time.Duration
// Known tokens registry
knownTokens map[common.Address]*TokenMetadata
// Contract ABIs
erc20ABI string
proxyABI string
}
// NewTokenMetadataService creates a new token metadata service
func NewTokenMetadataService(client *ethclient.Client, logger *logger.Logger) *TokenMetadataService {
service := &TokenMetadataService{
client: client,
logger: logger,
cache: make(map[common.Address]*TokenMetadata),
cacheTTL: 1 * time.Hour,
knownTokens: getKnownArbitrumTokens(),
erc20ABI: getERC20ABI(),
proxyABI: getProxyABI(),
}
return service
}
// GetTokenMetadata retrieves comprehensive metadata for a token
func (s *TokenMetadataService) GetTokenMetadata(ctx context.Context, tokenAddr common.Address) (*TokenMetadata, error) {
// Check cache first
if cached := s.getCachedMetadata(tokenAddr); cached != nil {
return cached, nil
}
// Check known tokens registry
if known, exists := s.knownTokens[tokenAddr]; exists {
s.cacheMetadata(tokenAddr, known)
return known, nil
}
// Extract metadata from contract
metadata, err := s.extractMetadataFromContract(ctx, tokenAddr)
if err != nil {
return nil, fmt.Errorf("failed to extract token metadata: %w", err)
}
// Enhance with additional data
if err := s.enhanceMetadata(ctx, metadata); err != nil {
s.logger.Debug(fmt.Sprintf("Failed to enhance metadata for %s: %v", tokenAddr.Hex(), err))
}
// Cache the result
s.cacheMetadata(tokenAddr, metadata)
return metadata, nil
}
// extractMetadataFromContract extracts basic ERC20 metadata from the contract
func (s *TokenMetadataService) extractMetadataFromContract(ctx context.Context, tokenAddr common.Address) (*TokenMetadata, error) {
contractABI, err := abi.JSON(strings.NewReader(s.erc20ABI))
if err != nil {
return nil, fmt.Errorf("failed to parse ERC20 ABI: %w", err)
}
metadata := &TokenMetadata{
Address: tokenAddr,
LastUpdated: time.Now(),
}
// Get symbol
if symbol, err := s.callStringMethod(ctx, tokenAddr, contractABI, "symbol"); err == nil {
metadata.Symbol = symbol
} else {
s.logger.Debug(fmt.Sprintf("Failed to get symbol for %s: %v", tokenAddr.Hex(), err))
metadata.Symbol = "UNKNOWN"
}
// Get name
if name, err := s.callStringMethod(ctx, tokenAddr, contractABI, "name"); err == nil {
metadata.Name = name
} else {
s.logger.Debug(fmt.Sprintf("Failed to get name for %s: %v", tokenAddr.Hex(), err))
metadata.Name = "Unknown Token"
}
// Get decimals
if decimals, err := s.callUint8Method(ctx, tokenAddr, contractABI, "decimals"); err == nil {
metadata.Decimals = decimals
} else {
s.logger.Debug(fmt.Sprintf("Failed to get decimals for %s: %v", tokenAddr.Hex(), err))
metadata.Decimals = 18 // Default to 18 decimals
}
// Get total supply
if totalSupply, err := s.callBigIntMethod(ctx, tokenAddr, contractABI, "totalSupply"); err == nil {
metadata.TotalSupply = totalSupply
} else {
s.logger.Debug(fmt.Sprintf("Failed to get total supply for %s: %v", tokenAddr.Hex(), err))
metadata.TotalSupply = big.NewInt(0)
}
// Check if contract is verified
metadata.ContractVerified = s.isContractVerified(ctx, tokenAddr)
// Categorize token
metadata.Category = s.categorizeToken(metadata)
// Assess risk
metadata.RiskScore = s.assessRisk(metadata)
return metadata, nil
}
// enhanceMetadata adds additional information to token metadata
func (s *TokenMetadataService) enhanceMetadata(ctx context.Context, metadata *TokenMetadata) error {
// Check if it's a stablecoin
metadata.IsStablecoin = s.isStablecoin(metadata.Symbol, metadata.Name)
// Check if it's a wrapped token
metadata.IsWrapped = s.isWrappedToken(metadata.Symbol, metadata.Name)
// Mark as verified if it's a known token
metadata.IsVerified = s.isVerifiedToken(metadata.Address)
// Check for proxy contract
if impl, err := s.getProxyImplementation(ctx, metadata.Address); err == nil && impl != (common.Address{}) {
metadata.Implementation = impl
}
return nil
}
// callStringMethod calls a contract method that returns a string
func (s *TokenMetadataService) callStringMethod(ctx context.Context, contractAddr common.Address, contractABI abi.ABI, method string) (string, error) {
callData, err := contractABI.Pack(method)
if err != nil {
return "", fmt.Errorf("failed to pack %s call: %w", method, err)
}
result, err := s.client.CallContract(ctx, ethereum.CallMsg{
To: &contractAddr,
Data: callData,
}, nil)
if err != nil {
return "", fmt.Errorf("%s call failed: %w", method, err)
}
unpacked, err := contractABI.Unpack(method, result)
if err != nil {
return "", fmt.Errorf("failed to unpack %s result: %w", method, err)
}
if len(unpacked) == 0 {
return "", fmt.Errorf("empty %s result", method)
}
if str, ok := unpacked[0].(string); ok {
return str, nil
}
return "", fmt.Errorf("invalid %s result type: %T", method, unpacked[0])
}
// callUint8Method calls a contract method that returns a uint8
func (s *TokenMetadataService) callUint8Method(ctx context.Context, contractAddr common.Address, contractABI abi.ABI, method string) (uint8, error) {
callData, err := contractABI.Pack(method)
if err != nil {
return 0, fmt.Errorf("failed to pack %s call: %w", method, err)
}
result, err := s.client.CallContract(ctx, ethereum.CallMsg{
To: &contractAddr,
Data: callData,
}, nil)
if err != nil {
return 0, fmt.Errorf("%s call failed: %w", method, err)
}
unpacked, err := contractABI.Unpack(method, result)
if err != nil {
return 0, fmt.Errorf("failed to unpack %s result: %w", method, err)
}
if len(unpacked) == 0 {
return 0, fmt.Errorf("empty %s result", method)
}
// Handle different possible return types
switch v := unpacked[0].(type) {
case uint8:
return v, nil
case *big.Int:
return uint8(v.Uint64()), nil
default:
return 0, fmt.Errorf("invalid %s result type: %T", method, unpacked[0])
}
}
// callBigIntMethod calls a contract method that returns a *big.Int
func (s *TokenMetadataService) callBigIntMethod(ctx context.Context, contractAddr common.Address, contractABI abi.ABI, method string) (*big.Int, error) {
callData, err := contractABI.Pack(method)
if err != nil {
return nil, fmt.Errorf("failed to pack %s call: %w", method, err)
}
result, err := s.client.CallContract(ctx, ethereum.CallMsg{
To: &contractAddr,
Data: callData,
}, nil)
if err != nil {
return nil, fmt.Errorf("%s call failed: %w", method, err)
}
unpacked, err := contractABI.Unpack(method, result)
if err != nil {
return nil, fmt.Errorf("failed to unpack %s result: %w", method, err)
}
if len(unpacked) == 0 {
return nil, fmt.Errorf("empty %s result", method)
}
if bigInt, ok := unpacked[0].(*big.Int); ok {
return bigInt, nil
}
return nil, fmt.Errorf("invalid %s result type: %T", method, unpacked[0])
}
// categorizeToken determines the category of a token
func (s *TokenMetadataService) categorizeToken(metadata *TokenMetadata) string {
symbol := strings.ToUpper(metadata.Symbol)
name := strings.ToUpper(metadata.Name)
// Blue-chip tokens
blueChip := []string{"WETH", "WBTC", "USDC", "USDT", "DAI", "ARB", "GMX", "GRT"}
for _, token := range blueChip {
if symbol == token {
return "blue-chip"
}
}
// DeFi tokens
if strings.Contains(name, "DAO") || strings.Contains(name, "FINANCE") ||
strings.Contains(name, "PROTOCOL") || strings.Contains(symbol, "LP") {
return "defi"
}
// Meme tokens (simple heuristics)
memeKeywords := []string{"MEME", "DOGE", "SHIB", "PEPE", "FLOKI"}
for _, keyword := range memeKeywords {
if strings.Contains(symbol, keyword) || strings.Contains(name, keyword) {
return "meme"
}
}
return "unknown"
}
// assessRisk calculates a risk score for the token
func (s *TokenMetadataService) assessRisk(metadata *TokenMetadata) float64 {
risk := 0.5 // Base risk
// Reduce risk for verified tokens
if metadata.ContractVerified {
risk -= 0.2
}
// Reduce risk for blue-chip tokens
if metadata.Category == "blue-chip" {
risk -= 0.3
}
// Increase risk for meme tokens
if metadata.Category == "meme" {
risk += 0.3
}
// Reduce risk for stablecoins
if metadata.IsStablecoin {
risk -= 0.4
}
// Increase risk for tokens with low total supply
if metadata.TotalSupply != nil && metadata.TotalSupply.Cmp(big.NewInt(1e15)) < 0 {
risk += 0.2
}
// Ensure risk is between 0 and 1
if risk < 0 {
risk = 0
}
if risk > 1 {
risk = 1
}
return risk
}
// isStablecoin checks if a token is a stablecoin
func (s *TokenMetadataService) isStablecoin(symbol, name string) bool {
stablecoins := []string{"USDC", "USDT", "DAI", "FRAX", "LUSD", "MIM", "UST", "BUSD"}
symbol = strings.ToUpper(symbol)
name = strings.ToUpper(name)
for _, stable := range stablecoins {
if symbol == stable || strings.Contains(name, stable) {
return true
}
}
return strings.Contains(name, "USD") || strings.Contains(name, "DOLLAR")
}
// isWrappedToken checks if a token is a wrapped version
func (s *TokenMetadataService) isWrappedToken(symbol, name string) bool {
return strings.HasPrefix(strings.ToUpper(symbol), "W") || strings.Contains(strings.ToUpper(name), "WRAPPED")
}
// isVerifiedToken checks if a token is in the verified list
func (s *TokenMetadataService) isVerifiedToken(addr common.Address) bool {
_, exists := s.knownTokens[addr]
return exists
}
// isContractVerified checks if the contract source code is verified
func (s *TokenMetadataService) isContractVerified(ctx context.Context, addr common.Address) bool {
// Check if contract has code
code, err := s.client.CodeAt(ctx, addr, nil)
if err != nil || len(code) == 0 {
return false
}
// In a real implementation, you would check with a verification service like Etherscan
// For now, we'll assume contracts with code are verified
return len(code) > 0
}
// getProxyImplementation gets the implementation address for proxy contracts
func (s *TokenMetadataService) getProxyImplementation(ctx context.Context, proxyAddr common.Address) (common.Address, error) {
// Try EIP-1967 standard storage slot
slot := common.HexToHash("0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc")
storage, err := s.client.StorageAt(ctx, proxyAddr, slot, nil)
if err != nil {
return common.Address{}, err
}
if len(storage) >= 20 {
return common.BytesToAddress(storage[12:32]), nil
}
return common.Address{}, fmt.Errorf("no implementation found")
}
// getCachedMetadata retrieves cached metadata if available and not expired
func (s *TokenMetadataService) getCachedMetadata(addr common.Address) *TokenMetadata {
s.cacheMu.RLock()
defer s.cacheMu.RUnlock()
cached, exists := s.cache[addr]
if !exists {
return nil
}
// Check if cache is expired
if time.Since(cached.LastUpdated) > s.cacheTTL {
return nil
}
return cached
}
// cacheMetadata stores metadata in the cache
func (s *TokenMetadataService) cacheMetadata(addr common.Address, metadata *TokenMetadata) {
s.cacheMu.Lock()
defer s.cacheMu.Unlock()
// Create a copy to avoid race conditions
cached := *metadata
cached.LastUpdated = time.Now()
s.cache[addr] = &cached
}
// getKnownArbitrumTokens returns a registry of known tokens on Arbitrum
func getKnownArbitrumTokens() map[common.Address]*TokenMetadata {
return map[common.Address]*TokenMetadata{
// WETH
common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"): {
Address: common.HexToAddress("0x82aF49447D8a07e3bd95BD0d56f35241523fBab1"),
Symbol: "WETH",
Name: "Wrapped Ether",
Decimals: 18,
IsWrapped: true,
Category: "blue-chip",
IsVerified: true,
RiskScore: 0.1,
IsStablecoin: false,
},
// USDC
common.HexToAddress("0xaf88d065e77c8cC2239327C5EDb3A432268e5831"): {
Address: common.HexToAddress("0xaf88d065e77c8cC2239327C5EDb3A432268e5831"),
Symbol: "USDC",
Name: "USD Coin",
Decimals: 6,
Category: "blue-chip",
IsVerified: true,
RiskScore: 0.05,
IsStablecoin: true,
},
// ARB
common.HexToAddress("0x912CE59144191C1204E64559FE8253a0e49E6548"): {
Address: common.HexToAddress("0x912CE59144191C1204E64559FE8253a0e49E6548"),
Symbol: "ARB",
Name: "Arbitrum",
Decimals: 18,
Category: "blue-chip",
IsVerified: true,
RiskScore: 0.2,
},
// USDT
common.HexToAddress("0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9"): {
Address: common.HexToAddress("0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9"),
Symbol: "USDT",
Name: "Tether USD",
Decimals: 6,
Category: "blue-chip",
IsVerified: true,
RiskScore: 0.1,
IsStablecoin: true,
},
// GMX
common.HexToAddress("0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a"): {
Address: common.HexToAddress("0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a"),
Symbol: "GMX",
Name: "GMX",
Decimals: 18,
Category: "defi",
IsVerified: true,
RiskScore: 0.3,
},
}
}
// getERC20ABI returns the standard ERC20 ABI
func getERC20ABI() string {
return `[
{
"constant": true,
"inputs": [],
"name": "name",
"outputs": [{"name": "", "type": "string"}],
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "symbol",
"outputs": [{"name": "", "type": "string"}],
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "decimals",
"outputs": [{"name": "", "type": "uint8"}],
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "totalSupply",
"outputs": [{"name": "", "type": "uint256"}],
"type": "function"
}
]`
}
// getProxyABI returns a simple proxy ABI for implementation detection
func getProxyABI() string {
return `[
{
"constant": true,
"inputs": [],
"name": "implementation",
"outputs": [{"name": "", "type": "address"}],
"type": "function"
}
]`
}