@phantom/browser-sdk 1.0.0 → 1.0.3
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 +3 -3
- package/dist/index.js +574 -703
- package/dist/index.mjs +554 -683
- package/package.json +10 -10
package/dist/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { AddressType } from "@phantom/client";
|
|
3
3
|
|
|
4
4
|
// src/providers/injected/index.ts
|
|
5
|
-
import { AddressType as
|
|
5
|
+
import { AddressType as AddressType3 } from "@phantom/client";
|
|
6
6
|
|
|
7
7
|
// src/debug.ts
|
|
8
8
|
var DebugLevel = /* @__PURE__ */ ((DebugLevel2) => {
|
|
@@ -79,12 +79,27 @@ var DebugCategory = {
|
|
|
79
79
|
};
|
|
80
80
|
|
|
81
81
|
// src/wallets/discovery.ts
|
|
82
|
+
import { PHANTOM_ICON } from "@phantom/constants";
|
|
82
83
|
import { AddressType as ClientAddressType } from "@phantom/client";
|
|
83
84
|
import { isPhantomExtensionInstalled } from "@phantom/browser-injected-sdk";
|
|
84
85
|
import { createPhantom, createExtensionPlugin } from "@phantom/browser-injected-sdk";
|
|
85
86
|
import { createSolanaPlugin } from "@phantom/browser-injected-sdk/solana";
|
|
86
87
|
import { createEthereumPlugin } from "@phantom/browser-injected-sdk/ethereum";
|
|
87
88
|
import { createAutoConfirmPlugin } from "@phantom/browser-injected-sdk/auto-confirm";
|
|
89
|
+
|
|
90
|
+
// src/wallets/custom-wallets.ts
|
|
91
|
+
import { AddressType as AddressType2 } from "@phantom/client";
|
|
92
|
+
var CUSTOM_WALLET_CONFIGS = [
|
|
93
|
+
{
|
|
94
|
+
id: "coinbase-wallet",
|
|
95
|
+
name: "Coinbase Wallet",
|
|
96
|
+
icon: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNTYiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0iTTI4IDU2YzE1LjQ2NCAwIDI4LTEyLjUzNiAyOC0yOFM0My40NjQgMCAyOCAwIDAgMTIuNTM2IDAgMjhzMTIuNTM2IDI4IDI4IDI4WiIgZmlsbD0iIzFCNTNFNCIvPjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNNyAyOGMwIDExLjU5OCA5LjQwMiAyMSAyMSAyMXMyMS05LjQwMiAyMS0yMVMzOS41OTggNyAyOCA3IDcgMTYuNDAyIDcgMjhabTE3LjIzNC02Ljc2NmEzIDMgMCAwIDAtMyAzdjcuNTMzYTMgMyAwIDAgMCAzIDNoNy41MzNhMyAzIDAgMCAwIDMtM3YtNy41MzNhMyAzIDAgMCAwLTMtM2gtNy41MzNaIiBmaWxsPSIjZmZmIi8+PC9zdmc+",
|
|
97
|
+
windowProperty: "coinbaseSolana",
|
|
98
|
+
addressTypes: [AddressType2.solana]
|
|
99
|
+
}
|
|
100
|
+
];
|
|
101
|
+
|
|
102
|
+
// src/wallets/discovery.ts
|
|
88
103
|
function generateWalletIdFromEIP6963(info) {
|
|
89
104
|
if (info.rdns) {
|
|
90
105
|
return info.rdns.split(".").reverse().join("-");
|
|
@@ -297,7 +312,7 @@ async function discoverSolanaWallets() {
|
|
|
297
312
|
return chainLower.startsWith("solana:") || chainLower === "solana";
|
|
298
313
|
}) || wallet.features && typeof wallet.features === "object" && Object.keys(wallet.features).some((featureKey) => {
|
|
299
314
|
const featureLower = featureKey.toLowerCase();
|
|
300
|
-
return featureLower.
|
|
315
|
+
return featureLower.startsWith("solana:");
|
|
301
316
|
});
|
|
302
317
|
if (!supportsSolana) {
|
|
303
318
|
const featureKeys = wallet.features ? Object.keys(wallet.features) : [];
|
|
@@ -348,6 +363,51 @@ async function discoverSolanaWallets() {
|
|
|
348
363
|
walletNames: wallets.map((w) => w.name)
|
|
349
364
|
};
|
|
350
365
|
debug.log(DebugCategory.BROWSER_SDK, "Wallet Standard Solana discovery completed", finalLogData);
|
|
366
|
+
const customWallets = discoverCustomSolanaWallets();
|
|
367
|
+
wallets.push(...customWallets);
|
|
368
|
+
return wallets;
|
|
369
|
+
}
|
|
370
|
+
function discoverCustomSolanaWallets() {
|
|
371
|
+
const wallets = [];
|
|
372
|
+
if (typeof window === "undefined") {
|
|
373
|
+
debug.log(DebugCategory.BROWSER_SDK, "Custom wallet discovery skipped (not in browser environment)");
|
|
374
|
+
return wallets;
|
|
375
|
+
}
|
|
376
|
+
debug.log(DebugCategory.BROWSER_SDK, "Starting custom Solana wallet discovery", {
|
|
377
|
+
configCount: CUSTOM_WALLET_CONFIGS.length
|
|
378
|
+
});
|
|
379
|
+
for (const config of CUSTOM_WALLET_CONFIGS) {
|
|
380
|
+
if (!config.addressTypes.includes(ClientAddressType.solana)) {
|
|
381
|
+
continue;
|
|
382
|
+
}
|
|
383
|
+
const provider = window[config.windowProperty];
|
|
384
|
+
if (!provider) {
|
|
385
|
+
debug.log(DebugCategory.BROWSER_SDK, "Custom wallet not found", {
|
|
386
|
+
walletId: config.id,
|
|
387
|
+
windowProperty: config.windowProperty
|
|
388
|
+
});
|
|
389
|
+
continue;
|
|
390
|
+
}
|
|
391
|
+
debug.log(DebugCategory.BROWSER_SDK, "Discovered custom Solana wallet", {
|
|
392
|
+
walletId: config.id,
|
|
393
|
+
walletName: config.name,
|
|
394
|
+
windowProperty: config.windowProperty
|
|
395
|
+
});
|
|
396
|
+
wallets.push({
|
|
397
|
+
id: config.id,
|
|
398
|
+
name: config.name,
|
|
399
|
+
icon: config.icon,
|
|
400
|
+
addressTypes: config.addressTypes,
|
|
401
|
+
providers: {
|
|
402
|
+
solana: provider
|
|
403
|
+
},
|
|
404
|
+
discovery: "custom"
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
debug.log(DebugCategory.BROWSER_SDK, "Custom Solana wallet discovery completed", {
|
|
408
|
+
discoveredCount: wallets.length,
|
|
409
|
+
walletIds: wallets.map((w) => w.id)
|
|
410
|
+
});
|
|
351
411
|
return wallets;
|
|
352
412
|
}
|
|
353
413
|
function discoverPhantomWallet(addressTypes) {
|
|
@@ -369,8 +429,7 @@ function discoverPhantomWallet(addressTypes) {
|
|
|
369
429
|
return {
|
|
370
430
|
id: "phantom",
|
|
371
431
|
name: "Phantom",
|
|
372
|
-
icon:
|
|
373
|
-
// Icon will be rendered from icons package in UI components
|
|
432
|
+
icon: PHANTOM_ICON,
|
|
374
433
|
addressTypes,
|
|
375
434
|
providers: {
|
|
376
435
|
solana: addressTypes.includes(ClientAddressType.solana) ? phantomInstance.solana : void 0,
|
|
@@ -439,67 +498,65 @@ async function discoverWallets(addressTypes) {
|
|
|
439
498
|
return Array.from(walletMap.values());
|
|
440
499
|
}
|
|
441
500
|
|
|
501
|
+
// src/wallets/registry.ts
|
|
502
|
+
import { PHANTOM_ICON as PHANTOM_ICON2 } from "@phantom/constants";
|
|
503
|
+
|
|
442
504
|
// src/providers/injected/chains/InjectedWalletSolanaChain.ts
|
|
443
505
|
import { EventEmitter } from "eventemitter3";
|
|
444
|
-
import { Buffer
|
|
506
|
+
import { Buffer } from "buffer";
|
|
445
507
|
var InjectedWalletSolanaChain = class {
|
|
446
508
|
constructor(provider, walletId, walletName) {
|
|
509
|
+
// Expose eventEmitter for testing - allows tests to trigger events directly
|
|
447
510
|
this.eventEmitter = new EventEmitter();
|
|
448
|
-
this._connected = false;
|
|
449
511
|
this._publicKey = null;
|
|
450
512
|
this.provider = provider;
|
|
451
513
|
this.walletId = walletId;
|
|
452
514
|
this.walletName = walletName;
|
|
453
515
|
this.setupEventListeners();
|
|
454
516
|
}
|
|
455
|
-
get connected() {
|
|
456
|
-
return this._connected;
|
|
457
|
-
}
|
|
458
517
|
get publicKey() {
|
|
459
518
|
return this._publicKey;
|
|
460
519
|
}
|
|
520
|
+
get isConnected() {
|
|
521
|
+
return this.provider.isConnected || !!this._publicKey;
|
|
522
|
+
}
|
|
461
523
|
async connect(options) {
|
|
462
|
-
debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Solana connect", {
|
|
463
|
-
walletId: this.walletId,
|
|
464
|
-
walletName: this.walletName,
|
|
465
|
-
onlyIfTrusted: options?.onlyIfTrusted
|
|
466
|
-
});
|
|
467
524
|
try {
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Solana connected", {
|
|
525
|
+
await this.provider.connect(options);
|
|
526
|
+
const isConnected = this.provider.isConnected;
|
|
527
|
+
if (!isConnected || this.provider.publicKey === null) {
|
|
528
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "Provider not connected after connect() call", {
|
|
473
529
|
walletId: this.walletId,
|
|
474
530
|
walletName: this.walletName,
|
|
475
|
-
|
|
531
|
+
providerConnected: isConnected,
|
|
532
|
+
providerPublicKey: this.provider.publicKey
|
|
476
533
|
});
|
|
477
|
-
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
534
|
+
throw new Error("Provider not connected after connect() call");
|
|
535
|
+
}
|
|
536
|
+
let publicKey;
|
|
537
|
+
const providerPublicKey = this.provider.publicKey;
|
|
538
|
+
if (typeof providerPublicKey === "string") {
|
|
539
|
+
publicKey = providerPublicKey;
|
|
540
|
+
} else if (providerPublicKey !== null && providerPublicKey !== void 0 && typeof providerPublicKey.toString === "function") {
|
|
541
|
+
publicKey = providerPublicKey.toString();
|
|
542
|
+
} else {
|
|
543
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "Invalid publicKey format in provider state", {
|
|
483
544
|
walletId: this.walletId,
|
|
484
545
|
walletName: this.walletName,
|
|
485
|
-
|
|
546
|
+
publicKeyType: typeof providerPublicKey
|
|
486
547
|
});
|
|
487
|
-
|
|
488
|
-
}
|
|
489
|
-
if (
|
|
490
|
-
|
|
491
|
-
if (typeof firstAccount === "object" && firstAccount !== null && "address" in firstAccount) {
|
|
492
|
-
this._connected = true;
|
|
493
|
-
this._publicKey = firstAccount.address;
|
|
494
|
-
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Solana connected", {
|
|
495
|
-
walletId: this.walletId,
|
|
496
|
-
walletName: this.walletName,
|
|
497
|
-
publicKey: firstAccount.address
|
|
498
|
-
});
|
|
499
|
-
return { publicKey: firstAccount.address };
|
|
500
|
-
}
|
|
548
|
+
throw new Error("Invalid publicKey format in provider state");
|
|
549
|
+
}
|
|
550
|
+
if (!publicKey || publicKey.length === 0) {
|
|
551
|
+
throw new Error("Empty publicKey from provider");
|
|
501
552
|
}
|
|
502
|
-
|
|
553
|
+
this._publicKey = publicKey;
|
|
554
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Solana connected", {
|
|
555
|
+
walletId: this.walletId,
|
|
556
|
+
walletName: this.walletName,
|
|
557
|
+
publicKey
|
|
558
|
+
});
|
|
559
|
+
return { publicKey };
|
|
503
560
|
} catch (error) {
|
|
504
561
|
debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Solana connect failed", {
|
|
505
562
|
walletId: this.walletId,
|
|
@@ -516,7 +573,6 @@ var InjectedWalletSolanaChain = class {
|
|
|
516
573
|
});
|
|
517
574
|
try {
|
|
518
575
|
await this.provider.disconnect();
|
|
519
|
-
this._connected = false;
|
|
520
576
|
this._publicKey = null;
|
|
521
577
|
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Solana disconnected", {
|
|
522
578
|
walletId: this.walletId,
|
|
@@ -548,7 +604,7 @@ var InjectedWalletSolanaChain = class {
|
|
|
548
604
|
signatureLength: result.signature.length
|
|
549
605
|
});
|
|
550
606
|
return {
|
|
551
|
-
signature: result.signature instanceof Uint8Array ? result.signature : new Uint8Array(
|
|
607
|
+
signature: result.signature instanceof Uint8Array ? result.signature : new Uint8Array(Buffer.from(result.signature, "base64")),
|
|
552
608
|
publicKey: result.publicKey || this._publicKey || ""
|
|
553
609
|
};
|
|
554
610
|
} catch (error) {
|
|
@@ -652,27 +708,19 @@ var InjectedWalletSolanaChain = class {
|
|
|
652
708
|
switchNetwork(_network) {
|
|
653
709
|
return Promise.resolve();
|
|
654
710
|
}
|
|
655
|
-
getPublicKey() {
|
|
656
|
-
return Promise.resolve(this._publicKey);
|
|
657
|
-
}
|
|
658
|
-
isConnected() {
|
|
659
|
-
return this._connected;
|
|
660
|
-
}
|
|
661
711
|
setupEventListeners() {
|
|
662
712
|
if (typeof this.provider.on === "function") {
|
|
663
713
|
this.provider.on("connect", (publicKey) => {
|
|
664
|
-
this._connected = true;
|
|
665
714
|
this._publicKey = publicKey;
|
|
666
715
|
this.eventEmitter.emit("connect", publicKey);
|
|
667
716
|
});
|
|
668
717
|
this.provider.on("disconnect", () => {
|
|
669
|
-
this._connected = false;
|
|
670
718
|
this._publicKey = null;
|
|
671
719
|
this.eventEmitter.emit("disconnect");
|
|
672
720
|
});
|
|
673
721
|
this.provider.on("accountChanged", (publicKey) => {
|
|
674
|
-
this._publicKey = publicKey;
|
|
675
|
-
this.eventEmitter.emit("accountChanged",
|
|
722
|
+
this._publicKey = publicKey ? publicKey : null;
|
|
723
|
+
this.eventEmitter.emit("accountChanged", this._publicKey);
|
|
676
724
|
});
|
|
677
725
|
}
|
|
678
726
|
}
|
|
@@ -685,26 +733,29 @@ var InjectedWalletSolanaChain = class {
|
|
|
685
733
|
};
|
|
686
734
|
|
|
687
735
|
// src/providers/injected/chains/WalletStandardSolanaAdapter.ts
|
|
736
|
+
import { EventEmitter as EventEmitter2 } from "eventemitter3";
|
|
688
737
|
import { deserializeSolanaTransaction } from "@phantom/parsers";
|
|
738
|
+
import { Buffer as Buffer2 } from "buffer";
|
|
689
739
|
import bs58 from "bs58";
|
|
690
740
|
var WalletStandardSolanaAdapter = class {
|
|
691
741
|
constructor(wallet, walletId, walletName) {
|
|
692
|
-
this.
|
|
742
|
+
this.eventEmitter = new EventEmitter2();
|
|
693
743
|
this._publicKey = null;
|
|
694
744
|
this.wallet = wallet;
|
|
695
745
|
this.walletId = walletId;
|
|
696
746
|
this.walletName = walletName;
|
|
697
|
-
|
|
698
|
-
get connected() {
|
|
699
|
-
return this._connected;
|
|
747
|
+
this.setupEventListeners();
|
|
700
748
|
}
|
|
701
749
|
get publicKey() {
|
|
702
750
|
return this._publicKey;
|
|
703
751
|
}
|
|
752
|
+
get isConnected() {
|
|
753
|
+
return this._publicKey !== null;
|
|
754
|
+
}
|
|
704
755
|
async connect(_options) {
|
|
705
756
|
try {
|
|
706
|
-
const connectFeature = this.wallet.features
|
|
707
|
-
if (!connectFeature
|
|
757
|
+
const connectFeature = this.wallet.features["standard:connect"];
|
|
758
|
+
if (!connectFeature) {
|
|
708
759
|
throw new Error("Wallet Standard connect feature not available");
|
|
709
760
|
}
|
|
710
761
|
const connectResult = await connectFeature.connect();
|
|
@@ -725,14 +776,13 @@ var WalletStandardSolanaAdapter = class {
|
|
|
725
776
|
if (typeof firstAccount === "string") {
|
|
726
777
|
address = firstAccount;
|
|
727
778
|
} else if (typeof firstAccount === "object" && firstAccount !== null) {
|
|
728
|
-
address = firstAccount.address || firstAccount.publicKey?.toString() || (firstAccount.publicKey instanceof Uint8Array ?
|
|
779
|
+
address = firstAccount.address || firstAccount.publicKey?.toString() || (firstAccount.publicKey instanceof Uint8Array ? Buffer2.from(firstAccount.publicKey).toString("hex") : void 0);
|
|
729
780
|
}
|
|
730
781
|
if (!address) {
|
|
731
782
|
throw new Error(
|
|
732
783
|
`Could not extract address from account. Account structure: ${JSON.stringify(firstAccount, null, 2)}`
|
|
733
784
|
);
|
|
734
785
|
}
|
|
735
|
-
this._connected = true;
|
|
736
786
|
this._publicKey = address;
|
|
737
787
|
return { publicKey: address };
|
|
738
788
|
} catch (error) {
|
|
@@ -746,11 +796,10 @@ var WalletStandardSolanaAdapter = class {
|
|
|
746
796
|
}
|
|
747
797
|
async disconnect() {
|
|
748
798
|
try {
|
|
749
|
-
const disconnectFeature = this.wallet.features
|
|
750
|
-
if (disconnectFeature
|
|
799
|
+
const disconnectFeature = this.wallet.features["standard:disconnect"];
|
|
800
|
+
if (disconnectFeature) {
|
|
751
801
|
await disconnectFeature.disconnect();
|
|
752
802
|
}
|
|
753
|
-
this._connected = false;
|
|
754
803
|
this._publicKey = null;
|
|
755
804
|
} catch (error) {
|
|
756
805
|
debug.error(DebugCategory.INJECTED_PROVIDER, "Wallet Standard Solana disconnect failed", {
|
|
@@ -763,14 +812,14 @@ var WalletStandardSolanaAdapter = class {
|
|
|
763
812
|
}
|
|
764
813
|
async signMessage(message) {
|
|
765
814
|
try {
|
|
766
|
-
const signMessageFeature = this.wallet.features
|
|
767
|
-
if (!signMessageFeature
|
|
815
|
+
const signMessageFeature = this.wallet.features["solana:signMessage"];
|
|
816
|
+
if (!signMessageFeature) {
|
|
768
817
|
throw new Error("Wallet Standard signMessage feature not available");
|
|
769
818
|
}
|
|
770
819
|
const messageBytes = typeof message === "string" ? new TextEncoder().encode(message) : message;
|
|
771
820
|
const result = await signMessageFeature.signMessage({
|
|
772
821
|
message: messageBytes,
|
|
773
|
-
account: this.wallet.accounts
|
|
822
|
+
account: this.wallet.accounts[0]
|
|
774
823
|
});
|
|
775
824
|
if (!Array.isArray(result) || result.length === 0) {
|
|
776
825
|
throw new Error(`Expected array result from signMessage, got: ${typeof result}`);
|
|
@@ -783,7 +832,7 @@ var WalletStandardSolanaAdapter = class {
|
|
|
783
832
|
if (signature.length === 0) {
|
|
784
833
|
throw new Error(`Signature is empty`);
|
|
785
834
|
}
|
|
786
|
-
const publicKey = signedMessageResult.account?.address || this.wallet.accounts
|
|
835
|
+
const publicKey = signedMessageResult.account?.address || this.wallet.accounts[0]?.address || this._publicKey || "";
|
|
787
836
|
return { signature, publicKey };
|
|
788
837
|
} catch (error) {
|
|
789
838
|
debug.error(DebugCategory.INJECTED_PROVIDER, "Wallet Standard Solana signMessage failed", {
|
|
@@ -796,8 +845,8 @@ var WalletStandardSolanaAdapter = class {
|
|
|
796
845
|
}
|
|
797
846
|
async signTransaction(transaction) {
|
|
798
847
|
try {
|
|
799
|
-
const signTransactionFeature = this.wallet.features
|
|
800
|
-
if (!signTransactionFeature
|
|
848
|
+
const signTransactionFeature = this.wallet.features["solana:signTransaction"];
|
|
849
|
+
if (!signTransactionFeature) {
|
|
801
850
|
throw new Error("Wallet Standard signTransaction feature not available");
|
|
802
851
|
}
|
|
803
852
|
if (!this.wallet.accounts || this.wallet.accounts.length === 0) {
|
|
@@ -816,7 +865,8 @@ var WalletStandardSolanaAdapter = class {
|
|
|
816
865
|
transactionData = firstItem.signedTransaction || firstItem.transaction;
|
|
817
866
|
}
|
|
818
867
|
} else if (results && typeof results === "object" && !Array.isArray(results)) {
|
|
819
|
-
|
|
868
|
+
const resultObj = results;
|
|
869
|
+
transactionData = resultObj.transaction || resultObj.signedTransaction;
|
|
820
870
|
}
|
|
821
871
|
if (!transactionData) {
|
|
822
872
|
throw new Error("No transaction data found in Wallet Standard result");
|
|
@@ -838,8 +888,8 @@ var WalletStandardSolanaAdapter = class {
|
|
|
838
888
|
}
|
|
839
889
|
async signAndSendTransaction(transaction) {
|
|
840
890
|
try {
|
|
841
|
-
const signAndSendTransactionFeature = this.wallet.features
|
|
842
|
-
if (!signAndSendTransactionFeature
|
|
891
|
+
const signAndSendTransactionFeature = this.wallet.features["solana:signAndSendTransaction"];
|
|
892
|
+
if (!signAndSendTransactionFeature) {
|
|
843
893
|
throw new Error("Wallet Standard signAndSendTransaction feature not available");
|
|
844
894
|
}
|
|
845
895
|
if (!this.wallet.accounts || this.wallet.accounts.length === 0) {
|
|
@@ -910,40 +960,87 @@ var WalletStandardSolanaAdapter = class {
|
|
|
910
960
|
throw error;
|
|
911
961
|
}
|
|
912
962
|
}
|
|
913
|
-
async switchNetwork(
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
963
|
+
async switchNetwork(_network) {
|
|
964
|
+
return Promise.resolve();
|
|
965
|
+
}
|
|
966
|
+
/**
|
|
967
|
+
* Set up event listeners for Wallet Standard events
|
|
968
|
+
* Maps Wallet Standard "change" events to "accountChanged" events
|
|
969
|
+
*
|
|
970
|
+
* Note: Wallet Standard only has a "change" event. There are no "connect" or "disconnect" events.
|
|
971
|
+
* Connection/disconnection is indicated by the presence or absence of accounts in the change event.
|
|
972
|
+
*/
|
|
973
|
+
setupEventListeners() {
|
|
974
|
+
const eventsFeature = this.wallet.features["standard:events"];
|
|
975
|
+
if (!eventsFeature) {
|
|
976
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Wallet Standard events feature not available", {
|
|
922
977
|
walletId: this.walletId,
|
|
923
|
-
walletName: this.walletName
|
|
924
|
-
network,
|
|
925
|
-
error: error instanceof Error ? error.message : String(error)
|
|
978
|
+
walletName: this.walletName
|
|
926
979
|
});
|
|
927
|
-
|
|
980
|
+
return;
|
|
928
981
|
}
|
|
982
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up Wallet Standard event listeners", {
|
|
983
|
+
walletId: this.walletId,
|
|
984
|
+
walletName: this.walletName
|
|
985
|
+
});
|
|
986
|
+
eventsFeature.on("change", (properties) => {
|
|
987
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Wallet Standard change event received", {
|
|
988
|
+
walletId: this.walletId,
|
|
989
|
+
walletName: this.walletName,
|
|
990
|
+
hasAccounts: !!properties.accounts,
|
|
991
|
+
accountCount: properties.accounts?.length || 0
|
|
992
|
+
});
|
|
993
|
+
if (properties.accounts !== void 0) {
|
|
994
|
+
if (properties.accounts.length > 0) {
|
|
995
|
+
const firstAccount = properties.accounts[0];
|
|
996
|
+
const address = this.extractAccountAddress(firstAccount);
|
|
997
|
+
if (address) {
|
|
998
|
+
this._publicKey = address;
|
|
999
|
+
this.eventEmitter.emit("accountChanged", address);
|
|
1000
|
+
this.eventEmitter.emit("connect", address);
|
|
1001
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Emitted accountChanged and connect events", {
|
|
1002
|
+
walletId: this.walletId,
|
|
1003
|
+
walletName: this.walletName,
|
|
1004
|
+
address
|
|
1005
|
+
});
|
|
1006
|
+
} else {
|
|
1007
|
+
this._publicKey = null;
|
|
1008
|
+
this.eventEmitter.emit("accountChanged", null);
|
|
1009
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Emitted accountChanged event (null - invalid account)", {
|
|
1010
|
+
walletId: this.walletId,
|
|
1011
|
+
walletName: this.walletName
|
|
1012
|
+
});
|
|
1013
|
+
}
|
|
1014
|
+
} else {
|
|
1015
|
+
this._publicKey = null;
|
|
1016
|
+
this.eventEmitter.emit("accountChanged", null);
|
|
1017
|
+
this.eventEmitter.emit("disconnect");
|
|
1018
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Emitted accountChanged and disconnect events", {
|
|
1019
|
+
walletId: this.walletId,
|
|
1020
|
+
walletName: this.walletName
|
|
1021
|
+
});
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
});
|
|
929
1025
|
}
|
|
930
|
-
|
|
931
|
-
return
|
|
932
|
-
}
|
|
933
|
-
isConnected() {
|
|
934
|
-
return this._connected;
|
|
1026
|
+
extractAccountAddress(account) {
|
|
1027
|
+
return account.address;
|
|
935
1028
|
}
|
|
936
|
-
on(
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
1029
|
+
on(event, listener) {
|
|
1030
|
+
this.eventEmitter.on(event, listener);
|
|
1031
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Added event listener", {
|
|
1032
|
+
walletId: this.walletId,
|
|
1033
|
+
walletName: this.walletName,
|
|
1034
|
+
event
|
|
1035
|
+
});
|
|
941
1036
|
}
|
|
942
|
-
off(
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
1037
|
+
off(event, listener) {
|
|
1038
|
+
this.eventEmitter.off(event, listener);
|
|
1039
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Removed event listener", {
|
|
1040
|
+
walletId: this.walletId,
|
|
1041
|
+
walletName: this.walletName,
|
|
1042
|
+
event
|
|
1043
|
+
});
|
|
947
1044
|
}
|
|
948
1045
|
/**
|
|
949
1046
|
* Serialize a transaction to Uint8Array for Wallet Standard API
|
|
@@ -987,10 +1084,11 @@ var WalletStandardSolanaAdapter = class {
|
|
|
987
1084
|
};
|
|
988
1085
|
|
|
989
1086
|
// src/providers/injected/chains/InjectedWalletEthereumChain.ts
|
|
990
|
-
import { EventEmitter as
|
|
1087
|
+
import { EventEmitter as EventEmitter3 } from "eventemitter3";
|
|
991
1088
|
var InjectedWalletEthereumChain = class {
|
|
992
1089
|
constructor(provider, walletId, walletName) {
|
|
993
|
-
|
|
1090
|
+
// Expose eventEmitter for testing - allows tests to trigger events directly
|
|
1091
|
+
this.eventEmitter = new EventEmitter3();
|
|
994
1092
|
this._connected = false;
|
|
995
1093
|
this._chainId = "0x1";
|
|
996
1094
|
this._accounts = [];
|
|
@@ -999,9 +1097,6 @@ var InjectedWalletEthereumChain = class {
|
|
|
999
1097
|
this.walletName = walletName;
|
|
1000
1098
|
this.setupEventListeners();
|
|
1001
1099
|
}
|
|
1002
|
-
get connected() {
|
|
1003
|
-
return this._connected;
|
|
1004
|
-
}
|
|
1005
1100
|
get chainId() {
|
|
1006
1101
|
return this._chainId;
|
|
1007
1102
|
}
|
|
@@ -1131,7 +1226,8 @@ var InjectedWalletEthereumChain = class {
|
|
|
1131
1226
|
address
|
|
1132
1227
|
});
|
|
1133
1228
|
try {
|
|
1134
|
-
const
|
|
1229
|
+
const providerAny = this.provider;
|
|
1230
|
+
const providerConnected = (typeof providerAny.isConnected === "function" ? providerAny.isConnected() : false) || (typeof providerAny.connected === "boolean" ? providerAny.connected : false);
|
|
1135
1231
|
if (!this._connected || this._accounts.length === 0 || !providerConnected) {
|
|
1136
1232
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Not connected, attempting to connect before signing", {
|
|
1137
1233
|
walletId: this.walletId,
|
|
@@ -1364,6 +1460,7 @@ var InjectedWalletEthereumChain = class {
|
|
|
1364
1460
|
});
|
|
1365
1461
|
this.provider.on("accountsChanged", (accounts) => {
|
|
1366
1462
|
this._accounts = accounts;
|
|
1463
|
+
this._connected = accounts.length > 0;
|
|
1367
1464
|
this.eventEmitter.emit("accountsChanged", accounts);
|
|
1368
1465
|
});
|
|
1369
1466
|
this.provider.on("chainChanged", (chainId) => {
|
|
@@ -1380,218 +1477,13 @@ var InjectedWalletEthereumChain = class {
|
|
|
1380
1477
|
}
|
|
1381
1478
|
};
|
|
1382
1479
|
|
|
1383
|
-
// src/providers/injected/chains/SolanaChain.ts
|
|
1384
|
-
import { EventEmitter as EventEmitter3 } from "eventemitter3";
|
|
1385
|
-
import { Buffer as Buffer3 } from "buffer";
|
|
1386
|
-
var PhantomSolanaChain = class {
|
|
1387
|
-
constructor(phantom) {
|
|
1388
|
-
this._publicKey = null;
|
|
1389
|
-
this.eventEmitter = new EventEmitter3();
|
|
1390
|
-
this.phantom = phantom;
|
|
1391
|
-
this.setupEventListeners();
|
|
1392
|
-
}
|
|
1393
|
-
// Wallet adapter compliant properties
|
|
1394
|
-
get connected() {
|
|
1395
|
-
return this._publicKey !== null;
|
|
1396
|
-
}
|
|
1397
|
-
get publicKey() {
|
|
1398
|
-
return this._publicKey;
|
|
1399
|
-
}
|
|
1400
|
-
// Connection methods
|
|
1401
|
-
async connect(options) {
|
|
1402
|
-
const result = await this.phantom.solana.connect(options);
|
|
1403
|
-
if (!result) {
|
|
1404
|
-
throw new Error("Failed to connect to Solana wallet");
|
|
1405
|
-
}
|
|
1406
|
-
const publicKey = typeof result === "string" ? result : "";
|
|
1407
|
-
this._publicKey = publicKey;
|
|
1408
|
-
return { publicKey };
|
|
1409
|
-
}
|
|
1410
|
-
async disconnect() {
|
|
1411
|
-
await this.phantom.solana.disconnect();
|
|
1412
|
-
this._publicKey = null;
|
|
1413
|
-
}
|
|
1414
|
-
// Standard wallet adapter methods
|
|
1415
|
-
async signMessage(message) {
|
|
1416
|
-
const messageBytes = typeof message === "string" ? new TextEncoder().encode(message) : message;
|
|
1417
|
-
const result = await this.phantom.solana.signMessage(messageBytes);
|
|
1418
|
-
return {
|
|
1419
|
-
signature: result.signature instanceof Uint8Array ? result.signature : new Uint8Array(Buffer3.from(result.signature, "base64")),
|
|
1420
|
-
publicKey: this._publicKey || ""
|
|
1421
|
-
};
|
|
1422
|
-
}
|
|
1423
|
-
async signTransaction(transaction) {
|
|
1424
|
-
if (!this.connected) {
|
|
1425
|
-
return Promise.reject(new Error("Provider not connected. Call provider connect first."));
|
|
1426
|
-
}
|
|
1427
|
-
try {
|
|
1428
|
-
const result = await this.phantom.solana.signTransaction(transaction);
|
|
1429
|
-
return result;
|
|
1430
|
-
} catch (error) {
|
|
1431
|
-
return Promise.reject(error);
|
|
1432
|
-
}
|
|
1433
|
-
}
|
|
1434
|
-
async signAndSendTransaction(transaction) {
|
|
1435
|
-
const result = await this.phantom.solana.signAndSendTransaction(transaction);
|
|
1436
|
-
return { signature: result.signature };
|
|
1437
|
-
}
|
|
1438
|
-
async signAllTransactions(transactions) {
|
|
1439
|
-
if (!this.connected) {
|
|
1440
|
-
return Promise.reject(new Error("Provider not connected. Call provider connect first."));
|
|
1441
|
-
}
|
|
1442
|
-
try {
|
|
1443
|
-
const result = await this.phantom.solana.signAllTransactions(transactions);
|
|
1444
|
-
return result;
|
|
1445
|
-
} catch (error) {
|
|
1446
|
-
return Promise.reject(error);
|
|
1447
|
-
}
|
|
1448
|
-
}
|
|
1449
|
-
async signAndSendAllTransactions(transactions) {
|
|
1450
|
-
if (!this.connected) {
|
|
1451
|
-
return Promise.reject(new Error("Provider not connected. Call provider connect first."));
|
|
1452
|
-
}
|
|
1453
|
-
try {
|
|
1454
|
-
const result = await this.phantom.solana.signAndSendAllTransactions(transactions);
|
|
1455
|
-
return { signatures: result.signatures };
|
|
1456
|
-
} catch (error) {
|
|
1457
|
-
return Promise.reject(error);
|
|
1458
|
-
}
|
|
1459
|
-
}
|
|
1460
|
-
switchNetwork(_network) {
|
|
1461
|
-
return Promise.resolve();
|
|
1462
|
-
}
|
|
1463
|
-
// Legacy methods
|
|
1464
|
-
getPublicKey() {
|
|
1465
|
-
return Promise.resolve(this._publicKey);
|
|
1466
|
-
}
|
|
1467
|
-
isConnected() {
|
|
1468
|
-
return this.connected;
|
|
1469
|
-
}
|
|
1470
|
-
setupEventListeners() {
|
|
1471
|
-
this.phantom.solana.addEventListener("connect", (publicKey) => {
|
|
1472
|
-
this._publicKey = publicKey;
|
|
1473
|
-
this.eventEmitter.emit("connect", publicKey);
|
|
1474
|
-
});
|
|
1475
|
-
this.phantom.solana.addEventListener("disconnect", () => {
|
|
1476
|
-
this._publicKey = null;
|
|
1477
|
-
this.eventEmitter.emit("disconnect");
|
|
1478
|
-
});
|
|
1479
|
-
this.phantom.solana.addEventListener("accountChanged", (publicKey) => {
|
|
1480
|
-
this._publicKey = publicKey;
|
|
1481
|
-
this.eventEmitter.emit("accountChanged", publicKey);
|
|
1482
|
-
});
|
|
1483
|
-
}
|
|
1484
|
-
// Event methods for interface compliance
|
|
1485
|
-
on(event, listener) {
|
|
1486
|
-
this.eventEmitter.on(event, listener);
|
|
1487
|
-
}
|
|
1488
|
-
off(event, listener) {
|
|
1489
|
-
this.eventEmitter.off(event, listener);
|
|
1490
|
-
}
|
|
1491
|
-
};
|
|
1492
|
-
|
|
1493
|
-
// src/providers/injected/chains/EthereumChain.ts
|
|
1494
|
-
import { EventEmitter as EventEmitter4 } from "eventemitter3";
|
|
1495
|
-
var PhantomEthereumChain = class {
|
|
1496
|
-
constructor(phantom) {
|
|
1497
|
-
this._chainId = "0x1";
|
|
1498
|
-
this._accounts = [];
|
|
1499
|
-
this.eventEmitter = new EventEmitter4();
|
|
1500
|
-
this.phantom = phantom;
|
|
1501
|
-
this.setupEventListeners();
|
|
1502
|
-
}
|
|
1503
|
-
// EIP-1193 compliant properties
|
|
1504
|
-
get connected() {
|
|
1505
|
-
return this._accounts.length > 0;
|
|
1506
|
-
}
|
|
1507
|
-
get chainId() {
|
|
1508
|
-
return this._chainId;
|
|
1509
|
-
}
|
|
1510
|
-
get accounts() {
|
|
1511
|
-
return this._accounts;
|
|
1512
|
-
}
|
|
1513
|
-
// EIP-1193 core method with eth_signTransaction support
|
|
1514
|
-
async request(args) {
|
|
1515
|
-
if (args.method === "eth_signTransaction") {
|
|
1516
|
-
const [transaction] = args.params;
|
|
1517
|
-
const result = await this.signTransaction(transaction);
|
|
1518
|
-
return result;
|
|
1519
|
-
}
|
|
1520
|
-
const phantomProvider = await this.phantom.ethereum.getProvider();
|
|
1521
|
-
return await phantomProvider.request(args);
|
|
1522
|
-
}
|
|
1523
|
-
// Connection methods
|
|
1524
|
-
async connect() {
|
|
1525
|
-
const accounts = await this.phantom.ethereum.getAccounts();
|
|
1526
|
-
this._accounts = accounts;
|
|
1527
|
-
return accounts;
|
|
1528
|
-
}
|
|
1529
|
-
async disconnect() {
|
|
1530
|
-
await this.phantom.ethereum.disconnect();
|
|
1531
|
-
this._accounts = [];
|
|
1532
|
-
}
|
|
1533
|
-
// Standard compliant methods (return raw values, not wrapped objects)
|
|
1534
|
-
async signPersonalMessage(message, address) {
|
|
1535
|
-
return await this.phantom.ethereum.signPersonalMessage(message, address);
|
|
1536
|
-
}
|
|
1537
|
-
async signTypedData(typedData, address) {
|
|
1538
|
-
return await this.phantom.ethereum.signTypedData(typedData, address);
|
|
1539
|
-
}
|
|
1540
|
-
async signTransaction(transaction) {
|
|
1541
|
-
return await this.phantom.ethereum.signTransaction(transaction);
|
|
1542
|
-
}
|
|
1543
|
-
async sendTransaction(transaction) {
|
|
1544
|
-
return await this.phantom.ethereum.sendTransaction(transaction);
|
|
1545
|
-
}
|
|
1546
|
-
async switchChain(chainId) {
|
|
1547
|
-
const hexChainId = typeof chainId === "string" ? chainId.toLowerCase().startsWith("0x") ? chainId : `0x${parseInt(chainId, 10).toString(16)}` : `0x${chainId.toString(16)}`;
|
|
1548
|
-
await this.phantom.ethereum.switchChain(hexChainId);
|
|
1549
|
-
this._chainId = hexChainId;
|
|
1550
|
-
this.eventEmitter.emit("chainChanged", this._chainId);
|
|
1551
|
-
}
|
|
1552
|
-
async getChainId() {
|
|
1553
|
-
const chainId = await this.phantom.ethereum.getChainId();
|
|
1554
|
-
return parseInt(chainId, 16);
|
|
1555
|
-
}
|
|
1556
|
-
async getAccounts() {
|
|
1557
|
-
return await this.phantom.ethereum.getAccounts();
|
|
1558
|
-
}
|
|
1559
|
-
isConnected() {
|
|
1560
|
-
return this.connected;
|
|
1561
|
-
}
|
|
1562
|
-
setupEventListeners() {
|
|
1563
|
-
this.phantom.ethereum.addEventListener("connect", (accounts) => {
|
|
1564
|
-
this._accounts = accounts;
|
|
1565
|
-
this.eventEmitter.emit("connect", { chainId: this._chainId });
|
|
1566
|
-
this.eventEmitter.emit("accountsChanged", accounts);
|
|
1567
|
-
});
|
|
1568
|
-
this.phantom.ethereum.addEventListener("disconnect", () => {
|
|
1569
|
-
this._accounts = [];
|
|
1570
|
-
this.eventEmitter.emit("disconnect", { code: 4900, message: "Provider disconnected" });
|
|
1571
|
-
this.eventEmitter.emit("accountsChanged", []);
|
|
1572
|
-
});
|
|
1573
|
-
this.phantom.ethereum.addEventListener("accountsChanged", (accounts) => {
|
|
1574
|
-
this._accounts = accounts;
|
|
1575
|
-
this.eventEmitter.emit("accountsChanged", accounts);
|
|
1576
|
-
});
|
|
1577
|
-
this.phantom.ethereum.addEventListener("chainChanged", (chainId) => {
|
|
1578
|
-
this._chainId = chainId;
|
|
1579
|
-
this.eventEmitter.emit("chainChanged", chainId);
|
|
1580
|
-
});
|
|
1581
|
-
}
|
|
1582
|
-
// Event methods for interface compliance
|
|
1583
|
-
on(event, listener) {
|
|
1584
|
-
this.eventEmitter.on(event, listener);
|
|
1585
|
-
}
|
|
1586
|
-
off(event, listener) {
|
|
1587
|
-
this.eventEmitter.off(event, listener);
|
|
1588
|
-
}
|
|
1589
|
-
};
|
|
1590
|
-
|
|
1591
1480
|
// src/wallets/registry.ts
|
|
1592
1481
|
function isPhantomWallet(wallet) {
|
|
1593
1482
|
return wallet !== void 0 && wallet.id === "phantom" && "isPhantom" in wallet && wallet.isPhantom === true;
|
|
1594
1483
|
}
|
|
1484
|
+
function isWalletStandardWallet(provider) {
|
|
1485
|
+
return provider !== null && typeof provider === "object" && "features" in provider && typeof provider.features === "object";
|
|
1486
|
+
}
|
|
1595
1487
|
var InjectedWalletRegistry = class {
|
|
1596
1488
|
constructor() {
|
|
1597
1489
|
this.wallets = /* @__PURE__ */ new Map();
|
|
@@ -1600,8 +1492,7 @@ var InjectedWalletRegistry = class {
|
|
|
1600
1492
|
register(info) {
|
|
1601
1493
|
const wrappedProviders = {};
|
|
1602
1494
|
if (info.providers?.solana) {
|
|
1603
|
-
|
|
1604
|
-
if (isWalletStandard) {
|
|
1495
|
+
if (isWalletStandardWallet(info.providers.solana)) {
|
|
1605
1496
|
wrappedProviders.solana = new WalletStandardSolanaAdapter(info.providers.solana, info.id, info.name);
|
|
1606
1497
|
debug.log(DebugCategory.BROWSER_SDK, "Wrapped Wallet Standard Solana wallet with adapter", {
|
|
1607
1498
|
walletId: info.id,
|
|
@@ -1631,26 +1522,26 @@ var InjectedWalletRegistry = class {
|
|
|
1631
1522
|
/**
|
|
1632
1523
|
* Register Phantom wallet with its instance
|
|
1633
1524
|
* This creates wrapped providers and stores the Phantom instance for auto-confirm access
|
|
1525
|
+
* Uses unified InjectedWallet chains for both Phantom and external wallets
|
|
1634
1526
|
*/
|
|
1635
1527
|
registerPhantom(phantomInstance, addressTypes) {
|
|
1636
1528
|
const wrappedProviders = {};
|
|
1637
1529
|
if (addressTypes.includes(AddressType.solana) && phantomInstance.solana) {
|
|
1638
|
-
wrappedProviders.solana = new
|
|
1639
|
-
debug.log(DebugCategory.BROWSER_SDK, "Created
|
|
1530
|
+
wrappedProviders.solana = new InjectedWalletSolanaChain(phantomInstance.solana, "phantom", "Phantom");
|
|
1531
|
+
debug.log(DebugCategory.BROWSER_SDK, "Created InjectedWalletSolanaChain wrapper for Phantom", {
|
|
1640
1532
|
walletId: "phantom"
|
|
1641
1533
|
});
|
|
1642
1534
|
}
|
|
1643
1535
|
if (addressTypes.includes(AddressType.ethereum) && phantomInstance.ethereum) {
|
|
1644
|
-
wrappedProviders.ethereum = new
|
|
1645
|
-
debug.log(DebugCategory.BROWSER_SDK, "Created
|
|
1536
|
+
wrappedProviders.ethereum = new InjectedWalletEthereumChain(phantomInstance.ethereum, "phantom", "Phantom");
|
|
1537
|
+
debug.log(DebugCategory.BROWSER_SDK, "Created InjectedWalletEthereumChain wrapper for Phantom", {
|
|
1646
1538
|
walletId: "phantom"
|
|
1647
1539
|
});
|
|
1648
1540
|
}
|
|
1649
1541
|
const phantomWallet = {
|
|
1650
1542
|
id: "phantom",
|
|
1651
1543
|
name: "Phantom",
|
|
1652
|
-
icon:
|
|
1653
|
-
// Icon will be rendered from icons package in UI components
|
|
1544
|
+
icon: PHANTOM_ICON2,
|
|
1654
1545
|
addressTypes,
|
|
1655
1546
|
providers: wrappedProviders,
|
|
1656
1547
|
isPhantom: true,
|
|
@@ -1727,15 +1618,16 @@ var WAS_CONNECTED_KEY = "phantom-injected-was-connected";
|
|
|
1727
1618
|
var WAS_CONNECTED_VALUE = "true";
|
|
1728
1619
|
var LAST_WALLET_ID_KEY = "phantom-injected-last-wallet-id";
|
|
1729
1620
|
var InjectedProvider = class {
|
|
1730
|
-
//
|
|
1621
|
+
// Store cleanups per walletId
|
|
1731
1622
|
constructor(config) {
|
|
1732
1623
|
this.selectedWalletId = null;
|
|
1733
1624
|
this.walletStates = /* @__PURE__ */ new Map();
|
|
1734
1625
|
// Event management
|
|
1735
1626
|
this.eventListeners = /* @__PURE__ */ new Map();
|
|
1736
|
-
this.browserInjectedCleanupFunctions = [];
|
|
1737
1627
|
this.eventsInitialized = false;
|
|
1738
|
-
this.
|
|
1628
|
+
this.eventListenersSetup = /* @__PURE__ */ new Set();
|
|
1629
|
+
// Track walletId that have listeners set up
|
|
1630
|
+
this.eventListenerCleanups = /* @__PURE__ */ new Map();
|
|
1739
1631
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Initializing InjectedProvider", { config });
|
|
1740
1632
|
this.addressTypes = config.addressTypes;
|
|
1741
1633
|
this.walletRegistry = getWalletRegistry();
|
|
@@ -1766,9 +1658,12 @@ var InjectedProvider = class {
|
|
|
1766
1658
|
});
|
|
1767
1659
|
}
|
|
1768
1660
|
}
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1661
|
+
/**
|
|
1662
|
+
* Helper method to get a chain provider with consistent error handling
|
|
1663
|
+
*/
|
|
1664
|
+
getChainProvider(addressType, providerKey, chainName) {
|
|
1665
|
+
if (!this.addressTypes.includes(addressType)) {
|
|
1666
|
+
throw new Error(`${chainName} not enabled for this provider`);
|
|
1772
1667
|
}
|
|
1773
1668
|
const walletId = this.selectedWalletId || "phantom";
|
|
1774
1669
|
const walletInfo = this.walletRegistry.getById(walletId);
|
|
@@ -1783,46 +1678,29 @@ var InjectedProvider = class {
|
|
|
1783
1678
|
`Wallet "${walletId}" not found. Please ensure wallet discovery has completed. Make sure you call sdk.discoverWallets() and await it before accessing chain properties.`
|
|
1784
1679
|
);
|
|
1785
1680
|
}
|
|
1786
|
-
|
|
1681
|
+
const provider = walletInfo.providers?.[providerKey];
|
|
1682
|
+
if (!provider) {
|
|
1787
1683
|
throw new Error(
|
|
1788
|
-
`Selected wallet "${walletInfo.name}" does not support
|
|
1684
|
+
`Selected wallet "${walletInfo.name}" does not support ${chainName}. This wallet only supports: ${walletInfo.addressTypes.join(", ")}. Make sure your SDK config includes ${chainName} in addressTypes.`
|
|
1789
1685
|
);
|
|
1790
1686
|
}
|
|
1791
|
-
return
|
|
1687
|
+
return provider;
|
|
1688
|
+
}
|
|
1689
|
+
get solana() {
|
|
1690
|
+
return this.getChainProvider(AddressType3.solana, "solana", "Solana");
|
|
1792
1691
|
}
|
|
1793
1692
|
/**
|
|
1794
1693
|
* Access to Ethereum chain operations
|
|
1795
1694
|
*/
|
|
1796
1695
|
get ethereum() {
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
throw new Error(
|
|
1806
|
-
`Wallet "${walletId}" not found. Wallet discovery is still in progress. Please wait for sdk.discoverWallets() to complete before accessing chain properties.`
|
|
1807
|
-
);
|
|
1808
|
-
}
|
|
1809
|
-
throw new Error(
|
|
1810
|
-
`Wallet "${walletId}" not found. Please ensure wallet discovery has completed. Make sure you call sdk.discoverWallets() and await it before accessing chain properties.`
|
|
1811
|
-
);
|
|
1812
|
-
}
|
|
1813
|
-
if (!walletInfo.providers?.ethereum) {
|
|
1814
|
-
throw new Error(
|
|
1815
|
-
`Selected wallet "${walletInfo.name}" does not support Ethereum. This wallet only supports: ${walletInfo.addressTypes.join(", ")}. Make sure your SDK config includes Ethereum in addressTypes.`
|
|
1816
|
-
);
|
|
1817
|
-
}
|
|
1818
|
-
return walletInfo.providers.ethereum;
|
|
1819
|
-
}
|
|
1820
|
-
validateAndSelectWallet(requestedWalletId) {
|
|
1821
|
-
if (!this.walletRegistry.has(requestedWalletId)) {
|
|
1822
|
-
debug.error(DebugCategory.INJECTED_PROVIDER, "Unknown injected wallet id requested", {
|
|
1823
|
-
walletId: requestedWalletId
|
|
1824
|
-
});
|
|
1825
|
-
throw new Error(`Unknown injected wallet id: ${requestedWalletId}`);
|
|
1696
|
+
return this.getChainProvider(AddressType3.ethereum, "ethereum", "Ethereum");
|
|
1697
|
+
}
|
|
1698
|
+
validateAndSelectWallet(requestedWalletId) {
|
|
1699
|
+
if (!this.walletRegistry.has(requestedWalletId)) {
|
|
1700
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "Unknown injected wallet id requested", {
|
|
1701
|
+
walletId: requestedWalletId
|
|
1702
|
+
});
|
|
1703
|
+
throw new Error(`Unknown injected wallet id: ${requestedWalletId}`);
|
|
1826
1704
|
}
|
|
1827
1705
|
const walletInfo = this.walletRegistry.getById(requestedWalletId);
|
|
1828
1706
|
if (!walletInfo || !walletInfo.providers) {
|
|
@@ -1853,16 +1731,10 @@ var InjectedProvider = class {
|
|
|
1853
1731
|
options
|
|
1854
1732
|
});
|
|
1855
1733
|
if (!options?.skipEventListeners) {
|
|
1856
|
-
this.
|
|
1857
|
-
if (this.selectedWalletId === "phantom" && isPhantomWallet(walletInfo)) {
|
|
1858
|
-
this.browserInjectedCleanupFunctions.forEach((cleanup) => cleanup());
|
|
1859
|
-
this.browserInjectedCleanupFunctions = [];
|
|
1860
|
-
this.setupBrowserInjectedEvents();
|
|
1861
|
-
this.eventsInitialized = true;
|
|
1862
|
-
}
|
|
1734
|
+
this.setupEventListeners(walletInfo);
|
|
1863
1735
|
}
|
|
1864
1736
|
const connectedAddresses = [];
|
|
1865
|
-
if (this.addressTypes.includes(
|
|
1737
|
+
if (this.addressTypes.includes(AddressType3.solana) && walletInfo.providers?.solana) {
|
|
1866
1738
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting Solana connection", {
|
|
1867
1739
|
walletId: this.selectedWalletId,
|
|
1868
1740
|
walletName: walletInfo.name,
|
|
@@ -1874,7 +1746,7 @@ var InjectedProvider = class {
|
|
|
1874
1746
|
);
|
|
1875
1747
|
const address = result.publicKey;
|
|
1876
1748
|
connectedAddresses.push({
|
|
1877
|
-
addressType:
|
|
1749
|
+
addressType: AddressType3.solana,
|
|
1878
1750
|
address
|
|
1879
1751
|
});
|
|
1880
1752
|
debug.info(DebugCategory.INJECTED_PROVIDER, "Solana connected successfully", {
|
|
@@ -1895,7 +1767,7 @@ var InjectedProvider = class {
|
|
|
1895
1767
|
throw err;
|
|
1896
1768
|
}
|
|
1897
1769
|
}
|
|
1898
|
-
if (this.addressTypes.includes(
|
|
1770
|
+
if (this.addressTypes.includes(AddressType3.ethereum) && walletInfo.providers?.ethereum) {
|
|
1899
1771
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting Ethereum connection", {
|
|
1900
1772
|
walletId: this.selectedWalletId,
|
|
1901
1773
|
walletName: walletInfo.name,
|
|
@@ -1911,7 +1783,7 @@ var InjectedProvider = class {
|
|
|
1911
1783
|
if (accounts.length > 0) {
|
|
1912
1784
|
connectedAddresses.push(
|
|
1913
1785
|
...accounts.map((address) => ({
|
|
1914
|
-
addressType:
|
|
1786
|
+
addressType: AddressType3.ethereum,
|
|
1915
1787
|
address
|
|
1916
1788
|
}))
|
|
1917
1789
|
);
|
|
@@ -1991,7 +1863,8 @@ var InjectedProvider = class {
|
|
|
1991
1863
|
this.emit("connect", {
|
|
1992
1864
|
addresses: connectedAddresses,
|
|
1993
1865
|
source: "manual-connect",
|
|
1994
|
-
authUserId
|
|
1866
|
+
authUserId,
|
|
1867
|
+
walletId
|
|
1995
1868
|
});
|
|
1996
1869
|
return result;
|
|
1997
1870
|
}
|
|
@@ -2003,12 +1876,13 @@ var InjectedProvider = class {
|
|
|
2003
1876
|
if (authOptions.provider !== "injected") {
|
|
2004
1877
|
throw new Error(`Invalid provider for injected connection: ${authOptions.provider}. Must be "injected"`);
|
|
2005
1878
|
}
|
|
1879
|
+
const requestedWalletId = authOptions.walletId || "phantom";
|
|
2006
1880
|
this.emit("connect_start", {
|
|
2007
1881
|
source: "manual-connect",
|
|
2008
|
-
providerType: "injected"
|
|
1882
|
+
providerType: "injected",
|
|
1883
|
+
walletId: requestedWalletId
|
|
2009
1884
|
});
|
|
2010
1885
|
try {
|
|
2011
|
-
const requestedWalletId = authOptions.walletId || "phantom";
|
|
2012
1886
|
const walletInfo = this.validateAndSelectWallet(requestedWalletId);
|
|
2013
1887
|
const connectedAddresses = await this.connectToWallet(walletInfo);
|
|
2014
1888
|
return await this.finalizeConnection(connectedAddresses, "injected", this.selectedWalletId || void 0);
|
|
@@ -2024,7 +1898,7 @@ var InjectedProvider = class {
|
|
|
2024
1898
|
debug.info(DebugCategory.INJECTED_PROVIDER, "Starting injected provider disconnect");
|
|
2025
1899
|
const walletInfo = this.walletRegistry.getById(this.selectedWalletId || "phantom");
|
|
2026
1900
|
if (walletInfo?.providers) {
|
|
2027
|
-
if (this.addressTypes.includes(
|
|
1901
|
+
if (this.addressTypes.includes(AddressType3.solana) && walletInfo.providers.solana) {
|
|
2028
1902
|
try {
|
|
2029
1903
|
await walletInfo.providers.solana.disconnect();
|
|
2030
1904
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana disconnected successfully");
|
|
@@ -2032,7 +1906,7 @@ var InjectedProvider = class {
|
|
|
2032
1906
|
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to disconnect Solana", { error: err });
|
|
2033
1907
|
}
|
|
2034
1908
|
}
|
|
2035
|
-
if (this.addressTypes.includes(
|
|
1909
|
+
if (this.addressTypes.includes(AddressType3.ethereum) && walletInfo.providers.ethereum) {
|
|
2036
1910
|
try {
|
|
2037
1911
|
await walletInfo.providers.ethereum.disconnect();
|
|
2038
1912
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum disconnected successfully");
|
|
@@ -2041,10 +1915,14 @@ var InjectedProvider = class {
|
|
|
2041
1915
|
}
|
|
2042
1916
|
}
|
|
2043
1917
|
}
|
|
2044
|
-
this.
|
|
2045
|
-
|
|
1918
|
+
const walletId = this.selectedWalletId || "phantom";
|
|
1919
|
+
const cleanups = this.eventListenerCleanups.get(walletId);
|
|
1920
|
+
if (cleanups) {
|
|
1921
|
+
cleanups.forEach((cleanup) => cleanup());
|
|
1922
|
+
this.eventListenerCleanups.delete(walletId);
|
|
1923
|
+
}
|
|
1924
|
+
this.eventListenersSetup.delete(walletId);
|
|
2046
1925
|
if (this.selectedWalletId) {
|
|
2047
|
-
this.externalWalletEventListenersSetup.delete(this.selectedWalletId);
|
|
2048
1926
|
this.setWalletState(this.selectedWalletId, {
|
|
2049
1927
|
connected: false,
|
|
2050
1928
|
addresses: []
|
|
@@ -2113,13 +1991,7 @@ var InjectedProvider = class {
|
|
|
2113
1991
|
});
|
|
2114
1992
|
return;
|
|
2115
1993
|
}
|
|
2116
|
-
this.
|
|
2117
|
-
if (this.selectedWalletId === "phantom" && isPhantomWallet(walletInfo)) {
|
|
2118
|
-
this.browserInjectedCleanupFunctions.forEach((cleanup) => cleanup());
|
|
2119
|
-
this.browserInjectedCleanupFunctions = [];
|
|
2120
|
-
this.setupBrowserInjectedEvents();
|
|
2121
|
-
this.eventsInitialized = true;
|
|
2122
|
-
}
|
|
1994
|
+
this.setupEventListeners(walletInfo);
|
|
2123
1995
|
if (this.selectedWalletId) {
|
|
2124
1996
|
this.setWalletState(this.selectedWalletId, {
|
|
2125
1997
|
connected: true,
|
|
@@ -2130,7 +2002,8 @@ var InjectedProvider = class {
|
|
|
2130
2002
|
this.emit("connect", {
|
|
2131
2003
|
addresses: connectedAddresses,
|
|
2132
2004
|
source: "auto-connect",
|
|
2133
|
-
authUserId
|
|
2005
|
+
authUserId,
|
|
2006
|
+
walletId: this.selectedWalletId
|
|
2134
2007
|
});
|
|
2135
2008
|
debug.info(DebugCategory.INJECTED_PROVIDER, "Auto-connect successful", {
|
|
2136
2009
|
addressCount: connectedAddresses.length,
|
|
@@ -2160,6 +2033,170 @@ var InjectedProvider = class {
|
|
|
2160
2033
|
setWalletState(walletId, state) {
|
|
2161
2034
|
this.walletStates.set(walletId, state);
|
|
2162
2035
|
}
|
|
2036
|
+
/**
|
|
2037
|
+
* Update wallet state with new addresses for a specific address type
|
|
2038
|
+
* Replaces all existing addresses of the given type with the new addresses
|
|
2039
|
+
* @param walletId - The wallet ID to update
|
|
2040
|
+
* @param newAddresses - Array of new addresses (strings) for the address type
|
|
2041
|
+
* @param addressType - The type of addresses being updated
|
|
2042
|
+
* @returns The updated addresses array
|
|
2043
|
+
*/
|
|
2044
|
+
updateWalletAddresses(walletId, newAddresses, addressType) {
|
|
2045
|
+
const state = this.getWalletState(walletId);
|
|
2046
|
+
const otherAddresses = state.addresses.filter((addr) => addr.addressType !== addressType);
|
|
2047
|
+
const addressesOfType = newAddresses.map((address) => ({ addressType, address }));
|
|
2048
|
+
const updatedAddresses = [...otherAddresses, ...addressesOfType];
|
|
2049
|
+
this.setWalletState(walletId, {
|
|
2050
|
+
connected: updatedAddresses.length > 0,
|
|
2051
|
+
addresses: updatedAddresses
|
|
2052
|
+
});
|
|
2053
|
+
return updatedAddresses;
|
|
2054
|
+
}
|
|
2055
|
+
/**
|
|
2056
|
+
* Helper to construct account change source string
|
|
2057
|
+
*/
|
|
2058
|
+
getAccountChangeSource(source) {
|
|
2059
|
+
return `${source}-account-change`;
|
|
2060
|
+
}
|
|
2061
|
+
/**
|
|
2062
|
+
* Create a handler for Solana connect events
|
|
2063
|
+
*/
|
|
2064
|
+
createSolanaConnectHandler(walletId, source) {
|
|
2065
|
+
return async (publicKey) => {
|
|
2066
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana connect event received", { publicKey, walletId });
|
|
2067
|
+
const newAddresses = this.updateWalletAddresses(walletId, [publicKey], AddressType3.solana);
|
|
2068
|
+
const authUserId = await this.getAuthUserId("Solana connect event");
|
|
2069
|
+
this.emit("connect", {
|
|
2070
|
+
addresses: newAddresses,
|
|
2071
|
+
source,
|
|
2072
|
+
authUserId,
|
|
2073
|
+
walletId: this.selectedWalletId
|
|
2074
|
+
});
|
|
2075
|
+
};
|
|
2076
|
+
}
|
|
2077
|
+
/**
|
|
2078
|
+
* Create a handler for Solana disconnect events
|
|
2079
|
+
*/
|
|
2080
|
+
createSolanaDisconnectHandler(walletId, source) {
|
|
2081
|
+
return () => {
|
|
2082
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana disconnect event received", { walletId });
|
|
2083
|
+
const state = this.getWalletState(walletId);
|
|
2084
|
+
const filteredAddresses = state.addresses.filter((addr) => addr.addressType !== AddressType3.solana);
|
|
2085
|
+
this.setWalletState(walletId, {
|
|
2086
|
+
connected: filteredAddresses.length > 0,
|
|
2087
|
+
addresses: filteredAddresses
|
|
2088
|
+
});
|
|
2089
|
+
this.emit("disconnect", {
|
|
2090
|
+
source
|
|
2091
|
+
});
|
|
2092
|
+
};
|
|
2093
|
+
}
|
|
2094
|
+
/**
|
|
2095
|
+
* Create a handler for Solana account change events
|
|
2096
|
+
* Can receive string | null per Wallet Standard
|
|
2097
|
+
*/
|
|
2098
|
+
createSolanaAccountChangeHandler(walletId, source) {
|
|
2099
|
+
return async (publicKey) => {
|
|
2100
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana account changed event received", { publicKey, walletId });
|
|
2101
|
+
if (publicKey) {
|
|
2102
|
+
const newAddresses = this.updateWalletAddresses(walletId, [publicKey], AddressType3.solana);
|
|
2103
|
+
const authUserId = await this.getAuthUserId("Solana account changed event");
|
|
2104
|
+
this.emit("connect", {
|
|
2105
|
+
addresses: newAddresses,
|
|
2106
|
+
source: this.getAccountChangeSource(source),
|
|
2107
|
+
authUserId,
|
|
2108
|
+
walletId: this.selectedWalletId
|
|
2109
|
+
});
|
|
2110
|
+
} else {
|
|
2111
|
+
const state = this.getWalletState(walletId);
|
|
2112
|
+
const otherAddresses = state.addresses.filter((addr) => addr.addressType !== AddressType3.solana);
|
|
2113
|
+
this.setWalletState(walletId, {
|
|
2114
|
+
connected: otherAddresses.length > 0,
|
|
2115
|
+
addresses: otherAddresses
|
|
2116
|
+
});
|
|
2117
|
+
this.emit("disconnect", {
|
|
2118
|
+
source: this.getAccountChangeSource(source)
|
|
2119
|
+
});
|
|
2120
|
+
}
|
|
2121
|
+
};
|
|
2122
|
+
}
|
|
2123
|
+
/**
|
|
2124
|
+
* Create a handler for Ethereum connect events
|
|
2125
|
+
* EIP-1193 connect event receives { chainId: string }, but we need to get accounts separately
|
|
2126
|
+
*/
|
|
2127
|
+
createEthereumConnectHandler(walletId, source) {
|
|
2128
|
+
return async (connectInfo) => {
|
|
2129
|
+
let accounts = [];
|
|
2130
|
+
if (Array.isArray(connectInfo)) {
|
|
2131
|
+
accounts = connectInfo;
|
|
2132
|
+
} else {
|
|
2133
|
+
try {
|
|
2134
|
+
const walletInfo = this.walletRegistry.getById(walletId);
|
|
2135
|
+
if (walletInfo?.providers?.ethereum) {
|
|
2136
|
+
accounts = await walletInfo.providers.ethereum.getAccounts();
|
|
2137
|
+
}
|
|
2138
|
+
} catch (error) {
|
|
2139
|
+
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to get accounts on connect", { error });
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2142
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum connect event received", { accounts, walletId });
|
|
2143
|
+
if (accounts.length > 0) {
|
|
2144
|
+
const newAddresses = this.updateWalletAddresses(walletId, accounts, AddressType3.ethereum);
|
|
2145
|
+
const authUserId = await this.getAuthUserId("Ethereum connect event");
|
|
2146
|
+
this.emit("connect", {
|
|
2147
|
+
addresses: newAddresses,
|
|
2148
|
+
source,
|
|
2149
|
+
authUserId,
|
|
2150
|
+
walletId: this.selectedWalletId
|
|
2151
|
+
});
|
|
2152
|
+
}
|
|
2153
|
+
};
|
|
2154
|
+
}
|
|
2155
|
+
/**
|
|
2156
|
+
* Create a handler for Ethereum disconnect events
|
|
2157
|
+
*/
|
|
2158
|
+
createEthereumDisconnectHandler(walletId, source) {
|
|
2159
|
+
return () => {
|
|
2160
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum disconnect event received", { walletId });
|
|
2161
|
+
const state = this.getWalletState(walletId);
|
|
2162
|
+
const filteredAddresses = state.addresses.filter((addr) => addr.addressType !== AddressType3.ethereum);
|
|
2163
|
+
this.setWalletState(walletId, {
|
|
2164
|
+
connected: filteredAddresses.length > 0,
|
|
2165
|
+
addresses: filteredAddresses
|
|
2166
|
+
});
|
|
2167
|
+
this.emit("disconnect", {
|
|
2168
|
+
source
|
|
2169
|
+
});
|
|
2170
|
+
};
|
|
2171
|
+
}
|
|
2172
|
+
/**
|
|
2173
|
+
* Create a handler for Ethereum account change events
|
|
2174
|
+
*/
|
|
2175
|
+
createEthereumAccountChangeHandler(walletId, source) {
|
|
2176
|
+
return async (accounts) => {
|
|
2177
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum accounts changed event received", { accounts, walletId });
|
|
2178
|
+
if (accounts && accounts.length > 0) {
|
|
2179
|
+
const newAddresses = this.updateWalletAddresses(walletId, accounts, AddressType3.ethereum);
|
|
2180
|
+
const authUserId = await this.getAuthUserId("Ethereum accounts changed event");
|
|
2181
|
+
this.emit("connect", {
|
|
2182
|
+
addresses: newAddresses,
|
|
2183
|
+
source: this.getAccountChangeSource(source),
|
|
2184
|
+
authUserId,
|
|
2185
|
+
walletId: this.selectedWalletId
|
|
2186
|
+
});
|
|
2187
|
+
} else {
|
|
2188
|
+
const state = this.getWalletState(walletId);
|
|
2189
|
+
const otherAddresses = state.addresses.filter((addr) => addr.addressType !== AddressType3.ethereum);
|
|
2190
|
+
this.setWalletState(walletId, {
|
|
2191
|
+
connected: otherAddresses.length > 0,
|
|
2192
|
+
addresses: otherAddresses
|
|
2193
|
+
});
|
|
2194
|
+
this.emit("disconnect", {
|
|
2195
|
+
source: this.getAccountChangeSource(source)
|
|
2196
|
+
});
|
|
2197
|
+
}
|
|
2198
|
+
};
|
|
2199
|
+
}
|
|
2163
2200
|
getAddresses() {
|
|
2164
2201
|
const walletId = this.selectedWalletId || "phantom";
|
|
2165
2202
|
return this.getWalletState(walletId).addresses;
|
|
@@ -2253,19 +2290,22 @@ var InjectedProvider = class {
|
|
|
2253
2290
|
on(event, callback) {
|
|
2254
2291
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Adding event listener", { event });
|
|
2255
2292
|
if (!this.eventsInitialized) {
|
|
2256
|
-
this.
|
|
2257
|
-
|
|
2293
|
+
const walletId = this.selectedWalletId || "phantom";
|
|
2294
|
+
const walletInfo = this.walletRegistry.getById(walletId);
|
|
2295
|
+
if (walletInfo) {
|
|
2296
|
+
this.setupEventListeners(walletInfo);
|
|
2297
|
+
}
|
|
2258
2298
|
}
|
|
2259
2299
|
if (!this.eventListeners.has(event)) {
|
|
2260
2300
|
this.eventListeners.set(event, /* @__PURE__ */ new Set());
|
|
2261
2301
|
}
|
|
2262
|
-
this.eventListeners.get(event)
|
|
2302
|
+
this.eventListeners.get(event)?.add(callback);
|
|
2263
2303
|
}
|
|
2264
2304
|
off(event, callback) {
|
|
2265
2305
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Removing event listener", { event });
|
|
2266
2306
|
if (this.eventListeners.has(event)) {
|
|
2267
|
-
this.eventListeners.get(event)
|
|
2268
|
-
if (this.eventListeners.get(event)
|
|
2307
|
+
this.eventListeners.get(event)?.delete(callback);
|
|
2308
|
+
if (this.eventListeners.get(event)?.size === 0) {
|
|
2269
2309
|
this.eventListeners.delete(event);
|
|
2270
2310
|
}
|
|
2271
2311
|
}
|
|
@@ -2287,246 +2327,89 @@ var InjectedProvider = class {
|
|
|
2287
2327
|
});
|
|
2288
2328
|
}
|
|
2289
2329
|
}
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2330
|
+
/**
|
|
2331
|
+
* Set up Solana event listeners for any provider (Phantom or external)
|
|
2332
|
+
*/
|
|
2333
|
+
setupSolanaEventListeners(provider, walletId, source) {
|
|
2334
|
+
if (typeof provider.on !== "function")
|
|
2294
2335
|
return;
|
|
2295
|
-
}
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
}
|
|
2301
|
-
if (this.addressTypes.includes(AddressType2.ethereum)) {
|
|
2302
|
-
this.setupEthereumEvents(walletInfo.phantomInstance);
|
|
2303
|
-
}
|
|
2304
|
-
}
|
|
2305
|
-
}
|
|
2306
|
-
setupSolanaEvents(phantom) {
|
|
2307
|
-
debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up Solana event listeners");
|
|
2308
|
-
const handleSolanaConnect = async (publicKey) => {
|
|
2309
|
-
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana connect event received", { publicKey });
|
|
2310
|
-
const walletId = this.selectedWalletId || "phantom";
|
|
2311
|
-
const state = this.getWalletState(walletId);
|
|
2312
|
-
const solanaAddress = { addressType: AddressType2.solana, address: publicKey };
|
|
2313
|
-
const hasSolana = state.addresses.some((addr) => addr.addressType === AddressType2.solana);
|
|
2314
|
-
const newAddresses = hasSolana ? state.addresses.map((addr) => addr.addressType === AddressType2.solana ? solanaAddress : addr) : [...state.addresses, solanaAddress];
|
|
2315
|
-
this.setWalletState(walletId, {
|
|
2316
|
-
connected: true,
|
|
2317
|
-
addresses: newAddresses
|
|
2318
|
-
});
|
|
2319
|
-
const authUserId = await this.getAuthUserId("Solana connect event");
|
|
2320
|
-
this.emit("connect", {
|
|
2321
|
-
addresses: newAddresses,
|
|
2322
|
-
source: "injected-extension",
|
|
2323
|
-
authUserId
|
|
2324
|
-
});
|
|
2325
|
-
};
|
|
2326
|
-
const handleSolanaDisconnect = () => {
|
|
2327
|
-
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana disconnect event received");
|
|
2328
|
-
const walletId = this.selectedWalletId || "phantom";
|
|
2329
|
-
const state = this.getWalletState(walletId);
|
|
2330
|
-
const filteredAddresses = state.addresses.filter((addr) => addr.addressType !== AddressType2.solana);
|
|
2331
|
-
this.setWalletState(walletId, {
|
|
2332
|
-
connected: filteredAddresses.length > 0,
|
|
2333
|
-
addresses: filteredAddresses
|
|
2334
|
-
});
|
|
2335
|
-
this.emit("disconnect", {
|
|
2336
|
-
source: "injected-extension"
|
|
2337
|
-
});
|
|
2336
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up Solana event listeners", { walletId, source });
|
|
2337
|
+
const handlers = {
|
|
2338
|
+
connect: this.createSolanaConnectHandler(walletId, source),
|
|
2339
|
+
disconnect: this.createSolanaDisconnectHandler(walletId, source),
|
|
2340
|
+
accountChanged: this.createSolanaAccountChangeHandler(walletId, source)
|
|
2338
2341
|
};
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
(
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
this.emit("connect", {
|
|
2353
|
-
addresses: newAddresses,
|
|
2354
|
-
source: "injected-extension-account-change",
|
|
2355
|
-
authUserId
|
|
2356
|
-
});
|
|
2357
|
-
};
|
|
2358
|
-
const cleanupConnect = phantom.solana.addEventListener("connect", handleSolanaConnect);
|
|
2359
|
-
const cleanupDisconnect = phantom.solana.addEventListener("disconnect", handleSolanaDisconnect);
|
|
2360
|
-
const cleanupAccountChanged = phantom.solana.addEventListener("accountChanged", handleSolanaAccountChanged);
|
|
2361
|
-
this.browserInjectedCleanupFunctions.push(cleanupConnect, cleanupDisconnect, cleanupAccountChanged);
|
|
2362
|
-
}
|
|
2363
|
-
setupEthereumEvents(phantom) {
|
|
2364
|
-
debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up Ethereum event listeners");
|
|
2365
|
-
const handleEthereumConnect = async (accounts) => {
|
|
2366
|
-
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum connect event received", { accounts });
|
|
2367
|
-
const walletId = this.selectedWalletId || "phantom";
|
|
2368
|
-
const state = this.getWalletState(walletId);
|
|
2369
|
-
const ethAddresses = accounts.map((address) => ({ addressType: AddressType2.ethereum, address }));
|
|
2370
|
-
const otherAddresses = state.addresses.filter((addr) => addr.addressType !== AddressType2.ethereum);
|
|
2371
|
-
const newAddresses = [...otherAddresses, ...ethAddresses];
|
|
2372
|
-
this.setWalletState(walletId, {
|
|
2373
|
-
connected: true,
|
|
2374
|
-
addresses: newAddresses
|
|
2375
|
-
});
|
|
2376
|
-
const authUserId = await this.getAuthUserId("Ethereum connect event");
|
|
2377
|
-
this.emit("connect", {
|
|
2378
|
-
addresses: newAddresses,
|
|
2379
|
-
source: "injected-extension",
|
|
2380
|
-
authUserId
|
|
2381
|
-
});
|
|
2382
|
-
};
|
|
2383
|
-
const handleEthereumDisconnect = () => {
|
|
2384
|
-
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum disconnect event received");
|
|
2385
|
-
const walletId = this.selectedWalletId || "phantom";
|
|
2386
|
-
const state = this.getWalletState(walletId);
|
|
2387
|
-
const filteredAddresses = state.addresses.filter((addr) => addr.addressType !== AddressType2.ethereum);
|
|
2388
|
-
this.setWalletState(walletId, {
|
|
2389
|
-
connected: filteredAddresses.length > 0,
|
|
2390
|
-
addresses: filteredAddresses
|
|
2391
|
-
});
|
|
2392
|
-
this.emit("disconnect", {
|
|
2393
|
-
source: "injected-extension"
|
|
2394
|
-
});
|
|
2395
|
-
};
|
|
2396
|
-
const handleEthereumAccountsChanged = async (accounts) => {
|
|
2397
|
-
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum accounts changed event received", { accounts });
|
|
2398
|
-
const walletId = this.selectedWalletId || "phantom";
|
|
2399
|
-
const state = this.getWalletState(walletId);
|
|
2400
|
-
const otherAddresses = state.addresses.filter((addr) => addr.addressType !== AddressType2.ethereum);
|
|
2401
|
-
if (accounts && accounts.length > 0) {
|
|
2402
|
-
const ethAddresses = accounts.map((address) => ({ addressType: AddressType2.ethereum, address }));
|
|
2403
|
-
const newAddresses = [...otherAddresses, ...ethAddresses];
|
|
2404
|
-
this.setWalletState(walletId, {
|
|
2405
|
-
connected: true,
|
|
2406
|
-
addresses: newAddresses
|
|
2407
|
-
});
|
|
2408
|
-
const authUserId = await this.getAuthUserId("Ethereum accounts changed event");
|
|
2409
|
-
this.emit("connect", {
|
|
2410
|
-
addresses: newAddresses,
|
|
2411
|
-
source: "injected-extension-account-change",
|
|
2412
|
-
authUserId
|
|
2413
|
-
});
|
|
2414
|
-
} else {
|
|
2415
|
-
this.setWalletState(walletId, {
|
|
2416
|
-
connected: otherAddresses.length > 0,
|
|
2417
|
-
addresses: otherAddresses
|
|
2418
|
-
});
|
|
2419
|
-
this.emit("disconnect", {
|
|
2420
|
-
source: "injected-extension-account-change"
|
|
2421
|
-
});
|
|
2422
|
-
}
|
|
2423
|
-
};
|
|
2424
|
-
const cleanupConnect = phantom.ethereum.addEventListener("connect", handleEthereumConnect);
|
|
2425
|
-
const cleanupDisconnect = phantom.ethereum.addEventListener("disconnect", handleEthereumDisconnect);
|
|
2426
|
-
const cleanupAccountsChanged = phantom.ethereum.addEventListener("accountsChanged", handleEthereumAccountsChanged);
|
|
2427
|
-
this.browserInjectedCleanupFunctions.push(cleanupConnect, cleanupDisconnect, cleanupAccountsChanged);
|
|
2342
|
+
provider.on("connect", handlers.connect);
|
|
2343
|
+
provider.on("disconnect", handlers.disconnect);
|
|
2344
|
+
provider.on("accountChanged", handlers.accountChanged);
|
|
2345
|
+
const cleanups = [];
|
|
2346
|
+
if (typeof provider.off === "function") {
|
|
2347
|
+
cleanups.push(
|
|
2348
|
+
() => provider.off("connect", handlers.connect),
|
|
2349
|
+
() => provider.off("disconnect", handlers.disconnect),
|
|
2350
|
+
() => provider.off("accountChanged", handlers.accountChanged)
|
|
2351
|
+
);
|
|
2352
|
+
}
|
|
2353
|
+
const existingCleanups = this.eventListenerCleanups.get(walletId) || [];
|
|
2354
|
+
this.eventListenerCleanups.set(walletId, [...existingCleanups, ...cleanups]);
|
|
2428
2355
|
}
|
|
2429
|
-
|
|
2430
|
-
|
|
2356
|
+
/**
|
|
2357
|
+
* Set up Ethereum event listeners for any provider (Phantom or external)
|
|
2358
|
+
*/
|
|
2359
|
+
setupEthereumEventListeners(provider, walletId, source) {
|
|
2360
|
+
if (typeof provider.on !== "function")
|
|
2431
2361
|
return;
|
|
2362
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up Ethereum event listeners", { walletId, source });
|
|
2363
|
+
const handlers = {
|
|
2364
|
+
connect: this.createEthereumConnectHandler(walletId, source),
|
|
2365
|
+
disconnect: this.createEthereumDisconnectHandler(walletId, source),
|
|
2366
|
+
accountsChanged: this.createEthereumAccountChangeHandler(walletId, source)
|
|
2367
|
+
};
|
|
2368
|
+
provider.on("connect", handlers.connect);
|
|
2369
|
+
provider.on("disconnect", handlers.disconnect);
|
|
2370
|
+
provider.on("accountsChanged", handlers.accountsChanged);
|
|
2371
|
+
const cleanups = [];
|
|
2372
|
+
if (typeof provider.off === "function") {
|
|
2373
|
+
cleanups.push(
|
|
2374
|
+
() => provider.off("connect", handlers.connect),
|
|
2375
|
+
() => provider.off("disconnect", handlers.disconnect),
|
|
2376
|
+
() => provider.off("accountsChanged", handlers.accountsChanged)
|
|
2377
|
+
);
|
|
2432
2378
|
}
|
|
2433
|
-
|
|
2379
|
+
const existingCleanups = this.eventListenerCleanups.get(walletId) || [];
|
|
2380
|
+
this.eventListenerCleanups.set(walletId, [...existingCleanups, ...cleanups]);
|
|
2381
|
+
}
|
|
2382
|
+
/**
|
|
2383
|
+
* Unified event listener setup for all wallet types (Phantom and external).
|
|
2384
|
+
* Cleans up listeners for previously selected wallets to prevent stale events
|
|
2385
|
+
* from causing walletId flicker during connections.
|
|
2386
|
+
*/
|
|
2387
|
+
setupEventListeners(walletInfo) {
|
|
2388
|
+
const walletId = this.selectedWalletId || "phantom";
|
|
2389
|
+
if (this.eventListenersSetup.has(walletId)) {
|
|
2390
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Event listeners already set up for wallet", { walletId });
|
|
2434
2391
|
return;
|
|
2435
2392
|
}
|
|
2436
|
-
|
|
2437
|
-
walletId
|
|
2438
|
-
|
|
2439
|
-
if (walletInfo.providers?.ethereum) {
|
|
2440
|
-
const handleExternalEthereumAccountsChanged = async (accounts) => {
|
|
2441
|
-
debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum accounts changed event received", {
|
|
2442
|
-
walletId: this.selectedWalletId,
|
|
2443
|
-
accounts
|
|
2444
|
-
});
|
|
2445
|
-
const walletId = this.selectedWalletId;
|
|
2446
|
-
const state = this.getWalletState(walletId);
|
|
2447
|
-
const otherAddresses = state.addresses.filter((addr) => addr.addressType !== AddressType2.ethereum);
|
|
2448
|
-
if (accounts && accounts.length > 0) {
|
|
2449
|
-
const ethAddresses = accounts.map((address) => ({ addressType: AddressType2.ethereum, address }));
|
|
2450
|
-
const newAddresses = [...otherAddresses, ...ethAddresses];
|
|
2451
|
-
this.setWalletState(walletId, {
|
|
2452
|
-
connected: true,
|
|
2453
|
-
addresses: newAddresses
|
|
2454
|
-
});
|
|
2455
|
-
debug.log(DebugCategory.INJECTED_PROVIDER, "Updated Ethereum addresses after account change", {
|
|
2456
|
-
walletId,
|
|
2457
|
-
oldCount: 0,
|
|
2458
|
-
// We filtered them out
|
|
2459
|
-
newCount: accounts.length,
|
|
2460
|
-
addresses: newAddresses.filter((addr) => addr.addressType === AddressType2.ethereum)
|
|
2461
|
-
});
|
|
2462
|
-
const authUserId = await this.getAuthUserId("External wallet Ethereum accounts changed event");
|
|
2463
|
-
this.emit("connect", {
|
|
2464
|
-
addresses: newAddresses,
|
|
2465
|
-
source: "external-wallet-account-change",
|
|
2466
|
-
authUserId
|
|
2467
|
-
});
|
|
2468
|
-
} else {
|
|
2469
|
-
this.setWalletState(walletId, {
|
|
2470
|
-
connected: otherAddresses.length > 0,
|
|
2471
|
-
addresses: otherAddresses
|
|
2472
|
-
});
|
|
2473
|
-
this.emit("disconnect", {
|
|
2474
|
-
source: "external-wallet-account-change"
|
|
2475
|
-
});
|
|
2476
|
-
}
|
|
2477
|
-
};
|
|
2478
|
-
if (typeof walletInfo.providers.ethereum.on === "function") {
|
|
2479
|
-
walletInfo.providers.ethereum.on("accountsChanged", handleExternalEthereumAccountsChanged);
|
|
2480
|
-
this.browserInjectedCleanupFunctions.push(() => {
|
|
2481
|
-
if (typeof walletInfo.providers?.ethereum?.off === "function") {
|
|
2482
|
-
walletInfo.providers.ethereum.off("accountsChanged", handleExternalEthereumAccountsChanged);
|
|
2483
|
-
}
|
|
2484
|
-
});
|
|
2393
|
+
for (const existingWalletId of this.eventListenersSetup) {
|
|
2394
|
+
if (existingWalletId === walletId) {
|
|
2395
|
+
continue;
|
|
2485
2396
|
}
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
walletId: this.selectedWalletId,
|
|
2491
|
-
publicKey
|
|
2492
|
-
});
|
|
2493
|
-
const walletId = this.selectedWalletId;
|
|
2494
|
-
const state = this.getWalletState(walletId);
|
|
2495
|
-
const otherAddresses = state.addresses.filter((addr) => addr.addressType !== AddressType2.solana);
|
|
2496
|
-
if (publicKey) {
|
|
2497
|
-
const newAddresses = [...otherAddresses, { addressType: AddressType2.solana, address: publicKey }];
|
|
2498
|
-
this.setWalletState(walletId, {
|
|
2499
|
-
connected: true,
|
|
2500
|
-
addresses: newAddresses
|
|
2501
|
-
});
|
|
2502
|
-
const authUserId = await this.getAuthUserId("External wallet Solana account changed event");
|
|
2503
|
-
this.emit("connect", {
|
|
2504
|
-
addresses: newAddresses,
|
|
2505
|
-
source: "external-wallet-account-change",
|
|
2506
|
-
authUserId
|
|
2507
|
-
});
|
|
2508
|
-
} else {
|
|
2509
|
-
this.setWalletState(walletId, {
|
|
2510
|
-
connected: otherAddresses.length > 0,
|
|
2511
|
-
addresses: otherAddresses
|
|
2512
|
-
});
|
|
2513
|
-
this.emit("disconnect", {
|
|
2514
|
-
source: "external-wallet-account-change"
|
|
2515
|
-
});
|
|
2516
|
-
}
|
|
2517
|
-
};
|
|
2518
|
-
if (typeof walletInfo.providers.solana.on === "function") {
|
|
2519
|
-
walletInfo.providers.solana.on("accountChanged", handleExternalSolanaAccountChanged);
|
|
2520
|
-
this.browserInjectedCleanupFunctions.push(() => {
|
|
2521
|
-
if (typeof walletInfo.providers?.solana?.off === "function") {
|
|
2522
|
-
walletInfo.providers.solana.off("accountChanged", handleExternalSolanaAccountChanged);
|
|
2523
|
-
}
|
|
2524
|
-
});
|
|
2397
|
+
const cleanups = this.eventListenerCleanups.get(existingWalletId);
|
|
2398
|
+
if (cleanups) {
|
|
2399
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Cleaning up event listeners for wallet", { existingWalletId });
|
|
2400
|
+
cleanups.forEach((cleanup) => cleanup());
|
|
2525
2401
|
}
|
|
2402
|
+
this.eventListenersSetup.delete(existingWalletId);
|
|
2526
2403
|
}
|
|
2527
|
-
|
|
2528
|
-
|
|
2404
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up event listeners", { walletId });
|
|
2405
|
+
if (this.addressTypes.includes(AddressType3.solana) && walletInfo.providers?.solana) {
|
|
2406
|
+
this.setupSolanaEventListeners(walletInfo.providers.solana, walletId, "wallet");
|
|
2407
|
+
}
|
|
2408
|
+
if (this.addressTypes.includes(AddressType3.ethereum) && walletInfo.providers?.ethereum) {
|
|
2409
|
+
this.setupEthereumEventListeners(walletInfo.providers.ethereum, walletId, "wallet");
|
|
2529
2410
|
}
|
|
2411
|
+
this.eventListenersSetup.add(walletId);
|
|
2412
|
+
this.eventsInitialized = true;
|
|
2530
2413
|
}
|
|
2531
2414
|
};
|
|
2532
2415
|
|
|
@@ -2666,7 +2549,7 @@ var BrowserURLParamsAccessor = class {
|
|
|
2666
2549
|
var browserUrlParamsAccessor = new BrowserURLParamsAccessor();
|
|
2667
2550
|
|
|
2668
2551
|
// src/providers/embedded/adapters/auth.ts
|
|
2669
|
-
import { DEFAULT_AUTH_URL } from "@phantom/constants";
|
|
2552
|
+
import { DEFAULT_AUTH_URL, DEFAULT_AUTHENTICATOR_ALGORITHM } from "@phantom/constants";
|
|
2670
2553
|
|
|
2671
2554
|
// src/utils/browser-detection.ts
|
|
2672
2555
|
function parseBrowserFromUserAgent(userAgent, hasBraveAPI) {
|
|
@@ -2841,9 +2724,10 @@ var BrowserAuthProvider = class {
|
|
|
2841
2724
|
// OAuth session management - defaults to allow refresh unless explicitly clearing after logout
|
|
2842
2725
|
clear_previous_session: (phantomOptions.clearPreviousSession ?? false).toString(),
|
|
2843
2726
|
allow_refresh: (phantomOptions.allowRefresh ?? true).toString(),
|
|
2844
|
-
sdk_version: "1.0.
|
|
2727
|
+
sdk_version: "1.0.3",
|
|
2845
2728
|
sdk_type: "browser",
|
|
2846
|
-
platform: detectBrowser().name
|
|
2729
|
+
platform: detectBrowser().name,
|
|
2730
|
+
algorithm: phantomOptions.algorithm || DEFAULT_AUTHENTICATOR_ALGORITHM
|
|
2847
2731
|
});
|
|
2848
2732
|
if (phantomOptions.provider) {
|
|
2849
2733
|
debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Provider specified, will skip selection", {
|
|
@@ -2964,28 +2848,9 @@ var BrowserAuthProvider = class {
|
|
|
2964
2848
|
// src/providers/embedded/adapters/phantom-app.ts
|
|
2965
2849
|
import { isPhantomExtensionInstalled as isPhantomExtensionInstalled3 } from "@phantom/browser-injected-sdk";
|
|
2966
2850
|
|
|
2967
|
-
// src/
|
|
2851
|
+
// src/waitForPhantomExtension.ts
|
|
2968
2852
|
import { isPhantomExtensionInstalled as isPhantomExtensionInstalled2 } from "@phantom/browser-injected-sdk";
|
|
2969
|
-
async function
|
|
2970
|
-
const extensionInstalled = await waitForExtension(timeoutMs);
|
|
2971
|
-
if (!extensionInstalled) {
|
|
2972
|
-
return false;
|
|
2973
|
-
}
|
|
2974
|
-
try {
|
|
2975
|
-
if (!window.phantom?.app?.features || typeof window.phantom.app.features !== "function") {
|
|
2976
|
-
return false;
|
|
2977
|
-
}
|
|
2978
|
-
const response = await window.phantom.app.features();
|
|
2979
|
-
if (!Array.isArray(response.features)) {
|
|
2980
|
-
return false;
|
|
2981
|
-
}
|
|
2982
|
-
return response.features.includes("phantom_login");
|
|
2983
|
-
} catch (error) {
|
|
2984
|
-
console.error("Error checking Phantom extension features", error);
|
|
2985
|
-
return false;
|
|
2986
|
-
}
|
|
2987
|
-
}
|
|
2988
|
-
async function waitForExtension(timeoutMs) {
|
|
2853
|
+
async function waitForPhantomExtension(timeoutMs = 3e3) {
|
|
2989
2854
|
return new Promise((resolve) => {
|
|
2990
2855
|
const startTime = Date.now();
|
|
2991
2856
|
const checkInterval = 100;
|
|
@@ -3008,6 +2873,27 @@ async function waitForExtension(timeoutMs) {
|
|
|
3008
2873
|
});
|
|
3009
2874
|
}
|
|
3010
2875
|
|
|
2876
|
+
// src/isPhantomLoginAvailable.ts
|
|
2877
|
+
async function isPhantomLoginAvailable(timeoutMs = 3e3) {
|
|
2878
|
+
const extensionInstalled = await waitForPhantomExtension(timeoutMs);
|
|
2879
|
+
if (!extensionInstalled) {
|
|
2880
|
+
return false;
|
|
2881
|
+
}
|
|
2882
|
+
try {
|
|
2883
|
+
if (!window.phantom?.app?.features || typeof window.phantom.app.features !== "function") {
|
|
2884
|
+
return false;
|
|
2885
|
+
}
|
|
2886
|
+
const response = await window.phantom.app.features();
|
|
2887
|
+
if (!Array.isArray(response.features)) {
|
|
2888
|
+
return false;
|
|
2889
|
+
}
|
|
2890
|
+
return response.features.includes("phantom_login");
|
|
2891
|
+
} catch (error) {
|
|
2892
|
+
console.error("Error checking Phantom extension features", error);
|
|
2893
|
+
return false;
|
|
2894
|
+
}
|
|
2895
|
+
}
|
|
2896
|
+
|
|
3011
2897
|
// src/providers/embedded/adapters/phantom-app.ts
|
|
3012
2898
|
var BrowserPhantomAppProvider = class {
|
|
3013
2899
|
/**
|
|
@@ -3105,7 +2991,7 @@ var EmbeddedProvider = class extends CoreEmbeddedProvider {
|
|
|
3105
2991
|
// Full user agent for more detailed info
|
|
3106
2992
|
[ANALYTICS_HEADERS.APP_ID]: config.appId,
|
|
3107
2993
|
[ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
|
|
3108
|
-
[ANALYTICS_HEADERS.SDK_VERSION]: "1.0.
|
|
2994
|
+
[ANALYTICS_HEADERS.SDK_VERSION]: "1.0.3"
|
|
3109
2995
|
// Replaced at build time
|
|
3110
2996
|
}
|
|
3111
2997
|
};
|
|
@@ -3144,11 +3030,12 @@ function isAuthCallbackUrl(searchParams) {
|
|
|
3144
3030
|
}
|
|
3145
3031
|
|
|
3146
3032
|
// src/utils/deeplink.ts
|
|
3147
|
-
function getDeeplinkToPhantom(ref) {
|
|
3148
|
-
|
|
3033
|
+
function getDeeplinkToPhantom(ref, currentHref) {
|
|
3034
|
+
const resolvedHref = currentHref ?? window.location.href;
|
|
3035
|
+
if (!resolvedHref.startsWith("http:") && !resolvedHref.startsWith("https:")) {
|
|
3149
3036
|
throw new Error("Invalid URL protocol - only HTTP/HTTPS URLs are supported for deeplinks");
|
|
3150
3037
|
}
|
|
3151
|
-
const currentUrl = encodeURIComponent(
|
|
3038
|
+
const currentUrl = encodeURIComponent(resolvedHref);
|
|
3152
3039
|
const refParam = ref ? `?ref=${encodeURIComponent(ref)}` : "";
|
|
3153
3040
|
return `https://phantom.app/ul/browse/${currentUrl}${refParam}`;
|
|
3154
3041
|
}
|
|
@@ -3244,8 +3131,14 @@ var ProviderManager = class {
|
|
|
3244
3131
|
} else if (requestedProvider === "deeplink") {
|
|
3245
3132
|
try {
|
|
3246
3133
|
const deeplinkUrl = getDeeplinkToPhantom();
|
|
3247
|
-
if (typeof window !== "undefined") {
|
|
3248
|
-
|
|
3134
|
+
if (typeof window !== "undefined" && window.location) {
|
|
3135
|
+
try {
|
|
3136
|
+
window.location.href = deeplinkUrl;
|
|
3137
|
+
} catch (error) {
|
|
3138
|
+
debug.warn(DebugCategory.PROVIDER_MANAGER, "Failed to set deeplink location", {
|
|
3139
|
+
error: error instanceof Error ? error.message : String(error)
|
|
3140
|
+
});
|
|
3141
|
+
}
|
|
3249
3142
|
}
|
|
3250
3143
|
return {
|
|
3251
3144
|
addresses: [],
|
|
@@ -3390,7 +3283,7 @@ var ProviderManager = class {
|
|
|
3390
3283
|
if (!this.eventListeners.has(event)) {
|
|
3391
3284
|
this.eventListeners.set(event, /* @__PURE__ */ new Set());
|
|
3392
3285
|
}
|
|
3393
|
-
this.eventListeners.get(event)
|
|
3286
|
+
this.eventListeners.get(event)?.add(callback);
|
|
3394
3287
|
this.ensureProviderEventForwarding();
|
|
3395
3288
|
}
|
|
3396
3289
|
/**
|
|
@@ -3399,8 +3292,8 @@ var ProviderManager = class {
|
|
|
3399
3292
|
off(event, callback) {
|
|
3400
3293
|
debug.log(DebugCategory.PROVIDER_MANAGER, "Removing event listener", { event });
|
|
3401
3294
|
if (this.eventListeners.has(event)) {
|
|
3402
|
-
this.eventListeners.get(event)
|
|
3403
|
-
if (this.eventListeners.get(event)
|
|
3295
|
+
this.eventListeners.get(event)?.delete(callback);
|
|
3296
|
+
if (this.eventListeners.get(event)?.size === 0) {
|
|
3404
3297
|
this.eventListeners.delete(event);
|
|
3405
3298
|
}
|
|
3406
3299
|
}
|
|
@@ -3716,6 +3609,7 @@ var BrowserSDK = class {
|
|
|
3716
3609
|
*/
|
|
3717
3610
|
async autoConnect() {
|
|
3718
3611
|
debug.log(DebugCategory.BROWSER_SDK, "Attempting auto-connect with fallback strategy");
|
|
3612
|
+
await this.discoverWallets();
|
|
3719
3613
|
const result = await this.providerManager.autoConnect();
|
|
3720
3614
|
if (result) {
|
|
3721
3615
|
debug.info(DebugCategory.BROWSER_SDK, "Auto-connect successful", {
|
|
@@ -3863,40 +3757,17 @@ var BrowserSDK = class {
|
|
|
3863
3757
|
}
|
|
3864
3758
|
};
|
|
3865
3759
|
|
|
3866
|
-
// src/waitForPhantomExtension.ts
|
|
3867
|
-
import { isPhantomExtensionInstalled as isPhantomExtensionInstalled4 } from "@phantom/browser-injected-sdk";
|
|
3868
|
-
async function waitForPhantomExtension(timeoutMs = 3e3) {
|
|
3869
|
-
return new Promise((resolve) => {
|
|
3870
|
-
const startTime = Date.now();
|
|
3871
|
-
const checkInterval = 100;
|
|
3872
|
-
const checkForExtension = () => {
|
|
3873
|
-
try {
|
|
3874
|
-
if (isPhantomExtensionInstalled4()) {
|
|
3875
|
-
resolve(true);
|
|
3876
|
-
return;
|
|
3877
|
-
}
|
|
3878
|
-
} catch (error) {
|
|
3879
|
-
}
|
|
3880
|
-
const elapsed = Date.now() - startTime;
|
|
3881
|
-
if (elapsed >= timeoutMs) {
|
|
3882
|
-
resolve(false);
|
|
3883
|
-
return;
|
|
3884
|
-
}
|
|
3885
|
-
setTimeout(checkForExtension, checkInterval);
|
|
3886
|
-
};
|
|
3887
|
-
checkForExtension();
|
|
3888
|
-
});
|
|
3889
|
-
}
|
|
3890
|
-
|
|
3891
3760
|
// src/index.ts
|
|
3892
3761
|
import { NetworkId } from "@phantom/constants";
|
|
3893
|
-
import { AddressType as
|
|
3762
|
+
import { AddressType as AddressType4 } from "@phantom/client";
|
|
3763
|
+
import { PHANTOM_ICON as PHANTOM_ICON3 } from "@phantom/constants";
|
|
3894
3764
|
export {
|
|
3895
|
-
|
|
3765
|
+
AddressType4 as AddressType,
|
|
3896
3766
|
BrowserSDK,
|
|
3897
3767
|
DebugCategory,
|
|
3898
3768
|
DebugLevel,
|
|
3899
3769
|
NetworkId,
|
|
3770
|
+
PHANTOM_ICON3 as PHANTOM_ICON,
|
|
3900
3771
|
debug,
|
|
3901
3772
|
detectBrowser,
|
|
3902
3773
|
getBrowserDisplayName,
|