"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isSlowFill = isSlowFill;
exports.getSlowFillLeafLpFeePct = getSlowFillLeafLpFeePct;
exports.unpackDepositEvent = unpackDepositEvent;
exports.unpackFillEvent = unpackFillEvent;
exports.getRelayDataHash = getRelayDataHash;
exports.getRelayHashFromEvent = getRelayHashFromEvent;
exports.isUnsafeDepositId = isUnsafeDepositId;
exports.getMessageHash = getMessageHash;
exports.findInvalidFills = findInvalidFills;
const viem_1 = require("viem");
const common_1 = require("./common");
const constants_1 = require("../constants");
const interfaces_1 = require("../interfaces");
const arch_1 = require("../arch");
const BigNumberUtils_1 = require("./BigNumberUtils");
const DepositUtils_1 = require("./DepositUtils");
const NetworkUtils_1 = require("./NetworkUtils");
const AddressUtils_1 = require("./AddressUtils");
function isSlowFill(fill) {
    return fill.relayExecutionInfo.fillType === interfaces_1.FillType.SlowFill;
}
function getSlowFillLeafLpFeePct(leaf) {
    const { relayData, updatedOutputAmount } = leaf;
    return relayData.inputAmount.sub(updatedOutputAmount).mul(common_1.fixedPointAdjustment).div(relayData.inputAmount);
}
function unpackDepositEvent(rawEvent, originChainId) {
    const event = rawEvent;
    return {
        ...event,
        originChainId,
        depositor: (0, AddressUtils_1.toAddressType)(event.depositor, originChainId),
        recipient: (0, AddressUtils_1.toAddressType)(event.recipient, event.destinationChainId),
        inputToken: (0, AddressUtils_1.toAddressType)(event.inputToken, originChainId),
        outputToken: (0, AddressUtils_1.toAddressType)(event.outputToken, event.destinationChainId),
        exclusiveRelayer: (0, AddressUtils_1.toAddressType)(event.exclusiveRelayer, event.destinationChainId),
        messageHash: getMessageHash(event.message),
    };
}
function unpackFillEvent(rawEvent, destinationChainId) {
    const event = rawEvent;
    return {
        ...event,
        destinationChainId,
        depositor: (0, AddressUtils_1.toAddressType)(event.depositor, event.originChainId),
        recipient: (0, AddressUtils_1.toAddressType)(event.recipient, destinationChainId),
        inputToken: (0, AddressUtils_1.toAddressType)(event.inputToken, event.originChainId),
        outputToken: (0, AddressUtils_1.toAddressType)(event.outputToken, destinationChainId),
        exclusiveRelayer: (0, AddressUtils_1.toAddressType)(event.exclusiveRelayer, destinationChainId),
        relayer: (0, AddressUtils_1.toAddressType)(event.relayer, event.repaymentChainId),
        relayExecutionInfo: {
            ...event.relayExecutionInfo,
            updatedRecipient: (0, AddressUtils_1.toAddressType)(event.relayExecutionInfo.updatedRecipient, destinationChainId),
        },
    };
}
const RELAYDATA_ABI = [
    {
        type: "tuple",
        components: [
            { type: "bytes32", name: "depositor" },
            { type: "bytes32", name: "recipient" },
            { type: "bytes32", name: "exclusiveRelayer" },
            { type: "bytes32", name: "inputToken" },
            { type: "bytes32", name: "outputToken" },
            { type: "uint256", name: "inputAmount" },
            { type: "uint256", name: "outputAmount" },
            { type: "uint256", name: "originChainId" },
            { type: "uint256", name: "depositId" },
            { type: "uint32", name: "fillDeadline" },
            { type: "uint32", name: "exclusivityDeadline" },
            { type: "bytes", name: "message" },
        ],
    },
    { type: "uint256", name: "destinationChainId" },
];
function getRelayDataHash(relayData, destinationChainId) {
    if ((0, NetworkUtils_1.chainIsSvm)(destinationChainId)) {
        const messageHash = getMessageHash(relayData.message);
        return arch_1.svm.getRelayDataHash({ ...relayData, messageHash }, destinationChainId);
    }
    const _relayData = {
        ...relayData,
        depositor: relayData.depositor.toBytes32(),
        recipient: relayData.recipient.toBytes32(),
        inputToken: relayData.inputToken.toBytes32(),
        outputToken: relayData.outputToken.toBytes32(),
        exclusiveRelayer: relayData.exclusiveRelayer.toBytes32(),
    };
    return (0, viem_1.keccak256)((0, viem_1.encodeAbiParameters)(RELAYDATA_ABI, [_relayData, destinationChainId]));
}
function getRelayHashFromEvent(e) {
    return getRelayDataHash(e, e.destinationChainId);
}
function isUnsafeDepositId(depositId) {
    const maxSafeDepositId = BigNumberUtils_1.BigNumber.from(constants_1.MAX_SAFE_DEPOSIT_ID);
    return maxSafeDepositId.lt(depositId);
}
function getMessageHash(message) {
    return (0, DepositUtils_1.isMessageEmpty)(message) ? constants_1.ZERO_BYTES : (0, viem_1.keccak256)(message);
}
async function findInvalidFills(spokePoolClients) {
    const invalidFills = [];
    for (const spokePoolClient of Object.values(spokePoolClients)) {
        const fills = spokePoolClient.getFills();
        const fillDepositPairs = await Promise.all(fills.map(async (fill) => {
            if (isUnsafeDepositId(fill.depositId)) {
                return null;
            }
            const depositResult = await spokePoolClients[fill.originChainId]?.findDeposit(fill.depositId);
            if (!depositResult?.found) {
                return {
                    fill,
                    deposit: null,
                    reason: `No ${(0, NetworkUtils_1.getNetworkName)(fill.originChainId)} deposit with depositId ${fill.depositId} found`,
                };
            }
            const validationResult = (0, DepositUtils_1.validateFillForDeposit)(fill, depositResult.deposit);
            if (!validationResult.valid) {
                return {
                    fill,
                    deposit: depositResult.deposit,
                    reason: validationResult.reason,
                };
            }
            return null;
        }));
        for (const pair of fillDepositPairs) {
            if (pair) {
                invalidFills.push({
                    fill: pair.fill,
                    reason: pair.reason,
                    deposit: pair.deposit || undefined,
                });
            }
        }
    }
    return invalidFills;
}
//# sourceMappingURL=SpokeUtils.js.map