Quick Start
Send your first private payment in under 5 minutes. This guide assumes you've already installed ExePay.
Step 1: Set Up Wallet Provider
Wrap your app with the Solana wallet provider:
// app/layout.tsx or _app.tsx
import { WalletAdapterNetwork } from '@solana/wallet-adapter-base';
import { PhantomWalletAdapter } from '@solana/wallet-adapter-wallets';
import {
ConnectionProvider,
WalletProvider,
} from '@solana/wallet-adapter-react';
import { WalletModalProvider } from '@solana/wallet-adapter-react-ui';
import { useMemo } from 'react';
// Import wallet adapter CSS
import '@solana/wallet-adapter-react-ui/styles.css';
export default function App({ children }) {
const network = WalletAdapterNetwork.Devnet;
const endpoint = process.env.NEXT_PUBLIC_SOLANA_RPC_URL;
const wallets = useMemo(() => [new PhantomWalletAdapter()], []);
return (
<ConnectionProvider endpoint={endpoint}>
<WalletProvider wallets={wallets} autoConnect>
<WalletModalProvider>
{children}
</WalletModalProvider>
</WalletProvider>
</ConnectionProvider>
);
}Step 2: Connect Wallet
Add a wallet connect button to your page:
'use client';
import { useWallet } from '@solana/wallet-adapter-react';
import { WalletMultiButton } from '@solana/wallet-adapter-react-ui';
export default function WalletPage() {
const { publicKey, connected } = useWallet();
return (
<div>
<WalletMultiButton />
{connected && (
<p>Connected: {publicKey?.toBase58()}</p>
)}
</div>
);
}Step 3: Send Your First Payment
Send a public SOL payment:
'use client';
import { useWallet, useConnection } from '@solana/wallet-adapter-react';
import { PublicKey, SystemProgram, Transaction, LAMPORTS_PER_SOL } from '@solana/web3.js';
import { useState } from 'react';
export default function SendPayment() {
const { publicKey, sendTransaction } = useWallet();
const { connection } = useConnection();
const [recipient, setRecipient] = useState('');
const [amount, setAmount] = useState('');
const [status, setStatus] = useState('');
const handleSend = async () => {
if (!publicKey) return;
try {
setStatus('Sending...');
const transaction = new Transaction().add(
SystemProgram.transfer({
fromPubkey: publicKey,
toPubkey: new PublicKey(recipient),
lamports: parseFloat(amount) * LAMPORTS_PER_SOL,
})
);
const signature = await sendTransaction(transaction, connection);
await connection.confirmTransaction(signature, 'confirmed');
setStatus(`Success! Signature: ${signature}`);
} catch (error) {
setStatus(`Error: ${error.message}`);
}
};
return (
<div>
<input
type="text"
placeholder="Recipient address"
value={recipient}
onChange={(e) => setRecipient(e.target.value)}
/>
<input
type="number"
placeholder="Amount (SOL)"
value={amount}
onChange={(e) => setAmount(e.target.value)}
/>
<button onClick={handleSend}>Send SOL</button>
{status && <p>{status}</p>}
</div>
);
}Step 4: Enable Privacy
Switch to a shielded transfer to hide the amount:
import { createShieldedTransfer } from '@exe-pay/core';
// Instead of SystemProgram.transfer, use:
const { transaction, proof } = await createShieldedTransfer({
sender: publicKey,
recipient: new PublicKey(recipient),
amount: parseFloat(amount) * LAMPORTS_PER_SOL,
connection,
});
const signature = await sendTransaction(transaction, connection);Production Ready
Shielded and Private transfers are now in PRODUCTION! They use real Groth16 ZK-SNARKs to provide cryptographic privacy. Your transactions are truly private.
Get Devnet SOL
You'll need devnet SOL for testing. Get free devnet SOL from:
- Solana Faucet - Official faucet
- SolFaucet - Community faucet
- Use
solana airdrop 2via Solana CLI
Next Steps
You've sent your first payment! Now explore:
- Privacy Modes - Learn about Public, Shielded, and Private transfers
- Batch Payments - Send to multiple recipients at once
- Code Examples - More real-world examples