Documentation Index
Fetch the complete documentation index at: https://docs.privacyboost.io/llms.txt
Use this file to discover all available pages before exploring further.
Error Handling
This guide covers error types and handling strategies in the Privacy Boost TypeScript SDK.
Error Types
All SDK errors extend from PrivacyBoostError:
class PrivacyBoostError extends Error {
code: string; // Error code for programmatic handling
message: string; // Human-readable message
retryable: boolean; // Whether the operation can be retried
cause?: Error; // Original error if wrapped
isAuthError(): boolean; // Check if this is an auth-related error
isWalletError(): boolean; // Check if this is a wallet-related error
hasCode(): boolean; // Check if a specific error code is set
static from(error: unknown): PrivacyBoostError; // Wrap unknown errors
}
Error Categories
Configuration Errors
| Code | Description |
|---|
INVALID_CONFIG | Invalid SDK configuration |
try {
await PrivacyBoost.create({
serverUrl: 'invalid-url', // Will throw
// ...
});
} catch (error) {
if (error.code === 'INVALID_CONFIG') {
console.log('Please provide valid configuration');
}
}
Wallet Errors
| Code | Description |
|---|
TRANSACTION_REJECTED | User rejected the request |
WRONG_NETWORK | Wrong network |
try {
await sdk.auth.authenticate(adapter);
} catch (error) {
switch (error.code) {
case 'TRANSACTION_REJECTED':
showToast('Authentication cancelled');
break;
case 'WRONG_NETWORK':
showToast('Please switch to the correct network');
break;
default:
showToast('Authentication failed');
}
}
Authentication Errors
| Code | Description |
|---|
NOT_AUTHENTICATED | Not authenticated |
AUTH_NONCE_EXPIRED | Authentication nonce expired |
AUTH_INVALID_SIGNATURE | Invalid signature |
SESSION_EXPIRED | JWT token expired |
try {
await sdk.auth.authenticate(adapter);
} catch (error) {
if (error.code === 'AUTH_NONCE_EXPIRED') {
// Retry authentication
await sdk.auth.authenticate(adapter);
}
}
Operation Errors
| Code | Description |
|---|
TRANSFER_PROOF_FAILED | Transfer proof generation failed |
try {
await sdk.vault.shield(params);
} catch (error) {
switch (error.code) {
case 'TRANSACTION_REJECTED':
showError('Transaction cancelled');
break;
case 'TRANSFER_PROOF_FAILED':
showError('Proof generation failed');
break;
default:
showError('Deposit failed: ' + error.message);
}
}
Network Errors
| Code | Description |
|---|
TIMEOUT | Request timed out |
HTTP_ERROR | HTTP request failed |
RATE_LIMITED | Rate limited |
try {
await sdk.vault.getBalance(tokenAddress);
} catch (error) {
if (error.code === 'TIMEOUT') {
// Retry after delay
await delay(2000);
await sdk.vault.getBalance(tokenAddress);
}
}
Proof Errors
| Code | Description |
|---|
TRANSFER_PROOF_FAILED | Failed to generate transfer proof |
Error Handling Patterns
Basic Try-Catch
try {
await sdk.vault.shield(params);
} catch (error) {
if (error instanceof PrivacyBoostError) {
console.log('SDK Error:', error.code, error.message);
} else {
console.log('Unknown error:', error);
}
}
Error Handler Function
function handleError(error: unknown): string {
if (!(error instanceof PrivacyBoostError)) {
return 'An unexpected error occurred';
}
const messages: Record<string, string> = {
TRANSACTION_REJECTED: 'Request cancelled',
SESSION_EXPIRED: 'Session expired, please login again',
TIMEOUT: 'Request timed out, please try again',
WRONG_NETWORK: 'Please switch to the correct network',
};
return messages[error.code] || error.message;
}
// Usage
try {
await sdk.vault.transfer(params);
} catch (error) {
showToast(handleError(error));
}
Retry Logic
async function withRetry<T>(
operation: () => Promise<T>,
maxRetries = 3,
delay = 1000
): Promise<T> {
let lastError: Error;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await operation();
} catch (error) {
lastError = error;
// Don't retry user rejections
if (error.code === 'TRANSACTION_REJECTED') {
throw error;
}
// Retry retryable errors
if (error.retryable) {
await new Promise((r) => setTimeout(r, delay * attempt));
continue;
}
throw error;
}
}
throw lastError!;
}
// Usage
const balance = await withRetry(() => sdk.vault.getBalance(token));
Session Refresh
async function withSessionRefresh<T>(
operation: () => Promise<T>
): Promise<T> {
try {
return await operation();
} catch (error) {
if (error.code === 'SESSION_EXPIRED') {
await sdk.auth.authenticate(adapter);
return await operation();
}
throw error;
}
}
// Usage
const history = await withSessionRefresh(() =>
sdk.transactions.fetchHistory()
);
React Error Boundary
class PrivacyBoostErrorBoundary extends React.Component<
{ children: React.ReactNode },
{ error: Error | null }
> {
state = { error: null };
static getDerivedStateFromError(error: Error) {
return { error };
}
render() {
if (this.state.error) {
return (
<div>
<h2>Something went wrong</h2>
<p>{this.state.error.message}</p>
<button onClick={() => this.setState({ error: null })}>
Try again
</button>
</div>
);
}
return this.props.children;
}
}
React Hook for Error Handling
function useSDKOperation<T>(operation: () => Promise<T>) {
const [loading, setLoading] = useState(false);
const [error, setError] = useState<PrivacyBoostError | null>(null);
const [data, setData] = useState<T | null>(null);
const execute = useCallback(async () => {
setLoading(true);
setError(null);
try {
const result = await operation();
setData(result);
return result;
} catch (err) {
const sdkError = err instanceof PrivacyBoostError ? err : PrivacyBoostError.from(err);
setError(sdkError);
throw sdkError;
} finally {
setLoading(false);
}
}, [operation]);
return { execute, loading, error, data };
}
// Usage
function ShieldButton({ tokenAddress, amount }: { tokenAddress: Hex; amount: bigint }) {
const { execute, loading, error } = useSDKOperation(() =>
sdk.vault.shield({ tokenAddress, amount })
);
return (
<>
<button onClick={execute} disabled={loading}>
{loading ? 'Processing...' : 'Deposit'}
</button>
{error && <p className="error">{error.message}</p>}
</>
);
}
Logging Errors
function logError(error: unknown, context: string) {
if (error instanceof PrivacyBoostError) {
console.error(`[${context}] SDK Error:`, {
code: error.code,
message: error.message,
cause: error.cause,
});
} else {
console.error(`[${context}] Unknown error:`, error);
}
}
// Usage
try {
await sdk.vault.shield(params);
} catch (error) {
logError(error, 'deposit');
throw error;
}
Best Practices
1. Always Handle User Rejections Gracefully
if (error.code === 'TRANSACTION_REJECTED') {
// Don't show error, user intentionally cancelled
return;
}
2. Provide Actionable Error Messages
const actionableMessages: Record<string, string> = {
WRONG_NETWORK: 'Click here to switch networks',
SESSION_EXPIRED: 'Click to reconnect your wallet',
TRANSACTION_REJECTED: 'Transaction was cancelled',
};
3. Log Errors for Debugging
catch (error) {
// Log for developers
console.error('Operation failed:', error);
// Show user-friendly message
showToast(getUserMessage(error));
}
4. Use Error Codes, Not Messages
// BAD - Message might change
if (error.message.includes('rejected')) {
// ...
}
// GOOD - Code is stable
if (error.code === 'TRANSACTION_REJECTED') {
// ...
}
Next Steps