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