ccxt
Version:
1,234 lines (1,232 loc) • 118 kB
JavaScript
'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