gist June 7, 2023

Calc Merkle Tree Size

Utility for calculating merkle tree size config when setting up a Solana compressed NFT project.
import {
  ALL_DEPTH_SIZE_PAIRS,
  getConcurrentMerkleTreeAccountSize,
} from "@solana/spl-account-compression";
import { Connection, LAMPORTS_PER_SOL } from "@solana/web3.js";

type CostResult = {
  size: number;
  cost: number;
};

type TreeResult = {
  maxProof: number;
  canopy: number;
  maxBuffer: number;
  maxDepth: number;
  supply: number;
} & CostResult;

// Get cost to create tree
const getTreeCost = async (size: number, connection: Connection) => {
  try {
    const rent =
      (await connection.getMinimumBalanceForRentExemption(size)) /
      LAMPORTS_PER_SOL;

    return rent;
  } catch (error) {}

  return 0;
};

// Accepts a supply as a number and returns a tree that should work.
export const calculateTreeSize = async (
  supply: number
): Promise<TreeResult | null> => {
  // Tensor max proof is 9 so this should be supported and provide extra room.
  const MAX_PROOF_SIZE = 8;

  // Include results with the following max buffer size.
  const MAX_BUFFER_SIZES = [64];

  const connection = new Connection("https://api.mainnet-beta.solana.com");

  const relevantDepthPairs = ALL_DEPTH_SIZE_PAIRS.filter(
    ({ maxBufferSize }) => MAX_BUFFER_SIZES.indexOf(maxBufferSize) >= 0
  );

  let result: TreeResult | null = null;

  for (const pair of relevantDepthPairs) {
    const canopy = pair.maxDepth - MAX_PROOF_SIZE;

    const size = getConcurrentMerkleTreeAccountSize(
      pair.maxDepth,
      pair.maxBufferSize,
      canopy
    );

    const cost = await getTreeCost(size, connection);

    const maxSupply = Math.pow(2, pair.maxDepth);

    // If no cost or max buffer isn't one we are looking for.
    if (!cost || maxSupply <= supply) {
      continue;
    }

    result = {
      maxProof: MAX_PROOF_SIZE,
      canopy,
      maxBuffer: pair.maxBufferSize,
      maxDepth: pair.maxDepth,
      size,
      cost,
      supply: maxSupply,
    };

    break;
  }

  return result;
};

Get in touch