Package Exports
- @todayapp/avantis-sdk
Readme
Avantis TypeScript SDK (Unofficial)
⚠️ BETA SOFTWARE - This is an unofficial, community-developed SDK for Avantis. Use at your own risk.
An unofficial TypeScript SDK for interacting with Avantis - the decentralized perpetual futures DEX on Base network. Trade crypto, forex, commodities, and indices with up to 100x leverage.
Note: This SDK is currently in beta and is not officially endorsed by Avantis. While it has been thoroughly tested, users should exercise caution when using it in production environments.
✨ Features
- 🚀 Full Trading Suite: Market orders, limit orders, stop orders, and position management
- 🔮 Pyth Oracle Integration: Automatic price feed fetching from Pyth Network for all 89+ trading pairs
- 💰 Platform Fee System: Built-in fee management with referral support and transaction bundling
- 📊 Real-time Data: WebSocket-based live price feeds and market data
- 💱 89+ Trading Pairs: Crypto, forex, commodities, stocks, and metals with Pyth price feeds
- 🌐 Socket API Integration: Fast, cached access to all market metadata, open interest, and asset filtering
- 🔐 Type-Safe: Full TypeScript with runtime validation using Zod
- 📱 Cross-Platform: Works with Node.js, browsers, and React Native
- ⚡ Gas Optimized: Multicall3 transaction bundling for 30-40% gas savings
- 🛡️ Production Ready: Comprehensive error handling and recovery
- 🔗 Viem-Powered: Built with viem for modern blockchain interactions and account abstraction support
📦 Installation
npm install @todayapp/avantis-sdk
# or
yarn add @todayapp/avantis-sdk
# or
pnpm add @todayapp/avantis-sdk🚀 Quick Start
Basic Trading
import { AvantisSDK, PositionSide, OrderType } from '@todayapp/avantis-sdk';
// Initialize SDK
const sdk = new AvantisSDK('base'); // 'base' for mainnet, 'base-sepolia' for testnet
// Set up signer
await sdk.setSigner({
type: 'privateKey',
privateKey: process.env.PRIVATE_KEY
});
// Open a position
const result = await sdk.trader.openPosition({
pair: 'ETH/USD',
side: PositionSide.LONG,
size: 1000, // $1000 position size
leverage: 10, // 10x leverage
orderType: OrderType.MARKET,
stopLoss: 2800, // Optional SL at $2800
takeProfit: 3500, // Optional TP at $3500
slippage: 0.5 // 0.5% slippage tolerance
});
console.log('Position opened:', result.transactionHash);With Platform Fees
// Configure platform fees (for platforms/integrators)
sdk.trader.setPlatformFeeConfig({
platformWallet: '0xYourPlatformWallet',
baseFeePercent: 0.001, // 0.1% platform fee
referralSplitPercent: 30, // 30% goes to referrers
enabled: true
});
// Open position with fees
const result = await sdk.trader.openPositionWithFees({
pair: 'BTC/USD',
side: PositionSide.SHORT,
size: 5000,
leverage: 25,
platformFee: {
enabled: true,
discountPercent: 20, // 20% fee discount for this user
referralAddress: '0xReferrerWallet' // Optional referrer
}
});Real-time Price Feeds
// Initialize feed client
await sdk.feed.connect();
// Subscribe to price updates
const unsubscribe = sdk.feed.subscribeToPrice('BTC/USD', (priceData) => {
console.log(`BTC Price: $${priceData.price.toFixed(2)}`);
console.log(`24h Change: ${priceData.change24h}%`);
});
// Get latest price once
const price = await sdk.feed.getLatestPrice('ETH/USD');
console.log(`ETH: $${price.price}`);
// Cleanup
unsubscribe();
await sdk.feed.disconnect();Socket API - Market Discovery
The SDK uses the Avantis Socket API to fetch comprehensive market data for all 89+ trading pairs:
// Get all markets from Socket API (fast, cached, complete)
const markets = await sdk.getAllMarketsFromAPI();
console.log(`Found ${markets.length} markets`); // 89+
// Each market includes:
markets.forEach(market => {
console.log({
pairIndex: market.pairIndex,
name: market.name, // e.g., "BTC/USD"
maxLeverage: market.maxLeverage, // e.g., 75
spreadPercent: market.spreadPercent, // Trading spread
pythFeedId: market.pythFeedId, // For price fetching
assetType: market.assetType // Crypto, FX, Equity, etc.
});
});
// Filter by asset type
const cryptos = await sdk.getMarketsByType('Crypto'); // 57 pairs
const forex = await sdk.getMarketsByType('FX'); // 17 pairs
const stocks = await sdk.getMarketsByType('Equity'); // 10 pairs
// Get specific market
const eth = await sdk.getMarketByIndex(0); // ETH/USD
console.log(`${eth.name}: ${eth.maxLeverage}x leverage`);
// Get total open interest
const oi = await sdk.getTotalOpenInterest();
console.log(`Long OI: $${oi.long}, Short OI: $${oi.short}`);Why Socket API?
- ✅ Complete: All 89+ pairs vs only 4 from on-chain
- ✅ Fast: ~50-100ms with 5-minute cache
- ✅ Rich Metadata: Names, asset types, leverage, spreads
- ✅ No RPC Costs: Doesn't consume blockchain RPC quota
See docs/SOCKET_API.md for full documentation.
Pyth Network Oracle Integration
The SDK automatically fetches real-time price data from Pyth Network oracles, which is required by Avantis smart contracts:
// Get prices for markets using Pyth feed IDs from Socket API
const markets = await sdk.getAllMarketsFromAPI();
const feedIds = markets.slice(0, 10).map(m => m.pythFeedId);
const prices = await sdk.pyth.getLatestPricesByFeedIds(feedIds);
markets.slice(0, 10).forEach(market => {
const priceData = prices.get(market.pythFeedId);
if (priceData) {
const expo = priceData.expo;
const price = expo < 0
? parseFloat(priceData.price) / Math.pow(10, Math.abs(expo))
: parseFloat(priceData.price) * Math.pow(10, expo);
console.log(`${market.name}: $${price}`);
}
});
// Get single market price
const btc = await sdk.getMarketByIndex(1); // BTC/USD
const btcPrice = await sdk.pyth.getLatestPriceByFeedId(btc.pythFeedId);
// Automatic price fetching in trades (default behavior)
const result = await sdk.trader.openPosition({
pair: 'BTC/USD',
side: PositionSide.LONG,
size: 1000,
leverage: 10
// Pyth prices automatically fetched and included!
});
// Manual control over price fetching
const result = await sdk.trader.openPosition({
pair: 'ETH/USD',
side: PositionSide.SHORT,
size: 500,
leverage: 5,
autofetchPrices: false, // Disable auto-fetch
priceUpdateData: customPriceData // Provide your own price data
});Why Pyth? Avantis uses Pyth Network's decentralized oracle for accurate, low-latency price feeds. The SDK handles all the complexity of fetching and formatting price data automatically.
📱 React Native Setup
For React Native/Expo apps, install the required polyfill:
npm install react-native-get-random-valuesAdd to your app's entry point:
// index.js or App.tsx
import 'react-native-get-random-values';
// Your app code
import App from './App';Note: The SDK now uses viem which has better React Native compatibility than ethers.js
📖 Core Concepts
Trading Pairs & Market Data
The SDK supports 89+ trading pairs across different asset classes via the Socket API:
// Get all 89+ markets with full metadata (recommended)
const markets = await sdk.getAllMarketsFromAPI();
console.log(`Total markets: ${markets.length}`);
markets.forEach(market => {
console.log(`${market.name}: ${market.maxLeverage}x leverage, ${market.spreadPercent}% spread`);
});
// Filter by asset type
const cryptoMarkets = await sdk.getMarketsByType('Crypto'); // 57 crypto pairs
const forexMarkets = await sdk.getMarketsByType('FX'); // 17 forex pairs
const stockMarkets = await sdk.getMarketsByType('Equity'); // 10 stock pairs
const metalMarkets = await sdk.getMarketsByType('Metal'); // 2 metal pairs
const commodities = await sdk.getMarketsByType('Commodities'); // 1 commodity
// Get available asset types
const assetTypes = await sdk.getAssetTypes();
// Returns: ['Crypto', 'FX', 'Equity', 'Metal', 'Commodities']
// Get specific market by index
const btc = await sdk.getMarketByIndex(1); // BTC/USD
console.log(`${btc.name}: Max leverage ${btc.maxLeverage}x`);
// Get markets with current Pyth prices
const feedIds = markets.slice(0, 10).map(m => m.pythFeedId);
const prices = await sdk.pyth.getLatestPricesByFeedIds(feedIds);Market Breakdown:
- 🪙 Crypto: 57 pairs (ETH, BTC, SOL, BNB, ARB, DOGE, AVAX, OP, POL, TIA, SEI, SHIB, PEPE, BONK, WIF, and more)
- 💱 Forex: 17 pairs (EUR/USD, GBP/USD, USD/JPY, and major currency pairs)
- 📈 Stocks: 10 pairs (SPY, QQQ, NVDA, AAPL, TSLA, GOOG, AMZN, META, MSFT, COIN)
- 🥇 Metals: 2 pairs (XAU/USD Gold, XAG/USD Silver)
- 🛢️ Commodities: 1 pair (USOILSPOT/USD)
Getting Pair Indices Dynamically
Important: Pair indices are fetched dynamically from the Socket API. Never hardcode pair indices as they may change.
// Get pair index dynamically (recommended)
const ethIndex = await sdk.getPairIndexByName('ETH/USD'); // Returns: 0
const btcIndex = await sdk.getPairIndexByName('BTC/USD'); // Returns: 1
// Get pair name from index
const pairName = await sdk.getPairNameByIndex(1); // Returns: "BTC/USD"
// When trading, use pair names (indices are resolved automatically)
await sdk.trader.openPosition({
pair: 'ETH/USD', // ✅ Use names, not indices
side: PositionSide.LONG,
size: 1000,
leverage: 10
});Position Management
// Get all open positions
const positions = await sdk.trader.getPositions();
// Update stop loss and take profit
await sdk.trader.updatePosition({
positionId: '0-123', // Format: "pairIndex-positionIndex"
stopLoss: 2900,
takeProfit: 3200
});
// Close position (partial or full)
await sdk.trader.closePosition({
positionId: '0-123',
size: 500 // Optional: close only $500 (partial close)
});Account Information
const account = await sdk.trader.getAccountInfo();
console.log('Address:', account.address);
console.log('USDC Balance:', account.usdcBalance.toFixed(2));
console.log('Free Collateral:', account.freeCollateral.toFixed(2));
console.log('Active Positions:', account.positions.length);
console.log('Unrealized PnL:', account.unrealizedPnl.toFixed(2));
console.log('Margin Level:', account.marginLevel, '%');Limit Orders
// Place a limit order
const limitOrder = await sdk.trader.openPosition({
pair: 'ETH/USD',
side: PositionSide.LONG,
size: 2000,
leverage: 15,
orderType: OrderType.LIMIT,
openPrice: 2950, // Will execute when ETH reaches $2950
stopLoss: 2800,
takeProfit: 3200
});
// Update limit order
await sdk.trader.updateLimitOrder({
pairIndex: 1, // BTC/USD (get dynamically via sdk.getPairIndexByName('BTC/USD'))
orderIndex: 0,
price: 2940, // New limit price
takeProfit: 3250,
stopLoss: 2750
});
// Cancel limit order
await sdk.trader.cancelLimitOrder({
pairIndex: 1, // BTC/USD (get dynamically via sdk.getPairIndexByName('BTC/USD'))
orderIndex: 0
});💰 Platform Fee System
The SDK includes a comprehensive fee management system for platforms and integrators:
Features
- Transaction Bundling: Uses Multicall3 for gas-efficient atomic transactions
- Flexible Discounts: Per-user percentage discounts (0-100%)
- Referral Support: Automatic fee splitting with referrers
- Gas Optimized: ~30-40% gas savings through bundling
Implementation
// Configure global platform fees
sdk.trader.setPlatformFeeConfig({
platformWallet: '0xYourPlatformWallet',
baseFeePercent: 0.002, // 0.2% fee
referralSplitPercent: 40, // 40% to referrers
enabled: true
});
// Calculate fees before trading
const feeBreakdown = sdk.trader.calculateFeeBreakdown(
1000, // Trade size
{
enabled: true,
discountPercent: 25, // VIP discount
referralAddress: '0xReferrer'
}
);
console.log('Platform receives:', feeBreakdown.platformReceives);
console.log('Referrer receives:', feeBreakdown.referralFee);
console.log('Total fee:', feeBreakdown.totalFee);
// Execute trade with fees (bundled in single transaction)
await sdk.trader.openPositionWithFees({
// ... position params
platformFee: {
enabled: true,
discountPercent: 25,
referralAddress: '0xReferrer'
}
});🛡️ Error Handling
The SDK provides detailed error types for robust error handling:
import {
TradingError,
ValidationError,
NetworkError,
ErrorCode
} from '@todayapp/avantis-sdk';
try {
await sdk.trader.openPosition(params);
} catch (error) {
if (error instanceof TradingError) {
switch (error.code) {
case ErrorCode.INSUFFICIENT_COLLATERAL:
console.error('Not enough USDC balance');
break;
case ErrorCode.POSITION_SIZE_TOO_SMALL:
console.error('Position size below minimum');
break;
case ErrorCode.MAX_LEVERAGE_EXCEEDED:
console.error('Leverage too high for this pair');
break;
default:
console.error('Trading error:', error.message);
}
} else if (error instanceof ValidationError) {
console.error('Invalid input:', error.field, error.message);
} else if (error instanceof NetworkError) {
console.error('Network issue:', error.message);
}
}📊 Advanced Examples
Portfolio Monitoring
// Monitor all positions with real-time PnL
const positions = await sdk.trader.getPositions();
for (const position of positions) {
sdk.feed.subscribeToPrice(position.pair, (priceData) => {
const currentPrice = priceData.price;
const entryPrice = position.entryPrice;
const pnlPercent = position.side === PositionSide.LONG
? ((currentPrice - entryPrice) / entryPrice) * 100 * position.leverage
: ((entryPrice - currentPrice) / entryPrice) * 100 * position.leverage;
console.log(`${position.pair}: ${pnlPercent.toFixed(2)}% PnL`);
// Auto-close if profit target reached
if (pnlPercent >= 50) {
await sdk.trader.closePosition({ positionId: position.id });
console.log('Profit target reached, position closed!');
}
});
}Risk Management System
class RiskManager {
constructor(private sdk: AvantisSDK, private maxDrawdown: number = 10) {}
async monitorRisk() {
const account = await this.sdk.trader.getAccountInfo();
const initialBalance = account.usdcBalance;
setInterval(async () => {
const current = await this.sdk.trader.getAccountInfo();
const drawdown = ((initialBalance - current.usdcBalance) / initialBalance) * 100;
if (drawdown >= this.maxDrawdown) {
console.warn(`Max drawdown reached: ${drawdown.toFixed(2)}%`);
// Close all positions
for (const position of current.positions) {
await this.sdk.trader.closePosition({ positionId: position.id });
}
console.log('All positions closed due to max drawdown');
}
// Check margin level
if (current.marginLevel < 150) {
console.warn(`Low margin level: ${current.marginLevel}%`);
}
}, 5000); // Check every 5 seconds
}
}🔧 Configuration
Network Configuration
// Mainnet (Base)
const sdk = new AvantisSDK('base');
// Testnet (Base Sepolia)
const sdk = new AvantisSDK('base-sepolia');
// Custom RPC
const sdk = new AvantisSDK('base', 'https://your-rpc-url.com');
// Get network info
const network = sdk.trader.getNetwork();
console.log(`Network: ${network.name} (Chain ID: ${network.chainId})`);Signer Options
// Private key (Node.js)
await sdk.setSigner({
type: 'privateKey',
privateKey: '0x...'
});
// Mnemonic phrase
await sdk.setSigner({
type: 'mnemonic',
mnemonic: 'your twelve word phrase...',
path: "m/44'/60'/0'/0/0" // Optional HD path
});
// Account Abstraction (e.g., with Kernel/ZeroDev)
// The SDK is built with viem, making it compatible with smart account libraries
import { createKernelAccount } from '@zerodev/sdk';
const kernelAccount = await createKernelAccount(...);
await sdk.setSigner({
type: 'privateKey',
privateKey: kernelAccount.privateKey
});Account Abstraction Support: The SDK uses viem internally, making it fully compatible with viem-based account abstraction libraries like Kernel, Biconomy, and Safe.
📝 API Reference
Main Classes
AvantisSDK: Main SDK wrapper classgetPairIndexByName(name)- Get dynamic pair index from Socket APIgetPairNameByIndex(index)- Get pair name from indexgetAllPairNames()- Get all available pair namesgetAllMarketsFromAPI()- Get all 89+ markets with metadatagetMarketsByType(type)- Filter markets by asset typegetMarketByIndex(index)- Get specific market data
TraderClient: Trading operations and position managementgetPairIndexFromAPI(name)- Get accurate pair index (use instead of deprecatedgetPairIndex())getPairNameFromAPI(index)- Get pair name (use instead of deprecatedgetPairName())getAllPairsFromAPI()- Get all pairs (use instead of deprecatedgetAllPairs())- All trading methods now use Socket API for accurate pair indices
FeedClient: Real-time price feeds and market dataPythClient: Pyth Network oracle price data fetchingSocketAPIClient: Socket API for market metadata (89+ pairs)StorageClient: On-chain storage interactionsPriceClient: Price aggregation and oraclesFeeManager: Platform fee calculationsMulticallBundler: Transaction bundling
Key Types
MarketData: Complete market information (from Socket API)pairIndex,name,from,topythFeedId- Pyth price feed IDmaxLeverage,minLeverage- Leverage limitsspreadPercent- Trading spreadminPositionSizeUSDC,maxPositionSizeUSDC- Position size limitsmaxOpenInterestLong,maxOpenInterestShort- OI limitscurrentPrice?- Optional current Pyth price data
Position: Open position dataOpenPositionParams: Parameters for opening positions (withautofetchPricesandpriceUpdateData)ClosePositionParams: Parameters for closing positions (with Pyth support)UpdatePositionParams: Parameters for updating positions (with Pyth support)UpdateMarginParams: Parameters for margin updates (with Pyth support)PlatformFeeConfig: Platform fee configurationMarketStats: 24-hour market statisticsAccountInfo: Complete account informationPythPriceUpdate: Pyth price feed data structure
🔧 Technical Details
Built with Viem
This SDK uses viem as its blockchain interaction library. Viem provides:
- Smaller Bundle Size: ~80% smaller than ethers.js
- Better TypeScript: Superior type inference and safety
- Modern Architecture: Built for modern blockchain development
- Account Abstraction: Native compatibility with smart account libraries
Why Viem?
The SDK was migrated from ethers.js to viem to enable:
- Account Abstraction Support: Works seamlessly with Kernel, ZeroDev, Biconomy, Safe, and other viem-based AA libraries
- Better Developer Experience: Enhanced TypeScript support and modern APIs
- Performance: Smaller bundle size and optimized for tree-shaking
- Future-Proof: Built for the next generation of blockchain applications
All public APIs remain unchanged - the migration is internal only.
Dependencies
- viem ^2.21.60 - Blockchain interactions
- decimal.js ^10.6.0 - Precise decimal math
- axios ^1.12.2 - HTTP requests
- ws ^8.18.3 - WebSocket support
- zod ^4.1.11 - Runtime validation
🧪 Development
Building from Source
# Clone repository
git clone https://github.com/Today-Finance/avantis-sdk
cd avantis-sdk
# Install dependencies
npm install
# Build SDK
npm run build
# Run tests
npm test
# Type checking
npm run typecheck
# Linting
npm run lintTesting
# Run all tests
npm test
# Unit tests only
npm run test:unit
# Integration tests
npm run test:integration
# Test coverage
npm run test:coverage🤝 Contributing
We welcome contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
📚 Resources
- Documentation: docs.avantisfi.com
- Discord: discord.gg/avantis
- Twitter: @AvantisFinance
- GitHub: github.com/avantisfi
📄 License
MIT License - see LICENSE file for details.
⚠️ Important Disclaimers
Beta Software Notice
This SDK is currently in BETA and is an UNOFFICIAL implementation. It has not been audited or officially endorsed by Avantis. While extensive testing has been performed, users should:
- Test thoroughly in testnet before mainnet use
- Start with small amounts when using in production
- Monitor all transactions carefully
- Report any issues to the GitHub repository
Trading Risk Disclaimer
Trading perpetual futures involves significant risk of loss. This software is provided "as is" without warranty of any kind. Always do your own research, trade responsibly, and never invest more than you can afford to lose. Past performance is not indicative of future results.
No Warranty
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
This is an unofficial, community-developed SDK. Not affiliated with or endorsed by Avantis.