简体   繁体   English

如何获取ERC-721 tokenID?

[英]How to get ERC-721 tokenID?

I have created a ERC-721 contract deployed on ropston.network.我创建了一个部署在 ropston.network 上的 ERC-721 合约。 Using contract I'm creating NFT's and its totally working fine.使用合同,我正在创建 NFT,并且它完全可以正常工作。

Now for the transfer part I need to get tokenID of any NFT and transfer to to other address but I'm not able get the tokenID whenever I fetch transaction details from etherscan or using web3.现在对于转移部分,我需要获取任何 NFT 的 tokenID 并转移到其他地址,但是每当我从 etherscan 或使用 web3 获取交易详细信息时,我都无法获取 tokenID。

I want to store the tokenID in DB so it can be utilized while transferring to other address.我想将 tokenID 存储在数据库中,以便在转移到其他地址时可以使用它。

在此处输入图像描述

I have encircled the exact tokenID required in above image.我已经圈出上图中所需的确切 tokenID。

I'm using following code:我正在使用以下代码:

window.ethereum
    .request({
        method: 'eth_sendTransaction',
        params: [
            {
                from: fromAddress,
                to: contractAddress,
                gas: '50000',
                data: nftContract.methods.transferFrom(fromAddress, toAddress, tokenNumber).encodeABI()
            },
        ],
    })

I just want to get tokenID when NFT was created and store into DB for reference and perform business logic.我只想在创建 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;
    }

Above is the solidity function responsible for creating the NFT.以上是负责创建 NFT 的 solidity function。

You can try:你可以试试:

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 I check hash from ropsten testnet: https://ropsten.etherscan.io/tx/0x59928012c3e0605b9346215c24654e84be29f2bf47949a2284aecf9991996a28

and output is 11 output 是 11

Your mintNFT() function doesn't emit any event containing the newItemId .您的mintNFT() function 不会发出任何包含newItemId的事件。

solidity is using the standard definition of transfer solidity 使用的是标准的 transfer 定义

There's no "standard definition", the ERC-721 standard only defines an interface and few other rules - and the actual implementation (of the interface) is on each developer.没有“标准定义”, ERC-721标准只定义了一个接口和一些其他规则——并且(接口的)实际实现由每个开发人员负责。 However I'm assuming that by the "standard definition" you mean the OpenZeppelin implementation , which is a widely used implementation of the ERC-721 standard and is used by many people who start coding in Solidity.但是,我假设“标准定义”是指OpenZeppelin 实现,它是 ERC-721 标准的广泛使用的实现,许多开始使用 Solidity 编码的人都在使用它。

You can see in the linked implementation, that the OZ _mint() function emits the Transfer() event, where the 3rd argument is the minted token ID.您可以在链接的实现中看到,OZ _mint() function 发出Transfer()事件,其中第三个参数是铸造的令牌 ID。

So executing your mintNFT() function effectively emits the Transfer() event that contains the newly minted token ID as a value of the 3rd parameter.因此,执行mintNFT() function 会有效地发出Transfer()事件,其中包含新铸造的令牌 ID 作为第三个参数的值。


After you've executed the mintNFT() contract function from your JS code, it returns a PromiEvent object, that you can use to catch its receipt event.从 JS 代码执行mintNFT()合约 function 后,它会返回一个PromiEvent object,您可以使用它来捕获其receipt事件。

The receipt contains the emited logs, where you can find the Transfer() log as well.收据包含发出的日志,您也可以在其中找到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
});

If you want to get the token ID from an already existing transaction (using the tx hash), you can use this snippet:如果您想从已经存在的交易中获取令牌 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]));
});

You can find more details in the web3 docs for the send() method and the receipt .您可以在 web3 文档中找到send() 方法收据的更多详细信息。


Try this if receipt.logs[0].topics[3] doesn't work:如果receipt.logs[0].topics[3]不起作用,试试这个:

receipt.events.Transfer.returnValues.tokenId

For some reason my tokenId was under receipt.logs[1].topics[3] not receipt.logs[0].topics[3] (something to do with the indexed arguments?).出于某种原因,我的 tokenId 在receipt.logs[1].topics[3]而不是receipt.logs[0].topics[3]下(与索引 arguments 有关?)。 It was easy to find though, as if your id's are auto generated (and they usually are), it will show up in the logs as for example tokenId 3:不过很容易找到,就好像您的 ID 是自动生成的(通常是这样),它会显示在日志中,例如 tokenId 3:

0x0000000000000000000000000000000000000000000000000000000000000003

So as long as your id is under 10 they can be spotted as a decimal, 0x00...03 = 3 :因此,只要您的 ID 小于 10,就可以将它们识别为小数, 0x00...03 = 3

You can see it in the log on you.network Scanner.您可以在 you.network Scanner 的日志中看到它。

Then it's just a case of converting it from Hex to Decimal.那么这只是将它从十六进制转换为十进制的情况。 Which you can do in plain JS, passing in the radix 16 for hex:您可以在普通 JS 中执行此操作,将基数 16 传递给十六进制:

const tokenId = parseInt(receipt.logs[1].topics[3], 16);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM