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

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
@@ -1,6 +1,6 @@
1
1
  # @phantom/react-sdk
2
2
 
3
- React hooks for integrating Phantom wallet functionality into React applications with native transaction support.
3
+ React hooks for integrating Phantom wallet functionality into React applications with chain-specific operations.
4
4
 
5
5
  ## Installation
6
6
 
@@ -16,8 +16,6 @@ Install additional dependencies based on the networks you want to support:
16
16
  | --------------- | ---------------------------------- |
17
17
  | Solana | `@solana/web3.js` OR `@solana/kit` |
18
18
  | Ethereum/EVM | `viem` |
19
- | Bitcoin | `bitcoinjs-lib` |
20
- | Sui | `@mysten/sui.js` |
21
19
 
22
20
  **Example for Solana + Ethereum support (using @solana/web3.js):**
23
21
 
@@ -31,34 +29,65 @@ npm install @phantom/react-sdk @solana/web3.js viem
31
29
  npm install @phantom/react-sdk @solana/kit viem
32
30
  ```
33
31
 
34
- For complete dependency information and bundle optimization tips, see the [@phantom/browser-sdk documentation](../browser-sdk/README.md#bundle-optimization-tips).
35
-
36
32
  ## Quick Start
37
33
 
38
- ### Basic Setup
34
+ ### Basic Setup with Chain-Specific Operations
39
35
 
40
36
  ```tsx
41
- import { PhantomProvider } from "@phantom/react-sdk";
42
- import { AddressType } from "@phantom/client";
37
+ import { PhantomProvider, useConnect, useSolana, useEthereum } from "@phantom/react-sdk";
38
+ import { AddressType } from "@phantom/browser-sdk";
43
39
 
44
40
  function App() {
45
41
  return (
46
42
  <PhantomProvider
47
43
  config={{
48
44
  providerType: "injected", // Uses Phantom browser extension
45
+ addressTypes: [AddressType.solana, AddressType.ethereum],
49
46
  }}
50
47
  >
51
- <YourApp />
48
+ <WalletComponent />
52
49
  </PhantomProvider>
53
50
  );
54
51
  }
52
+
53
+ function WalletComponent() {
54
+ const { connect, isConnecting } = useConnect();
55
+ const solana = useSolana();
56
+ const ethereum = useEthereum();
57
+
58
+ const handleConnect = async () => {
59
+ const { addresses } = await connect();
60
+ console.log("Connected addresses:", addresses);
61
+ };
62
+
63
+ const signSolanaMessage = async () => {
64
+ const signature = await solana.signMessage("Hello Solana!");
65
+ console.log("Solana signature:", signature);
66
+ };
67
+
68
+ const signEthereumMessage = async () => {
69
+ const accounts = await ethereum.getAccounts();
70
+ const signature = await ethereum.signPersonalMessage("Hello Ethereum!", accounts[0]);
71
+ console.log("Ethereum signature:", signature);
72
+ };
73
+
74
+ return (
75
+ <div>
76
+ <button onClick={handleConnect} disabled={isConnecting}>
77
+ {isConnecting ? "Connecting..." : "Connect Wallet"}
78
+ </button>
79
+ <button onClick={signSolanaMessage}>Sign Solana Message</button>
80
+ <button onClick={signEthereumMessage}>Sign Ethereum Message</button>
81
+ </div>
82
+ );
83
+ }
55
84
  ```
56
85
 
57
86
  ### Embedded Wallet Setup
58
87
 
59
88
  ```tsx
60
89
  import { PhantomProvider } from "@phantom/react-sdk";
61
- import { AddressType } from "@phantom/client";
90
+ import { AddressType } from "@phantom/browser-sdk";
62
91
 
63
92
  function App() {
64
93
  return (
@@ -68,7 +97,6 @@ function App() {
68
97
  embeddedWalletType: "app-wallet", // or 'user-wallet'
69
98
  addressTypes: [AddressType.solana, AddressType.ethereum],
70
99
  apiBaseUrl: "https://api.phantom.app/v1/wallets",
71
- organizationId: "your-org-id",
72
100
  }}
73
101
  >
74
102
  <YourApp />
@@ -77,6 +105,61 @@ function App() {
77
105
  }
78
106
  ```
79
107
 
108
+ ## Connection Flow
109
+
110
+ The React SDK follows a clear connection pattern:
111
+
112
+ 1. **Provider Setup**: Wrap your app with `PhantomProvider`
113
+ 2. **Connection**: Use `useConnect()` to establish wallet connection
114
+ 3. **Chain Operations**: Use chain-specific hooks (`useSolana()`, `useEthereum()`) for transactions and signing
115
+
116
+ ```tsx
117
+ function WalletExample() {
118
+ const { connect } = useConnect();
119
+ const solana = useSolana();
120
+ const ethereum = useEthereum();
121
+
122
+ // 1. Connect first
123
+ const handleConnect = async () => {
124
+ await connect();
125
+ };
126
+
127
+ // 2. Then use chain-specific operations
128
+ const sendSolanaTransaction = async () => {
129
+ const result = await solana.signAndSendTransaction(transaction);
130
+ };
131
+
132
+ const sendEthereumTransaction = async () => {
133
+ const result = await ethereum.sendTransaction(transaction);
134
+ };
135
+ }
136
+ ```
137
+
138
+ ### Connection Options
139
+
140
+ For embedded user-wallets, you can specify authentication providers:
141
+
142
+ ```tsx
143
+ const { connect } = useConnect();
144
+
145
+ // Default: Show provider selection screen
146
+ await connect();
147
+
148
+ // Google authentication (skips provider selection)
149
+ await connect({
150
+ authOptions: {
151
+ provider: "google",
152
+ },
153
+ });
154
+
155
+ // Apple authentication (skips provider selection)
156
+ await connect({
157
+ authOptions: {
158
+ provider: "apple",
159
+ },
160
+ });
161
+ ```
162
+
80
163
  ## Provider Types
81
164
 
82
165
  ### Injected Provider
@@ -87,6 +170,7 @@ Uses the Phantom browser extension installed by the user.
87
170
  <PhantomProvider
88
171
  config={{
89
172
  providerType: "injected",
173
+ addressTypes: [AddressType.solana, AddressType.ethereum],
90
174
  }}
91
175
  >
92
176
  <YourApp />
@@ -110,7 +194,6 @@ Creates non-custodial wallets embedded in your application.
110
194
  embeddedWalletType: "app-wallet",
111
195
  addressTypes: [AddressType.solana],
112
196
  apiBaseUrl: "https://api.phantom.app/v1/wallets",
113
- organizationId: "your-org-id",
114
197
  }}
115
198
  >
116
199
  <YourApp />
@@ -130,7 +213,6 @@ Creates non-custodial wallets embedded in your application.
130
213
  embeddedWalletType: "user-wallet",
131
214
  addressTypes: [AddressType.solana, AddressType.ethereum],
132
215
  apiBaseUrl: "https://api.phantom.app/v1/wallets",
133
- organizationId: "your-org-id",
134
216
  }}
135
217
  >
136
218
  <YourApp />
@@ -148,7 +230,6 @@ When using `AddressType.solana`, you can choose between two Solana libraries:
148
230
  addressTypes: [AddressType.solana],
149
231
  solanaProvider: "web3js", // or 'kit'
150
232
  apiBaseUrl: "https://api.phantom.app/v1/wallets",
151
- organizationId: "your-org-id",
152
233
  }}
153
234
  >
154
235
  <YourApp />
@@ -167,7 +248,9 @@ When using `AddressType.solana`, you can choose between two Solana libraries:
167
248
 
168
249
  ## Available Hooks
169
250
 
170
- ### useConnect
251
+ ### Core Connection Hooks
252
+
253
+ #### useConnect
171
254
 
172
255
  Connect to wallet:
173
256
 
@@ -175,7 +258,7 @@ Connect to wallet:
175
258
  import { useConnect } from "@phantom/react-sdk";
176
259
 
177
260
  function ConnectButton() {
178
- const { connect, isLoading, error } = useConnect();
261
+ const { connect, isConnecting, error } = useConnect();
179
262
 
180
263
  const handleConnect = async () => {
181
264
  try {
@@ -187,14 +270,14 @@ function ConnectButton() {
187
270
  };
188
271
 
189
272
  return (
190
- <button onClick={handleConnect} disabled={isLoading}>
191
- {isLoading ? "Connecting..." : "Connect Wallet"}
273
+ <button onClick={handleConnect} disabled={isConnecting}>
274
+ {isConnecting ? "Connecting..." : "Connect Wallet"}
192
275
  </button>
193
276
  );
194
277
  }
195
278
  ```
196
279
 
197
- ### useAccounts
280
+ #### useAccounts
198
281
 
199
282
  Get connected wallet addresses:
200
283
 
@@ -220,7 +303,25 @@ function WalletAddresses() {
220
303
  }
221
304
  ```
222
305
 
223
- ### useIsExtensionInstalled
306
+ #### useDisconnect
307
+
308
+ Disconnect from wallet:
309
+
310
+ ```tsx
311
+ import { useDisconnect } from "@phantom/react-sdk";
312
+
313
+ function DisconnectButton() {
314
+ const { disconnect, isDisconnecting } = useDisconnect();
315
+
316
+ return (
317
+ <button onClick={disconnect} disabled={isDisconnecting}>
318
+ {isDisconnecting ? "Disconnecting..." : "Disconnect"}
319
+ </button>
320
+ );
321
+ }
322
+ ```
323
+
324
+ #### useIsExtensionInstalled
224
325
 
225
326
  Check if the Phantom browser extension is installed (for injected provider):
226
327
 
@@ -251,197 +352,293 @@ function ExtensionStatus() {
251
352
  }
252
353
  ```
253
354
 
254
- **Features:**
255
-
256
- - **Session-based caching**: Result is cached during the browser session to avoid redundant checks
257
- - **Automatic detection**: Runs automatically when the hook is first used
258
- - **Loading states**: Provides `isLoading` during the initial check
259
- - **Performance optimized**: Subsequent calls return cached result instantly
355
+ ### Chain-Specific Hooks
260
356
 
261
- **Use cases:**
357
+ #### useSolana
262
358
 
263
- - Show installation prompts for users without the extension
264
- - Conditionally render UI based on extension availability
265
- - Provide fallback options when extension is not installed
266
-
267
- ### useDisconnect
268
-
269
- Disconnect from wallet:
359
+ Hook for Solana chain operations:
270
360
 
271
361
  ```tsx
272
- import { useDisconnect } from "@phantom/react-sdk";
362
+ import { useSolana } from "@phantom/react-sdk";
363
+ import { VersionedTransaction, TransactionMessage, SystemProgram, PublicKey, Connection } from "@solana/web3.js";
273
364
 
274
- function DisconnectButton() {
275
- const { disconnect, isLoading } = useDisconnect();
365
+ function SolanaOperations() {
366
+ const solana = useSolana();
276
367
 
277
- return (
278
- <button onClick={disconnect} disabled={isLoading}>
279
- {isLoading ? "Disconnecting..." : "Disconnect"}
280
- </button>
281
- );
282
- }
283
- ```
368
+ const signMessage = async () => {
369
+ const signature = await solana.signMessage("Hello Solana!");
370
+ console.log("Signature:", signature);
371
+ };
284
372
 
285
- ### useSignMessage
373
+ const signAndSendTransaction = async () => {
374
+ // Create transaction
375
+ const connection = new Connection("https://api.mainnet-beta.solana.com");
376
+ const { blockhash } = await connection.getLatestBlockhash();
286
377
 
287
- Sign messages with native string input:
378
+ const fromAddress = await solana.getPublicKey();
379
+ const transferInstruction = SystemProgram.transfer({
380
+ fromPubkey: new PublicKey(fromAddress),
381
+ toPubkey: new PublicKey(toAddress),
382
+ lamports: 1000000, // 0.001 SOL
383
+ });
288
384
 
289
- ```tsx
290
- import { useSignMessage, NetworkId } from "@phantom/react-sdk";
385
+ const messageV0 = new TransactionMessage({
386
+ payerKey: new PublicKey(fromAddress),
387
+ recentBlockhash: blockhash,
388
+ instructions: [transferInstruction],
389
+ }).compileToV0Message();
291
390
 
292
- function SignMessage() {
293
- const { signMessage, isLoading, error } = useSignMessage();
391
+ const transaction = new VersionedTransaction(messageV0);
294
392
 
295
- const handleSign = async () => {
296
- try {
297
- const signature = await signMessage({
298
- message: "Hello from Phantom!",
299
- networkId: NetworkId.SOLANA_MAINNET,
300
- });
301
- console.log("Signature:", signature);
302
- } catch (err) {
303
- console.error("Failed to sign:", err);
304
- }
393
+ // Sign and send
394
+ const result = await solana.signAndSendTransaction(transaction);
395
+ console.log("Transaction sent:", result.hash);
396
+ };
397
+
398
+ const switchNetwork = async () => {
399
+ await solana.switchNetwork("devnet");
305
400
  };
306
401
 
307
402
  return (
308
- <button onClick={handleSign} disabled={isLoading}>
309
- {isLoading ? "Signing..." : "Sign Message"}
310
- </button>
403
+ <div>
404
+ <button onClick={signMessage}>Sign Message</button>
405
+ <button onClick={signAndSendTransaction}>Send Transaction</button>
406
+ <button onClick={switchNetwork}>Switch to Devnet</button>
407
+ <p>Connected: {solana.isConnected ? "Yes" : "No"}</p>
408
+ </div>
311
409
  );
312
410
  }
313
411
  ```
314
412
 
315
- ### useSignAndSendTransaction
413
+ **Available methods:**
414
+
415
+ - `signMessage(message)` - Sign a message
416
+ - `signTransaction(transaction)` - Sign without sending
417
+ - `signAndSendTransaction(transaction)` - Sign and send
418
+ - `switchNetwork(network)` - Switch between mainnet/devnet
419
+ - `getPublicKey()` - Get current public key
420
+ - `isConnected` - Connection status
421
+ - `isAvailable` - Provider availability
316
422
 
317
- #### Solana Transaction
423
+ #### useEthereum
424
+
425
+ Hook for Ethereum chain operations:
318
426
 
319
427
  ```tsx
320
- import { useSignAndSendTransaction, NetworkId } from "@phantom/react-sdk";
321
- import {
322
- VersionedTransaction,
323
- TransactionMessage,
324
- SystemProgram,
325
- PublicKey,
326
- LAMPORTS_PER_SOL,
327
- Connection,
328
- } from "@solana/web3.js";
329
-
330
- function SendSolanaTransaction() {
331
- const { signAndSendTransaction, isLoading, error } = useSignAndSendTransaction();
332
-
333
- const handleSend = async () => {
334
- // Get recent blockhash
335
- const connection = new Connection("https://api.mainnet-beta.solana.com");
336
- const { blockhash } = await connection.getLatestBlockhash();
428
+ import { useEthereum } from "@phantom/react-sdk";
337
429
 
338
- // Create transfer instruction
339
- const transferInstruction = SystemProgram.transfer({
340
- fromPubkey: new PublicKey(fromAddress),
341
- toPubkey: new PublicKey(toAddress),
342
- lamports: 0.001 * LAMPORTS_PER_SOL,
343
- });
430
+ function EthereumOperations() {
431
+ const ethereum = useEthereum();
344
432
 
345
- // Create VersionedTransaction
346
- const messageV0 = new TransactionMessage({
347
- payerKey: new PublicKey(fromAddress),
348
- recentBlockhash: blockhash,
349
- instructions: [transferInstruction],
350
- }).compileToV0Message();
433
+ const signPersonalMessage = async () => {
434
+ const accounts = await ethereum.getAccounts();
435
+ const signature = await ethereum.signPersonalMessage("Hello Ethereum!", accounts[0]);
436
+ console.log("Signature:", signature);
437
+ };
351
438
 
352
- const transaction = new VersionedTransaction(messageV0);
439
+ const signTypedData = async () => {
440
+ const accounts = await ethereum.getAccounts();
441
+ const typedData = {
442
+ types: {
443
+ EIP712Domain: [
444
+ { name: "name", type: "string" },
445
+ { name: "version", type: "string" },
446
+ { name: "chainId", type: "uint256" },
447
+ { name: "verifyingContract", type: "address" },
448
+ ],
449
+ Mail: [
450
+ { name: "from", type: "string" },
451
+ { name: "to", type: "string" },
452
+ { name: "contents", type: "string" },
453
+ ],
454
+ },
455
+ primaryType: "Mail",
456
+ domain: {
457
+ name: "Ether Mail",
458
+ version: "1",
459
+ chainId: 1,
460
+ verifyingContract: "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC",
461
+ },
462
+ message: {
463
+ from: "Alice",
464
+ to: "Bob",
465
+ contents: "Hello!",
466
+ },
467
+ };
353
468
 
354
- try {
355
- const result = await signAndSendTransaction({
356
- networkId: NetworkId.SOLANA_MAINNET,
357
- transaction: transaction, // Native VersionedTransaction object!
358
- });
359
- console.log("Transaction sent:", result.rawTransaction);
360
- } catch (err) {
361
- console.error("Failed to send:", err);
362
- }
469
+ const signature = await ethereum.signTypedData(typedData);
470
+ console.log("Typed data signature:", signature);
471
+ };
472
+
473
+ const sendTransaction = async () => {
474
+ const result = await ethereum.sendTransaction({
475
+ to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
476
+ value: "1000000000000000000", // 1 ETH in wei
477
+ gas: "21000",
478
+ });
479
+ console.log("Transaction sent:", result.hash);
480
+ };
481
+
482
+ const switchChain = async () => {
483
+ await ethereum.switchChain(137); // Switch to Polygon
363
484
  };
364
485
 
365
486
  return (
366
- <button onClick={handleSend} disabled={isLoading}>
367
- {isLoading ? "Sending..." : "Send SOL"}
368
- </button>
487
+ <div>
488
+ <button onClick={signPersonalMessage}>Sign Personal Message</button>
489
+ <button onClick={signTypedData}>Sign Typed Data</button>
490
+ <button onClick={sendTransaction}>Send Transaction</button>
491
+ <button onClick={switchChain}>Switch to Polygon</button>
492
+ <p>Connected: {ethereum.isConnected ? "Yes" : "No"}</p>
493
+ </div>
369
494
  );
370
495
  }
371
496
  ```
372
497
 
373
- #### Ethereum Transaction (with Viem)
498
+ **Available methods:**
499
+
500
+ - `request(args)` - EIP-1193 requests
501
+ - `signPersonalMessage(message, address)` - Sign personal message
502
+ - `signTypedData(typedData)` - Sign EIP-712 typed data
503
+ - `sendTransaction(transaction)` - Send transaction
504
+ - `switchChain(chainId)` - Switch chains
505
+ - `getChainId()` - Get current chain ID
506
+ - `getAccounts()` - Get connected accounts
507
+ - `isConnected` - Connection status
508
+ - `isAvailable` - Provider availability
509
+
510
+ ### Auto-Confirm Hook (Injected Provider Only)
511
+
512
+ #### useAutoConfirm
513
+
514
+ Hook for managing auto-confirm functionality with the Phantom extension. Auto-confirm allows transactions to be automatically approved without user interaction for enabled chains.
515
+
516
+ > **Note**: This hook only works with the `injected` provider type (Phantom browser extension). It will throw errors for embedded providers.
374
517
 
375
518
  ```tsx
376
- import { useSignAndSendTransaction, NetworkId } from "@phantom/react-sdk";
377
- import { parseEther, parseGwei } from "viem";
519
+ import { useAutoConfirm, NetworkId } from "@phantom/react-sdk";
378
520
 
379
- function SendEthereumTransaction() {
380
- const { signAndSendTransaction, isLoading } = useSignAndSendTransaction();
521
+ function AutoConfirmControls() {
522
+ const { enable, disable, status, supportedChains, isLoading, error, refetch } = useAutoConfirm();
381
523
 
382
- const handleSend = async () => {
524
+ const handleEnable = async () => {
383
525
  try {
384
- const result = await signAndSendTransaction({
385
- networkId: NetworkId.ETHEREUM_MAINNET,
386
- transaction: {
387
- to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
388
- value: parseEther("0.001"), // 0.001 ETH
389
- gas: 21000n,
390
- gasPrice: parseGwei("20"), // 20 gwei
391
- },
526
+ // Enable auto-confirm for specific chains
527
+ const result = await enable({
528
+ chains: [NetworkId.SOLANA_DEVNET, NetworkId.ETHEREUM_MAINNET],
392
529
  });
393
- console.log("Transaction sent:", result);
530
+ console.log("Auto-confirm enabled:", result);
394
531
  } catch (err) {
395
- console.error("Failed to send:", err);
532
+ console.error("Failed to enable auto-confirm:", err);
396
533
  }
397
534
  };
398
535
 
536
+ const handleDisable = async () => {
537
+ try {
538
+ await disable();
539
+ console.log("Auto-confirm disabled");
540
+ } catch (err) {
541
+ console.error("Failed to disable auto-confirm:", err);
542
+ }
543
+ };
544
+
545
+ if (isLoading) {
546
+ return <div>Loading auto-confirm settings...</div>;
547
+ }
548
+
549
+ if (error) {
550
+ return <div>Error: {error.message}</div>;
551
+ }
552
+
399
553
  return (
400
- <button onClick={handleSend} disabled={isLoading}>
401
- {isLoading ? "Sending..." : "Send ETH"}
402
- </button>
554
+ <div>
555
+ <h3>Auto-Confirm Settings</h3>
556
+
557
+ <div>
558
+ <strong>Status:</strong> {status?.enabled ? "Enabled" : "Disabled"}
559
+ {status?.chains && (
560
+ <div>
561
+ <strong>Active Chains:</strong>
562
+ <ul>
563
+ {status.chains.map(chain => (
564
+ <li key={chain}>{chain}</li>
565
+ ))}
566
+ </ul>
567
+ </div>
568
+ )}
569
+ </div>
570
+
571
+ <div>
572
+ <strong>Supported Chains:</strong>
573
+ {supportedChains?.chains && (
574
+ <ul>
575
+ {supportedChains.chains.map(chain => (
576
+ <li key={chain}>{chain}</li>
577
+ ))}
578
+ </ul>
579
+ )}
580
+ </div>
581
+
582
+ <div>
583
+ <button onClick={handleEnable} disabled={isLoading}>
584
+ Enable Auto-Confirm
585
+ </button>
586
+ <button onClick={handleDisable} disabled={isLoading}>
587
+ Disable Auto-Confirm
588
+ </button>
589
+ <button onClick={refetch} disabled={isLoading}>
590
+ Refresh Status
591
+ </button>
592
+ </div>
593
+ </div>
403
594
  );
404
595
  }
405
596
  ```
406
597
 
407
- ## Network Support
598
+ **Hook Interface:**
408
599
 
409
- ### Supported Networks
410
-
411
- The SDK automatically determines the transaction type from the NetworkId:
412
-
413
- #### Solana
414
-
415
- - `NetworkId.SOLANA_MAINNET`
416
- - `NetworkId.SOLANA_DEVNET`
417
- - `NetworkId.SOLANA_TESTNET`
418
-
419
- #### Ethereum/EVM
600
+ ```typescript
601
+ interface UseAutoConfirmResult {
602
+ enable: (params: AutoConfirmEnableParams) => Promise<AutoConfirmResult>;
603
+ disable: () => Promise<void>;
604
+ status: AutoConfirmResult | null;
605
+ supportedChains: AutoConfirmSupportedChainsResult | null;
606
+ isLoading: boolean;
607
+ error: Error | null;
608
+ refetch: () => Promise<void>;
609
+ }
420
610
 
421
- - `NetworkId.ETHEREUM_MAINNET`
422
- - `NetworkId.ETHEREUM_SEPOLIA`
423
- - `NetworkId.POLYGON_MAINNET`
424
- - `NetworkId.ARBITRUM_ONE`
425
- - `NetworkId.OPTIMISM_MAINNET`
426
- - `NetworkId.BASE_MAINNET`
611
+ interface AutoConfirmEnableParams {
612
+ chains?: NetworkId[]; // Optional array of chains to enable
613
+ }
427
614
 
428
- #### Bitcoin
615
+ interface AutoConfirmResult {
616
+ enabled: boolean;
617
+ chains: NetworkId[];
618
+ }
429
619
 
430
- - `NetworkId.BITCOIN_MAINNET`
431
- - `NetworkId.BITCOIN_TESTNET`
620
+ interface AutoConfirmSupportedChainsResult {
621
+ chains: NetworkId[];
622
+ }
623
+ ```
432
624
 
433
- #### Sui
625
+ **Available Methods:**
434
626
 
435
- - `NetworkId.SUI_MAINNET`
436
- - `NetworkId.SUI_TESTNET`
437
- - `NetworkId.SUI_DEVNET`
627
+ - `enable(params)` - Enable auto-confirm for specific chains
628
+ - `disable()` - Disable auto-confirm completely
629
+ - `refetch()` - Refresh status and supported chains from extension
630
+ - `status` - Current auto-confirm status (enabled/disabled and active chains)
631
+ - `supportedChains` - List of chains that support auto-confirm
632
+ - `isLoading` - Loading state for operations
633
+ - `error` - Any errors from auto-confirm operations
438
634
 
439
- ### Provider Network Support
635
+ **Usage Notes:**
440
636
 
441
- | Provider Type | Network Support |
442
- | ------------- | ----------------------------------------------- |
443
- | **Injected** | All networks supported by Phantom extension |
444
- | **Embedded** | All networks based on configured `addressTypes` |
637
+ - Auto-confirm automatically fetches status and supported chains when the hook initializes
638
+ - Only works with injected provider (Phantom extension)
639
+ - Throws errors for embedded providers
640
+ - Status is automatically updated after enable/disable operations
641
+ - Use `refetch()` to manually refresh data from the extension
445
642
 
446
643
  ## Transaction Examples
447
644
 
@@ -449,10 +646,10 @@ The SDK automatically determines the transaction type from the NetworkId:
449
646
 
450
647
  ```tsx
451
648
  import { VersionedTransaction, TransactionMessage, SystemProgram, PublicKey, Connection } from "@solana/web3.js";
452
- import { useSignAndSendTransaction, NetworkId } from "@phantom/react-sdk";
649
+ import { useSolana } from "@phantom/react-sdk";
453
650
 
454
651
  function SolanaExample() {
455
- const { signAndSendTransaction } = useSignAndSendTransaction();
652
+ const solana = useSolana();
456
653
 
457
654
  const sendTransaction = async () => {
458
655
  // Get recent blockhash
@@ -460,6 +657,7 @@ function SolanaExample() {
460
657
  const { blockhash } = await connection.getLatestBlockhash();
461
658
 
462
659
  // Create transfer instruction
660
+ const fromAddress = await solana.getPublicKey();
463
661
  const transferInstruction = SystemProgram.transfer({
464
662
  fromPubkey: new PublicKey(fromAddress),
465
663
  toPubkey: new PublicKey(toAddress),
@@ -475,12 +673,12 @@ function SolanaExample() {
475
673
 
476
674
  const transaction = new VersionedTransaction(messageV0);
477
675
 
478
- // No serialization or encoding needed!
479
- const result = await signAndSendTransaction({
480
- networkId: NetworkId.SOLANA_MAINNET,
481
- transaction,
482
- });
676
+ // Sign and send using chain-specific hook
677
+ const result = await solana.signAndSendTransaction(transaction);
678
+ console.log("Transaction sent:", result.hash);
483
679
  };
680
+
681
+ return <button onClick={sendTransaction}>Send SOL</button>;
484
682
  }
485
683
  ```
486
684
 
@@ -496,15 +694,16 @@ import {
496
694
  address,
497
695
  compileTransaction,
498
696
  } from "@solana/kit";
499
- import { useSignAndSendTransaction, NetworkId } from "@phantom/react-sdk";
697
+ import { useSolana } from "@phantom/react-sdk";
500
698
 
501
699
  function SolanaKitExample() {
502
- const { signAndSendTransaction } = useSignAndSendTransaction();
700
+ const solana = useSolana();
503
701
 
504
702
  const sendTransaction = async () => {
505
703
  const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");
506
704
  const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
507
705
 
706
+ const userPublicKey = await solana.getPublicKey();
508
707
  const transactionMessage = pipe(
509
708
  createTransactionMessage({ version: 0 }),
510
709
  tx => setTransactionMessageFeePayer(address(userPublicKey), tx),
@@ -513,11 +712,12 @@ function SolanaKitExample() {
513
712
 
514
713
  const transaction = compileTransaction(transactionMessage);
515
714
 
516
- const result = await signAndSendTransaction({
517
- networkId: NetworkId.SOLANA_MAINNET,
518
- transaction,
519
- });
715
+ // Sign and send using chain-specific hook
716
+ const result = await solana.signAndSendTransaction(transaction);
717
+ console.log("Transaction sent:", result.hash);
520
718
  };
719
+
720
+ return <button onClick={sendTransaction}>Send SOL</button>;
521
721
  }
522
722
  ```
523
723
 
@@ -525,96 +725,40 @@ function SolanaKitExample() {
525
725
 
526
726
  ```tsx
527
727
  import { parseEther, parseGwei, encodeFunctionData } from "viem";
528
- import { useSignAndSendTransaction, NetworkId } from "@phantom/react-sdk";
728
+ import { useEthereum } from "@phantom/react-sdk";
529
729
 
530
730
  function EthereumExample() {
531
- const { signAndSendTransaction } = useSignAndSendTransaction();
731
+ const ethereum = useEthereum();
532
732
 
533
733
  const sendEth = async () => {
534
- const result = await signAndSendTransaction({
535
- networkId: NetworkId.ETHEREUM_MAINNET,
536
- transaction: {
537
- to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
538
- value: parseEther("1"), // 1 ETH
539
- gas: 21000n,
540
- gasPrice: parseGwei("20"), // 20 gwei
541
- },
734
+ const result = await ethereum.sendTransaction({
735
+ to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
736
+ value: parseEther("1").toString(), // 1 ETH
737
+ gas: "21000",
738
+ gasPrice: parseGwei("20").toString(), // 20 gwei
542
739
  });
740
+ console.log("ETH sent:", result.hash);
543
741
  };
544
742
 
545
743
  const sendToken = async () => {
546
- const result = await signAndSendTransaction({
547
- networkId: NetworkId.ETHEREUM_MAINNET,
548
- transaction: {
549
- to: tokenContractAddress,
550
- data: encodeFunctionData({
551
- abi: erc20Abi,
552
- functionName: "transfer",
553
- args: [recipientAddress, parseEther("100")],
554
- }),
555
- gas: 50000n,
556
- maxFeePerGas: parseGwei("30"),
557
- maxPriorityFeePerGas: parseGwei("2"),
558
- },
559
- });
560
- };
561
- }
562
- ```
563
-
564
- ## Advanced Usage
565
-
566
- ### Multi-Chain Application
567
-
568
- ```tsx
569
- import { useSignAndSendTransaction, NetworkId } from "@phantom/react-sdk";
570
- import { VersionedTransaction, TransactionMessage, SystemProgram, PublicKey, Connection } from "@solana/web3.js";
571
- import { parseEther } from "viem";
572
-
573
- function MultiChainWallet() {
574
- const { signAndSendTransaction } = useSignAndSendTransaction();
575
-
576
- const sendSolana = async () => {
577
- // Get recent blockhash
578
- const connection = new Connection("https://api.mainnet-beta.solana.com");
579
- const { blockhash } = await connection.getLatestBlockhash();
580
-
581
- // Create transfer instruction
582
- const transferInstruction = SystemProgram.transfer({
583
- fromPubkey: new PublicKey(solanaAddress),
584
- toPubkey: new PublicKey(recipient),
585
- lamports: 1000000,
586
- });
587
-
588
- // Create VersionedTransaction
589
- const messageV0 = new TransactionMessage({
590
- payerKey: new PublicKey(solanaAddress),
591
- recentBlockhash: blockhash,
592
- instructions: [transferInstruction],
593
- }).compileToV0Message();
594
-
595
- const transaction = new VersionedTransaction(messageV0);
596
-
597
- return await signAndSendTransaction({
598
- networkId: NetworkId.SOLANA_MAINNET,
599
- transaction,
600
- });
601
- };
602
-
603
- const sendEthereum = async () => {
604
- return await signAndSendTransaction({
605
- networkId: NetworkId.ETHEREUM_MAINNET,
606
- transaction: {
607
- to: recipient,
608
- value: parseEther("0.1"),
609
- gas: 21000n,
610
- },
744
+ const result = await ethereum.sendTransaction({
745
+ to: tokenContractAddress,
746
+ data: encodeFunctionData({
747
+ abi: erc20Abi,
748
+ functionName: "transfer",
749
+ args: [recipientAddress, parseEther("100")],
750
+ }),
751
+ gas: "50000",
752
+ maxFeePerGas: parseGwei("30").toString(),
753
+ maxPriorityFeePerGas: parseGwei("2").toString(),
611
754
  });
755
+ console.log("Token sent:", result.hash);
612
756
  };
613
757
 
614
758
  return (
615
759
  <div>
616
- <button onClick={sendSolana}>Send SOL</button>
617
- <button onClick={sendEthereum}>Send ETH</button>
760
+ <button onClick={sendEth}>Send ETH</button>
761
+ <button onClick={sendToken}>Send Token</button>
618
762
  </div>
619
763
  );
620
764
  }
@@ -624,28 +768,27 @@ function MultiChainWallet() {
624
768
 
625
769
  Quick reference of all available hooks:
626
770
 
627
- | Hook | Purpose | Returns |
628
- | --------------------------- | -------------------------- | ---------------------------------------------- |
629
- | `useConnect` | Connect to wallet | `{ connect, isConnecting, error }` |
630
- | `useAccounts` | Get wallet addresses | `WalletAddress[]` or `null` |
631
- | `useIsExtensionInstalled` | Check extension status | `{ isLoading, isInstalled }` |
632
- | `useDisconnect` | Disconnect from wallet | `{ disconnect, isDisconnecting }` |
633
- | `useSignMessage` | Sign text messages | `{ signMessage, isSigning, error }` |
634
- | `useSignAndSendTransaction` | Sign and send transactions | `{ signAndSendTransaction, isSigning, error }` |
635
- | `usePhantom` | Get provider context | `{ isConnected, isReady }` |
771
+ | Hook | Purpose | Returns |
772
+ | ------------------------- | --------------------------------------- | --------------------------------------------------- |
773
+ | `useConnect` | Connect to wallet | `{ connect, isConnecting, error }` |
774
+ | `useAccounts` | Get wallet addresses | `WalletAddress[]` or `null` |
775
+ | `useIsExtensionInstalled` | Check extension status | `{ isLoading, isInstalled }` |
776
+ | `useDisconnect` | Disconnect from wallet | `{ disconnect, isDisconnecting }` |
777
+ | `useAutoConfirm` | Auto-confirm management (injected only) | `{ enable, disable, status, supportedChains, ... }` |
778
+ | `useSolana` | Solana chain operations | `{ signMessage, signAndSendTransaction, ... }` |
779
+ | `useEthereum` | Ethereum chain operations | `{ signPersonalMessage, sendTransaction, ... }` |
780
+ | `usePhantom` | Get provider context | `{ isConnected, isReady }` |
636
781
 
637
782
  ## Configuration Reference
638
783
 
639
784
  ```typescript
640
785
  interface PhantomSDKConfig {
641
786
  providerType: "injected" | "embedded";
642
- appName?: string; // Optional app name for branding
643
- appLogo?: string; // Optional app logo URL for branding
644
787
  addressTypes?: [AddressType, ...AddressType[]]; // Networks to enable (e.g., [AddressType.solana])
645
788
 
646
789
  // Required for embedded provider only
647
790
  apiBaseUrl?: string; // Phantom API base URL
648
- organizationId?: string; // Your organization ID
791
+ appId: string; // Your app ID
649
792
  authOptions?: {
650
793
  authUrl?: string; // Custom auth URL (optional)
651
794
  redirectUrl?: string; // Custom redirect URL (optional)
@@ -664,8 +807,8 @@ The React SDK supports separate debug configuration that can be changed without
664
807
 
665
808
  ```typescript
666
809
  interface PhantomDebugConfig {
667
- enabled?: boolean; // Enable debug logging
668
- level?: DebugLevel; // Debug level (ERROR, WARN, INFO, DEBUG)
810
+ enabled?: boolean; // Enable debug logging
811
+ level?: DebugLevel; // Debug level (ERROR, WARN, INFO, DEBUG)
669
812
  callback?: DebugCallback; // Custom debug message handler
670
813
  }
671
814
  ```
@@ -684,7 +827,6 @@ function App() {
684
827
  // SDK configuration - static, won't change when debug settings change
685
828
  const config: PhantomSDKConfig = {
686
829
  providerType: "embedded",
687
- organizationId: "your-org-id",
688
830
  // ... other config
689
831
  };
690
832
 
@@ -711,12 +853,12 @@ Debug callbacks receive a `DebugMessage` object:
711
853
 
712
854
  ```typescript
713
855
  interface DebugMessage {
714
- timestamp: number; // Unix timestamp
715
- level: DebugLevel; // Message level
716
- category: string; // Component category
717
- message: string; // Debug message text
718
- data?: any; // Additional debug data (optional)
856
+ timestamp: number; // Unix timestamp
857
+ level: DebugLevel; // Message level
858
+ category: string; // Component category
859
+ message: string; // Debug message text
860
+ data?: any; // Additional debug data (optional)
719
861
  }
720
862
  ```
721
863
 
722
- For more details, examples, and bundle optimization tips, see the [@phantom/browser-sdk documentation](../browser-sdk/README.md).
864
+ For more details and examples, see the [@phantom/browser-sdk documentation](../browser-sdk/README.md).