Skip to main content

Transactions

Understand how transactions work in Volr SDK and how to handle them.

Transaction Flow

When a user makes a payment, the following transaction flow occurs:

Transaction States

Transactions go through several states:

  1. Pending: Transaction is being created
  2. Signing: User is signing transaction with passkey
  3. Broadcasting: Transaction is being broadcasted to network
  4. Confirming: Waiting for blockchain confirmation
  5. Confirmed: Transaction confirmed on blockchain
  6. Failed: Transaction failed

Monitoring Transactions

Using Payment Handlers

Monitor transaction progress using payment handlers:

import { useVolrPay } from '@volr/react-ui';

function PaymentButton() {
const { pay } = useVolrPay();

const handlePay = () => {
pay({
amount: '10.00',
currency: 'USDC',
onSuccess: (result) => {
console.log('Transaction hash:', result.txHash);
console.log('Transaction confirmed!');
},
onError: (error) => {
console.error('Transaction failed:', error);
},
});
};

return <button onClick={handlePay}>Pay</button>;
}

Payment Result

The onSuccess callback receives a payment result:

interface PaymentResult {
id: string; // Payment ID
txHash: string; // Transaction hash
status: 'confirmed'; // Payment status
amount: string; // Payment amount
currency: string; // Payment currency
createdAt: string; // Payment timestamp
}

Transaction Hash

Get the transaction hash to track on block explorer:

pay({
amount: '10.00',
currency: 'USDC',
onSuccess: (result) => {
const txHash = result.txHash;
const explorerUrl = `https://basescan.org/tx/${txHash}`;
console.log('View on explorer:', explorerUrl);
},
});

Error Handling

Handle transaction errors:

pay({
amount: '10.00',
currency: 'USDC',
onError: (error) => {
if (error.message.includes('user rejected')) {
// User cancelled transaction
console.log('Transaction cancelled by user');
} else if (error.message.includes('insufficient')) {
// Insufficient balance
console.log('Insufficient balance');
} else if (error.message.includes('network')) {
// Network error
console.log('Network error, please retry');
} else {
// Other errors
console.error('Transaction error:', error);
}
},
});

Transaction History

View transaction history:

import { useVolrModal } from '@volr/react-ui';

function PaymentHistory() {
const { open } = useVolrModal();

return (
<button onClick={() => open({ mode: 'account' })}>
View Payment History
</button>
);
}

Or use the API directly:

import { useVolrPaymentApi } from '@volr/react';

function PaymentHistoryList() {
const { getPaymentHistory } = useVolrPaymentApi();
const [payments, setPayments] = useState([]);

useEffect(() => {
getPaymentHistory({ limit: 10 }).then(setPayments);
}, []);

return (
<ul>
{payments.map((payment) => (
<li key={payment.id}>
{payment.amount} {payment.currency} - {payment.txHash}
</li>
))}
</ul>
);
}

Best Practices

1. Show Transaction Status

Always show transaction status to users:

const [txStatus, setTxStatus] = useState<'idle' | 'pending' | 'success' | 'error'>('idle');

pay({
amount: '10.00',
currency: 'USDC',
onSuccess: () => {
setTxStatus('success');
},
onError: () => {
setTxStatus('error');
},
});

return (
<div>
{txStatus === 'pending' && <div>Processing transaction...</div>}
{txStatus === 'success' && <div>Transaction confirmed!</div>}
{txStatus === 'error' && <div>Transaction failed</div>}
</div>
);

Link to block explorer:

pay({
amount: '10.00',
currency: 'USDC',
onSuccess: (result) => {
const explorerUrl = `https://basescan.org/tx/${result.txHash}`;
// Show link to user
window.open(explorerUrl, '_blank');
},
});

3. Handle Timeouts

Handle long-running transactions:

const [isProcessing, setIsProcessing] = useState(false);

pay({
amount: '10.00',
currency: 'USDC',
onSuccess: () => {
setIsProcessing(false);
},
onError: () => {
setIsProcessing(false);
},
});

// Show timeout message if processing takes too long
useEffect(() => {
if (isProcessing) {
const timeout = setTimeout(() => {
alert('Transaction is taking longer than expected. Please check your wallet.');
}, 60000); // 1 minute

return () => clearTimeout(timeout);
}
}, [isProcessing]);

Batch Transactions

For complex operations that require multiple transactions, use batch transactions to bundle them into a single request.

Next Steps