"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.publishBatch = publishBatch;
const ethers_1 = require("ethers");
const logger_1 = require("../../ts/logger");
const types_1 = require("./types");
/**
 * Utility function to send a batch of messages to a poll contract
 * @dev This function will attempt to send a batch of messages to a poll contract
 * and if it fails, it will attempt to send a smaller batch size
 * @param deployment - The deployment instance
 * @param message - The message to send
 * @param keypair - The keypair to sign the message with
 * @param batchSize - The number of messages to send
 */
async function publishBatch(deployment, message, keypair, batchSize) {
    // then try and publish a large batch of votes
    const maciContract = await deployment.getContract({
        name: types_1.EContracts.MACI,
    });
    const lastPollId = (await maciContract.nextPollId()) - 1n;
    const pollContract = await deployment.getContract({
        name: types_1.EContracts.Poll,
        key: `poll-${lastPollId}`,
    });
    const messageBatch = Array.from({ length: batchSize }, () => message.asContractParam());
    const publicKeyBatch = Array.from({ length: batchSize }, () => keypair.publicKey.asContractParam());
    const deployer = await deployment.getDeployer();
    let optimalBatchSize = batchSize;
    let multiplier = 1;
    while (optimalBatchSize > 0) {
        const finalMessageBatch = messageBatch.slice(0, optimalBatchSize);
        const finalPublicKeyBatch = publicKeyBatch.slice(0, optimalBatchSize);
        try {
            // eslint-disable-next-line no-await-in-loop
            const [feeData, nonce, gasLimit] = await Promise.all([
                deployer.provider?.getFeeData(),
                deployer.provider?.getTransactionCount(deployer),
                pollContract.publishMessageBatch.estimateGas(finalMessageBatch, finalPublicKeyBatch),
            ]);
            // eslint-disable-next-line no-await-in-loop
            const tx = await pollContract.publishMessageBatch(finalMessageBatch, finalPublicKeyBatch, {
                gasPrice: feeData?.gasPrice && !feeData.maxFeePerGas ? Number(feeData.gasPrice) * multiplier : undefined,
                maxFeePerGas: feeData?.maxFeePerGas ? Number(feeData.maxFeePerGas) * multiplier : undefined,
                maxPriorityFeePerGas: feeData?.maxPriorityFeePerGas
                    ? Number(feeData.maxPriorityFeePerGas) * multiplier
                    : undefined,
                nonce,
                gasLimit,
            });
            const twoMinutesTimeout = 1000 * 60 * 2;
            // eslint-disable-next-line no-await-in-loop
            const receipt = await Promise.race([
                tx.wait(),
                new Promise((_, reject) => {
                    const timeout = setTimeout(() => {
                        reject(new Error("Timeout error"));
                        clearTimeout(timeout);
                    }, twoMinutesTimeout);
                }),
            ]);
            if (receipt instanceof ethers_1.TransactionReceipt) {
                (0, logger_1.logGreen)({ text: (0, logger_1.success)(`Successfully published batch of ${optimalBatchSize} messages`) });
                (0, logger_1.logGreen)({ text: (0, logger_1.success)(`Gas used: ${receipt.gasUsed.toString()} wei`) });
                (0, logger_1.logGreen)({ text: (0, logger_1.success)(`Tx: ${tx.hash}`) });
                break; // If successful, we've found the largest working batch size
            }
            else {
                throw new Error("Invalid receipt");
            }
        }
        catch (err) {
            // If this size doesn't work, reduce by 1 and try again
            optimalBatchSize -= 1;
            multiplier += 1;
        }
    }
    if (optimalBatchSize > 0) {
        (0, logger_1.logGreen)({ text: (0, logger_1.success)(`Found optimal batch size: ${optimalBatchSize}`) });
    }
    else {
        (0, logger_1.logRed)({ text: (0, logger_1.error)("Unable to publish even a single message") });
    }
}
//# sourceMappingURL=benchmarks.js.map