Skip to main content

Working with CW721 Data

How can players use the NFTs they own in the game? You can use the LCDClient to send a Query and retrieve NFT data. Let's fetch the NFT information you created in the previous steps. The CW721 contract address used in the example is xpla1wx3rm4qxf7l3tczj20mxz62wpnr74kme3f45tvk3muh78c432ucs2ceuqn.

Preview

Here's the code to get NFT data using JavaScript. Just change the contract address you created to your CW721 contract address on line 9, and put your wallet address that holds the NFT on line 10. Wait a bit, and you'll see the execution result on the right side.

const { LCDClient } = require("@xpla/xpla.js");

const lcd = new LCDClient({
  chainID: 'cube_47-5',
  URL: 'https://cube-lcd.xpla.dev'
});

async function main() {
    const contractAddress = "xpla1wx3rm4qxf7l3tczj20mxz62wpnr74kme3f45tvk3muh78c432ucs2ceuqn";
    const userAddress = "xpla1cwduqw0z8y66mnfpev2mvrzzzu98tuexepmwrk";

    const userNFTsMsg = {
        tokens : {
            owner : userAddress
        }
    };
    const userNFTs = await lcd.wasm.contractQuery(contractAddress, userNFTsMsg);
    console.log(userNFTs);

    const tokenIds = userNFTs.tokens;
    for (const tokenId of tokenIds) {
        const nftInfoMsg = {
            nft_info : {
                token_id : tokenId
            }
        }
        const nftInfo = await lcd.wasm.contractQuery(contractAddress, nftInfoMsg);
        console.log(JSON.stringify(nftInfo, null, 2));
    }
}
main()

By using the LCDClient, we could send a query to find out which NFTs are owned by a specific wallet address. Additionally, we could also fetch NFT information using the token_id of the NFT. This allows you to use the NFT information owned by users in your game.

You can also send queries to the contract using the XPLA Explorer. Let's search for the CW20 token contract address on the XPLA Explorer and take a look at the Init Msg tab.

https://explorer.xpla.io/testnet/address/xpla1xljvdrtyn86kv7hrdhae4qxdy8krajah3w7xhtyrt0n69und9xdqdhrasc#InitMsg
vaultimgcard

Afterward, if you click the Query button on the right, a pop-up will appear for you to write a Query message. This makes it easy for you to send a Query to the contract.

https://explorer.xpla.io/testnet/address/xpla1xljvdrtyn86kv7hrdhae4qxdy8krajah3w7xhtyrt0n69und9xdqdhrasc#InitMsg
vaultimgcard

When sending a query from XPLA Explorer, write it in JSON format.

The important thing to note is that, unlike writing messages in JavaScript code, you need to write it in JSON format as shown below.

{
"tokens" : {
"owner" : "xpla1cwduqw0z8y66mnfpev2mvrzzzu98tuexepmwrk"
}
}
How should I format the contract query message?

You can explore what queries you can send to the CW721 contract on the CW721 GitHub. The thing to be careful about is that while the message names are written in Camel Case in QueryMsg, you need to send them in Snake Case when actually sending the query. You input the parameters exactly as they are in the code.

For example, let's take a look at the NftInfo message on line 126 in the CW721 GitHub.

pub enum QueryMsg<Q: JsonSchema> {
...
/// With MetaData Extension.
/// Returns metadata about one particular token, based on *ERC721 Metadata JSON Schema*
/// but directly from the contract
#[returns(cw721::NftInfoResponse<Q>)]
NftInfo { token_id: String },

When sending an NftInfo query, you need to change the Camel Case NftInfo to Snake Case, so you'll input it as nft_info. The parameter section is { token_id: String }, so you just need to enter the token_id value of the NFT you want to know about as a String type. As a result, the final query message would look like this.

{
nft_info : {
token_id : "token_id_myExampleNFT1"
}
}

Use this as a reference to send various queries to your contract.


We've looked into how to send queries to the contract and how to write query messages. Now, let's analyze the Preview Code. If you've understood the Preview Code, you can skip reading the following and proceed to the next step.

Fetching NFT Date with Javascript

Let's use JavaScript code to find out what NFTs a specific wallet address owns and even fetch the information for each of those NFTs.

Running the Code

  1. Please create a file named "example-query-cw721.js".

  2. Copy and paste the code below into the "example-query-cw721.js" file and save it.

    const { LCDClient } = require("@xpla/xpla.js");

    const lcd = new LCDClient({
    chainID: 'cube_47-5',
    URL: 'https://cube-lcd.xpla.dev'
    });

    async function main() {
    const contractAddress = "xpla1wx3rm4qxf7l3tczj20mxz62wpnr74kme3f45tvk3muh78c432ucs2ceuqn";
    const userAddress = "xpla1cwduqw0z8y66mnfpev2mvrzzzu98tuexepmwrk";

    const userNFTsMsg = {
    tokens : {
    owner : userAddress
    }
    };
    const userNFTs = await lcd.wasm.contractQuery(contractAddress, userNFTsMsg);
    console.log(userNFTs);

    const tokenIds = userNFTs.tokens;
    for (const tokenId of tokenIds) {
    const nftInfoMsg = {
    nft_info : {
    token_id : tokenId
    }
    }
    const nftInfo = await lcd.wasm.contractQuery(contractAddress, nftInfoMsg);
    console.log(JSON.stringify(nftInfo, null, 2));
    }
    }
    main()
  3. On line 9, replace the CW721 contract address you created, and on line 10, replace it with the wallet address that holds the NFT.

  4. Enter the following command in the VSCode Terminal.

    node example-query-cw721.js
  5. Check the results in the Terminal. The first Log value will display the NFT information owned by a specific wallet, and the second Log value will show that you were able to retrieve information about a specific NFT.

Explanation

To figure out which NFTs a specific wallet owns, we prepared a Query message in the userNFTsMsg variable as follows. We followed the Query message format from the CW721 GitHub as a reference.

const userNFTsMsg = {
tokens : {
owner : userAddress
}
};
How should I format the contract query message?

You can explore what queries you can send to the CW721 contract on the CW721 GitHub. The thing to be careful about is that while the message names are written in Camel Case in QueryMsg, you need to send them in Snake Case when actually sending the query. You input the parameters exactly as they are in the code.

For example, let's take a look at the NftInfo message on line 126 in the CW721 GitHub.

pub enum QueryMsg<Q: JsonSchema> {
...
/// With MetaData Extension.
/// Returns metadata about one particular token, based on *ERC721 Metadata JSON Schema*
/// but directly from the contract
#[returns(cw721::NftInfoResponse<Q>)]
NftInfo { token_id: String },

When sending an NftInfo query, you need to change the Camel Case NftInfo to Snake Case, so you'll input it as nft_info. The parameter section is { token_id: String }, so you just need to enter the token_id value of the NFT you want to know about as a String type. As a result, the final query message would look like this.

{
nft_info : {
token_id : "token_id_myExampleNFT1"
}
}

Use this as a reference to send various queries to your contract.


Using the contractQuery function of LCDClient, we send a query to the contract. Depending on the query message we provide, we can receive data from the contract.

const userNFTs = await lcd.wasm.contractQuery(contractAddress, userNFTsMsg);
console.log(userNFTs);

The userNFTs.tokens variable contains an array of token_id values for the NFTs owned by the user. We've taken each NFT's token_id value and included it in the nftInfoMsg variable to create the query message as follows:

const tokenIds = userNFTs.tokens;
for (const tokenId of tokenIds) {
const nftInfoMsg = {
nft_info : {
token_id : tokenId
}
}
...

Similarly, we send a query to the contract using the contractQuery function of LCDClient. Just like before, we can receive data from the contract based on the query message we input.

const nftInfo = await lcd.wasm.contractQuery(contractAddress, nftInfoMsg);
console.log(JSON.stringify(nftInfo, null, 2));

Wrapping Up

So far, we've looked at the process of sending queries to the CW721 contract. By referring to the CW721 GitHub, you can explore in more detail the types of queries that can be sent to the CW721 contract. Let's fetch CW721 data from the contract tailored to your game and make it more enjoyable for users to play.