Skip to content

Commit 6b6f617

Browse files
committed
Winston/cnct 2363 export private key not working with connectbutton (#5498)
https://linear.app/thirdweb/issue/CNCT-2363/export-private-key-not-working-with-connectbutton <!-- start pr-codex --> --- ## PR-Codex overview This PR introduces the ability to export private keys for enclave wallets upon initial login, enhancing wallet management functionality. ### Detailed summary - Added `connectLocale` prop to the `PrivateKey` component. - Implemented `useEffect` to handle postMessage for private key export. - Changed base domain retrieval to use `getThirdwebBaseUrl`. - Updated `ModalHeader` title to use localized string. - Set iframe ID dynamically based on wallet ID. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex -->
1 parent 91cea2d commit 6b6f617

File tree

3 files changed

+67
-7
lines changed

3 files changed

+67
-7
lines changed

.changeset/smooth-hounds-kneel.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"thirdweb": patch
3+
---
4+
5+
enable private key export for enclave wallets upon initial login

packages/thirdweb/src/react/web/ui/ConnectWallet/Details.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,7 @@ function DetailsModal(props: {
882882
}}
883883
wallet={activeWallet}
884884
client={client}
885+
connectLocale={locale}
885886
/>
886887
);
887888
} else if (screen === "manage-wallet") {

packages/thirdweb/src/react/web/ui/ConnectWallet/screens/PrivateKey.tsx

Lines changed: 61 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
"use client";
2-
import { useState } from "react";
2+
import { useEffect, useState } from "react";
33
import type { ThirdwebClient } from "../../../../../client/client.js";
4-
import { getThirdwebDomains } from "../../../../../utils/domains.js";
4+
import { getThirdwebBaseUrl } from "../../../../../utils/domains.js";
5+
import { webLocalStorage } from "../../../../../utils/storage/webStorage.js";
56
import { isEcosystemWallet } from "../../../../../wallets/ecosystem/is-ecosystem-wallet.js";
7+
import { ClientScopedStorage } from "../../../../../wallets/in-app/core/authentication/client-scoped-storage.js";
68
import type { Wallet } from "../../../../../wallets/interfaces/wallet.js";
79
import type { Theme } from "../../../../core/design-system/index.js";
810
import { Spacer } from "../../components/Spacer.js";
911
import { Spinner } from "../../components/Spinner.js";
1012
import { Container, Line, ModalHeader } from "../../components/basic.js";
13+
import type { ConnectLocale } from "../locale/types.js";
1114

1215
/**
1316
* @internal
@@ -17,13 +20,62 @@ export function PrivateKey(props: {
1720
wallet?: Wallet;
1821
theme: "light" | "dark" | Theme;
1922
client: ThirdwebClient;
23+
connectLocale: ConnectLocale;
2024
}) {
2125
const [isLoading, setLoading] = useState(true);
26+
useEffect(() => {
27+
const loginReady = async (e: MessageEvent<{ eventType: string }>) => {
28+
if (
29+
typeof e.data === "object" &&
30+
"eventType" in e.data &&
31+
e.origin === baseDomain
32+
) {
33+
if (e.data.eventType === "exportPrivateKeyIframeLoaded") {
34+
const iframe = document.getElementById(
35+
`export-wallet-${props.wallet?.id}`,
36+
);
37+
38+
if (!(iframe instanceof HTMLIFrameElement)) {
39+
return;
40+
}
41+
if (!props.wallet) {
42+
return;
43+
}
44+
45+
const clientStorage = new ClientScopedStorage({
46+
clientId: props.client.clientId,
47+
storage: webLocalStorage,
48+
ecosystem: isEcosystemWallet(props.wallet)
49+
? {
50+
id: props.wallet.id,
51+
partnerId: props.wallet.getConfig()?.partnerId,
52+
}
53+
: undefined,
54+
});
55+
if (iframe?.contentWindow) {
56+
iframe.contentWindow.postMessage(
57+
{
58+
eventType: "initExportPrivateKey",
59+
authToken: await clientStorage.getAuthCookie(),
60+
},
61+
e.origin,
62+
);
63+
}
64+
}
65+
}
66+
};
67+
window.addEventListener("message", loginReady);
68+
69+
return () => {
70+
window.removeEventListener("message", loginReady);
71+
};
72+
}, [props.wallet, props.client.clientId]);
73+
2274
if (!props.wallet) {
2375
throw new Error("[PrivateKey] No wallet found");
2476
}
2577

26-
const baseDomain = getThirdwebDomains().inAppWallet;
78+
const baseDomain = getThirdwebBaseUrl("inAppWallet");
2779
const ecosystem = isEcosystemWallet(props.wallet)
2880
? { id: props.wallet.id, partnerId: props.wallet.getConfig()?.partnerId }
2981
: undefined;
@@ -35,7 +87,10 @@ export function PrivateKey(props: {
3587
}}
3688
>
3789
<Container p="lg">
38-
<ModalHeader title="Export Private Key" onBack={props.onBack} />
90+
<ModalHeader
91+
title={props.connectLocale.manageWallet.exportPrivateKey}
92+
onBack={props.onBack}
93+
/>
3994
</Container>
4095
<Line />
4196
<Container
@@ -68,6 +123,7 @@ export function PrivateKey(props: {
68123
}}
69124
>
70125
<iframe
126+
id={`export-wallet-${props.wallet.id}`}
71127
title="Export In-App Wallet"
72128
style={{
73129
width: "100%",
@@ -78,9 +134,7 @@ export function PrivateKey(props: {
78134
setLoading(false);
79135
}}
80136
allow="clipboard-read; clipboard-write"
81-
src={`${
82-
baseDomain.includes("localhost") ? "http" : "https"
83-
}://${baseDomain}/sdk/2022-08-12/embedded-wallet/export-private-key?clientId=${
137+
src={`${baseDomain}/sdk/2022-08-12/embedded-wallet/export-private-key?clientId=${
84138
props.client.clientId
85139
}&theme=${
86140
typeof props.theme === "string" ? props.theme : props.theme.type

0 commit comments

Comments
 (0)