Skip to content

Commit

Permalink
minor updates to css, adding callbacks for export and import
Browse files Browse the repository at this point in the history
  • Loading branch information
moe-dev committed Dec 5, 2024
1 parent 74f5ba7 commit 0c79501
Show file tree
Hide file tree
Showing 8 changed files with 203 additions and 80 deletions.
25 changes: 19 additions & 6 deletions examples/react-components/src/app/dashboard/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,13 @@ export default function Dashboard() {
const [emailInput, setEmailInput] = useState("");
const [phoneInput, setPhoneInput] = useState("");

const handleExportSuccess = async () => {
toast.success("Wallet successfully exported");
};
const handleImportSuccess = async () => {
await getWallets();
toast.success("Wallet successfully imported");
};
const handleResendEmail = async () => {
const initAuthResponse = await authIframeClient?.initOtpAuth({
organizationId: suborgId,
Expand Down Expand Up @@ -268,12 +275,11 @@ export default function Dashboard() {
try {
if (turnkey && authIframeClient) {
const session = await turnkey?.getReadWriteSession();
console.log(session);
if (!session || Date.now() > session!.sessionExpiry) {
if (!session || Date.now() > session!.expiry) {
await handleLogout();
}
await authIframeClient.injectCredentialBundle(
session.credentialBundle
session!.credentialBundle
);
const whoami = await authIframeClient?.getWhoami();
const suborgId = whoami?.organizationId;
Expand All @@ -285,7 +291,6 @@ export default function Dashboard() {
});

setUser(userResponse.user);
console.log(userResponse.user);
const walletsResponse = await authIframeClient!.getWallets({
organizationId: suborgId!,
});
Expand Down Expand Up @@ -654,8 +659,16 @@ export default function Dashboard() {
</RadioGroup>

<div className="exportImportGroup">
<Export walletId={selectedWallet!}></Export>
<Import onSuccess={getWallets} />
<Export
theme={{ "--button-bg": "red" }}
walletId={selectedWallet!}
onHandleExportSuccess={handleExportSuccess}
onError={(errorMessage: string) => toast.error(errorMessage)}
></Export>
<Import
onError={(errorMessage: string) => toast.error(errorMessage)}
onHandleImportSuccess={handleImportSuccess}
/>
</div>
<div className="authFooter">
<div className="authFooterLeft">
Expand Down
4 changes: 4 additions & 0 deletions examples/react-components/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ interface RootLayoutProps {
function RootLayout({ children }: RootLayoutProps) {
return (
<html lang="en" suppressHydrationWarning>
<head>
<title>Turnkey Auth Demo</title>
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
</head>
<body>
<TurnkeyProvider config={turnkeyConfig}>{children}</TurnkeyProvider>
</body>
Expand Down
30 changes: 17 additions & 13 deletions packages/sdk-react/src/components/export/Export.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
font-weight: 600;
letter-spacing: -0.01em;
text-align: left;
color: var(--text-primary);
}

.exportCard {
Expand All @@ -14,10 +15,10 @@
min-width: 375px;
margin: 0 auto;
padding: 20px;
background: var(--Greyscale-20, #f5f7fb);
border: 1px solid var(--Greyscale-100, #ebedf2);
border-radius: 15px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
background: var(--auth-card-bg);
border: 1px solid var(--auth-card-border);
border-radius: var(--auth-card-radius);
box-shadow: var(--auth-card-shadow);
}

.exportCard h2 {
Expand All @@ -28,6 +29,7 @@
text-align: center;
font-size: 1.5rem;
margin-bottom: 16px;
color: var(--text-primary);
}

.doneButtonContainer {
Expand All @@ -40,24 +42,24 @@
justify-content: center;
padding: 10px 16px;
gap: 8px;
color: var(--Greyscale-900, #2b2f33);
color: var(--button-text);
width: 100%;
font-size: 1rem;
background: #ffffff;
border: 1px solid var(--Greyscale-400, #a2a7ae);
background: var(--button-bg);
border: 1px solid var(--button-border);
border-radius: 8px;
cursor: pointer;
transition: background-color 0.3s ease;
}

.exportButton:hover {
background-color: #f5f5f5;
background-color: var(--button-hover-bg);
}

.exportButton:disabled {
color: var(--Greyscale-700, #a2a7ae);
background: #ffffff;
border-color: var(--Greyscale-100, #f5f7fb);
color: var(--button-disabled-text);
background: var(--button-disabled-bg);
border-color: var(--button-disabled-border);
cursor: default;
}

Expand All @@ -71,6 +73,7 @@
width: 95%;
margin-right: auto;
margin-bottom: 32px;
color: var(--text-primary);
}

.row {
Expand All @@ -92,15 +95,16 @@
font-weight: 400;
line-height: 16px;
letter-spacing: -0.01em;
color: var(--Greyscale-500, #868c95);
color: var(--text-secondary);
margin-top: 16px;
cursor: pointer;
}

.poweredBy span {
position: relative;
}

iframe {
box-sizing: border-box;
border: 0 solid #000;
border: 0 solid var(--border-default);
}
34 changes: 26 additions & 8 deletions packages/sdk-react/src/components/export/Export.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,18 @@ import eyeIcon from "assets/eye.svg";
import cautionIcon from "assets/caution.svg";
import turnkeyIcon from "assets/turnkey.svg";
import exportIcon from "assets/export.svg";

type ExportProps = {
walletId: string;
onHandleExportSuccess: () => Promise<void>;
onError: (errorMessage: string) => void;
};

const Export: React.FC<ExportProps> = ({ walletId }) => {
const Export: React.FC<ExportProps> = ({
walletId,
onHandleExportSuccess,
onError,
}) => {
const { authIframeClient, turnkey } = useTurnkey();
const [exportIframeClient, setExportIframeClient] =
useState<TurnkeyIframeClient | null>(null);
Expand Down Expand Up @@ -74,17 +81,28 @@ const Export: React.FC<ExportProps> = ({ walletId }) => {
};

const exportWallet = async () => {
const whoami = await authIframeClient!.getWhoami();
const exportResponse = await authIframeClient?.exportWallet({
organizationId: whoami.organizationId,
walletId: walletId!,
targetPublicKey: exportIframeClient!.iframePublicKey!,
});
if (exportResponse?.exportBundle) {
try {
const whoami = await authIframeClient!.getWhoami();

const exportResponse = await authIframeClient?.exportWallet({
organizationId: whoami.organizationId,
walletId: walletId!,
targetPublicKey: exportIframeClient!.iframePublicKey!,
});

if (!exportResponse?.exportBundle) {
throw new Error("Failed to retrieve export bundle");
}

await exportIframeClient?.injectWalletExportBundle(
exportResponse.exportBundle,
whoami.organizationId
);

onHandleExportSuccess();
} catch (error) {
console.error("Error during wallet export:", error);
onError("Failed to export wallet");
}
};

Expand Down
29 changes: 16 additions & 13 deletions packages/sdk-react/src/components/import/Import.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
font-weight: 600;
letter-spacing: -0.01em;
text-align: left;
color: var(--text-primary);
}

.importCard {
Expand All @@ -14,10 +15,10 @@
min-width: 375px;
margin: 0 auto;
padding: 20px;
background: var(--Greyscale-20, #f5f7fb);
border: 1px solid var(--Greyscale-100, #ebedf2);
border-radius: 15px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
background: var(--auth-card-bg);
border: 1px solid var(--auth-card-border);
border-radius: var(--auth-card-radius);
box-shadow: var(--auth-card-shadow);
}

.importCard h2 {
Expand All @@ -28,6 +29,7 @@
text-align: center;
font-size: 1.5rem;
margin-bottom: 16px;
color: var(--text-primary);
}

.importButton {
Expand All @@ -36,24 +38,24 @@
justify-content: center;
padding: 10px 16px;
gap: 8px;
color: var(--Greyscale-900, #2b2f33);
color: var(--button-text);
width: 100%;
font-size: 1rem;
background: #ffffff;
border: 1px solid var(--Greyscale-400, #a2a7ae);
background: var(--button-bg);
border: 1px solid var(--button-border);
border-radius: 8px;
cursor: pointer;
transition: background-color 0.3s ease;
}

.importButton:hover {
background-color: #f5f5f5;
background-color: var(--button-hover-bg);
}

.importButton:disabled {
color: var(--Greyscale-700, #a2a7ae);
background: #ffffff;
border-color: var(--Greyscale-100, #f5f7fb);
color: var(--button-disabled-text);
background: var(--button-disabled-bg);
border-color: var(--button-disabled-border);
cursor: default;
}

Expand All @@ -67,17 +69,18 @@
font-weight: 400;
line-height: 16px;
letter-spacing: -0.01em;
color: var(--Greyscale-500, #868c95);
color: var(--text-secondary);
margin-top: 16px;
cursor: pointer;
}

.poweredBy span {
position: relative;
}

iframe {
box-sizing: border-box;
border: 0 solid #000;
border: 0 solid var(--border-default);
width: 100%;
height: 100%;
}
86 changes: 47 additions & 39 deletions packages/sdk-react/src/components/import/Import.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ import styles from "./Import.module.css";
import turnkeyIcon from "assets/turnkey.svg";
import importIcon from "assets/import.svg";
type ImportProps = {
onSuccess?: () => void;
onError: (errorMessage: string) => void;
onHandleImportSuccess: () => Promise<void>;
};

const Import: React.FC<ImportProps> = ({ onSuccess = () => undefined }) => {
const Import: React.FC<ImportProps> = ({ onHandleImportSuccess, onError }) => {
const { authIframeClient, turnkey } = useTurnkey();
const [importIframeClient, setImportIframeClient] =
useState<TurnkeyIframeClient | null>(null);
Expand Down Expand Up @@ -66,44 +67,51 @@ const Import: React.FC<ImportProps> = ({ onSuccess = () => undefined }) => {
};

const handleImport = async () => {
const whoami = await authIframeClient!.getWhoami();
if (!importIframeClient) {
console.error("IframeStamper is not initialized.");
return;
}
const initResult = await authIframeClient!.initImportWallet({
organizationId: whoami.organizationId,
userId: whoami.userId,
});
const injected = await importIframeClient!.injectImportBundle(
initResult.importBundle,
whoami.organizationId,
whoami.userId
);
if (!injected) {
console.error("error injecting import bundle");
return;
}
const encryptedBundle =
await importIframeClient.extractWalletEncryptedBundle();
if (!encryptedBundle || encryptedBundle.trim() === "") {
console.error("failed to retrieve encrypted bundle.");
return;
}
const response = await authIframeClient?.importWallet({
organizationId: whoami.organizationId,
userId: whoami.userId,
walletName: walletName,
encryptedBundle,
accounts: [...DEFAULT_ETHEREUM_ACCOUNTS, ...DEFAULT_SOLANA_ACCOUNTS],
});
try {
const whoami = await authIframeClient!.getWhoami();
if (!importIframeClient) {
throw new Error("Import iframe client not initialized");
}

if (response) {
console.log("Wallet imported successfully!");
handleCloseModal();
onSuccess();
} else {
console.error("Failed to import wallet");
const initResult = await authIframeClient!.initImportWallet({
organizationId: whoami.organizationId,
userId: whoami.userId,
});

const injected = await importIframeClient!.injectImportBundle(
initResult.importBundle,
whoami.organizationId,
whoami.userId
);

if (!injected) {
throw new Error("Failed to inject import bundle");
}

const encryptedBundle =
await importIframeClient.extractWalletEncryptedBundle();

if (!encryptedBundle || encryptedBundle.trim() === "") {
throw new Error("Encrypted wallet bundle is empty or invalid");
}

const response = await authIframeClient?.importWallet({
organizationId: whoami.organizationId,
userId: whoami.userId,
walletName: walletName,
encryptedBundle,
accounts: [...DEFAULT_ETHEREUM_ACCOUNTS, ...DEFAULT_SOLANA_ACCOUNTS],
});

if (response?.walletId) {
handleCloseModal();
onHandleImportSuccess();
} else {
throw new Error("Failed to import wallet");
}
} catch (error) {
console.error("Error during wallet import:", error);
onError("Failed to import wallet");
}
};

Expand Down
Loading

0 comments on commit 0c79501

Please sign in to comment.