import { __awaiter, __generator } from "tslib";
/**
 * Local Merkle tree utilities that use our local getContractFactory.
 * These are reimplementations of the utilities from @across-protocol/contracts
 * to avoid dependency on their getContractFactory which looks for Hardhat artifacts.
 */
import { BigNumber, ethers } from "ethers";
import { getContractFactory } from "./getContractFactory";
import { MerkleTree } from "@across-protocol/contracts/dist/utils/MerkleTree";
import { expect } from "chai";
var _a = ethers.utils, keccak256 = _a.keccak256, defaultAbiCoder = _a.defaultAbiCoder;
/**
 * Get the parameter type for a contract function parameter.
 * Uses our local getContractFactory to load the contract ABI.
 */
export function getParamType(contractName, functionName, paramName) {
    return __awaiter(this, void 0, void 0, function () {
        var contractFactory, fragment, functionFragment;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4 /*yield*/, getContractFactory(contractName, new ethers.VoidSigner(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 /*return*/, ""];
                    }
                    functionFragment = fragment;
                    return [2 /*return*/, functionFragment.inputs.find(function (input) { return input.name === paramName; }) || ""];
            }
        });
    });
}
/**
 * Build a relayer refund Merkle tree.
 */
export function buildRelayerRefundTree(relayerRefundLeaves) {
    return __awaiter(this, void 0, void 0, function () {
        var i, paramType, hashFn;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0:
                    for (i = 0; i < relayerRefundLeaves.length; i++) {
                        expect(relayerRefundLeaves[i].refundAddresses.length).to.equal(relayerRefundLeaves[i].refundAmounts.length);
                    }
                    return [4 /*yield*/, getParamType("MerkleLibTest", "verifyRelayerRefund", "refund")];
                case 1:
                    paramType = _a.sent();
                    hashFn = function (input) { return keccak256(defaultAbiCoder.encode([paramType], [input])); };
                    return [2 /*return*/, new MerkleTree(relayerRefundLeaves, hashFn)];
            }
        });
    });
}
/**
 * Build relayer refund leaves.
 */
export function buildRelayerRefundLeaves(destinationChainIds, amountsToReturn, l2Tokens, refundAddresses, refundAmounts) {
    return Array(destinationChainIds.length)
        .fill(0)
        .map(function (_, i) {
        return {
            leafId: BigNumber.from(i),
            chainId: BigNumber.from(destinationChainIds[i]),
            amountToReturn: amountsToReturn[i],
            l2TokenAddress: l2Tokens[i],
            refundAddresses: refundAddresses[i],
            refundAmounts: refundAmounts[i],
        };
    });
}
/**
 * Build a pool rebalance Merkle tree.
 */
export function buildPoolRebalanceLeafTree(poolRebalanceLeaves) {
    return __awaiter(this, void 0, void 0, function () {
        var _i, poolRebalanceLeaves_1, leaf, l1Tokens, bundleLpFees, netSendAmounts, runningBalances, paramType, hashFn;
        return __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;
                        expect(l1Tokens.length).to.equal(bundleLpFees.length).to.equal(netSendAmounts.length);
                        if (runningBalances.length !== l1Tokens.length) {
                            expect(runningBalances.length).to.equal(2 * l1Tokens.length);
                        }
                    }
                    return [4 /*yield*/, getParamType("MerkleLibTest", "verifyPoolRebalance", "rebalance")];
                case 1:
                    paramType = _a.sent();
                    hashFn = function (input) { return keccak256(defaultAbiCoder.encode([paramType], [input])); };
                    return [2 /*return*/, new MerkleTree(poolRebalanceLeaves, hashFn)];
            }
        });
    });
}
/**
 * Build pool rebalance leaves.
 */
export function buildPoolRebalanceLeaves(destinationChainIds, l1Tokens, bundleLpFees, netSendAmounts, runningBalances, groupIndex) {
    return Array(destinationChainIds.length)
        .fill(0)
        .map(function (_, i) {
        return {
            chainId: BigNumber.from(destinationChainIds[i]),
            groupIndex: BigNumber.from(groupIndex[i]),
            bundleLpFees: bundleLpFees[i],
            netSendAmounts: netSendAmounts[i],
            runningBalances: runningBalances[i],
            leafId: BigNumber.from(i),
            l1Tokens: l1Tokens[i],
        };
    });
}
/**
 * Build a slow relay Merkle tree.
 */
export function buildSlowRelayTree(slowFills) {
    return __awaiter(this, void 0, void 0, function () {
        var paramType, hashFn;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4 /*yield*/, getParamType("MerkleLibTest", "verifySlowRelayFulfillment", "slowFill")];
                case 1:
                    paramType = _a.sent();
                    hashFn = function (input) { return keccak256(defaultAbiCoder.encode([paramType], [input])); };
                    return [2 /*return*/, new MerkleTree(slowFills, hashFn)];
            }
        });
    });
}
/**
 * Build a V3 slow relay Merkle tree.
 */
export function buildV3SlowRelayTree(slowFills) {
    return __awaiter(this, void 0, void 0, function () {
        var paramType, hashFn;
        return __generator(this, function (_a) {
            switch (_a.label) {
                case 0: return [4 /*yield*/, getParamType("MerkleLibTest", "verifyV3SlowRelayFulfillment", "slowFill")];
                case 1:
                    paramType = _a.sent();
                    hashFn = function (input) { return keccak256(defaultAbiCoder.encode([paramType], [input])); };
                    return [2 /*return*/, new MerkleTree(slowFills, hashFn)];
            }
        });
    });
}
//# sourceMappingURL=MerkleLib.utils.js.map