-
Notifications
You must be signed in to change notification settings - Fork 166
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
55 additions
and
156 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters