import 'dotenv/config.js'; import { WebSocketProvider, formatUnits } from 'ethers'; import { Observable } from 'rxjs'; import { map, scan } from 'rxjs/operators'; import { GasPrices } from '../types/gasPrices'; const rpcUrl = process.env.RPC_URL || "wss://ropsten.infura.io/ws/v3/YOUR_INFURA_PROJECT_ID"; const provider = new WebSocketProvider(rpcUrl); const blockGasPricesObservable = new Observable((observer) => { provider.on('block', async (blockNumber) => { try { const block = await provider.getBlock(blockNumber, true); if (!block) throw new Error(`Error fetching block! ${blockNumber}`); const gasPrices = block.prefetchedTransactions.map((tx) => tx.gasPrice); const fast = Number(formatUnits(gasPrices[Math.floor(gasPrices.length * 0.1)], "gwei")); const average = Number(formatUnits(gasPrices[Math.floor(gasPrices.length / 2)], "gwei")); const slow = Number(formatUnits(gasPrices[Math.floor(gasPrices.length * 0.95)], "gwei")); // Log averages every 10 blocks if (blockNumber % 10 == 0) console.log(`Found new block data for ${blockNumber}! Base average transaction cost: ${slow} Gwei`) observer.next({ fast, average, slow } as GasPrices); } catch (error) { observer.error(`Error fetching block! ${error}`); } }); }); const averageGasPricesObservable = blockGasPricesObservable.pipe( scan((acc, curr) => [...acc.slice(-19), curr], [] as GasPrices[]), map((blocks) => { const fastSum = blocks.reduce((sum, block) => sum + block.fast, 0); const averageSum = blocks.reduce((sum, block) => sum + block.average, 0); const slowSum = blocks.reduce((sum, block) => sum + block.slow, 0); return { fast: Math.round(fastSum / blocks.length), average: Math.round(averageSum / blocks.length), slow: Math.round(slowSum / blocks.length), }; }) ); export { averageGasPricesObservable };