ccxt 4.3.54__py2.py3-none-any.whl → 4.3.55__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.
Files changed (254) hide show
  1. ccxt/__init__.py +1 -1
  2. ccxt/abstract/kucoin.py +3 -0
  3. ccxt/abstract/kucoinfutures.py +3 -0
  4. ccxt/ace.py +1 -1
  5. ccxt/alpaca.py +1 -1
  6. ccxt/ascendex.py +6 -4
  7. ccxt/async_support/__init__.py +1 -1
  8. ccxt/async_support/ace.py +1 -1
  9. ccxt/async_support/alpaca.py +1 -1
  10. ccxt/async_support/ascendex.py +6 -4
  11. ccxt/async_support/base/exchange.py +1 -1
  12. ccxt/async_support/bigone.py +1 -1
  13. ccxt/async_support/binance.py +6 -6
  14. ccxt/async_support/bingx.py +3 -3
  15. ccxt/async_support/bit2c.py +1 -1
  16. ccxt/async_support/bitbank.py +1 -1
  17. ccxt/async_support/bitbns.py +1 -1
  18. ccxt/async_support/bitfinex.py +1 -1
  19. ccxt/async_support/bitfinex2.py +1 -1
  20. ccxt/async_support/bitflyer.py +1 -1
  21. ccxt/async_support/bitget.py +2 -2
  22. ccxt/async_support/bithumb.py +1 -1
  23. ccxt/async_support/bitmart.py +3 -3
  24. ccxt/async_support/bitmex.py +1 -1
  25. ccxt/async_support/bitopro.py +1 -1
  26. ccxt/async_support/bitrue.py +1 -1
  27. ccxt/async_support/bitso.py +1 -1
  28. ccxt/async_support/bitstamp.py +1 -1
  29. ccxt/async_support/bitteam.py +1 -1
  30. ccxt/async_support/bitvavo.py +2 -2
  31. ccxt/async_support/bl3p.py +1 -1
  32. ccxt/async_support/blockchaincom.py +28 -28
  33. ccxt/async_support/blofin.py +1 -1
  34. ccxt/async_support/btcalpha.py +4 -11
  35. ccxt/async_support/btcbox.py +1 -1
  36. ccxt/async_support/btcmarkets.py +1 -1
  37. ccxt/async_support/btcturk.py +1 -1
  38. ccxt/async_support/bybit.py +2 -2
  39. ccxt/async_support/cex.py +2 -2
  40. ccxt/async_support/coinbase.py +33 -33
  41. ccxt/async_support/coinbaseexchange.py +1 -1
  42. ccxt/async_support/coinbaseinternational.py +1 -1
  43. ccxt/async_support/coincheck.py +1 -1
  44. ccxt/async_support/coinex.py +2 -2
  45. ccxt/async_support/coinlist.py +2 -2
  46. ccxt/async_support/coinmate.py +1 -1
  47. ccxt/async_support/coinmetro.py +1 -1
  48. ccxt/async_support/coinone.py +1 -1
  49. ccxt/async_support/coinsph.py +1 -1
  50. ccxt/async_support/coinspot.py +1 -1
  51. ccxt/async_support/cryptocom.py +1 -1
  52. ccxt/async_support/currencycom.py +1 -1
  53. ccxt/async_support/delta.py +2 -2
  54. ccxt/async_support/deribit.py +4 -4
  55. ccxt/async_support/digifinex.py +2 -2
  56. ccxt/async_support/exmo.py +2 -2
  57. ccxt/async_support/gate.py +2 -2
  58. ccxt/async_support/gemini.py +1 -1
  59. ccxt/async_support/hitbtc.py +1 -1
  60. ccxt/async_support/hollaex.py +1 -1
  61. ccxt/async_support/htx.py +3 -3
  62. ccxt/async_support/huobijp.py +1 -1
  63. ccxt/async_support/hyperliquid.py +2 -2
  64. ccxt/async_support/idex.py +1 -1
  65. ccxt/async_support/independentreserve.py +1 -1
  66. ccxt/async_support/indodax.py +1 -1
  67. ccxt/async_support/kraken.py +2 -2
  68. ccxt/async_support/kucoin.py +127 -46
  69. ccxt/async_support/kucoinfutures.py +1 -1
  70. ccxt/async_support/kuna.py +1 -1
  71. ccxt/async_support/latoken.py +1 -1
  72. ccxt/async_support/lbank.py +1 -1
  73. ccxt/async_support/luno.py +1 -1
  74. ccxt/async_support/lykke.py +1 -1
  75. ccxt/async_support/mercado.py +1 -1
  76. ccxt/async_support/mexc.py +1 -1
  77. ccxt/async_support/ndax.py +1 -1
  78. ccxt/async_support/novadax.py +1 -1
  79. ccxt/async_support/oceanex.py +1 -1
  80. ccxt/async_support/okcoin.py +1 -1
  81. ccxt/async_support/okx.py +3 -3
  82. ccxt/async_support/onetrading.py +1 -1
  83. ccxt/async_support/oxfun.py +2 -2
  84. ccxt/async_support/p2b.py +1 -1
  85. ccxt/async_support/paymium.py +1 -1
  86. ccxt/async_support/phemex.py +2 -2
  87. ccxt/async_support/poloniex.py +4 -3
  88. ccxt/async_support/poloniexfutures.py +1 -1
  89. ccxt/async_support/probit.py +1 -1
  90. ccxt/async_support/timex.py +1 -1
  91. ccxt/async_support/tokocrypto.py +1 -1
  92. ccxt/async_support/tradeogre.py +1 -1
  93. ccxt/async_support/upbit.py +1 -1
  94. ccxt/async_support/vertex.py +2 -2
  95. ccxt/async_support/wavesexchange.py +1 -1
  96. ccxt/async_support/wazirx.py +1 -1
  97. ccxt/async_support/whitebit.py +2 -2
  98. ccxt/async_support/woo.py +5 -5
  99. ccxt/async_support/woofipro.py +3 -3
  100. ccxt/async_support/yobit.py +1 -1
  101. ccxt/async_support/zaif.py +1 -1
  102. ccxt/async_support/zonda.py +1 -1
  103. ccxt/base/exchange.py +1 -1
  104. ccxt/base/types.py +4 -1
  105. ccxt/bigone.py +1 -1
  106. ccxt/binance.py +6 -6
  107. ccxt/bingx.py +3 -3
  108. ccxt/bit2c.py +1 -1
  109. ccxt/bitbank.py +1 -1
  110. ccxt/bitbns.py +1 -1
  111. ccxt/bitfinex.py +1 -1
  112. ccxt/bitfinex2.py +1 -1
  113. ccxt/bitflyer.py +1 -1
  114. ccxt/bitget.py +2 -2
  115. ccxt/bithumb.py +1 -1
  116. ccxt/bitmart.py +3 -3
  117. ccxt/bitmex.py +1 -1
  118. ccxt/bitopro.py +1 -1
  119. ccxt/bitrue.py +1 -1
  120. ccxt/bitso.py +1 -1
  121. ccxt/bitstamp.py +1 -1
  122. ccxt/bitteam.py +1 -1
  123. ccxt/bitvavo.py +2 -2
  124. ccxt/bl3p.py +1 -1
  125. ccxt/blockchaincom.py +28 -28
  126. ccxt/blofin.py +1 -1
  127. ccxt/btcalpha.py +4 -11
  128. ccxt/btcbox.py +1 -1
  129. ccxt/btcmarkets.py +1 -1
  130. ccxt/btcturk.py +1 -1
  131. ccxt/bybit.py +2 -2
  132. ccxt/cex.py +2 -2
  133. ccxt/coinbase.py +33 -33
  134. ccxt/coinbaseexchange.py +1 -1
  135. ccxt/coinbaseinternational.py +1 -1
  136. ccxt/coincheck.py +1 -1
  137. ccxt/coinex.py +2 -2
  138. ccxt/coinlist.py +2 -2
  139. ccxt/coinmate.py +1 -1
  140. ccxt/coinmetro.py +1 -1
  141. ccxt/coinone.py +1 -1
  142. ccxt/coinsph.py +1 -1
  143. ccxt/coinspot.py +1 -1
  144. ccxt/cryptocom.py +1 -1
  145. ccxt/currencycom.py +1 -1
  146. ccxt/delta.py +2 -2
  147. ccxt/deribit.py +4 -4
  148. ccxt/digifinex.py +2 -2
  149. ccxt/exmo.py +2 -2
  150. ccxt/gate.py +2 -2
  151. ccxt/gemini.py +1 -1
  152. ccxt/hitbtc.py +1 -1
  153. ccxt/hollaex.py +1 -1
  154. ccxt/htx.py +3 -3
  155. ccxt/huobijp.py +1 -1
  156. ccxt/hyperliquid.py +2 -2
  157. ccxt/idex.py +1 -1
  158. ccxt/independentreserve.py +1 -1
  159. ccxt/indodax.py +1 -1
  160. ccxt/kraken.py +2 -2
  161. ccxt/kucoin.py +127 -46
  162. ccxt/kucoinfutures.py +1 -1
  163. ccxt/kuna.py +1 -1
  164. ccxt/latoken.py +1 -1
  165. ccxt/lbank.py +1 -1
  166. ccxt/luno.py +1 -1
  167. ccxt/lykke.py +1 -1
  168. ccxt/mercado.py +1 -1
  169. ccxt/mexc.py +1 -1
  170. ccxt/ndax.py +1 -1
  171. ccxt/novadax.py +1 -1
  172. ccxt/oceanex.py +1 -1
  173. ccxt/okcoin.py +1 -1
  174. ccxt/okx.py +3 -3
  175. ccxt/onetrading.py +1 -1
  176. ccxt/oxfun.py +2 -2
  177. ccxt/p2b.py +1 -1
  178. ccxt/paymium.py +1 -1
  179. ccxt/phemex.py +2 -2
  180. ccxt/poloniex.py +4 -3
  181. ccxt/poloniexfutures.py +1 -1
  182. ccxt/pro/__init__.py +1 -1
  183. ccxt/pro/binance.py +2 -2
  184. ccxt/pro/bitvavo.py +2 -2
  185. ccxt/pro/bybit.py +2 -2
  186. ccxt/pro/cex.py +3 -3
  187. ccxt/pro/coinbase.py +22 -1
  188. ccxt/pro/cryptocom.py +1 -1
  189. ccxt/pro/gate.py +2 -2
  190. ccxt/pro/hitbtc.py +1 -1
  191. ccxt/pro/kraken.py +2 -2
  192. ccxt/pro/kucoin.py +2 -2
  193. ccxt/pro/okx.py +2 -2
  194. ccxt/pro/oxfun.py +2 -2
  195. ccxt/pro/poloniex.py +1 -1
  196. ccxt/pro/vertex.py +1 -1
  197. ccxt/probit.py +1 -1
  198. ccxt/test/{test_async.py → tests_async.py} +27 -280
  199. ccxt/test/tests_helpers.py +284 -0
  200. ccxt/test/tests_init.py +35 -0
  201. ccxt/test/{test_sync.py → tests_sync.py} +27 -282
  202. ccxt/timex.py +1 -1
  203. ccxt/tokocrypto.py +1 -1
  204. ccxt/tradeogre.py +1 -1
  205. ccxt/upbit.py +1 -1
  206. ccxt/vertex.py +2 -2
  207. ccxt/wavesexchange.py +1 -1
  208. ccxt/wazirx.py +1 -1
  209. ccxt/whitebit.py +2 -2
  210. ccxt/woo.py +5 -5
  211. ccxt/woofipro.py +3 -3
  212. ccxt/yobit.py +1 -1
  213. ccxt/zaif.py +1 -1
  214. ccxt/zonda.py +1 -1
  215. {ccxt-4.3.54.dist-info → ccxt-4.3.55.dist-info}/METADATA +5 -5
  216. {ccxt-4.3.54.dist-info → ccxt-4.3.55.dist-info}/RECORD +219 -252
  217. ccxt/test/base/__init__.py +0 -29
  218. ccxt/test/base/test_account.py +0 -26
  219. ccxt/test/base/test_balance.py +0 -56
  220. ccxt/test/base/test_borrow_interest.py +0 -35
  221. ccxt/test/base/test_borrow_rate.py +0 -32
  222. ccxt/test/base/test_calculate_fee.py +0 -51
  223. ccxt/test/base/test_crypto.py +0 -127
  224. ccxt/test/base/test_currency.py +0 -76
  225. ccxt/test/base/test_datetime.py +0 -109
  226. ccxt/test/base/test_decimal_to_precision.py +0 -392
  227. ccxt/test/base/test_deep_extend.py +0 -68
  228. ccxt/test/base/test_deposit_withdrawal.py +0 -50
  229. ccxt/test/base/test_exchange_datetime_functions.py +0 -76
  230. ccxt/test/base/test_funding_rate_history.py +0 -29
  231. ccxt/test/base/test_last_price.py +0 -31
  232. ccxt/test/base/test_ledger_entry.py +0 -45
  233. ccxt/test/base/test_ledger_item.py +0 -48
  234. ccxt/test/base/test_leverage_tier.py +0 -33
  235. ccxt/test/base/test_liquidation.py +0 -50
  236. ccxt/test/base/test_margin_mode.py +0 -24
  237. ccxt/test/base/test_margin_modification.py +0 -35
  238. ccxt/test/base/test_market.py +0 -193
  239. ccxt/test/base/test_number.py +0 -411
  240. ccxt/test/base/test_ohlcv.py +0 -33
  241. ccxt/test/base/test_open_interest.py +0 -32
  242. ccxt/test/base/test_order.py +0 -64
  243. ccxt/test/base/test_order_book.py +0 -69
  244. ccxt/test/base/test_position.py +0 -60
  245. ccxt/test/base/test_shared_methods.py +0 -353
  246. ccxt/test/base/test_status.py +0 -24
  247. ccxt/test/base/test_throttle.py +0 -126
  248. ccxt/test/base/test_ticker.py +0 -92
  249. ccxt/test/base/test_trade.py +0 -47
  250. ccxt/test/base/test_trading_fee.py +0 -26
  251. ccxt/test/base/test_transaction.py +0 -39
  252. {ccxt-4.3.54.dist-info → ccxt-4.3.55.dist-info}/LICENSE.txt +0 -0
  253. {ccxt-4.3.54.dist-info → ccxt-4.3.55.dist-info}/WHEEL +0 -0
  254. {ccxt-4.3.54.dist-info → ccxt-4.3.55.dist-info}/top_level.txt +0 -0
ccxt/pro/cex.py CHANGED
@@ -640,7 +640,7 @@ class cex(ccxt.async_support.cex):
640
640
  # }
641
641
  # }
642
642
  # }
643
- # fullfilledOrder
643
+ # fulfilledOrder
644
644
  # {
645
645
  # "e": "order",
646
646
  # "data": {
@@ -1187,7 +1187,7 @@ class cex(ccxt.async_support.cex):
1187
1187
  :param str type: 'market' or 'limit'
1188
1188
  :param str side: 'buy' or 'sell'
1189
1189
  :param float amount: how much of currency you want to trade in units of base currency
1190
- :param float price: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1190
+ :param float price: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
1191
1191
  :param dict [params]: extra parameters specific to the kraken api endpoint
1192
1192
  :param boolean [params.maker_only]: Optional, maker only places an order only if offers best sell(<= max) or buy(>= max) price for self pair, if not order placement will be rejected with an error - "Order is not maker"
1193
1193
  :returns dict: an `order structure <https://docs.ccxt.com/en/latest/manual.html#order-structure>`
@@ -1222,7 +1222,7 @@ class cex(ccxt.async_support.cex):
1222
1222
  :param str type: 'market' or 'limit'
1223
1223
  :param str side: 'buy' or 'sell'
1224
1224
  :param float amount: how much of the currency you want to trade in units of the base currency
1225
- :param float|None [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1225
+ :param float|None [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
1226
1226
  :param dict [params]: extra parameters specific to the cex api endpoint
1227
1227
  :returns dict: an `order structure <https://docs.ccxt.com/en/latest/manual.html#order-structure>`
1228
1228
  """
ccxt/pro/coinbase.py CHANGED
@@ -660,6 +660,25 @@ class coinbase(ccxt.async_support.coinbase):
660
660
  #
661
661
  return message
662
662
 
663
+ def handle_heartbeats(self, client, message):
664
+ # although the subscription takes a product_ids parameter(i.e. symbol),
665
+ # there is no(clear) way of mapping the message back to the symbol.
666
+ #
667
+ # {
668
+ # "channel": "heartbeats",
669
+ # "client_id": "",
670
+ # "timestamp": "2023-06-23T20:31:26.122969572Z",
671
+ # "sequence_num": 0,
672
+ # "events": [
673
+ # {
674
+ # "current_time": "2023-06-23 20:31:56.121961769 +0000 UTC m=+91717.525857105",
675
+ # "heartbeat_counter": "3049"
676
+ # }
677
+ # ]
678
+ # }
679
+ #
680
+ return message
681
+
663
682
  def handle_message(self, client, message):
664
683
  channel = self.safe_string(message, 'channel')
665
684
  methods: dict = {
@@ -669,10 +688,12 @@ class coinbase(ccxt.async_support.coinbase):
669
688
  'market_trades': self.handle_trade,
670
689
  'user': self.handle_order,
671
690
  'l2_data': self.handle_order_book,
691
+ 'heartbeats': self.handle_heartbeats,
672
692
  }
673
693
  type = self.safe_string(message, 'type')
674
694
  if type == 'error':
675
695
  errorMessage = self.safe_string(message, 'message')
676
696
  raise ExchangeError(errorMessage)
677
697
  method = self.safe_value(methods, channel)
678
- method(client, message)
698
+ if method:
699
+ method(client, message)
ccxt/pro/cryptocom.py CHANGED
@@ -682,7 +682,7 @@ class cryptocom(ccxt.async_support.cryptocom):
682
682
  :param str type: 'market' or 'limit'
683
683
  :param str side: 'buy' or 'sell'
684
684
  :param float amount: how much of currency you want to trade in units of base currency
685
- :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
685
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
686
686
  :param dict [params]: extra parameters specific to the exchange API endpoint
687
687
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
688
688
  """
ccxt/pro/gate.py CHANGED
@@ -138,7 +138,7 @@ class gate(ccxt.async_support.gate):
138
138
  :param str type: 'limit' or 'market' *"market" is contract only*
139
139
  :param str side: 'buy' or 'sell'
140
140
  :param float amount: the amount of currency to trade
141
- :param float [price]: *ignored in "market" orders* the price at which the order is to be fullfilled at in units of the quote currency
141
+ :param float [price]: *ignored in "market" orders* the price at which the order is to be fulfilled at in units of the quote currency
142
142
  :param dict [params]: extra parameters specific to the exchange API endpoint
143
143
  :param float [params.stopPrice]: The price at which a trigger order is triggered at
144
144
  :param str [params.timeInForce]: "GTC", "IOC", or "PO"
@@ -249,7 +249,7 @@ class gate(ccxt.async_support.gate):
249
249
  :param str type: 'market' or 'limit'
250
250
  :param str side: 'buy' or 'sell'
251
251
  :param float amount: how much of the currency you want to trade in units of the base currency
252
- :param float [price]: the price at which the order is to be fullfilled, in units of the base currency, ignored in market orders
252
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
253
253
  :param dict [params]: extra parameters specific to the exchange API endpoint
254
254
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
255
255
  """
ccxt/pro/hitbtc.py CHANGED
@@ -954,7 +954,7 @@ class hitbtc(ccxt.async_support.hitbtc):
954
954
  :param str type: 'market' or 'limit'
955
955
  :param str side: 'buy' or 'sell'
956
956
  :param float amount: how much of currency you want to trade in units of base currency
957
- :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
957
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
958
958
  :param dict [params]: extra parameters specific to the exchange API endpoint
959
959
  :param str [params.marginMode]: 'cross' or 'isolated' only 'isolated' is supported for spot-margin, swap supports both, default is 'cross'
960
960
  :param bool [params.margin]: True for creating a margin order
ccxt/pro/kraken.py CHANGED
@@ -131,7 +131,7 @@ class kraken(ccxt.async_support.kraken):
131
131
  :param str type: 'market' or 'limit'
132
132
  :param str side: 'buy' or 'sell'
133
133
  :param float amount: how much of currency you want to trade in units of base currency
134
- :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
134
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
135
135
  :param dict [params]: extra parameters specific to the exchange API endpoint
136
136
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
137
137
  """
@@ -186,7 +186,7 @@ class kraken(ccxt.async_support.kraken):
186
186
  :param str type: 'market' or 'limit'
187
187
  :param str side: 'buy' or 'sell'
188
188
  :param float amount: how much of the currency you want to trade in units of the base currency
189
- :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
189
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
190
190
  :param dict [params]: extra parameters specific to the exchange API endpoint
191
191
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
192
192
  """
ccxt/pro/kucoin.py CHANGED
@@ -999,8 +999,8 @@ class kucoin(ccxt.async_support.kucoin):
999
999
  type = self.safe_string(trade, 'orderType')
1000
1000
  side = self.safe_string(trade, 'side')
1001
1001
  tradeId = self.safe_string(trade, 'tradeId')
1002
- price = self.safe_string(trade, 'price')
1003
- amount = self.safe_string(trade, 'size')
1002
+ price = self.safe_string(trade, 'matchPrice')
1003
+ amount = self.safe_string(trade, 'matchSize')
1004
1004
  order = self.safe_string(trade, 'orderId')
1005
1005
  timestamp = self.safe_integer_product(trade, 'ts', 0.000001)
1006
1006
  return self.safe_trade({
ccxt/pro/okx.py CHANGED
@@ -1520,7 +1520,7 @@ class okx(ccxt.async_support.okx):
1520
1520
  :param str type: 'market' or 'limit'
1521
1521
  :param str side: 'buy' or 'sell'
1522
1522
  :param float amount: how much of currency you want to trade in units of base currency
1523
- :param float|None [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1523
+ :param float|None [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
1524
1524
  :param dict [params]: extra parameters specific to the exchange API endpoint
1525
1525
  :param boolean params['test']: test order, default False
1526
1526
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
@@ -1586,7 +1586,7 @@ class okx(ccxt.async_support.okx):
1586
1586
  :param str type: 'market' or 'limit'
1587
1587
  :param str side: 'buy' or 'sell'
1588
1588
  :param float amount: how much of the currency you want to trade in units of the base currency
1589
- :param float|None [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1589
+ :param float|None [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
1590
1590
  :param dict [params]: extra parameters specific to the exchange API endpoint
1591
1591
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1592
1592
  """
ccxt/pro/oxfun.py CHANGED
@@ -715,7 +715,7 @@ class oxfun(ccxt.async_support.oxfun):
715
715
  :param str type: 'market', 'limit', 'STOP_LIMIT' or 'STOP_MARKET'
716
716
  :param str side: 'buy' or 'sell'
717
717
  :param float amount: how much of currency you want to trade in units of base currency
718
- :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
718
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
719
719
  :param dict [params]: extra parameters specific to the exchange API endpoint
720
720
  :param int [params.clientOrderId]: a unique id for the order
721
721
  :param int [params.timestamp]: in milliseconds. If an order reaches the matching engine and the current timestamp exceeds timestamp + recvWindow, then the order will be rejected.
@@ -754,7 +754,7 @@ class oxfun(ccxt.async_support.oxfun):
754
754
  :param str type: 'market' or 'limit'
755
755
  :param str side: 'buy' or 'sell'
756
756
  :param float amount: how much of the currency you want to trade in units of the base currency
757
- :param float|None [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
757
+ :param float|None [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
758
758
  :param int [params.timestamp]: in milliseconds. If an order reaches the matching engine and the current timestamp exceeds timestamp + recvWindow, then the order will be rejected.
759
759
  :param int [params.recvWindow]: in milliseconds. If an order reaches the matching engine and the current timestamp exceeds timestamp + recvWindow, then the order will be rejected. If timestamp is provided without recvWindow, then a default recvWindow of 1000ms is used.
760
760
  :param dict [params]: extra parameters specific to the exchange API endpoint
ccxt/pro/poloniex.py CHANGED
@@ -190,7 +190,7 @@ class poloniex(ccxt.async_support.poloniex):
190
190
  :param str type: 'market' or 'limit'
191
191
  :param str side: 'buy' or 'sell'
192
192
  :param float amount: how much of currency you want to trade in units of base currency
193
- :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
193
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
194
194
  :param dict [params]: extra parameters specific to the poloniex api endpoint
195
195
  :param str [params.timeInForce]: GTC(default), IOC, FOK
196
196
  :param str [params.clientOrderId]: Maximum 64-character length.*
ccxt/pro/vertex.py CHANGED
@@ -256,7 +256,7 @@ class vertex(ccxt.async_support.vertex):
256
256
  price = self.convertFromX18(self.safe_string(trade, 'price'))
257
257
  amount = self.convertFromX18(self.safe_string_2(trade, 'taker_qty', 'filled_qty'))
258
258
  cost = Precise.string_mul(price, amount)
259
- timestamp = Precise.string_div(self.safe_string(trade, 'timestamp'), '1000000')
259
+ timestamp = self.safe_integer_product(trade, 'timestamp', 0.000001)
260
260
  takerOrMaker = None
261
261
  isTaker = self.safe_bool(trade, 'is_taker')
262
262
  if isTaker is not None:
ccxt/probit.py CHANGED
@@ -1132,7 +1132,7 @@ class probit(Exchange, ImplicitAPI):
1132
1132
  :param str type: 'market' or 'limit'
1133
1133
  :param str side: 'buy' or 'sell'
1134
1134
  :param float amount: how much you want to trade in units of the base currency
1135
- :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1135
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
1136
1136
  :param dict [params]: extra parameters specific to the exchange API endpoint
1137
1137
  :param float [params.cost]: the quote quantity that can be used alternative for the amount for market buy orders
1138
1138
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
@@ -1,269 +1,10 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
- import argparse
4
- import json
5
- # import logging
6
- import os
7
- import sys
8
- from traceback import format_tb, format_exception
9
-
10
- import importlib # noqa: E402
11
- import re
12
-
13
- # ------------------------------------------------------------------------------
14
- # logging.basicConfig(level=logging.INFO)
15
- # ------------------------------------------------------------------------------
16
- DIR_NAME = os.path.dirname(os.path.abspath(__file__))
17
- root = os.path.dirname(os.path.dirname(DIR_NAME))
18
- sys.path.append(root)
19
-
20
- import ccxt.async_support as ccxt # noqa: E402
21
- import ccxt.pro as ccxtpro # noqa: E402
22
-
23
- # ------------------------------------------------------------------------------
24
3
  import asyncio
25
- # from typing import Optional
26
- # from typing import List
27
- from ccxt.base.errors import NotSupported
28
- from ccxt.base.errors import ProxyError
29
- from ccxt.base.errors import OperationFailed
30
- # from ccxt.base.errors import ExchangeError
31
- from ccxt.base.errors import ExchangeNotAvailable
32
- from ccxt.base.errors import OnMaintenance
33
- from ccxt.base.errors import AuthenticationError
34
-
35
- # ------------------------------------------------------------------------------
36
-
37
- class Argv(object):
38
- id_tests = False
39
- static_tests = False
40
- ws_tests = False
41
- request_tests = False
42
- response_tests = False
43
- token_bucket = False
44
- sandbox = False
45
- privateOnly = False
46
- private = False
47
- ws = False
48
- verbose = False
49
- nonce = None
50
- exchange = None
51
- symbol = None
52
- info = False
53
- pass
54
-
55
-
56
- argv = Argv()
57
- parser = argparse.ArgumentParser()
58
- parser.add_argument('--token_bucket', action='store_true', help='enable token bucket experimental test')
59
- parser.add_argument('--sandbox', action='store_true', help='enable sandbox mode')
60
- parser.add_argument('--privateOnly', action='store_true', help='run private tests only')
61
- parser.add_argument('--private', action='store_true', help='run private tests')
62
- parser.add_argument('--verbose', action='store_true', help='enable verbose output')
63
- parser.add_argument('--ws', action='store_true', help='websockets version')
64
- parser.add_argument('--info', action='store_true', help='enable info output')
65
- parser.add_argument('--static', action='store_true', help='run static tests')
66
- parser.add_argument('--useProxy', action='store_true', help='run static tests')
67
- parser.add_argument('--idTests', action='store_true', help='run brokerId tests')
68
- parser.add_argument('--responseTests', action='store_true', help='run response tests')
69
- parser.add_argument('--requestTests', action='store_true', help='run response tests')
70
- parser.add_argument('--nonce', type=int, help='integer')
71
- parser.add_argument('exchange', type=str, help='exchange id in lowercase', nargs='?')
72
- parser.add_argument('symbol', type=str, help='symbol in uppercase', nargs='?')
73
- parser.parse_args(namespace=argv)
74
-
75
- # ------------------------------------------------------------------------------
76
-
77
- path = os.path.dirname(ccxt.__file__)
78
- if 'site-packages' in os.path.dirname(ccxt.__file__):
79
- raise Exception("You are running test_async.py/test.py against a globally-installed version of the library! It was previously installed into your site-packages folder by pip or pip3. To ensure testing against the local folder uninstall it first with pip uninstall ccxt or pip3 uninstall ccxt")
80
-
81
- # ------------------------------------------------------------------------------
82
-
83
- Error = Exception
84
-
85
- # # print an error string
86
- # def dump_error(*args):
87
- # string = ' '.join([str(arg) for arg in args])
88
- # print(string)
89
- # sys.stderr.write(string + "\n")
90
- # sys.stderr.flush()
91
-
92
-
93
- def handle_all_unhandled_exceptions(type, value, traceback):
94
- dump((type), (value), '\n<UNHANDLED EXCEPTION>\n' + ('\n'.join(format_tb(traceback))))
95
- exit(1) # unrecoverable crash
96
-
97
-
98
- sys.excepthook = handle_all_unhandled_exceptions
99
- # ------------------------------------------------------------------------------
100
-
101
- # non-transpiled part, but shared names among langs
102
-
103
- is_synchronous = 'async' not in os.path.basename(__file__)
104
-
105
- rootDir = DIR_NAME + '/../../../'
106
- rootDirForSkips = DIR_NAME + '/../../../'
107
- envVars = os.environ
108
- LOG_CHARS_LENGTH = 10000
109
- ext = 'py'
110
- proxyTestFileName = 'proxies'
111
-
112
-
113
- def get_cli_arg_value(arg):
114
- arg_exists = getattr(argv, arg) if hasattr(argv, arg) else False
115
- with_hyphen = '--' + arg
116
- arg_exists_with_hyphen = getattr(argv, with_hyphen) if hasattr(argv, with_hyphen) else False
117
- without_hyphen = arg.replace('--', '')
118
- arg_exists_wo_hyphen = getattr(argv, without_hyphen) if hasattr(argv, without_hyphen) else False
119
- return arg_exists or arg_exists_with_hyphen or arg_exists_wo_hyphen
120
-
121
- isWsTests = get_cli_arg_value('--ws')
122
-
123
-
124
- class baseMainTestClass():
125
- lang = 'PY'
126
- is_synchronous = is_synchronous
127
- request_tests_failed = False
128
- response_tests_failed = False
129
- response_tests = False
130
- ws_tests = False
131
- load_keys = False
132
- skipped_settings_for_exchange = {}
133
- skipped_methods = {}
134
- check_public_tests = {}
135
- test_files = {}
136
- public_tests = {}
137
- new_line = '\n'
138
- root_dir = rootDir
139
- env_vars = envVars
140
- ext = ext
141
- root_dir_for_skips = rootDirForSkips
142
- only_specific_tests = []
143
- proxy_test_file_name = proxyTestFileName
144
- pass
145
4
 
146
5
 
147
- def dump(*args):
148
- print(' '.join([str(arg) for arg in args]))
6
+ from tests_helpers import get_cli_arg_value, dump, exit_script, get_test_files, init_exchange, set_exchange_prop, call_method, exception_message, io_file_exists, io_file_read, baseMainTestClass, AuthenticationError, NotSupported, OperationFailed, OnMaintenance, ExchangeNotAvailable, ProxyError, get_exchange_prop, close, json_parse, json_stringify, is_null_value, io_dir_read, convert_ascii, call_exchange_method_dynamically, set_fetch_response, call_exchange_method_dynamically_sync # noqa: F401
149
7
 
150
-
151
- def convert_ascii(str):
152
- return str # stub
153
-
154
- def json_parse(elem):
155
- return json.loads(elem)
156
-
157
-
158
- def json_stringify(elem):
159
- return json.dumps(elem)
160
-
161
-
162
- def convert_to_snake_case(content):
163
- res = re.sub(r'(?<!^)(?=[A-Z])', '_', content).lower()
164
- return res.replace('o_h_l_c_v', 'ohlcv')
165
-
166
-
167
- def get_test_name(methodName):
168
- # stub
169
- return methodName
170
-
171
-
172
- def io_file_exists(path):
173
- return os.path.isfile(path)
174
-
175
-
176
- def io_file_read(path, decode=True):
177
- fs = open(path, "r", encoding="utf-8")
178
- content = fs.read()
179
- if decode:
180
- return json.loads(content)
181
- else:
182
- return content
183
-
184
-
185
- def io_dir_read(path):
186
- return os.listdir(path)
187
-
188
-
189
- async def call_method(test_files, methodName, exchange, skippedProperties, args):
190
- methodNameToCall = 'test_' + convert_to_snake_case(methodName)
191
- return await getattr(test_files[methodName], methodNameToCall)(exchange, skippedProperties, *args)
192
-
193
-
194
- async def call_exchange_method_dynamically(exchange, methodName, args):
195
- return await getattr(exchange, methodName)(*args)
196
-
197
- async def call_overriden_method(exchange, methodName, args):
198
- # needed for php
199
- return await call_exchange_method_dynamically(exchange, methodName, args)
200
-
201
- def exception_message(exc):
202
- message = '[' + type(exc).__name__ + '] ' + "".join(format_exception(type(exc), exc, exc.__traceback__, limit=6))
203
- if len(message) > LOG_CHARS_LENGTH:
204
- # Accessing out of range element causes error
205
- message = message[0:LOG_CHARS_LENGTH]
206
- return message
207
-
208
-
209
- def exit_script(code=0):
210
- exit(code)
211
-
212
-
213
- def get_exchange_prop(exchange, prop, defaultValue=None):
214
- if hasattr(exchange, prop):
215
- res = getattr(exchange, prop)
216
- if res is not None and res != '':
217
- return res
218
- return defaultValue
219
-
220
-
221
- def set_exchange_prop(exchange, prop, value):
222
- setattr(exchange, prop, value)
223
- # set snake case too
224
- setattr(exchange, convert_to_snake_case(prop), value)
225
-
226
-
227
- def init_exchange(exchangeId, args, is_ws=False):
228
- if (is_ws):
229
- return getattr(ccxtpro, exchangeId)(args)
230
- return getattr(ccxt, exchangeId)(args)
231
-
232
-
233
- async def get_test_files(properties, ws=False):
234
- tests = {}
235
- finalPropList = properties + [proxyTestFileName]
236
- for i in range(0, len(finalPropList)):
237
- methodName = finalPropList[i]
238
- name_snake_case = convert_to_snake_case(methodName)
239
- prefix = 'async' if not is_synchronous else 'sync'
240
- dir_to_test = DIR_NAME + '/' + prefix + '/'
241
- module_string = 'ccxt.test.' + prefix + '.test_' + name_snake_case
242
- if (ws):
243
- prefix = 'pro'
244
- dir_to_test = DIR_NAME + '/../' + prefix + '/test/Exchange/'
245
- module_string = 'ccxt.pro.test.Exchange.test_' + name_snake_case
246
- filePathWithExt = dir_to_test + 'test_' + name_snake_case + '.py'
247
- if (io_file_exists (filePathWithExt)):
248
- imp = importlib.import_module(module_string)
249
- tests[methodName] = imp # getattr(imp, finalName)
250
- return tests
251
-
252
- async def close(exchange):
253
- if (not is_synchronous and hasattr(exchange, 'close')):
254
- await exchange.close()
255
-
256
- def is_null_value(value):
257
- return value is None
258
-
259
- def set_fetch_response(exchange: ccxt.Exchange, data):
260
- async def fetch(url, method='GET', headers=None, body=None):
261
- return data
262
- exchange.fetch = fetch
263
- return exchange
264
-
265
- # *********************************
266
- # ***** AUTO-TRANSPILER-START *****
267
8
  class testMainClass(baseMainTestClass):
268
9
  def parse_cli_args(self):
269
10
  self.response_tests = get_cli_arg_value('--responseTests')
@@ -452,7 +193,9 @@ class testMainClass(baseMainTestClass):
452
193
  args_stringified = '(' + exchange.json(args) + ')' # args.join() breaks when we provide a list of symbols or multidimensional array; "args.toString()" breaks bcz of "array to string conversion"
453
194
  dump(self.add_padding('[INFO] TESTING', 25), self.exchange_hint(exchange), method_name, args_stringified)
454
195
  await call_method(self.test_files, method_name, exchange, skipped_properties_for_method, args)
455
- # if it was passed successfully, add to the list of successfull tests
196
+ if self.info:
197
+ dump(self.add_padding('[INFO] TESTING DONE', 25), self.exchange_hint(exchange), method_name)
198
+ # add to the list of successed tests
456
199
  if is_public:
457
200
  self.checked_public_tests[method_name] = True
458
201
  return
@@ -507,7 +250,7 @@ class testMainClass(baseMainTestClass):
507
250
  # formatted message "[TEST_FAILURE] ..." and that output is then regex-matched by
508
251
  # run-tests.js, so the exceptions are still printed out to console from there.
509
252
  max_retries = 3
510
- args_stringified = exchange.json(args) # args.join() breaks when we provide a list of symbols | "args.toString()" breaks bcz of "array to string conversion"
253
+ args_stringified = exchange.json(args) # args.join() breaks when we provide a list of symbols or multidimensional array; "args.toString()" breaks bcz of "array to string conversion"
511
254
  for i in range(0, max_retries):
512
255
  try:
513
256
  await self.test_method(method_name, exchange, args, is_public)
@@ -836,12 +579,16 @@ class testMainClass(baseMainTestClass):
836
579
  for j in range(0, max_retries):
837
580
  try:
838
581
  await self.test_method(proxy_test_name, exchange, [], True)
839
- break # if successfull, then break
582
+ return # if successfull, then end the test
840
583
  except Exception as e:
841
584
  exception = e
585
+ await exchange.sleep(j * 1000)
842
586
  # if exception was set, then throw it
843
- if exception:
587
+ if exception is not None:
844
588
  error_message = '[TEST_FAILURE] Failed ' + proxy_test_name + ' : ' + exception_message(exception)
589
+ # temporary comment the below, because c# transpilation failure
590
+ # throw new ExchangeError (errorMessage.toString ());
591
+ dump('[TEST_WARNING]' + str(error_message))
845
592
 
846
593
  async def start_test(self, exchange, symbol):
847
594
  # we do not need to test aliases
@@ -1075,7 +822,10 @@ class testMainClass(baseMainTestClass):
1075
822
  output = None
1076
823
  request_url = None
1077
824
  try:
1078
- await call_exchange_method_dynamically(exchange, method, self.sanitize_data_input(data['input']))
825
+ if not self.is_synchronous:
826
+ await call_exchange_method_dynamically(exchange, method, self.sanitize_data_input(data['input']))
827
+ else:
828
+ call_exchange_method_dynamically_sync(exchange, method, self.sanitize_data_input(data['input']))
1079
829
  except Exception as e:
1080
830
  if not (isinstance(e, ProxyError)):
1081
831
  raise e
@@ -1093,8 +843,12 @@ class testMainClass(baseMainTestClass):
1093
843
  expected_result = exchange.safe_value(data, 'parsedResponse')
1094
844
  mocked_exchange = set_fetch_response(exchange, data['httpResponse'])
1095
845
  try:
1096
- unified_result = await call_exchange_method_dynamically(exchange, method, self.sanitize_data_input(data['input']))
1097
- self.assert_static_response_output(mocked_exchange, skip_keys, unified_result, expected_result)
846
+ if not self.is_synchronous:
847
+ unified_result = await call_exchange_method_dynamically(exchange, method, self.sanitize_data_input(data['input']))
848
+ self.assert_static_response_output(mocked_exchange, skip_keys, unified_result, expected_result)
849
+ else:
850
+ unified_result_sync = call_exchange_method_dynamically_sync(exchange, method, self.sanitize_data_input(data['input']))
851
+ self.assert_static_response_output(mocked_exchange, skip_keys, unified_result_sync, expected_result)
1098
852
  except Exception as e:
1099
853
  self.request_tests_failed = True
1100
854
  error_message = '[' + self.lang + '][STATIC_RESPONSE_TEST_FAILURE]' + '[' + self.exchange_hint(exchange) + ']' + '[' + method + ']' + '[' + data['description'] + ']' + str(e)
@@ -1179,7 +933,8 @@ class testMainClass(baseMainTestClass):
1179
933
  # reset options
1180
934
  # exchange.options = exchange.deepExtend (oldExchangeOptions, {});
1181
935
  exchange.extend_exchange_options(exchange.deep_extend(old_exchange_options, {}))
1182
- await close(exchange)
936
+ if not self.is_synchronous:
937
+ await close(exchange)
1183
938
  return True # in c# methods that will be used with promiseAll need to return something
1184
939
 
1185
940
  async def test_exchange_response_statically(self, exchange_name, exchange_data, test_name=None):
@@ -1228,7 +983,8 @@ class testMainClass(baseMainTestClass):
1228
983
  # reset options
1229
984
  # exchange.options = exchange.deepExtend (oldExchangeOptions, {});
1230
985
  exchange.extend_exchange_options(exchange.deep_extend(old_exchange_options, {}))
1231
- await close(exchange)
986
+ if not self.is_synchronous:
987
+ await close(exchange)
1232
988
  return True # in c# methods that will be used with promiseAll need to return something
1233
989
 
1234
990
  def get_number_of_tests_from_exchange(self, exchange, exchange_data, test_name=None):
@@ -1273,7 +1029,8 @@ class testMainClass(baseMainTestClass):
1273
1029
  if self.request_tests_failed or self.response_tests_failed:
1274
1030
  exit_script(1)
1275
1031
  else:
1276
- success_message = '[' + self.lang + '][TEST_SUCCESS] ' + str(sum) + ' static ' + type + ' tests passed.'
1032
+ prefix = '[SYNC]' if (self.is_synchronous) else ''
1033
+ success_message = '[' + self.lang + ']' + prefix + '[TEST_SUCCESS] ' + str(sum) + ' static ' + type + ' tests passed.'
1277
1034
  dump('[INFO]' + success_message)
1278
1035
 
1279
1036
  async def run_static_response_tests(self, exchange_name=None, test=None):
@@ -1671,13 +1428,3 @@ class testMainClass(baseMainTestClass):
1671
1428
  assert broker_id == id, 'vertex - id: ' + str(id) + ' different from broker_id: ' + str(broker_id)
1672
1429
  await close(exchange)
1673
1430
  return True
1674
-
1675
- # ***** AUTO-TRANSPILER-END *****
1676
- # *******************************
1677
-
1678
-
1679
- if __name__ == '__main__':
1680
- argvSymbol = argv.symbol if argv.symbol and '/' in argv.symbol else None
1681
- # in python, we check it through "symbol" arg (as opposed to JS/PHP) because argvs were already built above
1682
- argvMethod = argv.symbol if argv.symbol and '()' in argv.symbol else None
1683
- asyncio.run(testMainClass().init(argv.exchange, argvSymbol, argvMethod))