Developer Reference

React Hooks

Drop-in React hooks for QuantumDEX — built on wagmi and the QuantumDEX SDK. Add karma-aware DeFi to your dApp in minutes.

Package @qubismic/quantumdex-reactPeer React 18+, wagmi v2Tests 157 passing

Installation

pnpm add @qubismic/quantumdex-react @qubismic/quantumdex-sdk wagmi viem @tanstack/react-query

Provider Setup

// app/providers.tsx
import { QuantumDEXProvider } from '@qubismic/quantumdex-react';
import { WagmiProvider } from 'wagmi';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { thichain, thichain_testnet } from '@qubismic/quantumdex-sdk/chains';

const queryClient = new QueryClient();
const wagmiConfig = createConfig({ chains: [thichain, thichain_testnet], ... });

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <WagmiProvider config={wagmiConfig}>
      <QueryClientProvider client={queryClient}>
        <QuantumDEXProvider
          chainId={420420}
          rpcUrl="https://rpc.thichain.io"
        >
          {children}
        </QuantumDEXProvider>
      </QueryClientProvider>
    </WagmiProvider>
  );
}

useSwap

import { useSwap } from '@qubismic/quantumdex-react';

function SwapWidget() {
  const {
    quote,
    isLoading,
    isError,
    executeSwap,
    isPending,
    hash,
  } = useSwap({
    tokenIn:  '0x...USDC',
    tokenOut: '0x...THI',
    amountIn: '100',        // human-readable
    slippageTolerance: 0.5, // %
  });

  return (
    <div>
      {quote && (
        <p>
          Receive: {quote.amountOutFormatted} THI
          (Fee: {quote.feeBps} BPS · {quote.karmaTier})
        </p>
      )}
      <button onClick={executeSwap} disabled={isPending}>
        {isPending ? 'Swapping...' : 'Swap'}
      </button>
      {hash && <p>TX: {hash}</p>}
    </div>
  );
}

Return Value

FieldTypeDescription
quoteSwapQuote | undefinedCurrent quote (refreshes every 10s)
isLoadingbooleanQuote loading state
executeSwap() => voidExecute the swap
isPendingbooleanTX awaiting wallet confirmation
hashstring | undefinedTX hash after broadcast

usePool

import { usePool, useAddLiquidity } from '@qubismic/quantumdex-react';

function PoolInfo({ tokenA, tokenB }) {
  const { pool, isLoading } = usePool({ tokenA, tokenB });
  const { addLiquidity, isPending } = useAddLiquidity();

  if (isLoading) return <Spinner />;

  return (
    <div>
      <p>TVL: {pool.tvlFormatted}</p>
      <p>Fee: {pool.feeBps} BPS</p>
      <p>APR: {pool.apr}%</p>
    </div>
  );
}

useKarmaScore

import { useKarmaScore } from '@qubismic/quantumdex-react';

function KarmaDisplay() {
  const { karma, isLoading } = useKarmaScore();
  // Uses connected wallet address by default
  // Or pass: useKarmaScore({ address: '0x...' })

  return (
    <div className={`karma-badge tier-${karma?.tier.toLowerCase()}`}>
      {isLoading ? '...' : (
        <>
          <span>{karma.score}</span>
          <span>{karma.tier}</span>
          <span>{karma.feeBps} BPS fee</span>
        </>
      )}
    </div>
  );
}

usePerps

import { usePerps, useOpenPosition } from '@qubismic/quantumdex-react';

function PerpsTrading() {
  const { positions, markPrice } = usePerps({ pair: 'THI/USDC' });
  const { openPosition, isPending } = useOpenPosition();

  return (
    <div>
      <p>Mark Price: {markPrice}</p>
      {positions.map(pos => (
        <div key={pos.id}>
          {pos.direction} {pos.leverage}× · PnL: {pos.pnlFormatted}
        </div>
      ))}
    </div>
  );
}

useGovernance

import { useProposals, useVotingPower, useCastVote } from '@qubismic/quantumdex-react';

function GovernancePanel() {
  const { proposals } = useProposals({ state: 'ACTIVE' });
  const { votingPower } = useVotingPower();
  const { castVote } = useCastVote();

  return (
    <div>
      <p>Your veQBIT: {votingPower}</p>
      {proposals.map(p => (
        <div key={p.id}>
          <h4>{p.description}</h4>
          <button onClick={() => castVote(p.id, 1)}>Vote For</button>
        </div>
      ))}
    </div>
  );
}