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

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) {
@@ -810,22 +933,21 @@ var BrowserAuthProvider = class {
810
933
  }
811
934
  const phantomOptions = options;
812
935
  debug.info(DebugCategory.PHANTOM_CONNECT_AUTH, "Starting Phantom Connect authentication", {
813
- organizationId: phantomOptions.organizationId,
814
- parentOrganizationId: phantomOptions.parentOrganizationId,
936
+ publicKey: phantomOptions.publicKey,
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
- organization_id: phantomOptions.organizationId,
824
- parent_organization_id: phantomOptions.parentOrganizationId,
945
+ public_key: phantomOptions.publicKey,
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.11"
829
951
  });
830
952
  if (phantomOptions.provider) {
831
953
  debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Provider specified, will skip selection", {
@@ -841,8 +963,7 @@ var BrowserAuthProvider = class {
841
963
  params.append("authData", JSON.stringify(phantomOptions.customAuthData));
842
964
  }
843
965
  const authContext = {
844
- organizationId: phantomOptions.organizationId,
845
- parentOrganizationId: phantomOptions.parentOrganizationId,
966
+ publicKey: phantomOptions.publicKey,
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:") && !authUrl.startsWith("http://localhost")) {
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
  });
@@ -906,10 +1030,30 @@ var BrowserAuthProvider = class {
906
1030
  sessionId,
907
1031
  accountDerivationIndex: accountDerivationIndex ? parseInt(accountDerivationIndex) : void 0
908
1032
  });
1033
+ const organizationId = this.urlParamsAccessor.getParam("organization_id");
1034
+ const expiresInMs = this.urlParamsAccessor.getParam("expires_in_ms");
1035
+ debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Auth redirect parameters", {
1036
+ walletId,
1037
+ organizationId,
1038
+ sessionId,
1039
+ accountDerivationIndex,
1040
+ expiresInMs
1041
+ });
1042
+ if (!organizationId) {
1043
+ debug.error(DebugCategory.PHANTOM_CONNECT_AUTH, "Missing organization_id in auth response");
1044
+ throw new Error("Missing organization_id in auth response");
1045
+ }
1046
+ if (organizationId.startsWith("temp-")) {
1047
+ debug.warn(DebugCategory.PHANTOM_CONNECT_AUTH, "Received temporary organization_id, server may not be configured properly", {
1048
+ organizationId
1049
+ });
1050
+ }
909
1051
  return {
910
1052
  walletId,
1053
+ organizationId,
911
1054
  userInfo: context,
912
- accountDerivationIndex: accountDerivationIndex ? parseInt(accountDerivationIndex) : void 0
1055
+ accountDerivationIndex: accountDerivationIndex ? parseInt(accountDerivationIndex) : 0,
1056
+ expiresInMs: expiresInMs ? parseInt(expiresInMs) : 0
913
1057
  };
914
1058
  } catch (error) {
915
1059
  sessionStorage.removeItem("phantom-auth-context");
@@ -939,7 +1083,7 @@ function parseBrowserFromUserAgent(userAgent, hasBraveAPI) {
939
1083
  let name = "unknown";
940
1084
  let version = "unknown";
941
1085
  if (!userAgent || typeof userAgent !== "string") {
942
- return { name, version };
1086
+ return { name, version, userAgent: "unknown" };
943
1087
  }
944
1088
  try {
945
1089
  if (userAgent.includes("Edg/")) {
@@ -1021,11 +1165,11 @@ function parseBrowserFromUserAgent(userAgent, hasBraveAPI) {
1021
1165
  }
1022
1166
  } catch (error) {
1023
1167
  }
1024
- return { name, version };
1168
+ return { name, version, userAgent };
1025
1169
  }
1026
1170
  function detectBrowser() {
1027
1171
  if (typeof window === "undefined" || !window.navigator?.userAgent) {
1028
- return { name: "unknown", version: "unknown" };
1172
+ return { name: "unknown", version: "unknown", userAgent: "unknown" };
1029
1173
  }
1030
1174
  const userAgent = window.navigator.userAgent;
1031
1175
  const hasBraveAPI = !!navigator.brave;
@@ -1040,25 +1184,70 @@ function getBrowserDisplayName() {
1040
1184
  const capitalizedName = name.charAt(0).toUpperCase() + name.slice(1);
1041
1185
  return version !== "unknown" ? `${capitalizedName} ${version}` : capitalizedName;
1042
1186
  }
1187
+ function isMobileDevice() {
1188
+ if (typeof window === "undefined" || !window.navigator?.userAgent) {
1189
+ return false;
1190
+ }
1191
+ const userAgent = window.navigator.userAgent.toLowerCase();
1192
+ const mobilePatterns = [
1193
+ /android/,
1194
+ /iphone|ipad|ipod/,
1195
+ /blackberry/,
1196
+ /windows phone/,
1197
+ /mobile/,
1198
+ /tablet/,
1199
+ /silk/,
1200
+ /kindle/,
1201
+ /opera mini/,
1202
+ /opera mobi/
1203
+ ];
1204
+ const isMobileUA = mobilePatterns.some((pattern) => pattern.test(userAgent));
1205
+ let isSmallScreen = false;
1206
+ try {
1207
+ isSmallScreen = window.screen.width <= 768 || window.screen.height <= 768;
1208
+ } catch (error) {
1209
+ isSmallScreen = false;
1210
+ }
1211
+ let isTouchDevice = false;
1212
+ try {
1213
+ isTouchDevice = "ontouchstart" in window || navigator.maxTouchPoints > 0;
1214
+ } catch (error) {
1215
+ isTouchDevice = false;
1216
+ }
1217
+ return isMobileUA || isSmallScreen && isTouchDevice;
1218
+ }
1043
1219
 
1044
1220
  // src/providers/embedded/index.ts
1221
+ var import_constants2 = require("@phantom/constants");
1045
1222
  var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvider {
1046
1223
  constructor(config) {
1047
1224
  debug.log(DebugCategory.EMBEDDED_PROVIDER, "Initializing Browser EmbeddedProvider", { config });
1048
1225
  const urlParamsAccessor = new BrowserURLParamsAccessor();
1049
1226
  const stamper = new import_indexed_db_stamper.IndexedDbStamper({
1050
- dbName: `phantom-embedded-sdk-${config.organizationId}`,
1227
+ dbName: `phantom-embedded-sdk-${config.appId}`,
1051
1228
  storeName: "crypto-keys",
1052
1229
  keyName: "signing-key"
1053
1230
  });
1054
1231
  const platformName = getPlatformName();
1232
+ const { name: browserName, version } = detectBrowser();
1055
1233
  const platform = {
1056
1234
  storage: new BrowserStorage(),
1057
1235
  authProvider: new BrowserAuthProvider(urlParamsAccessor),
1058
1236
  urlParamsAccessor,
1059
1237
  stamper,
1060
- name: platformName
1238
+ name: platformName,
1061
1239
  // Use detected browser name and version for identification
1240
+ analyticsHeaders: {
1241
+ [import_constants2.ANALYTICS_HEADERS.SDK_TYPE]: "browser",
1242
+ [import_constants2.ANALYTICS_HEADERS.PLATFORM]: browserName,
1243
+ // firefox, chrome, safari, etc.
1244
+ [import_constants2.ANALYTICS_HEADERS.PLATFORM_VERSION]: version,
1245
+ // Full user agent for more detailed info
1246
+ [import_constants2.ANALYTICS_HEADERS.APP_ID]: config.appId,
1247
+ [import_constants2.ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
1248
+ [import_constants2.ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.11"
1249
+ // Replaced at build time
1250
+ }
1062
1251
  };
1063
1252
  debug.log(DebugCategory.EMBEDDED_PROVIDER, "Detected platform", { platformName });
1064
1253
  const logger = new BrowserLogger();
@@ -1068,6 +1257,7 @@ var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvi
1068
1257
  };
1069
1258
 
1070
1259
  // src/ProviderManager.ts
1260
+ var import_constants3 = require("@phantom/constants");
1071
1261
  var ProviderManager = class {
1072
1262
  // Track which providers have forwarding set up
1073
1263
  constructor(config) {
@@ -1086,6 +1276,15 @@ var ProviderManager = class {
1086
1276
  currentProviderKey: this.currentProviderKey
1087
1277
  });
1088
1278
  }
1279
+ getValidatedCurrentUrl() {
1280
+ if (typeof window === "undefined")
1281
+ return "";
1282
+ const currentUrl = window.location.href;
1283
+ if (!currentUrl.startsWith("http:") && !currentUrl.startsWith("https:")) {
1284
+ throw new Error("Invalid URL protocol - only HTTP/HTTPS URLs are supported");
1285
+ }
1286
+ return currentUrl;
1287
+ }
1089
1288
  /**
1090
1289
  * Switch to a different provider type
1091
1290
  */
@@ -1117,7 +1316,8 @@ var ProviderManager = class {
1117
1316
  getCurrentProviderInfo() {
1118
1317
  if (!this.currentProviderKey)
1119
1318
  return null;
1120
- const [type, embeddedWalletType] = this.currentProviderKey.split("-");
1319
+ const parts = this.currentProviderKey.split("-");
1320
+ const [type, embeddedWalletType] = parts;
1121
1321
  return {
1122
1322
  type,
1123
1323
  embeddedWalletType
@@ -1263,7 +1463,7 @@ var ProviderManager = class {
1263
1463
  */
1264
1464
  setDefaultProvider() {
1265
1465
  const defaultType = this.config.providerType || "embedded";
1266
- const defaultEmbeddedType = this.config.embeddedWalletType || "app-wallet";
1466
+ const defaultEmbeddedType = this.config.embeddedWalletType || "user-wallet";
1267
1467
  this.createProvider(defaultType, defaultEmbeddedType);
1268
1468
  this.switchProvider(defaultType, { embeddedWalletType: defaultEmbeddedType });
1269
1469
  }
@@ -1277,22 +1477,27 @@ var ProviderManager = class {
1277
1477
  let provider;
1278
1478
  if (type === "injected") {
1279
1479
  provider = new InjectedProvider({
1280
- solanaProvider: this.config.solanaProvider || "web3js",
1281
- addressTypes: this.config.addressTypes
1480
+ addressTypes: this.config.addressTypes || [import_client.AddressType.solana]
1282
1481
  });
1283
- } else {
1284
- if (!this.config.apiBaseUrl || !this.config.appId) {
1285
- throw new Error("apiBaseUrl and appId are required for embedded provider");
1482
+ } else if (type === "embedded") {
1483
+ if (!this.config.appId) {
1484
+ throw new Error("appId is required for embedded provider");
1286
1485
  }
1486
+ const apiBaseUrl = this.config.apiBaseUrl || import_constants3.DEFAULT_WALLET_API_URL;
1487
+ const authUrl = this.config.authOptions?.authUrl || import_constants3.DEFAULT_AUTH_URL;
1287
1488
  provider = new EmbeddedProvider({
1288
- apiBaseUrl: this.config.apiBaseUrl,
1289
- organizationId: this.config.appId,
1489
+ apiBaseUrl,
1290
1490
  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"
1491
+ authOptions: {
1492
+ ...this.config.authOptions || {},
1493
+ authUrl,
1494
+ redirectUrl: this.config.authOptions?.redirectUrl || this.getValidatedCurrentUrl()
1495
+ },
1496
+ embeddedWalletType: embeddedWalletType || import_constants3.DEFAULT_EMBEDDED_WALLET_TYPE,
1497
+ addressTypes: this.config.addressTypes || [import_client.AddressType.solana]
1295
1498
  });
1499
+ } else {
1500
+ throw new Error(`Unsupported provider type: ${type}`);
1296
1501
  }
1297
1502
  this.providers.set(key, provider);
1298
1503
  }
@@ -1302,8 +1507,10 @@ var ProviderManager = class {
1302
1507
  getProviderKey(type, embeddedWalletType) {
1303
1508
  if (type === "injected") {
1304
1509
  return "injected";
1510
+ } else if (type === "embedded") {
1511
+ return `embedded-${embeddedWalletType || "app-wallet"}`;
1305
1512
  }
1306
- return `embedded-${embeddedWalletType || "app-wallet"}`;
1513
+ throw new Error(`Unsupported provider type: ${type}`);
1307
1514
  }
1308
1515
  /**
1309
1516
  * Save provider preference to localStorage
@@ -1364,6 +1571,7 @@ async function waitForPhantomExtension(timeoutMs = 3e3) {
1364
1571
  }
1365
1572
 
1366
1573
  // src/BrowserSDK.ts
1574
+ var import_constants4 = require("@phantom/constants");
1367
1575
  var BrowserSDK = class {
1368
1576
  constructor(config) {
1369
1577
  debug.info(DebugCategory.BROWSER_SDK, "Initializing BrowserSDK", {
@@ -1375,7 +1583,7 @@ var BrowserSDK = class {
1375
1583
  debug.error(DebugCategory.BROWSER_SDK, "Invalid providerType", { providerType: config.providerType });
1376
1584
  throw new Error(`Invalid providerType: ${config.providerType}. Must be "injected" or "embedded".`);
1377
1585
  }
1378
- const embeddedWalletType = config.embeddedWalletType || "app-wallet";
1586
+ const embeddedWalletType = config.embeddedWalletType || import_constants4.DEFAULT_EMBEDDED_WALLET_TYPE;
1379
1587
  if (config.providerType === "embedded" && !["app-wallet", "user-wallet"].includes(embeddedWalletType)) {
1380
1588
  debug.error(DebugCategory.BROWSER_SDK, "Invalid embeddedWalletType", {
1381
1589
  embeddedWalletType: config.embeddedWalletType
@@ -1511,7 +1719,7 @@ var BrowserSDK = class {
1511
1719
  async autoConnect() {
1512
1720
  debug.log(DebugCategory.BROWSER_SDK, "Attempting auto-connect");
1513
1721
  const currentProvider = this.providerManager.getCurrentProvider();
1514
- if (currentProvider && "autoConnect" in currentProvider) {
1722
+ if (currentProvider) {
1515
1723
  await currentProvider.autoConnect();
1516
1724
  } else {
1517
1725
  debug.warn(DebugCategory.BROWSER_SDK, "Current provider does not support auto-connect", {
@@ -1660,9 +1868,16 @@ var BrowserSDK = class {
1660
1868
  }
1661
1869
  };
1662
1870
 
1663
- // src/types.ts
1664
- var import_client4 = require("@phantom/client");
1871
+ // src/utils/deeplink.ts
1872
+ function getDeeplinkToPhantom(ref) {
1873
+ if (!window.location.href.startsWith("http:") && !window.location.href.startsWith("https:")) {
1874
+ throw new Error("Invalid URL protocol - only HTTP/HTTPS URLs are supported for deeplinks");
1875
+ }
1876
+ const currentUrl = encodeURIComponent(window.location.href);
1877
+ const refParam = ref ? `?ref=${encodeURIComponent(ref)}` : "";
1878
+ return `https://phantom.app/ul/browse/${currentUrl}${refParam}`;
1879
+ }
1665
1880
 
1666
1881
  // src/index.ts
1667
- var import_constants2 = require("@phantom/constants");
1882
+ var import_constants5 = require("@phantom/constants");
1668
1883
  var import_client5 = require("@phantom/client");