Private Transfers
This guide covers sending tokens privately between privacy addresses using the Privacy Boost React SDK.Basic Transfer
import { useVault } from '@sunnyside-io/privacy-boost-react';
function TransferButton() {
const { send } = useVault();
const handleTransfer = async () => {
const result = await send({
recipient: '0x04...recipient-privacy-address',
tokenAddress: '0x...token-address',
amount: '1.0',
});
console.log('Transfer request:', result.requestId);
};
return <button onClick={handleTransfer}>Send</button>;
}
Transfer Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
recipient | Hex | string | Yes | Recipient’s privacy address |
tokenAddress | Hex | Yes | Token contract address |
amount | string | bigint | Yes | Amount (human-readable string or wei) |
Privacy Address Validation
import { isValidPrivacyAddress } from '@sunnyside-io/privacy-boost';
function TransferForm() {
const { send } = useVault();
const [recipient, setRecipient] = useState('');
const [error, setError] = useState('');
const handleTransfer = async () => {
if (!isValidPrivacyAddress(recipient)) {
setError('Invalid privacy address');
return;
}
await send({ recipient, tokenAddress: '0x...', amount: '1.0' });
};
// ...
}
Complete Example
import { useState } from 'react';
import { useVault, useBalances } from '@sunnyside-io/privacy-boost-react';
import { isValidPrivacyAddress } from '@sunnyside-io/privacy-boost';
function TransferForm({ tokenAddress }: { tokenAddress: string }) {
const { send } = useVault();
const { refresh } = useBalances();
const [recipient, setRecipient] = useState('');
const [amount, setAmount] = useState('');
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const handleTransfer = async () => {
if (!isValidPrivacyAddress(recipient)) {
setError('Invalid privacy address');
return;
}
setLoading(true);
setError(null);
try {
await send({ recipient, tokenAddress, amount });
setRecipient('');
setAmount('');
await refresh();
} catch (err: any) {
if (err.code !== 'TRANSACTION_REJECTED') {
setError(err.message);
}
} finally {
setLoading(false);
}
};
return (
<div>
<input
type="text"
value={recipient}
onChange={(e) => setRecipient(e.target.value)}
placeholder="Recipient privacy address"
disabled={loading}
/>
<input
type="text"
value={amount}
onChange={(e) => setAmount(e.target.value)}
placeholder="Amount"
disabled={loading}
/>
{error && <p style={{ color: 'red' }}>{error}</p>}
<button onClick={handleTransfer} disabled={loading || !recipient || !amount}>
{loading ? 'Sending...' : 'Send'}
</button>
</div>
);
}
Error Handling
try {
await send({ recipient, tokenAddress, amount });
} catch (error: any) {
switch (error.code) {
case 'TRANSACTION_REJECTED':
return;
case 'INSUFFICIENT_BALANCE':
setError('Not enough shielded balance');
break;
case 'INVALID_RECIPIENT':
setError('Invalid privacy address');
break;
default:
setError(error.message);
}
}
Best Practices
1. Validate Inputs Before Sending
Always validate the privacy address before attempting a transfer.2. Refresh After Transfer
await send({ recipient, tokenAddress, amount });
await refresh();