"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.processPendingExecutions = processPendingExecutions;
const logger_1 = require("../../utils/logger");
const helpers_1 = require("../../utils/helpers");
/**
 * Processes orders that have been bid on but not executed.
 * Only processes orders belonging to the current executor.
 */
async function processPendingExecutions(executor, _asBatch = true) {
    const config = executor.getConfig();
    const pricerApi = executor.getPricerApi();
    const orderService = executor.getOrderService();
    const transmitter = executor.getTransmitter();
    const arbitrageStrategies = executor.getArbitrageStrategies();
    const myAddress = executor.getMyAddress();
    logger_1.logger.info('🔃 Start processing Pending Executions');
    const sleepSec = executor.getPendingExecutionsInterval();
    while (true) {
        const enabledNetworksIds = executor.getEnabledNetworksIds();
        if (enabledNetworksIds.length === 0) {
            logger_1.logger.error('🚫 No networks enabled for executor. Exiting.');
            break;
        }
        let ordersPopulated;
        try {
            ordersPopulated = await pricerApi.fetchExecutorPendingExecutions(myAddress);
        }
        catch {
            await (0, helpers_1.sleep)(sleepSec, `Sleep between processing Pending Executions`);
            continue;
        }
        if (ordersPopulated.length === 0) {
            logger_1.logger.debug({ executor: myAddress, sleepSec }, '🔃 No pending Executions found');
            await (0, helpers_1.sleep)(sleepSec, `Sleep between processing pending Executions`);
            continue;
        }
        const orders = ordersPopulated.filter((order) => order !== null);
        // Filter out all non-executable by
        const executableOrdersFlags = orders.map((order) => {
            const balance = executor.getBalance(order.destination, order.destinationAssetCode);
            return orderService.isOrderExecutable(order, balance, arbitrageStrategies);
        });
        // Filter out all non-executable orders
        const executableOrders = orders.filter((_order, index) => executableOrdersFlags[index]);
        if (executableOrders.length === 0) {
            (0, logger_1.batchLogger)({ executor: myAddress }, '🔃 No pending Executions found', 60);
        }
        logger_1.logger.info({
            count: orders.length,
            executor: myAddress,
            executableOrders: executableOrders.map((o) => o.id).join(', '),
            notExecutableOrders: orders.length - executableOrders.length,
        }, '🚰️🏆 Processing pending Executions');
        // Group by destination network
        const ordersMapByDestination = executableOrders.reduce((acc, order) => {
            const destination = order.destination;
            if (!acc[destination]) {
                acc[destination] = [];
            }
            // Check if enabledNetworksIds includes the destination network
            if (!enabledNetworksIds.includes(destination)) {
                return acc;
            }
            acc[destination].push(order);
            return acc;
        }, {});
        // For each network process call transmitExecuteBatch per destination
        for (const destination in ordersMapByDestination) {
            const orders = ordersMapByDestination[destination];
            const transmitterInstance = transmitter.get(destination);
            if (!transmitterInstance) {
                logger_1.logger.fatal({ destination, executor }, `🚨 Transmitter instance not found for network`);
                continue;
            }
            if (config.executor.processPendingExecutions.batch) {
                const MAX_BATCH_SIZE = 30;
                for (let i = 0; i < orders.length; i += MAX_BATCH_SIZE) {
                    const batch = orders.slice(i, i + MAX_BATCH_SIZE);
                    transmitterInstance.transmitExecuteBatch(batch);
                }
            }
            else {
                for (const order of orders) {
                    transmitterInstance.transmitExecute(order);
                }
            }
        }
        await (0, helpers_1.sleep)(sleepSec, `Sleep between processing pending Executions`);
    }
}
//# sourceMappingURL=pendingExecutions.js.map