@phantom/browser-sdk 0.0.10 → 0.2.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/dist/index.mjs CHANGED
@@ -1,13 +1,772 @@
1
- import "./chunk-GV6AIHPN.mjs";
1
+ // src/providers/injected/index.ts
2
+ import { AddressType } from "@phantom/client";
3
+ import { createPhantom, createExtensionPlugin } from "@phantom/browser-injected-sdk";
4
+ import { createSolanaPlugin } from "@phantom/browser-injected-sdk/solana";
5
+ import { createEthereumPlugin } from "@phantom/browser-injected-sdk/ethereum";
6
+ var InjectedProvider = class {
7
+ constructor(config) {
8
+ this.connected = false;
9
+ this.addresses = [];
10
+ this.addressTypes = config.addressTypes || [AddressType.solana, AddressType.ethereum];
11
+ const plugins = [createExtensionPlugin()];
12
+ if (this.addressTypes.includes(AddressType.solana)) {
13
+ plugins.push(createSolanaPlugin());
14
+ }
15
+ if (this.addressTypes.includes(AddressType.ethereum)) {
16
+ plugins.push(createEthereumPlugin());
17
+ }
18
+ this.phantom = createPhantom({ plugins });
19
+ }
20
+ async connect() {
21
+ if (!this.phantom.extension.isInstalled()) {
22
+ throw new Error("Phantom wallet not found");
23
+ }
24
+ const connectedAddresses = [];
25
+ if (this.addressTypes.includes(AddressType.solana)) {
26
+ try {
27
+ const publicKey = await this.phantom.solana.connect();
28
+ if (publicKey) {
29
+ connectedAddresses.push({
30
+ addressType: AddressType.solana,
31
+ address: publicKey
32
+ });
33
+ }
34
+ } catch (err) {
35
+ console.error("Failed to connect Solana:", err);
36
+ }
37
+ }
38
+ if (this.addressTypes.includes(AddressType.ethereum)) {
39
+ try {
40
+ const accounts = await this.phantom.ethereum.connect();
41
+ if (accounts && accounts.length > 0) {
42
+ connectedAddresses.push(
43
+ ...accounts.map((address) => ({
44
+ addressType: AddressType.ethereum,
45
+ address
46
+ }))
47
+ );
48
+ }
49
+ } catch (err) {
50
+ console.error("Failed to connect Ethereum:", err);
51
+ }
52
+ }
53
+ if (connectedAddresses.length === 0) {
54
+ throw new Error("Failed to connect to any supported wallet provider");
55
+ }
56
+ this.addresses = connectedAddresses;
57
+ this.connected = true;
58
+ return {
59
+ addresses: this.addresses
60
+ // walletId is not applicable for injected providers
61
+ };
62
+ }
63
+ async disconnect() {
64
+ if (this.addressTypes.includes(AddressType.solana)) {
65
+ try {
66
+ await this.phantom.solana.disconnect();
67
+ } catch (err) {
68
+ console.error("Failed to disconnect Solana:", err);
69
+ }
70
+ }
71
+ if (this.addressTypes.includes(AddressType.ethereum)) {
72
+ try {
73
+ await this.phantom.ethereum.disconnect();
74
+ } catch (err) {
75
+ console.error("Failed to disconnect Ethereum:", err);
76
+ }
77
+ }
78
+ this.connected = false;
79
+ this.addresses = [];
80
+ }
81
+ async signMessage(params) {
82
+ if (!this.connected) {
83
+ throw new Error("Wallet not connected");
84
+ }
85
+ const networkPrefix = params.networkId.split(":")[0].toLowerCase();
86
+ if (networkPrefix === "solana") {
87
+ const { signature } = await this.phantom.solana.signMessage(new TextEncoder().encode(params.message));
88
+ return Array.from(signature).map((b) => b.toString(16).padStart(2, "0")).join("");
89
+ } else if (networkPrefix === "ethereum" || networkPrefix === "polygon" || networkPrefix === "eip155") {
90
+ const address = this.addresses.find((addr) => addr.addressType === AddressType.ethereum)?.address;
91
+ if (!address) {
92
+ throw new Error("No address available");
93
+ }
94
+ const signature = await this.phantom.ethereum.signPersonalMessage(params.message, address);
95
+ return signature;
96
+ }
97
+ throw new Error(`Network ${params.networkId} is not supported for injected wallets`);
98
+ }
99
+ async signAndSendTransaction(params) {
100
+ if (!this.connected) {
101
+ throw new Error("Wallet not connected");
102
+ }
103
+ const networkPrefix = params.networkId.split(":")[0].toLowerCase();
104
+ if (networkPrefix === "solana") {
105
+ const transaction = params.transaction;
106
+ const result = await this.phantom.solana.signAndSendTransaction(transaction);
107
+ return {
108
+ rawTransaction: result.signature
109
+ };
110
+ } else if (networkPrefix === "ethereum" || networkPrefix === "polygon" || networkPrefix === "eip155") {
111
+ const toHex = (value) => {
112
+ if (!value)
113
+ return void 0;
114
+ if (typeof value === "string" && value.startsWith("0x"))
115
+ return value;
116
+ if (typeof value === "string")
117
+ return value;
118
+ return "0x" + value.toString(16);
119
+ };
120
+ const txRequest = {
121
+ to: params.transaction.to,
122
+ value: params.transaction.value ? toHex(params.transaction.value) : "0x0",
123
+ gas: toHex(params.transaction.gas),
124
+ gasPrice: toHex(params.transaction.gasPrice),
125
+ maxFeePerGas: toHex(params.transaction.maxFeePerGas),
126
+ maxPriorityFeePerGas: toHex(params.transaction.maxPriorityFeePerGas),
127
+ data: params.transaction.data || "0x"
128
+ };
129
+ const txHash = await this.phantom.ethereum.sendTransaction(txRequest);
130
+ return {
131
+ rawTransaction: txHash
132
+ };
133
+ }
134
+ throw new Error(`Network ${params.networkId} is not supported for injected wallets`);
135
+ }
136
+ getAddresses() {
137
+ return this.addresses;
138
+ }
139
+ isConnected() {
140
+ return this.connected;
141
+ }
142
+ };
2
143
 
3
- // src/index.ts
4
- function createPhantom({ plugins = [] }) {
5
- const phantom = {};
6
- for (const plugin of plugins) {
7
- phantom[plugin.name] = plugin.create();
144
+ // src/providers/embedded/index.ts
145
+ import { PhantomClient, generateKeyPair } from "@phantom/client";
146
+ import { ApiKeyStamper } from "@phantom/api-key-stamper";
147
+
148
+ // src/providers/embedded/storage.ts
149
+ var IndexedDBStorage = class {
150
+ constructor() {
151
+ this.dbName = "phantom-browser-sdk";
152
+ this.storeName = "sessions";
153
+ this.version = 1;
154
+ }
155
+ async getDB() {
156
+ return new Promise((resolve, reject) => {
157
+ const request = indexedDB.open(this.dbName, this.version);
158
+ request.onerror = () => reject(request.error);
159
+ request.onsuccess = () => resolve(request.result);
160
+ request.onupgradeneeded = (event) => {
161
+ const db = event.target.result;
162
+ if (!db.objectStoreNames.contains(this.storeName)) {
163
+ db.createObjectStore(this.storeName);
164
+ }
165
+ };
166
+ });
8
167
  }
9
- return phantom;
168
+ async getSession() {
169
+ const db = await this.getDB();
170
+ return new Promise((resolve, reject) => {
171
+ const transaction = db.transaction([this.storeName], "readonly");
172
+ const store = transaction.objectStore(this.storeName);
173
+ const request = store.get("currentSession");
174
+ request.onsuccess = () => resolve(request.result || null);
175
+ request.onerror = () => reject(request.error);
176
+ });
177
+ }
178
+ async saveSession(session) {
179
+ const db = await this.getDB();
180
+ return new Promise((resolve, reject) => {
181
+ const transaction = db.transaction([this.storeName], "readwrite");
182
+ const store = transaction.objectStore(this.storeName);
183
+ const request = store.put(session, "currentSession");
184
+ request.onsuccess = () => resolve();
185
+ request.onerror = () => reject(request.error);
186
+ });
187
+ }
188
+ async clearSession() {
189
+ const db = await this.getDB();
190
+ return new Promise((resolve, reject) => {
191
+ const transaction = db.transaction([this.storeName], "readwrite");
192
+ const store = transaction.objectStore(this.storeName);
193
+ const request = store.delete("currentSession");
194
+ request.onsuccess = () => resolve();
195
+ request.onerror = () => reject(request.error);
196
+ });
197
+ }
198
+ };
199
+
200
+ // src/providers/embedded/auth.ts
201
+ var IframeAuth = class {
202
+ async authenticate(_options) {
203
+ await new Promise((resolve) => setTimeout(resolve, 100));
204
+ return {
205
+ walletId: `wallet-${Date.now()}`
206
+ };
207
+ }
208
+ };
209
+
210
+ // src/parsers/index.ts
211
+ import { base64urlEncode, stringToBase64url } from "@phantom/base64url";
212
+
213
+ // src/polyfills.ts
214
+ import { Buffer } from "buffer";
215
+ import { base64url } from "jose";
216
+
217
+ // src/parsers/index.ts
218
+ function parseMessage(message) {
219
+ return {
220
+ base64url: stringToBase64url(message)
221
+ };
10
222
  }
223
+ async function parseTransaction(transaction, networkId) {
224
+ const networkPrefix = networkId.split(":")[0].toLowerCase();
225
+ switch (networkPrefix) {
226
+ case "solana":
227
+ return parseSolanaTransaction(transaction);
228
+ case "ethereum":
229
+ case "polygon":
230
+ return parseEVMTransaction(transaction);
231
+ case "sui":
232
+ return await parseSuiTransaction(transaction);
233
+ case "bitcoin":
234
+ return parseBitcoinTransaction(transaction);
235
+ default:
236
+ throw new Error(`Unsupported network: ${networkPrefix}`);
237
+ }
238
+ }
239
+ function parseSolanaTransaction(transaction) {
240
+ if (transaction?.messageBytes != null) {
241
+ return {
242
+ base64url: base64urlEncode(transaction.messageBytes),
243
+ originalFormat: "@solana/kit"
244
+ };
245
+ }
246
+ if (typeof transaction?.serialize === "function") {
247
+ const serialized = transaction.serialize();
248
+ return {
249
+ base64url: base64urlEncode(serialized),
250
+ originalFormat: "@solana/web3.js"
251
+ };
252
+ }
253
+ if (transaction instanceof Uint8Array) {
254
+ return {
255
+ base64url: base64urlEncode(transaction),
256
+ originalFormat: "bytes"
257
+ };
258
+ }
259
+ throw new Error("Unsupported Solana transaction format");
260
+ }
261
+ function parseEVMTransaction(transaction) {
262
+ if (transaction && typeof transaction === "object" && (transaction.to || transaction.data)) {
263
+ const bytes = new TextEncoder().encode(
264
+ JSON.stringify(transaction, (_key, value) => typeof value === "bigint" ? value.toString() : value)
265
+ );
266
+ return {
267
+ base64url: base64urlEncode(bytes),
268
+ originalFormat: "viem"
269
+ };
270
+ }
271
+ if (transaction?.serialize && typeof transaction.serialize === "function") {
272
+ const serialized = transaction.serialize();
273
+ const bytes = new Uint8Array(Buffer.from(serialized.slice(2), "hex"));
274
+ return {
275
+ base64url: base64urlEncode(bytes),
276
+ originalFormat: "ethers"
277
+ };
278
+ }
279
+ if (transaction instanceof Uint8Array) {
280
+ return {
281
+ base64url: base64urlEncode(transaction),
282
+ originalFormat: "bytes"
283
+ };
284
+ }
285
+ if (typeof transaction === "string" && transaction.startsWith("0x")) {
286
+ const bytes = new Uint8Array(Buffer.from(transaction.slice(2), "hex"));
287
+ return {
288
+ base64url: base64urlEncode(bytes),
289
+ originalFormat: "hex"
290
+ };
291
+ }
292
+ throw new Error("Unsupported EVM transaction format");
293
+ }
294
+ async function parseSuiTransaction(transaction) {
295
+ if (transaction?.serialize && typeof transaction.serialize === "function") {
296
+ const serialized = transaction.serialize();
297
+ return {
298
+ base64url: base64urlEncode(serialized),
299
+ originalFormat: "sui-sdk"
300
+ };
301
+ }
302
+ if (transaction instanceof Uint8Array) {
303
+ return {
304
+ base64url: base64urlEncode(transaction),
305
+ originalFormat: "bytes"
306
+ };
307
+ }
308
+ if (transaction?.build && typeof transaction.build === "function") {
309
+ const built = await transaction.build();
310
+ if (built?.serialize && typeof built.serialize === "function") {
311
+ const serialized = built.serialize();
312
+ return {
313
+ base64url: base64urlEncode(serialized),
314
+ originalFormat: "transaction-block"
315
+ };
316
+ }
317
+ }
318
+ throw new Error("Unsupported Sui transaction format");
319
+ }
320
+ function parseBitcoinTransaction(transaction) {
321
+ if (transaction?.toBuffer && typeof transaction.toBuffer === "function") {
322
+ const buffer = transaction.toBuffer();
323
+ return {
324
+ base64url: base64urlEncode(new Uint8Array(buffer)),
325
+ originalFormat: "bitcoinjs-lib"
326
+ };
327
+ }
328
+ if (transaction instanceof Uint8Array) {
329
+ return {
330
+ base64url: base64urlEncode(transaction),
331
+ originalFormat: "bytes"
332
+ };
333
+ }
334
+ if (typeof transaction === "string") {
335
+ const bytes = new Uint8Array(Buffer.from(transaction, "hex"));
336
+ return {
337
+ base64url: base64urlEncode(bytes),
338
+ originalFormat: "hex"
339
+ };
340
+ }
341
+ throw new Error("Unsupported Bitcoin transaction format");
342
+ }
343
+
344
+ // src/providers/embedded/index.ts
345
+ var EmbeddedProvider = class {
346
+ constructor(config) {
347
+ this.client = null;
348
+ this.walletId = null;
349
+ this.addresses = [];
350
+ this.config = config;
351
+ this.storage = new IndexedDBStorage();
352
+ config.solanaProvider;
353
+ }
354
+ async connect() {
355
+ let session = await this.storage.getSession();
356
+ if (!session) {
357
+ const keypair = generateKeyPair();
358
+ const stamper2 = new ApiKeyStamper({
359
+ apiSecretKey: keypair.secretKey
360
+ });
361
+ const tempClient = new PhantomClient(
362
+ {
363
+ apiBaseUrl: this.config.apiBaseUrl
364
+ },
365
+ stamper2
366
+ );
367
+ const uid = Date.now();
368
+ const organizationName = `${this.config.organizationId}-${uid}`;
369
+ const { organizationId } = await tempClient.createOrganization(organizationName, keypair);
370
+ let walletId;
371
+ if (this.config.embeddedWalletType === "user-wallet") {
372
+ const auth = new IframeAuth();
373
+ const authResult = await auth.authenticate({
374
+ iframeUrl: this.config.authUrl || "https://auth-flow.phantom.app",
375
+ organizationId,
376
+ parentOrganizationId: this.config.organizationId,
377
+ embeddedWalletType: this.config.embeddedWalletType
378
+ });
379
+ walletId = authResult.walletId;
380
+ } else {
381
+ const wallet = await tempClient.createWallet(`Wallet ${Date.now()}`);
382
+ walletId = wallet.walletId;
383
+ }
384
+ session = {
385
+ walletId,
386
+ organizationId: this.config.organizationId,
387
+ keypair
388
+ };
389
+ await this.storage.saveSession(session);
390
+ }
391
+ const stamper = new ApiKeyStamper({
392
+ apiSecretKey: session.keypair.secretKey
393
+ });
394
+ this.client = new PhantomClient(
395
+ {
396
+ apiBaseUrl: this.config.apiBaseUrl,
397
+ organizationId: session.organizationId
398
+ },
399
+ stamper
400
+ );
401
+ this.walletId = session.walletId;
402
+ const addresses = await this.client.getWalletAddresses(session.walletId);
403
+ this.addresses = addresses.filter((addr) => this.config.addressTypes.some((type) => type === addr.addressType)).map((addr) => ({
404
+ addressType: addr.addressType,
405
+ address: addr.address
406
+ }));
407
+ return {
408
+ walletId: this.walletId,
409
+ addresses: this.addresses
410
+ };
411
+ }
412
+ async disconnect() {
413
+ await this.storage.clearSession();
414
+ this.client = null;
415
+ this.walletId = null;
416
+ this.addresses = [];
417
+ }
418
+ async signMessage(params) {
419
+ if (!this.client || !this.walletId) {
420
+ throw new Error("Not connected");
421
+ }
422
+ const parsedMessage = parseMessage(params.message);
423
+ return await this.client.signMessage(this.walletId, parsedMessage.base64url, params.networkId);
424
+ }
425
+ async signAndSendTransaction(params) {
426
+ if (!this.client || !this.walletId) {
427
+ throw new Error("Not connected");
428
+ }
429
+ const parsedTransaction = await parseTransaction(params.transaction, params.networkId);
430
+ return await this.client.signAndSendTransaction(this.walletId, parsedTransaction.base64url, params.networkId);
431
+ }
432
+ getAddresses() {
433
+ return this.addresses;
434
+ }
435
+ isConnected() {
436
+ return this.client !== null && this.walletId !== null;
437
+ }
438
+ };
439
+
440
+ // src/ProviderManager.ts
441
+ var ProviderManager = class {
442
+ constructor(config) {
443
+ this.providers = /* @__PURE__ */ new Map();
444
+ this.currentProvider = null;
445
+ this.currentProviderKey = null;
446
+ this.walletId = null;
447
+ this.config = config;
448
+ this.setDefaultProvider();
449
+ }
450
+ /**
451
+ * Switch to a different provider type
452
+ */
453
+ switchProvider(type, options) {
454
+ if (options?.embeddedWalletType && !["app-wallet", "user-wallet"].includes(options.embeddedWalletType)) {
455
+ throw new Error(
456
+ `Invalid embeddedWalletType: ${options.embeddedWalletType}. Must be "app-wallet" or "user-wallet".`
457
+ );
458
+ }
459
+ const key = this.getProviderKey(type, options?.embeddedWalletType);
460
+ if (!this.providers.has(key)) {
461
+ this.createProvider(type, options?.embeddedWalletType);
462
+ }
463
+ this.currentProvider = this.providers.get(key);
464
+ this.currentProviderKey = key;
465
+ this.walletId = null;
466
+ return this.currentProvider;
467
+ }
468
+ /**
469
+ * Get the current active provider
470
+ */
471
+ getCurrentProvider() {
472
+ return this.currentProvider;
473
+ }
474
+ /**
475
+ * Get current provider type and options
476
+ */
477
+ getCurrentProviderInfo() {
478
+ if (!this.currentProviderKey)
479
+ return null;
480
+ const [type, embeddedWalletType] = this.currentProviderKey.split("-");
481
+ return {
482
+ type,
483
+ embeddedWalletType
484
+ };
485
+ }
486
+ /**
487
+ * Connect using the current provider
488
+ */
489
+ async connect() {
490
+ if (!this.currentProvider) {
491
+ throw new Error("No provider selected");
492
+ }
493
+ const result = await this.currentProvider.connect();
494
+ this.walletId = result.walletId || null;
495
+ this.saveProviderPreference();
496
+ return result;
497
+ }
498
+ /**
499
+ * Disconnect from current provider
500
+ */
501
+ async disconnect() {
502
+ if (!this.currentProvider)
503
+ return;
504
+ await this.currentProvider.disconnect();
505
+ this.walletId = null;
506
+ }
507
+ /**
508
+ * Sign a message using current provider
509
+ */
510
+ async signMessage(params) {
511
+ if (!this.currentProvider) {
512
+ throw new Error("No provider connected");
513
+ }
514
+ return this.currentProvider.signMessage(params);
515
+ }
516
+ /**
517
+ * Sign and send transaction using current provider
518
+ */
519
+ async signAndSendTransaction(params) {
520
+ if (!this.currentProvider) {
521
+ throw new Error("No provider connected");
522
+ }
523
+ return this.currentProvider.signAndSendTransaction(params);
524
+ }
525
+ /**
526
+ * Get addresses from current provider
527
+ */
528
+ getAddresses() {
529
+ if (!this.currentProvider) {
530
+ return [];
531
+ }
532
+ return this.currentProvider.getAddresses();
533
+ }
534
+ /**
535
+ * Check if current provider is connected
536
+ */
537
+ isConnected() {
538
+ return this.currentProvider?.isConnected() ?? false;
539
+ }
540
+ /**
541
+ * Get current wallet ID
542
+ */
543
+ getWalletId() {
544
+ return this.walletId;
545
+ }
546
+ /**
547
+ * Set default provider based on initial config
548
+ */
549
+ setDefaultProvider() {
550
+ const defaultType = this.config.providerType || "embedded";
551
+ const defaultEmbeddedType = this.config.embeddedWalletType || "app-wallet";
552
+ this.createProvider(defaultType, defaultEmbeddedType);
553
+ this.switchProvider(defaultType, { embeddedWalletType: defaultEmbeddedType });
554
+ }
555
+ /**
556
+ * Create a provider instance
557
+ */
558
+ createProvider(type, embeddedWalletType) {
559
+ const key = this.getProviderKey(type, embeddedWalletType);
560
+ if (this.providers.has(key))
561
+ return;
562
+ let provider;
563
+ if (type === "injected") {
564
+ provider = new InjectedProvider({
565
+ solanaProvider: this.config.solanaProvider || "web3js",
566
+ addressTypes: this.config.addressTypes || []
567
+ });
568
+ } else {
569
+ if (!this.config.apiBaseUrl || !this.config.organizationId) {
570
+ throw new Error("apiBaseUrl and organizationId are required for embedded provider");
571
+ }
572
+ provider = new EmbeddedProvider({
573
+ apiBaseUrl: this.config.apiBaseUrl,
574
+ organizationId: this.config.organizationId,
575
+ authUrl: this.config.authUrl,
576
+ embeddedWalletType: embeddedWalletType || "app-wallet",
577
+ addressTypes: this.config.addressTypes || [],
578
+ solanaProvider: this.config.solanaProvider || "web3js"
579
+ });
580
+ }
581
+ this.providers.set(key, provider);
582
+ }
583
+ /**
584
+ * Generate a unique key for provider instances
585
+ */
586
+ getProviderKey(type, embeddedWalletType) {
587
+ if (type === "injected") {
588
+ return "injected";
589
+ }
590
+ return `embedded-${embeddedWalletType || "app-wallet"}`;
591
+ }
592
+ /**
593
+ * Save provider preference to localStorage
594
+ */
595
+ saveProviderPreference() {
596
+ try {
597
+ const preference = this.getCurrentProviderInfo();
598
+ if (preference) {
599
+ localStorage.setItem("phantom-provider-preference", JSON.stringify(preference));
600
+ }
601
+ } catch (error) {
602
+ console.error("Failed to save provider preference:", error);
603
+ }
604
+ }
605
+ /**
606
+ * Restore provider preference from localStorage
607
+ */
608
+ /*
609
+ private restoreProviderPreference(): void {
610
+ try {
611
+ const saved = localStorage.getItem("phantom-provider-preference");
612
+ if (saved) {
613
+ const preference: ProviderPreference = JSON.parse(saved);
614
+ this.switchProvider(preference.type, {
615
+ embeddedWalletType: preference.embeddedWalletType,
616
+ });
617
+ }
618
+ } catch (error) {
619
+ // Ignore localStorage errors - just use default provider
620
+ console.error("Failed to restore provider preference:", error);
621
+ }
622
+ }*/
623
+ };
624
+
625
+ // src/BrowserSDK.ts
626
+ import { isPhantomExtensionInstalled } from "@phantom/browser-injected-sdk";
627
+ var BrowserSDK = class {
628
+ constructor(config) {
629
+ if (!["injected", "embedded"].includes(config.providerType)) {
630
+ throw new Error(`Invalid providerType: ${config.providerType}. Must be "injected" or "embedded".`);
631
+ }
632
+ const embeddedWalletType = config.embeddedWalletType || "app-wallet";
633
+ if (config.providerType === "embedded" && !["app-wallet", "user-wallet"].includes(embeddedWalletType)) {
634
+ throw new Error(
635
+ `Invalid embeddedWalletType: ${config.embeddedWalletType}. Must be "app-wallet" or "user-wallet".`
636
+ );
637
+ }
638
+ config.embeddedWalletType = embeddedWalletType;
639
+ this.config = config;
640
+ this.providerManager = new ProviderManager(config);
641
+ }
642
+ /**
643
+ * Connect to the wallet with optional provider switching
644
+ */
645
+ async connect(options) {
646
+ if (options?.providerType) {
647
+ if (!["injected", "embedded"].includes(options.providerType)) {
648
+ throw new Error(`Invalid providerType: ${options.providerType}. Must be "injected" or "embedded".`);
649
+ }
650
+ if (options.embeddedWalletType && !["app-wallet", "user-wallet"].includes(options.embeddedWalletType)) {
651
+ throw new Error(
652
+ `Invalid embeddedWalletType: ${options.embeddedWalletType}. Must be "app-wallet" or "user-wallet".`
653
+ );
654
+ }
655
+ await this.providerManager.switchProvider(options.providerType, {
656
+ embeddedWalletType: options.embeddedWalletType
657
+ });
658
+ }
659
+ return this.providerManager.connect();
660
+ }
661
+ /**
662
+ * Switch to a different provider type
663
+ */
664
+ async switchProvider(type, options) {
665
+ if (!["injected", "embedded"].includes(type)) {
666
+ throw new Error(`Invalid providerType: ${type}. Must be "injected" or "embedded".`);
667
+ }
668
+ await this.providerManager.switchProvider(type, options);
669
+ }
670
+ /**
671
+ * Get current provider information
672
+ */
673
+ getCurrentProviderInfo() {
674
+ return this.providerManager.getCurrentProviderInfo();
675
+ }
676
+ /**
677
+ * Wait for Phantom extension to become available
678
+ */
679
+ async waitForPhantomExtension(timeoutMs) {
680
+ const isInstalled = async (retries = 3, timeAccumulated = 0) => {
681
+ const installed = isPhantomExtensionInstalled();
682
+ if (installed)
683
+ return true;
684
+ if (retries <= 0)
685
+ return false;
686
+ if (timeAccumulated >= (timeoutMs || 3e3))
687
+ return false;
688
+ return new Promise((resolve) => {
689
+ setTimeout(async () => {
690
+ const result = await isInstalled(retries - 1, timeAccumulated + 100);
691
+ resolve(result);
692
+ }, 100);
693
+ });
694
+ };
695
+ return isInstalled();
696
+ }
697
+ /**
698
+ * Disconnect from the wallet
699
+ */
700
+ async disconnect() {
701
+ return this.providerManager.disconnect();
702
+ }
703
+ /**
704
+ * Sign a message
705
+ * @param message - Message string to sign
706
+ * @param networkId - Network identifier
707
+ * @returns Signature string
708
+ */
709
+ async signMessage(params) {
710
+ return this.providerManager.signMessage(params);
711
+ }
712
+ /**
713
+ * Sign and send a transaction
714
+ * @param params - Transaction parameters with native transaction object
715
+ * @returns Transaction result
716
+ */
717
+ async signAndSendTransaction(params) {
718
+ return this.providerManager.signAndSendTransaction(params);
719
+ }
720
+ /**
721
+ * Get wallet addresses
722
+ */
723
+ getAddresses() {
724
+ return this.providerManager.getAddresses();
725
+ }
726
+ /**
727
+ * Check if wallet is connected
728
+ */
729
+ isConnected() {
730
+ return this.providerManager.isConnected();
731
+ }
732
+ /**
733
+ * Get the current wallet ID (for embedded wallets)
734
+ */
735
+ getWalletId() {
736
+ return this.providerManager.getWalletId();
737
+ }
738
+ /**
739
+ * Create a user organization via your backend API
740
+ * @param params - Parameters including userId and any additional options
741
+ * @returns Organization creation result with organizationId
742
+ */
743
+ async createUserOrganization(params) {
744
+ if (!this.config.serverUrl) {
745
+ throw new Error("serverUrl is required in config to create user organizations");
746
+ }
747
+ try {
748
+ const response = await fetch(`${this.config.serverUrl}/organizations`, {
749
+ method: "POST",
750
+ headers: {
751
+ "Content-Type": "application/json"
752
+ },
753
+ body: JSON.stringify(params)
754
+ });
755
+ if (!response.ok) {
756
+ throw new Error(`Failed to create organization: ${response.status} ${response.statusText}`);
757
+ }
758
+ const result = await response.json();
759
+ return result;
760
+ } catch (error) {
761
+ throw new Error(`Error creating user organization: ${error instanceof Error ? error.message : "Unknown error"}`);
762
+ }
763
+ }
764
+ };
765
+
766
+ // src/index.ts
767
+ import { NetworkId, AddressType as AddressType2 } from "@phantom/client";
11
768
  export {
12
- createPhantom
769
+ AddressType2 as AddressType,
770
+ BrowserSDK,
771
+ NetworkId
13
772
  };