UNPKG

sfccxt

Version:

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

1,043 lines (1,027 loc) 109 kB
'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { AuthenticationError, ArgumentsRequired, ExchangeError, InsufficientFunds, DDoSProtection, InvalidNonce, PermissionDenied, BadRequest, BadSymbol, NotSupported, AccountNotEnabled, OnMaintenance } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); const Precise = require ('./base/Precise'); module.exports = class cryptocom extends Exchange { describe () { return this.deepExtend (super.describe (), { 'id': 'cryptocom', 'name': 'Crypto.com', 'countries': [ 'MT' ], 'version': 'v2', 'rateLimit': 10, // 100 requests per second 'pro': true, 'has': { 'CORS': false, 'spot': true, 'margin': true, 'swap': undefined, // has but not fully implemented 'future': undefined, // has but not fully implemented 'option': undefined, 'borrowMargin': true, 'cancelAllOrders': true, 'cancelOrder': true, 'createOrder': true, 'fetchBalance': true, 'fetchBidsAsks': false, 'fetchBorrowInterest': true, 'fetchBorrowRate': false, 'fetchBorrowRateHistories': false, 'fetchBorrowRateHistory': false, 'fetchBorrowRates': true, 'fetchClosedOrders': 'emulated', 'fetchCurrencies': false, 'fetchDepositAddress': true, 'fetchDepositAddressesByNetwork': true, 'fetchDeposits': true, 'fetchFundingHistory': false, 'fetchFundingRate': false, 'fetchFundingRates': false, 'fetchMarginMode': false, 'fetchMarkets': true, 'fetchMyTrades': true, 'fetchOHLCV': true, 'fetchOpenOrders': true, 'fetchOrder': true, 'fetchOrderBook': true, 'fetchOrders': true, 'fetchPositionMode': false, 'fetchPositions': false, 'fetchStatus': false, 'fetchTicker': true, 'fetchTickers': true, 'fetchTime': false, 'fetchTrades': true, 'fetchTradingFee': false, 'fetchTradingFees': false, 'fetchTransactionFees': false, 'fetchTransactions': false, 'fetchTransfers': true, 'fetchWithdrawals': true, 'repayMargin': true, 'setLeverage': false, 'setMarginMode': false, 'transfer': true, 'withdraw': true, }, 'timeframes': { '1m': '1m', '5m': '5m', '15m': '15m', '30m': '30m', '1h': '1h', '4h': '4h', '6h': '6h', '12h': '12h', '1d': '1D', '1w': '7D', '2w': '14D', '1M': '1M', }, 'urls': { 'logo': 'https://user-images.githubusercontent.com/1294454/147792121-38ed5e36-c229-48d6-b49a-48d05fc19ed4.jpeg', 'test': { 'spot': 'https://uat-api.3ona.co/v2', 'derivatives': 'https://uat-api.3ona.co/v2', }, 'api': { 'spot': 'https://api.crypto.com/v2', 'derivatives': 'https://deriv-api.crypto.com/v1', }, 'www': 'https://crypto.com/', 'referral': 'https://crypto.com/exch/5835vstech', 'doc': [ 'https://exchange-docs.crypto.com/spot/index.html', 'https://exchange-docs.crypto.com/derivatives/index.html', ], 'fees': 'https://crypto.com/exchange/document/fees-limits', }, 'api': { 'spot': { 'public': { 'get': { 'public/auth': 1, 'public/get-instruments': 1, 'public/get-book': 1, 'public/get-candlestick': 1, 'public/get-ticker': 1, 'public/get-trades': 1, 'public/margin/get-transfer-currencies': 1, 'public/margin/get-load-currenices': 1, 'public/respond-heartbeat': 1, }, }, 'private': { 'post': { 'private/set-cancel-on-disconnect': 10 / 3, 'private/get-cancel-on-disconnect': 10 / 3, 'private/create-withdrawal': 10 / 3, 'private/get-withdrawal-history': 10 / 3, 'private/get-currency-networks': 10 / 3, 'private/get-deposit-history': 10 / 3, 'private/get-deposit-address': 10 / 3, 'private/get-account-summary': 10 / 3, 'private/create-order': 2 / 3, 'private/cancel-order': 2 / 3, 'private/cancel-all-orders': 2 / 3, 'private/create-order-list': 10 / 3, 'private/get-order-history': 10 / 3, 'private/get-open-orders': 10 / 3, 'private/get-order-detail': 1 / 3, 'private/get-trades': 100, 'private/margin/get-user-config': 10 / 3, 'private/margin/get-account-summary': 10 / 3, 'private/margin/transfer': 10 / 3, 'private/margin/borrow': 10 / 3, 'private/margin/repay': 10 / 3, 'private/margin/get-transfer-history': 10 / 3, 'private/margin/get-borrow-history': 10 / 3, 'private/margin/get-interest-history': 10 / 3, 'private/margin/get-repay-history': 10 / 3, 'private/margin/get-liquidation-history': 10 / 3, 'private/margin/get-liquidation-orders': 10 / 3, 'private/margin/create-order': 2 / 3, 'private/margin/cancel-order': 2 / 3, 'private/margin/cancel-all-orders': 2 / 3, 'private/margin/get-order-history': 10 / 3, 'private/margin/get-open-orders': 10 / 3, 'private/margin/get-order-detail': 1 / 3, 'private/margin/get-trades': 100, 'private/deriv/transfer': 10 / 3, 'private/deriv/get-transfer-history': 10 / 3, 'private/get-accounts': 10 / 3, 'private/get-subaccount-balances': 10 / 3, 'private/create-subaccount-transfer': 10 / 3, 'private/otc/get-otc-user': 10 / 3, 'private/otc/get-instruments': 10 / 3, 'private/otc/request-quote': 100, 'private/otc/accept-quote': 100, 'private/otc/get-quote-history': 10 / 3, 'private/otc/get-trade-history': 10 / 3, }, }, }, 'derivatives': { 'public': { 'get': { 'public/auth': 10 / 3, 'public/get-instruments': 10 / 3, 'public/get-book': 1, 'public/get-candlestick': 1, 'public/get-trades': 1, 'public/get-tickers': 1, 'public/get-valuations': 1, 'public/get-expired-settlement-price': 10 / 3, 'public/get-insurance': 1, }, }, 'private': { 'post': { 'private/set-cancel-on-disconnect': 10 / 3, 'private/get-cancel-on-disconnect': 10 / 3, 'private/user-balance': 10 / 3, 'private/user-balance-history': 10 / 3, 'private/get-positions': 10 / 3, 'private/create-order': 2 / 3, 'private/cancel-order': 2 / 3, 'private/cancel-all-orders': 2 / 3, 'private/close-position': 10 / 3, 'private/convert-collateral': 10 / 3, 'private/get-order-history': 100, 'private/get-open-orders': 10 / 3, 'private/get-order-detail': 1 / 3, 'private/get-trades': 100, 'private/change-account-leverage': 10 / 3, 'private/get-transactions': 10 / 3, }, }, }, }, 'fees': { 'trading': { 'maker': this.parseNumber ('0.004'), 'taker': this.parseNumber ('0.004'), 'tiers': { 'maker': [ [ this.parseNumber ('0'), this.parseNumber ('0.004') ], [ this.parseNumber ('25000'), this.parseNumber ('0.0035') ], [ this.parseNumber ('50000'), this.parseNumber ('0.0015') ], [ this.parseNumber ('100000'), this.parseNumber ('0.001') ], [ this.parseNumber ('250000'), this.parseNumber ('0.0009') ], [ this.parseNumber ('1000000'), this.parseNumber ('0.0008') ], [ this.parseNumber ('20000000'), this.parseNumber ('0.0007') ], [ this.parseNumber ('100000000'), this.parseNumber ('0.0006') ], [ this.parseNumber ('200000000'), this.parseNumber ('0.0004') ], ], 'taker': [ [ this.parseNumber ('0'), this.parseNumber ('0.004') ], [ this.parseNumber ('25000'), this.parseNumber ('0.0035') ], [ this.parseNumber ('50000'), this.parseNumber ('0.0025') ], [ this.parseNumber ('100000'), this.parseNumber ('0.0016') ], [ this.parseNumber ('250000'), this.parseNumber ('0.00015') ], [ this.parseNumber ('1000000'), this.parseNumber ('0.00014') ], [ this.parseNumber ('20000000'), this.parseNumber ('0.00013') ], [ this.parseNumber ('100000000'), this.parseNumber ('0.00012') ], [ this.parseNumber ('200000000'), this.parseNumber ('0.0001') ], ], }, }, }, 'options': { 'defaultType': 'spot', 'accountsById': { 'funding': 'SPOT', 'spot': 'SPOT', 'margin': 'MARGIN', 'derivatives': 'DERIVATIVES', 'swap': 'DERIVATIVES', 'future': 'DERIVATIVES', }, }, // https://exchange-docs.crypto.com/spot/index.html#response-and-reason-codes 'commonCurrencies': { 'USD_STABLE_COIN': 'USDC', }, 'precisionMode': TICK_SIZE, 'exceptions': { 'exact': { '10001': ExchangeError, '10002': PermissionDenied, '10003': PermissionDenied, '10004': BadRequest, '10005': PermissionDenied, '10006': DDoSProtection, '10007': InvalidNonce, '10008': BadRequest, '10009': BadRequest, '20001': BadRequest, '20002': InsufficientFunds, '20005': AccountNotEnabled, // {"id":"123xxx","method":"private/margin/xxx","code":"20005","message":"ACCOUNT_NOT_FOUND"} '30003': BadSymbol, '30004': BadRequest, '30005': BadRequest, '30006': BadRequest, '30007': BadRequest, '30008': BadRequest, '30009': BadRequest, '30010': BadRequest, '30013': BadRequest, '30014': BadRequest, '30016': BadRequest, '30017': BadRequest, '30023': BadRequest, '30024': BadRequest, '30025': BadRequest, '40001': BadRequest, '40002': BadRequest, '40003': BadRequest, '40004': BadRequest, '40005': BadRequest, '40006': BadRequest, '40007': BadRequest, '40101': AuthenticationError, '50001': BadRequest, '9010001': OnMaintenance, // {"code":9010001,"message":"SYSTEM_MAINTENANCE","details":"Crypto.com Exchange is currently under maintenance. Please refer to https://status.crypto.com for more details."} }, }, }); } async fetchMarkets (params = {}) { /** * @method * @name cryptocom#fetchMarkets * @see https://exchange-docs.crypto.com/spot/index.html#public-get-instruments * @see https://exchange-docs.crypto.com/derivatives/index.html#public-get-instruments * @description retrieves data on all markets for cryptocom * @param {object} params extra parameters specific to the exchange api endpoint * @returns {[object]} an array of objects representing market data */ let promises = [ this.fetchSpotMarkets (params), this.fetchDerivativesMarkets (params) ]; promises = await Promise.all (promises); const spotMarkets = promises[0]; const derivativeMarkets = promises[1]; const markets = this.arrayConcat (spotMarkets, derivativeMarkets); return markets; } async fetchSpotMarkets (params = {}) { const response = await this.spotPublicGetPublicGetInstruments (params); // // { // id: 11, // method: 'public/get-instruments', // code: 0, // result: { // 'instruments': [ // { // instrument_name: 'NEAR_BTC', // quote_currency: 'BTC', // base_currency: 'NEAR', // price_decimals: '8', // quantity_decimals: '2', // margin_trading_enabled: true, // margin_trading_enabled_5x: true, // margin_trading_enabled_10x: true, // max_quantity: '100000000', // min_quantity: '0.01', // max_price:'1', // min_price:'0.00000001', // last_update_date:1667263094857, // quantity_tick_size:'0.1', // price_tick_size:'0.00000001' // }, // ] // } // } // const resultResponse = this.safeValue (response, 'result', {}); const markets = this.safeValue (resultResponse, 'instruments', []); const result = []; for (let i = 0; i < markets.length; i++) { const market = markets[i]; const id = this.safeString (market, 'instrument_name'); const baseId = this.safeString (market, 'base_currency'); const quoteId = this.safeString (market, 'quote_currency'); const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const minPrice = this.safeString (market, 'min_price'); const minQuantity = this.safeString (market, 'min_quantity'); let maxLeverage = this.parseNumber ('1'); const margin_trading_enabled_5x = this.safeValue (market, 'margin_trading_enabled_5x'); if (margin_trading_enabled_5x) { maxLeverage = this.parseNumber ('5'); } const margin_trading_enabled_10x = this.safeValue (market, 'margin_trading_enabled_10x'); if (margin_trading_enabled_10x) { maxLeverage = this.parseNumber ('10'); } result.push ({ 'id': id, 'symbol': base + '/' + quote, 'base': base, 'quote': quote, 'settle': undefined, 'baseId': baseId, 'quoteId': quoteId, 'settleId': undefined, 'type': 'spot', 'spot': true, 'margin': this.safeValue (market, 'margin_trading_enabled'), 'swap': false, 'future': false, 'option': false, 'active': undefined, 'contract': false, 'linear': undefined, 'inverse': undefined, 'contractSize': undefined, 'expiry': undefined, 'expiryDatetime': undefined, 'strike': undefined, 'optionType': undefined, 'precision': { 'amount': this.safeNumber (market, 'quantity_tick_size'), 'price': this.safeNumber (market, 'price_tick_size'), }, 'limits': { 'leverage': { 'min': this.parseNumber ('1'), 'max': maxLeverage, }, 'amount': { 'min': this.parseNumber (minQuantity), 'max': this.safeNumber (market, 'max_quantity'), }, 'price': { 'min': this.parseNumber (minPrice), 'max': this.safeNumber (market, 'max_price'), }, 'cost': { 'min': this.parseNumber (Precise.stringMul (minQuantity, minPrice)), 'max': undefined, }, }, 'info': market, }); } return result; } async fetchDerivativesMarkets (params = {}) { const result = []; const futuresResponse = await this.derivativesPublicGetPublicGetInstruments (); // // { // id: -1, // method: 'public/get-instruments', // code: 0, // result: { // data: [ // { // symbol: '1INCHUSD-PERP', // inst_type: 'PERPETUAL_SWAP', // display_name: '1INCHUSD Perpetual', // base_ccy: '1INCH', // quote_ccy: 'USD_Stable_Coin', // quote_decimals: 4, // quantity_decimals: 0, // price_tick_size: '0.0001', // qty_tick_size: '1', // max_leverage: '50', // tradable: true, // expiry_timestamp_ms: 0, // beta_product: false, // underlying_symbol: '1INCHUSD-INDEX', // put_call: 'UNDEFINED', // strike: '0', // contract_size: '1' // }, // ] // } // } // const futuresResult = this.safeValue (futuresResponse, 'result', {}); const data = this.safeValue (futuresResult, 'data', []); for (let i = 0; i < data.length; i++) { const market = data[i]; const inst_type = this.safeString (market, 'inst_type'); const swap = inst_type === 'PERPETUAL_SWAP'; const future = inst_type === 'FUTURE'; if (inst_type === 'CCY_PAIR') { continue; // Found some inconsistencies between spot and derivatives api so use spot api for currency pairs. } const baseId = this.safeString (market, 'base_ccy'); const quoteId = this.safeString (market, 'quote_ccy'); const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); let symbol = base + '/' + quote + ':' + quote; let expiry = this.safeInteger (market, 'expiry_timestamp_ms'); if (expiry === 0) { expiry = undefined; } let type = 'swap'; if (future) { type = 'future'; symbol = symbol + '-' + this.yymmdd (expiry); } const contractSize = this.safeNumber (market, 'contract_size'); result.push ({ 'id': this.safeString (market, 'symbol'), 'symbol': symbol, 'base': base, 'quote': quote, 'settle': quote, 'baseId': baseId, 'quoteId': quoteId, 'settleId': quoteId, 'type': type, 'spot': false, 'margin': false, 'swap': swap, 'future': future, 'option': false, 'active': this.safeValue (market, 'tradable'), 'contract': true, 'linear': true, 'inverse': false, 'contractSize': contractSize, 'expiry': expiry, 'expiryDatetime': this.iso8601 (expiry), 'strike': undefined, 'optionType': undefined, 'precision': { 'price': this.parseNumber (this.parsePrecision (this.safeString (market, 'quote_decimals'))), 'amount': this.parseNumber (this.parsePrecision (this.safeString (market, 'quantity_decimals'))), }, 'limits': { 'leverage': { 'min': this.parseNumber ('1'), 'max': this.safeNumber (market, 'max_leverage'), }, 'amount': { 'min': this.parseNumber (contractSize), 'max': undefined, }, 'price': { 'min': undefined, 'max': undefined, }, 'cost': { 'min': undefined, 'max': undefined, }, }, 'info': market, }); } return result; } async fetchTickers (symbols = undefined, params = {}) { /** * @method * @name cryptocom#fetchTickers * @description fetches price tickers for multiple markets, statistical calculations with the information calculated over the past 24 hours each market * @see https://exchange-docs.crypto.com/spot/index.html#public-get-ticker * @see https://exchange-docs.crypto.com/derivatives/index.html#public-get-tickers * @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 cryptocom 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 = this.getSupportedMapping (marketType, { 'spot': 'spotPublicGetPublicGetTicker', 'future': 'derivativesPublicGetPublicGetTickers', 'swap': 'derivativesPublicGetPublicGetTickers', }); const response = await this[method] (query); // // { // "code":0, // "method":"public/get-ticker", // "result":{ // "data": [ // {"i":"CRO_BTC","b":0.00000890,"k":0.00001179,"a":0.00001042,"t":1591770793901,"v":14905879.59,"h":0.00,"l":0.00,"c":0.00}, // {"i":"EOS_USDT","b":2.7676,"k":2.7776,"a":2.7693,"t":1591770798500,"v":774.51,"h":0.05,"l":0.05,"c":0.00}, // {"i":"BCH_USDT","b":247.49,"k":251.73,"a":251.67,"t":1591770797601,"v":1.01693,"h":0.01292,"l":0.01231,"c":-0.00047}, // {"i":"ETH_USDT","b":239.92,"k":242.59,"a":240.30,"t":1591770798701,"v":0.97575,"h":0.01236,"l":0.01199,"c":-0.00018}, // {"i":"ETH_CRO","b":2693.11,"k":2699.84,"a":2699.55,"t":1591770795053,"v":95.680,"h":8.218,"l":7.853,"c":-0.050} // ] // } // } // const result = this.safeValue (response, 'result', {}); const data = this.safeValue (result, 'data', []); return this.parseTickers (data, symbols); } async fetchTicker (symbol, params = {}) { /** * @method * @name cryptocom#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 cryptocom 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 = { 'instrument_name': market['id'], }; const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchTicker', market, params); if (marketType !== 'spot') { throw new NotSupported (this.id + ' fetchTicker() only supports spot markets'); } const response = await this.spotPublicGetPublicGetTicker (this.extend (request, query)); // // { // "id":"-1", // "method":"public/get-tickers", // "code":"0", // "result":{ // "data":[ // { "i":"BTC_USDT", "h":"20567.16", "l":"20341.39", "a":"20394.23", "v":"2236.3762", "vv":"45739074.30", "c":"-0.0036", "b":"20394.01", "k":"20394.02", "t":"1667406085934" } // ] // } // const resultResponse = this.safeValue (response, 'result', {}); const data = this.safeValue (resultResponse, 'data', {}); const first = this.safeValue (data, 0, {}); return this.parseTicker (first, market); } async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { /** * @method * @name cryptocom#fetchOrders * @description fetches information on multiple orders made by the user * @param {string} symbol unified market symbol of the market orders were made in * @param {int|undefined} since the earliest time in ms to fetch orders for * @param {int|undefined} limit the maximum number of orde structures to retrieve * @param {object} params extra parameters specific to the cryptocom api endpoint * @returns {[object]} a list of [order structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure} */ if (symbol === undefined) { throw new ArgumentsRequired (this.id + ' fetchOrders() requires a symbol argument'); } await this.loadMarkets (); const market = this.market (symbol); const request = { 'instrument_name': market['id'], }; if (since !== undefined) { // maximum date range is one day request['start_ts'] = since; } if (limit !== undefined) { request['page_size'] = limit; } const [ marketType, marketTypeQuery ] = this.handleMarketTypeAndParams ('fetchOrders', market, params); let method = this.getSupportedMapping (marketType, { 'spot': 'spotPrivatePostPrivateGetOrderHistory', 'margin': 'spotPrivatePostPrivateMarginGetOrderHistory', 'future': 'derivativesPrivatePostPrivateGetOrderHistory', 'swap': 'derivativesPrivatePostPrivateGetOrderHistory', }); const [ marginMode, query ] = this.customHandleMarginModeAndParams ('fetchOrders', marketTypeQuery); if (marginMode !== undefined) { method = 'spotPrivatePostPrivateMarginGetOrderHistory'; } const response = await this[method] (this.extend (request, query)); // // spot and margin // { // id: 1641026542065, // method: 'private/get-order-history', // code: 0, // result: { // order_list: [ // { // status: 'FILLED', // side: 'BUY', // price: 0, // quantity: 110, // order_id: '2120246337927715937', // client_oid: '', // create_time: 1641025064904, // update_time: 1641025064958, // type: 'MARKET', // instrument_name: 'USDC_USDT', // avg_price: 1.0001, // cumulative_quantity: 110, // cumulative_value: 110.011, // fee_currency: 'USDC', // exec_inst: '', // time_in_force: 'GOOD_TILL_CANCEL' // } // ] // } // } // // swap // { // id: 1641026373106, // method: 'private/get-order-history', // code: 0, // result: { // data: [ // { // account_id: '85ff689a-7508-4b96-aa79-dc0545d6e637', // order_id: 13191401932, // client_oid: '1641025941461', // order_type: 'LIMIT', // time_in_force: 'GOOD_TILL_CANCEL', // side: 'BUY', // exec_inst: [], // quantity: '0.0001', // limit_price: '48000.0', // order_value: '4.80000000', // maker_fee_rate: '0.00050', // taker_fee_rate: '0.00070', // avg_price: '47253.5', // trigger_price: '0.0', // ref_price_type: 'NULL_VAL', // cumulative_quantity: '0.0001', // cumulative_value: '4.72535000', // cumulative_fee: '0.00330775', // status: 'FILLED', // update_user_id: 'ce075bef-b600-4277-bd6e-ff9007251e63', // order_date: '2022-01-01', // instrument_name: 'BTCUSD-PERP', // fee_instrument_name: 'USD_Stable_Coin', // create_time: 1641025941827, // create_time_ns: '1641025941827994756', // update_time: 1641025941827 // } // ] // } // } // const data = this.safeValue (response, 'result', {}); const orderList = this.safeValue2 (data, 'order_list', 'data', []); return this.parseOrders (orderList, market, since, limit); } async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { /** * @method * @name cryptocom#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 cryptocom 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 = { 'instrument_name': market['id'], }; if (since !== undefined) { // maximum date range is one day request['start_ts'] = since; } if (limit !== undefined) { request['page_size'] = limit; } const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchTrades', market, params); const method = this.getSupportedMapping (marketType, { 'spot': 'spotPublicGetPublicGetTrades', 'future': 'derivativesPublicGetPublicGetTrades', 'swap': 'derivativesPublicGetPublicGetTrades', }); const response = await this[method] (this.extend (request, query)); // { // "code":0, // "method":"public/get-trades", // "result": { // "instrument_name": "BTC_USDT", // "data:": [ // {"dataTime":1591710781947,"d":465533583799589409,"s":"BUY","p":2.96,"q":16.0,"t":1591710781946,"i":"ICX_CRO"}, // {"dataTime":1591707701899,"d":465430234542863152,"s":"BUY","p":0.007749,"q":115.0,"t":1591707701898,"i":"VET_USDT"}, // {"dataTime":1591710786155,"d":465533724976458209,"s":"SELL","p":25.676,"q":0.55,"t":1591710786154,"i":"XTZ_CRO"}, // {"dataTime":1591710783300,"d":465533629172286576,"s":"SELL","p":2.9016,"q":0.6,"t":1591710783298,"i":"XTZ_USDT"}, // {"dataTime":1591710784499,"d":465533669425626384,"s":"SELL","p":2.7662,"q":0.58,"t":1591710784498,"i":"EOS_USDT"}, // {"dataTime":1591710784700,"d":465533676120104336,"s":"SELL","p":243.21,"q":0.01647,"t":1591710784698,"i":"ETH_USDT"}, // {"dataTime":1591710786600,"d":465533739878620208,"s":"SELL","p":253.06,"q":0.00516,"t":1591710786598,"i":"BCH_USDT"}, // {"dataTime":1591710786900,"d":465533749959572464,"s":"BUY","p":0.9999,"q":0.2,"t":1591710786898,"i":"USDC_USDT"}, // {"dataTime":1591710787500,"d":465533770081010000,"s":"BUY","p":3.159,"q":1.65,"t":1591710787498,"i":"ATOM_USDT"}, // ] // } // } const resultResponse = this.safeValue (response, 'result', {}); const data = this.safeValue (resultResponse, 'data', []); return this.parseTrades (data, market, since, limit); } async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { /** * @method * @name cryptocom#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 cryptocom 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 = { 'instrument_name': market['id'], 'timeframe': this.timeframes[timeframe], }; const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchOHLCV', market, params); const method = this.getSupportedMapping (marketType, { 'spot': 'spotPublicGetPublicGetCandlestick', 'future': 'derivativesPublicGetPublicGetCandlestick', 'swap': 'derivativesPublicGetPublicGetCandlestick', }); if (marketType !== 'spot') { let reqLimit = 100; if (limit !== undefined) { reqLimit = limit; } request['count'] = reqLimit; } const response = await this[method] (this.extend (request, query)); // { // "code":0, // "method":"public/get-candlestick", // "result":{ // "instrument_name":"BTC_USDT", // "interval":"5m", // "data":[ // {"t":1596944700000,"o":11752.38,"h":11754.77,"l":11746.65,"c":11753.64,"v":3.694583}, // {"t":1596945000000,"o":11753.63,"h":11754.77,"l":11739.83,"c":11746.17,"v":2.073019}, // {"t":1596945300000,"o":11746.16,"h":11753.24,"l":11738.1,"c":11740.65,"v":0.867247}, // ... // ] // } // } const resultResponse = this.safeValue (response, 'result', {}); const data = this.safeValue (resultResponse, 'data', []); return this.parseOHLCVs (data, market, timeframe, since, limit); } async fetchOrderBook (symbol, limit = undefined, params = {}) { /** * @method * @name cryptocom#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 cryptocom 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 */ await this.loadMarkets (); const market = this.market (symbol); const request = { 'instrument_name': market['id'], }; if (limit) { request['depth'] = limit; } const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchOrderBook', market, params); const method = this.getSupportedMapping (marketType, { 'spot': 'spotPublicGetPublicGetBook', 'future': 'derivativesPublicGetPublicGetBook', 'swap': 'derivativesPublicGetPublicGetBook', }); const response = await this[method] (this.extend (request, query)); // { // "code":0, // "method":"public/get-book", // "result":{ // "bids":[[9668.44,0.006325,1.0],[9659.75,0.006776,1.0],[9653.14,0.011795,1.0],[9647.13,0.019434,1.0],[9634.62,0.013765,1.0],[9633.81,0.021395,1.0],[9628.46,0.037834,1.0],[9627.6,0.020909,1.0],[9621.51,0.026235,1.0],[9620.83,0.026701,1.0]], // "asks":[[9697.0,0.68251,1.0],[9697.6,1.722864,2.0],[9699.2,1.664177,2.0],[9700.8,1.824953,2.0],[9702.4,0.85778,1.0],[9704.0,0.935792,1.0],[9713.32,0.002926,1.0],[9716.42,0.78923,1.0],[9732.19,0.00645,1.0],[9737.88,0.020216,1.0]], // "t":1591704180270 // } // } const result = this.safeValue (response, 'result'); const data = this.safeValue (result, 'data'); const orderBook = this.safeValue (data, 0); const timestamp = this.safeInteger (orderBook, 't'); return this.parseOrderBook (orderBook, symbol, timestamp); } parseSwapBalance (response) { const responseResult = this.safeValue (response, 'result', {}); const data = this.safeValue (responseResult, 'data', []); const result = { 'info': response }; for (let i = 0; i < data.length; i++) { const balance = data[i]; const currencyId = this.safeString (balance, 'instrument_name'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); account['total'] = this.safeString (balance, 'total_cash_balance'); account['free'] = this.safeString (balance, 'total_available_balance'); result[code] = account; } return this.safeBalance (result); } parseSpotBalance (response) { const data = this.safeValue (response, 'result', {}); const coinList = this.safeValue (data, 'accounts', []); const result = { 'info': response }; for (let i = 0; i < coinList.length; i++) { const balance = coinList[i]; const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); account['total'] = this.safeString (balance, 'balance'); account['free'] = this.safeString (balance, 'available'); account['used'] = this.safeString (balance, 'order'); result[code] = account; } return this.safeBalance (result); } async fetchBalance (params = {}) { /** * @method * @name cryptocom#fetchBalance * @description query for balance and get the amount of funds available for trading or funds locked in orders * @param {object} params extra parameters specific to the cryptocom api endpoint * @returns {object} a [balance structure]{@link https://docs.ccxt.com/en/latest/manual.html?#balance-structure} */ await this.loadMarkets (); const [ marketType, marketTypeQuery ] = this.handleMarketTypeAndParams ('fetchBalance', undefined, params); let method = this.getSupportedMapping (marketType, { 'spot': 'spotPrivatePostPrivateGetAccountSummary', 'margin': 'spotPrivatePostPrivateMarginGetAccountSummary', 'future': 'derivativesPrivatePostPrivateUserBalance', 'swap': 'derivativesPrivatePostPrivateUserBalance', }); const [ marginMode, query ] = this.customHandleMarginModeAndParams ('fetchBalance', marketTypeQuery); if (marginMode !== undefined) { method = 'spotPrivatePostPrivateMarginGetAccountSummary'; } const response = await this[method] (query); // spot // { // "id": 11, // "method": "private/get-account-summary", // "code": 0, // "result": { // "accounts": [ // { // "balance": 99999999.905000000000000000, // "available": 99999996.905000000000000000, // "order": 3.000000000000000000, // "stake": 0, // "currency": "CRO" // } // ] // } // } // // margin // { // "id": 1656529728178, // "method": "private/margin/get-account-summary", // "code": 0, // "result": { // "accounts": [ // { // "balance": 0, // "available": 0, // "order": 0, // "borrowed": 0, // "position": 0, // "positionHomeCurrency": 0, // "positionBtc": 0, // "lastPriceHomeCurrency": 20111.38, // "lastPriceBtc": 1, // "currency": "BTC", // "accrued_interest": 0, // "liquidation_price": 0 // }, // ], // "is_liquidating": false, // "total_balance": 16, // "total_balance_btc": 0.00079556, // "equity_value": 16, // "equity_value_btc": 0.00079556, // "total_borrowed": 0, // "total_borrowed_btc": 0, // "total_accrued_interest": 0, // "total_accrued_interest_btc": 0, // "margin_score": "GOOD", // "currency": "USDT" // } // } // // swap // { // "id" : 1641025392400, // "method" : "private/user-balance", // "code" : 0, // "result" : { // "data" : [ { // "total_available_balance" : "109.56000000", // "total_margin_balance" : "109.56000000", // "total_initial_margin" : "0.00000000", // "total_maintenance_margin" : "0.00000000", // "total_position_cost" : "0.00000000", // "total_cash_balance" : "109.56000000", // "total_collateral_value" : "109.56000000", // "total_session_unrealized_pnl" : "0.00000000", // "instrument_name" : "USD_Stable_Coin", // "total_session_realized_pnl" : "0.00000000", // "position_balances" : [ { // "quantity" : "109.56000000", // "collateral_weight" : "1.000000", // "collateral_amount" : "109.56000000", // "market_value" : "109.56000000", // "max_withdrawal_balance" : "109.56000000", // "instrument_name" : "USD_Stable_Coin" // } ], // "total_effective_leverage" : "0.000000", // "position_limit" : "3000000.00000000", // "used_position_limit" : "0.00000000", // "is_liquidating" : false // } ] // } // } // const parser = this.getSupportedMapping (marketType, { 'spot': 'parseSpotBalance', 'margin': 'parseSpotBalance', 'future': 'parseSwapBalance', 'swap': 'parseSwapBalance', }); return this[parser] (response); } async fetchOrder (id, symbol = undefined, params = {}) { /** * @method * @name cryptocom#fetchOrder * @description fetches information on an order made by the user * @param {string|undefined} symbol unified symbol of the market the order was made in * @param {object} params extra parameters specific to the cryptocom api endpoint * @returns {object} An [order structure]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure} */ await this.loadMarkets (); let market = undefined; if (symbol !== undefined) { market = this.market (symbol); } const request = {}; const [ marketType, marketTypeQuery ] = this.handleMarketTypeAndParams ('fetchOrder', market, params); const [ marginMode, query ] = this.customHandleMarginModeAndParams ('fetchOrder', marketTypeQuery); if ((marketType === 'spot') || (marketType === 'margin') || (marginMode !== undefined)) { request['order_id'] = id.toString (); } else { request['order_id'] = parseInt (id); } let method = this.getSupportedMapping (marketType, { 'spot': 'spotPrivatePostPrivateGetOrderDetail', 'margin': 'spotPrivatePostPrivateMarginGetOrderDetail', 'future': 'derivativesPrivatePostPrivateGetOrderDetail', 'swap': 'derivativesPrivatePostPrivateGetOrderDetail', }); if (marginMode !== undefined) { method = 'spotPriv