Rate Limits
The API enforces rate limits to ensure fair usage and platform stability.
Rate Limit Overview
| Endpoint | Limit | Window |
|---|---|---|
| Registration | 5 requests | 24 hours |
| Wallet operations | 30 requests | 1 minute |
| Trading (swap/transfer/bridge) | 30 requests | 1 minute |
| Portfolio | 60 requests | 1 minute |
| Token search | 100 requests | 1 minute |
| DEX data | 60 requests | 1 minute |
| RPC proxy | 100 requests | 1 minute |
| Token launch | 1 request | 24 hours |
| Fee claims | 1 request | 1 hour |
Rate Limit Headers
All API responses include rate limit headers:
X-RateLimit-Limit: 30
X-RateLimit-Remaining: 25
X-RateLimit-Reset: 1699574400
Handling 429 Responses
When you exceed rate limits, the API returns HTTP 429:
import { RateLimitError } from '@loomlay/openclaw-wallet-sdk';
try {
await wallet.trading.swap({ ... });
} catch (error) {
if (error instanceof RateLimitError) {
console.log('Rate limited. Retry after:', error.retryAfter, 'seconds');
}
}Exponential Backoff
Implement exponential backoff for robust retry logic:
async function withRetry<T>(
fn: () => Promise<T>,
maxAttempts = 5
): Promise<T> {
let lastError: Error | undefined;
for (let attempt = 0; attempt < maxAttempts; attempt++) {
try {
return await fn();
} catch (error) {
if (error instanceof RateLimitError) {
// Use server-provided retry time, or calculate backoff
const delay = error.retryAfter
? error.retryAfter * 1000
: Math.min(1000 * Math.pow(2, attempt), 30000);
console.log(`Rate limited. Retrying in ${delay}ms...`);
await sleep(delay);
lastError = error;
} else {
throw error;
}
}
}
throw lastError;
}
function sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Usage
const result = await withRetry(() =>
wallet.trading.swap({
inputToken: 'SOL',
outputToken: 'USDC',
amount: '1',
})
);Built-in Retry
The SDK includes built-in retry for transient failures:
const wallet = new OpenClawWallet({
apiKey: process.env.LOOMLAY_API_KEY!,
maxRetries: 3, // Retry up to 3 times
retryDelay: 1000, // Start with 1s delay
});Built-in retry uses exponential backoff automatically. Each retry waits 2x longer than the previous.
WebSocket Limits
WebSocket connections have separate limits:
| Limit | Value |
|---|---|
| Subscriptions per client | 10 |
| Max upstream connections | 20 |
| Heartbeat interval | 30 seconds |
const dexWs = wallet.createDexWebSocket();
// Maximum 10 subscriptions per connection
dexWs.subscribePair('SOL/USDC');
dexWs.subscribePair('ETH/USDC');
// ... up to 10 pairsBest Practices
Batch When Possible
Instead of multiple individual calls:
// Less efficient: 3 API calls
const sol = await wallet.wallet.get();
const portfolio = await wallet.portfolio.get();
const status = await wallet.tokenize.status();Use a single portfolio call when you need holdings:
// More efficient: 1 API call
const portfolio = await wallet.portfolio.get();
// Contains balances across all chainsCache Responses
Cache data that doesn't change frequently:
let cachedPortfolio: PortfolioResult | null = null;
let cacheTime = 0;
const CACHE_TTL = 60000; // 1 minute
async function getPortfolio() {
const now = Date.now();
if (cachedPortfolio && now - cacheTime < CACHE_TTL) {
return cachedPortfolio;
}
cachedPortfolio = await wallet.portfolio.get();
cacheTime = now;
return cachedPortfolio;
}Use WebSockets for Real-time Data
For frequently updating data, use WebSockets instead of polling:
// Instead of polling
setInterval(async () => {
const data = await wallet.dex.getPair('SOL/USDC'); // Uses rate limit
}, 1000);
// Use WebSocket
const dexWs = wallet.createDexWebSocket();
dexWs.subscribePair('SOL/USDC');
dexWs.on('update', (data) => {
console.log('Real-time update:', data);
});Spread Out Requests
If you need to make many requests, spread them out:
const tokens = ['SOL', 'ETH', 'USDC', 'BONK', 'WIF'];
const results = [];
for (const token of tokens) {
const data = await wallet.dex.getToken(token);
results.push(data);
// Small delay between requests
await sleep(100);
}Registration Limits
Registration is strictly limited to prevent abuse. Each IP address can only register a limited number of accounts.
If you need additional API keys:
- Use the key management endpoints to create additional keys for your existing account
- Contact support for legitimate multi-account use cases
// Create additional keys for existing account
const newKey = await wallet.auth.createKey();
console.log('New key:', newKey.apiKey);
// List all keys
const keys = await wallet.auth.listKeys();
// Revoke a key
await wallet.auth.revokeKey({ keyId: 'key_to_revoke' });