Refactor to compute GasPrices differently
This commit is contained in:
parent
ef228254b3
commit
f78674578b
@ -1,6 +1,5 @@
|
|||||||
import 'dotenv/config.js';
|
import 'dotenv/config.js';
|
||||||
import { WebSocketProvider, formatUnits } from 'ethers';
|
import { WebSocketProvider, formatUnits } from 'ethers';
|
||||||
import { sortBy } from 'lodash';
|
|
||||||
import { Observable, throwError } from 'rxjs';
|
import { Observable, throwError } from 'rxjs';
|
||||||
import { catchError, map, scan, retry } from 'rxjs/operators';
|
import { catchError, map, scan, retry } from 'rxjs/operators';
|
||||||
|
|
||||||
@ -10,47 +9,51 @@ const rpcUrl = process.env.RPC_URL || "wss://ropsten.infura.io/ws/v3/YOUR_INFURA
|
|||||||
|
|
||||||
const provider = new WebSocketProvider(rpcUrl);
|
const provider = new WebSocketProvider(rpcUrl);
|
||||||
|
|
||||||
const blockGasPricesObservable = new Observable<GasPrices>((observer) => {
|
const blockBaseFeePerGasObservable$ = new Observable<number>((observer) => {
|
||||||
provider.on('block', async (blockNumber) => {
|
provider.on('block', async (blockNumber) => {
|
||||||
try {
|
try {
|
||||||
const block = await provider.getBlock(blockNumber, true);
|
const { baseFeePerGas } = await provider.getBlock(blockNumber, true) || {};
|
||||||
|
|
||||||
if (!block) throw new Error(`Error fetching block! ${blockNumber}`);
|
if (!baseFeePerGas) throw new Error(`Error fetching block! ${blockNumber}`);
|
||||||
|
|
||||||
const gasPrices = sortBy(block.prefetchedTransactions, ['gasPrice']).map(x => x.gasPrice);
|
|
||||||
const fast = Number(formatUnits(gasPrices[Math.floor(gasPrices.length * 0.9)], "gwei"));
|
|
||||||
const average = Number(formatUnits(gasPrices[Math.floor(gasPrices.length / 2)], "gwei"));
|
|
||||||
const slow = Number(formatUnits(gasPrices[Math.floor(gasPrices.length * 0.05)], "gwei"));
|
|
||||||
|
|
||||||
// Log averages every 10 blocks
|
// Log averages every 10 blocks
|
||||||
if (blockNumber % 10 == 0) console.log(`Found new block data for ${blockNumber}!
|
if (blockNumber % 10 == 0) console.log(
|
||||||
Gas price spreads: ⚡ ${fast.toFixed(2)} ⦚⦚ 🚶 ${average.toFixed(2)} ⦚⦚ 🐢 ${slow.toFixed(2)} Gwei`)
|
`Found new block data for ${blockNumber}! Gas price: 🐢 ${Number(formatUnits(baseFeePerGas, "gwei")).toFixed(2)} Gwei`
|
||||||
|
)
|
||||||
|
|
||||||
observer.next({ fast, average, slow } as GasPrices);
|
observer.next(Number(formatUnits(baseFeePerGas, "gwei")));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
observer.error(`Error fetching block! ${error}`);
|
observer.error(`Error fetching block! ${error}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const averageGasPricesObservable = blockGasPricesObservable.pipe(
|
const baseGasPricesObservable$ = blockBaseFeePerGasObservable$.pipe(
|
||||||
scan((acc, curr) => [...acc.slice(-19), curr], [] as GasPrices[]),
|
scan<number, GasPrices>(
|
||||||
map((blocks) => {
|
(acc: GasPrices, curr: number): GasPrices => {
|
||||||
const { fast, average, slow } = blocks
|
// Keep only the 20 latest values
|
||||||
.reduce((sum, block) =>
|
const values: number[] = acc.values ? [...acc.values.slice(-19), curr] : [curr];
|
||||||
({ // Find sums
|
|
||||||
fast: sum.fast + block.fast,
|
const fast: number = Math.max(...values);
|
||||||
average: sum.average + block.average,
|
const slow: number = Math.min(...values);
|
||||||
slow: sum.slow + block.slow
|
const sum: number = values.reduce((a, b) => a + b, 0);
|
||||||
}), { fast: 0, average: 0, slow: 0 } as GasPrices);
|
const average: number = sum / values.length;
|
||||||
return { // Then average them
|
|
||||||
fast: Math.round(fast / blocks.length),
|
return { values, fast, slow, average };
|
||||||
average: Math.round(average / blocks.length),
|
},
|
||||||
slow: Math.round(slow / blocks.length),
|
{ values: [], fast: -Infinity, slow: Infinity, average: NaN } // Initial value
|
||||||
} as GasPrices;
|
),
|
||||||
|
// 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))),
|
catchError(err => throwError(() => new Error(err))),
|
||||||
retry(2)
|
retry(2)
|
||||||
);
|
);
|
||||||
|
|
||||||
export { averageGasPricesObservable };
|
export { baseGasPricesObservable$ };
|
@ -9,7 +9,7 @@ import fs from 'node:fs';
|
|||||||
import path from 'node:path';
|
import path from 'node:path';
|
||||||
import { ActivityType, GatewayIntentBits } from 'discord.js';
|
import { ActivityType, GatewayIntentBits } from 'discord.js';
|
||||||
|
|
||||||
import { averageGasPricesObservable } from './blockchain';
|
import { baseGasPricesObservable$ } from './blockchain';
|
||||||
import { deployCommands } from './deploy';
|
import { deployCommands } from './deploy';
|
||||||
import { DiscordClient } from './discordClient';
|
import { DiscordClient } from './discordClient';
|
||||||
import { createGasAlertChecker } from './gasAlertChecker';
|
import { createGasAlertChecker } from './gasAlertChecker';
|
||||||
@ -76,7 +76,7 @@ client.login(token)
|
|||||||
})
|
})
|
||||||
.then(() => {
|
.then(() => {
|
||||||
// Start listening to blockchain
|
// Start listening to blockchain
|
||||||
averageGasPricesObservable.subscribe({
|
baseGasPricesObservable$.subscribe({
|
||||||
next: async (averageGasPrices) => {
|
next: async (averageGasPrices) => {
|
||||||
setDiscordStatus(averageGasPrices);
|
setDiscordStatus(averageGasPrices);
|
||||||
await redisClient.set('current-prices', JSON.stringify(averageGasPrices))
|
await redisClient.set('current-prices', JSON.stringify(averageGasPrices))
|
||||||
|
3
types/gasPrices.d.ts
vendored
3
types/gasPrices.d.ts
vendored
@ -2,4 +2,5 @@ export interface GasPrices {
|
|||||||
fast: number;
|
fast: number;
|
||||||
average: number;
|
average: number;
|
||||||
slow: number;
|
slow: number;
|
||||||
}
|
values?: number[];
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user