Skip to content

Add interactive Bubblegum tree cost calculator with merkle tree visua…#468

Merged
blockiosaurus merged 3 commits intomainfrom
claude/add-bubblegum-calculator-cuez6
Mar 26, 2026
Merged

Add interactive Bubblegum tree cost calculator with merkle tree visua…#468
blockiosaurus merged 3 commits intomainfrom
claude/add-bubblegum-calculator-cuez6

Conversation

@blockiosaurus
Copy link
Copy Markdown
Contributor

…lization

Adds an interactive calculator component to the "Creating Bubblegum Trees" pages for both Bubblegum v1 and v2. The calculator has two modes:

  • Quick Estimate: enter desired cNFT count, get three cost options (min/balanced/max canopy)
  • Advanced: manually tune maxDepth, maxBufferSize, and canopyDepth with live cost updates

Includes an SVG merkle tree visualization that shows canopy nodes (green), proof nodes (gray), and leaf nodes (blue) updating in real-time as parameters change.

Math validated against the SPL Account Compression program:

  • Account size = header(56) + tree(64 + buf*(40+depth32) + depth32) + canopy((2^(cd+1)-2)*32)
  • Rent = (size + 128) * 6960 lamports
  • All 33 valid depth/buffer pairs from ALL_DEPTH_SIZE_PAIRS included

Added to all 4 locales (en, ja, ko, zh) for both bubblegum and bubblegum-v2.

https://claude.ai/code/session_01Q2cQRgz6W8xHbm2TewiHzM

…lization

Adds an interactive calculator component to the "Creating Bubblegum Trees" pages
for both Bubblegum v1 and v2. The calculator has two modes:

- Quick Estimate: enter desired cNFT count, get three cost options (min/balanced/max canopy)
- Advanced: manually tune maxDepth, maxBufferSize, and canopyDepth with live cost updates

Includes an SVG merkle tree visualization that shows canopy nodes (green),
proof nodes (gray), and leaf nodes (blue) updating in real-time as parameters change.

Math validated against the SPL Account Compression program:
- Account size = header(56) + tree(64 + buf*(40+depth*32) + depth*32) + canopy((2^(cd+1)-2)*32)
- Rent = (size + 128) * 6960 lamports
- All 33 valid depth/buffer pairs from ALL_DEPTH_SIZE_PAIRS included

Added to all 4 locales (en, ja, ko, zh) for both bubblegum and bubblegum-v2.

https://claude.ai/code/session_01Q2cQRgz6W8xHbm2TewiHzM
@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 4, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
developer-hub Ready Ready Preview, Comment Mar 8, 2026 2:44pm

Request Review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 4, 2026

Summary by CodeRabbit

  • New Features

    • Added an interactive Bubblegum cost calculator with Simple and Advanced modes, presets for common targets, live cost/capacity/proof estimates, input validation, and a Merkle tree visualization.
  • Documentation

    • Embedded the calculator and added detailed cost/configuration tables and explanatory guidance across English, Japanese, Korean, and Chinese create-tree guides.

Walkthrough

Adds a new BubblegumCalculator React component, registers a self-closing Markdoc tag bubblegum-calculator, and embeds the calculator into localized Bubblegum tree creation docs. The component performs cost/rent modeling, offers Simple/Advanced modes, and renders a Merkle tree visualization.

Changes

Cohort / File(s) Summary
Component & Tag Registration
src/components/BubblegumCalculator.jsx, markdoc/tags.js
Adds BubblegumCalculator React component (cost/rent calculations, presets, Simple/Advanced UI, Merkle visualization) and registers a public, self-closing Markdoc tag bubblegum-calculator.
English docs
src/pages/en/smart-contracts/bubblegum/create-trees.md, src/pages/en/smart-contracts/bubblegum-v2/create-trees.md
Embeds the calculator tag, adds explanatory text and a table of recommended tree configurations with costs.
Japanese docs
src/pages/ja/smart-contracts/bubblegum/create-trees.md, src/pages/ja/smart-contracts/bubblegum-v2/create-trees.md
Inserted calculator embed and localized explanatory content for cost estimation.
Korean docs
src/pages/ko/smart-contracts/bubblegum/create-trees.md, src/pages/ko/smart-contracts/bubblegum-v2/create-trees.md
Inserted calculator embed, Korean guidance, and recommended configuration content.
Chinese docs
src/pages/zh/smart-contracts/bubblegum/create-trees.md, src/pages/zh/smart-contracts/bubblegum-v2/create-trees.md
Added calculator embed, localized explanatory text, and configuration/cost tables in Simplified Chinese.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant User as User
    participant Browser as Browser/Page
    participant Markdoc as Markdoc Renderer
    participant Component as BubblegumCalculator
    participant Helper as Cost & Visualization Logic

    User->>Browser: Open create-trees page
    Browser->>Markdoc: Render page content (includes `bubblegum-calculator` tag)
    Markdoc->>Component: Instantiate BubblegumCalculator
    Component->>Helper: Compute sizes, rent, costs, presets
    Helper-->>Component: Return computed metrics
    Component-->>Browser: Render UI and visualization
    User->>Component: Interact (toggle mode, change target NFTs)
    Component->>Helper: Recompute metrics
    Helper-->>Component: Updated metrics
    Component-->>Browser: Update UI and visualization
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • tonyboylehub
  • MarkSackerberg
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding an interactive Bubblegum tree cost calculator with merkle tree visualization.
Description check ✅ Passed The description provides relevant details about the calculator's two modes, visualization features, mathematical validation, and localization support—all present in the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch claude/add-bubblegum-calculator-cuez6

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/BubblegumCalculator.jsx`:
- Around line 292-299: In BubblegumCalculator.jsx, the clickable button elements
that call setMode('simple') / setMode('advanced') (the buttons that inspect mode
and use the onClick handler) need an explicit type="button" attribute to prevent
them from acting as implicit submit buttons when this component is placed inside
a form; update each <button> (the ones toggling mode—the group using mode ===
'simple' / mode === 'advanced' and the similar buttons around the 368–376 range)
to include type="button" while keeping the existing onClick and className logic
intact.
- Around line 350-352: Multiple <label> elements in BubblegumCalculator.jsx
aren’t bound to their inputs, breaking accessibility; update each label (e.g.,
the label "How many compressed NFTs do you need?" and the other labels around
lines noted) to be programmatically associated by adding htmlFor attributes that
match unique id attributes on the corresponding input/select elements (or
alternatively wrap the input/select inside the label). Locate the related JSX
for each question/input pair in the BubblegumCalculator component, add stable id
values (e.g., countInput, collectionSelect, feeInput, etc.) to the input/select
elements, and set each label’s htmlFor to that id so screen readers and form
controls are correctly linked.
- Around line 134-135: The SVG in BubblegumCalculator.jsx lacks an accessible
name; wrap a <title> and reference it from the <svg> using aria-labelledby (or
set aria-label) so assistive tech can announce the visualization. In the
BubblegumCalculator component, create a stable title id (use React's useId or
generate one) and render <title id={svgTitleId}>Descriptive name</title> inside
the <svg>, then add aria-labelledby={svgTitleId} (and role="img" if not present)
on the <svg> element so the edges map and visual are announced.
- Around line 300-310: The BubblegumCalculator.jsx component currently hardcodes
UI strings like "Quick Estimate" and "Advanced" (inside the button that calls
setMode and reads mode), which breaks localization; replace these literals with
calls to your localization system (e.g., t('calculator.quickEstimate') /
t('calculator.advanced') or a translations prop) wherever text is hardcoded
(including the other affected spots around the component at the ranges you
noted), updating the JSX to use the localized keys and ensure any aria-labels,
placeholders, and button labels use the same keys so ja/ko/zh docs render
translated copy.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 5c289fb3-5916-403a-9a72-689468e59fba

📥 Commits

Reviewing files that changed from the base of the PR and between 0f2115c and 4a02e17.

📒 Files selected for processing (10)
  • markdoc/tags.js
  • src/components/BubblegumCalculator.jsx
  • src/pages/en/smart-contracts/bubblegum-v2/create-trees.md
  • src/pages/en/smart-contracts/bubblegum/create-trees.md
  • src/pages/ja/smart-contracts/bubblegum-v2/create-trees.md
  • src/pages/ja/smart-contracts/bubblegum/create-trees.md
  • src/pages/ko/smart-contracts/bubblegum-v2/create-trees.md
  • src/pages/ko/smart-contracts/bubblegum/create-trees.md
  • src/pages/zh/smart-contracts/bubblegum-v2/create-trees.md
  • src/pages/zh/smart-contracts/bubblegum/create-trees.md

Comment thread src/components/BubblegumCalculator.jsx Outdated
Comment thread src/components/BubblegumCalculator.jsx
Comment thread src/components/BubblegumCalculator.jsx
Comment thread src/components/BubblegumCalculator.jsx Outdated
MarkSackerberg
MarkSackerberg previously approved these changes Mar 5, 2026
Copy link
Copy Markdown
Contributor

@MarkSackerberg MarkSackerberg left a comment

Choose a reason for hiding this comment

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

Code Rabbit is not wrong with the localization, but besides that fine with me. Numbers match with compressed.app

The Bubblegum program's create_tree instruction validates that
canopy depth >= maxDepth - 17 (MAX_ACC_PROOFS_SIZE), rejecting trees
that would produce proofs too large for a single Solana transaction.
The calculator now enforces these on-chain constraints:

- Minimum canopy: max(0, maxDepth - 17) per check_canopy_size
- Maximum canopy: min(maxDepth, 17) due to Solana 10MB account limit
- Simple mode "Minimum cost" uses the program minimum, not zero
- Advanced mode slider respects min/max bounds with warning text
- Both v1 and v2 share the same canopy validation logic

https://claude.ai/code/session_01Q2cQRgz6W8xHbm2TewiHzM
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/BubblegumCalculator.jsx`:
- Around line 8-45: Replace the hardcoded VALID_DEPTH_BUFFER_PAIRS with the
official tuples from the canonical package (`@solana/spl-account-compression`) so
the component only recommends supported on-chain configurations; import or
reference the package's ALL_DEPTH_SIZE_PAIRS (or the equivalent exported
constant) and assign VALID_DEPTH_BUFFER_PAIRS = ALL_DEPTH_SIZE_PAIRS (or a
filtered copy) and regenerate UNIQUE_DEPTHS from that array (keep UNIQUE_DEPTHS
= [...new Set(VALID_DEPTH_BUFFER_PAIRS.map(p => p.maxDepth))]) so only allowed
maxDepth values (3, 5, 14–20, 24, 26, 30) are used.
- Around line 130-146: The code incorrectly treats the root (level === 0) as
canopy when canopyLevel > 0; update both the node type and edge type assignments
in BubblegumCalculator.jsx so canopy is only applied when level > 0 and level <=
canopyLevel (e.g., replace the current checks that use level < canopyLevel /
level <= canopyLevel / level === canopyLevel with a single condition like level
> 0 && level <= canopyLevel for assigning type and edgeType, referencing the
variables type, edgeType, level, and canopyLevel).
- Around line 309-319: The input handler handleNftInput currently only strips
commas and then uses parseInt, which fails for other locale group separators;
update handleNftInput to normalize the input by removing all non-digit
characters (e.g., raw = e.target.value.replace(/\D/g, '')) before parsing to an
integer, then apply the same validation logic (setDesiredNfts(1) for
invalid/empty, clamp to Math.pow(2,30) if too large, otherwise set the parsed
number); keep the rest of the component (including
value={desiredNfts.toLocaleString()}) unchanged so formatting remains
locale-aware while parsing accepts any locale-specific separators.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: b97c71c5-c5f9-4e23-849c-b886932b74b5

📥 Commits

Reviewing files that changed from the base of the PR and between 4a02e17 and 5f43d19.

📒 Files selected for processing (1)
  • src/components/BubblegumCalculator.jsx

Comment thread src/components/BubblegumCalculator.jsx
Comment thread src/components/BubblegumCalculator.jsx
Comment thread src/components/BubblegumCalculator.jsx
…rsing

- Remove unsupported depth/buffer pairs (depths 6-13) not in SPL ALL_DEPTH_SIZE_PAIRS
- Add SVG accessibility: role="img" and descriptive <title> for tree visualization
- Add type="button" to all buttons to prevent accidental form submissions
- Add htmlFor/id bindings for all form labels and inputs
- Fix locale number parsing: replace /,/g with /\D/g to handle all locale separators

https://claude.ai/code/session_01Q2cQRgz6W8xHbm2TewiHzM
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (2)
src/components/BubblegumCalculator.jsx (2)

88-90: ⚠️ Potential issue | 🟠 Major

The component still isn't localized.

BubblegumCalculator has no locale/translation input, the UI copy is still hardcoded in English, and the numeric formatting is tied to the runtime default locale. When this widget is embedded in the ja/ko/zh docs, it still won't match the page language.

Suggested direction
-function formatNumber(n) {
-  return new Intl.NumberFormat().format(n)
+function formatNumber(n, locale) {
+  return new Intl.NumberFormat(locale).format(n)
 }
 
-export function BubblegumCalculator() {
+export function BubblegumCalculator({ locale = 'en', copy = COPY[locale] ?? COPY.en }) {
@@
-          Quick Estimate
+          {copy.quickEstimate}
@@
-          Advanced
+          {copy.advanced}

Based on learnings, localized documentation should translate page body prose while keeping Markdoc component names in English.

Also applies to: 232-338, 386-386

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/BubblegumCalculator.jsx` around lines 88 - 90, The
BubblegumCalculator component is not localized: update the component (and helper
formatNumber) to accept a locale prop (e.g., locale) and use it when formatting
numbers (call Intl.NumberFormat(locale).format) and expose or accept translated
UI strings (labels/buttons/placeholders) as props or a translations object so
all hardcoded English copy in BubblegumCalculator and formatNumber can be
replaced; ensure callers pass the page locale (e.g., "ja"/"ko"/"zh") into
BubblegumCalculator and update any internal uses (formatNumber, displayed
labels, and button text) to use the provided locale/translation props rather
than runtime defaults or hardcoded English.

122-138: ⚠️ Potential issue | 🟡 Minor

Don't count the root as part of the canopy.

The rent math excludes the root (2^(n+1)-2), but the visualization still marks level 0 as canopy whenever canopyDepth > 0. That overstates the cached canopy by one node and colors one extra edge level.

Suggested fix
       let type = 'proof'
-      if (level < canopyLevel) type = 'canopy'
-      else if (level === canopyLevel && canopyLevel > 0) type = 'canopy'
+      if (level > 0 && level <= canopyLevel) type = 'canopy'
       if (level === displayDepth) type = 'leaf'
@@
       let edgeType = 'proof'
-      if (level <= canopyLevel) edgeType = 'canopy'
+      if (level > 0 && level <= canopyLevel) edgeType = 'canopy'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/BubblegumCalculator.jsx` around lines 122 - 138, The
visualization is counting level 0 as canopy; update the canopy checks so the
root (level === 0) is excluded. Replace the node type logic (currently using if
(level < canopyLevel) / else if (level === canopyLevel && canopyLevel > 0)) with
a single check that marks canopy only when level > 0 and level <= canopyLevel
(while preserving the leaf override for displayDepth), and likewise change the
edge type assignment (edgeType = 'canopy') to only apply when level > 0 && level
<= canopyLevel so edges from the root are not colored as canopy.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/components/BubblegumCalculator.jsx`:
- Around line 88-90: The BubblegumCalculator component is not localized: update
the component (and helper formatNumber) to accept a locale prop (e.g., locale)
and use it when formatting numbers (call Intl.NumberFormat(locale).format) and
expose or accept translated UI strings (labels/buttons/placeholders) as props or
a translations object so all hardcoded English copy in BubblegumCalculator and
formatNumber can be replaced; ensure callers pass the page locale (e.g.,
"ja"/"ko"/"zh") into BubblegumCalculator and update any internal uses
(formatNumber, displayed labels, and button text) to use the provided
locale/translation props rather than runtime defaults or hardcoded English.
- Around line 122-138: The visualization is counting level 0 as canopy; update
the canopy checks so the root (level === 0) is excluded. Replace the node type
logic (currently using if (level < canopyLevel) / else if (level === canopyLevel
&& canopyLevel > 0)) with a single check that marks canopy only when level > 0
and level <= canopyLevel (while preserving the leaf override for displayDepth),
and likewise change the edge type assignment (edgeType = 'canopy') to only apply
when level > 0 && level <= canopyLevel so edges from the root are not colored as
canopy.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: f9de6b3a-dcca-4282-bb69-31bdcbba07cf

📥 Commits

Reviewing files that changed from the base of the PR and between 5f43d19 and 9d40036.

📒 Files selected for processing (1)
  • src/components/BubblegumCalculator.jsx

@blockiosaurus blockiosaurus merged commit b9b3eec into main Mar 26, 2026
3 checks passed
@blockiosaurus blockiosaurus deleted the claude/add-bubblegum-calculator-cuez6 branch March 26, 2026 17:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants