|
// This script retrieves the fees of a moonbeam block |
|
|
|
// Requirements (NodeJS 14+, ts-node) |
|
// npm install @polkadot/api moonbeam-types-bundle |
|
|
|
// Ex: |
|
// └────╼ node_modules/.bin/ts-node src/block-fees-simple.ts |
|
// #811083 : 0xbcdf1344362e8f963d8de2aa26eaed213428c2e9739e25b254a7e4f3d5fb1c92 |
|
// fees : 9933615642168512 |
|
// burnt : 7946892513734808 |
|
// supply diff : 7946892513734808 |
|
|
|
import { ApiPromise, WsProvider } from "@polkadot/api"; |
|
import { DispatchInfo } from "@polkadot/types/interfaces"; |
|
import { typesBundle } from "moonbeam-types-bundle"; |
|
|
|
const URL = "wss://moonriver.api.onfinality.io/public-ws"; |
|
const BLOCK = 811083; |
|
|
|
const main = async () => { |
|
const api = await ApiPromise.create({ |
|
provider: new WsProvider(URL), |
|
typesBundle: typesBundle as any, |
|
}); |
|
|
|
const blockHash = (await api.rpc.chain.getBlockHash(BLOCK)).toString(); |
|
|
|
const [{ block }, records] = await Promise.all([ |
|
api.rpc.chain.getBlock(blockHash), |
|
api.query.system.events.at(blockHash), |
|
]); |
|
|
|
let totalFees = 0n; |
|
let totalBurnt = 0n; |
|
|
|
for (let index = 0; index < block.extrinsics.length; index++) { |
|
const extrinsic = block.extrinsics[index]; |
|
|
|
let fee = 0n; |
|
if (extrinsic.method.section == "ethereum") { |
|
// For Ethereum transaction, we take the gas used * gas price |
|
// 1 gas is 25000 weight in current implementation; |
|
|
|
// Retrieve the event for the extrinsic info |
|
const { event } = records.find( |
|
({ phase, event }) => |
|
phase.isApplyExtrinsic && |
|
phase.asApplyExtrinsic.eq(index) && |
|
event.section === "system" && |
|
(event.method === "ExtrinsicSuccess" || event.method === "ExtrinsicFailed") |
|
); |
|
|
|
// Retrieve the dispatch info (where the used weight is stored) from the type of event |
|
const dispatchInfo = |
|
event.method === "ExtrinsicSuccess" |
|
? (event.data[0] as DispatchInfo) |
|
: (event.data[1] as DispatchInfo); |
|
|
|
const gasPrice = (extrinsic.method.args[0] as any).gasPrice.toBigInt(); |
|
fee = dispatchInfo.weight.toBigInt() * gasPrice / 25000n; |
|
} else if (!extrinsic.signer.isEmpty) { |
|
// For Substrate transaction, we only take signed transaction |
|
// we rely on the node payment calculation |
|
const paymentDetails = await api.rpc.payment.queryInfo( |
|
extrinsic.toHex(), |
|
block.header.parentHash |
|
); |
|
fee = paymentDetails.partialFee.toBigInt(); |
|
} |
|
|
|
totalFees += fee; |
|
totalBurnt += (fee * 80n) / 100n; // 20% is given to treasury, 80% is burnt |
|
} |
|
|
|
console.log( |
|
`${`#${block.header.number.toString()}`.padStart(12, " ")} : ${blockHash.toString()}` |
|
); |
|
console.log(` fees : ${totalFees.toString().padStart(30, " ")}`); |
|
console.log(` burnt : ${totalBurnt.toString().padStart(30, " ")}`); |
|
|
|
const preSupply = await (await api.at(block.header.parentHash)).query.balances.totalIssuance(); |
|
const postSupply = await (await api.at(block.header.hash)).query.balances.totalIssuance(); |
|
|
|
// This value is often equal to the burnt value, |
|
// EXCEPT when there is staking payout (every round) |
|
console.log( |
|
` supply diff : ${(preSupply.toBigInt() - postSupply.toBigInt()).toString().padStart(30, " ")}` |
|
); |
|
|
|
await api.disconnect(); |
|
}; |
|
|
|
main(); |