@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
JavaScript
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