@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  # @solana/react-hooks
2
2
 
3
- React hooks for `@solana/client-core`. Drop in the provider and call hooks instead of juggling RPC
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-core';
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 `{ data, status, refresh }` so
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 { blockhash, status, refresh } = useLatestBlockhash({ refreshInterval: 20_000 });
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 ?? 'loading…'}</p>
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 { data, status, refresh } = useProgramAccounts(programAddress);
256
-
257
- if (status === 'loading') return <p>Loading…</p>;
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
- {data?.map(({ pubkey }) => (
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 { logs, status, refresh } = useSimulateTransaction(transaction);
292
-
293
- if (status === 'loading') return <p>Simulating…</p>;
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
- <pre>{JSON.stringify(logs ?? [], null, 2)}</pre>
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 the
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