@ygcc/ygcc
v2.9.0
Published
Lightweight cryptocurrency exchange library — unified REST & WebSocket API for 30+ exchanges
Maintainers
Readme
YGCC — Cryptocurrency Exchange Library
Lightweight, unified REST & WebSocket API for cryptocurrency exchanges. One interface, 33 exchanges.
Overview
YGCC is a JavaScript library for cryptocurrency trading that provides a unified API across multiple exchanges. Write your trading logic once — it works on every supported exchange without modification.
Built from 5+ years of production trading experience across 30+ exchanges.
Features
- Unified API — Same method signatures across all exchanges (
fetchTicker,createOrder,watchOrderBook, etc.) - REST + WebSocket — Full market data, trading, and real-time streaming support
- Weight-Aware Rate Limiting — Token-bucket limiter that syncs with exchange response headers
- Auto-Reconnect WebSocket — Exponential backoff with jitter, automatic resubscription
- Typed Error Hierarchy —
AuthenticationError,InsufficientFunds,RateLimitExceeded, etc. - Minimal Dependencies — Only
wsfor WebSocket support - Multi-Auth Support — HMAC-SHA256/384/512 (hex, Base64), SHA512 content hash (Kraken/Gate.io/Bittrex), JWT/ES256 (Coinbase), UUID nonce (Bitstamp), MD5+HMAC-SHA256 (LBank), Base64-decoded HMAC-SHA256 (Phemex), HMAC-SHA256+memo (BitMart), HMAC-SHA256+URL-signature (Bitrue), HMAC-SHA256+path-signing (Bitforex), HMAC-SHA256+header-signing (Pionex), dual V3 HmacMD5 + V4 HmacSHA256 (Bibox), Base64+HMAC-SHA512 (WhiteBit), HMAC-SHA512 timestamp+method+path (VALR), HMAC-SHA256 uppercase 4-credential (Bitexen), Base64-decoded HMAC-SHA256 (BtcTurk), HMAC-SHA384 path-signing (BTSE), HMAC-SHA512 form-encoded (EXMO), double-layer HMAC-SHA256 (CoinTR), Huobi-style query-string HMAC-SHA256 Base64 (HotCoin), Base64-decoded HMAC-SHA256 ICX headers (iCrypex), Binance-compatible HMAC-SHA256 (JBEX/Trubit), HMAC-SHA512 payload-based (PointPay), HTTP Basic Auth (TradeOgre)
- Testnet Support — Built-in sandbox mode for safe testing
Supported Exchanges
CEX (Centralized)
| # | Exchange | ID | REST | WebSocket | Status |
|---|----------|-----|------|-----------|--------|
| 1 | Binance | binance | ✅ | ✅ | Ready |
| 2 | Bybit | bybit | ✅ | ✅ | Ready |
| 3 | OKX | okx | ✅ | ✅ | Ready |
| 4 | Kraken | kraken | ✅ | ✅ | Ready |
| 5 | Gate.io | gateio | ✅ | ✅ | Ready |
| 6 | Coinbase | coinbase | ✅ | ✅ | Ready |
| 7 | KuCoin | kucoin | ✅ | ✅ | Ready |
| 8 | Bitfinex | bitfinex | ✅ | ✅ | Ready |
| 9 | Bitstamp | bitstamp | ✅ | ✅ | Ready |
| 10 | Bittrex | bittrex | ✅ | ✅ | Ready |
| 11 | Bitrue | bitrue | ✅ | ✅ | Ready |
| 12 | LBANK | lbank | ✅ | ✅ | Ready |
| 13 | BitMart | bitmart | ✅ | ✅ | Ready |
| 14 | Bitforex | bitforex | ✅ | ✅ | Ready |
| 15 | Phemex | phemex | ✅ | ✅ | Ready |
| 16 | Pionex | pionex | ✅ | ✅ | Ready |
| 17 | Bibox | bibox | ✅ | ✅ | Ready |
| 18 | WhiteBit | whitebit | ✅ | ✅ | Ready |
| 19 | VALR | valr | ✅ | ✅ | Ready |
| 20 | Bitexen | bitexen | ✅ | ✅ | Ready |
| 21 | BtcTurk | btcturk | ✅ | ✅ | Ready |
| 22 | BTSE | btse | ✅ | ✅ | Ready |
| 23 | EXMO | exmo | ✅ | ✅ | Ready |
| 24 | CoinTR | cointr | ✅ | ✅ | Ready |
| 25 | HotCoin | hotcoin | ✅ | ✅ | Ready |
| 26 | iCrypex | icrypex | ✅ | ✅ | Ready |
| 27 | JBEX | jbex | ✅ | ✅ | Ready |
| 28 | PointPay | pointpay | ✅ | ✅ | Ready |
| 29 | TruBit | trubit | ✅ | ✅ | Ready |
| 30 | TradeOgre | tradeogre | ✅ | ❌ | Ready |
DEX (Decentralized)
| # | Exchange | ID | REST | WebSocket | Status |
|---|----------|-----|------|-----------|--------|
| 31 | Pollymarket | pollymarket | 🔜 | 🔜 | Planned |
| 32 | Hyperliquid | hyperliquid | 🔜 | 🔜 | Planned |
| 33 | ZKLighter | zklighter | 🔜 | 🔜 | Planned |
✅ = Implemented 🔜 = Coming Soon
Installation
npm install @ygcc/ygccOr clone directly:
git clone https://github.com/yuzgecoguz/ygcc.git
cd ygcc
npm installQuick Start
Fetch Market Data (Public — No API Key Needed)
const { Binance } = require('@ygcc/ygcc');
const exchange = new Binance();
(async () => {
// Load all trading pairs
await exchange.loadMarkets();
console.log(`${exchange.symbols.length} symbols loaded`);
// Get BTC price
const ticker = await exchange.fetchTicker('BTCUSDT');
console.log(`BTC: $${ticker.last} (${ticker.percentage}%)`);
// Order book (top 5 levels)
const book = await exchange.fetchOrderBook('BTCUSDT', 5);
console.log(`Best bid: $${book.bids[0][0]} | Best ask: $${book.asks[0][0]}`);
// OHLCV candlesticks
const candles = await exchange.fetchOHLCV('BTCUSDT', '1h', undefined, 5);
console.log(`Last 5 hourly candles:`, candles);
})();Place Orders (Private — API Key Required)
const { Binance } = require('@ygcc/ygcc');
const exchange = new Binance({
apiKey: process.env.BINANCE_API_KEY,
secret: process.env.BINANCE_SECRET,
enableRateLimit: true,
});
(async () => {
// Check balance
const balance = await exchange.fetchBalance();
console.log('USDT:', balance.USDT);
// Place a limit order
const order = await exchange.createLimitOrder('BTCUSDT', 'BUY', 0.001, 50000);
console.log(`Order ${order.id}: ${order.status}`);
// Cancel it
const canceled = await exchange.cancelOrder(order.id, 'BTCUSDT');
console.log(`Canceled: ${canceled.status}`);
})();WebSocket Streaming (Real-Time)
const { Binance } = require('@ygcc/ygcc');
const exchange = new Binance();
// Real-time ticker updates
exchange.watchTicker('BTCUSDT', (ticker) => {
console.log(`BTC: $${ticker.last} | Bid: $${ticker.bid} | Ask: $${ticker.ask}`);
});
// Real-time trades
exchange.watchTrades('ETHUSDT', (trade) => {
console.log(`${trade.side.toUpperCase()} ${trade.amount} ETH @ $${trade.price}`);
});
// Real-time order book
exchange.watchOrderBook('BTCUSDT', (book) => {
const spread = book.asks[0][0] - book.bids[0][0];
console.log(`Spread: $${spread.toFixed(2)}`);
}, 5);
// Graceful shutdown
process.on('SIGINT', async () => {
await exchange.closeAllWs();
process.exit(0);
});Using Bybit
const { Bybit } = require('@ygcc/ygcc');
const exchange = new Bybit();
(async () => {
await exchange.loadMarkets();
console.log(`${exchange.symbols.length} symbols loaded`);
const ticker = await exchange.fetchTicker('BTCUSDT');
console.log(`BTC: $${ticker.last}`);
const book = await exchange.fetchOrderBook('BTCUSDT', 50);
console.log(`Best bid: $${book.bids[0][0]} | Best ask: $${book.asks[0][0]}`);
})();Bybit Trading (Private)
const { Bybit } = require('@ygcc/ygcc');
const exchange = new Bybit({
apiKey: process.env.BYBIT_API_KEY,
secret: process.env.BYBIT_SECRET,
});
(async () => {
const balance = await exchange.fetchBalance();
console.log('USDT:', balance.USDT);
// Bybit V5 uses POST for orders (not query string like Binance)
const order = await exchange.createLimitOrder('BTCUSDT', 'Buy', 0.001, 50000);
console.log(`Order ${order.id}: ${order.status}`);
// Cancel uses POST too (not DELETE like Binance)
const canceled = await exchange.cancelOrder(order.id, 'BTCUSDT');
console.log(`Canceled: ${canceled.status}`);
})();Using OKX
const { Okx } = require('@ygcc/ygcc');
const exchange = new Okx();
(async () => {
await exchange.loadMarkets();
console.log(`${exchange.symbols.length} symbols loaded`);
// OKX uses dash-separated symbols: BTC-USDT (not BTCUSDT)
const ticker = await exchange.fetchTicker('BTC-USDT');
console.log(`BTC: $${ticker.last}`);
const book = await exchange.fetchOrderBook('BTC-USDT', 5);
console.log(`Best bid: $${book.bids[0][0]} | Best ask: $${book.asks[0][0]}`);
})();OKX Trading (Private)
const { Okx } = require('@ygcc/ygcc');
const exchange = new Okx({
apiKey: process.env.OKX_API_KEY,
secret: process.env.OKX_SECRET,
passphrase: process.env.OKX_PASSPHRASE, // OKX requires passphrase!
});
(async () => {
const balance = await exchange.fetchBalance();
console.log('USDT:', balance.USDT);
// OKX uses lowercase side/type, Base64 signature, POST for all trades
const order = await exchange.createLimitOrder('BTC-USDT', 'buy', 0.001, 50000);
console.log(`Order ${order.id}: ${order.status}`);
const canceled = await exchange.cancelOrder(order.id, 'BTC-USDT');
console.log(`Canceled: ${canceled.status}`);
})();Using Kraken
const { Kraken } = require('@ygcc/ygcc');
const exchange = new Kraken();
(async () => {
await exchange.loadMarkets();
console.log(`${exchange.symbols.length} symbols loaded`);
// Kraken uses slash-separated symbols: BTC/USD
const ticker = await exchange.fetchTicker('BTC/USD');
console.log(`BTC: $${ticker.last}`);
const book = await exchange.fetchOrderBook('BTC/USD', 10);
console.log(`Best bid: $${book.bids[0][0]} | Best ask: $${book.asks[0][0]}`);
})();Kraken Trading (Private)
const { Kraken } = require('@ygcc/ygcc');
const exchange = new Kraken({
apiKey: process.env.KRAKEN_API_KEY,
secret: process.env.KRAKEN_SECRET, // Base64-encoded secret
});
(async () => {
const balance = await exchange.fetchBalance();
console.log('USD:', balance.USD);
// Kraken uses form-urlencoded POST, SHA256+HMAC-SHA512 signing
const order = await exchange.createLimitOrder('BTC/USD', 'buy', 0.001, 50000);
console.log(`Order ${order.id}: ${order.status}`);
const canceled = await exchange.cancelOrder(order.id);
console.log(`Canceled: ${canceled.status}`);
})();Using Gate.io
const { Gateio } = require('@ygcc/ygcc');
const exchange = new Gateio();
(async () => {
await exchange.loadMarkets();
console.log(`${exchange.symbols.length} symbols loaded`);
// Gate.io uses underscore-separated symbols: BTC_USDT
const ticker = await exchange.fetchTicker('BTC/USDT');
console.log(`BTC: $${ticker.last}`);
const book = await exchange.fetchOrderBook('BTC/USDT', 10);
console.log(`Best bid: $${book.bids[0][0]} | Best ask: $${book.asks[0][0]}`);
})();Gate.io Trading (Private)
const { Gateio } = require('@ygcc/ygcc');
const exchange = new Gateio({
apiKey: process.env.GATEIO_API_KEY,
secret: process.env.GATEIO_SECRET,
});
(async () => {
const balance = await exchange.fetchBalance();
console.log('USDT:', balance.USDT);
// Gate.io uses HMAC-SHA512 hex signing with SHA512 body hash
const order = await exchange.createLimitOrder('BTC/USDT', 'buy', 0.001, 50000);
console.log(`Order ${order.id}: ${order.status}`);
const canceled = await exchange.cancelOrder(order.id, 'BTC/USDT');
console.log(`Canceled: ${canceled.status}`);
})();Using KuCoin
const { KuCoin } = require('@ygcc/ygcc');
const exchange = new KuCoin();
(async () => {
await exchange.loadMarkets();
console.log(`${exchange.symbols.length} symbols loaded`);
// KuCoin uses hyphen-separated symbols: BTC-USDT
const ticker = await exchange.fetchTicker('BTC/USDT');
console.log(`BTC: $${ticker.last}`);
const book = await exchange.fetchOrderBook('BTC/USDT', 20);
console.log(`Best bid: $${book.bids[0][0]} | Best ask: $${book.asks[0][0]}`);
})();KuCoin Trading (Private)
const { KuCoin } = require('@ygcc/ygcc');
const exchange = new KuCoin({
apiKey: process.env.KUCOIN_API_KEY,
secret: process.env.KUCOIN_SECRET,
passphrase: process.env.KUCOIN_PASSPHRASE, // KuCoin requires passphrase (encrypted automatically)
});
(async () => {
const balance = await exchange.fetchBalance();
console.log('USDT:', balance.USDT);
// KuCoin auto-generates clientOid (UUID) for every order
const order = await exchange.createLimitOrder('BTC/USDT', 'buy', 0.001, 50000);
console.log(`Order ${order.id}: ${order.status}`);
const canceled = await exchange.cancelOrder(order.id);
console.log(`Canceled: ${canceled.status}`);
})();Using Coinbase
const { Coinbase } = require('@ygcc/ygcc');
const exchange = new Coinbase();
(async () => {
await exchange.loadMarkets();
console.log(`${exchange.symbols.length} symbols loaded`);
// Coinbase uses hyphen-separated symbols: BTC-USD (note: USD, not USDT)
const ticker = await exchange.fetchTicker('BTC/USD');
console.log(`BTC: $${ticker.last}`);
const book = await exchange.fetchOrderBook('BTC/USD', 10);
console.log(`Best bid: $${book.bids[0][0]} | Best ask: $${book.asks[0][0]}`);
})();Coinbase Trading (Private)
const { Coinbase } = require('@ygcc/ygcc');
const exchange = new Coinbase({
apiKey: process.env.COINBASE_API_KEY, // organizations/{org_id}/apiKeys/{key_id}
secret: process.env.COINBASE_SECRET, // EC private key (PEM format)
});
(async () => {
const balance = await exchange.fetchBalance();
console.log('USD:', balance.USD);
// Coinbase uses JWT/ES256 auth, nested order_configuration, auto-generated client_order_id
const order = await exchange.createLimitOrder('BTC/USD', 'BUY', 0.001, 50000);
console.log(`Order ${order.id}: ${order.status}`);
// Cancel uses POST batch_cancel (not DELETE)
const canceled = await exchange.cancelOrder(order.id);
console.log(`Canceled: ${canceled.status}`);
})();Using Bitfinex
const { Bitfinex } = require('@ygcc/ygcc');
const exchange = new Bitfinex();
(async () => {
await exchange.loadMarkets();
console.log(`${exchange.symbols.length} symbols loaded`);
// Bitfinex uses tBTCUSD format internally, accepts BTC/USD
const ticker = await exchange.fetchTicker('BTC/USD');
console.log(`BTC: $${ticker.last}`);
const book = await exchange.fetchOrderBook('BTC/USD', 25);
console.log(`Best bid: $${book.bids[0][0]} | Best ask: $${book.asks[0][0]}`);
})();Bitfinex Trading (Private)
const { Bitfinex } = require('@ygcc/ygcc');
const exchange = new Bitfinex({
apiKey: process.env.BITFINEX_API_KEY,
secret: process.env.BITFINEX_SECRET,
});
(async () => {
const balance = await exchange.fetchBalance();
console.log('USD:', balance.USD);
// Bitfinex uses HMAC-SHA384, EXCHANGE LIMIT/MARKET types, amount sign for side
const order = await exchange.createLimitOrder('BTC/USD', 'buy', 0.001, 50000);
console.log(`Order ${order.id}: ${order.status}`);
const canceled = await exchange.cancelOrder(order.id);
console.log(`Canceled: ${canceled.status}`);
})();Using Bitstamp
const { Bitstamp } = require('@ygcc/ygcc');
const exchange = new Bitstamp();
(async () => {
await exchange.loadMarkets();
console.log(`${exchange.symbols.length} symbols loaded`);
// Bitstamp uses slash-separated symbols: BTC/USD
const ticker = await exchange.fetchTicker('BTC/USD');
console.log(`BTC: $${ticker.last}`);
const book = await exchange.fetchOrderBook('BTC/USD', 10);
console.log(`Best bid: $${book.bids[0][0]} | Best ask: $${book.asks[0][0]}`);
})();Bitstamp Trading (Private)
const { Bitstamp } = require('@ygcc/ygcc');
const exchange = new Bitstamp({
apiKey: process.env.BITSTAMP_API_KEY,
secret: process.env.BITSTAMP_SECRET,
});
(async () => {
const balance = await exchange.fetchBalance();
console.log('USD:', balance.USD);
// Bitstamp uses HMAC-SHA256 + UUID nonce, side is in the URL path (buy/sell)
const order = await exchange.createLimitOrder('BTC/USD', 'buy', 0.001, 50000);
console.log(`Order ${order.id}: ${order.status}`);
const canceled = await exchange.cancelOrder(order.id);
console.log(`Canceled: ${canceled.status}`);
})();Using Bittrex
const { Bittrex } = require('@ygcc/ygcc');
const exchange = new Bittrex();
(async () => {
await exchange.loadMarkets();
console.log(`${exchange.symbols.length} symbols loaded`);
// Bittrex uses hyphen-separated uppercase symbols: BTC-USDT
const ticker = await exchange.fetchTicker('BTC/USDT');
console.log(`BTC: $${ticker.last}`);
const book = await exchange.fetchOrderBook('BTC/USDT', 25);
console.log(`Best bid: $${book.bids[0][0]} | Best ask: $${book.asks[0][0]}`);
})();Bittrex Trading (Private)
const { Bittrex } = require('@ygcc/ygcc');
const exchange = new Bittrex({
apiKey: process.env.BITTREX_API_KEY,
secret: process.env.BITTREX_SECRET,
});
(async () => {
const balance = await exchange.fetchBalance();
console.log('USDT:', balance.USDT);
// Bittrex uses HMAC-SHA512 + SHA512 content hash, JSON POST body, DELETE for cancel
const order = await exchange.createLimitOrder('BTC/USDT', 'buy', 0.001, 50000);
console.log(`Order ${order.id}: ${order.status}`);
// Cancel uses DELETE method (unique among exchanges)
const canceled = await exchange.cancelOrder(order.id);
console.log(`Canceled: ${canceled.status}`);
})();Bittrex WebSocket (SignalR V3)
const { Bittrex } = require('@ygcc/ygcc');
const exchange = new Bittrex();
// Real-time ticker via SignalR V3 hub "c3"
exchange.watchTicker('BTC/USDT', (ticker) => {
console.log(`BTC: $${ticker.last} | Bid: $${ticker.bid} | Ask: $${ticker.ask}`);
});
// Real-time order book deltas
exchange.watchOrderBook('BTC/USDT', (book) => {
console.log(`Bids: ${book.bids.length} | Asks: ${book.asks.length} | Seq: ${book.nonce}`);
}, 25);
// Real-time trades
exchange.watchTrades('ETH/USD', (trade) => {
console.log(`${trade.side.toUpperCase()} ${trade.amount} ETH @ $${trade.price}`);
});
// Graceful shutdown
process.on('SIGINT', async () => {
await exchange.closeAllWs();
process.exit(0);
});Using LBank
const { LBank } = require('@ygcc/ygcc');
const exchange = new LBank();
(async () => {
await exchange.loadMarkets();
console.log(`${Object.keys(exchange.markets).length} symbols loaded`);
// LBank uses underscore-separated lowercase symbols: btc_usdt
const ticker = await exchange.fetchTicker('BTC/USDT');
console.log(`BTC: $${ticker.last}`);
const book = await exchange.fetchOrderBook('BTC/USDT', 50);
console.log(`Best bid: $${book.bids[0][0]} | Best ask: $${book.asks[0][0]}`);
})();LBank Trading (Private)
const { LBank } = require('@ygcc/ygcc');
const exchange = new LBank({
apiKey: process.env.LBANK_API_KEY,
secret: process.env.LBANK_SECRET,
});
(async () => {
const balance = await exchange.fetchBalance();
console.log('USDT:', balance.USDT);
// LBank uses MD5+HMAC-SHA256 two-step signing, POST params in query string
const order = await exchange.createLimitOrder('BTC/USDT', 'buy', 0.001, 50000);
console.log(`Order ${order.id}: ${order.status}`);
const canceled = await exchange.cancelOrder(order.id, 'BTC/USDT');
console.log(`Canceled: ${canceled.id}`);
})();LBank WebSocket (V3 JSON)
const { LBank } = require('@ygcc/ygcc');
const exchange = new LBank();
// Real-time ticker via V3 JSON subscribe
exchange.watchTicker('BTC/USDT', (ticker) => {
console.log(`BTC: $${ticker.last} | Bid: $${ticker.bid} | Ask: $${ticker.ask}`);
});
// Real-time order book depth
exchange.watchOrderBook('BTC/USDT', (book) => {
console.log(`Bids: ${book.bids.length} | Asks: ${book.asks.length}`);
}, 50);
// Real-time trades
exchange.watchTrades('ETH/USDT', (trades) => {
trades.forEach(t => console.log(`${t.side.toUpperCase()} ${t.amount} ETH @ $${t.price}`));
});
// Real-time klines
exchange.watchKlines('BTC/USDT', '1m', (kline) => {
console.log(`Open: ${kline.open} | Close: ${kline.close} | Vol: ${kline.volume}`);
});
// Graceful shutdown
process.on('SIGINT', async () => {
await exchange.closeAllWs();
process.exit(0);
});Using Phemex
const { Phemex } = require('@ygcc/ygcc');
const exchange = new Phemex();
(async () => {
await exchange.loadMarkets();
console.log(`${exchange.symbols.length} symbols loaded`);
// Phemex uses s-prefix format internally: sBTCUSDT
const ticker = await exchange.fetchTicker('BTC/USDT');
console.log(`BTC: $${ticker.last}`);
const book = await exchange.fetchOrderBook('BTC/USDT');
console.log(`Best bid: $${book.bids[0][0]} | Best ask: $${book.asks[0][0]}`);
})();Phemex Trading (Private)
const { Phemex } = require('@ygcc/ygcc');
const exchange = new Phemex({
apiKey: process.env.PHEMEX_API_KEY,
secret: process.env.PHEMEX_SECRET, // Base64-encoded secret key
});
(async () => {
const balance = await exchange.fetchBalance();
console.log('USDT:', balance.USDT);
// Phemex uses HMAC-SHA256 with Base64-decoded secret, Ep/Ev 10^8 scaling
const order = await exchange.createLimitOrder('BTC/USDT', 'buy', 0.001, 50000);
console.log(`Order ${order.id}: ${order.status}`);
// Cancel uses DELETE method with query params
const canceled = await exchange.cancelOrder(order.id, 'BTC/USDT');
console.log(`Canceled: ${canceled.id}`);
})();Phemex WebSocket (JSON-RPC)
const { Phemex } = require('@ygcc/ygcc');
const exchange = new Phemex();
// Real-time ticker via JSON-RPC subscribe
exchange.watchTicker('BTC/USDT', (ticker) => {
console.log(`BTC: $${ticker.last} | Bid: $${ticker.bid} | Ask: $${ticker.ask}`);
});
// Real-time order book (snapshot + incremental)
exchange.watchOrderBook('BTC/USDT', (book) => {
console.log(`Bids: ${book.bids.length} | Asks: ${book.asks.length} | Type: ${book.type}`);
});
// Real-time trades
exchange.watchTrades('ETH/USDT', (trades) => {
trades.forEach(t => console.log(`${t.side.toUpperCase()} ${t.amount} ETH @ $${t.price}`));
});
// Real-time klines
exchange.watchKlines('BTC/USDT', '1h', (klines) => {
klines.forEach(k => console.log(`Open: ${k.open} | Close: ${k.close}`));
});
// Graceful shutdown
process.on('SIGINT', async () => {
await exchange.closeAllWs();
process.exit(0);
});Using BitMart
const { BitMart } = require('@ygcc/ygcc');
const exchange = new BitMart();
(async () => {
await exchange.loadMarkets();
console.log(`${exchange.symbols.length} symbols loaded`);
// BitMart uses underscore-separated symbols: BTC_USDT
const ticker = await exchange.fetchTicker('BTC/USDT');
console.log(`BTC: $${ticker.last}`);
const book = await exchange.fetchOrderBook('BTC/USDT', 20);
console.log(`Best bid: $${book.bids[0][0]} | Best ask: $${book.asks[0][0]}`);
})();BitMart Trading (Private)
const { BitMart } = require('@ygcc/ygcc');
const exchange = new BitMart({
apiKey: process.env.BITMART_API_KEY,
secret: process.env.BITMART_SECRET,
memo: process.env.BITMART_MEMO, // BitMart requires memo (3rd credential)
});
(async () => {
const balance = await exchange.fetchBalance();
console.log('USDT:', balance.USDT);
// BitMart uses HMAC-SHA256 with memo in signature: timestamp#memo#body
const order = await exchange.createLimitOrder('BTC/USDT', 'buy', 0.001, 50000);
console.log(`Order ${order.id}: ${order.status}`);
const canceled = await exchange.cancelOrder(order.id, 'BTC/USDT');
console.log(`Canceled: ${canceled.status}`);
})();BitMart WebSocket (zlib compressed)
const { BitMart } = require('@ygcc/ygcc');
const exchange = new BitMart();
// Real-time ticker via zlib-compressed subscribe
exchange.watchTicker('BTC/USDT', (ticker) => {
console.log(`BTC: $${ticker.last} | Bid: $${ticker.bid} | Ask: $${ticker.ask}`);
});
// Real-time order book (depth5 or depth20)
exchange.watchOrderBook('BTC/USDT', (book) => {
console.log(`Bids: ${book.bids.length} | Asks: ${book.asks.length}`);
}, 20);
// Real-time trades
exchange.watchTrades('ETH/USDT', (trades) => {
trades.forEach(t => console.log(`${t.side.toUpperCase()} ${t.amount} ETH @ $${t.price}`));
});
// Real-time klines
exchange.watchKlines('BTC/USDT', '1h', (klines) => {
klines.forEach(k => console.log(`Open: ${k.open} | Close: ${k.close}`));
});
// Graceful shutdown
process.on('SIGINT', async () => {
await exchange.closeAllWs();
process.exit(0);
});Using Bitrue
const { Bitrue } = require('@ygcc/ygcc');
const exchange = new Bitrue();
(async () => {
await exchange.loadMarkets();
console.log(`${exchange.symbols.length} symbols loaded`);
// Bitrue uses Binance-style symbols: BTCUSDT (no separator)
const ticker = await exchange.fetchTicker('BTC/USDT');
console.log(`BTC: $${ticker.last}`);
const book = await exchange.fetchOrderBook('BTC/USDT', 20);
console.log(`Best bid: $${book.bids[0][0]} | Best ask: $${book.asks[0][0]}`);
})();Bitrue Trading (Private)
const { Bitrue } = require('@ygcc/ygcc');
const exchange = new Bitrue({
apiKey: process.env.BITRUE_API_KEY,
secret: process.env.BITRUE_SECRET,
});
(async () => {
const balance = await exchange.fetchBalance();
console.log('USDT:', balance.USDT);
// Bitrue uses HMAC-SHA256 with signature in URL, JSON POST body, GTT timeInForce
const order = await exchange.createLimitOrder('BTC/USDT', 'BUY', 0.001, 50000);
console.log(`Order ${order.id}: ${order.status}`);
const canceled = await exchange.cancelOrder(order.id, 'BTC/USDT');
console.log(`Canceled: ${canceled.status}`);
})();Bitrue WebSocket (gzip compressed)
const { Bitrue } = require('@ygcc/ygcc');
const exchange = new Bitrue();
// Real-time ticker via gzip-compressed subscribe
exchange.watchTicker('BTC/USDT', (ticker) => {
console.log(`BTC: $${ticker.last} | Bid: $${ticker.bid} | Ask: $${ticker.ask}`);
});
// Real-time order book (depth_step0)
exchange.watchOrderBook('BTC/USDT', (book) => {
console.log(`Bids: ${book.bids.length} | Asks: ${book.asks.length}`);
}, 20);
// Real-time trades
exchange.watchTrades('ETH/USDT', (trade) => {
console.log(`${trade.side.toUpperCase()} ${trade.amount} ETH @ $${trade.price}`);
});
// Real-time klines
exchange.watchKlines('BTC/USDT', '1h', (kline) => {
console.log(`Open: ${kline.open} | Close: ${kline.close} | Vol: ${kline.volume}`);
});
// Graceful shutdown
process.on('SIGINT', async () => {
await exchange.closeAllWs();
process.exit(0);
});Using Bitforex
const { Bitforex } = require('@ygcc/ygcc');
const exchange = new Bitforex();
(async () => {
await exchange.loadMarkets();
console.log(`${exchange.symbols.length} symbols loaded`);
// Bitforex uses unique coin-quote-base format: coin-usdt-btc
const ticker = await exchange.fetchTicker('BTC/USDT');
console.log(`BTC: $${ticker.last}`);
const book = await exchange.fetchOrderBook('BTC/USDT', 10);
console.log(`Best bid: $${book.bids[0][0]} | Best ask: $${book.asks[0][0]}`);
})();Bitforex Trading (Private)
const { Bitforex } = require('@ygcc/ygcc');
const exchange = new Bitforex({
apiKey: process.env.BITFOREX_API_KEY,
secret: process.env.BITFOREX_SECRET,
});
(async () => {
const balance = await exchange.fetchBalance();
console.log('USDT:', balance.USDT);
// Bitforex uses HMAC-SHA256 with path in signing string, limit orders only (no market orders)
const order = await exchange.createLimitOrder('BTC/USDT', 'buy', 0.001, 50000);
console.log(`Order ${order.id}: ${order.status}`);
const canceled = await exchange.cancelOrder(order.id, 'BTC/USDT');
console.log(`Canceled: ${canceled.status}`);
})();Bitforex WebSocket (plain text JSON)
const { Bitforex } = require('@ygcc/ygcc');
const exchange = new Bitforex();
// Real-time ticker via plain text JSON subscribe
exchange.watchTicker('BTC/USDT', (ticker) => {
console.log(`BTC: $${ticker.last} | Bid: $${ticker.bid} | Ask: $${ticker.ask}`);
});
// Real-time order book (depth10)
exchange.watchOrderBook('BTC/USDT', (book) => {
console.log(`Bids: ${book.bids.length} | Asks: ${book.asks.length}`);
}, 10);
// Real-time trades
exchange.watchTrades('ETH/USDT', (trade) => {
console.log(`${trade.side.toUpperCase()} ${trade.amount} ETH @ $${trade.price}`);
});
// Real-time klines
exchange.watchKlines('BTC/USDT', '1m', (kline) => {
console.log(`Open: ${kline.open} | Close: ${kline.close} | Vol: ${kline.volume}`);
});
// Graceful shutdown
process.on('SIGINT', async () => {
await exchange.closeAllWs();
process.exit(0);
});Using Pionex
const { Pionex } = require('@ygcc/ygcc');
const exchange = new Pionex();
(async () => {
// Pionex has NO REST market data — only loadMarkets is available publicly
await exchange.loadMarkets();
console.log(`${exchange.symbols.length} symbols loaded`);
// No fetchTicker, fetchOrderBook, fetchTrades, or fetchOHLCV!
// Use WebSocket for real-time market data instead
})();Pionex Trading (Private)
const { Pionex } = require('@ygcc/ygcc');
const exchange = new Pionex({
apiKey: process.env.PIONEX_API_KEY,
secret: process.env.PIONEX_SECRET,
});
(async () => {
const balance = await exchange.fetchBalance();
console.log('USDT:', balance.USDT);
// Pionex MARKET BUY uses amount (quote currency), SELL uses size (base currency)
const order = await exchange.createLimitOrder('BTC/USDT', 'BUY', 0.001, 50000);
console.log(`Order ${order.id}: ${order.status}`);
// Cancel uses DELETE with JSON body (unique to Pionex)
const canceled = await exchange.cancelOrder(order.id, 'BTC/USDT');
console.log(`Canceled: ${canceled.status}`);
// Cancel all open orders for a symbol
await exchange.cancelAllOrders('BTC/USDT');
})();Pionex WebSocket (Real-Time)
const { Pionex } = require('@ygcc/ygcc');
const exchange = new Pionex();
// Real-time order book (server PING → client PONG heartbeat)
exchange.watchOrderBook('BTC/USDT', (book) => {
const spread = book.asks[0][0] - book.bids[0][0];
console.log(`Spread: $${spread.toFixed(2)}`);
}, 100);
// Real-time trades
exchange.watchTrades('BTC/USDT', (trades) => {
trades.forEach(t => console.log(`${t.side} ${t.amount} @ $${t.price}`));
});
process.on('SIGINT', async () => {
await exchange.closeAllWs();
process.exit(0);
});Using Bibox
const { Bibox } = require('@ygcc/ygcc');
const exchange = new Bibox();
(async () => {
await exchange.loadMarkets();
console.log(`${exchange.symbols.length} symbols loaded`);
// Bibox uses underscore-separated symbols: BTC_USDT
const ticker = await exchange.fetchTicker('BTC/USDT');
console.log(`BTC: $${ticker.last}`);
const book = await exchange.fetchOrderBook('BTC/USDT', 10);
console.log(`Best bid: $${book.bids[0][0]} | Best ask: $${book.asks[0][0]}`);
})();Bibox Trading (Private)
const { Bibox } = require('@ygcc/ygcc');
const exchange = new Bibox({
apiKey: process.env.BIBOX_API_KEY,
secret: process.env.BIBOX_SECRET,
});
(async () => {
const balance = await exchange.fetchBalance();
console.log('USDT:', balance.USDT);
// Bibox uses dual auth: V3 HmacMD5 for trading, V4 HmacSHA256 for account
// Only limit orders supported (no market orders)
const order = await exchange.createLimitOrder('BTC/USDT', 'BUY', 0.001, 50000);
console.log(`Order ${order.id}: ${order.status}`);
// Cancel uses POST (not DELETE like Pionex)
const canceled = await exchange.cancelOrder(order.id);
console.log(`Canceled: ${canceled.status}`);
})();Bibox WebSocket (zlib compressed)
const { Bibox } = require('@ygcc/ygcc');
const exchange = new Bibox();
// Real-time order book via zlib-compressed binary data
exchange.watchOrderBook('BTC/USDT', (book) => {
const spread = book.asks[0][0] - book.bids[0][0];
console.log(`Spread: $${spread.toFixed(2)}`);
}, 10);
// Graceful shutdown
process.on('SIGINT', async () => {
await exchange.closeAllWs();
process.exit(0);
});Using WhiteBit
const { WhiteBit } = require('@ygcc/ygcc');
const exchange = new WhiteBit();
(async () => {
await exchange.loadMarkets();
console.log(`${exchange.symbols.length} symbols loaded`);
// WhiteBit uses underscore-separated symbols: BTC_USDT
const ticker = await exchange.fetchTicker('BTC/USDT');
console.log(`BTC: $${ticker.last}`);
const book = await exchange.fetchOrderBook('BTC/USDT', 10);
console.log(`Best bid: $${book.bids[0][0]} | Best ask: $${book.asks[0][0]}`);
})();WhiteBit Trading (Private)
const { WhiteBit } = require('@ygcc/ygcc');
const exchange = new WhiteBit({
apiKey: process.env.WHITEBIT_API_KEY,
secret: process.env.WHITEBIT_SECRET,
});
(async () => {
const balance = await exchange.fetchBalance();
console.log('USDT:', balance.USDT);
// WhiteBit uses Base64+HMAC-SHA512 signing, all private endpoints are POST
const order = await exchange.createLimitOrder('BTC/USDT', 'BUY', 0.001, 50000);
console.log(`Order ${order.id}: ${order.status}`);
const canceled = await exchange.cancelOrder(order.id);
console.log(`Canceled: ${canceled.status}`);
})();WhiteBit WebSocket (zlib compressed)
const { WhiteBit } = require('@ygcc/ygcc');
const exchange = new WhiteBit();
// Real-time order book via zlib-compressed binary data (Z_SYNC_FLUSH)
exchange.watchOrderBook('BTC/USDT', (book) => {
const spread = book.asks[0][0] - book.bids[0][0];
console.log(`Spread: $${spread.toFixed(2)}`);
}, 50);
process.on('SIGINT', async () => {
await exchange.closeAllWs();
process.exit(0);
});Using VALR
const { Valr } = require('@ygcc/ygcc');
const exchange = new Valr();
(async () => {
await exchange.loadMarkets();
console.log(`${exchange.symbols.length} symbols loaded`);
// VALR uses concatenated symbols: BTCZAR (South African exchange, ZAR quote)
const ticker = await exchange.fetchTicker('BTC/ZAR');
console.log(`BTC: R${ticker.last}`);
const book = await exchange.fetchOrderBook('BTC/ZAR', 10);
console.log(`Best bid: R${book.bids[0][0]} | Best ask: R${book.asks[0][0]}`);
})();VALR Trading (Private)
const { Valr } = require('@ygcc/ygcc');
const exchange = new Valr({
apiKey: process.env.VALR_API_KEY,
secret: process.env.VALR_SECRET,
});
(async () => {
const balance = await exchange.fetchBalance();
console.log('ZAR:', balance.ZAR);
// VALR uses HMAC-SHA512(timestamp+method+path+body) signing
const order = await exchange.createLimitOrder('BTC/ZAR', 'BUY', 0.001, 500000);
console.log(`Order ${order.id}: ${order.status}`);
// Cancel uses DELETE with JSON body (like Pionex)
const canceled = await exchange.cancelOrder(order.id, 'BTC/ZAR');
console.log(`Canceled: ${canceled.status}`);
})();Using Bitexen
const { Bitexen } = require('@ygcc/ygcc');
const exchange = new Bitexen();
(async () => {
await exchange.loadMarkets();
console.log(`${exchange.symbols.length} symbols loaded`);
// Bitexen uses concatenated symbols: BTCTRY (Turkish exchange, TRY quote)
const ticker = await exchange.fetchTicker('BTC/TRY');
console.log(`BTC: ₺${ticker.last}`);
})();Bitexen Trading (Private)
const { Bitexen } = require('@ygcc/ygcc');
const exchange = new Bitexen({
apiKey: process.env.BITEXEN_API_KEY,
secret: process.env.BITEXEN_SECRET,
passphrase: process.env.BITEXEN_PASSPHRASE, // Bitexen requires 4 credentials
uid: process.env.BITEXEN_USERNAME,
});
(async () => {
const balance = await exchange.fetchBalance();
console.log('TRY:', balance.TRY);
// Bitexen uses HMAC-SHA256 uppercase, only limit orders, buy_sell: B/S
const order = await exchange.createLimitOrder('BTC/TRY', 'BUY', 0.001, 750000);
console.log(`Order ${order.id}: ${order.status}`);
// Cancel uses POST with orderId in URL path
const canceled = await exchange.cancelOrder(order.id);
console.log(`Canceled: ${canceled.status}`);
})();Bitexen WebSocket (Socket.IO v2)
const { Bitexen } = require('@ygcc/ygcc');
const exchange = new Bitexen();
// Real-time ticker via Socket.IO v2 (SID handshake, Engine.IO keepalive)
exchange.watchTicker('BTC/TRY', (ticker) => {
console.log(`BTC: ₺${ticker.last}`);
});
// Real-time order book
exchange.watchOrderBook('BTC/TRY', (book) => {
const spread = book.asks[0][0] - book.bids[0][0];
console.log(`Spread: ₺${spread.toFixed(2)}`);
});
process.on('SIGINT', async () => {
await exchange.closeAllWs();
process.exit(0);
});Using BtcTurk
const { BtcTurk } = require('@ygcc/ygcc');
const exchange = new BtcTurk();
(async () => {
await exchange.loadMarkets();
console.log(`${exchange.symbols.length} symbols loaded`);
// BtcTurk uses concatenated symbols: BTCTRY (Turkish exchange)
const ticker = await exchange.fetchTicker('BTC/TRY');
console.log(`BTC: ₺${ticker.last}`);
const book = await exchange.fetchOrderBook('BTC/TRY', 5);
console.log(`Best bid: ₺${book.bids[0][0]} | Best ask: ₺${book.asks[0][0]}`);
})();BtcTurk Trading (Private)
const { BtcTurk } = require('@ygcc/ygcc');
const exchange = new BtcTurk({
apiKey: process.env.BTCTURK_API_KEY,
secret: process.env.BTCTURK_SECRET, // Base64-encoded secret
});
(async () => {
const balance = await exchange.fetchBalance();
console.log('TRY:', balance.TRY);
// BtcTurk uses HMAC-SHA256 with Base64-decoded secret key
const order = await exchange.createLimitOrder('BTC/TRY', 'buy', 0.001, 2500000);
console.log(`Order ${order.id}: ${order.status}`);
// cancelOrder uses DELETE with id in query params
const canceled = await exchange.cancelOrder(order.id, 'BTC/TRY');
console.log(`Canceled: ${canceled.status}`);
})();BtcTurk WebSocket
const { BtcTurk } = require('@ygcc/ygcc');
const exchange = new BtcTurk();
// Real-time order book via JSON array protocol [type, payload]
exchange.watchOrderBook('BTC/TRY', (book) => {
const spread = book.asks[0][0] - book.bids[0][0];
console.log(`Spread: ₺${spread.toFixed(2)}`);
});Using BTSE
const { Btse } = require('@ygcc/ygcc');
const exchange = new Btse();
(async () => {
await exchange.loadMarkets();
console.log(`${exchange.symbols.length} symbols loaded`);
// BTSE uses hyphen-separated symbols: BTC-USDT
const ticker = await exchange.fetchTicker('BTC/USDT');
console.log(`BTC: $${ticker.last}`);
const book = await exchange.fetchOrderBook('BTC/USDT', 5);
console.log(`Best bid: $${book.bids[0][0]} | Best ask: $${book.asks[0][0]}`);
})();BTSE Trading (Private)
const { Btse } = require('@ygcc/ygcc');
const exchange = new Btse({
apiKey: process.env.BTSE_API_KEY,
secret: process.env.BTSE_SECRET,
});
(async () => {
const balance = await exchange.fetchBalance();
console.log('USDT:', balance.USDT);
// BTSE uses HMAC-SHA384, numeric order types (76=limit, 77=market)
const order = await exchange.createLimitOrder('BTC/USDT', 'BUY', 0.001, 65000);
console.log(`Order ${order.id}: ${order.status}`);
// cancelOrder uses DELETE with JSON body
const canceled = await exchange.cancelOrder(order.id, 'BTC/USDT');
console.log(`Canceled: ${canceled.status}`);
})();Using EXMO
const { Exmo } = require('@ygcc/ygcc');
const exchange = new Exmo();
(async () => {
await exchange.loadMarkets();
console.log(`${exchange.symbols.length} symbols loaded`);
// EXMO uses underscore-separated symbols: BTC_USD
const ticker = await exchange.fetchTicker('BTC/USD');
console.log(`BTC: $${ticker.last}`);
const book = await exchange.fetchOrderBook('BTC/USD', 5);
console.log(`Best bid: $${book.bids[0][0]} | Best ask: $${book.asks[0][0]}`);
})();EXMO Trading (Private)
const { Exmo } = require('@ygcc/ygcc');
const exchange = new Exmo({
apiKey: process.env.EXMO_API_KEY,
secret: process.env.EXMO_SECRET,
});
(async () => {
const balance = await exchange.fetchBalance();
console.log('USD:', balance.USD);
// EXMO uses HMAC-SHA512 with form-encoded POST, nonce in body
const order = await exchange.createLimitOrder('BTC/USD', 'buy', 0.001, 65000);
console.log(`Order ${order.id}: ${order.status}`);
// cancelOrder also uses POST (all private endpoints are POST)
const canceled = await exchange.cancelOrder(order.id, 'BTC/USD');
console.log(`Canceled: ${canceled.status}`);
})();Using CoinTR
const { Cointr } = require('@ygcc/ygcc');
const exchange = new Cointr();
(async () => {
await exchange.loadMarkets();
console.log(`${exchange.symbols.length} symbols loaded`);
// CoinTR uses concatenated symbols: BTCUSDT (OKX-style API)
const ticker = await exchange.fetchTicker('BTC/USDT');
console.log(`BTC: $${ticker.last}`);
const book = await exchange.fetchOrderBook('BTC/USDT', 5);
console.log(`Best bid: $${book.bids[0][0]} | Best ask: $${book.asks[0][0]}`);
})();CoinTR Trading (Private)
const { Cointr } = require('@ygcc/ygcc');
const exchange = new Cointr({
apiKey: process.env.COINTR_API_KEY,
secret: process.env.COINTR_SECRET,
});
(async () => {
const balance = await exchange.fetchBalance();
console.log('USDT:', balance.USDT);
// CoinTR uses double-layer HMAC-SHA256, auto-generates clOrdId (UUID)
const order = await exchange.createLimitOrder('BTC/USDT', 'buy', 0.001, 65000);
console.log(`Order ${order.id}: ${order.status}`);
const canceled = await exchange.cancelOrder(order.id, 'BTC/USDT');
console.log(`Canceled: ${canceled.status}`);
})();Testnet / Sandbox Mode
// Binance testnet
const binance = new Binance({
apiKey: 'testnet-key',
secret: 'testnet-secret',
options: { sandbox: true }, // Uses testnet.binance.vision
});
// Bybit testnet
const bybit = new Bybit({
apiKey: 'testnet-key',
secret: 'testnet-secret',
options: { sandbox: true }, // Uses api-testnet.bybit.com
});
// OKX demo trading
const okx = new Okx({
apiKey: 'demo-key',
secret: 'demo-secret',
passphrase: 'demo-pass',
options: { sandbox: true }, // Adds x-simulated-trading header
});Unified API Reference
All exchanges implement the same method signatures:
Market Data (Public)
| Method | Description | Binance | Bybit | OKX | Kraken | Gate.io | KuCoin | Coinbase | Bitfinex | Bitstamp | Bittrex | LBank | Phemex | BitMart | Bitrue | Bitforex | Pionex | Bibox | WhiteBit | VALR | Bitexen | BtcTurk | BTSE | EXMO | CoinTR |
|--------|-------------|---------|-------|-----|--------|---------|--------|----------|----------|----------|---------|-------|--------|---------|--------|----------|--------|-------|----------|------|---------|---------|------|------|--------|
| loadMarkets() | Load trading pairs, filters, precision rules | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| fetchTicker(symbol) | 24hr price statistics | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| fetchTickers(symbols?) | All tickers at once | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | ❌ | ❌ | ✅ | ❌ | ✅ | ✅ | ❌ | ✅ | ✅ |
| fetchOrderBook(symbol, limit?) | Bids & asks depth | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ |
| fetchTrades(symbol, since?, limit?) | Recent public trades | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| fetchOHLCV(symbol, timeframe?, since?, limit?) | Candlestick / kline data | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| fetchAvgPrice(symbol) | Current average price | ✅ | | | | | | | | | | | | | | | | | | | | | | | |
| fetchPrice(symbol?) | Quick price lookup (lightweight) | ✅ | | | | | | | | | | | | | | | | | | | | | | | |
| fetchBookTicker(symbol?) | Best bid/ask only | ✅ | | | | | | | | | | | | | | | | | | | | | | | |
| fetchTime() | Server time | | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
Trading (Private — Signed)
| Method | Description | Binance | Bybit | OKX | Kraken | Gate.io | KuCoin | Coinbase | Bitfinex | Bitstamp | Bittrex | LBank | Phemex | BitMart | Bitrue | Bitforex | Pionex | Bibox | WhiteBit | VALR | Bitexen | BtcTurk | BTSE | EXMO | CoinTR |
|--------|-------------|---------|-------|-----|--------|---------|--------|----------|----------|----------|---------|-------|--------|---------|--------|----------|--------|-------|----------|------|---------|---------|------|------|--------|
| createOrder(symbol, type, side, amount, price?, params?) | Place any order type | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| createLimitOrder(symbol, side, amount, price) | Limit order shortcut | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| createMarketOrder(symbol, side, amount) | Market order shortcut | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | ✅ | ❌ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ |
| cancelOrder(id, symbol) | Cancel single order | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| cancelAllOrders(symbol) | Cancel all open orders | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | ✅ | | ❌ | ❌ | ❌ | | | | |
| amendOrder(id, symbol, params) | Modify existing order | ✅ | ✅ | ✅ | | | | | | | | | | | | | | | | | | | | | |
| createOCO(symbol, side, qty, price, stopPrice) | One-Cancels-Other | ✅ | | | | | | | | | | | | | | | | | | | | | | | |
| createOTO(...) | One-Triggers-Other | ✅ | | | | | | | | | | | | | | | | | | | | | | | |
| createOTOCO(...) | One-Triggers-OCO | ✅ | | | | | | | | | | | | | | | | | | | | | | | |
| testOrder(...) | Validate without placing | ✅ | | | | | | | | | | | | | | | | | | | | | | | |
Account (Private — Signed)
| Method | Description | Binance | Bybit | OKX | Kraken | Gate.io | KuCoin | Coinbase | Bitfinex | Bitstamp | Bittrex | LBank | Phemex | BitMart | Bitrue | Bitforex | Pionex | Bibox | WhiteBit | VALR | Bitexen | BtcTurk | BTSE | EXMO | CoinTR |
|--------|-------------|---------|-------|-----|--------|---------|--------|----------|----------|----------|---------|-------|--------|---------|--------|----------|--------|-------|----------|------|---------|---------|------|------|--------|
| fetchBalance() | Account balances (free, used, total) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| fetchOrder(id, symbol) | Single order status | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| fetchOpenOrders(symbol?) | All open orders | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ |
| fetchClosedOrders(symbol, ...) | Closed order history | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | ✅ | ✅ | ✅ | ✅ | ✅ | | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| fetchMyTrades(symbol, ...) | Trade history with fees | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | ✅ | ✅ | ✅ | | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| fetchTradingFees(symbol) | Maker/taker fee rates | | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | ✅ | | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| fetchCommission(symbol) | Maker/taker commission rates | ✅ | | | | | | | | | | | | | | | | | | | | | | | |
WebSocket Streams
| Method | Description | Binance | Bybit | OKX | Kraken | Gate.io | KuCoin | Coinbase | Bitfinex | Bitstamp | Bittrex | LBank | Phemex | BitMart | Bitrue | Bitforex | Pionex | Bibox | WhiteBit | VALR | Bitexen | BtcTurk | BTSE | EXMO | CoinTR |
|--------|-------------|---------|-------|-----|--------|---------|--------|----------|----------|----------|---------|-------|--------|---------|--------|----------|--------|-------|----------|------|---------|---------|------|------|--------|
| watchTicker(symbol, callback) | Real-time ticker | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ |
| watchAllTickers(callback) | All tickers stream | ✅ | | | | | | | | | | | | | | | | | | | | | | | |
| watchOrderBook(symbol, callback, levels?) | Real-time order book | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| watchTrades(symbol, callback) | Real-time trades | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| watchKlines(symbol, interval, callback) | Real-time candlesticks | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| watchBookTicker(symbol, callback) | Real-time best bid/ask | ✅ | | | | | | | | | | | | | | | | | | | | | | | |
| watchBalance(callback) | Balance updates (private) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | | | | | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| watchOrders(callback) | Order updates (private) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | | | | | | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
Unified Response Formats
Ticker
{
symbol: 'BTCUSDT',
last: 97500.00,
bid: 97499.50, bidVolume: 1.5,
ask: 97500.50, askVolume: 0.8,
high: 98200.00, low: 96800.00,
open: 97000.00, close: 97500.00,
volume: 12345.678,
quoteVolume: 1204567890.12,
change: 500.00,
percentage: 0.515,
timestamp: 1700000000000,
datetime: '2023-11-14T22:13:20.000Z',
}Order Book
{
symbol: 'BTCUSDT',
bids: [[97500.00, 1.5], [97499.00, 2.0], ...], // [price, quantity]
asks: [[97501.00, 0.8], [97502.00, 1.2], ...],
timestamp: 1700000000000,
nonce: 123456789,
}Order
{
id: '12345678',
clientOrderId: 'myOrder1',
symbol: 'BTCUSDT',
type: 'LIMIT',
side: 'BUY',
price: 95000.00,
amount: 0.01,
filled: 0.005,
remaining: 0.005,
cost: 475.00,
average: 95000.00,
status: 'PARTIALLY_FILLED', // NEW, FILLED, CANCELED, EXPIRED, REJECTED
timestamp: 1700000000000,
trades: [{ price, amount, commission, commissionAsset }],
}Balance
{
BTC: { free: 0.50, used: 0.10, total: 0.60 },
USDT: { free: 5000, used: 1000, total: 6000 },
timestamp: 1700000000000,
}Error Handling
YGCC provides typed errors for precise error handling:
const {
Binance,
AuthenticationError,
InsufficientFunds,
RateLimitExceeded,
InvalidOrder,
OrderNotFound,
BadSymbol,
NetworkError,
} = require('@ygcc/ygcc');
try {
await exchange.createOrder('BTCUSDT', 'LIMIT', 'BUY', 0.001, 95000);
} catch (error) {
if (error instanceof AuthenticationError) {
console.error('Check your API key and secret');
} else if (error instanceof InsufficientFunds) {
console.error('Not enough balance');
} else if (error instanceof RateLimitExceeded) {
console.error('Slow down — rate limited');
} else if (error instanceof InvalidOrder) {
console.error('Order rejected:', error.message);
} else if (error instanceof NetworkError) {
console.error('Connection issue — retry');
}
}Error Hierarchy
Error
└── ExchangeError
├── AuthenticationError // Invalid API key, signature, or timestamp
├── RateLimitExceeded // 429 / 418 responses
├── InsufficientFunds // Not enough balance
├── InvalidOrder // Filter violations, bad params
├── OrderNotFound // Order doesn't exist
├── BadSymbol // Invalid trading pair
├── BadRequest // Malformed request
├── ExchangeNotAvailable // Exchange maintenance
└── NetworkError
└── RequestTimeout // Request exceeded timeoutRate Limiting
YGCC automatically tracks and respects exchange rate limits:
const exchange = new Binance({ enableRateLimit: true }); // Default: true
// Monitor rate limit usage
exchange.on('rateLimitWarning', ({ used, limit }) => {
console.warn(`Rate limit: ${used}/${limit} weight used`);
});Binance uses a weight-based system (6000 weight/minute). Each endpoint has a different weight cost. YGCC tracks the X-MBX-USED-WEIGHT-1M response header and automatically throttles requests when approaching the limit.
Architecture
ygcc/
├── index.js # Entry point: const { Binance, Bybit, Okx, ..., HotCoin, Icrypex, Jbex, PointPay, Trubit, TradeOgre } = require('@ygcc/ygcc')
├── lib/
│ ├── BaseExchange.js # Abstract base class — unified interface
│ ├── binance.js # Binance implementation (1369 lines, 59 methods)
│ ├── bybit.js # Bybit V5 implementation (1021 lines, 45 methods)
│ ├── okx.js # OKX V5 implementation (690 lines, 42 methods)
│ ├── kraken.js # Kraken implementation (680 lines, 40 methods)
│ ├── gateio.js # Gate.io V4 implementation (700 lines, 40 methods)
│ ├── kucoin.js # KuCoin V1 implementation (1033 lines, 42 methods)
│ ├── coinbase.js # Coinbase Advanced Trade implementation (780 lines, 42 methods)
│ ├── bitfinex.js # Bitfinex V2 implementation (750 lines, 42 methods)
│ ├── bitstamp.js # Bitstamp V2 implementation (580 lines, 38 methods)
│ ├── bittrex.js # Bittrex V3 implementation (976 lines, 44 methods)
│ ├── lbank.js # LBank V2 implementation (530 lines, 40 methods)
│ ├── phemex.js # Phemex Spot implementation (580 lines, 42 methods)
│ ├── bitmart.js # BitMart Spot implementation (600 lines, 48 methods)
│ ├── bitrue.js # Bitrue Spot implementation (600 lines, 42 methods)
│ ├── bitforex.js # Bitforex Spot implementation (500 lines, 35 methods)
│ ├── pionex.js # Pionex — HMAC-SHA256 header-signing, DELETE with JSON body
│ ├── bibox.js # Bibox — dual V3 HmacMD5 + V4 HmacSHA256, zlib WS, limit orders only
│ ├── whitebit.js # WhiteBit — Base64+HMAC-SHA512, zlib Z_SYNC_FLUSH WS, all private POST
│ ├── valr.js # VALR — HMAC-SHA512 timestamp+method+path, DELETE with JSON body, ZAR pairs
│ ├── bitexen.js # Bitexen — 4-credential HMAC-SHA256 uppercase, Socket.IO v2 WS, TRY pairs
│ ├── btcturk.js # BtcTurk exchange
│ ├── btse.js # BTSE exchange
│ ├── exmo.js # EXMO exchange
│ ├── cointr.js # CoinTR exchange
│ ├── hotcoin.js # HotCoin — Huobi-style query-string HMAC-SHA256 Base64, GZIP WS
│ ├── icrypex.js # iCrypex — Base64-decoded HMAC-SHA256, ICX headers, pipe-delimited WS
│ ├── jbex.js # JBEX — Binance-compatible HMAC-SHA256, Galactic-Tech white-label
│ ├── pointpay.js # PointPay — HMAC-SHA512 payload-based, all private POST
│ ├── trubit.js # Trubit — Binance-compatible, same platform as JBEX
│ ├── tradeogre.js # TradeOgre — HTTP Basic Auth, no WS, limit orders only
│ └── utils/
│ ├── crypto.js # HMAC-SHA256/384/512 + JWT/ES256 + MD5 + HmacMD5 + Base64-decoded + memo + path + Base64 + uppercase signing
│ ├── errors.js # Typed error classes
│ ├── helpers.js # Safe value extraction, query builders
│ ├── throttler.js # Token-bucket rate limiter
│ └── ws.js # WebSocket with auto-reconnect
├── examples/
│ ├── fetch-ticker.js # Public market data demo
│ ├── place-order.js # Trading demo
│ └── websocket-stream.js # Real-time streaming demo
└── tests/
├── binance.test.js # 82 tests — Binance implementation
├── bybit.test.js # 83 tests — Bybit V5 implementation
├── okx.test.js # 91 tests — OKX V5 implementation
├── kraken.test.js # 86 tests — Kraken implementation
├── gateio.test.js # 84 tests — Gate.io V4 implementation
├── kucoin.test.js # 86 tests — KuCoin V1 implementation
├── coinbase.test.js # 93 tests — Coinbase Advanced Trade implementation
├── bitfinex.test.js # 97 tests — Bitfinex V2 implementation
├── bitstamp.test.js # 91 tests — Bitstamp V2 implementation
├── bittrex.test.js # 112 tests — Bittrex V3 implementation
├── lbank.test.js # 110 tests — LBank V2 implementation
├── phemex.test.js # 106 tests — Phemex Spot implementation
├── bitmart.test.js # 108 tests — BitMart Spot implementation
├── bitrue.test.js # 108 tests — Bitrue Spot implementation
├── bitforex.test.js # 101 tests — Bitforex Spot implementation
├── pionex.test.js # 101 tests — Pionex implementation
├── bibox.test.js # 98 tests — Bibox dual-auth implementation
├── whitebit.test.js # 94 tests — WhiteBit Base64+HMAC-SHA512 implementation
├── valr.test.js # 97 tests — VALR HMAC-SHA512 implementation
├── bitexen.test.js # 101 tests — Bitexen 4-credential implementation
├── btcturk.test.js # 97 tests — BtcTurk tests (97 tests, 16 sections)
├── btse.test.js # 94 tests — BTSE tests (94 tests, 16 sections)
├── exmo.test.js # 93 tests — EXMO tests (93 tests, 16 sections)
├── cointr.test.js # 92 tests — CoinTR tests (92 tests, 16 sections)
├── hotcoin.test.js # 95 tests — HotCoin tests (16 sections)
├── icrypex.test.js # 95 tests — iCrypex tests (16 sections)
├── jbex.test.js # 93 tests — JBEX tests (16 sections)
├── pointpay.test.js # 95 tests — PointPay tests (16 sections)
├── trubit.test.js # 93 tests — Trubit tests (16 sections)
└── tradeogre.test.js # 91 tests — TradeOgre tests (15 sections, no WS)Adding a New Exchange
Every exchange extends BaseExchange and implements:
const BaseExchange = require('./BaseExchange');
class MyExchange extends BaseExchange {
describe() {
return {
id: 'myexchange',
name: 'My Exchange',
version: 'v1',
rateLimit: 100,
urls: { api: 'https://api.myexchange.com' },
has: { fetchTicker: true, createOrder: true, ... },
};
}
_sign(path, method, params) {
// Exchange-specific authentication
}
async loadMarkets() { /* ... */ }
async fetchTicker(symbol) { /* ... */ }
async createOrder(symbol, type, side, amount, price) { /* ... */ }
// ... implement all supported methods
}Tests
npm test▶ Module Exports (4 tests)
▶ Binance Constructor (7 tests)
▶ BaseExchange (1 test)
▶ Binance Authentication (5 tests)
▶ Binance Parsers (8 tests)
▶ Binance Error Mapping (9 tests)
▶ Binance Rate Limit Header Handling (2 tests)
▶ Binance API Methods — mocked (16 tests)
▶ Utility Functions (18 tests)
▶ Crypto Utilities (4 tests)
▶ Throttler (5 tests)
▶ Error Classes (4 tests)
▶ Binance market() lookup (3 tests)
▶ Module Exports — Bybit (3 tests)
▶ Bybit Constructor (10 tests)
▶ Bybit Authentication (6 tests)
▶ Bybit Response Unwrapping (4 tests)
▶ Bybit Parsers (10 tests)
▶ Bybit Helper Methods (3 tests)
▶ Bybit Error Mapping (13 tests)
▶ Bybit HTTP Error Handling (5 tests)
▶ Bybit Rate Limit Header Handling (3 tests)
▶ Bybit API Methods — mocked (20 tests)
▶ Bybit market() lookup (3 tests)
▶ Bybit vs Binance Differences (5 tests)
▶ Module Exports — OKX (3 tests)
▶ OKX Constructor (12 tests)
▶ OKX Authentication (9 tests)
▶ OKX Response Unwrapping (4 tests)
▶ OKX Parsers (9 tests)
▶ OKX Helper Methods (4 tests)
▶ OKX Error Mapping (12 tests)
▶ OKX HTTP Error Handling (5 tests)
▶ OKX Rate Limit Header Handling (3 tests)
▶ OKX API Methods — mocked (18 tests)
▶ OKX market() lookup (3 tests)
▶ OKX vs Binance/Bybit Differences (7 tests)
▶ Crypto — hmacSHA256Base64 (2 tests)
▶ Module Exports — Kraken (3 tests)
▶ Kraken Constructor (10 tests)
▶ Kraken Authentication (8 tests)
▶ Kraken Response Unwrapping (4 tests)
▶ Kraken Parsers (10 tests)
▶ Kraken Helper Methods (4 tests)
▶ Kraken Error Mapping (12 tests)
▶ Kraken HTTP Error Handling (5 tests)
▶ Kraken Rate Limit Headers (3 tests)
▶ Kraken Mocked API Calls (20 tests)
▶ Kraken Market Lookup (3 tests)
▶ Kraken vs Other Exchanges (7 tests)
▶ Crypto — krakenSign (3 tests)
▶ Module Exports — Gate.io (3 tests)
▶ Gateio Constructor (10 tests)
▶ Gate.io Authentication (8 tests)
▶ Gate.io Response Handling (4 tests)
▶ Gate.io Parsers (9 tests)
▶ Gate.io Helper Methods (4 tests)
▶ Gate.io Error Mapping (10 tests)
▶ Gate.io HTTP Error Handling (5 tests)
▶ Gate.io Rate Limit Headers (3 tests)
▶ Gate.io Mocked API Calls (17 tests)
▶ Gate.io Market Lookup (3 tests)
▶ Gate.io vs Others Differences (5 tests)
▶ Crypto — sha512 & hmacSHA512Hex (3 tests)
▶ Module Exports — KuCoin (3 tests)
▶ KuCoin Constructor (10 tests)
▶ KuCoin Authentication (8 tests)
▶ KuCoin Response Handling (4 tests)
▶ KuCoin Parsers (10 tests)
▶ KuCoin Helper Methods (4 tests)
▶ KuCoin Error Mapping (10 tests)
▶ KuCoin HTTP Error Handling (5 tests)
▶ KuCoin Rate Limit Handling (3 tests)
▶ KuCoin Mocked API Calls (18 tests)
▶ KuCoin Market Lookup (3 tests)
▶ KuCoin vs Others Differences (6 tests)
▶ Crypto — hmacSHA256Base64 for KuCoin (3 tests)
▶ Module Exports — Coinbase (3 tests)
▶ Coinbase Constructor (10 tests)
▶ Coinbase Authentication — JWT/ES256 (10 tests)
▶ Coinbase Response Handling (4 tests)
▶ Coinbase Parsers (10 tests)
▶ Coinbase Helper Methods (8 tests)
▶ Coinbase Error Mapping (10 tests)
▶ Coinbase HTTP Error Handling (5 tests)
▶ Coinbase Rate Limit Handling (3 tests)
▶ Coinbase Mocked API Calls (16 tests)
▶ Coinbase Market Lookup (3 tests)
▶ Coinbase vs Others Differences (8 tests)
▶ Crypto — signJWT + base64UrlEncode (3 tests)
▶ Module Exports — Bitfinex (3 tests)
▶ Bitfinex Constructor (10 tests)
▶ Bitfinex Authentication — HMAC-SHA384 (10 tests)
▶ Bitfinex Response Handling (5 tests)
▶ Bitfinex Parsers (12 tests)
▶ Bitfinex Helper Methods (13 tests)
▶ Bitfinex Error Mapping (10 tests)
▶ Bitfinex HTTP Error Handling (6 tests)
▶ Bitfinex Rate Limit Handling (3 tests)
▶ Bitfinex Mocked API Calls (16 tests)
▶ Bitfinex Market Lookup (3 tests)
▶ Bitfinex vs Other Exchanges (8 tests)
▶ Crypto — hmacSHA