UNPKG

@proton/ccxt

Version:

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

1,016 lines (1,014 loc) 134 kB
// ---------------------------------------------------------------------------- // PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN: // https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code // EDIT THE CORRESPONDENT .ts FILE INSTEAD // --------------------------------------------------------------------------- import Exchange from './abstract/cryptocom.js'; import { Precise } from './base/Precise.js'; import { AuthenticationError, ArgumentsRequired, ExchangeError, InsufficientFunds, DDoSProtection, InvalidNonce, PermissionDenied, BadRequest, BadSymbol, NotSupported, AccountNotEnabled, OnMaintenance, InvalidOrder } from './base/errors.js'; import { TICK_SIZE } from './base/functions/number.js'; import { sha256 } from './static_dependencies/noble-hashes/sha256.js'; export default class cryptocom extends Exchange { describe() { return this.deepExtend(super.describe(), { 'id': 'cryptocom', 'name': 'Crypto.com', 'countries': ['MT'], 'version': 'v2', 'rateLimit': 10, 'certified': true, 'pro': true, 'has': { 'CORS': false, 'spot': true, 'margin': true, 'swap': undefined, 'future': undefined, 'option': undefined, 'borrowMargin': true, 'cancelAllOrders': true, 'cancelOrder': true, 'createOrder': true, 'fetchAccounts': 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, 'fetchDepositsWithdrawals': false, 'fetchDepositWithdrawFee': 'emulated', 'fetchDepositWithdrawFees': true, 'fetchFundingHistory': false, 'fetchFundingRate': false, 'fetchFundingRateHistory': true, 'fetchFundingRates': false, 'fetchLedger': true, 'fetchMarginMode': false, 'fetchMarkets': true, 'fetchMyTrades': true, 'fetchOHLCV': true, 'fetchOpenOrders': true, 'fetchOrder': true, 'fetchOrderBook': true, 'fetchOrders': true, 'fetchPosition': true, 'fetchPositionMode': false, 'fetchPositions': true, 'fetchSettlementHistory': true, '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': { 'v1': 'https://uat-api.3ona.co/exchange/v1', 'v2': 'https://uat-api.3ona.co/v2', 'derivatives': 'https://uat-api.3ona.co/v2', }, 'api': { 'v1': 'https://api.crypto.com/exchange/v1', 'v2': '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/exchange/v1/rest-ws/index.html', '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': { 'v1': { '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/create-order-list': 10 / 3, 'private/cancel-order': 2 / 3, 'private/cancel-order-list': 10 / 3, 'private/cancel-all-orders': 2 / 3, 'private/close-position': 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, 'private/create-subaccount-transfer': 10 / 3, 'private/get-subaccount-balances': 10 / 3, 'private/get-order-list': 10 / 3, 'private/create-withdrawal': 10 / 3, 'private/get-currency-networks': 10 / 3, 'private/get-deposit-address': 10 / 3, 'private/get-accounts': 10 / 3, }, }, }, 'v2': { '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/create-order-list': 10 / 3, 'private/cancel-order': 2 / 3, 'private/cancel-order-list': 10 / 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, 'private/create-subaccount-transfer': 10 / 3, 'private/get-subaccount-balances': 10 / 3, 'private/get-order-list': 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', }, 'networks': { 'BEP20': 'BSC', 'ERC20': 'ETH', 'TRX': 'TRON', 'TRC20': 'TRON', }, 'networksById': { 'BSC': 'BEP20', 'ETH': 'ERC20', 'TRON': 'TRC20', }, 'broker': 'CCXT_', }, // 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, '30003': BadSymbol, '30004': BadRequest, '30005': BadRequest, '30006': InvalidOrder, '30007': InvalidOrder, '30008': InvalidOrder, '30009': InvalidOrder, '30010': BadRequest, '30013': InvalidOrder, '30014': InvalidOrder, '30016': InvalidOrder, '30017': InvalidOrder, '30023': InvalidOrder, '30024': InvalidOrder, '30025': InvalidOrder, '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/exchange/v1/rest-ws/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 */ const response = await this.v1PublicGetPublicGetInstruments(params); // // { // "id": 1, // "method": "public/get-instruments", // "code": 0, // "result": { // "data": [ // { // "symbol": "BTC_USDT", // "inst_type": "CCY_PAIR", // "display_name": "BTC/USDT", // "base_ccy": "BTC", // "quote_ccy": "USDT", // "quote_decimals": 2, // "quantity_decimals": 5, // "price_tick_size": "0.01", // "qty_tick_size": "0.00001", // "max_leverage": "50", // "tradable": true, // "expiry_timestamp_ms": 0, // "beta_product": false, // "margin_buy_enabled": false, // "margin_sell_enabled": true // }, // { // "symbol": "RUNEUSD-PERP", // "inst_type": "PERPETUAL_SWAP", // "display_name": "RUNEUSD Perpetual", // "base_ccy": "RUNE", // "quote_ccy": "USD", // "quote_decimals": 3, // "quantity_decimals": 1, // "price_tick_size": "0.001", // "qty_tick_size": "0.1", // "max_leverage": "50", // "tradable": true, // "expiry_timestamp_ms": 0, // "beta_product": false, // "underlying_symbol": "RUNEUSD-INDEX", // "contract_size": "1", // "margin_buy_enabled": false, // "margin_sell_enabled": false // }, // { // "symbol": "ETHUSD-230825", // "inst_type": "FUTURE", // "display_name": "ETHUSD Futures 20230825", // "base_ccy": "ETH", // "quote_ccy": "USD", // "quote_decimals": 2, // "quantity_decimals": 4, // "price_tick_size": "0.01", // "qty_tick_size": "0.0001", // "max_leverage": "100", // "tradable": true, // "expiry_timestamp_ms": 1692950400000, // "beta_product": false, // "underlying_symbol": "ETHUSD-INDEX", // "contract_size": "1", // "margin_buy_enabled": false, // "margin_sell_enabled": false // }, // { // "symbol": "BTCUSD-230630-CW30000", // "inst_type": "WARRANT", // "display_name": "BTCUSD-230630-CW30000", // "base_ccy": "BTC", // "quote_ccy": "USD", // "quote_decimals": 3, // "quantity_decimals": 0, // "price_tick_size": "0.001", // "qty_tick_size": "10", // "max_leverage": "50", // "tradable": true, // "expiry_timestamp_ms": 1688112000000, // "beta_product": false, // "underlying_symbol": "BTCUSD-INDEX", // "put_call": "CALL", // "strike": "30000", // "contract_size": "0.0001", // "margin_buy_enabled": false, // "margin_sell_enabled": false // }, // ] // } // } // const resultResponse = this.safeValue(response, 'result', {}); const data = this.safeValue(resultResponse, 'data', []); const result = []; for (let i = 0; i < data.length; i++) { const market = data[i]; const inst_type = this.safeString(market, 'inst_type'); const spot = inst_type === 'CCY_PAIR'; const swap = inst_type === 'PERPETUAL_SWAP'; const future = inst_type === 'FUTURE'; const option = inst_type === 'WARRANT'; const baseId = this.safeString(market, 'base_ccy'); const quoteId = this.safeString(market, 'quote_ccy'); const settleId = spot ? undefined : quoteId; const base = this.safeCurrencyCode(baseId); const quote = this.safeCurrencyCode(quoteId); const settle = spot ? undefined : this.safeCurrencyCode(settleId); const optionType = this.safeStringLower(market, 'put_call'); const strike = this.safeString(market, 'strike'); const marginBuyEnabled = this.safeValue(market, 'margin_buy_enabled'); const marginSellEnabled = this.safeValue(market, 'margin_sell_enabled'); const expiry = this.omitZero(this.safeInteger(market, 'expiry_timestamp_ms')); let symbol = base + '/' + quote; let type = undefined; let contract = undefined; if (inst_type === 'CCY_PAIR') { type = 'spot'; contract = false; } else if (inst_type === 'PERPETUAL_SWAP') { type = 'swap'; symbol = symbol + ':' + quote; contract = true; } else if (inst_type === 'FUTURE') { type = 'future'; symbol = symbol + ':' + quote + '-' + this.yymmdd(expiry); contract = true; } else if (inst_type === 'WARRANT') { type = 'option'; const symbolOptionType = (optionType === 'call') ? 'C' : 'P'; symbol = symbol + ':' + quote + '-' + this.yymmdd(expiry) + '-' + strike + '-' + symbolOptionType; contract = true; } result.push({ 'id': this.safeString(market, 'symbol'), 'symbol': symbol, 'base': base, 'quote': quote, 'settle': settle, 'baseId': baseId, 'quoteId': quoteId, 'settleId': settleId, 'type': type, 'spot': spot, 'margin': ((marginBuyEnabled) || (marginSellEnabled)), 'swap': swap, 'future': future, 'option': option, 'active': this.safeValue(market, 'tradable'), 'contract': contract, 'linear': (contract) ? true : undefined, 'inverse': (contract) ? false : undefined, 'contractSize': this.safeNumber(market, 'contract_size'), 'expiry': expiry, 'expiryDatetime': this.iso8601(expiry), 'strike': this.parseNumber(strike), 'optionType': optionType, 'precision': { 'price': this.parseNumber(this.safeString(market, 'price_tick_size')), 'amount': this.parseNumber(this.safeString(market, 'qty_tick_size')), }, 'limits': { 'leverage': { 'min': this.parseNumber('1'), 'max': this.safeNumber(market, 'max_leverage'), }, 'amount': { 'min': undefined, '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/exchange/v1/rest-ws/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} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure} */ await this.loadMarkets(); let market = undefined; const request = {}; if (symbols !== undefined) { let symbol = undefined; if (Array.isArray(symbols)) { const symbolsLength = symbols.length; if (symbolsLength > 1) { throw new BadRequest(this.id + ' fetchTickers() symbols argument cannot contain more than 1 symbol'); } symbol = symbols[0]; } else { symbol = symbols; } market = this.market(symbol); request['instrument_name'] = market['id']; } const response = await this.v1PublicGetPublicGetTickers(this.extend(request, params)); // // { // "id": -1, // "method": "public/get-tickers", // "code": 0, // "result": { // "data": [ // { // "i": "AVAXUSD-PERP", // "h": "13.209", // "l": "12.148", // "a": "13.209", // "v": "1109.8", // "vv": "14017.33", // "c": "0.0732", // "b": "13.210", // "k": "13.230", // "oi": "10888.9", // "t": 1687402657575 // }, // ] // } // } // 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 * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#public-get-tickers * @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/#/?id=ticker-structure} */ await this.loadMarkets(); symbol = this.symbol(symbol); const tickers = await this.fetchTickers([symbol], params); return this.safeValue(tickers, symbol); } async fetchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) { /** * @method * @name cryptocom#fetchOrders * @description fetches information on multiple orders made by the user * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-get-order-history * @param {string} symbol unified market symbol of the market the orders were made in * @param {int|undefined} since the earliest time in ms to fetch orders for, max date range is one day * @param {int|undefined} limit the maximum number of order structures to retrieve, default 100 max 100 * @param {object} params extra parameters specific to the cryptocom api endpoint * @param {int|undefined} params.until timestamp in ms for the ending date filter, default is the current time * @returns {[object]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure} */ await this.loadMarkets(); let market = undefined; const request = {}; if (symbol !== undefined) { market = this.market(symbol); request['instrument_name'] = market['id']; } if (since !== undefined) { request['start_time'] = since; } if (limit !== undefined) { request['limit'] = limit; } const until = this.safeInteger2(params, 'until', 'till'); params = this.omit(params, ['until', 'till']); if (until !== undefined) { request['end_time'] = until; } const response = await this.v1PrivatePostPrivateGetOrderHistory(this.extend(request, params)); // // { // "id": 1686881486183, // "method": "private/get-order-history", // "code": 0, // "result": { // "data": [ // { // "account_id": "ce075bef-1234-4321-bd6g-ff9007252e63", // "order_id": "6142909895014042762", // "client_oid": "4e918597-1234-4321-8201-a7577e1e1d91", // "order_type": "MARKET", // "time_in_force": "GOOD_TILL_CANCEL", // "side": "SELL", // "exec_inst": [ ], // "quantity": "0.00024", // "order_value": "5.7054672", // "maker_fee_rate": "0", // "taker_fee_rate": "0", // "avg_price": "25023.97", // "trigger_price": "0", // "ref_price": "0", // "ref_price_type": "NULL_VAL", // "cumulative_quantity": "0.00024", // "cumulative_value": "6.0057528", // "cumulative_fee": "0.001501438200", // "status": "FILLED", // "update_user_id": "ce075bef-1234-4321-bd6g-ff9007252e63", // "order_date": "2023-06-15", // "instrument_name": "BTC_USD", // "fee_instrument_name": "USD", // "create_time": 1686805465891, // "create_time_ns": "1686805465891812578", // "update_time": 1686805465891 // } // ] // } // } // const data = this.safeValue(response, 'result', {}); const orders = this.safeValue(data, 'data', []); return this.parseOrders(orders, market, since, limit); } async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) { /** * @method * @name cryptocom#fetchTrades * @description get a list of the most recent trades for a particular symbol * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#public-get-trades * @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, maximum date range is one day * @param {int|undefined} limit the maximum number of trades to fetch * @param {object} params extra parameters specific to the cryptocom api endpoint * @param {int|undefined} params.until timestamp in ms for the ending date filter, default is the current time * @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) { request['start_ts'] = since; } if (limit !== undefined) { request['count'] = limit; } const until = this.safeInteger2(params, 'until', 'till'); params = this.omit(params, ['until', 'till']); if (until !== undefined) { request['end_ts'] = until; } const response = await this.v1PublicGetPublicGetTrades(this.extend(request, params)); // // { // "id": -1, // "method": "public/get-trades", // "code": 0, // "result": { // "data": [ // { // "s": "sell", // "p": "26386.00", // "q": "0.00453", // "t": 1686944282062, // "d": "4611686018455979970", // "i": "BTC_USD" // }, // ] // } // } // const result = this.safeValue(response, 'result', {}); const trades = this.safeValue(result, 'data', []); return this.parseTrades(trades, 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 * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#public-get-candlestick * @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 * @param {int|undefined} params.until timestamp in ms for the ending date filter, default is the current time * @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.safeString(this.timeframes, timeframe, timeframe), }; if (since !== undefined) { request['start_ts'] = since; } if (limit !== undefined) { request['count'] = limit; } const until = this.safeInteger2(params, 'until', 'till'); params = this.omit(params, ['until', 'till']); if (until !== undefined) { request['end_ts'] = until; } const response = await this.v1PublicGetPublicGetCandlestick(this.extend(request, params)); // // { // "id": -1, // "method": "public/get-candlestick", // "code": 0, // "result": { // "interval": "1m", // "data": [ // { // "o": "26949.89", // "h": "26957.64", // "l": "26948.24", // "c": "26950.00", // "v": "0.0670", // "t": 1687237080000 // }, // ], // "instrument_name": "BTC_USD" // } // } // const result = this.safeValue(response, 'result', {}); const data = this.safeValue(result, '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 * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#public-get-book * @param {string} symbol unified symbol of the market to fetch the order book for * @param {int|undefined} limit the number of order book entries to return, max 50 * @param {object} params extra parameters specific to the cryptocom api endpoint * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=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 response = await this.v1PublicGetPublicGetBook(this.extend(request, params)); // // { // "id": -1, // "method": "public/get-book", // "code": 0, // "result": { // "depth": 3, // "data": [ // { // "bids": [ [ "30025.00", "0.00004", "1" ], [ "30020.15", "0.02498", "1" ], [ "30020.00", "0.00004", "1" ] ], // "asks": [ [ "30025.01", "0.04090", "1" ], [ "30025.70", "0.01000", "1" ], [ "30026.94", "0.02681", "1" ] ], // "t": 1687491287380 // } // ], // "instrument_name": "BTC_USD" // } // } // 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); } parseBalance(response) { const responseResult = this.safeValue(response, 'result', {}); const data = this.safeValue(responseResult, 'data', []); const positionBalances = this.safeValue(data[0], 'position_balances', []); const result = { 'info': response }; for (let i = 0; i < positionBalances.length; i++) { const balance = positionBalances[i]; const currencyId = this.safeString(balance, 'instrument_name'); const code = this.safeCurrencyCode(currencyId); const account = this.account(); account['total'] = this.safeString(balance, 'quantity'); account['used'] = this.safeString(balance, 'reserved_qty'); 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 * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-user-balance * @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 response = await this.v1PrivatePostPrivateUserBalance(params); // // { // "id": 1687300499018, // "method": "private/user-balance", // "code": 0, // "result": { // "data": [ // { // "total_available_balance": "5.84684368", // "total_margin_balance": "5.84684368", // "total_initial_margin": "0", // "total_maintenance_margin": "0", // "total_position_cost": "0", // "total_cash_balance": "6.44412101", // "total_collateral_value": "5.846843685", // "total_session_unrealized_pnl": "0", // "instrument_name": "USD", // "total_session_realized_pnl": "0", // "position_balances": [ // { // "quantity": "0.0002119875", // "reserved_qty": "0", // "collateral_weight": "0.9", // "collateral_amount": "5.37549592", // "market_value": "5.97277325", // "max_withdrawal_balance": "0.00021198", // "instrument_name": "BTC", // "hourly_interest_rate": "0" // }, // ], // "total_effective_leverage": "0", // "position_limit": "3000000", // "used_position_limit": "0", // "total_borrow": "0", // "margin_score": "0", // "is_liquidating": false, // "has_risk": false, // "terminatable": true // } // ] // } // } // return this.parseBalance(response); } async fetchOrder(id, symbol = undefined, params = {}) { /** * @method * @name cryptocom#fetchOrder * @description fetches information on an order made by the user * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-get-order-detail * @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/#/?id=order-structure} */ await this.loadMarkets(); let market = undefined; if (symbol !== undefined) { market = this.market(symbol); } const request = { 'order_id': id, }; const response = await this.v1PrivatePostPrivateGetOrderDetail(this.extend(request, params)); // // { // "id": 1686872583882, // "method": "private/get-order-detail", // "code": 0, // "result": { // "account_id": "ae075bef-1234-4321-bd6g-bb9007252a63", // "order_id": "6142909895025252686", // "client_oid": "CCXT_c2d2152cc32d40a3ae7fbf", // "order_type": "LIMIT", // "time_in_force": "GOOD_TILL_CANCEL", // "side": "BUY", // "exec_inst": [ ], // "quantity": "0.00020", // "limit_price": "20000.00", // "order_value": "4", // "avg_price": "0", // "trigger_price": "0", // "ref_price": "0", // "cumulative_quantity": "0", // "cumulative_value": "0", // "cumulative_fee": "0", // "status": "ACTIVE", // "update_user_id": "ae075bef-1234-4321-bd6g-bb9007252a63", // "order_date": "2023-06-15", // "instrument_name": "BTC_USD", // "fee_instrument_name": "BTC", // "create_time": 1686870220684, // "create_time_ns": "1686870220684239675", // "update_time": 1686870220684 // } // } // const order = this.safeValue(response, 'result', {}); return this.parseOrder(order, market); } async createOrder(symbol, type, side, amount, price = undefined, params = {}) { /** * @method * @name cryptocom#createOrder * @description create a trade order * @see https://exchange-docs.crypto.com/exchange/v1/rest-ws/index.html#private-create-order * @param {string} symbol unified symbol of the market to create an order in * @param {string} type 'market', 'limit', 'stop_loss', 'stop_limit', 'take_profit', 'take_profit_limit' * @param {string} side 'buy' or 'sell' * @param {float} amount how much you want to trade in units of base currency * @param {float|undefined} price the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders * @param {object} params extra parameters specific to the cryptocom api endpoint * @param {string|undefined} params.timeInForce 'GTC', 'IOC', 'FOK' or 'PO' * @param {string|undefined} params.ref_price_type 'MARK_PRICE', 'INDEX_PRICE', 'LAST_PRICE' which trigger price type to use, default is MARK_PRICE * @param {float|undefined} params.stopPrice price to trigger a stop order * @param {float|undefined} params.stopLossPrice price to trigger a stop-loss trigger order * @param {float|undefined} params.takeProfitPrice price to trigger a take-profit trigger order * @returns {object} an [order structure]{@link https://docs.ccxt.com/#/?id=order-structure} */ await this.loadMarkets(); const market = this.market(symbol); const uppercaseType = type.toUpperCase(); const request = { 'instrument_name': market['id'], 'side': side.toUpperCase(), 'quantity': this.amountToPrecision(symbol, amount), }; if ((uppercaseType === 'LIMIT') || (uppercaseType === 'S