PRC-721
#
PRC-721 ContractPRC-721 is a standard interface for issuing non-fungible tokens (NFT) on the PlatON network and is fully compatible with ERC-721.
#
Protocol StandardsEach PRC-721-compliant smart contract must implement the PRC721 and PRC165 interfaces, and can implement other extended interfaces according to business needs.
#
PRC-721 & PRC-165 Interfaceinterface PRC721 /* is PRC165 */ { //events 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);
//required function balanceOf(address _owner) external view returns (uint256); function ownerOf(uint256 _tokenId) external view returns (address); function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable; function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable; function transferFrom(address _from, address _to, uint256 _tokenId) external payable; function approve(address _approved, uint256 _tokenId) external payable; function setApprovalForAll(address _operator, bool _approved) external; function getApproved(uint256 _tokenId) external view returns (address); function isApprovedForAll(address _owner, address _operator) external view returns (bool); interface PRC165 { function supportsInterface(bytes4 interfaceID) external view returns (bool); }
//optional interface PRC721TokenReceiver { function onERC721Received(address _operator, address _from, uint256 _tokenId, bytes _data) external returns(bytes4); } //The metadata extension interface is optional for PRC-721 smart contracts and allows users to query the name of the smart contract as well as the details of the asset represented by the NFT. interface PRC721Metadata { function name() external view returns (string _name); function symbol() external view returns (string _symbol); function tokenURI(uint256 _tokenId) external view returns (string); } //The enumeration extension is optional for PRC-721 smart contracts and allows a user's smart contract to publish its full list of NFTs and make them visible. interface PRC721Enumerable { function totalSupply() external view returns (uint256); function tokenByIndex(uint256 _index) external view returns (uint256); function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256); }}
#
Required interfacesbalanceOf
Counts the number of NFTs held by users.
ownerOf
Query the holder of the NFT.
safeTransferFrom
Transfer ownership of the NFT from one address to another.
transferFrom
Transferring NFT ownership, the caller is responsible for confirming that the recipient has the ability to receive NFTs that might otherwise be permanently lost.
approve
Authorize a third party to operate an NFT asset.
setApprovalForAll
Authorize a third party to operate an NFT asset.
getApproved
Get which address management is authorized for a single NFT.
isApprovedForAll
Queries whether an address is authorized to manage token by another address.
supportsInterface
Queries whether an address is authorized to manage token by another address.
#
Optionally interfacesonERC721Received
Contracts that need to accept secure transfers must implement the PRC721TokenReceiver interface.
name
The name of the contract.
symbol
The abbreviated code for the contract.
tokenURI
Give the token a Uniform Resource Identifier (URI) that points to a JSON file that conforms to the "PRC721 Metadata JSON Schema", which needs to be assigned a unique URI for each token when minting it.
{ "title": "Asset Metadata", "type": "object", "properties": { "name": { "type": "string", "description": "Identifies the asset to which this NFT represents" }, "description": { "type": "string", "description": "Describes the asset to which this NFT represents" }, "image": { "type": "string", "description": "A URI pointing to a resource with mime type image/* representing the asset to which this NFT represents. Consider making any images at a width between 320 and 1080 pixels and aspect ratio between 1.91:1 and 4:5 inclusive." } }}
totalSupply
Query the total number of tokens owned by this contract.
tokenByIndex
Query token by index.
tokenOfOwnerByIndex
Find the user's token based on the index.
#
EventTransfer
This event is triggered when the ownership of any NFT changes (either way), and a log of ownership change information is recorded on the chain.
Approval
Triggered when the authorized address of the NFT is changed or confirmed, logging this information on the chain.
ApprovalForAll
Triggered when the owner enables or disables the operator (the operator can manage the NFTs held by the owner), logging this information in the chain.
#
ExampleThe PRC-721 standard is fully compatible with ERC-721, examples of which can be found here.
#
ViewIt can be viewed through PlatON browser and also through ATON to view the PRC-721 contract transactions.
#
Deployplease refer to Solidity Contracts Getting Started Manual
#
Invoking functionsUsing python as an example.
#
Installing python dependenciesUse the following command to install the PlatON python library, Python version 3.7.5+ is recommended:
pip install client-sdk-python
During the installation process, some dependency packages will require c++14 compilation, please download cppbuildtools after you see the relevant prompt, use the default value to install it, and then re-execute the pip install command.
#
Instantiate the contractThe following is a sample python code.
from client_sdk_python import Web3, HTTPProvider
rpc, chain_id, hrp = 'http://127.0.0.1:6789', 210425, 'lat'w3 = Web3(HTTPProvider(rpc), chain_id=chain_id, hrp_type=hrp)abi = [ { "inputs": [ { "internalType": "string", "name":"_name", "type": "string"} {"internalType": "string", "name":"_symbol", "type": "string"} ], "stateMutability": "nonpayable", "type": "constructor" }, { "inputs": [ { "internalType": "address", "name": "_to", "type": "address" } {"internalType": "uint256", "name":"_tokenId", "type": "uint256"}, {"internalType": "uint256", "name":"_tokenId", "type": "uint256"}, {"internalType": "string", "name":"_uri", "type": "string"} ], "name": "mint", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [{"internalType": "address", "name": "_owner", "type": "address"}], "name": "balanceOf", "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}], "stateMutability": "view", "type": "function" }, { "inputs": [{"internalType": "uint256", "name": "_tokenId", "type": "uint256"}], "name": "ownerOf", "outputs": [{"internalType": "address", "name": "_owner", "type": "address"}], "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", "name": "_from", "type": "address" } {"internalType": "address", "name":"_to", "type": "address"}, {"internalType": "address", "name":"_to", "type": "address"}, {"internalType": "address", "name":"_to", "type": "address"}, {"internalType": "uint256", "name":"_tokenId", "type": "uint256"}, {"internalType": "uint256", "name":"_tokenId", "type": "uint256"} ], "name": "safeTransferFrom", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "anonymous": false, "inputs": [ { "indexed": true, "internalType": "address", "name": "_from", "type": "address" } {"indexed": true, "internalType": "address", "name":"_to", "type": "address"}, "indexed": true, "internalType": "address", "name":"_to", "type": "address"}, {"indexed": true, "internalType": "uint256", "name":"_tokenId", "type": "uint256"} ], "name": "Transfer", "type": "event" },]prc721 = w3.eth.contract(address='contract address', abi=abi)# View all functions and events of the contractprint([func for func in prc721.functions])print([event for event in prc721.events])
#
Query contract informationWith balanceOf, ownerOf example, other query methods are similar to this.
# Count the number of NFTs held by usersprc721.functions.balanceOf('your address').call()# Query the holder of NFTsprc721.functions.ownerOf('your token id').call()
#
Sending contract transactionsUsing the safeTransferFrom example, other transaction methods are similar to this.
# Transfer ownership of NFT from one address to anothertx = { 'chainId': w3.chain_id, 'nonce': w3.eth.getTransactionCount('your address'), 'gas': 4012388, 'value': 0, 'gasPrice': 1000000000,}txn = prc721.functions.safeTransferFrom(_from='your address', _to='to address', _tokenId='your token id').buildTransaction(tx)signed_txn = w3.eth.account.signTransaction(txn, private_key='your private key')tx_hash = w3.eth.sendRawTransaction(signed_txn.rawTransaction).hex()receipt = w3.eth.waitForTransactionReceipt(tx_hash)
#
Get contract eventsUsing the safeTransferFrom transaction event example, other event fetching methods are similar to this.
events = prc721.events.Transfer().processReceipt(receiveipt)
#
Upload Metadata to IPFS networkMetadata is the metadata of NFT tokens in order to display more detailed information about NFT assets, stored under the chain, generally the issuance of an NFT token will specify a URI path to the Metadata data of this token.
#
1. Install IPFSRefer to the IPFS installation instructions to install and start.
#
2. Adding files to ipfsPrepare an image, name it PlatON.jpeg, and upload it to the ipfs node
$ ipfs add PlatON.jpegadd QmZtmD2qt6fJot32nabSP3CUjicnypEBz7bHVDhPQt9aAy PlatON.jpeg//QmZtmD2qt6fJot32nabSP3CUjicnypEBz7bHVDhPQt9aAy is the unique ID of the file, generated after adding it to ipfs
If you open the link to the image in your browser and see the image, it means that the image was successfully downloaded: https://ipfs.io/ipfs/QmZtmD2qt6fJot32nabSP3CUjicnypEBz7bHVDhPQt9aAy?filename=PlatON.jpeg
With the image link above, you can use it to construct the metadata for NFT.
First, follow the instructions in the PRC-721 document metadata to create a json file named PlatON.json:
{ "name": "PlatON.jpg", "author": "PlatON", "description": "use for prc721", "image": "https://ipfs.io/ipfs/QmZtmD2qt6fJot32nabSP3CUjicnypEBz7bHVDhPQt9aAy?filename=PlatON.jpeg"}
Upload to the ipfs node:
$ ipfs add PlatON.jsonadded QmQXqTVCb1w7CmdsYxHWR1T1qyaCHHgWwiPmoZDcQL39Px PlatON.json
Open the uri of the metadata file in your browser: https://ipfs.io/ipfs/QmQXqTVCb1w7CmdsYxHWR1T1qyaCHHgWwiPmoZDcQL39Px?filename=PlatON.json
Above, the upload is complete.