You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何调用智能合约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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 12:45:33