"Gas"是指衡量执行操作(例如进行交易或运行智能合约)所需计算量的单位。它类似于汽车的燃料——是网络处理和验证操作的必要条件。以太坊上的每笔交易都需要一定数量的 gas,具体数量由交易的复杂程度决定。用户以 Gwei(1 Gwei = 十亿分之一以太币)为单位设置 gas 价格,代表他们愿意为每单位 gas 支付的以太币数量。
了解 gas 价格对于区块链网络至关重要,它帮助用户管理交易成本。掌握当前 gas 价格,用户可以选择最经济的时机发起交易,并确定交易速度。了解 gas 价格对于防止交易失败、规划预算、理解网络拥堵状况以及做出明智的投资决策同样不可或缺。
MetaMask Gas API
MetaMask Gas API 通过 Infura 提供,是一款专为以太坊虚拟机(EVM)兼容网络提供实时 gas 价格信息而设计的专业工具。它作为预言机运行,提供在这些网络上执行操作或交易所需计算成本的最新数据。该 API 赋能开发者构建高级 gas 估算功能,从而降低后端交易操作的成本,或提升用户界面体验。
在本教程中,我们将学习如何使用 Gas API、Next.js 和 ShadcnUI 构建一个 Gas 追踪应用。该应用将使 dapp 用户能够根据其交易优先级获取推荐的 gas 价格,从而确保这些交易高效地被纳入区块链区块中。
前提条件
有效的 Web3 API 密钥和 API 密钥 secret。
已安装 Node.js 以及 npm 或 yarn。
熟悉 Next.js 和 React。
配置 Next.js + ShadcnUI
首先,确保您的机器上已安装 Node.js。完成 Node.js 的配置后,打开终端并执行以下命令,启动一个新的 Next.js 应用:
npx create-next-app@latest执行命令后,不仅会出现若干提示,还会在您指定的项目名称下生成一个新目录——我使用的是 gastracker-app,从而建立 Next.js 的基础结构并安装必要的依赖项。现在,进入您的项目目录:
npx create-next-app@latest
✔ What is your project named? … gastracker-app
✔ Would you like to use TypeScript? … No / Yes
✔ Would you like to use ESLint? … No / Yes
✔ Would you like to use Tailwind CSS? … No / Yes
✔ Would you like to use `src/` directory? … No / Yes
✔ Would you like to use App Router? (recommended) … No / Yes
✔ Would you like to customize the default import alias (@/*)? … No / Yes
进入新项目目录后,使用以下命令以开发模式启动 Next.js 应用。然后,您可以在浏览器中访问 http://localhost:3000 来浏览您的应用。
cd gastracker-app
npm run dev
构建用户界面
我们的应用将使用一个组件库。首先安装 ShadcnUI:
npx shadcn-ui@latest init安装过程中,系统将引导您通过以下提示配置 components.json 文件:
Would you like to use TypeScript (recommended)? no / yes
Which style would you like to use? › Default
Which color would you like to use as base color? › Slate
Where is your global CSS file? › › app/globals.css
Do you want to use CSS variables for colors? › no / yes
Where is your tailwind.config.js located? › tailwind.config.js
Configure the import alias for components: › @/components
Configure the import alias for utils: › @/lib/utils
Are you using React Server Components? › no / yes
完成上述步骤后,我们还需安装 Shadcn UI 的 Card 组件:
npx shadcn-ui@latest add card在本教程中,我们将重点使用 Shadcn UI 的 Card 组件。如需了解更多关于这些组件的信息,请访问 Shadcn UI 官网。前端配置完成后,我们就可以开始使用 Gas API 了。
在根目录中,创建一个名为 .env 的文件,用于存储以下凭据:
INFURA_API_KEY=
INFURA_API_KEY_SECRET=
请确保从您的 Infura 控制台获取 API_KEY 和 API_KEY_SECRET。务必避免将 API 密钥推送到 GitHub。在根目录中,检查 .gitignore 文件,确认其中包含必要的内容。
# Ignore environment variables
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
我们还需要安装 axios 和 dotenv 包:
npm install axios
npm install dotenv
现在,在 gastracker-app 的根目录中创建一个名为 'index.js' 的文件,并将以下代码复制到其中:
const axios = require("axios");
require("dotenv").config();
const Auth = Buffer.from(
process.env.INFURA_API_KEY + ":" + process.env.INFURA_API_KEY_SECRET,
).toString("base64");
const chainId = 1;
(async () => {
try {
const { data } = await axios.get(
`https://gas.api.infura.io/networks/${chainId}/suggestedGasFees`,
{
headers: {
Authorization: `Basic ${Auth}`,
},
},
);
console.log("Suggested gas fees:", data);
} catch (error) {
console.log("Server responded with:", error);
}
})();
在另一个终端窗口中,运行以下命令。
node index.js您应该会看到以下内容:
Suggested gas fees: {
low: {
suggestedMaxPriorityFeePerGas: '0.05',
suggestedMaxFeePerGas: '28.501086221',
minWaitTimeEstimate: 15000,
maxWaitTimeEstimate: 30000
},
medium: {
suggestedMaxPriorityFeePerGas: '0.1',
suggestedMaxFeePerGas: '38.508966399',
minWaitTimeEstimate: 15000,
maxWaitTimeEstimate: 45000
},
high: {
suggestedMaxPriorityFeePerGas: '0.3',
suggestedMaxFeePerGas: '48.666846576',
minWaitTimeEstimate: 15000,
maxWaitTimeEstimate: 60000
},
estimatedBaseFee: '28.451086221',
networkCongestion: 0.7718,
latestPriorityFeeRange: [ '0.05', '9.249760902' ],
historicalPriorityFeeRange: [ '0.023435712', '56.009283908' ],
historicalBaseFeeRange: [ '19.277073248', '31.361941035' ],
priorityFeeTrend: 'down',
baseFeeTrend: 'up'
}
如果您在终端中看到显示的数据,说明我们已成功接收到 API 的响应。下一步是将这些数据呈现在前端界面上。现在您可以删除 index.js 文件。
在前端展示 gas 数据
为了在整个项目中使用自定义类型,请在根目录中创建一个名为 'index.d.ts' 的文件,并添加以下内容:
interface GasFeeEstimate {
suggestedMaxPriorityFeePerGas: string;
suggestedMaxFeePerGas: string;
minWaitTimeEstimate: number;
maxWaitTimeEstimate: number;
}
interface GasFeesApiResponse {
low: GasFeeEstimate;
medium: GasFeeEstimate;
high: GasFeeEstimate;
estimatedBaseFee: string;
networkCongestion: number;
latestPriorityFeeRange: string[];
historicalPriorityFeeRange: string[];
historicalBaseFeeRange: string[];
priorityFeeTrend: 'up' | 'down';
baseFeeTrend: 'up' | 'down';
}
全局文件中的这些 TypeScript 接口声明定义了 gas 费用估算和 API 响应的数据结构,涵盖区块链网络上不同交易优先级的费用建议、等待时间、网络拥堵情况以及费用趋势等详细信息。
在 'lib' 文件夹中,创建一个名为 'getData.ts' 的文件,并添加以下代码:
const Auth = Buffer.from(
process.env["INFURA_API_KEY"] + ":" + process.env["INFURA_API_KEY_SECRET"]
).toString("base64");
const chainId = 1;
export const getData = async () => {
try {
const res = await fetch(
`https://gas.api.infura.io/networks/${chainId}/suggestedGasFees`,
{
headers: {
Authorization: `Basic ${Auth}`,
},
}
);
const data = await res.json();
return data as GasFeesApiResponse;
} catch (error) {
console.log("Server responded with:", error);
}
};
这些代码从 Gas API 获取 gas 费用数据:
身份验证配置:从 INFURA_API_KEY 和 INFURA_API_KEY_SECRET(均设置为环境变量)创建一个 Buffer,然后将其转换为 base64 字符串(命名为 'Auth'),用于 API 请求的基本身份验证。
Chain ID 指定:将变量 chainId 设置为 1,在区块链中通常代表以太坊主网。
getData 函数:一个用于获取 gas 费用数据的异步函数:
使用 fetch 向 Infura API 端点发起 GET 请求,获取指定 chainId 的建议 gas 费用。
使用之前创建的 Auth 令牌在请求中设置 Authorization 请求头。
如果请求成功,将响应解析为 JSON 并以 GasFeesApiResponse 类型返回,与之前定义的接口保持一致。
将网络问题或服务器错误等任何错误记录到控制台。
Chain ID 可变性:chainId 可根据应用所针对的网络进行调整。Infura 上的 Gas API 支持大多数主流 EVM 网络。有关支持网络的更多信息,请访问文档。
构建 UI
现在我们进入令人兴奋的部分——专注于 UI 以展示数据。让我们进入 components 文件夹,创建一个名为 'GasCard.tsx' 的组件。
import { getData } from "@/lib/getData";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
export const GasCard = async () => {
const data = await getData();
const renderGasFeeEstimateCard = (
estimate: GasFeeEstimate,
title: string
) => (
<Card>
<CardHeader>
<CardTitle>{title}</CardTitle>
</CardHeader>
<CardContent>
<p>Max Priority Fee: {estimate.suggestedMaxPriorityFeePerGas}</p>
<p>Max Fee Per Gas: {estimate.suggestedMaxFeePerGas}</p>
<p>Min Wait Time: {estimate.minWaitTimeEstimate} seconds</p>
<p>Max Wait Time: {estimate.maxWaitTimeEstimate} seconds</p>
</CardContent>
</Card>
);
return (
<div className="space-y-4">
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
{data?.low &&
renderGasFeeEstimateCard(data.low, "Low Gas Fee Estimate")}
{data?.medium &&
renderGasFeeEstimateCard(data.medium, "Medium Gas Fee Estimate")}
{data?.high &&
renderGasFeeEstimateCard(data.high, "High Gas Fee Estimate")}
</div>
<Card>
<CardContent>
<h2 className="font-semibold">Estimated Base Fee</h2>
<p>Gas Price: {data?.estimatedBaseFee}</p>
<h2 className="font-semibold">Network Congestion</h2>
<p>{data?.networkCongestion}</p>
<h2 className="font-semibold">Latest Priority Fee Range</h2>
<p>{data?.latestPriorityFeeRange.join(" - ")}</p>
<h2 className="font-semibold">Historical Priority Fee Range</h2>
<p>{data?.historicalPriorityFeeRange.join(" - ")}</p>
<h2 className="font-semibold">Historical Base Fee Range</h2>
<p>{data?.historicalBaseFeeRange.join(" - ")}</p>
<h2 className="font-semibold">Priority Fee Trend</h2>
<p>{data?.priorityFeeTrend}</p>
<h2 className="font-semibold">Base Fee Trend</h2>
<p>{data?.baseFeeTrend}</p>
</CardContent>
</Card>
</div>
);
};
让我们来看看这里发生了什么:
导入与数据获取:
该组件导入了用于获取 gas 费用数据的 getData 函数,以及各种 UI 组件,如 Card、CardContent、CardHeader 和 CardTitle,这些都是我们之前安装的 Shadcn UI 的一部分。
在 GasCard 组件内部,调用 getData 函数来获取 gas 费用数据。
渲染 Gas 费用估算:
定义了一个名为 renderGasFeeEstimateCard 的函数,用于为特定的 gas 费用估算(GasFeeEstimate)和标题(title)渲染卡片 UI。
该函数构建一个 Card 组件,显示最高优先费、每单位 gas 最高费用以及预计等待时间等详细信息。
组件结构:
GasCard 组件的 JSX 结构在 return 语句中定义。它采用网格布局展示低、中、高三档 gas 费用估算的卡片,这些卡片根据数据可用性进行条件渲染。
另一张卡片显示更多信息,如预计基础费用、网络拥堵情况、优先费范围(最新及历史数据)以及优先费和基础费用的趋势。
现在,唯一剩下的步骤是将 GasCard.tsx 导入 page.tsx 文件。完成后,所有数据应该都能在前端界面上显示。
开始使用 Gas API
使用 Infura 上的 Gas API 为与 EVM 兼容网络交互的开发者提供了显著优势。它提供对波动 gas 市场的实时洞察,帮助用户就交易费用做出明智决策,尤其有助于优化交易速度和成本效益。
本教程介绍了如何开始使用 GasAPI 并创建一个简单的 Gas 追踪应用。您可以在此处找到代码:GitHub 上的 GasAPI-Template。
当然,我们还可以用它做更多有趣的事情:例如添加带倒计时的定时刷新 GasData 功能,也可以将 GasAPI 集成到任何现有应用中。我建议参考以下资源:
Gas API 文档:Infura Gas API 文档
EventSea:一个创意使用 GasAPI 的全栈活动 Dapp:GitHub 上的 EventSea
祝您构建愉快!🚀