Solana has recently introduced state compression and compressed NFTs that would reduce the cost of minting and development. Compressed NFTs on the Solana blockchain are a new type of NFT that use a compressed format to reduce their file size and gas costs. In this article, we will dive into the exciting world of compressed NFTs on Solana and explore the easiest way to mint, transfer, burn and view compressed NFTs on Solana with the help of [SHYFT APIs](https://docs.shyft.to/). Read more about [compressed NFTs](https://docs.shyft.to/start-hacking/nft/compressed-nft). ## Before getting started To get started, we will need a few things. Register your Shyft account and get your own Shyft API key `x-api-key` is an authentication parameter, which gives you access to Shyft APIs. You can get your own API Key from the Shyft website. Just signup with your email id here and you can get it for free. If you already have an Shyft API Key, please skip this step. Node.js or any server environment that supports API calls We have used Node.js for this article, but these can be bootstrapped using any server environment that supports API calls, or even with frontend React, Next.js or Vanilla JS Applications. This will be the result when we complete this tutorial. [INSERT VIDEO] ## Creating a Merkle Tree To mint a compressed NFT, we must begin by creating a Merkle tree. A merkle tree, sometimes called a "hash tree", is a hash based binary tree structure where each leaf node is represented as a cryptographic hash of its inner data. And every node that is not a leaf, called a branch, is represented as a hash of its child leaf hashes. Read more about Merkle trees and how to use them to create compressed NFTs [here](https://docs.solana.com/learn/state-compression). The Shyft API enables us to construct a Merkle tree by providing the following parameters: - `network`: specifies the Solana Blockchain environment, which can be devnet, testnet and mainnet-beta. - `wallet_address`: specifies the tree authority and the payer of the transaction (if not stated explicitly by the `fee_payer` field) - `max_depth_size_pair`: This is a JSON object which further specifies two fields - `max_depth` (the maximum depth of the Merkle tree) and `max_buffer_size` (maximum number of changes that can be made while still maintaining the validity of the root hash) - `canopy_depth`: specifies the number of proof nodes that are stored or cached on-chain for a specific proof path. - `fee_payer`(optional) : If specified, this account will pay the transaction gas fee, instead of the tree authority `wallet_address` For a comprehensive list of parameters supported by Shyft and to learn more about Merkle trees, please refer to our detailed documentation available here. ```javascript= const axios = require('axios'); // or whatever http client you like const YOUR_WALLET_ADDRESS = 'CDXLgstdVZJ7qUh3DC1mAGuCmTM3UiS1M24m44t3UViS'; const network = 'devnet' // // can be devnet or testnet as well async function createMerkleTree() { const response = await axios.post("https://api.shyft.to/sol/v1/nft/compressed/create_tree", /* Shyft create merkle API endpoint */ { network, wallet_address: YOUR_WALLET_ADDRESS, max_depth_size_pair: { max_depth: 14, max_buffer_size: 64 }, canopy_depth: 11 }, { headers: { "x-api-key": process.env.SHYFT_API_KEY // replace with your own key. Get free one from shyft.to } }); console.dir(response.data, { depth: null }) } createMerkleTree(); ``` The result ```json { success: true, message: 'Merkle tree creation transaction generated successfully', result: { encoded_transaction: 'AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsx5Al/LnmuaRE433spcsmZcBiWnfSnBYNz0XXgrAxKUAj30+m3zBbXrxR4ZWjSof2Ck3CU6Vdt4mjPXY2dXQNAgAEB6al1LAvaVtZ9aKL54myXpqjNU53HBAS2YEy3SlvVZTLPh5N+X7diQ52sBIWBKtWS/znHqffM2wMhy+tAYj1EITXm2AFc2QcnkEoEzz5uEvm1TH7foYK1VC/hULHAg3mnwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmIuA63k1KGmyJHRfWd2/iiZYyhPcaIEhJjUcrgfBpaUJKhPulcQcugimf1rGfo334doRYl4dZBN/j08jgwN/FAu8D8C7R8ovdMQRLpSrE8+jxjTl3BfqywPNGiPNfnh81aTOYisSwHg9gPTVmFDNMxFqmMT9bnYfi1pLN93ZzZYCAwIAATQAAAAAgP6XQwAAAAD4ewIAAAAAAAkqE+6VxBy6CKZ/WsZ+jffh2hFiXh1kE3+PTyODA38UBAcCAQAABgUDEqVTiI5Zyi/cDgAAAEAAAAABAA==', tree: '5BV5a4Px8Ghtxmdw2we2SYn7r3t6EUPwCH7hL6bw6wN3', signers: [ 'CDXLgstdVZJ7qUh3DC1mAGuCmTM3UiS1M24m44t3UViS' ] } } ``` [Transaction signature](https://translator.shyft.to/tx/5A8fD73z15vf7gWxZhCbnfH4t81tscsH2GqHvBgpXxxSAKwv2rJSfEEvgRiXWtrapJQDbpNVqmQNCJm3CiekikqX?cluster=devnet) Once successfully executed, the response returned will have an `encoded_transaction` which will require a signature from the `wallet_address` and `fee_payer` (if specified), on completion of which a new Merkle tree will be created. We have deployed a small project to test out transaction signing while working with Shyft APIs. Try it out here: https://shyft-insider.vercel.app/ For more information about signing transactions on Solana, please refer to our detailed documentation available [here](https://docs.shyft.to/tutorials/how-to-sign-transactions-on-solana). The response also includes the `tree` field, which represents the address of the created tree. It is essential to remember this address as we will need it when creating the compressed NFT. ## Minting Compressed NFTs Once the Merkle tree has been created, we can proceed to mint a compressed NFT by utilizing Shyft's compressed NFT minting endpoint and providing the following parameters: - `network`: Solana blockchain environment (devnet/mainnet-beta) - `creator_wallet`: The creator/payer of the NFT. - `merkle_tree`: Merkle tree address which we've created. - `metadata_uri`: URI that contains metadata of the NFT (metaplex non-fungible-standard) in JSON file format. For an extensive list of parameters supported by Shyft, please consult our detailed documentation, which is available here. This documentation will guide you through the entire process of minting a compressed NFT using Shyft's platform. ```javascript= async function mintCompressedNFT() { const response = await axios.post("https://api.shyft.to/sol/v1/nft/compressed/mint", /* Shyft mint compressed NFT API endpoint */ { network, creator_wallet: YOUR_WALLET_ADDRESS, metadata_uri: "https://gateway.pinata.cloud/ipfs/QmYmUb5MHZwYovnQg9qANTJUi7R8VaE5CetfssczaSWn5K", merkle_tree: "5BV5a4Px8Ghtxmdw2we2SYn7r3t6EUPwCH7hL6bw6wN3", }, { headers: { "x-api-key": process.env.SHYFT_API_KEY // replace with your own key. Get free one from shyft.to } }); console.dir(response.data, { depth: null }) } mintCompressedNFT(); ``` The result ```json { success: true, message: 'NFT mint transaction generated successfully', result: { encoded_transaction: 'AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAQHpqXUsC9pW1n1oovnibJemqM1TnccEBLZgTLdKW9VlMs+Hk35ft2JDnawEhYEq1ZL/Ocep98zbAyHL60BiPUQhNebYAVzZByeQSgTPPm4S+bVMft+hgrVUL+FQscCDeafAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACYi4DreTUoabIkdF9Z3b+KJljKE9xogSEmNRyuB8GlpQkqE+6VxBy6CKZ/WsZ+jffh2hFiXh1kE3+PTyODA38UC7wPwLtHyi90xBEulKsTz6PGNOXcF+rLA80aI81+eHwVO0xxQnKazXvT1FSHZ2UVHJp+5nNVniVdtN9wli7OAQEECQIAAAEAAAYFA48BkWLAdriTdmgOAAAATWFkIExhZHMgIzk5NjQDAAAATUFEOQAAAGh0dHBzOi8vbWFkbGFkcy5zMy51cy13ZXN0LTIuYW1hem9uYXdzLmNvbS9qc29uLzk5NjQuanNvbvQBAAEBAAEAAAAAAQAAABU7mQjzfDvicKRwHJ/PJDL9WraVCB9vMEw3M+t9B0dpAGQ=', mint: 'GSmMYNTohnQEtq26i76DqLK9rEL2gcG8FBjRi7p6tGcr', signers: [ 'CDXLgstdVZJ7qUh3DC1mAGuCmTM3UiS1M24m44t3UViS' ] } } ``` [Transaction signature](https://translator.shyft.to/tx/QfgVDvwkh8MgEpT5MuC51h9Q4FYb3ZXTVosYFAc5k1g23sqHybTHLdDHWecHh8dfH2psPxMB25mnQJaj2rC4ufH?cluster=devnet) After a successful execution, the response will include an `encoded_transaction` requiring signatures from both the `creator_wallet` and, if specified, the `fee_payer`. Once these signatures are obtained and the transaction is completed, a new compressed NFT will be created. The response also includes the `mint` field, which represents the address of the created compressed NFT. ## View all Compressed NFTs in your wallet To display all compressed NFTs on your wallet, Shyft offers an API that allows you to retrieve both on-chain and off-chain data of these NFTs. ```javascript= const YOUR_WALLET_ADDRESS = 'CDXLgstdVZJ7qUh3DC1mAGuCmTM3UiS1M24m44t3UViS'; const network = 'devnet' // can be devnet or testnet as well async function fetchCNFTsByOwnerAddress() { const response = await axios.get(`https://api.shyft.to/sol/v1/nft/compressed/read_all?network=${network}&wallet_address=${YOUR_WALLET_ADDRESS}`, /* Shyft real all compressed NFTs by owner address API endpoint */{ headers: { "x-api-key": process.env.SHYFT_API_KEY // replace with your own key. Get free one from shyft.to } }); console.dir(response.data, { depth: null }) } fetchCNFTsByOwnerAddress(); ``` The result ```json { success: true, message: 'All compressed NFTs present in the wallet: CDXLgstdVZJ7qUh3DC1mAGuCmTM3UiS1M24m44t3UViS', result: { nfts: [ { name: 'Mad Lads #9964', symbol: 'MAD', royalty: 5, image_uri: 'https://madlads.s3.us-west-2.amazonaws.com/images/9964.png', cached_image_uri: 'https://madlads.s3.us-west-2.amazonaws.com/images/9964.png', animation_url: '', cached_animation_url: '', metadata_uri: 'https://madlads.s3.us-west-2.amazonaws.com/json/9964.json', description: 'Fock it.', mint: 'GSmMYNTohnQEtq26i76DqLK9rEL2gcG8FBjRi7p6tGcr', owner: 'CDXLgstdVZJ7qUh3DC1mAGuCmTM3UiS1M24m44t3UViS', update_authority: 'FWe52u7crZ3UVQsBf18k8VMZmRoZ85zWduzagVJBQPUJ', creators: [ { address: '2RtGg6fsFiiF1EQzHqbd66AhW7R5bWeQGpTbv2UMkCdW', share: 100, verified: false } ], collection: {}, attributes: { Gender: 'Male', Type: 'Dark', Expression: 'Joy', Hat: 'Homburg', Eyes: 'Closed', Clothing: 'Metal', Background: 'Red' }, attributes_array: [ { trait_type: 'Gender', value: 'Male' }, { trait_type: 'Type', value: 'Dark' }, { trait_type: 'Expression', value: 'Joy' }, { trait_type: 'Hat', value: 'Homburg' }, { trait_type: 'Eyes', value: 'Closed' }, { trait_type: 'Clothing', value: 'Metal' }, { trait_type: 'Background', value: 'Red' } ], files: [ { id: 'portrait', uri: 'https://madlads.s3.us-west-2.amazonaws.com/images/9964.png', type: 'image/png' }, { id: 'rug', uri: 'https://arweave.net/qJ5B6fx5hEt4P7XbicbJQRyTcbyLaV-OQNA1KjzdqOQ/9964.png', type: 'image/png' } ], external_url: 'https://madlads.com', primary_sale_happened: false, is_mutable: true, token_standard: 'NonFungible', is_loaded_metadata: true }, { name: 'LILY #9998', symbol: 'LILY', royalty: 5, image_uri: 'https://bafybeidtb66eyfb6x4xacobyogrlefguwt2c6dljri4iwjfkjoy757abmm.ipfs.nftstorage.link/1262.png?ext=png', cached_image_uri: 'https://bafybeidtb66eyfb6x4xacobyogrlefguwt2c6dljri4iwjfkjoy757abmm.ipfs.nftstorage.link/1262.png?ext=png', animation_url: '', cached_animation_url: '', metadata_uri: 'https://gya6zihhbchxtliqqxwdmqq4g4zjs7smvjdj2i2pg642iw7zyrlq.arweave.net/NgHsoOcIj3mtEIXsNkIcNzKZfkyqRp0jTze5pFv5xFc?ext=json', description: 'LILY is a generative art project made up of 10,000 digital collectibles. Holding one grants you access to our community of optimalists.', mint: '38oc3MGNwvywoNG1jXkMmeNXGbei6r4AoEESrpvQAtyP', owner: 'CDXLgstdVZJ7qUh3DC1mAGuCmTM3UiS1M24m44t3UViS', update_authority: 'A7uejueApYhoxtmeVzxVVtFnfwoxFrMucM94kwjQv639', creators: [ { address: '3NoPerEGS1JpPA6FGYpPfKJ8QUkBjYPngST2pwpQt7ED', share: 100, verified: false } ], collection: { name: 'LILY', family: 'LILY' }, attributes: { Background: 'One', Hands: 'Wrapped Fist', Origin: 'Andro', Eyes: 'Cheerful', Mouth: 'Toothpick', Clothing: 'Petal Armour', Accessories: 'None', Eyewear: 'None', Hair: 'Swept', Headgear: 'None', Aura: 'None' }, attributes_array: [ { trait_type: 'Background', value: 'One' }, { trait_type: 'Hands', value: 'Wrapped Fist' }, { trait_type: 'Origin', value: 'Andro' }, { trait_type: 'Eyes', value: 'Cheerful' }, { trait_type: 'Mouth', value: 'Toothpick' }, { trait_type: 'Clothing', value: 'Petal Armour' }, { trait_type: 'Accessories', value: 'None' }, { trait_type: 'Eyewear', value: 'None' }, { trait_type: 'Hair', value: 'Swept' }, { trait_type: 'Headgear', value: 'None' }, { trait_type: 'Aura', value: 'None' } ], files: [ { uri: 'https://bafybeidtb66eyfb6x4xacobyogrlefguwt2c6dljri4iwjfkjoy757abmm.ipfs.nftstorage.link/1262.png?ext=png', type: 'image/png' } ], external_url: 'https://www.thelotus.io/', primary_sale_happened: false, is_mutable: true, token_standard: 'NonFungible', is_loaded_metadata: true } ] } } ``` Upon making a request using the provided API, the response will contain a comprehensive list of NFTs. This list includes all relevant information about each compressed NFT associated with your wallet. ## Transfer Compressed NFTs If you wish to transfer your compressed NFT to a friend, Shyft offers an API that facilitates this process. Below is an example code snippet demonstrating how to perform the NFT transfer: ```javascript= const YOUR_WALLET_ADDRESS = 'CDXLgstdVZJ7qUh3DC1mAGuCmTM3UiS1M24m44t3UViS'; const network = 'devnet' // can be devnet or testnet as well async function transferCNFT() { const response = await axios.post("https://api.shyft.to/sol/v1/nft/compressed/transfer", /* Shyft transfer compressed NFT API endpoint */ { network, nft_address: "GSmMYNTohnQEtq26i76DqLK9rEL2gcG8FBjRi7p6tGcr", sender: YOUR_WALLET_ADDRESS, receiver: "5AHKzmDcjeAAnafTivi5u7dWYw3jUQh2VBRDzSd9ztVr", // your friend wallet address }, { headers: { "x-api-key": process.env.SHYFT_API_KEY // replace with your own key. Get free one from shyft.to } }); console.dir(response.data, { depth: null }) } transferCNFT(); ``` The result ```json { success: true, message: 'NFT transfer transaction generated successfully', result: { encoded_transaction: 'AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAgKpqXUsC9pW1n1oovnibJemqM1TnccEBLZgTLdKW9VlMs+Hk35ft2JDnawEhYEq1ZL/Ocep98zbAyHL60BiPUQhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPc9vwugugbLY8UDHpZOkvm6CjdiuUqduXkJ/E99OEV2Yi4DreTUoabIkdF9Z3b+KJljKE9xogSEmNRyuB8Glpa0yKLZ299PNQoSlRD8X8ZYrNuSRswpAskBYSeWXul+1CSoT7pXEHLoIpn9axn6N9+HaEWJeHWQTf49PI4MDfxS0wRlRlXxvj2QsSvYc1rJGQP7G3H/GB+6CBqmekkENMNebYAVzZByeQSgTPPm4S+bVMft+hgrVUL+FQscCDeafC7wPwLtHyi90xBEulKsTz6PGNOXcF+rLA80aI81+eHxqMAH+AcPHJ1fsUKchSB6B8SWKuQ9SvFH1LCgJXdMzRAEECwgAAAMBCQYCAgUHdKM0yOeMA0W6KqIR6o20iSgwIl/wglnfmVa/oimJWgDax+fd354FvgmQMaaqhYGRUegcoVx07SaRz/wM21RFsxsq95lCWP1kcZG5+QjBgTUQplrTg9bJr8/xsPTkOOklRgIoPn8S/n2QAAAAAAAAAAAAAAAA', signers: [ 'CDXLgstdVZJ7qUh3DC1mAGuCmTM3UiS1M24m44t3UViS' ] } } ``` [Transaction signature](https://translator.shyft.to/tx/55AXMShbf2fNj6AWEKNE23i3MDYtuAFREWTbomVAKr9w47zHwWhZZAH1X51BQZfMNNyJHSTxkhmARN28R5YZ2AFD?cluster=devnet) Once the NFT transfer request is successfully executed using the provided API, the response will include an `encoded_transaction`. This transaction will require a signature from the `sender` of the NFT. After obtaining the `sender`'s signature and completing the transaction, the compressed NFT will be successfully transferred to the `receiver` address, making it now owned by the recipient. ## Burn Compressed NFTs If you have a lot of unwanted or "trash" NFTs in your wallet and wish to remove them, Shyft provides a solution for this as well. By utilizing Shyft's Burning compressed NFT API, you can easily initiate the removal or deletion of these unwanted NFTs from your wallet. Below is an example code snippet demonstrating how to perform the removal process: ```javascript= async function burnCNFT() { const response = await axios.delete("https://api.shyft.to/sol/v1/nft/compressed/burn", /* Shyft burn compressed NFT API endpoint */ { headers: { "x-api-key": process.env.SHYFT_API_KEY // replace with your own key. Get free one from shyft.to }, data: { network, nft_address: "8ZRtGiBcjPEuT5uQV4cBJyGQQvVqfRK1TSEd93KQTXZf", wallet_address: YOUR_WALLET_ADDRESS, } }); console.dir(response.data, { depth: null }) } burnCNFT(); ``` ```json { success: true, message: 'NFT burn transaction generated successfully', result: { encoded_transaction: 'AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAkLpqXUsC9pW1n1oovnibJemqM1TnccEBLZgTLdKW9VlMs3ovZrQ+pUsCTrehDgYeVetu0OQSvpRdocX/bwKdmFrAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAId25o1aBXD+sECa23sXfMSSvuttIXJulo+M5igS3uoWHfjMTOJP7QK3vIQXfedcwKSAUSYhoY7bZGxVd8VQVKI/1Au7nP4G1VTBPOK+nijN3YJ7dCgJKuUwCbFbb/MVzmIuA63k1KGmyJHRfWd2/iiZYyhPcaIEhJjUcrgfBpaWtMii2dvfTzUKEpUQ/F/GWKzbkkbMKQLJAWEnll7pftQkqE+6VxBy6CKZ/WsZ+jffh2hFiXh1kE3+PTyODA38UtMEZUZV8b49kLEr2HNayRkD+xtx/xgfuggapnpJBDTALvA/Au0fKL3TEES6UqxPPo8Y05dwX6ssDzRojzX54fC7oOj8qHftMPzWR7+DHDNxh0tPfuErOm2kq5AjVoM8/AQYLBAAAAQoIAgUHCQN0dG4dOGvbKl3myuchmv6d1tlioNuiLyPTAlXPfzNTLf51zUQG1V0270lLcmYMp/F9+D/Oja7lxmai0SstNaIIJcsfH8nCvBCDDuB/nrFkPQY9YyfkGkPiC1QlQQyiFKwhv1DhfWJxCaoAAAAAAAAAAAAAAAA=', signers: [ 'CDXLgstdVZJ7qUh3DC1mAGuCmTM3UiS1M24m44t3UViS' ] } } ``` [Transaction signature](https://translator.shyft.to/tx/4XdkUVMY99Lj7YTF3XQnE6gS83cTEUDx3HFBc3S6WJ19xx1RLMkQSrg9E3s3bjvz3D6rPr1ujn6BRZgNkHhjWwDJ?cluster=devnet) Once the NFT burn request is successfully executed using the provided API, the response will contain an `encoded_transaction`. This transaction will necessitate a signature from the `wallet_address`. After obtaining the signature from the `wallet_address` and completing the transaction, the compressed NFT will be successfully burned, effectively removing it from you wallet. ## Conclusion So far, we have gone through the entire process, from creating a Merkle tree, minting new compressed NFTs, viewing all NFTs associated with a wallet, transferring NFTs, to burning unwanted NFTs. By utilizing Shyft's comprehensive suite of APIs, users have the ability to seamlessly manage and interact with their compressed NFTs. If you enjoyed reading about compressed NFTs in this article, we invite you to explore more of our content. Discover our other articles on topics like ["Creating a Live Web3 Activity Feed on Solana"](https://medium.com/shyft-to/how-to-create-a-live-activity-feed-on-solana-25f3f4fc0070) and ["Getting Human-Readable Transactions on Solana."](https://blogs.shyft.to/how-to-get-decoded-solana-transactions-d73d57ef5b66) We hope these resources will enrich your experience in building with Shyft. Furthermore, Shyft offers a comprehensive JS SDK that empowers you to interact with the Solana Blockchain seamlessly. This SDK provides a wide range of functionalities, including NFTs, Fungible Tokens, Wallets, Callbacks, and Transactions. You can find more details about the JS SDK [here](https://www.npmjs.com/package/@shyft-to/js) and unleash the full potential of your Solana-based projects. Happy building! ## Resources - [SHYFT API Documentation](https://docs.shyft.to/) - [Shyft Website](https://shyft.to/) - [Get API Key](https://shyft.to/get-api-key) - [GitHub](https://github.com/Shyft-to) - Join our [Discord](https://discord.gg/8JyZCjRPmr) - [Javascript SDK](https://www.npmjs.com/package/@shyft-to/js) - [Try out our APIs on Swagger UI](https://api.shyft.to/sol/api/explore/#/)