My objective here is to burn cNFTs on the frontend but it keeps failing b/c tx size is too large. I've attempted to do this with the older createBurnInstruction
fn as well as the burn
fn with umi
. I've also attempted to fetch the proof of the cNFTs from multiple sources. These sources include Helius RPC (DAS getAssetProofBatch
method) and the API that Phantom uses(I can burn these cNFT's there w/out issues). Always on mainnet env. Here's the asset on Helius
I was debugging another cNFT with this same issue and when I trimmed down the proof
length by 1 it actually worked. From my code you can see that I'm determining this via the canopyDepth
which at the time was 0 (same as the cNFT above that I'm debugging with now). The proof size is 24 which according to compressed.app is a valid. Something has to be off with the proofs and canopy size is my guess but I'm at a loss after a lot of debugging. Is there anything obvious to anyone that I'm missing here?
export const buildBurnCnftTxs = async (
umi: Context,
connection: Connection,
cnfts: AssetToBurn[],
): Promise<TransactionBuilder[]> => {
if (cnfts.length === 0) return [];
const cNftIds = cnfts.map((i) => i.id);
const cNnftProofs = await getAssetProofBatch({ ids: cNftIds });
const builders = await Promise.all(
cnfts.map(async (asset) => {
const assetProof = cNnftProofs[asset.id];
const treeAccount = await ConcurrentMerkleTreeAccount.fromAccountAddress(
connection,
new PublicKey(assetProof.tree_id),
);
const treeAuthority = treeAccount.getAuthority();
const canopyDepth = treeAccount.getCanopyDepth() || 0;
// parse the list of proof addresses into a valid AccountMeta[]
const proof: AccountMeta[] = assetProof.proof
// remove the id's that are already part of the canopy
.slice(0, assetProof.proof.length - (!!canopyDepth ? canopyDepth : 0))
.map((node: string) => ({
pubkey: new PublicKey(node),
isSigner: false,
isWritable: false,
}));
const burnIx = createBurnInstruction(
{
merkleTree: new PublicKey(assetProof.tree_id),
treeAuthority,
leafOwner: new PublicKey(asset.ownership.owner),
leafDelegate: new PublicKey(
asset.ownership.delegate || asset.ownership.owner,
),
logWrapper: SPL_NOOP_PROGRAM_ID,
compressionProgram: SPL_ACCOUNT_COMPRESSION_PROGRAM_ID,
anchorRemainingAccounts: proof,
},
{
root: [...new PublicKey(assetProof.root.trim()).toBytes()],
dataHash: [
...new PublicKey(asset.compression!.data_hash.trim()).toBytes(),
],
creatorHash: [
...new PublicKey(asset.compression!.creator_hash.trim()).toBytes(),
],
nonce: asset.compression!.leaf_id,
index: asset.compression!.leaf_id,
},
BUBBLEGUM_PROGRAM_ID,
);
const builder = transactionBuilder().add({
instruction: {
keys: burnIx.keys.map((i) => ({
...i,
pubkey: publicKey(i.pubkey),
})),
programId: publicKey(burnIx.programId),
data: burnIx.data,
},
signers: [umi.payer],
bytesCreatedOnChain: 0,
});
const txSizeInBurn = builder.getTransactionSize(umi);
console.log({ txSizeInBurn });
return builder;
}),
);
return builders;
};