@onflow/react-sdk
@onflow/react-sdk is a lightweight React utility library that simplifies interacting with the Flow blockchain. It provides a collection of hooks and components designed to make authentication, script execution, transactions, event subscriptions, and network configuration seamless in React apps.
What's Included
Cadence Hooks
Hooks for interacting with native Flow Cadence runtime:
useFlowCurrentUser– Authenticate and manage the current Flow useruseFlowAccount– Fetch Flow account details by addressuseFlowBlock– Query latest or specific Flow blocksuseFlowChainId– Retrieve the current Flow chain IDuseFlowConfig– Access the current Flow configurationuseFlowEvents– Subscribe to Flow events in real-timeuseFlowQuery– Execute Cadence scripts with optional argumentsuseFlowQueryRaw– Execute Cadence scripts with optional arguments returning non-decoded datauseFlowMutate– Send transactions to the Flow blockchainuseFlowRevertibleRandom– Generate pseudorandom values tied to block heightuseFlowTransaction– Fetch a Flow transaction by IDuseFlowTransactionStatus– Track transaction status updatesuseDarkMode– Get current dark mode state
Cross-VM (Flow EVM ↔ Cadence) Hooks
useCrossVmBatchTransaction– Execute mutliple EVM transactions in a single atomic Cadence transactionuseCrossVmTokenBalance– Query fungible token balances across Cadence and Flow EVMuseCrossVmSpendNft– Bridge NFTs from Cadence to Flow EVM and execute arbitrary EVM transactions to atomically spend themuseCrossVmSpendToken– Bridge fungible tokens from Cadence to Flow EVM and execute arbitrary EVM transactionsuseCrossVmTransactionStatus– Track Cross-VM transaction status and EVM call results
Components
Reusable UI components:
<Connect />- A wallet authentication button<TransactionButton />- Context-aware button for executing Flow transactions<TransactionDialog />- A dialog modal that tracks a Flow transaction's lifecycle<TransactionLink />- A button that links to the block explorer based on network
Installation
_10npm install @onflow/react-sdk
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/react-sdk"_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      }}_25      flowJson={flowJSON}_25      darkMode={false}_25    >_25      <App />_25    </FlowProvider>_25  )_25}_25_25export default Root
If you're using Next.js, place the FlowProvider inside your layout.tsx. Since React hooks must run on the client, you may need to wrap the provider in a separate file that begins with 'use client' to avoid issues with server-side rendering. Adjust this setup as needed for other frontend frameworks.
👉 Learn more about configuring flow.json in the Configuration Guide.
🎨 Theming
How Theming Works
All UI components in @onflow/react-sdk are styled using Tailwind CSS utility classes. The kit supports both light and dark themes out of the box, using Tailwind's dark: variant for dark mode styling.
You can customize the look and feel of the kit by providing a custom theme to the FlowProvider via the theme prop. This allows you to override default colors and styles to better match your app's branding.
_17import { FlowProvider } from "@onflow/react-sdk"_17_17<FlowProvider_17  config={...}_17  theme={{_17    colors: {_17      primary: {_17        background: "bg-blue-600 dark:bg-blue-400",_17        text: "text-white dark:text-blue-900",_17        hover: "hover:bg-blue-700 dark:hover:bg-blue-300",_17      },_17      // ...other color overrides_17    }_17  }}_17>_17  <App />_17</FlowProvider>
🌙 Dark Mode
How Dark Mode Works
Dark mode is fully controlled by the parent app using the darkMode prop on FlowProvider. The kit does not manage dark mode state internally—this gives you full control and ensures the kit always matches your app's theme.
darkMode={false}(default): Forces all kit components to use light mode styles.darkMode={true}: Forces all kit components to use dark mode styles.- You can dynamically change the 
darkModeprop to switch themes at runtime. 
Example:
_10function App() {_10  // Parent app manages dark mode state_10  const [isDark, setIsDark] = useState(false)_10_10  return (_10    <FlowProvider config={...} darkMode={isDark}>_10      <MyFlowComponents />_10    </FlowProvider>_10  )_10}
Accessing Dark Mode State in Components:
You can use the useDarkMode hook to check the current mode inside your components:
_10import { useDarkMode } from "@onflow/react-sdk"_10_10function MyComponent() {_10  // useDarkMode only returns the current state, no setter_10  const { isDark } = useDarkMode()_10  return <div>{isDark ? "Dark mode" : "Light mode"}</div>_10}
Notes
- The kit does not automatically follow system preferences or save user choices. You are responsible for managing and passing the correct 
darkModevalue. - All kit components will automatically apply the correct Tailwind 
dark:classes based on thedarkModeprop. - For best results, ensure your app's global theme and the kit's 
darkModeprop are always in sync. 
Components
Connect
A drop-in wallet connection component with UI for copy address, logout, and balance display.
Props:
variant?: ButtonProps["variant"]– Optional button style variant (default:"primary")onConnect?: () => void– Callback triggered after successful authenticationonDisconnect?: () => void– Callback triggered after logoutbalanceType?: "cadence" | "evm" | "combined"– Specifies which balance to display (default:"cadence"). Options:"cadence": Shows the FLOW token balance from the Cadence side"evm": Shows the FLOW token balance from the Flow EVM side"combined": Shows the total combined FLOW token balance from both sides
_10import { Connect } from "@onflow/react-sdk"_10_10<Connect_10  onConnect={() => console.log("Connected!")}_10  onDisconnect={() => console.log("Logged out")}_10/>
Live Demo
TransactionButton
Button component for executing Flow transactions with built-in loading states and global transaction management.
Props:
transaction: Parameters<typeof mutate>[0]– Flow transaction object to execute when clickedlabel?: string– Optional custom button label (default:"Execute Transaction")mutation?: UseMutationOptions<string, Error, Parameters<typeof mutate>[0]>– Optional TanStack React Query mutation options...buttonProps– All otherButtonPropsexceptonClickandchildren(includesvariant,disabled,className, etc.)
_23import { TransactionButton } from "@onflow/react-sdk"_23_23const myTransaction = {_23  cadence: `_23    transaction() {_23      prepare(acct: &Account) {_23        log("Hello from ", acct.address)_23      }_23    }_23  `,_23  args: (arg, t) => [],_23  limit: 100,_23}_23_23<TransactionButton_23  transaction={myTransaction}_23  label="Say Hello"_23  variant="primary"_23  mutation={{_23    onSuccess: (txId) => console.log("Transaction sent:", txId),_23    onError: (error) => console.error("Transaction failed:", error),_23  }}_23/>
Live Demo
TransactionDialog
Dialog component for real-time transaction status updates.
Props:
open: boolean– Whether the dialog is openonOpenChange: (open: boolean) => void– Callback to open/close dialogtxId?: string– Optional Flow transaction ID to trackonSuccess?: () => void– Optional callback when transaction is successfulpendingTitle?: string– Optional custom pending state titlependingDescription?: string– Optional custom pending state descriptionsuccessTitle?: string– Optional custom success state titlesuccessDescription?: string– Optional custom success state descriptioncloseOnSuccess?: boolean– Iftrue, closes the dialog automatically after success
_11import { TransactionDialog } from "@onflow/react-sdk"_11_11_11<TransactionDialog_11  open={isOpen}_11  onOpenChange={setIsOpen}_11  txId="6afa38b7bd1a23c6cc01a4ea2e51ed376f16761f9d06eca0577f674a9edc0716"_11  pendingTitle="Sending..."_11  successTitle="All done!"_11  closeOnSuccess_11/>
Live Demo
TransactionLink
Link to the block explorer with the appropriate network scoped to transaction ID.
Props:
txId: string– The transaction ID to link tovariant?: ButtonProps["variant"]– Optional button variant (defaults to"link")
_10import { TransactionLink } from "@onflow/react-sdk"_10_10<TransactionLink txId="your-tx-id" />
Live Demo
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.
useFlowCurrentUser
_10import { useFlowCurrentUser } from "@onflow/react-sdk"
Parameters
flowClient?: FlowClient- OptionalFlowClientinstance
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 } = useFlowCurrentUser()_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/react-sdk"
Parameters:
address?: string– Flow address (with or without0xprefix)query?: UseQueryOptions<Account | null, Error>– Optional TanStackQuery optionsflowClient?: FlowClient- OptionalFlowClientinstance
Returns: UseQueryResult<Account | null, Error>
_19function AccountDetails() {_19  const { data: account, isLoading, error, refetch } = useFlowAccount({_19    address: "0x1cf0e2f2f715450",_19    query: { staleTime: 5000 },_19  })_19_19  if (isLoading) return <p>Loading account...</p>_19  if (error) return <p>Error fetching account: {error.message}</p>_19  if (!account) return <p>No account data</p>_19_19  return (_19    <div>_19      <h2>Account: {account.address}</h2>_19      <p>Balance: {account.balance}</p>_19      <pre>{account.code}</pre>_19      <button onClick={refetch}>Refetch</button>_19    </div>_19  )_19}
useFlowBlock
_10import { useFlowBlock } from "@onflow/react-sdk"
Parameters:
sealed?: boolean– Iftrue, fetch latest sealed blockid?: string– Block by IDheight?: number– Block by heightquery?: UseQueryOptions<Block | null, Error>– Optional TanStackQuery optionsflowClient?: FlowClient- OptionalFlowClientinstance
Only one of sealed, id, or height should be provided.
Returns: UseQueryResult<Block | null, Error>
_14function LatestBlock() {_14  const { data: block, isLoading, error } = useFlowBlock({ query: { staleTime: 10000 } })_14_14  if (isLoading) return <p>Loading...</p>_14  if (error) return <p>Error: {error.message}</p>_14  if (!block) return <p>No block data.</p>_14_14  return (_14    <div>_14      <h2>Block {block.height}</h2>_14      <p>ID: {block.id}</p>_14    </div>_14  )_14}
useFlowChainId
_10import { useFlowChainId } from "@onflow/react-sdk"
This hook retrieves the Flow chain ID, which is useful for identifying the current network.
Parameters:
query?: Omit<UseQueryOptions<string | null>, "queryKey" | "queryFn">– Optional TanStack Query options likestaleTime,enabled, etc.flowClient?: FlowClient- OptionalFlowClientinstance
Returns: UseQueryResult<string | null, Error>
Valid chain IDs include: testnet (Flow Testnet), mainnet (Flow Mainnet), and emulator (Flow Emulator).  The flow- prefix will be stripped from the chain ID returned by the access node (e.g. flow-testnet will return testnet).
_10function ChainIdExample() {_10  const { data: chainId, isLoading, error } = useFlowChainId({_10    query: { staleTime: 10000 },_10  })_10_10  if (isLoading) return <p>Loading chain ID...</p>_10  if (error) return <p>Error fetching chain ID: {error.message}</p>_10_10  return <div>Current Flow Chain ID: {chainId}</div>_10}
useFlowClient
This hook returns the FlowClient for the current <FlowProvider /> context.
Parameters:
flowClient?: FlowClient- OptionalFlowClientinstance to override the result
useFlowConfig
_10import { useFlowConfig } from "@onflow/react-sdk"
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/react-sdk"
Parameters:
startBlockId?: string– Optional ID of the block to start listening fromstartHeight?: number– Optional block height to start listening fromeventTypes?: string[]– Array of event type strings (e.g.,A.0xDeaDBeef.Contract.EventName)addresses?: string[]– Filter by Flow addressescontracts?: string[]– Filter by contract identifiersopts?: { heartbeatInterval?: number }– Options for subscription heartbeatonEvent: (event: Event) => void– Callback for each event receivedonError?: (error: Error) => void– Optional error handlerflowClient?: FlowClient- OptionalFlowClientinstance
Example:
_10function EventListener() {_10  useFlowEvents({_10    eventTypes: ["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/react-sdk"
Parameters:
cadence: string– Cadence script to runargs?: (arg, t) => unknown[]– Function returning FCL argumentsquery?: UseQueryOptions<unknown, Error>– Optional TanStackQuery optionsflowClient?: FlowClient- OptionalFlowClientinstance
Returns: UseQueryResult<unknown, Error>
_22function QueryExample() {_22  const { data, isLoading, error, refetch } = useFlowQuery({_22    cadence: `_22      access(all)_22      fun main(a: Int, b: Int): Int {_22        return a + b_22      }_22    `,_22    args: (arg, t) => [arg(1, t.Int), arg(2, t.Int)],_22    query: { staleTime: 10000 },_22  })_22_22  if (isLoading) return <p>Loading query...</p>_22  if (error) return <p>Error: {error.message}</p>_22_22  return (_22    <div>_22      <p>Result: {data}</p>_22      <button onClick={refetch}>Refetch</button>_22    </div>_22  )_22}
useFlowQueryRaw
_10import { useFlowQueryRaw } from "@onflow/react-sdk"
This hook is identical to useFlowQuery but returns the raw, non-decoded response data from the Flow blockchain. This is useful when you need access to the original response structure or want to handle decoding manually.
Parameters:
cadence: string– Cadence script to runargs?: (arg, t) => unknown[]– Function returning FCL argumentsquery?: UseQueryOptions<unknown, Error>– Optional TanStackQuery optionsflowClient?: FlowClient- OptionalFlowClientinstance
Returns: UseQueryResult<unknown, Error>
The returned data will be in its raw, non-decoded format as received from the Flow access node.
_22function QueryRawExample() {_22  const { data: rawData, isLoading, error, refetch } = useFlowQueryRaw({_22    cadence: `_22      access(all)_22      fun main(a: Int, b: Int): Int {_22        return a + b_22      }_22    `,_22    args: (arg, t) => [arg(1, t.Int), arg(2, t.Int)],_22    query: { staleTime: 10000 },_22  })_22_22  if (isLoading) return <p>Loading query...</p>_22  if (error) return <p>Error: {error.message}</p>_22_22  return (_22    <div>_22      <p>Raw Result: {JSON.stringify(rawData, null, 2)}</p>_22      <button onClick={refetch}>Refetch</button>_22    </div>_22  )_22}
useFlowMutate
_10import { useFlowMutate } from "@onflow/react-sdk"
Parameters:
mutation?: UseMutationOptions<string, Error, FCLMutateParams>– Optional TanStackQuery mutation optionsflowClient?: FlowClient- OptionalFlowClientinstance
Returns: UseMutationResult<string, Error, FCLMutateParams>
_33function CreatePage() {_33  const { mutate, isPending, error, data: txId } = useFlowMutate({_33    mutation: {_33      onSuccess: (txId) => console.log("TX ID:", txId),_33    },_33  })_33_33  const sendTransaction = () => {_33    mutate({_33      cadence: `transaction() {_33        prepare(acct: &Account) {_33          log(acct.address)_33        }_33      }`,_33      args: (arg, t) => [],_33      proposer: fcl.currentUser,_33      payer: fcl.currentUser,_33      authorizations: [],_33      limit: 100,_33    })_33  }_33_33  return (_33    <div>_33      <button onClick={sendTransaction} disabled={isPending}>_33        Send Transaction_33      </button>_33      {isPending && <p>Sending transaction...</p>}_33      {error && <p>Error: {error.message}</p>}_33      {txId && <p>Transaction ID: {txId}</p>}_33    </div>_33  )_33}
useFlowRevertibleRandom
_10import { useFlowRevertibleRandom } from "@onflow/react-sdk"
Parameters:
min?: string– Minimum random value (inclusive), as a UInt256 decimal string. Defaults to"0".max: string– Maximum random value (inclusive), as a UInt256 decimal string. Required.count?: number– Number of random values to fetch (must be at least 1). Defaults to1.query?: Omit<UseQueryOptions<any, Error>, "queryKey" | "queryFn">– Optional TanStack Query settings likestaleTime,enabled,retry, etc.flowClient?: FlowClient- OptionalFlowClientinstance
Returns: UseQueryResult<RevertibleRandomResult[], Error>
Each RevertibleRandomResult includes:
blockHeight: string— The block height from which the random value was generated.value: string— The random UInt256 value, returned as a decimal string.
_26function RandomValues() {_26  const { data: randoms, isLoading, error, refetch } = useFlowRevertibleRandom({_26    min: "0",_26    max: "1000000000000000000000000", // Example large max_26    count: 3,_26    query: { staleTime: 10000 },_26  })_26_26  if (isLoading) return <p>Loading random numbers...</p>_26  if (error) return <p>Error fetching random numbers: {error.message}</p>_26  if (!randoms) return <p>No random values generated.</p>_26_26  return (_26    <div>_26      <h2>Generated Random Numbers</h2>_26      <ul>_26        {randoms.map((rand, idx) => (_26          <li key={idx}>_26            Block {rand.blockHeight}: {rand.value}_26          </li>_26        ))}_26      </ul>_26      <button onClick={refetch}>Regenerate</button>_26    </div>_26  )_26}
Notes:
- Randomness is generated using the onchain 
revertibleRandomfunction on Flow, producing pseudorandom values tied to block and script execution. - Values are deterministic: The values returned for identical calls within the same block will be identical.
 - If 
countis larger than one, the returned values are distinct. - This hook is designed for simple use cases that don't require unpredictability, such as randomized UIs. Since the hook uses script executions on existing blocks, the random source is already public and the randoms are predictable.
 - For more advanced use cases that do require onchain randomness logic via transactions, Flow provides built-in support using Cadence's 
revertibleRandomand commit-reveal scheme. 
useFlowTransaction
_10import { useFlowTransaction } from "@onflow/react-sdk"
Fetches a Flow transaction by ID and returns the decoded transaction object.
Parameters:
txId?: string– The Flow transaction ID to fetch.query?: Omit<UseQueryOptions<Transaction | null, Error>, "queryKey" | "queryFn">– Optional TanStack Query options likestaleTime,enabled, etc.flowClient?: FlowClient- OptionalFlowClientinstance
Returns: UseQueryResult<Transaction | null, Error>
_19function TransactionDetails({ txId }: { txId: string }) {_19  const { data: transaction, isLoading, error, refetch } = useFlowTransaction({_19    txId,_19    query: { staleTime: 10000 },_19  })_19_19  if (isLoading) return <p>Loading transaction...</p>_19  if (error) return <p>Error fetching transaction: {error.message}</p>_19  if (!transaction) return <p>No transaction data.</p>_19_19  return (_19    <div>_19      <h2>Transaction ID: {transaction.id}</h2>_19      <p>Gas Limit: {transaction.gasLimit}</p>_19      <pre>Arguments: {JSON.stringify(transaction.arguments, null, 2)}</pre>_19      <button onClick={refetch}>Refetch</button>_19    </div>_19  )_19}
useFlowTransactionStatus
_10import { useFlowTransactionStatus } from "@onflow/react-sdk"
Parameters:
id: string– Transaction ID to subscribe toflowClient?: FlowClient- OptionalFlowClientinstance
Returns:
transactionStatus: TransactionStatus | nullerror: Error | null
_10function TransactionStatusComponent() {_10  const txId = "your-transaction-id-here"_10  const { transactionStatus, error } = useFlowTransactionStatus({ id: txId })_10_10  if (error) return <div>Error: {error.message}</div>;_10_10  return <div>Status: {transactionStatus?.statusString}</div>;_10}
useDarkMode
_10import { useDarkMode } from "@onflow/react-sdk"
This hook provides access to the current dark mode state from the FlowProvider. It's useful for conditionally rendering content or applying custom styling based on the current theme.
Returns:
isDark: boolean– Whether dark mode is currently enabled
_10function ThemeAwareComponent() {_10  const { isDark } = useDarkMode()_10_10  return (_10    <div className={isDark ? "bg-gray-900 text-white" : "bg-white text-black"}>_10      <h2>Current Theme: {isDark ? "Dark" : "Light"}</h2>_10      <p>This component adapts to the current theme!</p>_10    </div>_10  )_10}
Cross-VM Hooks
useCrossVmBatchTransaction
_10import { useCrossVmBatchTransaction } from "@onflow/react-sdk"
This hook allows you to execute multiple EVM transactions in a single atomic Cadence transaction. It is useful for batch processing EVM calls while ensuring they are executed together, either all succeeding or allowing for some to fail without affecting the others.
Parameters:
mutation?: UseMutationOptions<string, Error, UseCrossVmBatchTransactionMutateArgs>– Optional TanStackQuery mutation optionsflowClient?: FlowClient- OptionalFlowClientinstance
Returns: UseCrossVmBatchTransactionResult
Where UseCrossVmBatchTransactionResult is defined as:
_10interface UseCrossVmBatchTransactionResult extends Omit<_10  UseMutationResult<string, Error, UseCrossVmBatchTransactionMutateArgs>,_10  "mutate" | "mutateAsync"_10> {_10  mutate: (calls: UseCrossVmBatchTransactionMutateArgs) => void_10  mutateAsync: (calls: UseCrossVmBatchTransactionMutateArgs) => Promise<string>_10}
Where UseCrossVmBatchTransactionMutateArgs is defined as:
_10interface UseCrossVmBatchTransactionMutateArgs {_10  calls: EvmBatchCall[]_10  mustPass?: boolean_10}
Where EvmBatchCall is defined as:
_14interface EvmBatchCall {_14  // The target EVM contract address (as a string)_14  address: string_14  // The contract ABI fragment_14  abi: Abi_14  // The name of the function to call_14  functionName: string_14  // The function arguments_14  args?: readonly unknown[]_14  // The gas limit for the call_14  gasLimit?: bigint_14  // The value to send with the call_14  value?: bigint_14}
_35function CrossVmBatchTransactionExample() {_35  const { sendBatchTransaction, isPending, error, data: txId } = useCrossVmBatchTransaction({_35    mutation: {_35      onSuccess: (txId) => console.log("TX ID:", txId),_35    },_35  })_35_35  const sendTransaction = () => {_35    const calls = [_35      {_35        address: "0x1234567890abcdef",_35        abi: {_35          // ABI definition for the contract_35        },_35        functionName: "transfer",_35        args: ["0xabcdef1234567890", 100n], // Example arguments_35        gasLimit: 21000n, // Example gas limit_35      },_35      // Add more calls as needed_35    ]_35_35    sendBatchTransaction({calls})_35  }_35_35  return (_35    <div>_35      <button onClick={sendTransaction} disabled={isPending}>_35        Send Cross-VM Transaction_35      </button>_35      {isPending && <p>Sending transaction...</p>}_35      {error && <p>Error: {error.message}</p>}_35      {txId && <p>Transaction ID: {txId}</p>}_35    </div>_35  )_35}
useCrossVmTokenBalance
_10import { useCrossVmTokenBalance } from "@onflow/react-sdk"
Fetch the balance of a token balance for a given user across both Cadence and EVM environments.
Parameters:
owner: string– Cadence address of the account whose token balances you want.vaultIdentifier?: string– Optional Cadence resource identifier (e.g. "0x1cf0e2f2f715450.FlowToken.Vault") for onchain balanceerc20AddressHexArg?: string– Optional bridged ERC-20 contract address (hex) for EVM/COA balancequery?: Omit<UseQueryOptions<unknown, Error>, "queryKey" | "queryFn">– Optional TanStack Query config (e.g. staleTime, enabled)flowClient?: FlowClient- OptionalFlowClientinstance
Note: You must pass
owner, and one ofvaultIdentifierorerc20AddressHexArg.
Returns: UseQueryResult<UseCrossVmTokenBalanceData | null, Error>
Where UseCrossVmTokenBalanceData is defined as:
_10interface UseCrossVmTokenBalanceData {_10  cadence: TokenBalance // Token balance of Cadence vault_10  evm: TokenBalance // Token balance of EVM (COA stored in /storage/coa)_10  combined: TokenBalance // Combined balance of both Cadence and EVM_10}
Where TokenBalance is defined as:
_10interface TokenBalance {_10  value: bigint // Balance value in smallest unit_10  formatted: string // Formatted balance string (e.g. "123.45")_10  precision: number // Number of decimal places for the token_10}
_20function UseCrossVmTokenBalanceExample() {_20  const { data, isLoading, error, refetch } = useCrossVmTokenBalance({_20    owner: '0x1e4aa0b87d10b141',_20    vaultIdentifier: 'A.1654653399040a61.FlowToken.Vault',_20    query: { staleTime: 10000 },_20  });_20_20  if (isLoading) return <p>Loading token balance...</p>;_20  if (error) return <p>Error fetching token balance: {error.message}</p>;_20_20  return (_20    <div>_20      <h2>Token Balances</h2>_20      <p>Cadence Balance: {data.cadence.formatted} (Value: {data.cadence.value})</p>_20      <p>EVM Balance: {data.evm.formatted} (Value: {data.evm.value})</p>_20      <p>Combined Balance: {data.combined.formatted} (Value: {data.combined.value})</p>_20      <button onClick={refetch}>Refetch</button>_20    </div>_20  )_20}
useCrossVmSpendNft
_10import { useCrossVmSpendNft } from "@onflow/react-sdk"
Bridge NFTs from Cadence to Flow EVM and execute arbitrary EVM transactions to atomically spend them.
Parameters:
mutation?: UseMutationOptions<string, Error, UseCrossVmSpendFtMutateArgs>– Optional TanStackQuery mutation optionsflowClient?: FlowClient- OptionalFlowClientinstance
Where UseCrossVmSpendFtMutateArgs is defined as:
_10interface UseCrossVmSpendFtMutateArgs {_10  nftIdentifier: string // Cadence NFT identifier (e.g. "0x1cf0e2f2f715450.FlowNFT")_10  nftIds: string[] // Array of NFT IDs to bridge_10  calls: EVMBatchCall[] // Array of EVM calls to execute atomically_10}
Returns: UseCrossVmSpendNftResult
Where UseCrossVmSpendNftResult is defined as:
_10interface UseCrossVmSpendNftResult extends Omit<_10  UseMutationResult<string, Error, CrossVmSpendNftParams>,_10  "mutate" | "mutateAsync"_10> {_10  spendNft: (params: CrossVmSpendNftParams) => Promise<string>_10  spendNftAsync: (params: CrossVmSpendNftParams) => Promise<string>_10}
_31function CrossVmSpendNftExample() {_31  const { spendNft, isPending, error, data: txId } = useCrossVmSpendNft()_31_31  const handleSpendNft = () => {_31    spendNft({_31      nftIdentifier: "0x1cf0e2f2f715450.FlowNFT", // Cadence NFT identifier_31      nftIds: ["1"], // Array of NFT IDs to bridge_31      calls: [_31        {_31          abi: contractAbi, // ABI of the EVM contract_31          contractAddress: "0x1234567890abcdef1234567890abcdef12345678", // EVM contract address_31          functionName: "transferNFT",_31          args: ["123"], // Example args_31          value: "1000000000000000000", // Amount in wei (if applicable)_31          gasLimit: "21000", // Gas limit for the EVM call_31        },_31      ],_31    })_31  }_31_31  return (_31    <div>_31      <button onClick={handleSpendNft} disabled={isPending}>_31        Bridge and Spend NFT_31      </button>_31      {isPending && <p>Sending transaction...</p>}_31      {error && <p>Error: {error.message}</p>}_31      {txId && <p>Transaction ID: {txId}</p>}_31    </div>_31  )_31}
useCrossVmSpendToken
_10import { useCrossVmSpendToken } from "@onflow/react-sdk"
Bridge FTs from Cadence to Flow EVM and execute arbitrary EVM transactions to atomically spend them.
Parameters:
mutation?: UseMutationOptions<string, Error, UseCrossVmSpendTokenMutateArgs>– Optional TanStackQuery mutation optionsflowClient?: FlowClient- OptionalFlowClientinstance
Where UseCrossVmSpendTokenMutateArgs is defined as:
_10interface UseCrossVmSpendTokenMutateArgs {_10  vaultIdentifier: string; // Cadence vault identifier (e.g. "0x1cf0e2f2f715450.ExampleToken.Vault")_10  amount: string; // Amount of tokens to bridge, as a decimal string (e.g. "1.23")_10  calls: EVMBatchCall[]; // Array of EVM calls to execute after bridging_10}
Returns: UseCrossVmSpendTokenResult
Where UseCrossVmSpendTokenResult is defined as:
_10interface UseCrossVmSpendTokenResult extends Omit<_10  UseMutationResult<string, Error, UseCrossVmSpendTokenMutateArgs>,_10  "mutate" | "mutateAsync"_10> {_10  spendToken: (args: UseCrossVmSpendTokenMutateArgs) => void; // Function to trigger the FT bridging and EVM calls_10  spendTokenAsync: (args: UseCrossVmSpendTokenMutateArgs) => Promise<string>; // Async version of spendToken_10}
_31function CrossVmSpendTokenExample() {_31  const { spendToken, isPending, error, data: txId } = useCrossVmSpendToken()_31_31  const handleSpendToken = () => {_31    spendToken({_31      vaultIdentifier: "0x1cf0e2f2f715450.ExampleToken.Vault", // Cadence vault identifier_31      amount: "1.23", // Amount of tokens to bridge to EVM_31      calls: [_31        {_31          abi: myEvmContractAbi, // EVM contract ABI_31          address: "0x01234567890abcdef01234567890abcdef", // EVM contract address_31          function: "transfer", // EVM function to call_31          args: [_31            "0xabcdef01234567890abcdef01234567890abcdef", // Recipient address_31          ],_31        },_31      ],_31    })_31  }_31_31  return (_31    <div>_31      <button onClick={handleSpendToken} disabled={isPending}>_31        Bridge and Spend FTs_31      </button>_31      {isPending && <p>Sending transaction...</p>}_31      {error && <p>Error: {error.message}</p>}_31      {txId && <p>Cadence Transaction ID: {txId}</p>}_31    </div>_31  )_31}
useCrossVmTransactionStatus
_10import { useCrossVmTransactionStatus } from "@onflow/react-sdk"
Subscribes to status updates for a given Cross-VM Flow transaction ID that executes EVM calls. This hook monitors the transaction status and extracts EVM call results if available.
Parameters:
id?: string– Optional Flow transaction ID to monitorflowClient?: FlowClient- OptionalFlowClientinstance
Returns: UseCrossVmTransactionStatusResult
Where UseCrossVmTransactionStatusResult is defined as:
_10interface UseCrossVmTransactionStatusResult {_10  transactionStatus: TransactionStatus | null // Latest transaction status, or null before any update_10  evmResults?: CallOutcome[] // EVM transaction results, if available_10  error: Error | null // Any error encountered during status updates_10}
Where CallOutcome is defined as:
_10interface CallOutcome {_10  status: "passed" | "failed" | "skipped" // Status of the EVM call_10  hash?: string // EVM transaction hash if available_10  errorMessage?: string // Error message if the call failed_10}
_26function CrossVmTransactionStatusComponent() {_26  const txId = "your-cross-vm-transaction-id-here"_26  const { transactionStatus, evmResults, error } = useCrossVmTransactionStatus({ id: txId })_26_26  if (error) return <div>Error: {error.message}</div>_26_26  return (_26    <div>_26      <div>Flow Status: {transactionStatus?.statusString}</div>_26      {evmResults && evmResults.length > 0 && (_26        <div>_26          <h3>EVM Call Results:</h3>_26          <ul>_26            {evmResults.map((result, idx) => (_26              <li key={idx}>_26                Status: {result.status}_26                {result.hash && <span> | Hash: {result.hash}</span>}_26                {result.errorMessage && <span> | Error: {result.errorMessage}</span>}_26              </li>_26            ))}_26          </ul>_26        </div>_26      )}_26    </div>_26  )_26}