Implementation Examples
This page provides code examples and patterns from real node implementations.
Example 1: Simple API Integration
A basic node that integrates with a simple REST API:
class SimpleApiNode implements Node {
private apiKey: string;
private baseUrl: string = "https://api.example.com";
supportedTokens: ChainToken[] = [];
supportedChainIds: string[] = [];
constructor(apiKey: string) {
this.apiKey = apiKey;
}
async syncState(): Promise<NodeResult<void>> {
try {
const response = await fetch(`${this.baseUrl}/tokens`, {
headers: { 'Authorization': `Bearer ${this.apiKey}` }
});
const data = await response.json();
this.supportedTokens = data.tokens.map(token => ({
chain_id: token.chainId,
address: token.address,
decimals: token.decimals
}));
this.supportedChainIds = [...new Set(data.tokens.map(t => t.chainId))];
} catch (error) {
return new NodeError("Failed to sync tokens", NodeError.errorCodes.NetworkError);
}
}
// Implement other methods...
}
Example 2: Multi-Mode Node
A node that supports multiple modes with different configurations:
enum MyNodeMode {
FAST,
CHEAP,
SECURE
}
class MyNode implements Node {
constructor(private mode: MyNodeMode) {
// Initialize based on mode
switch (mode) {
case MyNodeMode.FAST:
this.nodeConfig.timeout = 10000;
break;
case MyNodeMode.CHEAP:
this.nodeConfig.timeout = 60000;
break;
case MyNodeMode.SECURE:
this.nodeConfig.timeout = 30000;
break;
}
}
// Mode-specific implementations...
}
Real-World References
NEAR Intents Integration
Location: ts/src/nodes/near/common.ts
Key patterns:
- Parameter shaping for quotes
- Address validation
- Multi-chain calldata generation
- Asset ID resolution with fallbacks
// Example: Address validation
private validateAndFormatAddress(address: string): string {
// NEAR-specific address validation and formatting
}
// Example: Asset ID resolution
private findAssetId(token: ChainToken): string | null {
// Resolve asset IDs with multiple fallback strategies
}
Meson Swapping Integration
Location: ts/src/nodes/meson/common.ts
Key patterns:
- Price and limits checking
- Transaction data encoding
- Error code decoding
- Cache management for limits
// Example: Price quote with limits check
private async getPriceQuote(input: SwapRequest): Promise<NodeResult<any>> {
// Check limits first
const limits = await this.getLimits();
// Then get price quote
// Handle API errors with decoded error codes
}
GasZip Native Bridging
Location: ts/src/nodes/gaszip/common.ts and ts/src/nodes/gaszip/solana-calldata.ts
Key patterns:
- Native token handling
- Chain ID mapping (name ↔ ID)
- Solana transaction construction
- Capacity validation
// Example: Chain ID normalization
private normalizeChainId(chainId: string): string {
// Map between numeric IDs and human-readable names
}
// Example: Solana calldata generation
private generateSolanaCalldata(request: SwapRequest): string {
// Construct Solana transaction instructions
}
Common Patterns
Token Address Normalization
private normalizeTokenAddress(address: string, chainId: string): string {
// Handle native tokens
if (address === '0x0000000000000000000000000000000000000000') {
return this.getNativeTokenAddress(chainId);
}
// Normalize EVM addresses
if (address.startsWith('0x')) {
return address.toLowerCase();
}
return address;
}
Chain ID Normalization
private normalizeChainId(chainId: string): string {
const chainIdMap: Record<string, string> = {
'1': 'ethereum',
'137': 'polygon',
'56': 'bsc',
};
return chainIdMap[chainId] || chainId.toLowerCase();
}
API Call with Retry Logic
private async makeApiCall<T>(url: string, options: RequestInit): Promise<NodeResult<T>> {
const maxRetries = this.nodeConfig.retryConfig?.maxRetries || 3;
let lastError: Error;
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const response = await fetch(url, {
...options,
timeout: this.nodeConfig.timeout,
});
if (response.ok) {
return await response.json();
}
lastError = new Error(`HTTP ${response.status}: ${response.statusText}`);
// Don't retry on client errors
if (response.status >= 400 && response.status < 500) {
break;
}
} catch (error) {
lastError = error as Error;
}
// Wait before retry
if (attempt < maxRetries - 1) {
await new Promise(resolve =>
setTimeout(resolve, this.nodeConfig.retryConfig?.retryDelay || 1000)
);
}
}
return new NodeError(
`API call failed after ${maxRetries} attempts: ${lastError.message}`,
NodeError.errorCodes.NetworkError
);
}
Next Steps
- Testing - Write tests for your implementation
- Best Practices - Follow development guidelines