59 lines
2.0 KiB
TypeScript
59 lines
2.0 KiB
TypeScript
import 'dotenv/config.js';
|
|
import { WebSocketProvider, formatUnits } from 'ethers';
|
|
import { Observable, throwError } from 'rxjs';
|
|
import { catchError, map, scan, retry } 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 blockBaseFeePerGasObservable$ = new Observable<number>((observer) => {
|
|
provider.on('block', async (blockNumber) => {
|
|
try {
|
|
const { baseFeePerGas } = await provider.getBlock(blockNumber, true) || {};
|
|
|
|
if (!baseFeePerGas) throw new Error(`Error fetching block! ${blockNumber}`);
|
|
|
|
// Log averages every 10 blocks
|
|
if (blockNumber % 10 == 0) console.log(
|
|
`Found new block data for ${blockNumber}! Gas price: 🐢 ${Number(formatUnits(baseFeePerGas, "gwei")).toFixed(2)} Gwei`
|
|
)
|
|
|
|
observer.next(Number(formatUnits(baseFeePerGas, "gwei")));
|
|
} catch (error) {
|
|
observer.error(`Error fetching block! ${error}`);
|
|
}
|
|
});
|
|
});
|
|
|
|
const baseGasPricesObservable$ = blockBaseFeePerGasObservable$.pipe(
|
|
scan<number, GasPrices>(
|
|
(acc: GasPrices, curr: number): GasPrices => {
|
|
// Keep only the 20 latest values
|
|
const values: number[] = acc.values ? [...acc.values.slice(-19), curr] : [curr];
|
|
|
|
const fast: number = Math.max(...values);
|
|
const slow: number = Math.min(...values);
|
|
const sum: number = values.reduce((a, b) => a + b, 0);
|
|
const average: number = sum / values.length;
|
|
|
|
return { values, fast, slow, average };
|
|
},
|
|
{ values: [], fast: -Infinity, slow: Infinity, average: NaN } // Initial value
|
|
),
|
|
// Only emit the computed prices
|
|
map<GasPrices, GasPrices>((computedGasPrices: GasPrices): GasPrices => {
|
|
const { fast, average, slow } = computedGasPrices;
|
|
return {
|
|
fast: Math.round(fast),
|
|
average: Math.round(average),
|
|
slow: Math.round(slow)
|
|
};
|
|
}),
|
|
catchError(err => throwError(() => new Error(err))),
|
|
retry(2)
|
|
);
|
|
|
|
export { baseGasPricesObservable$ }; |