React hooks and Vue composables for building Polkadot apps.
Status: this is an experiment, not an official library. The effort will move into @parity/product-sdk, which is the right place for it to live long term.
One install, one provider, 64 hooks. use-truapi wraps the entire
TruAPI /
@parity/product-sdk surface —
chain queries, wallet accounts, transactions, contracts, chat, statement
store, payments, notifications, cloud storage, preimages, personhood proofs
and host identity — so your frontend never imports (or even installs) the
underlying SDK packages. Tracks TruAPI protocol 0.14 (@parity/truapi
0.13.1) and the product-sdk v0.27 wave. Every hook is built
on TanStack Query, so you get caching,
staleTime/gcTime strategies, refetching, invalidation and devtools.
Documentation: justraman.github.io/use-truapi
const { submit, phase } = useTx();
const balance = useBalance(account?.address);
const total = useChainQuery((api) => api.query.Balances.TotalIssuance.getValue(), [], {
query: { staleTime: 60_000 }, // any TanStack Query option
});
const theme = useTheme();| Package | Registry | What it is |
|---|---|---|
@use-truapi/react |
npm | React 18/19 hooks |
@use-truapi/vue |
npm | Vue 3 composables |
@use-truapi/core |
npm | Framework-agnostic runtime both bind to |
# React
npm i @use-truapi/react @tanstack/react-query # or bun add / pnpm add / yarn add
# Vue
npm i @use-truapi/vue @tanstack/vue-queryTanStack Query v5 is a peer dependency — if your app already uses it, the
hooks share your existing QueryClient and show up in your devtools.
You'll also want PAPI descriptors for the chains you use — either generate
them (npx papi add) or use the prebuilt ones:
npm i @parity/product-sdk-descriptorsBuilding with Claude Code, Cursor or another coding agent? Install the bundled agent skill — a token-efficient distillation of the docs (setup, all hooks, host-vs-standalone rules) that the agent loads on demand:
npx skills add justraman/use-truapiThe skill lives in skills/use-truapi; see the
AI docs page for details.
The docs site also serves /llms.txt
and /llms-full.txt.
| Capability | Inside a Polkadot host | Standalone (plain browser) |
|---|---|---|
| Chain connection | host provider; genesis discovered by hostChain role (RFC-0026) |
wsUrls from your config |
| Accounts | product account derived from the host's product context | Alice…Ferdie dev accounts |
| Signing permission | ChainSubmit requested per tx |
no-op |
| Theme / locale | host theme and language subscriptions | prefers-color-scheme / navigator.language |
| Host identity, product context, chain discovery, connection status | native | null / "disconnected" |
| KV storage | host localStorage | browser localStorage |
| Chat / payments / notifications / cloud reads / preimages | native | unavailable — hooks error or stay inert (documented per hook) |
| VRF and ring-VRF personhood (RFC-0023/0024) | native | HostUnavailableError |
| Statements | sponsored (RFC-0010) publish/subscribe | inert (publish → false, lists stay empty) |
The rule of thumb: read-style hooks degrade silently, action-style hooks
throw HostUnavailableError so you can gate UI with useIsHost().
@use-truapi/react @use-truapi/vue ← thin bindings over TanStack Query (+ stores/refs)
@tanstack/react-query @tanstack/vue-query
└──────────┬──────────┘
@use-truapi/core ← runtime: stores, query keys, live registry, lifecycles
┌──────────┴───────────┐
@parity/product-sdk-* polkadot-api ← host getters, SignerManager, submitAndWatch, PAPI
└──────────┬──────────┘
@parity/truapi ← TruAPI wire protocol (SCALE over postMessage)
│
Polkadot host (Desktop / Mobile / Web)
@use-truapi/core owns everything stateful so the framework packages stay
tiny and identical in behavior:
- host detection memoized once per page;
- one PAPI client per configured chain (promise-cached, failure-evicting, 15 s host-provider timeout);
- one
SignerManagerbridged into a subscribable store; - lazy, connect-once chat / statement / payment / storage clients;
- every host subscription wrapped with
unsubscribe+onInterrupthandling; - a refcounted live-subscription registry per QueryClient, so N components on the same query key share one host subscription feeding the query cache.
bun install
bunx nx run-many -t build # build core → react/vue (cached, ordered)
bunx nx run-many -t test # vitest everywhere
bunx nx run-many -t typecheck # tsc --noEmit
bunx nx run-many -t lint # biome
bun run --cwd apps/example-react dev # standalone example on :3000
bun run --cwd apps/example-vue dev # standalone example on :5174
cd e2e && bunx playwright test # runs example-react inside a real Spektr test hostThe e2e suite uses
@parity/host-api-test-sdk —
a real host implementation with dev accounts, permission/signing logs and
theme control — so hooks are exercised against the actual wire protocol, not
mocks.
truapi-host
runs a real signing host on your machine (real product account, statement
store, entropy, preimages, personhood) with no phone or desktop build:
curl -fsSL https://raw.githubusercontent.com/paritytech/host-rust-core/main/scripts/truapi-host-installer.sh | bash
# one command: start the host, then the example dev server against it
truapi-host dev --app-port 3000 -- bun run --cwd apps/example-react devThe examples' Vite config probes http://127.0.0.1:9955/bootstrap.js at
dev-server start and, when a host is serving it, injects the bridge script so
the app is detected as hosted (useHostMode() → "host",
useHostInfo() → truapi-host …). A signing host started separately works
the same way: truapi-host signing-host --serve --frame-listen 127.0.0.1:9955 --product-id localhost:3000 --auto-accept. The first run registers a test
identity on-chain and can take a few minutes.
- Bump the version in
packages/{core,react,vue}/package.json(keep them in lockstep). - Commit, tag
vX.Y.Z, push the tag. - The
release.ymlworkflow verifies tag == package versions, builds, tests, and publishes all three packages to npm.
MIT