'use client'
'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var _tslib = require('../../../../../_virtual/_tslib.cjs');
var React = require('react');
var sdkApiCore = require('@dynamic-labs/sdk-api-core');
var utils = require('@dynamic-labs/utils');
var walletConnectorCore = require('@dynamic-labs/wallet-connector-core');
var UserWalletsContext = require('../../../context/UserWalletsContext/UserWalletsContext.cjs');
require('@dynamic-labs-sdk/client/core');
require('../../../client/client.cjs');
require('@dynamic-labs-sdk/client');
require('../../../config/ApiEndpoint.cjs');
require('@dynamic-labs/iconic');
require('react/jsx-runtime');
require('../../../context/ViewContext/ViewContext.cjs');
require('../../../shared/logger.cjs');
require('@dynamic-labs/wallet-book');
require('../../constants/colors.cjs');
require('../../constants/values.cjs');
require('../../../shared/consts/index.cjs');
require('@dynamic-labs/multi-wallet');
require('react-international-phone');
require('../../../store/state/nonce/nonce.cjs');
var shouldManuallyReconnectOnRefresh = require('../../functions/shouldManuallyReconnectOnRefresh/shouldManuallyReconnectOnRefresh.cjs');
var updatePrimaryWalletId = require('../../functions/updatePrimaryWalletId/updatePrimaryWalletId.cjs');
var getWalletUniqueId = require('../../functions/getWalletUniqueId/getWalletUniqueId.cjs');
var connectedWalletsInfo = require('../../../store/state/connectedWalletsInfo/connectedWalletsInfo.cjs');
require('../../../store/state/dynamicContextProps/dynamicContextProps.cjs');
var primaryWalletId = require('../../../store/state/primaryWalletId/primaryWalletId.cjs');
var dynamicEvents = require('../../../events/dynamicEvents.cjs');
var session = require('../../../data/api/session/session.cjs');
require('@dynamic-labs/locale');
var authMode = require('../../../store/state/authMode/authMode.cjs');
var getWalletConnectorForWallet = require('../../functions/getWalletConnectorForWallet/getWalletConnectorForWallet.cjs');
var isConnectOnly = require('../authenticationHooks/helpers/isConnectOnly.cjs');
var useDebounce = require('../useDebounce/useDebounce.cjs');
var HandleConnectWalletRejectionError = require('./HandleConnectWalletRejectionError.cjs');
var updateUserWalletsFromConnectedWallets = require('./updateUserWalletsFromConnectedWallets/updateUserWalletsFromConnectedWallets.cjs');

const useConnectWallet = ({ enableVisitTrackingOnConnectOnly, environmentId, primaryWalletId: primaryWalletId$1, walletConnectorOptions, handleConnectedWallet, setShowAuthFlow, isBridgeFlow, }) => {
    const connectedWalletsInfo$1 = connectedWalletsInfo.useConnectedWalletsInfo();
    const [connectedWallets, _setConnectedWallets] = React.useState([]);
    const { setUserWallets, addedWalletsIds, removedWalletsIds } = UserWalletsContext.useInternalUserWallets();
    /** This wrapper is to ensure userWallets is always properly updated alongside connectedWallets */
    const setConnectedWallets = React.useCallback((newWallets) => {
        // Prevent unnecessary re-renders when state is empty
        _setConnectedWallets((prevWallets) => {
            if (prevWallets.length === 0 && newWallets.length === 0) {
                return prevWallets;
            }
            return newWallets;
        });
        setUserWallets((userWallets) => updateUserWalletsFromConnectedWallets.updateUserWalletsFromConnectedWallets(userWallets, newWallets));
    }, [setUserWallets]);
    const disconnectWallet = React.useCallback((walletId) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
        const walletToDisconnect = connectedWallets.find((wallet) => wallet.id === walletId);
        yield (walletToDisconnect === null || walletToDisconnect === void 0 ? void 0 : walletToDisconnect.connector.endSession());
        const updatedConnectedWalletsInfo = connectedWalletsInfo$1.filter((wallet) => wallet.id !== walletId);
        connectedWalletsInfo.setConnectedWalletsInfo(updatedConnectedWalletsInfo);
        removedWalletsIds.current.push(walletId);
        if (walletId !== primaryWalletId$1) {
            return;
        }
        const hasConnectedWallet = updatedConnectedWalletsInfo.length > 0;
        if (isBridgeFlow || !hasConnectedWallet) {
            primaryWalletId.resetPrimaryWalletId();
        }
        else {
            updatePrimaryWalletId.updatePrimaryWalletId(updatedConnectedWalletsInfo[0].id);
        }
    }), [
        connectedWallets,
        connectedWalletsInfo$1,
        isBridgeFlow,
        primaryWalletId$1,
        removedWalletsIds,
    ]);
    // The function to update and define the connectedWallets list.
    // It should be called on the first render, when connectedWalletsInfo updates and when walletConnectorOptions updates.
    // To avoid unnecessary updates that are causing issues with connectors added asynchronously,
    // we're debouncing this function
    const updateConnectedWalletsList = useDebounce.useDebounce(() => _tslib.__awaiter(void 0, void 0, void 0, function* () {
        const walletConnectors = walletConnectorOptions.map((wallet) => wallet.walletConnector);
        if (!walletConnectors.length) {
            return;
        }
        const updatedConnectedWallets = (yield Promise.all(connectedWalletsInfo$1.map((storedConnectedWalletInfo) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
            const walletConnector = walletConnectorCore.getWalletConnectorByKey(walletConnectors, storedConnectedWalletInfo.walletConnectorKey, storedConnectedWalletInfo.walletChain);
            if (!walletConnector) {
                walletConnectorCore.logger.error('Could not find walletConnector: ' +
                    storedConnectedWalletInfo.walletConnectorKey);
                yield disconnectWallet(storedConnectedWalletInfo.id);
                return null;
            }
            if (walletConnectorCore.isHardwareWalletConnector(walletConnector) &&
                storedConnectedWalletInfo.hardwareWallet ===
                    sdkApiCore.HardwareWalletEnum.Ledger) {
                walletConnector.isHardwareWalletEnabled = true;
            }
            const [walletAddress] = yield walletConnector.getConnectedAccounts();
            if (!walletAddress) {
                yield disconnectWallet(storedConnectedWalletInfo.id);
                return null;
            }
            const additionalAddresses = yield walletConnector.getAdditionalAddresses(walletAddress);
            const walletChain = walletConnector.connectedChain;
            const walletObject = walletConnector.createWallet({
                additionalAddresses,
                address: walletAddress,
                chain: walletChain,
                connector: walletConnector,
                id: storedConnectedWalletInfo.id,
                isAuthenticated: false,
                key: walletConnector.key,
            });
            return walletObject;
        })))).filter((wallet) => Boolean(wallet));
        setConnectedWallets(updatedConnectedWallets);
    }), 300);
    // Generate the connectedWallets list when connectedWalletsInfo (localStorage) or memoized wallet connector updates
    React.useEffect(() => {
        updateConnectedWalletsList();
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [connectedWalletsInfo$1, walletConnectorOptions]);
    const updateConnectedWalletById = React.useCallback((walletId, walletObject) => {
        var _a;
        const clonedConnectedWalletsList = [...connectedWallets];
        const connectedWalletIndex = clonedConnectedWalletsList.findIndex((connectedWallet) => connectedWallet.id === walletId);
        if (connectedWalletIndex < 0) {
            return;
        }
        clonedConnectedWalletsList[connectedWalletIndex] =
            clonedConnectedWalletsList[connectedWalletIndex].connector.createWallet(Object.assign(Object.assign({}, clonedConnectedWalletsList[connectedWalletIndex]), { address: (_a = walletObject.address) !== null && _a !== void 0 ? _a : clonedConnectedWalletsList[connectedWalletIndex].address, connector: getWalletConnectorForWallet.getWalletConnectorForWallet(clonedConnectedWalletsList[connectedWalletIndex]) }));
        setConnectedWallets(clonedConnectedWalletsList);
    }, [connectedWallets, setConnectedWallets]);
    // Keeps connected wallet data inside localStorage
    const applyConnectedWalletToStore = React.useCallback(({ walletId, walletConnectorKey, walletChain, provider, }) => {
        const updatedConnectedWalletsInfo = [...connectedWalletsInfo$1];
        const walletConnectors = walletConnectorOptions.map((wallet) => wallet.walletConnector);
        const walletConnector = walletConnectorCore.getWalletConnectorByKey(walletConnectors, walletConnectorKey, walletChain);
        const hardwareWallet = walletConnector &&
            walletConnectorCore.isHardwareWalletConnector(walletConnector) &&
            walletConnector.isHardwareWalletEnabled
            ? sdkApiCore.HardwareWalletEnum.Ledger
            : undefined;
        updatedConnectedWalletsInfo.push({
            hardwareWallet,
            id: walletId,
            provider,
            walletChain,
            walletConnectorKey,
        });
        connectedWalletsInfo.setConnectedWalletsInfo(updatedConnectedWalletsInfo);
    }, [connectedWalletsInfo$1, walletConnectorOptions]);
    // Updates connected wallet (network and address) and verifies connected wallet connection
    const refreshConnectedWallet = (walletId, walletConnector) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
        if (shouldManuallyReconnectOnRefresh.shouldManuallyReconnectOnRefresh(walletConnector)) {
            yield walletConnector.connect();
        }
        const currentWalletConnectorAddress = yield walletConnector.getAddress();
        if (currentWalletConnectorAddress && handleConnectedWallet) {
            const shouldProceedWithConnection = yield handleConnectedWallet({
                address: currentWalletConnectorAddress,
                chain: walletConnector.connectedChain,
                connector: walletConnector,
            });
            if (!shouldProceedWithConnection) {
                walletConnectorCore.logger.info('Connection was not established because handleConnectedWallet returned false');
                disconnectWallet(walletId);
                setShowAuthFlow(false, { emitCancelAuth: true });
                return;
            }
        }
        updateConnectedWalletById(walletId, {
            address: currentWalletConnectorAddress,
        });
    });
    const connectWallet = React.useCallback((walletConnector, getAddressOpts, options) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
        const { applyHandleConnectedWallet = true } = options !== null && options !== void 0 ? options : {};
        let walletAddress;
        try {
            walletAddress = yield walletConnector.getAddress(getAddressOpts);
        }
        catch (error) {
            if (error instanceof utils.CustomError) {
                dynamicEvents.dynamicEvents.emit('walletConnectionFailed', walletConnector, error);
                throw error;
            }
            dynamicEvents.dynamicEvents.emit('walletConnectionFailed', walletConnector, error);
            throw new utils.MissingPublicAddressError();
        }
        // Throw a generic error for any errors we're not processing above
        if (!walletAddress) {
            const missingPublicAddressError = new utils.MissingPublicAddressError();
            dynamicEvents.dynamicEvents.emit('walletConnectionFailed', walletConnector, missingPublicAddressError);
            throw missingPublicAddressError;
        }
        if (handleConnectedWallet && applyHandleConnectedWallet) {
            const shouldProceedWithConnection = yield handleConnectedWallet({
                address: walletAddress,
                chain: walletConnector.connectedChain,
                connector: walletConnector,
            });
            if (!shouldProceedWithConnection) {
                walletConnectorCore.logger.info('Connection was not established because handleConnectedWallet returned false');
                setShowAuthFlow(false);
                dynamicEvents.dynamicEvents.emit('walletConnectionFailed', walletConnector, new HandleConnectWalletRejectionError.HandleConnectWalletRejectionError(walletConnector));
                return;
            }
        }
        const isWalletStored = connectedWalletsInfo$1.some(({ walletConnectorKey: storedWalletConnectorKey }) => storedWalletConnectorKey === walletConnector.key);
        const walletChain = walletConnector.connectedChain;
        const authMode$1 = authMode.getAuthMode();
        const shouldCreateVisit = !isWalletStored &&
            (authMode$1 !== 'connect-only' || enableVisitTrackingOnConnectOnly);
        if (shouldCreateVisit) {
            // send information to backend to kick off background jobs
            // so verify/sign on the next step could go by more quickly
            // this is async work, but DO NOT AWAIT
            void session.createVisit({
                authMode: authMode$1,
                chain: walletChain || '',
                environmentId,
                publicWalletAddress: walletAddress,
                walletName: walletConnector.key,
                walletProvider: walletConnectorCore.getWalletProvider(walletConnector),
            });
        }
        // On connect and sign, we don't want to add this wallet to userWallets
        // until it has been signed. Therefore, we don't add it to
        // the connectedWallets array because userWallets draws from it.
        // In this scenario we only need the wallet address, since the id will come from somewhere else.
        // In fact, there is a refactor planned to never use the connect-wallet-X ids anymore:
        // https://linear.app/dynamic-labs/issue/QNTM-784/rework-the-way-we-compute-wallet-ids
        if (!isConnectOnly.isConnectOnly())
            return { address: walletAddress, id: '' };
        const walletId = getWalletUniqueId.getWalletUniqueId({
            address: walletAddress,
            chain: walletConnector.connectedChain,
            connectorKey: walletConnector.key,
        });
        if (!primaryWalletId$1) {
            updatePrimaryWalletId.updatePrimaryWalletId(walletId);
        }
        addedWalletsIds.current.push(walletId);
        if (isWalletStored) {
            yield updateConnectedWalletsList();
        }
        else {
            applyConnectedWalletToStore({
                provider: walletConnectorCore.getWalletProvider(walletConnector),
                walletAddress: walletAddress,
                walletChain,
                walletConnectorKey: walletConnector.key,
                walletId,
            });
        }
        return { address: walletAddress, id: walletId };
    }), [
        addedWalletsIds,
        applyConnectedWalletToStore,
        connectedWalletsInfo$1,
        enableVisitTrackingOnConnectOnly,
        environmentId,
        handleConnectedWallet,
        primaryWalletId$1,
        setShowAuthFlow,
        updateConnectedWalletsList,
    ]);
    const getConnectedWalletById = React.useCallback((walletId) => connectedWallets.find((wallet) => wallet.id === walletId), [connectedWallets]);
    return {
        connectWallet,
        connectedWallets,
        connectedWalletsInfo: connectedWalletsInfo$1,
        disconnectWallet,
        getConnectedWalletById,
        refreshConnectedWallet,
    };
};

exports.useConnectWallet = useConnectWallet;
