@phantom/browser-sdk 0.3.8 → 1.0.0-beta.0
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 +457 -430
- package/dist/index.d.ts +58 -30
- package/dist/index.js +351 -235
- package/dist/index.mjs +355 -226
- package/package.json +10 -9
package/dist/index.mjs
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
// src/providers/injected/index.ts
|
|
2
2
|
import { AddressType } from "@phantom/client";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
createPhantom,
|
|
5
|
+
createExtensionPlugin
|
|
6
|
+
} from "@phantom/browser-injected-sdk";
|
|
4
7
|
import { createSolanaPlugin } from "@phantom/browser-injected-sdk/solana";
|
|
5
8
|
import { createEthereumPlugin } from "@phantom/browser-injected-sdk/ethereum";
|
|
9
|
+
import { createAutoConfirmPlugin } from "@phantom/browser-injected-sdk/auto-confirm";
|
|
6
10
|
|
|
7
11
|
// src/debug.ts
|
|
8
12
|
var DebugLevel = /* @__PURE__ */ ((DebugLevel2) => {
|
|
@@ -78,10 +82,116 @@ var DebugCategory = {
|
|
|
78
82
|
SESSION: "Session"
|
|
79
83
|
};
|
|
80
84
|
|
|
85
|
+
// src/providers/injected/chains/SolanaChain.ts
|
|
86
|
+
import { getExplorerUrl, NetworkId } from "@phantom/constants";
|
|
87
|
+
import { Buffer } from "buffer";
|
|
88
|
+
var InjectedSolanaChain = class {
|
|
89
|
+
constructor(phantom) {
|
|
90
|
+
this.phantom = phantom;
|
|
91
|
+
}
|
|
92
|
+
async signMessage(message) {
|
|
93
|
+
const messageBytes = typeof message === "string" ? new TextEncoder().encode(message) : message;
|
|
94
|
+
const result = await this.phantom.solana.signMessage(messageBytes);
|
|
95
|
+
const signature = result.signature instanceof Uint8Array ? Buffer.from(result.signature).toString("base64") : result.signature;
|
|
96
|
+
return {
|
|
97
|
+
signature,
|
|
98
|
+
rawSignature: signature
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
signTransaction(_transaction) {
|
|
102
|
+
throw new Error("signTransaction not available in browser-injected-sdk, use signAndSendTransaction instead");
|
|
103
|
+
}
|
|
104
|
+
async signAndSendTransaction(transaction) {
|
|
105
|
+
const result = await this.phantom.solana.signAndSendTransaction(transaction);
|
|
106
|
+
return {
|
|
107
|
+
hash: result.signature,
|
|
108
|
+
rawTransaction: result.signature,
|
|
109
|
+
blockExplorer: getExplorerUrl(NetworkId.SOLANA_MAINNET, "transaction", result.signature)
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
async connect(_options) {
|
|
113
|
+
const address = await this.phantom.solana.connect();
|
|
114
|
+
if (!address) {
|
|
115
|
+
throw new Error("Failed to connect to Solana wallet");
|
|
116
|
+
}
|
|
117
|
+
return { publicKey: address };
|
|
118
|
+
}
|
|
119
|
+
async disconnect() {
|
|
120
|
+
return await this.phantom.solana.disconnect();
|
|
121
|
+
}
|
|
122
|
+
async switchNetwork(_network) {
|
|
123
|
+
}
|
|
124
|
+
async getPublicKey() {
|
|
125
|
+
try {
|
|
126
|
+
const address = await this.phantom.solana.getAccount();
|
|
127
|
+
return address || null;
|
|
128
|
+
} catch {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
isConnected() {
|
|
133
|
+
try {
|
|
134
|
+
return !!this.phantom.extension?.isInstalled();
|
|
135
|
+
} catch {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
// src/providers/injected/chains/EthereumChain.ts
|
|
142
|
+
import { getExplorerUrl as getExplorerUrl2, NetworkId as NetworkId2, chainIdToNetworkId } from "@phantom/constants";
|
|
143
|
+
var InjectedEthereumChain = class {
|
|
144
|
+
constructor(phantom) {
|
|
145
|
+
this.phantom = phantom;
|
|
146
|
+
}
|
|
147
|
+
async request(args) {
|
|
148
|
+
const provider = await this.phantom.ethereum.getProvider();
|
|
149
|
+
return await provider.request(args);
|
|
150
|
+
}
|
|
151
|
+
async signPersonalMessage(message, address) {
|
|
152
|
+
const signature = await this.phantom.ethereum.signPersonalMessage(message, address);
|
|
153
|
+
return {
|
|
154
|
+
signature,
|
|
155
|
+
rawSignature: signature
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
async signTypedData(typedData, address) {
|
|
159
|
+
const signature = await this.phantom.ethereum.signTypedData(typedData, address);
|
|
160
|
+
return {
|
|
161
|
+
signature,
|
|
162
|
+
rawSignature: signature
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
async sendTransaction(transaction) {
|
|
166
|
+
const hash = await this.phantom.ethereum.sendTransaction(transaction);
|
|
167
|
+
const chainId = await this.getChainId();
|
|
168
|
+
const networkId = chainIdToNetworkId(chainId) || NetworkId2.ETHEREUM_MAINNET;
|
|
169
|
+
return {
|
|
170
|
+
hash,
|
|
171
|
+
rawTransaction: hash,
|
|
172
|
+
blockExplorer: getExplorerUrl2(networkId, "transaction", hash)
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
async switchChain(chainId) {
|
|
176
|
+
return await this.phantom.ethereum.switchChain(`0x${chainId.toString(16)}`);
|
|
177
|
+
}
|
|
178
|
+
async getChainId() {
|
|
179
|
+
const chainId = await this.phantom.ethereum.getChainId();
|
|
180
|
+
return parseInt(chainId, 16);
|
|
181
|
+
}
|
|
182
|
+
async getAccounts() {
|
|
183
|
+
return await this.phantom.ethereum.getAccounts();
|
|
184
|
+
}
|
|
185
|
+
isConnected() {
|
|
186
|
+
try {
|
|
187
|
+
return !!this.phantom.extension?.isInstalled();
|
|
188
|
+
} catch {
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
|
|
81
194
|
// src/providers/injected/index.ts
|
|
82
|
-
import { base64urlEncode } from "@phantom/base64url";
|
|
83
|
-
import { getExplorerUrl } from "@phantom/constants";
|
|
84
|
-
import bs58 from "bs58";
|
|
85
195
|
var InjectedProvider = class {
|
|
86
196
|
constructor(config) {
|
|
87
197
|
this.connected = false;
|
|
@@ -102,12 +212,38 @@ var InjectedProvider = class {
|
|
|
102
212
|
plugins.push(createEthereumPlugin());
|
|
103
213
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum plugin added");
|
|
104
214
|
}
|
|
215
|
+
plugins.push(createAutoConfirmPlugin());
|
|
216
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "AutoConfirm plugin added");
|
|
105
217
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Creating Phantom instance with plugins", {
|
|
106
218
|
pluginCount: plugins.length
|
|
107
219
|
});
|
|
108
220
|
this.phantom = createPhantom({ plugins });
|
|
109
221
|
debug.info(DebugCategory.INJECTED_PROVIDER, "InjectedProvider initialized");
|
|
110
222
|
}
|
|
223
|
+
/**
|
|
224
|
+
* Access to Solana chain operations
|
|
225
|
+
*/
|
|
226
|
+
get solana() {
|
|
227
|
+
if (!this.addressTypes.includes(AddressType.solana)) {
|
|
228
|
+
throw new Error("Solana not enabled for this provider");
|
|
229
|
+
}
|
|
230
|
+
if (!this._solanaChain) {
|
|
231
|
+
this._solanaChain = new InjectedSolanaChain(this.phantom);
|
|
232
|
+
}
|
|
233
|
+
return this._solanaChain;
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Access to Ethereum chain operations
|
|
237
|
+
*/
|
|
238
|
+
get ethereum() {
|
|
239
|
+
if (!this.addressTypes.includes(AddressType.ethereum)) {
|
|
240
|
+
throw new Error("Ethereum not enabled for this provider");
|
|
241
|
+
}
|
|
242
|
+
if (!this._ethereumChain) {
|
|
243
|
+
this._ethereumChain = new InjectedEthereumChain(this.phantom);
|
|
244
|
+
}
|
|
245
|
+
return this._ethereumChain;
|
|
246
|
+
}
|
|
111
247
|
async connect(authOptions) {
|
|
112
248
|
debug.info(DebugCategory.INJECTED_PROVIDER, "Starting injected provider connect", {
|
|
113
249
|
addressTypes: this.addressTypes,
|
|
@@ -119,7 +255,7 @@ var InjectedProvider = class {
|
|
|
119
255
|
providerType: "injected"
|
|
120
256
|
});
|
|
121
257
|
try {
|
|
122
|
-
if (!this.phantom.extension
|
|
258
|
+
if (!this.phantom.extension?.isInstalled?.()) {
|
|
123
259
|
debug.error(DebugCategory.INJECTED_PROVIDER, "Phantom wallet extension not found");
|
|
124
260
|
const error = new Error("Phantom wallet not found");
|
|
125
261
|
this.emit("connect_error", {
|
|
@@ -133,13 +269,13 @@ var InjectedProvider = class {
|
|
|
133
269
|
if (this.addressTypes.includes(AddressType.solana)) {
|
|
134
270
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting Solana connection");
|
|
135
271
|
try {
|
|
136
|
-
const
|
|
137
|
-
if (publicKey) {
|
|
272
|
+
const result2 = await this.solana.connect();
|
|
273
|
+
if (result2.publicKey) {
|
|
138
274
|
connectedAddresses.push({
|
|
139
275
|
addressType: AddressType.solana,
|
|
140
|
-
address: publicKey
|
|
276
|
+
address: result2.publicKey
|
|
141
277
|
});
|
|
142
|
-
debug.info(DebugCategory.INJECTED_PROVIDER, "Solana connected successfully", { address: publicKey });
|
|
278
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "Solana connected successfully", { address: result2.publicKey });
|
|
143
279
|
}
|
|
144
280
|
} catch (err) {
|
|
145
281
|
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Solana", { error: err });
|
|
@@ -147,7 +283,7 @@ var InjectedProvider = class {
|
|
|
147
283
|
}
|
|
148
284
|
if (this.addressTypes.includes(AddressType.ethereum)) {
|
|
149
285
|
try {
|
|
150
|
-
const accounts = await this.
|
|
286
|
+
const accounts = await this.ethereum.getAccounts();
|
|
151
287
|
if (accounts && accounts.length > 0) {
|
|
152
288
|
connectedAddresses.push(
|
|
153
289
|
...accounts.map((address) => ({
|
|
@@ -155,6 +291,7 @@ var InjectedProvider = class {
|
|
|
155
291
|
address
|
|
156
292
|
}))
|
|
157
293
|
);
|
|
294
|
+
debug.info(DebugCategory.INJECTED_PROVIDER, "Ethereum connected successfully", { addresses: accounts });
|
|
158
295
|
}
|
|
159
296
|
} catch (err) {
|
|
160
297
|
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Ethereum", { error: err });
|
|
@@ -194,20 +331,17 @@ var InjectedProvider = class {
|
|
|
194
331
|
debug.info(DebugCategory.INJECTED_PROVIDER, "Starting injected provider disconnect");
|
|
195
332
|
if (this.addressTypes.includes(AddressType.solana)) {
|
|
196
333
|
try {
|
|
197
|
-
await this.
|
|
334
|
+
await this.solana.disconnect();
|
|
198
335
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana disconnected successfully");
|
|
199
336
|
} catch (err) {
|
|
200
337
|
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to disconnect Solana", { error: err });
|
|
201
338
|
}
|
|
202
339
|
}
|
|
203
340
|
if (this.addressTypes.includes(AddressType.ethereum)) {
|
|
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
|
-
}
|
|
341
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum disconnected (no-op)");
|
|
210
342
|
}
|
|
343
|
+
this._solanaChain = void 0;
|
|
344
|
+
this._ethereumChain = void 0;
|
|
211
345
|
this.browserInjectedCleanupFunctions.forEach((cleanup) => cleanup());
|
|
212
346
|
this.browserInjectedCleanupFunctions = [];
|
|
213
347
|
this.connected = false;
|
|
@@ -217,77 +351,29 @@ var InjectedProvider = class {
|
|
|
217
351
|
});
|
|
218
352
|
debug.info(DebugCategory.INJECTED_PROVIDER, "Injected provider disconnected successfully");
|
|
219
353
|
}
|
|
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
354
|
getAddresses() {
|
|
286
355
|
return this.addresses;
|
|
287
356
|
}
|
|
288
357
|
isConnected() {
|
|
289
358
|
return this.connected;
|
|
290
359
|
}
|
|
360
|
+
// AutoConfirm methods - only available for injected providers
|
|
361
|
+
async enableAutoConfirm(params) {
|
|
362
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Enabling autoConfirm", { params });
|
|
363
|
+
return await this.phantom.autoConfirm.autoConfirmEnable(params);
|
|
364
|
+
}
|
|
365
|
+
async disableAutoConfirm() {
|
|
366
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Disabling autoConfirm");
|
|
367
|
+
await this.phantom.autoConfirm.autoConfirmDisable();
|
|
368
|
+
}
|
|
369
|
+
async getAutoConfirmStatus() {
|
|
370
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Getting autoConfirm status");
|
|
371
|
+
return await this.phantom.autoConfirm.autoConfirmStatus();
|
|
372
|
+
}
|
|
373
|
+
async getSupportedAutoConfirmChains() {
|
|
374
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Getting supported autoConfirm chains");
|
|
375
|
+
return await this.phantom.autoConfirm.autoConfirmSupportedChains();
|
|
376
|
+
}
|
|
291
377
|
// Event management methods - implementing unified event interface
|
|
292
378
|
on(event, callback) {
|
|
293
379
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Adding event listener", { event });
|
|
@@ -328,16 +414,16 @@ var InjectedProvider = class {
|
|
|
328
414
|
}
|
|
329
415
|
setupBrowserInjectedEvents() {
|
|
330
416
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up browser-injected-sdk event listeners");
|
|
331
|
-
if (this.addressTypes.includes(AddressType.solana)
|
|
417
|
+
if (this.addressTypes.includes(AddressType.solana)) {
|
|
332
418
|
this.setupSolanaEvents();
|
|
333
419
|
}
|
|
334
|
-
if (this.addressTypes.includes(AddressType.ethereum)
|
|
420
|
+
if (this.addressTypes.includes(AddressType.ethereum)) {
|
|
335
421
|
this.setupEthereumEvents();
|
|
336
422
|
}
|
|
337
423
|
}
|
|
338
424
|
setupSolanaEvents() {
|
|
339
425
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up Solana event listeners");
|
|
340
|
-
const
|
|
426
|
+
const handleSolanaConnect = (publicKey) => {
|
|
341
427
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana connect event received", { publicKey });
|
|
342
428
|
const solanaAddress = { addressType: AddressType.solana, address: publicKey };
|
|
343
429
|
if (!this.addresses.find((addr) => addr.addressType === AddressType.solana)) {
|
|
@@ -348,16 +434,16 @@ var InjectedProvider = class {
|
|
|
348
434
|
addresses: this.addresses,
|
|
349
435
|
source: "injected-extension"
|
|
350
436
|
});
|
|
351
|
-
}
|
|
352
|
-
const
|
|
437
|
+
};
|
|
438
|
+
const handleSolanaDisconnect = () => {
|
|
353
439
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana disconnect event received");
|
|
354
440
|
this.addresses = this.addresses.filter((addr) => addr.addressType !== AddressType.solana);
|
|
355
441
|
this.connected = this.addresses.length > 0;
|
|
356
442
|
this.emit("disconnect", {
|
|
357
443
|
source: "injected-extension"
|
|
358
444
|
});
|
|
359
|
-
}
|
|
360
|
-
const
|
|
445
|
+
};
|
|
446
|
+
const handleSolanaAccountChanged = (publicKey) => {
|
|
361
447
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Solana account changed event received", { publicKey });
|
|
362
448
|
const solanaIndex = this.addresses.findIndex((addr) => addr.addressType === AddressType.solana);
|
|
363
449
|
if (solanaIndex >= 0) {
|
|
@@ -369,16 +455,19 @@ var InjectedProvider = class {
|
|
|
369
455
|
addresses: this.addresses,
|
|
370
456
|
source: "injected-extension-account-change"
|
|
371
457
|
});
|
|
372
|
-
}
|
|
458
|
+
};
|
|
459
|
+
const cleanupConnect = this.phantom.solana.addEventListener("connect", handleSolanaConnect);
|
|
460
|
+
const cleanupDisconnect = this.phantom.solana.addEventListener("disconnect", handleSolanaDisconnect);
|
|
461
|
+
const cleanupAccountChanged = this.phantom.solana.addEventListener("accountChanged", handleSolanaAccountChanged);
|
|
373
462
|
this.browserInjectedCleanupFunctions.push(
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
463
|
+
cleanupConnect,
|
|
464
|
+
cleanupDisconnect,
|
|
465
|
+
cleanupAccountChanged
|
|
377
466
|
);
|
|
378
467
|
}
|
|
379
468
|
setupEthereumEvents() {
|
|
380
469
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Setting up Ethereum event listeners");
|
|
381
|
-
const
|
|
470
|
+
const handleEthereumConnect = (accounts) => {
|
|
382
471
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum connect event received", { accounts });
|
|
383
472
|
this.addresses = this.addresses.filter((addr) => addr.addressType !== AddressType.ethereum);
|
|
384
473
|
if (accounts && accounts.length > 0) {
|
|
@@ -392,17 +481,17 @@ var InjectedProvider = class {
|
|
|
392
481
|
addresses: this.addresses,
|
|
393
482
|
source: "injected-extension"
|
|
394
483
|
});
|
|
395
|
-
}
|
|
396
|
-
const
|
|
484
|
+
};
|
|
485
|
+
const handleEthereumDisconnect = () => {
|
|
397
486
|
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum disconnect event received");
|
|
398
487
|
this.addresses = this.addresses.filter((addr) => addr.addressType !== AddressType.ethereum);
|
|
399
488
|
this.connected = this.addresses.length > 0;
|
|
400
489
|
this.emit("disconnect", {
|
|
401
490
|
source: "injected-extension"
|
|
402
491
|
});
|
|
403
|
-
}
|
|
404
|
-
const
|
|
405
|
-
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum
|
|
492
|
+
};
|
|
493
|
+
const handleEthereumAccountsChanged = (accounts) => {
|
|
494
|
+
debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum accounts changed event received", { accounts });
|
|
406
495
|
this.addresses = this.addresses.filter((addr) => addr.addressType !== AddressType.ethereum);
|
|
407
496
|
if (accounts && accounts.length > 0) {
|
|
408
497
|
this.addresses.push(...accounts.map((address) => ({
|
|
@@ -414,11 +503,14 @@ var InjectedProvider = class {
|
|
|
414
503
|
addresses: this.addresses,
|
|
415
504
|
source: "injected-extension-account-change"
|
|
416
505
|
});
|
|
417
|
-
}
|
|
506
|
+
};
|
|
507
|
+
const cleanupConnect = this.phantom.ethereum.addEventListener("connect", handleEthereumConnect);
|
|
508
|
+
const cleanupDisconnect = this.phantom.ethereum.addEventListener("disconnect", handleEthereumDisconnect);
|
|
509
|
+
const cleanupAccountsChanged = this.phantom.ethereum.addEventListener("accountsChanged", handleEthereumAccountsChanged);
|
|
418
510
|
this.browserInjectedCleanupFunctions.push(
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
511
|
+
cleanupConnect,
|
|
512
|
+
cleanupDisconnect,
|
|
513
|
+
cleanupAccountsChanged
|
|
422
514
|
);
|
|
423
515
|
}
|
|
424
516
|
};
|
|
@@ -583,6 +675,7 @@ var BrowserAuthProvider = class {
|
|
|
583
675
|
try {
|
|
584
676
|
const walletId = this.urlParamsAccessor.getParam("wallet_id");
|
|
585
677
|
const sessionId = this.urlParamsAccessor.getParam("session_id");
|
|
678
|
+
const accountDerivationIndex = this.urlParamsAccessor.getParam("selected_account_index");
|
|
586
679
|
const error = this.urlParamsAccessor.getParam("error");
|
|
587
680
|
const errorDescription = this.urlParamsAccessor.getParam("error_description");
|
|
588
681
|
if (error) {
|
|
@@ -626,11 +719,13 @@ var BrowserAuthProvider = class {
|
|
|
626
719
|
sessionStorage.removeItem("phantom-auth-context");
|
|
627
720
|
debug.info(DebugCategory.PHANTOM_CONNECT_AUTH, "Successfully resumed auth from redirect", {
|
|
628
721
|
walletId,
|
|
629
|
-
sessionId
|
|
722
|
+
sessionId,
|
|
723
|
+
accountDerivationIndex: accountDerivationIndex ? parseInt(accountDerivationIndex) : void 0
|
|
630
724
|
});
|
|
631
725
|
return {
|
|
632
726
|
walletId,
|
|
633
|
-
userInfo: context
|
|
727
|
+
userInfo: context,
|
|
728
|
+
accountDerivationIndex: accountDerivationIndex ? parseInt(accountDerivationIndex) : void 0
|
|
634
729
|
};
|
|
635
730
|
} catch (error) {
|
|
636
731
|
sessionStorage.removeItem("phantom-auth-context");
|
|
@@ -879,24 +974,6 @@ var ProviderManager = class {
|
|
|
879
974
|
await this.currentProvider.disconnect();
|
|
880
975
|
this.walletId = null;
|
|
881
976
|
}
|
|
882
|
-
/**
|
|
883
|
-
* Sign a message using current provider
|
|
884
|
-
*/
|
|
885
|
-
async signMessage(params) {
|
|
886
|
-
if (!this.currentProvider) {
|
|
887
|
-
throw new Error("No provider connected");
|
|
888
|
-
}
|
|
889
|
-
return this.currentProvider.signMessage(params);
|
|
890
|
-
}
|
|
891
|
-
/**
|
|
892
|
-
* Sign and send transaction using current provider
|
|
893
|
-
*/
|
|
894
|
-
async signAndSendTransaction(params) {
|
|
895
|
-
if (!this.currentProvider) {
|
|
896
|
-
throw new Error("No provider connected");
|
|
897
|
-
}
|
|
898
|
-
return this.currentProvider.signAndSendTransaction(params);
|
|
899
|
-
}
|
|
900
977
|
/**
|
|
901
978
|
* Get addresses from current provider
|
|
902
979
|
*/
|
|
@@ -1095,145 +1172,109 @@ var BrowserSDK = class {
|
|
|
1095
1172
|
`Invalid embeddedWalletType: ${config.embeddedWalletType}. Must be "app-wallet" or "user-wallet".`
|
|
1096
1173
|
);
|
|
1097
1174
|
}
|
|
1098
|
-
config.embeddedWalletType = embeddedWalletType;
|
|
1099
|
-
debug.log(DebugCategory.BROWSER_SDK, "Creating ProviderManager", { config });
|
|
1100
1175
|
this.providerManager = new ProviderManager(config);
|
|
1101
|
-
debug.info(DebugCategory.BROWSER_SDK, "BrowserSDK initialized successfully");
|
|
1102
1176
|
}
|
|
1177
|
+
// ===== CHAIN API =====
|
|
1103
1178
|
/**
|
|
1104
|
-
*
|
|
1179
|
+
* Access Solana chain operations
|
|
1105
1180
|
*/
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
if (
|
|
1109
|
-
|
|
1110
|
-
providerType: options.providerType,
|
|
1111
|
-
embeddedWalletType: options.embeddedWalletType
|
|
1112
|
-
});
|
|
1113
|
-
if (!["injected", "embedded"].includes(options.providerType)) {
|
|
1114
|
-
debug.error(DebugCategory.BROWSER_SDK, "Invalid providerType in connect options", {
|
|
1115
|
-
providerType: options.providerType
|
|
1116
|
-
});
|
|
1117
|
-
throw new Error(`Invalid providerType: ${options.providerType}. Must be "injected" or "embedded".`);
|
|
1118
|
-
}
|
|
1119
|
-
if (options.embeddedWalletType && !["app-wallet", "user-wallet"].includes(options.embeddedWalletType)) {
|
|
1120
|
-
debug.error(DebugCategory.BROWSER_SDK, "Invalid embeddedWalletType in connect options", {
|
|
1121
|
-
embeddedWalletType: options.embeddedWalletType
|
|
1122
|
-
});
|
|
1123
|
-
throw new Error(
|
|
1124
|
-
`Invalid embeddedWalletType: ${options.embeddedWalletType}. Must be "app-wallet" or "user-wallet".`
|
|
1125
|
-
);
|
|
1126
|
-
}
|
|
1127
|
-
debug.log(DebugCategory.BROWSER_SDK, "Switching provider", {
|
|
1128
|
-
providerType: options.providerType,
|
|
1129
|
-
embeddedWalletType: options.embeddedWalletType
|
|
1130
|
-
});
|
|
1131
|
-
await this.providerManager.switchProvider(options.providerType, {
|
|
1132
|
-
embeddedWalletType: options.embeddedWalletType
|
|
1133
|
-
});
|
|
1181
|
+
get solana() {
|
|
1182
|
+
const currentProvider = this.providerManager.getCurrentProvider();
|
|
1183
|
+
if (!currentProvider) {
|
|
1184
|
+
throw new Error("No provider available. Call connect() first.");
|
|
1134
1185
|
}
|
|
1135
|
-
|
|
1136
|
-
authOptions: options?.authOptions
|
|
1137
|
-
});
|
|
1138
|
-
const result = await this.providerManager.connect(options?.authOptions);
|
|
1139
|
-
debug.info(DebugCategory.BROWSER_SDK, "Connect completed successfully", result);
|
|
1140
|
-
return result;
|
|
1186
|
+
return currentProvider.solana;
|
|
1141
1187
|
}
|
|
1142
1188
|
/**
|
|
1143
|
-
*
|
|
1189
|
+
* Access Ethereum chain operations
|
|
1144
1190
|
*/
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1191
|
+
get ethereum() {
|
|
1192
|
+
const currentProvider = this.providerManager.getCurrentProvider();
|
|
1193
|
+
if (!currentProvider) {
|
|
1194
|
+
throw new Error("No provider available. Call connect() first.");
|
|
1148
1195
|
}
|
|
1149
|
-
|
|
1150
|
-
}
|
|
1151
|
-
/**
|
|
1152
|
-
* Get current provider information
|
|
1153
|
-
*/
|
|
1154
|
-
getCurrentProviderInfo() {
|
|
1155
|
-
return this.providerManager.getCurrentProviderInfo();
|
|
1196
|
+
return currentProvider.ethereum;
|
|
1156
1197
|
}
|
|
1198
|
+
// ===== CONNECTION MANAGEMENT =====
|
|
1157
1199
|
/**
|
|
1158
|
-
*
|
|
1200
|
+
* Connect to the wallet
|
|
1159
1201
|
*/
|
|
1160
|
-
async
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
return false;
|
|
1169
|
-
return new Promise((resolve) => {
|
|
1170
|
-
setTimeout(async () => {
|
|
1171
|
-
const result = await isInstalled(retries - 1, timeAccumulated + 100);
|
|
1172
|
-
resolve(result);
|
|
1173
|
-
}, 100);
|
|
1202
|
+
async connect(options) {
|
|
1203
|
+
debug.info(DebugCategory.BROWSER_SDK, "Starting connection", options);
|
|
1204
|
+
try {
|
|
1205
|
+
const result = await this.providerManager.connect(options);
|
|
1206
|
+
debug.info(DebugCategory.BROWSER_SDK, "Connection successful", {
|
|
1207
|
+
addressCount: result.addresses.length,
|
|
1208
|
+
walletId: result.walletId,
|
|
1209
|
+
status: result.status
|
|
1174
1210
|
});
|
|
1175
|
-
|
|
1176
|
-
|
|
1211
|
+
return result;
|
|
1212
|
+
} catch (error) {
|
|
1213
|
+
debug.error(DebugCategory.BROWSER_SDK, "Connection failed", { error: error.message });
|
|
1214
|
+
throw error;
|
|
1215
|
+
}
|
|
1177
1216
|
}
|
|
1178
1217
|
/**
|
|
1179
1218
|
* Disconnect from the wallet
|
|
1180
1219
|
*/
|
|
1181
1220
|
async disconnect() {
|
|
1182
|
-
|
|
1221
|
+
debug.info(DebugCategory.BROWSER_SDK, "Disconnecting");
|
|
1222
|
+
try {
|
|
1223
|
+
await this.providerManager.disconnect();
|
|
1224
|
+
debug.info(DebugCategory.BROWSER_SDK, "Disconnection successful");
|
|
1225
|
+
} catch (error) {
|
|
1226
|
+
debug.error(DebugCategory.BROWSER_SDK, "Disconnection failed", { error: error.message });
|
|
1227
|
+
throw error;
|
|
1228
|
+
}
|
|
1183
1229
|
}
|
|
1184
1230
|
/**
|
|
1185
|
-
*
|
|
1186
|
-
* @param message - Message string to sign
|
|
1187
|
-
* @param networkId - Network identifier
|
|
1188
|
-
* @returns Signature string
|
|
1231
|
+
* Switch between provider types (injected vs embedded)
|
|
1189
1232
|
*/
|
|
1190
|
-
async
|
|
1191
|
-
debug.info(DebugCategory.BROWSER_SDK, "
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1233
|
+
async switchProvider(type, options) {
|
|
1234
|
+
debug.info(DebugCategory.BROWSER_SDK, "Switching provider", { type, options });
|
|
1235
|
+
try {
|
|
1236
|
+
await this.providerManager.switchProvider(type, options);
|
|
1237
|
+
debug.info(DebugCategory.BROWSER_SDK, "Provider switch successful", { type });
|
|
1238
|
+
} catch (error) {
|
|
1239
|
+
debug.error(DebugCategory.BROWSER_SDK, "Provider switch failed", {
|
|
1240
|
+
type,
|
|
1241
|
+
error: error.message
|
|
1242
|
+
});
|
|
1243
|
+
throw error;
|
|
1244
|
+
}
|
|
1202
1245
|
}
|
|
1246
|
+
// ===== STATE QUERIES =====
|
|
1203
1247
|
/**
|
|
1204
|
-
*
|
|
1205
|
-
* @param params - Transaction parameters with native transaction object
|
|
1206
|
-
* @returns Transaction result
|
|
1248
|
+
* Check if the SDK is connected to a wallet
|
|
1207
1249
|
*/
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
networkId: params.networkId
|
|
1211
|
-
});
|
|
1212
|
-
const result = await this.providerManager.signAndSendTransaction(params);
|
|
1213
|
-
debug.info(DebugCategory.BROWSER_SDK, "Transaction signed and sent successfully", {
|
|
1214
|
-
networkId: params.networkId,
|
|
1215
|
-
result
|
|
1216
|
-
});
|
|
1217
|
-
return result;
|
|
1250
|
+
isConnected() {
|
|
1251
|
+
return this.providerManager.isConnected();
|
|
1218
1252
|
}
|
|
1219
1253
|
/**
|
|
1220
|
-
* Get wallet addresses
|
|
1254
|
+
* Get all connected wallet addresses
|
|
1221
1255
|
*/
|
|
1222
1256
|
getAddresses() {
|
|
1223
1257
|
return this.providerManager.getAddresses();
|
|
1224
1258
|
}
|
|
1225
1259
|
/**
|
|
1226
|
-
*
|
|
1260
|
+
* Get information about the current provider
|
|
1227
1261
|
*/
|
|
1228
|
-
|
|
1229
|
-
return this.providerManager.
|
|
1262
|
+
getCurrentProviderInfo() {
|
|
1263
|
+
return this.providerManager.getCurrentProviderInfo();
|
|
1230
1264
|
}
|
|
1231
1265
|
/**
|
|
1232
|
-
* Get the
|
|
1266
|
+
* Get the wallet ID (for embedded wallets)
|
|
1233
1267
|
*/
|
|
1234
1268
|
getWalletId() {
|
|
1235
1269
|
return this.providerManager.getWalletId();
|
|
1236
1270
|
}
|
|
1271
|
+
// ===== UTILITY METHODS =====
|
|
1272
|
+
/**
|
|
1273
|
+
* Check if Phantom extension is installed
|
|
1274
|
+
*/
|
|
1275
|
+
static isPhantomInstalled() {
|
|
1276
|
+
return isPhantomExtensionInstalled();
|
|
1277
|
+
}
|
|
1237
1278
|
/**
|
|
1238
1279
|
* Add event listener for provider events (connect, connect_start, connect_error, disconnect, error)
|
|
1239
1280
|
* Works with both embedded and injected providers
|
|
@@ -1315,13 +1356,101 @@ var BrowserSDK = class {
|
|
|
1315
1356
|
this.setDebugCallback(config.callback);
|
|
1316
1357
|
}
|
|
1317
1358
|
}
|
|
1359
|
+
// ===== AUTO-CONFIRM METHODS (Injected Provider Only) =====
|
|
1360
|
+
/**
|
|
1361
|
+
* Enable auto-confirm for transactions
|
|
1362
|
+
* Only available for injected providers
|
|
1363
|
+
*/
|
|
1364
|
+
async enableAutoConfirm(params) {
|
|
1365
|
+
debug.info(DebugCategory.BROWSER_SDK, "Enabling auto-confirm", { params });
|
|
1366
|
+
const currentProvider = this.providerManager.getCurrentProvider();
|
|
1367
|
+
if (!currentProvider) {
|
|
1368
|
+
throw new Error("No provider available. Call connect() first.");
|
|
1369
|
+
}
|
|
1370
|
+
if (!("enableAutoConfirm" in currentProvider)) {
|
|
1371
|
+
throw new Error("Auto-confirm is only available for injected providers");
|
|
1372
|
+
}
|
|
1373
|
+
try {
|
|
1374
|
+
const result = await currentProvider.enableAutoConfirm(params);
|
|
1375
|
+
debug.info(DebugCategory.BROWSER_SDK, "Auto-confirm enabled successfully", { result });
|
|
1376
|
+
return result;
|
|
1377
|
+
} catch (error) {
|
|
1378
|
+
debug.error(DebugCategory.BROWSER_SDK, "Failed to enable auto-confirm", { error: error.message });
|
|
1379
|
+
throw error;
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
/**
|
|
1383
|
+
* Disable auto-confirm for transactions
|
|
1384
|
+
* Only available for injected providers
|
|
1385
|
+
*/
|
|
1386
|
+
async disableAutoConfirm() {
|
|
1387
|
+
debug.info(DebugCategory.BROWSER_SDK, "Disabling auto-confirm");
|
|
1388
|
+
const currentProvider = this.providerManager.getCurrentProvider();
|
|
1389
|
+
if (!currentProvider) {
|
|
1390
|
+
throw new Error("No provider available. Call connect() first.");
|
|
1391
|
+
}
|
|
1392
|
+
if (!("disableAutoConfirm" in currentProvider)) {
|
|
1393
|
+
throw new Error("Auto-confirm is only available for injected providers");
|
|
1394
|
+
}
|
|
1395
|
+
try {
|
|
1396
|
+
await currentProvider.disableAutoConfirm();
|
|
1397
|
+
debug.info(DebugCategory.BROWSER_SDK, "Auto-confirm disabled successfully");
|
|
1398
|
+
} catch (error) {
|
|
1399
|
+
debug.error(DebugCategory.BROWSER_SDK, "Failed to disable auto-confirm", { error: error.message });
|
|
1400
|
+
throw error;
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
/**
|
|
1404
|
+
* Get current auto-confirm status
|
|
1405
|
+
* Only available for injected providers
|
|
1406
|
+
*/
|
|
1407
|
+
async getAutoConfirmStatus() {
|
|
1408
|
+
debug.info(DebugCategory.BROWSER_SDK, "Getting auto-confirm status");
|
|
1409
|
+
const currentProvider = this.providerManager.getCurrentProvider();
|
|
1410
|
+
if (!currentProvider) {
|
|
1411
|
+
throw new Error("No provider available. Call connect() first.");
|
|
1412
|
+
}
|
|
1413
|
+
if (!("getAutoConfirmStatus" in currentProvider)) {
|
|
1414
|
+
throw new Error("Auto-confirm is only available for injected providers");
|
|
1415
|
+
}
|
|
1416
|
+
try {
|
|
1417
|
+
const result = await currentProvider.getAutoConfirmStatus();
|
|
1418
|
+
debug.info(DebugCategory.BROWSER_SDK, "Got auto-confirm status", { result });
|
|
1419
|
+
return result;
|
|
1420
|
+
} catch (error) {
|
|
1421
|
+
debug.error(DebugCategory.BROWSER_SDK, "Failed to get auto-confirm status", { error: error.message });
|
|
1422
|
+
throw error;
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
/**
|
|
1426
|
+
* Get supported chains for auto-confirm
|
|
1427
|
+
* Only available for injected providers
|
|
1428
|
+
*/
|
|
1429
|
+
async getSupportedAutoConfirmChains() {
|
|
1430
|
+
debug.info(DebugCategory.BROWSER_SDK, "Getting supported auto-confirm chains");
|
|
1431
|
+
const currentProvider = this.providerManager.getCurrentProvider();
|
|
1432
|
+
if (!currentProvider) {
|
|
1433
|
+
throw new Error("No provider available. Call connect() first.");
|
|
1434
|
+
}
|
|
1435
|
+
if (!("getSupportedAutoConfirmChains" in currentProvider)) {
|
|
1436
|
+
throw new Error("Auto-confirm is only available for injected providers");
|
|
1437
|
+
}
|
|
1438
|
+
try {
|
|
1439
|
+
const result = await currentProvider.getSupportedAutoConfirmChains();
|
|
1440
|
+
debug.info(DebugCategory.BROWSER_SDK, "Got supported auto-confirm chains", { result });
|
|
1441
|
+
return result;
|
|
1442
|
+
} catch (error) {
|
|
1443
|
+
debug.error(DebugCategory.BROWSER_SDK, "Failed to get supported auto-confirm chains", { error: error.message });
|
|
1444
|
+
throw error;
|
|
1445
|
+
}
|
|
1446
|
+
}
|
|
1318
1447
|
};
|
|
1319
1448
|
|
|
1320
1449
|
// src/types.ts
|
|
1321
1450
|
import { AddressType as AddressType2 } from "@phantom/client";
|
|
1322
1451
|
|
|
1323
1452
|
// src/index.ts
|
|
1324
|
-
import { NetworkId } from "@phantom/constants";
|
|
1453
|
+
import { NetworkId as NetworkId3 } from "@phantom/constants";
|
|
1325
1454
|
import { AddressType as AddressType3 } from "@phantom/client";
|
|
1326
1455
|
export {
|
|
1327
1456
|
AddressType3 as AddressType,
|
|
@@ -1330,7 +1459,7 @@ export {
|
|
|
1330
1459
|
DEFAULT_WALLET_API_URL,
|
|
1331
1460
|
DebugCategory,
|
|
1332
1461
|
DebugLevel,
|
|
1333
|
-
NetworkId,
|
|
1462
|
+
NetworkId3 as NetworkId,
|
|
1334
1463
|
debug,
|
|
1335
1464
|
detectBrowser,
|
|
1336
1465
|
getBrowserDisplayName,
|