如何调用智能合约tokensOfOwner获取用户持有的Token ID
前端代码调整实现方案
原有代码仅用布尔值标记持有状态,无法存储具体Token ID列表,只需要调整状态定义、补充合约返回值的类型转换逻辑即可,具体修改如下:
1. 修改状态定义
将原本存储布尔值的状态改为存储Token ID数组,持有状态直接通过数组长度派生即可,不需要单独维护布尔值,避免多状态不同步:
// 存储当前连接钱包持有的所有Token ID,默认值为空数组 const [heldTokenIds, setHeldTokenIds] = useState([]); // 派生持有状态:数组长度大于0即为持有者 const isTokenHolder = heldTokenIds.length > 0;
2. 调整查询方法逻辑
合约的tokensOfOwner方法本身已经返回指定地址持有的全部Token ID数组,ethers.js调用后返回的是BigNumber类型的数组(适配Solidity uint256类型),需要做格式转换后存入状态,同时补充错误捕获:
const checkOwners = async () => { if (!ethereum) return; try { const provider = new ethers.providers.Web3Provider(ethereum); const signer = provider.getSigner(); const nftContract = new ethers.Contract(contractAddress, abi, signer); if (currentAccount && nftContract) { // 调用合约方法获取原始BigNumber格式的Token ID列表 const rawOwnedTokens = await nftContract.tokensOfOwner(currentAccount); // 格式转换:小于JS最大安全整数的ID转Number,大ID转字符串避免精度丢失 const formattedTokenIds = rawOwnedTokens.map(tokenId => { return tokenId.lt(Number.MAX_SAFE_INTEGER) ? tokenId.toNumber() : tokenId.toString(); }); // 更新状态 setHeldTokenIds(formattedTokenIds); } } catch (error) { console.error("查询钱包持有Token失败:", error); // 调用失败时重置列表为空 setHeldTokenIds([]); } };
注意事项
- 不要直接将ethers返回的BigNumber实例存入状态做渲染使用,必须做类型转换;如果你的NFT Token ID可能超过
9007199254740991(JS最大安全整数),统一转字符串存储是最稳妥的方案,避免出现ID精度错乱。 - 建议在钱包账户切换、链网络切换、组件首次加载的时机都调用一次
checkOwners,保证展示的持有数据和当前钱包状态一致。 - 后续业务中需要判断用户是否持有、取具体Token ID,直接读
heldTokenIds数组即可,比如取第一个持有ID用heldTokenIds[0],遍历所有ID直接map数组即可。
内容的提问来源于stack exchange,提问作者ppm.eth
相关产品推荐
相关产品推荐

