@phantom/browser-sdk 1.0.2 → 1.0.4
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 +9 -15
- package/dist/index.d.ts +8 -3
- package/dist/index.js +518 -193
- package/dist/index.mjs +503 -172
- package/package.json +11 -10
package/dist/index.js
CHANGED
|
@@ -30,11 +30,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var src_exports = {};
|
|
32
32
|
__export(src_exports, {
|
|
33
|
-
AddressType: () =>
|
|
33
|
+
AddressType: () => import_client5.AddressType,
|
|
34
34
|
BrowserSDK: () => BrowserSDK,
|
|
35
35
|
DebugCategory: () => DebugCategory,
|
|
36
36
|
DebugLevel: () => DebugLevel,
|
|
37
|
-
NetworkId: () =>
|
|
37
|
+
NetworkId: () => import_constants7.NetworkId,
|
|
38
|
+
PHANTOM_ICON: () => import_constants8.PHANTOM_ICON,
|
|
38
39
|
debug: () => debug,
|
|
39
40
|
detectBrowser: () => detectBrowser,
|
|
40
41
|
getBrowserDisplayName: () => getBrowserDisplayName,
|
|
@@ -51,7 +52,7 @@ module.exports = __toCommonJS(src_exports);
|
|
|
51
52
|
var import_client = require("@phantom/client");
|
|
52
53
|
|
|
53
54
|
// src/providers/injected/index.ts
|
|
54
|
-
var
|
|
55
|
+
var import_client4 = require("@phantom/client");
|
|
55
56
|
|
|
56
57
|
// src/debug.ts
|
|
57
58
|
var DebugLevel = /* @__PURE__ */ ((DebugLevel2) => {
|
|
@@ -128,12 +129,27 @@ var DebugCategory = {
|
|
|
128
129
|
};
|
|
129
130
|
|
|
130
131
|
// src/wallets/discovery.ts
|
|
131
|
-
var
|
|
132
|
+
var import_constants = require("@phantom/constants");
|
|
133
|
+
var import_client3 = require("@phantom/client");
|
|
132
134
|
var import_browser_injected_sdk = require("@phantom/browser-injected-sdk");
|
|
133
135
|
var import_browser_injected_sdk2 = require("@phantom/browser-injected-sdk");
|
|
134
136
|
var import_solana = require("@phantom/browser-injected-sdk/solana");
|
|
135
137
|
var import_ethereum = require("@phantom/browser-injected-sdk/ethereum");
|
|
136
138
|
var import_auto_confirm = require("@phantom/browser-injected-sdk/auto-confirm");
|
|
139
|
+
|
|
140
|
+
// src/wallets/custom-wallets.ts
|
|
141
|
+
var import_client2 = require("@phantom/client");
|
|
142
|
+
var CUSTOM_WALLET_CONFIGS = [
|
|
143
|
+
{
|
|
144
|
+
id: "coinbase-wallet",
|
|
145
|
+
name: "Coinbase Wallet",
|
|
146
|
+
icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNTYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTI4IDU2YzE1LjQ2NCAwIDI4LTEyLjUzNiAyOC0yOFM0My40NjQgMCAyOCAwIDAgMTIuNTM2IDAgMjhzMTIuNTM2IDI4IDI4IDI4WiIgZmlsbD0iIzFCNTNFNCIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNyAyOGMwIDExLjU5OCA5LjQwMiAyMSAyMSAyMXMyMS05LjQwMiAyMS0yMVMzOS41OTggNyAyOCA3IDcgMTYuNDAyIDcgMjhabTE3LjIzNC02Ljc2NmEzIDMgMCAwIDAtMyAzdjcuNTMzYTMgMyAwIDAgMCAzIDNoNy41MzNhMyAzIDAgMCAwIDMtM3YtNy41MzNhMyAzIDAgMCAwLTMtM2gtNy41MzNaIiBmaWxsPSIjZmZmIi8+PC9zdmc+",
|
|
147
|
+
windowProperty: "coinbaseSolana",
|
|
148
|
+
addressTypes: [import_client2.AddressType.solana]
|
|
149
|
+
}
|
|
150
|
+
];
|
|
151
|
+
|
|
152
|
+
// src/wallets/discovery.ts
|
|
137
153
|
function generateWalletIdFromEIP6963(info) {
|
|
138
154
|
if (info.rdns) {
|
|
139
155
|
return info.rdns.split(".").reverse().join("-");
|
|
@@ -166,7 +182,7 @@ function processEIP6963Providers(providers) {
|
|
|
166
182
|
id: walletId,
|
|
167
183
|
name: info.name,
|
|
168
184
|
icon: info.icon,
|
|
169
|
-
addressTypes: [
|
|
185
|
+
addressTypes: [import_client3.AddressType.ethereum],
|
|
170
186
|
providers: {
|
|
171
187
|
// EIP-6963 provider implements EIP-1193 interface (IEthereumChain)
|
|
172
188
|
ethereum: provider
|
|
@@ -376,7 +392,7 @@ async function discoverSolanaWallets() {
|
|
|
376
392
|
id: walletId,
|
|
377
393
|
name: wallet.name,
|
|
378
394
|
icon: wallet.icon,
|
|
379
|
-
addressTypes: [
|
|
395
|
+
addressTypes: [import_client3.AddressType.solana],
|
|
380
396
|
providers: {
|
|
381
397
|
// Cast to ISolanaChain - Wallet Standard wallets have compatible methods
|
|
382
398
|
// The InjectedWalletSolanaChain wrapper will handle the actual method calls
|
|
@@ -397,6 +413,51 @@ async function discoverSolanaWallets() {
|
|
|
397
413
|
walletNames: wallets.map((w) => w.name)
|
|
398
414
|
};
|
|
399
415
|
debug.log(DebugCategory.BROWSER_SDK, "Wallet Standard Solana discovery completed", finalLogData);
|
|
416
|
+
const customWallets = discoverCustomSolanaWallets();
|
|
417
|
+
wallets.push(...customWallets);
|
|
418
|
+
return wallets;
|
|
419
|
+
}
|
|
420
|
+
function discoverCustomSolanaWallets() {
|
|
421
|
+
const wallets = [];
|
|
422
|
+
if (typeof window === "undefined") {
|
|
423
|
+
debug.log(DebugCategory.BROWSER_SDK, "Custom wallet discovery skipped (not in browser environment)");
|
|
424
|
+
return wallets;
|
|
425
|
+
}
|
|
426
|
+
debug.log(DebugCategory.BROWSER_SDK, "Starting custom Solana wallet discovery", {
|
|
427
|
+
configCount: CUSTOM_WALLET_CONFIGS.length
|
|
428
|
+
});
|
|
429
|
+
for (const config of CUSTOM_WALLET_CONFIGS) {
|
|
430
|
+
if (!config.addressTypes.includes(import_client3.AddressType.solana)) {
|
|
431
|
+
continue;
|
|
432
|
+
}
|
|
433
|
+
const provider = window[config.windowProperty];
|
|
434
|
+
if (!provider) {
|
|
435
|
+
debug.log(DebugCategory.BROWSER_SDK, "Custom wallet not found", {
|
|
436
|
+
walletId: config.id,
|
|
437
|
+
windowProperty: config.windowProperty
|
|
438
|
+
});
|
|
439
|
+
continue;
|
|
440
|
+
}
|
|
441
|
+
debug.log(DebugCategory.BROWSER_SDK, "Discovered custom Solana wallet", {
|
|
442
|
+
walletId: config.id,
|
|
443
|
+
walletName: config.name,
|
|
444
|
+
windowProperty: config.windowProperty
|
|
445
|
+
});
|
|
446
|
+
wallets.push({
|
|
447
|
+
id: config.id,
|
|
448
|
+
name: config.name,
|
|
449
|
+
icon: config.icon,
|
|
450
|
+
addressTypes: config.addressTypes,
|
|
451
|
+
providers: {
|
|
452
|
+
solana: provider
|
|
453
|
+
},
|
|
454
|
+
discovery: "custom"
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
debug.log(DebugCategory.BROWSER_SDK, "Custom Solana wallet discovery completed", {
|
|
458
|
+
discoveredCount: wallets.length,
|
|
459
|
+
walletIds: wallets.map((w) => w.id)
|
|
460
|
+
});
|
|
400
461
|
return wallets;
|
|
401
462
|
}
|
|
402
463
|
function discoverPhantomWallet(addressTypes) {
|
|
@@ -407,10 +468,10 @@ function discoverPhantomWallet(addressTypes) {
|
|
|
407
468
|
return null;
|
|
408
469
|
}
|
|
409
470
|
const plugins = [(0, import_browser_injected_sdk2.createExtensionPlugin)()];
|
|
410
|
-
if (addressTypes.includes(
|
|
471
|
+
if (addressTypes.includes(import_client3.AddressType.solana)) {
|
|
411
472
|
plugins.push((0, import_solana.createSolanaPlugin)());
|
|
412
473
|
}
|
|
413
|
-
if (addressTypes.includes(
|
|
474
|
+
if (addressTypes.includes(import_client3.AddressType.ethereum)) {
|
|
414
475
|
plugins.push((0, import_ethereum.createEthereumPlugin)());
|
|
415
476
|
}
|
|
416
477
|
plugins.push((0, import_auto_confirm.createAutoConfirmPlugin)());
|
|
@@ -418,12 +479,11 @@ function discoverPhantomWallet(addressTypes) {
|
|
|
418
479
|
return {
|
|
419
480
|
id: "phantom",
|
|
420
481
|
name: "Phantom",
|
|
421
|
-
icon:
|
|
422
|
-
// Icon will be rendered from icons package in UI components
|
|
482
|
+
icon: import_constants.PHANTOM_ICON,
|
|
423
483
|
addressTypes,
|
|
424
484
|
providers: {
|
|
425
|
-
solana: addressTypes.includes(
|
|
426
|
-
ethereum: addressTypes.includes(
|
|
485
|
+
solana: addressTypes.includes(import_client3.AddressType.solana) ? phantomInstance.solana : void 0,
|
|
486
|
+
ethereum: addressTypes.includes(import_client3.AddressType.ethereum) ? phantomInstance.ethereum : void 0
|
|
427
487
|
},
|
|
428
488
|
isPhantom: true,
|
|
429
489
|
phantomInstance,
|
|
@@ -488,6 +548,9 @@ async function discoverWallets(addressTypes) {
|
|
|
488
548
|
return Array.from(walletMap.values());
|
|
489
549
|
}
|
|
490
550
|
|
|
551
|
+
// src/wallets/registry.ts
|
|
552
|
+
var import_constants2 = require("@phantom/constants");
|
|
553
|
+
|
|
491
554
|
// src/providers/injected/chains/InjectedWalletSolanaChain.ts
|
|
492
555
|
var import_eventemitter3 = require("eventemitter3");
|
|
493
556
|
var import_buffer = require("buffer");
|
|
@@ -495,61 +558,55 @@ var InjectedWalletSolanaChain = class {
|
|
|
495
558
|
constructor(provider, walletId, walletName) {
|
|
496
559
|
// Expose eventEmitter for testing - allows tests to trigger events directly
|
|
497
560
|
this.eventEmitter = new import_eventemitter3.EventEmitter();
|
|
498
|
-
this._connected = false;
|
|
499
561
|
this._publicKey = null;
|
|
500
562
|
this.provider = provider;
|
|
501
563
|
this.walletId = walletId;
|
|
502
564
|
this.walletName = walletName;
|
|
503
565
|
this.setupEventListeners();
|
|
504
566
|
}
|
|
505
|
-
get connected() {
|
|
506
|
-
return this._connected;
|
|
507
|
-
}
|
|
508
567
|
get publicKey() {
|
|
509
568
|
return this._publicKey;
|
|
510
569
|
}
|
|
570
|
+
get isConnected() {
|
|
571
|
+
return this.provider.isConnected || !!this._publicKey;
|
|
572
|
+
}
|
|
511
573
|
async connect(options) {
|
|
512
|
-
debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Solana connect", {
|
|
513
|
-
walletId: this.walletId,
|
|
514
|
-
walletName: this.walletName,
|
|
515
|
-
onlyIfTrusted: options?.onlyIfTrusted
|
|
516
|
-
});
|
|
517
574
|
try {
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Solana connected", {
|
|
575
|
+
await this.provider.connect(options);
|
|
576
|
+
const isConnected = this.provider.isConnected;
|
|
577
|
+
if (!isConnected || this.provider.publicKey === null) {
|
|
578
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "Provider not connected after connect() call", {
|
|
523
579
|
walletId: this.walletId,
|
|
524
580
|
walletName: this.walletName,
|
|
525
|
-
|
|
581
|
+
providerConnected: isConnected,
|
|
582
|
+
providerPublicKey: this.provider.publicKey
|
|
526
583
|
});
|
|
527
|
-
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
584
|
+
throw new Error("Provider not connected after connect() call");
|
|
585
|
+
}
|
|
586
|
+
let publicKey;
|
|
587
|
+
const providerPublicKey = this.provider.publicKey;
|
|
588
|
+
if (typeof providerPublicKey === "string") {
|
|
589
|
+
publicKey = providerPublicKey;
|
|
590
|
+
} else if (providerPublicKey !== null && providerPublicKey !== void 0 && typeof providerPublicKey.toString === "function") {
|
|
591
|
+
publicKey = providerPublicKey.toString();
|
|
592
|
+
} else {
|
|
593
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "Invalid publicKey format in provider state", {
|
|
533
594
|
walletId: this.walletId,
|
|
534
595
|
walletName: this.walletName,
|
|
535
|
-
|
|
596
|
+
publicKeyType: typeof providerPublicKey
|
|
536
597
|
});
|
|
537
|
-
|
|
538
|
-
}
|
|
539
|
-
if (
|
|
540
|
-
|
|
541
|
-
if (typeof firstAccount === "object" && firstAccount !== null && "address" in firstAccount) {
|
|
542
|
-
this._connected = true;
|
|
543
|
-
this._publicKey = firstAccount.address;
|
|
544
|
-
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Solana connected", {
|
|
545
|
-
walletId: this.walletId,
|
|
546
|
-
walletName: this.walletName,
|
|
547
|
-
publicKey: firstAccount.address
|
|
548
|
-
});
|
|
549
|
-
return { publicKey: firstAccount.address };
|
|
550
|
-
}
|
|
598
|
+
throw new Error("Invalid publicKey format in provider state");
|
|
599
|
+
}
|
|
600
|
+
if (!publicKey || publicKey.length === 0) {
|
|
601
|
+
throw new Error("Empty publicKey from provider");
|
|
551
602
|
}
|
|
552
|
-
|
|
603
|
+
this._publicKey = publicKey;
|
|
604
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Solana connected", {
|
|
605
|
+
walletId: this.walletId,
|
|
606
|
+
walletName: this.walletName,
|
|
607
|
+
publicKey
|
|
608
|
+
});
|
|
609
|
+
return { publicKey };
|
|
553
610
|
} catch (error) {
|
|
554
611
|
debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Solana connect failed", {
|
|
555
612
|
walletId: this.walletId,
|
|
@@ -566,7 +623,6 @@ var InjectedWalletSolanaChain = class {
|
|
|
566
623
|
});
|
|
567
624
|
try {
|
|
568
625
|
await this.provider.disconnect();
|
|
569
|
-
this._connected = false;
|
|
570
626
|
this._publicKey = null;
|
|
571
627
|
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Solana disconnected", {
|
|
572
628
|
walletId: this.walletId,
|
|
@@ -702,28 +758,19 @@ var InjectedWalletSolanaChain = class {
|
|
|
702
758
|
switchNetwork(_network) {
|
|
703
759
|
return Promise.resolve();
|
|
704
760
|
}
|
|
705
|
-
getPublicKey() {
|
|
706
|
-
return Promise.resolve(this._publicKey);
|
|
707
|
-
}
|
|
708
|
-
isConnected() {
|
|
709
|
-
return this._connected;
|
|
710
|
-
}
|
|
711
761
|
setupEventListeners() {
|
|
712
762
|
if (typeof this.provider.on === "function") {
|
|
713
763
|
this.provider.on("connect", (publicKey) => {
|
|
714
|
-
this._connected = true;
|
|
715
764
|
this._publicKey = publicKey;
|
|
716
765
|
this.eventEmitter.emit("connect", publicKey);
|
|
717
766
|
});
|
|
718
767
|
this.provider.on("disconnect", () => {
|
|
719
|
-
this._connected = false;
|
|
720
768
|
this._publicKey = null;
|
|
721
769
|
this.eventEmitter.emit("disconnect");
|
|
722
770
|
});
|
|
723
771
|
this.provider.on("accountChanged", (publicKey) => {
|
|
724
|
-
this._publicKey = publicKey;
|
|
725
|
-
this.
|
|
726
|
-
this.eventEmitter.emit("accountChanged", publicKey);
|
|
772
|
+
this._publicKey = publicKey ? publicKey : null;
|
|
773
|
+
this.eventEmitter.emit("accountChanged", this._publicKey);
|
|
727
774
|
});
|
|
728
775
|
}
|
|
729
776
|
}
|
|
@@ -749,12 +796,12 @@ var WalletStandardSolanaAdapter = class {
|
|
|
749
796
|
this.walletName = walletName;
|
|
750
797
|
this.setupEventListeners();
|
|
751
798
|
}
|
|
752
|
-
get connected() {
|
|
753
|
-
return this._publicKey !== null;
|
|
754
|
-
}
|
|
755
799
|
get publicKey() {
|
|
756
800
|
return this._publicKey;
|
|
757
801
|
}
|
|
802
|
+
get isConnected() {
|
|
803
|
+
return this._publicKey !== null;
|
|
804
|
+
}
|
|
758
805
|
async connect(_options) {
|
|
759
806
|
try {
|
|
760
807
|
const connectFeature = this.wallet.features["standard:connect"];
|
|
@@ -966,12 +1013,6 @@ var WalletStandardSolanaAdapter = class {
|
|
|
966
1013
|
async switchNetwork(_network) {
|
|
967
1014
|
return Promise.resolve();
|
|
968
1015
|
}
|
|
969
|
-
getPublicKey() {
|
|
970
|
-
return Promise.resolve(this._publicKey);
|
|
971
|
-
}
|
|
972
|
-
isConnected() {
|
|
973
|
-
return this._publicKey !== null;
|
|
974
|
-
}
|
|
975
1016
|
/**
|
|
976
1017
|
* Set up event listeners for Wallet Standard events
|
|
977
1018
|
* Maps Wallet Standard "change" events to "accountChanged" events
|
|
@@ -1106,9 +1147,6 @@ var InjectedWalletEthereumChain = class {
|
|
|
1106
1147
|
this.walletName = walletName;
|
|
1107
1148
|
this.setupEventListeners();
|
|
1108
1149
|
}
|
|
1109
|
-
get connected() {
|
|
1110
|
-
return this._connected;
|
|
1111
|
-
}
|
|
1112
1150
|
get chainId() {
|
|
1113
1151
|
return this._chainId;
|
|
1114
1152
|
}
|
|
@@ -1238,7 +1276,8 @@ var InjectedWalletEthereumChain = class {
|
|
|
1238
1276
|
address
|
|
1239
1277
|
});
|
|
1240
1278
|
try {
|
|
1241
|
-
const
|
|
1279
|
+
const providerAny = this.provider;
|
|
1280
|
+
const providerConnected = (typeof providerAny.isConnected === "function" ? providerAny.isConnected() : false) || (typeof providerAny.connected === "boolean" ? providerAny.connected : false);
|
|
1242
1281
|
if (!this._connected || this._accounts.length === 0 || !providerConnected) {
|
|
1243
1282
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Not connected, attempting to connect before signing", {
|
|
1244
1283
|
walletId: this.walletId,
|
|
@@ -1552,8 +1591,7 @@ var InjectedWalletRegistry = class {
|
|
|
1552
1591
|
const phantomWallet = {
|
|
1553
1592
|
id: "phantom",
|
|
1554
1593
|
name: "Phantom",
|
|
1555
|
-
icon:
|
|
1556
|
-
// Icon will be rendered from icons package in UI components
|
|
1594
|
+
icon: import_constants2.PHANTOM_ICON,
|
|
1557
1595
|
addressTypes,
|
|
1558
1596
|
providers: wrappedProviders,
|
|
1559
1597
|
isPhantom: true,
|
|
@@ -1699,13 +1737,13 @@ var InjectedProvider = class {
|
|
|
1699
1737
|
return provider;
|
|
1700
1738
|
}
|
|
1701
1739
|
get solana() {
|
|
1702
|
-
return this.getChainProvider(
|
|
1740
|
+
return this.getChainProvider(import_client4.AddressType.solana, "solana", "Solana");
|
|
1703
1741
|
}
|
|
1704
1742
|
/**
|
|
1705
1743
|
* Access to Ethereum chain operations
|
|
1706
1744
|
*/
|
|
1707
1745
|
get ethereum() {
|
|
1708
|
-
return this.getChainProvider(
|
|
1746
|
+
return this.getChainProvider(import_client4.AddressType.ethereum, "ethereum", "Ethereum");
|
|
1709
1747
|
}
|
|
1710
1748
|
validateAndSelectWallet(requestedWalletId) {
|
|
1711
1749
|
if (!this.walletRegistry.has(requestedWalletId)) {
|
|
@@ -1746,7 +1784,7 @@ var InjectedProvider = class {
|
|
|
1746
1784
|
this.setupEventListeners(walletInfo);
|
|
1747
1785
|
}
|
|
1748
1786
|
const connectedAddresses = [];
|
|
1749
|
-
if (this.addressTypes.includes(
|
|
1787
|
+
if (this.addressTypes.includes(import_client4.AddressType.solana) && walletInfo.providers?.solana) {
|
|
1750
1788
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting Solana connection", {
|
|
1751
1789
|
walletId: this.selectedWalletId,
|
|
1752
1790
|
walletName: walletInfo.name,
|
|
@@ -1758,7 +1796,7 @@ var InjectedProvider = class {
|
|
|
1758
1796
|
);
|
|
1759
1797
|
const address = result.publicKey;
|
|
1760
1798
|
connectedAddresses.push({
|
|
1761
|
-
addressType:
|
|
1799
|
+
addressType: import_client4.AddressType.solana,
|
|
1762
1800
|
address
|
|
1763
1801
|
});
|
|
1764
1802
|
debug.info(DebugCategory.INJECTED_PROVIDER, "Solana connected successfully", {
|
|
@@ -1767,19 +1805,14 @@ var InjectedProvider = class {
|
|
|
1767
1805
|
walletName: walletInfo.name
|
|
1768
1806
|
});
|
|
1769
1807
|
} catch (err) {
|
|
1770
|
-
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Solana,
|
|
1808
|
+
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Solana, continuing with other chains", {
|
|
1771
1809
|
error: err,
|
|
1772
1810
|
walletId: this.selectedWalletId,
|
|
1773
1811
|
walletName: walletInfo.name
|
|
1774
1812
|
});
|
|
1775
|
-
this.emit("connect_error", {
|
|
1776
|
-
error: err instanceof Error ? err.message : "Failed to connect",
|
|
1777
|
-
source: options?.skipEventListeners ? "auto-connect" : "manual-connect"
|
|
1778
|
-
});
|
|
1779
|
-
throw err;
|
|
1780
1813
|
}
|
|
1781
1814
|
}
|
|
1782
|
-
if (this.addressTypes.includes(
|
|
1815
|
+
if (this.addressTypes.includes(import_client4.AddressType.ethereum) && walletInfo.providers?.ethereum) {
|
|
1783
1816
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting Ethereum connection", {
|
|
1784
1817
|
walletId: this.selectedWalletId,
|
|
1785
1818
|
walletName: walletInfo.name,
|
|
@@ -1795,7 +1828,7 @@ var InjectedProvider = class {
|
|
|
1795
1828
|
if (accounts.length > 0) {
|
|
1796
1829
|
connectedAddresses.push(
|
|
1797
1830
|
...accounts.map((address) => ({
|
|
1798
|
-
addressType:
|
|
1831
|
+
addressType: import_client4.AddressType.ethereum,
|
|
1799
1832
|
address
|
|
1800
1833
|
}))
|
|
1801
1834
|
);
|
|
@@ -1806,16 +1839,11 @@ var InjectedProvider = class {
|
|
|
1806
1839
|
});
|
|
1807
1840
|
}
|
|
1808
1841
|
} catch (err) {
|
|
1809
|
-
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Ethereum,
|
|
1842
|
+
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Ethereum, continuing with other chains", {
|
|
1810
1843
|
error: err,
|
|
1811
1844
|
walletId: this.selectedWalletId,
|
|
1812
1845
|
walletName: walletInfo.name
|
|
1813
1846
|
});
|
|
1814
|
-
this.emit("connect_error", {
|
|
1815
|
-
error: err instanceof Error ? err.message : "Failed to connect",
|
|
1816
|
-
source: options?.skipEventListeners ? "auto-connect" : "manual-connect"
|
|
1817
|
-
});
|
|
1818
|
-
throw err;
|
|
1819
1847
|
}
|
|
1820
1848
|
}
|
|
1821
1849
|
return connectedAddresses;
|
|
@@ -1875,7 +1903,8 @@ var InjectedProvider = class {
|
|
|
1875
1903
|
this.emit("connect", {
|
|
1876
1904
|
addresses: connectedAddresses,
|
|
1877
1905
|
source: "manual-connect",
|
|
1878
|
-
authUserId
|
|
1906
|
+
authUserId,
|
|
1907
|
+
walletId
|
|
1879
1908
|
});
|
|
1880
1909
|
return result;
|
|
1881
1910
|
}
|
|
@@ -1887,12 +1916,13 @@ var InjectedProvider = class {
|
|
|
1887
1916
|
if (authOptions.provider !== "injected") {
|
|
1888
1917
|
throw new Error(`Invalid provider for injected connection: ${authOptions.provider}. Must be "injected"`);
|
|
1889
1918
|
}
|
|
1919
|
+
const requestedWalletId = authOptions.walletId || "phantom";
|
|
1890
1920
|
this.emit("connect_start", {
|
|
1891
1921
|
source: "manual-connect",
|
|
1892
|
-
providerType: "injected"
|
|
1922
|
+
providerType: "injected",
|
|
1923
|
+
walletId: requestedWalletId
|
|
1893
1924
|
});
|
|
1894
1925
|
try {
|
|
1895
|
-
const requestedWalletId = authOptions.walletId || "phantom";
|
|
1896
1926
|
const walletInfo = this.validateAndSelectWallet(requestedWalletId);
|
|
1897
1927
|
const connectedAddresses = await this.connectToWallet(walletInfo);
|
|
1898
1928
|
return await this.finalizeConnection(connectedAddresses, "injected", this.selectedWalletId || void 0);
|
|
@@ -1908,7 +1938,7 @@ var InjectedProvider = class {
|
|
|
1908
1938
|
debug.info(DebugCategory.INJECTED_PROVIDER, "Starting injected provider disconnect");
|
|
1909
1939
|
const walletInfo = this.walletRegistry.getById(this.selectedWalletId || "phantom");
|
|
1910
1940
|
if (walletInfo?.providers) {
|
|
1911
|
-
if (this.addressTypes.includes(
|
|
1941
|
+
if (this.addressTypes.includes(import_client4.AddressType.solana) && walletInfo.providers.solana) {
|
|
1912
1942
|
try {
|
|
1913
1943
|
await walletInfo.providers.solana.disconnect();
|
|
1914
1944
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana disconnected successfully");
|
|
@@ -1916,7 +1946,7 @@ var InjectedProvider = class {
|
|
|
1916
1946
|
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to disconnect Solana", { error: err });
|
|
1917
1947
|
}
|
|
1918
1948
|
}
|
|
1919
|
-
if (this.addressTypes.includes(
|
|
1949
|
+
if (this.addressTypes.includes(import_client4.AddressType.ethereum) && walletInfo.providers.ethereum) {
|
|
1920
1950
|
try {
|
|
1921
1951
|
await walletInfo.providers.ethereum.disconnect();
|
|
1922
1952
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum disconnected successfully");
|
|
@@ -2012,7 +2042,8 @@ var InjectedProvider = class {
|
|
|
2012
2042
|
this.emit("connect", {
|
|
2013
2043
|
addresses: connectedAddresses,
|
|
2014
2044
|
source: "auto-connect",
|
|
2015
|
-
authUserId
|
|
2045
|
+
authUserId,
|
|
2046
|
+
walletId: this.selectedWalletId
|
|
2016
2047
|
});
|
|
2017
2048
|
debug.info(DebugCategory.INJECTED_PROVIDER, "Auto-connect successful", {
|
|
2018
2049
|
addressCount: connectedAddresses.length,
|
|
@@ -2073,12 +2104,13 @@ var InjectedProvider = class {
|
|
|
2073
2104
|
createSolanaConnectHandler(walletId, source) {
|
|
2074
2105
|
return async (publicKey) => {
|
|
2075
2106
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana connect event received", { publicKey, walletId });
|
|
2076
|
-
const newAddresses = this.updateWalletAddresses(walletId, [publicKey],
|
|
2107
|
+
const newAddresses = this.updateWalletAddresses(walletId, [publicKey], import_client4.AddressType.solana);
|
|
2077
2108
|
const authUserId = await this.getAuthUserId("Solana connect event");
|
|
2078
2109
|
this.emit("connect", {
|
|
2079
2110
|
addresses: newAddresses,
|
|
2080
2111
|
source,
|
|
2081
|
-
authUserId
|
|
2112
|
+
authUserId,
|
|
2113
|
+
walletId: this.selectedWalletId
|
|
2082
2114
|
});
|
|
2083
2115
|
};
|
|
2084
2116
|
}
|
|
@@ -2089,7 +2121,7 @@ var InjectedProvider = class {
|
|
|
2089
2121
|
return () => {
|
|
2090
2122
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana disconnect event received", { walletId });
|
|
2091
2123
|
const state = this.getWalletState(walletId);
|
|
2092
|
-
const filteredAddresses = state.addresses.filter((addr) => addr.addressType !==
|
|
2124
|
+
const filteredAddresses = state.addresses.filter((addr) => addr.addressType !== import_client4.AddressType.solana);
|
|
2093
2125
|
this.setWalletState(walletId, {
|
|
2094
2126
|
connected: filteredAddresses.length > 0,
|
|
2095
2127
|
addresses: filteredAddresses
|
|
@@ -2107,16 +2139,17 @@ var InjectedProvider = class {
|
|
|
2107
2139
|
return async (publicKey) => {
|
|
2108
2140
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana account changed event received", { publicKey, walletId });
|
|
2109
2141
|
if (publicKey) {
|
|
2110
|
-
const newAddresses = this.updateWalletAddresses(walletId, [publicKey],
|
|
2142
|
+
const newAddresses = this.updateWalletAddresses(walletId, [publicKey], import_client4.AddressType.solana);
|
|
2111
2143
|
const authUserId = await this.getAuthUserId("Solana account changed event");
|
|
2112
2144
|
this.emit("connect", {
|
|
2113
2145
|
addresses: newAddresses,
|
|
2114
2146
|
source: this.getAccountChangeSource(source),
|
|
2115
|
-
authUserId
|
|
2147
|
+
authUserId,
|
|
2148
|
+
walletId: this.selectedWalletId
|
|
2116
2149
|
});
|
|
2117
2150
|
} else {
|
|
2118
2151
|
const state = this.getWalletState(walletId);
|
|
2119
|
-
const otherAddresses = state.addresses.filter((addr) => addr.addressType !==
|
|
2152
|
+
const otherAddresses = state.addresses.filter((addr) => addr.addressType !== import_client4.AddressType.solana);
|
|
2120
2153
|
this.setWalletState(walletId, {
|
|
2121
2154
|
connected: otherAddresses.length > 0,
|
|
2122
2155
|
addresses: otherAddresses
|
|
@@ -2148,12 +2181,13 @@ var InjectedProvider = class {
|
|
|
2148
2181
|
}
|
|
2149
2182
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum connect event received", { accounts, walletId });
|
|
2150
2183
|
if (accounts.length > 0) {
|
|
2151
|
-
const newAddresses = this.updateWalletAddresses(walletId, accounts,
|
|
2184
|
+
const newAddresses = this.updateWalletAddresses(walletId, accounts, import_client4.AddressType.ethereum);
|
|
2152
2185
|
const authUserId = await this.getAuthUserId("Ethereum connect event");
|
|
2153
2186
|
this.emit("connect", {
|
|
2154
2187
|
addresses: newAddresses,
|
|
2155
2188
|
source,
|
|
2156
|
-
authUserId
|
|
2189
|
+
authUserId,
|
|
2190
|
+
walletId: this.selectedWalletId
|
|
2157
2191
|
});
|
|
2158
2192
|
}
|
|
2159
2193
|
};
|
|
@@ -2165,7 +2199,7 @@ var InjectedProvider = class {
|
|
|
2165
2199
|
return () => {
|
|
2166
2200
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum disconnect event received", { walletId });
|
|
2167
2201
|
const state = this.getWalletState(walletId);
|
|
2168
|
-
const filteredAddresses = state.addresses.filter((addr) => addr.addressType !==
|
|
2202
|
+
const filteredAddresses = state.addresses.filter((addr) => addr.addressType !== import_client4.AddressType.ethereum);
|
|
2169
2203
|
this.setWalletState(walletId, {
|
|
2170
2204
|
connected: filteredAddresses.length > 0,
|
|
2171
2205
|
addresses: filteredAddresses
|
|
@@ -2182,16 +2216,17 @@ var InjectedProvider = class {
|
|
|
2182
2216
|
return async (accounts) => {
|
|
2183
2217
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum accounts changed event received", { accounts, walletId });
|
|
2184
2218
|
if (accounts && accounts.length > 0) {
|
|
2185
|
-
const newAddresses = this.updateWalletAddresses(walletId, accounts,
|
|
2219
|
+
const newAddresses = this.updateWalletAddresses(walletId, accounts, import_client4.AddressType.ethereum);
|
|
2186
2220
|
const authUserId = await this.getAuthUserId("Ethereum accounts changed event");
|
|
2187
2221
|
this.emit("connect", {
|
|
2188
2222
|
addresses: newAddresses,
|
|
2189
2223
|
source: this.getAccountChangeSource(source),
|
|
2190
|
-
authUserId
|
|
2224
|
+
authUserId,
|
|
2225
|
+
walletId: this.selectedWalletId
|
|
2191
2226
|
});
|
|
2192
2227
|
} else {
|
|
2193
2228
|
const state = this.getWalletState(walletId);
|
|
2194
|
-
const otherAddresses = state.addresses.filter((addr) => addr.addressType !==
|
|
2229
|
+
const otherAddresses = state.addresses.filter((addr) => addr.addressType !== import_client4.AddressType.ethereum);
|
|
2195
2230
|
this.setWalletState(walletId, {
|
|
2196
2231
|
connected: otherAddresses.length > 0,
|
|
2197
2232
|
addresses: otherAddresses
|
|
@@ -2385,7 +2420,9 @@ var InjectedProvider = class {
|
|
|
2385
2420
|
this.eventListenerCleanups.set(walletId, [...existingCleanups, ...cleanups]);
|
|
2386
2421
|
}
|
|
2387
2422
|
/**
|
|
2388
|
-
* Unified event listener setup for all wallet types (Phantom and external)
|
|
2423
|
+
* Unified event listener setup for all wallet types (Phantom and external).
|
|
2424
|
+
* Cleans up listeners for previously selected wallets to prevent stale events
|
|
2425
|
+
* from causing walletId flicker during connections.
|
|
2389
2426
|
*/
|
|
2390
2427
|
setupEventListeners(walletInfo) {
|
|
2391
2428
|
const walletId = this.selectedWalletId || "phantom";
|
|
@@ -2393,11 +2430,22 @@ var InjectedProvider = class {
|
|
|
2393
2430
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Event listeners already set up for wallet", { walletId });
|
|
2394
2431
|
return;
|
|
2395
2432
|
}
|
|
2433
|
+
for (const existingWalletId of this.eventListenersSetup) {
|
|
2434
|
+
if (existingWalletId === walletId) {
|
|
2435
|
+
continue;
|
|
2436
|
+
}
|
|
2437
|
+
const cleanups = this.eventListenerCleanups.get(existingWalletId);
|
|
2438
|
+
if (cleanups) {
|
|
2439
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Cleaning up event listeners for wallet", { existingWalletId });
|
|
2440
|
+
cleanups.forEach((cleanup) => cleanup());
|
|
2441
|
+
}
|
|
2442
|
+
this.eventListenersSetup.delete(existingWalletId);
|
|
2443
|
+
}
|
|
2396
2444
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up event listeners", { walletId });
|
|
2397
|
-
if (this.addressTypes.includes(
|
|
2445
|
+
if (this.addressTypes.includes(import_client4.AddressType.solana) && walletInfo.providers?.solana) {
|
|
2398
2446
|
this.setupSolanaEventListeners(walletInfo.providers.solana, walletId, "wallet");
|
|
2399
2447
|
}
|
|
2400
|
-
if (this.addressTypes.includes(
|
|
2448
|
+
if (this.addressTypes.includes(import_client4.AddressType.ethereum) && walletInfo.providers?.ethereum) {
|
|
2401
2449
|
this.setupEthereumEventListeners(walletInfo.providers.ethereum, walletId, "wallet");
|
|
2402
2450
|
}
|
|
2403
2451
|
this.eventListenersSetup.add(walletId);
|
|
@@ -2541,7 +2589,7 @@ var BrowserURLParamsAccessor = class {
|
|
|
2541
2589
|
var browserUrlParamsAccessor = new BrowserURLParamsAccessor();
|
|
2542
2590
|
|
|
2543
2591
|
// src/providers/embedded/adapters/auth.ts
|
|
2544
|
-
var
|
|
2592
|
+
var import_constants3 = require("@phantom/constants");
|
|
2545
2593
|
|
|
2546
2594
|
// src/utils/browser-detection.ts
|
|
2547
2595
|
function parseBrowserFromUserAgent(userAgent, hasBraveAPI) {
|
|
@@ -2706,7 +2754,7 @@ var BrowserAuthProvider = class {
|
|
|
2706
2754
|
provider: phantomOptions.provider,
|
|
2707
2755
|
authUrl: phantomOptions.authUrl
|
|
2708
2756
|
});
|
|
2709
|
-
const baseUrl = phantomOptions.authUrl ||
|
|
2757
|
+
const baseUrl = phantomOptions.authUrl || import_constants3.DEFAULT_AUTH_URL;
|
|
2710
2758
|
debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Using auth URL", { baseUrl });
|
|
2711
2759
|
const params = new URLSearchParams({
|
|
2712
2760
|
public_key: phantomOptions.publicKey,
|
|
@@ -2716,9 +2764,10 @@ var BrowserAuthProvider = class {
|
|
|
2716
2764
|
// OAuth session management - defaults to allow refresh unless explicitly clearing after logout
|
|
2717
2765
|
clear_previous_session: (phantomOptions.clearPreviousSession ?? false).toString(),
|
|
2718
2766
|
allow_refresh: (phantomOptions.allowRefresh ?? true).toString(),
|
|
2719
|
-
sdk_version: "1.0.
|
|
2767
|
+
sdk_version: "1.0.4",
|
|
2720
2768
|
sdk_type: "browser",
|
|
2721
|
-
platform: detectBrowser().name
|
|
2769
|
+
platform: detectBrowser().name,
|
|
2770
|
+
algorithm: phantomOptions.algorithm || import_constants3.DEFAULT_AUTHENTICATOR_ALGORITHM
|
|
2722
2771
|
});
|
|
2723
2772
|
if (phantomOptions.provider) {
|
|
2724
2773
|
debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Provider specified, will skip selection", {
|
|
@@ -2746,7 +2795,7 @@ var BrowserAuthProvider = class {
|
|
|
2746
2795
|
resolve();
|
|
2747
2796
|
});
|
|
2748
2797
|
}
|
|
2749
|
-
resumeAuthFromRedirect(provider) {
|
|
2798
|
+
async resumeAuthFromRedirect(provider) {
|
|
2750
2799
|
try {
|
|
2751
2800
|
const walletId = this.urlParamsAccessor.getParam("wallet_id");
|
|
2752
2801
|
const sessionId = this.urlParamsAccessor.getParam("session_id");
|
|
@@ -2821,14 +2870,14 @@ var BrowserAuthProvider = class {
|
|
|
2821
2870
|
}
|
|
2822
2871
|
);
|
|
2823
2872
|
}
|
|
2824
|
-
return {
|
|
2873
|
+
return Promise.resolve({
|
|
2825
2874
|
walletId,
|
|
2826
2875
|
organizationId,
|
|
2827
2876
|
accountDerivationIndex: accountDerivationIndex ? parseInt(accountDerivationIndex) : 0,
|
|
2828
2877
|
expiresInMs: expiresInMs ? parseInt(expiresInMs) : 0,
|
|
2829
2878
|
authUserId: authUserId || void 0,
|
|
2830
2879
|
provider
|
|
2831
|
-
};
|
|
2880
|
+
});
|
|
2832
2881
|
} catch (error) {
|
|
2833
2882
|
sessionStorage.removeItem("phantom-auth-context");
|
|
2834
2883
|
throw error;
|
|
@@ -2836,31 +2885,286 @@ var BrowserAuthProvider = class {
|
|
|
2836
2885
|
}
|
|
2837
2886
|
};
|
|
2838
2887
|
|
|
2839
|
-
// src/providers/embedded/adapters/
|
|
2840
|
-
var
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2888
|
+
// src/providers/embedded/adapters/Auth2AuthProvider.ts
|
|
2889
|
+
var import_auth2 = require("@phantom/auth2");
|
|
2890
|
+
var Auth2AuthProvider = class {
|
|
2891
|
+
constructor(stamper, storage, urlParamsAccessor, auth2ProviderOptions, kmsClientOptions) {
|
|
2892
|
+
this.stamper = stamper;
|
|
2893
|
+
this.storage = storage;
|
|
2894
|
+
this.urlParamsAccessor = urlParamsAccessor;
|
|
2895
|
+
this.auth2ProviderOptions = auth2ProviderOptions;
|
|
2896
|
+
this.kms = new import_auth2.Auth2KmsRpcClient(stamper, kmsClientOptions);
|
|
2848
2897
|
}
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2898
|
+
/** Redirect the browser. Extracted as a static method so tests can spy on it. */
|
|
2899
|
+
static navigate(url) {
|
|
2900
|
+
window.location.href = url;
|
|
2901
|
+
}
|
|
2902
|
+
/**
|
|
2903
|
+
* Builds the Auth2 /login/start URL and redirects the browser.
|
|
2904
|
+
*
|
|
2905
|
+
* Called by EmbeddedProvider.handleRedirectAuth() after the stamper has
|
|
2906
|
+
* already been initialized and a pending Session has been saved to storage.
|
|
2907
|
+
* We store the PKCE code_verifier and salt into that session so they survive
|
|
2908
|
+
* the page redirect without ever touching sessionStorage.
|
|
2909
|
+
*/
|
|
2910
|
+
async authenticate(options) {
|
|
2911
|
+
if (!this.stamper.getKeyInfo()) {
|
|
2912
|
+
await this.stamper.init();
|
|
2913
|
+
}
|
|
2914
|
+
const keyPair = this.stamper.getCryptoKeyPair();
|
|
2915
|
+
if (!keyPair) {
|
|
2916
|
+
throw new Error("Stamper key pair not found.");
|
|
2917
|
+
}
|
|
2918
|
+
const codeVerifier = (0, import_auth2.createCodeVerifier)();
|
|
2919
|
+
const salt = (0, import_auth2.createSalt)();
|
|
2920
|
+
const session = await this.storage.getSession();
|
|
2921
|
+
if (!session) {
|
|
2922
|
+
throw new Error("Session not found.");
|
|
2923
|
+
}
|
|
2924
|
+
await this.storage.saveSession({ ...session, pkceCodeVerifier: codeVerifier, salt });
|
|
2925
|
+
const url = await (0, import_auth2.createConnectStartUrl)({
|
|
2926
|
+
keyPair,
|
|
2927
|
+
connectLoginUrl: this.auth2ProviderOptions.connectLoginUrl,
|
|
2928
|
+
clientId: this.auth2ProviderOptions.clientId,
|
|
2929
|
+
redirectUri: this.auth2ProviderOptions.redirectUri,
|
|
2930
|
+
sessionId: options.sessionId,
|
|
2931
|
+
provider: options.provider,
|
|
2932
|
+
codeVerifier,
|
|
2933
|
+
salt
|
|
2934
|
+
});
|
|
2935
|
+
Auth2AuthProvider.navigate(url);
|
|
2936
|
+
}
|
|
2937
|
+
/**
|
|
2938
|
+
* Processes the Auth2 callback after the browser returns from /login/start.
|
|
2939
|
+
*
|
|
2940
|
+
* Exchanges the authorization code for tokens, discovers the organization
|
|
2941
|
+
* and wallet via KMS RPC, then returns a completed AuthResult.
|
|
2942
|
+
*/
|
|
2943
|
+
async resumeAuthFromRedirect(provider) {
|
|
2944
|
+
const code = this.urlParamsAccessor.getParam("code");
|
|
2945
|
+
if (!code) {
|
|
2946
|
+
return null;
|
|
2852
2947
|
}
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
return false;
|
|
2948
|
+
if (!this.stamper.getKeyInfo()) {
|
|
2949
|
+
await this.stamper.init();
|
|
2856
2950
|
}
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2951
|
+
const session = await this.storage.getSession();
|
|
2952
|
+
if (!session) {
|
|
2953
|
+
throw new Error("Session not found.");
|
|
2954
|
+
}
|
|
2955
|
+
const codeVerifier = session?.pkceCodeVerifier;
|
|
2956
|
+
if (!codeVerifier) {
|
|
2957
|
+
return null;
|
|
2958
|
+
}
|
|
2959
|
+
const state = this.urlParamsAccessor.getParam("state");
|
|
2960
|
+
if (!state || state !== session.sessionId) {
|
|
2961
|
+
throw new Error("Missing or invalid Auth2 state parameter \u2014 possible CSRF attack.");
|
|
2962
|
+
}
|
|
2963
|
+
const error = this.urlParamsAccessor.getParam("error");
|
|
2964
|
+
if (error) {
|
|
2965
|
+
const description = this.urlParamsAccessor.getParam("error_description");
|
|
2966
|
+
throw new Error(`Auth2 callback error: ${description ?? error}`);
|
|
2967
|
+
}
|
|
2968
|
+
const { idToken, bearerToken, authUserId, expiresInMs } = await (0, import_auth2.exchangeAuthCode)({
|
|
2969
|
+
authApiBaseUrl: this.auth2ProviderOptions.authApiBaseUrl,
|
|
2970
|
+
clientId: this.auth2ProviderOptions.clientId,
|
|
2971
|
+
redirectUri: this.auth2ProviderOptions.redirectUri,
|
|
2972
|
+
code,
|
|
2973
|
+
codeVerifier
|
|
2974
|
+
});
|
|
2975
|
+
this.stamper.idToken = idToken;
|
|
2976
|
+
this.stamper.salt = session?.salt;
|
|
2977
|
+
await this.storage.saveSession({
|
|
2978
|
+
...session,
|
|
2979
|
+
status: "completed",
|
|
2980
|
+
bearerToken,
|
|
2981
|
+
authUserId,
|
|
2982
|
+
pkceCodeVerifier: void 0,
|
|
2983
|
+
// no longer needed after code exchange
|
|
2984
|
+
salt: void 0
|
|
2985
|
+
// no longer needed after nonce binding is complete
|
|
2986
|
+
});
|
|
2987
|
+
const { organizationId, walletId } = await this.kms.discoverOrganizationAndWalletId(bearerToken, authUserId);
|
|
2988
|
+
return {
|
|
2989
|
+
walletId,
|
|
2990
|
+
organizationId,
|
|
2991
|
+
provider,
|
|
2992
|
+
accountDerivationIndex: 0,
|
|
2993
|
+
// discoverWalletId uses derivation index of 0.
|
|
2994
|
+
expiresInMs,
|
|
2995
|
+
authUserId,
|
|
2996
|
+
bearerToken
|
|
2997
|
+
};
|
|
2861
2998
|
}
|
|
2862
|
-
}
|
|
2863
|
-
|
|
2999
|
+
};
|
|
3000
|
+
|
|
3001
|
+
// src/providers/embedded/adapters/Auth2Stamper.ts
|
|
3002
|
+
var import_bs582 = __toESM(require("bs58"));
|
|
3003
|
+
var import_base64url = require("@phantom/base64url");
|
|
3004
|
+
var import_sdk_types = require("@phantom/sdk-types");
|
|
3005
|
+
var STORE_NAME = "crypto-keys";
|
|
3006
|
+
var ACTIVE_KEY = "auth2-p256-signing-key";
|
|
3007
|
+
var Auth2Stamper = class {
|
|
3008
|
+
/**
|
|
3009
|
+
* @param dbName - IndexedDB database name (use a unique name per app to
|
|
3010
|
+
* avoid key collisions with other stampers, e.g. `phantom-auth2-<appId>`).
|
|
3011
|
+
*/
|
|
3012
|
+
constructor(dbName) {
|
|
3013
|
+
this.dbName = dbName;
|
|
3014
|
+
this.db = null;
|
|
3015
|
+
this.keyPair = null;
|
|
3016
|
+
this._keyInfo = null;
|
|
3017
|
+
this.algorithm = import_sdk_types.Algorithm.secp256r1;
|
|
3018
|
+
this.type = "PKI";
|
|
3019
|
+
}
|
|
3020
|
+
async init() {
|
|
3021
|
+
await this.openDB();
|
|
3022
|
+
const stored = await this.loadKeyPair();
|
|
3023
|
+
if (stored) {
|
|
3024
|
+
this.keyPair = stored.keyPair;
|
|
3025
|
+
this._keyInfo = stored.keyInfo;
|
|
3026
|
+
return this._keyInfo;
|
|
3027
|
+
}
|
|
3028
|
+
return this.generateAndStore();
|
|
3029
|
+
}
|
|
3030
|
+
getKeyInfo() {
|
|
3031
|
+
return this._keyInfo;
|
|
3032
|
+
}
|
|
3033
|
+
getCryptoKeyPair() {
|
|
3034
|
+
return this.keyPair;
|
|
3035
|
+
}
|
|
3036
|
+
async stamp(params) {
|
|
3037
|
+
if (!this.keyPair || !this._keyInfo) {
|
|
3038
|
+
throw new Error("Auth2Stamper not initialized. Call init() first.");
|
|
3039
|
+
}
|
|
3040
|
+
const signatureRaw = await crypto.subtle.sign(
|
|
3041
|
+
{ name: "ECDSA", hash: "SHA-256" },
|
|
3042
|
+
this.keyPair.privateKey,
|
|
3043
|
+
new Uint8Array(params.data)
|
|
3044
|
+
);
|
|
3045
|
+
const rawPublicKey = import_bs582.default.decode(this._keyInfo.publicKey);
|
|
3046
|
+
if (this.idToken === void 0 || this.salt === void 0) {
|
|
3047
|
+
throw new Error("Auth2Stamper not initialized with idToken or salt.");
|
|
3048
|
+
}
|
|
3049
|
+
const stampData = {
|
|
3050
|
+
kind: "OIDC",
|
|
3051
|
+
idToken: this.idToken,
|
|
3052
|
+
publicKey: (0, import_base64url.base64urlEncode)(rawPublicKey),
|
|
3053
|
+
algorithm: "Secp256r1",
|
|
3054
|
+
salt: this.salt,
|
|
3055
|
+
signature: (0, import_base64url.base64urlEncode)(new Uint8Array(signatureRaw))
|
|
3056
|
+
};
|
|
3057
|
+
return (0, import_base64url.base64urlEncode)(new TextEncoder().encode(JSON.stringify(stampData)));
|
|
3058
|
+
}
|
|
3059
|
+
async resetKeyPair() {
|
|
3060
|
+
await this.clearStoredKey();
|
|
3061
|
+
this.keyPair = null;
|
|
3062
|
+
this._keyInfo = null;
|
|
3063
|
+
return this.generateAndStore();
|
|
3064
|
+
}
|
|
3065
|
+
async clear() {
|
|
3066
|
+
await this.clearStoredKey();
|
|
3067
|
+
this.keyPair = null;
|
|
3068
|
+
this._keyInfo = null;
|
|
3069
|
+
}
|
|
3070
|
+
// Auth2 doesn't use key rotation; provide minimal no-op implementations.
|
|
3071
|
+
async rotateKeyPair() {
|
|
3072
|
+
return this.init();
|
|
3073
|
+
}
|
|
3074
|
+
// eslint-disable-next-line @typescript-eslint/require-await
|
|
3075
|
+
async commitRotation(authenticatorId) {
|
|
3076
|
+
if (this._keyInfo) {
|
|
3077
|
+
this._keyInfo.authenticatorId = authenticatorId;
|
|
3078
|
+
}
|
|
3079
|
+
}
|
|
3080
|
+
async rollbackRotation() {
|
|
3081
|
+
}
|
|
3082
|
+
async generateAndStore() {
|
|
3083
|
+
const keyPair = await crypto.subtle.generateKey(
|
|
3084
|
+
{ name: "ECDSA", namedCurve: "P-256" },
|
|
3085
|
+
false,
|
|
3086
|
+
// non-extractable — private key never leaves Web Crypto
|
|
3087
|
+
["sign", "verify"]
|
|
3088
|
+
);
|
|
3089
|
+
const rawPublicKey = new Uint8Array(await crypto.subtle.exportKey("raw", keyPair.publicKey));
|
|
3090
|
+
const publicKeyBase58 = import_bs582.default.encode(rawPublicKey);
|
|
3091
|
+
const keyIdBuffer = await crypto.subtle.digest("SHA-256", rawPublicKey.buffer);
|
|
3092
|
+
const keyId = (0, import_base64url.base64urlEncode)(new Uint8Array(keyIdBuffer)).substring(0, 16);
|
|
3093
|
+
this.keyPair = keyPair;
|
|
3094
|
+
this._keyInfo = {
|
|
3095
|
+
keyId,
|
|
3096
|
+
publicKey: publicKeyBase58,
|
|
3097
|
+
createdAt: Date.now()
|
|
3098
|
+
};
|
|
3099
|
+
await this.storeKeyPair(keyPair, this._keyInfo);
|
|
3100
|
+
return this._keyInfo;
|
|
3101
|
+
}
|
|
3102
|
+
async openDB() {
|
|
3103
|
+
return new Promise((resolve, reject) => {
|
|
3104
|
+
const request = indexedDB.open(this.dbName, 1);
|
|
3105
|
+
request.onsuccess = () => {
|
|
3106
|
+
this.db = request.result;
|
|
3107
|
+
resolve();
|
|
3108
|
+
};
|
|
3109
|
+
request.onerror = () => reject(request.error);
|
|
3110
|
+
request.onupgradeneeded = (event) => {
|
|
3111
|
+
const db = event.target.result;
|
|
3112
|
+
if (!db.objectStoreNames.contains(STORE_NAME)) {
|
|
3113
|
+
db.createObjectStore(STORE_NAME);
|
|
3114
|
+
}
|
|
3115
|
+
};
|
|
3116
|
+
});
|
|
3117
|
+
}
|
|
3118
|
+
async loadKeyPair() {
|
|
3119
|
+
return new Promise((resolve, reject) => {
|
|
3120
|
+
if (!this.db) {
|
|
3121
|
+
throw new Error("Database not initialized");
|
|
3122
|
+
}
|
|
3123
|
+
const request = this.db.transaction([STORE_NAME], "readonly").objectStore(STORE_NAME).get(ACTIVE_KEY);
|
|
3124
|
+
request.onsuccess = () => {
|
|
3125
|
+
resolve(request.result ?? null);
|
|
3126
|
+
};
|
|
3127
|
+
request.onerror = () => {
|
|
3128
|
+
reject(request.error);
|
|
3129
|
+
};
|
|
3130
|
+
});
|
|
3131
|
+
}
|
|
3132
|
+
async storeKeyPair(keyPair, keyInfo) {
|
|
3133
|
+
return new Promise((resolve, reject) => {
|
|
3134
|
+
if (!this.db) {
|
|
3135
|
+
throw new Error("Database not initialized");
|
|
3136
|
+
}
|
|
3137
|
+
const request = this.db.transaction([STORE_NAME], "readwrite").objectStore(STORE_NAME).put({ keyPair, keyInfo }, ACTIVE_KEY);
|
|
3138
|
+
request.onsuccess = () => {
|
|
3139
|
+
resolve();
|
|
3140
|
+
};
|
|
3141
|
+
request.onerror = () => {
|
|
3142
|
+
reject(request.error);
|
|
3143
|
+
};
|
|
3144
|
+
});
|
|
3145
|
+
}
|
|
3146
|
+
async clearStoredKey() {
|
|
3147
|
+
return new Promise((resolve, reject) => {
|
|
3148
|
+
if (!this.db) {
|
|
3149
|
+
throw new Error("Database not initialized");
|
|
3150
|
+
}
|
|
3151
|
+
const request = this.db.transaction([STORE_NAME], "readwrite").objectStore(STORE_NAME).delete(ACTIVE_KEY);
|
|
3152
|
+
request.onsuccess = () => {
|
|
3153
|
+
resolve();
|
|
3154
|
+
};
|
|
3155
|
+
request.onerror = () => {
|
|
3156
|
+
reject(request.error);
|
|
3157
|
+
};
|
|
3158
|
+
});
|
|
3159
|
+
}
|
|
3160
|
+
};
|
|
3161
|
+
|
|
3162
|
+
// src/providers/embedded/adapters/phantom-app.ts
|
|
3163
|
+
var import_browser_injected_sdk4 = require("@phantom/browser-injected-sdk");
|
|
3164
|
+
|
|
3165
|
+
// src/waitForPhantomExtension.ts
|
|
3166
|
+
var import_browser_injected_sdk3 = require("@phantom/browser-injected-sdk");
|
|
3167
|
+
async function waitForPhantomExtension(timeoutMs = 3e3) {
|
|
2864
3168
|
return new Promise((resolve) => {
|
|
2865
3169
|
const startTime = Date.now();
|
|
2866
3170
|
const checkInterval = 100;
|
|
@@ -2883,6 +3187,27 @@ async function waitForExtension(timeoutMs) {
|
|
|
2883
3187
|
});
|
|
2884
3188
|
}
|
|
2885
3189
|
|
|
3190
|
+
// src/isPhantomLoginAvailable.ts
|
|
3191
|
+
async function isPhantomLoginAvailable(timeoutMs = 3e3) {
|
|
3192
|
+
const extensionInstalled = await waitForPhantomExtension(timeoutMs);
|
|
3193
|
+
if (!extensionInstalled) {
|
|
3194
|
+
return false;
|
|
3195
|
+
}
|
|
3196
|
+
try {
|
|
3197
|
+
if (!window.phantom?.app?.features || typeof window.phantom.app.features !== "function") {
|
|
3198
|
+
return false;
|
|
3199
|
+
}
|
|
3200
|
+
const response = await window.phantom.app.features();
|
|
3201
|
+
if (!Array.isArray(response.features)) {
|
|
3202
|
+
return false;
|
|
3203
|
+
}
|
|
3204
|
+
return response.features.includes("phantom_login");
|
|
3205
|
+
} catch (error) {
|
|
3206
|
+
console.error("Error checking Phantom extension features", error);
|
|
3207
|
+
return false;
|
|
3208
|
+
}
|
|
3209
|
+
}
|
|
3210
|
+
|
|
2886
3211
|
// src/providers/embedded/adapters/phantom-app.ts
|
|
2887
3212
|
var BrowserPhantomAppProvider = class {
|
|
2888
3213
|
/**
|
|
@@ -2952,35 +3277,50 @@ var BrowserLogger = class {
|
|
|
2952
3277
|
};
|
|
2953
3278
|
|
|
2954
3279
|
// src/providers/embedded/index.ts
|
|
2955
|
-
var
|
|
3280
|
+
var import_constants4 = require("@phantom/constants");
|
|
2956
3281
|
var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvider {
|
|
2957
3282
|
constructor(config) {
|
|
2958
3283
|
debug.log(DebugCategory.EMBEDDED_PROVIDER, "Initializing Browser EmbeddedProvider", { config });
|
|
2959
3284
|
const urlParamsAccessor = new BrowserURLParamsAccessor();
|
|
2960
|
-
const
|
|
3285
|
+
const storage = new BrowserStorage();
|
|
3286
|
+
const stamper = config.unstable__auth2Options ? new Auth2Stamper(`phantom-auth2-${config.appId}`) : new import_indexed_db_stamper.IndexedDbStamper({
|
|
2961
3287
|
dbName: `phantom-embedded-sdk-${config.appId}`,
|
|
2962
3288
|
storeName: "crypto-keys",
|
|
2963
3289
|
keyName: "signing-key"
|
|
2964
3290
|
});
|
|
2965
3291
|
const platformName = getPlatformName();
|
|
2966
3292
|
const { name: browserName, version } = detectBrowser();
|
|
3293
|
+
const authProvider = config.unstable__auth2Options && config.authOptions?.authUrl && config.authOptions?.redirectUrl && stamper instanceof Auth2Stamper ? new Auth2AuthProvider(
|
|
3294
|
+
stamper,
|
|
3295
|
+
storage,
|
|
3296
|
+
urlParamsAccessor,
|
|
3297
|
+
{
|
|
3298
|
+
redirectUri: config.authOptions.redirectUrl,
|
|
3299
|
+
connectLoginUrl: config.authOptions.authUrl,
|
|
3300
|
+
clientId: config.unstable__auth2Options.clientId,
|
|
3301
|
+
authApiBaseUrl: config.unstable__auth2Options.authApiBaseUrl
|
|
3302
|
+
},
|
|
3303
|
+
{
|
|
3304
|
+
apiBaseUrl: config.apiBaseUrl,
|
|
3305
|
+
appId: config.appId
|
|
3306
|
+
}
|
|
3307
|
+
) : new BrowserAuthProvider(urlParamsAccessor);
|
|
2967
3308
|
const platform = {
|
|
2968
|
-
storage
|
|
2969
|
-
authProvider
|
|
3309
|
+
storage,
|
|
3310
|
+
authProvider,
|
|
2970
3311
|
phantomAppProvider: new BrowserPhantomAppProvider(),
|
|
2971
3312
|
urlParamsAccessor,
|
|
2972
3313
|
stamper,
|
|
2973
3314
|
name: platformName,
|
|
2974
3315
|
// Use detected browser name and version for identification
|
|
2975
3316
|
analyticsHeaders: {
|
|
2976
|
-
[
|
|
2977
|
-
[
|
|
2978
|
-
|
|
2979
|
-
[
|
|
2980
|
-
|
|
2981
|
-
[
|
|
2982
|
-
[
|
|
2983
|
-
[import_constants2.ANALYTICS_HEADERS.SDK_VERSION]: "1.0.2"
|
|
3317
|
+
[import_constants4.ANALYTICS_HEADERS.SDK_TYPE]: "browser",
|
|
3318
|
+
[import_constants4.ANALYTICS_HEADERS.PLATFORM]: "ext-sdk",
|
|
3319
|
+
[import_constants4.ANALYTICS_HEADERS.PLATFORM_VERSION]: version,
|
|
3320
|
+
[import_constants4.ANALYTICS_HEADERS.CLIENT]: browserName,
|
|
3321
|
+
[import_constants4.ANALYTICS_HEADERS.APP_ID]: config.appId,
|
|
3322
|
+
[import_constants4.ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
|
|
3323
|
+
[import_constants4.ANALYTICS_HEADERS.SDK_VERSION]: "1.0.4"
|
|
2984
3324
|
// Replaced at build time
|
|
2985
3325
|
}
|
|
2986
3326
|
};
|
|
@@ -2997,7 +3337,7 @@ var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvi
|
|
|
2997
3337
|
|
|
2998
3338
|
// src/ProviderManager.ts
|
|
2999
3339
|
var import_embedded_provider_core2 = require("@phantom/embedded-provider-core");
|
|
3000
|
-
var
|
|
3340
|
+
var import_constants5 = require("@phantom/constants");
|
|
3001
3341
|
|
|
3002
3342
|
// src/utils/auth-callback.ts
|
|
3003
3343
|
function isAuthFailureCallback(searchParams) {
|
|
@@ -3017,11 +3357,12 @@ function isAuthCallbackUrl(searchParams) {
|
|
|
3017
3357
|
}
|
|
3018
3358
|
|
|
3019
3359
|
// src/utils/deeplink.ts
|
|
3020
|
-
function getDeeplinkToPhantom(ref) {
|
|
3021
|
-
|
|
3360
|
+
function getDeeplinkToPhantom(ref, currentHref) {
|
|
3361
|
+
const resolvedHref = currentHref ?? window.location.href;
|
|
3362
|
+
if (!resolvedHref.startsWith("http:") && !resolvedHref.startsWith("https:")) {
|
|
3022
3363
|
throw new Error("Invalid URL protocol - only HTTP/HTTPS URLs are supported for deeplinks");
|
|
3023
3364
|
}
|
|
3024
|
-
const currentUrl = encodeURIComponent(
|
|
3365
|
+
const currentUrl = encodeURIComponent(resolvedHref);
|
|
3025
3366
|
const refParam = ref ? `?ref=${encodeURIComponent(ref)}` : "";
|
|
3026
3367
|
return `https://phantom.app/ul/browse/${currentUrl}${refParam}`;
|
|
3027
3368
|
}
|
|
@@ -3117,8 +3458,14 @@ var ProviderManager = class {
|
|
|
3117
3458
|
} else if (requestedProvider === "deeplink") {
|
|
3118
3459
|
try {
|
|
3119
3460
|
const deeplinkUrl = getDeeplinkToPhantom();
|
|
3120
|
-
if (typeof window !== "undefined") {
|
|
3121
|
-
|
|
3461
|
+
if (typeof window !== "undefined" && window.location) {
|
|
3462
|
+
try {
|
|
3463
|
+
window.location.href = deeplinkUrl;
|
|
3464
|
+
} catch (error) {
|
|
3465
|
+
debug.warn(DebugCategory.PROVIDER_MANAGER, "Failed to set deeplink location", {
|
|
3466
|
+
error: error instanceof Error ? error.message : String(error)
|
|
3467
|
+
});
|
|
3468
|
+
}
|
|
3122
3469
|
}
|
|
3123
3470
|
return {
|
|
3124
3471
|
addresses: [],
|
|
@@ -3381,8 +3728,8 @@ var ProviderManager = class {
|
|
|
3381
3728
|
if (!this.config.appId) {
|
|
3382
3729
|
throw new Error("appId is required for embedded provider");
|
|
3383
3730
|
}
|
|
3384
|
-
const apiBaseUrl = this.config.apiBaseUrl ||
|
|
3385
|
-
const authUrl = this.config.authOptions?.authUrl ||
|
|
3731
|
+
const apiBaseUrl = this.config.apiBaseUrl || import_constants5.DEFAULT_WALLET_API_URL;
|
|
3732
|
+
const authUrl = this.config.authOptions?.authUrl || import_constants5.DEFAULT_AUTH_URL;
|
|
3386
3733
|
provider = new EmbeddedProvider({
|
|
3387
3734
|
apiBaseUrl,
|
|
3388
3735
|
appId: this.config.appId,
|
|
@@ -3391,7 +3738,8 @@ var ProviderManager = class {
|
|
|
3391
3738
|
authUrl,
|
|
3392
3739
|
redirectUrl: this.config.authOptions?.redirectUrl || this.getValidatedCurrentUrl()
|
|
3393
3740
|
},
|
|
3394
|
-
|
|
3741
|
+
unstable__auth2Options: this.config.unstable__auth2Options,
|
|
3742
|
+
embeddedWalletType: embeddedWalletType || import_constants5.DEFAULT_EMBEDDED_WALLET_TYPE,
|
|
3395
3743
|
addressTypes: this.config.addressTypes || [import_client.AddressType.solana]
|
|
3396
3744
|
});
|
|
3397
3745
|
} else {
|
|
@@ -3427,7 +3775,7 @@ var ProviderManager = class {
|
|
|
3427
3775
|
|
|
3428
3776
|
// src/BrowserSDK.ts
|
|
3429
3777
|
var import_embedded_provider_core3 = require("@phantom/embedded-provider-core");
|
|
3430
|
-
var
|
|
3778
|
+
var import_constants6 = require("@phantom/constants");
|
|
3431
3779
|
var BROWSER_SDK_PROVIDER_TYPES = [
|
|
3432
3780
|
...import_embedded_provider_core3.EMBEDDED_PROVIDER_AUTH_TYPES,
|
|
3433
3781
|
"injected",
|
|
@@ -3463,7 +3811,7 @@ var BrowserSDK = class {
|
|
|
3463
3811
|
});
|
|
3464
3812
|
throw new Error("appId is required when using embedded providers (google, apple, phantom, etc.)");
|
|
3465
3813
|
}
|
|
3466
|
-
const embeddedWalletType = config.embeddedWalletType ||
|
|
3814
|
+
const embeddedWalletType = config.embeddedWalletType || import_constants6.DEFAULT_EMBEDDED_WALLET_TYPE;
|
|
3467
3815
|
if (!["app-wallet", "user-wallet"].includes(embeddedWalletType)) {
|
|
3468
3816
|
debug.error(DebugCategory.BROWSER_SDK, "Invalid embeddedWalletType", {
|
|
3469
3817
|
embeddedWalletType: config.embeddedWalletType
|
|
@@ -3589,6 +3937,7 @@ var BrowserSDK = class {
|
|
|
3589
3937
|
*/
|
|
3590
3938
|
async autoConnect() {
|
|
3591
3939
|
debug.log(DebugCategory.BROWSER_SDK, "Attempting auto-connect with fallback strategy");
|
|
3940
|
+
await this.discoverWallets();
|
|
3592
3941
|
const result = await this.providerManager.autoConnect();
|
|
3593
3942
|
if (result) {
|
|
3594
3943
|
debug.info(DebugCategory.BROWSER_SDK, "Auto-connect successful", {
|
|
@@ -3736,31 +4085,7 @@ var BrowserSDK = class {
|
|
|
3736
4085
|
}
|
|
3737
4086
|
};
|
|
3738
4087
|
|
|
3739
|
-
// src/waitForPhantomExtension.ts
|
|
3740
|
-
var import_browser_injected_sdk5 = require("@phantom/browser-injected-sdk");
|
|
3741
|
-
async function waitForPhantomExtension(timeoutMs = 3e3) {
|
|
3742
|
-
return new Promise((resolve) => {
|
|
3743
|
-
const startTime = Date.now();
|
|
3744
|
-
const checkInterval = 100;
|
|
3745
|
-
const checkForExtension = () => {
|
|
3746
|
-
try {
|
|
3747
|
-
if ((0, import_browser_injected_sdk5.isPhantomExtensionInstalled)()) {
|
|
3748
|
-
resolve(true);
|
|
3749
|
-
return;
|
|
3750
|
-
}
|
|
3751
|
-
} catch (error) {
|
|
3752
|
-
}
|
|
3753
|
-
const elapsed = Date.now() - startTime;
|
|
3754
|
-
if (elapsed >= timeoutMs) {
|
|
3755
|
-
resolve(false);
|
|
3756
|
-
return;
|
|
3757
|
-
}
|
|
3758
|
-
setTimeout(checkForExtension, checkInterval);
|
|
3759
|
-
};
|
|
3760
|
-
checkForExtension();
|
|
3761
|
-
});
|
|
3762
|
-
}
|
|
3763
|
-
|
|
3764
4088
|
// src/index.ts
|
|
3765
|
-
var
|
|
3766
|
-
var
|
|
4089
|
+
var import_constants7 = require("@phantom/constants");
|
|
4090
|
+
var import_client5 = require("@phantom/client");
|
|
4091
|
+
var import_constants8 = require("@phantom/constants");
|