UNPKG

@turnkey/react-wallet-kit

Version:

The easiest and most powerful way to integrate Turnkey's Embedded Wallets into your React applications.

795 lines (793 loc) 233 kB
'use client'; import { slicedToArray as _slicedToArray, asyncToGenerator as _asyncToGenerator, regeneratorRuntime as _regeneratorRuntime, objectSpread2 as _objectSpread2 } from '../../_virtual/_rollupPluginBabelHelpers.mjs'; import { jsx } from 'react/jsx-runtime'; import { sha256 } from '@noble/hashes/sha2'; import { bytesToHex } from '@noble/hashes/utils'; import { useWalletProviderState, useDebouncedCallback, isValidSession, withTurnkeyErrorHandling, GOOGLE_AUTH_URL, popupWidth, popupHeight, APPLE_AUTH_URL, exchangeCodeForToken, FACEBOOK_AUTH_URL, generateChallengePair, parseOAuthRedirect, handleFacebookPKCEFlow, SESSION_WARNING_THRESHOLD_MS } from '../../utils.mjs'; import { DEFAULT_SESSION_EXPIRATION_IN_SECONDS, WalletInterfaceType, OtpType, TurnkeyClient, Chain, getAuthProxyConfig } from '@turnkey/core'; import { useState, useRef, useCallback, useEffect } from 'react'; import { TurnkeyError, TurnkeyErrorCodes, OAuthProviders, TurnkeyNetworkError } from '@turnkey/sdk-types'; import { useModal } from '../modal/Hook.mjs'; import { AuthState, ClientState, ExportType } from '../../types/base.mjs'; import { AuthComponent } from '../../components/auth/index.mjs'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faApple, faGoogle, faFacebook } from '@fortawesome/free-brands-svg-icons'; import { ActionPage } from '../../components/auth/Action.mjs'; import { SignMessageModal } from '../../components/sign/Message.mjs'; import { ExportComponent } from '../../components/export/Export.mjs'; import { ImportComponent } from '../../components/import/Import.mjs'; import { SuccessPage } from '../../components/design/Success.mjs'; import { UpdateEmail } from '../../components/user/UpdateEmail.mjs'; import { UpdatePhoneNumber } from '../../components/user/UpdatePhoneNumber.mjs'; import { UpdateUserName } from '../../components/user/UpdateUserName.mjs'; import { RemoveOAuthProvider } from '../../components/user/RemoveOAuthProvider.mjs'; import { RemovePasskey } from '../../components/user/RemovePasskey.mjs'; import { LinkWalletModal } from '../../components/user/LinkWallet.mjs'; import { ClientContext } from './Types.mjs'; import { OtpVerification } from '../../components/auth/OTP.mjs'; import { RemoveEmail } from '../../components/user/RemoveEmail.mjs'; import { RemovePhoneNumber } from '../../components/user/RemovePhoneNumber.mjs'; /** * Provides Turnkey client authentication, session management, wallet operations, and user profile management * for the React Wallet Kit SDK. This context provider encapsulates all core authentication flows (Passkey, Wallet, OTP, OAuth), * session lifecycle (creation, expiration, refresh), wallet linking/import/export, and user profile updates (email, phone, name). * * The provider automatically initializes the Turnkey client, fetches configuration (including proxy auth config if needed), * and synchronizes session and authentication state. It exposes a comprehensive set of methods for authentication flows, * wallet management, and user profile operations, as well as UI handlers for modal-driven flows. * * Features: * - Passkey, Wallet, OTP (Email/SMS), and OAuth (Google, Apple, Facebook) authentication and sign-up flows. * - Session management: creation, expiration scheduling, refresh, and clearing. * - Wallet management: fetch, link, import, export, account management. * - User profile management: email, phone, name, OAuth provider, and passkey linking/removal. * - Modal-driven UI flows for authentication, wallet linking, and profile updates. * - Error handling and callback integration for custom error and event responses. * * Usage: * Wrap your application with `TurnkeyProvider` to enable authentication and wallet features via context. * * @param config - The Turnkey provider configuration object. * @param children - React children to be rendered within the provider. * @param callbacks - Optional callbacks for error handling and session events. * * @returns A React context provider exposing authentication, wallet, and user management methods and state. */ var ClientProvider = function ClientProvider(_ref) { var config = _ref.config, children = _ref.children, callbacks = _ref.callbacks; var _useState = useState(undefined), _useState2 = _slicedToArray(_useState, 2), client = _useState2[0], setClient = _useState2[1]; var _useState3 = useState(undefined), _useState4 = _slicedToArray(_useState3, 2), session = _useState4[0], setSession = _useState4[1]; var _useState5 = useState(undefined), _useState6 = _slicedToArray(_useState5, 2), masterConfig = _useState6[0], setMasterConfig = _useState6[1]; var _useState7 = useState([]), _useState8 = _slicedToArray(_useState7, 2), wallets = _useState8[0], setWallets = _useState8[1]; var _useState9 = useState(undefined), _useState0 = _slicedToArray(_useState9, 2), user = _useState0[0], setUser = _useState0[1]; var _useState1 = useState(), _useState10 = _slicedToArray(_useState1, 2), clientState = _useState10[0], setClientState = _useState10[1]; var _useState11 = useState(AuthState.Unauthenticated), _useState12 = _slicedToArray(_useState11, 2), authState = _useState12[0], setAuthState = _useState12[1]; // we use this custom hook to only update the state if the value is different // this is so our useEffect that calls `initializeWalletProviderListeners()` only runs when it needs to var _useWalletProviderSta = useWalletProviderState(), _useWalletProviderSta2 = _slicedToArray(_useWalletProviderSta, 2), walletProviders = _useWalletProviderSta2[0], setWalletProviders = _useWalletProviderSta2[1]; var expiryTimeoutsRef = useRef({}); var proxyAuthConfigRef = useRef(null); var _useState13 = useState(undefined), _useState14 = _slicedToArray(_useState13, 2), allSessions = _useState14[0], setAllSessions = _useState14[1]; var _useModal = useModal(), pushPage = _useModal.pushPage, closeModal = _useModal.closeModal; var completeRedirectOauth = /*#__PURE__*/function () { var _ref2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee3() { var searchParams, code, state, stateParams, provider, flow, publicKey, openModal, _masterConfig$auth, _masterConfig$auth$oa, _masterConfig$auth2, _masterConfig$auth2$o, clientId, redirectURI, hash, _parseOAuthRedirect, idToken, _provider, _flow, _publicKey, _openModal, providerName, icon; return _regeneratorRuntime().wrap(function _callee3$(_context3) { while (1) switch (_context3.prev = _context3.next) { case 0: if (!(window.location.hash || window.location.search)) { _context3.next = 32; break; } if (!(window.location.search && window.location.search.includes("code=") && window.location.search.includes("state="))) { _context3.next = 19; break; } searchParams = new URLSearchParams(window.location.search.substring(1)); code = searchParams.get("code"); state = searchParams.get("state"); // Parse state parameter if (!(state && code)) { _context3.next = 17; break; } stateParams = new URLSearchParams(state); provider = stateParams.get("provider"); flow = stateParams.get("flow"); publicKey = stateParams.get("publicKey"); openModal = stateParams.get("openModal"); if (!(provider === "facebook" && flow === "redirect" && publicKey)) { _context3.next = 17; break; } // We have all the required parameters for a Facebook PKCE flow clientId = masterConfig === null || masterConfig === void 0 ? void 0 : (_masterConfig$auth = masterConfig.auth) === null || _masterConfig$auth === void 0 ? void 0 : (_masterConfig$auth$oa = _masterConfig$auth.oauthConfig) === null || _masterConfig$auth$oa === void 0 ? void 0 : _masterConfig$auth$oa.facebookClientId; redirectURI = masterConfig === null || masterConfig === void 0 ? void 0 : (_masterConfig$auth2 = masterConfig.auth) === null || _masterConfig$auth2 === void 0 ? void 0 : (_masterConfig$auth2$o = _masterConfig$auth2.oauthConfig) === null || _masterConfig$auth2$o === void 0 ? void 0 : _masterConfig$auth2$o.oauthRedirectUri; if (!(clientId && redirectURI)) { _context3.next = 17; break; } _context3.next = 17; return handleFacebookPKCEFlow({ code: code, publicKey: publicKey, openModal: openModal, clientId: clientId, redirectURI: redirectURI, callbacks: callbacks, completeOauth: completeOauth, onPushPage: function onPushPage(oidcToken) { return new Promise(function (resolve, reject) { pushPage({ key: "Facebook OAuth", content: jsx(ActionPage, { title: "Authenticating with Facebook...", action: function () { var _action = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee() { return _regeneratorRuntime().wrap(function _callee$(_context) { while (1) switch (_context.prev = _context.next) { case 0: _context.prev = 0; _context.next = 3; return completeOauth({ oidcToken: oidcToken, publicKey: publicKey, providerName: "facebook" }); case 3: resolve(); _context.next = 9; break; case 6: _context.prev = 6; _context.t0 = _context["catch"](0); reject(_context.t0); case 9: case "end": return _context.stop(); } }, _callee, null, [[0, 6]]); })); function action() { return _action.apply(this, arguments); } return action; }(), icon: jsx(FontAwesomeIcon, { size: "3x", icon: faFacebook }) }), showTitle: false }); }); } })["catch"](function (error) { // Handle errors if (callbacks !== null && callbacks !== void 0 && callbacks.onError) { callbacks.onError(error instanceof TurnkeyError ? error : new TurnkeyError("Facebook authentication failed", TurnkeyErrorCodes.OAUTH_SIGNUP_ERROR, error)); } }); case 17: _context3.next = 32; break; case 19: if (!window.location.hash) { _context3.next = 32; break; } hash = window.location.hash.substring(1); // Parse the hash using our helper functions _parseOAuthRedirect = parseOAuthRedirect(hash), idToken = _parseOAuthRedirect.idToken, _provider = _parseOAuthRedirect.provider, _flow = _parseOAuthRedirect.flow, _publicKey = _parseOAuthRedirect.publicKey, _openModal = _parseOAuthRedirect.openModal; if (!(idToken && _flow === "redirect" && _publicKey)) { _context3.next = 32; break; } if (!(_openModal === "true")) { _context3.next = 30; break; } providerName = _provider ? _provider.charAt(0).toUpperCase() + _provider.slice(1) : "Provider"; // Determine which icon to show based on the provider if (_provider === "apple") { icon = jsx(FontAwesomeIcon, { size: "3x", icon: faApple }); } else { // Default to Google icon icon = jsx(FontAwesomeIcon, { size: "3x", icon: faGoogle }); } // This state is set when the OAuth flow comes from the AuthComponent _context3.next = 28; return new Promise(function (resolve, reject) { pushPage({ key: "".concat(providerName, " OAuth"), content: jsx(ActionPage, { title: "Authenticating with ".concat(providerName, "..."), action: function () { var _action2 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee2() { return _regeneratorRuntime().wrap(function _callee2$(_context2) { while (1) switch (_context2.prev = _context2.next) { case 0: _context2.prev = 0; _context2.next = 3; return completeOauth(_objectSpread2({ oidcToken: idToken, publicKey: _publicKey }, _provider ? { providerName: _provider } : {})); case 3: resolve(null); _context2.next = 9; break; case 6: _context2.prev = 6; _context2.t0 = _context2["catch"](0); reject(_context2.t0); case 9: case "end": return _context2.stop(); } }, _callee2, null, [[0, 6]]); })); function action() { return _action2.apply(this, arguments); } return action; }(), icon: icon }), showTitle: false }); }); case 28: _context3.next = 31; break; case 30: if (callbacks !== null && callbacks !== void 0 && callbacks.onOauthRedirect) { callbacks.onOauthRedirect({ idToken: idToken, publicKey: _publicKey }); } else { completeOauth(_objectSpread2({ oidcToken: idToken, publicKey: _publicKey }, _provider ? { providerName: _provider } : {})); } case 31: // Clean up the URL after processing window.history.replaceState(null, document.title, window.location.pathname + window.location.search); case 32: case "end": return _context3.stop(); } }, _callee3); })); return function completeRedirectOauth() { return _ref2.apply(this, arguments); }; }(); var buildConfig = function buildConfig(proxyAuthConfig) { var _config$auth$methods$, _config$auth, _config$auth$methods, _config$auth$methods$2, _config$auth2, _config$auth2$methods, _config$auth$methods$3, _config$auth3, _config$auth3$methods, _config$auth$methods$4, _config$auth4, _config$auth4$methods, _config$auth$methods$5, _config$auth5, _config$auth5$methods, _config$auth$methods$6, _config$auth6, _config$auth6$methods, _config$auth$methods$7, _config$auth7, _config$auth7$methods, _config$auth$oauthOrd, _config$auth8, _config$auth$methodOr, _config$auth9, _config$auth0, _config$auth1, _config$auth1$oauthCo, _config$auth$autoRefr, _config$auth10, _config$walletConfig, _ref3, _resolvedMethods$wall, _config$walletConfig2, _config$walletConfig3, _config$walletConfig$, _config$walletConfig4, _config$walletConfig5, _config$walletConfig6, _config$walletConfig7, _config$walletConfig8, _config$walletConfig$2, _config$walletConfig9, _config$walletConfig0, _config$walletConfig1, _config$walletConfig10, _config$walletConfig11, _config$walletConfig$3, _config$walletConfig12, _config$walletConfig13, _config$walletConfig14, _config$importIframeU, _config$exportIframeU; // Juggle the local overrides with the values set in the dashboard (proxyAuthConfig). var resolvedMethods = { emailOtpAuthEnabled: (_config$auth$methods$ = (_config$auth = config.auth) === null || _config$auth === void 0 ? void 0 : (_config$auth$methods = _config$auth.methods) === null || _config$auth$methods === void 0 ? void 0 : _config$auth$methods.emailOtpAuthEnabled) !== null && _config$auth$methods$ !== void 0 ? _config$auth$methods$ : proxyAuthConfig === null || proxyAuthConfig === void 0 ? void 0 : proxyAuthConfig.enabledProviders.includes("email"), smsOtpAuthEnabled: (_config$auth$methods$2 = (_config$auth2 = config.auth) === null || _config$auth2 === void 0 ? void 0 : (_config$auth2$methods = _config$auth2.methods) === null || _config$auth2$methods === void 0 ? void 0 : _config$auth2$methods.smsOtpAuthEnabled) !== null && _config$auth$methods$2 !== void 0 ? _config$auth$methods$2 : proxyAuthConfig === null || proxyAuthConfig === void 0 ? void 0 : proxyAuthConfig.enabledProviders.includes("sms"), passkeyAuthEnabled: (_config$auth$methods$3 = (_config$auth3 = config.auth) === null || _config$auth3 === void 0 ? void 0 : (_config$auth3$methods = _config$auth3.methods) === null || _config$auth3$methods === void 0 ? void 0 : _config$auth3$methods.passkeyAuthEnabled) !== null && _config$auth$methods$3 !== void 0 ? _config$auth$methods$3 : proxyAuthConfig === null || proxyAuthConfig === void 0 ? void 0 : proxyAuthConfig.enabledProviders.includes("passkey"), walletAuthEnabled: (_config$auth$methods$4 = (_config$auth4 = config.auth) === null || _config$auth4 === void 0 ? void 0 : (_config$auth4$methods = _config$auth4.methods) === null || _config$auth4$methods === void 0 ? void 0 : _config$auth4$methods.walletAuthEnabled) !== null && _config$auth$methods$4 !== void 0 ? _config$auth$methods$4 : proxyAuthConfig === null || proxyAuthConfig === void 0 ? void 0 : proxyAuthConfig.enabledProviders.includes("wallet"), googleOauthEnabled: (_config$auth$methods$5 = (_config$auth5 = config.auth) === null || _config$auth5 === void 0 ? void 0 : (_config$auth5$methods = _config$auth5.methods) === null || _config$auth5$methods === void 0 ? void 0 : _config$auth5$methods.googleOauthEnabled) !== null && _config$auth$methods$5 !== void 0 ? _config$auth$methods$5 : proxyAuthConfig === null || proxyAuthConfig === void 0 ? void 0 : proxyAuthConfig.enabledProviders.includes("google"), appleOauthEnabled: (_config$auth$methods$6 = (_config$auth6 = config.auth) === null || _config$auth6 === void 0 ? void 0 : (_config$auth6$methods = _config$auth6.methods) === null || _config$auth6$methods === void 0 ? void 0 : _config$auth6$methods.appleOauthEnabled) !== null && _config$auth$methods$6 !== void 0 ? _config$auth$methods$6 : proxyAuthConfig === null || proxyAuthConfig === void 0 ? void 0 : proxyAuthConfig.enabledProviders.includes("apple"), facebookOauthEnabled: (_config$auth$methods$7 = (_config$auth7 = config.auth) === null || _config$auth7 === void 0 ? void 0 : (_config$auth7$methods = _config$auth7.methods) === null || _config$auth7$methods === void 0 ? void 0 : _config$auth7$methods.facebookOauthEnabled) !== null && _config$auth$methods$7 !== void 0 ? _config$auth$methods$7 : proxyAuthConfig === null || proxyAuthConfig === void 0 ? void 0 : proxyAuthConfig.enabledProviders.includes("facebook") }; // Set a default ordering for the oAuth methods var oauthOrder = (_config$auth$oauthOrd = (_config$auth8 = config.auth) === null || _config$auth8 === void 0 ? void 0 : _config$auth8.oauthOrder) !== null && _config$auth$oauthOrd !== void 0 ? _config$auth$oauthOrd : ["google", "apple", "facebook"].filter(function (provider) { return resolvedMethods["".concat(provider, "OauthEnabled")]; }); // Set a default ordering for the overall auth methods var methodOrder = (_config$auth$methodOr = (_config$auth9 = config.auth) === null || _config$auth9 === void 0 ? void 0 : _config$auth9.methodOrder) !== null && _config$auth$methodOr !== void 0 ? _config$auth$methodOr : [oauthOrder.length > 0 ? "socials" : null, resolvedMethods.emailOtpAuthEnabled ? "email" : null, resolvedMethods.smsOtpAuthEnabled ? "sms" : null, resolvedMethods.passkeyAuthEnabled ? "passkey" : null, resolvedMethods.walletAuthEnabled ? "wallet" : null].filter(Boolean); return _objectSpread2(_objectSpread2({}, config), {}, { // Overrides: auth: _objectSpread2(_objectSpread2({}, config.auth), {}, { methods: resolvedMethods, oauthConfig: _objectSpread2(_objectSpread2({}, (_config$auth0 = config.auth) === null || _config$auth0 === void 0 ? void 0 : _config$auth0.oauthConfig), {}, { openOauthInPage: (_config$auth1 = config.auth) === null || _config$auth1 === void 0 ? void 0 : (_config$auth1$oauthCo = _config$auth1.oauthConfig) === null || _config$auth1$oauthCo === void 0 ? void 0 : _config$auth1$oauthCo.openOauthInPage }), sessionExpirationSeconds: proxyAuthConfig === null || proxyAuthConfig === void 0 ? void 0 : proxyAuthConfig.sessionExpirationSeconds, methodOrder: methodOrder, oauthOrder: oauthOrder, autoRefreshSession: (_config$auth$autoRefr = (_config$auth10 = config.auth) === null || _config$auth10 === void 0 ? void 0 : _config$auth10.autoRefreshSession) !== null && _config$auth$autoRefr !== void 0 ? _config$auth$autoRefr : true }), walletConfig: _objectSpread2(_objectSpread2({}, config.walletConfig), {}, { features: _objectSpread2(_objectSpread2({}, (_config$walletConfig = config.walletConfig) === null || _config$walletConfig === void 0 ? void 0 : _config$walletConfig.features), {}, { auth: // If walletAuthEnabled is not set, default to true. Wallet auth can be enabled/disabled in the dashboard or by explicitly changing the walletAuthEnabled / walletConfig auth feature. (_ref3 = (_resolvedMethods$wall = resolvedMethods.walletAuthEnabled) !== null && _resolvedMethods$wall !== void 0 ? _resolvedMethods$wall : (_config$walletConfig2 = config.walletConfig) === null || _config$walletConfig2 === void 0 ? void 0 : (_config$walletConfig3 = _config$walletConfig2.features) === null || _config$walletConfig3 === void 0 ? void 0 : _config$walletConfig3.auth) !== null && _ref3 !== void 0 ? _ref3 : true, connecting: (_config$walletConfig$ = (_config$walletConfig4 = config.walletConfig) === null || _config$walletConfig4 === void 0 ? void 0 : (_config$walletConfig5 = _config$walletConfig4.features) === null || _config$walletConfig5 === void 0 ? void 0 : _config$walletConfig5.connecting) !== null && _config$walletConfig$ !== void 0 ? _config$walletConfig$ : true // Default connecting to true if not set. We don't care about auth settings here. }), chains: _objectSpread2(_objectSpread2({}, (_config$walletConfig6 = config.walletConfig) === null || _config$walletConfig6 === void 0 ? void 0 : _config$walletConfig6.chains), {}, { ethereum: _objectSpread2(_objectSpread2({}, (_config$walletConfig7 = config.walletConfig) === null || _config$walletConfig7 === void 0 ? void 0 : (_config$walletConfig8 = _config$walletConfig7.chains) === null || _config$walletConfig8 === void 0 ? void 0 : _config$walletConfig8.ethereum), {}, { // keep user's value if provided; default only when undefined "native": (_config$walletConfig$2 = (_config$walletConfig9 = config.walletConfig) === null || _config$walletConfig9 === void 0 ? void 0 : (_config$walletConfig0 = _config$walletConfig9.chains) === null || _config$walletConfig0 === void 0 ? void 0 : (_config$walletConfig1 = _config$walletConfig0.ethereum) === null || _config$walletConfig1 === void 0 ? void 0 : _config$walletConfig1["native"]) !== null && _config$walletConfig$2 !== void 0 ? _config$walletConfig$2 : true }), solana: _objectSpread2(_objectSpread2({}, (_config$walletConfig10 = config.walletConfig) === null || _config$walletConfig10 === void 0 ? void 0 : (_config$walletConfig11 = _config$walletConfig10.chains) === null || _config$walletConfig11 === void 0 ? void 0 : _config$walletConfig11.solana), {}, { // keep user's value if provided; default only when undefined "native": (_config$walletConfig$3 = (_config$walletConfig12 = config.walletConfig) === null || _config$walletConfig12 === void 0 ? void 0 : (_config$walletConfig13 = _config$walletConfig12.chains) === null || _config$walletConfig13 === void 0 ? void 0 : (_config$walletConfig14 = _config$walletConfig13.solana) === null || _config$walletConfig14 === void 0 ? void 0 : _config$walletConfig14["native"]) !== null && _config$walletConfig$3 !== void 0 ? _config$walletConfig$3 : true }) }) }), importIframeUrl: (_config$importIframeU = config.importIframeUrl) !== null && _config$importIframeU !== void 0 ? _config$importIframeU : "https://import.turnkey.com", exportIframeUrl: (_config$exportIframeU = config.exportIframeUrl) !== null && _config$exportIframeU !== void 0 ? _config$exportIframeU : "https://export.turnkey.com" }); }; /** * Initializes the Turnkey client with the provided configuration. * This function sets up the client, fetches the proxy auth config if needed, * and prepares the client for use in authentication and wallet operations. * * @internal */ var initializeClient = /*#__PURE__*/function () { var _ref4 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee4() { var _masterConfig$passkey, _masterConfig$passkey2, _masterConfig$passkey3, _masterConfig$passkey4, _masterConfig$walletC, _masterConfig$walletC2, _masterConfig$walletC3, turnkeyClient, _callbacks$onError, _callbacks$onError2; return _regeneratorRuntime().wrap(function _callee4$(_context4) { while (1) switch (_context4.prev = _context4.next) { case 0: if (!(!masterConfig || client || clientState == ClientState.Loading)) { _context4.next = 2; break; } return _context4.abrupt("return"); case 2: _context4.prev = 2; setClientState(ClientState.Loading); turnkeyClient = new TurnkeyClient({ apiBaseUrl: masterConfig.apiBaseUrl, authProxyUrl: masterConfig.authProxyUrl, authProxyConfigId: masterConfig.authProxyConfigId, organizationId: masterConfig.organizationId, // Define passkey and wallet config here. If we don't pass it into the client, Mr. Client will assume that we don't want to use passkeys/wallets and not create the stamper! passkeyConfig: { rpId: (_masterConfig$passkey = masterConfig.passkeyConfig) === null || _masterConfig$passkey === void 0 ? void 0 : _masterConfig$passkey.rpId, timeout: ((_masterConfig$passkey2 = masterConfig.passkeyConfig) === null || _masterConfig$passkey2 === void 0 ? void 0 : _masterConfig$passkey2.timeout) || 60000, // 60 seconds userVerification: ((_masterConfig$passkey3 = masterConfig.passkeyConfig) === null || _masterConfig$passkey3 === void 0 ? void 0 : _masterConfig$passkey3.userVerification) || "preferred", allowCredentials: ((_masterConfig$passkey4 = masterConfig.passkeyConfig) === null || _masterConfig$passkey4 === void 0 ? void 0 : _masterConfig$passkey4.allowCredentials) || [] }, walletConfig: _objectSpread2({ features: _objectSpread2({}, (_masterConfig$walletC = masterConfig.walletConfig) === null || _masterConfig$walletC === void 0 ? void 0 : _masterConfig$walletC.features), chains: _objectSpread2({}, (_masterConfig$walletC2 = masterConfig.walletConfig) === null || _masterConfig$walletC2 === void 0 ? void 0 : _masterConfig$walletC2.chains) }, ((_masterConfig$walletC3 = masterConfig.walletConfig) === null || _masterConfig$walletC3 === void 0 ? void 0 : _masterConfig$walletC3.walletConnect) && { walletConnect: masterConfig.walletConfig.walletConnect }) }); _context4.next = 7; return turnkeyClient.init(); case 7: setClient(turnkeyClient); // Don't set clientState to ready until we fetch the proxy auth config (See other fetchProxyAuthConfig useEffect) _context4.next = 14; break; case 10: _context4.prev = 10; _context4.t0 = _context4["catch"](2); setClientState(ClientState.Error); if (_context4.t0 instanceof TurnkeyError || _context4.t0 instanceof TurnkeyNetworkError) { callbacks === null || callbacks === void 0 ? void 0 : (_callbacks$onError = callbacks.onError) === null || _callbacks$onError === void 0 ? void 0 : _callbacks$onError.call(callbacks, _context4.t0); } else { callbacks === null || callbacks === void 0 ? void 0 : (_callbacks$onError2 = callbacks.onError) === null || _callbacks$onError2 === void 0 ? void 0 : _callbacks$onError2.call(callbacks, new TurnkeyError("Failed to initialize Turnkey client", TurnkeyErrorCodes.INITIALIZE_CLIENT_ERROR, _context4.t0)); } case 14: case "end": return _context4.stop(); } }, _callee4, null, [[2, 10]]); })); return function initializeClient() { return _ref4.apply(this, arguments); }; }(); /** * Initializes the user sessions by fetching all active sessions and setting up their state. * @internal */ var initializeSessions = /*#__PURE__*/function () { var _ref5 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee6() { var allLocalStorageSessions, activeSessionKey, _callbacks$onError3, _callbacks$onError4; return _regeneratorRuntime().wrap(function _callee6$(_context6) { while (1) switch (_context6.prev = _context6.next) { case 0: setSession(undefined); setAllSessions(undefined); _context6.prev = 2; _context6.next = 5; return getAllSessions(); case 5: allLocalStorageSessions = _context6.sent; if (allLocalStorageSessions) { _context6.next = 8; break; } return _context6.abrupt("return"); case 8: _context6.next = 10; return Promise.all(Object.keys(allLocalStorageSessions).map(/*#__PURE__*/function () { var _ref6 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee5(sessionKey) { var session; return _regeneratorRuntime().wrap(function _callee5$(_context5) { while (1) switch (_context5.prev = _context5.next) { case 0: session = allLocalStorageSessions === null || allLocalStorageSessions === void 0 ? void 0 : allLocalStorageSessions[sessionKey]; if (isValidSession(session)) { _context5.next = 12; break; } _context5.next = 4; return clearSession({ sessionKey: sessionKey }); case 4: _context5.t0 = sessionKey; _context5.next = 7; return getActiveSessionKey(); case 7: _context5.t1 = _context5.sent; if (!(_context5.t0 === _context5.t1)) { _context5.next = 10; break; } setSession(undefined); case 10: delete allLocalStorageSessions[sessionKey]; return _context5.abrupt("return"); case 12: scheduleSessionExpiration({ sessionKey: sessionKey, expiry: session.expiry }); case 13: case "end": return _context5.stop(); } }, _callee5); })); return function (_x) { return _ref6.apply(this, arguments); }; }())); case 10: setAllSessions(allLocalStorageSessions || undefined); _context6.next = 13; return client === null || client === void 0 ? void 0 : client.getActiveSessionKey(); case 13: activeSessionKey = _context6.sent; if (!activeSessionKey) { _context6.next = 23; break; } if (allLocalStorageSessions[activeSessionKey]) { _context6.next = 17; break; } return _context6.abrupt("return"); case 17: setSession(allLocalStorageSessions[activeSessionKey]); _context6.next = 20; return refreshUser(); case 20: _context6.next = 22; return refreshWallets(); case 22: return _context6.abrupt("return"); case 23: _context6.next = 28; break; case 25: _context6.prev = 25; _context6.t0 = _context6["catch"](2); if (_context6.t0 instanceof TurnkeyError || _context6.t0 instanceof TurnkeyNetworkError) { callbacks === null || callbacks === void 0 ? void 0 : (_callbacks$onError3 = callbacks.onError) === null || _callbacks$onError3 === void 0 ? void 0 : _callbacks$onError3.call(callbacks, _context6.t0); } else { callbacks === null || callbacks === void 0 ? void 0 : (_callbacks$onError4 = callbacks.onError) === null || _callbacks$onError4 === void 0 ? void 0 : _callbacks$onError4.call(callbacks, new TurnkeyError("Failed to initialize sessions", TurnkeyErrorCodes.INITIALIZE_SESSION_ERROR, _context6.t0)); } case 28: case "end": return _context6.stop(); } }, _callee6, null, [[2, 25]]); })); return function initializeSessions() { return _ref5.apply(this, arguments); }; }(); /** * @internal * Attach listeners for connected wallet providers so we can refresh state on changes. * * - Ethereum: listens for disconnect and chain switches to trigger a refresh. * - Solana: listens for disconnect via Wallet Standard `change` events to trigger a refresh. * - WalletConnect: listens for disconnect via our custom wrapper’s `change` event to trigger a refresh. * * Notes: * - Only providers that are connected are bound. * - WalletConnect is excluded from the “native” paths and handled via its unified `change` event. * * @param walletProviders - Discovered providers; only connected ones are bound. * @param onWalletsChanged - Invoked when a relevant provider event occurs. * @returns Cleanup function that removes all listeners registered by this call. */ function initializeWalletProviderListeners(_x2, _x3) { return _initializeWalletProviderListeners.apply(this, arguments); } /** * @internal * Schedules a session expiration and warning timeout for the given session key. * * - This function sets up two timeouts: one for warning before the session expires and another to expire the session. * - The warning timeout is set to trigger before the session expires, allowing for actions like refreshing the session. * - The expiration timeout clears the session and triggers any necessary callbacks. * * @param params.sessionKey - The key of the session to schedule expiration for. * @param params.expiry - The expiration time in seconds for the session. * @throws {TurnkeyError} If an error occurs while scheduling the session expiration. */ function _initializeWalletProviderListeners() { _initializeWalletProviderListeners = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee89(walletProviders, onWalletsChanged) { var _masterConfig$walletC6, _masterConfig$walletC7, _masterConfig$walletC8, _masterConfig$walletC9; var cleanups, nativeOnly, ethProviders, solProviders, wcProviders, attachEthereumListeners, attachSolanaListeners; return _regeneratorRuntime().wrap(function _callee89$(_context89) { while (1) switch (_context89.prev = _context89.next) { case 0: attachSolanaListeners = function _attachSolanaListener(provider, onWalletsChanged) { var _provider$features; var cleanups = []; var walletEvents = provider === null || provider === void 0 ? void 0 : (_provider$features = provider.features) === null || _provider$features === void 0 ? void 0 : _provider$features["standard:events"]; if (walletEvents !== null && walletEvents !== void 0 && walletEvents.on) { var offChange = walletEvents.on("change", function (_evt) { onWalletsChanged(); }); cleanups.push(offChange); } return function () { return cleanups.forEach(function (fn) { return fn(); }); }; }; attachEthereumListeners = function _attachEthereumListen(provider, onWalletsChanged) { if (typeof provider.on !== "function") return; var handleChainChanged = function handleChainChanged(_chainId) { return onWalletsChanged(); }; var handleAccountsChanged = function handleAccountsChanged(accounts) { if (accounts.length === 0) onWalletsChanged(); }; var handleDisconnect = function handleDisconnect() { return onWalletsChanged(); }; provider.on("chainChanged", handleChainChanged); provider.on("accountsChanged", handleAccountsChanged); provider.on("disconnect", handleDisconnect); return function () { provider.removeListener("chainChanged", handleChainChanged); provider.removeListener("accountsChanged", handleAccountsChanged); provider.removeListener("disconnect", handleDisconnect); }; }; if (!(walletProviders.length === 0)) { _context89.next = 4; break; } return _context89.abrupt("return", function () {}); case 4: cleanups = []; // we only want to initialize these listeners for connected walletProviders nativeOnly = function nativeOnly(provider) { return provider.interfaceType !== WalletInterfaceType.WalletConnect; }; ethProviders = masterConfig !== null && masterConfig !== void 0 && (_masterConfig$walletC6 = masterConfig.walletConfig) !== null && _masterConfig$walletC6 !== void 0 && (_masterConfig$walletC7 = _masterConfig$walletC6.chains.ethereum) !== null && _masterConfig$walletC7 !== void 0 && _masterConfig$walletC7["native"] ? walletProviders.filter(function (provider) { return provider.chainInfo.namespace === Chain.Ethereum && nativeOnly(provider) && provider.connectedAddresses.length > 0; }) : []; solProviders = masterConfig !== null && masterConfig !== void 0 && (_masterConfig$walletC8 = masterConfig.walletConfig) !== null && _masterConfig$walletC8 !== void 0 && (_masterConfig$walletC9 = _masterConfig$walletC8.chains.solana) !== null && _masterConfig$walletC9 !== void 0 && _masterConfig$walletC9["native"] ? walletProviders.filter(function (provider) { return provider.chainInfo.namespace === Chain.Solana && nativeOnly(provider) && provider.connectedAddresses.length > 0; }) : []; // we exclude WalletConnect from the native event wiring // this is because WC is handled separately with a custom wrapper’s // `change` event wcProviders = walletProviders.filter(function (p) { return p.interfaceType === WalletInterfaceType.WalletConnect && p.connectedAddresses.length > 0; }); ethProviders.forEach(function (p) { var cleanup = attachEthereumListeners(p.provider, onWalletsChanged); if (cleanup) cleanups.push(cleanup); }); solProviders.forEach(function (p) { var cleanup = attachSolanaListeners(p.provider, onWalletsChanged); if (cleanup) cleanups.push(cleanup); }); wcProviders.forEach(function (p) { var _p$provider, _p$provider$features; var standardEvents = (_p$provider = p.provider) === null || _p$provider === void 0 ? void 0 : (_p$provider$features = _p$provider.features) === null || _p$provider$features === void 0 ? void 0 : _p$provider$features["standard:events"]; if (standardEvents !== null && standardEvents !== void 0 && standardEvents.on) { var unsubscribe = standardEvents.on("change", onWalletsChanged); cleanups.push(unsubscribe); } }); return _context89.abrupt("return", function () { cleanups.forEach(function (remove) { return remove(); }); }); case 13: case "end": return _context89.stop(); } }, _callee89); })); return _initializeWalletProviderListeners.apply(this, arguments); } function scheduleSessionExpiration(_x4) { return _scheduleSessionExpiration.apply(this, arguments); } /** * Clears all scheduled session expiration and warning timeouts for the client. * * - This function removes all active session expiration and warning timeouts managed by the provider. * - It is called automatically when sessions are re-initialized or on logout to prevent memory leaks and ensure no stale timeouts remain. * - All timeouts stored in `expiryTimeoutsRef` are cleared and the reference is reset. * * @throws {TurnkeyError} If an error occurs while clearing the timeouts. */ function _scheduleSessionExpiration() { _scheduleSessionExpiration = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee92(params) { var sessionKey, expiry, timeUntilExpiry, _beforeExpiry, expireSession, _callbacks$onError0, _callbacks$onError1; return _regeneratorRuntime().wrap(function _callee92$(_context92) { while (1) switch (_context92.prev = _context92.next) { case 0: sessionKey = params.sessionKey, expiry = params.expiry; try { // Clear any existing timeout for this session key if (expiryTimeoutsRef.current[sessionKey]) { clearTimeout(expiryTimeoutsRef.current[sessionKey]); delete expiryTimeoutsRef.current[sessionKey]; } if (expiryTimeoutsRef.current["".concat(sessionKey, "-warning")]) { clearTimeout(expiryTimeoutsRef.current["".concat(sessionKey, "-warning")]); delete expiryTimeoutsRef.current["".concat(sessionKey, "-warning")]; } timeUntilExpiry = expiry * 1000 - Date.now(); _beforeExpiry = /*#__PURE__*/function () { var _ref107 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee90() { var _callbacks$beforeSess, _masterConfig$auth28; var activeSession, session; return _regeneratorRuntime().wrap(function _callee90$(_context90) { while (1) switch (_context90.prev = _context90.next) { case 0: _context90.next = 2; return getSession(); case 2: activeSession = _context90.sent; if (!(!activeSession && expiryTimeoutsRef.current[sessionKey])) { _context90.next = 7; break; } clearTimeout(expiryTimeoutsRef.current["".concat(sessionKey, "-warning")]); expiryTimeoutsRef.current["".concat(sessionKey, "-warning")] = setTimeout(_beforeExpiry, 10000); return _context90.abrupt("return"); case 7: _context90.next = 9; return getSession({ sessionKey: sessionKey }); case 9: session = _context90.sent; if (session) { _context90.next = 12; break; } return _context90.abrupt("return"); case 12: callbacks === null || callbacks === void 0 ? void 0 : (_callbacks$beforeSess = callbacks.beforeSessionExpiry) === null || _callbacks$beforeSess === void 0 ? void 0 : _callbacks$beforeSess.call(callbacks, { sessionKey: sessionKey }); if (!(masterConfig !== null && masterConfig !== void 0 && (_masterConfig$auth28 = masterConfig.auth) !== null && _masterConfig$auth28 !== void 0 && _masterConfig$auth28.autoRefreshSession)) { _context90.next = 16; break; } _context90.next = 16; return refreshSession({ expirationSeconds: session.expirationSeconds, sessionKey: sessionKey }); case 16: case "end": return _context90.stop(); } }, _callee90); })); return function beforeExpiry() { return _ref107.apply(this, arguments); }; }(); expireSession = /*#__PURE__*/function () { var _ref108 = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime().mark(function _callee91() { var _callbacks$onSessionE; var expiredSession; return _regeneratorRuntime().wrap(function _callee91$(_context91) { while (1) switch (_context91.prev = _context91.next) { case 0: _context91.next = 2; return getSession({ sessionKey: sessionKey }); case 2: expiredSession = _context91.sent; if (expiredSession) { _context91.next = 5; break; } return _context91.abrupt("return"); case 5: callbacks === null || callbacks === void 0 ? void 0 : (_callbacks$onSessionE = callbacks.onSessionExpired) === null || _callbacks$onSessionE === void 0 ? void 0 : _callbacks$onSessionE.call(callbacks, { sessionKey: sessionKey }); _context91.next = 8; return getActiveSessionKey(); case 8: _context91.t0 = _context91.sent; _context91.t1 = sessionKey; if (!(_context91.t0 === _context91.t1)) { _context91.next = 12; break; } setSession(undefined); case 12: setAllSessions(function (prevSessions) { if (!prevSessions) return prevSessions; var newSessions = _objectSpread2({}, prevSessions); delete newSessions[sessionKey]; return newSessions; }); _context91.next = 15; return clearSession({ sessionKey: sessionKey }); case 15: delete expiryTimeoutsRef.current[sessionKey]; delete expiryTimeoutsRef.current["".concat(sessionKey, "-warning")]; _context91.next = 19; return logout(); case 19: case "end":