// src/signing.ts
import { ml_dsa65 } from "@noble/post-quantum/ml-dsa";
import { randomBytes } from "@noble/hashes/utils";
var DILITHIUM3_SEED_BYTES = 32;
function generateKeypair(seed) {
  const actualSeed = seed ?? randomBytes(DILITHIUM3_SEED_BYTES);
  if (actualSeed.length !== DILITHIUM3_SEED_BYTES) {
    throw new Error(
      `Dilithium3 seed must be ${DILITHIUM3_SEED_BYTES} bytes, got ${actualSeed.length}`
    );
  }
  const keys = ml_dsa65.keygen(actualSeed);
  return {
    publicKey: keys.publicKey,
    secretKey: keys.secretKey
  };
}
function sign(message, secretKey) {
  return ml_dsa65.sign(secretKey, message);
}
function verify(message, signature, publicKey) {
  try {
    return ml_dsa65.verify(publicKey, message, signature);
  } catch {
    return false;
  }
}

// src/hashing.ts
import { blake3 as nobleBlake3 } from "@noble/hashes/blake3";
import { sha256 as nobleSha256 } from "@noble/hashes/sha256";
function blake3(data, dkLen = 32) {
  return nobleBlake3(data, { dkLen });
}
function sha256(data) {
  return nobleSha256(data);
}

// src/bech32.ts
var CHARSET = "qpzry9x8gf2tvdw0s3jn54khce6mua7l";
var CHARSET_MAP = {};
for (let i = 0; i < CHARSET.length; i++) {
  CHARSET_MAP[CHARSET.charAt(i)] = i;
}
var GENERATOR = [996825010, 642813549, 513874426, 1027748829, 705979059];
function polymod(values) {
  let chk = 1;
  for (const v of values) {
    const top = chk >> 25;
    chk = (chk & 33554431) << 5 ^ v;
    for (let i = 0; i < 5; i++) {
      if (top >> i & 1) chk ^= GENERATOR[i];
    }
  }
  return chk;
}
function hrpExpand(hrp) {
  const ret = [];
  for (let i = 0; i < hrp.length; i++) ret.push(hrp.charCodeAt(i) >> 5);
  ret.push(0);
  for (let i = 0; i < hrp.length; i++) ret.push(hrp.charCodeAt(i) & 31);
  return ret;
}
function createChecksum(hrp, data) {
  const values = hrpExpand(hrp).concat(data).concat([0, 0, 0, 0, 0, 0]);
  const mod = polymod(values) ^ 1;
  const ret = [];
  for (let p = 0; p < 6; p++) ret.push(mod >> 5 * (5 - p) & 31);
  return ret;
}
function verifyChecksum(hrp, data) {
  return polymod(hrpExpand(hrp).concat(data)) === 1;
}
function convertBits(data, fromBits, toBits, pad) {
  let acc = 0;
  let bits = 0;
  const ret = [];
  const maxv = (1 << toBits) - 1;
  const maxAcc = (1 << fromBits + toBits - 1) - 1;
  for (let i = 0; i < data.length; i++) {
    const value = data[i];
    if (value < 0 || value >> fromBits !== 0) return null;
    acc = (acc << fromBits | value) & maxAcc;
    bits += fromBits;
    while (bits >= toBits) {
      bits -= toBits;
      ret.push(acc >> bits & maxv);
    }
  }
  if (pad) {
    if (bits > 0) ret.push(acc << toBits - bits & maxv);
  } else if (bits >= fromBits || (acc << toBits - bits & maxv) !== 0) {
    return null;
  }
  return ret;
}
function bech32Encode(hrp, bytes) {
  if (!/^[!-~]+$/.test(hrp) || hrp.toLowerCase() !== hrp) {
    throw new Error(`bech32: invalid hrp "${hrp}"`);
  }
  const data = convertBits(bytes, 8, 5, true);
  if (!data) throw new Error("bech32: convertBits failed on encode");
  const combined = data.concat(createChecksum(hrp, data));
  let ret = `${hrp}1`;
  for (const d of combined) ret += CHARSET.charAt(d);
  if (ret.length > 90) throw new Error("bech32: encoded string exceeds 90 chars");
  return ret;
}
function bech32Decode(input) {
  if (input.length < 8 || input.length > 90) return null;
  const lower = input.toLowerCase();
  const upper = input.toUpperCase();
  if (input !== lower && input !== upper) return null;
  const s = lower;
  const sep = s.lastIndexOf("1");
  if (sep < 1 || sep + 7 > s.length) return null;
  const hrp = s.slice(0, sep);
  const dataPart = s.slice(sep + 1);
  const data = [];
  for (let i = 0; i < dataPart.length; i++) {
    const c = dataPart.charAt(i);
    if (!(c in CHARSET_MAP)) return null;
    data.push(CHARSET_MAP[c]);
  }
  if (!verifyChecksum(hrp, data)) return null;
  const payload = convertBits(data.slice(0, -6), 5, 8, false);
  if (!payload) return null;
  return { hrp, bytes: new Uint8Array(payload) };
}

// src/address.ts
var ASE_HRP = "ase";
var ADDRESS_BYTE_LENGTH = 20;
var ADDRESS_HEX_LENGTH = 40;
function addressBytesFromPublicKey(publicKey) {
  return blake3(publicKey).slice(0, ADDRESS_BYTE_LENGTH);
}
function addressFromPublicKey(publicKey) {
  const bytes = addressBytesFromPublicKey(publicKey);
  return toChecksumAddress(bytesToHex(bytes));
}
function toChecksumAddress(address) {
  const stripped = address.toLowerCase().replace(/^0x/, "");
  if (stripped.length !== ADDRESS_HEX_LENGTH) {
    throw new Error(
      `Invalid address length: expected ${ADDRESS_HEX_LENGTH} hex chars, got ${stripped.length}`
    );
  }
  if (!/^[0-9a-f]+$/.test(stripped)) {
    throw new Error("Invalid address: non-hex characters present");
  }
  const hashBytes = blake3(new TextEncoder().encode(stripped));
  const hashHex = bytesToHex(hashBytes);
  let checksum = "";
  for (let i = 0; i < stripped.length; i++) {
    const char = stripped.charAt(i);
    const hashChar = hashHex.charAt(i);
    const nibble = parseInt(hashChar, 16);
    checksum += nibble >= 8 ? char.toUpperCase() : char;
  }
  return `0x${checksum}`;
}
function isValidAddress(address) {
  if (typeof address !== "string") return false;
  if (!address.startsWith("0x")) return false;
  const stripped = address.slice(2);
  if (stripped.length !== ADDRESS_HEX_LENGTH) return false;
  return /^[0-9a-fA-F]+$/.test(stripped);
}
function bytesToHex(bytes) {
  let hex = "";
  for (let i = 0; i < bytes.length; i++) {
    hex += (bytes[i] ?? 0).toString(16).padStart(2, "0");
  }
  return hex;
}
function hexToBytes(hex) {
  const stripped = hex.toLowerCase().replace(/^0x/, "");
  if (stripped.length !== ADDRESS_HEX_LENGTH) {
    throw new Error(`Invalid hex address length: expected ${ADDRESS_HEX_LENGTH}, got ${stripped.length}`);
  }
  const out = new Uint8Array(ADDRESS_BYTE_LENGTH);
  for (let i = 0; i < ADDRESS_BYTE_LENGTH; i++) {
    out[i] = parseInt(stripped.slice(i * 2, i * 2 + 2), 16);
  }
  return out;
}
function bytesToBech32Address(bytes) {
  if (bytes.length !== ADDRESS_BYTE_LENGTH) {
    throw new Error(`bech32 address requires ${ADDRESS_BYTE_LENGTH} bytes, got ${bytes.length}`);
  }
  return bech32Encode(ASE_HRP, bytes);
}
function bech32AddressToBytes(addr) {
  const decoded = bech32Decode(addr);
  if (!decoded) throw new Error(`Invalid bech32 address: ${addr}`);
  if (decoded.hrp !== ASE_HRP) {
    throw new Error(`Wrong bech32 hrp: expected "${ASE_HRP}", got "${decoded.hrp}"`);
  }
  if (decoded.bytes.length !== ADDRESS_BYTE_LENGTH) {
    throw new Error(`bech32 payload has ${decoded.bytes.length} bytes, expected ${ADDRESS_BYTE_LENGTH}`);
  }
  return decoded.bytes;
}
function bech32AddressFromPublicKey(publicKey) {
  return bytesToBech32Address(addressBytesFromPublicKey(publicKey));
}
function isValidBech32Address(s) {
  if (typeof s !== "string") return false;
  const decoded = bech32Decode(s);
  if (!decoded) return false;
  return decoded.hrp === ASE_HRP && decoded.bytes.length === ADDRESS_BYTE_LENGTH;
}
function parseAnyAddress(input) {
  if (typeof input !== "string" || input.length === 0) {
    throw new Error("parseAnyAddress: empty input");
  }
  const trimmed = input.trim();
  if (trimmed.toLowerCase().startsWith("0x")) return hexToBytes(trimmed);
  if (trimmed.toLowerCase().startsWith(`${ASE_HRP}1`)) return bech32AddressToBytes(trimmed);
  throw new Error(`parseAnyAddress: unrecognized address form "${input.slice(0, 12)}\u2026"`);
}
function canonicalizeAddress(input, form) {
  const bytes = parseAnyAddress(input);
  if (form === "bech32") return bytesToBech32Address(bytes);
  return toChecksumAddress(bytesToHex(bytes));
}
export {
  ASE_HRP,
  addressBytesFromPublicKey,
  addressFromPublicKey,
  bech32AddressFromPublicKey,
  bech32AddressToBytes,
  bech32Decode,
  bech32Encode,
  blake3,
  bytesToBech32Address,
  canonicalizeAddress,
  convertBits,
  generateKeypair,
  isValidAddress,
  isValidBech32Address,
  parseAnyAddress,
  sha256,
  sign,
  toChecksumAddress,
  verify
};
//# sourceMappingURL=index.js.map