Features
Updating Compressed NFTs
Last updated June 19, 2026
Summary
Updating a compressed NFT modifies its metadata using the updateMetadataV2 instruction. This page covers update authority rules for collection-based and tree-based cNFTs.
- Update cNFT metadata (name, URI, creators, royalties) using updateMetadataV2
- Collection authority updates cNFTs that belong to a collection
- Tree authority updates cNFTs that do not belong to a collection
- Changes are reflected in the merkle tree and indexed by DAS API providers
- Spread
...assetWithProofintoupdateMetadataV2socurrentMetadatais the leaf-canonical value fromgetAssetWithProof
The updateMetadataV2 instruction can be used to modify the metadata of a Compressed NFT. The Merkle root is updated to reflect the propagated hash of the data, and RPC providers who conform to the Metaplex DAS API will update their index of the cNFTs.
The metadata can be updated by one of two authorities, depending on if the compressed NFT is a verified item in a collection.
Update Authority
A cNFT has two possible update authorities: the tree owner, or (if it belongs to a collection) the collection authority.
Collection Authority
If your cNFT belongs to a collection, then the update authority of that cNFT will be the authority of the collection. When updating the cNFT you will need to pass in a coreCollection arg to the update function.
The authority will be inferred from the current umi identity. If the authority is different from the current umi identity, then you will either have to pass in the authority arg as a signer type or create a noopSigner for later signing.
await updateMetadataV2(umi, {
...
authority: collectionAuthority,
coreCollection: publicKey("11111111111111111111111111111111"),
}).sendAndConfirm(umi)
Tree Authority
If your cNFT does not belong to a collection then the update authority for the cNFT will be the authority of the tree that the cNFT belongs to. In this case, you would omit the coreCollection arg from the update function.
The authority will be inferred from the current umi identity. If the authority is different from the current umi identity, then you will either have to pass in the authority arg as a signer type or create a noopSigner for later signing.
Update cNFT
Update a Compressed NFT
import {
getAssetWithProof,
updateMetadataV2,
UpdateArgsArgs,
} from '@metaplex-foundation/mpl-bubblegum'
import { some } from '@metaplex-foundation/umi'
// Use the helper to fetch the asset and proof.
const assetWithProof = await getAssetWithProof(umi, assetId, {
truncateCanopy: true,
})
// Then we can use it to update metadata for the NFT.
const updateArgs: UpdateArgsArgs = {
name: some('New name'),
uri: some('https://updated-example.com/my-nft.json'),
}
await updateMetadataV2(umi, {
...assetWithProof, // includes currentMetadata (leaf-canonical)
leafOwner,
updateArgs,
// Optional param. If your authority is a different signer type
// than the current umi identity assign that signer here.
authority: <Signer>,
// Optional param. If cNFT belongs to a collection pass it here.
coreCollection: publicKey("22222222222222222222222222222222"),
}).sendAndConfirm(umi)
Leaf metadata for write instructions
getAssetWithProof returns both metadata (DAS display / resolved rate) and currentMetadata (leaf-canonical MetadataArgsV2Args, including 65535 when inherited). Spread ...assetWithProof into write instructions — do not pass metadata as currentMetadata. Use metadata / rpcAsset for UI; check inherited for inherit detection.
For guidance on DAS response fields when reading assets, see Reading Inherited Royalties.
Inherited royalties
You can switch a cNFT to inherited royalties by setting updateArgs.sellerFeeBasisPoints to some(SELLER_FEE_BASIS_POINTS_INHERIT). The collection must have the Royalties plugin and the updated metadata must have an empty creators array.
To switch from inherited royalties back to an explicit percentage — for example before removing the cNFT from its collection — pass the desired basis points:
1import {
2 getAssetWithProof,
3 updateMetadataV2,
4 UpdateArgsArgs,
5 mplBubblegum,
6} from '@metaplex-foundation/mpl-bubblegum'
7import { dasApi } from '@metaplex-foundation/digital-asset-standard-api'
8import { keypairIdentity, publicKey, some } from '@metaplex-foundation/umi'
9import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
10import { readFileSync } from 'fs'
11
12// getAssetWithProof calls getAsset and getAssetProof, so this needs a
13// DAS-capable RPC. The public Solana endpoints do not serve DAS methods.
14const umi = createUmi('YOUR_DAS_ENABLED_RPC_URL')
15 .use(mplBubblegum())
16 .use(dasApi())
17
18// The leaf owner or an authorised delegate must sign the update.
19const keypair = umi.eddsa.createKeypairFromSecretKey(
20 new Uint8Array(JSON.parse(readFileSync('./keypair.json', 'utf8')))
21)
22umi.use(keypairIdentity(keypair))
23
24const assetId = publicKey('YOUR_ASSET_ID')
25const collectionPublicKey = publicKey('YOUR_COLLECTION_ADDRESS')
26
27const assetWithProof = await getAssetWithProof(umi, assetId, {
28 truncateCanopy: true,
29})
30
31// Switch from inherited royalties to an explicit seller fee before removing
32// the cNFT from its collection.
33const updateArgs: UpdateArgsArgs = {
34 sellerFeeBasisPoints: some(550), // explicit 5.5%
35}
36
37// Spread includes currentMetadata (leaf-canonical). Do not pass metadata here.
38await updateMetadataV2(umi, {
39 ...assetWithProof,
40 updateArgs,
41 coreCollection: collectionPublicKey,
42}).sendAndConfirm(umi)
43
44// Leaf seller fee updated from inherit sentinel (65535) to 550 basis points
Notes
- The update authority depends on whether the cNFT belongs to a collection. Collection cNFTs use the collection authority; standalone cNFTs use the tree authority.
- Spread
...assetWithProofintoupdateMetadataV2so the program verifies against leaf-canonicalcurrentMetadata. - Use
some()for fields to update; omit fields you wish to leave unchanged. - Inherited seller fees require an empty leaf-level
creatorsarray and a collection with theRoyaltiesplugin.
FAQ
Who can update a compressed NFT's metadata?
If the cNFT belongs to a collection, only the collection authority can update it. If it does not belong to a collection, the tree authority (tree creator or delegate) can update it.
What fields can I update on a cNFT?
You can update the name, URI, seller fee basis points, and other metadata fields defined in UpdateArgsArgs. Use some('newValue') for fields you want to change.
Do I need to pass the collection when updating?
Yes, if the cNFT belongs to a collection. Pass the coreCollection parameter with the collection's public key. The collection authority must sign the transaction.
How do I update a cNFT that inherits royalties from its collection?
Spread ...assetWithProof into updateMetadataV2 so currentMetadata carries the on-chain sentinel when inherited. Use updateArgs.sellerFeeBasisPoints with some(SELLER_FEE_BASIS_POINTS_INHERIT) to switch to inherited royalties, or an explicit number to switch away from them.
Glossary
| Term | Definition |
|---|---|
| updateMetadataV2 | The Bubblegum V2 instruction for modifying compressed NFT metadata |
| Collection Authority | The update authority of the MPL-Core collection, authorized to update cNFTs in that collection |
| Tree Authority | The tree creator or delegate, authorized to update cNFTs that do not belong to a collection |
| UpdateArgsArgs | The TypeScript type defining which metadata fields to update, using Option wrappers |
| currentMetadata | IDL argument on updateMetadataV2 for existing leaf metadata; provided by getAssetWithProof.currentMetadata when you spread ...assetWithProof |
| SELLER_FEE_BASIS_POINTS_INHERIT | Sentinel value 65535 indicating royalties are inherited from the MPL-Core collection |
