# Table of Contents - [Create & Launch Tokens on Solana | Token Generation Event (TGE) | Metaplex](#create-launch-tokens-on-solana-token-generation-event-tge-metaplex) - [Metaplex Developer Hub](#metaplex-developer-hub) - [Create NFTs on Solana | Metaplex Core | Digital Collectibles | Metaplex](#create-nfts-on-solana-metaplex-core-digital-collectibles-metaplex) - [Update an NFT | NFTs](#update-an-nft-nfts) - [Overview | Token Metadata](#overview-token-metadata) - [Transfer an NFT | NFTs](#transfer-an-nft-nfts) - [Burn an NFT | NFTs](#burn-an-nft-nfts) - [Overview | MPL-Hybrid](#overview-mpl-hybrid) - [Overview | Bubblegum V2](#overview-bubblegum-v2) - [Genesis — Solana Token Launchpad for Fair Launches & Token Sales | Metaplex](#genesis-solana-token-launchpad-for-fair-launches-token-sales-metaplex) - [Metaplex Core | Next-Gen NFT Standard for Solana](#metaplex-core-next-gen-nft-standard-for-solana) - [Overview | Core Candy Machine](#overview-core-candy-machine) - [Overview | Bubblegum](#overview-bubblegum) - [Overview | DAS API](#overview-das-api) - [Security | Developer Hub](#security-developer-hub) - [Metaplex Official Links | Developer Hub](#metaplex-official-links-developer-hub) - [Overview | Umi](#overview-umi) - [Overview | Inscription](#overview-inscription) - [Shank | Metaplex Developer Hub](#shank-metaplex-developer-hub) - [Protocol Fees | Developer Hub](#protocol-fees-developer-hub) - [Create a Token with Anchor | Solana Tokens](#create-a-token-with-anchor-solana-tokens) - [Solana Smart Contracts & Programs | NFT & Token Infrastructure | Metaplex](#solana-smart-contracts-programs-nft-token-infrastructure-metaplex) - [Solana Dev Tools | CLI, SDKs & APIs for NFTs & Tokens | Metaplex](#solana-dev-tools-cli-sdks-apis-for-nfts-tokens-metaplex) - [Metaplex Solana Guides | Guides](#metaplex-solana-guides-guides) - [How to Update Fungible Token Metadata on Solana | Tokens](#how-to-update-fungible-token-metadata-on-solana-tokens) - [Legacy Documentation | Developer Hub](#legacy-documentation-developer-hub) - [Create a Fungible Token | Tokens](#create-a-fungible-token-tokens) - [How to Mint Additional Fungible Tokens on Solana | Tokens](#how-to-mint-additional-fungible-tokens-on-solana-tokens) - [How to Transfer Fungible Tokens on Solana | Tokens](#how-to-transfer-fungible-tokens-on-solana-tokens) - [How to Burn Fungible Tokens on Solana | Tokens](#how-to-burn-fungible-tokens-on-solana-tokens) - [Fetch an NFT | NFTs](#fetch-an-nft-nfts) - [Create an NFT | NFTs](#create-an-nft-nfts) - [Launch a Token on Solana — Genesis Fair Launch Guide | Metaplex](#launch-a-token-on-solana-genesis-fair-launch-guide-metaplex) - [Stability Index | Developer Hub](#stability-index-developer-hub) - [Overview | Amman](#overview-amman) - [CLI Commands | Amman](#cli-commands-amman) - [Configuration | Amman](#configuration-amman) - [Getting Started | Amman](#getting-started-amman) - [Pre Made Configurations | Amman](#pre-made-configurations-amman) - [Introduction | Metaplex CLI](#introduction-metaplex-cli) - [Burn Compressed NFT | Metaplex CLI](#burn-compressed-nft-metaplex-cli) - [Bubblegum V2 (Compressed NFTs) | Metaplex CLI](#bubblegum-v2-compressed-nfts-metaplex-cli) - [Create Compressed NFT | Metaplex CLI](#create-compressed-nft-metaplex-cli) - [Transfer Compressed NFT | Metaplex CLI](#transfer-compressed-nft-metaplex-cli) - [List Merkle Trees | Metaplex CLI](#list-merkle-trees-metaplex-cli) - [Create Merkle Tree | Metaplex CLI](#create-merkle-tree-metaplex-cli) - [Fetch Compressed NFT | Metaplex CLI](#fetch-compressed-nft-metaplex-cli) - [Update Compressed NFT | Metaplex CLI](#update-compressed-nft-metaplex-cli) - [MPLX CLI - Fetch Candy Machine Information](#mplx-cli-fetch-candy-machine-information) - [MPLX CLI - Insert Items Command](#mplx-cli-insert-items-command) - [MPLX CLI - Create Candy Machine Command](#mplx-cli-create-candy-machine-command) - [MPLX CLI - Validate Cache Command](#mplx-cli-validate-cache-command) - [Explorer Configuration | Metaplex CLI](#explorer-configuration-metaplex-cli) - [MPLX CLI - Candy Machine Commands](#mplx-cli-candy-machine-commands) - [MPLX CLI - Upload Assets Command](#mplx-cli-upload-assets-command) - [MPLX CLI - Withdraw Candy Machine](#mplx-cli-withdraw-candy-machine) - [Burn Asset | Metaplex CLI](#burn-asset-metaplex-cli) - [Wallets | Metaplex CLI](#wallets-metaplex-cli) - [Create Asset | Metaplex CLI](#create-asset-metaplex-cli) - [RPCs | Metaplex CLI](#rpcs-metaplex-cli) - [Create Collection | Metaplex CLI](#create-collection-metaplex-cli) - [Fetch Asset or Collection | Metaplex CLI](#fetch-asset-or-collection-metaplex-cli) - [Update Asset | Metaplex CLI](#update-asset-metaplex-cli) - [Add Metadata to Token | Metaplex CLI](#add-metadata-to-token-metaplex-cli) - [Installation | Metaplex CLI](#installation-metaplex-cli) - [SOL Airdrop | Metaplex CLI](#sol-airdrop-metaplex-cli) - [Plugins | Metaplex CLI](#plugins-metaplex-cli) - [SOL Transfer | Metaplex CLI](#sol-transfer-metaplex-cli) - [SOL Balance | Metaplex CLI](#sol-balance-metaplex-cli) - [Token Transfer | Metaplex CLI](#token-transfer-metaplex-cli) - [Create Token | Metaplex CLI](#create-token-metaplex-cli) - [Guides | Umi Guides](#guides-umi-guides) - [Update Token Metadata | Metaplex CLI](#update-token-metadata-metaplex-cli) - [Convert standard DAS to Core Type | DAS API Core Extension](#convert-standard-das-to-core-type-das-api-core-extension) - [Umi - Optimal transaction landing using Compute Units (CU) and priority fees](#umi-optimal-transaction-landing-using-compute-units-cu-and-priority-fees) - [Shank Macros Reference | Metaplex Developer Hub](#shank-macros-reference-metaplex-developer-hub) - [Methods | Core DAS API Extension](#methods-core-das-api-extension) - [Getting Started | Shank](#getting-started-shank) - [Get Core Assets by Authority | DAS API Core Extension](#get-core-assets-by-authority-das-api-core-extension) - [Umi - Serializing, Deserializing, and sending Transactions](#umi-serializing-deserializing-and-sending-transactions) - [Get Core Assets by Collection | DAS API Core Extension](#get-core-assets-by-collection-das-api-core-extension) - [Get Asset | DAS API Core Extension](#get-asset-das-api-core-extension) - [Get Collection | DAS API Core Extension](#get-collection-das-api-core-extension) - [Get Core Assets by Owner | DAS API Core Extension](#get-core-assets-by-owner-das-api-core-extension) - [DAS API Core Extension - Plugin Derivation](#das-api-core-extension-plugin-derivation) - [Analyze Collection Statistics | DAS API Guides](#analyze-collection-statistics-das-api-guides) - [Guides | DAS API](#guides-das-api) - [Search Core Collections | DAS API Core Extension](#search-core-collections-das-api-core-extension) - [Display Options | DAS API](#display-options-das-api) - [Search Core Assets | DAS API Core Extension](#search-core-assets-das-api-core-extension) - [Getting Started | DAS API](#getting-started-das-api) - [Find Token Holders | DAS API Guides](#find-token-holders-das-api-guides) - [Find Compressed NFTs | DAS API Guides](#find-compressed-nfts-das-api-guides) - [Get Wallet Tokens | DAS API Guides](#get-wallet-tokens-das-api-guides) - [Get NFTs by Owner | DAS API Guides](#get-nfts-by-owner-das-api-guides) - [Get Assets by Owner and Collection | DAS API Guides](#get-assets-by-owner-and-collection-das-api-guides) - [Get All Tokens in a Collection | DAS API Guides](#get-all-tokens-in-a-collection-das-api-guides) - [Guides | Bubblegum](#guides-bubblegum) - [Get Fungible Assets | DAS API Guides](#get-fungible-assets-das-api-guides) - [Methods | DAS API](#methods-das-api) - [Get Asset | DAS API](#get-asset-das-api) - [Get Asset Proofs | DAS API](#get-asset-proofs-das-api) - [Pagination | DAS API](#pagination-das-api) - [Get Asset Proof | DAS API](#get-asset-proof-das-api) - [Sending HTTP requests | Umi](#sending-http-requests-umi) - [Get Assets By Authority | DAS API](#get-assets-by-authority-das-api) - [Get Asset Signatures | DAS API](#get-asset-signatures-das-api) - [Interface Implementations | Umi](#interface-implementations-umi) - [Get Assets | DAS API](#get-assets-das-api) - [Interfaces | Umi](#interfaces-umi) - [Getting Started | Umi](#getting-started-umi) - [Fetching Accounts | Umi](#fetching-accounts-umi) - [Search Assets by Multiple Criteria | DAS API Guides](#search-assets-by-multiple-criteria-das-api-guides) - [Get Assets By Creator | DAS API](#get-assets-by-creator-das-api) - [Get Assets By Group | DAS API](#get-assets-by-group-das-api) - [Get Assets By Owner | DAS API](#get-assets-by-owner-das-api) - [Umi Helpers | Umi](#umi-helpers-umi) - [Umi - @solana/kit Adapters](#umi-solana-kit-adapters) - [How to Interact with cNFTs on Other SVMs | Bubblegum](#how-to-interact-with-cnfts-on-other-svms-bubblegum) - [Search Assets | DAS API](#search-assets-das-api) - [Overview | Tool](#overview-tool) - [Create Account | Toolbox](#create-account-toolbox) - [Get NFT Editions | DAS API](#get-nft-editions-das-api) - [Memo Program | Toolbox](#memo-program-toolbox) - [Transfer Sol | Toolbox](#transfer-sol-toolbox) - [Registering Programs | Umi](#registering-programs-umi) - [Plugins | Umi](#plugins-umi) - [Timed Auction using Auctioneer | Auction House](#timed-auction-using-auctioneer-auction-house) - [Get Token Accounts | DAS API](#get-token-accounts-das-api) - [Metaplex Umi Plugins | Umi](#metaplex-umi-plugins-umi) - [Priority Fees and Compute Management | Toolbox](#priority-fees-and-compute-management-toolbox) - [FAQ | Auction House](#faq-auction-house) - [Uploading and Downloading Assets | Umi](#uploading-and-downloading-assets-umi) - [Address Lookup Table | Toolbox](#address-lookup-table-toolbox) - [Generating Umi clients via Kinobi | Umi](#generating-umi-clients-via-kinobi-umi) - [Beet | Developer Tools](#beet-developer-tools) - [Manage Buyer Escrow Accounts | Auction House](#manage-buyer-escrow-accounts-auction-house) - [Developer Tools | Rust Bin](#developer-tools-rust-bin) - [Developer Tools | Cusper](#developer-tools-cusper) - [Find | Auction House](#find-auction-house) - [Connecting with an RPC | Umi](#connecting-with-an-rpc-umi) - [Token Management | Toolbox](#token-management-toolbox) - [Developer Tools | Solita](#developer-tools-solita) - [Receipts | Auction House](#receipts-auction-house) - [Overview | Fixed Price Sale](#overview-fixed-price-sale) - [Gumdrop | Developer Hub](#gumdrop-developer-hub) - [Getting Started | Auction House](#getting-started-auction-house) - [Overview | Auction House](#overview-auction-house) - [Guides for Metaplex Candy Machine | Candy Machine](#guides-for-metaplex-candy-machine-candy-machine) - [Public keys and Signers | Umi](#public-keys-and-signers-umi) - [Manage Auction Houses | Auction House](#manage-auction-houses-auction-house) - [Burning Compressed NFTs | Bubblegum](#burning-compressed-nfts-bubblegum) - [Delegating Trees | Bubblegum](#delegating-trees-bubblegum) - [Delegating Compressed NFTs - Bubblegum](#delegating-compressed-nfts-bubblegum) - [Token Entangler | Developer Hub](#token-entangler-developer-hub) - [Manage Auction Houses using CLI | Auction House](#manage-auction-houses-using-cli-auction-house) - [Transferring Compressed NFTs | Bubblegum](#transferring-compressed-nfts-bubblegum) - [Updating Compressed NFTs | Bubblegum](#updating-compressed-nfts-bubblegum) - [Burning Compressed NFTs | Bubblegum V2](#burning-compressed-nfts-bubblegum-v2) - [iOS SDK | Developer Hub](#ios-sdk-developer-hub) - [Settings | Auction House](#settings-auction-house) - [Verifying Creators | Bubblegum](#verifying-creators-bubblegum) - [Delegating Trees | Bubblegum V2](#delegating-trees-bubblegum-v2) - [Merkle Tree Canopy | Bubblegum V2](#merkle-tree-canopy-bubblegum-v2) - [Javascript SDK | MPL-Bubblegum](#javascript-sdk-mpl-bubblegum) - [Technical Description | Fixed Price Sale](#technical-description-fixed-price-sale) - [SDKs | Bubblegum](#sdks-bubblegum) - [Delegating Compressed NFTs | Bubblegum V2](#delegating-compressed-nfts-bubblegum-v2) - [Trading Assets | Auction House](#trading-assets-auction-house) - [Umi - @solana/web3.js Differences and Adapters](#umi-solana-web3-js-differences-and-adapters) - [Verifying Collections | Bubblegum](#verifying-collections-bubblegum) - [Verifying Collections | Bubblegum V2](#verifying-collections-bubblegum-v2) - [Creating Bubblegum Trees | Bubblegum](#creating-bubblegum-trees-bubblegum) - [Decompressing Compressed NFTs | Bubblegum](#decompressing-compressed-nfts-bubblegum) - [Storing and Indexing NFT Data | Bubblegum V2](#storing-and-indexing-nft-data-bubblegum-v2) - [Updating Compressed NFTs | Bubblegum V2](#updating-compressed-nfts-bubblegum-v2) - [JavaScript SDK | MPL-Bubblegum V2](#javascript-sdk-mpl-bubblegum-v2) - [Create 1 Million NFTs on Solana | Bubblegum](#create-1-million-nfts-on-solana-bubblegum) - [SDKs | Bubblegum V2](#sdks-bubblegum-v2) - [Sending transactions | Umi](#sending-transactions-umi) - [FAQ | Bubblegum V2](#faq-bubblegum-v2) - [Verifying Creators | Bubblegum V2](#verifying-creators-bubblegum-v2) - [Minting Compressed NFTs | Bubblegum V2](#minting-compressed-nfts-bubblegum-v2) - [Minting Compressed NFTs | Bubblegum](#minting-compressed-nfts-bubblegum) - [Freezing and Thawing Compressed NFTs | Bubblegum V2](#freezing-and-thawing-compressed-nfts-bubblegum-v2) - [Android SDK | Developer Hub](#android-sdk-developer-hub) - [Creating Bubblegum Trees | Bubblegum V2](#creating-bubblegum-trees-bubblegum-v2) - [Fetching Compressed NFTs | Bubblegum V2](#fetching-compressed-nfts-bubblegum-v2) - [Transferring Compressed NFTs | Bubblegum v2](#transferring-compressed-nfts-bubblegum-v2) - [Mint from Candy Machine to a different wallet | Candy Machine](#mint-from-candy-machine-to-a-different-wallet-candy-machine) - [Airdrops - Mint from Candy Machine to a different wallet | Candy Machine](#airdrops-mint-from-candy-machine-to-a-different-wallet-candy-machine) - [Concurrent Merkle Trees | Bubblegum V2](#concurrent-merkle-trees-bubblegum-v2) - [Rust SDK | MPL-Bubblegum](#rust-sdk-mpl-bubblegum) - [Create a Token Metadata TM NFT Collection on Solana with Candy Machine | Candy Machine](#create-a-token-metadata-tm-nft-collection-on-solana-with-candy-machine-candy-machine) - [Hashing NFT Data | Bubblegum V2](#hashing-nft-data-bubblegum-v2) - [Serializers | Umi](#serializers-umi) - [Rust SDK | MPL-Bubblegum V2](#rust-sdk-mpl-bubblegum-v2) - [JavaScript SDK | Candy Machine](#javascript-sdk-candy-machine) - [launch | Sugar](#launch-sugar) - [airdrop | Sugar](#airdrop-sugar) - [Candy Machine - Getting Started - Rust SDK | Candy Machine](#candy-machine-getting-started-rust-sdk-candy-machine) - [bundlr | Sugar](#bundlr-sugar) - [deploy | Sugar](#deploy-sugar) - [config | Sugar](#config-sugar) - [collection | Sugar](#collection-sugar) - [show | Sugar](#show-sugar) - [reveal | Sugar](#reveal-sugar) - [hash | Sugar](#hash-sugar) - [mint | Sugar](#mint-sugar) - [sign | Sugar](#sign-sugar) - [freeze | Sugar](#freeze-sugar) - [guard | Sugar](#guard-sugar) - [Overview | Sugar](#overview-sugar) - [Cache File | Sugar](#cache-file-sugar) - [Address Gate Guard | Candy Machine](#address-gate-guard-candy-machine) - [Generating Custom Guard Client | Candy Machine](#generating-custom-guard-client-candy-machine) - [Candy Machine Guards - End Date Guard | Candy Machine](#candy-machine-guards-end-date-guard-candy-machine) - [Getting Started | Candy Machine](#getting-started-candy-machine) - [Bring Your Own Uploader | Sugar](#bring-your-own-uploader-sugar) - [API References | Candy Machine](#api-references-candy-machine) - [Mint Limit Guard | Candy Machine](#mint-limit-guard-candy-machine) - [NFT Burn Guard | Candy Machine](#nft-burn-guard-candy-machine) - [NFT Gate Guard | Candy Machine](#nft-gate-guard-candy-machine) - [Program Gate Guard | Candy Machine](#program-gate-guard-candy-machine) - [Special Guard Instructions | Candy Machine](#special-guard-instructions-candy-machine) - [Gatekeeper Guard | Candy Machine](#gatekeeper-guard-candy-machine) - [Allocation Guard | Candy Machine"](#allocation-guard-candy-machine-) - [Bot Tax Guard | Candy Machine](#bot-tax-guard-candy-machine) - [NFT Payment Guard | Candy Machine](#nft-payment-guard-candy-machine) - [Start Date Guard | Candy Machine](#start-date-guard-candy-machine) - [Redeemed Amount Guard | Candy Machine](#redeemed-amount-guard-candy-machine) - [Sol Payment Guard | Candy Machine](#sol-payment-guard-candy-machine) - [Token Gate Guard | Candy Machine](#token-gate-guard-candy-machine) - [Token Burn Guard | Candy Machine](#token-burn-guard-candy-machine) - [Third Party Signer Guard | Candy Machine](#third-party-signer-guard-candy-machine) - [Token Payment Guard | Candy Machine](#token-payment-guard-candy-machine) - [Token2022 Payment Guard | Candy Machine](#token2022-payment-guard-candy-machine) - [Overview | Candy Machine](#overview-candy-machine) - [Programmable NFTs | Candy Machine](#programmable-nfts-candy-machine) - [Guard Groups | Candy Machine](#guard-groups-candy-machine) - [Inserting Items | Candy Machine](#inserting-items-candy-machine) - [Allowlist | Candy Machine](#allowlist-candy-machine) - [Candy Guards | Candy Machine](#candy-guards-candy-machine) - [Freeze Sol Payment Guard | Candy Machine](#freeze-sol-payment-guard-candy-machine) - [Freeze Token Payment Guard | Candy Machine](#freeze-token-payment-guard-candy-machine) - [Settings | Candy Machine](#settings-candy-machine) - [Create, Update, Fetch and Delete | Candy Machine](#create-update-fetch-and-delete-candy-machine) - [Minting | Candy Machine](#minting-candy-machine) - [JSON Schema | Core](#json-schema-core) - [Guides | Core](#guides-core) --- # Create & Launch Tokens on Solana | Token Generation Event (TGE) | Metaplex Solana Tokens ------------- Create, launch, and manage fungible tokens on Solana. Build token generation events (TGE), fair launches, and token sales using Metaplex Genesis and SDKs. [### Launch Token\ \ Run a TGE or fair launch on Solana.\ \ Learn more](https://developers.metaplex.com/tokens/launch-token) [### Create A Token\ \ Create token data on chain using Metaplex SDKs.\ \ Learn more](https://developers.metaplex.com/tokens/create-a-token) [### Mint Tokens\ \ Mint additional tokens using Metaplex SDKs.\ \ Learn more](https://developers.metaplex.com/tokens/mint-tokens) [### Transfer Tokens\ \ Transfer tokens using Metaplex SDKs.\ \ Learn more](https://developers.metaplex.com/tokens/transfer-a-token) [### Update A Token\ \ Update token metadata using Metaplex SDKs.\ \ Learn more](https://developers.metaplex.com/tokens/update-token) [### Burn Tokens\ \ Burn tokens using Metaplex SDKs.\ \ Learn more](https://developers.metaplex.com/tokens/burn-tokens) Anchor ------ Create and manage tokens using Rust and the Anchor framework. [### Create Token with Anchor\ \ Create a token using Rust and Anchor framework.\ \ Learn more](https://developers.metaplex.com/tokens/anchor/create-token) --- # Metaplex Developer Hub Tokens ------ Create and launch tokens on Solana. Run token generation events (TGE), fair launches, and manage fungible tokens. [### Launch Token\ \ Run a TGE or fair launch on Solana.\ \ Learn more](https://developers.metaplex.com/tokens/launch-token) [### Create A Token\ \ Create token data on chain using Metaplex SDKs.\ \ Learn more](https://developers.metaplex.com/tokens/create-a-token) [### Mint Tokens\ \ Mint additional tokens using Metaplex SDKs.\ \ Learn more](https://developers.metaplex.com/tokens/mint-tokens) [### Transfer Tokens\ \ Transfer tokens using Metaplex SDKs.\ \ Learn more](https://developers.metaplex.com/tokens/transfer-a-token) [### Update A Token\ \ Update token metadata using Metaplex SDKs.\ \ Learn more](https://developers.metaplex.com/tokens/update-token) [### Burn Tokens\ \ Burn tokens using Metaplex SDKs.\ \ Learn more](https://developers.metaplex.com/tokens/burn-tokens) NFTs ---- Create, manage, and trade NFTs on Solana using Metaplex Core and other NFT standards. [### Create A NFT\ \ Create NFT data on chain using Metaplex SDKs.\ \ Learn more](https://developers.metaplex.com/nfts/create-nft) [### Read A NFT\ \ Read NFT data on chain using DAS and Metaplex SDKs.\ \ Learn more](https://developers.metaplex.com/nfts/fetch-nft) [### Update A NFT\ \ Update NFT data on chain using DAS and Metaplex SDKs.\ \ Learn more](https://developers.metaplex.com/nfts/update-nft) [### Burn A NFT\ \ Burn NFT data on chain using DAS and Metaplex SDKs.\ \ Learn more](https://developers.metaplex.com/nfts/burn-nft) [### Transfer A NFT\ \ Transfer NFT data on chain using Metaplex SDKs.\ \ Learn more](https://developers.metaplex.com/nfts/transfer-nft) Smart Contracts --------------- Production-ready on-chain programs for NFTs, tokens, and digital assets on Solana. [### Token Metadata\ \ Digital ownership standard\ \ Learn more](https://developers.metaplex.com/smart-contracts/token-metadata) [### Core\ \ Next gen NFT standard\ \ Learn more](https://developers.metaplex.com/smart-contracts/core) [### Bubblegum v2\ \ Improved Compressed NFTs\ \ Learn more](https://developers.metaplex.com/smart-contracts/bubblegum-v2) [### Core Candy Machine\ \ Core Asset launchpad\ \ Learn more](https://developers.metaplex.com/smart-contracts/core-candy-machine) [### MPL-Hybrid\ \ Hybrid Assets\ \ Learn more](https://developers.metaplex.com/smart-contracts/mpl-hybrid) [### Genesis\ \ Token Launch Platform\ \ Learn more](https://developers.metaplex.com/smart-contracts/genesis) [### Inscription\ \ NFT inscribed on Solana\ \ Learn more](https://developers.metaplex.com/smart-contracts/inscription) [### Bubblegum v1 (legacy)\ \ Compressed NFTs\ \ Learn more](https://developers.metaplex.com/smart-contracts/bubblegum) Dev Tools --------- SDKs, CLIs, and APIs to build, test, and deploy digital asset applications on Solana. [### DAS API\ \ Fetch Digital Asset Data\ \ Learn more](https://developers.metaplex.com/dev-tools/das-api) [### Umi\ \ Client wrapper\ \ Learn more](https://developers.metaplex.com/dev-tools/umi) [### CLI\ \ MPLX CLI\ \ Learn more](https://developers.metaplex.com/dev-tools/cli) [### Shank\ \ IDL Extraction for Solana Programs\ \ Learn more](https://developers.metaplex.com/dev-tools/shank) [### Amman\ \ Local Validator Toolkit\ \ Learn more](https://developers.metaplex.com/dev-tools/amman) [### Legacy\ \ Products from our old docs\ \ Learn more](https://developers.metaplex.com/legacy-documentation) Solana ------ [### Solana\ \ Guides for the Solana Blockchain\ \ Learn more](https://developers.metaplex.com/solana) --- # Create NFTs on Solana | Metaplex Core | Digital Collectibles | Metaplex Solana NFTs ----------- Create, manage, and trade NFTs on Solana using Metaplex Core. Build digital collectibles, art, and gaming assets with the most efficient NFT standard. [### Create A NFT\ \ Create NFT data on chain using Metaplex SDKs.\ \ Learn more](https://developers.metaplex.com/nfts/create-nft) [### Read A NFT\ \ Read NFT data on chain using DAS and Metaplex SDKs.\ \ Learn more](https://developers.metaplex.com/nfts/fetch-nft) [### Update A NFT\ \ Update NFT data on chain using DAS and Metaplex SDKs.\ \ Learn more](https://developers.metaplex.com/nfts/update-nft) [### Burn A NFT\ \ Burn NFT data on chain using DAS and Metaplex SDKs.\ \ Learn more](https://developers.metaplex.com/nfts/burn-nft) [### Transfer A NFT\ \ Transfer NFT data on chain using Metaplex SDKs.\ \ Learn more](https://developers.metaplex.com/nfts/transfer-nft) --- # Update an NFT | NFTs Update your NFT's name and metadata as the update authority. Update an NFT ------------- In the following section you can find a full code example and the parameters that you might need to change. You can learn more about updating NFTs in the [Core documentation](https://developers.metaplex.com/smart-contracts/core/update) . Umi (JS)CLI SnippetFull Copy 1import { createUmi } from '@metaplex-foundation/umi-bundle-defaults' 2import { update } from '@metaplex-foundation/mpl-core' 3import { mplCore } from '@metaplex-foundation/mpl-core' 4import { publicKey } from '@metaplex-foundation/umi' 5 6const umi = createUmi('https://api.devnet.solana.com').use(mplCore()) 7const assetAddress = publicKey('AssetAddressHere...') 8 9// Update an existing NFT asset's metadata 10const result = await update(umi, { 11 asset: assetAddress, 12 name: 'Updated NFT Name', 13 uri: 'https://updated-example.com/metadata.json', 14}).sendAndConfirm(umi) 15 16console.log('Asset updated successfully') 1# Update an NFT using the Metaplex CLI 2 3# Update name and URI 4mplx core asset update --name "Updated NFT" --uri "https://example.com/new-metadata.json" 5 6# Update with new image 7mplx core asset update --image "./new-image.png" 8 9# Update with JSON metadata file 10mplx core asset update --json "./metadata.json" 11 12# Update with both JSON and image 13mplx core asset update --json "./metadata.json" --image "./new-image.png" Parameters ---------- Customize these parameters for your update: | Parameter | Description | | --- | --- | | `assetAddress` | The public key of the NFT to update | | `name` | New name for the NFT (optional) | | `uri` | New metadata URI (optional) | How It Works ------------ The update process involves three steps: 1. **Fetch the NFT** - Get the current NFT data using `fetchAsset` 2. **Prepare update** - Specify the new name or URI you want to change 3. **Send update** - Execute the update transaction Only the update authority of the NFT can modify it. If the NFT is part of a collection and uses collection authority, you need to be the collection's update authority. Previous [← Fetch an NFT](https://developers.metaplex.com/nfts/fetch-nft) Next [Transfer an NFT →](https://developers.metaplex.com/nfts/transfer-nft) --- # Overview | Token Metadata The Token Metadata program is a fundamental program when dealing NFTs and Fungible assets on the Solana blockchain. In this overview, we explain what this program does and how we can leverage its various features at a high level. Please note that certain Token Metadata instructions will require protocol fees. Please review the [Protocol Fees](https://developers.metaplex.com/protocol-fees) page for up-to-date information. [Getting Started](https://developers.metaplex.com/smart-contracts/token-metadata/getting-started) -------------------------------------------------------------------------------------------------- Find the language or library of your choice and get started with digital assets on Solana. [API reference](https://mpl-token-metadata.typedoc.metaplex.com/) ------------------------------------------------------------------ Looking for something specific? Have a peak at our API References and find your answer. Introduction ------------ The Token Metadata program is one of the most important programs when dealing with NFTs on the Solana blockchain. Its main goal is to **attach additional data to [Fungible](https://en.wikipedia.org/wiki/Fungibility) or Non-Fungible [Tokens](https://spl.solana.com/token) ** on Solana. It achieves this using [Program Derived Addresses](https://developers.metaplex.com/solana/understanding-programs#program-derived-addresses-pda) (PDAs) that are _derived_ from the address of Mint Accounts. If you’re not familiar with [Solana’s Token program](https://spl.solana.com/token) , _Mint Accounts_ are responsible for storing the global information of a Token and _Token Accounts_ store the relationship between a wallet and a Mint Account. Press enter or space to select a node.You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel. Press enter or space to select an edge. You can then press delete to remove it or escape to cancel. Whilst Mint Accounts contain a few data attributes such as its current supply, it doesn't offer the ability to inject standardized data that can be understood by apps and marketplaces. This is why the Token Metadata program offers a **Metadata Account** that attaches itself to a Mint Account via a PDA. Press enter or space to select a node.You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel. Press enter or space to select an edge. You can then press delete to remove it or escape to cancel. That Metadata Account holds a lot of valuable information that can be used throughout the ecosystem. For instance, it maintains a list of creators for the token. Each creator has a `Verified` attribute that, when `True`, guarantees the token was signed by that creator. Each creator also has a `Share` attribute that can be used by marketplaces to distribute royalties. By attaching more data to the Mint Account, **the Token Metadata program is able to make Digital Assets** of regular onchain Tokens. A JSON standard --------------- One important attribute of the Metadata Account is the `URI` attribute that points to a JSON file off-chain. This is used to safely provide additional data whilst not being constrained by the fees involved in storing onchain data. That JSON file [follows a certain standard](https://developers.metaplex.com/smart-contracts/token-metadata/token-standard) that anyone can use to find useful information on tokens. Press enter or space to select a node.You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel. Press enter or space to select an edge. You can then press delete to remove it or escape to cancel. Note that, this JSON file can be stored using a permanent storage solution such as Arweave to ensure it cannot be updated. Additionally, one can use the `Is Mutable` attribute of the Metadata Account to make it immutable and, therefore, forbid the `URI` attribute — and other attributes such as `Name` and `Creators` — to ever be changed. Using this combination, we can guarantee the immutability of the off-chain JSON file. NFTs ---- You might be wondering: what has this got to do with NFTs? Well, NFTs are special tokens that are Non-Fungible. More precisely, NFTs in Solana are Mint Accounts with the following characteristics: * It has **a supply of 1**, meaning only one token is in circulation. * It has **zero decimals**, meaning there cannot be such a thing as 0.5 tokens. * It has **no mint authority**, meaning no one can ever mint additional tokens. What we end up with is a token that cannot be traded with something of the same kind, which is the definition of a Non-Fungible Token (NFT). Press enter or space to select a node.You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel. Press enter or space to select an edge. You can then press delete to remove it or escape to cancel. In this particular yet popular case, the goal of the Metadata Account is to provide the actual data of that NFT to make it a useful Digital Asset. Additionally, the Token Metadata program offers another account specifically for NFTs called the **Master Edition Account**. This account is also a PDA derived from the Mint Account. Before creating this account, the Token Metadata program will ensure the special characteristics of Non-Fungible Tokens listed above are met. However, it is worth noting that, instead of voiding the Mint Authority, it will transfer both the Mint Authority and the Freeze Authority to the Master Edition PDA to ensure no one can mint or freeze tokens without going through the Token Metadata program. You can [read more about why this decision was made in the FAQ](https://developers.metaplex.com/smart-contracts/token-metadata/faq#why-are-the-mint-and-freeze-authorities-transferred-to-the-edition-pda) . Thus, **the existence of the Master Edition account acts as proof of Non-Fungibility** for that Mint Account. Press enter or space to select a node.You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel. Press enter or space to select an edge. You can then press delete to remove it or escape to cancel. Printing Editions ----------------- In addition to being Non-Fungibility evidence, the Master Edition account also allows users to print one or multiple copies of an NFT. This feature is particularly helpful to creators that want to offer multiple copies of their 1/1 NFTs to their audience. The Master Edition account contains an optional `Max Supply` attribute that dictates the maximum amount of NFTs that can be printed that way. If set to `0`, printing is disabled. If set to `None` an unlimited amount of copies can be printed. The Master Edition NFT, a.k.a. Original NFT, acts as the master record that one can use to print copies, a.k.a. Print NFTs. Each Print NFT is made of its own Mint Account and its own Metadata Account whose data is copied from the Original NFT. However, instead of having a Master Edition account attached to their Mint Account, Print NFTs use yet another PDA account called an **Edition Account**. This account keeps track of the edition number and the parent Master Edition it originated from. Note that the Master Edition account and the Edition account share the same seeds for their PDA. That means an NFT can be one or the other but not both. Press enter or space to select a node.You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel. Press enter or space to select an edge. You can then press delete to remove it or escape to cancel. Semi-Fungible Tokens -------------------- Whilst NFTs are the biggest use case of the Token Metadata program, it’s important to notice that the program also works with Fungible Token and, what we call, Semi-Fungible Tokens or Fungible Assets. At the end of the day, the Metadata account helps attach data to tokens regardless of their fungibility. However, the standard of the off-chain JSON file will vary slightly to accommodate their needs. To safely identify the fungibility of a token — and, thus, the standard that we should use — the Metadata account keeps track of that information in its `Token Standard` attribute. This attribute is automatically computed by the program and cannot be manually updated. It can take the following values. * `NonFungible`: The Mint account is associated with a Master Edition account and, therefore, is Non-Fungible. This is your typical NFT standard. * `NonFungibleEdition`: This is the same as `NonFungible` but the NFT was printed from an Original NFT and, thus, is associated with an Edition account instead of a Master Edition account. * `FungibleAsset`: The Mint account is Fungible but has zero decimal places. Having zero decimals means we can treat the token as an asset whose supply is not limited to one. For instance, Fungible Assets can be used in the gaming industry to store resources such as “Wood” or “Iron”. * `Fungible`: The Mint account is Fungible and has more than one decimal place. This is more likely going to be a token used as a decentralised currency. * `ProgrammableNonFungible`: A special `NonFungible` token that is frozen at all times to enforce custom authorization rules. See the next section for more information. You can [read more about these standards here](https://developers.metaplex.com/smart-contracts/token-metadata/token-standard) . Press enter or space to select a node.You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel. Press enter or space to select an edge. You can then press delete to remove it or escape to cancel. Programmable NFTs ----------------- Because the Token Metadata program is building on top of the Solana Token program, anyone can transfer tokens (fungible or not) without going through the Token Metadata program. Whilst this is great for program composibility, it also means that the Token Metadata program cannot enforce any rules on the tokens it is attached to. A good example of why this can be problematic is that Token Metadata cannot enforce secondary sales royalties. Whilst there is **Seller Fee Basis Points** attribute on the Metadata account, it is purely [indicative](https://developers.metaplex.com/solana/understanding-programs#indicative-fields) and anyone could create a marketplace that does not honor royalties — which is exactly what happened. **Programmable NFTs** were introduced to solve this problem. They are a new _opt-in_ Token Standard that **keeps the underlying token accounts frozen at all times**. That way, nobody can transfer, lock or burn Programmable NFTs without going through the Token Metadata program. It is then up to the creators to define custom operation-specific authorization rules that will be enforced by the Token Metadata program. These are defined in a special **RuleSet** account which is attached to the Metadata account. An example of such RuleSet could be an allowlist of program addresses that honor royalties. RuleSets are part of a new Metaplex program called [Token Auth Rules](https://developers.metaplex.com/smart-contracts/token-auth-rules) . You can [read more about Programmable NFTs here](https://developers.metaplex.com/smart-contracts/token-metadata/pnfts) . Press enter or space to select a node.You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel. Press enter or space to select an edge. You can then press delete to remove it or escape to cancel. And a lot more -------------- Whilst this provides a good overview of the Token Metadata program and what it has to offer, there’s still a lot more that can be done with it. The other pages of this documentation aim to document it further and explain significant features in their own individual pages. * [Token Standards (Assets)](https://developers.metaplex.com/smart-contracts/token-metadata/token-standard) * [Minting Assets](https://developers.metaplex.com/smart-contracts/token-metadata/mint) * [Updating Assets](https://developers.metaplex.com/smart-contracts/token-metadata/update) * [Transferring Assets](https://developers.metaplex.com/smart-contracts/token-metadata/transfer) * [Burning Assets](https://developers.metaplex.com/smart-contracts/token-metadata/burn) * [Printed Editions](https://developers.metaplex.com/smart-contracts/token-metadata/print) * [Verified Collections](https://developers.metaplex.com/smart-contracts/token-metadata/collections) * [Verified Creators](https://developers.metaplex.com/smart-contracts/token-metadata/creators) * [Delegated Authorities](https://developers.metaplex.com/smart-contracts/token-metadata/delegates) * [Locking Assets](https://developers.metaplex.com/smart-contracts/token-metadata/lock) * [Programmable NFTs](https://developers.metaplex.com/smart-contracts/token-metadata/pnfts) * [NFT Escrow](https://developers.metaplex.com/smart-contracts/token-metadata/escrow) Next [Getting Started →](https://developers.metaplex.com/smart-contracts/token-metadata/getting-started) --- # Transfer an NFT | NFTs Transfer NFT ownership between wallets on Solana. Transfer an NFT --------------- In the following section you can find a full code example and the parameters that you might need to change. You can learn more about transferring NFTs in the [Core documentation](https://developers.metaplex.com/smart-contracts/core/transfer) . Umi (JS) SnippetFull Copy 1import { createUmi } from '@metaplex-foundation/umi-bundle-defaults' 2import { transfer } from '@metaplex-foundation/mpl-core' 3import { mplCore } from '@metaplex-foundation/mpl-core' 4import { publicKey } from '@metaplex-foundation/umi' 5 6// Initialize UMI 7const umi = createUmi('https://api.devnet.solana.com') 8 .use(mplCore()) 9 10// Transfer an existing NFT asset to a new owner 11const result = await transfer(umi, { 12 asset: publicKey('AssetAddressHere...'), 13 newOwner: publicKey('RecipientAddressHere...'), 14}).sendAndConfirm(umi) 15 16console.log('Asset transferred:', result.signature) Parameters ---------- Customize these parameters for your transfer: | Parameter | Description | | --- | --- | | `assetAddress` | The public key of the NFT to transfer | | `newOwner` | The wallet address of the recipient | How It Works ------------ The transfer process involves three steps: 1. **Verify ownership** - You must be the current owner of the NFT 2. **Specify recipient** - Provide the new owner's wallet address 3. **Execute transfer** - The NFT ownership is transferred immediately NFT Transfers ------------- Unlike SPL/fungible tokens, Core NFTs don't require the recipient to create a token account first. The ownership is recorded directly in the NFT, making transfers simpler and cheaper. Previous [← Update an NFT](https://developers.metaplex.com/nfts/update-nft) Next [Burn an NFT →](https://developers.metaplex.com/nfts/burn-nft) --- # Burn an NFT | NFTs Permanently destroy an NFT and reclaim rent fees. Burn an NFT ----------- In the following section you can find a full code example and the parameters that you might need to change. You can learn more about burning NFTs in the [Core documentation](https://developers.metaplex.com/smart-contracts/core/burn) . Umi (JS)CLI SnippetFull Copy 1import { createUmi } from '@metaplex-foundation/umi-bundle-defaults' 2import { burn } from '@metaplex-foundation/mpl-core' 3import { mplCore } from '@metaplex-foundation/mpl-core' 4import { publicKey } from '@metaplex-foundation/umi' 5 6const umi = createUmi('https://api.devnet.solana.com').use(mplCore()) 7const assetAddress = publicKey('AssetAddressHere...') 8 9// Permanently destroy/burn an NFT asset 10const result = await burn(umi, { 11 asset: assetAddress, 12}).sendAndConfirm(umi) 13 14console.log('Asset burned successfully') 1# Burn an NFT using the Metaplex CLI 2 3# Burn a single asset by its mint address 4mplx core asset burn 5 6# Burn an asset from that is part of a collection 7mplx core asset burn --collection Parameters ---------- Customize these parameters for your burn: | Parameter | Description | | --- | --- | | `assetAddress` | The public key of the NFT to burn | How It Works ------------ The burn process involves three steps: 1. **Fetch the NFT** - Get the NFT data using `fetchAsset` 2. **Execute burn** - Destroy the NFT permanently 3. **Reclaim rent** - Most SOL is returned to you (except ~0.00089784 SOL) **Warning**: Burning is permanent and cannot be reversed. Make sure you want to destroy the NFT before proceeding. Rent Reclamation ---------------- When you burn an NFT: * Most of the rent SOL is returned to the NFT owner * A small amount (~0.00089784 SOL) remains to prevent the account from being reopened * You must be the NFT owner to burn it Previous [← Transfer an NFT](https://developers.metaplex.com/nfts/transfer-nft) --- # Overview | MPL-Hybrid **MPL-404** is a new model for digital assets, web3 games, and onchain communities. At the core of the model is a swap program (**mpl-hybrid**) that trades a fixed number of fungible assets for a non-fungible asset and vice versa. The swap is a dual escrow system, ensuring that all available non-fungible assets are backed by escrowed fungibles and vice versa. Please note that certain MPL-Hybrid instructions will require protocol fees. Please review the [Protocol Fees](https://developers.metaplex.com/protocol-fees) page for up-to-date information. Swapping -------- The ability to freely move between fungible and non-fungible assets in a predictable way allows this new asset class (often called **hybrids**) to take advantage of the best aspects of both asset types. **Non-fungible assets can now benefit from the liquidity, distribution, and DeFi opportunities** associated with fungible assets. Conversely, fungible assets can now benefit from the improved utility, collectability, and identity that come from the non-fungible world. Re-Rolling ---------- the `mpl-hybrid` program includes the option to "re-roll" the asset each time its swapped. For example, every non-fungible asset can have its metadata blanked as it enters the escrow wallet and randomly reassigned (rerolled) as it leaves escrow. The creator has the ability to both manage available traits as well as to charge a small fee during the swap (typically when swapping into an NFT). MPL-Hybrid can add “loot box” gamification to every 404 project and can serve as an alternative source of revenue (e.g. unique limited time traits for an NFT community or randomized in-game rewards). It also offers the ability to craft more dynamic collections that can evolve to better suit the needs of the project and community over time. Next [Preparation →](https://developers.metaplex.com/smart-contracts/mpl-hybrid/preparation) --- # Overview | Bubblegum V2 Bubblegum V2 is the latest iteration of the Metaplex Protocol program for creating and interacting with compressed NFTs (cNFTs) on Solana. Built for large-scale operations, Bubblegum V2 preserves all the benefits of the original Bubblegum while introducing powerful new features. Compressed NFTs make it possible to scale the creation of NFTs to new orders of magnitude by rethinking the way we store data onchain. Please note that certain Bubblegum V2 instructions will require protocol fees. Please review the [Protocol Fees](https://developers.metaplex.com/protocol-fees) page for up-to-date information. [Getting Started](https://developers.metaplex.com/smart-contracts/bubblegum-v2/sdk) ------------------------------------------------------------------------------------ Find the language or library of your choice and get started with compressed NFTs. [API reference](https://mpl-bubblegum.typedoc.metaplex.com/) ------------------------------------------------------------- Looking for something specific? Have a peak at our API References and find your answer. What's New in Bubblegum V2 -------------------------- Bubblegum V2 builds on the foundation of the original Bubblegum program while introducing several powerful new features: * **Freeze and Thaw Functionality**: Two types of freeze/thaw are available: 1) cNFT owners can delegate freeze authority to a leaf delegate for asset-level control, providing flexibility for various use cases such as preventing transfers during specific events or implementing vesting mechanics. 2) If the `PermanentFreezeDelegate` plugin is enabled on collection creation, project creators can freeze and thaw cNFTs via the permanent freeze delegate for collection-wide control * **MPL-Core Collections Integration**: Bubblegum V2 NFTs can now be added to MPL-Core collections instead of being limited to token metadata collections, allowing for greater flexibility and integration with the broader Metaplex ecosystem. * **Royalty Enforcement**: Since Bubblegum V2 is using [MPL-Core](https://developers.metaplex.com/smart-contracts/core) Collections, it is possible to enforce royalties on cNFTs e.g. using a `ProgramDenyList`. * **Soulbound NFTs**: cNFTs can now be made soulbound (non-transferrable), permanently binding them to their owner's wallet. This is perfect for credentials, proof of attendance, identity verification, and more. It requires the `PermanentFreezeDelegate` plugin to be enabled when creating the collection. * **Allow Permanent Transfer**: The permanent transfer delegate can now transfer the cNFT to a new owner without interaction of the leaf owner if the `PermanentTransferDelegate` plugin is enabled on the collection. * **Burning by Authority**: If the Collection has the `PermanentBurnDelegate` plugin enabled, the delegate could burn the NFT without the leaf owner's signature. * **Attributes**: Attribute Data on collection level can be added using the MPL-Core `attributes` plugin. To allow the above features to work, Bubblegum V2 introduces a new leaf schema (`LeafSchemaV2`). To learn more what leaves are used in Bubblegum V2, check out the following sections. LeafSchemaV2 ------------ Bubblegum V2 introduces a new leaf schema (LeafSchemaV2) which supports the additional features while maintaining backward compatibility. This new schema allows for: * Integration with MPL-Core collections instead of traditional token metadata * Supporting freezing/thawing functionality * Enabling soulbound capabilities Projects can choose to use the original leaf Schema by using Legacy Bubblegum or the new v2 schema with Bubblegum V2 depending on their requirements. To use the new `LeafSchemaV2`, a V2 Merkle Tree has to be used that needs to be created using the [`createTreeV2` instruction](https://developers.metaplex.com/smart-contracts/bubblegum-v2/create-trees) . V1 Merkle Trees do not support the new leaf schema and V2 Merkle Trees are not compatible with V1 leaves. Merkle Trees, leaves and proofs ------------------------------- Compressed NFTs only exist in the context of a **Merkle Tree**. We explain [in a dedicated advanced guide](https://developers.metaplex.com/smart-contracts/bubblegum-v2/concurrent-merkle-trees) what Merkle Trees are but, for the sake of this overview, you can think of a Merkle Tree as a collection of hashes that we call **Leaves**. Each Leaf is obtained by [hashing the data of the compressed NFT](https://developers.metaplex.com/smart-contracts/bubblegum-v2/hashed-nft-data) . For each Leaf in the Merkle Tree, one can provide a list of hashes — called a **Proof** — that enables anyone to verify that the given Leaf is part of that tree. Whenever a compressed NFT is updated or transferred, its associated Leaf will change and so will its Proof. Press enter or space to select a node.You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel. Press enter or space to select an edge. You can then press delete to remove it or escape to cancel. As such, Merkle Trees act as an onchain structure that allows anyone to verify a given compressed NFT exist. They do this without storing any NFT data which makes them so scalable. Which brings us to an important question: where is the NFT data stored? Metaplex DAS API ---------------- When we mint a new compressed NFT, its data is hashed and added as a new Leaf in a Merkle Tree. But there's more. Additionally, the entire NFT data is stored in the transaction that created the compressed NFT. Similarly, when a compressed NFT is updated, its updated data is, once again, saved on the transaction as a changelog. So, while there aren't any accounts keeping track of that data, one can look at all previous transactions in the ledger and find that information. Press enter or space to select a node.You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel. Press enter or space to select an edge. You can then press delete to remove it or escape to cancel. Crawling through millions of transactions every time just to fetch the data of one NFT is admittedly not the best user experience. Therefore, compressed NFTs rely on some RPCs to index that information in real time to abstract this away from the end-user. We call the resulting RPC API, which enables fetching compressed NFTs, **the Metaplex DAS API**. Note that not all RPCs support the DAS API. As such, you may be interested in the ["Metaplex DAS API RPCs"](https://developers.metaplex.com/solana/rpcs-and-das) page to select an appropriate RPC when using compressed NFTs in your application. We talk about this in more detail in our advanced ["Storing and indexing NFT data"](https://developers.metaplex.com/smart-contracts/bubblegum-v2/stored-nft-data) guide. Features -------- Even though NFT data does not live inside accounts, it is still possible to execute a variety of operations on compressed NFTs. This is possible by requesting the current NFT data and ensuring its hashed Leaf is valid on the Merkle Tree. As such, the following operations can be performed on compressed NFTs: * [Mint a cNFT](https://developers.metaplex.com/smart-contracts/bubblegum-v2/mint-cnfts) with or without an associated collection. * [Transfer a cNFT](https://developers.metaplex.com/smart-contracts/bubblegum-v2/transfer-cnfts) . * [Update the data or collection of a cNFT](https://developers.metaplex.com/smart-contracts/bubblegum-v2/update-cnfts) . * [Burn a cNFT](https://developers.metaplex.com/smart-contracts/bubblegum-v2/burn-cnfts) . * [Delegate a cNFT](https://developers.metaplex.com/smart-contracts/bubblegum-v2/delegate-cnfts) . * [Verify and unverify a cNFT collection](https://developers.metaplex.com/smart-contracts/bubblegum-v2/collections) . * [Verify and unverify the creators of a cNFT](https://developers.metaplex.com/smart-contracts/bubblegum-v2/verify-creators) . * [Freeze and thaw a cNFT](https://developers.metaplex.com/smart-contracts/bubblegum-v2/freeze-cnfts) . * [Make a cNFT soulbound](https://developers.metaplex.com/smart-contracts/bubblegum-v2/freeze-cnfts#create-a-soulbound-c-nft) . Next steps ---------- Now that we know how compressed NFTs work at a high level and what's new in Bubblegum V2, we recommend checking out our [Getting Started](https://developers.metaplex.com/smart-contracts/bubblegum-v2/sdk) page which enumerates the various languages/frameworks that one can use to interact with compressed NFTs. Afterwards, the various [feature pages](https://developers.metaplex.com/smart-contracts/bubblegum-v2/create-trees) can be used to learn more about the specific operations that can be performed on cNFTs. Finally, [advanced guides](https://developers.metaplex.com/smart-contracts/bubblegum-v2/concurrent-merkle-trees) are also available to deepen your knowledge of cNFTs and Merkle Trees. Next [Metaplex DAS API RPCs →](https://developers.metaplex.com/solana/rpcs-and-das) --- # Genesis — Solana Token Launchpad for Fair Launches & Token Sales | Metaplex **Genesis** is a Solana token launchpad and smart contract for **Token Generation Events (TGE)**. Run a presale, fair launch, auction, or crowdsale with on-chain coordination for SPL token creation, token distribution, and fund collection. Choose Your Path * **No-code launch?** Use the [Metaplex token launchpad](https://www.metaplex.com/) to launch a token with no coding required * **Build your own launchpad?** Use the Genesis SDK to build a custom token launch platform or host a token sale on your own website * **New to Genesis?** Start with [Getting Started](https://developers.metaplex.com/smart-contracts/genesis/getting-started) to understand the flow * **Ready to build?** Jump to [Launch Pool](https://developers.metaplex.com/smart-contracts/genesis/launch-pool) or [Presale](https://developers.metaplex.com/smart-contracts/genesis/presale) What is Genesis? ---------------- Genesis is a decentralized token launch platform that provides on-chain infrastructure for launching SPL tokens on Solana. Whether you need to run a token sale, presale, or fair launch, Genesis handles: * **Token creation** with metadata (name, symbol, image) * **Fund collection** from participants (SOL deposits) * **Distribution** based on your chosen mechanism * **Time coordination** for deposit and claim windows Think of Genesis as a token launchpad smart contract that sits between you (the launcher) and your participants, ensuring fair, transparent, and automated token distribution — a modern on-chain alternative to centralized token sale platforms. Launch Mechanisms ----------------- Genesis supports three mechanisms that can be combined: | Mechanism | Price | Distribution | Best For | | --- | --- | --- | --- | | **[Launch Pool](https://developers.metaplex.com/smart-contracts/genesis/launch-pool)
** | Discovered at close | Proportional to deposit | Fair launches, community tokens, crowdsales | | **[Presale](https://developers.metaplex.com/smart-contracts/genesis/presale)
** | Fixed upfront | First-come-first-served | Token sales, known valuation | | **[Uniform Price Auction](https://developers.metaplex.com/smart-contracts/genesis/uniform-price-auction)
** | Clearing price | Highest bidders win | Large raises, institutional interest | ### Which Should I Use? **Launch Pool** - You want organic price discovery and fair token distribution. Similar to a crowdsale, everyone who deposits gets tokens proportional to their share. No one gets sniped. **Presale** - You know your valuation and want predictable pricing. Set a fixed price and let participants buy until the cap is reached. In Genesis, "presale" means tokens are sold immediately before initial trading — buyers receive tokens directly, not a future right to receive them. **Auction** - You want competitive bidding from larger participants. A structured auction approach best suited for established projects with institutional interest. Core Concepts ------------- ### Genesis Account The central coordinator for your launch. When you initialize a Genesis Account, it: * Creates your SPL token with metadata * Mints the total supply to escrow * Provides the foundation for adding distribution buckets ### Buckets Modular components that define how tokens and funds flow: | Type | Purpose | Examples | | --- | --- | --- | | **Inflow** | Collect SOL from users | Launch Pool, Presale | | **Outflow** | Receive funds for team/treasury | Unlocked Bucket | ### Time Conditions Every bucket has time windows that control when actions are allowed: * **Deposit window** - When users can deposit SOL * **Claim window** - When users can claim tokens Protocol Fees ------------- | Action | Fee | | --- | --- | | Deposit | 2% of deposit amount | | Withdraw | 2% of withdrawal amount | | Claim | Transaction fee only | No upfront costs. You only pay fees on funds raised. Program Information ------------------- | Network | Program ID | | --- | --- | | Mainnet | `GENSkbxvLc7iBQvEAJv3Y5wVMHGD3RjfCNwWgU8Tqgkc` | | Devnet | `GENSkbxvLc7iBQvEAJv3Y5wVMHGD3RjfCNwWgU8Tqgkc` | Security -------- After your launch completes, revoke token authorities to signal that no additional tokens can be minted: * **Mint authority** - Revoke to prevent new token minting * **Freeze authority** - Revoke to prevent token freezing See [Getting Started](https://developers.metaplex.com/smart-contracts/genesis/getting-started) for details on authority management. FAQ --- ### What is Genesis? Genesis is a Metaplex smart contract for Token Generation Events (TGE) on Solana. It provides on-chain infrastructure for presales, launch pools, and auctions with coordinated token creation and distribution. ### What launch mechanisms does Genesis support? Genesis supports three mechanisms: **Launch Pool** (proportional distribution with price discovery), **Presale** (fixed price), and **Uniform Price Auction** (bid-based with clearing price). ### How much does it cost to use Genesis? Genesis charges a 2% protocol fee on deposits. There are no upfront costs—you only pay Solana transaction fees plus the protocol fee on funds raised. ### Can I revoke token authorities after launch? Yes. Genesis provides `revokeMintAuthorityV2` and `revokeFreezeAuthorityV2` instructions to permanently revoke authorities. ### What's the difference between Launch Pool and Presale? **Presale** has a fixed price set upfront. **Launch Pool** discovers price organically—more deposits means higher implied price per token, with proportional distribution to all participants. ### Can I combine multiple launch mechanisms? Yes. Genesis uses a bucket system where you can add multiple inflow buckets and configure outflow buckets for treasury or vesting. Glossary -------- | Term | Definition | | --- | --- | | **Genesis Account** | Central coordinator that creates the token and manages all buckets | | **Bucket** | Modular component that defines token/SOL flow | | **Inflow Bucket** | Bucket that collects SOL from users | | **Outflow Bucket** | Bucket that receives funds via end behaviors | | **Launch Pool** | Deposit-based distribution where price is discovered at close | | **Presale** | Fixed-price sale at a predetermined rate | | **Quote Token** | The token users deposit (usually wSOL) | | **Base Token** | The token being launched and distributed | Next Steps ---------- 1. **[Getting Started](https://developers.metaplex.com/smart-contracts/genesis/getting-started) ** - Understand the Genesis flow 2. **[JavaScript SDK](https://developers.metaplex.com/smart-contracts/genesis/sdk/javascript) ** - Installation and setup 3. **[Launch Pool](https://developers.metaplex.com/smart-contracts/genesis/launch-pool) ** - Build a proportional distribution launch 4. **[Presale](https://developers.metaplex.com/smart-contracts/genesis/presale) ** - Build a fixed-price sale Next [Getting Started →](https://developers.metaplex.com/smart-contracts/genesis/getting-started) --- # Metaplex Core | Next-Gen NFT Standard for Solana Metaplex Core ("Core") is the **next-generation NFT standard** on Solana. It uses a **single-account design** that reduces minting costs by 80%+ compared to alternatives, while providing **enforced royalties**, **collection-level operations**, and a **flexible plugin system** for custom behaviors. What You'll Learn This overview covers: * What Metaplex Core is and why it exists * Key advantages over Token Metadata and other standards * Core concepts: Assets, Collections, and Plugins * How to get started building with Core Summary ------- **Metaplex Core** is a Solana NFT standard that replaces Token Metadata for most new projects. It offers the lowest minting costs, enforced royalties, and a plugin architecture for custom functionality. * Single-account design: ~0.0029 SOL per mint (vs 0.022 SOL for Token Metadata) * Enforced royalties by default with allowlist/denylist controls * Plugin system for staking, attributes, delegates, and custom behaviors * Collection-level operations: freeze, update royalties, or modify all assets at once Out of Scope ------------ This overview does not cover: fungible tokens (use SPL Token), Token Metadata migration paths, or detailed plugin implementation. See specific pages for those topics. Quick Start ----------- **Jump to:** [Getting Started](https://developers.metaplex.com/smart-contracts/core#next-steps) · [Key Advantages](https://developers.metaplex.com/smart-contracts/core#introduction) · [FAQ](https://developers.metaplex.com/smart-contracts/core#faq) · [Glossary](https://developers.metaplex.com/smart-contracts/core#glossary) 1. Install the SDK: `npm install @metaplex-foundation/mpl-core` 2. Create an Asset: [Creating Assets guide](https://developers.metaplex.com/smart-contracts/core/create-asset) 3. Add plugins: [Plugins overview](https://developers.metaplex.com/smart-contracts/core/plugins) 4. Query with DAS: [Fetching Assets](https://developers.metaplex.com/smart-contracts/core/fetch) [Getting Started](https://developers.metaplex.com/smart-contracts/core/sdk) ---------------------------------------------------------------------------- Find the language or library of your choice and get started with digital assets on Solana. [API Reference](https://mpl-core.typedoc.metaplex.com/) -------------------------------------------------------- Looking for something specific? Check our API References. [Differences from Token Metadata](https://developers.metaplex.com/smart-contracts/core/tm-differences) ------------------------------------------------------------------------------------------------------- Coming from Token Metadata? See what's changed and what's new. [Try Core in a UI](https://core.metaplex.com/) ----------------------------------------------- Mint a Core Asset yourself using our web interface. Introduction ------------ Metaplex Core is the recommended NFT standard for new projects on Solana. Compared to Token Metadata and other standards, Core provides: ### Cost Efficiency | Standard | Mint Cost | Compute Units | | --- | --- | --- | | **Metaplex Core** | ~0.0029 SOL | ~17,000 CU | | Token Metadata | ~0.022 SOL | ~205,000 CU | | Token Extensions | ~0.0046 SOL | ~85,000 CU | ### Key Advantages * **Single Account Design**: Core uses one account per asset instead of multiple (mint + metadata + token account). This reduces costs and simplifies development. * **Enforced Royalties**: The [Royalties plugin](https://developers.metaplex.com/smart-contracts/core/plugins/royalties) enforces creator royalties by default with allowlist/denylist controls. * **Collection-Level Operations**: Update royalties, freeze assets, or modify metadata for an entire collection in a single transaction. * **Plugin Architecture**: Add custom behaviors to assets via plugins: * [Freeze Delegate](https://developers.metaplex.com/smart-contracts/core/plugins/freeze-delegate) - Allow others to freeze/unfreeze * [Burn Delegate](https://developers.metaplex.com/smart-contracts/core/plugins/burn-delegate) - Allow others to burn * [Attributes](https://developers.metaplex.com/smart-contracts/core/plugins/attribute) - On-chain key/value data (auto-indexed by DAS) * [Transfer Delegate](https://developers.metaplex.com/smart-contracts/core/plugins/transfer-delegate) - Allow others to transfer * And many more in the [Plugins section](https://developers.metaplex.com/smart-contracts/core/plugins) * **DAS Indexing**: All major [RPC providers supporting DAS](https://developers.metaplex.com/solana/rpcs-and-das) already index Core assets. Core Concepts ------------- ### Assets An **Asset** is a single on-chain account representing an NFT. Unlike Token Metadata (which uses 3+ accounts), Core Assets contain ownership, metadata URI, and plugin data in one account. See: [What is an Asset?](https://developers.metaplex.com/smart-contracts/core/what-is-an-asset) ### Collections A **Collection** is a Core account that groups related Assets. Collections can have their own plugins that apply to all member Assets. Collection-level royalties, for example, apply to every Asset in the collection unless overridden. See: [Collections](https://developers.metaplex.com/smart-contracts/core/collections) ### Plugins **Plugins** are modular extensions that add behavior to Assets or Collections. They hook into lifecycle events (create, transfer, burn) to enforce rules or store data. See: [Plugins Overview](https://developers.metaplex.com/smart-contracts/core/plugins) Quick Reference --------------- ### Program IDs | Program | Address | | --- | --- | | MPL Core | `CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d` | | MPL Core (Devnet) | `CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d` | ### SDK Packages | Language | Package | | --- | --- | | JavaScript/TypeScript | `@metaplex-foundation/mpl-core` | | Rust | `mpl-core` | Next Steps ---------- 1. **Choose your SDK**: Visit [Getting Started](https://developers.metaplex.com/smart-contracts/core/sdk) to install the JavaScript or Rust SDK 2. **Create your first Asset**: Follow the [Creating Assets](https://developers.metaplex.com/smart-contracts/core/create-asset) guide 3. **Explore plugins**: See available behaviors in [Plugins](https://developers.metaplex.com/smart-contracts/core/plugins) 4. **Migrate from Token Metadata**: Review [Differences from Token Metadata](https://developers.metaplex.com/smart-contracts/core/tm-differences) Please note that certain Core instructions require protocol fees. Review the [Protocol Fees](https://developers.metaplex.com/protocol-fees) page for current information. FAQ --- ### What is Metaplex Core? Metaplex Core is a next-generation NFT standard on Solana that uses a single-account design for lower costs, enforced royalties, and a flexible plugin system. It's the recommended standard for new NFT projects. ### How is Core different from Token Metadata? Core uses one account per asset (vs 3+ for Token Metadata), costs ~80% less to mint, has lower compute usage, and includes built-in royalty enforcement. Token Metadata is considered legacy for new projects. See [Differences from Token Metadata](https://developers.metaplex.com/smart-contracts/core/tm-differences) for a detailed comparison. ### Can I migrate from Token Metadata to Core? Core Assets and Token Metadata NFTs are separate standards. There's no automatic migration. New projects should use Core; existing Token Metadata collections continue to work. ### Does Core support royalties? Yes. Core has a [Royalties plugin](https://developers.metaplex.com/smart-contracts/core/plugins/royalties) that enforces royalties by default. You can set basis points, creator splits, and allowlist/denylist rules for marketplaces. ### What are plugins? Plugins are modular extensions that add behavior to Core Assets or Collections. Examples include Freeze Delegate (allow freezing), Attributes (on-chain data), and Royalties (creator payments). ### How much does it cost to mint a Core Asset? Approximately 0.0029 SOL per base asset, compared to ~0.022 SOL for Token Metadata. This makes Core ~80% cheaper for minting. See [Differences from Token Metadata](https://developers.metaplex.com/smart-contracts/core/tm-differences) for more details. ### Which RPC providers support Core? All major RPC providers supporting DAS (Digital Asset Standard) index Core assets. See [RPC Providers](https://developers.metaplex.com/solana/rpcs-and-das) for a current list. ### Can I use Core for gaming assets? Yes. Core's plugin system makes it ideal for gaming: use Attributes for on-chain stats, Freeze Delegate for locking items, and Transfer Delegate for marketplace integration. Glossary -------- | Term | Definition | | --- | --- | | **Asset** | A single Core on-chain account representing an NFT with ownership, metadata, and plugins | | **Collection** | A Core account that groups related Assets and can apply collection-wide plugins | | **Plugin** | A modular extension that adds behavior to Assets or Collections (royalties, freeze, attributes) | | **DAS** | Digital Asset Standard - the API specification for querying indexed NFT data | | **Basis Points** | Royalty percentage in hundredths of a percent (500 = 5%) | | **Delegate** | An account authorized to perform specific actions on an Asset without owning it | | **CPI** | Cross-Program Invocation - calling the Core program from another Solana program | | **URI** | The off-chain metadata URL pointing to a JSON file with name, image, and attributes | Next [What is an Asset? →](https://developers.metaplex.com/smart-contracts/core/what-is-an-asset) --- # Overview | Core Candy Machine The Metaplex Protocol **Candy Machine** is the leading minting and distribution program for fair NFT collection launches on Solana. With the introduction of the `Metaplex Core Protocol` simplifying the NFT process on Solana it was only fitting for a Core edition of the Candy Machine to come to the masses. Much like its name suggests, you can think of a Candy Machine as a temporary structure which is first loaded by creators and then unloaded by buyers. It allows creators to bring their digital assets onchain in a secure and customizable way. The name refers to the vending machines that dispense candy for coins via a mechanical crank. In this case the candy are NFTs and the payment is SOL or a SPL token. [Getting Started](https://developers.metaplex.com/smart-contracts/core-candy-machine/sdk) ------------------------------------------------------------------------------------------ Find the language or library of your choice and get started with Candy Machines. [CLI Commands](https://developers.metaplex.com/dev-tools/cli/cm) ----------------------------------------------------------------- Create and manage candy machines using the Metaplex CLI with interactive wizard. [API reference](https://mpl-core-candy-machine.typedoc.metaplex.com/) ---------------------------------------------------------------------- Check out the Javascript API docs. [API reference](https://docs.rs/mpl-core-candy-machine-core/) -------------------------------------------------------------- Check out the Rust API docs. This documentation refers to the latest iteration of Candy Machine known as Core Candy Machine. It allows minting [Core](https://developers.metaplex.com/smart-contracts/core) Assets. If you want to mint Metaplex Token Metadata NFTs [please refer to Candy Machine V3 instead](https://developers.metaplex.com/smart-contracts/candy-machine) . Next [Javascript SDK →](https://developers.metaplex.com/smart-contracts/core-candy-machine/sdk/javascript) --- # Overview | Bubblegum New Bubblegum version We recommend using [Bubblegum v2](https://developers.metaplex.com/smart-contracts/bubblegum-v2) to allow more flexibility and features. Please note that certain Bubblegum instructions will require protocol fees. Please review the [Protocol Fees](https://developers.metaplex.com/protocol-fees) page for up-to-date information. Bubblegum is the Metaplex Protocol program for creating and interacting with compressed NFTs (cNFTs) on Solana. Compressed NFTs make it possible to scale the creation of NFTs to new orders of magnitude by rethinking the way we store data onchain. [Getting Started](https://developers.metaplex.com/smart-contracts/bubblegum/sdk) --------------------------------------------------------------------------------- Find the language or library of your choice and get started with compressed NFTs. [API reference](https://mpl-bubblegum.typedoc.metaplex.com/) ------------------------------------------------------------- Looking for something specific? Have a peak at our API References and find your answer. Introduction ------------ As NFTs have flourished on the Solana blockchain, there's been an increasing need for NFTs to be as ubiquitous as any digital asset on the Internet: every single item in your game's inventory, proof-of-engagement in your favorite consumer app, or even a profile for every human on the planet. So far, though, these types of products have been held back by the cost of rent for NFTs on Solana, which is relatively cheap but scales linearly. Compression for NFTs drastically reduces the cost of onchain storage of NFTs to enable creators to be as expressive with the technology as they wish. Launching a cNFT project on Solana using Merkle trees can be incredibly cost-effective, with costs starting as low as: | Number of cNFTs | Storage Cost | Transaction Cost | Total Cost | Cost per cNFT | | --- | --- | --- | --- | --- | | 10,000 | 0.2222 | 0.05 | 0.2722 | 0.000027222 | | 100,000 | 0.2656 | 0.5 | 0.7656 | 0.000007656 | | 1,000,000 | 0.3122 | 5 | 5.3122 | 0.000005312 | | 10,000,000 | 0.4236 | 50 | 50.4236 | 0.000005042 | | 100,000,000 | 7.2205 | 500 | 507.2205 | 0.000005072 | | 1,000,000,000 | 7.2205 | 5,000 | 5007.2205 | 0.000005007 | These compressed NFTs can be transferred, delegated, and even decompressed into regular NFTs for interoperability with existing smart contracts. Merkle Trees, leaves and proofs ------------------------------- Compressed NFTs only exist in the context of a **Merkle Tree**. We explain [in a dedicated advanced guide](https://developers.metaplex.com/smart-contracts/bubblegum-v2/concurrent-merkle-trees) what Merkle Trees are but, for the sake of this overview, you can think of a Merkle Tree as a collection of hashes that we call **Leaves**. Each Leaf is obtained by [hashing the data of the compressed NFT](https://developers.metaplex.com/smart-contracts/bubblegum-v2/hashed-nft-data) . For each Leaf in the Merkle Tree, one can provide a list of hashes — called a **Proof** — that enables anyone to verify that the given Leaf is part of that tree. Whenever a compressed NFT is updated or transferred, its associated Leaf will change and so will its Proof. Press enter or space to select a node.You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel. Press enter or space to select an edge. You can then press delete to remove it or escape to cancel. As such, Merkle Trees act as an onchain structure that allows anyone to verify a given compressed NFT exist. They do this without storing any NFT data which makes them so scalable. Which brings us to an important question: where is the NFT data stored? Metaplex DAS API ---------------- When we mint a new compressed NFT, its data is hashed and added as a new Leaf in a Merkle Tree. But there's more. Additionally, the entire NFT data is stored in the transaction that created the compressed NFT. Similarly, when a compressed NFT is updated, its updated data is, once again, saved on the transaction as a changelog. So, whilst there aren't any accounts keeping track of that data, one can look at all previous transactions in the ledger and find that information. Press enter or space to select a node.You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel. Press enter or space to select an edge. You can then press delete to remove it or escape to cancel. Crawling through millions of transactions every time just to fetch the data of one NFT is admittedly not the best user experience. Therefore, compressed NFTs rely on some RPCs to index that information in real time to abstract this away from the end-user. We call the resulting RPC API, which enables fetching compressed NFTs, **the Metaplex DAS API**. Note that not all RPCs support the DAS API. As such, you may be interested in the ["Metaplex DAS API RPCs"](https://developers.metaplex.com/solana/rpcs-and-das) page to select an appropriate RPC when using compressed NFTs in your application. We talk about this in more detail in our advanced ["Storing and indexing NFT data"](https://developers.metaplex.com/smart-contracts/bubblegum-v2/stored-nft-data) guide. Features -------- Even though NFT data does not live inside accounts, it is still possible to execute a variety of operations on compressed NFTs. This is possible by requesting the current NFT data and ensuring its hashed Leaf is valid on the Merkle Tree. As such, the following operations can be performed on compressed NFTs: * [Mint a cNFT](https://developers.metaplex.com/smart-contracts/bubblegum/mint-cnfts) with or without an associated collection. * [Transfer a cNFT](https://developers.metaplex.com/smart-contracts/bubblegum/transfer-cnfts) . * [Update the data of a cNFT](https://developers.metaplex.com/smart-contracts/bubblegum/update-cnfts) . * [Burn a cNFT](https://developers.metaplex.com/smart-contracts/bubblegum/burn-cnfts) . * [Decompress a cNFT into a regular NFT](https://developers.metaplex.com/smart-contracts/bubblegum/decompress-cnfts) . Note that this enables interoperability with existing smart contracts but creates onchain accounts with rent fees. * [Delegate a cNFT](https://developers.metaplex.com/smart-contracts/bubblegum/delegate-cnfts) . * [Verify and unverify a cNFT collection](https://developers.metaplex.com/smart-contracts/bubblegum/verify-collections) . * [Verify and unverify the creators of a cNFT](https://developers.metaplex.com/smart-contracts/bubblegum/verify-creators) . Next steps ---------- Now that we know how compressed NFTs work at a high level, we recommend checking out our [Getting Started](https://developers.metaplex.com/smart-contracts/bubblegum/getting-started) page which enumerates the various languages/frameworks that one can use to interact with compressed NFTs. Afterward, the various [feature pages](https://developers.metaplex.com/smart-contracts/bubblegum/create-trees) can be used to learn more about the specific operations that can be performed on cNFTs. Finally, [advanced guides](https://developers.metaplex.com/smart-contracts/bubblegum-v2/concurrent-merkle-trees) are also available to deepen your knowledge of cNFTs and Merkle Trees. Next [Metaplex DAS API RPCs →](https://developers.metaplex.com/solana/rpcs-and-das) --- # Overview | DAS API The Metaplex Digital Asset Standard (DAS) API represents a unified interface for interacting with digital assets on Solana, supporting all three Metaplex standards Core, Token Metadata, compressed (Bubblegum) assets. This allows easy access and filtering of Asset Data. This is especially useful for: * Core Assets, where the Plugins can be automatically derived and include the plugin data of the collection. * Compressed NFT, where the detailed account data is not stored onchain, but in data stores managed by RPC providers. * Fetching Data with less Calls because the Off Chain Metadata is also indexed through the standard. The API defines a set of methods that RPCs implement in order to provide asset data. In the majority of cases, the data is indexed using Metaplex Digital Asset RPC infrastructure. Core Extension -------------- In addition to the general DAS SDK an extension for [MPL Core](https://developers.metaplex.com/smart-contracts/core) has been created that directly returns you the correct types to further use with the MPL Core SDKs. It also automatically derives the plugins in assets inherited from the collection and provides functions for [DAS-to-Core type conversions](https://developers.metaplex.com/dev-tools/das-api/core-extension/convert-das-asset-to-core) . [Getting Started](https://developers.metaplex.com/dev-tools/das-api/getting-started) ------------------------------------------------------------------------------------- Find the language or library of your choice and get started with essential programs. [Methods](https://developers.metaplex.com/dev-tools/das-api/methods) --------------------------------------------------------------------- DAS API methods for fetching data. [MPL Core Extension](https://developers.metaplex.com/dev-tools/das-api/core-extension) --------------------------------------------------------------------------------------- Get and parse MPL Core assets easily Next [Getting Started →](https://developers.metaplex.com/dev-tools/das-api/getting-started) --- # Security | Developer Hub Reporting a Vulnerability ------------------------- **Please do not open a public GitHub Issue to report the vulnerability**. Instead, please email [\[email protected\]](https://developers.metaplex.com/cdn-cgi/l/email-protection) . You should receive a response within 24-48 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: * Type of issue (e.g. buffer overflow, missing ownership check, cross-site scripting, etc.) * Full paths of source file(s) related to the manifestation of the issue * The location of the affected source code (tag/branch/commit or direct URL) * Any special configuration required to reproduce the issue * Step-by-step instructions to reproduce the issue * Proof-of-concept or exploit code (if possible) * Impact of the issue, including how an attacker might exploit the issue This information will help us triage your report more quickly. You may also be eligible for a bounty. More details can be found [on the Metaplex Bounty Program page](https://www.metaplex.com/bounty-program) . Audits ------ Ongoing automated and manual security audits are routinely performed by our audit partners [Sec3](https://www.sec3.dev/) , [Accretion](https://www.accretion.fi/) , and [OtterSec](https://osec.io/) . Automated audits are performed for every PR and security issues must be resolved before merging into the main branch. Manual ongoing audits are initiated for changes above a specific threshold and security issues must be resolved before merging into the main branch. [OShield](https://www.oshield.xyz/) (formerly MadShield) is responsible for many of our historical audits. Large one-off audits are also performed when there are large changes to the code or functionality as detailed below. | Protocol | Last major one-off audit date | | --- | --- | | Core | 2024-05-06 | | Token Metadata | 2025-01-21 | | Inscriptions | 2024-01-16 | | Bubblegum/Compression | 2025-05-12 | | Trifle/Fusion | 2023-04-13 | | Candy Machine V3 | 2022-11-01 | | Candy Machine V2 | 2022-11-01 | | Auction House | 2022-10-24 | | Gumdrop | 2022-05-16 | We do not have ongoing automated nor manual security audits that are routinely performed by our audit partners for our developer tools. However, audits may be ordered, facilitated, and paid for by our community of 3rd party Solana ecosystem developers or entities of their own accord. | Developer Tools | Last audit date | | --- | --- | | Sugar CLI\* | 2022-08-26 | (\*) Audited by [OtterSec](https://osec.io/) --- # Metaplex Official Links | Developer Hub Websites -------- | Name | Link | | --- | --- | | Main Website | [Main Website](https://metaplex.com/) | | Documentation | [Documentation](https://developers.metaplex.com/) | | Github | [Github](https://github.com/metaplex-foundation) | Twitter ------- | Name | Handle | Link | | --- | --- | --- | | Metaplex | @metaplex | [Metaplex](https://twitter.com/metaplex) | | Metaplex Status Updates | @metaplexstatus | [Metaplex Status Updates](https://twitter.com/metaplexstatus) | | Metaplex Foundation | @metaplexfndn | [Metaplex Foundation](https://twitter.com/metaplexfndn) | Instagram --------- | Name | Handle | Link | | --- | --- | --- | | Metaplex | @metaplex | [Metaplex](https://instagram.com/metaplex) | StackExchange ------------- | Tagged | Link | | --- | --- | | @metaplex | [View {tagged} questions](https://solana.stackexchange.com/questions/tagged/metaplex) | StackOverflow ------------- | Tagged | Link | | --- | --- | | @metaplex | [View {tagged} questions](https://stackoverflow.com/questions/tagged/metaplex) | Programs -------- | Name | Program ID | Github | Documentation | | --- | --- | --- | --- | | Token Metadata | metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s | [GitHub](https://github.com/metaplex-foundation/mpl-token-metadata) | [Docs](https://developers.metaplex.com/smart-contracts/token-metadata) | | Core | CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d | [GitHub](https://github.com/metaplex-foundation/mpl-core) | [Docs](https://developers.metaplex.com/smart-contracts/core) | | Bubblegum v2 | BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY | [GitHub](https://github.com/metaplex-foundation/mpl-bubblegum) | [Docs](https://developers.metaplex.com/smart-contracts/bubblegum-v2) | | Bubblegum | BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY | [GitHub](https://github.com/metaplex-foundation/mpl-bubblegum) | [Docs](https://developers.metaplex.com/smart-contracts/bubblegum) | | Core Candy Machine | CMACYFENjoBMHzapRXyo1JZkVS6EtaDDzkjMrmQLvr4J | [GitHub](https://github.com/metaplex-foundation/mpl-core-candy-machine/tree/main/programs/candy-machine-core) | [Docs](https://developers.metaplex.com/smart-contracts/core-candy-machine) | | Core Candy Guard | CMAGAKJ67e9hRZgfC5SFTbZH8MgEmtqazKXjmkaJjWTJ | [GitHub](https://github.com/metaplex-foundation/mpl-core-candy-machine/tree/main/programs/candy-guard) | [Docs](https://developers.metaplex.com/smart-contracts/core-candy-machine/guards) | | Candy Machine v3 | CndyV3LdqHUfDLmE5naZjVN8rBZz4tqhdefbAnjHG3JR | [GitHub](https://github.com/metaplex-foundation/mpl-candy-machine/tree/main/programs/candy-machine-core) | [Docs](https://developers.metaplex.com/smart-contracts/candy-machine) | | Candy Guard | Guard1JwRhJkVH6XZhzoYxeBVQe872VH6QggF4BWmS9g | [GitHub](https://github.com/metaplex-foundation/mpl-candy-machine/tree/main/programs/candy-guard) | [Docs](https://developers.metaplex.com/smart-contracts/candy-machine/guards) | | Genesis | GENSxbxqAy7G1fHDtNwbHsMUThb9vpYqoJJrXBbpLZn8 | — | [Docs](https://developers.metaplex.com/smart-contracts/genesis) | | MPL-Hybrid | MPL4o4wMzndgh8T1NVDxELQCj5UQfYTYEkabX3wNKtb | [GitHub](https://github.com/metaplex-foundation/mpl-hybrid) | [Docs](https://developers.metaplex.com/smart-contracts/mpl-hybrid) | | Fusion (Trifle) | trifMWutwBxkSuatmpPVnEe7NoE3BJKgjVi8sSyoXWX | [GitHub](https://github.com/metaplex-foundation/mpl-trifle) | [Docs](https://developers.metaplex.com/smart-contracts/fusion) | | Token Auth Rules | auth9SigNpDKz4sJJ1DfCTuZrZNSAgh9sFD3rboVmgg | [GitHub](https://github.com/metaplex-foundation/mpl-token-auth-rules) | [Docs](https://developers.metaplex.com/smart-contracts/token-auth-rules) | | Hydra | hyDQ4Nz1eYyegS6JfenyKwKzYxRsCWCriYSAjtzP4Vg | [GitHub](https://github.com/metaplex-foundation/mpl-hydra) | [Docs](https://developers.metaplex.com/smart-contracts/hydra) | | Inscriptions | 1NSCRfGeyo7wPUazGbaPBUsTM49e1k2aXewHGARfzSo | [GitHub](https://github.com/metaplex-foundation/mpl-inscription) | [Docs](https://developers.metaplex.com/smart-contracts/inscription) | | MPL System Extras | SysExL2WDyJi9aRZrXorrjHJut3JwHQ7R9bTyctbNNG | [GitHub](https://github.com/metaplex-foundation/mpl-toolbox) | [Docs](https://developers.metaplex.com/dev-tools/umi/toolbox) | | MPL Token Extras | TokExjvjJmhKaRBShsBAsbSvEWMA1AgUNK7ps4SAc2p | [GitHub](https://github.com/metaplex-foundation/mpl-toolbox) | [Docs](https://developers.metaplex.com/dev-tools/umi/toolbox) | | Auction House | hausS13jsjafwWwGqZTUQRmWyvyxn9EQpqMwV1PBBmk | [GitHub](https://github.com/metaplex-foundation/metaplex-program-library/tree/master/auction-house) | [Docs](https://developers.metaplex.com/legacy-documentation/auction-house) | | Auctioneer | neer8g6yJq2mQM6KbnViEDAD4gr3gRZyMMf4F2p3MEh | [GitHub](https://github.com/metaplex-foundation/metaplex-program-library/tree/master/auctioneer) | [Docs](https://developers.metaplex.com/legacy-documentation/auction-house/auctioneer) | | Gumdrop | gdrpGjVffourzkdDRrQmySw4aTHr8a3xmQzzxSwFD1a | [GitHub](https://github.com/metaplex-foundation/gumdrop) | [Docs](https://developers.metaplex.com/legacy-documentation/gumdrop) | Tokens and NFTs --------------- | Name | ID | | --- | --- | | MPLX Token | METAewgxyPbgwsseH8T16a39CQ5VyVxZi9zXiDPY18m | | Metaplex Whitepaper NFT (collection address) | 9q2Ejt1Qubk5t4f3xXaiwRtvjhHrEK8r9EYsH6gwnt39 | | Candy Studio NFT (collection address) | 3NauNKfqAbQVhAJyv464Tq14jynV6THSNiGxhf7W6fP9 | | MPLX Token Launch Party NFT (collection address) | BodU7rcs75cf3J94EBK7vKuxoepgz6ayb2t7oJDbXtWX | Metaplex Rulesets ----------------- To be used with the pNFTs Auth Rules. | Name | ID | | --- | --- | | Metaplex Foundation Rule Set | eBJLFYPxJmMGKuFwpDWkzxZeUrad92kZRC5BJLpzyT9 | | Compatibility Rule Set | AdH2Utn6Fus15ZhtenW4hZBQnvtLgM1YCW2MfVp7pYS5 | --- # Overview | Umi A Solana Framework for JavaScript clients. Umi is a modular framework for building and using JavaScript clients for Solana programs. It provides a zero-dependency library that defines a set of core interfaces that libraries can rely on without being tied to a specific implementation. It is then up to the end-user to choose the implementation that best suits their needs. Umi also provides a set of default implementations and bundles that can be used out of the box allowing developers to get started quickly. [Getting Started](https://developers.metaplex.com/dev-tools/umi/getting-started) --------------------------------------------------------------------------------- Find the language or library of your choice and get started essentials programs. [API reference](https://umi.typedoc.metaplex.com/) --------------------------------------------------- Looking for something specific? Have a peak at our API References and find your answer. Next [Getting Started →](https://developers.metaplex.com/dev-tools/umi/getting-started) --- # Overview | Inscription The Metaplex Inscription Program allows you to write data directly to Solana, using the blockchain as a method of data storage. The Inscription program also allows for this data storage to be optionally linked to an NFT. In this overview, we explain how this program works and how we can leverage its various features at a high level. [Getting Started](https://developers.metaplex.com/smart-contracts/inscription/getting-started) ----------------------------------------------------------------------------------------------- Find the language or library of your choice and get started with digital assets on Solana. [API reference](https://mpl-inscription.typedoc.metaplex.com/) --------------------------------------------------------------- Looking for something specific? Have a peak at our API References and find your answer. Introduction ------------ NFT JSON data and Images have historically been stored on decentralized storage providers like Arweave or IPFS. The Inscription program introduces Solana as another option for NFT data storage, allowing you to write that data directly to the chain. The Metaplex Inscription program introduces the novel use case of all of an NFT's associated data now being stored on Solana. This enables many new use cases such as Solana programs with trait-based bids, dynamic images that are updated via programs, or even RPG game state onchain. There are two different kinds of Inscriptions: 1. Inscriptions **[attached to NFT Mints](https://developers.metaplex.com/smart-contracts/inscription#inscriptions-attached-to-nft-mints) ** - NFT data is written to the chain instead or in addition to off chain storage 2. Inscriptions as **[storage providers](https://developers.metaplex.com/smart-contracts/inscription#inscriptions-as-storage-provider) ** - Write arbitrary data to the chain ### Inscriptions attached to NFT Mints Inscriptions can be used in addition to off chain storage like Arweave, where the metadata JSON and the media is stored, or can be completely replace those off chain storage using the [Inscription Gateway](https://developers.metaplex.com/smart-contracts/inscription#inscription-gateway) . In both cases the same process to create the inscription is used. When using the gateway the only difference is the URI used in the onchain metadata. Read more on this in the [Gateway section](https://developers.metaplex.com/smart-contracts/inscription#inscription-gateway) . When storing the NFT Metadata onchain three inscription accounts are used: 1. `inscriptionAccount` which stores the JSON Metadata. 2. `inscriptionMetadata` which stores the metadata of the inscription 3. `associatedInscriptionAccount` which is storing the media / image. Press enter or space to select a node.You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel. Press enter or space to select an edge. You can then press delete to remove it or escape to cancel. The below script creates both of these Accounts for you and points the newly minted NFT to the Metaplex gateway. With this your NFT is completely onchain. Inscribe Data for new NFT using the Gateway JavaScript ``const umi = await createUmi() umi.use(mplTokenMetadata()) umi.use(mplInscription()) // Create and mint the NFT to be inscribed. const mint = generateSigner(umi) const inscriptionAccount = await findMintInscriptionPda(umi, { mint: mint.publicKey, }) await createV1(umi, { mint, name: 'My NFT', uri: `https://igw.metaplex.com/devnet/${inscriptionAccount[0]}`, sellerFeeBasisPoints: percentAmount(5.5), tokenStandard: TokenStandard.NonFungible, }).sendAndConfirm(umi) await mintV1(umi, { mint: mint.publicKey, tokenStandard: TokenStandard.NonFungible, }).sendAndConfirm(umi) const inscriptionMetadataAccount = await findInscriptionMetadataPda(umi, { inscriptionAccount: inscriptionAccount[0], }) let builder = new TransactionBuilder() // We initialize the Inscription and create the account where the JSON will be stored. builder = builder.add( initializeFromMint(umi, { mintAccount: mint.publicKey, }) ) // And then write the JSON data for the NFT to the Inscription account. builder = builder.add( writeData(umi, { inscriptionAccount: inscriptionAccount[0], inscriptionMetadataAccount, value: Buffer.from( '{"description": "A bread! But onchain!", "external_url": "https://breadheads.io"}' ), associatedTag: null, offset: 0, }) ) // We then create the associated Inscription that will contain the image. const associatedInscriptionAccount = findAssociatedInscriptionPda(umi, { associated_tag: 'image', inscriptionMetadataAccount, }) builder = builder.add( initializeAssociatedInscription(umi, { inscriptionMetadataAccount, associatedInscriptionAccount, associationTag: 'image', }) ) await builder.sendAndConfirm(umi, { confirm: { commitment: 'finalized' } }) // Open the image file to fetch the raw bytes. const imageBytes: Buffer = await fs.promises.readFile('bread.png') // And write the image. const chunkSize = 800 for (let i = 0; i < imageBytes.length; i += chunkSize) { const chunk = imageBytes.slice(i, i + chunkSize) await writeData(umi, { inscriptionAccount: associatedInscriptionAccount, inscriptionMetadataAccount, value: chunk, associatedTag: 'image', offset: i, }).sendAndConfirm(umi) }`` ### Inscriptions as a Storage Provider In addition to the usage with NFT Mints Inscriptions can also be used to store arbitrary data up to 10 MB onchain. An unlimited number of [Associated Inscriptions](https://developers.metaplex.com/smart-contracts/inscription#associated-inscription-accounts) can be created. This can be useful when writing an onchain game that needs to store JSON data, storing text onchain, or storing any program-related data that's not an NFT. Press enter or space to select a node.You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel. Press enter or space to select an edge. You can then press delete to remove it or escape to cancel. The following example shows how to write NFT JSON data to an Inscription in three different transactions to avoid the 1280 byte transaction size limit. Find the rank of a specific NFT inscription JavaScript `const inscriptionAccount = generateSigner(umi) const inscriptionMetadataAccount = await findInscriptionMetadataPda(umi, { inscriptionAccount: inscriptionAccount.publicKey, }) let builder = new TransactionBuilder() builder = builder.add( initialize(umi, { inscriptionAccount, }) ) builder = builder.add( writeData(umi, { inscriptionAccount: inscriptionAccount.publicKey, inscriptionMetadataAccount, value: Buffer.from('{"description": "A bread! But onchain!"'), associatedTag: null, offset: 0, }) ) builder = builder.add( writeData(umi, { inscriptionAccount: inscriptionAccount.publicKey, inscriptionMetadataAccount, value: Buffer.from(', "external_url":'), associatedTag: null, offset: '{"description": "A bread! But onchain!"'.length, }) ) builder = builder.add( writeData(umi, { inscriptionAccount: inscriptionAccount.publicKey, inscriptionMetadataAccount, value: Buffer.from(' "https://breadheads.io"}'), associatedTag: null, offset: '{"description": "A bread! But onchain!", "external_url":'.length, }) ) await builder.sendAndConfirm(umi, { confirm: { commitment: 'finalized' } })` Associated Inscription Accounts ------------------------------- The [Metaplex JSON standards](https://developers.metaplex.com/smart-contracts/token-metadata/token-standard) include the option of linking associated files to a token via the files properties in the JSON schemas. The Inscription program introduces a new method of associating additional data using the power of PDAs! A PDA is derived from the Inscription and an **Association Tag**, resulting in a programmatic way to derive additional inscribed data, rather that requiring expensive JSON deserialization and parsing. Inscription Gateway ------------------- Together with the [Inscription Gateway](https://github.com/metaplex-foundation/inscription-gateway) you can use the normal Token Metadata Standard and just point the URI to the gateway which again reads your data directly from chain without all tools like wallets and explorers reading the data have to read it any differently than NFTs are read usually. You can either use the gateway that is hosted by Metaplex using the following URL structure: `https://igw.metaplex.com//`, e.g. [view this example on the Inscription Gateway](https://igw.metaplex.com/devnet/Fgf4Wn3wjVcLWp5XnMQ4t4Gpaaq2iRbc2cmtXjrQd5hF) or host the gateway yourself with a custom URL. Inscription Rank ---------------- The Inscription Rank is the unique number of each inscription. This number represents a sequential, global ranking of all Metaplex Inscriptions in existence based on the total Inscription count at the time of creation. Inscription Rank is managed through a parallelized counter that is explained further in [Inscription Sharding](https://developers.metaplex.com/smart-contracts/inscription/sharding) . To find the `inscriptionRank` of your Inscription you need to fetch the `inscriptionMetadata` Account and read the `inscriptionRank` `bigint`: Find the rank of a specific NFT inscription JavaScript `const inscriptionAccount = await findMintInscriptionPda(umi, { mint: mint.publicKey, }) const inscriptionMetadataAccount = await findInscriptionMetadataPda(umi, { inscriptionAccount, }) const { inscriptionRank } = await fetchInscriptionMetadata( umi, inscriptionMetadataAccount )` When creating your inscriptions you should always use a random shard to avoid write locks. You can just calculate the random number like this: Find random shard JavaScript `const randomShard = Math.floor(Math.random() * 32)` The total amount of Metaplex Inscriptions on Solana can be calculated like this: Fetch total Inscription amount JavaScript `import { fetchAllInscriptionShard, findInscriptionShardPda, } from '@metaplex-foundation/mpl-inscription' const shardKeys = [] for (let shardNumber = 0; shardNumber < 32; shardNumber += 1) { shardKeys.push(findInscriptionShardPda(umi, { shardNumber })) } const shards = await fetchAllInscriptionShard(umi, shardKeys) let numInscriptions = 0 shards.forEach((shard) => { const rank = 32 * Number(shard.count) + shard.shardNumber numInscriptions = Math.max(numInscriptions, rank) })` And a lot more -------------- Whilst this provides a good overview of the Inscription program and what it has to offer, there’s still a lot more that can be done with it. The other pages of this documentation aim to document it further and explain significant features in their own individual pages. * [Initialize](https://developers.metaplex.com/smart-contracts/inscription/initialize) * [Write](https://developers.metaplex.com/smart-contracts/inscription/write) * [Fetch](https://developers.metaplex.com/smart-contracts/inscription/fetch) * [Clear](https://developers.metaplex.com/smart-contracts/inscription/clear) * [Close](https://developers.metaplex.com/smart-contracts/inscription/close) * [Authorities](https://developers.metaplex.com/smart-contracts/inscription/authority) * [Inscription Gateway](https://github.com/metaplex-foundation/inscription-gateway) Next [Getting Started →](https://developers.metaplex.com/smart-contracts/inscription/getting-started) --- # Shank | Metaplex Developer Hub Shank is a collection of Rust crates designed to extract Interface Definition Language (IDL) from Solana program code annotated with Shank attribute macros. The extracted IDL can then be used to generate TypeScript SDKs and facilitate interaction with Solana programs. Shank simplifies the development workflow for Solana programs by automating the generation of IDL files, which serve as a bridge between your Rust program code and client-side SDKs. Quick Start ----------- 1. Install Shank CLI: `cargo install shank-cli` 2. Add Shank to your project: `shank = "0.4"` 3. Annotate your program with `ShankAccount` and `ShankInstruction` macros 4. Extract IDL: `shank idl --out-dir ./target/idl --crate-root ./` Key Features ------------ * **Five derive macros** for annotating Solana programs (`ShankAccount`, `ShankInstruction`, `ShankBuilder`, `ShankContext`, `ShankType`) * **Automatic IDL generation** from annotated Rust code * **TypeScript SDK generation** via integration with Solita and Kinobi * **Borsh serialization support** with type overrides and padding fields * **Comprehensive account metadata** including mutability, signer requirements, and descriptions Documentation ------------- * **[Getting Started](https://developers.metaplex.com/dev-tools/shank/getting-started) ** - Installation, setup, detailed usage guide, and comprehensive examples Integration ----------- Shank integrates seamlessly with other Metaplex tools: * **[Kinobi](https://developers.metaplex.com/dev-tools/umi/kinobi) ** - Modern IDL generation and client creation * **[Solita](https://developers.metaplex.com/legacy-documentation/developer-tools/solita) ** - TypeScript SDK generation Resources --------- * [GitHub Repository](https://github.com/metaplex-foundation/shank) * [Rust Crate](https://docs.rs/shank) * [CLI Crate](https://docs.rs/shank-cli) * [Discord Community](https://discord.gg/metaplex) Next [Getting Started →](https://developers.metaplex.com/dev-tools/shank/getting-started) --- # Protocol Fees | Developer Hub The Metaplex Protocol currently includes the following fees: Token Launches -------------- Protocol fees for launching specific types of onchain assets. ### Memecoins | Instruction | Solana | | --- | --- | | User Deposit | 0% | | PHBT | 2% | | Liquidity Graduation | 1% | | Secondary Trading | 0.4%\* | ### Project Tokens | Instruction | Solana | | --- | --- | | User Deposit | 2% | | User Withdraw | 2% | | Liquidity Graduation | 0% | | Liquidity Withdrawal | 5% | | Secondary Trading | 0.4%\* | \* Total pool fees are 0.9%: 0.42% goes to liquidity providers and 0.08% to Raydium. Genesis ------- Token launch platform fees for different operations. ### Launch Pool | Instruction | Solana | | --- | --- | | Deposit | 2% | | Withdraw | 2% | | Graduation | 5% | ### Presale | Instruction | Solana | | --- | --- | | Deposit | 2% | | Graduation | 5% | Core ---- Paid by the minter, which is typically individual collectors minting new drops. Includes all instructions that "create" an NFT including ones that create print editions. | Instruction | Solana | | --- | --- | | Create | 0.0015 SOL | | Execute | 0.00004872 SOL | Bubblegum v2 ------------ Compressed NFTs with improved features and flexibility. | Instruction | Solana | | --- | --- | | Create | 0.00009 SOL | | Transfer | 0.000006 SOL | Token Metadata -------------- Paid by the minter, which is typically individual collectors minting new drops. Alternatively creators may consider using Core (next gen NFTs) for maximum composability and lower mint costs, or Bubblegum (compressed NFTs). | Instruction | Solana | | --- | --- | | Create | 0.01 SOL | Bubblegum v1 (Legacy) --------------------- The original compressed NFT program. | Instruction | Solana | | --- | --- | | Create | Free | MPL-Hybrid ---------- Paid by the individual who swaps tokens and NFTs. | Instruction | Solana | | --- | --- | | Swap | 0.005 SOL | Fusion (Trifle) --------------- Composable NFT fees for combine, split, and constraint editing operations. | Instruction | Solana | | --- | --- | | Combine | 0.002 SOL | | Split | 0.002 SOL | | Edit Constraint | 0.01 SOL | FAQs ---- ### Will the fee amounts change over time? The Metaplex Foundation is constantly monitoring community feedback related to the fees and may change the fee amounts over time. Our goal is for fees to be minimally disruptive and promote the growth and usage of the protocol. ### How are Metaplex Protocol Fees Used? All protocol fees are used to further the objectives of the Metaplex Foundation, which is a non-profit organization established to foster the research, development and adoption of the Metaplex ecosystem. This includes providing incentives and assistance to the Metaplex community for the continued development, security, governance, and administration of the Metaplex Protocol and Metaplex DAO. Currently, 50% of protocol fees are converted to $MPLX and contributed to the Metaplex DAO treasury. The remaining 50% are reserved by the Metaplex Foundation to support the long-term sustainable development of the Metaplex ecosystem. --- # Create a Token with Anchor | Solana Tokens This guide demonstrates how to create a fungible token with metadata on Solana using **Rust**, the **Anchor** framework, and the **Metaplex Token Metadata** program via CPI. What You'll Build A single Anchor instruction that: * Creates a new SPL token mint * Creates the associated token account for the payer * Creates a metadata account with name, symbol, and URI * Mints an initial token supply to the payer Summary ------- Create a **fungible SPL token** on Solana with **Anchor (Rust)**, mint an initial supply, and attach **Metaplex Token Metadata** (name, symbol, URI) via CPI. * One instruction: init **mint + ATA + metadata**, then mint supply * Uses: SPL Token + Metaplex Token Metadata CPI * Tested: Anchor 0.32.1, Solana Agave 3.1.6 * Fungible only; NFTs need Master Edition + `decimals=0` + `supply=1` Out of Scope ------------ Token-2022 extensions, confidential transfers, authority revocation, metadata updates, full NFT flow, mainnet deployment. Quick Start ----------- **Jump to:** [Program](https://developers.metaplex.com/tokens/anchor/create-token#the-program) · [Test Client](https://developers.metaplex.com/tokens/anchor/create-token#the-client) · [Common Errors](https://developers.metaplex.com/tokens/anchor/create-token#common-errors) 1. `anchor init anchor-spl-token` 2. Add `anchor-spl` with `metadata` feature to `Cargo.toml` 3. Clone Token Metadata program in `Anchor.toml` for localnet 4. Paste the program code and run `anchor test` Prerequisites ------------- * **Rust** installed ([rustup.rs](https://rustup.rs/) ) * **Solana CLI** installed ([docs.solana.com](https://docs.solana.com/cli/install-solana-cli-tools) ) * **Anchor CLI** installed (`cargo install --git https://github.com/coral-xyz/anchor anchor-cli`) * **Node.js** and **Yarn** for running tests * A Solana wallet with SOL for transaction fees Tested Configuration -------------------- This guide was tested with the following versions: | Tool | Version | | --- | --- | | Anchor CLI | 0.32.1 | | Solana CLI | 3.1.6 (Agave) | | Rust | 1.92.0 | | Node.js | 22.15.1 | | Yarn | 1.22.x | Initial Setup ------------- Start by initializing a new Anchor project: `anchor init anchor-spl-token cd anchor-spl-token` ### Configure Cargo.toml Update `programs/anchor-spl-token/Cargo.toml`: programs/anchor-spl-token/Cargo.toml `1[package] 2name = "anchor-spl-token" 3version = "0.1.0" 4description = "Created with Anchor" 5edition = "2021" 6 7[lib] 8crate-type = ["cdylib", "lib"] 9name = "anchor_spl_token" 10 11[lints.rust] 12unexpected_cfgs = { level = "warn", check-cfg = [ 13 'cfg(feature, values("custom-heap", "custom-panic", "anchor-debug"))' 14] } 15 16[features] 17default = [] 18cpi = ["no-entrypoint"] 19no-entrypoint = [] 20no-idl = [] 21no-log-ix-name = [] 22idl-build = ["anchor-lang/idl-build", "anchor-spl/idl-build"] 23 24[dependencies] 25anchor-lang = "0.32.1" 26anchor-spl = { version = "0.32.1", features = ["token", "metadata", "associated_token"] }` Important The `idl-build` feature **must** include `anchor-spl/idl-build` or you'll get errors like `no function or associated item named 'create_type' found for struct 'anchor_spl::token::Mint'`. ### Configure Anchor.toml Update `Anchor.toml` to clone the Token Metadata program for local testing: Anchor.toml `1[toolchain] 2package_manager = "yarn" 3 4[features] 5resolution = true 6skip-lint = false 7 8[programs.localnet] 9anchor_spl_token = "YOUR_PROGRAM_ID_HERE" 10 11[registry] 12url = "https://api.apr.dev" 13 14[provider] 15cluster = "localnet" 16wallet = "~/.config/solana/id.json" 17 18[scripts] 19test = "yarn run ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" 20 21[test.validator] 22url = "https://api.mainnet-beta.solana.com" 23bind_address = "127.0.0.1" 24 25[[test.validator.clone]] 26address = "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"` * `bind_address = "127.0.0.1"` is required for Agave 3.x validators (0.0.0.0 causes a panic) * The `[[test.validator.clone]]` section clones the Metaplex Token Metadata program from mainnet ### Configure package.json package.json `1{ 2 "license": "ISC", 3 "scripts": { 4 "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", 5 "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" 6 }, 7 "dependencies": { 8 "@coral-xyz/anchor": "^0.32.1", 9 "@metaplex-foundation/mpl-token-metadata": "^3.4.0", 10 "@solana/spl-token": "^0.4.9" 11 }, 12 "devDependencies": { 13 "chai": "^4.3.4", 14 "mocha": "^9.0.3", 15 "ts-mocha": "^10.0.0", 16 "@types/bn.js": "^5.1.0", 17 "@types/chai": "^4.3.0", 18 "@types/mocha": "^9.0.0", 19 "typescript": "^5.7.3", 20 "prettier": "^2.6.2" 21 } 22}` The Program ----------- ### Imports and Template Here we define all the imports and create the template for the Account struct and instruction in `programs/anchor-spl-token/src/lib.rs`: programs/anchor-spl-token/src/lib.rs `1use anchor_lang::prelude::*; 2use anchor_spl::{ 3 associated_token::AssociatedToken, 4 metadata::{ 5 create_metadata_accounts_v3, mpl_token_metadata::types::DataV2, CreateMetadataAccountsV3, 6 Metadata, 7 }, 8 token::{mint_to, Mint, MintTo, Token, TokenAccount}, 9}; 10 11declare_id!("YOUR_PROGRAM_ID_HERE"); 12 13#[program] 14pub mod anchor_spl_token { 15 use super::*; 16 17 pub fn create_token( 18 ctx: Context, 19 name: String, 20 symbol: String, 21 uri: String, 22 decimals: u8, 23 amount: u64, 24 ) -> Result<()> { 25 Ok(()) 26 } 27} 28 29#[derive(Accounts)] 30#[instruction(name: String, symbol: String, uri: String, decimals: u8)] 31pub struct CreateToken<'info> { 32 33}` ### Creating the Account Struct The `CreateToken` struct defines all accounts required by the instruction and applies the necessary constraints: programs/anchor-spl-token/src/lib.rs `1#[derive(Accounts)] 2#[instruction(name: String, symbol: String, uri: String, decimals: u8)] 3pub struct CreateToken<'info> { 4 #[account(mut)] 5 pub payer: Signer<'info>, 6 7 /// The mint account to be created 8 #[account( 9 init, 10 payer = payer, 11 mint::decimals = decimals, 12 mint::authority = payer.key(), 13 mint::freeze_authority = payer.key(), 14 )] 15 pub mint: Account<'info, Mint>, 16 17 /// The associated token account to receive minted tokens 18 #[account( 19 init, 20 payer = payer, 21 associated_token::mint = mint, 22 associated_token::authority = payer, 23 )] 24 pub token_account: Account<'info, TokenAccount>, 25 26 /// The metadata account to be created 27 /// CHECK: Validated by seeds constraint to be the correct PDA 28 #[account( 29 mut, 30 seeds = [ 31 b"metadata", 32 token_metadata_program.key().as_ref(), 33 mint.key().as_ref(), 34 ], 35 bump, 36 seeds::program = token_metadata_program.key(), 37 )] 38 pub metadata_account: UncheckedAccount<'info>, 39 40 pub token_program: Program<'info, Token>, 41 pub token_metadata_program: Program<'info, Metadata>, 42 pub associated_token_program: Program<'info, AssociatedToken>, 43 pub system_program: Program<'info, System>, 44 pub rent: Sysvar<'info, Rent>, 45}` **Account Types:** * The `#[instruction(...)]` attribute allows using instruction arguments (like `decimals`) in account constraints * `mint` uses Anchor's `init` constraint with `mint::decimals = decimals` to create the token mint with the specified decimal places * `token_account` is initialized as an associated token account using `associated_token::` helpers * `metadata_account` uses `seeds::program` to validate the PDA belongs to the Token Metadata program ### Creating the Instruction The `create_token` function creates the metadata account via CPI and mints the initial token supply: programs/anchor-spl-token/src/lib.rs `1pub fn create_token( 2 ctx: Context, 3 name: String, 4 symbol: String, 5 uri: String, 6 decimals: u8, 7 amount: u64, 8) -> Result<()> { 9 msg!("Creating token mint..."); 10 msg!("Mint: {}", ctx.accounts.mint.key()); 11 msg!("Creating metadata account..."); 12 msg!("Metadata account address: {}", ctx.accounts.metadata_account.key()); 13 14 // Cross Program Invocation (CPI) to token metadata program 15 create_metadata_accounts_v3( 16 CpiContext::new( 17 ctx.accounts.token_metadata_program.to_account_info(), 18 CreateMetadataAccountsV3 { 19 metadata: ctx.accounts.metadata_account.to_account_info(), 20 mint: ctx.accounts.mint.to_account_info(), 21 mint_authority: ctx.accounts.payer.to_account_info(), 22 update_authority: ctx.accounts.payer.to_account_info(), 23 payer: ctx.accounts.payer.to_account_info(), 24 system_program: ctx.accounts.system_program.to_account_info(), 25 rent: ctx.accounts.rent.to_account_info(), 26 }, 27 ), 28 DataV2 { 29 name, 30 symbol, 31 uri, 32 seller_fee_basis_points: 0, 33 creators: None, 34 collection: None, 35 uses: None, 36 }, 37 true, // is_mutable 38 true, // update_authority_is_signer 39 None, // collection_details 40 )?; 41 42 // Mint tokens to the payer's associated token account 43 msg!("Minting {} tokens to {}", amount, ctx.accounts.token_account.key()); 44 45 mint_to( 46 CpiContext::new( 47 ctx.accounts.token_program.to_account_info(), 48 MintTo { 49 mint: ctx.accounts.mint.to_account_info(), 50 to: ctx.accounts.token_account.to_account_info(), 51 authority: ctx.accounts.payer.to_account_info(), 52 }, 53 ), 54 amount, 55 )?; 56 57 msg!("Token created and {} tokens minted successfully.", amount); 58 Ok(()) 59}` The function performs two Cross-Program Invocations: 1. `create_metadata_accounts_v3` (lines 14-40) - Creates and initializes the metadata account with name, symbol, and URI 2. `mint_to` (lines 43-54) - Mints the specified amount to the payer's token account The Client ---------- Before testing, build the program: `anchor build` Get your program ID and update it in both `lib.rs` and `Anchor.toml`: `solana address -k target/deploy/anchor_spl_token-keypair.json` Then rebuild and deploy: `anchor build anchor deploy` ### Creating the Test Create the test file at `tests/anchor-spl-token.ts`: tests/anchor-spl-token.ts `1import * as anchor from "@coral-xyz/anchor"; 2import { Program } from "@coral-xyz/anchor"; 3import { AnchorSplToken } from "../target/types/anchor_spl_token"; 4import { Keypair, PublicKey, SystemProgram, SYSVAR_RENT_PUBKEY } from "@solana/web3.js"; 5import { TOKEN_PROGRAM_ID, ASSOCIATED_PROGRAM_ID } from "@coral-xyz/anchor/dist/cjs/utils/token"; 6import { getAssociatedTokenAddressSync } from "@solana/spl-token"; 7import { BN } from "bn.js"; 8 9const TOKEN_METADATA_PROGRAM_ID = new PublicKey( 10 "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s" 11); 12 13describe("anchor-spl-token", () => { 14 const provider = anchor.AnchorProvider.env(); 15 anchor.setProvider(provider); 16 17 const program = anchor.workspace.AnchorSplToken as Program; 18 const payer = provider.wallet; 19 20 it("Creates a token with metadata and mints initial supply", async () => { 21 const mintKeypair = Keypair.generate(); 22 23 const tokenName = "My Token"; 24 const tokenSymbol = "MYTKN"; 25 const tokenUri = "https://example.com/token-metadata.json"; 26 const tokenDecimals = 9; 27 const mintAmount = new BN(1_000_000).mul(new BN(10).pow(new BN(tokenDecimals))); 28 29 // Derive the metadata account PDA 30 const [metadataAccount] = PublicKey.findProgramAddressSync( 31 [ 32 Buffer.from("metadata"), 33 TOKEN_METADATA_PROGRAM_ID.toBuffer(), 34 mintKeypair.publicKey.toBuffer(), 35 ], 36 TOKEN_METADATA_PROGRAM_ID 37 ); 38 39 // Derive the associated token account 40 const tokenAccount = getAssociatedTokenAddressSync( 41 mintKeypair.publicKey, 42 payer.publicKey 43 ); 44 45 console.log("Mint address:", mintKeypair.publicKey.toBase58()); 46 console.log("Metadata address:", metadataAccount.toBase58()); 47 console.log("Token account:", tokenAccount.toBase58()); 48 49 const tx = await program.methods 50 .createToken(tokenName, tokenSymbol, tokenUri, tokenDecimals, mintAmount) 51 .accountsPartial({ 52 payer: payer.publicKey, 53 mint: mintKeypair.publicKey, 54 tokenAccount: tokenAccount, 55 metadataAccount: metadataAccount, 56 tokenProgram: TOKEN_PROGRAM_ID, 57 tokenMetadataProgram: TOKEN_METADATA_PROGRAM_ID, 58 associatedTokenProgram: ASSOCIATED_PROGRAM_ID, 59 systemProgram: SystemProgram.programId, 60 rent: SYSVAR_RENT_PUBKEY, 61 }) 62 .signers([mintKeypair]) 63 .rpc(); 64 65 console.log("Transaction signature:", tx); 66 console.log("Token created and minted successfully!"); 67 }); 68});` **Key Points:** * The metadata account PDA is derived using seeds: `["metadata", TOKEN_METADATA_PROGRAM_ID, mint_pubkey]` (lines 29-36) * The associated token account is derived using `getAssociatedTokenAddressSync` (lines 39-42) * The mint keypair must be passed as a signer since it's being initialized * Use `accountsPartial` to specify accounts (Anchor 0.32+ syntax) * Use `BN` for large numbers (token amounts with decimals) * `tokenDecimals` is passed to the instruction and used to calculate the mint amount ### Running the Test `yarn install anchor test` Expected output: `anchor-spl-token Mint address: GpPyH2FuMcS5PcrKWtrmEkBmW8h8gSwUaxNCQkFXwifV Metadata address: 6jskfrDAmH9d67iL37CLNBK7Hf6FRwNZbq34q4vGucDq Token account: J3KCxCfmnK9RJ3onmiUsfBDjvKyuVsAXgWvuypsaFQ2i Transaction signature: 36v63t5cCsXYM8ny4pgahh... Token created and minted successfully! ✔ Creates a token with metadata and mints initial supply (243ms) 1 passing (245ms)` Metadata JSON Format -------------------- The `uri` field should point to a JSON file containing your token's off-chain metadata: token-metadata.json `{ "name": "My Token", "symbol": "MYTKN", "description": "A description of my token", "image": "https://example.com/token-image.png" }` Host this JSON file on a permanent storage solution like Arweave or IPFS. Common Errors ------------- ### `no function or associated item named 'create_type' found` Add `"anchor-spl/idl-build"` to the `idl-build` feature in Cargo.toml: `idl-build = ["anchor-lang/idl-build", "anchor-spl/idl-build"]` ### `Program account is not executable` Clone the Token Metadata program in Anchor.toml: `[[test.validator.clone]] address = "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"` ### `UnspecifiedIpAddr(0.0.0.0)` / Validator panic Add `bind_address = "127.0.0.1"` to `[test.validator]` in Anchor.toml. Notes ----- * The `amount` parameter is in **base units** (includes decimals). For 1 million tokens with 9 decimals, pass `1_000_000 * 10^9`. * This example keeps **mint authority** and **freeze authority** on the payer. Production tokens often revoke or transfer these authorities after initial minting. * The metadata account is **mutable** (`is_mutable = true`). Set to `false` if you want immutable metadata. Next Steps ---------- * **Deploy to Devnet:** Change `cluster = "devnet"` in Anchor.toml and run `anchor deploy` * **Create an NFT:** Set `decimals = 0` and `supply = 1` for non-fungible tokens * **Add Token Extensions:** Explore [SPL Token 2022](https://spl.solana.com/token-2022) for transfer fees, interest-bearing tokens, and more * **Learn more about Token Metadata:** See the [Token Metadata documentation](https://developers.metaplex.com/smart-contracts/token-metadata) Quick Reference --------------- ### Key Program IDs | Program | Address | | --- | --- | | Token Program | `TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA` | | Associated Token Program | `ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL` | | Token Metadata Program | `metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s` | | System Program | `11111111111111111111111111111111` | ### Metadata PDA Seeds Deriving the Metadata PDA TypeScript `1const [metadataAccount] = PublicKey.findProgramAddressSync( 2 [Buffer.from("metadata"), TOKEN_METADATA_PROGRAM_ID.toBuffer(), mint.toBuffer()], 3 TOKEN_METADATA_PROGRAM_ID 4);` ### Minimum Dependencies Cargo.toml `anchor-lang = "0.32.1" anchor-spl = { version = "0.32.1", features = ["token", "metadata", "associated_token"] }` FAQ --- Terminology * **Fungible token:** `decimals >= 0`, unlimited supply potential * **NFT:** `decimals = 0`, `supply = 1`, plus Master Edition account * **Token Metadata:** Metaplex program used for both fungible tokens and NFTs * **SPL:** Solana Program Library, the standard token interface ### What is an SPL token? An SPL token is Solana's equivalent of an ERC-20 token on Ethereum. SPL stands for Solana Program Library. SPL tokens are fungible tokens that can represent currencies, governance tokens, stablecoins, or any other fungible asset on Solana. ### What is the difference between a token mint and a token account? * **Token Mint:** The factory that creates tokens. It defines the token's properties (decimals, supply, authorities). There is one mint per token type. * **Token Account:** A wallet that holds tokens. Each user needs their own token account for each token type they want to hold. ### What is an Associated Token Account (ATA)? An Associated Token Account is a deterministically-derived token account for a given wallet and mint. Instead of creating random token accounts, ATAs use a standard derivation so anyone can calculate the token account address for any wallet. This is the recommended way to handle token accounts. ### What is Metaplex Token Metadata? Metaplex Token Metadata is a program that attaches metadata (name, symbol, image URI) to SPL tokens. Without it, tokens are just anonymous mints. The metadata is stored in a Program Derived Address (PDA) associated with the mint. ### Why clone the Token Metadata program for local testing? The local Solana test validator starts with a clean state and doesn't include any programs except the core Solana programs. Metaplex Token Metadata is a separate program deployed on mainnet, so you need to clone it to use it locally. ### Can I use this code to create an NFT? Yes, with modifications: * Set `mint::decimals = 0` (NFTs are indivisible) * Mint exactly 1 token * Remove mint authority after minting (so no more can be created) * Add a Master Edition account (for Metaplex NFT standard) ### How much does it cost to create a token on Solana? Creating a token requires rent for three accounts: * Mint account: ~0.00145 SOL * Token account: ~0.00203 SOL * Metadata account: ~0.01 SOL Total: approximately 0.015-0.02 SOL (varies with rent prices). ### What's the difference between Anchor and native Solana Rust? Anchor is a framework that simplifies Solana development by: * Auto-generating account serialization/deserialization * Providing declarative account validation with macros * Generating TypeScript clients automatically * Handling common patterns like PDAs and CPIs Native Solana Rust requires manually handling all of these concerns. Glossary -------- | Term | Definition | | --- | --- | | **SPL Token** | Solana Program Library token standard, equivalent to ERC-20 | | **Mint** | The account that defines a token and can create new supply | | **Token Account** | An account that holds a balance of a specific token | | **ATA** | Associated Token Account - deterministic token account for a wallet | | **PDA** | Program Derived Address - an address derived from seeds, owned by a program | | **CPI** | Cross-Program Invocation - calling one Solana program from another | | **Anchor** | A Rust framework for building Solana programs | | **Metaplex** | Protocol for NFTs and token metadata on Solana | | **IDL** | Interface Definition Language - describes a program's interface | | **Rent** | SOL required to keep an account alive on Solana | Previous [← Burn Tokens](https://developers.metaplex.com/tokens/burn-tokens) --- # Solana Smart Contracts & Programs | NFT & Token Infrastructure | Metaplex Solana Smart Contracts ---------------------- Production-ready Solana smart contracts for NFTs, tokens, and digital assets. Build with Core, Token Metadata, Candy Machine, Genesis, and more. [### Token Metadata\ \ Digital ownership standard\ \ Learn more](https://developers.metaplex.com/smart-contracts/token-metadata) [### Core\ \ Next gen NFT standard\ \ Learn more](https://developers.metaplex.com/smart-contracts/core) [### Bubblegum v2\ \ Improved Compressed NFTs\ \ Learn more](https://developers.metaplex.com/smart-contracts/bubblegum-v2) [### Core Candy Machine\ \ Core Asset launchpad\ \ Learn more](https://developers.metaplex.com/smart-contracts/core-candy-machine) [### MPL-Hybrid\ \ Hybrid Assets\ \ Learn more](https://developers.metaplex.com/smart-contracts/mpl-hybrid) [### Genesis\ \ Token Launch Platform\ \ Learn more](https://developers.metaplex.com/smart-contracts/genesis) [### Inscription\ \ NFT inscribed on Solana\ \ Learn more](https://developers.metaplex.com/smart-contracts/inscription) [### Bubblegum v1 (legacy)\ \ Compressed NFTs\ \ Learn more](https://developers.metaplex.com/smart-contracts/bubblegum) --- # Solana Dev Tools | CLI, SDKs & APIs for NFTs & Tokens | Metaplex Solana Developer Tools ---------------------- Developer tools for building on Solana. CLI tools, TypeScript SDKs, APIs, and utilities for NFTs, tokens, and digital assets. [### DAS API\ \ Fetch Digital Asset Data\ \ Learn more](https://developers.metaplex.com/dev-tools/das-api) [### Umi\ \ Client wrapper\ \ Learn more](https://developers.metaplex.com/dev-tools/umi) [### CLI\ \ MPLX CLI\ \ Learn more](https://developers.metaplex.com/dev-tools/cli) [### Shank\ \ IDL Extraction for Solana Programs\ \ Learn more](https://developers.metaplex.com/dev-tools/shank) [### Amman\ \ Local Validator Toolkit\ \ Learn more](https://developers.metaplex.com/dev-tools/amman) [### Legacy\ \ Products from our old docs\ \ Learn more](https://developers.metaplex.com/legacy-documentation) --- # Metaplex Solana Guides | Guides ![Metaplex Solana Guides Banner](https://developers.metaplex.com/assets/banners/touch-screen.jpg) The guides in this section are **designed to help new Solana developers start their journey** by providing step-by-step instructions and practical examples they can execute. These guides focus on teaching key concepts with a structured learning path that gradually introduces developers to the Solana ecosystem. They cover everything from the basics of blockchain and Solana's unique features to advanced topics such as program development and optimization techniques. By incorporating a variety of learning resources, including tutorials and code samples, **the guides are designed to be accessible to new and experienced developers in the space**. The guides are regularly updated to reflect the latest developments in the Solana ecosystem. The guides are shared for educational and informational purposes only and are not to be relied upon as professional advice. All content included in these learning resources are not guaranteed to be current or error-free. Program Guides Index ==================== airdrop anchor javascript nfts rust tokens * Bubblegum V1 * [How to create 1000000 NFTs on Solana](https://developers.metaplex.com/smart-contracts/bubblegum/guides/javascript/how-to-create-1000000-nfts-on-solana) * [How to interact with CNFTs on other SVMS](https://developers.metaplex.com/smart-contracts/bubblegum/guides/javascript/how-to-interact-with-cnfts-on-other-svms) * Candy Machine * [Airdrop Mint to Another Wallet](https://developers.metaplex.com/smart-contracts/candy-machine/guides/airdrop-mint-to-another-wallet) * [Create an NFT Collection on Solana with Candy Machine](https://developers.metaplex.com/smart-contracts/candy-machine/guides/create-an-nft-collection-on-solana-with-candy-machine) * Core Candy Machine * [Create a Core Candy Machine UI](https://developers.metaplex.com/smart-contracts/core-candy-machine/guides/create-a-core-candy-machine-ui) * [Create a Core Candy Machine with Hidden Settings](https://developers.metaplex.com/smart-contracts/core-candy-machine/guides/create-a-core-candy-machine-with-hidden-settings) * Core * [Immutable NFTs](https://developers.metaplex.com/smart-contracts/core/guides/immutability) * [Create Soulbound NFT Asset](https://developers.metaplex.com/smart-contracts/core/guides/create-soulbound-nft-asset) * [Print Editions](https://developers.metaplex.com/smart-contracts/core/guides/print-editions) * [Oracle Plugin Example](https://developers.metaplex.com/smart-contracts/core/guides/oracle-plugin-example) * [Onchain Ticketing with AppData](https://developers.metaplex.com/smart-contracts/core/guides/onchain-ticketing-with-appdata) * [How to create a Core NFT Asset with JavaScript](https://developers.metaplex.com/smart-contracts/core/guides/javascript/how-to-create-a-core-nft-asset-with-javascript) * [How to create a Core Collection with Javascript](https://developers.metaplex.com/smart-contracts/core/guides/javascript/how-to-create-a-core-collection-with-javascript) * [Web2 Typescript Staking Example](https://developers.metaplex.com/smart-contracts/core/guides/javascript/web2-typescript-staking-example) * [Loyalty Card Concept Guide](https://developers.metaplex.com/smart-contracts/core/guides/loyalty-card-concept-guide) * [How to create a Core NFT Asset with Anchor](https://developers.metaplex.com/smart-contracts/core/guides/anchor/how-to-create-a-core-nft-asset-with-anchor) * [How to create a Core Collection with Anchor](https://developers.metaplex.com/smart-contracts/core/guides/anchor/how-to-create-a-core-collection-with-anchor) * [Anchor Staking Example](https://developers.metaplex.com/smart-contracts/core/guides/anchor/anchor-staking-example) * Token Metadata * [Get NFTs By Collection](https://developers.metaplex.com/smart-contracts/token-metadata/guides/get-by-collection) * [Account Size Reduction](https://developers.metaplex.com/smart-contracts/token-metadata/guides/account-size-reduction) * [Spl Token Claim Airdrop Using Gumdrop](https://developers.metaplex.com/solana/general/spl-token-claim-airdrop-using-gumdrop) * [Token Claimer Smart Contract](https://developers.metaplex.com/smart-contracts/token-metadata/guides/anchor/token-claimer-smart-contract) * [Create an NFT](https://developers.metaplex.com/smart-contracts/token-metadata/guides/javascript/create-an-nft) * Umi * [Optimal Transactions with Compute Units and Priority Fees](https://developers.metaplex.com/dev-tools/umi/guides/optimal-transactions-with-compute-units-and-priority-fees) * [Serializing and Deserializing Transactions](https://developers.metaplex.com/dev-tools/umi/guides/serializing-and-deserializing-transactions) Next [What is Solana? →](https://developers.metaplex.com/solana/what-is-solana) --- # How to Update Fungible Token Metadata on Solana | Tokens Update the metadata of your fungible token to change its name, symbol, image, or other properties. Update Token Metadata --------------------- In the following section you can find a full code example and the parameters that you might have to change. This uses the Token Metadata program to update on-chain metadata. Umi (JS)CLI SnippetFull Copy 1// npm install @metaplex-foundation/mpl-token-metadata @metaplex-foundation/umi @metaplex-foundation/umi-bundle-defaults 2import { 3 fetchDigitalAsset, 4 mplTokenMetadata, 5 updateV1, 6} from '@metaplex-foundation/mpl-token-metadata' 7import { 8 keypairIdentity, 9 publicKey, 10} from '@metaplex-foundation/umi' 11import { createUmi } from '@metaplex-foundation/umi-bundle-defaults' 12import { readFileSync } from 'fs' 13 14// Initialize Umi with your RPC endpoint 15const umi = createUmi('https://api.devnet.solana.com').use(mplTokenMetadata()) 16 17// Load your wallet keypair (must be the update authority) 18const wallet = '' 19const secretKey = JSON.parse(readFileSync(wallet, 'utf-8')) 20const keypair = umi.eddsa.createKeypairFromSecretKey(new Uint8Array(secretKey)) 21umi.use(keypairIdentity(keypair)) 22 23// Your token mint address 24const mintAddress = publicKey('') 25 26// Fetch existing token data 27const asset = await fetchDigitalAsset(umi, mintAddress) 28 29// Update the token metadata (name, symbol, and URI) 30await updateV1(umi, { 31 mint: mintAddress, 32 authority: umi.identity, 33 data: { 34 ...asset.metadata, 35 name: 'Updated Token Name', 36 symbol: 'UTN', 37 uri: 'https://example.com/updated-metadata.json', 38 }, 39}).sendAndConfirm(umi) 40 41console.log('Token metadata updated successfully') 42console.log('Mint:', mintAddress) 43console.log('New name:', 'Updated Token Name') 44console.log('New URI:', 'https://example.com/updated-metadata.json') 1# Update Token Metadata using the Metaplex CLI 2 3# Interactive editor mode (opens metadata JSON in your default editor) 4mplx toolbox token update --editor 5 6# Update specific fields via flags 7mplx toolbox token update --name "New Token Name" 8mplx toolbox token update --symbol "NEW" 9mplx toolbox token update --description "Updated description" 10 11# Update with new image 12mplx toolbox token update --image ./new-image.png 13 14# Update multiple fields at once 15mplx toolbox token update \ 16 --name "Updated Token" \ 17 --symbol "UPD" \ 18 --description "An updated token description" \ 19 --image ./updated-image.png 20 21# Note: You must be the update authority to update token metadata 22# Note: --editor flag cannot be combined with other update flags Parameters ---------- Customize these parameters for your update: | Parameter | Description | | --- | --- | | `mintAddress` | The token mint address | | `name` | New token name (max 32 characters) | | `symbol` | New token symbol (max 10 characters) | | `uri` | New link to off-chain metadata JSON | | `sellerFeeBasisPoints` | Royalty percentage (usually 0 for fungibles) | How It Works ------------ The update process is straightforward: 1. **Connect with update authority** - Your wallet must be the update authority for the token 2. **Call updateV1** - Provide the mint address and new metadata values 3. **Confirm transaction** - The metadata is updated on-chain What Can Be Updated ------------------- You can update the following on-chain metadata: * **Name** - The display name of your token * **Symbol** - The short ticker symbol * **URI** - Link to off-chain JSON metadata (image, description, etc.) * **Seller fee basis points** - Royalty percentage Requirements ------------ To update token metadata, you must: * **Be the update authority** - Only the designated update authority can modify metadata * **Have a mutable token** - The token must have been created with `isMutable: true` Updating Off-Chain Metadata --------------------------- To update the token image or description, you need to: 1. Create a new JSON metadata file with updated information 2. Upload the new JSON to a storage provider (like Arweave) 3. Update the `uri` field to point to the new JSON file `{ "name": "Updated Token Name", "symbol": "UTN", "description": "An updated description for my token", "image": "https://arweave.net/new-image-hash" }` Important Notes --------------- * Updates only affect the metadata, not the token itself or existing balances * If your token was created as immutable, you cannot update its metadata * Changing the `uri` allows you to update off-chain data like images and descriptions Previous [← Transfer Tokens](https://developers.metaplex.com/tokens/transfer-a-token) Next [Burn Tokens →](https://developers.metaplex.com/tokens/burn-tokens) --- # Legacy Documentation | Developer Hub A collection of documentation of older Programs and Tools which might not be used anymore or deprecated. Migrated from our old docs for documentation for completeness. [Auction House](https://developers.metaplex.com/legacy-documentation/auction-house) ------------------------------------------------------------------------------------ Allows users to exchange assets within the Solana blockchain. [Fixed Price Sale](https://developers.metaplex.com/legacy-documentation/fixed-price-sale) ------------------------------------------------------------------------------------------ Sell NFTs at a fixed price by minting print editions from a single master edition. [Gumdrop](https://developers.metaplex.com/legacy-documentation/gumdrop) ------------------------------------------------------------------------ Let your community claim tokens instead of having to airdrop them and paying the fees yourself. [Token Entangler](https://developers.metaplex.com/legacy-documentation/token-entangler) ---------------------------------------------------------------------------------------- Entangle NFTs with each other. E.g. to derug projects or fix ones with messed up immutable metadata. [Mobile SDKs](https://developers.metaplex.com/en/legacy-documentation) ----------------------------------------------------------------------- Probably helpful when looking into Android or iOS Development. [Developer Tools](https://developers.metaplex.com/en/legacy-documentation) --------------------------------------------------------------------------- Some older developer tools that might still help you along the way. Next [Overview →](https://developers.metaplex.com/legacy-documentation/auction-house) --- # Create a Fungible Token | Tokens Create a fungible token with metadata on Solana using the Token Metadata program. What You'll Learn ----------------- This guide shows you how to create and mint a fungible token with: * Custom name, symbol, and metadata * Token image and description * Configurable decimals (divisibility) * Initial token supply Create a Token -------------- The following code is a fully runnable example. Below the parameters that you might want to customize are shown. You can learn more about token creation details in the [Token Metadata program](https://developers.metaplex.com/smart-contracts/token-metadata/mint#minting-tokens) pages. Umi (JS)Kit (JS)CLI SnippetFull Copy 1// npm install @metaplex-foundation/mpl-token-metadata @metaplex-foundation/mpl-toolbox @metaplex-foundation/umi @metaplex-foundation/umi-bundle-defaults 2import { 3 createFungible, 4 mplTokenMetadata, 5} from '@metaplex-foundation/mpl-token-metadata' 6import { 7 createTokenIfMissing, 8 findAssociatedTokenPda, 9 mintTokensTo, 10} from '@metaplex-foundation/mpl-toolbox' 11import { 12 generateSigner, 13 keypairIdentity, 14 percentAmount, 15 some, 16} from '@metaplex-foundation/umi' 17import { createUmi } from '@metaplex-foundation/umi-bundle-defaults' 18import { readFileSync } from 'fs' 19 20// Initialize Umi with your RPC endpoint 21const umi = createUmi('https://api.devnet.solana.com').use(mplTokenMetadata()) 22 23// Load your wallet keypair 24const wallet = '' 25const secretKey = JSON.parse(readFileSync(wallet, 'utf-8')) 26const keypair = umi.eddsa.createKeypairFromSecretKey(new Uint8Array(secretKey)) 27umi.use(keypairIdentity(keypair)) 28 29// Generate a new mint account 30const mint = generateSigner(umi) 31 32// Step 1: Create the fungible token with metadata 33await createFungible(umi, { 34 mint, 35 name: 'My Fungible Token', 36 symbol: 'MFT', 37 uri: 'https://example.com/my-token-metadata.json', 38 sellerFeeBasisPoints: percentAmount(0), 39 decimals: some(9), 40}).sendAndConfirm(umi) 41 42// Step 2: Mint initial supply to your wallet 43await createTokenIfMissing(umi, { 44 mint: mint.publicKey, 45 owner: umi.identity.publicKey, 46}) 47 .add( 48 mintTokensTo(umi, { 49 mint: mint.publicKey, 50 token: findAssociatedTokenPda(umi, { 51 mint: mint.publicKey, 52 owner: umi.identity.publicKey, 53 }), 54 amount: 1_000_000_000_000_000, // 1,000,000 tokens with 9 decimals 55 }) 56 ) 57 .sendAndConfirm(umi) 58 59console.log('Token created:', mint.publicKey) 60console.log('Metadata and mint account initialized') 61console.log('Initial supply minted to:', umi.identity.publicKey) 1import { generateKeyPairSigner } from '@solana/kit'; 2import { createFungible } from '@metaplex-foundation/mpl-token-metadata-kit'; 3 4// Assuming rpc, rpcSubscriptions, and sendAndConfirmInstructions are set up 5// See getting-started for full setup 6 7const mint = await generateKeyPairSigner(); 8const authority = await generateKeyPairSigner(); // Your wallet 9 10// Create a fungible token with metadata and mint initial supply 11const createAndMintIx = await createFungible({ 12 mint, 13 authority, 14 payer: authority, 15 name: 'My Fungible Token', 16 symbol: 'MFT', 17 uri: 'https://example.com/my-token-metadata.json', 18 sellerFeeBasisPoints: 0, 19 decimals: 9, 20 tokenOwner: authority.address, 21 amount: 1_000_000_000_000_000n, // 1,000,000 tokens with 9 decimals 22}); 23 24// Send the instruction (createFungible returns a single combined instruction) 25await sendAndConfirm({ 26 instructions: [createAndMintIx], 27 payer: authority, 28}); 29 30console.log('Fungible token created:', mint.address); 31console.log('Initial supply minted to:', authority.address); 1# Create a Fungible Token using the Metaplex CLI 2 3# Interactive wizard mode (recommended for beginners) 4mplx toolbox token create --wizard 5 6# Basic token creation (required: --name, --symbol, --mint-amount) 7mplx toolbox token create \ 8 --name "My Token" \ 9 --symbol "MYT" \ 10 --mint-amount 1000000 11 12# Full token creation with all options 13mplx toolbox token create \ 14 --name "My Token" \ 15 --symbol "MYT" \ 16 --description "A fungible token on Solana" \ 17 --image ./token-image.png \ 18 --decimals 9 \ 19 --mint-amount 1000000000000000 20 21# Note: mint-amount is in smallest units 22# With --decimals 9, to mint 1,000,000 tokens: --mint-amount 1000000000000000 23# With --decimals 0 (default), to mint 1,000,000 tokens: --mint-amount 1000000 Parameters ---------- Customize these parameters for your token: | Parameter | Description | | --- | --- | | `name` | Token name (max 32 characters) | | `symbol` | Short name of your Token (max 6 characters) | | `uri` | Link to off-chain metadata JSON | | `sellerFeeBasisPoints` | Royalty percentage (550 = 5.5%) | | `decimals` | Decimal places (`some(9)` is standard) | | `amount` | Number of tokens to mint | Metadata and Images ------------------- <<<<<<< HEAD The `uri` should point to a JSON file containing at least the following information. You can find more details on the [Token Metadata Standard page](https://developers.metaplex.com/token-metadata/token-standard#the-fungible-standard) . You need to upload the JSON and the image url so that they are accessible from everywhere. We recommend to use a web3 storage provider like Arweave. If you want to do so by code you can follow this [guide](https://developers.metaplex.com/smart-contracts/mpl-hybrid/guides/create-deterministic-metadata-with-turbo) . \======= The `uri` should point to a JSON file containing at least the following information. You can find more details on the [Token Metadata Standard page](https://developers.metaplex.com/smart-contracts/token-metadata/token-standard#the-fungible-standard) . You need to upload the JSON and the image url so that they are accessible from everywhere. We recommend to use a web3 storage provider like Arweave. If you want to do so by code you can follow this [guide on creating deterministic metadata with Turbo](https://developers.metaplex.com/guides/general/create-deterministic-metadata-with-turbo) . > > > > > > > main `{ "name": "My Fungible Token", "symbol": "MFT", "description": "A fungible token on Solana", "image": "https://arweave.net/tx-hash" }` Previous [← Overview](https://developers.metaplex.com/tokens) Next [Launch a Token →](https://developers.metaplex.com/tokens/launch-token) --- # How to Mint Additional Fungible Tokens on Solana | Tokens Mint additional fungible tokens to increase the circulating supply of your token on Solana. Mint Tokens ----------- In the following section you can find a full code example and the parameters that you might have to change. This assumes you already have a fungible token created and want to mint more tokens. Umi (JS)CLI SnippetFull Copy 1// To install all the required packages use the following command 2// npm install @metaplex-foundation/mpl-toolbox @metaplex-foundation/umi @metaplex-foundation/umi-bundle-defaults 3import { 4 createTokenIfMissing, 5 findAssociatedTokenPda, 6 mintTokensTo, 7} from '@metaplex-foundation/mpl-toolbox'; 8import { 9 keypairIdentity, 10 publicKey, 11 transactionBuilder, 12} from '@metaplex-foundation/umi'; 13import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'; 14import { readFileSync } from 'fs'; 15 16// Initialize Umi with Devnet endpoint 17const umi = createUmi('https://api.devnet.solana.com') 18 19// Load your wallet/keypair 20const wallet = '' 21const secretKey = JSON.parse(readFileSync(wallet, 'utf-8')) 22const keypair = umi.eddsa.createKeypairFromSecretKey(new Uint8Array(secretKey)) 23umi.use(keypairIdentity(keypair)) 24 25// Your token mint address and destination wallet 26const mintAddress = publicKey('') 27const destinationAddress = publicKey('') 28 29// Find the destination token account 30const destinationTokenAccount = findAssociatedTokenPda(umi, { 31 mint: mintAddress, 32 owner: destinationAddress, 33}) 34 35// Create the destination token account if it doesn't exist and mint tokens 36await transactionBuilder() 37 .add(createTokenIfMissing(umi, { 38 mint: mintAddress, 39 owner: destinationAddress, 40 })) 41 // Mint 100 tokens to the destination 42 .add( 43 mintTokensTo(umi, { 44 mint: mintAddress, 45 token: destinationTokenAccount, 46 amount: 100, 47 })) 48 .sendAndConfirm(umi) 49 50console.log('Minted 100 tokens') 51console.log('Mint:', mintAddress) 52console.log('To:', destinationTokenAccount) 1# Mint Additional Tokens using the Metaplex CLI 2 3# Mint tokens to your own wallet (default) 4# Usage: mplx toolbox token mint 5mplx toolbox token mint 6 7# Mint tokens to a specific recipient 8mplx toolbox token mint --recipient 9 10# Example: Mint 1000 tokens (0 decimals) to your wallet 11mplx toolbox token mint 7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU 1000 12 13# Example: Mint 1000 tokens (9 decimals) to your wallet 14# Amount is in smallest units: 1000 * 10^9 = 1000000000000 15mplx toolbox token mint 7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU 1000000000000 16 17# Example: Mint tokens to another wallet 18mplx toolbox token mint 7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU 1000 \ 19 --recipient 9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM 20 21# Note: You must be the mint authority to mint additional tokens Parameters ---------- Customize these parameters for your mint operation: | Parameter | Description | | --- | --- | | `mintAddress` | The token mint address | | `destinationAddress` | Wallet address to receive the tokens | | `amount` | Number of tokens to mint | How It Works ------------ The minting process involves three steps, that you may or may not have to execute manually, depending on the tool you are using. The following steps are focusing on umi: 1. **Find destination token account** - Locate the recipient's token account using `findAssociatedTokenPda` 2. **Create token account if needed** - Use `createTokenIfMissing` to ensure the recipient has a token account 3. **Mint tokens** - Execute the mint with `mintTokensTo` Requirements ------------ To mint additional tokens, you must **be the mint authority** - Only the wallet designated as the mint authority can mint new tokens Important Notes --------------- * Depending on the tool you are using, you may or may not have to account for decimals. The `amount` should account for decimals (e.g., for 9 decimals, minting 1 token requires `amount: 1_000_000_000`) * You can mint to any wallet address—the token account will be created if it doesn't exist * Only the mint authority can mint new tokens Previous [← Read Token Data](https://developers.metaplex.com/tokens/read-token) Next [Transfer Tokens →](https://developers.metaplex.com/tokens/transfer-a-token) --- # How to Transfer Fungible Tokens on Solana | Tokens Transfer fungible tokens (SPL tokens) between wallets on the Solana blockchain. Transfer Tokens --------------- In the following section you can find a full code example and the Parameters that you might have to change. You can learn more about token transfer details in the [Token Metadata program](https://developers.metaplex.com/smart-contracts/token-metadata) pages. Umi (JS)CLI SnippetFull Copy 1// To install all the required packages use the following command 2// npm install @metaplex-foundation/mpl-toolbox @metaplex-foundation/umi @metaplex-foundation/umi-bundle-defaults 3import { 4 createTokenIfMissing, 5 findAssociatedTokenPda, 6 transferTokens, 7} from '@metaplex-foundation/mpl-toolbox'; 8import { 9 keypairIdentity, 10 publicKey, 11 transactionBuilder, 12} from '@metaplex-foundation/umi'; 13import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'; 14import { readFileSync } from 'fs'; 15 16// Initialize Umi with Devnet endpoint 17 const umi = createUmi('https://api.devnet.solana.com') 18 19 // Load your wallet/keypair 20 const wallet = '' 21 const secretKey = JSON.parse(readFileSync(wallet, 'utf-8')) 22 const keypair = umi.eddsa.createKeypairFromSecretKey(new Uint8Array(secretKey)) 23 umi.use(keypairIdentity(keypair)) 24 25 // Your token mint address and destination wallet 26 const mintAddress = publicKey('') 27 const destinationAddress = publicKey('') 28 29// Find the source token account (your account) 30 const sourceTokenAccount = findAssociatedTokenPda(umi, { 31 mint: mintAddress, 32 owner: umi.identity.publicKey, 33 }) 34 35 // Find the destination token account 36 const destinationTokenAccount = findAssociatedTokenPda(umi, { 37 mint: mintAddress, 38 owner: destinationAddress, 39 }) 40 41 // Create the destination token account if it doesn't exist 42 transactionBuilder() 43 .add(createTokenIfMissing(umi, { 44 mint: mintAddress, 45 owner: destinationAddress, 46 })) 47 // Transfer 100 tokens 48 .add( 49 transferTokens(umi, { 50 source: sourceTokenAccount, 51 destination: destinationTokenAccount, 52 amount: 100, 53 })) 54 .sendAndConfirm(umi) 55 56console.log('Transferred 100 tokens') 57 console.log('From:', sourceTokenAccount) 58 console.log('To:', destinationTokenAccount) 1# Transfer Tokens using the Metaplex CLI 2 3# Usage: mplx toolbox token transfer 4mplx toolbox token transfer 5 6# Example: Transfer 100 tokens (0 decimals) 7mplx toolbox token transfer 7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU 100 9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM 8 9# Example: Transfer 100 tokens (9 decimals) 10# Amount is in smallest units: 100 * 10^9 = 100000000000 11mplx toolbox token transfer 7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU 100000000000 9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM 12 13# Note: If the destination doesn't have a token account, it will be created automatically Parameters ---------- Customize these parameters for your transfer: | Parameter | Description | | --- | --- | | `mintAddress` | The token mint address | | `destinationAddress` | Recipient wallet address | | `amount` | Number of tokens to transfer | How It Works ------------ The transfer process involves four steps: 1. **Find source token account** - Locate your token account using `findAssociatedTokenPda` 2. **Find destination token account** - Locate the recipient's token account 3. **Create destination token account if needed** - Use `createTokenIfMissing` to ensure the recipient has a token account 4. **Transfer tokens** - Execute the transfer with `transferTokens` Token Accounts -------------- Each wallet has an Associated Token Account (ATA) for each type of token they hold. The `findAssociatedTokenPda` function derives the address of these accounts based on the wallet address and token mint. The `createTokenIfMissing` function automatically creates the token account if it doesn't exist yet, or does nothing if it already exists. This ensures the transfer will always succeed. Previous [← Mint Tokens](https://developers.metaplex.com/tokens/mint-tokens) Next [Update Token Metadata →](https://developers.metaplex.com/tokens/update-token) --- # How to Burn Fungible Tokens on Solana | Tokens Burn fungible tokens to permanently remove them from circulation on the Solana blockchain. Burn Tokens ----------- In the following section you can find a full code example and the parameters that you might have to change. Burning tokens permanently destroys them—this action cannot be undone. Umi (JS) SnippetFull Copy 1// To install all the required packages use the following command 2// npm install @metaplex-foundation/mpl-toolbox @metaplex-foundation/umi @metaplex-foundation/umi-bundle-defaults 3import { 4 burnToken, 5 findAssociatedTokenPda, 6} from '@metaplex-foundation/mpl-toolbox'; 7import { 8 keypairIdentity, 9 publicKey, 10} from '@metaplex-foundation/umi'; 11import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'; 12import { readFileSync } from 'fs'; 13 14// Initialize Umi with Devnet endpoint 15const umi = createUmi('https://api.devnet.solana.com') 16 17// Load your wallet/keypair 18const wallet = '' 19const secretKey = JSON.parse(readFileSync(wallet, 'utf-8')) 20const keypair = umi.eddsa.createKeypairFromSecretKey(new Uint8Array(secretKey)) 21umi.use(keypairIdentity(keypair)) 22 23// Your token mint address 24const mintAddress = publicKey('') 25 26// Find the token account to burn from 27const tokenAccount = findAssociatedTokenPda(umi, { 28 mint: mintAddress, 29 owner: umi.identity.publicKey, 30}) 31 32// Burn 100 tokens 33await burnToken(umi, { 34 account: tokenAccount, 35 mint: mintAddress, 36 amount: 100, 37}).sendAndConfirm(umi) 38 39console.log('Burned 100 tokens') 40console.log('Mint:', mintAddress) 41console.log('Token Account:', tokenAccount) Parameters ---------- Customize these parameters for your burn operation: | Parameter | Description | | --- | --- | | `mintAddress` | The token mint address | | `amount` | Number of tokens to burn | How It Works ------------ The burn process involves two steps: 1. **Find your token account** - Locate your token account using `findAssociatedTokenPda` 2. **Burn tokens** - Execute the burn with `burnToken` When to Burn Tokens ------------------- Common use cases for burning tokens include: * **Reducing supply** - Decrease total circulating supply * **Deflationary mechanics** - Implement tokenomics that reduce supply over time * **Error correction** - Remove tokens minted by mistake Important Notes --------------- * Burning is **permanent** and cannot be reversed * You can only burn tokens that you own * The `amount` should account for decimals (e.g., for 9 decimals, burning 1 token requires `amount: 1_000_000_000`) Previous [← Update Token Metadata](https://developers.metaplex.com/tokens/update-token) Next [Create a Token with Anchor →](https://developers.metaplex.com/tokens/anchor/create-token) --- # Fetch an NFT | NFTs Fetch NFT data from the Solana blockchain. Fetch an NFT or a Collection ---------------------------- In the following section you can find a full code example and the parameters that you might need to change. You can learn more about fetching NFTs and collections in the [Core documentation](https://developers.metaplex.com/smart-contracts/core/fetch) . Umi (JS)CLIDAS (JS)DAS (cURL) SnippetFull Copy 1import { fetchAsset, fetchCollection, mplCore } from '@metaplex-foundation/mpl-core'; 2import { publicKey } from '@metaplex-foundation/umi'; 3import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'; 4 5// Initialize UMI 6const umi = createUmi('https://api.devnet.solana.com') 7 .use(mplCore()) 8 9// Fetch a Core Asset 10const assetAddress = publicKey('AssetAddressHere...') 11const asset = await fetchAsset(umi, assetAddress) 12 13// Fetch a Core Collection 14const collectionAddress = publicKey('CollectionAddressHere...') 15const collection = await fetchCollection(umi, collectionAddress) 16 17console.log('Asset fetched:', asset) 18console.log('Name:', asset.name) 19console.log('Owner:', asset.owner) 20console.log('URI:', asset.uri) 21 22console.log('\nCollection fetched:', collection) 23console.log('Name:', collection.name) 24console.log('URI:', collection.uri) 1# Fetch an NFT using the Metaplex CLI 2 3# Fetch asset by ID 4mplx core fetch asset 5 6# Download all files to a directory 7mplx core fetch asset --download --output ./assets 8 9# Download only the image 10mplx core fetch asset --download --image 11 12# Download only the metadata 13mplx core fetch asset --download --metadata 1// npm install @metaplex-foundation/umi @metaplex-foundation/umi-bundle-defaults @metaplex-foundation/digital-asset-standard-api 2import { publicKey } from '@metaplex-foundation/umi' 3import { createUmi } from '@metaplex-foundation/umi-bundle-defaults' 4import { dasApi } from '@metaplex-foundation/digital-asset-standard-api' 5 6// Initialize Umi with a DAS-enabled RPC endpoint 7const umi = createUmi('https://api.devnet.solana.com').use(dasApi()) 8 9// The address of the NFT you want to fetch 10const assetAddress = publicKey('YOUR_NFT_ADDRESS') 11 12// Fetch the asset using DAS API 13const asset = await umi.rpc.getAsset(assetAddress) 14 15console.log('Asset ID:', asset.id) 16console.log('Name:', asset.content.metadata?.name) 17console.log('Description:', asset.content.metadata?.description) 18console.log('Image:', asset.content.links?.image) 19console.log('Owner:', asset.ownership.owner) 20console.log('Interface:', asset.interface) 1# Fetch an NFT using the DAS API 2curl -X POST \ 3 -H "Content-Type: application/json" \ 4 -d '{ 5 "jsonrpc": "2.0", 6 "id": 1, 7 "method": "getAsset", 8 "params": { 9 "id": "" 10 } 11 }' \ 12 https://api.devnet.solana.com Parameters ---------- Customize these parameters for your fetch: | Parameter | Description | | --- | --- | | `assetAddress` | The public key of the NFT asset | | `collectionAddress` | The public key of the collection (optional) | How It Works ------------ The fetch process involves these steps: 1. **Get the address** - You need the public key of the NFT asset or collection you want to fetch 2. **Fetch asset data** - Use `fetchAsset` to retrieve NFT information including name, URI, owner, and plugins 3. **Fetch collection data** - Use `fetchCollection` to retrieve collection information (optional) NFT and Collection Data ----------------------- When you fetch an asset, you get back all its data: * **Name** - The NFT's name * **URI** - Link to the metadata JSON * **Owner** - The wallet that owns the NFT * **Update Authority** - Who can modify the NFT * **Plugins** - Any attached plugins like royalties or attributes When you fetch a collection, you get: * **Name** - The collection's name * **URI** - Link to the collection metadata JSON * **Update Authority** - Who can modify the collection * **Num Minted** - Number of assets in the collection * **Plugins** - Any attached plugins like royalties or attributes Previous [← Create an NFT](https://developers.metaplex.com/nfts/create-nft) Next [Update an NFT →](https://developers.metaplex.com/nfts/update-nft) --- # Create an NFT | NFTs Create an NFT using Metaplex Core on Solana. What You'll Learn ----------------- This guide shows you how to create an NFT with: * Custom name and metadata * Image and description * Optional attributes Create an NFT ------------- The following code is a fully runnable example. Below the parameters that you might want to customize are shown. You can learn more about NFT creation details in the [Core documentation](https://developers.metaplex.com/smart-contracts/core) . Umi (JS)CLI SnippetFull Copy 1import { createUmi } from '@metaplex-foundation/umi-bundle-defaults' 2import { create } from '@metaplex-foundation/mpl-core' 3import { mplCore } from '@metaplex-foundation/mpl-core' 4 5// Initialize UMI 6const umi = createUmi('https://api.devnet.solana.com') 7 .use(mplCore()) 8 9// Create a new NFT asset 10const asset = await create(umi, { 11 name: 'My NFT', 12 uri: 'https://example.com/metadata.json' 13}).sendAndConfirm(umi) 14 15console.log('Asset created:', asset.publicKey) 1# Create an NFT using the Metaplex CLI 2 3# Interactive wizard mode (recommended) 4mplx core asset create --wizard 5 6# Simple creation with name and URI 7mplx core asset create --name "My NFT" --uri "https://example.com/metadata.json" 8 9# Create with files (image + metadata) 10mplx core asset create --files --image "./my-nft.png" --json "./metadata.json" On-Chain Parameters ------------------- Customize these parameters for your NFT: | Parameter | Description | | --- | --- | | `name` | NFT name (max 32 characters) | | `uri` | Link to off-chain metadata JSON | Metadata and Images ------------------- Below you can find the minimum metadata that you need to upload. Additional fields like `external_url`, `attributes`, and `properties` are optional and can be found with further description and examples in the [JSON schema](https://developers.metaplex.com/smart-contracts/core/json-schema) . You need to upload the JSON and the image so that they are accessible from everywhere. We recommend to use a web3 storage provider like Arweave. If you want to do so by code you can follow this [guide](https://developers.metaplex.com/smart-contracts/mpl-hybrid/guides/create-deterministic-metadata-with-turbo) . `{ "name": "My NFT", "description": "An NFT on Solana", "image": "https://arweave.net/tx-hash", "attributes": [] }` Plugins ------- MPL Core Assets support the use of plugins at both the Collection and Asset levels. To create a Core Asset with a plugin you pass in the plugin type and its parameters into the `plugins` array arg during creation. You can find more information about plugins in the [Plugins Overview](https://developers.metaplex.com/smart-contracts/core/plugins) page. In the context of NFTs like Profile Pictures the [Royalties plugin](https://developers.metaplex.com/smart-contracts/core/plugins/royalties) is a common use case. Previous [← Overview](https://developers.metaplex.com/nfts) Next [Fetch an NFT →](https://developers.metaplex.com/nfts/fetch-nft) --- # Launch a Token on Solana — Genesis Fair Launch Guide | Metaplex Launch an SPL token on Solana using [Genesis](https://developers.metaplex.com/smart-contracts/genesis) Launch Pools. This guide walks you through a fair launch where users deposit SOL during a window and receive tokens proportional to their share of total deposits — all handled transparently on-chain. No-Code Option Don't want to write code? Use the [Metaplex token launchpad](https://www.metaplex.com/) to launch a token with no coding required. This guide is for developers who want to build their own token launch experience or host a token sale on their own website using the Genesis SDK. Other Launch Methods This guide covers the **Launch Pool** fair launch method, but Genesis also supports **[Presale](https://developers.metaplex.com/smart-contracts/genesis/presale) ** token sales where tokens are sold at a fixed price. Check the [Genesis overview](https://developers.metaplex.com/smart-contracts/genesis) to compare methods and choose the best fit for your project. Overview -------- Genesis is a Solana token launchpad that provides fair, on-chain token launch mechanisms. Unlike a centralized token sale platform where tokens are sold at a fixed price, a Launch Pool lets the market determine token distribution — every participant receives tokens proportional to their deposit, ensuring a fair and transparent token generation event (TGE). All SPL token creation, fundraising, and distribution happens on-chain with no intermediaries. A Launch Pool token launch has three phases: 1. **Setup** (you run once) - Create the token, configure the launch, and activate it 2. **Deposit Period** (users interact) - Users deposit SOL during the window you configured 3. **Post-Launch** (you + users) - Execute the transition, users claim tokens, you revoke authorities This guide walks you through creating **four separate scripts** that you'll run at different stages: | Script | When to Run | Purpose | | --- | --- | --- | | `launch.ts` | Once, to start | Creates your token and activates the launch | | `transition.ts` | After deposits close | Moves collected SOL to your unlocked bucket | | `claim.ts` | After transition | Users run this to claim their tokens | | `revoke.ts` | When launch is complete | Permanently removes mint/freeze authorities | Prerequisites ------------- Create a new project and install dependencies: `mkdir my-token-launch cd my-token-launch npm init -y npm install @metaplex-foundation/genesis @metaplex-foundation/umi @metaplex-foundation/umi-bundle-defaults @metaplex-foundation/mpl-toolbox` The Complete Launch Script -------------------------- Below is a complete, runnable script. Each section is commented to explain what it does. You'll run this script **once** to set up your launch. Keypair Required You need a Solana keypair file on your machine to sign transactions. This is typically your Solana CLI wallet located at `~/.config/solana/id.json`. Update the `walletFile` path in the script to point to your keypair file. Make sure this wallet has SOL for transaction fees. Create a file called `launch.ts`: `import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'; import { genesis, initializeV2, findGenesisAccountV2Pda, findLaunchPoolBucketV2Pda, findUnlockedBucketV2Pda, addLaunchPoolBucketV2, addUnlockedBucketV2, finalizeV2, } from '@metaplex-foundation/genesis'; import { generateSigner, publicKey, keypairIdentity } from '@metaplex-foundation/umi'; async function main() { // ============================================ // SETUP: Configure your connection and wallet // ============================================ const umi = createUmi('https://api.devnet.solana.com') .use(genesis()); // Load your wallet keypair from a file on your machine // This is typically your Solana CLI wallet at ~/.config/solana/id.json // Or use any keypair file you have access to const walletFile = '/path/to/your/keypair.json'; // <-- UPDATE THIS PATH const secretKey = JSON.parse(require('fs').readFileSync(walletFile, 'utf-8')); const keypair = umi.eddsa.createKeypairFromSecretKey(new Uint8Array(secretKey)); umi.use(keypairIdentity(keypair)); // ============================================ // CONFIGURATION: Customize these values // ============================================ // Token details const TOKEN_NAME = 'My Token'; const TOKEN_SYMBOL = 'MTK'; const TOKEN_URI = 'https://example.com/metadata.json'; // Your metadata JSON URL const TOTAL_SUPPLY = 1_000_000_000_000n; // 1 trillion tokens (adjust as needed) // Timing (in seconds from now) const DEPOSIT_DURATION = 24 * 60 * 60; // 24 hours const CLAIM_DURATION = 7 * 24 * 60 * 60; // 7 days // Calculate timestamps const now = BigInt(Math.floor(Date.now() / 1000)); const depositStart = now; const depositEnd = now + BigInt(DEPOSIT_DURATION); const claimStart = depositEnd + 1n; const claimEnd = claimStart + BigInt(CLAIM_DURATION); // ============================================ // STEP 1: Create your token // ============================================ console.log('Step 1: Creating token...'); const baseMint = generateSigner(umi); const [genesisAccount] = findGenesisAccountV2Pda(umi, { baseMint: baseMint.publicKey, genesisIndex: 0, }); await initializeV2(umi, { baseMint, fundingMode: 0, totalSupplyBaseToken: TOTAL_SUPPLY, name: TOKEN_NAME, uri: TOKEN_URI, symbol: TOKEN_SYMBOL, }).sendAndConfirm(umi); console.log('✓ Token created!'); console.log(' Token mint:', baseMint.publicKey); console.log(' Genesis account:', genesisAccount); // ============================================ // STEP 2: Add Launch Pool bucket // This is where users will deposit SOL // ============================================ console.log('\nStep 2: Adding Launch Pool bucket...'); const [launchPoolBucket] = findLaunchPoolBucketV2Pda(umi, { genesisAccount, bucketIndex: 0, }); const [unlockedBucket] = findUnlockedBucketV2Pda(umi, { genesisAccount, bucketIndex: 0, }); await addLaunchPoolBucketV2(umi, { genesisAccount, baseMint: baseMint.publicKey, baseTokenAllocation: TOTAL_SUPPLY, depositStartCondition: { __kind: 'TimeAbsolute', padding: Array(47).fill(0), time: depositStart, triggeredTimestamp: null, }, depositEndCondition: { __kind: 'TimeAbsolute', padding: Array(47).fill(0), time: depositEnd, triggeredTimestamp: null, }, claimStartCondition: { __kind: 'TimeAbsolute', padding: Array(47).fill(0), time: claimStart, triggeredTimestamp: null, }, claimEndCondition: { __kind: 'TimeAbsolute', padding: Array(47).fill(0), time: claimEnd, triggeredTimestamp: null, }, minimumDepositAmount: null, endBehaviors: [ { __kind: 'SendQuoteTokenPercentage', padding: Array(4).fill(0), destinationBucket: publicKey(unlockedBucket), percentageBps: 10000, // 100% of collected SOL goes to unlocked bucket processed: false, }, ], }).sendAndConfirm(umi); console.log('✓ Launch Pool bucket added!'); console.log(' Bucket address:', launchPoolBucket); // ============================================ // STEP 3: Add Unlocked bucket // This receives the collected SOL for your team // ============================================ console.log('\nStep 3: Adding Unlocked bucket...'); await addUnlockedBucketV2(umi, { genesisAccount, baseMint: baseMint.publicKey, baseTokenAllocation: 0n, recipient: umi.identity.publicKey, claimStartCondition: { __kind: 'TimeAbsolute', padding: Array(47).fill(0), time: claimStart, triggeredTimestamp: null, }, claimEndCondition: { __kind: 'TimeAbsolute', padding: Array(47).fill(0), time: claimEnd, triggeredTimestamp: null, }, backendSigner: null, }).sendAndConfirm(umi); console.log('✓ Unlocked bucket added!'); console.log(' Bucket address:', unlockedBucket); // ============================================ // STEP 4: Finalize - activates the launch // After this, no more changes can be made // ============================================ console.log('\nStep 4: Finalizing...'); await finalizeV2(umi, { baseMint: baseMint.publicKey, genesisAccount, }).sendAndConfirm(umi); console.log('✓ Launch is now ACTIVE!'); // ============================================ // SUMMARY: Save these addresses! // ============================================ console.log('\n========================================'); console.log('LAUNCH COMPLETE - SAVE THESE ADDRESSES:'); console.log('========================================'); console.log('Token mint:', baseMint.publicKey); console.log('Genesis account:', genesisAccount); console.log('Launch Pool bucket:', launchPoolBucket); console.log('Unlocked bucket:', unlockedBucket); console.log(''); console.log('TIMING:'); console.log('Deposits open:', new Date(Number(depositStart) * 1000).toISOString()); console.log('Deposits close:', new Date(Number(depositEnd) * 1000).toISOString()); console.log('Claims open:', new Date(Number(claimStart) * 1000).toISOString()); console.log('Claims close:', new Date(Number(claimEnd) * 1000).toISOString()); } main().catch(console.error);` Run the script: `npx ts-node launch.ts` **Save the addresses that are printed!** You'll need them for the next steps. What Happens Next ----------------- After running the launch script, your launch is live. Here's what happens during each phase: ### During the Deposit Period Users deposit SOL using your frontend or directly via the SDK. Each deposit: * Has a fee applied * Is tracked in a deposit PDA * Can be partially or fully withdrawn (with fee) ### After Deposits Close Once the deposit period ends, you need to run the **transition** to move the collected SOL to the unlocked bucket. Create a file called `transition.ts`: `import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'; import { genesis, transitionV2, WRAPPED_SOL_MINT, } from '@metaplex-foundation/genesis'; import { findAssociatedTokenPda } from '@metaplex-foundation/mpl-toolbox'; import { publicKey, keypairIdentity } from '@metaplex-foundation/umi'; async function main() { const umi = createUmi('https://api.devnet.solana.com') .use(genesis()); // Load your wallet keypair (same wallet used for launch) const walletFile = '/path/to/your/keypair.json'; // <-- UPDATE THIS PATH const secretKey = JSON.parse(require('fs').readFileSync(walletFile, 'utf-8')); const keypair = umi.eddsa.createKeypairFromSecretKey(new Uint8Array(secretKey)); umi.use(keypairIdentity(keypair)); // Fill in the addresses printed by your launch script const genesisAccount = publicKey('YOUR_GENESIS_ACCOUNT'); const baseMint = publicKey('YOUR_TOKEN_MINT'); const launchPoolBucket = publicKey('YOUR_LAUNCH_POOL_BUCKET'); const unlockedBucket = publicKey('YOUR_UNLOCKED_BUCKET'); const unlockedBucketQuoteTokenAccount = findAssociatedTokenPda(umi, { owner: unlockedBucket, mint: WRAPPED_SOL_MINT, }); console.log('Executing transition...'); await transitionV2(umi, { genesisAccount, primaryBucket: launchPoolBucket, baseMint, }) .addRemainingAccounts([ { pubkey: unlockedBucket, isSigner: false, isWritable: true, }, { pubkey: publicKey(unlockedBucketQuoteTokenAccount), isSigner: false, isWritable: true, }, ]) .sendAndConfirm(umi); console.log('✓ Transition complete! SOL moved to unlocked bucket.'); } main().catch(console.error);` Run after the deposit period ends: `npx ts-node transition.ts` ### Users Claim Tokens After the transition, users can claim their tokens. Each user receives tokens proportional to their share of total deposits: `userTokens = (userDeposit / totalDeposits) * totalTokenSupply` Users can claim via your frontend or using this script (create `claim.ts`): `import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'; import { genesis, claimLaunchPoolV2, } from '@metaplex-foundation/genesis'; import { publicKey, keypairIdentity } from '@metaplex-foundation/umi'; async function main() { const umi = createUmi('https://api.devnet.solana.com') .use(genesis()); // Load the user's wallet keypair (whoever deposited SOL) const walletFile = '/path/to/your/keypair.json'; // <-- UPDATE THIS PATH const secretKey = JSON.parse(require('fs').readFileSync(walletFile, 'utf-8')); const keypair = umi.eddsa.createKeypairFromSecretKey(new Uint8Array(secretKey)); umi.use(keypairIdentity(keypair)); // Fill in the addresses from the launch const genesisAccount = publicKey('YOUR_GENESIS_ACCOUNT'); const baseMint = publicKey('YOUR_TOKEN_MINT'); const launchPoolBucket = publicKey('YOUR_LAUNCH_POOL_BUCKET'); console.log('Claiming tokens...'); await claimLaunchPoolV2(umi, { genesisAccount, bucket: launchPoolBucket, baseMint, recipient: umi.identity.publicKey, }).sendAndConfirm(umi); console.log('✓ Tokens claimed!'); } main().catch(console.error);` ### Finalize: Revoke Authorities After the launch is complete, revoke mint and freeze authorities. This signals to holders that no additional tokens can ever be minted. **This is irreversible.** Once revoked, you can never mint additional tokens or freeze accounts. Only do this when you're certain the launch is complete. Create `revoke.ts`: `import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'; import { genesis, revokeMintAuthorityV2, revokeFreezeAuthorityV2, } from '@metaplex-foundation/genesis'; import { publicKey, keypairIdentity } from '@metaplex-foundation/umi'; async function main() { const umi = createUmi('https://api.devnet.solana.com') .use(genesis()); // Load your wallet keypair (same wallet used for launch) const walletFile = '/path/to/your/keypair.json'; // <-- UPDATE THIS PATH const secretKey = JSON.parse(require('fs').readFileSync(walletFile, 'utf-8')); const keypair = umi.eddsa.createKeypairFromSecretKey(new Uint8Array(secretKey)); umi.use(keypairIdentity(keypair)); // Fill in your token mint address from the launch const baseMint = publicKey('YOUR_TOKEN_MINT'); console.log('Revoking mint authority...'); await revokeMintAuthorityV2(umi, { baseMint, }).sendAndConfirm(umi); console.log('✓ Mint authority revoked'); console.log('Revoking freeze authority...'); await revokeFreezeAuthorityV2(umi, { baseMint, }).sendAndConfirm(umi); console.log('✓ Freeze authority revoked'); console.log('\n✓ Launch complete! Token is fully decentralized.'); } main().catch(console.error);` Next Steps ---------- * [Genesis Overview](https://developers.metaplex.com/smart-contracts/genesis) - Learn more about the Solana token launchpad * [Launch Pool](https://developers.metaplex.com/smart-contracts/genesis/launch-pool) - Detailed fair launch documentation * [Presale](https://developers.metaplex.com/smart-contracts/genesis/presale) - Run a token presale at a fixed price * [Aggregation API](https://developers.metaplex.com/smart-contracts/genesis/aggregation) - Query launch and token sale data via API Previous [← Create a Token](https://developers.metaplex.com/tokens/create-a-token) Next [Aggregate Token Launches →](https://developers.metaplex.com/smart-contracts/genesis/aggregation) --- # Stability Index | Developer Hub The Metaplex Stability Index provides information about the stability of each product in the Metaplex ecosystem. This helps developers make informed decisions about which products to use in their projects. ### Stability 3 - Code Freeze Functionality and features of program are finalized. Security firms perform final audits before upgrade authority is destroyed. | Product Name | | --- | | Token Metadata | ### Stability 2 - Stable Compatibility with the ecosystem is a high priority. | Product Name | | --- | | Token Auth Rules | | Bubblegum | | Candy Machine v3 | | Sugar | | Umi | | Amman | | Shank | ### Stability 1 - Experimental The feature may emit warnings. The feature is not subject to Semantic Versioning rules. Non-backward compatible changes or removal may occur in any future release. Use of the feature is not recommended in production or mainnet environments. | Product Name | | --- | | Genesis | | Core | | Fusion | | Hydra | | Kinobi | | Gum Drop | ### Stability 0 - Deprecated The feature may emit warnings. Backward compatibility is not guaranteed. | Product Name | | --- | | Candy Machine v2 | | Candy Machine v1 | | Auction House | | Auctioneer | | Auctions | | NFT Packs | | Fair Launch | | Membership Token Sale | | Token Entangler | | Fireball | --- # Overview | Amman **A** **m** odern **man** datory toolbelt to help test solana SDK libraries and apps on a locally running validator. [Getting Started](https://developers.metaplex.com/dev-tools/amman/getting-started) ----------------------------------------------------------------------------------- Find the language or library of your choice and get started essentials programs. [Configurations](https://developers.metaplex.com/dev-tools/amman/pre-made-configs) ----------------------------------------------------------------------------------- A set of ready made configurations for you to try and modify. Next [Getting Started →](https://developers.metaplex.com/dev-tools/amman/getting-started) --- # CLI Commands | Amman `amman [command] Commands: amman start Launches a solana-test-validator and the amman relay and/or mock storage if so configured amman stop Stops the relay and storage and kills the running solana test validator amman logs Launches 'solana logs' and pipes them through a prettifier amman airdrop Airdrops provided Sol to the payer amman label Adds labels for accounts or transactions to amman amman account Retrieves account information for a PublicKey or a label or shows all labeled accounts amman run Executes the provided command after expanding all address labels Options: --help Show help [boolean] --version Show version number [boolean]` Running Commands ---------------- `npx amman start ` If no `config.js` is provided _amman_ looks for an `.ammanrc.js` file in the current directory. If that isn't found either it uses a default config. If you added Amman into your package.json scripts you can respectively run Amman from your package installer of choice. `// npm npm run amman:start // yarn yarn amman:start // pnpm pnpm run amman:start` Previous [← Getting Started](https://developers.metaplex.com/dev-tools/amman/getting-started) Next [Configuration →](https://developers.metaplex.com/dev-tools/amman/configuration) --- # Configuration | Amman When executed Amman will look for the configuration `.ammanrc.js` in the project root. If this file is not present Amman will load up with a default configuration. The config should be a JavaScript module exporting 'validator' with any of the below properties: * **killRunningValidators**: if true will kill any solana-test-validators currently running on the system. * **programs**: bpf programs which should be loaded into the test validator * **accountsCluster**: default cluster to clone remote accounts from * **accounts**: array of remote accounts to load into the test validator * **jsonRpcUrl**: the URL at which the test validator should listen for JSON RPC requests * **websocketUrl**: for the RPC websocket * **ledgerDir**: where the solana test validator writes the ledger * **resetLedger**: if true the ledger is reset to genesis at startup * **verifyFees**: if true the validator is not considered fully started up until it charges transaction fees Example Configs --------------- ### Validator/Relay/Storage Config with Defaults Below is an example config with all values set to the defaults except for an added program and a `relay` and `storage` config. A _amman-explorer relay_ is launched automatically with the validator unless it is running in a _CI_ environment and if a relay is already running on the known _relay port_, it is killed first. A _mock storage_ is launched only if a `storage` config is provided. In case a storage server is already running on the known _storage port_, it is killed first. `import { LOCALHOST, tmpLedgerDir } from '@metaplex-foundation/amman' module.exports = { validator: { killRunningValidators: true, programs: [ { label: 'Token Metadata Program', programId: programIds.metadata, deployPath: localDeployPath('mpl_token_metadata'), }, ], jsonRpcUrl: LOCALHOST, websocketUrl: '', commitment: 'confirmed', ledgerDir: tmpLedgerDir(), resetLedger: true, verifyFees: false, detached: process.env.CI != null, }, relay: { enabled: process.env.CI == null, killRunningRelay: true, }, storage: { enabled: process.env.CI == null, storageId: 'mock-storage', clearOnStart: true, }, }` ### Config with Remote Accounts and Programs Amman can pull both accounts and programs for local use and testing from the cluster of your choice. `module.exports = { validator: { // By default Amman will pull the account data from the accountsCluster (can be overridden on a per account basis) accountsCluster: 'https://api.metaplex.solana.com', accounts: [ { label: 'Token Metadata Program', accountId: 'metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s', // marking executable as true will cause Amman to pull the executable data account as well automatically executable: true, }, { label: 'Random other account', accountId: '4VLgNs1jXgdciSidxcaLKfrR9WjATkj6vmTm5yCwNwui', // By default executable is false and is not required to be in the config // executable: false, // Providing a cluster here will override the accountsCluster field cluster: 'https://metaplex.devnet.rpcpool.com', }, ], }, }` ### Deactivating Test Validator Features For the different clusters like _devnet_ some features are disabled. By default the locally running solana-test-validator does not disable any features and thus behaves differently than the provided clusters. In order to run tests in a scenario that is closer to how they would run against a specific cluster you can match the features of it via the _matchFeatures_ config property: ``module.exports = { validator: { ... // The below disables any features that are deactivated for the `mainnet-beta` cluster matchFeatures: 'mainnet-beta', } }`` If you want to explicitly disable a set of features you can do so via the _deactivateFeatures_ property: `module.exports = { validator: { ... deactivateFeatures: ['21AWDosvp3pBamFW91KB35pNoaoZVTM7ess8nr2nt53B'], } }` **NOTE**: that only one of the above properties can be set #### Resources * [test validator runtime features](https://docs.solana.com/developing/test-validator#appendix-ii-runtime-features) * [runtime new features](https://docs.solana.com/developing/programming-model/runtime#new-features) Previous [← CLI Commands](https://developers.metaplex.com/dev-tools/amman/cli-commands) Next [Pre-made Configs →](https://developers.metaplex.com/dev-tools/amman/pre-made-configs) --- # Getting Started | Amman Prerequisites. -------------- Before running Amman your system will need to have a few things installed on your system. * [Rust](https://www.rust-lang.org/tools/install) * [Solana CLI](https://docs.solanalabs.com/cli/install) * [NodeJs](https://nodejs.org/en/download) Installation ------------ Once you have initiated a new or opened an existing project you can install Amman via a package manager. `npm i @metaplex-foundation/amman` Add to Scripts (optional) ------------------------- For ease of use you may wish to add the execution of Amman to your package.json scripts. package.json JavaScript `"scripts": { ... "amman:start": "npx amman start" },` Previous [← Overview](https://developers.metaplex.com/dev-tools/amman) Next [CLI Commands →](https://developers.metaplex.com/dev-tools/amman/cli-commands) --- # Pre Made Configurations | Amman Here are a few basic examples of Amman configurations for working with different Metaplex programs. You may need to modify these files to suite your needs. Bubblegum --------- This setup is designed to test and work with Metaplex Bubblegum. `const { LOCALHOST, tmpLedgerDir } = require("@metaplex-foundation/amman"); module.exports = { validator: { killRunningValidators: true, accountsCluster: "https://api.devnet.solana.com", accounts: [ { label: "Bubblegum", accountId: "BGUMAp9Gq7iTEuizy4pqaxsTyUCBK68MDfK752saRPUY", executable: true, }, { label: "Token Metadata Program", accountId: "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s", executable: true, }, { label: "Token Auth Rules", accountId: "auth9SigNpDKz4sJJ1DfCTuZrZNSAgh9sFD3rboVmgg", executable: true, }, { label: "Spl ATA Program", accountId: "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", executable: true, }, { label: "SPL Token Program", accountId: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", executable: true, }, { label: "SPL Account Compression", accountId: "cmtDvXumGCrqC1Age74AVPhSRVXJMd8PJS91L8KbNCK", executable: true }, { label: "SPL Noop Program", accountId: "noopb9bkMVfRPU8AsbpTUg8AQkHtKwMYZiFUjNRtMmV", executable: true }, ], jsonRpcUrl: LOCALHOST, websocketUrl: "", commitment: "confirmed", ledgerDir: tmpLedgerDir(), resetLedger: true, verifyFees: false, detached: process.env.CI != null, }, relay: { enabled: process.env.CI == null, killRunningRelay: true, }, storage: { enabled: process.env.CI == null, storageId: "mock-storage", clearOnStart: true, }, };` Candy Machine ------------- This setup is designed to test and work with Metaplex Candy Machine. `const { LOCALHOST, tmpLedgerDir } = require("@metaplex-foundation/amman"); module.exports = { validator: { killRunningValidators: true, accountsCluster: "https://api.devnet.solana.com", accounts: [ { label: "Candy Machine v3", accountId: "CndyV3LdqHUfDLmE5naZjVN8rBZz4tqhdefbAnjHG3JR", executable: true, }, { label: "Candy Guard", accountId: "Guard1JwRhJkVH6XZhzoYxeBVQe872VH6QggF4BWmS9g", executable: true, }, { label: "Token Metadata Program", accountId: "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s", executable: true, }, { label: "Token Auth Rules", accountId: "auth9SigNpDKz4sJJ1DfCTuZrZNSAgh9sFD3rboVmgg", executable: true, }, { label: "Spl ATA Program", accountId: "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", executable: true, }, { label: "SPL Token Program", accountId: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", executable: true, }, ], jsonRpcUrl: LOCALHOST, websocketUrl: "", commitment: "confirmed", ledgerDir: tmpLedgerDir(), resetLedger: true, verifyFees: false, detached: process.env.CI != null, }, relay: { enabled: process.env.CI == null, killRunningRelay: true, }, storage: { enabled: process.env.CI == null, storageId: "mock-storage", clearOnStart: true, }, };` Core Candy Machine ------------------ This setup is designed to test and work with Metaplex Core Candy Machine. Compared to the Candy Machine example above different Candy Machine program id and Candy Guard program id are used and the MPL-Core program is added. `const { LOCALHOST, tmpLedgerDir } = require("@metaplex-foundation/amman"); module.exports = { validator: { killRunningValidators: true, accountsCluster: "https://api.devnet.solana.com", accounts: [ { label: "Core Candy Machine", accountId: "CMACYFENjoBMHzapRXyo1JZkVS6EtaDDzkjMrmQLvr4J", executable: true, }, { label: "Core Candy Guard", accountId: "CMAGAKJ67e9hRZgfC5SFTbZH8MgEmtqazKXjmkaJjWTJ", executable: true, }, { label: "mpl-core", accountId: "CoREENxT6tW1HoK8ypY1SxRMZTcVPm7R94rH4PZNhX7d", executable: true, }, { label: "Token Metadata Program", accountId: "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s", executable: true, }, { label: "Token Auth Rules", accountId: "auth9SigNpDKz4sJJ1DfCTuZrZNSAgh9sFD3rboVmgg", executable: true, }, { label: "Spl ATA Program", accountId: "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL", executable: true, }, { label: "SPL Token Program", accountId: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", executable: true, }, ], jsonRpcUrl: LOCALHOST, websocketUrl: "", commitment: "confirmed", ledgerDir: tmpLedgerDir(), resetLedger: true, verifyFees: false, detached: process.env.CI != null, }, relay: { enabled: process.env.CI == null, killRunningRelay: true, }, storage: { enabled: process.env.CI == null, storageId: "mock-storage", clearOnStart: true, }, };` Previous [← Configuration](https://developers.metaplex.com/dev-tools/amman/configuration) --- # Introduction | Metaplex CLI Metaplex CLI ============ The Metaplex CLI is a powerful command-line tool that provides a comprehensive suite of utilities for interacting with the Metaplex protocol on Solana. Whether you're a developer building NFT applications or a creator managing digital assets, the CLI offers a robust set of features to streamline your workflow. Key Features ------------ ### Core Functionality * Create and manage MPL Core Assets and Collections * Upload and update asset metadata * Fetch asset and collection information * Manage asset properties and attributes ### Candy Machine Support * Create MPL Core Candy Machines with step-by-step guidance * Upload, validate, and insert assets with intelligent caching * Set up complex minting rules and guard groups * Real-time indicators for uploads, creation, and deployment ### Toolbox Utilities * Create and manage fungible tokens * Transfer SOL between addresses * Check SOL balances * Airdrop SOL for testing purposes ### Configuration Management * Manage multiple wallets * Configure RPC endpoints * Set preferred blockchain explorer * Customize CLI behavior Why Use the CLI? ---------------- 1. **Developer-Friendly**: Built with developers in mind, offering both simple commands and advanced options 2. **Interactive Mode**: User-friendly wizards for complex operations 3. **Flexible Configuration**: Customize your environment with multiple wallets and RPC endpoints 4. **Comprehensive Tools**: Everything you need for NFT and token management in one place 5. **Cross-Platform**: Works on Windows, macOS, and Linux Getting Started --------------- 1. [Install the CLI](https://developers.metaplex.com/dev-tools/cli/installation) 2. Configure your environment: * [Set up your wallet](https://developers.metaplex.com/dev-tools/cli/config/wallets) * [Configure RPC endpoints](https://developers.metaplex.com/dev-tools/cli/config/rpcs) * [Choose your preferred explorer](https://developers.metaplex.com/dev-tools/cli/config/explorer) 3. Start using the commands: * [Create assets](https://developers.metaplex.com/dev-tools/cli/core/create-asset) * [Create collections](https://developers.metaplex.com/dev-tools/cli/core/create-collection) Command Structure ----------------- The CLI follows a hierarchical command structure: `mplx [options]` Categories include: * `core`: MPL Core asset management * `cm`: Candy Machine operations * `toolbox`: Utility commands * `config`: Configuration management Best Practices -------------- 1. **Use Configuration**: Set up your wallets and RPC endpoints for a smoother experience 2. **Interactive Mode**: Use the `--wizard` flag for guided operations 3. **Check Balances**: Always verify your SOL balance before transactions 4. **Test First**: Use devnet for testing before mainnet deployment 5. **Backup**: Keep your wallet files and configuration secure Support and Resources --------------------- * [GitHub Repository](https://github.com/metaplex-foundation/cli) * [Documentation](https://developers.metaplex.com/) * [Discord Community](https://discord.gg/metaplex) Quick Start Examples -------------------- ### Create Your First Candy Machine Get started with the interactive wizard: `# Install and configure the CLI mplx config set keypair /path/to/my-wallet.json mplx config set rpcUrl https://api.mainnet-beta.solana.com # Create a candy machine with guided setup mplx cm create --wizard` ### Create Individual Assets For single assets or custom collections: `# Create a collection mplx core create-collection # Create an asset in the collection mplx core create-asset` Next Steps ---------- Ready to get started? Choose your path: 1. **For Setup**: Visit the [installation guide](https://developers.metaplex.com/dev-tools/cli/installation) 2. **For NFT Collections**: Start with the [candy machine wizard](https://developers.metaplex.com/dev-tools/cli/cm/create) 3. **For Individual Assets**: Begin with [asset creation](https://developers.metaplex.com/dev-tools/cli/core/create-asset) Next [Installation →](https://developers.metaplex.com/dev-tools/cli/installation) --- # Burn Compressed NFT | Metaplex CLI The `mplx bg nft burn` command permanently destroys a compressed NFT. This action is **irreversible**. Basic Usage ----------- `mplx bg nft burn ` Arguments --------- | Argument | Description | | --- | --- | | `ASSET_ID` | The compressed NFT asset ID to burn | Global Flags ------------ | Flag | Description | | --- | --- | | `-c, --config ` | Path to config file. Default is `~/.config/mplx/config.json` | | `-k, --keypair ` | Path to keypair file or ledger (e.g., `usb://ledger?key=0`) | | `-r, --rpc ` | RPC URL for the cluster | | `--json` | Format output as JSON | Examples -------- 1. Burn a compressed NFT: `mplx bg nft burn CNFTAssetIdHere` 1. Burn with JSON output: `mplx bg nft burn CNFTAssetIdHere --json` Output ------ `Fetching asset and proof data... ✓ Verifying ownership... ✓ Burning compressed NFT... ✓ Compressed NFT burned successfully! -------------------------------- Compressed NFT Burned! Asset ID: CNFTAssetIdHere Owner: YourWalletAddressHere Tree: 9hRvTxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Signature: 5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Explorer: https://solscan.io/tx/5xxx... --------------------------------` Authority Requirements ---------------------- To burn a compressed NFT, you must be either: * **Current Owner** - The wallet that currently owns the NFT * **Delegate** - A wallet that has been delegated authority over the NFT Notes ----- * **Warning**: Burning is permanent and irreversible * The RPC must support DAS API * Burning does not recover rent from the Merkle tree * The tree's capacity is not freed - the slot remains occupied (marked as burnt) * Any associated metadata remains on storage but is no longer linked Previous [← Transfer Compressed NFT](https://developers.metaplex.com/dev-tools/cli/bubblegum/transfer-cnft) Next [Token Creation →](https://developers.metaplex.com/dev-tools/cli/toolbox/token-create) --- # Bubblegum V2 (Compressed NFTs) | Metaplex CLI Bubblegum (Compressed NFTs) =========================== These CLI commands are for **Bubblegum V2** only. Bubblegum V2 uses [Metaplex Core collections](https://developers.metaplex.com/smart-contracts/core/collections) and is not compatible with Bubblegum V1 trees or Token Metadata collections. Bubblegum is Metaplex's compressed NFT (cNFT) program that allows you to create NFTs at a fraction of the cost of traditional NFTs. By using concurrent Merkle trees for state compression, compressed NFTs can be minted just the transaction costs after the initial tree creation cost. Key Concepts ------------ ### Merkle Trees Compressed NFTs are stored in Merkle trees rather than individual on-chain accounts. You must create a tree before minting any compressed NFTs. Tree size determines: * Maximum number of NFTs that can be stored * Upfront rent cost (paid once when creating the tree) * Proof size required for operations ### Collections Bubblegum V2 uses [Metaplex Core collections](https://developers.metaplex.com/smart-contracts/core/collections) (not Token Metadata collections). Create a Core collection first: `mplx core collection create --wizard` ### RPC Requirements Compressed NFT operations require an RPC endpoint that supports the [DAS (Digital Asset Standard) API](https://developers.metaplex.com/solana/rpcs-and-das#metaplex-das-api) . Standard Solana RPC endpoints do not support DAS and will not work for fetching, updating, transferring, or burning compressed NFTs. Command Structure ----------------- All Bubblegum commands follow this pattern: `mplx bg [options]` ### Available Commands **Tree Management** * `mplx bg tree create` - Create a new Merkle tree * `mplx bg tree list` - List all saved trees **NFT Operations** * `mplx bg nft create` - Mint a compressed NFT * `mplx bg nft fetch` - Fetch NFT data and merkle proof * `mplx bg nft update` - Update NFT metadata * `mplx bg nft transfer` - Transfer NFT to new owner * `mplx bg nft burn` - Permanently destroy NFT Quick Start ----------- 1. Configure a DAS-enabled RPC: `mplx config rpcs add ` 1. Create a Merkle tree: `mplx bg tree create --wizard` 1. Create a collection (optional but recommended): `mplx core collection create --wizard` 1. Mint compressed NFTs: `mplx bg nft create my-tree --wizard` Authority Model --------------- | Operation | Required Authority | | --- | --- | | Create NFT | Tree authority (or anyone if tree is public) | | Update NFT | Tree authority OR Collection update authority | | Transfer NFT | Current owner OR delegate | | Burn NFT | Current owner OR delegate | Next Steps ---------- * [Create a Merkle Tree](https://developers.metaplex.com/dev-tools/cli/bubblegum/create-tree) * [Create Compressed NFT](https://developers.metaplex.com/dev-tools/cli/bubblegum/create-cnft) * [Fetch Compressed NFT](https://developers.metaplex.com/dev-tools/cli/bubblegum/fetch-cnft) Previous [← Withdraw](https://developers.metaplex.com/cli/cm/withdraw) Next [Create Tree →](https://developers.metaplex.com/dev-tools/cli/bubblegum/create-tree) --- # Create Compressed NFT | Metaplex CLI The `mplx bg nft create` command mints a compressed NFT into an existing Merkle tree. If you do not have a Merkle Tree yet [create](https://developers.metaplex.com/dev-tools/cli/bubblegum/create-tree) one first. Basic Usage ----------- ### Interactive Wizard (Recommended) `mplx bg nft create --wizard` ### With Specific Tree `mplx bg nft create my-tree --wizard` ### File-Based Creation `mplx bg nft create my-tree --image ./nft.png --json ./metadata.json` ### URI-Based Creation `mplx bg nft create my-tree --name "My NFT" --uri "https://example.com/metadata.json"` Arguments --------- | Argument | Description | | --- | --- | | `TREE` | Tree name (saved) or Merkle tree address (optional in wizard mode) | Options ------- | Option | Description | | --- | --- | | `--wizard` | Use interactive wizard | | `--name ` | NFT name | | `--uri ` | Existing metadata URI | | `--json ` | Path to JSON metadata file (requires `--image`) | | `--image ` | Path to image file | | `--description ` | NFT description | | `--attributes ` | Attributes in "trait:value,trait:value" format | | `--animation ` | Path to animation/video file | | `--project-url ` | External project URL | | `--symbol ` | On-chain symbol | | `--royalties ` | Royalty percentage (0-100) | | `--collection ` | Collection mint address ([Metaplex Core collection](https://developers.metaplex.com/smart-contracts/core/collections)
) | | `--owner ` | Leaf owner public key (defaults to payer) | Global Flags ------------ | Flag | Description | | --- | --- | | `-c, --config ` | Path to config file. Default is `~/.config/mplx/config.json` | | `-k, --keypair ` | Path to keypair file or ledger (e.g., `usb://ledger?key=0`) | | `-r, --rpc ` | RPC URL for the cluster | | `--json` | Format output as JSON | Examples -------- 1. Create using the wizard: `mplx bg nft create --wizard` 1. Create with specific tree using wizard: `mplx bg nft create my-tree --wizard` 1. Create with existing metadata URI: `mplx bg nft create my-tree --name "My NFT" --uri "https://arweave.net/xxx"` 1. Create with local files: `mplx bg nft create my-tree --image ./artwork.png --json ./metadata.json` 1. Create with metadata flags: `mplx bg nft create my-tree \ --name "Cool NFT #1" \ --image ./nft.png \ --description "A very cool compressed NFT" \ --attributes "Background:Blue,Eyes:Laser,Hat:Crown" \ --royalties 5` 1. Create in a collection: `mplx bg nft create my-tree \ --name "Collection Item #1" \ --image ./nft.png \ --collection 7kPqYxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` Output ------ `Uploading image... ✓ Uploading metadata... ✓ Creating compressed NFT... ✓ -------------------------------- Compressed NFT Created! Tree: my-tree Owner: YourWalletAddressHere Asset ID: CNFTAssetIdHere Signature: 5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Explorer: https://solscan.io/tx/5xxx... --------------------------------` Metadata JSON Format -------------------- When using `--json`, your metadata file should follow this structure: `{ "name": "My NFT", "symbol": "MNFT", "description": "Description of the NFT", "seller_fee_basis_points": 500, "attributes": [ { "trait_type": "Background", "value": "Blue" }, { "trait_type": "Rarity", "value": "Rare" } ], "properties": { "files": [ { "uri": "", "type": "image/png" } ] } }` The `image` field will be automatically populated with the uploaded image URI. Notes ----- * The tree argument can be either a saved tree name or a public key address * If the tree is private, you must be the tree authority to mint * If the tree is public, anyone can mint NFTs to it * The RPC must support DAS API * **Bubblegum V2 only** - These commands work with Bubblegum V2 trees and use [Metaplex Core collections](https://developers.metaplex.com/smart-contracts/core/collections) (not Token Metadata collections) * Attributes format: `"trait:value,trait:value"` - colons separate trait from value, commas separate pairs Previous [← List Trees](https://developers.metaplex.com/dev-tools/cli/bubblegum/list-trees) Next [Fetch Compressed NFT →](https://developers.metaplex.com/dev-tools/cli/bubblegum/fetch-cnft) --- # Transfer Compressed NFT | Metaplex CLI The `mplx bg nft transfer` command transfers ownership of a compressed NFT to a new wallet address. Basic Usage ----------- `mplx bg nft transfer ` Arguments --------- | Argument | Description | | --- | --- | | `ASSET_ID` | The compressed NFT asset ID to transfer | | `NEW_OWNER` | The public key of the new owner | Global Flags ------------ | Flag | Description | | --- | --- | | `-c, --config ` | Path to config file. Default is `~/.config/mplx/config.json` | | `-k, --keypair ` | Path to keypair file or ledger (e.g., `usb://ledger?key=0`) | | `-r, --rpc ` | RPC URL for the cluster | | `--json` | Format output as JSON | Example ------- Transfer to a new owner: `mplx bg nft transfer CNFTAssetIdHere RecipientWalletAddressHere` Output ------ `Fetching asset and proof data... ✓ Verifying ownership... ✓ Executing transfer... ✓ Compressed NFT transferred successfully! -------------------------------- Compressed NFT Transferred! Asset ID: CNFTAssetIdHere From: OriginalOwnerAddressHere To: NewOwnerAddressHere Tree: 9hRvTxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Signature: 5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Explorer: https://solscan.io/tx/5xxx... --------------------------------` Authority Requirements ---------------------- To transfer a compressed NFT, you must be either: * **Current Owner** - The wallet that currently owns the NFT * **Delegate** - A wallet that has been delegated authority over the NFT Notes ----- * The RPC must support DAS API * The transfer is atomic - either it completes fully or fails entirely * The new owner immediately gains full ownership rights * Unlike traditional NFTs, compressed NFT transfers don't create new token accounts * The asset ID remains the same after transfer (only the owner changes) Previous [← Update Compressed NFT](https://developers.metaplex.com/dev-tools/cli/bubblegum/update-cnft) Next [Burn Compressed NFT →](https://developers.metaplex.com/dev-tools/cli/bubblegum/burn-cnft) --- # List Merkle Trees | Metaplex CLI The `mplx bg tree list` command displays all Merkle trees you've created and saved locally. Basic Usage ----------- `mplx bg tree list` ### Filter by Network `mplx bg tree list --network devnet` Options ------- | Option | Description | | --- | --- | | `--network ` | Filter trees by network (mainnet, devnet, testnet, localnet) | Global Flags ------------ | Flag | Description | | --- | --- | | `-c, --config ` | Path to config file. Default is `~/.config/mplx/config.json` | | `--json` | Format output as JSON | Examples -------- 1. List all trees: `mplx bg tree list` 1. List only devnet trees: `mplx bg tree list --network devnet` 1. List only mainnet trees: `mplx bg tree list --network mainnet` Output ------ `Saved Trees: ┌─────────┬────────────────────────────────────────────┬─────────┬───────────┬────────┬────────────┐ │ Name │ Address │ Network │ Max NFTs │ Public │ Created │ ├─────────┼────────────────────────────────────────────┼─────────┼───────────┼────────┼────────────┤ │ my-tree │ 9hRvTxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx │ devnet │ 16,384 │ No │ 1/15/2025 │ │ prod │ 7kPqYxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx │ mainnet │ 1,048,576 │ No │ 1/10/2025 │ └─────────┴────────────────────────────────────────────┴─────────┴───────────┴────────┴────────────┘ Total: 2 trees` Using Tree Names ---------------- Once you've saved a tree with a name, you can reference it by name in other commands: `# Using tree name mplx bg nft create my-tree --wizard # Using tree address (also works) mplx bg nft create 9hRvTxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --wizard` Notes ----- * Trees are saved per-network, so the same name can exist on different networks * Tree data is stored locally in `~/.config/mplx/trees.json` * If no trees are found, the command will suggest creating one with `mplx bg tree create --wizard` Previous [← Create Tree](https://developers.metaplex.com/dev-tools/cli/bubblegum/create-tree) Next [Create Compressed NFT →](https://developers.metaplex.com/dev-tools/cli/bubblegum/create-cnft) --- # Create Merkle Tree | Metaplex CLI The `mplx bg tree create` command creates a Merkle tree that will store your compressed NFTs. You must create a tree before minting any compressed NFTs. This creates a **Bubblegum V2** tree. V2 trees are not compatible with V1 and use [Metaplex Core collections](https://developers.metaplex.com/smart-contracts/core/collections) . Basic Usage ----------- ### Interactive Wizard (Recommended) `mplx bg tree create --wizard` ### Direct Creation `mplx bg tree create --maxDepth 14 --maxBufferSize 64 --canopyDepth 8 --name "my-tree"` Options ------- | Option | Description | | --- | --- | | `--wizard` | Use interactive wizard to create tree | | `--maxDepth ` | Maximum depth of the tree (determines max NFTs) | | `--maxBufferSize ` | Maximum buffer size for concurrent changes | | `--canopyDepth ` | Canopy depth for verification optimization | | `--public` | Make tree public (allows anyone to mint NFTs) | | `--name ` | Short name for easy reference | Global Flags ------------ | Flag | Description | | --- | --- | | `-c, --config ` | Path to config file. Default is `~/.config/mplx/config.json` | | `-k, --keypair ` | Path to keypair file or ledger (e.g., `usb://ledger?key=0`) | | `-r, --rpc ` | RPC URL for the cluster | | `--json` | Format output as JSON | Tree Configurations ------------------- The CLI provides recommended configurations optimized for different collection sizes: | Max NFTs | Max Depth | Buffer Size | Canopy Depth | Estimated Cost | | --- | --- | --- | --- | --- | | 16,384 | 14 | 64 | 8 | ~0.34 SOL | | 65,536 | 16 | 64 | 10 | ~0.71 SOL | | 262,144 | 18 | 64 | 12 | ~2.10 SOL | | 1,048,576 | 20 | 1024 | 13 | ~8.50 SOL | | 16,777,216 | 24 | 2048 | 15 | ~26.12 SOL | Examples -------- 1. Create a tree using the wizard: `mplx bg tree create --wizard` 1. Create a small tree for testing: `mplx bg tree create --maxDepth 14 --maxBufferSize 64 --canopyDepth 8 --name "test-tree"` 1. Create a public tree (anyone can mint): `mplx bg tree create --maxDepth 14 --maxBufferSize 64 --canopyDepth 8 --public --name "public-tree"` Output ------ `-------------------------------- Tree Created Successfully! Tree Name: my-collection-tree Tree Address: 9hRvTxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Max Depth: 14 Max Buffer Size: 64 Canopy Depth: 8 Public Tree: No Max NFTs: 16,384 Transaction: 5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Explorer: https://solscan.io/tx/5xxx... Tree Explorer: https://solscan.io/account/9hRv... --------------------------------` Understanding Tree Parameters ----------------------------- * **Max Depth**: Determines the maximum number of NFTs: `2^maxDepth` (Depth 14 = 16,384 NFTs) * **Max Buffer Size**: Controls how many concurrent modifications can happen * **Canopy Depth**: Stores part of the proof on-chain, reducing transaction size Notes ----- * Tree names must be unique per network (devnet/mainnet) * Tree names can contain letters, numbers, hyphens, underscores, and spaces (1-50 characters) * The rent cost is paid once when creating the tree * Trees cannot be resized after creation * **Warning**: Public trees allow anyone to mint NFTs - use with caution Previous [← Overview](https://developers.metaplex.com/dev-tools/cli/bubblegum) Next [List Trees →](https://developers.metaplex.com/dev-tools/cli/bubblegum/list-trees) --- # Fetch Compressed NFT | Metaplex CLI The `mplx bg nft fetch` command retrieves the asset data and merkle proof for a compressed NFT using the DAS (Digital Asset Standard) API. Basic Usage ----------- `mplx bg nft fetch ` ### Download to Files `mplx bg nft fetch --download --output ./nfts` ### Fetch Proof Only `mplx bg nft fetch --proof-only` Arguments --------- | Argument | Description | | --- | --- | | `ASSET_ID` | The compressed NFT asset ID (leaf asset ID) | Options ------- | Option | Description | | --- | --- | | `--download` | Download asset data and proof to files | | `--output ` | Directory path for downloaded files (requires `--download`) | | `--proof-only` | Only fetch and display the merkle proof | Global Flags ------------ | Flag | Description | | --- | --- | | `-c, --config ` | Path to config file. Default is `~/.config/mplx/config.json` | | `-r, --rpc ` | RPC URL for the cluster | | `--json` | Format output as JSON | Examples -------- 1. Fetch and display NFT information: `mplx bg nft fetch CNFTAssetIdHere` 1. Download asset data to files: `mplx bg nft fetch CNFTAssetIdHere --download` 1. Download to specific directory: `mplx bg nft fetch CNFTAssetIdHere --download --output ./nft-data` 1. Fetch only the merkle proof: `mplx bg nft fetch CNFTAssetIdHere --proof-only` 1. Output as JSON: `mplx bg nft fetch CNFTAssetIdHere --json` Output ------ `-------------------------------- Compressed NFT Details Asset ID: CNFTAssetIdHere Name: My Compressed NFT Symbol: CNFT Description: A beautiful compressed NFT Compressed: true Tree: 9hRvTxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Leaf ID: 42 Owner: OwnerWalletAddressHere Collection: CollectionAddressHere Metadata URI: https://arweave.net/xxx Image: https://arweave.net/yyy Mutable: true Burnt: false Merkle Proof: Root: RootHashHere Node Index: 42 Proof Length: 6 nodes Tree ID: 9hRvTxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Royalty: Basis Points: 500 (5%) Primary Sale: No Creators: CreatorAddress1 (100%) ✓ --------------------------------` Downloaded Files ---------------- When using `--download`, two files are created: * `-asset.json` - Full asset data including metadata, ownership, compression info * `-proof.json` - Merkle proof required for write operations (transfer, burn, update) Notes ----- * The RPC must support DAS API * Standard Solana RPC endpoints will fail with "Asset not found or RPC does not support DAS API" * The merkle proof is essential for transfer, burn, and update operations * The `--json` flag outputs machine-readable JSON for scripting Previous [← Create Compressed NFT](https://developers.metaplex.com/dev-tools/cli/bubblegum/create-cnft) Next [Update Compressed NFT →](https://developers.metaplex.com/dev-tools/cli/bubblegum/update-cnft) --- # Update Compressed NFT | Metaplex CLI The `mplx bg nft update` command updates the off-chain metadata of a compressed NFT. You can update individual fields or use the interactive editor to modify the full metadata JSON. Basic Usage ----------- ### Update Individual Fields `mplx bg nft update --name "New Name"` ### Update Multiple Fields `mplx bg nft update --name "New Name" --description "New Description" --image ./new-image.png` ### Interactive Editor `mplx bg nft update --editor` Arguments --------- | Argument | Description | | --- | --- | | `ASSET_ID` | The compressed NFT asset ID to update | Options ------- | Option | Description | | --- | --- | | `--name ` | New name for the NFT | | `--symbol ` | New symbol for the NFT | | `--description ` | New description for the NFT | | `--image ` | Path to new image file | | `--uri ` | New metadata URI (alternative to updating fields) | | `-e, --editor` | Open metadata JSON in your default editor | Global Flags ------------ | Flag | Description | | --- | --- | | `-c, --config ` | Path to config file. Default is `~/.config/mplx/config.json` | | `-k, --keypair ` | Path to keypair file or ledger (e.g., `usb://ledger?key=0`) | | `-r, --rpc ` | RPC URL for the cluster | | `--json` | Format output as JSON | Examples -------- 1. Update the name: `mplx bg nft update CNFTAssetIdHere --name "Updated NFT Name"` 1. Update name and description: `mplx bg nft update CNFTAssetIdHere \ --name "New Name" \ --description "This NFT has been updated"` 1. Update with new image: `mplx bg nft update CNFTAssetIdHere \ --name "Refreshed NFT" \ --image ./new-artwork.png` 1. Replace entire metadata URI: `mplx bg nft update CNFTAssetIdHere --uri "https://arweave.net/xxx"` 1. Use interactive editor: `mplx bg nft update CNFTAssetIdHere --editor` Output ------ `-------------------------------- Compressed NFT Update -------------------------------- Fetching asset and proof data... ✓ Uploading Image... ✓ Uploading JSON file... ✓ Updating compressed NFT... ✓ -------------------------------- Compressed NFT: Updated NFT Name Asset ID: CNFTAssetIdHere Signature: 5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Explorer: https://solscan.io/tx/5xxx... --------------------------------` Authority Requirements ---------------------- To update a compressed NFT, you must be either: * **Tree Authority** - If the NFT is not in a collection * **Collection Update Authority** - If the NFT belongs to a [Metaplex Core collection](https://developers.metaplex.com/smart-contracts/core/collections) Notes ----- * The RPC must support DAS API * If updating fields (not URI), the existing metadata is fetched and merged with your changes * If metadata fetch fails, you must provide all fields to create new metadata * The `--uri` flag is mutually exclusive with `--image`, `--description`, and `--editor` * The `--editor` flag is mutually exclusive with all other update flags * Editor uses `$EDITOR` environment variable, or defaults to nano/notepad Previous [← Fetch Compressed NFT](https://developers.metaplex.com/dev-tools/cli/bubblegum/fetch-cnft) Next [Transfer Compressed NFT →](https://developers.metaplex.com/dev-tools/cli/bubblegum/transfer-cnft) --- # MPLX CLI - Fetch Candy Machine Information The `mplx cm fetch` command retrieves and displays comprehensive information about a candy machine, including configuration, guard settings, item status, and deployment details. This command is essential for monitoring and verifying your candy machine setup. Usage ----- `# Fetch info from current candy machine directory mplx cm fetch # Fetch specific candy machine by address mplx cm fetch ` The fetch command supports an additional flag for detailed information: * `--items`: Include detailed information about loaded items Related Commands ---------------- * [`mplx cm create`](https://developers.metaplex.com/dev-tools/cli/cm/create) - Create the candy machine to fetch * [`mplx cm insert`](https://developers.metaplex.com/dev-tools/cli/cm/insert) - Load items (affects item counts) * [`mplx cm validate`](https://developers.metaplex.com/dev-tools/cli/cm/validate) - Validate cache vs on-chain data * [`mplx cm withdraw`](https://developers.metaplex.com/dev-tools/cli/cm/withdraw) - Clean up after checking status Next [Introduction →](https://developers.metaplex.com/dev-tools/cli) --- # MPLX CLI - Insert Items Command The `mplx cm insert` command inserts uploaded assets from your cache file into the on-chain candy machine, making them available for minting. It features smart loading detection, efficient batch processing, and detailed transaction tracking. Usage ----- `# Insert items from current candy machine directory mplx cm insert # Insert items from specific candy machine directory mplx cm insert ` Requirements ------------ Before running the insert command, ensure you have: 1. **Asset Cache**: Valid `asset-cache.json` with uploaded URIs 2. **Candy Machine**: Created candy machine with ID in cache 3. **Wallet Balance**: Sufficient SOL for transaction fees 4. **Network Access**: Stable connection to Solana network ### Prerequisites `# 1. Candy machine must be created mplx cm create # 2. Upload the assets mplx cm upload # 3. Then insert items mplx cm insert` Related Commands ---------------- * [`mplx cm upload`](https://developers.metaplex.com/dev-tools/cli/cm/upload) - Upload assets (required before insert) * [`mplx cm create`](https://developers.metaplex.com/dev-tools/cli/cm/create) - Create candy machine (required before insert) * [`mplx cm validate`](https://developers.metaplex.com/dev-tools/cli/cm/validate) - Validate cache and uploads * [`mplx cm fetch`](https://developers.metaplex.com/dev-tools/cli/cm/fetch) - Verify insertion status Next Steps ---------- 1. **[Verify insertion](https://developers.metaplex.com/dev-tools/cli/cm/fetch) ** to confirm all items are loaded 2. **[Test minting](https://developers.metaplex.com/smart-contracts/core-candy-machine/mint) ** to ensure candy machine works 3. **[Monitor performance](https://developers.metaplex.com/dev-tools/cli/cm/validate) ** to check for issues 4. **[Plan your launch](https://developers.metaplex.com/smart-contracts/core-candy-machine/guides) ** with appropriate guards Next [Introduction →](https://developers.metaplex.com/dev-tools/cli) --- # MPLX CLI - Create Candy Machine Command The `mplx cm create` command creates a new MPL Core Candy Machine with configurable settings and asset uploads. It offers both an interactive wizard for beginners and manual configuration for advanced users. Usage ----- `# Interactive wizard (recommended) mplx cm create --wizard # Create directory template mplx cm create --template # Manual creation (requires existing cm-config.json) mplx cm create` Prerequisite Assets ------------------- Independent of the Mode (Wizard or Manual) you choose you will need your assets prepared. If you want to play around with dummy assets you can create them using `mplx cm create --template`. All the image and metadata files should be in their own `assets` folder. _Image Files:_ * **Formats**: PNG, JPG * **Naming**: Sequential (0.png, 1.png, 2.png, ...) _Metadata Files:_ * **Format**: JSON * **Naming**: Matching image files (0.json, 1.json, 2.json, ...) * **Schema**: Standard [Metaplex Core metadata format](https://developers.metaplex.com/smart-contracts/core/json-schema) _Collection Files:_ * **collection.png**: Collection image * **collection.json**: Collection metadata Template Mode ------------- Create a basic directory structure to get started: `mplx cm create --template` This creates the following structure, but not the candy machine. `candy-machine-template/ ├── assets/ │ ├── 0.png # Example image │ ├── 0.json # Example metadata │ ├── collection.png # Example collection image │ └── collection.json # Example collection metadata └── cm-config.json # Example configuration` After creating the template: 1. Replace example assets with your actual files 2. Update the configuration in `cm-config.json` 3. Run `mplx cm create` to deploy Interactive Wizard Mode ----------------------- The wizard provides a guided, user-friendly experience with comprehensive validation and progress tracking. **This is the recommended approach for most users.** ### Wizard Workflow 1. Project Setup 2. Asset Discovery & Validation 3. Collection Configuration 4. Candy Machine and Candy Guard Settings 5. Asset Upload & Processing 6. Candy Machine Creation 7. Item Insertion Manual Configuration Mode ------------------------- For advanced users who want full control over the configuration process. ### Prerequisites 1. **Candy machine asset directory** with proper structure 2. **Manually created `cm-config.json`** with required configuration. See below for an example 3. **Prepared assets** in the `assets/` directory in a structure as shown below ### Directory Structure `my-candy-machine/ ├── assets/ │ ├── 0.png │ ├── 0.json │ ├── 1.png │ ├── 1.json │ ├── ... │ ├── collection.png │ └── collection.json └── cm-config.json # Required` ### Configuration File Format Create `cm-config.json` with this structure: `{ "name": "My Candy Machine", "config": { "collection": "CollectionPublicKey...", // existing collection "itemsAvailable": 100, "isMutable": true, "isSequential": false, "guardConfig": { "solPayment": { "lamports": 1000000000, "destination": "111111111111111111111111111111111" }, "mintLimit": { "id": 1, "limit": 1 } }, "groups": [ { "label": "wl", "guards": { "allowList": { "merkleRoot": "MerkleRootHash..." }, "solPayment": { "lamports": 500000000, "destination": "111111111111111111111111111111111" } } } ] } }` ### Manual Workflow `# 1. Navigate to your candy machine directory cd ./my-candy-machine # 2. Create candy machine using existing config mplx cm create # 3. Upload assets to storage mplx cm upload # 4. Insert items into candy machine mplx cm insert # 5. Validate setup (optional) mplx cm validate` Configuration Options --------------------- ### Core Settings | Setting | Description | Required | | --- | --- | --- | | `name` | Display name for the candy machine | ✅ | | `itemsAvailable` | Total number of items to mint | ✅ | | `isMutable` | Whether NFTs can be updated after minting | ✅ | | `isSequential` | Whether to mint items in order | ✅ | | `collection` | Existing collection address (optional) | ❌ | ### Guard Configuration **Global Guards** (`guardConfig`): * Apply to all groups and the candy machine as a whole * Cannot be overridden by group guards * Useful for universal restrictions **Guard Groups** (`groups`): * Apply only to specific groups * Allow different rules per minting phase * Group labels limited to 6 characters maximum ### Common Guard Examples #### Basic Public Sale `{ "guardConfig": { "solPayment": { "lamports": 1000000000, "destination": "YourWalletAddress..." }, "mintLimit": { "id": 1, "limit": 1 } } }` #### Whitelist Phase `{ "groups": [ { "label": "wl", "guards": { "allowList": { "merkleRoot": "MerkleRootHash..." }, "solPayment": { "lamports": 500000000, "destination": "YourWalletAddress..." } } } ] }` ### Getting Help * Use `mplx cm create --help` for command options * Join the [Metaplex Discord](https://discord.gg/metaplex) for support Related Commands ---------------- * [`mplx cm upload`](https://developers.metaplex.com/dev-tools/cli/cm/upload) - Upload assets to storage * [`mplx cm insert`](https://developers.metaplex.com/dev-tools/cli/cm/insert) - Insert items into candy machine * [`mplx cm validate`](https://developers.metaplex.com/dev-tools/cli/cm/validate) - Validate asset cache * [`mplx cm fetch`](https://developers.metaplex.com/dev-tools/cli/cm/fetch) - View candy machine information Next Steps ---------- 1. **[Upload assets](https://developers.metaplex.com/dev-tools/cli/cm/upload) ** if created manually 2. **[Insert items](https://developers.metaplex.com/dev-tools/cli/cm/insert) ** to load assets into candy machine 3. **[Validate your setup](https://developers.metaplex.com/dev-tools/cli/cm/validate) ** to ensure everything works 4. **[Learn about guards](https://developers.metaplex.com/smart-contracts/core-candy-machine/guards) ** for advanced configuration Next [Introduction →](https://developers.metaplex.com/dev-tools/cli) --- # MPLX CLI - Validate Cache Command The `mplx cm validate` command validates the asset cache file to ensure all assets are properly uploaded and accessible. It provides comprehensive validation, error detection, and cache integrity verification. Usage ----- `# Validate cache in current candy machine directory mplx cm validate # Validate specific cache file mplx cm validate # Validate on-chain insertions (requires candy machine to exist) mplx cm validate --onchain` If the validation command shows issues, depending on the error you might want to check the issues with your assets or run the upload or insert command. Related Commands ---------------- * [`mplx cm upload`](https://developers.metaplex.com/dev-tools/cli/cm/upload) - Upload assets and create cache * [`mplx cm create`](https://developers.metaplex.com/dev-tools/cli/cm/create) - Create candy machine * [`mplx cm insert`](https://developers.metaplex.com/dev-tools/cli/cm/insert) - Insert validated assets * [`mplx cm fetch`](https://developers.metaplex.com/dev-tools/cli/cm/fetch) - Check candy machine status Next Steps ---------- 1. **[Fix any issues](https://developers.metaplex.com/dev-tools/cli/cm/upload) ** found during validation 2. **[Create candy machine](https://developers.metaplex.com/dev-tools/cli/cm/create) ** if cache is valid 3. **[Insert items](https://developers.metaplex.com/dev-tools/cli/cm/insert) ** to load assets 4. **[Monitor deployment](https://developers.metaplex.com/dev-tools/cli/cm/fetch) ** to ensure success Next [Introduction →](https://developers.metaplex.com/dev-tools/cli) --- # Explorer Configuration | Metaplex CLI The `mplx config explorer` command allows you to set your preferred blockchain explorer for viewing transactions and accounts. Basic Usage ----------- ### Set Explorer `mplx config explorer set` Commands -------- ### Set Explorer Sets your preferred blockchain explorer from a list of available options. #### Examples `mplx config explorer set` #### Notes * Opens an interactive prompt to select from available explorers * Updates the active explorer in your configuration * The selected explorer will be used for viewing transactions and accounts * Available explorers include: * Solana Explorer (https://explorer.solana.com) * Solscan (https://solscan.io) * Solana FM (https://solana.fm) Configuration File ------------------ The explorer configuration is stored in your config file (default: `~/.mplx/config.json`). The structure looks like this: `{ "explorer": "https://explorer.solana.com" }` Notes ----- * The explorer setting is used when displaying links to transactions and accounts * The configuration file is automatically created if it doesn't exist * You can change your preferred explorer at any time * The selected explorer will be used for all explorer links in command outputs * Each explorer provides different features and interfaces for viewing blockchain data Previous [← RPCs](https://developers.metaplex.com/dev-tools/cli/config/rpcs) Next [Create Asset →](https://developers.metaplex.com/dev-tools/cli/core/create-asset) --- # MPLX CLI - Candy Machine Commands The MPLX CLI provides comprehensive support for creating and managing **MPL Core Candy Machines** on Solana. These commands allow you to create NFT collections with configurable minting rules, upload assets, and manage the entire candy machine lifecycle through an intuitive command-line interface. Quick Start ----------- Get started quickly with the interactive wizard: `mplx cm create --wizard` This single command handles everything to create a candy machine: asset validation, upload, candy machine creation including guard configuration, item insertion with progress tracking. Command Overview ---------------- | Command | Purpose | Key Features | | --- | --- | --- | | [`create`](https://developers.metaplex.com/dev-tools/cli/cm/create) | Create a new candy machine | Interactive wizard, template generation, manual config | | [`upload`](https://developers.metaplex.com/dev-tools/cli/cm/upload) | Upload assets to storage | Intelligent caching, progress tracking, validation | | [`insert`](https://developers.metaplex.com/dev-tools/cli/cm/insert) | Insert items into candy machine | Smart loading detection, batch processing | | [`validate`](https://developers.metaplex.com/dev-tools/cli/cm/validate) | Validate asset cache | Comprehensive validation, error reporting | | [`fetch`](https://developers.metaplex.com/dev-tools/cli/cm/fetch) | Fetch candy machine info | Display configuration, guard settings, status | | [`withdraw`](https://developers.metaplex.com/dev-tools/cli/cm/withdraw) | Withdraw and delete | Clean withdrawal, balance recovery | Key Features ------------ ### Interactive Wizard * **Guided Setup**: Step-by-step candy machine creation * **Asset Validation**: Comprehensive file and metadata validation * **Progress Tracking**: Real-time indicators for all operations * **Error Recovery**: Detailed error messages with actionable guidance ### Intelligent Asset Management * **Smart Caching**: Reuses existing uploads when possible * **Batch Processing**: Efficient asset upload and insertion * **File Validation**: Ensures proper naming and metadata format * **Collection Support**: Automatic collection creation ### Flexible Configuration * **Guard Support**: All Core Candy Machine guards supported * **Guard Groups**: Create different minting phases with distinct rules * **Template Generation**: Quick directory structure setup * **Manual Configuration**: Advanced users can create custom configs Directory Structure ------------------- All candy machine commands work from a **candy machine asset directory** with this structure: `my-candy-machine/ ├── assets/ │ ├── 0.png # Image files (PNG, JPG) │ ├── 0.json # Metadata files │ ├── 1.png │ ├── 1.json │ ├── ... │ ├── collection.png # Collection image │ └── collection.json # Collection metadata ├── asset-cache.json # Asset upload cache (generated) └── cm-config.json # Candy machine configuration (generated when using the wizard)` Workflow Options ---------------- ### Option 1: Wizard Mode (Recommended) Perfect for beginners and most use cases: `mplx cm create --wizard` **What it does:** 1. Validates assets and configuration 2. Uploads all assets with progress tracking 3. Creates the candy machine on-chain 4. Inserts all items with transaction progress 5. Provides comprehensive completion summary ### Option 2: Manual Mode (Advanced) For advanced users who want full control: `# 1. Set up directory and config manually mkdir my-candy-machine && cd my-candy-machine # (create assets/ directory and add your assets) # 2. Upload assets mplx cm upload # 3. Create candy machine mplx cm create # 4. Insert items mplx cm insert # 5. Validate (optional) mplx cm validate` Guard Configuration ------------------- The CLI supports all Core Candy Machine guards and guard groups: ### Global Guards `{ "guardConfig": { "solPayment": { "lamports": 1000000000, "destination": "111111111111111111111111111111111" }, "mintLimit": { "id": 1, "limit": 1 } } }` ### Guard Groups (Minting Phases) `{ "groups": [ { "label": "wl", "guards": { "allowList": { "merkleRoot": "MerkleRootHash..." }, "solPayment": { "lamports": 500000000, "destination": "111111111111111111111111111111111" } } }, { "label": "public", "guards": { "solPayment": { "lamports": 1000000000, "destination": "111111111111111111111111111111111" } } } ] }` Available Guards ---------------- The CLI supports all Core Candy Machine guards: **Payment Guards**: `solPayment`, `solFixedFee`, `tokenPayment`, `token2022Payment`, `nftPayment`, `assetPayment`, `assetPaymentMulti` **Access Control**: `addressGate`, `allowList`, `nftGate`, `tokenGate`, `assetGate`, `programGate`, `thirdPartySigner` **Time-Based**: `startDate`, `endDate` **Limits**: `mintLimit`, `allocation`, `nftMintLimit`, `assetMintLimit`, `redeemedAmount` **Burn Guards**: `nftBurn`, `tokenBurn`, `assetBurn`, `assetBurnMulti` **Special**: `botTax`, `edition`, `vanityMint` **Freeze Guards**: `freezeSolPayment`, `freezeTokenPayment` For detailed guard documentation, see the [Core Candy Machine Guards](https://developers.metaplex.com/smart-contracts/core-candy-machine/guards) reference. Best Practices -------------- ### 🎯 Directory Organization * Keep each candy machine in its own directory * Use descriptive directory names * Maintain consistent asset naming (0.png, 1.png, etc.) * Back up your candy machine directories ### 📁 Asset Preparation * Use consistent naming (0.png, 1.png, etc.) * Ensure metadata JSON files match image files * Validate image formats (PNG, JPG supported) * Keep file sizes reasonable (< 10MB recommended) * Include collection.json with a valid "name" field ### ⚙️ Configuration * Test on devnet before mainnet * Use the wizard for guided configuration * Back up configuration files * Document guard settings * Consider adding at least one guard or guard group ### 🚀 Deployment * Verify candy machine creation * Test minting functionality * Monitor transaction status * Keep explorer links for verification Related Documentation --------------------- * [Core Candy Machine Overview](https://developers.metaplex.com/smart-contracts/core-candy-machine) - Understanding MPL Core Candy Machines * [Core Candy Machine Guards](https://developers.metaplex.com/smart-contracts/core-candy-machine/guards) - Complete guard reference * [CLI Installation](https://developers.metaplex.com/dev-tools/cli/installation) - Setting up the MPLX CLI * [CLI Configuration](https://developers.metaplex.com/dev-tools/cli/config/wallets) - Wallet and RPC setup Next Steps ---------- 1. **[Install the CLI](https://developers.metaplex.com/dev-tools/cli/installation) ** if you haven't already 2. **[Create your first candy machine](https://developers.metaplex.com/dev-tools/cli/cm/create) ** using the wizard 3. **[Explore guard configuration](https://developers.metaplex.com/smart-contracts/core-candy-machine/guards) ** for advanced minting rules 4. **[Learn about guard groups](https://developers.metaplex.com/smart-contracts/core-candy-machine/guard-groups) ** for phased launches Next [Introduction →](https://developers.metaplex.com/dev-tools/cli) --- # MPLX CLI - Upload Assets Command The `mplx cm upload` command uploads assets to a decentralized storage and generates an `asset-cache.json` file containing upload URIs and metadata. This command provides intelligent caching, progress tracking, and comprehensive validation. Usage ----- `# Upload assets from current candy machine directory mplx cm upload # Upload assets from specific candy machine directory mplx cm upload ` ### Directory Structure `my-candy-machine/ ├── assets/ │ ├── 0.png # Image files (PNG, JPG) │ ├── 0.json # Metadata files │ ├── 1.png │ ├── 1.json │ ├── ... │ ├── collection.png # Collection image │ └── collection.json # Collection metadata └── asset-cache.json # Generated after upload` Upload Process -------------- 1. Asset Discovery: The command automatically scans the `assets/` directory and identifies image, metadata and collection files. 2. Validation Phase: Verifies the integrity of your files, for example if all image files have matching metadata files and that the metadata is valid json. 3. Cache Check: To identify which files were already uploaded the `asset-cache.json` file is validated. 4. Upload: The actual upload is done. 5. Cache Generation: The `asset-cache.json` file is generated Generated Asset Cache --------------------- The `asset-cache.json` file contains detailed information about uploaded assets. Manually inspecting and using it is only recommended for advanced users. Example: `{ "candyMachineId": null, "collection": null, "assetItems": { "0": { "name": "Asset #0", "image": "0.png", "imageUri": "https://gateway.irys.xyz/ABC123...", "imageType": "image/png", "json": "0.json", "jsonUri": "https://gateway.irys.xyz/DEF456...", "loaded": false }, "1": { "name": "Asset #1", "image": "1.png", "imageUri": "https://gateway.irys.xyz/GHI789...", "imageType": "image/png", "json": "1.json", "jsonUri": "https://gateway.irys.xyz/JKL012...", "loaded": false } } }` Related Commands ---------------- * [`mplx cm create`](https://developers.metaplex.com/dev-tools/cli/cm/create) - Create candy machine (can upload automatically) * [`mplx cm validate`](https://developers.metaplex.com/dev-tools/cli/cm/validate) - Validate uploaded assets * [`mplx cm insert`](https://developers.metaplex.com/dev-tools/cli/cm/insert) - Insert uploaded assets into candy machine * [`mplx cm fetch`](https://developers.metaplex.com/dev-tools/cli/cm/fetch) - View candy machine and asset information Next Steps ---------- 1. **[Validate your uploads](https://developers.metaplex.com/dev-tools/cli/cm/validate) ** to ensure everything uploaded correctly 2. **[Create your candy machine](https://developers.metaplex.com/dev-tools/cli/cm/create) ** using the uploaded assets 3. **[Insert items](https://developers.metaplex.com/dev-tools/cli/cm/insert) ** to load assets into the candy machine 4. **[Monitor your setup](https://developers.metaplex.com/dev-tools/cli/cm/fetch) ** to verify everything is working Next [Introduction →](https://developers.metaplex.com/dev-tools/cli) --- # MPLX CLI - Withdraw Candy Machine The `mplx cm withdraw` command withdraws and deletes a candy machine, recovering any remaining SOL balance and cleaning up the on-chain account. This operation is irreversible and should be used when the candy machine is no longer needed. Already minted NFTs are not affected. Irreversible This command is irreversible. Once executed your candy machine is destroyed and can not be recreated. Usage ----- `# Withdraw candy machine from current directory mplx cm withdraw # Withdraw specific candy machine by address mplx cm withdraw --address ` Optional Flags that you can use: * `--address`: Specify candy machine address directly * `--force`: _Danger_ Skip confirmation prompts (use with extreme caution) ### ⚠️ Irreversible Operation * **Permanent Deletion**: The candy machine account will be permanently deleted * **No Recovery**: Cannot be undone or restored * **Data Loss**: All on-chain configuration and state will be lost * **Minted NFTs**: Existing minted NFTs are not affected ### 🛡️ Best Practices **Planning:** * Plan withdrawal timing carefully * Coordinate with team members **Execution:** * Double-check all parameters * Use devnet for practice Related Commands ---------------- * [`mplx cm fetch`](https://developers.metaplex.com/dev-tools/cli/cm/fetch) - Check status before withdrawal * [`mplx cm create`](https://developers.metaplex.com/dev-tools/cli/cm/create) - Create new candy machines * [`mplx cm validate`](https://developers.metaplex.com/dev-tools/cli/cm/validate) - Validate before withdrawal * [`solana balance`](https://docs.solana.com/cli) - Check recovered balance Next [Introduction →](https://developers.metaplex.com/dev-tools/cli) --- # Burn Asset | Metaplex CLI The `mplx core asset burn` command allows you to permanently destroy MPL Core Assets and reclaim rent fees. You can burn a single asset or multiple assets at once using a JSON list file. Basic Usage ----------- ### Burn Single Asset `mplx core asset burn ` ### Burn Asset from Collection `mplx core asset burn --collection ` ### Burn Multiple Assets `mplx core asset burn --list ./assets-to-burn.json` Arguments --------- | Argument | Description | | --- | --- | | `ASSET` | The mint address of the asset to burn | Options ------- | Option | Description | | --- | --- | | `--collection ` | Collection ID to burn the asset from | | `--list ` | File path to a JSON list of assets to burn (e.g., `["asset1", "asset2"]`) | Global Flags ------------ | Flag | Description | | --- | --- | | `-c, --config ` | Path to config file. Default is `~/.config/mplx/config.json` | | `-k, --keypair ` | Path to keypair file or ledger (e.g., `usb://ledger?key=0`) | | `-p, --payer ` | Path to payer keypair file or ledger | | `-r, --rpc ` | RPC URL for the cluster | | `--commitment