"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.DeterministicAddressGenerator = exports.getEvmAddress = exports.getDeterministicAddress = exports.getLegacyAddress = void 0;
const crypto_1 = __importDefault(require("crypto"));
const ethers_1 = require("ethers");
const BASE58_ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
const BECH32_CHARSET = 'qpzry9x8gf2tvdw0s3jn54khce6mua7l';
const base58Encode = (source) => {
    let num = BigInt('0x' + source.toString('hex'));
    let encoded = '';
    while (num > 0n) {
        const remainder = Number(num % 58n);
        encoded = BASE58_ALPHABET[remainder] + encoded;
        num = num / 58n;
    }
    for (const byte of source) {
        if (byte === 0) {
            encoded = '1' + encoded;
        }
        else {
            break;
        }
    }
    return encoded;
};
const base58EncodeFixed = (source, length) => {
    let num = BigInt('0x' + source.toString('hex'));
    let encoded = '';
    while (encoded.length < length) {
        if (num === 0n) {
            encoded = BASE58_ALPHABET[0] + encoded;
            continue;
        }
        const remainder = Number(num % 58n);
        encoded = BASE58_ALPHABET[remainder] + encoded;
        num = num / 58n;
    }
    return encoded;
};
const bech32EncodeFixed = (source, length) => {
    let num = BigInt('0x' + source.toString('hex'));
    let encoded = '';
    while (encoded.length < length) {
        if (num === 0n) {
            encoded = BECH32_CHARSET[0] + encoded;
            continue;
        }
        const remainder = Number(num % 32n);
        encoded = BECH32_CHARSET[remainder] + encoded;
        num = num / 32n;
    }
    return encoded;
};
/**
 * Trust Wallet compatible address formats for UTXO-like networks.
 *
 * These formats are intentionally synthetic: the server does not derive real
 * HD keys from the stored seed phrase, but the generated strings must visually
 * match the prefix and length that Trust Wallet displays so the app can render
 * them consistently.
 */
const UTXO_FORMATS = {
    BTC: { prefix: 'bc1q', encoding: 'bech32', dataLength: 38 },
    LTC: { prefix: 'ltc1q', encoding: 'bech32', dataLength: 38 },
    DGB: { prefix: 'dgb1q', encoding: 'bech32', dataLength: 38 },
    DOGE: { prefix: 'D', encoding: 'base58', dataLength: 33 },
    DASH: { prefix: 'X', encoding: 'base58', dataLength: 33 },
    ZEC: { prefix: 't1', encoding: 'base58', dataLength: 32 },
    RVN: { prefix: 'R', encoding: 'base58', dataLength: 33 },
    DCR: { prefix: 'Ds', encoding: 'base58', dataLength: 32 },
    BCH: { prefix: 'bitcoincash:q', encoding: 'bech32', dataLength: 41 },
};
const hashFor = (network, wallet) => crypto_1.default.createHash('sha256').update(`${wallet.id}:${network.id}`).digest();
/**
 * Produces the legacy address format (e.g. BTC starting with '1') used before
 * the Trust Wallet format fix. This is exposed so the healing script can
 * identify old addresses and migrate them deterministically.
 */
const getLegacyAddress = (network, wallet) => {
    const hash = hashFor(network, wallet);
    const base58 = base58Encode(hash);
    return `1${base58.slice(0, 33)}`;
};
exports.getLegacyAddress = getLegacyAddress;
const generateUtxoAddress = (network, hash) => {
    const format = UTXO_FORMATS[network.code.toUpperCase()];
    if (!format) {
        return `1${base58Encode(hash).slice(0, 33)}`;
    }
    const data = format.encoding === 'base58'
        ? base58EncodeFixed(hash, format.dataLength)
        : bech32EncodeFixed(hash, format.dataLength);
    return `${format.prefix}${data}`;
};
const generateSyntheticAddress = (network, wallet) => {
    const hash = hashFor(network, wallet);
    if (network.addressType.startsWith('bitcoin')) {
        return generateUtxoAddress(network, hash);
    }
    const base58 = base58Encode(hash);
    switch (network.addressType) {
        case 'solana':
            return base58.slice(0, 44);
        case 'ripple':
            return `r${base58.slice(0, 33)}`;
        case 'evm':
        default:
            return `0x${hash.toString('hex').slice(0, 40)}`;
    }
};
/**
 * Generates a deterministic address in the format that Trust Wallet displays
 * for the given network. The result is still synthetic (not derived from the
 * stored seed phrase) but visually matches the expected prefix and length.
 */
const getDeterministicAddress = (network, wallet) => generateSyntheticAddress(network, wallet);
exports.getDeterministicAddress = getDeterministicAddress;
/**
 * Derives the Trust Wallet compatible EVM address from a BIP-39 mnemonic.
 *
 * Trust Wallet uses the standard BIP-44 path for Ethereum:
 *   m/44'/60'/0'/0/0
 *
 * All EVM networks share this single address for a given seed phrase.
 */
const getEvmAddress = (mnemonicPhrase) => {
    return ethers_1.ethers.Wallet.fromPhrase(mnemonicPhrase).address;
};
exports.getEvmAddress = getEvmAddress;
class DeterministicAddressGenerator {
    encryptionService;
    constructor(encryptionService) {
        this.encryptionService = encryptionService;
    }
    generate(network, wallet) {
        if (network.addressType === 'evm') {
            const phrase = this.encryptionService.decrypt(wallet.encryptedPhrase);
            return {
                address: (0, exports.getEvmAddress)(phrase),
                type: network.addressType,
            };
        }
        return {
            address: generateSyntheticAddress(network, wallet),
            type: network.addressType,
        };
    }
}
exports.DeterministicAddressGenerator = DeterministicAddressGenerator;
//# sourceMappingURL=deterministic-address-generator.js.map