@phantom/react-native-sdk 1.0.0-beta.21 → 1.0.0-beta.24
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 +178 -27
- package/dist/index.d.ts +23 -13
- package/dist/index.js +444 -102
- package/dist/index.mjs +438 -94
- package/package.json +18 -13
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,414 @@
|
|
|
1
1
|
// src/PhantomProvider.tsx
|
|
2
|
-
import {
|
|
2
|
+
import { useState as useState5, useEffect as useEffect2, useMemo as useMemo2 } from "react";
|
|
3
3
|
import { EmbeddedProvider } from "@phantom/embedded-provider-core";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
ANALYTICS_HEADERS,
|
|
6
|
+
DEFAULT_WALLET_API_URL,
|
|
7
|
+
DEFAULT_EMBEDDED_WALLET_TYPE,
|
|
8
|
+
DEFAULT_AUTH_URL as DEFAULT_AUTH_URL2
|
|
9
|
+
} from "@phantom/constants";
|
|
10
|
+
import { ThemeProvider, darkTheme } from "@phantom/wallet-sdk-ui";
|
|
11
|
+
|
|
12
|
+
// src/ModalProvider.tsx
|
|
13
|
+
import { useState as useState4, useCallback as useCallback4, useMemo } from "react";
|
|
14
|
+
|
|
15
|
+
// src/ModalContext.ts
|
|
16
|
+
import { createContext, useContext } from "react";
|
|
17
|
+
var ModalContext = createContext(void 0);
|
|
18
|
+
function useModal() {
|
|
19
|
+
const context = useContext(ModalContext);
|
|
20
|
+
if (!context) {
|
|
21
|
+
throw new Error("useModal must be used within a ModalProvider");
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
open: context.openModal,
|
|
25
|
+
close: context.closeModal,
|
|
26
|
+
isOpened: context.isModalOpen
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// src/components/Modal.tsx
|
|
31
|
+
import { Modal as RNModal, View, StyleSheet, SafeAreaView } from "react-native";
|
|
32
|
+
import { useTheme } from "@phantom/wallet-sdk-ui";
|
|
33
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
34
|
+
function Modal({ isVisible, onClose, children }) {
|
|
35
|
+
const theme = useTheme();
|
|
36
|
+
const styles = StyleSheet.create({
|
|
37
|
+
bottomSheet: {
|
|
38
|
+
backgroundColor: theme.background,
|
|
39
|
+
borderTopLeftRadius: 32,
|
|
40
|
+
borderTopRightRadius: 32,
|
|
41
|
+
bottom: 0,
|
|
42
|
+
left: 0,
|
|
43
|
+
paddingBottom: 20,
|
|
44
|
+
position: "absolute",
|
|
45
|
+
right: 0
|
|
46
|
+
},
|
|
47
|
+
handle: {
|
|
48
|
+
alignSelf: "center",
|
|
49
|
+
backgroundColor: theme.secondary,
|
|
50
|
+
borderRadius: 2.5,
|
|
51
|
+
height: 5,
|
|
52
|
+
marginTop: 12,
|
|
53
|
+
opacity: 0.3,
|
|
54
|
+
width: 40
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
return /* @__PURE__ */ jsx(RNModal, { visible: isVisible, transparent: true, animationType: "slide", onRequestClose: onClose, children: /* @__PURE__ */ jsxs(SafeAreaView, { style: styles.bottomSheet, children: [
|
|
58
|
+
/* @__PURE__ */ jsx(View, { style: styles.handle }),
|
|
59
|
+
children
|
|
60
|
+
] }) });
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// src/PhantomContext.tsx
|
|
64
|
+
import { createContext as createContext2, useContext as useContext2 } from "react";
|
|
65
|
+
var PhantomContext = createContext2(void 0);
|
|
66
|
+
function usePhantom() {
|
|
67
|
+
const context = useContext2(PhantomContext);
|
|
68
|
+
if (context === void 0) {
|
|
69
|
+
throw new Error("usePhantom must be used within a PhantomProvider");
|
|
70
|
+
}
|
|
71
|
+
return context;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// src/components/ConnectModalContent.tsx
|
|
75
|
+
import { useState, useCallback as useCallback2 } from "react";
|
|
76
|
+
import { View as View2, Image, StyleSheet as StyleSheet2, ActivityIndicator } from "react-native";
|
|
77
|
+
import { Button, Icon, Text, useTheme as useTheme2, hexToRgba, ModalHeader } from "@phantom/wallet-sdk-ui";
|
|
78
|
+
|
|
79
|
+
// src/hooks/useConnect.ts
|
|
80
|
+
import { useCallback } from "react";
|
|
81
|
+
function useConnect() {
|
|
82
|
+
const { sdk, isConnecting, connectError, setWalletId } = usePhantom();
|
|
83
|
+
const connect = useCallback(
|
|
84
|
+
async (options) => {
|
|
85
|
+
if (!sdk) {
|
|
86
|
+
throw new Error("SDK not initialized");
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
const result = await sdk.connect(options);
|
|
90
|
+
if (result.status === "completed" && result.walletId) {
|
|
91
|
+
setWalletId(result.walletId);
|
|
92
|
+
}
|
|
93
|
+
return result;
|
|
94
|
+
} catch (err) {
|
|
95
|
+
const error = err;
|
|
96
|
+
throw error;
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
[sdk, setWalletId]
|
|
100
|
+
);
|
|
101
|
+
return {
|
|
102
|
+
connect,
|
|
103
|
+
isConnecting,
|
|
104
|
+
error: connectError
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// src/components/ConnectModalContent.tsx
|
|
109
|
+
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
110
|
+
function ConnectModalContent({ appIcon, onClose }) {
|
|
111
|
+
const theme = useTheme2();
|
|
112
|
+
const { isConnecting: contextIsConnecting, allowedProviders } = usePhantom();
|
|
113
|
+
const { connect } = useConnect();
|
|
114
|
+
const [isConnecting, setIsConnecting] = useState(false);
|
|
115
|
+
const [error, setError] = useState(null);
|
|
116
|
+
const [providerType, setProviderType] = useState(null);
|
|
117
|
+
const isLoading = contextIsConnecting || isConnecting;
|
|
118
|
+
const errorBackgroundColor = hexToRgba(theme.error, 0.1);
|
|
119
|
+
const errorBorderColor = hexToRgba(theme.error, 0.3);
|
|
120
|
+
const errorTextColor = theme.error;
|
|
121
|
+
const connectWithAuthProvider = useCallback2(
|
|
122
|
+
async (provider) => {
|
|
123
|
+
try {
|
|
124
|
+
setIsConnecting(true);
|
|
125
|
+
setError(null);
|
|
126
|
+
setProviderType(provider);
|
|
127
|
+
await connect({ provider });
|
|
128
|
+
onClose();
|
|
129
|
+
} catch (err) {
|
|
130
|
+
const error2 = err instanceof Error ? err : new Error(String(err));
|
|
131
|
+
setError(error2);
|
|
132
|
+
} finally {
|
|
133
|
+
setIsConnecting(false);
|
|
134
|
+
setProviderType(null);
|
|
135
|
+
}
|
|
136
|
+
},
|
|
137
|
+
[connect, onClose]
|
|
138
|
+
);
|
|
139
|
+
const styles = StyleSheet2.create({
|
|
140
|
+
appIcon: {
|
|
141
|
+
borderRadius: 28,
|
|
142
|
+
height: 56,
|
|
143
|
+
marginBottom: 12,
|
|
144
|
+
width: 56
|
|
145
|
+
},
|
|
146
|
+
buttonContainer: {
|
|
147
|
+
alignItems: "center",
|
|
148
|
+
flexDirection: "column",
|
|
149
|
+
gap: 12,
|
|
150
|
+
paddingHorizontal: 32,
|
|
151
|
+
width: "100%"
|
|
152
|
+
},
|
|
153
|
+
buttonContent: {
|
|
154
|
+
alignItems: "center",
|
|
155
|
+
flexDirection: "row",
|
|
156
|
+
justifyContent: "space-between",
|
|
157
|
+
width: "100%"
|
|
158
|
+
},
|
|
159
|
+
buttonContentLeft: {
|
|
160
|
+
alignItems: "center",
|
|
161
|
+
flexDirection: "row",
|
|
162
|
+
gap: 8
|
|
163
|
+
},
|
|
164
|
+
container: {
|
|
165
|
+
alignItems: "center",
|
|
166
|
+
flexDirection: "column",
|
|
167
|
+
gap: 12,
|
|
168
|
+
paddingBottom: 24,
|
|
169
|
+
width: "100%"
|
|
170
|
+
},
|
|
171
|
+
errorContainer: {
|
|
172
|
+
backgroundColor: errorBackgroundColor,
|
|
173
|
+
borderColor: errorBorderColor,
|
|
174
|
+
borderRadius: parseInt(theme.borderRadius),
|
|
175
|
+
borderWidth: 1,
|
|
176
|
+
padding: 12,
|
|
177
|
+
width: "100%"
|
|
178
|
+
},
|
|
179
|
+
errorText: {
|
|
180
|
+
color: errorTextColor,
|
|
181
|
+
fontSize: 14
|
|
182
|
+
},
|
|
183
|
+
footer: {
|
|
184
|
+
alignItems: "center",
|
|
185
|
+
borderColor: theme.aux,
|
|
186
|
+
borderTopWidth: 1,
|
|
187
|
+
flexDirection: "row",
|
|
188
|
+
gap: 4,
|
|
189
|
+
justifyContent: "center",
|
|
190
|
+
marginTop: 24,
|
|
191
|
+
padding: 16,
|
|
192
|
+
width: "100%"
|
|
193
|
+
},
|
|
194
|
+
loadingContainer: {
|
|
195
|
+
alignItems: "center",
|
|
196
|
+
flexDirection: "column",
|
|
197
|
+
gap: 12,
|
|
198
|
+
justifyContent: "center",
|
|
199
|
+
padding: 24
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
return /* @__PURE__ */ jsxs2(View2, { style: styles.container, children: [
|
|
203
|
+
/* @__PURE__ */ jsx2(ModalHeader, { title: "Login or Sign Up", onClose }),
|
|
204
|
+
appIcon && /* @__PURE__ */ jsx2(Image, { testID: "app-icon", source: { uri: appIcon }, style: styles.appIcon }),
|
|
205
|
+
isLoading ? /* @__PURE__ */ jsxs2(View2, { style: styles.loadingContainer, children: [
|
|
206
|
+
/* @__PURE__ */ jsx2(ActivityIndicator, { testID: "activity-indicator", size: "large", color: theme.brand }),
|
|
207
|
+
/* @__PURE__ */ jsx2(Text, { variant: "label", color: theme.secondary, children: "Loading..." })
|
|
208
|
+
] }) : /* @__PURE__ */ jsxs2(View2, { style: styles.buttonContainer, children: [
|
|
209
|
+
error && /* @__PURE__ */ jsx2(View2, { style: styles.errorContainer, children: /* @__PURE__ */ jsx2(Text, { style: styles.errorText, children: error.message }) }),
|
|
210
|
+
allowedProviders.includes("google") && /* @__PURE__ */ jsx2(
|
|
211
|
+
Button,
|
|
212
|
+
{
|
|
213
|
+
onClick: () => connectWithAuthProvider("google"),
|
|
214
|
+
disabled: isConnecting,
|
|
215
|
+
isLoading: isConnecting && providerType === "google",
|
|
216
|
+
fullWidth: true,
|
|
217
|
+
children: /* @__PURE__ */ jsxs2(View2, { style: styles.buttonContent, children: [
|
|
218
|
+
/* @__PURE__ */ jsxs2(View2, { style: styles.buttonContentLeft, children: [
|
|
219
|
+
/* @__PURE__ */ jsx2(Icon, { type: "google", size: 20, color: theme.text }),
|
|
220
|
+
/* @__PURE__ */ jsx2(Text, { variant: "captionBold", children: "Continue with Google" })
|
|
221
|
+
] }),
|
|
222
|
+
/* @__PURE__ */ jsx2(Icon, { type: "chevron-right", size: 16, color: theme.secondary })
|
|
223
|
+
] })
|
|
224
|
+
}
|
|
225
|
+
),
|
|
226
|
+
allowedProviders.includes("apple") && /* @__PURE__ */ jsx2(
|
|
227
|
+
Button,
|
|
228
|
+
{
|
|
229
|
+
onClick: () => connectWithAuthProvider("apple"),
|
|
230
|
+
disabled: isConnecting,
|
|
231
|
+
isLoading: isConnecting && providerType === "apple",
|
|
232
|
+
fullWidth: true,
|
|
233
|
+
children: /* @__PURE__ */ jsxs2(View2, { style: styles.buttonContent, children: [
|
|
234
|
+
/* @__PURE__ */ jsxs2(View2, { style: styles.buttonContentLeft, children: [
|
|
235
|
+
/* @__PURE__ */ jsx2(Icon, { type: "apple", size: 20, color: theme.text }),
|
|
236
|
+
/* @__PURE__ */ jsx2(Text, { variant: "captionBold", children: "Continue with Apple" })
|
|
237
|
+
] }),
|
|
238
|
+
/* @__PURE__ */ jsx2(Icon, { type: "chevron-right", size: 16, color: theme.secondary })
|
|
239
|
+
] })
|
|
240
|
+
}
|
|
241
|
+
),
|
|
242
|
+
allowedProviders.includes("x") && /* @__PURE__ */ jsx2(
|
|
243
|
+
Button,
|
|
244
|
+
{
|
|
245
|
+
onClick: () => connectWithAuthProvider("x"),
|
|
246
|
+
disabled: isConnecting,
|
|
247
|
+
isLoading: isConnecting && providerType === "x",
|
|
248
|
+
fullWidth: true,
|
|
249
|
+
children: /* @__PURE__ */ jsxs2(View2, { style: styles.buttonContent, children: [
|
|
250
|
+
/* @__PURE__ */ jsxs2(View2, { style: styles.buttonContentLeft, children: [
|
|
251
|
+
/* @__PURE__ */ jsx2(Icon, { type: "x", size: 20, color: theme.text }),
|
|
252
|
+
/* @__PURE__ */ jsx2(Text, { variant: "captionBold", children: "Continue with X" })
|
|
253
|
+
] }),
|
|
254
|
+
/* @__PURE__ */ jsx2(Icon, { type: "chevron-right", size: 16, color: theme.secondary })
|
|
255
|
+
] })
|
|
256
|
+
}
|
|
257
|
+
),
|
|
258
|
+
allowedProviders.includes("tiktok") && /* @__PURE__ */ jsx2(
|
|
259
|
+
Button,
|
|
260
|
+
{
|
|
261
|
+
onClick: () => connectWithAuthProvider("tiktok"),
|
|
262
|
+
disabled: isConnecting,
|
|
263
|
+
isLoading: isConnecting && providerType === "tiktok",
|
|
264
|
+
fullWidth: true,
|
|
265
|
+
children: /* @__PURE__ */ jsxs2(View2, { style: styles.buttonContent, children: [
|
|
266
|
+
/* @__PURE__ */ jsxs2(View2, { style: styles.buttonContentLeft, children: [
|
|
267
|
+
/* @__PURE__ */ jsx2(Icon, { type: "tiktok", size: 20, color: theme.text }),
|
|
268
|
+
/* @__PURE__ */ jsx2(Text, { variant: "captionBold", children: "Continue with TikTok" })
|
|
269
|
+
] }),
|
|
270
|
+
/* @__PURE__ */ jsx2(Icon, { type: "chevron-right", size: 16, color: theme.secondary })
|
|
271
|
+
] })
|
|
272
|
+
}
|
|
273
|
+
)
|
|
274
|
+
] }),
|
|
275
|
+
/* @__PURE__ */ jsxs2(View2, { style: styles.footer, children: [
|
|
276
|
+
/* @__PURE__ */ jsx2(Text, { variant: "label", color: theme.secondary, children: "Powered by" }),
|
|
277
|
+
/* @__PURE__ */ jsx2(Icon, { type: "phantom", size: 16, color: theme.secondary }),
|
|
278
|
+
/* @__PURE__ */ jsx2(Text, { variant: "label", color: theme.secondary, children: "Phantom" })
|
|
279
|
+
] })
|
|
280
|
+
] });
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// src/components/ConnectedModalContent.tsx
|
|
284
|
+
import { useState as useState3, useEffect } from "react";
|
|
285
|
+
import { View as View3, StyleSheet as StyleSheet3 } from "react-native";
|
|
286
|
+
import { Button as Button2, Text as Text2, useTheme as useTheme3, hexToRgba as hexToRgba2, ModalHeader as ModalHeader2 } from "@phantom/wallet-sdk-ui";
|
|
287
|
+
|
|
288
|
+
// src/hooks/useDisconnect.ts
|
|
289
|
+
import { useState as useState2, useCallback as useCallback3 } from "react";
|
|
290
|
+
function useDisconnect() {
|
|
291
|
+
const { sdk } = usePhantom();
|
|
292
|
+
const [isDisconnecting, setIsDisconnecting] = useState2(false);
|
|
293
|
+
const [error, setError] = useState2(null);
|
|
294
|
+
const disconnect = useCallback3(async () => {
|
|
295
|
+
if (!sdk) {
|
|
296
|
+
throw new Error("SDK not initialized");
|
|
297
|
+
}
|
|
298
|
+
setIsDisconnecting(true);
|
|
299
|
+
setError(null);
|
|
300
|
+
try {
|
|
301
|
+
await sdk.disconnect();
|
|
302
|
+
} catch (err) {
|
|
303
|
+
const error2 = err;
|
|
304
|
+
setError(error2);
|
|
305
|
+
throw error2;
|
|
306
|
+
} finally {
|
|
307
|
+
setIsDisconnecting(false);
|
|
308
|
+
}
|
|
309
|
+
}, [sdk]);
|
|
310
|
+
return {
|
|
311
|
+
disconnect,
|
|
312
|
+
isDisconnecting,
|
|
313
|
+
error
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// src/components/ConnectedModalContent.tsx
|
|
318
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
319
|
+
function ConnectedModalContent({ onClose }) {
|
|
320
|
+
const theme = useTheme3();
|
|
321
|
+
const { addresses } = usePhantom();
|
|
322
|
+
const { disconnect } = useDisconnect();
|
|
323
|
+
const [isDisconnecting, setIsDisconnecting] = useState3(false);
|
|
324
|
+
const [disconnectError, setDisconnectError] = useState3(null);
|
|
325
|
+
const errorBackgroundColor = hexToRgba2(theme.error, 0.1);
|
|
326
|
+
const errorBorderColor = hexToRgba2(theme.error, 0.3);
|
|
327
|
+
useEffect(() => {
|
|
328
|
+
setDisconnectError(null);
|
|
329
|
+
}, []);
|
|
330
|
+
const handleDisconnect = async () => {
|
|
331
|
+
try {
|
|
332
|
+
setIsDisconnecting(true);
|
|
333
|
+
setDisconnectError(null);
|
|
334
|
+
await disconnect();
|
|
335
|
+
onClose();
|
|
336
|
+
} catch (err) {
|
|
337
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
338
|
+
setDisconnectError(error);
|
|
339
|
+
} finally {
|
|
340
|
+
setIsDisconnecting(false);
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
const styles = StyleSheet3.create({
|
|
344
|
+
accountItem: {
|
|
345
|
+
flexDirection: "column",
|
|
346
|
+
gap: 8,
|
|
347
|
+
width: "100%"
|
|
348
|
+
},
|
|
349
|
+
accountList: {
|
|
350
|
+
flexDirection: "column",
|
|
351
|
+
gap: 16,
|
|
352
|
+
width: "100%"
|
|
353
|
+
},
|
|
354
|
+
accountTypeText: {
|
|
355
|
+
textTransform: "uppercase"
|
|
356
|
+
},
|
|
357
|
+
addressText: {
|
|
358
|
+
fontFamily: "monospace"
|
|
359
|
+
},
|
|
360
|
+
container: {
|
|
361
|
+
alignItems: "center",
|
|
362
|
+
flexDirection: "column",
|
|
363
|
+
gap: 24,
|
|
364
|
+
paddingBottom: 24,
|
|
365
|
+
paddingHorizontal: 32,
|
|
366
|
+
width: "100%"
|
|
367
|
+
},
|
|
368
|
+
errorContainer: {
|
|
369
|
+
backgroundColor: errorBackgroundColor,
|
|
370
|
+
borderColor: errorBorderColor,
|
|
371
|
+
borderRadius: theme.borderRadius,
|
|
372
|
+
borderWidth: 1,
|
|
373
|
+
padding: 12,
|
|
374
|
+
width: "100%"
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
return /* @__PURE__ */ jsxs3(View3, { style: styles.container, children: [
|
|
378
|
+
/* @__PURE__ */ jsx3(ModalHeader2, { title: "Wallet", onClose }),
|
|
379
|
+
addresses && addresses.length > 0 && /* @__PURE__ */ jsx3(View3, { style: styles.accountList, children: addresses.map((account, index) => /* @__PURE__ */ jsxs3(View3, { style: styles.accountItem, children: [
|
|
380
|
+
/* @__PURE__ */ jsx3(Text2, { variant: "label", color: theme.secondary, style: styles.accountTypeText, children: account.addressType }),
|
|
381
|
+
/* @__PURE__ */ jsx3(Text2, { variant: "caption", style: styles.addressText, children: account.address })
|
|
382
|
+
] }, index)) }),
|
|
383
|
+
disconnectError && /* @__PURE__ */ jsx3(View3, { style: styles.errorContainer, children: /* @__PURE__ */ jsx3(Text2, { variant: "caption", color: theme.error, children: "Failed to disconnect" }) }),
|
|
384
|
+
/* @__PURE__ */ jsx3(Button2, { onClick: handleDisconnect, disabled: isDisconnecting, isLoading: isDisconnecting, fullWidth: true, children: /* @__PURE__ */ jsx3(Text2, { variant: "captionBold", children: isDisconnecting ? "Disconnecting..." : "Disconnect" }) })
|
|
385
|
+
] });
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// src/ModalProvider.tsx
|
|
389
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
390
|
+
function ModalProvider({ children, appIcon, appName }) {
|
|
391
|
+
const { isConnected } = usePhantom();
|
|
392
|
+
const [isModalOpen, setIsModalOpen] = useState4(false);
|
|
393
|
+
const openModal = useCallback4(() => {
|
|
394
|
+
setIsModalOpen(true);
|
|
395
|
+
}, []);
|
|
396
|
+
const closeModal = useCallback4(() => {
|
|
397
|
+
setIsModalOpen(false);
|
|
398
|
+
}, []);
|
|
399
|
+
const modalContextValue = useMemo(
|
|
400
|
+
() => ({
|
|
401
|
+
isModalOpen,
|
|
402
|
+
openModal,
|
|
403
|
+
closeModal
|
|
404
|
+
}),
|
|
405
|
+
[isModalOpen, openModal, closeModal]
|
|
406
|
+
);
|
|
407
|
+
return /* @__PURE__ */ jsxs4(ModalContext.Provider, { value: modalContextValue, children: [
|
|
408
|
+
children,
|
|
409
|
+
/* @__PURE__ */ jsx4(Modal, { isVisible: isModalOpen, onClose: closeModal, appIcon, appName, isMobile: true, children: isConnected ? /* @__PURE__ */ jsx4(ConnectedModalContent, { onClose: closeModal }) : /* @__PURE__ */ jsx4(ConnectModalContent, { appIcon, appName, onClose: closeModal }) })
|
|
410
|
+
] });
|
|
411
|
+
}
|
|
5
412
|
|
|
6
413
|
// src/providers/embedded/storage.ts
|
|
7
414
|
import * as SecureStore from "expo-secure-store";
|
|
@@ -109,7 +516,7 @@ var ExpoAuthProvider = class {
|
|
|
109
516
|
// OAuth session management - defaults to allow refresh unless explicitly clearing after logout
|
|
110
517
|
clear_previous_session: (phantomOptions.clearPreviousSession ?? false).toString(),
|
|
111
518
|
allow_refresh: (phantomOptions.allowRefresh ?? true).toString(),
|
|
112
|
-
sdk_version: "1.0.0-beta.
|
|
519
|
+
sdk_version: "1.0.0-beta.24",
|
|
113
520
|
sdk_type: "react-native",
|
|
114
521
|
platform: Platform.OS
|
|
115
522
|
});
|
|
@@ -141,7 +548,6 @@ var ExpoAuthProvider = class {
|
|
|
141
548
|
const url = new URL(result.url);
|
|
142
549
|
const walletId = url.searchParams.get("wallet_id");
|
|
143
550
|
const organizationId = url.searchParams.get("organization_id");
|
|
144
|
-
const provider2 = url.searchParams.get("provider");
|
|
145
551
|
const accountDerivationIndex = url.searchParams.get("selected_account_index");
|
|
146
552
|
const expiresInMs = url.searchParams.get("expires_in_ms");
|
|
147
553
|
const authUserId = url.searchParams.get("auth_user_id");
|
|
@@ -155,7 +561,7 @@ var ExpoAuthProvider = class {
|
|
|
155
561
|
console.log("[ExpoAuthProvider] Auth redirect parameters", {
|
|
156
562
|
walletId,
|
|
157
563
|
organizationId,
|
|
158
|
-
provider
|
|
564
|
+
provider,
|
|
159
565
|
accountDerivationIndex,
|
|
160
566
|
expiresInMs,
|
|
161
567
|
authUserId
|
|
@@ -163,7 +569,7 @@ var ExpoAuthProvider = class {
|
|
|
163
569
|
return {
|
|
164
570
|
walletId,
|
|
165
571
|
organizationId,
|
|
166
|
-
provider:
|
|
572
|
+
provider: provider || void 0,
|
|
167
573
|
accountDerivationIndex: accountDerivationIndex ? parseInt(accountDerivationIndex) : 0,
|
|
168
574
|
expiresInMs: expiresInMs ? parseInt(expiresInMs) : 0,
|
|
169
575
|
authUserId: authUserId || void 0
|
|
@@ -470,16 +876,15 @@ var ReactNativePhantomAppProvider = class {
|
|
|
470
876
|
|
|
471
877
|
// src/PhantomProvider.tsx
|
|
472
878
|
import { Platform as Platform2 } from "react-native";
|
|
473
|
-
import { jsx } from "react/jsx-runtime";
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
const [
|
|
477
|
-
const [
|
|
478
|
-
const [
|
|
479
|
-
const [
|
|
480
|
-
const [
|
|
481
|
-
const
|
|
482
|
-
const memoizedConfig = useMemo(() => {
|
|
879
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
880
|
+
function PhantomProvider({ children, config, debugConfig, theme, appIcon, appName }) {
|
|
881
|
+
const [isConnected, setIsConnected] = useState5(false);
|
|
882
|
+
const [isConnecting, setIsConnecting] = useState5(false);
|
|
883
|
+
const [connectError, setConnectError] = useState5(null);
|
|
884
|
+
const [addresses, setAddresses] = useState5([]);
|
|
885
|
+
const [walletId, setWalletId] = useState5(null);
|
|
886
|
+
const [user, setUser] = useState5(null);
|
|
887
|
+
const memoizedConfig = useMemo2(() => {
|
|
483
888
|
const redirectUrl = config.authOptions?.redirectUrl || `${config.scheme}://phantom-auth-callback`;
|
|
484
889
|
return {
|
|
485
890
|
...config,
|
|
@@ -492,7 +897,7 @@ function PhantomProvider({ children, config, debugConfig }) {
|
|
|
492
897
|
}
|
|
493
898
|
};
|
|
494
899
|
}, [config]);
|
|
495
|
-
const sdk =
|
|
900
|
+
const sdk = useMemo2(() => {
|
|
496
901
|
const storage = new ExpoSecureStorage();
|
|
497
902
|
const authProvider = new ExpoAuthProvider();
|
|
498
903
|
const urlParamsAccessor = new ExpoURLParamsAccessor();
|
|
@@ -515,13 +920,13 @@ function PhantomProvider({ children, config, debugConfig }) {
|
|
|
515
920
|
[ANALYTICS_HEADERS.PLATFORM_VERSION]: `${Platform2.Version}`,
|
|
516
921
|
[ANALYTICS_HEADERS.APP_ID]: config.appId,
|
|
517
922
|
[ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
|
|
518
|
-
[ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.
|
|
923
|
+
[ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.24"
|
|
519
924
|
// Replaced at build time
|
|
520
925
|
}
|
|
521
926
|
};
|
|
522
927
|
return new EmbeddedProvider(memoizedConfig, platform, logger);
|
|
523
928
|
}, [memoizedConfig, debugConfig, config.appId, config.embeddedWalletType]);
|
|
524
|
-
|
|
929
|
+
useEffect2(() => {
|
|
525
930
|
const handleConnectStart = () => {
|
|
526
931
|
setIsConnecting(true);
|
|
527
932
|
setConnectError(null);
|
|
@@ -566,13 +971,11 @@ function PhantomProvider({ children, config, debugConfig }) {
|
|
|
566
971
|
sdk.off("disconnect", handleDisconnect);
|
|
567
972
|
};
|
|
568
973
|
}, [sdk]);
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
}, [sdk, config.autoConnect]);
|
|
575
|
-
const value = useMemo(
|
|
974
|
+
useEffect2(() => {
|
|
975
|
+
sdk.autoConnect().catch(() => {
|
|
976
|
+
});
|
|
977
|
+
}, [sdk]);
|
|
978
|
+
const value = useMemo2(
|
|
576
979
|
() => ({
|
|
577
980
|
sdk,
|
|
578
981
|
isConnected,
|
|
@@ -581,76 +984,13 @@ function PhantomProvider({ children, config, debugConfig }) {
|
|
|
581
984
|
addresses,
|
|
582
985
|
walletId,
|
|
583
986
|
setWalletId,
|
|
584
|
-
user
|
|
987
|
+
user,
|
|
988
|
+
allowedProviders: config.providers
|
|
585
989
|
}),
|
|
586
|
-
[sdk, isConnected, isConnecting, connectError, addresses, walletId, setWalletId, user]
|
|
990
|
+
[sdk, isConnected, isConnecting, connectError, addresses, walletId, setWalletId, user, config.providers]
|
|
587
991
|
);
|
|
588
|
-
|
|
589
|
-
}
|
|
590
|
-
function usePhantom() {
|
|
591
|
-
const context = useContext(PhantomContext);
|
|
592
|
-
if (context === void 0) {
|
|
593
|
-
throw new Error("usePhantom must be used within a PhantomProvider");
|
|
594
|
-
}
|
|
595
|
-
return context;
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
// src/hooks/useConnect.ts
|
|
599
|
-
import { useCallback } from "react";
|
|
600
|
-
function useConnect() {
|
|
601
|
-
const { sdk, isConnecting, connectError, setWalletId } = usePhantom();
|
|
602
|
-
const connect = useCallback(
|
|
603
|
-
async (options) => {
|
|
604
|
-
if (!sdk) {
|
|
605
|
-
throw new Error("SDK not initialized");
|
|
606
|
-
}
|
|
607
|
-
try {
|
|
608
|
-
const result = await sdk.connect(options);
|
|
609
|
-
if (result.status === "completed" && result.walletId) {
|
|
610
|
-
setWalletId(result.walletId);
|
|
611
|
-
}
|
|
612
|
-
return result;
|
|
613
|
-
} catch (err) {
|
|
614
|
-
const error = err;
|
|
615
|
-
throw error;
|
|
616
|
-
}
|
|
617
|
-
},
|
|
618
|
-
[sdk, setWalletId]
|
|
619
|
-
);
|
|
620
|
-
return {
|
|
621
|
-
connect,
|
|
622
|
-
isConnecting,
|
|
623
|
-
error: connectError
|
|
624
|
-
};
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
// src/hooks/useDisconnect.ts
|
|
628
|
-
import { useState as useState2, useCallback as useCallback2 } from "react";
|
|
629
|
-
function useDisconnect() {
|
|
630
|
-
const { sdk } = usePhantom();
|
|
631
|
-
const [isDisconnecting, setIsDisconnecting] = useState2(false);
|
|
632
|
-
const [error, setError] = useState2(null);
|
|
633
|
-
const disconnect = useCallback2(async () => {
|
|
634
|
-
if (!sdk) {
|
|
635
|
-
throw new Error("SDK not initialized");
|
|
636
|
-
}
|
|
637
|
-
setIsDisconnecting(true);
|
|
638
|
-
setError(null);
|
|
639
|
-
try {
|
|
640
|
-
await sdk.disconnect();
|
|
641
|
-
} catch (err) {
|
|
642
|
-
const error2 = err;
|
|
643
|
-
setError(error2);
|
|
644
|
-
throw error2;
|
|
645
|
-
} finally {
|
|
646
|
-
setIsDisconnecting(false);
|
|
647
|
-
}
|
|
648
|
-
}, [sdk]);
|
|
649
|
-
return {
|
|
650
|
-
disconnect,
|
|
651
|
-
isDisconnecting,
|
|
652
|
-
error
|
|
653
|
-
};
|
|
992
|
+
const resolvedTheme = theme || darkTheme;
|
|
993
|
+
return /* @__PURE__ */ jsx5(ThemeProvider, { theme: resolvedTheme, children: /* @__PURE__ */ jsx5(PhantomContext.Provider, { value, children: /* @__PURE__ */ jsx5(ModalProvider, { appIcon, appName, children }) }) });
|
|
654
994
|
}
|
|
655
995
|
|
|
656
996
|
// src/hooks/useAccounts.ts
|
|
@@ -688,14 +1028,18 @@ function useEthereum() {
|
|
|
688
1028
|
// src/index.ts
|
|
689
1029
|
import { AddressType } from "@phantom/client";
|
|
690
1030
|
import { NetworkId } from "@phantom/constants";
|
|
1031
|
+
import { darkTheme as darkTheme2, lightTheme } from "@phantom/wallet-sdk-ui";
|
|
691
1032
|
export {
|
|
692
1033
|
AddressType,
|
|
693
1034
|
NetworkId,
|
|
694
1035
|
PhantomProvider,
|
|
1036
|
+
darkTheme2 as darkTheme,
|
|
1037
|
+
lightTheme,
|
|
695
1038
|
useAccounts,
|
|
696
1039
|
useConnect,
|
|
697
1040
|
useDisconnect,
|
|
698
1041
|
useEthereum,
|
|
1042
|
+
useModal,
|
|
699
1043
|
usePhantom,
|
|
700
1044
|
useSolana
|
|
701
1045
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phantom/react-native-sdk",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.24",
|
|
4
4
|
"description": "Phantom Wallet SDK for React Native and Expo applications",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -41,18 +41,19 @@
|
|
|
41
41
|
"author": "Phantom",
|
|
42
42
|
"repository": {
|
|
43
43
|
"type": "git",
|
|
44
|
-
"url": "https://github.com/phantom/
|
|
44
|
+
"url": "https://github.com/phantom/phantom-connect-sdk",
|
|
45
45
|
"directory": "packages/react-native-sdk"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@phantom/api-key-stamper": "^1.0.0-beta.
|
|
49
|
-
"@phantom/base64url": "^1.0.0-beta.
|
|
50
|
-
"@phantom/chain-interfaces": "^1.0.0-beta.
|
|
51
|
-
"@phantom/client": "^1.0.0-beta.
|
|
52
|
-
"@phantom/constants": "^1.0.0-beta.
|
|
53
|
-
"@phantom/crypto": "^1.0.0-beta.
|
|
54
|
-
"@phantom/embedded-provider-core": "^1.0.0-beta.
|
|
55
|
-
"@phantom/sdk-types": "^1.0.0-beta.
|
|
48
|
+
"@phantom/api-key-stamper": "^1.0.0-beta.12",
|
|
49
|
+
"@phantom/base64url": "^1.0.0-beta.12",
|
|
50
|
+
"@phantom/chain-interfaces": "^1.0.0-beta.12",
|
|
51
|
+
"@phantom/client": "^1.0.0-beta.24",
|
|
52
|
+
"@phantom/constants": "^1.0.0-beta.12",
|
|
53
|
+
"@phantom/crypto": "^1.0.0-beta.12",
|
|
54
|
+
"@phantom/embedded-provider-core": "^1.0.0-beta.24",
|
|
55
|
+
"@phantom/sdk-types": "^1.0.0-beta.12",
|
|
56
|
+
"@phantom/wallet-sdk-ui": "^1.0.0-beta.3",
|
|
56
57
|
"@types/bs58": "^5.0.0",
|
|
57
58
|
"bs58": "^6.0.0",
|
|
58
59
|
"buffer": "^6.0.3"
|
|
@@ -64,9 +65,12 @@
|
|
|
64
65
|
"expo-web-browser": ">=12.0.0",
|
|
65
66
|
"react": ">=19.0.0",
|
|
66
67
|
"react-native": ">=0.79.0",
|
|
67
|
-
"react-native-get-random-values": ">=1.8.0"
|
|
68
|
+
"react-native-get-random-values": ">=1.8.0",
|
|
69
|
+
"react-native-svg": ">=15.0.0"
|
|
68
70
|
},
|
|
69
71
|
"devDependencies": {
|
|
72
|
+
"@testing-library/jest-native": "^5.4.3",
|
|
73
|
+
"@testing-library/react-native": "14.0.0-alpha.1",
|
|
70
74
|
"@types/jest": "^29.5.14",
|
|
71
75
|
"@types/react": "~19.0.10",
|
|
72
76
|
"@types/react-native": "^0.72.0",
|
|
@@ -81,12 +85,13 @@
|
|
|
81
85
|
"jest": "^29.7.0",
|
|
82
86
|
"jest-environment-jsdom": "^29.7.0",
|
|
83
87
|
"prettier": "^3.5.2",
|
|
84
|
-
"react": "19.
|
|
88
|
+
"react": "19.0.0",
|
|
85
89
|
"react-native": "0.79.5",
|
|
86
90
|
"rimraf": "^6.0.1",
|
|
87
91
|
"ts-jest": "^29",
|
|
88
92
|
"tsup": "^6.7.0",
|
|
89
|
-
"typescript": "^5.8.3"
|
|
93
|
+
"typescript": "^5.8.3",
|
|
94
|
+
"universal-test-renderer": "0.6.0"
|
|
90
95
|
},
|
|
91
96
|
"publishConfig": {
|
|
92
97
|
"directory": "_release/package"
|