UNPKG

sfccxt

Version:

A JavaScript / Python / PHP cryptocurrency trading library with support for 130+ exchanges

1,223 lines (1,203 loc) 192 kB
'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, BadRequest, BadSymbol, RateLimitExceeded, InsufficientFunds, OrderNotFound, InvalidOrder, AuthenticationError, PermissionDenied, ExchangeNotAvailable, RequestTimeout } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- module.exports = class coinex extends Exchange { describe () { return this.deepExtend (super.describe (), { 'id': 'coinex', 'name': 'CoinEx', 'version': 'v1', 'countries': [ 'CN' ], // IP ratelimit is 400 requests per second // rateLimit = 1000ms / 400 = 2.5 // 200 per 2 seconds => 100 per second => weight = 4 // 120 per 2 seconds => 60 per second => weight = 6.667 // 80 per 2 seconds => 40 per second => weight = 10 // 60 per 2 seconds => 30 per second => weight = 13.334 // 40 per 2 seconds => 20 per second => weight = 20 // 20 per 2 seconds => 10 per second => weight = 40 'rateLimit': 2.5, 'pro': true, 'has': { 'CORS': undefined, 'spot': true, 'margin': true, 'swap': true, 'future': false, 'option': false, 'addMargin': true, 'borrowMargin': true, 'cancelAllOrders': true, 'cancelOrder': true, 'createDepositAddress': true, 'createOrder': true, 'createReduceOnlyOrder': true, 'fetchBalance': true, 'fetchBorrowInterest': true, 'fetchBorrowRate': true, 'fetchBorrowRateHistories': false, 'fetchBorrowRateHistory': false, 'fetchBorrowRates': true, 'fetchClosedOrders': true, 'fetchCurrencies': true, 'fetchDepositAddress': true, 'fetchDepositAddressByNetwork': false, 'fetchDepositAddresses': false, 'fetchDeposits': true, 'fetchFundingHistory': true, 'fetchFundingRate': true, 'fetchFundingRateHistory': true, 'fetchFundingRates': false, 'fetchIndexOHLCV': false, 'fetchLeverage': false, 'fetchLeverageTiers': true, 'fetchMarketLeverageTiers': 'emulated', 'fetchMarkets': true, 'fetchMarkOHLCV': false, 'fetchMyTrades': true, 'fetchOHLCV': true, 'fetchOpenOrders': true, 'fetchOrder': true, 'fetchOrderBook': true, 'fetchPosition': true, 'fetchPositions': true, 'fetchPositionsRisk': false, 'fetchPremiumIndexOHLCV': false, 'fetchTicker': true, 'fetchTickers': true, 'fetchTime': true, 'fetchTrades': true, 'fetchTradingFee': true, 'fetchTradingFees': true, 'fetchTransactionFee:': false, 'fetchTransactoinFees': false, 'fetchTransfer': false, 'fetchTransfers': true, 'fetchWithdrawal': false, 'fetchWithdrawals': true, 'reduceMargin': true, 'repayMargin': true, 'setLeverage': true, 'setMarginMode': true, 'setPositionMode': false, 'transfer': true, 'withdraw': true, }, 'timeframes': { '1m': '1min', '3m': '3min', '5m': '5min', '15m': '15min', '30m': '30min', '1h': '1hour', '2h': '2hour', '4h': '4hour', '6h': '6hour', '12h': '12hour', '1d': '1day', '3d': '3day', '1w': '1week', }, 'urls': { 'logo': 'https://user-images.githubusercontent.com/51840849/87182089-1e05fa00-c2ec-11ea-8da9-cc73b45abbbc.jpg', 'api': { 'public': 'https://api.coinex.com', 'private': 'https://api.coinex.com', 'perpetualPublic': 'https://api.coinex.com/perpetual', 'perpetualPrivate': 'https://api.coinex.com/perpetual', }, 'www': 'https://www.coinex.com', 'doc': 'https://github.com/coinexcom/coinex_exchange_api/wiki', 'fees': 'https://www.coinex.com/fees', 'referral': 'https://www.coinex.com/register?refer_code=yw5fz', }, 'api': { 'public': { 'get': { 'amm/market': 1, 'common/currency/rate': 1, 'common/asset/config': 1, 'common/maintain/info': 1, 'common/temp-maintain/info': 1, 'margin/market': 1, 'market/info': 1, 'market/list': 1, 'market/ticker': 1, 'market/ticker/all': 1, 'market/depth': 1, 'market/deals': 1, 'market/kline': 1, 'market/detail': 1, }, }, 'private': { 'get': { 'account/amm/balance': 40, 'account/investment/balance': 40, 'account/balance/history': 40, 'account/market/fee': 40, 'balance/coin/deposit': 40, 'balance/coin/withdraw': 40, 'balance/info': 40, 'balance/deposit/address/{coin_type}': 40, 'contract/transfer/history': 40, 'credit/info': 40, 'credit/balance': 40, 'investment/transfer/history': 40, 'margin/account': 1, 'margin/config': 1, 'margin/loan/history': 40, 'margin/transfer/history': 40, 'order/deals': 40, 'order/finished': 40, 'order/pending': 4, 'order/status': 4, 'order/status/batch': 4, 'order/user/deals': 40, 'order/stop/finished': 40, 'order/stop/pending': 4, 'order/user/trade/fee': 1, 'order/market/trade/info': 1, 'sub_account/balance': 1, 'sub_account/transfer/history': 40, 'sub_account/auth/api/{user_auth_id}': 40, }, 'post': { 'balance/coin/withdraw': 40, 'contract/balance/transfer': 40, 'margin/flat': 40, 'margin/loan': 40, 'margin/transfer': 40, 'order/limit/batch': 13.334, 'order/ioc': 6.667, 'order/limit': 6.667, 'order/market': 6.667, 'order/modify': 6.667, 'order/stop/limit': 6.667, 'order/stop/market': 6.667, 'order/stop/modify': 6.667, 'sub_account/transfer': 40, 'sub_account/register': 1, 'sub_account/unfrozen': 40, 'sub_account/frozen': 40, 'sub_account/auth/api': 40, }, 'put': { 'balance/deposit/address/{coin_type}': 40, 'sub_account/auth/api/{user_auth_id}': 40, 'v1/account/settings': 40, }, 'delete': { 'balance/coin/withdraw': 40, 'order/pending/batch': 13.334, 'order/pending': 6.667, 'order/stop/pending': 13.334, 'order/stop/pending/{id}': 13.334, 'sub_account/auth/api/{user_auth_id}': 40, }, }, 'perpetualPublic': { 'get': { 'ping': 1, 'time': 1, 'market/list': 1, 'market/limit_config': 1, 'market/ticker': 1, 'market/ticker/all': 1, 'market/depth': 1, 'market/deals': 1, 'market/funding_history': 1, 'market/user_deals': 1, 'market/kline': 1, }, }, 'perpetualPrivate': { 'get': { 'asset/query': 40, 'order/pending': 4, 'order/finished': 40, 'order/stop_finished': 40, 'order/stop_pending': 4, 'order/status': 4, 'order/stop_status': 4, 'position/pending': 40, 'position/funding': 40, }, 'post': { 'market/adjust_leverage': 1, 'market/position_expect': 1, 'order/put_limit': 10, 'order/put_market': 10, 'order/put_stop_limit': 10, 'order/put_stop_market': 10, 'order/modify': 10, 'order/modify_stop': 10, 'order/cancel': 10, 'order/cancel_all': 20, 'order/cancel_batch': 20, 'order/cancel_stop': 10, 'order/cancel_stop_all': 20, 'order/close_limit': 10, 'order/close_market': 10, 'position/adjust_margin': 10, 'position/stop_loss': 10, 'position/take_profit': 10, 'position/market_close': 10, }, }, }, 'fees': { 'trading': { 'maker': 0.001, 'taker': 0.001, }, 'funding': { 'withdraw': { 'BCH': 0.0, 'BTC': 0.001, 'LTC': 0.001, 'ETH': 0.001, 'ZEC': 0.0001, 'DASH': 0.0001, }, }, }, 'limits': { 'amount': { 'min': 0.001, 'max': undefined, }, }, 'options': { 'createMarketBuyOrderRequiresPrice': true, 'defaultType': 'spot', // spot, swap, margin 'defaultSubType': 'linear', // linear, inverse 'fetchDepositAddress': { 'fillResponseFromRequest': true, }, 'accountsById': { 'spot': '0', }, }, 'commonCurrencies': { 'ACM': 'Actinium', }, 'precisionMode': TICK_SIZE, }); } async fetchCurrencies (params = {}) { const response = await this.publicGetCommonAssetConfig (params); // { // code: 0, // data: { // "USDT-ERC20": { // "asset": "USDT", // "chain": "ERC20", // "withdrawal_precision": 6, // "can_deposit": true, // "can_withdraw": true, // "deposit_least_amount": "4.9", // "withdraw_least_amount": "4.9", // "withdraw_tx_fee": "4.9" // }, // ... // }, // message: 'Success', // } // const data = this.safeValue (response, 'data', []); const coins = Object.keys (data); const result = {}; for (let i = 0; i < coins.length; i++) { const coin = coins[i]; const currency = data[coin]; const currencyId = this.safeString (currency, 'asset'); const networkId = this.safeString (currency, 'chain'); const code = this.safeCurrencyCode (currencyId); const precision = this.parseNumber (this.parsePrecision (this.safeString (currency, 'withdrawal_precision'))); if (this.safeValue (result, code) === undefined) { result[code] = { 'id': currencyId, 'numericId': undefined, 'code': code, 'info': currency, 'name': undefined, 'active': true, 'deposit': this.safeValue (currency, 'can_deposit'), 'withdraw': this.safeValue (currency, 'can_withdraw'), 'fee': this.safeNumber (currency, 'withdraw_tx_fee'), 'precision': precision, 'limits': { 'amount': { 'min': undefined, 'max': undefined, }, 'deposit': { 'min': this.safeNumber (currency, 'deposit_least_amount'), 'max': undefined, }, 'withdraw': { 'min': this.safeNumber (currency, 'withdraw_least_amount'), 'max': undefined, }, }, }; } const networks = this.safeValue (result[code], 'networks', {}); const network = { 'info': currency, 'id': networkId, 'network': networkId, 'name': undefined, 'limits': { 'amount': { 'min': undefined, 'max': undefined, }, 'deposit': { 'min': this.safeNumber (currency, 'deposit_least_amount'), 'max': undefined, }, 'withdraw': { 'min': this.safeNumber (currency, 'withdraw_least_amount'), 'max': undefined, }, }, 'active': true, 'deposit': this.safeValue (currency, 'can_deposit'), 'withdraw': this.safeValue (currency, 'can_withdraw'), 'fee': this.safeNumber (currency, 'withdraw_tx_fee'), 'precision': precision, }; networks[networkId] = network; result[code]['networks'] = networks; } return result; } async fetchMarkets (params = {}) { /** * @method * @name coinex#fetchMarkets * @description retrieves data on all markets for coinex * @param {object} params extra parameters specific to the exchange api endpoint * @returns {[object]} an array of objects representing market data */ let result = []; const [ type, query ] = this.handleMarketTypeAndParams ('fetchMarkets', undefined, params); if (type === 'spot' || type === 'margin') { result = await this.fetchSpotMarkets (query); } else if (type === 'swap') { result = await this.fetchContractMarkets (query); } else { throw new ExchangeError (this.id + " does not support the '" + type + "' market type, set exchange.options['defaultType'] to 'spot', 'margin' or 'swap'"); } return result; } async fetchSpotMarkets (params) { const response = await this.publicGetMarketInfo (params); // // { // "code": 0, // "data": { // "WAVESBTC": { // "name": "WAVESBTC", // "min_amount": "1", // "maker_fee_rate": "0.001", // "taker_fee_rate": "0.001", // "pricing_name": "BTC", // "pricing_decimal": 8, // "trading_name": "WAVES", // "trading_decimal": 8 // } // } // } // const markets = this.safeValue (response, 'data', {}); const result = []; const keys = Object.keys (markets); for (let i = 0; i < keys.length; i++) { const key = keys[i]; const market = markets[key]; const id = this.safeString (market, 'name'); const tradingName = this.safeString (market, 'trading_name'); const baseId = tradingName; const quoteId = this.safeString (market, 'pricing_name'); const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); let symbol = base + '/' + quote; if (tradingName === id) { symbol = id; } result.push ({ 'id': id, 'symbol': symbol, 'base': base, 'quote': quote, 'settle': undefined, 'baseId': baseId, 'quoteId': quoteId, 'settleId': undefined, 'type': 'spot', 'spot': true, 'margin': undefined, 'swap': false, 'future': false, 'option': false, 'active': undefined, 'contract': false, 'linear': undefined, 'inverse': undefined, 'taker': this.safeNumber (market, 'taker_fee_rate'), 'maker': this.safeNumber (market, 'maker_fee_rate'), 'contractSize': undefined, 'expiry': undefined, 'expiryDatetime': undefined, 'strike': undefined, 'optionType': undefined, 'precision': { 'amount': this.parseNumber (this.parsePrecision (this.safeString (market, 'trading_decimal'))), 'price': this.parseNumber (this.parsePrecision (this.safeString (market, 'pricing_decimal'))), }, 'limits': { 'leverage': { 'min': undefined, 'max': undefined, }, 'amount': { 'min': this.safeNumber (market, 'min_amount'), 'max': undefined, }, 'price': { 'min': undefined, 'max': undefined, }, 'cost': { 'min': undefined, 'max': undefined, }, }, 'info': market, }); } return result; } async fetchContractMarkets (params) { const response = await this.perpetualPublicGetMarketList (params); // // { // "code": 0, // "data": [ // { // "name": "BTCUSD", // "type": 2, // 1: USDT-M Contracts, 2: Coin-M Contracts // "leverages": ["3", "5", "8", "10", "15", "20", "30", "50", "100"], // "stock": "BTC", // "money": "USD", // "fee_prec": 5, // "stock_prec": 8, // "money_prec": 1, // "amount_prec": 0, // "amount_min": "10", // "multiplier": "1", // "tick_size": "0.1", // Min. Price Increment // "available": true // }, // ], // "message": "OK" // } // const markets = this.safeValue (response, 'data', []); const result = []; for (let i = 0; i < markets.length; i++) { const entry = markets[i]; const fees = this.fees; const leverages = this.safeValue (entry, 'leverages', []); const subType = this.safeInteger (entry, 'type'); const linear = (subType === 1) ? true : false; const inverse = (subType === 2) ? true : false; const id = this.safeString (entry, 'name'); const baseId = this.safeString (entry, 'stock'); const quoteId = this.safeString (entry, 'money'); const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const settleId = (subType === 1) ? 'USDT' : baseId; const settle = this.safeCurrencyCode (settleId); const symbol = base + '/' + quote + ':' + settle; result.push ({ 'id': id, 'symbol': symbol, 'base': base, 'quote': quote, 'settle': settle, 'baseId': baseId, 'quoteId': quoteId, 'settleId': settleId, 'type': 'swap', 'spot': false, 'margin': false, 'swap': true, 'future': false, 'option': false, 'active': this.safeValue (entry, 'available'), 'contract': true, 'linear': linear, 'inverse': inverse, 'taker': fees['trading']['taker'], 'maker': fees['trading']['maker'], 'contractSize': undefined, 'expiry': undefined, 'expiryDatetime': undefined, 'strike': undefined, 'optionType': undefined, 'precision': { 'amount': this.parseNumber (this.parsePrecision (this.safeString (entry, 'stock_prec'))), 'price': this.parseNumber (this.parsePrecision (this.safeString (entry, 'money_prec'))), }, 'limits': { 'leverage': { 'min': this.safeString (leverages, 0), 'max': this.safeString (leverages, leverages.length - 1), }, 'amount': { 'min': this.safeString (entry, 'amount_min'), 'max': undefined, }, 'price': { 'min': undefined, 'max': undefined, }, 'cost': { 'min': undefined, 'max': undefined, }, }, 'info': entry, }); } return result; } parseTicker (ticker, market = undefined) { // // Spot fetchTicker, fetchTickers // // { // "vol": "293.19415130", // "low": "38200.00", // "open": "39514.99", // "high": "39530.00", // "last": "38649.57", // "buy": "38640.20", // "buy_amount": "0.22800000", // "sell": "38640.21", // "sell_amount": "0.02828439" // } // // Swap fetchTicker, fetchTickers // // { // "vol": "7714.2175", // "low": "38200.00", // "open": "39569.23", // "high": "39569.23", // "last": "38681.37", // "buy": "38681.36", // "period": 86400, // "funding_time": 462, // "position_amount": "296.7552", // "funding_rate_last": "0.00009395", // "funding_rate_next": "0.00000649", // "funding_rate_predict": "-0.00007176", // "insurance": "16464465.09431942163278132918", // "sign_price": "38681.93", // "index_price": "38681.69500000", // "sell_total": "16.6039", // "buy_total": "19.8481", // "buy_amount": "4.6315", // "sell": "38681.37", // "sell_amount": "11.4044" // } // const timestamp = this.safeInteger (ticker, 'date'); const symbol = this.safeSymbol (undefined, market); ticker = this.safeValue (ticker, 'ticker', {}); const last = this.safeString (ticker, 'last'); return this.safeTicker ({ 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': this.safeString (ticker, 'high'), 'low': this.safeString (ticker, 'low'), 'bid': this.safeString (ticker, 'buy'), 'bidVolume': undefined, 'ask': this.safeString (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': this.safeString (ticker, 'open'), 'close': last, 'last': last, 'previousClose': undefined, 'change': undefined, 'percentage': undefined, 'average': undefined, 'baseVolume': this.safeString2 (ticker, 'vol', 'volume'), 'quoteVolume': undefined, 'info': ticker, }, market); } async fetchTicker (symbol, params = {}) { /** * @method * @name coinex#fetchTicker * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market * @param {string} symbol unified symbol of the market to fetch the ticker for * @param {object} params extra parameters specific to the coinex api endpoint * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/en/latest/manual.html#ticker-structure} */ await this.loadMarkets (); const market = this.market (symbol); const request = { 'market': market['id'], }; const method = market['swap'] ? 'perpetualPublicGetMarketTicker' : 'publicGetMarketTicker'; const response = await this[method] (this.extend (request, params)); // // Spot // // { // "code": 0, // "data": { // "date": 1651306913414, // "ticker": { // "vol": "293.19415130", // "low": "38200.00", // "open": "39514.99", // "high": "39530.00", // "last": "38649.57", // "buy": "38640.20", // "buy_amount": "0.22800000", // "sell": "38640.21", // "sell_amount": "0.02828439" // } // }, // "message": "OK" // } // // Swap // // { // "code": 0, // "data": { // "date": 1651306641500, // "ticker": { // "vol": "7714.2175", // "low": "38200.00", // "open": "39569.23", // "high": "39569.23", // "last": "38681.37", // "buy": "38681.36", // "period": 86400, // "funding_time": 462, // "position_amount": "296.7552", // "funding_rate_last": "0.00009395", // "funding_rate_next": "0.00000649", // "funding_rate_predict": "-0.00007176", // "insurance": "16464465.09431942163278132918", // "sign_price": "38681.93", // "index_price": "38681.69500000", // "sell_total": "16.6039", // "buy_total": "19.8481", // "buy_amount": "4.6315", // "sell": "38681.37", // "sell_amount": "11.4044" // } // }, // "message": "OK" // } // return this.parseTicker (response['data'], market); } async fetchTickers (symbols = undefined, params = {}) { /** * @method * @name coinex#fetchTickers * @description fetches price tickers for multiple markets, statistical calculations with the information calculated over the past 24 hours each market * @see https://viabtc.github.io/coinex_api_en_doc/spot/#docsspot001_market008_all_market_ticker * @see https://viabtc.github.io/coinex_api_en_doc/futures/#docsfutures001_http009_market_ticker_all * @param {[string]|undefined} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned * @param {object} params extra parameters specific to the coinex api endpoint * @returns {object} an array of [ticker structures]{@link https://docs.ccxt.com/en/latest/manual.html#ticker-structure} */ await this.loadMarkets (); symbols = this.marketSymbols (symbols); let market = undefined; if (symbols !== undefined) { const symbol = this.safeValue (symbols, 0); market = this.market (symbol); } const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchTickers', market, params); const method = (marketType === 'swap') ? 'perpetualPublicGetMarketTickerAll' : 'publicGetMarketTickerAll'; const response = await this[method] (query); // // Spot // // { // "code": 0, // "data": { // "date": 1651519857284, // "ticker": { // "PSPUSDT": { // "vol": "127131.55227034", // "low": "0.0669", // "open": "0.0688", // "high": "0.0747", // "last": "0.0685", // "buy": "0.0676", // "buy_amount": "702.70117866", // "sell": "0.0690", // "sell_amount": "686.76861562" // }, // } // }, // "message": "Ok" // } // // Swap // // { // "code": 0, // "data": { // "date": 1651520268644, // "ticker": { // "KAVAUSDT": { // "vol": "834924", // "low": "3.9418", // "open": "4.1834", // "high": "4.4328", // "last": "4.0516", // "buy": "4.0443", // "period": 86400, // "funding_time": 262, // "position_amount": "16111", // "funding_rate_last": "-0.00069514", // "funding_rate_next": "-0.00061009", // "funding_rate_predict": "-0.00055812", // "insurance": "16532425.53026084124483989548", // "sign_price": "4.0516", // "index_price": "4.0530", // "sell_total": "59446", // "buy_total": "62423", // "buy_amount": "959", // "sell": "4.0466", // "sell_amount": "141" // }, // } // }, // "message": "Ok" // } // const data = this.safeValue (response, 'data'); const timestamp = this.safeInteger (data, 'date'); const tickers = this.safeValue (data, 'ticker', {}); const marketIds = Object.keys (tickers); const result = {}; for (let i = 0; i < marketIds.length; i++) { const marketId = marketIds[i]; const market = this.safeMarket (marketId); const symbol = market['symbol']; const ticker = this.parseTicker ({ 'date': timestamp, 'ticker': tickers[marketId], }, market); ticker['symbol'] = symbol; result[symbol] = ticker; } return this.filterByArray (result, 'symbol', symbols); } async fetchTime (params = {}) { /** * @method * @name coinex#fetchTime * @description fetches the current integer timestamp in milliseconds from the exchange server * @param {object} params extra parameters specific to the coinex api endpoint * @returns {int} the current integer timestamp in milliseconds from the exchange server */ const response = await this.perpetualPublicGetTime (params); // // { // code: '0', // data: '1653261274414', // message: 'OK' // } // return this.safeNumber (response, 'data'); } async fetchOrderBook (symbol, limit = 20, params = {}) { /** * @method * @name coinex#fetchOrderBook * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data * @param {string} symbol unified symbol of the market to fetch the order book for * @param {int|undefined} limit the maximum amount of order book entries to return * @param {object} params extra parameters specific to the coinex api endpoint * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-book-structure} indexed by market symbols */ if (symbol === undefined) { throw new ArgumentsRequired (this.id + ' fetchOrderBook() requires a symbol argument'); } await this.loadMarkets (); const market = this.market (symbol); if (limit === undefined) { limit = 20; // default } const request = { 'market': this.marketId (symbol), 'merge': '0', 'limit': limit.toString (), }; const method = market['swap'] ? 'perpetualPublicGetMarketDepth' : 'publicGetMarketDepth'; const response = await this[method] (this.extend (request, params)); // // Spot // // { // "code": 0, // "data": { // "asks": [ // ["41056.33", "0.31727613"], // ["41056.34", "1.05657294"], // ["41056.35", "0.02346648"] // ], // "bids": [ // ["41050.61", "0.40618608"], // ["41046.98", "0.13800000"], // ["41046.56", "0.22579234"] // ], // "last": "41050.61", // "time": 1650573220346 // }, // "message": "OK" // } // // Swap // // { // "code": 0, // "data": { // "asks": [ // ["40620.90", "0.0384"], // ["40625.50", "0.0219"], // ["40625.90", "0.3506"] // ], // "bids": [ // ["40620.89", "19.6861"], // ["40620.80", "0.0012"], // ["40619.87", "0.0365"] // ], // "last": "40620.89", // "time": 1650587672406, // "sign_price": "40619.32", // "index_price": "40609.93" // }, // "message": "OK" // } // const result = this.safeValue (response, 'data', {}); const timestamp = this.safeInteger (result, 'time'); return this.parseOrderBook (result, symbol, timestamp); } parseTrade (trade, market = undefined) { // // Spot and Swap fetchTrades (public) // // { // "id": 2611511379, // "type": "buy", // "price": "192.63", // "amount": "0.02266931", // "date": 1638990110, // "date_ms": 1638990110518 // }, // // Spot and Margin fetchMyTrades (private) // // { // "id": 2611520950, // "order_id": 63286573298, // "account_id": 0, // "create_time": 1638990636, // "type": "sell", // "role": "taker", // "price": "192.29", // "amount": "0.098", // "fee": "0.03768884", // "fee_asset": "USDT", // "market": "AAVEUSDT", // "deal_money": "18.84442" // } // // Swap fetchMyTrades (private) // // { // "amount": "0.0012", // "deal_fee": "0.0237528", // "deal_insurance": "0", // "deal_margin": "15.8352", // "deal_order_id": 17797031903, // "deal_profit": "0", // "deal_stock": "47.5056", // "deal_type": 1, // "deal_user_id": 2969195, // "fee_asset": "", // "fee_discount": "0", // "fee_price": "0", // "fee_rate": "0.0005", // "fee_real_rate": "0.0005", // "id": 379044296, // "leverage": "3", // "margin_amount": "15.8352", // "market": "BTCUSDT", // "open_price": "39588", // "order_id": 17797092987, // "position_amount": "0.0012", // "position_id": 62052321, // "position_type": 1, // "price": "39588", // "role": 2, // "side": 2, // "time": 1650675936.016103, // "user_id": 3620173 // } // let timestamp = this.safeTimestamp2 (trade, 'create_time', 'time'); if (timestamp === undefined) { timestamp = this.safeInteger (trade, 'date_ms'); } const tradeId = this.safeString (trade, 'id'); const orderId = this.safeString (trade, 'order_id'); const priceString = this.safeString (trade, 'price'); const amountString = this.safeString (trade, 'amount'); const marketId = this.safeString (trade, 'market'); market = this.safeMarket (marketId, market); const symbol = this.safeSymbol (marketId, market); const costString = this.safeString (trade, 'deal_money'); let fee = undefined; const feeCostString = this.safeString2 (trade, 'fee', 'deal_fee'); if (feeCostString !== undefined) { const feeCurrencyId = this.safeString (trade, 'fee_asset'); const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId); fee = { 'cost': feeCostString, 'currency': feeCurrencyCode, }; } let takerOrMaker = this.safeString (trade, 'role'); if (takerOrMaker === '1') { takerOrMaker = 'maker'; } else if (takerOrMaker === '2') { takerOrMaker = 'taker'; } let side = undefined; if (market['type'] === 'swap') { side = this.safeInteger (trade, 'side'); if (side === 1) { side = 'sell'; } else if (side === 2) { side = 'buy'; } if (side === undefined) { side = this.safeString (trade, 'type'); } } else { side = this.safeString (trade, 'type'); } return this.safeTrade ({ 'info': trade, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'symbol': symbol, 'id': tradeId, 'order': orderId, 'type': undefined, 'side': side, 'takerOrMaker': takerOrMaker, 'price': priceString, 'amount': amountString, 'cost': costString, 'fee': fee, }, market); } async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { /** * @method * @name coinex#fetchTrades * @description get the list of most recent trades for a particular symbol * @param {string} symbol unified symbol of the market to fetch trades for * @param {int|undefined} since timestamp in ms of the earliest trade to fetch * @param {int|undefined} limit the maximum amount of trades to fetch * @param {object} params extra parameters specific to the coinex api endpoint * @returns {[object]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades} */ await this.loadMarkets (); const market = this.market (symbol); const request = { 'market': market['id'], // 'last_id': 0, }; if (limit !== undefined) { request['limit'] = limit; } const method = market['swap'] ? 'perpetualPublicGetMarketDeals' : 'publicGetMarketDeals'; const response = await this[method] (this.extend (request, params)); // // Spot and Swap // // { // "code": 0, // "data": [ // { // "id": 2611511379, // "type": "buy", // "price": "192.63", // "amount": "0.02266931", // "date": 1638990110, // "date_ms": 1638990110518 // }, // ], // "message": "OK" // } // return this.parseTrades (response['data'], market, since, limit); } async fetchTradingFee (symbol, params = {}) { /** * @method * @name coinex#fetchTradingFee * @description fetch the trading fees for a market * @param {string} symbol unified market symbol * @param {object} params extra parameters specific to the coinex api endpoint * @returns {object} a [fee structure]{@link https://docs.ccxt.com/en/latest/manual.html#fee-structure} */ await this.loadMarkets (); const market = this.market (symbol); const request = { 'market': market['id'], }; const response = await this.publicGetMarketDetail (this.extend (request, params)); // // { // "code": 0, // "data": { // "name": "BTCUSDC", // "min_amount": "0.0005", // "maker_fee_rate": "0.002", // "taker_fee_rate": "0.002", // "pricing_name": "USDC", // "pricing_decimal": 2, // "trading_name": "BTC", // "trading_decimal": 8 // }, // "message": "OK" // } // const data = this.safeValue (response, 'data', {}); return this.parseTradingFee (data); } async fetchTradingFees (params = {}) { /** * @method * @name coinex#fetchTradingFees * @description fetch the trading fees for multiple markets * @param {object} params extra parameters specific to the coinex api endpoint * @returns {object} a dictionary of [fee structures]{@link https://docs.ccxt.com/en/latest/manual.html#fee-structure} indexed by market symbols */ await this.loadMarkets (); const response = await this.publicGetMarketInfo (params); // // { // "code": 0, // "data": { // "WAVESBTC": { // "name": "WAVESBTC", // "min_amount": "1", // "maker_fee_rate": "0.001", // "taker_fee_rate": "0.001", // "pricing_name": "BTC", // "pricing_decimal": 8, // "trading_name": "WAVES", // "trading_decimal": 8 // } // ... // } // } // const data = this.safeValue (response, 'data', {}); const result = {}; for (let i = 0; i < this.symbols.length; i++) { const symbol = this.symbols[i]; const market = this.market (symbol); const fee = this.safeValue (data, market['id'], {}); result[symbol] = this.parseTradingFee (fee, market); } return result; } parseTradingFee (fee, market = undefined) { const marketId = this.safeValue (fee, 'name'); const symbol = this.safeSymbol (marketId, market); return { 'info': fee, 'symbol': symbol, 'maker': this.safeNumber (fee, 'maker_fee_rate'), 'taker': this.safeNumber (fee, 'taker_fee_rate'), 'percentage': true, 'tierBased': true, }; } parseOHLCV (ohlcv, market = undefined) { // // [ // 1591484400, // "0.02505349", // "0.02506988", // "0.02507000", // "0.02505304", // "343.19716223", // "8.6021323866383196", // "ETHBTC" // ] // return [ this.safeTimestamp (ohlcv, 0), this.safeNumber (ohlcv, 1), this.safeNumber (ohlcv, 3), this.safeNumber (ohlcv, 4), this.safeNumber (ohlcv, 2), this.safeNumber (ohlcv, 5), ]; } async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { /** * @method * @name coinex#fetchOHLCV * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market * @param {string} symbol unified symbol of the market to fetch OHLCV data for * @param {string} timeframe the length of time each candle represents * @param {int|undefined} since timestamp in ms of the earliest candle to fetch * @param {int|undefined} limit the maximum amount of candles to fetch * @param {object} params extra parameters specific to the coinex api endpoint * @returns {[[int]]} A list of candles ordered as timestamp, open, high, low, close, volume */ await this.loadMarkets (); const market = this.market (symbol); const request = { 'market': market['id'], 'type': this.timeframes[timeframe], }; if (limit !== undefined) { request['limit'] = limit; } const method = market['swap'] ? 'perpetualPublicGetMarketKline' : 'publicGetMarketKline'; const response = await this[method] (this.extend (reque