Skip to main content

@onflow/kit

warning

🚧 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

Installation


_10
npm 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.


_25
import React from "react"
_25
import App from "./App"
_25
import { FlowProvider } from "@onflow/kit"
_25
import flowJSON from "../flow.json"
_25
_25
function 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
_25
export default Root

If you're using [Next.js], put this in layout.tsx. Adapt as appropriate for other frontend frameworks.


Hooks

useCurrentFlowUser


_10
import { useCurrentFlowUser } from "@onflow/kit"

Returns:

  • user: CurrentUser – The current user object from FCL
  • authenticate: () => Promise<CurrentUser> – Triggers wallet authentication
  • unauthenticate: () => void – Logs the user out

_16
function 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


_10
import { useFlowAccount } from "@onflow/kit"

Parameters:

  • address?: string – Flow address (with or without 0x prefix)

Returns: UseQueryResult<Account | null, Error>


_16
function 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


_10
import { 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>


_13
function 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


_10
import { useFlowConfig } from "@onflow/kit"

Returns: FlowConfig


_10
function 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


_10
import { useFlowEvents } from "@onflow/kit"

Parameters:

  • eventNameOrFilter: string | EventFilter
  • options: { onEvent: (event) => void, onError?: (error) => void }

Example:


_10
function 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


_10
import { useFlowQuery } from "@onflow/kit"

Parameters:

  • cadence: string – Cadence script to run
  • args?: (arg, t) => unknown[] – Function returning FCL arguments
  • enabled?: boolean – Defaults to true

Returns: UseQueryResult<unknown, Error>


_20
function 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


_10
import { useFlowMutate } from "@onflow/kit"

Returns: UseMutationResult<string, Error, FCLMutateParams>

  • mutate: A function to send the transaction
  • data: Transaction ID
  • error: Any error
  • isPending: Boolean status

_29
function 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


_10
import { useFlowTransaction } from "@onflow/kit"

Parameters:

  • txId: string – Transaction ID to subscribe to

Returns:

  • transactionStatus: TransactionStatus | null
  • error: Error | null

_12
function 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
}