Documentation Index
Fetch the complete documentation index at: https://docs.webacy.com/llms.txt
Use this file to discover all available pages before exploring further.
You can handle errors gracefully using the SDK’s structured error classes. All errors extend the base WebacyError class, making it easy to catch and respond to different failure scenarios.
Error Classes
import {
WebacyError,
AuthenticationError,
ValidationError,
RateLimitError,
NotFoundError,
NetworkError,
} from '@webacy-xyz/sdk';
| Error | HTTP Status | Description |
|---|
AuthenticationError | 401 | Invalid or missing API key |
ValidationError | 400 | Invalid input parameters |
RateLimitError | 429 | Rate limit exceeded |
NotFoundError | 404 | Resource not found |
NetworkError | - | Network connectivity issues |
WebacyError | Various | Base class for all errors |
Basic Error Handling
import { ThreatClient, ValidationError, RateLimitError } from '@webacy-xyz/sdk';
const client = new ThreatClient({ apiKey: process.env.WEBACY_API_KEY });
try {
const result = await client.addresses.analyze('0x...');
} catch (error) {
if (error instanceof ValidationError) {
console.error('Invalid input:', error.message);
} else if (error instanceof RateLimitError) {
console.error('Rate limited, retry later');
} else {
console.error('Unexpected error:', error);
}
}
Error Properties
All SDK errors include these properties:
try {
await client.addresses.analyze('invalid-address');
} catch (error) {
if (error instanceof WebacyError) {
console.log(error.message); // Human-readable message
console.log(error.code); // Programmatic error code
console.log(error.status); // HTTP status code (if applicable)
console.log(error.requestId); // Request ID for support
console.log(error.endpoint); // Failed endpoint
console.log(error.cause); // Original error (if wrapped)
}
}
Recovery Suggestions
Errors provide recovery suggestions:
try {
await client.addresses.analyze('invalid');
} catch (error) {
if (error instanceof WebacyError) {
const suggestion = error.getRecoverySuggestion();
if (suggestion) {
console.log('How to fix:', suggestion);
}
}
}
Specific Error Types
AuthenticationError
Thrown when the API key is invalid or missing.
import { ThreatClient, AuthenticationError } from '@webacy-xyz/sdk';
try {
const client = new ThreatClient({ apiKey: 'invalid-key' });
await client.addresses.analyze('0x...');
} catch (error) {
if (error instanceof AuthenticationError) {
console.error('Invalid API key');
// Prompt user to check their API key
}
}
ValidationError
Thrown when input parameters are invalid.
import { ThreatClient, Chain, ValidationError } from '@webacy-xyz/sdk';
const client = new ThreatClient({ apiKey: 'your-api-key' });
try {
await client.addresses.analyze('not-an-address', { chain: Chain.ETH });
} catch (error) {
if (error instanceof ValidationError) {
console.error('Validation failed:', error.message);
console.log('Fix:', error.getRecoverySuggestion());
// "Ensure the address is a valid Ethereum address (0x followed by 40 hex characters)"
}
}
RateLimitError
Thrown when you exceed API rate limits. The SDK automatically retries rate-limited requests with exponential backoff.
import { ThreatClient, RateLimitError } from '@webacy-xyz/sdk';
const client = new ThreatClient({ apiKey: 'your-api-key' });
try {
await client.addresses.analyze('0x...');
} catch (error) {
if (error instanceof RateLimitError) {
console.error('Rate limited');
if (error.retryAfter) {
console.log(`Retry after ${error.retryAfter} seconds`);
}
if (error.resetAt) {
const resetDate = new Date(error.resetAt * 1000);
console.log(`Limit resets at ${resetDate.toISOString()}`);
}
}
}
NotFoundError
Thrown when the requested resource doesn’t exist.
import { ThreatClient, NotFoundError } from '@webacy-xyz/sdk';
const client = new ThreatClient({ apiKey: 'your-api-key' });
try {
await client.contracts.analyze('0xNonExistentContract...');
} catch (error) {
if (error instanceof NotFoundError) {
console.error('Contract not found');
}
}
NetworkError
Thrown when there are network connectivity issues.
import { ThreatClient, NetworkError } from '@webacy-xyz/sdk';
const client = new ThreatClient({ apiKey: 'your-api-key' });
try {
await client.addresses.analyze('0x...');
} catch (error) {
if (error instanceof NetworkError) {
console.error('Network error:', error.message);
if (error.requestId) {
console.error('Request ID:', error.requestId);
}
// Retry or notify user of connectivity issues
}
}
Retryable Errors
Check if an error can be retried:
import { ThreatClient, WebacyError } from '@webacy-xyz/sdk';
const client = new ThreatClient({ apiKey: 'your-api-key' });
async function analyzeWithRetry(address: string, maxRetries = 3) {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await client.addresses.analyze(address);
} catch (error) {
if (error instanceof WebacyError && error.isRetryable() && attempt < maxRetries) {
// Safe to retry (rate limits, network issues)
const delay = Math.pow(2, attempt) * 1000; // Exponential backoff
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
// Don't retry (validation errors, auth errors) or max retries reached
throw error;
}
}
}
Retryable errors:
RateLimitError - Wait and retry
NetworkError - Retry after connectivity restored
Non-retryable errors:
AuthenticationError - Fix API key
ValidationError - Fix input
NotFoundError - Resource doesn’t exist
Automatic Retries
The SDK automatically retries failed requests with exponential backoff:
const client = new ThreatClient({
apiKey: process.env.WEBACY_API_KEY,
retry: {
maxRetries: 3, // Default: 3
initialDelay: 1000, // Default: 1000ms
maxDelay: 30000, // Default: 30000ms
backoffMultiplier: 2, // Default: 2
},
});
Disable retries for specific requests using an AbortController:
const controller = new AbortController();
// Timeout after 5 seconds (no retries)
setTimeout(() => controller.abort(), 5000);
try {
await client.addresses.analyze('0x...', {
signal: controller.signal,
});
} catch (error) {
if (error.name === 'AbortError') {
console.log('Request timed out');
}
}
Logging Errors
Convert errors to JSON for logging:
try {
await client.addresses.analyze('0x...');
} catch (error) {
if (error instanceof WebacyError) {
// Structured logging
console.error(JSON.stringify(error.toJSON(), null, 2));
// {
// "name": "ValidationError",
// "message": "Invalid Ethereum address format",
// "code": "VALIDATION_ERROR",
// "status": 400,
// "requestId": "req_abc123",
// "endpoint": "/addresses/invalid"
// }
}
}
Full Example
import {
ThreatClient,
Chain,
WebacyError,
AuthenticationError,
ValidationError,
RateLimitError,
NotFoundError,
NetworkError,
} from '@webacy-xyz/sdk';
async function safeAnalyze(client: ThreatClient, address: string) {
try {
return await client.addresses.analyze(address);
} catch (error) {
// Handle specific error types
if (error instanceof AuthenticationError) {
throw new Error('Please check your API key configuration');
}
if (error instanceof ValidationError) {
throw new Error(`Invalid address: ${error.getRecoverySuggestion()}`);
}
if (error instanceof RateLimitError) {
const waitTime = error.retryAfter || 60;
throw new Error(`Too many requests. Please wait ${waitTime} seconds.`);
}
if (error instanceof NotFoundError) {
return null; // Address not found, return null
}
if (error instanceof NetworkError) {
throw new Error('Network error. Please check your connection.');
}
// Log unexpected errors with request ID for support
if (error instanceof WebacyError) {
console.error('Unexpected error:', error.toJSON());
if (error.requestId) {
console.error(`Request ID for support: ${error.requestId}`);
}
}
throw error;
}
}