@onflow/kit
π§ This library is currently in alpha and is subject to change.
@onflow/kit
is a lightweight React utility library that simplifies interacting with the Flow blockchain. It provides a collection of hooks, similar to those in other popular web3 libraries, that make it easier to build frontends that understand blockchain interactions. In the future, it will also provided components designed to make authentication, script execution, transactions, event subscriptions, and network configuration seamless in React apps.
π Included React Hooksβ
useCurrentFlowUser
β Authenticate and manage the current Flow useruseFlowAccount
β Fetch Flow account details by addressuseFlowBlock
β Query latest or specific Flow blocksuseFlowConfig
β Access the current Flow configurationuseFlowEvents
β Subscribe to Flow events in real-timeuseFlowQuery
β Execute Cadence scripts with optional argumentsuseFlowMutate
β Send transactions to the Flow blockchainuseFlowTransaction
β Track transaction status updates
Installationβ
_10npm install @onflow/kit
Usageβ
Wrapping Your App With FlowProvider
β
Begin by wrapping your application with the FlowProvider
to initialize FCL configuration. This sets up FCL and maps its configuration keys to a strictly typed format for your hooks.
_25import React from "react"_25import App from "./App"_25import { FlowProvider } from "@onflow/kit"_25import flowJSON from "../flow.json"_25_25function Root() {_25 return (_25 <FlowProvider_25 config={{_25 accessNodeUrl: "https://access-mainnet.onflow.org",_25 flowNetwork: "mainnet",_25 appDetailTitle: "My On Chain App",_25 appDetailIcon: "https://example.com/icon.png",_25 appDetailDescription: "A decentralized app on Flow",_25 appDetailUrl: "https://myonchainapp.com",_25 // include other typed configuration keys as needed..._25 }}_25 flowJson={flowJSON}_25 >_25 <App />_25 </FlowProvider>_25 )_25}_25_25export default Root
If you're using [Next.js], put this in layout.tsx
. Adapt as appropriate for other frontend frameworks.
Hooksβ
Many of these hooks are built using @tanstack/react-query
, which provides powerful caching, revalidation, and background refetching features. As a result, youβll see return types like UseQueryResult
and UseMutationResult
throughout this section. Other typesβsuch as Account
, Block
, and CurrentUser
βare from the Flow Client Library (FCL) TypeDefs. Refer to their respective documentation for full type definitions and usage patterns.
useCurrentFlowUser
β
_10import { useCurrentFlowUser } from "@onflow/kit"
Returns:β
user: CurrentUser
β The current user object from FCLauthenticate: () => Promise<CurrentUser>
β Triggers wallet authenticationunauthenticate: () => void
β Logs the user out
_16function AuthComponent() {_16 const { user, authenticate, unauthenticate } = useCurrentFlowUser()_16_16 return (_16 <div>_16 {user.loggedIn ? (_16 <>_16 <p>Logged in as {user.addr}</p>_16 <button onClick={unauthenticate}>Logout</button>_16 </>_16 ) : (_16 <button onClick={authenticate}>Login</button>_16 )}_16 </div>_16 )_16}
useFlowAccount
β
_10import { useFlowAccount } from "@onflow/kit"
Parameters:β
address?: string
β Flow address (with or without0x
prefix)
Returns: UseQueryResult<Account | null, Error>
β
_16function AccountDetails() {_16 const { data: account, isLoading, error, refetch } = useFlowAccount("0x1cf0e2f2f715450")_16_16 if (isLoading) return <p>Loading account...</p>_16 if (error) return <p>Error fetching account: {error.message}</p>_16 if (!account) return <p>No account data</p>_16_16 return (_16 <div>_16 <h2>Account: {account.address}</h2>_16 <p>Balance: {account.balance}</p>_16 <pre>{account.code}</pre>_16 <button onClick={refetch}>Refetch</button>_16 </div>_16 )_16}
useFlowBlock
β
_10import { useFlowBlock } from "@onflow/kit"
Parameters (mutually exclusive):β
{}
β Latest block (default){ sealed: true }
β Latest sealed block{ id: string }
β Block by ID{ height: number }
β Block by height
Returns: UseQueryResult<Block | null, Error>
β
_13function LatestBlock() {_13 const { data: block, isLoading, error } = useFlowBlock()_13 if (isLoading) return <p>Loading...</p>_13 if (error) return <p>Error: {error.message}</p>_13 if (!block) return <p>No block data.</p>_13_13 return (_13 <div>_13 <h2>Block {block.height}</h2>_13 <p>ID: {block.id}</p>_13 </div>_13 )_13}
useFlowConfig
β
_10import { useFlowConfig } from "@onflow/kit"
Returns: FlowConfig
β
_10function MyComponent() {_10 const config = useFlowConfig()_10_10 return (_10 <div>_10 <p>Current network: {config.flowNetwork}</p>_10 <p>Current access node: {config.accessNodeUrl}</p>_10 </div>_10 )_10}
useFlowEvents
β
_10import { useFlowEvents } from "@onflow/kit"
Parameters:β
eventNameOrFilter
: string | EventFilteroptions: { onEvent: (event) => void, onError?: (error) => void }
Example:β
_10function EventListener() {_10 useFlowEvents("A.0xDeaDBeef.SomeContract.SomeEvent", {_10 onEvent: (event) => console.log("New event:", event),_10 onError: (error) => console.error("Error:", error),_10 })_10_10 return <div>Listening for events...</div>_10}
useFlowQuery
β
_10import { useFlowQuery } from "@onflow/kit"
Parameters:β
cadence: string
β Cadence script to runargs?: (arg, t) => unknown[]
β Function returning FCL argumentsenabled?: boolean
β Defaults totrue
Returns: UseQueryResult<unknown, Error>
β
_20function QueryExample() {_20 const { data, isLoading, error, refetch } = useFlowQuery({_20 cadence: `_20 pub fun main(a: Int, b: Int): Int {_20 return a + b_20 }_20 `,_20 args: (arg, t) => [arg(1, t.Int), arg(2, t.Int)],_20 })_20_20 if (isLoading) return <p>Loading query...</p>_20 if (error) return <p>Error: {error.message}</p>_20_20 return (_20 <div>_20 <p>Result: {data}</p>_20 <button onClick={refetch}>Refetch</button>_20 </div>_20 )_20}
useFlowMutate
β
_10import { useFlowMutate } from "@onflow/kit"
Returns: UseMutationResult<string, Error, FCLMutateParams>
β
mutate
: A function to send the transactiondata
: Transaction IDerror
: Any errorisPending
: Boolean status
_29function CreatePage() {_29 const { mutate, isPending, error, data: txId } = useFlowMutate()_29_29 const sendTransaction = () => {_29 mutate({_29 cadence: `transaction() {_29 prepare(acct: &Account) {_29 log(acct.address)_29 }_29 }`,_29 args: (arg, t) => [],_29 proposer: fcl.currentUser,_29 payer: fcl.currentUser,_29 authorizations: [],_29 limit: 100,_29 })_29 }_29_29 return (_29 <div>_29 <button onClick={sendTransaction} disabled={isPending}>_29 Send Transaction_29 </button>_29 {isPending && <p>Sending transaction...</p>}_29 {error && <p>Error: {error.message}</p>}_29 {txId && <p>Transaction ID: {txId}</p>}_29 </div>_29 )_29}
useFlowTransaction
β
_10import { useFlowTransaction } from "@onflow/kit"
Parameters:β
txId: string
β Transaction ID to subscribe to
Returns:β
transactionStatus: TransactionStatus | null
error: Error | null
_12function TransactionComponent() {_12 const txId = "your-transaction-id-here"_12 const { transactionStatus, error } = useFlowTransaction(txId)_12_12 if (error) return <div>Error: {error.message}</div>_12_12 return (_12 <div>_12 Status: {transactionStatus?.statusString}_12 </div>_12 )_12}