React hooks for Stellar and Soroban. The
wagmiyou've been waiting for.
npm install stellar-hooksstellar-hooks wires the Stellar JS SDK v13 and the Freighter wallet API into a set of ergonomic React hooks so you can build Stellar dApps without copy-pasting the same boilerplate across repos.
// main.tsx
import { StellarProvider } from "stellar-hooks";
ReactDOM.createRoot(document.getElementById("root")!).render(
<StellarProvider network="testnet">
<App />
</StellarProvider>
);// App.tsx
import { useFreighter, useStellarBalance } from "stellar-hooks";
export function App() {
const { isConnected, publicKey, connect } = useFreighter();
const { xlmBalance } = useStellarBalance(publicKey);
if (!isConnected) {
return <button onClick={connect}>Connect Freighter</button>;
}
return (
<p>
{publicKey} · {xlmBalance?.balance ?? "..."} XLM
</p>
);
}Connect to and interact with the Freighter browser extension wallet, including arbitrary data signing via signBlob.
Fetch and subscribe to a Stellar account's data, including balances, sequence number, and thresholds.
Invoke a Soroban smart-contract method. Handles simulation, auth, submission, and status polling in one hook.
Submit a pre-signed transaction XDR and poll until it is confirmed. Works with both Soroban (RPC) and classic Stellar (Horizon) transactions.
const {
isInstalled, // boolean — is Freighter installed?
isConnected, // boolean — has the user granted access?
publicKey, // string | null
network, // string | null e.g. "TESTNET"
networkPassphrase, // string | null
isLoading,
error,
connect, // () => Promise<void>
disconnect, // () => void
signTransaction, // (xdr: string, opts?) => Promise<string>
signAuthEntry, // (entryPreimageXdr: string) => Promise<string>
signBlob, // (blob: string, opts?) => Promise<string>
} = useFreighter();Fetch (and optionally poll) a full Stellar account from Horizon.
const {
data, // StellarAccountData | null
isLoading,
error,
lastFetchedAt, // Date | null
refetch,
} = useStellarAccount("G...", {
enabled: true, // default: true
refetchInterval: 5000, // poll every 5 s; 0 = disabled (default)
});
// data.balances → StellarBalance[]
// data.sequence → string
// data.subentryCount → number
// data.numSponsored → number
// data.numSponsoring → number
// data.raw → raw Horizon.AccountResponseConvenience wrapper around useStellarAccount that surfaces the XLM balance at the top level.
const {
balances, // StellarBalance[]
xlmBalance, // StellarBalance | null (the native XLM entry)
isLoading,
error,
refetch,
} = useStellarBalance("G...");Simulate → sign (via Freighter) → submit → poll a Soroban contract call. Full lifecycle in one hook.
const { call, status, result, hash, error, reset } = useSorobanContract({
contractId: "CABC...XYZ", // Soroban C... contract address
method: "increment",
args: [nativeToScVal(1, { type: "u32" })],
fee: "100", // stroops (default: BASE_FEE)
timeoutSeconds: 30, // default: 30
});
// Statuses: "idle" | "building" | "signing" | "submitting" | "polling" | "success" | "error"
<button onClick={() => call()} disabled={status !== "idle"}>
{status}
</button>You may also pass a pre-configured rpc.Server instance via the sorobanRpcServer option to reuse an existing connection or custom transport:
const { call, status } = useSorobanContract({
contractId: "CABC...XYZ",
method: "hello",
args: [nativeToScVal("world")],
sorobanRpcServer: myCustomServer,
});result contains the raw xdr.ScVal return value. Parse it with scValToNative from the SDK.
Submit a pre-signed XDR and poll for confirmation. Useful when you sign outside React (e.g. hardware wallet, server-side).
const { submit, status, hash, isSuccess, isError, error, reset } = useTransaction({
mode: "soroban", // "soroban" (default) | "classic"
timeoutSeconds: 60,
});
await submit(signedXdr);Read a raw Soroban ledger entry by its xdr.LedgerKey without constructing a contract call.
import { xdr, Address, Contract } from "@stellar/stellar-sdk";
const key = xdr.LedgerKey.contractData(
new xdr.LedgerKeyContractData({
contract: new Address(CONTRACT_ID).toScAddress(),
key: xdr.ScVal.scvSymbol("Counter"),
durability: xdr.ContractDataDurability.persistent(),
})
);
const { data, isLoading, error, refetch } = useLedgerEntry(key, {
refetchInterval: 3000,
});Wrap your app with <StellarProvider> to configure the network.
// Testnet (default)
<StellarProvider network="testnet">...</StellarProvider>
// Mainnet
<StellarProvider network="mainnet">...</StellarProvider>
// Custom RPC
<StellarProvider
network="custom"
customConfig={{
network: "custom",
horizonUrl: "https://my-horizon.example.com",
sorobanRpcUrl: "https://my-rpc.example.com",
networkPassphrase: "My Network ; 2024",
}}
>
...
</StellarProvider>All types are exported and fully documented via JSDoc.
import type {
StellarNetwork,
NetworkConfig,
CustomNetworkConfig,
StellarAccountData,
StellarBalance,
FreighterState,
UseFreighterReturn,
TransactionStatus,
ContractCallOptions,
} from "stellar-hooks";| Peer dependency | Version |
|---|---|
| react | ≥ 18 |
| react-dom | ≥ 18 |
The library ships with @stellar/stellar-sdk v13 and @stellar/freighter-api v2 as direct dependencies — you don't need to install them separately unless you need a different version.
git clone https://github.com/YOUR_USERNAME/stellar-hooksnpm installnpm run dev— builds in watch mode- Edit hooks in
src/hooks/, types insrc/types/ - Open a PR
Please review our Contributing Guide and Code of Conduct for more details before opening a pull request.
-
usePayment()— send XLM / SAT payments with one hook -
useClaimableBalance()— list and claim claimable balances -
useContractEvents()— subscribe to Soroban contract events via streaming -
usePathPayment()— strict send / receive path payment hook -
useStellarToml()— fetch and parse a domain'sstellar.toml - React Query / SWR adapter (optional peer dependency)
testnet (default), mainnet, futurenet, and any custom network via the custom mode with a customConfig prop on <StellarProvider>.
No — it ships as a direct dependency. You only need to install it separately if you require a version different from the bundled one.
Most hooks that interact with user accounts (useFreighter, useSorobanContract, useStellarBalance, etc.) rely on a Freighter-connected wallet. useStellarAccount and useLedgerEntry are read-only and work without a wallet.
useFreighter depends on the Freighter browser extension API, so it works in web environments only. The other hooks should work anywhere you can run @stellar/stellar-sdk.
useStellarBalance is a lightweight wrapper around useStellarAccount that surfaces the native XLM balance at the top level for convenience.
Both useStellarAccount and useLedgerEntry accept a refetchInterval option (in ms). Set it to 5000 to poll every 5 seconds, or 0 (default) to disable polling.
No — the hooks consume configuration from the provider context. Wrap your app with <StellarProvider> at the root.
MIT