rpcUtils.js
1 import axios from 'axios'; 2 import { getProxyUrl, getApiConfig, handleApiError } from './apiUtils'; 3 4 /** 5 * Make a JSON-RPC request to the proxy 6 * @param {string} method - RPC method name 7 * @param {Array} params - RPC method parameters 8 * @param {string} network - Network path (e.g., 'ethereum/mainnet') 9 * @param {string} token - Optional JWT token 10 * @param {Object} basicAuth - Optional basic auth {username, password} 11 * @returns {Promise<Object>} RPC response or error 12 */ 13 export const makeRpcRequest = async (method, params = [], network = 'ethereum/mainnet', token = null, basicAuth = null) => { 14 try { 15 const proxyUrl = getProxyUrl(); 16 const rpcPayload = { 17 jsonrpc: '2.0', 18 method: method, 19 params: params, 20 id: 1 // Use constant ID for better caching since we handle requests synchronously 21 }; 22 23 console.log(`Making ${method} request to ${network}:`, rpcPayload); 24 25 const response = await axios.post( 26 `${proxyUrl}/${network}`, 27 rpcPayload, 28 getApiConfig(token, basicAuth) 29 ); 30 31 console.log(`${method} response:`, response.data); 32 33 return { 34 success: true, 35 data: response.data, 36 method: method, 37 network: network, 38 timestamp: new Date().toLocaleString() 39 }; 40 } catch (error) { 41 console.error(`Error making ${method} request:`, error); 42 const errorInfo = handleApiError(error); 43 44 return { 45 success: false, 46 error: errorInfo, 47 method: method, 48 network: network, 49 timestamp: new Date().toLocaleString() 50 }; 51 } 52 }; 53 54 /** 55 * Make a permanent cache RPC request (eth_chainId) 56 * @param {string} network - Network path 57 * @param {string} token - Optional JWT token 58 * @param {Object} basicAuth - Optional basic auth 59 * @returns {Promise<Object>} RPC response or error 60 */ 61 export const makePermanentCacheRequest = async (network = 'ethereum/mainnet', token = null, basicAuth = null) => { 62 const result = await makeRpcRequest('eth_chainId', [], network, token, basicAuth); 63 return { ...result, cacheType: 'permanent' }; 64 }; 65 66 /** 67 * Make a short cache RPC request (eth_blockNumber) 68 * @param {string} network - Network path 69 * @param {string} token - Optional JWT token 70 * @param {Object} basicAuth - Optional basic auth 71 * @returns {Promise<Object>} RPC response or error 72 */ 73 export const makeShortCacheRequest = async (network = 'ethereum/mainnet', token = null, basicAuth = null) => { 74 const result = await makeRpcRequest('eth_blockNumber', [], network, token, basicAuth); 75 return { ...result, cacheType: 'short' }; 76 }; 77 78 /** 79 * Make a minimal cache RPC request (eth_gasPrice) 80 * @param {string} network - Network path 81 * @param {string} token - Optional JWT token 82 * @param {Object} basicAuth - Optional basic auth 83 * @returns {Promise<Object>} RPC response or error 84 */ 85 export const makeMinimalCacheRequest = async (network = 'ethereum/mainnet', token = null, basicAuth = null) => { 86 const result = await makeRpcRequest('eth_gasPrice', [], network, token, basicAuth); 87 return { ...result, cacheType: 'minimal' }; 88 }; 89 90 /** 91 * Make multiple RPC requests in parallel 92 * @param {Array} requests - Array of request objects {method, params, cacheType} 93 * @param {string} network - Network path 94 * @param {string} token - Optional JWT token 95 * @param {Object} basicAuth - Optional basic auth 96 * @returns {Promise<Array>} Array of RPC responses 97 */ 98 export const makeParallelRpcRequests = async (requests, network = 'ethereum/mainnet', token = null, basicAuth = null) => { 99 const promises = requests.map(request => { 100 const result = makeRpcRequest(request.method, request.params || [], network, token, basicAuth); 101 if (request.cacheType) { 102 return result.then(r => ({ ...r, cacheType: request.cacheType })); 103 } 104 return result; 105 }); 106 107 try { 108 return await Promise.all(promises); 109 } catch (error) { 110 console.error('Error in parallel RPC requests:', error); 111 throw error; 112 } 113 }; 114 115 /** 116 * Make all three cache type requests (permanent, short, minimal) 117 * @param {string} network - Network path 118 * @param {string} token - Optional JWT token 119 * @param {Object} basicAuth - Optional basic auth 120 * @returns {Promise<Object>} Object with results for each cache type 121 */ 122 export const makeAllCacheTypeRequests = async (network = 'ethereum/mainnet', token = null, basicAuth = null) => { 123 try { 124 const requests = [ 125 { method: 'eth_chainId', params: [], cacheType: 'permanent' }, 126 { method: 'eth_blockNumber', params: [], cacheType: 'short' }, 127 { method: 'eth_gasPrice', params: [], cacheType: 'minimal' } 128 ]; 129 130 const results = await makeParallelRpcRequests(requests, network, token, basicAuth); 131 132 return { 133 permanent: results[0], 134 short: results[1], 135 minimal: results[2] 136 }; 137 } catch (error) { 138 console.error('Error making all cache type requests:', error); 139 throw error; 140 } 141 }; 142 143 /** 144 * Test RPC connectivity with basic method 145 * @param {string} network - Network path 146 * @param {string} token - Optional JWT token 147 * @param {Object} basicAuth - Optional basic auth 148 * @returns {Promise<Object>} Connection test result 149 */ 150 export const testRpcConnectivity = async (network = 'ethereum/mainnet', token = null, basicAuth = null) => { 151 const startTime = Date.now(); 152 153 try { 154 const result = await makeRpcRequest('eth_blockNumber', [], network, token, basicAuth); 155 const responseTime = Date.now() - startTime; 156 157 return { 158 success: result.success, 159 network: network, 160 responseTime: responseTime, 161 blockNumber: result.success ? result.data.result : null, 162 error: result.success ? null : result.error, 163 timestamp: new Date().toLocaleString() 164 }; 165 } catch (error) { 166 const responseTime = Date.now() - startTime; 167 return { 168 success: false, 169 network: network, 170 responseTime: responseTime, 171 blockNumber: null, 172 error: handleApiError(error), 173 timestamp: new Date().toLocaleString() 174 }; 175 } 176 }; 177 178 /** 179 * Format RPC result for display 180 * @param {Object} result - RPC result object 181 * @returns {Object} Formatted result for UI display 182 */ 183 export const formatRpcResult = (result) => { 184 if (!result) return null; 185 186 return { 187 method: result.method, 188 network: result.network, 189 cacheType: result.cacheType || 'unknown', 190 timestamp: result.timestamp, 191 success: result.success, 192 responseData: result.success ? result.data : null, 193 error: result.success ? null : result.error, 194 displayValue: result.success ? result.data.result : 'Error' 195 }; 196 }; 197 198 /** 199 * Get display color for cache type 200 * @param {string} cacheType - Cache type (permanent, short, minimal) 201 * @returns {string} CSS color value 202 */ 203 export const getCacheTypeColor = (cacheType) => { 204 switch (cacheType) { 205 case 'permanent': 206 return '#4CAF50'; 207 case 'short': 208 return '#FF9800'; 209 case 'minimal': 210 return '#2196F3'; 211 default: 212 return '#666'; 213 } 214 }; 215 216 /** 217 * Get display emoji for cache type 218 * @param {string} cacheType - Cache type (permanent, short, minimal) 219 * @returns {string} Emoji character 220 */ 221 export const getCacheTypeEmoji = (cacheType) => { 222 switch (cacheType) { 223 case 'permanent': 224 return '🔒'; 225 case 'short': 226 return '⏱️'; 227 case 'minimal': 228 return '⚡'; 229 default: 230 return '❓'; 231 } 232 };