/**
 * Privacy Address
 *
 * A privacy address encodes both the recipient's Master Public Key (MPK)
 * and their viewing public key into a single address string.
 *
 * Format: 0x<MPK:64><ViewingPubKeyX:64><ViewingPubKeyY:64>
 * - MPK: 32 bytes (64 hex chars) - used for note ownership
 * - ViewingPubKeyX: 32 bytes (64 hex chars) - X coordinate of viewing public key
 * - ViewingPubKeyY: 32 bytes (64 hex chars) - Y coordinate of viewing public key
 * - Total: 96 bytes = 192 hex chars + "0x" prefix = 194 characters
 *
 * This format enables private transfers where:
 * - MPK is used to derive the note public key (NPK) for ownership
 * - Viewing public key is used for HPKE encryption of note contents
 */
/** Length of privacy address in hex characters (excluding 0x prefix) */
export const PRIVACY_ADDRESS_HEX_LENGTH = 192;
/** Length of privacy address including 0x prefix */
export const PRIVACY_ADDRESS_LENGTH = 194;
/** Length of each component in hex characters */
export const COMPONENT_HEX_LENGTH = 64;
/**
 * Encode MPK and viewing public key into a privacy address
 *
 * @param mpk - Master Public Key (32-byte bigint)
 * @param viewingPublicKey - Viewing public key point (two 32-byte coordinates)
 * @returns Privacy address as hex string
 *
 * @example
 * ```typescript
 * const address = encodePrivacyAddress(mpk, { x: viewingKeyX, y: viewingKeyY });
 * // Returns: 0x<mpk:64><x:64><y:64>
 * ```
 */
// Maximum value that fits in 32 bytes (256 bits)
const MAX_UINT256 = (1n << 256n) - 1n;
export function encodePrivacyAddress(mpk, viewingPublicKey) {
    if (mpk < 0n || mpk > MAX_UINT256) {
        throw new Error(`Invalid MPK: value out of 256-bit range`);
    }
    if (viewingPublicKey.x < 0n || viewingPublicKey.x > MAX_UINT256) {
        throw new Error(`Invalid viewing public key X: value out of 256-bit range`);
    }
    if (viewingPublicKey.y < 0n || viewingPublicKey.y > MAX_UINT256) {
        throw new Error(`Invalid viewing public key Y: value out of 256-bit range`);
    }
    const mpkHex = mpk.toString(16).padStart(COMPONENT_HEX_LENGTH, '0');
    const xHex = viewingPublicKey.x.toString(16).padStart(COMPONENT_HEX_LENGTH, '0');
    const yHex = viewingPublicKey.y.toString(16).padStart(COMPONENT_HEX_LENGTH, '0');
    return `0x${mpkHex}${xHex}${yHex}`;
}
/**
 * Decode a privacy address into its components
 *
 * @param address - Privacy address (96-byte hex string)
 * @returns Decoded MPK and viewing public key
 * @throws Error if address format is invalid
 *
 * @example
 * ```typescript
 * const { mpk, viewingPublicKey } = decodePrivacyAddress(address);
 * ```
 */
export function decodePrivacyAddress(address) {
    if (!isValidPrivacyAddress(address)) {
        throw new Error(`Invalid privacy address: expected ${PRIVACY_ADDRESS_LENGTH} character hex string (0x + ${PRIVACY_ADDRESS_HEX_LENGTH} hex chars)`);
    }
    // Remove 0x prefix
    const hex = address.slice(2);
    // Extract components (each 64 hex chars = 32 bytes)
    const mpkHex = hex.slice(0, COMPONENT_HEX_LENGTH);
    const xHex = hex.slice(COMPONENT_HEX_LENGTH, COMPONENT_HEX_LENGTH * 2);
    const yHex = hex.slice(COMPONENT_HEX_LENGTH * 2, COMPONENT_HEX_LENGTH * 3);
    return {
        mpk: BigInt(`0x${mpkHex}`),
        viewingPublicKey: {
            x: BigInt(`0x${xHex}`),
            y: BigInt(`0x${yHex}`),
        },
    };
}
/**
 * Check if a string is a valid privacy address format.
 *
 * **Format validation only** — checks prefix, length, and hex characters.
 * Does not verify that the encoded keys are cryptographically valid
 * (e.g., on the correct curve).
 *
 * @param address - String to validate
 * @returns true if valid privacy address format
 *
 * @example
 * ```typescript
 * if (isValidPrivacyAddress(input)) {
 *   const { mpk, viewingPublicKey } = decodePrivacyAddress(input);
 * }
 * ```
 */
export function isValidPrivacyAddress(address) {
    if (typeof address !== 'string')
        return false;
    // Must start with 0x
    if (!address.startsWith('0x'))
        return false;
    // Must be exactly 194 characters (0x + 192 hex chars)
    if (address.length !== PRIVACY_ADDRESS_LENGTH)
        return false;
    // Must be valid hex
    const hex = address.slice(2);
    if (!/^[a-fA-F0-9]+$/.test(hex))
        return false;
    return true;
}
/**
 * Validate a privacy address and return detailed result
 *
 * @param address - String to validate
 * @returns Validation result with message
 */
export function validatePrivacyAddress(address) {
    if (!address || !address.trim()) {
        return { valid: false, message: 'Privacy address is required' };
    }
    const trimmed = address.trim();
    if (!trimmed.startsWith('0x')) {
        return { valid: false, message: 'Privacy address must start with 0x' };
    }
    if (trimmed.length !== PRIVACY_ADDRESS_LENGTH) {
        return {
            valid: false,
            message: `Invalid length: expected ${PRIVACY_ADDRESS_LENGTH} characters, got ${trimmed.length}`,
        };
    }
    const hex = trimmed.slice(2);
    if (!/^[a-fA-F0-9]+$/.test(hex)) {
        return { valid: false, message: 'Invalid characters: must be hexadecimal' };
    }
    return { valid: true, message: 'Valid privacy address' };
}
/**
 * Extract just the MPK from a privacy address (for display purposes)
 *
 * @param address - Privacy address
 * @returns MPK as hex string (0x + 64 chars)
 */
export function extractMpkFromPrivacyAddress(address) {
    if (!isValidPrivacyAddress(address)) {
        throw new Error('Invalid privacy address');
    }
    const mpkHex = address.slice(2, 2 + COMPONENT_HEX_LENGTH);
    return `0x${mpkHex}`;
}
/**
 * Format a privacy address for display (truncated)
 *
 * @param address - Privacy address
 * @param startChars - Number of characters to show at start (default: 10)
 * @param endChars - Number of characters to show at end (default: 8)
 * @returns Truncated address string
 */
export function formatPrivacyAddress(address, startChars = 10, endChars = 8) {
    if (!address)
        return '';
    if (address.length <= startChars + endChars + 3)
        return address;
    return `${address.slice(0, startChars)}...${address.slice(-endChars)}`;
}
//# sourceMappingURL=address.js.map