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 server-side integration for bots, payment processors, or any backend service that needs to swap tokens programmatically.

Prerequisites

npm install viem dotenv
Create a .env file:
.env
AKKA_API_KEY=your_api_key
PRIVATE_KEY=0xabc123...  # your wallet private key

Full working script

This script checks allowance, approves if needed, and executes a swap — all from the command line.
swap.ts
import 'dotenv/config';
import {
  createPublicClient,
  createWalletClient,
  http,
  parseUnits,
  formatUnits,
  defineChain,
} from 'viem';
import { privateKeyToAccount } from 'viem/accounts';

// ── Config ──────────────────────────────────────────────────────────
const API_BASE = 'https://api.akka.finance';
const API_KEY = process.env.AKKA_API_KEY!;
const PRIVATE_KEY = process.env.PRIVATE_KEY! as `0x${string}`;

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

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

const account = privateKeyToAccount(PRIVATE_KEY);
const publicClient = createPublicClient({ chain: hyperEVM, transport: http() });
const walletClient = createWalletClient({ chain: hyperEVM, transport: http(), account });

// ── API helpers ─────────────────────────────────────────────────────
async function akkaGet<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 body = await res.json();
    throw new Error(body.message || `HTTP ${res.status}`);
  }
  return res.json();
}

// ── Swap flow ───────────────────────────────────────────────────────
async function swap(
  src: string,
  dst: string,
  amount: string,   // in wei
  slippage: number,
) {
  const from = account.address;

  // 1. Check allowance (skip for native token)
  if (src.toLowerCase() !== NATIVE) {
    console.log('Checking allowance...');
    const { allowance } = await akkaGet<{ allowance: string }>(
      `/swap/v1/${CHAIN_ID}/approve/allowance`,
      { tokenAddress: src, walletAddress: from },
    );

    if (BigInt(allowance) < BigInt(amount)) {
      console.log('Approving token spend...');
      const approveTx = await akkaGet<{ to: string; data: string; value: string }>(
        `/swap/v1/${CHAIN_ID}/approve/transaction`,
        { tokenAddress: src },
      );

      const approveHash = await walletClient.sendTransaction({
        to: approveTx.to as `0x${string}`,
        data: approveTx.data as `0x${string}`,
        value: BigInt(approveTx.value),
      });
      await publicClient.waitForTransactionReceipt({ hash: approveHash });
      console.log(`Approved: ${approveHash}`);
    } else {
      console.log('Allowance sufficient, skipping approval.');
    }
  }

  // 2. Get swap transaction
  console.log('Fetching swap data...');
  const swapData = await akkaGet<{
    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(),
  });

  // 3. Execute
  console.log('Sending swap transaction...');
  const { tx } = swapData;
  const hash = await walletClient.sendTransaction({
    to: tx.to as `0x${string}`,
    data: tx.data as `0x${string}`,
    value: BigInt(tx.value),
    gasPrice: BigInt(tx.gasPrice),
    gas: BigInt(tx.gas),
  });

  const receipt = await publicClient.waitForTransactionReceipt({ hash });
  console.log(`Swap confirmed in block ${receipt.blockNumber}`);
  console.log(`TX: https://hyperevmscan.io/tx/${hash}`);
  console.log(`Output: ${swapData.dstAmount} wei`);
}

// ── Run ─────────────────────────────────────────────────────────────
const SRC = '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee';  // HYPE
const DST = '0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb';  // UBTC
const AMOUNT = parseUnits('1', 18).toString();               // 1 HYPE
const SLIPPAGE = 1;                                          // 1%

swap(SRC, DST, AMOUNT, SLIPPAGE).catch(console.error);
Run it:
npx tsx swap.ts

Reusable client class

For services that make multiple swaps, wrap the logic into a class:
akkaClient.ts
const API_BASE = 'https://api.akka.finance';

export class AkkaClient {
  constructor(
    private apiKey: string,
    private chainId: number = 999,
  ) {}

  private async get<T>(path: string, params: Record<string, string> = {}): Promise<T> {
    const url = `${API_BASE}${path}?${new URLSearchParams(params)}`;
    const res = await fetch(url, { headers: { apikey: this.apiKey } });
    if (!res.ok) {
      const body = await res.json();
      throw new Error(body.message || `HTTP ${res.status}`);
    }
    return res.json();
  }

  async quote(src: string, dst: string, amount: string) {
    return this.get<{ dstAmount: string; gas?: string }>(
      `/swap/v1/${this.chainId}/quote`,
      { src, dst, amount, includeGas: 'true' },
    );
  }

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

  async allowance(tokenAddress: string, walletAddress: string) {
    return this.get<{ allowance: string }>(
      `/swap/v1/${this.chainId}/approve/allowance`,
      { tokenAddress, walletAddress },
    );
  }

  async approveTransaction(tokenAddress: string) {
    return this.get<{ to: string; data: string; value: string }>(
      `/swap/v1/${this.chainId}/approve/transaction`,
      { tokenAddress },
    );
  }

  async tokens(verified = true) {
    return this.get<{ tokens: Record<string, any> }>(
      `/${this.chainId}/tokens`,
      { verified: String(verified) },
    );
  }
}
Usage:
const akka = new AkkaClient(process.env.AKKA_API_KEY!);

const { dstAmount } = await akka.quote(SRC, DST, amount);
console.log(`Expected output: ${dstAmount}`);

Polling for price changes

Monitor a pair and swap when the rate is favorable:
priceMonitor.ts
import { AkkaClient } from './akkaClient';
import { parseUnits, formatUnits } from 'viem';

const akka = new AkkaClient(process.env.AKKA_API_KEY!);

const SRC = '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee';
const DST = '0xB8CE59FC3717ada4C02eaDF9682A9e934F625ebb';
const AMOUNT = parseUnits('10', 18).toString(); // 10 HYPE
const TARGET_RATE = 0.0005; // trigger when 10 HYPE buys >= 0.0005 UBTC

async function monitor() {
  console.log('Monitoring price...');

  setInterval(async () => {
    try {
      const { dstAmount } = await akka.quote(SRC, DST, AMOUNT);
      const output = Number(formatUnits(BigInt(dstAmount), 18));
      console.log(`${new Date().toISOString()} — 10 HYPE → ${output.toFixed(8)} UBTC`);

      if (output >= TARGET_RATE) {
        console.log('Target rate reached!');
        // Execute swap or send notification here
      }
    } catch (err) {
      console.error('Quote failed:', err);
    }
  }, 15_000); // every 15 seconds
}

monitor();
All amounts are in wei (the smallest unit). Use parseUnits and formatUnits from viem to convert between human-readable amounts and wei.