useQuote
The useQuote hook provides optimized bridge quotes by comparing multiple providers (Relay.link and deBridge) and selecting the best option based on retention rate.
Import
import { useQuote } from '@silentswap/react';Basic Usage
import { useQuote } from '@silentswap/react';
import { useAccount } from 'wagmi';
function BridgeComponent() {
const { address } = useAccount();
const {
getQuote,
isLoading,
error,
ingressEstimates,
egressEstimates,
} = useQuote({
address: address || undefined,
maxImpactPercent: 5, // Optional, default from SDK
});
const handleGetQuote = async () => {
const quote = await getQuote(
1, // Source chain ID (Ethereum)
'0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // Source token (USDC)
'1000000', // Amount in token units (1 USDC = 1e6)
43114, // Destination chain ID (Avalanche)
'0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E' // Destination token (USDC.e)
);
if (quote) {
console.log('Provider:', quote.provider);
console.log('Output Amount:', quote.outputAmount);
console.log('Fee (USD):', quote.feeUsd);
console.log('Slippage:', quote.slippage);
console.log('Retention Rate:', quote.retentionRate);
}
};
return (
<div>
{isLoading && <div>Getting quote...</div>}
{error && <div>Error: {error.message}</div>}
<button onClick={handleGetQuote} disabled={isLoading}>
Get Quote
</button>
</div>
);
}API Reference
Options
interface useQuoteOptions {
/** User's EVM address */
address?: `0x${string}`;
/** Maximum price impact percentage allowed (default from SDK constants) */
maxImpactPercent?: number;
/** Timeout for quote requests in milliseconds (default: 30000) */
quoteTimeout?: number;
}Return Value
interface useQuoteReturn {
// State
isLoading: boolean;
error: Error | null;
// Estimates cache
ingressEstimates: Record<string, Estimate>;
egressEstimates: Record<string, Estimate>;
// Methods
getQuote: (
srcChainId: number,
srcToken: string,
srcAmount: string,
dstChainId: number,
dstToken: string
) => Promise<BridgeQuoteResult>;
solveUsdcAmount: (
srcChainId: number,
srcToken: string,
srcAmount: string,
depositCalldata?: string
) => Promise<SolveResult>;
estimateLive: (
direction: 'ingress' | 'egress',
assetCaip19: string,
chainId: number,
tokenAddress: string,
amount: number,
usdPrice: number
) => Promise<EstimateResult>;
interpolateSamples: (
samples: EstimateSample[],
usdValue: number,
marginHi?: number
) => number;
}BridgeQuoteResult
interface BridgeQuoteResult {
/** Selected bridge provider ('relay' or 'debridge') */
provider: BridgeProvider;
/** Output amount in destination token units (as string) */
outputAmount: string;
/** Input amount required in source token units (as string) */
inputAmount: string;
/** Total fee in USD */
feeUsd: number;
/** Price slippage/impact percentage */
slippage: number;
/** Estimated time in seconds */
estimatedTime: number;
/** Retention rate (how much value is retained after fees, 0-1) */
retentionRate: number;
/** Number of transactions required */
txCount: number;
/** Raw response from the provider */
rawResponse: RelayQuoteResponse | DeBridgeOrderResponse;
}Advanced Usage
Auto-fetch Quote on Amount Change
import { useEffect, useState } from 'react';
import { useQuote } from '@silentswap/react';
function AutoQuoteComponent() {
const [amount, setAmount] = useState('');
const [quote, setQuote] = useState(null);
const { getQuote, isLoading } = useQuote({ address });
useEffect(() => {
if (!amount || parseFloat(amount) <= 0) {
setQuote(null);
return;
}
const fetchQuote = async () => {
const result = await getQuote(
1, // Ethereum
'0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
parseUnits(amount, 6).toString(), // Convert to token units
43114, // Avalanche
'0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E' // USDC.e
);
setQuote(result);
};
// Debounce quote fetching
const timeout = setTimeout(fetchQuote, 800);
return () => clearTimeout(timeout);
}, [amount, getQuote]);
return (
<div>
<input
value={amount}
onChange={(e) => setAmount(e.target.value)}
placeholder="Amount"
/>
{isLoading && <div>Loading quote...</div>}
{quote && (
<div>
<p>You'll receive: {formatUnits(quote.outputAmount, 6)} USDC</p>
<p>Fee: ${quote.feeUsd.toFixed(2)}</p>
</div>
)}
</div>
);
}Using Estimates Cache
The hook maintains a cache of ingress and egress estimates that can be used for quick lookups:
const { ingressEstimates, egressEstimates, estimateLive } = useQuote({ address });
// Get live estimate for a specific direction
const estimate = await estimateLive(
'ingress', // or 'egress'
'eip155:1/erc20:0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
1, // Chain ID
'0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // Token address
100, // Amount
1.0 // USD price per token
);Error Handling
The hook automatically handles errors from both providers and returns the best available quote:
const { getQuote, error } = useQuote({ address });
try {
const quote = await getQuote(/* ... */);
if (!quote) {
// Both providers failed
console.error('Failed to get quote from any provider');
}
} catch (err) {
// Handle error
console.error('Quote error:', err);
}Best Practices
- Debounce Quote Requests - Don't fetch quotes on every keystroke
- Handle Loading States - Show loading indicators while fetching
- Cache Quotes - Store quotes locally to avoid unnecessary requests
- Validate Amounts - Check that amounts are valid before fetching quotes
- Handle Errors Gracefully - Provide fallback UI when quotes fail
Next Steps
- Learn about transaction execution
- See a complete example