React Integration
Use the Intuition SDK with React applications via Wagmi hooks for wallet connectivity and blockchain interactions.
Setupβ
Install required dependencies:
npm install wagmi viem @tanstack/react-query
SDK read helpers use the mainnet GraphQL API by default. Because this guide configures Wagmi for Intuition Testnet, initialize the SDK read endpoint once during application startup:
import { configureSdk } from '@0xintuition/sdk'
import { API_URL_DEV } from '@0xintuition/graphql'
configureSdk({ apiUrl: API_URL_DEV })
Import this configuration module before components call SDK read helpers. Use API_URL_PROD when your Wagmi chains target intuitionMainnet.
Wagmi Configurationβ
Set up Wagmi provider in your app:
import { http, createConfig } from 'wagmi'
import { intuitionTestnet } from '@0xintuition/sdk'
import { injected } from 'wagmi/connectors'
export const config = createConfig({
chains: [intuitionTestnet],
connectors: [injected()],
transports: {
[intuitionTestnet.id]: http(),
},
})
Pass the exported Wagmi config into the provider component:
import type { PropsWithChildren } from 'react'
import { WagmiProvider, type Config } from 'wagmi'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import './sdk-config'
const queryClient = new QueryClient()
type AppProvidersProps = PropsWithChildren<{ config: Config }>
export function AppProviders({ children, config }: AppProvidersProps) {
return (
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>
{children}
</QueryClientProvider>
</WagmiProvider>
)
}
Provider convention: Every usage component in this guide must render inside the WagmiProvider and QueryClientProvider shown above. Pasting a component into an app without that wrapper can throw WagmiProviderNotFoundError or "No QueryClient set".
Creating Atomsβ
Use SDK functions with Wagmi hooks.
createAtomFromString fetches and forwards the required atom base cost. The optional amount in these examples is an additional TRUST/tTRUST deposit (signal).
import { usePublicClient, useWalletClient, useChainId } from 'wagmi'
import {
createAtomFromString,
getMultiVaultAddressFromChainId,
} from '@0xintuition/sdk'
import { parseEther } from 'viem'
import { useState } from 'react'
export function CreateAtomButton() {
// Renders inside the providers from Setup
const chainId = useChainId()
const publicClient = usePublicClient()
const { data: walletClient } = useWalletClient()
const [loading, setLoading] = useState(false)
const [atomId, setAtomId] = useState<string | null>(null)
const handleCreateAtom = async () => {
if (!publicClient || !walletClient) {
alert('Connect wallet first')
return
}
setLoading(true)
try {
const address = getMultiVaultAddressFromChainId(chainId)
const atom = await createAtomFromString(
{ walletClient, publicClient, address },
'My Atom',
parseEther('0.01')
)
setAtomId(atom.state.termId)
console.log('Created atom:', atom.state.termId)
} catch (error) {
console.error('Error:', error)
alert('Failed to create atom')
} finally {
setLoading(false)
}
}
return (
<div>
<button onClick={handleCreateAtom} disabled={loading || !walletClient}>
{loading ? 'Creating...' : 'Create Atom'}
</button>
{atomId && <p>Created: {atomId}</p>}
</div>
)
}
Custom Hooksβ
Create reusable hooks for SDK operations:
import { useMutation } from '@tanstack/react-query'
import { usePublicClient, useWalletClient, useChainId } from 'wagmi'
import {
createAtomFromString,
getMultiVaultAddressFromChainId,
} from '@0xintuition/sdk'
import { parseEther } from 'viem'
export function useCreateAtom() {
const chainId = useChainId()
const publicClient = usePublicClient()
const { data: walletClient } = useWalletClient()
return useMutation({
mutationFn: async ({ data, deposit }: { data: string, deposit?: string }) => {
if (!publicClient || !walletClient) {
throw new Error('Wallet not connected')
}
const address = getMultiVaultAddressFromChainId(chainId)
return createAtomFromString(
{ walletClient, publicClient, address },
data,
deposit ? parseEther(deposit) : undefined
)
},
})
}
// Usage in component
function MyComponent() {
// Renders inside the providers from Setup
const createAtom = useCreateAtom()
const handleCreate = async () => {
const result = await createAtom.mutateAsync({
data: 'My Atom',
deposit: '0.01',
})
console.log('Created:', result.state.termId)
}
return (
<button
onClick={handleCreate}
disabled={createAtom.isPending}
>
{createAtom.isPending ? 'Creating...' : 'Create Atom'}
</button>
)
}
Query Hooksβ
Fetch data with React Query:
import { useQuery } from '@tanstack/react-query'
import { getAtomDetails } from '@0xintuition/sdk'
export function useAtomDetails(atomId: string | undefined) {
return useQuery({
queryKey: ['atom', atomId],
queryFn: () => atomId ? getAtomDetails(atomId) : null,
enabled: !!atomId,
staleTime: 30000, // 30 seconds
})
}
// Usage
function AtomDisplay({ atomId }: { atomId: string }) {
// Renders inside the providers from Setup
const { data: atom, isLoading, error } = useAtomDetails(atomId)
if (isLoading) return <div>Loading...</div>
if (error) return <div>Error loading atom</div>
if (!atom) return null
const vault = atom.term?.vaults[0]
return (
<div>
<h3>{atom.label}</h3>
<p>Creator: {atom.creator?.label ?? atom.creator_id}</p>
<p>Shares: {vault?.total_shares ?? 'Unavailable'}</p>
</div>
)
}
Complete Exampleβ
Full-featured React component:
import { useState } from 'react'
import { useAccount, usePublicClient, useWalletClient, useChainId } from 'wagmi'
import { useQuery, useMutation } from '@tanstack/react-query'
import './sdk-config'
import {
createAtomFromString,
globalSearch,
getMultiVaultAddressFromChainId,
} from '@0xintuition/sdk'
import { parseEther } from 'viem'
export function AtomManager() {
// Renders inside the providers from Setup
const chainId = useChainId()
const { address: accountAddress } = useAccount()
const publicClient = usePublicClient()
const { data: walletClient } = useWalletClient()
const [searchQuery, setSearchQuery] = useState('')
const [newAtomData, setNewAtomData] = useState('')
// Search atoms
const { data: searchResults } = useQuery({
queryKey: ['search', searchQuery],
queryFn: () => globalSearch(searchQuery, { atomsLimit: 10 }),
enabled: searchQuery.length > 2,
})
// Create atom mutation
const createAtom = useMutation({
mutationFn: async (data: string) => {
if (!publicClient || !walletClient) throw new Error('Not connected')
const address = getMultiVaultAddressFromChainId(chainId)
return createAtomFromString(
{ walletClient, publicClient, address },
data,
parseEther('0.01')
)
},
onSuccess: (result) => {
console.log('Created:', result.state.termId)
setNewAtomData('')
},
})
return (
<div>
<h2>Atom Manager</h2>
{/* Search */}
<div>
<h3>Search Atoms</h3>
<input
type="text"
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
placeholder="Search..."
/>
{searchResults?.atoms.map(atom => (
<div key={atom.term_id}>{atom.label}</div>
))}
</div>
{/* Create */}
<div>
<h3>Create Atom</h3>
<input
type="text"
value={newAtomData}
onChange={(e) => setNewAtomData(e.target.value)}
placeholder="Atom data..."
/>
<button
onClick={() => createAtom.mutate(newAtomData)}
disabled={!accountAddress || createAtom.isPending}
>
{createAtom.isPending ? 'Creating...' : 'Create'}
</button>
</div>
</div>
)
}