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

获取当前账户NFT Token ID异常:误返回全部Token ID问题排查

解决获取当前账户NFT Token ID返回所有ID的问题

问题1:account变量未就绪时调用查询

你的代码直接在顶层执行test2(),此时Moralis的account可能还未完成初始化,传入getNFTs的是undefined。Web3.js遇到filter: { to: undefined }会忽略该过滤条件,导致返回所有Transfer事件。

修复方式:
通过useEffect监听account的变化,仅当账户地址存在时才执行查询:

// 删除顶层的 test2(); 调用
useEffect(() => {
  if (!account) return;
  const fetchUserNFTs = async () => {
    const userNFTs = await getNFTs(account);
    console.log(userNFTs);
  };
  fetchUserNFTs();
}, [account]);

问题2:未排除已转出的NFT

仅过滤Transfer事件的to字段,会把曾经转入但后来转出的NFT也包含进去,结果包含非当前持有Token ID。需要同时处理转出事件,计算实际持有量。

修复方式:修改getNFTs函数,结合转入和转出事件计算当前持有NFT:

async function getNFTs(address) {
  // 获取所有转入当前地址的Transfer事件
  const transferInEvents = await contract.getPastEvents("Transfer", {
    filter: { to: address },
    fromBlock: 0,
    toBlock: "latest"
  });
  // 获取所有从当前地址转出的Transfer事件
  const transferOutEvents = await contract.getPastEvents("Transfer", {
    filter: { from: address },
    fromBlock: 0,
    toBlock: "latest"
  });

  // 用Set存储转入的tokenId,自动去重
  const ownedTokens = new Set(transferInEvents.map(evt => evt.returnValues.tokenId));
  // 移除已转出的tokenId
  transferOutEvents.forEach(evt => ownedTokens.delete(evt.returnValues.tokenId));

  return Array.from(ownedTokens);
}

额外验证点

  • 确认合约的Transfer事件符合标准ERC721/ERC1155定义,to和from字段类型为address,否则过滤条件会失效。
  • 检查传入的account地址格式是否与合约事件中记录的一致(Web3.js事件过滤对地址大小写敏感)。

内容的提问来源于stack exchange,提问作者bela jonas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 11:46:02