Data Fetching Hooks
Hooks for fetching data from the Solana blockchain
These hooks provide easy access to common Solana blockchain data with automatic caching, refetching, and error handling.
useAccount
Get the account info for an address using the Solana RPC method
getAccountInfo.
Usage
"use client";
import { useAccount } from "@gillsdk/react";
export function AccountInfo() {
const { account, isLoading, isError, error } = useAccount({
address: "nicktrLHhYzLmoVbuZQzHUTicd2sfP571orwo9jfc8c",
});
if (isLoading) return <div>Loading...</div>;
if (isError) return <div>Error: {error?.message}</div>;
return (
<div>
<pre>{JSON.stringify(account, null, 2)}</pre>
</div>
);
}With Decoder
Fetch and decode an account's data into a typed object using an appropriate decoder function:
"use client";
import { useAccount } from "@gillsdk/react";
import { getMintDecoder } from "gill/programs";
export function MintInfo() {
const { account, isLoading } = useAccount({
// USDC mint account on mainnet
address: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
decoder: getMintDecoder(),
});
if (isLoading) return <div>Loading...</div>;
return (
<div>
<p>Supply: {account?.data?.supply.toString()}</p>
<p>Decimals: {account?.data?.decimals}</p>
</div>
);
}Parameters
interface UseAccountOptions {
address: Address | string;
decoder?: Decoder<T>;
commitment?: Commitment;
minContextSlot?: number;
enabled?: boolean;
// ... other TanStack Query options
}useBalance
Get an account's balance in lamports using
getBalance.
Usage
"use client";
import { lamportsToSol } from "gill";
import { useBalance } from "@gillsdk/react";
export function WalletBalance() {
const { balance, isLoading, isError, error } = useBalance({
address: "nicktrLHhYzLmoVbuZQzHUTicd2sfP571orwo9jfc8c",
});
if (isLoading) return <div>Loading...</div>;
if (isError) return <div>Error: {error?.message}</div>;
return (
<div>
<p>Balance: {lamportsToSol(balance)} SOL</p>
</div>
);
}With Automatic Refetch
const { balance } = useBalance({
address: walletAddress,
refetchInterval: 5000, // Refetch every 5 seconds
refetchOnWindowFocus: true,
});Parameters
interface UseBalanceOptions {
address: Address | string;
commitment?: Commitment;
minContextSlot?: number;
enabled?: boolean;
// ... other TanStack Query options
}useLatestBlockhash
Get the latest blockhash using
getLatestBlockhash.
Usage
"use client";
import { useLatestBlockhash } from "@gillsdk/react";
export function BlockhashDisplay() {
const { latestBlockhash, isLoading } = useLatestBlockhash();
if (isLoading) return <div>Loading...</div>;
return (
<div>
<p>Blockhash: {latestBlockhash?.blockhash}</p>
<p>Last Valid Height: {latestBlockhash?.lastValidBlockHeight}</p>
</div>
);
}For Transactions
const { latestBlockhash } = useLatestBlockhash();
// Use in transaction
const transaction = createTransaction({
blockhash: latestBlockhash.blockhash,
// ... other transaction params
});Parameters
interface UseLatestBlockhashOptions {
commitment?: Commitment;
minContextSlot?: number;
enabled?: boolean;
// ... other TanStack Query options
}useSignatureStatuses
Get the statuses of signatures using
getSignatureStatuses.
Usage
"use client";
import { useSignatureStatuses } from "@gillsdk/react";
export function TransactionStatus({ signature }) {
const { statuses, isLoading } = useSignatureStatuses({
signatures: [signature],
});
if (isLoading) return <div>Checking status...</div>;
const status = statuses?.[0];
return (
<div>
<p>Confirmed: {status?.confirmationStatus}</p>
<p>Confirmations: {status?.confirmations}</p>
{status?.err && <p>Error: {JSON.stringify(status.err)}</p>}
</div>
);
}Multiple Signatures
const { statuses } = useSignatureStatuses({
signatures: [sig1, sig2, sig3],
searchTransactionHistory: true,
});
statuses?.forEach((status, index) => {
console.log(`Signature ${index}:`, status);
});Parameters
interface UseSignatureStatusesOptions {
signatures: string[];
searchTransactionHistory?: boolean;
enabled?: boolean;
// ... other TanStack Query options
}useSignaturesForAddress
Get signatures for confirmed transactions using
getSignaturesForAddress.
Usage
"use client";
import { useSignaturesForAddress } from "@gillsdk/react";
export function TransactionHistory({ address }) {
const { signatures, isLoading } = useSignaturesForAddress({
address,
config: {
limit: 10,
},
});
if (isLoading) return <div>Loading history...</div>;
return (
<ul>
{signatures?.map((sig) => (
<li key={sig.signature}>
<p>Signature: {sig.signature}</p>
<p>Slot: {sig.slot}</p>
<p>Time: {new Date(sig.blockTime * 1000).toLocaleString()}</p>
</li>
))}
</ul>
);
}With Pagination
const { signatures, refetch } = useSignaturesForAddress({
address,
config: {
limit: 20,
before: lastSignature, // For pagination
until: firstSignature,
},
});Parameters
interface UseSignaturesForAddressOptions {
address: Address | string;
config?: {
limit?: number;
before?: string;
until?: string;
commitment?: Commitment;
};
enabled?: boolean;
// ... other TanStack Query options
}useProgramAccounts
Get all accounts owned by a program using the
getProgramAccounts RPC method.
Important getProgramAccounts (GPA) Limitations
getProgramAccountscan return large amounts of data and is resource-intensive- Many RPC providers return errors or have rate limits due to the system load
- Public RPC endpoints often have
getProgramAccountsdisabled entirely - Consider using filters to reduce the data returned and always use a paid RPC provider for production
- For large programs, consider alternative approaches like indexers or specialized APIs
Usage
"use client";
import { useProgramAccounts } from "@gillsdk/react";
export function ProgramAccounts() {
const { accounts, isLoading } = useProgramAccounts({
program: "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
config: {
encoding: "base64",
filters: [
{ dataSize: 165n }, // Token account size
],
},
});
if (isLoading) return <div>Loading accounts...</div>;
return (
<div>
<p>Found {accounts?.length} accounts</p>
</div>
);
}With Memcmp Filter
const { accounts } = useProgramAccounts({
program: programId,
config: {
filters: [
{
memcmp: {
offset: 0n,
bytes: base58.encode(ownerPubkey),
encoding: "base58",
},
},
],
},
});Parameters
interface UseProgramAccountsOptions {
program: Address | string;
config?: {
encoding?: "base64" | "jsonParsed";
filters?: Filter[];
commitment?: Commitment;
minContextSlot?: number;
withContext?: boolean;
};
decoder?: Decoder<T>;
enabled?: boolean;
// ... other TanStack Query options
}useTokenMint
Get a decoded Mint account for a token.
Usage
"use client";
import { useTokenMint } from "@gillsdk/react";
export function TokenInfo() {
const { account, isLoading } = useTokenMint({
// USDC mint on mainnet
mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
});
if (isLoading) return <div>Loading...</div>;
const mintData = account?.data;
return (
<div>
<p>Supply: {mintData?.supply.toString()}</p>
<p>Decimals: {mintData?.decimals}</p>
<p>Mint Authority: {mintData?.mintAuthority?.toString()}</p>
</div>
);
}Parameters
interface UseTokenMintOptions {
mint: Address | string;
commitment?: Commitment;
enabled?: boolean;
// ... other TanStack Query options
}useTokenAccount
Get the decoded Token Account for a given mint and owner, automatically deriving the Associated Token Account (ATA) address:
Usage
"use client";
import { useTokenAccount } from "@gillsdk/react";
export function TokenBalance() {
const { account, isLoading } = useTokenAccount({
mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
owner: "nicktrLHhYzLmoVbuZQzHUTicd2sfP571orwo9jfc8c",
});
if (isLoading) return <div>Loading...</div>;
const tokenData = account?.data;
return (
<div>
<p>Balance: {tokenData?.amount.toString()}</p>
<p>Delegated: {tokenData?.delegatedAmount.toString()}</p>
</div>
);
}With ATA Address
If you need to fetch and decode a specific Token Account's address (like for ancillary token accounts), you can manually derive the address and provide it to the hook:
const { account } = useTokenAccount({
ata: "CCMCWh4FudPEmY6Q1AVi5o8mQMXkHYkJUmZfzRGdcJ9P",
});Parameters
interface UseTokenAccountOptions {
// Option 1: Provide mint and owner
mint?: Address | string;
owner?: Address | string;
// Option 2: Provide ATA address directly
ata?: Address | string;
commitment?: Commitment;
enabled?: boolean;
// ... other TanStack Query options
}Performance Optimization
Conditional Fetching
const { balance } = useBalance({
address: walletAddress,
enabled: !!walletAddress, // Only fetch if address exists
});Stale Time Configuration
const { account } = useAccount({
address,
options: {
staleTime: 30000, // Consider data fresh for 30 seconds
cacheTime: 300000, // Keep in cache for 5 minutes
},
});Query Invalidation
import { useQueryClient } from "@tanstack/react-query";
function RefreshButton() {
const queryClient = useQueryClient();
const refreshAll = () => {
// Invalidate all `@gillsdk/react` queries
queryClient.invalidateQueries({ queryKey: ["gill"] });
};
return <button onClick={refreshAll}>Refresh All</button>;
}