ccxt 4.1.54__py2.py3-none-any.whl → 4.1.56__py2.py3-none-any.whl

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.

Potentially problematic release.


This version of ccxt might be problematic. Click here for more details.

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