Stablecoins
Stablecoins are digital currencies pegged to stable assets like the US dollar, providing the benefits of cryptocurrency without the volatility. They enable fast, low-cost global payments and serve as a bridge between traditional finance and decentralized applications. With Human Wallet, users can seamlessly interact with stablecoins across multiple chains, making them ideal for remittances, payments, and DeFi applications. The combination of Human Wallet's 2PC and 2PC-MPC security and stablecoin stability creates a powerful foundation for building the next generation of financial applications.
Stablecoins ecosystem​
The stablecoin ecosystem is dominated by several major players, each serving different use cases and user preferences. USDT (Tether) remains the largest by market cap, widely used for trading and remittances across multiple blockchains. USDC (USD Coin) by Circle is known for its regulatory compliance and transparency, making it preferred for institutional use. Ethena USDE represents the next generation of stablecoins, using a synthetic dollar backed by staked ETH and short ETH perpetual positions. Other notable stablecoins include DAI (decentralized, over-collateralized), BUSD (Binance USD), and FRAX (algorithmic). Human Wallet supports all major stablecoins across EVM-compatible chains, enabling users to choose the stablecoin that best fits their needs.
Demo and source code​
This recipe is also available as an example project.
→ View live demo | → Browse source code
What are we cooking?​
A React application based on Human Wallet quick start example with WAGMI that connects Human Wallet to stablecoin networks, enabling users to:
- Send and receive stablecoins across multiple chains
- Check balances and transaction history
- Generate payment requests and QR codes
- Integrate with on-ramp services
Key Components​
- Human Wallet - Non-custodial wallets with 2PC and 2PC-MPC security and policy engine
- Stablecoin - USDC across multiple EVM chains
- Wagmi Integration - Type-safe blockchain interactions
- Cross-chain Support - Stablecoin transfers across multiple networks
Project Setup​
Get started with Human Wallet quick start example​
npx gitpick holonym-foundation/human-wallet-examples/tree/main/human-wallet-wagmi-nextjs
cd human-wallet-wagmi-nextjs
npm install
npm run dev
Core Functionality​
Receiving USDC​
To receive USDC, users need to share their wallet address with the sender. Human Wallet makes this process simple and secure.
Getting the wallet address​
import { useAccount } from 'wagmi';
function ReceiveUSDC() {
const { address, isConnected } = useAccount();
if (!isConnected) {
return <div>Please connect your wallet first</div>;
}
return (
<div>
<h3>Your USDC Address:</h3>
<p style={{ fontFamily: 'monospace', wordBreak: 'break-all' }}>
{address}
</p>
<button onClick={() => navigator.clipboard.writeText(address)}>
Copy Address
</button>
</div>
);
}
Displaying as QR Code​
For mobile users, displaying the address as a QR code makes it easier to share:
import { useAccount } from 'wagmi';
import QRCode from 'qrcode.react';
function USDCQRCode() {
const { address } = useAccount();
return (
<div>
<h3>Scan to send USDC</h3>
<QRCode value={address} size={200} />
<p>Address: {address}</p>
</div>
);
}
Checking USDC Balance​
import { useAccount, useReadContract } from 'wagmi';
import { formatUnits } from 'viem';
function CheckUSDCBalance() {
const { address } = useAccount();
// USDC contract address on Sepolia testnet
const usdcAddress = '0x1c7D4B196Cb0C7B01d743Fbc70B6A3cE8C4C4C4C4';
const { data: balance, isLoading, error } = useReadContract({
address: usdcAddress,
abi: [{
name: 'balanceOf',
type: 'function',
stateMutability: 'view',
inputs: [{ name: 'account', type: 'address' }],
outputs: [{ name: '', type: 'uint256' }]
}],
functionName: 'balanceOf',
args: [address],
});
if (isLoading) return <div>Loading balance...</div>;
if (error) return <div>Error: {error.message}</div>;
const balanceInUSDC = balance ? formatUnits(balance, 6) : '0';
return (
<div>
<h3>USDC Balance</h3>
<p>{balanceInUSDC} USDC</p>
</div>
);
}
Sending USDC​
Sending USDC requires interacting with the USDC smart contract. Here's how to implement it with Human Wallet:
Basic USDC Transfer​
import { useState } from 'react';
import { useAccount, useWriteContract, useWaitForTransactionReceipt } from 'wagmi';
import { parseUnits } from 'viem';
function SendUSDC() {
const { address } = useAccount();
const [recipient, setRecipient] = useState('');
const [amount, setAmount] = useState('');
// USDC contract address on Sepolia testnet
const usdcAddress = '0x1c7D4B196Cb0C7B01d743Fbc70B6A3cE8C4C4C4C4';
const { writeContract, data: hash, isPending } = useWriteContract();
const { isLoading: isConfirming, isSuccess } = useWaitForTransactionReceipt({
hash,
});
const sendUSDC = async () => {
if (!recipient || !amount) return;
try {
writeContract({
address: usdcAddress,
abi: [{
name: 'transfer',
type: 'function',
stateMutability: 'nonpayable',
inputs: [
{ name: 'to', type: 'address' },
{ name: 'amount', type: 'uint256' }
],
outputs: [{ name: '', type: 'bool' }]
}],
functionName: 'transfer',
args: [recipient, parseUnits(amount, 6)], // USDC has 6 decimals
});
} catch (error) {
console.error('Error sending USDC:', error);
}
};
return (
<div>
<input
type="text"
placeholder="Recipient address"
value={recipient}
onChange={(e) => setRecipient(e.target.value)}
/>
<input
type="number"
placeholder="Amount in USDC"
value={amount}
onChange={(e) => setAmount(e.target.value)}
/>
<button
onClick={sendUSDC}
disabled={isPending || isConfirming}
>
{isPending ? 'Confirming...' : isConfirming ? 'Sending...' : 'Send USDC'}
</button>
{hash && <p>Transaction: {hash}</p>}
{isSuccess && <p>Transaction successful!</p>}
</div>
);
}
Cross-Chain USDC Transfers​
Human Wallet supports sending USDC across multiple chains. Here's how to handle cross-chain transfers:
import { useAccount, useSwitchChain, useChainId } from 'wagmi';
import { sepolia, baseSepolia } from 'wagmi/chains';
function CrossChainUSDC() {
const { address } = useAccount();
const chainId = useChainId();
const { switchChain } = useSwitchChain();
const getUSDCAddress = (chainId) => {
const addresses = {
[sepolia.id]: '0x1c7D4B196Cb0C7B01d743Fbc70B6A3cE8C4C4C4C4', // Sepolia
[baseSepolia.id]: '0x036CbD53842c5426634e7929541eC2318f3dCF7e' // Base Sepolia
};
return addresses[chainId] || addresses[sepolia.id];
};
const getChainName = (chainId) => {
const names = {
[sepolia.id]: 'Sepolia',
[baseSepolia.id]: 'Base Sepolia'
};
return names[chainId] || 'Unknown';
};
return (
<div>
<h3>Select Chain for USDC Transfer</h3>
<div>
<button onClick={() => switchChain({ chainId: sepolia.id })}>
Sepolia
</button>
<button onClick={() => switchChain({ chainId: baseSepolia.id })}>
Base Sepolia
</button>
</div>
<p>Current Chain: {getChainName(chainId)}</p>
<p>USDC Contract: {getUSDCAddress(chainId)}</p>
</div>
);
}
Integration with External Services​
Human Wallet can be integrated with various external services for enhanced functionality:
On-Ramp Integration​
// Example integration with on-ramp services
function OnRampIntegration() {
const openOnRamp = (provider) => {
const onRampUrls = {
'banxa': 'https://banxa.com/',
'coinbase': 'https://commerce.coinbase.com/',
'moonpay': 'https://www.moonpay.com/'
};
window.open(onRampUrls[provider], '_blank');
};
return (
<div>
<h3>Buy USDC with Fiat</h3>
<button onClick={() => openOnRamp('banxa')}>Buy with Banxa</button>
<button onClick={() => openOnRamp('coinbase')}>Buy with Coinbase</button>
<button onClick={() => openOnRamp('moonpay')}>Buy with MoonPay</button>
</div>
);
}
Payment Request Generation​
import { useAccount } from 'wagmi';
function PaymentRequest() {
const { address } = useAccount();
const generatePaymentRequest = (amount, memo) => {
const paymentRequest = {
address: address,
amount: amount,
token: 'USDC',
memo: memo,
timestamp: Date.now()
};
const requestUrl = `https://your-app.com/pay?data=${encodeURIComponent(JSON.stringify(paymentRequest))}`;
return requestUrl;
};
return (
<div>
<h3>Generate Payment Request</h3>
<p>Share this link to request USDC payment:</p>
<p style={{ wordBreak: 'break-all' }}>
{generatePaymentRequest('100', 'Payment for services')}
</p>
</div>
);
}
Security Best Practices​
When working with stablecoins, security is paramount:
- Always verify contract addresses before interacting with them
- Check the recipient/to address before sending
- Use proper gas estimation to avoid failed transactions
- Implement proper error handling for all blockchain interactions
- Regularly update your integration to use the latest security practices
Conclusion​
Human Wallet provides a secure and user-friendly way to interact with stablecoins across multiple chains. By leveraging 2PC and 2PC-MPC technology and supporting various authentication methods, users can seamlessly send, receive, and manage stablecoins without the complexity typically associated with cryptocurrency wallets. This makes it ideal for building financial applications that need to support global payments and DeFi interactions.
For more advanced features and integrations, refer to our Methods guide and Customization guide.