SDK
React Integration
This guide shows you how to integrate the PerpCity SDK with Wagmi in a React application.
Installation
Install required dependencies:
pnpm add @strobelabs/perpcity-sdk wagmi viem @tanstack/react-queryWagmi Configuration
Set up your Wagmi config:
// wagmi.config.ts
import { http, createConfig } from 'wagmi'
import { base } from 'wagmi/chains'
import { injected, walletConnect } from 'wagmi/connectors'
export const config = createConfig({
chains: [base],
connectors: [
injected(),
walletConnect({ projectId: 'YOUR_PROJECT_ID' })
],
transports: {
[base.id]: http(process.env.NEXT_PUBLIC_RPC_URL)
}
})App Setup
Wrap your app with Wagmi providers:
// app.tsx
import { WagmiProvider } from 'wagmi'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { config } from './wagmi.config'
const queryClient = new QueryClient()
function App() {
return (
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>
<YourApp />
</QueryClientProvider>
</WagmiProvider>
)
}
export default AppCreate a PerpCity Hook
Create a custom hook to manage the PerpCity context:
// hooks/usePerpCity.ts
import { useMemo } from 'react'
import { useWalletClient } from 'wagmi'
import { PerpCityContext } from '@strobelabs/perpcity-sdk'
const PERP_MANAGER_ADDRESS = '0x...' as const
const USDC_ADDRESS = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913' as const
export function usePerpCity(): PerpCityContext | null {
const { data: walletClient } = useWalletClient()
const context = useMemo(() => {
if (!walletClient) return null
return new PerpCityContext({
walletClient,
rpcUrl: process.env.NEXT_PUBLIC_RPC_URL!,
deployments: {
perpManager: PERP_MANAGER_ADDRESS,
usdc: USDC_ADDRESS
}
})
}, [walletClient])
return context
}Using the Hook in Components
Display User Balance
// components/Balance.tsx
import { useEffect, useState } from 'react'
import { useAccount } from 'wagmi'
import { usePerpCity } from '../hooks/usePerpCity'
import { getUserUsdcBalance } from '@strobelabs/perpcity-sdk'
export function Balance() {
const context = usePerpCity()
const { address } = useAccount()
const [balance, setBalance] = useState<number | null>(null)
useEffect(() => {
if (!context || !address) return
const fetchBalance = async () => {
// Two-step pattern: fetch user data, then extract balance
const userData = await context.getUserData(address, [])
const bal = getUserUsdcBalance(userData)
setBalance(bal)
}
fetchBalance()
// Refresh every 10 seconds
const interval = setInterval(fetchBalance, 10_000)
return () => clearInterval(interval)
}, [context, address])
if (!context) return <div>Connect wallet</div>
if (balance === null) return <div>Loading...</div>
return (
<div>
<h3>USDC Balance</h3>
<p>${balance.toFixed(2)}</p>
</div>
)
}React Query Integration
For better state management, use React Query:
// hooks/usePositionData.ts
import { useQuery } from '@tanstack/react-query'
import { usePerpCity } from './usePerpCity'
import type { Hex } from 'viem'
export function usePositionData(
perpId: Hex,
positionId: bigint,
isLong: boolean,
isMaker: boolean
) {
const context = usePerpCity()
return useQuery({
queryKey: ['position', perpId, positionId.toString(), isLong, isMaker],
queryFn: async () => {
if (!context) throw new Error('No context')
return await context.getOpenPositionData(perpId, positionId, isLong, isMaker)
},
enabled: !!context,
refetchInterval: 10_000 // Refresh every 10 seconds
})
}Use in components:
// components/Position.tsx
import { usePositionData } from '../hooks/usePositionData'
import type { Hex } from 'viem'
export function Position({
perpId,
positionId
}: {
perpId: Hex
positionId: bigint
}) {
const { data, isLoading, error } = usePositionData(perpId, positionId, true, false)
if (isLoading) return <div>Loading...</div>
if (error) return <div>Error: {error.message}</div>
if (!data) return null
const pnl = data.liveDetails.pnl
return (
<div>
<h4>Position {positionId.toString()}</h4>
<p>PnL: ${pnl.toFixed(2)}</p>
<p>{data.liveDetails.isLiquidatable ? '⚠️ At risk' : '✅ Healthy'}</p>
</div>
)
}Complete Example App
// App.tsx
import { WagmiProvider } from 'wagmi'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { ConnectKitProvider, ConnectKitButton } from 'connectkit'
import { config } from './wagmi.config'
import { Balance } from './components/Balance'
import { OpenPosition } from './components/OpenPosition'
import { PositionList } from './components/PositionList'
const queryClient = new QueryClient()
function App() {
return (
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>
<ConnectKitProvider>
<div style={{ padding: '20px' }}>
<ConnectKitButton />
<div style={{ marginTop: '20px' }}>
<Balance />
<OpenPosition />
<PositionList />
</div>
</div>
</ConnectKitProvider>
</QueryClientProvider>
</WagmiProvider>
)
}
export default AppNext Steps
- Query Data for advanced querying patterns
- API Reference for complete function list