@phantom/browser-sdk 1.0.0-beta.1 → 1.0.0-beta.3
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 +37 -60
- package/dist/index.d.ts +19 -8
- package/dist/index.js +149 -34
- package/dist/index.mjs +146 -31
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -44,8 +44,7 @@ import { BrowserSDK, AddressType } from "@phantom/browser-sdk";
|
|
|
44
44
|
const sdk = new BrowserSDK({
|
|
45
45
|
providerType: "embedded",
|
|
46
46
|
addressTypes: [AddressType.solana, AddressType.ethereum],
|
|
47
|
-
|
|
48
|
-
appId: "your-app-id",
|
|
47
|
+
appId: "your-app-id", // Get your app ID from phantom.com/portal
|
|
49
48
|
});
|
|
50
49
|
|
|
51
50
|
const { addresses } = await sdk.connect();
|
|
@@ -190,48 +189,29 @@ Creates a non-custodial wallet embedded in your application. Requires API config
|
|
|
190
189
|
const sdk = new BrowserSDK({
|
|
191
190
|
providerType: "embedded",
|
|
192
191
|
addressTypes: [AddressType.solana, AddressType.ethereum],
|
|
193
|
-
|
|
194
|
-
appId: "your-app-id",
|
|
195
|
-
embeddedWalletType: "app-wallet", // or 'user-wallet'
|
|
192
|
+
appId: "your-app-id", // Get your app ID from phantom.com/portal
|
|
196
193
|
authOptions: {
|
|
197
|
-
authUrl: "https://
|
|
194
|
+
authUrl: "https://connect.phantom.app/login", // optional, defaults to "https://connect.phantom.app/login"
|
|
198
195
|
redirectUrl: "https://yourapp.com/callback", // optional, defaults to current page
|
|
199
196
|
},
|
|
200
197
|
autoConnect: true, // optional, auto-connect to existing session (default: true for embedded)
|
|
201
198
|
});
|
|
202
199
|
```
|
|
203
200
|
|
|
204
|
-
### Embedded Wallet
|
|
205
|
-
|
|
206
|
-
#### App Wallet (`'app-wallet'`)
|
|
207
|
-
|
|
208
|
-
- **New wallets** created per application
|
|
209
|
-
- **Unfunded** by default - you need to fund them
|
|
210
|
-
- **Independent** from user's existing Phantom wallet
|
|
211
|
-
- **Perfect for**: Gaming, DeFi protocols, or apps that need fresh wallets
|
|
212
|
-
|
|
213
|
-
```typescript
|
|
214
|
-
const sdk = new BrowserSDK({
|
|
215
|
-
providerType: "embedded",
|
|
216
|
-
embeddedWalletType: "app-wallet",
|
|
217
|
-
addressTypes: [AddressType.solana],
|
|
218
|
-
// ... other config
|
|
219
|
-
});
|
|
220
|
-
```
|
|
201
|
+
### Embedded Wallet Type
|
|
221
202
|
|
|
222
203
|
#### User Wallet (`'user-wallet'`)
|
|
223
204
|
|
|
224
205
|
- **Uses Phantom authentication** - user logs in with existing Phantom account
|
|
225
206
|
- **Potentially funded** - brings in user's existing wallet balance
|
|
226
207
|
- **Connected** to user's Phantom ecosystem
|
|
227
|
-
- **Perfect for**:
|
|
208
|
+
- **Perfect for**: All embedded wallet use cases
|
|
228
209
|
|
|
229
210
|
```typescript
|
|
230
211
|
const sdk = new BrowserSDK({
|
|
231
212
|
providerType: "embedded",
|
|
232
|
-
|
|
213
|
+
appId: "your-app-id",
|
|
233
214
|
addressTypes: [AddressType.solana, AddressType.ethereum],
|
|
234
|
-
// ... other config
|
|
235
215
|
});
|
|
236
216
|
```
|
|
237
217
|
|
|
@@ -242,28 +222,6 @@ const sdk = new BrowserSDK({
|
|
|
242
222
|
| `AddressType.solana` | Solana Mainnet, Devnet, Testnet |
|
|
243
223
|
| `AddressType.ethereum` | Ethereum, Polygon, Arbitrum, and more |
|
|
244
224
|
|
|
245
|
-
### Solana Provider Configuration
|
|
246
|
-
|
|
247
|
-
When using `AddressType.solana`, you can choose between two Solana libraries:
|
|
248
|
-
|
|
249
|
-
```typescript
|
|
250
|
-
const sdk = new BrowserSDK({
|
|
251
|
-
providerType: "embedded",
|
|
252
|
-
addressTypes: [AddressType.solana],
|
|
253
|
-
solanaProvider: "web3js", // or 'kit'
|
|
254
|
-
// ... other config
|
|
255
|
-
});
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
**Provider Options:**
|
|
259
|
-
|
|
260
|
-
- `'web3js'` (default) - Uses `@solana/web3.js` library
|
|
261
|
-
- `'kit'` - Uses `@solana/kit` library (modern, TypeScript-first)
|
|
262
|
-
|
|
263
|
-
**When to use each:**
|
|
264
|
-
|
|
265
|
-
- **@solana/web3.js**: Better ecosystem compatibility, wider community support
|
|
266
|
-
- **@solana/kit**: Better TypeScript support, modern architecture, smaller bundle size
|
|
267
225
|
|
|
268
226
|
### Auto-Connect Feature
|
|
269
227
|
|
|
@@ -272,8 +230,8 @@ The SDK can automatically reconnect to existing sessions when instantiated, prov
|
|
|
272
230
|
```typescript
|
|
273
231
|
const sdk = new BrowserSDK({
|
|
274
232
|
providerType: "embedded",
|
|
233
|
+
appId: "your-app-id",
|
|
275
234
|
addressTypes: [AddressType.solana],
|
|
276
|
-
// ... other config
|
|
277
235
|
autoConnect: true, // Default: true for embedded, false for injected
|
|
278
236
|
});
|
|
279
237
|
|
|
@@ -295,8 +253,8 @@ if (sdk.isConnected()) {
|
|
|
295
253
|
```typescript
|
|
296
254
|
const sdk = new BrowserSDK({
|
|
297
255
|
providerType: "embedded",
|
|
256
|
+
appId: "your-app-id",
|
|
298
257
|
addressTypes: [AddressType.solana],
|
|
299
|
-
// ... other config
|
|
300
258
|
autoConnect: false, // Disable auto-connect
|
|
301
259
|
});
|
|
302
260
|
|
|
@@ -320,15 +278,16 @@ interface BrowserSDKConfig {
|
|
|
320
278
|
addressTypes?: [AddressType, ...AddressType[]]; // Networks to enable (e.g., [AddressType.solana])
|
|
321
279
|
|
|
322
280
|
// Required for embedded provider only
|
|
323
|
-
|
|
324
|
-
|
|
281
|
+
appId?: string; // Your app ID from phantom.com/portal (required for embedded provider)
|
|
282
|
+
|
|
283
|
+
// Optional configuration
|
|
284
|
+
apiBaseUrl?: string; // Phantom API base URL (optional, has default)
|
|
325
285
|
authOptions?: {
|
|
326
|
-
authUrl?: string; // Custom auth URL (
|
|
327
|
-
redirectUrl?: string; // Custom redirect URL after authentication
|
|
286
|
+
authUrl?: string; // Custom auth URL (optional, defaults to "https://connect.phantom.app/login")
|
|
287
|
+
redirectUrl?: string; // Custom redirect URL after authentication (optional)
|
|
328
288
|
};
|
|
329
|
-
embeddedWalletType?: "
|
|
330
|
-
|
|
331
|
-
autoConnect?: boolean; // Enable auto-connect to existing sessions (default: true)
|
|
289
|
+
embeddedWalletType?: "user-wallet"; // Wallet type (optional, defaults to "user-wallet", currently the only supported type)
|
|
290
|
+
autoConnect?: boolean; // Enable auto-connect to existing sessions (optional, defaults to true for embedded)
|
|
332
291
|
}
|
|
333
292
|
```
|
|
334
293
|
|
|
@@ -463,6 +422,12 @@ const balance = await sdk.ethereum.request({
|
|
|
463
422
|
method: "eth_getBalance",
|
|
464
423
|
params: [address, "latest"],
|
|
465
424
|
});
|
|
425
|
+
|
|
426
|
+
// Sign transaction via RPC (alternative to signTransaction method)
|
|
427
|
+
const signedTx = await sdk.ethereum.request({
|
|
428
|
+
method: "eth_signTransaction",
|
|
429
|
+
params: [{ to: "0x...", value: "0x...", gas: "0x..." }],
|
|
430
|
+
});
|
|
466
431
|
```
|
|
467
432
|
|
|
468
433
|
#### signPersonalMessage(message, address)
|
|
@@ -511,6 +476,20 @@ const signature = await sdk.ethereum.signTypedData(typedData, address);
|
|
|
511
476
|
// Returns: { signature: string, rawSignature: string }
|
|
512
477
|
```
|
|
513
478
|
|
|
479
|
+
#### signTransaction(transaction)
|
|
480
|
+
|
|
481
|
+
Sign an Ethereum transaction without sending it.
|
|
482
|
+
|
|
483
|
+
```typescript
|
|
484
|
+
const signedTx = await sdk.ethereum.signTransaction({
|
|
485
|
+
to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
|
|
486
|
+
value: "1000000000000000000", // 1 ETH in wei
|
|
487
|
+
gas: "21000",
|
|
488
|
+
gasPrice: "20000000000", // 20 gwei
|
|
489
|
+
});
|
|
490
|
+
// Returns: string (hex-encoded signed transaction)
|
|
491
|
+
```
|
|
492
|
+
|
|
514
493
|
#### sendTransaction(transaction)
|
|
515
494
|
|
|
516
495
|
Send an Ethereum transaction.
|
|
@@ -728,7 +707,7 @@ import { BrowserSDK, DebugLevel } from "@phantom/browser-sdk";
|
|
|
728
707
|
|
|
729
708
|
const sdk = new BrowserSDK({
|
|
730
709
|
providerType: "embedded",
|
|
731
|
-
|
|
710
|
+
appId: "your-app-id",
|
|
732
711
|
});
|
|
733
712
|
|
|
734
713
|
// Store debug messages
|
|
@@ -795,7 +774,6 @@ import { BrowserSDK, AddressType } from "@phantom/browser-sdk";
|
|
|
795
774
|
const sdk = new BrowserSDK({
|
|
796
775
|
providerType: "injected",
|
|
797
776
|
addressTypes: [AddressType.solana],
|
|
798
|
-
solanaProvider: "web3js",
|
|
799
777
|
});
|
|
800
778
|
|
|
801
779
|
await sdk.connect();
|
|
@@ -849,7 +827,6 @@ import { BrowserSDK, AddressType } from "@phantom/browser-sdk";
|
|
|
849
827
|
const sdk = new BrowserSDK({
|
|
850
828
|
providerType: "injected",
|
|
851
829
|
addressTypes: [AddressType.solana],
|
|
852
|
-
solanaProvider: "kit",
|
|
853
830
|
});
|
|
854
831
|
|
|
855
832
|
await sdk.connect();
|
package/dist/index.d.ts
CHANGED
|
@@ -57,13 +57,17 @@ interface DebugConfig {
|
|
|
57
57
|
level?: DebugLevel;
|
|
58
58
|
callback?: DebugCallback;
|
|
59
59
|
}
|
|
60
|
-
interface BrowserSDKConfig extends Partial<EmbeddedProviderConfig
|
|
60
|
+
interface BrowserSDKConfig extends Partial<Omit<EmbeddedProviderConfig, "authOptions">> {
|
|
61
61
|
providerType: "injected" | "embedded" | (string & Record<never, never>);
|
|
62
62
|
addressTypes: [AddressType, ...AddressType[]];
|
|
63
63
|
apiBaseUrl?: string;
|
|
64
64
|
appId?: string;
|
|
65
65
|
embeddedWalletType?: "app-wallet" | "user-wallet" | (string & Record<never, never>);
|
|
66
66
|
autoConnect?: boolean;
|
|
67
|
+
authOptions?: {
|
|
68
|
+
authUrl?: string;
|
|
69
|
+
redirectUrl?: string;
|
|
70
|
+
};
|
|
67
71
|
}
|
|
68
72
|
|
|
69
73
|
interface Provider {
|
|
@@ -205,18 +209,13 @@ declare class BrowserSDK {
|
|
|
205
209
|
getSupportedAutoConfirmChains(): Promise<AutoConfirmSupportedChainsResult>;
|
|
206
210
|
}
|
|
207
211
|
|
|
208
|
-
/**
|
|
209
|
-
* Constants used throughout the browser SDK
|
|
210
|
-
*/
|
|
211
|
-
declare const DEFAULT_AUTH_URL = "https://connect.phantom.app";
|
|
212
|
-
declare const DEFAULT_WALLET_API_URL = "https://api.phantom.app/v1/wallets";
|
|
213
|
-
|
|
214
212
|
/**
|
|
215
213
|
* Browser detection utility to identify browser name and version
|
|
216
214
|
*/
|
|
217
215
|
interface BrowserInfo {
|
|
218
216
|
name: string;
|
|
219
217
|
version: string;
|
|
218
|
+
userAgent: string;
|
|
220
219
|
}
|
|
221
220
|
/**
|
|
222
221
|
* Parse browser information from a user agent string
|
|
@@ -237,6 +236,18 @@ declare function getPlatformName(): string;
|
|
|
237
236
|
* Format: "Chrome 120.0" or "Firefox 119.0"
|
|
238
237
|
*/
|
|
239
238
|
declare function getBrowserDisplayName(): string;
|
|
239
|
+
/**
|
|
240
|
+
* Detect if the current device is a mobile device
|
|
241
|
+
* Checks user agent for mobile indicators and screen size
|
|
242
|
+
*/
|
|
243
|
+
declare function isMobileDevice(): boolean;
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Generates a deeplink URL to open the current page in Phantom mobile app
|
|
247
|
+
* @param ref Optional referrer parameter
|
|
248
|
+
* @returns Phantom mobile app deeplink URL
|
|
249
|
+
*/
|
|
250
|
+
declare function getDeeplinkToPhantom(ref?: string): string;
|
|
240
251
|
|
|
241
252
|
/**
|
|
242
253
|
* Wait for Phantom extension to be available with retry logic
|
|
@@ -256,4 +267,4 @@ declare function getBrowserDisplayName(): string;
|
|
|
256
267
|
*/
|
|
257
268
|
declare function waitForPhantomExtension(timeoutMs?: number): Promise<boolean>;
|
|
258
269
|
|
|
259
|
-
export { BrowserInfo, BrowserSDK, BrowserSDKConfig,
|
|
270
|
+
export { BrowserInfo, BrowserSDK, BrowserSDKConfig, DebugCallback, DebugCategory, DebugConfig, DebugLevel, DebugMessage, Provider, debug, detectBrowser, getBrowserDisplayName, getDeeplinkToPhantom, getPlatformName, isMobileDevice, parseBrowserFromUserAgent, waitForPhantomExtension };
|
package/dist/index.js
CHANGED
|
@@ -22,15 +22,15 @@ var src_exports = {};
|
|
|
22
22
|
__export(src_exports, {
|
|
23
23
|
AddressType: () => import_client5.AddressType,
|
|
24
24
|
BrowserSDK: () => BrowserSDK,
|
|
25
|
-
DEFAULT_AUTH_URL: () => DEFAULT_AUTH_URL,
|
|
26
|
-
DEFAULT_WALLET_API_URL: () => DEFAULT_WALLET_API_URL,
|
|
27
25
|
DebugCategory: () => DebugCategory,
|
|
28
26
|
DebugLevel: () => DebugLevel,
|
|
29
|
-
NetworkId: () =>
|
|
27
|
+
NetworkId: () => import_constants5.NetworkId,
|
|
30
28
|
debug: () => debug,
|
|
31
29
|
detectBrowser: () => detectBrowser,
|
|
32
30
|
getBrowserDisplayName: () => getBrowserDisplayName,
|
|
31
|
+
getDeeplinkToPhantom: () => getDeeplinkToPhantom,
|
|
33
32
|
getPlatformName: () => getPlatformName,
|
|
33
|
+
isMobileDevice: () => isMobileDevice,
|
|
34
34
|
parseBrowserFromUserAgent: () => parseBrowserFromUserAgent,
|
|
35
35
|
waitForPhantomExtension: () => waitForPhantomExtension
|
|
36
36
|
});
|
|
@@ -163,17 +163,42 @@ var InjectedSolanaChain = class {
|
|
|
163
163
|
publicKey: this._publicKey || ""
|
|
164
164
|
};
|
|
165
165
|
}
|
|
166
|
-
signTransaction(
|
|
167
|
-
|
|
168
|
-
new Error("
|
|
169
|
-
|
|
166
|
+
async signTransaction(transaction) {
|
|
167
|
+
if (!this.callbacks.isConnected()) {
|
|
168
|
+
return Promise.reject(new Error("Provider not connected. Call provider connect first."));
|
|
169
|
+
}
|
|
170
|
+
try {
|
|
171
|
+
const result = await this.phantom.solana.signTransaction(transaction);
|
|
172
|
+
return result;
|
|
173
|
+
} catch (error) {
|
|
174
|
+
return Promise.reject(error);
|
|
175
|
+
}
|
|
170
176
|
}
|
|
171
177
|
async signAndSendTransaction(transaction) {
|
|
172
178
|
const result = await this.phantom.solana.signAndSendTransaction(transaction);
|
|
173
179
|
return { signature: result.signature };
|
|
174
180
|
}
|
|
175
|
-
signAllTransactions(
|
|
176
|
-
|
|
181
|
+
async signAllTransactions(transactions) {
|
|
182
|
+
if (!this.callbacks.isConnected()) {
|
|
183
|
+
return Promise.reject(new Error("Provider not connected. Call provider connect first."));
|
|
184
|
+
}
|
|
185
|
+
try {
|
|
186
|
+
const result = await this.phantom.solana.signAllTransactions(transactions);
|
|
187
|
+
return result;
|
|
188
|
+
} catch (error) {
|
|
189
|
+
return Promise.reject(error);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
async signAndSendAllTransactions(transactions) {
|
|
193
|
+
if (!this.callbacks.isConnected()) {
|
|
194
|
+
return Promise.reject(new Error("Provider not connected. Call provider connect first."));
|
|
195
|
+
}
|
|
196
|
+
try {
|
|
197
|
+
const result = await this.phantom.solana.signAndSendAllTransactions(transactions);
|
|
198
|
+
return { signatures: result.signatures };
|
|
199
|
+
} catch (error) {
|
|
200
|
+
return Promise.reject(error);
|
|
201
|
+
}
|
|
177
202
|
}
|
|
178
203
|
switchNetwork(_network) {
|
|
179
204
|
return Promise.resolve();
|
|
@@ -253,8 +278,13 @@ var InjectedEthereumChain = class {
|
|
|
253
278
|
get accounts() {
|
|
254
279
|
return this._accounts;
|
|
255
280
|
}
|
|
256
|
-
// EIP-1193 core method
|
|
281
|
+
// EIP-1193 core method with eth_signTransaction support
|
|
257
282
|
async request(args) {
|
|
283
|
+
if (args.method === "eth_signTransaction") {
|
|
284
|
+
const [transaction] = args.params;
|
|
285
|
+
const result = await this.signTransaction(transaction);
|
|
286
|
+
return result;
|
|
287
|
+
}
|
|
258
288
|
const provider = await this.phantom.ethereum.getProvider();
|
|
259
289
|
return await provider.request(args);
|
|
260
290
|
}
|
|
@@ -278,6 +308,9 @@ var InjectedEthereumChain = class {
|
|
|
278
308
|
async signTypedData(typedData, address) {
|
|
279
309
|
return await this.phantom.ethereum.signTypedData(typedData, address);
|
|
280
310
|
}
|
|
311
|
+
async signTransaction(transaction) {
|
|
312
|
+
return await this.phantom.ethereum.signTransaction(transaction);
|
|
313
|
+
}
|
|
281
314
|
async sendTransaction(transaction) {
|
|
282
315
|
return await this.phantom.ethereum.sendTransaction(transaction);
|
|
283
316
|
}
|
|
@@ -794,15 +827,19 @@ var BrowserURLParamsAccessor = class {
|
|
|
794
827
|
};
|
|
795
828
|
var browserUrlParamsAccessor = new BrowserURLParamsAccessor();
|
|
796
829
|
|
|
797
|
-
// src/constants.ts
|
|
798
|
-
var DEFAULT_AUTH_URL = "https://connect.phantom.app";
|
|
799
|
-
var DEFAULT_WALLET_API_URL = "https://api.phantom.app/v1/wallets";
|
|
800
|
-
|
|
801
830
|
// src/providers/embedded/adapters/auth.ts
|
|
831
|
+
var import_constants = require("@phantom/constants");
|
|
802
832
|
var BrowserAuthProvider = class {
|
|
803
833
|
constructor(urlParamsAccessor) {
|
|
804
834
|
this.urlParamsAccessor = urlParamsAccessor;
|
|
805
835
|
}
|
|
836
|
+
getValidatedCurrentUrl() {
|
|
837
|
+
const currentUrl = window.location.href;
|
|
838
|
+
if (!currentUrl.startsWith("http:") && !currentUrl.startsWith("https:")) {
|
|
839
|
+
throw new Error("Invalid URL protocol - only HTTP/HTTPS URLs are supported");
|
|
840
|
+
}
|
|
841
|
+
return currentUrl;
|
|
842
|
+
}
|
|
806
843
|
authenticate(options) {
|
|
807
844
|
return new Promise((resolve) => {
|
|
808
845
|
if ("jwtToken" in options) {
|
|
@@ -817,13 +854,13 @@ var BrowserAuthProvider = class {
|
|
|
817
854
|
authUrl: phantomOptions.authUrl,
|
|
818
855
|
hasCustomData: !!phantomOptions.customAuthData
|
|
819
856
|
});
|
|
820
|
-
const baseUrl = phantomOptions.authUrl || DEFAULT_AUTH_URL;
|
|
857
|
+
const baseUrl = phantomOptions.authUrl || import_constants.DEFAULT_AUTH_URL;
|
|
821
858
|
debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Using auth URL", { baseUrl });
|
|
822
859
|
const params = new URLSearchParams({
|
|
823
860
|
organization_id: phantomOptions.organizationId,
|
|
824
861
|
parent_organization_id: phantomOptions.parentOrganizationId,
|
|
825
862
|
app_id: phantomOptions.appId,
|
|
826
|
-
redirect_uri: phantomOptions.redirectUrl || (typeof window !== "undefined" ?
|
|
863
|
+
redirect_uri: phantomOptions.redirectUrl || (typeof window !== "undefined" ? this.getValidatedCurrentUrl() : ""),
|
|
827
864
|
session_id: phantomOptions.sessionId,
|
|
828
865
|
clear_previous_session: true.toString()
|
|
829
866
|
});
|
|
@@ -851,6 +888,9 @@ var BrowserAuthProvider = class {
|
|
|
851
888
|
debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Stored auth context in session storage", { authContext });
|
|
852
889
|
const authUrl = `${baseUrl}?${params.toString()}`;
|
|
853
890
|
debug.info(DebugCategory.PHANTOM_CONNECT_AUTH, "Redirecting to Phantom Connect", { authUrl });
|
|
891
|
+
if (!authUrl.startsWith("https:")) {
|
|
892
|
+
throw new Error("Invalid auth URL - only HTTPS URLs are allowed for authentication");
|
|
893
|
+
}
|
|
854
894
|
window.location.href = authUrl;
|
|
855
895
|
resolve();
|
|
856
896
|
});
|
|
@@ -939,7 +979,7 @@ function parseBrowserFromUserAgent(userAgent, hasBraveAPI) {
|
|
|
939
979
|
let name = "unknown";
|
|
940
980
|
let version = "unknown";
|
|
941
981
|
if (!userAgent || typeof userAgent !== "string") {
|
|
942
|
-
return { name, version };
|
|
982
|
+
return { name, version, userAgent: "unknown" };
|
|
943
983
|
}
|
|
944
984
|
try {
|
|
945
985
|
if (userAgent.includes("Edg/")) {
|
|
@@ -1021,11 +1061,11 @@ function parseBrowserFromUserAgent(userAgent, hasBraveAPI) {
|
|
|
1021
1061
|
}
|
|
1022
1062
|
} catch (error) {
|
|
1023
1063
|
}
|
|
1024
|
-
return { name, version };
|
|
1064
|
+
return { name, version, userAgent };
|
|
1025
1065
|
}
|
|
1026
1066
|
function detectBrowser() {
|
|
1027
1067
|
if (typeof window === "undefined" || !window.navigator?.userAgent) {
|
|
1028
|
-
return { name: "unknown", version: "unknown" };
|
|
1068
|
+
return { name: "unknown", version: "unknown", userAgent: "unknown" };
|
|
1029
1069
|
}
|
|
1030
1070
|
const userAgent = window.navigator.userAgent;
|
|
1031
1071
|
const hasBraveAPI = !!navigator.brave;
|
|
@@ -1040,8 +1080,41 @@ function getBrowserDisplayName() {
|
|
|
1040
1080
|
const capitalizedName = name.charAt(0).toUpperCase() + name.slice(1);
|
|
1041
1081
|
return version !== "unknown" ? `${capitalizedName} ${version}` : capitalizedName;
|
|
1042
1082
|
}
|
|
1083
|
+
function isMobileDevice() {
|
|
1084
|
+
if (typeof window === "undefined" || !window.navigator?.userAgent) {
|
|
1085
|
+
return false;
|
|
1086
|
+
}
|
|
1087
|
+
const userAgent = window.navigator.userAgent.toLowerCase();
|
|
1088
|
+
const mobilePatterns = [
|
|
1089
|
+
/android/,
|
|
1090
|
+
/iphone|ipad|ipod/,
|
|
1091
|
+
/blackberry/,
|
|
1092
|
+
/windows phone/,
|
|
1093
|
+
/mobile/,
|
|
1094
|
+
/tablet/,
|
|
1095
|
+
/silk/,
|
|
1096
|
+
/kindle/,
|
|
1097
|
+
/opera mini/,
|
|
1098
|
+
/opera mobi/
|
|
1099
|
+
];
|
|
1100
|
+
const isMobileUA = mobilePatterns.some((pattern) => pattern.test(userAgent));
|
|
1101
|
+
let isSmallScreen = false;
|
|
1102
|
+
try {
|
|
1103
|
+
isSmallScreen = window.screen.width <= 768 || window.screen.height <= 768;
|
|
1104
|
+
} catch (error) {
|
|
1105
|
+
isSmallScreen = false;
|
|
1106
|
+
}
|
|
1107
|
+
let isTouchDevice = false;
|
|
1108
|
+
try {
|
|
1109
|
+
isTouchDevice = "ontouchstart" in window || navigator.maxTouchPoints > 0;
|
|
1110
|
+
} catch (error) {
|
|
1111
|
+
isTouchDevice = false;
|
|
1112
|
+
}
|
|
1113
|
+
return isMobileUA || isSmallScreen && isTouchDevice;
|
|
1114
|
+
}
|
|
1043
1115
|
|
|
1044
1116
|
// src/providers/embedded/index.ts
|
|
1117
|
+
var import_constants2 = require("@phantom/constants");
|
|
1045
1118
|
var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvider {
|
|
1046
1119
|
constructor(config) {
|
|
1047
1120
|
debug.log(DebugCategory.EMBEDDED_PROVIDER, "Initializing Browser EmbeddedProvider", { config });
|
|
@@ -1052,13 +1125,25 @@ var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvi
|
|
|
1052
1125
|
keyName: "signing-key"
|
|
1053
1126
|
});
|
|
1054
1127
|
const platformName = getPlatformName();
|
|
1128
|
+
const { name: browserName, version } = detectBrowser();
|
|
1055
1129
|
const platform = {
|
|
1056
1130
|
storage: new BrowserStorage(),
|
|
1057
1131
|
authProvider: new BrowserAuthProvider(urlParamsAccessor),
|
|
1058
1132
|
urlParamsAccessor,
|
|
1059
1133
|
stamper,
|
|
1060
|
-
name: platformName
|
|
1134
|
+
name: platformName,
|
|
1061
1135
|
// Use detected browser name and version for identification
|
|
1136
|
+
analyticsHeaders: {
|
|
1137
|
+
[import_constants2.ANALYTICS_HEADERS.SDK_TYPE]: "browser",
|
|
1138
|
+
[import_constants2.ANALYTICS_HEADERS.PLATFORM]: browserName,
|
|
1139
|
+
// firefox, chrome, safari, etc.
|
|
1140
|
+
[import_constants2.ANALYTICS_HEADERS.PLATFORM_VERSION]: version,
|
|
1141
|
+
// Full user agent for more detailed info
|
|
1142
|
+
[import_constants2.ANALYTICS_HEADERS.APP_ID]: config.appId,
|
|
1143
|
+
[import_constants2.ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
|
|
1144
|
+
[import_constants2.ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.3"
|
|
1145
|
+
// Replaced at build time
|
|
1146
|
+
}
|
|
1062
1147
|
};
|
|
1063
1148
|
debug.log(DebugCategory.EMBEDDED_PROVIDER, "Detected platform", { platformName });
|
|
1064
1149
|
const logger = new BrowserLogger();
|
|
@@ -1068,6 +1153,7 @@ var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvi
|
|
|
1068
1153
|
};
|
|
1069
1154
|
|
|
1070
1155
|
// src/ProviderManager.ts
|
|
1156
|
+
var import_constants3 = require("@phantom/constants");
|
|
1071
1157
|
var ProviderManager = class {
|
|
1072
1158
|
// Track which providers have forwarding set up
|
|
1073
1159
|
constructor(config) {
|
|
@@ -1086,6 +1172,15 @@ var ProviderManager = class {
|
|
|
1086
1172
|
currentProviderKey: this.currentProviderKey
|
|
1087
1173
|
});
|
|
1088
1174
|
}
|
|
1175
|
+
getValidatedCurrentUrl() {
|
|
1176
|
+
if (typeof window === "undefined")
|
|
1177
|
+
return "";
|
|
1178
|
+
const currentUrl = window.location.href;
|
|
1179
|
+
if (!currentUrl.startsWith("http:") && !currentUrl.startsWith("https:")) {
|
|
1180
|
+
throw new Error("Invalid URL protocol - only HTTP/HTTPS URLs are supported");
|
|
1181
|
+
}
|
|
1182
|
+
return currentUrl;
|
|
1183
|
+
}
|
|
1089
1184
|
/**
|
|
1090
1185
|
* Switch to a different provider type
|
|
1091
1186
|
*/
|
|
@@ -1117,7 +1212,8 @@ var ProviderManager = class {
|
|
|
1117
1212
|
getCurrentProviderInfo() {
|
|
1118
1213
|
if (!this.currentProviderKey)
|
|
1119
1214
|
return null;
|
|
1120
|
-
const
|
|
1215
|
+
const parts = this.currentProviderKey.split("-");
|
|
1216
|
+
const [type, embeddedWalletType] = parts;
|
|
1121
1217
|
return {
|
|
1122
1218
|
type,
|
|
1123
1219
|
embeddedWalletType
|
|
@@ -1263,7 +1359,7 @@ var ProviderManager = class {
|
|
|
1263
1359
|
*/
|
|
1264
1360
|
setDefaultProvider() {
|
|
1265
1361
|
const defaultType = this.config.providerType || "embedded";
|
|
1266
|
-
const defaultEmbeddedType = this.config.embeddedWalletType || "
|
|
1362
|
+
const defaultEmbeddedType = this.config.embeddedWalletType || "user-wallet";
|
|
1267
1363
|
this.createProvider(defaultType, defaultEmbeddedType);
|
|
1268
1364
|
this.switchProvider(defaultType, { embeddedWalletType: defaultEmbeddedType });
|
|
1269
1365
|
}
|
|
@@ -1277,22 +1373,28 @@ var ProviderManager = class {
|
|
|
1277
1373
|
let provider;
|
|
1278
1374
|
if (type === "injected") {
|
|
1279
1375
|
provider = new InjectedProvider({
|
|
1280
|
-
solanaProvider: this.config.solanaProvider || "web3js",
|
|
1281
1376
|
addressTypes: this.config.addressTypes
|
|
1282
1377
|
});
|
|
1283
|
-
} else {
|
|
1284
|
-
if (!this.config.
|
|
1285
|
-
throw new Error("
|
|
1378
|
+
} else if (type === "embedded") {
|
|
1379
|
+
if (!this.config.appId) {
|
|
1380
|
+
throw new Error("appId is required for embedded provider");
|
|
1286
1381
|
}
|
|
1382
|
+
const apiBaseUrl = this.config.apiBaseUrl || import_constants3.DEFAULT_WALLET_API_URL;
|
|
1383
|
+
const authUrl = this.config.authOptions?.authUrl || import_constants3.DEFAULT_AUTH_URL;
|
|
1287
1384
|
provider = new EmbeddedProvider({
|
|
1288
|
-
apiBaseUrl
|
|
1385
|
+
apiBaseUrl,
|
|
1289
1386
|
organizationId: this.config.appId,
|
|
1290
1387
|
appId: this.config.appId,
|
|
1291
|
-
authOptions:
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1388
|
+
authOptions: {
|
|
1389
|
+
...this.config.authOptions || {},
|
|
1390
|
+
authUrl,
|
|
1391
|
+
redirectUrl: this.config.authOptions?.redirectUrl || this.getValidatedCurrentUrl()
|
|
1392
|
+
},
|
|
1393
|
+
embeddedWalletType: embeddedWalletType || import_constants3.DEFAULT_EMBEDDED_WALLET_TYPE,
|
|
1394
|
+
addressTypes: this.config.addressTypes
|
|
1295
1395
|
});
|
|
1396
|
+
} else {
|
|
1397
|
+
throw new Error(`Unsupported provider type: ${type}`);
|
|
1296
1398
|
}
|
|
1297
1399
|
this.providers.set(key, provider);
|
|
1298
1400
|
}
|
|
@@ -1302,8 +1404,10 @@ var ProviderManager = class {
|
|
|
1302
1404
|
getProviderKey(type, embeddedWalletType) {
|
|
1303
1405
|
if (type === "injected") {
|
|
1304
1406
|
return "injected";
|
|
1407
|
+
} else if (type === "embedded") {
|
|
1408
|
+
return `embedded-${embeddedWalletType || "app-wallet"}`;
|
|
1305
1409
|
}
|
|
1306
|
-
|
|
1410
|
+
throw new Error(`Unsupported provider type: ${type}`);
|
|
1307
1411
|
}
|
|
1308
1412
|
/**
|
|
1309
1413
|
* Save provider preference to localStorage
|
|
@@ -1364,6 +1468,7 @@ async function waitForPhantomExtension(timeoutMs = 3e3) {
|
|
|
1364
1468
|
}
|
|
1365
1469
|
|
|
1366
1470
|
// src/BrowserSDK.ts
|
|
1471
|
+
var import_constants4 = require("@phantom/constants");
|
|
1367
1472
|
var BrowserSDK = class {
|
|
1368
1473
|
constructor(config) {
|
|
1369
1474
|
debug.info(DebugCategory.BROWSER_SDK, "Initializing BrowserSDK", {
|
|
@@ -1375,7 +1480,7 @@ var BrowserSDK = class {
|
|
|
1375
1480
|
debug.error(DebugCategory.BROWSER_SDK, "Invalid providerType", { providerType: config.providerType });
|
|
1376
1481
|
throw new Error(`Invalid providerType: ${config.providerType}. Must be "injected" or "embedded".`);
|
|
1377
1482
|
}
|
|
1378
|
-
const embeddedWalletType = config.embeddedWalletType ||
|
|
1483
|
+
const embeddedWalletType = config.embeddedWalletType || import_constants4.DEFAULT_EMBEDDED_WALLET_TYPE;
|
|
1379
1484
|
if (config.providerType === "embedded" && !["app-wallet", "user-wallet"].includes(embeddedWalletType)) {
|
|
1380
1485
|
debug.error(DebugCategory.BROWSER_SDK, "Invalid embeddedWalletType", {
|
|
1381
1486
|
embeddedWalletType: config.embeddedWalletType
|
|
@@ -1663,6 +1768,16 @@ var BrowserSDK = class {
|
|
|
1663
1768
|
// src/types.ts
|
|
1664
1769
|
var import_client4 = require("@phantom/client");
|
|
1665
1770
|
|
|
1771
|
+
// src/utils/deeplink.ts
|
|
1772
|
+
function getDeeplinkToPhantom(ref) {
|
|
1773
|
+
if (!window.location.href.startsWith("http:") && !window.location.href.startsWith("https:")) {
|
|
1774
|
+
throw new Error("Invalid URL protocol - only HTTP/HTTPS URLs are supported for deeplinks");
|
|
1775
|
+
}
|
|
1776
|
+
const currentUrl = encodeURIComponent(window.location.href);
|
|
1777
|
+
const refParam = ref ? `?ref=${encodeURIComponent(ref)}` : "";
|
|
1778
|
+
return `https://phantom.app/ul/browse/${currentUrl}${refParam}`;
|
|
1779
|
+
}
|
|
1780
|
+
|
|
1666
1781
|
// src/index.ts
|
|
1667
|
-
var
|
|
1782
|
+
var import_constants5 = require("@phantom/constants");
|
|
1668
1783
|
var import_client5 = require("@phantom/client");
|
package/dist/index.mjs
CHANGED
|
@@ -127,17 +127,42 @@ var InjectedSolanaChain = class {
|
|
|
127
127
|
publicKey: this._publicKey || ""
|
|
128
128
|
};
|
|
129
129
|
}
|
|
130
|
-
signTransaction(
|
|
131
|
-
|
|
132
|
-
new Error("
|
|
133
|
-
|
|
130
|
+
async signTransaction(transaction) {
|
|
131
|
+
if (!this.callbacks.isConnected()) {
|
|
132
|
+
return Promise.reject(new Error("Provider not connected. Call provider connect first."));
|
|
133
|
+
}
|
|
134
|
+
try {
|
|
135
|
+
const result = await this.phantom.solana.signTransaction(transaction);
|
|
136
|
+
return result;
|
|
137
|
+
} catch (error) {
|
|
138
|
+
return Promise.reject(error);
|
|
139
|
+
}
|
|
134
140
|
}
|
|
135
141
|
async signAndSendTransaction(transaction) {
|
|
136
142
|
const result = await this.phantom.solana.signAndSendTransaction(transaction);
|
|
137
143
|
return { signature: result.signature };
|
|
138
144
|
}
|
|
139
|
-
signAllTransactions(
|
|
140
|
-
|
|
145
|
+
async signAllTransactions(transactions) {
|
|
146
|
+
if (!this.callbacks.isConnected()) {
|
|
147
|
+
return Promise.reject(new Error("Provider not connected. Call provider connect first."));
|
|
148
|
+
}
|
|
149
|
+
try {
|
|
150
|
+
const result = await this.phantom.solana.signAllTransactions(transactions);
|
|
151
|
+
return result;
|
|
152
|
+
} catch (error) {
|
|
153
|
+
return Promise.reject(error);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
async signAndSendAllTransactions(transactions) {
|
|
157
|
+
if (!this.callbacks.isConnected()) {
|
|
158
|
+
return Promise.reject(new Error("Provider not connected. Call provider connect first."));
|
|
159
|
+
}
|
|
160
|
+
try {
|
|
161
|
+
const result = await this.phantom.solana.signAndSendAllTransactions(transactions);
|
|
162
|
+
return { signatures: result.signatures };
|
|
163
|
+
} catch (error) {
|
|
164
|
+
return Promise.reject(error);
|
|
165
|
+
}
|
|
141
166
|
}
|
|
142
167
|
switchNetwork(_network) {
|
|
143
168
|
return Promise.resolve();
|
|
@@ -217,8 +242,13 @@ var InjectedEthereumChain = class {
|
|
|
217
242
|
get accounts() {
|
|
218
243
|
return this._accounts;
|
|
219
244
|
}
|
|
220
|
-
// EIP-1193 core method
|
|
245
|
+
// EIP-1193 core method with eth_signTransaction support
|
|
221
246
|
async request(args) {
|
|
247
|
+
if (args.method === "eth_signTransaction") {
|
|
248
|
+
const [transaction] = args.params;
|
|
249
|
+
const result = await this.signTransaction(transaction);
|
|
250
|
+
return result;
|
|
251
|
+
}
|
|
222
252
|
const provider = await this.phantom.ethereum.getProvider();
|
|
223
253
|
return await provider.request(args);
|
|
224
254
|
}
|
|
@@ -242,6 +272,9 @@ var InjectedEthereumChain = class {
|
|
|
242
272
|
async signTypedData(typedData, address) {
|
|
243
273
|
return await this.phantom.ethereum.signTypedData(typedData, address);
|
|
244
274
|
}
|
|
275
|
+
async signTransaction(transaction) {
|
|
276
|
+
return await this.phantom.ethereum.signTransaction(transaction);
|
|
277
|
+
}
|
|
245
278
|
async sendTransaction(transaction) {
|
|
246
279
|
return await this.phantom.ethereum.sendTransaction(transaction);
|
|
247
280
|
}
|
|
@@ -758,15 +791,19 @@ var BrowserURLParamsAccessor = class {
|
|
|
758
791
|
};
|
|
759
792
|
var browserUrlParamsAccessor = new BrowserURLParamsAccessor();
|
|
760
793
|
|
|
761
|
-
// src/constants.ts
|
|
762
|
-
var DEFAULT_AUTH_URL = "https://connect.phantom.app";
|
|
763
|
-
var DEFAULT_WALLET_API_URL = "https://api.phantom.app/v1/wallets";
|
|
764
|
-
|
|
765
794
|
// src/providers/embedded/adapters/auth.ts
|
|
795
|
+
import { DEFAULT_AUTH_URL } from "@phantom/constants";
|
|
766
796
|
var BrowserAuthProvider = class {
|
|
767
797
|
constructor(urlParamsAccessor) {
|
|
768
798
|
this.urlParamsAccessor = urlParamsAccessor;
|
|
769
799
|
}
|
|
800
|
+
getValidatedCurrentUrl() {
|
|
801
|
+
const currentUrl = window.location.href;
|
|
802
|
+
if (!currentUrl.startsWith("http:") && !currentUrl.startsWith("https:")) {
|
|
803
|
+
throw new Error("Invalid URL protocol - only HTTP/HTTPS URLs are supported");
|
|
804
|
+
}
|
|
805
|
+
return currentUrl;
|
|
806
|
+
}
|
|
770
807
|
authenticate(options) {
|
|
771
808
|
return new Promise((resolve) => {
|
|
772
809
|
if ("jwtToken" in options) {
|
|
@@ -787,7 +824,7 @@ var BrowserAuthProvider = class {
|
|
|
787
824
|
organization_id: phantomOptions.organizationId,
|
|
788
825
|
parent_organization_id: phantomOptions.parentOrganizationId,
|
|
789
826
|
app_id: phantomOptions.appId,
|
|
790
|
-
redirect_uri: phantomOptions.redirectUrl || (typeof window !== "undefined" ?
|
|
827
|
+
redirect_uri: phantomOptions.redirectUrl || (typeof window !== "undefined" ? this.getValidatedCurrentUrl() : ""),
|
|
791
828
|
session_id: phantomOptions.sessionId,
|
|
792
829
|
clear_previous_session: true.toString()
|
|
793
830
|
});
|
|
@@ -815,6 +852,9 @@ var BrowserAuthProvider = class {
|
|
|
815
852
|
debug.log(DebugCategory.PHANTOM_CONNECT_AUTH, "Stored auth context in session storage", { authContext });
|
|
816
853
|
const authUrl = `${baseUrl}?${params.toString()}`;
|
|
817
854
|
debug.info(DebugCategory.PHANTOM_CONNECT_AUTH, "Redirecting to Phantom Connect", { authUrl });
|
|
855
|
+
if (!authUrl.startsWith("https:")) {
|
|
856
|
+
throw new Error("Invalid auth URL - only HTTPS URLs are allowed for authentication");
|
|
857
|
+
}
|
|
818
858
|
window.location.href = authUrl;
|
|
819
859
|
resolve();
|
|
820
860
|
});
|
|
@@ -903,7 +943,7 @@ function parseBrowserFromUserAgent(userAgent, hasBraveAPI) {
|
|
|
903
943
|
let name = "unknown";
|
|
904
944
|
let version = "unknown";
|
|
905
945
|
if (!userAgent || typeof userAgent !== "string") {
|
|
906
|
-
return { name, version };
|
|
946
|
+
return { name, version, userAgent: "unknown" };
|
|
907
947
|
}
|
|
908
948
|
try {
|
|
909
949
|
if (userAgent.includes("Edg/")) {
|
|
@@ -985,11 +1025,11 @@ function parseBrowserFromUserAgent(userAgent, hasBraveAPI) {
|
|
|
985
1025
|
}
|
|
986
1026
|
} catch (error) {
|
|
987
1027
|
}
|
|
988
|
-
return { name, version };
|
|
1028
|
+
return { name, version, userAgent };
|
|
989
1029
|
}
|
|
990
1030
|
function detectBrowser() {
|
|
991
1031
|
if (typeof window === "undefined" || !window.navigator?.userAgent) {
|
|
992
|
-
return { name: "unknown", version: "unknown" };
|
|
1032
|
+
return { name: "unknown", version: "unknown", userAgent: "unknown" };
|
|
993
1033
|
}
|
|
994
1034
|
const userAgent = window.navigator.userAgent;
|
|
995
1035
|
const hasBraveAPI = !!navigator.brave;
|
|
@@ -1004,8 +1044,41 @@ function getBrowserDisplayName() {
|
|
|
1004
1044
|
const capitalizedName = name.charAt(0).toUpperCase() + name.slice(1);
|
|
1005
1045
|
return version !== "unknown" ? `${capitalizedName} ${version}` : capitalizedName;
|
|
1006
1046
|
}
|
|
1047
|
+
function isMobileDevice() {
|
|
1048
|
+
if (typeof window === "undefined" || !window.navigator?.userAgent) {
|
|
1049
|
+
return false;
|
|
1050
|
+
}
|
|
1051
|
+
const userAgent = window.navigator.userAgent.toLowerCase();
|
|
1052
|
+
const mobilePatterns = [
|
|
1053
|
+
/android/,
|
|
1054
|
+
/iphone|ipad|ipod/,
|
|
1055
|
+
/blackberry/,
|
|
1056
|
+
/windows phone/,
|
|
1057
|
+
/mobile/,
|
|
1058
|
+
/tablet/,
|
|
1059
|
+
/silk/,
|
|
1060
|
+
/kindle/,
|
|
1061
|
+
/opera mini/,
|
|
1062
|
+
/opera mobi/
|
|
1063
|
+
];
|
|
1064
|
+
const isMobileUA = mobilePatterns.some((pattern) => pattern.test(userAgent));
|
|
1065
|
+
let isSmallScreen = false;
|
|
1066
|
+
try {
|
|
1067
|
+
isSmallScreen = window.screen.width <= 768 || window.screen.height <= 768;
|
|
1068
|
+
} catch (error) {
|
|
1069
|
+
isSmallScreen = false;
|
|
1070
|
+
}
|
|
1071
|
+
let isTouchDevice = false;
|
|
1072
|
+
try {
|
|
1073
|
+
isTouchDevice = "ontouchstart" in window || navigator.maxTouchPoints > 0;
|
|
1074
|
+
} catch (error) {
|
|
1075
|
+
isTouchDevice = false;
|
|
1076
|
+
}
|
|
1077
|
+
return isMobileUA || isSmallScreen && isTouchDevice;
|
|
1078
|
+
}
|
|
1007
1079
|
|
|
1008
1080
|
// src/providers/embedded/index.ts
|
|
1081
|
+
import { ANALYTICS_HEADERS } from "@phantom/constants";
|
|
1009
1082
|
var EmbeddedProvider = class extends CoreEmbeddedProvider {
|
|
1010
1083
|
constructor(config) {
|
|
1011
1084
|
debug.log(DebugCategory.EMBEDDED_PROVIDER, "Initializing Browser EmbeddedProvider", { config });
|
|
@@ -1016,13 +1089,25 @@ var EmbeddedProvider = class extends CoreEmbeddedProvider {
|
|
|
1016
1089
|
keyName: "signing-key"
|
|
1017
1090
|
});
|
|
1018
1091
|
const platformName = getPlatformName();
|
|
1092
|
+
const { name: browserName, version } = detectBrowser();
|
|
1019
1093
|
const platform = {
|
|
1020
1094
|
storage: new BrowserStorage(),
|
|
1021
1095
|
authProvider: new BrowserAuthProvider(urlParamsAccessor),
|
|
1022
1096
|
urlParamsAccessor,
|
|
1023
1097
|
stamper,
|
|
1024
|
-
name: platformName
|
|
1098
|
+
name: platformName,
|
|
1025
1099
|
// Use detected browser name and version for identification
|
|
1100
|
+
analyticsHeaders: {
|
|
1101
|
+
[ANALYTICS_HEADERS.SDK_TYPE]: "browser",
|
|
1102
|
+
[ANALYTICS_HEADERS.PLATFORM]: browserName,
|
|
1103
|
+
// firefox, chrome, safari, etc.
|
|
1104
|
+
[ANALYTICS_HEADERS.PLATFORM_VERSION]: version,
|
|
1105
|
+
// Full user agent for more detailed info
|
|
1106
|
+
[ANALYTICS_HEADERS.APP_ID]: config.appId,
|
|
1107
|
+
[ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
|
|
1108
|
+
[ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.3"
|
|
1109
|
+
// Replaced at build time
|
|
1110
|
+
}
|
|
1026
1111
|
};
|
|
1027
1112
|
debug.log(DebugCategory.EMBEDDED_PROVIDER, "Detected platform", { platformName });
|
|
1028
1113
|
const logger = new BrowserLogger();
|
|
@@ -1032,6 +1117,7 @@ var EmbeddedProvider = class extends CoreEmbeddedProvider {
|
|
|
1032
1117
|
};
|
|
1033
1118
|
|
|
1034
1119
|
// src/ProviderManager.ts
|
|
1120
|
+
import { DEFAULT_WALLET_API_URL, DEFAULT_EMBEDDED_WALLET_TYPE, DEFAULT_AUTH_URL as DEFAULT_AUTH_URL2 } from "@phantom/constants";
|
|
1035
1121
|
var ProviderManager = class {
|
|
1036
1122
|
// Track which providers have forwarding set up
|
|
1037
1123
|
constructor(config) {
|
|
@@ -1050,6 +1136,15 @@ var ProviderManager = class {
|
|
|
1050
1136
|
currentProviderKey: this.currentProviderKey
|
|
1051
1137
|
});
|
|
1052
1138
|
}
|
|
1139
|
+
getValidatedCurrentUrl() {
|
|
1140
|
+
if (typeof window === "undefined")
|
|
1141
|
+
return "";
|
|
1142
|
+
const currentUrl = window.location.href;
|
|
1143
|
+
if (!currentUrl.startsWith("http:") && !currentUrl.startsWith("https:")) {
|
|
1144
|
+
throw new Error("Invalid URL protocol - only HTTP/HTTPS URLs are supported");
|
|
1145
|
+
}
|
|
1146
|
+
return currentUrl;
|
|
1147
|
+
}
|
|
1053
1148
|
/**
|
|
1054
1149
|
* Switch to a different provider type
|
|
1055
1150
|
*/
|
|
@@ -1081,7 +1176,8 @@ var ProviderManager = class {
|
|
|
1081
1176
|
getCurrentProviderInfo() {
|
|
1082
1177
|
if (!this.currentProviderKey)
|
|
1083
1178
|
return null;
|
|
1084
|
-
const
|
|
1179
|
+
const parts = this.currentProviderKey.split("-");
|
|
1180
|
+
const [type, embeddedWalletType] = parts;
|
|
1085
1181
|
return {
|
|
1086
1182
|
type,
|
|
1087
1183
|
embeddedWalletType
|
|
@@ -1227,7 +1323,7 @@ var ProviderManager = class {
|
|
|
1227
1323
|
*/
|
|
1228
1324
|
setDefaultProvider() {
|
|
1229
1325
|
const defaultType = this.config.providerType || "embedded";
|
|
1230
|
-
const defaultEmbeddedType = this.config.embeddedWalletType || "
|
|
1326
|
+
const defaultEmbeddedType = this.config.embeddedWalletType || "user-wallet";
|
|
1231
1327
|
this.createProvider(defaultType, defaultEmbeddedType);
|
|
1232
1328
|
this.switchProvider(defaultType, { embeddedWalletType: defaultEmbeddedType });
|
|
1233
1329
|
}
|
|
@@ -1241,22 +1337,28 @@ var ProviderManager = class {
|
|
|
1241
1337
|
let provider;
|
|
1242
1338
|
if (type === "injected") {
|
|
1243
1339
|
provider = new InjectedProvider({
|
|
1244
|
-
solanaProvider: this.config.solanaProvider || "web3js",
|
|
1245
1340
|
addressTypes: this.config.addressTypes
|
|
1246
1341
|
});
|
|
1247
|
-
} else {
|
|
1248
|
-
if (!this.config.
|
|
1249
|
-
throw new Error("
|
|
1342
|
+
} else if (type === "embedded") {
|
|
1343
|
+
if (!this.config.appId) {
|
|
1344
|
+
throw new Error("appId is required for embedded provider");
|
|
1250
1345
|
}
|
|
1346
|
+
const apiBaseUrl = this.config.apiBaseUrl || DEFAULT_WALLET_API_URL;
|
|
1347
|
+
const authUrl = this.config.authOptions?.authUrl || DEFAULT_AUTH_URL2;
|
|
1251
1348
|
provider = new EmbeddedProvider({
|
|
1252
|
-
apiBaseUrl
|
|
1349
|
+
apiBaseUrl,
|
|
1253
1350
|
organizationId: this.config.appId,
|
|
1254
1351
|
appId: this.config.appId,
|
|
1255
|
-
authOptions:
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1352
|
+
authOptions: {
|
|
1353
|
+
...this.config.authOptions || {},
|
|
1354
|
+
authUrl,
|
|
1355
|
+
redirectUrl: this.config.authOptions?.redirectUrl || this.getValidatedCurrentUrl()
|
|
1356
|
+
},
|
|
1357
|
+
embeddedWalletType: embeddedWalletType || DEFAULT_EMBEDDED_WALLET_TYPE,
|
|
1358
|
+
addressTypes: this.config.addressTypes
|
|
1259
1359
|
});
|
|
1360
|
+
} else {
|
|
1361
|
+
throw new Error(`Unsupported provider type: ${type}`);
|
|
1260
1362
|
}
|
|
1261
1363
|
this.providers.set(key, provider);
|
|
1262
1364
|
}
|
|
@@ -1266,8 +1368,10 @@ var ProviderManager = class {
|
|
|
1266
1368
|
getProviderKey(type, embeddedWalletType) {
|
|
1267
1369
|
if (type === "injected") {
|
|
1268
1370
|
return "injected";
|
|
1371
|
+
} else if (type === "embedded") {
|
|
1372
|
+
return `embedded-${embeddedWalletType || "app-wallet"}`;
|
|
1269
1373
|
}
|
|
1270
|
-
|
|
1374
|
+
throw new Error(`Unsupported provider type: ${type}`);
|
|
1271
1375
|
}
|
|
1272
1376
|
/**
|
|
1273
1377
|
* Save provider preference to localStorage
|
|
@@ -1328,6 +1432,7 @@ async function waitForPhantomExtension(timeoutMs = 3e3) {
|
|
|
1328
1432
|
}
|
|
1329
1433
|
|
|
1330
1434
|
// src/BrowserSDK.ts
|
|
1435
|
+
import { DEFAULT_EMBEDDED_WALLET_TYPE as DEFAULT_EMBEDDED_WALLET_TYPE2 } from "@phantom/constants";
|
|
1331
1436
|
var BrowserSDK = class {
|
|
1332
1437
|
constructor(config) {
|
|
1333
1438
|
debug.info(DebugCategory.BROWSER_SDK, "Initializing BrowserSDK", {
|
|
@@ -1339,7 +1444,7 @@ var BrowserSDK = class {
|
|
|
1339
1444
|
debug.error(DebugCategory.BROWSER_SDK, "Invalid providerType", { providerType: config.providerType });
|
|
1340
1445
|
throw new Error(`Invalid providerType: ${config.providerType}. Must be "injected" or "embedded".`);
|
|
1341
1446
|
}
|
|
1342
|
-
const embeddedWalletType = config.embeddedWalletType ||
|
|
1447
|
+
const embeddedWalletType = config.embeddedWalletType || DEFAULT_EMBEDDED_WALLET_TYPE2;
|
|
1343
1448
|
if (config.providerType === "embedded" && !["app-wallet", "user-wallet"].includes(embeddedWalletType)) {
|
|
1344
1449
|
debug.error(DebugCategory.BROWSER_SDK, "Invalid embeddedWalletType", {
|
|
1345
1450
|
embeddedWalletType: config.embeddedWalletType
|
|
@@ -1627,21 +1732,31 @@ var BrowserSDK = class {
|
|
|
1627
1732
|
// src/types.ts
|
|
1628
1733
|
import { AddressType as AddressType4 } from "@phantom/client";
|
|
1629
1734
|
|
|
1735
|
+
// src/utils/deeplink.ts
|
|
1736
|
+
function getDeeplinkToPhantom(ref) {
|
|
1737
|
+
if (!window.location.href.startsWith("http:") && !window.location.href.startsWith("https:")) {
|
|
1738
|
+
throw new Error("Invalid URL protocol - only HTTP/HTTPS URLs are supported for deeplinks");
|
|
1739
|
+
}
|
|
1740
|
+
const currentUrl = encodeURIComponent(window.location.href);
|
|
1741
|
+
const refParam = ref ? `?ref=${encodeURIComponent(ref)}` : "";
|
|
1742
|
+
return `https://phantom.app/ul/browse/${currentUrl}${refParam}`;
|
|
1743
|
+
}
|
|
1744
|
+
|
|
1630
1745
|
// src/index.ts
|
|
1631
1746
|
import { NetworkId } from "@phantom/constants";
|
|
1632
1747
|
import { AddressType as AddressType5 } from "@phantom/client";
|
|
1633
1748
|
export {
|
|
1634
1749
|
AddressType5 as AddressType,
|
|
1635
1750
|
BrowserSDK,
|
|
1636
|
-
DEFAULT_AUTH_URL,
|
|
1637
|
-
DEFAULT_WALLET_API_URL,
|
|
1638
1751
|
DebugCategory,
|
|
1639
1752
|
DebugLevel,
|
|
1640
1753
|
NetworkId,
|
|
1641
1754
|
debug,
|
|
1642
1755
|
detectBrowser,
|
|
1643
1756
|
getBrowserDisplayName,
|
|
1757
|
+
getDeeplinkToPhantom,
|
|
1644
1758
|
getPlatformName,
|
|
1759
|
+
isMobileDevice,
|
|
1645
1760
|
parseBrowserFromUserAgent,
|
|
1646
1761
|
waitForPhantomExtension
|
|
1647
1762
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phantom/browser-sdk",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.3",
|
|
4
4
|
"description": "Browser SDK for Phantom Wallet",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -28,14 +28,14 @@
|
|
|
28
28
|
"prettier": "prettier --write \"src/**/*.{ts,tsx}\""
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@phantom/base64url": "^1.0.0-beta.
|
|
32
|
-
"@phantom/browser-injected-sdk": "^1.0.0-beta.
|
|
33
|
-
"@phantom/chains": "^1.0.0-beta.
|
|
34
|
-
"@phantom/client": "^1.0.0-beta.
|
|
35
|
-
"@phantom/constants": "^1.0.0-beta.
|
|
36
|
-
"@phantom/embedded-provider-core": "^1.0.0-beta.
|
|
31
|
+
"@phantom/base64url": "^1.0.0-beta.3",
|
|
32
|
+
"@phantom/browser-injected-sdk": "^1.0.0-beta.3",
|
|
33
|
+
"@phantom/chains": "^1.0.0-beta.3",
|
|
34
|
+
"@phantom/client": "^1.0.0-beta.3",
|
|
35
|
+
"@phantom/constants": "^1.0.0-beta.3",
|
|
36
|
+
"@phantom/embedded-provider-core": "^1.0.0-beta.3",
|
|
37
37
|
"@phantom/indexed-db-stamper": "^1.0.0-beta.1",
|
|
38
|
-
"@phantom/parsers": "^1.0.0-beta.
|
|
38
|
+
"@phantom/parsers": "^1.0.0-beta.3",
|
|
39
39
|
"axios": "^1.10.0",
|
|
40
40
|
"bs58": "^6.0.0",
|
|
41
41
|
"buffer": "^6.0.3",
|