UNPKG

@turnkey/react-wallet-kit

Version:

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

402 lines (399 loc) 23.6 kB
import { slicedToArray as _slicedToArray, asyncToGenerator as _asyncToGenerator, regenerator as _regenerator } from '../../_virtual/_rollupPluginBabelHelpers.mjs'; import { jsxs, jsx } from 'react/jsx-runtime'; import { useState, useEffect } from 'react'; import { useModal } from '../../providers/modal/Hook.mjs'; import { useTurnkey } from '../../providers/client/Hook.mjs'; import { IframeStamper } from '@turnkey/iframe-stamper'; import { TurnkeyError, TurnkeyErrorCodes } from '@turnkey/sdk-types'; import { ActionButton } from '../design/Buttons.mjs'; import { Input } from '@headlessui/react'; import { generateWalletAccountsFromAddressFormat } from '@turnkey/core'; import { SuccessPage } from '../design/Success.mjs'; import clsx from 'clsx'; import { ImportType } from '../../types/base.mjs'; var TurnkeyImportIframeContainerId = "turnkey-import-iframe-container-id"; var TurnkeyIframeElementId = "turnkey-default-iframe-element-id"; var 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 var iconBackgroundLight = "#e5e7eb"; var iconBackgroundDark = "#333336"; var iconTextLight = "#828282"; var iconTextDark = "#a3a3a5"; function ImportComponent(props) { var _config$ui11, _config$ui12, _config$ui12$colors, _config$ui12$colors$d, _config$ui13, _config$ui13$colors, _config$ui13$colors$l, _config$ui14, _config$ui15, _config$ui15$colors, _config$ui15$colors$d, _config$ui16, _config$ui16$colors, _config$ui16$colors$l, _error$cause; var importType = props.importType, _props$curve = props.curve, curve = _props$curve === void 0 ? "CURVE_SECP256K1" : _props$curve, _props$addressFormats = props.addressFormats, addressFormats = _props$addressFormats === void 0 ? ["ADDRESS_FORMAT_ETHEREUM"] : _props$addressFormats, onSuccess = props.onSuccess, onError = props.onError, defaultWalletAccounts = props.defaultWalletAccounts, successPageDuration = props.successPageDuration, clearClipboardOnPaste = props.clearClipboardOnPaste, stampWith = props.stampWith, name = props.name, keyFormat = props.keyFormat; var _useTurnkey = useTurnkey(), config = _useTurnkey.config, session = _useTurnkey.session, importWallet = _useTurnkey.importWallet, importPrivateKey = _useTurnkey.importPrivateKey, httpClient = _useTurnkey.httpClient; if (!config) { throw new TurnkeyError("Turnkey SDK is not properly configured. Please check your configuration.", TurnkeyErrorCodes.CONFIG_NOT_INITIALIZED); } var organizationId = props.organizationId || (session === null || session === void 0 ? void 0 : session.organizationId); if (!organizationId) { throw new TurnkeyError("Organization ID or a valid session is required for importing. Please pass in an organizationId or log in.", TurnkeyErrorCodes.IMPORT_WALLET_ERROR); } var userId = props.userId || (session === null || session === void 0 ? void 0 : session.userId); if (!userId) { throw new TurnkeyError("User ID or a valid session is required for importing. Please pass in a userId or log in.", TurnkeyErrorCodes.IMPORT_WALLET_ERROR); } var _useState = useState(name || ""), _useState2 = _slicedToArray(_useState, 2), walletName = _useState2[0], setWalletName = _useState2[1]; var _useState3 = useState(false), _useState4 = _slicedToArray(_useState3, 2), isLoading = _useState4[0], setIsLoading = _useState4[1]; var _useState5 = useState(null), _useState6 = _slicedToArray(_useState5, 2), error = _useState6[0], setError = _useState6[1]; var _useState7 = useState(false), _useState8 = _slicedToArray(_useState7, 2), shaking = _useState8[0], setShaking = _useState8[1]; var shakeInput = function shakeInput() { setShaking(true); setTimeout(function () { return setShaking(false); }, 250); }; var importIframeUrl = config === null || config === void 0 ? void 0 : config.importIframeUrl; var _useModal = useModal(), closeModal = _useModal.closeModal, pushPage = _useModal.pushPage, isMobile = _useModal.isMobile; var _useState9 = useState(null), _useState0 = _slicedToArray(_useState9, 2), importIframeClient = _useState0[0], setImportIframeClient = _useState0[1]; var subtitle = importType === ImportType.Wallet ? "Enter your seed phrase. Seed phrases are typically 12-24 words." : importType === ImportType.PrivateKey ? "Enter your private key." : ""; var placeholder = importType === ImportType.Wallet ? "Enter your wallet name" : importType === ImportType.PrivateKey ? "Enter your private key name" : ""; useEffect(function () { var initIframe = /*#__PURE__*/function () { var _ref = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() { var _config$ui, _config$ui2, _config$ui2$colors, _config$ui2$colors$da, _config$ui3, _config$ui3$colors, _config$ui3$colors$li, _config$ui4, _config$ui5, _config$ui5$colors, _config$ui5$colors$da, _config$ui6, _config$ui6$colors, _config$ui6$colors$li, newImportIframeClient, _t; return _regenerator().w(function (_context) { while (1) switch (_context.p = _context.n) { case 0: _context.p = 0; newImportIframeClient = new IframeStamper({ iframeUrl: importIframeUrl, iframeElementId: TurnkeyIframeElementId, iframeContainer: document.getElementById(TurnkeyImportIframeContainerId), clearClipboardOnPaste: clearClipboardOnPaste }); _context.n = 1; return newImportIframeClient.init(); case 1: _context.n = 2; return newImportIframeClient.applySettings({ styles: { fontSize: "16px", // IMPORTANT: These colors need to match --icon-text-light and --icon-text-dark in index.css backgroundColor: config !== null && config !== void 0 && (_config$ui = config.ui) !== null && _config$ui !== void 0 && _config$ui.darkMode ? (config === null || config === void 0 ? void 0 : (_config$ui2 = config.ui) === null || _config$ui2 === void 0 ? void 0 : (_config$ui2$colors = _config$ui2.colors) === null || _config$ui2$colors === void 0 ? void 0 : (_config$ui2$colors$da = _config$ui2$colors.dark) === null || _config$ui2$colors$da === void 0 ? void 0 : _config$ui2$colors$da.iconBackground) || iconBackgroundDark : (config === null || config === void 0 ? void 0 : (_config$ui3 = config.ui) === null || _config$ui3 === void 0 ? void 0 : (_config$ui3$colors = _config$ui3.colors) === null || _config$ui3$colors === void 0 ? void 0 : (_config$ui3$colors$li = _config$ui3$colors.light) === null || _config$ui3$colors$li === void 0 ? void 0 : _config$ui3$colors$li.iconBackground) || iconBackgroundLight, color: config !== null && config !== void 0 && (_config$ui4 = config.ui) !== null && _config$ui4 !== void 0 && _config$ui4.darkMode ? (config === null || config === void 0 ? void 0 : (_config$ui5 = config.ui) === null || _config$ui5 === void 0 ? void 0 : (_config$ui5$colors = _config$ui5.colors) === null || _config$ui5$colors === void 0 ? void 0 : (_config$ui5$colors$da = _config$ui5$colors.dark) === null || _config$ui5$colors$da === void 0 ? void 0 : _config$ui5$colors$da.iconText) || iconTextDark : (config === null || config === void 0 ? void 0 : (_config$ui6 = config.ui) === null || _config$ui6 === void 0 ? void 0 : (_config$ui6$colors = _config$ui6.colors) === null || _config$ui6$colors === void 0 ? void 0 : (_config$ui6$colors$li = _config$ui6$colors.light) === null || _config$ui6$colors$li === void 0 ? void 0 : _config$ui6$colors$li.iconText) || iconTextLight } }); case 2: setImportIframeClient(newImportIframeClient); _context.n = 4; break; case 3: _context.p = 3; _t = _context.v; throw new TurnkeyError("Error initializing IframeStamper", TurnkeyErrorCodes.INTERNAL_ERROR, _t); case 4: return _context.a(2); } }, _callee, null, [[0, 3]]); })); return function initIframe() { return _ref.apply(this, arguments); }; }(); var existingIframe = document.getElementById(TurnkeyIframeElementId); if (!existingIframe) { initIframe(); } var iframeElement = document.getElementById(TurnkeyIframeElementId); if (iframeElement) { iframeElement.className = TurnkeyIframeClassNames; } return function () { handleImportModalClose(); }; }, []); useEffect(function () { var reapplyIframeStyles = /*#__PURE__*/function () { var _ref2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() { var _config$ui7, _config$ui8, _config$ui8$colors, _config$ui8$colors$da, _config$ui9, _config$ui9$colors, _config$ui9$colors$li, _config$ui0, _config$ui1, _config$ui1$colors, _config$ui1$colors$da, _config$ui10, _config$ui10$colors, _config$ui10$colors$l; return _regenerator().w(function (_context2) { while (1) switch (_context2.n) { case 0: _context2.n = 1; return importIframeClient === null || importIframeClient === void 0 ? void 0 : importIframeClient.applySettings({ styles: { fontSize: "16px", backgroundColor: config !== null && config !== void 0 && (_config$ui7 = config.ui) !== null && _config$ui7 !== void 0 && _config$ui7.darkMode ? (config === null || config === void 0 ? void 0 : (_config$ui8 = config.ui) === null || _config$ui8 === void 0 ? void 0 : (_config$ui8$colors = _config$ui8.colors) === null || _config$ui8$colors === void 0 ? void 0 : (_config$ui8$colors$da = _config$ui8$colors.dark) === null || _config$ui8$colors$da === void 0 ? void 0 : _config$ui8$colors$da.iconBackground) || iconBackgroundDark : (config === null || config === void 0 ? void 0 : (_config$ui9 = config.ui) === null || _config$ui9 === void 0 ? void 0 : (_config$ui9$colors = _config$ui9.colors) === null || _config$ui9$colors === void 0 ? void 0 : (_config$ui9$colors$li = _config$ui9$colors.light) === null || _config$ui9$colors$li === void 0 ? void 0 : _config$ui9$colors$li.iconBackground) || iconBackgroundLight, color: config !== null && config !== void 0 && (_config$ui0 = config.ui) !== null && _config$ui0 !== void 0 && _config$ui0.darkMode ? (config === null || config === void 0 ? void 0 : (_config$ui1 = config.ui) === null || _config$ui1 === void 0 ? void 0 : (_config$ui1$colors = _config$ui1.colors) === null || _config$ui1$colors === void 0 ? void 0 : (_config$ui1$colors$da = _config$ui1$colors.dark) === null || _config$ui1$colors$da === void 0 ? void 0 : _config$ui1$colors$da.iconText) || iconTextDark : (config === null || config === void 0 ? void 0 : (_config$ui10 = config.ui) === null || _config$ui10 === void 0 ? void 0 : (_config$ui10$colors = _config$ui10.colors) === null || _config$ui10$colors === void 0 ? void 0 : (_config$ui10$colors$l = _config$ui10$colors.light) === null || _config$ui10$colors$l === void 0 ? void 0 : _config$ui10$colors$l.iconText) || iconTextLight } }); case 1: return _context2.a(2); } }, _callee2); })); return function reapplyIframeStyles() { return _ref2.apply(this, arguments); }; }(); reapplyIframeStyles(); }, [config.ui]); function handleImportModalClose() { if (importIframeClient) { setImportIframeClient(null); var existingIframe = document.getElementById(TurnkeyIframeElementId); if (existingIframe) { existingIframe.remove(); } } } function handleImport() { return _handleImport.apply(this, arguments); } function _handleImport() { _handleImport = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3() { var _defaultWalletAccount; var response, initWalletResult, injectedWallet, encryptedWalletBundle, accounts, initPrivateKeyResult, injectedKey, encryptedKeyBundle, _t2, _t3; return _regenerator().w(function (_context3) { while (1) switch (_context3.p = _context3.n) { case 0: setIsLoading(true); _context3.p = 1; if (importIframeClient) { _context3.n = 2; break; } throw new TurnkeyError("Import iframe client not initialized", TurnkeyErrorCodes.INTERNAL_ERROR); case 2: _t2 = importType; _context3.n = _t2 === ImportType.Wallet ? 3 : _t2 === ImportType.PrivateKey ? 11 : 19; break; case 3: _context3.n = 4; return httpClient === null || httpClient === void 0 ? void 0 : httpClient.initImportWallet({ organizationId: organizationId, userId: userId }, stampWith); case 4: initWalletResult = _context3.v; if (!(!initWalletResult || !initWalletResult.importBundle)) { _context3.n = 5; break; } throw new TurnkeyError("Failed to retrieve import bundle", TurnkeyErrorCodes.IMPORT_WALLET_ERROR); case 5: _context3.n = 6; return importIframeClient.injectImportBundle(initWalletResult.importBundle, organizationId, userId); case 6: injectedWallet = _context3.v; if (injectedWallet) { _context3.n = 7; break; } throw new TurnkeyError("Failed to inject import bundle", TurnkeyErrorCodes.IMPORT_WALLET_ERROR); case 7: _context3.n = 8; return importIframeClient.extractWalletEncryptedBundle(); case 8: encryptedWalletBundle = _context3.v; if (!(!encryptedWalletBundle || encryptedWalletBundle.trim() === "")) { _context3.n = 9; break; } throw new TurnkeyError("Encrypted bundle is empty", TurnkeyErrorCodes.IMPORT_WALLET_ERROR); case 9: accounts = []; if (Array.isArray(defaultWalletAccounts) && defaultWalletAccounts.length > 0 && ((_defaultWalletAccount = defaultWalletAccounts[0]) === null || _defaultWalletAccount === void 0 ? void 0 : _defaultWalletAccount.addressFormat) === undefined) { accounts = generateWalletAccountsFromAddressFormat({ addresses: defaultWalletAccounts }); } else if (Array.isArray(defaultWalletAccounts)) { accounts = defaultWalletAccounts; } _context3.n = 10; return importWallet({ walletName: walletName, accounts: accounts, encryptedBundle: encryptedWalletBundle, stampWith: stampWith, organizationId: organizationId, userId: userId }); case 10: response = _context3.v; return _context3.a(3, 20); case 11: _context3.n = 12; return httpClient === null || httpClient === void 0 ? void 0 : httpClient.initImportPrivateKey({ organizationId: organizationId, userId: userId }, stampWith); case 12: initPrivateKeyResult = _context3.v; if (!(!initPrivateKeyResult || !initPrivateKeyResult.importBundle)) { _context3.n = 13; break; } throw new TurnkeyError("Failed to retrieve import bundle", TurnkeyErrorCodes.IMPORT_WALLET_ERROR); case 13: _context3.n = 14; return importIframeClient.injectImportBundle(initPrivateKeyResult.importBundle, organizationId, userId); case 14: injectedKey = _context3.v; if (injectedKey) { _context3.n = 15; break; } throw new TurnkeyError("Failed to inject import bundle", TurnkeyErrorCodes.IMPORT_WALLET_ERROR); case 15: _context3.n = 16; return importIframeClient.extractKeyEncryptedBundle(keyFormat); case 16: encryptedKeyBundle = _context3.v; if (!(!encryptedKeyBundle || encryptedKeyBundle.trim() === "")) { _context3.n = 17; break; } throw new TurnkeyError("Encrypted bundle is empty", TurnkeyErrorCodes.IMPORT_WALLET_ERROR); case 17: _context3.n = 18; return importPrivateKey({ addressFormats: addressFormats, curve: curve, privateKeyName: walletName, encryptedBundle: encryptedKeyBundle, stampWith: stampWith, organizationId: organizationId, userId: userId }); case 18: response = _context3.v; return _context3.a(3, 20); case 19: throw new TurnkeyError("Invalid import type", TurnkeyErrorCodes.IMPORT_WALLET_ERROR); case 20: if (!response) { _context3.n = 21; break; } onSuccess(response); if (successPageDuration && successPageDuration !== 0) { pushPage({ key: "success", content: jsx(SuccessPage, { text: importType === ImportType.Wallet ? "Wallet imported successfully!" : importType === ImportType.PrivateKey ? "Private key imported successfully!" : "Success!", duration: successPageDuration, onComplete: function onComplete() { handleImportModalClose(); closeModal(); } }), preventBack: true, showTitle: false }); } else { handleImportModalClose(); closeModal(); } handleImportModalClose(); _context3.n = 23; break; case 21: _context3.n = 22; return importIframeClient.clear(); case 22: throw new TurnkeyError("Failed to import wallet", TurnkeyErrorCodes.IMPORT_WALLET_ERROR); case 23: _context3.n = 25; break; case 24: _context3.p = 24; _t3 = _context3.v; shakeInput(); setError(_t3 instanceof TurnkeyError ? _t3 : new TurnkeyError("Error importing wallet", TurnkeyErrorCodes.IMPORT_WALLET_ERROR, _t3)); if (_t3 instanceof TurnkeyError) onError(_t3); throw new TurnkeyError("Error importing wallet", TurnkeyErrorCodes.IMPORT_WALLET_ERROR, _t3); case 25: _context3.p = 25; setIsLoading(false); return _context3.f(25); case 26: return _context3.a(2); } }, _callee3, null, [[1, 24, 25, 26]]); })); return _handleImport.apply(this, arguments); } return jsxs("div", { className: clsx("flex flex-col items-center pt-4", isMobile ? "w-full" : "w-[21rem]"), children: [jsx("p", { className: "text-sm text-icon-text-light dark:text-icon-text-dark", children: subtitle }), jsx("div", { id: TurnkeyImportIframeContainerId, style: { height: "100%", overflow: "hidden", display: "block", backgroundColor: config !== null && config !== void 0 && (_config$ui11 = config.ui) !== null && _config$ui11 !== void 0 && _config$ui11.darkMode ? (config === null || config === void 0 ? void 0 : (_config$ui12 = config.ui) === null || _config$ui12 === void 0 ? void 0 : (_config$ui12$colors = _config$ui12.colors) === null || _config$ui12$colors === void 0 ? void 0 : (_config$ui12$colors$d = _config$ui12$colors.dark) === null || _config$ui12$colors$d === void 0 ? void 0 : _config$ui12$colors$d.iconBackground) || iconBackgroundDark : (config === null || config === void 0 ? void 0 : (_config$ui13 = config.ui) === null || _config$ui13 === void 0 ? void 0 : (_config$ui13$colors = _config$ui13.colors) === null || _config$ui13$colors === void 0 ? void 0 : (_config$ui13$colors$l = _config$ui13$colors.light) === null || _config$ui13$colors$l === void 0 ? void 0 : _config$ui13$colors$l.iconBackground) || iconBackgroundLight, width: "100%", boxSizing: "border-box", padding: "5px", borderStyle: "solid", borderWidth: "1px", borderRadius: "8px", borderColor: config !== null && config !== void 0 && (_config$ui14 = config.ui) !== null && _config$ui14 !== void 0 && _config$ui14.darkMode ? (config === null || config === void 0 ? void 0 : (_config$ui15 = config.ui) === null || _config$ui15 === void 0 ? void 0 : (_config$ui15$colors = _config$ui15.colors) === null || _config$ui15$colors === void 0 ? void 0 : (_config$ui15$colors$d = _config$ui15$colors.dark) === null || _config$ui15$colors$d === void 0 ? void 0 : _config$ui15$colors$d.iconText) || iconTextDark : (config === null || config === void 0 ? void 0 : (_config$ui16 = config.ui) === null || _config$ui16 === void 0 ? void 0 : (_config$ui16$colors = _config$ui16.colors) === null || _config$ui16$colors === void 0 ? void 0 : (_config$ui16$colors$l = _config$ui16$colors.light) === null || _config$ui16$colors$l === void 0 ? void 0 : _config$ui16$colors$l.iconText) || iconTextLight }, className: "transition-all ".concat(shaking ? "animate-shake" : "") }), !name && jsx(Input, { type: "text", "data-testid": "import-wallet-name-input", placeholder: placeholder, value: walletName, onChange: function onChange(e) { return setWalletName(e.target.value); }, className: "placeholder:text-icon-text-light dark:placeholder:text-icon-text-dark w-full mt-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" }), jsx(ActionButton, { name: "import-button", loading: isLoading, spinnerClassName: "text-primary-text-light dark:text-primary-text-dark", onClick: handleImport, className: "bg-primary-light mt-2 dark:bg-primary-dark text-primary-text-light dark:text-primary-text-dark", children: "Import" }), jsxs("p", { "data-testid": "import-error-message", 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 === null || error === void 0 ? void 0 : error.message, ":", " ", (error === null || error === void 0 ? void 0 : error.cause) instanceof TurnkeyError ? error === null || error === void 0 ? void 0 : error.cause.message : (error === null || error === void 0 ? void 0 : (_error$cause = error.cause) === null || _error$cause === void 0 ? void 0 : _error$cause.toString()) || "Unknown error"] })] }); } export { ImportComponent }; //# sourceMappingURL=Import.mjs.map