Solana NFT: Why Modifications Are Needed
As a developer on Solana, interacting with compressed NFTs can seem like an uphill battle. This no longer needs to be the case with the ability for modifications, or changes to compressed NFTs through the Bubblegum program.
When a compressed NFT is minted, Merkle proofs must be provided with the transaction instruction to make any changes to that NFT (e.g., transfer, burn). For those unfamiliar, a Merkle proof is a set of hashes that can prove the leaf belongs to the tree.
In this walkthrough, we will cover:
- The importance of modifications with compressed NFTs.
- Setting up burn and transfer modifications to compressed NFTs.
- Detailing the importance of the Digital Asset Standard (DAS) API.
Solana NFT: Prerequisites
Before diving in, ensure you have:
- A fundamental grasp of JavaScript/TypeScript.
- Some familiarity with compressed NFTs.
- Git installed.
- npm or yarn.
- A clone of the example repository, available here.
Solana NFT: Environment Setup
- Clone our example repository:
Block Field
- Navigate into the project folder:
Block Field
- Install npm:
Block Field
- Create an .env file at the root:
Block Field
In this, input your FluxRPC API key, and the payer wallet secret key. Make sure this wallet has Solana in it to fund the transactions.
Solana NFT: Modifications
Modifications require obtaining the current proofs for the instruction, alongside the asset’s current ownership, authority, and compression hashes. You need to fetch this data from the Digital Asset Standard (DAS) API, which streamlines interactions with compressed assets.
The current list of modifications available through Bubblegum are:
- Mint
- Transfer
- Burn
- Delegate, CancelDelegate
- Redeem, CancelRedeem
- Decompress
- VerifyCreator, SetAndVerifyCreator
- VerifyCollection, SetAndVerifyCollection
To interact with compressed assets, you need to ensure you return:
- getAssetProof - Fetches the proof for computation.
- getAsset - Retrieves the creator hash, data hash, leaf nonce, and the current owner/leaf delegate.
- getBubblegumAuthorityPDA - A program derived address from the tree ID.
In these examples, we will go over the burning and transferring of compressed NFTs we will mint.
NFT: Transfer
The transfer modification lets you move a compressed NFT from one owner’s wallet to another. Both compressed NFT sales and listings use this instruction to display sales on marketplaces.
To set this up in our existing repository, we will go to our utils.ts file and take a look at our transferAsset function.
We will need to pass in the following:
- Connection - A Solana RPC connection.
- Current owner - The public key of the current NFT owner.
- New owner for the NFT - The public key for the new owner.
- Asset ID - Allows us to get current details on the specific asset you pass in.
We can see below in our example transferAsset function that we are initially requesting the asset proof and setting up something called a proofPath. This is a request made on the DAS API that returns the proof for the asset you are wanting to transfer and you are computing it to pass into the transaction instruction.
Block Field
Returning the asset proof is needed as you need to return the current state of the compressed asset, this is required for every transfer of a compressed NFT. You are computing this in the proofPath for it to be passed into our transaction instruction that we will see shortly.
Now that we have our proof path, we can use getAsset on the DAS API to return our leaf nonce, leaf delegate, data hash, and creator hash.
We can set that up below:
Block Field
You can see that the getAsset request is being made to return the owner/delegate and leaf nonce. We are also defining our tree authority just by using the tree ID (that we returned from our assetProof request).
Now that we have these defined, we can start building our transaction instruction.
Block Field
To do this for a transferred asset, you will need to pass in all of our variables that we returned from the getAsset, getAssetProof, and the Metaplex SDK: leaf delegate/owner, data hash, root, and leaf nonce.
You will also notice we are passing in a few program IDs. These are the public keys for the compression and noop programs that are imported at the top of the file. You can alternatively pass these in as a public key.
Now that this is in place, we can set up sending our transaction instruction:
Block Field
In the above code, we are defining our transaction by using tx and adding a Transaction type for our transferIx from solana/web3.js .
We are then submitting it by passing in our:
- Solana connection
- Transaction Instructions
- Payer
- Commitment
We can now submit this transaction by running:
Block Field
This function will mint a compressed NFT and its collection, then transfers it to a wallet specified.
Here is the entire transferAsset function:
Block Field
NFT: Burn
Burning cNFTs purges the NFT from the Merkle tree. This allows for diverse use cases, like burning for rewards, removing spam assets, or addressing custom requirements. This was used in the Tensor mint where 10 cNFTs were burned for new 1 cNFT to be minted.
To burn a compressed NFT, we will need to pass in the following:
- Connection - A Solana RPC connection.
- Current owner - The public key of the current NFT owner.
- Asset ID - Allows us to get current details on the specific asset you pass in.
We can see this in our utils.ts under burnAsset:
Block Field
This is the same as transferAsset as it is using getAssetProof to return the root and tree ID. You are also calling getAsset to return the creator hash, data hash, leaf nonce, and current owner.
This makes it easy to know what values you need returned here to modify your compressed asset.
Now, we can set up our transaction instruction below this code:
Block Field
Now that we have this set up to burn, we can submit our transaction in a very similar method to the transfer instruction:
Block Field
We are then submitting it by passing in our:
- Solana connection
- Transaction Instructions
- Payer
- Commitment
Once this function is run, it will burn the asset for the ID you provided. This will remove the asset data from the tree and apply a burnt=true flag on the compressed asset. By default, these burned assets will return when you use the DAS API.
In your terminal, you can now run:
Block Field
Solana NFTs: Conclusion
Compressed NFTs provide a dynamic means of engaging with the NFT ecosystem on Solana. Through Merkle proofs obtained through the DAS API and precise transaction instructions, developers can modify and interact with these unique digital assets. By understanding the nuances of the transfer and burn modifications, developers are empowered to build more reliable applications.