Copy import React, { useEffect, useState } from 'react';
import { publicClient, walletClient } from './clients';
import { USDC_CONTRACT_ADDRESS, USDC_ABI } from './constants';
import {
type Address,
type Hash,
type TransactionReceipt,
} from 'viem';
function USDCApp() {
const [account, setAccount] = useState<Address>();
const [balance, setBalance] = useState<string>();
const [hash, setHash] = useState<Hash>();
const [receipt, setReceipt] = useState<TransactionReceipt>();
const [recipient, setRecipient] = useState('');
const [amount, setAmount] = useState('');
const [isTransferring, setIsTransferring] = useState(false);
// Fetch USDC balance
const fetchBalance = async (address: Address) => {
const raw = await publicClient.readContract({
address: USDC_CONTRACT_ADDRESS,
abi: USDC_ABI,
functionName: 'balanceOf',
args: [address],
}) as bigint;
setBalance((Number(raw) / 1e6).toFixed(2));
};
// Connect wallet
const connect = async () => {
const [addr] = await walletClient.requestAddresses();
setAccount(addr);
fetchBalance(addr);
};
// Transfer USDC
const transferUSDC = async (e: React.FormEvent) => {
e.preventDefault();
if (!account || !recipient || !amount) return;
try {
setIsTransferring(true);
const value = BigInt(Math.floor(Number(amount) * 1e6));
const { request } = await publicClient.simulateContract({
account,
address: USDC_CONTRACT_ADDRESS,
abi: USDC_ABI,
functionName: 'transfer',
args: [recipient as Address, value],
});
const txHash = await walletClient.writeContract(request);
setHash(txHash);
const rcpt = await publicClient.waitForTransactionReceipt({ hash: txHash });
setReceipt(rcpt);
await fetchBalance(account); // refresh balance
setRecipient('');
setAmount('');
} catch (err) {
console.error('Transfer failed:', err);
} finally {
setIsTransferring(false);
}
};
return (
<div>
<h1>USDC Transfer Sample App</h1>
{account ? (
<>
<p><strong>Connected wallet:</strong> {account}</p>
<p><strong>USDC balance:</strong> {balance ?? 'Fetching…'} USDC</p>
<form onSubmit={transferUSDC} style={{ marginTop: 20 }}>
<div style={{ marginBottom: 10 }}>
<label>
Recipient address
<input
type="text"
value={recipient}
onChange={e => setRecipient(e.target.value)}
placeholder="0x..."
style={{ marginLeft: 10, width: 300 }}
/>
</label>
</div>
<div style={{ marginBottom: 10 }}>
<label>
Amount (USDC)
<input
type="number"
value={amount}
onChange={e => setAmount(e.target.value)}
placeholder="0.00"
step="0.01"
min="0"
style={{ marginLeft: 10 }}
/>
</label>
</div>
<button type="submit" disabled={isTransferring}>
{isTransferring ? 'Transferring…' : 'Transfer USDC'}
</button>
</form>
{hash && (
<p style={{ marginTop: 20 }}>
<strong>Transaction hash:</strong> {hash}
</p>
)}
{receipt && (
<p style={{ marginTop: 10 }}>
<strong>Transaction status:</strong>{' '}
{receipt.status === 'success' ? 'Success' : 'Failed'}
</p>
)}
</>
) : (
<button onClick={connect}>Connect Wallet</button>
)}
</div>
);
}
export default USDCApp;