@phantom/react-sdk 1.0.0-beta.2 → 1.0.0-beta.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -52,11 +52,11 @@ function App() {
52
52
 
53
53
  function WalletComponent() {
54
54
  const { connect, isConnecting } = useConnect();
55
- const solana = useSolana();
56
- const ethereum = useEthereum();
55
+ const { solana } = useSolana();
56
+ const { ethereum } = useEthereum();
57
57
 
58
58
  const handleConnect = async () => {
59
- const { addresses } = await connect();
59
+ const { addresses } = await connect({ provider: "injected" });
60
60
  console.log("Connected addresses:", addresses);
61
61
  };
62
62
 
@@ -94,9 +94,8 @@ function App() {
94
94
  <PhantomProvider
95
95
  config={{
96
96
  providerType: "embedded",
97
- embeddedWalletType: "app-wallet", // or 'user-wallet'
97
+ appId: "your-app-id", // Get your app ID from phantom.com/portal
98
98
  addressTypes: [AddressType.solana, AddressType.ethereum],
99
- apiBaseUrl: "https://api.phantom.app/v1/wallets",
100
99
  }}
101
100
  >
102
101
  <YourApp />
@@ -116,12 +115,12 @@ The React SDK follows a clear connection pattern:
116
115
  ```tsx
117
116
  function WalletExample() {
118
117
  const { connect } = useConnect();
119
- const solana = useSolana();
120
- const ethereum = useEthereum();
118
+ const { solana } = useSolana();
119
+ const { ethereum } = useEthereum();
121
120
 
122
- // 1. Connect first
121
+ // 1. Connect first (provider parameter is required)
123
122
  const handleConnect = async () => {
124
- await connect();
123
+ await connect({ provider: "injected" });
125
124
  };
126
125
 
127
126
  // 2. Then use chain-specific operations
@@ -137,26 +136,40 @@ function WalletExample() {
137
136
 
138
137
  ### Connection Options
139
138
 
140
- For embedded user-wallets, you can specify authentication providers:
139
+ The `connect()` method requires a `provider` parameter and automatically switches between providers based on the authentication method you specify:
141
140
 
142
141
  ```tsx
143
142
  const { connect } = useConnect();
144
143
 
145
- // Default: Show provider selection screen
146
- await connect();
144
+ // Connect with injected provider (Phantom extension)
145
+ // Automatically switches to injected provider if not already using it
146
+ await connect({
147
+ provider: "injected",
148
+ });
149
+
150
+ // Connect with Google authentication (embedded provider)
151
+ // Automatically switches to embedded provider if not already using it
152
+ await connect({
153
+ provider: "google",
154
+ });
155
+
156
+ // Connect with Apple authentication (embedded provider)
157
+ // Automatically switches to embedded provider if not already using it
158
+ await connect({
159
+ provider: "apple",
160
+ });
147
161
 
148
- // Google authentication (skips provider selection)
162
+ // Connect with Phantom authentication (embedded provider)
163
+ // Uses Phantom extension or mobile app for authentication
164
+ // Automatically switches to embedded provider if not already using it
149
165
  await connect({
150
- authOptions: {
151
- provider: "google",
152
- },
166
+ provider: "phantom",
153
167
  });
154
168
 
155
- // Apple authentication (skips provider selection)
169
+ // Connect with JWT authentication (embedded provider)
156
170
  await connect({
157
- authOptions: {
158
- provider: "apple",
159
- },
171
+ provider: "jwt",
172
+ jwtToken: "your-jwt-token",
160
173
  });
161
174
  ```
162
175
 
@@ -181,26 +194,7 @@ Uses the Phantom browser extension installed by the user.
181
194
 
182
195
  Creates non-custodial wallets embedded in your application.
183
196
 
184
- #### App Wallet (Recommended for most apps)
185
-
186
- - **New wallets** created per application
187
- - **Unfunded** by default - you need to fund them
188
- - **Independent** from user's existing Phantom wallet
189
-
190
- ```tsx
191
- <PhantomProvider
192
- config={{
193
- providerType: "embedded",
194
- embeddedWalletType: "app-wallet",
195
- addressTypes: [AddressType.solana],
196
- apiBaseUrl: "https://api.phantom.app/v1/wallets",
197
- }}
198
- >
199
- <YourApp />
200
- </PhantomProvider>
201
- ```
202
-
203
- #### User Wallet (For existing Phantom users)
197
+ #### User Wallet
204
198
 
205
199
  - **Uses Phantom authentication** - user logs in with existing account
206
200
  - **Potentially funded** - brings existing wallet balance
@@ -210,41 +204,14 @@ Creates non-custodial wallets embedded in your application.
210
204
  <PhantomProvider
211
205
  config={{
212
206
  providerType: "embedded",
213
- embeddedWalletType: "user-wallet",
207
+ appId: "your-app-id",
214
208
  addressTypes: [AddressType.solana, AddressType.ethereum],
215
- apiBaseUrl: "https://api.phantom.app/v1/wallets",
216
- }}
217
- >
218
- <YourApp />
219
- </PhantomProvider>
220
- ```
221
-
222
- ## Solana Provider Configuration
223
-
224
- When using `AddressType.solana`, you can choose between two Solana libraries:
225
-
226
- ```tsx
227
- <PhantomProvider
228
- config={{
229
- providerType: "embedded",
230
- addressTypes: [AddressType.solana],
231
- solanaProvider: "web3js", // or 'kit'
232
- apiBaseUrl: "https://api.phantom.app/v1/wallets",
233
209
  }}
234
210
  >
235
211
  <YourApp />
236
212
  </PhantomProvider>
237
213
  ```
238
214
 
239
- **Provider Options:**
240
-
241
- - `'web3js'` (default) - Uses `@solana/web3.js` library
242
- - `'kit'` - Uses `@solana/kit` library (modern, TypeScript-first)
243
-
244
- **When to use each:**
245
-
246
- - **@solana/web3.js**: Better ecosystem compatibility, wider community support
247
- - **@solana/kit**: Better TypeScript support, modern architecture, smaller bundle size
248
215
 
249
216
  ## Available Hooks
250
217
 
@@ -262,7 +229,7 @@ function ConnectButton() {
262
229
 
263
230
  const handleConnect = async () => {
264
231
  try {
265
- const { walletId, addresses } = await connect();
232
+ const { addresses } = await connect({ provider: "injected" });
266
233
  console.log("Connected addresses:", addresses);
267
234
  } catch (err) {
268
235
  console.error("Failed to connect:", err);
@@ -352,6 +319,33 @@ function ExtensionStatus() {
352
319
  }
353
320
  ```
354
321
 
322
+ #### useIsPhantomLoginAvailable
323
+
324
+ Check if Phantom Login is available (requires extension installed and `phantom_login` feature support):
325
+
326
+ ```tsx
327
+ import { useIsPhantomLoginAvailable } from "@phantom/react-sdk";
328
+
329
+ function PhantomLoginButton() {
330
+ const { isLoading, isAvailable } = useIsPhantomLoginAvailable();
331
+ const { connect } = useConnect();
332
+
333
+ if (isLoading) {
334
+ return <div>Checking Phantom Login availability...</div>;
335
+ }
336
+
337
+ if (!isAvailable) {
338
+ return null; // Don't show button if Phantom Login is not available
339
+ }
340
+
341
+ return (
342
+ <button onClick={() => connect({ provider: "phantom" })}>
343
+ Login with Phantom
344
+ </button>
345
+ );
346
+ }
347
+ ```
348
+
355
349
  ### Chain-Specific Hooks
356
350
 
357
351
  #### useSolana
@@ -363,7 +357,7 @@ import { useSolana } from "@phantom/react-sdk";
363
357
  import { VersionedTransaction, TransactionMessage, SystemProgram, PublicKey, Connection } from "@solana/web3.js";
364
358
 
365
359
  function SolanaOperations() {
366
- const solana = useSolana();
360
+ const { solana } = useSolana();
367
361
 
368
362
  const signMessage = async () => {
369
363
  const signature = await solana.signMessage("Hello Solana!");
@@ -392,7 +386,7 @@ function SolanaOperations() {
392
386
 
393
387
  // Sign and send
394
388
  const result = await solana.signAndSendTransaction(transaction);
395
- console.log("Transaction sent:", result.hash);
389
+ console.log("Transaction sent:", result.signature);
396
390
  };
397
391
 
398
392
  const switchNetwork = async () => {
@@ -428,7 +422,7 @@ Hook for Ethereum chain operations:
428
422
  import { useEthereum } from "@phantom/react-sdk";
429
423
 
430
424
  function EthereumOperations() {
431
- const ethereum = useEthereum();
425
+ const { ethereum } = useEthereum();
432
426
 
433
427
  const signPersonalMessage = async () => {
434
428
  const accounts = await ethereum.getAccounts();
@@ -513,12 +507,27 @@ function EthereumOperations() {
513
507
  - `signTypedData(typedData)` - Sign EIP-712 typed data
514
508
  - `signTransaction(transaction)` - Sign transaction without sending
515
509
  - `sendTransaction(transaction)` - Sign and send transaction
516
- - `switchChain(chainId)` - Switch chains
510
+ - `switchChain(chainId)` - Switch chains (accepts chain ID as number or a hex string)
517
511
  - `getChainId()` - Get current chain ID
518
512
  - `getAccounts()` - Get connected accounts
519
513
  - `isConnected` - Connection status
520
514
  - `isAvailable` - Provider availability
521
515
 
516
+ **Supported EVM Networks:**
517
+
518
+ | Network | Chain ID | Usage |
519
+ |---------|----------|-------|
520
+ | Ethereum Mainnet | `1` | `ethereum.switchChain(1)` |
521
+ | Ethereum Sepolia | `11155111` | `ethereum.switchChain(11155111)` |
522
+ | Polygon Mainnet | `137` | `ethereum.switchChain(137)` |
523
+ | Polygon Amoy | `80002` | `ethereum.switchChain(80002)` |
524
+ | Base Mainnet | `8453` | `ethereum.switchChain(8453)` |
525
+ | Base Sepolia | `84532` | `ethereum.switchChain(84532)` |
526
+ | Arbitrum One | `42161` | `ethereum.switchChain(42161)` |
527
+ | Arbitrum Sepolia | `421614` | `ethereum.switchChain(421614)` |
528
+ | Monad Mainnet | `143` | `ethereum.switchChain(143)` |
529
+ | Monad Testnet | `10143` | `ethereum.switchChain(10143)` |
530
+
522
531
  ### Auto-Confirm Hook (Injected Provider Only)
523
532
 
524
533
  #### useAutoConfirm
@@ -661,7 +670,7 @@ import { VersionedTransaction, TransactionMessage, SystemProgram, PublicKey, Con
661
670
  import { useSolana } from "@phantom/react-sdk";
662
671
 
663
672
  function SolanaExample() {
664
- const solana = useSolana();
673
+ const { solana } = useSolana();
665
674
 
666
675
  const sendTransaction = async () => {
667
676
  // Get recent blockhash
@@ -687,7 +696,7 @@ function SolanaExample() {
687
696
 
688
697
  // Sign and send using chain-specific hook
689
698
  const result = await solana.signAndSendTransaction(transaction);
690
- console.log("Transaction sent:", result.hash);
699
+ console.log("Transaction sent:", result.signature);
691
700
  };
692
701
 
693
702
  return <button onClick={sendTransaction}>Send SOL</button>;
@@ -709,7 +718,7 @@ import {
709
718
  import { useSolana } from "@phantom/react-sdk";
710
719
 
711
720
  function SolanaKitExample() {
712
- const solana = useSolana();
721
+ const { solana } = useSolana();
713
722
 
714
723
  const sendTransaction = async () => {
715
724
  const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");
@@ -726,7 +735,7 @@ function SolanaKitExample() {
726
735
 
727
736
  // Sign and send using chain-specific hook
728
737
  const result = await solana.signAndSendTransaction(transaction);
729
- console.log("Transaction sent:", result.hash);
738
+ console.log("Transaction sent:", result.signature);
730
739
  };
731
740
 
732
741
  return <button onClick={sendTransaction}>Send SOL</button>;
@@ -740,7 +749,7 @@ import { parseEther, parseGwei, encodeFunctionData } from "viem";
740
749
  import { useEthereum } from "@phantom/react-sdk";
741
750
 
742
751
  function EthereumExample() {
743
- const ethereum = useEthereum();
752
+ const { ethereum } = useEthereum();
744
753
 
745
754
  const sendEth = async () => {
746
755
  const result = await ethereum.sendTransaction({
@@ -780,16 +789,17 @@ function EthereumExample() {
780
789
 
781
790
  Quick reference of all available hooks:
782
791
 
783
- | Hook | Purpose | Returns |
784
- | ------------------------- | --------------------------------------- | --------------------------------------------------- |
785
- | `useConnect` | Connect to wallet | `{ connect, isConnecting, error }` |
786
- | `useAccounts` | Get wallet addresses | `WalletAddress[]` or `null` |
787
- | `useIsExtensionInstalled` | Check extension status | `{ isLoading, isInstalled }` |
788
- | `useDisconnect` | Disconnect from wallet | `{ disconnect, isDisconnecting }` |
789
- | `useAutoConfirm` | Auto-confirm management (injected only) | `{ enable, disable, status, supportedChains, ... }` |
790
- | `useSolana` | Solana chain operations | `{ signMessage, signAndSendTransaction, ... }` |
791
- | `useEthereum` | Ethereum chain operations | `{ signPersonalMessage, sendTransaction, ... }` |
792
- | `usePhantom` | Get provider context | `{ isConnected, isReady }` |
792
+ | Hook | Purpose | Returns |
793
+ | ----------------------------- | --------------------------------------- | --------------------------------------------------- |
794
+ | `useConnect` | Connect to wallet | `{ connect, isConnecting, error }` |
795
+ | `useAccounts` | Get wallet addresses | `WalletAddress[]` or `null` |
796
+ | `useIsExtensionInstalled` | Check extension status | `{ isLoading, isInstalled }` |
797
+ | `useIsPhantomLoginAvailable` | Check Phantom Login availability | `{ isLoading, isAvailable }` |
798
+ | `useDisconnect` | Disconnect from wallet | `{ disconnect, isDisconnecting }` |
799
+ | `useAutoConfirm` | Auto-confirm management (injected only) | `{ enable, disable, status, supportedChains, ... }` |
800
+ | `useSolana` | Solana chain operations | `{ signMessage, signAndSendTransaction, ... }` |
801
+ | `useEthereum` | Ethereum chain operations | `{ signPersonalMessage, sendTransaction, ... }` |
802
+ | `usePhantom` | Get provider context | `{ isConnected, isReady }` |
793
803
 
794
804
  ## Configuration Reference
795
805
 
@@ -799,15 +809,16 @@ interface PhantomSDKConfig {
799
809
  addressTypes?: [AddressType, ...AddressType[]]; // Networks to enable (e.g., [AddressType.solana])
800
810
 
801
811
  // Required for embedded provider only
802
- apiBaseUrl?: string; // Phantom API base URL
803
- appId: string; // Your app ID
812
+ appId: string; // Your app ID from phantom.com/portal (required for embedded provider)
813
+
814
+ // Optional configuration
815
+ apiBaseUrl?: string; // Phantom API base URL (optional, has default)
804
816
  authOptions?: {
805
- authUrl?: string; // Custom auth URL (optional)
806
- redirectUrl?: string; // Custom redirect URL (optional)
817
+ authUrl?: string; // Custom auth URL (optional, defaults to "https://connect.phantom.app/login")
818
+ redirectUrl?: string; // Custom redirect URL after authentication (optional)
807
819
  };
808
- embeddedWalletType?: "app-wallet" | "user-wallet"; // Wallet type
809
- solanaProvider?: "web3js" | "kit"; // Solana library choice (default: 'web3js')
810
- autoConnect?: boolean; // Auto-connect to existing session on SDK instantiation (default: true for embedded, false for injected)
820
+ embeddedWalletType?: "user-wallet"; // Wallet type (optional, defaults to "user-wallet", currently the only supported type)
821
+ autoConnect?: boolean; // Auto-connect to existing session on SDK instantiation (optional, defaults to true for embedded, false for injected)
811
822
  }
812
823
  ```
813
824
 
@@ -839,6 +850,7 @@ function App() {
839
850
  // SDK configuration - static, won't change when debug settings change
840
851
  const config: PhantomSDKConfig = {
841
852
  providerType: "embedded",
853
+ appId: "your-app-id",
842
854
  // ... other config
843
855
  };
844
856
 
package/dist/index.d.ts CHANGED
@@ -1,13 +1,12 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
- import { BrowserSDKConfig, DebugConfig, AuthOptions, BrowserSDK, WalletAddress, AutoConfirmEnableParams, AutoConfirmResult, AutoConfirmSupportedChainsResult } from '@phantom/browser-sdk';
4
- export { AddressType, AutoConfirmEnableParams, AutoConfirmResult, AutoConfirmSupportedChainsResult, DebugLevel, DebugMessage, NetworkId, SignedTransaction, WalletAddress, debug } from '@phantom/browser-sdk';
3
+ import { BrowserSDKConfig, DebugConfig, AuthOptions, BrowserSDK, WalletAddress, ConnectResult, AutoConfirmEnableParams, AutoConfirmResult, AutoConfirmSupportedChainsResult } from '@phantom/browser-sdk';
4
+ export { AddressType, AutoConfirmEnableParams, AutoConfirmResult, AutoConfirmSupportedChainsResult, ConnectErrorEventData, ConnectEventData, ConnectStartEventData, DebugLevel, DebugMessage, DisconnectEventData, EmbeddedProviderEvent, EmbeddedProviderEventMap, EventCallback, NetworkId, SignedTransaction, WalletAddress, debug } from '@phantom/browser-sdk';
5
5
  import * as _phantom_embedded_provider_core from '@phantom/embedded-provider-core';
6
- import { ISolanaChain, IEthereumChain, EthTransactionRequest } from '@phantom/chains';
7
- export { EthTransactionRequest, IEthereumChain, ISolanaChain } from '@phantom/chains';
6
+ import { ISolanaChain, IEthereumChain } from '@phantom/chain-interfaces';
7
+ export { EthTransactionRequest, IEthereumChain, ISolanaChain } from '@phantom/chain-interfaces';
8
8
 
9
- interface PhantomSDKConfig extends BrowserSDKConfig {
10
- }
9
+ type PhantomSDKConfig = BrowserSDKConfig;
11
10
  interface PhantomDebugConfig extends DebugConfig {
12
11
  }
13
12
  interface ConnectOptions {
@@ -21,9 +20,10 @@ interface PhantomContextValue {
21
20
  isConnecting: boolean;
22
21
  connectError: Error | null;
23
22
  addresses: WalletAddress[];
24
- walletId: string | null;
25
23
  currentProviderType: "injected" | "embedded" | null;
26
24
  isPhantomAvailable: boolean;
25
+ isClient: boolean;
26
+ user: ConnectResult | null;
27
27
  }
28
28
  interface PhantomProviderProps {
29
29
  children: ReactNode;
@@ -34,7 +34,7 @@ declare function PhantomProvider({ children, config, debugConfig }: PhantomProvi
34
34
  declare function usePhantom(): PhantomContextValue;
35
35
 
36
36
  declare function useConnect(): {
37
- connect: (options?: AuthOptions) => Promise<_phantom_embedded_provider_core.ConnectResult>;
37
+ connect: (options: AuthOptions) => Promise<_phantom_embedded_provider_core.ConnectResult>;
38
38
  isConnecting: boolean;
39
39
  error: Error | null;
40
40
  currentProviderType: "injected" | "embedded" | null;
@@ -58,6 +58,15 @@ declare function useIsExtensionInstalled(): {
58
58
  isInstalled: boolean;
59
59
  };
60
60
 
61
+ /**
62
+ * React hook to check if Phantom Login is available
63
+ * Checks if extension is installed and supports phantom_login feature
64
+ */
65
+ declare function useIsPhantomLoginAvailable(): {
66
+ isLoading: boolean;
67
+ isAvailable: boolean;
68
+ };
69
+
61
70
  interface UseAutoConfirmResult {
62
71
  enable: (params: AutoConfirmEnableParams) => Promise<AutoConfirmResult>;
63
72
  disable: () => Promise<void>;
@@ -72,53 +81,23 @@ declare function useAutoConfirm(): UseAutoConfirmResult;
72
81
  /**
73
82
  * Hook for Solana chain operations
74
83
  *
75
- * @returns Solana chain interface and convenient methods
84
+ * @returns Solana chain interface with connection enforcement
76
85
  */
77
86
  declare function useSolana(): {
78
- solana: ISolanaChain | null;
79
- signMessage: (message: string | Uint8Array) => Promise<{
80
- signature: Uint8Array;
81
- publicKey: string;
82
- }>;
83
- signTransaction: <T>(transaction: T) => Promise<T>;
84
- signAndSendTransaction: <T>(transaction: T) => Promise<{
85
- signature: string;
86
- }>;
87
- connect: (options?: {
88
- onlyIfTrusted?: boolean;
89
- }) => Promise<{
90
- publicKey: string;
91
- }>;
92
- disconnect: () => Promise<void>;
93
- switchNetwork: (network: "mainnet" | "devnet") => Promise<void | undefined>;
94
- getPublicKey: () => Promise<string | null>;
87
+ solana: ISolanaChain;
95
88
  isAvailable: boolean;
96
- isConnected: boolean;
97
89
  };
98
90
 
99
91
  /**
100
92
  * Hook for Ethereum chain operations
101
93
  *
102
- * @returns Ethereum chain interface and convenient methods
94
+ * @returns Ethereum chain interface with connection enforcement
103
95
  */
104
96
  declare function useEthereum(): {
105
- ethereum: IEthereumChain | null;
106
- request: <T = any>(args: {
107
- method: string;
108
- params?: unknown[];
109
- }) => Promise<T>;
110
- signPersonalMessage: (message: string, address: string) => Promise<string>;
111
- signMessage: (message: string) => Promise<string>;
112
- signTransaction: (transaction: EthTransactionRequest) => Promise<string>;
113
- signTypedData: (typedData: any) => Promise<string>;
114
- sendTransaction: (transaction: EthTransactionRequest) => Promise<string>;
115
- switchChain: (chainId: number) => Promise<void>;
116
- getChainId: () => Promise<number>;
117
- getAccounts: () => Promise<string[]>;
97
+ ethereum: IEthereumChain;
118
98
  isAvailable: boolean;
119
- isConnected: boolean;
120
99
  };
121
100
 
122
101
  type ProviderType = "injected" | "embedded";
123
102
 
124
- export { ConnectOptions, PhantomDebugConfig, PhantomProvider, PhantomProviderProps, PhantomSDKConfig, ProviderType, useAccounts, useAutoConfirm, useConnect, useDisconnect, useEthereum, useIsExtensionInstalled, usePhantom, useSolana };
103
+ export { ConnectOptions, PhantomDebugConfig, PhantomProvider, PhantomProviderProps, PhantomSDKConfig, ProviderType, useAccounts, useAutoConfirm, useConnect, useDisconnect, useEthereum, useIsExtensionInstalled, useIsPhantomLoginAvailable, usePhantom, useSolana };
package/dist/index.js CHANGED
@@ -30,17 +30,18 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
- AddressType: () => import_browser_sdk3.AddressType,
34
- DebugLevel: () => import_browser_sdk3.DebugLevel,
35
- NetworkId: () => import_browser_sdk3.NetworkId,
33
+ AddressType: () => import_browser_sdk4.AddressType,
34
+ DebugLevel: () => import_browser_sdk4.DebugLevel,
35
+ NetworkId: () => import_browser_sdk4.NetworkId,
36
36
  PhantomProvider: () => PhantomProvider,
37
- debug: () => import_browser_sdk3.debug,
37
+ debug: () => import_browser_sdk4.debug,
38
38
  useAccounts: () => useAccounts,
39
39
  useAutoConfirm: () => useAutoConfirm,
40
40
  useConnect: () => useConnect,
41
41
  useDisconnect: () => useDisconnect,
42
42
  useEthereum: () => useEthereum,
43
43
  useIsExtensionInstalled: () => useIsExtensionInstalled,
44
+ useIsPhantomLoginAvailable: () => useIsPhantomLoginAvailable,
44
45
  usePhantom: () => usePhantom,
45
46
  useSolana: () => useSolana
46
47
  });
@@ -52,42 +53,46 @@ var import_browser_sdk = require("@phantom/browser-sdk");
52
53
  var import_jsx_runtime = require("react/jsx-runtime");
53
54
  var PhantomContext = (0, import_react.createContext)(void 0);
54
55
  function PhantomProvider({ children, config, debugConfig }) {
55
- const memoizedConfig = (0, import_react.useMemo)(() => {
56
- return {
57
- ...config,
58
- // Use providerType if provided, default to embedded
59
- providerType: config.providerType || "embedded"
60
- };
61
- }, [config]);
56
+ const memoizedConfig = (0, import_react.useMemo)(() => config, [config]);
57
+ const [sdk, setSdk] = (0, import_react.useState)(null);
58
+ const [isClient, setIsClient] = (0, import_react.useState)(false);
62
59
  const [isConnected, setIsConnected] = (0, import_react.useState)(false);
63
60
  const [isConnecting, setIsConnecting] = (0, import_react.useState)(false);
64
61
  const [connectError, setConnectError] = (0, import_react.useState)(null);
65
62
  const [addresses, setAddresses] = (0, import_react.useState)([]);
66
- const [walletId, setWalletId] = (0, import_react.useState)(null);
67
63
  const [currentProviderType, setCurrentProviderType] = (0, import_react.useState)(
68
64
  memoizedConfig.providerType || null
69
65
  );
70
66
  const [isPhantomAvailable, setIsPhantomAvailable] = (0, import_react.useState)(false);
71
- const [sdk, setSdk] = (0, import_react.useState)(null);
67
+ const [user, setUser] = (0, import_react.useState)(null);
68
+ (0, import_react.useEffect)(() => {
69
+ setIsClient(true);
70
+ }, []);
72
71
  (0, import_react.useEffect)(() => {
72
+ if (!isClient)
73
+ return;
73
74
  const sdkInstance = new import_browser_sdk.BrowserSDK(memoizedConfig);
75
+ setSdk(sdkInstance);
76
+ }, [isClient, memoizedConfig]);
77
+ (0, import_react.useEffect)(() => {
78
+ if (!sdk)
79
+ return;
74
80
  const handleConnectStart = () => {
75
81
  setIsConnecting(true);
76
82
  setConnectError(null);
77
83
  };
78
- const handleConnect = async () => {
84
+ const handleConnect = async (data) => {
79
85
  try {
80
86
  setIsConnected(true);
81
87
  setIsConnecting(false);
82
- const providerInfo = sdkInstance.getCurrentProviderInfo();
83
- setCurrentProviderType(providerInfo?.type || null);
84
- const addrs = await sdkInstance.getAddresses();
88
+ setUser(data);
89
+ setCurrentProviderType(data.providerType || null);
90
+ const addrs = await sdk.getAddresses();
85
91
  setAddresses(addrs);
86
- setWalletId(sdkInstance.getWalletId());
87
92
  } catch (err) {
88
93
  console.error("Error connecting:", err);
89
94
  try {
90
- await sdkInstance.disconnect();
95
+ await sdk.disconnect();
91
96
  } catch (err2) {
92
97
  console.error("Error disconnecting:", err2);
93
98
  }
@@ -97,33 +102,33 @@ function PhantomProvider({ children, config, debugConfig }) {
97
102
  setIsConnecting(false);
98
103
  setIsConnected(false);
99
104
  setConnectError(new Error(errorData.error || "Connection failed"));
105
+ setAddresses([]);
100
106
  };
101
107
  const handleDisconnect = () => {
102
108
  setIsConnected(false);
103
109
  setIsConnecting(false);
104
110
  setConnectError(null);
105
111
  setAddresses([]);
106
- setWalletId(null);
112
+ setUser(null);
107
113
  };
108
- sdkInstance.on("connect_start", handleConnectStart);
109
- sdkInstance.on("connect", handleConnect);
110
- sdkInstance.on("connect_error", handleConnectError);
111
- sdkInstance.on("disconnect", handleDisconnect);
112
- setSdk(sdkInstance);
114
+ sdk.on("connect_start", handleConnectStart);
115
+ sdk.on("connect", handleConnect);
116
+ sdk.on("connect_error", handleConnectError);
117
+ sdk.on("disconnect", handleDisconnect);
113
118
  return () => {
114
- sdkInstance.off("connect_start", handleConnectStart);
115
- sdkInstance.off("connect", handleConnect);
116
- sdkInstance.off("connect_error", handleConnectError);
117
- sdkInstance.off("disconnect", handleDisconnect);
119
+ sdk.off("connect_start", handleConnectStart);
120
+ sdk.off("connect", handleConnect);
121
+ sdk.off("connect_error", handleConnectError);
122
+ sdk.off("disconnect", handleDisconnect);
118
123
  };
119
- }, [memoizedConfig]);
124
+ }, [sdk]);
120
125
  (0, import_react.useEffect)(() => {
121
- if (!sdk || !debugConfig)
126
+ if (!debugConfig || !sdk)
122
127
  return;
123
128
  sdk.configureDebug(debugConfig);
124
129
  }, [sdk, debugConfig]);
125
130
  (0, import_react.useEffect)(() => {
126
- if (!sdk)
131
+ if (!isClient || !sdk)
127
132
  return;
128
133
  const initialize = async () => {
129
134
  try {
@@ -139,7 +144,7 @@ function PhantomProvider({ children, config, debugConfig }) {
139
144
  }
140
145
  };
141
146
  initialize();
142
- }, [sdk, memoizedConfig.autoConnect]);
147
+ }, [sdk, memoizedConfig.autoConnect, isClient]);
143
148
  const value = (0, import_react.useMemo)(
144
149
  () => ({
145
150
  sdk,
@@ -147,11 +152,12 @@ function PhantomProvider({ children, config, debugConfig }) {
147
152
  isConnecting,
148
153
  connectError,
149
154
  addresses,
150
- walletId,
151
155
  currentProviderType,
152
- isPhantomAvailable
156
+ isPhantomAvailable,
157
+ isClient,
158
+ user
153
159
  }),
154
- [sdk, isConnected, isConnecting, connectError, addresses, walletId, currentProviderType, isPhantomAvailable]
160
+ [sdk, isConnected, isConnecting, connectError, addresses, currentProviderType, isPhantomAvailable, isClient, user]
155
161
  );
156
162
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PhantomContext.Provider, { value, children });
157
163
  }
@@ -258,6 +264,39 @@ function useIsExtensionInstalled() {
258
264
  return { isLoading, isInstalled };
259
265
  }
260
266
 
267
+ // src/hooks/useIsPhantomLoginAvailable.ts
268
+ var React2 = __toESM(require("react"));
269
+ var import_browser_sdk3 = require("@phantom/browser-sdk");
270
+ function useIsPhantomLoginAvailable() {
271
+ const [isLoading, setIsLoading] = React2.useState(true);
272
+ const [isAvailable, setIsAvailable] = React2.useState(false);
273
+ React2.useEffect(() => {
274
+ let isMounted = true;
275
+ const checkPhantomLogin = async () => {
276
+ try {
277
+ setIsLoading(true);
278
+ const result = await (0, import_browser_sdk3.isPhantomLoginAvailable)(3e3);
279
+ if (isMounted) {
280
+ setIsAvailable(result);
281
+ }
282
+ } catch (error) {
283
+ if (isMounted) {
284
+ setIsAvailable(false);
285
+ }
286
+ } finally {
287
+ if (isMounted) {
288
+ setIsLoading(false);
289
+ }
290
+ }
291
+ };
292
+ checkPhantomLogin();
293
+ return () => {
294
+ isMounted = false;
295
+ };
296
+ }, []);
297
+ return { isLoading, isAvailable };
298
+ }
299
+
261
300
  // src/hooks/useAutoConfirm.ts
262
301
  var import_react4 = require("react");
263
302
  function useAutoConfirm() {
@@ -353,189 +392,40 @@ function useAutoConfirm() {
353
392
  }
354
393
 
355
394
  // src/hooks/useSolana.ts
356
- var import_react5 = require("react");
357
395
  function useSolana() {
358
- const { sdk, isConnected } = usePhantom();
359
- const getSolanaChain = (0, import_react5.useCallback)(() => {
360
- if (!sdk)
361
- throw new Error("Phantom SDK not initialized.");
362
- if (!sdk.isConnected())
363
- throw new Error("Phantom SDK not connected. Call connect() first.");
364
- return sdk.solana;
365
- }, [sdk]);
366
- const solanaChain = (0, import_react5.useMemo)(() => {
367
- if (!sdk || !isConnected)
368
- return null;
369
- try {
370
- return sdk.solana;
371
- } catch {
372
- return null;
373
- }
374
- }, [sdk, isConnected]);
375
- const signMessage = (0, import_react5.useCallback)(
376
- async (message) => {
377
- const chain = getSolanaChain();
378
- return chain.signMessage(message);
379
- },
380
- [getSolanaChain]
381
- );
382
- const signTransaction = (0, import_react5.useCallback)(
383
- async (transaction) => {
384
- const chain = getSolanaChain();
385
- return chain.signTransaction(transaction);
386
- },
387
- [getSolanaChain]
388
- );
389
- const signAndSendTransaction = (0, import_react5.useCallback)(
390
- async (transaction) => {
391
- const chain = getSolanaChain();
392
- return chain.signAndSendTransaction(transaction);
393
- },
394
- [getSolanaChain]
395
- );
396
- const connect = (0, import_react5.useCallback)(
397
- async (options) => {
398
- const chain = getSolanaChain();
399
- return chain.connect(options);
400
- },
401
- [getSolanaChain]
402
- );
403
- const disconnect = (0, import_react5.useCallback)(async () => {
404
- const chain = getSolanaChain();
405
- return chain.disconnect();
406
- }, [getSolanaChain]);
407
- const switchNetwork = (0, import_react5.useCallback)(
408
- async (network) => {
409
- const chain = getSolanaChain();
410
- return chain.switchNetwork?.(network);
411
- },
412
- [getSolanaChain]
413
- );
414
- const getPublicKey = (0, import_react5.useCallback)(async () => {
415
- if (!sdk || !sdk.isConnected())
416
- return null;
417
- return sdk.solana.getPublicKey();
418
- }, [sdk]);
396
+ const { sdk, isConnected, isClient } = usePhantom();
397
+ if (!isClient || !sdk) {
398
+ return {
399
+ solana: {},
400
+ // This will be replaced when SDK is ready
401
+ isAvailable: false
402
+ };
403
+ }
419
404
  return {
420
- // Chain instance for advanced usage
421
- solana: solanaChain,
422
- // Convenient methods
423
- signMessage,
424
- signTransaction,
425
- signAndSendTransaction,
426
- connect,
427
- disconnect,
428
- switchNetwork,
429
- getPublicKey,
405
+ // Chain instance with connection enforcement for signing methods
406
+ solana: sdk.solana,
430
407
  // State
431
- isAvailable: !!solanaChain,
432
- isConnected: solanaChain?.isConnected() ?? false
408
+ isAvailable: !!isConnected
433
409
  };
434
410
  }
435
411
 
436
412
  // src/hooks/useEthereum.ts
437
- var import_react6 = require("react");
438
413
  function useEthereum() {
439
- const { sdk, isConnected } = usePhantom();
440
- const getEthereumChain = (0, import_react6.useCallback)(() => {
441
- if (!sdk)
442
- throw new Error("Phantom SDK not initialized.");
443
- if (!sdk.isConnected())
444
- throw new Error("Phantom SDK not connected. Call connect() first.");
445
- return sdk.ethereum;
446
- }, [sdk]);
447
- const ethereumChain = (0, import_react6.useMemo)(() => {
448
- if (!sdk || !isConnected)
449
- return null;
450
- try {
451
- return sdk.ethereum;
452
- } catch {
453
- return null;
454
- }
455
- }, [sdk, isConnected]);
456
- const request = (0, import_react6.useCallback)(
457
- async (args) => {
458
- const chain = getEthereumChain();
459
- return chain.request(args);
460
- },
461
- [getEthereumChain]
462
- );
463
- const signPersonalMessage = (0, import_react6.useCallback)(
464
- async (message, address) => {
465
- return request({
466
- method: "personal_sign",
467
- params: [message, address]
468
- });
469
- },
470
- [request]
471
- );
472
- const signTransaction = (0, import_react6.useCallback)(
473
- async (transaction) => {
474
- const chain = getEthereumChain();
475
- return chain.signTransaction(transaction);
476
- },
477
- [getEthereumChain]
478
- );
479
- const sendTransaction = (0, import_react6.useCallback)(
480
- async (transaction) => {
481
- const chain = getEthereumChain();
482
- return chain.sendTransaction(transaction);
483
- },
484
- [getEthereumChain]
485
- );
486
- const switchChain = (0, import_react6.useCallback)(
487
- async (chainId) => {
488
- const chain = getEthereumChain();
489
- return chain.switchChain(chainId);
490
- },
491
- [getEthereumChain]
492
- );
493
- const getChainId = (0, import_react6.useCallback)(async () => {
494
- const chain = getEthereumChain();
495
- return chain.getChainId();
496
- }, [getEthereumChain]);
497
- const getAccounts = (0, import_react6.useCallback)(async () => {
498
- const chain = getEthereumChain();
499
- return chain.getAccounts();
500
- }, [getEthereumChain]);
501
- const signMessage = (0, import_react6.useCallback)(
502
- async (message) => {
503
- return request({
504
- method: "eth_sign",
505
- params: [await getAccounts().then((accounts) => accounts[0]), message]
506
- });
507
- },
508
- [request, getAccounts]
509
- );
510
- const signTypedData = (0, import_react6.useCallback)(
511
- async (typedData) => {
512
- const accounts = await getAccounts();
513
- return request({
514
- method: "eth_signTypedData_v4",
515
- params: [accounts[0], JSON.stringify(typedData)]
516
- });
517
- },
518
- [request, getAccounts]
519
- );
414
+ const { sdk, isConnected, isClient } = usePhantom();
415
+ if (!isClient || !sdk) {
416
+ return {
417
+ ethereum: {},
418
+ // This will be replaced when SDK is ready
419
+ isAvailable: false
420
+ };
421
+ }
520
422
  return {
521
- // Chain instance for advanced usage
522
- ethereum: ethereumChain,
523
- // Standard EIP-1193 interface
524
- request,
525
- // Convenient methods
526
- signPersonalMessage,
527
- signMessage,
528
- signTransaction,
529
- signTypedData,
530
- sendTransaction,
531
- switchChain,
532
- getChainId,
533
- getAccounts,
423
+ // Chain instance with connection enforcement for signing methods
424
+ ethereum: sdk.ethereum,
534
425
  // State
535
- isAvailable: !!ethereumChain,
536
- isConnected: ethereumChain?.isConnected() ?? false
426
+ isAvailable: !!isConnected
537
427
  };
538
428
  }
539
429
 
540
430
  // src/index.ts
541
- var import_browser_sdk3 = require("@phantom/browser-sdk");
431
+ var import_browser_sdk4 = require("@phantom/browser-sdk");
package/dist/index.mjs CHANGED
@@ -4,42 +4,46 @@ import { BrowserSDK } from "@phantom/browser-sdk";
4
4
  import { jsx } from "react/jsx-runtime";
5
5
  var PhantomContext = createContext(void 0);
6
6
  function PhantomProvider({ children, config, debugConfig }) {
7
- const memoizedConfig = useMemo(() => {
8
- return {
9
- ...config,
10
- // Use providerType if provided, default to embedded
11
- providerType: config.providerType || "embedded"
12
- };
13
- }, [config]);
7
+ const memoizedConfig = useMemo(() => config, [config]);
8
+ const [sdk, setSdk] = useState(null);
9
+ const [isClient, setIsClient] = useState(false);
14
10
  const [isConnected, setIsConnected] = useState(false);
15
11
  const [isConnecting, setIsConnecting] = useState(false);
16
12
  const [connectError, setConnectError] = useState(null);
17
13
  const [addresses, setAddresses] = useState([]);
18
- const [walletId, setWalletId] = useState(null);
19
14
  const [currentProviderType, setCurrentProviderType] = useState(
20
15
  memoizedConfig.providerType || null
21
16
  );
22
17
  const [isPhantomAvailable, setIsPhantomAvailable] = useState(false);
23
- const [sdk, setSdk] = useState(null);
18
+ const [user, setUser] = useState(null);
19
+ useEffect(() => {
20
+ setIsClient(true);
21
+ }, []);
24
22
  useEffect(() => {
23
+ if (!isClient)
24
+ return;
25
25
  const sdkInstance = new BrowserSDK(memoizedConfig);
26
+ setSdk(sdkInstance);
27
+ }, [isClient, memoizedConfig]);
28
+ useEffect(() => {
29
+ if (!sdk)
30
+ return;
26
31
  const handleConnectStart = () => {
27
32
  setIsConnecting(true);
28
33
  setConnectError(null);
29
34
  };
30
- const handleConnect = async () => {
35
+ const handleConnect = async (data) => {
31
36
  try {
32
37
  setIsConnected(true);
33
38
  setIsConnecting(false);
34
- const providerInfo = sdkInstance.getCurrentProviderInfo();
35
- setCurrentProviderType(providerInfo?.type || null);
36
- const addrs = await sdkInstance.getAddresses();
39
+ setUser(data);
40
+ setCurrentProviderType(data.providerType || null);
41
+ const addrs = await sdk.getAddresses();
37
42
  setAddresses(addrs);
38
- setWalletId(sdkInstance.getWalletId());
39
43
  } catch (err) {
40
44
  console.error("Error connecting:", err);
41
45
  try {
42
- await sdkInstance.disconnect();
46
+ await sdk.disconnect();
43
47
  } catch (err2) {
44
48
  console.error("Error disconnecting:", err2);
45
49
  }
@@ -49,33 +53,33 @@ function PhantomProvider({ children, config, debugConfig }) {
49
53
  setIsConnecting(false);
50
54
  setIsConnected(false);
51
55
  setConnectError(new Error(errorData.error || "Connection failed"));
56
+ setAddresses([]);
52
57
  };
53
58
  const handleDisconnect = () => {
54
59
  setIsConnected(false);
55
60
  setIsConnecting(false);
56
61
  setConnectError(null);
57
62
  setAddresses([]);
58
- setWalletId(null);
63
+ setUser(null);
59
64
  };
60
- sdkInstance.on("connect_start", handleConnectStart);
61
- sdkInstance.on("connect", handleConnect);
62
- sdkInstance.on("connect_error", handleConnectError);
63
- sdkInstance.on("disconnect", handleDisconnect);
64
- setSdk(sdkInstance);
65
+ sdk.on("connect_start", handleConnectStart);
66
+ sdk.on("connect", handleConnect);
67
+ sdk.on("connect_error", handleConnectError);
68
+ sdk.on("disconnect", handleDisconnect);
65
69
  return () => {
66
- sdkInstance.off("connect_start", handleConnectStart);
67
- sdkInstance.off("connect", handleConnect);
68
- sdkInstance.off("connect_error", handleConnectError);
69
- sdkInstance.off("disconnect", handleDisconnect);
70
+ sdk.off("connect_start", handleConnectStart);
71
+ sdk.off("connect", handleConnect);
72
+ sdk.off("connect_error", handleConnectError);
73
+ sdk.off("disconnect", handleDisconnect);
70
74
  };
71
- }, [memoizedConfig]);
75
+ }, [sdk]);
72
76
  useEffect(() => {
73
- if (!sdk || !debugConfig)
77
+ if (!debugConfig || !sdk)
74
78
  return;
75
79
  sdk.configureDebug(debugConfig);
76
80
  }, [sdk, debugConfig]);
77
81
  useEffect(() => {
78
- if (!sdk)
82
+ if (!isClient || !sdk)
79
83
  return;
80
84
  const initialize = async () => {
81
85
  try {
@@ -91,7 +95,7 @@ function PhantomProvider({ children, config, debugConfig }) {
91
95
  }
92
96
  };
93
97
  initialize();
94
- }, [sdk, memoizedConfig.autoConnect]);
98
+ }, [sdk, memoizedConfig.autoConnect, isClient]);
95
99
  const value = useMemo(
96
100
  () => ({
97
101
  sdk,
@@ -99,11 +103,12 @@ function PhantomProvider({ children, config, debugConfig }) {
99
103
  isConnecting,
100
104
  connectError,
101
105
  addresses,
102
- walletId,
103
106
  currentProviderType,
104
- isPhantomAvailable
107
+ isPhantomAvailable,
108
+ isClient,
109
+ user
105
110
  }),
106
- [sdk, isConnected, isConnecting, connectError, addresses, walletId, currentProviderType, isPhantomAvailable]
111
+ [sdk, isConnected, isConnecting, connectError, addresses, currentProviderType, isPhantomAvailable, isClient, user]
107
112
  );
108
113
  return /* @__PURE__ */ jsx(PhantomContext.Provider, { value, children });
109
114
  }
@@ -210,14 +215,47 @@ function useIsExtensionInstalled() {
210
215
  return { isLoading, isInstalled };
211
216
  }
212
217
 
218
+ // src/hooks/useIsPhantomLoginAvailable.ts
219
+ import * as React2 from "react";
220
+ import { isPhantomLoginAvailable } from "@phantom/browser-sdk";
221
+ function useIsPhantomLoginAvailable() {
222
+ const [isLoading, setIsLoading] = React2.useState(true);
223
+ const [isAvailable, setIsAvailable] = React2.useState(false);
224
+ React2.useEffect(() => {
225
+ let isMounted = true;
226
+ const checkPhantomLogin = async () => {
227
+ try {
228
+ setIsLoading(true);
229
+ const result = await isPhantomLoginAvailable(3e3);
230
+ if (isMounted) {
231
+ setIsAvailable(result);
232
+ }
233
+ } catch (error) {
234
+ if (isMounted) {
235
+ setIsAvailable(false);
236
+ }
237
+ } finally {
238
+ if (isMounted) {
239
+ setIsLoading(false);
240
+ }
241
+ }
242
+ };
243
+ checkPhantomLogin();
244
+ return () => {
245
+ isMounted = false;
246
+ };
247
+ }, []);
248
+ return { isLoading, isAvailable };
249
+ }
250
+
213
251
  // src/hooks/useAutoConfirm.ts
214
- import { useCallback as useCallback3, useState as useState4, useEffect as useEffect3 } from "react";
252
+ import { useCallback as useCallback3, useState as useState5, useEffect as useEffect4 } from "react";
215
253
  function useAutoConfirm() {
216
254
  const { sdk, currentProviderType } = usePhantom();
217
- const [status, setStatus] = useState4(null);
218
- const [supportedChains, setSupportedChains] = useState4(null);
219
- const [isLoading, setIsLoading] = useState4(false);
220
- const [error, setError] = useState4(null);
255
+ const [status, setStatus] = useState5(null);
256
+ const [supportedChains, setSupportedChains] = useState5(null);
257
+ const [isLoading, setIsLoading] = useState5(false);
258
+ const [error, setError] = useState5(null);
221
259
  const isInjected = currentProviderType === "injected";
222
260
  const enable = useCallback3(
223
261
  async (params) => {
@@ -284,7 +322,7 @@ function useAutoConfirm() {
284
322
  setIsLoading(false);
285
323
  }
286
324
  }, [sdk, isInjected]);
287
- useEffect3(() => {
325
+ useEffect4(() => {
288
326
  if (sdk && isInjected) {
289
327
  refetch();
290
328
  } else {
@@ -305,187 +343,38 @@ function useAutoConfirm() {
305
343
  }
306
344
 
307
345
  // src/hooks/useSolana.ts
308
- import { useCallback as useCallback4, useMemo as useMemo2 } from "react";
309
346
  function useSolana() {
310
- const { sdk, isConnected } = usePhantom();
311
- const getSolanaChain = useCallback4(() => {
312
- if (!sdk)
313
- throw new Error("Phantom SDK not initialized.");
314
- if (!sdk.isConnected())
315
- throw new Error("Phantom SDK not connected. Call connect() first.");
316
- return sdk.solana;
317
- }, [sdk]);
318
- const solanaChain = useMemo2(() => {
319
- if (!sdk || !isConnected)
320
- return null;
321
- try {
322
- return sdk.solana;
323
- } catch {
324
- return null;
325
- }
326
- }, [sdk, isConnected]);
327
- const signMessage = useCallback4(
328
- async (message) => {
329
- const chain = getSolanaChain();
330
- return chain.signMessage(message);
331
- },
332
- [getSolanaChain]
333
- );
334
- const signTransaction = useCallback4(
335
- async (transaction) => {
336
- const chain = getSolanaChain();
337
- return chain.signTransaction(transaction);
338
- },
339
- [getSolanaChain]
340
- );
341
- const signAndSendTransaction = useCallback4(
342
- async (transaction) => {
343
- const chain = getSolanaChain();
344
- return chain.signAndSendTransaction(transaction);
345
- },
346
- [getSolanaChain]
347
- );
348
- const connect = useCallback4(
349
- async (options) => {
350
- const chain = getSolanaChain();
351
- return chain.connect(options);
352
- },
353
- [getSolanaChain]
354
- );
355
- const disconnect = useCallback4(async () => {
356
- const chain = getSolanaChain();
357
- return chain.disconnect();
358
- }, [getSolanaChain]);
359
- const switchNetwork = useCallback4(
360
- async (network) => {
361
- const chain = getSolanaChain();
362
- return chain.switchNetwork?.(network);
363
- },
364
- [getSolanaChain]
365
- );
366
- const getPublicKey = useCallback4(async () => {
367
- if (!sdk || !sdk.isConnected())
368
- return null;
369
- return sdk.solana.getPublicKey();
370
- }, [sdk]);
347
+ const { sdk, isConnected, isClient } = usePhantom();
348
+ if (!isClient || !sdk) {
349
+ return {
350
+ solana: {},
351
+ // This will be replaced when SDK is ready
352
+ isAvailable: false
353
+ };
354
+ }
371
355
  return {
372
- // Chain instance for advanced usage
373
- solana: solanaChain,
374
- // Convenient methods
375
- signMessage,
376
- signTransaction,
377
- signAndSendTransaction,
378
- connect,
379
- disconnect,
380
- switchNetwork,
381
- getPublicKey,
356
+ // Chain instance with connection enforcement for signing methods
357
+ solana: sdk.solana,
382
358
  // State
383
- isAvailable: !!solanaChain,
384
- isConnected: solanaChain?.isConnected() ?? false
359
+ isAvailable: !!isConnected
385
360
  };
386
361
  }
387
362
 
388
363
  // src/hooks/useEthereum.ts
389
- import { useCallback as useCallback5, useMemo as useMemo3 } from "react";
390
364
  function useEthereum() {
391
- const { sdk, isConnected } = usePhantom();
392
- const getEthereumChain = useCallback5(() => {
393
- if (!sdk)
394
- throw new Error("Phantom SDK not initialized.");
395
- if (!sdk.isConnected())
396
- throw new Error("Phantom SDK not connected. Call connect() first.");
397
- return sdk.ethereum;
398
- }, [sdk]);
399
- const ethereumChain = useMemo3(() => {
400
- if (!sdk || !isConnected)
401
- return null;
402
- try {
403
- return sdk.ethereum;
404
- } catch {
405
- return null;
406
- }
407
- }, [sdk, isConnected]);
408
- const request = useCallback5(
409
- async (args) => {
410
- const chain = getEthereumChain();
411
- return chain.request(args);
412
- },
413
- [getEthereumChain]
414
- );
415
- const signPersonalMessage = useCallback5(
416
- async (message, address) => {
417
- return request({
418
- method: "personal_sign",
419
- params: [message, address]
420
- });
421
- },
422
- [request]
423
- );
424
- const signTransaction = useCallback5(
425
- async (transaction) => {
426
- const chain = getEthereumChain();
427
- return chain.signTransaction(transaction);
428
- },
429
- [getEthereumChain]
430
- );
431
- const sendTransaction = useCallback5(
432
- async (transaction) => {
433
- const chain = getEthereumChain();
434
- return chain.sendTransaction(transaction);
435
- },
436
- [getEthereumChain]
437
- );
438
- const switchChain = useCallback5(
439
- async (chainId) => {
440
- const chain = getEthereumChain();
441
- return chain.switchChain(chainId);
442
- },
443
- [getEthereumChain]
444
- );
445
- const getChainId = useCallback5(async () => {
446
- const chain = getEthereumChain();
447
- return chain.getChainId();
448
- }, [getEthereumChain]);
449
- const getAccounts = useCallback5(async () => {
450
- const chain = getEthereumChain();
451
- return chain.getAccounts();
452
- }, [getEthereumChain]);
453
- const signMessage = useCallback5(
454
- async (message) => {
455
- return request({
456
- method: "eth_sign",
457
- params: [await getAccounts().then((accounts) => accounts[0]), message]
458
- });
459
- },
460
- [request, getAccounts]
461
- );
462
- const signTypedData = useCallback5(
463
- async (typedData) => {
464
- const accounts = await getAccounts();
465
- return request({
466
- method: "eth_signTypedData_v4",
467
- params: [accounts[0], JSON.stringify(typedData)]
468
- });
469
- },
470
- [request, getAccounts]
471
- );
365
+ const { sdk, isConnected, isClient } = usePhantom();
366
+ if (!isClient || !sdk) {
367
+ return {
368
+ ethereum: {},
369
+ // This will be replaced when SDK is ready
370
+ isAvailable: false
371
+ };
372
+ }
472
373
  return {
473
- // Chain instance for advanced usage
474
- ethereum: ethereumChain,
475
- // Standard EIP-1193 interface
476
- request,
477
- // Convenient methods
478
- signPersonalMessage,
479
- signMessage,
480
- signTransaction,
481
- signTypedData,
482
- sendTransaction,
483
- switchChain,
484
- getChainId,
485
- getAccounts,
374
+ // Chain instance with connection enforcement for signing methods
375
+ ethereum: sdk.ethereum,
486
376
  // State
487
- isAvailable: !!ethereumChain,
488
- isConnected: ethereumChain?.isConnected() ?? false
377
+ isAvailable: !!isConnected
489
378
  };
490
379
  }
491
380
 
@@ -503,6 +392,7 @@ export {
503
392
  useDisconnect,
504
393
  useEthereum,
505
394
  useIsExtensionInstalled,
395
+ useIsPhantomLoginAvailable,
506
396
  usePhantom,
507
397
  useSolana
508
398
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phantom/react-sdk",
3
- "version": "1.0.0-beta.2",
3
+ "version": "1.0.0-beta.21",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.mjs",
6
6
  "types": "dist/index.d.ts",
@@ -26,9 +26,9 @@
26
26
  "prettier": "prettier --write \"src/**/*.{ts,tsx}\""
27
27
  },
28
28
  "dependencies": {
29
- "@phantom/browser-sdk": "^1.0.0-beta.2",
30
- "@phantom/chains": "^1.0.0-beta.2",
31
- "@phantom/constants": "^1.0.0-beta.2"
29
+ "@phantom/browser-sdk": "^1.0.0-beta.21",
30
+ "@phantom/chain-interfaces": "^1.0.0-beta.9",
31
+ "@phantom/constants": "^1.0.0-beta.9"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@testing-library/dom": "^10.4.0",