UNPKG

preidman-ccxt

Version:

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

1,102 lines (1,072 loc) 54.3 kB
'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, AuthenticationError, InvalidOrder, InvalidAddress, InsufficientFunds, OrderNotFound, PermissionDenied } = require ('./base/errors'); // --------------------------------------------------------------------------- module.exports = class uex extends Exchange { describe () { return this.deepExtend (super.describe (), { 'id': 'uex', 'name': 'UEX', 'countries': [ 'SG', 'US' ], 'version': 'v1.0.3', 'rateLimit': 1000, 'certified': false, // new metainfo interface 'has': { 'CORS': false, 'fetchMyTrades': true, 'fetchOHLCV': true, 'fetchOrder': true, 'fetchOpenOrders': true, 'fetchClosedOrders': true, 'fetchDepositAddress': true, 'fetchDeposits': true, 'fetchWithdrawals': true, 'withdraw': true, }, 'timeframes': { '1m': '1', '5m': '5', '15m': '15', '30m': '30', '1h': '60', '2h': '120', '3h': '180', '4h': '240', '6h': '360', '12h': '720', '1d': '1440', }, 'urls': { 'logo': 'https://user-images.githubusercontent.com/1294454/43999923-051d9884-9e1f-11e8-965a-76948cb17678.jpg', 'api': 'https://open-api.uex.com/open/api', 'www': 'https://www.uex.com', 'doc': 'https://download.uex.com/doc/UEX-API-English-1.0.3.pdf', 'fees': 'https://www.uex.com/footer/ufees.html', 'referral': 'https://www.uex.com/signup.html?code=VAGQLL', }, 'api': { 'public': { 'get': [ 'common/coins', // funding limits 'common/symbols', 'get_records', // ohlcvs 'get_ticker', 'get_trades', 'market_dept', // dept here is not a typo... they mean depth ], }, 'private': { 'get': [ 'deposit_address_list', 'withdraw_address_list', 'deposit_history', 'withdraw_history', 'user/account', 'market', // an assoc array of market ids to corresponding prices traded most recently (prices of last trades per market) 'order_info', 'new_order', // a list of currently open orders 'all_order', 'all_trade', ], 'post': [ 'create_order', 'cancel_order', 'create_withdraw', ], }, }, 'fees': { 'trading': { 'tierBased': false, 'percentage': true, 'maker': 0.0010, 'taker': 0.0010, }, }, 'exceptions': { // descriptions from ↓ exchange // '0': 'no error', // succeed '4': InsufficientFunds, // {"code":"4","msg":"余额不足:0E-16","data":null} '5': InvalidOrder, // fail to order {"code":"5","msg":"Price fluctuates more than1000.0%","data":null} '6': InvalidOrder, // the quantity value less than the minimum one {"code":"6","msg":"数量小于最小值:0.001","data":null} '7': InvalidOrder, // the quantity value more than the maximum one {"code":"7","msg":"数量大于最大值:10000","data":null} '8': InvalidOrder, // fail to cancel order '9': ExchangeError, // transaction be frozen '13': ExchangeError, // Sorry, the program made an error, please contact with the manager. '19': InsufficientFunds, // Available balance is insufficient. '22': OrderNotFound, // The order does not exist. {"code":"22","msg":"not exist order","data":null} '23': InvalidOrder, // Lack of parameters of numbers of transaction '24': InvalidOrder, // Lack of parameters of transaction price '100001': ExchangeError, // System is abnormal '100002': ExchangeNotAvailable, // Update System '100004': ExchangeError, // {"code":"100004","msg":"request parameter illegal","data":null} '100005': AuthenticationError, // {"code":"100005","msg":"request sign illegal","data":null} '100007': PermissionDenied, // illegal IP '110002': ExchangeError, // unknown currency code '110003': AuthenticationError, // fund password error '110004': AuthenticationError, // fund password error '110005': InsufficientFunds, // Available balance is insufficient. '110020': AuthenticationError, // Username does not exist. '110023': AuthenticationError, // Phone number is registered. '110024': AuthenticationError, // Email box is registered. '110025': PermissionDenied, // Account is locked by background manager '110032': PermissionDenied, // The user has no authority to do this operation. '110033': ExchangeError, // fail to recharge '110034': ExchangeError, // fail to withdraw '-100': ExchangeError, // {"code":"-100","msg":"Your request path is not exist or you can try method GET/POST.","data":null} '-1000': ExchangeNotAvailable, // {"msg":"System maintenance!","code":"-1000","data":null} }, 'requiredCredentials': { 'apiKey': true, 'secret': true, }, 'options': { 'createMarketBuyOrderRequiresPrice': true, 'limits': { 'BTC/USDT': { 'amount': { 'min': 0.001 }, 'price': { 'min': 0.01 }}, 'ETH/USDT': { 'amount': { 'min': 0.001 }, 'price': { 'min': 0.01 }}, 'BCH/USDT': { 'amount': { 'min': 0.001 }, 'price': { 'min': 0.01 }}, 'ETH/BTC': { 'amount': { 'min': 0.001 }, 'price': { 'min': 0.000001 }}, 'BCH/BTC': { 'amount': { 'min': 0.001 }, 'price': { 'min': 0.000001 }}, 'LEEK/ETH': { 'amount': { 'min': 10 }, 'price': { 'min': 10 }}, 'CTXC/ETH': { 'amount': { 'min': 10 }, 'price': { 'min': 10 }}, 'COSM/ETH': { 'amount': { 'min': 10 }, 'price': { 'min': 10 }}, 'MANA/ETH': { 'amount': { 'min': 10 }, 'price': { 'min': 10 }}, 'LBA/BTC': { 'amount': { 'min': 10 }, 'price': { 'min': 10 }}, 'OLT/ETH': { 'amount': { 'min': 10 }, 'price': { 'min': 10 }}, 'DTA/ETH': { 'amount': { 'min': 10 }, 'price': { 'min': 10 }}, 'KNT/ETH': { 'amount': { 'min': 10 }, 'price': { 'min': 10 }}, 'REN/ETH': { 'amount': { 'min': 10 }, 'price': { 'min': 10 }}, 'LBA/ETH': { 'amount': { 'min': 10 }, 'price': { 'min': 10 }}, 'EXC/ETH': { 'amount': { 'min': 10 }, 'price': { 'min': 10 }}, 'ZIL/ETH': { 'amount': { 'min': 10 }, 'price': { 'min': 10 }}, 'RATING/ETH': { 'amount': { 'min': 100 }, 'price': { 'min': 100 }}, 'CENNZ/ETH': { 'amount': { 'min': 10 }, 'price': { 'min': 10 }}, 'TTC/ETH': { 'amount': { 'min': 10 }, 'price': { 'min': 10 }}, }, }, }); } calculateFee (symbol, type, side, amount, price, takerOrMaker = 'taker', params = {}) { let market = this.markets[symbol]; let key = 'quote'; let rate = market[takerOrMaker]; let cost = parseFloat (this.costToPrecision (symbol, amount * rate)); if (side === 'sell') { cost *= price; } else { key = 'base'; } return { 'type': takerOrMaker, 'currency': market[key], 'rate': rate, 'cost': parseFloat (this.currencyToPrecision (market[key], cost)), }; } async fetchMarkets (params = {}) { let response = await this.publicGetCommonSymbols (); // // { code: "0", // msg: "suc", // data: [ { symbol: "btcusdt", // count_coin: "usdt", // amount_precision: 3, // base_coin: "btc", // price_precision: 2 }, // { symbol: "ethusdt", // count_coin: "usdt", // amount_precision: 3, // base_coin: "eth", // price_precision: 2 }, // { symbol: "ethbtc", // count_coin: "btc", // amount_precision: 3, // base_coin: "eth", // price_precision: 6 }]} // let result = []; let markets = response['data']; for (let i = 0; i < markets.length; i++) { let market = markets[i]; let id = market['symbol']; let baseId = market['base_coin']; let quoteId = market['count_coin']; let base = baseId.toUpperCase (); let quote = quoteId.toUpperCase (); base = this.commonCurrencyCode (base); quote = this.commonCurrencyCode (quote); let symbol = base + '/' + quote; let precision = { 'amount': market['amount_precision'], 'price': market['price_precision'], }; let active = true; let defaultLimits = this.safeValue (this.options['limits'], symbol, {}); let limits = this.deepExtend ({ 'amount': { 'min': undefined, 'max': undefined, }, 'price': { 'min': undefined, 'max': undefined, }, 'cost': { 'min': undefined, 'max': undefined, }, }, defaultLimits); result.push ({ 'id': id, 'symbol': symbol, 'base': base, 'quote': quote, 'baseId': baseId, 'quoteId': quoteId, 'active': active, 'info': market, 'precision': precision, 'limits': limits, }); } return result; } async fetchBalance (params = {}) { await this.loadMarkets (); let response = await this.privateGetUserAccount (params); // // { code: "0", // msg: "suc", // data: { total_asset: "0.00000000", // coin_list: [ { normal: "0.00000000", // btcValuatin: "0.00000000", // locked: "0.00000000", // coin: "usdt" }, // { normal: "0.00000000", // btcValuatin: "0.00000000", // locked: "0.00000000", // coin: "btc" }, // { normal: "0.00000000", // btcValuatin: "0.00000000", // locked: "0.00000000", // coin: "eth" }, // { normal: "0.00000000", // btcValuatin: "0.00000000", // locked: "0.00000000", // coin: "ren" }]}} // let balances = response['data']['coin_list']; let result = { 'info': balances }; for (let i = 0; i < balances.length; i++) { let balance = balances[i]; let currencyId = balance['coin']; let code = currencyId.toUpperCase (); if (currencyId in this.currencies_by_id) { code = this.currencies_by_id[currencyId]['code']; } else { code = this.commonCurrencyCode (code); } let account = this.account (); let free = parseFloat (balance['normal']); let used = parseFloat (balance['locked']); let total = this.sum (free, used); account['free'] = free; account['used'] = used; account['total'] = total; result[code] = account; } return this.parseBalance (result); } async fetchOrderBook (symbol, limit = undefined, params = {}) { await this.loadMarkets (); let response = await this.publicGetMarketDept (this.extend ({ 'symbol': this.marketId (symbol), 'type': 'step0', // step1, step2 from most detailed to least detailed }, params)); // // { code: "0", // msg: "suc", // data: { tick: { asks: [ ["0.05824200", 9.77], // ["0.05830000", 7.81], // ["0.05832900", 8.59], // ["0.10000000", 0.001] ], // bids: [ ["0.05780000", 8.25], // ["0.05775000", 8.12], // ["0.05773200", 8.57], // ["0.00010000", 0.79] ], // time: 1533412622463 } } } // let timestamp = this.safeInteger (response['data']['tick'], 'time'); return this.parseOrderBook (response['data']['tick'], timestamp); } parseTicker (ticker, market = undefined) { // // { code: "0", // msg: "suc", // data: { symbol: "ETHBTC", // high: 0.058426, // vol: 19055.875, // last: 0.058019, // low: 0.055802, // change: 0.03437271, // buy: "0.05780000", // sell: "0.05824200", // time: 1533413083184 } } // let timestamp = this.safeInteger (ticker, 'time'); let symbol = undefined; if (market === undefined) { let marketId = this.safeString (ticker, 'symbol'); marketId = marketId.toLowerCase (); if (marketId in this.markets_by_id) { market = this.markets_by_id[marketId]; } } if (market !== undefined) { symbol = market['symbol']; } let last = this.safeFloat (ticker, 'last'); let change = this.safeFloat (ticker, 'change'); let percentage = change * 100; return { 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': this.safeFloat (ticker, 'high'), 'low': this.safeFloat (ticker, 'low'), 'bid': this.safeFloat (ticker, 'buy'), 'bidVolume': undefined, 'ask': this.safeFloat (ticker, 'sell'), 'askVolume': undefined, 'vwap': undefined, 'open': undefined, 'close': last, 'last': last, 'previousClose': undefined, 'change': undefined, 'percentage': percentage, 'average': undefined, 'baseVolume': this.safeFloat (ticker, 'vol'), 'quoteVolume': undefined, 'info': ticker, }; } async fetchTicker (symbol, params = {}) { await this.loadMarkets (); let market = this.market (symbol); let response = await this.publicGetGetTicker (this.extend ({ 'symbol': market['id'], }, params)); // // { code: "0", // msg: "suc", // data: { symbol: "ETHBTC", // high: 0.058426, // vol: 19055.875, // last: 0.058019, // low: 0.055802, // change: 0.03437271, // buy: "0.05780000", // sell: "0.05824200", // time: 1533413083184 } } // return this.parseTicker (response['data'], market); } parseTrade (trade, market = undefined) { // // public fetchTrades // // { amount: 0.88, // create_time: 1533414358000, // price: 0.058019, // id: 406531, // type: "sell" }, // // private fetchMyTrades, fetchOrder, fetchOpenOrders, fetchClosedOrders // // { volume: "0.010", // side: "SELL", // feeCoin: "BTC", // price: "0.05816200", // fee: "0.00000029", // ctime: 1533616674000, // deal_price: "0.00058162", // id: 415779, // type: "卖出", // bid_id: 3669539, // only in fetchMyTrades // ask_id: 3669583, // only in fetchMyTrades // } // let timestamp = this.safeInteger2 (trade, 'create_time', 'ctime'); if (timestamp === undefined) { let timestring = this.safeString (trade, 'created_at'); if (timestring !== undefined) { timestamp = this.parse8601 ('2018-' + timestring + ':00Z'); } } let side = this.safeString2 (trade, 'side', 'type'); if (side !== undefined) { side = side.toLowerCase (); } let id = this.safeString (trade, 'id'); let symbol = undefined; if (market !== undefined) { symbol = market['symbol']; } let price = this.safeFloat (trade, 'price'); let amount = this.safeFloat2 (trade, 'volume', 'amount'); let cost = this.safeFloat (trade, 'deal_price'); if (cost === undefined) { if (amount !== undefined) { if (price !== undefined) { cost = amount * price; } } } let fee = undefined; let feeCost = this.safeFloat2 (trade, 'fee', 'deal_fee'); if (feeCost !== undefined) { let feeCurrency = this.safeString (trade, 'feeCoin'); if (feeCurrency !== undefined) { let currencyId = feeCurrency.toLowerCase (); if (currencyId in this.currencies_by_id) { feeCurrency = this.currencies_by_id[currencyId]['code']; } } fee = { 'cost': feeCost, 'currency': feeCurrency, }; } let orderIdField = (side === 'sell') ? 'ask_id' : 'bid_id'; let orderId = this.safeString (trade, orderIdField); return { 'id': id, 'info': trade, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'symbol': symbol, 'order': orderId, 'type': undefined, 'side': side, 'price': price, 'amount': amount, 'cost': cost, 'fee': fee, }; } async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) { await this.loadMarkets (); let market = this.market (symbol); let response = await this.publicGetGetTrades (this.extend ({ 'symbol': market['id'], }, params)); // // { code: "0", // msg: "suc", // data: [ { amount: 0.88, // create_time: 1533414358000, // price: 0.058019, // id: 406531, // type: "sell" }, // { amount: 4.88, // create_time: 1533414331000, // price: 0.058019, // id: 406530, // type: "buy" }, // { amount: 0.5, // create_time: 1533414311000, // price: 0.058019, // id: 406529, // type: "sell" } ] } // return this.parseTrades (response['data'], market, since, limit); } parseOHLCV (ohlcv, market = undefined, timeframe = '1d', since = undefined, limit = undefined) { return [ ohlcv[0] * 1000, // timestamp ohlcv[1], // open ohlcv[2], // high ohlcv[3], // low ohlcv[4], // close ohlcv[5], // volume ]; } async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { await this.loadMarkets (); let market = this.market (symbol); let request = { 'symbol': market['id'], 'period': this.timeframes[timeframe], // in minutes }; let response = await this.publicGetGetRecords (this.extend (request, params)); // // { code: '0', // msg: 'suc', // data: // [ [ 1533402420, 0.057833, 0.057833, 0.057833, 0.057833, 18.1 ], // [ 1533402480, 0.057833, 0.057833, 0.057833, 0.057833, 29.88 ], // [ 1533402540, 0.057833, 0.057833, 0.057833, 0.057833, 29.06 ] ] } // return this.parseOHLCVs (response['data'], market, timeframe, since, limit); } async createOrder (symbol, type, side, amount, price = undefined, params = {}) { if (type === 'market') { // for market buy it requires the amount of quote currency to spend if (side === 'buy') { if (this.options['createMarketBuyOrderRequiresPrice']) { if (price === undefined) { throw new InvalidOrder (this.id + " createOrder() requires the price argument with market buy orders to calculate total order cost (amount to spend), where cost = amount * price. Supply a price argument to createOrder() call if you want the cost to be calculated for you from price and amount, or, alternatively, add .options['createMarketBuyOrderRequiresPrice'] = false to supply the cost in the amount argument (the exchange-specific behaviour)"); } else { amount = amount * price; } } } } await this.loadMarkets (); let market = this.market (symbol); let orderType = (type === 'limit') ? '1' : '2'; let orderSide = side.toUpperCase (); let amountToPrecision = this.amountToPrecision (symbol, amount); let request = { 'side': orderSide, 'type': orderType, 'symbol': market['id'], 'volume': amountToPrecision, // An excerpt from their docs: // side required Trading Direction // type required pending order types,1:Limit-price Delegation 2:Market- price Delegation // volume required // Purchase Quantity(polysemy,multiplex field) // type=1: Quantity of buying and selling // type=2: Buying represents gross price, and selling represents total number // Trading restriction user/me-user information // price optional Delegation Price:type=2:this parameter is no use. // fee_is_user_exchange_coin optional // 0,when making transactions with all platform currencies, // this parameter represents whether to use them to pay // fees or not and 0 is no, 1 is yes. }; let priceToPrecision = undefined; if (type === 'limit') { priceToPrecision = this.priceToPrecision (symbol, price); request['price'] = priceToPrecision; } let response = await this.privatePostCreateOrder (this.extend (request, params)); // // { code: '0', // msg: 'suc', // data: { 'order_id' : 34343 } } // let result = this.parseOrder (response['data'], market); return this.extend (result, { 'info': response, 'symbol': symbol, 'type': type, 'side': side, 'status': 'open', 'price': parseFloat (priceToPrecision), 'amount': parseFloat (amountToPrecision), }); } async cancelOrder (id, symbol = undefined, params = {}) { await this.loadMarkets (); let market = this.market (symbol); let request = { 'order_id': id, 'symbol': market['id'], }; let response = await this.privatePostCancelOrder (this.extend (request, params)); let order = this.safeValue (response, 'data', {}); return this.extend (this.parseOrder (order), { 'id': id, 'symbol': symbol, 'status': 'canceled', }); } parseOrderStatus (status) { let statuses = { '0': 'open', // INIT(0,"primary order,untraded and not enter the market") '1': 'open', // NEW_(1,"new order,untraded and enter the market ") '2': 'closed', // FILLED(2,"complete deal") '3': 'open', // PART_FILLED(3,"partial deal") '4': 'canceled', // CANCELED(4,"already withdrawn") '5': 'canceled', // PENDING_CANCEL(5,"pending withdrawak") '6': 'canceled', // EXPIRED(6,"abnormal orders") }; if (status in statuses) { return statuses[status]; } return status; } parseOrder (order, market = undefined) { // // createOrder // // {"order_id":34343} // // fetchOrder, fetchOpenOrders, fetchClosedOrders // // { side: "BUY", // total_price: "0.10000000", // created_at: 1510993841000, // avg_price: "0.10000000", // countCoin: "btc", // source: 1, // type: 1, // side_msg: "买入", // volume: "1.000", // price: "0.10000000", // source_msg: "WEB", // status_msg: "完全成交", // deal_volume: "1.00000000", // id: 424, // remain_volume: "0.00000000", // baseCoin: "eth", // tradeList: [ { volume: "1.000", // feeCoin: "YLB", // price: "0.10000000", // fee: "0.16431104", // ctime: 1510996571195, // deal_price: "0.10000000", // id: 306, // type: "买入" } ], // status: 2 } // // fetchOrder // // { trade_list: [ { volume: "0.010", // feeCoin: "BTC", // price: "0.05816200", // fee: "0.00000029", // ctime: 1533616674000, // deal_price: "0.00058162", // id: 415779, // type: "卖出" } ], // order_info: { side: "SELL", // total_price: "0.010", // created_at: 1533616673000, // avg_price: "0.05816200", // countCoin: "btc", // source: 3, // type: 2, // side_msg: "卖出", // volume: "0.010", // price: "0.00000000", // source_msg: "API", // status_msg: "完全成交", // deal_volume: "0.01000000", // id: 3669583, // remain_volume: "0.00000000", // baseCoin: "eth", // tradeList: [ { volume: "0.010", // feeCoin: "BTC", // price: "0.05816200", // fee: "0.00000029", // ctime: 1533616674000, // deal_price: "0.00058162", // id: 415779, // type: "卖出" } ], // status: 2 } } // let side = this.safeString (order, 'side'); if (side !== undefined) side = side.toLowerCase (); let status = this.parseOrderStatus (this.safeString (order, 'status')); let symbol = undefined; if (market === undefined) { let baseId = this.safeString (order, 'baseCoin'); let quoteId = this.safeString (order, 'countCoin'); let marketId = baseId + quoteId; if (marketId in this.markets_by_id) { market = this.markets_by_id[marketId]; } else { if ((baseId !== undefined) && (quoteId !== undefined)) { let base = baseId.toUpperCase (); let quote = quoteId.toUpperCase (); base = this.commonCurrencyCode (base); quote = this.commonCurrencyCode (quote); symbol = base + '/' + quote; } } } if (market !== undefined) { symbol = market['symbol']; } let timestamp = this.safeInteger (order, 'created_at'); if (timestamp === undefined) { let timestring = this.safeString (order, 'created_at'); if (timestring !== undefined) { timestamp = this.parse8601 ('2018-' + timestring + ':00Z'); } } let lastTradeTimestamp = undefined; let fee = undefined; let average = this.safeFloat (order, 'avg_price'); let price = this.safeFloat (order, 'price'); if (price === 0) { price = average; } let amount = this.safeFloat (order, 'volume'); let filled = this.safeFloat (order, 'deal_volume'); let remaining = this.safeFloat (order, 'remain_volume'); let cost = this.safeFloat (order, 'total_price'); let id = this.safeString2 (order, 'id', 'order_id'); let trades = undefined; let tradeList = this.safeValue (order, 'tradeList', []); let feeCurrencies = {}; let feeCost = undefined; for (let i = 0; i < tradeList.length; i++) { let trade = this.parseTrade (tradeList[i], market); if (feeCost === undefined) { feeCost = 0; } feeCost = feeCost + trade['fee']['cost']; let tradeFeeCurrency = trade['fee']['currency']; feeCurrencies[tradeFeeCurrency] = trade['fee']['cost']; if (trades === undefined) { trades = []; } lastTradeTimestamp = trade['timestamp']; trades.push (this.extend (trade, { 'order': id, })); } if (feeCost !== undefined) { let feeCurrency = undefined; let keys = Object.keys (feeCurrencies); let numCurrencies = keys.length; if (numCurrencies === 1) { feeCurrency = keys[0]; } fee = { 'cost': feeCost, 'currency': feeCurrency, }; } let result = { 'info': order, 'id': id, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'lastTradeTimestamp': lastTradeTimestamp, 'symbol': symbol, 'type': 'limit', 'side': side, 'price': price, 'cost': cost, 'average': average, 'amount': amount, 'filled': filled, 'remaining': remaining, 'status': status, 'fee': fee, 'trades': trades, }; return result; } async fetchOrdersWithMethod (method, symbol = undefined, since = undefined, limit = undefined, params = {}) { if (symbol === undefined) { throw new ArgumentsRequired (this.id + ' fetchOrdersWithMethod() requires a symbol argument'); } await this.loadMarkets (); let market = this.market (symbol); let request = { // pageSize optional page size // page optional page number 'symbol': market['id'], }; if (limit !== undefined) { request['pageSize'] = limit; } let response = await this[method] (this.extend (request, params)); // // { code: "0", // msg: "suc", // data: { count: 1, // orderList: [ { side: "SELL", // total_price: "0.010", // created_at: 1533616673000, // avg_price: "0.05816200", // countCoin: "btc", // source: 3, // type: 2, // side_msg: "卖出", // volume: "0.010", // price: "0.00000000", // source_msg: "API", // status_msg: "完全成交", // deal_volume: "0.01000000", // id: 3669583, // remain_volume: "0.00000000", // baseCoin: "eth", // tradeList: [ { volume: "0.010", // feeCoin: "BTC", // price: "0.05816200", // fee: "0.00000029", // ctime: 1533616674000, // deal_price: "0.00058162", // id: 415779, // type: "卖出" } ], // status: 2 } ] } } // // privateGetNewOrder returns resultList, privateGetAllOrder returns orderList let orders = this.safeValue2 (response['data'], 'orderList', 'resultList', []); return this.parseOrders (orders, market, since, limit); } async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { return this.fetchOrdersWithMethod ('privateGetNewOrder', symbol, since, limit, params); } async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) { return this.fetchOrdersWithMethod ('privateGetAllOrder', symbol, since, limit, params); } async fetchOrder (id, symbol = undefined, params = {}) { await this.loadMarkets (); let market = this.market (symbol); let request = { 'order_id': id, 'symbol': market['id'], }; let response = await this.privateGetOrderInfo (this.extend (request, params)); // // { code: "0", // msg: "suc", // data: { trade_list: [ { volume: "0.010", // feeCoin: "BTC", // price: "0.05816200", // fee: "0.00000029", // ctime: 1533616674000, // deal_price: "0.00058162", // id: 415779, // type: "卖出" } ], // order_info: { side: "SELL", // total_price: "0.010", // created_at: 1533616673000, // avg_price: "0.05816200", // countCoin: "btc", // source: 3, // type: 2, // side_msg: "卖出", // volume: "0.010", // price: "0.00000000", // source_msg: "API", // status_msg: "完全成交", // deal_volume: "0.01000000", // id: 3669583, // remain_volume: "0.00000000", // baseCoin: "eth", // tradeList: [ { volume: "0.010", // feeCoin: "BTC", // price: "0.05816200", // fee: "0.00000029", // ctime: 1533616674000, // deal_price: "0.00058162", // id: 415779, // type: "卖出" } ], // status: 2 } } } // return this.parseOrder (response['data']['order_info'], market); } async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) { if (symbol === undefined) { throw new ArgumentsRequired (this.id + ' fetchMyTrades requires a symbol argument'); } await this.loadMarkets (); let market = this.market (symbol); let request = { // pageSize optional page size // page optional page number 'symbol': market['id'], }; if (limit !== undefined) { request['pageSize'] = limit; } let response = await this.privateGetAllTrade (this.extend (request, params)); // // { code: "0", // msg: "suc", // data: { count: 1, // resultList: [ { volume: "0.010", // side: "SELL", // feeCoin: "BTC", // price: "0.05816200", // fee: "0.00000029", // ctime: 1533616674000, // deal_price: "0.00058162", // id: 415779, // type: "卖出", // bid_id: 3669539, // ask_id: 3669583 } ] } } // let trades = this.safeValue (response['data'], 'resultList', []); return this.parseTrades (trades, market, since, limit); } async fetchDepositAddress (code, params = {}) { await this.loadMarkets (); let currency = this.currency (code); let request = { 'coin': currency['id'], }; // https://github.com/UEX-OpenAPI/API_Docs_en/wiki/Query-deposit-address-of-assigned-token let response = await this.privateGetDepositAddressList (this.extend (request, params)); // // { // "code": "0", // "msg": "suc", // "data": { // "addressList": [ // { // "address": "0x198803ef8e0df9e8812c0105421885e843e6d2e2", // "tag": "", // }, // ], // }, // } // let data = this.safeValue (response, 'data'); if (data === undefined) { throw new InvalidAddress (this.id + ' privateGetDepositAddressList() returned no data'); } let addressList = this.safeValue (data, 'addressList'); if (addressList === undefined) { throw new InvalidAddress (this.id + ' privateGetDepositAddressList() returned no address list'); } let numAddresses = addressList.length; if (numAddresses < 1) { throw new InvalidAddress (this.id + ' privatePostDepositAddresses() returned no addresses'); } let firstAddress = addressList[0]; let address = this.safeString (firstAddress, 'address'); let tag = this.safeString (firstAddress, 'tag'); this.checkAddress (address); return { 'currency': code, 'address': address, 'tag': tag, 'info': response, }; } async fetchTransactionsByType (type, code = undefined, since = undefined, limit = undefined, params = {}) { if (code === undefined) { throw new ArgumentsRequired (this.id + ' fetchWithdrawals requires a currency code argument'); } const currency = this.currency (code); const request = { 'coin': currency['id'], }; if (limit !== undefined) { request['pageSize'] = limit; // default 10 } const transactionType = (type === 'deposit') ? 'deposit' : 'withdraw'; // instead of withdrawal... const method = 'privateGet' + this.capitalize (transactionType) + 'History'; // https://github.com/UEX-OpenAPI/API_Docs_en/wiki/Query-deposit-record-of-assigned-token // https://github.com/UEX-OpenAPI/API_Docs_en/wiki/Query-withdraw-record-of-assigned-token const response = await this[method] (this.extend (request, params)); // // { code: "0", // msg: "suc", // data: { depositList: [ { createdAt: 1533615955000, // amount: "0.01", // updateAt: 1533616311000, // txid: "0x0922fde6ab8270fe6eb31cb5a37dc732d96dc8193f81cf46c4ab29fde…", // tag: "", // confirmations: 30, // addressTo: "0x198803ef8e0df9e8812c0105421885e843e6d2e2", // status: 1, // coin: "ETH" } ] } } // // { // "code": "0", // "msg": "suc", // "data": { // "withdrawList": [{ // "updateAt": 1540344965000, // "createdAt": 1539311971000, // "status": 0, // "addressTo": "tz1d7DXJXU3AKWh77gSmpP7hWTeDYs8WF18q", // "tag": "100128877", // "id": 5, // "txid": "", // "fee": 0.0, // "amount": "1", // "symbol": "XTZ" // }] // } // } // const transactions = this.safeValue (response['data'], transactionType + 'List'); return this.parseTransactionsByType (type, transactions, code, since, limit); } async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) { return await this.fetchTransactionsByType ('deposit', code, since, limit, params); } async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) { return await this.fetchTransactionsByType ('withdrawal', code, since, limit, params); } parseTransactionsByType (type, transactions, code = undefined, since = undefined, limit = undefined) { const result = []; for (let i = 0; i < transactions.length; i++) { const transaction = this.parseTransaction (this.extend ({ 'type': type, }, transactions[i])); result.push (transaction); } return this.filterByCurrencySinceLimit (result, code, since, limit); } parseTransaction (transaction, currency = undefined) { // // deposits // // { createdAt: 1533615955000, // amount: "0.01", // updateAt: 1533616311000, // txid: "0x0922fde6ab8270fe6eb31cb5a37dc732d96dc8193f81cf46c4ab29fde…", // tag: "", // confirmations: 30, // addressTo: "0x198803ef8e0df9e8812c0105421885e843e6d2e2", // status: 1, // coin: "ETH" } ] } } // // withdrawals // // { // "updateAt": 1540344965000, // "createdAt": 1539311971000, // "status": 0, // "addressTo": "tz1d7DXJXU3AKWh77gSmpP7hWTeDYs8WF18q", // "tag": "100128877", // "id": 5, // "txid": "", // "fee": 0.0, // "amount": "1", // "symbol": "XTZ" // } // const id = this.safeString (transaction, 'id'); const txid = this.safeString (transaction, 'txid'); let timestamp = this.safeInteger (transaction, 'createdAt'); let updated = this.safeInteger (transaction, 'updateAt'); let code = undefined; let currencyId = this.safeString2 (transaction, 'symbol', 'coin'); currency = this.safeValue (this.currencies_by_id, currencyId); if (currency !== undefined) { code = currency['code']; } else { code = this.commonCurrencyCode (currencyId); } const address = this.safeString (transaction, 'addressTo'); const tag = this.safeString (transaction, 'tag'); const amount = this.safeFloat (transaction, 'amount'); const status = this.parseTransactionStatus (this.safeString (transaction, 'status')); const type = this.safeString (transaction, 'type'); // injected from the outside let feeCost = this.safeFloat (transaction, 'fee'); if ((type === 'deposit') && (feeCost === undefined)) { feeCost = 0; } return { 'info': transaction, 'id': id, 'currency': code,