import { createInitializeInstruction, initializeInstructionDiscriminator } from '@metaplex-foundation/mpl-candy-guard';
import { Keypair } from '@solarti/web3.js';
import { emptyDefaultCandyGuardSettings } from '../guards/default.mjs';
import { serializeDiscriminator } from '../../../types/Serializer.mjs';
import { makeConfirmOptionsFinalizedOnMainnet } from '../../../types/Operation.mjs';
import { TransactionBuilder } from '../../../utils/TransactionBuilder.mjs';

// -----------------
// Operation
// -----------------

const Key = 'CreateCandyGuardOperation';

/**
 * Creates a new Candy Guard account with the provided settings.
 *
 * ```ts
 * const { candyGuard } = await metaplex
 *   .candyMachines()
 *   .createCandyGuard({
 *     guards: {
 *       startDate: { date: toDateTime('2022-09-05T20:00:00.000Z') },
 *       solPayment: { amount: sol(1.5), },
 *       botTax: { lamports: sol(0.01), lastInstruction: true },
 *     },
 *   };
 * ```
 *
 * @group Operations
 * @category Constructors
 */
const createCandyGuardOperation = _createCandyGuardOperation;
// eslint-disable-next-line @typescript-eslint/naming-convention
function _createCandyGuardOperation(input) {
  return {
    key: Key,
    input
  };
}
_createCandyGuardOperation.key = Key;

/**
 * @group Operations
 * @category Types
 */

/**
 * @group Operations
 * @category Handlers
 */
const createCandyGuardOperationHandler = {
  async handle(operation, metaplex, scope) {
    const builder = createCandyGuardBuilder(metaplex, operation.input, scope);
    const confirmOptions = makeConfirmOptionsFinalizedOnMainnet(metaplex, scope.confirmOptions);
    const output = await builder.sendAndConfirm(metaplex, confirmOptions);
    scope.throwIfCanceled();
    const candyGuard = await metaplex.candyMachines().findCandyGuardByBaseAddress({
      address: output.base.publicKey
    }, scope);
    return {
      ...output,
      candyGuard
    };
  }
};

// -----------------
// Builder
// -----------------

/**
 * @group Transaction Builders
 * @category Inputs
 */

/**
 * Creates a new Candy Guard account with the provided settings.
 *
 * ```ts
 * const transactionBuilder = await metaplex
 *   .candyMachines()
 *   .builders()
 *   .createCandyGuard({
 *     guards: {
 *       startDate: { date: toDateTime('2022-09-05T20:00:00.000Z') },
 *       solPayment: { amount: sol(1.5), },
 *       botTax: { lamports: sol(0.01), lastInstruction: true },
 *     },
 *   });
 * ```
 *
 * @group Transaction Builders
 * @category Constructors
 */
const createCandyGuardBuilder = (metaplex, params, options = {}) => {
  const {
    programs,
    payer = metaplex.rpc().getDefaultFeePayer()
  } = options;
  const base = params.base ?? Keypair.generate();
  const authority = params.authority ?? metaplex.identity().publicKey;
  const candyGuardProgram = metaplex.programs().getCandyGuard(programs);
  const candyGuard = metaplex.candyMachines().pdas().candyGuard({
    base: base.publicKey,
    programs
  });
  const initializeInstruction = createInitializeInstruction({
    candyGuard,
    base: base.publicKey,
    authority,
    payer: payer.publicKey
  }, {
    data: {
      default: emptyDefaultCandyGuardSettings,
      groups: null
    }
  }, candyGuardProgram.address);
  const serializedSettings = metaplex.candyMachines().guards().serializeSettings(params.guards, params.groups ?? [], programs);
  const discriminator = serializeDiscriminator(initializeInstructionDiscriminator);
  initializeInstruction.data = Buffer.concat([discriminator, serializedSettings]);
  return TransactionBuilder.make().setFeePayer(payer).setContext({
    base,
    candyGuardAddress: candyGuard
  })

  // Create and initialize the candy guard account.
  .add({
    instruction: initializeInstruction,
    signers: [base, payer],
    key: params.createCandyGuardInstructionKey ?? 'createCandyGuard'
  });
};

export { createCandyGuardBuilder, createCandyGuardOperation, createCandyGuardOperationHandler };
//# sourceMappingURL=createCandyGuard.mjs.map
