构建以太坊gas跟踪器

构建以太坊gas跟踪器

259787ed0b905b5e83acba982f72b5dd.jpg

介绍

2021年8月的伦敦硬分叉带来了以太坊网络有史以来最大的一次升级。该分叉实现了EIP-1559;一种被吹捧为优于盲目拍卖模式的gas定价机制。它还引入了以太坊(ETH)货币政策的根本性变化,使其至少在短期内成为通货紧缩货币。

在本教程中,我们将构建一个gas跟踪器,用于跟踪EIP-1559中gas费用的两个新组成部分以及最近20个区块的其他统计数据(如区块体积)。通过这样做,我们将实现两个重要目标:

  • 更深入地理解EIP-1559的工作原理,以及它带来了哪些改进。
  • 一个功能齐全的gas跟踪应用程序,检索最新的区块数体积和gas费用,按基数和优先费用进行分类。

为了做到这一点,我们将使用Alchemy、Alchemy web3.js库、Node和React。如果这些单词对你来说听起来很陌生,不要担心,我们将详细介绍它们!

本教程假设读者对以太坊上的gas和gas价格如何工作有一个基本的了解。对EIP-1559的初步了解也有帮助,但不是必需的。

EIP-1559快速回顾

EIP-1559给以太坊的gas定价机制带来了以下变化:

  • 盲目拍卖的gas费现在被两种费用所取代:基本费和优先费(或矿工小费)。
  • 基本费用由网络自动确定。如果前一个区块是满的,它可以增加到12.5%,如果前一个区块是空的,它可以减少到12.5%。
  • 矿工的小费由用户决定,可以根据交易的紧迫性进行调优。
  • 基础费用是由网络烧的,以防止矿工人为的淹没区块。然而,矿工们可以将小费收入囊中。

除了改善gas价格,EIP-1559还提出了改进措施,以更好地装备网络,来应对突发的流量高峰。正如你可能知道的,以太坊中的交易被分组成区块。在分叉之前,无论流量怎样,一个区块只能容纳1500万的gas交易。

随着升级,区块大小上限已翻倍至3000万gas。这样做是为了更好地应对需求增长时期。然而,预计基础费用将调整为区块体积(或区块使用的gas)平均在50%或1500万gas左右。

可以通过我们制作的gas跟踪器实时看到这一切是如何工作的。我们将分两部分构建这个项目:在第一部分中,我们将编写一个节点脚本,实时跟踪交易费用的历史记录。在第二部分,我们将利用这个脚本创建一个React应用程序来构建最终的跟踪器。

第1部分:交易费用历史记录脚本

在本节中,我们将编写一个脚本(在节点中),它将允许我们获得以太坊网络上最近20个区块的gas费的历史记录。

步骤0:安装node和npm

ff2e2e1c19746e22d2a628e6c7662b87.jpg

确保在本地计算机上安装了node和npm(至少是v14或更高版本)。

步骤1:创建一个Alchemy帐户

为了获得区块最新的gas费历史记录,我们需要连接到以太坊网络进行通信。Alchemy是一个区块链开发平台,它允许我们无需启动我们自己的节点就可以实现这一点。

步骤2:创建Alchemy应用程序(和API密钥)

80ce97d9ce3efcd250a365dcc4016680.jpg

在Alchemy仪表板上创建一个应用程序。链设置为以太坊,网络设置为主网。

7e036ac5432920a7856d270361b0b556.jpg

接下来,访问你的应用程序页面,点击View Key。这将打开一个包含应用程序的HTTP和Websocket URL的弹出窗口。在本教程中,我们将使用Websocket URL。

步骤3:创建节点项目并安装依赖项

现在我们可以开始编写节点脚本了。让我们创建一个空的存储库并安装依赖项。对于这个脚本,我们将需要Alchemy web3.js库。

在你的终端(或命令提示符)上,运行以下命令:

mkdir gas-tracker-script && cd gas-tracker-script > npm init -y > npm install --save @alch/alchemy-web3 > touch main.js

这将创建一个名为gas tracker-script的存储库,其中包含我们需要的所有文件和依赖项。在您喜欢的代码编辑器中打开此回购。我们将在main.js文件中编写所有的代码。

步骤4:使用Alchemy创建一个web3客户端实例

使用Alchemy web3创建客户端实例非常简单。

在main.js文件中,添加以下代码行:

const { createAlchemyWeb3 } = require("@alch/alchemy-web3");// Using WebSockets
const web3 = createAlchemyWeb3(
    "wss://eth-mainnet.alchemyapi.io/v2/<--API KEY-->",

);

确保用应用程序的 websocket URL 替换上面的占位符。

步骤5:获取最近20个区块的历史记录

我们想要最近10个区块的 gas 费用历史记录。我们感兴趣的数据包括基本费用、优先费用范围、区块体积和区块编号。

幸运的是,Alchemy有一个非常方便的eth_feeHistory,它可以自动返回前面提到的所有数据。

我们需要指定的是我们想要数据的最新区块,要查看的区块总数,以及优先费用的百分比范围。

我们感兴趣的是最近的20个区块以及优先费用的第 25、50 和 75 个百分位感兴趣。

web3.eth.getFeeHistory(20, "latest", [25, 50, 75]).then(console.log)

运行这个脚本(使用node main.js)应该会获取你正在寻找的数据。这里是一些数据,我在请求5个区块数据后收到的结果。

980a7dea3a9e8e9a43b586e0f933a9b2.jpg

步骤6:格式化输出

我们在第5步中收到的输出是正确的,但可读性不强。费用是用十六进制表示的,数据结构使得很难找出哪个数据对应哪个区块。

让我们编写一个小函数,将原始数据转换为一个字典列表,其中每个字典将包含特定区块上的数据。该函数还将所有以wei表示的十六进制gas值转换为以Gwei表示的十进制数。

const formatOutput = (data, numBlocks) => {    let blocks = []
    for (let i = 0; i < numBlocks; i++) {
        blocks.push({
            blockNumber: Number(data.oldestBlock) + i,
            reward: data.reward[i].map(r => Math.round(Number(r) / 10 ** 9)),
            baseFeePerGas: Math.round(Number(data.baseFeePerGas[i]) / 10 ** 9),
            gasUsedRatio: data.gasUsedRatio[i],
        })
    }
    return blocks;

最后,让我们将此函数用作feeHistory

const numBlocks = 5;web3.eth.getFeeHistory(numBlocks, "latest", [25, 50, 75]).then((data) => {
    const blocks = formatOutput(data, numBlocks);
    console.log(blocks);
});

运行这个版本的脚本应该会产生如下格式的输出:

ac68a2fe1b23de7de6c049c77b3dc9f5.jpg

步骤7:订阅最新的block header

以太坊区块链大约每15秒新增一个区块。因此,理想情况下,我们希望订阅正在添加的区块的事件,并更新我们的交易历史,这样它总是显示最近20个区块的数据。

让我们在订阅事件回调中嵌套getFeeHistory功能。

let subscription = web3.eth.subscribe('newBlockHeaders');subscription.on("data", () => {
    web3.eth.getFeeHistory(numBlocks, "latest", [25, 50, 75]).then((data) => {
        const blocks = formatOutput(data, numBlocks);
        console.log(blocks);
    });
});

现在运行main.js脚本将每15秒左右输出一批最新的数据。如果你已经走了这么远,恭喜你!你现在有了一个功能齐全的gas跟踪器。

第2部分:React应用程序

f227aadbaedd09a5bed334fcc1c16a65.jpg

在上一节中,我们编写了一个脚本,每次向以太坊主网添加一个新区块时,它都会检索最近20个区块的费用历史记录。

在本节中,我们将构建一个小型React应用程序,将这些数据从终端传输到浏览器。除了费用交易历史,我们还将显示过去20个区块的平均gas费用和区块体积。

步骤1:初始化React项目并安装依赖项

执行如下命令:

npx create-react-app gas-tracker-frontend > cd gas-tracker-frontend

这将创建一个示例React项目。除了react依赖项之外,我们还需要安装上一节中的Alchemy web3库。

npm install --save @alch/alchemy-web3

步骤2:填充App.js文件

我们所有的逻辑都将驻留在App.js文件中。复制以下内容到上述文件。

import './App.css';
import { useEffect, useState } from 'react';
import { createAlchemyWeb3 } from '@alch/alchemy-web3';const NUM_BLOCKS = 20;function App() {  const [blockHistory, setBlockHistory] = useState(null);
  const [avgGas, setAvgGas] = useState(null);
  const [avgBlockVolume, setAvgBlockVolume] = useState(null);  const formatOutput = (data) => {    let avgGasFee = 0;
    let avgFill = 0;
    let blocks = [];    for (let i = 0; i < NUM_BLOCKS; i++) {      avgGasFee = avgGasFee + Number(data.reward[i][1]) + Number(data.baseFeePerGas[i])
      avgFill = avgFill + Math.round(data.gasUsedRatio[i] * 100);      blocks.push({
        blockNumber: Number(data.oldestBlock) + i,
        reward: data.reward[i].map(r => Math.round(Number(r) / 10 ** 9)),
        baseFeePerGas: Math.round(Number(data.baseFeePerGas[i]) / 10 ** 9),
        gasUsedRatio: Math.round(data.gasUsedRatio[i] * 100),
      })
    }    avgGasFee = avgGasFee / NUM_BLOCKS;
    avgGasFee = Math.round(avgGasFee / 10 ** 9)    avgFill = avgFill / NUM_BLOCKS;
    return [blocks, avgGasFee, avgFill];
  }  useEffect(() => {    const web3 = createAlchemyWeb3(
      "wss://eth-mainnet.alchemyapi.io/v2/<--API KEY-->",
    );    let subscription = web3.eth.subscribe('newBlockHeaders');    subscription.on('data', () => {
      web3.eth.getFeeHistory(NUM_BLOCKS, "latest", [25, 50, 75]).then((feeHistory) => {
        const [blocks, avgGasFee, avgFill] = formatOutput(feeHistory, NUM_BLOCKS);
        setBlockHistory(blocks);
        setAvgGas(avgGasFee);
        setAvgBlockVolume(avgFill);
      });
    });    return () => {
      web3.eth.clearSubscriptions();
    }
  }, [])
  return (
    <div className='main-container'>
      <h1>EIP-1559 Gas Tracker</h1>
      {!blockHistory && <p>Data is loading...</p>}
      {avgGas && avgBlockVolume && <h3>
        <span className='gas'>{avgGas} Gwei</span> | <span className='vol'>{avgBlockVolume}% Volume</span>
      </h3>}
      {blockHistory && <table>
        <thead>
          <tr>
            <th>Block Number</th>
            <th>Base Fee</th>
            <th>Reward (25%)</th>
            <th>Reward (50%)</th>
            <th>Reward (75%)</th>
            <th>Gas Used</th>
          </tr>
        </thead>
        <tbody>
          {blockHistory.map(block => {
            return (
              <tr key={block.blockNumber}>
                <td>{block.blockNumber}</td>
                <td>{block.baseFeePerGas}</td>
                <td>{block.reward[0]}</td>
                <td>{block.reward[1]}</td>
                <td>{block.reward[2]}</td>
                <td>{block.gasUsedRatio}%</td>
              </tr>
            )
          })}
        </tbody>
      </table>}
    </div>
  );
}export default App;

因为这不是一门React课程,所以我们不打算深入研究React特有的部分。但是你应该能够观察到,我们所做的只是像我们在脚本中所做的那样检索费用历史记录并以 HTML 表格的形式输出它。

我们使用的唯一附加逻辑是计算20个区块的平均gas价格和平均区块体积,这是一项微不足道的任务。

(可选)步骤3:添加一些样式

你可以在App.css文件中添加一些基本的样式,如下所示:

.main-container {
    text-align: center;
}table {
    border-collapse: collapse;
    margin: 20px auto;
    box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2);
}thead {
    background: linear-gradient(267.45deg,#05d5ff -34.23%,#53f 99.39%);
    color: white;
    padding: 10px;
}th {
    font-size: 18px;
    padding: 15px;}tbody > tr {
    border-top: 1px solid #ccc; 
    border-bottom: 1px solid #ccc;
    margin: 0px;
    padding: 15px;
}td {
    padding: 6px;
}.gas {
    color: #4299E1;
}.vol {
    color: #4C51BF;

步骤4:将应用程序部署到localhost

我们都完成了。通过运行查看你的应用程序:

npm start

这是应用程序应该看起来的样子:

5c62eeca3ce55d986edf1265db78f0a6.jpg

恭喜你!你做了一个功能齐全的gas追踪应用。

分析

让我们回过头来分析一下上面的数据。以下是我们可以观察到的EIP-1559实现的直接结果。

  • 基本费用不会在每个区块之间波动很大。事实上,它最大的增减幅度是12.5%。
  • 在大多数情况下,优先费只占总费用的一小部分。
  • 区块体积倾向于波动,但平均区块体积徘徊在50%左右。

数据似乎表明,在这个模型中,gas费用的可预测性要高得多。由于每个人都要支付相同的基本费用和优先费用,在大多数情况下,优先费用只占总费用的一小部分,所以大多数交易最终不会为gas支付过高的费用。因此,这个样本数据表明,EIP-1559已经成功实现了它的目标;更可预测的gas价格,更少的gas超额支付。

结论

在本文中,我们已经讨论了很多内容。通过从头构建EIP-1559的gas跟踪器,我希望大家能够理解并欣赏它给以太坊交易带来的改进。

我还希望大家已经很好地掌握了如何使用Alchemy、它的API和web3.js库。关于它的功能和提供的产品,我们仅仅触及了表面。我强烈建议,当你开始构建下一个伟大的dapp时,你应该深入挖掘他们的文档。

Source:https://medium.com/scrappy-squirrels/building-an-ethereum-gas-tracker-e7cd6fd5b691

关于

ChinaDeFi - ChinaDeFi.com 是一个研究驱动的DeFi创新组织,同时我们也是区块链开发团队。每天从全球超过500个优质信息源的近900篇内容中,寻找思考更具深度、梳理更为系统的内容,以最快的速度同步到中国市场提供决策辅助材料。

Layer 2道友 - 欢迎对Layer 2感兴趣的区块链技术爱好者、研究分析人与Gavin(微信: chinadefi)联系,共同探讨Layer 2带来的落地机遇。敬请关注我们的微信公众号 “去中心化金融社区”

本文首发于:https://mp.weixin.qq.com/s/aCyVGyxXwcscIy4PxMgfvw

点赞 2
收藏 2
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
ChinaDeFi 去中心化金融社区
ChinaDeFi 去中心化金融社区
ChinaDeFi.com 是一个研究驱动的DeFi创新组织,同时我们也是区块链开发团队。每天从全球超过500个优质信息源的近900篇内容中,寻找思考更具深度、梳理更为系统的内容,以最快的速度同步到中国市场提供决策辅助材料。