@phantom/browser-sdk 0.3.9 → 1.0.0-beta.1
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 +493 -455
- package/dist/index.d.ts +78 -32
- package/dist/index.js +566 -273
- package/dist/index.mjs +566 -261
- package/package.json +11 -9
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
// src/providers/injected/index.ts
|
|
2
|
-
import { AddressType } from "@phantom/client";
|
|
2
|
+
import { AddressType as AddressType3 } from "@phantom/client";
|
|
3
3
|
import { createPhantom, createExtensionPlugin } from "@phantom/browser-injected-sdk";
|
|
4
4
|
import { createSolanaPlugin } from "@phantom/browser-injected-sdk/solana";
|
|
5
5
|
import { createEthereumPlugin } from "@phantom/browser-injected-sdk/ethereum";
|
|
6
|
+
import {
|
|
7
|
+
createAutoConfirmPlugin
|
|
8
|
+
} from "@phantom/browser-injected-sdk/auto-confirm";
|
|
6
9
|
|
|
7
10
|
// src/debug.ts
|
|
8
11
|
var DebugLevel = /* @__PURE__ */ ((DebugLevel2) => {
|
|
@@ -78,10 +81,236 @@ var DebugCategory = {
|
|
|
78
81
|
SESSION: "Session"
|
|
79
82
|
};
|
|
80
83
|
|
|
84
|
+
// src/providers/injected/chains/SolanaChain.ts
|
|
85
|
+
import { EventEmitter } from "eventemitter3";
|
|
86
|
+
import { AddressType } from "@phantom/client";
|
|
87
|
+
import { Buffer } from "buffer";
|
|
88
|
+
var InjectedSolanaChain = class {
|
|
89
|
+
constructor(phantom, callbacks) {
|
|
90
|
+
this._connected = false;
|
|
91
|
+
this._publicKey = null;
|
|
92
|
+
this.eventEmitter = new EventEmitter();
|
|
93
|
+
this.phantom = phantom;
|
|
94
|
+
this.callbacks = callbacks;
|
|
95
|
+
this.setupEventListeners();
|
|
96
|
+
this.syncInitialState();
|
|
97
|
+
}
|
|
98
|
+
// Wallet adapter compliant properties
|
|
99
|
+
get connected() {
|
|
100
|
+
return this._connected;
|
|
101
|
+
}
|
|
102
|
+
get publicKey() {
|
|
103
|
+
return this._publicKey;
|
|
104
|
+
}
|
|
105
|
+
// Connection methods - delegate to provider
|
|
106
|
+
connect(_options) {
|
|
107
|
+
if (!this.callbacks.isConnected()) {
|
|
108
|
+
return Promise.reject(new Error("Provider not connected. Call provider connect first."));
|
|
109
|
+
}
|
|
110
|
+
const addresses = this.callbacks.getAddresses();
|
|
111
|
+
const solanaAddress = addresses.find((addr) => addr.addressType === AddressType.solana);
|
|
112
|
+
if (!solanaAddress) {
|
|
113
|
+
return Promise.reject(new Error("Solana not enabled for this provider"));
|
|
114
|
+
}
|
|
115
|
+
this.updateConnectionState(true, solanaAddress.address);
|
|
116
|
+
return Promise.resolve({ publicKey: solanaAddress.address });
|
|
117
|
+
}
|
|
118
|
+
async disconnect() {
|
|
119
|
+
await this.callbacks.disconnect();
|
|
120
|
+
}
|
|
121
|
+
// Standard wallet adapter methods
|
|
122
|
+
async signMessage(message) {
|
|
123
|
+
const messageBytes = typeof message === "string" ? new TextEncoder().encode(message) : message;
|
|
124
|
+
const result = await this.phantom.solana.signMessage(messageBytes);
|
|
125
|
+
return {
|
|
126
|
+
signature: result.signature instanceof Uint8Array ? result.signature : new Uint8Array(Buffer.from(result.signature, "base64")),
|
|
127
|
+
publicKey: this._publicKey || ""
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
signTransaction(_transaction) {
|
|
131
|
+
return Promise.reject(
|
|
132
|
+
new Error("Sign-only transactions not supported by injected provider. Use signAndSendTransaction instead.")
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
async signAndSendTransaction(transaction) {
|
|
136
|
+
const result = await this.phantom.solana.signAndSendTransaction(transaction);
|
|
137
|
+
return { signature: result.signature };
|
|
138
|
+
}
|
|
139
|
+
signAllTransactions(_transactions) {
|
|
140
|
+
return Promise.reject(new Error("Sign-only transactions not supported by injected provider"));
|
|
141
|
+
}
|
|
142
|
+
switchNetwork(_network) {
|
|
143
|
+
return Promise.resolve();
|
|
144
|
+
}
|
|
145
|
+
// Legacy methods
|
|
146
|
+
getPublicKey() {
|
|
147
|
+
return Promise.resolve(this._publicKey);
|
|
148
|
+
}
|
|
149
|
+
isConnected() {
|
|
150
|
+
return this._connected && this.callbacks.isConnected();
|
|
151
|
+
}
|
|
152
|
+
setupEventListeners() {
|
|
153
|
+
this.phantom.solana.addEventListener("connect", (publicKey) => {
|
|
154
|
+
this.updateConnectionState(true, publicKey);
|
|
155
|
+
this.eventEmitter.emit("connect", publicKey);
|
|
156
|
+
});
|
|
157
|
+
this.phantom.solana.addEventListener("disconnect", () => {
|
|
158
|
+
this.updateConnectionState(false, null);
|
|
159
|
+
this.eventEmitter.emit("disconnect");
|
|
160
|
+
});
|
|
161
|
+
this.phantom.solana.addEventListener("accountChanged", (publicKey) => {
|
|
162
|
+
this._publicKey = publicKey;
|
|
163
|
+
this.eventEmitter.emit("accountChanged", publicKey);
|
|
164
|
+
});
|
|
165
|
+
this.callbacks.on("connect", (data) => {
|
|
166
|
+
const solanaAddress = data.addresses?.find((addr) => addr.addressType === AddressType.solana);
|
|
167
|
+
if (solanaAddress) {
|
|
168
|
+
this.updateConnectionState(true, solanaAddress.address);
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
this.callbacks.on("disconnect", () => {
|
|
172
|
+
this.updateConnectionState(false, null);
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
syncInitialState() {
|
|
176
|
+
if (this.callbacks.isConnected()) {
|
|
177
|
+
const solanaAddress = this.callbacks.getAddresses().find((addr) => addr.addressType === AddressType.solana);
|
|
178
|
+
if (solanaAddress) {
|
|
179
|
+
this.updateConnectionState(true, solanaAddress.address);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
updateConnectionState(connected, publicKey) {
|
|
184
|
+
this._connected = connected;
|
|
185
|
+
this._publicKey = publicKey;
|
|
186
|
+
}
|
|
187
|
+
// Event methods for interface compliance
|
|
188
|
+
on(event, listener) {
|
|
189
|
+
this.eventEmitter.on(event, listener);
|
|
190
|
+
}
|
|
191
|
+
off(event, listener) {
|
|
192
|
+
this.eventEmitter.off(event, listener);
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
// src/providers/injected/chains/EthereumChain.ts
|
|
197
|
+
import { EventEmitter as EventEmitter2 } from "eventemitter3";
|
|
198
|
+
import { AddressType as AddressType2 } from "@phantom/client";
|
|
199
|
+
var InjectedEthereumChain = class {
|
|
200
|
+
constructor(phantom, callbacks) {
|
|
201
|
+
this._connected = false;
|
|
202
|
+
this._chainId = "0x1";
|
|
203
|
+
this._accounts = [];
|
|
204
|
+
this.eventEmitter = new EventEmitter2();
|
|
205
|
+
this.phantom = phantom;
|
|
206
|
+
this.callbacks = callbacks;
|
|
207
|
+
this.setupEventListeners();
|
|
208
|
+
this.syncInitialState();
|
|
209
|
+
}
|
|
210
|
+
// EIP-1193 compliant properties
|
|
211
|
+
get connected() {
|
|
212
|
+
return this._connected;
|
|
213
|
+
}
|
|
214
|
+
get chainId() {
|
|
215
|
+
return this._chainId;
|
|
216
|
+
}
|
|
217
|
+
get accounts() {
|
|
218
|
+
return this._accounts;
|
|
219
|
+
}
|
|
220
|
+
// EIP-1193 core method - unchanged, already compliant!
|
|
221
|
+
async request(args) {
|
|
222
|
+
const provider = await this.phantom.ethereum.getProvider();
|
|
223
|
+
return await provider.request(args);
|
|
224
|
+
}
|
|
225
|
+
// Connection methods - delegate to provider
|
|
226
|
+
connect() {
|
|
227
|
+
if (!this.callbacks.isConnected()) {
|
|
228
|
+
return Promise.reject(new Error("Provider not connected. Call provider connect first."));
|
|
229
|
+
}
|
|
230
|
+
const addresses = this.callbacks.getAddresses();
|
|
231
|
+
const ethAddresses = addresses.filter((addr) => addr.addressType === AddressType2.ethereum).map((addr) => addr.address);
|
|
232
|
+
this.updateConnectionState(true, ethAddresses);
|
|
233
|
+
return Promise.resolve(ethAddresses);
|
|
234
|
+
}
|
|
235
|
+
async disconnect() {
|
|
236
|
+
await this.callbacks.disconnect();
|
|
237
|
+
}
|
|
238
|
+
// Standard compliant methods (return raw values, not wrapped objects)
|
|
239
|
+
async signPersonalMessage(message, address) {
|
|
240
|
+
return await this.phantom.ethereum.signPersonalMessage(message, address);
|
|
241
|
+
}
|
|
242
|
+
async signTypedData(typedData, address) {
|
|
243
|
+
return await this.phantom.ethereum.signTypedData(typedData, address);
|
|
244
|
+
}
|
|
245
|
+
async sendTransaction(transaction) {
|
|
246
|
+
return await this.phantom.ethereum.sendTransaction(transaction);
|
|
247
|
+
}
|
|
248
|
+
async switchChain(chainId) {
|
|
249
|
+
await this.phantom.ethereum.switchChain(`0x${chainId.toString(16)}`);
|
|
250
|
+
this._chainId = `0x${chainId.toString(16)}`;
|
|
251
|
+
this.eventEmitter.emit("chainChanged", this._chainId);
|
|
252
|
+
}
|
|
253
|
+
async getChainId() {
|
|
254
|
+
const chainId = await this.phantom.ethereum.getChainId();
|
|
255
|
+
return parseInt(chainId, 16);
|
|
256
|
+
}
|
|
257
|
+
async getAccounts() {
|
|
258
|
+
return await this.phantom.ethereum.getAccounts();
|
|
259
|
+
}
|
|
260
|
+
isConnected() {
|
|
261
|
+
return this._connected && this.callbacks.isConnected();
|
|
262
|
+
}
|
|
263
|
+
setupEventListeners() {
|
|
264
|
+
this.phantom.ethereum.addEventListener("connect", (accounts) => {
|
|
265
|
+
this.updateConnectionState(true, accounts);
|
|
266
|
+
this.eventEmitter.emit("connect", { chainId: this._chainId });
|
|
267
|
+
this.eventEmitter.emit("accountsChanged", accounts);
|
|
268
|
+
});
|
|
269
|
+
this.phantom.ethereum.addEventListener("disconnect", () => {
|
|
270
|
+
this.updateConnectionState(false, []);
|
|
271
|
+
this.eventEmitter.emit("disconnect", { code: 4900, message: "Provider disconnected" });
|
|
272
|
+
this.eventEmitter.emit("accountsChanged", []);
|
|
273
|
+
});
|
|
274
|
+
this.phantom.ethereum.addEventListener("accountsChanged", (accounts) => {
|
|
275
|
+
this._accounts = accounts;
|
|
276
|
+
this.eventEmitter.emit("accountsChanged", accounts);
|
|
277
|
+
});
|
|
278
|
+
this.phantom.ethereum.addEventListener("chainChanged", (chainId) => {
|
|
279
|
+
this._chainId = chainId;
|
|
280
|
+
this.eventEmitter.emit("chainChanged", chainId);
|
|
281
|
+
});
|
|
282
|
+
this.callbacks.on("connect", (data) => {
|
|
283
|
+
const ethAddresses = data.addresses?.filter((addr) => addr.addressType === AddressType2.ethereum)?.map((addr) => addr.address) || [];
|
|
284
|
+
if (ethAddresses.length > 0) {
|
|
285
|
+
this.updateConnectionState(true, ethAddresses);
|
|
286
|
+
}
|
|
287
|
+
});
|
|
288
|
+
this.callbacks.on("disconnect", () => {
|
|
289
|
+
this.updateConnectionState(false, []);
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
syncInitialState() {
|
|
293
|
+
if (this.callbacks.isConnected()) {
|
|
294
|
+
const ethAddresses = this.callbacks.getAddresses().filter((addr) => addr.addressType === AddressType2.ethereum).map((addr) => addr.address);
|
|
295
|
+
if (ethAddresses.length > 0) {
|
|
296
|
+
this.updateConnectionState(true, ethAddresses);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
updateConnectionState(connected, accounts) {
|
|
301
|
+
this._connected = connected;
|
|
302
|
+
this._accounts = accounts;
|
|
303
|
+
}
|
|
304
|
+
// Event methods for interface compliance
|
|
305
|
+
on(event, listener) {
|
|
306
|
+
this.eventEmitter.on(event, listener);
|
|
307
|
+
}
|
|
308
|
+
off(event, listener) {
|
|
309
|
+
this.eventEmitter.off(event, listener);
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
|
|
81
313
|
// src/providers/injected/index.ts
|
|
82
|
-
import { base64urlEncode } from "@phantom/base64url";
|
|
83
|
-
import { getExplorerUrl } from "@phantom/constants";
|
|
84
|
-
import bs58 from "bs58";
|
|
85
314
|
var InjectedProvider = class {
|
|
86
315
|
constructor(config) {
|
|
87
316
|
this.connected = false;
|
|
@@ -94,20 +323,53 @@ var InjectedProvider = class {
|
|
|
94
323
|
this.addressTypes = config.addressTypes;
|
|
95
324
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Address types configured", { addressTypes: this.addressTypes });
|
|
96
325
|
const plugins = [createExtensionPlugin()];
|
|
97
|
-
if (this.addressTypes.includes(
|
|
326
|
+
if (this.addressTypes.includes(AddressType3.solana)) {
|
|
98
327
|
plugins.push(createSolanaPlugin());
|
|
99
328
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana plugin added");
|
|
100
329
|
}
|
|
101
|
-
if (this.addressTypes.includes(
|
|
330
|
+
if (this.addressTypes.includes(AddressType3.ethereum)) {
|
|
102
331
|
plugins.push(createEthereumPlugin());
|
|
103
332
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum plugin added");
|
|
104
333
|
}
|
|
334
|
+
plugins.push(createAutoConfirmPlugin());
|
|
335
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "AutoConfirm plugin added");
|
|
105
336
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Creating Phantom instance with plugins", {
|
|
106
337
|
pluginCount: plugins.length
|
|
107
338
|
});
|
|
108
339
|
this.phantom = createPhantom({ plugins });
|
|
340
|
+
const callbacks = this.createCallbacks();
|
|
341
|
+
if (this.addressTypes.includes(AddressType3.solana)) {
|
|
342
|
+
this._solanaChain = new InjectedSolanaChain(this.phantom, callbacks);
|
|
343
|
+
}
|
|
344
|
+
if (this.addressTypes.includes(AddressType3.ethereum)) {
|
|
345
|
+
this._ethereumChain = new InjectedEthereumChain(this.phantom, callbacks);
|
|
346
|
+
}
|
|
109
347
|
debug.info(DebugCategory.INJECTED_PROVIDER, "InjectedProvider initialized");
|
|
110
348
|
}
|
|
349
|
+
/**
|
|
350
|
+
* Access to Solana chain operations
|
|
351
|
+
*/
|
|
352
|
+
get solana() {
|
|
353
|
+
if (!this.addressTypes.includes(AddressType3.solana)) {
|
|
354
|
+
throw new Error("Solana not enabled for this provider");
|
|
355
|
+
}
|
|
356
|
+
if (!this._solanaChain) {
|
|
357
|
+
throw new Error("Solana chain not initialized");
|
|
358
|
+
}
|
|
359
|
+
return this._solanaChain;
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Access to Ethereum chain operations
|
|
363
|
+
*/
|
|
364
|
+
get ethereum() {
|
|
365
|
+
if (!this.addressTypes.includes(AddressType3.ethereum)) {
|
|
366
|
+
throw new Error("Ethereum not enabled for this provider");
|
|
367
|
+
}
|
|
368
|
+
if (!this._ethereumChain) {
|
|
369
|
+
throw new Error("Ethereum chain not initialized");
|
|
370
|
+
}
|
|
371
|
+
return this._ethereumChain;
|
|
372
|
+
}
|
|
111
373
|
async connect(authOptions) {
|
|
112
374
|
debug.info(DebugCategory.INJECTED_PROVIDER, "Starting injected provider connect", {
|
|
113
375
|
addressTypes: this.addressTypes,
|
|
@@ -119,7 +381,7 @@ var InjectedProvider = class {
|
|
|
119
381
|
providerType: "injected"
|
|
120
382
|
});
|
|
121
383
|
try {
|
|
122
|
-
if (!this.phantom.extension
|
|
384
|
+
if (!this.phantom.extension?.isInstalled?.()) {
|
|
123
385
|
debug.error(DebugCategory.INJECTED_PROVIDER, "Phantom wallet extension not found");
|
|
124
386
|
const error = new Error("Phantom wallet not found");
|
|
125
387
|
this.emit("connect_error", {
|
|
@@ -130,13 +392,13 @@ var InjectedProvider = class {
|
|
|
130
392
|
}
|
|
131
393
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Phantom extension detected");
|
|
132
394
|
const connectedAddresses = [];
|
|
133
|
-
if (this.addressTypes.includes(
|
|
395
|
+
if (this.addressTypes.includes(AddressType3.solana)) {
|
|
134
396
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting Solana connection");
|
|
135
397
|
try {
|
|
136
398
|
const publicKey = await this.phantom.solana.connect();
|
|
137
399
|
if (publicKey) {
|
|
138
400
|
connectedAddresses.push({
|
|
139
|
-
addressType:
|
|
401
|
+
addressType: AddressType3.solana,
|
|
140
402
|
address: publicKey
|
|
141
403
|
});
|
|
142
404
|
debug.info(DebugCategory.INJECTED_PROVIDER, "Solana connected successfully", { address: publicKey });
|
|
@@ -145,16 +407,17 @@ var InjectedProvider = class {
|
|
|
145
407
|
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Solana", { error: err });
|
|
146
408
|
}
|
|
147
409
|
}
|
|
148
|
-
if (this.addressTypes.includes(
|
|
410
|
+
if (this.addressTypes.includes(AddressType3.ethereum)) {
|
|
149
411
|
try {
|
|
150
412
|
const accounts = await this.phantom.ethereum.connect();
|
|
151
413
|
if (accounts && accounts.length > 0) {
|
|
152
414
|
connectedAddresses.push(
|
|
153
415
|
...accounts.map((address) => ({
|
|
154
|
-
addressType:
|
|
416
|
+
addressType: AddressType3.ethereum,
|
|
155
417
|
address
|
|
156
418
|
}))
|
|
157
419
|
);
|
|
420
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "Ethereum connected successfully", { addresses: accounts });
|
|
158
421
|
}
|
|
159
422
|
} catch (err) {
|
|
160
423
|
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Ethereum", { error: err });
|
|
@@ -192,7 +455,7 @@ var InjectedProvider = class {
|
|
|
192
455
|
}
|
|
193
456
|
async disconnect() {
|
|
194
457
|
debug.info(DebugCategory.INJECTED_PROVIDER, "Starting injected provider disconnect");
|
|
195
|
-
if (this.addressTypes.includes(
|
|
458
|
+
if (this.addressTypes.includes(AddressType3.solana)) {
|
|
196
459
|
try {
|
|
197
460
|
await this.phantom.solana.disconnect();
|
|
198
461
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana disconnected successfully");
|
|
@@ -200,13 +463,8 @@ var InjectedProvider = class {
|
|
|
200
463
|
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to disconnect Solana", { error: err });
|
|
201
464
|
}
|
|
202
465
|
}
|
|
203
|
-
if (this.addressTypes.includes(
|
|
204
|
-
|
|
205
|
-
await this.phantom.ethereum.disconnect();
|
|
206
|
-
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum disconnected successfully");
|
|
207
|
-
} catch (err) {
|
|
208
|
-
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to disconnect Ethereum", { error: err });
|
|
209
|
-
}
|
|
466
|
+
if (this.addressTypes.includes(AddressType3.ethereum)) {
|
|
467
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum disconnected (no-op)");
|
|
210
468
|
}
|
|
211
469
|
this.browserInjectedCleanupFunctions.forEach((cleanup) => cleanup());
|
|
212
470
|
this.browserInjectedCleanupFunctions = [];
|
|
@@ -217,77 +475,29 @@ var InjectedProvider = class {
|
|
|
217
475
|
});
|
|
218
476
|
debug.info(DebugCategory.INJECTED_PROVIDER, "Injected provider disconnected successfully");
|
|
219
477
|
}
|
|
220
|
-
async signMessage(params) {
|
|
221
|
-
if (!this.connected) {
|
|
222
|
-
throw new Error("Wallet not connected");
|
|
223
|
-
}
|
|
224
|
-
const networkPrefix = params.networkId.split(":")[0].toLowerCase();
|
|
225
|
-
let signatureResult;
|
|
226
|
-
if (networkPrefix === "solana") {
|
|
227
|
-
const { signature } = await this.phantom.solana.signMessage(new TextEncoder().encode(params.message));
|
|
228
|
-
signatureResult = bs58.encode(signature);
|
|
229
|
-
} else if (networkPrefix === "ethereum" || networkPrefix === "polygon" || networkPrefix === "eip155") {
|
|
230
|
-
const address = this.addresses.find((addr) => addr.addressType === AddressType.ethereum)?.address;
|
|
231
|
-
if (!address) {
|
|
232
|
-
throw new Error("No address available");
|
|
233
|
-
}
|
|
234
|
-
const signature = await this.phantom.ethereum.signPersonalMessage(params.message, address);
|
|
235
|
-
signatureResult = signature;
|
|
236
|
-
} else {
|
|
237
|
-
throw new Error(`Network ${params.networkId} is not supported for injected wallets`);
|
|
238
|
-
}
|
|
239
|
-
return {
|
|
240
|
-
signature: signatureResult,
|
|
241
|
-
rawSignature: base64urlEncode(signatureResult)
|
|
242
|
-
};
|
|
243
|
-
}
|
|
244
|
-
async signAndSendTransaction(params) {
|
|
245
|
-
if (!this.connected) {
|
|
246
|
-
throw new Error("Wallet not connected");
|
|
247
|
-
}
|
|
248
|
-
const networkPrefix = params.networkId.split(":")[0].toLowerCase();
|
|
249
|
-
if (networkPrefix === "solana") {
|
|
250
|
-
const transaction = params.transaction;
|
|
251
|
-
const result = await this.phantom.solana.signAndSendTransaction(transaction);
|
|
252
|
-
return {
|
|
253
|
-
hash: result.signature,
|
|
254
|
-
rawTransaction: base64urlEncode(result.signature),
|
|
255
|
-
blockExplorer: getExplorerUrl(params.networkId, "transaction", result.signature)
|
|
256
|
-
};
|
|
257
|
-
} else if (networkPrefix === "ethereum" || networkPrefix === "polygon" || networkPrefix === "eip155") {
|
|
258
|
-
const toHex = (value) => {
|
|
259
|
-
if (!value)
|
|
260
|
-
return void 0;
|
|
261
|
-
if (typeof value === "string" && value.startsWith("0x"))
|
|
262
|
-
return value;
|
|
263
|
-
if (typeof value === "string")
|
|
264
|
-
return value;
|
|
265
|
-
return "0x" + value.toString(16);
|
|
266
|
-
};
|
|
267
|
-
const txRequest = {
|
|
268
|
-
to: params.transaction.to,
|
|
269
|
-
value: params.transaction.value ? toHex(params.transaction.value) : "0x0",
|
|
270
|
-
gas: toHex(params.transaction.gas),
|
|
271
|
-
gasPrice: toHex(params.transaction.gasPrice),
|
|
272
|
-
maxFeePerGas: toHex(params.transaction.maxFeePerGas),
|
|
273
|
-
maxPriorityFeePerGas: toHex(params.transaction.maxPriorityFeePerGas),
|
|
274
|
-
data: params.transaction.data || "0x"
|
|
275
|
-
};
|
|
276
|
-
const txHash = await this.phantom.ethereum.sendTransaction(txRequest);
|
|
277
|
-
return {
|
|
278
|
-
hash: txHash,
|
|
279
|
-
rawTransaction: base64urlEncode(txHash),
|
|
280
|
-
blockExplorer: getExplorerUrl(params.networkId, "transaction", txHash)
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
throw new Error(`Network ${params.networkId} is not supported for injected wallets`);
|
|
284
|
-
}
|
|
285
478
|
getAddresses() {
|
|
286
479
|
return this.addresses;
|
|
287
480
|
}
|
|
288
481
|
isConnected() {
|
|
289
482
|
return this.connected;
|
|
290
483
|
}
|
|
484
|
+
// AutoConfirm methods - only available for injected providers
|
|
485
|
+
async enableAutoConfirm(params) {
|
|
486
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Enabling autoConfirm", { params });
|
|
487
|
+
return await this.phantom.autoConfirm.autoConfirmEnable(params);
|
|
488
|
+
}
|
|
489
|
+
async disableAutoConfirm() {
|
|
490
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Disabling autoConfirm");
|
|
491
|
+
await this.phantom.autoConfirm.autoConfirmDisable();
|
|
492
|
+
}
|
|
493
|
+
async getAutoConfirmStatus() {
|
|
494
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Getting autoConfirm status");
|
|
495
|
+
return await this.phantom.autoConfirm.autoConfirmStatus();
|
|
496
|
+
}
|
|
497
|
+
async getSupportedAutoConfirmChains() {
|
|
498
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Getting supported autoConfirm chains");
|
|
499
|
+
return await this.phantom.autoConfirm.autoConfirmSupportedChains();
|
|
500
|
+
}
|
|
291
501
|
// Event management methods - implementing unified event interface
|
|
292
502
|
on(event, callback) {
|
|
293
503
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Adding event listener", { event });
|
|
@@ -328,19 +538,19 @@ var InjectedProvider = class {
|
|
|
328
538
|
}
|
|
329
539
|
setupBrowserInjectedEvents() {
|
|
330
540
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up browser-injected-sdk event listeners");
|
|
331
|
-
if (this.addressTypes.includes(
|
|
541
|
+
if (this.addressTypes.includes(AddressType3.solana)) {
|
|
332
542
|
this.setupSolanaEvents();
|
|
333
543
|
}
|
|
334
|
-
if (this.addressTypes.includes(
|
|
544
|
+
if (this.addressTypes.includes(AddressType3.ethereum)) {
|
|
335
545
|
this.setupEthereumEvents();
|
|
336
546
|
}
|
|
337
547
|
}
|
|
338
548
|
setupSolanaEvents() {
|
|
339
549
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up Solana event listeners");
|
|
340
|
-
const
|
|
550
|
+
const handleSolanaConnect = (publicKey) => {
|
|
341
551
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana connect event received", { publicKey });
|
|
342
|
-
const solanaAddress = { addressType:
|
|
343
|
-
if (!this.addresses.find((addr) => addr.addressType ===
|
|
552
|
+
const solanaAddress = { addressType: AddressType3.solana, address: publicKey };
|
|
553
|
+
if (!this.addresses.find((addr) => addr.addressType === AddressType3.solana)) {
|
|
344
554
|
this.addresses.push(solanaAddress);
|
|
345
555
|
}
|
|
346
556
|
this.connected = true;
|
|
@@ -348,78 +558,109 @@ var InjectedProvider = class {
|
|
|
348
558
|
addresses: this.addresses,
|
|
349
559
|
source: "injected-extension"
|
|
350
560
|
});
|
|
351
|
-
}
|
|
352
|
-
const
|
|
561
|
+
};
|
|
562
|
+
const handleSolanaDisconnect = () => {
|
|
353
563
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana disconnect event received");
|
|
354
|
-
this.addresses = this.addresses.filter((addr) => addr.addressType !==
|
|
564
|
+
this.addresses = this.addresses.filter((addr) => addr.addressType !== AddressType3.solana);
|
|
355
565
|
this.connected = this.addresses.length > 0;
|
|
356
566
|
this.emit("disconnect", {
|
|
357
567
|
source: "injected-extension"
|
|
358
568
|
});
|
|
359
|
-
}
|
|
360
|
-
const
|
|
569
|
+
};
|
|
570
|
+
const handleSolanaAccountChanged = (publicKey) => {
|
|
361
571
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana account changed event received", { publicKey });
|
|
362
|
-
const solanaIndex = this.addresses.findIndex((addr) => addr.addressType ===
|
|
572
|
+
const solanaIndex = this.addresses.findIndex((addr) => addr.addressType === AddressType3.solana);
|
|
363
573
|
if (solanaIndex >= 0) {
|
|
364
|
-
this.addresses[solanaIndex] = { addressType:
|
|
574
|
+
this.addresses[solanaIndex] = { addressType: AddressType3.solana, address: publicKey };
|
|
365
575
|
} else {
|
|
366
|
-
this.addresses.push({ addressType:
|
|
576
|
+
this.addresses.push({ addressType: AddressType3.solana, address: publicKey });
|
|
367
577
|
}
|
|
368
578
|
this.emit("connect", {
|
|
369
579
|
addresses: this.addresses,
|
|
370
580
|
source: "injected-extension-account-change"
|
|
371
581
|
});
|
|
372
|
-
}
|
|
373
|
-
this.
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
582
|
+
};
|
|
583
|
+
const cleanupConnect = this.phantom.solana.addEventListener("connect", handleSolanaConnect);
|
|
584
|
+
const cleanupDisconnect = this.phantom.solana.addEventListener("disconnect", handleSolanaDisconnect);
|
|
585
|
+
const cleanupAccountChanged = this.phantom.solana.addEventListener(
|
|
586
|
+
"accountChanged",
|
|
587
|
+
handleSolanaAccountChanged
|
|
377
588
|
);
|
|
589
|
+
this.browserInjectedCleanupFunctions.push(cleanupConnect, cleanupDisconnect, cleanupAccountChanged);
|
|
378
590
|
}
|
|
379
591
|
setupEthereumEvents() {
|
|
380
592
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up Ethereum event listeners");
|
|
381
|
-
const
|
|
593
|
+
const handleEthereumConnect = (accounts) => {
|
|
382
594
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum connect event received", { accounts });
|
|
383
|
-
this.addresses = this.addresses.filter((addr) => addr.addressType !==
|
|
595
|
+
this.addresses = this.addresses.filter((addr) => addr.addressType !== AddressType3.ethereum);
|
|
384
596
|
if (accounts && accounts.length > 0) {
|
|
385
|
-
this.addresses.push(
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
597
|
+
this.addresses.push(
|
|
598
|
+
...accounts.map((address) => ({
|
|
599
|
+
addressType: AddressType3.ethereum,
|
|
600
|
+
address
|
|
601
|
+
}))
|
|
602
|
+
);
|
|
389
603
|
}
|
|
390
604
|
this.connected = this.addresses.length > 0;
|
|
391
605
|
this.emit("connect", {
|
|
392
606
|
addresses: this.addresses,
|
|
393
607
|
source: "injected-extension"
|
|
394
608
|
});
|
|
395
|
-
}
|
|
396
|
-
const
|
|
609
|
+
};
|
|
610
|
+
const handleEthereumDisconnect = () => {
|
|
397
611
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum disconnect event received");
|
|
398
|
-
this.addresses = this.addresses.filter((addr) => addr.addressType !==
|
|
612
|
+
this.addresses = this.addresses.filter((addr) => addr.addressType !== AddressType3.ethereum);
|
|
399
613
|
this.connected = this.addresses.length > 0;
|
|
400
614
|
this.emit("disconnect", {
|
|
401
615
|
source: "injected-extension"
|
|
402
616
|
});
|
|
403
|
-
}
|
|
404
|
-
const
|
|
405
|
-
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum
|
|
406
|
-
this.addresses = this.addresses.filter((addr) => addr.addressType !==
|
|
617
|
+
};
|
|
618
|
+
const handleEthereumAccountsChanged = (accounts) => {
|
|
619
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum accounts changed event received", { accounts });
|
|
620
|
+
this.addresses = this.addresses.filter((addr) => addr.addressType !== AddressType3.ethereum);
|
|
407
621
|
if (accounts && accounts.length > 0) {
|
|
408
|
-
this.addresses.push(
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
622
|
+
this.addresses.push(
|
|
623
|
+
...accounts.map((address) => ({
|
|
624
|
+
addressType: AddressType3.ethereum,
|
|
625
|
+
address
|
|
626
|
+
}))
|
|
627
|
+
);
|
|
412
628
|
}
|
|
413
629
|
this.emit("connect", {
|
|
414
630
|
addresses: this.addresses,
|
|
415
631
|
source: "injected-extension-account-change"
|
|
416
632
|
});
|
|
417
|
-
}
|
|
418
|
-
this.
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
633
|
+
};
|
|
634
|
+
const cleanupConnect = this.phantom.ethereum.addEventListener("connect", handleEthereumConnect);
|
|
635
|
+
const cleanupDisconnect = this.phantom.ethereum.addEventListener("disconnect", handleEthereumDisconnect);
|
|
636
|
+
const cleanupAccountsChanged = this.phantom.ethereum.addEventListener(
|
|
637
|
+
"accountsChanged",
|
|
638
|
+
handleEthereumAccountsChanged
|
|
422
639
|
);
|
|
640
|
+
this.browserInjectedCleanupFunctions.push(cleanupConnect, cleanupDisconnect, cleanupAccountsChanged);
|
|
641
|
+
}
|
|
642
|
+
createCallbacks() {
|
|
643
|
+
return {
|
|
644
|
+
connect: async () => {
|
|
645
|
+
const result = await this.connect();
|
|
646
|
+
return result.addresses;
|
|
647
|
+
},
|
|
648
|
+
disconnect: async () => {
|
|
649
|
+
await this.disconnect();
|
|
650
|
+
},
|
|
651
|
+
isConnected: () => {
|
|
652
|
+
return this.isConnected();
|
|
653
|
+
},
|
|
654
|
+
getAddresses: () => {
|
|
655
|
+
return this.getAddresses();
|
|
656
|
+
},
|
|
657
|
+
on: (event, callback) => {
|
|
658
|
+
this.on(event, callback);
|
|
659
|
+
},
|
|
660
|
+
off: (event, callback) => {
|
|
661
|
+
this.off(event, callback);
|
|
662
|
+
}
|
|
663
|
+
};
|
|
423
664
|
}
|
|
424
665
|
};
|
|
425
666
|
|
|
@@ -535,6 +776,7 @@ var BrowserAuthProvider = class {
|
|
|
535
776
|
debug.info(DebugCategory.PHANTOM_CONNECT_AUTH, "Starting Phantom Connect authentication", {
|
|
536
777
|
organizationId: phantomOptions.organizationId,
|
|
537
778
|
parentOrganizationId: phantomOptions.parentOrganizationId,
|
|
779
|
+
appId: phantomOptions.appId,
|
|
538
780
|
provider: phantomOptions.provider,
|
|
539
781
|
authUrl: phantomOptions.authUrl,
|
|
540
782
|
hasCustomData: !!phantomOptions.customAuthData
|
|
@@ -544,13 +786,10 @@ var BrowserAuthProvider = class {
|
|
|
544
786
|
const params = new URLSearchParams({
|
|
545
787
|
organization_id: phantomOptions.organizationId,
|
|
546
788
|
parent_organization_id: phantomOptions.parentOrganizationId,
|
|
789
|
+
app_id: phantomOptions.appId,
|
|
547
790
|
redirect_uri: phantomOptions.redirectUrl || (typeof window !== "undefined" ? window.location.href : ""),
|
|
548
791
|
session_id: phantomOptions.sessionId,
|
|
549
|
-
clear_previous_session: true.toString()
|
|
550
|
-
app_name: phantomOptions.appName || "",
|
|
551
|
-
// Optional app name
|
|
552
|
-
app_logo: phantomOptions.appLogo || ""
|
|
553
|
-
// Optional app logo URL
|
|
792
|
+
clear_previous_session: true.toString()
|
|
554
793
|
});
|
|
555
794
|
if (phantomOptions.provider) {
|
|
556
795
|
debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Provider specified, will skip selection", {
|
|
@@ -568,6 +807,7 @@ var BrowserAuthProvider = class {
|
|
|
568
807
|
const authContext = {
|
|
569
808
|
organizationId: phantomOptions.organizationId,
|
|
570
809
|
parentOrganizationId: phantomOptions.parentOrganizationId,
|
|
810
|
+
appId: phantomOptions.appId,
|
|
571
811
|
provider: phantomOptions.provider,
|
|
572
812
|
sessionId: phantomOptions.sessionId
|
|
573
813
|
};
|
|
@@ -882,24 +1122,6 @@ var ProviderManager = class {
|
|
|
882
1122
|
await this.currentProvider.disconnect();
|
|
883
1123
|
this.walletId = null;
|
|
884
1124
|
}
|
|
885
|
-
/**
|
|
886
|
-
* Sign a message using current provider
|
|
887
|
-
*/
|
|
888
|
-
async signMessage(params) {
|
|
889
|
-
if (!this.currentProvider) {
|
|
890
|
-
throw new Error("No provider connected");
|
|
891
|
-
}
|
|
892
|
-
return this.currentProvider.signMessage(params);
|
|
893
|
-
}
|
|
894
|
-
/**
|
|
895
|
-
* Sign and send transaction using current provider
|
|
896
|
-
*/
|
|
897
|
-
async signAndSendTransaction(params) {
|
|
898
|
-
if (!this.currentProvider) {
|
|
899
|
-
throw new Error("No provider connected");
|
|
900
|
-
}
|
|
901
|
-
return this.currentProvider.signAndSendTransaction(params);
|
|
902
|
-
}
|
|
903
1125
|
/**
|
|
904
1126
|
* Get addresses from current provider
|
|
905
1127
|
*/
|
|
@@ -983,7 +1205,13 @@ var ProviderManager = class {
|
|
|
983
1205
|
return;
|
|
984
1206
|
}
|
|
985
1207
|
debug.log(DebugCategory.PROVIDER_MANAGER, "Setting up event forwarding from current provider");
|
|
986
|
-
const eventsToForward = [
|
|
1208
|
+
const eventsToForward = [
|
|
1209
|
+
"connect_start",
|
|
1210
|
+
"connect",
|
|
1211
|
+
"connect_error",
|
|
1212
|
+
"disconnect",
|
|
1213
|
+
"error"
|
|
1214
|
+
];
|
|
987
1215
|
for (const event of eventsToForward) {
|
|
988
1216
|
const forwardingCallback = (data) => {
|
|
989
1217
|
debug.log(DebugCategory.PROVIDER_MANAGER, "Forwarding event from provider", { event, data });
|
|
@@ -1017,19 +1245,17 @@ var ProviderManager = class {
|
|
|
1017
1245
|
addressTypes: this.config.addressTypes
|
|
1018
1246
|
});
|
|
1019
1247
|
} else {
|
|
1020
|
-
if (!this.config.apiBaseUrl || !this.config.
|
|
1021
|
-
throw new Error("apiBaseUrl and
|
|
1248
|
+
if (!this.config.apiBaseUrl || !this.config.appId) {
|
|
1249
|
+
throw new Error("apiBaseUrl and appId are required for embedded provider");
|
|
1022
1250
|
}
|
|
1023
1251
|
provider = new EmbeddedProvider({
|
|
1024
1252
|
apiBaseUrl: this.config.apiBaseUrl,
|
|
1025
|
-
organizationId: this.config.
|
|
1253
|
+
organizationId: this.config.appId,
|
|
1254
|
+
appId: this.config.appId,
|
|
1026
1255
|
authOptions: this.config.authOptions,
|
|
1027
1256
|
embeddedWalletType: embeddedWalletType || "app-wallet",
|
|
1028
1257
|
addressTypes: this.config.addressTypes,
|
|
1029
|
-
solanaProvider: this.config.solanaProvider || "web3js"
|
|
1030
|
-
appLogo: this.config.appLogo,
|
|
1031
|
-
// Optional app logo URL
|
|
1032
|
-
appName: this.config.appName
|
|
1258
|
+
solanaProvider: this.config.solanaProvider || "web3js"
|
|
1033
1259
|
});
|
|
1034
1260
|
}
|
|
1035
1261
|
this.providers.set(key, provider);
|
|
@@ -1076,8 +1302,32 @@ var ProviderManager = class {
|
|
|
1076
1302
|
}*/
|
|
1077
1303
|
};
|
|
1078
1304
|
|
|
1079
|
-
// src/
|
|
1305
|
+
// src/waitForPhantomExtension.ts
|
|
1080
1306
|
import { isPhantomExtensionInstalled } from "@phantom/browser-injected-sdk";
|
|
1307
|
+
async function waitForPhantomExtension(timeoutMs = 3e3) {
|
|
1308
|
+
return new Promise((resolve) => {
|
|
1309
|
+
const startTime = Date.now();
|
|
1310
|
+
const checkInterval = 100;
|
|
1311
|
+
const checkForExtension = () => {
|
|
1312
|
+
try {
|
|
1313
|
+
if (isPhantomExtensionInstalled()) {
|
|
1314
|
+
resolve(true);
|
|
1315
|
+
return;
|
|
1316
|
+
}
|
|
1317
|
+
} catch (error) {
|
|
1318
|
+
}
|
|
1319
|
+
const elapsed = Date.now() - startTime;
|
|
1320
|
+
if (elapsed >= timeoutMs) {
|
|
1321
|
+
resolve(false);
|
|
1322
|
+
return;
|
|
1323
|
+
}
|
|
1324
|
+
setTimeout(checkForExtension, checkInterval);
|
|
1325
|
+
};
|
|
1326
|
+
checkForExtension();
|
|
1327
|
+
});
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
// src/BrowserSDK.ts
|
|
1081
1331
|
var BrowserSDK = class {
|
|
1082
1332
|
constructor(config) {
|
|
1083
1333
|
debug.info(DebugCategory.BROWSER_SDK, "Initializing BrowserSDK", {
|
|
@@ -1098,145 +1348,109 @@ var BrowserSDK = class {
|
|
|
1098
1348
|
`Invalid embeddedWalletType: ${config.embeddedWalletType}. Must be "app-wallet" or "user-wallet".`
|
|
1099
1349
|
);
|
|
1100
1350
|
}
|
|
1101
|
-
config.embeddedWalletType = embeddedWalletType;
|
|
1102
|
-
debug.log(DebugCategory.BROWSER_SDK, "Creating ProviderManager", { config });
|
|
1103
1351
|
this.providerManager = new ProviderManager(config);
|
|
1104
|
-
debug.info(DebugCategory.BROWSER_SDK, "BrowserSDK initialized successfully");
|
|
1105
1352
|
}
|
|
1353
|
+
// ===== CHAIN API =====
|
|
1106
1354
|
/**
|
|
1107
|
-
*
|
|
1355
|
+
* Access Solana chain operations
|
|
1108
1356
|
*/
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
if (
|
|
1112
|
-
|
|
1113
|
-
providerType: options.providerType,
|
|
1114
|
-
embeddedWalletType: options.embeddedWalletType
|
|
1115
|
-
});
|
|
1116
|
-
if (!["injected", "embedded"].includes(options.providerType)) {
|
|
1117
|
-
debug.error(DebugCategory.BROWSER_SDK, "Invalid providerType in connect options", {
|
|
1118
|
-
providerType: options.providerType
|
|
1119
|
-
});
|
|
1120
|
-
throw new Error(`Invalid providerType: ${options.providerType}. Must be "injected" or "embedded".`);
|
|
1121
|
-
}
|
|
1122
|
-
if (options.embeddedWalletType && !["app-wallet", "user-wallet"].includes(options.embeddedWalletType)) {
|
|
1123
|
-
debug.error(DebugCategory.BROWSER_SDK, "Invalid embeddedWalletType in connect options", {
|
|
1124
|
-
embeddedWalletType: options.embeddedWalletType
|
|
1125
|
-
});
|
|
1126
|
-
throw new Error(
|
|
1127
|
-
`Invalid embeddedWalletType: ${options.embeddedWalletType}. Must be "app-wallet" or "user-wallet".`
|
|
1128
|
-
);
|
|
1129
|
-
}
|
|
1130
|
-
debug.log(DebugCategory.BROWSER_SDK, "Switching provider", {
|
|
1131
|
-
providerType: options.providerType,
|
|
1132
|
-
embeddedWalletType: options.embeddedWalletType
|
|
1133
|
-
});
|
|
1134
|
-
await this.providerManager.switchProvider(options.providerType, {
|
|
1135
|
-
embeddedWalletType: options.embeddedWalletType
|
|
1136
|
-
});
|
|
1357
|
+
get solana() {
|
|
1358
|
+
const currentProvider = this.providerManager.getCurrentProvider();
|
|
1359
|
+
if (!currentProvider) {
|
|
1360
|
+
throw new Error("No provider available. Call connect() first.");
|
|
1137
1361
|
}
|
|
1138
|
-
|
|
1139
|
-
authOptions: options?.authOptions
|
|
1140
|
-
});
|
|
1141
|
-
const result = await this.providerManager.connect(options?.authOptions);
|
|
1142
|
-
debug.info(DebugCategory.BROWSER_SDK, "Connect completed successfully", result);
|
|
1143
|
-
return result;
|
|
1362
|
+
return currentProvider.solana;
|
|
1144
1363
|
}
|
|
1145
1364
|
/**
|
|
1146
|
-
*
|
|
1365
|
+
* Access Ethereum chain operations
|
|
1147
1366
|
*/
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1367
|
+
get ethereum() {
|
|
1368
|
+
const currentProvider = this.providerManager.getCurrentProvider();
|
|
1369
|
+
if (!currentProvider) {
|
|
1370
|
+
throw new Error("No provider available. Call connect() first.");
|
|
1151
1371
|
}
|
|
1152
|
-
|
|
1372
|
+
return currentProvider.ethereum;
|
|
1153
1373
|
}
|
|
1374
|
+
// ===== CONNECTION MANAGEMENT =====
|
|
1154
1375
|
/**
|
|
1155
|
-
*
|
|
1376
|
+
* Connect to the wallet
|
|
1156
1377
|
*/
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
const installed = isPhantomExtensionInstalled();
|
|
1166
|
-
if (installed)
|
|
1167
|
-
return true;
|
|
1168
|
-
if (retries <= 0)
|
|
1169
|
-
return false;
|
|
1170
|
-
if (timeAccumulated >= (timeoutMs || 3e3))
|
|
1171
|
-
return false;
|
|
1172
|
-
return new Promise((resolve) => {
|
|
1173
|
-
setTimeout(async () => {
|
|
1174
|
-
const result = await isInstalled(retries - 1, timeAccumulated + 100);
|
|
1175
|
-
resolve(result);
|
|
1176
|
-
}, 100);
|
|
1378
|
+
async connect(options) {
|
|
1379
|
+
debug.info(DebugCategory.BROWSER_SDK, "Starting connection", options);
|
|
1380
|
+
try {
|
|
1381
|
+
const result = await this.providerManager.connect(options);
|
|
1382
|
+
debug.info(DebugCategory.BROWSER_SDK, "Connection successful", {
|
|
1383
|
+
addressCount: result.addresses.length,
|
|
1384
|
+
walletId: result.walletId,
|
|
1385
|
+
status: result.status
|
|
1177
1386
|
});
|
|
1178
|
-
|
|
1179
|
-
|
|
1387
|
+
return result;
|
|
1388
|
+
} catch (error) {
|
|
1389
|
+
debug.error(DebugCategory.BROWSER_SDK, "Connection failed", { error: error.message });
|
|
1390
|
+
throw error;
|
|
1391
|
+
}
|
|
1180
1392
|
}
|
|
1181
1393
|
/**
|
|
1182
1394
|
* Disconnect from the wallet
|
|
1183
1395
|
*/
|
|
1184
1396
|
async disconnect() {
|
|
1185
|
-
|
|
1397
|
+
debug.info(DebugCategory.BROWSER_SDK, "Disconnecting");
|
|
1398
|
+
try {
|
|
1399
|
+
await this.providerManager.disconnect();
|
|
1400
|
+
debug.info(DebugCategory.BROWSER_SDK, "Disconnection successful");
|
|
1401
|
+
} catch (error) {
|
|
1402
|
+
debug.error(DebugCategory.BROWSER_SDK, "Disconnection failed", { error: error.message });
|
|
1403
|
+
throw error;
|
|
1404
|
+
}
|
|
1186
1405
|
}
|
|
1187
1406
|
/**
|
|
1188
|
-
*
|
|
1189
|
-
* @param message - Message string to sign
|
|
1190
|
-
* @param networkId - Network identifier
|
|
1191
|
-
* @returns Signature string
|
|
1407
|
+
* Switch between provider types (injected vs embedded)
|
|
1192
1408
|
*/
|
|
1193
|
-
async
|
|
1194
|
-
debug.info(DebugCategory.BROWSER_SDK, "
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1409
|
+
async switchProvider(type, options) {
|
|
1410
|
+
debug.info(DebugCategory.BROWSER_SDK, "Switching provider", { type, options });
|
|
1411
|
+
try {
|
|
1412
|
+
await this.providerManager.switchProvider(type, options);
|
|
1413
|
+
debug.info(DebugCategory.BROWSER_SDK, "Provider switch successful", { type });
|
|
1414
|
+
} catch (error) {
|
|
1415
|
+
debug.error(DebugCategory.BROWSER_SDK, "Provider switch failed", {
|
|
1416
|
+
type,
|
|
1417
|
+
error: error.message
|
|
1418
|
+
});
|
|
1419
|
+
throw error;
|
|
1420
|
+
}
|
|
1205
1421
|
}
|
|
1422
|
+
// ===== STATE QUERIES =====
|
|
1206
1423
|
/**
|
|
1207
|
-
*
|
|
1208
|
-
* @param params - Transaction parameters with native transaction object
|
|
1209
|
-
* @returns Transaction result
|
|
1424
|
+
* Check if the SDK is connected to a wallet
|
|
1210
1425
|
*/
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
networkId: params.networkId
|
|
1214
|
-
});
|
|
1215
|
-
const result = await this.providerManager.signAndSendTransaction(params);
|
|
1216
|
-
debug.info(DebugCategory.BROWSER_SDK, "Transaction signed and sent successfully", {
|
|
1217
|
-
networkId: params.networkId,
|
|
1218
|
-
result
|
|
1219
|
-
});
|
|
1220
|
-
return result;
|
|
1426
|
+
isConnected() {
|
|
1427
|
+
return this.providerManager.isConnected();
|
|
1221
1428
|
}
|
|
1222
1429
|
/**
|
|
1223
|
-
* Get wallet addresses
|
|
1430
|
+
* Get all connected wallet addresses
|
|
1224
1431
|
*/
|
|
1225
1432
|
getAddresses() {
|
|
1226
1433
|
return this.providerManager.getAddresses();
|
|
1227
1434
|
}
|
|
1228
1435
|
/**
|
|
1229
|
-
*
|
|
1436
|
+
* Get information about the current provider
|
|
1230
1437
|
*/
|
|
1231
|
-
|
|
1232
|
-
return this.providerManager.
|
|
1438
|
+
getCurrentProviderInfo() {
|
|
1439
|
+
return this.providerManager.getCurrentProviderInfo();
|
|
1233
1440
|
}
|
|
1234
1441
|
/**
|
|
1235
|
-
* Get the
|
|
1442
|
+
* Get the wallet ID (for embedded wallets)
|
|
1236
1443
|
*/
|
|
1237
1444
|
getWalletId() {
|
|
1238
1445
|
return this.providerManager.getWalletId();
|
|
1239
1446
|
}
|
|
1447
|
+
// ===== UTILITY METHODS =====
|
|
1448
|
+
/**
|
|
1449
|
+
* Check if Phantom extension is installed
|
|
1450
|
+
*/
|
|
1451
|
+
static async isPhantomInstalled(timeoutMs) {
|
|
1452
|
+
return waitForPhantomExtension(timeoutMs);
|
|
1453
|
+
}
|
|
1240
1454
|
/**
|
|
1241
1455
|
* Add event listener for provider events (connect, connect_start, connect_error, disconnect, error)
|
|
1242
1456
|
* Works with both embedded and injected providers
|
|
@@ -1318,16 +1532,106 @@ var BrowserSDK = class {
|
|
|
1318
1532
|
this.setDebugCallback(config.callback);
|
|
1319
1533
|
}
|
|
1320
1534
|
}
|
|
1535
|
+
// ===== AUTO-CONFIRM METHODS (Injected Provider Only) =====
|
|
1536
|
+
/**
|
|
1537
|
+
* Enable auto-confirm for transactions
|
|
1538
|
+
* Only available for injected providers
|
|
1539
|
+
*/
|
|
1540
|
+
async enableAutoConfirm(params) {
|
|
1541
|
+
debug.info(DebugCategory.BROWSER_SDK, "Enabling auto-confirm", { params });
|
|
1542
|
+
const currentProvider = this.providerManager.getCurrentProvider();
|
|
1543
|
+
if (!currentProvider) {
|
|
1544
|
+
throw new Error("No provider available. Call connect() first.");
|
|
1545
|
+
}
|
|
1546
|
+
if (!("enableAutoConfirm" in currentProvider)) {
|
|
1547
|
+
throw new Error("Auto-confirm is only available for injected providers");
|
|
1548
|
+
}
|
|
1549
|
+
try {
|
|
1550
|
+
const result = await currentProvider.enableAutoConfirm(params);
|
|
1551
|
+
debug.info(DebugCategory.BROWSER_SDK, "Auto-confirm enabled successfully", { result });
|
|
1552
|
+
return result;
|
|
1553
|
+
} catch (error) {
|
|
1554
|
+
debug.error(DebugCategory.BROWSER_SDK, "Failed to enable auto-confirm", { error: error.message });
|
|
1555
|
+
throw error;
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
/**
|
|
1559
|
+
* Disable auto-confirm for transactions
|
|
1560
|
+
* Only available for injected providers
|
|
1561
|
+
*/
|
|
1562
|
+
async disableAutoConfirm() {
|
|
1563
|
+
debug.info(DebugCategory.BROWSER_SDK, "Disabling auto-confirm");
|
|
1564
|
+
const currentProvider = this.providerManager.getCurrentProvider();
|
|
1565
|
+
if (!currentProvider) {
|
|
1566
|
+
throw new Error("No provider available. Call connect() first.");
|
|
1567
|
+
}
|
|
1568
|
+
if (!("disableAutoConfirm" in currentProvider)) {
|
|
1569
|
+
throw new Error("Auto-confirm is only available for injected providers");
|
|
1570
|
+
}
|
|
1571
|
+
try {
|
|
1572
|
+
await currentProvider.disableAutoConfirm();
|
|
1573
|
+
debug.info(DebugCategory.BROWSER_SDK, "Auto-confirm disabled successfully");
|
|
1574
|
+
} catch (error) {
|
|
1575
|
+
debug.error(DebugCategory.BROWSER_SDK, "Failed to disable auto-confirm", { error: error.message });
|
|
1576
|
+
throw error;
|
|
1577
|
+
}
|
|
1578
|
+
}
|
|
1579
|
+
/**
|
|
1580
|
+
* Get current auto-confirm status
|
|
1581
|
+
* Only available for injected providers
|
|
1582
|
+
*/
|
|
1583
|
+
async getAutoConfirmStatus() {
|
|
1584
|
+
debug.info(DebugCategory.BROWSER_SDK, "Getting auto-confirm status");
|
|
1585
|
+
const currentProvider = this.providerManager.getCurrentProvider();
|
|
1586
|
+
if (!currentProvider) {
|
|
1587
|
+
throw new Error("No provider available. Call connect() first.");
|
|
1588
|
+
}
|
|
1589
|
+
if (!("getAutoConfirmStatus" in currentProvider)) {
|
|
1590
|
+
throw new Error("Auto-confirm is only available for injected providers");
|
|
1591
|
+
}
|
|
1592
|
+
try {
|
|
1593
|
+
const result = await currentProvider.getAutoConfirmStatus();
|
|
1594
|
+
debug.info(DebugCategory.BROWSER_SDK, "Got auto-confirm status", { result });
|
|
1595
|
+
return result;
|
|
1596
|
+
} catch (error) {
|
|
1597
|
+
debug.error(DebugCategory.BROWSER_SDK, "Failed to get auto-confirm status", { error: error.message });
|
|
1598
|
+
throw error;
|
|
1599
|
+
}
|
|
1600
|
+
}
|
|
1601
|
+
/**
|
|
1602
|
+
* Get supported chains for auto-confirm
|
|
1603
|
+
* Only available for injected providers
|
|
1604
|
+
*/
|
|
1605
|
+
async getSupportedAutoConfirmChains() {
|
|
1606
|
+
debug.info(DebugCategory.BROWSER_SDK, "Getting supported auto-confirm chains");
|
|
1607
|
+
const currentProvider = this.providerManager.getCurrentProvider();
|
|
1608
|
+
if (!currentProvider) {
|
|
1609
|
+
throw new Error("No provider available. Call connect() first.");
|
|
1610
|
+
}
|
|
1611
|
+
if (!("getSupportedAutoConfirmChains" in currentProvider)) {
|
|
1612
|
+
throw new Error("Auto-confirm is only available for injected providers");
|
|
1613
|
+
}
|
|
1614
|
+
try {
|
|
1615
|
+
const result = await currentProvider.getSupportedAutoConfirmChains();
|
|
1616
|
+
debug.info(DebugCategory.BROWSER_SDK, "Got supported auto-confirm chains", { result });
|
|
1617
|
+
return result;
|
|
1618
|
+
} catch (error) {
|
|
1619
|
+
debug.error(DebugCategory.BROWSER_SDK, "Failed to get supported auto-confirm chains", {
|
|
1620
|
+
error: error.message
|
|
1621
|
+
});
|
|
1622
|
+
throw error;
|
|
1623
|
+
}
|
|
1624
|
+
}
|
|
1321
1625
|
};
|
|
1322
1626
|
|
|
1323
1627
|
// src/types.ts
|
|
1324
|
-
import { AddressType as
|
|
1628
|
+
import { AddressType as AddressType4 } from "@phantom/client";
|
|
1325
1629
|
|
|
1326
1630
|
// src/index.ts
|
|
1327
1631
|
import { NetworkId } from "@phantom/constants";
|
|
1328
|
-
import { AddressType as
|
|
1632
|
+
import { AddressType as AddressType5 } from "@phantom/client";
|
|
1329
1633
|
export {
|
|
1330
|
-
|
|
1634
|
+
AddressType5 as AddressType,
|
|
1331
1635
|
BrowserSDK,
|
|
1332
1636
|
DEFAULT_AUTH_URL,
|
|
1333
1637
|
DEFAULT_WALLET_API_URL,
|
|
@@ -1338,5 +1642,6 @@ export {
|
|
|
1338
1642
|
detectBrowser,
|
|
1339
1643
|
getBrowserDisplayName,
|
|
1340
1644
|
getPlatformName,
|
|
1341
|
-
parseBrowserFromUserAgent
|
|
1645
|
+
parseBrowserFromUserAgent,
|
|
1646
|
+
waitForPhantomExtension
|
|
1342
1647
|
};
|