"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildRelayerRefundTree = buildRelayerRefundTree;
exports.buildRelayerRefundLeaves = buildRelayerRefundLeaves;
exports.buildPoolRebalanceLeafTree = buildPoolRebalanceLeafTree;
exports.buildPoolRebalanceLeaves = buildPoolRebalanceLeaves;
exports.constructSingleRelayerRefundTree = constructSingleRelayerRefundTree;
exports.constructSingleChainTree = constructSingleChainTree;
exports.buildSlowRelayTree = buildSlowRelayTree;
exports.buildV3SlowRelayTree = buildV3SlowRelayTree;
const utils_1 = require("../../../utils/utils");
const constants_1 = require("./constants");
const MerkleTree_1 = require("../../../utils/MerkleTree");
async function buildRelayerRefundTree(relayerRefundLeaves) {
    for (let i = 0; i < relayerRefundLeaves.length; i++) {
        // The 2 provided parallel arrays must be of equal length.
        (0, utils_1.expect)(relayerRefundLeaves[i].refundAddresses.length).to.equal(relayerRefundLeaves[i].refundAmounts.length);
    }
    const paramType = await (0, utils_1.getParamType)("MerkleLibTest", "verifyRelayerRefund", "refund");
    const hashFn = (input) => (0, utils_1.keccak256)(utils_1.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: utils_1.BigNumber.from(i),
            chainId: utils_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;
        // l1Tokens, bundleLpFees and netSendAmounts must always be of equal length.
        (0, utils_1.expect)(l1Tokens.length).to.equal(bundleLpFees.length).to.equal(netSendAmounts.length);
        // runningBalances must be 1x or 2x as long as the other arrays. If its 2x as long, then the first half of the
        // array will be viewed as one set of running balances, and the second half will be viewed as another set of
        // of values.
        if (runningBalances.length !== l1Tokens.length) {
            (0, utils_1.expect)(runningBalances.length).to.equal(2 * l1Tokens.length);
        }
    }
    const paramType = await (0, utils_1.getParamType)("MerkleLibTest", "verifyPoolRebalance", "rebalance");
    const hashFn = (input) => (0, utils_1.keccak256)(utils_1.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: utils_1.BigNumber.from(destinationChainIds[i]),
            groupIndex: utils_1.BigNumber.from(groupIndex[i]),
            bundleLpFees: bundleLpFees[i],
            netSendAmounts: netSendAmounts[i],
            runningBalances: runningBalances[i],
            leafId: utils_1.BigNumber.from(i),
            l1Tokens: l1Tokens[i],
        };
    });
}
async function constructSingleRelayerRefundTree(l2Token, destinationChainId) {
    const leaves = buildRelayerRefundLeaves([destinationChainId], // Destination chain ID.
    [constants_1.amountToReturn], // amountToReturn.
    [l2Token], // l2Token.
    [[]], // refundAddresses.
    [[]] // refundAmounts.
    );
    const tree = await buildRelayerRefundTree(leaves);
    return { leaves, tree };
}
async function constructSingleChainTree(token, scalingSize = 1, repaymentChain = constants_1.repaymentChainId, decimals = 18) {
    const tokensSendToL2 = (0, utils_1.toBNWeiWithDecimals)(100 * scalingSize, decimals);
    const realizedLpFees = (0, utils_1.toBNWeiWithDecimals)(10 * scalingSize, decimals);
    const leaves = buildPoolRebalanceLeaves([repaymentChain], // repayment chain. In this test we only want to send one token to one chain.
    [[token]], // l1Token. We will only be sending 1 token to one chain.
    [[realizedLpFees]], // bundleLpFees.
    [[tokensSendToL2]], // netSendAmounts.
    [[tokensSendToL2]], // runningBalances.
    [0] // groupIndex
    );
    const tree = await buildPoolRebalanceLeafTree(leaves);
    return { tokensSendToL2, realizedLpFees, leaves, tree };
}
async function buildSlowRelayTree(slowFills) {
    const paramType = await (0, utils_1.getParamType)("MerkleLibTest", "verifySlowRelayFulfillment", "slowFill");
    const hashFn = (input) => {
        return (0, utils_1.keccak256)(utils_1.defaultAbiCoder.encode([paramType], [input]));
    };
    return new MerkleTree_1.MerkleTree(slowFills, hashFn);
}
async function buildV3SlowRelayTree(slowFills) {
    const paramType = await (0, utils_1.getParamType)("MerkleLibTest", "verifyV3SlowRelayFulfillment", "slowFill");
    const hashFn = (input) => {
        return (0, utils_1.keccak256)(utils_1.defaultAbiCoder.encode([paramType], [input]));
    };
    return new MerkleTree_1.MerkleTree(slowFills, hashFn);
}
