Skip to content

Instantly share code, notes, and snippets.

@johngrantuk
Last active November 17, 2020 15:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save johngrantuk/0c9b0ab73e0da5d3d673ea58129212bd to your computer and use it in GitHub Desktop.
Save johngrantuk/0c9b0ab73e0da5d3d673ea58129212bd to your computer and use it in GitHub Desktop.
// 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&timestamp=${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