@solana/react-hooks 0.0.0 → 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 +114 -25
- package/dist/index.browser.cjs +1333 -0
- package/dist/index.browser.cjs.map +1 -0
- package/dist/index.browser.mjs +1294 -0
- package/dist/index.browser.mjs.map +1 -0
- package/dist/index.native.mjs +1294 -0
- package/dist/index.native.mjs.map +1 -0
- package/dist/index.node.cjs +1333 -0
- package/dist/index.node.cjs.map +1 -0
- package/dist/index.node.mjs +1294 -0
- package/dist/index.node.mjs.map +1 -0
- package/dist/types/QueryProvider.d.ts +11 -0
- package/dist/types/QueryProvider.d.ts.map +1 -0
- package/dist/types/SolanaProvider.d.ts +35 -0
- package/dist/types/SolanaProvider.d.ts.map +1 -0
- package/dist/types/context.d.ts +22 -0
- package/dist/types/context.d.ts.map +1 -0
- package/dist/types/hooks.d.ts +208 -0
- package/dist/types/hooks.d.ts.map +1 -0
- package/dist/types/index.d.ts +10 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/query.d.ts +20 -0
- package/dist/types/query.d.ts.map +1 -0
- package/dist/types/queryHooks.d.ts +43 -0
- package/dist/types/queryHooks.d.ts.map +1 -0
- package/dist/types/querySuspenseContext.d.ts +4 -0
- package/dist/types/querySuspenseContext.d.ts.map +1 -0
- package/dist/types/ui.d.ts +52 -0
- package/dist/types/ui.d.ts.map +1 -0
- package/dist/types/useClientStore.d.ts +6 -0
- package/dist/types/useClientStore.d.ts.map +1 -0
- package/dist/types/walletStandardHooks.d.ts +78 -0
- package/dist/types/walletStandardHooks.d.ts.map +1 -0
- package/package.json +88 -84
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @solana/react-hooks
|
|
2
2
|
|
|
3
|
-
React hooks for `@solana/client
|
|
3
|
+
React hooks for `@solana/client`. Drop in the provider and call hooks instead of juggling RPC
|
|
4
4
|
clients, wallets, and stores yourself.
|
|
5
5
|
|
|
6
6
|
> **Status:** Experimental – breaking changes may land often.
|
|
@@ -59,6 +59,8 @@ export function App() {
|
|
|
59
59
|
- `useBalance` / `useAccount` – fetch lamports once or keep account data in sync.
|
|
60
60
|
- `useSolTransfer`, `useSplToken`, `useTransactionPool` – helper-driven flows for SOL, SPL, and
|
|
61
61
|
general transactions.
|
|
62
|
+
- `useSendTransaction` – prepare and submit arbitrary instructions with shared mutation state.
|
|
63
|
+
- `useSignatureStatus`, `useWaitForSignature` – declarative helpers for tracking confirmations.
|
|
62
64
|
- `useClientStore` – access the underlying Zustand store if you need low-level state.
|
|
63
65
|
|
|
64
66
|
### Wallet helpers
|
|
@@ -178,7 +180,7 @@ const SplBalance = ({ mint }) => {
|
|
|
178
180
|
Compose instructions, refresh blockhashes automatically, and send transactions from one hook.
|
|
179
181
|
|
|
180
182
|
```tsx
|
|
181
|
-
import type { TransactionInstructionInput } from '@solana/client
|
|
183
|
+
import type { TransactionInstructionInput } from '@solana/client';
|
|
182
184
|
|
|
183
185
|
const useMemoizedInstruction = (): TransactionInstructionInput => ({
|
|
184
186
|
accounts: [],
|
|
@@ -220,48 +222,136 @@ function ClusterStatus() {
|
|
|
220
222
|
}
|
|
221
223
|
```
|
|
222
224
|
|
|
225
|
+
### General transaction sender
|
|
226
|
+
|
|
227
|
+
Use `useSendTransaction` when you already have instructions/messages and just need a mutation helper
|
|
228
|
+
that exposes `{ send, sendPrepared, status, error, signature }`. When no authority is supplied, it
|
|
229
|
+
will use the currently connected wallet session by default.
|
|
230
|
+
|
|
231
|
+
```tsx
|
|
232
|
+
import { useSendTransaction } from '@solana/react-hooks';
|
|
233
|
+
|
|
234
|
+
function SendAnythingButton({ instructions }) {
|
|
235
|
+
const { send, isSending, signature, error } = useSendTransaction();
|
|
236
|
+
|
|
237
|
+
return (
|
|
238
|
+
<div>
|
|
239
|
+
<button disabled={isSending} onClick={() => send({ instructions })}>
|
|
240
|
+
{isSending ? 'Submitting…' : 'Send transaction'}
|
|
241
|
+
</button>
|
|
242
|
+
{signature ? <p>Signature: {signature}</p> : null}
|
|
243
|
+
{error ? <p role="alert">Failed to send: {String(error)}</p> : null}
|
|
244
|
+
</div>
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Signature helpers
|
|
250
|
+
|
|
251
|
+
Poll RPC for signature metadata or wait for a confirmation level without writing loops.
|
|
252
|
+
|
|
253
|
+
```tsx
|
|
254
|
+
import { useSignatureStatus, useWaitForSignature } from '@solana/react-hooks';
|
|
255
|
+
|
|
256
|
+
function SignatureStatusCard({ signature }) {
|
|
257
|
+
const status = useSignatureStatus(signature);
|
|
258
|
+
|
|
259
|
+
if (status.isLoading) return <p>Loading…</p>;
|
|
260
|
+
if (status.isError) return <p>RPC error.</p>;
|
|
261
|
+
|
|
262
|
+
return (
|
|
263
|
+
<div>
|
|
264
|
+
<p>Confirmation: {status.confirmationStatus ?? 'pending'}</p>
|
|
265
|
+
<button onClick={() => status.refresh()}>Refresh</button>
|
|
266
|
+
</div>
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function WaitForSignature({ signature }) {
|
|
271
|
+
const wait = useWaitForSignature(signature, { commitment: 'finalized' });
|
|
272
|
+
|
|
273
|
+
if (wait.waitStatus === 'error') return <p role="alert">Failed: {JSON.stringify(wait.waitError)}</p>;
|
|
274
|
+
if (wait.waitStatus === 'success') return <p>Finalized!</p>;
|
|
275
|
+
if (wait.waitStatus === 'waiting') return <p>Waiting for confirmation…</p>;
|
|
276
|
+
return <p>Provide a signature</p>;
|
|
277
|
+
}
|
|
278
|
+
```
|
|
279
|
+
|
|
223
280
|
## Query hooks
|
|
224
281
|
|
|
225
282
|
Wrap a subtree with `<SolanaQueryProvider>` and call hooks like `useLatestBlockhash`,
|
|
226
|
-
`useProgramAccounts`, or `useSimulateTransaction`. Every hook returns
|
|
227
|
-
you can read the current value and trigger a refetch
|
|
283
|
+
`useProgramAccounts`, `useSignatureStatus`, or `useSimulateTransaction`. Every hook returns
|
|
284
|
+
`{ data, status, refresh }` so you can read the current value and trigger a refetch. Want to lean on React
|
|
285
|
+
Suspense later? Pass `suspense` to `SolanaQueryProvider` and wrap just the section that should pause in a
|
|
286
|
+
local `<Suspense>` boundary—no hook changes required:
|
|
287
|
+
|
|
288
|
+
```tsx
|
|
289
|
+
import { SolanaQueryProvider, useBalance } from '@solana/react-hooks';
|
|
290
|
+
import { Suspense } from 'react';
|
|
291
|
+
|
|
292
|
+
function BalanceDetails({ address }: { address: string }) {
|
|
293
|
+
const balance = useBalance(address);
|
|
294
|
+
return <p>Lamports: {balance.lamports?.toString() ?? '0'}</p>;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
export function WalletPanel({ address }: { address: string }) {
|
|
298
|
+
return (
|
|
299
|
+
<SolanaQueryProvider suspense>
|
|
300
|
+
{/* Only this block suspends while balance loads */}
|
|
301
|
+
<Suspense fallback={<p>Loading balance…</p>}>
|
|
302
|
+
<BalanceDetails address={address} />
|
|
303
|
+
</Suspense>
|
|
304
|
+
</SolanaQueryProvider>
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
```
|
|
228
308
|
|
|
229
309
|
### Latest blockhash
|
|
230
310
|
|
|
231
311
|
Poll or refetch the cluster's latest blockhash.
|
|
232
312
|
|
|
233
313
|
```tsx
|
|
234
|
-
import { useLatestBlockhash } from '@solana/react-hooks';
|
|
314
|
+
import { SolanaQueryProvider, useLatestBlockhash } from '@solana/react-hooks';
|
|
235
315
|
|
|
236
316
|
function BlockhashTicker() {
|
|
237
|
-
const
|
|
317
|
+
const latest = useLatestBlockhash({ refreshInterval: 20_000 });
|
|
318
|
+
if (latest.status === 'loading') return <p>Fetching blockhash…</p>;
|
|
319
|
+
if (latest.status === 'error') return <p role="alert">Failed to fetch blockhash.</p>;
|
|
238
320
|
|
|
239
321
|
return (
|
|
240
322
|
<div>
|
|
241
|
-
<button onClick={() => refresh()}>Refresh</button>
|
|
242
|
-
<p>Status: {status}</p>
|
|
243
|
-
<p>Blockhash: {blockhash ?? '
|
|
323
|
+
<button onClick={() => latest.refresh()}>Refresh</button>
|
|
324
|
+
<p>Status: {latest.status}</p>
|
|
325
|
+
<p>Blockhash: {latest.blockhash ?? 'unknown'}</p>
|
|
244
326
|
</div>
|
|
245
327
|
);
|
|
246
328
|
}
|
|
329
|
+
|
|
330
|
+
export function BlockhashCard() {
|
|
331
|
+
return (
|
|
332
|
+
<SolanaQueryProvider>
|
|
333
|
+
<BlockhashTicker />
|
|
334
|
+
</SolanaQueryProvider>
|
|
335
|
+
);
|
|
336
|
+
}
|
|
247
337
|
```
|
|
248
338
|
|
|
249
339
|
### Program accounts
|
|
250
340
|
|
|
251
341
|
```tsx
|
|
252
|
-
import { SolanaQueryProvider, useProgramAccounts } from '@solana/react-hooks';
|
|
342
|
+
import { SolanaClientProvider, SolanaQueryProvider, useProgramAccounts } from '@solana/react-hooks';
|
|
253
343
|
|
|
254
344
|
function ProgramAccountsList({ programAddress }) {
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
if (status === '
|
|
258
|
-
if (status === 'error') return <p>Retry later.</p>;
|
|
345
|
+
const query = useProgramAccounts(programAddress);
|
|
346
|
+
if (query.status === 'loading') return <p>Loading accounts…</p>;
|
|
347
|
+
if (query.status === 'error') return <p role="alert">Retry later.</p>;
|
|
259
348
|
|
|
260
349
|
return (
|
|
261
350
|
<div>
|
|
262
|
-
<button onClick={() => refresh()}>Refresh</button>
|
|
351
|
+
<button onClick={() => query.refresh()}>Refresh</button>
|
|
352
|
+
<p>Status: {query.status}</p>
|
|
263
353
|
<ul>
|
|
264
|
-
{
|
|
354
|
+
{query.accounts?.map(({ pubkey }) => (
|
|
265
355
|
<li key={pubkey.toString()}>{pubkey.toString()}</li>
|
|
266
356
|
))}
|
|
267
357
|
</ul>
|
|
@@ -288,15 +378,14 @@ Simulate any transaction payload (wire string or object) and read RPC logs.
|
|
|
288
378
|
import { useSimulateTransaction } from '@solana/react-hooks';
|
|
289
379
|
|
|
290
380
|
function SimulationLogs({ transaction }) {
|
|
291
|
-
const
|
|
292
|
-
|
|
293
|
-
if (status === '
|
|
294
|
-
if (status === 'error') return <p>Simulation failed.</p>;
|
|
295
|
-
|
|
381
|
+
const query = useSimulateTransaction(transaction);
|
|
382
|
+
if (query.status === 'loading') return <p>Simulating…</p>;
|
|
383
|
+
if (query.status === 'error') return <p role="alert">Simulation failed.</p>;
|
|
296
384
|
return (
|
|
297
385
|
<div>
|
|
298
|
-
<button onClick={() => refresh()}>Re-run</button>
|
|
299
|
-
<
|
|
386
|
+
<button onClick={() => query.refresh()}>Re-run</button>
|
|
387
|
+
<p>Status: {query.status}</p>
|
|
388
|
+
<pre>{JSON.stringify(query.logs, null, 2)}</pre>
|
|
300
389
|
</div>
|
|
301
390
|
);
|
|
302
391
|
}
|
|
@@ -306,8 +395,8 @@ function SimulationLogs({ transaction }) {
|
|
|
306
395
|
|
|
307
396
|
- Need Wallet Standard buttons or sign/send helpers? Use `useSignIn`, `useSignMessage`,
|
|
308
397
|
`useSignTransaction`, and friends from `walletStandardHooks.ts`.
|
|
309
|
-
- Looking for examples? See `examples/react-hooks` for a ready-to-run playground that wires
|
|
310
|
-
provider, hooks, and mock UIs together.
|
|
398
|
+
- Looking for examples? See `examples/react-hooks` for a ready-to-run, tabbed playground that wires
|
|
399
|
+
the provider, hooks, and mock UIs together across wallet/state, transaction, and query demos.
|
|
311
400
|
|
|
312
401
|
## Scripts
|
|
313
402
|
|