import { BN } from "@coral-xyz/anchor";
import { ethers } from "ethers";
import { serialize } from "borsh";
/**
 * Calculates the relay hash from relay data and chain ID.
 */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function calculateRelayHashUint8Array(relayData, chainId) {
    var contentToHash = Buffer.concat([
        relayData.depositor.toBuffer(),
        relayData.recipient.toBuffer(),
        relayData.exclusiveRelayer.toBuffer(),
        relayData.inputToken.toBuffer(),
        relayData.outputToken.toBuffer(),
        Buffer.from(relayData.inputAmount),
        relayData.outputAmount.toArrayLike(Buffer, "le", 8),
        relayData.originChainId.toArrayLike(Buffer, "le", 8),
        Buffer.from(relayData.depositId),
        new BN(relayData.fillDeadline).toArrayLike(Buffer, "le", 4),
        new BN(relayData.exclusivityDeadline).toArrayLike(Buffer, "le", 4),
        hashNonEmptyMessage(relayData.message), // Replace with hash of message, so that relay hash can be recovered from event.
        chainId.toArrayLike(Buffer, "le", 8),
    ]);
    var relayHash = ethers.utils.keccak256(contentToHash);
    var relayHashBuffer = Buffer.from(relayHash.slice(2), "hex");
    return new Uint8Array(relayHashBuffer);
}
/**
 * Calculates the relay event hash from relay event data and chain ID.
 */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function calculateRelayEventHashUint8Array(relayEventData, chainId) {
    var contentToHash = Buffer.concat([
        relayEventData.depositor.toBuffer(),
        relayEventData.recipient.toBuffer(),
        relayEventData.exclusiveRelayer.toBuffer(),
        relayEventData.inputToken.toBuffer(),
        relayEventData.outputToken.toBuffer(),
        Buffer.from(relayEventData.inputAmount),
        relayEventData.outputAmount.toArrayLike(Buffer, "le", 8),
        relayEventData.originChainId.toArrayLike(Buffer, "le", 8),
        Buffer.from(relayEventData.depositId),
        new BN(relayEventData.fillDeadline).toArrayLike(Buffer, "le", 4),
        new BN(relayEventData.exclusivityDeadline).toArrayLike(Buffer, "le", 4),
        Buffer.from(relayEventData.messageHash), // Renamed to messageHash in the event data.
        chainId.toArrayLike(Buffer, "le", 8),
    ]);
    var relayHash = ethers.utils.keccak256(contentToHash);
    var relayHashBuffer = Buffer.from(relayHash.slice(2), "hex");
    return new Uint8Array(relayHashBuffer);
}
/**
 * Reads a 256-bit unsigned integer from a buffer.
 */
export var readUInt256BE = function (buffer) {
    var result = BigInt(0);
    for (var i = 0; i < buffer.length; i++) {
        result = (result << BigInt(8)) + BigInt(buffer[i]);
    }
    return result;
};
/**
 * Hashes a non-empty message using Keccak256.
 */
export function hashNonEmptyMessage(message) {
    if (message.length > 0) {
        var hash = ethers.utils.keccak256(message);
        return Uint8Array.from(Buffer.from(hash.slice(2), "hex"));
    }
    // else return zeroed bytes32
    return new Uint8Array(32);
}
/**
 * Class for relay data.
 */
var RelayData = /** @class */ (function () {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    function RelayData(properties) {
        Object.assign(this, properties);
    }
    return RelayData;
}());
/**
 * Schema for relay data.
 */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
var relayDataSchema = new Map([
    [
        RelayData,
        {
            kind: "struct",
            fields: [
                ["amountToReturn", "u64"],
                ["chainId", "u64"],
                ["refundAmounts", ["u64"]],
                ["leafId", "u32"],
                ["mintPublicKey", [32]],
                ["refundAddresses", [[32]]],
            ],
        },
    ],
]);
/**
 * Calculates the relayer refund leaf hash for Solana.
 */
export function calculateRelayerRefundLeafHashUint8Array(relayData) {
    var refundAddresses = relayData.refundAddresses.map(function (address) { return address.toBuffer(); });
    var data = new RelayData({
        amountToReturn: relayData.amountToReturn,
        chainId: relayData.chainId,
        refundAmounts: relayData.refundAmounts,
        leafId: relayData.leafId,
        mintPublicKey: relayData.mintPublicKey.toBuffer(),
        refundAddresses: refundAddresses,
    });
    var serializedData = serialize(relayDataSchema, data);
    // SVM leaves require the first 64 bytes to be 0 to ensure EVM leaves can never be played on SVM and vice versa.
    var contentToHash = Buffer.concat([Buffer.alloc(64, 0), serializedData]);
    return ethers.utils.keccak256(contentToHash);
}
/**
 * Hash function for relayer refund leaves.
 */
export var relayerRefundHashFn = function (input) {
    if (!input.isSolana) {
        var abiCoder = new ethers.utils.AbiCoder();
        var encodedData = abiCoder.encode([
            "tuple( uint256 amountToReturn, uint256 chainId, uint256[] refundAmounts, uint256 leafId, address l2TokenAddress, address[] refundAddresses)",
        ], [
            {
                leafId: input.leafId,
                chainId: input.chainId,
                amountToReturn: input.amountToReturn,
                l2TokenAddress: input.l2TokenAddress, // Type assertion
                refundAddresses: input.refundAddresses, // Type assertion
                refundAmounts: input.refundAmounts, // Type assertion
            },
        ]);
        return ethers.utils.keccak256(encodedData);
    }
    else {
        return calculateRelayerRefundLeafHashUint8Array(input);
    }
};
/**
 * Class for slow fill data.
 */
var SlowFillData = /** @class */ (function () {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    function SlowFillData(properties) {
        Object.assign(this, properties);
    }
    return SlowFillData;
}());
/**
 * Schema for slow fill data.
 */
// eslint-disable-next-line @typescript-eslint/no-explicit-any
var slowFillDataSchema = new Map([
    [
        SlowFillData,
        {
            kind: "struct",
            fields: [
                ["depositor", [32]],
                ["recipient", [32]],
                ["exclusiveRelayer", [32]],
                ["inputToken", [32]],
                ["outputToken", [32]],
                ["inputAmount", [32]],
                ["outputAmount", "u64"],
                ["originChainId", "u64"],
                ["depositId", [32]],
                ["fillDeadline", "u32"],
                ["exclusivityDeadline", "u32"],
                ["message", ["u8"]],
                ["chainId", "u64"],
                ["updatedOutputAmount", "u64"],
            ],
        },
    ],
]);
/**
 * Hash function for slow fill leaves.
 */
export function slowFillHashFn(slowFillLeaf) {
    var data = new SlowFillData({
        depositor: Uint8Array.from(slowFillLeaf.relayData.depositor.toBuffer()),
        recipient: Uint8Array.from(slowFillLeaf.relayData.recipient.toBuffer()),
        exclusiveRelayer: Uint8Array.from(slowFillLeaf.relayData.exclusiveRelayer.toBuffer()),
        inputToken: Uint8Array.from(slowFillLeaf.relayData.inputToken.toBuffer()),
        outputToken: Uint8Array.from(slowFillLeaf.relayData.outputToken.toBuffer()),
        inputAmount: slowFillLeaf.relayData.inputAmount,
        outputAmount: slowFillLeaf.relayData.outputAmount,
        originChainId: slowFillLeaf.relayData.originChainId,
        depositId: Uint8Array.from(Buffer.from(slowFillLeaf.relayData.depositId)),
        fillDeadline: slowFillLeaf.relayData.fillDeadline,
        exclusivityDeadline: slowFillLeaf.relayData.exclusivityDeadline,
        message: Uint8Array.from(slowFillLeaf.relayData.message),
        chainId: slowFillLeaf.chainId,
        updatedOutputAmount: slowFillLeaf.updatedOutputAmount,
    });
    var serializedData = serialize(slowFillDataSchema, data);
    // SVM leaves require the first 64 bytes to be 0 to ensure EVM leaves cannot be played on SVM and vice versa
    var contentToHash = Buffer.concat([Buffer.alloc(64, 0), serializedData]);
    return ethers.utils.keccak256(contentToHash);
}
//# sourceMappingURL=relayHashUtils.js.map