Quote System

The IXFI Protocol's quote system provides real-time, accurate pricing information across all supported DEXes and chains. It aggregates quotes from multiple sources, accounts for gas costs, and provides execution guarantees.

Overview

The quote system serves as the pricing engine for the IXFI Protocol, offering:

  1. Multi-source aggregation from 35+ DEXes across 8+ chains

  2. Real-time price discovery with sub-second latency

  3. Gas-adjusted quotes including transaction costs

  4. Execution guarantees with slippage protection

  5. Quote comparison across different routes and DEXes

Architecture

Core Components

class IXFIQuoteSystem {
    constructor() {
        this.quoteSources = new Map(); // dexName -> QuoteSource
        this.priceCache = new PriceCache();
        this.gasOracle = new GasOracle();
        this.slippageCalculator = new SlippageCalculator();
        this.routeOptimizer = new RouteOptimizer();
    }

    async getQuote(request) {
        const {
            fromToken,
            toToken,
            amountIn,
            fromChain,
            toChain,
            slippageTolerance = 0.005, // 0.5% default
            gasPrice,
            includeGasCosts = true,
            preferredDEXes = [],
            maxHops = 3
        } = request;

        // Validate input parameters
        this.validateQuoteRequest(request);

        // Get quotes from all relevant sources
        const quotes = await this.aggregateQuotes(request);

        // Filter and rank quotes
        const rankedQuotes = await this.rankQuotes(quotes, request);

        // Return best quotes with detailed breakdown
        return {
            bestQuote: rankedQuotes[0],
            alternativeQuotes: rankedQuotes.slice(1, 5),
            marketAnalysis: await this.getMarketAnalysis(request),
            timestamp: Date.now(),
            validUntil: Date.now() + 30000 // 30 seconds
        };
    }

    async aggregateQuotes(request) {
        const { fromToken, toToken, fromChain, toChain } = request;
        const quotePromises = [];

        // Same chain quotes - direct DEX swaps
        if (fromChain === toChain) {
            const chainDEXes = this.getChainDEXes(fromChain);
            
            for (const dex of chainDEXes) {
                if (await this.supportsPair(dex, fromToken, toToken)) {
                    quotePromises.push(
                        this.getDirectQuote(dex, request)
                    );
                }
            }

            // Multi-hop quotes on same chain
            if (request.maxHops > 1) {
                quotePromises.push(
                    this.getMultiHopQuotes(request)
                );
            }
        } else {
            // Cross-chain quotes
            quotePromises.push(
                this.getCrossChainQuotes(request)
            );
        }

        // Execute all quote requests in parallel
        const results = await Promise.allSettled(quotePromises);
        
        return results
            .filter(result => result.status === 'fulfilled')
            .map(result => result.value)
            .flat()
            .filter(quote => quote && quote.outputAmount > 0);
    }

    async getDirectQuote(dex, request) {
        try {
            const source = this.quoteSources.get(dex.name);
            if (!source) {
                throw new Error(`No quote source for DEX: ${dex.name}`);
            }

            const rawQuote = await source.getQuote(
                request.fromToken,
                request.toToken,
                request.amountIn,
                request.fromChain
            );

            return this.enrichQuote(rawQuote, dex, request);

        } catch (error) {
            console.warn(`Failed to get quote from ${dex.name}:`, error.message);
            return null;
        }
    }

    async enrichQuote(rawQuote, dex, request) {
        const enrichedQuote = {
            ...rawQuote,
            dexName: dex.name,
            dexType: dex.type,
            chainId: request.fromChain,
            route: 'DIRECT',
            timestamp: Date.now()
        };

        // Add gas cost estimation
        if (request.includeGasCosts) {
            const gasEstimate = await this.estimateGasCost(dex, request);
            enrichedQuote.gasCost = gasEstimate;
            enrichedQuote.netOutputAmount = enrichedQuote.outputAmount - gasEstimate.usdValue;
        }

        // Add slippage analysis
        enrichedQuote.slippageAnalysis = await this.analyzeSlippage(dex, request);

        // Add execution probability
        enrichedQuote.executionProbability = await this.calculateExecutionProbability(dex, request);

        // Add route breakdown
        enrichedQuote.routeBreakdown = [{
            step: 1,
            dex: dex.name,
            fromToken: request.fromToken,
            toToken: request.toToken,
            inputAmount: request.amountIn,
            outputAmount: enrichedQuote.outputAmount,
            fee: enrichedQuote.fee,
            priceImpact: enrichedQuote.priceImpact
        }];

        return enrichedQuote;
    }

    async getMultiHopQuotes(request) {
        const intermediateTokens = await this.getIntermediateTokens(request.fromChain);
        const multiHopQuotes = [];

        for (const intermediateToken of intermediateTokens) {
            try {
                // First hop: fromToken -> intermediateToken
                const firstHopQuotes = await this.getHopQuotes(
                    request.fromToken,
                    intermediateToken,
                    request.amountIn,
                    request.fromChain
                );

                for (const firstHop of firstHopQuotes) {
                    // Second hop: intermediateToken -> toToken
                    const secondHopQuotes = await this.getHopQuotes(
                        intermediateToken,
                        request.toToken,
                        firstHop.outputAmount,
                        request.fromChain
                    );

                    for (const secondHop of secondHopQuotes) {
                        // Skip if using same DEX twice (unless it's beneficial)
                        if (firstHop.dexName === secondHop.dexName && 
                            !this.isBeneficialSameDEX(firstHop, secondHop)) {
                            continue;
                        }

                        const multiHopQuote = this.combineHops([firstHop, secondHop], request);
                        if (multiHopQuote.outputAmount > 0) {
                            multiHopQuotes.push(multiHopQuote);
                        }
                    }
                }
            } catch (error) {
                console.warn(`Multi-hop quote failed for ${intermediateToken}:`, error.message);
            }
        }

        return multiHopQuotes;
    }

    async getCrossChainQuotes(request) {
        const crossChainQuotes = [];
        const bridges = await this.getAvailableBridges(request.fromChain, request.toChain);

        for (const bridge of bridges) {
            try {
                // Option 1: Swap then bridge
                const swapThenBridge = await this.getSwapThenBridgeQuote(bridge, request);
                if (swapThenBridge) {
                    crossChainQuotes.push(swapThenBridge);
                }

                // Option 2: Bridge then swap
                const bridgeThenSwap = await this.getBridgeThenSwapQuote(bridge, request);
                if (bridgeThenSwap) {
                    crossChainQuotes.push(bridgeThenSwap);
                }

                // Option 3: Bridge native asset (if applicable)
                if (this.isNativeAsset(request.fromToken) || this.isNativeAsset(request.toToken)) {
                    const nativeBridge = await this.getNativeBridgeQuote(bridge, request);
                    if (nativeBridge) {
                        crossChainQuotes.push(nativeBridge);
                    }
                }

            } catch (error) {
                console.warn(`Cross-chain quote failed for bridge ${bridge.name}:`, error.message);
            }
        }

        return crossChainQuotes;
    }

    async getSwapThenBridgeQuote(bridge, request) {
        // Step 1: Swap fromToken to bridgeable token on source chain
        const bridgeableTokens = bridge.getSupportedTokens(request.fromChain);
        let bestQuote = null;

        for (const bridgeToken of bridgeableTokens) {
            if (bridgeToken === request.fromToken) continue;

            try {
                // Get swap quote on source chain
                const swapQuote = await this.getBestDirectQuote(
                    request.fromToken,
                    bridgeToken,
                    request.amountIn,
                    request.fromChain
                );

                if (!swapQuote) continue;

                // Get bridge quote
                const bridgeQuote = await bridge.getQuote(
                    bridgeToken,
                    swapQuote.outputAmount,
                    request.fromChain,
                    request.toChain
                );

                if (!bridgeQuote) continue;

                // Get final swap quote on destination chain (if needed)
                let finalQuote = null;
                if (bridgeToken !== request.toToken) {
                    finalQuote = await this.getBestDirectQuote(
                        bridgeToken,
                        request.toToken,
                        bridgeQuote.outputAmount,
                        request.toChain
                    );
                }

                const finalOutputAmount = finalQuote 
                    ? finalQuote.outputAmount 
                    : bridgeQuote.outputAmount;

                const combinedQuote = {
                    outputAmount: finalOutputAmount,
                    route: 'SWAP_BRIDGE_SWAP',
                    steps: [
                        { type: 'SWAP', ...swapQuote },
                        { type: 'BRIDGE', ...bridgeQuote },
                        ...(finalQuote ? [{ type: 'SWAP', ...finalQuote }] : [])
                    ],
                    totalGasCost: this.calculateTotalGasCost([swapQuote, bridgeQuote, finalQuote].filter(Boolean)),
                    estimatedTime: swapQuote.estimatedTime + bridgeQuote.estimatedTime + (finalQuote?.estimatedTime || 0),
                    bridgeUsed: bridge.name,
                    reliability: Math.min(
                        swapQuote.reliability || 0.99,
                        bridgeQuote.reliability || 0.99,
                        finalQuote?.reliability || 0.99
                    )
                };

                if (!bestQuote || combinedQuote.outputAmount > bestQuote.outputAmount) {
                    bestQuote = combinedQuote;
                }

            } catch (error) {
                console.warn(`Swap-then-bridge quote failed for ${bridgeToken}:`, error.message);
            }
        }

        return bestQuote;
    }

    async rankQuotes(quotes, request) {
        const rankedQuotes = [];

        for (const quote of quotes) {
            const score = await this.scoreQuote(quote, request);
            rankedQuotes.push({ ...quote, score });
        }

        // Sort by score (higher is better)
        rankedQuotes.sort((a, b) => b.score - a.score);

        return rankedQuotes;
    }

    async scoreQuote(quote, request) {
        const weights = request.weights || {
            outputAmount: 0.4,     // 40% - amount received
            gasCost: 0.25,         // 25% - gas efficiency
            reliability: 0.15,     // 15% - execution probability
            speed: 0.1,            // 10% - execution time
            priceImpact: 0.1       // 10% - slippage
        };

        // Normalize metrics to 0-1 scale
        const normalizedMetrics = {
            outputAmount: this.normalizeOutputAmount(quote.outputAmount, request.amountIn),
            gasCost: this.normalizeGasCost(quote.gasCost, quote.outputAmount),
            reliability: quote.reliability || 0.99,
            speed: this.normalizeSpeed(quote.estimatedTime),
            priceImpact: 1 - Math.min(quote.priceImpact || 0, 0.1) / 0.1
        };

        // Calculate weighted score
        let score = 0;
        for (const [metric, weight] of Object.entries(weights)) {
            score += normalizedMetrics[metric] * weight;
        }

        return score;
    }

    normalizeOutputAmount(outputAmount, inputAmount) {
        // Higher output ratio is better (capped at 1.0 for safety)
        return Math.min(outputAmount / inputAmount, 1.0);
    }

    normalizeGasCost(gasCost, outputAmount) {
        if (!gasCost || !gasCost.usdValue) return 1.0;
        
        // Lower gas cost ratio is better
        const gasCostRatio = gasCost.usdValue / outputAmount;
        return Math.max(0, 1 - Math.min(gasCostRatio * 10, 1));
    }

    normalizeSpeed(estimatedTime) {
        // Faster is better (normalize against 1 hour max)
        const maxTime = 3600; // 1 hour in seconds
        return Math.max(0, 1 - Math.min(estimatedTime / maxTime, 1));
    }
}

Quote Sources

DEX Integration

Each DEX has a specialized quote source that handles its unique characteristics:

class UniswapV2QuoteSource {
    constructor(chainId, routerAddress) {
        this.chainId = chainId;
        this.routerAddress = routerAddress;
        this.provider = this.getProvider(chainId);
        this.routerContract = this.getRouterContract();
    }

    async getQuote(tokenA, tokenB, amountIn) {
        try {
            // Get reserves for the pair
            const pair = await this.getPairAddress(tokenA, tokenB);
            const reserves = await this.getReserves(pair);
            
            // Calculate output using x*y=k formula
            const outputAmount = this.calculateOutputAmount(
                amountIn,
                reserves.reserve0,
                reserves.reserve1,
                tokenA,
                tokenB
            );

            // Calculate price impact
            const priceImpact = this.calculatePriceImpact(
                amountIn,
                outputAmount,
                reserves.reserve0,
                reserves.reserve1
            );

            return {
                outputAmount,
                priceImpact,
                fee: 0.003, // 0.3% for Uniswap V2
                estimatedGas: 150000,
                estimatedTime: 60, // 1 minute
                reliability: 0.99,
                dexType: 'UNISWAP_V2',
                liquiditySource: pair
            };

        } catch (error) {
            throw new Error(`Uniswap V2 quote failed: ${error.message}`);
        }
    }

    calculateOutputAmount(amountIn, reserveIn, reserveOut, tokenA, tokenB) {
        const amountInWithFee = amountIn * 997; // 0.3% fee
        const numerator = amountInWithFee * reserveOut;
        const denominator = (reserveIn * 1000) + amountInWithFee;
        return numerator / denominator;
    }

    calculatePriceImpact(amountIn, amountOut, reserveIn, reserveOut) {
        const priceBeforeTrade = reserveOut / reserveIn;
        const priceAfterTrade = (reserveOut - amountOut) / (reserveIn + amountIn);
        return Math.abs((priceAfterTrade - priceBeforeTrade) / priceBeforeTrade);
    }
}

class UniswapV3QuoteSource {
    constructor(chainId, quoterAddress) {
        this.chainId = chainId;
        this.quoterAddress = quoterAddress;
        this.quoterContract = this.getQuoterContract();
    }

    async getQuote(tokenA, tokenB, amountIn, fee = 3000) {
        try {
            // Try different fee tiers
            const feeTiers = [500, 3000, 10000];
            let bestQuote = null;

            for (const feeLevel of feeTiers) {
                try {
                    const quote = await this.quoterContract.callStatic.quoteExactInputSingle(
                        tokenA,
                        tokenB,
                        feeLevel,
                        amountIn,
                        0 // sqrtPriceLimitX96
                    );

                    if (!bestQuote || quote.amountOut > bestQuote.outputAmount) {
                        bestQuote = {
                            outputAmount: quote.amountOut,
                            fee: feeLevel / 1000000, // Convert to decimal
                            priceImpact: await this.calculateV3PriceImpact(tokenA, tokenB, amountIn, quote.amountOut, feeLevel),
                            estimatedGas: 180000,
                            estimatedTime: 60,
                            reliability: 0.99,
                            dexType: 'UNISWAP_V3',
                            feeLevel: feeLevel
                        };
                    }
                } catch (error) {
                    // Fee tier might not exist, continue with others
                    continue;
                }
            }

            if (!bestQuote) {
                throw new Error('No valid Uniswap V3 pools found');
            }

            return bestQuote;

        } catch (error) {
            throw new Error(`Uniswap V3 quote failed: ${error.message}`);
        }
    }

    async calculateV3PriceImpact(tokenA, tokenB, amountIn, amountOut, fee) {
        // Implementation would query pool state and calculate price impact
        // This is simplified for demonstration
        const poolContract = await this.getPoolContract(tokenA, tokenB, fee);
        const slot0 = await poolContract.slot0();
        
        // Calculate price impact based on current price and trade size
        // Complex calculation involving tick math - simplified here
        return amountIn / (amountIn + 1000000) * 0.01; // Simplified estimate
    }
}

class CurveQuoteSource {
    constructor(chainId) {
        this.chainId = chainId;
        this.provider = this.getProvider(chainId);
        this.pools = this.getCurvePools();
    }

    async getQuote(tokenA, tokenB, amountIn) {
        try {
            // Find pool containing both tokens
            const pool = await this.findPool(tokenA, tokenB);
            if (!pool) {
                throw new Error('No Curve pool found for token pair');
            }

            const poolContract = this.getPoolContract(pool.address);
            const tokenAIndex = pool.tokens.indexOf(tokenA);
            const tokenBIndex = pool.tokens.indexOf(tokenB);

            // Get quote from Curve pool
            const outputAmount = await poolContract.get_dy(
                tokenAIndex,
                tokenBIndex,
                amountIn
            );

            // Calculate price impact (Curve has lower slippage for stablecoins)
            const priceImpact = await this.calculateCurvePriceImpact(
                pool,
                tokenAIndex,
                tokenBIndex,
                amountIn,
                outputAmount
            );

            return {
                outputAmount,
                priceImpact,
                fee: pool.fee,
                estimatedGas: 200000,
                estimatedTime: 60,
                reliability: 0.995, // Curve is very reliable
                dexType: 'CURVE',
                poolUsed: pool.name
            };

        } catch (error) {
            throw new Error(`Curve quote failed: ${error.message}`);
        }
    }

    async findPool(tokenA, tokenB) {
        for (const pool of this.pools) {
            if (pool.tokens.includes(tokenA) && pool.tokens.includes(tokenB)) {
                return pool;
            }
        }
        return null;
    }

    async calculateCurvePriceImpact(pool, indexA, indexB, amountIn, amountOut) {
        // Curve has sophisticated bonding curve math
        // This is a simplified calculation
        const poolContract = this.getPoolContract(pool.address);
        const balanceA = await poolContract.balances(indexA);
        const balanceB = await poolContract.balances(indexB);
        
        // Price impact is generally lower for Curve due to its design
        const tradeSizeRatio = amountIn / balanceA;
        return Math.min(tradeSizeRatio * 0.5, 0.02); // Max 2% impact
    }
}

Gas Cost Estimation

class GasOracle {
    constructor() {
        this.gasPriceCache = new Map();
        this.gasEstimateCache = new Map();
        this.chainGasTokens = {
            1: 'ETH',
            137: 'MATIC',
            56: 'BNB',
            42161: 'ETH',
            10: 'ETH',
            43114: 'AVAX',
            250: 'FTM',
            8453: 'ETH'
        };
    }

    async estimateGasCost(dex, operation, chainId, gasPrice) {
        const cacheKey = `${dex.name}-${operation}-${chainId}`;
        
        if (this.gasEstimateCache.has(cacheKey)) {
            const cached = this.gasEstimateCache.get(cacheKey);
            if (Date.now() - cached.timestamp < 300000) { // 5 minute cache
                return this.calculateGasCostUSD(cached.gasUnits, gasPrice || cached.gasPrice, chainId);
            }
        }

        const gasUnits = await this.getGasEstimate(dex, operation, chainId);
        const currentGasPrice = gasPrice || await this.getCurrentGasPrice(chainId);

        this.gasEstimateCache.set(cacheKey, {
            gasUnits,
            gasPrice: currentGasPrice,
            timestamp: Date.now()
        });

        return this.calculateGasCostUSD(gasUnits, currentGasPrice, chainId);
    }

    async getGasEstimate(dex, operation, chainId) {
        // Base gas estimates by DEX type and operation
        const baseEstimates = {
            'UNISWAP_V2': {
                'SWAP': 150000,
                'ADD_LIQUIDITY': 200000,
                'REMOVE_LIQUIDITY': 180000
            },
            'UNISWAP_V3': {
                'SWAP': 180000,
                'ADD_LIQUIDITY': 250000,
                'REMOVE_LIQUIDITY': 220000
            },
            'CURVE': {
                'SWAP': 200000,
                'ADD_LIQUIDITY': 300000,
                'REMOVE_LIQUIDITY': 250000
            },
            'BALANCER': {
                'SWAP': 220000,
                'ADD_LIQUIDITY': 350000,
                'REMOVE_LIQUIDITY': 300000
            },
            'SUSHISWAP': {
                'SWAP': 150000,
                'ADD_LIQUIDITY': 200000,
                'REMOVE_LIQUIDITY': 180000
            }
        };

        const estimate = baseEstimates[dex.type]?.[operation] || 200000;
        
        // Apply chain-specific multipliers
        const chainMultipliers = {
            1: 1.0,    // Ethereum
            137: 1.2,  // Polygon (more complex state)
            56: 1.1,   // BSC
            42161: 1.0, // Arbitrum
            10: 1.0,   // Optimism
            43114: 1.3, // Avalanche
            250: 1.1,  // Fantom
            8453: 1.0  // Base
        };

        return Math.round(estimate * (chainMultipliers[chainId] || 1.0));
    }

    async getCurrentGasPrice(chainId) {
        const cacheKey = `gasPrice-${chainId}`;
        
        if (this.gasPriceCache.has(cacheKey)) {
            const cached = this.gasPriceCache.get(cacheKey);
            if (Date.now() - cached.timestamp < 60000) { // 1 minute cache
                return cached.gasPrice;
            }
        }

        let gasPrice;
        
        try {
            const provider = this.getProvider(chainId);
            gasPrice = await provider.getGasPrice();
        } catch (error) {
            // Fallback to chain-specific defaults
            const defaultGasPrices = {
                1: ethers.utils.parseUnits('20', 'gwei'),
                137: ethers.utils.parseUnits('30', 'gwei'),
                56: ethers.utils.parseUnits('5', 'gwei'),
                42161: ethers.utils.parseUnits('0.1', 'gwei'),
                10: ethers.utils.parseUnits('0.001', 'gwei'),
                43114: ethers.utils.parseUnits('25', 'gwei'),
                250: ethers.utils.parseUnits('20', 'gwei'),
                8453: ethers.utils.parseUnits('0.001', 'gwei')
            };
            
            gasPrice = defaultGasPrices[chainId] || ethers.utils.parseUnits('20', 'gwei');
        }

        this.gasPriceCache.set(cacheKey, {
            gasPrice,
            timestamp: Date.now()
        });

        return gasPrice;
    }

    async calculateGasCostUSD(gasUnits, gasPrice, chainId) {
        const gasToken = this.chainGasTokens[chainId];
        const gasTokenPriceUSD = await this.getTokenPriceUSD(gasToken);
        
        const gasCostInToken = (gasUnits * gasPrice) / Math.pow(10, 18); // Convert to token units
        const gasCostUSD = gasCostInToken * gasTokenPriceUSD;

        return {
            gasUnits,
            gasPrice: gasPrice.toString(),
            gasToken,
            gasCostInToken,
            usdValue: gasCostUSD
        };
    }

    async getTokenPriceUSD(tokenSymbol) {
        // Implementation would fetch from price oracle or DEX
        // Using mock prices for demonstration
        const mockPrices = {
            'ETH': 2000,
            'MATIC': 0.8,
            'BNB': 300,
            'AVAX': 25,
            'FTM': 0.3
        };

        return mockPrices[tokenSymbol] || 1;
    }
}

Quote Validation and Guarantees

class QuoteValidator {
    constructor() {
        this.validationRules = new Map();
        this.setupValidationRules();
    }

    setupValidationRules() {
        this.validationRules.set('MIN_OUTPUT', (quote, request) => {
            const minOutput = request.amountIn * (1 - request.slippageTolerance);
            return quote.outputAmount >= minOutput;
        });

        this.validationRules.set('MAX_PRICE_IMPACT', (quote, request) => {
            const maxImpact = request.maxPriceImpact || 0.1; // 10% default
            return (quote.priceImpact || 0) <= maxImpact;
        });

        this.validationRules.set('GAS_EFFICIENCY', (quote, request) => {
            if (!quote.gasCost) return true;
            const gasCostRatio = quote.gasCost.usdValue / quote.outputAmount;
            return gasCostRatio <= 0.05; // Max 5% gas cost ratio
        });

        this.validationRules.set('LIQUIDITY_CHECK', async (quote, request) => {
            // Verify sufficient liquidity exists
            return await this.verifyLiquidity(quote, request);
        });

        this.validationRules.set('EXECUTION_PROBABILITY', (quote, request) => {
            const minProbability = request.minExecutionProbability || 0.95;
            return (quote.executionProbability || 0.99) >= minProbability;
        });
    }

    async validateQuote(quote, request) {
        const validationResult = {
            isValid: true,
            errors: [],
            warnings: []
        };

        for (const [ruleName, rule] of this.validationRules) {
            try {
                const isValid = await rule(quote, request);
                
                if (!isValid) {
                    validationResult.isValid = false;
                    validationResult.errors.push({
                        rule: ruleName,
                        message: this.getErrorMessage(ruleName, quote, request)
                    });
                }
            } catch (error) {
                validationResult.warnings.push({
                    rule: ruleName,
                    message: `Validation failed: ${error.message}`
                });
            }
        }

        return validationResult;
    }

    getErrorMessage(ruleName, quote, request) {
        const messages = {
            'MIN_OUTPUT': `Output amount ${quote.outputAmount} below minimum required`,
            'MAX_PRICE_IMPACT': `Price impact ${(quote.priceImpact * 100).toFixed(2)}% exceeds maximum`,
            'GAS_EFFICIENCY': `Gas cost ratio too high`,
            'LIQUIDITY_CHECK': `Insufficient liquidity for trade size`,
            'EXECUTION_PROBABILITY': `Execution probability below minimum threshold`
        };

        return messages[ruleName] || `Validation failed for rule: ${ruleName}`;
    }

    async verifyLiquidity(quote, request) {
        // Implementation would check actual DEX liquidity
        // This is a simplified version
        for (const step of quote.routeBreakdown || []) {
            if (step.type === 'SWAP') {
                const liquidity = await this.getDEXLiquidity(step.dex, step.fromToken, step.toToken);
                if (liquidity < step.inputAmount * 2) { // Require 2x liquidity buffer
                    return false;
                }
            }
        }
        return true;
    }
}

Market Analysis

class MarketAnalyzer {
    async getMarketAnalysis(request) {
        const analysis = {
            priceComparison: await this.comparePricesAcrossDEXes(request),
            liquidityAnalysis: await this.analyzeLiquidity(request),
            volatilityMetrics: await this.getVolatilityMetrics(request),
            marketTrends: await this.getMarketTrends(request),
            optimalTiming: await this.analyzeOptimalTiming(request)
        };

        return analysis;
    }

    async comparePricesAcrossDEXes(request) {
        const dexPrices = new Map();
        const chainDEXes = this.getChainDEXes(request.fromChain);

        for (const dex of chainDEXes) {
            try {
                const quote = await this.getSimpleQuote(dex, request);
                if (quote) {
                    dexPrices.set(dex.name, {
                        price: quote.outputAmount / request.amountIn,
                        liquidity: quote.liquidity,
                        priceImpact: quote.priceImpact
                    });
                }
            } catch (error) {
                // Skip failed quotes
            }
        }

        const prices = Array.from(dexPrices.values()).map(d => d.price);
        const avgPrice = prices.reduce((sum, price) => sum + price, 0) / prices.length;
        const priceSpread = Math.max(...prices) - Math.min(...prices);

        return {
            dexPrices: Object.fromEntries(dexPrices),
            averagePrice: avgPrice,
            priceSpread,
            spreadPercentage: priceSpread / avgPrice
        };
    }

    async analyzeLiquidity(request) {
        const liquidityData = {
            totalLiquidity: 0,
            liquidityDistribution: {},
            depthAnalysis: {}
        };

        const chainDEXes = this.getChainDEXes(request.fromChain);

        for (const dex of chainDEXes) {
            try {
                const liquidity = await this.getDEXLiquidity(
                    dex.name,
                    request.fromToken,
                    request.toToken
                );

                liquidityData.totalLiquidity += liquidity;
                liquidityData.liquidityDistribution[dex.name] = liquidity;

                // Analyze depth at different trade sizes
                liquidityData.depthAnalysis[dex.name] = await this.analyzeDepth(
                    dex,
                    request,
                    [0.1, 0.5, 1, 2, 5] // Trade size multipliers
                );

            } catch (error) {
                // Skip failed liquidity checks
            }
        }

        return liquidityData;
    }

    async getVolatilityMetrics(request) {
        const priceHistory = await this.getPriceHistory(
            request.fromToken,
            request.toToken,
            request.fromChain,
            24 // 24 hours
        );

        const prices = priceHistory.map(p => p.price);
        const returns = [];

        for (let i = 1; i < prices.length; i++) {
            returns.push((prices[i] - prices[i-1]) / prices[i-1]);
        }

        const avgReturn = returns.reduce((sum, r) => sum + r, 0) / returns.length;
        const variance = returns.reduce((sum, r) => sum + Math.pow(r - avgReturn, 2), 0) / returns.length;
        const volatility = Math.sqrt(variance);

        return {
            dailyVolatility: volatility,
            priceRange: {
                min: Math.min(...prices),
                max: Math.max(...prices),
                current: prices[prices.length - 1]
            },
            trend: this.calculateTrend(prices)
        };
    }

    calculateTrend(prices) {
        const recentPrices = prices.slice(-10); // Last 10 data points
        const firstPrice = recentPrices[0];
        const lastPrice = recentPrices[recentPrices.length - 1];
        
        const trendDirection = lastPrice > firstPrice ? 'UPWARD' : 'DOWNWARD';
        const trendStrength = Math.abs((lastPrice - firstPrice) / firstPrice);

        return {
            direction: trendDirection,
            strength: trendStrength,
            classification: trendStrength > 0.05 ? 'STRONG' : trendStrength > 0.02 ? 'MODERATE' : 'WEAK'
        };
    }
}

Integration Examples

React Hook for Quotes

import { useState, useEffect, useCallback } from 'react';
import { IXFIQuoteSystem } from '@ixfi/sdk';

export function useIXFIQuote(request, options = {}) {
    const [quote, setQuote] = useState(null);
    const [loading, setLoading] = useState(false);
    const [error, setError] = useState(null);
    const [alternatives, setAlternatives] = useState([]);

    const quoteSystem = new IXFIQuoteSystem(options.config);

    const fetchQuote = useCallback(async () => {
        if (!request.fromToken || !request.toToken || !request.amountIn) {
            return;
        }

        setLoading(true);
        setError(null);

        try {
            const result = await quoteSystem.getQuote(request);
            setQuote(result.bestQuote);
            setAlternatives(result.alternativeQuotes);
        } catch (err) {
            setError(err.message);
            setQuote(null);
            setAlternatives([]);
        } finally {
            setLoading(false);
        }
    }, [request, quoteSystem]);

    useEffect(() => {
        fetchQuote();
        
        // Auto-refresh quotes every 30 seconds
        const interval = setInterval(fetchQuote, 30000);
        return () => clearInterval(interval);
    }, [fetchQuote]);

    return {
        quote,
        alternatives,
        loading,
        error,
        refresh: fetchQuote
    };
}

Node.js Integration

const { IXFIQuoteSystem } = require('@ixfi/sdk');

class TradingBot {
    constructor(config) {
        this.quoteSystem = new IXFIQuoteSystem(config);
        this.minProfitThreshold = 0.005; // 0.5%
    }

    async findArbitrageOpportunities() {
        const tokenPairs = this.getMonitoredPairs();
        const opportunities = [];

        for (const pair of tokenPairs) {
            try {
                const quotes = await this.quoteSystem.getQuote({
                    fromToken: pair.tokenA,
                    toToken: pair.tokenB,
                    amountIn: pair.testAmount,
                    fromChain: pair.chainId,
                    toChain: pair.chainId,
                    includeGasCosts: true
                });

                const reverseQuotes = await this.quoteSystem.getQuote({
                    fromToken: pair.tokenB,
                    toToken: pair.tokenA,
                    amountIn: quotes.bestQuote.outputAmount,
                    fromChain: pair.chainId,
                    toChain: pair.chainId,
                    includeGasCosts: true
                });

                const profit = reverseQuotes.bestQuote.outputAmount - pair.testAmount;
                const profitPercentage = profit / pair.testAmount;

                if (profitPercentage > this.minProfitThreshold) {
                    opportunities.push({
                        pair,
                        profit,
                        profitPercentage,
                        route1: quotes.bestQuote,
                        route2: reverseQuotes.bestQuote
                    });
                }

            } catch (error) {
                console.warn(`Failed to check arbitrage for ${pair.tokenA}-${pair.tokenB}:`, error.message);
            }
        }

        return opportunities.sort((a, b) => b.profitPercentage - a.profitPercentage);
    }
}

Performance Metrics

The quote system maintains detailed performance metrics:

  • Response Time: Average < 500ms for simple quotes, < 2s for complex multi-chain routes

  • Accuracy: 99%+ quote accuracy within 1% of execution price

  • Coverage: 35+ DEXes across 8+ chains with 95%+ uptime

  • Cache Hit Rate: 85%+ for frequently requested pairs

  • Gas Estimation: Within 5% of actual gas usage

Best Practices

  1. Cache Effectively: Use appropriate cache timeouts for different quote types

  2. Handle Failures Gracefully: Always provide fallback quotes when primary sources fail

  3. Validate Before Execution: Always re-validate quotes immediately before execution

  4. Monitor Performance: Track quote accuracy and execution success rates

  5. Update Regularly: Keep DEX integrations and gas estimates current

Resources

Last updated