@phantom/browser-sdk 1.0.0-beta.2 → 1.0.0-beta.21

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
@@ -22,22 +22,26 @@ var src_exports = {};
22
22
  __export(src_exports, {
23
23
  AddressType: () => import_client5.AddressType,
24
24
  BrowserSDK: () => BrowserSDK,
25
- DEFAULT_AUTH_URL: () => DEFAULT_AUTH_URL,
26
- DEFAULT_WALLET_API_URL: () => DEFAULT_WALLET_API_URL,
27
25
  DebugCategory: () => DebugCategory,
28
26
  DebugLevel: () => DebugLevel,
29
- NetworkId: () => import_constants2.NetworkId,
27
+ NetworkId: () => import_constants5.NetworkId,
30
28
  debug: () => debug,
31
29
  detectBrowser: () => detectBrowser,
32
30
  getBrowserDisplayName: () => getBrowserDisplayName,
31
+ getDeeplinkToPhantom: () => getDeeplinkToPhantom,
33
32
  getPlatformName: () => getPlatformName,
33
+ isMobileDevice: () => isMobileDevice,
34
+ isPhantomLoginAvailable: () => isPhantomLoginAvailable,
34
35
  parseBrowserFromUserAgent: () => parseBrowserFromUserAgent,
35
36
  waitForPhantomExtension: () => waitForPhantomExtension
36
37
  });
37
38
  module.exports = __toCommonJS(src_exports);
38
39
 
40
+ // src/types.ts
41
+ var import_client = require("@phantom/client");
42
+
39
43
  // src/providers/injected/index.ts
40
- var import_client3 = require("@phantom/client");
44
+ var import_client4 = require("@phantom/client");
41
45
  var import_browser_injected_sdk = require("@phantom/browser-injected-sdk");
42
46
  var import_solana = require("@phantom/browser-injected-sdk/solana");
43
47
  var import_ethereum = require("@phantom/browser-injected-sdk/ethereum");
@@ -119,7 +123,7 @@ var DebugCategory = {
119
123
 
120
124
  // src/providers/injected/chains/SolanaChain.ts
121
125
  var import_eventemitter3 = require("eventemitter3");
122
- var import_client = require("@phantom/client");
126
+ var import_client2 = require("@phantom/client");
123
127
  var import_buffer = require("buffer");
124
128
  var InjectedSolanaChain = class {
125
129
  constructor(phantom, callbacks) {
@@ -144,7 +148,7 @@ var InjectedSolanaChain = class {
144
148
  return Promise.reject(new Error("Provider not connected. Call provider connect first."));
145
149
  }
146
150
  const addresses = this.callbacks.getAddresses();
147
- const solanaAddress = addresses.find((addr) => addr.addressType === import_client.AddressType.solana);
151
+ const solanaAddress = addresses.find((addr) => addr.addressType === import_client2.AddressType.solana);
148
152
  if (!solanaAddress) {
149
153
  return Promise.reject(new Error("Solana not enabled for this provider"));
150
154
  }
@@ -178,8 +182,27 @@ var InjectedSolanaChain = class {
178
182
  const result = await this.phantom.solana.signAndSendTransaction(transaction);
179
183
  return { signature: result.signature };
180
184
  }
181
- signAllTransactions(_transactions) {
182
- return Promise.reject(new Error("Sign-only transactions not supported by injected provider"));
185
+ async signAllTransactions(transactions) {
186
+ if (!this.callbacks.isConnected()) {
187
+ return Promise.reject(new Error("Provider not connected. Call provider connect first."));
188
+ }
189
+ try {
190
+ const result = await this.phantom.solana.signAllTransactions(transactions);
191
+ return result;
192
+ } catch (error) {
193
+ return Promise.reject(error);
194
+ }
195
+ }
196
+ async signAndSendAllTransactions(transactions) {
197
+ if (!this.callbacks.isConnected()) {
198
+ return Promise.reject(new Error("Provider not connected. Call provider connect first."));
199
+ }
200
+ try {
201
+ const result = await this.phantom.solana.signAndSendAllTransactions(transactions);
202
+ return { signatures: result.signatures };
203
+ } catch (error) {
204
+ return Promise.reject(error);
205
+ }
183
206
  }
184
207
  switchNetwork(_network) {
185
208
  return Promise.resolve();
@@ -205,7 +228,7 @@ var InjectedSolanaChain = class {
205
228
  this.eventEmitter.emit("accountChanged", publicKey);
206
229
  });
207
230
  this.callbacks.on("connect", (data) => {
208
- const solanaAddress = data.addresses?.find((addr) => addr.addressType === import_client.AddressType.solana);
231
+ const solanaAddress = data.addresses?.find((addr) => addr.addressType === import_client2.AddressType.solana);
209
232
  if (solanaAddress) {
210
233
  this.updateConnectionState(true, solanaAddress.address);
211
234
  }
@@ -216,7 +239,7 @@ var InjectedSolanaChain = class {
216
239
  }
217
240
  syncInitialState() {
218
241
  if (this.callbacks.isConnected()) {
219
- const solanaAddress = this.callbacks.getAddresses().find((addr) => addr.addressType === import_client.AddressType.solana);
242
+ const solanaAddress = this.callbacks.getAddresses().find((addr) => addr.addressType === import_client2.AddressType.solana);
220
243
  if (solanaAddress) {
221
244
  this.updateConnectionState(true, solanaAddress.address);
222
245
  }
@@ -237,7 +260,7 @@ var InjectedSolanaChain = class {
237
260
 
238
261
  // src/providers/injected/chains/EthereumChain.ts
239
262
  var import_eventemitter32 = require("eventemitter3");
240
- var import_client2 = require("@phantom/client");
263
+ var import_client3 = require("@phantom/client");
241
264
  var InjectedEthereumChain = class {
242
265
  constructor(phantom, callbacks) {
243
266
  this._connected = false;
@@ -275,7 +298,7 @@ var InjectedEthereumChain = class {
275
298
  return Promise.reject(new Error("Provider not connected. Call provider connect first."));
276
299
  }
277
300
  const addresses = this.callbacks.getAddresses();
278
- const ethAddresses = addresses.filter((addr) => addr.addressType === import_client2.AddressType.ethereum).map((addr) => addr.address);
301
+ const ethAddresses = addresses.filter((addr) => addr.addressType === import_client3.AddressType.ethereum).map((addr) => addr.address);
279
302
  this.updateConnectionState(true, ethAddresses);
280
303
  return Promise.resolve(ethAddresses);
281
304
  }
@@ -296,8 +319,9 @@ var InjectedEthereumChain = class {
296
319
  return await this.phantom.ethereum.sendTransaction(transaction);
297
320
  }
298
321
  async switchChain(chainId) {
299
- await this.phantom.ethereum.switchChain(`0x${chainId.toString(16)}`);
300
- this._chainId = `0x${chainId.toString(16)}`;
322
+ const hexChainId = typeof chainId === "string" ? chainId.toLowerCase().startsWith("0x") ? chainId : `0x${parseInt(chainId, 10).toString(16)}` : `0x${chainId.toString(16)}`;
323
+ await this.phantom.ethereum.switchChain(hexChainId);
324
+ this._chainId = hexChainId;
301
325
  this.eventEmitter.emit("chainChanged", this._chainId);
302
326
  }
303
327
  async getChainId() {
@@ -330,7 +354,7 @@ var InjectedEthereumChain = class {
330
354
  this.eventEmitter.emit("chainChanged", chainId);
331
355
  });
332
356
  this.callbacks.on("connect", (data) => {
333
- const ethAddresses = data.addresses?.filter((addr) => addr.addressType === import_client2.AddressType.ethereum)?.map((addr) => addr.address) || [];
357
+ const ethAddresses = data.addresses?.filter((addr) => addr.addressType === import_client3.AddressType.ethereum)?.map((addr) => addr.address) || [];
334
358
  if (ethAddresses.length > 0) {
335
359
  this.updateConnectionState(true, ethAddresses);
336
360
  }
@@ -341,7 +365,7 @@ var InjectedEthereumChain = class {
341
365
  }
342
366
  syncInitialState() {
343
367
  if (this.callbacks.isConnected()) {
344
- const ethAddresses = this.callbacks.getAddresses().filter((addr) => addr.addressType === import_client2.AddressType.ethereum).map((addr) => addr.address);
368
+ const ethAddresses = this.callbacks.getAddresses().filter((addr) => addr.addressType === import_client3.AddressType.ethereum).map((addr) => addr.address);
345
369
  if (ethAddresses.length > 0) {
346
370
  this.updateConnectionState(true, ethAddresses);
347
371
  }
@@ -361,6 +385,8 @@ var InjectedEthereumChain = class {
361
385
  };
362
386
 
363
387
  // src/providers/injected/index.ts
388
+ var MANUAL_DISCONNECT_KEY = "phantom-injected-manual-disconnect";
389
+ var MANUAL_DISCONNECT_VALUE = "true";
364
390
  var InjectedProvider = class {
365
391
  constructor(config) {
366
392
  this.connected = false;
@@ -373,11 +399,11 @@ var InjectedProvider = class {
373
399
  this.addressTypes = config.addressTypes;
374
400
  debug.log(DebugCategory.INJECTED_PROVIDER, "Address types configured", { addressTypes: this.addressTypes });
375
401
  const plugins = [(0, import_browser_injected_sdk.createExtensionPlugin)()];
376
- if (this.addressTypes.includes(import_client3.AddressType.solana)) {
402
+ if (this.addressTypes.includes(import_client4.AddressType.solana)) {
377
403
  plugins.push((0, import_solana.createSolanaPlugin)());
378
404
  debug.log(DebugCategory.INJECTED_PROVIDER, "Solana plugin added");
379
405
  }
380
- if (this.addressTypes.includes(import_client3.AddressType.ethereum)) {
406
+ if (this.addressTypes.includes(import_client4.AddressType.ethereum)) {
381
407
  plugins.push((0, import_ethereum.createEthereumPlugin)());
382
408
  debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum plugin added");
383
409
  }
@@ -388,10 +414,10 @@ var InjectedProvider = class {
388
414
  });
389
415
  this.phantom = (0, import_browser_injected_sdk.createPhantom)({ plugins });
390
416
  const callbacks = this.createCallbacks();
391
- if (this.addressTypes.includes(import_client3.AddressType.solana)) {
417
+ if (this.addressTypes.includes(import_client4.AddressType.solana)) {
392
418
  this._solanaChain = new InjectedSolanaChain(this.phantom, callbacks);
393
419
  }
394
- if (this.addressTypes.includes(import_client3.AddressType.ethereum)) {
420
+ if (this.addressTypes.includes(import_client4.AddressType.ethereum)) {
395
421
  this._ethereumChain = new InjectedEthereumChain(this.phantom, callbacks);
396
422
  }
397
423
  debug.info(DebugCategory.INJECTED_PROVIDER, "InjectedProvider initialized");
@@ -400,7 +426,7 @@ var InjectedProvider = class {
400
426
  * Access to Solana chain operations
401
427
  */
402
428
  get solana() {
403
- if (!this.addressTypes.includes(import_client3.AddressType.solana)) {
429
+ if (!this.addressTypes.includes(import_client4.AddressType.solana)) {
404
430
  throw new Error("Solana not enabled for this provider");
405
431
  }
406
432
  if (!this._solanaChain) {
@@ -412,7 +438,7 @@ var InjectedProvider = class {
412
438
  * Access to Ethereum chain operations
413
439
  */
414
440
  get ethereum() {
415
- if (!this.addressTypes.includes(import_client3.AddressType.ethereum)) {
441
+ if (!this.addressTypes.includes(import_client4.AddressType.ethereum)) {
416
442
  throw new Error("Ethereum not enabled for this provider");
417
443
  }
418
444
  if (!this._ethereumChain) {
@@ -423,9 +449,11 @@ var InjectedProvider = class {
423
449
  async connect(authOptions) {
424
450
  debug.info(DebugCategory.INJECTED_PROVIDER, "Starting injected provider connect", {
425
451
  addressTypes: this.addressTypes,
426
- authOptionsIgnored: !!authOptions
427
- // Note: authOptions are ignored for injected provider
452
+ provider: authOptions.provider
428
453
  });
454
+ if (authOptions.provider !== "injected") {
455
+ throw new Error(`Invalid provider for injected connection: ${authOptions.provider}. Must be "injected"`);
456
+ }
429
457
  this.emit("connect_start", {
430
458
  source: "manual-connect",
431
459
  providerType: "injected"
@@ -442,35 +470,45 @@ var InjectedProvider = class {
442
470
  }
443
471
  debug.log(DebugCategory.INJECTED_PROVIDER, "Phantom extension detected");
444
472
  const connectedAddresses = [];
445
- if (this.addressTypes.includes(import_client3.AddressType.solana)) {
473
+ if (this.addressTypes.includes(import_client4.AddressType.solana)) {
446
474
  debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting Solana connection");
447
475
  try {
448
476
  const publicKey = await this.phantom.solana.connect();
449
477
  if (publicKey) {
450
478
  connectedAddresses.push({
451
- addressType: import_client3.AddressType.solana,
479
+ addressType: import_client4.AddressType.solana,
452
480
  address: publicKey
453
481
  });
454
482
  debug.info(DebugCategory.INJECTED_PROVIDER, "Solana connected successfully", { address: publicKey });
455
483
  }
456
484
  } catch (err) {
457
- debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Solana", { error: err });
485
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Solana, stopping", { error: err });
486
+ this.emit("connect_error", {
487
+ error: err instanceof Error ? err.message : "Failed to connect",
488
+ source: "manual-connect"
489
+ });
490
+ throw err;
458
491
  }
459
492
  }
460
- if (this.addressTypes.includes(import_client3.AddressType.ethereum)) {
493
+ if (this.addressTypes.includes(import_client4.AddressType.ethereum)) {
461
494
  try {
462
495
  const accounts = await this.phantom.ethereum.connect();
463
496
  if (accounts && accounts.length > 0) {
464
497
  connectedAddresses.push(
465
498
  ...accounts.map((address) => ({
466
- addressType: import_client3.AddressType.ethereum,
499
+ addressType: import_client4.AddressType.ethereum,
467
500
  address
468
501
  }))
469
502
  );
470
503
  debug.info(DebugCategory.INJECTED_PROVIDER, "Ethereum connected successfully", { addresses: accounts });
471
504
  }
472
505
  } catch (err) {
473
- debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Ethereum", { error: err });
506
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Ethereum, stopping", { error: err });
507
+ this.emit("connect_error", {
508
+ error: err instanceof Error ? err.message : "Failed to connect",
509
+ source: "manual-connect"
510
+ });
511
+ throw err;
474
512
  }
475
513
  }
476
514
  if (connectedAddresses.length === 0) {
@@ -483,14 +521,22 @@ var InjectedProvider = class {
483
521
  }
484
522
  this.addresses = connectedAddresses;
485
523
  this.connected = true;
524
+ const authUserId = await this.getAuthUserId("manual-connect");
525
+ try {
526
+ localStorage.removeItem(MANUAL_DISCONNECT_KEY);
527
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Cleared manual disconnect flag - auto-reconnect enabled");
528
+ } catch (error) {
529
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to clear manual disconnect flag", { error });
530
+ }
486
531
  const result = {
487
532
  addresses: this.addresses,
488
- status: "completed"
489
- // walletId is not applicable for injected providers
533
+ status: "completed",
534
+ authUserId
490
535
  };
491
536
  this.emit("connect", {
492
537
  addresses: this.addresses,
493
- source: "manual-connect"
538
+ source: "manual-connect",
539
+ authUserId
494
540
  });
495
541
  return result;
496
542
  } catch (error) {
@@ -505,7 +551,7 @@ var InjectedProvider = class {
505
551
  }
506
552
  async disconnect() {
507
553
  debug.info(DebugCategory.INJECTED_PROVIDER, "Starting injected provider disconnect");
508
- if (this.addressTypes.includes(import_client3.AddressType.solana)) {
554
+ if (this.addressTypes.includes(import_client4.AddressType.solana)) {
509
555
  try {
510
556
  await this.phantom.solana.disconnect();
511
557
  debug.log(DebugCategory.INJECTED_PROVIDER, "Solana disconnected successfully");
@@ -513,18 +559,117 @@ var InjectedProvider = class {
513
559
  debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to disconnect Solana", { error: err });
514
560
  }
515
561
  }
516
- if (this.addressTypes.includes(import_client3.AddressType.ethereum)) {
562
+ if (this.addressTypes.includes(import_client4.AddressType.ethereum)) {
517
563
  debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum disconnected (no-op)");
518
564
  }
519
565
  this.browserInjectedCleanupFunctions.forEach((cleanup) => cleanup());
520
566
  this.browserInjectedCleanupFunctions = [];
521
567
  this.connected = false;
522
568
  this.addresses = [];
569
+ try {
570
+ localStorage.setItem(MANUAL_DISCONNECT_KEY, MANUAL_DISCONNECT_VALUE);
571
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Set manual disconnect flag to prevent auto-reconnect");
572
+ } catch (error) {
573
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to set manual disconnect flag", { error });
574
+ }
523
575
  this.emit("disconnect", {
524
576
  source: "manual-disconnect"
525
577
  });
526
578
  debug.info(DebugCategory.INJECTED_PROVIDER, "Injected provider disconnected successfully");
527
579
  }
580
+ /**
581
+ * Attempt auto-connection using onlyIfTrusted parameter
582
+ * This will only connect if the dApp is already trusted by the user
583
+ * Should be called after setting up event listeners
584
+ */
585
+ async autoConnect() {
586
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting auto-connect with onlyIfTrusted=true");
587
+ try {
588
+ const manualDisconnect = localStorage.getItem(MANUAL_DISCONNECT_KEY);
589
+ if (manualDisconnect === MANUAL_DISCONNECT_VALUE) {
590
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Skipping auto-connect: user previously disconnected manually");
591
+ return;
592
+ }
593
+ } catch (error) {
594
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to check manual disconnect flag", { error });
595
+ }
596
+ this.emit("connect_start", {
597
+ source: "auto-connect",
598
+ providerType: "injected"
599
+ });
600
+ try {
601
+ if (!this.phantom.extension?.isInstalled?.()) {
602
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Phantom wallet extension not found for auto-connect");
603
+ this.emit("connect_error", {
604
+ error: "Phantom wallet not found",
605
+ source: "auto-connect"
606
+ });
607
+ return;
608
+ }
609
+ const connectedAddresses = [];
610
+ if (this.addressTypes.includes(import_client4.AddressType.solana)) {
611
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting Solana auto-connect");
612
+ try {
613
+ const publicKey = await this.phantom.solana.connect({ onlyIfTrusted: true });
614
+ if (publicKey) {
615
+ connectedAddresses.push({
616
+ addressType: import_client4.AddressType.solana,
617
+ address: publicKey
618
+ });
619
+ debug.info(DebugCategory.INJECTED_PROVIDER, "Solana auto-connected successfully", { address: publicKey });
620
+ }
621
+ } catch (err) {
622
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Solana auto-connect failed (expected if not trusted)", { error: err });
623
+ }
624
+ }
625
+ if (this.addressTypes.includes(import_client4.AddressType.ethereum)) {
626
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting Ethereum auto-connect");
627
+ try {
628
+ const accounts = await this.phantom.ethereum.connect({ onlyIfTrusted: true });
629
+ if (accounts && accounts.length > 0) {
630
+ connectedAddresses.push(
631
+ ...accounts.map((address) => ({
632
+ addressType: import_client4.AddressType.ethereum,
633
+ address
634
+ }))
635
+ );
636
+ debug.info(DebugCategory.INJECTED_PROVIDER, "Ethereum auto-connected successfully", { addresses: accounts });
637
+ }
638
+ } catch (err) {
639
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum auto-connect failed (expected if not trusted)", { error: err });
640
+ }
641
+ }
642
+ if (connectedAddresses.length === 0) {
643
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Auto-connect failed: no trusted connections available");
644
+ this.emit("connect_error", {
645
+ error: "No trusted connections available",
646
+ source: "auto-connect"
647
+ });
648
+ return;
649
+ }
650
+ this.addresses = connectedAddresses;
651
+ this.connected = true;
652
+ const authUserId = await this.getAuthUserId("auto-connect");
653
+ this.emit("connect", {
654
+ addresses: this.addresses,
655
+ source: "auto-connect",
656
+ authUserId
657
+ });
658
+ debug.info(DebugCategory.INJECTED_PROVIDER, "Auto-connect successful", {
659
+ addressCount: connectedAddresses.length,
660
+ addresses: connectedAddresses.map((addr) => ({ type: addr.addressType, address: addr.address.substring(0, 8) + "..." })),
661
+ authUserId
662
+ });
663
+ } catch (error) {
664
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Auto-connect failed with error", {
665
+ error: error instanceof Error ? error.message : String(error)
666
+ });
667
+ this.emit("connect_error", {
668
+ error: error instanceof Error ? error.message : "Auto-connect failed",
669
+ source: "auto-connect"
670
+ });
671
+ }
672
+ }
528
673
  getAddresses() {
529
674
  return this.addresses;
530
675
  }
@@ -548,6 +693,27 @@ var InjectedProvider = class {
548
693
  debug.log(DebugCategory.INJECTED_PROVIDER, "Getting supported autoConfirm chains");
549
694
  return await this.phantom.autoConfirm.autoConfirmSupportedChains();
550
695
  }
696
+ /**
697
+ * Helper method to get authUserId from window.phantom.app.getUser()
698
+ * Returns undefined if the method is not available or fails
699
+ */
700
+ async getAuthUserId(context) {
701
+ try {
702
+ if (window.phantom?.app?.getUser) {
703
+ const userInfo = await window.phantom.app.getUser();
704
+ const authUserId = userInfo?.authUserId;
705
+ if (authUserId) {
706
+ debug.log(DebugCategory.INJECTED_PROVIDER, `Retrieved authUserId from window.phantom.app.getUser() during ${context}`, {
707
+ authUserId
708
+ });
709
+ }
710
+ return authUserId;
711
+ }
712
+ } catch (error) {
713
+ debug.log(DebugCategory.INJECTED_PROVIDER, `Failed to get user info during ${context} (method may not be supported)`, { error });
714
+ }
715
+ return void 0;
716
+ }
551
717
  // Event management methods - implementing unified event interface
552
718
  on(event, callback) {
553
719
  debug.log(DebugCategory.INJECTED_PROVIDER, "Adding event listener", { event });
@@ -588,98 +754,108 @@ var InjectedProvider = class {
588
754
  }
589
755
  setupBrowserInjectedEvents() {
590
756
  debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up browser-injected-sdk event listeners");
591
- if (this.addressTypes.includes(import_client3.AddressType.solana)) {
757
+ if (this.addressTypes.includes(import_client4.AddressType.solana)) {
592
758
  this.setupSolanaEvents();
593
759
  }
594
- if (this.addressTypes.includes(import_client3.AddressType.ethereum)) {
760
+ if (this.addressTypes.includes(import_client4.AddressType.ethereum)) {
595
761
  this.setupEthereumEvents();
596
762
  }
597
763
  }
598
764
  setupSolanaEvents() {
599
765
  debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up Solana event listeners");
600
- const handleSolanaConnect = (publicKey) => {
766
+ const handleSolanaConnect = async (publicKey) => {
601
767
  debug.log(DebugCategory.INJECTED_PROVIDER, "Solana connect event received", { publicKey });
602
- const solanaAddress = { addressType: import_client3.AddressType.solana, address: publicKey };
603
- if (!this.addresses.find((addr) => addr.addressType === import_client3.AddressType.solana)) {
768
+ const solanaAddress = { addressType: import_client4.AddressType.solana, address: publicKey };
769
+ if (!this.addresses.find((addr) => addr.addressType === import_client4.AddressType.solana)) {
604
770
  this.addresses.push(solanaAddress);
605
771
  }
606
772
  this.connected = true;
773
+ const authUserId = await this.getAuthUserId("Solana connect event");
607
774
  this.emit("connect", {
608
775
  addresses: this.addresses,
609
- source: "injected-extension"
776
+ source: "injected-extension",
777
+ authUserId
610
778
  });
611
779
  };
612
780
  const handleSolanaDisconnect = () => {
613
781
  debug.log(DebugCategory.INJECTED_PROVIDER, "Solana disconnect event received");
614
- this.addresses = this.addresses.filter((addr) => addr.addressType !== import_client3.AddressType.solana);
615
- this.connected = this.addresses.length > 0;
782
+ this.addresses = this.addresses.filter((addr) => addr.addressType !== import_client4.AddressType.solana);
783
+ this.connected = false;
616
784
  this.emit("disconnect", {
617
785
  source: "injected-extension"
618
786
  });
619
787
  };
620
- const handleSolanaAccountChanged = (publicKey) => {
788
+ const handleSolanaAccountChanged = async (publicKey) => {
621
789
  debug.log(DebugCategory.INJECTED_PROVIDER, "Solana account changed event received", { publicKey });
622
- const solanaIndex = this.addresses.findIndex((addr) => addr.addressType === import_client3.AddressType.solana);
790
+ const solanaIndex = this.addresses.findIndex((addr) => addr.addressType === import_client4.AddressType.solana);
623
791
  if (solanaIndex >= 0) {
624
- this.addresses[solanaIndex] = { addressType: import_client3.AddressType.solana, address: publicKey };
792
+ this.addresses[solanaIndex] = { addressType: import_client4.AddressType.solana, address: publicKey };
625
793
  } else {
626
- this.addresses.push({ addressType: import_client3.AddressType.solana, address: publicKey });
794
+ this.addresses.push({ addressType: import_client4.AddressType.solana, address: publicKey });
627
795
  }
796
+ const authUserId = await this.getAuthUserId("Solana account changed event");
628
797
  this.emit("connect", {
629
798
  addresses: this.addresses,
630
- source: "injected-extension-account-change"
799
+ source: "injected-extension-account-change",
800
+ authUserId
631
801
  });
632
802
  };
633
803
  const cleanupConnect = this.phantom.solana.addEventListener("connect", handleSolanaConnect);
634
804
  const cleanupDisconnect = this.phantom.solana.addEventListener("disconnect", handleSolanaDisconnect);
635
- const cleanupAccountChanged = this.phantom.solana.addEventListener(
636
- "accountChanged",
637
- handleSolanaAccountChanged
638
- );
805
+ const cleanupAccountChanged = this.phantom.solana.addEventListener("accountChanged", handleSolanaAccountChanged);
639
806
  this.browserInjectedCleanupFunctions.push(cleanupConnect, cleanupDisconnect, cleanupAccountChanged);
640
807
  }
641
808
  setupEthereumEvents() {
642
809
  debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up Ethereum event listeners");
643
- const handleEthereumConnect = (accounts) => {
810
+ const handleEthereumConnect = async (accounts) => {
644
811
  debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum connect event received", { accounts });
645
- this.addresses = this.addresses.filter((addr) => addr.addressType !== import_client3.AddressType.ethereum);
812
+ this.addresses = this.addresses.filter((addr) => addr.addressType !== import_client4.AddressType.ethereum);
646
813
  if (accounts && accounts.length > 0) {
647
814
  this.addresses.push(
648
815
  ...accounts.map((address) => ({
649
- addressType: import_client3.AddressType.ethereum,
816
+ addressType: import_client4.AddressType.ethereum,
650
817
  address
651
818
  }))
652
819
  );
653
820
  }
654
821
  this.connected = this.addresses.length > 0;
822
+ const authUserId = await this.getAuthUserId("Ethereum connect event");
655
823
  this.emit("connect", {
656
824
  addresses: this.addresses,
657
- source: "injected-extension"
825
+ source: "injected-extension",
826
+ authUserId
658
827
  });
659
828
  };
660
829
  const handleEthereumDisconnect = () => {
661
830
  debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum disconnect event received");
662
- this.addresses = this.addresses.filter((addr) => addr.addressType !== import_client3.AddressType.ethereum);
663
- this.connected = this.addresses.length > 0;
831
+ this.addresses = this.addresses.filter((addr) => addr.addressType !== import_client4.AddressType.ethereum);
832
+ this.connected = false;
664
833
  this.emit("disconnect", {
665
834
  source: "injected-extension"
666
835
  });
667
836
  };
668
- const handleEthereumAccountsChanged = (accounts) => {
837
+ const handleEthereumAccountsChanged = async (accounts) => {
669
838
  debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum accounts changed event received", { accounts });
670
- this.addresses = this.addresses.filter((addr) => addr.addressType !== import_client3.AddressType.ethereum);
839
+ this.addresses = this.addresses.filter((addr) => addr.addressType !== import_client4.AddressType.ethereum);
671
840
  if (accounts && accounts.length > 0) {
672
841
  this.addresses.push(
673
842
  ...accounts.map((address) => ({
674
- addressType: import_client3.AddressType.ethereum,
843
+ addressType: import_client4.AddressType.ethereum,
675
844
  address
676
845
  }))
677
846
  );
847
+ const authUserId = await this.getAuthUserId("Ethereum accounts changed event");
848
+ this.emit("connect", {
849
+ addresses: this.addresses,
850
+ source: "injected-extension-account-change",
851
+ authUserId
852
+ });
853
+ } else {
854
+ this.connected = false;
855
+ this.emit("disconnect", {
856
+ source: "injected-extension-account-change"
857
+ });
678
858
  }
679
- this.emit("connect", {
680
- addresses: this.addresses,
681
- source: "injected-extension-account-change"
682
- });
683
859
  };
684
860
  const cleanupConnect = this.phantom.ethereum.addEventListener("connect", handleEthereumConnect);
685
861
  const cleanupDisconnect = this.phantom.ethereum.addEventListener("disconnect", handleEthereumDisconnect);
@@ -692,7 +868,7 @@ var InjectedProvider = class {
692
868
  createCallbacks() {
693
869
  return {
694
870
  connect: async () => {
695
- const result = await this.connect();
871
+ const result = await this.connect({ provider: "injected" });
696
872
  return result.addresses;
697
873
  },
698
874
  disconnect: async () => {
@@ -797,6 +973,47 @@ var BrowserStorage = class {
797
973
  };
798
974
  });
799
975
  }
976
+ async getShouldClearPreviousSession() {
977
+ debug.log(DebugCategory.STORAGE, "Getting shouldClearPreviousSession flag from IndexedDB");
978
+ const db = await this.getDB();
979
+ return new Promise((resolve, reject) => {
980
+ const transaction = db.transaction([this.storeName], "readonly");
981
+ const store = transaction.objectStore(this.storeName);
982
+ const request = store.get("shouldClearPreviousSession");
983
+ request.onsuccess = () => {
984
+ const shouldClear = request.result ?? false;
985
+ debug.log(DebugCategory.STORAGE, "Retrieved shouldClearPreviousSession flag from IndexedDB", {
986
+ shouldClear
987
+ });
988
+ resolve(shouldClear);
989
+ };
990
+ request.onerror = () => {
991
+ debug.error(DebugCategory.STORAGE, "Failed to get shouldClearPreviousSession flag from IndexedDB", {
992
+ error: request.error
993
+ });
994
+ reject(request.error);
995
+ };
996
+ });
997
+ }
998
+ async setShouldClearPreviousSession(should) {
999
+ debug.log(DebugCategory.STORAGE, "Setting shouldClearPreviousSession flag in IndexedDB", { should });
1000
+ const db = await this.getDB();
1001
+ return new Promise((resolve, reject) => {
1002
+ const transaction = db.transaction([this.storeName], "readwrite");
1003
+ const store = transaction.objectStore(this.storeName);
1004
+ const request = store.put(should, "shouldClearPreviousSession");
1005
+ request.onsuccess = () => {
1006
+ debug.log(DebugCategory.STORAGE, "Successfully set shouldClearPreviousSession flag in IndexedDB");
1007
+ resolve();
1008
+ };
1009
+ request.onerror = () => {
1010
+ debug.error(DebugCategory.STORAGE, "Failed to set shouldClearPreviousSession flag in IndexedDB", {
1011
+ error: request.error
1012
+ });
1013
+ reject(request.error);
1014
+ };
1015
+ });
1016
+ }
800
1017
  };
801
1018
 
802
1019
  // src/providers/embedded/adapters/url-params.ts
@@ -808,15 +1025,160 @@ var BrowserURLParamsAccessor = class {
808
1025
  };
809
1026
  var browserUrlParamsAccessor = new BrowserURLParamsAccessor();
810
1027
 
811
- // src/constants.ts
812
- var DEFAULT_AUTH_URL = "https://connect.phantom.app";
813
- var DEFAULT_WALLET_API_URL = "https://api.phantom.app/v1/wallets";
1028
+ // src/providers/embedded/adapters/auth.ts
1029
+ var import_constants = require("@phantom/constants");
1030
+
1031
+ // src/utils/browser-detection.ts
1032
+ function parseBrowserFromUserAgent(userAgent, hasBraveAPI) {
1033
+ let name = "unknown";
1034
+ let version = "unknown";
1035
+ if (!userAgent || typeof userAgent !== "string") {
1036
+ return { name, version, userAgent: "unknown" };
1037
+ }
1038
+ try {
1039
+ if (userAgent.includes("Edg/")) {
1040
+ name = "edge";
1041
+ const match = userAgent.match(/Edg\/([0-9]+(?:\.[0-9]+)*)/);
1042
+ if (match)
1043
+ version = match[1].split(".")[0];
1044
+ } else if (userAgent.includes("OPR/") || userAgent.includes("Opera/")) {
1045
+ name = "opera";
1046
+ const match = userAgent.match(/(?:OPR|Opera)\/([0-9]+(?:\.[0-9]+)*)/);
1047
+ if (match)
1048
+ version = match[1].split(".")[0];
1049
+ } else if (userAgent.includes("SamsungBrowser/")) {
1050
+ name = "samsung";
1051
+ const match = userAgent.match(/SamsungBrowser\/([0-9]+(?:\.[0-9]+)*)/);
1052
+ if (match)
1053
+ version = match[1].split(".")[0];
1054
+ } else if (userAgent.includes("DuckDuckGo/")) {
1055
+ name = "duckduckgo";
1056
+ const match = userAgent.match(/DuckDuckGo\/([0-9]+(?:\.[0-9]+)*)/);
1057
+ if (match)
1058
+ version = match[1].split(".")[0];
1059
+ } else if (userAgent.includes("Chrome/") && hasBraveAPI) {
1060
+ name = "brave";
1061
+ const match = userAgent.match(/Chrome\/([0-9]+(?:\.[0-9]+)*)/);
1062
+ if (match)
1063
+ version = match[1].split(".")[0];
1064
+ } else if (userAgent.includes("Mobile/") || userAgent.includes("Android")) {
1065
+ if (userAgent.includes("Chrome/")) {
1066
+ name = "chrome-mobile";
1067
+ const match = userAgent.match(/Chrome\/([0-9]+(?:\.[0-9]+)*)/);
1068
+ if (match)
1069
+ version = match[1].split(".")[0];
1070
+ } else if (userAgent.includes("Firefox/")) {
1071
+ name = "firefox-mobile";
1072
+ const match = userAgent.match(/Firefox\/([0-9]+(?:\.[0-9]+)*)/);
1073
+ if (match)
1074
+ version = match[1].split(".")[0];
1075
+ } else if (userAgent.includes("Safari/") && userAgent.includes("Mobile/")) {
1076
+ name = "safari-mobile";
1077
+ const match = userAgent.match(/Version\/([0-9]+(?:\.[0-9]+)*)/);
1078
+ if (match)
1079
+ version = match[1].split(".")[0];
1080
+ } else {
1081
+ name = "mobile";
1082
+ }
1083
+ } else if (userAgent.includes("Chrome/")) {
1084
+ name = "chrome";
1085
+ const match = userAgent.match(/Chrome\/([0-9]+(?:\.[0-9]+)*)/);
1086
+ if (match)
1087
+ version = match[1].split(".")[0];
1088
+ } else if (userAgent.includes("Firefox/")) {
1089
+ name = "firefox";
1090
+ const match = userAgent.match(/Firefox\/([0-9]+(?:\.[0-9]+)*)/);
1091
+ if (match)
1092
+ version = match[1].split(".")[0];
1093
+ } else if (userAgent.includes("Safari/") && !userAgent.includes("Chrome/")) {
1094
+ name = "safari";
1095
+ const match = userAgent.match(/Version\/([0-9]+(?:\.[0-9]+)*)/);
1096
+ if (match)
1097
+ version = match[1].split(".")[0];
1098
+ }
1099
+ if (name === "unknown") {
1100
+ const patterns = [
1101
+ { regex: /Chrome\/([0-9]+)/, name: "chrome" },
1102
+ { regex: /Firefox\/([0-9]+)/, name: "firefox" },
1103
+ { regex: /Safari\/([0-9]+)/, name: "safari" },
1104
+ { regex: /Edge\/([0-9]+)/, name: "edge" },
1105
+ { regex: /Opera\/([0-9]+)/, name: "opera" }
1106
+ ];
1107
+ for (const pattern of patterns) {
1108
+ const match = userAgent.match(pattern.regex);
1109
+ if (match) {
1110
+ name = pattern.name;
1111
+ version = match[1];
1112
+ break;
1113
+ }
1114
+ }
1115
+ }
1116
+ } catch (error) {
1117
+ }
1118
+ return { name, version, userAgent };
1119
+ }
1120
+ function detectBrowser() {
1121
+ if (typeof window === "undefined" || !window.navigator?.userAgent) {
1122
+ return { name: "unknown", version: "unknown", userAgent: "unknown" };
1123
+ }
1124
+ const userAgent = window.navigator.userAgent;
1125
+ const hasBraveAPI = !!navigator.brave;
1126
+ return parseBrowserFromUserAgent(userAgent, hasBraveAPI);
1127
+ }
1128
+ function getPlatformName() {
1129
+ const { name, version } = detectBrowser();
1130
+ return version !== "unknown" ? `${name}-v${version}` : name;
1131
+ }
1132
+ function getBrowserDisplayName() {
1133
+ const { name, version } = detectBrowser();
1134
+ const capitalizedName = name.charAt(0).toUpperCase() + name.slice(1);
1135
+ return version !== "unknown" ? `${capitalizedName} ${version}` : capitalizedName;
1136
+ }
1137
+ function isMobileDevice() {
1138
+ if (typeof window === "undefined" || !window.navigator?.userAgent) {
1139
+ return false;
1140
+ }
1141
+ const userAgent = window.navigator.userAgent.toLowerCase();
1142
+ const mobilePatterns = [
1143
+ /android/,
1144
+ /iphone|ipad|ipod/,
1145
+ /blackberry/,
1146
+ /windows phone/,
1147
+ /mobile/,
1148
+ /tablet/,
1149
+ /silk/,
1150
+ /kindle/,
1151
+ /opera mini/,
1152
+ /opera mobi/
1153
+ ];
1154
+ const isMobileUA = mobilePatterns.some((pattern) => pattern.test(userAgent));
1155
+ let isSmallScreen = false;
1156
+ try {
1157
+ isSmallScreen = window.screen.width <= 768 || window.screen.height <= 768;
1158
+ } catch (error) {
1159
+ isSmallScreen = false;
1160
+ }
1161
+ let isTouchDevice = false;
1162
+ try {
1163
+ isTouchDevice = "ontouchstart" in window || navigator.maxTouchPoints > 0;
1164
+ } catch (error) {
1165
+ isTouchDevice = false;
1166
+ }
1167
+ return isMobileUA || isSmallScreen && isTouchDevice;
1168
+ }
814
1169
 
815
1170
  // src/providers/embedded/adapters/auth.ts
816
1171
  var BrowserAuthProvider = class {
817
1172
  constructor(urlParamsAccessor) {
818
1173
  this.urlParamsAccessor = urlParamsAccessor;
819
1174
  }
1175
+ getValidatedCurrentUrl() {
1176
+ const currentUrl = window.location.href;
1177
+ if (!currentUrl.startsWith("http:") && !currentUrl.startsWith("https:")) {
1178
+ throw new Error("Invalid URL protocol - only HTTP/HTTPS URLs are supported");
1179
+ }
1180
+ return currentUrl;
1181
+ }
820
1182
  authenticate(options) {
821
1183
  return new Promise((resolve) => {
822
1184
  if ("jwtToken" in options) {
@@ -824,22 +1186,24 @@ var BrowserAuthProvider = class {
824
1186
  }
825
1187
  const phantomOptions = options;
826
1188
  debug.info(DebugCategory.PHANTOM_CONNECT_AUTH, "Starting Phantom Connect authentication", {
827
- organizationId: phantomOptions.organizationId,
828
- parentOrganizationId: phantomOptions.parentOrganizationId,
1189
+ publicKey: phantomOptions.publicKey,
829
1190
  appId: phantomOptions.appId,
830
1191
  provider: phantomOptions.provider,
831
- authUrl: phantomOptions.authUrl,
832
- hasCustomData: !!phantomOptions.customAuthData
1192
+ authUrl: phantomOptions.authUrl
833
1193
  });
834
- const baseUrl = phantomOptions.authUrl || DEFAULT_AUTH_URL;
1194
+ const baseUrl = phantomOptions.authUrl || import_constants.DEFAULT_AUTH_URL;
835
1195
  debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Using auth URL", { baseUrl });
836
1196
  const params = new URLSearchParams({
837
- organization_id: phantomOptions.organizationId,
838
- parent_organization_id: phantomOptions.parentOrganizationId,
1197
+ public_key: phantomOptions.publicKey,
839
1198
  app_id: phantomOptions.appId,
840
- redirect_uri: phantomOptions.redirectUrl || (typeof window !== "undefined" ? window.location.href : ""),
1199
+ redirect_uri: phantomOptions.redirectUrl || (typeof window !== "undefined" ? this.getValidatedCurrentUrl() : ""),
841
1200
  session_id: phantomOptions.sessionId,
842
- clear_previous_session: true.toString()
1201
+ // OAuth session management - defaults to allow refresh unless explicitly clearing after logout
1202
+ clear_previous_session: (phantomOptions.clearPreviousSession ?? false).toString(),
1203
+ allow_refresh: (phantomOptions.allowRefresh ?? true).toString(),
1204
+ sdk_version: "1.0.0-beta.21",
1205
+ sdk_type: "browser",
1206
+ platform: detectBrowser().name
843
1207
  });
844
1208
  if (phantomOptions.provider) {
845
1209
  debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Provider specified, will skip selection", {
@@ -850,13 +1214,8 @@ var BrowserAuthProvider = class {
850
1214
  debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "No provider specified, defaulting to Google");
851
1215
  params.append("provider", "google");
852
1216
  }
853
- if (phantomOptions.customAuthData) {
854
- debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Adding custom auth data");
855
- params.append("authData", JSON.stringify(phantomOptions.customAuthData));
856
- }
857
1217
  const authContext = {
858
- organizationId: phantomOptions.organizationId,
859
- parentOrganizationId: phantomOptions.parentOrganizationId,
1218
+ publicKey: phantomOptions.publicKey,
860
1219
  appId: phantomOptions.appId,
861
1220
  provider: phantomOptions.provider,
862
1221
  sessionId: phantomOptions.sessionId
@@ -865,6 +1224,9 @@ var BrowserAuthProvider = class {
865
1224
  debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Stored auth context in session storage", { authContext });
866
1225
  const authUrl = `${baseUrl}?${params.toString()}`;
867
1226
  debug.info(DebugCategory.PHANTOM_CONNECT_AUTH, "Redirecting to Phantom Connect", { authUrl });
1227
+ if (!authUrl.startsWith("https:") && !authUrl.startsWith("http://localhost")) {
1228
+ throw new Error("Invalid auth URL - only HTTPS URLs are allowed for authentication");
1229
+ }
868
1230
  window.location.href = authUrl;
869
1231
  resolve();
870
1232
  });
@@ -920,10 +1282,32 @@ var BrowserAuthProvider = class {
920
1282
  sessionId,
921
1283
  accountDerivationIndex: accountDerivationIndex ? parseInt(accountDerivationIndex) : void 0
922
1284
  });
1285
+ const organizationId = this.urlParamsAccessor.getParam("organization_id");
1286
+ const expiresInMs = this.urlParamsAccessor.getParam("expires_in_ms");
1287
+ const authUserId = this.urlParamsAccessor.getParam("auth_user_id");
1288
+ debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Auth redirect parameters", {
1289
+ walletId,
1290
+ organizationId,
1291
+ sessionId,
1292
+ accountDerivationIndex,
1293
+ expiresInMs,
1294
+ authUserId
1295
+ });
1296
+ if (!organizationId) {
1297
+ debug.error(DebugCategory.PHANTOM_CONNECT_AUTH, "Missing organization_id in auth response");
1298
+ throw new Error("Missing organization_id in auth response");
1299
+ }
1300
+ if (organizationId.startsWith("temp-")) {
1301
+ debug.warn(DebugCategory.PHANTOM_CONNECT_AUTH, "Received temporary organization_id, server may not be configured properly", {
1302
+ organizationId
1303
+ });
1304
+ }
923
1305
  return {
924
1306
  walletId,
925
- userInfo: context,
926
- accountDerivationIndex: accountDerivationIndex ? parseInt(accountDerivationIndex) : void 0
1307
+ organizationId,
1308
+ accountDerivationIndex: accountDerivationIndex ? parseInt(accountDerivationIndex) : 0,
1309
+ expiresInMs: expiresInMs ? parseInt(expiresInMs) : 0,
1310
+ authUserId: authUserId || void 0
927
1311
  };
928
1312
  } catch (error) {
929
1313
  sessionStorage.removeItem("phantom-auth-context");
@@ -932,6 +1316,105 @@ var BrowserAuthProvider = class {
932
1316
  }
933
1317
  };
934
1318
 
1319
+ // src/providers/embedded/adapters/phantom-app.ts
1320
+ var import_browser_injected_sdk3 = require("@phantom/browser-injected-sdk");
1321
+
1322
+ // src/isPhantomLoginAvailable.ts
1323
+ var import_browser_injected_sdk2 = require("@phantom/browser-injected-sdk");
1324
+ async function isPhantomLoginAvailable(timeoutMs = 3e3) {
1325
+ const extensionInstalled = await waitForExtension(timeoutMs);
1326
+ if (!extensionInstalled) {
1327
+ return false;
1328
+ }
1329
+ try {
1330
+ if (!window.phantom?.app?.features || typeof window.phantom.app.features !== "function") {
1331
+ return false;
1332
+ }
1333
+ const response = await window.phantom.app.features();
1334
+ if (!Array.isArray(response.features)) {
1335
+ return false;
1336
+ }
1337
+ return response.features.includes("phantom_login");
1338
+ } catch (error) {
1339
+ console.error("Error checking Phantom extension features", error);
1340
+ return false;
1341
+ }
1342
+ }
1343
+ async function waitForExtension(timeoutMs) {
1344
+ return new Promise((resolve) => {
1345
+ const startTime = Date.now();
1346
+ const checkInterval = 100;
1347
+ const checkForExtension = () => {
1348
+ try {
1349
+ if ((0, import_browser_injected_sdk2.isPhantomExtensionInstalled)()) {
1350
+ resolve(true);
1351
+ return;
1352
+ }
1353
+ } catch (error) {
1354
+ }
1355
+ const elapsed = Date.now() - startTime;
1356
+ if (elapsed >= timeoutMs) {
1357
+ resolve(false);
1358
+ return;
1359
+ }
1360
+ setTimeout(checkForExtension, checkInterval);
1361
+ };
1362
+ checkForExtension();
1363
+ });
1364
+ }
1365
+
1366
+ // src/providers/embedded/adapters/phantom-app.ts
1367
+ var BrowserPhantomAppProvider = class {
1368
+ /**
1369
+ * Check if the Phantom extension is installed in the browser
1370
+ */
1371
+ isAvailable() {
1372
+ return (0, import_browser_injected_sdk3.isPhantomExtensionInstalled)();
1373
+ }
1374
+ /**
1375
+ * Authenticate using the Phantom browser extension
1376
+ */
1377
+ async authenticate(options) {
1378
+ if (!this.isAvailable()) {
1379
+ throw new Error(
1380
+ "Phantom extension is not installed. Please install the Phantom browser extension to use this authentication method."
1381
+ );
1382
+ }
1383
+ const loginAvailable = await isPhantomLoginAvailable();
1384
+ if (!loginAvailable) {
1385
+ throw new Error(
1386
+ "Phantom Login is not available. Please update your Phantom extension to use this authentication method."
1387
+ );
1388
+ }
1389
+ try {
1390
+ if (!window.phantom?.app?.login) {
1391
+ throw new Error("Phantom extension login method not found");
1392
+ }
1393
+ const result = await window.phantom.app.login({
1394
+ publicKey: options.publicKey,
1395
+ appId: options.appId,
1396
+ sessionId: options.sessionId
1397
+ });
1398
+ if (!result || !result.walletId || !result.organizationId) {
1399
+ throw new Error("Invalid authentication response from Phantom extension");
1400
+ }
1401
+ return {
1402
+ walletId: result.walletId,
1403
+ organizationId: result.organizationId,
1404
+ provider: "phantom",
1405
+ accountDerivationIndex: result.accountDerivationIndex ?? 0,
1406
+ expiresInMs: result.expiresInMs ?? 0,
1407
+ authUserId: result.authUserId
1408
+ };
1409
+ } catch (error) {
1410
+ if (error instanceof Error) {
1411
+ throw error;
1412
+ }
1413
+ throw new Error(`Phantom extension authentication failed: ${String(error)}`);
1414
+ }
1415
+ }
1416
+ };
1417
+
935
1418
  // src/providers/embedded/adapters/logger.ts
936
1419
  var BrowserLogger = class {
937
1420
  info(category, message, data) {
@@ -948,131 +1431,38 @@ var BrowserLogger = class {
948
1431
  }
949
1432
  };
950
1433
 
951
- // src/utils/browser-detection.ts
952
- function parseBrowserFromUserAgent(userAgent, hasBraveAPI) {
953
- let name = "unknown";
954
- let version = "unknown";
955
- if (!userAgent || typeof userAgent !== "string") {
956
- return { name, version };
957
- }
958
- try {
959
- if (userAgent.includes("Edg/")) {
960
- name = "edge";
961
- const match = userAgent.match(/Edg\/([0-9]+(?:\.[0-9]+)*)/);
962
- if (match)
963
- version = match[1].split(".")[0];
964
- } else if (userAgent.includes("OPR/") || userAgent.includes("Opera/")) {
965
- name = "opera";
966
- const match = userAgent.match(/(?:OPR|Opera)\/([0-9]+(?:\.[0-9]+)*)/);
967
- if (match)
968
- version = match[1].split(".")[0];
969
- } else if (userAgent.includes("SamsungBrowser/")) {
970
- name = "samsung";
971
- const match = userAgent.match(/SamsungBrowser\/([0-9]+(?:\.[0-9]+)*)/);
972
- if (match)
973
- version = match[1].split(".")[0];
974
- } else if (userAgent.includes("DuckDuckGo/")) {
975
- name = "duckduckgo";
976
- const match = userAgent.match(/DuckDuckGo\/([0-9]+(?:\.[0-9]+)*)/);
977
- if (match)
978
- version = match[1].split(".")[0];
979
- } else if (userAgent.includes("Chrome/") && hasBraveAPI) {
980
- name = "brave";
981
- const match = userAgent.match(/Chrome\/([0-9]+(?:\.[0-9]+)*)/);
982
- if (match)
983
- version = match[1].split(".")[0];
984
- } else if (userAgent.includes("Mobile/") || userAgent.includes("Android")) {
985
- if (userAgent.includes("Chrome/")) {
986
- name = "chrome-mobile";
987
- const match = userAgent.match(/Chrome\/([0-9]+(?:\.[0-9]+)*)/);
988
- if (match)
989
- version = match[1].split(".")[0];
990
- } else if (userAgent.includes("Firefox/")) {
991
- name = "firefox-mobile";
992
- const match = userAgent.match(/Firefox\/([0-9]+(?:\.[0-9]+)*)/);
993
- if (match)
994
- version = match[1].split(".")[0];
995
- } else if (userAgent.includes("Safari/") && userAgent.includes("Mobile/")) {
996
- name = "safari-mobile";
997
- const match = userAgent.match(/Version\/([0-9]+(?:\.[0-9]+)*)/);
998
- if (match)
999
- version = match[1].split(".")[0];
1000
- } else {
1001
- name = "mobile";
1002
- }
1003
- } else if (userAgent.includes("Chrome/")) {
1004
- name = "chrome";
1005
- const match = userAgent.match(/Chrome\/([0-9]+(?:\.[0-9]+)*)/);
1006
- if (match)
1007
- version = match[1].split(".")[0];
1008
- } else if (userAgent.includes("Firefox/")) {
1009
- name = "firefox";
1010
- const match = userAgent.match(/Firefox\/([0-9]+(?:\.[0-9]+)*)/);
1011
- if (match)
1012
- version = match[1].split(".")[0];
1013
- } else if (userAgent.includes("Safari/") && !userAgent.includes("Chrome/")) {
1014
- name = "safari";
1015
- const match = userAgent.match(/Version\/([0-9]+(?:\.[0-9]+)*)/);
1016
- if (match)
1017
- version = match[1].split(".")[0];
1018
- }
1019
- if (name === "unknown") {
1020
- const patterns = [
1021
- { regex: /Chrome\/([0-9]+)/, name: "chrome" },
1022
- { regex: /Firefox\/([0-9]+)/, name: "firefox" },
1023
- { regex: /Safari\/([0-9]+)/, name: "safari" },
1024
- { regex: /Edge\/([0-9]+)/, name: "edge" },
1025
- { regex: /Opera\/([0-9]+)/, name: "opera" }
1026
- ];
1027
- for (const pattern of patterns) {
1028
- const match = userAgent.match(pattern.regex);
1029
- if (match) {
1030
- name = pattern.name;
1031
- version = match[1];
1032
- break;
1033
- }
1034
- }
1035
- }
1036
- } catch (error) {
1037
- }
1038
- return { name, version };
1039
- }
1040
- function detectBrowser() {
1041
- if (typeof window === "undefined" || !window.navigator?.userAgent) {
1042
- return { name: "unknown", version: "unknown" };
1043
- }
1044
- const userAgent = window.navigator.userAgent;
1045
- const hasBraveAPI = !!navigator.brave;
1046
- return parseBrowserFromUserAgent(userAgent, hasBraveAPI);
1047
- }
1048
- function getPlatformName() {
1049
- const { name, version } = detectBrowser();
1050
- return version !== "unknown" ? `${name}-v${version}` : name;
1051
- }
1052
- function getBrowserDisplayName() {
1053
- const { name, version } = detectBrowser();
1054
- const capitalizedName = name.charAt(0).toUpperCase() + name.slice(1);
1055
- return version !== "unknown" ? `${capitalizedName} ${version}` : capitalizedName;
1056
- }
1057
-
1058
1434
  // src/providers/embedded/index.ts
1435
+ var import_constants2 = require("@phantom/constants");
1059
1436
  var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvider {
1060
1437
  constructor(config) {
1061
1438
  debug.log(DebugCategory.EMBEDDED_PROVIDER, "Initializing Browser EmbeddedProvider", { config });
1062
1439
  const urlParamsAccessor = new BrowserURLParamsAccessor();
1063
1440
  const stamper = new import_indexed_db_stamper.IndexedDbStamper({
1064
- dbName: `phantom-embedded-sdk-${config.organizationId}`,
1441
+ dbName: `phantom-embedded-sdk-${config.appId}`,
1065
1442
  storeName: "crypto-keys",
1066
1443
  keyName: "signing-key"
1067
1444
  });
1068
1445
  const platformName = getPlatformName();
1446
+ const { name: browserName, version } = detectBrowser();
1069
1447
  const platform = {
1070
1448
  storage: new BrowserStorage(),
1071
1449
  authProvider: new BrowserAuthProvider(urlParamsAccessor),
1450
+ phantomAppProvider: new BrowserPhantomAppProvider(),
1072
1451
  urlParamsAccessor,
1073
1452
  stamper,
1074
- name: platformName
1453
+ name: platformName,
1075
1454
  // Use detected browser name and version for identification
1455
+ analyticsHeaders: {
1456
+ [import_constants2.ANALYTICS_HEADERS.SDK_TYPE]: "browser",
1457
+ [import_constants2.ANALYTICS_HEADERS.PLATFORM]: browserName,
1458
+ // firefox, chrome, safari, etc.
1459
+ [import_constants2.ANALYTICS_HEADERS.PLATFORM_VERSION]: version,
1460
+ // Full user agent for more detailed info
1461
+ [import_constants2.ANALYTICS_HEADERS.APP_ID]: config.appId,
1462
+ [import_constants2.ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
1463
+ [import_constants2.ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.21"
1464
+ // Replaced at build time
1465
+ }
1076
1466
  };
1077
1467
  debug.log(DebugCategory.EMBEDDED_PROVIDER, "Detected platform", { platformName });
1078
1468
  const logger = new BrowserLogger();
@@ -1081,6 +1471,26 @@ var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvi
1081
1471
  }
1082
1472
  };
1083
1473
 
1474
+ // src/ProviderManager.ts
1475
+ var import_constants3 = require("@phantom/constants");
1476
+
1477
+ // src/utils/auth-callback.ts
1478
+ function isAuthFailureCallback(searchParams) {
1479
+ if (typeof window === "undefined" && !searchParams)
1480
+ return false;
1481
+ const params = searchParams || new URLSearchParams(window.location.search);
1482
+ const responseType = params.get("response_type");
1483
+ const sessionId = params.get("session_id");
1484
+ return responseType === "failure" && !!sessionId;
1485
+ }
1486
+ function isAuthCallbackUrl(searchParams) {
1487
+ if (typeof window === "undefined" && !searchParams)
1488
+ return false;
1489
+ const params = searchParams || new URLSearchParams(window.location.search);
1490
+ const sessionId = params.get("session_id");
1491
+ return !!(sessionId && (params.has("response_type") || params.has("wallet_id")));
1492
+ }
1493
+
1084
1494
  // src/ProviderManager.ts
1085
1495
  var ProviderManager = class {
1086
1496
  // Track which providers have forwarding set up
@@ -1088,7 +1498,6 @@ var ProviderManager = class {
1088
1498
  this.providers = /* @__PURE__ */ new Map();
1089
1499
  this.currentProvider = null;
1090
1500
  this.currentProviderKey = null;
1091
- this.walletId = null;
1092
1501
  // Event management for forwarding provider events
1093
1502
  this.eventListeners = /* @__PURE__ */ new Map();
1094
1503
  this.providerForwardingSetup = /* @__PURE__ */ new WeakSet();
@@ -1100,6 +1509,15 @@ var ProviderManager = class {
1100
1509
  currentProviderKey: this.currentProviderKey
1101
1510
  });
1102
1511
  }
1512
+ getValidatedCurrentUrl() {
1513
+ if (typeof window === "undefined")
1514
+ return "";
1515
+ const currentUrl = window.location.href;
1516
+ if (!currentUrl.startsWith("http:") && !currentUrl.startsWith("https:")) {
1517
+ throw new Error("Invalid URL protocol - only HTTP/HTTPS URLs are supported");
1518
+ }
1519
+ return currentUrl;
1520
+ }
1103
1521
  /**
1104
1522
  * Switch to a different provider type
1105
1523
  */
@@ -1115,7 +1533,6 @@ var ProviderManager = class {
1115
1533
  }
1116
1534
  this.currentProvider = this.providers.get(key);
1117
1535
  this.currentProviderKey = key;
1118
- this.walletId = null;
1119
1536
  this.ensureProviderEventForwarding();
1120
1537
  return this.currentProvider;
1121
1538
  }
@@ -1131,7 +1548,8 @@ var ProviderManager = class {
1131
1548
  getCurrentProviderInfo() {
1132
1549
  if (!this.currentProviderKey)
1133
1550
  return null;
1134
- const [type, embeddedWalletType] = this.currentProviderKey.split("-");
1551
+ const parts = this.currentProviderKey.split("-");
1552
+ const [type, embeddedWalletType] = parts;
1135
1553
  return {
1136
1554
  type,
1137
1555
  embeddedWalletType
@@ -1139,27 +1557,51 @@ var ProviderManager = class {
1139
1557
  }
1140
1558
  /**
1141
1559
  * Connect using the current provider
1560
+ * Automatically switches provider based on authOptions.provider
1142
1561
  */
1143
1562
  async connect(authOptions) {
1144
1563
  debug.info(DebugCategory.PROVIDER_MANAGER, "Starting connection", {
1145
1564
  currentProviderKey: this.currentProviderKey,
1146
- authOptions: authOptions ? { provider: authOptions.provider, hasJwtToken: !!authOptions.jwtToken } : void 0
1565
+ authOptions: { provider: authOptions.provider, hasJwtToken: !!authOptions.jwtToken }
1147
1566
  });
1567
+ const requestedProvider = authOptions.provider;
1568
+ let targetProviderType = null;
1569
+ if (requestedProvider === "injected") {
1570
+ targetProviderType = "injected";
1571
+ } else if (["google", "apple", "jwt", "phantom"].includes(requestedProvider)) {
1572
+ targetProviderType = "embedded";
1573
+ }
1574
+ if (targetProviderType) {
1575
+ const currentInfo = this.getCurrentProviderInfo();
1576
+ if (currentInfo?.type !== targetProviderType) {
1577
+ debug.log(DebugCategory.PROVIDER_MANAGER, "Auto-switching provider based on auth options", {
1578
+ from: currentInfo?.type,
1579
+ to: targetProviderType,
1580
+ requestedProvider
1581
+ });
1582
+ const switchOptions = {};
1583
+ if (targetProviderType === "embedded") {
1584
+ switchOptions.embeddedWalletType = currentInfo?.embeddedWalletType || this.config.embeddedWalletType;
1585
+ }
1586
+ this.switchProvider(targetProviderType, switchOptions);
1587
+ }
1588
+ }
1148
1589
  if (!this.currentProvider) {
1149
1590
  debug.error(DebugCategory.PROVIDER_MANAGER, "No provider selected");
1150
1591
  throw new Error("No provider selected");
1151
1592
  }
1152
1593
  debug.log(DebugCategory.PROVIDER_MANAGER, "Delegating to provider connect method");
1153
1594
  const result = await this.currentProvider.connect(authOptions);
1154
- this.walletId = result.walletId || null;
1595
+ const providerInfo = this.getCurrentProviderInfo();
1596
+ result.providerType = providerInfo?.type;
1155
1597
  debug.log(DebugCategory.PROVIDER_MANAGER, "Connection successful, saving preferences", {
1156
- walletId: this.walletId,
1157
- addressCount: result.addresses?.length || 0
1598
+ addressCount: result.addresses?.length || 0,
1599
+ providerType: result.providerType
1158
1600
  });
1159
1601
  this.saveProviderPreference();
1160
1602
  debug.info(DebugCategory.PROVIDER_MANAGER, "Connect completed", {
1161
- walletId: this.walletId,
1162
- addresses: result.addresses
1603
+ addresses: result.addresses,
1604
+ providerType: result.providerType
1163
1605
  });
1164
1606
  return result;
1165
1607
  }
@@ -1170,7 +1612,6 @@ var ProviderManager = class {
1170
1612
  if (!this.currentProvider)
1171
1613
  return;
1172
1614
  await this.currentProvider.disconnect();
1173
- this.walletId = null;
1174
1615
  }
1175
1616
  /**
1176
1617
  * Get addresses from current provider
@@ -1188,10 +1629,69 @@ var ProviderManager = class {
1188
1629
  return this.currentProvider?.isConnected() ?? false;
1189
1630
  }
1190
1631
  /**
1191
- * Get current wallet ID
1632
+ * Attempt auto-connect with fallback strategy
1633
+ * Tries embedded provider first if it exists, then injected provider
1634
+ * Returns true if any provider successfully connected
1192
1635
  */
1193
- getWalletId() {
1194
- return this.walletId;
1636
+ async autoConnect() {
1637
+ debug.log(DebugCategory.PROVIDER_MANAGER, "Starting auto-connect with fallback strategy");
1638
+ if (isAuthFailureCallback()) {
1639
+ debug.warn(DebugCategory.PROVIDER_MANAGER, "Auth failure detected in URL, skipping autoConnect fallback");
1640
+ return false;
1641
+ }
1642
+ const embeddedWalletType = this.config.embeddedWalletType || "user-wallet";
1643
+ const embeddedKey = this.getProviderKey("embedded", embeddedWalletType);
1644
+ if (this.providers.has(embeddedKey)) {
1645
+ debug.log(DebugCategory.PROVIDER_MANAGER, "Trying auto-connect with existing embedded provider");
1646
+ const embeddedProvider = this.providers.get(embeddedKey);
1647
+ try {
1648
+ const previousProvider = this.currentProvider;
1649
+ const previousKey = this.currentProviderKey;
1650
+ this.currentProvider = embeddedProvider;
1651
+ this.currentProviderKey = embeddedKey;
1652
+ this.ensureProviderEventForwarding();
1653
+ await embeddedProvider.autoConnect();
1654
+ if (embeddedProvider.isConnected()) {
1655
+ debug.info(DebugCategory.PROVIDER_MANAGER, "Embedded auto-connect successful");
1656
+ this.saveProviderPreference();
1657
+ return true;
1658
+ } else {
1659
+ debug.log(DebugCategory.PROVIDER_MANAGER, "Embedded provider did not connect, restoring previous provider");
1660
+ this.currentProvider = previousProvider;
1661
+ this.currentProviderKey = previousKey;
1662
+ }
1663
+ } catch (error) {
1664
+ debug.log(DebugCategory.PROVIDER_MANAGER, "Embedded auto-connect failed", {
1665
+ error: error.message
1666
+ });
1667
+ if (isAuthCallbackUrl()) {
1668
+ debug.log(DebugCategory.PROVIDER_MANAGER, "In auth callback URL, not attempting injected fallback");
1669
+ return false;
1670
+ }
1671
+ }
1672
+ }
1673
+ const injectedKey = this.getProviderKey("injected");
1674
+ if (this.providers.has(injectedKey)) {
1675
+ debug.log(DebugCategory.PROVIDER_MANAGER, "Trying auto-connect with existing injected provider");
1676
+ const injectedProvider = this.providers.get(injectedKey);
1677
+ try {
1678
+ this.currentProvider = injectedProvider;
1679
+ this.currentProviderKey = injectedKey;
1680
+ this.ensureProviderEventForwarding();
1681
+ await injectedProvider.autoConnect();
1682
+ if (injectedProvider.isConnected()) {
1683
+ debug.info(DebugCategory.PROVIDER_MANAGER, "Injected auto-connect successful");
1684
+ this.saveProviderPreference();
1685
+ return true;
1686
+ }
1687
+ } catch (error) {
1688
+ debug.log(DebugCategory.PROVIDER_MANAGER, "Injected auto-connect failed", {
1689
+ error: error.message
1690
+ });
1691
+ }
1692
+ }
1693
+ debug.log(DebugCategory.PROVIDER_MANAGER, "Auto-connect failed for all existing providers");
1694
+ return false;
1195
1695
  }
1196
1696
  /**
1197
1697
  * Add event listener - stores callback and ensures current provider forwards events to ProviderManager
@@ -1274,12 +1774,22 @@ var ProviderManager = class {
1274
1774
  }
1275
1775
  /**
1276
1776
  * Set default provider based on initial config
1777
+ * Creates both embedded and injected providers for autoConnect fallback
1277
1778
  */
1278
1779
  setDefaultProvider() {
1279
1780
  const defaultType = this.config.providerType || "embedded";
1280
- const defaultEmbeddedType = this.config.embeddedWalletType || "app-wallet";
1281
- this.createProvider(defaultType, defaultEmbeddedType);
1282
- this.switchProvider(defaultType, { embeddedWalletType: defaultEmbeddedType });
1781
+ const defaultEmbeddedType = this.config.embeddedWalletType || "user-wallet";
1782
+ if (this.config.appId) {
1783
+ debug.log(DebugCategory.PROVIDER_MANAGER, "Creating embedded provider");
1784
+ this.createProvider("embedded", defaultEmbeddedType);
1785
+ }
1786
+ debug.log(DebugCategory.PROVIDER_MANAGER, "Creating injected provider");
1787
+ this.createProvider("injected");
1788
+ const switchOptions = {};
1789
+ if (defaultType === "embedded") {
1790
+ switchOptions.embeddedWalletType = defaultEmbeddedType;
1791
+ }
1792
+ this.switchProvider(defaultType, switchOptions);
1283
1793
  }
1284
1794
  /**
1285
1795
  * Create a provider instance
@@ -1291,22 +1801,27 @@ var ProviderManager = class {
1291
1801
  let provider;
1292
1802
  if (type === "injected") {
1293
1803
  provider = new InjectedProvider({
1294
- solanaProvider: this.config.solanaProvider || "web3js",
1295
- addressTypes: this.config.addressTypes
1804
+ addressTypes: this.config.addressTypes || [import_client.AddressType.solana]
1296
1805
  });
1297
- } else {
1298
- if (!this.config.apiBaseUrl || !this.config.appId) {
1299
- throw new Error("apiBaseUrl and appId are required for embedded provider");
1806
+ } else if (type === "embedded") {
1807
+ if (!this.config.appId) {
1808
+ throw new Error("appId is required for embedded provider");
1300
1809
  }
1810
+ const apiBaseUrl = this.config.apiBaseUrl || import_constants3.DEFAULT_WALLET_API_URL;
1811
+ const authUrl = this.config.authOptions?.authUrl || import_constants3.DEFAULT_AUTH_URL;
1301
1812
  provider = new EmbeddedProvider({
1302
- apiBaseUrl: this.config.apiBaseUrl,
1303
- organizationId: this.config.appId,
1813
+ apiBaseUrl,
1304
1814
  appId: this.config.appId,
1305
- authOptions: this.config.authOptions,
1306
- embeddedWalletType: embeddedWalletType || "app-wallet",
1307
- addressTypes: this.config.addressTypes,
1308
- solanaProvider: this.config.solanaProvider || "web3js"
1815
+ authOptions: {
1816
+ ...this.config.authOptions || {},
1817
+ authUrl,
1818
+ redirectUrl: this.config.authOptions?.redirectUrl || this.getValidatedCurrentUrl()
1819
+ },
1820
+ embeddedWalletType: embeddedWalletType || import_constants3.DEFAULT_EMBEDDED_WALLET_TYPE,
1821
+ addressTypes: this.config.addressTypes || [import_client.AddressType.solana]
1309
1822
  });
1823
+ } else {
1824
+ throw new Error(`Unsupported provider type: ${type}`);
1310
1825
  }
1311
1826
  this.providers.set(key, provider);
1312
1827
  }
@@ -1316,8 +1831,10 @@ var ProviderManager = class {
1316
1831
  getProviderKey(type, embeddedWalletType) {
1317
1832
  if (type === "injected") {
1318
1833
  return "injected";
1834
+ } else if (type === "embedded") {
1835
+ return `embedded-${embeddedWalletType || "app-wallet"}`;
1319
1836
  }
1320
- return `embedded-${embeddedWalletType || "app-wallet"}`;
1837
+ throw new Error(`Unsupported provider type: ${type}`);
1321
1838
  }
1322
1839
  /**
1323
1840
  * Save provider preference to localStorage
@@ -1332,35 +1849,17 @@ var ProviderManager = class {
1332
1849
  console.error("Failed to save provider preference:", error);
1333
1850
  }
1334
1851
  }
1335
- /**
1336
- * Restore provider preference from localStorage
1337
- */
1338
- /*
1339
- private restoreProviderPreference(): void {
1340
- try {
1341
- const saved = localStorage.getItem("phantom-provider-preference");
1342
- if (saved) {
1343
- const preference: ProviderPreference = JSON.parse(saved);
1344
- this.switchProvider(preference.type, {
1345
- embeddedWalletType: preference.embeddedWalletType,
1346
- });
1347
- }
1348
- } catch (error) {
1349
- // Ignore localStorage errors - just use default provider
1350
- console.error("Failed to restore provider preference:", error);
1351
- }
1352
- }*/
1353
1852
  };
1354
1853
 
1355
1854
  // src/waitForPhantomExtension.ts
1356
- var import_browser_injected_sdk2 = require("@phantom/browser-injected-sdk");
1855
+ var import_browser_injected_sdk4 = require("@phantom/browser-injected-sdk");
1357
1856
  async function waitForPhantomExtension(timeoutMs = 3e3) {
1358
1857
  return new Promise((resolve) => {
1359
1858
  const startTime = Date.now();
1360
1859
  const checkInterval = 100;
1361
1860
  const checkForExtension = () => {
1362
1861
  try {
1363
- if ((0, import_browser_injected_sdk2.isPhantomExtensionInstalled)()) {
1862
+ if ((0, import_browser_injected_sdk4.isPhantomExtensionInstalled)()) {
1364
1863
  resolve(true);
1365
1864
  return;
1366
1865
  }
@@ -1378,6 +1877,7 @@ async function waitForPhantomExtension(timeoutMs = 3e3) {
1378
1877
  }
1379
1878
 
1380
1879
  // src/BrowserSDK.ts
1880
+ var import_constants4 = require("@phantom/constants");
1381
1881
  var BrowserSDK = class {
1382
1882
  constructor(config) {
1383
1883
  debug.info(DebugCategory.BROWSER_SDK, "Initializing BrowserSDK", {
@@ -1389,7 +1889,7 @@ var BrowserSDK = class {
1389
1889
  debug.error(DebugCategory.BROWSER_SDK, "Invalid providerType", { providerType: config.providerType });
1390
1890
  throw new Error(`Invalid providerType: ${config.providerType}. Must be "injected" or "embedded".`);
1391
1891
  }
1392
- const embeddedWalletType = config.embeddedWalletType || "app-wallet";
1892
+ const embeddedWalletType = config.embeddedWalletType || import_constants4.DEFAULT_EMBEDDED_WALLET_TYPE;
1393
1893
  if (config.providerType === "embedded" && !["app-wallet", "user-wallet"].includes(embeddedWalletType)) {
1394
1894
  debug.error(DebugCategory.BROWSER_SDK, "Invalid embeddedWalletType", {
1395
1895
  embeddedWalletType: config.embeddedWalletType
@@ -1431,7 +1931,6 @@ var BrowserSDK = class {
1431
1931
  const result = await this.providerManager.connect(options);
1432
1932
  debug.info(DebugCategory.BROWSER_SDK, "Connection successful", {
1433
1933
  addressCount: result.addresses.length,
1434
- walletId: result.walletId,
1435
1934
  status: result.status
1436
1935
  });
1437
1936
  return result;
@@ -1453,22 +1952,6 @@ var BrowserSDK = class {
1453
1952
  throw error;
1454
1953
  }
1455
1954
  }
1456
- /**
1457
- * Switch between provider types (injected vs embedded)
1458
- */
1459
- async switchProvider(type, options) {
1460
- debug.info(DebugCategory.BROWSER_SDK, "Switching provider", { type, options });
1461
- try {
1462
- await this.providerManager.switchProvider(type, options);
1463
- debug.info(DebugCategory.BROWSER_SDK, "Provider switch successful", { type });
1464
- } catch (error) {
1465
- debug.error(DebugCategory.BROWSER_SDK, "Provider switch failed", {
1466
- type,
1467
- error: error.message
1468
- });
1469
- throw error;
1470
- }
1471
- }
1472
1955
  // ===== STATE QUERIES =====
1473
1956
  /**
1474
1957
  * Check if the SDK is connected to a wallet
@@ -1488,12 +1971,6 @@ var BrowserSDK = class {
1488
1971
  getCurrentProviderInfo() {
1489
1972
  return this.providerManager.getCurrentProviderInfo();
1490
1973
  }
1491
- /**
1492
- * Get the wallet ID (for embedded wallets)
1493
- */
1494
- getWalletId() {
1495
- return this.providerManager.getWalletId();
1496
- }
1497
1974
  // ===== UTILITY METHODS =====
1498
1975
  /**
1499
1976
  * Check if Phantom extension is installed
@@ -1520,17 +1997,17 @@ var BrowserSDK = class {
1520
1997
  /**
1521
1998
  * Attempt auto-connection using existing session
1522
1999
  * Should be called after setting up event listeners
1523
- * Only works with embedded providers
2000
+ * Tries embedded provider first, then injected provider as fallback
1524
2001
  */
1525
2002
  async autoConnect() {
1526
- debug.log(DebugCategory.BROWSER_SDK, "Attempting auto-connect");
1527
- const currentProvider = this.providerManager.getCurrentProvider();
1528
- if (currentProvider && "autoConnect" in currentProvider) {
1529
- await currentProvider.autoConnect();
1530
- } else {
1531
- debug.warn(DebugCategory.BROWSER_SDK, "Current provider does not support auto-connect", {
2003
+ debug.log(DebugCategory.BROWSER_SDK, "Attempting auto-connect with fallback strategy");
2004
+ const result = await this.providerManager.autoConnect();
2005
+ if (result) {
2006
+ debug.info(DebugCategory.BROWSER_SDK, "Auto-connect successful", {
1532
2007
  providerType: this.getCurrentProviderInfo()?.type
1533
2008
  });
2009
+ } else {
2010
+ debug.log(DebugCategory.BROWSER_SDK, "Auto-connect failed for all providers");
1534
2011
  }
1535
2012
  }
1536
2013
  /**
@@ -1674,9 +2151,16 @@ var BrowserSDK = class {
1674
2151
  }
1675
2152
  };
1676
2153
 
1677
- // src/types.ts
1678
- var import_client4 = require("@phantom/client");
2154
+ // src/utils/deeplink.ts
2155
+ function getDeeplinkToPhantom(ref) {
2156
+ if (!window.location.href.startsWith("http:") && !window.location.href.startsWith("https:")) {
2157
+ throw new Error("Invalid URL protocol - only HTTP/HTTPS URLs are supported for deeplinks");
2158
+ }
2159
+ const currentUrl = encodeURIComponent(window.location.href);
2160
+ const refParam = ref ? `?ref=${encodeURIComponent(ref)}` : "";
2161
+ return `https://phantom.app/ul/browse/${currentUrl}${refParam}`;
2162
+ }
1679
2163
 
1680
2164
  // src/index.ts
1681
- var import_constants2 = require("@phantom/constants");
2165
+ var import_constants5 = require("@phantom/constants");
1682
2166
  var import_client5 = require("@phantom/client");