import { Buffer } from 'buffer';
import * as beet from '@metaplex-foundation/beet';
import { allowListBeet } from '@metaplex-foundation/mpl-candy-guard';
import { mapSerializer, createSerializerFromBeet } from '../../../types/Serializer.mjs';

/**
 * The allowList guard validates the minting wallet against
 * a predefined list of wallets.
 *
 * Instead of passing the entire list of wallets as settings,
 * this guard accepts the Root of a Merkle Tree created from
 * this allow list. The program can then validate that the minting
 * wallet is part of the allow list by requiring a Merkle Proof.
 * Minting will fail if either the minting address is not part of
 * the merkle tree or if no Merkle Proof is specified.
 *
 * You may use the `getMerkleRoot` and `getMerkleProof` helper
 * functions provided by the SDK to help you set up this guard.
 * Here is an example.
 *
 * ```ts
 * import { getMerkleProof, getMerkleRoot } from '@metaplex-solarti/js';
 * const allowList = [
 *   'Ur1CbWSGsXCdedknRbJsEk7urwAvu1uddmQv51nAnXB',
 *   'GjwcWFQYzemBtpUoN5fMAP2FZviTtMRWCmrppGuTthJS',
 *   'AT8nPwujHAD14cLojTcB1qdBzA1VXnT6LVGuUd6Y73Cy',
 * ];
 * const merkleRoot = getMerkleRoot(allowList);
 * const validMerkleProof = getMerkleProof(allowList, 'Ur1CbWSGsXCdedknRbJsEk7urwAvu1uddmQv51nAnXB');
 * const invalidMerkleProof = getMerkleProof(allowList, 'invalid-address');
 * ```
 *
 * Note that you will need to provide the Merkle Proof for the
 * minting wallet before calling the mint instruction via the
 * special "route" instruction of the guard.
 * See {@link AllowListGuardRouteSettings} for more information.
 *
 * This object defines the settings that should be
 * provided when creating and/or updating a Candy
 * Machine if you wish to enable this guard.
 *
 * @see {@link AllowListGuardRouteSettings} to learn more about
 * the instructions that can be executed against this guard.
 */

/** @internal */
const allowListGuardManifest = {
  name: 'allowList',
  settingsBytes: 32,
  settingsSerializer: mapSerializer(createSerializerFromBeet(allowListBeet), settings => ({
    merkleRoot: new Uint8Array(settings.merkleRoot)
  }), settings => ({
    merkleRoot: Array.from(settings.merkleRoot)
  })),
  mintSettingsParser: ({
    metaplex,
    settings,
    payer,
    candyMachine,
    candyGuard
  }) => {
    return {
      arguments: Buffer.from([]),
      remainingAccounts: [{
        isSigner: false,
        isWritable: false,
        address: metaplex.candyMachines().pdas().merkleProof({
          merkleRoot: settings.merkleRoot,
          user: payer.publicKey,
          candyMachine,
          candyGuard
        })
      }]
    };
  },
  routeSettingsParser: ({
    metaplex,
    settings,
    routeSettings,
    programs,
    candyMachine,
    candyGuard,
    payer
  }) => {
    const proof = routeSettings.merkleProof;
    const vectorSize = Buffer.alloc(4);
    beet.u32.write(vectorSize, 0, proof.length);
    return {
      arguments: Buffer.concat([vectorSize, ...proof]),
      remainingAccounts: [{
        isSigner: false,
        isWritable: true,
        address: metaplex.candyMachines().pdas().merkleProof({
          merkleRoot: settings.merkleRoot,
          user: payer.publicKey,
          candyMachine,
          candyGuard
        })
      }, {
        isSigner: false,
        isWritable: false,
        address: metaplex.programs().getSystem(programs).address
      }]
    };
  }
};

export { allowListGuardManifest };
//# sourceMappingURL=allowList.mjs.map
