Sandbox version
For experimental use only. Proceed with caution.
Tutorials
React Query Integration
Wrap Honeycluster proxy calls in TanStack React Query hooks with caching, background refetch, and typed errors.

If you're using TanStack Start or any React app with @tanstack/react-query, you probably want Honeycluster responses to flow through the Query cache alongside the rest of your data. This tutorial shows the shape of a reusable useLedger hook — and how to keep the API key safely on your server side.

1. Backend assumption
##

This tutorial shows both patterns:

  • Public cluster: call https://honeycluster.io directly from the browser. No proxy, no key, no server code.
  • Private / enterprise cluster: call your own proxy's /api/ledger/:index route instead, and let the proxy forward to the private endpoint with the X-API-Key header attached. See the Node.js proxy tutorial if you need to build that layer.

The hook structure is the same either way — only the URL differs.

2. Typed fetch helper
##
TypeScript
// lib/honeycluster.ts
export interface LedgerSummary {
  ledger_index: number
  ledger_hash: string
  close_time_human: string
  transactions?: readonly unknown[]
}

// Public cluster — call directly from the browser.
// For a private endpoint, swap this for `/api/ledger/${index}` and let
// your proxy forward to the private hostname with the key attached.
export async function fetchLedger(index: number): Promise<LedgerSummary> {
  const res = await fetch('https://honeycluster.io', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      method: 'ledger',
      params: [{ ledger_index: index, transactions: true, expand: true }],
    }),
  })
  if (!res.ok) {
    const body = await res.json().catch(() => ({}))
    throw new Error(body?.message ?? `Ledger request failed: ${res.status}`)
  }
  const payload = await res.json()
  return payload.result.ledger as LedgerSummary
}

Keep this in a plain module so it's testable without React.

3. The hook
##
TypeScript
// hooks/useLedger.ts
import { useQuery } from '@tanstack/react-query'
import { fetchLedger, type LedgerSummary } from '~/lib/honeycluster'

export function useLedger(index: number | null) {
  return useQuery<LedgerSummary, Error>({
    queryKey: ['honeycluster', 'ledger', index],
    queryFn: () => fetchLedger(index!),
    enabled: index !== null,
    // Historical ledgers are immutable — cache effectively forever.
    staleTime: Infinity,
    gcTime: 1000 * 60 * 60, // 1 hour in memory
  })
}

Two important defaults:

  • staleTime: Infinity — historical ledger data never changes, so there's no point refetching. New React Query consumers hit the cache instantly.
  • enabled: index !== null — lets components call the hook unconditionally and still defer the fetch until they have a valid index.
4. Using it
##
Tsx
import { useLedger } from '~/hooks/useLedger'

export function LedgerCard({ index }: { index: number }) {
  const { data, isPending, error } = useLedger(index)

  if (isPending) return <p>Loading ledger {index}…</p>
  if (error) return <p className="text-danger9">{error.message}</p>
  if (!data) return null

  return (
    <div>
      <h3>Ledger {data.ledger_index}</h3>
      <p>Closed at {data.close_time_human}</p>
      <p>{data.transactions?.length ?? 0} transactions</p>
    </div>
  )
}
5. Streaming data
##

For live streams — ledgerClosed, account subscriptions, etc. — React Query isn't the right primitive. Those are push-based. Use a long-lived xrpl.js client on your server and relay events to the browser via Server-Sent Events or WebSockets. React Query can still hold the seeded "last known" value, and your stream handler can call queryClient.setQueryData(['ledger', 'latest'], event) to keep it fresh.

See Subscribe to Account Events for the server-side subscription pattern.