Code Examples
Real-world code examples to help you integrate ExePay into your application.
1. Simple SOL Payment
Send SOL from one wallet to another with transaction confirmation.
import { useWallet, useConnection } from '@solana/wallet-adapter-react';
import { PublicKey, SystemProgram, Transaction, LAMPORTS_PER_SOL } from '@solana/web3.js';
export function SendSOL() {
const { publicKey, sendTransaction } = useWallet();
const { connection } = useConnection();
const sendPayment = async (recipientAddress: string, amount: number) => {
if (!publicKey) throw new Error('Wallet not connected');
const transaction = new Transaction().add(
SystemProgram.transfer({
fromPubkey: publicKey,
toPubkey: new PublicKey(recipientAddress),
lamports: amount * LAMPORTS_PER_SOL,
})
);
const signature = await sendTransaction(transaction, connection);
await connection.confirmTransaction(signature, 'confirmed');
return signature;
};
return (
<button onClick={() => sendPayment('RECIPIENT_ADDRESS', 0.1)}>
Send 0.1 SOL
</button>
);
}2. SPL Token Transfer (USDC)
Send USDC or other SPL tokens with automatic ATA creation.
import { useWallet, useConnection } from '@solana/wallet-adapter-react';
import { PublicKey, Transaction } from '@solana/web3.js';
import {
getAssociatedTokenAddress,
createAssociatedTokenAccountInstruction,
createTransferInstruction,
} from '@solana/spl-token';
const USDC_MINT = new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'); // Mainnet USDC
export function SendUSDC() {
const { publicKey, sendTransaction } = useWallet();
const { connection } = useConnection();
const sendUSDC = async (recipientAddress: string, amount: number) => {
if (!publicKey) throw new Error('Wallet not connected');
const recipient = new PublicKey(recipientAddress);
// Get token accounts
const senderATA = await getAssociatedTokenAddress(USDC_MINT, publicKey);
const recipientATA = await getAssociatedTokenAddress(USDC_MINT, recipient);
const transaction = new Transaction();
// Check if recipient ATA exists, if not create it
const recipientAccount = await connection.getAccountInfo(recipientATA);
if (!recipientAccount) {
transaction.add(
createAssociatedTokenAccountInstruction(
publicKey,
recipientATA,
recipient,
USDC_MINT
)
);
}
// Add transfer instruction (USDC has 6 decimals)
transaction.add(
createTransferInstruction(
senderATA,
recipientATA,
publicKey,
amount * 1_000_000 // Convert to smallest unit
)
);
const signature = await sendTransaction(transaction, connection);
await connection.confirmTransaction(signature, 'confirmed');
return signature;
};
return (
<button onClick={() => sendUSDC('RECIPIENT_ADDRESS', 10)}>
Send 10 USDC
</button>
);
}3. Batch Payments
Send payments to multiple recipients in a single transaction.
import { useWallet, useConnection } from '@solana/wallet-adapter-react';
import { PublicKey, SystemProgram, Transaction, LAMPORTS_PER_SOL } from '@solana/web3.js';
interface Recipient {
address: string;
amount: number;
}
export function BatchPayment() {
const { publicKey, sendTransaction } = useWallet();
const { connection } = useConnection();
const sendBatch = async (recipients: Recipient[]) => {
if (!publicKey) throw new Error('Wallet not connected');
const transaction = new Transaction();
// Add transfer instruction for each recipient
for (const recipient of recipients) {
transaction.add(
SystemProgram.transfer({
fromPubkey: publicKey,
toPubkey: new PublicKey(recipient.address),
lamports: recipient.amount * LAMPORTS_PER_SOL,
})
);
}
const signature = await sendTransaction(transaction, connection);
await connection.confirmTransaction(signature, 'confirmed');
return signature;
};
const recipients: Recipient[] = [
{ address: 'ADDRESS_1', amount: 0.1 },
{ address: 'ADDRESS_2', amount: 0.2 },
{ address: 'ADDRESS_3', amount: 0.3 },
];
return (
<button onClick={() => sendBatch(recipients)}>
Send Batch Payment
</button>
);
}4. Recurring Payments Setup
Create a subscription that automatically executes payments on a schedule.
import { useState, useEffect } from 'react';
import { useWallet, useConnection } from '@solana/wallet-adapter-react';
import { PublicKey, SystemProgram, Transaction, LAMPORTS_PER_SOL } from '@solana/web3.js';
interface Subscription {
id: string;
recipient: string;
amount: number;
frequency: 'daily' | 'weekly' | 'monthly';
nextPayment: Date;
active: boolean;
}
export function RecurringPayment() {
const { publicKey, sendTransaction } = useWallet();
const { connection } = useConnection();
const [subscriptions, setSubscriptions] = useState<Subscription[]>([]);
const createSubscription = (
recipient: string,
amount: number,
frequency: 'daily' | 'weekly' | 'monthly'
) => {
const subscription: Subscription = {
id: Date.now().toString(),
recipient,
amount,
frequency,
nextPayment: getNextPaymentDate(frequency),
active: true,
};
setSubscriptions([...subscriptions, subscription]);
localStorage.setItem('subscriptions', JSON.stringify([...subscriptions, subscription]));
};
const executePayment = async (subscription: Subscription) => {
if (!publicKey) return;
const transaction = new Transaction().add(
SystemProgram.transfer({
fromPubkey: publicKey,
toPubkey: new PublicKey(subscription.recipient),
lamports: subscription.amount * LAMPORTS_PER_SOL,
})
);
const signature = await sendTransaction(transaction, connection);
await connection.confirmTransaction(signature, 'confirmed');
// Update next payment date
const updated = subscriptions.map(sub =>
sub.id === subscription.id
? { ...sub, nextPayment: getNextPaymentDate(sub.frequency) }
: sub
);
setSubscriptions(updated);
localStorage.setItem('subscriptions', JSON.stringify(updated));
return signature;
};
const getNextPaymentDate = (frequency: string) => {
const now = new Date();
switch (frequency) {
case 'daily':
return new Date(now.getTime() + 24 * 60 * 60 * 1000);
case 'weekly':
return new Date(now.getTime() + 7 * 24 * 60 * 60 * 1000);
case 'monthly':
return new Date(now.setMonth(now.getMonth() + 1));
default:
return now;
}
};
// Check for due payments
useEffect(() => {
const interval = setInterval(() => {
subscriptions.forEach(sub => {
if (sub.active && new Date() >= sub.nextPayment) {
executePayment(sub);
}
});
}, 60000); // Check every minute
return () => clearInterval(interval);
}, [subscriptions]);
return (
<div>
<button
onClick={() => createSubscription('RECIPIENT_ADDRESS', 0.1, 'monthly')}
>
Subscribe (0.1 SOL/month)
</button>
<div>
{subscriptions.map(sub => (
<div key={sub.id}>
<p>To: {sub.recipient}</p>
<p>Amount: {sub.amount} SOL</p>
<p>Frequency: {sub.frequency}</p>
<p>Next: {sub.nextPayment.toLocaleDateString()}</p>
</div>
))}
</div>
</div>
);
}5. Fetch Transaction History
Display a user's transaction history with details.
import { useState, useEffect } from 'react';
import { useWallet, useConnection } from '@solana/wallet-adapter-react';
import { PublicKey, LAMPORTS_PER_SOL } from '@solana/web3.js';
interface Transaction {
signature: string;
timestamp: number;
amount: number;
type: 'sent' | 'received';
counterparty: string;
}
export function TransactionHistory() {
const { publicKey } = useWallet();
const { connection } = useConnection();
const [transactions, setTransactions] = useState<Transaction[]>([]);
const [loading, setLoading] = useState(false);
const fetchHistory = async () => {
if (!publicKey) return;
setLoading(true);
try {
const signatures = await connection.getSignaturesForAddress(publicKey, { limit: 10 });
const txs: Transaction[] = [];
for (const sig of signatures) {
const tx = await connection.getParsedTransaction(sig.signature);
if (!tx) continue;
const instruction = tx.transaction.message.instructions[0];
if ('parsed' in instruction && instruction.parsed.type === 'transfer') {
const info = instruction.parsed.info;
const isSent = info.source === publicKey.toBase58();
txs.push({
signature: sig.signature,
timestamp: tx.blockTime || 0,
amount: info.lamports / LAMPORTS_PER_SOL,
type: isSent ? 'sent' : 'received',
counterparty: isSent ? info.destination : info.source,
});
}
}
setTransactions(txs);
} catch (error) {
console.error('Failed to fetch history:', error);
} finally {
setLoading(false);
}
};
useEffect(() => {
fetchHistory();
}, [publicKey]);
return (
<div>
<h2>Transaction History</h2>
{loading ? (
<p>Loading...</p>
) : (
<div>
{transactions.map(tx => (
<div key={tx.signature}>
<p>
{tx.type === 'sent' ? '↗️ Sent' : '↙️ Received'} {tx.amount} SOL
</p>
<p>
{tx.type === 'sent' ? 'To' : 'From'}: {tx.counterparty.slice(0, 8)}...
</p>
<p>{new Date(tx.timestamp * 1000).toLocaleString()}</p>
<a
href={`https://solscan.io/tx/${tx.signature}`}
target="_blank"
rel="noopener noreferrer"
>
View on Solscan
</a>
</div>
))}
</div>
)}
</div>
);
}More Examples
Check out our GitHub repository for more examples, including:
- Payment links and QR codes
- Multi-token support
- Error handling and retries
- Mobile wallet integration