@phantom/browser-sdk 1.0.0-beta.1 → 1.0.0-beta.10

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,25 @@ 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
34
  parseBrowserFromUserAgent: () => parseBrowserFromUserAgent,
35
35
  waitForPhantomExtension: () => waitForPhantomExtension
36
36
  });
37
37
  module.exports = __toCommonJS(src_exports);
38
38
 
39
+ // src/types.ts
40
+ var import_client = require("@phantom/client");
41
+
39
42
  // src/providers/injected/index.ts
40
- var import_client3 = require("@phantom/client");
43
+ var import_client4 = require("@phantom/client");
41
44
  var import_browser_injected_sdk = require("@phantom/browser-injected-sdk");
42
45
  var import_solana = require("@phantom/browser-injected-sdk/solana");
43
46
  var import_ethereum = require("@phantom/browser-injected-sdk/ethereum");
@@ -119,7 +122,7 @@ var DebugCategory = {
119
122
 
120
123
  // src/providers/injected/chains/SolanaChain.ts
121
124
  var import_eventemitter3 = require("eventemitter3");
122
- var import_client = require("@phantom/client");
125
+ var import_client2 = require("@phantom/client");
123
126
  var import_buffer = require("buffer");
124
127
  var InjectedSolanaChain = class {
125
128
  constructor(phantom, callbacks) {
@@ -144,7 +147,7 @@ var InjectedSolanaChain = class {
144
147
  return Promise.reject(new Error("Provider not connected. Call provider connect first."));
145
148
  }
146
149
  const addresses = this.callbacks.getAddresses();
147
- const solanaAddress = addresses.find((addr) => addr.addressType === import_client.AddressType.solana);
150
+ const solanaAddress = addresses.find((addr) => addr.addressType === import_client2.AddressType.solana);
148
151
  if (!solanaAddress) {
149
152
  return Promise.reject(new Error("Solana not enabled for this provider"));
150
153
  }
@@ -163,17 +166,42 @@ var InjectedSolanaChain = class {
163
166
  publicKey: this._publicKey || ""
164
167
  };
165
168
  }
166
- signTransaction(_transaction) {
167
- return Promise.reject(
168
- new Error("Sign-only transactions not supported by injected provider. Use signAndSendTransaction instead.")
169
- );
169
+ async signTransaction(transaction) {
170
+ if (!this.callbacks.isConnected()) {
171
+ return Promise.reject(new Error("Provider not connected. Call provider connect first."));
172
+ }
173
+ try {
174
+ const result = await this.phantom.solana.signTransaction(transaction);
175
+ return result;
176
+ } catch (error) {
177
+ return Promise.reject(error);
178
+ }
170
179
  }
171
180
  async signAndSendTransaction(transaction) {
172
181
  const result = await this.phantom.solana.signAndSendTransaction(transaction);
173
182
  return { signature: result.signature };
174
183
  }
175
- signAllTransactions(_transactions) {
176
- return Promise.reject(new Error("Sign-only transactions not supported by injected provider"));
184
+ async signAllTransactions(transactions) {
185
+ if (!this.callbacks.isConnected()) {
186
+ return Promise.reject(new Error("Provider not connected. Call provider connect first."));
187
+ }
188
+ try {
189
+ const result = await this.phantom.solana.signAllTransactions(transactions);
190
+ return result;
191
+ } catch (error) {
192
+ return Promise.reject(error);
193
+ }
194
+ }
195
+ async signAndSendAllTransactions(transactions) {
196
+ if (!this.callbacks.isConnected()) {
197
+ return Promise.reject(new Error("Provider not connected. Call provider connect first."));
198
+ }
199
+ try {
200
+ const result = await this.phantom.solana.signAndSendAllTransactions(transactions);
201
+ return { signatures: result.signatures };
202
+ } catch (error) {
203
+ return Promise.reject(error);
204
+ }
177
205
  }
178
206
  switchNetwork(_network) {
179
207
  return Promise.resolve();
@@ -199,7 +227,7 @@ var InjectedSolanaChain = class {
199
227
  this.eventEmitter.emit("accountChanged", publicKey);
200
228
  });
201
229
  this.callbacks.on("connect", (data) => {
202
- const solanaAddress = data.addresses?.find((addr) => addr.addressType === import_client.AddressType.solana);
230
+ const solanaAddress = data.addresses?.find((addr) => addr.addressType === import_client2.AddressType.solana);
203
231
  if (solanaAddress) {
204
232
  this.updateConnectionState(true, solanaAddress.address);
205
233
  }
@@ -210,7 +238,7 @@ var InjectedSolanaChain = class {
210
238
  }
211
239
  syncInitialState() {
212
240
  if (this.callbacks.isConnected()) {
213
- const solanaAddress = this.callbacks.getAddresses().find((addr) => addr.addressType === import_client.AddressType.solana);
241
+ const solanaAddress = this.callbacks.getAddresses().find((addr) => addr.addressType === import_client2.AddressType.solana);
214
242
  if (solanaAddress) {
215
243
  this.updateConnectionState(true, solanaAddress.address);
216
244
  }
@@ -231,7 +259,7 @@ var InjectedSolanaChain = class {
231
259
 
232
260
  // src/providers/injected/chains/EthereumChain.ts
233
261
  var import_eventemitter32 = require("eventemitter3");
234
- var import_client2 = require("@phantom/client");
262
+ var import_client3 = require("@phantom/client");
235
263
  var InjectedEthereumChain = class {
236
264
  constructor(phantom, callbacks) {
237
265
  this._connected = false;
@@ -253,8 +281,13 @@ var InjectedEthereumChain = class {
253
281
  get accounts() {
254
282
  return this._accounts;
255
283
  }
256
- // EIP-1193 core method - unchanged, already compliant!
284
+ // EIP-1193 core method with eth_signTransaction support
257
285
  async request(args) {
286
+ if (args.method === "eth_signTransaction") {
287
+ const [transaction] = args.params;
288
+ const result = await this.signTransaction(transaction);
289
+ return result;
290
+ }
258
291
  const provider = await this.phantom.ethereum.getProvider();
259
292
  return await provider.request(args);
260
293
  }
@@ -264,7 +297,7 @@ var InjectedEthereumChain = class {
264
297
  return Promise.reject(new Error("Provider not connected. Call provider connect first."));
265
298
  }
266
299
  const addresses = this.callbacks.getAddresses();
267
- const ethAddresses = addresses.filter((addr) => addr.addressType === import_client2.AddressType.ethereum).map((addr) => addr.address);
300
+ const ethAddresses = addresses.filter((addr) => addr.addressType === import_client3.AddressType.ethereum).map((addr) => addr.address);
268
301
  this.updateConnectionState(true, ethAddresses);
269
302
  return Promise.resolve(ethAddresses);
270
303
  }
@@ -278,6 +311,9 @@ var InjectedEthereumChain = class {
278
311
  async signTypedData(typedData, address) {
279
312
  return await this.phantom.ethereum.signTypedData(typedData, address);
280
313
  }
314
+ async signTransaction(transaction) {
315
+ return await this.phantom.ethereum.signTransaction(transaction);
316
+ }
281
317
  async sendTransaction(transaction) {
282
318
  return await this.phantom.ethereum.sendTransaction(transaction);
283
319
  }
@@ -316,7 +352,7 @@ var InjectedEthereumChain = class {
316
352
  this.eventEmitter.emit("chainChanged", chainId);
317
353
  });
318
354
  this.callbacks.on("connect", (data) => {
319
- const ethAddresses = data.addresses?.filter((addr) => addr.addressType === import_client2.AddressType.ethereum)?.map((addr) => addr.address) || [];
355
+ const ethAddresses = data.addresses?.filter((addr) => addr.addressType === import_client3.AddressType.ethereum)?.map((addr) => addr.address) || [];
320
356
  if (ethAddresses.length > 0) {
321
357
  this.updateConnectionState(true, ethAddresses);
322
358
  }
@@ -327,7 +363,7 @@ var InjectedEthereumChain = class {
327
363
  }
328
364
  syncInitialState() {
329
365
  if (this.callbacks.isConnected()) {
330
- const ethAddresses = this.callbacks.getAddresses().filter((addr) => addr.addressType === import_client2.AddressType.ethereum).map((addr) => addr.address);
366
+ const ethAddresses = this.callbacks.getAddresses().filter((addr) => addr.addressType === import_client3.AddressType.ethereum).map((addr) => addr.address);
331
367
  if (ethAddresses.length > 0) {
332
368
  this.updateConnectionState(true, ethAddresses);
333
369
  }
@@ -359,11 +395,11 @@ var InjectedProvider = class {
359
395
  this.addressTypes = config.addressTypes;
360
396
  debug.log(DebugCategory.INJECTED_PROVIDER, "Address types configured", { addressTypes: this.addressTypes });
361
397
  const plugins = [(0, import_browser_injected_sdk.createExtensionPlugin)()];
362
- if (this.addressTypes.includes(import_client3.AddressType.solana)) {
398
+ if (this.addressTypes.includes(import_client4.AddressType.solana)) {
363
399
  plugins.push((0, import_solana.createSolanaPlugin)());
364
400
  debug.log(DebugCategory.INJECTED_PROVIDER, "Solana plugin added");
365
401
  }
366
- if (this.addressTypes.includes(import_client3.AddressType.ethereum)) {
402
+ if (this.addressTypes.includes(import_client4.AddressType.ethereum)) {
367
403
  plugins.push((0, import_ethereum.createEthereumPlugin)());
368
404
  debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum plugin added");
369
405
  }
@@ -374,10 +410,10 @@ var InjectedProvider = class {
374
410
  });
375
411
  this.phantom = (0, import_browser_injected_sdk.createPhantom)({ plugins });
376
412
  const callbacks = this.createCallbacks();
377
- if (this.addressTypes.includes(import_client3.AddressType.solana)) {
413
+ if (this.addressTypes.includes(import_client4.AddressType.solana)) {
378
414
  this._solanaChain = new InjectedSolanaChain(this.phantom, callbacks);
379
415
  }
380
- if (this.addressTypes.includes(import_client3.AddressType.ethereum)) {
416
+ if (this.addressTypes.includes(import_client4.AddressType.ethereum)) {
381
417
  this._ethereumChain = new InjectedEthereumChain(this.phantom, callbacks);
382
418
  }
383
419
  debug.info(DebugCategory.INJECTED_PROVIDER, "InjectedProvider initialized");
@@ -386,7 +422,7 @@ var InjectedProvider = class {
386
422
  * Access to Solana chain operations
387
423
  */
388
424
  get solana() {
389
- if (!this.addressTypes.includes(import_client3.AddressType.solana)) {
425
+ if (!this.addressTypes.includes(import_client4.AddressType.solana)) {
390
426
  throw new Error("Solana not enabled for this provider");
391
427
  }
392
428
  if (!this._solanaChain) {
@@ -398,7 +434,7 @@ var InjectedProvider = class {
398
434
  * Access to Ethereum chain operations
399
435
  */
400
436
  get ethereum() {
401
- if (!this.addressTypes.includes(import_client3.AddressType.ethereum)) {
437
+ if (!this.addressTypes.includes(import_client4.AddressType.ethereum)) {
402
438
  throw new Error("Ethereum not enabled for this provider");
403
439
  }
404
440
  if (!this._ethereumChain) {
@@ -428,13 +464,13 @@ var InjectedProvider = class {
428
464
  }
429
465
  debug.log(DebugCategory.INJECTED_PROVIDER, "Phantom extension detected");
430
466
  const connectedAddresses = [];
431
- if (this.addressTypes.includes(import_client3.AddressType.solana)) {
467
+ if (this.addressTypes.includes(import_client4.AddressType.solana)) {
432
468
  debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting Solana connection");
433
469
  try {
434
470
  const publicKey = await this.phantom.solana.connect();
435
471
  if (publicKey) {
436
472
  connectedAddresses.push({
437
- addressType: import_client3.AddressType.solana,
473
+ addressType: import_client4.AddressType.solana,
438
474
  address: publicKey
439
475
  });
440
476
  debug.info(DebugCategory.INJECTED_PROVIDER, "Solana connected successfully", { address: publicKey });
@@ -443,13 +479,13 @@ var InjectedProvider = class {
443
479
  debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Solana", { error: err });
444
480
  }
445
481
  }
446
- if (this.addressTypes.includes(import_client3.AddressType.ethereum)) {
482
+ if (this.addressTypes.includes(import_client4.AddressType.ethereum)) {
447
483
  try {
448
484
  const accounts = await this.phantom.ethereum.connect();
449
485
  if (accounts && accounts.length > 0) {
450
486
  connectedAddresses.push(
451
487
  ...accounts.map((address) => ({
452
- addressType: import_client3.AddressType.ethereum,
488
+ addressType: import_client4.AddressType.ethereum,
453
489
  address
454
490
  }))
455
491
  );
@@ -491,7 +527,7 @@ var InjectedProvider = class {
491
527
  }
492
528
  async disconnect() {
493
529
  debug.info(DebugCategory.INJECTED_PROVIDER, "Starting injected provider disconnect");
494
- if (this.addressTypes.includes(import_client3.AddressType.solana)) {
530
+ if (this.addressTypes.includes(import_client4.AddressType.solana)) {
495
531
  try {
496
532
  await this.phantom.solana.disconnect();
497
533
  debug.log(DebugCategory.INJECTED_PROVIDER, "Solana disconnected successfully");
@@ -499,7 +535,7 @@ var InjectedProvider = class {
499
535
  debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to disconnect Solana", { error: err });
500
536
  }
501
537
  }
502
- if (this.addressTypes.includes(import_client3.AddressType.ethereum)) {
538
+ if (this.addressTypes.includes(import_client4.AddressType.ethereum)) {
503
539
  debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum disconnected (no-op)");
504
540
  }
505
541
  this.browserInjectedCleanupFunctions.forEach((cleanup) => cleanup());
@@ -511,6 +547,87 @@ var InjectedProvider = class {
511
547
  });
512
548
  debug.info(DebugCategory.INJECTED_PROVIDER, "Injected provider disconnected successfully");
513
549
  }
550
+ /**
551
+ * Attempt auto-connection using onlyIfTrusted parameter
552
+ * This will only connect if the dApp is already trusted by the user
553
+ * Should be called after setting up event listeners
554
+ */
555
+ async autoConnect() {
556
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting auto-connect with onlyIfTrusted=true");
557
+ this.emit("connect_start", {
558
+ source: "auto-connect",
559
+ providerType: "injected"
560
+ });
561
+ try {
562
+ if (!this.phantom.extension?.isInstalled?.()) {
563
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Phantom wallet extension not found for auto-connect");
564
+ this.emit("connect_error", {
565
+ error: "Phantom wallet not found",
566
+ source: "auto-connect"
567
+ });
568
+ return;
569
+ }
570
+ const connectedAddresses = [];
571
+ if (this.addressTypes.includes(import_client4.AddressType.solana)) {
572
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting Solana auto-connect");
573
+ try {
574
+ const publicKey = await this.phantom.solana.connect({ onlyIfTrusted: true });
575
+ if (publicKey) {
576
+ connectedAddresses.push({
577
+ addressType: import_client4.AddressType.solana,
578
+ address: publicKey
579
+ });
580
+ debug.info(DebugCategory.INJECTED_PROVIDER, "Solana auto-connected successfully", { address: publicKey });
581
+ }
582
+ } catch (err) {
583
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Solana auto-connect failed (expected if not trusted)", { error: err });
584
+ }
585
+ }
586
+ if (this.addressTypes.includes(import_client4.AddressType.ethereum)) {
587
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting Ethereum auto-connect");
588
+ try {
589
+ const accounts = await this.phantom.ethereum.connect({ onlyIfTrusted: true });
590
+ if (accounts && accounts.length > 0) {
591
+ connectedAddresses.push(
592
+ ...accounts.map((address) => ({
593
+ addressType: import_client4.AddressType.ethereum,
594
+ address
595
+ }))
596
+ );
597
+ debug.info(DebugCategory.INJECTED_PROVIDER, "Ethereum auto-connected successfully", { addresses: accounts });
598
+ }
599
+ } catch (err) {
600
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum auto-connect failed (expected if not trusted)", { error: err });
601
+ }
602
+ }
603
+ if (connectedAddresses.length === 0) {
604
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Auto-connect failed: no trusted connections available");
605
+ this.emit("connect_error", {
606
+ error: "No trusted connections available",
607
+ source: "auto-connect"
608
+ });
609
+ return;
610
+ }
611
+ this.addresses = connectedAddresses;
612
+ this.connected = true;
613
+ this.emit("connect", {
614
+ addresses: this.addresses,
615
+ source: "auto-connect"
616
+ });
617
+ debug.info(DebugCategory.INJECTED_PROVIDER, "Auto-connect successful", {
618
+ addressCount: connectedAddresses.length,
619
+ addresses: connectedAddresses.map((addr) => ({ type: addr.addressType, address: addr.address.substring(0, 8) + "..." }))
620
+ });
621
+ } catch (error) {
622
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Auto-connect failed with error", {
623
+ error: error instanceof Error ? error.message : String(error)
624
+ });
625
+ this.emit("connect_error", {
626
+ error: error instanceof Error ? error.message : "Auto-connect failed",
627
+ source: "auto-connect"
628
+ });
629
+ }
630
+ }
514
631
  getAddresses() {
515
632
  return this.addresses;
516
633
  }
@@ -574,10 +691,10 @@ var InjectedProvider = class {
574
691
  }
575
692
  setupBrowserInjectedEvents() {
576
693
  debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up browser-injected-sdk event listeners");
577
- if (this.addressTypes.includes(import_client3.AddressType.solana)) {
694
+ if (this.addressTypes.includes(import_client4.AddressType.solana)) {
578
695
  this.setupSolanaEvents();
579
696
  }
580
- if (this.addressTypes.includes(import_client3.AddressType.ethereum)) {
697
+ if (this.addressTypes.includes(import_client4.AddressType.ethereum)) {
581
698
  this.setupEthereumEvents();
582
699
  }
583
700
  }
@@ -585,8 +702,8 @@ var InjectedProvider = class {
585
702
  debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up Solana event listeners");
586
703
  const handleSolanaConnect = (publicKey) => {
587
704
  debug.log(DebugCategory.INJECTED_PROVIDER, "Solana connect event received", { publicKey });
588
- const solanaAddress = { addressType: import_client3.AddressType.solana, address: publicKey };
589
- if (!this.addresses.find((addr) => addr.addressType === import_client3.AddressType.solana)) {
705
+ const solanaAddress = { addressType: import_client4.AddressType.solana, address: publicKey };
706
+ if (!this.addresses.find((addr) => addr.addressType === import_client4.AddressType.solana)) {
590
707
  this.addresses.push(solanaAddress);
591
708
  }
592
709
  this.connected = true;
@@ -597,19 +714,19 @@ var InjectedProvider = class {
597
714
  };
598
715
  const handleSolanaDisconnect = () => {
599
716
  debug.log(DebugCategory.INJECTED_PROVIDER, "Solana disconnect event received");
600
- this.addresses = this.addresses.filter((addr) => addr.addressType !== import_client3.AddressType.solana);
601
- this.connected = this.addresses.length > 0;
717
+ this.addresses = this.addresses.filter((addr) => addr.addressType !== import_client4.AddressType.solana);
718
+ this.connected = false;
602
719
  this.emit("disconnect", {
603
720
  source: "injected-extension"
604
721
  });
605
722
  };
606
723
  const handleSolanaAccountChanged = (publicKey) => {
607
724
  debug.log(DebugCategory.INJECTED_PROVIDER, "Solana account changed event received", { publicKey });
608
- const solanaIndex = this.addresses.findIndex((addr) => addr.addressType === import_client3.AddressType.solana);
725
+ const solanaIndex = this.addresses.findIndex((addr) => addr.addressType === import_client4.AddressType.solana);
609
726
  if (solanaIndex >= 0) {
610
- this.addresses[solanaIndex] = { addressType: import_client3.AddressType.solana, address: publicKey };
727
+ this.addresses[solanaIndex] = { addressType: import_client4.AddressType.solana, address: publicKey };
611
728
  } else {
612
- this.addresses.push({ addressType: import_client3.AddressType.solana, address: publicKey });
729
+ this.addresses.push({ addressType: import_client4.AddressType.solana, address: publicKey });
613
730
  }
614
731
  this.emit("connect", {
615
732
  addresses: this.addresses,
@@ -618,21 +735,18 @@ var InjectedProvider = class {
618
735
  };
619
736
  const cleanupConnect = this.phantom.solana.addEventListener("connect", handleSolanaConnect);
620
737
  const cleanupDisconnect = this.phantom.solana.addEventListener("disconnect", handleSolanaDisconnect);
621
- const cleanupAccountChanged = this.phantom.solana.addEventListener(
622
- "accountChanged",
623
- handleSolanaAccountChanged
624
- );
738
+ const cleanupAccountChanged = this.phantom.solana.addEventListener("accountChanged", handleSolanaAccountChanged);
625
739
  this.browserInjectedCleanupFunctions.push(cleanupConnect, cleanupDisconnect, cleanupAccountChanged);
626
740
  }
627
741
  setupEthereumEvents() {
628
742
  debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up Ethereum event listeners");
629
743
  const handleEthereumConnect = (accounts) => {
630
744
  debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum connect event received", { accounts });
631
- this.addresses = this.addresses.filter((addr) => addr.addressType !== import_client3.AddressType.ethereum);
745
+ this.addresses = this.addresses.filter((addr) => addr.addressType !== import_client4.AddressType.ethereum);
632
746
  if (accounts && accounts.length > 0) {
633
747
  this.addresses.push(
634
748
  ...accounts.map((address) => ({
635
- addressType: import_client3.AddressType.ethereum,
749
+ addressType: import_client4.AddressType.ethereum,
636
750
  address
637
751
  }))
638
752
  );
@@ -645,27 +759,32 @@ var InjectedProvider = class {
645
759
  };
646
760
  const handleEthereumDisconnect = () => {
647
761
  debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum disconnect event received");
648
- this.addresses = this.addresses.filter((addr) => addr.addressType !== import_client3.AddressType.ethereum);
649
- this.connected = this.addresses.length > 0;
762
+ this.addresses = this.addresses.filter((addr) => addr.addressType !== import_client4.AddressType.ethereum);
763
+ this.connected = false;
650
764
  this.emit("disconnect", {
651
765
  source: "injected-extension"
652
766
  });
653
767
  };
654
768
  const handleEthereumAccountsChanged = (accounts) => {
655
769
  debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum accounts changed event received", { accounts });
656
- this.addresses = this.addresses.filter((addr) => addr.addressType !== import_client3.AddressType.ethereum);
770
+ this.addresses = this.addresses.filter((addr) => addr.addressType !== import_client4.AddressType.ethereum);
657
771
  if (accounts && accounts.length > 0) {
658
772
  this.addresses.push(
659
773
  ...accounts.map((address) => ({
660
- addressType: import_client3.AddressType.ethereum,
774
+ addressType: import_client4.AddressType.ethereum,
661
775
  address
662
776
  }))
663
777
  );
778
+ this.emit("connect", {
779
+ addresses: this.addresses,
780
+ source: "injected-extension-account-change"
781
+ });
782
+ } else {
783
+ this.connected = false;
784
+ this.emit("disconnect", {
785
+ source: "injected-extension-account-change"
786
+ });
664
787
  }
665
- this.emit("connect", {
666
- addresses: this.addresses,
667
- source: "injected-extension-account-change"
668
- });
669
788
  };
670
789
  const cleanupConnect = this.phantom.ethereum.addEventListener("connect", handleEthereumConnect);
671
790
  const cleanupDisconnect = this.phantom.ethereum.addEventListener("disconnect", handleEthereumDisconnect);
@@ -794,15 +913,19 @@ var BrowserURLParamsAccessor = class {
794
913
  };
795
914
  var browserUrlParamsAccessor = new BrowserURLParamsAccessor();
796
915
 
797
- // src/constants.ts
798
- var DEFAULT_AUTH_URL = "https://connect.phantom.app";
799
- var DEFAULT_WALLET_API_URL = "https://api.phantom.app/v1/wallets";
800
-
801
916
  // src/providers/embedded/adapters/auth.ts
917
+ var import_constants = require("@phantom/constants");
802
918
  var BrowserAuthProvider = class {
803
919
  constructor(urlParamsAccessor) {
804
920
  this.urlParamsAccessor = urlParamsAccessor;
805
921
  }
922
+ getValidatedCurrentUrl() {
923
+ const currentUrl = window.location.href;
924
+ if (!currentUrl.startsWith("http:") && !currentUrl.startsWith("https:")) {
925
+ throw new Error("Invalid URL protocol - only HTTP/HTTPS URLs are supported");
926
+ }
927
+ return currentUrl;
928
+ }
806
929
  authenticate(options) {
807
930
  return new Promise((resolve) => {
808
931
  if ("jwtToken" in options) {
@@ -811,21 +934,20 @@ var BrowserAuthProvider = class {
811
934
  const phantomOptions = options;
812
935
  debug.info(DebugCategory.PHANTOM_CONNECT_AUTH, "Starting Phantom Connect authentication", {
813
936
  organizationId: phantomOptions.organizationId,
814
- parentOrganizationId: phantomOptions.parentOrganizationId,
815
937
  appId: phantomOptions.appId,
816
938
  provider: phantomOptions.provider,
817
939
  authUrl: phantomOptions.authUrl,
818
940
  hasCustomData: !!phantomOptions.customAuthData
819
941
  });
820
- const baseUrl = phantomOptions.authUrl || DEFAULT_AUTH_URL;
942
+ const baseUrl = phantomOptions.authUrl || import_constants.DEFAULT_AUTH_URL;
821
943
  debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Using auth URL", { baseUrl });
822
944
  const params = new URLSearchParams({
823
945
  organization_id: phantomOptions.organizationId,
824
- parent_organization_id: phantomOptions.parentOrganizationId,
825
946
  app_id: phantomOptions.appId,
826
- redirect_uri: phantomOptions.redirectUrl || (typeof window !== "undefined" ? window.location.href : ""),
947
+ redirect_uri: phantomOptions.redirectUrl || (typeof window !== "undefined" ? this.getValidatedCurrentUrl() : ""),
827
948
  session_id: phantomOptions.sessionId,
828
- clear_previous_session: true.toString()
949
+ clear_previous_session: true.toString(),
950
+ sdk_version: "1.0.0-beta.10"
829
951
  });
830
952
  if (phantomOptions.provider) {
831
953
  debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Provider specified, will skip selection", {
@@ -842,7 +964,6 @@ var BrowserAuthProvider = class {
842
964
  }
843
965
  const authContext = {
844
966
  organizationId: phantomOptions.organizationId,
845
- parentOrganizationId: phantomOptions.parentOrganizationId,
846
967
  appId: phantomOptions.appId,
847
968
  provider: phantomOptions.provider,
848
969
  sessionId: phantomOptions.sessionId
@@ -851,6 +972,9 @@ var BrowserAuthProvider = class {
851
972
  debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Stored auth context in session storage", { authContext });
852
973
  const authUrl = `${baseUrl}?${params.toString()}`;
853
974
  debug.info(DebugCategory.PHANTOM_CONNECT_AUTH, "Redirecting to Phantom Connect", { authUrl });
975
+ if (!authUrl.startsWith("https:")) {
976
+ throw new Error("Invalid auth URL - only HTTPS URLs are allowed for authentication");
977
+ }
854
978
  window.location.href = authUrl;
855
979
  resolve();
856
980
  });
@@ -939,7 +1063,7 @@ function parseBrowserFromUserAgent(userAgent, hasBraveAPI) {
939
1063
  let name = "unknown";
940
1064
  let version = "unknown";
941
1065
  if (!userAgent || typeof userAgent !== "string") {
942
- return { name, version };
1066
+ return { name, version, userAgent: "unknown" };
943
1067
  }
944
1068
  try {
945
1069
  if (userAgent.includes("Edg/")) {
@@ -1021,11 +1145,11 @@ function parseBrowserFromUserAgent(userAgent, hasBraveAPI) {
1021
1145
  }
1022
1146
  } catch (error) {
1023
1147
  }
1024
- return { name, version };
1148
+ return { name, version, userAgent };
1025
1149
  }
1026
1150
  function detectBrowser() {
1027
1151
  if (typeof window === "undefined" || !window.navigator?.userAgent) {
1028
- return { name: "unknown", version: "unknown" };
1152
+ return { name: "unknown", version: "unknown", userAgent: "unknown" };
1029
1153
  }
1030
1154
  const userAgent = window.navigator.userAgent;
1031
1155
  const hasBraveAPI = !!navigator.brave;
@@ -1040,25 +1164,70 @@ function getBrowserDisplayName() {
1040
1164
  const capitalizedName = name.charAt(0).toUpperCase() + name.slice(1);
1041
1165
  return version !== "unknown" ? `${capitalizedName} ${version}` : capitalizedName;
1042
1166
  }
1167
+ function isMobileDevice() {
1168
+ if (typeof window === "undefined" || !window.navigator?.userAgent) {
1169
+ return false;
1170
+ }
1171
+ const userAgent = window.navigator.userAgent.toLowerCase();
1172
+ const mobilePatterns = [
1173
+ /android/,
1174
+ /iphone|ipad|ipod/,
1175
+ /blackberry/,
1176
+ /windows phone/,
1177
+ /mobile/,
1178
+ /tablet/,
1179
+ /silk/,
1180
+ /kindle/,
1181
+ /opera mini/,
1182
+ /opera mobi/
1183
+ ];
1184
+ const isMobileUA = mobilePatterns.some((pattern) => pattern.test(userAgent));
1185
+ let isSmallScreen = false;
1186
+ try {
1187
+ isSmallScreen = window.screen.width <= 768 || window.screen.height <= 768;
1188
+ } catch (error) {
1189
+ isSmallScreen = false;
1190
+ }
1191
+ let isTouchDevice = false;
1192
+ try {
1193
+ isTouchDevice = "ontouchstart" in window || navigator.maxTouchPoints > 0;
1194
+ } catch (error) {
1195
+ isTouchDevice = false;
1196
+ }
1197
+ return isMobileUA || isSmallScreen && isTouchDevice;
1198
+ }
1043
1199
 
1044
1200
  // src/providers/embedded/index.ts
1201
+ var import_constants2 = require("@phantom/constants");
1045
1202
  var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvider {
1046
1203
  constructor(config) {
1047
1204
  debug.log(DebugCategory.EMBEDDED_PROVIDER, "Initializing Browser EmbeddedProvider", { config });
1048
1205
  const urlParamsAccessor = new BrowserURLParamsAccessor();
1049
1206
  const stamper = new import_indexed_db_stamper.IndexedDbStamper({
1050
- dbName: `phantom-embedded-sdk-${config.organizationId}`,
1207
+ dbName: `phantom-embedded-sdk-${config.appId}`,
1051
1208
  storeName: "crypto-keys",
1052
1209
  keyName: "signing-key"
1053
1210
  });
1054
1211
  const platformName = getPlatformName();
1212
+ const { name: browserName, version } = detectBrowser();
1055
1213
  const platform = {
1056
1214
  storage: new BrowserStorage(),
1057
1215
  authProvider: new BrowserAuthProvider(urlParamsAccessor),
1058
1216
  urlParamsAccessor,
1059
1217
  stamper,
1060
- name: platformName
1218
+ name: platformName,
1061
1219
  // Use detected browser name and version for identification
1220
+ analyticsHeaders: {
1221
+ [import_constants2.ANALYTICS_HEADERS.SDK_TYPE]: "browser",
1222
+ [import_constants2.ANALYTICS_HEADERS.PLATFORM]: browserName,
1223
+ // firefox, chrome, safari, etc.
1224
+ [import_constants2.ANALYTICS_HEADERS.PLATFORM_VERSION]: version,
1225
+ // Full user agent for more detailed info
1226
+ [import_constants2.ANALYTICS_HEADERS.APP_ID]: config.appId,
1227
+ [import_constants2.ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
1228
+ [import_constants2.ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.10"
1229
+ // Replaced at build time
1230
+ }
1062
1231
  };
1063
1232
  debug.log(DebugCategory.EMBEDDED_PROVIDER, "Detected platform", { platformName });
1064
1233
  const logger = new BrowserLogger();
@@ -1068,6 +1237,7 @@ var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvi
1068
1237
  };
1069
1238
 
1070
1239
  // src/ProviderManager.ts
1240
+ var import_constants3 = require("@phantom/constants");
1071
1241
  var ProviderManager = class {
1072
1242
  // Track which providers have forwarding set up
1073
1243
  constructor(config) {
@@ -1086,6 +1256,15 @@ var ProviderManager = class {
1086
1256
  currentProviderKey: this.currentProviderKey
1087
1257
  });
1088
1258
  }
1259
+ getValidatedCurrentUrl() {
1260
+ if (typeof window === "undefined")
1261
+ return "";
1262
+ const currentUrl = window.location.href;
1263
+ if (!currentUrl.startsWith("http:") && !currentUrl.startsWith("https:")) {
1264
+ throw new Error("Invalid URL protocol - only HTTP/HTTPS URLs are supported");
1265
+ }
1266
+ return currentUrl;
1267
+ }
1089
1268
  /**
1090
1269
  * Switch to a different provider type
1091
1270
  */
@@ -1117,7 +1296,8 @@ var ProviderManager = class {
1117
1296
  getCurrentProviderInfo() {
1118
1297
  if (!this.currentProviderKey)
1119
1298
  return null;
1120
- const [type, embeddedWalletType] = this.currentProviderKey.split("-");
1299
+ const parts = this.currentProviderKey.split("-");
1300
+ const [type, embeddedWalletType] = parts;
1121
1301
  return {
1122
1302
  type,
1123
1303
  embeddedWalletType
@@ -1263,7 +1443,7 @@ var ProviderManager = class {
1263
1443
  */
1264
1444
  setDefaultProvider() {
1265
1445
  const defaultType = this.config.providerType || "embedded";
1266
- const defaultEmbeddedType = this.config.embeddedWalletType || "app-wallet";
1446
+ const defaultEmbeddedType = this.config.embeddedWalletType || "user-wallet";
1267
1447
  this.createProvider(defaultType, defaultEmbeddedType);
1268
1448
  this.switchProvider(defaultType, { embeddedWalletType: defaultEmbeddedType });
1269
1449
  }
@@ -1277,22 +1457,27 @@ var ProviderManager = class {
1277
1457
  let provider;
1278
1458
  if (type === "injected") {
1279
1459
  provider = new InjectedProvider({
1280
- solanaProvider: this.config.solanaProvider || "web3js",
1281
- addressTypes: this.config.addressTypes
1460
+ addressTypes: this.config.addressTypes || [import_client.AddressType.solana]
1282
1461
  });
1283
- } else {
1284
- if (!this.config.apiBaseUrl || !this.config.appId) {
1285
- throw new Error("apiBaseUrl and appId are required for embedded provider");
1462
+ } else if (type === "embedded") {
1463
+ if (!this.config.appId) {
1464
+ throw new Error("appId is required for embedded provider");
1286
1465
  }
1466
+ const apiBaseUrl = this.config.apiBaseUrl || import_constants3.DEFAULT_WALLET_API_URL;
1467
+ const authUrl = this.config.authOptions?.authUrl || import_constants3.DEFAULT_AUTH_URL;
1287
1468
  provider = new EmbeddedProvider({
1288
- apiBaseUrl: this.config.apiBaseUrl,
1289
- organizationId: this.config.appId,
1469
+ apiBaseUrl,
1290
1470
  appId: this.config.appId,
1291
- authOptions: this.config.authOptions,
1292
- embeddedWalletType: embeddedWalletType || "app-wallet",
1293
- addressTypes: this.config.addressTypes,
1294
- solanaProvider: this.config.solanaProvider || "web3js"
1471
+ authOptions: {
1472
+ ...this.config.authOptions || {},
1473
+ authUrl,
1474
+ redirectUrl: this.config.authOptions?.redirectUrl || this.getValidatedCurrentUrl()
1475
+ },
1476
+ embeddedWalletType: embeddedWalletType || import_constants3.DEFAULT_EMBEDDED_WALLET_TYPE,
1477
+ addressTypes: this.config.addressTypes || [import_client.AddressType.solana]
1295
1478
  });
1479
+ } else {
1480
+ throw new Error(`Unsupported provider type: ${type}`);
1296
1481
  }
1297
1482
  this.providers.set(key, provider);
1298
1483
  }
@@ -1302,8 +1487,10 @@ var ProviderManager = class {
1302
1487
  getProviderKey(type, embeddedWalletType) {
1303
1488
  if (type === "injected") {
1304
1489
  return "injected";
1490
+ } else if (type === "embedded") {
1491
+ return `embedded-${embeddedWalletType || "app-wallet"}`;
1305
1492
  }
1306
- return `embedded-${embeddedWalletType || "app-wallet"}`;
1493
+ throw new Error(`Unsupported provider type: ${type}`);
1307
1494
  }
1308
1495
  /**
1309
1496
  * Save provider preference to localStorage
@@ -1364,6 +1551,7 @@ async function waitForPhantomExtension(timeoutMs = 3e3) {
1364
1551
  }
1365
1552
 
1366
1553
  // src/BrowserSDK.ts
1554
+ var import_constants4 = require("@phantom/constants");
1367
1555
  var BrowserSDK = class {
1368
1556
  constructor(config) {
1369
1557
  debug.info(DebugCategory.BROWSER_SDK, "Initializing BrowserSDK", {
@@ -1375,7 +1563,7 @@ var BrowserSDK = class {
1375
1563
  debug.error(DebugCategory.BROWSER_SDK, "Invalid providerType", { providerType: config.providerType });
1376
1564
  throw new Error(`Invalid providerType: ${config.providerType}. Must be "injected" or "embedded".`);
1377
1565
  }
1378
- const embeddedWalletType = config.embeddedWalletType || "app-wallet";
1566
+ const embeddedWalletType = config.embeddedWalletType || import_constants4.DEFAULT_EMBEDDED_WALLET_TYPE;
1379
1567
  if (config.providerType === "embedded" && !["app-wallet", "user-wallet"].includes(embeddedWalletType)) {
1380
1568
  debug.error(DebugCategory.BROWSER_SDK, "Invalid embeddedWalletType", {
1381
1569
  embeddedWalletType: config.embeddedWalletType
@@ -1511,7 +1699,7 @@ var BrowserSDK = class {
1511
1699
  async autoConnect() {
1512
1700
  debug.log(DebugCategory.BROWSER_SDK, "Attempting auto-connect");
1513
1701
  const currentProvider = this.providerManager.getCurrentProvider();
1514
- if (currentProvider && "autoConnect" in currentProvider) {
1702
+ if (currentProvider) {
1515
1703
  await currentProvider.autoConnect();
1516
1704
  } else {
1517
1705
  debug.warn(DebugCategory.BROWSER_SDK, "Current provider does not support auto-connect", {
@@ -1660,9 +1848,16 @@ var BrowserSDK = class {
1660
1848
  }
1661
1849
  };
1662
1850
 
1663
- // src/types.ts
1664
- var import_client4 = require("@phantom/client");
1851
+ // src/utils/deeplink.ts
1852
+ function getDeeplinkToPhantom(ref) {
1853
+ if (!window.location.href.startsWith("http:") && !window.location.href.startsWith("https:")) {
1854
+ throw new Error("Invalid URL protocol - only HTTP/HTTPS URLs are supported for deeplinks");
1855
+ }
1856
+ const currentUrl = encodeURIComponent(window.location.href);
1857
+ const refParam = ref ? `?ref=${encodeURIComponent(ref)}` : "";
1858
+ return `https://phantom.app/ul/browse/${currentUrl}${refParam}`;
1859
+ }
1665
1860
 
1666
1861
  // src/index.ts
1667
- var import_constants2 = require("@phantom/constants");
1862
+ var import_constants5 = require("@phantom/constants");
1668
1863
  var import_client5 = require("@phantom/client");