From 8dbae66f86a5b0b80516865e82954be415845d88 Mon Sep 17 00:00:00 2001 From: 0xCipherCoder Date: Thu, 14 Nov 2024 17:18:22 +0530 Subject: [PATCH] Define IDL instructions for the confidential transfer fee extension (#51) Added confidential transfer fees extension --- .../instructions/disableHarvestToMint.ts | 220 +++++++ .../instructions/enableHarvestToMint.ts | 220 +++++++ ...dTokensToMintForConfidentialTransferFee.ts | 195 ++++++ .../js/src/generated/instructions/index.ts | 6 + .../initializeConfidentialTransferFee.ts | 227 +++++++ ...sFromAccountsForConfidentialTransferFee.ts | 322 +++++++++ ...okensFromMintForConfidentialTransferFee.ts | 315 +++++++++ .../js/src/generated/programs/token2022.ts | 66 ++ .../getInitializeInstructionsForExtensions.ts | 9 + .../initializeConfidentialTransferFee.test.ts | 126 ++++ program/idl.json | 612 ++++++++++++++++++ 11 files changed, 2318 insertions(+) create mode 100644 clients/js/src/generated/instructions/disableHarvestToMint.ts create mode 100644 clients/js/src/generated/instructions/enableHarvestToMint.ts create mode 100644 clients/js/src/generated/instructions/harvestWithheldTokensToMintForConfidentialTransferFee.ts create mode 100644 clients/js/src/generated/instructions/initializeConfidentialTransferFee.ts create mode 100644 clients/js/src/generated/instructions/withdrawWithheldTokensFromAccountsForConfidentialTransferFee.ts create mode 100644 clients/js/src/generated/instructions/withdrawWithheldTokensFromMintForConfidentialTransferFee.ts create mode 100644 clients/js/test/extensions/confidentialTransferFee/initializeConfidentialTransferFee.test.ts diff --git a/clients/js/src/generated/instructions/disableHarvestToMint.ts b/clients/js/src/generated/instructions/disableHarvestToMint.ts new file mode 100644 index 0000000..d2bf9e5 --- /dev/null +++ b/clients/js/src/generated/instructions/disableHarvestToMint.ts @@ -0,0 +1,220 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + AccountRole, + combineCodec, + getStructDecoder, + getStructEncoder, + getU8Decoder, + getU8Encoder, + transformEncoder, + type Address, + type Codec, + type Decoder, + type Encoder, + type IAccountMeta, + type IAccountSignerMeta, + type IInstruction, + type IInstructionWithAccounts, + type IInstructionWithData, + type ReadonlyAccount, + type ReadonlySignerAccount, + type TransactionSigner, + type WritableAccount, +} from '@solana/web3.js'; +import { TOKEN_2022_PROGRAM_ADDRESS } from '../programs'; +import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; + +export const DISABLE_HARVEST_TO_MINT_DISCRIMINATOR = 37; + +export function getDisableHarvestToMintDiscriminatorBytes() { + return getU8Encoder().encode(DISABLE_HARVEST_TO_MINT_DISCRIMINATOR); +} + +export const DISABLE_HARVEST_TO_MINT_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR = 5; + +export function getDisableHarvestToMintConfidentialTransferFeeDiscriminatorBytes() { + return getU8Encoder().encode( + DISABLE_HARVEST_TO_MINT_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR + ); +} + +export type DisableHarvestToMintInstruction< + TProgram extends string = typeof TOKEN_2022_PROGRAM_ADDRESS, + TAccountMint extends string | IAccountMeta = string, + TAccountAuthority extends string | IAccountMeta = string, + TRemainingAccounts extends readonly IAccountMeta[] = [], +> = IInstruction & + IInstructionWithData & + IInstructionWithAccounts< + [ + TAccountMint extends string + ? WritableAccount + : TAccountMint, + TAccountAuthority extends string + ? ReadonlyAccount + : TAccountAuthority, + ...TRemainingAccounts, + ] + >; + +export type DisableHarvestToMintInstructionData = { + discriminator: number; + confidentialTransferFeeDiscriminator: number; +}; + +export type DisableHarvestToMintInstructionDataArgs = {}; + +export function getDisableHarvestToMintInstructionDataEncoder(): Encoder { + return transformEncoder( + getStructEncoder([ + ['discriminator', getU8Encoder()], + ['confidentialTransferFeeDiscriminator', getU8Encoder()], + ]), + (value) => ({ + ...value, + discriminator: DISABLE_HARVEST_TO_MINT_DISCRIMINATOR, + confidentialTransferFeeDiscriminator: + DISABLE_HARVEST_TO_MINT_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR, + }) + ); +} + +export function getDisableHarvestToMintInstructionDataDecoder(): Decoder { + return getStructDecoder([ + ['discriminator', getU8Decoder()], + ['confidentialTransferFeeDiscriminator', getU8Decoder()], + ]); +} + +export function getDisableHarvestToMintInstructionDataCodec(): Codec< + DisableHarvestToMintInstructionDataArgs, + DisableHarvestToMintInstructionData +> { + return combineCodec( + getDisableHarvestToMintInstructionDataEncoder(), + getDisableHarvestToMintInstructionDataDecoder() + ); +} + +export type DisableHarvestToMintInput< + TAccountMint extends string = string, + TAccountAuthority extends string = string, +> = { + /** The token mint. */ + mint: Address; + /** The confidential transfer fee authority */ + authority: Address | TransactionSigner; + multiSigners?: Array; +}; + +export function getDisableHarvestToMintInstruction< + TAccountMint extends string, + TAccountAuthority extends string, + TProgramAddress extends Address = typeof TOKEN_2022_PROGRAM_ADDRESS, +>( + input: DisableHarvestToMintInput, + config?: { programAddress?: TProgramAddress } +): DisableHarvestToMintInstruction< + TProgramAddress, + TAccountMint, + (typeof input)['authority'] extends TransactionSigner + ? ReadonlySignerAccount & + IAccountSignerMeta + : TAccountAuthority +> { + // Program address. + const programAddress = config?.programAddress ?? TOKEN_2022_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + mint: { value: input.mint ?? null, isWritable: true }, + authority: { value: input.authority ?? null, isWritable: false }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + // Original args. + const args = { ...input }; + + // Remaining accounts. + const remainingAccounts: IAccountMeta[] = (args.multiSigners ?? []).map( + (signer) => ({ + address: signer.address, + role: AccountRole.READONLY_SIGNER, + signer, + }) + ); + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [ + getAccountMeta(accounts.mint), + getAccountMeta(accounts.authority), + ...remainingAccounts, + ], + programAddress, + data: getDisableHarvestToMintInstructionDataEncoder().encode({}), + } as DisableHarvestToMintInstruction< + TProgramAddress, + TAccountMint, + (typeof input)['authority'] extends TransactionSigner + ? ReadonlySignerAccount & + IAccountSignerMeta + : TAccountAuthority + >; + + return instruction; +} + +export type ParsedDisableHarvestToMintInstruction< + TProgram extends string = typeof TOKEN_2022_PROGRAM_ADDRESS, + TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], +> = { + programAddress: Address; + accounts: { + /** The token mint. */ + mint: TAccountMetas[0]; + /** The confidential transfer fee authority */ + authority: TAccountMetas[1]; + }; + data: DisableHarvestToMintInstructionData; +}; + +export function parseDisableHarvestToMintInstruction< + TProgram extends string, + TAccountMetas extends readonly IAccountMeta[], +>( + instruction: IInstruction & + IInstructionWithAccounts & + IInstructionWithData +): ParsedDisableHarvestToMintInstruction { + if (instruction.accounts.length < 2) { + // TODO: Coded error. + throw new Error('Not enough accounts'); + } + let accountIndex = 0; + const getNextAccount = () => { + const accountMeta = instruction.accounts![accountIndex]!; + accountIndex += 1; + return accountMeta; + }; + return { + programAddress: instruction.programAddress, + accounts: { + mint: getNextAccount(), + authority: getNextAccount(), + }, + data: getDisableHarvestToMintInstructionDataDecoder().decode( + instruction.data + ), + }; +} diff --git a/clients/js/src/generated/instructions/enableHarvestToMint.ts b/clients/js/src/generated/instructions/enableHarvestToMint.ts new file mode 100644 index 0000000..c67e524 --- /dev/null +++ b/clients/js/src/generated/instructions/enableHarvestToMint.ts @@ -0,0 +1,220 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + AccountRole, + combineCodec, + getStructDecoder, + getStructEncoder, + getU8Decoder, + getU8Encoder, + transformEncoder, + type Address, + type Codec, + type Decoder, + type Encoder, + type IAccountMeta, + type IAccountSignerMeta, + type IInstruction, + type IInstructionWithAccounts, + type IInstructionWithData, + type ReadonlyAccount, + type ReadonlySignerAccount, + type TransactionSigner, + type WritableAccount, +} from '@solana/web3.js'; +import { TOKEN_2022_PROGRAM_ADDRESS } from '../programs'; +import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; + +export const ENABLE_HARVEST_TO_MINT_DISCRIMINATOR = 37; + +export function getEnableHarvestToMintDiscriminatorBytes() { + return getU8Encoder().encode(ENABLE_HARVEST_TO_MINT_DISCRIMINATOR); +} + +export const ENABLE_HARVEST_TO_MINT_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR = 4; + +export function getEnableHarvestToMintConfidentialTransferFeeDiscriminatorBytes() { + return getU8Encoder().encode( + ENABLE_HARVEST_TO_MINT_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR + ); +} + +export type EnableHarvestToMintInstruction< + TProgram extends string = typeof TOKEN_2022_PROGRAM_ADDRESS, + TAccountMint extends string | IAccountMeta = string, + TAccountAuthority extends string | IAccountMeta = string, + TRemainingAccounts extends readonly IAccountMeta[] = [], +> = IInstruction & + IInstructionWithData & + IInstructionWithAccounts< + [ + TAccountMint extends string + ? WritableAccount + : TAccountMint, + TAccountAuthority extends string + ? ReadonlyAccount + : TAccountAuthority, + ...TRemainingAccounts, + ] + >; + +export type EnableHarvestToMintInstructionData = { + discriminator: number; + confidentialTransferFeeDiscriminator: number; +}; + +export type EnableHarvestToMintInstructionDataArgs = {}; + +export function getEnableHarvestToMintInstructionDataEncoder(): Encoder { + return transformEncoder( + getStructEncoder([ + ['discriminator', getU8Encoder()], + ['confidentialTransferFeeDiscriminator', getU8Encoder()], + ]), + (value) => ({ + ...value, + discriminator: ENABLE_HARVEST_TO_MINT_DISCRIMINATOR, + confidentialTransferFeeDiscriminator: + ENABLE_HARVEST_TO_MINT_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR, + }) + ); +} + +export function getEnableHarvestToMintInstructionDataDecoder(): Decoder { + return getStructDecoder([ + ['discriminator', getU8Decoder()], + ['confidentialTransferFeeDiscriminator', getU8Decoder()], + ]); +} + +export function getEnableHarvestToMintInstructionDataCodec(): Codec< + EnableHarvestToMintInstructionDataArgs, + EnableHarvestToMintInstructionData +> { + return combineCodec( + getEnableHarvestToMintInstructionDataEncoder(), + getEnableHarvestToMintInstructionDataDecoder() + ); +} + +export type EnableHarvestToMintInput< + TAccountMint extends string = string, + TAccountAuthority extends string = string, +> = { + /** The token mint. */ + mint: Address; + /** The confidential transfer fee authority */ + authority: Address | TransactionSigner; + multiSigners?: Array; +}; + +export function getEnableHarvestToMintInstruction< + TAccountMint extends string, + TAccountAuthority extends string, + TProgramAddress extends Address = typeof TOKEN_2022_PROGRAM_ADDRESS, +>( + input: EnableHarvestToMintInput, + config?: { programAddress?: TProgramAddress } +): EnableHarvestToMintInstruction< + TProgramAddress, + TAccountMint, + (typeof input)['authority'] extends TransactionSigner + ? ReadonlySignerAccount & + IAccountSignerMeta + : TAccountAuthority +> { + // Program address. + const programAddress = config?.programAddress ?? TOKEN_2022_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + mint: { value: input.mint ?? null, isWritable: true }, + authority: { value: input.authority ?? null, isWritable: false }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + // Original args. + const args = { ...input }; + + // Remaining accounts. + const remainingAccounts: IAccountMeta[] = (args.multiSigners ?? []).map( + (signer) => ({ + address: signer.address, + role: AccountRole.READONLY_SIGNER, + signer, + }) + ); + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [ + getAccountMeta(accounts.mint), + getAccountMeta(accounts.authority), + ...remainingAccounts, + ], + programAddress, + data: getEnableHarvestToMintInstructionDataEncoder().encode({}), + } as EnableHarvestToMintInstruction< + TProgramAddress, + TAccountMint, + (typeof input)['authority'] extends TransactionSigner + ? ReadonlySignerAccount & + IAccountSignerMeta + : TAccountAuthority + >; + + return instruction; +} + +export type ParsedEnableHarvestToMintInstruction< + TProgram extends string = typeof TOKEN_2022_PROGRAM_ADDRESS, + TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], +> = { + programAddress: Address; + accounts: { + /** The token mint. */ + mint: TAccountMetas[0]; + /** The confidential transfer fee authority */ + authority: TAccountMetas[1]; + }; + data: EnableHarvestToMintInstructionData; +}; + +export function parseEnableHarvestToMintInstruction< + TProgram extends string, + TAccountMetas extends readonly IAccountMeta[], +>( + instruction: IInstruction & + IInstructionWithAccounts & + IInstructionWithData +): ParsedEnableHarvestToMintInstruction { + if (instruction.accounts.length < 2) { + // TODO: Coded error. + throw new Error('Not enough accounts'); + } + let accountIndex = 0; + const getNextAccount = () => { + const accountMeta = instruction.accounts![accountIndex]!; + accountIndex += 1; + return accountMeta; + }; + return { + programAddress: instruction.programAddress, + accounts: { + mint: getNextAccount(), + authority: getNextAccount(), + }, + data: getEnableHarvestToMintInstructionDataDecoder().decode( + instruction.data + ), + }; +} diff --git a/clients/js/src/generated/instructions/harvestWithheldTokensToMintForConfidentialTransferFee.ts b/clients/js/src/generated/instructions/harvestWithheldTokensToMintForConfidentialTransferFee.ts new file mode 100644 index 0000000..1fe510c --- /dev/null +++ b/clients/js/src/generated/instructions/harvestWithheldTokensToMintForConfidentialTransferFee.ts @@ -0,0 +1,195 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + AccountRole, + combineCodec, + getStructDecoder, + getStructEncoder, + getU8Decoder, + getU8Encoder, + transformEncoder, + type Address, + type Codec, + type Decoder, + type Encoder, + type IAccountMeta, + type IInstruction, + type IInstructionWithAccounts, + type IInstructionWithData, + type WritableAccount, +} from '@solana/web3.js'; +import { TOKEN_2022_PROGRAM_ADDRESS } from '../programs'; +import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; + +export const HARVEST_WITHHELD_TOKENS_TO_MINT_FOR_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR = 37; + +export function getHarvestWithheldTokensToMintForConfidentialTransferFeeDiscriminatorBytes() { + return getU8Encoder().encode( + HARVEST_WITHHELD_TOKENS_TO_MINT_FOR_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR + ); +} + +export const HARVEST_WITHHELD_TOKENS_TO_MINT_FOR_CONFIDENTIAL_TRANSFER_FEE_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR = 3; + +export function getHarvestWithheldTokensToMintForConfidentialTransferFeeConfidentialTransferFeeDiscriminatorBytes() { + return getU8Encoder().encode( + HARVEST_WITHHELD_TOKENS_TO_MINT_FOR_CONFIDENTIAL_TRANSFER_FEE_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR + ); +} + +export type HarvestWithheldTokensToMintForConfidentialTransferFeeInstruction< + TProgram extends string = typeof TOKEN_2022_PROGRAM_ADDRESS, + TAccountMint extends string | IAccountMeta = string, + TRemainingAccounts extends readonly IAccountMeta[] = [], +> = IInstruction & + IInstructionWithData & + IInstructionWithAccounts< + [ + TAccountMint extends string + ? WritableAccount + : TAccountMint, + ...TRemainingAccounts, + ] + >; + +export type HarvestWithheldTokensToMintForConfidentialTransferFeeInstructionData = + { discriminator: number; confidentialTransferFeeDiscriminator: number }; + +export type HarvestWithheldTokensToMintForConfidentialTransferFeeInstructionDataArgs = + {}; + +export function getHarvestWithheldTokensToMintForConfidentialTransferFeeInstructionDataEncoder(): Encoder { + return transformEncoder( + getStructEncoder([ + ['discriminator', getU8Encoder()], + ['confidentialTransferFeeDiscriminator', getU8Encoder()], + ]), + (value) => ({ + ...value, + discriminator: + HARVEST_WITHHELD_TOKENS_TO_MINT_FOR_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR, + confidentialTransferFeeDiscriminator: + HARVEST_WITHHELD_TOKENS_TO_MINT_FOR_CONFIDENTIAL_TRANSFER_FEE_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR, + }) + ); +} + +export function getHarvestWithheldTokensToMintForConfidentialTransferFeeInstructionDataDecoder(): Decoder { + return getStructDecoder([ + ['discriminator', getU8Decoder()], + ['confidentialTransferFeeDiscriminator', getU8Decoder()], + ]); +} + +export function getHarvestWithheldTokensToMintForConfidentialTransferFeeInstructionDataCodec(): Codec< + HarvestWithheldTokensToMintForConfidentialTransferFeeInstructionDataArgs, + HarvestWithheldTokensToMintForConfidentialTransferFeeInstructionData +> { + return combineCodec( + getHarvestWithheldTokensToMintForConfidentialTransferFeeInstructionDataEncoder(), + getHarvestWithheldTokensToMintForConfidentialTransferFeeInstructionDataDecoder() + ); +} + +export type HarvestWithheldTokensToMintForConfidentialTransferFeeInput< + TAccountMint extends string = string, +> = { + /** The mint. */ + mint: Address; + sources?: Array
; +}; + +export function getHarvestWithheldTokensToMintForConfidentialTransferFeeInstruction< + TAccountMint extends string, + TProgramAddress extends Address = typeof TOKEN_2022_PROGRAM_ADDRESS, +>( + input: HarvestWithheldTokensToMintForConfidentialTransferFeeInput, + config?: { programAddress?: TProgramAddress } +): HarvestWithheldTokensToMintForConfidentialTransferFeeInstruction< + TProgramAddress, + TAccountMint +> { + // Program address. + const programAddress = config?.programAddress ?? TOKEN_2022_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + mint: { value: input.mint ?? null, isWritable: true }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + // Original args. + const args = { ...input }; + + // Remaining accounts. + const remainingAccounts: IAccountMeta[] = (args.sources ?? []).map( + (address) => ({ address, role: AccountRole.WRITABLE }) + ); + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [getAccountMeta(accounts.mint), ...remainingAccounts], + programAddress, + data: getHarvestWithheldTokensToMintForConfidentialTransferFeeInstructionDataEncoder().encode( + {} + ), + } as HarvestWithheldTokensToMintForConfidentialTransferFeeInstruction< + TProgramAddress, + TAccountMint + >; + + return instruction; +} + +export type ParsedHarvestWithheldTokensToMintForConfidentialTransferFeeInstruction< + TProgram extends string = typeof TOKEN_2022_PROGRAM_ADDRESS, + TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], +> = { + programAddress: Address; + accounts: { + /** The mint. */ + mint: TAccountMetas[0]; + }; + data: HarvestWithheldTokensToMintForConfidentialTransferFeeInstructionData; +}; + +export function parseHarvestWithheldTokensToMintForConfidentialTransferFeeInstruction< + TProgram extends string, + TAccountMetas extends readonly IAccountMeta[], +>( + instruction: IInstruction & + IInstructionWithAccounts & + IInstructionWithData +): ParsedHarvestWithheldTokensToMintForConfidentialTransferFeeInstruction< + TProgram, + TAccountMetas +> { + if (instruction.accounts.length < 1) { + // TODO: Coded error. + throw new Error('Not enough accounts'); + } + let accountIndex = 0; + const getNextAccount = () => { + const accountMeta = instruction.accounts![accountIndex]!; + accountIndex += 1; + return accountMeta; + }; + return { + programAddress: instruction.programAddress, + accounts: { + mint: getNextAccount(), + }, + data: getHarvestWithheldTokensToMintForConfidentialTransferFeeInstructionDataDecoder().decode( + instruction.data + ), + }; +} diff --git a/clients/js/src/generated/instructions/index.ts b/clients/js/src/generated/instructions/index.ts index 4c81bb8..1d91fbb 100644 --- a/clients/js/src/generated/instructions/index.ts +++ b/clients/js/src/generated/instructions/index.ts @@ -24,20 +24,24 @@ export * from './createAssociatedTokenIdempotent'; export * from './createNativeMint'; export * from './disableConfidentialCredits'; export * from './disableCpiGuard'; +export * from './disableHarvestToMint'; export * from './disableMemoTransfers'; export * from './disableNonConfidentialCredits'; export * from './emitTokenMetadata'; export * from './emptyConfidentialTransferAccount'; export * from './enableConfidentialCredits'; export * from './enableCpiGuard'; +export * from './enableHarvestToMint'; export * from './enableMemoTransfers'; export * from './enableNonConfidentialCredits'; export * from './freezeAccount'; export * from './getAccountDataSize'; export * from './harvestWithheldTokensToMint'; +export * from './harvestWithheldTokensToMintForConfidentialTransferFee'; export * from './initializeAccount'; export * from './initializeAccount2'; export * from './initializeAccount3'; +export * from './initializeConfidentialTransferFee'; export * from './initializeConfidentialTransferMint'; export * from './initializeDefaultAccountState'; export * from './initializeGroupMemberPointer'; @@ -81,4 +85,6 @@ export * from './updateTokenMetadataField'; export * from './updateTokenMetadataUpdateAuthority'; export * from './updateTransferHook'; export * from './withdrawWithheldTokensFromAccounts'; +export * from './withdrawWithheldTokensFromAccountsForConfidentialTransferFee'; export * from './withdrawWithheldTokensFromMint'; +export * from './withdrawWithheldTokensFromMintForConfidentialTransferFee'; diff --git a/clients/js/src/generated/instructions/initializeConfidentialTransferFee.ts b/clients/js/src/generated/instructions/initializeConfidentialTransferFee.ts new file mode 100644 index 0000000..f4ff65a --- /dev/null +++ b/clients/js/src/generated/instructions/initializeConfidentialTransferFee.ts @@ -0,0 +1,227 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + combineCodec, + getAddressDecoder, + getAddressEncoder, + getOptionDecoder, + getOptionEncoder, + getStructDecoder, + getStructEncoder, + getU8Decoder, + getU8Encoder, + transformEncoder, + type Address, + type Codec, + type Decoder, + type Encoder, + type IAccountMeta, + type IInstruction, + type IInstructionWithAccounts, + type IInstructionWithData, + type Option, + type OptionOrNullable, + type WritableAccount, +} from '@solana/web3.js'; +import { TOKEN_2022_PROGRAM_ADDRESS } from '../programs'; +import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; + +export const INITIALIZE_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR = 37; + +export function getInitializeConfidentialTransferFeeDiscriminatorBytes() { + return getU8Encoder().encode( + INITIALIZE_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR + ); +} + +export const INITIALIZE_CONFIDENTIAL_TRANSFER_FEE_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR = 0; + +export function getInitializeConfidentialTransferFeeConfidentialTransferFeeDiscriminatorBytes() { + return getU8Encoder().encode( + INITIALIZE_CONFIDENTIAL_TRANSFER_FEE_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR + ); +} + +export type InitializeConfidentialTransferFeeInstruction< + TProgram extends string = typeof TOKEN_2022_PROGRAM_ADDRESS, + TAccountMint extends string | IAccountMeta = string, + TRemainingAccounts extends readonly IAccountMeta[] = [], +> = IInstruction & + IInstructionWithData & + IInstructionWithAccounts< + [ + TAccountMint extends string + ? WritableAccount + : TAccountMint, + ...TRemainingAccounts, + ] + >; + +export type InitializeConfidentialTransferFeeInstructionData = { + discriminator: number; + confidentialTransferFeeDiscriminator: number; + /** Optional authority to set the withdraw withheld authority ElGamal key */ + authority: Option
; + /** Withheld fees from accounts must be encrypted with this ElGamal key */ + withdrawWithheldAuthorityElGamalPubkey: Option
; +}; + +export type InitializeConfidentialTransferFeeInstructionDataArgs = { + /** Optional authority to set the withdraw withheld authority ElGamal key */ + authority: OptionOrNullable
; + /** Withheld fees from accounts must be encrypted with this ElGamal key */ + withdrawWithheldAuthorityElGamalPubkey: OptionOrNullable
; +}; + +export function getInitializeConfidentialTransferFeeInstructionDataEncoder(): Encoder { + return transformEncoder( + getStructEncoder([ + ['discriminator', getU8Encoder()], + ['confidentialTransferFeeDiscriminator', getU8Encoder()], + [ + 'authority', + getOptionEncoder(getAddressEncoder(), { + prefix: null, + noneValue: 'zeroes', + }), + ], + [ + 'withdrawWithheldAuthorityElGamalPubkey', + getOptionEncoder(getAddressEncoder(), { + prefix: null, + noneValue: 'zeroes', + }), + ], + ]), + (value) => ({ + ...value, + discriminator: INITIALIZE_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR, + confidentialTransferFeeDiscriminator: + INITIALIZE_CONFIDENTIAL_TRANSFER_FEE_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR, + }) + ); +} + +export function getInitializeConfidentialTransferFeeInstructionDataDecoder(): Decoder { + return getStructDecoder([ + ['discriminator', getU8Decoder()], + ['confidentialTransferFeeDiscriminator', getU8Decoder()], + [ + 'authority', + getOptionDecoder(getAddressDecoder(), { + prefix: null, + noneValue: 'zeroes', + }), + ], + [ + 'withdrawWithheldAuthorityElGamalPubkey', + getOptionDecoder(getAddressDecoder(), { + prefix: null, + noneValue: 'zeroes', + }), + ], + ]); +} + +export function getInitializeConfidentialTransferFeeInstructionDataCodec(): Codec< + InitializeConfidentialTransferFeeInstructionDataArgs, + InitializeConfidentialTransferFeeInstructionData +> { + return combineCodec( + getInitializeConfidentialTransferFeeInstructionDataEncoder(), + getInitializeConfidentialTransferFeeInstructionDataDecoder() + ); +} + +export type InitializeConfidentialTransferFeeInput< + TAccountMint extends string = string, +> = { + /** The SPL Token mint. */ + mint: Address; + authority: InitializeConfidentialTransferFeeInstructionDataArgs['authority']; + withdrawWithheldAuthorityElGamalPubkey: InitializeConfidentialTransferFeeInstructionDataArgs['withdrawWithheldAuthorityElGamalPubkey']; +}; + +export function getInitializeConfidentialTransferFeeInstruction< + TAccountMint extends string, + TProgramAddress extends Address = typeof TOKEN_2022_PROGRAM_ADDRESS, +>( + input: InitializeConfidentialTransferFeeInput, + config?: { programAddress?: TProgramAddress } +): InitializeConfidentialTransferFeeInstruction { + // Program address. + const programAddress = config?.programAddress ?? TOKEN_2022_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + mint: { value: input.mint ?? null, isWritable: true }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + // Original args. + const args = { ...input }; + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [getAccountMeta(accounts.mint)], + programAddress, + data: getInitializeConfidentialTransferFeeInstructionDataEncoder().encode( + args as InitializeConfidentialTransferFeeInstructionDataArgs + ), + } as InitializeConfidentialTransferFeeInstruction< + TProgramAddress, + TAccountMint + >; + + return instruction; +} + +export type ParsedInitializeConfidentialTransferFeeInstruction< + TProgram extends string = typeof TOKEN_2022_PROGRAM_ADDRESS, + TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], +> = { + programAddress: Address; + accounts: { + /** The SPL Token mint. */ + mint: TAccountMetas[0]; + }; + data: InitializeConfidentialTransferFeeInstructionData; +}; + +export function parseInitializeConfidentialTransferFeeInstruction< + TProgram extends string, + TAccountMetas extends readonly IAccountMeta[], +>( + instruction: IInstruction & + IInstructionWithAccounts & + IInstructionWithData +): ParsedInitializeConfidentialTransferFeeInstruction { + if (instruction.accounts.length < 1) { + // TODO: Coded error. + throw new Error('Not enough accounts'); + } + let accountIndex = 0; + const getNextAccount = () => { + const accountMeta = instruction.accounts![accountIndex]!; + accountIndex += 1; + return accountMeta; + }; + return { + programAddress: instruction.programAddress, + accounts: { + mint: getNextAccount(), + }, + data: getInitializeConfidentialTransferFeeInstructionDataDecoder().decode( + instruction.data + ), + }; +} diff --git a/clients/js/src/generated/instructions/withdrawWithheldTokensFromAccountsForConfidentialTransferFee.ts b/clients/js/src/generated/instructions/withdrawWithheldTokensFromAccountsForConfidentialTransferFee.ts new file mode 100644 index 0000000..3c987cc --- /dev/null +++ b/clients/js/src/generated/instructions/withdrawWithheldTokensFromAccountsForConfidentialTransferFee.ts @@ -0,0 +1,322 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + AccountRole, + combineCodec, + getI8Decoder, + getI8Encoder, + getStructDecoder, + getStructEncoder, + getU8Decoder, + getU8Encoder, + transformEncoder, + type Address, + type Codec, + type Decoder, + type Encoder, + type IAccountMeta, + type IAccountSignerMeta, + type IInstruction, + type IInstructionWithAccounts, + type IInstructionWithData, + type ReadonlyAccount, + type ReadonlySignerAccount, + type TransactionSigner, + type WritableAccount, +} from '@solana/web3.js'; +import { TOKEN_2022_PROGRAM_ADDRESS } from '../programs'; +import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; +import { + getDecryptableBalanceDecoder, + getDecryptableBalanceEncoder, + type DecryptableBalance, + type DecryptableBalanceArgs, +} from '../types'; + +export const WITHDRAW_WITHHELD_TOKENS_FROM_ACCOUNTS_FOR_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR = 37; + +export function getWithdrawWithheldTokensFromAccountsForConfidentialTransferFeeDiscriminatorBytes() { + return getU8Encoder().encode( + WITHDRAW_WITHHELD_TOKENS_FROM_ACCOUNTS_FOR_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR + ); +} + +export const WITHDRAW_WITHHELD_TOKENS_FROM_ACCOUNTS_FOR_CONFIDENTIAL_TRANSFER_FEE_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR = 2; + +export function getWithdrawWithheldTokensFromAccountsForConfidentialTransferFeeConfidentialTransferFeeDiscriminatorBytes() { + return getU8Encoder().encode( + WITHDRAW_WITHHELD_TOKENS_FROM_ACCOUNTS_FOR_CONFIDENTIAL_TRANSFER_FEE_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR + ); +} + +export type WithdrawWithheldTokensFromAccountsForConfidentialTransferFeeInstruction< + TProgram extends string = typeof TOKEN_2022_PROGRAM_ADDRESS, + TAccountMint extends string | IAccountMeta = string, + TAccountDestination extends string | IAccountMeta = string, + TAccountInstructionsSysvarOrContextState extends + | string + | IAccountMeta = string, + TAccountRecord extends string | IAccountMeta = string, + TAccountAuthority extends string | IAccountMeta = string, + TRemainingAccounts extends readonly IAccountMeta[] = [], +> = IInstruction & + IInstructionWithData & + IInstructionWithAccounts< + [ + TAccountMint extends string + ? ReadonlyAccount + : TAccountMint, + TAccountDestination extends string + ? WritableAccount + : TAccountDestination, + TAccountInstructionsSysvarOrContextState extends string + ? ReadonlyAccount + : TAccountInstructionsSysvarOrContextState, + TAccountRecord extends string + ? ReadonlyAccount + : TAccountRecord, + TAccountAuthority extends string + ? ReadonlyAccount + : TAccountAuthority, + ...TRemainingAccounts, + ] + >; + +export type WithdrawWithheldTokensFromAccountsForConfidentialTransferFeeInstructionData = + { + discriminator: number; + confidentialTransferFeeDiscriminator: number; + /** Number of token accounts harvested */ + numTokenAccounts: number; + /** Proof instruction offset */ + proofInstructionOffset: number; + /** The new decryptable balance in the destination token account */ + newDecryptableAvailableBalance: DecryptableBalance; + }; + +export type WithdrawWithheldTokensFromAccountsForConfidentialTransferFeeInstructionDataArgs = + { + /** Number of token accounts harvested */ + numTokenAccounts: number; + /** Proof instruction offset */ + proofInstructionOffset: number; + /** The new decryptable balance in the destination token account */ + newDecryptableAvailableBalance: DecryptableBalanceArgs; + }; + +export function getWithdrawWithheldTokensFromAccountsForConfidentialTransferFeeInstructionDataEncoder(): Encoder { + return transformEncoder( + getStructEncoder([ + ['discriminator', getU8Encoder()], + ['confidentialTransferFeeDiscriminator', getU8Encoder()], + ['numTokenAccounts', getU8Encoder()], + ['proofInstructionOffset', getI8Encoder()], + ['newDecryptableAvailableBalance', getDecryptableBalanceEncoder()], + ]), + (value) => ({ + ...value, + discriminator: + WITHDRAW_WITHHELD_TOKENS_FROM_ACCOUNTS_FOR_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR, + confidentialTransferFeeDiscriminator: + WITHDRAW_WITHHELD_TOKENS_FROM_ACCOUNTS_FOR_CONFIDENTIAL_TRANSFER_FEE_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR, + }) + ); +} + +export function getWithdrawWithheldTokensFromAccountsForConfidentialTransferFeeInstructionDataDecoder(): Decoder { + return getStructDecoder([ + ['discriminator', getU8Decoder()], + ['confidentialTransferFeeDiscriminator', getU8Decoder()], + ['numTokenAccounts', getU8Decoder()], + ['proofInstructionOffset', getI8Decoder()], + ['newDecryptableAvailableBalance', getDecryptableBalanceDecoder()], + ]); +} + +export function getWithdrawWithheldTokensFromAccountsForConfidentialTransferFeeInstructionDataCodec(): Codec< + WithdrawWithheldTokensFromAccountsForConfidentialTransferFeeInstructionDataArgs, + WithdrawWithheldTokensFromAccountsForConfidentialTransferFeeInstructionData +> { + return combineCodec( + getWithdrawWithheldTokensFromAccountsForConfidentialTransferFeeInstructionDataEncoder(), + getWithdrawWithheldTokensFromAccountsForConfidentialTransferFeeInstructionDataDecoder() + ); +} + +export type WithdrawWithheldTokensFromAccountsForConfidentialTransferFeeInput< + TAccountMint extends string = string, + TAccountDestination extends string = string, + TAccountInstructionsSysvarOrContextState extends string = string, + TAccountRecord extends string = string, + TAccountAuthority extends string = string, +> = { + /** The token mint. */ + mint: Address; + /** The fee receiver account. */ + destination: Address; + /** Instructions sysvar or context state account */ + instructionsSysvarOrContextState: Address; + /** Optional record account */ + record?: Address; + /** The mint's withdraw_withheld_authority */ + authority: Address | TransactionSigner; + numTokenAccounts: WithdrawWithheldTokensFromAccountsForConfidentialTransferFeeInstructionDataArgs['numTokenAccounts']; + proofInstructionOffset: WithdrawWithheldTokensFromAccountsForConfidentialTransferFeeInstructionDataArgs['proofInstructionOffset']; + newDecryptableAvailableBalance: WithdrawWithheldTokensFromAccountsForConfidentialTransferFeeInstructionDataArgs['newDecryptableAvailableBalance']; + multiSigners?: Array; +}; + +export function getWithdrawWithheldTokensFromAccountsForConfidentialTransferFeeInstruction< + TAccountMint extends string, + TAccountDestination extends string, + TAccountInstructionsSysvarOrContextState extends string, + TAccountRecord extends string, + TAccountAuthority extends string, + TProgramAddress extends Address = typeof TOKEN_2022_PROGRAM_ADDRESS, +>( + input: WithdrawWithheldTokensFromAccountsForConfidentialTransferFeeInput< + TAccountMint, + TAccountDestination, + TAccountInstructionsSysvarOrContextState, + TAccountRecord, + TAccountAuthority + >, + config?: { programAddress?: TProgramAddress } +): WithdrawWithheldTokensFromAccountsForConfidentialTransferFeeInstruction< + TProgramAddress, + TAccountMint, + TAccountDestination, + TAccountInstructionsSysvarOrContextState, + TAccountRecord, + (typeof input)['authority'] extends TransactionSigner + ? ReadonlySignerAccount & + IAccountSignerMeta + : TAccountAuthority +> { + // Program address. + const programAddress = config?.programAddress ?? TOKEN_2022_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + mint: { value: input.mint ?? null, isWritable: false }, + destination: { value: input.destination ?? null, isWritable: true }, + instructionsSysvarOrContextState: { + value: input.instructionsSysvarOrContextState ?? null, + isWritable: false, + }, + record: { value: input.record ?? null, isWritable: false }, + authority: { value: input.authority ?? null, isWritable: false }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + // Original args. + const args = { ...input }; + + // Remaining accounts. + const remainingAccounts: IAccountMeta[] = (args.multiSigners ?? []).map( + (signer) => ({ + address: signer.address, + role: AccountRole.READONLY_SIGNER, + signer, + }) + ); + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [ + getAccountMeta(accounts.mint), + getAccountMeta(accounts.destination), + getAccountMeta(accounts.instructionsSysvarOrContextState), + getAccountMeta(accounts.record), + getAccountMeta(accounts.authority), + ...remainingAccounts, + ], + programAddress, + data: getWithdrawWithheldTokensFromAccountsForConfidentialTransferFeeInstructionDataEncoder().encode( + args as WithdrawWithheldTokensFromAccountsForConfidentialTransferFeeInstructionDataArgs + ), + } as WithdrawWithheldTokensFromAccountsForConfidentialTransferFeeInstruction< + TProgramAddress, + TAccountMint, + TAccountDestination, + TAccountInstructionsSysvarOrContextState, + TAccountRecord, + (typeof input)['authority'] extends TransactionSigner + ? ReadonlySignerAccount & + IAccountSignerMeta + : TAccountAuthority + >; + + return instruction; +} + +export type ParsedWithdrawWithheldTokensFromAccountsForConfidentialTransferFeeInstruction< + TProgram extends string = typeof TOKEN_2022_PROGRAM_ADDRESS, + TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], +> = { + programAddress: Address; + accounts: { + /** The token mint. */ + mint: TAccountMetas[0]; + /** The fee receiver account. */ + destination: TAccountMetas[1]; + /** Instructions sysvar or context state account */ + instructionsSysvarOrContextState: TAccountMetas[2]; + /** Optional record account */ + record?: TAccountMetas[3] | undefined; + /** The mint's withdraw_withheld_authority */ + authority: TAccountMetas[4]; + }; + data: WithdrawWithheldTokensFromAccountsForConfidentialTransferFeeInstructionData; +}; + +export function parseWithdrawWithheldTokensFromAccountsForConfidentialTransferFeeInstruction< + TProgram extends string, + TAccountMetas extends readonly IAccountMeta[], +>( + instruction: IInstruction & + IInstructionWithAccounts & + IInstructionWithData +): ParsedWithdrawWithheldTokensFromAccountsForConfidentialTransferFeeInstruction< + TProgram, + TAccountMetas +> { + if (instruction.accounts.length < 5) { + // TODO: Coded error. + throw new Error('Not enough accounts'); + } + let accountIndex = 0; + const getNextAccount = () => { + const accountMeta = instruction.accounts![accountIndex]!; + accountIndex += 1; + return accountMeta; + }; + const getNextOptionalAccount = () => { + const accountMeta = getNextAccount(); + return accountMeta.address === TOKEN_2022_PROGRAM_ADDRESS + ? undefined + : accountMeta; + }; + return { + programAddress: instruction.programAddress, + accounts: { + mint: getNextAccount(), + destination: getNextAccount(), + instructionsSysvarOrContextState: getNextAccount(), + record: getNextOptionalAccount(), + authority: getNextAccount(), + }, + data: getWithdrawWithheldTokensFromAccountsForConfidentialTransferFeeInstructionDataDecoder().decode( + instruction.data + ), + }; +} diff --git a/clients/js/src/generated/instructions/withdrawWithheldTokensFromMintForConfidentialTransferFee.ts b/clients/js/src/generated/instructions/withdrawWithheldTokensFromMintForConfidentialTransferFee.ts new file mode 100644 index 0000000..b28aeb2 --- /dev/null +++ b/clients/js/src/generated/instructions/withdrawWithheldTokensFromMintForConfidentialTransferFee.ts @@ -0,0 +1,315 @@ +/** + * This code was AUTOGENERATED using the codama library. + * Please DO NOT EDIT THIS FILE, instead use visitors + * to add features, then rerun codama to update it. + * + * @see https://github.com/codama-idl/codama + */ + +import { + AccountRole, + combineCodec, + getI8Decoder, + getI8Encoder, + getStructDecoder, + getStructEncoder, + getU8Decoder, + getU8Encoder, + transformEncoder, + type Address, + type Codec, + type Decoder, + type Encoder, + type IAccountMeta, + type IAccountSignerMeta, + type IInstruction, + type IInstructionWithAccounts, + type IInstructionWithData, + type ReadonlyAccount, + type ReadonlySignerAccount, + type TransactionSigner, + type WritableAccount, +} from '@solana/web3.js'; +import { TOKEN_2022_PROGRAM_ADDRESS } from '../programs'; +import { getAccountMetaFactory, type ResolvedAccount } from '../shared'; +import { + getDecryptableBalanceDecoder, + getDecryptableBalanceEncoder, + type DecryptableBalance, + type DecryptableBalanceArgs, +} from '../types'; + +export const WITHDRAW_WITHHELD_TOKENS_FROM_MINT_FOR_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR = 37; + +export function getWithdrawWithheldTokensFromMintForConfidentialTransferFeeDiscriminatorBytes() { + return getU8Encoder().encode( + WITHDRAW_WITHHELD_TOKENS_FROM_MINT_FOR_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR + ); +} + +export const WITHDRAW_WITHHELD_TOKENS_FROM_MINT_FOR_CONFIDENTIAL_TRANSFER_FEE_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR = 1; + +export function getWithdrawWithheldTokensFromMintForConfidentialTransferFeeConfidentialTransferFeeDiscriminatorBytes() { + return getU8Encoder().encode( + WITHDRAW_WITHHELD_TOKENS_FROM_MINT_FOR_CONFIDENTIAL_TRANSFER_FEE_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR + ); +} + +export type WithdrawWithheldTokensFromMintForConfidentialTransferFeeInstruction< + TProgram extends string = typeof TOKEN_2022_PROGRAM_ADDRESS, + TAccountMint extends string | IAccountMeta = string, + TAccountDestination extends string | IAccountMeta = string, + TAccountInstructionsSysvarOrContextState extends + | string + | IAccountMeta = string, + TAccountRecord extends string | IAccountMeta = string, + TAccountAuthority extends string | IAccountMeta = string, + TRemainingAccounts extends readonly IAccountMeta[] = [], +> = IInstruction & + IInstructionWithData & + IInstructionWithAccounts< + [ + TAccountMint extends string + ? WritableAccount + : TAccountMint, + TAccountDestination extends string + ? WritableAccount + : TAccountDestination, + TAccountInstructionsSysvarOrContextState extends string + ? ReadonlyAccount + : TAccountInstructionsSysvarOrContextState, + TAccountRecord extends string + ? ReadonlyAccount + : TAccountRecord, + TAccountAuthority extends string + ? ReadonlyAccount + : TAccountAuthority, + ...TRemainingAccounts, + ] + >; + +export type WithdrawWithheldTokensFromMintForConfidentialTransferFeeInstructionData = + { + discriminator: number; + confidentialTransferFeeDiscriminator: number; + /** Proof instruction offset */ + proofInstructionOffset: number; + /** The new decryptable balance in the destination token account */ + newDecryptableAvailableBalance: DecryptableBalance; + }; + +export type WithdrawWithheldTokensFromMintForConfidentialTransferFeeInstructionDataArgs = + { + /** Proof instruction offset */ + proofInstructionOffset: number; + /** The new decryptable balance in the destination token account */ + newDecryptableAvailableBalance: DecryptableBalanceArgs; + }; + +export function getWithdrawWithheldTokensFromMintForConfidentialTransferFeeInstructionDataEncoder(): Encoder { + return transformEncoder( + getStructEncoder([ + ['discriminator', getU8Encoder()], + ['confidentialTransferFeeDiscriminator', getU8Encoder()], + ['proofInstructionOffset', getI8Encoder()], + ['newDecryptableAvailableBalance', getDecryptableBalanceEncoder()], + ]), + (value) => ({ + ...value, + discriminator: + WITHDRAW_WITHHELD_TOKENS_FROM_MINT_FOR_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR, + confidentialTransferFeeDiscriminator: + WITHDRAW_WITHHELD_TOKENS_FROM_MINT_FOR_CONFIDENTIAL_TRANSFER_FEE_CONFIDENTIAL_TRANSFER_FEE_DISCRIMINATOR, + }) + ); +} + +export function getWithdrawWithheldTokensFromMintForConfidentialTransferFeeInstructionDataDecoder(): Decoder { + return getStructDecoder([ + ['discriminator', getU8Decoder()], + ['confidentialTransferFeeDiscriminator', getU8Decoder()], + ['proofInstructionOffset', getI8Decoder()], + ['newDecryptableAvailableBalance', getDecryptableBalanceDecoder()], + ]); +} + +export function getWithdrawWithheldTokensFromMintForConfidentialTransferFeeInstructionDataCodec(): Codec< + WithdrawWithheldTokensFromMintForConfidentialTransferFeeInstructionDataArgs, + WithdrawWithheldTokensFromMintForConfidentialTransferFeeInstructionData +> { + return combineCodec( + getWithdrawWithheldTokensFromMintForConfidentialTransferFeeInstructionDataEncoder(), + getWithdrawWithheldTokensFromMintForConfidentialTransferFeeInstructionDataDecoder() + ); +} + +export type WithdrawWithheldTokensFromMintForConfidentialTransferFeeInput< + TAccountMint extends string = string, + TAccountDestination extends string = string, + TAccountInstructionsSysvarOrContextState extends string = string, + TAccountRecord extends string = string, + TAccountAuthority extends string = string, +> = { + /** The token mint. */ + mint: Address; + /** The fee receiver account. */ + destination: Address; + /** Instructions sysvar or context state account */ + instructionsSysvarOrContextState: Address; + /** Optional record account if proof is read from record */ + record?: Address; + /** The mint's withdraw_withheld_authority */ + authority: Address | TransactionSigner; + proofInstructionOffset: WithdrawWithheldTokensFromMintForConfidentialTransferFeeInstructionDataArgs['proofInstructionOffset']; + newDecryptableAvailableBalance: WithdrawWithheldTokensFromMintForConfidentialTransferFeeInstructionDataArgs['newDecryptableAvailableBalance']; + multiSigners?: Array; +}; + +export function getWithdrawWithheldTokensFromMintForConfidentialTransferFeeInstruction< + TAccountMint extends string, + TAccountDestination extends string, + TAccountInstructionsSysvarOrContextState extends string, + TAccountRecord extends string, + TAccountAuthority extends string, + TProgramAddress extends Address = typeof TOKEN_2022_PROGRAM_ADDRESS, +>( + input: WithdrawWithheldTokensFromMintForConfidentialTransferFeeInput< + TAccountMint, + TAccountDestination, + TAccountInstructionsSysvarOrContextState, + TAccountRecord, + TAccountAuthority + >, + config?: { programAddress?: TProgramAddress } +): WithdrawWithheldTokensFromMintForConfidentialTransferFeeInstruction< + TProgramAddress, + TAccountMint, + TAccountDestination, + TAccountInstructionsSysvarOrContextState, + TAccountRecord, + (typeof input)['authority'] extends TransactionSigner + ? ReadonlySignerAccount & + IAccountSignerMeta + : TAccountAuthority +> { + // Program address. + const programAddress = config?.programAddress ?? TOKEN_2022_PROGRAM_ADDRESS; + + // Original accounts. + const originalAccounts = { + mint: { value: input.mint ?? null, isWritable: true }, + destination: { value: input.destination ?? null, isWritable: true }, + instructionsSysvarOrContextState: { + value: input.instructionsSysvarOrContextState ?? null, + isWritable: false, + }, + record: { value: input.record ?? null, isWritable: false }, + authority: { value: input.authority ?? null, isWritable: false }, + }; + const accounts = originalAccounts as Record< + keyof typeof originalAccounts, + ResolvedAccount + >; + + // Original args. + const args = { ...input }; + + // Remaining accounts. + const remainingAccounts: IAccountMeta[] = (args.multiSigners ?? []).map( + (signer) => ({ + address: signer.address, + role: AccountRole.READONLY_SIGNER, + signer, + }) + ); + + const getAccountMeta = getAccountMetaFactory(programAddress, 'programId'); + const instruction = { + accounts: [ + getAccountMeta(accounts.mint), + getAccountMeta(accounts.destination), + getAccountMeta(accounts.instructionsSysvarOrContextState), + getAccountMeta(accounts.record), + getAccountMeta(accounts.authority), + ...remainingAccounts, + ], + programAddress, + data: getWithdrawWithheldTokensFromMintForConfidentialTransferFeeInstructionDataEncoder().encode( + args as WithdrawWithheldTokensFromMintForConfidentialTransferFeeInstructionDataArgs + ), + } as WithdrawWithheldTokensFromMintForConfidentialTransferFeeInstruction< + TProgramAddress, + TAccountMint, + TAccountDestination, + TAccountInstructionsSysvarOrContextState, + TAccountRecord, + (typeof input)['authority'] extends TransactionSigner + ? ReadonlySignerAccount & + IAccountSignerMeta + : TAccountAuthority + >; + + return instruction; +} + +export type ParsedWithdrawWithheldTokensFromMintForConfidentialTransferFeeInstruction< + TProgram extends string = typeof TOKEN_2022_PROGRAM_ADDRESS, + TAccountMetas extends readonly IAccountMeta[] = readonly IAccountMeta[], +> = { + programAddress: Address; + accounts: { + /** The token mint. */ + mint: TAccountMetas[0]; + /** The fee receiver account. */ + destination: TAccountMetas[1]; + /** Instructions sysvar or context state account */ + instructionsSysvarOrContextState: TAccountMetas[2]; + /** Optional record account if proof is read from record */ + record?: TAccountMetas[3] | undefined; + /** The mint's withdraw_withheld_authority */ + authority: TAccountMetas[4]; + }; + data: WithdrawWithheldTokensFromMintForConfidentialTransferFeeInstructionData; +}; + +export function parseWithdrawWithheldTokensFromMintForConfidentialTransferFeeInstruction< + TProgram extends string, + TAccountMetas extends readonly IAccountMeta[], +>( + instruction: IInstruction & + IInstructionWithAccounts & + IInstructionWithData +): ParsedWithdrawWithheldTokensFromMintForConfidentialTransferFeeInstruction< + TProgram, + TAccountMetas +> { + if (instruction.accounts.length < 5) { + // TODO: Coded error. + throw new Error('Not enough accounts'); + } + let accountIndex = 0; + const getNextAccount = () => { + const accountMeta = instruction.accounts![accountIndex]!; + accountIndex += 1; + return accountMeta; + }; + const getNextOptionalAccount = () => { + const accountMeta = getNextAccount(); + return accountMeta.address === TOKEN_2022_PROGRAM_ADDRESS + ? undefined + : accountMeta; + }; + return { + programAddress: instruction.programAddress, + accounts: { + mint: getNextAccount(), + destination: getNextAccount(), + instructionsSysvarOrContextState: getNextAccount(), + record: getNextOptionalAccount(), + authority: getNextAccount(), + }, + data: getWithdrawWithheldTokensFromMintForConfidentialTransferFeeInstructionDataDecoder().decode( + instruction.data + ), + }; +} diff --git a/clients/js/src/generated/programs/token2022.ts b/clients/js/src/generated/programs/token2022.ts index 08e3c5f..66de187 100644 --- a/clients/js/src/generated/programs/token2022.ts +++ b/clients/js/src/generated/programs/token2022.ts @@ -29,20 +29,24 @@ import { type ParsedCreateNativeMintInstruction, type ParsedDisableConfidentialCreditsInstruction, type ParsedDisableCpiGuardInstruction, + type ParsedDisableHarvestToMintInstruction, type ParsedDisableMemoTransfersInstruction, type ParsedDisableNonConfidentialCreditsInstruction, type ParsedEmitTokenMetadataInstruction, type ParsedEmptyConfidentialTransferAccountInstruction, type ParsedEnableConfidentialCreditsInstruction, type ParsedEnableCpiGuardInstruction, + type ParsedEnableHarvestToMintInstruction, type ParsedEnableMemoTransfersInstruction, type ParsedEnableNonConfidentialCreditsInstruction, type ParsedFreezeAccountInstruction, type ParsedGetAccountDataSizeInstruction, + type ParsedHarvestWithheldTokensToMintForConfidentialTransferFeeInstruction, type ParsedHarvestWithheldTokensToMintInstruction, type ParsedInitializeAccount2Instruction, type ParsedInitializeAccount3Instruction, type ParsedInitializeAccountInstruction, + type ParsedInitializeConfidentialTransferFeeInstruction, type ParsedInitializeConfidentialTransferMintInstruction, type ParsedInitializeDefaultAccountStateInstruction, type ParsedInitializeGroupMemberPointerInstruction, @@ -84,7 +88,9 @@ import { type ParsedUpdateTokenMetadataFieldInstruction, type ParsedUpdateTokenMetadataUpdateAuthorityInstruction, type ParsedUpdateTransferHookInstruction, + type ParsedWithdrawWithheldTokensFromAccountsForConfidentialTransferFeeInstruction, type ParsedWithdrawWithheldTokensFromAccountsInstruction, + type ParsedWithdrawWithheldTokensFromMintForConfidentialTransferFeeInstruction, type ParsedWithdrawWithheldTokensFromMintInstruction, } from '../instructions'; @@ -174,6 +180,12 @@ export enum Token2022Instruction { InitializePermanentDelegate, InitializeTransferHook, UpdateTransferHook, + InitializeConfidentialTransferFee, + WithdrawWithheldTokensFromMintForConfidentialTransferFee, + WithdrawWithheldTokensFromAccountsForConfidentialTransferFee, + HarvestWithheldTokensToMintForConfidentialTransferFee, + EnableHarvestToMint, + DisableHarvestToMint, InitializeMetadataPointer, UpdateMetadataPointer, InitializeGroupPointer, @@ -453,6 +465,42 @@ export function identifyToken2022Instruction( ) { return Token2022Instruction.UpdateTransferHook; } + if ( + containsBytes(data, getU8Encoder().encode(37), 0) && + containsBytes(data, getU8Encoder().encode(0), 1) + ) { + return Token2022Instruction.InitializeConfidentialTransferFee; + } + if ( + containsBytes(data, getU8Encoder().encode(37), 0) && + containsBytes(data, getU8Encoder().encode(1), 1) + ) { + return Token2022Instruction.WithdrawWithheldTokensFromMintForConfidentialTransferFee; + } + if ( + containsBytes(data, getU8Encoder().encode(37), 0) && + containsBytes(data, getU8Encoder().encode(2), 1) + ) { + return Token2022Instruction.WithdrawWithheldTokensFromAccountsForConfidentialTransferFee; + } + if ( + containsBytes(data, getU8Encoder().encode(37), 0) && + containsBytes(data, getU8Encoder().encode(3), 1) + ) { + return Token2022Instruction.HarvestWithheldTokensToMintForConfidentialTransferFee; + } + if ( + containsBytes(data, getU8Encoder().encode(37), 0) && + containsBytes(data, getU8Encoder().encode(4), 1) + ) { + return Token2022Instruction.EnableHarvestToMint; + } + if ( + containsBytes(data, getU8Encoder().encode(37), 0) && + containsBytes(data, getU8Encoder().encode(5), 1) + ) { + return Token2022Instruction.DisableHarvestToMint; + } if ( containsBytes(data, getU8Encoder().encode(39), 0) && containsBytes(data, getU8Encoder().encode(0), 1) @@ -744,6 +792,24 @@ export type ParsedToken2022Instruction< | ({ instructionType: Token2022Instruction.UpdateTransferHook; } & ParsedUpdateTransferHookInstruction) + | ({ + instructionType: Token2022Instruction.InitializeConfidentialTransferFee; + } & ParsedInitializeConfidentialTransferFeeInstruction) + | ({ + instructionType: Token2022Instruction.WithdrawWithheldTokensFromMintForConfidentialTransferFee; + } & ParsedWithdrawWithheldTokensFromMintForConfidentialTransferFeeInstruction) + | ({ + instructionType: Token2022Instruction.WithdrawWithheldTokensFromAccountsForConfidentialTransferFee; + } & ParsedWithdrawWithheldTokensFromAccountsForConfidentialTransferFeeInstruction) + | ({ + instructionType: Token2022Instruction.HarvestWithheldTokensToMintForConfidentialTransferFee; + } & ParsedHarvestWithheldTokensToMintForConfidentialTransferFeeInstruction) + | ({ + instructionType: Token2022Instruction.EnableHarvestToMint; + } & ParsedEnableHarvestToMintInstruction) + | ({ + instructionType: Token2022Instruction.DisableHarvestToMint; + } & ParsedDisableHarvestToMintInstruction) | ({ instructionType: Token2022Instruction.InitializeMetadataPointer; } & ParsedInitializeMetadataPointerInstruction) diff --git a/clients/js/src/getInitializeInstructionsForExtensions.ts b/clients/js/src/getInitializeInstructionsForExtensions.ts index 4791e4a..af260d1 100644 --- a/clients/js/src/getInitializeInstructionsForExtensions.ts +++ b/clients/js/src/getInitializeInstructionsForExtensions.ts @@ -23,6 +23,7 @@ import { getInitializeNonTransferableMintInstruction, getInitializeTransferHookInstruction, getInitializePermanentDelegateInstruction, + getInitializeConfidentialTransferFeeInstruction, } from './generated'; /** @@ -100,6 +101,14 @@ export function getPreInitializeInstructionsForMintExtensions( mint, delegate: extension.delegate, }); + case 'ConfidentialTransferFee': + return [ + getInitializeConfidentialTransferFeeInstruction({ + mint, + authority: extension.authority, + withdrawWithheldAuthorityElGamalPubkey: extension.elgamalPubkey, + }), + ]; default: return []; } diff --git a/clients/js/test/extensions/confidentialTransferFee/initializeConfidentialTransferFee.test.ts b/clients/js/test/extensions/confidentialTransferFee/initializeConfidentialTransferFee.test.ts new file mode 100644 index 0000000..3620600 --- /dev/null +++ b/clients/js/test/extensions/confidentialTransferFee/initializeConfidentialTransferFee.test.ts @@ -0,0 +1,126 @@ +import { Account, address, generateKeyPairSigner, some } from '@solana/web3.js'; +import test from 'ava'; +import { + Mint, + extension, + fetchMint, + getInitializeConfidentialTransferFeeInstruction, + getInitializeTransferFeeConfigInstruction, + getInitializeConfidentialTransferMintInstruction, +} from '../../../src'; +import { + createDefaultSolanaClient, + generateKeyPairSignerWithSol, + getCreateMintInstructions, + sendAndConfirmInstructions, +} from '../../_setup'; + +test('it initializes a mint with confidential transfer fee', async (t) => { + // Given an authority and a mint account. + const client = createDefaultSolanaClient(); + const [authority, mint] = await Promise.all([ + generateKeyPairSignerWithSol(client), + generateKeyPairSigner(), + ]); + + // And required extensions configuration + const confidentialTransferAuthority = address( + '6sPR6MzvjMMP5LSZzEtTe4ZBVX9rhBmtM1dmfFtkNTbW' + ); + const elgamalPubkey = address('BTNEPmmWuj7Sg4Fo5i1FC5eiV2Aj4jiv9boarvE5XeaX'); + + // TransferFeeConfig extension + const transferFeeConfigExtension = extension('TransferFeeConfig', { + transferFeeConfigAuthority: confidentialTransferAuthority, + withdrawWithheldAuthority: confidentialTransferAuthority, + withheldAmount: 0n, + olderTransferFee: { + epoch: 0n, + maximumFee: 0n, + transferFeeBasisPoints: 0, + }, + newerTransferFee: { + epoch: 0n, + maximumFee: 0n, + transferFeeBasisPoints: 0, + }, + }); + + // ConfidentialTransferMint extension + const confidentialTransferMintExtension = extension( + 'ConfidentialTransferMint', + { + authority: some(confidentialTransferAuthority), + autoApproveNewAccounts: true, + auditorElgamalPubkey: some(elgamalPubkey), + } + ); + + // ConfidentialTransferFee extension + const confidentialTransferFeeExtension = extension( + 'ConfidentialTransferFee', + { + authority: some(confidentialTransferAuthority), + elgamalPubkey, + harvestToMintEnabled: true, + withheldAmount: new Uint8Array(64).fill(0), + } + ); + + // When we create and initialize a mint account with these extensions. + const [createMintInstruction, initMintInstruction] = + await getCreateMintInstructions({ + authority: authority.address, + client, + decimals: 2, + extensions: [ + transferFeeConfigExtension, + confidentialTransferMintExtension, + confidentialTransferFeeExtension, + ], + mint, + payer: authority, + }); + + await sendAndConfirmInstructions(client, authority, [ + createMintInstruction, + // Initialize TransferFeeConfig first + getInitializeTransferFeeConfigInstruction({ + mint: mint.address, + transferFeeConfigAuthority: confidentialTransferAuthority, + withdrawWithheldAuthority: confidentialTransferAuthority, + transferFeeBasisPoints: 0, + maximumFee: 0n, + }), + // Then initialize ConfidentialTransferMint + getInitializeConfidentialTransferMintInstruction({ + mint: mint.address, + authority: some(confidentialTransferAuthority), + autoApproveNewAccounts: true, + auditorElgamalPubkey: some(elgamalPubkey), + }), + // Finally initialize ConfidentialTransferFee + getInitializeConfidentialTransferFeeInstruction({ + mint: mint.address, + authority: some(confidentialTransferAuthority), + withdrawWithheldAuthorityElGamalPubkey: some(elgamalPubkey), + }), + initMintInstruction, + ]); + + // Then we expect the mint account to exist and have all extensions. + const mintAccount = await fetchMint(client.rpc, mint.address); + t.like(mintAccount, >{ + address: mint.address, + data: { + mintAuthority: some(authority.address), + decimals: 2, + isInitialized: true, + extensions: some([ + transferFeeConfigExtension, + confidentialTransferMintExtension, + confidentialTransferFeeExtension, + ]), + }, + }); +}); diff --git a/program/idl.json b/program/idl.json index 119248b..9ccccc8 100644 --- a/program/idl.json +++ b/program/idl.json @@ -5881,6 +5881,618 @@ } ] }, + { + "kind": "instructionNode", + "name": "initializeConfidentialTransferFee", + "docs": [ + "Initializes confidential transfer fees for a mint.", + "", + "The instruction must be included within the same Transaction as TokenInstruction::InitializeMint.", + "Otherwise another party can initialize the configuration.", + "", + "The instruction fails if TokenInstruction::InitializeMint has already executed for the mint." + ], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "mint", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": ["The SPL Token mint."] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 37 + } + }, + { + "kind": "instructionArgumentNode", + "name": "confidentialTransferFeeDiscriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 0 + } + }, + { + "kind": "instructionArgumentNode", + "name": "authority", + "docs": [ + "Optional authority to set the withdraw withheld authority ElGamal key" + ], + "type": { + "kind": "zeroableOptionTypeNode", + "item": { + "kind": "publicKeyTypeNode" + } + } + }, + { + "kind": "instructionArgumentNode", + "name": "withdrawWithheldAuthorityElGamalPubkey", + "docs": [ + "Withheld fees from accounts must be encrypted with this ElGamal key" + ], + "type": { + "kind": "zeroableOptionTypeNode", + "item": { + "kind": "publicKeyTypeNode" + } + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + }, + { + "kind": "fieldDiscriminatorNode", + "name": "confidentialTransferFeeDiscriminator", + "offset": 1 + } + ] + }, + { + "kind": "instructionNode", + "name": "withdrawWithheldTokensFromMintForConfidentialTransferFee", + "docs": [ + "Transfer all withheld confidential tokens in the mint to an account.", + "Signed by the mint's withdraw withheld tokens authority.", + "", + "The withheld confidential tokens are aggregated directly into the destination available balance.", + "", + "Must be accompanied by the VerifyCiphertextCiphertextEquality instruction", + "of the zk_elgamal_proof program in the same transaction or the address of", + "a context state account for the proof must be provided." + ], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "mint", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": ["The token mint."] + }, + { + "kind": "instructionAccountNode", + "name": "destination", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": ["The fee receiver account."] + }, + { + "kind": "instructionAccountNode", + "name": "instructionsSysvarOrContextState", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": ["Instructions sysvar or context state account"] + }, + { + "kind": "instructionAccountNode", + "name": "record", + "isWritable": false, + "isSigner": false, + "isOptional": true, + "docs": ["Optional record account if proof is read from record"] + }, + { + "kind": "instructionAccountNode", + "name": "authority", + "isWritable": false, + "isSigner": "either", + "isOptional": false, + "docs": ["The mint's withdraw_withheld_authority"] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 37 + } + }, + { + "kind": "instructionArgumentNode", + "name": "confidentialTransferFeeDiscriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 1 + } + }, + { + "kind": "instructionArgumentNode", + "name": "proofInstructionOffset", + "docs": ["Proof instruction offset"], + "type": { + "kind": "numberTypeNode", + "format": "i8", + "endian": "le" + } + }, + { + "kind": "instructionArgumentNode", + "name": "newDecryptableAvailableBalance", + "docs": [ + "The new decryptable balance in the destination token account" + ], + "type": { + "kind": "definedTypeLinkNode", + "name": "decryptableBalance" + } + } + ], + "remainingAccounts": [ + { + "kind": "instructionRemainingAccountsNode", + "isOptional": true, + "isSigner": true, + "docs": [], + "value": { + "kind": "argumentValueNode", + "name": "multiSigners" + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + }, + { + "kind": "fieldDiscriminatorNode", + "name": "confidentialTransferFeeDiscriminator", + "offset": 1 + } + ] + }, + { + "kind": "instructionNode", + "name": "withdrawWithheldTokensFromAccountsForConfidentialTransferFee", + "docs": [ + "Transfer all withheld tokens to an account. Signed by the mint's withdraw withheld", + "tokens authority. This instruction is susceptible to front-running.", + "Use `HarvestWithheldTokensToMint` and `WithdrawWithheldTokensFromMint` as alternative.", + "", + "Must be accompanied by the VerifyWithdrawWithheldTokens instruction." + ], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "mint", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": ["The token mint."] + }, + { + "kind": "instructionAccountNode", + "name": "destination", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": ["The fee receiver account."] + }, + { + "kind": "instructionAccountNode", + "name": "instructionsSysvarOrContextState", + "isWritable": false, + "isSigner": false, + "isOptional": false, + "docs": ["Instructions sysvar or context state account"] + }, + { + "kind": "instructionAccountNode", + "name": "record", + "isWritable": false, + "isSigner": false, + "isOptional": true, + "docs": ["Optional record account"] + }, + { + "kind": "instructionAccountNode", + "name": "authority", + "isWritable": false, + "isSigner": "either", + "isOptional": false, + "docs": ["The mint's withdraw_withheld_authority"] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 37 + } + }, + { + "kind": "instructionArgumentNode", + "name": "confidentialTransferFeeDiscriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 2 + } + }, + { + "kind": "instructionArgumentNode", + "name": "numTokenAccounts", + "docs": ["Number of token accounts harvested"], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + } + }, + { + "kind": "instructionArgumentNode", + "name": "proofInstructionOffset", + "docs": ["Proof instruction offset"], + "type": { + "kind": "numberTypeNode", + "format": "i8", + "endian": "le" + } + }, + { + "kind": "instructionArgumentNode", + "name": "newDecryptableAvailableBalance", + "docs": [ + "The new decryptable balance in the destination token account" + ], + "type": { + "kind": "definedTypeLinkNode", + "name": "decryptableBalance" + } + } + ], + "remainingAccounts": [ + { + "kind": "instructionRemainingAccountsNode", + "isOptional": true, + "isSigner": true, + "docs": [], + "value": { + "kind": "argumentValueNode", + "name": "multiSigners" + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + }, + { + "kind": "fieldDiscriminatorNode", + "name": "confidentialTransferFeeDiscriminator", + "offset": 1 + } + ] + }, + { + "kind": "instructionNode", + "name": "harvestWithheldTokensToMintForConfidentialTransferFee", + "docs": [ + "Permissionless instruction to transfer all withheld confidential tokens to the mint.", + "", + "Succeeds for frozen accounts.", + "", + "Accounts provided should include both the `TransferFeeAmount` and", + "`ConfidentialTransferAccount` extension. If not, the account is skipped." + ], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "mint", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": ["The mint."] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 37 + } + }, + { + "kind": "instructionArgumentNode", + "name": "confidentialTransferFeeDiscriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 3 + } + } + ], + "remainingAccounts": [ + { + "kind": "instructionRemainingAccountsNode", + "isOptional": true, + "isSigner": false, + "isWritable": true, + "docs": ["The source accounts to harvest from"], + "value": { + "kind": "argumentValueNode", + "name": "sources" + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + }, + { + "kind": "fieldDiscriminatorNode", + "name": "confidentialTransferFeeDiscriminator", + "offset": 1 + } + ] + }, + { + "kind": "instructionNode", + "name": "enableHarvestToMint", + "docs": [ + "Configure a confidential transfer fee mint to accept harvested confidential fees." + ], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "mint", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": ["The token mint."] + }, + { + "kind": "instructionAccountNode", + "name": "authority", + "isWritable": false, + "isSigner": "either", + "isOptional": false, + "docs": ["The confidential transfer fee authority"] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 37 + } + }, + { + "kind": "instructionArgumentNode", + "name": "confidentialTransferFeeDiscriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 4 + } + } + ], + "remainingAccounts": [ + { + "kind": "instructionRemainingAccountsNode", + "isOptional": true, + "isSigner": true, + "docs": [], + "value": { + "kind": "argumentValueNode", + "name": "multiSigners" + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + }, + { + "kind": "fieldDiscriminatorNode", + "name": "confidentialTransferFeeDiscriminator", + "offset": 1 + } + ] + }, + { + "kind": "instructionNode", + "name": "disableHarvestToMint", + "docs": [ + "Configure a confidential transfer fee mint to reject any harvested confidential fees." + ], + "optionalAccountStrategy": "programId", + "accounts": [ + { + "kind": "instructionAccountNode", + "name": "mint", + "isWritable": true, + "isSigner": false, + "isOptional": false, + "docs": ["The token mint."] + }, + { + "kind": "instructionAccountNode", + "name": "authority", + "isWritable": false, + "isSigner": "either", + "isOptional": false, + "docs": ["The confidential transfer fee authority"] + } + ], + "arguments": [ + { + "kind": "instructionArgumentNode", + "name": "discriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 37 + } + }, + { + "kind": "instructionArgumentNode", + "name": "confidentialTransferFeeDiscriminator", + "defaultValueStrategy": "omitted", + "docs": [], + "type": { + "kind": "numberTypeNode", + "format": "u8", + "endian": "le" + }, + "defaultValue": { + "kind": "numberValueNode", + "number": 5 + } + } + ], + "remainingAccounts": [ + { + "kind": "instructionRemainingAccountsNode", + "isOptional": true, + "isSigner": true, + "docs": [], + "value": { + "kind": "argumentValueNode", + "name": "multiSigners" + } + } + ], + "discriminators": [ + { + "kind": "fieldDiscriminatorNode", + "name": "discriminator", + "offset": 0 + }, + { + "kind": "fieldDiscriminatorNode", + "name": "confidentialTransferFeeDiscriminator", + "offset": 1 + } + ] + }, { "kind": "instructionNode", "name": "initializeMetadataPointer",