@phantom/browser-sdk 1.0.0-beta.22 → 1.0.0-beta.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -2,13 +2,7 @@
2
2
  import { AddressType } from "@phantom/client";
3
3
 
4
4
  // src/providers/injected/index.ts
5
- import { AddressType as AddressType4 } from "@phantom/client";
6
- import { createPhantom, createExtensionPlugin } from "@phantom/browser-injected-sdk";
7
- import { createSolanaPlugin } from "@phantom/browser-injected-sdk/solana";
8
- import { createEthereumPlugin } from "@phantom/browser-injected-sdk/ethereum";
9
- import {
10
- createAutoConfirmPlugin
11
- } from "@phantom/browser-injected-sdk/auto-confirm";
5
+ import { AddressType as AddressType2 } from "@phantom/client";
12
6
 
13
7
  // src/debug.ts
14
8
  var DebugLevel = /* @__PURE__ */ ((DebugLevel2) => {
@@ -27,111 +21,1404 @@ var Debug = class {
27
21
  if (!Debug.instance) {
28
22
  Debug.instance = new Debug();
29
23
  }
30
- return Debug.instance;
24
+ return Debug.instance;
25
+ }
26
+ setCallback(callback) {
27
+ this.callback = callback;
28
+ }
29
+ setLevel(level) {
30
+ this.level = level;
31
+ }
32
+ enable() {
33
+ this.enabled = true;
34
+ }
35
+ disable() {
36
+ this.enabled = false;
37
+ }
38
+ writeLog(level, category, message, data) {
39
+ if (!this.enabled || level > this.level) {
40
+ return;
41
+ }
42
+ const debugMessage = {
43
+ timestamp: Date.now(),
44
+ level,
45
+ category,
46
+ message,
47
+ data
48
+ };
49
+ if (this.callback) {
50
+ this.callback(debugMessage);
51
+ }
52
+ }
53
+ error(category, message, data) {
54
+ this.writeLog(0 /* ERROR */, category, message, data);
55
+ }
56
+ warn(category, message, data) {
57
+ this.writeLog(1 /* WARN */, category, message, data);
58
+ }
59
+ info(category, message, data) {
60
+ this.writeLog(2 /* INFO */, category, message, data);
61
+ }
62
+ debug(category, message, data) {
63
+ this.writeLog(3 /* DEBUG */, category, message, data);
64
+ }
65
+ log(category, message, data) {
66
+ this.writeLog(3 /* DEBUG */, category, message, data);
67
+ }
68
+ };
69
+ var debug = Debug.getInstance();
70
+ var DebugCategory = {
71
+ BROWSER_SDK: "BrowserSDK",
72
+ PROVIDER_MANAGER: "ProviderManager",
73
+ EMBEDDED_PROVIDER: "EmbeddedProvider",
74
+ INJECTED_PROVIDER: "InjectedProvider",
75
+ PHANTOM_CONNECT_AUTH: "PhantomConnectAuth",
76
+ JWT_AUTH: "JWTAuth",
77
+ STORAGE: "Storage",
78
+ SESSION: "Session"
79
+ };
80
+
81
+ // src/wallets/discovery.ts
82
+ import { AddressType as ClientAddressType } from "@phantom/client";
83
+ import { isPhantomExtensionInstalled } from "@phantom/browser-injected-sdk";
84
+ import { createPhantom, createExtensionPlugin } from "@phantom/browser-injected-sdk";
85
+ import { createSolanaPlugin } from "@phantom/browser-injected-sdk/solana";
86
+ import { createEthereumPlugin } from "@phantom/browser-injected-sdk/ethereum";
87
+ import { createAutoConfirmPlugin } from "@phantom/browser-injected-sdk/auto-confirm";
88
+ function generateWalletIdFromEIP6963(info) {
89
+ if (info.rdns) {
90
+ return info.rdns.split(".").reverse().join("-");
91
+ }
92
+ return info.name.toLowerCase().replace(/\s+/g, "-");
93
+ }
94
+ function generateWalletIdFromName(name) {
95
+ return name.toLowerCase().replace(/\s+/g, "-");
96
+ }
97
+ function processEIP6963Providers(providers) {
98
+ const wallets = [];
99
+ debug.log(DebugCategory.BROWSER_SDK, "Processing EIP-6963 providers", {
100
+ providerCount: providers.size,
101
+ providerNames: Array.from(providers.values()).map((d) => d.info.name)
102
+ });
103
+ for (const [, detail] of providers) {
104
+ const { info, provider } = detail;
105
+ const isPhantom = info.name.toLowerCase().includes("phantom") || info.rdns && (info.rdns.toLowerCase().includes("phantom") || info.rdns.toLowerCase() === "app.phantom");
106
+ if (isPhantom) {
107
+ debug.log(DebugCategory.BROWSER_SDK, "Skipping Phantom from EIP-6963", { name: info.name, rdns: info.rdns });
108
+ continue;
109
+ }
110
+ const walletId = generateWalletIdFromEIP6963(info);
111
+ debug.log(DebugCategory.BROWSER_SDK, "Discovered EIP-6963 wallet", {
112
+ walletId,
113
+ walletName: info.name,
114
+ rdns: info.rdns
115
+ });
116
+ wallets.push({
117
+ id: walletId,
118
+ name: info.name,
119
+ icon: info.icon,
120
+ addressTypes: [ClientAddressType.ethereum],
121
+ providers: {
122
+ // EIP-6963 provider implements EIP-1193 interface (IEthereumChain)
123
+ ethereum: provider
124
+ },
125
+ rdns: info.rdns
126
+ // Store rdns for potential future matching
127
+ });
128
+ }
129
+ debug.log(DebugCategory.BROWSER_SDK, "EIP-6963 discovery completed", {
130
+ discoveredCount: wallets.length,
131
+ walletIds: wallets.map((w) => w.id)
132
+ });
133
+ return wallets;
134
+ }
135
+ function discoverEthereumWallets() {
136
+ return new Promise((resolve) => {
137
+ const discoveredProviders = /* @__PURE__ */ new Map();
138
+ if (typeof window === "undefined") {
139
+ resolve([]);
140
+ return;
141
+ }
142
+ const handleAnnounce = (event) => {
143
+ const detail = event.detail;
144
+ if (detail?.info && detail?.provider) {
145
+ discoveredProviders.set(detail.info.uuid, detail);
146
+ }
147
+ };
148
+ window.addEventListener("eip6963:announceProvider", handleAnnounce);
149
+ window.dispatchEvent(new Event("eip6963:requestProvider"));
150
+ const processProviders = () => {
151
+ const wallets = processEIP6963Providers(discoveredProviders);
152
+ window.removeEventListener("eip6963:announceProvider", handleAnnounce);
153
+ resolve(wallets);
154
+ };
155
+ setTimeout(processProviders, 400);
156
+ });
157
+ }
158
+ async function discoverSolanaWallets() {
159
+ const wallets = [];
160
+ if (typeof window === "undefined" || typeof navigator === "undefined") {
161
+ debug.log(DebugCategory.BROWSER_SDK, "Wallet Standard discovery skipped (not in browser environment)");
162
+ return wallets;
163
+ }
164
+ const registeredWalletsSet = /* @__PURE__ */ new Set();
165
+ let cachedWalletsArray;
166
+ function addRegisteredWallet(wallet) {
167
+ cachedWalletsArray = void 0;
168
+ registeredWalletsSet.add(wallet);
169
+ const featureKeys = wallet.features ? Object.keys(wallet.features) : [];
170
+ debug.log(DebugCategory.BROWSER_SDK, "Wallet registered", {
171
+ name: wallet.name,
172
+ chains: wallet.chains,
173
+ featureKeys,
174
+ totalWallets: registeredWalletsSet.size
175
+ });
176
+ }
177
+ function removeRegisteredWallet(wallet) {
178
+ cachedWalletsArray = void 0;
179
+ registeredWalletsSet.delete(wallet);
180
+ }
181
+ function getRegisteredWallets() {
182
+ if (!cachedWalletsArray) {
183
+ cachedWalletsArray = [...registeredWalletsSet];
184
+ }
185
+ return cachedWalletsArray;
186
+ }
187
+ function register(...wallets2) {
188
+ wallets2 = wallets2.filter((wallet) => !registeredWalletsSet.has(wallet));
189
+ if (!wallets2.length) {
190
+ return () => {
191
+ };
192
+ }
193
+ wallets2.forEach((wallet) => addRegisteredWallet(wallet));
194
+ return function unregister() {
195
+ wallets2.forEach((wallet) => removeRegisteredWallet(wallet));
196
+ };
197
+ }
198
+ const registerAPI = Object.freeze({ register });
199
+ const handleRegisterWalletEvent = (event) => {
200
+ const callback = event.detail;
201
+ if (typeof callback === "function") {
202
+ try {
203
+ callback(registerAPI);
204
+ } catch (error) {
205
+ debug.warn(DebugCategory.BROWSER_SDK, "Error calling wallet registration callback", { error });
206
+ }
207
+ }
208
+ };
209
+ try {
210
+ window.addEventListener("wallet-standard:register-wallet", handleRegisterWalletEvent);
211
+ } catch (error) {
212
+ debug.warn(DebugCategory.BROWSER_SDK, "Could not add register-wallet event listener", { error });
213
+ }
214
+ class AppReadyEvent extends Event {
215
+ constructor(api) {
216
+ super("wallet-standard:app-ready", {
217
+ bubbles: false,
218
+ cancelable: false,
219
+ composed: false
220
+ });
221
+ this.detail = api;
222
+ }
223
+ }
224
+ try {
225
+ window.dispatchEvent(new AppReadyEvent(registerAPI));
226
+ debug.log(DebugCategory.BROWSER_SDK, "Dispatched wallet-standard:app-ready event");
227
+ } catch (error) {
228
+ debug.warn(DebugCategory.BROWSER_SDK, "Could not dispatch app-ready event", { error });
229
+ }
230
+ const walletsAPI = {
231
+ getWallets: () => {
232
+ return {
233
+ get: getRegisteredWallets,
234
+ on: (_event, _listener) => {
235
+ return () => {
236
+ };
237
+ },
238
+ register
239
+ };
240
+ }
241
+ };
242
+ if (!navigator.wallets) {
243
+ navigator.wallets = walletsAPI;
244
+ }
245
+ debug.log(DebugCategory.BROWSER_SDK, "Initialized Wallet Standard registry");
246
+ await new Promise((resolve) => setTimeout(resolve, 100));
247
+ const existingWalletsAPI = navigator.wallets || window.wallets;
248
+ if (!existingWalletsAPI || typeof existingWalletsAPI.getWallets !== "function") {
249
+ const logData = {
250
+ hasNavigator: !!navigator,
251
+ hasWindow: typeof window !== "undefined",
252
+ note: "Wallet Standard API not properly initialized"
253
+ };
254
+ debug.log(DebugCategory.BROWSER_SDK, "Wallet Standard API not available", logData);
255
+ return wallets;
256
+ }
257
+ const walletsGetter = existingWalletsAPI.getWallets();
258
+ const getWalletsFn = () => Promise.resolve([...walletsGetter.get()]);
259
+ debug.log(DebugCategory.BROWSER_SDK, "Wallet Standard API detected, starting discovery");
260
+ try {
261
+ let registeredWallets = [];
262
+ let attempts = 0;
263
+ const maxAttempts = 5;
264
+ const initialDelay = 100;
265
+ const eip6963Timeout = 400;
266
+ await new Promise((resolve) => setTimeout(resolve, initialDelay));
267
+ while (attempts < maxAttempts) {
268
+ registeredWallets = await getWalletsFn();
269
+ const logData = {
270
+ attempt: attempts + 1,
271
+ walletCount: registeredWallets.length,
272
+ walletNames: registeredWallets.map((w) => w.name),
273
+ chains: registeredWallets.flatMap((w) => w.chains)
274
+ };
275
+ debug.log(DebugCategory.BROWSER_SDK, `Wallet Standard getWallets attempt ${attempts + 1}`, logData);
276
+ if (registeredWallets.length > 0 || attempts === maxAttempts - 1) {
277
+ break;
278
+ }
279
+ await new Promise((resolve) => setTimeout(resolve, initialDelay));
280
+ attempts++;
281
+ }
282
+ const totalWaitTime = initialDelay + attempts * initialDelay;
283
+ if (totalWaitTime < eip6963Timeout) {
284
+ const remainingWait = eip6963Timeout - totalWaitTime;
285
+ await new Promise((resolve) => setTimeout(resolve, remainingWait));
286
+ registeredWallets = await getWalletsFn();
287
+ }
288
+ debug.log(DebugCategory.BROWSER_SDK, "Wallet Standard getWallets final result", {
289
+ walletCount: registeredWallets.length,
290
+ walletNames: registeredWallets.map((w) => w.name),
291
+ attempts: attempts + 1
292
+ });
293
+ for (const wallet of registeredWallets) {
294
+ const supportsSolana = wallet.chains.some((chain) => {
295
+ const chainLower = chain.toLowerCase();
296
+ return chainLower.startsWith("solana:") || chainLower === "solana";
297
+ }) || wallet.features && typeof wallet.features === "object" && Object.keys(wallet.features).some((featureKey) => {
298
+ const featureLower = featureKey.toLowerCase();
299
+ return featureLower.includes("solana") || featureLower.includes("standard:connect") || featureLower.includes("standard:signTransaction");
300
+ });
301
+ if (!supportsSolana) {
302
+ const featureKeys = wallet.features ? Object.keys(wallet.features) : [];
303
+ debug.log(DebugCategory.BROWSER_SDK, "Wallet does not support Solana", {
304
+ walletName: wallet.name,
305
+ chains: wallet.chains,
306
+ featureKeys
307
+ });
308
+ continue;
309
+ }
310
+ if (wallet.name.toLowerCase().includes("phantom")) {
311
+ debug.log(DebugCategory.BROWSER_SDK, "Skipping Phantom from Wallet Standard (handled separately)");
312
+ continue;
313
+ }
314
+ const walletId = generateWalletIdFromName(wallet.name);
315
+ const safeFeatures = wallet.features ? Object.keys(wallet.features) : [];
316
+ debug.log(DebugCategory.BROWSER_SDK, "Discovered Wallet Standard Solana wallet", {
317
+ walletId,
318
+ walletName: wallet.name,
319
+ chains: wallet.chains,
320
+ featureKeys: safeFeatures,
321
+ icon: wallet.icon,
322
+ version: wallet.version,
323
+ accountCount: wallet.accounts?.length || 0
324
+ });
325
+ wallets.push({
326
+ id: walletId,
327
+ name: wallet.name,
328
+ icon: wallet.icon,
329
+ addressTypes: [ClientAddressType.solana],
330
+ providers: {
331
+ // Cast to ISolanaChain - Wallet Standard wallets have compatible methods
332
+ // The InjectedWalletSolanaChain wrapper will handle the actual method calls
333
+ solana: wallet
334
+ }
335
+ });
336
+ }
337
+ } catch (error) {
338
+ debug.warn(DebugCategory.BROWSER_SDK, "Wallet Standard API error", {
339
+ error: error instanceof Error ? error.message : String(error),
340
+ stack: error instanceof Error ? error.stack : void 0
341
+ });
342
+ }
343
+ const finalLogData = {
344
+ discoveredCount: wallets.length,
345
+ walletIds: wallets.map((w) => w.id),
346
+ walletNames: wallets.map((w) => w.name)
347
+ };
348
+ debug.log(DebugCategory.BROWSER_SDK, "Wallet Standard Solana discovery completed", finalLogData);
349
+ return wallets;
350
+ }
351
+ function discoverPhantomWallet(addressTypes) {
352
+ if (typeof window === "undefined") {
353
+ return null;
354
+ }
355
+ if (!isPhantomExtensionInstalled()) {
356
+ return null;
357
+ }
358
+ const plugins = [createExtensionPlugin()];
359
+ if (addressTypes.includes(ClientAddressType.solana)) {
360
+ plugins.push(createSolanaPlugin());
361
+ }
362
+ if (addressTypes.includes(ClientAddressType.ethereum)) {
363
+ plugins.push(createEthereumPlugin());
364
+ }
365
+ plugins.push(createAutoConfirmPlugin());
366
+ const phantomInstance = createPhantom({ plugins });
367
+ return {
368
+ id: "phantom",
369
+ name: "Phantom",
370
+ icon: void 0,
371
+ // Icon will be rendered from icons package in UI components
372
+ addressTypes,
373
+ providers: {
374
+ solana: addressTypes.includes(ClientAddressType.solana) ? phantomInstance.solana : void 0,
375
+ ethereum: addressTypes.includes(ClientAddressType.ethereum) ? phantomInstance.ethereum : void 0
376
+ },
377
+ isPhantom: true,
378
+ phantomInstance
379
+ };
380
+ }
381
+ async function discoverWallets(addressTypes) {
382
+ const requestedAddressTypes = addressTypes || [];
383
+ debug.log(DebugCategory.BROWSER_SDK, "Starting all wallet discovery methods", {
384
+ addressTypes: requestedAddressTypes
385
+ });
386
+ const [solanaWallets, ethereumWallets] = await Promise.all([discoverSolanaWallets(), discoverEthereumWallets()]);
387
+ const phantomWallet = discoverPhantomWallet(requestedAddressTypes);
388
+ debug.log(DebugCategory.BROWSER_SDK, "All wallet discovery methods completed", {
389
+ phantomFound: !!phantomWallet,
390
+ solanaWalletsCount: solanaWallets.length,
391
+ ethereumWalletsCount: ethereumWallets.length,
392
+ solanaWalletIds: solanaWallets.map((w) => w.id),
393
+ ethereumWalletIds: ethereumWallets.map((w) => w.id)
394
+ });
395
+ const walletMap = /* @__PURE__ */ new Map();
396
+ if (phantomWallet) {
397
+ walletMap.set("phantom", phantomWallet);
398
+ }
399
+ for (const wallet of [...solanaWallets, ...ethereumWallets]) {
400
+ const existing = walletMap.get(wallet.id);
401
+ if (existing) {
402
+ const mergedAddressTypes = Array.from(/* @__PURE__ */ new Set([...existing.addressTypes, ...wallet.addressTypes]));
403
+ const mergedProviders = {
404
+ ...existing.providers,
405
+ ...wallet.providers
406
+ };
407
+ const mergedWallet = {
408
+ ...existing,
409
+ addressTypes: mergedAddressTypes,
410
+ // Prefer icon from the most recent discovery
411
+ icon: wallet.icon || existing.icon,
412
+ providers: mergedProviders
413
+ };
414
+ walletMap.set(wallet.id, mergedWallet);
415
+ debug.log(DebugCategory.BROWSER_SDK, "Merged wallet by ID", {
416
+ walletName: wallet.name,
417
+ walletId: wallet.id,
418
+ existingAddressTypes: existing.addressTypes,
419
+ newAddressTypes: wallet.addressTypes,
420
+ mergedAddressTypes,
421
+ existingProviders: Object.keys(existing.providers || {}),
422
+ newProviders: Object.keys(wallet.providers || {}),
423
+ mergedProviders: Object.keys(mergedProviders)
424
+ });
425
+ debug.log(DebugCategory.BROWSER_SDK, "Merged wallet from multiple discovery methods", {
426
+ walletId: wallet.id,
427
+ walletName: wallet.name,
428
+ existingAddressTypes: existing.addressTypes,
429
+ newAddressTypes: wallet.addressTypes,
430
+ mergedAddressTypes
431
+ });
432
+ } else {
433
+ walletMap.set(wallet.id, wallet);
434
+ }
435
+ }
436
+ return Array.from(walletMap.values());
437
+ }
438
+
439
+ // src/providers/injected/chains/InjectedWalletSolanaChain.ts
440
+ import { EventEmitter } from "eventemitter3";
441
+ import { Buffer as Buffer2 } from "buffer";
442
+ var InjectedWalletSolanaChain = class {
443
+ constructor(provider, walletId, walletName) {
444
+ this.eventEmitter = new EventEmitter();
445
+ this._connected = false;
446
+ this._publicKey = null;
447
+ this.provider = provider;
448
+ this.walletId = walletId;
449
+ this.walletName = walletName;
450
+ this.setupEventListeners();
451
+ }
452
+ get connected() {
453
+ return this._connected;
454
+ }
455
+ get publicKey() {
456
+ return this._publicKey;
457
+ }
458
+ async connect(options) {
459
+ debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Solana connect", {
460
+ walletId: this.walletId,
461
+ walletName: this.walletName,
462
+ onlyIfTrusted: options?.onlyIfTrusted
463
+ });
464
+ try {
465
+ const result = await this.provider.connect(options);
466
+ if (typeof result === "string") {
467
+ this._connected = true;
468
+ this._publicKey = result;
469
+ debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Solana connected", {
470
+ walletId: this.walletId,
471
+ walletName: this.walletName,
472
+ publicKey: result
473
+ });
474
+ return { publicKey: result };
475
+ }
476
+ if (typeof result === "object" && result !== null && "publicKey" in result) {
477
+ this._connected = true;
478
+ this._publicKey = result.publicKey;
479
+ debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Solana connected", {
480
+ walletId: this.walletId,
481
+ walletName: this.walletName,
482
+ publicKey: result.publicKey
483
+ });
484
+ return result;
485
+ }
486
+ if (Array.isArray(result) && result.length > 0) {
487
+ const firstAccount = result[0];
488
+ if (typeof firstAccount === "object" && firstAccount !== null && "address" in firstAccount) {
489
+ this._connected = true;
490
+ this._publicKey = firstAccount.address;
491
+ debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Solana connected", {
492
+ walletId: this.walletId,
493
+ walletName: this.walletName,
494
+ publicKey: firstAccount.address
495
+ });
496
+ return { publicKey: firstAccount.address };
497
+ }
498
+ }
499
+ throw new Error("Unexpected connect result format");
500
+ } catch (error) {
501
+ debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Solana connect failed", {
502
+ walletId: this.walletId,
503
+ walletName: this.walletName,
504
+ error: error instanceof Error ? error.message : String(error)
505
+ });
506
+ throw error;
507
+ }
508
+ }
509
+ async disconnect() {
510
+ debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Solana disconnect", {
511
+ walletId: this.walletId,
512
+ walletName: this.walletName
513
+ });
514
+ try {
515
+ await this.provider.disconnect();
516
+ this._connected = false;
517
+ this._publicKey = null;
518
+ debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Solana disconnected", {
519
+ walletId: this.walletId,
520
+ walletName: this.walletName
521
+ });
522
+ } catch (error) {
523
+ debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Solana disconnect failed", {
524
+ walletId: this.walletId,
525
+ walletName: this.walletName,
526
+ error: error instanceof Error ? error.message : String(error)
527
+ });
528
+ throw error;
529
+ }
530
+ }
531
+ async signMessage(message) {
532
+ const messageBytes = typeof message === "string" ? new TextEncoder().encode(message) : message;
533
+ const messagePreview = typeof message === "string" ? message.substring(0, 50) : `${messageBytes.length} bytes`;
534
+ debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signMessage", {
535
+ walletId: this.walletId,
536
+ walletName: this.walletName,
537
+ messagePreview,
538
+ messageLength: messageBytes.length
539
+ });
540
+ try {
541
+ const result = await this.provider.signMessage(message);
542
+ debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signMessage success", {
543
+ walletId: this.walletId,
544
+ walletName: this.walletName,
545
+ signatureLength: result.signature.length
546
+ });
547
+ return {
548
+ signature: result.signature instanceof Uint8Array ? result.signature : new Uint8Array(Buffer2.from(result.signature, "base64")),
549
+ publicKey: result.publicKey || this._publicKey || ""
550
+ };
551
+ } catch (error) {
552
+ debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signMessage failed", {
553
+ walletId: this.walletId,
554
+ walletName: this.walletName,
555
+ error: error instanceof Error ? error.message : String(error)
556
+ });
557
+ throw error;
558
+ }
559
+ }
560
+ async signTransaction(transaction) {
561
+ debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signTransaction", {
562
+ walletId: this.walletId,
563
+ walletName: this.walletName
564
+ });
565
+ try {
566
+ const result = await this.provider.signTransaction(transaction);
567
+ debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signTransaction success", {
568
+ walletId: this.walletId,
569
+ walletName: this.walletName
570
+ });
571
+ return result;
572
+ } catch (error) {
573
+ debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signTransaction failed", {
574
+ walletId: this.walletId,
575
+ walletName: this.walletName,
576
+ error: error instanceof Error ? error.message : String(error)
577
+ });
578
+ throw error;
579
+ }
580
+ }
581
+ async signAndSendTransaction(transaction) {
582
+ debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signAndSendTransaction", {
583
+ walletId: this.walletId,
584
+ walletName: this.walletName
585
+ });
586
+ try {
587
+ const result = await this.provider.signAndSendTransaction(transaction);
588
+ debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signAndSendTransaction success", {
589
+ walletId: this.walletId,
590
+ walletName: this.walletName,
591
+ signature: result.signature
592
+ });
593
+ return result;
594
+ } catch (error) {
595
+ debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signAndSendTransaction failed", {
596
+ walletId: this.walletId,
597
+ walletName: this.walletName,
598
+ error: error instanceof Error ? error.message : String(error)
599
+ });
600
+ throw error;
601
+ }
602
+ }
603
+ async signAllTransactions(transactions) {
604
+ debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signAllTransactions", {
605
+ walletId: this.walletId,
606
+ walletName: this.walletName,
607
+ transactionCount: transactions.length
608
+ });
609
+ try {
610
+ const result = await this.provider.signAllTransactions(transactions);
611
+ debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signAllTransactions success", {
612
+ walletId: this.walletId,
613
+ walletName: this.walletName,
614
+ signedCount: result.length
615
+ });
616
+ return result;
617
+ } catch (error) {
618
+ debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signAllTransactions failed", {
619
+ walletId: this.walletId,
620
+ walletName: this.walletName,
621
+ error: error instanceof Error ? error.message : String(error)
622
+ });
623
+ throw error;
624
+ }
625
+ }
626
+ async signAndSendAllTransactions(transactions) {
627
+ debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signAndSendAllTransactions", {
628
+ walletId: this.walletId,
629
+ walletName: this.walletName,
630
+ transactionCount: transactions.length
631
+ });
632
+ try {
633
+ const result = await this.provider.signAndSendAllTransactions(transactions);
634
+ debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signAndSendAllTransactions success", {
635
+ walletId: this.walletId,
636
+ walletName: this.walletName,
637
+ signatureCount: result.signatures.length
638
+ });
639
+ return result;
640
+ } catch (error) {
641
+ debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signAndSendAllTransactions failed", {
642
+ walletId: this.walletId,
643
+ walletName: this.walletName,
644
+ error: error instanceof Error ? error.message : String(error)
645
+ });
646
+ throw error;
647
+ }
648
+ }
649
+ switchNetwork(_network) {
650
+ return Promise.resolve();
651
+ }
652
+ getPublicKey() {
653
+ return Promise.resolve(this._publicKey);
654
+ }
655
+ isConnected() {
656
+ return this._connected;
657
+ }
658
+ setupEventListeners() {
659
+ if (typeof this.provider.on === "function") {
660
+ this.provider.on("connect", (publicKey) => {
661
+ this._connected = true;
662
+ this._publicKey = publicKey;
663
+ this.eventEmitter.emit("connect", publicKey);
664
+ });
665
+ this.provider.on("disconnect", () => {
666
+ this._connected = false;
667
+ this._publicKey = null;
668
+ this.eventEmitter.emit("disconnect");
669
+ });
670
+ this.provider.on("accountChanged", (publicKey) => {
671
+ this._publicKey = publicKey;
672
+ this.eventEmitter.emit("accountChanged", publicKey);
673
+ });
674
+ }
675
+ }
676
+ on(event, listener) {
677
+ this.eventEmitter.on(event, listener);
678
+ }
679
+ off(event, listener) {
680
+ this.eventEmitter.off(event, listener);
681
+ }
682
+ };
683
+
684
+ // src/providers/injected/chains/WalletStandardSolanaAdapter.ts
685
+ import { deserializeSolanaTransaction } from "@phantom/parsers";
686
+ import bs58 from "bs58";
687
+ var WalletStandardSolanaAdapter = class {
688
+ constructor(wallet, walletId, walletName) {
689
+ this._connected = false;
690
+ this._publicKey = null;
691
+ this.wallet = wallet;
692
+ this.walletId = walletId;
693
+ this.walletName = walletName;
694
+ }
695
+ get connected() {
696
+ return this._connected;
697
+ }
698
+ get publicKey() {
699
+ return this._publicKey;
700
+ }
701
+ async connect(_options) {
702
+ try {
703
+ const connectFeature = this.wallet.features?.["standard:connect"];
704
+ if (!connectFeature || typeof connectFeature.connect !== "function") {
705
+ throw new Error("Wallet Standard connect feature not available");
706
+ }
707
+ const connectResult = await connectFeature.connect();
708
+ let accounts;
709
+ if (Array.isArray(connectResult) && connectResult.length > 0) {
710
+ accounts = connectResult;
711
+ } else if (this.wallet.accounts && this.wallet.accounts.length > 0) {
712
+ accounts = Array.from(this.wallet.accounts);
713
+ }
714
+ if (!accounts || accounts.length === 0) {
715
+ throw new Error("No accounts available after connecting to wallet");
716
+ }
717
+ const firstAccount = accounts[0];
718
+ if (!firstAccount) {
719
+ throw new Error("First account is null or undefined");
720
+ }
721
+ let address;
722
+ if (typeof firstAccount === "string") {
723
+ address = firstAccount;
724
+ } else if (typeof firstAccount === "object" && firstAccount !== null) {
725
+ address = firstAccount.address || firstAccount.publicKey?.toString() || (firstAccount.publicKey instanceof Uint8Array ? Buffer.from(firstAccount.publicKey).toString("hex") : void 0);
726
+ }
727
+ if (!address) {
728
+ throw new Error(
729
+ `Could not extract address from account. Account structure: ${JSON.stringify(firstAccount, null, 2)}`
730
+ );
731
+ }
732
+ this._connected = true;
733
+ this._publicKey = address;
734
+ return { publicKey: address };
735
+ } catch (error) {
736
+ debug.error(DebugCategory.INJECTED_PROVIDER, "Wallet Standard Solana connect failed", {
737
+ walletId: this.walletId,
738
+ walletName: this.walletName,
739
+ error: error instanceof Error ? error.message : String(error)
740
+ });
741
+ throw error;
742
+ }
743
+ }
744
+ async disconnect() {
745
+ try {
746
+ const disconnectFeature = this.wallet.features?.["standard:disconnect"];
747
+ if (disconnectFeature && typeof disconnectFeature.disconnect === "function") {
748
+ await disconnectFeature.disconnect();
749
+ }
750
+ this._connected = false;
751
+ this._publicKey = null;
752
+ } catch (error) {
753
+ debug.error(DebugCategory.INJECTED_PROVIDER, "Wallet Standard Solana disconnect failed", {
754
+ walletId: this.walletId,
755
+ walletName: this.walletName,
756
+ error: error instanceof Error ? error.message : String(error)
757
+ });
758
+ throw error;
759
+ }
760
+ }
761
+ async signMessage(message) {
762
+ try {
763
+ const signMessageFeature = this.wallet.features?.["solana:signMessage"];
764
+ if (!signMessageFeature || typeof signMessageFeature.signMessage !== "function") {
765
+ throw new Error("Wallet Standard signMessage feature not available");
766
+ }
767
+ const messageBytes = typeof message === "string" ? new TextEncoder().encode(message) : message;
768
+ const result = await signMessageFeature.signMessage({
769
+ message: messageBytes,
770
+ account: this.wallet.accounts?.[0]
771
+ });
772
+ if (!Array.isArray(result) || result.length === 0) {
773
+ throw new Error(`Expected array result from signMessage, got: ${typeof result}`);
774
+ }
775
+ const signedMessageResult = result[0];
776
+ if (!signedMessageResult || !signedMessageResult.signature) {
777
+ throw new Error(`Invalid signMessage result structure: ${JSON.stringify(result)}`);
778
+ }
779
+ const signature = this.parseUint8Array(signedMessageResult.signature);
780
+ if (signature.length === 0) {
781
+ throw new Error(`Signature is empty`);
782
+ }
783
+ const publicKey = signedMessageResult.account?.address || this.wallet.accounts?.[0]?.address || this._publicKey || "";
784
+ return { signature, publicKey };
785
+ } catch (error) {
786
+ debug.error(DebugCategory.INJECTED_PROVIDER, "Wallet Standard Solana signMessage failed", {
787
+ walletId: this.walletId,
788
+ walletName: this.walletName,
789
+ error: error instanceof Error ? error.message : String(error)
790
+ });
791
+ throw error;
792
+ }
793
+ }
794
+ async signTransaction(transaction) {
795
+ try {
796
+ const signTransactionFeature = this.wallet.features?.["solana:signTransaction"];
797
+ if (!signTransactionFeature || typeof signTransactionFeature.signTransaction !== "function") {
798
+ throw new Error("Wallet Standard signTransaction feature not available");
799
+ }
800
+ if (!this.wallet.accounts || this.wallet.accounts.length === 0) {
801
+ throw new Error("No accounts available. Please connect first.");
802
+ }
803
+ const account = this.wallet.accounts[0];
804
+ const serializedTransaction = this.serializeTransaction(transaction);
805
+ const results = await signTransactionFeature.signTransaction({
806
+ transaction: serializedTransaction,
807
+ account
808
+ });
809
+ let transactionData;
810
+ if (Array.isArray(results) && results.length > 0) {
811
+ const firstItem = results[0];
812
+ if (firstItem && typeof firstItem === "object") {
813
+ transactionData = firstItem.signedTransaction || firstItem.transaction;
814
+ }
815
+ } else if (results && typeof results === "object" && !Array.isArray(results)) {
816
+ transactionData = results.transaction || results.signedTransaction;
817
+ }
818
+ if (!transactionData) {
819
+ throw new Error("No transaction data found in Wallet Standard result");
820
+ }
821
+ const signedBytes = this.parseUint8Array(transactionData);
822
+ if (signedBytes.length === 0) {
823
+ throw new Error("Empty signed transaction returned from Wallet Standard");
824
+ }
825
+ const signedTx = deserializeSolanaTransaction(signedBytes);
826
+ return signedTx;
827
+ } catch (error) {
828
+ debug.error(DebugCategory.INJECTED_PROVIDER, "Wallet Standard Solana signTransaction failed", {
829
+ walletId: this.walletId,
830
+ walletName: this.walletName,
831
+ error: error instanceof Error ? error.message : String(error)
832
+ });
833
+ throw error;
834
+ }
835
+ }
836
+ async signAndSendTransaction(transaction) {
837
+ try {
838
+ const signAndSendTransactionFeature = this.wallet.features?.["solana:signAndSendTransaction"];
839
+ if (!signAndSendTransactionFeature || typeof signAndSendTransactionFeature.signAndSendTransaction !== "function") {
840
+ throw new Error("Wallet Standard signAndSendTransaction feature not available");
841
+ }
842
+ if (!this.wallet.accounts || this.wallet.accounts.length === 0) {
843
+ throw new Error("No accounts available. Please connect first.");
844
+ }
845
+ const account = this.wallet.accounts[0];
846
+ const chain = account.chains?.[0] || "solana:mainnet";
847
+ const serializedTransaction = this.serializeTransaction(transaction);
848
+ const results = await signAndSendTransactionFeature.signAndSendTransaction({
849
+ transaction: serializedTransaction,
850
+ account,
851
+ chain
852
+ });
853
+ let signatureOutput;
854
+ if (Array.isArray(results) && results.length > 0) {
855
+ signatureOutput = results[0];
856
+ } else if (results && typeof results === "object" && !Array.isArray(results)) {
857
+ signatureOutput = results;
858
+ } else {
859
+ throw new Error("Invalid signAndSendTransaction result format");
860
+ }
861
+ if (!signatureOutput.signature) {
862
+ throw new Error("No signature found in signAndSendTransaction result");
863
+ }
864
+ const signatureBytes = this.parseUint8Array(signatureOutput.signature);
865
+ const signature = bs58.encode(signatureBytes);
866
+ return { signature };
867
+ } catch (error) {
868
+ debug.error(DebugCategory.INJECTED_PROVIDER, "Wallet Standard Solana signAndSendTransaction failed", {
869
+ walletId: this.walletId,
870
+ walletName: this.walletName,
871
+ error: error instanceof Error ? error.message : String(error)
872
+ });
873
+ throw error;
874
+ }
875
+ }
876
+ async signAllTransactions(transactions) {
877
+ try {
878
+ const signedTransactions = [];
879
+ for (const transaction of transactions) {
880
+ const signedTx = await this.signTransaction(transaction);
881
+ signedTransactions.push(signedTx);
882
+ }
883
+ return signedTransactions;
884
+ } catch (error) {
885
+ debug.error(DebugCategory.INJECTED_PROVIDER, "Wallet Standard Solana signAllTransactions failed", {
886
+ walletId: this.walletId,
887
+ walletName: this.walletName,
888
+ error: error instanceof Error ? error.message : String(error)
889
+ });
890
+ throw error;
891
+ }
892
+ }
893
+ async signAndSendAllTransactions(transactions) {
894
+ try {
895
+ const signatures = [];
896
+ for (const transaction of transactions) {
897
+ const result = await this.signAndSendTransaction(transaction);
898
+ signatures.push(result.signature);
899
+ }
900
+ return { signatures };
901
+ } catch (error) {
902
+ debug.error(DebugCategory.INJECTED_PROVIDER, "Wallet Standard Solana signAndSendAllTransactions failed", {
903
+ walletId: this.walletId,
904
+ walletName: this.walletName,
905
+ error: error instanceof Error ? error.message : String(error)
906
+ });
907
+ throw error;
908
+ }
909
+ }
910
+ async switchNetwork(network) {
911
+ try {
912
+ const switchNetworkFeature = this.wallet.features?.["standard:switchNetwork"];
913
+ if (switchNetworkFeature && typeof switchNetworkFeature.switchNetwork === "function") {
914
+ const chainId = network === "mainnet" ? "solana:mainnet" : "solana:devnet";
915
+ await switchNetworkFeature.switchNetwork({ chain: chainId });
916
+ }
917
+ } catch (error) {
918
+ debug.error(DebugCategory.INJECTED_PROVIDER, "Wallet Standard Solana switchNetwork failed", {
919
+ walletId: this.walletId,
920
+ walletName: this.walletName,
921
+ network,
922
+ error: error instanceof Error ? error.message : String(error)
923
+ });
924
+ throw error;
925
+ }
926
+ }
927
+ getPublicKey() {
928
+ return Promise.resolve(this._publicKey);
929
+ }
930
+ isConnected() {
931
+ return this._connected;
932
+ }
933
+ on(_event, _listener) {
934
+ const eventsFeature = this.wallet.features?.["standard:events"];
935
+ if (eventsFeature && typeof eventsFeature.on === "function") {
936
+ eventsFeature.on(_event, _listener);
937
+ }
938
+ }
939
+ off(_event, _listener) {
940
+ const eventsFeature = this.wallet.features?.["standard:events"];
941
+ if (eventsFeature && typeof eventsFeature.off === "function") {
942
+ eventsFeature.off(_event, _listener);
943
+ }
944
+ }
945
+ /**
946
+ * Serialize a transaction to Uint8Array for Wallet Standard API
947
+ */
948
+ serializeTransaction(transaction) {
949
+ if (typeof transaction.serialize === "function") {
950
+ return transaction.serialize({
951
+ requireAllSignatures: false,
952
+ verifySignatures: false
953
+ });
954
+ }
955
+ if (transaction instanceof Uint8Array) {
956
+ return transaction;
957
+ }
958
+ return new Uint8Array(0);
959
+ }
960
+ /**
961
+ * Parse a Uint8Array from various formats
962
+ * Handles: Uint8Array, Array, object with numeric keys (JSON-serialized Uint8Array)
963
+ */
964
+ parseUint8Array(value) {
965
+ if (value instanceof Uint8Array) {
966
+ return value;
967
+ }
968
+ if (Array.isArray(value)) {
969
+ return new Uint8Array(value);
970
+ }
971
+ if (typeof value === "object" && value !== null) {
972
+ const keys = Object.keys(value).map(Number).filter((k) => !isNaN(k) && k >= 0).sort((a, b) => a - b);
973
+ if (keys.length > 0) {
974
+ const maxKey = Math.max(...keys);
975
+ const array = new Uint8Array(maxKey + 1);
976
+ for (const key of keys) {
977
+ array[key] = Number(value[key]) || 0;
978
+ }
979
+ return array;
980
+ }
981
+ }
982
+ return new Uint8Array(0);
983
+ }
984
+ };
985
+
986
+ // src/providers/injected/chains/InjectedWalletEthereumChain.ts
987
+ import { EventEmitter as EventEmitter2 } from "eventemitter3";
988
+ var InjectedWalletEthereumChain = class {
989
+ constructor(provider, walletId, walletName) {
990
+ this.eventEmitter = new EventEmitter2();
991
+ this._connected = false;
992
+ this._chainId = "0x1";
993
+ this._accounts = [];
994
+ this.provider = provider;
995
+ this.walletId = walletId;
996
+ this.walletName = walletName;
997
+ this.setupEventListeners();
998
+ }
999
+ get connected() {
1000
+ return this._connected;
1001
+ }
1002
+ get chainId() {
1003
+ return this._chainId;
1004
+ }
1005
+ get accounts() {
1006
+ return this._accounts;
1007
+ }
1008
+ async request(args) {
1009
+ debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum request", {
1010
+ walletId: this.walletId,
1011
+ walletName: this.walletName,
1012
+ method: args.method
1013
+ });
1014
+ try {
1015
+ const requiresAuth = [
1016
+ "personal_sign",
1017
+ "eth_sign",
1018
+ "eth_signTypedData",
1019
+ "eth_signTypedData_v4",
1020
+ "eth_sendTransaction",
1021
+ "eth_signTransaction"
1022
+ ].includes(args.method);
1023
+ if (requiresAuth && (!this._connected || this._accounts.length === 0)) {
1024
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Method requires authorization, ensuring connection", {
1025
+ walletId: this.walletId,
1026
+ walletName: this.walletName,
1027
+ method: args.method
1028
+ });
1029
+ await this.connect();
1030
+ }
1031
+ const result = await this.provider.request(args);
1032
+ debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum request success", {
1033
+ walletId: this.walletId,
1034
+ walletName: this.walletName,
1035
+ method: args.method
1036
+ });
1037
+ return result;
1038
+ } catch (error) {
1039
+ if (error?.code === 4100) {
1040
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Got 4100 Unauthorized, attempting to re-authorize", {
1041
+ walletId: this.walletId,
1042
+ walletName: this.walletName,
1043
+ method: args.method
1044
+ });
1045
+ try {
1046
+ await this.provider.request({ method: "eth_requestAccounts" });
1047
+ const result = await this.provider.request(args);
1048
+ debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum request success (after re-auth)", {
1049
+ walletId: this.walletId,
1050
+ walletName: this.walletName,
1051
+ method: args.method
1052
+ });
1053
+ return result;
1054
+ } catch (retryError) {
1055
+ debug.error(DebugCategory.INJECTED_PROVIDER, "Failed after re-authorization", {
1056
+ walletId: this.walletId,
1057
+ walletName: this.walletName,
1058
+ method: args.method,
1059
+ error: retryError instanceof Error ? retryError.message : String(retryError)
1060
+ });
1061
+ throw retryError;
1062
+ }
1063
+ }
1064
+ debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum request failed", {
1065
+ walletId: this.walletId,
1066
+ walletName: this.walletName,
1067
+ method: args.method,
1068
+ error: error instanceof Error ? error.message : String(error),
1069
+ errorCode: error?.code
1070
+ });
1071
+ throw error;
1072
+ }
1073
+ }
1074
+ async connect() {
1075
+ debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum connect", {
1076
+ walletId: this.walletId,
1077
+ walletName: this.walletName
1078
+ });
1079
+ try {
1080
+ const accounts = await this.provider.request({ method: "eth_requestAccounts" });
1081
+ this._connected = accounts.length > 0;
1082
+ this._accounts = accounts;
1083
+ debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum connected (via eth_requestAccounts)", {
1084
+ walletId: this.walletId,
1085
+ walletName: this.walletName,
1086
+ accountCount: accounts.length,
1087
+ accounts
1088
+ });
1089
+ return accounts;
1090
+ } catch (error) {
1091
+ debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum connect failed", {
1092
+ walletId: this.walletId,
1093
+ walletName: this.walletName,
1094
+ error: error instanceof Error ? error.message : String(error)
1095
+ });
1096
+ throw error;
1097
+ }
1098
+ }
1099
+ async disconnect() {
1100
+ debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum disconnect", {
1101
+ walletId: this.walletId,
1102
+ walletName: this.walletName
1103
+ });
1104
+ try {
1105
+ await this.provider.disconnect();
1106
+ this._connected = false;
1107
+ this._accounts = [];
1108
+ debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum disconnected", {
1109
+ walletId: this.walletId,
1110
+ walletName: this.walletName
1111
+ });
1112
+ } catch (error) {
1113
+ debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum disconnect failed", {
1114
+ walletId: this.walletId,
1115
+ walletName: this.walletName,
1116
+ error: error instanceof Error ? error.message : String(error)
1117
+ });
1118
+ throw error;
1119
+ }
31
1120
  }
32
- setCallback(callback) {
33
- this.callback = callback;
1121
+ async signPersonalMessage(message, address) {
1122
+ const messagePreview = message.length > 50 ? message.substring(0, 50) + "..." : message;
1123
+ debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum signPersonalMessage", {
1124
+ walletId: this.walletId,
1125
+ walletName: this.walletName,
1126
+ messagePreview,
1127
+ messageLength: message.length,
1128
+ address
1129
+ });
1130
+ try {
1131
+ const providerConnected = this.provider.isConnected?.() || this.provider.connected || false;
1132
+ if (!this._connected || this._accounts.length === 0 || !providerConnected) {
1133
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Not connected, attempting to connect before signing", {
1134
+ walletId: this.walletId,
1135
+ walletName: this.walletName,
1136
+ internalConnected: this._connected,
1137
+ accountsLength: this._accounts.length,
1138
+ providerConnected
1139
+ });
1140
+ await this.connect();
1141
+ }
1142
+ const normalizedAddress = address.toLowerCase();
1143
+ const normalizedAccounts = this._accounts.map((acc) => acc.toLowerCase());
1144
+ if (!normalizedAccounts.includes(normalizedAddress)) {
1145
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Address not in connected accounts, refreshing connection", {
1146
+ walletId: this.walletId,
1147
+ walletName: this.walletName,
1148
+ requestedAddress: address,
1149
+ connectedAccounts: this._accounts
1150
+ });
1151
+ const currentAccounts = await this.getAccounts();
1152
+ const normalizedCurrentAccounts = currentAccounts.map((acc) => acc.toLowerCase());
1153
+ if (!normalizedCurrentAccounts.includes(normalizedAddress)) {
1154
+ throw new Error(`Address ${address} is not connected. Connected accounts: ${currentAccounts.join(", ")}`);
1155
+ }
1156
+ this._accounts = currentAccounts;
1157
+ }
1158
+ if (typeof this.provider.signPersonalMessage === "function") {
1159
+ const result2 = await this.provider.signPersonalMessage(message, address);
1160
+ debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum signPersonalMessage success", {
1161
+ walletId: this.walletId,
1162
+ walletName: this.walletName,
1163
+ signatureLength: result2.length
1164
+ });
1165
+ return result2;
1166
+ }
1167
+ const result = await this.request({
1168
+ method: "personal_sign",
1169
+ params: [message, address]
1170
+ });
1171
+ debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum signPersonalMessage success", {
1172
+ walletId: this.walletId,
1173
+ walletName: this.walletName,
1174
+ signatureLength: result.length
1175
+ });
1176
+ return result;
1177
+ } catch (error) {
1178
+ debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum signPersonalMessage failed", {
1179
+ walletId: this.walletId,
1180
+ walletName: this.walletName,
1181
+ error: error instanceof Error ? error.message : String(error),
1182
+ errorCode: error?.code
1183
+ });
1184
+ throw error;
1185
+ }
34
1186
  }
35
- setLevel(level) {
36
- this.level = level;
1187
+ async signTypedData(typedData, address) {
1188
+ debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum signTypedData", {
1189
+ walletId: this.walletId,
1190
+ walletName: this.walletName,
1191
+ primaryType: typedData?.primaryType,
1192
+ address
1193
+ });
1194
+ try {
1195
+ if (typeof this.provider.signTypedData === "function") {
1196
+ const result2 = await this.provider.signTypedData(typedData, address);
1197
+ debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum signTypedData success", {
1198
+ walletId: this.walletId,
1199
+ walletName: this.walletName,
1200
+ signatureLength: result2.length
1201
+ });
1202
+ return result2;
1203
+ }
1204
+ const result = await this.request({
1205
+ method: "eth_signTypedData_v4",
1206
+ params: [address, typedData]
1207
+ });
1208
+ debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum signTypedData success", {
1209
+ walletId: this.walletId,
1210
+ walletName: this.walletName,
1211
+ signatureLength: result.length
1212
+ });
1213
+ return result;
1214
+ } catch (error) {
1215
+ debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum signTypedData failed", {
1216
+ walletId: this.walletId,
1217
+ walletName: this.walletName,
1218
+ error: error instanceof Error ? error.message : String(error)
1219
+ });
1220
+ throw error;
1221
+ }
37
1222
  }
38
- enable() {
39
- this.enabled = true;
1223
+ async signTransaction(transaction) {
1224
+ debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum signTransaction", {
1225
+ walletId: this.walletId,
1226
+ walletName: this.walletName,
1227
+ from: transaction.from,
1228
+ to: transaction.to
1229
+ });
1230
+ try {
1231
+ if (typeof this.provider.signTransaction === "function") {
1232
+ const result2 = await this.provider.signTransaction(transaction);
1233
+ debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum signTransaction success", {
1234
+ walletId: this.walletId,
1235
+ walletName: this.walletName,
1236
+ signatureLength: result2.length
1237
+ });
1238
+ return result2;
1239
+ }
1240
+ const result = await this.request({
1241
+ method: "eth_signTransaction",
1242
+ params: [transaction]
1243
+ });
1244
+ debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum signTransaction success", {
1245
+ walletId: this.walletId,
1246
+ walletName: this.walletName,
1247
+ signatureLength: result.length
1248
+ });
1249
+ return result;
1250
+ } catch (error) {
1251
+ debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum signTransaction failed", {
1252
+ walletId: this.walletId,
1253
+ walletName: this.walletName,
1254
+ error: error instanceof Error ? error.message : String(error)
1255
+ });
1256
+ throw error;
1257
+ }
40
1258
  }
41
- disable() {
42
- this.enabled = false;
1259
+ async sendTransaction(transaction) {
1260
+ debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum sendTransaction", {
1261
+ walletId: this.walletId,
1262
+ walletName: this.walletName,
1263
+ from: transaction.from,
1264
+ to: transaction.to,
1265
+ value: transaction.value
1266
+ });
1267
+ try {
1268
+ if (typeof this.provider.sendTransaction === "function") {
1269
+ const result2 = await this.provider.sendTransaction(transaction);
1270
+ debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum sendTransaction success", {
1271
+ walletId: this.walletId,
1272
+ walletName: this.walletName,
1273
+ txHash: result2
1274
+ });
1275
+ return result2;
1276
+ }
1277
+ const result = await this.request({
1278
+ method: "eth_sendTransaction",
1279
+ params: [transaction]
1280
+ });
1281
+ debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum sendTransaction success", {
1282
+ walletId: this.walletId,
1283
+ walletName: this.walletName,
1284
+ txHash: result
1285
+ });
1286
+ return result;
1287
+ } catch (error) {
1288
+ debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum sendTransaction failed", {
1289
+ walletId: this.walletId,
1290
+ walletName: this.walletName,
1291
+ error: error instanceof Error ? error.message : String(error)
1292
+ });
1293
+ throw error;
1294
+ }
43
1295
  }
44
- writeLog(level, category, message, data) {
45
- if (!this.enabled || level > this.level) {
46
- return;
1296
+ async switchChain(chainId) {
1297
+ debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum switchChain", {
1298
+ walletId: this.walletId,
1299
+ walletName: this.walletName,
1300
+ chainId
1301
+ });
1302
+ try {
1303
+ const hexChainId = typeof chainId === "string" ? chainId.toLowerCase().startsWith("0x") ? chainId : `0x${parseInt(chainId, 10).toString(16)}` : `0x${chainId.toString(16)}`;
1304
+ if (typeof this.provider.switchChain === "function") {
1305
+ await this.provider.switchChain(hexChainId);
1306
+ } else {
1307
+ await this.request({ method: "wallet_switchEthereumChain", params: [{ chainId: hexChainId }] });
1308
+ }
1309
+ this._chainId = hexChainId;
1310
+ this.eventEmitter.emit("chainChanged", this._chainId);
1311
+ debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum switchChain success", {
1312
+ walletId: this.walletId,
1313
+ walletName: this.walletName,
1314
+ chainId: hexChainId
1315
+ });
1316
+ } catch (error) {
1317
+ debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum switchChain failed", {
1318
+ walletId: this.walletId,
1319
+ walletName: this.walletName,
1320
+ error: error instanceof Error ? error.message : String(error)
1321
+ });
1322
+ throw error;
47
1323
  }
48
- const debugMessage = {
49
- timestamp: Date.now(),
50
- level,
51
- category,
52
- message,
53
- data
54
- };
55
- if (this.callback) {
56
- this.callback(debugMessage);
1324
+ }
1325
+ async getChainId() {
1326
+ if (typeof this.provider.getChainId === "function") {
1327
+ const chainId2 = await this.provider.getChainId();
1328
+ this._chainId = `0x${chainId2.toString(16)}`;
1329
+ return chainId2;
57
1330
  }
1331
+ const chainId = await this.request({ method: "eth_chainId" });
1332
+ const parsed = parseInt(chainId, 16);
1333
+ this._chainId = chainId;
1334
+ return parsed;
58
1335
  }
59
- error(category, message, data) {
60
- this.writeLog(0 /* ERROR */, category, message, data);
1336
+ async getAccounts() {
1337
+ if (typeof this.provider.getAccounts === "function") {
1338
+ const accounts2 = await this.provider.getAccounts();
1339
+ this._accounts = accounts2;
1340
+ return accounts2;
1341
+ }
1342
+ const accounts = await this.request({ method: "eth_accounts" });
1343
+ this._accounts = accounts;
1344
+ return accounts;
61
1345
  }
62
- warn(category, message, data) {
63
- this.writeLog(1 /* WARN */, category, message, data);
1346
+ isConnected() {
1347
+ return this._connected;
64
1348
  }
65
- info(category, message, data) {
66
- this.writeLog(2 /* INFO */, category, message, data);
1349
+ setupEventListeners() {
1350
+ if (typeof this.provider.on === "function") {
1351
+ this.provider.on("connect", (info) => {
1352
+ this._connected = true;
1353
+ this._chainId = info.chainId;
1354
+ this.eventEmitter.emit("connect", info);
1355
+ });
1356
+ this.provider.on("disconnect", (error) => {
1357
+ this._connected = false;
1358
+ this._accounts = [];
1359
+ this.eventEmitter.emit("disconnect", error);
1360
+ this.eventEmitter.emit("accountsChanged", []);
1361
+ });
1362
+ this.provider.on("accountsChanged", (accounts) => {
1363
+ this._accounts = accounts;
1364
+ this.eventEmitter.emit("accountsChanged", accounts);
1365
+ });
1366
+ this.provider.on("chainChanged", (chainId) => {
1367
+ this._chainId = chainId;
1368
+ this.eventEmitter.emit("chainChanged", chainId);
1369
+ });
1370
+ }
67
1371
  }
68
- debug(category, message, data) {
69
- this.writeLog(3 /* DEBUG */, category, message, data);
1372
+ on(event, listener) {
1373
+ this.eventEmitter.on(event, listener);
70
1374
  }
71
- log(category, message, data) {
72
- this.writeLog(3 /* DEBUG */, category, message, data);
1375
+ off(event, listener) {
1376
+ this.eventEmitter.off(event, listener);
73
1377
  }
74
1378
  };
75
- var debug = Debug.getInstance();
76
- var DebugCategory = {
77
- BROWSER_SDK: "BrowserSDK",
78
- PROVIDER_MANAGER: "ProviderManager",
79
- EMBEDDED_PROVIDER: "EmbeddedProvider",
80
- INJECTED_PROVIDER: "InjectedProvider",
81
- PHANTOM_CONNECT_AUTH: "PhantomConnectAuth",
82
- JWT_AUTH: "JWTAuth",
83
- STORAGE: "Storage",
84
- SESSION: "Session"
85
- };
86
1379
 
87
1380
  // src/providers/injected/chains/SolanaChain.ts
88
- import { EventEmitter } from "eventemitter3";
89
- import { AddressType as AddressType2 } from "@phantom/client";
90
- import { Buffer } from "buffer";
91
- var InjectedSolanaChain = class {
92
- constructor(phantom, callbacks) {
93
- this._connected = false;
1381
+ import { EventEmitter as EventEmitter3 } from "eventemitter3";
1382
+ import { Buffer as Buffer3 } from "buffer";
1383
+ var PhantomSolanaChain = class {
1384
+ constructor(phantom) {
94
1385
  this._publicKey = null;
95
- this.eventEmitter = new EventEmitter();
1386
+ this.eventEmitter = new EventEmitter3();
96
1387
  this.phantom = phantom;
97
- this.callbacks = callbacks;
98
1388
  this.setupEventListeners();
99
- this.syncInitialState();
100
1389
  }
101
1390
  // Wallet adapter compliant properties
102
1391
  get connected() {
103
- return this._connected;
1392
+ return this._publicKey !== null;
104
1393
  }
105
1394
  get publicKey() {
106
1395
  return this._publicKey;
107
1396
  }
108
- // Connection methods - delegate to provider
109
- connect(_options) {
110
- if (!this.callbacks.isConnected()) {
111
- return Promise.reject(new Error("Provider not connected. Call provider connect first."));
112
- }
113
- const addresses = this.callbacks.getAddresses();
114
- const solanaAddress = addresses.find((addr) => addr.addressType === AddressType2.solana);
115
- if (!solanaAddress) {
116
- return Promise.reject(new Error("Solana not enabled for this provider"));
1397
+ // Connection methods
1398
+ async connect(options) {
1399
+ const result = await this.phantom.solana.connect(options);
1400
+ if (!result) {
1401
+ throw new Error("Failed to connect to Solana wallet");
117
1402
  }
118
- this.updateConnectionState(true, solanaAddress.address);
119
- return Promise.resolve({ publicKey: solanaAddress.address });
1403
+ const publicKey = typeof result === "string" ? result : "";
1404
+ this._publicKey = publicKey;
1405
+ return { publicKey };
120
1406
  }
121
1407
  async disconnect() {
122
- await this.callbacks.disconnect();
1408
+ await this.phantom.solana.disconnect();
1409
+ this._publicKey = null;
123
1410
  }
124
1411
  // Standard wallet adapter methods
125
1412
  async signMessage(message) {
126
1413
  const messageBytes = typeof message === "string" ? new TextEncoder().encode(message) : message;
127
1414
  const result = await this.phantom.solana.signMessage(messageBytes);
128
1415
  return {
129
- signature: result.signature instanceof Uint8Array ? result.signature : new Uint8Array(Buffer.from(result.signature, "base64")),
1416
+ signature: result.signature instanceof Uint8Array ? result.signature : new Uint8Array(Buffer3.from(result.signature, "base64")),
130
1417
  publicKey: this._publicKey || ""
131
1418
  };
132
1419
  }
133
1420
  async signTransaction(transaction) {
134
- if (!this.callbacks.isConnected()) {
1421
+ if (!this.connected) {
135
1422
  return Promise.reject(new Error("Provider not connected. Call provider connect first."));
136
1423
  }
137
1424
  try {
@@ -146,7 +1433,7 @@ var InjectedSolanaChain = class {
146
1433
  return { signature: result.signature };
147
1434
  }
148
1435
  async signAllTransactions(transactions) {
149
- if (!this.callbacks.isConnected()) {
1436
+ if (!this.connected) {
150
1437
  return Promise.reject(new Error("Provider not connected. Call provider connect first."));
151
1438
  }
152
1439
  try {
@@ -157,7 +1444,7 @@ var InjectedSolanaChain = class {
157
1444
  }
158
1445
  }
159
1446
  async signAndSendAllTransactions(transactions) {
160
- if (!this.callbacks.isConnected()) {
1447
+ if (!this.connected) {
161
1448
  return Promise.reject(new Error("Provider not connected. Call provider connect first."));
162
1449
  }
163
1450
  try {
@@ -175,42 +1462,21 @@ var InjectedSolanaChain = class {
175
1462
  return Promise.resolve(this._publicKey);
176
1463
  }
177
1464
  isConnected() {
178
- return this._connected && this.callbacks.isConnected();
1465
+ return this.connected;
179
1466
  }
180
1467
  setupEventListeners() {
181
1468
  this.phantom.solana.addEventListener("connect", (publicKey) => {
182
- this.updateConnectionState(true, publicKey);
1469
+ this._publicKey = publicKey;
183
1470
  this.eventEmitter.emit("connect", publicKey);
184
1471
  });
185
1472
  this.phantom.solana.addEventListener("disconnect", () => {
186
- this.updateConnectionState(false, null);
1473
+ this._publicKey = null;
187
1474
  this.eventEmitter.emit("disconnect");
188
1475
  });
189
1476
  this.phantom.solana.addEventListener("accountChanged", (publicKey) => {
190
1477
  this._publicKey = publicKey;
191
1478
  this.eventEmitter.emit("accountChanged", publicKey);
192
1479
  });
193
- this.callbacks.on("connect", (data) => {
194
- const solanaAddress = data.addresses?.find((addr) => addr.addressType === AddressType2.solana);
195
- if (solanaAddress) {
196
- this.updateConnectionState(true, solanaAddress.address);
197
- }
198
- });
199
- this.callbacks.on("disconnect", () => {
200
- this.updateConnectionState(false, null);
201
- });
202
- }
203
- syncInitialState() {
204
- if (this.callbacks.isConnected()) {
205
- const solanaAddress = this.callbacks.getAddresses().find((addr) => addr.addressType === AddressType2.solana);
206
- if (solanaAddress) {
207
- this.updateConnectionState(true, solanaAddress.address);
208
- }
209
- }
210
- }
211
- updateConnectionState(connected, publicKey) {
212
- this._connected = connected;
213
- this._publicKey = publicKey;
214
1480
  }
215
1481
  // Event methods for interface compliance
216
1482
  on(event, listener) {
@@ -222,22 +1488,18 @@ var InjectedSolanaChain = class {
222
1488
  };
223
1489
 
224
1490
  // src/providers/injected/chains/EthereumChain.ts
225
- import { EventEmitter as EventEmitter2 } from "eventemitter3";
226
- import { AddressType as AddressType3 } from "@phantom/client";
227
- var InjectedEthereumChain = class {
228
- constructor(phantom, callbacks) {
229
- this._connected = false;
1491
+ import { EventEmitter as EventEmitter4 } from "eventemitter3";
1492
+ var PhantomEthereumChain = class {
1493
+ constructor(phantom) {
230
1494
  this._chainId = "0x1";
231
1495
  this._accounts = [];
232
- this.eventEmitter = new EventEmitter2();
1496
+ this.eventEmitter = new EventEmitter4();
233
1497
  this.phantom = phantom;
234
- this.callbacks = callbacks;
235
1498
  this.setupEventListeners();
236
- this.syncInitialState();
237
1499
  }
238
1500
  // EIP-1193 compliant properties
239
1501
  get connected() {
240
- return this._connected;
1502
+ return this._accounts.length > 0;
241
1503
  }
242
1504
  get chainId() {
243
1505
  return this._chainId;
@@ -252,21 +1514,18 @@ var InjectedEthereumChain = class {
252
1514
  const result = await this.signTransaction(transaction);
253
1515
  return result;
254
1516
  }
255
- const provider = await this.phantom.ethereum.getProvider();
256
- return await provider.request(args);
1517
+ const phantomProvider = await this.phantom.ethereum.getProvider();
1518
+ return await phantomProvider.request(args);
257
1519
  }
258
- // Connection methods - delegate to provider
259
- connect() {
260
- if (!this.callbacks.isConnected()) {
261
- return Promise.reject(new Error("Provider not connected. Call provider connect first."));
262
- }
263
- const addresses = this.callbacks.getAddresses();
264
- const ethAddresses = addresses.filter((addr) => addr.addressType === AddressType3.ethereum).map((addr) => addr.address);
265
- this.updateConnectionState(true, ethAddresses);
266
- return Promise.resolve(ethAddresses);
1520
+ // Connection methods
1521
+ async connect() {
1522
+ const accounts = await this.phantom.ethereum.getAccounts();
1523
+ this._accounts = accounts;
1524
+ return accounts;
267
1525
  }
268
1526
  async disconnect() {
269
- await this.callbacks.disconnect();
1527
+ await this.phantom.ethereum.disconnect();
1528
+ this._accounts = [];
270
1529
  }
271
1530
  // Standard compliant methods (return raw values, not wrapped objects)
272
1531
  async signPersonalMessage(message, address) {
@@ -295,16 +1554,16 @@ var InjectedEthereumChain = class {
295
1554
  return await this.phantom.ethereum.getAccounts();
296
1555
  }
297
1556
  isConnected() {
298
- return this._connected && this.callbacks.isConnected();
1557
+ return this.connected;
299
1558
  }
300
1559
  setupEventListeners() {
301
1560
  this.phantom.ethereum.addEventListener("connect", (accounts) => {
302
- this.updateConnectionState(true, accounts);
1561
+ this._accounts = accounts;
303
1562
  this.eventEmitter.emit("connect", { chainId: this._chainId });
304
1563
  this.eventEmitter.emit("accountsChanged", accounts);
305
1564
  });
306
1565
  this.phantom.ethereum.addEventListener("disconnect", () => {
307
- this.updateConnectionState(false, []);
1566
+ this._accounts = [];
308
1567
  this.eventEmitter.emit("disconnect", { code: 4900, message: "Provider disconnected" });
309
1568
  this.eventEmitter.emit("accountsChanged", []);
310
1569
  });
@@ -316,27 +1575,6 @@ var InjectedEthereumChain = class {
316
1575
  this._chainId = chainId;
317
1576
  this.eventEmitter.emit("chainChanged", chainId);
318
1577
  });
319
- this.callbacks.on("connect", (data) => {
320
- const ethAddresses = data.addresses?.filter((addr) => addr.addressType === AddressType3.ethereum)?.map((addr) => addr.address) || [];
321
- if (ethAddresses.length > 0) {
322
- this.updateConnectionState(true, ethAddresses);
323
- }
324
- });
325
- this.callbacks.on("disconnect", () => {
326
- this.updateConnectionState(false, []);
327
- });
328
- }
329
- syncInitialState() {
330
- if (this.callbacks.isConnected()) {
331
- const ethAddresses = this.callbacks.getAddresses().filter((addr) => addr.addressType === AddressType3.ethereum).map((addr) => addr.address);
332
- if (ethAddresses.length > 0) {
333
- this.updateConnectionState(true, ethAddresses);
334
- }
335
- }
336
- }
337
- updateConnectionState(connected, accounts) {
338
- this._connected = connected;
339
- this._accounts = accounts;
340
1578
  }
341
1579
  // Event methods for interface compliance
342
1580
  on(event, listener) {
@@ -347,64 +1585,401 @@ var InjectedEthereumChain = class {
347
1585
  }
348
1586
  };
349
1587
 
1588
+ // src/wallets/registry.ts
1589
+ function isPhantomWallet(wallet) {
1590
+ return wallet !== void 0 && wallet.id === "phantom" && "isPhantom" in wallet && wallet.isPhantom === true;
1591
+ }
1592
+ var InjectedWalletRegistry = class {
1593
+ constructor() {
1594
+ this.wallets = /* @__PURE__ */ new Map();
1595
+ this.discoveryPromise = null;
1596
+ }
1597
+ register(info) {
1598
+ const wrappedProviders = {};
1599
+ if (info.providers?.solana) {
1600
+ const isWalletStandard = info.providers.solana && typeof info.providers.solana === "object" && "features" in info.providers.solana && typeof info.providers.solana.features === "object";
1601
+ if (isWalletStandard) {
1602
+ wrappedProviders.solana = new WalletStandardSolanaAdapter(info.providers.solana, info.id, info.name);
1603
+ debug.log(DebugCategory.BROWSER_SDK, "Wrapped Wallet Standard Solana wallet with adapter", {
1604
+ walletId: info.id,
1605
+ walletName: info.name
1606
+ });
1607
+ } else {
1608
+ wrappedProviders.solana = new InjectedWalletSolanaChain(info.providers.solana, info.id, info.name);
1609
+ debug.log(DebugCategory.BROWSER_SDK, "Wrapped Solana provider with InjectedWalletSolanaChain", {
1610
+ walletId: info.id,
1611
+ walletName: info.name
1612
+ });
1613
+ }
1614
+ }
1615
+ if (info.providers?.ethereum) {
1616
+ wrappedProviders.ethereum = new InjectedWalletEthereumChain(info.providers.ethereum, info.id, info.name);
1617
+ debug.log(DebugCategory.BROWSER_SDK, "Wrapped Ethereum provider with InjectedWalletEthereumChain", {
1618
+ walletId: info.id,
1619
+ walletName: info.name
1620
+ });
1621
+ }
1622
+ const wrappedInfo = {
1623
+ ...info,
1624
+ providers: Object.keys(wrappedProviders).length > 0 ? wrappedProviders : info.providers
1625
+ };
1626
+ this.wallets.set(info.id, wrappedInfo);
1627
+ }
1628
+ /**
1629
+ * Register Phantom wallet with its instance
1630
+ * This creates wrapped providers and stores the Phantom instance for auto-confirm access
1631
+ */
1632
+ registerPhantom(phantomInstance, addressTypes) {
1633
+ const wrappedProviders = {};
1634
+ if (addressTypes.includes(AddressType.solana) && phantomInstance.solana) {
1635
+ wrappedProviders.solana = new PhantomSolanaChain(phantomInstance);
1636
+ debug.log(DebugCategory.BROWSER_SDK, "Created PhantomSolanaChain wrapper", {
1637
+ walletId: "phantom"
1638
+ });
1639
+ }
1640
+ if (addressTypes.includes(AddressType.ethereum) && phantomInstance.ethereum) {
1641
+ wrappedProviders.ethereum = new PhantomEthereumChain(phantomInstance);
1642
+ debug.log(DebugCategory.BROWSER_SDK, "Created PhantomEthereumChain wrapper", {
1643
+ walletId: "phantom"
1644
+ });
1645
+ }
1646
+ const phantomWallet = {
1647
+ id: "phantom",
1648
+ name: "Phantom",
1649
+ icon: "",
1650
+ // Icon will be rendered from icons package in UI components
1651
+ addressTypes,
1652
+ providers: wrappedProviders,
1653
+ isPhantom: true,
1654
+ phantomInstance
1655
+ };
1656
+ this.wallets.set("phantom", phantomWallet);
1657
+ debug.log(DebugCategory.BROWSER_SDK, "Registered Phantom wallet with chain wrappers", {
1658
+ addressTypes,
1659
+ hasSolana: !!wrappedProviders.solana,
1660
+ hasEthereum: !!wrappedProviders.ethereum
1661
+ });
1662
+ }
1663
+ unregister(id) {
1664
+ this.wallets.delete(id);
1665
+ }
1666
+ has(id) {
1667
+ return this.wallets.has(id);
1668
+ }
1669
+ getById(id) {
1670
+ return this.wallets.get(id);
1671
+ }
1672
+ getAll() {
1673
+ return Array.from(this.wallets.values());
1674
+ }
1675
+ getByAddressTypes(addressTypes) {
1676
+ if (addressTypes.length === 0) {
1677
+ return this.getAll();
1678
+ }
1679
+ const allowed = new Set(addressTypes);
1680
+ return this.getAll().filter((wallet) => wallet.addressTypes.some((t) => allowed.has(t)));
1681
+ }
1682
+ discover(addressTypes) {
1683
+ if (this.discoveryPromise) {
1684
+ return this.discoveryPromise;
1685
+ }
1686
+ debug.log(DebugCategory.BROWSER_SDK, "Starting wallet discovery", { addressTypes });
1687
+ this.discoveryPromise = discoverWallets(addressTypes).then((discoveredWallets) => {
1688
+ const relevantWallets = addressTypes ? discoveredWallets.filter((wallet) => wallet.addressTypes.some((type) => addressTypes.includes(type))) : discoveredWallets;
1689
+ for (const wallet of relevantWallets) {
1690
+ if (wallet.id === "phantom" && isPhantomWallet(wallet)) {
1691
+ this.registerPhantom(wallet.phantomInstance, wallet.addressTypes);
1692
+ } else {
1693
+ this.register(wallet);
1694
+ }
1695
+ debug.log(DebugCategory.BROWSER_SDK, "Registered discovered wallet", {
1696
+ id: wallet.id,
1697
+ name: wallet.name,
1698
+ addressTypes: wallet.addressTypes
1699
+ });
1700
+ }
1701
+ debug.info(DebugCategory.BROWSER_SDK, "Wallet discovery completed", {
1702
+ totalDiscovered: discoveredWallets.length,
1703
+ relevantWallets: relevantWallets.length
1704
+ });
1705
+ }).catch((error) => {
1706
+ debug.warn(DebugCategory.BROWSER_SDK, "Wallet discovery failed", { error });
1707
+ this.discoveryPromise = null;
1708
+ throw error;
1709
+ });
1710
+ return this.discoveryPromise;
1711
+ }
1712
+ };
1713
+ var walletRegistry = null;
1714
+ function getWalletRegistry() {
1715
+ if (!walletRegistry) {
1716
+ walletRegistry = new InjectedWalletRegistry();
1717
+ }
1718
+ return walletRegistry;
1719
+ }
1720
+
350
1721
  // src/providers/injected/index.ts
351
1722
  var WAS_CONNECTED_KEY = "phantom-injected-was-connected";
352
1723
  var WAS_CONNECTED_VALUE = "true";
1724
+ var LAST_WALLET_ID_KEY = "phantom-injected-last-wallet-id";
353
1725
  var InjectedProvider = class {
1726
+ // Track which wallets have event listeners set up
354
1727
  constructor(config) {
355
- this.connected = false;
356
- this.addresses = [];
1728
+ this.selectedWalletId = null;
1729
+ this.walletStates = /* @__PURE__ */ new Map();
357
1730
  // Event management
358
1731
  this.eventListeners = /* @__PURE__ */ new Map();
359
1732
  this.browserInjectedCleanupFunctions = [];
360
1733
  this.eventsInitialized = false;
1734
+ this.externalWalletEventListenersSetup = /* @__PURE__ */ new Set();
361
1735
  debug.log(DebugCategory.INJECTED_PROVIDER, "Initializing InjectedProvider", { config });
362
1736
  this.addressTypes = config.addressTypes;
1737
+ this.walletRegistry = getWalletRegistry();
363
1738
  debug.log(DebugCategory.INJECTED_PROVIDER, "Address types configured", { addressTypes: this.addressTypes });
364
- const plugins = [createExtensionPlugin()];
365
- if (this.addressTypes.includes(AddressType4.solana)) {
366
- plugins.push(createSolanaPlugin());
367
- debug.log(DebugCategory.INJECTED_PROVIDER, "Solana plugin added");
368
- }
369
- if (this.addressTypes.includes(AddressType4.ethereum)) {
370
- plugins.push(createEthereumPlugin());
371
- debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum plugin added");
372
- }
373
- plugins.push(createAutoConfirmPlugin());
374
- debug.log(DebugCategory.INJECTED_PROVIDER, "AutoConfirm plugin added");
375
- debug.log(DebugCategory.INJECTED_PROVIDER, "Creating Phantom instance with plugins", {
376
- pluginCount: plugins.length
1739
+ this.walletRegistry.discover(this.addressTypes).catch((error) => {
1740
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Wallet discovery failed during initialization", { error });
377
1741
  });
378
- this.phantom = createPhantom({ plugins });
379
- const callbacks = this.createCallbacks();
380
- if (this.addressTypes.includes(AddressType4.solana)) {
381
- this._solanaChain = new InjectedSolanaChain(this.phantom, callbacks);
1742
+ debug.info(DebugCategory.INJECTED_PROVIDER, "InjectedProvider initialized");
1743
+ }
1744
+ /**
1745
+ * Wait for wallet discovery to complete if the wallet is not yet in the registry
1746
+ * This is needed for auto-connect when the last wallet was an external wallet
1747
+ */
1748
+ async waitForWalletDiscovery(walletId) {
1749
+ if (this.walletRegistry.has(walletId)) {
1750
+ return;
382
1751
  }
383
- if (this.addressTypes.includes(AddressType4.ethereum)) {
384
- this._ethereumChain = new InjectedEthereumChain(this.phantom, callbacks);
1752
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Wallet not found in registry, waiting for discovery", {
1753
+ walletId
1754
+ });
1755
+ try {
1756
+ await this.walletRegistry.discover(this.addressTypes);
1757
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Wallet discovery completed", { walletId });
1758
+ } catch (error) {
1759
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Wallet discovery failed", {
1760
+ walletId,
1761
+ error: error instanceof Error ? error.message : String(error)
1762
+ });
385
1763
  }
386
- debug.info(DebugCategory.INJECTED_PROVIDER, "InjectedProvider initialized");
387
1764
  }
388
1765
  get solana() {
389
- if (!this.addressTypes.includes(AddressType4.solana)) {
1766
+ if (!this.addressTypes.includes(AddressType2.solana)) {
390
1767
  throw new Error("Solana not enabled for this provider");
391
1768
  }
392
- if (!this._solanaChain) {
393
- throw new Error("Solana chain not initialized");
1769
+ const walletId = this.selectedWalletId || "phantom";
1770
+ const walletInfo = this.walletRegistry.getById(walletId);
1771
+ if (!walletInfo) {
1772
+ const registry = this.walletRegistry;
1773
+ if (registry.discoveryPromise) {
1774
+ throw new Error(
1775
+ `Wallet "${walletId}" not found. Wallet discovery is still in progress. Please wait for sdk.discoverWallets() to complete before accessing chain properties.`
1776
+ );
1777
+ }
1778
+ throw new Error(
1779
+ `Wallet "${walletId}" not found. Please ensure wallet discovery has completed. Make sure you call sdk.discoverWallets() and await it before accessing chain properties.`
1780
+ );
1781
+ }
1782
+ if (!walletInfo.providers?.solana) {
1783
+ throw new Error(
1784
+ `Selected wallet "${walletInfo.name}" does not support Solana. This wallet only supports: ${walletInfo.addressTypes.join(", ")}. Make sure your SDK config includes Solana in addressTypes.`
1785
+ );
1786
+ }
1787
+ return walletInfo.providers.solana;
1788
+ }
1789
+ /**
1790
+ * Access to Ethereum chain operations
1791
+ */
1792
+ get ethereum() {
1793
+ if (!this.addressTypes.includes(AddressType2.ethereum)) {
1794
+ throw new Error("Ethereum not enabled for this provider");
1795
+ }
1796
+ const walletId = this.selectedWalletId || "phantom";
1797
+ const walletInfo = this.walletRegistry.getById(walletId);
1798
+ if (!walletInfo) {
1799
+ const registry = this.walletRegistry;
1800
+ if (registry.discoveryPromise) {
1801
+ throw new Error(
1802
+ `Wallet "${walletId}" not found. Wallet discovery is still in progress. Please wait for sdk.discoverWallets() to complete before accessing chain properties.`
1803
+ );
1804
+ }
1805
+ throw new Error(
1806
+ `Wallet "${walletId}" not found. Please ensure wallet discovery has completed. Make sure you call sdk.discoverWallets() and await it before accessing chain properties.`
1807
+ );
1808
+ }
1809
+ if (!walletInfo.providers?.ethereum) {
1810
+ throw new Error(
1811
+ `Selected wallet "${walletInfo.name}" does not support Ethereum. This wallet only supports: ${walletInfo.addressTypes.join(", ")}. Make sure your SDK config includes Ethereum in addressTypes.`
1812
+ );
1813
+ }
1814
+ return walletInfo.providers.ethereum;
1815
+ }
1816
+ validateAndSelectWallet(requestedWalletId) {
1817
+ if (!this.walletRegistry.has(requestedWalletId)) {
1818
+ debug.error(DebugCategory.INJECTED_PROVIDER, "Unknown injected wallet id requested", {
1819
+ walletId: requestedWalletId
1820
+ });
1821
+ throw new Error(`Unknown injected wallet id: ${requestedWalletId}`);
1822
+ }
1823
+ const walletInfo = this.walletRegistry.getById(requestedWalletId);
1824
+ if (!walletInfo || !walletInfo.providers) {
1825
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Wallet not available for connection", {
1826
+ walletId: requestedWalletId
1827
+ });
1828
+ throw new Error(`Wallet not available for connection: ${requestedWalletId}`);
1829
+ }
1830
+ this.selectedWalletId = requestedWalletId;
1831
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Selected injected wallet for connection", {
1832
+ walletId: requestedWalletId
1833
+ });
1834
+ return walletInfo;
1835
+ }
1836
+ async connectToWallet(walletInfo, options) {
1837
+ if (!walletInfo.providers) {
1838
+ const error = new Error(`Wallet adapter not available for wallet: ${this.selectedWalletId}`);
1839
+ debug.error(DebugCategory.INJECTED_PROVIDER, "Wallet adapter not available", { walletId: this.selectedWalletId });
1840
+ this.emit("connect_error", {
1841
+ error: error.message,
1842
+ source: options?.skipEventListeners ? "auto-connect" : "manual-connect"
1843
+ });
1844
+ throw error;
1845
+ }
1846
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Connecting via wallet", {
1847
+ walletId: this.selectedWalletId,
1848
+ walletName: walletInfo.name,
1849
+ options
1850
+ });
1851
+ if (!options?.skipEventListeners) {
1852
+ this.setupExternalWalletEvents(walletInfo);
1853
+ if (this.selectedWalletId === "phantom" && isPhantomWallet(walletInfo)) {
1854
+ this.browserInjectedCleanupFunctions.forEach((cleanup) => cleanup());
1855
+ this.browserInjectedCleanupFunctions = [];
1856
+ this.setupBrowserInjectedEvents();
1857
+ this.eventsInitialized = true;
1858
+ }
1859
+ }
1860
+ const connectedAddresses = [];
1861
+ if (this.addressTypes.includes(AddressType2.solana) && walletInfo.providers?.solana) {
1862
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting Solana connection", {
1863
+ walletId: this.selectedWalletId,
1864
+ walletName: walletInfo.name,
1865
+ onlyIfTrusted: options?.onlyIfTrusted
1866
+ });
1867
+ try {
1868
+ const result = await walletInfo.providers.solana.connect(
1869
+ options?.onlyIfTrusted ? { onlyIfTrusted: true } : void 0
1870
+ );
1871
+ const address = result.publicKey;
1872
+ connectedAddresses.push({
1873
+ addressType: AddressType2.solana,
1874
+ address
1875
+ });
1876
+ debug.info(DebugCategory.INJECTED_PROVIDER, "Solana connected successfully", {
1877
+ address,
1878
+ walletId: this.selectedWalletId,
1879
+ walletName: walletInfo.name
1880
+ });
1881
+ } catch (err) {
1882
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Solana, stopping", {
1883
+ error: err,
1884
+ walletId: this.selectedWalletId,
1885
+ walletName: walletInfo.name
1886
+ });
1887
+ this.emit("connect_error", {
1888
+ error: err instanceof Error ? err.message : "Failed to connect",
1889
+ source: options?.skipEventListeners ? "auto-connect" : "manual-connect"
1890
+ });
1891
+ throw err;
1892
+ }
1893
+ }
1894
+ if (this.addressTypes.includes(AddressType2.ethereum) && walletInfo.providers?.ethereum) {
1895
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting Ethereum connection", {
1896
+ walletId: this.selectedWalletId,
1897
+ walletName: walletInfo.name,
1898
+ silent: options?.silent
1899
+ });
1900
+ try {
1901
+ let accounts;
1902
+ if (options?.silent) {
1903
+ accounts = await walletInfo.providers.ethereum.request({ method: "eth_accounts" });
1904
+ } else {
1905
+ accounts = await walletInfo.providers.ethereum.connect();
1906
+ }
1907
+ if (accounts.length > 0) {
1908
+ connectedAddresses.push(
1909
+ ...accounts.map((address) => ({
1910
+ addressType: AddressType2.ethereum,
1911
+ address
1912
+ }))
1913
+ );
1914
+ debug.info(DebugCategory.INJECTED_PROVIDER, "Ethereum connected successfully", {
1915
+ addresses: accounts,
1916
+ walletId: this.selectedWalletId,
1917
+ walletName: walletInfo.name
1918
+ });
1919
+ }
1920
+ } catch (err) {
1921
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Ethereum, stopping", {
1922
+ error: err,
1923
+ walletId: this.selectedWalletId,
1924
+ walletName: walletInfo.name
1925
+ });
1926
+ this.emit("connect_error", {
1927
+ error: err instanceof Error ? err.message : "Failed to connect",
1928
+ source: options?.skipEventListeners ? "auto-connect" : "manual-connect"
1929
+ });
1930
+ throw err;
1931
+ }
394
1932
  }
395
- return this._solanaChain;
1933
+ return connectedAddresses;
396
1934
  }
397
- /**
398
- * Access to Ethereum chain operations
399
- */
400
- get ethereum() {
401
- if (!this.addressTypes.includes(AddressType4.ethereum)) {
402
- throw new Error("Ethereum not enabled for this provider");
1935
+ async finalizeConnection(connectedAddresses, authProvider, walletId) {
1936
+ if (connectedAddresses.length === 0) {
1937
+ const error = new Error("Failed to connect to any supported wallet provider");
1938
+ this.emit("connect_error", {
1939
+ error: error.message,
1940
+ source: "manual-connect"
1941
+ });
1942
+ throw error;
403
1943
  }
404
- if (!this._ethereumChain) {
405
- throw new Error("Ethereum chain not initialized");
1944
+ if (this.selectedWalletId) {
1945
+ this.setWalletState(this.selectedWalletId, {
1946
+ connected: true,
1947
+ addresses: connectedAddresses
1948
+ });
406
1949
  }
407
- return this._ethereumChain;
1950
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Finalized connection with addresses", {
1951
+ addressCount: connectedAddresses.length,
1952
+ addresses: connectedAddresses.map((addr) => ({
1953
+ type: addr.addressType,
1954
+ address: addr.address.substring(0, 10) + "..."
1955
+ }))
1956
+ });
1957
+ const authUserId = await this.getAuthUserId("manual-connect");
1958
+ try {
1959
+ localStorage.setItem(WAS_CONNECTED_KEY, WAS_CONNECTED_VALUE);
1960
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Set was-connected flag - auto-reconnect enabled");
1961
+ if (this.selectedWalletId) {
1962
+ localStorage.setItem(LAST_WALLET_ID_KEY, this.selectedWalletId);
1963
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Stored last injected wallet id", {
1964
+ walletId: this.selectedWalletId
1965
+ });
1966
+ }
1967
+ } catch (error) {
1968
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to persist injected provider state", { error });
1969
+ }
1970
+ const result = {
1971
+ addresses: connectedAddresses,
1972
+ status: "completed",
1973
+ authUserId,
1974
+ authProvider,
1975
+ walletId
1976
+ };
1977
+ this.emit("connect", {
1978
+ addresses: connectedAddresses,
1979
+ source: "manual-connect",
1980
+ authUserId
1981
+ });
1982
+ return result;
408
1983
  }
409
1984
  async connect(authOptions) {
410
1985
  debug.info(DebugCategory.INJECTED_PROVIDER, "Starting injected provider connect", {
@@ -419,110 +1994,48 @@ var InjectedProvider = class {
419
1994
  providerType: "injected"
420
1995
  });
421
1996
  try {
422
- if (!this.phantom.extension?.isInstalled?.()) {
423
- debug.error(DebugCategory.INJECTED_PROVIDER, "Phantom wallet extension not found");
424
- const error = new Error("Phantom wallet not found");
425
- this.emit("connect_error", {
426
- error: error.message,
427
- source: "manual-connect"
428
- });
429
- throw error;
430
- }
431
- debug.log(DebugCategory.INJECTED_PROVIDER, "Phantom extension detected");
432
- const connectedAddresses = [];
433
- if (this.addressTypes.includes(AddressType4.solana)) {
434
- debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting Solana connection");
1997
+ const requestedWalletId = authOptions.walletId || "phantom";
1998
+ const walletInfo = this.validateAndSelectWallet(requestedWalletId);
1999
+ const connectedAddresses = await this.connectToWallet(walletInfo);
2000
+ return await this.finalizeConnection(connectedAddresses, "injected", this.selectedWalletId || void 0);
2001
+ } catch (error) {
2002
+ this.emit("connect_error", {
2003
+ error: error instanceof Error ? error.message : "Failed to connect",
2004
+ source: "manual-connect"
2005
+ });
2006
+ throw error;
2007
+ }
2008
+ }
2009
+ async disconnect() {
2010
+ debug.info(DebugCategory.INJECTED_PROVIDER, "Starting injected provider disconnect");
2011
+ const walletInfo = this.walletRegistry.getById(this.selectedWalletId || "phantom");
2012
+ if (walletInfo?.providers) {
2013
+ if (this.addressTypes.includes(AddressType2.solana) && walletInfo.providers.solana) {
435
2014
  try {
436
- const publicKey = await this.phantom.solana.connect();
437
- if (publicKey) {
438
- connectedAddresses.push({
439
- addressType: AddressType4.solana,
440
- address: publicKey
441
- });
442
- debug.info(DebugCategory.INJECTED_PROVIDER, "Solana connected successfully", { address: publicKey });
443
- }
2015
+ await walletInfo.providers.solana.disconnect();
2016
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Solana disconnected successfully");
444
2017
  } catch (err) {
445
- debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Solana, stopping", { error: err });
446
- this.emit("connect_error", {
447
- error: err instanceof Error ? err.message : "Failed to connect",
448
- source: "manual-connect"
449
- });
450
- throw err;
2018
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to disconnect Solana", { error: err });
451
2019
  }
452
2020
  }
453
- if (this.addressTypes.includes(AddressType4.ethereum)) {
2021
+ if (this.addressTypes.includes(AddressType2.ethereum) && walletInfo.providers.ethereum) {
454
2022
  try {
455
- const accounts = await this.phantom.ethereum.connect();
456
- if (accounts && accounts.length > 0) {
457
- connectedAddresses.push(
458
- ...accounts.map((address) => ({
459
- addressType: AddressType4.ethereum,
460
- address
461
- }))
462
- );
463
- debug.info(DebugCategory.INJECTED_PROVIDER, "Ethereum connected successfully", { addresses: accounts });
464
- }
2023
+ await walletInfo.providers.ethereum.disconnect();
2024
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum disconnected successfully");
465
2025
  } catch (err) {
466
- debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Ethereum, stopping", { error: err });
467
- this.emit("connect_error", {
468
- error: err instanceof Error ? err.message : "Failed to connect",
469
- source: "manual-connect"
470
- });
471
- throw err;
2026
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to disconnect Ethereum", { error: err });
472
2027
  }
473
2028
  }
474
- if (connectedAddresses.length === 0) {
475
- const error = new Error("Failed to connect to any supported wallet provider");
476
- this.emit("connect_error", {
477
- error: error.message,
478
- source: "manual-connect"
479
- });
480
- throw error;
481
- }
482
- this.addresses = connectedAddresses;
483
- this.connected = true;
484
- const authUserId = await this.getAuthUserId("manual-connect");
485
- try {
486
- localStorage.setItem(WAS_CONNECTED_KEY, WAS_CONNECTED_VALUE);
487
- debug.log(DebugCategory.INJECTED_PROVIDER, "Set was-connected flag - auto-reconnect enabled");
488
- } catch (error) {
489
- debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to set was-connected flag", { error });
490
- }
491
- const result = {
492
- addresses: this.addresses,
493
- status: "completed",
494
- authUserId
495
- };
496
- this.emit("connect", {
497
- addresses: this.addresses,
498
- source: "manual-connect",
499
- authUserId
500
- });
501
- return result;
502
- } catch (error) {
503
- if (error instanceof Error && !error.message.includes("Phantom wallet not found") && !error.message.includes("Failed to connect to any supported wallet provider")) {
504
- this.emit("connect_error", {
505
- error: error.message,
506
- source: "manual-connect"
507
- });
508
- }
509
- throw error;
510
- }
511
- }
512
- async disconnect() {
513
- debug.info(DebugCategory.INJECTED_PROVIDER, "Starting injected provider disconnect");
514
- if (this.addressTypes.includes(AddressType4.solana)) {
515
- try {
516
- await this.phantom.solana.disconnect();
517
- debug.log(DebugCategory.INJECTED_PROVIDER, "Solana disconnected successfully");
518
- } catch (err) {
519
- debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to disconnect Solana", { error: err });
520
- }
521
2029
  }
522
2030
  this.browserInjectedCleanupFunctions.forEach((cleanup) => cleanup());
523
2031
  this.browserInjectedCleanupFunctions = [];
524
- this.connected = false;
525
- this.addresses = [];
2032
+ if (this.selectedWalletId) {
2033
+ this.externalWalletEventListenersSetup.delete(this.selectedWalletId);
2034
+ this.setWalletState(this.selectedWalletId, {
2035
+ connected: false,
2036
+ addresses: []
2037
+ });
2038
+ }
526
2039
  try {
527
2040
  localStorage.removeItem(WAS_CONNECTED_KEY);
528
2041
  debug.log(DebugCategory.INJECTED_PROVIDER, "Cleared was connected flag to prevent auto-reconnect");
@@ -541,13 +2054,17 @@ var InjectedProvider = class {
541
2054
  */
542
2055
  async autoConnect() {
543
2056
  debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting auto-connect");
2057
+ let lastWalletId = null;
544
2058
  try {
545
2059
  const wasConnected = localStorage.getItem(WAS_CONNECTED_KEY);
546
2060
  if (wasConnected !== WAS_CONNECTED_VALUE) {
547
2061
  debug.log(DebugCategory.INJECTED_PROVIDER, "Skipping auto-connect: user was not previously connected");
548
2062
  return;
549
2063
  }
550
- debug.log(DebugCategory.INJECTED_PROVIDER, "User was previously connected, attempting auto-connect");
2064
+ lastWalletId = localStorage.getItem(LAST_WALLET_ID_KEY);
2065
+ debug.log(DebugCategory.INJECTED_PROVIDER, "User was previously connected, attempting auto-connect", {
2066
+ lastWalletId: lastWalletId || "phantom"
2067
+ });
551
2068
  } catch (error) {
552
2069
  debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to check was-connected flag", { error });
553
2070
  return;
@@ -557,53 +2074,22 @@ var InjectedProvider = class {
557
2074
  providerType: "injected"
558
2075
  });
559
2076
  try {
560
- if (!this.phantom.extension?.isInstalled?.()) {
561
- debug.warn(DebugCategory.INJECTED_PROVIDER, "Phantom wallet extension not found for auto-connect");
562
- this.emit("connect_error", {
563
- error: "Phantom wallet not found",
564
- source: "auto-connect"
2077
+ const walletId = lastWalletId || "phantom";
2078
+ await this.waitForWalletDiscovery(walletId);
2079
+ const walletInfo = this.validateAndSelectWallet(walletId);
2080
+ let connectedAddresses = [];
2081
+ try {
2082
+ connectedAddresses = await this.connectToWallet(walletInfo, {
2083
+ onlyIfTrusted: true,
2084
+ silent: true,
2085
+ skipEventListeners: true
2086
+ // Set up listeners only if connection succeeds
2087
+ });
2088
+ } catch (err) {
2089
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Auto-connect failed (expected if not trusted)", {
2090
+ error: err,
2091
+ walletId: this.selectedWalletId
565
2092
  });
566
- return;
567
- }
568
- const connectedAddresses = [];
569
- if (this.addressTypes.includes(AddressType4.solana)) {
570
- debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting Solana auto-connect");
571
- try {
572
- const publicKey = await this.phantom.solana.connect({ onlyIfTrusted: true });
573
- if (publicKey) {
574
- connectedAddresses.push({
575
- addressType: AddressType4.solana,
576
- address: publicKey
577
- });
578
- debug.info(DebugCategory.INJECTED_PROVIDER, "Solana auto-connected successfully", { address: publicKey });
579
- }
580
- } catch (err) {
581
- debug.log(DebugCategory.INJECTED_PROVIDER, "Solana auto-connect failed (expected if not trusted)", {
582
- error: err
583
- });
584
- throw err;
585
- }
586
- }
587
- if (this.addressTypes.includes(AddressType4.ethereum)) {
588
- debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting Ethereum auto-connect");
589
- try {
590
- const accounts = await this.phantom.ethereum.connect({ onlyIfTrusted: true });
591
- if (accounts && accounts.length > 0) {
592
- connectedAddresses.push(
593
- ...accounts.map((address) => ({
594
- addressType: AddressType4.ethereum,
595
- address
596
- }))
597
- );
598
- debug.info(DebugCategory.INJECTED_PROVIDER, "Ethereum auto-connected successfully", {
599
- addresses: accounts
600
- });
601
- }
602
- } catch (err) {
603
- debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum auto-connect failed (expected if not trusted)", {
604
- error: err
605
- });
606
- }
607
2093
  }
608
2094
  if (connectedAddresses.length === 0) {
609
2095
  debug.log(DebugCategory.INJECTED_PROVIDER, "Auto-connect failed: no trusted connections available");
@@ -613,11 +2099,22 @@ var InjectedProvider = class {
613
2099
  });
614
2100
  return;
615
2101
  }
616
- this.addresses = connectedAddresses;
617
- this.connected = true;
2102
+ this.setupExternalWalletEvents(walletInfo);
2103
+ if (this.selectedWalletId === "phantom" && isPhantomWallet(walletInfo)) {
2104
+ this.browserInjectedCleanupFunctions.forEach((cleanup) => cleanup());
2105
+ this.browserInjectedCleanupFunctions = [];
2106
+ this.setupBrowserInjectedEvents();
2107
+ this.eventsInitialized = true;
2108
+ }
2109
+ if (this.selectedWalletId) {
2110
+ this.setWalletState(this.selectedWalletId, {
2111
+ connected: true,
2112
+ addresses: connectedAddresses
2113
+ });
2114
+ }
618
2115
  const authUserId = await this.getAuthUserId("auto-connect");
619
2116
  this.emit("connect", {
620
- addresses: this.addresses,
2117
+ addresses: connectedAddresses,
621
2118
  source: "auto-connect",
622
2119
  authUserId
623
2120
  });
@@ -627,6 +2124,7 @@ var InjectedProvider = class {
627
2124
  type: addr.addressType,
628
2125
  address: addr.address.substring(0, 8) + "..."
629
2126
  })),
2127
+ walletId: this.selectedWalletId,
630
2128
  authUserId
631
2129
  });
632
2130
  } catch (error) {
@@ -639,34 +2137,80 @@ var InjectedProvider = class {
639
2137
  });
640
2138
  }
641
2139
  }
2140
+ getWalletState(walletId) {
2141
+ if (!this.walletStates.has(walletId)) {
2142
+ this.walletStates.set(walletId, { connected: false, addresses: [] });
2143
+ }
2144
+ return this.walletStates.get(walletId);
2145
+ }
2146
+ setWalletState(walletId, state) {
2147
+ this.walletStates.set(walletId, state);
2148
+ }
642
2149
  getAddresses() {
643
- return this.addresses;
2150
+ const walletId = this.selectedWalletId || "phantom";
2151
+ return this.getWalletState(walletId).addresses;
2152
+ }
2153
+ /**
2154
+ * Get enabled address types for the current selected wallet
2155
+ * - For Phantom: returns config.addressTypes
2156
+ * - For external wallets: returns the wallet's addressTypes from registry
2157
+ */
2158
+ getEnabledAddressTypes() {
2159
+ if (!this.selectedWalletId || this.selectedWalletId === "phantom") {
2160
+ return this.addressTypes;
2161
+ }
2162
+ const walletInfo = this.walletRegistry.getById(this.selectedWalletId);
2163
+ if (walletInfo) {
2164
+ return walletInfo.addressTypes;
2165
+ }
2166
+ return this.addressTypes;
644
2167
  }
645
2168
  isConnected() {
646
- return this.connected;
2169
+ const walletId = this.selectedWalletId || "phantom";
2170
+ return this.getWalletState(walletId).connected;
647
2171
  }
648
- // AutoConfirm methods - only available for injected providers
2172
+ // AutoConfirm methods - only available for Phantom wallet
649
2173
  async enableAutoConfirm(params) {
2174
+ const walletInfo = this.walletRegistry.getById(this.selectedWalletId || "phantom");
2175
+ if (!isPhantomWallet(walletInfo)) {
2176
+ throw new Error("Auto-confirm is only available for Phantom wallet");
2177
+ }
650
2178
  debug.log(DebugCategory.INJECTED_PROVIDER, "Enabling autoConfirm", { params });
651
- return await this.phantom.autoConfirm.autoConfirmEnable(params);
2179
+ return await walletInfo.phantomInstance.autoConfirm.autoConfirmEnable(params);
652
2180
  }
653
2181
  async disableAutoConfirm() {
2182
+ const walletInfo = this.walletRegistry.getById(this.selectedWalletId || "phantom");
2183
+ if (!isPhantomWallet(walletInfo)) {
2184
+ throw new Error("Auto-confirm is only available for Phantom wallet");
2185
+ }
654
2186
  debug.log(DebugCategory.INJECTED_PROVIDER, "Disabling autoConfirm");
655
- await this.phantom.autoConfirm.autoConfirmDisable();
2187
+ await walletInfo.phantomInstance.autoConfirm.autoConfirmDisable();
656
2188
  }
657
2189
  async getAutoConfirmStatus() {
2190
+ const walletInfo = this.walletRegistry.getById(this.selectedWalletId || "phantom");
2191
+ if (!isPhantomWallet(walletInfo)) {
2192
+ throw new Error("Auto-confirm is only available for Phantom wallet");
2193
+ }
658
2194
  debug.log(DebugCategory.INJECTED_PROVIDER, "Getting autoConfirm status");
659
- return await this.phantom.autoConfirm.autoConfirmStatus();
2195
+ return await walletInfo.phantomInstance.autoConfirm.autoConfirmStatus();
660
2196
  }
661
2197
  async getSupportedAutoConfirmChains() {
2198
+ const walletInfo = this.walletRegistry.getById(this.selectedWalletId || "phantom");
2199
+ if (!isPhantomWallet(walletInfo)) {
2200
+ throw new Error("Auto-confirm is only available for Phantom wallet");
2201
+ }
662
2202
  debug.log(DebugCategory.INJECTED_PROVIDER, "Getting supported autoConfirm chains");
663
- return await this.phantom.autoConfirm.autoConfirmSupportedChains();
2203
+ return await walletInfo.phantomInstance.autoConfirm.autoConfirmSupportedChains();
664
2204
  }
665
2205
  /**
666
2206
  * Helper method to get authUserId from window.phantom.app.getUser()
667
- * Returns undefined if the method is not available or fails
2207
+ * Returns undefined if the method is not available or fails, or if wallet is not Phantom
668
2208
  */
669
2209
  async getAuthUserId(context) {
2210
+ const walletInfo = this.walletRegistry.getById(this.selectedWalletId || "phantom");
2211
+ if (!isPhantomWallet(walletInfo)) {
2212
+ return void 0;
2213
+ }
670
2214
  try {
671
2215
  if (window.phantom?.app?.getUser) {
672
2216
  const userInfo = await window.phantom.app.getUser();
@@ -730,140 +2274,245 @@ var InjectedProvider = class {
730
2274
  }
731
2275
  }
732
2276
  setupBrowserInjectedEvents() {
733
- debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up browser-injected-sdk event listeners");
734
- if (this.addressTypes.includes(AddressType4.solana)) {
735
- this.setupSolanaEvents();
2277
+ const walletInfo = this.walletRegistry.getById(this.selectedWalletId || "phantom");
2278
+ if (!isPhantomWallet(walletInfo)) {
2279
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Skipping browser-injected-sdk event setup - not Phantom wallet");
2280
+ return;
736
2281
  }
737
- if (this.addressTypes.includes(AddressType4.ethereum)) {
738
- this.setupEthereumEvents();
2282
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up browser-injected-sdk event listeners");
2283
+ if (this.selectedWalletId === "phantom" && isPhantomWallet(walletInfo)) {
2284
+ if (this.addressTypes.includes(AddressType2.solana)) {
2285
+ this.setupSolanaEvents(walletInfo.phantomInstance);
2286
+ }
2287
+ if (this.addressTypes.includes(AddressType2.ethereum)) {
2288
+ this.setupEthereumEvents(walletInfo.phantomInstance);
2289
+ }
739
2290
  }
740
2291
  }
741
- setupSolanaEvents() {
2292
+ setupSolanaEvents(phantom) {
742
2293
  debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up Solana event listeners");
743
2294
  const handleSolanaConnect = async (publicKey) => {
744
2295
  debug.log(DebugCategory.INJECTED_PROVIDER, "Solana connect event received", { publicKey });
745
- const solanaAddress = { addressType: AddressType4.solana, address: publicKey };
746
- if (!this.addresses.find((addr) => addr.addressType === AddressType4.solana)) {
747
- this.addresses.push(solanaAddress);
748
- }
749
- this.connected = true;
2296
+ const walletId = this.selectedWalletId || "phantom";
2297
+ const state = this.getWalletState(walletId);
2298
+ const solanaAddress = { addressType: AddressType2.solana, address: publicKey };
2299
+ const hasSolana = state.addresses.some((addr) => addr.addressType === AddressType2.solana);
2300
+ const newAddresses = hasSolana ? state.addresses.map((addr) => addr.addressType === AddressType2.solana ? solanaAddress : addr) : [...state.addresses, solanaAddress];
2301
+ this.setWalletState(walletId, {
2302
+ connected: true,
2303
+ addresses: newAddresses
2304
+ });
750
2305
  const authUserId = await this.getAuthUserId("Solana connect event");
751
2306
  this.emit("connect", {
752
- addresses: this.addresses,
2307
+ addresses: newAddresses,
753
2308
  source: "injected-extension",
754
2309
  authUserId
755
2310
  });
756
2311
  };
757
2312
  const handleSolanaDisconnect = () => {
758
2313
  debug.log(DebugCategory.INJECTED_PROVIDER, "Solana disconnect event received");
759
- this.addresses = this.addresses.filter((addr) => addr.addressType !== AddressType4.solana);
760
- this.connected = false;
2314
+ const walletId = this.selectedWalletId || "phantom";
2315
+ const state = this.getWalletState(walletId);
2316
+ const filteredAddresses = state.addresses.filter((addr) => addr.addressType !== AddressType2.solana);
2317
+ this.setWalletState(walletId, {
2318
+ connected: filteredAddresses.length > 0,
2319
+ addresses: filteredAddresses
2320
+ });
761
2321
  this.emit("disconnect", {
762
2322
  source: "injected-extension"
763
2323
  });
764
2324
  };
765
2325
  const handleSolanaAccountChanged = async (publicKey) => {
766
2326
  debug.log(DebugCategory.INJECTED_PROVIDER, "Solana account changed event received", { publicKey });
767
- const solanaIndex = this.addresses.findIndex((addr) => addr.addressType === AddressType4.solana);
768
- if (solanaIndex >= 0) {
769
- this.addresses[solanaIndex] = { addressType: AddressType4.solana, address: publicKey };
770
- } else {
771
- this.addresses.push({ addressType: AddressType4.solana, address: publicKey });
772
- }
2327
+ const walletId = this.selectedWalletId || "phantom";
2328
+ const state = this.getWalletState(walletId);
2329
+ const solanaIndex = state.addresses.findIndex((addr) => addr.addressType === AddressType2.solana);
2330
+ const newAddresses = solanaIndex >= 0 ? state.addresses.map(
2331
+ (addr, idx) => idx === solanaIndex ? { addressType: AddressType2.solana, address: publicKey } : addr
2332
+ ) : [...state.addresses, { addressType: AddressType2.solana, address: publicKey }];
2333
+ this.setWalletState(walletId, {
2334
+ connected: true,
2335
+ addresses: newAddresses
2336
+ });
773
2337
  const authUserId = await this.getAuthUserId("Solana account changed event");
774
2338
  this.emit("connect", {
775
- addresses: this.addresses,
2339
+ addresses: newAddresses,
776
2340
  source: "injected-extension-account-change",
777
2341
  authUserId
778
2342
  });
779
2343
  };
780
- const cleanupConnect = this.phantom.solana.addEventListener("connect", handleSolanaConnect);
781
- const cleanupDisconnect = this.phantom.solana.addEventListener("disconnect", handleSolanaDisconnect);
782
- const cleanupAccountChanged = this.phantom.solana.addEventListener("accountChanged", handleSolanaAccountChanged);
2344
+ const cleanupConnect = phantom.solana.addEventListener("connect", handleSolanaConnect);
2345
+ const cleanupDisconnect = phantom.solana.addEventListener("disconnect", handleSolanaDisconnect);
2346
+ const cleanupAccountChanged = phantom.solana.addEventListener("accountChanged", handleSolanaAccountChanged);
783
2347
  this.browserInjectedCleanupFunctions.push(cleanupConnect, cleanupDisconnect, cleanupAccountChanged);
784
2348
  }
785
- setupEthereumEvents() {
2349
+ setupEthereumEvents(phantom) {
786
2350
  debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up Ethereum event listeners");
787
2351
  const handleEthereumConnect = async (accounts) => {
788
2352
  debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum connect event received", { accounts });
789
- this.addresses = this.addresses.filter((addr) => addr.addressType !== AddressType4.ethereum);
790
- if (accounts && accounts.length > 0) {
791
- this.addresses.push(
792
- ...accounts.map((address) => ({
793
- addressType: AddressType4.ethereum,
794
- address
795
- }))
796
- );
797
- }
798
- this.connected = this.addresses.length > 0;
2353
+ const walletId = this.selectedWalletId || "phantom";
2354
+ const state = this.getWalletState(walletId);
2355
+ const ethAddresses = accounts.map((address) => ({ addressType: AddressType2.ethereum, address }));
2356
+ const otherAddresses = state.addresses.filter((addr) => addr.addressType !== AddressType2.ethereum);
2357
+ const newAddresses = [...otherAddresses, ...ethAddresses];
2358
+ this.setWalletState(walletId, {
2359
+ connected: true,
2360
+ addresses: newAddresses
2361
+ });
799
2362
  const authUserId = await this.getAuthUserId("Ethereum connect event");
800
2363
  this.emit("connect", {
801
- addresses: this.addresses,
2364
+ addresses: newAddresses,
802
2365
  source: "injected-extension",
803
2366
  authUserId
804
2367
  });
805
2368
  };
806
2369
  const handleEthereumDisconnect = () => {
807
2370
  debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum disconnect event received");
808
- this.addresses = this.addresses.filter((addr) => addr.addressType !== AddressType4.ethereum);
809
- this.connected = false;
2371
+ const walletId = this.selectedWalletId || "phantom";
2372
+ const state = this.getWalletState(walletId);
2373
+ const filteredAddresses = state.addresses.filter((addr) => addr.addressType !== AddressType2.ethereum);
2374
+ this.setWalletState(walletId, {
2375
+ connected: filteredAddresses.length > 0,
2376
+ addresses: filteredAddresses
2377
+ });
810
2378
  this.emit("disconnect", {
811
2379
  source: "injected-extension"
812
2380
  });
813
2381
  };
814
2382
  const handleEthereumAccountsChanged = async (accounts) => {
815
2383
  debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum accounts changed event received", { accounts });
816
- this.addresses = this.addresses.filter((addr) => addr.addressType !== AddressType4.ethereum);
2384
+ const walletId = this.selectedWalletId || "phantom";
2385
+ const state = this.getWalletState(walletId);
2386
+ const otherAddresses = state.addresses.filter((addr) => addr.addressType !== AddressType2.ethereum);
817
2387
  if (accounts && accounts.length > 0) {
818
- this.addresses.push(
819
- ...accounts.map((address) => ({
820
- addressType: AddressType4.ethereum,
821
- address
822
- }))
823
- );
2388
+ const ethAddresses = accounts.map((address) => ({ addressType: AddressType2.ethereum, address }));
2389
+ const newAddresses = [...otherAddresses, ...ethAddresses];
2390
+ this.setWalletState(walletId, {
2391
+ connected: true,
2392
+ addresses: newAddresses
2393
+ });
824
2394
  const authUserId = await this.getAuthUserId("Ethereum accounts changed event");
825
2395
  this.emit("connect", {
826
- addresses: this.addresses,
2396
+ addresses: newAddresses,
827
2397
  source: "injected-extension-account-change",
828
2398
  authUserId
829
2399
  });
830
2400
  } else {
831
- this.connected = false;
2401
+ this.setWalletState(walletId, {
2402
+ connected: otherAddresses.length > 0,
2403
+ addresses: otherAddresses
2404
+ });
832
2405
  this.emit("disconnect", {
833
2406
  source: "injected-extension-account-change"
834
2407
  });
835
2408
  }
836
2409
  };
837
- const cleanupConnect = this.phantom.ethereum.addEventListener("connect", handleEthereumConnect);
838
- const cleanupDisconnect = this.phantom.ethereum.addEventListener("disconnect", handleEthereumDisconnect);
839
- const cleanupAccountsChanged = this.phantom.ethereum.addEventListener(
840
- "accountsChanged",
841
- handleEthereumAccountsChanged
842
- );
2410
+ const cleanupConnect = phantom.ethereum.addEventListener("connect", handleEthereumConnect);
2411
+ const cleanupDisconnect = phantom.ethereum.addEventListener("disconnect", handleEthereumDisconnect);
2412
+ const cleanupAccountsChanged = phantom.ethereum.addEventListener("accountsChanged", handleEthereumAccountsChanged);
843
2413
  this.browserInjectedCleanupFunctions.push(cleanupConnect, cleanupDisconnect, cleanupAccountsChanged);
844
2414
  }
845
- createCallbacks() {
846
- return {
847
- connect: async () => {
848
- const result = await this.connect({ provider: "injected" });
849
- return result.addresses;
850
- },
851
- disconnect: async () => {
852
- await this.disconnect();
853
- },
854
- isConnected: () => {
855
- return this.isConnected();
856
- },
857
- getAddresses: () => {
858
- return this.getAddresses();
859
- },
860
- on: (event, callback) => {
861
- this.on(event, callback);
862
- },
863
- off: (event, callback) => {
864
- this.off(event, callback);
2415
+ setupExternalWalletEvents(walletInfo) {
2416
+ if (isPhantomWallet(walletInfo)) {
2417
+ return;
2418
+ }
2419
+ if (!this.selectedWalletId || this.externalWalletEventListenersSetup.has(this.selectedWalletId)) {
2420
+ return;
2421
+ }
2422
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up external wallet event listeners", {
2423
+ walletId: this.selectedWalletId
2424
+ });
2425
+ if (walletInfo.providers?.ethereum) {
2426
+ const handleExternalEthereumAccountsChanged = async (accounts) => {
2427
+ debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum accounts changed event received", {
2428
+ walletId: this.selectedWalletId,
2429
+ accounts
2430
+ });
2431
+ const walletId = this.selectedWalletId;
2432
+ const state = this.getWalletState(walletId);
2433
+ const otherAddresses = state.addresses.filter((addr) => addr.addressType !== AddressType2.ethereum);
2434
+ if (accounts && accounts.length > 0) {
2435
+ const ethAddresses = accounts.map((address) => ({ addressType: AddressType2.ethereum, address }));
2436
+ const newAddresses = [...otherAddresses, ...ethAddresses];
2437
+ this.setWalletState(walletId, {
2438
+ connected: true,
2439
+ addresses: newAddresses
2440
+ });
2441
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Updated Ethereum addresses after account change", {
2442
+ walletId,
2443
+ oldCount: 0,
2444
+ // We filtered them out
2445
+ newCount: accounts.length,
2446
+ addresses: newAddresses.filter((addr) => addr.addressType === AddressType2.ethereum)
2447
+ });
2448
+ const authUserId = await this.getAuthUserId("External wallet Ethereum accounts changed event");
2449
+ this.emit("connect", {
2450
+ addresses: newAddresses,
2451
+ source: "external-wallet-account-change",
2452
+ authUserId
2453
+ });
2454
+ } else {
2455
+ this.setWalletState(walletId, {
2456
+ connected: otherAddresses.length > 0,
2457
+ addresses: otherAddresses
2458
+ });
2459
+ this.emit("disconnect", {
2460
+ source: "external-wallet-account-change"
2461
+ });
2462
+ }
2463
+ };
2464
+ if (typeof walletInfo.providers.ethereum.on === "function") {
2465
+ walletInfo.providers.ethereum.on("accountsChanged", handleExternalEthereumAccountsChanged);
2466
+ this.browserInjectedCleanupFunctions.push(() => {
2467
+ if (typeof walletInfo.providers?.ethereum?.off === "function") {
2468
+ walletInfo.providers.ethereum.off("accountsChanged", handleExternalEthereumAccountsChanged);
2469
+ }
2470
+ });
865
2471
  }
866
- };
2472
+ }
2473
+ if (walletInfo.providers?.solana) {
2474
+ const handleExternalSolanaAccountChanged = async (publicKey) => {
2475
+ debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Solana account changed event received", {
2476
+ walletId: this.selectedWalletId,
2477
+ publicKey
2478
+ });
2479
+ const walletId = this.selectedWalletId;
2480
+ const state = this.getWalletState(walletId);
2481
+ const otherAddresses = state.addresses.filter((addr) => addr.addressType !== AddressType2.solana);
2482
+ if (publicKey) {
2483
+ const newAddresses = [...otherAddresses, { addressType: AddressType2.solana, address: publicKey }];
2484
+ this.setWalletState(walletId, {
2485
+ connected: true,
2486
+ addresses: newAddresses
2487
+ });
2488
+ const authUserId = await this.getAuthUserId("External wallet Solana account changed event");
2489
+ this.emit("connect", {
2490
+ addresses: newAddresses,
2491
+ source: "external-wallet-account-change",
2492
+ authUserId
2493
+ });
2494
+ } else {
2495
+ this.setWalletState(walletId, {
2496
+ connected: otherAddresses.length > 0,
2497
+ addresses: otherAddresses
2498
+ });
2499
+ this.emit("disconnect", {
2500
+ source: "external-wallet-account-change"
2501
+ });
2502
+ }
2503
+ };
2504
+ if (typeof walletInfo.providers.solana.on === "function") {
2505
+ walletInfo.providers.solana.on("accountChanged", handleExternalSolanaAccountChanged);
2506
+ this.browserInjectedCleanupFunctions.push(() => {
2507
+ if (typeof walletInfo.providers?.solana?.off === "function") {
2508
+ walletInfo.providers.solana.off("accountChanged", handleExternalSolanaAccountChanged);
2509
+ }
2510
+ });
2511
+ }
2512
+ }
2513
+ if (this.selectedWalletId) {
2514
+ this.externalWalletEventListenersSetup.add(this.selectedWalletId);
2515
+ }
867
2516
  }
868
2517
  };
869
2518
 
@@ -1178,7 +2827,7 @@ var BrowserAuthProvider = class {
1178
2827
  // OAuth session management - defaults to allow refresh unless explicitly clearing after logout
1179
2828
  clear_previous_session: (phantomOptions.clearPreviousSession ?? false).toString(),
1180
2829
  allow_refresh: (phantomOptions.allowRefresh ?? true).toString(),
1181
- sdk_version: "1.0.0-beta.22",
2830
+ sdk_version: "1.0.0-beta.25",
1182
2831
  sdk_type: "browser",
1183
2832
  platform: detectBrowser().name
1184
2833
  });
@@ -1299,10 +2948,10 @@ var BrowserAuthProvider = class {
1299
2948
  };
1300
2949
 
1301
2950
  // src/providers/embedded/adapters/phantom-app.ts
1302
- import { isPhantomExtensionInstalled as isPhantomExtensionInstalled2 } from "@phantom/browser-injected-sdk";
2951
+ import { isPhantomExtensionInstalled as isPhantomExtensionInstalled3 } from "@phantom/browser-injected-sdk";
1303
2952
 
1304
2953
  // src/isPhantomLoginAvailable.ts
1305
- import { isPhantomExtensionInstalled } from "@phantom/browser-injected-sdk";
2954
+ import { isPhantomExtensionInstalled as isPhantomExtensionInstalled2 } from "@phantom/browser-injected-sdk";
1306
2955
  async function isPhantomLoginAvailable(timeoutMs = 3e3) {
1307
2956
  const extensionInstalled = await waitForExtension(timeoutMs);
1308
2957
  if (!extensionInstalled) {
@@ -1328,7 +2977,7 @@ async function waitForExtension(timeoutMs) {
1328
2977
  const checkInterval = 100;
1329
2978
  const checkForExtension = () => {
1330
2979
  try {
1331
- if (isPhantomExtensionInstalled()) {
2980
+ if (isPhantomExtensionInstalled2()) {
1332
2981
  resolve(true);
1333
2982
  return;
1334
2983
  }
@@ -1351,7 +3000,7 @@ var BrowserPhantomAppProvider = class {
1351
3000
  * Check if the Phantom extension is installed in the browser
1352
3001
  */
1353
3002
  isAvailable() {
1354
- return isPhantomExtensionInstalled2();
3003
+ return isPhantomExtensionInstalled3();
1355
3004
  }
1356
3005
  /**
1357
3006
  * Authenticate using the Phantom browser extension
@@ -1442,15 +3091,19 @@ var EmbeddedProvider = class extends CoreEmbeddedProvider {
1442
3091
  // Full user agent for more detailed info
1443
3092
  [ANALYTICS_HEADERS.APP_ID]: config.appId,
1444
3093
  [ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
1445
- [ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.22"
3094
+ [ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.25"
1446
3095
  // Replaced at build time
1447
3096
  }
1448
3097
  };
1449
3098
  debug.log(DebugCategory.EMBEDDED_PROVIDER, "Detected platform", { platformName });
1450
3099
  const logger = new BrowserLogger();
1451
3100
  super(config, platform, logger);
3101
+ this.addressTypes = config.addressTypes;
1452
3102
  debug.info(DebugCategory.EMBEDDED_PROVIDER, "Browser EmbeddedProvider initialized");
1453
3103
  }
3104
+ getEnabledAddressTypes() {
3105
+ return this.addressTypes;
3106
+ }
1454
3107
  };
1455
3108
 
1456
3109
  // src/ProviderManager.ts
@@ -1858,37 +3511,14 @@ var ProviderManager = class {
1858
3511
  }
1859
3512
  };
1860
3513
 
1861
- // src/waitForPhantomExtension.ts
1862
- import { isPhantomExtensionInstalled as isPhantomExtensionInstalled3 } from "@phantom/browser-injected-sdk";
1863
- async function waitForPhantomExtension(timeoutMs = 3e3) {
1864
- return new Promise((resolve) => {
1865
- const startTime = Date.now();
1866
- const checkInterval = 100;
1867
- const checkForExtension = () => {
1868
- try {
1869
- if (isPhantomExtensionInstalled3()) {
1870
- resolve(true);
1871
- return;
1872
- }
1873
- } catch (error) {
1874
- }
1875
- const elapsed = Date.now() - startTime;
1876
- if (elapsed >= timeoutMs) {
1877
- resolve(false);
1878
- return;
1879
- }
1880
- setTimeout(checkForExtension, checkInterval);
1881
- };
1882
- checkForExtension();
1883
- });
1884
- }
1885
-
1886
3514
  // src/BrowserSDK.ts
1887
3515
  import { EMBEDDED_PROVIDER_AUTH_TYPES as EMBEDDED_PROVIDER_AUTH_TYPES2 } from "@phantom/embedded-provider-core";
1888
3516
  import { DEFAULT_EMBEDDED_WALLET_TYPE as DEFAULT_EMBEDDED_WALLET_TYPE2 } from "@phantom/constants";
1889
3517
  var BROWSER_SDK_PROVIDER_TYPES = [...EMBEDDED_PROVIDER_AUTH_TYPES2, "injected"];
1890
3518
  var BrowserSDK = class {
1891
3519
  constructor(config) {
3520
+ this.walletRegistry = getWalletRegistry();
3521
+ this.isLoading = true;
1892
3522
  debug.info(DebugCategory.BROWSER_SDK, "Initializing BrowserSDK", {
1893
3523
  providers: config.providers,
1894
3524
  embeddedWalletType: config.embeddedWalletType,
@@ -1924,7 +3554,14 @@ var BrowserSDK = class {
1924
3554
  `Invalid embeddedWalletType: ${config.embeddedWalletType}. Must be "app-wallet" or "user-wallet".`
1925
3555
  );
1926
3556
  }
3557
+ this.config = config;
1927
3558
  this.providerManager = new ProviderManager(config);
3559
+ void this.discoverWallets();
3560
+ }
3561
+ discoverWallets() {
3562
+ return this.walletRegistry.discover(this.config.addressTypes).finally(() => {
3563
+ this.isLoading = false;
3564
+ });
1928
3565
  }
1929
3566
  // ===== CHAIN API =====
1930
3567
  /**
@@ -1997,13 +3634,20 @@ var BrowserSDK = class {
1997
3634
  getCurrentProviderInfo() {
1998
3635
  return this.providerManager.getCurrentProviderInfo();
1999
3636
  }
2000
- // ===== UTILITY METHODS =====
2001
3637
  /**
2002
- * Check if Phantom extension is installed
3638
+ * Get enabled address types for the current provider
3639
+ * - For embedded provider: returns config.addressTypes
3640
+ * - For Phantom injected: returns config.addressTypes
3641
+ * - For discovered wallets: returns the wallet's addressTypes from registry
2003
3642
  */
2004
- static async isPhantomInstalled(timeoutMs) {
2005
- return waitForPhantomExtension(timeoutMs);
3643
+ getEnabledAddressTypes() {
3644
+ const currentProvider = this.providerManager.getCurrentProvider();
3645
+ if (!currentProvider) {
3646
+ return [];
3647
+ }
3648
+ return currentProvider.getEnabledAddressTypes();
2006
3649
  }
3650
+ // ===== UTILITY METHODS =====
2007
3651
  /**
2008
3652
  * Add event listener for provider events (connect, connect_start, connect_error, disconnect, error)
2009
3653
  * Works with both embedded and injected providers
@@ -2036,40 +3680,21 @@ var BrowserSDK = class {
2036
3680
  debug.log(DebugCategory.BROWSER_SDK, "Auto-connect failed for all providers");
2037
3681
  }
2038
3682
  }
2039
- /**
2040
- * Debug configuration methods
2041
- * These allow dynamic debug configuration without SDK reinstantiation
2042
- */
2043
- /**
2044
- * Enable debug logging
2045
- */
2046
3683
  enableDebug() {
2047
3684
  debug.enable();
2048
3685
  debug.info(DebugCategory.BROWSER_SDK, "Debug logging enabled");
2049
3686
  }
2050
- /**
2051
- * Disable debug logging
2052
- */
2053
3687
  disableDebug() {
2054
3688
  debug.disable();
2055
3689
  }
2056
- /**
2057
- * Set debug level
2058
- */
2059
3690
  setDebugLevel(level) {
2060
3691
  debug.setLevel(level);
2061
3692
  debug.info(DebugCategory.BROWSER_SDK, "Debug level updated", { level });
2062
3693
  }
2063
- /**
2064
- * Set debug callback function
2065
- */
2066
3694
  setDebugCallback(callback) {
2067
3695
  debug.setCallback(callback);
2068
3696
  debug.info(DebugCategory.BROWSER_SDK, "Debug callback updated");
2069
3697
  }
2070
- /**
2071
- * Configure debug settings all at once
2072
- */
2073
3698
  configureDebug(config) {
2074
3699
  if (config.enabled !== void 0) {
2075
3700
  if (config.enabled) {
@@ -2175,6 +3800,22 @@ var BrowserSDK = class {
2175
3800
  throw error;
2176
3801
  }
2177
3802
  }
3803
+ getDiscoveredWallets() {
3804
+ debug.log(DebugCategory.BROWSER_SDK, "Getting discovered wallets");
3805
+ try {
3806
+ const allWallets = this.walletRegistry.getByAddressTypes(this.config.addressTypes);
3807
+ debug.log(DebugCategory.BROWSER_SDK, "Retrieved discovered wallets", {
3808
+ count: allWallets.length,
3809
+ walletIds: allWallets.map((w) => w.id)
3810
+ });
3811
+ return allWallets;
3812
+ } catch (error) {
3813
+ debug.error(DebugCategory.BROWSER_SDK, "Failed to get discovered wallets", {
3814
+ error: error.message
3815
+ });
3816
+ return [];
3817
+ }
3818
+ }
2178
3819
  };
2179
3820
 
2180
3821
  // src/utils/deeplink.ts
@@ -2187,11 +3828,36 @@ function getDeeplinkToPhantom(ref) {
2187
3828
  return `https://phantom.app/ul/browse/${currentUrl}${refParam}`;
2188
3829
  }
2189
3830
 
3831
+ // src/waitForPhantomExtension.ts
3832
+ import { isPhantomExtensionInstalled as isPhantomExtensionInstalled4 } from "@phantom/browser-injected-sdk";
3833
+ async function waitForPhantomExtension(timeoutMs = 3e3) {
3834
+ return new Promise((resolve) => {
3835
+ const startTime = Date.now();
3836
+ const checkInterval = 100;
3837
+ const checkForExtension = () => {
3838
+ try {
3839
+ if (isPhantomExtensionInstalled4()) {
3840
+ resolve(true);
3841
+ return;
3842
+ }
3843
+ } catch (error) {
3844
+ }
3845
+ const elapsed = Date.now() - startTime;
3846
+ if (elapsed >= timeoutMs) {
3847
+ resolve(false);
3848
+ return;
3849
+ }
3850
+ setTimeout(checkForExtension, checkInterval);
3851
+ };
3852
+ checkForExtension();
3853
+ });
3854
+ }
3855
+
2190
3856
  // src/index.ts
2191
3857
  import { NetworkId } from "@phantom/constants";
2192
- import { AddressType as AddressType5 } from "@phantom/client";
3858
+ import { AddressType as AddressType3 } from "@phantom/client";
2193
3859
  export {
2194
- AddressType5 as AddressType,
3860
+ AddressType3 as AddressType,
2195
3861
  BrowserSDK,
2196
3862
  DebugCategory,
2197
3863
  DebugLevel,