@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.mjs CHANGED
@@ -1,5 +1,8 @@
1
+ // src/types.ts
2
+ import { AddressType } from "@phantom/client";
3
+
1
4
  // src/providers/injected/index.ts
2
- import { AddressType as AddressType3 } from "@phantom/client";
5
+ import { AddressType as AddressType4 } from "@phantom/client";
3
6
  import { createPhantom, createExtensionPlugin } from "@phantom/browser-injected-sdk";
4
7
  import { createSolanaPlugin } from "@phantom/browser-injected-sdk/solana";
5
8
  import { createEthereumPlugin } from "@phantom/browser-injected-sdk/ethereum";
@@ -83,7 +86,7 @@ var DebugCategory = {
83
86
 
84
87
  // src/providers/injected/chains/SolanaChain.ts
85
88
  import { EventEmitter } from "eventemitter3";
86
- import { AddressType } from "@phantom/client";
89
+ import { AddressType as AddressType2 } from "@phantom/client";
87
90
  import { Buffer } from "buffer";
88
91
  var InjectedSolanaChain = class {
89
92
  constructor(phantom, callbacks) {
@@ -108,7 +111,7 @@ var InjectedSolanaChain = class {
108
111
  return Promise.reject(new Error("Provider not connected. Call provider connect first."));
109
112
  }
110
113
  const addresses = this.callbacks.getAddresses();
111
- const solanaAddress = addresses.find((addr) => addr.addressType === AddressType.solana);
114
+ const solanaAddress = addresses.find((addr) => addr.addressType === AddressType2.solana);
112
115
  if (!solanaAddress) {
113
116
  return Promise.reject(new Error("Solana not enabled for this provider"));
114
117
  }
@@ -142,8 +145,27 @@ var InjectedSolanaChain = class {
142
145
  const result = await this.phantom.solana.signAndSendTransaction(transaction);
143
146
  return { signature: result.signature };
144
147
  }
145
- signAllTransactions(_transactions) {
146
- return Promise.reject(new Error("Sign-only transactions not supported by injected provider"));
148
+ async signAllTransactions(transactions) {
149
+ if (!this.callbacks.isConnected()) {
150
+ return Promise.reject(new Error("Provider not connected. Call provider connect first."));
151
+ }
152
+ try {
153
+ const result = await this.phantom.solana.signAllTransactions(transactions);
154
+ return result;
155
+ } catch (error) {
156
+ return Promise.reject(error);
157
+ }
158
+ }
159
+ async signAndSendAllTransactions(transactions) {
160
+ if (!this.callbacks.isConnected()) {
161
+ return Promise.reject(new Error("Provider not connected. Call provider connect first."));
162
+ }
163
+ try {
164
+ const result = await this.phantom.solana.signAndSendAllTransactions(transactions);
165
+ return { signatures: result.signatures };
166
+ } catch (error) {
167
+ return Promise.reject(error);
168
+ }
147
169
  }
148
170
  switchNetwork(_network) {
149
171
  return Promise.resolve();
@@ -169,7 +191,7 @@ var InjectedSolanaChain = class {
169
191
  this.eventEmitter.emit("accountChanged", publicKey);
170
192
  });
171
193
  this.callbacks.on("connect", (data) => {
172
- const solanaAddress = data.addresses?.find((addr) => addr.addressType === AddressType.solana);
194
+ const solanaAddress = data.addresses?.find((addr) => addr.addressType === AddressType2.solana);
173
195
  if (solanaAddress) {
174
196
  this.updateConnectionState(true, solanaAddress.address);
175
197
  }
@@ -180,7 +202,7 @@ var InjectedSolanaChain = class {
180
202
  }
181
203
  syncInitialState() {
182
204
  if (this.callbacks.isConnected()) {
183
- const solanaAddress = this.callbacks.getAddresses().find((addr) => addr.addressType === AddressType.solana);
205
+ const solanaAddress = this.callbacks.getAddresses().find((addr) => addr.addressType === AddressType2.solana);
184
206
  if (solanaAddress) {
185
207
  this.updateConnectionState(true, solanaAddress.address);
186
208
  }
@@ -201,7 +223,7 @@ var InjectedSolanaChain = class {
201
223
 
202
224
  // src/providers/injected/chains/EthereumChain.ts
203
225
  import { EventEmitter as EventEmitter2 } from "eventemitter3";
204
- import { AddressType as AddressType2 } from "@phantom/client";
226
+ import { AddressType as AddressType3 } from "@phantom/client";
205
227
  var InjectedEthereumChain = class {
206
228
  constructor(phantom, callbacks) {
207
229
  this._connected = false;
@@ -239,7 +261,7 @@ var InjectedEthereumChain = class {
239
261
  return Promise.reject(new Error("Provider not connected. Call provider connect first."));
240
262
  }
241
263
  const addresses = this.callbacks.getAddresses();
242
- const ethAddresses = addresses.filter((addr) => addr.addressType === AddressType2.ethereum).map((addr) => addr.address);
264
+ const ethAddresses = addresses.filter((addr) => addr.addressType === AddressType3.ethereum).map((addr) => addr.address);
243
265
  this.updateConnectionState(true, ethAddresses);
244
266
  return Promise.resolve(ethAddresses);
245
267
  }
@@ -260,8 +282,9 @@ var InjectedEthereumChain = class {
260
282
  return await this.phantom.ethereum.sendTransaction(transaction);
261
283
  }
262
284
  async switchChain(chainId) {
263
- await this.phantom.ethereum.switchChain(`0x${chainId.toString(16)}`);
264
- this._chainId = `0x${chainId.toString(16)}`;
285
+ const hexChainId = typeof chainId === "string" ? chainId.toLowerCase().startsWith("0x") ? chainId : `0x${parseInt(chainId, 10).toString(16)}` : `0x${chainId.toString(16)}`;
286
+ await this.phantom.ethereum.switchChain(hexChainId);
287
+ this._chainId = hexChainId;
265
288
  this.eventEmitter.emit("chainChanged", this._chainId);
266
289
  }
267
290
  async getChainId() {
@@ -294,7 +317,7 @@ var InjectedEthereumChain = class {
294
317
  this.eventEmitter.emit("chainChanged", chainId);
295
318
  });
296
319
  this.callbacks.on("connect", (data) => {
297
- const ethAddresses = data.addresses?.filter((addr) => addr.addressType === AddressType2.ethereum)?.map((addr) => addr.address) || [];
320
+ const ethAddresses = data.addresses?.filter((addr) => addr.addressType === AddressType3.ethereum)?.map((addr) => addr.address) || [];
298
321
  if (ethAddresses.length > 0) {
299
322
  this.updateConnectionState(true, ethAddresses);
300
323
  }
@@ -305,7 +328,7 @@ var InjectedEthereumChain = class {
305
328
  }
306
329
  syncInitialState() {
307
330
  if (this.callbacks.isConnected()) {
308
- const ethAddresses = this.callbacks.getAddresses().filter((addr) => addr.addressType === AddressType2.ethereum).map((addr) => addr.address);
331
+ const ethAddresses = this.callbacks.getAddresses().filter((addr) => addr.addressType === AddressType3.ethereum).map((addr) => addr.address);
309
332
  if (ethAddresses.length > 0) {
310
333
  this.updateConnectionState(true, ethAddresses);
311
334
  }
@@ -325,6 +348,8 @@ var InjectedEthereumChain = class {
325
348
  };
326
349
 
327
350
  // src/providers/injected/index.ts
351
+ var MANUAL_DISCONNECT_KEY = "phantom-injected-manual-disconnect";
352
+ var MANUAL_DISCONNECT_VALUE = "true";
328
353
  var InjectedProvider = class {
329
354
  constructor(config) {
330
355
  this.connected = false;
@@ -337,11 +362,11 @@ var InjectedProvider = class {
337
362
  this.addressTypes = config.addressTypes;
338
363
  debug.log(DebugCategory.INJECTED_PROVIDER, "Address types configured", { addressTypes: this.addressTypes });
339
364
  const plugins = [createExtensionPlugin()];
340
- if (this.addressTypes.includes(AddressType3.solana)) {
365
+ if (this.addressTypes.includes(AddressType4.solana)) {
341
366
  plugins.push(createSolanaPlugin());
342
367
  debug.log(DebugCategory.INJECTED_PROVIDER, "Solana plugin added");
343
368
  }
344
- if (this.addressTypes.includes(AddressType3.ethereum)) {
369
+ if (this.addressTypes.includes(AddressType4.ethereum)) {
345
370
  plugins.push(createEthereumPlugin());
346
371
  debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum plugin added");
347
372
  }
@@ -352,10 +377,10 @@ var InjectedProvider = class {
352
377
  });
353
378
  this.phantom = createPhantom({ plugins });
354
379
  const callbacks = this.createCallbacks();
355
- if (this.addressTypes.includes(AddressType3.solana)) {
380
+ if (this.addressTypes.includes(AddressType4.solana)) {
356
381
  this._solanaChain = new InjectedSolanaChain(this.phantom, callbacks);
357
382
  }
358
- if (this.addressTypes.includes(AddressType3.ethereum)) {
383
+ if (this.addressTypes.includes(AddressType4.ethereum)) {
359
384
  this._ethereumChain = new InjectedEthereumChain(this.phantom, callbacks);
360
385
  }
361
386
  debug.info(DebugCategory.INJECTED_PROVIDER, "InjectedProvider initialized");
@@ -364,7 +389,7 @@ var InjectedProvider = class {
364
389
  * Access to Solana chain operations
365
390
  */
366
391
  get solana() {
367
- if (!this.addressTypes.includes(AddressType3.solana)) {
392
+ if (!this.addressTypes.includes(AddressType4.solana)) {
368
393
  throw new Error("Solana not enabled for this provider");
369
394
  }
370
395
  if (!this._solanaChain) {
@@ -376,7 +401,7 @@ var InjectedProvider = class {
376
401
  * Access to Ethereum chain operations
377
402
  */
378
403
  get ethereum() {
379
- if (!this.addressTypes.includes(AddressType3.ethereum)) {
404
+ if (!this.addressTypes.includes(AddressType4.ethereum)) {
380
405
  throw new Error("Ethereum not enabled for this provider");
381
406
  }
382
407
  if (!this._ethereumChain) {
@@ -387,9 +412,11 @@ var InjectedProvider = class {
387
412
  async connect(authOptions) {
388
413
  debug.info(DebugCategory.INJECTED_PROVIDER, "Starting injected provider connect", {
389
414
  addressTypes: this.addressTypes,
390
- authOptionsIgnored: !!authOptions
391
- // Note: authOptions are ignored for injected provider
415
+ provider: authOptions.provider
392
416
  });
417
+ if (authOptions.provider !== "injected") {
418
+ throw new Error(`Invalid provider for injected connection: ${authOptions.provider}. Must be "injected"`);
419
+ }
393
420
  this.emit("connect_start", {
394
421
  source: "manual-connect",
395
422
  providerType: "injected"
@@ -406,35 +433,45 @@ var InjectedProvider = class {
406
433
  }
407
434
  debug.log(DebugCategory.INJECTED_PROVIDER, "Phantom extension detected");
408
435
  const connectedAddresses = [];
409
- if (this.addressTypes.includes(AddressType3.solana)) {
436
+ if (this.addressTypes.includes(AddressType4.solana)) {
410
437
  debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting Solana connection");
411
438
  try {
412
439
  const publicKey = await this.phantom.solana.connect();
413
440
  if (publicKey) {
414
441
  connectedAddresses.push({
415
- addressType: AddressType3.solana,
442
+ addressType: AddressType4.solana,
416
443
  address: publicKey
417
444
  });
418
445
  debug.info(DebugCategory.INJECTED_PROVIDER, "Solana connected successfully", { address: publicKey });
419
446
  }
420
447
  } catch (err) {
421
- debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Solana", { error: err });
448
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Solana, stopping", { error: err });
449
+ this.emit("connect_error", {
450
+ error: err instanceof Error ? err.message : "Failed to connect",
451
+ source: "manual-connect"
452
+ });
453
+ throw err;
422
454
  }
423
455
  }
424
- if (this.addressTypes.includes(AddressType3.ethereum)) {
456
+ if (this.addressTypes.includes(AddressType4.ethereum)) {
425
457
  try {
426
458
  const accounts = await this.phantom.ethereum.connect();
427
459
  if (accounts && accounts.length > 0) {
428
460
  connectedAddresses.push(
429
461
  ...accounts.map((address) => ({
430
- addressType: AddressType3.ethereum,
462
+ addressType: AddressType4.ethereum,
431
463
  address
432
464
  }))
433
465
  );
434
466
  debug.info(DebugCategory.INJECTED_PROVIDER, "Ethereum connected successfully", { addresses: accounts });
435
467
  }
436
468
  } catch (err) {
437
- debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Ethereum", { error: err });
469
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Ethereum, stopping", { error: err });
470
+ this.emit("connect_error", {
471
+ error: err instanceof Error ? err.message : "Failed to connect",
472
+ source: "manual-connect"
473
+ });
474
+ throw err;
438
475
  }
439
476
  }
440
477
  if (connectedAddresses.length === 0) {
@@ -447,14 +484,22 @@ var InjectedProvider = class {
447
484
  }
448
485
  this.addresses = connectedAddresses;
449
486
  this.connected = true;
487
+ const authUserId = await this.getAuthUserId("manual-connect");
488
+ try {
489
+ localStorage.removeItem(MANUAL_DISCONNECT_KEY);
490
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Cleared manual disconnect flag - auto-reconnect enabled");
491
+ } catch (error) {
492
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to clear manual disconnect flag", { error });
493
+ }
450
494
  const result = {
451
495
  addresses: this.addresses,
452
- status: "completed"
453
- // walletId is not applicable for injected providers
496
+ status: "completed",
497
+ authUserId
454
498
  };
455
499
  this.emit("connect", {
456
500
  addresses: this.addresses,
457
- source: "manual-connect"
501
+ source: "manual-connect",
502
+ authUserId
458
503
  });
459
504
  return result;
460
505
  } catch (error) {
@@ -469,7 +514,7 @@ var InjectedProvider = class {
469
514
  }
470
515
  async disconnect() {
471
516
  debug.info(DebugCategory.INJECTED_PROVIDER, "Starting injected provider disconnect");
472
- if (this.addressTypes.includes(AddressType3.solana)) {
517
+ if (this.addressTypes.includes(AddressType4.solana)) {
473
518
  try {
474
519
  await this.phantom.solana.disconnect();
475
520
  debug.log(DebugCategory.INJECTED_PROVIDER, "Solana disconnected successfully");
@@ -477,18 +522,117 @@ var InjectedProvider = class {
477
522
  debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to disconnect Solana", { error: err });
478
523
  }
479
524
  }
480
- if (this.addressTypes.includes(AddressType3.ethereum)) {
525
+ if (this.addressTypes.includes(AddressType4.ethereum)) {
481
526
  debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum disconnected (no-op)");
482
527
  }
483
528
  this.browserInjectedCleanupFunctions.forEach((cleanup) => cleanup());
484
529
  this.browserInjectedCleanupFunctions = [];
485
530
  this.connected = false;
486
531
  this.addresses = [];
532
+ try {
533
+ localStorage.setItem(MANUAL_DISCONNECT_KEY, MANUAL_DISCONNECT_VALUE);
534
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Set manual disconnect flag to prevent auto-reconnect");
535
+ } catch (error) {
536
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to set manual disconnect flag", { error });
537
+ }
487
538
  this.emit("disconnect", {
488
539
  source: "manual-disconnect"
489
540
  });
490
541
  debug.info(DebugCategory.INJECTED_PROVIDER, "Injected provider disconnected successfully");
491
542
  }
543
+ /**
544
+ * Attempt auto-connection using onlyIfTrusted parameter
545
+ * This will only connect if the dApp is already trusted by the user
546
+ * Should be called after setting up event listeners
547
+ */
548
+ async autoConnect() {
549
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting auto-connect with onlyIfTrusted=true");
550
+ try {
551
+ const manualDisconnect = localStorage.getItem(MANUAL_DISCONNECT_KEY);
552
+ if (manualDisconnect === MANUAL_DISCONNECT_VALUE) {
553
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Skipping auto-connect: user previously disconnected manually");
554
+ return;
555
+ }
556
+ } catch (error) {
557
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to check manual disconnect flag", { error });
558
+ }
559
+ this.emit("connect_start", {
560
+ source: "auto-connect",
561
+ providerType: "injected"
562
+ });
563
+ try {
564
+ if (!this.phantom.extension?.isInstalled?.()) {
565
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Phantom wallet extension not found for auto-connect");
566
+ this.emit("connect_error", {
567
+ error: "Phantom wallet not found",
568
+ source: "auto-connect"
569
+ });
570
+ return;
571
+ }
572
+ const connectedAddresses = [];
573
+ if (this.addressTypes.includes(AddressType4.solana)) {
574
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting Solana auto-connect");
575
+ try {
576
+ const publicKey = await this.phantom.solana.connect({ onlyIfTrusted: true });
577
+ if (publicKey) {
578
+ connectedAddresses.push({
579
+ addressType: AddressType4.solana,
580
+ address: publicKey
581
+ });
582
+ debug.info(DebugCategory.INJECTED_PROVIDER, "Solana auto-connected successfully", { address: publicKey });
583
+ }
584
+ } catch (err) {
585
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Solana auto-connect failed (expected if not trusted)", { error: err });
586
+ }
587
+ }
588
+ if (this.addressTypes.includes(AddressType4.ethereum)) {
589
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting Ethereum auto-connect");
590
+ try {
591
+ const accounts = await this.phantom.ethereum.connect({ onlyIfTrusted: true });
592
+ if (accounts && accounts.length > 0) {
593
+ connectedAddresses.push(
594
+ ...accounts.map((address) => ({
595
+ addressType: AddressType4.ethereum,
596
+ address
597
+ }))
598
+ );
599
+ debug.info(DebugCategory.INJECTED_PROVIDER, "Ethereum auto-connected successfully", { addresses: accounts });
600
+ }
601
+ } catch (err) {
602
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum auto-connect failed (expected if not trusted)", { error: err });
603
+ }
604
+ }
605
+ if (connectedAddresses.length === 0) {
606
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Auto-connect failed: no trusted connections available");
607
+ this.emit("connect_error", {
608
+ error: "No trusted connections available",
609
+ source: "auto-connect"
610
+ });
611
+ return;
612
+ }
613
+ this.addresses = connectedAddresses;
614
+ this.connected = true;
615
+ const authUserId = await this.getAuthUserId("auto-connect");
616
+ this.emit("connect", {
617
+ addresses: this.addresses,
618
+ source: "auto-connect",
619
+ authUserId
620
+ });
621
+ debug.info(DebugCategory.INJECTED_PROVIDER, "Auto-connect successful", {
622
+ addressCount: connectedAddresses.length,
623
+ addresses: connectedAddresses.map((addr) => ({ type: addr.addressType, address: addr.address.substring(0, 8) + "..." })),
624
+ authUserId
625
+ });
626
+ } catch (error) {
627
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Auto-connect failed with error", {
628
+ error: error instanceof Error ? error.message : String(error)
629
+ });
630
+ this.emit("connect_error", {
631
+ error: error instanceof Error ? error.message : "Auto-connect failed",
632
+ source: "auto-connect"
633
+ });
634
+ }
635
+ }
492
636
  getAddresses() {
493
637
  return this.addresses;
494
638
  }
@@ -512,6 +656,27 @@ var InjectedProvider = class {
512
656
  debug.log(DebugCategory.INJECTED_PROVIDER, "Getting supported autoConfirm chains");
513
657
  return await this.phantom.autoConfirm.autoConfirmSupportedChains();
514
658
  }
659
+ /**
660
+ * Helper method to get authUserId from window.phantom.app.getUser()
661
+ * Returns undefined if the method is not available or fails
662
+ */
663
+ async getAuthUserId(context) {
664
+ try {
665
+ if (window.phantom?.app?.getUser) {
666
+ const userInfo = await window.phantom.app.getUser();
667
+ const authUserId = userInfo?.authUserId;
668
+ if (authUserId) {
669
+ debug.log(DebugCategory.INJECTED_PROVIDER, `Retrieved authUserId from window.phantom.app.getUser() during ${context}`, {
670
+ authUserId
671
+ });
672
+ }
673
+ return authUserId;
674
+ }
675
+ } catch (error) {
676
+ debug.log(DebugCategory.INJECTED_PROVIDER, `Failed to get user info during ${context} (method may not be supported)`, { error });
677
+ }
678
+ return void 0;
679
+ }
515
680
  // Event management methods - implementing unified event interface
516
681
  on(event, callback) {
517
682
  debug.log(DebugCategory.INJECTED_PROVIDER, "Adding event listener", { event });
@@ -552,98 +717,108 @@ var InjectedProvider = class {
552
717
  }
553
718
  setupBrowserInjectedEvents() {
554
719
  debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up browser-injected-sdk event listeners");
555
- if (this.addressTypes.includes(AddressType3.solana)) {
720
+ if (this.addressTypes.includes(AddressType4.solana)) {
556
721
  this.setupSolanaEvents();
557
722
  }
558
- if (this.addressTypes.includes(AddressType3.ethereum)) {
723
+ if (this.addressTypes.includes(AddressType4.ethereum)) {
559
724
  this.setupEthereumEvents();
560
725
  }
561
726
  }
562
727
  setupSolanaEvents() {
563
728
  debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up Solana event listeners");
564
- const handleSolanaConnect = (publicKey) => {
729
+ const handleSolanaConnect = async (publicKey) => {
565
730
  debug.log(DebugCategory.INJECTED_PROVIDER, "Solana connect event received", { publicKey });
566
- const solanaAddress = { addressType: AddressType3.solana, address: publicKey };
567
- if (!this.addresses.find((addr) => addr.addressType === AddressType3.solana)) {
731
+ const solanaAddress = { addressType: AddressType4.solana, address: publicKey };
732
+ if (!this.addresses.find((addr) => addr.addressType === AddressType4.solana)) {
568
733
  this.addresses.push(solanaAddress);
569
734
  }
570
735
  this.connected = true;
736
+ const authUserId = await this.getAuthUserId("Solana connect event");
571
737
  this.emit("connect", {
572
738
  addresses: this.addresses,
573
- source: "injected-extension"
739
+ source: "injected-extension",
740
+ authUserId
574
741
  });
575
742
  };
576
743
  const handleSolanaDisconnect = () => {
577
744
  debug.log(DebugCategory.INJECTED_PROVIDER, "Solana disconnect event received");
578
- this.addresses = this.addresses.filter((addr) => addr.addressType !== AddressType3.solana);
579
- this.connected = this.addresses.length > 0;
745
+ this.addresses = this.addresses.filter((addr) => addr.addressType !== AddressType4.solana);
746
+ this.connected = false;
580
747
  this.emit("disconnect", {
581
748
  source: "injected-extension"
582
749
  });
583
750
  };
584
- const handleSolanaAccountChanged = (publicKey) => {
751
+ const handleSolanaAccountChanged = async (publicKey) => {
585
752
  debug.log(DebugCategory.INJECTED_PROVIDER, "Solana account changed event received", { publicKey });
586
- const solanaIndex = this.addresses.findIndex((addr) => addr.addressType === AddressType3.solana);
753
+ const solanaIndex = this.addresses.findIndex((addr) => addr.addressType === AddressType4.solana);
587
754
  if (solanaIndex >= 0) {
588
- this.addresses[solanaIndex] = { addressType: AddressType3.solana, address: publicKey };
755
+ this.addresses[solanaIndex] = { addressType: AddressType4.solana, address: publicKey };
589
756
  } else {
590
- this.addresses.push({ addressType: AddressType3.solana, address: publicKey });
757
+ this.addresses.push({ addressType: AddressType4.solana, address: publicKey });
591
758
  }
759
+ const authUserId = await this.getAuthUserId("Solana account changed event");
592
760
  this.emit("connect", {
593
761
  addresses: this.addresses,
594
- source: "injected-extension-account-change"
762
+ source: "injected-extension-account-change",
763
+ authUserId
595
764
  });
596
765
  };
597
766
  const cleanupConnect = this.phantom.solana.addEventListener("connect", handleSolanaConnect);
598
767
  const cleanupDisconnect = this.phantom.solana.addEventListener("disconnect", handleSolanaDisconnect);
599
- const cleanupAccountChanged = this.phantom.solana.addEventListener(
600
- "accountChanged",
601
- handleSolanaAccountChanged
602
- );
768
+ const cleanupAccountChanged = this.phantom.solana.addEventListener("accountChanged", handleSolanaAccountChanged);
603
769
  this.browserInjectedCleanupFunctions.push(cleanupConnect, cleanupDisconnect, cleanupAccountChanged);
604
770
  }
605
771
  setupEthereumEvents() {
606
772
  debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up Ethereum event listeners");
607
- const handleEthereumConnect = (accounts) => {
773
+ const handleEthereumConnect = async (accounts) => {
608
774
  debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum connect event received", { accounts });
609
- this.addresses = this.addresses.filter((addr) => addr.addressType !== AddressType3.ethereum);
775
+ this.addresses = this.addresses.filter((addr) => addr.addressType !== AddressType4.ethereum);
610
776
  if (accounts && accounts.length > 0) {
611
777
  this.addresses.push(
612
778
  ...accounts.map((address) => ({
613
- addressType: AddressType3.ethereum,
779
+ addressType: AddressType4.ethereum,
614
780
  address
615
781
  }))
616
782
  );
617
783
  }
618
784
  this.connected = this.addresses.length > 0;
785
+ const authUserId = await this.getAuthUserId("Ethereum connect event");
619
786
  this.emit("connect", {
620
787
  addresses: this.addresses,
621
- source: "injected-extension"
788
+ source: "injected-extension",
789
+ authUserId
622
790
  });
623
791
  };
624
792
  const handleEthereumDisconnect = () => {
625
793
  debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum disconnect event received");
626
- this.addresses = this.addresses.filter((addr) => addr.addressType !== AddressType3.ethereum);
627
- this.connected = this.addresses.length > 0;
794
+ this.addresses = this.addresses.filter((addr) => addr.addressType !== AddressType4.ethereum);
795
+ this.connected = false;
628
796
  this.emit("disconnect", {
629
797
  source: "injected-extension"
630
798
  });
631
799
  };
632
- const handleEthereumAccountsChanged = (accounts) => {
800
+ const handleEthereumAccountsChanged = async (accounts) => {
633
801
  debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum accounts changed event received", { accounts });
634
- this.addresses = this.addresses.filter((addr) => addr.addressType !== AddressType3.ethereum);
802
+ this.addresses = this.addresses.filter((addr) => addr.addressType !== AddressType4.ethereum);
635
803
  if (accounts && accounts.length > 0) {
636
804
  this.addresses.push(
637
805
  ...accounts.map((address) => ({
638
- addressType: AddressType3.ethereum,
806
+ addressType: AddressType4.ethereum,
639
807
  address
640
808
  }))
641
809
  );
810
+ const authUserId = await this.getAuthUserId("Ethereum accounts changed event");
811
+ this.emit("connect", {
812
+ addresses: this.addresses,
813
+ source: "injected-extension-account-change",
814
+ authUserId
815
+ });
816
+ } else {
817
+ this.connected = false;
818
+ this.emit("disconnect", {
819
+ source: "injected-extension-account-change"
820
+ });
642
821
  }
643
- this.emit("connect", {
644
- addresses: this.addresses,
645
- source: "injected-extension-account-change"
646
- });
647
822
  };
648
823
  const cleanupConnect = this.phantom.ethereum.addEventListener("connect", handleEthereumConnect);
649
824
  const cleanupDisconnect = this.phantom.ethereum.addEventListener("disconnect", handleEthereumDisconnect);
@@ -656,7 +831,7 @@ var InjectedProvider = class {
656
831
  createCallbacks() {
657
832
  return {
658
833
  connect: async () => {
659
- const result = await this.connect();
834
+ const result = await this.connect({ provider: "injected" });
660
835
  return result.addresses;
661
836
  },
662
837
  disconnect: async () => {
@@ -761,6 +936,47 @@ var BrowserStorage = class {
761
936
  };
762
937
  });
763
938
  }
939
+ async getShouldClearPreviousSession() {
940
+ debug.log(DebugCategory.STORAGE, "Getting shouldClearPreviousSession flag from IndexedDB");
941
+ const db = await this.getDB();
942
+ return new Promise((resolve, reject) => {
943
+ const transaction = db.transaction([this.storeName], "readonly");
944
+ const store = transaction.objectStore(this.storeName);
945
+ const request = store.get("shouldClearPreviousSession");
946
+ request.onsuccess = () => {
947
+ const shouldClear = request.result ?? false;
948
+ debug.log(DebugCategory.STORAGE, "Retrieved shouldClearPreviousSession flag from IndexedDB", {
949
+ shouldClear
950
+ });
951
+ resolve(shouldClear);
952
+ };
953
+ request.onerror = () => {
954
+ debug.error(DebugCategory.STORAGE, "Failed to get shouldClearPreviousSession flag from IndexedDB", {
955
+ error: request.error
956
+ });
957
+ reject(request.error);
958
+ };
959
+ });
960
+ }
961
+ async setShouldClearPreviousSession(should) {
962
+ debug.log(DebugCategory.STORAGE, "Setting shouldClearPreviousSession flag in IndexedDB", { should });
963
+ const db = await this.getDB();
964
+ return new Promise((resolve, reject) => {
965
+ const transaction = db.transaction([this.storeName], "readwrite");
966
+ const store = transaction.objectStore(this.storeName);
967
+ const request = store.put(should, "shouldClearPreviousSession");
968
+ request.onsuccess = () => {
969
+ debug.log(DebugCategory.STORAGE, "Successfully set shouldClearPreviousSession flag in IndexedDB");
970
+ resolve();
971
+ };
972
+ request.onerror = () => {
973
+ debug.error(DebugCategory.STORAGE, "Failed to set shouldClearPreviousSession flag in IndexedDB", {
974
+ error: request.error
975
+ });
976
+ reject(request.error);
977
+ };
978
+ });
979
+ }
764
980
  };
765
981
 
766
982
  // src/providers/embedded/adapters/url-params.ts
@@ -772,15 +988,160 @@ var BrowserURLParamsAccessor = class {
772
988
  };
773
989
  var browserUrlParamsAccessor = new BrowserURLParamsAccessor();
774
990
 
775
- // src/constants.ts
776
- var DEFAULT_AUTH_URL = "https://connect.phantom.app";
777
- var DEFAULT_WALLET_API_URL = "https://api.phantom.app/v1/wallets";
991
+ // src/providers/embedded/adapters/auth.ts
992
+ import { DEFAULT_AUTH_URL } from "@phantom/constants";
993
+
994
+ // src/utils/browser-detection.ts
995
+ function parseBrowserFromUserAgent(userAgent, hasBraveAPI) {
996
+ let name = "unknown";
997
+ let version = "unknown";
998
+ if (!userAgent || typeof userAgent !== "string") {
999
+ return { name, version, userAgent: "unknown" };
1000
+ }
1001
+ try {
1002
+ if (userAgent.includes("Edg/")) {
1003
+ name = "edge";
1004
+ const match = userAgent.match(/Edg\/([0-9]+(?:\.[0-9]+)*)/);
1005
+ if (match)
1006
+ version = match[1].split(".")[0];
1007
+ } else if (userAgent.includes("OPR/") || userAgent.includes("Opera/")) {
1008
+ name = "opera";
1009
+ const match = userAgent.match(/(?:OPR|Opera)\/([0-9]+(?:\.[0-9]+)*)/);
1010
+ if (match)
1011
+ version = match[1].split(".")[0];
1012
+ } else if (userAgent.includes("SamsungBrowser/")) {
1013
+ name = "samsung";
1014
+ const match = userAgent.match(/SamsungBrowser\/([0-9]+(?:\.[0-9]+)*)/);
1015
+ if (match)
1016
+ version = match[1].split(".")[0];
1017
+ } else if (userAgent.includes("DuckDuckGo/")) {
1018
+ name = "duckduckgo";
1019
+ const match = userAgent.match(/DuckDuckGo\/([0-9]+(?:\.[0-9]+)*)/);
1020
+ if (match)
1021
+ version = match[1].split(".")[0];
1022
+ } else if (userAgent.includes("Chrome/") && hasBraveAPI) {
1023
+ name = "brave";
1024
+ const match = userAgent.match(/Chrome\/([0-9]+(?:\.[0-9]+)*)/);
1025
+ if (match)
1026
+ version = match[1].split(".")[0];
1027
+ } else if (userAgent.includes("Mobile/") || userAgent.includes("Android")) {
1028
+ if (userAgent.includes("Chrome/")) {
1029
+ name = "chrome-mobile";
1030
+ const match = userAgent.match(/Chrome\/([0-9]+(?:\.[0-9]+)*)/);
1031
+ if (match)
1032
+ version = match[1].split(".")[0];
1033
+ } else if (userAgent.includes("Firefox/")) {
1034
+ name = "firefox-mobile";
1035
+ const match = userAgent.match(/Firefox\/([0-9]+(?:\.[0-9]+)*)/);
1036
+ if (match)
1037
+ version = match[1].split(".")[0];
1038
+ } else if (userAgent.includes("Safari/") && userAgent.includes("Mobile/")) {
1039
+ name = "safari-mobile";
1040
+ const match = userAgent.match(/Version\/([0-9]+(?:\.[0-9]+)*)/);
1041
+ if (match)
1042
+ version = match[1].split(".")[0];
1043
+ } else {
1044
+ name = "mobile";
1045
+ }
1046
+ } else if (userAgent.includes("Chrome/")) {
1047
+ name = "chrome";
1048
+ const match = userAgent.match(/Chrome\/([0-9]+(?:\.[0-9]+)*)/);
1049
+ if (match)
1050
+ version = match[1].split(".")[0];
1051
+ } else if (userAgent.includes("Firefox/")) {
1052
+ name = "firefox";
1053
+ const match = userAgent.match(/Firefox\/([0-9]+(?:\.[0-9]+)*)/);
1054
+ if (match)
1055
+ version = match[1].split(".")[0];
1056
+ } else if (userAgent.includes("Safari/") && !userAgent.includes("Chrome/")) {
1057
+ name = "safari";
1058
+ const match = userAgent.match(/Version\/([0-9]+(?:\.[0-9]+)*)/);
1059
+ if (match)
1060
+ version = match[1].split(".")[0];
1061
+ }
1062
+ if (name === "unknown") {
1063
+ const patterns = [
1064
+ { regex: /Chrome\/([0-9]+)/, name: "chrome" },
1065
+ { regex: /Firefox\/([0-9]+)/, name: "firefox" },
1066
+ { regex: /Safari\/([0-9]+)/, name: "safari" },
1067
+ { regex: /Edge\/([0-9]+)/, name: "edge" },
1068
+ { regex: /Opera\/([0-9]+)/, name: "opera" }
1069
+ ];
1070
+ for (const pattern of patterns) {
1071
+ const match = userAgent.match(pattern.regex);
1072
+ if (match) {
1073
+ name = pattern.name;
1074
+ version = match[1];
1075
+ break;
1076
+ }
1077
+ }
1078
+ }
1079
+ } catch (error) {
1080
+ }
1081
+ return { name, version, userAgent };
1082
+ }
1083
+ function detectBrowser() {
1084
+ if (typeof window === "undefined" || !window.navigator?.userAgent) {
1085
+ return { name: "unknown", version: "unknown", userAgent: "unknown" };
1086
+ }
1087
+ const userAgent = window.navigator.userAgent;
1088
+ const hasBraveAPI = !!navigator.brave;
1089
+ return parseBrowserFromUserAgent(userAgent, hasBraveAPI);
1090
+ }
1091
+ function getPlatformName() {
1092
+ const { name, version } = detectBrowser();
1093
+ return version !== "unknown" ? `${name}-v${version}` : name;
1094
+ }
1095
+ function getBrowserDisplayName() {
1096
+ const { name, version } = detectBrowser();
1097
+ const capitalizedName = name.charAt(0).toUpperCase() + name.slice(1);
1098
+ return version !== "unknown" ? `${capitalizedName} ${version}` : capitalizedName;
1099
+ }
1100
+ function isMobileDevice() {
1101
+ if (typeof window === "undefined" || !window.navigator?.userAgent) {
1102
+ return false;
1103
+ }
1104
+ const userAgent = window.navigator.userAgent.toLowerCase();
1105
+ const mobilePatterns = [
1106
+ /android/,
1107
+ /iphone|ipad|ipod/,
1108
+ /blackberry/,
1109
+ /windows phone/,
1110
+ /mobile/,
1111
+ /tablet/,
1112
+ /silk/,
1113
+ /kindle/,
1114
+ /opera mini/,
1115
+ /opera mobi/
1116
+ ];
1117
+ const isMobileUA = mobilePatterns.some((pattern) => pattern.test(userAgent));
1118
+ let isSmallScreen = false;
1119
+ try {
1120
+ isSmallScreen = window.screen.width <= 768 || window.screen.height <= 768;
1121
+ } catch (error) {
1122
+ isSmallScreen = false;
1123
+ }
1124
+ let isTouchDevice = false;
1125
+ try {
1126
+ isTouchDevice = "ontouchstart" in window || navigator.maxTouchPoints > 0;
1127
+ } catch (error) {
1128
+ isTouchDevice = false;
1129
+ }
1130
+ return isMobileUA || isSmallScreen && isTouchDevice;
1131
+ }
778
1132
 
779
1133
  // src/providers/embedded/adapters/auth.ts
780
1134
  var BrowserAuthProvider = class {
781
1135
  constructor(urlParamsAccessor) {
782
1136
  this.urlParamsAccessor = urlParamsAccessor;
783
1137
  }
1138
+ getValidatedCurrentUrl() {
1139
+ const currentUrl = window.location.href;
1140
+ if (!currentUrl.startsWith("http:") && !currentUrl.startsWith("https:")) {
1141
+ throw new Error("Invalid URL protocol - only HTTP/HTTPS URLs are supported");
1142
+ }
1143
+ return currentUrl;
1144
+ }
784
1145
  authenticate(options) {
785
1146
  return new Promise((resolve) => {
786
1147
  if ("jwtToken" in options) {
@@ -788,22 +1149,24 @@ var BrowserAuthProvider = class {
788
1149
  }
789
1150
  const phantomOptions = options;
790
1151
  debug.info(DebugCategory.PHANTOM_CONNECT_AUTH, "Starting Phantom Connect authentication", {
791
- organizationId: phantomOptions.organizationId,
792
- parentOrganizationId: phantomOptions.parentOrganizationId,
1152
+ publicKey: phantomOptions.publicKey,
793
1153
  appId: phantomOptions.appId,
794
1154
  provider: phantomOptions.provider,
795
- authUrl: phantomOptions.authUrl,
796
- hasCustomData: !!phantomOptions.customAuthData
1155
+ authUrl: phantomOptions.authUrl
797
1156
  });
798
1157
  const baseUrl = phantomOptions.authUrl || DEFAULT_AUTH_URL;
799
1158
  debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Using auth URL", { baseUrl });
800
1159
  const params = new URLSearchParams({
801
- organization_id: phantomOptions.organizationId,
802
- parent_organization_id: phantomOptions.parentOrganizationId,
1160
+ public_key: phantomOptions.publicKey,
803
1161
  app_id: phantomOptions.appId,
804
- redirect_uri: phantomOptions.redirectUrl || (typeof window !== "undefined" ? window.location.href : ""),
1162
+ redirect_uri: phantomOptions.redirectUrl || (typeof window !== "undefined" ? this.getValidatedCurrentUrl() : ""),
805
1163
  session_id: phantomOptions.sessionId,
806
- clear_previous_session: true.toString()
1164
+ // OAuth session management - defaults to allow refresh unless explicitly clearing after logout
1165
+ clear_previous_session: (phantomOptions.clearPreviousSession ?? false).toString(),
1166
+ allow_refresh: (phantomOptions.allowRefresh ?? true).toString(),
1167
+ sdk_version: "1.0.0-beta.21",
1168
+ sdk_type: "browser",
1169
+ platform: detectBrowser().name
807
1170
  });
808
1171
  if (phantomOptions.provider) {
809
1172
  debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Provider specified, will skip selection", {
@@ -814,13 +1177,8 @@ var BrowserAuthProvider = class {
814
1177
  debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "No provider specified, defaulting to Google");
815
1178
  params.append("provider", "google");
816
1179
  }
817
- if (phantomOptions.customAuthData) {
818
- debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Adding custom auth data");
819
- params.append("authData", JSON.stringify(phantomOptions.customAuthData));
820
- }
821
1180
  const authContext = {
822
- organizationId: phantomOptions.organizationId,
823
- parentOrganizationId: phantomOptions.parentOrganizationId,
1181
+ publicKey: phantomOptions.publicKey,
824
1182
  appId: phantomOptions.appId,
825
1183
  provider: phantomOptions.provider,
826
1184
  sessionId: phantomOptions.sessionId
@@ -829,6 +1187,9 @@ var BrowserAuthProvider = class {
829
1187
  debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Stored auth context in session storage", { authContext });
830
1188
  const authUrl = `${baseUrl}?${params.toString()}`;
831
1189
  debug.info(DebugCategory.PHANTOM_CONNECT_AUTH, "Redirecting to Phantom Connect", { authUrl });
1190
+ if (!authUrl.startsWith("https:") && !authUrl.startsWith("http://localhost")) {
1191
+ throw new Error("Invalid auth URL - only HTTPS URLs are allowed for authentication");
1192
+ }
832
1193
  window.location.href = authUrl;
833
1194
  resolve();
834
1195
  });
@@ -884,10 +1245,32 @@ var BrowserAuthProvider = class {
884
1245
  sessionId,
885
1246
  accountDerivationIndex: accountDerivationIndex ? parseInt(accountDerivationIndex) : void 0
886
1247
  });
1248
+ const organizationId = this.urlParamsAccessor.getParam("organization_id");
1249
+ const expiresInMs = this.urlParamsAccessor.getParam("expires_in_ms");
1250
+ const authUserId = this.urlParamsAccessor.getParam("auth_user_id");
1251
+ debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Auth redirect parameters", {
1252
+ walletId,
1253
+ organizationId,
1254
+ sessionId,
1255
+ accountDerivationIndex,
1256
+ expiresInMs,
1257
+ authUserId
1258
+ });
1259
+ if (!organizationId) {
1260
+ debug.error(DebugCategory.PHANTOM_CONNECT_AUTH, "Missing organization_id in auth response");
1261
+ throw new Error("Missing organization_id in auth response");
1262
+ }
1263
+ if (organizationId.startsWith("temp-")) {
1264
+ debug.warn(DebugCategory.PHANTOM_CONNECT_AUTH, "Received temporary organization_id, server may not be configured properly", {
1265
+ organizationId
1266
+ });
1267
+ }
887
1268
  return {
888
1269
  walletId,
889
- userInfo: context,
890
- accountDerivationIndex: accountDerivationIndex ? parseInt(accountDerivationIndex) : void 0
1270
+ organizationId,
1271
+ accountDerivationIndex: accountDerivationIndex ? parseInt(accountDerivationIndex) : 0,
1272
+ expiresInMs: expiresInMs ? parseInt(expiresInMs) : 0,
1273
+ authUserId: authUserId || void 0
891
1274
  };
892
1275
  } catch (error) {
893
1276
  sessionStorage.removeItem("phantom-auth-context");
@@ -896,6 +1279,105 @@ var BrowserAuthProvider = class {
896
1279
  }
897
1280
  };
898
1281
 
1282
+ // src/providers/embedded/adapters/phantom-app.ts
1283
+ import { isPhantomExtensionInstalled as isPhantomExtensionInstalled2 } from "@phantom/browser-injected-sdk";
1284
+
1285
+ // src/isPhantomLoginAvailable.ts
1286
+ import { isPhantomExtensionInstalled } from "@phantom/browser-injected-sdk";
1287
+ async function isPhantomLoginAvailable(timeoutMs = 3e3) {
1288
+ const extensionInstalled = await waitForExtension(timeoutMs);
1289
+ if (!extensionInstalled) {
1290
+ return false;
1291
+ }
1292
+ try {
1293
+ if (!window.phantom?.app?.features || typeof window.phantom.app.features !== "function") {
1294
+ return false;
1295
+ }
1296
+ const response = await window.phantom.app.features();
1297
+ if (!Array.isArray(response.features)) {
1298
+ return false;
1299
+ }
1300
+ return response.features.includes("phantom_login");
1301
+ } catch (error) {
1302
+ console.error("Error checking Phantom extension features", error);
1303
+ return false;
1304
+ }
1305
+ }
1306
+ async function waitForExtension(timeoutMs) {
1307
+ return new Promise((resolve) => {
1308
+ const startTime = Date.now();
1309
+ const checkInterval = 100;
1310
+ const checkForExtension = () => {
1311
+ try {
1312
+ if (isPhantomExtensionInstalled()) {
1313
+ resolve(true);
1314
+ return;
1315
+ }
1316
+ } catch (error) {
1317
+ }
1318
+ const elapsed = Date.now() - startTime;
1319
+ if (elapsed >= timeoutMs) {
1320
+ resolve(false);
1321
+ return;
1322
+ }
1323
+ setTimeout(checkForExtension, checkInterval);
1324
+ };
1325
+ checkForExtension();
1326
+ });
1327
+ }
1328
+
1329
+ // src/providers/embedded/adapters/phantom-app.ts
1330
+ var BrowserPhantomAppProvider = class {
1331
+ /**
1332
+ * Check if the Phantom extension is installed in the browser
1333
+ */
1334
+ isAvailable() {
1335
+ return isPhantomExtensionInstalled2();
1336
+ }
1337
+ /**
1338
+ * Authenticate using the Phantom browser extension
1339
+ */
1340
+ async authenticate(options) {
1341
+ if (!this.isAvailable()) {
1342
+ throw new Error(
1343
+ "Phantom extension is not installed. Please install the Phantom browser extension to use this authentication method."
1344
+ );
1345
+ }
1346
+ const loginAvailable = await isPhantomLoginAvailable();
1347
+ if (!loginAvailable) {
1348
+ throw new Error(
1349
+ "Phantom Login is not available. Please update your Phantom extension to use this authentication method."
1350
+ );
1351
+ }
1352
+ try {
1353
+ if (!window.phantom?.app?.login) {
1354
+ throw new Error("Phantom extension login method not found");
1355
+ }
1356
+ const result = await window.phantom.app.login({
1357
+ publicKey: options.publicKey,
1358
+ appId: options.appId,
1359
+ sessionId: options.sessionId
1360
+ });
1361
+ if (!result || !result.walletId || !result.organizationId) {
1362
+ throw new Error("Invalid authentication response from Phantom extension");
1363
+ }
1364
+ return {
1365
+ walletId: result.walletId,
1366
+ organizationId: result.organizationId,
1367
+ provider: "phantom",
1368
+ accountDerivationIndex: result.accountDerivationIndex ?? 0,
1369
+ expiresInMs: result.expiresInMs ?? 0,
1370
+ authUserId: result.authUserId
1371
+ };
1372
+ } catch (error) {
1373
+ if (error instanceof Error) {
1374
+ throw error;
1375
+ }
1376
+ throw new Error(`Phantom extension authentication failed: ${String(error)}`);
1377
+ }
1378
+ }
1379
+ };
1380
+
899
1381
  // src/providers/embedded/adapters/logger.ts
900
1382
  var BrowserLogger = class {
901
1383
  info(category, message, data) {
@@ -912,131 +1394,38 @@ var BrowserLogger = class {
912
1394
  }
913
1395
  };
914
1396
 
915
- // src/utils/browser-detection.ts
916
- function parseBrowserFromUserAgent(userAgent, hasBraveAPI) {
917
- let name = "unknown";
918
- let version = "unknown";
919
- if (!userAgent || typeof userAgent !== "string") {
920
- return { name, version };
921
- }
922
- try {
923
- if (userAgent.includes("Edg/")) {
924
- name = "edge";
925
- const match = userAgent.match(/Edg\/([0-9]+(?:\.[0-9]+)*)/);
926
- if (match)
927
- version = match[1].split(".")[0];
928
- } else if (userAgent.includes("OPR/") || userAgent.includes("Opera/")) {
929
- name = "opera";
930
- const match = userAgent.match(/(?:OPR|Opera)\/([0-9]+(?:\.[0-9]+)*)/);
931
- if (match)
932
- version = match[1].split(".")[0];
933
- } else if (userAgent.includes("SamsungBrowser/")) {
934
- name = "samsung";
935
- const match = userAgent.match(/SamsungBrowser\/([0-9]+(?:\.[0-9]+)*)/);
936
- if (match)
937
- version = match[1].split(".")[0];
938
- } else if (userAgent.includes("DuckDuckGo/")) {
939
- name = "duckduckgo";
940
- const match = userAgent.match(/DuckDuckGo\/([0-9]+(?:\.[0-9]+)*)/);
941
- if (match)
942
- version = match[1].split(".")[0];
943
- } else if (userAgent.includes("Chrome/") && hasBraveAPI) {
944
- name = "brave";
945
- const match = userAgent.match(/Chrome\/([0-9]+(?:\.[0-9]+)*)/);
946
- if (match)
947
- version = match[1].split(".")[0];
948
- } else if (userAgent.includes("Mobile/") || userAgent.includes("Android")) {
949
- if (userAgent.includes("Chrome/")) {
950
- name = "chrome-mobile";
951
- const match = userAgent.match(/Chrome\/([0-9]+(?:\.[0-9]+)*)/);
952
- if (match)
953
- version = match[1].split(".")[0];
954
- } else if (userAgent.includes("Firefox/")) {
955
- name = "firefox-mobile";
956
- const match = userAgent.match(/Firefox\/([0-9]+(?:\.[0-9]+)*)/);
957
- if (match)
958
- version = match[1].split(".")[0];
959
- } else if (userAgent.includes("Safari/") && userAgent.includes("Mobile/")) {
960
- name = "safari-mobile";
961
- const match = userAgent.match(/Version\/([0-9]+(?:\.[0-9]+)*)/);
962
- if (match)
963
- version = match[1].split(".")[0];
964
- } else {
965
- name = "mobile";
966
- }
967
- } else if (userAgent.includes("Chrome/")) {
968
- name = "chrome";
969
- const match = userAgent.match(/Chrome\/([0-9]+(?:\.[0-9]+)*)/);
970
- if (match)
971
- version = match[1].split(".")[0];
972
- } else if (userAgent.includes("Firefox/")) {
973
- name = "firefox";
974
- const match = userAgent.match(/Firefox\/([0-9]+(?:\.[0-9]+)*)/);
975
- if (match)
976
- version = match[1].split(".")[0];
977
- } else if (userAgent.includes("Safari/") && !userAgent.includes("Chrome/")) {
978
- name = "safari";
979
- const match = userAgent.match(/Version\/([0-9]+(?:\.[0-9]+)*)/);
980
- if (match)
981
- version = match[1].split(".")[0];
982
- }
983
- if (name === "unknown") {
984
- const patterns = [
985
- { regex: /Chrome\/([0-9]+)/, name: "chrome" },
986
- { regex: /Firefox\/([0-9]+)/, name: "firefox" },
987
- { regex: /Safari\/([0-9]+)/, name: "safari" },
988
- { regex: /Edge\/([0-9]+)/, name: "edge" },
989
- { regex: /Opera\/([0-9]+)/, name: "opera" }
990
- ];
991
- for (const pattern of patterns) {
992
- const match = userAgent.match(pattern.regex);
993
- if (match) {
994
- name = pattern.name;
995
- version = match[1];
996
- break;
997
- }
998
- }
999
- }
1000
- } catch (error) {
1001
- }
1002
- return { name, version };
1003
- }
1004
- function detectBrowser() {
1005
- if (typeof window === "undefined" || !window.navigator?.userAgent) {
1006
- return { name: "unknown", version: "unknown" };
1007
- }
1008
- const userAgent = window.navigator.userAgent;
1009
- const hasBraveAPI = !!navigator.brave;
1010
- return parseBrowserFromUserAgent(userAgent, hasBraveAPI);
1011
- }
1012
- function getPlatformName() {
1013
- const { name, version } = detectBrowser();
1014
- return version !== "unknown" ? `${name}-v${version}` : name;
1015
- }
1016
- function getBrowserDisplayName() {
1017
- const { name, version } = detectBrowser();
1018
- const capitalizedName = name.charAt(0).toUpperCase() + name.slice(1);
1019
- return version !== "unknown" ? `${capitalizedName} ${version}` : capitalizedName;
1020
- }
1021
-
1022
1397
  // src/providers/embedded/index.ts
1398
+ import { ANALYTICS_HEADERS } from "@phantom/constants";
1023
1399
  var EmbeddedProvider = class extends CoreEmbeddedProvider {
1024
1400
  constructor(config) {
1025
1401
  debug.log(DebugCategory.EMBEDDED_PROVIDER, "Initializing Browser EmbeddedProvider", { config });
1026
1402
  const urlParamsAccessor = new BrowserURLParamsAccessor();
1027
1403
  const stamper = new IndexedDbStamper({
1028
- dbName: `phantom-embedded-sdk-${config.organizationId}`,
1404
+ dbName: `phantom-embedded-sdk-${config.appId}`,
1029
1405
  storeName: "crypto-keys",
1030
1406
  keyName: "signing-key"
1031
1407
  });
1032
1408
  const platformName = getPlatformName();
1409
+ const { name: browserName, version } = detectBrowser();
1033
1410
  const platform = {
1034
1411
  storage: new BrowserStorage(),
1035
1412
  authProvider: new BrowserAuthProvider(urlParamsAccessor),
1413
+ phantomAppProvider: new BrowserPhantomAppProvider(),
1036
1414
  urlParamsAccessor,
1037
1415
  stamper,
1038
- name: platformName
1416
+ name: platformName,
1039
1417
  // Use detected browser name and version for identification
1418
+ analyticsHeaders: {
1419
+ [ANALYTICS_HEADERS.SDK_TYPE]: "browser",
1420
+ [ANALYTICS_HEADERS.PLATFORM]: browserName,
1421
+ // firefox, chrome, safari, etc.
1422
+ [ANALYTICS_HEADERS.PLATFORM_VERSION]: version,
1423
+ // Full user agent for more detailed info
1424
+ [ANALYTICS_HEADERS.APP_ID]: config.appId,
1425
+ [ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
1426
+ [ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.21"
1427
+ // Replaced at build time
1428
+ }
1040
1429
  };
1041
1430
  debug.log(DebugCategory.EMBEDDED_PROVIDER, "Detected platform", { platformName });
1042
1431
  const logger = new BrowserLogger();
@@ -1045,6 +1434,26 @@ var EmbeddedProvider = class extends CoreEmbeddedProvider {
1045
1434
  }
1046
1435
  };
1047
1436
 
1437
+ // src/ProviderManager.ts
1438
+ import { DEFAULT_WALLET_API_URL, DEFAULT_EMBEDDED_WALLET_TYPE, DEFAULT_AUTH_URL as DEFAULT_AUTH_URL2 } from "@phantom/constants";
1439
+
1440
+ // src/utils/auth-callback.ts
1441
+ function isAuthFailureCallback(searchParams) {
1442
+ if (typeof window === "undefined" && !searchParams)
1443
+ return false;
1444
+ const params = searchParams || new URLSearchParams(window.location.search);
1445
+ const responseType = params.get("response_type");
1446
+ const sessionId = params.get("session_id");
1447
+ return responseType === "failure" && !!sessionId;
1448
+ }
1449
+ function isAuthCallbackUrl(searchParams) {
1450
+ if (typeof window === "undefined" && !searchParams)
1451
+ return false;
1452
+ const params = searchParams || new URLSearchParams(window.location.search);
1453
+ const sessionId = params.get("session_id");
1454
+ return !!(sessionId && (params.has("response_type") || params.has("wallet_id")));
1455
+ }
1456
+
1048
1457
  // src/ProviderManager.ts
1049
1458
  var ProviderManager = class {
1050
1459
  // Track which providers have forwarding set up
@@ -1052,7 +1461,6 @@ var ProviderManager = class {
1052
1461
  this.providers = /* @__PURE__ */ new Map();
1053
1462
  this.currentProvider = null;
1054
1463
  this.currentProviderKey = null;
1055
- this.walletId = null;
1056
1464
  // Event management for forwarding provider events
1057
1465
  this.eventListeners = /* @__PURE__ */ new Map();
1058
1466
  this.providerForwardingSetup = /* @__PURE__ */ new WeakSet();
@@ -1064,6 +1472,15 @@ var ProviderManager = class {
1064
1472
  currentProviderKey: this.currentProviderKey
1065
1473
  });
1066
1474
  }
1475
+ getValidatedCurrentUrl() {
1476
+ if (typeof window === "undefined")
1477
+ return "";
1478
+ const currentUrl = window.location.href;
1479
+ if (!currentUrl.startsWith("http:") && !currentUrl.startsWith("https:")) {
1480
+ throw new Error("Invalid URL protocol - only HTTP/HTTPS URLs are supported");
1481
+ }
1482
+ return currentUrl;
1483
+ }
1067
1484
  /**
1068
1485
  * Switch to a different provider type
1069
1486
  */
@@ -1079,7 +1496,6 @@ var ProviderManager = class {
1079
1496
  }
1080
1497
  this.currentProvider = this.providers.get(key);
1081
1498
  this.currentProviderKey = key;
1082
- this.walletId = null;
1083
1499
  this.ensureProviderEventForwarding();
1084
1500
  return this.currentProvider;
1085
1501
  }
@@ -1095,7 +1511,8 @@ var ProviderManager = class {
1095
1511
  getCurrentProviderInfo() {
1096
1512
  if (!this.currentProviderKey)
1097
1513
  return null;
1098
- const [type, embeddedWalletType] = this.currentProviderKey.split("-");
1514
+ const parts = this.currentProviderKey.split("-");
1515
+ const [type, embeddedWalletType] = parts;
1099
1516
  return {
1100
1517
  type,
1101
1518
  embeddedWalletType
@@ -1103,27 +1520,51 @@ var ProviderManager = class {
1103
1520
  }
1104
1521
  /**
1105
1522
  * Connect using the current provider
1523
+ * Automatically switches provider based on authOptions.provider
1106
1524
  */
1107
1525
  async connect(authOptions) {
1108
1526
  debug.info(DebugCategory.PROVIDER_MANAGER, "Starting connection", {
1109
1527
  currentProviderKey: this.currentProviderKey,
1110
- authOptions: authOptions ? { provider: authOptions.provider, hasJwtToken: !!authOptions.jwtToken } : void 0
1528
+ authOptions: { provider: authOptions.provider, hasJwtToken: !!authOptions.jwtToken }
1111
1529
  });
1530
+ const requestedProvider = authOptions.provider;
1531
+ let targetProviderType = null;
1532
+ if (requestedProvider === "injected") {
1533
+ targetProviderType = "injected";
1534
+ } else if (["google", "apple", "jwt", "phantom"].includes(requestedProvider)) {
1535
+ targetProviderType = "embedded";
1536
+ }
1537
+ if (targetProviderType) {
1538
+ const currentInfo = this.getCurrentProviderInfo();
1539
+ if (currentInfo?.type !== targetProviderType) {
1540
+ debug.log(DebugCategory.PROVIDER_MANAGER, "Auto-switching provider based on auth options", {
1541
+ from: currentInfo?.type,
1542
+ to: targetProviderType,
1543
+ requestedProvider
1544
+ });
1545
+ const switchOptions = {};
1546
+ if (targetProviderType === "embedded") {
1547
+ switchOptions.embeddedWalletType = currentInfo?.embeddedWalletType || this.config.embeddedWalletType;
1548
+ }
1549
+ this.switchProvider(targetProviderType, switchOptions);
1550
+ }
1551
+ }
1112
1552
  if (!this.currentProvider) {
1113
1553
  debug.error(DebugCategory.PROVIDER_MANAGER, "No provider selected");
1114
1554
  throw new Error("No provider selected");
1115
1555
  }
1116
1556
  debug.log(DebugCategory.PROVIDER_MANAGER, "Delegating to provider connect method");
1117
1557
  const result = await this.currentProvider.connect(authOptions);
1118
- this.walletId = result.walletId || null;
1558
+ const providerInfo = this.getCurrentProviderInfo();
1559
+ result.providerType = providerInfo?.type;
1119
1560
  debug.log(DebugCategory.PROVIDER_MANAGER, "Connection successful, saving preferences", {
1120
- walletId: this.walletId,
1121
- addressCount: result.addresses?.length || 0
1561
+ addressCount: result.addresses?.length || 0,
1562
+ providerType: result.providerType
1122
1563
  });
1123
1564
  this.saveProviderPreference();
1124
1565
  debug.info(DebugCategory.PROVIDER_MANAGER, "Connect completed", {
1125
- walletId: this.walletId,
1126
- addresses: result.addresses
1566
+ addresses: result.addresses,
1567
+ providerType: result.providerType
1127
1568
  });
1128
1569
  return result;
1129
1570
  }
@@ -1134,7 +1575,6 @@ var ProviderManager = class {
1134
1575
  if (!this.currentProvider)
1135
1576
  return;
1136
1577
  await this.currentProvider.disconnect();
1137
- this.walletId = null;
1138
1578
  }
1139
1579
  /**
1140
1580
  * Get addresses from current provider
@@ -1152,10 +1592,69 @@ var ProviderManager = class {
1152
1592
  return this.currentProvider?.isConnected() ?? false;
1153
1593
  }
1154
1594
  /**
1155
- * Get current wallet ID
1595
+ * Attempt auto-connect with fallback strategy
1596
+ * Tries embedded provider first if it exists, then injected provider
1597
+ * Returns true if any provider successfully connected
1156
1598
  */
1157
- getWalletId() {
1158
- return this.walletId;
1599
+ async autoConnect() {
1600
+ debug.log(DebugCategory.PROVIDER_MANAGER, "Starting auto-connect with fallback strategy");
1601
+ if (isAuthFailureCallback()) {
1602
+ debug.warn(DebugCategory.PROVIDER_MANAGER, "Auth failure detected in URL, skipping autoConnect fallback");
1603
+ return false;
1604
+ }
1605
+ const embeddedWalletType = this.config.embeddedWalletType || "user-wallet";
1606
+ const embeddedKey = this.getProviderKey("embedded", embeddedWalletType);
1607
+ if (this.providers.has(embeddedKey)) {
1608
+ debug.log(DebugCategory.PROVIDER_MANAGER, "Trying auto-connect with existing embedded provider");
1609
+ const embeddedProvider = this.providers.get(embeddedKey);
1610
+ try {
1611
+ const previousProvider = this.currentProvider;
1612
+ const previousKey = this.currentProviderKey;
1613
+ this.currentProvider = embeddedProvider;
1614
+ this.currentProviderKey = embeddedKey;
1615
+ this.ensureProviderEventForwarding();
1616
+ await embeddedProvider.autoConnect();
1617
+ if (embeddedProvider.isConnected()) {
1618
+ debug.info(DebugCategory.PROVIDER_MANAGER, "Embedded auto-connect successful");
1619
+ this.saveProviderPreference();
1620
+ return true;
1621
+ } else {
1622
+ debug.log(DebugCategory.PROVIDER_MANAGER, "Embedded provider did not connect, restoring previous provider");
1623
+ this.currentProvider = previousProvider;
1624
+ this.currentProviderKey = previousKey;
1625
+ }
1626
+ } catch (error) {
1627
+ debug.log(DebugCategory.PROVIDER_MANAGER, "Embedded auto-connect failed", {
1628
+ error: error.message
1629
+ });
1630
+ if (isAuthCallbackUrl()) {
1631
+ debug.log(DebugCategory.PROVIDER_MANAGER, "In auth callback URL, not attempting injected fallback");
1632
+ return false;
1633
+ }
1634
+ }
1635
+ }
1636
+ const injectedKey = this.getProviderKey("injected");
1637
+ if (this.providers.has(injectedKey)) {
1638
+ debug.log(DebugCategory.PROVIDER_MANAGER, "Trying auto-connect with existing injected provider");
1639
+ const injectedProvider = this.providers.get(injectedKey);
1640
+ try {
1641
+ this.currentProvider = injectedProvider;
1642
+ this.currentProviderKey = injectedKey;
1643
+ this.ensureProviderEventForwarding();
1644
+ await injectedProvider.autoConnect();
1645
+ if (injectedProvider.isConnected()) {
1646
+ debug.info(DebugCategory.PROVIDER_MANAGER, "Injected auto-connect successful");
1647
+ this.saveProviderPreference();
1648
+ return true;
1649
+ }
1650
+ } catch (error) {
1651
+ debug.log(DebugCategory.PROVIDER_MANAGER, "Injected auto-connect failed", {
1652
+ error: error.message
1653
+ });
1654
+ }
1655
+ }
1656
+ debug.log(DebugCategory.PROVIDER_MANAGER, "Auto-connect failed for all existing providers");
1657
+ return false;
1159
1658
  }
1160
1659
  /**
1161
1660
  * Add event listener - stores callback and ensures current provider forwards events to ProviderManager
@@ -1238,12 +1737,22 @@ var ProviderManager = class {
1238
1737
  }
1239
1738
  /**
1240
1739
  * Set default provider based on initial config
1740
+ * Creates both embedded and injected providers for autoConnect fallback
1241
1741
  */
1242
1742
  setDefaultProvider() {
1243
1743
  const defaultType = this.config.providerType || "embedded";
1244
- const defaultEmbeddedType = this.config.embeddedWalletType || "app-wallet";
1245
- this.createProvider(defaultType, defaultEmbeddedType);
1246
- this.switchProvider(defaultType, { embeddedWalletType: defaultEmbeddedType });
1744
+ const defaultEmbeddedType = this.config.embeddedWalletType || "user-wallet";
1745
+ if (this.config.appId) {
1746
+ debug.log(DebugCategory.PROVIDER_MANAGER, "Creating embedded provider");
1747
+ this.createProvider("embedded", defaultEmbeddedType);
1748
+ }
1749
+ debug.log(DebugCategory.PROVIDER_MANAGER, "Creating injected provider");
1750
+ this.createProvider("injected");
1751
+ const switchOptions = {};
1752
+ if (defaultType === "embedded") {
1753
+ switchOptions.embeddedWalletType = defaultEmbeddedType;
1754
+ }
1755
+ this.switchProvider(defaultType, switchOptions);
1247
1756
  }
1248
1757
  /**
1249
1758
  * Create a provider instance
@@ -1255,22 +1764,27 @@ var ProviderManager = class {
1255
1764
  let provider;
1256
1765
  if (type === "injected") {
1257
1766
  provider = new InjectedProvider({
1258
- solanaProvider: this.config.solanaProvider || "web3js",
1259
- addressTypes: this.config.addressTypes
1767
+ addressTypes: this.config.addressTypes || [AddressType.solana]
1260
1768
  });
1261
- } else {
1262
- if (!this.config.apiBaseUrl || !this.config.appId) {
1263
- throw new Error("apiBaseUrl and appId are required for embedded provider");
1769
+ } else if (type === "embedded") {
1770
+ if (!this.config.appId) {
1771
+ throw new Error("appId is required for embedded provider");
1264
1772
  }
1773
+ const apiBaseUrl = this.config.apiBaseUrl || DEFAULT_WALLET_API_URL;
1774
+ const authUrl = this.config.authOptions?.authUrl || DEFAULT_AUTH_URL2;
1265
1775
  provider = new EmbeddedProvider({
1266
- apiBaseUrl: this.config.apiBaseUrl,
1267
- organizationId: this.config.appId,
1776
+ apiBaseUrl,
1268
1777
  appId: this.config.appId,
1269
- authOptions: this.config.authOptions,
1270
- embeddedWalletType: embeddedWalletType || "app-wallet",
1271
- addressTypes: this.config.addressTypes,
1272
- solanaProvider: this.config.solanaProvider || "web3js"
1778
+ authOptions: {
1779
+ ...this.config.authOptions || {},
1780
+ authUrl,
1781
+ redirectUrl: this.config.authOptions?.redirectUrl || this.getValidatedCurrentUrl()
1782
+ },
1783
+ embeddedWalletType: embeddedWalletType || DEFAULT_EMBEDDED_WALLET_TYPE,
1784
+ addressTypes: this.config.addressTypes || [AddressType.solana]
1273
1785
  });
1786
+ } else {
1787
+ throw new Error(`Unsupported provider type: ${type}`);
1274
1788
  }
1275
1789
  this.providers.set(key, provider);
1276
1790
  }
@@ -1280,8 +1794,10 @@ var ProviderManager = class {
1280
1794
  getProviderKey(type, embeddedWalletType) {
1281
1795
  if (type === "injected") {
1282
1796
  return "injected";
1797
+ } else if (type === "embedded") {
1798
+ return `embedded-${embeddedWalletType || "app-wallet"}`;
1283
1799
  }
1284
- return `embedded-${embeddedWalletType || "app-wallet"}`;
1800
+ throw new Error(`Unsupported provider type: ${type}`);
1285
1801
  }
1286
1802
  /**
1287
1803
  * Save provider preference to localStorage
@@ -1296,35 +1812,17 @@ var ProviderManager = class {
1296
1812
  console.error("Failed to save provider preference:", error);
1297
1813
  }
1298
1814
  }
1299
- /**
1300
- * Restore provider preference from localStorage
1301
- */
1302
- /*
1303
- private restoreProviderPreference(): void {
1304
- try {
1305
- const saved = localStorage.getItem("phantom-provider-preference");
1306
- if (saved) {
1307
- const preference: ProviderPreference = JSON.parse(saved);
1308
- this.switchProvider(preference.type, {
1309
- embeddedWalletType: preference.embeddedWalletType,
1310
- });
1311
- }
1312
- } catch (error) {
1313
- // Ignore localStorage errors - just use default provider
1314
- console.error("Failed to restore provider preference:", error);
1315
- }
1316
- }*/
1317
1815
  };
1318
1816
 
1319
1817
  // src/waitForPhantomExtension.ts
1320
- import { isPhantomExtensionInstalled } from "@phantom/browser-injected-sdk";
1818
+ import { isPhantomExtensionInstalled as isPhantomExtensionInstalled3 } from "@phantom/browser-injected-sdk";
1321
1819
  async function waitForPhantomExtension(timeoutMs = 3e3) {
1322
1820
  return new Promise((resolve) => {
1323
1821
  const startTime = Date.now();
1324
1822
  const checkInterval = 100;
1325
1823
  const checkForExtension = () => {
1326
1824
  try {
1327
- if (isPhantomExtensionInstalled()) {
1825
+ if (isPhantomExtensionInstalled3()) {
1328
1826
  resolve(true);
1329
1827
  return;
1330
1828
  }
@@ -1342,6 +1840,7 @@ async function waitForPhantomExtension(timeoutMs = 3e3) {
1342
1840
  }
1343
1841
 
1344
1842
  // src/BrowserSDK.ts
1843
+ import { DEFAULT_EMBEDDED_WALLET_TYPE as DEFAULT_EMBEDDED_WALLET_TYPE2 } from "@phantom/constants";
1345
1844
  var BrowserSDK = class {
1346
1845
  constructor(config) {
1347
1846
  debug.info(DebugCategory.BROWSER_SDK, "Initializing BrowserSDK", {
@@ -1353,7 +1852,7 @@ var BrowserSDK = class {
1353
1852
  debug.error(DebugCategory.BROWSER_SDK, "Invalid providerType", { providerType: config.providerType });
1354
1853
  throw new Error(`Invalid providerType: ${config.providerType}. Must be "injected" or "embedded".`);
1355
1854
  }
1356
- const embeddedWalletType = config.embeddedWalletType || "app-wallet";
1855
+ const embeddedWalletType = config.embeddedWalletType || DEFAULT_EMBEDDED_WALLET_TYPE2;
1357
1856
  if (config.providerType === "embedded" && !["app-wallet", "user-wallet"].includes(embeddedWalletType)) {
1358
1857
  debug.error(DebugCategory.BROWSER_SDK, "Invalid embeddedWalletType", {
1359
1858
  embeddedWalletType: config.embeddedWalletType
@@ -1395,7 +1894,6 @@ var BrowserSDK = class {
1395
1894
  const result = await this.providerManager.connect(options);
1396
1895
  debug.info(DebugCategory.BROWSER_SDK, "Connection successful", {
1397
1896
  addressCount: result.addresses.length,
1398
- walletId: result.walletId,
1399
1897
  status: result.status
1400
1898
  });
1401
1899
  return result;
@@ -1417,22 +1915,6 @@ var BrowserSDK = class {
1417
1915
  throw error;
1418
1916
  }
1419
1917
  }
1420
- /**
1421
- * Switch between provider types (injected vs embedded)
1422
- */
1423
- async switchProvider(type, options) {
1424
- debug.info(DebugCategory.BROWSER_SDK, "Switching provider", { type, options });
1425
- try {
1426
- await this.providerManager.switchProvider(type, options);
1427
- debug.info(DebugCategory.BROWSER_SDK, "Provider switch successful", { type });
1428
- } catch (error) {
1429
- debug.error(DebugCategory.BROWSER_SDK, "Provider switch failed", {
1430
- type,
1431
- error: error.message
1432
- });
1433
- throw error;
1434
- }
1435
- }
1436
1918
  // ===== STATE QUERIES =====
1437
1919
  /**
1438
1920
  * Check if the SDK is connected to a wallet
@@ -1452,12 +1934,6 @@ var BrowserSDK = class {
1452
1934
  getCurrentProviderInfo() {
1453
1935
  return this.providerManager.getCurrentProviderInfo();
1454
1936
  }
1455
- /**
1456
- * Get the wallet ID (for embedded wallets)
1457
- */
1458
- getWalletId() {
1459
- return this.providerManager.getWalletId();
1460
- }
1461
1937
  // ===== UTILITY METHODS =====
1462
1938
  /**
1463
1939
  * Check if Phantom extension is installed
@@ -1484,17 +1960,17 @@ var BrowserSDK = class {
1484
1960
  /**
1485
1961
  * Attempt auto-connection using existing session
1486
1962
  * Should be called after setting up event listeners
1487
- * Only works with embedded providers
1963
+ * Tries embedded provider first, then injected provider as fallback
1488
1964
  */
1489
1965
  async autoConnect() {
1490
- debug.log(DebugCategory.BROWSER_SDK, "Attempting auto-connect");
1491
- const currentProvider = this.providerManager.getCurrentProvider();
1492
- if (currentProvider && "autoConnect" in currentProvider) {
1493
- await currentProvider.autoConnect();
1494
- } else {
1495
- debug.warn(DebugCategory.BROWSER_SDK, "Current provider does not support auto-connect", {
1966
+ debug.log(DebugCategory.BROWSER_SDK, "Attempting auto-connect with fallback strategy");
1967
+ const result = await this.providerManager.autoConnect();
1968
+ if (result) {
1969
+ debug.info(DebugCategory.BROWSER_SDK, "Auto-connect successful", {
1496
1970
  providerType: this.getCurrentProviderInfo()?.type
1497
1971
  });
1972
+ } else {
1973
+ debug.log(DebugCategory.BROWSER_SDK, "Auto-connect failed for all providers");
1498
1974
  }
1499
1975
  }
1500
1976
  /**
@@ -1638,8 +2114,15 @@ var BrowserSDK = class {
1638
2114
  }
1639
2115
  };
1640
2116
 
1641
- // src/types.ts
1642
- import { AddressType as AddressType4 } from "@phantom/client";
2117
+ // src/utils/deeplink.ts
2118
+ function getDeeplinkToPhantom(ref) {
2119
+ if (!window.location.href.startsWith("http:") && !window.location.href.startsWith("https:")) {
2120
+ throw new Error("Invalid URL protocol - only HTTP/HTTPS URLs are supported for deeplinks");
2121
+ }
2122
+ const currentUrl = encodeURIComponent(window.location.href);
2123
+ const refParam = ref ? `?ref=${encodeURIComponent(ref)}` : "";
2124
+ return `https://phantom.app/ul/browse/${currentUrl}${refParam}`;
2125
+ }
1643
2126
 
1644
2127
  // src/index.ts
1645
2128
  import { NetworkId } from "@phantom/constants";
@@ -1647,15 +2130,16 @@ import { AddressType as AddressType5 } from "@phantom/client";
1647
2130
  export {
1648
2131
  AddressType5 as AddressType,
1649
2132
  BrowserSDK,
1650
- DEFAULT_AUTH_URL,
1651
- DEFAULT_WALLET_API_URL,
1652
2133
  DebugCategory,
1653
2134
  DebugLevel,
1654
2135
  NetworkId,
1655
2136
  debug,
1656
2137
  detectBrowser,
1657
2138
  getBrowserDisplayName,
2139
+ getDeeplinkToPhantom,
1658
2140
  getPlatformName,
2141
+ isMobileDevice,
2142
+ isPhantomLoginAvailable,
1659
2143
  parseBrowserFromUserAgent,
1660
2144
  waitForPhantomExtension
1661
2145
  };