@phantom/react-sdk 0.0.10 → 0.1.0

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,292 +1,602 @@
1
- # Phantom React SDK
1
+ # @phantom/react-sdk
2
2
 
3
- React hooks and components for integrating with Phantom wallet.
3
+ React hooks for integrating Phantom wallet functionality into React applications with native transaction support.
4
4
 
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
- npm install @phantom/react-sdk @phantom/browser-sdk
8
+ npm install @phantom/react-sdk
9
9
  ```
10
10
 
11
+ ## Dependencies
12
+
13
+ Install additional dependencies based on the networks you want to support:
14
+
15
+ | Network Support | Required Dependencies |
16
+ | --------------- | ---------------------------------- |
17
+ | Solana | `@solana/web3.js` OR `@solana/kit` |
18
+ | Ethereum/EVM | `viem` |
19
+ | Bitcoin | `bitcoinjs-lib` |
20
+ | Sui | `@mysten/sui.js` |
21
+
22
+ **Example for Solana + Ethereum support (using @solana/web3.js):**
23
+
24
+ ```bash
25
+ npm install @phantom/react-sdk @solana/web3.js viem
26
+ ```
27
+
28
+ **Example for Solana + Ethereum support (using @solana/kit):**
29
+
30
+ ```bash
31
+ npm install @phantom/react-sdk @solana/kit viem
32
+ ```
33
+
34
+ For complete dependency information and bundle optimization tips, see the [@phantom/browser-sdk documentation](../browser-sdk/README.md#bundle-optimization-tips).
35
+
11
36
  ## Quick Start
12
37
 
38
+ ### Basic Setup
39
+
13
40
  ```tsx
14
- import React from "react";
15
- import { PhantomProvider, useConnect } from "@phantom/react-sdk/solana";
16
- import { createSolanaPlugin } from "@phantom/browser-sdk/solana";
41
+ import { PhantomProvider } from "@phantom/react-sdk";
42
+ import { AddressType } from "@phantom/client";
17
43
 
18
44
  function App() {
19
45
  return (
20
- <PhantomProvider config={{ plugins: [createSolanaPlugin()] }}>
21
- <WalletComponent />
46
+ <PhantomProvider
47
+ config={{
48
+ providerType: "injected", // Uses Phantom browser extension
49
+ }}
50
+ >
51
+ <YourApp />
22
52
  </PhantomProvider>
23
53
  );
24
54
  }
55
+ ```
25
56
 
26
- function WalletComponent() {
27
- const { connect } = useConnect();
57
+ ### Embedded Wallet Setup
28
58
 
29
- const handleConnect = async () => {
30
- try {
31
- const connectedAccount = await connect();
32
- console.log("Wallet connected:", connectedAccount?.publicKey?.toString());
33
- } catch (error) {
34
- console.error("Connection failed:", error);
35
- }
36
- };
59
+ ```tsx
60
+ import { PhantomProvider } from "@phantom/react-sdk";
61
+ import { AddressType } from "@phantom/client";
37
62
 
63
+ function App() {
38
64
  return (
39
- <div>
40
- <button onClick={handleConnect}>Connect to Solana</button>
41
- </div>
65
+ <PhantomProvider
66
+ config={{
67
+ providerType: "embedded",
68
+ embeddedWalletType: "app-wallet", // or 'user-wallet'
69
+ addressTypes: [AddressType.solana, AddressType.ethereum],
70
+ apiBaseUrl: "https://api.phantom.com",
71
+ organizationId: "your-org-id",
72
+ }}
73
+ >
74
+ <YourApp />
75
+ </PhantomProvider>
42
76
  );
43
77
  }
78
+ ```
79
+
80
+ ## Provider Types
44
81
 
45
- export default App;
82
+ ### Injected Provider
83
+
84
+ Uses the Phantom browser extension installed by the user.
85
+
86
+ ```tsx
87
+ <PhantomProvider
88
+ config={{
89
+ providerType: "injected",
90
+ }}
91
+ >
92
+ <YourApp />
93
+ </PhantomProvider>
46
94
  ```
47
95
 
48
- ## API Reference
96
+ ### Embedded Provider
97
+
98
+ Creates non-custodial wallets embedded in your application.
49
99
 
50
- ### PhantomProvider
100
+ #### App Wallet (Recommended for most apps)
51
101
 
52
- The PhantomProvider component provides the Phantom context to child components.
102
+ - **New wallets** created per application
103
+ - **Unfunded** by default - you need to fund them
104
+ - **Independent** from user's existing Phantom wallet
53
105
 
54
106
  ```tsx
55
- import { PhantomProvider } from "@phantom/react-sdk";
56
- import { createSolanaPlugin } from "@phantom/browser-sdk/solana";
107
+ <PhantomProvider
108
+ config={{
109
+ providerType: "embedded",
110
+ embeddedWalletType: "app-wallet",
111
+ addressTypes: [AddressType.solana],
112
+ apiBaseUrl: "https://api.phantom.com",
113
+ organizationId: "your-org-id",
114
+ }}
115
+ >
116
+ <YourApp />
117
+ </PhantomProvider>
118
+ ```
119
+
120
+ #### User Wallet (For existing Phantom users)
121
+
122
+ - **Uses Phantom authentication** - user logs in with existing account
123
+ - **Potentially funded** - brings existing wallet balance
124
+ - **Connected** to user's Phantom ecosystem
57
125
 
58
- <PhantomProvider config={{ plugins: [createSolanaPlugin()] }}>{children}</PhantomProvider>;
126
+ ```tsx
127
+ <PhantomProvider
128
+ config={{
129
+ providerType: "embedded",
130
+ embeddedWalletType: "user-wallet",
131
+ addressTypes: [AddressType.solana, AddressType.ethereum],
132
+ apiBaseUrl: "https://api.phantom.com",
133
+ organizationId: "your-org-id",
134
+ }}
135
+ >
136
+ <YourApp />
137
+ </PhantomProvider>
59
138
  ```
60
139
 
61
- ### usePhantom
140
+ ## Solana Provider Configuration
62
141
 
63
- The `usePhantom` hoo provides access to the phantom instance. With Phantom instance you can call browser-sdk methods directly.
142
+ When using `AddressType.solana`, you can choose between two Solana libraries:
64
143
 
65
- ## Solana API Reference
144
+ ```tsx
145
+ <PhantomProvider
146
+ config={{
147
+ providerType: "embedded",
148
+ addressTypes: [AddressType.solana],
149
+ solanaProvider: "web3js", // or 'kit'
150
+ apiBaseUrl: "https://api.phantom.com",
151
+ organizationId: "your-org-id",
152
+ }}
153
+ >
154
+ <YourApp />
155
+ </PhantomProvider>
156
+ ```
66
157
 
67
- ### useConnect (Solana)
158
+ **Provider Options:**
68
159
 
69
- The `useConnect` hook provides a function to connect to the Phantom wallet for Solana.
160
+ - `'web3js'` (default) - Uses `@solana/web3.js` library
161
+ - `'kit'` - Uses `@solana/kit` library (modern, TypeScript-first)
70
162
 
71
- #### Props
163
+ **When to use each:**
72
164
 
73
- - `autoConnect?: boolean` (optional) - If `true`, attempts to connect to the wallet automatically when the component mounts. Defaults to `false`.
165
+ - **@solana/web3.js**: Better ecosystem compatibility, wider community support
166
+ - **@solana/kit**: Better TypeScript support, modern architecture, smaller bundle size
74
167
 
75
- #### Return Value
168
+ ## Available Hooks
76
169
 
77
- The hook returns an object with the following property:
170
+ ### useConnect
78
171
 
79
- - `connect: () => Promise<ConnectResponse>` - An asynchronous function that initiates the connection process. Returns a promise that resolves with the connection response (e.g., `{ publicKey: string }`) or rejects if connection fails.
172
+ Connect to wallet:
80
173
 
81
174
  ```tsx
82
- import { useConnect } from "@phantom/react-sdk/solana"; // Or '@phantom/react-sdk/solana' if specific
175
+ import { useConnect } from "@phantom/react-sdk";
83
176
 
84
- function MyComponent() {
85
- const { connect } = useConnect({ autoConnect: true });
177
+ function ConnectButton() {
178
+ const { connect, isLoading, error } = useConnect();
86
179
 
87
- const handleConnectClick = async () => {
180
+ const handleConnect = async () => {
88
181
  try {
89
- const res = await connect();
90
- console.log("Connected:", res.publicKey.toString());
182
+ const { walletId, addresses } = await connect();
183
+ console.log("Connected addresses:", addresses);
91
184
  } catch (err) {
92
- console.error("Connection error:", err);
185
+ console.error("Failed to connect:", err);
93
186
  }
94
187
  };
95
- // ...
188
+
189
+ return (
190
+ <button onClick={handleConnect} disabled={isLoading}>
191
+ {isLoading ? "Connecting..." : "Connect Wallet"}
192
+ </button>
193
+ );
96
194
  }
97
195
  ```
98
196
 
99
- ### useDisconnect (Solana)
197
+ ### useAccounts
100
198
 
101
- The `useDisconnect` hook provides a function to disconnect from the Phantom wallet for Solana.
199
+ Get connected wallet addresses:
200
+
201
+ ```tsx
202
+ import { useAccounts } from "@phantom/react-sdk";
102
203
 
103
- #### Return Value
204
+ function WalletAddresses() {
205
+ const addresses = useAccounts();
206
+
207
+ if (!addresses) {
208
+ return <div>Not connected</div>;
209
+ }
210
+
211
+ return (
212
+ <div>
213
+ {addresses.map((addr, index) => (
214
+ <div key={index}>
215
+ <strong>{addr.addressType}:</strong> {addr.address}
216
+ </div>
217
+ ))}
218
+ </div>
219
+ );
220
+ }
221
+ ```
104
222
 
105
- The hook returns an object with the following property:
223
+ ### useIsExtensionInstalled
106
224
 
107
- - `disconnect: () => Promise<void>` - An asynchronous function that initiates the disconnection process. Returns a promise that resolves when disconnection is complete or rejects if disconnection fails.
225
+ Check if the Phantom browser extension is installed (for injected provider):
108
226
 
109
227
  ```tsx
110
- import { useDisconnect } from "@phantom/react-sdk/solana";
228
+ import { useIsExtensionInstalled } from "@phantom/react-sdk";
111
229
 
112
- function MyComponent() {
113
- const { disconnect } = useDisconnect();
230
+ function ExtensionStatus() {
231
+ const { isLoading, isInstalled } = useIsExtensionInstalled();
114
232
 
115
- const handleDisconnectClick = async () => {
116
- try {
117
- await disconnect();
118
- console.log("Disconnected");
119
- } catch (err) {
120
- console.error("Disconnection error:", err);
121
- }
122
- };
123
- // ...
233
+ if (isLoading) {
234
+ return <div>Checking for Phantom extension...</div>;
235
+ }
236
+
237
+ return (
238
+ <div>
239
+ {isInstalled ? (
240
+ <p>✅ Phantom extension is installed!</p>
241
+ ) : (
242
+ <p>❌ Phantom extension not found. <a href="https://phantom.app/download" target="_blank">Install here</a></p>
243
+ )}
244
+ </div>
245
+ );
124
246
  }
125
247
  ```
126
248
 
127
- ### useAccount
249
+ **Features:**
250
+ - **Session-based caching**: Result is cached during the browser session to avoid redundant checks
251
+ - **Automatic detection**: Runs automatically when the hook is first used
252
+ - **Loading states**: Provides `isLoading` during the initial check
253
+ - **Performance optimized**: Subsequent calls return cached result instantly
128
254
 
129
- The `useAccount` hook provides access the currently connected address
255
+ **Use cases:**
256
+ - Show installation prompts for users without the extension
257
+ - Conditionally render UI based on extension availability
258
+ - Provide fallback options when extension is not installed
130
259
 
131
- #### Return Value
260
+ ### useDisconnect
132
261
 
133
- The hook returns a string with the currently connected address or undefined when account is not connected.
262
+ Disconnect from wallet:
134
263
 
135
- ````tsx
136
-
137
- ### useSignIn (Solana)
264
+ ```tsx
265
+ import { useDisconnect } from "@phantom/react-sdk";
138
266
 
139
- The `useSignIn` hook provides a function to initiate a sign-in request to the Phantom wallet for Solana. This is compliant with SIP-001 (Sign In With Solana).
267
+ function DisconnectButton() {
268
+ const { disconnect, isLoading } = useDisconnect();
140
269
 
141
- #### Return Value
270
+ return (
271
+ <button onClick={disconnect} disabled={isLoading}>
272
+ {isLoading ? "Disconnecting..." : "Disconnect"}
273
+ </button>
274
+ );
275
+ }
276
+ ```
142
277
 
143
- The hook returns an object with the following property:
278
+ ### useSignMessage
144
279
 
145
- - `signIn: (signInData: SolanaSignInData) => Promise<{ address: string; signature: Uint8Array; signedMessage: Uint8Array }>` - An asynchronous function that initiates the sign-in process. `SolanaSignInData` is a type imported from `@phantom/browser-sdk/solana`. Returns a promise that resolves with the `address` (string), `signature` (Uint8Array), and `signedMessage` (Uint8Array), or rejects if the sign-in fails.
280
+ Sign messages with native string input:
146
281
 
147
282
  ```tsx
148
- import { useSignIn } from "@phantom/react-sdk/solana";
149
- import { SolanaSignInData } from "@phantom/browser-sdk/solana"; // This type might be needed from the browser-sdk
283
+ import { useSignMessage, NetworkId } from "@phantom/react-sdk";
150
284
 
151
- function MyComponent() {
152
- const { signIn } = useSignIn();
153
-
154
- const handleSignInClick = async () => {
155
- // Construct SolanaSignInData according to your needs
156
- // This typically includes the domain and a statement for the user.
157
- const signInData: SolanaSignInData = {
158
- domain: window.location.host,
159
- statement: "Please sign in to access exclusive features.",
160
- // Other fields like `nonce`, `chainId`, `resources` can be added as per SIP-001
161
- };
285
+ function SignMessage() {
286
+ const { signMessage, isLoading, error } = useSignMessage();
162
287
 
288
+ const handleSign = async () => {
163
289
  try {
164
- const result = await signIn(signInData);
165
- console.log("Sign In successful. Address:", result.address.toString());
166
- // You can now verify the signature and signedMessage on your backend
167
- // Handle successful sign-in (e.g., update UI, set user session)
290
+ const signature = await signMessage("Hello from Phantom!", NetworkId.SOLANA_MAINNET);
291
+ console.log("Signature:", signature);
168
292
  } catch (err) {
169
- console.error("Sign In error:", err);
170
- // Handle sign-in error (e.g., show error message to user)
293
+ console.error("Failed to sign:", err);
171
294
  }
172
295
  };
173
296
 
174
- return <button onClick={handleSignInClick}>Sign In with Solana</button>;
297
+ return (
298
+ <button onClick={handleSign} disabled={isLoading}>
299
+ {isLoading ? "Signing..." : "Sign Message"}
300
+ </button>
301
+ );
175
302
  }
176
- ````
303
+ ```
177
304
 
178
- ### useSignMessage (Solana)
305
+ ### useSignAndSendTransaction
179
306
 
180
- The `useSignMessage` hook provides a function to prompt the user to sign an arbitrary message with their Solana account.
307
+ #### Solana Transaction
181
308
 
182
- #### Return Value
309
+ ```tsx
310
+ import { useSignAndSendTransaction, NetworkId } from "@phantom/react-sdk";
311
+ import { Transaction, SystemProgram, PublicKey, LAMPORTS_PER_SOL } from "@solana/web3.js";
312
+
313
+ function SendSolanaTransaction() {
314
+ const { signAndSendTransaction, isLoading, error } = useSignAndSendTransaction();
315
+
316
+ const handleSend = async () => {
317
+ // Create native Solana transaction - no encoding needed!
318
+ const transaction = new Transaction().add(
319
+ SystemProgram.transfer({
320
+ fromPubkey: new PublicKey(fromAddress),
321
+ toPubkey: new PublicKey(toAddress),
322
+ lamports: 0.001 * LAMPORTS_PER_SOL,
323
+ }),
324
+ );
183
325
 
184
- The hook returns an object with the following property:
326
+ try {
327
+ const result = await signAndSendTransaction({
328
+ networkId: NetworkId.SOLANA_MAINNET,
329
+ transaction: transaction, // Native Transaction object!
330
+ });
331
+ console.log("Transaction sent:", result.rawTransaction);
332
+ } catch (err) {
333
+ console.error("Failed to send:", err);
334
+ }
335
+ };
185
336
 
186
- - `signMessage: (message: Uint8Array, display?: 'utf8' | 'hex') => Promise<{ signature: Uint8Array; publicKey: string }>` - An asynchronous function that prompts the user to sign a message. The `message` must be a `Uint8Array`. The optional `display` parameter can be 'utf8' (default) or 'hex' to suggest how the wallet should display the message bytes. Returns a promise that resolves with the `signature` (Uint8Array) and `publicKey` (string) of the signer, or rejects if signing fails.
337
+ return (
338
+ <button onClick={handleSend} disabled={isLoading}>
339
+ {isLoading ? "Sending..." : "Send SOL"}
340
+ </button>
341
+ );
342
+ }
343
+ ```
344
+
345
+ #### Ethereum Transaction (with Viem)
187
346
 
188
347
  ```tsx
189
- import { useSignMessage } from "@phantom/react-sdk/solana";
348
+ import { useSignAndSendTransaction, NetworkId } from "@phantom/react-sdk";
349
+ import { parseEther, parseGwei } from "viem";
190
350
 
191
- function MyComponent() {
192
- const { signMessage } = useSignMessage();
351
+ function SendEthereumTransaction() {
352
+ const { signAndSendTransaction, isLoading } = useSignAndSendTransaction();
193
353
 
194
- const handleSignMessage = async () => {
195
- const messageToSign = "Please confirm your action by signing this message.";
196
- const messageBytes = new TextEncoder().encode(messageToSign);
354
+ const handleSend = async () => {
197
355
  try {
198
- const { signature, publicKey } = await signMessage(messageBytes, "utf8");
199
- console.log("Message signed successfully!");
200
- console.log("Signature:", signature);
201
- console.log("Public Key:", publicKey);
202
- // You can now verify this signature on a backend or use it as needed.
356
+ const result = await signAndSendTransaction({
357
+ networkId: NetworkId.ETHEREUM_MAINNET,
358
+ transaction: {
359
+ to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
360
+ value: parseEther("0.001"), // 0.001 ETH
361
+ gas: 21000n,
362
+ gasPrice: parseGwei("20"), // 20 gwei
363
+ },
364
+ });
365
+ console.log("Transaction sent:", result);
203
366
  } catch (err) {
204
- console.error("Sign message error:", err);
205
- // Handle error (e.g., user rejected, wallet error)
367
+ console.error("Failed to send:", err);
206
368
  }
207
369
  };
208
370
 
209
- return <button onClick={handleSignMessage}>Sign Message</button>;
371
+ return (
372
+ <button onClick={handleSend} disabled={isLoading}>
373
+ {isLoading ? "Sending..." : "Send ETH"}
374
+ </button>
375
+ );
210
376
  }
211
377
  ```
212
378
 
213
- ### useSignAndSendTransaction (Solana)
379
+ ## Network Support
380
+
381
+ ### Supported Networks
214
382
 
215
- The `useSignAndSendTransaction` hook prompts the user to sign **and** send a Kit-style transaction.
383
+ The SDK automatically determines the transaction type from the NetworkId:
216
384
 
217
- #### Return Value
385
+ #### Solana
218
386
 
219
- The hook returns an object with the following property:
387
+ - `NetworkId.SOLANA_MAINNET`
388
+ - `NetworkId.SOLANA_DEVNET`
389
+ - `NetworkId.SOLANA_TESTNET`
390
+
391
+ #### Ethereum/EVM
392
+
393
+ - `NetworkId.ETHEREUM_MAINNET`
394
+ - `NetworkId.ETHEREUM_SEPOLIA`
395
+ - `NetworkId.POLYGON_MAINNET`
396
+ - `NetworkId.ARBITRUM_ONE`
397
+ - `NetworkId.OPTIMISM_MAINNET`
398
+ - `NetworkId.BASE_MAINNET`
399
+
400
+ #### Bitcoin
401
+
402
+ - `NetworkId.BITCOIN_MAINNET`
403
+ - `NetworkId.BITCOIN_TESTNET`
404
+
405
+ #### Sui
406
+
407
+ - `NetworkId.SUI_MAINNET`
408
+ - `NetworkId.SUI_TESTNET`
409
+ - `NetworkId.SUI_DEVNET`
410
+
411
+ ### Provider Network Support
412
+
413
+ | Provider Type | Network Support |
414
+ | ------------- | ----------------------------------------------- |
415
+ | **Injected** | All networks supported by Phantom extension |
416
+ | **Embedded** | All networks based on configured `addressTypes` |
417
+
418
+ ## Transaction Examples
419
+
420
+ ### Solana with @solana/web3.js
421
+
422
+ ```tsx
423
+ import { Transaction, SystemProgram, PublicKey } from "@solana/web3.js";
424
+ import { useSignAndSendTransaction, NetworkId } from "@phantom/react-sdk";
425
+
426
+ function SolanaExample() {
427
+ const { signAndSendTransaction } = useSignAndSendTransaction();
428
+
429
+ const sendTransaction = async () => {
430
+ const transaction = new Transaction().add(
431
+ SystemProgram.transfer({
432
+ fromPubkey: new PublicKey(fromAddress),
433
+ toPubkey: new PublicKey(toAddress),
434
+ lamports: 1000000, // 0.001 SOL
435
+ }),
436
+ );
437
+
438
+ // No serialization or encoding needed!
439
+ const result = await signAndSendTransaction({
440
+ networkId: NetworkId.SOLANA_MAINNET,
441
+ transaction,
442
+ });
443
+ };
444
+ }
445
+ ```
220
446
 
221
- - `signAndSendTransaction(transaction: Transaction): Promise<{ signature: string; publicKey?: string }>` – accepts a `Transaction` built with **`@solana/kit`** and returns the confirmed signature.
447
+ ### Solana with @solana/kit
222
448
 
223
449
  ```tsx
224
- import { useSignAndSendTransaction } from "@phantom/react-sdk/solana"; // scoped import is fine
225
450
  import {
226
451
  createSolanaRpc,
452
+ pipe,
227
453
  createTransactionMessage,
228
454
  setTransactionMessageFeePayer,
229
455
  setTransactionMessageLifetimeUsingBlockhash,
230
- pipe,
231
456
  address,
232
457
  compileTransaction,
233
458
  } from "@solana/kit";
459
+ import { useSignAndSendTransaction, NetworkId } from "@phantom/react-sdk";
234
460
 
235
- function MyComponent() {
461
+ function SolanaKitExample() {
236
462
  const { signAndSendTransaction } = useSignAndSendTransaction();
237
463
 
238
- const handlePayment = async (publicKey: string) => {
239
- // 0️⃣ Ensure the wallet is connected and we have a fee-payer address
240
- if (!publicKey) return console.error("Wallet not connected");
464
+ const sendTransaction = async () => {
465
+ const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");
466
+ const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
241
467
 
242
- try {
243
- // 1️⃣ Fetch a recent blockhash
244
- const rpc = createSolanaRpc("https://api.devnet.solana.com");
245
- const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
246
-
247
- // 2️⃣ Build a minimal v0 transaction message (no instructions – demo only)
248
- const txMessage = pipe(
249
- createTransactionMessage({ version: 0 }),
250
- tx => setTransactionMessageFeePayer(address(publicKey), tx),
251
- tx => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
252
- );
253
-
254
- const transaction = compileTransaction(txMessage);
255
-
256
- // 3️⃣ Prompt the user to sign and send
257
- const { signature } = await signAndSendTransaction(transaction);
258
- console.log("Transaction signature:", signature);
259
- } catch (err) {
260
- console.error("Transaction error:", err);
261
- }
262
- };
468
+ const transactionMessage = pipe(
469
+ createTransactionMessage({ version: 0 }),
470
+ tx => setTransactionMessageFeePayer(address(userPublicKey), tx),
471
+ tx => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
472
+ );
263
473
 
264
- return <button onClick={() => handlePayment("YOUR_CONNECTED_WALLET_PUBLIC_KEY")}>Send 0.001 SOL</button>;
474
+ const transaction = compileTransaction(transactionMessage);
475
+
476
+ const result = await signAndSendTransaction({
477
+ networkId: NetworkId.SOLANA_MAINNET,
478
+ transaction,
479
+ });
480
+ };
265
481
  }
266
482
  ```
267
483
 
268
- ### useAccountEffect
484
+ ### Ethereum with Viem
269
485
 
270
- The `useAccountEffect` hook provides easy way to subscribe to events like `connect`, `disconnect` and `accountChanged`. You can subscribe by calling the hook and declaring event callbacks you want to react to.
486
+ ```tsx
487
+ import { parseEther, parseGwei, encodeFunctionData } from "viem";
488
+ import { useSignAndSendTransaction, NetworkId } from "@phantom/react-sdk";
271
489
 
272
- Example:
490
+ function EthereumExample() {
491
+ const { signAndSendTransaction } = useSignAndSendTransaction();
273
492
 
274
- ```tsx
275
- useAccountEffect({
276
- onConnect: data => {
277
- console.log("Connected to Phantom with public key:", data.publicKey);
278
- },
279
- onDisconnect: () => {
280
- console.log("Disconnected from Phantom");
281
- },
282
- onAccountChanged: data => {
283
- console.log("Account changed to:", data.publicKey);
284
- },
285
- });
493
+ const sendEth = async () => {
494
+ const result = await signAndSendTransaction({
495
+ networkId: NetworkId.ETHEREUM_MAINNET,
496
+ transaction: {
497
+ to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
498
+ value: parseEther("1"), // 1 ETH
499
+ gas: 21000n,
500
+ gasPrice: parseGwei("20"), // 20 gwei
501
+ },
502
+ });
503
+ };
504
+
505
+ const sendToken = async () => {
506
+ const result = await signAndSendTransaction({
507
+ networkId: NetworkId.ETHEREUM_MAINNET,
508
+ transaction: {
509
+ to: tokenContractAddress,
510
+ data: encodeFunctionData({
511
+ abi: erc20Abi,
512
+ functionName: "transfer",
513
+ args: [recipientAddress, parseEther("100")],
514
+ }),
515
+ gas: 50000n,
516
+ maxFeePerGas: parseGwei("30"),
517
+ maxPriorityFeePerGas: parseGwei("2"),
518
+ },
519
+ });
520
+ };
521
+ }
286
522
  ```
287
523
 
288
- ## Extension API Reference
524
+ ## Advanced Usage
525
+
526
+ ### Multi-Chain Application
289
527
 
290
- ### useIsInstalled
528
+ ```tsx
529
+ import { useSignAndSendTransaction, NetworkId } from "@phantom/react-sdk";
530
+ import { Transaction, SystemProgram, PublicKey } from "@solana/web3.js";
531
+ import { parseEther } from "viem";
532
+
533
+ function MultiChainWallet() {
534
+ const { signAndSendTransaction } = useSignAndSendTransaction();
535
+
536
+ const sendSolana = async () => {
537
+ const transaction = new Transaction().add(
538
+ SystemProgram.transfer({
539
+ fromPubkey: new PublicKey(solanaAddress),
540
+ toPubkey: new PublicKey(recipient),
541
+ lamports: 1000000,
542
+ }),
543
+ );
544
+
545
+ return await signAndSendTransaction({
546
+ networkId: NetworkId.SOLANA_MAINNET,
547
+ transaction,
548
+ });
549
+ };
550
+
551
+ const sendEthereum = async () => {
552
+ return await signAndSendTransaction({
553
+ networkId: NetworkId.ETHEREUM_MAINNET,
554
+ transaction: {
555
+ to: recipient,
556
+ value: parseEther("0.1"),
557
+ gas: 21000n,
558
+ },
559
+ });
560
+ };
561
+
562
+ return (
563
+ <div>
564
+ <button onClick={sendSolana}>Send SOL</button>
565
+ <button onClick={sendEthereum}>Send ETH</button>
566
+ </div>
567
+ );
568
+ }
569
+ ```
570
+
571
+ ## Hooks Reference
572
+
573
+ Quick reference of all available hooks:
574
+
575
+ | Hook | Purpose | Returns |
576
+ |------|---------|---------|
577
+ | `useConnect` | Connect to wallet | `{ connect, isConnecting, error }` |
578
+ | `useAccounts` | Get wallet addresses | `WalletAddress[]` or `null` |
579
+ | `useIsExtensionInstalled` | Check extension status | `{ isLoading, isInstalled }` |
580
+ | `useDisconnect` | Disconnect from wallet | `{ disconnect, isDisconnecting }` |
581
+ | `useSignMessage` | Sign text messages | `{ signMessage, isSigning, error }` |
582
+ | `useSignAndSendTransaction` | Sign and send transactions | `{ signAndSendTransaction, isSigning, error }` |
583
+ | `useCreateUserOrganization` | Create user organization (embedded) | `{ createUserOrganization, isCreating, error }` |
584
+ | `usePhantom` | Get provider context | `{ isConnected, isReady, currentProviderType }` |
585
+
586
+ ## Configuration Reference
587
+
588
+ ```typescript
589
+ interface PhantomSDKConfig {
590
+ providerType: "injected" | "embedded";
591
+
592
+ // Required for embedded provider only
593
+ addressTypes?: AddressType[]; // Networks to enable
594
+ apiBaseUrl?: string; // Phantom API base URL
595
+ organizationId?: string; // Your organization ID
596
+ authUrl?: string; // Custom auth URL (optional)
597
+ embeddedWalletType?: "app-wallet" | "user-wallet"; // Wallet type
598
+ solanaProvider?: "web3js" | "kit"; // Solana library choice (default: 'web3js')
599
+ }
600
+ ```
291
601
 
292
- The `useIsInstalled` hook provides a function to check whether the phantom extension is installed
602
+ For more details, examples, and bundle optimization tips, see the [@phantom/browser-sdk documentation](../browser-sdk/README.md).