A complete server-side integration for bots, payment processors, or any backend service that needs to swap tokens programmatically.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.
Prerequisites
npm install viem dotenv
.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);
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) },
);
}
}
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.