Custom provider
Learn how to configure custom providers and RPC endpoints for optimal performance.
Basic Provider Setup
const { ethers } = require('ethers')
const { MoroBestRate } = require('@moromoro/moro-sdk')
// JsonRpcProvider
const provider = new ethers.providers.JsonRpcProvider(
'https://rpc.hyperliquid.xyz/evm'
)
const moroClient = new MoroBestRate(provider, 'hyperevm')Using Custom RPC Endpoints
// High-performance RPC
const customProvider = new ethers.providers.JsonRpcProvider(
'https://your-custom-rpc.com',
{
chainId: 998, // HyperEVM chain ID (example)
name: 'hyperevm'
}
)
const moroClient = new MoroBestRate(customProvider, 'hyperevm')Provider with API Key
const apiKey = process.env.RPC_API_KEY
const provider = new ethers.providers.JsonRpcProvider(
`https://your-rpc-provider.com/${apiKey}`
)
const moroClient = new MoroBestRate(provider, 'hyperevm')WebSocket Provider
For real-time updates and better performance:
const { ethers } = require('ethers')
const { MoroBestRate } = require('@moromoro/moro-sdk')
const wsProvider = new ethers.providers.WebSocketProvider(
'wss://your-websocket-endpoint.com'
)
const moroClient = new MoroBestRate(wsProvider, 'hyperevm')
// Remember to close connection when done
process.on('exit', () => {
wsProvider.destroy()
})Fallback Provider
Use multiple RPC endpoints for reliability:
const { ethers } = require('ethers')
const { MoroBestRate } = require('@moromoro/moro-sdk')
const provider = new ethers.providers.FallbackProvider([
{
provider: new ethers.providers.JsonRpcProvider('https://rpc1.hyperliquid.xyz/evm'),
priority: 1,
stallTimeout: 2000
},
{
provider: new ethers.providers.JsonRpcProvider('https://rpc2.hyperliquid.xyz/evm'),
priority: 2,
stallTimeout: 2000
}
])
const moroClient = new MoroBestRate(provider, 'hyperevm')Provider Caching
Reuse provider instances for better performance:
const { ethers } = require('ethers')
const { MoroBestRate } = require('@moromoro/moro-sdk')
class ProviderManager {
constructor() {
this.providers = new Map()
}
getProvider(network, rpcUrl) {
const key = `${network}-${rpcUrl}`
if (!this.providers.has(key)) {
const provider = new ethers.providers.JsonRpcProvider(rpcUrl)
this.providers.set(key, provider)
}
return this.providers.get(key)
}
getClient(network, rpcUrl, options = {}) {
const provider = this.getProvider(network, rpcUrl)
return new MoroBestRate(provider, network, options)
}
}
// Usage
const manager = new ProviderManager()
const client1 = manager.getClient('hyperevm', 'https://rpc.hyperliquid.xyz/evm')
const client2 = manager.getClient('hyperevm', 'https://rpc.hyperliquid.xyz/evm') // Reuses providerCustom Network Configuration
const { ethers } = require('ethers')
const { initProvider } = require('@moromoro/moro-sdk')
// Using SDK's provider initializer
const provider = initProvider('https://rpc.hyperliquid.xyz/evm')
// Or custom configuration
const customProvider = new ethers.providers.JsonRpcProvider(
'https://your-rpc.com',
{
chainId: 998,
name: 'hyperevm'
}
)Provider with Retry Logic
const { ethers } = require('ethers')
class RetryProvider extends ethers.providers.JsonRpcProvider {
constructor(url, network, maxRetries = 3) {
super(url, network)
this.maxRetries = maxRetries
}
async send(method, params) {
let lastError
for (let i = 0; i < this.maxRetries; i++) {
try {
return await super.send(method, params)
} catch (error) {
lastError = error
console.log(`Retry ${i + 1}/${this.maxRetries} for ${method}`)
await new Promise(r => setTimeout(r, 1000 * (i + 1)))
}
}
throw lastError
}
}
const provider = new RetryProvider('https://rpc.hyperliquid.xyz/evm', 'hyperevm', 3)
const moroClient = new MoroBestRate(provider, 'hyperevm')Provider Performance Monitoring
class MonitoredProvider extends ethers.providers.JsonRpcProvider {
constructor(url, network) {
super(url, network)
this.stats = {
calls: 0,
errors: 0,
totalTime: 0
}
}
async send(method, params) {
this.stats.calls++
const start = Date.now()
try {
const result = await super.send(method, params)
this.stats.totalTime += Date.now() - start
return result
} catch (error) {
this.stats.errors++
throw error
}
}
getStats() {
return {
...this.stats,
avgTime: this.stats.calls > 0 ? this.stats.totalTime / this.stats.calls : 0,
errorRate: this.stats.calls > 0 ? this.stats.errors / this.stats.calls : 0
}
}
}
const provider = new MonitoredProvider('https://rpc.hyperliquid.xyz/evm', 'hyperevm')
const moroClient = new MoroBestRate(provider, 'hyperevm')
// After some operations
console.log('Provider stats:', provider.getStats())Environment-Based Configuration
const { ethers } = require('ethers')
const { MoroBestRate } = require('@moromoro/moro-sdk')
function getProvider(network) {
const rpcUrls = {
hyperevm: {
production: process.env.HYPEREVM_RPC_PROD,
development: 'https://rpc.hyperliquid.xyz/evm',
test: process.env.HYPEREVM_RPC_TEST
},
bsc: {
production: process.env.BSC_RPC_PROD,
development: 'https://bsc-dataseed.binance.org',
test: process.env.BSC_RPC_TEST
}
}
const env = process.env.NODE_ENV || 'development'
const rpcUrl = rpcUrls[network][env]
if (!rpcUrl) {
throw new Error(`No RPC URL configured for ${network} in ${env}`)
}
return new ethers.providers.JsonRpcProvider(rpcUrl)
}
// Usage
const provider = getProvider('hyperevm')
const moroClient = new MoroBestRate(provider, 'hyperevm')Provider Connection Testing
async function testProvider(provider) {
try {
// Test 1: Get block number
const blockNumber = await provider.getBlockNumber()
console.log('✓ Block number:', blockNumber)
// Test 2: Get network
const network = await provider.getNetwork()
console.log('✓ Network:', network.name, 'Chain ID:', network.chainId)
// Test 3: Get gas price
const gasPrice = await provider.getGasPrice()
console.log('✓ Gas price:', ethers.utils.formatUnits(gasPrice, 'gwei'), 'gwei')
// Test 4: Response time
const start = Date.now()
await provider.getBlockNumber()
const responseTime = Date.now() - start
console.log('✓ Response time:', responseTime, 'ms')
return {
working: true,
blockNumber,
network,
gasPrice: gasPrice.toString(),
responseTime
}
} catch (error) {
console.error('✗ Provider test failed:', error.message)
return {
working: false,
error: error.message
}
}
}
// Test your provider
const provider = new ethers.providers.JsonRpcProvider('https://rpc.hyperliquid.xyz/evm')
testProvider(provider).then(result => {
console.log('Test result:', result)
})Multi-Provider Pool
class ProviderPool {
constructor(urls, network) {
this.providers = urls.map(url =>
new ethers.providers.JsonRpcProvider(url, network)
)
this.currentIndex = 0
}
getProvider() {
const provider = this.providers[this.currentIndex]
this.currentIndex = (this.currentIndex + 1) % this.providers.length
return provider
}
async getWorkingProvider() {
for (const provider of this.providers) {
try {
await provider.getBlockNumber()
return provider
} catch (error) {
console.log('Provider failed, trying next...')
}
}
throw new Error('No working providers available')
}
}
// Usage
const pool = new ProviderPool(
[
'https://rpc1.hyperliquid.xyz/evm',
'https://rpc2.hyperliquid.xyz/evm'
],
'hyperevm'
)
const provider = await pool.getWorkingProvider()
const moroClient = new MoroBestRate(provider, 'hyperevm')See Also
Gas Optimization