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