@phantom/browser-sdk 1.0.0-beta.0 → 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
@@ -20,23 +20,27 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
20
20
  // src/index.ts
21
21
  var src_exports = {};
22
22
  __export(src_exports, {
23
- AddressType: () => import_client3.AddressType,
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_constants4.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,
34
- parseBrowserFromUserAgent: () => parseBrowserFromUserAgent
33
+ isMobileDevice: () => isMobileDevice,
34
+ parseBrowserFromUserAgent: () => parseBrowserFromUserAgent,
35
+ waitForPhantomExtension: () => waitForPhantomExtension
35
36
  });
36
37
  module.exports = __toCommonJS(src_exports);
37
38
 
38
- // src/providers/injected/index.ts
39
+ // src/types.ts
39
40
  var import_client = require("@phantom/client");
41
+
42
+ // src/providers/injected/index.ts
43
+ var import_client4 = require("@phantom/client");
40
44
  var import_browser_injected_sdk = require("@phantom/browser-injected-sdk");
41
45
  var import_solana = require("@phantom/browser-injected-sdk/solana");
42
46
  var import_ethereum = require("@phantom/browser-injected-sdk/ethereum");
@@ -117,97 +121,206 @@ var DebugCategory = {
117
121
  };
118
122
 
119
123
  // src/providers/injected/chains/SolanaChain.ts
120
- var import_constants = require("@phantom/constants");
124
+ var import_eventemitter3 = require("eventemitter3");
125
+ var import_client2 = require("@phantom/client");
121
126
  var import_buffer = require("buffer");
122
127
  var InjectedSolanaChain = class {
123
- constructor(phantom) {
128
+ constructor(phantom, callbacks) {
129
+ this._connected = false;
130
+ this._publicKey = null;
131
+ this.eventEmitter = new import_eventemitter3.EventEmitter();
124
132
  this.phantom = phantom;
133
+ this.callbacks = callbacks;
134
+ this.setupEventListeners();
135
+ this.syncInitialState();
136
+ }
137
+ // Wallet adapter compliant properties
138
+ get connected() {
139
+ return this._connected;
140
+ }
141
+ get publicKey() {
142
+ return this._publicKey;
143
+ }
144
+ // Connection methods - delegate to provider
145
+ connect(_options) {
146
+ if (!this.callbacks.isConnected()) {
147
+ return Promise.reject(new Error("Provider not connected. Call provider connect first."));
148
+ }
149
+ const addresses = this.callbacks.getAddresses();
150
+ const solanaAddress = addresses.find((addr) => addr.addressType === import_client2.AddressType.solana);
151
+ if (!solanaAddress) {
152
+ return Promise.reject(new Error("Solana not enabled for this provider"));
153
+ }
154
+ this.updateConnectionState(true, solanaAddress.address);
155
+ return Promise.resolve({ publicKey: solanaAddress.address });
125
156
  }
157
+ async disconnect() {
158
+ await this.callbacks.disconnect();
159
+ }
160
+ // Standard wallet adapter methods
126
161
  async signMessage(message) {
127
162
  const messageBytes = typeof message === "string" ? new TextEncoder().encode(message) : message;
128
163
  const result = await this.phantom.solana.signMessage(messageBytes);
129
- const signature = result.signature instanceof Uint8Array ? import_buffer.Buffer.from(result.signature).toString("base64") : result.signature;
130
164
  return {
131
- signature,
132
- rawSignature: signature
165
+ signature: result.signature instanceof Uint8Array ? result.signature : new Uint8Array(import_buffer.Buffer.from(result.signature, "base64")),
166
+ publicKey: this._publicKey || ""
133
167
  };
134
168
  }
135
- signTransaction(_transaction) {
136
- throw new Error("signTransaction not available in browser-injected-sdk, use signAndSendTransaction instead");
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
+ }
137
179
  }
138
180
  async signAndSendTransaction(transaction) {
139
181
  const result = await this.phantom.solana.signAndSendTransaction(transaction);
140
- return {
141
- hash: result.signature,
142
- rawTransaction: result.signature,
143
- blockExplorer: (0, import_constants.getExplorerUrl)(import_constants.NetworkId.SOLANA_MAINNET, "transaction", result.signature)
144
- };
182
+ return { signature: result.signature };
145
183
  }
146
- async connect(_options) {
147
- const address = await this.phantom.solana.connect();
148
- if (!address) {
149
- throw new Error("Failed to connect to Solana wallet");
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);
150
193
  }
151
- return { publicKey: address };
152
- }
153
- async disconnect() {
154
- return await this.phantom.solana.disconnect();
155
- }
156
- async switchNetwork(_network) {
157
194
  }
158
- async getPublicKey() {
195
+ async signAndSendAllTransactions(transactions) {
196
+ if (!this.callbacks.isConnected()) {
197
+ return Promise.reject(new Error("Provider not connected. Call provider connect first."));
198
+ }
159
199
  try {
160
- const address = await this.phantom.solana.getAccount();
161
- return address || null;
162
- } catch {
163
- return null;
200
+ const result = await this.phantom.solana.signAndSendAllTransactions(transactions);
201
+ return { signatures: result.signatures };
202
+ } catch (error) {
203
+ return Promise.reject(error);
164
204
  }
165
205
  }
206
+ switchNetwork(_network) {
207
+ return Promise.resolve();
208
+ }
209
+ // Legacy methods
210
+ getPublicKey() {
211
+ return Promise.resolve(this._publicKey);
212
+ }
166
213
  isConnected() {
167
- try {
168
- return !!this.phantom.extension?.isInstalled();
169
- } catch {
170
- return false;
214
+ return this._connected && this.callbacks.isConnected();
215
+ }
216
+ setupEventListeners() {
217
+ this.phantom.solana.addEventListener("connect", (publicKey) => {
218
+ this.updateConnectionState(true, publicKey);
219
+ this.eventEmitter.emit("connect", publicKey);
220
+ });
221
+ this.phantom.solana.addEventListener("disconnect", () => {
222
+ this.updateConnectionState(false, null);
223
+ this.eventEmitter.emit("disconnect");
224
+ });
225
+ this.phantom.solana.addEventListener("accountChanged", (publicKey) => {
226
+ this._publicKey = publicKey;
227
+ this.eventEmitter.emit("accountChanged", publicKey);
228
+ });
229
+ this.callbacks.on("connect", (data) => {
230
+ const solanaAddress = data.addresses?.find((addr) => addr.addressType === import_client2.AddressType.solana);
231
+ if (solanaAddress) {
232
+ this.updateConnectionState(true, solanaAddress.address);
233
+ }
234
+ });
235
+ this.callbacks.on("disconnect", () => {
236
+ this.updateConnectionState(false, null);
237
+ });
238
+ }
239
+ syncInitialState() {
240
+ if (this.callbacks.isConnected()) {
241
+ const solanaAddress = this.callbacks.getAddresses().find((addr) => addr.addressType === import_client2.AddressType.solana);
242
+ if (solanaAddress) {
243
+ this.updateConnectionState(true, solanaAddress.address);
244
+ }
171
245
  }
172
246
  }
247
+ updateConnectionState(connected, publicKey) {
248
+ this._connected = connected;
249
+ this._publicKey = publicKey;
250
+ }
251
+ // Event methods for interface compliance
252
+ on(event, listener) {
253
+ this.eventEmitter.on(event, listener);
254
+ }
255
+ off(event, listener) {
256
+ this.eventEmitter.off(event, listener);
257
+ }
173
258
  };
174
259
 
175
260
  // src/providers/injected/chains/EthereumChain.ts
176
- var import_constants2 = require("@phantom/constants");
261
+ var import_eventemitter32 = require("eventemitter3");
262
+ var import_client3 = require("@phantom/client");
177
263
  var InjectedEthereumChain = class {
178
- constructor(phantom) {
264
+ constructor(phantom, callbacks) {
265
+ this._connected = false;
266
+ this._chainId = "0x1";
267
+ this._accounts = [];
268
+ this.eventEmitter = new import_eventemitter32.EventEmitter();
179
269
  this.phantom = phantom;
270
+ this.callbacks = callbacks;
271
+ this.setupEventListeners();
272
+ this.syncInitialState();
273
+ }
274
+ // EIP-1193 compliant properties
275
+ get connected() {
276
+ return this._connected;
277
+ }
278
+ get chainId() {
279
+ return this._chainId;
280
+ }
281
+ get accounts() {
282
+ return this._accounts;
180
283
  }
284
+ // EIP-1193 core method with eth_signTransaction support
181
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
+ }
182
291
  const provider = await this.phantom.ethereum.getProvider();
183
292
  return await provider.request(args);
184
293
  }
294
+ // Connection methods - delegate to provider
295
+ connect() {
296
+ if (!this.callbacks.isConnected()) {
297
+ return Promise.reject(new Error("Provider not connected. Call provider connect first."));
298
+ }
299
+ const addresses = this.callbacks.getAddresses();
300
+ const ethAddresses = addresses.filter((addr) => addr.addressType === import_client3.AddressType.ethereum).map((addr) => addr.address);
301
+ this.updateConnectionState(true, ethAddresses);
302
+ return Promise.resolve(ethAddresses);
303
+ }
304
+ async disconnect() {
305
+ await this.callbacks.disconnect();
306
+ }
307
+ // Standard compliant methods (return raw values, not wrapped objects)
185
308
  async signPersonalMessage(message, address) {
186
- const signature = await this.phantom.ethereum.signPersonalMessage(message, address);
187
- return {
188
- signature,
189
- rawSignature: signature
190
- };
309
+ return await this.phantom.ethereum.signPersonalMessage(message, address);
191
310
  }
192
311
  async signTypedData(typedData, address) {
193
- const signature = await this.phantom.ethereum.signTypedData(typedData, address);
194
- return {
195
- signature,
196
- rawSignature: signature
197
- };
312
+ return await this.phantom.ethereum.signTypedData(typedData, address);
313
+ }
314
+ async signTransaction(transaction) {
315
+ return await this.phantom.ethereum.signTransaction(transaction);
198
316
  }
199
317
  async sendTransaction(transaction) {
200
- const hash = await this.phantom.ethereum.sendTransaction(transaction);
201
- const chainId = await this.getChainId();
202
- const networkId = (0, import_constants2.chainIdToNetworkId)(chainId) || import_constants2.NetworkId.ETHEREUM_MAINNET;
203
- return {
204
- hash,
205
- rawTransaction: hash,
206
- blockExplorer: (0, import_constants2.getExplorerUrl)(networkId, "transaction", hash)
207
- };
318
+ return await this.phantom.ethereum.sendTransaction(transaction);
208
319
  }
209
320
  async switchChain(chainId) {
210
- return await this.phantom.ethereum.switchChain(`0x${chainId.toString(16)}`);
321
+ await this.phantom.ethereum.switchChain(`0x${chainId.toString(16)}`);
322
+ this._chainId = `0x${chainId.toString(16)}`;
323
+ this.eventEmitter.emit("chainChanged", this._chainId);
211
324
  }
212
325
  async getChainId() {
213
326
  const chainId = await this.phantom.ethereum.getChainId();
@@ -217,12 +330,56 @@ var InjectedEthereumChain = class {
217
330
  return await this.phantom.ethereum.getAccounts();
218
331
  }
219
332
  isConnected() {
220
- try {
221
- return !!this.phantom.extension?.isInstalled();
222
- } catch {
223
- return false;
333
+ return this._connected && this.callbacks.isConnected();
334
+ }
335
+ setupEventListeners() {
336
+ this.phantom.ethereum.addEventListener("connect", (accounts) => {
337
+ this.updateConnectionState(true, accounts);
338
+ this.eventEmitter.emit("connect", { chainId: this._chainId });
339
+ this.eventEmitter.emit("accountsChanged", accounts);
340
+ });
341
+ this.phantom.ethereum.addEventListener("disconnect", () => {
342
+ this.updateConnectionState(false, []);
343
+ this.eventEmitter.emit("disconnect", { code: 4900, message: "Provider disconnected" });
344
+ this.eventEmitter.emit("accountsChanged", []);
345
+ });
346
+ this.phantom.ethereum.addEventListener("accountsChanged", (accounts) => {
347
+ this._accounts = accounts;
348
+ this.eventEmitter.emit("accountsChanged", accounts);
349
+ });
350
+ this.phantom.ethereum.addEventListener("chainChanged", (chainId) => {
351
+ this._chainId = chainId;
352
+ this.eventEmitter.emit("chainChanged", chainId);
353
+ });
354
+ this.callbacks.on("connect", (data) => {
355
+ const ethAddresses = data.addresses?.filter((addr) => addr.addressType === import_client3.AddressType.ethereum)?.map((addr) => addr.address) || [];
356
+ if (ethAddresses.length > 0) {
357
+ this.updateConnectionState(true, ethAddresses);
358
+ }
359
+ });
360
+ this.callbacks.on("disconnect", () => {
361
+ this.updateConnectionState(false, []);
362
+ });
363
+ }
364
+ syncInitialState() {
365
+ if (this.callbacks.isConnected()) {
366
+ const ethAddresses = this.callbacks.getAddresses().filter((addr) => addr.addressType === import_client3.AddressType.ethereum).map((addr) => addr.address);
367
+ if (ethAddresses.length > 0) {
368
+ this.updateConnectionState(true, ethAddresses);
369
+ }
224
370
  }
225
371
  }
372
+ updateConnectionState(connected, accounts) {
373
+ this._connected = connected;
374
+ this._accounts = accounts;
375
+ }
376
+ // Event methods for interface compliance
377
+ on(event, listener) {
378
+ this.eventEmitter.on(event, listener);
379
+ }
380
+ off(event, listener) {
381
+ this.eventEmitter.off(event, listener);
382
+ }
226
383
  };
227
384
 
228
385
  // src/providers/injected/index.ts
@@ -238,11 +395,11 @@ var InjectedProvider = class {
238
395
  this.addressTypes = config.addressTypes;
239
396
  debug.log(DebugCategory.INJECTED_PROVIDER, "Address types configured", { addressTypes: this.addressTypes });
240
397
  const plugins = [(0, import_browser_injected_sdk.createExtensionPlugin)()];
241
- if (this.addressTypes.includes(import_client.AddressType.solana)) {
398
+ if (this.addressTypes.includes(import_client4.AddressType.solana)) {
242
399
  plugins.push((0, import_solana.createSolanaPlugin)());
243
400
  debug.log(DebugCategory.INJECTED_PROVIDER, "Solana plugin added");
244
401
  }
245
- if (this.addressTypes.includes(import_client.AddressType.ethereum)) {
402
+ if (this.addressTypes.includes(import_client4.AddressType.ethereum)) {
246
403
  plugins.push((0, import_ethereum.createEthereumPlugin)());
247
404
  debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum plugin added");
248
405
  }
@@ -252,17 +409,24 @@ var InjectedProvider = class {
252
409
  pluginCount: plugins.length
253
410
  });
254
411
  this.phantom = (0, import_browser_injected_sdk.createPhantom)({ plugins });
412
+ const callbacks = this.createCallbacks();
413
+ if (this.addressTypes.includes(import_client4.AddressType.solana)) {
414
+ this._solanaChain = new InjectedSolanaChain(this.phantom, callbacks);
415
+ }
416
+ if (this.addressTypes.includes(import_client4.AddressType.ethereum)) {
417
+ this._ethereumChain = new InjectedEthereumChain(this.phantom, callbacks);
418
+ }
255
419
  debug.info(DebugCategory.INJECTED_PROVIDER, "InjectedProvider initialized");
256
420
  }
257
421
  /**
258
422
  * Access to Solana chain operations
259
423
  */
260
424
  get solana() {
261
- if (!this.addressTypes.includes(import_client.AddressType.solana)) {
425
+ if (!this.addressTypes.includes(import_client4.AddressType.solana)) {
262
426
  throw new Error("Solana not enabled for this provider");
263
427
  }
264
428
  if (!this._solanaChain) {
265
- this._solanaChain = new InjectedSolanaChain(this.phantom);
429
+ throw new Error("Solana chain not initialized");
266
430
  }
267
431
  return this._solanaChain;
268
432
  }
@@ -270,11 +434,11 @@ var InjectedProvider = class {
270
434
  * Access to Ethereum chain operations
271
435
  */
272
436
  get ethereum() {
273
- if (!this.addressTypes.includes(import_client.AddressType.ethereum)) {
437
+ if (!this.addressTypes.includes(import_client4.AddressType.ethereum)) {
274
438
  throw new Error("Ethereum not enabled for this provider");
275
439
  }
276
440
  if (!this._ethereumChain) {
277
- this._ethereumChain = new InjectedEthereumChain(this.phantom);
441
+ throw new Error("Ethereum chain not initialized");
278
442
  }
279
443
  return this._ethereumChain;
280
444
  }
@@ -300,28 +464,28 @@ var InjectedProvider = class {
300
464
  }
301
465
  debug.log(DebugCategory.INJECTED_PROVIDER, "Phantom extension detected");
302
466
  const connectedAddresses = [];
303
- if (this.addressTypes.includes(import_client.AddressType.solana)) {
467
+ if (this.addressTypes.includes(import_client4.AddressType.solana)) {
304
468
  debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting Solana connection");
305
469
  try {
306
- const result2 = await this.solana.connect();
307
- if (result2.publicKey) {
470
+ const publicKey = await this.phantom.solana.connect();
471
+ if (publicKey) {
308
472
  connectedAddresses.push({
309
- addressType: import_client.AddressType.solana,
310
- address: result2.publicKey
473
+ addressType: import_client4.AddressType.solana,
474
+ address: publicKey
311
475
  });
312
- debug.info(DebugCategory.INJECTED_PROVIDER, "Solana connected successfully", { address: result2.publicKey });
476
+ debug.info(DebugCategory.INJECTED_PROVIDER, "Solana connected successfully", { address: publicKey });
313
477
  }
314
478
  } catch (err) {
315
479
  debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Solana", { error: err });
316
480
  }
317
481
  }
318
- if (this.addressTypes.includes(import_client.AddressType.ethereum)) {
482
+ if (this.addressTypes.includes(import_client4.AddressType.ethereum)) {
319
483
  try {
320
- const accounts = await this.ethereum.getAccounts();
484
+ const accounts = await this.phantom.ethereum.connect();
321
485
  if (accounts && accounts.length > 0) {
322
486
  connectedAddresses.push(
323
487
  ...accounts.map((address) => ({
324
- addressType: import_client.AddressType.ethereum,
488
+ addressType: import_client4.AddressType.ethereum,
325
489
  address
326
490
  }))
327
491
  );
@@ -363,19 +527,17 @@ var InjectedProvider = class {
363
527
  }
364
528
  async disconnect() {
365
529
  debug.info(DebugCategory.INJECTED_PROVIDER, "Starting injected provider disconnect");
366
- if (this.addressTypes.includes(import_client.AddressType.solana)) {
530
+ if (this.addressTypes.includes(import_client4.AddressType.solana)) {
367
531
  try {
368
- await this.solana.disconnect();
532
+ await this.phantom.solana.disconnect();
369
533
  debug.log(DebugCategory.INJECTED_PROVIDER, "Solana disconnected successfully");
370
534
  } catch (err) {
371
535
  debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to disconnect Solana", { error: err });
372
536
  }
373
537
  }
374
- if (this.addressTypes.includes(import_client.AddressType.ethereum)) {
538
+ if (this.addressTypes.includes(import_client4.AddressType.ethereum)) {
375
539
  debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum disconnected (no-op)");
376
540
  }
377
- this._solanaChain = void 0;
378
- this._ethereumChain = void 0;
379
541
  this.browserInjectedCleanupFunctions.forEach((cleanup) => cleanup());
380
542
  this.browserInjectedCleanupFunctions = [];
381
543
  this.connected = false;
@@ -385,6 +547,87 @@ var InjectedProvider = class {
385
547
  });
386
548
  debug.info(DebugCategory.INJECTED_PROVIDER, "Injected provider disconnected successfully");
387
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
+ }
388
631
  getAddresses() {
389
632
  return this.addresses;
390
633
  }
@@ -448,10 +691,10 @@ var InjectedProvider = class {
448
691
  }
449
692
  setupBrowserInjectedEvents() {
450
693
  debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up browser-injected-sdk event listeners");
451
- if (this.addressTypes.includes(import_client.AddressType.solana)) {
694
+ if (this.addressTypes.includes(import_client4.AddressType.solana)) {
452
695
  this.setupSolanaEvents();
453
696
  }
454
- if (this.addressTypes.includes(import_client.AddressType.ethereum)) {
697
+ if (this.addressTypes.includes(import_client4.AddressType.ethereum)) {
455
698
  this.setupEthereumEvents();
456
699
  }
457
700
  }
@@ -459,8 +702,8 @@ var InjectedProvider = class {
459
702
  debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up Solana event listeners");
460
703
  const handleSolanaConnect = (publicKey) => {
461
704
  debug.log(DebugCategory.INJECTED_PROVIDER, "Solana connect event received", { publicKey });
462
- const solanaAddress = { addressType: import_client.AddressType.solana, address: publicKey };
463
- if (!this.addresses.find((addr) => addr.addressType === import_client.AddressType.solana)) {
705
+ const solanaAddress = { addressType: import_client4.AddressType.solana, address: publicKey };
706
+ if (!this.addresses.find((addr) => addr.addressType === import_client4.AddressType.solana)) {
464
707
  this.addresses.push(solanaAddress);
465
708
  }
466
709
  this.connected = true;
@@ -471,19 +714,19 @@ var InjectedProvider = class {
471
714
  };
472
715
  const handleSolanaDisconnect = () => {
473
716
  debug.log(DebugCategory.INJECTED_PROVIDER, "Solana disconnect event received");
474
- this.addresses = this.addresses.filter((addr) => addr.addressType !== import_client.AddressType.solana);
475
- this.connected = this.addresses.length > 0;
717
+ this.addresses = this.addresses.filter((addr) => addr.addressType !== import_client4.AddressType.solana);
718
+ this.connected = false;
476
719
  this.emit("disconnect", {
477
720
  source: "injected-extension"
478
721
  });
479
722
  };
480
723
  const handleSolanaAccountChanged = (publicKey) => {
481
724
  debug.log(DebugCategory.INJECTED_PROVIDER, "Solana account changed event received", { publicKey });
482
- const solanaIndex = this.addresses.findIndex((addr) => addr.addressType === import_client.AddressType.solana);
725
+ const solanaIndex = this.addresses.findIndex((addr) => addr.addressType === import_client4.AddressType.solana);
483
726
  if (solanaIndex >= 0) {
484
- this.addresses[solanaIndex] = { addressType: import_client.AddressType.solana, address: publicKey };
727
+ this.addresses[solanaIndex] = { addressType: import_client4.AddressType.solana, address: publicKey };
485
728
  } else {
486
- this.addresses.push({ addressType: import_client.AddressType.solana, address: publicKey });
729
+ this.addresses.push({ addressType: import_client4.AddressType.solana, address: publicKey });
487
730
  }
488
731
  this.emit("connect", {
489
732
  addresses: this.addresses,
@@ -493,22 +736,20 @@ var InjectedProvider = class {
493
736
  const cleanupConnect = this.phantom.solana.addEventListener("connect", handleSolanaConnect);
494
737
  const cleanupDisconnect = this.phantom.solana.addEventListener("disconnect", handleSolanaDisconnect);
495
738
  const cleanupAccountChanged = this.phantom.solana.addEventListener("accountChanged", handleSolanaAccountChanged);
496
- this.browserInjectedCleanupFunctions.push(
497
- cleanupConnect,
498
- cleanupDisconnect,
499
- cleanupAccountChanged
500
- );
739
+ this.browserInjectedCleanupFunctions.push(cleanupConnect, cleanupDisconnect, cleanupAccountChanged);
501
740
  }
502
741
  setupEthereumEvents() {
503
742
  debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up Ethereum event listeners");
504
743
  const handleEthereumConnect = (accounts) => {
505
744
  debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum connect event received", { accounts });
506
- this.addresses = this.addresses.filter((addr) => addr.addressType !== import_client.AddressType.ethereum);
745
+ this.addresses = this.addresses.filter((addr) => addr.addressType !== import_client4.AddressType.ethereum);
507
746
  if (accounts && accounts.length > 0) {
508
- this.addresses.push(...accounts.map((address) => ({
509
- addressType: import_client.AddressType.ethereum,
510
- address
511
- })));
747
+ this.addresses.push(
748
+ ...accounts.map((address) => ({
749
+ addressType: import_client4.AddressType.ethereum,
750
+ address
751
+ }))
752
+ );
512
753
  }
513
754
  this.connected = this.addresses.length > 0;
514
755
  this.emit("connect", {
@@ -518,34 +759,63 @@ var InjectedProvider = class {
518
759
  };
519
760
  const handleEthereumDisconnect = () => {
520
761
  debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum disconnect event received");
521
- this.addresses = this.addresses.filter((addr) => addr.addressType !== import_client.AddressType.ethereum);
522
- this.connected = this.addresses.length > 0;
762
+ this.addresses = this.addresses.filter((addr) => addr.addressType !== import_client4.AddressType.ethereum);
763
+ this.connected = false;
523
764
  this.emit("disconnect", {
524
765
  source: "injected-extension"
525
766
  });
526
767
  };
527
768
  const handleEthereumAccountsChanged = (accounts) => {
528
769
  debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum accounts changed event received", { accounts });
529
- this.addresses = this.addresses.filter((addr) => addr.addressType !== import_client.AddressType.ethereum);
770
+ this.addresses = this.addresses.filter((addr) => addr.addressType !== import_client4.AddressType.ethereum);
530
771
  if (accounts && accounts.length > 0) {
531
- this.addresses.push(...accounts.map((address) => ({
532
- addressType: import_client.AddressType.ethereum,
533
- address
534
- })));
772
+ this.addresses.push(
773
+ ...accounts.map((address) => ({
774
+ addressType: import_client4.AddressType.ethereum,
775
+ address
776
+ }))
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
+ });
535
787
  }
536
- this.emit("connect", {
537
- addresses: this.addresses,
538
- source: "injected-extension-account-change"
539
- });
540
788
  };
541
789
  const cleanupConnect = this.phantom.ethereum.addEventListener("connect", handleEthereumConnect);
542
790
  const cleanupDisconnect = this.phantom.ethereum.addEventListener("disconnect", handleEthereumDisconnect);
543
- const cleanupAccountsChanged = this.phantom.ethereum.addEventListener("accountsChanged", handleEthereumAccountsChanged);
544
- this.browserInjectedCleanupFunctions.push(
545
- cleanupConnect,
546
- cleanupDisconnect,
547
- cleanupAccountsChanged
791
+ const cleanupAccountsChanged = this.phantom.ethereum.addEventListener(
792
+ "accountsChanged",
793
+ handleEthereumAccountsChanged
548
794
  );
795
+ this.browserInjectedCleanupFunctions.push(cleanupConnect, cleanupDisconnect, cleanupAccountsChanged);
796
+ }
797
+ createCallbacks() {
798
+ return {
799
+ connect: async () => {
800
+ const result = await this.connect();
801
+ return result.addresses;
802
+ },
803
+ disconnect: async () => {
804
+ await this.disconnect();
805
+ },
806
+ isConnected: () => {
807
+ return this.isConnected();
808
+ },
809
+ getAddresses: () => {
810
+ return this.getAddresses();
811
+ },
812
+ on: (event, callback) => {
813
+ this.on(event, callback);
814
+ },
815
+ off: (event, callback) => {
816
+ this.off(event, callback);
817
+ }
818
+ };
549
819
  }
550
820
  };
551
821
 
@@ -643,15 +913,19 @@ var BrowserURLParamsAccessor = class {
643
913
  };
644
914
  var browserUrlParamsAccessor = new BrowserURLParamsAccessor();
645
915
 
646
- // src/constants.ts
647
- var DEFAULT_AUTH_URL = "https://connect.phantom.app";
648
- var DEFAULT_WALLET_API_URL = "https://api.phantom.app/v1/wallets";
649
-
650
916
  // src/providers/embedded/adapters/auth.ts
917
+ var import_constants = require("@phantom/constants");
651
918
  var BrowserAuthProvider = class {
652
919
  constructor(urlParamsAccessor) {
653
920
  this.urlParamsAccessor = urlParamsAccessor;
654
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
+ }
655
929
  authenticate(options) {
656
930
  return new Promise((resolve) => {
657
931
  if ("jwtToken" in options) {
@@ -660,23 +934,20 @@ var BrowserAuthProvider = class {
660
934
  const phantomOptions = options;
661
935
  debug.info(DebugCategory.PHANTOM_CONNECT_AUTH, "Starting Phantom Connect authentication", {
662
936
  organizationId: phantomOptions.organizationId,
663
- parentOrganizationId: phantomOptions.parentOrganizationId,
937
+ appId: phantomOptions.appId,
664
938
  provider: phantomOptions.provider,
665
939
  authUrl: phantomOptions.authUrl,
666
940
  hasCustomData: !!phantomOptions.customAuthData
667
941
  });
668
- const baseUrl = phantomOptions.authUrl || DEFAULT_AUTH_URL;
942
+ const baseUrl = phantomOptions.authUrl || import_constants.DEFAULT_AUTH_URL;
669
943
  debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Using auth URL", { baseUrl });
670
944
  const params = new URLSearchParams({
671
945
  organization_id: phantomOptions.organizationId,
672
- parent_organization_id: phantomOptions.parentOrganizationId,
673
- redirect_uri: phantomOptions.redirectUrl || (typeof window !== "undefined" ? window.location.href : ""),
946
+ app_id: phantomOptions.appId,
947
+ redirect_uri: phantomOptions.redirectUrl || (typeof window !== "undefined" ? this.getValidatedCurrentUrl() : ""),
674
948
  session_id: phantomOptions.sessionId,
675
949
  clear_previous_session: true.toString(),
676
- app_name: phantomOptions.appName || "",
677
- // Optional app name
678
- app_logo: phantomOptions.appLogo || ""
679
- // Optional app logo URL
950
+ sdk_version: "1.0.0-beta.10"
680
951
  });
681
952
  if (phantomOptions.provider) {
682
953
  debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Provider specified, will skip selection", {
@@ -693,7 +964,7 @@ var BrowserAuthProvider = class {
693
964
  }
694
965
  const authContext = {
695
966
  organizationId: phantomOptions.organizationId,
696
- parentOrganizationId: phantomOptions.parentOrganizationId,
967
+ appId: phantomOptions.appId,
697
968
  provider: phantomOptions.provider,
698
969
  sessionId: phantomOptions.sessionId
699
970
  };
@@ -701,6 +972,9 @@ var BrowserAuthProvider = class {
701
972
  debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Stored auth context in session storage", { authContext });
702
973
  const authUrl = `${baseUrl}?${params.toString()}`;
703
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
+ }
704
978
  window.location.href = authUrl;
705
979
  resolve();
706
980
  });
@@ -789,7 +1063,7 @@ function parseBrowserFromUserAgent(userAgent, hasBraveAPI) {
789
1063
  let name = "unknown";
790
1064
  let version = "unknown";
791
1065
  if (!userAgent || typeof userAgent !== "string") {
792
- return { name, version };
1066
+ return { name, version, userAgent: "unknown" };
793
1067
  }
794
1068
  try {
795
1069
  if (userAgent.includes("Edg/")) {
@@ -871,11 +1145,11 @@ function parseBrowserFromUserAgent(userAgent, hasBraveAPI) {
871
1145
  }
872
1146
  } catch (error) {
873
1147
  }
874
- return { name, version };
1148
+ return { name, version, userAgent };
875
1149
  }
876
1150
  function detectBrowser() {
877
1151
  if (typeof window === "undefined" || !window.navigator?.userAgent) {
878
- return { name: "unknown", version: "unknown" };
1152
+ return { name: "unknown", version: "unknown", userAgent: "unknown" };
879
1153
  }
880
1154
  const userAgent = window.navigator.userAgent;
881
1155
  const hasBraveAPI = !!navigator.brave;
@@ -890,25 +1164,70 @@ function getBrowserDisplayName() {
890
1164
  const capitalizedName = name.charAt(0).toUpperCase() + name.slice(1);
891
1165
  return version !== "unknown" ? `${capitalizedName} ${version}` : capitalizedName;
892
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
+ }
893
1199
 
894
1200
  // src/providers/embedded/index.ts
1201
+ var import_constants2 = require("@phantom/constants");
895
1202
  var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvider {
896
1203
  constructor(config) {
897
1204
  debug.log(DebugCategory.EMBEDDED_PROVIDER, "Initializing Browser EmbeddedProvider", { config });
898
1205
  const urlParamsAccessor = new BrowserURLParamsAccessor();
899
1206
  const stamper = new import_indexed_db_stamper.IndexedDbStamper({
900
- dbName: `phantom-embedded-sdk-${config.organizationId}`,
1207
+ dbName: `phantom-embedded-sdk-${config.appId}`,
901
1208
  storeName: "crypto-keys",
902
1209
  keyName: "signing-key"
903
1210
  });
904
1211
  const platformName = getPlatformName();
1212
+ const { name: browserName, version } = detectBrowser();
905
1213
  const platform = {
906
1214
  storage: new BrowserStorage(),
907
1215
  authProvider: new BrowserAuthProvider(urlParamsAccessor),
908
1216
  urlParamsAccessor,
909
1217
  stamper,
910
- name: platformName
1218
+ name: platformName,
911
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
+ }
912
1231
  };
913
1232
  debug.log(DebugCategory.EMBEDDED_PROVIDER, "Detected platform", { platformName });
914
1233
  const logger = new BrowserLogger();
@@ -918,6 +1237,7 @@ var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvi
918
1237
  };
919
1238
 
920
1239
  // src/ProviderManager.ts
1240
+ var import_constants3 = require("@phantom/constants");
921
1241
  var ProviderManager = class {
922
1242
  // Track which providers have forwarding set up
923
1243
  constructor(config) {
@@ -936,6 +1256,15 @@ var ProviderManager = class {
936
1256
  currentProviderKey: this.currentProviderKey
937
1257
  });
938
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
+ }
939
1268
  /**
940
1269
  * Switch to a different provider type
941
1270
  */
@@ -967,7 +1296,8 @@ var ProviderManager = class {
967
1296
  getCurrentProviderInfo() {
968
1297
  if (!this.currentProviderKey)
969
1298
  return null;
970
- const [type, embeddedWalletType] = this.currentProviderKey.split("-");
1299
+ const parts = this.currentProviderKey.split("-");
1300
+ const [type, embeddedWalletType] = parts;
971
1301
  return {
972
1302
  type,
973
1303
  embeddedWalletType
@@ -1091,7 +1421,13 @@ var ProviderManager = class {
1091
1421
  return;
1092
1422
  }
1093
1423
  debug.log(DebugCategory.PROVIDER_MANAGER, "Setting up event forwarding from current provider");
1094
- const eventsToForward = ["connect_start", "connect", "connect_error", "disconnect", "error"];
1424
+ const eventsToForward = [
1425
+ "connect_start",
1426
+ "connect",
1427
+ "connect_error",
1428
+ "disconnect",
1429
+ "error"
1430
+ ];
1095
1431
  for (const event of eventsToForward) {
1096
1432
  const forwardingCallback = (data) => {
1097
1433
  debug.log(DebugCategory.PROVIDER_MANAGER, "Forwarding event from provider", { event, data });
@@ -1107,7 +1443,7 @@ var ProviderManager = class {
1107
1443
  */
1108
1444
  setDefaultProvider() {
1109
1445
  const defaultType = this.config.providerType || "embedded";
1110
- const defaultEmbeddedType = this.config.embeddedWalletType || "app-wallet";
1446
+ const defaultEmbeddedType = this.config.embeddedWalletType || "user-wallet";
1111
1447
  this.createProvider(defaultType, defaultEmbeddedType);
1112
1448
  this.switchProvider(defaultType, { embeddedWalletType: defaultEmbeddedType });
1113
1449
  }
@@ -1121,24 +1457,27 @@ var ProviderManager = class {
1121
1457
  let provider;
1122
1458
  if (type === "injected") {
1123
1459
  provider = new InjectedProvider({
1124
- solanaProvider: this.config.solanaProvider || "web3js",
1125
- addressTypes: this.config.addressTypes
1460
+ addressTypes: this.config.addressTypes || [import_client.AddressType.solana]
1126
1461
  });
1127
- } else {
1128
- if (!this.config.apiBaseUrl || !this.config.organizationId) {
1129
- throw new Error("apiBaseUrl and organizationId 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");
1130
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;
1131
1468
  provider = new EmbeddedProvider({
1132
- apiBaseUrl: this.config.apiBaseUrl,
1133
- organizationId: this.config.organizationId,
1134
- authOptions: this.config.authOptions,
1135
- embeddedWalletType: embeddedWalletType || "app-wallet",
1136
- addressTypes: this.config.addressTypes,
1137
- solanaProvider: this.config.solanaProvider || "web3js",
1138
- appLogo: this.config.appLogo,
1139
- // Optional app logo URL
1140
- appName: this.config.appName
1469
+ apiBaseUrl,
1470
+ appId: this.config.appId,
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]
1141
1478
  });
1479
+ } else {
1480
+ throw new Error(`Unsupported provider type: ${type}`);
1142
1481
  }
1143
1482
  this.providers.set(key, provider);
1144
1483
  }
@@ -1148,8 +1487,10 @@ var ProviderManager = class {
1148
1487
  getProviderKey(type, embeddedWalletType) {
1149
1488
  if (type === "injected") {
1150
1489
  return "injected";
1490
+ } else if (type === "embedded") {
1491
+ return `embedded-${embeddedWalletType || "app-wallet"}`;
1151
1492
  }
1152
- return `embedded-${embeddedWalletType || "app-wallet"}`;
1493
+ throw new Error(`Unsupported provider type: ${type}`);
1153
1494
  }
1154
1495
  /**
1155
1496
  * Save provider preference to localStorage
@@ -1184,8 +1525,33 @@ var ProviderManager = class {
1184
1525
  }*/
1185
1526
  };
1186
1527
 
1187
- // src/BrowserSDK.ts
1528
+ // src/waitForPhantomExtension.ts
1188
1529
  var import_browser_injected_sdk2 = require("@phantom/browser-injected-sdk");
1530
+ async function waitForPhantomExtension(timeoutMs = 3e3) {
1531
+ return new Promise((resolve) => {
1532
+ const startTime = Date.now();
1533
+ const checkInterval = 100;
1534
+ const checkForExtension = () => {
1535
+ try {
1536
+ if ((0, import_browser_injected_sdk2.isPhantomExtensionInstalled)()) {
1537
+ resolve(true);
1538
+ return;
1539
+ }
1540
+ } catch (error) {
1541
+ }
1542
+ const elapsed = Date.now() - startTime;
1543
+ if (elapsed >= timeoutMs) {
1544
+ resolve(false);
1545
+ return;
1546
+ }
1547
+ setTimeout(checkForExtension, checkInterval);
1548
+ };
1549
+ checkForExtension();
1550
+ });
1551
+ }
1552
+
1553
+ // src/BrowserSDK.ts
1554
+ var import_constants4 = require("@phantom/constants");
1189
1555
  var BrowserSDK = class {
1190
1556
  constructor(config) {
1191
1557
  debug.info(DebugCategory.BROWSER_SDK, "Initializing BrowserSDK", {
@@ -1197,7 +1563,7 @@ var BrowserSDK = class {
1197
1563
  debug.error(DebugCategory.BROWSER_SDK, "Invalid providerType", { providerType: config.providerType });
1198
1564
  throw new Error(`Invalid providerType: ${config.providerType}. Must be "injected" or "embedded".`);
1199
1565
  }
1200
- const embeddedWalletType = config.embeddedWalletType || "app-wallet";
1566
+ const embeddedWalletType = config.embeddedWalletType || import_constants4.DEFAULT_EMBEDDED_WALLET_TYPE;
1201
1567
  if (config.providerType === "embedded" && !["app-wallet", "user-wallet"].includes(embeddedWalletType)) {
1202
1568
  debug.error(DebugCategory.BROWSER_SDK, "Invalid embeddedWalletType", {
1203
1569
  embeddedWalletType: config.embeddedWalletType
@@ -1306,8 +1672,8 @@ var BrowserSDK = class {
1306
1672
  /**
1307
1673
  * Check if Phantom extension is installed
1308
1674
  */
1309
- static isPhantomInstalled() {
1310
- return (0, import_browser_injected_sdk2.isPhantomExtensionInstalled)();
1675
+ static async isPhantomInstalled(timeoutMs) {
1676
+ return waitForPhantomExtension(timeoutMs);
1311
1677
  }
1312
1678
  /**
1313
1679
  * Add event listener for provider events (connect, connect_start, connect_error, disconnect, error)
@@ -1333,7 +1699,7 @@ var BrowserSDK = class {
1333
1699
  async autoConnect() {
1334
1700
  debug.log(DebugCategory.BROWSER_SDK, "Attempting auto-connect");
1335
1701
  const currentProvider = this.providerManager.getCurrentProvider();
1336
- if (currentProvider && "autoConnect" in currentProvider) {
1702
+ if (currentProvider) {
1337
1703
  await currentProvider.autoConnect();
1338
1704
  } else {
1339
1705
  debug.warn(DebugCategory.BROWSER_SDK, "Current provider does not support auto-connect", {
@@ -1474,15 +1840,24 @@ var BrowserSDK = class {
1474
1840
  debug.info(DebugCategory.BROWSER_SDK, "Got supported auto-confirm chains", { result });
1475
1841
  return result;
1476
1842
  } catch (error) {
1477
- debug.error(DebugCategory.BROWSER_SDK, "Failed to get supported auto-confirm chains", { error: error.message });
1843
+ debug.error(DebugCategory.BROWSER_SDK, "Failed to get supported auto-confirm chains", {
1844
+ error: error.message
1845
+ });
1478
1846
  throw error;
1479
1847
  }
1480
1848
  }
1481
1849
  };
1482
1850
 
1483
- // src/types.ts
1484
- var import_client2 = 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
+ }
1485
1860
 
1486
1861
  // src/index.ts
1487
- var import_constants4 = require("@phantom/constants");
1488
- var import_client3 = require("@phantom/client");
1862
+ var import_constants5 = require("@phantom/constants");
1863
+ var import_client5 = require("@phantom/client");