"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getParamType = getParamType;
exports.buildRelayerRefundTree = buildRelayerRefundTree;
exports.buildRelayerRefundLeaves = buildRelayerRefundLeaves;
exports.buildPoolRebalanceLeafTree = buildPoolRebalanceLeafTree;
exports.buildPoolRebalanceLeaves = buildPoolRebalanceLeaves;
exports.buildSlowRelayTree = buildSlowRelayTree;
exports.buildV3SlowRelayTree = buildV3SlowRelayTree;
exports.constructSingleRelayerRefundTree = constructSingleRelayerRefundTree;
exports.constructSingleChainTree = constructSingleChainTree;
const ethers_1 = require("ethers");
const getContractFactory_1 = require("./getContractFactory");
const MerkleTree_1 = require("@across-protocol/contracts/dist/utils/MerkleTree");
const chai_1 = require("chai");
const constants_1 = require("../constants");
const { keccak256, defaultAbiCoder } = ethers_1.ethers.utils;
async function getParamType(contractName, functionName, paramName) {
    const contractFactory = await (0, getContractFactory_1.getContractFactory)(contractName, new ethers_1.ethers.VoidSigner(ethers_1.ethers.constants.AddressZero));
    const fragment = contractFactory.interface.fragments.find((fragment) => fragment.name === functionName);
    if (!fragment || fragment.type !== "function") {
        return "";
    }
    const functionFragment = fragment;
    return functionFragment.inputs.find((input) => input.name === paramName) || "";
}
async function buildRelayerRefundTree(relayerRefundLeaves) {
    for (let i = 0; i < relayerRefundLeaves.length; i++) {
        (0, chai_1.expect)(relayerRefundLeaves[i].refundAddresses.length).to.equal(relayerRefundLeaves[i].refundAmounts.length);
    }
    const paramType = await getParamType("MerkleLibTest", "verifyRelayerRefund", "refund");
    const hashFn = (input) => keccak256(defaultAbiCoder.encode([paramType], [input]));
    return new MerkleTree_1.MerkleTree(relayerRefundLeaves, hashFn);
}
function buildRelayerRefundLeaves(destinationChainIds, amountsToReturn, l2Tokens, refundAddresses, refundAmounts) {
    return Array(destinationChainIds.length)
        .fill(0)
        .map((_, i) => {
        return {
            leafId: ethers_1.BigNumber.from(i),
            chainId: ethers_1.BigNumber.from(destinationChainIds[i]),
            amountToReturn: amountsToReturn[i],
            l2TokenAddress: l2Tokens[i],
            refundAddresses: refundAddresses[i],
            refundAmounts: refundAmounts[i],
        };
    });
}
async function buildPoolRebalanceLeafTree(poolRebalanceLeaves) {
    for (const leaf of poolRebalanceLeaves) {
        const { l1Tokens, bundleLpFees, netSendAmounts, runningBalances } = leaf;
        (0, chai_1.expect)(l1Tokens.length).to.equal(bundleLpFees.length).to.equal(netSendAmounts.length);
        if (runningBalances.length !== l1Tokens.length) {
            (0, chai_1.expect)(runningBalances.length).to.equal(2 * l1Tokens.length);
        }
    }
    const paramType = await getParamType("MerkleLibTest", "verifyPoolRebalance", "rebalance");
    const hashFn = (input) => keccak256(defaultAbiCoder.encode([paramType], [input]));
    return new MerkleTree_1.MerkleTree(poolRebalanceLeaves, hashFn);
}
function buildPoolRebalanceLeaves(destinationChainIds, l1Tokens, bundleLpFees, netSendAmounts, runningBalances, groupIndex) {
    return Array(destinationChainIds.length)
        .fill(0)
        .map((_, i) => {
        return {
            chainId: ethers_1.BigNumber.from(destinationChainIds[i]),
            groupIndex: ethers_1.BigNumber.from(groupIndex[i]),
            bundleLpFees: bundleLpFees[i],
            netSendAmounts: netSendAmounts[i],
            runningBalances: runningBalances[i],
            leafId: ethers_1.BigNumber.from(i),
            l1Tokens: l1Tokens[i],
        };
    });
}
async function buildSlowRelayTree(slowFills) {
    const paramType = await getParamType("MerkleLibTest", "verifySlowRelayFulfillment", "slowFill");
    const hashFn = (input) => keccak256(defaultAbiCoder.encode([paramType], [input]));
    return new MerkleTree_1.MerkleTree(slowFills, hashFn);
}
async function buildV3SlowRelayTree(slowFills) {
    const paramType = await getParamType("MerkleLibTest", "verifyV3SlowRelayFulfillment", "slowFill");
    const hashFn = (input) => keccak256(defaultAbiCoder.encode([paramType], [input]));
    return new MerkleTree_1.MerkleTree(slowFills, hashFn);
}
async function constructSingleRelayerRefundTree(l2Token, destinationChainId, amount) {
    const amountToUse = amount !== undefined ? amount : constants_1.amountToReturn;
    const l2TokenAddress = typeof l2Token === "string" ? l2Token : l2Token.address;
    const leaves = buildRelayerRefundLeaves([destinationChainId], [amountToUse], [l2TokenAddress], [[]], [[]]);
    const tree = await buildRelayerRefundTree(leaves);
    return { leaves, tree };
}
async function constructSingleChainTree(token, scalingSize = 1, repaymentChain = constants_1.repaymentChainId, decimals = 18) {
    const tokensSendToL2 = ethers_1.ethers.utils.parseUnits((100 * scalingSize).toString(), decimals);
    const realizedLpFees = ethers_1.ethers.utils.parseUnits((10 * scalingSize).toString(), decimals);
    const leaves = buildPoolRebalanceLeaves([repaymentChain], [[token]], [[realizedLpFees]], [[tokensSendToL2]], [[tokensSendToL2]], [0]);
    const tree = await buildPoolRebalanceLeafTree(leaves);
    return { tokensSendToL2, realizedLpFees, leaves, tree };
}
//# sourceMappingURL=MerkleLib.utils.js.map