ccxt 4.1.52 → 4.1.54

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