useTransaction
The useTransaction hook handles the execution of bridge transactions, including automatic chain switching, transaction sending, and status monitoring.
Import
import { useTransaction } from '@silentswap/react';Basic Usage
import { useTransaction, useQuote } from '@silentswap/react';
import { useAccount, useWalletClient } from 'wagmi';
function BridgeComponent() {
const { address, connector } = useAccount();
const { data: walletClient } = useWalletClient();
const { getQuote } = useQuote({ address });
const {
executeTransaction,
getStatus,
isLoading,
currentStep,
error,
} = useTransaction({
address: address!,
walletClient: walletClient as any,
connector,
});
const handleBridge = async () => {
// Get quote first
const quote = await getQuote(
1, // Ethereum
'0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
'1000000', // 1 USDC
43114, // Avalanche
'0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E' // USDC.e
);
if (!quote) {
console.error('Failed to get quote');
return;
}
// Execute the bridge transaction
const result = await executeTransaction(quote);
if (result) {
console.log('Bridge completed:', result);
// Check status if we have a request ID
if (result.requestId) {
const status = await getStatus(result.requestId, quote.provider);
console.log('Bridge status:', status);
}
}
};
return (
<div>
{isLoading && (
<div>
<p>{currentStep || 'Processing...'}</p>
<progress value={0.5} />
</div>
)}
{error && <div>Error: {error.message}</div>}
<button onClick={handleBridge} disabled={isLoading}>
{isLoading ? currentStep || 'Executing...' : 'Execute Bridge'}
</button>
</div>
);
}API Reference
Options
interface useTransactionOptions {
/** User's EVM address */
address: `0x${string}`;
/** Wallet client for signing operations */
walletClient?: WalletClient;
/** Wagmi connector */
connector?: Connector;
}Return Value
interface useTransactionReturn {
// State
isLoading: boolean;
currentStep: string;
error: Error | null;
// Methods
executeTransaction: (quote: BridgeQuote) => Promise<BridgeStatus | null>;
getStatus: (requestId: string, provider: BridgeProvider) => Promise<BridgeStatus | null>;
}BridgeQuote
The executeTransaction method expects a BridgeQuote object. You can convert a BridgeQuoteResult from useQuote to a BridgeQuote:
interface BridgeQuote {
provider: BridgeProvider;
estimatedTime: number;
fee: {
amount: string;
token: string;
usdValue: number;
};
slippage: number;
route: RelayQuoteResponse | DeBridgeOrderResponse;
txs: BridgeTransaction[];
}
interface BridgeTransaction {
to: `0x${string}`;
value: string;
data: `0x${string}`;
gasLimit?: string;
chainId: number;
}BridgeStatus
interface BridgeStatus {
status: 'pending' | 'completed' | 'failed';
requestId?: string;
txHashes?: string[];
error?: string;
}Advanced Usage
Converting Quote to BridgeQuote
import { parseUnits } from 'viem';
import { getAllAssetsArray } from '@silentswap/sdk';
function convertQuoteToBridgeQuote(
quote: BridgeQuoteResult,
sourceTokenInfo: AssetInfo
): BridgeQuote {
return {
provider: quote.provider,
estimatedTime: quote.estimatedTime,
fee: {
amount: '0',
token: sourceTokenInfo.symbol,
usdValue: quote.feeUsd,
},
slippage: quote.slippage,
route: quote.rawResponse,
txs: extractTransactions(quote.rawResponse, quote.provider, sourceChainId),
};
}
function extractTransactions(
rawResponse: any,
provider: string,
chainId: number
): BridgeTransaction[] {
if (provider === 'relay') {
return rawResponse.steps?.flatMap((step: any) =>
step.items?.map((item: any) => ({
to: item.data?.to,
value: item.data?.value || '0',
data: item.data?.data || '0x',
gasLimit: item.data?.gas,
chainId: item.data?.chainId || chainId,
})) || []
) || [];
} else if (provider === 'debridge') {
return rawResponse.tx ? [{
to: rawResponse.tx.to,
value: rawResponse.tx.value || '0',
data: rawResponse.tx.data || '0x',
chainId: chainId,
}] : [];
}
return [];
}Monitoring Transaction Progress
const { executeTransaction, getStatus, currentStep } = useTransaction({
address: address!,
walletClient,
connector,
});
const handleBridge = async () => {
const quote = await getQuote(/* ... */);
if (!quote) return;
const result = await executeTransaction(quote);
if (result?.requestId) {
// Poll for status updates
const checkStatus = setInterval(async () => {
const status = await getStatus(result.requestId!, quote.provider);
if (status?.status === 'completed') {
clearInterval(checkStatus);
console.log('Bridge completed!');
} else if (status?.status === 'failed') {
clearInterval(checkStatus);
console.error('Bridge failed:', status.error);
}
}, 5000); // Check every 5 seconds
// Cleanup after 5 minutes
setTimeout(() => clearInterval(checkStatus), 5 * 60 * 1000);
}
};Error Handling
const { executeTransaction, error } = useTransaction({
address: address!,
walletClient,
connector,
});
const handleBridge = async () => {
try {
const quote = await getQuote(/* ... */);
if (!quote) {
throw new Error('Failed to get quote');
}
const result = await executeTransaction(quote);
if (!result) {
throw new Error('Transaction execution failed');
}
if (result.status === 'failed') {
throw new Error(result.error || 'Bridge transaction failed');
}
// Success!
console.log('Bridge completed:', result);
} catch (err) {
console.error('Bridge error:', err);
// Show error to user
}
};Transaction Flow
- Chain Switching - Automatically switches to the source chain if needed
- Transaction Sending - Sends the bridge transaction(s)
- Confirmation - Waits for transaction confirmation
- Status Updates - Provides real-time status updates via
currentStep - Completion - Returns final status with transaction hashes
Supported Providers
- Relay.link - Multi-step bridge transactions
- deBridge - Single transaction bridges
Best Practices
- Always Check Quote - Verify quote exists before executing
- Handle Loading States - Show progress using
currentStep - Monitor Status - Poll for status updates on long-running bridges
- Error Recovery - Provide retry mechanisms for failed transactions
- User Feedback - Keep users informed of transaction progress
Next Steps
- Learn about getting quotes
- See a complete example