"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
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());
    });
};
var __asyncValues = (this && this.__asyncValues) || function (o) {
    if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
    var m = o[Symbol.asyncIterator], i;
    return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
    function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
    function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.OfferMixin = void 0;
const base_core_sdk_1 = require("./../mixins/base-core-sdk");
const erc20 = __importStar(require("../erc20"));
const erc721 = __importStar(require("../erc721"));
const erc1155 = __importStar(require("../erc1155"));
const offers = __importStar(require("."));
const accounts = __importStar(require("../accounts"));
const orchestration = __importStar(require("../orchestration"));
const groups = __importStar(require("../groups"));
const common_1 = require("@bosonprotocol/common");
const groupBy_1 = __importDefault(require("lodash/groupBy"));
const bignumber_1 = require("@ethersproject/bignumber");
const logs_1 = require("../utils/logs");
const tokenInfoManager_1 = require("../utils/tokenInfoManager");
const promises_1 = require("../utils/promises");
class OfferMixin extends base_core_sdk_1.BaseCoreSDK {
    // Implementation
    createOffer(offerToCreate_1) {
        return __awaiter(this, arguments, void 0, function* (offerToCreate, overrides = {}) {
            const { returnTxInfo } = overrides;
            const offerArgs = {
                offerToCreate,
                web3Lib: this._web3Lib,
                theGraphStorage: this._theGraphStorage,
                metadataStorage: this._metadataStorage,
                subgraphUrl: this._subgraphUrl,
                contractAddress: overrides.contractAddress || this._protocolDiamond,
                txRequest: overrides.txRequest
            };
            if (returnTxInfo === true) {
                return offers.handler.createOffer(Object.assign(Object.assign({}, offerArgs), { returnTxInfo: true }));
            }
            else {
                return offers.handler.createOffer(Object.assign(Object.assign({}, offerArgs), { returnTxInfo: false }));
            }
        });
    }
    // Implementation
    createOfferBatch(offersToCreate_1) {
        return __awaiter(this, arguments, void 0, function* (offersToCreate, overrides = {}) {
            const { returnTxInfo } = overrides;
            const batchArgs = {
                offersToCreate,
                web3Lib: this._web3Lib,
                theGraphStorage: this._theGraphStorage,
                metadataStorage: this._metadataStorage,
                contractAddress: overrides.contractAddress || this._protocolDiamond
            };
            if (returnTxInfo === true) {
                return offers.handler.createOfferBatch(Object.assign(Object.assign({}, batchArgs), { returnTxInfo: true }));
            }
            else {
                return offers.handler.createOfferBatch(Object.assign(Object.assign({}, batchArgs), { returnTxInfo: false }));
            }
        });
    }
    /**
     * Utility method to retrieve the created `offerId` from logs after calling `createOffer`
     * or `createOfferAndSeller`.
     * @param logs - Logs to search in.
     * @returns Created offer id.
     */
    getCreatedOfferIdFromLogs(logs) {
        var _a;
        const offerId = (0, logs_1.getValueFromLogs)({
            iface: offers.iface.bosonOfferHandlerIface,
            logs,
            eventArgsKey: "offerId",
            eventName: "OfferCreated"
        });
        return (_a = (offerId ||
            (0, logs_1.getValueFromLogs)({
                iface: orchestration.iface.bosonOrchestrationHandlerIface,
                logs,
                eventArgsKey: "offerId",
                eventName: "OfferCreated"
            }))) === null || _a === void 0 ? void 0 : _a.toString();
    }
    /**
     * Utility method to retrieve the created `offerIds` from logs after calling `createOfferBatch`
     * @param logs - Logs to search in.
     * @returns Array of created offerIds.
     */
    getCreatedOfferIdsFromLogs(logs) {
        return (0, logs_1.getValuesFromLogs)({
            iface: offers.iface.bosonOfferHandlerIface,
            logs,
            eventArgsKey: "offerId",
            eventName: "OfferCreated"
        }).map((o) => o.toString());
    }
    /**
     * Utility method to retrieve the created `groupIds` from logs after calling `createGroup`
     * @param logs - Logs to search in.
     * @returns Array of group Ids.
     */
    getCreatedGroupIdsFromLogs(logs) {
        return (0, logs_1.getValuesFromLogs)({
            iface: groups.iface.bosonGroupHandlerIface,
            logs,
            eventArgsKey: "groupId",
            eventName: "GroupCreated"
        }).map((g) => g.toString());
    }
    /**
     * Utility method to retrieve the created `sellerId` from logs after calling `createSeller`
     * or `createOfferAndSeller`.
     * @param logs - Logs to search in.
     * @returns Created offer id.
     */
    getCreatedSellerIdFromLogs(logs) {
        var _a;
        const sellerId = (0, logs_1.getValueFromLogs)({
            iface: accounts.iface.bosonAccountHandlerIface,
            logs,
            eventArgsKey: "sellerId",
            eventName: "SellerCreated"
        });
        return (_a = (sellerId ||
            (0, logs_1.getValueFromLogs)({
                iface: orchestration.iface.bosonOrchestrationHandlerIface,
                logs,
                eventArgsKey: "sellerId",
                eventName: "SellerCreated"
            }))) === null || _a === void 0 ? void 0 : _a.toString();
    }
    /**
     * Utility method to retrieve the created `buyerId` from logs after calling `createBuyer`
     *
     * @param logs - Logs to search in.
     * @returns Created buyer id.
     */
    getCreatedBuyerIdFromLogs(logs) {
        var _a;
        const buyerId = (0, logs_1.getValueFromLogs)({
            iface: accounts.iface.bosonAccountHandlerIface,
            logs,
            eventArgsKey: "buyerId",
            eventName: "BuyerCreated"
        });
        return (_a = (buyerId ||
            (0, logs_1.getValueFromLogs)({
                iface: orchestration.iface.bosonOrchestrationHandlerIface,
                logs,
                eventArgsKey: "buyerId",
                eventName: "BuyerCreated"
            }))) === null || _a === void 0 ? void 0 : _a.toString();
    }
    // Implementation
    voidOffer(offerId_1) {
        return __awaiter(this, arguments, void 0, function* (offerId, overrides = {}) {
            const { returnTxInfo } = overrides;
            const voidArgs = {
                offerId,
                web3Lib: this._web3Lib,
                subgraphUrl: this._subgraphUrl,
                contractAddress: overrides.contractAddress || this._protocolDiamond
            };
            if (returnTxInfo === true) {
                return offers.handler.voidOffer(Object.assign(Object.assign({}, voidArgs), { returnTxInfo: true }));
            }
            else {
                return offers.handler.voidOffer(Object.assign(Object.assign({}, voidArgs), { returnTxInfo: false }));
            }
        });
    }
    // Implementation
    voidOfferBatch(offerIds_1) {
        return __awaiter(this, arguments, void 0, function* (offerIds, overrides = {}) {
            const { returnTxInfo } = overrides;
            const batchArgs = {
                offerIds,
                web3Lib: this._web3Lib,
                subgraphUrl: this._subgraphUrl,
                contractAddress: overrides.contractAddress || this._protocolDiamond
            };
            if (returnTxInfo === true) {
                return offers.handler.voidOfferBatch(Object.assign(Object.assign({}, batchArgs), { returnTxInfo: true }));
            }
            else {
                return offers.handler.voidOfferBatch(Object.assign(Object.assign({}, batchArgs), { returnTxInfo: false }));
            }
        });
    }
    // Implementation
    voidNonListedOffer(fullOffer_1) {
        return __awaiter(this, arguments, void 0, function* (fullOffer, overrides = {}) {
            const { returnTxInfo } = overrides;
            const voidArgs = {
                fullOffer,
                web3Lib: this._web3Lib,
                subgraphUrl: this._subgraphUrl,
                contractAddress: overrides.contractAddress || this._protocolDiamond
            };
            if (returnTxInfo === true) {
                return offers.handler.voidNonListedOffer(Object.assign(Object.assign({}, voidArgs), { returnTxInfo: true }));
            }
            else {
                return offers.handler.voidNonListedOffer(Object.assign(Object.assign({}, voidArgs), { returnTxInfo: false }));
            }
        });
    }
    // Implementation
    voidNonListedOfferBatch(fullOffers_1) {
        return __awaiter(this, arguments, void 0, function* (fullOffers, overrides = {}) {
            const { returnTxInfo } = overrides;
            const voidArgs = {
                fullOffers,
                web3Lib: this._web3Lib,
                subgraphUrl: this._subgraphUrl,
                contractAddress: overrides.contractAddress || this._protocolDiamond
            };
            if (returnTxInfo === true) {
                return offers.handler.voidNonListedOfferBatch(Object.assign(Object.assign({}, voidArgs), { returnTxInfo: true }));
            }
            else {
                return offers.handler.voidNonListedOfferBatch(Object.assign(Object.assign({}, voidArgs), { returnTxInfo: false }));
            }
        });
    }
    // Implementation
    extendOffer(offerId_1, validUntil_1) {
        return __awaiter(this, arguments, void 0, function* (offerId, validUntil, overrides = {}) {
            const { returnTxInfo } = overrides;
            const extendArgs = {
                offerId,
                validUntil,
                web3Lib: this._web3Lib,
                subgraphUrl: this._subgraphUrl,
                contractAddress: overrides.contractAddress || this._protocolDiamond
            };
            if (returnTxInfo === true) {
                return offers.handler.extendOffer(Object.assign(Object.assign({}, extendArgs), { returnTxInfo: true }));
            }
            else {
                return offers.handler.extendOffer(Object.assign(Object.assign({}, extendArgs), { returnTxInfo: false }));
            }
        });
    }
    // Implementation
    extendOfferBatch(offerIds_1, validUntil_1) {
        return __awaiter(this, arguments, void 0, function* (offerIds, validUntil, overrides = {}) {
            const { returnTxInfo } = overrides;
            const batchArgs = {
                offerIds,
                validUntil,
                web3Lib: this._web3Lib,
                subgraphUrl: this._subgraphUrl,
                contractAddress: overrides.contractAddress || this._protocolDiamond
            };
            if (returnTxInfo === true) {
                return offers.handler.extendOfferBatch(Object.assign(Object.assign({}, batchArgs), { returnTxInfo: true }));
            }
            else {
                return offers.handler.extendOfferBatch(Object.assign(Object.assign({}, batchArgs), { returnTxInfo: false }));
            }
        });
    }
    /**
     * Returns offer from subgraph.
     * @param offerId - ID of offer.
     * @param queryVars - Optional query variables to skip, order or filter.
     * @returns Offer entity from subgraph.
     */
    getOfferById(offerId, queryVars) {
        return __awaiter(this, void 0, void 0, function* () {
            return offers.subgraph.getOfferById(this._subgraphUrl, offerId, queryVars);
        });
    }
    /**
     * Returns offers from subgraph.
     * @param queryVars - Optional query variables to skip, order or filter.
     * @returns Offer entities from subgraph.
     */
    getOffers(queryVars) {
        return __awaiter(this, void 0, void 0, function* () {
            return offers.subgraph.getOffers(this._subgraphUrl, queryVars);
        });
    }
    /**
     * Renders contractual agreement for given offer.
     * @param offerId - Id of offer to render agreement for.
     * @returns Contractual agreement as string.
     */
    renderContractualAgreementForOffer(offerId) {
        return __awaiter(this, void 0, void 0, function* () {
            const offerData = yield offers.subgraph.getOfferById(this._subgraphUrl, offerId);
            return offers.renderContractualAgreementForOffer(offerData);
        });
    }
    /**
     * Renders contractual agreement for given offer.
     * @param template - Mustache syntax based template.
     * @param offerData - Offer data.
     * @returns Contractual agreement as string.
     */
    renderContractualAgreement(template, offerData, offerMetadata) {
        return __awaiter(this, void 0, void 0, function* () {
            const tokenInfo = yield this.getExchangeTokenInfo(offerData.exchangeToken);
            return offers.renderContractualAgreement(template, offerData, offerMetadata, tokenInfo);
        });
    }
    // Implementation
    reserveRange(offerId_1, length_1, to_1) {
        return __awaiter(this, arguments, void 0, function* (offerId, length, to, overrides = {}) {
            const { returnTxInfo } = overrides;
            const offer = yield this.getOfferById(offerId);
            const reserveArgs = {
                offerId,
                length,
                to: to === "contract"
                    ? offer.seller.voucherCloneAddress
                    : offer.seller.assistant,
                subgraphUrl: this._subgraphUrl,
                contractAddress: overrides.contractAddress || this._protocolDiamond,
                web3Lib: this._web3Lib
            };
            if (returnTxInfo === true) {
                return offers.handler.reserveRange(Object.assign(Object.assign({}, reserveArgs), { returnTxInfo: true }));
            }
            else {
                return offers.handler.reserveRange(Object.assign(Object.assign({}, reserveArgs), { returnTxInfo: false }));
            }
        });
    }
    /* -------------------------------------------------------------------------- */
    /*                   ERC20 / Exchange Token related methods                   */
    /* -------------------------------------------------------------------------- */
    /**
     * Returns the current allowance of the given token by calling the contract.
     * @param exchangeToken - Address of exchange token.
     * @param overrides - Optional overrides.
     * @returns Allowance for given signer.
     */
    getExchangeTokenAllowance(exchangeToken_1) {
        return __awaiter(this, arguments, void 0, function* (exchangeToken, overrides = {}) {
            return erc20.handler.getAllowance({
                web3Lib: this._web3Lib,
                contractAddress: exchangeToken,
                spender: overrides.spender || this._protocolDiamond,
                owner: overrides.owner || (yield this._web3Lib.getSignerAddress())
            });
        });
    }
    /**
     * Returns `name`, `decimals` and `symbol` of the given token by calling the contract.
     * @param exchangeToken - Address exchange token.
     * @returns Decimals, name and symbol.
     */
    getExchangeTokenInfo(exchangeToken) {
        return __awaiter(this, void 0, void 0, function* () {
            if (this._tokenInfoManager === undefined) {
                this._tokenInfoManager = new tokenInfoManager_1.TokenInfoManager(this._chainId, this._web3Lib, this._subgraphUrl);
            }
            return this._tokenInfoManager.getExchangeTokenInfo(exchangeToken);
        });
    }
    // Implementation
    approveExchangeToken(exchangeToken_1, value_1) {
        return __awaiter(this, arguments, void 0, function* (exchangeToken, value, overrides = {}) {
            const { returnTxInfo } = overrides;
            const approveArgs = {
                contractAddress: exchangeToken,
                spender: overrides.spender || this._protocolDiamond,
                value,
                web3Lib: this._web3Lib
            };
            if (returnTxInfo === true) {
                return erc20.handler.approve(Object.assign(Object.assign({}, approveArgs), { returnTxInfo: true }));
            }
            else {
                return erc20.handler.approve(Object.assign(Object.assign({}, approveArgs), { returnTxInfo: false }));
            }
        });
    }
    getProtocolAllowance(exchangeToken_1) {
        return __awaiter(this, arguments, void 0, function* (exchangeToken, overrides = {}) {
            return erc20.handler.getAllowance({
                contractAddress: exchangeToken,
                owner: overrides.owner || (yield this._web3Lib.getSignerAddress()),
                spender: overrides.spender || this._protocolDiamond,
                web3Lib: this._web3Lib
            });
        });
    }
    checkTokenGatedCondition(offerId, buyerAddress) {
        return __awaiter(this, void 0, void 0, function* () {
            var _a, e_1, _b, _c, _d, e_2, _e, _f, _g, e_3, _h, _j, _k, e_4, _l, _m;
            const offer = yield this.getOfferById(offerId);
            if (!(offer === null || offer === void 0 ? void 0 : offer.condition)) {
                return true;
            }
            const offerConditionId = offer.condition.id;
            const getCanTokenIdBeUsedToCommit = () => __awaiter(this, void 0, void 0, function* () {
                const conditionalCommitLogs = yield this.getConditionalCommitAuthorizedEventLogs({
                    conditionalCommitAuthorizedLogsFilter: {
                        groupId: offerConditionId, // all offers of the same product have the same condition.id
                        buyerAddress
                    }
                });
                const tokenIdMapWithMultipleEntries = (0, groupBy_1.default)(conditionalCommitLogs, (log) => log.tokenId);
                // build a map of tokenId -> log with the min available commits (or the most recent log) in all the logs
                const tokenIdToAvailableCommitsMap = new Map();
                Object.entries(tokenIdMapWithMultipleEntries).forEach(([tokenId, logs]) => {
                    let logWithMinAvailableCommits = logs[0];
                    for (const log of logs) {
                        const currentAvailableCommits = Number(log.maxCommits) - Number(log.commitCount);
                        const savedAvailableCommits = Number(logWithMinAvailableCommits.maxCommits) -
                            Number(logWithMinAvailableCommits.commitCount);
                        if (currentAvailableCommits < savedAvailableCommits) {
                            logWithMinAvailableCommits = log;
                        }
                    }
                    tokenIdToAvailableCommitsMap.set(tokenId, logWithMinAvailableCommits);
                });
                const canTokenIdBeUsedToCommit = (tokenId) => {
                    if (!tokenIdToAvailableCommitsMap.has(tokenId)) {
                        return true;
                    }
                    const log = tokenIdToAvailableCommitsMap.get(tokenId);
                    if (!log) {
                        return true;
                    }
                    return Number(log.maxCommits) - Number(log.commitCount) > 0;
                };
                return canTokenIdBeUsedToCommit;
            });
            const getCurrentCommits = () => __awaiter(this, void 0, void 0, function* () {
                var _a, _b;
                const buyers = yield this.getBuyers({
                    buyersFilter: {
                        wallet: buyerAddress
                    },
                    includeExchanges: true,
                    exchangesFilter: {
                        offer_: {
                            condition: offerConditionId
                        }
                    }
                });
                const [buyer] = buyers !== null && buyers !== void 0 ? buyers : [];
                return (_b = (_a = buyer === null || buyer === void 0 ? void 0 : buyer.exchanges) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
            });
            const concurrencyLimit = 5;
            const { minTokenId: _minTokenId, maxTokenId: _maxTokenId, tokenType, threshold, method, tokenAddress, gatingType, maxCommits: _maxCommits } = offer.condition;
            const minTokenId = BigInt(_minTokenId);
            const maxTokenId = BigInt(_maxTokenId);
            const returnTrueBecauseItCannotBeChecked = () => {
                const maxRequestsThreshold = 10;
                if (minTokenId > maxTokenId) {
                    return true; // leave the smart contract check this
                }
                if (maxTokenId - minTokenId > maxRequestsThreshold) {
                    return true; // leave the smart contract check this
                }
            };
            const maxCommits = Number(_maxCommits);
            if (tokenType === common_1.TokenType.FungibleToken) {
                const balance = yield erc20.handler.balanceOf({
                    contractAddress: tokenAddress,
                    owner: buyerAddress,
                    web3Lib: this._web3Lib
                });
                if (!bignumber_1.BigNumber.from(balance).gte(threshold)) {
                    return false;
                }
                const currentCommits = yield getCurrentCommits();
                return currentCommits < maxCommits;
            }
            if (tokenType === common_1.TokenType.NonFungibleToken) {
                if (gatingType === common_1.GatingType.PerAddress) {
                    if (method === common_1.EvaluationMethod.Threshold) {
                        const balance = yield erc721.handler.balanceOf({
                            contractAddress: tokenAddress,
                            owner: buyerAddress,
                            web3Lib: this._web3Lib
                        });
                        if (!bignumber_1.BigNumber.from(balance).gte(threshold)) {
                            return false;
                        }
                        const currentCommits = yield getCurrentCommits();
                        return currentCommits < maxCommits;
                    }
                    if (method === common_1.EvaluationMethod.TokenRange) {
                        if (returnTrueBecauseItCannotBeChecked()) {
                            return true;
                        }
                        const promises = [];
                        for (let i = minTokenId; i <= maxTokenId; i++) {
                            const tokenId = i;
                            promises.push(() => erc721.handler.ownerOf({
                                contractAddress: tokenAddress,
                                tokenId,
                                web3Lib: this._web3Lib
                            }));
                        }
                        const currentCommits = yield getCurrentCommits();
                        try {
                            for (var _o = true, _p = __asyncValues((0, promises_1.batchTasks)(promises, concurrencyLimit)), _q; _q = yield _p.next(), _a = _q.done, !_a; _o = true) {
                                _c = _q.value;
                                _o = false;
                                const owners = _c;
                                if (owners.some((owner) => owner === buyerAddress)) {
                                    return currentCommits < maxCommits;
                                }
                            }
                        }
                        catch (e_1_1) { e_1 = { error: e_1_1 }; }
                        finally {
                            try {
                                if (!_o && !_a && (_b = _p.return)) yield _b.call(_p);
                            }
                            finally { if (e_1) throw e_1.error; }
                        }
                        return false;
                    }
                    throw new Error(`Unsupported method=${method} for this tokenType=${tokenType} and gatingType=${gatingType}`);
                }
                if (gatingType === common_1.GatingType.PerTokenId) {
                    if (method === common_1.EvaluationMethod.TokenRange) {
                        if (returnTrueBecauseItCannotBeChecked()) {
                            return true;
                        }
                        const canTokenIdBeUsedToCommit = yield getCanTokenIdBeUsedToCommit();
                        const promises = [];
                        for (let i = minTokenId; i <= maxTokenId; i++) {
                            const tokenId = i;
                            promises.push(() => erc721.handler.ownerOf({
                                contractAddress: tokenAddress,
                                tokenId,
                                web3Lib: this._web3Lib
                            }));
                        }
                        let tokenId = minTokenId;
                        try {
                            for (var _r = true, _s = __asyncValues((0, promises_1.batchTasks)(promises, concurrencyLimit)), _t; _t = yield _s.next(), _d = _t.done, !_d; _r = true) {
                                _f = _t.value;
                                _r = false;
                                const owners = _f;
                                if (owners.some((owner) => owner === buyerAddress) &&
                                    canTokenIdBeUsedToCommit(tokenId.toString())) {
                                    return true;
                                }
                                tokenId++;
                            }
                        }
                        catch (e_2_1) { e_2 = { error: e_2_1 }; }
                        finally {
                            try {
                                if (!_r && !_d && (_e = _s.return)) yield _e.call(_s);
                            }
                            finally { if (e_2) throw e_2.error; }
                        }
                        return false;
                    }
                    throw new Error(`Unsupported method=${method} for this tokenType=${tokenType} and gatingType=${gatingType}`);
                }
                throw new Error(`Unsupported gatingType=${gatingType} for this tokenType=${tokenType}`);
            }
            if (tokenType === common_1.TokenType.MultiToken) {
                if (gatingType === common_1.GatingType.PerAddress) {
                    if (returnTrueBecauseItCannotBeChecked()) {
                        return true;
                    }
                    const promises = [];
                    for (let i = minTokenId; i <= maxTokenId; i++) {
                        const tokenId = i;
                        promises.push(() => erc1155.handler.balanceOf({
                            contractAddress: tokenAddress,
                            tokenId,
                            owner: buyerAddress,
                            web3Lib: this._web3Lib
                        }));
                    }
                    try {
                        for (var _u = true, _v = __asyncValues((0, promises_1.batchTasks)(promises, concurrencyLimit)), _w; _w = yield _v.next(), _g = _w.done, !_g; _u = true) {
                            _j = _w.value;
                            _u = false;
                            const balances = _j;
                            if (balances.some((balance) => bignumber_1.BigNumber.from(balance).gte(threshold))) {
                                return true;
                            }
                        }
                    }
                    catch (e_3_1) { e_3 = { error: e_3_1 }; }
                    finally {
                        try {
                            if (!_u && !_g && (_h = _v.return)) yield _h.call(_v);
                        }
                        finally { if (e_3) throw e_3.error; }
                    }
                    return false;
                }
                if (gatingType === common_1.GatingType.PerTokenId) {
                    if (returnTrueBecauseItCannotBeChecked()) {
                        return true;
                    }
                    const canTokenIdBeUsedToCommit = yield getCanTokenIdBeUsedToCommit();
                    const promises = [];
                    for (let i = minTokenId; i <= maxTokenId; i++) {
                        const tokenId = i;
                        promises.push(() => erc1155.handler.balanceOf({
                            contractAddress: tokenAddress,
                            tokenId,
                            owner: buyerAddress,
                            web3Lib: this._web3Lib
                        }));
                    }
                    let tokenId = minTokenId;
                    try {
                        for (var _x = true, _y = __asyncValues((0, promises_1.batchTasks)(promises, concurrencyLimit)), _z; _z = yield _y.next(), _k = _z.done, !_k; _x = true) {
                            _m = _z.value;
                            _x = false;
                            const balances = _m;
                            if (balances.some((balance) => bignumber_1.BigNumber.from(balance).gte(threshold)) &&
                                canTokenIdBeUsedToCommit(tokenId.toString())) {
                                return true;
                            }
                            tokenId++;
                        }
                    }
                    catch (e_4_1) { e_4 = { error: e_4_1 }; }
                    finally {
                        try {
                            if (!_x && !_k && (_l = _y.return)) yield _l.call(_y);
                        }
                        finally { if (e_4) throw e_4.error; }
                    }
                    return false;
                }
                throw new Error(`Unsupported gatingType=${gatingType} for this tokenType=${tokenType}`);
            }
            throw new Error(`Unsupported tokenType=${tokenType}`);
        });
    }
    /**
     * Check a given offer meets ExchangePolicy rules.
     * @param offerId - Id of offer to render agreement for.
     * @returns Contractual agreement as string.
     */
    checkExchangePolicy(offerId, rules) {
        return __awaiter(this, void 0, void 0, function* () {
            const offerData = yield offers.subgraph.getOfferById(this._subgraphUrl, offerId);
            return offers.checkExchangePolicy(offerData, rules);
        });
    }
    // Implementation
    updateOfferRoyaltyRecipients(offerId_1, royaltyInfo_1) {
        return __awaiter(this, arguments, void 0, function* (offerId, royaltyInfo, overrides = {}) {
            const { returnTxInfo } = overrides;
            const royaltyArgs = {
                offerId,
                royaltyInfo,
                web3Lib: this._web3Lib,
                contractAddress: overrides.contractAddress || this._protocolDiamond
            };
            if (returnTxInfo === true) {
                return offers.handler.updateOfferRoyaltyRecipients(Object.assign(Object.assign({}, royaltyArgs), { returnTxInfo: true }));
            }
            else {
                return offers.handler.updateOfferRoyaltyRecipients(Object.assign(Object.assign({}, royaltyArgs), { returnTxInfo: false }));
            }
        });
    }
    // Implementation
    updateOfferRoyaltyRecipientsBatch(offerIds_1, royaltyInfo_1) {
        return __awaiter(this, arguments, void 0, function* (offerIds, royaltyInfo, overrides = {}) {
            const { returnTxInfo } = overrides;
            const batchArgs = {
                offerIds,
                royaltyInfo,
                web3Lib: this._web3Lib,
                contractAddress: overrides.contractAddress || this._protocolDiamond
            };
            if (returnTxInfo === true) {
                return offers.handler.updateOfferRoyaltyRecipientsBatch(Object.assign(Object.assign({}, batchArgs), { returnTxInfo: true }));
            }
            else {
                return offers.handler.updateOfferRoyaltyRecipientsBatch(Object.assign(Object.assign({}, batchArgs), { returnTxInfo: false }));
            }
        });
    }
    getOfferHash(fullOfferArgsUnsigned_1) {
        return __awaiter(this, arguments, void 0, function* (fullOfferArgsUnsigned, overrides = {}) {
            return offers.handler.getOfferHash({
                fullOfferArgsUnsigned,
                web3Lib: this._web3Lib,
                contractAddress: overrides.contractAddress || this._protocolDiamond
            });
        });
    }
}
exports.OfferMixin = OfferMixin;
//# sourceMappingURL=mixin.js.map