var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
import { createInitializeCandyMachineInstruction, createSetCollectionInstruction, } from '@metaplex-solarti/mpl-candy-machine';
import { Keypair } from '@solarti/web3.js';
import { getCandyMachineV2AccountSizeFromData } from '../helpers';
import { toCandyMachineV2InstructionData, } from '../models';
import { findCandyMachineV2CollectionPda } from '../pdas';
import { CandyMachineV2Program } from '../program';
import { TransactionBuilder, } from '../../../utils';
import { assertSameCurrencies, isSigner, makeConfirmOptionsFinalizedOnMainnet, SOL, toBigNumber, toPublicKey, useOperation, } from '../../../types';
import { ExpectedSignerError } from '../../../errors';
// -----------------
// Operation
// -----------------
const Key = 'CreateCandyMachineV2Operation';
/**
 * Creates a brand new Candy Machine.
 *
 * ```ts
 * const { candyMachine } = await metaplex
 *   .candyMachinesV2()
 *   .create({
 *     sellerFeeBasisPoints: 500, // 5% royalties
 *     price: sol(1.3), // 1.3 SOL
 *     itemsAvailable: toBigNumber(1000), // 1000 items available
 *   };
 * ```
 *
 * @group Operations
 * @category Constructors
 */
export const createCandyMachineV2Operation = useOperation(Key);
/**
 * @group Operations
 * @category Handlers
 */
export const createCandyMachineV2OperationHandler = {
    handle(operation, metaplex, scope) {
        return __awaiter(this, void 0, void 0, function* () {
            const builder = yield createCandyMachineV2Builder(metaplex, operation.input, scope);
            scope.throwIfCanceled();
            const confirmOptions = makeConfirmOptionsFinalizedOnMainnet(metaplex, scope.confirmOptions);
            const output = yield builder.sendAndConfirm(metaplex, confirmOptions);
            scope.throwIfCanceled();
            const candyMachine = yield metaplex
                .candyMachinesV2()
                .findByAddress({ address: output.candyMachineSigner.publicKey }, scope);
            return Object.assign(Object.assign({}, output), { candyMachine });
        });
    },
};
/**
 * Creates a brand new Candy Machine.
 *
 * ```ts
 * const transactionBuilder = await metaplex
 *   .candyMachinesV2()
 *   .builders()
 *   .create({
 *     sellerFeeBasisPoints: 500, // 5% royalties
 *     price: sol(1.3), // 1.3 SOL
 *     itemsAvailable: toBigNumber(1000), // 1000 items available
 *   });
 * ```
 *
 * @group Transaction Builders
 * @category Constructors
 */
export const createCandyMachineV2Builder = (metaplex, params, options = {}) => __awaiter(void 0, void 0, void 0, function* () {
    var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
    const { programs, payer = metaplex.rpc().getDefaultFeePayer() } = options;
    const candyMachine = (_a = params.candyMachine) !== null && _a !== void 0 ? _a : Keypair.generate();
    const authority = (_b = params.authority) !== null && _b !== void 0 ? _b : metaplex.identity();
    const collection = (_c = params.collection) !== null && _c !== void 0 ? _c : null;
    const { data, wallet, tokenMint } = toCandyMachineV2InstructionData(candyMachine.publicKey, Object.assign(Object.assign({}, params), { wallet: (_d = params.wallet) !== null && _d !== void 0 ? _d : metaplex.identity().publicKey, tokenMint: (_e = params.tokenMint) !== null && _e !== void 0 ? _e : null, symbol: (_f = params.symbol) !== null && _f !== void 0 ? _f : '', maxEditionSupply: (_g = params.maxEditionSupply) !== null && _g !== void 0 ? _g : toBigNumber(0), isMutable: (_h = params.isMutable) !== null && _h !== void 0 ? _h : true, retainAuthority: (_j = params.retainAuthority) !== null && _j !== void 0 ? _j : true, goLiveDate: (_k = params.goLiveDate) !== null && _k !== void 0 ? _k : null, endSettings: (_l = params.endSettings) !== null && _l !== void 0 ? _l : null, creators: (_m = params.creators) !== null && _m !== void 0 ? _m : [
            {
                address: metaplex.identity().publicKey,
                share: 100,
                verified: false,
            },
        ], hiddenSettings: (_o = params.hiddenSettings) !== null && _o !== void 0 ? _o : null, whitelistMintSettings: (_p = params.whitelistMintSettings) !== null && _p !== void 0 ? _p : null, gatekeeper: (_q = params.gatekeeper) !== null && _q !== void 0 ? _q : null }));
    const initializeInstruction = createInitializeCandyMachineInstruction({
        candyMachine: candyMachine.publicKey,
        wallet,
        authority: toPublicKey(authority),
        payer: payer.publicKey,
    }, { data });
    if (tokenMint) {
        initializeInstruction.keys.push({
            pubkey: tokenMint,
            isWritable: false,
            isSigner: false,
        });
    }
    else {
        assertSameCurrencies(params.price, SOL);
    }
    return (TransactionBuilder.make()
        .setFeePayer(payer)
        .setContext({
        candyMachineSigner: candyMachine,
        wallet,
        authority: toPublicKey(authority),
        creators: data.creators,
    })
        // Create an empty account for the candy machine.
        .add(yield metaplex
        .system()
        .builders()
        .createAccount({
        newAccount: candyMachine,
        space: getCandyMachineV2AccountSizeFromData(data),
        program: CandyMachineV2Program.publicKey,
        instructionKey: (_r = params.createAccountInstructionKey) !== null && _r !== void 0 ? _r : 'createAccount',
    }, { payer, programs }))
        // Initialize the candy machine account.
        .add({
        instruction: initializeInstruction,
        signers: [candyMachine, payer],
        key: (_s = params.initializeCandyMachineInstructionKey) !== null && _s !== void 0 ? _s : 'initializeCandyMachine',
    })
        // Set the collection.
        .when(!!collection, (builder) => {
        var _a;
        if (!isSigner(authority)) {
            throw new ExpectedSignerError('authority', 'PublicKey', {
                problemSuffix: 'You are trying to create a Candy Machine with a Collection NFT. ' +
                    'In order for the Collection NFT to be set successfully, you must provide the authority as a Signer.',
                solution: 'Please provide the "authority" parameter as a Signer if you want to set the Collection NFT upon creation. ' +
                    'Alternatively, you may remove the "collection" parameter to create a Candy Machine without an associated Collection NFT.',
            });
        }
        const collectionMint = collection;
        const metadata = metaplex.nfts().pdas().metadata({
            mint: collectionMint,
            programs,
        });
        const edition = metaplex.nfts().pdas().masterEdition({
            mint: collectionMint,
            programs,
        });
        const collectionPda = findCandyMachineV2CollectionPda(candyMachine.publicKey);
        const collectionAuthorityRecord = metaplex
            .nfts()
            .pdas()
            .collectionAuthorityRecord({
            mint: collectionMint,
            collectionAuthority: collectionPda,
            programs,
        });
        return builder.add({
            instruction: createSetCollectionInstruction({
                candyMachine: candyMachine.publicKey,
                authority: toPublicKey(authority),
                collectionPda,
                payer: payer.publicKey,
                metadata,
                mint: collectionMint,
                edition,
                collectionAuthorityRecord,
                tokenMetadataProgram: metaplex.programs().getTokenMetadata()
                    .address,
            }),
            signers: [authority],
            key: (_a = params.setCollectionInstructionKey) !== null && _a !== void 0 ? _a : 'setCollection',
        });
    }));
});
//# sourceMappingURL=createCandyMachineV2.js.map