sdk or react
connect-sdk is the framework-neutral client — typed reads over HTTP plus one multiplexed WebSocket. connect-react is that, as hooks, plus the checkout drawer. Reach for react unless you can't.
Two clients, one wire.
@prophecy-dev/connect-sdk
The framework-neutral client. Typed reads over HTTP (cached), and realtime subscriptions over one multiplexed WebSocket — not a socket per subscription.
const client = new ConnectClient({ baseUrl: 'https://api.prophecyhosting.com' })
const { holders } = await client.markets.holders(id, { limit: 15 })
Use it directly when you’re not on React: a server route, a bot, a Svelte or Vue venue, a native app via a thin bridge.
@prophecy-dev/connect-react
The same client as hooks — useEvents, useOdds, useActivity, useSearch, useLiveStats,
useLeaderboard, useWallet, usePositions, useResolution — plus the parts you should not
rebuild:
<ConnectProvider>— one client, one socket, shared by every hook beneath it.- The {c} Checkout — the trade confirm surface, including the gasless path.
- Live-trade animation —
<LiveTrades>/<TradePulse>, sharing one subscription. - The claim surface —
<WalletBalance>puts “Claim 42 PST” in the space the balance already occupies;<ClaimSheet>is the drawer behind it. A venue with its own claim page passesclaim={{ href }}and we link there instead.
<ProphecyConfirm/> is required, and it is easy to miss
Mount it once, anywhere inside <ProphecyProvider>:
<ProphecyProvider …>
{children}
<ProphecyConfirm />
</ProphecyProvider>
useConfirm().confirm() only queues a request — <ProphecyConfirm/> is what renders it and
settles the promise. Without one, any surface that awaits a confirm waits forever. That covers market
creation and claiming: <ClaimSheet> hides its claim button when no confirm is mounted rather
than offering an action that could never complete, and warns in dev saying so. If a claim button is
missing on a wallet that clearly has winnings, this is the first thing to check.
Reach for this by default. The hooks handle subscription lifecycle, refresh intervals and deduplication, which is most of what you’d otherwise write twice.
What else ships in the box
Shipped across 1.13–1.18 and easy to miss, so listed with the one thing about each that stops you building it twice. Every signature below was read from the source, not remembered.
Claiming — a wallet’s settled winnings, and the way to take them.
client.wallets.claimable(address) |
every settled condition still holding redeemable tokens, with payout and why: kind ('winnings' / 'refund'), winningOutcomes, outcomeLabels. Not positions() filtered by resolution — that read is the trade fold, which never learns about a redeem. |
useClaimable(wallet) |
the same, as claims / total / winnings / refunds / loading / error / refetch / clear. error is deliberately separate from an empty list. |
buildRedeemPlan({ reader, claims, owner }) |
the calls, grouped: the ERC-1155 approval alone first, then every redeem batched. Hand it to useConfirm’s send. |
predictor.redeem({ claims }) |
the same action, sent for you — for a one-tap surface rather than a confirm-first one. |
A void refunds down the same path as a win, so both arrive in one list. Word a refund as a refund:
kind is decided server-side precisely so the wrong wording takes deliberate effort.
Prefetching claims on a server render? Seed from wallets.claimablePending, not
wallets.claimable — on the client and on createReadClient() from @prophecy-dev/connect-sdk/server
(added in connect-sdk@1.44.0). They are two different reads, and only the first one matches what
useClaimable puts in the cache:
wallets.claimable(address) |
the raw wire answer, { wallet, claimable }, edge-cached for a few seconds after a redeem. |
wallets.claimablePending(address) |
the same rows as a bare Claimable[], with anything just claimed through this client filtered out. What useClaimable fetches. |
Seed publicKeys.claimable(wallet) from the raw one and the hook never finds it — the shapes differ,
so it looks up an entry nobody wrote. It fails safe (no seed, never a wrong seed), so the only
symptom is a claim panel that flashes its skeleton on a page that was supposed to arrive warm, which
is exactly the kind of thing nobody reports.
Overlays — <ProphecyModal>, plus useModalBehaviour, useEscape, useSwipeToDismiss and
focusablesIn. Portals to document.body (a transform on any ancestor otherwise becomes the
containing block for position: fixed and clips the sheet), with aria-modal, Escape, a focus trap
and focus restore. keepMounted keeps a closed overlay in the DOM for surfaces that animate out.
Building your own floating surface? Use this rather than rediscovering the four defects it fixes.
Community — comments, takes, rooms, profiles and moderation. The full map, with which piece goes on which screen and the server rules behind them, is Comments & feeds. In brief:
- Components:
<Comments>,<Feed>,<TakeCard>,<StanceChip>,<TakePrompt>. - Reads:
useComments,useFeed(withsignals,threads,labels),useForYou,useAuthorTakes+takeReceipt,useTakeCounts,useRoomMembership,useRoomBoard. - Writes:
usePostActions(create/edit/remove/react/report),useTail,useCanPost,useBlock. - Moderation:
useModerationQueue,useModerate.
<Comments> takes viewer — the signed-in wallet, which gates edit/delete. Omit it and neither is
drawn, because guessing puts a Delete button on somebody else’s writing. The composed screens
(<MarketComments>, <CommunityTakes>, <RoomFeed>, <ModerationQueue>) are in venue-kit.
The market clock — useMarketClock(market) returns the phase and time remaining as a value that
changes, on a shared tick, with a tier (urgent / soon / later / none) graded once and
both thresholds overridable. formatMarketClock(clock) gives the label. Use them instead of
formatting closesAt yourself: a countdown that never re-renders is how a closed market keeps
looking open.
autoConfirm on a ConfirmRequest — for when your own surface was the confirmation. The
drawer starts working instead of asking again, and still runs the sponsorship gate, the step
progress and the decoded revert. It changes who asks, never whether the gate runs.
Choosing
| You are… | Use |
|---|---|
| A React venue | connect-react |
| A React venue that also needs a one-off read outside a component | both — connect-react wraps connect-sdk, and the client is available to you |
| Not React | connect-sdk |
| Rendering markets on a server | connect-sdk |
One socket, one auth
Two independent ConnectAuth instances will race — each mints its own session, and writes land on
whichever won. Create one and hand it to both providers. The
Login & Session page shows the wiring a venue should copy.