import { privateKeyFromRaw, privateKeyToProtobuf, privateKeyFromProtobuf, publicKeyFromRaw, publicKeyToProtobuf } from "@libp2p/crypto/keys";
import { peerIdFromString, peerIdFromMultihash, peerIdFromPrivateKey, peerIdFromPublicKey } from "@libp2p/peer-id";
import * as Digest from "multiformats/hashes/digest";
import { ed25519 } from "@noble/curves/ed25519.js";
import { fromString as uint8ArrayFromString } from "uint8arrays/from-string";
import { toString as uint8ArrayToString } from "uint8arrays/to-string";
import { CID } from "multiformats/cid";
import { bases } from "multiformats/basics";
import Logger from "../logger.js";
export const generatePrivateKey = async () => {
    const privateKeyBuffer = ed25519.utils.randomSecretKey();
    const privateKeyBase64 = uint8ArrayToString(privateKeyBuffer, "base64");
    return privateKeyBase64;
};
export const getPKCAddressFromPrivateKey = async (privateKeyBase64) => {
    const peerId = await getPeerIdFromPrivateKey(privateKeyBase64);
    return peerId.toString().trim();
};
export const getPKCAddressFromPublicKey = (publicKeyBase64) => {
    const peerId = getPeerIdFromPublicKey(publicKeyBase64);
    return peerId.toString().trim();
};
export const getPKCAddressFromPublicKeyBuffer = (publicKeyBuffer) => {
    // the PeerId public key is not a raw public key, it adds a suffix
    const peerId = getPeerIdFromPublicKeyBuffer(publicKeyBuffer);
    return peerId.toString().trim();
};
export const getBufferedPKCAddressFromPublicKey = (publicKeyBase64) => {
    const peerId = getPeerIdFromPublicKey(publicKeyBase64);
    return peerId.toMultihash().bytes;
};
export const getIpfsKeyFromPrivateKey = async (privateKeyBase64) => {
    if (!privateKeyBase64 || typeof privateKeyBase64 !== "string")
        throw Error(`getIpfsKeyFromPrivateKey privateKeyBase64 not a string`);
    let privateKeyBuffer;
    try {
        privateKeyBuffer = uint8ArrayFromString(privateKeyBase64, "base64");
    }
    catch (e) {
        if (e instanceof Error)
            e.message = `getIpfsKeyFromPrivateKey privateKeyBase64 invalid: ${e.message}`;
        throw e;
    }
    if (privateKeyBuffer.length !== 32)
        throw Error(`getIpfsKeyFromPrivateKey privateKeyBase64 ed25519 private key length not 32 bytes (${privateKeyBuffer.length} bytes)`);
    const publicKeyBuffer = ed25519.getPublicKey(privateKeyBuffer);
    // ipfs ed25519 private keys format are private (32 bytes) + public (32 bytes) (64 bytes total)
    const privateAndPublicKeyBuffer = new Uint8Array(64);
    privateAndPublicKeyBuffer.set(privateKeyBuffer);
    privateAndPublicKeyBuffer.set(publicKeyBuffer, 32);
    const ed25519PrivateKeyInstance = privateKeyFromRaw(privateAndPublicKeyBuffer);
    // the "ipfs key" adds a suffix, then the private key, then the public key, it is not the raw private key
    return privateKeyToProtobuf(ed25519PrivateKeyInstance);
};
export const getPublicKeyFromPrivateKey = async (privateKeyBase64) => {
    if (!privateKeyBase64 || typeof privateKeyBase64 !== "string")
        throw Error(`getPublicKeyFromPrivateKey privateKeyBase64 not a string`);
    let privateKeyBuffer;
    try {
        privateKeyBuffer = uint8ArrayFromString(privateKeyBase64, "base64");
    }
    catch (e) {
        if (e instanceof Error)
            e.message = `getPublicKeyFromPrivateKey privateKeyBase64 invalid: ${e.message}`;
        throw e;
    }
    if (privateKeyBuffer.length !== 32)
        throw Error(`getPublicKeyFromPrivateKey privateKeyBase64 ed25519 private key length not 32 bytes (${privateKeyBuffer.length} bytes)`);
    const publicKeyBuffer = ed25519.getPublicKey(privateKeyBuffer);
    return uint8ArrayToString(publicKeyBuffer, "base64");
};
export const getPeerIdFromPrivateKey = async (privateKeyBase64) => {
    const ipfsKey = await getIpfsKeyFromPrivateKey(privateKeyBase64);
    // the PeerId private key is not a raw private key, it's an "ipfs key"
    const peerId = peerIdFromPrivateKey(privateKeyFromProtobuf(ipfsKey));
    return peerId;
};
export const getPeerIdFromPublicKey = (publicKeyBase64) => {
    if (!publicKeyBase64 || typeof publicKeyBase64 !== "string")
        throw Error(`getPeerIdFromPublicKey publicKeyBase64 '${publicKeyBase64}' not a string`);
    let publicKeyBuffer;
    try {
        publicKeyBuffer = uint8ArrayFromString(publicKeyBase64, "base64");
    }
    catch (e) {
        if (e instanceof Error)
            e.message = `getPeerIdFromPublicKey publicKeyBase64 invalid: ${e.message}`;
        throw e;
    }
    if (publicKeyBuffer.length !== 32)
        throw Error(`getPeerIdFromPublicKey publicKeyBase64 '${publicKeyBase64}' ed25519 public key length not 32 bytes (${publicKeyBuffer.length} bytes)`);
    // the PeerId public key is not a raw public key, it adds a suffix
    const ed25519PublicKeyInstance = publicKeyFromRaw(publicKeyBuffer);
    const peerId = peerIdFromPublicKey(ed25519PublicKeyInstance);
    return peerId;
};
export const getPeerIdFromPublicKeyBuffer = (publicKeyBuffer) => {
    if (publicKeyBuffer.length !== 32)
        throw Error(`getPeerIdFromPublicKeyBuffer publicKeyBuffer ed25519 public key length not 32 bytes (${publicKeyBuffer.length} bytes)`);
    // the PeerId public key is not a raw public key, it adds a suffix
    const ed25519PublicKeyInstance = publicKeyFromRaw(publicKeyBuffer);
    const peerId = peerIdFromPublicKey(ed25519PublicKeyInstance);
    return peerId;
};
export const convertBase58IpnsNameToBase36Cid = (ipnsName) => {
    const log = Logger("pkc-js:signer:util:convertBase58IpnsNameToBase32");
    let peerId;
    try {
        peerId = peerIdFromString(ipnsName);
    }
    catch (error) {
        log.error("Error creating peer id from ipns name:", error);
        throw error;
    }
    try {
        return peerId.toCID().toString(bases.base36);
    }
    catch (e) {
        log.error(`Failed to convert peer id to CIDv1base36`, e);
        throw e;
    }
};
export function convertBase32ToBase58btc(base32String) {
    // Decode base32 to bytes
    const cid = CID.parse(base32String);
    const peerId = peerIdFromMultihash(cid.multihash);
    return peerId.toString().trim();
}
export const getPKCAddressFromPublicKeySync = (publicKeyBase64) => {
    // pkc address is the base58 string of the peer id of the public key
    if (!publicKeyBase64 || typeof publicKeyBase64 !== "string")
        throw Error(`getPKCAddressFromPublicKeySync publicKeyBase64 '${publicKeyBase64}' not a string`);
    let publicKeyBuffer;
    try {
        publicKeyBuffer = uint8ArrayFromString(publicKeyBase64, "base64");
    }
    catch (e) {
        if (e instanceof Error)
            e.message = `getPKCAddressFromPublicKeySync publicKeyBase64 invalid: ${e.message}`;
        throw e;
    }
    if (publicKeyBuffer.length !== 32)
        throw Error(`getPKCAddressFromPublicKeySync publicKeyBase64 '${publicKeyBase64}' ed25519 public key length not 32 bytes (${publicKeyBuffer.length} bytes)`);
    // Marshal to libp2p protobuf bytes to build the identity multihash
    const ed25519PublicKeyInstance = publicKeyFromRaw(publicKeyBuffer);
    const publicKeyBytes = publicKeyToProtobuf(ed25519PublicKeyInstance);
    // For Ed25519 keys, create identity hash multihash
    const multihash = new Uint8Array(2 + publicKeyBytes.length);
    multihash[0] = 0x00; // Identity hash code
    multihash[1] = publicKeyBytes.length; // digest length
    multihash.set(publicKeyBytes, 2); // the public key bytes themselves
    // Create PeerId from the multihash bytes and return as base58 string
    const peerId = peerIdFromMultihash(Digest.decode(multihash));
    return peerId.toString().trim();
};
//# sourceMappingURL=util.js.map