Documentation Index
Fetch the complete documentation index at: https://docs.kaleidoswap.com/llms.txt
Use this file to discover all available pages before exploring further.
Client Initialization
Use Environment Variables
Keep configuration out of source code:
import { KaleidoClient } from 'kaleido-sdk';
const client = KaleidoClient.create({
baseUrl: process.env.KALEIDO_API_URL!,
nodeUrl: process.env.KALEIDO_NODE_URL,
apiKey: process.env.KALEIDO_API_KEY,
});
Use a Singleton Client
Create one client instance and reuse it throughout your application:
// lib/kaleido.ts
import { KaleidoClient } from 'kaleido-sdk';
let client: KaleidoClient | null = null;
export function getClient(): KaleidoClient {
if (!client) {
client = KaleidoClient.create({
baseUrl: process.env.KALEIDO_API_URL!,
});
}
return client;
}
Error Handling
Always Handle Errors
Wrap SDK calls in try/catch blocks and handle specific error types:
import { KaleidoError, NetworkError, QuoteExpiredError } from 'kaleido-sdk';
try {
const quote = await client.maker.getQuote({ /* ... */ });
} catch (error) {
if (error instanceof QuoteExpiredError) {
// Retry with a fresh quote
} else if (error instanceof NetworkError && error.isRetryable()) {
// Retry after a delay
} else if (error instanceof KaleidoError) {
// Log and handle gracefully
console.error(`[${error.code}] ${error.message}`);
}
}
Check Retryability
Use isRetryable() before implementing retry logic:
if (error instanceof KaleidoError && error.isRetryable()) {
// Safe to retry: NetworkError, TimeoutError, 5xx errors, 429
}
Async Patterns
TypeScript: Parallel Requests
Use Promise.all for independent requests:
const [assets, pairs, lspInfo] = await Promise.all([
client.maker.listAssets(),
client.maker.listPairs(),
client.maker.getLspInfo(),
]);
Use Promise.allSettled when you want partial results:
const results = await Promise.allSettled([
client.maker.listAssets(),
client.maker.listPairs(),
]);
for (const result of results) {
if (result.status === 'fulfilled') {
console.log('Success:', result.value);
} else {
console.error('Failed:', result.reason);
}
}
Python: Sequential with Error Recovery
results = {}
for name, fn in [
("assets", lambda: client.maker.list_assets()),
("pairs", lambda: client.maker.list_pairs()),
]:
try:
results[name] = fn()
except KaleidoError as e:
print(f"Failed to fetch {name}: {e}")
results[name] = None
Amount Handling
Always Use Raw Units for API Calls
The API works with raw (smallest unit) amounts. Convert display amounts before sending:
import { toSmallestUnits } from 'kaleido-sdk';
// User enters 0.001 BTC
const userInput = 0.001;
const rawAmount = toSmallestUnits(userInput, 8); // 100000
const quote = await client.maker.getQuote({
from_asset: { asset_id: 'BTC', layer: 'BTC_LN', amount: rawAmount },
to_asset: { asset_id: 'USDT', layer: 'RGB_LN' }
});
Use PrecisionHandler for Multi-Asset Apps
When working with multiple assets, use PrecisionHandler to avoid precision errors:
import { createPrecisionHandler } from 'kaleido-sdk';
const handler = createPrecisionHandler(mappedAssets);
// Convert safely using asset ID
const raw = handler.toRawAmount(userInput, assetId);
const display = handler.toDisplayAmount(rawFromApi, assetId);
Node Operations
Check Node Before Using RLN
Always verify the node is configured:
if (!client.hasNode()) {
throw new Error('Node URL required for this operation');
}
const balance = await client.rln.getBtcBalance();
WebSocket
Unsubscribe When Done
Always clean up WebSocket subscriptions:
const unsubscribe = await client.maker.streamQuotesByTicker(
'BTC', 'USDT', 100000, onQuote
);
// Clean up when component unmounts or user navigates away
unsubscribe();
Handle Reconnection
Listen for reconnection events and update UI accordingly:
const ws = client.maker.enableWebSocket(wsUrl);
ws.on('disconnected', () => {
// Show "reconnecting" indicator
});
ws.on('connected', () => {
// Re-request quotes after reconnection
ws.requestQuote({ /* ... */ });
});
ws.on('maxReconnectExceeded', () => {
// Show "connection lost" error to user
});
Security
Never Expose API Keys in Client Code
API keys should only be used server-side. For browser applications, proxy API calls through your backend.
Always validate amounts and addresses before sending to the API:
// Validate amount is within limits
const pairs = await client.maker.listPairs();
const pair = pairs.pairs.find(p =>
p.base_asset_ticker === 'BTC' && p.quote_asset_ticker === 'USDT'
);
if (pair?.routes?.[0]) {
const route = pair.routes[0];
if (amount < route.min_from_amount || amount > route.max_from_amount) {
throw new Error(`Amount must be between ${route.min_from_amount} and ${route.max_from_amount}`);
}
}
Cache Static Data
Assets and trading pairs change infrequently. Cache them to reduce API calls:
let cachedPairs: ListPairsResponse | null = null;
let cacheTime = 0;
async function getPairs() {
const now = Date.now();
if (!cachedPairs || now - cacheTime > 60000) { // 60 second cache
cachedPairs = await client.maker.listPairs();
cacheTime = now;
}
return cachedPairs;
}