# Cudos Network NFTs
NFTs are compatible with Cudos Network natively.
# Module Overview
A module for operating with Non-Fungible Tokens on the CUDOS network. The methods that are exposed by it are mainly based on the ERC721 interface (opens new window) from the Ethereum network and not so much on the CW-721 (opens new window) from the Cosmos network. The reason for this is that the main idea of the module is to transfer tokens through the bridge (opens new window) between the Cudos Network and Ethereum, and thus it is better to follow the ERC721 standard.
# Module Interface
The module gives the user the ability to either write (via transaction) or read (via query) to/from the network.
# The following commands are available (click on them for further info)
# Transaction
Command | Description |
---|---|
issue | Issues a new denomination to the specified owner |
mint | Mints a new NFT in a given denomination to the specified owner |
edit | Edits an already existing NFT |
transfer | Transfers an existing NFT from one owner to another |
burn | Burns the specified NFT . Only the owner can burn the NFT |
approve | Adds an approved operator that can transfer the NFT |
revoke | Removes an approved operated for the NFT |
approveAll | Approves an operator on user level - the operator can transfer all of the user tokens |
# Query
Command | Description |
---|---|
denom | Queries for a denomination by denomination Id |
denom-by-name | Queries for a denomination by denomination name |
denoms | Query for all denominations of all collections of NFTs |
collection | Get all the NFTs from a given collection . |
supply | Returns the total supply of a collection or owner of NFTs. |
owner | Queries for the owner and returns the NFTs owned by an account address. |
token | Query a single NFT from a collection . |
approvals | Get the approved addresses for the NFT |
isApprovedForAll | Gets whether the address is approved for all |
# Quick start (public testnet)
In this section we provide the basic commands that need to be executed in order to mint an NFT and send it to another wallet. For a full description of all the available functionality, please have a look at each function's description. In order to follow these instructions, a running node is needed (for example a full node), as well as having added the keys of at least one wallet. You can find instructions on how to add an account into your keyring, or import a wallet you created in Keplr in the developer setup page. After doing so, keep your terminal inside the Docker container open to follow the next steps.
# Minting a new NFT
All NFTs need to belong to a parent group, called denomination, or denom
for short.
A denomination can have many NFTs minted within it, and is used to identify the creator of an NFT.
Denominations can be thought of as groups of NFTs.
Thus, in order to mint an NFT, the first step is to issue a denomination for our account.
Denominations need to have an ID, which needs to be an alphanumeric string in lowercase -- we use the placeholder <testdenom>
in the examples below.
We also need to specify in flags the network where we want to issue our denomination, the wallet that will issue it (which needs to be in the keyring -- we use the placeholder <walletAddress>
in what follows) and a name for the denomination, which we can choose.
We will be using the test
backend for the keyring (the default one in public testnet) for these instructions.
However, if you are running a Validator using the os
backend, you can use your Validator wallet, as long as you specify the --keyring-backend os
flag in the commands below.
Also, we must specify the node
flag, setting it to the IP address of the node that is running on the Cudos Network.
Thus, in order to create a denomination in public testnet the command looks like
cudos-noded tx nft issue <testdenom> --from=<walletAddress> --name="My first denom" --chain-id=cudos-testnet-public --node https://sentry1.gcp-uscentral1.cudos.org:26657
Please note that we will be prompted at all steps to confirm we want to broadcast the transaction.
When asked for confirmation, just type y
and press enter.
Now that we have created a denom
for our account, we can mint an NFT.
When minting one, we can choose who the owner of that NFT is going to be at the start.
More precisely, when minting an NFT we need to include the --recipient
flag and assign it the wallet address where we want that NFT to go to.
The address that we choose will be the owner of that NFT.
Let us start by minting and NFT and sending it to our own address. To do so, simply run the following command, using the denom name you just chose and your wallet address,
cudos-noded tx nft mint <testdenom> --from=<walletAddress> --recipient=<walletAddress> --chain-id=cudos-testnet-public --node https://sentry1.gcp-uscentral1.cudos.org:26657
To see our freshly minted NFT, we can run the following command
cudos-noded query nft collection <testdenom>
The output should look like the following:
collection:
denom:
creator: <walletAddress>
id: <testdenom>
name: My first denom
schema: ""
nfts:
- approvedAddresses: {}
data: ""
id: "1"
name: ""
owner: <walletAddress>
uri: ""
pagination:
next_key: null
total: "0"
This provides a list of all the NFTs for the specified denom.
All NFTs belong to a collection
, and are uniquely identified by its denom and its NFT ID.
At the moment, we have only created one NFT, and thus its ID is 1.
This ID is just a counter, so it will increase by one unit every time we mint a new NFT.
# Further options for NFT minting
We can add extra flags when minting an NFT, in order to further customise it.
For example, we can use the --uri
to set some metadata to it (in JSON format), or we can set some fees that will need to be paid every time this NFT is transacted with, with the flag --fees
.
In order to add a fee, we also need to include its unit.
For example, if we want to mint an NFT and set a 10acudos fee on it (acudos stands for attoCUDOS, the SI prefix (opens new window)), we can execute the following
cudos-noded tx nft mint <testdenom> --from=<walletAddress> --recipient=<walletAddress> --chain-id=cudos-testnet-public --fees=10acudos
# Sending an NFT to another wallet
In order to send an NFT we use the transfer
function.
Please note that sending the NFT to someone else changes its owner, and owners are able to, amongst other things, change its metadata or approve addresses to move it.
To test this, first we would recommend adding a second wallet to your keyring, so that you are still the owner after the NFT after moving it to a different account. As a reminder, you can create a new wallet and add it to your keyring by running the following command,
cudos-noded keys add <newAccount>
where <newAccount>
is a placeholder to be changed to the name you want to give to this new account.
After doing that, we can transfer the NFT by specifying the wallet where it comes from, the one we want to send it to, the denom ID, the NFT ID (the incremental ID we explained above, which was 1
for our first NFT) and the relevant flags:
cudos-noded tx nft transfer <walletAddress> <newAccount> <testdenom> 1 --from=<walletAddress> --chain-id=cudos-testnet-public
Note that we still need to specify the --from
flag with the address that is requesting the transfer of the NFT.
That is because, in addition to being the owner of the NFT, it can also be an address that is approved to move this token.
# Full commands information
# Transaction commands
# issue
Issues a new denom that will be used for minting new NFTs. Only the denom creator can issue new NFTs.
- arguments:
denom-id
string
Unique Id that identifies the denom. Must be all lowercase
required: true
- flags:
--name
string
The unique name of the denom.
required: true
--from
string
The address that is issuing the denom. Will be set as denom creator. Can be either an address or alias to that address
required: true
--schema
string
Metadata about the NFT. Schema-content or path to schema.json.
required: false
--chain-id
string
The name of the network.
required
--fees
string
The specified fee for the operation
required: false
Example:
$ cudos-noded tx nft issue <denom-id> --from=<key-name> --name=<denom-name> --schema=<schema-content or path to schema.json> --chain-id=<chain-id> --fees=<fee>
# mint
Mint a NFT and set the owner to the recipient. Only the denom creator can mint a new NFT.
- arguments:
denom-id
string
The denomId that this NFT will be associated
required: true
- flags:
--from
string
The address that is minting the NFT. Must be denom creator. Can be either an address or alias to that address
required: true
--recipient
string
The user(owner) that will receive the NFT
required: true
--uri
string
The URI of the NFT.
required: false
--chain-id
string
The name of the network.
required: true
--fees
string
The specified fee for the operation
required: false
Example:
$ cudos-noded tx nft mint <denom-id> --recipient=<recipient> --from=<key-name> --uri=<uri> --chain-id=<chain-id> --fees=<fee>
# edit
Edit an NFT - can change name, uri or data. Only the owner can edit the NFT.
- arguments:
denom-id
string
The denomId of the edited NFT
required: true
token-id
string
Unique Id that identifies the token. Must be all lowercase
required: true
- flags:
--from
string
The address that is editing the NFT. Can be either an address or alias to that address
required: true
--uri
string
The URI of the NFT.
required: false
--chain-id
string
The name of the network.
required: true
--fees
string
The specified fee for the operation
required: false
Example:
$ cudos-noded tx nft edit <denom-id> <token-id> --from=<key-name> --uri=<uri> --chain-id=<chain-id> --fees=<fee>
# burn
Burns the NFT - deletes it permanently.
- arguments:
denom-id
string
The denomId of the edited NFT
required: true
token-id
string
Unique Id that identifies the token. Must be all lowercase
required: true
- flags:
--from
string
The address that is editing the NFT. Can be either an address or alias to that address
required: true
--chain-id
string
The name of the network.
required: true
--fees
string
The specified fee for the operation
required: false
Example:
$ cudos-noded tx nft burn <denom-id> <token-id> --from=<key-name> --chain-id=<chain-id> --fees=<fee>
# transfer
Transfer an NFT - from one owner to a new owner. The sender must be either the owner, an approved address for that NFT or a globally approved operator.
- arguments:
from
string
The address of the NFT owner
required: true
to
string
The address of the user that will receive the NFT
required: true
denom-id
string
The denomId of the edited NFT
required: true
token-id
string
Unique Id that identifies the token. Must be all lowercase
required: true
- flags:
--from
string
The address that is requesting the transfer of the NFT. Can be either an address or alias to that address. must be either the owner, approved address on NFT or globally approved operator.
required: true
--uri
string
The URI of the NFT.
required: false
--chain-id
string
The name of the network.
required: true
--fees
string
The specified fee for the operation
required: false
Example:
$ cudos-noded tx nft transfer <from> <to> <denom-id> <token-id> --from=<key-name> --uri=<uri> --chain-id=<chain-id> --fees=<fee>
# approve
Adds an address to the approved list. Approved addresses on the NFT level can transfer the NFT from one owner to another. Approved addresses for the NFT are cleared upon transfer.
- arguments:
approvedAddress
string
The address that will be approved
required: true
denom-id
string
The denomId of the edited NFT
required: true
token-id
string
Unique Id that identifies the token. Must be all lowercase
required: true
- flags:
--from
string
The address that is requesting the approval. Can be either an address or alias to that address. must be either the owner or globally approved operator.
required: true
--chain-id
string
The name of the network.
required: true
--fees
string
The specified fee for the operation
required: false
Example:
$ cudos-noded tx nft approve <approvedAddress> <denom-id> <token-id> --from=<key-name> --chain-id=<chain-id> --fees=<fee>
# revoke
Removes the address from the approved list. Approved addresses on the NFT level can transfer the NFT from one owner to another. Approved addresses for the NFT are cleared upon transfer.
- arguments:
addressToRevoke
string
The address that will be removed
required: true
denom-id
string
The denomId of the edited NFT
required: true
token-id
string
Unique Id that identifies the token. Must be all lowercase
required: true
- flags:
--from
string
The address that is requesting the removal of approval. Can be either an address or alias to that address. Must be either the owner or globally approved operator.
required: true
--chain-id
string
The name of the network.
required: true
--fees
string
Тhe specified fee for the operation
required: false
Example:
$ cudos-noded tx nft revoke <addressToRevoke> <denom-id> <token-id>--uri=<uri> --from=<key-name> --chain-id=<chain-id> --fees=<fee>
# approveAll
Adds the address to the approved operator list for the user. Approved addresses on the user level can transfer the NFT from one owner to another. The address is automatically added to the msg.sender(--from) approved list.
- arguments:
operator
string
The address that will be approved
required: true
approved
string
Boolean value indicating if the addres is approved: can be true or false
required: true
- flags:
--from
string
The address that is requesting the approval. The approved address will be able to handle the transfers of --from assets. Can be either an address or alias to that address. must be either the owner or globally approved operator.
required: true
--chain-id
string
The name of the network.
required: true
--fees
string
The specified fee for the operation
required: false
Example:
$ cudos-noded tx nft approveAll <operator> <true/false> --from=<key-name> --chain-id=<chain-id> --fees=<fee>
# Query commands
# denom
Query the denom by the specified denom id.
- arguments:
denom-id
string
The denomId to search for
required: true
- flags:
- none
Example:
$ cudos-noded query nft denom <denomId>
# denom-by-name
Query the denom by the specified denom name.
- arguments:
denom-name
string
The denom name to search for
required: true
- flags:
- none
Example:
$ cudos-noded query nft denom <denomName>
# denoms
Query all denominations of all collections of NFTs.
- arguments:
- none
- flags:
- none
Example:
$ cudos-noded query nft denoms
# collection
Query all denominations of all collections of NFTs.
- arguments:
denom-id
:The id of the denomination collection.
required:true
- flags:
- none
Example:
$ cudos-noded query nft collection <denom-id>
# supply
Gets the total supply of a collection or owner of NFTs.
- arguments:
denom-id
:The id of the denomination collection.
required:true
- flags:
- none
Example:
$ cudos-noded query nft supply <denom-id>
# owner
Get the NFTs owned by an account address.
- arguments:
address
:The address of the owner.
required:true
- flags:
--denom-id
:The id of the denom
required:true
Example:
$ cudos-noded query nft owner <address> --denom-id=<denom-id>
# token
Query a single NFT from a collection.
- arguments:
denom-id
:The id of the denom collection
required:true
token-id
:The id of the NFT
required:true
- flags:
- none
Example:
$ cudos-noded query nft token <denom-id> <token-id>
# approvals
Get the approved addresses for the NFT.
- arguments:
denom-id
:The id of the denom collection
required:true
token-id
:The id of the NFT
required:true
- flags:
- none
Example:
$ cudos-noded query nft approvals <denomId> <tokenId>
# isApprovedForAll
Query if an address is an authorised operator for another address.
- arguments:
owner
:The owner addresses to search
required:true
operator
:The operator address to be searched for
required:true
- flags:
- none
Example:
$ cudos-noded query nft approvals <owner> <operator>
# Object types
# NFT
// NFT non fungible token interface
type NFT interface {
GetID() string // unique identifier of the NFT
GetName() string // return the name of BaseNFT
GetOwner() sdk.AccAddress // gets owner account of the NFT
GetURI() string // tokenData field: URI to retrieve the of chain tokenData of the NFT
GetData() string // return the Data of BaseNFT
GetApprovedAddresses() map[string]bool// returns the approved addresses of BaseNFT
}
# NFT implementation
type BaseNFT struct {
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
URI string `protobuf:"bytes,3,opt,name=uri,proto3" json:"uri,omitempty"`
Data string `protobuf:"bytes,4,opt,name=data,proto3" json:"data,omitempty"`
Owner string `protobuf:"bytes,5,opt,name=owner,proto3" json:"owner,omitempty"`
ApprovedAddresses map[string]bool `protobuf:"bytes,6,rep,name=approvedAddresses,proto3" json:"approvedAddresses,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
}
# Collections
As all NFTs belong to a specific
Collection
under{denomID}/{tokenID}
// Collection of non fungible tokens
type Collection struct {
Denom Denom `json:"denom"` // Denom of the collection; not exported to clients
NFTs []BaseNFT `json:"nfts"` // NFTs that belongs to a collection
}
# Owners
Owner holds the address of the user and their collection of NFTs.
// Owner of non fungible tokens
type Owner struct {
Address string `json:"address"`
IDCollections []IDCollection `json:"id_collections"`
}
# IDCollection
IDCollection holds the denomId and the Ids of the NFTs (instead of the full object).
// IDCollection of non fungible tokens
type IDCollection struct {
DenomId string `json:"denom_id"`
TokenIds []string `json:"token_ids"`
}
# Denom
The denomination is used to group NFTs under it.
// Denom defines a type of NFT
type Denom struct {
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
Schema string `protobuf:"bytes,3,opt,name=schema,proto3" json:"schema,omitempty"`
Creator string `protobuf:"bytes,4,opt,name=creator,proto3" json:"creator,omitempty"`
}
# Events
The events that are emitted after certain operations.
EventTypeIssueDenom = "issue_denom"
EventTypeTransferNft = "transfer_nft"
EventTypeApproveNft = "approve_nft"
EventTypeApproveAllNft = "approve_all_nft"
EventTypeRevokeNft = "revoke_nft"
EventTypeEditNFT = "edit_nft"
EventTypeMintNFT = "mint_nft"
EventTypeBurnNFT = "burn_nft"