@phantom/browser-sdk 1.0.0-beta.15 → 1.0.0-beta.16
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 +25 -2
- package/dist/index.js +94 -10
- package/dist/index.mjs +94 -10
- 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,7 @@ interface PhantomAppLoginResult {
|
|
|
68
68
|
}
|
|
69
69
|
interface PhantomApp {
|
|
70
70
|
login(options: PhantomAppLoginOptions): Promise<PhantomAppLoginResult>;
|
|
71
|
+
features(): Promise<string[]>;
|
|
71
72
|
}
|
|
72
73
|
declare global {
|
|
73
74
|
interface Window {
|
|
@@ -297,4 +298,26 @@ declare function getDeeplinkToPhantom(ref?: string): string;
|
|
|
297
298
|
*/
|
|
298
299
|
declare function waitForPhantomExtension(timeoutMs?: number): Promise<boolean>;
|
|
299
300
|
|
|
300
|
-
|
|
301
|
+
/**
|
|
302
|
+
* Check if Phantom Login is available
|
|
303
|
+
*
|
|
304
|
+
* This function checks if:
|
|
305
|
+
* 1. The Phantom extension is installed
|
|
306
|
+
* 2. The extension supports the phantom_login feature
|
|
307
|
+
*
|
|
308
|
+
* @param timeoutMs - Maximum time to wait for extension in milliseconds (default: 3000)
|
|
309
|
+
* @returns Promise<boolean> - true if Phantom Login is available, false otherwise
|
|
310
|
+
*
|
|
311
|
+
* Usage:
|
|
312
|
+
* ```typescript
|
|
313
|
+
* const isAvailable = await isPhantomLoginAvailable();
|
|
314
|
+
* if (isAvailable) {
|
|
315
|
+
* console.log("Phantom Login is available!");
|
|
316
|
+
* } else {
|
|
317
|
+
* console.log("Phantom Login is not available");
|
|
318
|
+
* }
|
|
319
|
+
* ```
|
|
320
|
+
*/
|
|
321
|
+
declare function isPhantomLoginAvailable(timeoutMs?: number): Promise<boolean>;
|
|
322
|
+
|
|
323
|
+
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.16",
|
|
1133
1144
|
sdk_type: "browser",
|
|
1134
1145
|
platform: detectBrowser().name
|
|
1135
1146
|
});
|
|
@@ -1267,6 +1278,26 @@ var BrowserPhantomAppProvider = class {
|
|
|
1267
1278
|
"Phantom extension authentication is not yet implemented. The extension needs to expose an app.login API (window.phantom.app.login)."
|
|
1268
1279
|
);
|
|
1269
1280
|
}
|
|
1281
|
+
try {
|
|
1282
|
+
if (!window.phantom?.app?.features || typeof window.phantom.app.features !== "function") {
|
|
1283
|
+
throw new Error(
|
|
1284
|
+
"Phantom Login is not available. The extension does not support the features API."
|
|
1285
|
+
);
|
|
1286
|
+
}
|
|
1287
|
+
const features = await window.phantom.app.features();
|
|
1288
|
+
if (!Array.isArray(features) || !features.includes("phantom_login")) {
|
|
1289
|
+
throw new Error(
|
|
1290
|
+
"Phantom Login is not available. Please update your Phantom extension to use this authentication method."
|
|
1291
|
+
);
|
|
1292
|
+
}
|
|
1293
|
+
} catch (error) {
|
|
1294
|
+
if (error instanceof Error) {
|
|
1295
|
+
throw error;
|
|
1296
|
+
}
|
|
1297
|
+
throw new Error(
|
|
1298
|
+
"Failed to check Phantom Login availability. Please ensure you have the latest version of the Phantom extension."
|
|
1299
|
+
);
|
|
1300
|
+
}
|
|
1270
1301
|
try {
|
|
1271
1302
|
const result = await window.phantom.app.login({
|
|
1272
1303
|
publicKey: options.publicKey,
|
|
@@ -1337,7 +1368,7 @@ var EmbeddedProvider = class extends import_embedded_provider_core.EmbeddedProvi
|
|
|
1337
1368
|
// Full user agent for more detailed info
|
|
1338
1369
|
[import_constants2.ANALYTICS_HEADERS.APP_ID]: config.appId,
|
|
1339
1370
|
[import_constants2.ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
|
|
1340
|
-
[import_constants2.ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.
|
|
1371
|
+
[import_constants2.ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.16"
|
|
1341
1372
|
// Replaced at build time
|
|
1342
1373
|
}
|
|
1343
1374
|
};
|
|
@@ -1457,9 +1488,11 @@ var ProviderManager = class {
|
|
|
1457
1488
|
to: targetProviderType,
|
|
1458
1489
|
requestedProvider
|
|
1459
1490
|
});
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1491
|
+
const switchOptions = {};
|
|
1492
|
+
if (targetProviderType === "embedded") {
|
|
1493
|
+
switchOptions.embeddedWalletType = currentInfo?.embeddedWalletType || this.config.embeddedWalletType;
|
|
1494
|
+
}
|
|
1495
|
+
this.switchProvider(targetProviderType, switchOptions);
|
|
1463
1496
|
}
|
|
1464
1497
|
}
|
|
1465
1498
|
}
|
|
@@ -1469,12 +1502,16 @@ var ProviderManager = class {
|
|
|
1469
1502
|
}
|
|
1470
1503
|
debug.log(DebugCategory.PROVIDER_MANAGER, "Delegating to provider connect method");
|
|
1471
1504
|
const result = await this.currentProvider.connect(authOptions);
|
|
1505
|
+
const providerInfo = this.getCurrentProviderInfo();
|
|
1506
|
+
result.providerType = providerInfo?.type;
|
|
1472
1507
|
debug.log(DebugCategory.PROVIDER_MANAGER, "Connection successful, saving preferences", {
|
|
1473
|
-
addressCount: result.addresses?.length || 0
|
|
1508
|
+
addressCount: result.addresses?.length || 0,
|
|
1509
|
+
providerType: result.providerType
|
|
1474
1510
|
});
|
|
1475
1511
|
this.saveProviderPreference();
|
|
1476
1512
|
debug.info(DebugCategory.PROVIDER_MANAGER, "Connect completed", {
|
|
1477
|
-
addresses: result.addresses
|
|
1513
|
+
addresses: result.addresses,
|
|
1514
|
+
providerType: result.providerType
|
|
1478
1515
|
});
|
|
1479
1516
|
return result;
|
|
1480
1517
|
}
|
|
@@ -1658,7 +1695,11 @@ var ProviderManager = class {
|
|
|
1658
1695
|
}
|
|
1659
1696
|
debug.log(DebugCategory.PROVIDER_MANAGER, "Creating injected provider");
|
|
1660
1697
|
this.createProvider("injected");
|
|
1661
|
-
|
|
1698
|
+
const switchOptions = {};
|
|
1699
|
+
if (defaultType === "embedded") {
|
|
1700
|
+
switchOptions.embeddedWalletType = defaultEmbeddedType;
|
|
1701
|
+
}
|
|
1702
|
+
this.switchProvider(defaultType, switchOptions);
|
|
1662
1703
|
}
|
|
1663
1704
|
/**
|
|
1664
1705
|
* Create a provider instance
|
|
@@ -2030,6 +2071,49 @@ function getDeeplinkToPhantom(ref) {
|
|
|
2030
2071
|
return `https://phantom.app/ul/browse/${currentUrl}${refParam}`;
|
|
2031
2072
|
}
|
|
2032
2073
|
|
|
2074
|
+
// src/isPhantomLoginAvailable.ts
|
|
2075
|
+
var import_browser_injected_sdk4 = require("@phantom/browser-injected-sdk");
|
|
2076
|
+
async function isPhantomLoginAvailable(timeoutMs = 3e3) {
|
|
2077
|
+
const extensionInstalled = await waitForExtension(timeoutMs);
|
|
2078
|
+
if (!extensionInstalled) {
|
|
2079
|
+
return false;
|
|
2080
|
+
}
|
|
2081
|
+
try {
|
|
2082
|
+
if (!window.phantom?.app?.features || typeof window.phantom.app.features !== "function") {
|
|
2083
|
+
return false;
|
|
2084
|
+
}
|
|
2085
|
+
const features = await window.phantom.app.features();
|
|
2086
|
+
if (!Array.isArray(features)) {
|
|
2087
|
+
return false;
|
|
2088
|
+
}
|
|
2089
|
+
return features.includes("phantom_login");
|
|
2090
|
+
} catch (error) {
|
|
2091
|
+
return false;
|
|
2092
|
+
}
|
|
2093
|
+
}
|
|
2094
|
+
async function waitForExtension(timeoutMs) {
|
|
2095
|
+
return new Promise((resolve) => {
|
|
2096
|
+
const startTime = Date.now();
|
|
2097
|
+
const checkInterval = 100;
|
|
2098
|
+
const checkForExtension = () => {
|
|
2099
|
+
try {
|
|
2100
|
+
if ((0, import_browser_injected_sdk4.isPhantomExtensionInstalled)()) {
|
|
2101
|
+
resolve(true);
|
|
2102
|
+
return;
|
|
2103
|
+
}
|
|
2104
|
+
} catch (error) {
|
|
2105
|
+
}
|
|
2106
|
+
const elapsed = Date.now() - startTime;
|
|
2107
|
+
if (elapsed >= timeoutMs) {
|
|
2108
|
+
resolve(false);
|
|
2109
|
+
return;
|
|
2110
|
+
}
|
|
2111
|
+
setTimeout(checkForExtension, checkInterval);
|
|
2112
|
+
};
|
|
2113
|
+
checkForExtension();
|
|
2114
|
+
});
|
|
2115
|
+
}
|
|
2116
|
+
|
|
2033
2117
|
// src/index.ts
|
|
2034
2118
|
var import_constants5 = require("@phantom/constants");
|
|
2035
2119
|
var import_client5 = require("@phantom/client");
|
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.16",
|
|
1097
1107
|
sdk_type: "browser",
|
|
1098
1108
|
platform: detectBrowser().name
|
|
1099
1109
|
});
|
|
@@ -1231,6 +1241,26 @@ var BrowserPhantomAppProvider = class {
|
|
|
1231
1241
|
"Phantom extension authentication is not yet implemented. The extension needs to expose an app.login API (window.phantom.app.login)."
|
|
1232
1242
|
);
|
|
1233
1243
|
}
|
|
1244
|
+
try {
|
|
1245
|
+
if (!window.phantom?.app?.features || typeof window.phantom.app.features !== "function") {
|
|
1246
|
+
throw new Error(
|
|
1247
|
+
"Phantom Login is not available. The extension does not support the features API."
|
|
1248
|
+
);
|
|
1249
|
+
}
|
|
1250
|
+
const features = await window.phantom.app.features();
|
|
1251
|
+
if (!Array.isArray(features) || !features.includes("phantom_login")) {
|
|
1252
|
+
throw new Error(
|
|
1253
|
+
"Phantom Login is not available. Please update your Phantom extension to use this authentication method."
|
|
1254
|
+
);
|
|
1255
|
+
}
|
|
1256
|
+
} catch (error) {
|
|
1257
|
+
if (error instanceof Error) {
|
|
1258
|
+
throw error;
|
|
1259
|
+
}
|
|
1260
|
+
throw new Error(
|
|
1261
|
+
"Failed to check Phantom Login availability. Please ensure you have the latest version of the Phantom extension."
|
|
1262
|
+
);
|
|
1263
|
+
}
|
|
1234
1264
|
try {
|
|
1235
1265
|
const result = await window.phantom.app.login({
|
|
1236
1266
|
publicKey: options.publicKey,
|
|
@@ -1301,7 +1331,7 @@ var EmbeddedProvider = class extends CoreEmbeddedProvider {
|
|
|
1301
1331
|
// Full user agent for more detailed info
|
|
1302
1332
|
[ANALYTICS_HEADERS.APP_ID]: config.appId,
|
|
1303
1333
|
[ANALYTICS_HEADERS.WALLET_TYPE]: config.embeddedWalletType,
|
|
1304
|
-
[ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.
|
|
1334
|
+
[ANALYTICS_HEADERS.SDK_VERSION]: "1.0.0-beta.16"
|
|
1305
1335
|
// Replaced at build time
|
|
1306
1336
|
}
|
|
1307
1337
|
};
|
|
@@ -1421,9 +1451,11 @@ var ProviderManager = class {
|
|
|
1421
1451
|
to: targetProviderType,
|
|
1422
1452
|
requestedProvider
|
|
1423
1453
|
});
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1454
|
+
const switchOptions = {};
|
|
1455
|
+
if (targetProviderType === "embedded") {
|
|
1456
|
+
switchOptions.embeddedWalletType = currentInfo?.embeddedWalletType || this.config.embeddedWalletType;
|
|
1457
|
+
}
|
|
1458
|
+
this.switchProvider(targetProviderType, switchOptions);
|
|
1427
1459
|
}
|
|
1428
1460
|
}
|
|
1429
1461
|
}
|
|
@@ -1433,12 +1465,16 @@ var ProviderManager = class {
|
|
|
1433
1465
|
}
|
|
1434
1466
|
debug.log(DebugCategory.PROVIDER_MANAGER, "Delegating to provider connect method");
|
|
1435
1467
|
const result = await this.currentProvider.connect(authOptions);
|
|
1468
|
+
const providerInfo = this.getCurrentProviderInfo();
|
|
1469
|
+
result.providerType = providerInfo?.type;
|
|
1436
1470
|
debug.log(DebugCategory.PROVIDER_MANAGER, "Connection successful, saving preferences", {
|
|
1437
|
-
addressCount: result.addresses?.length || 0
|
|
1471
|
+
addressCount: result.addresses?.length || 0,
|
|
1472
|
+
providerType: result.providerType
|
|
1438
1473
|
});
|
|
1439
1474
|
this.saveProviderPreference();
|
|
1440
1475
|
debug.info(DebugCategory.PROVIDER_MANAGER, "Connect completed", {
|
|
1441
|
-
addresses: result.addresses
|
|
1476
|
+
addresses: result.addresses,
|
|
1477
|
+
providerType: result.providerType
|
|
1442
1478
|
});
|
|
1443
1479
|
return result;
|
|
1444
1480
|
}
|
|
@@ -1622,7 +1658,11 @@ var ProviderManager = class {
|
|
|
1622
1658
|
}
|
|
1623
1659
|
debug.log(DebugCategory.PROVIDER_MANAGER, "Creating injected provider");
|
|
1624
1660
|
this.createProvider("injected");
|
|
1625
|
-
|
|
1661
|
+
const switchOptions = {};
|
|
1662
|
+
if (defaultType === "embedded") {
|
|
1663
|
+
switchOptions.embeddedWalletType = defaultEmbeddedType;
|
|
1664
|
+
}
|
|
1665
|
+
this.switchProvider(defaultType, switchOptions);
|
|
1626
1666
|
}
|
|
1627
1667
|
/**
|
|
1628
1668
|
* Create a provider instance
|
|
@@ -1994,6 +2034,49 @@ function getDeeplinkToPhantom(ref) {
|
|
|
1994
2034
|
return `https://phantom.app/ul/browse/${currentUrl}${refParam}`;
|
|
1995
2035
|
}
|
|
1996
2036
|
|
|
2037
|
+
// src/isPhantomLoginAvailable.ts
|
|
2038
|
+
import { isPhantomExtensionInstalled as isPhantomExtensionInstalled3 } from "@phantom/browser-injected-sdk";
|
|
2039
|
+
async function isPhantomLoginAvailable(timeoutMs = 3e3) {
|
|
2040
|
+
const extensionInstalled = await waitForExtension(timeoutMs);
|
|
2041
|
+
if (!extensionInstalled) {
|
|
2042
|
+
return false;
|
|
2043
|
+
}
|
|
2044
|
+
try {
|
|
2045
|
+
if (!window.phantom?.app?.features || typeof window.phantom.app.features !== "function") {
|
|
2046
|
+
return false;
|
|
2047
|
+
}
|
|
2048
|
+
const features = await window.phantom.app.features();
|
|
2049
|
+
if (!Array.isArray(features)) {
|
|
2050
|
+
return false;
|
|
2051
|
+
}
|
|
2052
|
+
return features.includes("phantom_login");
|
|
2053
|
+
} catch (error) {
|
|
2054
|
+
return false;
|
|
2055
|
+
}
|
|
2056
|
+
}
|
|
2057
|
+
async function waitForExtension(timeoutMs) {
|
|
2058
|
+
return new Promise((resolve) => {
|
|
2059
|
+
const startTime = Date.now();
|
|
2060
|
+
const checkInterval = 100;
|
|
2061
|
+
const checkForExtension = () => {
|
|
2062
|
+
try {
|
|
2063
|
+
if (isPhantomExtensionInstalled3()) {
|
|
2064
|
+
resolve(true);
|
|
2065
|
+
return;
|
|
2066
|
+
}
|
|
2067
|
+
} catch (error) {
|
|
2068
|
+
}
|
|
2069
|
+
const elapsed = Date.now() - startTime;
|
|
2070
|
+
if (elapsed >= timeoutMs) {
|
|
2071
|
+
resolve(false);
|
|
2072
|
+
return;
|
|
2073
|
+
}
|
|
2074
|
+
setTimeout(checkForExtension, checkInterval);
|
|
2075
|
+
};
|
|
2076
|
+
checkForExtension();
|
|
2077
|
+
});
|
|
2078
|
+
}
|
|
2079
|
+
|
|
1997
2080
|
// src/index.ts
|
|
1998
2081
|
import { NetworkId } from "@phantom/constants";
|
|
1999
2082
|
import { AddressType as AddressType5 } from "@phantom/client";
|
|
@@ -2009,6 +2092,7 @@ export {
|
|
|
2009
2092
|
getDeeplinkToPhantom,
|
|
2010
2093
|
getPlatformName,
|
|
2011
2094
|
isMobileDevice,
|
|
2095
|
+
isPhantomLoginAvailable,
|
|
2012
2096
|
parseBrowserFromUserAgent,
|
|
2013
2097
|
waitForPhantomExtension
|
|
2014
2098
|
};
|
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.16",
|
|
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.16",
|
|
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.16",
|
|
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",
|