Overview
The @atomic/sdk package wraps every public contract function with TypeScript types, transaction simulation, and standard error handling. If you are building a frontend, a bot, or a backend integration, the SDK is the recommended path.
SDK for application code (what you probably want). REST API for read-heavy server-side queries. Direct contract calls if you need full control. The SDK uses the API and contracts under the hood.
Install
pnpm add @atomic/sdk # or npm install @atomic/sdk yarn add @atomic/sdk
Peer dependencies: viem (or ethers v6 - both supported) and a signer.
Initialize
import { Atomic } from '@atomic/sdk';
import { createWalletClient, http } from 'viem';
import { arbitrum } from 'viem/chains';
const wallet = createWalletClient({
chain: arbitrum,
transport: http(),
account: '0x...',
});
const atomic = new Atomic({
chain: 'arbitrum',
signer: wallet,
});The client auto-detects the latest deployed contract addresses for the chosen chain. Override via the addresses option if you need to pin a specific deployment.
Open a position
const position = await atomic.openPosition({
market: 'ETH-USDC.e',
side: 'long', // 'long' | 'short'
collateral: '1000', // USDC.e, in human units (string to avoid float issues)
leverage: 10,
maxSlippage: 30, // basis points; default 30
});
console.log(position.id); // bigint, on-chain position id
console.log(position.entryPrice); // string, executed entry
console.log(position.liqPrice); // string, computed liquidation priceThe call simulates against current state, signs once, broadcasts, and resolves when the transaction confirms.
Manage a position
// Fetch live state
const live = await atomic.getPosition(position.id);
// Set or update Take Profit and Stop Loss
await atomic.updateTriggers(position.id, {
takeProfit: '4200',
stopLoss: '3050',
});
// Close at market
const closed = await atomic.closePosition(position.id);
console.log(closed.realizedPnl); // string, in USDC.eupdateTriggers is gas-only; setting/editing TP/SL incurs no protocol fee.
Query state
// All open positions for the connected wallet
const open = await atomic.getOpenPositions();
// All positions ever (open + closed) - paginated
const history = await atomic.getPositionHistory({ limit: 100 });
// Live market quote
const quote = await atomic.getQuote({
market: 'ETH-USDC.e',
side: 'long',
size: '10000',
});
// Lending pool state
const pool = await atomic.getLendingPool();
console.log(pool.utilization, pool.apy);Read methods are cached for ~1 second to avoid hammering the RPC. Pass { fresh: true } to bypass.
Lending operations
// Deposit USDC.e into the lending pool
await atomic.lendDeposit('5000');
// Withdraw (full or partial)
await atomic.lendWithdraw('1000');
// Account state
const balance = await atomic.getLenderBalance();
console.log(balance.principal, balance.accruedYield);Withdrawals queue when pool utilization is high - see Lending → Withdraw. The SDK exposes the queue position via getLenderBalance().
Error handling
The SDK throws typed errors for every contract revert reason:
import { AtomicError, InsufficientMarginError, SlippageExceededError } from '@atomic/sdk';
try {
await atomic.openPosition({ ... });
} catch (e) {
if (e instanceof SlippageExceededError) {
// retry with wider slippage or smaller size
} else if (e instanceof InsufficientMarginError) {
// user does not have enough USDC.e
} else if (e instanceof AtomicError) {
// some other contract error; e.message is human-readable
} else {
throw e; // network/RPC errors bubble up
}
}Subscribing to events
const unsubscribe = atomic.onPositionOpen((p) => {
console.log('new position', p.id, p.market, p.side);
});
// Stop listening when done
unsubscribe();Available event hooks: onPositionOpen, onPositionClose, onLiquidation, onLenderDeposit, onLenderWithdraw. All wrap the underlying contract event filter.
Versioning
The SDK follows semver. Major versions track contract version: @atomic/sdk@2.x for V2, @atomic/sdk@3.x for V3 (current). Breaking changes are documented in the changelog.
Pin to a major version (^3.0.0) in production. Minor releases are non-breaking; majors are not, and tracking V2 → V3 was a significant migration.