UNPKG

@turnkey/react-wallet-kit

Version:

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

222 lines (218 loc) 9.75 kB
'use strict'; var jsxRuntime = require('react/jsx-runtime'); var react = require('react'); var Hook$1 = require('../../providers/modal/Hook.js'); var Hook = require('../../providers/client/Hook.js'); var iframeStamper = require('@turnkey/iframe-stamper'); var sdkTypes = require('@turnkey/sdk-types'); var Buttons = require('../design/Buttons.js'); var react$1 = require('@headlessui/react'); var core = require('@turnkey/core'); var Success = require('../design/Success.js'); var clsx = require('clsx'); const TurnkeyImportIframeContainerId = "turnkey-import-iframe-container-id"; const TurnkeyIframeElementId = "turnkey-default-iframe-element-id"; const TurnkeyIframeClassNames = "w-full h-full overflow-hidden border-none !text-base bg-icon-background-light dark:bg-icon-background-dark"; // IMPORTANT: These colors need to match --icon-text-light, --icon-background-light, --icon-background-dark and --icon-text-dark in index.css const iconBackgroundLight = "#e5e7eb"; const iconBackgroundDark = "#333336"; const iconTextLight = "#828282"; const iconTextDark = "#a3a3a5"; function ImportComponent(params) { const { onSuccess, onError, defaultWalletAccounts, successPageDuration, stampWith } = params; const { config, session, importWallet, httpClient } = Hook.useTurnkey(); const [walletName, setWalletName] = react.useState(""); const [isLoading, setIsLoading] = react.useState(false); const [error, setError] = react.useState(null); const [shaking, setShaking] = react.useState(false); const shakeInput = () => { setShaking(true); setTimeout(() => setShaking(false), 250); }; const apiBaseUrl = config?.apiBaseUrl; const importIframeUrl = config?.importIframeUrl; const { closeModal, pushPage, isMobile } = Hook$1.useModal(); const [importIframeClient, setImportIframeClient] = react.useState(null); if (!apiBaseUrl) { throw new sdkTypes.TurnkeyError("API base URL is not configured. Please set it in the Turnkey configuration."); } react.useEffect(() => { const initIframe = async () => { try { const newImportIframeClient = new iframeStamper.IframeStamper({ iframeUrl: importIframeUrl, iframeElementId: TurnkeyIframeElementId, iframeContainer: document.getElementById(TurnkeyImportIframeContainerId) }); await newImportIframeClient.init(); await newImportIframeClient.applySettings({ styles: { fontSize: "16px", // IMPORTANT: These colors need to match --icon-text-light and --icon-text-dark in index.css backgroundColor: config?.ui?.darkMode ? config?.ui?.colors?.dark?.iconBackground || iconBackgroundDark : config?.ui?.colors?.light?.iconBackground || iconBackgroundLight, color: config?.ui?.darkMode ? config?.ui?.colors?.dark?.iconText || iconTextDark : config?.ui?.colors?.light?.iconText || iconTextLight } }); setImportIframeClient(newImportIframeClient); } catch (error) { throw new sdkTypes.TurnkeyError(`Error initializing IframeStamper`, sdkTypes.TurnkeyErrorCodes.INTERNAL_ERROR, error); } }; const existingIframe = document.getElementById(TurnkeyIframeElementId); if (!existingIframe) { initIframe(); } const iframeElement = document.getElementById(TurnkeyIframeElementId); if (iframeElement) { iframeElement.className = TurnkeyIframeClassNames; } return () => { handleImportModalClose(); }; }, []); react.useEffect(() => { const reapplyIframeStyles = async () => { await importIframeClient?.applySettings({ styles: { fontSize: "16px", backgroundColor: config?.ui?.darkMode ? config?.ui?.colors?.dark?.iconBackground || iconBackgroundDark : config?.ui?.colors?.light?.iconBackground || iconBackgroundLight, color: config?.ui?.darkMode ? config?.ui?.colors?.dark?.iconText || iconTextDark : config?.ui?.colors?.light?.iconText || iconTextLight } }); }; reapplyIframeStyles(); }, [config.ui]); function handleImportModalClose() { if (importIframeClient) { setImportIframeClient(null); const existingIframe = document.getElementById(TurnkeyIframeElementId); if (existingIframe) { existingIframe.remove(); } } } async function handleImport() { setIsLoading(true); try { if (!importIframeClient) { throw new sdkTypes.TurnkeyError("Import iframe client not initialized", sdkTypes.TurnkeyErrorCodes.INTERNAL_ERROR); } const initResult = await httpClient?.initImportWallet({ organizationId: session?.organizationId, userId: session?.userId }); if (!initResult || !initResult.importBundle) { throw new sdkTypes.TurnkeyError("Failed to retrieve import bundle", sdkTypes.TurnkeyErrorCodes.IMPORT_WALLET_ERROR); } const injected = await importIframeClient.injectImportBundle(initResult.importBundle, session?.organizationId, session?.userId); if (!injected) { throw new sdkTypes.TurnkeyError("Failed to inject import bundle", sdkTypes.TurnkeyErrorCodes.IMPORT_WALLET_ERROR); } const encryptedBundle = await importIframeClient.extractWalletEncryptedBundle(); if (!encryptedBundle || encryptedBundle.trim() === "") { throw new sdkTypes.TurnkeyError("Encrypted bundle is empty", sdkTypes.TurnkeyErrorCodes.IMPORT_WALLET_ERROR); } let accounts = []; if (Array.isArray(defaultWalletAccounts) && defaultWalletAccounts.length > 0 && defaultWalletAccounts[0]?.addressFormat === undefined) { accounts = core.generateWalletAccountsFromAddressFormat({ addresses: defaultWalletAccounts }); } else if (Array.isArray(defaultWalletAccounts)) { accounts = defaultWalletAccounts; } const response = await importWallet({ walletName: walletName, accounts, encryptedBundle, stampWith }); if (response) { onSuccess(response); if (successPageDuration && successPageDuration !== 0) { pushPage({ key: "success", content: jsxRuntime.jsx(Success.SuccessPage, { text: "Wallet imported successfully!", duration: successPageDuration, onComplete: () => { handleImportModalClose(); closeModal(); } }), preventBack: true, showTitle: false }); } else { handleImportModalClose(); closeModal(); } handleImportModalClose(); } else { await importIframeClient.clear(); throw new sdkTypes.TurnkeyError("Failed to import wallet", sdkTypes.TurnkeyErrorCodes.IMPORT_WALLET_ERROR); } } catch (error) { shakeInput(); setError(error instanceof sdkTypes.TurnkeyError ? error : new sdkTypes.TurnkeyError(`Error importing wallet`, sdkTypes.TurnkeyErrorCodes.IMPORT_WALLET_ERROR, error)); if (error instanceof sdkTypes.TurnkeyError) onError(error); throw new sdkTypes.TurnkeyError(`Error importing wallet`, sdkTypes.TurnkeyErrorCodes.IMPORT_WALLET_ERROR, error); } finally { setIsLoading(false); } } return jsxRuntime.jsxs("div", { className: clsx("flex flex-col items-center pt-4", isMobile ? "w-full" : "w-[21rem]"), children: [jsxRuntime.jsx("p", { className: "text-sm text-icon-text-light dark:text-icon-text-dark", children: "Enter your seed phrase. Seed phrases are typically 12-24 words." }), jsxRuntime.jsx("div", { id: TurnkeyImportIframeContainerId, style: { height: "100%", overflow: "hidden", display: "block", backgroundColor: config?.ui?.darkMode ? config?.ui?.colors?.dark?.iconBackground || iconBackgroundDark : config?.ui?.colors?.light?.iconBackground || iconBackgroundLight, width: "100%", boxSizing: "border-box", padding: "5px", borderStyle: "solid", borderWidth: "1px", borderRadius: "8px", borderColor: config?.ui?.darkMode ? config?.ui?.colors?.dark?.iconText || iconTextDark : config?.ui?.colors?.light?.iconText || iconTextLight }, className: `transition-all ${shaking ? "animate-shake" : ""}` }), jsxRuntime.jsx(react$1.Input, { type: "text", placeholder: "Enter your wallet name", value: walletName, onChange: e => setWalletName(e.target.value), className: "placeholder:text-icon-text-light dark:placeholder:text-icon-text-dark w-full my-2 py-3 px-3 rounded-md text-inherit bg-icon-background-light dark:bg-icon-background-dark border border-modal-background-dark/20 dark:border-modal-background-light/20 focus:outline-primary-light focus:dark:outline-primary-dark focus:outline-[1px] focus:outline-offset-0 box-border" }), jsxRuntime.jsx(Buttons.ActionButton, { loading: isLoading, spinnerClassName: "text-primary-text-light dark:text-primary-text-dark", onClick: handleImport, className: "bg-primary-light dark:bg-primary-dark text-primary-text-light dark:text-primary-text-dark", children: "Import" }), jsxRuntime.jsxs("p", { className: clsx("text-sm text-red-500 transition-opacity delay-75 line-clamp-2 w-full", error ? "opacity-100 pointer-events-auto mt-2" : "opacity-0 pointer-events-none absolute"), children: [error?.message, ":", " ", error?.cause instanceof sdkTypes.TurnkeyError ? error?.cause.message : error?.cause?.toString() || "Unknown error"] })] }); } exports.ImportComponent = ImportComponent; //# sourceMappingURL=Import.js.map