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 { toCandyGuard, toCandyMachine } from '../models';
import { assertCandyGuardProgram } from '../programs';
import { assertAccountExists, PublicKey, } from '../../../types';
// -----------------
// Operation
// -----------------
const Key = 'FindCandyMachineByAddressOperation';
/**
 * Find an existing Candy Machine by its address.
 *
 * ```ts
 * const candyMachine = await metaplex
 *   .candyMachines()
 *   .findbyAddress({ address };
 * ```
 *
 * @group Operations
 * @category Constructors
 */
export const findCandyMachineByAddressOperation = _findCandyMachineByAddressOperation;
// eslint-disable-next-line @typescript-eslint/naming-convention
function _findCandyMachineByAddressOperation(input) {
    return { key: Key, input };
}
_findCandyMachineByAddressOperation.key = Key;
/**
 * @group Operations
 * @category Handlers
 */
export const findCandyMachineByAddressOperationHandler = {
    handle(operation, metaplex, scope) {
        return __awaiter(this, void 0, void 0, function* () {
            const { address } = operation.input;
            const { commitment, programs } = scope;
            const potentialCandyGuardAddress = metaplex
                .candyMachines()
                .pdas()
                .candyGuard({ base: address, programs });
            const [candyMachineAccount, potentialCandyGuardAccount] = yield metaplex
                .rpc()
                .getMultipleAccounts([address, potentialCandyGuardAddress], commitment);
            scope.throwIfCanceled();
            assertAccountExists(candyMachineAccount, 'CandyMachine');
            const candyMachine = toCandyMachine(candyMachineAccount);
            const mintAuthority = candyMachine.mintAuthorityAddress;
            // Optimisation that tries to load both the Candy Machine
            // And the Candy Guard in one RPC call assuming the Candy
            // Machine's address is the base address of the Candy Guard.
            if (potentialCandyGuardAccount.exists &&
                potentialCandyGuardAccount.publicKey.equals(mintAuthority)) {
                return Object.assign(Object.assign({}, candyMachine), { candyGuard: toCandyGuard(potentialCandyGuardAccount, metaplex) });
            }
            // If the Candy Machine's mint authority is not a PDA,
            // it cannot have an associated Candy Guard.
            if (PublicKey.isOnCurve(mintAuthority)) {
                return candyMachine;
            }
            // Fetch the content of the mint authority PDA.
            const mintAuthorityAccount = yield metaplex
                .rpc()
                .getAccount(mintAuthority, commitment);
            scope.throwIfCanceled();
            try {
                // Identity the program owner as a Candy Guard program
                // and parse the Candy Guard accordingly.
                assertAccountExists(mintAuthorityAccount);
                const program = metaplex.programs().get(mintAuthorityAccount.owner);
                assertCandyGuardProgram(program);
                return Object.assign(Object.assign({}, candyMachine), { candyGuard: toCandyGuard(mintAuthorityAccount, metaplex) });
            }
            catch (error) {
                // If anything goes wrong, assume there is no Candy Guard
                // attached to this Candy Machine.
                return candyMachine;
            }
        });
    },
};
//# sourceMappingURL=findCandyMachineByAddress.js.map