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