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.
- Freighter Integration: Seamlessly connect and interact with the Freighter wallet.
- Horizon Data Fetching: Easy access to account balances, offers, and more.
- Soroban Support: Call smart contracts with built-in simulation and auth handling.
- Transaction Helpers: Simplified submission and polling for both classic and Soroban.
- Modular Adapters: First-class support for React Query and SWR.
- Type-Safe: Written in TypeScript with full type definitions.
// 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>
);
}Every hook listed below is implemented and exported from the package entry point. Hooks with a ↓ link have an expanded reference further down this page.
| Hook | Description |
|---|---|
useFreighter() ↓ |
Connect to the Freighter extension (@stellar/freighter-api v6); sign transactions, auth entries, and messages. Supports signMessage() and autoConnect. |
useFreighterAccounts() |
Track previously-seen Freighter addresses in localStorage; drive the permission dialog to switch between them. |
useWalletKit() ↓ |
Detect installed Stellar wallets (Freighter, Lobstr, xBull) and expose a unified connect / sign interface. |
useWalletsKit() |
Multi-wallet adapter via @creit-tech/stellar-wallets-kit (Freighter, xBull, Albedo, Lobstr, WalletConnect, …). |
useWalletConnect() |
WalletConnect v2 adapter for Stellar / Freighter Mobile. |
useNetwork() ↓ |
Read the active network configuration and switch networks at runtime. |
useStellarNetwork() ↓ |
Read the active network and switch networks dynamically via setNetwork() — no page reload required. |
| Hook | Description |
|---|---|
useStellarAccount() ↓ |
Fetch (and optionally poll) a full account from Horizon. |
useStellarAccounts() |
Fetch and poll multiple accounts in parallel (no serial waterfall). |
useStellarBalance() ↓ |
XLM and per-asset balances (wrapper around useStellarAccount). |
useSorobanTokenBalance() |
Read SAC (Stellar Asset Contract) token balances via Soroban RPC. |
useLedgerEntry() ↓ |
Read a raw Soroban ledger entry by its xdr.LedgerKey. |
useOperations() |
Fetch operations for an account or transaction from Horizon; supports includeFailed and cursor-based pagination. |
useEffects() |
Stream account effects from Horizon. |
useAssets() |
Fetch and list Stellar assets via Horizon. |
useAssetMetadata() |
Fetch asset metadata from a domain's stellar.toml. |
useStellarToml() |
Fetch and parse a domain's stellar.toml. |
useOffers() |
Fetch open offers for a Stellar account with pagination helpers. |
useStellarOffers() |
Fetch open offers for a Stellar account. |
useOrderBook() ↓ |
Query the Stellar DEX order book for any asset pair; supports live polling. |
useTrades() ↓ |
Fetch DEX trade history for an account with optional asset pair filtering. |
useStrictSendPaths() ↓ |
Discover payment paths and exchange rates via Horizon's strict-send endpoint before committing to a swap. |
useClaimableBalances() |
List claimable balances for an account. |
| Hook | Description |
|---|---|
usePayment() ↓ |
Build, sign, and submit a classic XLM / asset payment. |
usePathPayment() |
Strict send / receive path payments. |
useTransaction() ↓ |
Submit a pre-signed XDR and poll until confirmed (Soroban RPC or classic Horizon). |
useTrade() |
Place, modify, and cancel Stellar DEX offers. |
useTrustline() |
Add, remove, and modify trustlines. |
useCreateAccount() |
Fund (via Friendbot) and create new accounts. |
useAccountMerge() |
Build and submit an account merge. |
useAccountFlags() |
Set and clear account auth flags. |
useBumpSequence() |
Bump an account's sequence number. |
useMultiSig() |
Build a multi-sig transaction, collect signatures, and submit once the threshold is met. |
useInflation() |
Submit an inflation operation (legacy support). |
useClaimBalance() / useCreateClaimableBalance() |
Claim and create claimable balances. |
For a cross-hook breakdown of how error, isError, refetch, and reset behave, see the Error Handling Patterns guide.
| Hook | Description |
|---|---|
useSorobanContract() ↓ |
Simulate → sign → submit → poll a Soroban contract call in one hook. |
useLedgerEntry() ↓ |
Read a raw Soroban ledger entry without constructing a contract call. |
Connect to and interact with the Freighter browser extension wallet. Built on @stellar/freighter-api v6 — signBlob is implemented on top of Freighter's signMessage API.
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
networkPassphraseMismatch, // boolean — true when wallet network differs from `expectedNetworkPassphrase` (or the <StellarProvider> network)
networkPassphraseWarning, // string | null — actionable warning text on mismatch; null otherwise
isLoading,
isSigningMessage, // boolean — true while signMessage() is in flight
isAutoConnecting, // boolean — true while the autoConnect silent check runs
error,
connect, // () => Promise<void>
disconnect, // () => void
signTransaction, // (xdr: string, opts?) => Promise<string>
signAuthEntry, // (entryPreimageXdr: string) => Promise<string>
signBlob, // (blob: string, opts?) => Promise<string> — wraps signMessage
signMessage, // (message: string, opts?) => Promise<string> — sign arbitrary messages
} = useFreighter();Use signMessage() to implement challenge-response authentication flows:
import { useFreighter } from "stellar-hooks";
function SignInButton() {
const { isConnected, publicKey, signMessage, isSigningMessage, connect } = useFreighter();
async function handleSignIn() {
if (!isConnected) { await connect(); return; }
const challenge = `Sign in to MyApp at ${new Date().toISOString()}`;
const signature = await signMessage(challenge);
// Send { publicKey, challenge, signature } to your backend for verification
await fetch("/api/auth", {
method: "POST",
body: JSON.stringify({ publicKey, challenge, signature }),
});
}
return (
<button onClick={handleSignIn} disabled={isSigningMessage}>
{isSigningMessage ? "Signing…" : "Sign In with Stellar"}
</button>
);
}Pass autoConnect: true to silently reconnect users who previously granted access — no popup:
const { isConnected, publicKey, isAutoConnecting } = useFreighter({
autoConnect: true,
});
if (isAutoConnecting) return <p>Reconnecting…</p>;
if (isConnected) return <p>Welcome back, {publicKey}</p>;If the wallet is on a different Stellar network than your dApp expects, signing would silently target the wrong ledger. The hook accepts an optional expectedNetworkPassphrase:
const { networkPassphraseMismatch, networkPassphraseWarning } = useFreighter({
expectedNetworkPassphrase: "Test SDF Network ; September 2015",
});
// Or, if your app is wrapped in <StellarProvider network="testnet">, the
// expected passphrase is taken from the provider automatically.Render networkPassphraseWarning to surface the issue, or gate signing behind an acknowledgement. See the API reference for a full example.
Read the active network configuration and switch networks at runtime. All values reflect the currently active network — including any network switch made via switchNetwork.
Read the full active network configuration object from the provider context without drilling props around your tree.
import { useNetworkConfig } from "stellar-hooks";
function NetworkBadge() {
const { network, horizonUrl, sorobanRpcUrl, networkPassphrase } = useNetworkConfig();
return <pre>{JSON.stringify({ network, horizonUrl, sorobanRpcUrl, networkPassphrase }, null, 2)}</pre>;
}Return the configured Horizon server instance for custom queries beyond the built-in hooks.
import { useHorizonServer } from "stellar-hooks";
function CustomHorizonExample() {
const server = useHorizonServer();
async function loadAccountOffers(publicKey: string) {
return server.offers().forAccount(publicKey).call();
}
return null;
}const {
network, // StellarNetwork — "testnet" | "mainnet" | "futurenet" | "custom"
networkPassphrase, // string — e.g. "Test SDF Network ; September 2015"
horizonUrl, // string — active Horizon REST API endpoint
sorobanRpcUrl, // string — active Soroban RPC endpoint
config, // NetworkConfig — full { network, horizonUrl, sorobanRpcUrl, networkPassphrase }
switchNetwork, // (network: StellarNetwork, customConfig?: CustomNetworkConfig) => void
} = useNetwork();Switch networks at runtime (e.g. a settings UI):
import { useNetwork } from "stellar-hooks";
import type { StellarNetwork } from "stellar-hooks";
function NetworkSwitcher() {
const { network, switchNetwork } = useNetwork();
return (
<select
value={network}
onChange={(e) => switchNetwork(e.target.value as StellarNetwork)}
>
<option value="testnet">Testnet</option>
<option value="mainnet">Mainnet</option>
<option value="futurenet">Futurenet</option>
</select>
);
}When switching to a custom network, pass the full CustomNetworkConfig as the second argument:
switchNetwork("custom", {
network: "custom",
horizonUrl: "https://my-horizon.example.com",
sorobanRpcUrl: "https://my-rpc.example.com",
networkPassphrase: "My Network ; 2024",
});The selected network is persisted to localStorage and survives page reloads.
Read the active network and switch networks dynamically via setNetwork() — no page reload or provider remount required. All child hooks re-fetch automatically when the network changes.
const {
network, // StellarNetwork
networkPassphrase, // string
horizonUrl, // string
sorobanRpcUrl, // string
config, // NetworkConfig
setNetwork, // (network: StellarNetwork, customConfig?: CustomNetworkConfig) => void
} = useStellarNetwork();Example — a testnet/mainnet toggle:
import { useStellarNetwork } from "stellar-hooks";
function NetworkToggle() {
const { network, setNetwork } = useStellarNetwork();
return (
<button onClick={() => setNetwork(network === "testnet" ? "mainnet" : "testnet")}>
Currently: {network} — click to switch
</button>
);
}Detect installed Stellar wallets (Freighter, Lobstr, xBull) and expose a unified interface — connect, disconnect, and sign regardless of which wallet is active.
const {
availableWallets, // WalletId[] — e.g. ["freighter", "lobstr"]
activeWallet, // WalletId | null
publicKey, // string | null
isConnecting, // boolean
error, // Error | null
setActiveWallet, // (id: WalletId) => void
connect, // (walletId?: WalletId) => Promise<string | null>
disconnect, // () => void
signTransaction, // (xdr: string, opts?) => Promise<string>
} = useWalletKit();Example — wallet picker:
import { useWalletKit } from "stellar-hooks";
function WalletPicker() {
const { availableWallets, activeWallet, publicKey, connect, disconnect } = useWalletKit();
if (publicKey) {
return (
<div>
<p>Connected via {activeWallet}: {publicKey}</p>
<button onClick={disconnect}>Disconnect</button>
</div>
);
}
if (availableWallets.length === 0) return <p>No Stellar wallets detected.</p>;
return (
<div>
{availableWallets.map((id) => (
<button key={id} onClick={() => connect(id)}>
Connect {id}
</button>
))}
</div>
);
}Falls back gracefully when a wallet extension is not installed — it simply won't appear in availableWallets.
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 and optionally a specific asset balance.
const {
balances, // StellarBalance[]
xlmBalance, // StellarBalance | null (the native XLM entry)
assetBalance, // StellarBalance | null (the specific asset requested, if any)
isLoading,
error,
refetch,
} = useStellarBalance("G...", { code: "USDC", issuer: "G..." });Fetch and poll multiple Stellar accounts in parallel — useful for multisig rosters, account pickers, or any list view. Issues one batched Promise.all(loadAccount) per tick and returns a per-key map.
const {
accounts, // Record<publicKey, StellarAccountData | null>
errors, // Record<publicKey, Error | null>
isLoading,
isError,
error, // First per-key error across the batch, or null
refetch,
lastFetchedAt,
} = useStellarAccounts([signerA, signerB, signerC], { refetchInterval: 10_000 });null/undefinedentries in the input are skipped.- Duplicate keys are deduplicated before the RPC call.
- A single failing account does NOT poison the rest of the batch —
errors[pk]carries per-key errors.
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);Expose real-time Horizon and RPC health. Useful for showing network status indicators in dApp UIs.
const {
horizonLatency, // number — latency in ms; Infinity if offline
rpcLatency, // number — latency in ms; Infinity if offline
isHorizonHealthy,// boolean
isRpcHealthy, // boolean
ledger, // number — latest ledger sequence
} = useNetworkStatus({
refetchInterval: 10000, // poll every 10s (default)
});This hook will gracefully handle timeouts and offline scenarios for each endpoint independently.
Fetch paginated transaction history for a given Stellar account from Horizon.
const {
transactions, // Horizon.TransactionResponse[]
fetchNextPage, // () => void
hasMore, // boolean
isLoading, // boolean
error,
} = useTransactionHistory("G...", {
limit: 20, // default: 10
order: "desc", // default: "desc"
});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,
});Fetch a specific asset balance (native XLM or issued asset) for a given public key.
const { balance, isLoading, error } = useAssetBalance("G...", "native");
// balance → StellarBalance | null
const { balance } = useAssetBalance("G...", { code: "USDC", issuer: "G..." });Supports the same refetchInterval and enabled options as useStellarAccount.
List and manage trustlines for an account.
const { trustlines, addTrustline, removeTrustline, status } = useTrustlines("G...");
await addTrustline({ code: "USDC", issuer: "G..." }); // add a trustline
await removeTrustline({ code: "USDC", issuer: "G..." }); // remove (set limit to 0)
// status: "idle" | "submitting" | "success" | "error"
// Each mutation signs via Freighter and submits through Horizon.Merge the funded account into a destination account via Freighter.
const { merge, status, hash, error } = useAccountMerge();
await merge("GDEST...", { confirm: true });
// Throws if confirm !== true (safety guard against accidental merges).Get a configured SorobanRpc.Server instance from the StellarProvider context.
const server = useSorobanServer();
// Equivalent to: new SorobanRpc.Server(config.sorobanRpcUrl)
// Useful for ad-hoc RPC calls outside of the existing hooks:
const account = await server.getAccount("G...");
const ledgerEntries = await server.getLedgerEntries(key);Throws a descriptive error if used outside <StellarProvider>.
Wrap your app (or the portion that needs Stellar) with <StellarProvider> to configure the network. Every hook that reads blockchain data consumes endpoint configuration from this provider.
| Prop | Type | Default | Description |
|---|---|---|---|
network |
StellarNetwork |
"testnet" |
The network to connect to. One of "testnet", "mainnet", "futurenet", or "custom". |
customConfig |
CustomNetworkConfig |
— | Required when network is "custom". Supplies Horizon URL, Soroban RPC URL, and the network passphrase for your deployment. |
children |
React.ReactNode |
— | The component tree that will have access to Stellar context. |
| Network | Horizon URL | Soroban RPC URL | Network Passphrase |
|---|---|---|---|
testnet |
https://horizon-testnet.stellar.org |
https://soroban-testnet.stellar.org |
Test SDF Network ; September 2015 |
mainnet |
https://horizon.stellar.org |
https://mainnet.sorobanrpc.com |
Public Global Stellar Network ; September 2015 |
futurenet |
https://horizon-futurenet.stellar.org |
https://rpc-futurenet.stellar.org |
Test SDF Future Network ; October 2022 |
These presets are also exported as NETWORK_CONFIGS if you need them outside React:
import { NETWORK_CONFIGS } from "stellar-hooks";
const { horizonUrl } = NETWORK_CONFIGS.mainnet;// Testnet (default)
<StellarProvider network="testnet">
<App />
</StellarProvider>
// Mainnet
<StellarProvider network="mainnet">
<App />
</StellarProvider>
// Futurenet
<StellarProvider network="futurenet">
<App />
</StellarProvider>
// Custom / self-hosted network
<StellarProvider
network="custom"
customConfig={{
network: "custom",
horizonUrl: "https://my-horizon.example.com",
sorobanRpcUrl: "https://my-rpc.example.com",
networkPassphrase: "My Network ; 2024",
}}
>
<App />
</StellarProvider>Use this interface when connecting to a private or self-hosted Stellar network.
| Field | Type | Description |
|---|---|---|
network |
"custom" |
Must be "custom". |
horizonUrl |
string |
Horizon REST API base URL for this network. |
sorobanRpcUrl |
string |
Soroban RPC endpoint for contract simulation and submission. |
networkPassphrase |
string |
Network passphrase used when signing transactions. |
<StellarProvider> automatically persists the active network in localStorage under the keys stellar-hooks:network and stellar-hooks:custom-config. On subsequent page loads the persisted choice is restored, overriding the network prop. To switch networks at runtime and persist the change, use useNetwork().switchNetwork.
All types are exported and fully documented via JSDoc.
import type {
StellarNetwork,
NetworkConfig,
CustomNetworkConfig,
StellarAccountData,
StellarBalance,
FreighterState,
UseFreighterReturn,
TransactionStatus,
ContractCallOptions,
AssetDescriptor,
UseAssetBalanceReturn,
TrustlineAsset,
UseTrustlinesReturn,
UseAccountMergeReturn,
} from "stellar-hooks";| Peer dependency | Version |
|---|---|
| react | ≥ 18 |
| react-dom | ≥ 18 |
The library ships with @stellar/stellar-sdk v13 and @stellar/freighter-api v6 as direct dependencies — you don't need to install them separately unless you need a different version.
See MIGRATION.md for a version-by-version guide to breaking changes and how to update your code.
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
- Run
npm run changesetto create a changeset note for your change. - If your PR includes code changes, run
npm run buildbefore opening the PR.
Please review our Contributing Guide and Code of Conduct for more details before opening a pull request.
Full documentation with live examples is available at https://spiffamani.github.io/stellar-hooks/
To preview the documentation site locally:
npm install
npm run docs:devThe docs site will be available at http://localhost:5173 (or the port VitePress assigns).
This repository uses Changesets for automated changelog generation, version bumps, and npm publishing.
- Use
npm run changesetto add a release note to your PR. - After a changeset is merged into
main, the GitHub Actions release workflow will publish the package automatically. - To enable automated publishing, add
NPM_TOKENto repository secrets.
-
usePayment()— send XLM / asset payments with one hook -
useClaimableBalance()— list and claim claimable balances -
usePathPayment()— strict send / receive path payment hook -
useStellarToml()— fetch and parse a domain'sstellar.toml - React Query / SWR adapters —
@stellar-hooks/queryand@stellar-hooks/swr
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
Fetch DEX trade history for a given Stellar account from Horizon's /accounts/{id}/trades endpoint.
Supports optional asset pair filtering and cursor-based pagination.
import { useTrades } from "stellar-hooks";
import { Asset } from "@stellar/stellar-sdk";
// Basic usage — account trade history
const {
trades, // TradeRecord[]
isLoading, // boolean
error, // Error | null
lastFetchedAt, // Date | null
refetch, // () => Promise<void>
} = useTrades("G...", {
limit: 20, // default: 10
order: "desc", // default: "desc"
cursor: "12345", // optional, for pagination
refetchInterval: 10000, // optional, poll every 10 s
});
// With asset pair filter
const USDC_ISSUER = "GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN";
const { trades } = useTrades("G...", {
baseAsset: Asset.native(),
counterAsset: new Asset("USDC", USDC_ISSUER),
});Each TradeRecord exposes: id, ledger_close_time, base_amount, base_asset_type,
counter_amount, counter_asset_type, base_is_seller, price, and more.
Query the Stellar DEX order book for a given selling/buying asset pair.
Supports both native XLM and any issued asset. Optionally polls at refetchInterval for live price feeds.
import { useOrderBook } from "stellar-hooks";
import { Asset } from "@stellar/stellar-sdk";
const USDC_ISSUER = "GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN";
function SwapPriceDisplay() {
const { bids, asks, isLoading, error, refetch } = useOrderBook(
Asset.native(),
new Asset("USDC", USDC_ISSUER),
{ limit: 10, refetchInterval: 5000 },
);
if (isLoading) return <p>Loading…</p>;
if (error) return <p>Error: {error.message}</p>;
const bestBid = bids[0]?.price ?? "—";
const bestAsk = asks[0]?.price ?? "—";
return (
<div>
<p>Best Bid: {bestBid} USDC</p>
<p>Best Ask: {bestAsk} USDC</p>
</div>
);
}| Property | Type | Description |
|---|---|---|
bids |
OrderBookLevel[] |
Buy-side price levels (highest first) |
asks |
OrderBookLevel[] |
Sell-side price levels (lowest first) |
raw |
OrderBookRecord | null |
Full raw Horizon response |
isLoading |
boolean |
true while fetching |
error |
Error | null |
Last fetch error |
lastFetchedAt |
Date | null |
Timestamp of last successful fetch |
refetch |
() => Promise<void> |
Manually trigger a re-fetch |
Discover available payment paths and exchange rates via Horizon's /paths/strict-send endpoint
before the user commits to a swap. Automatically re-queries when inputs change, with a configurable
debounce (default 300 ms).
import { useStrictSendPaths } from "stellar-hooks";
import { Asset } from "@stellar/stellar-sdk";
const USDC_ISSUER = "GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN";
function SwapRatePreview({ sendAmount }: { sendAmount: string }) {
const { paths, isLoading, error } = useStrictSendPaths(
Asset.native(),
sendAmount,
[new Asset("USDC", USDC_ISSUER)],
{ debounceMs: 300 }, // default
);
if (isLoading) return <p>Finding best rate…</p>;
if (error) return <p>Error: {error.message}</p>;
const best = paths[0];
if (!best) return <p>No paths found.</p>;
return (
<p>
Send {best.source_amount} XLM → Receive ~{best.destination_amount} USDC
</p>
);
}| Option | Type | Default | Description |
|---|---|---|---|
debounceMs |
number |
300 |
Delay in ms before re-querying on input change |
enabled |
boolean |
true |
Set false to disable fetching |
| Return value | Type | Description |
|---|---|---|
paths |
PathRecord[] |
Available paths sorted by Horizon (best first) |
isLoading |
boolean |
true while a query is in flight |
error |
Error | null |
Last fetch error |
lastFetchedAt |
Date | null |
Timestamp of last successful fetch |