"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;
var tslib_1 = require("tslib");
var ethers_1 = require("ethers");
var getContractFactory_1 = require("./getContractFactory");
var MerkleTree_1 = require("@across-protocol/contracts/dist/utils/MerkleTree");
var chai_1 = require("chai");
var constants_1 = require("../constants");
var _a = ethers_1.ethers.utils, keccak256 = _a.keccak256, defaultAbiCoder = _a.defaultAbiCoder;
function getParamType(contractName, functionName, paramName) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var contractFactory, fragment, functionFragment;
        return tslib_1.__generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4, (0, getContractFactory_1.getContractFactory)(contractName, new ethers_1.ethers.VoidSigner(ethers_1.ethers.constants.AddressZero))];
                case 1:
                    contractFactory = _a.sent();
                    fragment = contractFactory.interface.fragments.find(function (fragment) { return fragment.name === functionName; });
                    if (!fragment || fragment.type !== "function") {
                        return [2, ""];
                    }
                    functionFragment = fragment;
                    return [2, functionFragment.inputs.find(function (input) { return input.name === paramName; }) || ""];
            }
        });
    });
}
function buildRelayerRefundTree(relayerRefundLeaves) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var i, paramType, hashFn;
        return tslib_1.__generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    for (i = 0; i < relayerRefundLeaves.length; i++) {
                        (0, chai_1.expect)(relayerRefundLeaves[i].refundAddresses.length).to.equal(relayerRefundLeaves[i].refundAmounts.length);
                    }
                    return [4, getParamType("MerkleLibTest", "verifyRelayerRefund", "refund")];
                case 1:
                    paramType = _a.sent();
                    hashFn = function (input) { return keccak256(defaultAbiCoder.encode([paramType], [input])); };
                    return [2, new MerkleTree_1.MerkleTree(relayerRefundLeaves, hashFn)];
            }
        });
    });
}
function buildRelayerRefundLeaves(destinationChainIds, amountsToReturn, l2Tokens, refundAddresses, refundAmounts) {
    return Array(destinationChainIds.length)
        .fill(0)
        .map(function (_, 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],
        };
    });
}
function buildPoolRebalanceLeafTree(poolRebalanceLeaves) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var _i, poolRebalanceLeaves_1, leaf, l1Tokens, bundleLpFees, netSendAmounts, runningBalances, paramType, hashFn;
        return tslib_1.__generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    for (_i = 0, poolRebalanceLeaves_1 = poolRebalanceLeaves; _i < poolRebalanceLeaves_1.length; _i++) {
                        leaf = poolRebalanceLeaves_1[_i];
                        l1Tokens = leaf.l1Tokens, bundleLpFees = leaf.bundleLpFees, netSendAmounts = leaf.netSendAmounts, runningBalances = leaf.runningBalances;
                        (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);
                        }
                    }
                    return [4, getParamType("MerkleLibTest", "verifyPoolRebalance", "rebalance")];
                case 1:
                    paramType = _a.sent();
                    hashFn = function (input) { return keccak256(defaultAbiCoder.encode([paramType], [input])); };
                    return [2, new MerkleTree_1.MerkleTree(poolRebalanceLeaves, hashFn)];
            }
        });
    });
}
function buildPoolRebalanceLeaves(destinationChainIds, l1Tokens, bundleLpFees, netSendAmounts, runningBalances, groupIndex) {
    return Array(destinationChainIds.length)
        .fill(0)
        .map(function (_, 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],
        };
    });
}
function buildSlowRelayTree(slowFills) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var paramType, hashFn;
        return tslib_1.__generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4, getParamType("MerkleLibTest", "verifySlowRelayFulfillment", "slowFill")];
                case 1:
                    paramType = _a.sent();
                    hashFn = function (input) { return keccak256(defaultAbiCoder.encode([paramType], [input])); };
                    return [2, new MerkleTree_1.MerkleTree(slowFills, hashFn)];
            }
        });
    });
}
function buildV3SlowRelayTree(slowFills) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var paramType, hashFn;
        return tslib_1.__generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4, getParamType("MerkleLibTest", "verifyV3SlowRelayFulfillment", "slowFill")];
                case 1:
                    paramType = _a.sent();
                    hashFn = function (input) { return keccak256(defaultAbiCoder.encode([paramType], [input])); };
                    return [2, new MerkleTree_1.MerkleTree(slowFills, hashFn)];
            }
        });
    });
}
function constructSingleRelayerRefundTree(l2Token, destinationChainId, amount) {
    return tslib_1.__awaiter(this, void 0, void 0, function () {
        var amountToUse, l2TokenAddress, leaves, tree;
        return tslib_1.__generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    amountToUse = amount !== undefined ? amount : constants_1.amountToReturn;
                    l2TokenAddress = typeof l2Token === "string" ? l2Token : l2Token.address;
                    leaves = buildRelayerRefundLeaves([destinationChainId], [amountToUse], [l2TokenAddress], [[]], [[]]);
                    return [4, buildRelayerRefundTree(leaves)];
                case 1:
                    tree = _a.sent();
                    return [2, { leaves: leaves, tree: tree }];
            }
        });
    });
}
function constructSingleChainTree(token_1) {
    return tslib_1.__awaiter(this, arguments, void 0, function (token, scalingSize, repaymentChain, decimals) {
        var tokensSendToL2, realizedLpFees, leaves, tree;
        if (scalingSize === void 0) { scalingSize = 1; }
        if (repaymentChain === void 0) { repaymentChain = constants_1.repaymentChainId; }
        if (decimals === void 0) { decimals = 18; }
        return tslib_1.__generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    tokensSendToL2 = ethers_1.ethers.utils.parseUnits((100 * scalingSize).toString(), decimals);
                    realizedLpFees = ethers_1.ethers.utils.parseUnits((10 * scalingSize).toString(), decimals);
                    leaves = buildPoolRebalanceLeaves([repaymentChain], [[token]], [[realizedLpFees]], [[tokensSendToL2]], [[tokensSendToL2]], [0]);
                    return [4, buildPoolRebalanceLeafTree(leaves)];
                case 1:
                    tree = _a.sent();
                    return [2, { tokensSendToL2: tokensSendToL2, realizedLpFees: realizedLpFees, leaves: leaves, tree: tree }];
            }
        });
    });
}
//# sourceMappingURL=MerkleLib.utils.js.map