Solidity
NFT 元數據未顯示在 opensea 上?
我正在使用開放式 Zeppelin 在 ETH 上開發 NFT 合約,並達到了我在 rinkeby 上部署的階段。但是,由於圖像和元數據未在 opensea 上顯示,因此 tokenURI 和 contractURI 似乎存在問題。
我像這樣實現 tokenURI 和 ContractURI:
// SPDX-License-Identifier: MIT pragma solidity ^0.8.1; import "hardhat/console.sol"; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; //access control import "@openzeppelin/contracts/access/Ownable.sol"; // Helper functions OpenZeppelin provides. import "@openzeppelin/contracts/utils/Counters.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; import "./libraries/Base64.sol"; contract MetropolisWorldGenesis is ERC721, Ownable { .... string private _contractURI; function contractURI() public view returns (string memory) { return _contractURI; } function tokenURI(uint256 _tokenId) public view override returns (string memory) { PropertyAttributes memory propAttributes = nftHolderAttributes[_tokenId]; string memory json = Base64.encode( abi.encodePacked( '{"name": "', propAttributes.name, '", "description": "',propAttributes.description,'", "image": "', propAttributes.image, '", "attributes": [ { "trait_type": "Tower", "value": ',propAttributes.properties.tower,', "trait_type": "District", "value":',propAttributes.properties.district, ', "trait_type": "neighborhood", "value":',propAttributes.properties.neighborhood,',]}' ) ); string memory output = string( abi.encodePacked("data:application/json;base64,", json) ); return output; } function setContractURI( string memory name, string memory desc, string memory image,string memory link, uint royalty) public onlyOwner() { string memory x = Base64.encode( abi.encodePacked( '{"name": "', name, '", "description": "', desc, '", "image": "', image, '", "external_link": "', link, '","seller_fee_basis_points":"', royalty, // 100 Indicates a 1% seller fee '", "fee_recipient": "0xA97F337c39cccE66adfeCB2BF99C1DdC54C2D721" }' // Where seller fees will be paid to.} ) ); _contractURI = string(abi.encodePacked( "data:application/json;base64,", x )); console.log("contract uri updated"); } }
當在本地執行時,tokenURI 會返回以下輸出,它會解析瀏覽器中的正確數據:
data:application/json;base64,eyJuYW1lIjogIkdpbGRlZCBBdHRpYyIsICJkZXNjcmlwdGlvbiI6ICJUaGUgQXN0cm9ub21lcidzIFN0dWRpbwpVbmRlciB0aGUgZG9tZSBpcyBhIHBsYW5ldHJpdW0gClJlc2VhcmNoZXMgdGhlIG9yaWdpbnMgb2YgdGhlIE1ldHJvcG9saXMiLCAiaW1hZ2UiOiAiaXBmczovL1FtWnc3NzY1ZG04aHBIRndITDl3b29RSkNzSkd6TFR3WTIyNjVDR1lpeFB3aUciLCAiYXR0cmlidXRlcyI6IFsgeyAidHJhaXRfdHlwZSI6ICJUb3dlciIsICJ2YWx1ZSI6IFRvd2VyIDEsICJ0cmFpdF90eXBlIjogIkRpc3RyaWN0IiwgInZhbHVlIjpIaWdoLUZseWVyLCAidHJhaXRfdHlwZSI6ICJuZWlnaGJvcmhvb2QiLCAidmFsdWUiOkZyZWUgQWxsZXkgUXVhcnRlcnMsXX0=
任何想法我哪裡出錯了?
因此,當我認為這是創建動態元數據的一種完全可行的方法時,我需要的更改是在令牌 URI 函式的末尾添加正確的括號。所以功能變成了這個。一個微小但令人沮喪的變化。
function tokenURI(uint256 _tokenId) public view override returns (string memory) { PropertyAttributes memory propAttributes = nftHolderAttributes[_tokenId]; string memory json = Base64.encode( abi.encodePacked( '{"name": "', propAttributes.name, '", "description": "',propAttributes.description,'", "image": "', propAttributes.image, '", "attributes": [ { "trait_type": "Tower", "value": ',propAttributes.properties.tower,', "trait_type": "District", "value":',propAttributes.properties.district, ', "trait_type": "neighborhood", "value":',propAttributes.properties.neighborhood,'}]}' ) ); string memory output = string( abi.encodePacked("data:application/json;base64,", json) ); return output; }
我還了解到所有變數都必須是字元串,因此 contractURI 函式中的版稅變數導致它無法工作。並且設置合約 URI 功能需要更改為此。
function setContractURI( string memory name, string memory desc, string memory image,string memory link, string memory royalty) public onlyOwner() { string memory x = Base64.encode( abi.encodePacked( '{"name": "', name, '", "description": "', desc, '", "image": "', image, '", "external_link": "', link, '","seller_fee_basis_points":"', royalty, // 100 Indicates a 1% seller fee '", "fee_recipient": "0xA97F337c39cccE66adfeCB2BF99C1DdC54C2D721" }' // Where seller fees will be paid to.} ) ); _contractURI = string(abi.encodePacked( "data:application/json;base64,", x )); console.log("contract uri updated"); }
令牌 uri 應該是 URI,而不是 JSON 類型。您應該將您的 json 上傳到伺服器或類似 IPFS 的東西,並將您的 URI 帶到您的契約中。
有關更多資訊,請查看提案的原始網站。特別是檢查元數據部分。