Skip to content

feat: @polymarket/react hooks SDK - #220

Draft
cesarenaldi wants to merge 12 commits into
mainfrom
feature/react-sdk-phase-1
Draft

feat: @polymarket/react hooks SDK#220
cesarenaldi wants to merge 12 commits into
mainfrom
feature/react-sdk-phase-1

Conversation

@cesarenaldi

Copy link
Copy Markdown
Collaborator

Introduces @polymarket/react, the React hooks SDK built on @polymarket/client, covering the full end-user trading-hub loop: discover, authenticate, onboard, trade, and monitor. Design direction and settled decisions are recorded in docs/react-sdk-direction.md.

Architecture

  • The provider holds a base client (no bound action methods); every hook imports only the standalone action it needs, so consumers bundle only what they use.
  • Session is the state; clients are derived. Session is a serializable object apps persist themselves; the secure client is a memoized derivation of (config, session). initialSession restores synchronously at mount with no logged-out flash; revoked sessions surface as 401s that end the session.
  • Wallet operations flow through a signature-only WorkflowHandler (single interception point over the client's workflow generators). EOA accounts are rejected by invariant, which keeps the handler vocabulary signature-only: no transaction sending, no gas.
  • Wallet libraries live behind dedicated entry points with optional peers; @polymarket/react/viem ships first (useWorkflowHandler, works with anything producing a viem WalletClient).
  • Reads have no query cache in v1: hooks return what the actions return plus refetch, with skip pausing and TanStack-compatible result naming so a cache layer can be adopted later without breakage.
  • Writes are imperative [execute, { status, step, data, error, reset }], with per-hook narrowing of both handler request kinds and step kinds. Order placement has no automatic allowance recovery: rejections surface as the new typed InsufficientAllowanceError and integrators route users through the approvals hook.

Client package additions

  • createBaseClient / createBaseSecureClient: construction without bound actions, including restoring an authenticated client from session credentials without running an authentication workflow.
  • beginAuthentication promoted to public API; workflow request vocabulary types exported.
  • fetchDepositWallet: the default account-wallet resolution extracted from createSecureClient.
  • InsufficientAllowanceError: the balance/allowance order rejection typed at the posting boundary instead of a string-matched message.

Hook surface

Setup createConfig/PolymarketProvider · auth useAuthentication · onboarding useIsWalletDeployed/useDeployWallet/useSetupTradingApprovals · discovery useMarkets/useMarket/useEvents/useEvent/useSearch/useTags/useRelatedTags/useComments/usePublicProfile/useMarketHolders/useTraderLeaderboard · trading form useOrderBook/useMidpoint/useLastTradePrice/usePriceHistory/useEstimatedMarketPrice/usePlaceMarketOrder/usePlaceLimitOrder/useCancelOrder · portfolio usePositions/useClosedPositions/usePortfolioValue/useActivity/useBalance/useOpenOrders/useOrder/useNotifications/useDropNotifications/useTradingRestriction · lifecycle useRedeemPositions/useSplitPosition/useMergePositions/useTransfer · escape hatch usePolymarketClient.

Per-address portfolio reads default user to the session wallet and pause while unauthenticated; an explicit user works without a session. The roster is deliberately curated for end-user hubs (not market-maker/builder dashboards); skipped actions and reasons are documented in the direction doc.

Verification

  • 70 react tests (jsdom behavior tests with controlled actions and scripted workflow handlers, msw-backed auth/cancel/deploy/session-defaulting flows, 12 type tests including handler/step narrowing and @ts-expect-error rejections)
  • 4 live integration tests against production reads
  • Full client suite (207 tests) including new coverage for the factories and the allowance-rejection mapping
  • pnpm lint, pnpm typecheck, pnpm build green throughout

Out of scope / follow-ups

  • Phase 5 realtime hooks (stacked next: generic useSubscriptions over the unified subscribe topics + dedicated live order book / user channel hooks)
  • Live E2E placement pass with funded credentials
  • Client tree-shaking follow-up: the base factories currently share a module graph with the decorators (noted in the direction doc)
  • listMarketHolders returns a direct array despite the list* prefix; rename candidate
  • authenticate() does not deployment-check explicitly passed Safe/Proxy wallets the way createSecureClient does

Changesets included: @polymarket/react minor (initial beta) and @polymarket/client patches.

Add createBaseSecureClient to restore an authenticated client from existing session credentials without running an authentication workflow, promote beginAuthentication to the public API, export the workflow request vocabulary types from the root entry point, and add fetchDepositWallet, extracting the default Deposit Wallet resolution from createSecureClient.
Add the signature-only WorkflowHandler contract with cancellation unified onto CancelledSigningError, useAuthentication with handler-driven authenticate/logout, serializable Session with synchronous initialSession restore and 401 invalidation, internal read primitives renamed to the public/secure families with secure gating, useOpenOrders, and the @polymarket/react/viem entry point with useWorkflowHandler and WalletClientUnavailableError. Only dedicated hooks and usePolymarketClient are exported; action primitives stay internal.
Capture the session-derivation model, signature-only handler ownership at wallet entry points, error-surface decisions, entry-point isolation as a review-enforced guideline, and the client tree-shaking follow-up.
…eError

Map the balance/allowance 400 rejection to a typed error at the order posting boundary so consumers can branch on it without string-matching the rejection message. Added to the PostOrderError, PostOrdersError, PlaceMarketOrderError, and PlaceLimitOrderError unions; the internal allowance-recovery detection now checks the typed error directly.
Add usePlaceMarketOrder and usePlaceLimitOrder driving the order posting workflows through the workflow handler with per-hook step narrowing and no automatic allowance recovery, useSetupTradingApprovals as the account-readiness and allowance-recovery path over the gasless relayer, useCancelOrder, and the internal useSecureWrite primitive with UnauthenticatedError, 401 session invalidation, reset, and stale-execution discarding.
Add usePositions, useClosedPositions, usePortfolioValue, and useActivity over public per-address data with the user defaulting to the session wallet (paused while unauthenticated, explicit user works without a session), useBalance, useNotifications, useOrder, and useTradingRestriction for session-bound account state, and useDropNotifications as the notification dismissal write.
Add the market-order execution preview over estimateMarketPrice, pairing with the placement hooks' slippage bounds. Skip pausing covers empty amount inputs; the estimate is refreshed explicitly via refetch.
Add discovery and trading-form reads (useEvent, usePriceHistory, useMidpoint, useLastTradePrice, useSearch, useTags, useRelatedTags, useComments, usePublicProfile, useMarketHolders, useTraderLeaderboard) and gasless lifecycle writes resolving at transaction confirmation (useRedeemPositions, useSplitPosition, useMergePositions, useTransfer). Generalize the gasless workflow step vocabulary into GaslessStep/asGaslessWorkflow shared across the gasless write hooks.
Add useIsWalletDeployed reading the session wallet's deployment status and useDeployWallet deploying the Deposit Wallet signature-free through the gasless relayer, resolving at transaction confirmation. Deployment stays an explicit onboarding step; ordering with trading approvals is documented on both hooks.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant