Skip to main content

Best practices

Provider setup

The ContextProvider must be inside both WagmiProvider and QueryClientProvider. Configure QueryClient for live market data:
const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: 5_000,        // 5 seconds for market data
      refetchInterval: 10_000,  // poll every 10 seconds
    },
  },
})

Query patterns

Dependent queries

const { data: market } = useMarket(marketId)
const { data: orderbook } = useOrderbook(marketId, {
  enabled: !!market,  // only fetch orderbook after market loads
})

Polling for live data

const { data: quotes } = useQuotes(marketId, {
  refetchInterval: 5_000,  // refresh every 5 seconds
})

Parallel queries

function MarketDetail({ id }: { id: string }) {
  const { data: market } = useMarket(id)
  const { data: quotes } = useQuotes(id)
  const { data: orderbook } = useOrderbook(id)

  // All three queries run in parallel
}

Cache invalidation

Mutation hooks automatically invalidate related queries. For manual invalidation:
import { contextKeys } from '@contextwtf/react'
import { useQueryClient } from '@tanstack/react-query'

const queryClient = useQueryClient()

// After a custom action
queryClient.invalidateQueries({ queryKey: contextKeys.orders.all })
queryClient.invalidateQueries({ queryKey: contextKeys.portfolio.all })

Wallet connection

The ContextProvider automatically picks up the connected wallet from wagmi. Trading hooks throw ContextWalletError if no wallet is connected.
import { useAccountStatus, useSetupAccount } from '@contextwtf/react'

function OnboardingFlow() {
  const { data: status } = useAccountStatus()
  const { mutate: setup } = useSetupAccount()

  if (!status?.isOperatorApproved) {
    return <button onClick={() => setup()}>Setup account</button>
  }

  return <div>Ready to trade</div>
}

Error handling

import { ContextWalletError } from '@contextwtf/react'

function TradeButton({ params }) {
  const { mutate: createOrder, error } = useCreateOrder()

  if (error instanceof ContextWalletError) {
    return <div>Please connect your wallet to trade</div>
  }

  return (
    <button onClick={() => createOrder(params)}>
      Buy
    </button>
  )
}

Optimistic updates

For a responsive UI, update the cache optimistically on mutations:
const queryClient = useQueryClient()
const { mutate: createOrder } = useCreateOrder({
  onSuccess: () => {
    // Refetch portfolio and orders after successful trade
    queryClient.invalidateQueries({ queryKey: contextKeys.orders.all })
    queryClient.invalidateQueries({ queryKey: contextKeys.portfolio.all })
  },
})