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