@phantom/browser-sdk 1.0.0-beta.21 → 1.0.0-beta.22

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 CHANGED
@@ -15,7 +15,7 @@ import { BrowserSDK, AddressType } from "@phantom/browser-sdk";
15
15
 
16
16
  // Connect to Phantom browser extension
17
17
  const sdk = new BrowserSDK({
18
- providerType: "injected",
18
+ providers: ["injected"], // Only allow browser extension
19
19
  addressTypes: [AddressType.solana, AddressType.ethereum],
20
20
  });
21
21
 
@@ -35,14 +35,14 @@ const solanaResult = await sdk.solana.signAndSendTransaction(mySolanaTransaction
35
35
  const ethResult = await sdk.ethereum.sendTransaction(myEthTransaction);
36
36
  ```
37
37
 
38
- ### Embedded Provider
38
+ ### Embedded Provider (Multiple Auth Methods)
39
39
 
40
40
  ```typescript
41
41
  import { BrowserSDK, AddressType } from "@phantom/browser-sdk";
42
42
 
43
- // Create embedded non-custodial wallet
43
+ // Create embedded non-custodial wallet with multiple auth providers
44
44
  const sdk = new BrowserSDK({
45
- providerType: "embedded",
45
+ providers: ["google", "apple", "phantom"], // Allow Google, Apple, and Phantom Login
46
46
  addressTypes: [AddressType.solana, AddressType.ethereum],
47
47
  appId: "your-app-id", // Get your app ID from phantom.com/portal
48
48
  });
@@ -72,14 +72,15 @@ After instantiating the SDK, use `sdk.connect()` to establish a connection to th
72
72
  ```typescript
73
73
  import { BrowserSDK, AddressType } from "@phantom/browser-sdk";
74
74
 
75
- // 1. Create SDK instance
75
+ // 1. Create SDK instance with allowed providers
76
76
  const sdk = new BrowserSDK({
77
- providerType: "injected",
77
+ providers: ["google", "apple", "phantom", "injected"], // Allowed auth providers
78
78
  addressTypes: [AddressType.solana, AddressType.ethereum],
79
+ appId: "your-app-id", // Required when using embedded providers
79
80
  });
80
81
 
81
- // 2. Connect to wallet (provider parameter is required)
82
- const { addresses } = await sdk.connect({ provider: "injected" });
82
+ // 2. Connect to wallet (provider parameter must be in allowed providers list)
83
+ const { addresses } = await sdk.connect({ provider: "google" });
83
84
  console.log("Connected addresses:", addresses);
84
85
 
85
86
  // 3. Use chain-specific methods
@@ -182,39 +183,50 @@ const accounts = await sdk.ethereum.getAccounts();
182
183
  const isConnected = sdk.ethereum.isConnected();
183
184
  ```
184
185
 
185
- ## Provider Types
186
+ ## Authentication Providers
187
+
188
+ The SDK supports multiple authentication providers that you configure via the `providers` array:
189
+
190
+ ### Available Providers
186
191
 
187
- ### Injected Provider
192
+ - **`"injected"`** - Phantom browser extension (no `appId` required)
193
+ - **`"google"`** - Google OAuth (requires `appId`)
194
+ - **`"apple"`** - Apple ID (requires `appId`)
195
+ - **`"phantom"`** - Phantom Login (requires `appId`)
196
+ - **`"x"`** - X/Twitter (requires `appId`)
197
+ - **`"tiktok"`** - TikTok (requires `appId`)
188
198
 
189
- Uses the Phantom browser extension installed by the user. No additional configuration needed.
199
+ ### Configuration Examples
200
+
201
+ **Injected Provider Only (Browser Extension)**
190
202
 
191
203
  ```typescript
192
204
  const sdk = new BrowserSDK({
193
- providerType: "injected",
205
+ providers: ["injected"], // Only allow browser extension
194
206
  addressTypes: [AddressType.solana, AddressType.ethereum],
195
207
  });
196
208
  ```
197
209
 
198
- ### Embedded Provider
199
-
200
- Creates a non-custodial wallet embedded in your application. Requires API configuration.
210
+ **Multiple Authentication Methods**
201
211
 
202
212
  ```typescript
203
213
  const sdk = new BrowserSDK({
204
- providerType: "embedded",
214
+ providers: ["google", "apple", "phantom", "injected"], // Allow all methods
205
215
  addressTypes: [AddressType.solana, AddressType.ethereum],
206
- appId: "your-app-id", // Get your app ID from phantom.com/portal
216
+ appId: "your-app-id", // Required for embedded providers (google, apple, phantom, x, tiktok)
207
217
  authOptions: {
208
- authUrl: "https://connect.phantom.app/login", // optional, defaults to "https://connect.phantom.app/login"
218
+ authUrl: "https://connect.phantom.app/login", // optional
209
219
  redirectUrl: "https://yourapp.com/callback", // optional, defaults to current page
210
220
  },
211
- autoConnect: true, // optional, auto-connect to existing session (default: true for embedded)
221
+ autoConnect: true, // optional, auto-connect to existing session (default: true when embedded providers are used)
212
222
  });
213
223
  ```
214
224
 
215
225
  ### Embedded Wallet Type
216
226
 
217
- #### User Wallet (`'user-wallet'`)
227
+ When using embedded providers (google, apple, phantom, etc.), you can specify the wallet type:
228
+
229
+ #### User Wallet (`'user-wallet'`) - Default
218
230
 
219
231
  - **Uses Phantom authentication** - user logs in with existing Phantom account
220
232
  - **Potentially funded** - brings in user's existing wallet balance
@@ -223,9 +235,10 @@ const sdk = new BrowserSDK({
223
235
 
224
236
  ```typescript
225
237
  const sdk = new BrowserSDK({
226
- providerType: "embedded",
238
+ providers: ["google", "apple", "phantom"],
227
239
  appId: "your-app-id",
228
240
  addressTypes: [AddressType.solana, AddressType.ethereum],
241
+ embeddedWalletType: "user-wallet", // default, can be omitted
229
242
  });
230
243
  ```
231
244
 
@@ -236,17 +249,16 @@ const sdk = new BrowserSDK({
236
249
  | `AddressType.solana` | Solana Mainnet, Devnet, Testnet |
237
250
  | `AddressType.ethereum` | Ethereum, Polygon, Arbitrum, and more |
238
251
 
239
-
240
252
  ### Auto-Connect Feature
241
253
 
242
254
  The SDK can automatically reconnect to existing sessions when instantiated, providing a seamless user experience.
243
255
 
244
256
  ```typescript
245
257
  const sdk = new BrowserSDK({
246
- providerType: "embedded",
258
+ providers: ["google", "apple", "phantom"],
247
259
  appId: "your-app-id",
248
260
  addressTypes: [AddressType.solana],
249
- autoConnect: true, // Default: true for embedded, false for injected
261
+ autoConnect: true, // Default: true when embedded providers are used, false for injected-only
250
262
  });
251
263
 
252
264
  // SDK will automatically check for existing valid session and connect in background
@@ -258,7 +270,7 @@ if (sdk.isConnected()) {
258
270
  const addresses = await sdk.getAddresses();
259
271
  } else {
260
272
  // First time or session expired, need to connect manually
261
- await sdk.connect();
273
+ await sdk.connect({ provider: "google" });
262
274
  }
263
275
  ```
264
276
 
@@ -266,14 +278,14 @@ if (sdk.isConnected()) {
266
278
 
267
279
  ```typescript
268
280
  const sdk = new BrowserSDK({
269
- providerType: "embedded",
281
+ providers: ["google", "apple", "phantom"],
270
282
  appId: "your-app-id",
271
283
  addressTypes: [AddressType.solana],
272
284
  autoConnect: false, // Disable auto-connect
273
285
  });
274
286
 
275
287
  // Now you must manually call connect() every time
276
- await sdk.connect();
288
+ await sdk.connect({ provider: "google" });
277
289
  ```
278
290
 
279
291
  ## API Reference
@@ -288,21 +300,26 @@ new BrowserSDK(config: BrowserSDKConfig)
288
300
 
289
301
  ```typescript
290
302
  interface BrowserSDKConfig {
291
- providerType: "injected" | "embedded";
303
+ // List of allowed authentication providers (REQUIRED)
304
+ providers: AuthProviderType[]; // e.g., ["google", "apple", "phantom", "injected"]
305
+
292
306
  addressTypes?: [AddressType, ...AddressType[]]; // Networks to enable (e.g., [AddressType.solana])
293
307
 
294
- // Required for embedded provider only
295
- appId?: string; // Your app ID from phantom.com/portal (required for embedded provider)
296
-
308
+ // Required when using embedded providers (google, apple, phantom, x, tiktok)
309
+ appId?: string; // Your app ID from phantom.com/portal
310
+
297
311
  // Optional configuration
298
312
  apiBaseUrl?: string; // Phantom API base URL (optional, has default)
299
313
  authOptions?: {
300
314
  authUrl?: string; // Custom auth URL (optional, defaults to "https://connect.phantom.app/login")
301
315
  redirectUrl?: string; // Custom redirect URL after authentication (optional)
302
316
  };
303
- embeddedWalletType?: "user-wallet"; // Wallet type (optional, defaults to "user-wallet", currently the only supported type)
304
- autoConnect?: boolean; // Enable auto-connect to existing sessions (optional, defaults to true for embedded)
317
+ embeddedWalletType?: "user-wallet"; // Wallet type (optional, defaults to "user-wallet")
318
+ autoConnect?: boolean; // Auto-connect to existing session (default: true when embedded providers used)
305
319
  }
320
+
321
+ // Valid provider types
322
+ type AuthProviderType = "google" | "apple" | "phantom" | "x" | "tiktok" | "injected";
306
323
  ```
307
324
 
308
325
  ### Extension Detection
@@ -347,6 +364,7 @@ if (isAvailable) {
347
364
  Connect to wallet and get addresses for configured AddressTypes.
348
365
 
349
366
  **Parameters:**
367
+
350
368
  - `options: AuthOptions` (required) - Authentication options
351
369
  - `provider: "google" | "apple" | "jwt" | "phantom" | "injected"` (required) - Authentication provider to use
352
370
  - `jwtToken?: string` (optional) - JWT token (required when `provider` is "jwt")
@@ -362,7 +380,7 @@ const result = await sdk.connect({ provider: "phantom" });
362
380
  // Connect with Google authentication
363
381
  const result = await sdk.connect({ provider: "google" });
364
382
 
365
- // Returns: { addresses: WalletAddress[], status: "pending" | "completed", providerType: "embedded" | "injected" }
383
+ // Returns: { addresses: WalletAddress[], status: "pending" | "completed", provider: "google" | "apple" | "injected" ... }
366
384
  // addresses only includes types from addressTypes config
367
385
  ```
368
386
 
@@ -554,18 +572,18 @@ await sdk.ethereum.switchChain(42161); // Arbitrum One
554
572
 
555
573
  **Supported EVM Networks:**
556
574
 
557
- | Network | Chain ID | Usage |
558
- |---------|----------|-------|
559
- | Ethereum Mainnet | `1` | `switchChain(1)` |
575
+ | Network | Chain ID | Usage |
576
+ | ---------------- | ---------- | ----------------------- |
577
+ | Ethereum Mainnet | `1` | `switchChain(1)` |
560
578
  | Ethereum Sepolia | `11155111` | `switchChain(11155111)` |
561
- | Polygon Mainnet | `137` | `switchChain(137)` |
562
- | Polygon Amoy | `80002` | `switchChain(80002)` |
563
- | Base Mainnet | `8453` | `switchChain(8453)` |
564
- | Base Sepolia | `84532` | `switchChain(84532)` |
565
- | Arbitrum One | `42161` | `switchChain(42161)` |
566
- | Arbitrum Sepolia | `421614` | `switchChain(421614)` |
567
- | Monad Mainnet | `143` | `switchChain(143)` |
568
- | Monad Testnet | `10143` | `switchChain(10143)` |
579
+ | Polygon Mainnet | `137` | `switchChain(137)` |
580
+ | Polygon Amoy | `80002` | `switchChain(80002)` |
581
+ | Base Mainnet | `8453` | `switchChain(8453)` |
582
+ | Base Sepolia | `84532` | `switchChain(84532)` |
583
+ | Arbitrum One | `42161` | `switchChain(42161)` |
584
+ | Arbitrum Sepolia | `421614` | `switchChain(421614)` |
585
+ | Monad Mainnet | `143` | `switchChain(143)` |
586
+ | Monad Testnet | `10143` | `switchChain(10143)` |
569
587
 
570
588
  #### getChainId()
571
589
 
@@ -609,66 +627,66 @@ The SDK provides typed event handlers that allow you to listen for connection st
609
627
  #### Available Events
610
628
 
611
629
  ```typescript
612
- import { BrowserSDK } from '@phantom/browser-sdk';
630
+ import { BrowserSDK, AddressType } from "@phantom/browser-sdk";
613
631
  import type {
614
632
  ConnectEventData,
615
633
  ConnectStartEventData,
616
634
  ConnectErrorEventData,
617
- DisconnectEventData
618
- } from '@phantom/browser-sdk';
635
+ DisconnectEventData,
636
+ } from "@phantom/browser-sdk";
619
637
 
620
638
  const sdk = new BrowserSDK({
621
- providerType: 'embedded',
622
- appId: 'your-app-id',
639
+ providers: ["google", "apple", "phantom"],
640
+ appId: "your-app-id",
623
641
  addressTypes: [AddressType.solana],
624
642
  });
625
643
 
626
644
  // 1. connect_start - Fired when connection starts
627
- sdk.on('connect_start', (data: ConnectStartEventData) => {
628
- console.log('Connection starting:', data.source); // "auto-connect" | "manual-connect"
629
- console.log('Auth options:', data.authOptions?.provider); // "google" | "apple" | etc.
645
+ sdk.on("connect_start", (data: ConnectStartEventData) => {
646
+ console.log("Connection starting:", data.source); // "auto-connect" | "manual-connect"
647
+ console.log("Auth options:", data.authOptions?.provider); // "google" | "apple" | etc.
630
648
  });
631
649
 
632
650
  // 2. connect - Fired when connection succeeds (includes full ConnectResult)
633
- sdk.on('connect', (data: ConnectEventData) => {
634
- console.log('Connected successfully!');
635
- console.log('Provider type:', data.providerType); // "embedded" | "injected"
636
- console.log('Wallet ID:', data.walletId); // only for embedded providers
637
- console.log('Addresses:', data.addresses); // WalletAddress[]
638
- console.log('Status:', data.status); // "pending" | "completed"
639
- console.log('Source:', data.source); // "auto-connect" | "manual-connect" | "manual-existing" | "existing-session" | "manual"
651
+ sdk.on("connect", (data: ConnectEventData) => {
652
+ console.log("Connected successfully!");
653
+ console.log("Provider type:", data.provider); // "google" | "apple" | "injected" ...
654
+ console.log("Wallet ID:", data.walletId); // only for embedded providers
655
+ console.log("Addresses:", data.addresses); // WalletAddress[]
656
+ console.log("Status:", data.status); // "pending" | "completed"
657
+ console.log("Source:", data.source); // "auto-connect" | "manual-connect" | "manual-existing" | "existing-session" | "manual"
640
658
  });
641
659
 
642
660
  // 3. connect_error - Fired when connection fails
643
- sdk.on('connect_error', (data: ConnectErrorEventData) => {
644
- console.error('Connection failed:', data.error);
645
- console.log('Source:', data.source); // "auto-connect" | "manual-connect"
661
+ sdk.on("connect_error", (data: ConnectErrorEventData) => {
662
+ console.error("Connection failed:", data.error);
663
+ console.log("Source:", data.source); // "auto-connect" | "manual-connect"
646
664
  });
647
665
 
648
666
  // 4. disconnect - Fired when disconnected
649
- sdk.on('disconnect', (data: DisconnectEventData) => {
650
- console.log('Disconnected from wallet');
651
- console.log('Source:', data.source); // "manual"
667
+ sdk.on("disconnect", (data: DisconnectEventData) => {
668
+ console.log("Disconnected from wallet");
669
+ console.log("Source:", data.source); // "manual"
652
670
  });
653
671
 
654
672
  // 5. error - General error handler
655
- sdk.on('error', (error: unknown) => {
656
- console.error('SDK error:', error);
673
+ sdk.on("error", (error: unknown) => {
674
+ console.error("SDK error:", error);
657
675
  });
658
676
 
659
677
  // Don't forget to remove listeners when done
660
- sdk.off('connect', handleConnect);
678
+ sdk.off("connect", handleConnect);
661
679
  ```
662
680
 
663
681
  #### Event Types
664
682
 
665
- | Event | Payload Type | When Fired | Key Data |
666
- |-------|-------------|------------|----------|
667
- | `connect_start` | `ConnectStartEventData` | Connection initiated | `source`, `authOptions` |
668
- | `connect` | `ConnectEventData` | Connection successful | `providerType`, `addresses`, `status`, `source`, `user`|
669
- | `connect_error` | `ConnectErrorEventData` | Connection failed | `error`, `source` |
670
- | `disconnect` | `DisconnectEventData` | Disconnected | `source` |
671
- | `error` | `unknown` | General SDK errors | Error details |
683
+ | Event | Payload Type | When Fired | Key Data |
684
+ | --------------- | ----------------------- | --------------------- | --------------------------------------------------- |
685
+ | `connect_start` | `ConnectStartEventData` | Connection initiated | `source`, `authOptions` |
686
+ | `connect` | `ConnectEventData` | Connection successful | `provider`, `addresses`, `status`, `source`, `user` |
687
+ | `connect_error` | `ConnectErrorEventData` | Connection failed | `error`, `source` |
688
+ | `disconnect` | `DisconnectEventData` | Disconnected | `source` |
689
+ | `error` | `unknown` | General SDK errors | Error details |
672
690
 
673
691
  #### Using Events with autoConnect()
674
692
 
@@ -676,24 +694,24 @@ Event handlers are especially useful with `autoConnect()` since it doesn't retur
676
694
 
677
695
  ```typescript
678
696
  const sdk = new BrowserSDK({
679
- providerType: 'embedded',
680
- appId: 'your-app-id',
697
+ providers: ["google", "apple", "phantom"],
698
+ appId: "your-app-id",
681
699
  addressTypes: [AddressType.solana],
682
700
  autoConnect: true,
683
701
  });
684
702
 
685
703
  // Set up event listeners BEFORE autoConnect
686
- sdk.on('connect', (data: ConnectEventData) => {
687
- console.log('Auto-connected successfully!');
688
- console.log('Provider type:', data.providerType);
689
- console.log('Addresses:', data.addresses);
704
+ sdk.on("connect", (data: ConnectEventData) => {
705
+ console.log("Auto-connected successfully!");
706
+ console.log("Provider type:", data.provider);
707
+ console.log("Addresses:", data.addresses);
690
708
 
691
709
  // Update your UI state here
692
710
  updateUIWithAddresses(data.addresses);
693
711
  });
694
712
 
695
- sdk.on('connect_error', (data: ConnectErrorEventData) => {
696
- console.log('Auto-connect failed:', data.error);
713
+ sdk.on("connect_error", (data: ConnectErrorEventData) => {
714
+ console.log("Auto-connect failed:", data.error);
697
715
  // Show connect button to user
698
716
  showConnectButton();
699
717
  });
@@ -838,11 +856,12 @@ interface DebugMessage {
838
856
  ### Example: Debug Console Implementation
839
857
 
840
858
  ```typescript
841
- import { BrowserSDK, DebugLevel } from "@phantom/browser-sdk";
859
+ import { BrowserSDK, DebugLevel, AddressType } from "@phantom/browser-sdk";
842
860
 
843
861
  const sdk = new BrowserSDK({
844
- providerType: "embedded",
862
+ providers: ["google", "apple", "phantom"],
845
863
  appId: "your-app-id",
864
+ addressTypes: [AddressType.solana],
846
865
  });
847
866
 
848
867
  // Store debug messages
@@ -907,7 +926,7 @@ import {
907
926
  import { BrowserSDK, AddressType } from "@phantom/browser-sdk";
908
927
 
909
928
  const sdk = new BrowserSDK({
910
- providerType: "injected",
929
+ providers: ["injected"],
911
930
  addressTypes: [AddressType.solana],
912
931
  });
913
932
 
@@ -960,7 +979,7 @@ import {
960
979
  import { BrowserSDK, AddressType } from "@phantom/browser-sdk";
961
980
 
962
981
  const sdk = new BrowserSDK({
963
- providerType: "injected",
982
+ providers: ["injected"],
964
983
  addressTypes: [AddressType.solana],
965
984
  });
966
985
 
@@ -990,7 +1009,7 @@ console.log("Transaction signature:", result.hash);
990
1009
  import { BrowserSDK, AddressType } from "@phantom/browser-sdk";
991
1010
 
992
1011
  const sdk = new BrowserSDK({
993
- providerType: "injected",
1012
+ providers: ["injected"],
994
1013
  addressTypes: [AddressType.ethereum],
995
1014
  });
996
1015
 
@@ -1024,9 +1043,9 @@ import { parseEther, parseGwei, encodeFunctionData } from "viem";
1024
1043
  import { BrowserSDK, AddressType } from "@phantom/browser-sdk";
1025
1044
 
1026
1045
  const sdk = new BrowserSDK({
1027
- providerType: "embedded",
1046
+ providers: ["google", "apple", "phantom"],
1047
+ appId: "your-app-id",
1028
1048
  addressTypes: [AddressType.ethereum],
1029
- // ... config
1030
1049
  });
1031
1050
 
1032
1051
  // Simple transfer with viem utilities
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { EmbeddedProviderConfig, AuthOptions, ConnectResult, WalletAddress, EmbeddedProviderEvent, EventCallback } from '@phantom/embedded-provider-core';
2
- export { AuthOptions, ConnectErrorEventData, ConnectEventData, ConnectResult, ConnectStartEventData, DisconnectEventData, EmbeddedProviderEvent, EmbeddedProviderEventMap, EventCallback, SignAndSendTransactionParams, SignMessageParams, SignMessageResult, SignedTransaction, WalletAddress } from '@phantom/embedded-provider-core';
1
+ import { EmbeddedProviderConfig, EmbeddedProviderAuthType, ConnectResult as ConnectResult$1, WalletAddress, EmbeddedProviderEvent, EventCallback } from '@phantom/embedded-provider-core';
2
+ export { ConnectErrorEventData, ConnectEventData, ConnectStartEventData, DisconnectEventData, EmbeddedProviderEvent, EmbeddedProviderEventMap, EventCallback, SignAndSendTransactionParams, SignMessageParams, SignMessageResult, SignedTransaction, WalletAddress } from '@phantom/embedded-provider-core';
3
3
  import { ISolanaChain, IEthereumChain } from '@phantom/chain-interfaces';
4
4
  export { EthTransactionRequest, IEthereumChain, ISolanaChain } from '@phantom/chain-interfaces';
5
5
  import { AddressType } from '@phantom/client';
@@ -52,9 +52,6 @@ declare const DebugCategory: {
52
52
  readonly SESSION: "Session";
53
53
  };
54
54
 
55
- /**
56
- * Phantom extension app.login API types
57
- */
58
55
  interface PhantomAppLoginOptions {
59
56
  publicKey: string;
60
57
  appId: string;
@@ -95,30 +92,30 @@ interface DebugConfig {
95
92
  level?: DebugLevel;
96
93
  callback?: DebugCallback;
97
94
  }
98
- type BrowserSDKConfig = Prettify<(ExtendedEmbeddedProviderConfig | ExtendedInjectedProviderConfig) & {
99
- autoConnect?: boolean;
100
- }>;
101
- type Prettify<T> = {
102
- [K in keyof T]: T[K];
103
- } & {};
104
- interface ExtendedEmbeddedProviderConfig extends Omit<EmbeddedProviderConfig, "authOptions" | "apiBaseUrl" | "embeddedWalletType"> {
105
- providerType: "embedded";
95
+ type BrowserSDKConfig = Prettify<Omit<EmbeddedProviderConfig, "authOptions" | "apiBaseUrl" | "embeddedWalletType" | "appId"> & InjectedProviderConfig & {
96
+ providers: AuthProviderType[];
97
+ appId?: string;
106
98
  apiBaseUrl?: string;
107
99
  embeddedWalletType?: "app-wallet" | "user-wallet";
108
100
  authOptions?: {
109
101
  authUrl?: string;
110
102
  redirectUrl?: string;
111
103
  };
112
- }
113
- interface ExtendedInjectedProviderConfig extends InjectedProviderConfig {
114
- providerType: "injected";
115
- appId?: never;
116
- authOptions?: never;
117
- embeddedWalletType?: never;
118
- }
104
+ }>;
105
+ type Prettify<T> = {
106
+ [K in keyof T]: T[K];
107
+ } & {};
108
+ type AuthProviderType = EmbeddedProviderAuthType | "injected";
109
+ type AuthOptions = {
110
+ provider: AuthProviderType;
111
+ customAuthData?: Record<string, any>;
112
+ };
113
+ type ConnectResult = Omit<ConnectResult$1, "authProvider"> & {
114
+ authProvider?: AuthProviderType | undefined;
115
+ };
119
116
 
120
117
  interface Provider {
121
- connect(authOptions?: AuthOptions): Promise<ConnectResult>;
118
+ connect(authOptions: AuthOptions): Promise<ConnectResult>;
122
119
  disconnect(): Promise<void>;
123
120
  getAddresses(): WalletAddress[];
124
121
  isConnected(): boolean;
@@ -132,19 +129,6 @@ interface ProviderPreference {
132
129
  embeddedWalletType?: "app-wallet" | "user-wallet";
133
130
  }
134
131
 
135
- /**
136
- * Browser SDK with chain-specific API
137
- *
138
- * Usage:
139
- * ```typescript
140
- * const sdk = new BrowserSDK({ providerType: 'embedded', appId: 'your-app-id' });
141
- * await sdk.connect();
142
- *
143
- * // Chain-specific operations
144
- * await sdk.solana.signMessage(message);
145
- * await sdk.ethereum.signPersonalMessage(message, address);
146
- * ```
147
- */
148
132
  declare class BrowserSDK {
149
133
  private providerManager;
150
134
  constructor(config: BrowserSDKConfig);
@@ -326,4 +310,4 @@ declare function waitForPhantomExtension(timeoutMs?: number): Promise<boolean>;
326
310
  */
327
311
  declare function isPhantomLoginAvailable(timeoutMs?: number): Promise<boolean>;
328
312
 
329
- export { BrowserInfo, BrowserSDK, BrowserSDKConfig, DebugCallback, DebugCategory, DebugConfig, DebugLevel, DebugMessage, Provider, debug, detectBrowser, getBrowserDisplayName, getDeeplinkToPhantom, getPlatformName, isMobileDevice, isPhantomLoginAvailable, parseBrowserFromUserAgent, waitForPhantomExtension };
313
+ export { AuthOptions, AuthProviderType, BrowserInfo, BrowserSDK, BrowserSDKConfig, ConnectResult, DebugCallback, DebugCategory, DebugConfig, DebugLevel, DebugMessage, Provider, debug, detectBrowser, getBrowserDisplayName, getDeeplinkToPhantom, getPlatformName, isMobileDevice, isPhantomLoginAvailable, parseBrowserFromUserAgent, waitForPhantomExtension };
package/dist/index.js CHANGED
@@ -385,8 +385,8 @@ var InjectedEthereumChain = class {
385
385
  };
386
386
 
387
387
  // src/providers/injected/index.ts
388
- var MANUAL_DISCONNECT_KEY = "phantom-injected-manual-disconnect";
389
- var MANUAL_DISCONNECT_VALUE = "true";
388
+ var WAS_CONNECTED_KEY = "phantom-injected-was-connected";
389
+ var WAS_CONNECTED_VALUE = "true";
390
390
  var InjectedProvider = class {
391
391
  constructor(config) {
392
392
  this.connected = false;
@@ -422,9 +422,6 @@ var InjectedProvider = class {
422
422
  }
423
423
  debug.info(DebugCategory.INJECTED_PROVIDER, "InjectedProvider initialized");
424
424
  }
425
- /**
426
- * Access to Solana chain operations
427
- */
428
425
  get solana() {
429
426
  if (!this.addressTypes.includes(import_client4.AddressType.solana)) {
430
427
  throw new Error("Solana not enabled for this provider");
@@ -523,10 +520,10 @@ var InjectedProvider = class {
523
520
  this.connected = true;
524
521
  const authUserId = await this.getAuthUserId("manual-connect");
525
522
  try {
526
- localStorage.removeItem(MANUAL_DISCONNECT_KEY);
527
- debug.log(DebugCategory.INJECTED_PROVIDER, "Cleared manual disconnect flag - auto-reconnect enabled");
523
+ localStorage.setItem(WAS_CONNECTED_KEY, WAS_CONNECTED_VALUE);
524
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Set was-connected flag - auto-reconnect enabled");
528
525
  } catch (error) {
529
- debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to clear manual disconnect flag", { error });
526
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to set was-connected flag", { error });
530
527
  }
531
528
  const result = {
532
529
  addresses: this.addresses,
@@ -559,18 +556,15 @@ var InjectedProvider = class {
559
556
  debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to disconnect Solana", { error: err });
560
557
  }
561
558
  }
562
- if (this.addressTypes.includes(import_client4.AddressType.ethereum)) {
563
- debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum disconnected (no-op)");
564
- }
565
559
  this.browserInjectedCleanupFunctions.forEach((cleanup) => cleanup());
566
560
  this.browserInjectedCleanupFunctions = [];
567
561
  this.connected = false;
568
562
  this.addresses = [];
569
563
  try {
570
- localStorage.setItem(MANUAL_DISCONNECT_KEY, MANUAL_DISCONNECT_VALUE);
571
- debug.log(DebugCategory.INJECTED_PROVIDER, "Set manual disconnect flag to prevent auto-reconnect");
564
+ localStorage.removeItem(WAS_CONNECTED_KEY);
565
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Cleared was connected flag to prevent auto-reconnect");
572
566
  } catch (error) {
573
- debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to set manual disconnect flag", { error });
567
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to clear was-connected flag", { error });
574
568
  }
575
569
  this.emit("disconnect", {
576
570
  source: "manual-disconnect"
@@ -578,20 +572,22 @@ var InjectedProvider = class {
578
572
  debug.info(DebugCategory.INJECTED_PROVIDER, "Injected provider disconnected successfully");
579
573
  }
580
574
  /**
581
- * Attempt auto-connection using onlyIfTrusted parameter
582
- * This will only connect if the dApp is already trusted by the user
575
+ * Attempt auto-connection if user was previously connected
576
+ * Only reconnects if the user connected before and didn't explicitly disconnect
583
577
  * Should be called after setting up event listeners
584
578
  */
585
579
  async autoConnect() {
586
- debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting auto-connect with onlyIfTrusted=true");
580
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting auto-connect");
587
581
  try {
588
- const manualDisconnect = localStorage.getItem(MANUAL_DISCONNECT_KEY);
589
- if (manualDisconnect === MANUAL_DISCONNECT_VALUE) {
590
- debug.log(DebugCategory.INJECTED_PROVIDER, "Skipping auto-connect: user previously disconnected manually");
582
+ const wasConnected = localStorage.getItem(WAS_CONNECTED_KEY);
583
+ if (wasConnected !== WAS_CONNECTED_VALUE) {
584
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Skipping auto-connect: user was not previously connected");
591
585
  return;
592
586
  }
587
+ debug.log(DebugCategory.INJECTED_PROVIDER, "User was previously connected, attempting auto-connect");
593
588
  } catch (error) {
594
- debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to check manual disconnect flag", { error });
589
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to check was-connected flag", { error });
590
+ return;
595
591
  }
596
592
  this.emit("connect_start", {
597
593
  source: "auto-connect",
@@ -619,7 +615,10 @@ var InjectedProvider = class {
619
615
  debug.info(DebugCategory.INJECTED_PROVIDER, "Solana auto-connected successfully", { address: publicKey });
620
616
  }
621
617
  } catch (err) {
622
- debug.log(DebugCategory.INJECTED_PROVIDER, "Solana auto-connect failed (expected if not trusted)", { error: err });
618
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Solana auto-connect failed (expected if not trusted)", {
619
+ error: err
620
+ });
621
+ throw err;
623
622
  }
624
623
  }
625
624
  if (this.addressTypes.includes(import_client4.AddressType.ethereum)) {
@@ -633,10 +632,14 @@ var InjectedProvider = class {
633
632
  address
634
633
  }))
635
634
  );
636
- debug.info(DebugCategory.INJECTED_PROVIDER, "Ethereum auto-connected successfully", { addresses: accounts });
635
+ debug.info(DebugCategory.INJECTED_PROVIDER, "Ethereum auto-connected successfully", {
636
+ addresses: accounts
637
+ });
637
638
  }
638
639
  } catch (err) {
639
- debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum auto-connect failed (expected if not trusted)", { error: err });
640
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum auto-connect failed (expected if not trusted)", {
641
+ error: err
642
+ });
640
643
  }
641
644
  }
642
645
  if (connectedAddresses.length === 0) {
@@ -657,7 +660,10 @@ var InjectedProvider = class {
657
660
  });
658
661
  debug.info(DebugCategory.INJECTED_PROVIDER, "Auto-connect successful", {
659
662
  addressCount: connectedAddresses.length,
660
- addresses: connectedAddresses.map((addr) => ({ type: addr.addressType, address: addr.address.substring(0, 8) + "..." })),
663
+ addresses: connectedAddresses.map((addr) => ({
664
+ type: addr.addressType,
665
+ address: addr.address.substring(0, 8) + "..."
666
+ })),
661
667
  authUserId
662
668
  });
663
669
  } catch (error) {
@@ -703,14 +709,22 @@ var InjectedProvider = class {
703
709
  const userInfo = await window.phantom.app.getUser();
704
710
  const authUserId = userInfo?.authUserId;
705
711
  if (authUserId) {
706
- debug.log(DebugCategory.INJECTED_PROVIDER, `Retrieved authUserId from window.phantom.app.getUser() during ${context}`, {
707
- authUserId
708
- });
712
+ debug.log(
713
+ DebugCategory.INJECTED_PROVIDER,
714
+ `Retrieved authUserId from window.phantom.app.getUser() during ${context}`,
715
+ {
716
+ authUserId
717
+ }
718
+ );
709
719
  }
710
720
  return authUserId;
711
721
  }
712
722
  } catch (error) {
713
- debug.log(DebugCategory.INJECTED_PROVIDER, `Failed to get user info during ${context} (method may not be supported)`, { error });
723
+ debug.log(
724
+ DebugCategory.INJECTED_PROVIDER,
725
+ `Failed to get user info during ${context} (method may not be supported)`,
726
+ { error }
727
+ );
714
728
  }
715
729
  return void 0;
716
730
  }
@@ -1201,7 +1215,7 @@ var BrowserAuthProvider = class {
1201
1215
  // OAuth session management - defaults to allow refresh unless explicitly clearing after logout
1202
1216
  clear_previous_session: (phantomOptions.clearPreviousSession ?? false).toString(),
1203
1217
  allow_refresh: (phantomOptions.allowRefresh ?? true).toString(),
1204
- sdk_version: "1.0.0-beta.21",
1218
+ sdk_version: "1.0.0-beta.22",
1205
1219
  sdk_type: "browser",
1206
1220
  platform: detectBrowser().name
1207
1221
  });
@@ -1231,7 +1245,7 @@ var BrowserAuthProvider = class {
1231
1245
  resolve();
1232
1246
  });
1233
1247
  }
1234
- resumeAuthFromRedirect() {
1248
+ resumeAuthFromRedirect(provider) {
1235
1249
  try {
1236
1250
  const walletId = this.urlParamsAccessor.getParam("wallet_id");
1237
1251
  const sessionId = this.urlParamsAccessor.getParam("session_id");
@@ -1298,16 +1312,21 @@ var BrowserAuthProvider = class {
1298
1312
  throw new Error("Missing organization_id in auth response");
1299
1313
  }
1300
1314
  if (organizationId.startsWith("temp-")) {
1301
- debug.warn(DebugCategory.PHANTOM_CONNECT_AUTH, "Received temporary organization_id, server may not be configured properly", {
1302
- organizationId
1303
- });
1315
+ debug.warn(
1316
+ DebugCategory.PHANTOM_CONNECT_AUTH,
1317
+ "Received temporary organization_id, server may not be configured properly",
1318
+ {
1319
+ organizationId
1320
+ }
1321
+ );
1304
1322
  }
1305
1323
  return {
1306
1324
  walletId,
1307
1325
  organizationId,
1308
1326
  accountDerivationIndex: accountDerivationIndex ? parseInt(accountDerivationIndex) : 0,
1309
1327
  expiresInMs: expiresInMs ? parseInt(expiresInMs) : 0,
1310
- authUserId: authUserId || void 0
1328
+ authUserId: authUserId || void 0,
1329
+ provider
1311
1330
  };
1312
1331
  } catch (error) {
1313
1332
  sessionStorage.removeItem("phantom-auth-context");
@@ -1460,7 +1479,7 @@ var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvi
1460
1479
  // Full user agent for more detailed info
1461
1480
  [import_constants2.ANALYTICS_HEADERS.APP_ID]: config.appId,
1462
1481
  [import_constants2.ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
1463
- [import_constants2.ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.21"
1482
+ [import_constants2.ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.22"
1464
1483
  // Replaced at build time
1465
1484
  }
1466
1485
  };
@@ -1472,6 +1491,7 @@ var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvi
1472
1491
  };
1473
1492
 
1474
1493
  // src/ProviderManager.ts
1494
+ var import_embedded_provider_core2 = require("@phantom/embedded-provider-core");
1475
1495
  var import_constants3 = require("@phantom/constants");
1476
1496
 
1477
1497
  // src/utils/auth-callback.ts
@@ -1555,6 +1575,12 @@ var ProviderManager = class {
1555
1575
  embeddedWalletType
1556
1576
  };
1557
1577
  }
1578
+ /**
1579
+ * Check if a provider is allowed by the config
1580
+ */
1581
+ isProviderAllowed(provider) {
1582
+ return this.config.providers.includes(provider);
1583
+ }
1558
1584
  /**
1559
1585
  * Connect using the current provider
1560
1586
  * Automatically switches provider based on authOptions.provider
@@ -1562,13 +1588,18 @@ var ProviderManager = class {
1562
1588
  async connect(authOptions) {
1563
1589
  debug.info(DebugCategory.PROVIDER_MANAGER, "Starting connection", {
1564
1590
  currentProviderKey: this.currentProviderKey,
1565
- authOptions: { provider: authOptions.provider, hasJwtToken: !!authOptions.jwtToken }
1591
+ authOptions: { provider: authOptions.provider }
1566
1592
  });
1593
+ if (!this.isProviderAllowed(authOptions.provider)) {
1594
+ const error = `Provider "${authOptions.provider}" is not in the allowed providers list: ${JSON.stringify(this.config.providers)}`;
1595
+ debug.error(DebugCategory.PROVIDER_MANAGER, error);
1596
+ throw new Error(error);
1597
+ }
1567
1598
  const requestedProvider = authOptions.provider;
1568
1599
  let targetProviderType = null;
1569
1600
  if (requestedProvider === "injected") {
1570
1601
  targetProviderType = "injected";
1571
- } else if (["google", "apple", "jwt", "phantom"].includes(requestedProvider)) {
1602
+ } else if (import_embedded_provider_core2.EMBEDDED_PROVIDER_AUTH_TYPES.includes(requestedProvider)) {
1572
1603
  targetProviderType = "embedded";
1573
1604
  }
1574
1605
  if (targetProviderType) {
@@ -1592,16 +1623,14 @@ var ProviderManager = class {
1592
1623
  }
1593
1624
  debug.log(DebugCategory.PROVIDER_MANAGER, "Delegating to provider connect method");
1594
1625
  const result = await this.currentProvider.connect(authOptions);
1595
- const providerInfo = this.getCurrentProviderInfo();
1596
- result.providerType = providerInfo?.type;
1597
1626
  debug.log(DebugCategory.PROVIDER_MANAGER, "Connection successful, saving preferences", {
1598
1627
  addressCount: result.addresses?.length || 0,
1599
- providerType: result.providerType
1628
+ provider: authOptions.provider
1600
1629
  });
1601
1630
  this.saveProviderPreference();
1602
1631
  debug.info(DebugCategory.PROVIDER_MANAGER, "Connect completed", {
1603
1632
  addresses: result.addresses,
1604
- providerType: result.providerType
1633
+ provider: authOptions.provider
1605
1634
  });
1606
1635
  return result;
1607
1636
  }
@@ -1630,7 +1659,7 @@ var ProviderManager = class {
1630
1659
  }
1631
1660
  /**
1632
1661
  * Attempt auto-connect with fallback strategy
1633
- * Tries embedded provider first if it exists, then injected provider
1662
+ * Tries embedded provider first if it exists and is allowed, then injected provider if allowed
1634
1663
  * Returns true if any provider successfully connected
1635
1664
  */
1636
1665
  async autoConnect() {
@@ -1641,7 +1670,8 @@ var ProviderManager = class {
1641
1670
  }
1642
1671
  const embeddedWalletType = this.config.embeddedWalletType || "user-wallet";
1643
1672
  const embeddedKey = this.getProviderKey("embedded", embeddedWalletType);
1644
- if (this.providers.has(embeddedKey)) {
1673
+ const embeddedAllowed = this.config.providers.some((p) => p !== "injected");
1674
+ if (embeddedAllowed && this.providers.has(embeddedKey)) {
1645
1675
  debug.log(DebugCategory.PROVIDER_MANAGER, "Trying auto-connect with existing embedded provider");
1646
1676
  const embeddedProvider = this.providers.get(embeddedKey);
1647
1677
  try {
@@ -1670,8 +1700,9 @@ var ProviderManager = class {
1670
1700
  }
1671
1701
  }
1672
1702
  }
1703
+ const injectedAllowed = this.config.providers.includes("injected");
1673
1704
  const injectedKey = this.getProviderKey("injected");
1674
- if (this.providers.has(injectedKey)) {
1705
+ if (injectedAllowed && this.providers.has(injectedKey)) {
1675
1706
  debug.log(DebugCategory.PROVIDER_MANAGER, "Trying auto-connect with existing injected provider");
1676
1707
  const injectedProvider = this.providers.get(injectedKey);
1677
1708
  try {
@@ -1690,7 +1721,7 @@ var ProviderManager = class {
1690
1721
  });
1691
1722
  }
1692
1723
  }
1693
- debug.log(DebugCategory.PROVIDER_MANAGER, "Auto-connect failed for all existing providers");
1724
+ debug.log(DebugCategory.PROVIDER_MANAGER, "Auto-connect failed for all allowed providers");
1694
1725
  return false;
1695
1726
  }
1696
1727
  /**
@@ -1774,17 +1805,28 @@ var ProviderManager = class {
1774
1805
  }
1775
1806
  /**
1776
1807
  * Set default provider based on initial config
1777
- * Creates both embedded and injected providers for autoConnect fallback
1808
+ * Creates providers based on the allowed providers array
1778
1809
  */
1779
1810
  setDefaultProvider() {
1780
- const defaultType = this.config.providerType || "embedded";
1781
1811
  const defaultEmbeddedType = this.config.embeddedWalletType || "user-wallet";
1782
- if (this.config.appId) {
1783
- debug.log(DebugCategory.PROVIDER_MANAGER, "Creating embedded provider");
1812
+ const hasInjected = this.config.providers.includes("injected");
1813
+ const hasEmbedded = this.config.providers.some((p) => p !== "injected");
1814
+ if (hasInjected) {
1815
+ debug.log(DebugCategory.PROVIDER_MANAGER, "Creating injected provider (allowed by providers array)");
1816
+ this.createProvider("injected");
1817
+ }
1818
+ if (hasEmbedded) {
1819
+ debug.log(DebugCategory.PROVIDER_MANAGER, "Creating embedded provider (allowed by providers array)");
1784
1820
  this.createProvider("embedded", defaultEmbeddedType);
1785
1821
  }
1786
- debug.log(DebugCategory.PROVIDER_MANAGER, "Creating injected provider");
1787
- this.createProvider("injected");
1822
+ let defaultType;
1823
+ if (hasEmbedded && this.providers.has(`embedded-${defaultEmbeddedType}`)) {
1824
+ defaultType = "embedded";
1825
+ } else if (hasInjected && this.providers.has("injected")) {
1826
+ defaultType = "injected";
1827
+ } else {
1828
+ throw new Error("No valid providers could be created from the providers array");
1829
+ }
1788
1830
  const switchOptions = {};
1789
1831
  if (defaultType === "embedded") {
1790
1832
  switchOptions.embeddedWalletType = defaultEmbeddedType;
@@ -1877,20 +1919,39 @@ async function waitForPhantomExtension(timeoutMs = 3e3) {
1877
1919
  }
1878
1920
 
1879
1921
  // src/BrowserSDK.ts
1922
+ var import_embedded_provider_core3 = require("@phantom/embedded-provider-core");
1880
1923
  var import_constants4 = require("@phantom/constants");
1924
+ var BROWSER_SDK_PROVIDER_TYPES = [...import_embedded_provider_core3.EMBEDDED_PROVIDER_AUTH_TYPES, "injected"];
1881
1925
  var BrowserSDK = class {
1882
1926
  constructor(config) {
1883
1927
  debug.info(DebugCategory.BROWSER_SDK, "Initializing BrowserSDK", {
1884
- providerType: config.providerType,
1928
+ providers: config.providers,
1885
1929
  embeddedWalletType: config.embeddedWalletType,
1886
1930
  addressTypes: config.addressTypes
1887
1931
  });
1888
- if (!["injected", "embedded"].includes(config.providerType)) {
1889
- debug.error(DebugCategory.BROWSER_SDK, "Invalid providerType", { providerType: config.providerType });
1890
- throw new Error(`Invalid providerType: ${config.providerType}. Must be "injected" or "embedded".`);
1932
+ if (!Array.isArray(config.providers) || config.providers.length === 0) {
1933
+ debug.error(DebugCategory.BROWSER_SDK, "Invalid providers array", { providers: config.providers });
1934
+ throw new Error("providers must be a non-empty array of AuthProviderType");
1935
+ }
1936
+ const invalidProviders = config.providers.filter((p) => !BROWSER_SDK_PROVIDER_TYPES.includes(p));
1937
+ if (invalidProviders.length > 0) {
1938
+ debug.error(DebugCategory.BROWSER_SDK, "Invalid provider types", {
1939
+ invalidProviders,
1940
+ validProviders: BROWSER_SDK_PROVIDER_TYPES
1941
+ });
1942
+ throw new Error(
1943
+ `Invalid provider type(s): ${invalidProviders.join(", ")}. Valid providers are: ${BROWSER_SDK_PROVIDER_TYPES.join(", ")}`
1944
+ );
1945
+ }
1946
+ const hasEmbeddedProviders = config.providers.some((p) => p !== "injected");
1947
+ if (hasEmbeddedProviders && !config.appId) {
1948
+ debug.error(DebugCategory.BROWSER_SDK, "appId required for embedded providers", {
1949
+ providers: config.providers
1950
+ });
1951
+ throw new Error("appId is required when using embedded providers (google, apple, phantom, etc.)");
1891
1952
  }
1892
1953
  const embeddedWalletType = config.embeddedWalletType || import_constants4.DEFAULT_EMBEDDED_WALLET_TYPE;
1893
- if (config.providerType === "embedded" && !["app-wallet", "user-wallet"].includes(embeddedWalletType)) {
1954
+ if (!["app-wallet", "user-wallet"].includes(embeddedWalletType)) {
1894
1955
  debug.error(DebugCategory.BROWSER_SDK, "Invalid embeddedWalletType", {
1895
1956
  embeddedWalletType: config.embeddedWalletType
1896
1957
  });
package/dist/index.mjs CHANGED
@@ -348,8 +348,8 @@ var InjectedEthereumChain = class {
348
348
  };
349
349
 
350
350
  // src/providers/injected/index.ts
351
- var MANUAL_DISCONNECT_KEY = "phantom-injected-manual-disconnect";
352
- var MANUAL_DISCONNECT_VALUE = "true";
351
+ var WAS_CONNECTED_KEY = "phantom-injected-was-connected";
352
+ var WAS_CONNECTED_VALUE = "true";
353
353
  var InjectedProvider = class {
354
354
  constructor(config) {
355
355
  this.connected = false;
@@ -385,9 +385,6 @@ var InjectedProvider = class {
385
385
  }
386
386
  debug.info(DebugCategory.INJECTED_PROVIDER, "InjectedProvider initialized");
387
387
  }
388
- /**
389
- * Access to Solana chain operations
390
- */
391
388
  get solana() {
392
389
  if (!this.addressTypes.includes(AddressType4.solana)) {
393
390
  throw new Error("Solana not enabled for this provider");
@@ -486,10 +483,10 @@ var InjectedProvider = class {
486
483
  this.connected = true;
487
484
  const authUserId = await this.getAuthUserId("manual-connect");
488
485
  try {
489
- localStorage.removeItem(MANUAL_DISCONNECT_KEY);
490
- debug.log(DebugCategory.INJECTED_PROVIDER, "Cleared manual disconnect flag - auto-reconnect enabled");
486
+ localStorage.setItem(WAS_CONNECTED_KEY, WAS_CONNECTED_VALUE);
487
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Set was-connected flag - auto-reconnect enabled");
491
488
  } catch (error) {
492
- debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to clear manual disconnect flag", { error });
489
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to set was-connected flag", { error });
493
490
  }
494
491
  const result = {
495
492
  addresses: this.addresses,
@@ -522,18 +519,15 @@ var InjectedProvider = class {
522
519
  debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to disconnect Solana", { error: err });
523
520
  }
524
521
  }
525
- if (this.addressTypes.includes(AddressType4.ethereum)) {
526
- debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum disconnected (no-op)");
527
- }
528
522
  this.browserInjectedCleanupFunctions.forEach((cleanup) => cleanup());
529
523
  this.browserInjectedCleanupFunctions = [];
530
524
  this.connected = false;
531
525
  this.addresses = [];
532
526
  try {
533
- localStorage.setItem(MANUAL_DISCONNECT_KEY, MANUAL_DISCONNECT_VALUE);
534
- debug.log(DebugCategory.INJECTED_PROVIDER, "Set manual disconnect flag to prevent auto-reconnect");
527
+ localStorage.removeItem(WAS_CONNECTED_KEY);
528
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Cleared was connected flag to prevent auto-reconnect");
535
529
  } catch (error) {
536
- debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to set manual disconnect flag", { error });
530
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to clear was-connected flag", { error });
537
531
  }
538
532
  this.emit("disconnect", {
539
533
  source: "manual-disconnect"
@@ -541,20 +535,22 @@ var InjectedProvider = class {
541
535
  debug.info(DebugCategory.INJECTED_PROVIDER, "Injected provider disconnected successfully");
542
536
  }
543
537
  /**
544
- * Attempt auto-connection using onlyIfTrusted parameter
545
- * This will only connect if the dApp is already trusted by the user
538
+ * Attempt auto-connection if user was previously connected
539
+ * Only reconnects if the user connected before and didn't explicitly disconnect
546
540
  * Should be called after setting up event listeners
547
541
  */
548
542
  async autoConnect() {
549
- debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting auto-connect with onlyIfTrusted=true");
543
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Attempting auto-connect");
550
544
  try {
551
- const manualDisconnect = localStorage.getItem(MANUAL_DISCONNECT_KEY);
552
- if (manualDisconnect === MANUAL_DISCONNECT_VALUE) {
553
- debug.log(DebugCategory.INJECTED_PROVIDER, "Skipping auto-connect: user previously disconnected manually");
545
+ const wasConnected = localStorage.getItem(WAS_CONNECTED_KEY);
546
+ if (wasConnected !== WAS_CONNECTED_VALUE) {
547
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Skipping auto-connect: user was not previously connected");
554
548
  return;
555
549
  }
550
+ debug.log(DebugCategory.INJECTED_PROVIDER, "User was previously connected, attempting auto-connect");
556
551
  } catch (error) {
557
- debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to check manual disconnect flag", { error });
552
+ debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to check was-connected flag", { error });
553
+ return;
558
554
  }
559
555
  this.emit("connect_start", {
560
556
  source: "auto-connect",
@@ -582,7 +578,10 @@ var InjectedProvider = class {
582
578
  debug.info(DebugCategory.INJECTED_PROVIDER, "Solana auto-connected successfully", { address: publicKey });
583
579
  }
584
580
  } catch (err) {
585
- debug.log(DebugCategory.INJECTED_PROVIDER, "Solana auto-connect failed (expected if not trusted)", { error: err });
581
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Solana auto-connect failed (expected if not trusted)", {
582
+ error: err
583
+ });
584
+ throw err;
586
585
  }
587
586
  }
588
587
  if (this.addressTypes.includes(AddressType4.ethereum)) {
@@ -596,10 +595,14 @@ var InjectedProvider = class {
596
595
  address
597
596
  }))
598
597
  );
599
- debug.info(DebugCategory.INJECTED_PROVIDER, "Ethereum auto-connected successfully", { addresses: accounts });
598
+ debug.info(DebugCategory.INJECTED_PROVIDER, "Ethereum auto-connected successfully", {
599
+ addresses: accounts
600
+ });
600
601
  }
601
602
  } catch (err) {
602
- debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum auto-connect failed (expected if not trusted)", { error: err });
603
+ debug.log(DebugCategory.INJECTED_PROVIDER, "Ethereum auto-connect failed (expected if not trusted)", {
604
+ error: err
605
+ });
603
606
  }
604
607
  }
605
608
  if (connectedAddresses.length === 0) {
@@ -620,7 +623,10 @@ var InjectedProvider = class {
620
623
  });
621
624
  debug.info(DebugCategory.INJECTED_PROVIDER, "Auto-connect successful", {
622
625
  addressCount: connectedAddresses.length,
623
- addresses: connectedAddresses.map((addr) => ({ type: addr.addressType, address: addr.address.substring(0, 8) + "..." })),
626
+ addresses: connectedAddresses.map((addr) => ({
627
+ type: addr.addressType,
628
+ address: addr.address.substring(0, 8) + "..."
629
+ })),
624
630
  authUserId
625
631
  });
626
632
  } catch (error) {
@@ -666,14 +672,22 @@ var InjectedProvider = class {
666
672
  const userInfo = await window.phantom.app.getUser();
667
673
  const authUserId = userInfo?.authUserId;
668
674
  if (authUserId) {
669
- debug.log(DebugCategory.INJECTED_PROVIDER, `Retrieved authUserId from window.phantom.app.getUser() during ${context}`, {
670
- authUserId
671
- });
675
+ debug.log(
676
+ DebugCategory.INJECTED_PROVIDER,
677
+ `Retrieved authUserId from window.phantom.app.getUser() during ${context}`,
678
+ {
679
+ authUserId
680
+ }
681
+ );
672
682
  }
673
683
  return authUserId;
674
684
  }
675
685
  } catch (error) {
676
- debug.log(DebugCategory.INJECTED_PROVIDER, `Failed to get user info during ${context} (method may not be supported)`, { error });
686
+ debug.log(
687
+ DebugCategory.INJECTED_PROVIDER,
688
+ `Failed to get user info during ${context} (method may not be supported)`,
689
+ { error }
690
+ );
677
691
  }
678
692
  return void 0;
679
693
  }
@@ -1164,7 +1178,7 @@ var BrowserAuthProvider = class {
1164
1178
  // OAuth session management - defaults to allow refresh unless explicitly clearing after logout
1165
1179
  clear_previous_session: (phantomOptions.clearPreviousSession ?? false).toString(),
1166
1180
  allow_refresh: (phantomOptions.allowRefresh ?? true).toString(),
1167
- sdk_version: "1.0.0-beta.21",
1181
+ sdk_version: "1.0.0-beta.22",
1168
1182
  sdk_type: "browser",
1169
1183
  platform: detectBrowser().name
1170
1184
  });
@@ -1194,7 +1208,7 @@ var BrowserAuthProvider = class {
1194
1208
  resolve();
1195
1209
  });
1196
1210
  }
1197
- resumeAuthFromRedirect() {
1211
+ resumeAuthFromRedirect(provider) {
1198
1212
  try {
1199
1213
  const walletId = this.urlParamsAccessor.getParam("wallet_id");
1200
1214
  const sessionId = this.urlParamsAccessor.getParam("session_id");
@@ -1261,16 +1275,21 @@ var BrowserAuthProvider = class {
1261
1275
  throw new Error("Missing organization_id in auth response");
1262
1276
  }
1263
1277
  if (organizationId.startsWith("temp-")) {
1264
- debug.warn(DebugCategory.PHANTOM_CONNECT_AUTH, "Received temporary organization_id, server may not be configured properly", {
1265
- organizationId
1266
- });
1278
+ debug.warn(
1279
+ DebugCategory.PHANTOM_CONNECT_AUTH,
1280
+ "Received temporary organization_id, server may not be configured properly",
1281
+ {
1282
+ organizationId
1283
+ }
1284
+ );
1267
1285
  }
1268
1286
  return {
1269
1287
  walletId,
1270
1288
  organizationId,
1271
1289
  accountDerivationIndex: accountDerivationIndex ? parseInt(accountDerivationIndex) : 0,
1272
1290
  expiresInMs: expiresInMs ? parseInt(expiresInMs) : 0,
1273
- authUserId: authUserId || void 0
1291
+ authUserId: authUserId || void 0,
1292
+ provider
1274
1293
  };
1275
1294
  } catch (error) {
1276
1295
  sessionStorage.removeItem("phantom-auth-context");
@@ -1423,7 +1442,7 @@ var EmbeddedProvider = class extends CoreEmbeddedProvider {
1423
1442
  // Full user agent for more detailed info
1424
1443
  [ANALYTICS_HEADERS.APP_ID]: config.appId,
1425
1444
  [ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
1426
- [ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.21"
1445
+ [ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.22"
1427
1446
  // Replaced at build time
1428
1447
  }
1429
1448
  };
@@ -1435,6 +1454,9 @@ var EmbeddedProvider = class extends CoreEmbeddedProvider {
1435
1454
  };
1436
1455
 
1437
1456
  // src/ProviderManager.ts
1457
+ import {
1458
+ EMBEDDED_PROVIDER_AUTH_TYPES
1459
+ } from "@phantom/embedded-provider-core";
1438
1460
  import { DEFAULT_WALLET_API_URL, DEFAULT_EMBEDDED_WALLET_TYPE, DEFAULT_AUTH_URL as DEFAULT_AUTH_URL2 } from "@phantom/constants";
1439
1461
 
1440
1462
  // src/utils/auth-callback.ts
@@ -1518,6 +1540,12 @@ var ProviderManager = class {
1518
1540
  embeddedWalletType
1519
1541
  };
1520
1542
  }
1543
+ /**
1544
+ * Check if a provider is allowed by the config
1545
+ */
1546
+ isProviderAllowed(provider) {
1547
+ return this.config.providers.includes(provider);
1548
+ }
1521
1549
  /**
1522
1550
  * Connect using the current provider
1523
1551
  * Automatically switches provider based on authOptions.provider
@@ -1525,13 +1553,18 @@ var ProviderManager = class {
1525
1553
  async connect(authOptions) {
1526
1554
  debug.info(DebugCategory.PROVIDER_MANAGER, "Starting connection", {
1527
1555
  currentProviderKey: this.currentProviderKey,
1528
- authOptions: { provider: authOptions.provider, hasJwtToken: !!authOptions.jwtToken }
1556
+ authOptions: { provider: authOptions.provider }
1529
1557
  });
1558
+ if (!this.isProviderAllowed(authOptions.provider)) {
1559
+ const error = `Provider "${authOptions.provider}" is not in the allowed providers list: ${JSON.stringify(this.config.providers)}`;
1560
+ debug.error(DebugCategory.PROVIDER_MANAGER, error);
1561
+ throw new Error(error);
1562
+ }
1530
1563
  const requestedProvider = authOptions.provider;
1531
1564
  let targetProviderType = null;
1532
1565
  if (requestedProvider === "injected") {
1533
1566
  targetProviderType = "injected";
1534
- } else if (["google", "apple", "jwt", "phantom"].includes(requestedProvider)) {
1567
+ } else if (EMBEDDED_PROVIDER_AUTH_TYPES.includes(requestedProvider)) {
1535
1568
  targetProviderType = "embedded";
1536
1569
  }
1537
1570
  if (targetProviderType) {
@@ -1555,16 +1588,14 @@ var ProviderManager = class {
1555
1588
  }
1556
1589
  debug.log(DebugCategory.PROVIDER_MANAGER, "Delegating to provider connect method");
1557
1590
  const result = await this.currentProvider.connect(authOptions);
1558
- const providerInfo = this.getCurrentProviderInfo();
1559
- result.providerType = providerInfo?.type;
1560
1591
  debug.log(DebugCategory.PROVIDER_MANAGER, "Connection successful, saving preferences", {
1561
1592
  addressCount: result.addresses?.length || 0,
1562
- providerType: result.providerType
1593
+ provider: authOptions.provider
1563
1594
  });
1564
1595
  this.saveProviderPreference();
1565
1596
  debug.info(DebugCategory.PROVIDER_MANAGER, "Connect completed", {
1566
1597
  addresses: result.addresses,
1567
- providerType: result.providerType
1598
+ provider: authOptions.provider
1568
1599
  });
1569
1600
  return result;
1570
1601
  }
@@ -1593,7 +1624,7 @@ var ProviderManager = class {
1593
1624
  }
1594
1625
  /**
1595
1626
  * Attempt auto-connect with fallback strategy
1596
- * Tries embedded provider first if it exists, then injected provider
1627
+ * Tries embedded provider first if it exists and is allowed, then injected provider if allowed
1597
1628
  * Returns true if any provider successfully connected
1598
1629
  */
1599
1630
  async autoConnect() {
@@ -1604,7 +1635,8 @@ var ProviderManager = class {
1604
1635
  }
1605
1636
  const embeddedWalletType = this.config.embeddedWalletType || "user-wallet";
1606
1637
  const embeddedKey = this.getProviderKey("embedded", embeddedWalletType);
1607
- if (this.providers.has(embeddedKey)) {
1638
+ const embeddedAllowed = this.config.providers.some((p) => p !== "injected");
1639
+ if (embeddedAllowed && this.providers.has(embeddedKey)) {
1608
1640
  debug.log(DebugCategory.PROVIDER_MANAGER, "Trying auto-connect with existing embedded provider");
1609
1641
  const embeddedProvider = this.providers.get(embeddedKey);
1610
1642
  try {
@@ -1633,8 +1665,9 @@ var ProviderManager = class {
1633
1665
  }
1634
1666
  }
1635
1667
  }
1668
+ const injectedAllowed = this.config.providers.includes("injected");
1636
1669
  const injectedKey = this.getProviderKey("injected");
1637
- if (this.providers.has(injectedKey)) {
1670
+ if (injectedAllowed && this.providers.has(injectedKey)) {
1638
1671
  debug.log(DebugCategory.PROVIDER_MANAGER, "Trying auto-connect with existing injected provider");
1639
1672
  const injectedProvider = this.providers.get(injectedKey);
1640
1673
  try {
@@ -1653,7 +1686,7 @@ var ProviderManager = class {
1653
1686
  });
1654
1687
  }
1655
1688
  }
1656
- debug.log(DebugCategory.PROVIDER_MANAGER, "Auto-connect failed for all existing providers");
1689
+ debug.log(DebugCategory.PROVIDER_MANAGER, "Auto-connect failed for all allowed providers");
1657
1690
  return false;
1658
1691
  }
1659
1692
  /**
@@ -1737,17 +1770,28 @@ var ProviderManager = class {
1737
1770
  }
1738
1771
  /**
1739
1772
  * Set default provider based on initial config
1740
- * Creates both embedded and injected providers for autoConnect fallback
1773
+ * Creates providers based on the allowed providers array
1741
1774
  */
1742
1775
  setDefaultProvider() {
1743
- const defaultType = this.config.providerType || "embedded";
1744
1776
  const defaultEmbeddedType = this.config.embeddedWalletType || "user-wallet";
1745
- if (this.config.appId) {
1746
- debug.log(DebugCategory.PROVIDER_MANAGER, "Creating embedded provider");
1777
+ const hasInjected = this.config.providers.includes("injected");
1778
+ const hasEmbedded = this.config.providers.some((p) => p !== "injected");
1779
+ if (hasInjected) {
1780
+ debug.log(DebugCategory.PROVIDER_MANAGER, "Creating injected provider (allowed by providers array)");
1781
+ this.createProvider("injected");
1782
+ }
1783
+ if (hasEmbedded) {
1784
+ debug.log(DebugCategory.PROVIDER_MANAGER, "Creating embedded provider (allowed by providers array)");
1747
1785
  this.createProvider("embedded", defaultEmbeddedType);
1748
1786
  }
1749
- debug.log(DebugCategory.PROVIDER_MANAGER, "Creating injected provider");
1750
- this.createProvider("injected");
1787
+ let defaultType;
1788
+ if (hasEmbedded && this.providers.has(`embedded-${defaultEmbeddedType}`)) {
1789
+ defaultType = "embedded";
1790
+ } else if (hasInjected && this.providers.has("injected")) {
1791
+ defaultType = "injected";
1792
+ } else {
1793
+ throw new Error("No valid providers could be created from the providers array");
1794
+ }
1751
1795
  const switchOptions = {};
1752
1796
  if (defaultType === "embedded") {
1753
1797
  switchOptions.embeddedWalletType = defaultEmbeddedType;
@@ -1840,20 +1884,39 @@ async function waitForPhantomExtension(timeoutMs = 3e3) {
1840
1884
  }
1841
1885
 
1842
1886
  // src/BrowserSDK.ts
1887
+ import { EMBEDDED_PROVIDER_AUTH_TYPES as EMBEDDED_PROVIDER_AUTH_TYPES2 } from "@phantom/embedded-provider-core";
1843
1888
  import { DEFAULT_EMBEDDED_WALLET_TYPE as DEFAULT_EMBEDDED_WALLET_TYPE2 } from "@phantom/constants";
1889
+ var BROWSER_SDK_PROVIDER_TYPES = [...EMBEDDED_PROVIDER_AUTH_TYPES2, "injected"];
1844
1890
  var BrowserSDK = class {
1845
1891
  constructor(config) {
1846
1892
  debug.info(DebugCategory.BROWSER_SDK, "Initializing BrowserSDK", {
1847
- providerType: config.providerType,
1893
+ providers: config.providers,
1848
1894
  embeddedWalletType: config.embeddedWalletType,
1849
1895
  addressTypes: config.addressTypes
1850
1896
  });
1851
- if (!["injected", "embedded"].includes(config.providerType)) {
1852
- debug.error(DebugCategory.BROWSER_SDK, "Invalid providerType", { providerType: config.providerType });
1853
- throw new Error(`Invalid providerType: ${config.providerType}. Must be "injected" or "embedded".`);
1897
+ if (!Array.isArray(config.providers) || config.providers.length === 0) {
1898
+ debug.error(DebugCategory.BROWSER_SDK, "Invalid providers array", { providers: config.providers });
1899
+ throw new Error("providers must be a non-empty array of AuthProviderType");
1900
+ }
1901
+ const invalidProviders = config.providers.filter((p) => !BROWSER_SDK_PROVIDER_TYPES.includes(p));
1902
+ if (invalidProviders.length > 0) {
1903
+ debug.error(DebugCategory.BROWSER_SDK, "Invalid provider types", {
1904
+ invalidProviders,
1905
+ validProviders: BROWSER_SDK_PROVIDER_TYPES
1906
+ });
1907
+ throw new Error(
1908
+ `Invalid provider type(s): ${invalidProviders.join(", ")}. Valid providers are: ${BROWSER_SDK_PROVIDER_TYPES.join(", ")}`
1909
+ );
1910
+ }
1911
+ const hasEmbeddedProviders = config.providers.some((p) => p !== "injected");
1912
+ if (hasEmbeddedProviders && !config.appId) {
1913
+ debug.error(DebugCategory.BROWSER_SDK, "appId required for embedded providers", {
1914
+ providers: config.providers
1915
+ });
1916
+ throw new Error("appId is required when using embedded providers (google, apple, phantom, etc.)");
1854
1917
  }
1855
1918
  const embeddedWalletType = config.embeddedWalletType || DEFAULT_EMBEDDED_WALLET_TYPE2;
1856
- if (config.providerType === "embedded" && !["app-wallet", "user-wallet"].includes(embeddedWalletType)) {
1919
+ if (!["app-wallet", "user-wallet"].includes(embeddedWalletType)) {
1857
1920
  debug.error(DebugCategory.BROWSER_SDK, "Invalid embeddedWalletType", {
1858
1921
  embeddedWalletType: config.embeddedWalletType
1859
1922
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phantom/browser-sdk",
3
- "version": "1.0.0-beta.21",
3
+ "version": "1.0.0-beta.22",
4
4
  "description": "Browser SDK for Phantom Wallet",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -28,15 +28,15 @@
28
28
  "prettier": "prettier --write \"src/**/*.{ts,tsx}\""
29
29
  },
30
30
  "dependencies": {
31
- "@phantom/base64url": "^1.0.0-beta.9",
32
- "@phantom/browser-injected-sdk": "^1.0.0-beta.6",
33
- "@phantom/chain-interfaces": "^1.0.0-beta.9",
34
- "@phantom/client": "^1.0.0-beta.21",
35
- "@phantom/constants": "^1.0.0-beta.9",
36
- "@phantom/embedded-provider-core": "^1.0.0-beta.21",
37
- "@phantom/indexed-db-stamper": "^1.0.0-beta.2",
38
- "@phantom/parsers": "^1.0.0-beta.9",
39
- "@phantom/sdk-types": "^1.0.0-beta.9",
31
+ "@phantom/base64url": "^1.0.0-beta.10",
32
+ "@phantom/browser-injected-sdk": "^1.0.0-beta.7",
33
+ "@phantom/chain-interfaces": "^1.0.0-beta.10",
34
+ "@phantom/client": "^1.0.0-beta.22",
35
+ "@phantom/constants": "^1.0.0-beta.10",
36
+ "@phantom/embedded-provider-core": "^1.0.0-beta.22",
37
+ "@phantom/indexed-db-stamper": "^1.0.0-beta.3",
38
+ "@phantom/parsers": "^1.0.0-beta.10",
39
+ "@phantom/sdk-types": "^1.0.0-beta.10",
40
40
  "axios": "^1.10.0",
41
41
  "bs58": "^6.0.0",
42
42
  "buffer": "^6.0.3",