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 { Disposable } from '../../utils';
import { OperationHandlerMissingError } from '../../errors';
/**
 * @group Modules
 */
export class OperationClient {
    constructor(metaplex) {
        this.metaplex = metaplex;
        /**
         * Maps the name of an operation with its operation handler.
         * Whilst the types on the Map are relatively loose, we ensure
         * operations match with their handlers when registering them.
         */
        this.operationHandlers = new Map();
    }
    register(operationConstructor, operationHandler) {
        this.operationHandlers.set(operationConstructor.key, operationHandler);
        return this;
    }
    get(operation) {
        const operationHandler = this.operationHandlers.get(operation.key);
        if (!operationHandler) {
            throw new OperationHandlerMissingError(operation.key);
        }
        return operationHandler;
    }
    execute(operation, options = {}) {
        var _a;
        return __awaiter(this, void 0, void 0, function* () {
            const operationHandler = this.get(operation);
            const signal = (_a = options.signal) !== null && _a !== void 0 ? _a : new AbortController().signal;
            return new Disposable(signal).run((scope) => operationHandler.handle(operation, this.metaplex, this.getOperationScope(options, scope)));
        });
    }
    getOperationScope(options, scope) {
        var _a;
        if (!!options.commitment && !options.confirmOptions) {
            options.confirmOptions = { commitment: options.commitment };
        }
        const payer = (_a = options.payer) !== null && _a !== void 0 ? _a : this.metaplex.rpc().getDefaultFeePayer();
        return Object.assign(Object.assign(Object.assign({}, options), scope), { payer });
    }
}
//# sourceMappingURL=OperationClient.js.map