"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildMerkleRoot = buildMerkleRoot;
exports.merkleProofs = merkleProofs;
const ethers_1 = require("ethers");
/** Matches CheckpointLeaf.buildMerkleRoot (pair sort, odd duplicate). */
function buildMerkleRoot(hashes) {
    if (hashes.length === 0)
        return ethers_1.ethers.ZeroHash;
    let layer = [...hashes];
    while (layer.length > 1) {
        const next = [];
        for (let i = 0; i < layer.length; i += 2) {
            const a = layer[i];
            const b = i + 1 < layer.length ? layer[i + 1] : a;
            const [left, right] = a.toLowerCase() < b.toLowerCase() ? [a, b] : [b, a];
            next.push(ethers_1.ethers.keccak256(ethers_1.ethers.concat([left, right])));
        }
        layer = next;
    }
    return layer[0];
}
function merkleProofs(hashes) {
    const root = buildMerkleRoot(hashes);
    const proofs = hashes.map((_, index) => buildProof(hashes, index));
    return { root, proofs };
}
function buildProof(leaves, index) {
    const proof = [];
    let idx = index;
    let layer = [...leaves];
    while (layer.length > 1) {
        const next = [];
        for (let i = 0; i < layer.length; i += 2) {
            const a = layer[i];
            const b = i + 1 < layer.length ? layer[i + 1] : a;
            const [left, right] = a.toLowerCase() < b.toLowerCase() ? [a, b] : [b, a];
            next.push(ethers_1.ethers.keccak256(ethers_1.ethers.concat([left, right])));
        }
        const siblingIdx = idx % 2 === 0 ? idx + 1 : idx - 1;
        if (siblingIdx < layer.length)
            proof.push(layer[siblingIdx]);
        idx = Math.floor(idx / 2);
        layer = next;
    }
    return proof;
}
