/**
 * 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 {
  assertAccountExists,
  assertAccountsExist,
  decodeAccount,
  fetchEncodedAccount,
  fetchEncodedAccounts,
  type Account,
  type EncodedAccount,
  type FetchAccountConfig,
  type FetchAccountsConfig,
  type MaybeAccount,
  type MaybeEncodedAccount,
} from '@solana/kit';
import { getAddressDecoder, getAddressEncoder, type Address } from '@solana/kit';
import {
  combineCodec,
  fixDecoderSize,
  fixEncoderSize,
  getBytesDecoder,
  getBytesEncoder,
  getStructDecoder,
  getStructEncoder,
  getU64Decoder,
  getU64Encoder,
  getU8Decoder,
  getU8Encoder,
  transformEncoder,
  type Codec,
  type Decoder,
  type Encoder,
  type ReadonlyUint8Array,
} from '@solana/kit';

export const GUARD_DISCRIMINATOR = new Uint8Array([54, 187, 84, 137, 192, 15, 74, 248]);

export function getGuardDiscriminatorBytes() {
  return fixEncoderSize(getBytesEncoder(), 8).encode(GUARD_DISCRIMINATOR);
}

export type Guard = {
  discriminator: ReadonlyUint8Array;
  /** Token that is used for collected protocol fees */
  feeToken: Address;
  /** Version that allows having multiple Guards with same `fee_token` */
  version: number;
  /** PDA bump */
  bump: number;
  /** Public key of auctioneer that signs permissions and confirmations */
  auctioneerPubKey: Address;
  /** Amount of collected fees, in collateral tokens */
  collectedFees: bigint;
};

export type GuardArgs = {
  /** Token that is used for collected protocol fees */
  feeToken: Address;
  /** Version that allows having multiple Guards with same `fee_token` */
  version: number;
  /** PDA bump */
  bump: number;
  /** Public key of auctioneer that signs permissions and confirmations */
  auctioneerPubKey: Address;
  /** Amount of collected fees, in collateral tokens */
  collectedFees: number | bigint;
};

export function getGuardEncoder(): Encoder<GuardArgs> {
  return transformEncoder(
    getStructEncoder([
      ['discriminator', fixEncoderSize(getBytesEncoder(), 8)],
      ['feeToken', getAddressEncoder()],
      ['version', getU8Encoder()],
      ['bump', getU8Encoder()],
      ['auctioneerPubKey', getAddressEncoder()],
      ['collectedFees', getU64Encoder()],
    ]),
    (value) => ({ ...value, discriminator: GUARD_DISCRIMINATOR }),
  );
}

export function getGuardDecoder(): Decoder<Guard> {
  return getStructDecoder([
    ['discriminator', fixDecoderSize(getBytesDecoder(), 8)],
    ['feeToken', getAddressDecoder()],
    ['version', getU8Decoder()],
    ['bump', getU8Decoder()],
    ['auctioneerPubKey', getAddressDecoder()],
    ['collectedFees', getU64Decoder()],
  ]);
}

export function getGuardCodec(): Codec<GuardArgs, Guard> {
  return combineCodec(getGuardEncoder(), getGuardDecoder());
}

export function decodeGuard<TAddress extends string = string>(
  encodedAccount: EncodedAccount<TAddress>,
): Account<Guard, TAddress>;
export function decodeGuard<TAddress extends string = string>(
  encodedAccount: MaybeEncodedAccount<TAddress>,
): MaybeAccount<Guard, TAddress>;
export function decodeGuard<TAddress extends string = string>(
  encodedAccount: EncodedAccount<TAddress> | MaybeEncodedAccount<TAddress>,
): Account<Guard, TAddress> | MaybeAccount<Guard, TAddress> {
  return decodeAccount(encodedAccount as MaybeEncodedAccount<TAddress>, getGuardDecoder());
}

export async function fetchGuard<TAddress extends string = string>(
  rpc: Parameters<typeof fetchEncodedAccount>[0],
  address: Address<TAddress>,
  config?: FetchAccountConfig,
): Promise<Account<Guard, TAddress>> {
  const maybeAccount = await fetchMaybeGuard(rpc, address, config);
  assertAccountExists(maybeAccount);
  return maybeAccount;
}

export async function fetchMaybeGuard<TAddress extends string = string>(
  rpc: Parameters<typeof fetchEncodedAccount>[0],
  address: Address<TAddress>,
  config?: FetchAccountConfig,
): Promise<MaybeAccount<Guard, TAddress>> {
  const maybeAccount = await fetchEncodedAccount(rpc, address, config);
  return decodeGuard(maybeAccount);
}

export async function fetchAllGuard(
  rpc: Parameters<typeof fetchEncodedAccounts>[0],
  addresses: Array<Address>,
  config?: FetchAccountsConfig,
): Promise<Account<Guard>[]> {
  const maybeAccounts = await fetchAllMaybeGuard(rpc, addresses, config);
  assertAccountsExist(maybeAccounts);
  return maybeAccounts;
}

export async function fetchAllMaybeGuard(
  rpc: Parameters<typeof fetchEncodedAccounts>[0],
  addresses: Array<Address>,
  config?: FetchAccountsConfig,
): Promise<MaybeAccount<Guard>[]> {
  const maybeAccounts = await fetchEncodedAccounts(rpc, addresses, config);
  return maybeAccounts.map((maybeAccount) => decodeGuard(maybeAccount));
}

export function getGuardSize(): number {
  return 82;
}
