"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createAuthentication = exports.createPrivateKeyAuthentication = exports.AuthenticationInjectionToken = void 0;
const utils_1 = require("@streamr/utils");
const ethers_1 = require("ethers");
const p_memoize_1 = __importDefault(require("p-memoize"));
const promises_1 = require("./utils/promises");
exports.AuthenticationInjectionToken = Symbol('Authentication');
const createPrivateKeyAuthentication = (key) => {
    const userId = (0, utils_1.toUserId)((0, ethers_1.computeAddress)(key));
    return {
        getUserId: async () => userId,
        createMessageSignature: async (payload) => (0, utils_1.createSignature)(payload, (0, utils_1.hexToBinary)(key)),
        getTransactionSigner: async (rpcProviderSource) => {
            const primaryProvider = rpcProviderSource.getProvider();
            return new ethers_1.Wallet(key, primaryProvider);
        }
    };
};
exports.createPrivateKeyAuthentication = createPrivateKeyAuthentication;
const createAuthentication = (config) => {
    if (config.auth?.privateKey !== undefined) {
        const privateKey = config.auth.privateKey;
        const normalizedPrivateKey = !privateKey.startsWith('0x')
            ? `0x${privateKey}`
            : privateKey;
        return (0, exports.createPrivateKeyAuthentication)(normalizedPrivateKey);
    }
    else if (config.auth?.ethereum !== undefined) {
        const ethereum = config.auth?.ethereum;
        const provider = new ethers_1.BrowserProvider(ethereum);
        const signer = provider.getSigner();
        return {
            getUserId: (0, p_memoize_1.default)(async () => {
                return (0, utils_1.toUserId)(await (await signer).getAddress());
            }),
            createMessageSignature: (0, promises_1.pLimitFn)(async (payload) => {
                // sign one at a time & wait a moment before asking for next signature
                // otherwise MetaMask extension may not show the prompt window
                const sig = await (await signer).signMessage(payload);
                await (0, utils_1.wait)(50);
                return (0, utils_1.hexToBinary)(sig);
            }, 1),
            getTransactionSigner: async () => {
                if (config.contracts.ethereumNetwork.chainId === undefined) {
                    throw new Error('Streamr chainId not configuredin the StreamrClient options!');
                }
                const expectedChainId = config.contracts.ethereumNetwork.chainId;
                const actualChainId = (await provider.getNetwork()).chainId;
                if (actualChainId !== BigInt(expectedChainId)) {
                    throw new Error(`Please connect the custom authentication provider with chainId ${expectedChainId} (current chainId is ${actualChainId})`);
                }
                return signer;
                // TODO: handle events
                // ethereum.on('accountsChanged', (accounts) => { })
                // https://docs.metamask.io/guide/ethereum-provider.html#events says:
                //   "We recommend reloading the page unless you have a very good reason not to"
                //   Of course we can't and won't do that, but if we need something chain-dependent...
                // ethereum.on('chainChanged', (chainId) => { window.location.reload() });
            }
        };
    }
    else {
        return (0, exports.createPrivateKeyAuthentication)(ethers_1.Wallet.createRandom().privateKey);
    }
};
exports.createAuthentication = createAuthentication;
//# sourceMappingURL=Authentication.js.map