@dynamic-labs-sdk/react-native-embedded-wallet-export 0.0.0 → 1.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +116 -0
- package/dist/ExportPrivateKey/ExportPrivateKey.d.ts +26 -0
- package/dist/ExportPrivateKey/ExportPrivateKey.d.ts.map +1 -0
- package/dist/ExportPrivateKey/ExportPrivateKey.types.d.ts +33 -0
- package/dist/ExportPrivateKey/ExportPrivateKey.types.d.ts.map +1 -0
- package/dist/createWebViewWaasContainer/createWebViewWaasContainer.d.ts +54 -0
- package/dist/createWebViewWaasContainer/createWebViewWaasContainer.d.ts.map +1 -0
- package/dist/exports/index.d.ts +3 -0
- package/dist/exports/index.d.ts.map +1 -0
- package/dist/index.cjs +252 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.esm.js +224 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -0
- package/package.json +44 -1
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { assertPackageVersion } from "@dynamic-labs-sdk/assert-package-version";
|
|
2
|
+
import { getDefaultClient } from "@dynamic-labs-sdk/client";
|
|
3
|
+
import { setScreenshotProtection } from "@dynamic-labs-sdk/client/core";
|
|
4
|
+
import { exportWaasPrivateKeyToContainer } from "@dynamic-labs-sdk/client/waas/core";
|
|
5
|
+
import { useEffect, useMemo, useRef, useState } from "react";
|
|
6
|
+
import { StyleSheet, View } from "react-native";
|
|
7
|
+
import WebView from "react-native-webview";
|
|
8
|
+
import { jsx } from "react/jsx-runtime";
|
|
9
|
+
|
|
10
|
+
//#region package.json
|
|
11
|
+
var name = "@dynamic-labs-sdk/react-native-embedded-wallet-export";
|
|
12
|
+
var version = "1.11.0";
|
|
13
|
+
|
|
14
|
+
//#endregion
|
|
15
|
+
//#region src/createWebViewWaasContainer/createWebViewWaasContainer.ts
|
|
16
|
+
/**
|
|
17
|
+
* JS injected into the hosted export page before its own scripts run. The page
|
|
18
|
+
* is written for the browser iframe transport: it reaches the SDK host via
|
|
19
|
+
* `window.parent.postMessage` and listens with `window.addEventListener
|
|
20
|
+
* ('message', ...)`. In a top-level WebView `window.parent === window`, so we
|
|
21
|
+
* override `window.postMessage` to forward the page's outbound payload to React
|
|
22
|
+
* Native through `window.ReactNativeWebView.postMessage`. The reverse direction
|
|
23
|
+
* (host -> page) is delivered by `sendMessage` injecting a synthetic
|
|
24
|
+
* `MessageEvent`, so no inbound wiring is needed here. Mirrors the native
|
|
25
|
+
* `BRIDGE_USER_SCRIPT` in the client package's DynamicWebViewHost.
|
|
26
|
+
*/
|
|
27
|
+
const WAAS_EXPORT_BRIDGE_SHIM = `
|
|
28
|
+
(function () {
|
|
29
|
+
if (window.__dynamicBridgeInstalled) { return; }
|
|
30
|
+
window.__dynamicBridgeInstalled = true;
|
|
31
|
+
var post = function (data) {
|
|
32
|
+
try {
|
|
33
|
+
var json = typeof data === 'string' ? data : JSON.stringify(data);
|
|
34
|
+
window.ReactNativeWebView.postMessage(json);
|
|
35
|
+
} catch (e) {}
|
|
36
|
+
};
|
|
37
|
+
try {
|
|
38
|
+
Object.defineProperty(window, 'postMessage', {
|
|
39
|
+
configurable: true,
|
|
40
|
+
writable: true,
|
|
41
|
+
value: function (data, targetOrigin, transfer) { post(data); }
|
|
42
|
+
});
|
|
43
|
+
} catch (e) {
|
|
44
|
+
try { window.postMessage = function (d) { post(d); }; } catch (_) {}
|
|
45
|
+
}
|
|
46
|
+
})();
|
|
47
|
+
true;
|
|
48
|
+
`;
|
|
49
|
+
/**
|
|
50
|
+
* Creates a `WaasSDKContainer` backed by a `react-native-webview` rendered in
|
|
51
|
+
* the normal RN view tree (so it scrolls, clips, and positions like any view —
|
|
52
|
+
* no native overlay or manual window positioning). The private key is rendered
|
|
53
|
+
* inside the WebView's sandboxed document and never crosses the bridge; only
|
|
54
|
+
* the WaaS transport protocol messages do.
|
|
55
|
+
*
|
|
56
|
+
* The returned `container` is passed to `exportWaasPrivateKeyToContainer`; the
|
|
57
|
+
* `handleWebView*` sinks are wired into the WebView's `onMessage`/`onError` by
|
|
58
|
+
* the host component.
|
|
59
|
+
*
|
|
60
|
+
* @not-instrumented
|
|
61
|
+
*/
|
|
62
|
+
const createWebViewWaasContainer = ({ setUrl, webViewRef }) => {
|
|
63
|
+
const messageHandlers = [];
|
|
64
|
+
const errorHandlers = [];
|
|
65
|
+
let destroyed = false;
|
|
66
|
+
return {
|
|
67
|
+
container: {
|
|
68
|
+
destroy() {
|
|
69
|
+
if (destroyed) return;
|
|
70
|
+
destroyed = true;
|
|
71
|
+
messageHandlers.length = 0;
|
|
72
|
+
errorHandlers.length = 0;
|
|
73
|
+
setUrl("");
|
|
74
|
+
},
|
|
75
|
+
isAlive: () => !destroyed,
|
|
76
|
+
onError(handler) {
|
|
77
|
+
errorHandlers.push(handler);
|
|
78
|
+
return () => {
|
|
79
|
+
const index = errorHandlers.indexOf(handler);
|
|
80
|
+
if (index !== -1) errorHandlers.splice(index, 1);
|
|
81
|
+
};
|
|
82
|
+
},
|
|
83
|
+
onMessage(handler) {
|
|
84
|
+
messageHandlers.push(handler);
|
|
85
|
+
return () => {
|
|
86
|
+
const index = messageHandlers.indexOf(handler);
|
|
87
|
+
if (index !== -1) messageHandlers.splice(index, 1);
|
|
88
|
+
};
|
|
89
|
+
},
|
|
90
|
+
sendMessage(data) {
|
|
91
|
+
const payload = JSON.stringify(data);
|
|
92
|
+
webViewRef.current?.injectJavaScript(`window.dispatchEvent(new MessageEvent('message',{data:${payload},origin:window.location.origin}));true;`);
|
|
93
|
+
},
|
|
94
|
+
async setUrl(url) {
|
|
95
|
+
setUrl(url);
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
handleWebViewError(error) {
|
|
99
|
+
if (destroyed) return;
|
|
100
|
+
for (const handler of errorHandlers) handler(error);
|
|
101
|
+
},
|
|
102
|
+
handleWebViewMessage(raw) {
|
|
103
|
+
if (destroyed) return;
|
|
104
|
+
let data;
|
|
105
|
+
try {
|
|
106
|
+
data = JSON.parse(raw);
|
|
107
|
+
} catch {
|
|
108
|
+
data = raw;
|
|
109
|
+
}
|
|
110
|
+
for (const handler of messageHandlers) handler(data);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
//#endregion
|
|
116
|
+
//#region src/ExportPrivateKey/ExportPrivateKey.tsx
|
|
117
|
+
/**
|
|
118
|
+
* Renders a secure private-key export box for a WaaS wallet account on React
|
|
119
|
+
* Native. The key is rendered inside a `react-native-webview` that fills the
|
|
120
|
+
* box — the same split the web SDK uses (host renders the chrome, the
|
|
121
|
+
* cross-origin document renders only the key). Because it is a normal RN view,
|
|
122
|
+
* it scrolls, clips and positions like any view; no native overlay or manual
|
|
123
|
+
* window positioning is involved. The key is rendered inside the WebView and
|
|
124
|
+
* never crosses the bridge, so the host app's JS cannot read, log, or
|
|
125
|
+
* screenshot it. On Android, window-level screenshot/recording protection is
|
|
126
|
+
* enabled while the component is mounted.
|
|
127
|
+
*
|
|
128
|
+
* Place it inside your own modal/card and add your own close button — unmounting
|
|
129
|
+
* tears the WebView down. Size/position it with the `style` prop.
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```tsx
|
|
133
|
+
* <Modal visible={revealing} onRequestClose={() => setRevealing(false)}>
|
|
134
|
+
* <ExportPrivateKey walletAccount={walletAccount} onError={setError} />
|
|
135
|
+
* <Button title="I'm Done" onPress={() => setRevealing(false)} />
|
|
136
|
+
* </Modal>
|
|
137
|
+
* ```
|
|
138
|
+
*/
|
|
139
|
+
const ExportPrivateKey = ({ walletAccount, password, onComplete, onError, style }) => {
|
|
140
|
+
const webViewRef = useRef(null);
|
|
141
|
+
const [url, setUrl] = useState(null);
|
|
142
|
+
const onCompleteRef = useRef(onComplete);
|
|
143
|
+
onCompleteRef.current = onComplete;
|
|
144
|
+
const onErrorRef = useRef(onError);
|
|
145
|
+
onErrorRef.current = onError;
|
|
146
|
+
const passwordRef = useRef(password);
|
|
147
|
+
passwordRef.current = password;
|
|
148
|
+
const connectorRef = useRef(null);
|
|
149
|
+
if (connectorRef.current === null) connectorRef.current = createWebViewWaasContainer({
|
|
150
|
+
setUrl: (next) => setUrl(next || null),
|
|
151
|
+
webViewRef
|
|
152
|
+
});
|
|
153
|
+
const { container, handleWebViewMessage, handleWebViewError } = connectorRef.current;
|
|
154
|
+
const aliveRef = useRef(true);
|
|
155
|
+
const startedRef = useRef(false);
|
|
156
|
+
useEffect(() => {
|
|
157
|
+
if (startedRef.current) return;
|
|
158
|
+
startedRef.current = true;
|
|
159
|
+
setScreenshotProtection({ enabled: true });
|
|
160
|
+
exportWaasPrivateKeyToContainer({
|
|
161
|
+
container,
|
|
162
|
+
password: passwordRef.current,
|
|
163
|
+
walletAccount
|
|
164
|
+
}, getDefaultClient()).then(() => {
|
|
165
|
+
if (aliveRef.current) onCompleteRef.current?.();
|
|
166
|
+
}).catch((error) => {
|
|
167
|
+
if (aliveRef.current) onErrorRef.current?.(error);
|
|
168
|
+
});
|
|
169
|
+
return () => {
|
|
170
|
+
aliveRef.current = false;
|
|
171
|
+
container.destroy();
|
|
172
|
+
setScreenshotProtection({ enabled: false });
|
|
173
|
+
};
|
|
174
|
+
}, []);
|
|
175
|
+
const expectedOrigin = useMemo(() => {
|
|
176
|
+
if (!url) return null;
|
|
177
|
+
try {
|
|
178
|
+
return new URL(url).origin;
|
|
179
|
+
} catch {
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
}, [url]);
|
|
183
|
+
return /* @__PURE__ */ jsx(View, {
|
|
184
|
+
style: [styles.box, style],
|
|
185
|
+
children: url && /* @__PURE__ */ jsx(WebView, {
|
|
186
|
+
ref: webViewRef,
|
|
187
|
+
source: { uri: url },
|
|
188
|
+
injectedJavaScriptBeforeContentLoaded: WAAS_EXPORT_BRIDGE_SHIM,
|
|
189
|
+
onMessage: (event) => handleWebViewMessage(event.nativeEvent.data),
|
|
190
|
+
onError: (event) => handleWebViewError(event.nativeEvent),
|
|
191
|
+
onHttpError: (event) => handleWebViewError(event.nativeEvent),
|
|
192
|
+
originWhitelist: expectedOrigin ? [expectedOrigin] : [],
|
|
193
|
+
onShouldStartLoadWithRequest: (request) => {
|
|
194
|
+
if (!expectedOrigin) return true;
|
|
195
|
+
try {
|
|
196
|
+
return new URL(request.url).origin === expectedOrigin;
|
|
197
|
+
} catch {
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
incognito: true,
|
|
202
|
+
style: styles.webView
|
|
203
|
+
})
|
|
204
|
+
});
|
|
205
|
+
};
|
|
206
|
+
const styles = StyleSheet.create({
|
|
207
|
+
box: {
|
|
208
|
+
backgroundColor: "#FFFFFF",
|
|
209
|
+
minHeight: 88,
|
|
210
|
+
overflow: "hidden"
|
|
211
|
+
},
|
|
212
|
+
webView: {
|
|
213
|
+
backgroundColor: "transparent",
|
|
214
|
+
flex: 1
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
//#endregion
|
|
219
|
+
//#region src/exports/index.ts
|
|
220
|
+
assertPackageVersion(name, version);
|
|
221
|
+
|
|
222
|
+
//#endregion
|
|
223
|
+
export { ExportPrivateKey };
|
|
224
|
+
//# sourceMappingURL=index.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.esm.js","names":["messageHandlers: Array<(data: unknown) => void>","errorHandlers: Array<(error: unknown) => void>","data: unknown","ExportPrivateKey: FC<ExportPrivateKeyProps>","packageName","packageVersion"],"sources":["../package.json","../src/createWebViewWaasContainer/createWebViewWaasContainer.ts","../src/ExportPrivateKey/ExportPrivateKey.tsx","../src/exports/index.ts"],"sourcesContent":["","import type { WaasSDKContainer } from '@dynamic-labs-sdk/client/waas/core';\nimport type { RefObject } from 'react';\nimport type WebView from 'react-native-webview';\n\n/**\n * JS injected into the hosted export page before its own scripts run. The page\n * is written for the browser iframe transport: it reaches the SDK host via\n * `window.parent.postMessage` and listens with `window.addEventListener\n * ('message', ...)`. In a top-level WebView `window.parent === window`, so we\n * override `window.postMessage` to forward the page's outbound payload to React\n * Native through `window.ReactNativeWebView.postMessage`. The reverse direction\n * (host -> page) is delivered by `sendMessage` injecting a synthetic\n * `MessageEvent`, so no inbound wiring is needed here. Mirrors the native\n * `BRIDGE_USER_SCRIPT` in the client package's DynamicWebViewHost.\n */\nexport const WAAS_EXPORT_BRIDGE_SHIM = `\n(function () {\n if (window.__dynamicBridgeInstalled) { return; }\n window.__dynamicBridgeInstalled = true;\n var post = function (data) {\n try {\n var json = typeof data === 'string' ? data : JSON.stringify(data);\n window.ReactNativeWebView.postMessage(json);\n } catch (e) {}\n };\n try {\n Object.defineProperty(window, 'postMessage', {\n configurable: true,\n writable: true,\n value: function (data, targetOrigin, transfer) { post(data); }\n });\n } catch (e) {\n try { window.postMessage = function (d) { post(d); }; } catch (_) {}\n }\n})();\ntrue;\n`;\n\n/**\n * Parameters for {@link createWebViewWaasContainer}.\n */\nexport type CreateWebViewWaasContainerParams = {\n /**\n * Sets the URL the hosted `<WebView>` should load. An empty string unmounts\n * it (used by `destroy`). The component renders the WebView from this state.\n */\n setUrl: (url: string) => void;\n /** Ref to the rendered `react-native-webview` instance. */\n webViewRef: RefObject<WebView | null>;\n};\n\n/**\n * A {@link WaasSDKContainer} bound to a `react-native-webview`, plus the event\n * sinks the host component wires into the WebView's `onMessage`/`onError`.\n */\nexport type WebViewWaasContainer = {\n /** The container handed to `exportWaasPrivateKeyToContainer`. */\n container: WaasSDKContainer;\n /** Feed a `<WebView>` load/HTTP error into the container's onError handlers. */\n handleWebViewError: (error: unknown) => void;\n /** Feed a raw `<WebView>` onMessage payload into the container's handlers. */\n handleWebViewMessage: (raw: string) => void;\n};\n\n/**\n * Creates a `WaasSDKContainer` backed by a `react-native-webview` rendered in\n * the normal RN view tree (so it scrolls, clips, and positions like any view —\n * no native overlay or manual window positioning). The private key is rendered\n * inside the WebView's sandboxed document and never crosses the bridge; only\n * the WaaS transport protocol messages do.\n *\n * The returned `container` is passed to `exportWaasPrivateKeyToContainer`; the\n * `handleWebView*` sinks are wired into the WebView's `onMessage`/`onError` by\n * the host component.\n *\n * @not-instrumented\n */\nexport const createWebViewWaasContainer = ({\n setUrl,\n webViewRef,\n}: CreateWebViewWaasContainerParams): WebViewWaasContainer => {\n // IframeManager registers more than one onMessage handler on the same\n // container (handshake wait + transport forwarding), so we fan out to all.\n const messageHandlers: Array<(data: unknown) => void> = [];\n const errorHandlers: Array<(error: unknown) => void> = [];\n let destroyed = false;\n\n const container: WaasSDKContainer = {\n destroy() {\n if (destroyed) return;\n destroyed = true;\n messageHandlers.length = 0;\n errorHandlers.length = 0;\n // Unmount the WebView so the displayed key cannot outlive the container.\n setUrl('');\n },\n\n isAlive: () => !destroyed,\n\n // Signature is dictated by the upstream WaasSDKContainer interface.\n // eslint-disable-next-line custom-rules/require-single-object-param\n onError(handler: (error: unknown) => void) {\n errorHandlers.push(handler);\n return () => {\n const index = errorHandlers.indexOf(handler);\n if (index !== -1) errorHandlers.splice(index, 1);\n };\n },\n\n // Signature is dictated by the upstream WaasSDKContainer interface.\n // eslint-disable-next-line custom-rules/require-single-object-param\n onMessage(handler: (data: unknown) => void) {\n messageHandlers.push(handler);\n return () => {\n const index = messageHandlers.indexOf(handler);\n if (index !== -1) messageHandlers.splice(index, 1);\n };\n },\n\n sendMessage(data: Record<string, unknown>) {\n // Deliver host -> page as a synthetic 'message' event — the shape the\n // page expects from window.parent.postMessage in a browser iframe.\n const payload = JSON.stringify(data);\n webViewRef.current?.injectJavaScript(\n `window.dispatchEvent(new MessageEvent('message',{data:${payload},origin:window.location.origin}));true;`\n );\n },\n\n // Signature is dictated by the upstream WaasSDKContainer interface.\n // eslint-disable-next-line custom-rules/require-single-object-param\n async setUrl(url: string) {\n setUrl(url);\n },\n };\n\n return {\n container,\n\n handleWebViewError(error: unknown) {\n if (destroyed) return;\n for (const handler of errorHandlers) handler(error);\n },\n\n // Single positional arg matches the WebView onMessage event sink shape.\n // eslint-disable-next-line custom-rules/require-single-object-param\n handleWebViewMessage(raw: string) {\n if (destroyed) return;\n // The WaaS transport posts BOTH objects (JSON) and plain strings (e.g. the\n // `iframe-ready-<instanceId>` handshake). Deliver parsed JSON when possible,\n // otherwise the raw string — mirroring browser postMessage semantics, where\n // a string stays a string and an object stays an object. Discarding non-JSON\n // here would drop the handshake and hang the export until timeout.\n let data: unknown;\n try {\n data = JSON.parse(raw);\n } catch {\n data = raw;\n }\n for (const handler of messageHandlers) handler(data);\n },\n };\n};\n","import { getDefaultClient } from '@dynamic-labs-sdk/client';\nimport { setScreenshotProtection } from '@dynamic-labs-sdk/client/core';\nimport { exportWaasPrivateKeyToContainer } from '@dynamic-labs-sdk/client/waas/core';\nimport type { FC } from 'react';\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport { StyleSheet, View } from 'react-native';\nimport WebView from 'react-native-webview';\n\nimport {\n WAAS_EXPORT_BRIDGE_SHIM,\n createWebViewWaasContainer,\n} from '../createWebViewWaasContainer/createWebViewWaasContainer';\nimport type { WebViewWaasContainer } from '../createWebViewWaasContainer/createWebViewWaasContainer';\nimport type { ExportPrivateKeyProps } from './ExportPrivateKey.types';\n\n/**\n * Renders a secure private-key export box for a WaaS wallet account on React\n * Native. The key is rendered inside a `react-native-webview` that fills the\n * box — the same split the web SDK uses (host renders the chrome, the\n * cross-origin document renders only the key). Because it is a normal RN view,\n * it scrolls, clips and positions like any view; no native overlay or manual\n * window positioning is involved. The key is rendered inside the WebView and\n * never crosses the bridge, so the host app's JS cannot read, log, or\n * screenshot it. On Android, window-level screenshot/recording protection is\n * enabled while the component is mounted.\n *\n * Place it inside your own modal/card and add your own close button — unmounting\n * tears the WebView down. Size/position it with the `style` prop.\n *\n * @example\n * ```tsx\n * <Modal visible={revealing} onRequestClose={() => setRevealing(false)}>\n * <ExportPrivateKey walletAccount={walletAccount} onError={setError} />\n * <Button title=\"I'm Done\" onPress={() => setRevealing(false)} />\n * </Modal>\n * ```\n */\nexport const ExportPrivateKey: FC<ExportPrivateKeyProps> = ({\n walletAccount,\n password,\n onComplete,\n onError,\n style,\n}) => {\n const webViewRef = useRef<WebView | null>(null);\n const [url, setUrl] = useState<string | null>(null);\n\n // Hold callbacks + options in refs so re-renders don't restart the export.\n const onCompleteRef = useRef(onComplete);\n onCompleteRef.current = onComplete;\n const onErrorRef = useRef(onError);\n onErrorRef.current = onError;\n const passwordRef = useRef(password);\n passwordRef.current = password;\n\n // The container handed to the SDK plus the sinks wired into the WebView. It\n // holds mutable state (handler arrays, destroyed flag), so it must be created\n // exactly once and stay stable for the component's lifetime — useRef, not\n // useMemo (which React may discard and recompute). setUrl drives whether (and\n // what) the WebView renders.\n const connectorRef = useRef<WebViewWaasContainer | null>(null);\n if (connectorRef.current === null) {\n connectorRef.current = createWebViewWaasContainer({\n setUrl: (next: string) => setUrl(next || null),\n webViewRef,\n });\n }\n const { container, handleWebViewMessage, handleWebViewError } =\n connectorRef.current;\n\n const aliveRef = useRef(true);\n const startedRef = useRef(false);\n\n useEffect(() => {\n // One-shot: the export ceremony runs once.\n if (startedRef.current) return;\n startedRef.current = true;\n\n // Window-level screenshot/recording protection while the key is visible\n // (Android FLAG_SECURE; no-op on iOS).\n setScreenshotProtection({ enabled: true });\n\n exportWaasPrivateKeyToContainer(\n {\n container,\n password: passwordRef.current,\n walletAccount,\n },\n // Internal API takes the client explicitly; the component defaults it.\n getDefaultClient()\n )\n .then(() => {\n if (aliveRef.current) onCompleteRef.current?.();\n })\n .catch((error: unknown) => {\n if (aliveRef.current) onErrorRef.current?.(error);\n });\n\n return () => {\n // Unmounting tears down the WebView + container and clears screenshot\n // protection so the displayed key cannot outlive the screen.\n aliveRef.current = false;\n container.destroy();\n setScreenshotProtection({ enabled: false });\n };\n // Effect intentionally runs once; inputs are captured in refs above.\n }, []);\n\n // Pin the WebView to the export URL's origin (navigation off it is blocked).\n const expectedOrigin = useMemo(() => {\n if (!url) return null;\n try {\n return new URL(url).origin;\n } catch {\n return null;\n }\n }, [url]);\n\n return (\n <View style={[styles.box, style]}>\n {url && (\n <WebView\n ref={webViewRef}\n source={{ uri: url }}\n injectedJavaScriptBeforeContentLoaded={WAAS_EXPORT_BRIDGE_SHIM}\n onMessage={(event) => handleWebViewMessage(event.nativeEvent.data)}\n onError={(event) => handleWebViewError(event.nativeEvent)}\n onHttpError={(event) => handleWebViewError(event.nativeEvent)}\n originWhitelist={expectedOrigin ? [expectedOrigin] : []}\n onShouldStartLoadWithRequest={(request) => {\n if (!expectedOrigin) return true;\n // Exact-origin match — a prefix check would let look-alike hosts\n // (e.g. https://export.example.com.evil.com) through.\n try {\n return new URL(request.url).origin === expectedOrigin;\n } catch {\n return false;\n }\n }}\n // A fresh, isolated, ephemeral store per export.\n incognito\n style={styles.webView}\n />\n )}\n </View>\n );\n};\n\nconst styles = StyleSheet.create({\n // Minimal default so the component stays \"headless\" — the host owns the\n // chrome (border, radius, etc.) via the `style` prop. We only keep an opaque\n // background, a min height so the box is measurable before the host sizes it,\n // and clipping for the WebView.\n box: {\n backgroundColor: '#FFFFFF',\n minHeight: 88,\n overflow: 'hidden',\n },\n webView: {\n backgroundColor: 'transparent',\n flex: 1,\n },\n});\n","import { assertPackageVersion } from '@dynamic-labs-sdk/assert-package-version';\n\nimport {\n name as packageName,\n version as packageVersion,\n} from '../../package.json';\nassertPackageVersion(packageName, packageVersion);\n\nexport { ExportPrivateKey } from '../ExportPrivateKey/ExportPrivateKey';\nexport type { ExportPrivateKeyProps } from '../ExportPrivateKey/ExportPrivateKey.types';\n"],"mappings":"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"}
|