"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.deriveKeysetId = exports.deserializeMintKeys = exports.serializeMintKeys = exports.createRandomPrivateKey = exports.getKeysetIdInt = exports.pointFromHex = exports.hashToCurve = void 0;
const secp256k1_1 = require("@noble/curves/secp256k1");
const sha256_1 = require("@noble/hashes/sha256");
const utils_1 = require("@noble/curves/abstract/utils");
const utils_js_1 = require("../util/utils.js");
const buffer_1 = require("buffer/");
const DOMAIN_SEPARATOR = (0, utils_1.hexToBytes)('536563703235366b315f48617368546f43757276655f43617368755f');
function hashToCurve(secret) {
    const msgToHash = (0, sha256_1.sha256)(buffer_1.Buffer.concat([DOMAIN_SEPARATOR, secret]));
    const counter = new Uint32Array(1);
    const maxIterations = 2 ** 16;
    for (let i = 0; i < maxIterations; i++) {
        const counterBytes = new Uint8Array(counter.buffer);
        const hash = (0, sha256_1.sha256)(buffer_1.Buffer.concat([msgToHash, counterBytes]));
        try {
            return pointFromHex((0, utils_1.bytesToHex)(buffer_1.Buffer.concat([new Uint8Array([0x02]), hash])));
        }
        catch (error) {
            counter[0]++;
        }
    }
    throw new Error('No valid point found');
}
exports.hashToCurve = hashToCurve;
function pointFromHex(hex) {
    return secp256k1_1.secp256k1.ProjectivePoint.fromHex(hex);
}
exports.pointFromHex = pointFromHex;
const getKeysetIdInt = (keysetId) => {
    let keysetIdInt;
    if (/^[a-fA-F0-9]+$/.test(keysetId)) {
        keysetIdInt = (0, utils_js_1.hexToNumber)(keysetId) % BigInt(2 ** 31 - 1);
    }
    else {
        //legacy keyset compatibility
        keysetIdInt = (0, utils_js_1.bytesToNumber)((0, utils_js_1.encodeBase64toUint8)(keysetId)) % BigInt(2 ** 31 - 1);
    }
    return keysetIdInt;
};
exports.getKeysetIdInt = getKeysetIdInt;
function createRandomPrivateKey() {
    return secp256k1_1.secp256k1.utils.randomPrivateKey();
}
exports.createRandomPrivateKey = createRandomPrivateKey;
function serializeMintKeys(mintKeys) {
    const serializedMintKeys = {};
    Object.keys(mintKeys).forEach((p) => {
        serializedMintKeys[p] = (0, utils_1.bytesToHex)(mintKeys[p]);
    });
    return serializedMintKeys;
}
exports.serializeMintKeys = serializeMintKeys;
function deserializeMintKeys(serializedMintKeys) {
    const mintKeys = {};
    Object.keys(serializedMintKeys).forEach((p) => {
        mintKeys[p] = (0, utils_1.hexToBytes)(serializedMintKeys[p]);
    });
    return mintKeys;
}
exports.deserializeMintKeys = deserializeMintKeys;
function deriveKeysetId(keys) {
    const KEYSET_VERSION = '00';
    const mapBigInt = (k) => {
        return [BigInt(k[0]), k[1]];
    };
    const pubkeysConcat = Object.entries(serializeMintKeys(keys))
        .map(mapBigInt)
        .sort((a, b) => (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0))
        .map(([, pubKey]) => (0, utils_1.hexToBytes)(pubKey))
        .reduce((prev, curr) => mergeUInt8Arrays(prev, curr), new Uint8Array());
    const hash = (0, sha256_1.sha256)(pubkeysConcat);
    const hashHex = buffer_1.Buffer.from(hash).toString('hex').slice(0, 14);
    return '00' + hashHex;
}
exports.deriveKeysetId = deriveKeysetId;
function mergeUInt8Arrays(a1, a2) {
    // sum of individual array lengths
    const mergedArray = new Uint8Array(a1.length + a2.length);
    mergedArray.set(a1);
    mergedArray.set(a2, a1.length);
    return mergedArray;
}
//# sourceMappingURL=index.js.map