@phantom/react-native-sdk 1.0.0-beta.13 → 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/README.md CHANGED
@@ -473,11 +473,3 @@ interface PhantomDebugConfig {
473
473
  }
474
474
  ```
475
475
 
476
- ## Support
477
-
478
- - **Documentation**: [phantom.app/docs](https://phantom.app/docs)
479
- - **GitHub Issues**: [github.com/phantom/wallet-sdk/issues](https://github.com/phantom/wallet-sdk/issues)
480
-
481
- ## License
482
-
483
- MIT License - see [LICENSE](LICENSE) file for details.
package/dist/index.d.ts CHANGED
@@ -30,8 +30,6 @@ interface ConnectOptions {
30
30
  provider?: "google" | "apple" | "jwt";
31
31
  /** JWT token for JWT authentication */
32
32
  jwtToken?: string;
33
- /** Custom authentication data */
34
- customAuthData?: Record<string, any>;
35
33
  }
36
34
 
37
35
  interface PhantomContextValue {
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, customAuthData, appId } = phantomOptions;
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
- clear_previous_session: "true",
122
- sdk_version: "1.0.0-beta.13"
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 import_react_native = require("react-native");
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 import_react_native.Linking.getInitialURL();
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 = import_react_native.Linking.addEventListener("url", ({ url }) => {
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 import_react_native2 = require("react-native");
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 = `${import_react_native2.Platform.OS}-${import_react_native2.Platform.Version}`;
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]: import_react_native2.Platform.OS,
509
- [import_constants2.ANALYTICS_HEADERS.PLATFORM_VERSION]: `${import_react_native2.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.13"
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, customAuthData, appId } = phantomOptions;
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
- clear_previous_session: "true",
78
- sdk_version: "1.0.0-beta.13"
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 = `${Platform.OS}-${Platform.Version}`;
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]: Platform.OS,
465
- [ANALYTICS_HEADERS.PLATFORM_VERSION]: `${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.13"
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.13",
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.13",
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.13",
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",