'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 types = require('@dynamic-labs/types');
var utils = require('@dynamic-labs/utils');
var client = require('../../../client/client.cjs');
var CaptchaContext = require('../../../context/CaptchaContext/CaptchaContext.cjs');
require('../../../context/DynamicContext/DynamicContext.cjs');
require('../../../store/state/loadingAndLifecycle/loadingAndLifecycle.cjs');
require('@dynamic-labs/iconic');
require('@dynamic-labs/wallet-connector-core');
require('react/jsx-runtime');
require('../../../context/ViewContext/ViewContext.cjs');
var logger = require('../../../shared/logger.cjs');
require('@dynamic-labs/wallet-book');
require('../../constants/colors.cjs');
require('../../constants/values.cjs');
require('../../../shared/consts/index.cjs');
var dynamicEvents = require('../../../events/dynamicEvents.cjs');
var ErrorContext = require('../../../context/ErrorContext/ErrorContext.cjs');
var digestSHA256 = require('../../functions/digestSHA256/digestSHA256.cjs');
var encodeBase64URL = require('../../functions/encodeBase64URL/encodeBase64URL.cjs');
require('@dynamic-labs/multi-wallet');
require('react-international-phone');
var getOauthLoginUrl = require('../../functions/getOauthLoginUrl/getOauthLoginUrl.cjs');
var socialStorage = require('../../functions/socialStorage/socialStorage.cjs');
var getProviderByType = require('../../functions/getProviderByType/getProviderByType.cjs');
var nonce = require('../../../store/state/nonce/nonce.cjs');
var randomString = require('../../functions/randomString/randomString.cjs');
require('@dynamic-labs-sdk/client/core');
require('@dynamic-labs-sdk/client');
require('../../../config/ApiEndpoint.cjs');
var oauth = require('../../../data/api/oauth/oauth.cjs');
require('@dynamic-labs/locale');
require('../../../store/state/dynamicContextProps/dynamicContextProps.cjs');
require('../../../store/state/primaryWalletId/primaryWalletId.cjs');
require('../../../store/state/connectedWalletsInfo/connectedWalletsInfo.cjs');
var getClientSessionKeys = require('../../functions/clientSessionKeys/getClientSessionKeys.cjs');
require('../../../context/AccessDeniedContext/AccessDeniedContext.cjs');
require('../../../context/AccountExistsContext/AccountExistsContext.cjs');
require('../../../context/UserWalletsContext/UserWalletsContext.cjs');
require('../../../store/state/authMode/authMode.cjs');
require('../../../context/VerificationContext/VerificationContext.cjs');
require('react-dom');
require('../../functions/compareChains/compareChains.cjs');
require('../../../views/Passkey/utils/findPrimaryEmbeddedChain/findPrimaryEmbeddedChain.cjs');
var useEmbeddedWalletSessionKeys = require('../useEmbeddedWalletSessionKeys/useEmbeddedWalletSessionKeys.cjs');
require('../../../context/ThemeContext/ThemeContext.cjs');
require('../useUserUpdateRequest/useUpdateUser/userFieldsSchema.cjs');
require('bs58');
require('../../../context/SocialRedirectContext/SocialRedirectContext.cjs');
var useUserAuth = require('../useUserAuth/useUserAuth.cjs');
var farcaster = require('./farcaster/farcaster.cjs');
require('yup');
require('../../../context/MockContext/MockContext.cjs');
require('../../../views/CollectUserDataView/useFields.cjs');
require('../../../context/FieldsStateContext/FieldsStateContext.cjs');
require('../../../context/UserFieldEditorContext/UserFieldEditorContext.cjs');
require('@dynamic-labs/rpc-providers');
require('../../../store/state/walletOptions/walletOptions.cjs');
require('react-i18next');
require('../../../components/Accordion/components/AccordionItem/AccordionItem.cjs');
require('../../../components/Alert/Alert.cjs');
require('../../../context/WalletContext/WalletContext.cjs');
require('../../../components/ShadowDOM/ShadowDOM.cjs');
require('../../../components/IconButton/IconButton.cjs');
require('../../../components/InlineWidget/InlineWidget.cjs');
require('../../../components/Input/Input.cjs');
require('../../../components/IsBrowser/IsBrowser.cjs');
require('../../../components/MenuList/Dropdown/Dropdown.cjs');
require('../../../components/OverlayCard/OverlayCard.cjs');
require('../../../components/Transition/ZoomTransition/ZoomTransition.cjs');
require('../../../components/Transition/SlideInUpTransition/SlideInUpTransition.cjs');
require('../../../components/Transition/OpacityTransition/OpacityTransition.cjs');
require('../../../components/PasskeyCreatedSuccessBanner/PasskeyCreatedSuccessBanner.cjs');
require('../../../components/Popper/Popper/Popper.cjs');
require('../../../components/Popper/PopperContext/PopperContext.cjs');
require('react-focus-lock');
require('qrcode');
require('formik');
require('../useSubdomainCheck/useSubdomainCheck.cjs');
require('../../../context/WalletGroupContext/WalletGroupContext.cjs');
require('../../../context/IpConfigurationContext/IpConfigurationContext.cjs');
require('../../../context/ConnectWithOtpContext/ConnectWithOtpContext.cjs');
require('../../../widgets/DynamicBridgeWidget/views/WalletsView/components/SecondaryWallets/SecondaryWallets.cjs');
require('@hcaptcha/react-hcaptcha');
require('../../../context/LoadingContext/LoadingContext.cjs');
require('../../../widgets/DynamicWidget/context/DynamicWidgetContext.cjs');
require('../../../widgets/DynamicWidget/helpers/convertExchangeKeyAndProviderEnum.cjs');
require('../../../views/ExchangeWhitelistWarning/ExchangeWhitelistWarning.cjs');
require('../../../context/ErrorContext/hooks/useErrorText/useErrorText.cjs');
require('../../../context/FooterAnimationContext/index.cjs');
require('../../../views/MfaChooseDeviceView/useGetMfaOptions/useGetMfaOptions.cjs');
require('../../../context/PasskeyContext/PasskeyContext.cjs');
require('../../../context/OnrampContext/OnrampContext.cjs');
require('../../../store/state/sendBalances.cjs');
require('../../../store/state/connectorsInitializing/connectorsInitializing.cjs');
require('../../../components/OverlayCardBase/OverlayCardTarget/OverlayCardTarget.cjs');
require('../../../widgets/DynamicWidget/components/DynamicWidgetHeader/DynamicWidgetHeader.cjs');
require('../../../views/TransactionConfirmationView/TransactionConfirmationView.cjs');
require('../../../widgets/DynamicWidget/components/PasskeyCard/PasskeyCard.cjs');
require('../useEmbeddedWallet/useSecureEnclaveEmbeddedWallet/constants.cjs');
require('../../../widgets/DynamicWidget/views/CryptoComOnramp/CryptoComOnramp.cjs');
require('../../../../index.cjs');
require('../../../widgets/DynamicWidget/views/ReceiveWalletFunds/ReceiveWalletFunds.cjs');
require('../../../store/state/tokenBalances.cjs');
require('../../../store/state/multichainBalances.cjs');
require('../../../shared/utils/functions/getInitialUrl/getInitialUrl.cjs');
var useInternalDynamicContext = require('../../../context/DynamicContext/useDynamicContext/useInternalDynamicContext/useInternalDynamicContext.cjs');

const socialProviders = [
    'apple',
    'coinbasesocial',
    'discord',
    'epicgames',
    'facebook',
    'farcaster',
    'github',
    'google',
    'kraken',
    'line',
    'shopify',
    'spotify',
    'tiktok',
    'telegram',
    'twitch',
    'twitter',
];
// pkce params are only required for twitter and break if added for other providers, like google
// so we should only add provider that support pkce to this list
const providersRequiringPkce = ['twitter', 'github'];
// Hook to handle common social auth logic (for social linking and social sign in)
const useSocialAuth = ({ onSettled, onError, onFarcasterUrl, }) => {
    var _a;
    const { environmentId, setShowAuthFlow, socialSettings, projectSettings, redirectUrl: defaultRedirectUrl, } = useInternalDynamicContext.useInternalDynamicContext();
    /**
     * Represents if the SDK will use a popup or redirect for social auth
     */
    const strategy = React.useMemo(() => (socialSettings === null || socialSettings === void 0 ? void 0 : socialSettings.strategy) || 'redirect', [socialSettings]);
    const { setErrorMessage, setError: setContextError } = ErrorContext.useErrorContext();
    const { initAuth } = useUserAuth.useUserAuth({
        authMethod: 'social',
    });
    const { generateSessionKey, shouldRegisterSessionKeysOnSignin } = useEmbeddedWalletSessionKeys.useEmbeddedWalletSessionKeys({
        environmentId,
        projectSettings,
    });
    const [isProcessing, setIsProcessing] = React.useState(false);
    const [error, setError] = React.useState();
    const { engageCaptcha } = CaptchaContext.useCaptchaContext();
    const clearError = React.useCallback(() => {
        setError(undefined);
        setContextError(undefined);
    }, [setContextError]);
    const onFailed = React.useCallback((provider, reason, options) => {
        setIsProcessing(false);
        onError === null || onError === void 0 ? void 0 : onError();
        onSettled === null || onSettled === void 0 ? void 0 : onSettled();
        if (provider && (options === null || options === void 0 ? void 0 : options.raiseAuthFailure))
            dynamicEvents.dynamicEvents.emit('authFailure', {
                option: provider,
                provider,
                type: 'social',
            }, reason);
    }, [onError, onSettled]);
    const handleError = React.useCallback((provider, code, message, options) => {
        const error = { code, message };
        logger.logger.error(message);
        setError(error);
        setErrorMessage(code);
        onFailed(provider, { error }, options);
    }, [onFailed, setErrorMessage]);
    const checkValidProvider = React.useCallback((provider, authMode) => {
        if (!provider) {
            handleError(provider, types.SocialOAuthErrorCode.NO_PROVIDER, 'Provider is required', { raiseAuthFailure: authMode === 'signin' });
            return false;
        }
        if (!socialProviders.includes(provider)) {
            handleError(provider, types.SocialOAuthErrorCode.INVALID_PROVIDER, `Invalid social provider. Valid providers are: ${socialProviders.join(', ')}`, { raiseAuthFailure: authMode === 'signin' });
            return false;
        }
        return true;
    }, [handleError]);
    const linkAccount = React.useCallback((provider, apiCall) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
        try {
            const response = yield apiCall();
            if (!response) {
                handleError(provider, types.SocialOAuthErrorCode.VERIFICATION_ERROR, `Failed to link social account: ${provider}`, { raiseAuthFailure: false });
                return;
            }
            onSettled === null || onSettled === void 0 ? void 0 : onSettled();
        }
        catch (error) {
            if (error instanceof utils.SocialAccountAlreadyExistsError) {
                handleError(provider, types.SocialOAuthErrorCode.ACCOUNT_ALREADY_LINKED_TO_DIFFERENT_PROFILE, `Social account already linked to a different profile: ${provider}`, { raiseAuthFailure: false });
            }
        }
    }), [handleError, onSettled]);
    const signInAccount = React.useCallback((provider, apiCall) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
        yield initAuth({
            onError: () => handleError(provider, types.SocialOAuthErrorCode.SIGNIN_ERROR, `Failed to sign-in with social account: ${provider}`, { raiseAuthFailure: true }),
            onSettled,
            options: { provider },
            verifyFunction: () => apiCall(),
        });
    }), [handleError, initAuth, onSettled]);
    const completeConnection = React.useCallback((_b) => _tslib.__awaiter(void 0, [_b], void 0, function* ({ authMode, provider, state, authCode, captchaToken, verifier, telegramAuthToken, forceCreateUser = false, ssoProviderId, }) {
        try {
            let sessionPublicKey = undefined;
            utils.tracing.logEvent('oauth', 'completeConnection', utils.tracing.formatObject({
                authMode,
                provider,
                shouldRegisterSessionKeysOnSignin: shouldRegisterSessionKeysOnSignin(),
            }));
            if (shouldRegisterSessionKeysOnSignin()) {
                const keypair = yield generateSessionKey();
                sessionPublicKey = keypair.publicKey;
                utils.tracing.logEvent('oauth', 'completeConnection key generated', utils.tracing.formatObject({
                    sessionPublicKey,
                }));
            }
            if (authMode === 'signin') {
                yield getClientSessionKeys.generateClientSessionKeys();
                if (provider === sdkApiCore.ProviderEnum.Telegram && telegramAuthToken) {
                    const apiCall = () => oauth.telegramSignIn(environmentId, {
                        captchaToken,
                        forceCreateUser,
                        sessionPublicKey,
                        telegramAuthToken,
                    });
                    return yield signInAccount(provider, apiCall);
                }
                else if (provider === sdkApiCore.ProviderEnum.Telegram) {
                    const apiCall = () => oauth.telegramSignIn(environmentId, {
                        captchaToken,
                        code: authCode,
                        sessionPublicKey,
                        state,
                    });
                    yield signInAccount(provider, apiCall);
                }
                else {
                    const apiCall = () => oauth.signInOAuth(environmentId, provider, {
                        captchaToken,
                        code: authCode,
                        codeVerifier: verifier,
                        sessionPublicKey,
                        ssoProviderId,
                        state,
                    });
                    yield signInAccount(provider, apiCall);
                }
            }
            else {
                if (provider === sdkApiCore.ProviderEnum.Telegram) {
                    const apiCall = () => oauth.telegramVerify(environmentId, {
                        captchaToken,
                        code: authCode,
                        state,
                    });
                    yield linkAccount(provider, apiCall);
                }
                else {
                    const apiCall = () => oauth.verifyOAuth(environmentId, provider, {
                        code: authCode,
                        codeVerifier: verifier,
                        state,
                    });
                    yield linkAccount(provider, apiCall);
                }
            }
        }
        catch (error) {
            logger.logger.error('Social connection failed with unexpected error:', error);
            onFailed(provider, { error }, { raiseAuthFailure: authMode === 'signin' });
        }
    }), [
        environmentId,
        generateSessionKey,
        linkAccount,
        onFailed,
        shouldRegisterSessionKeysOnSignin,
        signInAccount,
    ]);
    const connectWithFarcaster = React.useCallback((authMode_1, _c) => _tslib.__awaiter(void 0, [authMode_1, _c], void 0, function* (authMode, { captchaToken, redirectUrl }) {
        let dynamicNonce;
        try {
            dynamicNonce = nonce.consumeNonce();
        }
        catch (error) {
            handleError(sdkApiCore.ProviderEnum.Farcaster, types.SocialOAuthErrorCode.GENERAL_ERROR, 'Missing nonce', { raiseAuthFailure: authMode === 'signin' });
            return;
        }
        const domain = utils.PlatformService.getHost();
        const data = yield farcaster.connect({
            domain,
            nonce: dynamicNonce,
            redirectUrl: redirectUrl || defaultRedirectUrl,
            siweUri: utils.PlatformService.getOrigin(),
        });
        if (!(data === null || data === void 0 ? void 0 : data.url) || !(data === null || data === void 0 ? void 0 : data.channelToken)) {
            handleError(sdkApiCore.ProviderEnum.Farcaster, types.SocialOAuthErrorCode.GENERAL_ERROR, "Farcaster didn't return a valid url.", { raiseAuthFailure: authMode === 'signin' });
            return;
        }
        // If on mobile, we want to redirect to the Warpcast app.
        if (utils.isMobile()) {
            yield utils.PlatformService.openURL(data.url);
        }
        else {
            setShowAuthFlow(true);
            onFarcasterUrl === null || onFarcasterUrl === void 0 ? void 0 : onFarcasterUrl(data.url);
        }
        const statusResponse = yield farcaster.watchStatus({
            channelToken: data.channelToken,
        });
        if (statusResponse.type === 'cancelled') {
            setIsProcessing(false);
            return;
        }
        if (statusResponse.type === 'timeout') {
            handleError(sdkApiCore.ProviderEnum.Farcaster, types.SocialOAuthErrorCode.GENERAL_ERROR, `Farcaster timed out while waiting for connection status. Error: ${statusResponse.error}`, { raiseAuthFailure: authMode === 'signin' });
            return;
        }
        if (!statusResponse.data.message ||
            !statusResponse.data.custody ||
            !statusResponse.data.signature ||
            !statusResponse.data.nonce) {
            handleError(sdkApiCore.ProviderEnum.Farcaster, types.SocialOAuthErrorCode.GENERAL_ERROR, `Farcaster returned invalid data. Expected to be defined: message, custody, signature, nonce. Received: ${JSON.stringify(statusResponse.data)}`, { raiseAuthFailure: authMode === 'signin' });
            return;
        }
        const { custody: address, message, signature, nonce: nonce$1, } = statusResponse.data;
        if (authMode === 'signin') {
            let sessionPublicKey = undefined;
            if (shouldRegisterSessionKeysOnSignin()) {
                const keypair = yield generateSessionKey();
                sessionPublicKey = keypair.publicKey;
            }
            yield getClientSessionKeys.generateClientSessionKeys();
            const apiCall = () => oauth.farcasterSignIn(environmentId, {
                address,
                captchaToken,
                domain,
                message,
                nonce: nonce$1,
                sessionPublicKey,
                signature,
            });
            yield signInAccount(sdkApiCore.ProviderEnum.Farcaster, apiCall);
        }
        else {
            const apiCall = () => oauth.farcasterVerify({
                environmentId,
                farcasterSignInRequest: {
                    address,
                    captchaToken,
                    domain,
                    message,
                    nonce: nonce$1,
                    signature,
                },
            });
            yield linkAccount(sdkApiCore.ProviderEnum.Farcaster, apiCall);
            setShowAuthFlow(false, { clearErrors: false });
        }
        setIsProcessing(false);
    }), [
        defaultRedirectUrl,
        environmentId,
        generateSessionKey,
        handleError,
        linkAccount,
        onFarcasterUrl,
        setShowAuthFlow,
        shouldRegisterSessionKeysOnSignin,
        signInAccount,
    ]);
    const connectSocialAccount = React.useCallback((_d) => _tslib.__awaiter(void 0, [_d], void 0, function* ({ authMode, provider, validator, captchaToken, isHeadlessSocialSignIn, payingWithDynamic, triggerFundFromExchangeOnSuccess, redirectUrl, telegramAuthToken, showWidgetAfterConnection, forcePopup, ssoProviderId, }) {
        var _e, _f;
        clearError();
        setIsProcessing(true);
        if (!authMode) {
            logger.logger.error('Auth mode is required. Please use either "link" or "signin"');
            return;
        }
        if (!checkValidProvider(provider, authMode)) {
            return;
        }
        // invalid connect request
        if (validator && !validator(provider)) {
            return;
        }
        dynamicEvents.dynamicEvents.emit('authInit', {
            option: provider,
            provider,
            type: 'social',
        });
        if (provider === sdkApiCore.ProviderEnum.Farcaster) {
            return connectWithFarcaster(authMode, {
                captchaToken,
                redirectUrl,
            });
        }
        const state = randomString.randomString(32);
        const verifier = randomString.randomString(43);
        // Whether we will use PKCE (code verifier/challenge) for this provider
        const usingPkce = providersRequiringPkce.includes(provider);
        socialStorage.setSocialStorageFor(provider, {
            captchaToken,
            codeVerifier: usingPkce ? verifier : undefined,
            dynamicOauthSsoProviderId: ssoProviderId,
            isHeadlessSocialSignIn,
            mode: authMode,
            payingWithDynamic,
            showWidgetAfterConnection,
            state,
            triggerFundFromExchangeOnSuccess,
        });
        const loginUrlString = getOauthLoginUrl.getOauthLoginUrl((_e = projectSettings === null || projectSettings === void 0 ? void 0 : projectSettings.providers) !== null && _e !== void 0 ? _e : [], provider);
        if (!loginUrlString) {
            handleError(provider, types.SocialOAuthErrorCode.NO_OAUTH_URL, `Failed to get login url to connect social account: ${provider}`, { raiseAuthFailure: authMode === 'signin' });
            return;
        }
        const oauthLoginUrl = new URL(loginUrlString);
        oauthLoginUrl.searchParams.set('state', state);
        // only add pkce params for providers that support/require it
        if (usingPkce) {
            const digest = yield digestSHA256.digestSHA256(verifier);
            oauthLoginUrl.searchParams.set('code_challenge', encodeBase64URL.encodeBase64URL(digest));
            oauthLoginUrl.searchParams.set('code_challenge_method', 'S256');
        }
        const isMobile = utils.isMobile();
        try {
            const effectiveStrategy = forcePopup ? 'popup' : strategy;
            const authCode = yield utils.Oauth2Service.getOauthCode({
                apiProvider: getProviderByType.getProviderByType((_f = projectSettings === null || projectSettings === void 0 ? void 0 : projectSettings.providers) !== null && _f !== void 0 ? _f : [], provider),
                getOAuthResultFromApi: () => oauth.getOAuthResult(environmentId, provider, {
                    state,
                }),
                initWebAuth: ({ redirectUrl } = {}) => oauth.initAuth(environmentId, provider, {
                    redirectUrl: redirectUrl
                        ? removeDynamicOauthParamsFromUrl(redirectUrl)
                        : undefined,
                    state,
                }),
                isMobile,
                oauthLoginUrl,
                onSettled,
                provider,
                redirectUrl: redirectUrl !== null && redirectUrl !== void 0 ? redirectUrl : defaultRedirectUrl,
                setIsProcessing,
                state,
                strategy: effectiveStrategy,
            });
            yield completeConnection({
                authCode,
                authMode,
                captchaToken,
                provider,
                ssoProviderId,
                state,
                telegramAuthToken,
                verifier,
            });
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
        }
        catch (error) {
            if (utils.Oauth2Service.isGetOauthCodeError(error)) {
                handleError(provider, error.code, error.message, {
                    raiseAuthFailure: authMode === 'signin',
                });
                return;
            }
            // Log message individually so the Expo console can display it (it fails to display objects)
            logger.logger.error('Social connection failed with unexpected error:', error.message, error);
            onFailed(provider, { error }, { raiseAuthFailure: authMode === 'signin' });
        }
    }), [
        checkValidProvider,
        clearError,
        completeConnection,
        connectWithFarcaster,
        defaultRedirectUrl,
        environmentId,
        handleError,
        onFailed,
        onSettled,
        projectSettings === null || projectSettings === void 0 ? void 0 : projectSettings.providers,
        strategy,
    ]);
    const checkCaptchaAndConnect = React.useCallback((props) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
        var _g;
        if (props.authMode === 'signin' && client.getDynamicClient().user) {
            throw new utils.DynamicError('User is already logged in');
        }
        else if (props.authMode === 'link' && !client.getDynamicClient().user) {
            throw new utils.DynamicError('User is not logged in');
        }
        if (!((_g = projectSettings === null || projectSettings === void 0 ? void 0 : projectSettings.security.hCaptcha) === null || _g === void 0 ? void 0 : _g.enabled)) {
            yield connectSocialAccount(props);
            return;
        }
        // Make sure the auth flow is visible
        // it would still be hidden in headless scenarios
        setShowAuthFlow(true, {
            initializeWalletConnect: false,
            performMultiWalletChecks: false,
        });
        engageCaptcha({
            authMethod: 'social',
            onCaptchaSuccess: (captchaToken) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
                yield connectSocialAccount(Object.assign(Object.assign({}, props), { captchaToken }));
                setShowAuthFlow(false);
            }),
        });
    }), [
        setShowAuthFlow,
        connectSocialAccount,
        engageCaptcha,
        (_a = projectSettings === null || projectSettings === void 0 ? void 0 : projectSettings.security.hCaptcha) === null || _a === void 0 ? void 0 : _a.enabled,
    ]);
    return React.useMemo(() => ({
        checkValidProvider,
        completeConnection,
        connectSocialAccount: checkCaptchaAndConnect,
        error,
        handleError,
        isProcessing,
        setError,
        setIsProcessing,
    }), [
        checkValidProvider,
        completeConnection,
        checkCaptchaAndConnect,
        error,
        handleError,
        isProcessing,
    ]);
};
const removeDynamicOauthParamsFromUrl = (url) => {
    const urlObject = new URL(url);
    urlObject.searchParams.delete('dynamicOauthState');
    urlObject.searchParams.delete('dynamicOauthCode');
    return urlObject.toString();
};

exports.useSocialAuth = useSocialAuth;
