/**
 * 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, fixDecoderSize, fixEncoderSize, getBooleanDecoder, getBooleanEncoder, getBytesDecoder, getBytesEncoder, getStructDecoder, getStructEncoder, getU128Decoder, getU128Encoder, getU64Decoder, getU64Encoder, transformEncoder, type AccountMeta, type AccountSignerMeta, type Address, type FixedSizeCodec, type FixedSizeDecoder, type FixedSizeEncoder, type Instruction, type InstructionWithAccounts, type InstructionWithData, type ReadonlyAccount, type ReadonlyUint8Array, type TransactionSigner, type WritableSignerAccount } from '@solana/kit';
import { YVAULTS_PROGRAM_ADDRESS } from '../programs';
import { getAccountMetaFactory, type ResolvedAccount } from '../shared';

export const ORCA_SWAP_DISCRIMINATOR = new Uint8Array([33, 94, 249, 97, 250, 254, 198, 93]);

export function getOrcaSwapDiscriminatorBytes() { return fixEncoderSize(getBytesEncoder(), 8).encode(ORCA_SWAP_DISCRIMINATOR); }

export type OrcaSwapInstruction<TProgram extends string = typeof YVAULTS_PROGRAM_ADDRESS, TAccountFunder extends string | AccountMeta<string> = string, TAccountTokenATokenProgram extends string | AccountMeta<string> = string, TAccountTokenBTokenProgram extends string | AccountMeta<string> = string, TAccountMemoProgram extends string | AccountMeta<string> = string, TAccountTokenAuthority extends string | AccountMeta<string> = string, TAccountWhirlpool extends string | AccountMeta<string> = string, TAccountTokenOwnerAccountA extends string | AccountMeta<string> = string, TAccountTokenVaultA extends string | AccountMeta<string> = string, TAccountTokenOwnerAccountB extends string | AccountMeta<string> = string, TAccountTokenVaultB extends string | AccountMeta<string> = string, TAccountTokenMintA extends string | AccountMeta<string> = string, TAccountTokenMintB extends string | AccountMeta<string> = string, TAccountTickArray0 extends string | AccountMeta<string> = string, TAccountTickArray1 extends string | AccountMeta<string> = string, TAccountTickArray2 extends string | AccountMeta<string> = string, TAccountOracle extends string | AccountMeta<string> = string, TAccountWhirlpoolProgram extends string | AccountMeta<string> = string, TRemainingAccounts extends readonly AccountMeta<string>[] = []> =
Instruction<TProgram> & InstructionWithData<ReadonlyUint8Array> & InstructionWithAccounts<[TAccountFunder extends string ? WritableSignerAccount<TAccountFunder> & AccountSignerMeta<TAccountFunder> : TAccountFunder, TAccountTokenATokenProgram extends string ? ReadonlyAccount<TAccountTokenATokenProgram> : TAccountTokenATokenProgram, TAccountTokenBTokenProgram extends string ? ReadonlyAccount<TAccountTokenBTokenProgram> : TAccountTokenBTokenProgram, TAccountMemoProgram extends string ? ReadonlyAccount<TAccountMemoProgram> : TAccountMemoProgram, TAccountTokenAuthority extends string ? ReadonlyAccount<TAccountTokenAuthority> : TAccountTokenAuthority, TAccountWhirlpool extends string ? ReadonlyAccount<TAccountWhirlpool> : TAccountWhirlpool, TAccountTokenOwnerAccountA extends string ? ReadonlyAccount<TAccountTokenOwnerAccountA> : TAccountTokenOwnerAccountA, TAccountTokenVaultA extends string ? ReadonlyAccount<TAccountTokenVaultA> : TAccountTokenVaultA, TAccountTokenOwnerAccountB extends string ? ReadonlyAccount<TAccountTokenOwnerAccountB> : TAccountTokenOwnerAccountB, TAccountTokenVaultB extends string ? ReadonlyAccount<TAccountTokenVaultB> : TAccountTokenVaultB, TAccountTokenMintA extends string ? ReadonlyAccount<TAccountTokenMintA> : TAccountTokenMintA, TAccountTokenMintB extends string ? ReadonlyAccount<TAccountTokenMintB> : TAccountTokenMintB, TAccountTickArray0 extends string ? ReadonlyAccount<TAccountTickArray0> : TAccountTickArray0, TAccountTickArray1 extends string ? ReadonlyAccount<TAccountTickArray1> : TAccountTickArray1, TAccountTickArray2 extends string ? ReadonlyAccount<TAccountTickArray2> : TAccountTickArray2, TAccountOracle extends string ? ReadonlyAccount<TAccountOracle> : TAccountOracle, TAccountWhirlpoolProgram extends string ? ReadonlyAccount<TAccountWhirlpoolProgram> : TAccountWhirlpoolProgram, ...TRemainingAccounts]>;

export type OrcaSwapInstructionData = { discriminator: ReadonlyUint8Array; amount: bigint; otherAmountThreshold: bigint; sqrtPriceLimit: bigint; amountSpecifiedIsInput: boolean; aToB: boolean;  };

export type OrcaSwapInstructionDataArgs = { amount: number | bigint; otherAmountThreshold: number | bigint; sqrtPriceLimit: number | bigint; amountSpecifiedIsInput: boolean; aToB: boolean;  };

export function getOrcaSwapInstructionDataEncoder(): FixedSizeEncoder<OrcaSwapInstructionDataArgs> {
    return transformEncoder(getStructEncoder([['discriminator', fixEncoderSize(getBytesEncoder(), 8)], ['amount', getU64Encoder()], ['otherAmountThreshold', getU64Encoder()], ['sqrtPriceLimit', getU128Encoder()], ['amountSpecifiedIsInput', getBooleanEncoder()], ['aToB', getBooleanEncoder()]]), (value) => ({ ...value, discriminator: ORCA_SWAP_DISCRIMINATOR }));
}

export function getOrcaSwapInstructionDataDecoder(): FixedSizeDecoder<OrcaSwapInstructionData> {
    return getStructDecoder([['discriminator', fixDecoderSize(getBytesDecoder(), 8)], ['amount', getU64Decoder()], ['otherAmountThreshold', getU64Decoder()], ['sqrtPriceLimit', getU128Decoder()], ['amountSpecifiedIsInput', getBooleanDecoder()], ['aToB', getBooleanDecoder()]]);
}

export function getOrcaSwapInstructionDataCodec(): FixedSizeCodec<OrcaSwapInstructionDataArgs, OrcaSwapInstructionData> {
    return combineCodec(getOrcaSwapInstructionDataEncoder(), getOrcaSwapInstructionDataDecoder());
}

export type OrcaSwapInput<TAccountFunder extends string = string, TAccountTokenATokenProgram extends string = string, TAccountTokenBTokenProgram extends string = string, TAccountMemoProgram extends string = string, TAccountTokenAuthority extends string = string, TAccountWhirlpool extends string = string, TAccountTokenOwnerAccountA extends string = string, TAccountTokenVaultA extends string = string, TAccountTokenOwnerAccountB extends string = string, TAccountTokenVaultB extends string = string, TAccountTokenMintA extends string = string, TAccountTokenMintB extends string = string, TAccountTickArray0 extends string = string, TAccountTickArray1 extends string = string, TAccountTickArray2 extends string = string, TAccountOracle extends string = string, TAccountWhirlpoolProgram extends string = string> =  {
  funder: TransactionSigner<TAccountFunder>;
tokenATokenProgram: Address<TAccountTokenATokenProgram>;
tokenBTokenProgram: Address<TAccountTokenBTokenProgram>;
memoProgram: Address<TAccountMemoProgram>;
tokenAuthority: Address<TAccountTokenAuthority>;
whirlpool: Address<TAccountWhirlpool>;
tokenOwnerAccountA: Address<TAccountTokenOwnerAccountA>;
tokenVaultA: Address<TAccountTokenVaultA>;
tokenOwnerAccountB: Address<TAccountTokenOwnerAccountB>;
tokenVaultB: Address<TAccountTokenVaultB>;
tokenMintA: Address<TAccountTokenMintA>;
tokenMintB: Address<TAccountTokenMintB>;
tickArray0: Address<TAccountTickArray0>;
tickArray1: Address<TAccountTickArray1>;
tickArray2: Address<TAccountTickArray2>;
oracle: Address<TAccountOracle>;
whirlpoolProgram: Address<TAccountWhirlpoolProgram>;
amount: OrcaSwapInstructionDataArgs["amount"];
otherAmountThreshold: OrcaSwapInstructionDataArgs["otherAmountThreshold"];
sqrtPriceLimit: OrcaSwapInstructionDataArgs["sqrtPriceLimit"];
amountSpecifiedIsInput: OrcaSwapInstructionDataArgs["amountSpecifiedIsInput"];
aToB: OrcaSwapInstructionDataArgs["aToB"];
}

export function getOrcaSwapInstruction<TAccountFunder extends string, TAccountTokenATokenProgram extends string, TAccountTokenBTokenProgram extends string, TAccountMemoProgram extends string, TAccountTokenAuthority extends string, TAccountWhirlpool extends string, TAccountTokenOwnerAccountA extends string, TAccountTokenVaultA extends string, TAccountTokenOwnerAccountB extends string, TAccountTokenVaultB extends string, TAccountTokenMintA extends string, TAccountTokenMintB extends string, TAccountTickArray0 extends string, TAccountTickArray1 extends string, TAccountTickArray2 extends string, TAccountOracle extends string, TAccountWhirlpoolProgram extends string, TProgramAddress extends Address = typeof YVAULTS_PROGRAM_ADDRESS>(input: OrcaSwapInput<TAccountFunder, TAccountTokenATokenProgram, TAccountTokenBTokenProgram, TAccountMemoProgram, TAccountTokenAuthority, TAccountWhirlpool, TAccountTokenOwnerAccountA, TAccountTokenVaultA, TAccountTokenOwnerAccountB, TAccountTokenVaultB, TAccountTokenMintA, TAccountTokenMintB, TAccountTickArray0, TAccountTickArray1, TAccountTickArray2, TAccountOracle, TAccountWhirlpoolProgram>, config?: { programAddress?: TProgramAddress } ): OrcaSwapInstruction<TProgramAddress, TAccountFunder, TAccountTokenATokenProgram, TAccountTokenBTokenProgram, TAccountMemoProgram, TAccountTokenAuthority, TAccountWhirlpool, TAccountTokenOwnerAccountA, TAccountTokenVaultA, TAccountTokenOwnerAccountB, TAccountTokenVaultB, TAccountTokenMintA, TAccountTokenMintB, TAccountTickArray0, TAccountTickArray1, TAccountTickArray2, TAccountOracle, TAccountWhirlpoolProgram> {
  // Program address.
const programAddress = config?.programAddress ?? YVAULTS_PROGRAM_ADDRESS;

 // Original accounts.
const originalAccounts = { funder: { value: input.funder ?? null, isWritable: true }, tokenATokenProgram: { value: input.tokenATokenProgram ?? null, isWritable: false }, tokenBTokenProgram: { value: input.tokenBTokenProgram ?? null, isWritable: false }, memoProgram: { value: input.memoProgram ?? null, isWritable: false }, tokenAuthority: { value: input.tokenAuthority ?? null, isWritable: false }, whirlpool: { value: input.whirlpool ?? null, isWritable: false }, tokenOwnerAccountA: { value: input.tokenOwnerAccountA ?? null, isWritable: false }, tokenVaultA: { value: input.tokenVaultA ?? null, isWritable: false }, tokenOwnerAccountB: { value: input.tokenOwnerAccountB ?? null, isWritable: false }, tokenVaultB: { value: input.tokenVaultB ?? null, isWritable: false }, tokenMintA: { value: input.tokenMintA ?? null, isWritable: false }, tokenMintB: { value: input.tokenMintB ?? null, isWritable: false }, tickArray0: { value: input.tickArray0 ?? null, isWritable: false }, tickArray1: { value: input.tickArray1 ?? null, isWritable: false }, tickArray2: { value: input.tickArray2 ?? null, isWritable: false }, oracle: { value: input.oracle ?? null, isWritable: false }, whirlpoolProgram: { value: input.whirlpoolProgram ?? null, isWritable: false } }
const accounts = originalAccounts as Record<keyof typeof originalAccounts, ResolvedAccount>;


// Original args.
const args = { ...input,  };




const getAccountMeta = getAccountMetaFactory(programAddress, 'programId');
return Object.freeze({ accounts: [getAccountMeta(accounts.funder), getAccountMeta(accounts.tokenATokenProgram), getAccountMeta(accounts.tokenBTokenProgram), getAccountMeta(accounts.memoProgram), getAccountMeta(accounts.tokenAuthority), getAccountMeta(accounts.whirlpool), getAccountMeta(accounts.tokenOwnerAccountA), getAccountMeta(accounts.tokenVaultA), getAccountMeta(accounts.tokenOwnerAccountB), getAccountMeta(accounts.tokenVaultB), getAccountMeta(accounts.tokenMintA), getAccountMeta(accounts.tokenMintB), getAccountMeta(accounts.tickArray0), getAccountMeta(accounts.tickArray1), getAccountMeta(accounts.tickArray2), getAccountMeta(accounts.oracle), getAccountMeta(accounts.whirlpoolProgram)], data: getOrcaSwapInstructionDataEncoder().encode(args as OrcaSwapInstructionDataArgs), programAddress } as OrcaSwapInstruction<TProgramAddress, TAccountFunder, TAccountTokenATokenProgram, TAccountTokenBTokenProgram, TAccountMemoProgram, TAccountTokenAuthority, TAccountWhirlpool, TAccountTokenOwnerAccountA, TAccountTokenVaultA, TAccountTokenOwnerAccountB, TAccountTokenVaultB, TAccountTokenMintA, TAccountTokenMintB, TAccountTickArray0, TAccountTickArray1, TAccountTickArray2, TAccountOracle, TAccountWhirlpoolProgram>);
}

export type ParsedOrcaSwapInstruction<TProgram extends string = typeof YVAULTS_PROGRAM_ADDRESS, TAccountMetas extends readonly AccountMeta[] = readonly AccountMeta[]> = { programAddress: Address<TProgram>;
accounts: {
funder: TAccountMetas[0];
tokenATokenProgram: TAccountMetas[1];
tokenBTokenProgram: TAccountMetas[2];
memoProgram: TAccountMetas[3];
tokenAuthority: TAccountMetas[4];
whirlpool: TAccountMetas[5];
tokenOwnerAccountA: TAccountMetas[6];
tokenVaultA: TAccountMetas[7];
tokenOwnerAccountB: TAccountMetas[8];
tokenVaultB: TAccountMetas[9];
tokenMintA: TAccountMetas[10];
tokenMintB: TAccountMetas[11];
tickArray0: TAccountMetas[12];
tickArray1: TAccountMetas[13];
tickArray2: TAccountMetas[14];
oracle: TAccountMetas[15];
whirlpoolProgram: TAccountMetas[16];
};
data: OrcaSwapInstructionData; };

export function parseOrcaSwapInstruction<TProgram extends string, TAccountMetas extends readonly AccountMeta[]>(instruction: Instruction<TProgram> & InstructionWithAccounts<TAccountMetas> & InstructionWithData<ReadonlyUint8Array>): ParsedOrcaSwapInstruction<TProgram, TAccountMetas> {
  if (instruction.accounts.length < 17) {
  // TODO: Coded error.
  throw new Error('Not enough accounts');
}
let accountIndex = 0;
const getNextAccount = () => {
  const accountMeta = (instruction.accounts as TAccountMetas)[accountIndex]!;
  accountIndex += 1;
  return accountMeta;
}
  return { programAddress: instruction.programAddress, accounts: { funder: getNextAccount(), tokenATokenProgram: getNextAccount(), tokenBTokenProgram: getNextAccount(), memoProgram: getNextAccount(), tokenAuthority: getNextAccount(), whirlpool: getNextAccount(), tokenOwnerAccountA: getNextAccount(), tokenVaultA: getNextAccount(), tokenOwnerAccountB: getNextAccount(), tokenVaultB: getNextAccount(), tokenMintA: getNextAccount(), tokenMintB: getNextAccount(), tickArray0: getNextAccount(), tickArray1: getNextAccount(), tickArray2: getNextAccount(), oracle: getNextAccount(), whirlpoolProgram: getNextAccount() }, data: getOrcaSwapInstructionDataDecoder().decode(instruction.data) };
}