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 { PublicKey } from '@solarti/web3.js';
import { parseCandyMachineV2Account, parseCandyMachineV2CollectionAccount, } from '../accounts';
import { toCandyMachineV2 } from '../models';
import { findCandyMachineV2CollectionPda } from '../pdas';
import { CandyMachineV2Program } from '../program';
import { zipMap } from '../../../utils';
import { useOperation, } from '../../../types';
import { toMint, toMintAccount } from '../../../plugins/tokenModule';
import { UnreachableCaseError } from '../../../errors';
// -----------------
// Operation
// -----------------
const Key = 'FindCandyMachinesV2ByPublicKeyOperation';
/**
 * Find all Candy Machines matching by a given `publicKey` or a given `type`.
 *
 * The following two types are supported.
 *
 * `authority`: Find Candy Machines whose authority is the given `publicKey`.
 * ```ts
 * const someAuthority = new PublicKey('...');
 * const candyMachines = await metaplex
 *   .candyMachinesV2()
 *   .findAllBy({ type: 'authority', someAuthority });
 * ```
 *
 * `wallet`: Find Candy Machines whose wallet address is the given `publicKey`.
 * ```ts
 * const someWallet = new PublicKey('...');
 * const candyMachines = await metaplex
 *   .candyMachinesV2()
 *   .findAllBy({ type: 'wallet', someWallet });
 * ```
 *
 * @group Operations
 * @category Constructors
 */
export const findCandyMachinesV2ByPublicKeyFieldOperation = useOperation(Key);
/**
 * @group Operations
 * @category Handlers
 */
export const findCandyMachinesV2ByPublicKeyFieldOperationHandler = {
    handle: (operation, metaplex, scope) => __awaiter(void 0, void 0, void 0, function* () {
        const { commitment } = scope;
        const { type, publicKey } = operation.input;
        const accounts = CandyMachineV2Program.accounts(metaplex).mergeConfig({
            commitment,
        });
        let candyMachineQuery;
        switch (type) {
            case 'authority':
                candyMachineQuery =
                    accounts.candyMachineAccountsForAuthority(publicKey);
                break;
            case 'wallet':
                candyMachineQuery = accounts.candyMachineAccountsForWallet(publicKey);
                break;
            default:
                throw new UnreachableCaseError(type);
        }
        const unparsedAccounts = yield candyMachineQuery.get();
        scope.throwIfCanceled();
        const collectionPdas = unparsedAccounts.map((unparsedAccount) => findCandyMachineV2CollectionPda(unparsedAccount.publicKey));
        // Find mint details for all unique SPL tokens used
        // in candy machines that have non-null `tokenMint`
        const parsedAccounts = Object.fromEntries(unparsedAccounts.map((unparsedAccount) => [
            unparsedAccount.publicKey.toString(),
            parseCandyMachineV2Account(unparsedAccount),
        ]));
        const tokenMints = [
            ...new Set(Object.values(parsedAccounts)
                .map((account) => { var _a; return (_a = account.data.tokenMint) === null || _a === void 0 ? void 0 : _a.toString(); })
                .filter((tokenMint) => tokenMint !== undefined)),
        ].map((address) => new PublicKey(address));
        const result = yield metaplex
            .rpc()
            .getMultipleAccounts(tokenMints.concat(collectionPdas), commitment);
        scope.throwIfCanceled();
        const unparsedMintAccounts = result.slice(0, tokenMints.length);
        const unparsedCollectionAccounts = result.slice(-collectionPdas.length);
        const mints = Object.fromEntries(unparsedMintAccounts.map((account) => [
            account.publicKey.toString(),
            toMint(toMintAccount(account)),
        ]));
        return zipMap(unparsedAccounts, unparsedCollectionAccounts, (unparsedAccount, unparsedCollectionAccount) => {
            var _a;
            const parsedAccount = parsedAccounts[unparsedAccount.publicKey.toString()];
            const collectionAccount = unparsedCollectionAccount
                ? parseCandyMachineV2CollectionAccount(unparsedCollectionAccount)
                : null;
            const tokenMintAddress = (_a = parsedAccount.data.tokenMint) === null || _a === void 0 ? void 0 : _a.toString();
            return toCandyMachineV2(parsedAccount, unparsedAccount, collectionAccount, tokenMintAddress ? mints[tokenMintAddress] : null);
        });
    }),
};
//# sourceMappingURL=findCandyMachinesV2ByPublicKeyField.js.map