"use strict";
/**
 * Midnight provider bundle assembly.
 *
 * Builds the six-provider bundle the Midnight JS SDK expects (per the Counter
 * CLI tutorial): privateState, publicData, zkConfig, proof, wallet, midnight.
 *
 * Split into two stages:
 *
 *  - `buildContractProviders(cfg)`, providers that need no wallet material:
 *    `publicDataProvider`, `zkConfigProvider`, `proofProvider`. Safe to build
 *    on plugin startup or per request.
 *
 *  - `buildFullProviderBundle(cfg, walletMaterial)`, augments the above with
 *    `privateStateProvider`, `walletProvider`, `midnightProvider`. Requires a
 *    decrypted session-scoped passwordProvider + accountId from the wallet
 *    material factory.
 *
 * The two-stage split lets submission construct contract providers cheaply and
 * only assemble wallet-bound providers when an active session is present.
 */
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ensureNetworkId = ensureNetworkId;
exports.buildContractProviders = buildContractProviders;
exports.buildFullProviderBundle = buildFullProviderBundle;
const ws_1 = __importDefault(require("ws"));
const sdk_loader_1 = require("./sdk-loader");
const CapDbPrivateStateProvider_1 = require("./CapDbPrivateStateProvider");
/**
 * The Midnight SDK keeps the active network as process-global state (see
 * `@midnight-ntwrk/midnight-js-network-id`). Every wallet/contract call reads
 * it via `getNetworkId()` and throws "Network ID has not been configured" if
 * it was never set. Call this before any SDK invocation. Idempotent.
 */
let lastSetNetworkId;
async function ensureNetworkId(network) {
    if (lastSetNetworkId === network)
        return;
    const mod = await import('@midnight-ntwrk/midnight-js-network-id');
    mod.setNetworkId(network);
    lastSetNetworkId = network;
}
async function buildContractProviders(cfg) {
    validateContractProvidersConfig(cfg);
    const sdk = await (0, sdk_loader_1.loadMidnightSdk)();
    const zkConfigProvider = new sdk.zk.NodeZkConfigProvider(cfg.zkConfigPath);
    const publicDataProvider = sdk.indexer.indexerPublicDataProvider(cfg.indexerHttpUrl, cfg.indexerWsUrl, 
    // Node has no built-in WebSocket; pass `ws` explicitly.
    ws_1.default);
    const proofProvider = sdk.proof.httpClientProofProvider(cfg.proofServerUrl, zkConfigProvider);
    return { publicDataProvider, zkConfigProvider, proofProvider };
}
async function buildFullProviderBundle(cfg, wallet) {
    validateWalletMaterial(wallet);
    const contractProviders = await buildContractProviders(cfg);
    const backend = wallet.privateStateBackend ?? 'cap-db';
    const checkedPasswordProvider = async () => {
        const pw = await wallet.privateStoragePasswordProvider();
        if (typeof pw !== 'string' || pw.length < 16) {
            throw new Error('Private storage password must be a string of at least 16 characters');
        }
        return pw;
    };
    let privateStateProvider;
    if (backend === 'cap-db') {
        privateStateProvider = new CapDbPrivateStateProvider_1.CapDbPrivateStateProvider({
            accountId: wallet.accountId,
            privateStoragePasswordProvider: checkedPasswordProvider
        });
    }
    else {
        const sdk = await (0, sdk_loader_1.loadMidnightSdk)();
        privateStateProvider = sdk.level.levelPrivateStateProvider({
            accountId: wallet.accountId,
            privateStoragePasswordProvider: checkedPasswordProvider
        });
    }
    return {
        ...contractProviders,
        privateStateProvider,
        walletProvider: wallet.walletAndMidnightProvider,
        midnightProvider: wallet.walletAndMidnightProvider
    };
}
function validateContractProvidersConfig(cfg) {
    if (!cfg.indexerHttpUrl)
        throw new Error('indexerHttpUrl is required');
    if (!cfg.indexerWsUrl)
        throw new Error('indexerWsUrl is required');
    if (!cfg.proofServerUrl)
        throw new Error('proofServerUrl is required');
    if (!cfg.zkConfigPath)
        throw new Error('zkConfigPath is required');
}
function validateWalletMaterial(wallet) {
    if (!wallet.accountId)
        throw new Error('walletMaterial.accountId is required');
    if (!wallet.privateStoragePasswordProvider)
        throw new Error('walletMaterial.privateStoragePasswordProvider is required');
    if (!wallet.walletAndMidnightProvider)
        throw new Error('walletMaterial.walletAndMidnightProvider is required');
}
