Skip to content

Instantly share code, notes, and snippets.

@obycode
Last active January 19, 2024 21:49
Show Gist options
  • Save obycode/d8c0adc7af1cb4e961013109668c6f6c to your computer and use it in GitHub Desktop.
Save obycode/d8c0adc7af1cb4e961013109668c6f6c to your computer and use it in GitHub Desktop.
Block Fee Analysis
const axios = require("axios");
async function fetchTransactionsAndFeeRates(baseUrl, blockHeight) {
let offset = 0;
const limit = 50; // Batch size
let totalCount = 0;
let isFirstRequest = true;
let feeRates = [];
while (isFirstRequest || offset < totalCount) {
const url = `${baseUrl}/extended/v1/tx/block_height/${blockHeight}?limit=${limit}&offset=${offset}`;
try {
const response = await axios.get(url, {
headers: { Accept: "application/json" },
maxBodyLength: Infinity,
});
if (isFirstRequest) {
totalCount = response.data.total; // Assuming 'total' is the field name
isFirstRequest = false;
}
// Extract fee_rate from each transaction and add it to the feeRates array
response.data.results.forEach((tx) => {
if (tx.fee_rate !== undefined) {
feeRates.push([tx.tx_type, tx.fee_rate]);
}
});
offset += limit;
} catch (error) {
if (error.response && error.response.status === 429) {
console.log("Rate limit hit, retrying after a delay...");
await new Promise((resolve) => setTimeout(resolve, 10000)); // 10 second delay
} else {
console.error(error);
break;
}
}
}
return feeRates;
}
labels = [
"fee < 0.0001",
"0.0001 <= fee < 0.001",
"0.001 <= fee < 0.01",
"0.01 <= fee < 0.1",
"0.1 <= fee < 1",
"1 <= fee < 10",
"10 <= fee",
];
// Function to calculate and display the frequency distribution
function calculateFeeDistribution(feeRates, blockHeight) {
const distribution = [0, 0, 0, 0, 0, 0, 0];
const distributionByType = {
contract_call: [0, 0, 0, 0, 0, 0, 0],
token_transfer: [0, 0, 0, 0, 0, 0, 0],
smart_contract: [0, 0, 0, 0, 0, 0, 0],
};
const txCountByType = {
coinbase: 0,
contract_call: 0,
token_transfer: 0,
smart_contract: 0,
};
let minFee = Number.MAX_SAFE_INTEGER;
// Counting the frequency of each fee rate
feeRates.forEach((item) => {
const type = item[0];
const fee = item[1];
txCountByType[type] += 1;
if (type == "coinbase") {
return;
} else {
minFee = Math.min(minFee, fee);
}
if (fee < 100) {
distribution[0] += 1;
distributionByType[type][0] += 1;
} else if (fee < 1000) {
distribution[1] += 1;
distributionByType[type][1] += 1;
} else if (fee < 10000) {
distribution[2] += 1;
distributionByType[type][2] += 1;
} else if (fee < 100000) {
distribution[3] += 1;
distributionByType[type][3] += 1;
} else if (fee < 1000000) {
distribution[4] += 1;
distributionByType[type][4] += 1;
} else if (fee < 10000000) {
distribution[5] += 1;
distributionByType[type][5] += 1;
} else if (fee < 10000000) {
distribution[6] += 1;
distributionByType[type][6] += 1;
}
});
console.log(`Block ${blockHeight} (${feeRates.length} txs)`);
console.log(`Min Fee: ${minFee / 1000000} STX`);
console.log(`\nOverall Fee Distribution:`);
distribution.forEach((frequency, rate) => {
console.log(
`${labels[rate]}: ${((frequency / feeRates.length) * 100).toFixed(2)}%`
);
});
console.log(`\nContract Calls`);
distributionByType["contract_call"].forEach((frequency, rate) => {
console.log(
`${labels[rate]}: ${(
(frequency / txCountByType["contract_call"]) *
100
).toFixed(2)}%`
);
});
console.log(`\nToken Transfers`);
distributionByType["token_transfer"].forEach((frequency, rate) => {
console.log(
`${labels[rate]}: ${(
(frequency / txCountByType["token_transfer"]) *
100
).toFixed(2)}%`
);
});
console.log("\nTransaction Breakdown");
const totalCount =
txCountByType["coinbase"] +
txCountByType["contract_call"] +
txCountByType["token_transfer"] +
txCountByType["smart_contract"];
console.log(
`Contract Calls: ${(
(txCountByType["contract_call"] / totalCount) *
100
).toFixed(2)}%`
);
console.log(
`Token Transfers: ${(
(txCountByType["token_transfer"] / totalCount) *
100
).toFixed(2)}%`
);
console.log(
`Smart Contracts: ${(
(txCountByType["smart_contract"] / totalCount) *
100
).toFixed(2)}%`
);
return distribution;
}
async function analyzeFeeRates(baseUrl, blockHeight) {
const feeRates = await fetchTransactionsAndFeeRates(baseUrl, blockHeight);
const distribution = calculateFeeDistribution(feeRates, blockHeight);
}
// Check if block height is provided as a command line argument
if (process.argv.length < 3) {
console.log(
"Please provide a block height. Usage: node script.js [block_height]"
);
process.exit(1);
}
const blockHeight = parseInt(process.argv[2]);
if (isNaN(blockHeight) || blockHeight < 0) {
console.log(
"Invalid block height provided. Please provide a positive integer."
);
process.exit(1);
}
// Usage
const BASE_URL = "https://api.mainnet.hiro.so";
analyzeFeeRates(BASE_URL, blockHeight);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment