/**
 * LocalKeyVault
 *
 * In-process KeyVault that wraps the WASM PrivacyBoost module directly.
 * Keys live in the same JS context. This is the backward-compatible default.
 */
import { createChainClient } from '../core/chains';
import { convertMapsToObjects } from './schemas';
const LS_SESSION_KEY = 'pb:privacyboost:session';
export class LocalKeyVault {
    wasmModule;
    wasm = null;
    _chainId = 0;
    _serverUrl = '';
    _appId = '';
    _rpcUrl;
    _publicClient = null;
    walletBridge = null;
    constructor(wasmModule) {
        this.wasmModule = wasmModule;
    }
    ensureWasm() {
        if (!this.wasm)
            throw new Error('LocalKeyVault not initialized');
        return this.wasm;
    }
    /** @internal Used by PrivacyBoost.ts for non-crypto operations (balances, etc.) */
    getWasmInstance() {
        return this.wasm;
    }
    async initialize(config) {
        this._chainId = config.chainId;
        this._serverUrl = config.serverUrl.replace(/\/+$/, '');
        this._appId = config.appId ?? '';
        this._rpcUrl = config.rpcUrl;
        // Cast to WasmSDK: the fine-grained crypto methods exist on the
        // wasm-bindgen struct but are not yet in the auto-generated .d.ts.
        this.wasm = new this.wasmModule.PrivacyBoost({
            serverUrl: config.serverUrl,
            chainId: config.chainId ?? 0,
            shieldContractAddress: config.shieldContractAddress ?? '',
            wethContractAddress: config.wethContractAddress,
            rpcUrl: config.rpcUrl,
            tokenRegistryAddress: config.tokenRegistryAddress,
            appId: config.appId,
            persistenceStorage: config.persistence?.storage,
            persistenceUnlock: config.persistence?.unlock,
            autoConsolidate: config.autoConsolidate,
            autoConsolidateThreshold: config.autoConsolidateThreshold,
            autoConsolidateMaxRounds: config.autoConsolidateMaxRounds,
        });
    }
    getOrCreatePublicClient() {
        if (!this._publicClient) {
            this._publicClient = createChainClient(this._chainId, this._rpcUrl);
        }
        return this._publicClient;
    }
    dispose() {
        this.wasm = null;
        this.walletBridge = null;
        this._publicClient = null;
    }
    // -- Authentication --
    async authenticate(keySource, tokenProviderCallback) {
        const wasm = this.ensureWasm();
        if (!this.walletBridge)
            throw new Error('Wallet bridge not set');
        const walletProxy = {
            signMessage: (msg) => this.walletBridge.signMessage(msg),
            signTypedData: (data) => this.walletBridge.signTypedData(data),
            sendTransaction: (tx) => this.walletBridge.sendTransaction(tx),
            getAddress: () => this.walletBridge.getAddress(),
            getChainId: () => this.walletBridge.getChainId(),
            waitForTransactionReceipt: async (txHash) => {
                const client = this.getOrCreatePublicClient();
                const receipt = await client.waitForTransactionReceipt({
                    hash: txHash,
                });
                return {
                    transactionHash: receipt.transactionHash,
                    status: receipt.status === 'success',
                    logs: receipt.logs.map((log) => ({
                        address: log.address,
                        topics: [...log.topics],
                        data: log.data,
                    })),
                };
            },
        };
        const raw = await wasm.authenticate(walletProxy, keySource, tokenProviderCallback);
        return raw;
    }
    async submitCredential(credential, tokenProviderCallback) {
        const wasm = this.ensureWasm();
        const raw = await wasm.submitCredential(credential, tokenProviderCallback);
        return raw;
    }
    async proceedAfterMnemonic(credential, tokenProviderCallback) {
        const wasm = this.ensureWasm();
        const raw = await wasm.proceedAfterMnemonic(credential, tokenProviderCallback);
        return raw;
    }
    async logout() {
        const wasm = this.ensureWasm();
        await wasm.logout();
    }
    async clearSession() {
        const wasm = this.ensureWasm();
        await wasm.clearSession();
    }
    // -- Session Persistence --
    async getStoredSession() {
        try {
            const raw = localStorage.getItem(LS_SESSION_KEY);
            if (!raw)
                return null;
            const store = JSON.parse(raw);
            if (!store.sessions)
                return null;
            const scopeKey = `${this._serverUrl}|${this._appId}|${this._chainId}`;
            const saved = store.sessions[scopeKey];
            if (!saved)
                return null;
            return {
                token: saved.token,
                expirySecs: saved.expiry_secs,
                walletAddress: saved.wallet_address,
                vaultExists: saved.vault_exists,
                chainRegistrations: saved.chain_registrations,
            };
        }
        catch {
            return null;
        }
    }
    // -- Key Status --
    async getKeyStatus() {
        const wasm = this.ensureWasm();
        if (wasm.getKeyStatus) {
            return wasm.getKeyStatus();
        }
        return wasm.isAuthenticated ? 'ready' : 'none';
    }
    async getPublicKeys() {
        // serde_wasm_bindgen serializes Rust maps as JS Map objects;
        // convert to plain objects so callers can use dot notation.
        return convertMapsToObjects(this.ensureWasm().getPublicKeys());
    }
    isAuthenticated() {
        return this.wasm?.isAuthenticated ?? false;
    }
    getPrivacyAddress() {
        return this.wasm?.getPrivacyAddress() ?? null;
    }
    getMpk() {
        return this.wasm?.getMpk() ?? null;
    }
    async deleteVault() {
        const wasm = this.ensureWasm();
        await wasm.deleteVault();
    }
    // -- Deposit Crypto --
    async buildShieldCommitment(params) {
        return this.ensureWasm().buildShieldCommitment(params.tokenId, params.amount, params.recipientMpk);
    }
    async encryptDepositCiphertext(params) {
        return this.ensureWasm().encryptDepositCiphertext(params.teePublicKey, params.tokenId, params.amount, params.randomIn, params.outputIndex);
    }
    // -- Transfer / Withdraw Crypto --
    async computeNullifiers(notes) {
        return this.ensureWasm().computeNullifiers(notes);
    }
    async generateNpk(recipientMpk, randomIn) {
        return this.ensureWasm().generateNpk(recipientMpk, randomIn);
    }
    async computeOutputCommitment(npk, tokenId, amount) {
        return this.ensureWasm().computeOutputCommitment(npk, tokenId, amount);
    }
    async deriveEcdhKeys(params) {
        return this.ensureWasm().deriveEcdhKeys(params.teePublicKey, params.recipientViewingPubKey);
    }
    async encryptTransferCiphertext(params) {
        return this.ensureWasm().encryptTransferCiphertext(params);
    }
    async signSpending(digestHi, digestLo) {
        return this.ensureWasm().signSpending(digestHi, digestLo);
    }
    // -- Digest Computation --
    async computeTransferDigest(params) {
        return this.ensureWasm().computeTransferDigest(params);
    }
    async computeWithdrawalDigest(params) {
        return this.ensureWasm().computeWithdrawalDigest(params);
    }
    async computeWithdrawalCommitment(recipientAddr, tokenId, amount) {
        return this.ensureWasm().computeWithdrawalCommitment(recipientAddr, tokenId, amount);
    }
    // -- Auth Crypto --
    async signViewAuth(mpk, nonce) {
        return convertMapsToObjects(this.ensureWasm().signViewAuth(mpk, nonce));
    }
    async getRegistrationData() {
        return convertMapsToObjects(this.ensureWasm().getRegistrationData());
    }
    // -- High-level Operations --
    async shield(tokenAddress, amount, onProgress) {
        const wasm = this.ensureWasm();
        if (typeof wasm.shield === 'function') {
            return wasm.shield({ tokenAddress, amount, onProgress });
        }
        if (typeof wasm.deposit === 'function') {
            return wasm.deposit(tokenAddress, amount);
        }
        throw new Error('LocalKeyVault: WASM SDK missing shield/deposit method');
    }
    async sendTransfer(tokenAddress, amount, recipientPrivacyAddress) {
        return this.ensureWasm().send({ tokenAddress, amount, to: recipientPrivacyAddress });
    }
    async unshield(tokenAddress, amount, recipientAddress, onProgress) {
        const wasm = this.ensureWasm();
        if (typeof wasm.unshield === 'function') {
            return wasm.unshield({ tokenAddress, amount, recipientAddress, onProgress });
        }
        if (typeof wasm.withdraw === 'function') {
            return wasm.withdraw(tokenAddress, amount, recipientAddress);
        }
        throw new Error('LocalKeyVault: WASM SDK missing unshield/withdraw method');
    }
    async consolidateNotes(tokenAddress, maxRounds) {
        const wasm = this.ensureWasm();
        if (typeof wasm.consolidateNotes === 'function') {
            return wasm.consolidateNotes(tokenAddress, maxRounds);
        }
        throw new Error('LocalKeyVault: WASM SDK missing consolidateNotes method');
    }
    async unwrapWeth(amount, recipientAddress) {
        return this.ensureWasm().unwrapWeth(amount, recipientAddress);
    }
    // -- Wallet Bridge --
    setWalletBridge(bridge) {
        this.walletBridge = bridge;
    }
}
//# sourceMappingURL=LocalKeyVault.js.map