/** * 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, getStructDecoder, getStructEncoder, getU64Decoder, getU64Encoder, getU8Decoder, getU8Encoder, SOLANA_ERROR__PROGRAM_CLIENTS__INSUFFICIENT_ACCOUNT_METAS, SolanaError, transformEncoder, type AccountMeta, type AccountSignerMeta, type Address, type FixedSizeCodec, type FixedSizeDecoder, type FixedSizeEncoder, type Instruction, type InstructionWithAccounts, type InstructionWithData, type ReadonlyAccount, type ReadonlySignerAccount, type ReadonlyUint8Array, type TransactionSigner, type WritableAccount, } from "@solana/kit"; import { getAccountMetaFactory, getAddressFromResolvedInstructionAccount, type ResolvedInstructionAccount, } from "@solana/program-client-core"; import { findWithdrawAuthorityPda } from "../pdas/index.ts"; import { SPL_STAKE_POOL_PROGRAM_ADDRESS } from "../programs/index.ts"; export const WITHDRAW_STAKE_DISCRIMINATOR = 10; export function getWithdrawStakeDiscriminatorBytes(): ReadonlyUint8Array { return getU8Encoder().encode(WITHDRAW_STAKE_DISCRIMINATOR); } export type WithdrawStakeInstruction< TProgram extends string = typeof SPL_STAKE_POOL_PROGRAM_ADDRESS, TAccountStakePool extends string | AccountMeta = string, TAccountValidatorList extends string | AccountMeta = string, TAccountWithdrawAuthority extends string | AccountMeta = string, TAccountSourceStakeAccount extends string | AccountMeta = string, TAccountDestinationStakeAccount extends string | AccountMeta = string, TAccountNewWithdrawAuthority extends string | AccountMeta = string, TAccountUserTransferAuthority extends string | AccountMeta = string, TAccountUserPoolTokenAccount extends string | AccountMeta = string, TAccountFeeAccount extends string | AccountMeta = string, TAccountPoolMint extends string | AccountMeta = string, TAccountClockSysvar extends string | AccountMeta = "SysvarC1ock11111111111111111111111111111111", TAccountTokenProgram extends string | AccountMeta = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA", TAccountStakeProgram extends string | AccountMeta = "Stake11111111111111111111111111111111111111", TRemainingAccounts extends readonly AccountMeta[] = [], > = Instruction & InstructionWithData & InstructionWithAccounts< [ TAccountStakePool extends string ? WritableAccount : TAccountStakePool, TAccountValidatorList extends string ? WritableAccount : TAccountValidatorList, TAccountWithdrawAuthority extends string ? ReadonlyAccount : TAccountWithdrawAuthority, TAccountSourceStakeAccount extends string ? WritableAccount : TAccountSourceStakeAccount, TAccountDestinationStakeAccount extends string ? WritableAccount : TAccountDestinationStakeAccount, TAccountNewWithdrawAuthority extends string ? ReadonlyAccount : TAccountNewWithdrawAuthority, TAccountUserTransferAuthority extends string ? ReadonlySignerAccount & AccountSignerMeta : TAccountUserTransferAuthority, TAccountUserPoolTokenAccount extends string ? WritableAccount : TAccountUserPoolTokenAccount, TAccountFeeAccount extends string ? WritableAccount : TAccountFeeAccount, TAccountPoolMint extends string ? WritableAccount : TAccountPoolMint, TAccountClockSysvar extends string ? ReadonlyAccount : TAccountClockSysvar, TAccountTokenProgram extends string ? ReadonlyAccount : TAccountTokenProgram, TAccountStakeProgram extends string ? ReadonlyAccount : TAccountStakeProgram, ...TRemainingAccounts, ] >; export type WithdrawStakeInstructionData = { discriminator: number; args: bigint; }; export type WithdrawStakeInstructionDataArgs = { args: number | bigint }; export function getWithdrawStakeInstructionDataEncoder(): FixedSizeEncoder { return transformEncoder( getStructEncoder([ ["discriminator", getU8Encoder()], ["args", getU64Encoder()], ]), (value) => ({ ...value, discriminator: WITHDRAW_STAKE_DISCRIMINATOR }), ); } export function getWithdrawStakeInstructionDataDecoder(): FixedSizeDecoder { return getStructDecoder([ ["discriminator", getU8Decoder()], ["args", getU64Decoder()], ]); } export function getWithdrawStakeInstructionDataCodec(): FixedSizeCodec< WithdrawStakeInstructionDataArgs, WithdrawStakeInstructionData > { return combineCodec( getWithdrawStakeInstructionDataEncoder(), getWithdrawStakeInstructionDataDecoder(), ); } export type WithdrawStakeAsyncInput< TAccountStakePool extends string = string, TAccountValidatorList extends string = string, TAccountWithdrawAuthority extends string = string, TAccountSourceStakeAccount extends string = string, TAccountDestinationStakeAccount extends string = string, TAccountNewWithdrawAuthority extends string = string, TAccountUserTransferAuthority extends string = string, TAccountUserPoolTokenAccount extends string = string, TAccountFeeAccount extends string = string, TAccountPoolMint extends string = string, TAccountClockSysvar extends string = string, TAccountTokenProgram extends string = string, TAccountStakeProgram extends string = string, > = { /** Stake pool */ stakePool: Address; /** Validator list */ validatorList: Address; /** Withdraw authority */ withdrawAuthority?: Address; /** Source stake account */ sourceStakeAccount: Address; /** Destination stake account */ destinationStakeAccount: Address; /** New withdraw authority */ newWithdrawAuthority: Address; /** User transfer authority */ userTransferAuthority: TransactionSigner; /** User pool token account */ userPoolTokenAccount: Address; /** Fee account */ feeAccount: Address; /** Pool mint */ poolMint: Address; /** Clock sysvar */ clockSysvar?: Address; /** Token program */ tokenProgram?: Address; /** Stake program */ stakeProgram?: Address; args: WithdrawStakeInstructionDataArgs["args"]; }; /** * Withdraw the token from the pool at the current ratio. * Succeeds if the stake account has enough SOL to cover the desired * amount of pool tokens, and if the withdrawal keeps the total * staked amount above the minimum of rent-exempt amount plus `max( * crate::MINIMUM_ACTIVE_STAKE, * solana_program::stake::tools::get_minimum_delegation() * )`. * When allowing withdrawals, the order of priority goes: * * preferred withdraw validator stake account (if set) * * validator stake accounts * * transient stake accounts * * reserve stake account OR totally remove validator stake accounts * A user can freely withdraw from a validator stake account, and if they * are all at the minimum, then they can withdraw from transient stake * accounts, and if they are all at minimum, then they can withdraw from * the reserve or remove any validator from the pool. * 0. `[w]` Stake pool * 1. `[w]` Validator stake list storage account * 2. `[]` Stake pool withdraw authority * 3. `[w]` Validator or reserve stake account to split * 4. `[w]` Uninitialized stake account to receive withdrawal * 5. `[]` User account to set as a new withdraw authority * 6. `[s]` User transfer authority, for pool token account * 7. `[w]` User account with pool tokens to burn from * 8. `[w]` Account to receive pool fee tokens * 9. `[w]` Pool token mint account * 10. `[]` Sysvar clock account (required) * 11. `[]` Pool token program id * 12. `[]` Stake program id, * User data: amount of pool tokens to withdraw */ export async function getWithdrawStakeInstructionAsync< TAccountStakePool extends string, TAccountValidatorList extends string, TAccountWithdrawAuthority extends string, TAccountSourceStakeAccount extends string, TAccountDestinationStakeAccount extends string, TAccountNewWithdrawAuthority extends string, TAccountUserTransferAuthority extends string, TAccountUserPoolTokenAccount extends string, TAccountFeeAccount extends string, TAccountPoolMint extends string, TAccountClockSysvar extends string, TAccountTokenProgram extends string, TAccountStakeProgram extends string, TProgramAddress extends Address = typeof SPL_STAKE_POOL_PROGRAM_ADDRESS, >( input: WithdrawStakeAsyncInput< TAccountStakePool, TAccountValidatorList, TAccountWithdrawAuthority, TAccountSourceStakeAccount, TAccountDestinationStakeAccount, TAccountNewWithdrawAuthority, TAccountUserTransferAuthority, TAccountUserPoolTokenAccount, TAccountFeeAccount, TAccountPoolMint, TAccountClockSysvar, TAccountTokenProgram, TAccountStakeProgram >, config?: { programAddress?: TProgramAddress }, ): Promise< WithdrawStakeInstruction< TProgramAddress, TAccountStakePool, TAccountValidatorList, TAccountWithdrawAuthority, TAccountSourceStakeAccount, TAccountDestinationStakeAccount, TAccountNewWithdrawAuthority, TAccountUserTransferAuthority, TAccountUserPoolTokenAccount, TAccountFeeAccount, TAccountPoolMint, TAccountClockSysvar, TAccountTokenProgram, TAccountStakeProgram > > { // Program address. const programAddress = config?.programAddress ?? SPL_STAKE_POOL_PROGRAM_ADDRESS; // Original accounts. const originalAccounts = { stakePool: { value: input.stakePool ?? null, isWritable: true }, validatorList: { value: input.validatorList ?? null, isWritable: true }, withdrawAuthority: { value: input.withdrawAuthority ?? null, isWritable: false, }, sourceStakeAccount: { value: input.sourceStakeAccount ?? null, isWritable: true, }, destinationStakeAccount: { value: input.destinationStakeAccount ?? null, isWritable: true, }, newWithdrawAuthority: { value: input.newWithdrawAuthority ?? null, isWritable: false, }, userTransferAuthority: { value: input.userTransferAuthority ?? null, isWritable: false, }, userPoolTokenAccount: { value: input.userPoolTokenAccount ?? null, isWritable: true, }, feeAccount: { value: input.feeAccount ?? null, isWritable: true }, poolMint: { value: input.poolMint ?? null, isWritable: true }, clockSysvar: { value: input.clockSysvar ?? null, isWritable: false }, tokenProgram: { value: input.tokenProgram ?? null, isWritable: false }, stakeProgram: { value: input.stakeProgram ?? null, isWritable: false }, }; const accounts = originalAccounts as Record< keyof typeof originalAccounts, ResolvedInstructionAccount >; // Original args. const args = { ...input }; // Resolve default values. if (!accounts.withdrawAuthority.value) { accounts.withdrawAuthority.value = await findWithdrawAuthorityPda( { stakePoolAddress: getAddressFromResolvedInstructionAccount( "stakePool", accounts.stakePool.value, ), }, { programAddress }, ); } if (!accounts.clockSysvar.value) { accounts.clockSysvar.value = "SysvarC1ock11111111111111111111111111111111" as Address<"SysvarC1ock11111111111111111111111111111111">; } if (!accounts.tokenProgram.value) { accounts.tokenProgram.value = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" as Address<"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA">; } if (!accounts.stakeProgram.value) { accounts.stakeProgram.value = "Stake11111111111111111111111111111111111111" as Address<"Stake11111111111111111111111111111111111111">; } const getAccountMeta = getAccountMetaFactory(programAddress, "programId"); return Object.freeze({ accounts: [ getAccountMeta("stakePool", accounts.stakePool), getAccountMeta("validatorList", accounts.validatorList), getAccountMeta("withdrawAuthority", accounts.withdrawAuthority), getAccountMeta("sourceStakeAccount", accounts.sourceStakeAccount), getAccountMeta( "destinationStakeAccount", accounts.destinationStakeAccount, ), getAccountMeta("newWithdrawAuthority", accounts.newWithdrawAuthority), getAccountMeta("userTransferAuthority", accounts.userTransferAuthority), getAccountMeta("userPoolTokenAccount", accounts.userPoolTokenAccount), getAccountMeta("feeAccount", accounts.feeAccount), getAccountMeta("poolMint", accounts.poolMint), getAccountMeta("clockSysvar", accounts.clockSysvar), getAccountMeta("tokenProgram", accounts.tokenProgram), getAccountMeta("stakeProgram", accounts.stakeProgram), ], data: getWithdrawStakeInstructionDataEncoder().encode( args as WithdrawStakeInstructionDataArgs, ), programAddress, } as WithdrawStakeInstruction< TProgramAddress, TAccountStakePool, TAccountValidatorList, TAccountWithdrawAuthority, TAccountSourceStakeAccount, TAccountDestinationStakeAccount, TAccountNewWithdrawAuthority, TAccountUserTransferAuthority, TAccountUserPoolTokenAccount, TAccountFeeAccount, TAccountPoolMint, TAccountClockSysvar, TAccountTokenProgram, TAccountStakeProgram >); } export type WithdrawStakeInput< TAccountStakePool extends string = string, TAccountValidatorList extends string = string, TAccountWithdrawAuthority extends string = string, TAccountSourceStakeAccount extends string = string, TAccountDestinationStakeAccount extends string = string, TAccountNewWithdrawAuthority extends string = string, TAccountUserTransferAuthority extends string = string, TAccountUserPoolTokenAccount extends string = string, TAccountFeeAccount extends string = string, TAccountPoolMint extends string = string, TAccountClockSysvar extends string = string, TAccountTokenProgram extends string = string, TAccountStakeProgram extends string = string, > = { /** Stake pool */ stakePool: Address; /** Validator list */ validatorList: Address; /** Withdraw authority */ withdrawAuthority: Address; /** Source stake account */ sourceStakeAccount: Address; /** Destination stake account */ destinationStakeAccount: Address; /** New withdraw authority */ newWithdrawAuthority: Address; /** User transfer authority */ userTransferAuthority: TransactionSigner; /** User pool token account */ userPoolTokenAccount: Address; /** Fee account */ feeAccount: Address; /** Pool mint */ poolMint: Address; /** Clock sysvar */ clockSysvar?: Address; /** Token program */ tokenProgram?: Address; /** Stake program */ stakeProgram?: Address; args: WithdrawStakeInstructionDataArgs["args"]; }; /** * Withdraw the token from the pool at the current ratio. * Succeeds if the stake account has enough SOL to cover the desired * amount of pool tokens, and if the withdrawal keeps the total * staked amount above the minimum of rent-exempt amount plus `max( * crate::MINIMUM_ACTIVE_STAKE, * solana_program::stake::tools::get_minimum_delegation() * )`. * When allowing withdrawals, the order of priority goes: * * preferred withdraw validator stake account (if set) * * validator stake accounts * * transient stake accounts * * reserve stake account OR totally remove validator stake accounts * A user can freely withdraw from a validator stake account, and if they * are all at the minimum, then they can withdraw from transient stake * accounts, and if they are all at minimum, then they can withdraw from * the reserve or remove any validator from the pool. * 0. `[w]` Stake pool * 1. `[w]` Validator stake list storage account * 2. `[]` Stake pool withdraw authority * 3. `[w]` Validator or reserve stake account to split * 4. `[w]` Uninitialized stake account to receive withdrawal * 5. `[]` User account to set as a new withdraw authority * 6. `[s]` User transfer authority, for pool token account * 7. `[w]` User account with pool tokens to burn from * 8. `[w]` Account to receive pool fee tokens * 9. `[w]` Pool token mint account * 10. `[]` Sysvar clock account (required) * 11. `[]` Pool token program id * 12. `[]` Stake program id, * User data: amount of pool tokens to withdraw */ export function getWithdrawStakeInstruction< TAccountStakePool extends string, TAccountValidatorList extends string, TAccountWithdrawAuthority extends string, TAccountSourceStakeAccount extends string, TAccountDestinationStakeAccount extends string, TAccountNewWithdrawAuthority extends string, TAccountUserTransferAuthority extends string, TAccountUserPoolTokenAccount extends string, TAccountFeeAccount extends string, TAccountPoolMint extends string, TAccountClockSysvar extends string, TAccountTokenProgram extends string, TAccountStakeProgram extends string, TProgramAddress extends Address = typeof SPL_STAKE_POOL_PROGRAM_ADDRESS, >( input: WithdrawStakeInput< TAccountStakePool, TAccountValidatorList, TAccountWithdrawAuthority, TAccountSourceStakeAccount, TAccountDestinationStakeAccount, TAccountNewWithdrawAuthority, TAccountUserTransferAuthority, TAccountUserPoolTokenAccount, TAccountFeeAccount, TAccountPoolMint, TAccountClockSysvar, TAccountTokenProgram, TAccountStakeProgram >, config?: { programAddress?: TProgramAddress }, ): WithdrawStakeInstruction< TProgramAddress, TAccountStakePool, TAccountValidatorList, TAccountWithdrawAuthority, TAccountSourceStakeAccount, TAccountDestinationStakeAccount, TAccountNewWithdrawAuthority, TAccountUserTransferAuthority, TAccountUserPoolTokenAccount, TAccountFeeAccount, TAccountPoolMint, TAccountClockSysvar, TAccountTokenProgram, TAccountStakeProgram > { // Program address. const programAddress = config?.programAddress ?? SPL_STAKE_POOL_PROGRAM_ADDRESS; // Original accounts. const originalAccounts = { stakePool: { value: input.stakePool ?? null, isWritable: true }, validatorList: { value: input.validatorList ?? null, isWritable: true }, withdrawAuthority: { value: input.withdrawAuthority ?? null, isWritable: false, }, sourceStakeAccount: { value: input.sourceStakeAccount ?? null, isWritable: true, }, destinationStakeAccount: { value: input.destinationStakeAccount ?? null, isWritable: true, }, newWithdrawAuthority: { value: input.newWithdrawAuthority ?? null, isWritable: false, }, userTransferAuthority: { value: input.userTransferAuthority ?? null, isWritable: false, }, userPoolTokenAccount: { value: input.userPoolTokenAccount ?? null, isWritable: true, }, feeAccount: { value: input.feeAccount ?? null, isWritable: true }, poolMint: { value: input.poolMint ?? null, isWritable: true }, clockSysvar: { value: input.clockSysvar ?? null, isWritable: false }, tokenProgram: { value: input.tokenProgram ?? null, isWritable: false }, stakeProgram: { value: input.stakeProgram ?? null, isWritable: false }, }; const accounts = originalAccounts as Record< keyof typeof originalAccounts, ResolvedInstructionAccount >; // Original args. const args = { ...input }; // Resolve default values. if (!accounts.clockSysvar.value) { accounts.clockSysvar.value = "SysvarC1ock11111111111111111111111111111111" as Address<"SysvarC1ock11111111111111111111111111111111">; } if (!accounts.tokenProgram.value) { accounts.tokenProgram.value = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" as Address<"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA">; } if (!accounts.stakeProgram.value) { accounts.stakeProgram.value = "Stake11111111111111111111111111111111111111" as Address<"Stake11111111111111111111111111111111111111">; } const getAccountMeta = getAccountMetaFactory(programAddress, "programId"); return Object.freeze({ accounts: [ getAccountMeta("stakePool", accounts.stakePool), getAccountMeta("validatorList", accounts.validatorList), getAccountMeta("withdrawAuthority", accounts.withdrawAuthority), getAccountMeta("sourceStakeAccount", accounts.sourceStakeAccount), getAccountMeta( "destinationStakeAccount", accounts.destinationStakeAccount, ), getAccountMeta("newWithdrawAuthority", accounts.newWithdrawAuthority), getAccountMeta("userTransferAuthority", accounts.userTransferAuthority), getAccountMeta("userPoolTokenAccount", accounts.userPoolTokenAccount), getAccountMeta("feeAccount", accounts.feeAccount), getAccountMeta("poolMint", accounts.poolMint), getAccountMeta("clockSysvar", accounts.clockSysvar), getAccountMeta("tokenProgram", accounts.tokenProgram), getAccountMeta("stakeProgram", accounts.stakeProgram), ], data: getWithdrawStakeInstructionDataEncoder().encode( args as WithdrawStakeInstructionDataArgs, ), programAddress, } as WithdrawStakeInstruction< TProgramAddress, TAccountStakePool, TAccountValidatorList, TAccountWithdrawAuthority, TAccountSourceStakeAccount, TAccountDestinationStakeAccount, TAccountNewWithdrawAuthority, TAccountUserTransferAuthority, TAccountUserPoolTokenAccount, TAccountFeeAccount, TAccountPoolMint, TAccountClockSysvar, TAccountTokenProgram, TAccountStakeProgram >); } export type ParsedWithdrawStakeInstruction< TProgram extends string = typeof SPL_STAKE_POOL_PROGRAM_ADDRESS, TAccountMetas extends readonly AccountMeta[] = readonly AccountMeta[], > = { programAddress: Address; accounts: { /** Stake pool */ stakePool: TAccountMetas[0]; /** Validator list */ validatorList: TAccountMetas[1]; /** Withdraw authority */ withdrawAuthority: TAccountMetas[2]; /** Source stake account */ sourceStakeAccount: TAccountMetas[3]; /** Destination stake account */ destinationStakeAccount: TAccountMetas[4]; /** New withdraw authority */ newWithdrawAuthority: TAccountMetas[5]; /** User transfer authority */ userTransferAuthority: TAccountMetas[6]; /** User pool token account */ userPoolTokenAccount: TAccountMetas[7]; /** Fee account */ feeAccount: TAccountMetas[8]; /** Pool mint */ poolMint: TAccountMetas[9]; /** Clock sysvar */ clockSysvar: TAccountMetas[10]; /** Token program */ tokenProgram: TAccountMetas[11]; /** Stake program */ stakeProgram: TAccountMetas[12]; }; data: WithdrawStakeInstructionData; }; export function parseWithdrawStakeInstruction< TProgram extends string, TAccountMetas extends readonly AccountMeta[], >( instruction: Instruction & InstructionWithAccounts & InstructionWithData, ): ParsedWithdrawStakeInstruction { if (instruction.accounts.length < 13) { throw new SolanaError( SOLANA_ERROR__PROGRAM_CLIENTS__INSUFFICIENT_ACCOUNT_METAS, { actualAccountMetas: instruction.accounts.length, expectedAccountMetas: 13, }, ); } let accountIndex = 0; const getNextAccount = () => { const accountMeta = (instruction.accounts as TAccountMetas)[accountIndex]!; accountIndex += 1; return accountMeta; }; return { programAddress: instruction.programAddress, accounts: { stakePool: getNextAccount(), validatorList: getNextAccount(), withdrawAuthority: getNextAccount(), sourceStakeAccount: getNextAccount(), destinationStakeAccount: getNextAccount(), newWithdrawAuthority: getNextAccount(), userTransferAuthority: getNextAccount(), userPoolTokenAccount: getNextAccount(), feeAccount: getNextAccount(), poolMint: getNextAccount(), clockSysvar: getNextAccount(), tokenProgram: getNextAccount(), stakeProgram: getNextAccount(), }, data: getWithdrawStakeInstructionDataDecoder().decode(instruction.data), }; }