- A+
一、说明
目前直接在支持BSC链的NFT平台上发行NFT作品是最为简单的方法,但是该处理方法存在一个问题,即发行的NFT作品无法在tp钱包显示图片,导致在tp钱包展示NFT 集合时比较混乱,无法正常显示NFT。
出现该问题的原因,主要是NFT图片的存储形式导致的。无论是nft图片存储到铸造平台的去中心化链上还是存储到ipfs等主流公链上都会存在链上数据与tp钱包之间的数据通信问题。主要考虑是NFT图片数据的访问链路或者接口与钱包直接的数据互信问题,导致无法在TP钱包展示NFT图片。如果此时可以正常在metamask等钱包展示NFT图片,但是无法在TP显示图片,进一步印证了该问题。
二、处理方案
解决该问题的处理方案,只能是脱离现有的NFT铸造平台,通过自部署NFT合约,设置NFT图片的存储方式以允许TP钱包访问,然后通过接口直接铸造NFT作品。
带有tokenURI的NFT合约源代码如下:
1、IERC721接口文件如下:
pragma solidity ^0.5.5;
import "./ITRC165.sol";
/**
* @dev Required interface of an TRC721 compliant contract.
*/
contract ITRC721 is ITRC165 {
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
/**
* @dev Returns the number of NFTs in `owner`'s account.
*/
function balanceOf(address owner) public view returns (uint256 balance);
/**
* @dev Returns the owner of the NFT specified by `tokenId`.
*/
function ownerOf(uint256 tokenId) public view returns (address owner);
/**
* @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to
* another (`to`).
*
*
*
* Requirements:
* - `from`, `to` cannot be zero.
* - `tokenId` must be owned by `from`.
* - If the caller is not `from`, it must be have been allowed to move this
* NFT by either {approve} or {setApprovalForAll}.
*/
function safeTransferFrom(address from, address to, uint256 tokenId) public;
/**
* @dev Transfers a specific NFT (`tokenId`) from one account (`from`) to
* another (`to`).
*
* Requirements:
* - If the caller is not `from`, it must be approved to move this NFT by
* either {approve} or {setApprovalForAll}.
*/
function transferFrom(address from, address to, uint256 tokenId) public;
function approve(address to, uint256 tokenId) public;
function getApproved(uint256 tokenId) public view returns (address operator);
function setApprovalForAll(address operator, bool _approved) public;
function isApprovedForAll(address owner, address operator) public view returns (bool);
function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public;
}
2、ITRC721Metadata 元数据接口合约源代码如下:
pragma solidity ^0.5.5;
import "./ITRC721.sol";
/**
* @title TRC-721 Non-Fungible Token Standard, optional metadata extension
*/
contract ITRC721Metadata is ITRC721 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function tokenURI(uint256 tokenId) external view returns (string memory);
}
3、TRC721Metadata 元数据实现类合约源代码如下
pragma solidity ^0.5.5;
import "./Counters.sol";
import "./TRC165.sol";
import "./TRC721.sol";
import "./ITRC721Metadata.sol";
contract TRC721Metadata is Context, TRC165, TRC721, ITRC721Metadata {
// Token name
string private _name;
// Token symbol
string private _symbol;
// Base URI
string private _baseURI;
// Optional mapping for token URIs
mapping(uint256 => string) private _tokenURIs;
/*
* bytes4(keccak256('name()')) == 0x06fdde03
* bytes4(keccak256('symbol()')) == 0x95d89b41
* bytes4(keccak256('tokenURI(uint256)')) == 0xc87b56dd
*
* => 0x06fdde03 ^ 0x95d89b41 ^ 0xc87b56dd == 0x5b5e139f
*/
bytes4 private constant _INTERFACE_ID_TRC721_METADATA = 0x5b5e139f;
/**
* @dev Constructor function
*/
constructor (string memory name, string memory symbol) public {
_name = name;
_symbol = symbol;
// register the supported interfaces to conform to TRC721 via TRC165
_registerInterface(_INTERFACE_ID_TRC721_METADATA);
}
/**
* @dev Gets the token name.
* @return string representing the token name
*/
function name() external view returns (string memory) {
return _name;
}
/**
* @dev Gets the token symbol.
* @return string representing the token symbol
*/
function symbol() external view returns (string memory) {
return _symbol;
}
/**
* @dev Returns the URI for a given token ID. May return an empty string.
*
* If the token's URI is non-empty and a base URI was set (via
* {_setBaseURI}), it will be added to the token ID's URI as a prefix.
*
* Reverts if the token ID does not exist.
*/
function tokenURI(uint256 tokenId) external view returns (string memory) {
require(_exists(tokenId), "TRC721Metadata: URI query for nonexistent token");
string memory _tokenURI = _tokenURIs[tokenId];
// Even if there is a base URI, it is only appended to non-empty token-specific URIs
if (bytes(_tokenURI).length == 0) {
return "";
} else {
// abi.encodePacked is being used to concatenate strings
return string(abi.encodePacked(_baseURI, _tokenURI));
}
}
/**
* @dev Internal function to set the token URI for a given token.
*
* Reverts if the token ID does not exist.
*
* TIP: if all token IDs share a prefix (e.g. if your URIs look like
* `http://api.myproject.com/token/<id>`), use {_setBaseURI} to store
* it and save gas.
*/
function _setTokenURI(uint256 tokenId, string memory _tokenURI) internal {
require(_exists(tokenId), "TRC721Metadata: URI set of nonexistent token");
_tokenURIs[tokenId] = _tokenURI;
}
/**
* @dev Internal function to set the base URI for all token IDs. It is
* automatically added as a prefix to the value returned in {tokenURI}.
*
* _Available since v2.5.0._
*/
function _setBaseURI(string memory baseURI) internal {
_baseURI = baseURI;
}
/**
* @dev Returns the base URI set via {_setBaseURI}. This will be
* automatically added as a preffix in {tokenURI} to each token's URI, when
* they are non-empty.
*
* _Available since v2.5.0._
*/
function baseURI() external view returns (string memory) {
return _baseURI;
}
/**
* @dev Internal function to burn a specific token.
* Reverts if the token does not exist.
* Deprecated, use _burn(uint256) instead.
* @param owner owner of the token to burn
* @param tokenId uint256 ID of the token being burned by the msg.sender
*/
function _burn(address owner, uint256 tokenId) internal {
super._burn(owner, tokenId);
// Clear metadata (if any)
if (bytes(_tokenURIs[tokenId]).length != 0) {
delete _tokenURIs[tokenId];
}
}
}
4、MinterRole NFT铸造者权限角色实现类合约源代码
pragma solidity ^0.5.5;
import "./Context.sol";
import "./Roles.sol";
contract MinterRole is Context {
using Roles for Roles.Role;
event MinterAdded(address indexed account);
event MinterRemoved(address indexed account);
Roles.Role private _minters;
constructor () internal {
_addMinter(_msgSender());
}
modifier onlyMinter() {
require(isMinter(_msgSender()), "MinterRole: caller does not have the Minter role");
_;
}
function isMinter(address account) public view returns (bool) {
return _minters.has(account);
}
function addMinter(address account) public onlyMinter {
_addMinter(account);
}
function renounceMinter() public {
_removeMinter(_msgSender());
}
function _addMinter(address account) internal {
_minters.add(account);
emit MinterAdded(account);
}
function _removeMinter(address account) internal {
_minters.remove(account);
emit MinterRemoved(account);
}
}
5、NFT主合约核心代码如下:
pragma solidity ^0.5.5;
import "./TRC721.sol";
import "./TRC721Enumerable.sol";
import "./TRC721MetadataMintable.sol";
contract NFT is TRC721, TRC721Enumerable, TRC721MetadataMintable {
constructor() public TRC721Metadata("NFT", "NFT") {
}
}
通过自部署合约铸造NFT作品,即可将NFT图片存储到指定数据对象路径,即可解决TP无法显示NFT图片问题。
至此,完成NFT单品铸造完成后无法在tp钱包显示图片故障处理及解决方法。
pdf+视频(BSC币安链+TRX波场链)NFT发行教程及合约源代码下载:
币安智能链BSC+波场链TRX NFT发行(合约部署、开源、参数配置、开发、故障处理、工具使用)教程下载:
币安智能链BSC+波场链TRX NFT发行合约源代码下载
pdf+视频(BSC币安链+TRX波场链)NFT发行教程及合约源代码下载地址:
添加VX或者telegram获取全程线上免费指导
本文是全系列中第1 / 18篇:NFT发行
- 币安链BSC上NFT发行教程——NFT单品铸造完成后无法在tp钱包显示图片故障处理及解决方法【pdf+视频BSC链NFT发行教程下载】
- 比特币NFTs: Ordinals NFT 图片怎么从rawTransaction原始交易中解析
- Safe 多签钱包签名消息, 支持签名登录 Opensea
- 币安链BSC上NFT发行教程——NFT合约中的代理人针对所有NFT的授权功能【pdf+视频BSC链NFT发行教程下载】
- NFTScan | 06.12~06.18 NFT 市场热点汇总
- 币安链BSC上NFT发行教程——NFT元数据模板,支持上线opensea并交易【pdf+视频BSC链NFT发行教程下载】
- 币安链BSC上NFT发行教程——NFT根据拍卖次数指数型递增增加价格【pdf+视频BSC链NFT发行教程下载】
- 铭文NFT与代币进行联动,销毁NFT铭文可以铸造mint代币,支付usdt或者WETH可以mint铸造NFT铭文
- 币安链BSC上NFT发行教程——自动创建tokenid的NFT合约源码实现【pdf+视频BSC链NFT发行教程下载】
- 波场链TRX上NFT发行教程——web页面上传NFT头像到IPFS链【pdf+视频TRX链NFT发行教程下载】
- 从PStake解读BTCFI的窘境与未来
- 币安BSC智能链发币教程——扫描所有NFT,根据NFT持有情况分红代币【pdf+视频BSC发币教程下载】
- 币安链BSC上NFT发行教程——BSC链铸造nft并转账(空投)到其他钱包地址【pdf+视频BSC链NFT发行教程下载】
- 币安链BSC上NFT发行教程——两种方式在BSC币安链上铸造NFT及部署NFT合约【pdf+视频BSC链NFT发行教程下载】
- 币安BSC智能链NFT Market搭建教程——搭建基于BSC链的NFT Market合约实现【pdf+视频BSC NFT教程下载】
- 波场链TRX上NFT发行教程——NFT中元数据合约源代码实现【pdf+视频TRX链NFT发行教程下载】
- 波场链TRX上NFT发行教程——部署波场链上的NFT合约【pdf+视频TRX链NFT发行教程下载】
- 波场链TRX上NFT发行教程——使用腾讯云存储代替ipfs存储的实现方式【pdf+视频TRX链NFT发行教程下载】
- 我的微信
- 这是我的微信扫一扫
-
- 我的电报
- 这是我的电报扫一扫
-