UNPKG

sfccxt

Version:

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

1,072 lines (1,052 loc) 123 kB
'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ArgumentsRequired, AuthenticationError, ExchangeError, InsufficientFunds, OrderNotFound, PermissionDenied, BadRequest, BadSymbol, DDoSProtection, InvalidOrder, AccountSuspended } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- module.exports = class stex extends Exchange { describe () { return this.deepExtend (super.describe (), { 'id': 'stex', 'name': 'STEX', // formerly known as stocks.exchange 'countries': [ 'EE' ], // Estonia 'rateLimit': 1000 / 3, // https://help.stex.com/en/articles/2815043-api-3-rate-limits 'certified': false, // new metainfo interface 'has': { 'CORS': undefined, 'spot': true, 'margin': false, 'swap': false, 'future': false, 'option': false, 'addMargin': false, 'cancelAllOrders': true, 'cancelOrder': true, 'createDepositAddress': true, 'createMarketOrder': false, 'createOrder': true, 'createReduceOnlyOrder': false, 'fetchBalance': true, 'fetchBorrowRate': false, 'fetchBorrowRateHistories': false, 'fetchBorrowRateHistory': false, 'fetchBorrowRates': false, 'fetchBorrowRatesPerSymbol': false, 'fetchClosedOrder': true, 'fetchCurrencies': true, 'fetchDeposit': true, 'fetchDepositAddress': true, 'fetchDeposits': true, 'fetchDepositWithdrawFee': 'emulated', 'fetchDepositWithdrawFees': true, 'fetchFundingHistory': false, 'fetchFundingRate': false, 'fetchFundingRateHistory': false, 'fetchFundingRates': false, 'fetchIndexOHLCV': false, 'fetchLeverage': false, 'fetchLeverageTiers': false, 'fetchMarginMode': false, 'fetchMarkets': true, 'fetchMarkOHLCV': false, 'fetchMyTrades': true, 'fetchOHLCV': true, 'fetchOpenInterestHistory': false, 'fetchOpenOrders': true, 'fetchOrder': true, 'fetchOrderBook': true, 'fetchOrderTrades': true, 'fetchPosition': false, 'fetchPositionMode': false, 'fetchPositions': false, 'fetchPositionsRisk': false, 'fetchPremiumIndexOHLCV': false, 'fetchTicker': true, 'fetchTickers': true, 'fetchTime': true, 'fetchTrades': true, 'fetchTradingFee': true, 'fetchTradingFees': false, 'fetchTransactionFees': true, 'fetchWithdrawal': true, 'fetchWithdrawals': true, 'reduceMargin': false, 'setLeverage': false, 'setMarginMode': false, 'setPositionMode': false, 'transfer': true, 'withdraw': true, }, 'version': 'v3', 'urls': { 'logo': 'https://user-images.githubusercontent.com/1294454/69680782-03fd0b80-10bd-11ea-909e-7f603500e9cc.jpg', 'api': { 'rest': 'https://api3.stex.com', }, 'www': 'https://www.stex.com', 'doc': [ 'https://apidocs.stex.com/', 'https://help.stex.com/en/collections/1593608-api-v3-documentation', ], 'fees': 'https://app.stex.com/en/pairs-specification', 'referral': 'https://app.stex.com?ref=36416021', }, 'requiredCredentials': { 'apiKey': false, 'secret': false, 'token': true, }, 'timeframes': { '1m': '1', '5m': '5', '30m': '30', '1h': '60', '4h': '240', '12h': '720', '1d': '1D', // default }, 'api': { 'public': { 'get': { 'currencies': 1, // Available Currencies 'currencies/{currencyId}': 1, // Get currency info 'markets': 1, // Available markets 'pairs-groups': 1, // Available currency pairs groups (as displayed at stex trading page) 'currency_pairs/list/{code}': 1, // Available currency pairs 'currency_pairs/group/{currencyPairGroupId}': 1, // Available currency pairs for a given group 'currency_pairs/{currencyPairId}': 1, // Get currency pair information 'ticker': 1, // Tickers list for all currency pairs 'ticker/{currencyPairId}': 1, // Ticker for currency pair 'trades/{currencyPairId}': 1, // Trades for given currency pair 'orderbook/{currencyPairId}': 1, // Orderbook for given currency pair 'chart/{currencyPairId}/{candlesType}': 1, // A list of candles for given currency pair 'deposit-statuses': 1, // Available Deposit Statuses 'deposit-statuses/{statusId}': 1, // Get deposit status info 'withdrawal-statuses': 1, // Available Withdrawal Statuses 'withdrawal-statuses/{statusId}': 1, // Get status info 'ping': 1, // Test API is working and get server time 'mobile-versions': 1, // Shows the official mobile applications data 'twitter': 1, // Get the last 20 posts (stex.com) on Twitter }, }, 'trading': { 'get': { 'fees/{currencyPairId}': 1, // Returns the user's fees for a given currency pair 'orders': 12, // List your currently open orders 'orders/{currencyPairId}': 6, // List your currently open orders for given currency pair 'order/{orderId}': 12, // Get a single order }, 'post': { 'orders/{currencyPairId}': 1.5, // Create new order and put it to the orders processing queue 'orders/bulk/{currencyPairId}': 12, // Create new orders in a bulk and put it to the orders processing queue }, 'delete': { 'orders': 30, // Delete all active orders 'orders/{currencyPairId}': 12, // Delete active orders for given currency pair 'order/{orderId}': 1.5, // Cancel order }, }, 'reports': { 'get': { 'currencies': 12, // Get a list of currencies user had any activity in 'currency_pairs': 12, // Gets the list of currency pairs the user had orders in for all the time 'orders': 12, // Get past orders 'orders/{orderId}': 12, // Get specified order details 'trades/{currencyPairId}': 12, // Get a list of user trades according to request parameters 'background/{listMode}': 12, // Get reports list for category 'background/{id}': 12, // Get some report info 'background/download/{id}': 12, // Get file by id }, 'post': { 'background/create': 12, // Create new report }, 'delete': { 'background/{id}': 12, // Remove report by id }, }, 'profile': { 'get': { 'info': 3, // Account information 'wallets': 3, // Get a list of user wallets 'wallets/{walletId}': 3, // Single wallet information 'wallets/address/{walletId}': 3, // Get deposit address for given wallet 'deposits': 3, // Get a list of deposits made by user 'deposits/{id}': 3, // Get deposit by id 'rewards': 3, // Get a list of rewards obtained by user (e.g. in trading competitions) 'rewards/{id}': 3, // Get reward by id 'addressbook': 3, // Get a list of user address book items 'addressbook/{itemId}': 3, // Single address book item 'withdrawals': 3, // Get a list of withdrawals made by user 'withdrawals/{id}': 3, // Get withdrawal by id 'notifications': 3, // Get notifications 'notifications/price': 3, // Get a list of active price alerts 'favorite/currency_pairs': 3, // Get favorite currency pairs 'token-scopes': 3, // Get current token scopes }, 'post': { 'wallets/burn/{walletId}': 3, // Burns the given wallet 'wallets/{walletId}/hold_amount': 3, // Move a part of the funds on the wallet to the "hold" to keep it safe from trading 'wallets/{currencyId}': 3, // Create a wallet for given currency 'wallets/address/{walletId}': 3, // Create new deposit address 'addressbook/disable_item/{itemId}': 3, // Disables the address book item 'addressbook/enable_item/{itemId}': 3, // Enable the address book item 'addressbook/enable_strict_wd': 3, // Restrict the withdrawals to only addresses that are active in addressbook 'addressbook/disable_strict_wd': 3, // Remove restriction to withdraw to only addresses that are active in addressbook. E.g. allow to withdraw to any address. 'withdraw': 30, // Create withdrawal request 'notifications/price': 3, // Create new price alert 'referral/program': 3, // Create referral program 'referral/insert/{code}': 3, // Insert referral code 'referral/bonus_transfer/{currencyId}': 3, // Transfer referral bonuses balance to main balance for given currency }, 'put': { 'favorite/currency_pairs/set': 3, // Set favorite currency pairs }, 'delete': { 'addressbook/{itemId}': 3, // Deletes address book item 'withdraw/{withdrawalId}': 30, // Cancel unconfirmed withdrawal 'notifications/price/{priceAlertId}': 3, // Delete the price alert by ID }, }, 'verification': { 'get': { 'countries': 1, // Countries list, beta 'status': 1, // Get status verify 'fractal/url': 1, // Generate verify url from Fractal 'smart-id': 1, // Check Smart-ID verify 'stex': 1, // Get information about your KYC, beta 'cryptonomica/code': 1, // Get Discount code for Cryptonomica }, 'post': { 'smart-id': 1, // Initialization Smart-ID verify (Send request to Smart-ID App) 'stex': 1, // Update information regarding of your KYC verification, beta 'cryptonomica': 1, // Add verification from Cryptonomica }, }, 'settings': { 'get': { 'notifications/{event}': 1, // User event notification settings 'notifications': 1, // User events notification settings }, 'put': { 'notifications': 1, // Set notification settings 'notifications/set': 1, }, }, }, 'fees': { 'trading': { 'tierBased': false, 'percentage': true, 'taker': this.parseNumber ('0.002'), 'maker': this.parseNumber ('0.002'), }, }, 'commonCurrencies': { 'BC': 'Bitcoin Confidential', 'BITS': 'Bitcoinus', 'BITSW': 'BITS', 'BHD': 'Bithold', 'BTH': 'Bithereum', 'MPH': 'Chasyr Token', 'SBTC': 'SBTCT', // SiamBitcoin }, 'options': { 'parseOrderToPrecision': false, 'networks': { 'ERC20': 5, 'ETH': 5, 'OMNI': 10, 'XLM': 20, 'BEP2': 22, 'TRC20': 24, 'TRX': 24, 'SOL': 25, 'BEP20': 501, }, 'accountsByType': { 'spot': 'spot', 'hold': 'hold', 'funding': 'funding', 'referal': 'referal', }, 'transfer': { 'fillResponseFromRequest': true, }, }, 'precisionMode': TICK_SIZE, 'exceptions': { 'exact': { // {"success":false,"message":"Wrong parameters","errors":{"candleType":["Invalid Candle Type!"]}} // {"success":false,"message":"Wrong parameters","errors":{"time":["timeStart or timeEnd is less then 1"]}} 'Wrong parameters': BadRequest, 'Unauthenticated.': AuthenticationError, // {"message":"Unauthenticated."} 'Server Error': ExchangeError, // { "message": "Server Error" } 'This feature is only enabled for users verifies by Cryptonomica': PermissionDenied, // {"success":false,"message":"This feature is only enabled for users verifies by Cryptonomica"} 'Too Many Attempts.': DDoSProtection, // { "message": "Too Many Attempts." } 'Selected Pair is disabled': BadSymbol, // {"success":false,"message":"Selected Pair is disabled"} 'Invalid scope(s) provided.': PermissionDenied, // { "message": "Invalid scope(s) provided." } 'The maximum amount of open orders with the same price cannot exceed 10': InvalidOrder, // { "success":false,"message":"The maximum amount of open orders with the same price cannot exceed 10" } 'Your account not verified!': AccountSuspended, // {"success":false,"message":"Your account not verified!","unified_message":{"message_id":"verification_required_to_continue","substitutions":null},"notice":"Please be informed that parameter `message` is deprecated and will be removed. Use unified_message instead."} }, 'broad': { 'Not enough': InsufficientFunds, // {"success":false,"message":"Not enough ETH"} }, }, }); } async fetchCurrencies (params = {}) { /** * @method * @name stex#fetchCurrencies * @description fetches all available currencies on an exchange * @param {object} params extra parameters specific to the stex api endpoint * @returns {object} an associative dictionary of currencies */ const response = await this.publicGetCurrencies (params); // // { // "success":true, // "data":[ // { // "id":1, // "code":"BTC", // "name":"Bitcoin", // "active":true, // "delisted":false, // "precision":8, // "minimum_tx_confirmations":1, // "minimum_withdrawal_amount":"0.00200000", // "minimum_deposit_amount":"0.00000000", // "deposit_fee_currency_id":1, // "deposit_fee_currency_code":"BTC", // "deposit_fee_const":"0.00000000", // "deposit_fee_percent":"0.00000000", // "withdrawal_fee_currency_id":1, // "withdrawal_fee_currency_code":"BTC", // "withdrawal_fee_const":"0.00100000", // "withdrawal_fee_percent":"0.00000000", // "block_explorer_url":"https:\/\/blockchain.info\/tx\/", // "protocol_specific_settings":null // }, // ] // } // const result = {}; const currencies = this.safeValue (response, 'data', []); for (let i = 0; i < currencies.length; i++) { const currency = currencies[i]; const id = this.safeString (currency, 'id'); const numericId = this.safeInteger (currency, 'id'); // todo: will need to rethink the fees // to add support for multiple withdrawal/deposit methods and // differentiated fees for each particular method const code = this.safeCurrencyCode (this.safeString (currency, 'code')); const precision = this.parseNumber (this.parsePrecision (this.safeString (currency, 'precision'))); const fee = this.safeNumber (currency, 'withdrawal_fee_const'); // todo: redesign const active = this.safeValue (currency, 'active', true); result[code] = { 'id': id, 'numericId': numericId, 'code': code, 'info': currency, 'type': undefined, 'name': this.safeString (currency, 'name'), 'active': active, 'deposit': undefined, 'withdraw': undefined, 'fee': fee, 'precision': precision, 'limits': { 'amount': { 'min': precision, 'max': undefined, }, 'deposit': { 'min': this.safeNumber (currency, 'minimum_deposit_amount'), 'max': undefined, }, 'withdraw': { 'min': this.safeNumber (currency, 'minimum_withdrawal_amount'), 'max': undefined, }, }, }; } return result; } async fetchMarkets (params = {}) { /** * @method * @name stex#fetchMarkets * @description retrieves data on all markets for stex * @param {object} params extra parameters specific to the exchange api endpoint * @returns {[object]} an array of objects representing market data */ const request = { 'code': 'ALL', }; const response = await this.publicGetCurrencyPairsListCode (this.extend (request, params)); // // { // "success":true, // "data":[ // { // "id":935, // "currency_id":662, // "currency_code":"ABET", // "currency_name":"Altbet", // "market_currency_id":1, // "market_code":"BTC", // "market_name":"Bitcoin", // "min_order_amount":"0.00000010", // "min_buy_price":"0.00000001", // "min_sell_price":"0.00000001", // "buy_fee_percent":"0.20000000", // "sell_fee_percent":"0.20000000", // "active":true, // "delisted":false, // "pair_message":"", // "currency_precision":8, // "market_precision":8, // "symbol":"ABET_BTC", // "group_name":"BTC", // "group_id":1 // } // ] // } // const result = []; const markets = this.safeValue (response, 'data', []); for (let i = 0; i < markets.length; i++) { const market = markets[i]; const id = this.safeString (market, 'id'); const numericId = this.safeInteger (market, 'id'); const baseId = this.safeString (market, 'currency_id'); const quoteId = this.safeString (market, 'market_currency_id'); const baseNumericId = this.safeInteger (market, 'currency_id'); const quoteNumericId = this.safeInteger (market, 'market_currency_id'); const base = this.safeCurrencyCode (this.safeString (market, 'currency_code')); const quote = this.safeCurrencyCode (this.safeString (market, 'market_code')); const minBuyPrice = this.safeString (market, 'min_buy_price'); const minSellPrice = this.safeString (market, 'min_sell_price'); const minPrice = Precise.stringMax (minBuyPrice, minSellPrice); const buyFee = Precise.stringDiv (this.safeString (market, 'buy_fee_percent'), '100'); const sellFee = Precise.stringDiv (this.safeString (market, 'sell_fee_percent'), '100'); const fee = Precise.stringMax (buyFee, sellFee); result.push ({ 'id': id, 'numericId': numericId, 'symbol': base + '/' + quote, 'base': base, 'quote': quote, 'settle': undefined, 'baseId': baseId, 'quoteId': quoteId, 'settleId': undefined, 'baseNumericId': baseNumericId, 'quoteNumericId': quoteNumericId, 'type': 'spot', 'spot': true, 'margin': false, 'swap': false, 'future': false, 'option': false, 'active': this.safeValue (market, 'active'), 'contract': false, 'linear': undefined, 'inverse': undefined, 'taker': fee, 'maker': fee, 'contractSize': undefined, 'expiry': undefined, 'expiryDatetime': undefined, 'strike': undefined, 'optionType': undefined, 'precision': { 'amount': this.parseNumber (this.parsePrecision (this.safeString (market, 'currency_precision'))), 'price': this.parseNumber (this.parsePrecision (this.safeString (market, 'market_precision'))), }, 'limits': { 'leverage': { 'min': undefined, 'max': undefined, }, 'amount': { 'min': this.safeNumber (market, 'min_order_amount'), 'max': undefined, }, 'price': { 'min': minPrice, 'max': undefined, }, 'cost': { 'min': undefined, 'max': undefined, }, }, 'info': market, }); } return result; } async fetchTicker (symbol, params = {}) { /** * @method * @name stex#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 stex 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 = { 'currencyPairId': market['id'], }; const response = await this.publicGetTickerCurrencyPairId (this.extend (request, params)); // // { // "success": true, // "data": { // "id": 2, // "amount_multiplier": 1, // "currency_code": "ETH", // "market_code": "BTC", // "currency_name": "Ethereum", // "market_name": "Bitcoin", // "symbol": "ETH_BTC", // "group_name": "BTC", // "group_id": 1, // "ask": "0.02069998", // "bid": "0.02028622", // "last": "0.02049224", // "open": "0.02059605", // "low": "0.01977744", // "high": "0.02097005", // "volume": "480.43248971", // "volumeQuote": "23491.29826130", // "count": "7384", // "fiatsRate": { // "USD": 7230.86, // "EUR": 6590.79, // "UAH": 173402, // "AUD": 10595.51, // "IDR": 101568085, // "CNY": 50752, // "KRW": 8452295, // "JPY": 784607, // "VND": 167315119, // "INR": 517596, // "GBP": 5607.25, // "CAD": 9602.63, // "BRL": 30472, // "RUB": 460718 // }, // "timestamp": 1574698235601 // } // } // const ticker = this.safeValue (response, 'data', {}); return this.parseTicker (ticker, market); } async fetchTime (params = {}) { /** * @method * @name stex#fetchTime * @description fetches the current integer timestamp in milliseconds from the exchange server * @param {object} params extra parameters specific to the stex api endpoint * @returns {int} the current integer timestamp in milliseconds from the exchange server */ const response = await this.publicGetPing (params); // // { // "success": true, // "data": { // "server_datetime": { // "date": "2019-01-22 15:13:34.233796", // "timezone_type": 3, // "timezone": "UTC" // }, // "server_timestamp": 1548170014 // } // } // const data = this.safeValue (response, 'data', {}); const serverDatetime = this.safeValue (data, 'server_datetime', {}); return this.parse8601 (this.safeString (serverDatetime, 'date')); } async fetchOrderBook (symbol, limit = undefined, params = {}) { /** * @method * @name stex#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 stex 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 = { 'currencyPairId': market['id'], }; if (limit !== undefined) { request['limit_bids'] = limit; // returns all if set to 0, default 100 request['limit_asks'] = limit; // returns all if set to 0, default 100 } const response = await this.publicGetOrderbookCurrencyPairId (this.extend (request, params)); // // { // "success": true, // "data": { // "ask": [ // { "currency_pair_id": 2, "amount": "2.17865373", "price": "0.02062917", "amount2": "0.04494382", "count": 1, "cumulative_amount": 2.17865373 }, // { "currency_pair_id": 2, "amount": "2.27521743", "price": "0.02062918", "amount2": "0.04693587", "count": 1, "cumulative_amount": 4.45387116 }, // { "currency_pair_id": 2, "amount": "1.26980049", "price": "0.02063170", "amount2": "0.02619814", "count": 1, "cumulative_amount": 5.72367165 }, // ], // "bid": [ // { "currency_pair_id": 2, "amount": "0.00978005", "price": "0.02057000", "amount2": "0.00020118", "count": 1, "cumulative_amount": 0.00978005 }, // { "currency_pair_id": 2, "amount": "0.00500000", "price": "0.02056000", "amount2": "0.00010280", "count": 1, "cumulative_amount": 0.01478005 }, // { "currency_pair_id": 2, "amount": "0.77679882", "price": "0.02054001", "amount2": "0.01595546", "count": 1, "cumulative_amount": 0.79157887 }, // ], // "ask_total_amount": 2555.749174609999, // "bid_total_amount": 29.180037330000005 // } // } // const orderbook = this.safeValue (response, 'data', {}); return this.parseOrderBook (orderbook, symbol, undefined, 'bid', 'ask', 'price', 'amount'); } parseTicker (ticker, market = undefined) { // // { // "id": 2, // "amount_multiplier": 1, // "currency_code": "ETH", // "market_code": "BTC", // "currency_name": "Ethereum", // "market_name": "Bitcoin", // "symbol": "ETH_BTC", // "group_name": "BTC", // "group_id": 1, // "ask": "0.02069998", // "bid": "0.02028622", // "last": "0.02049224", // "open": "0.02059605", // "low": "0.01977744", // "high": "0.02097005", // "volume": "480.43248971", // "volumeQuote": "23491.29826130", // "count": "7384", // "fiatsRate": { // "USD": 7230.86, // "EUR": 6590.79, // "UAH": 173402, // "AUD": 10595.51, // "IDR": 101568085, // "CNY": 50752, // "KRW": 8452295, // "JPY": 784607, // "VND": 167315119, // "INR": 517596, // "GBP": 5607.25, // "CAD": 9602.63, // "BRL": 30472, // "RUB": 460718 // }, // "timestamp": 1574698235601 // } // const timestamp = this.safeInteger (ticker, 'timestamp'); const marketId = this.safeString2 (ticker, 'id', 'symbol'); const symbol = this.safeSymbol (marketId, market, '_'); const last = this.safeString (ticker, 'last'); const open = this.safeString (ticker, 'open'); 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, 'bid'), 'bidVolume': undefined, 'ask': this.safeString (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': open, 'close': last, 'last': last, 'previousClose': undefined, // previous day close 'change': undefined, 'percentage': undefined, 'average': undefined, 'baseVolume': this.safeString (ticker, 'volumeQuote'), 'quoteVolume': this.safeString (ticker, 'volume'), 'info': ticker, }, market); } async fetchTickers (symbols = undefined, params = {}) { /** * @method * @name stex#fetchTickers * @description fetches price tickers for multiple markets, statistical calculations with the information calculated over the past 24 hours each market * @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 stex api endpoint * @returns {object} an array of [ticker structures]{@link https://docs.ccxt.com/en/latest/manual.html#ticker-structure} */ await this.loadMarkets (); const response = await this.publicGetTicker (params); // // { // "success":true, // "data":[ // { // "id":262, // "amount_multiplier":1, // "currency_code":"ARDR", // "market_code":"BTC", // "currency_name":"ARDOR", // "market_name":"Bitcoin", // "symbol":"ARDR_BTC", // "group_name":"BTC", // "group_id":1, // "ask":"0.00000630", // "bid":"0.00000613", // "last":"0.00000617", // "open":"0.00000620", // "low":"0.00000614", // "high":"0.00000630", // "volume":"30.37795305", // "volumeQuote":"4911487.01996544", // "count":"710", // "fiatsRate":{ // "USD":7230.86, // "EUR":6590.79, // "UAH":173402, // "AUD":10744.52, // "IDR":101568085, // "CNY":50752, // "KRW":8452295, // "JPY":784607, // "VND":167315119, // "INR":517596, // "GBP":5607.25, // "CAD":9602.63, // "BRL":30472, // "RUB":467358 // }, // "timestamp":1574698617304, // "group_position":1 // }, // ] // } // const tickers = this.safeValue (response, 'data', []); return this.parseTickers (tickers, symbols); } parseOHLCV (ohlcv, market = undefined) { // // { // "time": 1566086400000, // "close": 0.01895, // "open": 0.01812427, // "high": 0.0191588, // "low": 0.01807001, // "volume": 2588.597813750006 // } // return [ this.safeInteger (ohlcv, 'time'), this.safeNumber (ohlcv, 'open'), this.safeNumber (ohlcv, 'high'), this.safeNumber (ohlcv, 'low'), this.safeNumber (ohlcv, 'close'), this.safeNumber (ohlcv, 'volume'), ]; } async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { /** * @method * @name stex#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 stex 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 = { 'currencyPairId': market['id'], 'candlesType': this.timeframes[timeframe], // default 1d // 'timeStart': 1574709092, // unix timestamp in seconds, required // 'timeEnd': 1574709092, // unix timestamp in seconds, required // 'limit': 100, // default 100, optional // 'offset' 100, // optional, pagination within timerange }; if (limit === undefined) { limit = 100; } else { request['limit'] = limit; } const duration = this.parseTimeframe (timeframe); const timerange = limit * duration; if (since === undefined) { request['timeEnd'] = this.seconds (); request['timeStart'] = request['timeEnd'] - timerange; } else { request['timeStart'] = parseInt (since / 1000); request['timeEnd'] = this.sum (request['timeStart'], timerange); } const response = await this.publicGetChartCurrencyPairIdCandlesType (this.extend (request, params)); // // { // "success": true, // "data": [ // { // "time": 1566086400000, // "close": 0.01895, // "open": 0.01812427, // "high": 0.0191588, // "low": 0.01807001, // "volume": 2588.597813750006 // }, // ] // } // const data = this.safeValue (response, 'data', []); return this.parseOHLCVs (data, market, timeframe, since, limit); } parseTrade (trade, market = undefined) { // // public fetchTrades // // { // "id": 35989317, // "price": "0.02033813", // "amount": "3.60000000", // "type": "BUY", // "timestamp": "1574713503" // } // // private fetchMyTrades, fetchClosedOrder, fetchOrderTrades // // { // "id": 658745, // "buy_order_id": 6587453, // "sell_order_id": 6587459, // "price": 0.012285, // "amount": 6.35, // "trade_type": "SELL", // "timestamp": "1538737692" // } // const id = this.safeString (trade, 'id'); const timestamp = this.safeTimestamp (trade, 'timestamp'); const priceString = this.safeString (trade, 'price'); const amountString = this.safeString (trade, 'amount'); let symbol = undefined; if ((symbol === undefined) && (market !== undefined)) { symbol = market['symbol']; } const side = this.safeStringLower2 (trade, 'type', 'trade_type'); return this.safeTrade ({ 'info': trade, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'symbol': symbol, 'id': id, 'order': undefined, 'type': undefined, 'takerOrMaker': undefined, 'side': side, 'price': priceString, 'amount': amountString, 'cost': undefined, 'fee': undefined, }, market); } async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { /** * @method * @name stex#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 stex 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 = { 'currencyPairId': market['id'], // 'sort': 'ASC', // ASC or DESC, default DESC // 'from': 1574709092, // unix timestamp, optional // 'till': 1574709092, // unix timestamp, optional // 'limit': 100, // default 100, optional // 'offset': 100, // optional }; if (limit !== undefined) { request['limit'] = limit; // currently limited to 100 or fewer } if (since !== undefined) { request['sort'] = 'ASC'; // needed to make the from param work request['from'] = parseInt (since / 1000); } const response = await this.publicGetTradesCurrencyPairId (this.extend (request, params)); // // { // "success": true, // "data": [ // { // "id": 35989317, // "price": "0.02033813", // "amount": "3.60000000", // "type": "BUY", // "timestamp": "1574713503" // }, // ] // } // const trades = this.safeValue (response, 'data', []); return this.parseTrades (trades, market, since, limit); } async fetchTradingFee (symbol, params = {}) { /** * @method * @name stex#fetchTradingFee * @description fetch the trading fees for a market * @param {string} symbol unified market symbol * @param {object} params extra parameters specific to the stex 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 = { 'currencyPairId': market['id'], }; const response = await this.tradingGetFeesCurrencyPairId (this.extend (request, params)); // // { // success: true, // data: { buy_fee: '0.00200000', sell_fee: '0.00200000' }, // unified_message: { message_id: 'operation_successful', substitutions: [] } // } // const data = this.safeValue (response, 'data'); return { 'info': response, 'symbol': market['symbol'], 'maker': this.safeNumber (data, 'sell_fee'), 'taker': this.safeNumber (data, 'buy_fee'), 'percentage': true, 'tierBased': true, }; } parseBalance (response) { const result = { 'info': response, 'timestamp': undefined, 'datetime': undefined, }; const balances = this.safeValue (response, 'data', []); for (let i = 0; i < balances.length; i++) { const balance = balances[i]; const code = this.safeCurrencyCode (this.safeString (balance, 'currency_id')); const account = this.account (); account['free'] = this.safeString (balance, 'balance'); account['used'] = this.safeString (balance, 'frozen_balance'); result[code] = account; } return this.safeBalance (result); } async fetchBalance (params = {}) { /** * @method * @name stex#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 stex api endpoint * @returns {object} a [balance structure]{@link https://docs.ccxt.com/en/latest/manual.html?#balance-structure} */ await this.loadMarkets (); // await this.loadAccounts (); const response = await this.profileGetWallets (params); // // { // "success": true, // "data": [ // { // "id": null, // "currency_id": 665, // "delisted": false, // "disabled": false, // "disable_deposits": false, // "currency_code": "ORM", // "currency_name": "Orium", // "currency_type_id": 5, // "balance": "0", // "frozen_balance": "0", // "bonus_balance": "0", // "total_balance": "0", // "protocol_specific_settings": null, // "rates": { "BTC": "0.00000000020", "USD": "0.00000147" }, // }, // { // "id": null, // "currency_id": 272, // "delisted": false, // "disabled": false, // "disable_deposits": false, // "currency_code": "USDT", // "currency_name": "TetherUSD", // "currency_type_id": 23, // "balance": "0", // "frozen_balance": "0", // "bonus_balance": "0", // "total_balance": "0", // "protocol_specific_settings": [ // { "protocol_name": "OMNI", "protocol_id": 10, "active": true, "withdrawal_fee_currency_id": 272, "withdrawal_fee_const": 10, "withdrawal_fee_percent": 0, "block_explorer_url": "https://omniexplorer.info/search/" }, // { "protocol_name": "ERC20", "protocol_id": 5, "active": true, "withdrawal_fee_const": 1.2, "withdrawal_fee_percent": 0, "block_explorer_url": "https://etherscan.io/tx/" }, // { "protocol_name": "TRON", "protocol_id": 24, "active": true, "withdrawal_fee_currency_id": 272, "withdrawal_fee_const": 0.2, "withdrawal_fee_percent": 0, "block_explorer_url": "https://tronscan.org/#/transaction/" } // ], // "rates": { "BTC": "0.00013893", "USD": "1" }, // }, // ] // } // return this.parseBalance (response); } parseOrderStatus (status) { const statuses = { 'PROCESSING': 'open', 'PENDING': 'open', 'PARTIAL': 'open', 'FINISHED': 'closed', 'CANCELLED': 'canceled', }; return this.safeString (statuses, status, status); } parseOrder (order, market = undefined) { // // createOrder, fetchOpenOrders, fetchClosedOrders, cancelOrder, fetchOrder, fetchClosedOrder // // { // "id": 828680665, // "currency_pair_id": 1, // "currency_pair_name": "NXT_BTC", // "price": "0.011384", // "trigger_price": 0.011385, // "initial_amount": "13.942", // "processed_amount": "3.724", // missing in fetchClosedOrder // "type": "SELL", // "original_type": "STOP_LIMIT_SELL", // "created": "2019-01-17 10:14:48", // "timestamp": "1547720088", // "status": "PARTIAL" // // fetchClosedOrder only //