@phantom/browser-sdk 1.0.2 → 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 +218 -173
- package/dist/index.mjs +196 -151
- 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("-");
|
|
@@ -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,6 +498,9 @@ 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
506
|
import { Buffer } from "buffer";
|
|
@@ -446,61 +508,55 @@ var InjectedWalletSolanaChain = class {
|
|
|
446
508
|
constructor(provider, walletId, walletName) {
|
|
447
509
|
// Expose eventEmitter for testing - allows tests to trigger events directly
|
|
448
510
|
this.eventEmitter = new EventEmitter();
|
|
449
|
-
this._connected = false;
|
|
450
511
|
this._publicKey = null;
|
|
451
512
|
this.provider = provider;
|
|
452
513
|
this.walletId = walletId;
|
|
453
514
|
this.walletName = walletName;
|
|
454
515
|
this.setupEventListeners();
|
|
455
516
|
}
|
|
456
|
-
get connected() {
|
|
457
|
-
return this._connected;
|
|
458
|
-
}
|
|
459
517
|
get publicKey() {
|
|
460
518
|
return this._publicKey;
|
|
461
519
|
}
|
|
520
|
+
get isConnected() {
|
|
521
|
+
return this.provider.isConnected || !!this._publicKey;
|
|
522
|
+
}
|
|
462
523
|
async connect(options) {
|
|
463
|
-
debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Solana connect", {
|
|
464
|
-
walletId: this.walletId,
|
|
465
|
-
walletName: this.walletName,
|
|
466
|
-
onlyIfTrusted: options?.onlyIfTrusted
|
|
467
|
-
});
|
|
468
524
|
try {
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
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", {
|
|
474
529
|
walletId: this.walletId,
|
|
475
530
|
walletName: this.walletName,
|
|
476
|
-
|
|
531
|
+
providerConnected: isConnected,
|
|
532
|
+
providerPublicKey: this.provider.publicKey
|
|
477
533
|
});
|
|
478
|
-
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
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", {
|
|
484
544
|
walletId: this.walletId,
|
|
485
545
|
walletName: this.walletName,
|
|
486
|
-
|
|
546
|
+
publicKeyType: typeof providerPublicKey
|
|
487
547
|
});
|
|
488
|
-
|
|
489
|
-
}
|
|
490
|
-
if (
|
|
491
|
-
|
|
492
|
-
if (typeof firstAccount === "object" && firstAccount !== null && "address" in firstAccount) {
|
|
493
|
-
this._connected = true;
|
|
494
|
-
this._publicKey = firstAccount.address;
|
|
495
|
-
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Solana connected", {
|
|
496
|
-
walletId: this.walletId,
|
|
497
|
-
walletName: this.walletName,
|
|
498
|
-
publicKey: firstAccount.address
|
|
499
|
-
});
|
|
500
|
-
return { publicKey: firstAccount.address };
|
|
501
|
-
}
|
|
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");
|
|
502
552
|
}
|
|
503
|
-
|
|
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 };
|
|
504
560
|
} catch (error) {
|
|
505
561
|
debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Solana connect failed", {
|
|
506
562
|
walletId: this.walletId,
|
|
@@ -517,7 +573,6 @@ var InjectedWalletSolanaChain = class {
|
|
|
517
573
|
});
|
|
518
574
|
try {
|
|
519
575
|
await this.provider.disconnect();
|
|
520
|
-
this._connected = false;
|
|
521
576
|
this._publicKey = null;
|
|
522
577
|
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Solana disconnected", {
|
|
523
578
|
walletId: this.walletId,
|
|
@@ -653,28 +708,19 @@ var InjectedWalletSolanaChain = class {
|
|
|
653
708
|
switchNetwork(_network) {
|
|
654
709
|
return Promise.resolve();
|
|
655
710
|
}
|
|
656
|
-
getPublicKey() {
|
|
657
|
-
return Promise.resolve(this._publicKey);
|
|
658
|
-
}
|
|
659
|
-
isConnected() {
|
|
660
|
-
return this._connected;
|
|
661
|
-
}
|
|
662
711
|
setupEventListeners() {
|
|
663
712
|
if (typeof this.provider.on === "function") {
|
|
664
713
|
this.provider.on("connect", (publicKey) => {
|
|
665
|
-
this._connected = true;
|
|
666
714
|
this._publicKey = publicKey;
|
|
667
715
|
this.eventEmitter.emit("connect", publicKey);
|
|
668
716
|
});
|
|
669
717
|
this.provider.on("disconnect", () => {
|
|
670
|
-
this._connected = false;
|
|
671
718
|
this._publicKey = null;
|
|
672
719
|
this.eventEmitter.emit("disconnect");
|
|
673
720
|
});
|
|
674
721
|
this.provider.on("accountChanged", (publicKey) => {
|
|
675
|
-
this._publicKey = publicKey;
|
|
676
|
-
this.
|
|
677
|
-
this.eventEmitter.emit("accountChanged", publicKey);
|
|
722
|
+
this._publicKey = publicKey ? publicKey : null;
|
|
723
|
+
this.eventEmitter.emit("accountChanged", this._publicKey);
|
|
678
724
|
});
|
|
679
725
|
}
|
|
680
726
|
}
|
|
@@ -700,12 +746,12 @@ var WalletStandardSolanaAdapter = class {
|
|
|
700
746
|
this.walletName = walletName;
|
|
701
747
|
this.setupEventListeners();
|
|
702
748
|
}
|
|
703
|
-
get connected() {
|
|
704
|
-
return this._publicKey !== null;
|
|
705
|
-
}
|
|
706
749
|
get publicKey() {
|
|
707
750
|
return this._publicKey;
|
|
708
751
|
}
|
|
752
|
+
get isConnected() {
|
|
753
|
+
return this._publicKey !== null;
|
|
754
|
+
}
|
|
709
755
|
async connect(_options) {
|
|
710
756
|
try {
|
|
711
757
|
const connectFeature = this.wallet.features["standard:connect"];
|
|
@@ -917,12 +963,6 @@ var WalletStandardSolanaAdapter = class {
|
|
|
917
963
|
async switchNetwork(_network) {
|
|
918
964
|
return Promise.resolve();
|
|
919
965
|
}
|
|
920
|
-
getPublicKey() {
|
|
921
|
-
return Promise.resolve(this._publicKey);
|
|
922
|
-
}
|
|
923
|
-
isConnected() {
|
|
924
|
-
return this._publicKey !== null;
|
|
925
|
-
}
|
|
926
966
|
/**
|
|
927
967
|
* Set up event listeners for Wallet Standard events
|
|
928
968
|
* Maps Wallet Standard "change" events to "accountChanged" events
|
|
@@ -1057,9 +1097,6 @@ var InjectedWalletEthereumChain = class {
|
|
|
1057
1097
|
this.walletName = walletName;
|
|
1058
1098
|
this.setupEventListeners();
|
|
1059
1099
|
}
|
|
1060
|
-
get connected() {
|
|
1061
|
-
return this._connected;
|
|
1062
|
-
}
|
|
1063
1100
|
get chainId() {
|
|
1064
1101
|
return this._chainId;
|
|
1065
1102
|
}
|
|
@@ -1189,7 +1226,8 @@ var InjectedWalletEthereumChain = class {
|
|
|
1189
1226
|
address
|
|
1190
1227
|
});
|
|
1191
1228
|
try {
|
|
1192
|
-
const
|
|
1229
|
+
const providerAny = this.provider;
|
|
1230
|
+
const providerConnected = (typeof providerAny.isConnected === "function" ? providerAny.isConnected() : false) || (typeof providerAny.connected === "boolean" ? providerAny.connected : false);
|
|
1193
1231
|
if (!this._connected || this._accounts.length === 0 || !providerConnected) {
|
|
1194
1232
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Not connected, attempting to connect before signing", {
|
|
1195
1233
|
walletId: this.walletId,
|
|
@@ -1503,8 +1541,7 @@ var InjectedWalletRegistry = class {
|
|
|
1503
1541
|
const phantomWallet = {
|
|
1504
1542
|
id: "phantom",
|
|
1505
1543
|
name: "Phantom",
|
|
1506
|
-
icon:
|
|
1507
|
-
// Icon will be rendered from icons package in UI components
|
|
1544
|
+
icon: PHANTOM_ICON2,
|
|
1508
1545
|
addressTypes,
|
|
1509
1546
|
providers: wrappedProviders,
|
|
1510
1547
|
isPhantom: true,
|
|
@@ -1650,13 +1687,13 @@ var InjectedProvider = class {
|
|
|
1650
1687
|
return provider;
|
|
1651
1688
|
}
|
|
1652
1689
|
get solana() {
|
|
1653
|
-
return this.getChainProvider(
|
|
1690
|
+
return this.getChainProvider(AddressType3.solana, "solana", "Solana");
|
|
1654
1691
|
}
|
|
1655
1692
|
/**
|
|
1656
1693
|
* Access to Ethereum chain operations
|
|
1657
1694
|
*/
|
|
1658
1695
|
get ethereum() {
|
|
1659
|
-
return this.getChainProvider(
|
|
1696
|
+
return this.getChainProvider(AddressType3.ethereum, "ethereum", "Ethereum");
|
|
1660
1697
|
}
|
|
1661
1698
|
validateAndSelectWallet(requestedWalletId) {
|
|
1662
1699
|
if (!this.walletRegistry.has(requestedWalletId)) {
|
|
@@ -1697,7 +1734,7 @@ var InjectedProvider = class {
|
|
|
1697
1734
|
this.setupEventListeners(walletInfo);
|
|
1698
1735
|
}
|
|
1699
1736
|
const connectedAddresses = [];
|
|
1700
|
-
if (this.addressTypes.includes(
|
|
1737
|
+
if (this.addressTypes.includes(AddressType3.solana) && walletInfo.providers?.solana) {
|
|
1701
1738
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting Solana connection", {
|
|
1702
1739
|
walletId: this.selectedWalletId,
|
|
1703
1740
|
walletName: walletInfo.name,
|
|
@@ -1709,7 +1746,7 @@ var InjectedProvider = class {
|
|
|
1709
1746
|
);
|
|
1710
1747
|
const address = result.publicKey;
|
|
1711
1748
|
connectedAddresses.push({
|
|
1712
|
-
addressType:
|
|
1749
|
+
addressType: AddressType3.solana,
|
|
1713
1750
|
address
|
|
1714
1751
|
});
|
|
1715
1752
|
debug.info(DebugCategory.INJECTED_PROVIDER, "Solana connected successfully", {
|
|
@@ -1730,7 +1767,7 @@ var InjectedProvider = class {
|
|
|
1730
1767
|
throw err;
|
|
1731
1768
|
}
|
|
1732
1769
|
}
|
|
1733
|
-
if (this.addressTypes.includes(
|
|
1770
|
+
if (this.addressTypes.includes(AddressType3.ethereum) && walletInfo.providers?.ethereum) {
|
|
1734
1771
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting Ethereum connection", {
|
|
1735
1772
|
walletId: this.selectedWalletId,
|
|
1736
1773
|
walletName: walletInfo.name,
|
|
@@ -1746,7 +1783,7 @@ var InjectedProvider = class {
|
|
|
1746
1783
|
if (accounts.length > 0) {
|
|
1747
1784
|
connectedAddresses.push(
|
|
1748
1785
|
...accounts.map((address) => ({
|
|
1749
|
-
addressType:
|
|
1786
|
+
addressType: AddressType3.ethereum,
|
|
1750
1787
|
address
|
|
1751
1788
|
}))
|
|
1752
1789
|
);
|
|
@@ -1826,7 +1863,8 @@ var InjectedProvider = class {
|
|
|
1826
1863
|
this.emit("connect", {
|
|
1827
1864
|
addresses: connectedAddresses,
|
|
1828
1865
|
source: "manual-connect",
|
|
1829
|
-
authUserId
|
|
1866
|
+
authUserId,
|
|
1867
|
+
walletId
|
|
1830
1868
|
});
|
|
1831
1869
|
return result;
|
|
1832
1870
|
}
|
|
@@ -1838,12 +1876,13 @@ var InjectedProvider = class {
|
|
|
1838
1876
|
if (authOptions.provider !== "injected") {
|
|
1839
1877
|
throw new Error(`Invalid provider for injected connection: ${authOptions.provider}. Must be "injected"`);
|
|
1840
1878
|
}
|
|
1879
|
+
const requestedWalletId = authOptions.walletId || "phantom";
|
|
1841
1880
|
this.emit("connect_start", {
|
|
1842
1881
|
source: "manual-connect",
|
|
1843
|
-
providerType: "injected"
|
|
1882
|
+
providerType: "injected",
|
|
1883
|
+
walletId: requestedWalletId
|
|
1844
1884
|
});
|
|
1845
1885
|
try {
|
|
1846
|
-
const requestedWalletId = authOptions.walletId || "phantom";
|
|
1847
1886
|
const walletInfo = this.validateAndSelectWallet(requestedWalletId);
|
|
1848
1887
|
const connectedAddresses = await this.connectToWallet(walletInfo);
|
|
1849
1888
|
return await this.finalizeConnection(connectedAddresses, "injected", this.selectedWalletId || void 0);
|
|
@@ -1859,7 +1898,7 @@ var InjectedProvider = class {
|
|
|
1859
1898
|
debug.info(DebugCategory.INJECTED_PROVIDER, "Starting injected provider disconnect");
|
|
1860
1899
|
const walletInfo = this.walletRegistry.getById(this.selectedWalletId || "phantom");
|
|
1861
1900
|
if (walletInfo?.providers) {
|
|
1862
|
-
if (this.addressTypes.includes(
|
|
1901
|
+
if (this.addressTypes.includes(AddressType3.solana) && walletInfo.providers.solana) {
|
|
1863
1902
|
try {
|
|
1864
1903
|
await walletInfo.providers.solana.disconnect();
|
|
1865
1904
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana disconnected successfully");
|
|
@@ -1867,7 +1906,7 @@ var InjectedProvider = class {
|
|
|
1867
1906
|
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to disconnect Solana", { error: err });
|
|
1868
1907
|
}
|
|
1869
1908
|
}
|
|
1870
|
-
if (this.addressTypes.includes(
|
|
1909
|
+
if (this.addressTypes.includes(AddressType3.ethereum) && walletInfo.providers.ethereum) {
|
|
1871
1910
|
try {
|
|
1872
1911
|
await walletInfo.providers.ethereum.disconnect();
|
|
1873
1912
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum disconnected successfully");
|
|
@@ -1963,7 +2002,8 @@ var InjectedProvider = class {
|
|
|
1963
2002
|
this.emit("connect", {
|
|
1964
2003
|
addresses: connectedAddresses,
|
|
1965
2004
|
source: "auto-connect",
|
|
1966
|
-
authUserId
|
|
2005
|
+
authUserId,
|
|
2006
|
+
walletId: this.selectedWalletId
|
|
1967
2007
|
});
|
|
1968
2008
|
debug.info(DebugCategory.INJECTED_PROVIDER, "Auto-connect successful", {
|
|
1969
2009
|
addressCount: connectedAddresses.length,
|
|
@@ -2024,12 +2064,13 @@ var InjectedProvider = class {
|
|
|
2024
2064
|
createSolanaConnectHandler(walletId, source) {
|
|
2025
2065
|
return async (publicKey) => {
|
|
2026
2066
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana connect event received", { publicKey, walletId });
|
|
2027
|
-
const newAddresses = this.updateWalletAddresses(walletId, [publicKey],
|
|
2067
|
+
const newAddresses = this.updateWalletAddresses(walletId, [publicKey], AddressType3.solana);
|
|
2028
2068
|
const authUserId = await this.getAuthUserId("Solana connect event");
|
|
2029
2069
|
this.emit("connect", {
|
|
2030
2070
|
addresses: newAddresses,
|
|
2031
2071
|
source,
|
|
2032
|
-
authUserId
|
|
2072
|
+
authUserId,
|
|
2073
|
+
walletId: this.selectedWalletId
|
|
2033
2074
|
});
|
|
2034
2075
|
};
|
|
2035
2076
|
}
|
|
@@ -2040,7 +2081,7 @@ var InjectedProvider = class {
|
|
|
2040
2081
|
return () => {
|
|
2041
2082
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana disconnect event received", { walletId });
|
|
2042
2083
|
const state = this.getWalletState(walletId);
|
|
2043
|
-
const filteredAddresses = state.addresses.filter((addr) => addr.addressType !==
|
|
2084
|
+
const filteredAddresses = state.addresses.filter((addr) => addr.addressType !== AddressType3.solana);
|
|
2044
2085
|
this.setWalletState(walletId, {
|
|
2045
2086
|
connected: filteredAddresses.length > 0,
|
|
2046
2087
|
addresses: filteredAddresses
|
|
@@ -2058,16 +2099,17 @@ var InjectedProvider = class {
|
|
|
2058
2099
|
return async (publicKey) => {
|
|
2059
2100
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana account changed event received", { publicKey, walletId });
|
|
2060
2101
|
if (publicKey) {
|
|
2061
|
-
const newAddresses = this.updateWalletAddresses(walletId, [publicKey],
|
|
2102
|
+
const newAddresses = this.updateWalletAddresses(walletId, [publicKey], AddressType3.solana);
|
|
2062
2103
|
const authUserId = await this.getAuthUserId("Solana account changed event");
|
|
2063
2104
|
this.emit("connect", {
|
|
2064
2105
|
addresses: newAddresses,
|
|
2065
2106
|
source: this.getAccountChangeSource(source),
|
|
2066
|
-
authUserId
|
|
2107
|
+
authUserId,
|
|
2108
|
+
walletId: this.selectedWalletId
|
|
2067
2109
|
});
|
|
2068
2110
|
} else {
|
|
2069
2111
|
const state = this.getWalletState(walletId);
|
|
2070
|
-
const otherAddresses = state.addresses.filter((addr) => addr.addressType !==
|
|
2112
|
+
const otherAddresses = state.addresses.filter((addr) => addr.addressType !== AddressType3.solana);
|
|
2071
2113
|
this.setWalletState(walletId, {
|
|
2072
2114
|
connected: otherAddresses.length > 0,
|
|
2073
2115
|
addresses: otherAddresses
|
|
@@ -2099,12 +2141,13 @@ var InjectedProvider = class {
|
|
|
2099
2141
|
}
|
|
2100
2142
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum connect event received", { accounts, walletId });
|
|
2101
2143
|
if (accounts.length > 0) {
|
|
2102
|
-
const newAddresses = this.updateWalletAddresses(walletId, accounts,
|
|
2144
|
+
const newAddresses = this.updateWalletAddresses(walletId, accounts, AddressType3.ethereum);
|
|
2103
2145
|
const authUserId = await this.getAuthUserId("Ethereum connect event");
|
|
2104
2146
|
this.emit("connect", {
|
|
2105
2147
|
addresses: newAddresses,
|
|
2106
2148
|
source,
|
|
2107
|
-
authUserId
|
|
2149
|
+
authUserId,
|
|
2150
|
+
walletId: this.selectedWalletId
|
|
2108
2151
|
});
|
|
2109
2152
|
}
|
|
2110
2153
|
};
|
|
@@ -2116,7 +2159,7 @@ var InjectedProvider = class {
|
|
|
2116
2159
|
return () => {
|
|
2117
2160
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum disconnect event received", { walletId });
|
|
2118
2161
|
const state = this.getWalletState(walletId);
|
|
2119
|
-
const filteredAddresses = state.addresses.filter((addr) => addr.addressType !==
|
|
2162
|
+
const filteredAddresses = state.addresses.filter((addr) => addr.addressType !== AddressType3.ethereum);
|
|
2120
2163
|
this.setWalletState(walletId, {
|
|
2121
2164
|
connected: filteredAddresses.length > 0,
|
|
2122
2165
|
addresses: filteredAddresses
|
|
@@ -2133,16 +2176,17 @@ var InjectedProvider = class {
|
|
|
2133
2176
|
return async (accounts) => {
|
|
2134
2177
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum accounts changed event received", { accounts, walletId });
|
|
2135
2178
|
if (accounts && accounts.length > 0) {
|
|
2136
|
-
const newAddresses = this.updateWalletAddresses(walletId, accounts,
|
|
2179
|
+
const newAddresses = this.updateWalletAddresses(walletId, accounts, AddressType3.ethereum);
|
|
2137
2180
|
const authUserId = await this.getAuthUserId("Ethereum accounts changed event");
|
|
2138
2181
|
this.emit("connect", {
|
|
2139
2182
|
addresses: newAddresses,
|
|
2140
2183
|
source: this.getAccountChangeSource(source),
|
|
2141
|
-
authUserId
|
|
2184
|
+
authUserId,
|
|
2185
|
+
walletId: this.selectedWalletId
|
|
2142
2186
|
});
|
|
2143
2187
|
} else {
|
|
2144
2188
|
const state = this.getWalletState(walletId);
|
|
2145
|
-
const otherAddresses = state.addresses.filter((addr) => addr.addressType !==
|
|
2189
|
+
const otherAddresses = state.addresses.filter((addr) => addr.addressType !== AddressType3.ethereum);
|
|
2146
2190
|
this.setWalletState(walletId, {
|
|
2147
2191
|
connected: otherAddresses.length > 0,
|
|
2148
2192
|
addresses: otherAddresses
|
|
@@ -2336,7 +2380,9 @@ var InjectedProvider = class {
|
|
|
2336
2380
|
this.eventListenerCleanups.set(walletId, [...existingCleanups, ...cleanups]);
|
|
2337
2381
|
}
|
|
2338
2382
|
/**
|
|
2339
|
-
* Unified event listener setup for all wallet types (Phantom and external)
|
|
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.
|
|
2340
2386
|
*/
|
|
2341
2387
|
setupEventListeners(walletInfo) {
|
|
2342
2388
|
const walletId = this.selectedWalletId || "phantom";
|
|
@@ -2344,11 +2390,22 @@ var InjectedProvider = class {
|
|
|
2344
2390
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Event listeners already set up for wallet", { walletId });
|
|
2345
2391
|
return;
|
|
2346
2392
|
}
|
|
2393
|
+
for (const existingWalletId of this.eventListenersSetup) {
|
|
2394
|
+
if (existingWalletId === walletId) {
|
|
2395
|
+
continue;
|
|
2396
|
+
}
|
|
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());
|
|
2401
|
+
}
|
|
2402
|
+
this.eventListenersSetup.delete(existingWalletId);
|
|
2403
|
+
}
|
|
2347
2404
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up event listeners", { walletId });
|
|
2348
|
-
if (this.addressTypes.includes(
|
|
2405
|
+
if (this.addressTypes.includes(AddressType3.solana) && walletInfo.providers?.solana) {
|
|
2349
2406
|
this.setupSolanaEventListeners(walletInfo.providers.solana, walletId, "wallet");
|
|
2350
2407
|
}
|
|
2351
|
-
if (this.addressTypes.includes(
|
|
2408
|
+
if (this.addressTypes.includes(AddressType3.ethereum) && walletInfo.providers?.ethereum) {
|
|
2352
2409
|
this.setupEthereumEventListeners(walletInfo.providers.ethereum, walletId, "wallet");
|
|
2353
2410
|
}
|
|
2354
2411
|
this.eventListenersSetup.add(walletId);
|
|
@@ -2492,7 +2549,7 @@ var BrowserURLParamsAccessor = class {
|
|
|
2492
2549
|
var browserUrlParamsAccessor = new BrowserURLParamsAccessor();
|
|
2493
2550
|
|
|
2494
2551
|
// src/providers/embedded/adapters/auth.ts
|
|
2495
|
-
import { DEFAULT_AUTH_URL } from "@phantom/constants";
|
|
2552
|
+
import { DEFAULT_AUTH_URL, DEFAULT_AUTHENTICATOR_ALGORITHM } from "@phantom/constants";
|
|
2496
2553
|
|
|
2497
2554
|
// src/utils/browser-detection.ts
|
|
2498
2555
|
function parseBrowserFromUserAgent(userAgent, hasBraveAPI) {
|
|
@@ -2667,9 +2724,10 @@ var BrowserAuthProvider = class {
|
|
|
2667
2724
|
// OAuth session management - defaults to allow refresh unless explicitly clearing after logout
|
|
2668
2725
|
clear_previous_session: (phantomOptions.clearPreviousSession ?? false).toString(),
|
|
2669
2726
|
allow_refresh: (phantomOptions.allowRefresh ?? true).toString(),
|
|
2670
|
-
sdk_version: "1.0.
|
|
2727
|
+
sdk_version: "1.0.3",
|
|
2671
2728
|
sdk_type: "browser",
|
|
2672
|
-
platform: detectBrowser().name
|
|
2729
|
+
platform: detectBrowser().name,
|
|
2730
|
+
algorithm: phantomOptions.algorithm || DEFAULT_AUTHENTICATOR_ALGORITHM
|
|
2673
2731
|
});
|
|
2674
2732
|
if (phantomOptions.provider) {
|
|
2675
2733
|
debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Provider specified, will skip selection", {
|
|
@@ -2790,28 +2848,9 @@ var BrowserAuthProvider = class {
|
|
|
2790
2848
|
// src/providers/embedded/adapters/phantom-app.ts
|
|
2791
2849
|
import { isPhantomExtensionInstalled as isPhantomExtensionInstalled3 } from "@phantom/browser-injected-sdk";
|
|
2792
2850
|
|
|
2793
|
-
// src/
|
|
2851
|
+
// src/waitForPhantomExtension.ts
|
|
2794
2852
|
import { isPhantomExtensionInstalled as isPhantomExtensionInstalled2 } from "@phantom/browser-injected-sdk";
|
|
2795
|
-
async function
|
|
2796
|
-
const extensionInstalled = await waitForExtension(timeoutMs);
|
|
2797
|
-
if (!extensionInstalled) {
|
|
2798
|
-
return false;
|
|
2799
|
-
}
|
|
2800
|
-
try {
|
|
2801
|
-
if (!window.phantom?.app?.features || typeof window.phantom.app.features !== "function") {
|
|
2802
|
-
return false;
|
|
2803
|
-
}
|
|
2804
|
-
const response = await window.phantom.app.features();
|
|
2805
|
-
if (!Array.isArray(response.features)) {
|
|
2806
|
-
return false;
|
|
2807
|
-
}
|
|
2808
|
-
return response.features.includes("phantom_login");
|
|
2809
|
-
} catch (error) {
|
|
2810
|
-
console.error("Error checking Phantom extension features", error);
|
|
2811
|
-
return false;
|
|
2812
|
-
}
|
|
2813
|
-
}
|
|
2814
|
-
async function waitForExtension(timeoutMs) {
|
|
2853
|
+
async function waitForPhantomExtension(timeoutMs = 3e3) {
|
|
2815
2854
|
return new Promise((resolve) => {
|
|
2816
2855
|
const startTime = Date.now();
|
|
2817
2856
|
const checkInterval = 100;
|
|
@@ -2834,6 +2873,27 @@ async function waitForExtension(timeoutMs) {
|
|
|
2834
2873
|
});
|
|
2835
2874
|
}
|
|
2836
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
|
+
|
|
2837
2897
|
// src/providers/embedded/adapters/phantom-app.ts
|
|
2838
2898
|
var BrowserPhantomAppProvider = class {
|
|
2839
2899
|
/**
|
|
@@ -2931,7 +2991,7 @@ var EmbeddedProvider = class extends CoreEmbeddedProvider {
|
|
|
2931
2991
|
// Full user agent for more detailed info
|
|
2932
2992
|
[ANALYTICS_HEADERS.APP_ID]: config.appId,
|
|
2933
2993
|
[ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
|
|
2934
|
-
[ANALYTICS_HEADERS.SDK_VERSION]: "1.0.
|
|
2994
|
+
[ANALYTICS_HEADERS.SDK_VERSION]: "1.0.3"
|
|
2935
2995
|
// Replaced at build time
|
|
2936
2996
|
}
|
|
2937
2997
|
};
|
|
@@ -2970,11 +3030,12 @@ function isAuthCallbackUrl(searchParams) {
|
|
|
2970
3030
|
}
|
|
2971
3031
|
|
|
2972
3032
|
// src/utils/deeplink.ts
|
|
2973
|
-
function getDeeplinkToPhantom(ref) {
|
|
2974
|
-
|
|
3033
|
+
function getDeeplinkToPhantom(ref, currentHref) {
|
|
3034
|
+
const resolvedHref = currentHref ?? window.location.href;
|
|
3035
|
+
if (!resolvedHref.startsWith("http:") && !resolvedHref.startsWith("https:")) {
|
|
2975
3036
|
throw new Error("Invalid URL protocol - only HTTP/HTTPS URLs are supported for deeplinks");
|
|
2976
3037
|
}
|
|
2977
|
-
const currentUrl = encodeURIComponent(
|
|
3038
|
+
const currentUrl = encodeURIComponent(resolvedHref);
|
|
2978
3039
|
const refParam = ref ? `?ref=${encodeURIComponent(ref)}` : "";
|
|
2979
3040
|
return `https://phantom.app/ul/browse/${currentUrl}${refParam}`;
|
|
2980
3041
|
}
|
|
@@ -3070,8 +3131,14 @@ var ProviderManager = class {
|
|
|
3070
3131
|
} else if (requestedProvider === "deeplink") {
|
|
3071
3132
|
try {
|
|
3072
3133
|
const deeplinkUrl = getDeeplinkToPhantom();
|
|
3073
|
-
if (typeof window !== "undefined") {
|
|
3074
|
-
|
|
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
|
+
}
|
|
3075
3142
|
}
|
|
3076
3143
|
return {
|
|
3077
3144
|
addresses: [],
|
|
@@ -3542,6 +3609,7 @@ var BrowserSDK = class {
|
|
|
3542
3609
|
*/
|
|
3543
3610
|
async autoConnect() {
|
|
3544
3611
|
debug.log(DebugCategory.BROWSER_SDK, "Attempting auto-connect with fallback strategy");
|
|
3612
|
+
await this.discoverWallets();
|
|
3545
3613
|
const result = await this.providerManager.autoConnect();
|
|
3546
3614
|
if (result) {
|
|
3547
3615
|
debug.info(DebugCategory.BROWSER_SDK, "Auto-connect successful", {
|
|
@@ -3689,40 +3757,17 @@ var BrowserSDK = class {
|
|
|
3689
3757
|
}
|
|
3690
3758
|
};
|
|
3691
3759
|
|
|
3692
|
-
// src/waitForPhantomExtension.ts
|
|
3693
|
-
import { isPhantomExtensionInstalled as isPhantomExtensionInstalled4 } from "@phantom/browser-injected-sdk";
|
|
3694
|
-
async function waitForPhantomExtension(timeoutMs = 3e3) {
|
|
3695
|
-
return new Promise((resolve) => {
|
|
3696
|
-
const startTime = Date.now();
|
|
3697
|
-
const checkInterval = 100;
|
|
3698
|
-
const checkForExtension = () => {
|
|
3699
|
-
try {
|
|
3700
|
-
if (isPhantomExtensionInstalled4()) {
|
|
3701
|
-
resolve(true);
|
|
3702
|
-
return;
|
|
3703
|
-
}
|
|
3704
|
-
} catch (error) {
|
|
3705
|
-
}
|
|
3706
|
-
const elapsed = Date.now() - startTime;
|
|
3707
|
-
if (elapsed >= timeoutMs) {
|
|
3708
|
-
resolve(false);
|
|
3709
|
-
return;
|
|
3710
|
-
}
|
|
3711
|
-
setTimeout(checkForExtension, checkInterval);
|
|
3712
|
-
};
|
|
3713
|
-
checkForExtension();
|
|
3714
|
-
});
|
|
3715
|
-
}
|
|
3716
|
-
|
|
3717
3760
|
// src/index.ts
|
|
3718
3761
|
import { NetworkId } from "@phantom/constants";
|
|
3719
|
-
import { AddressType as
|
|
3762
|
+
import { AddressType as AddressType4 } from "@phantom/client";
|
|
3763
|
+
import { PHANTOM_ICON as PHANTOM_ICON3 } from "@phantom/constants";
|
|
3720
3764
|
export {
|
|
3721
|
-
|
|
3765
|
+
AddressType4 as AddressType,
|
|
3722
3766
|
BrowserSDK,
|
|
3723
3767
|
DebugCategory,
|
|
3724
3768
|
DebugLevel,
|
|
3725
3769
|
NetworkId,
|
|
3770
|
+
PHANTOM_ICON3 as PHANTOM_ICON,
|
|
3726
3771
|
debug,
|
|
3727
3772
|
detectBrowser,
|
|
3728
3773
|
getBrowserDisplayName,
|