[英]How to get ERC-721 tokenID?
我创建了一个部署在 ropston.network 上的 ERC-721 合约。 使用合同,我正在创建 NFT,并且它完全可以正常工作。
现在对于转移部分,我需要获取任何 NFT 的 tokenID 并转移到其他地址,但是每当我从 etherscan 或使用 web3 获取交易详细信息时,我都无法获取 tokenID。
我想将 tokenID 存储在数据库中,以便在转移到其他地址时可以使用它。
我已经圈出上图中所需的确切 tokenID。
我正在使用以下代码:
window.ethereum
.request({
method: 'eth_sendTransaction',
params: [
{
from: fromAddress,
to: contractAddress,
gas: '50000',
data: nftContract.methods.transferFrom(fromAddress, toAddress, tokenNumber).encodeABI()
},
],
})
我只想在创建 NFT 时获取 tokenID 并存储到数据库中以供参考并执行业务逻辑。
function mintNFT(address recipient, string memory tokenURI)
public onlyOwner
returns (uint256)
{
_tokenIds.increment();
uint256 newItemId = _tokenIds.current();
_mint(recipient, newItemId);
_setTokenURI(newItemId, tokenURI);
return newItemId;
}
以上是负责创建 NFT 的 solidity function。
你可以试试:
const receipt = await web3.eth.getTransactionReceipt(hash)
const tokenId = Web3.utils.hexToNumber(receipt.logs[0].topics[3])
I check hash from ropsten testnet: https://ropsten.etherscan.io/tx/0x59928012c3e0605b9346215c24654e84be29f2bf47949a2284aecf9991996a28
output 是 11
您的mintNFT()
function 不会发出任何包含newItemId
的事件。
solidity 使用的是标准的 transfer 定义
没有“标准定义”, ERC-721标准只定义了一个接口和一些其他规则——并且(接口的)实际实现由每个开发人员负责。 但是,我假设“标准定义”是指OpenZeppelin 实现,它是 ERC-721 标准的广泛使用的实现,许多开始使用 Solidity 编码的人都在使用它。
您可以在链接的实现中看到,OZ _mint()
function 发出Transfer()
事件,其中第三个参数是铸造的令牌 ID。
因此,执行mintNFT()
function 会有效地发出Transfer()
事件,其中包含新铸造的令牌 ID 作为第三个参数的值。
从 JS 代码执行mintNFT()
合约 function 后,它会返回一个PromiEvent
object,您可以使用它来捕获其receipt
事件。
收据包含发出的日志,您也可以在其中找到Transfer()
日志。
const tx = nftContract.methods.mintNFT(...).send({from: ...});
tx.on('receipt', function(receipt){
console.log(logs[0].topics[3]); // this prints the hex value of the tokenId
// you can use `web3.utils.hexToNumber()` to convert it to decimal
});
如果您想从已经存在的交易中获取令牌 ID(使用 tx 哈希),您可以使用以下代码段:
web3.eth.getTransactionReceipt('0x258a6d35445814d091ae67ec01cf60f87a4a58fa5ac1de25d0746edf8472f189').then(function(data){
let transaction = data;
let logs = data.logs;
console.log(logs);
console.log(web3.utils.hexToNumber(logs[0].topics[3]));
});
您可以在 web3 文档中找到send() 方法和收据的更多详细信息。
如果receipt.logs[0].topics[3]
不起作用,试试这个:
receipt.events.Transfer.returnValues.tokenId
出于某种原因,我的 tokenId 在receipt.logs[1].topics[3]
而不是receipt.logs[0].topics[3]
下(与索引 arguments 有关?)。 不过很容易找到,就好像您的 ID 是自动生成的(通常是这样),它会显示在日志中,例如 tokenId 3:
0x0000000000000000000000000000000000000000000000000000000000000003
因此,只要您的 ID 小于 10,就可以将它们识别为小数, 0x00...03 = 3
:
您可以在 you.network Scanner 的日志中看到它。
那么这只是将它从十六进制转换为十进制的情况。 您可以在普通 JS 中执行此操作,将基数 16 传递给十六进制:
const tokenId = parseInt(receipt.logs[1].topics[3], 16);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.