Create Non-Fungible Token with Golang
This document gives instructions and examples on how to use our pkg/client
package to create and
manage non-fungible token.
Complete code
Complete code with go.mod
file you can find
here
P.S. If you have issues with go mod tidy
command, just copy go.mod
file from the example above.
Creating NFT class
First we create class which is a container for a set of NFTs having the same purpose:
senderAddress, err := senderInfo.GetAddress()
if err != nil {
panic(err)
}
const classSymbol = "NFTClass"
msgIssueClass := &assetnfttypes.MsgIssueClass{
Issuer: senderAddress.String(),
Symbol: classSymbol,
Name: "NFT Class",
Description: "NFT Class",
Features: []assetnfttypes.ClassFeature{assetnfttypes.ClassFeature_freezing},
}
ctx := context.Background()
_, err = client.BroadcastTx(
ctx,
clientCtx.WithFromAddress(senderAddress),
txFactory,
msgIssueClass,
)
if err != nil {
panic(err)
}
Minting NFT
Then we mint new NFT for that class:
classID := assetnfttypes.BuildClassID(classSymbol, senderAddress)
const nftID = "myNFT"
msgMint := &assetnfttypes.MsgMint{
Sender: senderAddress.String(),
ClassID: classID,
ID: nftID,
}
_, err = client.BroadcastTx(
ctx,
clientCtx.WithFromAddress(senderAddress),
txFactory,
msgMint,
)
if err != nil {
panic(err)
}
Querying the owner
We query the owner of the NFT to verify that it is owned by the creator:
nftClient := nft.NewQueryClient(clientCtx)
resp, err := nftClient.Owner(ctx, &nft.QueryOwnerRequest{
ClassId: classID,
Id: nftID,
})
if err != nil {
panic(err)
}
fmt.Printf("Owner: %s\n", resp.Owner)
Sending NFT
Now we send NFT to someone else:
recipientInfo, _, err := clientCtx.Keyring().NewMnemonic(
"recipient",
keyring.English,
sdk.GetConfig().GetFullBIP44Path(),
"",
hd.Secp256k1,
)
if err != nil {
panic(err)
}
recipientAddress, err := recipientInfo.GetAddress()
if err != nil {
panic(err)
}
msgSend := &nft.MsgSend{
Sender: senderAddress.String(),
Receiver: recipientAddress.String(),
Id: nftID,
ClassId: classID,
}
_, err = client.BroadcastTx(
ctx,
clientCtx.WithFromAddress(senderAddress),
txFactory,
msgSend,
)
if err != nil {
panic(err)
}
Let's verify that recipient is the owner now:
resp, err = nftClient.Owner(ctx, &nft.QueryOwnerRequest{
ClassId: classID,
Id: nftID,
})
if err != nil {
panic(err)
}
fmt.Printf("Owner: %s\n", resp.Owner)
Freezing
Because issuer enabled freezing
feature during class issuance, he/she might freeze the NFT:
msgFreeze := &assetnfttypes.MsgFreeze{
Sender: senderAddress.String(),
ClassID: classID,
ID: nftID,
}
_, err = client.BroadcastTx(
ctx,
clientCtx.WithFromAddress(senderAddress),
txFactory,
msgFreeze,
)
if err != nil {
panic(err)
}
Update Data
update the data of the specified NFT with the information provided in the data file
dataDynamic := assetnfttypes.DataDynamic{
Items: []assetnfttypes.DataDynamicItem{
{
Editors: []assetnfttypes.DataEditor{
assetnfttypes.DataEditor_owner,
},
Data: jsonData,
},
},
}
data, err = codectypes.NewAnyWithValue(&dataDynamic)
if err != nil {
panic(err)
}
// Broadcast transaction minting new dynamic nft
classID = assetnfttypes.BuildClassID(classSymbol, senderAddress)
const dynamicNftID = "myDynamicNFT"
msgMint = &assetnfttypes.MsgMint{
Sender: senderAddress.String(),
ClassID: classID,
ID: dynamicNftID,
Data: data,
}
_, err = client.BroadcastTx(
ctx,
clientCtx.WithFromAddress(senderAddress),
txFactory,
msgMint,
)
if err != nil {
panic(err)
}
// Query the nft
storedNFT, err := nftClient.NFT(ctx, &nft.QueryNFTRequest{
ClassId: classID,
Id: dynamicNftID,
})
if err != nil {
panic(err)
}
var storedDataDynamic assetnfttypes.DataDynamic
err = storedDataDynamic.Unmarshal(storedNFT.Nft.Data.Value)
if err != nil {
panic(err)
}
fmt.Printf("Data: %s\n", string(storedDataDynamic.Items[0].Data))
// update stored NFT
msgUpdateData := &assetnfttypes.MsgUpdateData{
Sender: senderAddress.String(),
ClassID: classID,
ID: dynamicNftID,
Items: []assetnfttypes.DataDynamicIndexedItem{
{
Index: 0,
Data: []byte(`{"name": "Updated Name", "description": "Updated Description"}`),
},
},
}
_, err = client.BroadcastTx(
ctx,
clientCtx.WithFromAddress(senderAddress),
txFactory,
msgUpdateData,
)
if err != nil {
panic(err)
}
storedNFT, err = nftClient.NFT(ctx, &nft.QueryNFTRequest{
ClassId: classID,
Id: dynamicNftID,
})
if err != nil {
panic(err)
}
var storedDataDynamic2 assetnfttypes.DataDynamic
err = storedDataDynamic2.Unmarshal(storedNFT.Nft.Data.Value)
if err != nil {
panic(err)
}
fmt.Printf("Data: %s\n", string(storedDataDynamic2.Items[0].Data))
After doing this, recipient is not allowed to transfer the NFT from its account.
All the other features may be used in a similar fashion. More info is available in the documentation