From 0db98d33ecd9ff07bfbc78d50d3711b0b8408656 Mon Sep 17 00:00:00 2001 From: wslyvh Date: Sun, 4 Aug 2024 16:36:13 +0200 Subject: [PATCH] db update --- src/components/charts/trend.tsx | 4 - src/components/featured.module.scss | 8 ++ src/components/featured.tsx | 2 + src/hooks/useGasPrice.tsx | 1 - src/pages/gas.tsx | 25 +++--- src/pages/gas/[network].tsx | 33 +++---- src/services/indexer.ts | 135 +++++----------------------- src/types/gas.ts | 3 +- 8 files changed, 55 insertions(+), 156 deletions(-) diff --git a/src/components/charts/trend.tsx b/src/components/charts/trend.tsx index 46cf9e1e..7c6aadb0 100644 --- a/src/components/charts/trend.tsx +++ b/src/components/charts/trend.tsx @@ -26,10 +26,6 @@ export function TrendChart(props: Props) { }, } const series = [ - { - name: 'median', - data: props.data.map((item) => Math.round(item.median * 100) / 100), - }, { name: 'baseFee', data: props.data.map((item) => Math.round(item.baseFee * 100) / 100), diff --git a/src/components/featured.module.scss b/src/components/featured.module.scss index ec54f7db..67cc0728 100644 --- a/src/components/featured.module.scss +++ b/src/components/featured.module.scss @@ -30,6 +30,14 @@ } } + .double { + grid-template-columns: 1fr 1fr; + + @media (max-width: $screen-640) { + grid-template-columns: 1fr; + } + } + .rows { display: grid; gap: $gap-16; diff --git a/src/components/featured.tsx b/src/components/featured.tsx index e8a98d5d..1295efa7 100644 --- a/src/components/featured.tsx +++ b/src/components/featured.tsx @@ -8,12 +8,14 @@ interface Props { type?: 'grid' | 'rows' className?: string children: ReactNode + double?: boolean } export function Featured(props: Props) { let className = `${styles.container}` if (props.className) className += ` ${props.className}` let type = styles.grid + if (props.double) type += ` ${styles.double}` if (props.type) type = styles[props.type] return ( diff --git a/src/hooks/useGasPrice.tsx b/src/hooks/useGasPrice.tsx index 5724ad0e..d9804e9b 100644 --- a/src/hooks/useGasPrice.tsx +++ b/src/hooks/useGasPrice.tsx @@ -24,7 +24,6 @@ export function useGasPrice(network: string = '', interval: number = 12000) { try { const provider = !network ? getDefaultProvider() : GetRpcProvider(network as any) const feeData = await provider.getFeeData() - console.log('FEE DATA', feeData) if (feeData.gasPrice && feeData.maxPriorityFeePerGas) { const gasPrice = Math.round(Number(formatUnits(feeData.gasPrice, 'gwei')) * 100) / 100 diff --git a/src/pages/gas.tsx b/src/pages/gas.tsx index 44a24879..5b0d0cc0 100644 --- a/src/pages/gas.tsx +++ b/src/pages/gas.tsx @@ -35,7 +35,7 @@ export default function Index(props: Props) {
- +

⛽ Current

@@ -49,18 +49,7 @@ export default function Index(props: Props) {

🕘 Avg/last hour


- baseFee: {Math.round(props.gasData.lastHour.baseFee * 100) / 100} -
- median: {Math.round(props.gasData.lastHour.median * 100) / 100} -
- - -
-

📅 Avg/24 hours

-
- baseFee: {Math.round(props.gasData.lastDay.baseFee * 100) / 100} -
- median: {Math.round(props.gasData.lastDay.median * 100) / 100} + baseFee: {props.gasData.lastHour}
@@ -96,12 +85,18 @@ export default function Index(props: Props) {
  • Ethereum Gas Tracker
  • +
  • + Arbitrum Gas Tracker +
  • Optimism Gas Tracker
  • Polygon Gas Tracker
  • +
  • + Base Gas Tracker +
  • @@ -155,13 +150,13 @@ export const getStaticProps: GetStaticProps = async () => { const categories = await service.GetCategories() const gasData = await GetGasData() - const hourlyAverages = await GetAverage('hour', 168) + const averages = await GetAverage('hour', 168) return { props: { categories, gasData, - heatmap: hourlyAverages ?? [], + heatmap: averages ?? [], }, revalidate: DEFAULT_REVALIDATE_PERIOD, } diff --git a/src/pages/gas/[network].tsx b/src/pages/gas/[network].tsx index 63987bd8..69898d36 100644 --- a/src/pages/gas/[network].tsx +++ b/src/pages/gas/[network].tsx @@ -44,7 +44,7 @@ export default function Index(props: Props) {
    - +

    ⛽ Current

    @@ -58,18 +58,7 @@ export default function Index(props: Props) {

    🕘 Avg/last hour


    - baseFee: {Math.round(props.gasData.lastHour.baseFee * 100) / 100} -
    - median: {Math.round(props.gasData.lastHour.median * 100) / 100} -
    - - -
    -

    📅 Avg/24 hours

    -
    - baseFee: {Math.round(props.gasData.lastDay.baseFee * 100) / 100} -
    - median: {Math.round(props.gasData.lastDay.median * 100) / 100} + baseFee: {props.gasData.lastHour}
    @@ -105,15 +94,18 @@ export default function Index(props: Props) {
  • Ethereum Gas Tracker
  • - {/*
  • +
  • Arbitrum Gas Tracker -
  • */} +
  • Optimism Gas Tracker
  • Polygon Gas Tracker
  • +
  • + Base Gas Tracker +
  • @@ -171,9 +163,12 @@ export const getStaticPaths: GetStaticPaths = async () => { { params: { network: 'optimism' }, }, - // { - // params: { network: 'arbitrum' }, - // }, + { + params: { network: 'arbitrum' }, + }, + { + params: { network: 'base' }, + }, ], fallback: false, } @@ -184,7 +179,7 @@ export const getStaticProps: GetStaticProps = async (context) => const service = new MarkdownContentService() const categories = await service.GetCategories() - if (!network || !['polygon', 'optimism'].includes(network)) { + if (!network || !['polygon', 'optimism', 'base', 'arbitrum'].includes(network)) { return { props: null, notFound: true, diff --git a/src/services/indexer.ts b/src/services/indexer.ts index ceee0726..91a4d349 100644 --- a/src/services/indexer.ts +++ b/src/services/indexer.ts @@ -1,137 +1,42 @@ -import * as dotenv from 'dotenv' -import { createClient } from '@supabase/supabase-js' -import { getMin, getMax, getAverage, getMedian, toRoundedGwei, getEthPrice } from 'utils/gas' import { GasFee } from 'types/gas' -import { GetRpcProvider } from 'utils/providers' - -dotenv.config() const defaultBlockLimit = 10 -export type NETWORKS = 'mainnet' | 'polygon' | 'optimism' | 'arbitrum' - -if (!process.env.SUPABASE_URL || !process.env.SUPABASE_KEY) { - console.warn('SUPABASE_URL or SUPABASE_KEY env variables are not set.') -} - -if (!process.env.INFURA_KEY) { - console.warn('INFURA_KEY env variable is not set.') -} - -if (!process.env.NEXT_PUBLIC_ALCHEMY_API_KEY) { - console.warn('NEXT_PUBLIC_ALCHEMY_API_KEY env variable is not set.') -} - -export async function Index(network: NETWORKS = 'mainnet') { - console.log(`[${network}] Start indexing..`) - - const db = CreateDbClient() - const provider = GetRpcProvider(network) - - const currentBlock = await provider.getBlockNumber() - const lastProcessedBlock = await db.from(network).select('*').order('blockNr', { ascending: false }).limit(1) - const runUntil = - lastProcessedBlock.data && lastProcessedBlock.data.length > 0 ? lastProcessedBlock.data[0].blockNr : null || currentBlock - defaultBlockLimit - console.log(`[${network}] Process blocks # ${runUntil} / ${currentBlock}`) - - let blockNr = currentBlock - while (blockNr >= runUntil) { - console.log(`[${network}] # ${blockNr}`) - - const block = await provider.getBlockWithTransactions(blockNr) - const fees = block.transactions.map((i) => toRoundedGwei(i.maxFeePerGas)).filter((i) => i > 0) - const ethPrice = await getEthPrice() - - const record = { - blockNr: block.number, - baseFee: toRoundedGwei(block.baseFeePerGas), - gasLimit: block.gasLimit.toNumber(), - gasUsed: block.gasUsed.toNumber(), - txCount: block.transactions.length, - min: getMin(fees), - max: getMax(fees), - avg: getAverage(fees), - median: getMedian(fees), - ethPrice: ethPrice, - } - - // console.log(`[${network}] Add to db`, record) - const response = await db.from(network).upsert([record]) - if (response.error) { - console.log(`[${network}] Unable to save block # ${blockNr}`, record) - throw new Error(response.error.message) - } - - blockNr-- - } - - console.log(`[${network}] Completed.`) - return -} -export async function Cleanup(network: NETWORKS = 'mainnet') { - console.log(`[${network}] Start cleanup..`) - - const db = CreateDbClient() - try { - // delete all records where created_at is older than 14 days - const since = new Date(Date.now() - 14 * 24 * 60 * 60 * 1000).toISOString() - console.log(`[${network}] Delete records older than ${since}`) - const { data, error } = await db.from(network).delete().lte('created_at', since) - - if (error) { - console.error('Error:', error) - throw new Error(error.message) - } - - console.log('Data deleted!') - return data - } catch (error) { - console.error('Error:', error) - } -} +export type NETWORKS = 'mainnet' | 'polygon' | 'optimism' | 'arbitrum' | 'base' export async function GetGasData(network: NETWORKS = 'mainnet') { console.log('Get GasData', network) - const daily = await GetAverage('day', 1, network) - const hourly = await GetAverage('hour', 24, network) - if (!daily || daily.length === 0) { - throw new Error('Unable to fetch daily average') + try { + const res = await fetch(`https://www.ethgastracker.com/api/gas/history/${network}`) + const body = await res.json() + const blocks = body.data.blocks + const average = blocks.map((i: GasFee) => i.baseFee).reduce((a: number, b: number) => a + b, 0) / blocks.length + + return { + lastHour: Math.round(average * 100) / 100, + fees: body.data.blocks, + } } - if (!hourly || hourly.length === 0) { - throw new Error('Unable to fetch hourly average') + catch (error) { + console.error('Error:', error) } return { - lastDay: daily[0], - lastHour: hourly[0], - fees: hourly, + lastHour: 0, + fees: [], } } export async function GetAverage(period: 'hour' | 'day', limit: number = 24, network: NETWORKS = 'mainnet') { console.log(`[${network}] Get average by ${period}`) - const db = CreateDbClient() - try { - const { data, error } = await db.from(`gasdata_${network}_${period}`).select('*').limit(limit) - - if (error) { - console.error('Error:', error) - throw new Error(error.message) - } - - return data as GasFee[] - } catch (error) { - console.error('Error:', error) + const res = await fetch(`https://www.ethgastracker.com/api/gas/average/${network}`) + const body = await res.json() + return body.data.data } -} - -export function CreateDbClient() { - if (!process.env.SUPABASE_URL || !process.env.SUPABASE_KEY) { - throw new Error('SUPABASE_URL or SUPABASE_KEY env variables are not set.') + catch (error) { + console.error('Error:', error) } - - return createClient(process.env.SUPABASE_URL, process.env.SUPABASE_KEY) } diff --git a/src/types/gas.ts b/src/types/gas.ts index 4ef7a391..8ac59e7d 100644 --- a/src/types/gas.ts +++ b/src/types/gas.ts @@ -14,8 +14,7 @@ export interface Heatmap { } export interface GasData { - lastDay: GasFee - lastHour: GasFee + lastHour: number fees: GasFee[] }