@phantom/react-native-sdk 1.0.0-beta.14 → 1.0.0-beta.15
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/dist/index.d.ts +0 -2
- package/dist/index.js +68 -19
- package/dist/index.mjs +65 -16
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -52,6 +52,7 @@ var SecureStore = __toESM(require("expo-secure-store"));
|
|
|
52
52
|
var ExpoSecureStorage = class {
|
|
53
53
|
constructor(requireAuth = false) {
|
|
54
54
|
this.sessionKey = "phantom_session";
|
|
55
|
+
this.logoutFlagKey = "phantom_should_clear_previous_session";
|
|
55
56
|
this.requireAuth = requireAuth;
|
|
56
57
|
}
|
|
57
58
|
async saveSession(session) {
|
|
@@ -86,6 +87,36 @@ var ExpoSecureStorage = class {
|
|
|
86
87
|
console.error("[ExpoSecureStorage] Failed to clear session", { error: error.message });
|
|
87
88
|
}
|
|
88
89
|
}
|
|
90
|
+
async getShouldClearPreviousSession() {
|
|
91
|
+
try {
|
|
92
|
+
const flagData = await SecureStore.getItemAsync(this.logoutFlagKey, {
|
|
93
|
+
requireAuthentication: false
|
|
94
|
+
// Don't require auth for this flag
|
|
95
|
+
});
|
|
96
|
+
if (!flagData) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
return flagData === "true";
|
|
100
|
+
} catch (error) {
|
|
101
|
+
console.error("[ExpoSecureStorage] Failed to get shouldClearPreviousSession flag", {
|
|
102
|
+
error: error.message
|
|
103
|
+
});
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
async setShouldClearPreviousSession(should) {
|
|
108
|
+
try {
|
|
109
|
+
await SecureStore.setItemAsync(this.logoutFlagKey, should.toString(), {
|
|
110
|
+
requireAuthentication: false,
|
|
111
|
+
// Don't require auth for this flag
|
|
112
|
+
keychainAccessible: SecureStore.WHEN_UNLOCKED_THIS_DEVICE_ONLY
|
|
113
|
+
});
|
|
114
|
+
} catch (error) {
|
|
115
|
+
console.error("[ExpoSecureStorage] Failed to set shouldClearPreviousSession flag", {
|
|
116
|
+
error: error.message
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
89
120
|
async isAvailable() {
|
|
90
121
|
return await SecureStore.isAvailableAsync();
|
|
91
122
|
}
|
|
@@ -97,6 +128,7 @@ var ExpoSecureStorage = class {
|
|
|
97
128
|
|
|
98
129
|
// src/providers/embedded/auth.ts
|
|
99
130
|
var WebBrowser = __toESM(require("expo-web-browser"));
|
|
131
|
+
var import_react_native = require("react-native");
|
|
100
132
|
var import_constants = require("@phantom/constants");
|
|
101
133
|
var ExpoAuthProvider = class {
|
|
102
134
|
async authenticate(options) {
|
|
@@ -104,7 +136,7 @@ var ExpoAuthProvider = class {
|
|
|
104
136
|
return;
|
|
105
137
|
}
|
|
106
138
|
const phantomOptions = options;
|
|
107
|
-
const { authUrl, redirectUrl, publicKey, sessionId, provider,
|
|
139
|
+
const { authUrl, redirectUrl, publicKey, sessionId, provider, appId } = phantomOptions;
|
|
108
140
|
if (!redirectUrl) {
|
|
109
141
|
throw new Error("redirectUrl is required for web browser authentication");
|
|
110
142
|
}
|
|
@@ -118,8 +150,12 @@ var ExpoAuthProvider = class {
|
|
|
118
150
|
app_id: appId,
|
|
119
151
|
redirect_uri: redirectUrl,
|
|
120
152
|
session_id: sessionId,
|
|
121
|
-
|
|
122
|
-
|
|
153
|
+
// OAuth session management - defaults to allow refresh unless explicitly clearing after logout
|
|
154
|
+
clear_previous_session: (phantomOptions.clearPreviousSession ?? false).toString(),
|
|
155
|
+
allow_refresh: (phantomOptions.allowRefresh ?? true).toString(),
|
|
156
|
+
sdk_version: "1.0.0-beta.15",
|
|
157
|
+
sdk_type: "react-native",
|
|
158
|
+
platform: import_react_native.Platform.OS
|
|
123
159
|
});
|
|
124
160
|
if (provider) {
|
|
125
161
|
console.log("[ExpoAuthProvider] Provider specified, will skip selection", { provider });
|
|
@@ -128,18 +164,13 @@ var ExpoAuthProvider = class {
|
|
|
128
164
|
console.log("[ExpoAuthProvider] No provider specified, defaulting to Google");
|
|
129
165
|
params.append("provider", "google");
|
|
130
166
|
}
|
|
131
|
-
if (customAuthData) {
|
|
132
|
-
console.log("[ExpoAuthProvider] Adding custom auth data");
|
|
133
|
-
params.append("authData", JSON.stringify(customAuthData));
|
|
134
|
-
}
|
|
135
167
|
const fullAuthUrl = `${baseUrl}?${params.toString()}`;
|
|
136
168
|
console.log("[ExpoAuthProvider] Starting authentication", {
|
|
137
169
|
baseUrl,
|
|
138
170
|
redirectUrl,
|
|
139
171
|
publicKey,
|
|
140
172
|
sessionId,
|
|
141
|
-
provider
|
|
142
|
-
hasCustomData: !!customAuthData
|
|
173
|
+
provider
|
|
143
174
|
});
|
|
144
175
|
await WebBrowser.warmUpAsync();
|
|
145
176
|
const result = await WebBrowser.openAuthSessionAsync(fullAuthUrl, redirectUrl, {
|
|
@@ -157,6 +188,7 @@ var ExpoAuthProvider = class {
|
|
|
157
188
|
const provider2 = url.searchParams.get("provider");
|
|
158
189
|
const accountDerivationIndex = url.searchParams.get("selected_account_index");
|
|
159
190
|
const expiresInMs = url.searchParams.get("expires_in_ms");
|
|
191
|
+
const authUserId = url.searchParams.get("auth_user_id");
|
|
160
192
|
if (!walletId) {
|
|
161
193
|
throw new Error("Authentication failed: no walletId in redirect URL");
|
|
162
194
|
}
|
|
@@ -169,14 +201,16 @@ var ExpoAuthProvider = class {
|
|
|
169
201
|
organizationId,
|
|
170
202
|
provider: provider2,
|
|
171
203
|
accountDerivationIndex,
|
|
172
|
-
expiresInMs
|
|
204
|
+
expiresInMs,
|
|
205
|
+
authUserId
|
|
173
206
|
});
|
|
174
207
|
return {
|
|
175
208
|
walletId,
|
|
176
209
|
organizationId,
|
|
177
210
|
provider: provider2 || void 0,
|
|
178
211
|
accountDerivationIndex: accountDerivationIndex ? parseInt(accountDerivationIndex) : 0,
|
|
179
|
-
expiresInMs: expiresInMs ? parseInt(expiresInMs) : 0
|
|
212
|
+
expiresInMs: expiresInMs ? parseInt(expiresInMs) : 0,
|
|
213
|
+
authUserId: authUserId || void 0
|
|
180
214
|
};
|
|
181
215
|
} else if (result.type === "cancel") {
|
|
182
216
|
throw new Error("User cancelled authentication");
|
|
@@ -196,7 +230,7 @@ var ExpoAuthProvider = class {
|
|
|
196
230
|
};
|
|
197
231
|
|
|
198
232
|
// src/providers/embedded/url-params.ts
|
|
199
|
-
var
|
|
233
|
+
var import_react_native2 = require("react-native");
|
|
200
234
|
var ExpoURLParamsAccessor = class {
|
|
201
235
|
constructor() {
|
|
202
236
|
this.listeners = /* @__PURE__ */ new Set();
|
|
@@ -208,7 +242,7 @@ var ExpoURLParamsAccessor = class {
|
|
|
208
242
|
}
|
|
209
243
|
async getInitialParams() {
|
|
210
244
|
try {
|
|
211
|
-
const url = await
|
|
245
|
+
const url = await import_react_native2.Linking.getInitialURL();
|
|
212
246
|
if (!url) {
|
|
213
247
|
return null;
|
|
214
248
|
}
|
|
@@ -224,7 +258,7 @@ var ExpoURLParamsAccessor = class {
|
|
|
224
258
|
if (this.subscription) {
|
|
225
259
|
return;
|
|
226
260
|
}
|
|
227
|
-
this.subscription =
|
|
261
|
+
this.subscription = import_react_native2.Linking.addEventListener("url", ({ url }) => {
|
|
228
262
|
const params = this.parseURLParams(url);
|
|
229
263
|
if (params && Object.keys(params).length > 0) {
|
|
230
264
|
this.currentParams = { ...this.currentParams, ...params };
|
|
@@ -464,8 +498,22 @@ var ExpoLogger = class {
|
|
|
464
498
|
}
|
|
465
499
|
};
|
|
466
500
|
|
|
501
|
+
// src/providers/embedded/phantom-app.ts
|
|
502
|
+
var ReactNativePhantomAppProvider = class {
|
|
503
|
+
isAvailable() {
|
|
504
|
+
return false;
|
|
505
|
+
}
|
|
506
|
+
authenticate(_options) {
|
|
507
|
+
return Promise.reject(
|
|
508
|
+
new Error(
|
|
509
|
+
"Phantom app authentication is not available in React Native. Please use other authentication methods like Google, Apple, or JWT."
|
|
510
|
+
)
|
|
511
|
+
);
|
|
512
|
+
}
|
|
513
|
+
};
|
|
514
|
+
|
|
467
515
|
// src/PhantomProvider.tsx
|
|
468
|
-
var
|
|
516
|
+
var import_react_native3 = require("react-native");
|
|
469
517
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
470
518
|
var PhantomContext = (0, import_react.createContext)(void 0);
|
|
471
519
|
function PhantomProvider({ children, config, debugConfig }) {
|
|
@@ -496,20 +544,21 @@ function PhantomProvider({ children, config, debugConfig }) {
|
|
|
496
544
|
keyPrefix: `phantom-rn-${memoizedConfig.appId}`,
|
|
497
545
|
appId: memoizedConfig.appId
|
|
498
546
|
});
|
|
499
|
-
const platformName = `${
|
|
547
|
+
const platformName = `${import_react_native3.Platform.OS}-${import_react_native3.Platform.Version}`;
|
|
500
548
|
const platform = {
|
|
501
549
|
storage,
|
|
502
550
|
authProvider,
|
|
503
551
|
urlParamsAccessor,
|
|
504
552
|
stamper,
|
|
553
|
+
phantomAppProvider: new ReactNativePhantomAppProvider(),
|
|
505
554
|
name: platformName,
|
|
506
555
|
analyticsHeaders: {
|
|
507
556
|
[import_constants2.ANALYTICS_HEADERS.SDK_TYPE]: "react-native",
|
|
508
|
-
[import_constants2.ANALYTICS_HEADERS.PLATFORM]:
|
|
509
|
-
[import_constants2.ANALYTICS_HEADERS.PLATFORM_VERSION]: `${
|
|
557
|
+
[import_constants2.ANALYTICS_HEADERS.PLATFORM]: import_react_native3.Platform.OS,
|
|
558
|
+
[import_constants2.ANALYTICS_HEADERS.PLATFORM_VERSION]: `${import_react_native3.Platform.Version}`,
|
|
510
559
|
[import_constants2.ANALYTICS_HEADERS.APP_ID]: config.appId,
|
|
511
560
|
[import_constants2.ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
|
|
512
|
-
[import_constants2.ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.
|
|
561
|
+
[import_constants2.ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.15"
|
|
513
562
|
// Replaced at build time
|
|
514
563
|
}
|
|
515
564
|
};
|
package/dist/index.mjs
CHANGED
|
@@ -8,6 +8,7 @@ import * as SecureStore from "expo-secure-store";
|
|
|
8
8
|
var ExpoSecureStorage = class {
|
|
9
9
|
constructor(requireAuth = false) {
|
|
10
10
|
this.sessionKey = "phantom_session";
|
|
11
|
+
this.logoutFlagKey = "phantom_should_clear_previous_session";
|
|
11
12
|
this.requireAuth = requireAuth;
|
|
12
13
|
}
|
|
13
14
|
async saveSession(session) {
|
|
@@ -42,6 +43,36 @@ var ExpoSecureStorage = class {
|
|
|
42
43
|
console.error("[ExpoSecureStorage] Failed to clear session", { error: error.message });
|
|
43
44
|
}
|
|
44
45
|
}
|
|
46
|
+
async getShouldClearPreviousSession() {
|
|
47
|
+
try {
|
|
48
|
+
const flagData = await SecureStore.getItemAsync(this.logoutFlagKey, {
|
|
49
|
+
requireAuthentication: false
|
|
50
|
+
// Don't require auth for this flag
|
|
51
|
+
});
|
|
52
|
+
if (!flagData) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
return flagData === "true";
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error("[ExpoSecureStorage] Failed to get shouldClearPreviousSession flag", {
|
|
58
|
+
error: error.message
|
|
59
|
+
});
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async setShouldClearPreviousSession(should) {
|
|
64
|
+
try {
|
|
65
|
+
await SecureStore.setItemAsync(this.logoutFlagKey, should.toString(), {
|
|
66
|
+
requireAuthentication: false,
|
|
67
|
+
// Don't require auth for this flag
|
|
68
|
+
keychainAccessible: SecureStore.WHEN_UNLOCKED_THIS_DEVICE_ONLY
|
|
69
|
+
});
|
|
70
|
+
} catch (error) {
|
|
71
|
+
console.error("[ExpoSecureStorage] Failed to set shouldClearPreviousSession flag", {
|
|
72
|
+
error: error.message
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
45
76
|
async isAvailable() {
|
|
46
77
|
return await SecureStore.isAvailableAsync();
|
|
47
78
|
}
|
|
@@ -53,6 +84,7 @@ var ExpoSecureStorage = class {
|
|
|
53
84
|
|
|
54
85
|
// src/providers/embedded/auth.ts
|
|
55
86
|
import * as WebBrowser from "expo-web-browser";
|
|
87
|
+
import { Platform } from "react-native";
|
|
56
88
|
import { DEFAULT_AUTH_URL } from "@phantom/constants";
|
|
57
89
|
var ExpoAuthProvider = class {
|
|
58
90
|
async authenticate(options) {
|
|
@@ -60,7 +92,7 @@ var ExpoAuthProvider = class {
|
|
|
60
92
|
return;
|
|
61
93
|
}
|
|
62
94
|
const phantomOptions = options;
|
|
63
|
-
const { authUrl, redirectUrl, publicKey, sessionId, provider,
|
|
95
|
+
const { authUrl, redirectUrl, publicKey, sessionId, provider, appId } = phantomOptions;
|
|
64
96
|
if (!redirectUrl) {
|
|
65
97
|
throw new Error("redirectUrl is required for web browser authentication");
|
|
66
98
|
}
|
|
@@ -74,8 +106,12 @@ var ExpoAuthProvider = class {
|
|
|
74
106
|
app_id: appId,
|
|
75
107
|
redirect_uri: redirectUrl,
|
|
76
108
|
session_id: sessionId,
|
|
77
|
-
|
|
78
|
-
|
|
109
|
+
// OAuth session management - defaults to allow refresh unless explicitly clearing after logout
|
|
110
|
+
clear_previous_session: (phantomOptions.clearPreviousSession ?? false).toString(),
|
|
111
|
+
allow_refresh: (phantomOptions.allowRefresh ?? true).toString(),
|
|
112
|
+
sdk_version: "1.0.0-beta.15",
|
|
113
|
+
sdk_type: "react-native",
|
|
114
|
+
platform: Platform.OS
|
|
79
115
|
});
|
|
80
116
|
if (provider) {
|
|
81
117
|
console.log("[ExpoAuthProvider] Provider specified, will skip selection", { provider });
|
|
@@ -84,18 +120,13 @@ var ExpoAuthProvider = class {
|
|
|
84
120
|
console.log("[ExpoAuthProvider] No provider specified, defaulting to Google");
|
|
85
121
|
params.append("provider", "google");
|
|
86
122
|
}
|
|
87
|
-
if (customAuthData) {
|
|
88
|
-
console.log("[ExpoAuthProvider] Adding custom auth data");
|
|
89
|
-
params.append("authData", JSON.stringify(customAuthData));
|
|
90
|
-
}
|
|
91
123
|
const fullAuthUrl = `${baseUrl}?${params.toString()}`;
|
|
92
124
|
console.log("[ExpoAuthProvider] Starting authentication", {
|
|
93
125
|
baseUrl,
|
|
94
126
|
redirectUrl,
|
|
95
127
|
publicKey,
|
|
96
128
|
sessionId,
|
|
97
|
-
provider
|
|
98
|
-
hasCustomData: !!customAuthData
|
|
129
|
+
provider
|
|
99
130
|
});
|
|
100
131
|
await WebBrowser.warmUpAsync();
|
|
101
132
|
const result = await WebBrowser.openAuthSessionAsync(fullAuthUrl, redirectUrl, {
|
|
@@ -113,6 +144,7 @@ var ExpoAuthProvider = class {
|
|
|
113
144
|
const provider2 = url.searchParams.get("provider");
|
|
114
145
|
const accountDerivationIndex = url.searchParams.get("selected_account_index");
|
|
115
146
|
const expiresInMs = url.searchParams.get("expires_in_ms");
|
|
147
|
+
const authUserId = url.searchParams.get("auth_user_id");
|
|
116
148
|
if (!walletId) {
|
|
117
149
|
throw new Error("Authentication failed: no walletId in redirect URL");
|
|
118
150
|
}
|
|
@@ -125,14 +157,16 @@ var ExpoAuthProvider = class {
|
|
|
125
157
|
organizationId,
|
|
126
158
|
provider: provider2,
|
|
127
159
|
accountDerivationIndex,
|
|
128
|
-
expiresInMs
|
|
160
|
+
expiresInMs,
|
|
161
|
+
authUserId
|
|
129
162
|
});
|
|
130
163
|
return {
|
|
131
164
|
walletId,
|
|
132
165
|
organizationId,
|
|
133
166
|
provider: provider2 || void 0,
|
|
134
167
|
accountDerivationIndex: accountDerivationIndex ? parseInt(accountDerivationIndex) : 0,
|
|
135
|
-
expiresInMs: expiresInMs ? parseInt(expiresInMs) : 0
|
|
168
|
+
expiresInMs: expiresInMs ? parseInt(expiresInMs) : 0,
|
|
169
|
+
authUserId: authUserId || void 0
|
|
136
170
|
};
|
|
137
171
|
} else if (result.type === "cancel") {
|
|
138
172
|
throw new Error("User cancelled authentication");
|
|
@@ -420,8 +454,22 @@ var ExpoLogger = class {
|
|
|
420
454
|
}
|
|
421
455
|
};
|
|
422
456
|
|
|
457
|
+
// src/providers/embedded/phantom-app.ts
|
|
458
|
+
var ReactNativePhantomAppProvider = class {
|
|
459
|
+
isAvailable() {
|
|
460
|
+
return false;
|
|
461
|
+
}
|
|
462
|
+
authenticate(_options) {
|
|
463
|
+
return Promise.reject(
|
|
464
|
+
new Error(
|
|
465
|
+
"Phantom app authentication is not available in React Native. Please use other authentication methods like Google, Apple, or JWT."
|
|
466
|
+
)
|
|
467
|
+
);
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
|
|
423
471
|
// src/PhantomProvider.tsx
|
|
424
|
-
import { Platform } from "react-native";
|
|
472
|
+
import { Platform as Platform2 } from "react-native";
|
|
425
473
|
import { jsx } from "react/jsx-runtime";
|
|
426
474
|
var PhantomContext = createContext(void 0);
|
|
427
475
|
function PhantomProvider({ children, config, debugConfig }) {
|
|
@@ -452,20 +500,21 @@ function PhantomProvider({ children, config, debugConfig }) {
|
|
|
452
500
|
keyPrefix: `phantom-rn-${memoizedConfig.appId}`,
|
|
453
501
|
appId: memoizedConfig.appId
|
|
454
502
|
});
|
|
455
|
-
const platformName = `${
|
|
503
|
+
const platformName = `${Platform2.OS}-${Platform2.Version}`;
|
|
456
504
|
const platform = {
|
|
457
505
|
storage,
|
|
458
506
|
authProvider,
|
|
459
507
|
urlParamsAccessor,
|
|
460
508
|
stamper,
|
|
509
|
+
phantomAppProvider: new ReactNativePhantomAppProvider(),
|
|
461
510
|
name: platformName,
|
|
462
511
|
analyticsHeaders: {
|
|
463
512
|
[ANALYTICS_HEADERS.SDK_TYPE]: "react-native",
|
|
464
|
-
[ANALYTICS_HEADERS.PLATFORM]:
|
|
465
|
-
[ANALYTICS_HEADERS.PLATFORM_VERSION]: `${
|
|
513
|
+
[ANALYTICS_HEADERS.PLATFORM]: Platform2.OS,
|
|
514
|
+
[ANALYTICS_HEADERS.PLATFORM_VERSION]: `${Platform2.Version}`,
|
|
466
515
|
[ANALYTICS_HEADERS.APP_ID]: config.appId,
|
|
467
516
|
[ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
|
|
468
|
-
[ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.
|
|
517
|
+
[ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.15"
|
|
469
518
|
// Replaced at build time
|
|
470
519
|
}
|
|
471
520
|
};
|
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.15",
|
|
4
4
|
"description": "Phantom Wallet SDK for React Native and Expo applications",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -48,10 +48,10 @@
|
|
|
48
48
|
"@phantom/api-key-stamper": "^1.0.0-beta.7",
|
|
49
49
|
"@phantom/base64url": "^1.0.0-beta.7",
|
|
50
50
|
"@phantom/chain-interfaces": "^1.0.0-beta.7",
|
|
51
|
-
"@phantom/client": "^1.0.0-beta.
|
|
51
|
+
"@phantom/client": "^1.0.0-beta.15",
|
|
52
52
|
"@phantom/constants": "^1.0.0-beta.7",
|
|
53
53
|
"@phantom/crypto": "^1.0.0-beta.7",
|
|
54
|
-
"@phantom/embedded-provider-core": "^1.0.0-beta.
|
|
54
|
+
"@phantom/embedded-provider-core": "^1.0.0-beta.15",
|
|
55
55
|
"@phantom/sdk-types": "^1.0.0-beta.7",
|
|
56
56
|
"@types/bs58": "^5.0.0",
|
|
57
57
|
"bs58": "^6.0.0",
|