@@ -80,6 +80,7 @@ import {
8080 getConfigureConfidentialTransferAccountInstruction ,
8181 getCreateAssociatedTokenIdempotentInstruction ,
8282 getEmptyConfidentialTransferAccountInstruction ,
83+ getPermissionedConfidentialBurnInstruction ,
8384 getReallocateInstruction ,
8485 getUpdateConfidentialMintBurnDecryptableSupplyInstruction ,
8586 fetchToken ,
@@ -328,6 +329,15 @@ type GetConfidentialBurnInstructionPlanBaseInput = {
328329export type GetConfidentialBurnInstructionPlanInput = GetConfidentialBurnInstructionPlanBaseInput &
329330 ConfidentialTransferContextStateProofMode ;
330331
332+ export type GetPermissionedConfidentialBurnInstructionPlanInput = GetConfidentialBurnInstructionPlanInput & {
333+ /**
334+ * The authority configured on the mint's `PermissionedBurn` extension. It
335+ * must sign every permissioned burn; the token-2022 program rejects the
336+ * standard burn variant when this extension is present.
337+ */
338+ permissionedBurnAuthority : TransactionSigner ;
339+ } ;
340+
331341export type GetUpdateConfidentialMintBurnDecryptableSupplyInstructionFromSupplyInput = {
332342 mint : Address ;
333343 authority : Address | TransactionSigner ;
@@ -1524,18 +1534,18 @@ export async function getConfidentialMintInstructionPlan(
15241534}
15251535
15261536/**
1527- * Returns an instruction plan that confidentially burns `amount` tokens from a
1528- * token account's available balance, encrypting the amount on-chain and
1529- * advancing the mint's encrypted pending burn. Symmetric to
1530- * `getConfidentialMintInstructionPlan`.
1537+ * Computes the three burn proofs (equality, grouped-ciphertext validity, U128
1538+ * range), builds their context-state setup/cleanup plans, and assembles the
1539+ * burn-instruction arguments shared by both the standard and permissioned burn
1540+ * variants. Shared by {@link getConfidentialBurnInstructionPlan} and
1541+ * {@link getPermissionedConfidentialBurnInstructionPlan} — the two differ only
1542+ * in which middle instruction they emit and its signer set, not in the proofs.
15311543 *
15321544 * The amount is grouped-encrypted under `[source, supply, auditor]`; the source
15331545 * handle (index 0) is homomorphically subtracted from the account's available
15341546 * balance, and the auditor handle (index 2) is carried by the instruction.
15351547 */
1536- export async function getConfidentialBurnInstructionPlan (
1537- input : GetConfidentialBurnInstructionPlanInput ,
1538- ) : Promise < InstructionPlan > {
1548+ async function buildConfidentialBurnProofPlan ( input : GetConfidentialBurnInstructionPlanInput ) {
15391549 const sourceAccount = getRequiredConfidentialTransferAccountExtension ( input . sourceTokenAccount ) ;
15401550 const mintBurnExtension = getRequiredMintExtension ( input . mintAccount , 'ConfidentialMintBurn' ) ;
15411551 const amount = BigInt ( input . amount ) ;
@@ -1638,31 +1648,80 @@ export async function getConfidentialBurnInstructionPlan(
16381648 buildContextStateProofPlan ( rangeProofData . toBytes ( ) , verifyBatchedRangeProofU128 , input . payer , input . rpc ) ,
16391649 ] ) ;
16401650
1641- return sequentialInstructionPlan ( [
1642- parallelInstructionPlan ( [ equalityProofPlan . setup , ciphertextValidityProofPlan . setup , rangeProofPlan . setup ] ) ,
1643- getConfidentialBurnInstruction (
1644- {
1645- token : input . token ,
1646- mint : input . mint ,
1647- equalityRecord : equalityProofPlan . address ,
1648- ciphertextValidityRecord : ciphertextValidityProofPlan . address ,
1649- rangeRecord : rangeProofPlan . address ,
1650- authority : input . authority ,
1651- newDecryptableAvailableBalance : input . aesKey . encrypt ( remainingBalance ) . toBytes ( ) ,
1652- burnAmountAuditorCiphertextLo,
1653- burnAmountAuditorCiphertextHi,
1654- equalityProofInstructionOffset : 0 ,
1655- ciphertextValidityProofInstructionOffset : 0 ,
1656- rangeProofInstructionOffset : 0 ,
1657- multiSigners : input . multiSigners ,
1658- } ,
1659- { programAddress : getTokenProgramAddress ( input . programAddress ) } ,
1660- ) ,
1661- parallelInstructionPlan ( [
1651+ return {
1652+ setup : parallelInstructionPlan ( [
1653+ equalityProofPlan . setup ,
1654+ ciphertextValidityProofPlan . setup ,
1655+ rangeProofPlan . setup ,
1656+ ] ) ,
1657+ cleanup : parallelInstructionPlan ( [
16621658 equalityProofPlan . cleanup ,
16631659 ciphertextValidityProofPlan . cleanup ,
16641660 rangeProofPlan . cleanup ,
16651661 ] ) ,
1662+ // Arguments common to both burn instruction variants. The account owner
1663+ // (`authority`) always signs; the variant-specific signer field
1664+ // (`multiSigners` / `permissionedBurnAuthority`) is added by the caller.
1665+ burnArgs : {
1666+ token : input . token ,
1667+ mint : input . mint ,
1668+ equalityRecord : equalityProofPlan . address ,
1669+ ciphertextValidityRecord : ciphertextValidityProofPlan . address ,
1670+ rangeRecord : rangeProofPlan . address ,
1671+ authority : input . authority ,
1672+ newDecryptableAvailableBalance : input . aesKey . encrypt ( remainingBalance ) . toBytes ( ) ,
1673+ burnAmountAuditorCiphertextLo,
1674+ burnAmountAuditorCiphertextHi,
1675+ equalityProofInstructionOffset : 0 ,
1676+ ciphertextValidityProofInstructionOffset : 0 ,
1677+ rangeProofInstructionOffset : 0 ,
1678+ } ,
1679+ } ;
1680+ }
1681+
1682+ /**
1683+ * Returns an instruction plan that confidentially burns `amount` tokens from a
1684+ * token account's available balance, encrypting the amount on-chain and
1685+ * advancing the mint's encrypted pending burn. Symmetric to
1686+ * `getConfidentialMintInstructionPlan`.
1687+ *
1688+ * Emits the **standard** `ConfidentialBurn` instruction. For mints carrying the
1689+ * `PermissionedBurn` extension the token-2022 program rejects this variant — use
1690+ * {@link getPermissionedConfidentialBurnInstructionPlan} instead.
1691+ */
1692+ export async function getConfidentialBurnInstructionPlan (
1693+ input : GetConfidentialBurnInstructionPlanInput ,
1694+ ) : Promise < InstructionPlan > {
1695+ const { setup, cleanup, burnArgs } = await buildConfidentialBurnProofPlan ( input ) ;
1696+ return sequentialInstructionPlan ( [
1697+ setup ,
1698+ getConfidentialBurnInstruction (
1699+ { ...burnArgs , multiSigners : input . multiSigners } ,
1700+ { programAddress : getTokenProgramAddress ( input . programAddress ) } ,
1701+ ) ,
1702+ cleanup ,
1703+ ] ) ;
1704+ }
1705+
1706+ /**
1707+ * Like {@link getConfidentialBurnInstructionPlan}, but emits the **permissioned**
1708+ * burn variant, which token-2022 requires for mints carrying the
1709+ * `PermissionedBurn` extension (it rejects the standard variant on such mints
1710+ * with `TokenError::InvalidInstruction`). Identical proofs; the only difference
1711+ * is the mint's configured `permissionedBurnAuthority` co-signs alongside the
1712+ * account owner (`authority`).
1713+ */
1714+ export async function getPermissionedConfidentialBurnInstructionPlan (
1715+ input : GetPermissionedConfidentialBurnInstructionPlanInput ,
1716+ ) : Promise < InstructionPlan > {
1717+ const { setup, cleanup, burnArgs } = await buildConfidentialBurnProofPlan ( input ) ;
1718+ return sequentialInstructionPlan ( [
1719+ setup ,
1720+ getPermissionedConfidentialBurnInstruction (
1721+ { ...burnArgs , permissionedBurnAuthority : input . permissionedBurnAuthority } ,
1722+ { programAddress : getTokenProgramAddress ( input . programAddress ) } ,
1723+ ) ,
1724+ cleanup ,
16661725 ] ) ;
16671726}
16681727
0 commit comments