@tetherto/wdk-provider-failover
v1.0.0-beta.2
Published
A simple package to initialize WDK wallet instances with failover capabilities.
Readme
@tetherto/wdk-provider-failover
A resilient wrapper for WDK wallet instances that provides automatic failover across multiple provider configurations with configurable retry logic.
Features
- Automatic failover - Cascades through multiple provider configurations when failures occur
- Configurable retries - Retry failed operations with exponential backoff and jitter
- Lazy instantiation - Wallet instances are created only when needed
- Proxy-based - Transparent wrapper that preserves the original wallet API
- Lifecycle management - Proper cleanup of resources via
dispose()
Installation
npm install @tetherto/wdk-provider-failoverUsage
Basic Example
import { createFallbackWallet } from '@tetherto/wdk-provider-failover'
import { WalletAccountReadOnlyEvm } from '@tetherto/wdk-wallet-evm'
const wallet = createFallbackWallet(
WalletAccountReadOnlyEvm,
['0x742d35Cc6634C0532925a3b844Bc9e7595f...'], // constructor args
{
primary: { provider: 'https://mainnet.infura.io/v3/YOUR_KEY' },
fallbacks: [
{ provider: 'https://eth.llamarpc.com' },
{ provider: 'https://ethereum.publicnode.com' }
]
}
)
// Use the wallet as normal - failover is automatic
const balance = await wallet.getBalance()
// Clean up when done
await wallet.dispose()With Custom Options
const wallet = createFallbackWallet(
WalletAccountReadOnlyEvm,
[address],
{
primary: { provider: primaryRpcUrl },
fallbacks: [
{ provider: fallbackRpcUrl1 },
{ provider: fallbackRpcUrl2 }
],
fallbackOptions: {
timeout: 5000, // 5 second timeout per call
maxRetries: 3, // Retry current provider 3 times before switching
retryDelay: 1000, // Base delay between retries (ms)
exponentialBackoff: true, // Double delay on each retry
jitter: true, // Add randomness to prevent thundering herd
fallbackMethods: ['getBalance', 'getTransactions'], // Only wrap specific methods
logger: customLogger, // Custom logging function
onFallback: (index, config) => {
console.log(`Switching to provider ${index}`)
},
onConfigSwitch: (index, config) => {
console.log(`Successfully using provider ${index}`)
}
}
}
)API
createFallbackWallet(WalletClass, constructorArgs, config)
Factory function that creates a failover-wrapped wallet instance.
Parameters:
| Parameter | Type | Description |
|-----------|------|-------------|
| WalletClass | class | The wallet class to instantiate |
| constructorArgs | array | Arguments passed to the wallet constructor (before config) |
| config | object | Configuration object (see below) |
Config Object:
| Property | Type | Description |
|----------|------|-------------|
| primary | object | Primary provider configuration |
| fallbacks | array | Array of fallback provider configurations |
| fallbackOptions | object | Options for failover behavior (see below) |
Fallback Options:
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| timeout | number | 10000 | Timeout per method call (ms) |
| maxRetries | number | 3 | Retries per provider before switching |
| retryDelay | number | 1000 | Base delay between retries (ms) |
| exponentialBackoff | boolean | true | Double delay on each retry |
| jitter | boolean | true | Add ±15% randomness to delays |
| fallbackMethods | string[] | [] | Methods to wrap (empty = all methods) |
| logger | function | console | Custom logger function |
| onFallback | function | - | Called when switching to a fallback provider |
| onConfigSwitch | function | - | Called on successful operation after retries |
Proxy Methods
The returned proxy exposes additional utility methods:
| Method | Returns | Description |
|--------|---------|-------------|
| dispose() | Promise<void> | Disposes all wallet instances |
| getActiveIndex() | number | Current active provider index |
| getActiveConfig() | object | Current active provider config |
| getInstancesCount() | number | Total number of configured providers |
| switchTo(index) | number | Manually switch to a specific provider |
| getInstanceUnsafe() | object | Get the current wallet instance directly |
How It Works
- When a method is called on the proxy, it attempts the operation on the current provider
- If the call fails or times out, it retries up to
maxRetriestimes with backoff - After exhausting retries, it switches to the next provider in the cascade
- This continues until success or all providers have been exhausted
- On success, callbacks are invoked to notify of the active configuration
┌─────────────┐ fail ┌─────────────┐ fail ┌─────────────┐
│ Primary │──── retry ───▶│ Fallback 1 │──── retry ───▶│ Fallback 2 │
│ Provider │ (3 times) │ Provider │ (3 times) │ Provider │
└─────────────┘ └─────────────┘ └─────────────┘Custom Logger
The logger function receives structured log data:
const logger = (level, message, meta) => {
// level: 'debug' | 'info' | 'warn' | 'error'
// message: string description
// meta: object with additional context
console.log(`[${level}] ${message}`, meta)
}License
Apache-2.0
