@phantom/browser-sdk 1.0.0-beta.21 → 1.0.0-beta.24
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 +188 -91
- package/dist/index.d.ts +49 -61
- package/dist/index.js +2263 -494
- package/dist/index.mjs +2255 -496
- 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) => {
|
|
@@ -64,111 +70,1435 @@ var Debug = class {
|
|
|
64
70
|
if (!Debug.instance) {
|
|
65
71
|
Debug.instance = new Debug();
|
|
66
72
|
}
|
|
67
|
-
return Debug.instance;
|
|
68
|
-
}
|
|
69
|
-
setCallback(callback) {
|
|
70
|
-
this.callback = callback;
|
|
73
|
+
return Debug.instance;
|
|
74
|
+
}
|
|
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 getPhantomIconFromWalletStandard() {
|
|
401
|
+
if (typeof window === "undefined" || typeof navigator === "undefined") {
|
|
402
|
+
return null;
|
|
403
|
+
}
|
|
404
|
+
const walletsAPI = navigator.wallets;
|
|
405
|
+
if (!walletsAPI || typeof walletsAPI.getWallets !== "function") {
|
|
406
|
+
return null;
|
|
407
|
+
}
|
|
408
|
+
try {
|
|
409
|
+
const walletsGetter = walletsAPI.getWallets();
|
|
410
|
+
if (walletsGetter && typeof walletsGetter.get === "function") {
|
|
411
|
+
const registeredWallets = walletsGetter.get();
|
|
412
|
+
const phantomWallet = registeredWallets.find((w) => w.name.toLowerCase().includes("phantom"));
|
|
413
|
+
if (phantomWallet?.icon) {
|
|
414
|
+
return phantomWallet.icon;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
} catch (error) {
|
|
418
|
+
}
|
|
419
|
+
return null;
|
|
420
|
+
}
|
|
421
|
+
async function discoverPhantomWallet(addressTypes) {
|
|
422
|
+
if (typeof window === "undefined") {
|
|
423
|
+
return null;
|
|
424
|
+
}
|
|
425
|
+
if (!(0, import_browser_injected_sdk.isPhantomExtensionInstalled)()) {
|
|
426
|
+
return null;
|
|
427
|
+
}
|
|
428
|
+
let icon = await getPhantomIconFromWalletStandard();
|
|
429
|
+
if (!icon) {
|
|
430
|
+
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
431
|
+
icon = await getPhantomIconFromWalletStandard();
|
|
432
|
+
}
|
|
433
|
+
if (!icon) {
|
|
434
|
+
icon = "https://phantom.app/img/phantom-icon-purple.png";
|
|
435
|
+
}
|
|
436
|
+
const plugins = [(0, import_browser_injected_sdk2.createExtensionPlugin)()];
|
|
437
|
+
if (addressTypes.includes(import_client2.AddressType.solana)) {
|
|
438
|
+
plugins.push((0, import_solana.createSolanaPlugin)());
|
|
439
|
+
}
|
|
440
|
+
if (addressTypes.includes(import_client2.AddressType.ethereum)) {
|
|
441
|
+
plugins.push((0, import_ethereum.createEthereumPlugin)());
|
|
442
|
+
}
|
|
443
|
+
plugins.push((0, import_auto_confirm.createAutoConfirmPlugin)());
|
|
444
|
+
const phantomInstance = (0, import_browser_injected_sdk2.createPhantom)({ plugins });
|
|
445
|
+
return {
|
|
446
|
+
id: "phantom",
|
|
447
|
+
name: "Phantom",
|
|
448
|
+
icon,
|
|
449
|
+
addressTypes,
|
|
450
|
+
providers: {
|
|
451
|
+
solana: addressTypes.includes(import_client2.AddressType.solana) ? phantomInstance.solana : void 0,
|
|
452
|
+
ethereum: addressTypes.includes(import_client2.AddressType.ethereum) ? phantomInstance.ethereum : void 0
|
|
453
|
+
},
|
|
454
|
+
isPhantom: true,
|
|
455
|
+
phantomInstance
|
|
456
|
+
};
|
|
457
|
+
}
|
|
458
|
+
async function discoverWallets(addressTypes) {
|
|
459
|
+
const requestedAddressTypes = addressTypes || [];
|
|
460
|
+
debug.log(DebugCategory.BROWSER_SDK, "Starting all wallet discovery methods", {
|
|
461
|
+
addressTypes: requestedAddressTypes
|
|
462
|
+
});
|
|
463
|
+
const [phantomWallet, solanaWallets, ethereumWallets] = await Promise.all([
|
|
464
|
+
discoverPhantomWallet(requestedAddressTypes),
|
|
465
|
+
discoverSolanaWallets(),
|
|
466
|
+
discoverEthereumWallets()
|
|
467
|
+
]);
|
|
468
|
+
debug.log(DebugCategory.BROWSER_SDK, "All wallet discovery methods completed", {
|
|
469
|
+
phantomFound: !!phantomWallet,
|
|
470
|
+
solanaWalletsCount: solanaWallets.length,
|
|
471
|
+
ethereumWalletsCount: ethereumWallets.length,
|
|
472
|
+
solanaWalletIds: solanaWallets.map((w) => w.id),
|
|
473
|
+
ethereumWalletIds: ethereumWallets.map((w) => w.id)
|
|
474
|
+
});
|
|
475
|
+
const walletMap = /* @__PURE__ */ new Map();
|
|
476
|
+
if (phantomWallet) {
|
|
477
|
+
walletMap.set("phantom", phantomWallet);
|
|
478
|
+
}
|
|
479
|
+
for (const wallet of [...solanaWallets, ...ethereumWallets]) {
|
|
480
|
+
const existing = walletMap.get(wallet.id);
|
|
481
|
+
if (existing) {
|
|
482
|
+
const mergedAddressTypes = Array.from(/* @__PURE__ */ new Set([...existing.addressTypes, ...wallet.addressTypes]));
|
|
483
|
+
const mergedProviders = {
|
|
484
|
+
...existing.providers,
|
|
485
|
+
...wallet.providers
|
|
486
|
+
};
|
|
487
|
+
const mergedWallet = {
|
|
488
|
+
...existing,
|
|
489
|
+
addressTypes: mergedAddressTypes,
|
|
490
|
+
// Prefer icon from the most recent discovery
|
|
491
|
+
icon: wallet.icon || existing.icon,
|
|
492
|
+
providers: mergedProviders
|
|
493
|
+
};
|
|
494
|
+
walletMap.set(wallet.id, mergedWallet);
|
|
495
|
+
debug.log(DebugCategory.BROWSER_SDK, "Merged wallet by ID", {
|
|
496
|
+
walletName: wallet.name,
|
|
497
|
+
walletId: wallet.id,
|
|
498
|
+
existingAddressTypes: existing.addressTypes,
|
|
499
|
+
newAddressTypes: wallet.addressTypes,
|
|
500
|
+
mergedAddressTypes,
|
|
501
|
+
existingProviders: Object.keys(existing.providers || {}),
|
|
502
|
+
newProviders: Object.keys(wallet.providers || {}),
|
|
503
|
+
mergedProviders: Object.keys(mergedProviders)
|
|
504
|
+
});
|
|
505
|
+
debug.log(DebugCategory.BROWSER_SDK, "Merged wallet from multiple discovery methods", {
|
|
506
|
+
walletId: wallet.id,
|
|
507
|
+
walletName: wallet.name,
|
|
508
|
+
existingAddressTypes: existing.addressTypes,
|
|
509
|
+
newAddressTypes: wallet.addressTypes,
|
|
510
|
+
mergedAddressTypes
|
|
511
|
+
});
|
|
512
|
+
} else {
|
|
513
|
+
walletMap.set(wallet.id, wallet);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
return Array.from(walletMap.values());
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
// src/providers/injected/chains/InjectedWalletSolanaChain.ts
|
|
520
|
+
var import_eventemitter3 = require("eventemitter3");
|
|
521
|
+
var import_buffer = require("buffer");
|
|
522
|
+
var InjectedWalletSolanaChain = class {
|
|
523
|
+
constructor(provider, walletId, walletName) {
|
|
524
|
+
this.eventEmitter = new import_eventemitter3.EventEmitter();
|
|
525
|
+
this._connected = false;
|
|
526
|
+
this._publicKey = null;
|
|
527
|
+
this.provider = provider;
|
|
528
|
+
this.walletId = walletId;
|
|
529
|
+
this.walletName = walletName;
|
|
530
|
+
this.setupEventListeners();
|
|
531
|
+
}
|
|
532
|
+
get connected() {
|
|
533
|
+
return this._connected;
|
|
534
|
+
}
|
|
535
|
+
get publicKey() {
|
|
536
|
+
return this._publicKey;
|
|
537
|
+
}
|
|
538
|
+
async connect(options) {
|
|
539
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Solana connect", {
|
|
540
|
+
walletId: this.walletId,
|
|
541
|
+
walletName: this.walletName,
|
|
542
|
+
onlyIfTrusted: options?.onlyIfTrusted
|
|
543
|
+
});
|
|
544
|
+
try {
|
|
545
|
+
const result = await this.provider.connect(options);
|
|
546
|
+
if (typeof result === "string") {
|
|
547
|
+
this._connected = true;
|
|
548
|
+
this._publicKey = result;
|
|
549
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Solana connected", {
|
|
550
|
+
walletId: this.walletId,
|
|
551
|
+
walletName: this.walletName,
|
|
552
|
+
publicKey: result
|
|
553
|
+
});
|
|
554
|
+
return { publicKey: result };
|
|
555
|
+
}
|
|
556
|
+
if (typeof result === "object" && result !== null && "publicKey" in result) {
|
|
557
|
+
this._connected = true;
|
|
558
|
+
this._publicKey = result.publicKey;
|
|
559
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Solana connected", {
|
|
560
|
+
walletId: this.walletId,
|
|
561
|
+
walletName: this.walletName,
|
|
562
|
+
publicKey: result.publicKey
|
|
563
|
+
});
|
|
564
|
+
return result;
|
|
565
|
+
}
|
|
566
|
+
if (Array.isArray(result) && result.length > 0) {
|
|
567
|
+
const firstAccount = result[0];
|
|
568
|
+
if (typeof firstAccount === "object" && firstAccount !== null && "address" in firstAccount) {
|
|
569
|
+
this._connected = true;
|
|
570
|
+
this._publicKey = firstAccount.address;
|
|
571
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Solana connected", {
|
|
572
|
+
walletId: this.walletId,
|
|
573
|
+
walletName: this.walletName,
|
|
574
|
+
publicKey: firstAccount.address
|
|
575
|
+
});
|
|
576
|
+
return { publicKey: firstAccount.address };
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
throw new Error("Unexpected connect result format");
|
|
580
|
+
} catch (error) {
|
|
581
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Solana connect failed", {
|
|
582
|
+
walletId: this.walletId,
|
|
583
|
+
walletName: this.walletName,
|
|
584
|
+
error: error instanceof Error ? error.message : String(error)
|
|
585
|
+
});
|
|
586
|
+
throw error;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
async disconnect() {
|
|
590
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Solana disconnect", {
|
|
591
|
+
walletId: this.walletId,
|
|
592
|
+
walletName: this.walletName
|
|
593
|
+
});
|
|
594
|
+
try {
|
|
595
|
+
await this.provider.disconnect();
|
|
596
|
+
this._connected = false;
|
|
597
|
+
this._publicKey = null;
|
|
598
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Solana disconnected", {
|
|
599
|
+
walletId: this.walletId,
|
|
600
|
+
walletName: this.walletName
|
|
601
|
+
});
|
|
602
|
+
} catch (error) {
|
|
603
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Solana disconnect failed", {
|
|
604
|
+
walletId: this.walletId,
|
|
605
|
+
walletName: this.walletName,
|
|
606
|
+
error: error instanceof Error ? error.message : String(error)
|
|
607
|
+
});
|
|
608
|
+
throw error;
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
async signMessage(message) {
|
|
612
|
+
const messageBytes = typeof message === "string" ? new TextEncoder().encode(message) : message;
|
|
613
|
+
const messagePreview = typeof message === "string" ? message.substring(0, 50) : `${messageBytes.length} bytes`;
|
|
614
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signMessage", {
|
|
615
|
+
walletId: this.walletId,
|
|
616
|
+
walletName: this.walletName,
|
|
617
|
+
messagePreview,
|
|
618
|
+
messageLength: messageBytes.length
|
|
619
|
+
});
|
|
620
|
+
try {
|
|
621
|
+
const result = await this.provider.signMessage(message);
|
|
622
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signMessage success", {
|
|
623
|
+
walletId: this.walletId,
|
|
624
|
+
walletName: this.walletName,
|
|
625
|
+
signatureLength: result.signature.length
|
|
626
|
+
});
|
|
627
|
+
return {
|
|
628
|
+
signature: result.signature instanceof Uint8Array ? result.signature : new Uint8Array(import_buffer.Buffer.from(result.signature, "base64")),
|
|
629
|
+
publicKey: result.publicKey || this._publicKey || ""
|
|
630
|
+
};
|
|
631
|
+
} catch (error) {
|
|
632
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signMessage failed", {
|
|
633
|
+
walletId: this.walletId,
|
|
634
|
+
walletName: this.walletName,
|
|
635
|
+
error: error instanceof Error ? error.message : String(error)
|
|
636
|
+
});
|
|
637
|
+
throw error;
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
async signTransaction(transaction) {
|
|
641
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signTransaction", {
|
|
642
|
+
walletId: this.walletId,
|
|
643
|
+
walletName: this.walletName
|
|
644
|
+
});
|
|
645
|
+
try {
|
|
646
|
+
const result = await this.provider.signTransaction(transaction);
|
|
647
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signTransaction success", {
|
|
648
|
+
walletId: this.walletId,
|
|
649
|
+
walletName: this.walletName
|
|
650
|
+
});
|
|
651
|
+
return result;
|
|
652
|
+
} catch (error) {
|
|
653
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signTransaction failed", {
|
|
654
|
+
walletId: this.walletId,
|
|
655
|
+
walletName: this.walletName,
|
|
656
|
+
error: error instanceof Error ? error.message : String(error)
|
|
657
|
+
});
|
|
658
|
+
throw error;
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
async signAndSendTransaction(transaction) {
|
|
662
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signAndSendTransaction", {
|
|
663
|
+
walletId: this.walletId,
|
|
664
|
+
walletName: this.walletName
|
|
665
|
+
});
|
|
666
|
+
try {
|
|
667
|
+
const result = await this.provider.signAndSendTransaction(transaction);
|
|
668
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signAndSendTransaction success", {
|
|
669
|
+
walletId: this.walletId,
|
|
670
|
+
walletName: this.walletName,
|
|
671
|
+
signature: result.signature
|
|
672
|
+
});
|
|
673
|
+
return result;
|
|
674
|
+
} catch (error) {
|
|
675
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signAndSendTransaction failed", {
|
|
676
|
+
walletId: this.walletId,
|
|
677
|
+
walletName: this.walletName,
|
|
678
|
+
error: error instanceof Error ? error.message : String(error)
|
|
679
|
+
});
|
|
680
|
+
throw error;
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
async signAllTransactions(transactions) {
|
|
684
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signAllTransactions", {
|
|
685
|
+
walletId: this.walletId,
|
|
686
|
+
walletName: this.walletName,
|
|
687
|
+
transactionCount: transactions.length
|
|
688
|
+
});
|
|
689
|
+
try {
|
|
690
|
+
const result = await this.provider.signAllTransactions(transactions);
|
|
691
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signAllTransactions success", {
|
|
692
|
+
walletId: this.walletId,
|
|
693
|
+
walletName: this.walletName,
|
|
694
|
+
signedCount: result.length
|
|
695
|
+
});
|
|
696
|
+
return result;
|
|
697
|
+
} catch (error) {
|
|
698
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signAllTransactions failed", {
|
|
699
|
+
walletId: this.walletId,
|
|
700
|
+
walletName: this.walletName,
|
|
701
|
+
error: error instanceof Error ? error.message : String(error)
|
|
702
|
+
});
|
|
703
|
+
throw error;
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
async signAndSendAllTransactions(transactions) {
|
|
707
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signAndSendAllTransactions", {
|
|
708
|
+
walletId: this.walletId,
|
|
709
|
+
walletName: this.walletName,
|
|
710
|
+
transactionCount: transactions.length
|
|
711
|
+
});
|
|
712
|
+
try {
|
|
713
|
+
const result = await this.provider.signAndSendAllTransactions(transactions);
|
|
714
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signAndSendAllTransactions success", {
|
|
715
|
+
walletId: this.walletId,
|
|
716
|
+
walletName: this.walletName,
|
|
717
|
+
signatureCount: result.signatures.length
|
|
718
|
+
});
|
|
719
|
+
return result;
|
|
720
|
+
} catch (error) {
|
|
721
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Solana signAndSendAllTransactions failed", {
|
|
722
|
+
walletId: this.walletId,
|
|
723
|
+
walletName: this.walletName,
|
|
724
|
+
error: error instanceof Error ? error.message : String(error)
|
|
725
|
+
});
|
|
726
|
+
throw error;
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
switchNetwork(_network) {
|
|
730
|
+
return Promise.resolve();
|
|
731
|
+
}
|
|
732
|
+
getPublicKey() {
|
|
733
|
+
return Promise.resolve(this._publicKey);
|
|
734
|
+
}
|
|
735
|
+
isConnected() {
|
|
736
|
+
return this._connected;
|
|
737
|
+
}
|
|
738
|
+
setupEventListeners() {
|
|
739
|
+
if (typeof this.provider.on === "function") {
|
|
740
|
+
this.provider.on("connect", (publicKey) => {
|
|
741
|
+
this._connected = true;
|
|
742
|
+
this._publicKey = publicKey;
|
|
743
|
+
this.eventEmitter.emit("connect", publicKey);
|
|
744
|
+
});
|
|
745
|
+
this.provider.on("disconnect", () => {
|
|
746
|
+
this._connected = false;
|
|
747
|
+
this._publicKey = null;
|
|
748
|
+
this.eventEmitter.emit("disconnect");
|
|
749
|
+
});
|
|
750
|
+
this.provider.on("accountChanged", (publicKey) => {
|
|
751
|
+
this._publicKey = publicKey;
|
|
752
|
+
this.eventEmitter.emit("accountChanged", publicKey);
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
on(event, listener) {
|
|
757
|
+
this.eventEmitter.on(event, listener);
|
|
758
|
+
}
|
|
759
|
+
off(event, listener) {
|
|
760
|
+
this.eventEmitter.off(event, listener);
|
|
761
|
+
}
|
|
762
|
+
};
|
|
763
|
+
|
|
764
|
+
// src/providers/injected/chains/WalletStandardSolanaAdapter.ts
|
|
765
|
+
var import_parsers = require("@phantom/parsers");
|
|
766
|
+
var import_bs58 = __toESM(require("bs58"));
|
|
767
|
+
var WalletStandardSolanaAdapter = class {
|
|
768
|
+
constructor(wallet, walletId, walletName) {
|
|
769
|
+
this._connected = false;
|
|
770
|
+
this._publicKey = null;
|
|
771
|
+
this.wallet = wallet;
|
|
772
|
+
this.walletId = walletId;
|
|
773
|
+
this.walletName = walletName;
|
|
774
|
+
}
|
|
775
|
+
get connected() {
|
|
776
|
+
return this._connected;
|
|
777
|
+
}
|
|
778
|
+
get publicKey() {
|
|
779
|
+
return this._publicKey;
|
|
780
|
+
}
|
|
781
|
+
async connect(_options) {
|
|
782
|
+
try {
|
|
783
|
+
const connectFeature = this.wallet.features?.["standard:connect"];
|
|
784
|
+
if (!connectFeature || typeof connectFeature.connect !== "function") {
|
|
785
|
+
throw new Error("Wallet Standard connect feature not available");
|
|
786
|
+
}
|
|
787
|
+
const connectResult = await connectFeature.connect();
|
|
788
|
+
let accounts;
|
|
789
|
+
if (Array.isArray(connectResult) && connectResult.length > 0) {
|
|
790
|
+
accounts = connectResult;
|
|
791
|
+
} else if (this.wallet.accounts && this.wallet.accounts.length > 0) {
|
|
792
|
+
accounts = Array.from(this.wallet.accounts);
|
|
793
|
+
}
|
|
794
|
+
if (!accounts || accounts.length === 0) {
|
|
795
|
+
throw new Error("No accounts available after connecting to wallet");
|
|
796
|
+
}
|
|
797
|
+
const firstAccount = accounts[0];
|
|
798
|
+
if (!firstAccount) {
|
|
799
|
+
throw new Error("First account is null or undefined");
|
|
800
|
+
}
|
|
801
|
+
let address;
|
|
802
|
+
if (typeof firstAccount === "string") {
|
|
803
|
+
address = firstAccount;
|
|
804
|
+
} else if (typeof firstAccount === "object" && firstAccount !== null) {
|
|
805
|
+
address = firstAccount.address || firstAccount.publicKey?.toString() || (firstAccount.publicKey instanceof Uint8Array ? Buffer.from(firstAccount.publicKey).toString("hex") : void 0);
|
|
806
|
+
}
|
|
807
|
+
if (!address) {
|
|
808
|
+
throw new Error(
|
|
809
|
+
`Could not extract address from account. Account structure: ${JSON.stringify(firstAccount, null, 2)}`
|
|
810
|
+
);
|
|
811
|
+
}
|
|
812
|
+
this._connected = true;
|
|
813
|
+
this._publicKey = address;
|
|
814
|
+
return { publicKey: address };
|
|
815
|
+
} catch (error) {
|
|
816
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "Wallet Standard Solana connect failed", {
|
|
817
|
+
walletId: this.walletId,
|
|
818
|
+
walletName: this.walletName,
|
|
819
|
+
error: error instanceof Error ? error.message : String(error)
|
|
820
|
+
});
|
|
821
|
+
throw error;
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
async disconnect() {
|
|
825
|
+
try {
|
|
826
|
+
const disconnectFeature = this.wallet.features?.["standard:disconnect"];
|
|
827
|
+
if (disconnectFeature && typeof disconnectFeature.disconnect === "function") {
|
|
828
|
+
await disconnectFeature.disconnect();
|
|
829
|
+
}
|
|
830
|
+
this._connected = false;
|
|
831
|
+
this._publicKey = null;
|
|
832
|
+
} catch (error) {
|
|
833
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "Wallet Standard Solana disconnect failed", {
|
|
834
|
+
walletId: this.walletId,
|
|
835
|
+
walletName: this.walletName,
|
|
836
|
+
error: error instanceof Error ? error.message : String(error)
|
|
837
|
+
});
|
|
838
|
+
throw error;
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
async signMessage(message) {
|
|
842
|
+
try {
|
|
843
|
+
const signMessageFeature = this.wallet.features?.["solana:signMessage"];
|
|
844
|
+
if (!signMessageFeature || typeof signMessageFeature.signMessage !== "function") {
|
|
845
|
+
throw new Error("Wallet Standard signMessage feature not available");
|
|
846
|
+
}
|
|
847
|
+
const messageBytes = typeof message === "string" ? new TextEncoder().encode(message) : message;
|
|
848
|
+
const result = await signMessageFeature.signMessage({
|
|
849
|
+
message: messageBytes,
|
|
850
|
+
account: this.wallet.accounts?.[0]
|
|
851
|
+
});
|
|
852
|
+
if (!Array.isArray(result) || result.length === 0) {
|
|
853
|
+
throw new Error(`Expected array result from signMessage, got: ${typeof result}`);
|
|
854
|
+
}
|
|
855
|
+
const signedMessageResult = result[0];
|
|
856
|
+
if (!signedMessageResult || !signedMessageResult.signature) {
|
|
857
|
+
throw new Error(`Invalid signMessage result structure: ${JSON.stringify(result)}`);
|
|
858
|
+
}
|
|
859
|
+
const signature = this.parseUint8Array(signedMessageResult.signature);
|
|
860
|
+
if (signature.length === 0) {
|
|
861
|
+
throw new Error(`Signature is empty`);
|
|
862
|
+
}
|
|
863
|
+
const publicKey = signedMessageResult.account?.address || this.wallet.accounts?.[0]?.address || this._publicKey || "";
|
|
864
|
+
return { signature, publicKey };
|
|
865
|
+
} catch (error) {
|
|
866
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "Wallet Standard Solana signMessage failed", {
|
|
867
|
+
walletId: this.walletId,
|
|
868
|
+
walletName: this.walletName,
|
|
869
|
+
error: error instanceof Error ? error.message : String(error)
|
|
870
|
+
});
|
|
871
|
+
throw error;
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
async signTransaction(transaction) {
|
|
875
|
+
try {
|
|
876
|
+
const signTransactionFeature = this.wallet.features?.["solana:signTransaction"];
|
|
877
|
+
if (!signTransactionFeature || typeof signTransactionFeature.signTransaction !== "function") {
|
|
878
|
+
throw new Error("Wallet Standard signTransaction feature not available");
|
|
879
|
+
}
|
|
880
|
+
if (!this.wallet.accounts || this.wallet.accounts.length === 0) {
|
|
881
|
+
throw new Error("No accounts available. Please connect first.");
|
|
882
|
+
}
|
|
883
|
+
const account = this.wallet.accounts[0];
|
|
884
|
+
const serializedTransaction = this.serializeTransaction(transaction);
|
|
885
|
+
const results = await signTransactionFeature.signTransaction({
|
|
886
|
+
transaction: serializedTransaction,
|
|
887
|
+
account
|
|
888
|
+
});
|
|
889
|
+
let transactionData;
|
|
890
|
+
if (Array.isArray(results) && results.length > 0) {
|
|
891
|
+
const firstItem = results[0];
|
|
892
|
+
if (firstItem && typeof firstItem === "object") {
|
|
893
|
+
transactionData = firstItem.signedTransaction || firstItem.transaction;
|
|
894
|
+
}
|
|
895
|
+
} else if (results && typeof results === "object" && !Array.isArray(results)) {
|
|
896
|
+
transactionData = results.transaction || results.signedTransaction;
|
|
897
|
+
}
|
|
898
|
+
if (!transactionData) {
|
|
899
|
+
throw new Error("No transaction data found in Wallet Standard result");
|
|
900
|
+
}
|
|
901
|
+
const signedBytes = this.parseUint8Array(transactionData);
|
|
902
|
+
if (signedBytes.length === 0) {
|
|
903
|
+
throw new Error("Empty signed transaction returned from Wallet Standard");
|
|
904
|
+
}
|
|
905
|
+
const signedTx = (0, import_parsers.deserializeSolanaTransaction)(signedBytes);
|
|
906
|
+
return signedTx;
|
|
907
|
+
} catch (error) {
|
|
908
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "Wallet Standard Solana signTransaction failed", {
|
|
909
|
+
walletId: this.walletId,
|
|
910
|
+
walletName: this.walletName,
|
|
911
|
+
error: error instanceof Error ? error.message : String(error)
|
|
912
|
+
});
|
|
913
|
+
throw error;
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
async signAndSendTransaction(transaction) {
|
|
917
|
+
try {
|
|
918
|
+
const signAndSendTransactionFeature = this.wallet.features?.["solana:signAndSendTransaction"];
|
|
919
|
+
if (!signAndSendTransactionFeature || typeof signAndSendTransactionFeature.signAndSendTransaction !== "function") {
|
|
920
|
+
throw new Error("Wallet Standard signAndSendTransaction feature not available");
|
|
921
|
+
}
|
|
922
|
+
if (!this.wallet.accounts || this.wallet.accounts.length === 0) {
|
|
923
|
+
throw new Error("No accounts available. Please connect first.");
|
|
924
|
+
}
|
|
925
|
+
const account = this.wallet.accounts[0];
|
|
926
|
+
const chain = account.chains?.[0] || "solana:mainnet";
|
|
927
|
+
const serializedTransaction = this.serializeTransaction(transaction);
|
|
928
|
+
const results = await signAndSendTransactionFeature.signAndSendTransaction({
|
|
929
|
+
transaction: serializedTransaction,
|
|
930
|
+
account,
|
|
931
|
+
chain
|
|
932
|
+
});
|
|
933
|
+
let signatureOutput;
|
|
934
|
+
if (Array.isArray(results) && results.length > 0) {
|
|
935
|
+
signatureOutput = results[0];
|
|
936
|
+
} else if (results && typeof results === "object" && !Array.isArray(results)) {
|
|
937
|
+
signatureOutput = results;
|
|
938
|
+
} else {
|
|
939
|
+
throw new Error("Invalid signAndSendTransaction result format");
|
|
940
|
+
}
|
|
941
|
+
if (!signatureOutput.signature) {
|
|
942
|
+
throw new Error("No signature found in signAndSendTransaction result");
|
|
943
|
+
}
|
|
944
|
+
const signatureBytes = this.parseUint8Array(signatureOutput.signature);
|
|
945
|
+
const signature = import_bs58.default.encode(signatureBytes);
|
|
946
|
+
return { signature };
|
|
947
|
+
} catch (error) {
|
|
948
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "Wallet Standard Solana signAndSendTransaction failed", {
|
|
949
|
+
walletId: this.walletId,
|
|
950
|
+
walletName: this.walletName,
|
|
951
|
+
error: error instanceof Error ? error.message : String(error)
|
|
952
|
+
});
|
|
953
|
+
throw error;
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
async signAllTransactions(transactions) {
|
|
957
|
+
try {
|
|
958
|
+
const signedTransactions = [];
|
|
959
|
+
for (const transaction of transactions) {
|
|
960
|
+
const signedTx = await this.signTransaction(transaction);
|
|
961
|
+
signedTransactions.push(signedTx);
|
|
962
|
+
}
|
|
963
|
+
return signedTransactions;
|
|
964
|
+
} catch (error) {
|
|
965
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "Wallet Standard Solana signAllTransactions failed", {
|
|
966
|
+
walletId: this.walletId,
|
|
967
|
+
walletName: this.walletName,
|
|
968
|
+
error: error instanceof Error ? error.message : String(error)
|
|
969
|
+
});
|
|
970
|
+
throw error;
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
async signAndSendAllTransactions(transactions) {
|
|
974
|
+
try {
|
|
975
|
+
const signatures = [];
|
|
976
|
+
for (const transaction of transactions) {
|
|
977
|
+
const result = await this.signAndSendTransaction(transaction);
|
|
978
|
+
signatures.push(result.signature);
|
|
979
|
+
}
|
|
980
|
+
return { signatures };
|
|
981
|
+
} catch (error) {
|
|
982
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "Wallet Standard Solana signAndSendAllTransactions failed", {
|
|
983
|
+
walletId: this.walletId,
|
|
984
|
+
walletName: this.walletName,
|
|
985
|
+
error: error instanceof Error ? error.message : String(error)
|
|
986
|
+
});
|
|
987
|
+
throw error;
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
async switchNetwork(network) {
|
|
991
|
+
try {
|
|
992
|
+
const switchNetworkFeature = this.wallet.features?.["standard:switchNetwork"];
|
|
993
|
+
if (switchNetworkFeature && typeof switchNetworkFeature.switchNetwork === "function") {
|
|
994
|
+
const chainId = network === "mainnet" ? "solana:mainnet" : "solana:devnet";
|
|
995
|
+
await switchNetworkFeature.switchNetwork({ chain: chainId });
|
|
996
|
+
}
|
|
997
|
+
} catch (error) {
|
|
998
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "Wallet Standard Solana switchNetwork failed", {
|
|
999
|
+
walletId: this.walletId,
|
|
1000
|
+
walletName: this.walletName,
|
|
1001
|
+
network,
|
|
1002
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1003
|
+
});
|
|
1004
|
+
throw error;
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
getPublicKey() {
|
|
1008
|
+
return Promise.resolve(this._publicKey);
|
|
1009
|
+
}
|
|
1010
|
+
isConnected() {
|
|
1011
|
+
return this._connected;
|
|
1012
|
+
}
|
|
1013
|
+
on(_event, _listener) {
|
|
1014
|
+
const eventsFeature = this.wallet.features?.["standard:events"];
|
|
1015
|
+
if (eventsFeature && typeof eventsFeature.on === "function") {
|
|
1016
|
+
eventsFeature.on(_event, _listener);
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
off(_event, _listener) {
|
|
1020
|
+
const eventsFeature = this.wallet.features?.["standard:events"];
|
|
1021
|
+
if (eventsFeature && typeof eventsFeature.off === "function") {
|
|
1022
|
+
eventsFeature.off(_event, _listener);
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
/**
|
|
1026
|
+
* Serialize a transaction to Uint8Array for Wallet Standard API
|
|
1027
|
+
*/
|
|
1028
|
+
serializeTransaction(transaction) {
|
|
1029
|
+
if (typeof transaction.serialize === "function") {
|
|
1030
|
+
return transaction.serialize({
|
|
1031
|
+
requireAllSignatures: false,
|
|
1032
|
+
verifySignatures: false
|
|
1033
|
+
});
|
|
1034
|
+
}
|
|
1035
|
+
if (transaction instanceof Uint8Array) {
|
|
1036
|
+
return transaction;
|
|
1037
|
+
}
|
|
1038
|
+
return new Uint8Array(0);
|
|
1039
|
+
}
|
|
1040
|
+
/**
|
|
1041
|
+
* Parse a Uint8Array from various formats
|
|
1042
|
+
* Handles: Uint8Array, Array, object with numeric keys (JSON-serialized Uint8Array)
|
|
1043
|
+
*/
|
|
1044
|
+
parseUint8Array(value) {
|
|
1045
|
+
if (value instanceof Uint8Array) {
|
|
1046
|
+
return value;
|
|
1047
|
+
}
|
|
1048
|
+
if (Array.isArray(value)) {
|
|
1049
|
+
return new Uint8Array(value);
|
|
1050
|
+
}
|
|
1051
|
+
if (typeof value === "object" && value !== null) {
|
|
1052
|
+
const keys = Object.keys(value).map(Number).filter((k) => !isNaN(k) && k >= 0).sort((a, b) => a - b);
|
|
1053
|
+
if (keys.length > 0) {
|
|
1054
|
+
const maxKey = Math.max(...keys);
|
|
1055
|
+
const array = new Uint8Array(maxKey + 1);
|
|
1056
|
+
for (const key of keys) {
|
|
1057
|
+
array[key] = Number(value[key]) || 0;
|
|
1058
|
+
}
|
|
1059
|
+
return array;
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
return new Uint8Array(0);
|
|
1063
|
+
}
|
|
1064
|
+
};
|
|
1065
|
+
|
|
1066
|
+
// src/providers/injected/chains/InjectedWalletEthereumChain.ts
|
|
1067
|
+
var import_eventemitter32 = require("eventemitter3");
|
|
1068
|
+
var InjectedWalletEthereumChain = class {
|
|
1069
|
+
constructor(provider, walletId, walletName) {
|
|
1070
|
+
this.eventEmitter = new import_eventemitter32.EventEmitter();
|
|
1071
|
+
this._connected = false;
|
|
1072
|
+
this._chainId = "0x1";
|
|
1073
|
+
this._accounts = [];
|
|
1074
|
+
this.provider = provider;
|
|
1075
|
+
this.walletId = walletId;
|
|
1076
|
+
this.walletName = walletName;
|
|
1077
|
+
this.setupEventListeners();
|
|
1078
|
+
}
|
|
1079
|
+
get connected() {
|
|
1080
|
+
return this._connected;
|
|
1081
|
+
}
|
|
1082
|
+
get chainId() {
|
|
1083
|
+
return this._chainId;
|
|
1084
|
+
}
|
|
1085
|
+
get accounts() {
|
|
1086
|
+
return this._accounts;
|
|
1087
|
+
}
|
|
1088
|
+
async request(args) {
|
|
1089
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum request", {
|
|
1090
|
+
walletId: this.walletId,
|
|
1091
|
+
walletName: this.walletName,
|
|
1092
|
+
method: args.method
|
|
1093
|
+
});
|
|
1094
|
+
try {
|
|
1095
|
+
const requiresAuth = [
|
|
1096
|
+
"personal_sign",
|
|
1097
|
+
"eth_sign",
|
|
1098
|
+
"eth_signTypedData",
|
|
1099
|
+
"eth_signTypedData_v4",
|
|
1100
|
+
"eth_sendTransaction",
|
|
1101
|
+
"eth_signTransaction"
|
|
1102
|
+
].includes(args.method);
|
|
1103
|
+
if (requiresAuth && (!this._connected || this._accounts.length === 0)) {
|
|
1104
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Method requires authorization, ensuring connection", {
|
|
1105
|
+
walletId: this.walletId,
|
|
1106
|
+
walletName: this.walletName,
|
|
1107
|
+
method: args.method
|
|
1108
|
+
});
|
|
1109
|
+
await this.connect();
|
|
1110
|
+
}
|
|
1111
|
+
const result = await this.provider.request(args);
|
|
1112
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum request success", {
|
|
1113
|
+
walletId: this.walletId,
|
|
1114
|
+
walletName: this.walletName,
|
|
1115
|
+
method: args.method
|
|
1116
|
+
});
|
|
1117
|
+
return result;
|
|
1118
|
+
} catch (error) {
|
|
1119
|
+
if (error?.code === 4100) {
|
|
1120
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Got 4100 Unauthorized, attempting to re-authorize", {
|
|
1121
|
+
walletId: this.walletId,
|
|
1122
|
+
walletName: this.walletName,
|
|
1123
|
+
method: args.method
|
|
1124
|
+
});
|
|
1125
|
+
try {
|
|
1126
|
+
await this.provider.request({ method: "eth_requestAccounts" });
|
|
1127
|
+
const result = await this.provider.request(args);
|
|
1128
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum request success (after re-auth)", {
|
|
1129
|
+
walletId: this.walletId,
|
|
1130
|
+
walletName: this.walletName,
|
|
1131
|
+
method: args.method
|
|
1132
|
+
});
|
|
1133
|
+
return result;
|
|
1134
|
+
} catch (retryError) {
|
|
1135
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "Failed after re-authorization", {
|
|
1136
|
+
walletId: this.walletId,
|
|
1137
|
+
walletName: this.walletName,
|
|
1138
|
+
method: args.method,
|
|
1139
|
+
error: retryError instanceof Error ? retryError.message : String(retryError)
|
|
1140
|
+
});
|
|
1141
|
+
throw retryError;
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum request failed", {
|
|
1145
|
+
walletId: this.walletId,
|
|
1146
|
+
walletName: this.walletName,
|
|
1147
|
+
method: args.method,
|
|
1148
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1149
|
+
errorCode: error?.code
|
|
1150
|
+
});
|
|
1151
|
+
throw error;
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
async connect() {
|
|
1155
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum connect", {
|
|
1156
|
+
walletId: this.walletId,
|
|
1157
|
+
walletName: this.walletName
|
|
1158
|
+
});
|
|
1159
|
+
try {
|
|
1160
|
+
const accounts = await this.provider.request({ method: "eth_requestAccounts" });
|
|
1161
|
+
this._connected = accounts.length > 0;
|
|
1162
|
+
this._accounts = accounts;
|
|
1163
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum connected (via eth_requestAccounts)", {
|
|
1164
|
+
walletId: this.walletId,
|
|
1165
|
+
walletName: this.walletName,
|
|
1166
|
+
accountCount: accounts.length,
|
|
1167
|
+
accounts
|
|
1168
|
+
});
|
|
1169
|
+
return accounts;
|
|
1170
|
+
} catch (error) {
|
|
1171
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum connect failed", {
|
|
1172
|
+
walletId: this.walletId,
|
|
1173
|
+
walletName: this.walletName,
|
|
1174
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1175
|
+
});
|
|
1176
|
+
throw error;
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
async disconnect() {
|
|
1180
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum disconnect", {
|
|
1181
|
+
walletId: this.walletId,
|
|
1182
|
+
walletName: this.walletName
|
|
1183
|
+
});
|
|
1184
|
+
try {
|
|
1185
|
+
await this.provider.disconnect();
|
|
1186
|
+
this._connected = false;
|
|
1187
|
+
this._accounts = [];
|
|
1188
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum disconnected", {
|
|
1189
|
+
walletId: this.walletId,
|
|
1190
|
+
walletName: this.walletName
|
|
1191
|
+
});
|
|
1192
|
+
} catch (error) {
|
|
1193
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum disconnect failed", {
|
|
1194
|
+
walletId: this.walletId,
|
|
1195
|
+
walletName: this.walletName,
|
|
1196
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1197
|
+
});
|
|
1198
|
+
throw error;
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
async signPersonalMessage(message, address) {
|
|
1202
|
+
const messagePreview = message.length > 50 ? message.substring(0, 50) + "..." : message;
|
|
1203
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum signPersonalMessage", {
|
|
1204
|
+
walletId: this.walletId,
|
|
1205
|
+
walletName: this.walletName,
|
|
1206
|
+
messagePreview,
|
|
1207
|
+
messageLength: message.length,
|
|
1208
|
+
address
|
|
1209
|
+
});
|
|
1210
|
+
try {
|
|
1211
|
+
const providerConnected = this.provider.isConnected?.() || this.provider.connected || false;
|
|
1212
|
+
if (!this._connected || this._accounts.length === 0 || !providerConnected) {
|
|
1213
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Not connected, attempting to connect before signing", {
|
|
1214
|
+
walletId: this.walletId,
|
|
1215
|
+
walletName: this.walletName,
|
|
1216
|
+
internalConnected: this._connected,
|
|
1217
|
+
accountsLength: this._accounts.length,
|
|
1218
|
+
providerConnected
|
|
1219
|
+
});
|
|
1220
|
+
await this.connect();
|
|
1221
|
+
}
|
|
1222
|
+
const normalizedAddress = address.toLowerCase();
|
|
1223
|
+
const normalizedAccounts = this._accounts.map((acc) => acc.toLowerCase());
|
|
1224
|
+
if (!normalizedAccounts.includes(normalizedAddress)) {
|
|
1225
|
+
debug.warn(DebugCategory.INJECTED_PROVIDER, "Address not in connected accounts, refreshing connection", {
|
|
1226
|
+
walletId: this.walletId,
|
|
1227
|
+
walletName: this.walletName,
|
|
1228
|
+
requestedAddress: address,
|
|
1229
|
+
connectedAccounts: this._accounts
|
|
1230
|
+
});
|
|
1231
|
+
const currentAccounts = await this.getAccounts();
|
|
1232
|
+
const normalizedCurrentAccounts = currentAccounts.map((acc) => acc.toLowerCase());
|
|
1233
|
+
if (!normalizedCurrentAccounts.includes(normalizedAddress)) {
|
|
1234
|
+
throw new Error(`Address ${address} is not connected. Connected accounts: ${currentAccounts.join(", ")}`);
|
|
1235
|
+
}
|
|
1236
|
+
this._accounts = currentAccounts;
|
|
1237
|
+
}
|
|
1238
|
+
if (typeof this.provider.signPersonalMessage === "function") {
|
|
1239
|
+
const result2 = await this.provider.signPersonalMessage(message, address);
|
|
1240
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum signPersonalMessage success", {
|
|
1241
|
+
walletId: this.walletId,
|
|
1242
|
+
walletName: this.walletName,
|
|
1243
|
+
signatureLength: result2.length
|
|
1244
|
+
});
|
|
1245
|
+
return result2;
|
|
1246
|
+
}
|
|
1247
|
+
const result = await this.request({
|
|
1248
|
+
method: "personal_sign",
|
|
1249
|
+
params: [message, address]
|
|
1250
|
+
});
|
|
1251
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum signPersonalMessage success", {
|
|
1252
|
+
walletId: this.walletId,
|
|
1253
|
+
walletName: this.walletName,
|
|
1254
|
+
signatureLength: result.length
|
|
1255
|
+
});
|
|
1256
|
+
return result;
|
|
1257
|
+
} catch (error) {
|
|
1258
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum signPersonalMessage failed", {
|
|
1259
|
+
walletId: this.walletId,
|
|
1260
|
+
walletName: this.walletName,
|
|
1261
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1262
|
+
errorCode: error?.code
|
|
1263
|
+
});
|
|
1264
|
+
throw error;
|
|
1265
|
+
}
|
|
71
1266
|
}
|
|
72
|
-
|
|
73
|
-
|
|
1267
|
+
async signTypedData(typedData, address) {
|
|
1268
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum signTypedData", {
|
|
1269
|
+
walletId: this.walletId,
|
|
1270
|
+
walletName: this.walletName,
|
|
1271
|
+
primaryType: typedData?.primaryType,
|
|
1272
|
+
address
|
|
1273
|
+
});
|
|
1274
|
+
try {
|
|
1275
|
+
if (typeof this.provider.signTypedData === "function") {
|
|
1276
|
+
const result2 = await this.provider.signTypedData(typedData, address);
|
|
1277
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum signTypedData success", {
|
|
1278
|
+
walletId: this.walletId,
|
|
1279
|
+
walletName: this.walletName,
|
|
1280
|
+
signatureLength: result2.length
|
|
1281
|
+
});
|
|
1282
|
+
return result2;
|
|
1283
|
+
}
|
|
1284
|
+
const result = await this.request({
|
|
1285
|
+
method: "eth_signTypedData_v4",
|
|
1286
|
+
params: [address, typedData]
|
|
1287
|
+
});
|
|
1288
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum signTypedData success", {
|
|
1289
|
+
walletId: this.walletId,
|
|
1290
|
+
walletName: this.walletName,
|
|
1291
|
+
signatureLength: result.length
|
|
1292
|
+
});
|
|
1293
|
+
return result;
|
|
1294
|
+
} catch (error) {
|
|
1295
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum signTypedData failed", {
|
|
1296
|
+
walletId: this.walletId,
|
|
1297
|
+
walletName: this.walletName,
|
|
1298
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1299
|
+
});
|
|
1300
|
+
throw error;
|
|
1301
|
+
}
|
|
74
1302
|
}
|
|
75
|
-
|
|
76
|
-
|
|
1303
|
+
async signTransaction(transaction) {
|
|
1304
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum signTransaction", {
|
|
1305
|
+
walletId: this.walletId,
|
|
1306
|
+
walletName: this.walletName,
|
|
1307
|
+
from: transaction.from,
|
|
1308
|
+
to: transaction.to
|
|
1309
|
+
});
|
|
1310
|
+
try {
|
|
1311
|
+
if (typeof this.provider.signTransaction === "function") {
|
|
1312
|
+
const result2 = await this.provider.signTransaction(transaction);
|
|
1313
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum signTransaction success", {
|
|
1314
|
+
walletId: this.walletId,
|
|
1315
|
+
walletName: this.walletName,
|
|
1316
|
+
signatureLength: result2.length
|
|
1317
|
+
});
|
|
1318
|
+
return result2;
|
|
1319
|
+
}
|
|
1320
|
+
const result = await this.request({
|
|
1321
|
+
method: "eth_signTransaction",
|
|
1322
|
+
params: [transaction]
|
|
1323
|
+
});
|
|
1324
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum signTransaction success", {
|
|
1325
|
+
walletId: this.walletId,
|
|
1326
|
+
walletName: this.walletName,
|
|
1327
|
+
signatureLength: result.length
|
|
1328
|
+
});
|
|
1329
|
+
return result;
|
|
1330
|
+
} catch (error) {
|
|
1331
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum signTransaction failed", {
|
|
1332
|
+
walletId: this.walletId,
|
|
1333
|
+
walletName: this.walletName,
|
|
1334
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1335
|
+
});
|
|
1336
|
+
throw error;
|
|
1337
|
+
}
|
|
77
1338
|
}
|
|
78
|
-
|
|
79
|
-
|
|
1339
|
+
async sendTransaction(transaction) {
|
|
1340
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum sendTransaction", {
|
|
1341
|
+
walletId: this.walletId,
|
|
1342
|
+
walletName: this.walletName,
|
|
1343
|
+
from: transaction.from,
|
|
1344
|
+
to: transaction.to,
|
|
1345
|
+
value: transaction.value
|
|
1346
|
+
});
|
|
1347
|
+
try {
|
|
1348
|
+
if (typeof this.provider.sendTransaction === "function") {
|
|
1349
|
+
const result2 = await this.provider.sendTransaction(transaction);
|
|
1350
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum sendTransaction success", {
|
|
1351
|
+
walletId: this.walletId,
|
|
1352
|
+
walletName: this.walletName,
|
|
1353
|
+
txHash: result2
|
|
1354
|
+
});
|
|
1355
|
+
return result2;
|
|
1356
|
+
}
|
|
1357
|
+
const result = await this.request({
|
|
1358
|
+
method: "eth_sendTransaction",
|
|
1359
|
+
params: [transaction]
|
|
1360
|
+
});
|
|
1361
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum sendTransaction success", {
|
|
1362
|
+
walletId: this.walletId,
|
|
1363
|
+
walletName: this.walletName,
|
|
1364
|
+
txHash: result
|
|
1365
|
+
});
|
|
1366
|
+
return result;
|
|
1367
|
+
} catch (error) {
|
|
1368
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum sendTransaction failed", {
|
|
1369
|
+
walletId: this.walletId,
|
|
1370
|
+
walletName: this.walletName,
|
|
1371
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1372
|
+
});
|
|
1373
|
+
throw error;
|
|
1374
|
+
}
|
|
80
1375
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
1376
|
+
async switchChain(chainId) {
|
|
1377
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum switchChain", {
|
|
1378
|
+
walletId: this.walletId,
|
|
1379
|
+
walletName: this.walletName,
|
|
1380
|
+
chainId
|
|
1381
|
+
});
|
|
1382
|
+
try {
|
|
1383
|
+
const hexChainId = typeof chainId === "string" ? chainId.toLowerCase().startsWith("0x") ? chainId : `0x${parseInt(chainId, 10).toString(16)}` : `0x${chainId.toString(16)}`;
|
|
1384
|
+
if (typeof this.provider.switchChain === "function") {
|
|
1385
|
+
await this.provider.switchChain(hexChainId);
|
|
1386
|
+
} else {
|
|
1387
|
+
await this.request({ method: "wallet_switchEthereumChain", params: [{ chainId: hexChainId }] });
|
|
1388
|
+
}
|
|
1389
|
+
this._chainId = hexChainId;
|
|
1390
|
+
this.eventEmitter.emit("chainChanged", this._chainId);
|
|
1391
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum switchChain success", {
|
|
1392
|
+
walletId: this.walletId,
|
|
1393
|
+
walletName: this.walletName,
|
|
1394
|
+
chainId: hexChainId
|
|
1395
|
+
});
|
|
1396
|
+
} catch (error) {
|
|
1397
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum switchChain failed", {
|
|
1398
|
+
walletId: this.walletId,
|
|
1399
|
+
walletName: this.walletName,
|
|
1400
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1401
|
+
});
|
|
1402
|
+
throw error;
|
|
84
1403
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
};
|
|
92
|
-
if (this.callback) {
|
|
93
|
-
this.callback(debugMessage);
|
|
1404
|
+
}
|
|
1405
|
+
async getChainId() {
|
|
1406
|
+
if (typeof this.provider.getChainId === "function") {
|
|
1407
|
+
const chainId2 = await this.provider.getChainId();
|
|
1408
|
+
this._chainId = `0x${chainId2.toString(16)}`;
|
|
1409
|
+
return chainId2;
|
|
94
1410
|
}
|
|
1411
|
+
const chainId = await this.request({ method: "eth_chainId" });
|
|
1412
|
+
const parsed = parseInt(chainId, 16);
|
|
1413
|
+
this._chainId = chainId;
|
|
1414
|
+
return parsed;
|
|
95
1415
|
}
|
|
96
|
-
|
|
97
|
-
this.
|
|
1416
|
+
async getAccounts() {
|
|
1417
|
+
if (typeof this.provider.getAccounts === "function") {
|
|
1418
|
+
const accounts2 = await this.provider.getAccounts();
|
|
1419
|
+
this._accounts = accounts2;
|
|
1420
|
+
return accounts2;
|
|
1421
|
+
}
|
|
1422
|
+
const accounts = await this.request({ method: "eth_accounts" });
|
|
1423
|
+
this._accounts = accounts;
|
|
1424
|
+
return accounts;
|
|
98
1425
|
}
|
|
99
|
-
|
|
100
|
-
this.
|
|
1426
|
+
isConnected() {
|
|
1427
|
+
return this._connected;
|
|
101
1428
|
}
|
|
102
|
-
|
|
103
|
-
this.
|
|
1429
|
+
setupEventListeners() {
|
|
1430
|
+
if (typeof this.provider.on === "function") {
|
|
1431
|
+
this.provider.on("connect", (info) => {
|
|
1432
|
+
this._connected = true;
|
|
1433
|
+
this._chainId = info.chainId;
|
|
1434
|
+
this.eventEmitter.emit("connect", info);
|
|
1435
|
+
});
|
|
1436
|
+
this.provider.on("disconnect", (error) => {
|
|
1437
|
+
this._connected = false;
|
|
1438
|
+
this._accounts = [];
|
|
1439
|
+
this.eventEmitter.emit("disconnect", error);
|
|
1440
|
+
this.eventEmitter.emit("accountsChanged", []);
|
|
1441
|
+
});
|
|
1442
|
+
this.provider.on("accountsChanged", (accounts) => {
|
|
1443
|
+
this._accounts = accounts;
|
|
1444
|
+
this.eventEmitter.emit("accountsChanged", accounts);
|
|
1445
|
+
});
|
|
1446
|
+
this.provider.on("chainChanged", (chainId) => {
|
|
1447
|
+
this._chainId = chainId;
|
|
1448
|
+
this.eventEmitter.emit("chainChanged", chainId);
|
|
1449
|
+
});
|
|
1450
|
+
}
|
|
104
1451
|
}
|
|
105
|
-
|
|
106
|
-
this.
|
|
1452
|
+
on(event, listener) {
|
|
1453
|
+
this.eventEmitter.on(event, listener);
|
|
107
1454
|
}
|
|
108
|
-
|
|
109
|
-
this.
|
|
1455
|
+
off(event, listener) {
|
|
1456
|
+
this.eventEmitter.off(event, listener);
|
|
110
1457
|
}
|
|
111
1458
|
};
|
|
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
1459
|
|
|
124
1460
|
// src/providers/injected/chains/SolanaChain.ts
|
|
125
|
-
var
|
|
126
|
-
var
|
|
127
|
-
var
|
|
128
|
-
|
|
129
|
-
constructor(phantom, callbacks) {
|
|
130
|
-
this._connected = false;
|
|
1461
|
+
var import_eventemitter33 = require("eventemitter3");
|
|
1462
|
+
var import_buffer2 = require("buffer");
|
|
1463
|
+
var PhantomSolanaChain = class {
|
|
1464
|
+
constructor(phantom) {
|
|
131
1465
|
this._publicKey = null;
|
|
132
|
-
this.eventEmitter = new
|
|
1466
|
+
this.eventEmitter = new import_eventemitter33.EventEmitter();
|
|
133
1467
|
this.phantom = phantom;
|
|
134
|
-
this.callbacks = callbacks;
|
|
135
1468
|
this.setupEventListeners();
|
|
136
|
-
this.syncInitialState();
|
|
137
1469
|
}
|
|
138
1470
|
// Wallet adapter compliant properties
|
|
139
1471
|
get connected() {
|
|
140
|
-
return this.
|
|
1472
|
+
return this._publicKey !== null;
|
|
141
1473
|
}
|
|
142
1474
|
get publicKey() {
|
|
143
1475
|
return this._publicKey;
|
|
144
1476
|
}
|
|
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"));
|
|
1477
|
+
// Connection methods
|
|
1478
|
+
async connect(options) {
|
|
1479
|
+
const result = await this.phantom.solana.connect(options);
|
|
1480
|
+
if (!result) {
|
|
1481
|
+
throw new Error("Failed to connect to Solana wallet");
|
|
154
1482
|
}
|
|
155
|
-
|
|
156
|
-
|
|
1483
|
+
const publicKey = typeof result === "string" ? result : "";
|
|
1484
|
+
this._publicKey = publicKey;
|
|
1485
|
+
return { publicKey };
|
|
157
1486
|
}
|
|
158
1487
|
async disconnect() {
|
|
159
|
-
await this.
|
|
1488
|
+
await this.phantom.solana.disconnect();
|
|
1489
|
+
this._publicKey = null;
|
|
160
1490
|
}
|
|
161
1491
|
// Standard wallet adapter methods
|
|
162
1492
|
async signMessage(message) {
|
|
163
1493
|
const messageBytes = typeof message === "string" ? new TextEncoder().encode(message) : message;
|
|
164
1494
|
const result = await this.phantom.solana.signMessage(messageBytes);
|
|
165
1495
|
return {
|
|
166
|
-
signature: result.signature instanceof Uint8Array ? result.signature : new Uint8Array(
|
|
1496
|
+
signature: result.signature instanceof Uint8Array ? result.signature : new Uint8Array(import_buffer2.Buffer.from(result.signature, "base64")),
|
|
167
1497
|
publicKey: this._publicKey || ""
|
|
168
1498
|
};
|
|
169
1499
|
}
|
|
170
1500
|
async signTransaction(transaction) {
|
|
171
|
-
if (!this.
|
|
1501
|
+
if (!this.connected) {
|
|
172
1502
|
return Promise.reject(new Error("Provider not connected. Call provider connect first."));
|
|
173
1503
|
}
|
|
174
1504
|
try {
|
|
@@ -183,7 +1513,7 @@ var InjectedSolanaChain = class {
|
|
|
183
1513
|
return { signature: result.signature };
|
|
184
1514
|
}
|
|
185
1515
|
async signAllTransactions(transactions) {
|
|
186
|
-
if (!this.
|
|
1516
|
+
if (!this.connected) {
|
|
187
1517
|
return Promise.reject(new Error("Provider not connected. Call provider connect first."));
|
|
188
1518
|
}
|
|
189
1519
|
try {
|
|
@@ -194,7 +1524,7 @@ var InjectedSolanaChain = class {
|
|
|
194
1524
|
}
|
|
195
1525
|
}
|
|
196
1526
|
async signAndSendAllTransactions(transactions) {
|
|
197
|
-
if (!this.
|
|
1527
|
+
if (!this.connected) {
|
|
198
1528
|
return Promise.reject(new Error("Provider not connected. Call provider connect first."));
|
|
199
1529
|
}
|
|
200
1530
|
try {
|
|
@@ -212,42 +1542,21 @@ var InjectedSolanaChain = class {
|
|
|
212
1542
|
return Promise.resolve(this._publicKey);
|
|
213
1543
|
}
|
|
214
1544
|
isConnected() {
|
|
215
|
-
return this.
|
|
1545
|
+
return this.connected;
|
|
216
1546
|
}
|
|
217
1547
|
setupEventListeners() {
|
|
218
1548
|
this.phantom.solana.addEventListener("connect", (publicKey) => {
|
|
219
|
-
this.
|
|
1549
|
+
this._publicKey = publicKey;
|
|
220
1550
|
this.eventEmitter.emit("connect", publicKey);
|
|
221
1551
|
});
|
|
222
1552
|
this.phantom.solana.addEventListener("disconnect", () => {
|
|
223
|
-
this.
|
|
1553
|
+
this._publicKey = null;
|
|
224
1554
|
this.eventEmitter.emit("disconnect");
|
|
225
1555
|
});
|
|
226
1556
|
this.phantom.solana.addEventListener("accountChanged", (publicKey) => {
|
|
227
1557
|
this._publicKey = publicKey;
|
|
228
1558
|
this.eventEmitter.emit("accountChanged", publicKey);
|
|
229
1559
|
});
|
|
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
1560
|
}
|
|
252
1561
|
// Event methods for interface compliance
|
|
253
1562
|
on(event, listener) {
|
|
@@ -259,22 +1568,18 @@ var InjectedSolanaChain = class {
|
|
|
259
1568
|
};
|
|
260
1569
|
|
|
261
1570
|
// src/providers/injected/chains/EthereumChain.ts
|
|
262
|
-
var
|
|
263
|
-
var
|
|
264
|
-
|
|
265
|
-
constructor(phantom, callbacks) {
|
|
266
|
-
this._connected = false;
|
|
1571
|
+
var import_eventemitter34 = require("eventemitter3");
|
|
1572
|
+
var PhantomEthereumChain = class {
|
|
1573
|
+
constructor(phantom) {
|
|
267
1574
|
this._chainId = "0x1";
|
|
268
1575
|
this._accounts = [];
|
|
269
|
-
this.eventEmitter = new
|
|
1576
|
+
this.eventEmitter = new import_eventemitter34.EventEmitter();
|
|
270
1577
|
this.phantom = phantom;
|
|
271
|
-
this.callbacks = callbacks;
|
|
272
1578
|
this.setupEventListeners();
|
|
273
|
-
this.syncInitialState();
|
|
274
1579
|
}
|
|
275
1580
|
// EIP-1193 compliant properties
|
|
276
1581
|
get connected() {
|
|
277
|
-
return this.
|
|
1582
|
+
return this._accounts.length > 0;
|
|
278
1583
|
}
|
|
279
1584
|
get chainId() {
|
|
280
1585
|
return this._chainId;
|
|
@@ -289,21 +1594,18 @@ var InjectedEthereumChain = class {
|
|
|
289
1594
|
const result = await this.signTransaction(transaction);
|
|
290
1595
|
return result;
|
|
291
1596
|
}
|
|
292
|
-
const
|
|
293
|
-
return await
|
|
1597
|
+
const phantomProvider = await this.phantom.ethereum.getProvider();
|
|
1598
|
+
return await phantomProvider.request(args);
|
|
294
1599
|
}
|
|
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);
|
|
1600
|
+
// Connection methods
|
|
1601
|
+
async connect() {
|
|
1602
|
+
const accounts = await this.phantom.ethereum.getAccounts();
|
|
1603
|
+
this._accounts = accounts;
|
|
1604
|
+
return accounts;
|
|
304
1605
|
}
|
|
305
1606
|
async disconnect() {
|
|
306
|
-
await this.
|
|
1607
|
+
await this.phantom.ethereum.disconnect();
|
|
1608
|
+
this._accounts = [];
|
|
307
1609
|
}
|
|
308
1610
|
// Standard compliant methods (return raw values, not wrapped objects)
|
|
309
1611
|
async signPersonalMessage(message, address) {
|
|
@@ -332,16 +1634,16 @@ var InjectedEthereumChain = class {
|
|
|
332
1634
|
return await this.phantom.ethereum.getAccounts();
|
|
333
1635
|
}
|
|
334
1636
|
isConnected() {
|
|
335
|
-
return this.
|
|
1637
|
+
return this.connected;
|
|
336
1638
|
}
|
|
337
1639
|
setupEventListeners() {
|
|
338
1640
|
this.phantom.ethereum.addEventListener("connect", (accounts) => {
|
|
339
|
-
this.
|
|
1641
|
+
this._accounts = accounts;
|
|
340
1642
|
this.eventEmitter.emit("connect", { chainId: this._chainId });
|
|
341
1643
|
this.eventEmitter.emit("accountsChanged", accounts);
|
|
342
1644
|
});
|
|
343
1645
|
this.phantom.ethereum.addEventListener("disconnect", () => {
|
|
344
|
-
this.
|
|
1646
|
+
this._accounts = [];
|
|
345
1647
|
this.eventEmitter.emit("disconnect", { code: 4900, message: "Provider disconnected" });
|
|
346
1648
|
this.eventEmitter.emit("accountsChanged", []);
|
|
347
1649
|
});
|
|
@@ -353,27 +1655,6 @@ var InjectedEthereumChain = class {
|
|
|
353
1655
|
this._chainId = chainId;
|
|
354
1656
|
this.eventEmitter.emit("chainChanged", chainId);
|
|
355
1657
|
});
|
|
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
1658
|
}
|
|
378
1659
|
// Event methods for interface compliance
|
|
379
1660
|
on(event, listener) {
|
|
@@ -384,67 +1665,400 @@ var InjectedEthereumChain = class {
|
|
|
384
1665
|
}
|
|
385
1666
|
};
|
|
386
1667
|
|
|
1668
|
+
// src/wallets/registry.ts
|
|
1669
|
+
function isPhantomWallet(wallet) {
|
|
1670
|
+
return wallet !== void 0 && wallet.id === "phantom" && "isPhantom" in wallet && wallet.isPhantom === true;
|
|
1671
|
+
}
|
|
1672
|
+
var InjectedWalletRegistry = class {
|
|
1673
|
+
constructor() {
|
|
1674
|
+
this.wallets = /* @__PURE__ */ new Map();
|
|
1675
|
+
this.discoveryPromise = null;
|
|
1676
|
+
}
|
|
1677
|
+
register(info) {
|
|
1678
|
+
const wrappedProviders = {};
|
|
1679
|
+
if (info.providers?.solana) {
|
|
1680
|
+
const isWalletStandard = info.providers.solana && typeof info.providers.solana === "object" && "features" in info.providers.solana && typeof info.providers.solana.features === "object";
|
|
1681
|
+
if (isWalletStandard) {
|
|
1682
|
+
wrappedProviders.solana = new WalletStandardSolanaAdapter(info.providers.solana, info.id, info.name);
|
|
1683
|
+
debug.log(DebugCategory.BROWSER_SDK, "Wrapped Wallet Standard Solana wallet with adapter", {
|
|
1684
|
+
walletId: info.id,
|
|
1685
|
+
walletName: info.name
|
|
1686
|
+
});
|
|
1687
|
+
} else {
|
|
1688
|
+
wrappedProviders.solana = new InjectedWalletSolanaChain(info.providers.solana, info.id, info.name);
|
|
1689
|
+
debug.log(DebugCategory.BROWSER_SDK, "Wrapped Solana provider with InjectedWalletSolanaChain", {
|
|
1690
|
+
walletId: info.id,
|
|
1691
|
+
walletName: info.name
|
|
1692
|
+
});
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
1695
|
+
if (info.providers?.ethereum) {
|
|
1696
|
+
wrappedProviders.ethereum = new InjectedWalletEthereumChain(info.providers.ethereum, info.id, info.name);
|
|
1697
|
+
debug.log(DebugCategory.BROWSER_SDK, "Wrapped Ethereum provider with InjectedWalletEthereumChain", {
|
|
1698
|
+
walletId: info.id,
|
|
1699
|
+
walletName: info.name
|
|
1700
|
+
});
|
|
1701
|
+
}
|
|
1702
|
+
const wrappedInfo = {
|
|
1703
|
+
...info,
|
|
1704
|
+
providers: Object.keys(wrappedProviders).length > 0 ? wrappedProviders : info.providers
|
|
1705
|
+
};
|
|
1706
|
+
this.wallets.set(info.id, wrappedInfo);
|
|
1707
|
+
}
|
|
1708
|
+
/**
|
|
1709
|
+
* Register Phantom wallet with its instance
|
|
1710
|
+
* This creates wrapped providers and stores the Phantom instance for auto-confirm access
|
|
1711
|
+
*/
|
|
1712
|
+
registerPhantom(phantomInstance, addressTypes, icon) {
|
|
1713
|
+
const wrappedProviders = {};
|
|
1714
|
+
if (addressTypes.includes(import_client.AddressType.solana) && phantomInstance.solana) {
|
|
1715
|
+
wrappedProviders.solana = new PhantomSolanaChain(phantomInstance);
|
|
1716
|
+
debug.log(DebugCategory.BROWSER_SDK, "Created PhantomSolanaChain wrapper", {
|
|
1717
|
+
walletId: "phantom"
|
|
1718
|
+
});
|
|
1719
|
+
}
|
|
1720
|
+
if (addressTypes.includes(import_client.AddressType.ethereum) && phantomInstance.ethereum) {
|
|
1721
|
+
wrappedProviders.ethereum = new PhantomEthereumChain(phantomInstance);
|
|
1722
|
+
debug.log(DebugCategory.BROWSER_SDK, "Created PhantomEthereumChain wrapper", {
|
|
1723
|
+
walletId: "phantom"
|
|
1724
|
+
});
|
|
1725
|
+
}
|
|
1726
|
+
const phantomWallet = {
|
|
1727
|
+
id: "phantom",
|
|
1728
|
+
name: "Phantom",
|
|
1729
|
+
icon: icon || "https://phantom.app/img/phantom-icon-purple.png",
|
|
1730
|
+
addressTypes,
|
|
1731
|
+
providers: wrappedProviders,
|
|
1732
|
+
isPhantom: true,
|
|
1733
|
+
phantomInstance
|
|
1734
|
+
};
|
|
1735
|
+
this.wallets.set("phantom", phantomWallet);
|
|
1736
|
+
debug.log(DebugCategory.BROWSER_SDK, "Registered Phantom wallet with chain wrappers", {
|
|
1737
|
+
addressTypes,
|
|
1738
|
+
hasSolana: !!wrappedProviders.solana,
|
|
1739
|
+
hasEthereum: !!wrappedProviders.ethereum
|
|
1740
|
+
});
|
|
1741
|
+
}
|
|
1742
|
+
unregister(id) {
|
|
1743
|
+
this.wallets.delete(id);
|
|
1744
|
+
}
|
|
1745
|
+
has(id) {
|
|
1746
|
+
return this.wallets.has(id);
|
|
1747
|
+
}
|
|
1748
|
+
getById(id) {
|
|
1749
|
+
return this.wallets.get(id);
|
|
1750
|
+
}
|
|
1751
|
+
getAll() {
|
|
1752
|
+
return Array.from(this.wallets.values());
|
|
1753
|
+
}
|
|
1754
|
+
getByAddressTypes(addressTypes) {
|
|
1755
|
+
if (addressTypes.length === 0) {
|
|
1756
|
+
return this.getAll();
|
|
1757
|
+
}
|
|
1758
|
+
const allowed = new Set(addressTypes);
|
|
1759
|
+
return this.getAll().filter((wallet) => wallet.addressTypes.some((t) => allowed.has(t)));
|
|
1760
|
+
}
|
|
1761
|
+
discover(addressTypes) {
|
|
1762
|
+
if (this.discoveryPromise) {
|
|
1763
|
+
return this.discoveryPromise;
|
|
1764
|
+
}
|
|
1765
|
+
debug.log(DebugCategory.BROWSER_SDK, "Starting wallet discovery", { addressTypes });
|
|
1766
|
+
this.discoveryPromise = discoverWallets(addressTypes).then((discoveredWallets) => {
|
|
1767
|
+
const relevantWallets = addressTypes ? discoveredWallets.filter((wallet) => wallet.addressTypes.some((type) => addressTypes.includes(type))) : discoveredWallets;
|
|
1768
|
+
for (const wallet of relevantWallets) {
|
|
1769
|
+
if (wallet.id === "phantom" && isPhantomWallet(wallet)) {
|
|
1770
|
+
this.registerPhantom(wallet.phantomInstance, wallet.addressTypes, wallet.icon);
|
|
1771
|
+
} else {
|
|
1772
|
+
this.register(wallet);
|
|
1773
|
+
}
|
|
1774
|
+
debug.log(DebugCategory.BROWSER_SDK, "Registered discovered wallet", {
|
|
1775
|
+
id: wallet.id,
|
|
1776
|
+
name: wallet.name,
|
|
1777
|
+
addressTypes: wallet.addressTypes
|
|
1778
|
+
});
|
|
1779
|
+
}
|
|
1780
|
+
debug.info(DebugCategory.BROWSER_SDK, "Wallet discovery completed", {
|
|
1781
|
+
totalDiscovered: discoveredWallets.length,
|
|
1782
|
+
relevantWallets: relevantWallets.length
|
|
1783
|
+
});
|
|
1784
|
+
}).catch((error) => {
|
|
1785
|
+
debug.warn(DebugCategory.BROWSER_SDK, "Wallet discovery failed", { error });
|
|
1786
|
+
this.discoveryPromise = null;
|
|
1787
|
+
throw error;
|
|
1788
|
+
});
|
|
1789
|
+
return this.discoveryPromise;
|
|
1790
|
+
}
|
|
1791
|
+
};
|
|
1792
|
+
var walletRegistry = null;
|
|
1793
|
+
function getWalletRegistry() {
|
|
1794
|
+
if (!walletRegistry) {
|
|
1795
|
+
walletRegistry = new InjectedWalletRegistry();
|
|
1796
|
+
}
|
|
1797
|
+
return walletRegistry;
|
|
1798
|
+
}
|
|
1799
|
+
|
|
387
1800
|
// src/providers/injected/index.ts
|
|
388
|
-
var
|
|
389
|
-
var
|
|
1801
|
+
var WAS_CONNECTED_KEY = "phantom-injected-was-connected";
|
|
1802
|
+
var WAS_CONNECTED_VALUE = "true";
|
|
1803
|
+
var LAST_WALLET_ID_KEY = "phantom-injected-last-wallet-id";
|
|
390
1804
|
var InjectedProvider = class {
|
|
1805
|
+
// Track which wallets have event listeners set up
|
|
391
1806
|
constructor(config) {
|
|
392
|
-
this.
|
|
393
|
-
this.
|
|
1807
|
+
this.selectedWalletId = null;
|
|
1808
|
+
this.walletStates = /* @__PURE__ */ new Map();
|
|
394
1809
|
// Event management
|
|
395
1810
|
this.eventListeners = /* @__PURE__ */ new Map();
|
|
396
1811
|
this.browserInjectedCleanupFunctions = [];
|
|
397
1812
|
this.eventsInitialized = false;
|
|
1813
|
+
this.externalWalletEventListenersSetup = /* @__PURE__ */ new Set();
|
|
398
1814
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Initializing InjectedProvider", { config });
|
|
399
1815
|
this.addressTypes = config.addressTypes;
|
|
1816
|
+
this.walletRegistry = getWalletRegistry();
|
|
400
1817
|
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
|
|
1818
|
+
this.walletRegistry.discover(this.addressTypes).catch((error) => {
|
|
1819
|
+
debug.warn(DebugCategory.INJECTED_PROVIDER, "Wallet discovery failed during initialization", { error });
|
|
414
1820
|
});
|
|
415
|
-
this.phantom = (0, import_browser_injected_sdk.createPhantom)({ plugins });
|
|
416
|
-
const callbacks = this.createCallbacks();
|
|
417
|
-
if (this.addressTypes.includes(import_client4.AddressType.solana)) {
|
|
418
|
-
this._solanaChain = new InjectedSolanaChain(this.phantom, callbacks);
|
|
419
|
-
}
|
|
420
|
-
if (this.addressTypes.includes(import_client4.AddressType.ethereum)) {
|
|
421
|
-
this._ethereumChain = new InjectedEthereumChain(this.phantom, callbacks);
|
|
422
|
-
}
|
|
423
1821
|
debug.info(DebugCategory.INJECTED_PROVIDER, "InjectedProvider initialized");
|
|
424
1822
|
}
|
|
425
1823
|
/**
|
|
426
|
-
*
|
|
1824
|
+
* Wait for wallet discovery to complete if the wallet is not yet in the registry
|
|
1825
|
+
* This is needed for auto-connect when the last wallet was an external wallet
|
|
427
1826
|
*/
|
|
1827
|
+
async waitForWalletDiscovery(walletId) {
|
|
1828
|
+
if (this.walletRegistry.has(walletId)) {
|
|
1829
|
+
return;
|
|
1830
|
+
}
|
|
1831
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Wallet not found in registry, waiting for discovery", {
|
|
1832
|
+
walletId
|
|
1833
|
+
});
|
|
1834
|
+
try {
|
|
1835
|
+
await this.walletRegistry.discover(this.addressTypes);
|
|
1836
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Wallet discovery completed", { walletId });
|
|
1837
|
+
} catch (error) {
|
|
1838
|
+
debug.warn(DebugCategory.INJECTED_PROVIDER, "Wallet discovery failed", {
|
|
1839
|
+
walletId,
|
|
1840
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1841
|
+
});
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
428
1844
|
get solana() {
|
|
429
|
-
if (!this.addressTypes.includes(
|
|
1845
|
+
if (!this.addressTypes.includes(import_client3.AddressType.solana)) {
|
|
430
1846
|
throw new Error("Solana not enabled for this provider");
|
|
431
1847
|
}
|
|
432
|
-
|
|
433
|
-
|
|
1848
|
+
const walletId = this.selectedWalletId || "phantom";
|
|
1849
|
+
const walletInfo = this.walletRegistry.getById(walletId);
|
|
1850
|
+
if (!walletInfo) {
|
|
1851
|
+
const registry = this.walletRegistry;
|
|
1852
|
+
if (registry.discoveryPromise) {
|
|
1853
|
+
throw new Error(
|
|
1854
|
+
`Wallet "${walletId}" not found. Wallet discovery is still in progress. Please wait for sdk.discoverWallets() to complete before accessing chain properties.`
|
|
1855
|
+
);
|
|
1856
|
+
}
|
|
1857
|
+
throw new Error(
|
|
1858
|
+
`Wallet "${walletId}" not found. Please ensure wallet discovery has completed. Make sure you call sdk.discoverWallets() and await it before accessing chain properties.`
|
|
1859
|
+
);
|
|
1860
|
+
}
|
|
1861
|
+
if (!walletInfo.providers?.solana) {
|
|
1862
|
+
throw new Error(
|
|
1863
|
+
`Selected wallet "${walletInfo.name}" does not support Solana. This wallet only supports: ${walletInfo.addressTypes.join(", ")}. Make sure your SDK config includes Solana in addressTypes.`
|
|
1864
|
+
);
|
|
434
1865
|
}
|
|
435
|
-
return
|
|
1866
|
+
return walletInfo.providers.solana;
|
|
436
1867
|
}
|
|
437
1868
|
/**
|
|
438
1869
|
* Access to Ethereum chain operations
|
|
439
1870
|
*/
|
|
440
1871
|
get ethereum() {
|
|
441
|
-
if (!this.addressTypes.includes(
|
|
1872
|
+
if (!this.addressTypes.includes(import_client3.AddressType.ethereum)) {
|
|
442
1873
|
throw new Error("Ethereum not enabled for this provider");
|
|
443
1874
|
}
|
|
444
|
-
|
|
445
|
-
|
|
1875
|
+
const walletId = this.selectedWalletId || "phantom";
|
|
1876
|
+
const walletInfo = this.walletRegistry.getById(walletId);
|
|
1877
|
+
if (!walletInfo) {
|
|
1878
|
+
const registry = this.walletRegistry;
|
|
1879
|
+
if (registry.discoveryPromise) {
|
|
1880
|
+
throw new Error(
|
|
1881
|
+
`Wallet "${walletId}" not found. Wallet discovery is still in progress. Please wait for sdk.discoverWallets() to complete before accessing chain properties.`
|
|
1882
|
+
);
|
|
1883
|
+
}
|
|
1884
|
+
throw new Error(
|
|
1885
|
+
`Wallet "${walletId}" not found. Please ensure wallet discovery has completed. Make sure you call sdk.discoverWallets() and await it before accessing chain properties.`
|
|
1886
|
+
);
|
|
1887
|
+
}
|
|
1888
|
+
if (!walletInfo.providers?.ethereum) {
|
|
1889
|
+
throw new Error(
|
|
1890
|
+
`Selected wallet "${walletInfo.name}" does not support Ethereum. This wallet only supports: ${walletInfo.addressTypes.join(", ")}. Make sure your SDK config includes Ethereum in addressTypes.`
|
|
1891
|
+
);
|
|
1892
|
+
}
|
|
1893
|
+
return walletInfo.providers.ethereum;
|
|
1894
|
+
}
|
|
1895
|
+
validateAndSelectWallet(requestedWalletId) {
|
|
1896
|
+
if (!this.walletRegistry.has(requestedWalletId)) {
|
|
1897
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "Unknown injected wallet id requested", {
|
|
1898
|
+
walletId: requestedWalletId
|
|
1899
|
+
});
|
|
1900
|
+
throw new Error(`Unknown injected wallet id: ${requestedWalletId}`);
|
|
1901
|
+
}
|
|
1902
|
+
const walletInfo = this.walletRegistry.getById(requestedWalletId);
|
|
1903
|
+
if (!walletInfo || !walletInfo.providers) {
|
|
1904
|
+
debug.warn(DebugCategory.INJECTED_PROVIDER, "Wallet not available for connection", {
|
|
1905
|
+
walletId: requestedWalletId
|
|
1906
|
+
});
|
|
1907
|
+
throw new Error(`Wallet not available for connection: ${requestedWalletId}`);
|
|
1908
|
+
}
|
|
1909
|
+
this.selectedWalletId = requestedWalletId;
|
|
1910
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Selected injected wallet for connection", {
|
|
1911
|
+
walletId: requestedWalletId
|
|
1912
|
+
});
|
|
1913
|
+
return walletInfo;
|
|
1914
|
+
}
|
|
1915
|
+
async connectToWallet(walletInfo, options) {
|
|
1916
|
+
if (!walletInfo.providers) {
|
|
1917
|
+
const error = new Error(`Wallet adapter not available for wallet: ${this.selectedWalletId}`);
|
|
1918
|
+
debug.error(DebugCategory.INJECTED_PROVIDER, "Wallet adapter not available", { walletId: this.selectedWalletId });
|
|
1919
|
+
this.emit("connect_error", {
|
|
1920
|
+
error: error.message,
|
|
1921
|
+
source: options?.skipEventListeners ? "auto-connect" : "manual-connect"
|
|
1922
|
+
});
|
|
1923
|
+
throw error;
|
|
1924
|
+
}
|
|
1925
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Connecting via wallet", {
|
|
1926
|
+
walletId: this.selectedWalletId,
|
|
1927
|
+
walletName: walletInfo.name,
|
|
1928
|
+
options
|
|
1929
|
+
});
|
|
1930
|
+
if (!options?.skipEventListeners) {
|
|
1931
|
+
this.setupExternalWalletEvents(walletInfo);
|
|
1932
|
+
if (this.selectedWalletId === "phantom" && isPhantomWallet(walletInfo)) {
|
|
1933
|
+
this.browserInjectedCleanupFunctions.forEach((cleanup) => cleanup());
|
|
1934
|
+
this.browserInjectedCleanupFunctions = [];
|
|
1935
|
+
this.setupBrowserInjectedEvents();
|
|
1936
|
+
this.eventsInitialized = true;
|
|
1937
|
+
}
|
|
1938
|
+
}
|
|
1939
|
+
const connectedAddresses = [];
|
|
1940
|
+
if (this.addressTypes.includes(import_client3.AddressType.solana) && walletInfo.providers?.solana) {
|
|
1941
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting Solana connection", {
|
|
1942
|
+
walletId: this.selectedWalletId,
|
|
1943
|
+
walletName: walletInfo.name,
|
|
1944
|
+
onlyIfTrusted: options?.onlyIfTrusted
|
|
1945
|
+
});
|
|
1946
|
+
try {
|
|
1947
|
+
const result = await walletInfo.providers.solana.connect(
|
|
1948
|
+
options?.onlyIfTrusted ? { onlyIfTrusted: true } : void 0
|
|
1949
|
+
);
|
|
1950
|
+
const address = result.publicKey;
|
|
1951
|
+
connectedAddresses.push({
|
|
1952
|
+
addressType: import_client3.AddressType.solana,
|
|
1953
|
+
address
|
|
1954
|
+
});
|
|
1955
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "Solana connected successfully", {
|
|
1956
|
+
address,
|
|
1957
|
+
walletId: this.selectedWalletId,
|
|
1958
|
+
walletName: walletInfo.name
|
|
1959
|
+
});
|
|
1960
|
+
} catch (err) {
|
|
1961
|
+
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Solana, stopping", {
|
|
1962
|
+
error: err,
|
|
1963
|
+
walletId: this.selectedWalletId,
|
|
1964
|
+
walletName: walletInfo.name
|
|
1965
|
+
});
|
|
1966
|
+
this.emit("connect_error", {
|
|
1967
|
+
error: err instanceof Error ? err.message : "Failed to connect",
|
|
1968
|
+
source: options?.skipEventListeners ? "auto-connect" : "manual-connect"
|
|
1969
|
+
});
|
|
1970
|
+
throw err;
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
1973
|
+
if (this.addressTypes.includes(import_client3.AddressType.ethereum) && walletInfo.providers?.ethereum) {
|
|
1974
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting Ethereum connection", {
|
|
1975
|
+
walletId: this.selectedWalletId,
|
|
1976
|
+
walletName: walletInfo.name,
|
|
1977
|
+
silent: options?.silent
|
|
1978
|
+
});
|
|
1979
|
+
try {
|
|
1980
|
+
let accounts;
|
|
1981
|
+
if (options?.silent) {
|
|
1982
|
+
accounts = await walletInfo.providers.ethereum.request({ method: "eth_accounts" });
|
|
1983
|
+
} else {
|
|
1984
|
+
accounts = await walletInfo.providers.ethereum.connect();
|
|
1985
|
+
}
|
|
1986
|
+
if (accounts.length > 0) {
|
|
1987
|
+
connectedAddresses.push(
|
|
1988
|
+
...accounts.map((address) => ({
|
|
1989
|
+
addressType: import_client3.AddressType.ethereum,
|
|
1990
|
+
address
|
|
1991
|
+
}))
|
|
1992
|
+
);
|
|
1993
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "Ethereum connected successfully", {
|
|
1994
|
+
addresses: accounts,
|
|
1995
|
+
walletId: this.selectedWalletId,
|
|
1996
|
+
walletName: walletInfo.name
|
|
1997
|
+
});
|
|
1998
|
+
}
|
|
1999
|
+
} catch (err) {
|
|
2000
|
+
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Ethereum, stopping", {
|
|
2001
|
+
error: err,
|
|
2002
|
+
walletId: this.selectedWalletId,
|
|
2003
|
+
walletName: walletInfo.name
|
|
2004
|
+
});
|
|
2005
|
+
this.emit("connect_error", {
|
|
2006
|
+
error: err instanceof Error ? err.message : "Failed to connect",
|
|
2007
|
+
source: options?.skipEventListeners ? "auto-connect" : "manual-connect"
|
|
2008
|
+
});
|
|
2009
|
+
throw err;
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
return connectedAddresses;
|
|
2013
|
+
}
|
|
2014
|
+
async finalizeConnection(connectedAddresses, authProvider, walletId) {
|
|
2015
|
+
if (connectedAddresses.length === 0) {
|
|
2016
|
+
const error = new Error("Failed to connect to any supported wallet provider");
|
|
2017
|
+
this.emit("connect_error", {
|
|
2018
|
+
error: error.message,
|
|
2019
|
+
source: "manual-connect"
|
|
2020
|
+
});
|
|
2021
|
+
throw error;
|
|
2022
|
+
}
|
|
2023
|
+
if (this.selectedWalletId) {
|
|
2024
|
+
this.setWalletState(this.selectedWalletId, {
|
|
2025
|
+
connected: true,
|
|
2026
|
+
addresses: connectedAddresses
|
|
2027
|
+
});
|
|
446
2028
|
}
|
|
447
|
-
|
|
2029
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Finalized connection with addresses", {
|
|
2030
|
+
addressCount: connectedAddresses.length,
|
|
2031
|
+
addresses: connectedAddresses.map((addr) => ({
|
|
2032
|
+
type: addr.addressType,
|
|
2033
|
+
address: addr.address.substring(0, 10) + "..."
|
|
2034
|
+
}))
|
|
2035
|
+
});
|
|
2036
|
+
const authUserId = await this.getAuthUserId("manual-connect");
|
|
2037
|
+
try {
|
|
2038
|
+
localStorage.setItem(WAS_CONNECTED_KEY, WAS_CONNECTED_VALUE);
|
|
2039
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Set was-connected flag - auto-reconnect enabled");
|
|
2040
|
+
if (this.selectedWalletId) {
|
|
2041
|
+
localStorage.setItem(LAST_WALLET_ID_KEY, this.selectedWalletId);
|
|
2042
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Stored last injected wallet id", {
|
|
2043
|
+
walletId: this.selectedWalletId
|
|
2044
|
+
});
|
|
2045
|
+
}
|
|
2046
|
+
} catch (error) {
|
|
2047
|
+
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to persist injected provider state", { error });
|
|
2048
|
+
}
|
|
2049
|
+
const result = {
|
|
2050
|
+
addresses: connectedAddresses,
|
|
2051
|
+
status: "completed",
|
|
2052
|
+
authUserId,
|
|
2053
|
+
authProvider,
|
|
2054
|
+
walletId
|
|
2055
|
+
};
|
|
2056
|
+
this.emit("connect", {
|
|
2057
|
+
addresses: connectedAddresses,
|
|
2058
|
+
source: "manual-connect",
|
|
2059
|
+
authUserId
|
|
2060
|
+
});
|
|
2061
|
+
return result;
|
|
448
2062
|
}
|
|
449
2063
|
async connect(authOptions) {
|
|
450
2064
|
debug.info(DebugCategory.INJECTED_PROVIDER, "Starting injected provider connect", {
|
|
@@ -459,118 +2073,53 @@ var InjectedProvider = class {
|
|
|
459
2073
|
providerType: "injected"
|
|
460
2074
|
});
|
|
461
2075
|
try {
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
2076
|
+
const requestedWalletId = authOptions.walletId || "phantom";
|
|
2077
|
+
const walletInfo = this.validateAndSelectWallet(requestedWalletId);
|
|
2078
|
+
const connectedAddresses = await this.connectToWallet(walletInfo);
|
|
2079
|
+
return await this.finalizeConnection(connectedAddresses, "injected", this.selectedWalletId || void 0);
|
|
2080
|
+
} catch (error) {
|
|
2081
|
+
this.emit("connect_error", {
|
|
2082
|
+
error: error instanceof Error ? error.message : "Failed to connect",
|
|
2083
|
+
source: "manual-connect"
|
|
2084
|
+
});
|
|
2085
|
+
throw error;
|
|
2086
|
+
}
|
|
2087
|
+
}
|
|
2088
|
+
async disconnect() {
|
|
2089
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "Starting injected provider disconnect");
|
|
2090
|
+
const walletInfo = this.walletRegistry.getById(this.selectedWalletId || "phantom");
|
|
2091
|
+
if (walletInfo?.providers) {
|
|
2092
|
+
if (this.addressTypes.includes(import_client3.AddressType.solana) && walletInfo.providers.solana) {
|
|
475
2093
|
try {
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
connectedAddresses.push({
|
|
479
|
-
addressType: import_client4.AddressType.solana,
|
|
480
|
-
address: publicKey
|
|
481
|
-
});
|
|
482
|
-
debug.info(DebugCategory.INJECTED_PROVIDER, "Solana connected successfully", { address: publicKey });
|
|
483
|
-
}
|
|
2094
|
+
await walletInfo.providers.solana.disconnect();
|
|
2095
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana disconnected successfully");
|
|
484
2096
|
} catch (err) {
|
|
485
|
-
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to
|
|
486
|
-
this.emit("connect_error", {
|
|
487
|
-
error: err instanceof Error ? err.message : "Failed to connect",
|
|
488
|
-
source: "manual-connect"
|
|
489
|
-
});
|
|
490
|
-
throw err;
|
|
2097
|
+
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to disconnect Solana", { error: err });
|
|
491
2098
|
}
|
|
492
2099
|
}
|
|
493
|
-
if (this.addressTypes.includes(
|
|
2100
|
+
if (this.addressTypes.includes(import_client3.AddressType.ethereum) && walletInfo.providers.ethereum) {
|
|
494
2101
|
try {
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
connectedAddresses.push(
|
|
498
|
-
...accounts.map((address) => ({
|
|
499
|
-
addressType: import_client4.AddressType.ethereum,
|
|
500
|
-
address
|
|
501
|
-
}))
|
|
502
|
-
);
|
|
503
|
-
debug.info(DebugCategory.INJECTED_PROVIDER, "Ethereum connected successfully", { addresses: accounts });
|
|
504
|
-
}
|
|
2102
|
+
await walletInfo.providers.ethereum.disconnect();
|
|
2103
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum disconnected successfully");
|
|
505
2104
|
} catch (err) {
|
|
506
|
-
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to
|
|
507
|
-
this.emit("connect_error", {
|
|
508
|
-
error: err instanceof Error ? err.message : "Failed to connect",
|
|
509
|
-
source: "manual-connect"
|
|
510
|
-
});
|
|
511
|
-
throw err;
|
|
2105
|
+
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to disconnect Ethereum", { error: err });
|
|
512
2106
|
}
|
|
513
2107
|
}
|
|
514
|
-
if (connectedAddresses.length === 0) {
|
|
515
|
-
const error = new Error("Failed to connect to any supported wallet provider");
|
|
516
|
-
this.emit("connect_error", {
|
|
517
|
-
error: error.message,
|
|
518
|
-
source: "manual-connect"
|
|
519
|
-
});
|
|
520
|
-
throw error;
|
|
521
|
-
}
|
|
522
|
-
this.addresses = connectedAddresses;
|
|
523
|
-
this.connected = true;
|
|
524
|
-
const authUserId = await this.getAuthUserId("manual-connect");
|
|
525
|
-
try {
|
|
526
|
-
localStorage.removeItem(MANUAL_DISCONNECT_KEY);
|
|
527
|
-
debug.log(DebugCategory.INJECTED_PROVIDER, "Cleared manual disconnect flag - auto-reconnect enabled");
|
|
528
|
-
} catch (error) {
|
|
529
|
-
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to clear manual disconnect flag", { error });
|
|
530
|
-
}
|
|
531
|
-
const result = {
|
|
532
|
-
addresses: this.addresses,
|
|
533
|
-
status: "completed",
|
|
534
|
-
authUserId
|
|
535
|
-
};
|
|
536
|
-
this.emit("connect", {
|
|
537
|
-
addresses: this.addresses,
|
|
538
|
-
source: "manual-connect",
|
|
539
|
-
authUserId
|
|
540
|
-
});
|
|
541
|
-
return result;
|
|
542
|
-
} catch (error) {
|
|
543
|
-
if (error instanceof Error && !error.message.includes("Phantom wallet not found") && !error.message.includes("Failed to connect to any supported wallet provider")) {
|
|
544
|
-
this.emit("connect_error", {
|
|
545
|
-
error: error.message,
|
|
546
|
-
source: "manual-connect"
|
|
547
|
-
});
|
|
548
|
-
}
|
|
549
|
-
throw error;
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
async disconnect() {
|
|
553
|
-
debug.info(DebugCategory.INJECTED_PROVIDER, "Starting injected provider disconnect");
|
|
554
|
-
if (this.addressTypes.includes(import_client4.AddressType.solana)) {
|
|
555
|
-
try {
|
|
556
|
-
await this.phantom.solana.disconnect();
|
|
557
|
-
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana disconnected successfully");
|
|
558
|
-
} catch (err) {
|
|
559
|
-
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to disconnect Solana", { error: err });
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
if (this.addressTypes.includes(import_client4.AddressType.ethereum)) {
|
|
563
|
-
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum disconnected (no-op)");
|
|
564
2108
|
}
|
|
565
2109
|
this.browserInjectedCleanupFunctions.forEach((cleanup) => cleanup());
|
|
566
2110
|
this.browserInjectedCleanupFunctions = [];
|
|
567
|
-
this.
|
|
568
|
-
|
|
2111
|
+
if (this.selectedWalletId) {
|
|
2112
|
+
this.externalWalletEventListenersSetup.delete(this.selectedWalletId);
|
|
2113
|
+
this.setWalletState(this.selectedWalletId, {
|
|
2114
|
+
connected: false,
|
|
2115
|
+
addresses: []
|
|
2116
|
+
});
|
|
2117
|
+
}
|
|
569
2118
|
try {
|
|
570
|
-
localStorage.
|
|
571
|
-
debug.log(DebugCategory.INJECTED_PROVIDER, "
|
|
2119
|
+
localStorage.removeItem(WAS_CONNECTED_KEY);
|
|
2120
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Cleared was connected flag to prevent auto-reconnect");
|
|
572
2121
|
} catch (error) {
|
|
573
|
-
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to
|
|
2122
|
+
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to clear was-connected flag", { error });
|
|
574
2123
|
}
|
|
575
2124
|
this.emit("disconnect", {
|
|
576
2125
|
source: "manual-disconnect"
|
|
@@ -578,66 +2127,48 @@ var InjectedProvider = class {
|
|
|
578
2127
|
debug.info(DebugCategory.INJECTED_PROVIDER, "Injected provider disconnected successfully");
|
|
579
2128
|
}
|
|
580
2129
|
/**
|
|
581
|
-
* Attempt auto-connection
|
|
582
|
-
*
|
|
2130
|
+
* Attempt auto-connection if user was previously connected
|
|
2131
|
+
* Only reconnects if the user connected before and didn't explicitly disconnect
|
|
583
2132
|
* Should be called after setting up event listeners
|
|
584
2133
|
*/
|
|
585
2134
|
async autoConnect() {
|
|
586
|
-
debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting auto-connect
|
|
2135
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting auto-connect");
|
|
2136
|
+
let lastWalletId = null;
|
|
587
2137
|
try {
|
|
588
|
-
const
|
|
589
|
-
if (
|
|
590
|
-
debug.log(DebugCategory.INJECTED_PROVIDER, "Skipping auto-connect: user previously
|
|
2138
|
+
const wasConnected = localStorage.getItem(WAS_CONNECTED_KEY);
|
|
2139
|
+
if (wasConnected !== WAS_CONNECTED_VALUE) {
|
|
2140
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Skipping auto-connect: user was not previously connected");
|
|
591
2141
|
return;
|
|
592
2142
|
}
|
|
2143
|
+
lastWalletId = localStorage.getItem(LAST_WALLET_ID_KEY);
|
|
2144
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "User was previously connected, attempting auto-connect", {
|
|
2145
|
+
lastWalletId: lastWalletId || "phantom"
|
|
2146
|
+
});
|
|
593
2147
|
} catch (error) {
|
|
594
|
-
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to check
|
|
2148
|
+
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to check was-connected flag", { error });
|
|
2149
|
+
return;
|
|
595
2150
|
}
|
|
596
2151
|
this.emit("connect_start", {
|
|
597
2152
|
source: "auto-connect",
|
|
598
2153
|
providerType: "injected"
|
|
599
2154
|
});
|
|
600
2155
|
try {
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
2156
|
+
const walletId = lastWalletId || "phantom";
|
|
2157
|
+
await this.waitForWalletDiscovery(walletId);
|
|
2158
|
+
const walletInfo = this.validateAndSelectWallet(walletId);
|
|
2159
|
+
let connectedAddresses = [];
|
|
2160
|
+
try {
|
|
2161
|
+
connectedAddresses = await this.connectToWallet(walletInfo, {
|
|
2162
|
+
onlyIfTrusted: true,
|
|
2163
|
+
silent: true,
|
|
2164
|
+
skipEventListeners: true
|
|
2165
|
+
// Set up listeners only if connection succeeds
|
|
2166
|
+
});
|
|
2167
|
+
} catch (err) {
|
|
2168
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Auto-connect failed (expected if not trusted)", {
|
|
2169
|
+
error: err,
|
|
2170
|
+
walletId: this.selectedWalletId
|
|
606
2171
|
});
|
|
607
|
-
return;
|
|
608
|
-
}
|
|
609
|
-
const connectedAddresses = [];
|
|
610
|
-
if (this.addressTypes.includes(import_client4.AddressType.solana)) {
|
|
611
|
-
debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting Solana auto-connect");
|
|
612
|
-
try {
|
|
613
|
-
const publicKey = await this.phantom.solana.connect({ onlyIfTrusted: true });
|
|
614
|
-
if (publicKey) {
|
|
615
|
-
connectedAddresses.push({
|
|
616
|
-
addressType: import_client4.AddressType.solana,
|
|
617
|
-
address: publicKey
|
|
618
|
-
});
|
|
619
|
-
debug.info(DebugCategory.INJECTED_PROVIDER, "Solana auto-connected successfully", { address: publicKey });
|
|
620
|
-
}
|
|
621
|
-
} catch (err) {
|
|
622
|
-
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana auto-connect failed (expected if not trusted)", { error: err });
|
|
623
|
-
}
|
|
624
|
-
}
|
|
625
|
-
if (this.addressTypes.includes(import_client4.AddressType.ethereum)) {
|
|
626
|
-
debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting Ethereum auto-connect");
|
|
627
|
-
try {
|
|
628
|
-
const accounts = await this.phantom.ethereum.connect({ onlyIfTrusted: true });
|
|
629
|
-
if (accounts && accounts.length > 0) {
|
|
630
|
-
connectedAddresses.push(
|
|
631
|
-
...accounts.map((address) => ({
|
|
632
|
-
addressType: import_client4.AddressType.ethereum,
|
|
633
|
-
address
|
|
634
|
-
}))
|
|
635
|
-
);
|
|
636
|
-
debug.info(DebugCategory.INJECTED_PROVIDER, "Ethereum auto-connected successfully", { addresses: accounts });
|
|
637
|
-
}
|
|
638
|
-
} catch (err) {
|
|
639
|
-
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum auto-connect failed (expected if not trusted)", { error: err });
|
|
640
|
-
}
|
|
641
2172
|
}
|
|
642
2173
|
if (connectedAddresses.length === 0) {
|
|
643
2174
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Auto-connect failed: no trusted connections available");
|
|
@@ -647,17 +2178,32 @@ var InjectedProvider = class {
|
|
|
647
2178
|
});
|
|
648
2179
|
return;
|
|
649
2180
|
}
|
|
650
|
-
this.
|
|
651
|
-
this.
|
|
2181
|
+
this.setupExternalWalletEvents(walletInfo);
|
|
2182
|
+
if (this.selectedWalletId === "phantom" && isPhantomWallet(walletInfo)) {
|
|
2183
|
+
this.browserInjectedCleanupFunctions.forEach((cleanup) => cleanup());
|
|
2184
|
+
this.browserInjectedCleanupFunctions = [];
|
|
2185
|
+
this.setupBrowserInjectedEvents();
|
|
2186
|
+
this.eventsInitialized = true;
|
|
2187
|
+
}
|
|
2188
|
+
if (this.selectedWalletId) {
|
|
2189
|
+
this.setWalletState(this.selectedWalletId, {
|
|
2190
|
+
connected: true,
|
|
2191
|
+
addresses: connectedAddresses
|
|
2192
|
+
});
|
|
2193
|
+
}
|
|
652
2194
|
const authUserId = await this.getAuthUserId("auto-connect");
|
|
653
2195
|
this.emit("connect", {
|
|
654
|
-
addresses:
|
|
2196
|
+
addresses: connectedAddresses,
|
|
655
2197
|
source: "auto-connect",
|
|
656
2198
|
authUserId
|
|
657
2199
|
});
|
|
658
2200
|
debug.info(DebugCategory.INJECTED_PROVIDER, "Auto-connect successful", {
|
|
659
2201
|
addressCount: connectedAddresses.length,
|
|
660
|
-
addresses: connectedAddresses.map((addr) => ({
|
|
2202
|
+
addresses: connectedAddresses.map((addr) => ({
|
|
2203
|
+
type: addr.addressType,
|
|
2204
|
+
address: addr.address.substring(0, 8) + "..."
|
|
2205
|
+
})),
|
|
2206
|
+
walletId: this.selectedWalletId,
|
|
661
2207
|
authUserId
|
|
662
2208
|
});
|
|
663
2209
|
} catch (error) {
|
|
@@ -670,47 +2216,101 @@ var InjectedProvider = class {
|
|
|
670
2216
|
});
|
|
671
2217
|
}
|
|
672
2218
|
}
|
|
2219
|
+
getWalletState(walletId) {
|
|
2220
|
+
if (!this.walletStates.has(walletId)) {
|
|
2221
|
+
this.walletStates.set(walletId, { connected: false, addresses: [] });
|
|
2222
|
+
}
|
|
2223
|
+
return this.walletStates.get(walletId);
|
|
2224
|
+
}
|
|
2225
|
+
setWalletState(walletId, state) {
|
|
2226
|
+
this.walletStates.set(walletId, state);
|
|
2227
|
+
}
|
|
673
2228
|
getAddresses() {
|
|
674
|
-
|
|
2229
|
+
const walletId = this.selectedWalletId || "phantom";
|
|
2230
|
+
return this.getWalletState(walletId).addresses;
|
|
2231
|
+
}
|
|
2232
|
+
/**
|
|
2233
|
+
* Get enabled address types for the current selected wallet
|
|
2234
|
+
* - For Phantom: returns config.addressTypes
|
|
2235
|
+
* - For external wallets: returns the wallet's addressTypes from registry
|
|
2236
|
+
*/
|
|
2237
|
+
getEnabledAddressTypes() {
|
|
2238
|
+
if (!this.selectedWalletId || this.selectedWalletId === "phantom") {
|
|
2239
|
+
return this.addressTypes;
|
|
2240
|
+
}
|
|
2241
|
+
const walletInfo = this.walletRegistry.getById(this.selectedWalletId);
|
|
2242
|
+
if (walletInfo) {
|
|
2243
|
+
return walletInfo.addressTypes;
|
|
2244
|
+
}
|
|
2245
|
+
return this.addressTypes;
|
|
675
2246
|
}
|
|
676
2247
|
isConnected() {
|
|
677
|
-
|
|
2248
|
+
const walletId = this.selectedWalletId || "phantom";
|
|
2249
|
+
return this.getWalletState(walletId).connected;
|
|
678
2250
|
}
|
|
679
|
-
// AutoConfirm methods - only available for
|
|
2251
|
+
// AutoConfirm methods - only available for Phantom wallet
|
|
680
2252
|
async enableAutoConfirm(params) {
|
|
2253
|
+
const walletInfo = this.walletRegistry.getById(this.selectedWalletId || "phantom");
|
|
2254
|
+
if (!isPhantomWallet(walletInfo)) {
|
|
2255
|
+
throw new Error("Auto-confirm is only available for Phantom wallet");
|
|
2256
|
+
}
|
|
681
2257
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Enabling autoConfirm", { params });
|
|
682
|
-
return await
|
|
2258
|
+
return await walletInfo.phantomInstance.autoConfirm.autoConfirmEnable(params);
|
|
683
2259
|
}
|
|
684
2260
|
async disableAutoConfirm() {
|
|
2261
|
+
const walletInfo = this.walletRegistry.getById(this.selectedWalletId || "phantom");
|
|
2262
|
+
if (!isPhantomWallet(walletInfo)) {
|
|
2263
|
+
throw new Error("Auto-confirm is only available for Phantom wallet");
|
|
2264
|
+
}
|
|
685
2265
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Disabling autoConfirm");
|
|
686
|
-
await
|
|
2266
|
+
await walletInfo.phantomInstance.autoConfirm.autoConfirmDisable();
|
|
687
2267
|
}
|
|
688
2268
|
async getAutoConfirmStatus() {
|
|
2269
|
+
const walletInfo = this.walletRegistry.getById(this.selectedWalletId || "phantom");
|
|
2270
|
+
if (!isPhantomWallet(walletInfo)) {
|
|
2271
|
+
throw new Error("Auto-confirm is only available for Phantom wallet");
|
|
2272
|
+
}
|
|
689
2273
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Getting autoConfirm status");
|
|
690
|
-
return await
|
|
2274
|
+
return await walletInfo.phantomInstance.autoConfirm.autoConfirmStatus();
|
|
691
2275
|
}
|
|
692
2276
|
async getSupportedAutoConfirmChains() {
|
|
2277
|
+
const walletInfo = this.walletRegistry.getById(this.selectedWalletId || "phantom");
|
|
2278
|
+
if (!isPhantomWallet(walletInfo)) {
|
|
2279
|
+
throw new Error("Auto-confirm is only available for Phantom wallet");
|
|
2280
|
+
}
|
|
693
2281
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Getting supported autoConfirm chains");
|
|
694
|
-
return await
|
|
2282
|
+
return await walletInfo.phantomInstance.autoConfirm.autoConfirmSupportedChains();
|
|
695
2283
|
}
|
|
696
2284
|
/**
|
|
697
2285
|
* Helper method to get authUserId from window.phantom.app.getUser()
|
|
698
|
-
* Returns undefined if the method is not available or fails
|
|
2286
|
+
* Returns undefined if the method is not available or fails, or if wallet is not Phantom
|
|
699
2287
|
*/
|
|
700
2288
|
async getAuthUserId(context) {
|
|
2289
|
+
const walletInfo = this.walletRegistry.getById(this.selectedWalletId || "phantom");
|
|
2290
|
+
if (!isPhantomWallet(walletInfo)) {
|
|
2291
|
+
return void 0;
|
|
2292
|
+
}
|
|
701
2293
|
try {
|
|
702
2294
|
if (window.phantom?.app?.getUser) {
|
|
703
2295
|
const userInfo = await window.phantom.app.getUser();
|
|
704
2296
|
const authUserId = userInfo?.authUserId;
|
|
705
2297
|
if (authUserId) {
|
|
706
|
-
debug.log(
|
|
707
|
-
|
|
708
|
-
|
|
2298
|
+
debug.log(
|
|
2299
|
+
DebugCategory.INJECTED_PROVIDER,
|
|
2300
|
+
`Retrieved authUserId from window.phantom.app.getUser() during ${context}`,
|
|
2301
|
+
{
|
|
2302
|
+
authUserId
|
|
2303
|
+
}
|
|
2304
|
+
);
|
|
709
2305
|
}
|
|
710
2306
|
return authUserId;
|
|
711
2307
|
}
|
|
712
2308
|
} catch (error) {
|
|
713
|
-
debug.log(
|
|
2309
|
+
debug.log(
|
|
2310
|
+
DebugCategory.INJECTED_PROVIDER,
|
|
2311
|
+
`Failed to get user info during ${context} (method may not be supported)`,
|
|
2312
|
+
{ error }
|
|
2313
|
+
);
|
|
714
2314
|
}
|
|
715
2315
|
return void 0;
|
|
716
2316
|
}
|
|
@@ -753,140 +2353,245 @@ var InjectedProvider = class {
|
|
|
753
2353
|
}
|
|
754
2354
|
}
|
|
755
2355
|
setupBrowserInjectedEvents() {
|
|
756
|
-
|
|
757
|
-
if (
|
|
758
|
-
|
|
2356
|
+
const walletInfo = this.walletRegistry.getById(this.selectedWalletId || "phantom");
|
|
2357
|
+
if (!isPhantomWallet(walletInfo)) {
|
|
2358
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Skipping browser-injected-sdk event setup - not Phantom wallet");
|
|
2359
|
+
return;
|
|
759
2360
|
}
|
|
760
|
-
|
|
761
|
-
|
|
2361
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up browser-injected-sdk event listeners");
|
|
2362
|
+
if (this.selectedWalletId === "phantom" && isPhantomWallet(walletInfo)) {
|
|
2363
|
+
if (this.addressTypes.includes(import_client3.AddressType.solana)) {
|
|
2364
|
+
this.setupSolanaEvents(walletInfo.phantomInstance);
|
|
2365
|
+
}
|
|
2366
|
+
if (this.addressTypes.includes(import_client3.AddressType.ethereum)) {
|
|
2367
|
+
this.setupEthereumEvents(walletInfo.phantomInstance);
|
|
2368
|
+
}
|
|
762
2369
|
}
|
|
763
2370
|
}
|
|
764
|
-
setupSolanaEvents() {
|
|
2371
|
+
setupSolanaEvents(phantom) {
|
|
765
2372
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up Solana event listeners");
|
|
766
2373
|
const handleSolanaConnect = async (publicKey) => {
|
|
767
2374
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana connect event received", { publicKey });
|
|
768
|
-
const
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
2375
|
+
const walletId = this.selectedWalletId || "phantom";
|
|
2376
|
+
const state = this.getWalletState(walletId);
|
|
2377
|
+
const solanaAddress = { addressType: import_client3.AddressType.solana, address: publicKey };
|
|
2378
|
+
const hasSolana = state.addresses.some((addr) => addr.addressType === import_client3.AddressType.solana);
|
|
2379
|
+
const newAddresses = hasSolana ? state.addresses.map((addr) => addr.addressType === import_client3.AddressType.solana ? solanaAddress : addr) : [...state.addresses, solanaAddress];
|
|
2380
|
+
this.setWalletState(walletId, {
|
|
2381
|
+
connected: true,
|
|
2382
|
+
addresses: newAddresses
|
|
2383
|
+
});
|
|
773
2384
|
const authUserId = await this.getAuthUserId("Solana connect event");
|
|
774
2385
|
this.emit("connect", {
|
|
775
|
-
addresses:
|
|
2386
|
+
addresses: newAddresses,
|
|
776
2387
|
source: "injected-extension",
|
|
777
2388
|
authUserId
|
|
778
2389
|
});
|
|
779
2390
|
};
|
|
780
2391
|
const handleSolanaDisconnect = () => {
|
|
781
2392
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana disconnect event received");
|
|
782
|
-
|
|
783
|
-
|
|
2393
|
+
const walletId = this.selectedWalletId || "phantom";
|
|
2394
|
+
const state = this.getWalletState(walletId);
|
|
2395
|
+
const filteredAddresses = state.addresses.filter((addr) => addr.addressType !== import_client3.AddressType.solana);
|
|
2396
|
+
this.setWalletState(walletId, {
|
|
2397
|
+
connected: filteredAddresses.length > 0,
|
|
2398
|
+
addresses: filteredAddresses
|
|
2399
|
+
});
|
|
784
2400
|
this.emit("disconnect", {
|
|
785
2401
|
source: "injected-extension"
|
|
786
2402
|
});
|
|
787
2403
|
};
|
|
788
2404
|
const handleSolanaAccountChanged = async (publicKey) => {
|
|
789
2405
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana account changed event received", { publicKey });
|
|
790
|
-
const
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
}
|
|
2406
|
+
const walletId = this.selectedWalletId || "phantom";
|
|
2407
|
+
const state = this.getWalletState(walletId);
|
|
2408
|
+
const solanaIndex = state.addresses.findIndex((addr) => addr.addressType === import_client3.AddressType.solana);
|
|
2409
|
+
const newAddresses = solanaIndex >= 0 ? state.addresses.map(
|
|
2410
|
+
(addr, idx) => idx === solanaIndex ? { addressType: import_client3.AddressType.solana, address: publicKey } : addr
|
|
2411
|
+
) : [...state.addresses, { addressType: import_client3.AddressType.solana, address: publicKey }];
|
|
2412
|
+
this.setWalletState(walletId, {
|
|
2413
|
+
connected: true,
|
|
2414
|
+
addresses: newAddresses
|
|
2415
|
+
});
|
|
796
2416
|
const authUserId = await this.getAuthUserId("Solana account changed event");
|
|
797
2417
|
this.emit("connect", {
|
|
798
|
-
addresses:
|
|
2418
|
+
addresses: newAddresses,
|
|
799
2419
|
source: "injected-extension-account-change",
|
|
800
2420
|
authUserId
|
|
801
2421
|
});
|
|
802
2422
|
};
|
|
803
|
-
const cleanupConnect =
|
|
804
|
-
const cleanupDisconnect =
|
|
805
|
-
const cleanupAccountChanged =
|
|
2423
|
+
const cleanupConnect = phantom.solana.addEventListener("connect", handleSolanaConnect);
|
|
2424
|
+
const cleanupDisconnect = phantom.solana.addEventListener("disconnect", handleSolanaDisconnect);
|
|
2425
|
+
const cleanupAccountChanged = phantom.solana.addEventListener("accountChanged", handleSolanaAccountChanged);
|
|
806
2426
|
this.browserInjectedCleanupFunctions.push(cleanupConnect, cleanupDisconnect, cleanupAccountChanged);
|
|
807
2427
|
}
|
|
808
|
-
setupEthereumEvents() {
|
|
2428
|
+
setupEthereumEvents(phantom) {
|
|
809
2429
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up Ethereum event listeners");
|
|
810
2430
|
const handleEthereumConnect = async (accounts) => {
|
|
811
2431
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum connect event received", { accounts });
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
}
|
|
821
|
-
this.connected = this.addresses.length > 0;
|
|
2432
|
+
const walletId = this.selectedWalletId || "phantom";
|
|
2433
|
+
const state = this.getWalletState(walletId);
|
|
2434
|
+
const ethAddresses = accounts.map((address) => ({ addressType: import_client3.AddressType.ethereum, address }));
|
|
2435
|
+
const otherAddresses = state.addresses.filter((addr) => addr.addressType !== import_client3.AddressType.ethereum);
|
|
2436
|
+
const newAddresses = [...otherAddresses, ...ethAddresses];
|
|
2437
|
+
this.setWalletState(walletId, {
|
|
2438
|
+
connected: true,
|
|
2439
|
+
addresses: newAddresses
|
|
2440
|
+
});
|
|
822
2441
|
const authUserId = await this.getAuthUserId("Ethereum connect event");
|
|
823
2442
|
this.emit("connect", {
|
|
824
|
-
addresses:
|
|
2443
|
+
addresses: newAddresses,
|
|
825
2444
|
source: "injected-extension",
|
|
826
2445
|
authUserId
|
|
827
2446
|
});
|
|
828
2447
|
};
|
|
829
2448
|
const handleEthereumDisconnect = () => {
|
|
830
2449
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum disconnect event received");
|
|
831
|
-
|
|
832
|
-
|
|
2450
|
+
const walletId = this.selectedWalletId || "phantom";
|
|
2451
|
+
const state = this.getWalletState(walletId);
|
|
2452
|
+
const filteredAddresses = state.addresses.filter((addr) => addr.addressType !== import_client3.AddressType.ethereum);
|
|
2453
|
+
this.setWalletState(walletId, {
|
|
2454
|
+
connected: filteredAddresses.length > 0,
|
|
2455
|
+
addresses: filteredAddresses
|
|
2456
|
+
});
|
|
833
2457
|
this.emit("disconnect", {
|
|
834
2458
|
source: "injected-extension"
|
|
835
2459
|
});
|
|
836
2460
|
};
|
|
837
2461
|
const handleEthereumAccountsChanged = async (accounts) => {
|
|
838
2462
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum accounts changed event received", { accounts });
|
|
839
|
-
|
|
2463
|
+
const walletId = this.selectedWalletId || "phantom";
|
|
2464
|
+
const state = this.getWalletState(walletId);
|
|
2465
|
+
const otherAddresses = state.addresses.filter((addr) => addr.addressType !== import_client3.AddressType.ethereum);
|
|
840
2466
|
if (accounts && accounts.length > 0) {
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
);
|
|
2467
|
+
const ethAddresses = accounts.map((address) => ({ addressType: import_client3.AddressType.ethereum, address }));
|
|
2468
|
+
const newAddresses = [...otherAddresses, ...ethAddresses];
|
|
2469
|
+
this.setWalletState(walletId, {
|
|
2470
|
+
connected: true,
|
|
2471
|
+
addresses: newAddresses
|
|
2472
|
+
});
|
|
847
2473
|
const authUserId = await this.getAuthUserId("Ethereum accounts changed event");
|
|
848
2474
|
this.emit("connect", {
|
|
849
|
-
addresses:
|
|
2475
|
+
addresses: newAddresses,
|
|
850
2476
|
source: "injected-extension-account-change",
|
|
851
2477
|
authUserId
|
|
852
2478
|
});
|
|
853
2479
|
} else {
|
|
854
|
-
this.
|
|
2480
|
+
this.setWalletState(walletId, {
|
|
2481
|
+
connected: otherAddresses.length > 0,
|
|
2482
|
+
addresses: otherAddresses
|
|
2483
|
+
});
|
|
855
2484
|
this.emit("disconnect", {
|
|
856
2485
|
source: "injected-extension-account-change"
|
|
857
2486
|
});
|
|
858
2487
|
}
|
|
859
2488
|
};
|
|
860
|
-
const cleanupConnect =
|
|
861
|
-
const cleanupDisconnect =
|
|
862
|
-
const cleanupAccountsChanged =
|
|
863
|
-
"accountsChanged",
|
|
864
|
-
handleEthereumAccountsChanged
|
|
865
|
-
);
|
|
2489
|
+
const cleanupConnect = phantom.ethereum.addEventListener("connect", handleEthereumConnect);
|
|
2490
|
+
const cleanupDisconnect = phantom.ethereum.addEventListener("disconnect", handleEthereumDisconnect);
|
|
2491
|
+
const cleanupAccountsChanged = phantom.ethereum.addEventListener("accountsChanged", handleEthereumAccountsChanged);
|
|
866
2492
|
this.browserInjectedCleanupFunctions.push(cleanupConnect, cleanupDisconnect, cleanupAccountsChanged);
|
|
867
2493
|
}
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
this.
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
2494
|
+
setupExternalWalletEvents(walletInfo) {
|
|
2495
|
+
if (isPhantomWallet(walletInfo)) {
|
|
2496
|
+
return;
|
|
2497
|
+
}
|
|
2498
|
+
if (!this.selectedWalletId || this.externalWalletEventListenersSetup.has(this.selectedWalletId)) {
|
|
2499
|
+
return;
|
|
2500
|
+
}
|
|
2501
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up external wallet event listeners", {
|
|
2502
|
+
walletId: this.selectedWalletId
|
|
2503
|
+
});
|
|
2504
|
+
if (walletInfo.providers?.ethereum) {
|
|
2505
|
+
const handleExternalEthereumAccountsChanged = async (accounts) => {
|
|
2506
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Ethereum accounts changed event received", {
|
|
2507
|
+
walletId: this.selectedWalletId,
|
|
2508
|
+
accounts
|
|
2509
|
+
});
|
|
2510
|
+
const walletId = this.selectedWalletId;
|
|
2511
|
+
const state = this.getWalletState(walletId);
|
|
2512
|
+
const otherAddresses = state.addresses.filter((addr) => addr.addressType !== import_client3.AddressType.ethereum);
|
|
2513
|
+
if (accounts && accounts.length > 0) {
|
|
2514
|
+
const ethAddresses = accounts.map((address) => ({ addressType: import_client3.AddressType.ethereum, address }));
|
|
2515
|
+
const newAddresses = [...otherAddresses, ...ethAddresses];
|
|
2516
|
+
this.setWalletState(walletId, {
|
|
2517
|
+
connected: true,
|
|
2518
|
+
addresses: newAddresses
|
|
2519
|
+
});
|
|
2520
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Updated Ethereum addresses after account change", {
|
|
2521
|
+
walletId,
|
|
2522
|
+
oldCount: 0,
|
|
2523
|
+
// We filtered them out
|
|
2524
|
+
newCount: accounts.length,
|
|
2525
|
+
addresses: newAddresses.filter((addr) => addr.addressType === import_client3.AddressType.ethereum)
|
|
2526
|
+
});
|
|
2527
|
+
const authUserId = await this.getAuthUserId("External wallet Ethereum accounts changed event");
|
|
2528
|
+
this.emit("connect", {
|
|
2529
|
+
addresses: newAddresses,
|
|
2530
|
+
source: "external-wallet-account-change",
|
|
2531
|
+
authUserId
|
|
2532
|
+
});
|
|
2533
|
+
} else {
|
|
2534
|
+
this.setWalletState(walletId, {
|
|
2535
|
+
connected: otherAddresses.length > 0,
|
|
2536
|
+
addresses: otherAddresses
|
|
2537
|
+
});
|
|
2538
|
+
this.emit("disconnect", {
|
|
2539
|
+
source: "external-wallet-account-change"
|
|
2540
|
+
});
|
|
2541
|
+
}
|
|
2542
|
+
};
|
|
2543
|
+
if (typeof walletInfo.providers.ethereum.on === "function") {
|
|
2544
|
+
walletInfo.providers.ethereum.on("accountsChanged", handleExternalEthereumAccountsChanged);
|
|
2545
|
+
this.browserInjectedCleanupFunctions.push(() => {
|
|
2546
|
+
if (typeof walletInfo.providers?.ethereum?.off === "function") {
|
|
2547
|
+
walletInfo.providers.ethereum.off("accountsChanged", handleExternalEthereumAccountsChanged);
|
|
2548
|
+
}
|
|
2549
|
+
});
|
|
888
2550
|
}
|
|
889
|
-
}
|
|
2551
|
+
}
|
|
2552
|
+
if (walletInfo.providers?.solana) {
|
|
2553
|
+
const handleExternalSolanaAccountChanged = async (publicKey) => {
|
|
2554
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "External wallet Solana account changed event received", {
|
|
2555
|
+
walletId: this.selectedWalletId,
|
|
2556
|
+
publicKey
|
|
2557
|
+
});
|
|
2558
|
+
const walletId = this.selectedWalletId;
|
|
2559
|
+
const state = this.getWalletState(walletId);
|
|
2560
|
+
const otherAddresses = state.addresses.filter((addr) => addr.addressType !== import_client3.AddressType.solana);
|
|
2561
|
+
if (publicKey) {
|
|
2562
|
+
const newAddresses = [...otherAddresses, { addressType: import_client3.AddressType.solana, address: publicKey }];
|
|
2563
|
+
this.setWalletState(walletId, {
|
|
2564
|
+
connected: true,
|
|
2565
|
+
addresses: newAddresses
|
|
2566
|
+
});
|
|
2567
|
+
const authUserId = await this.getAuthUserId("External wallet Solana account changed event");
|
|
2568
|
+
this.emit("connect", {
|
|
2569
|
+
addresses: newAddresses,
|
|
2570
|
+
source: "external-wallet-account-change",
|
|
2571
|
+
authUserId
|
|
2572
|
+
});
|
|
2573
|
+
} else {
|
|
2574
|
+
this.setWalletState(walletId, {
|
|
2575
|
+
connected: otherAddresses.length > 0,
|
|
2576
|
+
addresses: otherAddresses
|
|
2577
|
+
});
|
|
2578
|
+
this.emit("disconnect", {
|
|
2579
|
+
source: "external-wallet-account-change"
|
|
2580
|
+
});
|
|
2581
|
+
}
|
|
2582
|
+
};
|
|
2583
|
+
if (typeof walletInfo.providers.solana.on === "function") {
|
|
2584
|
+
walletInfo.providers.solana.on("accountChanged", handleExternalSolanaAccountChanged);
|
|
2585
|
+
this.browserInjectedCleanupFunctions.push(() => {
|
|
2586
|
+
if (typeof walletInfo.providers?.solana?.off === "function") {
|
|
2587
|
+
walletInfo.providers.solana.off("accountChanged", handleExternalSolanaAccountChanged);
|
|
2588
|
+
}
|
|
2589
|
+
});
|
|
2590
|
+
}
|
|
2591
|
+
}
|
|
2592
|
+
if (this.selectedWalletId) {
|
|
2593
|
+
this.externalWalletEventListenersSetup.add(this.selectedWalletId);
|
|
2594
|
+
}
|
|
890
2595
|
}
|
|
891
2596
|
};
|
|
892
2597
|
|
|
@@ -1201,7 +2906,7 @@ var BrowserAuthProvider = class {
|
|
|
1201
2906
|
// OAuth session management - defaults to allow refresh unless explicitly clearing after logout
|
|
1202
2907
|
clear_previous_session: (phantomOptions.clearPreviousSession ?? false).toString(),
|
|
1203
2908
|
allow_refresh: (phantomOptions.allowRefresh ?? true).toString(),
|
|
1204
|
-
sdk_version: "1.0.0-beta.
|
|
2909
|
+
sdk_version: "1.0.0-beta.24",
|
|
1205
2910
|
sdk_type: "browser",
|
|
1206
2911
|
platform: detectBrowser().name
|
|
1207
2912
|
});
|
|
@@ -1231,7 +2936,7 @@ var BrowserAuthProvider = class {
|
|
|
1231
2936
|
resolve();
|
|
1232
2937
|
});
|
|
1233
2938
|
}
|
|
1234
|
-
resumeAuthFromRedirect() {
|
|
2939
|
+
resumeAuthFromRedirect(provider) {
|
|
1235
2940
|
try {
|
|
1236
2941
|
const walletId = this.urlParamsAccessor.getParam("wallet_id");
|
|
1237
2942
|
const sessionId = this.urlParamsAccessor.getParam("session_id");
|
|
@@ -1298,16 +3003,21 @@ var BrowserAuthProvider = class {
|
|
|
1298
3003
|
throw new Error("Missing organization_id in auth response");
|
|
1299
3004
|
}
|
|
1300
3005
|
if (organizationId.startsWith("temp-")) {
|
|
1301
|
-
debug.warn(
|
|
1302
|
-
|
|
1303
|
-
|
|
3006
|
+
debug.warn(
|
|
3007
|
+
DebugCategory.PHANTOM_CONNECT_AUTH,
|
|
3008
|
+
"Received temporary organization_id, server may not be configured properly",
|
|
3009
|
+
{
|
|
3010
|
+
organizationId
|
|
3011
|
+
}
|
|
3012
|
+
);
|
|
1304
3013
|
}
|
|
1305
3014
|
return {
|
|
1306
3015
|
walletId,
|
|
1307
3016
|
organizationId,
|
|
1308
3017
|
accountDerivationIndex: accountDerivationIndex ? parseInt(accountDerivationIndex) : 0,
|
|
1309
3018
|
expiresInMs: expiresInMs ? parseInt(expiresInMs) : 0,
|
|
1310
|
-
authUserId: authUserId || void 0
|
|
3019
|
+
authUserId: authUserId || void 0,
|
|
3020
|
+
provider
|
|
1311
3021
|
};
|
|
1312
3022
|
} catch (error) {
|
|
1313
3023
|
sessionStorage.removeItem("phantom-auth-context");
|
|
@@ -1317,10 +3027,10 @@ var BrowserAuthProvider = class {
|
|
|
1317
3027
|
};
|
|
1318
3028
|
|
|
1319
3029
|
// src/providers/embedded/adapters/phantom-app.ts
|
|
1320
|
-
var
|
|
3030
|
+
var import_browser_injected_sdk4 = require("@phantom/browser-injected-sdk");
|
|
1321
3031
|
|
|
1322
3032
|
// src/isPhantomLoginAvailable.ts
|
|
1323
|
-
var
|
|
3033
|
+
var import_browser_injected_sdk3 = require("@phantom/browser-injected-sdk");
|
|
1324
3034
|
async function isPhantomLoginAvailable(timeoutMs = 3e3) {
|
|
1325
3035
|
const extensionInstalled = await waitForExtension(timeoutMs);
|
|
1326
3036
|
if (!extensionInstalled) {
|
|
@@ -1346,7 +3056,7 @@ async function waitForExtension(timeoutMs) {
|
|
|
1346
3056
|
const checkInterval = 100;
|
|
1347
3057
|
const checkForExtension = () => {
|
|
1348
3058
|
try {
|
|
1349
|
-
if ((0,
|
|
3059
|
+
if ((0, import_browser_injected_sdk3.isPhantomExtensionInstalled)()) {
|
|
1350
3060
|
resolve(true);
|
|
1351
3061
|
return;
|
|
1352
3062
|
}
|
|
@@ -1369,7 +3079,7 @@ var BrowserPhantomAppProvider = class {
|
|
|
1369
3079
|
* Check if the Phantom extension is installed in the browser
|
|
1370
3080
|
*/
|
|
1371
3081
|
isAvailable() {
|
|
1372
|
-
return (0,
|
|
3082
|
+
return (0, import_browser_injected_sdk4.isPhantomExtensionInstalled)();
|
|
1373
3083
|
}
|
|
1374
3084
|
/**
|
|
1375
3085
|
* Authenticate using the Phantom browser extension
|
|
@@ -1460,18 +3170,23 @@ var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvi
|
|
|
1460
3170
|
// Full user agent for more detailed info
|
|
1461
3171
|
[import_constants2.ANALYTICS_HEADERS.APP_ID]: config.appId,
|
|
1462
3172
|
[import_constants2.ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
|
|
1463
|
-
[import_constants2.ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.
|
|
3173
|
+
[import_constants2.ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.24"
|
|
1464
3174
|
// Replaced at build time
|
|
1465
3175
|
}
|
|
1466
3176
|
};
|
|
1467
3177
|
debug.log(DebugCategory.EMBEDDED_PROVIDER, "Detected platform", { platformName });
|
|
1468
3178
|
const logger = new BrowserLogger();
|
|
1469
3179
|
super(config, platform, logger);
|
|
3180
|
+
this.addressTypes = config.addressTypes;
|
|
1470
3181
|
debug.info(DebugCategory.EMBEDDED_PROVIDER, "Browser EmbeddedProvider initialized");
|
|
1471
3182
|
}
|
|
3183
|
+
getEnabledAddressTypes() {
|
|
3184
|
+
return this.addressTypes;
|
|
3185
|
+
}
|
|
1472
3186
|
};
|
|
1473
3187
|
|
|
1474
3188
|
// src/ProviderManager.ts
|
|
3189
|
+
var import_embedded_provider_core2 = require("@phantom/embedded-provider-core");
|
|
1475
3190
|
var import_constants3 = require("@phantom/constants");
|
|
1476
3191
|
|
|
1477
3192
|
// src/utils/auth-callback.ts
|
|
@@ -1555,6 +3270,12 @@ var ProviderManager = class {
|
|
|
1555
3270
|
embeddedWalletType
|
|
1556
3271
|
};
|
|
1557
3272
|
}
|
|
3273
|
+
/**
|
|
3274
|
+
* Check if a provider is allowed by the config
|
|
3275
|
+
*/
|
|
3276
|
+
isProviderAllowed(provider) {
|
|
3277
|
+
return this.config.providers.includes(provider);
|
|
3278
|
+
}
|
|
1558
3279
|
/**
|
|
1559
3280
|
* Connect using the current provider
|
|
1560
3281
|
* Automatically switches provider based on authOptions.provider
|
|
@@ -1562,13 +3283,18 @@ var ProviderManager = class {
|
|
|
1562
3283
|
async connect(authOptions) {
|
|
1563
3284
|
debug.info(DebugCategory.PROVIDER_MANAGER, "Starting connection", {
|
|
1564
3285
|
currentProviderKey: this.currentProviderKey,
|
|
1565
|
-
authOptions: { provider: authOptions.provider
|
|
3286
|
+
authOptions: { provider: authOptions.provider }
|
|
1566
3287
|
});
|
|
3288
|
+
if (!this.isProviderAllowed(authOptions.provider)) {
|
|
3289
|
+
const error = `Provider "${authOptions.provider}" is not in the allowed providers list: ${JSON.stringify(this.config.providers)}`;
|
|
3290
|
+
debug.error(DebugCategory.PROVIDER_MANAGER, error);
|
|
3291
|
+
throw new Error(error);
|
|
3292
|
+
}
|
|
1567
3293
|
const requestedProvider = authOptions.provider;
|
|
1568
3294
|
let targetProviderType = null;
|
|
1569
3295
|
if (requestedProvider === "injected") {
|
|
1570
3296
|
targetProviderType = "injected";
|
|
1571
|
-
} else if (
|
|
3297
|
+
} else if (import_embedded_provider_core2.EMBEDDED_PROVIDER_AUTH_TYPES.includes(requestedProvider)) {
|
|
1572
3298
|
targetProviderType = "embedded";
|
|
1573
3299
|
}
|
|
1574
3300
|
if (targetProviderType) {
|
|
@@ -1592,16 +3318,14 @@ var ProviderManager = class {
|
|
|
1592
3318
|
}
|
|
1593
3319
|
debug.log(DebugCategory.PROVIDER_MANAGER, "Delegating to provider connect method");
|
|
1594
3320
|
const result = await this.currentProvider.connect(authOptions);
|
|
1595
|
-
const providerInfo = this.getCurrentProviderInfo();
|
|
1596
|
-
result.providerType = providerInfo?.type;
|
|
1597
3321
|
debug.log(DebugCategory.PROVIDER_MANAGER, "Connection successful, saving preferences", {
|
|
1598
3322
|
addressCount: result.addresses?.length || 0,
|
|
1599
|
-
|
|
3323
|
+
provider: authOptions.provider
|
|
1600
3324
|
});
|
|
1601
3325
|
this.saveProviderPreference();
|
|
1602
3326
|
debug.info(DebugCategory.PROVIDER_MANAGER, "Connect completed", {
|
|
1603
3327
|
addresses: result.addresses,
|
|
1604
|
-
|
|
3328
|
+
provider: authOptions.provider
|
|
1605
3329
|
});
|
|
1606
3330
|
return result;
|
|
1607
3331
|
}
|
|
@@ -1630,7 +3354,7 @@ var ProviderManager = class {
|
|
|
1630
3354
|
}
|
|
1631
3355
|
/**
|
|
1632
3356
|
* Attempt auto-connect with fallback strategy
|
|
1633
|
-
* Tries embedded provider first if it exists, then injected provider
|
|
3357
|
+
* Tries embedded provider first if it exists and is allowed, then injected provider if allowed
|
|
1634
3358
|
* Returns true if any provider successfully connected
|
|
1635
3359
|
*/
|
|
1636
3360
|
async autoConnect() {
|
|
@@ -1641,7 +3365,8 @@ var ProviderManager = class {
|
|
|
1641
3365
|
}
|
|
1642
3366
|
const embeddedWalletType = this.config.embeddedWalletType || "user-wallet";
|
|
1643
3367
|
const embeddedKey = this.getProviderKey("embedded", embeddedWalletType);
|
|
1644
|
-
|
|
3368
|
+
const embeddedAllowed = this.config.providers.some((p) => p !== "injected");
|
|
3369
|
+
if (embeddedAllowed && this.providers.has(embeddedKey)) {
|
|
1645
3370
|
debug.log(DebugCategory.PROVIDER_MANAGER, "Trying auto-connect with existing embedded provider");
|
|
1646
3371
|
const embeddedProvider = this.providers.get(embeddedKey);
|
|
1647
3372
|
try {
|
|
@@ -1670,8 +3395,9 @@ var ProviderManager = class {
|
|
|
1670
3395
|
}
|
|
1671
3396
|
}
|
|
1672
3397
|
}
|
|
3398
|
+
const injectedAllowed = this.config.providers.includes("injected");
|
|
1673
3399
|
const injectedKey = this.getProviderKey("injected");
|
|
1674
|
-
if (this.providers.has(injectedKey)) {
|
|
3400
|
+
if (injectedAllowed && this.providers.has(injectedKey)) {
|
|
1675
3401
|
debug.log(DebugCategory.PROVIDER_MANAGER, "Trying auto-connect with existing injected provider");
|
|
1676
3402
|
const injectedProvider = this.providers.get(injectedKey);
|
|
1677
3403
|
try {
|
|
@@ -1690,7 +3416,7 @@ var ProviderManager = class {
|
|
|
1690
3416
|
});
|
|
1691
3417
|
}
|
|
1692
3418
|
}
|
|
1693
|
-
debug.log(DebugCategory.PROVIDER_MANAGER, "Auto-connect failed for all
|
|
3419
|
+
debug.log(DebugCategory.PROVIDER_MANAGER, "Auto-connect failed for all allowed providers");
|
|
1694
3420
|
return false;
|
|
1695
3421
|
}
|
|
1696
3422
|
/**
|
|
@@ -1774,17 +3500,28 @@ var ProviderManager = class {
|
|
|
1774
3500
|
}
|
|
1775
3501
|
/**
|
|
1776
3502
|
* Set default provider based on initial config
|
|
1777
|
-
* Creates
|
|
3503
|
+
* Creates providers based on the allowed providers array
|
|
1778
3504
|
*/
|
|
1779
3505
|
setDefaultProvider() {
|
|
1780
|
-
const defaultType = this.config.providerType || "embedded";
|
|
1781
3506
|
const defaultEmbeddedType = this.config.embeddedWalletType || "user-wallet";
|
|
1782
|
-
|
|
1783
|
-
|
|
3507
|
+
const hasInjected = this.config.providers.includes("injected");
|
|
3508
|
+
const hasEmbedded = this.config.providers.some((p) => p !== "injected");
|
|
3509
|
+
if (hasInjected) {
|
|
3510
|
+
debug.log(DebugCategory.PROVIDER_MANAGER, "Creating injected provider (allowed by providers array)");
|
|
3511
|
+
this.createProvider("injected");
|
|
3512
|
+
}
|
|
3513
|
+
if (hasEmbedded) {
|
|
3514
|
+
debug.log(DebugCategory.PROVIDER_MANAGER, "Creating embedded provider (allowed by providers array)");
|
|
1784
3515
|
this.createProvider("embedded", defaultEmbeddedType);
|
|
1785
3516
|
}
|
|
1786
|
-
|
|
1787
|
-
this.
|
|
3517
|
+
let defaultType;
|
|
3518
|
+
if (hasEmbedded && this.providers.has(`embedded-${defaultEmbeddedType}`)) {
|
|
3519
|
+
defaultType = "embedded";
|
|
3520
|
+
} else if (hasInjected && this.providers.has("injected")) {
|
|
3521
|
+
defaultType = "injected";
|
|
3522
|
+
} else {
|
|
3523
|
+
throw new Error("No valid providers could be created from the providers array");
|
|
3524
|
+
}
|
|
1788
3525
|
const switchOptions = {};
|
|
1789
3526
|
if (defaultType === "embedded") {
|
|
1790
3527
|
switchOptions.embeddedWalletType = defaultEmbeddedType;
|
|
@@ -1851,46 +3588,42 @@ var ProviderManager = class {
|
|
|
1851
3588
|
}
|
|
1852
3589
|
};
|
|
1853
3590
|
|
|
1854
|
-
// src/waitForPhantomExtension.ts
|
|
1855
|
-
var import_browser_injected_sdk4 = require("@phantom/browser-injected-sdk");
|
|
1856
|
-
async function waitForPhantomExtension(timeoutMs = 3e3) {
|
|
1857
|
-
return new Promise((resolve) => {
|
|
1858
|
-
const startTime = Date.now();
|
|
1859
|
-
const checkInterval = 100;
|
|
1860
|
-
const checkForExtension = () => {
|
|
1861
|
-
try {
|
|
1862
|
-
if ((0, import_browser_injected_sdk4.isPhantomExtensionInstalled)()) {
|
|
1863
|
-
resolve(true);
|
|
1864
|
-
return;
|
|
1865
|
-
}
|
|
1866
|
-
} catch (error) {
|
|
1867
|
-
}
|
|
1868
|
-
const elapsed = Date.now() - startTime;
|
|
1869
|
-
if (elapsed >= timeoutMs) {
|
|
1870
|
-
resolve(false);
|
|
1871
|
-
return;
|
|
1872
|
-
}
|
|
1873
|
-
setTimeout(checkForExtension, checkInterval);
|
|
1874
|
-
};
|
|
1875
|
-
checkForExtension();
|
|
1876
|
-
});
|
|
1877
|
-
}
|
|
1878
|
-
|
|
1879
3591
|
// src/BrowserSDK.ts
|
|
3592
|
+
var import_embedded_provider_core3 = require("@phantom/embedded-provider-core");
|
|
1880
3593
|
var import_constants4 = require("@phantom/constants");
|
|
3594
|
+
var BROWSER_SDK_PROVIDER_TYPES = [...import_embedded_provider_core3.EMBEDDED_PROVIDER_AUTH_TYPES, "injected"];
|
|
1881
3595
|
var BrowserSDK = class {
|
|
1882
3596
|
constructor(config) {
|
|
3597
|
+
this.walletRegistry = getWalletRegistry();
|
|
3598
|
+
this.isLoading = true;
|
|
1883
3599
|
debug.info(DebugCategory.BROWSER_SDK, "Initializing BrowserSDK", {
|
|
1884
|
-
|
|
3600
|
+
providers: config.providers,
|
|
1885
3601
|
embeddedWalletType: config.embeddedWalletType,
|
|
1886
3602
|
addressTypes: config.addressTypes
|
|
1887
3603
|
});
|
|
1888
|
-
if (!
|
|
1889
|
-
debug.error(DebugCategory.BROWSER_SDK, "Invalid
|
|
1890
|
-
throw new Error(
|
|
3604
|
+
if (!Array.isArray(config.providers) || config.providers.length === 0) {
|
|
3605
|
+
debug.error(DebugCategory.BROWSER_SDK, "Invalid providers array", { providers: config.providers });
|
|
3606
|
+
throw new Error("providers must be a non-empty array of AuthProviderType");
|
|
3607
|
+
}
|
|
3608
|
+
const invalidProviders = config.providers.filter((p) => !BROWSER_SDK_PROVIDER_TYPES.includes(p));
|
|
3609
|
+
if (invalidProviders.length > 0) {
|
|
3610
|
+
debug.error(DebugCategory.BROWSER_SDK, "Invalid provider types", {
|
|
3611
|
+
invalidProviders,
|
|
3612
|
+
validProviders: BROWSER_SDK_PROVIDER_TYPES
|
|
3613
|
+
});
|
|
3614
|
+
throw new Error(
|
|
3615
|
+
`Invalid provider type(s): ${invalidProviders.join(", ")}. Valid providers are: ${BROWSER_SDK_PROVIDER_TYPES.join(", ")}`
|
|
3616
|
+
);
|
|
3617
|
+
}
|
|
3618
|
+
const hasEmbeddedProviders = config.providers.some((p) => p !== "injected");
|
|
3619
|
+
if (hasEmbeddedProviders && !config.appId) {
|
|
3620
|
+
debug.error(DebugCategory.BROWSER_SDK, "appId required for embedded providers", {
|
|
3621
|
+
providers: config.providers
|
|
3622
|
+
});
|
|
3623
|
+
throw new Error("appId is required when using embedded providers (google, apple, phantom, etc.)");
|
|
1891
3624
|
}
|
|
1892
3625
|
const embeddedWalletType = config.embeddedWalletType || import_constants4.DEFAULT_EMBEDDED_WALLET_TYPE;
|
|
1893
|
-
if (
|
|
3626
|
+
if (!["app-wallet", "user-wallet"].includes(embeddedWalletType)) {
|
|
1894
3627
|
debug.error(DebugCategory.BROWSER_SDK, "Invalid embeddedWalletType", {
|
|
1895
3628
|
embeddedWalletType: config.embeddedWalletType
|
|
1896
3629
|
});
|
|
@@ -1898,7 +3631,14 @@ var BrowserSDK = class {
|
|
|
1898
3631
|
`Invalid embeddedWalletType: ${config.embeddedWalletType}. Must be "app-wallet" or "user-wallet".`
|
|
1899
3632
|
);
|
|
1900
3633
|
}
|
|
3634
|
+
this.config = config;
|
|
1901
3635
|
this.providerManager = new ProviderManager(config);
|
|
3636
|
+
void this.discoverWallets();
|
|
3637
|
+
}
|
|
3638
|
+
discoverWallets() {
|
|
3639
|
+
return this.walletRegistry.discover(this.config.addressTypes).finally(() => {
|
|
3640
|
+
this.isLoading = false;
|
|
3641
|
+
});
|
|
1902
3642
|
}
|
|
1903
3643
|
// ===== CHAIN API =====
|
|
1904
3644
|
/**
|
|
@@ -1971,13 +3711,20 @@ var BrowserSDK = class {
|
|
|
1971
3711
|
getCurrentProviderInfo() {
|
|
1972
3712
|
return this.providerManager.getCurrentProviderInfo();
|
|
1973
3713
|
}
|
|
1974
|
-
// ===== UTILITY METHODS =====
|
|
1975
3714
|
/**
|
|
1976
|
-
*
|
|
3715
|
+
* Get enabled address types for the current provider
|
|
3716
|
+
* - For embedded provider: returns config.addressTypes
|
|
3717
|
+
* - For Phantom injected: returns config.addressTypes
|
|
3718
|
+
* - For discovered wallets: returns the wallet's addressTypes from registry
|
|
1977
3719
|
*/
|
|
1978
|
-
|
|
1979
|
-
|
|
3720
|
+
getEnabledAddressTypes() {
|
|
3721
|
+
const currentProvider = this.providerManager.getCurrentProvider();
|
|
3722
|
+
if (!currentProvider) {
|
|
3723
|
+
return [];
|
|
3724
|
+
}
|
|
3725
|
+
return currentProvider.getEnabledAddressTypes();
|
|
1980
3726
|
}
|
|
3727
|
+
// ===== UTILITY METHODS =====
|
|
1981
3728
|
/**
|
|
1982
3729
|
* Add event listener for provider events (connect, connect_start, connect_error, disconnect, error)
|
|
1983
3730
|
* Works with both embedded and injected providers
|
|
@@ -2010,40 +3757,21 @@ var BrowserSDK = class {
|
|
|
2010
3757
|
debug.log(DebugCategory.BROWSER_SDK, "Auto-connect failed for all providers");
|
|
2011
3758
|
}
|
|
2012
3759
|
}
|
|
2013
|
-
/**
|
|
2014
|
-
* Debug configuration methods
|
|
2015
|
-
* These allow dynamic debug configuration without SDK reinstantiation
|
|
2016
|
-
*/
|
|
2017
|
-
/**
|
|
2018
|
-
* Enable debug logging
|
|
2019
|
-
*/
|
|
2020
3760
|
enableDebug() {
|
|
2021
3761
|
debug.enable();
|
|
2022
3762
|
debug.info(DebugCategory.BROWSER_SDK, "Debug logging enabled");
|
|
2023
3763
|
}
|
|
2024
|
-
/**
|
|
2025
|
-
* Disable debug logging
|
|
2026
|
-
*/
|
|
2027
3764
|
disableDebug() {
|
|
2028
3765
|
debug.disable();
|
|
2029
3766
|
}
|
|
2030
|
-
/**
|
|
2031
|
-
* Set debug level
|
|
2032
|
-
*/
|
|
2033
3767
|
setDebugLevel(level) {
|
|
2034
3768
|
debug.setLevel(level);
|
|
2035
3769
|
debug.info(DebugCategory.BROWSER_SDK, "Debug level updated", { level });
|
|
2036
3770
|
}
|
|
2037
|
-
/**
|
|
2038
|
-
* Set debug callback function
|
|
2039
|
-
*/
|
|
2040
3771
|
setDebugCallback(callback) {
|
|
2041
3772
|
debug.setCallback(callback);
|
|
2042
3773
|
debug.info(DebugCategory.BROWSER_SDK, "Debug callback updated");
|
|
2043
3774
|
}
|
|
2044
|
-
/**
|
|
2045
|
-
* Configure debug settings all at once
|
|
2046
|
-
*/
|
|
2047
3775
|
configureDebug(config) {
|
|
2048
3776
|
if (config.enabled !== void 0) {
|
|
2049
3777
|
if (config.enabled) {
|
|
@@ -2149,6 +3877,22 @@ var BrowserSDK = class {
|
|
|
2149
3877
|
throw error;
|
|
2150
3878
|
}
|
|
2151
3879
|
}
|
|
3880
|
+
getDiscoveredWallets() {
|
|
3881
|
+
debug.log(DebugCategory.BROWSER_SDK, "Getting discovered wallets");
|
|
3882
|
+
try {
|
|
3883
|
+
const allWallets = this.walletRegistry.getByAddressTypes(this.config.addressTypes);
|
|
3884
|
+
debug.log(DebugCategory.BROWSER_SDK, "Retrieved discovered wallets", {
|
|
3885
|
+
count: allWallets.length,
|
|
3886
|
+
walletIds: allWallets.map((w) => w.id)
|
|
3887
|
+
});
|
|
3888
|
+
return allWallets;
|
|
3889
|
+
} catch (error) {
|
|
3890
|
+
debug.error(DebugCategory.BROWSER_SDK, "Failed to get discovered wallets", {
|
|
3891
|
+
error: error.message
|
|
3892
|
+
});
|
|
3893
|
+
return [];
|
|
3894
|
+
}
|
|
3895
|
+
}
|
|
2152
3896
|
};
|
|
2153
3897
|
|
|
2154
3898
|
// src/utils/deeplink.ts
|
|
@@ -2161,6 +3905,31 @@ function getDeeplinkToPhantom(ref) {
|
|
|
2161
3905
|
return `https://phantom.app/ul/browse/${currentUrl}${refParam}`;
|
|
2162
3906
|
}
|
|
2163
3907
|
|
|
3908
|
+
// src/waitForPhantomExtension.ts
|
|
3909
|
+
var import_browser_injected_sdk5 = require("@phantom/browser-injected-sdk");
|
|
3910
|
+
async function waitForPhantomExtension(timeoutMs = 3e3) {
|
|
3911
|
+
return new Promise((resolve) => {
|
|
3912
|
+
const startTime = Date.now();
|
|
3913
|
+
const checkInterval = 100;
|
|
3914
|
+
const checkForExtension = () => {
|
|
3915
|
+
try {
|
|
3916
|
+
if ((0, import_browser_injected_sdk5.isPhantomExtensionInstalled)()) {
|
|
3917
|
+
resolve(true);
|
|
3918
|
+
return;
|
|
3919
|
+
}
|
|
3920
|
+
} catch (error) {
|
|
3921
|
+
}
|
|
3922
|
+
const elapsed = Date.now() - startTime;
|
|
3923
|
+
if (elapsed >= timeoutMs) {
|
|
3924
|
+
resolve(false);
|
|
3925
|
+
return;
|
|
3926
|
+
}
|
|
3927
|
+
setTimeout(checkForExtension, checkInterval);
|
|
3928
|
+
};
|
|
3929
|
+
checkForExtension();
|
|
3930
|
+
});
|
|
3931
|
+
}
|
|
3932
|
+
|
|
2164
3933
|
// src/index.ts
|
|
2165
3934
|
var import_constants5 = require("@phantom/constants");
|
|
2166
|
-
var
|
|
3935
|
+
var import_client4 = require("@phantom/client");
|