Overview
The useQuotes hook manages the complete lifecycle of token swaps, from fetching quotes to executing transactions and monitoring their status. It handles wallet integration, quote expiration, and automatic status polling.
Import
import { useQuotes } from '@/lib/hooks' ;
Signature
const useQuotes : () => {
quote : Quote | null ;
status : QuoteStatus | null ;
loading : boolean ;
error : string | null ;
isPolling : boolean ;
predictedAddress : string | null ;
getPredictedAddress : () => Promise < string | null >;
getQuote : ( request : SimpleQuoteRequest ) => Promise < Quote | void >;
executeQuote : () => Promise < void >;
resetQuote : () => void ;
}
Return Values
The current quote object containing swap details, pricing, and chain operations. null when no quote is active.
Real-time transaction status after quote execution. Updates automatically via polling. Includes transaction hashes and explorer URLs.
Indicates if a quote fetch or transaction execution is in progress.
Error message if quote fetching or execution fails. null when no errors.
Indicates if the hook is actively polling for transaction status updates.
The user’s predicted account address (smart contract wallet). Required for balance checks and quote requests.
getPredictedAddress
() => Promise<string | null>
Async function to fetch the user’s predicted account address. Called automatically when needed.
getQuote
(request: SimpleQuoteRequest) => Promise<Quote | void>
Fetches a new swap quote based on the provided parameters. Parameters: request
SimpleQuoteRequest
required
Quote request parameters Show SimpleQuoteRequest Properties
Amount to swap in the smallest unit (wei). Use parseTokenAmount() utility to convert from user input.
Source asset identifier (e.g., "ob:usdc", "ob:eth").
Destination asset identifier (e.g., "ob:eth", "ob:usdc").
Optional recipient address for transfers. Must include chain prefix (e.g., "eip155:1:0x...").
Executes the current quote. Signs the quote using the embedded wallet and submits it for processing. Automatically starts polling for transaction status. Requirements:
User must be authenticated
Quote must exist and not be expired
Embedded wallet must be available
Clears the current quote, status, errors, and stops any active polling. Use when canceling a quote or resetting the swap form.
Usage Examples
Basic Swap Flow
import { useQuotes } from '@/lib/hooks' ;
import { parseTokenAmount } from '@/lib/utils/token' ;
function SwapForm () {
const {
quote ,
loading ,
error ,
getQuote ,
executeQuote ,
resetQuote
} = useQuotes ();
const handleGetQuote = async () => {
const amount = parseTokenAmount ( '100' , 18 ); // 100 tokens
await getQuote ({
fromTokenAmount: amount ,
fromAggregatedAssetId: 'ob:usdc' ,
toAggregatedAssetId: 'ob:eth'
});
};
const handleSwap = async () => {
await executeQuote ();
};
return (
< div >
< button onClick = { handleGetQuote } disabled = { loading } >
Get Quote
</ button >
{ quote && (
<>
< div > Rate : { quote . destinationToken . amount }</ div >
< button onClick = { handleSwap } disabled = { loading } >
Execute Swap
</ button >
< button onClick = { resetQuote } > Cancel </ button >
</>
)}
{ error && < div > Error : { error }</ div >}
</ div >
);
}
With Transaction Status Tracking
import { useQuotes } from '@/lib/hooks' ;
function SwapWithStatus () {
const {
quote ,
status ,
isPolling ,
executeQuote ,
resetQuote
} = useQuotes ();
useEffect (() => {
if ( status ?. status === 'COMPLETED' ) {
console . log ( 'Swap completed!' );
// Refresh balances, show success message, etc.
resetQuote ();
}
}, [ status ]);
return (
< div >
{ isPolling && (
< div >
Transaction Status : { status ?. status }
{ status ?. originChainOperations . map ( op => (
< a key = {op. hash } href = {op. explorerUrl } target = "_blank" >
View on Explorer : { op . hash }
</ a >
))}
</ div >
)}
</ div >
);
}
Debounced Quote Fetching
import { useQuotes } from '@/lib/hooks' ;
import { useCallback } from 'react' ;
import debounce from 'lodash.debounce' ;
function SwapForm () {
const { getQuote } = useQuotes ();
const [ amount , setAmount ] = useState ( '' );
// Debounce quote fetching to reduce API calls
const debouncedGetQuote = useCallback (
debounce ( async ( request ) => {
await getQuote ( request );
}, 1000 ),
[ getQuote ]
);
const handleAmountChange = ( value : string ) => {
setAmount ( value );
if ( value ) {
const parsed = parseTokenAmount ( value , 18 );
debouncedGetQuote ({
fromTokenAmount: parsed ,
fromAggregatedAssetId: 'ob:usdc' ,
toAggregatedAssetId: 'ob:eth'
});
}
};
return (
< input
type = "text"
value = { amount }
onChange = {(e) => handleAmountChange (e.target.value)}
placeholder = "Enter amount"
/>
);
}
Quote Expiration Handling
import { useQuotes } from '@/lib/hooks' ;
function QuoteWithExpiration () {
const { quote , getQuote } = useQuotes ();
const handleQuoteExpire = async () => {
// Re-fetch quote when it expires
if ( sourceAsset && targetAsset && amount ) {
await getQuote ({
fromTokenAmount: amount ,
fromAggregatedAssetId: sourceAsset ,
toAggregatedAssetId: targetAsset
});
}
};
return (
< div >
{ quote && (
< QuoteCountdown
expirationTimestamp = { parseInt (quote.expirationTimestamp)}
onExpire = { handleQuoteExpire }
/>
)}
</ div >
);
}
Types
Quote
interface Quote {
id : string ;
account : Account ;
originToken : TokenInfo ;
destinationToken : TokenInfo ;
expirationTimestamp : string ;
tamperProofSignature : string ;
originChainsOperations : ChainOperation [];
destinationChainOperation ?: ChainOperation ;
}
QuoteStatus
interface QuoteStatus {
quoteId : string ;
status : 'PENDING' | 'COMPLETED' | 'FAILED' | 'IN_PROGRESS' | 'REFUNDED' ;
user : string ;
recipientAccountId : string ;
originChainOperations : Array <{
hash : string ;
chainId : number ;
explorerUrl : string ;
}>;
destinationChainOperations : Array <{
hash : string ;
chainId : number ;
explorerUrl : string ;
}>;
}
Notes
The hook automatically polls for transaction status every 1 second after execution
Polling stops when the transaction reaches COMPLETED or FAILED status
Quote validation checks expiration time before execution
Requires Privy authentication and embedded wallet
Uses the PredictedAddressContext for account management
See Also