ccxt 4.1.52 → 4.1.53

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) hide show
  1. package/README.md +6 -8
  2. package/dist/ccxt.browser.js +1311 -2712
  3. package/dist/ccxt.browser.min.js +7 -7
  4. package/dist/cjs/ccxt.js +1 -7
  5. package/dist/cjs/src/ace.js +56 -59
  6. package/dist/cjs/src/ascendex.js +1 -2
  7. package/dist/cjs/src/base/Exchange.js +1 -11
  8. package/dist/cjs/src/bingx.js +48 -8
  9. package/dist/cjs/src/bybit.js +2 -11
  10. package/dist/cjs/src/cryptocom.js +1 -0
  11. package/dist/cjs/src/digifinex.js +9 -6
  12. package/dist/cjs/src/lbank.js +2333 -443
  13. package/dist/cjs/src/ndax.js +59 -61
  14. package/dist/cjs/src/novadax.js +57 -59
  15. package/dist/cjs/src/oceanex.js +58 -60
  16. package/dist/cjs/src/okcoin.js +1 -9
  17. package/dist/cjs/src/okx.js +0 -7
  18. package/dist/cjs/src/poloniex.js +55 -57
  19. package/dist/cjs/src/poloniexfutures.js +67 -70
  20. package/dist/cjs/src/pro/bingx.js +18 -11
  21. package/dist/cjs/src/pro/poloniexfutures.js +9 -0
  22. package/dist/cjs/src/probit.js +62 -65
  23. package/dist/cjs/src/timex.js +1 -5
  24. package/dist/cjs/src/upbit.js +56 -58
  25. package/dist/cjs/src/wazirx.js +72 -74
  26. package/dist/cjs/src/whitebit.js +88 -91
  27. package/dist/cjs/src/woo.js +75 -77
  28. package/dist/cjs/src/zaif.js +57 -71
  29. package/dist/cjs/src/zonda.js +67 -70
  30. package/js/ccxt.d.ts +2 -8
  31. package/js/ccxt.js +2 -6
  32. package/js/src/abstract/bybit.d.ts +1 -0
  33. package/js/src/abstract/lbank.d.ts +57 -15
  34. package/js/src/ace.d.ts +8 -7
  35. package/js/src/ace.js +56 -59
  36. package/js/src/alpaca.d.ts +4 -4
  37. package/js/src/ascendex.d.ts +12 -12
  38. package/js/src/ascendex.js +1 -2
  39. package/js/src/base/Exchange.js +1 -11
  40. package/js/src/base/types.d.ts +73 -71
  41. package/js/src/bigone.d.ts +10 -10
  42. package/js/src/binance.d.ts +27 -27
  43. package/js/src/bingx.d.ts +15 -15
  44. package/js/src/bingx.js +48 -8
  45. package/js/src/bit2c.d.ts +5 -5
  46. package/js/src/bitbank.d.ts +5 -5
  47. package/js/src/bitbns.d.ts +7 -7
  48. package/js/src/bitfinex.d.ts +8 -8
  49. package/js/src/bitfinex2.d.ts +12 -12
  50. package/js/src/bitflyer.d.ts +9 -9
  51. package/js/src/bitforex.d.ts +6 -6
  52. package/js/src/bitget.d.ts +24 -24
  53. package/js/src/bithumb.d.ts +4 -4
  54. package/js/src/bitmart.d.ts +21 -21
  55. package/js/src/bitmex.d.ts +14 -14
  56. package/js/src/bitopro.d.ts +12 -12
  57. package/js/src/bitpanda.d.ts +11 -11
  58. package/js/src/bitrue.d.ts +8 -8
  59. package/js/src/bitso.d.ts +11 -11
  60. package/js/src/bitstamp.d.ts +10 -10
  61. package/js/src/bitstamp1.d.ts +4 -4
  62. package/js/src/bittrex.d.ts +14 -14
  63. package/js/src/bitvavo.d.ts +9 -9
  64. package/js/src/bl3p.d.ts +2 -2
  65. package/js/src/blockchaincom.d.ts +13 -13
  66. package/js/src/btcalpha.d.ts +9 -9
  67. package/js/src/btcbox.d.ts +6 -6
  68. package/js/src/btcmarkets.d.ts +12 -12
  69. package/js/src/btcturk.d.ts +5 -5
  70. package/js/src/bybit.d.ts +28 -28
  71. package/js/src/bybit.js +2 -11
  72. package/js/src/cex.d.ts +6 -6
  73. package/js/src/coinbase.d.ts +17 -17
  74. package/js/src/coinbasepro.d.ts +13 -13
  75. package/js/src/coincheck.d.ts +6 -6
  76. package/js/src/coinex.d.ts +18 -18
  77. package/js/src/coinlist.d.ts +14 -14
  78. package/js/src/coinmate.d.ts +7 -7
  79. package/js/src/coinone.d.ts +5 -5
  80. package/js/src/coinsph.d.ts +10 -10
  81. package/js/src/coinspot.d.ts +3 -3
  82. package/js/src/cryptocom.d.ts +16 -16
  83. package/js/src/cryptocom.js +1 -0
  84. package/js/src/currencycom.d.ts +10 -10
  85. package/js/src/delta.d.ts +10 -10
  86. package/js/src/deribit.d.ts +13 -13
  87. package/js/src/digifinex.d.ts +17 -17
  88. package/js/src/digifinex.js +9 -6
  89. package/js/src/exmo.d.ts +12 -12
  90. package/js/src/gate.d.ts +20 -20
  91. package/js/src/gemini.d.ts +6 -6
  92. package/js/src/hitbtc.d.ts +15 -15
  93. package/js/src/hollaex.d.ts +12 -12
  94. package/js/src/htx.d.ts +27 -27
  95. package/js/src/huobijp.d.ts +16 -16
  96. package/js/src/idex.d.ts +13 -13
  97. package/js/src/independentreserve.d.ts +6 -6
  98. package/js/src/indodax.d.ts +6 -6
  99. package/js/src/kraken.d.ts +16 -16
  100. package/js/src/krakenfutures.d.ts +9 -9
  101. package/js/src/kucoin.d.ts +15 -15
  102. package/js/src/kucoinfutures.d.ts +11 -11
  103. package/js/src/kuna.d.ts +12 -12
  104. package/js/src/latoken.d.ts +9 -9
  105. package/js/src/lbank.d.ts +65 -12
  106. package/js/src/lbank.js +2334 -444
  107. package/js/src/lbank2.d.ts +11 -11
  108. package/js/src/luno.d.ts +10 -10
  109. package/js/src/lykke.d.ts +8 -8
  110. package/js/src/mercado.d.ts +6 -6
  111. package/js/src/mexc.d.ts +23 -23
  112. package/js/src/ndax.d.ts +13 -12
  113. package/js/src/ndax.js +59 -61
  114. package/js/src/novadax.d.ts +13 -12
  115. package/js/src/novadax.js +57 -59
  116. package/js/src/oceanex.d.ts +10 -9
  117. package/js/src/oceanex.js +58 -60
  118. package/js/src/okcoin.d.ts +12 -13
  119. package/js/src/okcoin.js +1 -9
  120. package/js/src/okx.d.ts +26 -27
  121. package/js/src/okx.js +0 -7
  122. package/js/src/paymium.d.ts +2 -2
  123. package/js/src/phemex.d.ts +16 -16
  124. package/js/src/poloniex.d.ts +15 -14
  125. package/js/src/poloniex.js +55 -57
  126. package/js/src/poloniexfutures.d.ts +11 -10
  127. package/js/src/poloniexfutures.js +67 -70
  128. package/js/src/pro/alpaca.d.ts +3 -3
  129. package/js/src/pro/ascendex.d.ts +2 -2
  130. package/js/src/pro/binance.d.ts +9 -9
  131. package/js/src/pro/bingx.d.ts +3 -3
  132. package/js/src/pro/bingx.js +19 -12
  133. package/js/src/pro/bitfinex.d.ts +3 -3
  134. package/js/src/pro/bitfinex2.d.ts +3 -3
  135. package/js/src/pro/bitget.d.ts +3 -3
  136. package/js/src/pro/bitmart.d.ts +2 -2
  137. package/js/src/pro/bitmex.d.ts +3 -3
  138. package/js/src/pro/bitpanda.d.ts +3 -3
  139. package/js/src/pro/bitrue.d.ts +2 -2
  140. package/js/src/pro/bitstamp.d.ts +2 -2
  141. package/js/src/pro/bittrex.d.ts +3 -3
  142. package/js/src/pro/bitvavo.d.ts +3 -3
  143. package/js/src/pro/blockchaincom.d.ts +2 -2
  144. package/js/src/pro/bybit.d.ts +4 -4
  145. package/js/src/pro/cex.d.ts +3 -3
  146. package/js/src/pro/coinbasepro.d.ts +3 -3
  147. package/js/src/pro/coinex.d.ts +2 -2
  148. package/js/src/pro/cryptocom.d.ts +5 -5
  149. package/js/src/pro/deribit.d.ts +3 -3
  150. package/js/src/pro/exmo.d.ts +2 -2
  151. package/js/src/pro/gate.d.ts +3 -3
  152. package/js/src/pro/gemini.d.ts +2 -2
  153. package/js/src/pro/hitbtc.d.ts +3 -3
  154. package/js/src/pro/hollaex.d.ts +3 -3
  155. package/js/src/pro/htx.d.ts +3 -3
  156. package/js/src/pro/idex.d.ts +3 -3
  157. package/js/src/pro/kraken.d.ts +7 -7
  158. package/js/src/pro/krakenfutures.d.ts +4 -4
  159. package/js/src/pro/kucoin.d.ts +3 -3
  160. package/js/src/pro/kucoinfutures.d.ts +3 -3
  161. package/js/src/pro/mexc.d.ts +3 -3
  162. package/js/src/pro/okcoin.d.ts +2 -2
  163. package/js/src/pro/okx.d.ts +6 -6
  164. package/js/src/pro/phemex.d.ts +3 -3
  165. package/js/src/pro/poloniex.d.ts +3 -3
  166. package/js/src/pro/poloniexfutures.d.ts +3 -3
  167. package/js/src/pro/poloniexfutures.js +9 -0
  168. package/js/src/pro/probit.d.ts +3 -3
  169. package/js/src/pro/wazirx.d.ts +3 -3
  170. package/js/src/pro/whitebit.d.ts +3 -3
  171. package/js/src/pro/woo.d.ts +2 -2
  172. package/js/src/probit.d.ts +11 -10
  173. package/js/src/probit.js +62 -65
  174. package/js/src/tidex.d.ts +5 -5
  175. package/js/src/timex.d.ts +10 -10
  176. package/js/src/timex.js +1 -5
  177. package/js/src/tokocrypto.d.ts +9 -9
  178. package/js/src/upbit.d.ts +11 -10
  179. package/js/src/upbit.js +56 -58
  180. package/js/src/wavesexchange.d.ts +7 -7
  181. package/js/src/wazirx.d.ts +7 -6
  182. package/js/src/wazirx.js +72 -74
  183. package/js/src/whitebit.d.ts +12 -11
  184. package/js/src/whitebit.js +88 -91
  185. package/js/src/woo.d.ts +20 -19
  186. package/js/src/woo.js +75 -77
  187. package/js/src/yobit.d.ts +5 -5
  188. package/js/src/zaif.d.ts +6 -5
  189. package/js/src/zaif.js +57 -71
  190. package/js/src/zonda.d.ts +7 -6
  191. package/js/src/zonda.js +67 -70
  192. package/package.json +1 -1
  193. package/skip-tests.json +0 -15
  194. package/test.ts +0 -0
  195. package/js/src/abstract/bitstamp1.d.ts +0 -26
  196. package/js/src/abstract/bitstamp1.js +0 -11
  197. package/js/src/abstract/lbank2.d.ts +0 -64
  198. package/js/src/abstract/lbank2.js +0 -11
@@ -2,16 +2,16 @@
2
2
 
3
3
  var lbank$1 = require('./abstract/lbank.js');
4
4
  var errors = require('./base/errors.js');
5
- var Precise = require('./base/Precise.js');
6
5
  var number = require('./base/functions/number.js');
6
+ var Precise = require('./base/Precise.js');
7
7
  var md5 = require('./static_dependencies/noble-hashes/md5.js');
8
- var rsa = require('./base/functions/rsa.js');
9
8
  var sha256 = require('./static_dependencies/noble-hashes/sha256.js');
9
+ var rsa = require('./base/functions/rsa.js');
10
10
 
11
11
  // ---------------------------------------------------------------------------
12
12
  // ---------------------------------------------------------------------------
13
13
  /**
14
- * @class lbank
14
+ * @class lbank2
15
15
  * @extends Exchange
16
16
  */
17
17
  class lbank extends lbank$1 {
@@ -20,15 +20,19 @@ class lbank extends lbank$1 {
20
20
  'id': 'lbank',
21
21
  'name': 'LBank',
22
22
  'countries': ['CN'],
23
- 'version': 'v1',
23
+ 'version': 'v2',
24
+ // 50 per second for making and cancelling orders 1000ms / 50 = 20
25
+ // 20 per second for all other requests, cost = 50 / 20 = 2.5
26
+ 'rateLimit': 20,
24
27
  'has': {
25
- 'CORS': undefined,
28
+ 'CORS': false,
26
29
  'spot': true,
27
30
  'margin': false,
28
- 'swap': false,
31
+ 'swap': undefined,
29
32
  'future': false,
30
33
  'option': false,
31
34
  'addMargin': false,
35
+ 'cancelAllOrders': true,
32
36
  'cancelOrder': true,
33
37
  'createOrder': true,
34
38
  'createReduceOnlyOrder': false,
@@ -41,20 +45,23 @@ class lbank extends lbank$1 {
41
45
  'fetchBorrowRateHistory': false,
42
46
  'fetchBorrowRates': false,
43
47
  'fetchBorrowRatesPerSymbol': false,
44
- 'fetchClosedOrders': true,
48
+ 'fetchClosedOrders': false,
49
+ 'fetchDepositWithdrawFee': 'emulated',
50
+ 'fetchDepositWithdrawFees': true,
45
51
  'fetchFundingHistory': false,
46
52
  'fetchFundingRate': false,
47
53
  'fetchFundingRateHistory': false,
48
54
  'fetchFundingRates': false,
49
55
  'fetchIndexOHLCV': false,
56
+ 'fetchIsolatedPositions': false,
50
57
  'fetchLeverage': false,
51
58
  'fetchLeverageTiers': false,
52
59
  'fetchMarginMode': false,
53
60
  'fetchMarkets': true,
54
61
  'fetchMarkOHLCV': false,
62
+ 'fetchMyTrades': true,
55
63
  'fetchOHLCV': true,
56
- 'fetchOpenInterestHistory': false,
57
- 'fetchOpenOrders': false,
64
+ 'fetchOpenOrders': true,
58
65
  'fetchOrder': true,
59
66
  'fetchOrderBook': true,
60
67
  'fetchOrders': true,
@@ -65,9 +72,10 @@ class lbank extends lbank$1 {
65
72
  'fetchPremiumIndexOHLCV': false,
66
73
  'fetchTicker': true,
67
74
  'fetchTickers': true,
75
+ 'fetchTime': true,
68
76
  'fetchTrades': true,
69
- 'fetchTradingFee': false,
70
- 'fetchTradingFees': false,
77
+ 'fetchTradingFees': true,
78
+ 'fetchTransactionFees': true,
71
79
  'reduceMargin': false,
72
80
  'setLeverage': false,
73
81
  'setMarginMode': false,
@@ -92,35 +100,95 @@ class lbank extends lbank$1 {
92
100
  'logo': 'https://user-images.githubusercontent.com/1294454/38063602-9605e28a-3302-11e8-81be-64b1e53c4cfb.jpg',
93
101
  'api': {
94
102
  'rest': 'https://api.lbank.info',
103
+ 'contract': 'https://lbkperp.lbank.com',
95
104
  },
105
+ 'api2': 'https://api.lbkex.com',
96
106
  'www': 'https://www.lbank.info',
97
- 'doc': 'https://github.com/LBank-exchange/lbank-official-api-docs',
98
- 'fees': 'https://www.lbank.info/fees.html',
107
+ 'doc': 'https://www.lbank.info/en-US/docs/index.html',
108
+ 'fees': 'https://lbankinfo.zendesk.com/hc/en-gb/articles/360012072873-Trading-Fees',
99
109
  'referral': 'https://www.lbank.info/invitevip?icode=7QCY',
100
110
  },
101
111
  'api': {
102
- 'public': {
103
- 'get': [
104
- 'currencyPairs',
105
- 'ticker',
106
- 'depth',
107
- 'trades',
108
- 'kline',
109
- 'accuracy',
110
- ],
112
+ 'spot': {
113
+ 'public': {
114
+ 'get': {
115
+ 'currencyPairs': 2.5,
116
+ 'accuracy': 2.5,
117
+ 'usdToCny': 2.5,
118
+ 'withdrawConfigs': 2.5,
119
+ 'timestamp': 2.5,
120
+ 'ticker/24hr': 2.5,
121
+ 'ticker': 2.5,
122
+ 'depth': 2.5,
123
+ 'incrDepth': 2.5,
124
+ 'trades': 2.5,
125
+ 'kline': 2.5,
126
+ // new quote endpoints
127
+ 'supplement/system_ping': 2.5,
128
+ 'supplement/incrDepth': 2.5,
129
+ 'supplement/trades': 2.5,
130
+ 'supplement/ticker/price': 2.5,
131
+ 'supplement/ticker/bookTicker': 2.5,
132
+ },
133
+ 'post': {
134
+ 'supplement/system_status': 2.5,
135
+ },
136
+ },
137
+ 'private': {
138
+ 'post': {
139
+ // account
140
+ 'user_info': 2.5,
141
+ 'subscribe/get_key': 2.5,
142
+ 'subscribe/refresh_key': 2.5,
143
+ 'subscribe/destroy_key': 2.5,
144
+ 'get_deposit_address': 2.5,
145
+ 'deposit_history': 2.5,
146
+ // order
147
+ 'create_order': 1,
148
+ 'batch_create_order': 1,
149
+ 'cancel_order': 1,
150
+ 'cancel_clientOrders': 1,
151
+ 'orders_info': 2.5,
152
+ 'orders_info_history': 2.5,
153
+ 'order_transaction_detail': 2.5,
154
+ 'transaction_history': 2.5,
155
+ 'orders_info_no_deal': 2.5,
156
+ // withdraw
157
+ 'withdraw': 2.5,
158
+ 'withdrawCancel': 2.5,
159
+ 'withdraws': 2.5,
160
+ 'supplement/user_info': 2.5,
161
+ 'supplement/withdraw': 2.5,
162
+ 'supplement/deposit_history': 2.5,
163
+ 'supplement/withdraws': 2.5,
164
+ 'supplement/get_deposit_address': 2.5,
165
+ 'supplement/asset_detail': 2.5,
166
+ 'supplement/customer_trade_fee': 2.5,
167
+ 'supplement/api_Restrictions': 2.5,
168
+ // new quote endpoints
169
+ 'supplement/system_ping': 2.5,
170
+ // new order endpoints
171
+ 'supplement/create_order_test': 1,
172
+ 'supplement/create_order': 1,
173
+ 'supplement/cancel_order': 1,
174
+ 'supplement/cancel_order_by_symbol': 1,
175
+ 'supplement/orders_info': 2.5,
176
+ 'supplement/orders_info_no_deal': 2.5,
177
+ 'supplement/orders_info_history': 2.5,
178
+ 'supplement/user_info_account': 2.5,
179
+ 'supplement/transaction_history': 2.5,
180
+ },
181
+ },
111
182
  },
112
- 'private': {
113
- 'post': [
114
- 'user_info',
115
- 'create_order',
116
- 'cancel_order',
117
- 'orders_info',
118
- 'orders_info_history',
119
- 'withdraw',
120
- 'withdrawCancel',
121
- 'withdraws',
122
- 'withdrawConfigs',
123
- ],
183
+ 'contract': {
184
+ 'public': {
185
+ 'get': {
186
+ 'cfd/openApi/v1/pub/getTime': 2.5,
187
+ 'cfd/openApi/v1/pub/instrument': 2.5,
188
+ 'cfd/openApi/v1/pub/marketData': 2.5,
189
+ 'cfd/openApi/v1/pub/marketOrder': 2.5,
190
+ },
191
+ },
124
192
  },
125
193
  },
126
194
  'fees': {
@@ -133,64 +201,188 @@ class lbank extends lbank$1 {
133
201
  },
134
202
  },
135
203
  'commonCurrencies': {
136
- 'GMT': 'GMT Token',
137
- 'PNT': 'Penta',
138
- 'SHINJA': 'SHINJA(1M)',
139
204
  'VET_ERC20': 'VEN',
205
+ 'PNT': 'Penta',
140
206
  },
207
+ 'precisionMode': number.TICK_SIZE,
141
208
  'options': {
142
209
  'cacheSecretAsPem': true,
210
+ 'createMarketBuyOrderRequiresPrice': true,
211
+ 'fetchTrades': {
212
+ 'method': 'spotPublicGetTrades', // or 'spotPublicGetTradesSupplement'
213
+ },
214
+ 'fetchTransactionFees': {
215
+ 'method': 'fetchPrivateTransactionFees', // or 'fetchPublicTransactionFees'
216
+ },
217
+ 'fetchDepositWithdrawFees': {
218
+ 'method': 'fetchPrivateDepositWithdrawFees', // or 'fetchPublicDepositWithdrawFees'
219
+ },
220
+ 'fetchDepositAddress': {
221
+ 'method': 'fetchDepositAddressDefault', // or fetchDepositAddressSupplement
222
+ },
223
+ 'createOrder': {
224
+ 'method': 'spotPrivatePostSupplementCreateOrder', // or spotPrivatePostCreateOrder
225
+ },
226
+ 'fetchOrder': {
227
+ 'method': 'fetchOrderSupplement', // or fetchOrderDefault
228
+ },
229
+ 'fetchBalance': {
230
+ 'method': 'spotPrivatePostSupplementUserInfo', // or spotPrivatePostSupplementUserInfoAccount or spotPrivatePostUserInfo
231
+ },
232
+ 'networks': {
233
+ 'ERC20': 'erc20',
234
+ 'ETH': 'erc20',
235
+ 'TRC20': 'trc20',
236
+ 'TRX': 'trc20',
237
+ 'OMNI': 'omni',
238
+ 'ASA': 'asa',
239
+ 'BEP20': 'bep20(bsc)',
240
+ 'BSC': 'bep20(bsc)',
241
+ 'HT': 'heco',
242
+ 'BNB': 'bep2',
243
+ 'BTC': 'btc',
244
+ 'DOGE': 'dogecoin',
245
+ 'MATIC': 'matic',
246
+ 'POLYGON': 'matic',
247
+ 'OEC': 'oec',
248
+ 'BTCTRON': 'btctron',
249
+ 'XRP': 'xrp',
250
+ // other unusual chains with number of listed currencies supported
251
+ // 'avax c-chain': 1,
252
+ // klay: 12,
253
+ // bta: 1,
254
+ // fantom: 1,
255
+ // celo: 1,
256
+ // sol: 2,
257
+ // zenith: 1,
258
+ // ftm: 5,
259
+ // bep20: 1, (single token with mis-named chain) SSS
260
+ // bitci: 1,
261
+ // sgb: 1,
262
+ // moonbeam: 1,
263
+ // ekta: 1,
264
+ // etl: 1,
265
+ // arbitrum: 1,
266
+ // tpc: 1,
267
+ // ptx: 1
268
+ // }
269
+ },
270
+ 'inverse-networks': {
271
+ 'erc20': 'ERC20',
272
+ 'trc20': 'TRC20',
273
+ 'omni': 'OMNI',
274
+ 'asa': 'ASA',
275
+ 'bep20(bsc)': 'BSC',
276
+ 'bep20': 'BSC',
277
+ 'heco': 'HT',
278
+ 'bep2': 'BNB',
279
+ 'btc': 'BTC',
280
+ 'dogecoin': 'DOGE',
281
+ 'matic': 'MATIC',
282
+ 'oec': 'OEC',
283
+ 'btctron': 'BTCTRON',
284
+ 'xrp': 'XRP',
285
+ },
286
+ 'defaultNetworks': {
287
+ 'USDT': 'TRC20',
288
+ },
143
289
  },
144
- 'precisionMode': number.TICK_SIZE,
145
290
  });
146
291
  }
292
+ async fetchTime(params = {}) {
293
+ /**
294
+ * @method
295
+ * @name lbank2#fetchTime
296
+ * @description fetches the current integer timestamp in milliseconds from the exchange server
297
+ * @see https://www.lbank.info/en-US/docs/index.html#get-timestamp
298
+ * @see https://www.lbank.com/en-US/docs/contract.html#get-the-current-time
299
+ * @param {object} [params] extra parameters specific to the lbank2 api endpoint
300
+ * @returns {int} the current integer timestamp in milliseconds from the exchange server
301
+ */
302
+ let type = undefined;
303
+ [type, params] = this.handleMarketTypeAndParams('fetchTime', undefined, params);
304
+ let response = undefined;
305
+ if (type === 'swap') {
306
+ response = await this.contractPublicGetCfdOpenApiV1PubGetTime(params);
307
+ }
308
+ else {
309
+ response = await this.spotPublicGetTimestamp(params);
310
+ }
311
+ //
312
+ // spot
313
+ //
314
+ // {
315
+ // "result": "true",
316
+ // "data": 1691789627950,
317
+ // "error_code": 0,
318
+ // "ts": 1691789627950
319
+ // }
320
+ //
321
+ // swap
322
+ //
323
+ // {
324
+ // "data": 1691789627950,
325
+ // "error_code": 0,
326
+ // "msg": "Success",
327
+ // "result": "true",
328
+ // "success": true
329
+ // }
330
+ //
331
+ return this.safeInteger(response, 'data');
332
+ }
147
333
  async fetchMarkets(params = {}) {
148
334
  /**
149
335
  * @method
150
- * @name lbank#fetchMarkets
151
- * @description retrieves data on all markets for lbank
336
+ * @name lbank2#fetchMarkets
337
+ * @description retrieves data on all markets for lbank2
338
+ * @see https://www.lbank.com/en-US/docs/index.html#trading-pairs
339
+ * @see https://www.lbank.com/en-US/docs/contract.html#query-contract-information-list
152
340
  * @param {object} [params] extra parameters specific to the exchange api endpoint
153
341
  * @returns {object[]} an array of objects representing market data
154
342
  */
155
- const response = await this.publicGetAccuracy(params);
343
+ const marketsPromises = [
344
+ this.fetchSpotMarkets(params),
345
+ this.fetchSwapMarkets(params),
346
+ ];
347
+ const resolvedMarkets = await Promise.all(marketsPromises);
348
+ return this.arrayConcat(resolvedMarkets[0], resolvedMarkets[1]);
349
+ }
350
+ async fetchSpotMarkets(params = {}) {
351
+ const response = await this.spotPublicGetAccuracy(params);
156
352
  //
157
- // [
158
- // {
159
- // "symbol": "btc_usdt",
160
- // "quantityAccuracy": "4",
161
- // "minTranQua": "0.0001",
162
- // "priceAccuracy": "2"
163
- // },
164
- // ...
165
- // ]
353
+ // {
354
+ // "result": "true",
355
+ // "data": [
356
+ // {
357
+ // "symbol": "btc_usdt",
358
+ // "quantityAccuracy": "4",
359
+ // "minTranQua": "0.0001",
360
+ // "priceAccuracy": "2"
361
+ // },
362
+ // ],
363
+ // "error_code": 0,
364
+ // "ts": 1691560288484
365
+ // }
166
366
  //
367
+ const data = this.safeValue(response, 'data', []);
167
368
  const result = [];
168
- for (let i = 0; i < response.length; i++) {
169
- const market = response[i];
170
- const id = market['symbol'];
171
- const parts = id.split('_');
172
- let baseId = undefined;
173
- let quoteId = undefined;
174
- const numParts = parts.length;
175
- // lbank will return symbols like "vet_erc20_usdt"
176
- if (numParts > 2) {
177
- baseId = parts[0] + '_' + parts[1];
178
- quoteId = parts[2];
179
- }
180
- else {
181
- baseId = parts[0];
182
- quoteId = parts[1];
183
- }
369
+ for (let i = 0; i < data.length; i++) {
370
+ const market = data[i];
371
+ const marketId = this.safeString(market, 'symbol');
372
+ const parts = marketId.split('_');
373
+ const baseId = parts[0];
374
+ const quoteId = parts[1];
184
375
  const base = this.safeCurrencyCode(baseId);
185
376
  const quote = this.safeCurrencyCode(quoteId);
377
+ const symbol = base + '/' + quote;
186
378
  result.push({
187
- 'id': id,
188
- 'symbol': base + '/' + quote,
379
+ 'id': marketId,
380
+ 'symbol': symbol,
189
381
  'base': base,
190
382
  'quote': quote,
191
- 'settle': undefined,
192
383
  'baseId': baseId,
193
384
  'quoteId': quoteId,
385
+ 'settle': undefined,
194
386
  'settleId': undefined,
195
387
  'type': 'spot',
196
388
  'spot': true,
@@ -217,7 +409,7 @@ class lbank extends lbank$1 {
217
409
  'max': undefined,
218
410
  },
219
411
  'amount': {
220
- 'min': this.safeFloat(market, 'minTranQua'),
412
+ 'min': this.safeNumber(market, 'minTranQua'),
221
413
  'max': undefined,
222
414
  },
223
415
  'price': {
@@ -230,178 +422,499 @@ class lbank extends lbank$1 {
230
422
  },
231
423
  },
232
424
  'created': undefined,
233
- 'info': id,
425
+ 'info': market,
426
+ });
427
+ }
428
+ return result;
429
+ }
430
+ async fetchSwapMarkets(params = {}) {
431
+ const request = {
432
+ 'productGroup': 'SwapU',
433
+ };
434
+ const response = await this.contractPublicGetCfdOpenApiV1PubInstrument(this.extend(request, params));
435
+ //
436
+ // {
437
+ // "data": [
438
+ // {
439
+ // "priceLimitUpperValue": 0.2,
440
+ // "symbol": "BTCUSDT",
441
+ // "volumeTick": 0.0001,
442
+ // "indexPrice": "29707.70200000",
443
+ // "minOrderVolume": "0.0001",
444
+ // "priceTick": 0.1,
445
+ // "maxOrderVolume": "30.0",
446
+ // "baseCurrency": "BTC",
447
+ // "volumeMultiple": 1.0,
448
+ // "exchangeID": "Exchange",
449
+ // "priceCurrency": "USDT",
450
+ // "priceLimitLowerValue": 0.2,
451
+ // "clearCurrency": "USDT",
452
+ // "symbolName": "BTCUSDT",
453
+ // "defaultLeverage": 20.0,
454
+ // "minOrderCost": "5.0"
455
+ // },
456
+ // ],
457
+ // "error_code": 0,
458
+ // "msg": "Success",
459
+ // "result": "true",
460
+ // "success": true
461
+ // }
462
+ //
463
+ const data = this.safeValue(response, 'data', []);
464
+ const result = [];
465
+ for (let i = 0; i < data.length; i++) {
466
+ const market = data[i];
467
+ const marketId = this.safeString(market, 'symbol');
468
+ const baseId = this.safeString(market, 'baseCurrency');
469
+ const settleId = this.safeString(market, 'clearCurrency');
470
+ const quoteId = settleId;
471
+ const base = this.safeCurrencyCode(baseId);
472
+ const quote = this.safeCurrencyCode(quoteId);
473
+ const settle = this.safeCurrencyCode(settleId);
474
+ const symbol = base + '/' + quote + ':' + settle;
475
+ result.push({
476
+ 'id': marketId,
477
+ 'symbol': symbol,
478
+ 'base': base,
479
+ 'quote': quote,
480
+ 'settle': settle,
481
+ 'baseId': baseId,
482
+ 'quoteId': quoteId,
483
+ 'settleId': settleId,
484
+ 'type': 'swap',
485
+ 'spot': false,
486
+ 'margin': false,
487
+ 'swap': true,
488
+ 'future': false,
489
+ 'option': false,
490
+ 'active': true,
491
+ 'contract': true,
492
+ 'linear': true,
493
+ 'inverse': undefined,
494
+ 'contractSize': this.safeNumber(market, 'volumeMultiple'),
495
+ 'expiry': undefined,
496
+ 'expiryDatetime': undefined,
497
+ 'strike': undefined,
498
+ 'optionType': undefined,
499
+ 'precision': {
500
+ 'amount': this.safeNumber(market, 'volumeTick'),
501
+ 'price': this.safeNumber(market, 'priceTick'),
502
+ },
503
+ 'limits': {
504
+ 'leverage': {
505
+ 'min': undefined,
506
+ 'max': undefined,
507
+ },
508
+ 'amount': {
509
+ 'min': this.safeNumber(market, 'minOrderVolume'),
510
+ 'max': this.safeNumber(market, 'maxOrderVolume'),
511
+ },
512
+ 'price': {
513
+ 'min': this.safeNumber(market, 'priceLimitLowerValue'),
514
+ 'max': this.safeNumber(market, 'priceLimitUpperValue'),
515
+ },
516
+ 'cost': {
517
+ 'min': this.safeNumber(market, 'minOrderCost'),
518
+ 'max': undefined,
519
+ },
520
+ },
521
+ 'created': undefined,
522
+ 'info': market,
234
523
  });
235
524
  }
236
525
  return result;
237
526
  }
238
527
  parseTicker(ticker, market = undefined) {
528
+ //
529
+ // spot: fetchTicker, fetchTickers
239
530
  //
240
531
  // {
241
- // "symbol":"btc_usdt",
242
- // "ticker":{
243
- // "high":43416.06,
244
- // "vol":7031.7427,
245
- // "low":41804.26,
246
- // "change":1.33,
247
- // "turnover":300302447.81,
248
- // "latest":43220.4
532
+ // "symbol": "btc_usdt",
533
+ // "ticker": {
534
+ // "high": "29695.57",
535
+ // "vol": "6890.2789",
536
+ // "low": "29110",
537
+ // "change": "0.58",
538
+ // "turnover": "202769821.06",
539
+ // "latest": "29405.98"
249
540
  // },
250
- // "timestamp":1642201617747
541
+ // "timestamp": :1692064274908
542
+ // }
543
+ //
544
+ // swap: fetchTickers
545
+ //
546
+ // {
547
+ // "prePositionFeeRate": "0.000053",
548
+ // "volume": "2435.459",
549
+ // "symbol": "BTCUSDT",
550
+ // "highestPrice": "29446.5",
551
+ // "lowestPrice": "29362.9",
552
+ // "openPrice": "29419.5",
553
+ // "markedPrice": "29385.1",
554
+ // "turnover": "36345526.2438402",
555
+ // "lastPrice": "29387.0"
251
556
  // }
252
557
  //
253
- const marketId = this.safeString(ticker, 'symbol');
254
- market = this.safeMarket(marketId, market, '_');
255
- const symbol = market['symbol'];
256
558
  const timestamp = this.safeInteger(ticker, 'timestamp');
257
- const info = ticker;
258
- ticker = info['ticker'];
259
- const last = this.safeString(ticker, 'latest');
260
- const percentage = this.safeString(ticker, 'change');
559
+ const marketId = this.safeString(ticker, 'symbol');
560
+ const symbol = this.safeSymbol(marketId, market);
561
+ const tickerData = this.safeValue(ticker, 'ticker', {});
562
+ market = this.safeMarket(marketId, market);
563
+ const data = (market['contract']) ? ticker : tickerData;
261
564
  return this.safeTicker({
262
565
  'symbol': symbol,
263
566
  'timestamp': timestamp,
264
567
  'datetime': this.iso8601(timestamp),
265
- 'high': this.safeString(ticker, 'high'),
266
- 'low': this.safeString(ticker, 'low'),
568
+ 'high': this.safeString2(data, 'high', 'highestPrice'),
569
+ 'low': this.safeString2(data, 'low', 'lowestPrice'),
267
570
  'bid': undefined,
268
571
  'bidVolume': undefined,
269
572
  'ask': undefined,
270
573
  'askVolume': undefined,
271
574
  'vwap': undefined,
272
- 'open': undefined,
273
- 'close': last,
274
- 'last': last,
575
+ 'open': this.safeString(data, 'openPrice'),
576
+ 'close': undefined,
577
+ 'last': this.safeString2(data, 'latest', 'lastPrice'),
275
578
  'previousClose': undefined,
276
579
  'change': undefined,
277
- 'percentage': percentage,
580
+ 'percentage': this.safeString(data, 'change'),
278
581
  'average': undefined,
279
- 'baseVolume': this.safeString(ticker, 'vol'),
280
- 'quoteVolume': this.safeString(ticker, 'turnover'),
281
- 'info': info,
582
+ 'baseVolume': this.safeString2(data, 'vol', 'volume'),
583
+ 'quoteVolume': this.safeString(data, 'turnover'),
584
+ 'info': ticker,
282
585
  }, market);
283
586
  }
284
587
  async fetchTicker(symbol, params = {}) {
285
588
  /**
286
589
  * @method
287
- * @name lbank#fetchTicker
590
+ * @name lbank2#fetchTicker
288
591
  * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
592
+ * @see https://www.lbank.info/en-US/docs/index.html#query-current-market-data-new
289
593
  * @param {string} symbol unified symbol of the market to fetch the ticker for
290
- * @param {object} [params] extra parameters specific to the lbank api endpoint
594
+ * @param {object} [params] extra parameters specific to the lbank2 api endpoint
291
595
  * @returns {object} a [ticker structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#ticker-structure}
292
596
  */
293
597
  await this.loadMarkets();
294
598
  const market = this.market(symbol);
599
+ if (market['swap']) {
600
+ const responseForSwap = await this.fetchTickers([market['symbol']], params);
601
+ return this.safeValue(responseForSwap, market['symbol']);
602
+ }
295
603
  const request = {
296
604
  'symbol': market['id'],
297
605
  };
298
- const response = await this.publicGetTicker(this.extend(request, params));
299
- // {
300
- // "symbol":"btc_usdt",
301
- // "ticker":{
302
- // "high":43416.06,
303
- // "vol":7031.7427,
304
- // "low":41804.26,
305
- // "change":1.33,
306
- // "turnover":300302447.81,
307
- // "latest":43220.4
308
- // },
309
- // "timestamp":1642201617747
310
- // }
311
- return this.parseTicker(response, market);
606
+ const response = await this.spotPublicGetTicker24hr(this.extend(request, params));
607
+ //
608
+ // {
609
+ // "result": "true",
610
+ // "data": [
611
+ // {
612
+ // "symbol": "btc_usdt",
613
+ // "ticker": {
614
+ // "high": "29695.57",
615
+ // "vol": "6890.2789",
616
+ // "low": "29110",
617
+ // "change": "0.58",
618
+ // "turnover": "202769821.06",
619
+ // "latest": "29405.98"
620
+ // },
621
+ // "timestamp": :1692064274908
622
+ // }
623
+ // ],
624
+ // "error_code": 0,
625
+ // "ts": :1692064276872
626
+ // }
627
+ //
628
+ const data = this.safeValue(response, 'data', []);
629
+ const first = this.safeValue(data, 0, {});
630
+ return this.parseTicker(first, market);
312
631
  }
313
632
  async fetchTickers(symbols = undefined, params = {}) {
314
633
  /**
315
634
  * @method
316
- * @name lbank#fetchTickers
635
+ * @name lbank2#fetchTickers
317
636
  * @description fetches price tickers for multiple markets, statistical calculations with the information calculated over the past 24 hours each market
637
+ * @see https://www.lbank.info/en-US/docs/index.html#query-current-market-data-new
638
+ * @see https://www.lbank.com/en-US/docs/contract.html#query-contract-market-list
318
639
  * @param {string[]|undefined} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
319
640
  * @param {object} [params] extra parameters specific to the lbank api endpoint
320
641
  * @returns {object} a dictionary of [ticker structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#ticker-structure}
321
642
  */
322
643
  await this.loadMarkets();
323
- symbols = this.marketSymbols(symbols);
324
- const request = {
325
- 'symbol': 'all',
326
- };
327
- const response = await this.publicGetTicker(this.extend(request, params));
328
- const result = {};
329
- for (let i = 0; i < response.length; i++) {
330
- const ticker = this.parseTicker(response[i]);
331
- const symbol = ticker['symbol'];
332
- result[symbol] = ticker;
644
+ let market = undefined;
645
+ if (symbols !== undefined) {
646
+ symbols = this.marketSymbols(symbols);
647
+ const symbolsLength = symbols.length;
648
+ if (symbolsLength > 0) {
649
+ market = this.market(symbols[0]);
650
+ }
651
+ }
652
+ const request = {};
653
+ let type = undefined;
654
+ [type, params] = this.handleMarketTypeAndParams('fetchTickers', market, params);
655
+ let response = undefined;
656
+ if (type === 'swap') {
657
+ request['productGroup'] = 'SwapU';
658
+ response = await this.contractPublicGetCfdOpenApiV1PubMarketData(this.extend(request, params));
659
+ }
660
+ else {
661
+ request['symbol'] = 'all';
662
+ response = await this.spotPublicGetTicker24hr(this.extend(request, params));
333
663
  }
334
- return this.filterByArrayTickers(result, 'symbol', symbols);
664
+ //
665
+ // spot
666
+ //
667
+ // {
668
+ // "result": "true",
669
+ // "data": [
670
+ // {
671
+ // "symbol": "btc_usdt",
672
+ // "ticker": {
673
+ // "high": "29695.57",
674
+ // "vol": "6890.2789",
675
+ // "low": "29110",
676
+ // "change": "0.58",
677
+ // "turnover": "202769821.06",
678
+ // "latest": "29405.98"
679
+ // },
680
+ // "timestamp": :1692064274908
681
+ // }
682
+ // ],
683
+ // "error_code": 0,
684
+ // "ts": :1692064276872
685
+ // }
686
+ //
687
+ // swap
688
+ //
689
+ // {
690
+ // "data": [
691
+ // {
692
+ // "prePositionFeeRate": "0.000053",
693
+ // "volume": "2435.459",
694
+ // "symbol": "BTCUSDT",
695
+ // "highestPrice": "29446.5",
696
+ // "lowestPrice": "29362.9",
697
+ // "openPrice": "29419.5",
698
+ // "markedPrice": "29385.1",
699
+ // "turnover": "36345526.2438402",
700
+ // "lastPrice": "29387.0"
701
+ // },
702
+ // ],
703
+ // "error_code": 0,
704
+ // "msg": "Success",
705
+ // "result": "true",
706
+ // "success": true
707
+ // }
708
+ //
709
+ const data = this.safeValue(response, 'data', []);
710
+ return this.parseTickers(data, symbols);
335
711
  }
336
- async fetchOrderBook(symbol, limit = 60, params = {}) {
712
+ async fetchOrderBook(symbol, limit = undefined, params = {}) {
337
713
  /**
338
714
  * @method
339
- * @name lbank#fetchOrderBook
715
+ * @name lbank2#fetchOrderBook
340
716
  * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data
717
+ * @see https://www.lbank.info/en-US/docs/index.html#query-market-depth
718
+ * @see https://www.lbank.com/en-US/docs/contract.html#get-handicap
341
719
  * @param {string} symbol unified symbol of the market to fetch the order book for
342
720
  * @param {int} [limit] the maximum amount of order book entries to return
343
- * @param {object} [params] extra parameters specific to the lbank api endpoint
721
+ * @param {object} [params] extra parameters specific to the lbank2 api endpoint
344
722
  * @returns {object} A dictionary of [order book structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-book-structure} indexed by market symbols
345
723
  */
346
724
  await this.loadMarkets();
347
- let size = 60;
348
- if (limit !== undefined) {
349
- size = Math.min(limit, size);
350
- }
351
725
  const market = this.market(symbol);
726
+ if (limit === undefined) {
727
+ limit = 60;
728
+ }
352
729
  const request = {
353
730
  'symbol': market['id'],
354
- 'size': size,
355
731
  };
356
- const response = await this.publicGetDepth(this.extend(request, params));
357
- return this.parseOrderBook(response, market['symbol']);
732
+ let type = undefined;
733
+ [type, params] = this.handleMarketTypeAndParams('fetchOrderBook', market, params);
734
+ let response = undefined;
735
+ if (type === 'swap') {
736
+ request['depth'] = limit;
737
+ response = await this.contractPublicGetCfdOpenApiV1PubMarketOrder(this.extend(request, params));
738
+ }
739
+ else {
740
+ request['size'] = limit;
741
+ response = await this.spotPublicGetDepth(this.extend(request, params));
742
+ }
743
+ //
744
+ // spot
745
+ //
746
+ // {
747
+ // "result": "true",
748
+ // "data": {
749
+ // "asks": [
750
+ // ["29243.37", "2.8783"],
751
+ // ["29243.39", "2.2842"],
752
+ // ["29243.4", "0.0337"]
753
+ // ],
754
+ // "bids": [
755
+ // ["29243.36", "1.5258"],
756
+ // ["29243.34", "0.8218"],
757
+ // ["29243.28", "1.285"]
758
+ // ],
759
+ // "timestamp": :1692157328820
760
+ // },
761
+ // "error_code": 0,
762
+ // "ts": :1692157328820
763
+ // }
764
+ //
765
+ // swap
766
+ //
767
+ // {
768
+ // "data": {
769
+ // "symbol": "BTCUSDT",
770
+ // "asks": [
771
+ // {
772
+ // "volume": "14.6535",
773
+ // "price": "29234.2",
774
+ // "orders": "1"
775
+ // },
776
+ // ],
777
+ // "bids": [
778
+ // {
779
+ // "volume": "13.4899",
780
+ // "price": "29234.1",
781
+ // "orders": "4"
782
+ // },
783
+ // ]
784
+ // },
785
+ // "error_code": 0,
786
+ // "msg": "Success",
787
+ // "result": "true",
788
+ // "success": true
789
+ // }
790
+ //
791
+ const orderbook = this.safeValue(response, 'data', {});
792
+ const timestamp = this.milliseconds();
793
+ if (market['swap']) {
794
+ return this.parseOrderBook(orderbook, market['symbol'], timestamp, 'bids', 'asks', 'price', 'volume');
795
+ }
796
+ return this.parseOrderBook(orderbook, market['symbol'], timestamp);
358
797
  }
359
798
  parseTrade(trade, market = undefined) {
360
- market = this.safeMarket(undefined, market);
361
- const timestamp = this.safeInteger(trade, 'date_ms');
362
- const priceString = this.safeString(trade, 'price');
363
- const amountString = this.safeString(trade, 'amount');
364
- const price = this.parseNumber(priceString);
365
- const amount = this.parseNumber(amountString);
366
- const cost = this.parseNumber(Precise["default"].stringMul(priceString, amountString));
367
- const id = this.safeString(trade, 'tid');
368
- const type = undefined;
369
- let side = this.safeString(trade, 'type');
370
- // remove type additions from i.e. buy_maker, sell_maker, buy_ioc, sell_ioc, buy_fok, sell_fok
371
- const splited = side.split('_');
372
- side = splited[0];
373
- return {
374
- 'id': id,
375
- 'info': this.safeValue(trade, 'info', trade),
799
+ //
800
+ // fetchTrades (old) spotPublicGetTrades
801
+ //
802
+ // {
803
+ // "date_ms":1647021989789,
804
+ // "amount":0.0028,
805
+ // "price":38804.2,
806
+ // "type":"buy",
807
+ // "tid":"52d5616ee35c43019edddebe59b3e094"
808
+ // }
809
+ //
810
+ //
811
+ // fetchTrades (new) spotPublicGetTradesSupplement
812
+ //
813
+ // {
814
+ // "quoteQty":1675.048485,
815
+ // "price":0.127545,
816
+ // "qty":13133,
817
+ // "id":"3589541dc22e4357b227283650f714e2",
818
+ // "time":1648058297110,
819
+ // "isBuyerMaker":false
820
+ // }
821
+ //
822
+ // fetchMyTrades (private)
823
+ //
824
+ // {
825
+ // "orderUuid":"38b4e7a4-14f6-45fd-aba1-1a37024124a0",
826
+ // "tradeFeeRate":0.0010000000,
827
+ // "dealTime":1648500944496,
828
+ // "dealQuantity":30.00000000000000000000,
829
+ // "tradeFee":0.00453300000000000000,
830
+ // "txUuid":"11f3850cc6214ea3b495adad3a032794",
831
+ // "dealPrice":0.15111300000000000000,
832
+ // "dealVolumePrice":4.53339000000000000000,
833
+ // "tradeType":"sell_market"
834
+ // }
835
+ //
836
+ let timestamp = this.safeInteger2(trade, 'date_ms', 'time');
837
+ if (timestamp === undefined) {
838
+ timestamp = this.safeInteger(trade, 'dealTime');
839
+ }
840
+ let amountString = this.safeString2(trade, 'amount', 'qty');
841
+ if (amountString === undefined) {
842
+ amountString = this.safeString(trade, 'dealQuantity');
843
+ }
844
+ let priceString = this.safeString(trade, 'price');
845
+ if (priceString === undefined) {
846
+ priceString = this.safeString(trade, 'dealPrice');
847
+ }
848
+ let costString = this.safeString(trade, 'quoteQty');
849
+ if (costString === undefined) {
850
+ costString = this.safeString(trade, 'dealVolumePrice');
851
+ }
852
+ let side = this.safeString2(trade, 'tradeType', 'type');
853
+ let type = undefined;
854
+ let takerOrMaker = undefined;
855
+ if (side !== undefined) {
856
+ const parts = side.split('_');
857
+ side = this.safeString(parts, 0);
858
+ const typePart = this.safeString(parts, 1);
859
+ type = 'limit';
860
+ takerOrMaker = 'taker';
861
+ if (typePart !== undefined) {
862
+ if (typePart === 'market') {
863
+ type = 'market';
864
+ }
865
+ else if (typePart === 'maker') {
866
+ takerOrMaker = 'maker';
867
+ }
868
+ }
869
+ }
870
+ let id = this.safeString2(trade, 'tid', 'id');
871
+ if (id === undefined) {
872
+ id = this.safeString(trade, 'txUuid');
873
+ }
874
+ const order = this.safeString(trade, 'orderUuid');
875
+ const symbol = this.safeSymbol(undefined, market);
876
+ let fee = undefined;
877
+ const feeCost = this.safeString(trade, 'tradeFee');
878
+ if (feeCost !== undefined) {
879
+ fee = {
880
+ 'cost': feeCost,
881
+ 'currency': (side === 'buy') ? market['base'] : market['quote'],
882
+ 'rate': this.safeString(trade, 'tradeFeeRate'),
883
+ };
884
+ }
885
+ return this.safeTrade({
376
886
  'timestamp': timestamp,
377
887
  'datetime': this.iso8601(timestamp),
378
- 'symbol': market['symbol'],
379
- 'order': undefined,
888
+ 'symbol': symbol,
889
+ 'id': id,
890
+ 'order': order,
380
891
  'type': type,
892
+ 'takerOrMaker': takerOrMaker,
381
893
  'side': side,
382
- 'takerOrMaker': undefined,
383
- 'price': price,
384
- 'amount': amount,
385
- 'cost': cost,
386
- 'fee': undefined,
387
- };
894
+ 'price': priceString,
895
+ 'amount': amountString,
896
+ 'cost': costString,
897
+ 'fee': fee,
898
+ 'info': trade,
899
+ }, market);
388
900
  }
389
901
  async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) {
390
902
  /**
391
903
  * @method
392
- * @name lbank#fetchTrades
904
+ * @name lbank2#fetchTrades
393
905
  * @description get the list of most recent trades for a particular symbol
906
+ * @see https://www.lbank.info/en-US/docs/index.html#query-historical-transactions
907
+ * @see https://www.lbank.info/en-US/docs/index.html#recent-transactions-list
394
908
  * @param {string} symbol unified symbol of the market to fetch trades for
395
909
  * @param {int} [since] timestamp in ms of the earliest trade to fetch
396
910
  * @param {int} [limit] the maximum amount of trades to fetch
397
- * @param {object} [params] extra parameters specific to the lbank api endpoint
911
+ * @param {object} [params] extra parameters specific to the lbank2 api endpoint
398
912
  * @returns {Trade[]} a list of [trade structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#public-trades}
399
913
  */
400
914
  await this.loadMarkets();
401
915
  const market = this.market(symbol);
402
916
  const request = {
403
917
  'symbol': market['id'],
404
- 'size': 100,
405
918
  };
406
919
  if (since !== undefined) {
407
920
  request['time'] = since;
@@ -409,19 +922,45 @@ class lbank extends lbank$1 {
409
922
  if (limit !== undefined) {
410
923
  request['size'] = Math.min(limit, 600);
411
924
  }
412
- const response = await this.publicGetTrades(this.extend(request, params));
413
- return this.parseTrades(response, market, since, limit);
925
+ else {
926
+ request['size'] = 600; // max
927
+ }
928
+ let method = this.safeString(params, 'method');
929
+ params = this.omit(params, 'method');
930
+ if (method === undefined) {
931
+ const options = this.safeValue(this.options, 'fetchTrades', {});
932
+ method = this.safeString(options, 'method', 'spotPublicGetTrades');
933
+ }
934
+ const response = await this[method](this.extend(request, params));
935
+ //
936
+ // {
937
+ // "result":"true",
938
+ // "data": [
939
+ // {
940
+ // "date_ms":1647021989789,
941
+ // "amount":0.0028,
942
+ // "price":38804.2,
943
+ // "type":"buy",
944
+ // "tid":"52d5616ee35c43019edddebe59b3e094"
945
+ // }
946
+ // ],
947
+ // "error_code":0,
948
+ // "ts":1647021999308
949
+ // }
950
+ //
951
+ const trades = this.safeValue(response, 'data', []);
952
+ return this.parseTrades(trades, market, since, limit);
414
953
  }
415
954
  parseOHLCV(ohlcv, market = undefined) {
416
955
  //
417
- // [
418
- // 1590969600,
419
- // 0.02451657,
420
- // 0.02452675,
421
- // 0.02443701,
422
- // 0.02447814,
423
- // 238.38210000
424
- // ]
956
+ // [
957
+ // 1482311500, // timestamp
958
+ // 5423.23, // open
959
+ // 5472.80, // high
960
+ // 5516.09, // low
961
+ // 5462, // close
962
+ // 234.3250 // volume
963
+ // ],
425
964
  //
426
965
  return [
427
966
  this.safeTimestamp(ohlcv, 0),
@@ -429,25 +968,27 @@ class lbank extends lbank$1 {
429
968
  this.safeNumber(ohlcv, 2),
430
969
  this.safeNumber(ohlcv, 3),
431
970
  this.safeNumber(ohlcv, 4),
432
- this.safeNumber(ohlcv, 5),
971
+ this.safeNumber(ohlcv, 5), // volume
433
972
  ];
434
973
  }
435
- async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = 1000, params = {}) {
974
+ async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
436
975
  /**
437
976
  * @method
438
- * @name lbank#fetchOHLCV
977
+ * @name lbank2#fetchOHLCV
439
978
  * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
979
+ * @see https://www.lbank.info/en-US/docs/index.html#query-k-bar-data
440
980
  * @param {string} symbol unified symbol of the market to fetch OHLCV data for
441
981
  * @param {string} timeframe the length of time each candle represents
442
982
  * @param {int} [since] timestamp in ms of the earliest candle to fetch
443
983
  * @param {int} [limit] the maximum amount of candles to fetch
444
- * @param {object} [params] extra parameters specific to the lbank api endpoint
984
+ * @param {object} [params] extra parameters specific to the lbank2 api endpoint
445
985
  * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume
446
986
  */
987
+ // endpoint doesnt work
447
988
  await this.loadMarkets();
448
989
  const market = this.market(symbol);
449
990
  if (limit === undefined) {
450
- limit = 100; // it's defined in lbank2
991
+ limit = 100;
451
992
  }
452
993
  if (since === undefined) {
453
994
  const duration = this.parseTimeframe(timeframe);
@@ -456,428 +997,1777 @@ class lbank extends lbank$1 {
456
997
  const request = {
457
998
  'symbol': market['id'],
458
999
  'type': this.safeString(this.timeframes, timeframe, timeframe),
459
- 'size': limit,
460
1000
  'time': this.parseToInt(since / 1000),
1001
+ 'size': limit, // max 2000
461
1002
  };
462
- const response = await this.publicGetKline(this.extend(request, params));
1003
+ const response = await this.spotPublicGetKline(this.extend(request, params));
1004
+ const ohlcvs = this.safeValue(response, 'data', []);
1005
+ //
463
1006
  //
464
- // [
465
- // [1590969600,0.02451657,0.02452675,0.02443701,0.02447814,238.38210000],
466
- // [1590969660,0.02447814,0.02449883,0.02443209,0.02445973,212.40270000],
467
- // [1590969720,0.02445973,0.02452067,0.02445909,0.02446151,266.16920000],
468
- // ]
1007
+ // [
1008
+ // [
1009
+ // 1482311500,
1010
+ // 5423.23,
1011
+ // 5472.80,
1012
+ // 5516.09,
1013
+ // 5462,
1014
+ // 234.3250
1015
+ // ],
1016
+ // [
1017
+ // 1482311400,
1018
+ // 5432.52,
1019
+ // 5459.87,
1020
+ // 5414.30,
1021
+ // 5428.23,
1022
+ // 213.7329
1023
+ // ]
1024
+ // ]
469
1025
  //
470
- return this.parseOHLCVs(response, market, timeframe, since, limit);
1026
+ return this.parseOHLCVs(ohlcvs, market, timeframe, since, limit);
471
1027
  }
472
1028
  parseBalance(response) {
1029
+ //
1030
+ // spotPrivatePostUserInfo
1031
+ //
1032
+ // {
1033
+ // "toBtc": {
1034
+ // "egc:": "0",
1035
+ // "iog": "0",
1036
+ // "ksm": "0",
1037
+ // },
1038
+ // "freeze": {
1039
+ // "egc": "0",
1040
+ // "iog": "0",
1041
+ // "ksm": "0" ,
1042
+ // },
1043
+ // "asset": {
1044
+ // "egc": "0",
1045
+ // "iog": "0",
1046
+ // "ksm": "0",
1047
+ // },
1048
+ // "free": {
1049
+ // "egc": "0",
1050
+ // "iog": "0",
1051
+ // "ksm": "0",
1052
+ // }
1053
+ // }
1054
+ //
1055
+ // spotPrivatePostSupplementUserInfoAccount
1056
+ //
1057
+ // {
1058
+ // "balances":[
1059
+ // {
1060
+ // "asset":"lbk",
1061
+ // "free":"0",
1062
+ // "locked":"0"
1063
+ // }, ...
1064
+ // ]
1065
+ // }
1066
+ //
1067
+ // spotPrivatePostSupplementUserInfo
1068
+ //
1069
+ // [
1070
+ // {
1071
+ // "usableAmt":"31.45130723",
1072
+ // "assetAmt":"31.45130723",
1073
+ // "networkList":[
1074
+ // {
1075
+ // "isDefault":true,
1076
+ // "withdrawFeeRate":"",
1077
+ // "name":"bep20(bsc)",
1078
+ // "withdrawMin":30,
1079
+ // "minLimit":0.0001,
1080
+ // "minDeposit":0.0001,
1081
+ // "feeAssetCode":"doge",
1082
+ // "withdrawFee":"30",
1083
+ // "type":1,
1084
+ // "coin":"doge",
1085
+ // "network":"bsc"
1086
+ // },
1087
+ // {
1088
+ // "isDefault":false,
1089
+ // "withdrawFeeRate":"",
1090
+ // "name":"dogecoin",
1091
+ // "withdrawMin":10,
1092
+ // "minLimit":0.0001,
1093
+ // "minDeposit":10,
1094
+ // "feeAssetCode":"doge",
1095
+ // "withdrawFee":"10",
1096
+ // "type":1,
1097
+ // "coin":"doge",
1098
+ // "network":"dogecoin"
1099
+ // }
1100
+ // ],
1101
+ // "freezeAmt":"0",
1102
+ // "coin":"doge"
1103
+ // }, ...
1104
+ // ]
1105
+ //
1106
+ const timestamp = this.safeInteger(response, 'ts');
473
1107
  const result = {
474
1108
  'info': response,
475
- 'timestamp': undefined,
476
- 'datetime': undefined,
1109
+ 'timestamp': timestamp,
1110
+ 'datetime': this.iso8601(timestamp),
477
1111
  };
478
- const info = this.safeValue(response, 'info', {});
479
- const free = this.safeValue(info, 'free', {});
480
- const freeze = this.safeValue(info, 'freeze', {});
481
- const asset = this.safeValue(info, 'asset', {});
482
- const currencyIds = Object.keys(free);
483
- for (let i = 0; i < currencyIds.length; i++) {
484
- const currencyId = currencyIds[i];
485
- const code = this.safeCurrencyCode(currencyId);
486
- const account = this.account();
487
- account['free'] = this.safeString(free, currencyId);
488
- account['used'] = this.safeString(freeze, currencyId);
489
- account['total'] = this.safeString(asset, currencyId);
490
- result[code] = account;
1112
+ const data = this.safeValue(response, 'data');
1113
+ // from spotPrivatePostUserInfo
1114
+ const toBtc = this.safeValue(data, 'toBtc');
1115
+ if (toBtc !== undefined) {
1116
+ const used = this.safeValue(data, 'freeze', {});
1117
+ const free = this.safeValue(data, 'free', {});
1118
+ const currencies = Object.keys(free);
1119
+ for (let i = 0; i < currencies.length; i++) {
1120
+ const currencyId = currencies[i];
1121
+ const code = this.safeCurrencyCode(currencyId);
1122
+ const account = this.account();
1123
+ account['used'] = this.safeString(used, currencyId);
1124
+ account['free'] = this.safeString(free, currencyId);
1125
+ result[code] = account;
1126
+ }
1127
+ return this.safeBalance(result);
1128
+ }
1129
+ // from spotPrivatePostSupplementUserInfoAccount
1130
+ const balances = this.safeValue(data, 'balances');
1131
+ if (balances !== undefined) {
1132
+ for (let i = 0; i < balances.length; i++) {
1133
+ const item = balances[i];
1134
+ const currencyId = this.safeString(item, 'asset');
1135
+ const codeInner = this.safeCurrencyCode(currencyId);
1136
+ const account = this.account();
1137
+ account['free'] = this.safeString(item, 'free');
1138
+ account['used'] = this.safeString(item, 'locked');
1139
+ result[codeInner] = account;
1140
+ }
1141
+ return this.safeBalance(result);
1142
+ }
1143
+ // from spotPrivatePostSupplementUserInfo
1144
+ const isArray = Array.isArray(data);
1145
+ if (isArray === true) {
1146
+ for (let i = 0; i < data.length; i++) {
1147
+ const item = data[i];
1148
+ const currencyId = this.safeString(item, 'coin');
1149
+ const codeInner = this.safeCurrencyCode(currencyId);
1150
+ const account = this.account();
1151
+ account['free'] = this.safeString(item, 'usableAmt');
1152
+ account['used'] = this.safeString(item, 'freezeAmt');
1153
+ result[codeInner] = account;
1154
+ }
1155
+ return this.safeBalance(result);
491
1156
  }
492
- return this.safeBalance(result);
1157
+ return undefined;
493
1158
  }
494
1159
  async fetchBalance(params = {}) {
495
1160
  /**
496
1161
  * @method
497
- * @name lbank#fetchBalance
1162
+ * @name lbank2#fetchBalance
498
1163
  * @description query for balance and get the amount of funds available for trading or funds locked in orders
499
- * @param {object} [params] extra parameters specific to the lbank api endpoint
1164
+ * @see https://www.lbank.info/en-US/docs/index.html#asset-information
1165
+ * @see https://www.lbank.info/en-US/docs/index.html#account-information
1166
+ * @see https://www.lbank.info/en-US/docs/index.html#get-all-coins-information
1167
+ * @param {object} [params] extra parameters specific to the lbank2 api endpoint
500
1168
  * @returns {object} a [balance structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#balance-structure}
501
1169
  */
502
1170
  await this.loadMarkets();
503
- const response = await this.privatePostUserInfo(params);
1171
+ let method = this.safeString(params, 'method');
1172
+ if (method === undefined) {
1173
+ const options = this.safeValue(this.options, 'fetchBalance', {});
1174
+ method = this.safeString(options, 'method', 'spotPrivatePostSupplementUserInfo');
1175
+ }
1176
+ const response = await this[method]();
504
1177
  //
505
- // {
506
- // "result":"true",
507
- // "info":{
508
- // "freeze":{
509
- // "iog":"0.00000000",
510
- // "ssc":"0.00000000",
511
- // "eon":"0.00000000",
512
- // },
513
- // "asset":{
514
- // "iog":"0.00000000",
515
- // "ssc":"0.00000000",
516
- // "eon":"0.00000000",
517
- // },
518
- // "free":{
519
- // "iog":"0.00000000",
520
- // "ssc":"0.00000000",
521
- // "eon":"0.00000000",
522
- // },
523
- // }
524
- // }
1178
+ // {
1179
+ // "result": "true",
1180
+ // "data": [
1181
+ // {
1182
+ // "usableAmt": "14.36",
1183
+ // "assetAmt": "14.36",
1184
+ // "networkList": [
1185
+ // {
1186
+ // "isDefault": false,
1187
+ // "withdrawFeeRate": "",
1188
+ // "name": "erc20",
1189
+ // "withdrawMin": 30,
1190
+ // "minLimit": 0.0001,
1191
+ // "minDeposit": 20,
1192
+ // "feeAssetCode": "usdt",
1193
+ // "withdrawFee": "30",
1194
+ // "type": 1,
1195
+ // "coin": "usdt",
1196
+ // "network": "eth"
1197
+ // },
1198
+ // ...
1199
+ // ],
1200
+ // "freezeAmt": "0",
1201
+ // "coin": "ada"
1202
+ // }
1203
+ // ],
1204
+ // "code": 0
1205
+ // }
525
1206
  //
526
1207
  return this.parseBalance(response);
527
1208
  }
528
- parseOrderStatus(status) {
529
- const statuses = {
530
- '-1': 'cancelled',
531
- '0': 'open',
532
- '1': 'open',
533
- '2': 'closed',
534
- '4': 'closed', // disposal processing
535
- };
536
- return this.safeString(statuses, status);
537
- }
538
- parseOrder(order, market = undefined) {
1209
+ parseTradingFee(fee, market = undefined) {
539
1210
  //
540
- // {
541
- // "symbol""eth_btc",
542
- // "amount"10.000000,
543
- // "create_time":1484289832081,
544
- // "price":5000.000000,
545
- // "avg_price":5277.301200,
546
- // "type":"sell",
547
- // "order_id":"ab704110-af0d-48fd-a083-c218f19a4a55",
548
- // "deal_amount":10.000000,
549
- // "status":2
550
- // }
1211
+ // {
1212
+ // "symbol":"skt_usdt",
1213
+ // "makerCommission":"0.10",
1214
+ // "takerCommission":"0.10"
1215
+ // }
551
1216
  //
552
- const marketId = this.safeString(order, 'symbol');
553
- const symbol = this.safeSymbol(marketId, market, '_');
554
- const timestamp = this.safeInteger(order, 'create_time');
555
- // Limit Order Request Returns: Order Price
556
- // Market Order Returns: cny amount of market order
557
- const price = this.safeString(order, 'price');
558
- const amount = this.safeString(order, 'amount');
559
- const filled = this.safeString(order, 'deal_amount');
560
- const average = this.safeString(order, 'avg_price');
561
- const status = this.parseOrderStatus(this.safeString(order, 'status'));
562
- const id = this.safeString(order, 'order_id');
563
- const type = this.safeString(order, 'order_type');
564
- const side = this.safeString(order, 'type');
565
- return this.safeOrder({
566
- 'id': id,
567
- 'clientOrderId': undefined,
568
- 'datetime': this.iso8601(timestamp),
569
- 'timestamp': timestamp,
570
- 'lastTradeTimestamp': undefined,
571
- 'status': status,
1217
+ const marketId = this.safeString(fee, 'symbol');
1218
+ const symbol = this.safeSymbol(marketId);
1219
+ return {
1220
+ 'info': fee,
572
1221
  'symbol': symbol,
573
- 'type': type,
574
- 'timeInForce': undefined,
575
- 'postOnly': undefined,
576
- 'side': side,
577
- 'price': price,
578
- 'stopPrice': undefined,
579
- 'triggerPrice': undefined,
580
- 'cost': undefined,
581
- 'amount': amount,
582
- 'filled': filled,
583
- 'remaining': undefined,
584
- 'trades': undefined,
585
- 'fee': undefined,
586
- 'info': this.safeValue(order, 'info', order),
587
- 'average': average,
588
- }, market);
1222
+ 'maker': this.safeNumber(fee, 'makerCommission'),
1223
+ 'taker': this.safeNumber(fee, 'takerCommission'),
1224
+ };
589
1225
  }
590
- async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
1226
+ async fetchTradingFee(symbol, params = {}) {
591
1227
  /**
592
1228
  * @method
593
- * @name lbank#createOrder
594
- * @description create a trade order
595
- * @param {string} symbol unified symbol of the market to create an order in
596
- * @param {string} type 'market' or 'limit'
597
- * @param {string} side 'buy' or 'sell'
598
- * @param {float} amount how much of currency you want to trade in units of base currency
1229
+ * @name lbank2#fetchTradingFee
1230
+ * @description fetch the trading fees for a market
1231
+ * @see https://www.lbank.info/en-US/docs/index.html#transaction-fee-rate-query
1232
+ * @param {string} symbol unified market symbol
1233
+ * @param {object} [params] extra parameters specific to the lbank2 api endpoint
1234
+ * @returns {object} a [fee structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#fee-structure}
1235
+ */
1236
+ const market = this.market(symbol);
1237
+ const result = await this.fetchTradingFees(this.extend(params, { 'category': market['id'] }));
1238
+ return result;
1239
+ }
1240
+ async fetchTradingFees(params = {}) {
1241
+ /**
1242
+ * @method
1243
+ * @name lbank2#fetchTradingFees
1244
+ * @description fetch the trading fees for multiple markets
1245
+ * @see https://www.lbank.info/en-US/docs/index.html#transaction-fee-rate-query
1246
+ * @param {object} [params] extra parameters specific to the lbank2 api endpoint
1247
+ * @returns {object} a dictionary of [fee structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#fee-structure} indexed by market symbols
1248
+ */
1249
+ await this.loadMarkets();
1250
+ const request = {};
1251
+ const response = await this.spotPrivatePostSupplementCustomerTradeFee(this.extend(request, params));
1252
+ const fees = this.safeValue(response, 'data', []);
1253
+ const result = {};
1254
+ for (let i = 0; i < fees.length; i++) {
1255
+ const fee = this.parseTradingFee(fees[i]);
1256
+ const symbol = fee['symbol'];
1257
+ result[symbol] = fee;
1258
+ }
1259
+ return result;
1260
+ }
1261
+ async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
1262
+ /**
1263
+ * @method
1264
+ * @name lbank2#createOrder
1265
+ * @description create a trade order
1266
+ * @see https://www.lbank.info/en-US/docs/index.html#place-order
1267
+ * @see https://www.lbank.info/en-US/docs/index.html#place-an-order
1268
+ * @param {string} symbol unified symbol of the market to create an order in
1269
+ * @param {string} type 'market' or 'limit'
1270
+ * @param {string} side 'buy' or 'sell'
1271
+ * @param {float} amount how much of currency you want to trade in units of base currency
599
1272
  * @param {float} [price] the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
600
- * @param {object} [params] extra parameters specific to the lbank api endpoint
1273
+ * @param {object} [params] extra parameters specific to the lbank2 api endpoint
601
1274
  * @returns {object} an [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
602
1275
  */
603
1276
  await this.loadMarkets();
604
1277
  const market = this.market(symbol);
605
- let order = {
1278
+ const clientOrderId = this.safeString2(params, 'custom_id', 'clientOrderId');
1279
+ const postOnly = this.safeValue(params, 'postOnly', false);
1280
+ const timeInForce = this.safeStringUpper(params, 'timeInForce');
1281
+ params = this.omit(params, ['custom_id', 'clientOrderId', 'timeInForce', 'postOnly']);
1282
+ const request = {
606
1283
  'symbol': market['id'],
607
- 'type': side,
608
- 'amount': amount,
609
1284
  };
610
- if (type === 'market') {
611
- order['type'] += '_market';
1285
+ const ioc = (timeInForce === 'IOC');
1286
+ const fok = (timeInForce === 'FOK');
1287
+ const maker = (postOnly || (timeInForce === 'PO'));
1288
+ if ((type === 'market') && (ioc || fok || maker)) {
1289
+ throw new errors.InvalidOrder(this.id + ' createOrder () does not allow market FOK, IOC, or postOnly orders. Only limit IOC, FOK, and postOnly orders are allowed');
612
1290
  }
613
- else {
614
- order['price'] = price;
1291
+ if (type === 'limit') {
1292
+ request['type'] = side;
1293
+ request['price'] = this.priceToPrecision(symbol, price);
1294
+ request['amount'] = this.amountToPrecision(symbol, amount);
1295
+ if (ioc) {
1296
+ request['type'] = side + '_' + 'ioc';
1297
+ }
1298
+ else if (fok) {
1299
+ request['type'] = side + '_' + 'fok';
1300
+ }
1301
+ else if (maker) {
1302
+ request['type'] = side + '_' + 'maker';
1303
+ }
1304
+ }
1305
+ else if (type === 'market') {
1306
+ if (side === 'sell') {
1307
+ request['type'] = side + '_' + 'market';
1308
+ request['amount'] = this.amountToPrecision(symbol, amount);
1309
+ }
1310
+ else if (side === 'buy') {
1311
+ request['type'] = side + '_' + 'market';
1312
+ if (this.options['createMarketBuyOrderRequiresPrice']) {
1313
+ if (price === undefined) {
1314
+ throw new errors.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 the 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)");
1315
+ }
1316
+ else {
1317
+ const amountString = this.numberToString(amount);
1318
+ const priceString = this.numberToString(price);
1319
+ const quoteAmount = Precise["default"].stringMul(amountString, priceString);
1320
+ const cost = this.parseNumber(quoteAmount);
1321
+ request['price'] = this.priceToPrecision(symbol, cost);
1322
+ }
1323
+ }
1324
+ else {
1325
+ request['price'] = amount;
1326
+ }
1327
+ }
1328
+ }
1329
+ if (clientOrderId !== undefined) {
1330
+ request['custom_id'] = clientOrderId;
615
1331
  }
616
- const response = await this.privatePostCreateOrder(this.extend(order, params));
617
- order = this.omit(order, 'type');
618
- order['order_id'] = response['order_id'];
619
- order['type'] = side;
620
- order['order_type'] = type;
621
- order['create_time'] = this.milliseconds();
622
- order['info'] = response;
623
- return this.parseOrder(order, market);
1332
+ let method = undefined;
1333
+ method = this.safeString(params, 'method');
1334
+ params = this.omit(params, 'method');
1335
+ if (method === undefined) {
1336
+ const options = this.safeValue(this.options, 'createOrder', {});
1337
+ method = this.safeString(options, 'method', 'spotPrivatePostSupplementCreateOrder');
1338
+ }
1339
+ const response = await this[method](this.extend(request, params));
1340
+ //
1341
+ // {
1342
+ // "result":true,
1343
+ // "data":{
1344
+ // "symbol":"doge_usdt",
1345
+ // "order_id":"0cf8a3de-4597-4296-af45-be7abaa06b07"
1346
+ // },
1347
+ // "error_code":0,
1348
+ // "ts":1648162321043
1349
+ // }
1350
+ //
1351
+ const result = this.safeValue(response, 'data', {});
1352
+ return this.safeOrder({
1353
+ 'id': this.safeString(result, 'order_id'),
1354
+ 'info': result,
1355
+ }, market);
624
1356
  }
625
- async cancelOrder(id, symbol = undefined, params = {}) {
1357
+ parseOrderStatus(status) {
1358
+ const statuses = {
1359
+ '-1': 'canceled',
1360
+ '0': 'open',
1361
+ '1': 'open',
1362
+ '2': 'closed',
1363
+ '3': 'canceled',
1364
+ '4': 'closed', // disposal processing
1365
+ };
1366
+ return this.safeString(statuses, status, status);
1367
+ }
1368
+ parseOrder(order, market = undefined) {
1369
+ //
1370
+ // fetchOrderSupplement (private)
1371
+ //
1372
+ // {
1373
+ // "cummulativeQuoteQty":0,
1374
+ // "symbol":"doge_usdt",
1375
+ // "executedQty":0,
1376
+ // "orderId":"53d2d53e-70fb-4398-b722-f48571a5f61e",
1377
+ // "origQty":1E+2,
1378
+ // "price":0.05,
1379
+ // "clientOrderId":null,
1380
+ // "origQuoteOrderQty":5,
1381
+ // "updateTime":1648163406000,
1382
+ // "time":1648163139387,
1383
+ // "type":"buy_maker",
1384
+ // "status":-1
1385
+ // }
1386
+ //
1387
+ //
1388
+ // fetchOrderDefault (private)
1389
+ //
1390
+ // {
1391
+ // "symbol":"shib_usdt",
1392
+ // "amount":1,
1393
+ // "create_time":1649367863356,
1394
+ // "price":0.0000246103,
1395
+ // "avg_price":0.00002466180000000104,
1396
+ // "type":"buy_market",
1397
+ // "order_id":"abe8b92d-86d9-4d6d-b71e-d14f5fb53ddf",
1398
+ // "custom_id": "007", // field only present if user creates it at order time
1399
+ // "deal_amount":40548.54065802,
1400
+ // "status":2
1401
+ // }
1402
+ //
1403
+ // fetchOpenOrders (private)
1404
+ //
1405
+ // {
1406
+ // "cummulativeQuoteQty":0,
1407
+ // "symbol":"doge_usdt",
1408
+ // "executedQty":0,
1409
+ // "orderId":"73878edf-008d-4e4c-8041-df1f1b2cd8bb",
1410
+ // "origQty":100,
1411
+ // "price":0.05,
1412
+ // "origQuoteOrderQty":5,
1413
+ // "updateTime":1648501762000,
1414
+ // "time":1648501762353,
1415
+ // "type":"buy",
1416
+ // "status":0
1417
+ // }
1418
+ //
1419
+ // fetchOrders (private)
1420
+ //
1421
+ // {
1422
+ // "cummulativeQuoteQty":0,
1423
+ // "symbol":"doge_usdt",
1424
+ // "executedQty":0,
1425
+ // "orderId":"2cadc7cc-b5f6-486b-a5b4-d6ac49a9c186",
1426
+ // "origQty":100,
1427
+ // "price":0.05,
1428
+ // "origQuoteOrderQty":5,
1429
+ // "updateTime":1648501384000,
1430
+ // "time":1648501363889,
1431
+ // "type":"buy",
1432
+ // "status":-1
1433
+ // }
1434
+ //
1435
+ const id = this.safeString2(order, 'orderId', 'order_id');
1436
+ const clientOrderId = this.safeString2(order, 'clientOrderId', 'custom_id');
1437
+ const timestamp = this.safeInteger2(order, 'time', 'create_time');
1438
+ const rawStatus = this.safeString(order, 'status');
1439
+ const marketId = this.safeString(order, 'symbol');
1440
+ market = this.safeMarket(marketId, market);
1441
+ let timeInForce = undefined;
1442
+ let postOnly = false;
1443
+ let type = 'limit';
1444
+ const rawType = this.safeString(order, 'type'); // buy, sell, buy_market, sell_market, buy_maker,sell_maker,buy_ioc,sell_ioc, buy_fok, sell_fok
1445
+ const parts = rawType.split('_');
1446
+ const side = this.safeString(parts, 0);
1447
+ const typePart = this.safeString(parts, 1); // market, maker, ioc, fok or undefined (limit)
1448
+ if (typePart === 'market') {
1449
+ type = 'market';
1450
+ }
1451
+ if (typePart === 'maker') {
1452
+ postOnly = true;
1453
+ timeInForce = 'PO';
1454
+ }
1455
+ if (typePart === 'ioc') {
1456
+ timeInForce = 'IOC';
1457
+ }
1458
+ if (typePart === 'fok') {
1459
+ timeInForce = 'FOK';
1460
+ }
1461
+ const price = this.safeString(order, 'price');
1462
+ const costString = this.safeString(order, 'cummulativeQuoteQty');
1463
+ let amountString = undefined;
1464
+ if (rawType !== 'buy_market') {
1465
+ amountString = this.safeString2(order, 'origQty', 'amount');
1466
+ }
1467
+ const filledString = this.safeString2(order, 'executedQty', 'deal_amount');
1468
+ return this.safeOrder({
1469
+ 'id': id,
1470
+ 'clientOrderId': clientOrderId,
1471
+ 'datetime': this.iso8601(timestamp),
1472
+ 'timestamp': timestamp,
1473
+ 'lastTradeTimestamp': undefined,
1474
+ 'status': this.parseOrderStatus(rawStatus),
1475
+ 'symbol': market['symbol'],
1476
+ 'type': type,
1477
+ 'timeInForce': timeInForce,
1478
+ 'postOnly': postOnly,
1479
+ 'side': side,
1480
+ 'price': price,
1481
+ 'stopPrice': undefined,
1482
+ 'triggerPrice': undefined,
1483
+ 'cost': costString,
1484
+ 'amount': amountString,
1485
+ 'filled': filledString,
1486
+ 'remaining': undefined,
1487
+ 'trades': undefined,
1488
+ 'fee': undefined,
1489
+ 'info': order,
1490
+ 'average': undefined,
1491
+ }, market);
1492
+ }
1493
+ async fetchOrder(id, symbol = undefined, params = {}) {
626
1494
  /**
627
1495
  * @method
628
- * @name lbank#cancelOrder
629
- * @description cancels an open order
630
- * @param {string} id order id
1496
+ * @name lbank2#fetchOrder
1497
+ * @description fetches information on an order made by the user
1498
+ * @see https://www.lbank.info/en-US/docs/index.html#query-order
1499
+ * @see https://www.lbank.info/en-US/docs/index.html#query-order-new
631
1500
  * @param {string} symbol unified symbol of the market the order was made in
632
- * @param {object} [params] extra parameters specific to the lbank api endpoint
1501
+ * @param {object} [params] extra parameters specific to the lbank2 api endpoint
633
1502
  * @returns {object} An [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
634
1503
  */
635
1504
  await this.loadMarkets();
1505
+ let method = this.safeString(params, 'method');
1506
+ if (method === undefined) {
1507
+ const options = this.safeValue(this.options, 'fetchOrder', {});
1508
+ method = this.safeString(options, 'method', 'fetchOrderSupplement');
1509
+ }
1510
+ if (method === 'fetchOrderSupplement') {
1511
+ return await this.fetchOrderSupplement(id, symbol, params);
1512
+ }
1513
+ return await this.fetchOrderDefault(id, symbol, params);
1514
+ }
1515
+ async fetchOrderSupplement(id, symbol = undefined, params = {}) {
1516
+ this.checkRequiredSymbol('fetchOrder', symbol);
1517
+ await this.loadMarkets();
636
1518
  const market = this.market(symbol);
637
1519
  const request = {
638
1520
  'symbol': market['id'],
639
- 'order_id': id,
1521
+ 'orderId': id,
640
1522
  };
641
- const response = await this.privatePostCancelOrder(this.extend(request, params));
642
- return response;
1523
+ const response = await this.spotPrivatePostSupplementOrdersInfo(this.extend(request, params));
1524
+ //
1525
+ // {
1526
+ // "result":true,
1527
+ // "data":{
1528
+ // "cummulativeQuoteQty":0,
1529
+ // "symbol":"doge_usdt",
1530
+ // "executedQty":0,
1531
+ // "orderId":"53d2d53e-70fb-4398-b722-f48571a5f61e",
1532
+ // "origQty":1E+2,
1533
+ // "price":0.05,
1534
+ // "clientOrderId":null,
1535
+ // "origQuoteOrderQty":5,
1536
+ // "updateTime":1648163406000,
1537
+ // "time":1648163139387,
1538
+ // "type":"buy_maker",
1539
+ // "status":-1
1540
+ // },
1541
+ // "error_code":0,
1542
+ // "ts":1648164471827
1543
+ // }
1544
+ //
1545
+ const result = this.safeValue(response, 'data', {});
1546
+ return this.parseOrder(result);
643
1547
  }
644
- async fetchOrder(id, symbol = undefined, params = {}) {
645
- /**
646
- * @method
647
- * @name lbank#fetchOrder
648
- * @description fetches information on an order made by the user
649
- * @param {string} symbol unified symbol of the market the order was made in
650
- * @param {object} [params] extra parameters specific to the lbank api endpoint
651
- * @returns {object} An [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
652
- */
1548
+ async fetchOrderDefault(id, symbol = undefined, params = {}) {
653
1549
  // Id can be a list of ids delimited by a comma
1550
+ this.checkRequiredSymbol('fetchOrder', symbol);
654
1551
  await this.loadMarkets();
655
1552
  const market = this.market(symbol);
656
1553
  const request = {
657
1554
  'symbol': market['id'],
658
1555
  'order_id': id,
659
1556
  };
660
- const response = await this.privatePostOrdersInfo(this.extend(request, params));
661
- const data = this.safeValue(response, 'orders', []);
662
- const orders = this.parseOrders(data, market);
663
- const numOrders = orders.length;
1557
+ const response = await this.spotPrivatePostOrdersInfo(this.extend(request, params));
1558
+ //
1559
+ // {
1560
+ // "result":true,
1561
+ // "data":[
1562
+ // {
1563
+ // "symbol":"doge_usdt",
1564
+ // "amount":18,
1565
+ // "create_time":1647455223186,
1566
+ // "price":0,
1567
+ // "avg_price":0.113344,
1568
+ // "type":"sell_market",
1569
+ // "order_id":"d4ca1ddd-40d9-42c1-9717-5de435865bec",
1570
+ // "deal_amount":18,
1571
+ // "status":2
1572
+ // }
1573
+ // ],
1574
+ // "error_code":0,
1575
+ // "ts":1647455270776
1576
+ // }
1577
+ //
1578
+ const result = this.safeValue(response, 'data', []);
1579
+ const numOrders = result.length;
664
1580
  if (numOrders === 1) {
665
- return orders[0];
1581
+ return this.parseOrder(result[0]);
666
1582
  }
667
1583
  else {
668
- throw new errors.BadRequest(this.id + ' fetchOrder() can only return one order at a time. Found ' + numOrders + ' orders.');
1584
+ // const parsedOrders = [];
1585
+ // for (let i = 0; i < numOrders; i++) {
1586
+ // const parsedOrder = this.parseOrder (result[i]);
1587
+ // parsedOrders.push (parsedOrder);
1588
+ // }
1589
+ // return parsedOrders;
1590
+ throw new errors.BadRequest(this.id + ' fetchOrder() can only fetch one order at a time');
1591
+ }
1592
+ }
1593
+ async fetchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1594
+ /**
1595
+ * @method
1596
+ * @name lbank2#fetchMyTrades
1597
+ * @description fetch all trades made by the user
1598
+ * @see https://www.lbank.info/en-US/docs/index.html#past-transaction-details
1599
+ * @param {string} symbol unified market symbol
1600
+ * @param {int} [since] the earliest time in ms to fetch trades for
1601
+ * @param {int} [limit] the maximum number of trade structures to retrieve
1602
+ * @param {object} [params] extra parameters specific to the lbank2 api endpoint
1603
+ * @returns {Trade[]} a list of [trade structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#trade-structure}
1604
+ */
1605
+ this.checkRequiredSymbol('fetchMyTrades', symbol);
1606
+ await this.loadMarkets();
1607
+ const market = this.market(symbol);
1608
+ since = this.safeValue(params, 'start_date', since);
1609
+ params = this.omit(params, 'start_date');
1610
+ const request = {
1611
+ 'symbol': market['id'],
1612
+ // 'start_date' Start time yyyy-mm-dd, the maximum is today, the default is yesterday
1613
+ // 'end_date' Finish time yyyy-mm-dd, the maximum is today, the default is today
1614
+ // 'The start': and end date of the query window is up to 2 days
1615
+ // 'from' Initial transaction number inquiring
1616
+ // 'direct' inquire direction,The default is the 'next' which is the positive sequence of dealing time,the 'prev' is inverted order of dealing time
1617
+ // 'size' Query the number of defaults to 100
1618
+ };
1619
+ if (limit !== undefined) {
1620
+ request['size'] = limit;
1621
+ }
1622
+ if (since !== undefined) {
1623
+ request['start_date'] = this.ymd(since, '-'); // max query 2 days ago
1624
+ request['end_date'] = this.ymd(since + 86400000, '-'); // will cover 2 days
669
1625
  }
1626
+ const response = await this.spotPrivatePostTransactionHistory(this.extend(request, params));
1627
+ //
1628
+ // {
1629
+ // "result":true,
1630
+ // "data":[
1631
+ // {
1632
+ // "orderUuid":"38b4e7a4-14f6-45fd-aba1-1a37024124a0",
1633
+ // "tradeFeeRate":0.0010000000,
1634
+ // "dealTime":1648500944496,
1635
+ // "dealQuantity":30.00000000000000000000,
1636
+ // "tradeFee":0.00453300000000000000,
1637
+ // "txUuid":"11f3850cc6214ea3b495adad3a032794",
1638
+ // "dealPrice":0.15111300000000000000,
1639
+ // "dealVolumePrice":4.53339000000000000000,
1640
+ // "tradeType":"sell_market"
1641
+ // }
1642
+ // ],
1643
+ // "error_code":0,
1644
+ // "ts":1648509742164
1645
+ // }
1646
+ //
1647
+ const trades = this.safeValue(response, 'data', []);
1648
+ return this.parseTrades(trades, market, since, limit);
670
1649
  }
671
1650
  async fetchOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
672
1651
  /**
673
1652
  * @method
674
- * @name lbank#fetchOrders
1653
+ * @name lbank2#fetchOrders
675
1654
  * @description fetches information on multiple orders made by the user
1655
+ * @see https://www.lbank.info/en-US/docs/index.html#query-all-orders
676
1656
  * @param {string} symbol unified market symbol of the market orders were made in
677
1657
  * @param {int} [since] the earliest time in ms to fetch orders for
678
- * @param {int} [limit] the maximum number of orde structures to retrieve
679
- * @param {object} [params] extra parameters specific to the lbank api endpoint
1658
+ * @param {int} [limit] the maximum number of order structures to retrieve
1659
+ * @param {object} [params] extra parameters specific to the lbank2 api endpoint
680
1660
  * @returns {Order[]} a list of [order structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
681
1661
  */
1662
+ // default query is for canceled and completely filled orders
1663
+ // does not return open orders unless specified explicitly
1664
+ this.checkRequiredSymbol('fetchOrders', symbol);
682
1665
  await this.loadMarkets();
1666
+ const market = this.market(symbol);
683
1667
  if (limit === undefined) {
684
1668
  limit = 100;
685
1669
  }
686
- const market = this.market(symbol);
687
1670
  const request = {
688
1671
  'symbol': market['id'],
689
1672
  'current_page': 1,
690
1673
  'page_length': limit,
1674
+ // 'status' -1: Cancelled, 0: Unfilled, 1: Partially filled, 2: Completely filled, 3: Partially filled and cancelled, 4: Cancellation is being processed
691
1675
  };
692
- const response = await this.privatePostOrdersInfoHistory(this.extend(request, params));
693
- const data = this.safeValue(response, 'orders', []);
694
- return this.parseOrders(data, undefined, since, limit);
1676
+ const response = await this.spotPrivatePostSupplementOrdersInfoHistory(this.extend(request, params));
1677
+ //
1678
+ // {
1679
+ // "result":true,
1680
+ // "data":{
1681
+ // "total":1,
1682
+ // "page_length":100,
1683
+ // "orders":[
1684
+ // {
1685
+ // "cummulativeQuoteQty":0,
1686
+ // "symbol":"doge_usdt",
1687
+ // "executedQty":0,
1688
+ // "orderId":"2cadc7cc-b5f6-486b-a5b4-d6ac49a9c186",
1689
+ // "origQty":100,
1690
+ // "price":0.05,
1691
+ // "origQuoteOrderQty":5,
1692
+ // "updateTime":1648501384000,
1693
+ // "time":1648501363889,
1694
+ // "type":"buy",
1695
+ // "status":-1
1696
+ // }, ...
1697
+ // ],
1698
+ // "current_page":1
1699
+ // },
1700
+ // "error_code":0,
1701
+ // "ts":1648505706348
1702
+ // }
1703
+ //
1704
+ const result = this.safeValue(response, 'data', {});
1705
+ const orders = this.safeValue(result, 'orders', []);
1706
+ return this.parseOrders(orders, market, since, limit);
695
1707
  }
696
- async fetchClosedOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
1708
+ async fetchOpenOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
697
1709
  /**
698
1710
  * @method
699
- * @name lbank#fetchClosedOrders
700
- * @description fetches information on multiple closed orders made by the user
701
- * @param {string} symbol unified market symbol of the market orders were made in
702
- * @param {int} [since] the earliest time in ms to fetch orders for
703
- * @param {int} [limit] the maximum number of orde structures to retrieve
704
- * @param {object} [params] extra parameters specific to the lbank api endpoint
1711
+ * @name lbank2#fetchOpenOrders
1712
+ * @description fetch all unfilled currently open orders
1713
+ * @see https://www.lbank.info/en-US/docs/index.html#current-pending-order
1714
+ * @param {string} symbol unified market symbol
1715
+ * @param {int} [since] the earliest time in ms to fetch open orders for
1716
+ * @param {int} [limit] the maximum number of open order structures to retrieve
1717
+ * @param {object} [params] extra parameters specific to the lbank2 api endpoint
705
1718
  * @returns {Order[]} a list of [order structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
706
1719
  */
1720
+ this.checkRequiredSymbol('fetchOpenOrders', symbol);
1721
+ await this.loadMarkets();
1722
+ const market = this.market(symbol);
1723
+ if (limit === undefined) {
1724
+ limit = 100;
1725
+ }
1726
+ const request = {
1727
+ 'symbol': market['id'],
1728
+ 'current_page': 1,
1729
+ 'page_length': limit,
1730
+ };
1731
+ const response = await this.spotPrivatePostSupplementOrdersInfoNoDeal(this.extend(request, params));
1732
+ //
1733
+ // {
1734
+ // "result":true,
1735
+ // "data":{
1736
+ // "total":1,
1737
+ // "page_length":100,
1738
+ // "orders":[
1739
+ // {
1740
+ // "cummulativeQuoteQty":0,
1741
+ // "symbol":"doge_usdt",
1742
+ // "executedQty":0,
1743
+ // "orderId":"73878edf-008d-4e4c-8041-df1f1b2cd8bb",
1744
+ // "origQty":100,
1745
+ // "price":0.05,
1746
+ // "origQuoteOrderQty":5,
1747
+ // "updateTime":1648501762000,
1748
+ // "time":1648501762353,
1749
+ // "type":"buy",
1750
+ // "status":0
1751
+ // }, ...
1752
+ // ],
1753
+ // "current_page":1
1754
+ // },
1755
+ // "error_code":0,
1756
+ // "ts":1648506110196
1757
+ // }
1758
+ //
1759
+ const result = this.safeValue(response, 'data', {});
1760
+ const orders = this.safeValue(result, 'orders', []);
1761
+ return this.parseOrders(orders, market, since, limit);
1762
+ }
1763
+ async cancelOrder(id, symbol = undefined, params = {}) {
1764
+ /**
1765
+ * @method
1766
+ * @name lbank2#cancelOrder
1767
+ * @description cancels an open order
1768
+ * @see https://www.lbank.info/en-US/docs/index.html#cancel-order-new
1769
+ * @param {string} id order id
1770
+ * @param {string} symbol unified symbol of the market the order was made in
1771
+ * @param {object} [params] extra parameters specific to the lbank2 api endpoint
1772
+ * @returns {object} An [order structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
1773
+ */
1774
+ this.checkRequiredSymbol('cancelOrder', symbol);
1775
+ await this.loadMarkets();
1776
+ const clientOrderId = this.safeString2(params, 'origClientOrderId', 'clientOrderId');
1777
+ params = this.omit(params, ['origClientOrderId', 'clientOrderId']);
1778
+ const market = this.market(symbol);
1779
+ const request = {
1780
+ 'symbol': market['id'],
1781
+ 'orderId': id,
1782
+ };
1783
+ if (clientOrderId !== undefined) {
1784
+ request['origClientOrderId'] = clientOrderId;
1785
+ }
1786
+ const response = await this.spotPrivatePostSupplementCancelOrder(this.extend(request, params));
1787
+ //
1788
+ // {
1789
+ // "result":true,
1790
+ // "data":{
1791
+ // "executedQty":0.0,
1792
+ // "price":0.05,
1793
+ // "origQty":100.0,
1794
+ // "tradeType":"buy",
1795
+ // "status":0
1796
+ // },
1797
+ // "error_code":0,
1798
+ // "ts":1648501286196
1799
+ // }
1800
+ const result = this.safeValue(response, 'data', {});
1801
+ return result;
1802
+ }
1803
+ async cancelAllOrders(symbol = undefined, params = {}) {
1804
+ /**
1805
+ * @method
1806
+ * @name lbank2#cancelAllOrders
1807
+ * @description cancel all open orders in a market
1808
+ * @see https://www.lbank.info/en-US/docs/index.html#cancel-all-pending-orders-for-a-single-trading-pair
1809
+ * @param {string} symbol unified market symbol of the market to cancel orders in
1810
+ * @param {object} [params] extra parameters specific to the lbank2 api endpoint
1811
+ * @returns {object[]} a list of [order structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#order-structure}
1812
+ */
1813
+ this.checkRequiredSymbol('cancelAllOrders', symbol);
707
1814
  await this.loadMarkets();
708
- if (symbol !== undefined) {
709
- const market = this.market(symbol);
710
- symbol = market['symbol'];
1815
+ const market = this.market(symbol);
1816
+ const request = {
1817
+ 'symbol': market['id'],
1818
+ };
1819
+ const response = await this.spotPrivatePostSupplementCancelOrderBySymbol(this.extend(request, params));
1820
+ //
1821
+ // {
1822
+ // "result":"true",
1823
+ // "data":[
1824
+ // {
1825
+ // "executedQty":0.00000000000000000000,
1826
+ // "orderId":"293ef71b-3e67-4962-af93-aa06990a045f",
1827
+ // "price":0.05000000000000000000,
1828
+ // "origQty":100.00000000000000000000,
1829
+ // "tradeType":"buy",
1830
+ // "status":0
1831
+ // },
1832
+ // ],
1833
+ // "error_code":0,
1834
+ // "ts":1648506641469
1835
+ // }
1836
+ //
1837
+ const result = this.safeValue(response, 'data', []);
1838
+ return result;
1839
+ }
1840
+ getNetworkCodeForCurrency(currencyCode, params) {
1841
+ const defaultNetworks = this.safeValue(this.options, 'defaultNetworks');
1842
+ const defaultNetwork = this.safeStringUpper(defaultNetworks, currencyCode);
1843
+ const networks = this.safeValue(this.options, 'networks', {});
1844
+ let network = this.safeStringUpper(params, 'network', defaultNetwork); // this line allows the user to specify either ERC20 or ETH
1845
+ network = this.safeString(networks, network, network); // handle ERC20>ETH alias
1846
+ return network;
1847
+ }
1848
+ async fetchDepositAddress(code, params = {}) {
1849
+ /**
1850
+ * @method
1851
+ * @name lbank2#fetchDepositAddress
1852
+ * @description fetch the deposit address for a currency associated with this account
1853
+ * @see https://www.lbank.info/en-US/docs/index.html#get-deposit-address
1854
+ * @see https://www.lbank.info/en-US/docs/index.html#the-user-obtains-the-deposit-address
1855
+ * @param {string} code unified currency code
1856
+ * @param {object} [params] extra parameters specific to the lbank2 api endpoint
1857
+ * @returns {object} an [address structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#address-structure}
1858
+ */
1859
+ await this.loadMarkets();
1860
+ let method = this.safeString(params, 'method');
1861
+ params = this.omit(params, 'method');
1862
+ if (method === undefined) {
1863
+ const options = this.safeValue(this.options, 'fetchDepositAddress', {});
1864
+ method = this.safeString(options, 'method', 'fetchDepositAddressDefault');
711
1865
  }
712
- const orders = await this.fetchOrders(symbol, since, limit, params);
713
- const closed = this.filterBy(orders, 'status', 'closed');
714
- const canceled = this.filterBy(orders, 'status', 'cancelled'); // cancelled orders may be partially filled
715
- const allOrders = this.arrayConcat(closed, canceled);
716
- return this.filterBySymbolSinceLimit(allOrders, symbol, since, limit);
1866
+ return await this[method](code, params);
1867
+ }
1868
+ async fetchDepositAddressDefault(code, params = {}) {
1869
+ await this.loadMarkets();
1870
+ const currency = this.currency(code);
1871
+ const request = {
1872
+ 'assetCode': currency['id'],
1873
+ };
1874
+ const network = this.getNetworkCodeForCurrency(code, params);
1875
+ if (network !== undefined) {
1876
+ request['netWork'] = network; // ... yes, really lol
1877
+ params = this.omit(params, 'network');
1878
+ }
1879
+ const response = await this.spotPrivatePostGetDepositAddress(this.extend(request, params));
1880
+ //
1881
+ // {
1882
+ // "result":true,
1883
+ // "data":{
1884
+ // "assetCode":"usdt",
1885
+ // "address":"0xc85689d37ca650bf2f2161364cdedee21eb6ca53",
1886
+ // "memo":null,
1887
+ // "netWork":"bep20(bsc)"
1888
+ // },
1889
+ // "error_code":0,
1890
+ // "ts":1648075865103
1891
+ // }
1892
+ //
1893
+ const result = this.safeValue(response, 'data');
1894
+ const address = this.safeString(result, 'address');
1895
+ const tag = this.safeString(result, 'memo');
1896
+ const networkId = this.safeString(result, 'netWork');
1897
+ const inverseNetworks = this.safeValue(this.options, 'inverse-networks', {});
1898
+ const networkCode = this.safeStringUpper(inverseNetworks, networkId, networkId);
1899
+ return {
1900
+ 'currency': code,
1901
+ 'address': address,
1902
+ 'tag': tag,
1903
+ 'network': networkCode,
1904
+ 'info': response,
1905
+ };
1906
+ }
1907
+ async fetchDepositAddressSupplement(code, params = {}) {
1908
+ // returns the address for whatever the default network is...
1909
+ await this.loadMarkets();
1910
+ const currency = this.currency(code);
1911
+ const request = {
1912
+ 'coin': currency['id'],
1913
+ };
1914
+ const networks = this.safeValue(this.options, 'networks');
1915
+ let network = this.safeStringUpper(params, 'network');
1916
+ network = this.safeString(networks, network, network);
1917
+ if (network !== undefined) {
1918
+ request['networkName'] = network;
1919
+ params = this.omit(params, 'network');
1920
+ }
1921
+ const response = await this.spotPrivatePostSupplementGetDepositAddress(this.extend(request, params));
1922
+ //
1923
+ // {
1924
+ // "result":true,
1925
+ // "data":{
1926
+ // "address":"TDxtabCC8iQwaxUUrPcE4WL2jArGAfvQ5A",
1927
+ // "memo":null,
1928
+ // "coin":"usdt"
1929
+ // },
1930
+ // "error_code":0,
1931
+ // "ts":1648073818880
1932
+ // }
1933
+ //
1934
+ const result = this.safeValue(response, 'data');
1935
+ const address = this.safeString(result, 'address');
1936
+ const tag = this.safeString(result, 'memo');
1937
+ const inverseNetworks = this.safeValue(this.options, 'inverse-networks', {});
1938
+ const networkCode = this.safeStringUpper(inverseNetworks, network, network);
1939
+ return {
1940
+ 'currency': code,
1941
+ 'address': address,
1942
+ 'tag': tag,
1943
+ 'network': networkCode,
1944
+ 'info': response,
1945
+ };
717
1946
  }
718
1947
  async withdraw(code, amount, address, tag = undefined, params = {}) {
719
1948
  /**
720
1949
  * @method
721
- * @name lbank#withdraw
1950
+ * @name lbank2#withdraw
722
1951
  * @description make a withdrawal
1952
+ * @see https://www.lbank.info/en-US/docs/index.html#withdrawal
723
1953
  * @param {string} code unified currency code
724
1954
  * @param {float} amount the amount to withdraw
725
1955
  * @param {string} address the address to withdraw to
726
1956
  * @param {string} tag
727
- * @param {object} [params] extra parameters specific to the lbank api endpoint
1957
+ * @param {object} [params] extra parameters specific to the lbank2 api endpoint
728
1958
  * @returns {object} a [transaction structure]{@link https://github.com/ccxt/ccxt/wiki/Manual#transaction-structure}
729
1959
  */
730
1960
  [tag, params] = this.handleWithdrawTagAndParams(tag, params);
731
- // mark and fee are optional params, mark is a note and must be less than 255 characters
732
1961
  this.checkAddress(address);
733
1962
  await this.loadMarkets();
1963
+ const fee = this.safeString(params, 'fee');
1964
+ params = this.omit(params, 'fee');
1965
+ // The relevant coin network fee can be found by calling fetchDepositWithdrawFees (), note: if no network param is supplied then the default network will be used, this can also be found in fetchDepositWithdrawFees ().
1966
+ this.checkRequiredArgument('withdraw', fee, 'fee');
734
1967
  const currency = this.currency(code);
735
1968
  const request = {
736
- 'assetCode': currency['id'],
1969
+ 'address': address,
1970
+ 'coin': currency['id'],
737
1971
  'amount': amount,
738
- 'account': address,
1972
+ 'fee': fee, // the correct coin-network fee must be supplied, which can be found by calling fetchDepositWithdrawFees (private)
1973
+ // 'networkName': defaults to the defaultNetwork of the coin which can be found in the /supplement/user_info endpoint
1974
+ // 'memo': memo: memo word of bts and dct
1975
+ // 'mark': Withdrawal Notes
1976
+ // 'name': Remarks of the address. After filling in this parameter, it will be added to the withdrawal address book of the currency.
1977
+ // 'withdrawOrderId': withdrawOrderId
1978
+ // 'type': type=1 is for intra-site transfer
739
1979
  };
740
1980
  if (tag !== undefined) {
741
1981
  request['memo'] = tag;
742
1982
  }
743
- const response = this.privatePostWithdraw(this.extend(request, params));
1983
+ const network = this.safeStringUpper2(params, 'network', 'networkName');
1984
+ params = this.omit(params, ['network', 'networkName']);
1985
+ const networks = this.safeValue(this.options, 'networks');
1986
+ const networkId = this.safeString(networks, network, network);
1987
+ if (networkId !== undefined) {
1988
+ request['networkName'] = networkId;
1989
+ }
1990
+ const response = await this.spotPrivatePostSupplementWithdraw(this.extend(request, params));
744
1991
  //
745
- // {
746
- // "result": "true",
747
- // "withdrawId": 90082,
748
- // "fee":0.001
749
- // }
1992
+ // {
1993
+ // "result":true,
1994
+ // "data": {
1995
+ // "fee":10.00000000000000000000,
1996
+ // "withdrawId":1900376
1997
+ // },
1998
+ // "error_code":0,
1999
+ // "ts":1648992501414
2000
+ // }
750
2001
  //
751
- return this.parseTransaction(response, currency);
2002
+ const result = this.safeValue(response, 'data', {});
2003
+ return {
2004
+ 'info': result,
2005
+ 'id': this.safeString(result, 'withdrawId'),
2006
+ };
2007
+ }
2008
+ parseTransactionStatus(status, type) {
2009
+ const statuses = {
2010
+ 'deposit': {
2011
+ '1': 'pending',
2012
+ '2': 'ok',
2013
+ '3': 'failed',
2014
+ '4': 'canceled',
2015
+ '5': 'transfer',
2016
+ },
2017
+ 'withdrawal': {
2018
+ '1': 'pending',
2019
+ '2': 'canceled',
2020
+ '3': 'failed',
2021
+ '4': 'ok',
2022
+ },
2023
+ };
2024
+ return this.safeString(this.safeValue(statuses, type, {}), status, status);
752
2025
  }
753
2026
  parseTransaction(transaction, currency = undefined) {
754
2027
  //
755
- // withdraw
2028
+ // fetchDeposits (private)
2029
+ //
2030
+ // {
2031
+ // "insertTime":1649012310000,
2032
+ // "amount":9.00000000000000000000,
2033
+ // "address":"TYASr5UV6HEcXatwdFQfmLVUqQQQMUxHLS",
2034
+ // "networkName":"trc20",
2035
+ // "txId":"081e4e9351dd0274922168da5f2d14ea6c495b1c3b440244f4a6dd9fe196bf2b",
2036
+ // "coin":"usdt",
2037
+ // "status":"2"
2038
+ // }
756
2039
  //
757
- // {
758
- // "result": "true",
759
- // "withdrawId": 90082,
760
- // "fee":0.001
761
- // }
762
2040
  //
763
- currency = this.safeCurrency(undefined, currency);
2041
+ // fetchWithdrawals (private)
2042
+ //
2043
+ // {
2044
+ // "amount":2.00000000000000000000,
2045
+ // "address":"TBjrW5JHDyPZjFc5nrRMhRWUDaJmhGhmD6",
2046
+ // "fee":1.00000000000000000000,
2047
+ // "networkName":"trc20",
2048
+ // "coid":"usdt",
2049
+ // "transferType":"数字资产提现",
2050
+ // "txId":"47eeee2763ad49b8817524dacfa7d092fb58f8b0ab7e5d25473314df1a793c3d",
2051
+ // "id":1902194,
2052
+ // "applyTime":1649014002000,
2053
+ // "status":"4"
2054
+ // }
2055
+ //
2056
+ const id = this.safeString(transaction, 'id');
2057
+ let type = undefined;
2058
+ if (id === undefined) {
2059
+ type = 'deposit';
2060
+ }
2061
+ else {
2062
+ type = 'withdrawal';
2063
+ }
2064
+ const txid = this.safeString(transaction, 'txId');
2065
+ const timestamp = this.safeInteger2(transaction, 'insertTime', 'applyTime');
2066
+ const networks = this.safeValue(this.options, 'inverse-networks', {});
2067
+ const networkId = this.safeString(transaction, 'networkName');
2068
+ const network = this.safeString(networks, networkId, networkId);
2069
+ const address = this.safeString(transaction, 'address');
2070
+ let addressFrom = undefined;
2071
+ let addressTo = undefined;
2072
+ if (type === 'deposit') {
2073
+ addressFrom = address;
2074
+ }
2075
+ else {
2076
+ addressTo = address;
2077
+ }
2078
+ const amount = this.safeNumber(transaction, 'amount');
2079
+ const currencyId = this.safeString2(transaction, 'coin', 'coid');
2080
+ const code = this.safeCurrencyCode(currencyId, currency);
2081
+ const status = this.parseTransactionStatus(this.safeString(transaction, 'status'), type);
2082
+ let fee = undefined;
2083
+ const feeCost = this.safeNumber(transaction, 'fee');
2084
+ if (feeCost !== undefined) {
2085
+ fee = {
2086
+ 'cost': feeCost,
2087
+ 'currency': code,
2088
+ };
2089
+ }
764
2090
  return {
765
- 'id': this.safeString2(transaction, 'id', 'withdrawId'),
766
- 'txid': undefined,
767
- 'timestamp': undefined,
768
- 'datetime': undefined,
769
- 'network': undefined,
770
- 'addressFrom': undefined,
771
- 'address': undefined,
772
- 'addressTo': undefined,
773
- 'amount': undefined,
774
- 'type': undefined,
775
- 'currency': currency['code'],
776
- 'status': undefined,
777
- 'updated': undefined,
778
- 'tagFrom': undefined,
2091
+ 'info': transaction,
2092
+ 'id': id,
2093
+ 'txid': txid,
2094
+ 'timestamp': timestamp,
2095
+ 'datetime': this.iso8601(timestamp),
2096
+ 'network': network,
2097
+ 'address': address,
2098
+ 'addressTo': addressTo,
2099
+ 'addressFrom': addressFrom,
779
2100
  'tag': undefined,
780
2101
  'tagTo': undefined,
2102
+ 'tagFrom': undefined,
2103
+ 'type': type,
2104
+ 'amount': amount,
2105
+ 'currency': code,
2106
+ 'status': status,
2107
+ 'updated': undefined,
781
2108
  'comment': undefined,
782
- 'internal': undefined,
783
- 'fee': undefined,
784
- 'info': transaction,
2109
+ 'internal': (status === 'transfer'),
2110
+ 'fee': fee,
785
2111
  };
786
2112
  }
787
- convertSecretToPem(secret) {
788
- const lineLength = 64;
789
- const secretLength = secret.length - 0;
790
- let numLines = this.parseToInt(secretLength / lineLength);
791
- numLines = this.sum(numLines, 1);
792
- let pem = "-----BEGIN PRIVATE KEY-----\n"; // eslint-disable-line
793
- for (let i = 0; i < numLines; i++) {
794
- const start = i * lineLength;
795
- const end = this.sum(start, lineLength);
796
- pem += this.secret.slice(start, end) + "\n"; // eslint-disable-line
2113
+ async fetchDeposits(code = undefined, since = undefined, limit = undefined, params = {}) {
2114
+ /**
2115
+ * @method
2116
+ * @name lbank2#fetchDeposits
2117
+ * @description fetch all deposits made to an account
2118
+ * @see https://www.lbank.info/en-US/docs/index.html#get-recharge-history
2119
+ * @param {string} code unified currency code
2120
+ * @param {int} [since] the earliest time in ms to fetch deposits for
2121
+ * @param {int} [limit] the maximum number of deposits structures to retrieve
2122
+ * @param {object} [params] extra parameters specific to the lbank2 api endpoint
2123
+ * @returns {object[]} a list of [transaction structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#transaction-structure}
2124
+ */
2125
+ await this.loadMarkets();
2126
+ const request = {
2127
+ // 'status': Recharge status: ("1","Applying"),("2","Recharge successful"),("3","Recharge failed"),("4","Already Cancel"), ("5", "Transfer")
2128
+ // 'endTime': end time, timestamp in milliseconds, default now
2129
+ };
2130
+ let currency = undefined;
2131
+ if (code !== undefined) {
2132
+ currency = this.currency(code);
2133
+ request['coin'] = currency['id'];
797
2134
  }
798
- return pem + '-----END PRIVATE KEY-----';
2135
+ if (since !== undefined) {
2136
+ request['startTime'] = since;
2137
+ }
2138
+ const response = await this.spotPrivatePostSupplementDepositHistory(this.extend(request, params));
2139
+ //
2140
+ // {
2141
+ // "result":true,
2142
+ // "data": {
2143
+ // "total":1,
2144
+ // "depositOrders": [
2145
+ // {
2146
+ // "insertTime":1649012310000,
2147
+ // "amount":9.00000000000000000000,
2148
+ // "address":"TYASr5UV6HEcXatwdFQfmLVUqQQQMUxHLS",
2149
+ // "networkName":"trc20",
2150
+ // "txId":"081e4e9351dd0274922168da5f2d14ea6c495b1c3b440244f4a6dd9fe196bf2b",
2151
+ // "coin":"usdt",
2152
+ // "status":"2"
2153
+ // },
2154
+ // ],
2155
+ // "page_length":20,
2156
+ // "current_page":1
2157
+ // },
2158
+ // "error_code":0,
2159
+ // "ts":1649719721758
2160
+ // }
2161
+ //
2162
+ const data = this.safeValue(response, 'data', {});
2163
+ const deposits = this.safeValue(data, 'depositOrders', []);
2164
+ return this.parseTransactions(deposits, currency, since, limit);
2165
+ }
2166
+ async fetchWithdrawals(code = undefined, since = undefined, limit = undefined, params = {}) {
2167
+ /**
2168
+ * @method
2169
+ * @name lbank2#fetchWithdrawals
2170
+ * @description fetch all withdrawals made from an account
2171
+ * @see https://www.lbank.info/en-US/docs/index.html#get-withdrawal-history
2172
+ * @param {string} code unified currency code
2173
+ * @param {int} [since] the earliest time in ms to fetch withdrawals for
2174
+ * @param {int} [limit] the maximum number of withdrawals structures to retrieve
2175
+ * @param {object} [params] extra parameters specific to the lbank2 api endpoint
2176
+ * @returns {object[]} a list of [transaction structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#transaction-structure}
2177
+ */
2178
+ await this.loadMarkets();
2179
+ const request = {
2180
+ // 'status': Recharge status: ("1","Applying"),("2","Recharge successful"),("3","Recharge failed"),("4","Already Cancel"), ("5", "Transfer")
2181
+ // 'endTime': end time, timestamp in milliseconds, default now
2182
+ // 'withdrawOrderId': Custom withdrawal id
2183
+ };
2184
+ let currency = undefined;
2185
+ if (code !== undefined) {
2186
+ currency = this.currency(code);
2187
+ request['coin'] = currency['id'];
2188
+ }
2189
+ if (since !== undefined) {
2190
+ request['startTime'] = since;
2191
+ }
2192
+ const response = await this.spotPrivatePostSupplementWithdraws(this.extend(request, params));
2193
+ //
2194
+ // {
2195
+ // "result":true,
2196
+ // "data": {
2197
+ // "total":1,
2198
+ // "withdraws": [
2199
+ // {
2200
+ // "amount":2.00000000000000000000,
2201
+ // "address":"TBjrW5JHDyPZjFc5nrRMhRWUDaJmhGhmD6",
2202
+ // "fee":1.00000000000000000000,
2203
+ // "networkName":"trc20",
2204
+ // "coid":"usdt",
2205
+ // "transferType":"数字资产提现",
2206
+ // "txId":"47eeee2763ad49b8817524dacfa7d092fb58f8b0ab7e5d25473314df1a793c3d",
2207
+ // "id":1902194,
2208
+ // "applyTime":1649014002000,
2209
+ // "status":"4"
2210
+ // },
2211
+ // ],
2212
+ // "page_length":20,
2213
+ // "current_page":1
2214
+ // },
2215
+ // "error_code":0,
2216
+ // "ts":1649720362362
2217
+ // }
2218
+ //
2219
+ const data = this.safeValue(response, 'data', {});
2220
+ const withdraws = this.safeValue(data, 'withdraws', []);
2221
+ return this.parseTransactions(withdraws, currency, since, limit);
2222
+ }
2223
+ async fetchTransactionFees(codes = undefined, params = {}) {
2224
+ /**
2225
+ * @method
2226
+ * @name lbank2#fetchTransactionFees
2227
+ * @deprecated
2228
+ * @description please use fetchDepositWithdrawFees instead
2229
+ * @param {string[]|undefined} codes not used by lbank2 fetchTransactionFees ()
2230
+ * @param {object} [params] extra parameters specific to the lbank2 api endpoint
2231
+ * @returns {object} a list of [fee structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#fee-structure}
2232
+ */
2233
+ // private only returns information for currencies with non-zero balance
2234
+ await this.loadMarkets();
2235
+ const isAuthorized = this.checkRequiredCredentials(false);
2236
+ let result = undefined;
2237
+ if (isAuthorized === true) {
2238
+ let method = this.safeString(params, 'method');
2239
+ params = this.omit(params, 'method');
2240
+ if (method === undefined) {
2241
+ const options = this.safeValue(this.options, 'fetchTransactionFees', {});
2242
+ method = this.safeString(options, 'method', 'fetchPrivateTransactionFees');
2243
+ }
2244
+ result = await this[method](params);
2245
+ }
2246
+ else {
2247
+ result = await this.fetchPublicTransactionFees(params);
2248
+ }
2249
+ return result;
2250
+ }
2251
+ async fetchPrivateTransactionFees(params = {}) {
2252
+ // complete response
2253
+ // incl. for coins which undefined in public method
2254
+ await this.loadMarkets();
2255
+ const response = await this.spotPrivatePostSupplementUserInfo();
2256
+ //
2257
+ // {
2258
+ // "result": "true",
2259
+ // "data": [
2260
+ // {
2261
+ // "usableAmt": "14.36",
2262
+ // "assetAmt": "14.36",
2263
+ // "networkList": [
2264
+ // {
2265
+ // "isDefault": false,
2266
+ // "withdrawFeeRate": "",
2267
+ // "name": "erc20",
2268
+ // "withdrawMin": 30,
2269
+ // "minLimit": 0.0001,
2270
+ // "minDeposit": 20,
2271
+ // "feeAssetCode": "usdt",
2272
+ // "withdrawFee": "30",
2273
+ // "type": 1,
2274
+ // "coin": "usdt",
2275
+ // "network": "eth"
2276
+ // },
2277
+ // ...
2278
+ // ],
2279
+ // "freezeAmt": "0",
2280
+ // "coin": "ada"
2281
+ // }
2282
+ // ],
2283
+ // "code": 0
2284
+ // }
2285
+ //
2286
+ const result = this.safeValue(response, 'data', []);
2287
+ const withdrawFees = {};
2288
+ for (let i = 0; i < result.length; i++) {
2289
+ const entry = result[i];
2290
+ const currencyId = this.safeString(entry, 'coin');
2291
+ const code = this.safeCurrencyCode(currencyId);
2292
+ const networkList = this.safeValue(entry, 'networkList', []);
2293
+ withdrawFees[code] = {};
2294
+ for (let j = 0; j < networkList.length; j++) {
2295
+ const networkEntry = networkList[j];
2296
+ const networkId = this.safeString(networkEntry, 'name');
2297
+ const networkCode = this.safeString(this.options['inverse-networks'], networkId, networkId);
2298
+ const fee = this.safeNumber(networkEntry, 'withdrawFee');
2299
+ if (fee !== undefined) {
2300
+ withdrawFees[code][networkCode] = fee;
2301
+ }
2302
+ }
2303
+ }
2304
+ return {
2305
+ 'withdraw': withdrawFees,
2306
+ 'deposit': {},
2307
+ 'info': response,
2308
+ };
2309
+ }
2310
+ async fetchPublicTransactionFees(params = {}) {
2311
+ // extremely incomplete response
2312
+ // vast majority fees undefined
2313
+ await this.loadMarkets();
2314
+ const code = this.safeString2(params, 'coin', 'assetCode');
2315
+ params = this.omit(params, ['coin', 'assetCode']);
2316
+ const request = {};
2317
+ if (code !== undefined) {
2318
+ const currency = this.currency(code);
2319
+ request['assetCode'] = currency['id'];
2320
+ }
2321
+ const response = await this.spotPublicGetWithdrawConfigs(this.extend(request, params));
2322
+ //
2323
+ // {
2324
+ // "result": "true",
2325
+ // "data": [
2326
+ // {
2327
+ // "amountScale": "4",
2328
+ // "chain": "heco",
2329
+ // "assetCode": "lbk",
2330
+ // "min": "200",
2331
+ // "transferAmtScale": "4",
2332
+ // "canWithDraw": true,
2333
+ // "fee": "100",
2334
+ // "minTransfer": "0.0001",
2335
+ // "type": "1"
2336
+ // },
2337
+ // ...
2338
+ // ],
2339
+ // "error_code": "0",
2340
+ // "ts": "1663364435973"
2341
+ // }
2342
+ //
2343
+ const result = this.safeValue(response, 'data', []);
2344
+ const withdrawFees = {};
2345
+ for (let i = 0; i < result.length; i++) {
2346
+ const item = result[i];
2347
+ const canWithdraw = this.safeValue(item, 'canWithDraw');
2348
+ if (canWithdraw === 'true') {
2349
+ const currencyId = this.safeString(item, 'assetCode');
2350
+ const codeInner = this.safeCurrencyCode(currencyId);
2351
+ const chain = this.safeString(item, 'chain');
2352
+ let network = this.safeString(this.options['inverse-networks'], chain, chain);
2353
+ if (network === undefined) {
2354
+ network = codeInner;
2355
+ }
2356
+ const fee = this.safeString(item, 'fee');
2357
+ if (withdrawFees[codeInner] === undefined) {
2358
+ withdrawFees[codeInner] = {};
2359
+ }
2360
+ withdrawFees[codeInner][network] = this.parseNumber(fee);
2361
+ }
2362
+ }
2363
+ return {
2364
+ 'withdraw': withdrawFees,
2365
+ 'deposit': {},
2366
+ 'info': response,
2367
+ };
2368
+ }
2369
+ async fetchDepositWithdrawFees(codes = undefined, params = {}) {
2370
+ /**
2371
+ * @method
2372
+ * @name lbank2#fetchDepositWithdrawFees
2373
+ * @description when using private endpoint, only returns information for currencies with non-zero balance, use public method by specifying this.options['fetchDepositWithdrawFees']['method'] = 'fetchPublicDepositWithdrawFees'
2374
+ * @see https://www.lbank.info/en-US/docs/index.html#get-all-coins-information
2375
+ * @see https://www.lbank.info/en-US/docs/index.html#withdrawal-configurations
2376
+ * @param {string[]|undefined} codes array of unified currency codes
2377
+ * @param {object} [params] extra parameters specific to the lbank2 api endpoint
2378
+ * @returns {object} a list of [fee structures]{@link https://github.com/ccxt/ccxt/wiki/Manual#fee-structure}
2379
+ */
2380
+ await this.loadMarkets();
2381
+ const isAuthorized = this.checkRequiredCredentials(false);
2382
+ let method = undefined;
2383
+ if (isAuthorized === true) {
2384
+ method = this.safeString(params, 'method');
2385
+ params = this.omit(params, 'method');
2386
+ if (method === undefined) {
2387
+ const options = this.safeValue(this.options, 'fetchDepositWithdrawFees', {});
2388
+ method = this.safeString(options, 'method', 'fetchPrivateDepositWithdrawFees');
2389
+ }
2390
+ }
2391
+ else {
2392
+ method = 'fetchPublicDepositWithdrawFees';
2393
+ }
2394
+ return await this[method](codes, params);
2395
+ }
2396
+ async fetchPrivateDepositWithdrawFees(codes = undefined, params = {}) {
2397
+ // complete response
2398
+ // incl. for coins which undefined in public method
2399
+ await this.loadMarkets();
2400
+ const response = await this.spotPrivatePostSupplementUserInfo(params);
2401
+ //
2402
+ // {
2403
+ // "result": "true",
2404
+ // "data": [
2405
+ // {
2406
+ // "usableAmt": "14.36",
2407
+ // "assetAmt": "14.36",
2408
+ // "networkList": [
2409
+ // {
2410
+ // "isDefault": false,
2411
+ // "withdrawFeeRate": "",
2412
+ // "name": "erc20",
2413
+ // "withdrawMin": 30,
2414
+ // "minLimit": 0.0001,
2415
+ // "minDeposit": 20,
2416
+ // "feeAssetCode": "usdt",
2417
+ // "withdrawFee": "30",
2418
+ // "type": 1,
2419
+ // "coin": "usdt",
2420
+ // "network": "eth"
2421
+ // },
2422
+ // ...
2423
+ // ],
2424
+ // "freezeAmt": "0",
2425
+ // "coin": "ada"
2426
+ // }
2427
+ // ],
2428
+ // "code": 0
2429
+ // }
2430
+ //
2431
+ const data = this.safeValue(response, 'data', []);
2432
+ return this.parseDepositWithdrawFees(data, codes, 'coin');
2433
+ }
2434
+ async fetchPublicDepositWithdrawFees(codes = undefined, params = {}) {
2435
+ // extremely incomplete response
2436
+ // vast majority fees undefined
2437
+ await this.loadMarkets();
2438
+ const request = {};
2439
+ const response = await this.spotPublicGetWithdrawConfigs(this.extend(request, params));
2440
+ //
2441
+ // {
2442
+ // "result": "true",
2443
+ // "data": [
2444
+ // {
2445
+ // "amountScale": "4",
2446
+ // "chain": "heco",
2447
+ // "assetCode": "lbk",
2448
+ // "min": "200",
2449
+ // "transferAmtScale": "4",
2450
+ // "canWithDraw": true,
2451
+ // "fee": "100",
2452
+ // "minTransfer": "0.0001",
2453
+ // "type": "1"
2454
+ // },
2455
+ // ...
2456
+ // ],
2457
+ // "error_code": "0",
2458
+ // "ts": "1663364435973"
2459
+ // }
2460
+ //
2461
+ const data = this.safeValue(response, 'data', []);
2462
+ return this.parsePublicDepositWithdrawFees(data, codes);
2463
+ }
2464
+ parsePublicDepositWithdrawFees(response, codes = undefined) {
2465
+ //
2466
+ // [
2467
+ // {
2468
+ // "amountScale": "4",
2469
+ // "chain": "heco",
2470
+ // "assetCode": "lbk",
2471
+ // "min": "200",
2472
+ // "transferAmtScale": "4",
2473
+ // "canWithDraw": true,
2474
+ // "fee": "100",
2475
+ // "minTransfer": "0.0001",
2476
+ // "type": "1"
2477
+ // },
2478
+ // ...
2479
+ // ]
2480
+ //
2481
+ const result = {};
2482
+ for (let i = 0; i < response.length; i++) {
2483
+ const fee = response[i];
2484
+ const canWithdraw = this.safeValue(fee, 'canWithDraw');
2485
+ if (canWithdraw === true) {
2486
+ const currencyId = this.safeString(fee, 'assetCode');
2487
+ const code = this.safeCurrencyCode(currencyId);
2488
+ if (codes === undefined || this.inArray(code, codes)) {
2489
+ const withdrawFee = this.safeNumber(fee, 'fee');
2490
+ if (withdrawFee !== undefined) {
2491
+ const resultValue = this.safeValue(result, code);
2492
+ if (resultValue === undefined) {
2493
+ result[code] = this.depositWithdrawFee([fee]);
2494
+ }
2495
+ else {
2496
+ result[code]['info'].push(fee);
2497
+ }
2498
+ const chain = this.safeString(fee, 'chain');
2499
+ const networkCode = this.safeString(this.options['inverse-networks'], chain, chain);
2500
+ if (networkCode !== undefined) {
2501
+ result[code]['networks'][networkCode] = {
2502
+ 'withdraw': {
2503
+ 'fee': withdrawFee,
2504
+ 'percentage': undefined,
2505
+ },
2506
+ 'deposit': {
2507
+ 'fee': undefined,
2508
+ 'percentage': undefined,
2509
+ },
2510
+ };
2511
+ }
2512
+ else {
2513
+ result[code]['withdraw'] = {
2514
+ 'fee': withdrawFee,
2515
+ 'percentage': undefined,
2516
+ };
2517
+ }
2518
+ }
2519
+ }
2520
+ }
2521
+ }
2522
+ return result;
2523
+ }
2524
+ parseDepositWithdrawFee(fee, currency = undefined) {
2525
+ //
2526
+ // * only used for fetchPrivateDepositWithdrawFees
2527
+ //
2528
+ // {
2529
+ // "usableAmt": "14.36",
2530
+ // "assetAmt": "14.36",
2531
+ // "networkList": [
2532
+ // {
2533
+ // "isDefault": false,
2534
+ // "withdrawFeeRate": "",
2535
+ // "name": "erc20",
2536
+ // "withdrawMin": 30,
2537
+ // "minLimit": 0.0001,
2538
+ // "minDeposit": 20,
2539
+ // "feeAssetCode": "usdt",
2540
+ // "withdrawFee": "30",
2541
+ // "type": 1,
2542
+ // "coin": "usdt",
2543
+ // "network": "eth"
2544
+ // },
2545
+ // ...
2546
+ // ],
2547
+ // "freezeAmt": "0",
2548
+ // "coin": "ada"
2549
+ // }
2550
+ //
2551
+ const result = this.depositWithdrawFee(fee);
2552
+ const networkList = this.safeValue(fee, 'networkList', []);
2553
+ for (let j = 0; j < networkList.length; j++) {
2554
+ const networkEntry = networkList[j];
2555
+ const networkId = this.safeString(networkEntry, 'name');
2556
+ const networkCode = this.safeStringUpper(this.options['inverse-networks'], networkId, networkId);
2557
+ const withdrawFee = this.safeNumber(networkEntry, 'withdrawFee');
2558
+ const isDefault = this.safeValue(networkEntry, 'isDefault');
2559
+ if (withdrawFee !== undefined) {
2560
+ if (isDefault) {
2561
+ result['withdraw'] = {
2562
+ 'fee': withdrawFee,
2563
+ 'percentage': undefined,
2564
+ };
2565
+ }
2566
+ result['networks'][networkCode] = {
2567
+ 'withdraw': {
2568
+ 'fee': withdrawFee,
2569
+ 'percentage': undefined,
2570
+ },
2571
+ 'deposit': {
2572
+ 'fee': undefined,
2573
+ 'percentage': undefined,
2574
+ },
2575
+ };
2576
+ }
2577
+ }
2578
+ return result;
799
2579
  }
800
2580
  sign(path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
801
2581
  let query = this.omit(params, this.extractParams(path));
802
2582
  let url = this.urls['api']['rest'] + '/' + this.version + '/' + this.implodeParams(path, params);
803
- // Every endpoint ends with ".do"
804
- url += '.do';
805
- if (api === 'public') {
2583
+ // Every spot endpoint ends with ".do"
2584
+ if (api[0] === 'spot') {
2585
+ url += '.do';
2586
+ }
2587
+ else {
2588
+ url = this.urls['api']['contract'] + '/' + this.implodeParams(path, params);
2589
+ }
2590
+ if (api[1] === 'public') {
806
2591
  if (Object.keys(query).length) {
807
- url += '?' + this.urlencode(query);
2592
+ url += '?' + this.urlencode(this.keysort(query));
808
2593
  }
809
2594
  }
810
2595
  else {
811
2596
  this.checkRequiredCredentials();
812
- query = this.keysort(this.extend({
2597
+ const timestamp = this.milliseconds().toString();
2598
+ const echostr = this.uuid22() + this.uuid16();
2599
+ query = this.extend({
813
2600
  'api_key': this.apiKey,
814
- }, query));
815
- const queryString = this.rawencode(query);
816
- const message = this.hash(this.encode(queryString), md5.md5).toUpperCase();
817
- const cacheSecretAsPem = this.safeValue(this.options, 'cacheSecretAsPem', true);
818
- let pem = undefined;
819
- if (cacheSecretAsPem) {
820
- pem = this.safeValue(this.options, 'pem');
821
- if (pem === undefined) {
822
- pem = this.convertSecretToPem(this.secret);
823
- this.options['pem'] = pem;
824
- }
2601
+ }, query);
2602
+ let signatureMethod = undefined;
2603
+ if (this.secret.length > 32) {
2604
+ signatureMethod = 'RSA';
825
2605
  }
826
2606
  else {
827
- pem = this.convertSecretToPem(this.secret);
2607
+ signatureMethod = 'HmacSHA256';
828
2608
  }
829
- query['sign'] = rsa.rsa(message, pem, sha256.sha256);
830
- body = this.urlencode(query);
831
- headers = { 'Content-Type': 'application/x-www-form-urlencoded' };
2609
+ const auth = this.rawencode(this.keysort(this.extend({
2610
+ 'echostr': echostr,
2611
+ 'signature_method': signatureMethod,
2612
+ 'timestamp': timestamp,
2613
+ }, query)));
2614
+ const encoded = this.encode(auth);
2615
+ const hash = this.hash(encoded, md5.md5);
2616
+ const uppercaseHash = hash.toUpperCase();
2617
+ let sign = undefined;
2618
+ if (signatureMethod === 'RSA') {
2619
+ const cacheSecretAsPem = this.safeValue(this.options, 'cacheSecretAsPem', true);
2620
+ let pem = undefined;
2621
+ if (cacheSecretAsPem) {
2622
+ pem = this.safeValue(this.options, 'pem');
2623
+ if (pem === undefined) {
2624
+ pem = this.convertSecretToPem(this.encode(this.secret));
2625
+ this.options['pem'] = pem;
2626
+ }
2627
+ }
2628
+ else {
2629
+ pem = this.convertSecretToPem(this.encode(this.secret));
2630
+ }
2631
+ sign = rsa.rsa(uppercaseHash, pem, sha256.sha256);
2632
+ }
2633
+ else if (signatureMethod === 'HmacSHA256') {
2634
+ sign = this.hmac(this.encode(uppercaseHash), this.encode(this.secret), sha256.sha256);
2635
+ }
2636
+ query['sign'] = sign;
2637
+ body = this.urlencode(this.keysort(query));
2638
+ headers = {
2639
+ 'Content-Type': 'application/x-www-form-urlencoded',
2640
+ 'timestamp': timestamp,
2641
+ 'signature_method': signatureMethod,
2642
+ 'echostr': echostr,
2643
+ };
832
2644
  }
833
2645
  return { 'url': url, 'method': method, 'body': body, 'headers': headers };
834
2646
  }
2647
+ convertSecretToPem(secret) {
2648
+ const lineLength = 64;
2649
+ const secretLength = secret.length - 0;
2650
+ let numLines = this.parseToInt(secretLength / lineLength);
2651
+ numLines = this.sum(numLines, 1);
2652
+ let pem = "-----BEGIN PRIVATE KEY-----\n"; // eslint-disable-line
2653
+ for (let i = 0; i < numLines; i++) {
2654
+ const start = i * lineLength;
2655
+ const end = this.sum(start, lineLength);
2656
+ pem += this.secret.slice(start, end) + "\n"; // eslint-disable-line
2657
+ }
2658
+ return pem + '-----END PRIVATE KEY-----';
2659
+ }
835
2660
  handleErrors(httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
836
2661
  if (response === undefined) {
837
2662
  return undefined;
838
2663
  }
839
- const success = this.safeString(response, 'result');
840
- if (success === 'false') {
2664
+ const success = this.safeValue(response, 'result');
2665
+ if (success === 'false' || !success) {
841
2666
  const errorCode = this.safeString(response, 'error_code');
842
2667
  const message = this.safeString({
843
2668
  '10000': 'Internal error',
844
2669
  '10001': 'The required parameters can not be empty',
845
- '10002': 'verification failed',
846
- '10003': 'Illegal parameters',
847
- '10004': 'User requests are too frequent',
848
- '10005': 'Key does not exist',
849
- '10006': 'user does not exist',
2670
+ '10002': 'Validation failed',
2671
+ '10003': 'Invalid parameter',
2672
+ '10004': 'Request too frequent',
2673
+ '10005': 'Secret key does not exist',
2674
+ '10006': 'User does not exist',
850
2675
  '10007': 'Invalid signature',
851
- '10008': 'This currency pair is not supported',
852
- '10009': 'Limit orders can not be missing orders and the number of orders',
853
- '10010': 'Order price or order quantity must be greater than 0',
854
- '10011': 'Market orders can not be missing the amount of the order',
855
- '10012': 'market sell orders can not be missing orders',
856
- '10013': 'is less than the minimum trading position 0.001',
857
- '10014': 'Account number is not enough',
858
- '10015': 'The order type is wrong',
859
- '10016': 'Account balance is not enough',
860
- '10017': 'Abnormal server',
861
- '10018': 'order inquiry can not be more than 50 less than one',
862
- '10019': 'withdrawal orders can not be more than 3 less than one',
863
- '10020': 'less than the minimum amount of the transaction limit of 0.001',
864
- '10022': 'Insufficient key authority',
2676
+ '10008': 'Invalid Trading Pair',
2677
+ '10009': 'Price and/or Amount are required for limit order',
2678
+ '10010': 'Price and/or Amount must be less than minimum requirement',
2679
+ // '10011': 'Market orders can not be missing the amount of the order',
2680
+ // '10012': 'market sell orders can not be missing orders',
2681
+ '10013': 'The amount is too small',
2682
+ '10014': 'Insufficient amount of money in the account',
2683
+ '10015': 'Invalid order type',
2684
+ '10016': 'Insufficient account balance',
2685
+ '10017': 'Server Error',
2686
+ '10018': 'Page size should be between 1 and 50',
2687
+ '10019': 'Cancel NO more than 3 orders in one request',
2688
+ '10020': 'Volume < 0.001',
2689
+ '10021': 'Price < 0.01',
2690
+ '10022': 'Invalid authorization',
2691
+ '10023': 'Market Order is not supported yet',
2692
+ '10024': 'User cannot trade on this pair',
2693
+ '10025': 'Order has been filled',
2694
+ '10026': 'Order has been cancelld',
2695
+ '10027': 'Order is cancelling',
2696
+ '10028': 'Wrong query time',
2697
+ '10029': 'from is not in the query time',
2698
+ '10030': 'from do not match the transaction type of inqury',
2699
+ '10031': 'echostr length must be valid and length must be from 30 to 40',
2700
+ '10033': 'Failed to create order',
2701
+ '10036': 'customID duplicated',
2702
+ '10100': 'Has no privilege to withdraw',
2703
+ '10101': 'Invalid fee rate to withdraw',
2704
+ '10102': 'Too little to withdraw',
2705
+ '10103': 'Exceed daily limitation of withdraw',
2706
+ '10104': 'Cancel was rejected',
2707
+ '10105': 'Request has been cancelled',
2708
+ '10106': 'None trade time',
2709
+ '10107': 'Start price exception',
2710
+ '10108': 'can not create order',
2711
+ '10109': 'wallet address is not mapping',
2712
+ '10110': 'transfer fee is not mapping',
2713
+ '10111': 'mount > 0',
2714
+ '10112': 'fee is too lower',
2715
+ '10113': 'transfer fee is 0',
2716
+ '10600': 'intercepted by replay attacks filter, check timestamp',
2717
+ '10601': 'Interface closed unavailable',
2718
+ '10701': 'invalid asset code',
2719
+ '10702': 'not allowed deposit',
865
2720
  }, errorCode, this.json(response));
866
2721
  const ErrorClass = this.safeValue({
2722
+ '10001': errors.BadRequest,
867
2723
  '10002': errors.AuthenticationError,
868
- '10004': errors.DDoSProtection,
2724
+ '10003': errors.BadRequest,
2725
+ '10004': errors.RateLimitExceeded,
869
2726
  '10005': errors.AuthenticationError,
870
2727
  '10006': errors.AuthenticationError,
871
2728
  '10007': errors.AuthenticationError,
2729
+ '10008': errors.BadSymbol,
872
2730
  '10009': errors.InvalidOrder,
873
2731
  '10010': errors.InvalidOrder,
874
- '10011': errors.InvalidOrder,
875
- '10012': errors.InvalidOrder,
876
2732
  '10013': errors.InvalidOrder,
877
- '10014': errors.InvalidOrder,
2733
+ '10014': errors.InsufficientFunds,
878
2734
  '10015': errors.InvalidOrder,
879
- '10016': errors.InvalidOrder,
880
- '10022': errors.AuthenticationError,
2735
+ '10016': errors.InsufficientFunds,
2736
+ '10017': errors.ExchangeError,
2737
+ '10018': errors.BadRequest,
2738
+ '10019': errors.BadRequest,
2739
+ '10020': errors.BadRequest,
2740
+ '10021': errors.InvalidOrder,
2741
+ '10022': errors.PermissionDenied,
2742
+ '10023': errors.InvalidOrder,
2743
+ '10024': errors.PermissionDenied,
2744
+ '10025': errors.InvalidOrder,
2745
+ '10026': errors.InvalidOrder,
2746
+ '10027': errors.InvalidOrder,
2747
+ '10028': errors.BadRequest,
2748
+ '10029': errors.BadRequest,
2749
+ '10030': errors.BadRequest,
2750
+ '10031': errors.InvalidNonce,
2751
+ '10033': errors.ExchangeError,
2752
+ '10036': errors.DuplicateOrderId,
2753
+ '10100': errors.PermissionDenied,
2754
+ '10101': errors.BadRequest,
2755
+ '10102': errors.InsufficientFunds,
2756
+ '10103': errors.ExchangeError,
2757
+ '10104': errors.ExchangeError,
2758
+ '10105': errors.ExchangeError,
2759
+ '10106': errors.BadRequest,
2760
+ '10107': errors.BadRequest,
2761
+ '10108': errors.ExchangeError,
2762
+ '10109': errors.InvalidAddress,
2763
+ '10110': errors.ExchangeError,
2764
+ '10111': errors.BadRequest,
2765
+ '10112': errors.BadRequest,
2766
+ '10113': errors.BadRequest,
2767
+ '10600': errors.BadRequest,
2768
+ '10601': errors.ExchangeError,
2769
+ '10701': errors.BadSymbol,
2770
+ '10702': errors.PermissionDenied, // 'not allowed deposit',
881
2771
  }, errorCode, errors.ExchangeError);
882
2772
  throw new ErrorClass(message);
883
2773
  }