@phantom/react-sdk 1.0.0-beta.1 → 1.0.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -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 />
@@ -181,26 +180,7 @@ Uses the Phantom browser extension installed by the user.
181
180
 
182
181
  Creates non-custodial wallets embedded in your application.
183
182
 
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)
183
+ #### User Wallet
204
184
 
205
185
  - **Uses Phantom authentication** - user logs in with existing account
206
186
  - **Potentially funded** - brings existing wallet balance
@@ -210,41 +190,14 @@ Creates non-custodial wallets embedded in your application.
210
190
  <PhantomProvider
211
191
  config={{
212
192
  providerType: "embedded",
213
- embeddedWalletType: "user-wallet",
193
+ appId: "your-app-id",
214
194
  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
195
  }}
234
196
  >
235
197
  <YourApp />
236
198
  </PhantomProvider>
237
199
  ```
238
200
 
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
201
 
249
202
  ## Available Hooks
250
203
 
@@ -392,7 +345,7 @@ function SolanaOperations() {
392
345
 
393
346
  // Sign and send
394
347
  const result = await solana.signAndSendTransaction(transaction);
395
- console.log("Transaction sent:", result.hash);
348
+ console.log("Transaction sent:", result.signature);
396
349
  };
397
350
 
398
351
  const switchNetwork = async () => {
@@ -470,6 +423,16 @@ function EthereumOperations() {
470
423
  console.log("Typed data signature:", signature);
471
424
  };
472
425
 
426
+ const signTransaction = async () => {
427
+ const signedTx = await ethereum.signTransaction({
428
+ to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
429
+ value: "1000000000000000000", // 1 ETH in wei
430
+ gas: "21000",
431
+ });
432
+ console.log("Transaction signed:", signedTx);
433
+ // Transaction is signed but not sent - you can broadcast it later
434
+ };
435
+
473
436
  const sendTransaction = async () => {
474
437
  const result = await ethereum.sendTransaction({
475
438
  to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
@@ -487,7 +450,8 @@ function EthereumOperations() {
487
450
  <div>
488
451
  <button onClick={signPersonalMessage}>Sign Personal Message</button>
489
452
  <button onClick={signTypedData}>Sign Typed Data</button>
490
- <button onClick={sendTransaction}>Send Transaction</button>
453
+ <button onClick={signTransaction}>Sign Transaction</button>
454
+ <button onClick={sendTransaction}>Sign & Send Transaction</button>
491
455
  <button onClick={switchChain}>Switch to Polygon</button>
492
456
  <p>Connected: {ethereum.isConnected ? "Yes" : "No"}</p>
493
457
  </div>
@@ -500,7 +464,8 @@ function EthereumOperations() {
500
464
  - `request(args)` - EIP-1193 requests
501
465
  - `signPersonalMessage(message, address)` - Sign personal message
502
466
  - `signTypedData(typedData)` - Sign EIP-712 typed data
503
- - `sendTransaction(transaction)` - Send transaction
467
+ - `signTransaction(transaction)` - Sign transaction without sending
468
+ - `sendTransaction(transaction)` - Sign and send transaction
504
469
  - `switchChain(chainId)` - Switch chains
505
470
  - `getChainId()` - Get current chain ID
506
471
  - `getAccounts()` - Get connected accounts
@@ -675,7 +640,7 @@ function SolanaExample() {
675
640
 
676
641
  // Sign and send using chain-specific hook
677
642
  const result = await solana.signAndSendTransaction(transaction);
678
- console.log("Transaction sent:", result.hash);
643
+ console.log("Transaction sent:", result.signature);
679
644
  };
680
645
 
681
646
  return <button onClick={sendTransaction}>Send SOL</button>;
@@ -714,7 +679,7 @@ function SolanaKitExample() {
714
679
 
715
680
  // Sign and send using chain-specific hook
716
681
  const result = await solana.signAndSendTransaction(transaction);
717
- console.log("Transaction sent:", result.hash);
682
+ console.log("Transaction sent:", result.signature);
718
683
  };
719
684
 
720
685
  return <button onClick={sendTransaction}>Send SOL</button>;
@@ -787,15 +752,16 @@ interface PhantomSDKConfig {
787
752
  addressTypes?: [AddressType, ...AddressType[]]; // Networks to enable (e.g., [AddressType.solana])
788
753
 
789
754
  // Required for embedded provider only
790
- apiBaseUrl?: string; // Phantom API base URL
791
- appId: string; // Your app ID
755
+ appId: string; // Your app ID from phantom.com/portal (required for embedded provider)
756
+
757
+ // Optional configuration
758
+ apiBaseUrl?: string; // Phantom API base URL (optional, has default)
792
759
  authOptions?: {
793
- authUrl?: string; // Custom auth URL (optional)
794
- redirectUrl?: string; // Custom redirect URL (optional)
760
+ authUrl?: string; // Custom auth URL (optional, defaults to "https://connect.phantom.app/login")
761
+ redirectUrl?: string; // Custom redirect URL after authentication (optional)
795
762
  };
796
- embeddedWalletType?: "app-wallet" | "user-wallet"; // Wallet type
797
- solanaProvider?: "web3js" | "kit"; // Solana library choice (default: 'web3js')
798
- autoConnect?: boolean; // Auto-connect to existing session on SDK instantiation (default: true for embedded, false for injected)
763
+ embeddedWalletType?: "user-wallet"; // Wallet type (optional, defaults to "user-wallet", currently the only supported type)
764
+ autoConnect?: boolean; // Auto-connect to existing session on SDK instantiation (optional, defaults to true for embedded, false for injected)
799
765
  }
800
766
  ```
801
767
 
@@ -827,6 +793,7 @@ function App() {
827
793
  // SDK configuration - static, won't change when debug settings change
828
794
  const config: PhantomSDKConfig = {
829
795
  providerType: "embedded",
796
+ appId: "your-app-id",
830
797
  // ... other config
831
798
  };
832
799
 
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ import { ReactNode } from 'react';
3
3
  import { BrowserSDKConfig, DebugConfig, AuthOptions, BrowserSDK, WalletAddress, AutoConfirmEnableParams, AutoConfirmResult, AutoConfirmSupportedChainsResult } from '@phantom/browser-sdk';
4
4
  export { AddressType, AutoConfirmEnableParams, AutoConfirmResult, AutoConfirmSupportedChainsResult, DebugLevel, DebugMessage, 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';
6
+ import * as _phantom_chains from '@phantom/chains';
7
7
  export { EthTransactionRequest, IEthereumChain, ISolanaChain } from '@phantom/chains';
8
8
 
9
9
  interface PhantomSDKConfig extends BrowserSDKConfig {
@@ -16,7 +16,7 @@ interface ConnectOptions {
16
16
  authOptions?: AuthOptions;
17
17
  }
18
18
  interface PhantomContextValue {
19
- sdk: BrowserSDK | null;
19
+ sdk: BrowserSDK;
20
20
  isConnected: boolean;
21
21
  isConnecting: boolean;
22
22
  connectError: Error | null;
@@ -72,50 +72,21 @@ declare function useAutoConfirm(): UseAutoConfirmResult;
72
72
  /**
73
73
  * Hook for Solana chain operations
74
74
  *
75
- * @returns Solana chain interface and convenient methods
75
+ * @returns Solana chain interface with connection enforcement
76
76
  */
77
77
  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>;
78
+ solana: _phantom_chains.ISolanaChain;
95
79
  isAvailable: boolean;
96
- isConnected: boolean;
97
80
  };
98
81
 
99
82
  /**
100
83
  * Hook for Ethereum chain operations
101
84
  *
102
- * @returns Ethereum chain interface and convenient methods
85
+ * @returns Ethereum chain interface with connection enforcement
103
86
  */
104
87
  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
- signTypedData: (typedData: any) => Promise<string>;
113
- sendTransaction: (transaction: EthTransactionRequest) => Promise<string>;
114
- switchChain: (chainId: number) => Promise<void>;
115
- getChainId: () => Promise<number>;
116
- getAccounts: () => Promise<string[]>;
88
+ ethereum: _phantom_chains.IEthereumChain;
117
89
  isAvailable: boolean;
118
- isConnected: boolean;
119
90
  };
120
91
 
121
92
  type ProviderType = "injected" | "embedded";
package/dist/index.js CHANGED
@@ -68,9 +68,8 @@ function PhantomProvider({ children, config, debugConfig }) {
68
68
  memoizedConfig.providerType || null
69
69
  );
70
70
  const [isPhantomAvailable, setIsPhantomAvailable] = (0, import_react.useState)(false);
71
- const [sdk, setSdk] = (0, import_react.useState)(null);
71
+ const sdk = (0, import_react.useMemo)(() => new import_browser_sdk.BrowserSDK(memoizedConfig), [memoizedConfig]);
72
72
  (0, import_react.useEffect)(() => {
73
- const sdkInstance = new import_browser_sdk.BrowserSDK(memoizedConfig);
74
73
  const handleConnectStart = () => {
75
74
  setIsConnecting(true);
76
75
  setConnectError(null);
@@ -79,15 +78,15 @@ function PhantomProvider({ children, config, debugConfig }) {
79
78
  try {
80
79
  setIsConnected(true);
81
80
  setIsConnecting(false);
82
- const providerInfo = sdkInstance.getCurrentProviderInfo();
81
+ const providerInfo = sdk.getCurrentProviderInfo();
83
82
  setCurrentProviderType(providerInfo?.type || null);
84
- const addrs = await sdkInstance.getAddresses();
83
+ const addrs = await sdk.getAddresses();
85
84
  setAddresses(addrs);
86
- setWalletId(sdkInstance.getWalletId());
85
+ setWalletId(sdk.getWalletId());
87
86
  } catch (err) {
88
87
  console.error("Error connecting:", err);
89
88
  try {
90
- await sdkInstance.disconnect();
89
+ await sdk.disconnect();
91
90
  } catch (err2) {
92
91
  console.error("Error disconnecting:", err2);
93
92
  }
@@ -105,18 +104,17 @@ function PhantomProvider({ children, config, debugConfig }) {
105
104
  setAddresses([]);
106
105
  setWalletId(null);
107
106
  };
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);
107
+ sdk.on("connect_start", handleConnectStart);
108
+ sdk.on("connect", handleConnect);
109
+ sdk.on("connect_error", handleConnectError);
110
+ sdk.on("disconnect", handleDisconnect);
113
111
  return () => {
114
- sdkInstance.off("connect_start", handleConnectStart);
115
- sdkInstance.off("connect", handleConnect);
116
- sdkInstance.off("connect_error", handleConnectError);
117
- sdkInstance.off("disconnect", handleDisconnect);
112
+ sdk.off("connect_start", handleConnectStart);
113
+ sdk.off("connect", handleConnect);
114
+ sdk.off("connect_error", handleConnectError);
115
+ sdk.off("disconnect", handleDisconnect);
118
116
  };
119
- }, [memoizedConfig]);
117
+ }, [sdk]);
120
118
  (0, import_react.useEffect)(() => {
121
119
  if (!sdk || !debugConfig)
122
120
  return;
@@ -353,176 +351,24 @@ function useAutoConfirm() {
353
351
  }
354
352
 
355
353
  // src/hooks/useSolana.ts
356
- var import_react5 = require("react");
357
354
  function useSolana() {
358
355
  const { sdk, isConnected } = usePhantom();
359
- const solanaChain = (0, import_react5.useMemo)(() => {
360
- if (!sdk || !isConnected)
361
- return null;
362
- try {
363
- return sdk.solana;
364
- } catch {
365
- return null;
366
- }
367
- }, [sdk, isConnected]);
368
- const signMessage = (0, import_react5.useCallback)(
369
- async (message) => {
370
- if (!solanaChain)
371
- throw new Error("Solana chain not available. Ensure SDK is connected.");
372
- return solanaChain.signMessage(message);
373
- },
374
- [solanaChain]
375
- );
376
- const signTransaction = (0, import_react5.useCallback)(
377
- async (transaction) => {
378
- if (!solanaChain)
379
- throw new Error("Solana chain not available. Ensure SDK is connected.");
380
- return solanaChain.signTransaction(transaction);
381
- },
382
- [solanaChain]
383
- );
384
- const signAndSendTransaction = (0, import_react5.useCallback)(
385
- async (transaction) => {
386
- if (!solanaChain)
387
- throw new Error("Solana chain not available. Ensure SDK is connected.");
388
- return solanaChain.signAndSendTransaction(transaction);
389
- },
390
- [solanaChain]
391
- );
392
- const connect = (0, import_react5.useCallback)(
393
- async (options) => {
394
- if (!solanaChain)
395
- throw new Error("Solana chain not available. Ensure SDK is connected.");
396
- return solanaChain.connect(options);
397
- },
398
- [solanaChain]
399
- );
400
- const disconnect = (0, import_react5.useCallback)(async () => {
401
- if (!solanaChain)
402
- throw new Error("Solana chain not available. Ensure SDK is connected.");
403
- return solanaChain.disconnect();
404
- }, [solanaChain]);
405
- const switchNetwork = (0, import_react5.useCallback)(
406
- async (network) => {
407
- if (!solanaChain)
408
- throw new Error("Solana chain not available. Ensure SDK is connected.");
409
- return solanaChain.switchNetwork?.(network);
410
- },
411
- [solanaChain]
412
- );
413
- const getPublicKey = (0, import_react5.useCallback)(async () => {
414
- if (!solanaChain)
415
- return null;
416
- return solanaChain.getPublicKey();
417
- }, [solanaChain]);
418
356
  return {
419
- // Chain instance for advanced usage
420
- solana: solanaChain,
421
- // Convenient methods
422
- signMessage,
423
- signTransaction,
424
- signAndSendTransaction,
425
- connect,
426
- disconnect,
427
- switchNetwork,
428
- getPublicKey,
357
+ // Chain instance with connection enforcement for signing methods
358
+ solana: sdk.solana,
429
359
  // State
430
- isAvailable: !!solanaChain,
431
- isConnected: solanaChain?.isConnected() ?? false
360
+ isAvailable: !!isConnected
432
361
  };
433
362
  }
434
363
 
435
364
  // src/hooks/useEthereum.ts
436
- var import_react6 = require("react");
437
365
  function useEthereum() {
438
366
  const { sdk, isConnected } = usePhantom();
439
- const ethereumChain = (0, import_react6.useMemo)(() => {
440
- if (!sdk || !isConnected)
441
- return null;
442
- try {
443
- return sdk.ethereum;
444
- } catch {
445
- return null;
446
- }
447
- }, [sdk, isConnected]);
448
- const request = (0, import_react6.useCallback)(
449
- async (args) => {
450
- if (!ethereumChain)
451
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
452
- return ethereumChain.request(args);
453
- },
454
- [ethereumChain]
455
- );
456
- const signPersonalMessage = (0, import_react6.useCallback)(
457
- async (message, address) => {
458
- return request({
459
- method: "personal_sign",
460
- params: [message, address]
461
- });
462
- },
463
- [request]
464
- );
465
- const sendTransaction = (0, import_react6.useCallback)(
466
- async (transaction) => {
467
- if (!ethereumChain)
468
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
469
- return ethereumChain.sendTransaction(transaction);
470
- },
471
- [ethereumChain]
472
- );
473
- const switchChain = (0, import_react6.useCallback)(
474
- async (chainId) => {
475
- if (!ethereumChain)
476
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
477
- return ethereumChain.switchChain(chainId);
478
- },
479
- [ethereumChain]
480
- );
481
- const getChainId = (0, import_react6.useCallback)(async () => {
482
- if (!ethereumChain)
483
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
484
- return ethereumChain.getChainId();
485
- }, [ethereumChain]);
486
- const getAccounts = (0, import_react6.useCallback)(async () => {
487
- if (!ethereumChain)
488
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
489
- return ethereumChain.getAccounts();
490
- }, [ethereumChain]);
491
- const signMessage = (0, import_react6.useCallback)(
492
- async (message) => {
493
- return request({
494
- method: "eth_sign",
495
- params: [await getAccounts().then((accounts) => accounts[0]), message]
496
- });
497
- },
498
- [request, getAccounts]
499
- );
500
- const signTypedData = (0, import_react6.useCallback)(
501
- async (typedData) => {
502
- const accounts = await getAccounts();
503
- return request({
504
- method: "eth_signTypedData_v4",
505
- params: [accounts[0], JSON.stringify(typedData)]
506
- });
507
- },
508
- [request, getAccounts]
509
- );
510
367
  return {
511
- // Chain instance for advanced usage
512
- ethereum: ethereumChain,
513
- // Standard EIP-1193 interface
514
- request,
515
- // Convenient methods
516
- signPersonalMessage,
517
- signMessage,
518
- signTypedData,
519
- sendTransaction,
520
- switchChain,
521
- getChainId,
522
- getAccounts,
368
+ // Chain instance with connection enforcement for signing methods
369
+ ethereum: sdk.ethereum,
523
370
  // State
524
- isAvailable: !!ethereumChain,
525
- isConnected: ethereumChain?.isConnected() ?? false
371
+ isAvailable: !!isConnected
526
372
  };
527
373
  }
528
374
 
package/dist/index.mjs CHANGED
@@ -20,9 +20,8 @@ function PhantomProvider({ children, config, debugConfig }) {
20
20
  memoizedConfig.providerType || null
21
21
  );
22
22
  const [isPhantomAvailable, setIsPhantomAvailable] = useState(false);
23
- const [sdk, setSdk] = useState(null);
23
+ const sdk = useMemo(() => new BrowserSDK(memoizedConfig), [memoizedConfig]);
24
24
  useEffect(() => {
25
- const sdkInstance = new BrowserSDK(memoizedConfig);
26
25
  const handleConnectStart = () => {
27
26
  setIsConnecting(true);
28
27
  setConnectError(null);
@@ -31,15 +30,15 @@ function PhantomProvider({ children, config, debugConfig }) {
31
30
  try {
32
31
  setIsConnected(true);
33
32
  setIsConnecting(false);
34
- const providerInfo = sdkInstance.getCurrentProviderInfo();
33
+ const providerInfo = sdk.getCurrentProviderInfo();
35
34
  setCurrentProviderType(providerInfo?.type || null);
36
- const addrs = await sdkInstance.getAddresses();
35
+ const addrs = await sdk.getAddresses();
37
36
  setAddresses(addrs);
38
- setWalletId(sdkInstance.getWalletId());
37
+ setWalletId(sdk.getWalletId());
39
38
  } catch (err) {
40
39
  console.error("Error connecting:", err);
41
40
  try {
42
- await sdkInstance.disconnect();
41
+ await sdk.disconnect();
43
42
  } catch (err2) {
44
43
  console.error("Error disconnecting:", err2);
45
44
  }
@@ -57,18 +56,17 @@ function PhantomProvider({ children, config, debugConfig }) {
57
56
  setAddresses([]);
58
57
  setWalletId(null);
59
58
  };
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);
59
+ sdk.on("connect_start", handleConnectStart);
60
+ sdk.on("connect", handleConnect);
61
+ sdk.on("connect_error", handleConnectError);
62
+ sdk.on("disconnect", handleDisconnect);
65
63
  return () => {
66
- sdkInstance.off("connect_start", handleConnectStart);
67
- sdkInstance.off("connect", handleConnect);
68
- sdkInstance.off("connect_error", handleConnectError);
69
- sdkInstance.off("disconnect", handleDisconnect);
64
+ sdk.off("connect_start", handleConnectStart);
65
+ sdk.off("connect", handleConnect);
66
+ sdk.off("connect_error", handleConnectError);
67
+ sdk.off("disconnect", handleDisconnect);
70
68
  };
71
- }, [memoizedConfig]);
69
+ }, [sdk]);
72
70
  useEffect(() => {
73
71
  if (!sdk || !debugConfig)
74
72
  return;
@@ -305,176 +303,24 @@ function useAutoConfirm() {
305
303
  }
306
304
 
307
305
  // src/hooks/useSolana.ts
308
- import { useCallback as useCallback4, useMemo as useMemo2 } from "react";
309
306
  function useSolana() {
310
307
  const { sdk, isConnected } = usePhantom();
311
- const solanaChain = useMemo2(() => {
312
- if (!sdk || !isConnected)
313
- return null;
314
- try {
315
- return sdk.solana;
316
- } catch {
317
- return null;
318
- }
319
- }, [sdk, isConnected]);
320
- const signMessage = useCallback4(
321
- async (message) => {
322
- if (!solanaChain)
323
- throw new Error("Solana chain not available. Ensure SDK is connected.");
324
- return solanaChain.signMessage(message);
325
- },
326
- [solanaChain]
327
- );
328
- const signTransaction = useCallback4(
329
- async (transaction) => {
330
- if (!solanaChain)
331
- throw new Error("Solana chain not available. Ensure SDK is connected.");
332
- return solanaChain.signTransaction(transaction);
333
- },
334
- [solanaChain]
335
- );
336
- const signAndSendTransaction = useCallback4(
337
- async (transaction) => {
338
- if (!solanaChain)
339
- throw new Error("Solana chain not available. Ensure SDK is connected.");
340
- return solanaChain.signAndSendTransaction(transaction);
341
- },
342
- [solanaChain]
343
- );
344
- const connect = useCallback4(
345
- async (options) => {
346
- if (!solanaChain)
347
- throw new Error("Solana chain not available. Ensure SDK is connected.");
348
- return solanaChain.connect(options);
349
- },
350
- [solanaChain]
351
- );
352
- const disconnect = useCallback4(async () => {
353
- if (!solanaChain)
354
- throw new Error("Solana chain not available. Ensure SDK is connected.");
355
- return solanaChain.disconnect();
356
- }, [solanaChain]);
357
- const switchNetwork = useCallback4(
358
- async (network) => {
359
- if (!solanaChain)
360
- throw new Error("Solana chain not available. Ensure SDK is connected.");
361
- return solanaChain.switchNetwork?.(network);
362
- },
363
- [solanaChain]
364
- );
365
- const getPublicKey = useCallback4(async () => {
366
- if (!solanaChain)
367
- return null;
368
- return solanaChain.getPublicKey();
369
- }, [solanaChain]);
370
308
  return {
371
- // Chain instance for advanced usage
372
- solana: solanaChain,
373
- // Convenient methods
374
- signMessage,
375
- signTransaction,
376
- signAndSendTransaction,
377
- connect,
378
- disconnect,
379
- switchNetwork,
380
- getPublicKey,
309
+ // Chain instance with connection enforcement for signing methods
310
+ solana: sdk.solana,
381
311
  // State
382
- isAvailable: !!solanaChain,
383
- isConnected: solanaChain?.isConnected() ?? false
312
+ isAvailable: !!isConnected
384
313
  };
385
314
  }
386
315
 
387
316
  // src/hooks/useEthereum.ts
388
- import { useCallback as useCallback5, useMemo as useMemo3 } from "react";
389
317
  function useEthereum() {
390
318
  const { sdk, isConnected } = usePhantom();
391
- const ethereumChain = useMemo3(() => {
392
- if (!sdk || !isConnected)
393
- return null;
394
- try {
395
- return sdk.ethereum;
396
- } catch {
397
- return null;
398
- }
399
- }, [sdk, isConnected]);
400
- const request = useCallback5(
401
- async (args) => {
402
- if (!ethereumChain)
403
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
404
- return ethereumChain.request(args);
405
- },
406
- [ethereumChain]
407
- );
408
- const signPersonalMessage = useCallback5(
409
- async (message, address) => {
410
- return request({
411
- method: "personal_sign",
412
- params: [message, address]
413
- });
414
- },
415
- [request]
416
- );
417
- const sendTransaction = useCallback5(
418
- async (transaction) => {
419
- if (!ethereumChain)
420
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
421
- return ethereumChain.sendTransaction(transaction);
422
- },
423
- [ethereumChain]
424
- );
425
- const switchChain = useCallback5(
426
- async (chainId) => {
427
- if (!ethereumChain)
428
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
429
- return ethereumChain.switchChain(chainId);
430
- },
431
- [ethereumChain]
432
- );
433
- const getChainId = useCallback5(async () => {
434
- if (!ethereumChain)
435
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
436
- return ethereumChain.getChainId();
437
- }, [ethereumChain]);
438
- const getAccounts = useCallback5(async () => {
439
- if (!ethereumChain)
440
- throw new Error("Ethereum chain not available. Ensure SDK is connected.");
441
- return ethereumChain.getAccounts();
442
- }, [ethereumChain]);
443
- const signMessage = useCallback5(
444
- async (message) => {
445
- return request({
446
- method: "eth_sign",
447
- params: [await getAccounts().then((accounts) => accounts[0]), message]
448
- });
449
- },
450
- [request, getAccounts]
451
- );
452
- const signTypedData = useCallback5(
453
- async (typedData) => {
454
- const accounts = await getAccounts();
455
- return request({
456
- method: "eth_signTypedData_v4",
457
- params: [accounts[0], JSON.stringify(typedData)]
458
- });
459
- },
460
- [request, getAccounts]
461
- );
462
319
  return {
463
- // Chain instance for advanced usage
464
- ethereum: ethereumChain,
465
- // Standard EIP-1193 interface
466
- request,
467
- // Convenient methods
468
- signPersonalMessage,
469
- signMessage,
470
- signTypedData,
471
- sendTransaction,
472
- switchChain,
473
- getChainId,
474
- getAccounts,
320
+ // Chain instance with connection enforcement for signing methods
321
+ ethereum: sdk.ethereum,
475
322
  // State
476
- isAvailable: !!ethereumChain,
477
- isConnected: ethereumChain?.isConnected() ?? false
323
+ isAvailable: !!isConnected
478
324
  };
479
325
  }
480
326
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phantom/react-sdk",
3
- "version": "1.0.0-beta.1",
3
+ "version": "1.0.0-beta.3",
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.1",
30
- "@phantom/chains": "^1.0.0-beta.1",
31
- "@phantom/constants": "^1.0.0-beta.1"
29
+ "@phantom/browser-sdk": "^1.0.0-beta.3",
30
+ "@phantom/chains": "^1.0.0-beta.3",
31
+ "@phantom/constants": "^1.0.0-beta.3"
32
32
  },
33
33
  "devDependencies": {
34
34
  "@testing-library/dom": "^10.4.0",