UNPKG

ccxt

Version:

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

1,234 lines (1,232 loc) • 118 kB
'use strict'; var lbank2$1 = require('./abstract/lbank2.js'); var errors = require('./base/errors.js'); var number = require('./base/functions/number.js'); var Precise = require('./base/Precise.js'); var md5 = require('./static_dependencies/noble-hashes/md5.js'); var sha256 = require('./static_dependencies/noble-hashes/sha256.js'); var rsa = require('./base/functions/rsa.js'); // --------------------------------------------------------------------------- // --------------------------------------------------------------------------- /** * @class lbank2 * @extends Exchange */ class lbank2 extends lbank2$1 { describe() { return this.deepExtend(super.describe(), { 'id': 'lbank2', 'name': 'LBank', 'countries': ['CN'], 'version': 'v2', // 50 per second for making and cancelling orders 1000ms / 50 = 20 // 20 per second for all other requests, cost = 50 / 20 = 2.5 'rateLimit': 20, 'has': { 'CORS': false, 'spot': true, 'margin': false, 'swap': undefined, 'future': false, 'option': false, 'addMargin': false, 'cancelAllOrders': true, 'cancelOrder': true, 'createOrder': true, 'createReduceOnlyOrder': false, 'createStopLimitOrder': false, 'createStopMarketOrder': false, 'createStopOrder': false, 'fetchBalance': true, 'fetchBorrowRate': false, 'fetchBorrowRateHistories': false, 'fetchBorrowRateHistory': false, 'fetchBorrowRates': false, 'fetchBorrowRatesPerSymbol': false, 'fetchClosedOrders': false, 'fetchDepositWithdrawFee': 'emulated', 'fetchDepositWithdrawFees': true, 'fetchFundingHistory': false, 'fetchFundingRate': false, 'fetchFundingRateHistory': false, 'fetchFundingRates': false, 'fetchIndexOHLCV': false, 'fetchIsolatedPositions': false, 'fetchLeverage': false, 'fetchLeverageTiers': false, 'fetchMarginMode': false, 'fetchMarkets': true, 'fetchMarkOHLCV': false, 'fetchMyTrades': true, 'fetchOHLCV': true, 'fetchOpenOrders': true, 'fetchOrder': true, 'fetchOrderBook': true, 'fetchOrders': true, 'fetchPosition': false, 'fetchPositionMode': false, 'fetchPositions': false, 'fetchPositionsRisk': false, 'fetchPremiumIndexOHLCV': false, 'fetchTicker': true, 'fetchTickers': true, 'fetchTime': true, 'fetchTrades': true, 'fetchTradingFees': true, 'fetchTransactionFees': true, 'reduceMargin': false, 'setLeverage': false, 'setMarginMode': false, 'setPositionMode': false, 'withdraw': true, }, 'timeframes': { '1m': 'minute1', '5m': 'minute5', '15m': 'minute15', '30m': 'minute30', '1h': 'hour1', '2h': 'hour2', '4h': 'hour4', '6h': 'hour6', '8h': 'hour8', '12h': 'hour12', '1d': 'day1', '1w': 'week1', }, 'urls': { 'logo': 'https://user-images.githubusercontent.com/1294454/38063602-9605e28a-3302-11e8-81be-64b1e53c4cfb.jpg', 'api': { 'rest': 'https://api.lbank.info', 'contract': 'https://lbkperp.lbank.com', }, 'api2': 'https://api.lbkex.com', 'www': 'https://www.lbank.info', 'doc': 'https://www.lbank.info/en-US/docs/index.html', 'fees': 'https://lbankinfo.zendesk.com/hc/en-gb/articles/360012072873-Trading-Fees', 'referral': 'https://www.lbank.info/invitevip?icode=7QCY', }, 'api': { 'spot': { 'public': { 'get': { 'currencyPairs': 2.5, 'accuracy': 2.5, 'usdToCny': 2.5, 'withdrawConfigs': 2.5, 'timestamp': 2.5, 'ticker/24hr': 2.5, 'ticker': 2.5, 'depth': 2.5, 'incrDepth': 2.5, 'trades': 2.5, 'kline': 2.5, // new quote endpoints 'supplement/system_ping': 2.5, 'supplement/incrDepth': 2.5, 'supplement/trades': 2.5, 'supplement/ticker/price': 2.5, 'supplement/ticker/bookTicker': 2.5, }, 'post': { 'supplement/system_status': 2.5, }, }, 'private': { 'post': { // account 'user_info': 2.5, 'subscribe/get_key': 2.5, 'subscribe/refresh_key': 2.5, 'subscribe/destroy_key': 2.5, 'get_deposit_address': 2.5, 'deposit_history': 2.5, // order 'create_order': 1, 'batch_create_order': 1, 'cancel_order': 1, 'cancel_clientOrders': 1, 'orders_info': 2.5, 'orders_info_history': 2.5, 'order_transaction_detail': 2.5, 'transaction_history': 2.5, 'orders_info_no_deal': 2.5, // withdraw 'withdraw': 2.5, 'withdrawCancel': 2.5, 'withdraws': 2.5, 'supplement/user_info': 2.5, 'supplement/withdraw': 2.5, 'supplement/deposit_history': 2.5, 'supplement/withdraws': 2.5, 'supplement/get_deposit_address': 2.5, 'supplement/asset_detail': 2.5, 'supplement/customer_trade_fee': 2.5, 'supplement/api_Restrictions': 2.5, // new quote endpoints 'supplement/system_ping': 2.5, // new order endpoints 'supplement/create_order_test': 1, 'supplement/create_order': 1, 'supplement/cancel_order': 1, 'supplement/cancel_order_by_symbol': 1, 'supplement/orders_info': 2.5, 'supplement/orders_info_no_deal': 2.5, 'supplement/orders_info_history': 2.5, 'supplement/user_info_account': 2.5, 'supplement/transaction_history': 2.5, }, }, }, 'contract': { 'public': { 'get': { 'cfd/openApi/v1/pub/getTime': 2.5, 'cfd/openApi/v1/pub/instrument': 2.5, 'cfd/openApi/v1/pub/marketData': 2.5, 'cfd/openApi/v1/pub/marketOrder': 2.5, }, }, }, }, 'fees': { 'trading': { 'maker': this.parseNumber('0.001'), 'taker': this.parseNumber('0.001'), }, 'funding': { 'withdraw': {}, }, }, 'commonCurrencies': { 'VET_ERC20': 'VEN', 'PNT': 'Penta', }, 'precisionMode': number.TICK_SIZE, 'options': { 'cacheSecretAsPem': true, 'createMarketBuyOrderRequiresPrice': true, 'fetchTrades': { 'method': 'spotPublicGetTrades', // or 'spotPublicGetTradesSupplement' }, 'fetchTransactionFees': { 'method': 'fetchPrivateTransactionFees', // or 'fetchPublicTransactionFees' }, 'fetchDepositWithdrawFees': { 'method': 'fetchPrivateDepositWithdrawFees', // or 'fetchPublicDepositWithdrawFees' }, 'fetchDepositAddress': { 'method': 'fetchDepositAddressDefault', // or fetchDepositAddressSupplement }, 'createOrder': { 'method': 'spotPrivatePostSupplementCreateOrder', // or spotPrivatePostCreateOrder }, 'fetchOrder': { 'method': 'fetchOrderSupplement', // or fetchOrderDefault }, 'fetchBalance': { 'method': 'spotPrivatePostSupplementUserInfo', // or spotPrivatePostSupplementUserInfoAccount or spotPrivatePostUserInfo }, 'networks': { 'ERC20': 'erc20', 'ETH': 'erc20', 'TRC20': 'trc20', 'TRX': 'trc20', 'OMNI': 'omni', 'ASA': 'asa', 'BEP20': 'bep20(bsc)', 'BSC': 'bep20(bsc)', 'HT': 'heco', 'BNB': 'bep2', 'BTC': 'btc', 'DOGE': 'dogecoin', 'MATIC': 'matic', 'POLYGON': 'matic', 'OEC': 'oec', 'BTCTRON': 'btctron', 'XRP': 'xrp', // other unusual chains with number of listed currencies supported // 'avax c-chain': 1, // klay: 12, // bta: 1, // fantom: 1, // celo: 1, // sol: 2, // zenith: 1, // ftm: 5, // bep20: 1, (single token with mis-named chain) SSS // bitci: 1, // sgb: 1, // moonbeam: 1, // ekta: 1, // etl: 1, // arbitrum: 1, // tpc: 1, // ptx: 1 // } }, 'inverse-networks': { 'erc20': 'ERC20', 'trc20': 'TRC20', 'omni': 'OMNI', 'asa': 'ASA', 'bep20(bsc)': 'BSC', 'bep20': 'BSC', 'heco': 'HT', 'bep2': 'BNB', 'btc': 'BTC', 'dogecoin': 'DOGE', 'matic': 'MATIC', 'oec': 'OEC', 'btctron': 'BTCTRON', 'xrp': 'XRP', }, 'defaultNetworks': { 'USDT': 'TRC20', }, }, }); } async fetchTime(params = {}) { /** * @method * @name lbank2#fetchTime * @description fetches the current integer timestamp in milliseconds from the exchange server * @see https://www.lbank.info/en-US/docs/index.html#get-timestamp * @see https://www.lbank.com/en-US/docs/contract.html#get-the-current-time * @param {object} [params] extra parameters specific to the lbank2 api endpoint * @returns {int} the current integer timestamp in milliseconds from the exchange server */ let type = undefined; [type, params] = this.handleMarketTypeAndParams('fetchTime', undefined, params); let response = undefined; if (type === 'swap') { response = await this.contractPublicGetCfdOpenApiV1PubGetTime(params); } else { response = await this.spotPublicGetTimestamp(params); } // // spot // // { // "result": "true", // "data": 1691789627950, // "error_code": 0, // "ts": 1691789627950 // } // // swap // // { // "data": 1691789627950, // "error_code": 0, // "msg": "Success", // "result": "true", // "success": true // } // return this.safeInteger(response, 'data'); } async fetchMarkets(params = {}) { /** * @method * @name lbank2#fetchMarkets * @description retrieves data on all markets for lbank2 * @see https://www.lbank.com/en-US/docs/index.html#trading-pairs * @see https://www.lbank.com/en-US/docs/contract.html#query-contract-information-list * @param {object} [params] extra parameters specific to the exchange api endpoint * @returns {object[]} an array of objects representing market data */ const marketsPromises = [ this.fetchSpotMarkets(params), this.fetchSwapMarkets(params), ]; const resolvedMarkets = await Promise.all(marketsPromises); return this.arrayConcat(resolvedMarkets[0], resolvedMarkets[1]); } async fetchSpotMarkets(params = {}) { const response = await this.spotPublicGetAccuracy(params); // // { // "result": "true", // "data": [ // { // "symbol": "btc_usdt", // "quantityAccuracy": "4", // "minTranQua": "0.0001", // "priceAccuracy": "2" // }, // ], // "error_code": 0, // "ts": 1691560288484 // } // const data = this.safeValue(response, 'data', []); const result = []; for (let i = 0; i < data.length; i++) { const market = data[i]; const marketId = this.safeString(market, 'symbol'); const parts = marketId.split('_'); const baseId = parts[0]; const quoteId = parts[1]; const base = this.safeCurrencyCode(baseId); const quote = this.safeCurrencyCode(quoteId); const symbol = base + '/' + quote; result.push({ 'id': marketId, 'symbol': symbol, 'base': base, 'quote': quote, 'settle': undefined, 'baseId': baseId, 'quoteId': quoteId, 'settleId': undefined, 'type': 'spot', 'spot': true, 'margin': false, 'swap': false, 'future': false, 'option': false, 'active': true, 'contract': undefined, 'linear': undefined, 'inverse': undefined, 'contractSize': undefined, 'expiry': undefined, 'expiryDatetime': undefined, 'strike': undefined, 'optionType': undefined, 'precision': { 'amount': this.parseNumber(this.parsePrecision(this.safeString(market, 'quantityAccuracy'))), 'price': this.parseNumber(this.parsePrecision(this.safeString(market, 'priceAccuracy'))), }, 'limits': { 'leverage': { 'min': undefined, 'max': undefined, }, 'amount': { 'min': this.safeNumber(market, 'minTranQua'), 'max': undefined, }, 'price': { 'min': undefined, 'max': undefined, }, 'cost': { 'min': undefined, 'max': undefined, }, }, 'created': undefined, 'info': market, }); } return result; } async fetchSwapMarkets(params = {}) { const request = { 'productGroup': 'SwapU', }; const response = await this.contractPublicGetCfdOpenApiV1PubInstrument(this.extend(request, params)); // // { // "data": [ // { // "priceLimitUpperValue": 0.2, // "symbol": "BTCUSDT", // "volumeTick": 0.0001, // "indexPrice": "29707.70200000", // "minOrderVolume": "0.0001", // "priceTick": 0.1, // "maxOrderVolume": "30.0", // "baseCurrency": "BTC", // "volumeMultiple": 1.0, // "exchangeID": "Exchange", // "priceCurrency": "USDT", // "priceLimitLowerValue": 0.2, // "clearCurrency": "USDT", // "symbolName": "BTCUSDT", // "defaultLeverage": 20.0, // "minOrderCost": "5.0" // }, // ], // "error_code": 0, // "msg": "Success", // "result": "true", // "success": true // } // const data = this.safeValue(response, 'data', []); const result = []; for (let i = 0; i < data.length; i++) { const market = data[i]; const marketId = this.safeString(market, 'symbol'); const baseId = this.safeString(market, 'baseCurrency'); const settleId = this.safeString(market, 'clearCurrency'); const quoteId = settleId; const base = this.safeCurrencyCode(baseId); const quote = this.safeCurrencyCode(quoteId); const settle = this.safeCurrencyCode(settleId); const symbol = base + '/' + quote + ':' + settle; result.push({ 'id': marketId, 'symbol': symbol, 'base': base, 'quote': quote, 'settle': settle, 'baseId': baseId, 'quoteId': quoteId, 'settleId': settleId, 'type': 'swap', 'spot': false, 'margin': false, 'swap': true, 'future': false, 'option': false, 'active': true, 'contract': true, 'linear': true, 'inverse': undefined, 'contractSize': this.safeNumber(market, 'volumeMultiple'), 'expiry': undefined, 'expiryDatetime': undefined, 'strike': undefined, 'optionType': undefined, 'precision': { 'amount': this.safeNumber(market, 'volumeTick'), 'price': this.safeNumber(market, 'priceTick'), }, 'limits': { 'leverage': { 'min': undefined, 'max': undefined, }, 'amount': { 'min': this.safeNumber(market, 'minOrderVolume'), 'max': this.safeNumber(market, 'maxOrderVolume'), }, 'price': { 'min': this.safeNumber(market, 'priceLimitLowerValue'), 'max': this.safeNumber(market, 'priceLimitUpperValue'), }, 'cost': { 'min': this.safeNumber(market, 'minOrderCost'), 'max': undefined, }, }, 'created': undefined, 'info': market, }); } return result; } parseTicker(ticker, market = undefined) { // // spot: fetchTicker, fetchTickers // // { // "symbol": "btc_usdt", // "ticker": { // "high": "29695.57", // "vol": "6890.2789", // "low": "29110", // "change": "0.58", // "turnover": "202769821.06", // "latest": "29405.98" // }, // "timestamp": :1692064274908 // } // // swap: fetchTickers // // { // "prePositionFeeRate": "0.000053", // "volume": "2435.459", // "symbol": "BTCUSDT", // "highestPrice": "29446.5", // "lowestPrice": "29362.9", // "openPrice": "29419.5", // "markedPrice": "29385.1", // "turnover": "36345526.2438402", // "lastPrice": "29387.0" // } // const timestamp = this.safeInteger(ticker, 'timestamp'); const marketId = this.safeString(ticker, 'symbol'); const symbol = this.safeSymbol(marketId, market); const tickerData = this.safeValue(ticker, 'ticker', {}); market = this.safeMarket(marketId, market); const data = (market['contract']) ? ticker : tickerData; return this.safeTicker({ 'symbol': symbol, 'timestamp': timestamp, 'datetime': this.iso8601(timestamp), 'high': this.safeString2(data, 'high', 'highestPrice'), 'low': this.safeString2(data, 'low', 'lowestPrice'), 'bid': undefined, 'bidVolume': undefined, 'ask': undefined, 'askVolume': undefined, 'vwap': undefined, 'open': this.safeString(data, 'openPrice'), 'close': undefined, 'last': this.safeString2(data, 'latest', 'lastPrice'), 'previousClose': undefined, 'change': undefined, 'percentage': this.safeString(data, 'change'), 'average': undefined, 'baseVolume': this.safeString2(data, 'vol', 'volume'), 'quoteVolume': this.safeString(data, 'turnover'), 'info': ticker, }, market); } async fetchTicker(symbol, params = {}) { /** * @method * @name lbank2#fetchTicker * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market * @see https://www.lbank.info/en-US/docs/index.html#query-current-market-data-new * @param {string} symbol unified symbol of the market to fetch the ticker for * @param {object} [params] extra parameters specific to the lbank2 api endpoint * @returns {object} a [ticker structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#ticker-structure} */ await this.loadMarkets(); const market = this.market(symbol); if (market['swap']) { const responseForSwap = await this.fetchTickers([market['symbol']], params); return this.safeValue(responseForSwap, market['symbol']); } const request = { 'symbol': market['id'], }; const response = await this.spotPublicGetTicker24hr(this.extend(request, params)); // // { // "result": "true", // "data": [ // { // "symbol": "btc_usdt", // "ticker": { // "high": "29695.57", // "vol": "6890.2789", // "low": "29110", // "change": "0.58", // "turnover": "202769821.06", // "latest": "29405.98" // }, // "timestamp": :1692064274908 // } // ], // "error_code": 0, // "ts": :1692064276872 // } // const data = this.safeValue(response, 'data', []); const first = this.safeValue(data, 0, {}); return this.parseTicker(first, market); } async fetchTickers(symbols = undefined, params = {}) { /** * @method * @name lbank2#fetchTickers * @description fetches price tickers for multiple markets, statistical calculations with the information calculated over the past 24 hours each market * @see https://www.lbank.info/en-US/docs/index.html#query-current-market-data-new * @see https://www.lbank.com/en-US/docs/contract.html#query-contract-market-list * @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 lbank api endpoint * @returns {object} a dictionary of [ticker structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#ticker-structure} */ await this.loadMarkets(); let market = undefined; if (symbols !== undefined) { symbols = this.marketSymbols(symbols); const symbolsLength = symbols.length; if (symbolsLength > 0) { market = this.market(symbols[0]); } } const request = {}; let type = undefined; [type, params] = this.handleMarketTypeAndParams('fetchTickers', market, params); let response = undefined; if (type === 'swap') { request['productGroup'] = 'SwapU'; response = await this.contractPublicGetCfdOpenApiV1PubMarketData(this.extend(request, params)); } else { request['symbol'] = 'all'; response = await this.spotPublicGetTicker24hr(this.extend(request, params)); } // // spot // // { // "result": "true", // "data": [ // { // "symbol": "btc_usdt", // "ticker": { // "high": "29695.57", // "vol": "6890.2789", // "low": "29110", // "change": "0.58", // "turnover": "202769821.06", // "latest": "29405.98" // }, // "timestamp": :1692064274908 // } // ], // "error_code": 0, // "ts": :1692064276872 // } // // swap // // { // "data": [ // { // "prePositionFeeRate": "0.000053", // "volume": "2435.459", // "symbol": "BTCUSDT", // "highestPrice": "29446.5", // "lowestPrice": "29362.9", // "openPrice": "29419.5", // "markedPrice": "29385.1", // "turnover": "36345526.2438402", // "lastPrice": "29387.0" // }, // ], // "error_code": 0, // "msg": "Success", // "result": "true", // "success": true // } // const data = this.safeValue(response, 'data', []); return this.parseTickers(data, symbols); } async fetchOrderBook(symbol, limit = undefined, params = {}) { /** * @method * @name lbank2#fetchOrderBook * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data * @see https://www.lbank.info/en-US/docs/index.html#query-market-depth * @see https://www.lbank.com/en-US/docs/contract.html#get-handicap * @param {string} symbol unified symbol of the market to fetch the order book for * @param {int} [limit] the maximum amount of order book entries to return * @param {object} [params] extra parameters specific to the lbank2 api endpoint * @returns {object} A dictionary of [order book structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-book-structure} indexed by market symbols */ await this.loadMarkets(); const market = this.market(symbol); if (limit === undefined) { limit = 60; } const request = { 'symbol': market['id'], }; let type = undefined; [type, params] = this.handleMarketTypeAndParams('fetchOrderBook', market, params); let response = undefined; if (type === 'swap') { request['depth'] = limit; response = await this.contractPublicGetCfdOpenApiV1PubMarketOrder(this.extend(request, params)); } else { request['size'] = limit; response = await this.spotPublicGetDepth(this.extend(request, params)); } // // spot // // { // "result": "true", // "data": { // "asks": [ // ["29243.37", "2.8783"], // ["29243.39", "2.2842"], // ["29243.4", "0.0337"] // ], // "bids": [ // ["29243.36", "1.5258"], // ["29243.34", "0.8218"], // ["29243.28", "1.285"] // ], // "timestamp": :1692157328820 // }, // "error_code": 0, // "ts": :1692157328820 // } // // swap // // { // "data": { // "symbol": "BTCUSDT", // "asks": [ // { // "volume": "14.6535", // "price": "29234.2", // "orders": "1" // }, // ], // "bids": [ // { // "volume": "13.4899", // "price": "29234.1", // "orders": "4" // }, // ] // }, // "error_code": 0, // "msg": "Success", // "result": "true", // "success": true // } // const orderbook = this.safeValue(response, 'data', {}); const timestamp = this.milliseconds(); if (market['swap']) { return this.parseOrderBook(orderbook, market['symbol'], timestamp, 'bids', 'asks', 'price', 'volume'); } return this.parseOrderBook(orderbook, market['symbol'], timestamp); } parseTrade(trade, market = undefined) { // // fetchTrades (old) spotPublicGetTrades // // { // "date_ms":1647021989789, // "amount":0.0028, // "price":38804.2, // "type":"buy", // "tid":"52d5616ee35c43019edddebe59b3e094" // } // // // fetchTrades (new) spotPublicGetTradesSupplement // // { // "quoteQty":1675.048485, // "price":0.127545, // "qty":13133, // "id":"3589541dc22e4357b227283650f714e2", // "time":1648058297110, // "isBuyerMaker":false // } // // fetchMyTrades (private) // // { // "orderUuid":"38b4e7a4-14f6-45fd-aba1-1a37024124a0", // "tradeFeeRate":0.0010000000, // "dealTime":1648500944496, // "dealQuantity":30.00000000000000000000, // "tradeFee":0.00453300000000000000, // "txUuid":"11f3850cc6214ea3b495adad3a032794", // "dealPrice":0.15111300000000000000, // "dealVolumePrice":4.53339000000000000000, // "tradeType":"sell_market" // } // let timestamp = this.safeInteger2(trade, 'date_ms', 'time'); if (timestamp === undefined) { timestamp = this.safeInteger(trade, 'dealTime'); } let amountString = this.safeString2(trade, 'amount', 'qty'); if (amountString === undefined) { amountString = this.safeString(trade, 'dealQuantity'); } let priceString = this.safeString(trade, 'price'); if (priceString === undefined) { priceString = this.safeString(trade, 'dealPrice'); } let costString = this.safeString(trade, 'quoteQty'); if (costString === undefined) { costString = this.safeString(trade, 'dealVolumePrice'); } let side = this.safeString2(trade, 'tradeType', 'type'); let type = undefined; let takerOrMaker = undefined; if (side !== undefined) { const parts = side.split('_'); side = this.safeString(parts, 0); const typePart = this.safeString(parts, 1); type = 'limit'; takerOrMaker = 'taker'; if (typePart !== undefined) { if (typePart === 'market') { type = 'market'; } else if (typePart === 'maker') { takerOrMaker = 'maker'; } } } let id = this.safeString2(trade, 'tid', 'id'); if (id === undefined) { id = this.safeString(trade, 'txUuid'); } const order = this.safeString(trade, 'orderUuid'); const symbol = this.safeSymbol(undefined, market); let fee = undefined; const feeCost = this.safeString(trade, 'tradeFee'); if (feeCost !== undefined) { fee = { 'cost': feeCost, 'currency': (side === 'buy') ? market['base'] : market['quote'], 'rate': this.safeString(trade, 'tradeFeeRate'), }; } return this.safeTrade({ 'timestamp': timestamp, 'datetime': this.iso8601(timestamp), 'symbol': symbol, 'id': id, 'order': order, 'type': type, 'takerOrMaker': takerOrMaker, 'side': side, 'price': priceString, 'amount': amountString, 'cost': costString, 'fee': fee, 'info': trade, }, market); } async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) { /** * @method * @name lbank2#fetchTrades * @description get the list of most recent trades for a particular symbol * @see https://www.lbank.info/en-US/docs/index.html#query-historical-transactions * @see https://www.lbank.info/en-US/docs/index.html#recent-transactions-list * @param {string} symbol unified symbol of the market to fetch trades for * @param {int} [since] timestamp in ms of the earliest trade to fetch * @param {int} [limit] the maximum amount of trades to fetch * @param {object} [params] extra parameters specific to the lbank2 api endpoint * @returns {Trade[]} a list of [trade structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#public-trades} */ await this.loadMarkets(); const market = this.market(symbol); const request = { 'symbol': market['id'], }; if (since !== undefined) { request['time'] = since; } if (limit !== undefined) { request['size'] = Math.min(limit, 600); } else { request['size'] = 600; // max } let method = this.safeString(params, 'method'); params = this.omit(params, 'method'); if (method === undefined) { const options = this.safeValue(this.options, 'fetchTrades', {}); method = this.safeString(options, 'method', 'spotPublicGetTrades'); } const response = await this[method](this.extend(request, params)); // // { // "result":"true", // "data": [ // { // "date_ms":1647021989789, // "amount":0.0028, // "price":38804.2, // "type":"buy", // "tid":"52d5616ee35c43019edddebe59b3e094" // } // ], // "error_code":0, // "ts":1647021999308 // } // const trades = this.safeValue(response, 'data', []); return this.parseTrades(trades, market, since, limit); } parseOHLCV(ohlcv, market = undefined) { // // [ // 1482311500, // timestamp // 5423.23, // open // 5472.80, // high // 5516.09, // low // 5462, // close // 234.3250 // volume // ], // return [ this.safeTimestamp(ohlcv, 0), this.safeNumber(ohlcv, 1), this.safeNumber(ohlcv, 2), this.safeNumber(ohlcv, 3), this.safeNumber(ohlcv, 4), this.safeNumber(ohlcv, 5), // volume ]; } async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) { /** * @method * @name lbank2#fetchOHLCV * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market * @see https://www.lbank.info/en-US/docs/index.html#query-k-bar-data * @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} [since] timestamp in ms of the earliest candle to fetch * @param {int} [limit] the maximum amount of candles to fetch * @param {object} [params] extra parameters specific to the lbank2 api endpoint * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume */ // endpoint doesnt work await this.loadMarkets(); const market = this.market(symbol); if (limit === undefined) { limit = 100; } if (since === undefined) { const duration = this.parseTimeframe(timeframe); since = this.milliseconds() - duration * 1000 * limit; } const request = { 'symbol': market['id'], 'type': this.safeString(this.timeframes, timeframe, timeframe), 'time': this.parseToInt(since / 1000), 'size': limit, // max 2000 }; const response = await this.spotPublicGetKline(this.extend(request, params)); const ohlcvs = this.safeValue(response, 'data', []); // // // [ // [ // 1482311500, // 5423.23, // 5472.80, // 5516.09, // 5462, // 234.3250 // ], // [ // 1482311400, // 5432.52, // 5459.87, // 5414.30, // 5428.23, // 213.7329 // ] // ] // return this.parseOHLCVs(ohlcvs, market, timeframe, since, limit); } parseBalance(response) { // // spotPrivatePostUserInfo // // { // "toBtc": { // "egc:": "0", // "iog": "0", // "ksm": "0", // }, // "freeze": { // "egc": "0", // "iog": "0", // "ksm": "0" , // }, // "asset": { // "egc": "0", // "iog": "0", // "ksm": "0", // }, // "free": { // "egc": "0", // "iog": "0", // "ksm": "0", // } // } // // spotPrivatePostSupplementUserInfoAccount // // { // "balances":[ // { // "asset":"lbk", // "free":"0", // "locked":"0" // }, ... // ] // } // // spotPrivatePostSupplementUserInfo // // [ // { // "usableAmt":"31.45130723", // "assetAmt":"31.45130723", // "networkList":[ // { // "isDefault":true, // "withdrawFeeRate":"", // "name":"bep20(bsc)", // "withdrawMin":30, // "minLimit":0.0001, // "minDeposit":0.0001, // "feeAssetCode":"doge", // "withdrawFee":"30", // "type":1, // "coin":"doge", // "network":"bsc" // }, // { // "isDefault":false, // "withdrawFeeRate":"", // "name":"dogecoin", // "withdrawMin":10, // "minLimit":0.0001, // "minDeposit":10, // "feeAssetCode":"doge", // "withdrawFee":"10", // "type":1, // "coin":"doge", // "network":"dogecoin" // } // ], // "freezeAmt":"0", // "coin":"doge" // }, ... // ] // const timestamp = this.safeInteger(response, 'ts'); const result = { 'info': response, 'timestamp': timestamp, 'datetime': this.iso8601(timestamp), }; const data = this.safeValue(response, 'data'); // from spotPrivatePostUserInfo const toBtc = this.safeValue(data, 'toBtc'); if (toBtc !== undefined) { const used = this.safeValue(data, 'freeze', {}); const free = this.safeValue(data, 'free', {}); const currencies = Object.keys(free); for (let i = 0; i < currencies.length; i++) { const currencyId = currencies[i]; const code = this.safeCurrencyCode(currencyId); const account = this.account(); account['used'] = this.safeString(used, currencyId); account['free'] = this.safeString(free, currencyId); result[code] = account; } return this.safeBalance(result); } // from spotPrivatePostSupplementUserInfoAccount const balances = this.safeValue(data, 'balances'); if (balances !== undefined) { for (let i = 0; i < balances.length; i++) { const item = balances[i]; const currencyId = this.safeString(item, 'asset'); const codeInner = this.safeCurrencyCode(currencyId); const account = this.account(); account['free'] = this.safeString(item, 'free'); account['used'] = this.safeString(item, 'locked'); result[codeInner] = account; } return this.safeBalance(result); } // from spotPrivatePostSupplementUserInfo const isArray = Array.isArray(data); if (isArray === true) { for (let i = 0; i < data.length; i++) { const item = data[i]; const currencyId = this.safeString(item, 'coin'); const codeInner = this.safeCurrencyCode(currencyId); const account = this.account(); account['free'] = this.safeString(item, 'usableAmt'); account['used'] = this.safeString(item, 'freezeAmt'); result[codeInner] = account; } return this.safeBalance(result); } return undefined; } async fetchBalance(params = {}) { /** * @method * @name lbank2#fetchBalance * @description query for balance and get the amount of funds available for trading or funds locked in orders * @see https://www.lbank.info/en-US/docs/index.html#asset-information * @see https://www.lbank.info/en-US/docs/index.html#account-information * @see https://www.lbank.info/en-US/docs/index.html#get-all-coins-information * @param {object} [params] extra parameters specific to the lbank2 api endpoint * @returns {object} a [balance structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#balance-structure} */ await this.loadMarkets(); let method = this.safeString(params, 'method'); if (method === undefined) { const options = this.safeValue(this.options, 'fetchBalance', {}); method = this.safeString(options, 'method', 'spotPrivatePostSupplementUserInfo'); } const response = await this[method](); // // { // "result": "true", // "data": [ // { // "usableAmt": "14.36", // "assetAmt": "14.36", // "networkList": [ // { // "isDefault": false, // "withdrawFeeRate": "", // "name": "erc20", // "withdrawMin": 30, // "minLimit": 0.0001, // "minDeposit": 20, // "feeAssetCode": "usdt", // "withdrawFee": "30", // "type": 1, // "coin": "usdt", // "network": "eth" // }, // ... // ], // "freezeAmt": "0", // "coin": "ada" // } // ], // "code": 0 // } // return this.parseBalance(response); } parseTradingFee(fee, market = undefined) { // // { // "symbol":"skt_usdt", // "makerCommission":"0.10", // "takerCommission":"0.10" // } // const marketId = this.safeString(fee, 'symbol'); const symbol = this.safeSymbol(marketId); return { 'info': fee, 'symbol': symbol, 'maker': this.safeNumber(fee, 'makerCommission'), 'taker': this.safeNumber(fee, 'takerCommission'), }; } async fetchTradingFee(symbol, params = {}) { /** * @method * @name lbank2#fetchTradingFee * @description fetch the trading fees for a market * @see https://www.lbank.info/en-US/docs/index.html#transaction-fee-rate-query * @param {string} symbol unified market symbol * @param {object} [params] extra parameters specific to the lbank2 api endpoint * @returns {object} a [fee structure]{@link https://github.com/ccxt/ccxt/wi