本文介绍了如何使用QuickNode SDK构建一个展示ERC20代币余额的React应用程序。通过使用QuickNode SDK,开发者可以简化与区块链的交互,无需直接处理智能合约,可方便地获取代币余额和其他信息。文章详细描述了设置环境、创建必要组件以及实现应用的步骤,并包含代码示例,适合有一定前端开发经验的读者。
创建一个应用程序来显示 ERC20 代币余额可以简单或复杂,具体取决于你的方法。传统的方法是使用像 ethers.js 这样的库直接与以太坊区块链进行交互并管理智能合约 ABI,这既费时又技术要求高。幸运的是,QuickNode SDK 简化了这个过程。它是一个强大的工具包,使得与 QuickNode 基础设施的工作变得简单,只需要一个函数就能检索代币余额。
本指南将说明如何使用 QuickNode SDK 构建一个 ERC20 代币余额应用程序。
传统上,要获取 ERC20 代币的余额,你需要使用像 ethers.js 的库直接与区块链进行交互,需要对智能合约 ABI 有了解并手动处理多个合约交互。你可以在我们的 综合指南 中了解更多关于这种方法的信息。
QuickNode SDK 通过提供一个简单的接口来与代币余额和其他区块链数据进行交互,从而简化了这个过程,而无需直接与合约交互。
QuickNode SDK 是一个工具,简化了与 EVM 区块链(如以太坊、Polygon 和 Arbitrum)的交互。它提供易于使用的函数来获取代币元数据、余额和转账历史,而不需要手动与区块链或智能合约进行交互。
到目前为止,SDK 主要围绕其核心模块展开。
核心 组件负责通过你的端点启用 RPC 功能,支持通过标准和扩展的 RPC 操作进行交互。在本文撰写时,核心模块支持 20 个 EVM 兼容链。支持的链和更多信息可以在 核心概述页面 中找到。
QuickNode SDK 的一些函数具有分页和筛选支持,这在构建去中心化应用程序时可能会很有用。在本指南中,我们将使用分页规范。
要有效利用 QuickNode SDK 中的 Token 和 NFT API v2 功能,我们需要设置一个具有特定捆绑附加功能的 QuickNode 端点。此设置可无缝访问 QuickNode 提供的各种功能,允许与区块链数据进行广泛的交互。如果你还没有,首先在 此处 创建一个免费的 QuickNode 账户。
一旦拥有账户,你便可以在 QuickNode 端点上免费启用 Token 和 NFT API v2 并进行配置信息如下:
启用附加功能后,你的 QuickNode 端点即可使用 Token 和 NFT API v2 的增强功能与区块链进行交互。复制并保存你的端点,因为你将在下一部分中需要它。
在开始编码之前,让我们进一步了解应用的主要组件和功能,并查看完成后应用的外观。
QuickNode SDK: 用于与区块链数据交互,从指定钱包地址提取 ERC20 代币余额。
SearchBar: 允许用户输入他们想查询的钱包地址的组件。
TokenList: 显示与该钱包相关的 ERC20 代币及其余额的展示组件。
Pagination: 实现以分页方式浏览代币列表,每页显示有限数量的代币(默认为每页最多 5 个代币)。
当用户输入钱包地址并发起搜索时,应用使用 QuickNode SDK 获取代币余额,更新代币列表并提供分页控制以浏览代币数据页面。
现在,我们准备开始构建了!让我们从设置一个新的 React 项目开始,并安装必要的依赖。
在你的终端中运行以下代码。这将设置一个新的 React 应用程序,导航到项目的文件夹,并安装 QuickNode SDK。
npx create-react-app token-balance-app
cd token-balance-app
npm install @quicknode/sdk
构建此应用所需的两个组件是:SearchBar 和 TokenList。运行以下命令以创建这些组件文件。
echo > src/SearchBar.js
echo > src/TokenList.js
SearchBar 组件包含一个输入字段,用于输入钱包地址,以及一个搜索按钮。SearchBar 使用 viem 的 isAddress
方法验证输入的地址,只有当地址有效时,搜索按钮才会启用。当用户在输入框中输入时,onInputChange
函数会更新状态为当前值。当搜索按钮被点击时,将触发 onSearch
函数。
打开 src/SearchBar.js 文件并添加以下代码。随时查阅注释以获取详细信息。
import React, { useState, useEffect } from 'react'
import { viem } from '@quicknode/sdk'
function SearchBar({ onSearch, inputValue, onInputChange }) {
const [notAddress, setNotAddress] = useState(false) // 状态监控输入值是否为有效地址
// useEffect 钩子在每次 inputValue 改变时验证地址
useEffect(() => {
// 如果 inputValue 是有效地址,将 notAddress 状态设为 false,否则设为 true
viem.isAddress(inputValue) ? setNotAddress(false) : setNotAddress(true)
}, [inputValue]) // 依赖数组包含 inputValue,因此当 inputValue 改变时该效果运行
return (
<div>
<input
className="search-bar"
type="text"
placeholder="请输入钱包地址" // 输入框的占位符文本
value={inputValue} // 受控输入框,其值设为 inputValue 状态
onChange={e => onInputChange(e.target.value)} // 在每次按键时更新 inputValue 状态
/>
<button onClick={onSearch} disabled={notAddress}>
{' '}
{/* // 发起搜索的按钮,如果 notAddress 为 true,则禁用 */}
{inputValue && notAddress ? '无效地址' : '搜索'}
</button>
</div>
)
}
export default SearchBar
TokenList 组件接收钱包地址和代币数组作为 props,并显示与该钱包相关的 ERC20 代币的详细信息列表。它还为每个代币的地址提供复制到剪贴板的功能,并在成功复制地址时出现简要通知。
打开 src/TokenList.js 文件并将其修改如下。随时查阅注释以获取详细信息。
import React, { useState } from 'react'
import { viem } from '@quicknode/sdk'
function TokenList({ walletAddress, tokens }) {
const [notification, setNotification] = useState('') // 状态处理通知消息
const handleCopyAddress = address => {
navigator.clipboard.writeText(address).then(() => {
// 异步将地址复制到剪贴板
// 一旦地址复制后显示通知消息
setNotification({ message: '地址已复制到剪贴板!' })
// 1秒后(1000毫秒)隐藏通知
setTimeout(() => {
setNotification('')
}, 1000)
})
}
return (
<div className="token-list">
{notification && (
// 如果有通知消息,则显示
<div className="notification">{notification.message}</div>
)}
<h2>钱包 {walletAddress} 的 ERC20 代币</h2>
{/* 遍历 tokens 数组并渲染每个代币的详细信息 */}
{tokens.length > 0 ? (
tokens.map(token => (
<div key={token.address} className="token-item">
<h2>
{token.name} ({token.symbol})
</h2>
{/* 使用 viem.formatUnits 格式化并显示代币余额 */}
<p>
余额:{' '}
{parseFloat(
viem.formatUnits(token.totalBalance, token.decimals)
).toFixed(2)}
</p>
<p>合约地址: {token.address}</p>
{/* 复制代币合约地址的按钮 */}
<button onClick={() => handleCopyAddress(token.address)}>
复制
</button>
</div>
))
) : (
<p>未找到 ERC-20 代币。</p>
)}
</div>
)
}
export default TokenList
组件准备就绪,现在是时候将它们整合在一起,构建主文件。
src/App.js 是一个 React 应用程序的主结构,它显示给定钱包地址的 ERC20 代币余额。它包括搜索和从 Token 和 NFT API v2 捆绑包 中检索代币余额的功能,进行结果导航的分页以及指示数据正在获取的加载状态。
转到代码编辑器中的 src/App.js 并粘贴以下代码。随时查阅注释以获取详细解释。
不要忘记将 YOUR_QUICKNODE_ENDPOINT_URL 替换为你在 设置 QuickNode SDK 部分获得的端点 URL。
import './App.css' // 导入样式的 CSS
import React, { useState } from 'react' // 导入 React 和 useState 钩子
import SearchBar from './SearchBar' // 导入 SearchBar 组件
import TokenList from './TokenList' // 导入 TokenList 组件
import QuickNode from '@quicknode/sdk' // 导入 QuickNode SDK
// 主应用组件
function App() {
// 应用的状态变量
const [walletAddress, setWalletAddress] = useState(""); // 状态存储钱包地址
const [tokens, setTokens] = useState([]); // 状态存储代币列表
const [currentPage, setCurrentPage] = useState(1); // 状态存储当前页码
const [pageInfo, setPageInfo] = useState(null); // 状态存储分页信息
const [loading, setLoading] = useState(false); // 状态处理加载状态
const [blockchain, setBlockchain] = useState("ethereum"); // 状态存储选择的区块链,默认为以太坊
// 每页显示的结果数量
const resultsPerPage = 5;
// 使用 QuickNode Endpoint 初始化 QuickNode Core
const core = new QuickNode.Core({
endpointUrl:
"YOUR_QUICKNODE_ENDPOINT_URL",
config: {
addOns: { nftTokenV2: true },
},
});
// 根据地址搜索代币余额的函数
const searchAddress = async (
pagination = "firstPage" // 默认分页设置
) => {
setLoading(true); // 开始加载
try {
let data;
// 根据参数处理分页
switch (pagination) {
case "firstPage":
// 获取第一页的代币余额
data = await core.client.qn_getWalletTokenBalance({
wallet: walletAddress,
perPage: resultsPerPage,
});
break;
case "nextPage":
// 获取下一页的代币余额
data = await core.client.qn_getWalletTokenBalance({
wallet: walletAddress,
perPage: resultsPerPage,
page: pageInfo.pageNumber + 1,
});
break;
case "previousPage":
// 获取上一页的代币余额
data = await core.client.qn_getWalletTokenBalance({
wallet: walletAddress,
perPage: resultsPerPage,
page: pageInfo.pageNumber - 1,
});
break;
default:
// 默认情况下处理其他情况
data = await core.client.qn_getWalletTokenBalance({
wallet: walletAddress,
perPage: resultsPerPage,
page: pageInfo.pageNumber,
});
}
setTokens(data.result); // 使用获取的数据更新 tokens 状态
setPageInfo({ pageNumber: data.pageNumber, totalPages: data.totalPages }); // 使用获取的数据更新 pageInfo 状态
} catch (error) {
console.error("获取代币余额时出错:", error); // 记录任何错误
}
setLoading(false); // 结束加载
};
// 导航到下一页的函数
const goToNextPage = () => {
if (pageInfo && pageInfo.pageNumber < pageInfo.totalPages) {
setCurrentPage(currentPage + 1); // 当前页码加 1
searchAddress("nextPage"); // 获取下一页的结果
}
};
// 导航到上一页的函数
const goToPreviousPage = () => {
if (pageInfo && pageInfo.pageNumber !== 1) {
setCurrentPage(currentPage - 1); // 当前页码减 1
searchAddress("previousPage"); // 获取上一页的结果
}
};
return (
<div className="App">
<header className="App-header">
<h1>ERC20 代币余额</h1>
</header>
{/* 下拉框选择区块链 */}
<select
value={blockchain}
onChange={(e) => setBlockchain(e.target.value)}
className="select-box"
>
<option value="ethereum">以太坊</option>
</select>
{/* 搜索框以输入和搜索钱包地址 */}
<SearchBar
onSearch={() => searchAddress("firstPage")}
inputValue={walletAddress}
onInputChange={setWalletAddress}
/>
{/* 条件渲染显示加载状态或代币列表 */}
{loading ? (
<p>加载中...</p> // 显示加载文本
) : (
<TokenList
walletAddress={walletAddress}
tokens={tokens}
page={currentPage}
pageSize={resultsPerPage}
/>
)}
{/* 分页控件以在页面之间导航 */}
<div className="pagination">
<button
onClick={goToPreviousPage}
disabled={!pageInfo || currentPage === 1} // 如果没有上一页,则禁用按钮
>
上一页
</button>
<span>{currentPage}</span>
<button
onClick={goToNextPage}
disabled={!pageInfo || currentPage === pageInfo.totalPages} // 如果没有下一页,则禁用按钮
>
下一页
</button>
</div>
</div>
);
}
export default App;
应用程序现在已经准备好了,只有样式还需要调整。由于使用 CSS 进行样式设计并不是本指南的重点,因此我们不会深入探讨每个样式设置。然而,请随意尝试代码并查看本地运行应用后效果。
打开 src/App.css 并用以下代码替换文件中的现有代码。
/* 通用样式 */
body {
font-family: 'Arial', sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 20px;
}
.App {
max-width: 600px;
margin: auto;
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.select-box {
margin-bottom: 1rem;
padding: 0.5rem 1rem;
border: 1px solid #ccc;
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
font-size: 1rem;
cursor: pointer;
}
/* 搜索框样式 */
.search-bar {
padding: 10px;
margin-bottom: 20px;
width: 100%;
box-sizing: border-box;
border-radius: 4px;
border: 1px solid #ccc;
}
/* 代币列表样式 */
.token-list {
list-style: none;
padding: 0;
}
.token-item {
padding: 15px;
background-color: #f9f9f9;
border: 1px solid #e1e1e1;
margin-bottom: 10px;
border-radius: 4px;
}
.token-item h2 {
margin-top: 0;
color: #333;
}
.token-item p {
margin: 5px 0;
}
.token-item button {
padding: 5px 10px;
background-color: #4caf50;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s;
}
.token-item button:hover {
background-color: #45a049;
}
/* 搜索按钮样式 */
.search-bar + button {
padding: 10px 15px;
background-color: #008cba;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s;
}
.search-bar + button:hover {
background-color: #007b9a;
}
.notification {
padding: 10px;
margin-bottom: 10px;
background-color: #4caf50;
color: white;
text-align: center;
border-radius: 4px;
position: fixed;
top: 20px;
left: 50%;
transform: translateX(-50%);
z-index: 1000;
}
/* 分页样式 */
.pagination {
display: flex;
justify-content: center;
margin-top: 20px;
}
.pagination button {
padding: 10px 15px;
margin: 0 5px;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s;
}
.pagination button:disabled {
background-color: #ccc;
}
.pagination button:not(:disabled):hover {
background-color: #0056b3;
}
.pagination span {
line-height: 30px;
margin: 0 10px;
}
编码部分现在已经完成!让我们通过运行以下命令来启动应用程序。
npm start
如果一切顺利,输出控制台应类似于下方文字。
编译成功!
你可以在浏览器中查看 token-balance-app。
本地: http://localhost:3000
在你的网络上: http://192.168.1.11:3000
注意,开发构建并未优化。
要创建生产构建,请使用 npm run build。
webpack 编译成功
然后,在浏览器中访问 http://localhost:3000。它的外观应该与下图的左侧相似。粘贴一个 EVM 地址并搜索后,前端应像右侧的图像。
检查所有功能,例如尝试不同的地址,以及通过点击分页按钮查看更多结果。
祝贺你完成了本指南!你已经学习了如何使用 QuickNode SDK 构建一个 React 应用程序,可以显示 ERC20 代币余额。如所示,QuickNode SDK 通过处理复杂的区块链交互简化了你的工作,让你可以将精力集中在创建应用的核心功能上。
要探索 QuickNode SDK 的更多功能,或有任何问题,请查看 QuickNode SDK 文档,在 Discord 加入 QuickNode 社区,或通过 Twitter 联系我们。
让我们知道 如果你有任何反馈或对新主题的请求。我们很想听听你的想法。
- 原文链接: quicknode.com/guides/qui...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!