SDK Overview

@taurusswap/sdk is the TypeScript client for TaurusSwap — a concentrated-liquidity stablecoin AMM on Algorand built on the Orbital AMM design. It handles on-chain state decoding, off-chain swap math, and unsigned Algorand transaction construction.

Package: @taurusswap/sdk · Peer dep: algosdk ^3.0.0 · Testnet App ID: 758284478

What the SDK Does

  • Reads pool state — Decodes global state, the reserves box, fee_growth box, and all tick: boxes into a typed PoolState object.
  • Quotes swaps off-chain — Runs the full Newton-bisection solver and tick-crossing logic locally, matching on-chain math exactly.
  • Builds unsigned transactions — Returns algosdk.Transaction[] ready for wallet signing. Never signs or broadcasts itself.
  • LP operations — Computes deposit amounts, tick parameters from depeg prices, and claimable fees.
  • Zap — Plans single-token deposits by splitting one token into equal amounts of all pool tokens.
  • APR estimation — Combines 24h fee volume with capital efficiency to project annualised yield.

What It Doesn't Do

  • Sign transactions — Pass the returned Transaction[] to your wallet (Pera, Defly, etc.).
  • Broadcast transactions — Call algod.sendRawTransaction(signedTxns).do() yourself.
  • Manage wallets — Use algosdk or a wallet adapter for key management.

Two Usage Styles

The SDK exposes two levels of abstraction:

High-level: TaurusClient

A single class that owns an Algod client, an Indexer client, a 10-second pool-state cache, and convenience wrappers for every operation. Recommended for most apps.

import { TaurusClient } from '@taurusswap/sdk';

const client = new TaurusClient(); // defaults to testnet AlgoNode

const quote = await client.quote({ fromIndex: 0, toIndex: 1, amountIn: 1_000_000n });
const txns  = await client.buildSwapTxns({ sender, fromIndex: 0, toIndex: 1, amountIn: 1_000_000n });
// → sign txns with your wallet, then algod.sendRawTransaction(signed).do()

Low-level: individual functions

Every operation is also exported as a standalone function. Use these when you need fine-grained control or want to bring your own Algod client.

import { readPoolState, getSwapQuote, buildSwapTxns } from '@taurusswap/sdk';
import algosdk from 'algosdk';

const algod = new algosdk.Algodv2('', 'https://testnet-api.algonode.cloud');
const pool  = await readPoolState(algod, 758284478);
const quote = getSwapQuote(pool, 0, 1, 1_000_000n); // synchronous
const txns  = await buildSwapTxns(algod, 758284478, sender, pool, 0, 1, 1_000_000n, 50);

Three-Layer Architecture

┌──────────────────────────────────────────┐
│  TaurusClient (src/client.ts)            │  ← High-level API + cache
│  .quote()  .buildSwapTxns()              │
│  .buildAddLiquidityTxns()                │
│  .buildZapTxns()  .estimateAPR()         │
├──────────────────────────────────────────┤
│  pool/ & algorand/  (mid-level)          │  ← State reading + tx builders
│  readPoolState()   getSwapQuote()        │
│  buildSwapGroup()  buildAddTickGroup()   │
│  tickParamsFromDepegPrice()              │
├──────────────────────────────────────────┤
│  math/  (pure BigInt functions)          │  ← Invariant math, no I/O
│  solveSwapNewton()  executeTradeWithCrossings()
│  consolidateTicks()  capitalEfficiency() │
└──────────────────────────────────────────┘

Unit System

There are three unit spaces. Getting this wrong is the most common source of bugs.

NameScaleUsed for
raw microunits×1ASA transfer amounts, all public API inputs/outputs (amountIn, amountOut, depositPerTokenRaw)
AMOUNT_SCALE units÷1 000Internal math, r and k tick parameters, reserve aggregates (sumX, rInt, etc.)
PRECISION units×10⁹feeGrowth accumulators, sqrtN, invSqrtN, price ratios

The rule of thumb: 1 USDC = 1_000_000n raw microunits. All SDK public methods accept and return raw microunits.

Error Classes

All errors extend TaurusError and carry a code string:

import {
  SwapTooSmallError,        // amountIn too small after fee + scaling
  InsufficientLiquidityError, // trade too large for available liquidity
  TickNotFoundError,         // tickId not present in pool
  InvalidTickParamsError,    // deposit would be zero or negative
  InvalidSlippageError,      // slippageBps out of 0–10000 range
  ZapAmountTooSmallError,    // totalAmountRaw too small to split
} from '@taurusswap/sdk';

try {
  const quote = await client.quote({ fromIndex: 0, toIndex: 1, amountIn: 100n });
} catch (err) {
  if (err instanceof SwapTooSmallError)         console.error(err.code); // "SWAP_TOO_SMALL"
  if (err instanceof InsufficientLiquidityError) console.error(err.code); // "INSUFFICIENT_LIQUIDITY"
}

Minimal End-to-End Example

import { TaurusClient } from '@taurusswap/sdk';
import algosdk from 'algosdk';

const client = new TaurusClient(); // testnet by default
const sender = 'YOUR_ALGORAND_ADDRESS';

// 1. Quote: sell 10 USDC (token 0) for USDT (token 1)
const quote = await client.quote({
  fromIndex: 0,
  toIndex: 1,
  amountIn: 10_000_000n, // 10 USDC in microunits
});

console.log('You receive:', Number(quote.amountOut) / 1e6, 'USDT');
console.log('Price impact:', (quote.priceImpact * 100).toFixed(4), '%');
console.log('Ticks crossed:', quote.ticksCrossed);

// 2. Build unsigned transaction group
const txns = await client.buildSwapTxns({
  sender,
  fromIndex: 0,
  toIndex: 1,
  amountIn: 10_000_000n,
  slippageBps: 50, // 0.5% default
});

// 3. Sign with your wallet, then submit
// const signedTxns = await peraWallet.signTransaction([txns.map(t => ({ txn: t }))]);
// const { txid } = await client.algod.sendRawTransaction(signedTxns).do();
// await algosdk.waitForConfirmation(client.algod, txid, 4);

Next Steps