var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
    if (kind === "m") throw new TypeError("Private method is not writable");
    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
    return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
    if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
    if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
    return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var _Detector_chainSpecs, _Detector_name, _Detector_isExtension, _Detector_providers;
import { ApiPromise } from '@polkadot/api';
import { SmoldotProvider } from './SmoldotProvider/SmoldotProvider.js';
import { ExtensionProvider } from './ExtensionProvider/ExtensionProvider.js';
import westend from './specs/westend.json';
import kusama from './specs/kusama.json';
import polkadot from './specs/polkadot.json';
/**
 * Detector is an API for providing an instance of the PolkadotJS API configured
 * to use a WASM-based light client.  It takes care of detecting whether the
 * user has the substrate connect browser extension installed or not and
 * configures the PolkadotJS API appropriately; falling back to a provider
 * which instantiates the WASM light client in the page when the extension is
 * not available.
 *
 * @example
 *
 * ```
 * import { Detector } from '@substrate/connect';
 *
 * // Create a new UApp with a unique name
 * const app = new Detector('burnr-wallet');
 * const westend = await app.connect('westend');
 * const kusama = await app.connect('kusama');
 *
 * await westend.rpc.chain.subscribeNewHeads((lastHeader) => {
 *   console.log(lastHeader.hash);
 * );
 * await kusama.rpc.chain.subscribeNewHeads((lastHeader) => {
 *   console.log(lastHeader.hash);
 * });
 *
 * // Interact with westend and kusama APIs ...
 *
 * await westend.disconnect();
 * await kusama.disconnect();
 * ```
 */
export class Detector {
    /**
     * @param name - the name of your app.
     *
     * @remarks
     *
     * You should make a best effort to make your app name unique to avoid
     * confusion for users in the extension user interface
     */
    constructor(name) {
        _Detector_chainSpecs.set(this, {
            // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
            'polkadot': polkadot,
            // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
            'kusama': kusama,
            // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
            'westend': westend
        });
        _Detector_name.set(this, void 0);
        _Detector_isExtension.set(this, void 0);
        _Detector_providers.set(this, {});
        /**
         * connect attempts to detect the extension and configures the PolkadotJS
         * API instance to return appropriately.
         *
         * There are 3 bundled networks: "polkadot", "kusama" and "westend" which
         * require no further configuration.
         *
         * Alternatively you may supply a chain spec and options to connect to a
         * custom chain with a light client (in-page only).
         *
         * @param chainName - the name of the blockchain network to connect to
         * @param chainSpec - an optional chainSpec to connect to a different network
         * @param options - any extra API options to passed to PolkadotJS when
         * constructing it.
         * @returns a promise that resolves to an instance of the PolkadotJS API
         *
         * @remarks
         *
         * When providing a custom chain spec, detect will always configure and return
         * an in-page light client and not use the extension
         *
         * Typically options is used to pass custom types to PolkadotJS API.
         *
         * See the PolkadotJS docs for documentation on using PolkadotJS.
         *
         * {@link https://polkadot.js.org/docs/}
         */
        this.connect = async (chainName, chainSpec, options) => {
            const provider = this.provider(chainName, chainSpec);
            provider.connect().catch(console.error);
            __classPrivateFieldGet(this, _Detector_providers, "f")[chainName] = provider;
            return await ApiPromise.create(Object.assign(options !== null && options !== void 0 ? options : {}, { provider }));
        };
        /**
         * Detects and returns an appropriate PolkadotJS provider depending on whether the user has the substrate connect extension installed
         *
         * @param chainName - the name of the blockchain network to connect to
         * @param chainSpec - an optional chainSpec to connect to a different network
         * @returns a provider will be used in a ApiPromise create for PolkadotJS API
         *
         * @internal
         *
         * @remarks
         * This is used internally for advanced PolkadotJS use cases and is not supported.  Use {@link connect} instead.
         */
        this.provider = (chainName, chainSpec) => {
            let provider = {};
            if (Object.keys(__classPrivateFieldGet(this, _Detector_chainSpecs, "f")).includes(chainName)) {
                if (__classPrivateFieldGet(this, _Detector_isExtension, "f")) {
                    provider = new ExtensionProvider(__classPrivateFieldGet(this, _Detector_name, "f"), chainName);
                }
                else if (!__classPrivateFieldGet(this, _Detector_isExtension, "f")) {
                    const chainSpec = JSON.stringify(__classPrivateFieldGet(this, _Detector_chainSpecs, "f")[chainName]);
                    provider = new SmoldotProvider(chainSpec);
                }
            }
            else if (chainSpec) {
                provider = new SmoldotProvider(chainSpec);
            }
            else if (!chainSpec) {
                throw new Error(`No known Chain was detected and no chainSpec was provided. Either give a known chain name ('${Object.keys(__classPrivateFieldGet(this, _Detector_chainSpecs, "f")).join('\', \'')}') or provide valid chainSpecs.`);
            }
            return provider;
        };
        /**
         * disconnect disconnects the PolkadotJS API isntance
         *
         * @param chainName - the name of the blockchain network to disconnect from
         */
        this.disconnect = async (chainName) => {
            await __classPrivateFieldGet(this, _Detector_providers, "f")[chainName].disconnect();
            delete __classPrivateFieldGet(this, _Detector_providers, "f")[chainName];
        };
        __classPrivateFieldSet(this, _Detector_isExtension, !!document.getElementById('substrateExtension'), "f");
        __classPrivateFieldSet(this, _Detector_name, name, "f");
    }
    /**
     * name is the name of the app. This is used by the extension to identify
     * your app in the user interface
     */
    get name() {
        return __classPrivateFieldGet(this, _Detector_name, "f");
    }
}
_Detector_chainSpecs = new WeakMap(), _Detector_name = new WeakMap(), _Detector_isExtension = new WeakMap(), _Detector_providers = new WeakMap();
//# sourceMappingURL=Detector.js.map