UNPKG

binance-futures-wrapper

Version:

A comprehensive TypeScript wrapper for Binance USDT-M Futures API with full REST and WebSocket support

298 lines 8.83 kB
"use strict"; /** * Utility functions for Binance Futures API */ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.ReconnectionManager = exports.RateLimiter = exports.Logger = void 0; exports.createSignature = createSignature; exports.getTimestamp = getTimestamp; exports.objectToQueryString = objectToQueryString; exports.addSignature = addSignature; exports.getBaseUrls = getBaseUrls; exports.validateConfig = validateConfig; exports.generateClientOrderId = generateClientOrderId; exports.formatNumber = formatNumber; exports.sleep = sleep; exports.retry = retry; exports.convertKlineData = convertKlineData; exports.convertKlinesData = convertKlinesData; const crypto = __importStar(require("crypto")); /** * Create HMAC SHA256 signature for Binance API */ function createSignature(queryString, apiSecret) { return crypto .createHmac('sha256', apiSecret) .update(queryString) .digest('hex'); } /** * Get current timestamp in milliseconds */ function getTimestamp() { return Date.now(); } /** * Convert object to query string */ function objectToQueryString(obj) { const params = new URLSearchParams(); for (const [key, value] of Object.entries(obj)) { if (value !== undefined && value !== null) { if (Array.isArray(value)) { params.append(key, JSON.stringify(value)); } else { params.append(key, String(value)); } } } return params.toString(); } /** * Add signature to parameters */ function addSignature(params, apiSecret, timestamp) { const finalParams = { ...params, timestamp: timestamp || getTimestamp() }; const queryString = objectToQueryString(finalParams); const signature = createSignature(queryString, apiSecret); return { ...finalParams, signature }; } /** * Get base URLs based on testnet configuration */ function getBaseUrls(testnet = false) { if (testnet) { return { rest: 'https://testnet.binancefuture.com', ws: 'wss://stream.binancefuture.com' }; } return { rest: 'https://fapi.binance.com', ws: 'wss://fstream.binance.com' }; } /** * Validate Binance configuration */ function validateConfig(config) { // Allow empty API key/secret for public endpoints only if (!config.apiKey && !config.apiSecret) { // This is OK for public endpoints return; } if (!config.apiKey) { throw new Error('API key is required'); } if (!config.apiSecret) { throw new Error('API secret is required'); } if (config.recvWindow && (config.recvWindow < 1000 || config.recvWindow > 60000)) { throw new Error('recvWindow must be between 1000 and 60000 milliseconds'); } } /** * Generate random string for client order ID */ function generateClientOrderId(prefix = 'x-') { const timestamp = Date.now().toString(36); const random = Math.random().toString(36).substring(2, 8); return `${prefix}${timestamp}${random}`; } /** * Format number to string with proper precision */ function formatNumber(num, precision) { if (precision !== undefined) { return num.toFixed(precision); } return num.toString(); } /** * Sleep function for delays */ function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } /** * Retry function with exponential backoff */ async function retry(fn, maxRetries = 3, baseDelay = 1000) { let lastError; for (let attempt = 0; attempt < maxRetries; attempt++) { try { return await fn(); } catch (error) { lastError = error; if (attempt === maxRetries - 1) { throw lastError; } const delay = baseDelay * Math.pow(2, attempt); await sleep(delay); } } throw lastError; } /** * Logger utility */ class Logger { constructor(enabled = false, prefix = '[Binance]') { this.enabled = enabled; this.prefix = prefix; } log(message, ...args) { if (this.enabled) { console.log(`${this.prefix} ${message}`, ...args); } } error(message, ...args) { if (this.enabled) { console.error(`${this.prefix} ERROR: ${message}`, ...args); } } warn(message, ...args) { if (this.enabled) { console.warn(`${this.prefix} WARN: ${message}`, ...args); } } debug(message, ...args) { if (this.enabled) { console.debug(`${this.prefix} DEBUG: ${message}`, ...args); } } } exports.Logger = Logger; /** * Rate limiter utility */ class RateLimiter { constructor(maxRequests = 1200, timeWindow = 60000) { this.requests = []; this.maxRequests = maxRequests; this.timeWindow = timeWindow; } async checkLimit() { const now = Date.now(); // Remove old requests outside the time window this.requests = this.requests.filter(time => now - time < this.timeWindow); if (this.requests.length >= this.maxRequests) { const oldestRequest = Math.min(...this.requests); const waitTime = this.timeWindow - (now - oldestRequest); await sleep(waitTime); return this.checkLimit(); } this.requests.push(now); } } exports.RateLimiter = RateLimiter; /** * WebSocket reconnection utility */ class ReconnectionManager { constructor(maxAttempts = 10, baseDelay = 1000, maxDelay = 30000) { this.attempts = 0; this.maxAttempts = maxAttempts; this.baseDelay = baseDelay; this.maxDelay = maxDelay; } async getDelay() { if (this.attempts >= this.maxAttempts) { throw new Error('Max reconnection attempts reached'); } const delay = Math.min(this.baseDelay * Math.pow(2, this.attempts), this.maxDelay); this.attempts++; return delay; } reset() { this.attempts = 0; } canReconnect() { return this.attempts < this.maxAttempts; } } exports.ReconnectionManager = ReconnectionManager; /** * REST Data Converters */ /** * Convert raw kline array to Kline object * Binance returns klines as arrays in this format: * [ * 1499040000000, // Open time * "0.01634790", // Open * "0.80000000", // High * "0.01575800", // Low * "0.01577100", // Close * "148976.11427815", // Volume * 1499644799999, // Close time * "2434.19055334", // Quote asset volume * 308, // Number of trades * "1756.87402397", // Taker buy base asset volume * "28.46694368", // Taker buy quote asset volume * "17928899.62484339" // Ignore * ] */ function convertKlineData(rawKline) { return { openTime: rawKline[0], open: rawKline[1], high: rawKline[2], low: rawKline[3], close: rawKline[4], volume: rawKline[5], closeTime: rawKline[6], quoteAssetVolume: rawKline[7], count: rawKline[8], takerBuyBaseAssetVolume: rawKline[9], takerBuyQuoteAssetVolume: rawKline[10] }; } /** * Convert array of raw klines to array of Kline objects */ function convertKlinesData(rawKlines) { return rawKlines.map(convertKlineData); } //# sourceMappingURL=index.js.map