Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion skills/solana-dev/references/frontend.md
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ export function useBalance(accountAddress?: Address) {
}
```

**Multi-cluster apps:** include the cluster in the cache key, and derive it from the same source that built the client — the client is typically rebuilt one render *after* the selection flips, so a key read from selection state binds the new network's fetch to the previous network's `rpc`. The [Kit example app](https://github.com/anza-xyz/kit/blob/main/examples/react-app/src/components/Balance.tsx) stamps `chain` onto the client with `extendClient` and reads it back off `useClient()` to keep the two in lockstep.
**Multi-cluster apps:** include the cluster in the cache key, and derive it from the same source that built the client — the client is typically rebuilt one render *after* the selection flips, so a key read from selection state binds the new network's fetch to the previous network's `rpc`. The [Kit example app](https://github.com/anza-xyz/kit/blob/main/examples/react-app/src/components/Balance.tsx) stamps `chain` onto the client with `extendClient` and reads it back off `useClient<AppClient>()` to keep the two in lockstep.

Render lamports with the Kit helpers rather than dividing by `1e9`:

Expand Down
4 changes: 3 additions & 1 deletion skills/solana-dev/references/kit/advanced.md
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,9 @@ await airdrop({

**Accounts**: `getAccountInfo`, `getMultipleAccounts`, `getBalance`, `getTokenAccountBalance`, `getTokenAccountsByOwner`, `getProgramAccounts`

**Transactions**: `sendTransaction`, `simulateTransaction`, `getTransaction`, `getSignatureStatuses`, `getSignaturesForAddress`
**Transactions**: `sendTransaction`, `simulateTransaction`, `getTransaction`, `getSignatureStatuses`, `getSignaturesForAddress`, `getTransactionsForAddress`

`getTransactionsForAddress` (`@solana/kit` 7.1+) combines address-history discovery and per-transaction fetching into a single query, with server-side filtering, bidirectional sorting, and cursor-based pagination — replacing a `getSignaturesForAddress` + N× `getTransaction` fan-out. It supports a `signatures`-only mode and a `full` mode (`json` / `jsonParsed` / `base58` / `base64`). It is part of the upcoming solana-rpc spec (`solana-rpc/superbank`) and is already available from major RPC providers, but is not yet universally supported — check the target endpoint before relying on it. Transaction metadata (from `getTransactionsForAddress` and `getTransaction`) also gained an optional `meta.costUnits` field.

**Blocks**: `getBlock`, `getBlockHeight`, `getSlot`, `getLatestBlockhash`, `isBlockhashValid`

Expand Down
55 changes: 53 additions & 2 deletions skills/solana-dev/references/kit/react.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export function Providers({ children }: { children: React.ReactNode }) {
}
```

Always pass your client type to `useClient` — a bare `useClient()` gives you an untyped `Client<object>` (and the type parameter is expected to become required):
Always pass your client type to `useClient` — as of `@solana/react` 7.1+, the `TClient` type parameter is required, so a bare `useClient()` fails to compile:

```tsx
import { useClient } from '@solana/react';
Expand All @@ -60,6 +60,8 @@ function Balance({ address }: { address: Address }) {

For caching, revalidation, and request dedup, prefer the framework adapters: `@solana/react/swr` (`useRequestSWR`, `useSubscriptionSWR`, `useTrackedDataSWR`) and `@solana/react/query` (`useRequestQuery`, `useSubscriptionQuery`, `useTrackedDataQuery`). Both are optional peer deps — install `swr` or `@tanstack/react-query` yourself.

As of `@solana/react` 7.1+, `useSubscriptionQuery` / `useTrackedDataQuery` (the TanStack Query adapters) surface a new error, `SOLANA_ERROR__SUBSCRIBABLE__STREAM_CLOSED_WITHOUT_ERROR`, when the underlying stream store closes in an error state with a nullish payload. The SWR adapters are unaffected.

### useTrackedData / useTrackedDataSWR / useTrackedDataQuery

Use these for any live account value (balances, token accounts, program state). The hook fires the initial RPC read and the subscription together and slot-dedupes them, so the first paint is fast and out-of-order arrivals never regress the surfaced value. Do **not** hand-roll a `getBalance` + `accountNotifications` pair.
Expand Down Expand Up @@ -109,12 +111,61 @@ const { dispatch, dispatchAsync, data, error, isRunning, reset } = useAction(
```

- `dispatch` returns `void` and never throws — the variant for `onClick`. `dispatchAsync` resolves the value or rejects.
- Dispatching while a call is in flight aborts the first via its `AbortSignal`. Awaiters of the superseded `dispatchAsync` see an `AbortError`, filterable with `isAbortError` from `@solana/promises`, which `@solana/kit` 7 does not re-export — install that package explicitly if you need it. Sticking to `dispatch` where you can avoids the question entirely.
- Dispatching while a call is in flight aborts the first via its `AbortSignal`. Awaiters of the superseded `dispatchAsync` see an `AbortError`, filterable with `isAbortError`, importable directly from `@solana/kit` (7.1+ re-exports `@solana/promises`). Sticking to `dispatch` where you can avoids the question entirely.
- `data` and `error` persist through subsequent `running` states for stale-while-revalidate UX; only `reset()` clears `data`.
- `fn` is held in a ref pointing at the latest render's closure — no deps array.

Most of the wallet plugin's action hooks (`useConnect`, `useDisconnect`, `useSignIn`, `useSignMessage`) are built on this and expose the same shape.

## Client Capability Hooks (requires `@solana/react` 7.1+)

These read off whichever plugin capabilities the client advertises. Each takes the client as its only argument.

### usePayer / useIdentity

`usePayer(client)` reads `client.payer`; `useIdentity(client)` reads `client.identity`. Both return the current `TransactionSigner`, or `undefined` while none is available.

```tsx
const payer = usePayer(client);
const identity = useIdentity(client);
return <span>{payer ? `Paying with ${payer.address}` : 'No payer'}</span>;
```

- When the client advertises `subscribeToPayer` / `subscribeToIdentity`, the hook subscribes so the returned signer always reflects the latest value. Otherwise it falls back to a one-time read.
- **Gotcha:** if reading the underlying value throws — as the wallet plugin does for `payer`/`identity` when it owns those roles and no wallet is connected — the hook surfaces `undefined` rather than throwing.

### usePlanTransaction / usePlanTransactions / useSendTransaction / useSendTransactions

Wrap a client's transaction planning/sending capabilities as `useAction`-style reactive actions — same `dispatch` / `dispatchAsync` / `data` / `error` / `isRunning` shape as `useAction`.

| Hook | Wraps | `dispatch` args | Resolves with |
|------|-------|------------------|----------------|
| `usePlanTransaction(client)` | `client.planTransaction` | instruction input | the planned transaction message |
| `usePlanTransactions(client)` | `client.planTransactions` | instruction input | the full transaction plan (may span multiple transactions) |
| `useSendTransaction(client)` | `client.sendTransaction` | instructions, an instruction plan, a transaction message, or a transaction plan | the successful single-transaction-plan result |
| `useSendTransactions(client)` | `client.sendTransactions` | instructions, an instruction plan, or a transaction plan | the transaction plan result for all transactions |

```tsx
const { dispatch, data, isRunning } = useSendTransaction(client);
<button disabled={isRunning} onClick={() => dispatch(instructions)}>Send</button>
```

Use the singular hooks when you expect everything to fit in one transaction; reach for the plural hooks when instructions might need splitting across transactions.

### useAirdrop

Wraps a client's `airdrop` capability (`ClientWithAirdrop`) as a tracked `useAction`. `dispatch(address, amount)` requests an airdrop with an injected `AbortSignal` and resolves with the transaction `Signature`, or `undefined` when the airdrop was applied without a transaction (e.g. some local-validator implementations update balances directly, with no transaction to sign).

```tsx
import { useAirdrop } from '@solana/react';
import { lamports } from '@solana/kit';

const { dispatch, isRunning } = useAirdrop(client);
<button disabled={isRunning} onClick={() => dispatch(address, lamports(1_000_000_000n))}>
Airdrop 1 SOL
</button>
```

## Wallet Hooks (`@solana/kit-plugin-wallet/react`)

Requires `@solana/kit-plugin-wallet` 0.14+ and the `walletSigner` (or `walletWithoutSigner`) plugin on the client. Every hook takes the wallet-enabled `client` as its first argument, keeping the app fully typed end-to-end.
Expand Down
2 changes: 2 additions & 0 deletions skills/solana-dev/references/rpc-quick-lookups.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ curl -s https://api.mainnet-beta.solana.com -X POST \
-d '{"jsonrpc":"2.0","id":1,"method":"getSignaturesForAddress","params":["<PUBKEY>",{"limit":10}]}'
```

If the endpoint supports it, `getTransactionsForAddress` replaces this call plus the follow-up `getTransaction` fan-out with one query — it does address-history discovery and per-transaction fetching together, with server-side filtering, bidirectional sorting, cursor pagination, and both `signatures`-only and `full` (`json`/`jsonParsed`/`base58`/`base64`) response modes. It's part of the upcoming solana-rpc spec and already live at major RPC providers, but not yet universally available — check the target endpoint before assuming it's there.

### Cluster liveness — `getSlot` / `getHealth`

Quick sanity check that the endpoint is reachable.
Expand Down