@phantom/browser-sdk 1.0.0-beta.15 → 1.0.0-beta.17
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 +120 -1
- package/dist/index.d.ts +27 -2
- package/dist/index.js +86 -15
- package/dist/index.mjs +86 -15
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -305,7 +305,9 @@ interface BrowserSDKConfig {
|
|
|
305
305
|
|
|
306
306
|
### Extension Detection
|
|
307
307
|
|
|
308
|
-
|
|
308
|
+
#### waitForPhantomExtension
|
|
309
|
+
|
|
310
|
+
Check if the Phantom extension is installed:
|
|
309
311
|
|
|
310
312
|
```typescript
|
|
311
313
|
import { waitForPhantomExtension } from "@phantom/browser-sdk";
|
|
@@ -319,6 +321,23 @@ if (isAvailable) {
|
|
|
319
321
|
}
|
|
320
322
|
```
|
|
321
323
|
|
|
324
|
+
#### isPhantomLoginAvailable
|
|
325
|
+
|
|
326
|
+
Check if Phantom Login is available (requires extension to be installed and support the `phantom_login` feature):
|
|
327
|
+
|
|
328
|
+
```typescript
|
|
329
|
+
import { isPhantomLoginAvailable } from "@phantom/browser-sdk";
|
|
330
|
+
|
|
331
|
+
const isAvailable = await isPhantomLoginAvailable();
|
|
332
|
+
|
|
333
|
+
if (isAvailable) {
|
|
334
|
+
console.log("Phantom Login is available!");
|
|
335
|
+
// Can use provider: "phantom" in connect()
|
|
336
|
+
} else {
|
|
337
|
+
console.log("Phantom Login is not available");
|
|
338
|
+
}
|
|
339
|
+
```
|
|
340
|
+
|
|
322
341
|
### Core Methods
|
|
323
342
|
|
|
324
343
|
#### connect()
|
|
@@ -552,6 +571,106 @@ Attempt auto-connection using existing session. Should be called after setting u
|
|
|
552
571
|
await sdk.autoConnect();
|
|
553
572
|
```
|
|
554
573
|
|
|
574
|
+
### Event Handlers
|
|
575
|
+
|
|
576
|
+
The SDK provides typed event handlers that allow you to listen for connection state changes. This is especially useful for `autoConnect()` flows where you need to track the connection result.
|
|
577
|
+
|
|
578
|
+
#### Available Events
|
|
579
|
+
|
|
580
|
+
```typescript
|
|
581
|
+
import { BrowserSDK } from '@phantom/browser-sdk';
|
|
582
|
+
import type {
|
|
583
|
+
ConnectEventData,
|
|
584
|
+
ConnectStartEventData,
|
|
585
|
+
ConnectErrorEventData,
|
|
586
|
+
DisconnectEventData
|
|
587
|
+
} from '@phantom/browser-sdk';
|
|
588
|
+
|
|
589
|
+
const sdk = new BrowserSDK({
|
|
590
|
+
providerType: 'embedded',
|
|
591
|
+
appId: 'your-app-id',
|
|
592
|
+
addressTypes: [AddressType.solana],
|
|
593
|
+
});
|
|
594
|
+
|
|
595
|
+
// 1. connect_start - Fired when connection starts
|
|
596
|
+
sdk.on('connect_start', (data: ConnectStartEventData) => {
|
|
597
|
+
console.log('Connection starting:', data.source); // "auto-connect" | "manual-connect"
|
|
598
|
+
console.log('Auth options:', data.authOptions?.provider); // "google" | "apple" | etc.
|
|
599
|
+
});
|
|
600
|
+
|
|
601
|
+
// 2. connect - Fired when connection succeeds (includes full ConnectResult)
|
|
602
|
+
sdk.on('connect', (data: ConnectEventData) => {
|
|
603
|
+
console.log('Connected successfully!');
|
|
604
|
+
console.log('Provider type:', data.providerType); // "embedded" | "injected"
|
|
605
|
+
console.log('Wallet ID:', data.walletId); // only for embedded providers
|
|
606
|
+
console.log('Addresses:', data.addresses); // WalletAddress[]
|
|
607
|
+
console.log('Status:', data.status); // "pending" | "completed"
|
|
608
|
+
console.log('Source:', data.source); // "auto-connect" | "manual-connect" | "manual-existing" | "existing-session" | "manual"
|
|
609
|
+
});
|
|
610
|
+
|
|
611
|
+
// 3. connect_error - Fired when connection fails
|
|
612
|
+
sdk.on('connect_error', (data: ConnectErrorEventData) => {
|
|
613
|
+
console.error('Connection failed:', data.error);
|
|
614
|
+
console.log('Source:', data.source); // "auto-connect" | "manual-connect"
|
|
615
|
+
});
|
|
616
|
+
|
|
617
|
+
// 4. disconnect - Fired when disconnected
|
|
618
|
+
sdk.on('disconnect', (data: DisconnectEventData) => {
|
|
619
|
+
console.log('Disconnected from wallet');
|
|
620
|
+
console.log('Source:', data.source); // "manual"
|
|
621
|
+
});
|
|
622
|
+
|
|
623
|
+
// 5. error - General error handler
|
|
624
|
+
sdk.on('error', (error: unknown) => {
|
|
625
|
+
console.error('SDK error:', error);
|
|
626
|
+
});
|
|
627
|
+
|
|
628
|
+
// Don't forget to remove listeners when done
|
|
629
|
+
sdk.off('connect', handleConnect);
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
#### Event Types
|
|
633
|
+
|
|
634
|
+
| Event | Payload Type | When Fired | Key Data |
|
|
635
|
+
|-------|-------------|------------|----------|
|
|
636
|
+
| `connect_start` | `ConnectStartEventData` | Connection initiated | `source`, `authOptions` |
|
|
637
|
+
| `connect` | `ConnectEventData` | Connection successful | `providerType`, `addresses`, `status`, `source`, `user`|
|
|
638
|
+
| `connect_error` | `ConnectErrorEventData` | Connection failed | `error`, `source` |
|
|
639
|
+
| `disconnect` | `DisconnectEventData` | Disconnected | `source` |
|
|
640
|
+
| `error` | `unknown` | General SDK errors | Error details |
|
|
641
|
+
|
|
642
|
+
#### Using Events with autoConnect()
|
|
643
|
+
|
|
644
|
+
Event handlers are especially useful with `autoConnect()` since it doesn't return a value:
|
|
645
|
+
|
|
646
|
+
```typescript
|
|
647
|
+
const sdk = new BrowserSDK({
|
|
648
|
+
providerType: 'embedded',
|
|
649
|
+
appId: 'your-app-id',
|
|
650
|
+
addressTypes: [AddressType.solana],
|
|
651
|
+
autoConnect: true,
|
|
652
|
+
});
|
|
653
|
+
|
|
654
|
+
// Set up event listeners BEFORE autoConnect
|
|
655
|
+
sdk.on('connect', (data: ConnectEventData) => {
|
|
656
|
+
console.log('Auto-connected successfully!');
|
|
657
|
+
console.log('Provider type:', data.providerType);
|
|
658
|
+
console.log('Addresses:', data.addresses);
|
|
659
|
+
|
|
660
|
+
// Update your UI state here
|
|
661
|
+
updateUIWithAddresses(data.addresses);
|
|
662
|
+
});
|
|
663
|
+
|
|
664
|
+
sdk.on('connect_error', (data: ConnectErrorEventData) => {
|
|
665
|
+
console.log('Auto-connect failed:', data.error);
|
|
666
|
+
// Show connect button to user
|
|
667
|
+
showConnectButton();
|
|
668
|
+
});
|
|
669
|
+
|
|
670
|
+
// Auto-connect will trigger events
|
|
671
|
+
await sdk.autoConnect();
|
|
672
|
+
```
|
|
673
|
+
|
|
555
674
|
### Auto-Confirm Methods (Injected Provider Only)
|
|
556
675
|
|
|
557
676
|
The SDK provides auto-confirm functionality that allows automatic transaction confirmation for specified chains. This feature is only available when using the injected provider (Phantom browser extension).
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EmbeddedProviderConfig, AuthOptions, ConnectResult, WalletAddress, EmbeddedProviderEvent, EventCallback } from '@phantom/embedded-provider-core';
|
|
2
|
-
export { AuthOptions, ConnectResult, SignAndSendTransactionParams, SignMessageParams, SignMessageResult, SignedTransaction, WalletAddress } 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';
|
|
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';
|
|
@@ -68,6 +68,9 @@ interface PhantomAppLoginResult {
|
|
|
68
68
|
}
|
|
69
69
|
interface PhantomApp {
|
|
70
70
|
login(options: PhantomAppLoginOptions): Promise<PhantomAppLoginResult>;
|
|
71
|
+
features(): Promise<{
|
|
72
|
+
features: string[];
|
|
73
|
+
}>;
|
|
71
74
|
}
|
|
72
75
|
declare global {
|
|
73
76
|
interface Window {
|
|
@@ -297,4 +300,26 @@ declare function getDeeplinkToPhantom(ref?: string): string;
|
|
|
297
300
|
*/
|
|
298
301
|
declare function waitForPhantomExtension(timeoutMs?: number): Promise<boolean>;
|
|
299
302
|
|
|
300
|
-
|
|
303
|
+
/**
|
|
304
|
+
* Check if Phantom Login is available
|
|
305
|
+
*
|
|
306
|
+
* This function checks if:
|
|
307
|
+
* 1. The Phantom extension is installed
|
|
308
|
+
* 2. The extension supports the phantom_login feature
|
|
309
|
+
*
|
|
310
|
+
* @param timeoutMs - Maximum time to wait for extension in milliseconds (default: 3000)
|
|
311
|
+
* @returns Promise<boolean> - true if Phantom Login is available, false otherwise
|
|
312
|
+
*
|
|
313
|
+
* Usage:
|
|
314
|
+
* ```typescript
|
|
315
|
+
* const isAvailable = await isPhantomLoginAvailable();
|
|
316
|
+
* if (isAvailable) {
|
|
317
|
+
* console.log("Phantom Login is available!");
|
|
318
|
+
* } else {
|
|
319
|
+
* console.log("Phantom Login is not available");
|
|
320
|
+
* }
|
|
321
|
+
* ```
|
|
322
|
+
*/
|
|
323
|
+
declare function isPhantomLoginAvailable(timeoutMs?: number): Promise<boolean>;
|
|
324
|
+
|
|
325
|
+
export { BrowserInfo, BrowserSDK, BrowserSDKConfig, DebugCallback, DebugCategory, DebugConfig, DebugLevel, DebugMessage, Provider, debug, detectBrowser, getBrowserDisplayName, getDeeplinkToPhantom, getPlatformName, isMobileDevice, isPhantomLoginAvailable, parseBrowserFromUserAgent, waitForPhantomExtension };
|
package/dist/index.js
CHANGED
|
@@ -31,6 +31,7 @@ __export(src_exports, {
|
|
|
31
31
|
getDeeplinkToPhantom: () => getDeeplinkToPhantom,
|
|
32
32
|
getPlatformName: () => getPlatformName,
|
|
33
33
|
isMobileDevice: () => isMobileDevice,
|
|
34
|
+
isPhantomLoginAvailable: () => isPhantomLoginAvailable,
|
|
34
35
|
parseBrowserFromUserAgent: () => parseBrowserFromUserAgent,
|
|
35
36
|
waitForPhantomExtension: () => waitForPhantomExtension
|
|
36
37
|
});
|
|
@@ -476,7 +477,12 @@ var InjectedProvider = class {
|
|
|
476
477
|
debug.info(DebugCategory.INJECTED_PROVIDER, "Solana connected successfully", { address: publicKey });
|
|
477
478
|
}
|
|
478
479
|
} catch (err) {
|
|
479
|
-
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Solana", { error: err });
|
|
480
|
+
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Solana, stopping", { error: err });
|
|
481
|
+
this.emit("connect_error", {
|
|
482
|
+
error: err instanceof Error ? err.message : "Failed to connect",
|
|
483
|
+
source: "manual-connect"
|
|
484
|
+
});
|
|
485
|
+
throw err;
|
|
480
486
|
}
|
|
481
487
|
}
|
|
482
488
|
if (this.addressTypes.includes(import_client4.AddressType.ethereum)) {
|
|
@@ -492,7 +498,12 @@ var InjectedProvider = class {
|
|
|
492
498
|
debug.info(DebugCategory.INJECTED_PROVIDER, "Ethereum connected successfully", { addresses: accounts });
|
|
493
499
|
}
|
|
494
500
|
} catch (err) {
|
|
495
|
-
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Ethereum", { error: err });
|
|
501
|
+
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Ethereum, stopping", { error: err });
|
|
502
|
+
this.emit("connect_error", {
|
|
503
|
+
error: err instanceof Error ? err.message : "Failed to connect",
|
|
504
|
+
source: "manual-connect"
|
|
505
|
+
});
|
|
506
|
+
throw err;
|
|
496
507
|
}
|
|
497
508
|
}
|
|
498
509
|
if (connectedAddresses.length === 0) {
|
|
@@ -1129,7 +1140,7 @@ var BrowserAuthProvider = class {
|
|
|
1129
1140
|
// OAuth session management - defaults to allow refresh unless explicitly clearing after logout
|
|
1130
1141
|
clear_previous_session: (phantomOptions.clearPreviousSession ?? false).toString(),
|
|
1131
1142
|
allow_refresh: (phantomOptions.allowRefresh ?? true).toString(),
|
|
1132
|
-
sdk_version: "1.0.0-beta.
|
|
1143
|
+
sdk_version: "1.0.0-beta.17",
|
|
1133
1144
|
sdk_type: "browser",
|
|
1134
1145
|
platform: detectBrowser().name
|
|
1135
1146
|
});
|
|
@@ -1245,13 +1256,59 @@ var BrowserAuthProvider = class {
|
|
|
1245
1256
|
};
|
|
1246
1257
|
|
|
1247
1258
|
// src/providers/embedded/adapters/phantom-app.ts
|
|
1259
|
+
var import_browser_injected_sdk3 = require("@phantom/browser-injected-sdk");
|
|
1260
|
+
|
|
1261
|
+
// src/isPhantomLoginAvailable.ts
|
|
1248
1262
|
var import_browser_injected_sdk2 = require("@phantom/browser-injected-sdk");
|
|
1263
|
+
async function isPhantomLoginAvailable(timeoutMs = 3e3) {
|
|
1264
|
+
const extensionInstalled = await waitForExtension(timeoutMs);
|
|
1265
|
+
if (!extensionInstalled) {
|
|
1266
|
+
return false;
|
|
1267
|
+
}
|
|
1268
|
+
try {
|
|
1269
|
+
if (!window.phantom?.app?.features || typeof window.phantom.app.features !== "function") {
|
|
1270
|
+
return false;
|
|
1271
|
+
}
|
|
1272
|
+
const response = await window.phantom.app.features();
|
|
1273
|
+
if (!Array.isArray(response.features)) {
|
|
1274
|
+
return false;
|
|
1275
|
+
}
|
|
1276
|
+
return response.features.includes("phantom_login");
|
|
1277
|
+
} catch (error) {
|
|
1278
|
+
console.error("Error checking Phantom extension features", error);
|
|
1279
|
+
return false;
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
async function waitForExtension(timeoutMs) {
|
|
1283
|
+
return new Promise((resolve) => {
|
|
1284
|
+
const startTime = Date.now();
|
|
1285
|
+
const checkInterval = 100;
|
|
1286
|
+
const checkForExtension = () => {
|
|
1287
|
+
try {
|
|
1288
|
+
if ((0, import_browser_injected_sdk2.isPhantomExtensionInstalled)()) {
|
|
1289
|
+
resolve(true);
|
|
1290
|
+
return;
|
|
1291
|
+
}
|
|
1292
|
+
} catch (error) {
|
|
1293
|
+
}
|
|
1294
|
+
const elapsed = Date.now() - startTime;
|
|
1295
|
+
if (elapsed >= timeoutMs) {
|
|
1296
|
+
resolve(false);
|
|
1297
|
+
return;
|
|
1298
|
+
}
|
|
1299
|
+
setTimeout(checkForExtension, checkInterval);
|
|
1300
|
+
};
|
|
1301
|
+
checkForExtension();
|
|
1302
|
+
});
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
// src/providers/embedded/adapters/phantom-app.ts
|
|
1249
1306
|
var BrowserPhantomAppProvider = class {
|
|
1250
1307
|
/**
|
|
1251
1308
|
* Check if the Phantom extension is installed in the browser
|
|
1252
1309
|
*/
|
|
1253
1310
|
isAvailable() {
|
|
1254
|
-
return (0,
|
|
1311
|
+
return (0, import_browser_injected_sdk3.isPhantomExtensionInstalled)();
|
|
1255
1312
|
}
|
|
1256
1313
|
/**
|
|
1257
1314
|
* Authenticate using the Phantom browser extension
|
|
@@ -1262,12 +1319,16 @@ var BrowserPhantomAppProvider = class {
|
|
|
1262
1319
|
"Phantom extension is not installed. Please install the Phantom browser extension to use this authentication method."
|
|
1263
1320
|
);
|
|
1264
1321
|
}
|
|
1265
|
-
|
|
1322
|
+
const loginAvailable = await isPhantomLoginAvailable();
|
|
1323
|
+
if (!loginAvailable) {
|
|
1266
1324
|
throw new Error(
|
|
1267
|
-
"Phantom
|
|
1325
|
+
"Phantom Login is not available. Please update your Phantom extension to use this authentication method."
|
|
1268
1326
|
);
|
|
1269
1327
|
}
|
|
1270
1328
|
try {
|
|
1329
|
+
if (!window.phantom?.app?.login) {
|
|
1330
|
+
throw new Error("Phantom extension login method not found");
|
|
1331
|
+
}
|
|
1271
1332
|
const result = await window.phantom.app.login({
|
|
1272
1333
|
publicKey: options.publicKey,
|
|
1273
1334
|
appId: options.appId,
|
|
@@ -1337,7 +1398,7 @@ var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvi
|
|
|
1337
1398
|
// Full user agent for more detailed info
|
|
1338
1399
|
[import_constants2.ANALYTICS_HEADERS.APP_ID]: config.appId,
|
|
1339
1400
|
[import_constants2.ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
|
|
1340
|
-
[import_constants2.ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.
|
|
1401
|
+
[import_constants2.ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.17"
|
|
1341
1402
|
// Replaced at build time
|
|
1342
1403
|
}
|
|
1343
1404
|
};
|
|
@@ -1457,9 +1518,11 @@ var ProviderManager = class {
|
|
|
1457
1518
|
to: targetProviderType,
|
|
1458
1519
|
requestedProvider
|
|
1459
1520
|
});
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1521
|
+
const switchOptions = {};
|
|
1522
|
+
if (targetProviderType === "embedded") {
|
|
1523
|
+
switchOptions.embeddedWalletType = currentInfo?.embeddedWalletType || this.config.embeddedWalletType;
|
|
1524
|
+
}
|
|
1525
|
+
this.switchProvider(targetProviderType, switchOptions);
|
|
1463
1526
|
}
|
|
1464
1527
|
}
|
|
1465
1528
|
}
|
|
@@ -1469,12 +1532,16 @@ var ProviderManager = class {
|
|
|
1469
1532
|
}
|
|
1470
1533
|
debug.log(DebugCategory.PROVIDER_MANAGER, "Delegating to provider connect method");
|
|
1471
1534
|
const result = await this.currentProvider.connect(authOptions);
|
|
1535
|
+
const providerInfo = this.getCurrentProviderInfo();
|
|
1536
|
+
result.providerType = providerInfo?.type;
|
|
1472
1537
|
debug.log(DebugCategory.PROVIDER_MANAGER, "Connection successful, saving preferences", {
|
|
1473
|
-
addressCount: result.addresses?.length || 0
|
|
1538
|
+
addressCount: result.addresses?.length || 0,
|
|
1539
|
+
providerType: result.providerType
|
|
1474
1540
|
});
|
|
1475
1541
|
this.saveProviderPreference();
|
|
1476
1542
|
debug.info(DebugCategory.PROVIDER_MANAGER, "Connect completed", {
|
|
1477
|
-
addresses: result.addresses
|
|
1543
|
+
addresses: result.addresses,
|
|
1544
|
+
providerType: result.providerType
|
|
1478
1545
|
});
|
|
1479
1546
|
return result;
|
|
1480
1547
|
}
|
|
@@ -1658,7 +1725,11 @@ var ProviderManager = class {
|
|
|
1658
1725
|
}
|
|
1659
1726
|
debug.log(DebugCategory.PROVIDER_MANAGER, "Creating injected provider");
|
|
1660
1727
|
this.createProvider("injected");
|
|
1661
|
-
|
|
1728
|
+
const switchOptions = {};
|
|
1729
|
+
if (defaultType === "embedded") {
|
|
1730
|
+
switchOptions.embeddedWalletType = defaultEmbeddedType;
|
|
1731
|
+
}
|
|
1732
|
+
this.switchProvider(defaultType, switchOptions);
|
|
1662
1733
|
}
|
|
1663
1734
|
/**
|
|
1664
1735
|
* Create a provider instance
|
|
@@ -1721,14 +1792,14 @@ var ProviderManager = class {
|
|
|
1721
1792
|
};
|
|
1722
1793
|
|
|
1723
1794
|
// src/waitForPhantomExtension.ts
|
|
1724
|
-
var
|
|
1795
|
+
var import_browser_injected_sdk4 = require("@phantom/browser-injected-sdk");
|
|
1725
1796
|
async function waitForPhantomExtension(timeoutMs = 3e3) {
|
|
1726
1797
|
return new Promise((resolve) => {
|
|
1727
1798
|
const startTime = Date.now();
|
|
1728
1799
|
const checkInterval = 100;
|
|
1729
1800
|
const checkForExtension = () => {
|
|
1730
1801
|
try {
|
|
1731
|
-
if ((0,
|
|
1802
|
+
if ((0, import_browser_injected_sdk4.isPhantomExtensionInstalled)()) {
|
|
1732
1803
|
resolve(true);
|
|
1733
1804
|
return;
|
|
1734
1805
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -440,7 +440,12 @@ var InjectedProvider = class {
|
|
|
440
440
|
debug.info(DebugCategory.INJECTED_PROVIDER, "Solana connected successfully", { address: publicKey });
|
|
441
441
|
}
|
|
442
442
|
} catch (err) {
|
|
443
|
-
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Solana", { error: err });
|
|
443
|
+
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Solana, stopping", { error: err });
|
|
444
|
+
this.emit("connect_error", {
|
|
445
|
+
error: err instanceof Error ? err.message : "Failed to connect",
|
|
446
|
+
source: "manual-connect"
|
|
447
|
+
});
|
|
448
|
+
throw err;
|
|
444
449
|
}
|
|
445
450
|
}
|
|
446
451
|
if (this.addressTypes.includes(AddressType4.ethereum)) {
|
|
@@ -456,7 +461,12 @@ var InjectedProvider = class {
|
|
|
456
461
|
debug.info(DebugCategory.INJECTED_PROVIDER, "Ethereum connected successfully", { addresses: accounts });
|
|
457
462
|
}
|
|
458
463
|
} catch (err) {
|
|
459
|
-
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Ethereum", { error: err });
|
|
464
|
+
debug.warn(DebugCategory.INJECTED_PROVIDER, "Failed to connect Ethereum, stopping", { error: err });
|
|
465
|
+
this.emit("connect_error", {
|
|
466
|
+
error: err instanceof Error ? err.message : "Failed to connect",
|
|
467
|
+
source: "manual-connect"
|
|
468
|
+
});
|
|
469
|
+
throw err;
|
|
460
470
|
}
|
|
461
471
|
}
|
|
462
472
|
if (connectedAddresses.length === 0) {
|
|
@@ -1093,7 +1103,7 @@ var BrowserAuthProvider = class {
|
|
|
1093
1103
|
// OAuth session management - defaults to allow refresh unless explicitly clearing after logout
|
|
1094
1104
|
clear_previous_session: (phantomOptions.clearPreviousSession ?? false).toString(),
|
|
1095
1105
|
allow_refresh: (phantomOptions.allowRefresh ?? true).toString(),
|
|
1096
|
-
sdk_version: "1.0.0-beta.
|
|
1106
|
+
sdk_version: "1.0.0-beta.17",
|
|
1097
1107
|
sdk_type: "browser",
|
|
1098
1108
|
platform: detectBrowser().name
|
|
1099
1109
|
});
|
|
@@ -1209,13 +1219,59 @@ var BrowserAuthProvider = class {
|
|
|
1209
1219
|
};
|
|
1210
1220
|
|
|
1211
1221
|
// src/providers/embedded/adapters/phantom-app.ts
|
|
1222
|
+
import { isPhantomExtensionInstalled as isPhantomExtensionInstalled2 } from "@phantom/browser-injected-sdk";
|
|
1223
|
+
|
|
1224
|
+
// src/isPhantomLoginAvailable.ts
|
|
1212
1225
|
import { isPhantomExtensionInstalled } from "@phantom/browser-injected-sdk";
|
|
1226
|
+
async function isPhantomLoginAvailable(timeoutMs = 3e3) {
|
|
1227
|
+
const extensionInstalled = await waitForExtension(timeoutMs);
|
|
1228
|
+
if (!extensionInstalled) {
|
|
1229
|
+
return false;
|
|
1230
|
+
}
|
|
1231
|
+
try {
|
|
1232
|
+
if (!window.phantom?.app?.features || typeof window.phantom.app.features !== "function") {
|
|
1233
|
+
return false;
|
|
1234
|
+
}
|
|
1235
|
+
const response = await window.phantom.app.features();
|
|
1236
|
+
if (!Array.isArray(response.features)) {
|
|
1237
|
+
return false;
|
|
1238
|
+
}
|
|
1239
|
+
return response.features.includes("phantom_login");
|
|
1240
|
+
} catch (error) {
|
|
1241
|
+
console.error("Error checking Phantom extension features", error);
|
|
1242
|
+
return false;
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
async function waitForExtension(timeoutMs) {
|
|
1246
|
+
return new Promise((resolve) => {
|
|
1247
|
+
const startTime = Date.now();
|
|
1248
|
+
const checkInterval = 100;
|
|
1249
|
+
const checkForExtension = () => {
|
|
1250
|
+
try {
|
|
1251
|
+
if (isPhantomExtensionInstalled()) {
|
|
1252
|
+
resolve(true);
|
|
1253
|
+
return;
|
|
1254
|
+
}
|
|
1255
|
+
} catch (error) {
|
|
1256
|
+
}
|
|
1257
|
+
const elapsed = Date.now() - startTime;
|
|
1258
|
+
if (elapsed >= timeoutMs) {
|
|
1259
|
+
resolve(false);
|
|
1260
|
+
return;
|
|
1261
|
+
}
|
|
1262
|
+
setTimeout(checkForExtension, checkInterval);
|
|
1263
|
+
};
|
|
1264
|
+
checkForExtension();
|
|
1265
|
+
});
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
// src/providers/embedded/adapters/phantom-app.ts
|
|
1213
1269
|
var BrowserPhantomAppProvider = class {
|
|
1214
1270
|
/**
|
|
1215
1271
|
* Check if the Phantom extension is installed in the browser
|
|
1216
1272
|
*/
|
|
1217
1273
|
isAvailable() {
|
|
1218
|
-
return
|
|
1274
|
+
return isPhantomExtensionInstalled2();
|
|
1219
1275
|
}
|
|
1220
1276
|
/**
|
|
1221
1277
|
* Authenticate using the Phantom browser extension
|
|
@@ -1226,12 +1282,16 @@ var BrowserPhantomAppProvider = class {
|
|
|
1226
1282
|
"Phantom extension is not installed. Please install the Phantom browser extension to use this authentication method."
|
|
1227
1283
|
);
|
|
1228
1284
|
}
|
|
1229
|
-
|
|
1285
|
+
const loginAvailable = await isPhantomLoginAvailable();
|
|
1286
|
+
if (!loginAvailable) {
|
|
1230
1287
|
throw new Error(
|
|
1231
|
-
"Phantom
|
|
1288
|
+
"Phantom Login is not available. Please update your Phantom extension to use this authentication method."
|
|
1232
1289
|
);
|
|
1233
1290
|
}
|
|
1234
1291
|
try {
|
|
1292
|
+
if (!window.phantom?.app?.login) {
|
|
1293
|
+
throw new Error("Phantom extension login method not found");
|
|
1294
|
+
}
|
|
1235
1295
|
const result = await window.phantom.app.login({
|
|
1236
1296
|
publicKey: options.publicKey,
|
|
1237
1297
|
appId: options.appId,
|
|
@@ -1301,7 +1361,7 @@ var EmbeddedProvider = class extends CoreEmbeddedProvider {
|
|
|
1301
1361
|
// Full user agent for more detailed info
|
|
1302
1362
|
[ANALYTICS_HEADERS.APP_ID]: config.appId,
|
|
1303
1363
|
[ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
|
|
1304
|
-
[ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.
|
|
1364
|
+
[ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.17"
|
|
1305
1365
|
// Replaced at build time
|
|
1306
1366
|
}
|
|
1307
1367
|
};
|
|
@@ -1421,9 +1481,11 @@ var ProviderManager = class {
|
|
|
1421
1481
|
to: targetProviderType,
|
|
1422
1482
|
requestedProvider
|
|
1423
1483
|
});
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1484
|
+
const switchOptions = {};
|
|
1485
|
+
if (targetProviderType === "embedded") {
|
|
1486
|
+
switchOptions.embeddedWalletType = currentInfo?.embeddedWalletType || this.config.embeddedWalletType;
|
|
1487
|
+
}
|
|
1488
|
+
this.switchProvider(targetProviderType, switchOptions);
|
|
1427
1489
|
}
|
|
1428
1490
|
}
|
|
1429
1491
|
}
|
|
@@ -1433,12 +1495,16 @@ var ProviderManager = class {
|
|
|
1433
1495
|
}
|
|
1434
1496
|
debug.log(DebugCategory.PROVIDER_MANAGER, "Delegating to provider connect method");
|
|
1435
1497
|
const result = await this.currentProvider.connect(authOptions);
|
|
1498
|
+
const providerInfo = this.getCurrentProviderInfo();
|
|
1499
|
+
result.providerType = providerInfo?.type;
|
|
1436
1500
|
debug.log(DebugCategory.PROVIDER_MANAGER, "Connection successful, saving preferences", {
|
|
1437
|
-
addressCount: result.addresses?.length || 0
|
|
1501
|
+
addressCount: result.addresses?.length || 0,
|
|
1502
|
+
providerType: result.providerType
|
|
1438
1503
|
});
|
|
1439
1504
|
this.saveProviderPreference();
|
|
1440
1505
|
debug.info(DebugCategory.PROVIDER_MANAGER, "Connect completed", {
|
|
1441
|
-
addresses: result.addresses
|
|
1506
|
+
addresses: result.addresses,
|
|
1507
|
+
providerType: result.providerType
|
|
1442
1508
|
});
|
|
1443
1509
|
return result;
|
|
1444
1510
|
}
|
|
@@ -1622,7 +1688,11 @@ var ProviderManager = class {
|
|
|
1622
1688
|
}
|
|
1623
1689
|
debug.log(DebugCategory.PROVIDER_MANAGER, "Creating injected provider");
|
|
1624
1690
|
this.createProvider("injected");
|
|
1625
|
-
|
|
1691
|
+
const switchOptions = {};
|
|
1692
|
+
if (defaultType === "embedded") {
|
|
1693
|
+
switchOptions.embeddedWalletType = defaultEmbeddedType;
|
|
1694
|
+
}
|
|
1695
|
+
this.switchProvider(defaultType, switchOptions);
|
|
1626
1696
|
}
|
|
1627
1697
|
/**
|
|
1628
1698
|
* Create a provider instance
|
|
@@ -1685,14 +1755,14 @@ var ProviderManager = class {
|
|
|
1685
1755
|
};
|
|
1686
1756
|
|
|
1687
1757
|
// src/waitForPhantomExtension.ts
|
|
1688
|
-
import { isPhantomExtensionInstalled as
|
|
1758
|
+
import { isPhantomExtensionInstalled as isPhantomExtensionInstalled3 } from "@phantom/browser-injected-sdk";
|
|
1689
1759
|
async function waitForPhantomExtension(timeoutMs = 3e3) {
|
|
1690
1760
|
return new Promise((resolve) => {
|
|
1691
1761
|
const startTime = Date.now();
|
|
1692
1762
|
const checkInterval = 100;
|
|
1693
1763
|
const checkForExtension = () => {
|
|
1694
1764
|
try {
|
|
1695
|
-
if (
|
|
1765
|
+
if (isPhantomExtensionInstalled3()) {
|
|
1696
1766
|
resolve(true);
|
|
1697
1767
|
return;
|
|
1698
1768
|
}
|
|
@@ -2009,6 +2079,7 @@ export {
|
|
|
2009
2079
|
getDeeplinkToPhantom,
|
|
2010
2080
|
getPlatformName,
|
|
2011
2081
|
isMobileDevice,
|
|
2082
|
+
isPhantomLoginAvailable,
|
|
2012
2083
|
parseBrowserFromUserAgent,
|
|
2013
2084
|
waitForPhantomExtension
|
|
2014
2085
|
};
|
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.17",
|
|
4
4
|
"description": "Browser SDK for Phantom Wallet",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
"@phantom/base64url": "^1.0.0-beta.7",
|
|
32
32
|
"@phantom/browser-injected-sdk": "^1.0.0-beta.5",
|
|
33
33
|
"@phantom/chain-interfaces": "^1.0.0-beta.7",
|
|
34
|
-
"@phantom/client": "^1.0.0-beta.
|
|
34
|
+
"@phantom/client": "^1.0.0-beta.17",
|
|
35
35
|
"@phantom/constants": "^1.0.0-beta.7",
|
|
36
|
-
"@phantom/embedded-provider-core": "^1.0.0-beta.
|
|
36
|
+
"@phantom/embedded-provider-core": "^1.0.0-beta.17",
|
|
37
37
|
"@phantom/indexed-db-stamper": "^1.0.0-beta.1",
|
|
38
38
|
"@phantom/parsers": "^1.0.0-beta.7",
|
|
39
39
|
"@phantom/sdk-types": "^1.0.0-beta.7",
|