"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GmpPayload = void 0;
const ethers_1 = require("ethers");
const logger_1 = require("../utils/logger");
class GmpPayload {
    static async deriveAllCommitmentsOfAccountOutOfBatchPayload(encodedBatchPayload, account, dynamo) {
        try {
            const batch = this.decodeBatchFromPackedWithRawGMPMessage(encodedBatchPayload);
            if (!batch) {
                return [];
            }
            const decodedPayload = this.decodeGMPPayload(batch.encodedGMPPayload);
            const orderIdsOfAccount = [];
            for (const message of decodedPayload) {
                if (message.messageType === 0 && (account == ethers_1.ethers.constants.AddressZero || message.beneficiary === account)) {
                    const order = await dynamo.fetchDBOrder(message.orderId, 'deriveAllCommitmentsOfAccountOutOfBatchPayload');
                    if (order) {
                        orderIdsOfAccount.push(order);
                    }
                }
            }
            return orderIdsOfAccount;
        }
        catch (error) {
            logger_1.logger.error({ error: error.message, account }, 'Failed to derive all commitments of account out of batch payload');
            return [];
        }
    }
    static deriveAllRevertedOrdersOutOfBatchPayload(encodedBatchPayload) {
        const result = [];
        const batch = this.decodeBatchFromPackedWithRawGMPMessage(encodedBatchPayload);
        if (!batch) {
            return [];
        }
        const decodedPayload = this.decodeGMPPayload(batch.encodedGMPPayload);
        for (const message of decodedPayload) {
            if (message.messageType === 1) {
                result.push(message.orderId);
            }
        }
        return result;
    }
    static decodeBatchFromPackedWithRawGMPMessage(encoded) {
        try {
            const decoded = ethers_1.ethers.utils.defaultAbiCoder.decode(['bool', 'bytes32', 'bytes32', 'address[]', 'address[]', 'bytes', 'uint32'], encoded);
            return {
                isHalted: decoded[0],
                currentCommitteeHash: decoded[1],
                nextCommitteeHash: decoded[2],
                maybeNextCommittee: decoded[3],
                bannedCommittee: decoded[4],
                encodedGMPPayload: decoded[5],
                index: decoded[6],
                encodedBatchPayload: encoded,
            };
        }
        catch (error) {
            logger_1.logger.error({ error: error.message, encoded }, 'Failed to decode batch from packed with raw GMP message with defaultAbiCoder.decode');
            return null;
        }
    }
    static createBatchPreamble(isHalted, currentCommitteeHash, nextCommitteeHash, encodedGMPPayload, index) {
        try {
            return ethers_1.ethers.utils.defaultAbiCoder.encode(['bool', 'bytes32', 'bytes32', 'address[]', 'address[]', 'bytes', 'uint32'], [isHalted, currentCommitteeHash, nextCommitteeHash, [], [], encodedGMPPayload, index]);
        }
        catch (error) {
            logger_1.logger.error({ error: error.message, currentCommitteeHash, isHalted, nextCommitteeHash, index }, 'Failed to encode batch pre-amble with defaultAbiCoder.encode');
            return '0x';
        }
    }
    static decodeGMPPayload(encodedGMPPayload) {
        const decodedGMPPayload = [];
        try {
            // Ensure the encodedGMPPayload has an even length
            if (encodedGMPPayload.length % 2 !== 0) {
                encodedGMPPayload = '0x0' + encodedGMPPayload.slice(2);
            }
            let offset = 2; // Start after the '0x' prefix
            let chunkLength = 0; // 1 byte for uint8 + 32 bytes for bytes32 + 20 bytes for address (total 66 bytes, or 132 hex chars)
            let chunk = '';
            let messageIndex = 0;
            while (offset < encodedGMPPayload.length) {
                const remainingLength = encodedGMPPayload.length - offset;
                if (remainingLength < 1) {
                    break; // Exit the loop if the remaining length is less than the required chunk length
                }
                const nextByte = encodedGMPPayload.slice(offset, offset + 2);
                if (nextByte == '05') {
                    chunkLength = 66 + 20 * 2 + 20 * 2 + 32 * 2 + 32 * 2 + 4 * 2 * 3; // 66 bytes for messageType, orderId, beneficiary + 20 bytes for each of the 7 openMarketArgs
                }
                else if (nextByte == '01') {
                    chunkLength = 66;
                }
                else if (nextByte == '00') {
                    chunkLength = 106;
                }
                chunk = encodedGMPPayload.slice(offset, offset + chunkLength);
                let messageTypeHex = '';
                let orderIdHex = '';
                let beneficiaryHex = '';
                let beneficiary = ethers_1.ethers.constants.AddressZero;
                let openMarketArgs = [];
                try {
                    messageTypeHex = '0x' + chunk.slice(0, 2);
                    const messageType = ethers_1.ethers.BigNumber.from(messageTypeHex).toNumber();
                    orderIdHex = '0x' + chunk.slice(2, 66);
                    const orderId = ethers_1.ethers.utils.hexlify(orderIdHex);
                    if (messageType == 0 || messageType == 5) {
                        beneficiaryHex = '0x' + chunk.slice(66, 106);
                        beneficiary = ethers_1.ethers.utils.getAddress(beneficiaryHex);
                    }
                    openMarketArgs = [];
                    // If GMP=0x05 Open Market Type
                    if (messageType == 5) {
                        const openMarketChunkLength = 20 * 2 + 20 * 2 + 32 * 2 + 32 * 2 + 4 * 2 * 3; // sender, reward asset, max reward, amount, assetId, reward assetId, nonce
                        const openMarketArgsBytesHex = encodedGMPPayload.slice(offset + chunkLength, offset + chunkLength + openMarketChunkLength);
                        const sender = ethers_1.ethers.utils.getAddress('0x' + openMarketArgsBytesHex.slice(0, 40));
                        const rewardAsset = ethers_1.ethers.utils.getAddress('0x' + openMarketArgsBytesHex.slice(40, 80));
                        const maxReward = ethers_1.ethers.BigNumber.from('0x' + openMarketArgsBytesHex.slice(80, 112)).toString();
                        const amount = ethers_1.ethers.BigNumber.from('0x' + openMarketArgsBytesHex.slice(112, 144)).toString();
                        const assetId = ethers_1.ethers.BigNumber.from('0x' + openMarketArgsBytesHex.slice(144, 152)).toString();
                        const rewardAssetId = ethers_1.ethers.BigNumber.from('0x' + openMarketArgsBytesHex.slice(152, 160)).toString();
                        const nonce = ethers_1.ethers.BigNumber.from('0x' + openMarketArgsBytesHex.slice(160, 168)).toString();
                        openMarketArgs.push(sender, rewardAsset, maxReward, amount, assetId, rewardAssetId, nonce);
                        offset += openMarketChunkLength; // Move to the next 66-byte chunk, 2 hex chars per byte
                    }
                    decodedGMPPayload.push({ messageType, orderId, beneficiary, openMarketArgs });
                }
                catch (decodeError) {
                    logger_1.logger.error({
                        chunk,
                        messageIndex,
                        encodedGMPPayload,
                        messageTypeHex,
                        orderIdHex,
                        beneficiaryHex,
                        openMarketArgs,
                        error: decodeError.message,
                    }, '➖ Error while decoding the GMP payload chunk');
                }
                offset += chunkLength; // Move to the next 66-byte chunk, 2 hex chars per byte
                messageIndex += 1;
            }
            return decodedGMPPayload;
        }
        catch (error) {
            logger_1.logger.error({
                error: error.message,
                encodedGMPPayload: encodedGMPPayload,
            }, `➖ Error while slicing the GMP payload`);
            return decodedGMPPayload;
        }
    }
}
exports.GmpPayload = GmpPayload;
//# sourceMappingURL=gmpPayload.js.map