Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/components/products/bubblegum-v2/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ export const bubblegumv2 = {
href: '/smart-contracts/bubblegum-v2/mint-cnfts',
},
{ title: 'Fetching cNFTs', href: '/smart-contracts/bubblegum-v2/fetch-cnfts' },
{
title: 'Reading Inherited Royalties',
href: '/smart-contracts/bubblegum-v2/reading-inherited-royalties',
},
{ title: 'Transferring cNFTs', href: '/smart-contracts/bubblegum-v2/transfer-cnfts' },
{ title: 'Freeze and Thaw cNFTs', href: '/smart-contracts/bubblegum-v2/freeze-cnfts' },
{ title: 'Updating cNFTs', href: '/smart-contracts/bubblegum-v2/update-cnfts' },
Expand Down Expand Up @@ -152,6 +156,11 @@ export const bubblegumv2 = {
ko: 'cNFT 가져오기',
zh: '获取cNFT'
},
'Reading Inherited Royalties': {
ja: '継承ロイヤリティの読み取り',
ko: '상속 로열티 읽기',
zh: '读取继承版税'
},
'Transferring cNFTs': {
ja: 'cNFTの転送',
ko: 'cNFT 전송',
Expand Down
32 changes: 32 additions & 0 deletions src/examples/bubblegum/get-asset-with-proof-inherited/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/**
* Example: getAssetWithProof with inherited royalties
*
* Leaf metadata keeps the on-chain sentinel; DAS main royalty fields hold the collection-resolved display rate.
*
* This file is auto-generated by scripts/build-examples.js
* Edit the native .js/.ts and .rs files, then run: node scripts/build-examples.js
*/

const umiSections = {
"imports": "import { getAssetWithProof, mplBubblegum } from '@metaplex-foundation/mpl-bubblegum'\nimport { publicKey } from '@metaplex-foundation/umi'\nimport { createUmi } from '@metaplex-foundation/umi-bundle-defaults'",
"setup": "const umi = createUmi('https://api.devnet.solana.com').use(mplBubblegum())\n\nconst assetId = publicKey('YOUR_ASSET_ID')",
"main": "const assetWithProof = await getAssetWithProof(umi, assetId, {\n truncateCanopy: true,\n})\n\n// Leaf / hashing value (65535 when inherited)\nconsole.log(assetWithProof.metadata.sellerFeeBasisPoints)\n\n// Display / payout value from DAS main fields\nconsole.log(assetWithProof.rpcAsset.royalty?.basis_points)",
Comment on lines +12 to +13

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files | rg 'src/examples/bubblegum/(get-asset-with-proof-inherited|update-inherit-royalties)/index' || true

echo "== target lines =="
for f in src/examples/bubblegum/get-asset-with-proof-inherited/index.js src/examples/bubblegum/update-inherit-royalties/index.js; do
  echo "--- $f ---"
  nl -ba "$f" | sed -n '1,80p'
done

echo "== related TypeScript source mentions =="
fd . src/examples/bubblegum -t f | sed 's#^\./##' | xargs -r -n1 sh -c 'echo "--- $0 ---"; rg -n "getAssetWithProof|api\.devnet\.solana\.com|YOUR_ASSET_ID|DAS|getAsset|getAssetProof|metaplex|Devnet" "$0" || true'

Repository: metaplex-foundation/developer-hub

Length of output: 434


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== target lines =="
for f in src/examples/bubblegum/get-asset-with-proof-inherited/index.js src/examples/bubblegum/update-inherit-royalties/index.js; do
  echo "--- $f ---"
  awk '{printf "%5d\t%s\n", NR, $0}' "$f" | sed -n '1,100p'
done

echo "== matching files =="
find src/examples/bubblegum -name 'index.js' -o -name 'index.ts' | sort | while read -r f; do
  echo "--- $f ---"
  grep -n -E "getAssetWithProof|api\.devnet\.solana\.com|YOUR_ASSET_ID|DAS|getAsset|getAssetProof|metaplex|Devnet" "$f" || true
done

Repository: metaplex-foundation/developer-hub

Length of output: 28093


🌐 Web query:

Metaplex Bubblegum v2 getAssetWithProof API getAssetAssetProof DAS required provider api.devnet.solana.com DAS

💡 Result:

The getAssetWithProof function is a helper method provided by the @metaplex-foundation/mpl-bubblegum library (part of the Umi framework) designed to simplify interactions with compressed NFTs (cNFTs) [1][2][3]. It automatically fetches both the asset data (via getAsset) and the Merkle tree proof (via getAssetProof) from the Metaplex Digital Asset Standard (DAS) API and formats them into the specific parameters required for Bubblegum V2 write instructions, such as transfers, burns, or updates [1][4][5]. Key technical points regarding your query: 1. Usage and Requirements: You should call getAssetWithProof immediately before any mutation instruction to avoid using stale proof data [1]. When using the Bubblegum Umi library, register the DAS API plugin (.use(dasApi())) to enable the required RPC methods [1][6]. 2. DAS API Providers: The URL api.devnet.solana.com is the standard Solana Devnet RPC endpoint, but it does not natively support Metaplex DAS API methods (like getAsset or getAssetProof) unless the provider explicitly includes DAS support [1][7]. Most developers use specialized RPC providers (such as Helius, Triton, or Shyft) that offer a specific "Digital Asset Standard (DAS)" API endpoint to handle these requests [8][6]. You must configure your Umi instance to point to an RPC provider that supports the DAS method set [6]. 3. Optimization: If you encounter transaction size limitations, you can use the truncateCanopy: true option within getAssetWithProof [5][9]. This optimizes the proof path by removing redundant nodes based on the tree's canopy configuration, helping to keep transaction sizes within protocol limits [5]. Example of basic usage: import { getAssetWithProof, transferV2 } from '@metaplex-foundation/mpl-bubblegum'; import { publicKey } from '@metaplex-foundation/umi'; // Fetch proof and asset data const assetWithProof = await getAssetWithProof(umi, assetId, { truncateCanopy: true }); // Use in write operation await transferV2(umi, {...assetWithProof, leafOwner: umi.identity, newLeafOwner: publicKey('NewOwnerAddress'), }).sendAndConfirm(umi);

Citations:


Use a DAS endpoint or DAS plugin in the inherited-royalty examples.

Both examples pass umi into getAssetWithProof, which needs getAsset/getAssetProof (Metaplex DAS) rather than only the standard Solana RPC methods. Replace api.devnet.solana.com with a DAS-enabled URL, or add a DAS/UMI DAS plugin setup, then regenerate the JavaScript files.

  • src/examples/bubblegum/get-asset-with-proof-inherited/index.js#L12-L13
  • src/examples/bubblegum/update-inherit-royalties/index.js#L12-L13
📍 Affects 2 files
  • src/examples/bubblegum/get-asset-with-proof-inherited/index.js#L12-L13 (this comment)
  • src/examples/bubblegum/update-inherit-royalties/index.js#L12-L13
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/examples/bubblegum/get-asset-with-proof-inherited/index.js` around lines
12 - 13, Configure DAS support for both inherited-royalty examples: update
src/examples/bubblegum/get-asset-with-proof-inherited/index.js lines 12-13 and
src/examples/bubblegum/update-inherit-royalties/index.js lines 12-13 to use a
DAS-enabled endpoint or DAS/UMI plugin setup so getAssetWithProof receives
getAsset and getAssetProof, then regenerate the JavaScript files.

"output": "// 65535\n// 500",
"full": "// [IMPORTS]\nimport { getAssetWithProof, mplBubblegum } from '@metaplex-foundation/mpl-bubblegum'\nimport { publicKey } from '@metaplex-foundation/umi'\nimport { createUmi } from '@metaplex-foundation/umi-bundle-defaults'\n// [/IMPORTS]\n\n// [SETUP]\nconst umi = createUmi('https://api.devnet.solana.com').use(mplBubblegum())\n\nconst assetId = publicKey('YOUR_ASSET_ID')\n// [/SETUP]\n\n// [MAIN]\nconst assetWithProof = await getAssetWithProof(umi, assetId, {\n truncateCanopy: true,\n})\n\n// Leaf / hashing value (65535 when inherited)\nconsole.log(assetWithProof.metadata.sellerFeeBasisPoints)\n\n// Display / payout value from DAS main fields\nconsole.log(assetWithProof.rpcAsset.royalty?.basis_points)\n// [/MAIN]\n\n// [OUTPUT]\n// 65535\n// 500\n// [/OUTPUT]\n"
}

export const metadata = {
title: "getAssetWithProof with inherited royalties",
description: "Leaf metadata keeps the on-chain sentinel; DAS main royalty fields hold the collection-resolved display rate.",
tags: [],
}

export const examples = {
umi: {
framework: 'Umi',
language: 'typescript',
code: umiSections.full,
sections: umiSections,
},

}
28 changes: 28 additions & 0 deletions src/examples/bubblegum/get-asset-with-proof-inherited/umi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// [IMPORTS]
import { getAssetWithProof, mplBubblegum } from '@metaplex-foundation/mpl-bubblegum'
import { publicKey } from '@metaplex-foundation/umi'
import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
// [/IMPORTS]

// [SETUP]
const umi = createUmi('https://api.devnet.solana.com').use(mplBubblegum())

const assetId = publicKey('YOUR_ASSET_ID')
// [/SETUP]

// [MAIN]
const assetWithProof = await getAssetWithProof(umi, assetId, {
truncateCanopy: true,
})

// Leaf / hashing value (65535 when inherited)
console.log(assetWithProof.metadata.sellerFeeBasisPoints)

// Display / payout value from DAS main fields
console.log(assetWithProof.rpcAsset.royalty?.basis_points)
// [/MAIN]

// [OUTPUT]
// 65535
// 500
// [/OUTPUT]
32 changes: 32 additions & 0 deletions src/examples/bubblegum/mint-inherit-royalties/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

57 changes: 57 additions & 0 deletions src/examples/bubblegum/mint-inherit-royalties/umi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// [IMPORTS]
import { createTreeV2, mintV2, mplBubblegum } from '@metaplex-foundation/mpl-bubblegum'
import { createCollection, mplCore, ruleSet } from '@metaplex-foundation/mpl-core'
import { generateSigner, some } from '@metaplex-foundation/umi'
import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
// [/IMPORTS]

// [SETUP]
const umi = createUmi('https://api.devnet.solana.com')
.use(mplBubblegum())
.use(mplCore())

const merkleTree = generateSigner(umi)
const collectionSigner = generateSigner(umi)

await createTreeV2(umi, {
merkleTree,
maxDepth: 5,
maxBufferSize: 8,
}).sendAndConfirm(umi)

// The collection must include BubblegumV2 and Royalties plugins.
await createCollection(umi, {
collection: collectionSigner,
name: 'My Collection',
uri: 'https://example.com/collection.json',
plugins: [
{ type: 'BubblegumV2' },
{
type: 'Royalties',
basisPoints: 500, // 5%
creators: [{ address: umi.identity.publicKey, percentage: 100 }],
ruleSet: ruleSet('None'),
},
],
}).sendAndConfirm(umi)
// [/SETUP]

// [MAIN]
// sellerFeeBasisPoints is omitted — the SDK sends the inherit sentinel (65535).
await mintV2(umi, {
collectionAuthority: umi.identity,
leafOwner: umi.identity.publicKey,
merkleTree: merkleTree.publicKey,
coreCollection: collectionSigner.publicKey,
metadata: {
name: 'My NFT',
uri: 'https://example.com/my-nft.json',
collection: some(collectionSigner.publicKey),
creators: [], // must be empty when inheriting royalties
},
}).sendAndConfirm(umi)
// [/MAIN]

// [OUTPUT]
// cNFT minted with SELLER_FEE_BASIS_POINTS_INHERIT (65535) on the leaf
// [/OUTPUT]
32 changes: 32 additions & 0 deletions src/examples/bubblegum/update-inherit-royalties/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 50 additions & 0 deletions src/examples/bubblegum/update-inherit-royalties/umi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// [IMPORTS]
import {
getAssetWithProof,
updateMetadataV2,
UpdateArgsArgs,
mplBubblegum,
} from '@metaplex-foundation/mpl-bubblegum'
import { publicKey, some } from '@metaplex-foundation/umi'
import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
// [/IMPORTS]

// [SETUP]
const umi = createUmi('https://api.devnet.solana.com').use(mplBubblegum())

const assetId = publicKey('YOUR_ASSET_ID')
const collectionPublicKey = publicKey('YOUR_COLLECTION_ADDRESS')
// [/SETUP]

// [MAIN]
const assetWithProof = await getAssetWithProof(umi, assetId, {
truncateCanopy: true,
})

// Switch from inherited royalties to an explicit seller fee before removing
// the cNFT from its collection.
const updateArgs: UpdateArgsArgs = {
sellerFeeBasisPoints: some(550), // explicit 5.5%
}

await updateMetadataV2(umi, {
...assetWithProof,
currentMetadata: {
name: assetWithProof.metadata.name,
symbol: assetWithProof.metadata.symbol,
uri: assetWithProof.metadata.uri,
sellerFeeBasisPoints: assetWithProof.metadata.sellerFeeBasisPoints,
primarySaleHappened: assetWithProof.metadata.primarySaleHappened,
isMutable: assetWithProof.metadata.isMutable,
tokenStandard: assetWithProof.metadata.tokenStandard,
creators: assetWithProof.metadata.creators,
collection: some(collectionPublicKey),
},
updateArgs,
coreCollection: collectionPublicKey,
}).sendAndConfirm(umi)
// [/MAIN]

// [OUTPUT]
// Leaf seller fee updated from inherit sentinel (65535) to 550 basis points
// [/OUTPUT]
2 changes: 2 additions & 0 deletions src/pages/en/dev-tools/das-api/methods/get-asset.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ tableOfContents: false

Returns the information of a compressed/standard asset including metadata and owner.

For Bubblegum V2 cNFTs that inherit seller fees from an MPL-Core collection, collection-resolved display values are on `royalty.basis_points` / `creators`, and leaf values are on `royalty.basis_points_raw` / `creators_raw` (with `royalty.inherited: true`). See [Reading Inherited Royalties](/smart-contracts/bubblegum-v2/reading-inherited-royalties).

## Parameters

| Name | Required | Description |
Expand Down
16 changes: 15 additions & 1 deletion src/pages/en/smart-contracts/bubblegum-v2/collections.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: Managing Collections
metaTitle: Managing Collections - Bubblegum V2 - Metaplex
description: Learn how to set, change, and remove MPL-Core collections on compressed NFTs using Bubblegum V2. Covers the setCollectionV2 instruction.
created: '01-15-2025'
updated: '02-24-2026'
updated: '06-19-2026'
keywords:
- NFT collection
- verify collection
Expand All @@ -26,6 +26,8 @@ faqs:
a: Yes. Use setCollectionV2 with both coreCollection (current) and newCoreCollection (new) parameters. Both collection authorities must sign.
- q: What is the BubblegumV2 plugin?
a: It is an MPL-Core collection plugin that enables Bubblegum V2 features like freeze/thaw, soulbound cNFTs, and royalty enforcement on the collection.
- q: Can I remove a cNFT from a collection when it inherits royalties?
a: No. Update sellerFeeBasisPoints to an explicit value first, then remove the collection with setCollectionV2.
---

## Summary
Expand Down Expand Up @@ -118,12 +120,20 @@ const signature = await setCollectionV2(umi, {
{% /dialect %}
{% /dialect-switcher %}

## Inherited royalties {% #inherited-royalties %}

cNFTs minted with [inherited seller fee basis points](/smart-contracts/bubblegum-v2/mint-cnfts#inheriting-royalties-from-the-collection) store the sentinel value `65535` on the leaf. This affects collection management:

- **Removing a collection** — `setCollectionV2` rejects the operation while the leaf still uses the inherit sentinel. Update the cNFT to an explicit `sellerFeeBasisPoints` first via [`updateMetadataV2`](/smart-contracts/bubblegum-v2/update-cnfts#inherited-royalties).
- **Moving to another collection** — Allowed when the destination collection has the `Royalties` plugin. The cNFT keeps the inherit sentinel and resolves royalties from the new collection.
- **Moving to a collection without royalties** — Rejected with `CollectionMustHaveRoyaltiesPlugin`.

## Notes

- The MPL-Core collection must have the `BubblegumV2` plugin enabled before cNFTs can be added to it.
- Unlike Bubblegum V1 (which uses Token Metadata collections with a "verified" boolean), V2 uses MPL-Core collections without verification flags.
- When changing between collections, both the old and new collection authorities must sign the transaction.
- cNFTs with inherited seller fees cannot be removed from a collection until royalties are set to an explicit value on the leaf.

## FAQ

Expand All @@ -139,6 +149,10 @@ Yes. Use `setCollectionV2` with both `coreCollection` (current) and `newCoreColl

It is an MPL-Core collection plugin that enables Bubblegum V2 features like freeze/thaw, soulbound cNFTs, royalty enforcement, and permanent delegates on the collection level.

### Can I remove a cNFT from a collection when it inherits royalties?

No. The program returns `CannotRemoveFromCollectionWithInheritedSellerFee`. Use `updateMetadataV2` to set an explicit `sellerFeeBasisPoints` value first, then call `setCollectionV2` to remove the collection.

## Glossary

| Term | Definition |
Expand Down
Loading