@phantom/react-sdk 0.3.8 → 1.0.0-beta.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 +401 -246
- package/dist/index.d.ts +62 -16
- package/dist/index.js +254 -81
- package/dist/index.mjs +249 -76
- package/package.json +4 -2
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
|
|
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/
|
|
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
|
-
<
|
|
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/
|
|
90
|
+
import { AddressType } from "@phantom/browser-sdk";
|
|
62
91
|
|
|
63
92
|
function App() {
|
|
64
93
|
return (
|
|
@@ -77,6 +106,61 @@ function App() {
|
|
|
77
106
|
}
|
|
78
107
|
```
|
|
79
108
|
|
|
109
|
+
## Connection Flow
|
|
110
|
+
|
|
111
|
+
The React SDK follows a clear connection pattern:
|
|
112
|
+
|
|
113
|
+
1. **Provider Setup**: Wrap your app with `PhantomProvider`
|
|
114
|
+
2. **Connection**: Use `useConnect()` to establish wallet connection
|
|
115
|
+
3. **Chain Operations**: Use chain-specific hooks (`useSolana()`, `useEthereum()`) for transactions and signing
|
|
116
|
+
|
|
117
|
+
```tsx
|
|
118
|
+
function WalletExample() {
|
|
119
|
+
const { connect } = useConnect();
|
|
120
|
+
const solana = useSolana();
|
|
121
|
+
const ethereum = useEthereum();
|
|
122
|
+
|
|
123
|
+
// 1. Connect first
|
|
124
|
+
const handleConnect = async () => {
|
|
125
|
+
await connect();
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// 2. Then use chain-specific operations
|
|
129
|
+
const sendSolanaTransaction = async () => {
|
|
130
|
+
const result = await solana.signAndSendTransaction(transaction);
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const sendEthereumTransaction = async () => {
|
|
134
|
+
const result = await ethereum.sendTransaction(transaction);
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Connection Options
|
|
140
|
+
|
|
141
|
+
For embedded user-wallets, you can specify authentication providers:
|
|
142
|
+
|
|
143
|
+
```tsx
|
|
144
|
+
const { connect } = useConnect();
|
|
145
|
+
|
|
146
|
+
// Default: Show provider selection screen
|
|
147
|
+
await connect();
|
|
148
|
+
|
|
149
|
+
// Google authentication (skips provider selection)
|
|
150
|
+
await connect({
|
|
151
|
+
authOptions: {
|
|
152
|
+
provider: "google",
|
|
153
|
+
},
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
// Apple authentication (skips provider selection)
|
|
157
|
+
await connect({
|
|
158
|
+
authOptions: {
|
|
159
|
+
provider: "apple",
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
```
|
|
163
|
+
|
|
80
164
|
## Provider Types
|
|
81
165
|
|
|
82
166
|
### Injected Provider
|
|
@@ -87,6 +171,7 @@ Uses the Phantom browser extension installed by the user.
|
|
|
87
171
|
<PhantomProvider
|
|
88
172
|
config={{
|
|
89
173
|
providerType: "injected",
|
|
174
|
+
addressTypes: [AddressType.solana, AddressType.ethereum],
|
|
90
175
|
}}
|
|
91
176
|
>
|
|
92
177
|
<YourApp />
|
|
@@ -167,7 +252,9 @@ When using `AddressType.solana`, you can choose between two Solana libraries:
|
|
|
167
252
|
|
|
168
253
|
## Available Hooks
|
|
169
254
|
|
|
170
|
-
###
|
|
255
|
+
### Core Connection Hooks
|
|
256
|
+
|
|
257
|
+
#### useConnect
|
|
171
258
|
|
|
172
259
|
Connect to wallet:
|
|
173
260
|
|
|
@@ -175,7 +262,7 @@ Connect to wallet:
|
|
|
175
262
|
import { useConnect } from "@phantom/react-sdk";
|
|
176
263
|
|
|
177
264
|
function ConnectButton() {
|
|
178
|
-
const { connect,
|
|
265
|
+
const { connect, isConnecting, error } = useConnect();
|
|
179
266
|
|
|
180
267
|
const handleConnect = async () => {
|
|
181
268
|
try {
|
|
@@ -187,14 +274,14 @@ function ConnectButton() {
|
|
|
187
274
|
};
|
|
188
275
|
|
|
189
276
|
return (
|
|
190
|
-
<button onClick={handleConnect} disabled={
|
|
191
|
-
{
|
|
277
|
+
<button onClick={handleConnect} disabled={isConnecting}>
|
|
278
|
+
{isConnecting ? "Connecting..." : "Connect Wallet"}
|
|
192
279
|
</button>
|
|
193
280
|
);
|
|
194
281
|
}
|
|
195
282
|
```
|
|
196
283
|
|
|
197
|
-
|
|
284
|
+
#### useAccounts
|
|
198
285
|
|
|
199
286
|
Get connected wallet addresses:
|
|
200
287
|
|
|
@@ -220,7 +307,25 @@ function WalletAddresses() {
|
|
|
220
307
|
}
|
|
221
308
|
```
|
|
222
309
|
|
|
223
|
-
|
|
310
|
+
#### useDisconnect
|
|
311
|
+
|
|
312
|
+
Disconnect from wallet:
|
|
313
|
+
|
|
314
|
+
```tsx
|
|
315
|
+
import { useDisconnect } from "@phantom/react-sdk";
|
|
316
|
+
|
|
317
|
+
function DisconnectButton() {
|
|
318
|
+
const { disconnect, isDisconnecting } = useDisconnect();
|
|
319
|
+
|
|
320
|
+
return (
|
|
321
|
+
<button onClick={disconnect} disabled={isDisconnecting}>
|
|
322
|
+
{isDisconnecting ? "Disconnecting..." : "Disconnect"}
|
|
323
|
+
</button>
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
#### useIsExtensionInstalled
|
|
224
329
|
|
|
225
330
|
Check if the Phantom browser extension is installed (for injected provider):
|
|
226
331
|
|
|
@@ -251,197 +356,299 @@ function ExtensionStatus() {
|
|
|
251
356
|
}
|
|
252
357
|
```
|
|
253
358
|
|
|
254
|
-
|
|
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
|
|
260
|
-
|
|
261
|
-
**Use cases:**
|
|
359
|
+
### Chain-Specific Hooks
|
|
262
360
|
|
|
263
|
-
|
|
264
|
-
- Conditionally render UI based on extension availability
|
|
265
|
-
- Provide fallback options when extension is not installed
|
|
361
|
+
#### useSolana
|
|
266
362
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
Disconnect from wallet:
|
|
363
|
+
Hook for Solana chain operations:
|
|
270
364
|
|
|
271
365
|
```tsx
|
|
272
|
-
import {
|
|
366
|
+
import { useSolana } from "@phantom/react-sdk";
|
|
367
|
+
import { VersionedTransaction, TransactionMessage, SystemProgram, PublicKey, Connection } from "@solana/web3.js";
|
|
273
368
|
|
|
274
|
-
function
|
|
275
|
-
const
|
|
369
|
+
function SolanaOperations() {
|
|
370
|
+
const solana = useSolana();
|
|
276
371
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
);
|
|
282
|
-
}
|
|
283
|
-
```
|
|
372
|
+
const signMessage = async () => {
|
|
373
|
+
const signature = await solana.signMessage("Hello Solana!");
|
|
374
|
+
console.log("Signature:", signature);
|
|
375
|
+
};
|
|
284
376
|
|
|
285
|
-
|
|
377
|
+
const signAndSendTransaction = async () => {
|
|
378
|
+
// Create transaction
|
|
379
|
+
const connection = new Connection("https://api.mainnet-beta.solana.com");
|
|
380
|
+
const { blockhash } = await connection.getLatestBlockhash();
|
|
381
|
+
|
|
382
|
+
const fromAddress = await solana.getPublicKey();
|
|
383
|
+
const transferInstruction = SystemProgram.transfer({
|
|
384
|
+
fromPubkey: new PublicKey(fromAddress),
|
|
385
|
+
toPubkey: new PublicKey(toAddress),
|
|
386
|
+
lamports: 1000000, // 0.001 SOL
|
|
387
|
+
});
|
|
286
388
|
|
|
287
|
-
|
|
389
|
+
const messageV0 = new TransactionMessage({
|
|
390
|
+
payerKey: new PublicKey(fromAddress),
|
|
391
|
+
recentBlockhash: blockhash,
|
|
392
|
+
instructions: [transferInstruction],
|
|
393
|
+
}).compileToV0Message();
|
|
288
394
|
|
|
289
|
-
|
|
290
|
-
import { useSignMessage, NetworkId } from "@phantom/react-sdk";
|
|
395
|
+
const transaction = new VersionedTransaction(messageV0);
|
|
291
396
|
|
|
292
|
-
|
|
293
|
-
|
|
397
|
+
// Sign and send
|
|
398
|
+
const result = await solana.signAndSendTransaction(transaction);
|
|
399
|
+
console.log("Transaction sent:", result.hash);
|
|
400
|
+
};
|
|
294
401
|
|
|
295
|
-
const
|
|
296
|
-
|
|
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
|
-
}
|
|
402
|
+
const switchNetwork = async () => {
|
|
403
|
+
await solana.switchNetwork('devnet');
|
|
305
404
|
};
|
|
306
405
|
|
|
307
406
|
return (
|
|
308
|
-
<
|
|
309
|
-
{
|
|
310
|
-
|
|
407
|
+
<div>
|
|
408
|
+
<button onClick={signMessage}>Sign Message</button>
|
|
409
|
+
<button onClick={signAndSendTransaction}>Send Transaction</button>
|
|
410
|
+
<button onClick={switchNetwork}>Switch to Devnet</button>
|
|
411
|
+
<p>Connected: {solana.isConnected ? 'Yes' : 'No'}</p>
|
|
412
|
+
</div>
|
|
311
413
|
);
|
|
312
414
|
}
|
|
313
415
|
```
|
|
314
416
|
|
|
315
|
-
|
|
417
|
+
**Available methods:**
|
|
418
|
+
- `signMessage(message)` - Sign a message
|
|
419
|
+
- `signTransaction(transaction)` - Sign without sending
|
|
420
|
+
- `signAndSendTransaction(transaction)` - Sign and send
|
|
421
|
+
- `switchNetwork(network)` - Switch between mainnet/devnet
|
|
422
|
+
- `getPublicKey()` - Get current public key
|
|
423
|
+
- `isConnected` - Connection status
|
|
424
|
+
- `isAvailable` - Provider availability
|
|
425
|
+
|
|
426
|
+
#### useEthereum
|
|
316
427
|
|
|
317
|
-
|
|
428
|
+
Hook for Ethereum chain operations:
|
|
318
429
|
|
|
319
430
|
```tsx
|
|
320
|
-
import {
|
|
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();
|
|
431
|
+
import { useEthereum } from "@phantom/react-sdk";
|
|
337
432
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
fromPubkey: new PublicKey(fromAddress),
|
|
341
|
-
toPubkey: new PublicKey(toAddress),
|
|
342
|
-
lamports: 0.001 * LAMPORTS_PER_SOL,
|
|
343
|
-
});
|
|
433
|
+
function EthereumOperations() {
|
|
434
|
+
const ethereum = useEthereum();
|
|
344
435
|
|
|
345
|
-
|
|
346
|
-
const
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
}).compileToV0Message();
|
|
436
|
+
const signPersonalMessage = async () => {
|
|
437
|
+
const accounts = await ethereum.getAccounts();
|
|
438
|
+
const signature = await ethereum.signPersonalMessage("Hello Ethereum!", accounts[0]);
|
|
439
|
+
console.log("Signature:", signature);
|
|
440
|
+
};
|
|
351
441
|
|
|
352
|
-
|
|
442
|
+
const signTypedData = async () => {
|
|
443
|
+
const accounts = await ethereum.getAccounts();
|
|
444
|
+
const typedData = {
|
|
445
|
+
types: {
|
|
446
|
+
EIP712Domain: [
|
|
447
|
+
{ name: "name", type: "string" },
|
|
448
|
+
{ name: "version", type: "string" },
|
|
449
|
+
{ name: "chainId", type: "uint256" },
|
|
450
|
+
{ name: "verifyingContract", type: "address" }
|
|
451
|
+
],
|
|
452
|
+
Mail: [
|
|
453
|
+
{ name: "from", type: "string" },
|
|
454
|
+
{ name: "to", type: "string" },
|
|
455
|
+
{ name: "contents", type: "string" }
|
|
456
|
+
]
|
|
457
|
+
},
|
|
458
|
+
primaryType: "Mail",
|
|
459
|
+
domain: {
|
|
460
|
+
name: "Ether Mail",
|
|
461
|
+
version: "1",
|
|
462
|
+
chainId: 1,
|
|
463
|
+
verifyingContract: "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC"
|
|
464
|
+
},
|
|
465
|
+
message: {
|
|
466
|
+
from: "Alice",
|
|
467
|
+
to: "Bob",
|
|
468
|
+
contents: "Hello!"
|
|
469
|
+
}
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
const signature = await ethereum.signTypedData(typedData);
|
|
473
|
+
console.log("Typed data signature:", signature);
|
|
474
|
+
};
|
|
353
475
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
476
|
+
const sendTransaction = async () => {
|
|
477
|
+
const result = await ethereum.sendTransaction({
|
|
478
|
+
to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
|
|
479
|
+
value: "1000000000000000000", // 1 ETH in wei
|
|
480
|
+
gas: "21000",
|
|
481
|
+
});
|
|
482
|
+
console.log("Transaction sent:", result.hash);
|
|
483
|
+
};
|
|
484
|
+
|
|
485
|
+
const switchChain = async () => {
|
|
486
|
+
await ethereum.switchChain(137); // Switch to Polygon
|
|
363
487
|
};
|
|
364
488
|
|
|
365
489
|
return (
|
|
366
|
-
<
|
|
367
|
-
{
|
|
368
|
-
|
|
490
|
+
<div>
|
|
491
|
+
<button onClick={signPersonalMessage}>Sign Personal Message</button>
|
|
492
|
+
<button onClick={signTypedData}>Sign Typed Data</button>
|
|
493
|
+
<button onClick={sendTransaction}>Send Transaction</button>
|
|
494
|
+
<button onClick={switchChain}>Switch to Polygon</button>
|
|
495
|
+
<p>Connected: {ethereum.isConnected ? 'Yes' : 'No'}</p>
|
|
496
|
+
</div>
|
|
369
497
|
);
|
|
370
498
|
}
|
|
371
499
|
```
|
|
372
500
|
|
|
373
|
-
|
|
501
|
+
**Available methods:**
|
|
502
|
+
- `request(args)` - EIP-1193 requests
|
|
503
|
+
- `signPersonalMessage(message, address)` - Sign personal message
|
|
504
|
+
- `signTypedData(typedData)` - Sign EIP-712 typed data
|
|
505
|
+
- `sendTransaction(transaction)` - Send transaction
|
|
506
|
+
- `switchChain(chainId)` - Switch chains
|
|
507
|
+
- `getChainId()` - Get current chain ID
|
|
508
|
+
- `getAccounts()` - Get connected accounts
|
|
509
|
+
- `isConnected` - Connection status
|
|
510
|
+
- `isAvailable` - Provider availability
|
|
374
511
|
|
|
375
|
-
|
|
376
|
-
import { useSignAndSendTransaction, NetworkId } from "@phantom/react-sdk";
|
|
377
|
-
import { parseEther, parseGwei } from "viem";
|
|
512
|
+
### Auto-Confirm Hook (Injected Provider Only)
|
|
378
513
|
|
|
379
|
-
|
|
380
|
-
const { signAndSendTransaction, isLoading } = useSignAndSendTransaction();
|
|
514
|
+
#### useAutoConfirm
|
|
381
515
|
|
|
382
|
-
|
|
516
|
+
Hook for managing auto-confirm functionality with the Phantom extension. Auto-confirm allows transactions to be automatically approved without user interaction for enabled chains.
|
|
517
|
+
|
|
518
|
+
> **Note**: This hook only works with the `injected` provider type (Phantom browser extension). It will throw errors for embedded providers.
|
|
519
|
+
|
|
520
|
+
```tsx
|
|
521
|
+
import { useAutoConfirm, NetworkId } from "@phantom/react-sdk";
|
|
522
|
+
|
|
523
|
+
function AutoConfirmControls() {
|
|
524
|
+
const {
|
|
525
|
+
enable,
|
|
526
|
+
disable,
|
|
527
|
+
status,
|
|
528
|
+
supportedChains,
|
|
529
|
+
isLoading,
|
|
530
|
+
error,
|
|
531
|
+
refetch,
|
|
532
|
+
} = useAutoConfirm();
|
|
533
|
+
|
|
534
|
+
const handleEnable = async () => {
|
|
383
535
|
try {
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
|
|
388
|
-
value: parseEther("0.001"), // 0.001 ETH
|
|
389
|
-
gas: 21000n,
|
|
390
|
-
gasPrice: parseGwei("20"), // 20 gwei
|
|
391
|
-
},
|
|
536
|
+
// Enable auto-confirm for specific chains
|
|
537
|
+
const result = await enable({
|
|
538
|
+
chains: [NetworkId.SOLANA_DEVNET, NetworkId.ETHEREUM_MAINNET]
|
|
392
539
|
});
|
|
393
|
-
console.log("
|
|
540
|
+
console.log("Auto-confirm enabled:", result);
|
|
394
541
|
} catch (err) {
|
|
395
|
-
console.error("Failed to
|
|
542
|
+
console.error("Failed to enable auto-confirm:", err);
|
|
396
543
|
}
|
|
397
544
|
};
|
|
398
545
|
|
|
546
|
+
const handleDisable = async () => {
|
|
547
|
+
try {
|
|
548
|
+
await disable();
|
|
549
|
+
console.log("Auto-confirm disabled");
|
|
550
|
+
} catch (err) {
|
|
551
|
+
console.error("Failed to disable auto-confirm:", err);
|
|
552
|
+
}
|
|
553
|
+
};
|
|
554
|
+
|
|
555
|
+
if (isLoading) {
|
|
556
|
+
return <div>Loading auto-confirm settings...</div>;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
if (error) {
|
|
560
|
+
return <div>Error: {error.message}</div>;
|
|
561
|
+
}
|
|
562
|
+
|
|
399
563
|
return (
|
|
400
|
-
<
|
|
401
|
-
|
|
402
|
-
|
|
564
|
+
<div>
|
|
565
|
+
<h3>Auto-Confirm Settings</h3>
|
|
566
|
+
|
|
567
|
+
<div>
|
|
568
|
+
<strong>Status:</strong> {status?.enabled ? "Enabled" : "Disabled"}
|
|
569
|
+
{status?.chains && (
|
|
570
|
+
<div>
|
|
571
|
+
<strong>Active Chains:</strong>
|
|
572
|
+
<ul>
|
|
573
|
+
{status.chains.map((chain) => (
|
|
574
|
+
<li key={chain}>{chain}</li>
|
|
575
|
+
))}
|
|
576
|
+
</ul>
|
|
577
|
+
</div>
|
|
578
|
+
)}
|
|
579
|
+
</div>
|
|
580
|
+
|
|
581
|
+
<div>
|
|
582
|
+
<strong>Supported Chains:</strong>
|
|
583
|
+
{supportedChains?.chains && (
|
|
584
|
+
<ul>
|
|
585
|
+
{supportedChains.chains.map((chain) => (
|
|
586
|
+
<li key={chain}>{chain}</li>
|
|
587
|
+
))}
|
|
588
|
+
</ul>
|
|
589
|
+
)}
|
|
590
|
+
</div>
|
|
591
|
+
|
|
592
|
+
<div>
|
|
593
|
+
<button onClick={handleEnable} disabled={isLoading}>
|
|
594
|
+
Enable Auto-Confirm
|
|
595
|
+
</button>
|
|
596
|
+
<button onClick={handleDisable} disabled={isLoading}>
|
|
597
|
+
Disable Auto-Confirm
|
|
598
|
+
</button>
|
|
599
|
+
<button onClick={refetch} disabled={isLoading}>
|
|
600
|
+
Refresh Status
|
|
601
|
+
</button>
|
|
602
|
+
</div>
|
|
603
|
+
</div>
|
|
403
604
|
);
|
|
404
605
|
}
|
|
405
606
|
```
|
|
406
607
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
### Supported Networks
|
|
608
|
+
**Hook Interface:**
|
|
410
609
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
610
|
+
```typescript
|
|
611
|
+
interface UseAutoConfirmResult {
|
|
612
|
+
enable: (params: AutoConfirmEnableParams) => Promise<AutoConfirmResult>;
|
|
613
|
+
disable: () => Promise<void>;
|
|
614
|
+
status: AutoConfirmResult | null;
|
|
615
|
+
supportedChains: AutoConfirmSupportedChainsResult | null;
|
|
616
|
+
isLoading: boolean;
|
|
617
|
+
error: Error | null;
|
|
618
|
+
refetch: () => Promise<void>;
|
|
619
|
+
}
|
|
420
620
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
- `NetworkId.ARBITRUM_ONE`
|
|
425
|
-
- `NetworkId.OPTIMISM_MAINNET`
|
|
426
|
-
- `NetworkId.BASE_MAINNET`
|
|
621
|
+
interface AutoConfirmEnableParams {
|
|
622
|
+
chains?: NetworkId[]; // Optional array of chains to enable
|
|
623
|
+
}
|
|
427
624
|
|
|
428
|
-
|
|
625
|
+
interface AutoConfirmResult {
|
|
626
|
+
enabled: boolean;
|
|
627
|
+
chains: NetworkId[];
|
|
628
|
+
}
|
|
429
629
|
|
|
430
|
-
|
|
431
|
-
|
|
630
|
+
interface AutoConfirmSupportedChainsResult {
|
|
631
|
+
chains: NetworkId[];
|
|
632
|
+
}
|
|
633
|
+
```
|
|
432
634
|
|
|
433
|
-
|
|
635
|
+
**Available Methods:**
|
|
434
636
|
|
|
435
|
-
- `
|
|
436
|
-
- `
|
|
437
|
-
- `
|
|
637
|
+
- `enable(params)` - Enable auto-confirm for specific chains
|
|
638
|
+
- `disable()` - Disable auto-confirm completely
|
|
639
|
+
- `refetch()` - Refresh status and supported chains from extension
|
|
640
|
+
- `status` - Current auto-confirm status (enabled/disabled and active chains)
|
|
641
|
+
- `supportedChains` - List of chains that support auto-confirm
|
|
642
|
+
- `isLoading` - Loading state for operations
|
|
643
|
+
- `error` - Any errors from auto-confirm operations
|
|
438
644
|
|
|
439
|
-
|
|
645
|
+
**Usage Notes:**
|
|
440
646
|
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
647
|
+
- Auto-confirm automatically fetches status and supported chains when the hook initializes
|
|
648
|
+
- Only works with injected provider (Phantom extension)
|
|
649
|
+
- Throws errors for embedded providers
|
|
650
|
+
- Status is automatically updated after enable/disable operations
|
|
651
|
+
- Use `refetch()` to manually refresh data from the extension
|
|
445
652
|
|
|
446
653
|
## Transaction Examples
|
|
447
654
|
|
|
@@ -449,10 +656,10 @@ The SDK automatically determines the transaction type from the NetworkId:
|
|
|
449
656
|
|
|
450
657
|
```tsx
|
|
451
658
|
import { VersionedTransaction, TransactionMessage, SystemProgram, PublicKey, Connection } from "@solana/web3.js";
|
|
452
|
-
import {
|
|
659
|
+
import { useSolana } from "@phantom/react-sdk";
|
|
453
660
|
|
|
454
661
|
function SolanaExample() {
|
|
455
|
-
const
|
|
662
|
+
const solana = useSolana();
|
|
456
663
|
|
|
457
664
|
const sendTransaction = async () => {
|
|
458
665
|
// Get recent blockhash
|
|
@@ -460,6 +667,7 @@ function SolanaExample() {
|
|
|
460
667
|
const { blockhash } = await connection.getLatestBlockhash();
|
|
461
668
|
|
|
462
669
|
// Create transfer instruction
|
|
670
|
+
const fromAddress = await solana.getPublicKey();
|
|
463
671
|
const transferInstruction = SystemProgram.transfer({
|
|
464
672
|
fromPubkey: new PublicKey(fromAddress),
|
|
465
673
|
toPubkey: new PublicKey(toAddress),
|
|
@@ -475,12 +683,12 @@ function SolanaExample() {
|
|
|
475
683
|
|
|
476
684
|
const transaction = new VersionedTransaction(messageV0);
|
|
477
685
|
|
|
478
|
-
//
|
|
479
|
-
const result = await signAndSendTransaction(
|
|
480
|
-
|
|
481
|
-
transaction,
|
|
482
|
-
});
|
|
686
|
+
// Sign and send using chain-specific hook
|
|
687
|
+
const result = await solana.signAndSendTransaction(transaction);
|
|
688
|
+
console.log("Transaction sent:", result.hash);
|
|
483
689
|
};
|
|
690
|
+
|
|
691
|
+
return <button onClick={sendTransaction}>Send SOL</button>;
|
|
484
692
|
}
|
|
485
693
|
```
|
|
486
694
|
|
|
@@ -496,15 +704,16 @@ import {
|
|
|
496
704
|
address,
|
|
497
705
|
compileTransaction,
|
|
498
706
|
} from "@solana/kit";
|
|
499
|
-
import {
|
|
707
|
+
import { useSolana } from "@phantom/react-sdk";
|
|
500
708
|
|
|
501
709
|
function SolanaKitExample() {
|
|
502
|
-
const
|
|
710
|
+
const solana = useSolana();
|
|
503
711
|
|
|
504
712
|
const sendTransaction = async () => {
|
|
505
713
|
const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");
|
|
506
714
|
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
|
|
507
715
|
|
|
716
|
+
const userPublicKey = await solana.getPublicKey();
|
|
508
717
|
const transactionMessage = pipe(
|
|
509
718
|
createTransactionMessage({ version: 0 }),
|
|
510
719
|
tx => setTransactionMessageFeePayer(address(userPublicKey), tx),
|
|
@@ -513,11 +722,12 @@ function SolanaKitExample() {
|
|
|
513
722
|
|
|
514
723
|
const transaction = compileTransaction(transactionMessage);
|
|
515
724
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
});
|
|
725
|
+
// Sign and send using chain-specific hook
|
|
726
|
+
const result = await solana.signAndSendTransaction(transaction);
|
|
727
|
+
console.log("Transaction sent:", result.hash);
|
|
520
728
|
};
|
|
729
|
+
|
|
730
|
+
return <button onClick={sendTransaction}>Send SOL</button>;
|
|
521
731
|
}
|
|
522
732
|
```
|
|
523
733
|
|
|
@@ -525,96 +735,40 @@ function SolanaKitExample() {
|
|
|
525
735
|
|
|
526
736
|
```tsx
|
|
527
737
|
import { parseEther, parseGwei, encodeFunctionData } from "viem";
|
|
528
|
-
import {
|
|
738
|
+
import { useEthereum } from "@phantom/react-sdk";
|
|
529
739
|
|
|
530
740
|
function EthereumExample() {
|
|
531
|
-
const
|
|
741
|
+
const ethereum = useEthereum();
|
|
532
742
|
|
|
533
743
|
const sendEth = async () => {
|
|
534
|
-
const result = await
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
gas: 21000n,
|
|
540
|
-
gasPrice: parseGwei("20"), // 20 gwei
|
|
541
|
-
},
|
|
744
|
+
const result = await ethereum.sendTransaction({
|
|
745
|
+
to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
|
|
746
|
+
value: parseEther("1").toString(), // 1 ETH
|
|
747
|
+
gas: "21000",
|
|
748
|
+
gasPrice: parseGwei("20").toString(), // 20 gwei
|
|
542
749
|
});
|
|
750
|
+
console.log("ETH sent:", result.hash);
|
|
543
751
|
};
|
|
544
752
|
|
|
545
753
|
const sendToken = async () => {
|
|
546
|
-
const result = await
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
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
|
-
},
|
|
754
|
+
const result = await ethereum.sendTransaction({
|
|
755
|
+
to: tokenContractAddress,
|
|
756
|
+
data: encodeFunctionData({
|
|
757
|
+
abi: erc20Abi,
|
|
758
|
+
functionName: "transfer",
|
|
759
|
+
args: [recipientAddress, parseEther("100")],
|
|
760
|
+
}),
|
|
761
|
+
gas: "50000",
|
|
762
|
+
maxFeePerGas: parseGwei("30").toString(),
|
|
763
|
+
maxPriorityFeePerGas: parseGwei("2").toString(),
|
|
611
764
|
});
|
|
765
|
+
console.log("Token sent:", result.hash);
|
|
612
766
|
};
|
|
613
767
|
|
|
614
768
|
return (
|
|
615
769
|
<div>
|
|
616
|
-
<button onClick={
|
|
617
|
-
<button onClick={
|
|
770
|
+
<button onClick={sendEth}>Send ETH</button>
|
|
771
|
+
<button onClick={sendToken}>Send Token</button>
|
|
618
772
|
</div>
|
|
619
773
|
);
|
|
620
774
|
}
|
|
@@ -630,8 +784,9 @@ Quick reference of all available hooks:
|
|
|
630
784
|
| `useAccounts` | Get wallet addresses | `WalletAddress[]` or `null` |
|
|
631
785
|
| `useIsExtensionInstalled` | Check extension status | `{ isLoading, isInstalled }` |
|
|
632
786
|
| `useDisconnect` | Disconnect from wallet | `{ disconnect, isDisconnecting }` |
|
|
633
|
-
| `
|
|
634
|
-
| `
|
|
787
|
+
| `useAutoConfirm` | Auto-confirm management (injected only) | `{ enable, disable, status, supportedChains, ... }` |
|
|
788
|
+
| `useSolana` | Solana chain operations | `{ signMessage, signAndSendTransaction, ... }` |
|
|
789
|
+
| `useEthereum` | Ethereum chain operations | `{ signPersonalMessage, sendTransaction, ... }`|
|
|
635
790
|
| `usePhantom` | Get provider context | `{ isConnected, isReady }` |
|
|
636
791
|
|
|
637
792
|
## Configuration Reference
|
|
@@ -719,4 +874,4 @@ interface DebugMessage {
|
|
|
719
874
|
}
|
|
720
875
|
```
|
|
721
876
|
|
|
722
|
-
For more details
|
|
877
|
+
For more details and examples, see the [@phantom/browser-sdk documentation](../browser-sdk/README.md).
|