"use strict";
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());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.INITIAL_COLLECTION_ID = void 0;
exports.findCollectionSalt = findCollectionSalt;
exports.createSeller = createSeller;
exports.updateSeller = updateSeller;
exports.optInToSellerUpdate = optInToSellerUpdate;
exports.createBuyer = createBuyer;
exports.createDisputeResolver = createDisputeResolver;
exports.addFeesToDisputeResolver = addFeesToDisputeResolver;
exports.addSellersToAllowList = addSellersToAllowList;
exports.removeFeesFromDisputeResolver = removeFeesFromDisputeResolver;
exports.removeSellersFromAllowList = removeSellersFromAllowList;
exports.updateDisputeResolver = updateDisputeResolver;
exports.optInToDisputeResolverUpdate = optInToDisputeResolverUpdate;
exports.createNewCollection = createNewCollection;
exports.isSellerSaltAvailable = isSellerSaltAvailable;
exports.calculateCollectionAddress = calculateCollectionAddress;
exports.addRoyaltyRecipients = addRoyaltyRecipients;
exports.updateRoyaltyRecipients = updateRoyaltyRecipients;
exports.removeRoyaltyRecipients = removeRoyaltyRecipients;
exports.getRoyaltyRecipients = getRoyaltyRecipients;
const common_1 = require("@bosonprotocol/common");
const strings_1 = require("@ethersproject/strings");
const interface_1 = require("./interface");
const subgraph_1 = require("./subgraph");
const storage_1 = require("../offers/storage");
exports.INITIAL_COLLECTION_ID = "initial";
function findCollectionSalt(args) {
    return __awaiter(this, void 0, void 0, function* () {
        // collectionSalt is added to the seller admin address to give the sellerSalt that is used to compute the voucher contract address
        // The seller creation will fail in case sellerSalt already exists
        // This may happen if the admin address was already assigned to another seller in the past
        // In that case, we add a random suffix on the collectionId to generate a different salt
        let collectionSalt = (0, strings_1.formatBytes32String)(exports.INITIAL_COLLECTION_ID);
        const isAvailable = yield isSellerSaltAvailable({
            adminAddress: args.sellerToCreate.admin,
            salt: collectionSalt,
            contractAddress: args.contractAddress,
            web3Lib: args.web3Lib
        });
        if (!isAvailable) {
            const uuid = Math.floor(Math.random() * 100000000).toFixed(0);
            collectionSalt = (0, strings_1.formatBytes32String)(`${exports.INITIAL_COLLECTION_ID}-${uuid}`.slice(0, 31));
        }
        return collectionSalt;
    });
}
// Implementation
function createSeller(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const collectionSalt = yield findCollectionSalt(args);
        yield Promise.all([args.sellerToCreate.contractUri, args.sellerToCreate.metadataUri].map((metadataUri) => (0, storage_1.storeMetadataOnTheGraph)({
            metadataUriOrHash: metadataUri,
            metadataStorage: args.metadataStorage,
            theGraphStorage: args.theGraphStorage
        })));
        const transactionRequest = {
            to: args.contractAddress,
            data: (0, interface_1.encodeCreateSeller)(args.sellerToCreate, collectionSalt)
        };
        if (args.returnTxInfo) {
            return transactionRequest;
        }
        else {
            return args.web3Lib.sendTransaction(transactionRequest);
        }
    });
}
// Implementation
function updateSeller(args) {
    return __awaiter(this, void 0, void 0, function* () {
        yield (0, storage_1.storeMetadataOnTheGraph)({
            metadataUriOrHash: args.sellerUpdates.metadataUri,
            metadataStorage: args.metadataStorage,
            theGraphStorage: args.theGraphStorage
        });
        const transactionRequest = {
            to: args.contractAddress,
            data: (0, interface_1.encodeUpdateSeller)(args.sellerUpdates)
        };
        if (args.returnTxInfo) {
            return transactionRequest;
        }
        else {
            return args.web3Lib.sendTransaction(transactionRequest);
        }
    });
}
// Implementation
function optInToSellerUpdate(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const transactionRequest = {
            to: args.contractAddress,
            data: (0, interface_1.encodeOptInToSellerUpdate)(args.sellerUpdates)
        };
        if (args.returnTxInfo) {
            return transactionRequest;
        }
        else {
            return args.web3Lib.sendTransaction(transactionRequest);
        }
    });
}
// Implementation
function createBuyer(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const transactionRequest = {
            to: args.contractAddress,
            data: (0, interface_1.encodeCreateBuyer)(args.buyerToCreate)
        };
        if (args.returnTxInfo) {
            return transactionRequest;
        }
        else {
            return args.web3Lib.sendTransaction(transactionRequest);
        }
    });
}
// Implementation
function createDisputeResolver(args) {
    return __awaiter(this, void 0, void 0, function* () {
        // TODO: validate metadata
        // disputeResolverToCreate.metadataUri
        const transactionRequest = {
            to: args.contractAddress,
            data: (0, interface_1.encodeCreateDisputeResolver)(args.disputeResolverToCreate)
        };
        if (args.returnTxInfo) {
            return transactionRequest;
        }
        else {
            return args.web3Lib.sendTransaction(transactionRequest);
        }
    });
}
// Implementation
function addFeesToDisputeResolver(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const transactionRequest = {
            to: args.contractAddress,
            data: (0, interface_1.encodeAddFeesToDisputeResolver)(args)
        };
        if (args.returnTxInfo) {
            return transactionRequest;
        }
        else {
            return args.web3Lib.sendTransaction(transactionRequest);
        }
    });
}
// Implementation
function addSellersToAllowList(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const transactionRequest = {
            to: args.contractAddress,
            data: (0, interface_1.encodeAddSellersToAllowList)(args)
        };
        if (args.returnTxInfo) {
            return transactionRequest;
        }
        else {
            return args.web3Lib.sendTransaction(transactionRequest);
        }
    });
}
// Implementation
function removeFeesFromDisputeResolver(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const transactionRequest = {
            to: args.contractAddress,
            data: (0, interface_1.encodeRemoveFeesFromDisputeResolver)(args)
        };
        if (args.returnTxInfo) {
            return transactionRequest;
        }
        else {
            return args.web3Lib.sendTransaction(transactionRequest);
        }
    });
}
// Implementation
function removeSellersFromAllowList(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const transactionRequest = {
            to: args.contractAddress,
            data: (0, interface_1.encodeRemoveSellersFromAllowList)(args)
        };
        if (args.returnTxInfo) {
            return transactionRequest;
        }
        else {
            return args.web3Lib.sendTransaction(transactionRequest);
        }
    });
}
// Implementation
function updateDisputeResolver(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const disputeResolver = yield (0, subgraph_1.getDisputeResolverById)(args.subgraphUrl, args.disputeResolverId);
        assertDisputeResolver(args.disputeResolverId, disputeResolver);
        // TODO: validate metadata
        // updates.metadataUri
        const transactionRequest = {
            to: args.contractAddress,
            data: (0, interface_1.encodeUpdateDisputeResolver)(Object.assign(Object.assign(Object.assign({}, disputeResolver), args.updates), { escalationResponsePeriod: args.updates.escalationResponsePeriodInMS
                    ? common_1.utils.timestamp.msToSec(args.updates.escalationResponsePeriodInMS)
                    : disputeResolver.escalationResponsePeriod }))
        };
        if (args.returnTxInfo) {
            return transactionRequest;
        }
        else {
            return args.web3Lib.sendTransaction(transactionRequest);
        }
    });
}
// Implementation
function optInToDisputeResolverUpdate(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const transactionRequest = {
            to: args.contractAddress,
            data: (0, interface_1.encodeOptInToDisputeResolverUpdate)(args.disputeResolverUpdates)
        };
        if (args.returnTxInfo) {
            return transactionRequest;
        }
        else {
            return args.web3Lib.sendTransaction(transactionRequest);
        }
    });
}
function assertDisputeResolver(disputeResolverId, disputeResolver) {
    if (!disputeResolver) {
        throw new Error(`Dispute resolver with id ${disputeResolverId} does not exist`);
    }
}
// Implementation
function createNewCollection(args) {
    return __awaiter(this, void 0, void 0, function* () {
        // call calculateCollectionAddress() to check no collection with the same collectionId already exists
        if (args.collectionToCreate.sellerId) {
            const { isAvailable } = yield calculateCollectionAddress({
                sellerId: args.collectionToCreate.sellerId,
                collectionId: args.collectionToCreate.collectionId,
                contractAddress: args.contractAddress,
                web3Lib: args.web3Lib
            });
            if (!isAvailable) {
                throw new Error(`CollectionId '${args.collectionToCreate.collectionId}' is not available for seller '${args.collectionToCreate.sellerId}'`);
            }
        }
        yield (0, storage_1.storeMetadataOnTheGraph)({
            metadataUriOrHash: args.collectionToCreate.contractUri,
            metadataStorage: args.metadataStorage,
            theGraphStorage: args.theGraphStorage
        });
        const transactionRequest = {
            to: args.contractAddress,
            data: (0, interface_1.encodeCreateNewCollection)(args.collectionToCreate)
        };
        if (args.returnTxInfo) {
            return transactionRequest;
        }
        else {
            return args.web3Lib.sendTransaction(transactionRequest);
        }
    });
}
function isSellerSaltAvailable(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const result = yield args.web3Lib.call({
            to: args.contractAddress,
            data: (0, interface_1.encodeIsSellerSaltAvailable)(args.adminAddress, args.salt)
        });
        return (0, interface_1.decodeIsSellerSaltAvailable)(result);
    });
}
function calculateCollectionAddress(args) {
    return __awaiter(this, void 0, void 0, function* () {
        if (args.collectionId.length >= 32) {
            throw new Error(`collectionId length should not exceed 31 characters`);
        }
        const collectionSalt = (0, strings_1.formatBytes32String)(args.collectionId);
        const result = yield args.web3Lib.call({
            to: args.contractAddress,
            data: (0, interface_1.encodeCalculateCollectionAddress)(args.sellerId, collectionSalt)
        });
        return (0, interface_1.decodeCalculateCollectionAddress)(result);
    });
}
// Implementation
function addRoyaltyRecipients(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const transactionRequest = {
            to: args.contractAddress,
            data: (0, interface_1.encodeAddRoyaltyRecipients)(args)
        };
        if (args.returnTxInfo) {
            return transactionRequest;
        }
        else {
            return args.web3Lib.sendTransaction(transactionRequest);
        }
    });
}
// Implementation
function updateRoyaltyRecipients(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const transactionRequest = {
            to: args.contractAddress,
            data: (0, interface_1.encodeUpdateRoyaltyRecipients)(args)
        };
        if (args.returnTxInfo) {
            return transactionRequest;
        }
        else {
            return args.web3Lib.sendTransaction(transactionRequest);
        }
    });
}
// Implementation
function removeRoyaltyRecipients(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const transactionRequest = {
            to: args.contractAddress,
            data: (0, interface_1.encodeRemoveRoyaltyRecipients)(args)
        };
        if (args.returnTxInfo) {
            return transactionRequest;
        }
        else {
            return args.web3Lib.sendTransaction(transactionRequest);
        }
    });
}
function getRoyaltyRecipients(args) {
    return __awaiter(this, void 0, void 0, function* () {
        const result = yield args.web3Lib.call({
            to: args.contractAddress,
            data: (0, interface_1.encodeGetRoyaltyRecipients)(args)
        });
        return (0, interface_1.decodeGetRoyaltyRecipients)(result);
    });
}
//# sourceMappingURL=handler.js.map