@phantom/browser-sdk 1.0.0-beta.14 → 1.0.0-beta.16

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.js CHANGED
@@ -31,6 +31,7 @@ __export(src_exports, {
31
31
  getDeeplinkToPhantom: () => getDeeplinkToPhantom,
32
32
  getPlatformName: () => getPlatformName,
33
33
  isMobileDevice: () => isMobileDevice,
34
+ isPhantomLoginAvailable: () => isPhantomLoginAvailable,
34
35
  parseBrowserFromUserAgent: () => parseBrowserFromUserAgent,
35
36
  waitForPhantomExtension: () => waitForPhantomExtension
36
37
  });
@@ -476,7 +477,12 @@ var InjectedProvider = class {
476
477
  debug.info(DebugCategory.INJECTED_PROVIDER, "Solana connected successfully", { address: publicKey });
477
478
  }
478
479
  } catch (err) {
479
- debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Solana", { error: err });
480
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Solana, stopping", { error: err });
481
+ this.emit("connect_error", {
482
+ error: err instanceof Error ? err.message : "Failed to connect",
483
+ source: "manual-connect"
484
+ });
485
+ throw err;
480
486
  }
481
487
  }
482
488
  if (this.addressTypes.includes(import_client4.AddressType.ethereum)) {
@@ -492,7 +498,12 @@ var InjectedProvider = class {
492
498
  debug.info(DebugCategory.INJECTED_PROVIDER, "Ethereum connected successfully", { addresses: accounts });
493
499
  }
494
500
  } catch (err) {
495
- debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Ethereum", { error: err });
501
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Ethereum, stopping", { error: err });
502
+ this.emit("connect_error", {
503
+ error: err instanceof Error ? err.message : "Failed to connect",
504
+ source: "manual-connect"
505
+ });
506
+ throw err;
496
507
  }
497
508
  }
498
509
  if (connectedAddresses.length === 0) {
@@ -901,6 +912,47 @@ var BrowserStorage = class {
901
912
  };
902
913
  });
903
914
  }
915
+ async getShouldClearPreviousSession() {
916
+ debug.log(DebugCategory.STORAGE, "Getting shouldClearPreviousSession flag from IndexedDB");
917
+ const db = await this.getDB();
918
+ return new Promise((resolve, reject) => {
919
+ const transaction = db.transaction([this.storeName], "readonly");
920
+ const store = transaction.objectStore(this.storeName);
921
+ const request = store.get("shouldClearPreviousSession");
922
+ request.onsuccess = () => {
923
+ const shouldClear = request.result ?? false;
924
+ debug.log(DebugCategory.STORAGE, "Retrieved shouldClearPreviousSession flag from IndexedDB", {
925
+ shouldClear
926
+ });
927
+ resolve(shouldClear);
928
+ };
929
+ request.onerror = () => {
930
+ debug.error(DebugCategory.STORAGE, "Failed to get shouldClearPreviousSession flag from IndexedDB", {
931
+ error: request.error
932
+ });
933
+ reject(request.error);
934
+ };
935
+ });
936
+ }
937
+ async setShouldClearPreviousSession(should) {
938
+ debug.log(DebugCategory.STORAGE, "Setting shouldClearPreviousSession flag in IndexedDB", { should });
939
+ const db = await this.getDB();
940
+ return new Promise((resolve, reject) => {
941
+ const transaction = db.transaction([this.storeName], "readwrite");
942
+ const store = transaction.objectStore(this.storeName);
943
+ const request = store.put(should, "shouldClearPreviousSession");
944
+ request.onsuccess = () => {
945
+ debug.log(DebugCategory.STORAGE, "Successfully set shouldClearPreviousSession flag in IndexedDB");
946
+ resolve();
947
+ };
948
+ request.onerror = () => {
949
+ debug.error(DebugCategory.STORAGE, "Failed to set shouldClearPreviousSession flag in IndexedDB", {
950
+ error: request.error
951
+ });
952
+ reject(request.error);
953
+ };
954
+ });
955
+ }
904
956
  };
905
957
 
906
958
  // src/providers/embedded/adapters/url-params.ts
@@ -914,6 +966,147 @@ var browserUrlParamsAccessor = new BrowserURLParamsAccessor();
914
966
 
915
967
  // src/providers/embedded/adapters/auth.ts
916
968
  var import_constants = require("@phantom/constants");
969
+
970
+ // src/utils/browser-detection.ts
971
+ function parseBrowserFromUserAgent(userAgent, hasBraveAPI) {
972
+ let name = "unknown";
973
+ let version = "unknown";
974
+ if (!userAgent || typeof userAgent !== "string") {
975
+ return { name, version, userAgent: "unknown" };
976
+ }
977
+ try {
978
+ if (userAgent.includes("Edg/")) {
979
+ name = "edge";
980
+ const match = userAgent.match(/Edg\/([0-9]+(?:\.[0-9]+)*)/);
981
+ if (match)
982
+ version = match[1].split(".")[0];
983
+ } else if (userAgent.includes("OPR/") || userAgent.includes("Opera/")) {
984
+ name = "opera";
985
+ const match = userAgent.match(/(?:OPR|Opera)\/([0-9]+(?:\.[0-9]+)*)/);
986
+ if (match)
987
+ version = match[1].split(".")[0];
988
+ } else if (userAgent.includes("SamsungBrowser/")) {
989
+ name = "samsung";
990
+ const match = userAgent.match(/SamsungBrowser\/([0-9]+(?:\.[0-9]+)*)/);
991
+ if (match)
992
+ version = match[1].split(".")[0];
993
+ } else if (userAgent.includes("DuckDuckGo/")) {
994
+ name = "duckduckgo";
995
+ const match = userAgent.match(/DuckDuckGo\/([0-9]+(?:\.[0-9]+)*)/);
996
+ if (match)
997
+ version = match[1].split(".")[0];
998
+ } else if (userAgent.includes("Chrome/") && hasBraveAPI) {
999
+ name = "brave";
1000
+ const match = userAgent.match(/Chrome\/([0-9]+(?:\.[0-9]+)*)/);
1001
+ if (match)
1002
+ version = match[1].split(".")[0];
1003
+ } else if (userAgent.includes("Mobile/") || userAgent.includes("Android")) {
1004
+ if (userAgent.includes("Chrome/")) {
1005
+ name = "chrome-mobile";
1006
+ const match = userAgent.match(/Chrome\/([0-9]+(?:\.[0-9]+)*)/);
1007
+ if (match)
1008
+ version = match[1].split(".")[0];
1009
+ } else if (userAgent.includes("Firefox/")) {
1010
+ name = "firefox-mobile";
1011
+ const match = userAgent.match(/Firefox\/([0-9]+(?:\.[0-9]+)*)/);
1012
+ if (match)
1013
+ version = match[1].split(".")[0];
1014
+ } else if (userAgent.includes("Safari/") && userAgent.includes("Mobile/")) {
1015
+ name = "safari-mobile";
1016
+ const match = userAgent.match(/Version\/([0-9]+(?:\.[0-9]+)*)/);
1017
+ if (match)
1018
+ version = match[1].split(".")[0];
1019
+ } else {
1020
+ name = "mobile";
1021
+ }
1022
+ } else if (userAgent.includes("Chrome/")) {
1023
+ name = "chrome";
1024
+ const match = userAgent.match(/Chrome\/([0-9]+(?:\.[0-9]+)*)/);
1025
+ if (match)
1026
+ version = match[1].split(".")[0];
1027
+ } else if (userAgent.includes("Firefox/")) {
1028
+ name = "firefox";
1029
+ const match = userAgent.match(/Firefox\/([0-9]+(?:\.[0-9]+)*)/);
1030
+ if (match)
1031
+ version = match[1].split(".")[0];
1032
+ } else if (userAgent.includes("Safari/") && !userAgent.includes("Chrome/")) {
1033
+ name = "safari";
1034
+ const match = userAgent.match(/Version\/([0-9]+(?:\.[0-9]+)*)/);
1035
+ if (match)
1036
+ version = match[1].split(".")[0];
1037
+ }
1038
+ if (name === "unknown") {
1039
+ const patterns = [
1040
+ { regex: /Chrome\/([0-9]+)/, name: "chrome" },
1041
+ { regex: /Firefox\/([0-9]+)/, name: "firefox" },
1042
+ { regex: /Safari\/([0-9]+)/, name: "safari" },
1043
+ { regex: /Edge\/([0-9]+)/, name: "edge" },
1044
+ { regex: /Opera\/([0-9]+)/, name: "opera" }
1045
+ ];
1046
+ for (const pattern of patterns) {
1047
+ const match = userAgent.match(pattern.regex);
1048
+ if (match) {
1049
+ name = pattern.name;
1050
+ version = match[1];
1051
+ break;
1052
+ }
1053
+ }
1054
+ }
1055
+ } catch (error) {
1056
+ }
1057
+ return { name, version, userAgent };
1058
+ }
1059
+ function detectBrowser() {
1060
+ if (typeof window === "undefined" || !window.navigator?.userAgent) {
1061
+ return { name: "unknown", version: "unknown", userAgent: "unknown" };
1062
+ }
1063
+ const userAgent = window.navigator.userAgent;
1064
+ const hasBraveAPI = !!navigator.brave;
1065
+ return parseBrowserFromUserAgent(userAgent, hasBraveAPI);
1066
+ }
1067
+ function getPlatformName() {
1068
+ const { name, version } = detectBrowser();
1069
+ return version !== "unknown" ? `${name}-v${version}` : name;
1070
+ }
1071
+ function getBrowserDisplayName() {
1072
+ const { name, version } = detectBrowser();
1073
+ const capitalizedName = name.charAt(0).toUpperCase() + name.slice(1);
1074
+ return version !== "unknown" ? `${capitalizedName} ${version}` : capitalizedName;
1075
+ }
1076
+ function isMobileDevice() {
1077
+ if (typeof window === "undefined" || !window.navigator?.userAgent) {
1078
+ return false;
1079
+ }
1080
+ const userAgent = window.navigator.userAgent.toLowerCase();
1081
+ const mobilePatterns = [
1082
+ /android/,
1083
+ /iphone|ipad|ipod/,
1084
+ /blackberry/,
1085
+ /windows phone/,
1086
+ /mobile/,
1087
+ /tablet/,
1088
+ /silk/,
1089
+ /kindle/,
1090
+ /opera mini/,
1091
+ /opera mobi/
1092
+ ];
1093
+ const isMobileUA = mobilePatterns.some((pattern) => pattern.test(userAgent));
1094
+ let isSmallScreen = false;
1095
+ try {
1096
+ isSmallScreen = window.screen.width <= 768 || window.screen.height <= 768;
1097
+ } catch (error) {
1098
+ isSmallScreen = false;
1099
+ }
1100
+ let isTouchDevice = false;
1101
+ try {
1102
+ isTouchDevice = "ontouchstart" in window || navigator.maxTouchPoints > 0;
1103
+ } catch (error) {
1104
+ isTouchDevice = false;
1105
+ }
1106
+ return isMobileUA || isSmallScreen && isTouchDevice;
1107
+ }
1108
+
1109
+ // src/providers/embedded/adapters/auth.ts
917
1110
  var BrowserAuthProvider = class {
918
1111
  constructor(urlParamsAccessor) {
919
1112
  this.urlParamsAccessor = urlParamsAccessor;
@@ -935,8 +1128,7 @@ var BrowserAuthProvider = class {
935
1128
  publicKey: phantomOptions.publicKey,
936
1129
  appId: phantomOptions.appId,
937
1130
  provider: phantomOptions.provider,
938
- authUrl: phantomOptions.authUrl,
939
- hasCustomData: !!phantomOptions.customAuthData
1131
+ authUrl: phantomOptions.authUrl
940
1132
  });
941
1133
  const baseUrl = phantomOptions.authUrl || import_constants.DEFAULT_AUTH_URL;
942
1134
  debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Using auth URL", { baseUrl });
@@ -945,8 +1137,12 @@ var BrowserAuthProvider = class {
945
1137
  app_id: phantomOptions.appId,
946
1138
  redirect_uri: phantomOptions.redirectUrl || (typeof window !== "undefined" ? this.getValidatedCurrentUrl() : ""),
947
1139
  session_id: phantomOptions.sessionId,
948
- clear_previous_session: true.toString(),
949
- sdk_version: "1.0.0-beta.14"
1140
+ // OAuth session management - defaults to allow refresh unless explicitly clearing after logout
1141
+ clear_previous_session: (phantomOptions.clearPreviousSession ?? false).toString(),
1142
+ allow_refresh: (phantomOptions.allowRefresh ?? true).toString(),
1143
+ sdk_version: "1.0.0-beta.16",
1144
+ sdk_type: "browser",
1145
+ platform: detectBrowser().name
950
1146
  });
951
1147
  if (phantomOptions.provider) {
952
1148
  debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Provider specified, will skip selection", {
@@ -957,10 +1153,6 @@ var BrowserAuthProvider = class {
957
1153
  debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "No provider specified, defaulting to Google");
958
1154
  params.append("provider", "google");
959
1155
  }
960
- if (phantomOptions.customAuthData) {
961
- debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Adding custom auth data");
962
- params.append("authData", JSON.stringify(phantomOptions.customAuthData));
963
- }
964
1156
  const authContext = {
965
1157
  publicKey: phantomOptions.publicKey,
966
1158
  appId: phantomOptions.appId,
@@ -1031,12 +1223,14 @@ var BrowserAuthProvider = class {
1031
1223
  });
1032
1224
  const organizationId = this.urlParamsAccessor.getParam("organization_id");
1033
1225
  const expiresInMs = this.urlParamsAccessor.getParam("expires_in_ms");
1226
+ const authUserId = this.urlParamsAccessor.getParam("auth_user_id");
1034
1227
  debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Auth redirect parameters", {
1035
1228
  walletId,
1036
1229
  organizationId,
1037
1230
  sessionId,
1038
1231
  accountDerivationIndex,
1039
- expiresInMs
1232
+ expiresInMs,
1233
+ authUserId
1040
1234
  });
1041
1235
  if (!organizationId) {
1042
1236
  debug.error(DebugCategory.PHANTOM_CONNECT_AUTH, "Missing organization_id in auth response");
@@ -1050,9 +1244,9 @@ var BrowserAuthProvider = class {
1050
1244
  return {
1051
1245
  walletId,
1052
1246
  organizationId,
1053
- userInfo: context,
1054
1247
  accountDerivationIndex: accountDerivationIndex ? parseInt(accountDerivationIndex) : 0,
1055
- expiresInMs: expiresInMs ? parseInt(expiresInMs) : 0
1248
+ expiresInMs: expiresInMs ? parseInt(expiresInMs) : 0,
1249
+ authUserId: authUserId || void 0
1056
1250
  };
1057
1251
  } catch (error) {
1058
1252
  sessionStorage.removeItem("phantom-auth-context");
@@ -1061,6 +1255,74 @@ var BrowserAuthProvider = class {
1061
1255
  }
1062
1256
  };
1063
1257
 
1258
+ // src/providers/embedded/adapters/phantom-app.ts
1259
+ var import_browser_injected_sdk2 = require("@phantom/browser-injected-sdk");
1260
+ var BrowserPhantomAppProvider = class {
1261
+ /**
1262
+ * Check if the Phantom extension is installed in the browser
1263
+ */
1264
+ isAvailable() {
1265
+ return (0, import_browser_injected_sdk2.isPhantomExtensionInstalled)();
1266
+ }
1267
+ /**
1268
+ * Authenticate using the Phantom browser extension
1269
+ */
1270
+ async authenticate(options) {
1271
+ if (!this.isAvailable()) {
1272
+ throw new Error(
1273
+ "Phantom extension is not installed. Please install the Phantom browser extension to use this authentication method."
1274
+ );
1275
+ }
1276
+ if (!window.phantom?.app?.login || typeof window.phantom.app.login !== "function") {
1277
+ throw new Error(
1278
+ "Phantom extension authentication is not yet implemented. The extension needs to expose an app.login API (window.phantom.app.login)."
1279
+ );
1280
+ }
1281
+ try {
1282
+ if (!window.phantom?.app?.features || typeof window.phantom.app.features !== "function") {
1283
+ throw new Error(
1284
+ "Phantom Login is not available. The extension does not support the features API."
1285
+ );
1286
+ }
1287
+ const features = await window.phantom.app.features();
1288
+ if (!Array.isArray(features) || !features.includes("phantom_login")) {
1289
+ throw new Error(
1290
+ "Phantom Login is not available. Please update your Phantom extension to use this authentication method."
1291
+ );
1292
+ }
1293
+ } catch (error) {
1294
+ if (error instanceof Error) {
1295
+ throw error;
1296
+ }
1297
+ throw new Error(
1298
+ "Failed to check Phantom Login availability. Please ensure you have the latest version of the Phantom extension."
1299
+ );
1300
+ }
1301
+ try {
1302
+ const result = await window.phantom.app.login({
1303
+ publicKey: options.publicKey,
1304
+ appId: options.appId,
1305
+ sessionId: options.sessionId
1306
+ });
1307
+ if (!result || !result.walletId || !result.organizationId) {
1308
+ throw new Error("Invalid authentication response from Phantom extension");
1309
+ }
1310
+ return {
1311
+ walletId: result.walletId,
1312
+ organizationId: result.organizationId,
1313
+ provider: "phantom",
1314
+ accountDerivationIndex: result.accountDerivationIndex ?? 0,
1315
+ expiresInMs: result.expiresInMs ?? 0
1316
+ };
1317
+ } catch (error) {
1318
+ if (error instanceof Error) {
1319
+ throw error;
1320
+ }
1321
+ throw new Error(`Phantom extension authentication failed: ${String(error)}`);
1322
+ }
1323
+ }
1324
+ };
1325
+
1064
1326
  // src/providers/embedded/adapters/logger.ts
1065
1327
  var BrowserLogger = class {
1066
1328
  info(category, message, data) {
@@ -1077,145 +1339,6 @@ var BrowserLogger = class {
1077
1339
  }
1078
1340
  };
1079
1341
 
1080
- // src/utils/browser-detection.ts
1081
- function parseBrowserFromUserAgent(userAgent, hasBraveAPI) {
1082
- let name = "unknown";
1083
- let version = "unknown";
1084
- if (!userAgent || typeof userAgent !== "string") {
1085
- return { name, version, userAgent: "unknown" };
1086
- }
1087
- try {
1088
- if (userAgent.includes("Edg/")) {
1089
- name = "edge";
1090
- const match = userAgent.match(/Edg\/([0-9]+(?:\.[0-9]+)*)/);
1091
- if (match)
1092
- version = match[1].split(".")[0];
1093
- } else if (userAgent.includes("OPR/") || userAgent.includes("Opera/")) {
1094
- name = "opera";
1095
- const match = userAgent.match(/(?:OPR|Opera)\/([0-9]+(?:\.[0-9]+)*)/);
1096
- if (match)
1097
- version = match[1].split(".")[0];
1098
- } else if (userAgent.includes("SamsungBrowser/")) {
1099
- name = "samsung";
1100
- const match = userAgent.match(/SamsungBrowser\/([0-9]+(?:\.[0-9]+)*)/);
1101
- if (match)
1102
- version = match[1].split(".")[0];
1103
- } else if (userAgent.includes("DuckDuckGo/")) {
1104
- name = "duckduckgo";
1105
- const match = userAgent.match(/DuckDuckGo\/([0-9]+(?:\.[0-9]+)*)/);
1106
- if (match)
1107
- version = match[1].split(".")[0];
1108
- } else if (userAgent.includes("Chrome/") && hasBraveAPI) {
1109
- name = "brave";
1110
- const match = userAgent.match(/Chrome\/([0-9]+(?:\.[0-9]+)*)/);
1111
- if (match)
1112
- version = match[1].split(".")[0];
1113
- } else if (userAgent.includes("Mobile/") || userAgent.includes("Android")) {
1114
- if (userAgent.includes("Chrome/")) {
1115
- name = "chrome-mobile";
1116
- const match = userAgent.match(/Chrome\/([0-9]+(?:\.[0-9]+)*)/);
1117
- if (match)
1118
- version = match[1].split(".")[0];
1119
- } else if (userAgent.includes("Firefox/")) {
1120
- name = "firefox-mobile";
1121
- const match = userAgent.match(/Firefox\/([0-9]+(?:\.[0-9]+)*)/);
1122
- if (match)
1123
- version = match[1].split(".")[0];
1124
- } else if (userAgent.includes("Safari/") && userAgent.includes("Mobile/")) {
1125
- name = "safari-mobile";
1126
- const match = userAgent.match(/Version\/([0-9]+(?:\.[0-9]+)*)/);
1127
- if (match)
1128
- version = match[1].split(".")[0];
1129
- } else {
1130
- name = "mobile";
1131
- }
1132
- } else if (userAgent.includes("Chrome/")) {
1133
- name = "chrome";
1134
- const match = userAgent.match(/Chrome\/([0-9]+(?:\.[0-9]+)*)/);
1135
- if (match)
1136
- version = match[1].split(".")[0];
1137
- } else if (userAgent.includes("Firefox/")) {
1138
- name = "firefox";
1139
- const match = userAgent.match(/Firefox\/([0-9]+(?:\.[0-9]+)*)/);
1140
- if (match)
1141
- version = match[1].split(".")[0];
1142
- } else if (userAgent.includes("Safari/") && !userAgent.includes("Chrome/")) {
1143
- name = "safari";
1144
- const match = userAgent.match(/Version\/([0-9]+(?:\.[0-9]+)*)/);
1145
- if (match)
1146
- version = match[1].split(".")[0];
1147
- }
1148
- if (name === "unknown") {
1149
- const patterns = [
1150
- { regex: /Chrome\/([0-9]+)/, name: "chrome" },
1151
- { regex: /Firefox\/([0-9]+)/, name: "firefox" },
1152
- { regex: /Safari\/([0-9]+)/, name: "safari" },
1153
- { regex: /Edge\/([0-9]+)/, name: "edge" },
1154
- { regex: /Opera\/([0-9]+)/, name: "opera" }
1155
- ];
1156
- for (const pattern of patterns) {
1157
- const match = userAgent.match(pattern.regex);
1158
- if (match) {
1159
- name = pattern.name;
1160
- version = match[1];
1161
- break;
1162
- }
1163
- }
1164
- }
1165
- } catch (error) {
1166
- }
1167
- return { name, version, userAgent };
1168
- }
1169
- function detectBrowser() {
1170
- if (typeof window === "undefined" || !window.navigator?.userAgent) {
1171
- return { name: "unknown", version: "unknown", userAgent: "unknown" };
1172
- }
1173
- const userAgent = window.navigator.userAgent;
1174
- const hasBraveAPI = !!navigator.brave;
1175
- return parseBrowserFromUserAgent(userAgent, hasBraveAPI);
1176
- }
1177
- function getPlatformName() {
1178
- const { name, version } = detectBrowser();
1179
- return version !== "unknown" ? `${name}-v${version}` : name;
1180
- }
1181
- function getBrowserDisplayName() {
1182
- const { name, version } = detectBrowser();
1183
- const capitalizedName = name.charAt(0).toUpperCase() + name.slice(1);
1184
- return version !== "unknown" ? `${capitalizedName} ${version}` : capitalizedName;
1185
- }
1186
- function isMobileDevice() {
1187
- if (typeof window === "undefined" || !window.navigator?.userAgent) {
1188
- return false;
1189
- }
1190
- const userAgent = window.navigator.userAgent.toLowerCase();
1191
- const mobilePatterns = [
1192
- /android/,
1193
- /iphone|ipad|ipod/,
1194
- /blackberry/,
1195
- /windows phone/,
1196
- /mobile/,
1197
- /tablet/,
1198
- /silk/,
1199
- /kindle/,
1200
- /opera mini/,
1201
- /opera mobi/
1202
- ];
1203
- const isMobileUA = mobilePatterns.some((pattern) => pattern.test(userAgent));
1204
- let isSmallScreen = false;
1205
- try {
1206
- isSmallScreen = window.screen.width <= 768 || window.screen.height <= 768;
1207
- } catch (error) {
1208
- isSmallScreen = false;
1209
- }
1210
- let isTouchDevice = false;
1211
- try {
1212
- isTouchDevice = "ontouchstart" in window || navigator.maxTouchPoints > 0;
1213
- } catch (error) {
1214
- isTouchDevice = false;
1215
- }
1216
- return isMobileUA || isSmallScreen && isTouchDevice;
1217
- }
1218
-
1219
1342
  // src/providers/embedded/index.ts
1220
1343
  var import_constants2 = require("@phantom/constants");
1221
1344
  var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvider {
@@ -1232,6 +1355,7 @@ var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvi
1232
1355
  const platform = {
1233
1356
  storage: new BrowserStorage(),
1234
1357
  authProvider: new BrowserAuthProvider(urlParamsAccessor),
1358
+ phantomAppProvider: new BrowserPhantomAppProvider(),
1235
1359
  urlParamsAccessor,
1236
1360
  stamper,
1237
1361
  name: platformName,
@@ -1244,7 +1368,7 @@ var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvi
1244
1368
  // Full user agent for more detailed info
1245
1369
  [import_constants2.ANALYTICS_HEADERS.APP_ID]: config.appId,
1246
1370
  [import_constants2.ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
1247
- [import_constants2.ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.14"
1371
+ [import_constants2.ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.16"
1248
1372
  // Replaced at build time
1249
1373
  }
1250
1374
  };
@@ -1257,6 +1381,25 @@ var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvi
1257
1381
 
1258
1382
  // src/ProviderManager.ts
1259
1383
  var import_constants3 = require("@phantom/constants");
1384
+
1385
+ // src/utils/auth-callback.ts
1386
+ function isAuthFailureCallback(searchParams) {
1387
+ if (typeof window === "undefined" && !searchParams)
1388
+ return false;
1389
+ const params = searchParams || new URLSearchParams(window.location.search);
1390
+ const responseType = params.get("response_type");
1391
+ const sessionId = params.get("session_id");
1392
+ return responseType === "failure" && !!sessionId;
1393
+ }
1394
+ function isAuthCallbackUrl(searchParams) {
1395
+ if (typeof window === "undefined" && !searchParams)
1396
+ return false;
1397
+ const params = searchParams || new URLSearchParams(window.location.search);
1398
+ const sessionId = params.get("session_id");
1399
+ return !!(sessionId && (params.has("response_type") || params.has("wallet_id")));
1400
+ }
1401
+
1402
+ // src/ProviderManager.ts
1260
1403
  var ProviderManager = class {
1261
1404
  // Track which providers have forwarding set up
1262
1405
  constructor(config) {
@@ -1322,24 +1465,53 @@ var ProviderManager = class {
1322
1465
  }
1323
1466
  /**
1324
1467
  * Connect using the current provider
1468
+ * Automatically switches provider based on authOptions.provider if specified
1325
1469
  */
1326
1470
  async connect(authOptions) {
1327
1471
  debug.info(DebugCategory.PROVIDER_MANAGER, "Starting connection", {
1328
1472
  currentProviderKey: this.currentProviderKey,
1329
1473
  authOptions: authOptions ? { provider: authOptions.provider, hasJwtToken: !!authOptions.jwtToken } : void 0
1330
1474
  });
1475
+ if (authOptions?.provider) {
1476
+ const requestedProvider = authOptions.provider;
1477
+ let targetProviderType = null;
1478
+ if (requestedProvider === "injected") {
1479
+ targetProviderType = "injected";
1480
+ } else if (["google", "apple", "jwt", "phantom"].includes(requestedProvider)) {
1481
+ targetProviderType = "embedded";
1482
+ }
1483
+ if (targetProviderType) {
1484
+ const currentInfo = this.getCurrentProviderInfo();
1485
+ if (currentInfo?.type !== targetProviderType) {
1486
+ debug.log(DebugCategory.PROVIDER_MANAGER, "Auto-switching provider based on auth options", {
1487
+ from: currentInfo?.type,
1488
+ to: targetProviderType,
1489
+ requestedProvider
1490
+ });
1491
+ const switchOptions = {};
1492
+ if (targetProviderType === "embedded") {
1493
+ switchOptions.embeddedWalletType = currentInfo?.embeddedWalletType || this.config.embeddedWalletType;
1494
+ }
1495
+ this.switchProvider(targetProviderType, switchOptions);
1496
+ }
1497
+ }
1498
+ }
1331
1499
  if (!this.currentProvider) {
1332
1500
  debug.error(DebugCategory.PROVIDER_MANAGER, "No provider selected");
1333
1501
  throw new Error("No provider selected");
1334
1502
  }
1335
1503
  debug.log(DebugCategory.PROVIDER_MANAGER, "Delegating to provider connect method");
1336
1504
  const result = await this.currentProvider.connect(authOptions);
1505
+ const providerInfo = this.getCurrentProviderInfo();
1506
+ result.providerType = providerInfo?.type;
1337
1507
  debug.log(DebugCategory.PROVIDER_MANAGER, "Connection successful, saving preferences", {
1338
- addressCount: result.addresses?.length || 0
1508
+ addressCount: result.addresses?.length || 0,
1509
+ providerType: result.providerType
1339
1510
  });
1340
1511
  this.saveProviderPreference();
1341
1512
  debug.info(DebugCategory.PROVIDER_MANAGER, "Connect completed", {
1342
- addresses: result.addresses
1513
+ addresses: result.addresses,
1514
+ providerType: result.providerType
1343
1515
  });
1344
1516
  return result;
1345
1517
  }
@@ -1373,6 +1545,10 @@ var ProviderManager = class {
1373
1545
  */
1374
1546
  async autoConnect() {
1375
1547
  debug.log(DebugCategory.PROVIDER_MANAGER, "Starting auto-connect with fallback strategy");
1548
+ if (isAuthFailureCallback()) {
1549
+ debug.warn(DebugCategory.PROVIDER_MANAGER, "Auth failure detected in URL, skipping autoConnect fallback");
1550
+ return false;
1551
+ }
1376
1552
  const embeddedWalletType = this.config.embeddedWalletType || "user-wallet";
1377
1553
  const embeddedKey = this.getProviderKey("embedded", embeddedWalletType);
1378
1554
  if (this.providers.has(embeddedKey)) {
@@ -1398,6 +1574,10 @@ var ProviderManager = class {
1398
1574
  debug.log(DebugCategory.PROVIDER_MANAGER, "Embedded auto-connect failed", {
1399
1575
  error: error.message
1400
1576
  });
1577
+ if (isAuthCallbackUrl()) {
1578
+ debug.log(DebugCategory.PROVIDER_MANAGER, "In auth callback URL, not attempting injected fallback");
1579
+ return false;
1580
+ }
1401
1581
  }
1402
1582
  }
1403
1583
  const injectedKey = this.getProviderKey("injected");
@@ -1515,7 +1695,11 @@ var ProviderManager = class {
1515
1695
  }
1516
1696
  debug.log(DebugCategory.PROVIDER_MANAGER, "Creating injected provider");
1517
1697
  this.createProvider("injected");
1518
- this.switchProvider(defaultType, { embeddedWalletType: defaultEmbeddedType });
1698
+ const switchOptions = {};
1699
+ if (defaultType === "embedded") {
1700
+ switchOptions.embeddedWalletType = defaultEmbeddedType;
1701
+ }
1702
+ this.switchProvider(defaultType, switchOptions);
1519
1703
  }
1520
1704
  /**
1521
1705
  * Create a provider instance
@@ -1575,35 +1759,17 @@ var ProviderManager = class {
1575
1759
  console.error("Failed to save provider preference:", error);
1576
1760
  }
1577
1761
  }
1578
- /**
1579
- * Restore provider preference from localStorage
1580
- */
1581
- /*
1582
- private restoreProviderPreference(): void {
1583
- try {
1584
- const saved = localStorage.getItem("phantom-provider-preference");
1585
- if (saved) {
1586
- const preference: ProviderPreference = JSON.parse(saved);
1587
- this.switchProvider(preference.type, {
1588
- embeddedWalletType: preference.embeddedWalletType,
1589
- });
1590
- }
1591
- } catch (error) {
1592
- // Ignore localStorage errors - just use default provider
1593
- console.error("Failed to restore provider preference:", error);
1594
- }
1595
- }*/
1596
1762
  };
1597
1763
 
1598
1764
  // src/waitForPhantomExtension.ts
1599
- var import_browser_injected_sdk2 = require("@phantom/browser-injected-sdk");
1765
+ var import_browser_injected_sdk3 = require("@phantom/browser-injected-sdk");
1600
1766
  async function waitForPhantomExtension(timeoutMs = 3e3) {
1601
1767
  return new Promise((resolve) => {
1602
1768
  const startTime = Date.now();
1603
1769
  const checkInterval = 100;
1604
1770
  const checkForExtension = () => {
1605
1771
  try {
1606
- if ((0, import_browser_injected_sdk2.isPhantomExtensionInstalled)()) {
1772
+ if ((0, import_browser_injected_sdk3.isPhantomExtensionInstalled)()) {
1607
1773
  resolve(true);
1608
1774
  return;
1609
1775
  }
@@ -1696,22 +1862,6 @@ var BrowserSDK = class {
1696
1862
  throw error;
1697
1863
  }
1698
1864
  }
1699
- /**
1700
- * Switch between provider types (injected vs embedded)
1701
- */
1702
- async switchProvider(type, options) {
1703
- debug.info(DebugCategory.BROWSER_SDK, "Switching provider", { type, options });
1704
- try {
1705
- await this.providerManager.switchProvider(type, options);
1706
- debug.info(DebugCategory.BROWSER_SDK, "Provider switch successful", { type });
1707
- } catch (error) {
1708
- debug.error(DebugCategory.BROWSER_SDK, "Provider switch failed", {
1709
- type,
1710
- error: error.message
1711
- });
1712
- throw error;
1713
- }
1714
- }
1715
1865
  // ===== STATE QUERIES =====
1716
1866
  /**
1717
1867
  * Check if the SDK is connected to a wallet
@@ -1921,6 +2071,49 @@ function getDeeplinkToPhantom(ref) {
1921
2071
  return `https://phantom.app/ul/browse/${currentUrl}${refParam}`;
1922
2072
  }
1923
2073
 
2074
+ // src/isPhantomLoginAvailable.ts
2075
+ var import_browser_injected_sdk4 = require("@phantom/browser-injected-sdk");
2076
+ async function isPhantomLoginAvailable(timeoutMs = 3e3) {
2077
+ const extensionInstalled = await waitForExtension(timeoutMs);
2078
+ if (!extensionInstalled) {
2079
+ return false;
2080
+ }
2081
+ try {
2082
+ if (!window.phantom?.app?.features || typeof window.phantom.app.features !== "function") {
2083
+ return false;
2084
+ }
2085
+ const features = await window.phantom.app.features();
2086
+ if (!Array.isArray(features)) {
2087
+ return false;
2088
+ }
2089
+ return features.includes("phantom_login");
2090
+ } catch (error) {
2091
+ return false;
2092
+ }
2093
+ }
2094
+ async function waitForExtension(timeoutMs) {
2095
+ return new Promise((resolve) => {
2096
+ const startTime = Date.now();
2097
+ const checkInterval = 100;
2098
+ const checkForExtension = () => {
2099
+ try {
2100
+ if ((0, import_browser_injected_sdk4.isPhantomExtensionInstalled)()) {
2101
+ resolve(true);
2102
+ return;
2103
+ }
2104
+ } catch (error) {
2105
+ }
2106
+ const elapsed = Date.now() - startTime;
2107
+ if (elapsed >= timeoutMs) {
2108
+ resolve(false);
2109
+ return;
2110
+ }
2111
+ setTimeout(checkForExtension, checkInterval);
2112
+ };
2113
+ checkForExtension();
2114
+ });
2115
+ }
2116
+
1924
2117
  // src/index.ts
1925
2118
  var import_constants5 = require("@phantom/constants");
1926
2119
  var import_client5 = require("@phantom/client");