babel_exchange 1.3.0
babel_exchange: ^1.3.0 copied to clipboard
A unified multi-exchange API client for Binance, MEXC, and Kraken. Supports REST, WebSocket, and provides a common interface across all exchanges.
Babel Exchange #
A unified multi-exchange API client for cryptocurrency trading in Dart.
Features #
- Unified Interface: Same API across all supported exchanges
- Type-Safe: Full Dart type safety with comprehensive models
- WebSocket Support: Real-time market data streams
- Flexible: Use public endpoints without authentication, or full trading with API keys
- Well Tested: Comprehensive test suite with 87+ unit tests
- Debug Mode: Built-in debug logging for troubleshooting
Supported Exchanges #
| Exchange | Status | Notes |
|---|---|---|
| Binance | ✅ Full | Largest exchange by volume |
| MEXC | ✅ Full | Spot trading with B2B fees |
| Kraken | ✅ Full | MiCA compliant, strong security |
Installation #
dependencies:
babel_exchange: ^1.3.0
Quick Start #
import 'package:babel_exchange/babel_exchange.dart';
void main() async {
// Create exchange instance - works identically for all exchanges
final exchange = BabelExchange.create(
Exchange.binance, // or Exchange.mexc, Exchange.kraken
apiKey: 'your-api-key',
secretKey: 'your-secret-key',
);
// Get market data (no auth required)
final ticker = await exchange.getTicker('BTCUSDT');
print('BTC Price: \$${ticker.lastPrice}');
// Get order book
final orderBook = await exchange.getOrderBook('BTCUSDT');
print('Spread: ${orderBook.spreadBps} bps');
// Place orders (requires auth)
final order = await exchange.placeMarketOrder(
symbol: 'BTCUSDT',
side: OrderSide.buy,
quantity: 0.001,
);
print('Order ID: ${order.orderId}');
// Subscribe to real-time data
exchange.subscribeToTrades('BTCUSDT').listen((trade) {
final side = trade.isBuy ? 'BUY' : 'SELL';
print('[$side] ${trade.quantity} @ \$${trade.price}');
});
// Clean up
exchange.dispose();
}
Multi-Exchange Usage #
// Same code works across all exchanges
Future<void> printPrices(List<Exchange> exchanges) async {
for (final ex in exchanges) {
final exchange = BabelExchange.create(ex);
try {
final price = await exchange.getPrice('BTCUSDT');
print('${exchange.name}: \$${price.toStringAsFixed(2)}');
} finally {
exchange.dispose();
}
}
}
// Use it
await printPrices([Exchange.binance, Exchange.mexc, Exchange.kraken]);
API Reference #
Factory #
// Create by enum
final exchange = BabelExchange.create(Exchange.binance, apiKey: '...', secretKey: '...');
// Create by name
final exchange = BabelExchange.fromName('binance', apiKey: '...', secretKey: '...');
// Get fee structure
final fees = BabelExchange.getDefaultFees(Exchange.mexc);
// List supported exchanges
final supported = BabelExchange.supportedExchanges; // [binance, mexc, kraken]
Market Data (No Auth Required) #
// Connectivity
await exchange.ping();
await exchange.getServerTime();
// Exchange info
final info = await exchange.getExchangeInfo();
print('Total symbols: ${info.symbols.length}');
// Ticker data
final ticker = await exchange.getTicker('BTCUSDT');
print('24h change: ${ticker.priceChangePercent}%');
final allTickers = await exchange.getAllTickers();
// Prices
final price = await exchange.getPrice('BTCUSDT');
final allPrices = await exchange.getAllPrices();
// Order book
final book = await exchange.getOrderBook('BTCUSDT', limit: 100);
print('Best bid: ${book.bestBid}, Best ask: ${book.bestAsk}');
print('Spread: ${book.spreadBps} bps');
// Candlesticks/Klines
final klines = await exchange.getKlines(
symbol: 'BTCUSDT',
interval: KlineInterval.h1,
limit: 100,
);
// Trades
final trades = await exchange.getAggTrades('BTCUSDT', limit: 100);
final recentTrades = await exchange.getRecentTrades('BTCUSDT');
Account & Trading (Auth Required) #
// Account info
final account = await exchange.getAccountInfo();
print('Can trade: ${account.canTrade}');
// Balances
final balances = await exchange.getBalances();
final btcBalance = await exchange.getBalance('BTC');
final nonZero = await exchange.getNonZeroBalances();
// Place orders
final marketOrder = await exchange.placeMarketOrder(
symbol: 'BTCUSDT',
side: OrderSide.buy,
quantity: 0.001,
);
final limitOrder = await exchange.placeLimitOrder(
symbol: 'BTCUSDT',
side: OrderSide.buy,
quantity: 0.001,
price: 50000.0,
timeInForce: TimeInForce.gtc,
);
// Advanced order
final order = await exchange.placeOrder(
symbol: 'BTCUSDT',
side: OrderSide.sell,
type: OrderType.stopLossLimit,
quantity: 0.001,
price: 48000.0,
stopPrice: 49000.0,
);
// Test order (validates without executing)
await exchange.testOrder(
symbol: 'BTCUSDT',
side: OrderSide.buy,
type: OrderType.limit,
quantity: 0.001,
price: 50000.0,
);
// Order management
final orderStatus = await exchange.getOrder(symbol: 'BTCUSDT', orderId: '123');
final openOrders = await exchange.getOpenOrders(symbol: 'BTCUSDT');
final history = await exchange.getOrderHistory(symbol: 'BTCUSDT', limit: 100);
// Cancel orders
await exchange.cancelOrder(symbol: 'BTCUSDT', orderId: '123');
await exchange.cancelAllOrders('BTCUSDT');
// Trade history
final myTrades = await exchange.getMyTrades(symbol: 'BTCUSDT', limit: 100);
WebSocket Streams #
// Trade stream
exchange.subscribeToTrades('BTCUSDT').listen((trade) {
print('Trade: ${trade.price} x ${trade.quantity}');
});
// Order book stream
exchange.subscribeToOrderBook('BTCUSDT', levels: 20).listen((book) {
print('Bid: ${book.bestBid} | Ask: ${book.bestAsk}');
});
// Kline/candlestick stream
exchange.subscribeToKlines('BTCUSDT', KlineInterval.m1).listen((candle) {
print('OHLC: ${candle.open}/${candle.high}/${candle.low}/${candle.close}');
});
// Ticker stream
exchange.subscribeToTicker('BTCUSDT').listen((ticker) {
print('Price: ${ticker.lastPrice}, 24h: ${ticker.priceChangePercent}%');
});
// All tickers stream (where supported)
exchange.subscribeToAllTickers().listen((ticker) {
if (ticker.priceChangePercent.abs() > 5) {
print('${ticker.symbol}: ${ticker.priceChangePercent}%');
}
});
Fee Structures #
| Exchange | Maker | Taker | Notes |
|---|---|---|---|
| MEXC B2B | 0% (-0.01% rebate) | 0.02% | Best rates with MX token |
| Binance VIP0 | 0.075% | 0.075% | 25% discount with BNB |
| Kraken Pro | 0.16% | 0.26% | Volume-based discounts |
final fees = ExchangeFees.mexcB2B;
final cost = fees.calculateFee(1000.0, isMaker: true); // $0 (+ $0.10 rebate)
Models #
All models include toJson() and fromJson() methods for serialization:
| Model | Description |
|---|---|
Candle |
OHLCV candlestick data with calculated properties (range, isBullish) |
OrderBook |
Bid/ask depth with spread and imbalance calculations |
Ticker |
24hr statistics with price change metrics |
AggTrade |
Aggregated trades with value calculation |
Order |
Order information with fill tracking |
Fill |
Individual fill within an order |
Balance |
Asset balance (free + locked) |
AccountInfo |
Account data with permissions |
Trade |
Trade history entry |
ExchangeInfo |
Exchange metadata and symbols |
SymbolInfo |
Trading pair configuration |
Enums #
| Enum | Values |
|---|---|
Exchange |
binance, mexc, kraken |
OrderSide |
buy, sell |
OrderType |
market, limit, stopLoss, stopLossLimit, takeProfit, takeProfitLimit, limitMaker |
OrderStatus |
newOrder, partiallyFilled, filled, canceled, rejected, expired |
TimeInForce |
gtc (Good Till Cancel), ioc (Immediate Or Cancel), fok (Fill Or Kill) |
KlineInterval |
m1, m3, m5, m15, m30, h1, h2, h4, h6, h8, h12, d1, d3, w1, M1 |
AccountType |
spot, margin, futures, funding |
SymbolStatus |
trading, break_, halt, haltBuyOnly, haltSellOnly, auctionMatch, preTrading, postTrading, endOfDay |
Coin |
btc, eth, bnb, sol, xrp, ada, usdt, usdc, and 50+ more |
Type-Safe Trading Pairs #
Use Coin and TradingPair for compile-time safety:
// Type-safe pair construction
final pair = TradingPair(Coin.btc, Coin.usdt);
final ticker = await exchange.getTicker(pair.symbol); // 'BTCUSDT'
// Predefined pairs
await exchange.getTicker(TradingPair.ethUsdt.symbol);
await exchange.getTicker(TradingPair.solBtc.symbol);
// Coin helpers
print(Coin.usdt.isStablecoin); // true
print(Coin.btc.isQuoteAsset); // true
print(Coin.sol.fullName); // 'Solana'
Debug Mode #
Enable debug logging to troubleshoot API issues:
// Enable via factory
final exchange = BabelExchange.create(
Exchange.binance,
debug: true,
debugLevel: DebugLevel.debug,
);
// Or enable globally
BabelDebug.enabled = true;
BabelDebug.level = DebugLevel.verbose;
// Custom log handler
BabelDebug.handler = (level, tag, message) {
myLogger.log(level.name, '[$tag] $message');
};
Output example:
[DEBUG] [HTTP] GET https://api.binance.com/api/v3/ticker/24hr?symbol=BTCUSDT
[DEBUG] [HTTP] GET /api/v3/ticker/24hr -> 200 body={"symbol":"BTCUSDT"...}
[ERROR] [Binance] API error [-1121]: Invalid symbol
Exception Handling #
try {
await exchange.placeMarketOrder(...);
} on InsufficientBalanceException catch (e) {
print('Not enough ${e.asset}: need ${e.required}, have ${e.available}');
} on ExchangeRateLimitException catch (e) {
print('Rate limited, retry after ${e.retryAfterSeconds}s');
} on ExchangeAuthException catch (e) {
print('Authentication failed: ${e.message}');
} on ExchangeParameterException catch (e) {
print('Invalid parameter: ${e.parameter}');
} on OrderNotFoundException catch (e) {
print('Order ${e.orderId} not found');
} on ExchangeApiException catch (e) {
print('API error [${e.code}]: ${e.message} (HTTP ${e.statusCode})');
} on ExchangeNetworkException catch (e) {
print('Network error: ${e.message}');
} on ExchangeWebSocketException catch (e) {
print('WebSocket error: ${e.message}');
}
Examples #
See the example/ directory for complete examples:
market_data_example.dart- Fetching market datatrading_example.dart- Order placement and managementwebsocket_example.dart- Real-time streaming
Testing #
# Run all tests
dart test
# Run specific test file
dart test test/core/models_test.dart
# Run with coverage
dart test --coverage=coverage
Contributing #
Contributions are welcome! Please read the contributing guidelines before submitting PRs.
License #
MIT License - see LICENSE for details.