UNPKG

ccxt

Version:

A JavaScript / TypeScript / Python / C# / PHP cryptocurrency trading library with support for 100+ exchanges

1,180 lines (1,178 loc) • 169 kB
'use strict'; var hitbtc$1 = require('./abstract/hitbtc.js'); var number = require('./base/functions/number.js'); var Precise = require('./base/Precise.js'); var errors = require('./base/errors.js'); var sha256 = require('./static_dependencies/noble-hashes/sha256.js'); // ---------------------------------------------------------------------------- /** * @class hitbtc * @augments Exchange */ class hitbtc extends hitbtc$1 { describe() { return this.deepExtend(super.describe(), { 'id': 'hitbtc', 'name': 'HitBTC', 'countries': ['HK'], // 300 requests per second => 1000ms / 300 = 3.333 (Trading: placing, replacing, deleting) // 30 requests per second => ( 1000ms / rateLimit ) / 30 = cost = 10 (Market Data and other Public Requests) // 20 requests per second => ( 1000ms / rateLimit ) / 20 = cost = 15 (All Other) 'rateLimit': 3.333, 'version': '3', 'has': { 'CORS': false, 'spot': true, 'margin': true, 'swap': true, 'future': false, 'option': undefined, 'addMargin': true, 'cancelAllOrders': true, 'cancelOrder': true, 'closePosition': false, 'createDepositAddress': true, 'createOrder': true, 'createPostOnlyOrder': true, 'createReduceOnlyOrder': true, 'createStopLimitOrder': true, 'createStopMarketOrder': true, 'createStopOrder': true, 'editOrder': true, 'fetchAccounts': false, 'fetchBalance': true, 'fetchBorrowRateHistories': undefined, 'fetchBorrowRateHistory': undefined, 'fetchClosedOrders': true, 'fetchCrossBorrowRate': false, 'fetchCrossBorrowRates': false, 'fetchCurrencies': true, 'fetchDepositAddress': true, 'fetchDepositAddresses': false, 'fetchDepositAddressesByNetwork': false, 'fetchDeposits': true, 'fetchDepositsWithdrawals': true, 'fetchDepositWithdrawFee': 'emulated', 'fetchDepositWithdrawFees': true, 'fetchFundingHistory': undefined, 'fetchFundingRate': true, 'fetchFundingRateHistory': true, 'fetchFundingRates': true, 'fetchIndexOHLCV': true, 'fetchIsolatedBorrowRate': false, 'fetchIsolatedBorrowRates': false, 'fetchLeverage': true, 'fetchLeverageTiers': undefined, 'fetchLiquidations': false, 'fetchMarginMode': 'emulated', 'fetchMarginModes': true, 'fetchMarketLeverageTiers': false, 'fetchMarkets': true, 'fetchMarkOHLCV': true, 'fetchMyLiquidations': false, 'fetchMyTrades': true, 'fetchOHLCV': true, 'fetchOpenInterest': true, 'fetchOpenInterestHistory': false, 'fetchOpenInterests': true, 'fetchOpenOrder': true, 'fetchOpenOrders': true, 'fetchOrder': true, 'fetchOrderBook': true, 'fetchOrderBooks': true, 'fetchOrders': false, 'fetchOrderTrades': true, 'fetchPosition': true, 'fetchPositions': true, 'fetchPremiumIndexOHLCV': true, 'fetchTicker': true, 'fetchTickers': true, 'fetchTrades': true, 'fetchTradingFee': true, 'fetchTradingFees': true, 'fetchTransactions': 'emulated', 'fetchWithdrawals': true, 'reduceMargin': true, 'sandbox': true, 'setLeverage': true, 'setMargin': false, 'setMarginMode': false, 'setPositionMode': false, 'transfer': true, 'withdraw': true, }, 'precisionMode': number.TICK_SIZE, 'urls': { 'logo': 'https://user-images.githubusercontent.com/1294454/27766555-8eaec20e-5edc-11e7-9c5b-6dc69fc42f5e.jpg', 'test': { 'public': 'https://api.demo.hitbtc.com/api/3', 'private': 'https://api.demo.hitbtc.com/api/3', }, 'api': { 'public': 'https://api.hitbtc.com/api/3', 'private': 'https://api.hitbtc.com/api/3', }, 'www': 'https://hitbtc.com', 'referral': 'https://hitbtc.com/?ref_id=5a5d39a65d466', 'doc': [ 'https://api.hitbtc.com', 'https://github.com/hitbtc-com/hitbtc-api/blob/master/APIv2.md', ], 'fees': [ 'https://hitbtc.com/fees-and-limits', 'https://support.hitbtc.com/hc/en-us/articles/115005148605-Fees-and-limits', ], }, 'api': { 'public': { 'get': { 'public/currency': 10, 'public/currency/{currency}': 10, 'public/symbol': 10, 'public/symbol/{symbol}': 10, 'public/ticker': 10, 'public/ticker/{symbol}': 10, 'public/price/rate': 10, 'public/price/history': 10, 'public/price/ticker': 10, 'public/price/ticker/{symbol}': 10, 'public/trades': 10, 'public/trades/{symbol}': 10, 'public/orderbook': 10, 'public/orderbook/{symbol}': 10, 'public/candles': 10, 'public/candles/{symbol}': 10, 'public/converted/candles': 10, 'public/converted/candles/{symbol}': 10, 'public/futures/info': 10, 'public/futures/info/{symbol}': 10, 'public/futures/history/funding': 10, 'public/futures/history/funding/{symbol}': 10, 'public/futures/candles/index_price': 10, 'public/futures/candles/index_price/{symbol}': 10, 'public/futures/candles/mark_price': 10, 'public/futures/candles/mark_price/{symbol}': 10, 'public/futures/candles/premium_index': 10, 'public/futures/candles/premium_index/{symbol}': 10, 'public/futures/candles/open_interest': 10, 'public/futures/candles/open_interest/{symbol}': 10, }, }, 'private': { 'get': { 'spot/balance': 15, 'spot/balance/{currency}': 15, 'spot/order': 1, 'spot/order/{client_order_id}': 1, 'spot/fee': 15, 'spot/fee/{symbol}': 15, 'spot/history/order': 15, 'spot/history/trade': 15, 'margin/account': 1, 'margin/account/isolated/{symbol}': 1, 'margin/account/cross/{currency}': 1, 'margin/order': 1, 'margin/order/{client_order_id}': 1, 'margin/config': 15, 'margin/history/order': 15, 'margin/history/trade': 15, 'margin/history/positions': 15, 'margin/history/clearing': 15, 'futures/balance': 15, 'futures/balance/{currency}': 15, 'futures/account': 1, 'futures/account/isolated/{symbol}': 1, 'futures/order': 1, 'futures/order/{client_order_id}': 1, 'futures/config': 15, 'futures/fee': 15, 'futures/fee/{symbol}': 15, 'futures/history/order': 15, 'futures/history/trade': 15, 'futures/history/positions': 15, 'futures/history/clearing': 15, 'wallet/balance': 30, 'wallet/balance/{currency}': 30, 'wallet/crypto/address': 30, 'wallet/crypto/address/recent-deposit': 30, 'wallet/crypto/address/recent-withdraw': 30, 'wallet/crypto/address/check-mine': 30, 'wallet/transactions': 30, 'wallet/transactions/{tx_id}': 30, 'wallet/crypto/fee/estimate': 30, 'wallet/airdrops': 30, 'wallet/amount-locks': 30, 'sub-account': 15, 'sub-account/acl': 15, 'sub-account/balance/{subAccID}': 15, 'sub-account/crypto/address/{subAccID}/{currency}': 15, }, 'post': { 'spot/order': 1, 'spot/order/list': 1, 'margin/order': 1, 'margin/order/list': 1, 'futures/order': 1, 'futures/order/list': 1, 'wallet/crypto/address': 30, 'wallet/crypto/withdraw': 30, 'wallet/convert': 30, 'wallet/transfer': 30, 'wallet/internal/withdraw': 30, 'wallet/crypto/check-offchain-available': 30, 'wallet/crypto/fees/estimate': 30, 'wallet/airdrops/{id}/claim': 30, 'sub-account/freeze': 15, 'sub-account/activate': 15, 'sub-account/transfer': 15, 'sub-account/acl': 15, }, 'patch': { 'spot/order/{client_order_id}': 1, 'margin/order/{client_order_id}': 1, 'futures/order/{client_order_id}': 1, }, 'delete': { 'spot/order': 1, 'spot/order/{client_order_id}': 1, 'margin/position': 1, 'margin/position/isolated/{symbol}': 1, 'margin/order': 1, 'margin/order/{client_order_id}': 1, 'futures/position': 1, 'futures/position/{margin_mode}/{symbol}': 1, 'futures/order': 1, 'futures/order/{client_order_id}': 1, 'wallet/crypto/withdraw/{id}': 30, }, 'put': { 'margin/account/isolated/{symbol}': 1, 'futures/account/isolated/{symbol}': 1, 'wallet/crypto/withdraw/{id}': 30, }, }, }, 'fees': { 'trading': { 'tierBased': true, 'percentage': true, 'taker': this.parseNumber('0.0009'), 'maker': this.parseNumber('0.0009'), 'tiers': { 'maker': [ [this.parseNumber('0'), this.parseNumber('0.0009')], [this.parseNumber('10'), this.parseNumber('0.0007')], [this.parseNumber('100'), this.parseNumber('0.0006')], [this.parseNumber('500'), this.parseNumber('0.0005')], [this.parseNumber('1000'), this.parseNumber('0.0003')], [this.parseNumber('5000'), this.parseNumber('0.0002')], [this.parseNumber('10000'), this.parseNumber('0.0001')], [this.parseNumber('20000'), this.parseNumber('0')], [this.parseNumber('50000'), this.parseNumber('-0.0001')], [this.parseNumber('100000'), this.parseNumber('-0.0001')], ], 'taker': [ [this.parseNumber('0'), this.parseNumber('0.0009')], [this.parseNumber('10'), this.parseNumber('0.0008')], [this.parseNumber('100'), this.parseNumber('0.0007')], [this.parseNumber('500'), this.parseNumber('0.0007')], [this.parseNumber('1000'), this.parseNumber('0.0006')], [this.parseNumber('5000'), this.parseNumber('0.0006')], [this.parseNumber('10000'), this.parseNumber('0.0005')], [this.parseNumber('20000'), this.parseNumber('0.0004')], [this.parseNumber('50000'), this.parseNumber('0.0003')], [this.parseNumber('100000'), this.parseNumber('0.0002')], ], }, }, }, 'features': { 'default': { 'sandbox': true, 'createOrder': { 'marginMode': false, 'triggerPrice': true, 'triggerPriceType': undefined, 'triggerDirection': false, 'stopLossPrice': false, 'takeProfitPrice': false, 'attachedStopLossTakeProfit': undefined, 'timeInForce': { 'IOC': true, 'FOK': true, 'PO': true, 'GTD': true, }, 'hedged': false, 'selfTradePrevention': false, 'trailing': false, 'leverage': false, 'marketBuyByCost': false, 'marketBuyRequiresPrice': false, 'iceberg': true, }, 'createOrders': undefined, 'fetchMyTrades': { 'marginMode': true, 'limit': 1000, 'daysBack': 100000, 'untilDays': 100000, 'symbolRequired': false, 'marketType': true, }, 'fetchOrder': { 'marginMode': true, 'trigger': false, 'trailing': false, 'symbolRequired': false, 'marketType': true, }, 'fetchOpenOrders': { 'marginMode': true, 'limit': 1000, 'trigger': false, 'trailing': false, 'symbolRequired': false, 'marketType': true, }, 'fetchOrders': undefined, 'fetchClosedOrders': { 'marginMode': true, 'limit': 1000, 'daysBack': 100000, 'daysBackCanceled': 1, 'untilDays': 100000, 'trigger': false, 'trailing': false, 'symbolRequired': false, 'marketType': true, }, 'fetchOHLCV': { 'limit': 1000, }, }, 'spot': { 'extends': 'default', }, 'forDerivatives': { 'extends': 'default', 'createOrder': { 'marginMode': true, }, 'fetchOrder': { 'marginMode': false, }, 'fetchMyTrades': { 'marginMode': false, }, 'fetchOpenOrders': { 'marginMode': false, }, 'fetchClosedOrders': { 'marginMode': false, }, }, 'swap': { 'linear': { 'extends': 'forDerivatives', }, 'inverse': { 'extends': 'forDerivatives', }, }, 'future': { 'linear': { 'extends': 'forDerivatives', }, 'inverse': { 'extends': 'forDerivatives', }, }, }, 'timeframes': { '1m': 'M1', '3m': 'M3', '5m': 'M5', '15m': 'M15', '30m': 'M30', '1h': 'H1', '4h': 'H4', '1d': 'D1', '1w': 'D7', '1M': '1M', }, 'exceptions': { 'exact': { '429': errors.RateLimitExceeded, '500': errors.ExchangeError, '503': errors.ExchangeNotAvailable, '504': errors.ExchangeNotAvailable, '600': errors.PermissionDenied, '800': errors.ExchangeError, '1002': errors.AuthenticationError, '1003': errors.PermissionDenied, '1004': errors.AuthenticationError, '1005': errors.AuthenticationError, '2001': errors.BadSymbol, '2002': errors.BadRequest, '2003': errors.BadRequest, '2010': errors.BadRequest, '2011': errors.BadRequest, '2012': errors.BadRequest, '2020': errors.BadRequest, '2022': errors.BadRequest, '2024': errors.InvalidOrder, '10001': errors.BadRequest, '10021': errors.AccountSuspended, '10022': errors.BadRequest, '20001': errors.InsufficientFunds, '20002': errors.OrderNotFound, '20003': errors.ExchangeError, '20004': errors.ExchangeError, '20005': errors.ExchangeError, '20006': errors.ExchangeError, '20007': errors.ExchangeError, '20008': errors.InvalidOrder, '20009': errors.InvalidOrder, '20010': errors.OnMaintenance, '20011': errors.ExchangeError, '20012': errors.ExchangeError, '20014': errors.ExchangeError, '20016': errors.ExchangeError, '20018': errors.ExchangeError, '20031': errors.ExchangeError, '20032': errors.ExchangeError, '20033': errors.ExchangeError, '20034': errors.ExchangeError, '20040': errors.ExchangeError, '20041': errors.ExchangeError, '20042': errors.ExchangeError, '20043': errors.ExchangeError, '20044': errors.PermissionDenied, '20045': errors.InvalidOrder, '20047': errors.InvalidOrder, '20048': errors.InvalidOrder, '20049': errors.InvalidOrder, '20080': errors.ExchangeError, '21001': errors.ExchangeError, '21003': errors.AccountSuspended, '21004': errors.AccountSuspended, '22004': errors.ExchangeError, '22008': errors.ExchangeError, // Gateway timeout exceeded. }, 'broad': {}, }, 'options': { 'defaultNetwork': 'ERC20', 'defaultNetworks': { 'ETH': 'ETH', 'USDT': 'TRC20', }, 'networks': { // mainnet network ids are in lowercase for BTC & ETH 'BTC': 'btc', 'OMNI': 'BTC', 'ETH': 'eth', 'ERC20': 'ETH', 'ETC': 'ETC', 'BEP20': 'BSC', 'TRC20': 'TRX', // '': 'UGT', 'NEAR': 'NEAR', // '': 'LWF', 'DGB': 'DGB', // '': 'YOYOW', 'AE': 'AE', // 'BCHABC': 'BCHABC', // '': 'BCI', // 'BYTECOIN': 'bcn', 'AR': 'AR', // '': 'HPC', 'ADA': 'ADA', // 'BELDEX': 'BDX', // 'ARDOR': 'ARDR', // 'NEBLIO': 'NEBL', // '': 'DIM', 'CHZ': 'CHZ', // '': 'BET', // '': '8BT', 'ABBC': 'ABBC', // '': 'ABTC', // 'ACHAIN': 'ACT', // '': 'ADK', // '': 'AEON', 'ALGO': 'ALGO', // 'AMBROSUS': 'AMB', // '': 'APL', 'APT': 'APT', // '': 'ARK', // 'PIRATECHAIN': 'ARRR', // '': 'ASP', // '': 'ATB', 'ATOM': 'ATOM', 'AVAXC': 'AVAC', 'AVAXX': 'AVAX', // '': 'AYA', // '': 'B2G', // '': 'B2X', // '': 'BANANO', // '': 'BCCF', 'BSV': 'BCHSV', 'BEP2': 'BNB', // 'BOSON': 'BOS', // '': 'BRL', // brazilian real // '': 'BST', // 'BITCOINADDITION': 'BTCADD', // '': 'BTCP', // 'SUPERBTC': 'SBTC', // 'BITCOINVAULT': 'BTCV', // 'BITCOINGOLD': 'BTG', // 'BITCOINDIAMOND': 'BCD', // 'BITCONNECT': 'BCC', // '': 'BTM', // 'BITSHARES_OLD': 'BTS', // '': 'BTX', // '': 'BWI', 'CELO': 'CELO', // '': 'CENNZ', // '': 'CHX', 'CKB': 'CKB', // 'CALLISTO': 'CLO', // '': 'CLR', // '': 'CNX', // '': 'CRS', // '': 'CSOV', 'CTXC': 'CTXC', // '': 'CURE', // 'CONSTELLATION': 'DAG', // '': 'DAPS', 'DASH': 'DASH', // '': 'DBIX', 'DCR': 'DCR', // '': 'DCT', // '': 'DDR', // '': 'DNA', 'DOGE': 'doge', // 'POLKADOT': 'DOT', // '': 'NEWDOT', POLKADOT NEW // '': 'dsh', // '': 'ECA', // '': 'ECOIN', // '': 'EEX', 'EGLD': 'EGLD', // '': 'ELE', // 'ELECTRONEUM': 'Electroneum', // '': 'ELM', // '': 'EMC', 'EOS': 'EOS', // 'AERGO': 'ERG', 'ETHW': 'ETHW', // 'ETHERLITE': 'ETL', // '': 'ETP', // metaverse etp // '': 'EUNO', 'EVER': 'EVER', // '': 'EXP', // '': 'fcn', 'FET': 'FET', 'FIL': 'FIL', // '': 'FIRO', 'FLOW': 'FLOW', // '': 'G999', // '': 'GAME', // '': 'GASP', // '': 'GBX', // '': 'GHOST', // '': 'GLEEC', 'GLMR': 'GLMR', // '': 'GMD', // '': 'GRAPH', 'GRIN': 'GRIN', 'HBAR': 'HBAR', // '': 'HDG', 'HIVE': 'HIVE', // 'HARBOR': 'HRB', // '': 'HSR', // '': 'HTML', 'HYDRA': 'HYDRA', 'ICP': 'ICP', 'ICX': 'ICX', // '': 'IML', 'IOST': 'IOST', 'IOTA': 'IOTA', 'IOTX': 'IOTX', // '': 'IQ', 'KAVA': 'KAVA', 'KLAY': 'KIM', 'KOMODO': 'KMD', // '': 'KRM', 'KSM': 'KSM', // '': 'LAVA', // 'LITECOINCASH': 'LCC', 'LSK': 'LSK', // '': 'LOC', 'LTC': 'ltc', // '': 'LTNM', // 'TERRACLASSIC': 'LUNA', // 'TERRA': 'LUNANEW', // '': 'MAN', // '': 'MESH', 'MINA': 'MINA', // '': 'MNX', // 'MOBILECOIN': 'MOB', 'MOVR': 'MOVR', // '': 'MPK', // '': 'MRV', 'NANO': 'NANO', // '': 'NAV', 'NEO': 'NEO', // 'NIMIQ': 'NIM', // '': 'NJBC', // '': 'NKN', // '': 'NLC2', // '': 'NOF', // 'ENERGI': 'NRG', // '': 'nxt', // '': 'ODN', 'ONE': 'ONE', // 'ONTOLOGYGAS': 'ONG', 'ONT': 'ONT', 'OPTIMISM': 'OP', // '': 'PAD', // '': 'PART', // '': 'PBKX', // '': 'PLC', 'PLCU': 'PLCU', // '': 'PLI', // '': 'POA', 'MATIC': 'POLYGON', // '': 'PPC', // '': 'PQT', // '': 'PROC', // 'PASTEL': 'PSL', // '': 'qcn', 'QTUM': 'QTUM', // '': 'RCOIN', 'REI': 'REI', // '': 'RIF', // '': 'ROOTS', 'OASIS': 'ROSE', // '': 'RPX', // '': 'RUB', 'RVN': 'RVN', // '': 'SBD', 'SC': 'SC', 'SCRT': 'SCRT', // '': 'SLX', // 'SMARTMESH': 'SMART', // '': 'SMT', // '': 'SNM', 'SOL': 'SOL', // '': 'SRX', // '': 'STAK', 'STEEM': 'STEEM', // 'STRATIS': 'STRAT', // '': 'TCN', // '': 'TENT', 'THETA': 'Theta', // '': 'TIV', // '': 'TNC', // 'TON': 'TONCOIN', 'TRUE': 'TRUE', // '': 'TRY', // turkish lira // '': 'UNO', // '': 'USNOTA', // '': 'VEO', 'VET': 'VET', // '': 'VITAE', // 'VELAS': 'VLX', 'VSYS': 'VSYS', // '': 'VTC', 'WAVES': 'WAVES', 'WAX': 'WAX', // '': 'WEALTH', // 'WALTONCHAIN': 'WTC', // '': 'WTT', 'XCH': 'XCH', // '': 'XDC', // xinfin? // '': 'xdn', // '': 'XDNCO', // '': 'XDNICCO', 'XEC': 'XEC', 'NEM': 'XEM', // 'HAVEN': 'XHV', // '': 'XLC', 'XLM': 'XLM', // '': 'XMO', 'XMR': 'xmr', // 'MONEROCLASSIC': 'XMC', // '': 'XNS', // '': 'XPRM', // '': 'XRC', 'XRD': 'XRD', 'XRP': 'XRP', 'XTZ': 'XTZ', 'XVG': 'XVG', 'XYM': 'XYM', 'ZEC': 'ZEC', 'ZEN': 'ZEN', 'ZIL': 'ZIL', // '': 'ZYN', }, 'accountsByType': { 'spot': 'spot', 'funding': 'wallet', 'swap': 'derivatives', 'future': 'derivatives', }, 'withdraw': { 'includeFee': false, }, }, 'commonCurrencies': { 'AUTO': 'Cube', 'BCC': 'BCC', 'BDP': 'BidiPass', 'BET': 'DAO.Casino', 'BIT': 'BitRewards', 'BOX': 'BOX Token', 'CPT': 'Cryptaur', 'GET': 'Themis', 'GMT': 'GMT Token', 'HSR': 'HC', 'IQ': 'IQ.Cash', 'LNC': 'LinkerCoin', 'PLA': 'PlayChip', 'PNT': 'Penta', 'SBTC': 'Super Bitcoin', 'STEPN': 'GMT', 'STX': 'STOX', 'TV': 'Tokenville', 'XMT': 'MTL', 'XPNT': 'PNT', }, }); } nonce() { return this.milliseconds(); } /** * @method * @name hitbtc#fetchMarkets * @description retrieves data on all markets for hitbtc * @see https://api.hitbtc.com/#symbols * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object[]} an array of objects representing market data */ async fetchMarkets(params = {}) { const response = await this.publicGetPublicSymbol(params); // // { // "AAVEUSDT_PERP":{ // "type":"futures", // "expiry":null, // "underlying":"AAVE", // "base_currency":null, // "quote_currency":"USDT", // "quantity_increment":"0.01", // "tick_size":"0.001", // "take_rate":"0.0005", // "make_rate":"0.0002", // "fee_currency":"USDT", // "margin_trading":true, // "max_initial_leverage":"50.00" // }, // "MANAUSDT":{ // "type":"spot", // "base_currency":"MANA", // "quote_currency":"USDT", // "quantity_increment":"1", // "tick_size":"0.0000001", // "take_rate":"0.0025", // "make_rate":"0.001", // "fee_currency":"USDT", // "margin_trading":true, // "max_initial_leverage":"5.00" // }, // } // const result = []; const ids = Object.keys(response); for (let i = 0; i < ids.length; i++) { const id = ids[i]; if (id.endsWith('_BQX')) { continue; // seems like an invalid symbol and if we try to access it individually we get: {"timestamp":"2023-09-02T14:38:20.351Z","error":{"description":"Try get /public/symbol, to get list of all available symbols.","code":2001,"message":"No such symbol: EOSUSD_BQX"},"path":"/api/3/public/symbol/EOSUSD_BQX","requestId":"e1e9fce6-16374591"} } const market = this.safeValue(response, id); const marketType = this.safeString(market, 'type'); const expiry = this.safeInteger(market, 'expiry'); const contract = (marketType === 'futures'); const spot = (marketType === 'spot'); const marginTrading = this.safeBool(market, 'margin_trading', false); const margin = spot && marginTrading; const future = (expiry !== undefined); const swap = (contract && !future); const option = false; const baseId = this.safeString2(market, 'base_currency', 'underlying'); const quoteId = this.safeString(market, 'quote_currency'); const feeCurrencyId = this.safeString(market, 'fee_currency'); const base = this.safeCurrencyCode(baseId); const quote = this.safeCurrencyCode(quoteId); const feeCurrency = this.safeCurrencyCode(feeCurrencyId); let settleId = undefined; let settle = undefined; let symbol = base + '/' + quote; let type = 'spot'; let contractSize = undefined; let linear = undefined; let inverse = undefined; if (contract) { contractSize = this.parseNumber('1'); settleId = feeCurrencyId; settle = this.safeCurrencyCode(settleId); linear = ((quote !== undefined) && (quote === settle)); inverse = !linear; symbol = symbol + ':' + settle; if (future) { symbol = symbol + '-' + expiry; type = 'future'; } else { type = 'swap'; } } const lotString = this.safeString(market, 'quantity_increment'); const stepString = this.safeString(market, 'tick_size'); const lot = this.parseNumber(lotString); const step = this.parseNumber(stepString); result.push({ 'id': id, 'symbol': symbol, 'base': base, 'quote': quote, 'settle': settle, 'baseId': baseId, 'quoteId': quoteId, 'settleId': settleId, 'type': type, 'spot': spot, 'margin': margin, 'swap': swap, 'future': future, 'option': option, 'active': true, 'contract': contract, 'linear': linear, 'inverse': inverse, 'taker': this.safeNumber(market, 'take_rate'), 'maker': this.safeNumber(market, 'make_rate'), 'contractSize': contractSize, 'expiry': expiry, 'expiryDatetime': undefined, 'strike': undefined, 'optionType': undefined, 'feeCurrency': feeCurrency, 'precision': { 'amount': lot, 'price': step, }, 'limits': { 'leverage': { 'min': this.parseNumber('1'), 'max': this.safeNumber(market, 'max_initial_leverage', 1), }, 'amount': { 'min': lot, 'max': undefined, }, 'price': { 'min': step, 'max': undefined, }, 'cost': { 'min': this.parseNumber(Precise["default"].stringMul(lotString, stepString)), 'max': undefined, }, }, 'created': undefined, 'info': market, }); } return result; } /** * @method * @name hitbtc#fetchCurrencies * @description fetches all available currencies on an exchange * @see https://api.hitbtc.com/#currencies * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} an associative dictionary of currencies */ async fetchCurrencies(params = {}) { const response = await this.publicGetPublicCurrency(params); // // { // "WEALTH": { // "full_name": "ConnectWealth", // "payin_enabled": false, // "payout_enabled": false, // "transfer_enabled": true, // "precision_transfer": "0.001", // "networks": [ // { // "network": "ETH", // "protocol": "ERC20", // "default": true, // "payin_enabled": false, // "payout_enabled": false, // "precision_payout": "0.001", // "payout_fee": "0.016800000000", // "payout_is_payment_id": false, // "payin_payment_id": false, // "payin_confirmations": "2" // } // ] // } // } // const result = {}; const currencies = Object.keys(response); for (let i = 0; i < currencies.length; i++) { const currencyId = currencies[i]; const code = this.safeCurrencyCode(currencyId); const entry = response[currencyId]; const name = this.safeString(entry, 'full_name'); const precision = this.safeNumber(entry, 'precision_transfer'); const payinEnabled = this.safeBool(entry, 'payin_enabled', false); const payoutEnabled = this.safeBool(entry, 'payout_enabled', false); const transferEnabled = this.safeBool(entry, 'transfer_enabled', false); const active = payinEnabled && payoutEnabled && transferEnabled; const rawNetworks = this.safeValue(entry, 'networks', []); const networks = {}; let fee = undefined; let depositEnabled = undefined; let withdrawEnabled = undefined; for (let j = 0; j < rawNetworks.length; j++) { const rawNetwork = rawNetworks[j]; const networkId = this.safeString2(rawNetwork, 'protocol', 'network'); let networkCode = this.networkIdToCode(networkId); networkCode = (networkCode !== undefined) ? networkCode.toUpperCase() : undefined; fee = this.safeNumber(rawNetwork, 'payout_fee'); const networkPrecision = this.safeNumber(rawNetwork, 'precision_payout'); const payinEnabledNetwork = this.safeBool(rawNetwork, 'payin_enabled', false); const payoutEnabledNetwork = this.safeBool(rawNetwork, 'payout_enabled', false); const activeNetwork = payinEnabledNetwork && payoutEnabledNetwork; if (payinEnabledNetwork && !depositEnabled) { depositEnabled = true; } else if (!payinEnabledNetwork) { depositEnabled = false; } if (payoutEnabledNetwork && !withdrawEnabled) { withdrawEnabled = true; } else if (!payoutEnabledNetwork) { withdrawEnabled = false; } networks[networkCode] = { 'info': rawNetwork, 'id': networkId, 'network': networkCode, 'fee': fee, 'active': activeNetwork, 'deposit': payinEnabledNetwork, 'withdraw': payoutEnabledNetwork, 'precision': networkPrecision, 'limits': { 'withdraw': { 'min': undefined, 'max': undefined, }, }, }; } const networksKeys = Object.keys(networks); const networksLength = networksKeys.length; result[code] = { 'info': entry, 'code': code, 'id': currencyId, 'precision': precision, 'name': name, 'active': active, 'deposit': depositEnabled, 'withdraw': withdrawEnabled, 'networks': networks, 'fee': (networksLength <= 1) ? fee : undefined, 'limits': { 'amount': { 'min': undefined, 'max': undefined, }, }, }; } return result; } /** * @method * @name hitbtc#createDepositAddress * @description create a currency deposit address * @see https://api.hitbtc.com/#generate-deposit-crypto-address * @param {string} code unified currency code of the currency for the deposit address * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} an [address structure]{@link https://docs.ccxt.com/#/?id=address-structure} */ async createDepositAddress(code, params = {}) { await this.loadMarkets(); const currency = this.currency(code); const request = { 'currency': currency['id'], }; const network = this.safeStringUpper(params, 'network'); if ((network !== undefined) && (code === 'USDT')) { const networks = this.safeValue(this.options, 'networks'); const parsedNetwork = this.safeString(networks, network); if (parsedNetwork !== undefined) { request['currency'] = parsedNetwork; } params = this.omit(params, 'network'); } const response = await this.privatePostWalletCryptoAddress(this.extend(request, params)); // // {"currency":"ETH","address":"0xd0d9aea60c41988c3e68417e2616065617b7afd3"} // const currencyId = this.safeString(response, 'currency'); return { 'currency': this.safeCurrencyCode(currencyId), 'address': this.safeString(response, 'address'), 'tag': this.safeString(response, 'payment_id'), 'network': undefined, 'info': response, }; } /** * @method * @name hitbtc#fetchDepositAddress * @description fetch the deposit address for a currency associated with this account * @see https://api.hitbtc.com/#get-deposit-crypto-address * @param {string} code unified currency code * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} an [address structure]{@link https://docs.ccxt.com/#/?id=address-structure} */ async fetchDepositAddress(code, params = {}) { await this.loadMarkets(); const currency = this.currency(code); const request = { 'currency': currency['id'], }; const network = this.safeStringUpper(params, 'network'); if ((network !== undefined) && (code === 'USDT')) { const networks = this.safeValue(this.options, 'networks'); const parsedNetwork = this.safeString(networks, network); if (parsedNetwork !== undefined) { request['currency'] = parsedNetwork; } params = this.omit(params, 'network'); } const response = await this.privateGetWalletCryptoAddress(this.extend(request, params)); // // [{"currency":"ETH","address":"0xd0d9aea60c41988c3e68417e2616065617b7afd3"}] // const firstAddress = this.safeValue(response, 0); const address = this.safeString(firstAddress, 'address'); const currencyId = this.safeString(firstAddress, 'currency'); const tag = this.safeString(firstAddress, 'payment_id'); const parsedCode = this.safeCurrencyCode(currencyId); return { 'info': response, 'currency': parsedCode, 'network': undefined, 'address': address, 'tag': tag, }; } parseBalance(response) { const result = { 'info': response }; for (let i = 0; i < response.length; i++) { const entry = response[i]; const currencyId = this.safeString(entry, 'currency'); const code = this.safeCurrencyCode(currencyId); const account = this.account(); account['free'] = this.safeString(entry, 'available'); account['used'] = this.safeString(entry, 'reserved'); result[code] = account; } return this.safeBalance(result); } /** * @method * @name hitbtc#fetchBalance * @description query for balance and get the amount of funds available for trading or funds locked in orders * @see https://api.hitbtc.com/#wallet-balance * @see https://api.hitbtc.com/#get-spot-trading-balance * @see https://api.hitbtc.com/#get-trading-balance * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a [balance structure]{@link https://docs.ccxt.com/#/?id=balance-structure} */ async fetchBalance(params = {}) { const type = this.safeStringLower(params, 'type', 'spot'); params = this.omit(params, ['type']); const accountsByType = this.safeValue(this.options, 'accountsByType', {}); const account = this.safeString(accountsByType, type, type); let response = undefined; if (account === 'wallet') { response = await this.privateGetWalletBalance(params); } else if (account === 'spot') { response = await this.privateGetSpotBalance(params); } else if (account === 'derivatives') { response = await this.privateGetFuturesBalance(params); } else { const keys = Object.keys(accountsByType); throw new errors.BadRequest(this.id + ' fetchBalance() type parameter must be one of ' + keys.join(', ')); } // // [ // { // "currency": "PAXG", // "available": "0", // "reserved": "0", // "reserved_margin": "0", // }, // ... // ] // return this.parseBalance(response); } /** * @method * @name hitbtc#fetchTicker * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market * @see https://api.hitbtc.com/#tickers * @param {string} symbol unified symbol of the market to fetch the ticker for * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure} */ async fetchTicker(symbol, params = {}) { await this.loadMarkets(); const market = this.market(symbol); const request = { 'symbol': market['id'], }; const response = await this.publicGetPublicTickerSymbol(this.extend(request, params)); // // { // "ask": "0.020572", // "bid": "0.020566", // "last": "0.020574", // "low": "0.020388", // "high": "0.021084", // "open": "0.020913", // "volume": "138444.3666", // "volume_quote": "2853.6874972480", // "timestamp": "2021-06-02T17:52:36.731Z" // } // return this.p