// Example using Etherscan API to analyse contract gas usage over time period. | |
// And .env file with ETHERSCAN API key. Free key from: https://etherscan.io/myapikey. | |
require('dotenv').config(); | |
const moment = require('moment'); | |
const axios = require('axios').default; | |
const Decimal = require('decimal.js'); | |
export const BONE = new Decimal(10).pow(18); | |
// Returns all transactions for block range | |
export async function fetchTransactions(startBlock, endBlock) { | |
// Address of contract of interest | |
const proxyAddr = `0x3E66B66Fd1d0b02fDa6C811Da9E0547970DB2f21`; | |
console.log(`Fetching Txs For ${proxyAddr} for blocks: ${startBlock}-${endBlock}`); | |
// https://etherscan.io/apis#accounts | |
const URL = `https://api.etherscan.io/api?module=account&action=txlist&address=${proxyAddr}&startblock=${startBlock}&endblock=${endBlock}&sort=asc&apikey=${process.env.ETHERSCAN}` | |
const response = await axios.get(URL); | |
// console.log(response.data.status); | |
// console.log(response.data.message); | |
const data = await response.data.result; | |
return data; | |
} | |
// Uses API to retrieve block number for timestamp | |
export async function getBlockForTime(timestamp){ | |
// const timestamp = `1596240000`; // 01/08/2020 | |
// console.log(`timestamp: ${timestamp}`); | |
// https://etherscan.io/apis#blocks | |
const URL = `https://api.etherscan.io/api?module=block&action=getblocknobytime×tamp=${timestamp}&closest=before&apikey=${process.env.ETHERSCAN}`; | |
const response = await axios.get(URL); | |
const data = await response.data.result; | |
return data; | |
} | |
// Main script | |
async function run() { | |
console.log('Starting'); | |
// Going to retrieve txs for last 30 days | |
const dateNow: any = moment(); | |
const dateStart: any = dateNow.clone().subtract(30, 'days'); | |
// Use api to get block numbers for timestamps | |
let startBlock = Number(await getBlockForTime(dateStart.unix())); | |
let endBlock = Number(await getBlockForTime(dateNow.unix())); | |
console.log(`Start: ${dateStart.format()} ${startBlock}`); | |
console.log(`End: ${dateNow.format()} ${endBlock}`); | |
let txs: any[] = []; | |
// Retrieve all txs in range (for max amt) using API | |
while(startBlock < endBlock){ | |
let endRange = startBlock + 15000; | |
let txsRange = await fetchTransactions(startBlock, endRange); | |
console.log(`No of txs: ${txsRange.length}`); | |
txs = txs.concat(txsRange); | |
startBlock = endRange + 1; | |
} | |
console.log(`Total: ${txs.length} transactions in period`); | |
let totalGas = Decimal(0); | |
let totalGasPrice = Decimal(0); | |
let totalCostEth = Decimal(0); | |
let gasPriceDist = {}; | |
// For each tx - | |
// Out gasUsed, gasPrice and ethCost (=gasPrice * gasUsed) | |
// sum gasUsed for avg | |
// sum gasPrice for avg | |
// sum ethCost for avg | |
// Create hash table of gasPrice distribution | |
txs.forEach(tx => { | |
let gasUsed = Decimal(tx.gasUsed); | |
totalGas = totalGas.plus(gasUsed); | |
let gasPrice = Decimal(tx.gasPrice); | |
totalGasPrice = totalGasPrice.plus(gasPrice); | |
let ethCost = gasPrice.mul(gasUsed); | |
totalCostEth = totalCostEth.plus(ethCost); | |
console.log(`GasUsed: ${gasUsed}, GasPrice: ${gasPrice}, Eth Cost: ${ethCost}`); | |
if(! gasPriceDist[tx.gasPrice]) | |
gasPriceDist[tx.gasPrice] = 1; | |
else | |
gasPriceDist[tx.gasPrice] += 1; | |
}); | |
// Output results | |
console.log(gasPriceDist); | |
let avgGasPrice = totalGasPrice.div(txs.length); | |
console.log(`Total Gas Used: ${totalGas.toString()}`); | |
console.log(`Total Eth: ${totalCostEth.div(BONE).toString()}`); | |
console.log(`Average Gas Price: ${avgGasPrice.toString()}`); | |
// console.log(txs[txs.length-1]); | |
} | |
run(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment