API Reference
@decentrl/sdk-react
React hooks and providers for building Decentrl-powered UIs with useSyncExternalStore.
npm install @decentrl/sdk-reactPeer dependency: React 18+ or 19+.
Provider
DecentrlProvider
Wraps your app with a DecentrlClient instance.
import { DecentrlProvider } from '@decentrl/sdk-react'
<DecentrlProvider client={client}>
<App />
</DecentrlProvider>useDecentrlClient()
Access the raw client from context. Throws if used outside DecentrlProvider.
function useDecentrlClient<TEvents, TState>(): DecentrlClient<TEvents, TState>Core Hooks
useDecentrl()
Returns the publish method and client instance.
function useDecentrl<TEvents, TState>(): {
publish: DecentrlClient<TEvents, TState>['publish']
client: DecentrlClient<TEvents, TState>
}const { publish } = useDecentrl()
await publish('message', { text: 'hello', threadId: crypto.randomUUID() })useDecentrlState(selector?)
Subscribes to client state with optional selector. Uses useSyncExternalStore for tear-free reads.
function useDecentrlState<TSelected>(
selector?: (state: InferState<TState>) => TSelected,
): TSelectedconst messages = useDecentrlState(s => s.messages)
const count = useDecentrlState(s => s.messages.length)useDecentrlIdentity()
Manages identity state and operations.
function useDecentrlIdentity(): {
identity: IdentityState | null
isInitialized: boolean
create: (opts: { alias: string; mediatorDid: string }) => Promise<IdentityState>
load: (serialized: SerializedIdentity) => IdentityState
serialize: () => SerializedIdentity
reset: () => void
contracts: ContractManager
}useConnectionStatus()
function useConnectionStatus(): ConnectionStatus
// 'disconnected' | 'connecting' | 'authenticating' | 'connected'useAutoSync(options?)
Starts automatic background sync. Cleans up on unmount.
function useAutoSync(options?: {
intervalMs?: number // default: 3000
enabled?: boolean // default: true
onError?: (error: unknown) => void
websocket?: boolean
fallbackIntervalMs?: number
}): voidEvent Hooks
useEventStream(callback, options?)
Subscribes to real-time events with optional type/tag filtering.
function useEventStream(
callback: (envelope: EventEnvelope) => void,
options?: { types?: string[]; tags?: string[] },
): voiduseEventStream(
(event) => console.log('New message:', event.data),
{ types: ['chat.message'] },
)useEventQuery(options)
Queries historical events with pagination and state selection.
function useEventQuery<TSelected>(options: {
tags?: string[]
select: (state: InferState<TState>) => TSelected
pageSize?: number // default: 20
queryOptions?: Omit<QueryOptions, 'tags' | 'pagination'>
}): {
data: TSelected
isLoading: boolean
error: Error | null
hasMore: boolean
fetchMore: () => void
}Contract Hooks
useActiveContracts()
function useActiveContracts(): {
contracts: StoredSignedContract[]
refresh: () => void
refreshAsync: () => Promise<void>
isRefreshing: boolean
isError: boolean
error: Error | null
}usePendingContracts(options?)
function usePendingContracts(
options?: { enabled?: boolean },
): {
data: PendingContractRequest[] | undefined
isPending: boolean
isError: boolean
error: Error | null
refetch: () => void
}useContractByDid(did)
function useContractByDid(did: string): StoredSignedContract | undefinedMutation Hooks
useCreateIdentity(options?)
function useCreateIdentity(options?): {
mutate: (vars: { alias: string; mediatorDid: string }) => void
mutateAsync: (vars) => Promise<IdentityState>
isPending: boolean
isSuccess: boolean
isError: boolean
error: Error | null
}useRequestContract(options?)
function useRequestContract(options?): {
mutate: (vars: { recipientDid: string; expiresIn?: number }) => void
mutateAsync: (vars) => Promise<void>
isPending: boolean
// ...
}useAcceptContract(options?)
function useAcceptContract(options?): {
mutate: (vars: {
pendingId: string
encryptedPayload: string
requestorEphemeralPublicKey: string
}) => void
mutateAsync: (vars) => Promise<void>
isPending: boolean
// ...
}useSync(options?)
Manually trigger a sync.
function useSync(options?): {
mutate: () => void
mutateAsync: () => Promise<void>
isPending: boolean
// ...
}Generic Primitives
These power all the hooks above and can be used for custom async operations:
useDecentrlQuery(queryFn, options?)
function useDecentrlQuery<TData, TError>(
queryFn: () => Promise<TData>,
options?: { enabled?: boolean },
): {
data: TData | undefined
isPending: boolean
isFetching: boolean
isSuccess: boolean
isError: boolean
error: TError | null
refetch: () => void
}useDecentrlMutation(mutationFn, options?)
function useDecentrlMutation<TVariables, TData, TError>(
mutationFn: (variables: TVariables) => Promise<TData>,
options?: {
onSuccess?: (data: TData, variables: TVariables) => void
onError?: (error: TError, variables: TVariables) => void
onSettled?: (data: TData | undefined, error: TError | null, variables: TVariables) => void
},
): {
mutate: (variables: TVariables) => void
mutateAsync: (variables: TVariables) => Promise<TData>
isPending: boolean
isSuccess: boolean
isError: boolean
isIdle: boolean
data: TData | undefined
error: TError | null
reset: () => void
}