Your First Integration
This guide walks you through creating your first integration with Starbloom, focusing on practical examples and common use cases.
Choose Your Integration Type​
Starbloom offers several integration patterns based on your needs:
1. Data Consumption​
- REST API for historical data
- WebSocket/SSE for real-time data
- Batch processing for large datasets
2. Data Production​
- Custom source connectors
- Protocol integrations
- Smart contract monitoring
Example: Market Data Integration​
Let's build a simple market data monitor that tracks Ethereum-based DEX trades.
1. Basic REST API Integration​
market-monitor.ts
import { StarbloomClient } from '@starbloom-ai/client';
async function getRecentTrades() {
const endpoint = 'starbloom.uniswap.1_0_0.Swap';
const params = new URLSearchParams({
limit: '10',
order: 'desc'
});
try {
const response = await fetch(
`https://api.starbloom.ai/v1/data/${endpoint}?${params}`,
{
headers: {
'Authorization': `Bearer ${process.env.STARBLOOM_API_KEY}`,
'Origin': process.env.ORIGIN
}
}
);
const trades = await response.json();
return trades.map(formatTrade);
} catch (error) {
console.error('Failed to fetch trades:', error);
throw error;
}
}
function formatTrade(trade: any) {
return {
timestamp: new Date(trade.ts).toISOString(),
tokenIn: trade.tokenIn,
tokenOut: trade.tokenOut,
amountIn: trade.amountIn,
amountOut: trade.amountOut
};
}
2. Real-time WebSocket Integration​
real-time-monitor.ts
class MarketMonitor {
private ws: WebSocket;
private reconnectAttempts = 0;
private maxReconnectAttempts = 5;
constructor(private apiKey: string) {
this.connect();
}
private connect() {
this.ws = new WebSocket(
`wss://stream.starbloom.ai/ws/v1/${this.apiKey}?topics=starbloom.uniswap.1_0_0.Swap`
);
this.ws.onopen = this.handleOpen.bind(this);
this.ws.onmessage = this.handleMessage.bind(this);
this.ws.onclose = this.handleClose.bind(this);
this.ws.onerror = this.handleError.bind(this);
}
private handleOpen() {
console.log('Connected to Starbloom WebSocket');
this.reconnectAttempts = 0;
}
private handleMessage(event: MessageEvent) {
const trade = JSON.parse(event.data);
this.processTrade(trade);
}
private handleClose() {
if (this.reconnectAttempts < this.maxReconnectAttempts) {
this.reconnectAttempts++;
console.log(`Reconnecting... Attempt ${this.reconnectAttempts}`);
setTimeout(() => this.connect(), 1000 * Math.pow(2, this.reconnectAttempts));
}
}
private handleError(error: Event) {
console.error('WebSocket error:', error);
}
private processTrade(trade: any) {
// Implement your trade processing logic here
console.log('New trade:', formatTrade(trade));
}
public close() {
this.ws.close();
}
}
3. Combined Integration Example​
Here's a complete example that combines historical and real-time data:
market-dashboard.ts
class MarketDashboard {
private monitor: MarketMonitor;
private trades: any[] = [];
constructor(private apiKey: string) {
this.monitor = new MarketMonitor(apiKey);
this.initialize();
}
private async initialize() {
try {
// Load historical data first
const recentTrades = await getRecentTrades();
this.trades = recentTrades;
// Start real-time monitoring
this.monitor = new MarketMonitor(this.apiKey);
// Update dashboard every 5 seconds
setInterval(() => this.updateMetrics(), 5000);
} catch (error) {
console.error('Failed to initialize dashboard:', error);
}
}
private updateMetrics() {
const lastHour = new Date(Date.now() - 3600000);
const recentTrades = this.trades.filter(t =>
new Date(t.timestamp) > lastHour
);
const metrics = {
tradeCount: recentTrades.length,
volume: this.calculateVolume(recentTrades),
averageSize: this.calculateAverageSize(recentTrades)
};
console.log('Updated metrics:', metrics);
}
private calculateVolume(trades: any[]): number {
return trades.reduce((sum, trade) => sum + Number(trade.amountIn), 0);
}
private calculateAverageSize(trades: any[]): number {
if (trades.length === 0) return 0;
return this.calculateVolume(trades) / trades.length;
}
public close() {
this.monitor.close();
}
}
// Usage
const dashboard = new MarketDashboard(process.env.STARBLOOM_API_KEY!);
Error Handling​
Implement proper error handling for production use:
error-handling.ts
class StarbloomError extends Error {
constructor(
message: string,
public statusCode?: number,
public retryable: boolean = false
) {
super(message);
this.name = 'StarbloomError';
}
}
async function handleStarbloomRequest<T>(
request: Promise<T>,
retries = 3
): Promise<T> {
try {
return await request;
} catch (error) {
if (error.statusCode === 429 && retries > 0) {
// Rate limit hit - implement backoff
await new Promise(resolve =>
setTimeout(resolve, 1000 * (4 - retries))
);
return handleStarbloomRequest(request, retries - 1);
}
throw new StarbloomError(
error.message,
error.statusCode,
error.statusCode >= 500
);
}
}
Best Practices​
-
Error Handling
- Always implement retry logic with backoff
- Handle WebSocket disconnections gracefully
- Log errors appropriately
-
Data Management
- Cache frequently accessed data
- Implement data cleanup for memory management
- Use appropriate data structures for your use case
-
Resource Management
- Close WebSocket connections when not in use
- Implement connection pooling for multiple streams
- Monitor resource usage
Troubleshooting Common Issues​
- No data received: Check topic names and authentication
- Slow responses: Review rate limits and connection quality
- Memory issues: Implement data cleanup and pagination
- Connection drops: Implement reconnection logic
Need help? Join our Discord community or email our support team.