PaymentModal Component
The PaymentModal component provides a complete payment UI for your application. It handles token selection, balance checking, payment confirmation, and transaction processing.
Basic Usage
The easiest way to use PaymentModal is through the useVolrPay hook:
import { useVolrPay } from '@volr/react-ui';
function CheckoutButton() {
const { pay } = useVolrPay();
const handlePay = () => {
pay({
amount: '10.00',
currency: 'USDC',
onSuccess: () => {
console.log('Payment successful!');
},
onError: (error) => {
console.error('Payment failed:', error);
},
});
};
return <button onClick={handlePay}>Pay $10.00</button>;
}
useVolrPay Hook
The useVolrPay hook provides a simple API for opening the payment modal.
Payment Options
interface PaymentModalOptions {
amount: string; // Payment amount (e.g., "10.00")
currency: string; // Currency symbol (e.g., "USDC")
item?: { // Optional item details
name: string;
description?: string;
image?: string;
};
onSuccess?: () => void; // Called when payment succeeds
onError?: (error: Error) => void; // Called when payment fails
onCancel?: () => void; // Called when user cancels
}
Example with Item Details
import { useVolrPay } from '@volr/react-ui';
function ProductCard({ product }) {
const { pay } = useVolrPay();
const handlePurchase = () => {
pay({
amount: product.price,
currency: 'USDC',
item: {
name: product.name,
description: product.description,
image: product.imageUrl,
},
onSuccess: () => {
console.log('Purchase successful!');
// Redirect to success page, update cart, etc.
},
onError: (error) => {
console.error('Purchase failed:', error);
alert('Payment failed. Please try again.');
},
});
};
return (
<div>
<h3>{product.name}</h3>
<p>{product.description}</p>
<button onClick={handlePurchase}>
Buy for {product.price} USDC
</button>
</div>
);
}
Direct PaymentModal Usage
You can also use PaymentModal directly if you need more control:
import { PaymentModal } from '@volr/react-ui';
import { useState } from 'react';
import { useVolrModal } from '@volr/react-ui';
function CustomPaymentFlow() {
const [showPayment, setShowPayment] = useState(false);
const { openPayment } = useVolrModal();
const handlePay = () => {
openPayment({
amount: '10.00',
currency: 'USDC',
onSuccess: () => {
setShowPayment(false);
console.log('Payment successful!');
},
onError: (error) => {
console.error('Payment failed:', error);
},
});
};
return (
<>
<button onClick={handlePay}>Pay</button>
{/* PaymentModal is rendered automatically via portal */}
</>
);
}
Payment States
The PaymentModal handles several states automatically:
1. Payment Info
Shows payment details and token selection:
- Payment amount
- Selected token
- Available tokens with balances
- Item details (if provided)
2. Wallet Choice
If user doesn't have a wallet:
- Create new Volr account
- Connect external wallet (MetaMask, etc.) when enabled
3. Deposit
If user has insufficient balance:
- Shows deposit option
- Opens DepositModal to add funds
External Wallet Payments
To enable external wallet payments, set allowExternalWalletPayment: true in
VolrUIProvider. The option is only shown for ERC-20 tokens that support permit
(permitSupported: true) and is hidden for native tokens.
Notes:
- External wallet payments use PaymentRouter (permit flow).
- When
walletPolicy.requireVolrWalletOnLoginis true, external wallet payment is disabled.
4. Processing
During payment:
- Shows transaction status
- Displays transaction hash
- Handles errors
5. Result
After payment:
- Success: Shows success message
- Error: Shows error message with retry option
PaymentModal State Diagram
Error Handling
Handle payment errors:
import { useVolrPay } from '@volr/react-ui';
function PaymentButton() {
const { pay } = useVolrPay();
const handlePay = () => {
pay({
amount: '10.00',
currency: 'USDC',
onSuccess: () => {
console.log('Payment successful!');
},
onError: (error) => {
// Handle different error types
if (error.message.includes('insufficient')) {
alert('Insufficient balance. Please deposit funds.');
} else if (error.message.includes('user rejected')) {
// User cancelled, no action needed
} else {
alert('Payment failed. Please try again.');
console.error('Payment error:', error);
}
},
});
};
return <button onClick={handlePay}>Pay</button>;
}
Customization
Branding
PaymentModal uses your VolrUIProvider branding settings:
<VolrUIProvider
config={{
// ... other config
}}
branding={{
logoUrl: 'https://example.com/logo.png',
primaryColor: '#0066ff',
}}
/>
Supported Tokens
Configure which tokens users can pay with in your Dashboard:
- Go to Settings > Tokens
- Select tokens for your project
- Users will see these tokens in PaymentModal
Examples
E-commerce Checkout
import { useVolrPay } from '@volr/react-ui';
import { useCart } from './useCart';
function Checkout() {
const { pay } = useVolrPay();
const { items, total } = useCart();
const handleCheckout = () => {
pay({
amount: total.toFixed(2),
currency: 'USDC',
item: {
name: `${items.length} items`,
description: items.map(i => i.name).join(', '),
},
onSuccess: () => {
// Clear cart, redirect to success page
console.log('Checkout successful!');
},
onError: (error) => {
console.error('Checkout failed:', error);
},
});
};
return (
<div>
<h2>Checkout</h2>
<p>Total: ${total} USDC</p>
<button onClick={handleCheckout}>Pay Now</button>
</div>
);
}
Subscription Payment
import { useVolrPay } from '@volr/react-ui';
function SubscribeButton({ plan }) {
const { pay } = useVolrPay();
const handleSubscribe = () => {
pay({
amount: plan.price,
currency: 'USDC',
item: {
name: `${plan.name} Subscription`,
description: plan.description,
},
onSuccess: () => {
console.log('Subscription activated!');
// Update user subscription status
},
onError: (error) => {
console.error('Subscription failed:', error);
},
});
};
return (
<button onClick={handleSubscribe}>
Subscribe for {plan.price} USDC/month
</button>
);
}
Next Steps
- Payment Flow - Understand the payment process in detail
- Configuration - Configure VolrUIProvider