Skip to main content

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:

sdk-config.ts
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:

wagmi-config.ts
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:

AppProviders.tsx
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).

CreateAtomButton.tsx
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:

useCreateAtom.ts
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:

useAtomDetails.ts
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:

AtomManager.tsx
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>
)
}

See Also​