Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.akka.finance/llms.txt

Use this file to discover all available pages before exploring further.

A complete guide to wiring AKKA’s API into a wagmi + viem frontend. By the end, you’ll have a working swap flow: connect wallet, check allowance, approve, and execute.

Prerequisites

npm install wagmi viem @tanstack/react-query

1. Chain Configuration

Define HyperEVM as a custom chain for wagmi:
config.ts
import { defineChain } from 'viem';
import { createConfig, http } from 'wagmi';

export const hyperEVM = defineChain({
  id: 999,
  name: 'HyperEVM',
  nativeCurrency: { name: 'HYPE', symbol: 'HYPE', decimals: 18 },
  rpcUrls: {
    default: { http: ['https://rpc.hyperliquid.xyz/evm'] },
  },
  blockExplorers: {
    default: { name: 'HyperEVM Scan', url: 'https://hyperevmscan.io' },
  },
});

export const config = createConfig({
  chains: [hyperEVM],
  transports: {
    [hyperEVM.id]: http(),
  },
});

2. AKKA API Client

A thin wrapper around the AKKA API:
akka.ts
const API_BASE = 'https://api.akka.finance';
const API_KEY = process.env.NEXT_PUBLIC_AKKA_API_KEY!;

const NATIVE_TOKEN = '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee';
const CHAIN_ID = 999;

async function akkaFetch<T>(path: string, params: Record<string, string>): Promise<T> {
  const url = `${API_BASE}${path}?${new URLSearchParams(params)}`;
  const res = await fetch(url, { headers: { apikey: API_KEY } });

  if (!res.ok) {
    const error = await res.json();
    throw new Error(error.message || 'AKKA API error');
  }
  return res.json();
}

export async function getQuote(src: string, dst: string, amount: string) {
  return akkaFetch<{
    dstAmount: string;
    srcToken?: { symbol: string; decimals: number };
    dstToken?: { symbol: string; decimals: number };
    gas?: string;
  }>(`/swap/v1/${CHAIN_ID}/quote`, {
    src, dst, amount,
    includeTokensInfo: 'true',
    includeGas: 'true',
  });
}

export async function getSwap(
  src: string, dst: string, amount: string,
  from: string, slippage: number,
) {
  return akkaFetch<{
    dstAmount: string;
    tx: { to: string; data: string; value: string; gasPrice: string; gas: string };
  }>(`/swap/v1/${CHAIN_ID}/swap`, {
    src, dst, amount, from,
    slippage: slippage.toString(),
  });
}

export async function getAllowance(tokenAddress: string, walletAddress: string) {
  return akkaFetch<{ allowance: string }>(
    `/swap/v1/${CHAIN_ID}/approve/allowance`,
    { tokenAddress, walletAddress },
  );
}

export async function getApproveTransaction(tokenAddress: string) {
  return akkaFetch<{ data: string; to: string; value: string; gasPrice: string }>(
    `/swap/v1/${CHAIN_ID}/approve/transaction`,
    { tokenAddress },
  );
}

export function isNativeToken(address: string) {
  return address.toLowerCase() === NATIVE_TOKEN;
}

3. Connect Wallet + Execute Swap

Wire the API client into wagmi hooks:
SwapButton.tsx
import { useAccount, useSendTransaction, useWaitForTransactionReceipt } from 'wagmi';
import { useState } from 'react';
import { getSwap, getAllowance, getApproveTransaction, isNativeToken } from './akka';

interface SwapButtonProps {
  src: string;
  dst: string;
  amount: string;  // in wei
  slippage: number;
}

export function SwapButton({ src, dst, amount, slippage }: SwapButtonProps) {
  const { address } = useAccount();
  const { sendTransactionAsync } = useSendTransaction();
  const [status, setStatus] = useState<'idle' | 'approving' | 'swapping' | 'done' | 'error'>('idle');
  const [txHash, setTxHash] = useState<string>();
  const [error, setError] = useState<string>();

  const handleSwap = async () => {
    if (!address) return;
    setError(undefined);

    try {
      // Step 1: Check & handle approval (skip for native tokens)
      if (!isNativeToken(src)) {
        setStatus('approving');
        const { allowance } = await getAllowance(src, address);

        if (BigInt(allowance) < BigInt(amount)) {
          const approveTx = await getApproveTransaction(src);
          const approveHash = await sendTransactionAsync({
            to: approveTx.to as `0x${string}`,
            data: approveTx.data as `0x${string}`,
            value: BigInt(approveTx.value),
          });
          // Wait for approval to confirm before swapping
          await waitForReceipt(approveHash);
        }
      }

      // Step 2: Execute swap
      setStatus('swapping');
      const swap = await getSwap(src, dst, amount, address, slippage);
      const { tx } = swap;

      const hash = await sendTransactionAsync({
        to: tx.to as `0x${string}`,
        data: tx.data as `0x${string}`,
        value: BigInt(tx.value),
        gasPrice: BigInt(tx.gasPrice),
        gas: BigInt(tx.gas),
      });

      setTxHash(hash);
      setStatus('done');
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Swap failed');
      setStatus('error');
    }
  };

  return (
    <div>
      <button onClick={handleSwap} disabled={!address || status === 'approving' || status === 'swapping'}>
        {status === 'approving' && 'Approving...'}
        {status === 'swapping' && 'Swapping...'}
        {status === 'idle' && 'Swap'}
        {status === 'done' && 'Done!'}
        {status === 'error' && 'Retry'}
      </button>
      {error && <p style={{ color: 'red' }}>{error}</p>}
      {txHash && (
        <a href={`https://hyperevmscan.io/tx/${txHash}`} target="_blank" rel="noreferrer">
          View transaction
        </a>
      )}
    </div>
  );
}

async function waitForReceipt(hash: string): Promise<void> {
  // Simple polling — in production, use wagmi's useWaitForTransactionReceipt
  const { createPublicClient, http } = await import('viem');
  const client = createPublicClient({ transport: http('https://rpc.hyperliquid.xyz/evm') });
  await client.waitForTransactionReceipt({ hash: hash as `0x${string}` });
}

4. Full Page Example

Putting it all together:
SwapPage.tsx
import { useAccount, useConnect } from 'wagmi';
import { injected } from 'wagmi/connectors';
import { useState } from 'react';
import { parseUnits } from 'viem';
import { SwapButton } from './SwapButton';
import { useAkkaQuote } from './hooks';  // see React Hooks guide

const HYPE = '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee';
const UBTC = '0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb';

export function SwapPage() {
  const { address, isConnected } = useAccount();
  const { connect } = useConnect();
  const [inputAmount, setInputAmount] = useState('');
  const amountWei = inputAmount ? parseUnits(inputAmount, 18).toString() : '0';

  const { quote, loading } = useAkkaQuote(HYPE, UBTC, amountWei);

  if (!isConnected) {
    return <button onClick={() => connect({ connector: injected() })}>Connect Wallet</button>;
  }

  return (
    <div>
      <input
        type="number"
        placeholder="Amount in HYPE"
        value={inputAmount}
        onChange={(e) => setInputAmount(e.target.value)}
      />

      {loading && <p>Fetching quote...</p>}
      {quote && <p>You'll receive: {(Number(quote.dstAmount) / 1e18).toFixed(6)} UBTC</p>}

      <SwapButton src={HYPE} dst={UBTC} amount={amountWei} slippage={1} />
    </div>
  );
}
See the React Hooks guide for the useAkkaQuote and useAkkaSwap hooks used above.