ccxt-ir 4.3.46.0.2__py2.py3-none-any.whl → 4.5.0__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 (528) hide show
  1. ccxt/__init__.py +39 -35
  2. ccxt/abantether.py +9 -9
  3. ccxt/abstract/alpaca.py +4 -0
  4. ccxt/abstract/apex.py +31 -0
  5. ccxt/abstract/bigone.py +1 -1
  6. ccxt/abstract/binance.py +106 -48
  7. ccxt/abstract/binancecoinm.py +106 -48
  8. ccxt/abstract/binanceus.py +141 -83
  9. ccxt/abstract/binanceusdm.py +106 -48
  10. ccxt/abstract/bingx.py +50 -1
  11. ccxt/abstract/bitbank.py +5 -0
  12. ccxt/abstract/bitfinex.py +136 -65
  13. ccxt/abstract/bitflyer.py +1 -0
  14. ccxt/abstract/bitget.py +67 -0
  15. ccxt/abstract/bitmart.py +19 -1
  16. ccxt/abstract/bitopro.py +1 -0
  17. ccxt/abstract/bitrue.py +68 -68
  18. ccxt/abstract/bitstamp.py +1 -0
  19. ccxt/abstract/blofin.py +30 -0
  20. ccxt/abstract/btcbox.py +2 -0
  21. ccxt/abstract/bybit.py +28 -13
  22. ccxt/abstract/cex.py +28 -29
  23. ccxt/abstract/coinbaseexchange.py +1 -0
  24. ccxt/abstract/coinbaseinternational.py +1 -1
  25. ccxt/abstract/cryptocom.py +16 -0
  26. ccxt/abstract/cryptomus.py +20 -0
  27. ccxt/abstract/defx.py +69 -0
  28. ccxt/abstract/deribit.py +1 -0
  29. ccxt/abstract/derive.py +117 -0
  30. ccxt/abstract/digifinex.py +1 -0
  31. ccxt/abstract/ellipx.py +25 -0
  32. ccxt/abstract/foxbit.py +26 -0
  33. ccxt/abstract/gate.py +19 -0
  34. ccxt/abstract/gateio.py +19 -0
  35. ccxt/abstract/gemini.py +1 -0
  36. ccxt/abstract/hibachi.py +26 -0
  37. ccxt/abstract/hyperliquid.py +1 -1
  38. ccxt/abstract/independentreserve.py +6 -0
  39. ccxt/abstract/kraken.py +1 -0
  40. ccxt/abstract/krakenfutures.py +4 -0
  41. ccxt/abstract/kucoin.py +10 -0
  42. ccxt/abstract/kucoinfutures.py +18 -0
  43. ccxt/abstract/lbank.py +2 -1
  44. ccxt/abstract/luno.py +1 -0
  45. ccxt/abstract/mexc.py +2 -0
  46. ccxt/abstract/modetrade.py +119 -0
  47. ccxt/abstract/myokx.py +349 -0
  48. ccxt/abstract/oceanex.py +5 -0
  49. ccxt/abstract/okx.py +25 -0
  50. ccxt/abstract/okxus.py +349 -0
  51. ccxt/abstract/onetrading.py +0 -12
  52. ccxt/abstract/paradex.py +23 -0
  53. ccxt/abstract/phemex.py +2 -0
  54. ccxt/abstract/poloniex.py +36 -0
  55. ccxt/abstract/tradeogre.py +3 -1
  56. ccxt/abstract/upbit.py +51 -34
  57. ccxt/abstract/whitebit.py +16 -0
  58. ccxt/abstract/woo.py +64 -6
  59. ccxt/abstract/xt.py +10 -5
  60. ccxt/afratether.py +7 -7
  61. ccxt/alpaca.py +828 -51
  62. ccxt/apex.py +1875 -0
  63. ccxt/arzinja.py +7 -7
  64. ccxt/arzplus.py +9 -9
  65. ccxt/ascendex.py +501 -306
  66. ccxt/async_support/__init__.py +39 -35
  67. ccxt/async_support/abantether.py +10 -10
  68. ccxt/async_support/afratether.py +9 -9
  69. ccxt/async_support/alpaca.py +828 -51
  70. ccxt/async_support/apex.py +1875 -0
  71. ccxt/async_support/arzinja.py +10 -10
  72. ccxt/async_support/arzplus.py +12 -12
  73. ccxt/async_support/ascendex.py +502 -306
  74. ccxt/async_support/base/exchange.py +303 -89
  75. ccxt/async_support/base/ws/cache.py +9 -3
  76. ccxt/async_support/base/ws/client.py +173 -38
  77. ccxt/async_support/base/ws/future.py +25 -37
  78. ccxt/async_support/bequant.py +5 -3
  79. ccxt/async_support/bigone.py +279 -144
  80. ccxt/async_support/binance.py +2347 -1158
  81. ccxt/async_support/binancecoinm.py +9 -3
  82. ccxt/async_support/binanceus.py +17 -3
  83. ccxt/async_support/binanceusdm.py +9 -4
  84. ccxt/async_support/bingx.py +2962 -920
  85. ccxt/async_support/bit2c.py +147 -27
  86. ccxt/async_support/bitbank.py +151 -23
  87. ccxt/async_support/bitbns.py +104 -30
  88. ccxt/async_support/bitfinex.py +3291 -1113
  89. ccxt/async_support/bitflyer.py +202 -27
  90. ccxt/async_support/bitget.py +3683 -1538
  91. ccxt/async_support/bithumb.py +195 -38
  92. ccxt/async_support/bitimen.py +12 -12
  93. ccxt/async_support/bitir.py +38 -38
  94. ccxt/async_support/bitmart.py +1288 -350
  95. ccxt/async_support/bitmex.py +260 -75
  96. ccxt/async_support/bitopro.py +262 -62
  97. ccxt/async_support/bitpin.py +17 -16
  98. ccxt/async_support/bitrue.py +459 -290
  99. ccxt/async_support/bitso.py +199 -54
  100. ccxt/async_support/bitstamp.py +230 -96
  101. ccxt/async_support/bitteam.py +167 -25
  102. ccxt/async_support/{huobijp.py → bittrade.py} +158 -30
  103. ccxt/async_support/bitvavo.py +213 -49
  104. ccxt/async_support/blockchaincom.py +160 -46
  105. ccxt/async_support/blofin.py +502 -120
  106. ccxt/async_support/btcalpha.py +169 -31
  107. ccxt/async_support/btcbox.py +292 -23
  108. ccxt/async_support/btcmarkets.py +211 -58
  109. ccxt/async_support/btcturk.py +161 -38
  110. ccxt/async_support/bybit.py +1775 -1030
  111. ccxt/async_support/cex.py +1440 -1303
  112. ccxt/async_support/coinbase.py +724 -212
  113. ccxt/async_support/coinbaseadvanced.py +2 -1
  114. ccxt/async_support/coinbaseexchange.py +388 -89
  115. ccxt/async_support/coinbaseinternational.py +412 -57
  116. ccxt/async_support/coincatch.py +177 -78
  117. ccxt/async_support/coincheck.py +135 -19
  118. ccxt/async_support/coinex.py +606 -232
  119. ccxt/async_support/coinmate.py +189 -63
  120. ccxt/async_support/coinmetro.py +195 -54
  121. ccxt/async_support/coinone.py +158 -51
  122. ccxt/async_support/coinsph.py +336 -61
  123. ccxt/async_support/coinspot.py +151 -52
  124. ccxt/async_support/cryptocom.py +661 -111
  125. ccxt/async_support/cryptomus.py +1137 -0
  126. ccxt/async_support/defx.py +2071 -0
  127. ccxt/async_support/delta.py +299 -99
  128. ccxt/async_support/deribit.py +348 -126
  129. ccxt/async_support/derive.py +2572 -0
  130. ccxt/async_support/digifinex.py +430 -214
  131. ccxt/async_support/ellipx.py +2029 -0
  132. ccxt/async_support/eterex.py +10 -10
  133. ccxt/async_support/excoino.py +31 -31
  134. ccxt/async_support/exir.py +14 -14
  135. ccxt/async_support/exmo.py +344 -131
  136. ccxt/async_support/exnovin.py +10 -10
  137. ccxt/async_support/farhadexchange.py +12 -12
  138. ccxt/async_support/fmfwio.py +2 -1
  139. ccxt/async_support/foxbit.py +1935 -0
  140. ccxt/async_support/gate.py +1351 -529
  141. ccxt/async_support/gateio.py +2 -1
  142. ccxt/async_support/gemini.py +144 -39
  143. ccxt/async_support/hashkey.py +152 -109
  144. ccxt/async_support/hibachi.py +2080 -0
  145. ccxt/async_support/hitbtc.py +395 -167
  146. ccxt/async_support/hitobit.py +12 -12
  147. ccxt/async_support/hollaex.py +307 -119
  148. ccxt/async_support/htx.py +851 -383
  149. ccxt/async_support/huobi.py +2 -1
  150. ccxt/async_support/hyperliquid.py +1848 -536
  151. ccxt/async_support/independentreserve.py +288 -15
  152. ccxt/async_support/indodax.py +190 -33
  153. ccxt/async_support/jibitex.py +12 -12
  154. ccxt/async_support/kraken.py +795 -351
  155. ccxt/async_support/krakenfutures.py +214 -62
  156. ccxt/async_support/kucoin.py +715 -396
  157. ccxt/async_support/kucoinfutures.py +652 -89
  158. ccxt/async_support/latoken.py +217 -113
  159. ccxt/async_support/lbank.py +425 -97
  160. ccxt/async_support/luno.py +382 -35
  161. ccxt/async_support/mercado.py +113 -6
  162. ccxt/async_support/mexc.py +874 -437
  163. ccxt/async_support/modetrade.py +2818 -0
  164. ccxt/async_support/myokx.py +54 -0
  165. ccxt/async_support/ndax.py +221 -64
  166. ccxt/async_support/nobitex.py +31 -37
  167. ccxt/async_support/novadax.py +190 -34
  168. ccxt/async_support/oceanex.py +217 -28
  169. ccxt/async_support/okcoin.py +253 -145
  170. ccxt/async_support/okexchange.py +11 -11
  171. ccxt/async_support/okx.py +1088 -351
  172. ccxt/async_support/okxus.py +54 -0
  173. ccxt/async_support/ompfinex.py +25 -24
  174. ccxt/async_support/onetrading.py +213 -392
  175. ccxt/async_support/oxfun.py +245 -166
  176. ccxt/async_support/p2b.py +151 -29
  177. ccxt/async_support/paradex.py +562 -49
  178. ccxt/async_support/paymium.py +82 -19
  179. ccxt/async_support/phemex.py +713 -172
  180. ccxt/async_support/poloniex.py +1602 -283
  181. ccxt/async_support/probit.py +224 -95
  182. ccxt/async_support/ramzinex.py +30 -27
  183. ccxt/async_support/sarmayex.py +9 -9
  184. ccxt/async_support/sarrafex.py +13 -13
  185. ccxt/async_support/tabdeal.py +14 -13
  186. ccxt/async_support/tetherland.py +9 -9
  187. ccxt/async_support/timex.py +210 -51
  188. ccxt/async_support/tokocrypto.py +167 -47
  189. ccxt/async_support/tradeogre.py +266 -31
  190. ccxt/async_support/twox.py +9 -9
  191. ccxt/async_support/ubitex.py +12 -12
  192. ccxt/async_support/upbit.py +568 -165
  193. ccxt/async_support/vertex.py +160 -32
  194. ccxt/async_support/wallex.py +12 -12
  195. ccxt/async_support/wavesexchange.py +165 -30
  196. ccxt/async_support/whitebit.py +975 -127
  197. ccxt/async_support/woo.py +1918 -1016
  198. ccxt/async_support/woofipro.py +433 -141
  199. ccxt/async_support/xt.py +649 -193
  200. ccxt/async_support/yobit.py +195 -70
  201. ccxt/async_support/zaif.py +91 -15
  202. ccxt/async_support/zonda.py +151 -36
  203. ccxt/base/decimal_to_precision.py +14 -10
  204. ccxt/base/errors.py +49 -18
  205. ccxt/base/exchange.py +1556 -450
  206. ccxt/base/precise.py +10 -0
  207. ccxt/base/types.py +114 -6
  208. ccxt/bequant.py +5 -3
  209. ccxt/bigone.py +279 -144
  210. ccxt/binance.py +2347 -1158
  211. ccxt/binancecoinm.py +9 -3
  212. ccxt/binanceus.py +17 -3
  213. ccxt/binanceusdm.py +9 -4
  214. ccxt/bingx.py +2962 -920
  215. ccxt/bit2c.py +147 -27
  216. ccxt/bitbank.py +151 -23
  217. ccxt/bitbns.py +104 -30
  218. ccxt/bitfinex.py +3290 -1113
  219. ccxt/bitflyer.py +202 -27
  220. ccxt/bitget.py +3683 -1538
  221. ccxt/bithumb.py +194 -38
  222. ccxt/bitimen.py +9 -9
  223. ccxt/bitir.py +35 -35
  224. ccxt/bitmart.py +1288 -350
  225. ccxt/bitmex.py +260 -75
  226. ccxt/bitopro.py +262 -62
  227. ccxt/bitpin.py +15 -14
  228. ccxt/bitrue.py +459 -290
  229. ccxt/bitso.py +199 -54
  230. ccxt/bitstamp.py +230 -96
  231. ccxt/bitteam.py +167 -25
  232. ccxt/{huobijp.py → bittrade.py} +158 -30
  233. ccxt/bitvavo.py +213 -49
  234. ccxt/blockchaincom.py +160 -46
  235. ccxt/blofin.py +502 -120
  236. ccxt/btcalpha.py +169 -31
  237. ccxt/btcbox.py +291 -23
  238. ccxt/btcmarkets.py +211 -58
  239. ccxt/btcturk.py +161 -38
  240. ccxt/bybit.py +1775 -1030
  241. ccxt/cex.py +1439 -1303
  242. ccxt/coinbase.py +724 -212
  243. ccxt/coinbaseadvanced.py +2 -1
  244. ccxt/coinbaseexchange.py +388 -89
  245. ccxt/coinbaseinternational.py +412 -57
  246. ccxt/coincatch.py +177 -78
  247. ccxt/coincheck.py +135 -19
  248. ccxt/coinex.py +606 -232
  249. ccxt/coinmate.py +189 -63
  250. ccxt/coinmetro.py +194 -54
  251. ccxt/coinone.py +158 -51
  252. ccxt/coinsph.py +336 -61
  253. ccxt/coinspot.py +151 -52
  254. ccxt/cryptocom.py +661 -111
  255. ccxt/cryptomus.py +1137 -0
  256. ccxt/defx.py +2070 -0
  257. ccxt/delta.py +299 -99
  258. ccxt/deribit.py +348 -126
  259. ccxt/derive.py +2571 -0
  260. ccxt/digifinex.py +430 -214
  261. ccxt/ellipx.py +2029 -0
  262. ccxt/eterex.py +7 -7
  263. ccxt/excoino.py +29 -29
  264. ccxt/exir.py +11 -11
  265. ccxt/exmo.py +343 -131
  266. ccxt/exnovin.py +8 -8
  267. ccxt/farhadexchange.py +10 -10
  268. ccxt/fmfwio.py +2 -1
  269. ccxt/foxbit.py +1935 -0
  270. ccxt/gate.py +1351 -529
  271. ccxt/gateio.py +2 -1
  272. ccxt/gemini.py +144 -39
  273. ccxt/hashkey.py +152 -109
  274. ccxt/hibachi.py +2079 -0
  275. ccxt/hitbtc.py +395 -167
  276. ccxt/hitobit.py +9 -9
  277. ccxt/hollaex.py +307 -119
  278. ccxt/htx.py +851 -383
  279. ccxt/huobi.py +2 -1
  280. ccxt/hyperliquid.py +1848 -536
  281. ccxt/independentreserve.py +287 -15
  282. ccxt/indodax.py +190 -33
  283. ccxt/jibitex.py +9 -9
  284. ccxt/kraken.py +794 -351
  285. ccxt/krakenfutures.py +214 -62
  286. ccxt/kucoin.py +715 -396
  287. ccxt/kucoinfutures.py +652 -89
  288. ccxt/latoken.py +217 -113
  289. ccxt/lbank.py +425 -97
  290. ccxt/luno.py +382 -35
  291. ccxt/mercado.py +113 -6
  292. ccxt/mexc.py +873 -437
  293. ccxt/modetrade.py +2818 -0
  294. ccxt/myokx.py +54 -0
  295. ccxt/ndax.py +221 -64
  296. ccxt/nobitex.py +29 -35
  297. ccxt/novadax.py +190 -34
  298. ccxt/oceanex.py +217 -28
  299. ccxt/okcoin.py +253 -145
  300. ccxt/okexchange.py +9 -9
  301. ccxt/okx.py +1088 -351
  302. ccxt/okxus.py +54 -0
  303. ccxt/ompfinex.py +22 -21
  304. ccxt/onetrading.py +213 -392
  305. ccxt/oxfun.py +245 -166
  306. ccxt/p2b.py +151 -29
  307. ccxt/paradex.py +562 -49
  308. ccxt/paymium.py +82 -19
  309. ccxt/phemex.py +712 -172
  310. ccxt/poloniex.py +1601 -283
  311. ccxt/pro/__init__.py +76 -17
  312. ccxt/pro/alpaca.py +21 -6
  313. ccxt/pro/apex.py +984 -0
  314. ccxt/pro/ascendex.py +58 -10
  315. ccxt/pro/bequant.py +6 -1
  316. ccxt/pro/binance.py +728 -156
  317. ccxt/pro/binancecoinm.py +6 -2
  318. ccxt/pro/binanceus.py +8 -4
  319. ccxt/pro/binanceusdm.py +7 -2
  320. ccxt/pro/bingx.py +333 -142
  321. ccxt/pro/bitfinex.py +727 -262
  322. ccxt/pro/bitget.py +570 -79
  323. ccxt/pro/bithumb.py +20 -6
  324. ccxt/pro/bitmart.py +216 -87
  325. ccxt/pro/bitmex.py +47 -9
  326. ccxt/pro/bitopro.py +26 -14
  327. ccxt/pro/bitrue.py +22 -22
  328. ccxt/pro/bitstamp.py +54 -21
  329. ccxt/pro/{huobijp.py → bittrade.py} +7 -6
  330. ccxt/pro/bitvavo.py +191 -67
  331. ccxt/pro/blockchaincom.py +21 -8
  332. ccxt/pro/blofin.py +9 -1
  333. ccxt/pro/bybit.py +632 -245
  334. ccxt/pro/cex.py +59 -24
  335. ccxt/pro/coinbase.py +102 -73
  336. ccxt/pro/coinbaseadvanced.py +2 -1
  337. ccxt/pro/coinbaseexchange.py +8 -8
  338. ccxt/pro/coinbaseinternational.py +181 -25
  339. ccxt/pro/coincatch.py +6 -7
  340. ccxt/pro/coincheck.py +11 -6
  341. ccxt/pro/coinex.py +967 -665
  342. ccxt/pro/coinone.py +16 -9
  343. ccxt/pro/cryptocom.py +448 -45
  344. ccxt/pro/defx.py +831 -0
  345. ccxt/pro/deribit.py +150 -14
  346. ccxt/pro/derive.py +704 -0
  347. ccxt/pro/exmo.py +239 -6
  348. ccxt/pro/gate.py +623 -65
  349. ccxt/pro/gateio.py +2 -1
  350. ccxt/pro/gemini.py +27 -11
  351. ccxt/pro/hashkey.py +2 -2
  352. ccxt/pro/hitbtc.py +196 -91
  353. ccxt/pro/hollaex.py +23 -7
  354. ccxt/pro/htx.py +51 -14
  355. ccxt/pro/huobi.py +2 -1
  356. ccxt/pro/hyperliquid.py +591 -27
  357. ccxt/pro/independentreserve.py +9 -6
  358. ccxt/pro/kraken.py +640 -320
  359. ccxt/pro/krakenfutures.py +62 -35
  360. ccxt/pro/kucoin.py +267 -46
  361. ccxt/pro/kucoinfutures.py +165 -21
  362. ccxt/pro/lbank.py +102 -21
  363. ccxt/pro/luno.py +12 -8
  364. ccxt/pro/mexc.py +877 -111
  365. ccxt/pro/modetrade.py +1271 -0
  366. ccxt/pro/myokx.py +38 -0
  367. ccxt/pro/ndax.py +15 -2
  368. ccxt/pro/okcoin.py +23 -4
  369. ccxt/pro/okx.py +573 -98
  370. ccxt/pro/okxus.py +38 -0
  371. ccxt/pro/onetrading.py +30 -13
  372. ccxt/pro/oxfun.py +131 -27
  373. ccxt/pro/p2b.py +88 -22
  374. ccxt/pro/paradex.py +3 -3
  375. ccxt/pro/phemex.py +75 -21
  376. ccxt/pro/poloniex.py +124 -41
  377. ccxt/pro/probit.py +87 -80
  378. ccxt/pro/tradeogre.py +272 -0
  379. ccxt/pro/upbit.py +152 -12
  380. ccxt/pro/vertex.py +8 -3
  381. ccxt/pro/whitebit.py +58 -5
  382. ccxt/pro/woo.py +228 -37
  383. ccxt/pro/woofipro.py +106 -18
  384. ccxt/pro/xt.py +111 -5
  385. ccxt/probit.py +224 -95
  386. ccxt/protobuf/__init__.py +0 -0
  387. ccxt/protobuf/mexc/PrivateAccountV3Api_pb2.py +37 -0
  388. ccxt/protobuf/mexc/PrivateDealsV3Api_pb2.py +37 -0
  389. ccxt/protobuf/mexc/PrivateOrdersV3Api_pb2.py +37 -0
  390. ccxt/protobuf/mexc/PublicAggreBookTickerV3Api_pb2.py +37 -0
  391. ccxt/protobuf/mexc/PublicAggreDealsV3Api_pb2.py +39 -0
  392. ccxt/protobuf/mexc/PublicAggreDepthsV3Api_pb2.py +39 -0
  393. ccxt/protobuf/mexc/PublicBookTickerBatchV3Api_pb2.py +38 -0
  394. ccxt/protobuf/mexc/PublicBookTickerV3Api_pb2.py +37 -0
  395. ccxt/protobuf/mexc/PublicDealsV3Api_pb2.py +39 -0
  396. ccxt/protobuf/mexc/PublicIncreaseDepthsBatchV3Api_pb2.py +38 -0
  397. ccxt/protobuf/mexc/PublicIncreaseDepthsV3Api_pb2.py +39 -0
  398. ccxt/protobuf/mexc/PublicLimitDepthsV3Api_pb2.py +39 -0
  399. ccxt/protobuf/mexc/PublicMiniTickerV3Api_pb2.py +37 -0
  400. ccxt/protobuf/mexc/PublicMiniTickersV3Api_pb2.py +38 -0
  401. ccxt/protobuf/mexc/PublicSpotKlineV3Api_pb2.py +37 -0
  402. ccxt/protobuf/mexc/PushDataV3ApiWrapper_pb2.py +52 -0
  403. ccxt/protobuf/mexc/__init__.py +0 -0
  404. ccxt/ramzinex.py +28 -25
  405. ccxt/sarmayex.py +7 -7
  406. ccxt/sarrafex.py +10 -10
  407. ccxt/static_dependencies/__init__.py +1 -1
  408. ccxt/static_dependencies/lark/py.typed +0 -0
  409. ccxt/static_dependencies/marshmallow/py.typed +0 -0
  410. ccxt/static_dependencies/marshmallow_dataclass/py.typed +0 -0
  411. ccxt/static_dependencies/marshmallow_oneofschema/py.typed +0 -0
  412. ccxt/tabdeal.py +12 -11
  413. ccxt/test/tests_async.py +261 -57
  414. ccxt/test/tests_helpers.py +1 -3
  415. ccxt/test/tests_init.py +4 -3
  416. ccxt/test/tests_sync.py +261 -57
  417. ccxt/tetherland.py +7 -7
  418. ccxt/timex.py +210 -51
  419. ccxt/tokocrypto.py +167 -47
  420. ccxt/tradeogre.py +266 -31
  421. ccxt/twox.py +7 -7
  422. ccxt/ubitex.py +9 -9
  423. ccxt/upbit.py +568 -165
  424. ccxt/vertex.py +160 -32
  425. ccxt/wallex.py +9 -9
  426. ccxt/wavesexchange.py +165 -30
  427. ccxt/whitebit.py +975 -127
  428. ccxt/woo.py +1917 -1016
  429. ccxt/woofipro.py +432 -141
  430. ccxt/xt.py +649 -193
  431. ccxt/yobit.py +194 -70
  432. ccxt/zaif.py +91 -15
  433. ccxt/zonda.py +151 -36
  434. {ccxt_ir-4.3.46.0.2.dist-info → ccxt_ir-4.5.0.dist-info}/METADATA +225 -73
  435. ccxt_ir-4.5.0.dist-info/RECORD +743 -0
  436. {ccxt_ir-4.3.46.0.2.dist-info → ccxt_ir-4.5.0.dist-info}/WHEEL +1 -1
  437. ccxt/abstract/ace.py +0 -15
  438. ccxt/abstract/bitbay.py +0 -53
  439. ccxt/abstract/bitcoincom.py +0 -115
  440. ccxt/abstract/bitfinex2.py +0 -139
  441. ccxt/abstract/bitpanda.py +0 -35
  442. ccxt/abstract/bl3p.py +0 -19
  443. ccxt/abstract/coinlist.py +0 -54
  444. ccxt/abstract/currencycom.py +0 -68
  445. ccxt/abstract/hitbtc3.py +0 -115
  446. ccxt/abstract/idex.py +0 -26
  447. ccxt/abstract/kuna.py +0 -182
  448. ccxt/abstract/lykke.py +0 -29
  449. ccxt/abstract/poloniexfutures.py +0 -48
  450. ccxt/abstract/wazirx.py +0 -30
  451. ccxt/ace.py +0 -1012
  452. ccxt/async_support/ace.py +0 -1012
  453. ccxt/async_support/base/ws/aiohttp_client.py +0 -125
  454. ccxt/async_support/base/ws/fast_client.py +0 -96
  455. ccxt/async_support/bitbay.py +0 -17
  456. ccxt/async_support/bitcoincom.py +0 -17
  457. ccxt/async_support/bitfinex2.py +0 -3552
  458. ccxt/async_support/bitpanda.py +0 -16
  459. ccxt/async_support/bl3p.py +0 -485
  460. ccxt/async_support/coinlist.py +0 -2243
  461. ccxt/async_support/currencycom.py +0 -1950
  462. ccxt/async_support/hitbtc3.py +0 -16
  463. ccxt/async_support/idex.py +0 -1766
  464. ccxt/async_support/kuna.py +0 -1841
  465. ccxt/async_support/lykke.py +0 -1270
  466. ccxt/async_support/poloniexfutures.py +0 -1717
  467. ccxt/async_support/wazirx.py +0 -1224
  468. ccxt/bitbay.py +0 -17
  469. ccxt/bitcoincom.py +0 -17
  470. ccxt/bitfinex2.py +0 -3552
  471. ccxt/bitpanda.py +0 -16
  472. ccxt/bl3p.py +0 -485
  473. ccxt/coinlist.py +0 -2243
  474. ccxt/currencycom.py +0 -1950
  475. ccxt/hitbtc3.py +0 -16
  476. ccxt/idex.py +0 -1766
  477. ccxt/kuna.py +0 -1841
  478. ccxt/lykke.py +0 -1270
  479. ccxt/poloniexfutures.py +0 -1717
  480. ccxt/pro/bitcoincom.py +0 -34
  481. ccxt/pro/bitfinex2.py +0 -1083
  482. ccxt/pro/bitpanda.py +0 -15
  483. ccxt/pro/currencycom.py +0 -536
  484. ccxt/pro/idex.py +0 -672
  485. ccxt/pro/poloniexfutures.py +0 -990
  486. ccxt/pro/wazirx.py +0 -749
  487. ccxt/test/base/__init__.py +0 -29
  488. ccxt/test/base/test_account.py +0 -26
  489. ccxt/test/base/test_balance.py +0 -56
  490. ccxt/test/base/test_borrow_interest.py +0 -35
  491. ccxt/test/base/test_borrow_rate.py +0 -32
  492. ccxt/test/base/test_calculate_fee.py +0 -51
  493. ccxt/test/base/test_crypto.py +0 -127
  494. ccxt/test/base/test_currency.py +0 -76
  495. ccxt/test/base/test_datetime.py +0 -109
  496. ccxt/test/base/test_decimal_to_precision.py +0 -392
  497. ccxt/test/base/test_deep_extend.py +0 -68
  498. ccxt/test/base/test_deposit_withdrawal.py +0 -50
  499. ccxt/test/base/test_exchange_datetime_functions.py +0 -76
  500. ccxt/test/base/test_funding_rate_history.py +0 -29
  501. ccxt/test/base/test_last_price.py +0 -31
  502. ccxt/test/base/test_ledger_entry.py +0 -45
  503. ccxt/test/base/test_ledger_item.py +0 -48
  504. ccxt/test/base/test_leverage_tier.py +0 -33
  505. ccxt/test/base/test_liquidation.py +0 -50
  506. ccxt/test/base/test_margin_mode.py +0 -24
  507. ccxt/test/base/test_margin_modification.py +0 -35
  508. ccxt/test/base/test_market.py +0 -193
  509. ccxt/test/base/test_number.py +0 -411
  510. ccxt/test/base/test_ohlcv.py +0 -33
  511. ccxt/test/base/test_open_interest.py +0 -32
  512. ccxt/test/base/test_order.py +0 -64
  513. ccxt/test/base/test_order_book.py +0 -69
  514. ccxt/test/base/test_position.py +0 -60
  515. ccxt/test/base/test_shared_methods.py +0 -353
  516. ccxt/test/base/test_status.py +0 -24
  517. ccxt/test/base/test_throttle.py +0 -126
  518. ccxt/test/base/test_ticker.py +0 -92
  519. ccxt/test/base/test_trade.py +0 -47
  520. ccxt/test/base/test_trading_fee.py +0 -26
  521. ccxt/test/base/test_transaction.py +0 -39
  522. ccxt/test/test_async.py +0 -1649
  523. ccxt/test/test_sync.py +0 -1648
  524. ccxt/wazirx.py +0 -1224
  525. ccxt_ir-4.3.46.0.2.dist-info/RECORD +0 -772
  526. /ccxt/abstract/{huobijp.py → bittrade.py} +0 -0
  527. {ccxt_ir-4.3.46.0.2.dist-info → ccxt_ir-4.5.0.dist-info/licenses}/LICENSE.txt +0 -0
  528. {ccxt_ir-4.3.46.0.2.dist-info → ccxt_ir-4.5.0.dist-info}/top_level.txt +0 -0
ccxt/test/tests_async.py CHANGED
@@ -12,7 +12,6 @@ class testMainClass:
12
12
  request_tests = False
13
13
  ws_tests = False
14
14
  response_tests = False
15
- static_tests = False
16
15
  info = False
17
16
  verbose = False
18
17
  debug = False
@@ -50,16 +49,16 @@ class testMainClass:
50
49
  if self.request_tests and self.response_tests:
51
50
  await self.run_static_request_tests(exchange_id, symbol_argv)
52
51
  await self.run_static_response_tests(exchange_id, symbol_argv)
53
- return
52
+ return True
54
53
  if self.response_tests:
55
54
  await self.run_static_response_tests(exchange_id, symbol_argv)
56
- return
55
+ return True
57
56
  if self.request_tests:
58
57
  await self.run_static_request_tests(exchange_id, symbol_argv) # symbol here is the testname
59
- return
58
+ return True
60
59
  if self.id_tests:
61
60
  await self.run_broker_id_tests()
62
- return
61
+ return True
63
62
  new_line = '\n'
64
63
  dump(new_line + '' + new_line + '' + '[INFO] TESTING ', self.ext, {
65
64
  'exchange': exchange_id,
@@ -104,6 +103,7 @@ class testMainClass:
104
103
  self.test_files = get_test_files_sync(properties, self.ws_tests)
105
104
  else:
106
105
  self.test_files = await get_test_files(properties, self.ws_tests)
106
+ return True
107
107
 
108
108
  def load_credentials_from_env(self, exchange):
109
109
  exchange_id = exchange.id
@@ -126,8 +126,12 @@ class testMainClass:
126
126
  keys_local = get_root_dir() + 'keys.local.json'
127
127
  keys_global_exists = io_file_exists(keys_global)
128
128
  keys_local_exists = io_file_exists(keys_local)
129
- global_settings = io_file_read(keys_global) if keys_global_exists else {}
130
- local_settings = io_file_read(keys_local) if keys_local_exists else {}
129
+ global_settings = {}
130
+ if keys_global_exists:
131
+ global_settings = io_file_read(keys_global)
132
+ local_settings = {}
133
+ if keys_local_exists:
134
+ local_settings = io_file_read(keys_local)
131
135
  all_settings = exchange.deep_extend(global_settings, local_settings)
132
136
  exchange_settings = exchange.safe_value(all_settings, exchange_id, {})
133
137
  if exchange_settings:
@@ -178,19 +182,20 @@ class testMainClass:
178
182
  exchange.options['checksum'] = False
179
183
  # todo: temporary skip for php
180
184
  if 'OrderBook' in method_name and self.ext == 'php':
181
- return
185
+ return True
182
186
  skipped_properties_for_method = self.get_skips(exchange, method_name)
183
187
  is_load_markets = (method_name == 'loadMarkets')
184
188
  is_fetch_currencies = (method_name == 'fetchCurrencies')
185
189
  is_proxy_test = (method_name == self.proxy_test_file_name)
190
+ is_feature_test = (method_name == 'features')
186
191
  # if this is a private test, and the implementation was already tested in public, then no need to re-test it in private test (exception is fetchCurrencies, because our approach in base exchange)
187
192
  if not is_public and (method_name in self.checked_public_tests) and not is_fetch_currencies:
188
- return
193
+ return True
189
194
  skip_message = None
190
195
  supported_by_exchange = (method_name in exchange.has) and exchange.has[method_name]
191
196
  if not is_load_markets and (len(self.only_specific_tests) > 0 and not exchange.in_array(method_name, self.only_specific_tests)):
192
197
  skip_message = '[INFO] IGNORED_TEST'
193
- elif not is_load_markets and not supported_by_exchange and not is_proxy_test:
198
+ elif not is_load_markets and not supported_by_exchange and not is_proxy_test and not is_feature_test:
194
199
  skip_message = '[INFO] UNSUPPORTED_TEST' # keep it aligned with the longest message
195
200
  elif isinstance(skipped_properties_for_method, str):
196
201
  skip_message = '[INFO] SKIPPED_TEST'
@@ -203,7 +208,7 @@ class testMainClass:
203
208
  if skip_message:
204
209
  if self.info:
205
210
  dump(self.add_padding(skip_message, 25), name, method_name)
206
- return
211
+ return True
207
212
  if self.info:
208
213
  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"
209
214
  dump(self.add_padding('[INFO] TESTING', 25), name, method_name, args_stringified)
@@ -216,7 +221,7 @@ class testMainClass:
216
221
  # add to the list of successed tests
217
222
  if is_public:
218
223
  self.checked_public_tests[method_name] = True
219
- return
224
+ return True
220
225
 
221
226
  def get_skips(self, exchange, method_name):
222
227
  final_skips = {}
@@ -285,10 +290,10 @@ class testMainClass:
285
290
  is_on_maintenance = (isinstance(e, OnMaintenance))
286
291
  is_exchange_not_available = (isinstance(e, ExchangeNotAvailable))
287
292
  should_fail = None
288
- return_success = None
293
+ ret_success = None
289
294
  if is_load_markets:
290
295
  # if "loadMarkets" does not succeed, we must return "false" to caller method, to stop tests continual
291
- return_success = False
296
+ ret_success = False
292
297
  # we might not break exchange tests, if exchange is on maintenance at this moment
293
298
  if is_on_maintenance:
294
299
  should_fail = False
@@ -299,20 +304,19 @@ class testMainClass:
299
304
  if is_exchange_not_available and not is_on_maintenance:
300
305
  # break exchange tests if "ExchangeNotAvailable" exception is thrown, but it's not maintenance
301
306
  should_fail = True
302
- return_success = False
307
+ ret_success = False
303
308
  else:
304
309
  # in all other cases of OperationFailed, show Warning, but don't mark test as failed
305
310
  should_fail = False
306
- return_success = True
311
+ ret_success = True
307
312
  # output the message
308
313
  fail_type = '[TEST_FAILURE]' if should_fail else '[TEST_WARNING]'
309
314
  dump(fail_type, 'Method could not be tested due to a repeated Network/Availability issues', ' | ', exchange.id, method_name, args_stringified, exception_message(e))
310
- return return_success
315
+ return ret_success
311
316
  else:
312
317
  # wait and retry again
313
318
  # (increase wait time on every retry)
314
319
  await exchange.sleep((i + 1) * 1000)
315
- continue
316
320
  else:
317
321
  # if it's loadMarkets, then fail test, because it's mandatory for tests
318
322
  if is_load_markets:
@@ -336,6 +340,7 @@ class testMainClass:
336
340
 
337
341
  async def run_public_tests(self, exchange, symbol):
338
342
  tests = {
343
+ 'features': [],
339
344
  'fetchCurrencies': [],
340
345
  'fetchTicker': [symbol],
341
346
  'fetchTickers': [symbol],
@@ -343,7 +348,6 @@ class testMainClass:
343
348
  'fetchOHLCV': [symbol],
344
349
  'fetchTrades': [symbol],
345
350
  'fetchOrderBook': [symbol],
346
- 'fetchL2OrderBook': [symbol],
347
351
  'fetchOrderBooks': [],
348
352
  'fetchBidsAsks': [],
349
353
  'fetchStatus': [],
@@ -375,6 +379,7 @@ class testMainClass:
375
379
  tests['fetchPremiumIndexOHLCV'] = [symbol]
376
380
  self.public_tests = tests
377
381
  await self.run_tests(exchange, tests, True)
382
+ return True
378
383
 
379
384
  async def run_tests(self, exchange, tests, is_public_test):
380
385
  test_names = list(tests.keys())
@@ -399,6 +404,7 @@ class testMainClass:
399
404
  dump('[TEST_FAILURE]', exchange.id, test_prefix_string, 'Failed methods : ' + errors_string)
400
405
  if self.info:
401
406
  dump(self.add_padding('[INFO] END ' + test_prefix_string + ' ' + exchange.id, 25))
407
+ return True
402
408
 
403
409
  async def load_exchange(self, exchange):
404
410
  result = await self.test_safe('loadMarkets', exchange, [], True)
@@ -519,11 +525,12 @@ class testMainClass:
519
525
  if exchange.has['swap'] and swap_symbol is not None:
520
526
  exchange.options['defaultType'] = 'swap'
521
527
  await self.run_private_tests(exchange, swap_symbol)
528
+ return True
522
529
 
523
530
  async def run_private_tests(self, exchange, symbol):
524
531
  if not exchange.check_required_credentials(False):
525
532
  dump('[INFO] Skipping private tests', 'Keys not found')
526
- return
533
+ return True
527
534
  code = self.get_exchange_code(exchange)
528
535
  # if (exchange.deepExtendedTest) {
529
536
  # await test ('InvalidNonce', exchange, symbol);
@@ -560,6 +567,8 @@ class testMainClass:
560
567
  'fetchBorrowRateHistory': [code],
561
568
  'fetchLedgerEntry': [code],
562
569
  }
570
+ if get_cli_arg_value('--fundedTests'):
571
+ tests['createOrder'] = [symbol]
563
572
  if self.ws_tests:
564
573
  tests = {
565
574
  'watchBalance': [code],
@@ -591,14 +600,14 @@ class testMainClass:
591
600
  proxy_test_name = self.proxy_test_file_name
592
601
  # todo: temporary skip for sync py
593
602
  if self.ext == 'py' and is_sync():
594
- return
603
+ return True
595
604
  # try proxy several times
596
605
  max_retries = 3
597
606
  exception = None
598
607
  for j in range(0, max_retries):
599
608
  try:
600
609
  await self.test_method(proxy_test_name, exchange, [], True)
601
- return # if successfull, then end the test
610
+ return True # if successfull, then end the test
602
611
  except Exception as e:
603
612
  exception = e
604
613
  await exchange.sleep(j * 1000)
@@ -607,12 +616,39 @@ class testMainClass:
607
616
  error_message = '[TEST_FAILURE] Failed ' + proxy_test_name + ' : ' + exception_message(exception)
608
617
  # temporary comment the below, because c# transpilation failure
609
618
  # throw new Exchange Error (errorMessage.toString ());
610
- dump('[TEST_WARNING]' + str(error_message))
619
+ dump('[TEST_WARNING]' + error_message)
620
+ return True
621
+
622
+ def check_constructor(self, exchange):
623
+ # todo: this might be moved in base tests later
624
+ if exchange.id == 'binance':
625
+ assert exchange.hostname is None or exchange.hostname == '', 'binance.com hostname should be empty'
626
+ assert exchange.urls['api']['public'] == 'https://api.binance.com/api/v3', 'https://api.binance.com/api/v3 does not match: ' + exchange.urls['api']['public']
627
+ assert ('lending/union/account' in exchange.api['sapi']['get']), 'SAPI should contain the endpoint lending/union/account, ' + json_stringify(exchange.api['sapi']['get'])
628
+ elif exchange.id == 'binanceus':
629
+ assert exchange.hostname == 'binance.us', 'binance.us hostname does not match ' + exchange.hostname
630
+ assert exchange.urls['api']['public'] == 'https://api.binance.us/api/v3', 'https://api.binance.us/api/v3 does not match: ' + exchange.urls['api']['public']
631
+
632
+ async def test_return_response_headers(self, exchange):
633
+ if exchange.id != 'binance':
634
+ return False # this test is only for binance exchange for now
635
+ exchange.return_response_headers = True
636
+ ticker = await exchange.fetch_ticker('BTC/USDT')
637
+ info = ticker['info']
638
+ headers = info['responseHeaders']
639
+ headers_keys = list(headers.keys())
640
+ assert len(headers_keys) > 0, 'Response headers should not be empty'
641
+ header_values = list(headers.values())
642
+ assert len(header_values) > 0, 'Response headers values should not be empty'
643
+ exchange.return_response_headers = False
644
+ return True
611
645
 
612
646
  async def start_test(self, exchange, symbol):
613
647
  # we do not need to test aliases
614
648
  if exchange.alias:
615
- return
649
+ return True
650
+ self.check_constructor(exchange)
651
+ # await this.testReturnResponseHeaders (exchange);
616
652
  if self.sandbox or get_exchange_prop(exchange, 'sandbox'):
617
653
  exchange.set_sandbox_mode(True)
618
654
  try:
@@ -620,7 +656,7 @@ class testMainClass:
620
656
  if not result:
621
657
  if not is_sync():
622
658
  await close(exchange)
623
- return
659
+ return True
624
660
  # if (exchange.id === 'binance') {
625
661
  # # we test proxies functionality just for one random exchange on each build, because proxy functionality is not exchange-specific, instead it's all done from base methods, so just one working sample would mean it works for all ccxt exchanges
626
662
  # # await this.testProxies (exchange);
@@ -712,7 +748,7 @@ class testMainClass:
712
748
  result[key] = value
713
749
  return result
714
750
 
715
- def assert_new_and_stored_output(self, exchange, skip_keys, new_output, stored_output, strict_type_check=True, asserting_key=None):
751
+ def assert_new_and_stored_output_inner(self, exchange, skip_keys, new_output, stored_output, strict_type_check=True, asserting_key=None):
716
752
  if is_null_value(new_output) and is_null_value(stored_output):
717
753
  return True
718
754
  if not new_output and not stored_output:
@@ -743,8 +779,8 @@ class testMainClass:
743
779
  self.assert_new_and_stored_output(exchange, skip_keys, new_item, stored_item, strict_type_check)
744
780
  else:
745
781
  # built-in types like strings, numbers, booleans
746
- sanitized_new_output = None if (not new_output) else new_output # we store undefined as nulls in the json file so we need to convert it back
747
- sanitized_stored_output = None if (not stored_output) else stored_output
782
+ sanitized_new_output = None if (is_null_value(new_output)) else new_output # we store undefined as nulls in the json file so we need to convert it back
783
+ sanitized_stored_output = None if (is_null_value(stored_output)) else stored_output
748
784
  new_output_string = str(sanitized_new_output) if sanitized_new_output else 'undefined'
749
785
  stored_output_string = str(sanitized_stored_output) if sanitized_stored_output else 'undefined'
750
786
  message_error = 'output value mismatch:' + new_output_string + ' != ' + stored_output_string
@@ -765,7 +801,7 @@ class testMainClass:
765
801
  is_string = is_computed_string or is_stored_string
766
802
  is_undefined = is_computed_undefined or is_stored_undefined # undefined is a perfetly valid value
767
803
  if is_boolean or is_string or is_undefined:
768
- if self.lang == 'C#':
804
+ if (self.lang == 'C#') or (self.lang == 'GO'):
769
805
  # tmp c# number comparsion
770
806
  is_number = False
771
807
  try:
@@ -794,6 +830,27 @@ class testMainClass:
794
830
  self.assert_static_error(numeric_new_output == numeric_stored_output, message_error, stored_output, new_output, asserting_key)
795
831
  return True # c# requ
796
832
 
833
+ def assert_new_and_stored_output(self, exchange, skip_keys, new_output, stored_output, strict_type_check=True, asserting_key=None):
834
+ res = True
835
+ try:
836
+ res = self.assert_new_and_stored_output_inner(exchange, skip_keys, new_output, stored_output, strict_type_check, asserting_key)
837
+ except Exception as e:
838
+ if self.info:
839
+ error_message = self.var_to_string(new_output) + '(calculated)' + ' != ' + self.var_to_string(stored_output) + '(stored)'
840
+ dump('[TEST_FAILURE_DETAIL]' + error_message)
841
+ raise e
842
+ return res
843
+
844
+ def var_to_string(self, obj=None):
845
+ new_string = None
846
+ if obj is None:
847
+ new_string = 'undefined'
848
+ elif is_null_value(obj):
849
+ new_string = 'null'
850
+ else:
851
+ new_string = json_stringify(obj)
852
+ return new_string
853
+
797
854
  def assert_static_request_output(self, exchange, type, skip_keys, stored_url, request_url, stored_output, new_output):
798
855
  if stored_url != request_url:
799
856
  # remove the host part from the url
@@ -811,11 +868,11 @@ class testMainClass:
811
868
  if (stored_url_query is None) and (new_url_query is None):
812
869
  # might be a get request without any query parameters
813
870
  # example: https://api.gateio.ws/api/v4/delivery/usdt/positions
814
- return
871
+ return True
815
872
  stored_url_params = self.urlencoded_to_dict(stored_url_query)
816
873
  new_url_params = self.urlencoded_to_dict(new_url_query)
817
874
  self.assert_new_and_stored_output(exchange, skip_keys, new_url_params, stored_url_params)
818
- return
875
+ return True
819
876
  if type == 'json' and (stored_output is not None) and (new_output is not None):
820
877
  if isinstance(stored_output, str):
821
878
  stored_output = json_parse(stored_output)
@@ -832,6 +889,7 @@ class testMainClass:
832
889
  stored_output = self.urlencoded_to_dict(stored_output)
833
890
  new_output = self.urlencoded_to_dict(new_output)
834
891
  self.assert_new_and_stored_output(exchange, skip_keys, new_output, stored_output)
892
+ return True
835
893
 
836
894
  def assert_static_response_output(self, exchange, skip_keys, computed_result, stored_result):
837
895
  self.assert_new_and_stored_output(exchange, skip_keys, computed_result, stored_result, False)
@@ -852,6 +910,8 @@ class testMainClass:
852
910
  async def test_request_statically(self, exchange, method, data, type, skip_keys):
853
911
  output = None
854
912
  request_url = None
913
+ if self.info:
914
+ dump('[INFO] STATIC REQUEST TEST:', method, ':', data['description'])
855
915
  try:
856
916
  if not is_sync():
857
917
  await call_exchange_method_dynamically(exchange, method, self.sanitize_data_input(data['input']))
@@ -867,12 +927,15 @@ class testMainClass:
867
927
  self.assert_static_request_output(exchange, type, skip_keys, data['url'], request_url, call_output, output)
868
928
  except Exception as e:
869
929
  self.request_tests_failed = True
870
- error_message = '[' + self.lang + '][STATIC_REQUEST]' + '[' + exchange.id + ']' + '[' + method + ']' + '[' + data['description'] + ']' + str(e)
930
+ error_message = '[' + self.lang + '][STATIC_REQUEST]' + '[' + exchange.id + ']' + '[' + method + ']' + '[' + data['description'] + ']' + exception_message(e)
871
931
  dump('[TEST_FAILURE]' + error_message)
932
+ return True
872
933
 
873
934
  async def test_response_statically(self, exchange, method, skip_keys, data):
874
935
  expected_result = exchange.safe_value(data, 'parsedResponse')
875
936
  mocked_exchange = set_fetch_response(exchange, data['httpResponse'])
937
+ if self.info:
938
+ dump('[INFO] STATIC RESPONSE TEST:', method, ':', data['description'])
876
939
  try:
877
940
  if not is_sync():
878
941
  unified_result = await call_exchange_method_dynamically(exchange, method, self.sanitize_data_input(data['input']))
@@ -882,13 +945,15 @@ class testMainClass:
882
945
  self.assert_static_response_output(mocked_exchange, skip_keys, unified_result_sync, expected_result)
883
946
  except Exception as e:
884
947
  self.response_tests_failed = True
885
- error_message = '[' + self.lang + '][STATIC_RESPONSE]' + '[' + exchange.id + ']' + '[' + method + ']' + '[' + data['description'] + ']' + str(e)
948
+ error_message = '[' + self.lang + '][STATIC_RESPONSE]' + '[' + exchange.id + ']' + '[' + method + ']' + '[' + data['description'] + ']' + exception_message(e)
886
949
  dump('[TEST_FAILURE]' + error_message)
887
950
  set_fetch_response(exchange, None) # reset state
951
+ return True
888
952
 
889
953
  def init_offline_exchange(self, exchange_name):
890
954
  markets = self.load_markets_from_file(exchange_name)
891
955
  currencies = self.load_currencies_from_file(exchange_name)
956
+ # we add "proxy" 2 times to intentionally trigger InvalidProxySettings
892
957
  exchange = init_exchange(exchange_name, {
893
958
  'markets': markets,
894
959
  'currencies': currencies,
@@ -903,7 +968,8 @@ class testMainClass:
903
968
  'privateKey': '0xff3bdd43534543d421f05aec535965b5050ad6ac15345435345435453495e771',
904
969
  'uid': 'uid',
905
970
  'token': 'token',
906
- 'accountId': 'accountId',
971
+ 'login': 'login',
972
+ 'accountId': '12345',
907
973
  'accounts': [{
908
974
  'id': 'myAccount',
909
975
  'code': 'USDT',
@@ -919,7 +985,8 @@ class testMainClass:
919
985
  'leverageBrackets': {},
920
986
  },
921
987
  })
922
- exchange.currencies = currencies # not working in python if assigned in the config dict
988
+ exchange.currencies = currencies
989
+ # not working in python if assigned in the config dict
923
990
  return exchange
924
991
 
925
992
  async def test_exchange_request_statically(self, exchange_name, exchange_data, test_name=None):
@@ -939,6 +1006,9 @@ class testMainClass:
939
1006
  wallet_address = exchange.safe_string(exchange_data, 'walletAddress')
940
1007
  if wallet_address:
941
1008
  exchange.walletAddress = str(wallet_address)
1009
+ accounts = exchange.safe_list(exchange_data, 'accounts')
1010
+ if accounts:
1011
+ exchange.accounts = accounts
942
1012
  # exchange.options = exchange.deepExtend (exchange.options, globalOptions); # custom options to be used in the tests
943
1013
  exchange.extend_exchange_options(global_options)
944
1014
  methods = exchange.safe_value(exchange_data, 'methods', {})
@@ -964,12 +1034,14 @@ class testMainClass:
964
1034
  is_disabled_c_sharp = exchange.safe_bool(result, 'disabledCS', False)
965
1035
  if is_disabled_c_sharp and (self.lang == 'C#'):
966
1036
  continue
1037
+ is_disabled_go = exchange.safe_bool(result, 'disabledGO', False)
1038
+ if is_disabled_go and (self.lang == 'GO'):
1039
+ continue
967
1040
  type = exchange.safe_string(exchange_data, 'outputType')
968
1041
  skip_keys = exchange.safe_value(exchange_data, 'skipKeys', [])
969
1042
  await self.test_request_statically(exchange, method, result, type, skip_keys)
970
1043
  # reset options
971
- # exchange.options = exchange.deepExtend (oldExchangeOptions, {});
972
- exchange.extend_exchange_options(exchange.deep_extend(old_exchange_options, {}))
1044
+ exchange.options = exchange.convert_to_safe_dictionary(exchange.deep_extend(old_exchange_options, {}))
973
1045
  if not is_sync():
974
1046
  await close(exchange)
975
1047
  return True # in c# methods that will be used with promiseAll need to return something
@@ -1015,6 +1087,9 @@ class testMainClass:
1015
1087
  continue
1016
1088
  if (test_name is not None) and (test_name != description):
1017
1089
  continue
1090
+ is_disabled_go = exchange.safe_bool(result, 'disabledGO', False)
1091
+ if is_disabled_go and (self.lang == 'GO'):
1092
+ continue
1018
1093
  skip_keys = exchange.safe_value(exchange_data, 'skipKeys', [])
1019
1094
  await self.test_response_statically(exchange, method, skip_keys, result)
1020
1095
  # reset options
@@ -1037,14 +1112,35 @@ class testMainClass:
1037
1112
  sum = exchange.sum(sum, results_length)
1038
1113
  return sum
1039
1114
 
1115
+ def check_if_exchange_is_disabled(self, exchange_name, exchange_data):
1116
+ exchange = init_exchange('Exchange', {})
1117
+ is_disabled_py = exchange.safe_bool(exchange_data, 'disabledPy', False)
1118
+ if is_disabled_py and (self.lang == 'PY'):
1119
+ dump('[TEST_WARNING] Exchange ' + exchange_name + ' is disabled in python')
1120
+ return True
1121
+ is_disabled_php = exchange.safe_bool(exchange_data, 'disabledPHP', False)
1122
+ if is_disabled_php and (self.lang == 'PHP'):
1123
+ dump('[TEST_WARNING] Exchange ' + exchange_name + ' is disabled in php')
1124
+ return True
1125
+ is_disabled_c_sharp = exchange.safe_bool(exchange_data, 'disabledCS', False)
1126
+ if is_disabled_c_sharp and (self.lang == 'C#'):
1127
+ dump('[TEST_WARNING] Exchange ' + exchange_name + ' is disabled in c#')
1128
+ return True
1129
+ is_disabled_go = exchange.safe_bool(exchange_data, 'disabledGO', False)
1130
+ if is_disabled_go and (self.lang == 'GO'):
1131
+ dump('[TEST_WARNING] Exchange ' + exchange_name + ' is disabled in go')
1132
+ return True
1133
+ return False
1134
+
1040
1135
  async def run_static_request_tests(self, target_exchange=None, test_name=None):
1041
1136
  await self.run_static_tests('request', target_exchange, test_name)
1137
+ return True
1042
1138
 
1043
1139
  async def run_static_tests(self, type, target_exchange=None, test_name=None):
1044
1140
  folder = get_root_dir() + './ts/src/test/static/' + type + '/'
1045
1141
  static_data = self.load_static_data(folder, target_exchange)
1046
1142
  if static_data is None:
1047
- return
1143
+ return True
1048
1144
  exchanges = list(static_data.keys())
1049
1145
  exchange = init_exchange('Exchange', {}) # tmp to do the calculations until we have the ast-transpiler transpiling this code
1050
1146
  promises = []
@@ -1056,13 +1152,24 @@ class testMainClass:
1056
1152
  for i in range(0, len(exchanges)):
1057
1153
  exchange_name = exchanges[i]
1058
1154
  exchange_data = static_data[exchange_name]
1155
+ disabled = self.check_if_exchange_is_disabled(exchange_name, exchange_data)
1156
+ if disabled:
1157
+ continue
1059
1158
  number_of_tests = self.get_number_of_tests_from_exchange(exchange, exchange_data, test_name)
1060
1159
  sum = exchange.sum(sum, number_of_tests)
1061
1160
  if type == 'request':
1062
1161
  promises.append(self.test_exchange_request_statically(exchange_name, exchange_data, test_name))
1063
1162
  else:
1064
1163
  promises.append(self.test_exchange_response_statically(exchange_name, exchange_data, test_name))
1065
- await asyncio.gather(*promises)
1164
+ try:
1165
+ await asyncio.gather(*promises)
1166
+ except Exception as e:
1167
+ if type == 'request':
1168
+ self.request_tests_failed = True
1169
+ else:
1170
+ self.response_tests_failed = True
1171
+ error_message = '[' + self.lang + '][STATIC_REQUEST]' + exception_message(e)
1172
+ dump('[TEST_FAILURE]' + error_message)
1066
1173
  if self.request_tests_failed or self.response_tests_failed:
1067
1174
  exit_script(1)
1068
1175
  else:
@@ -1075,20 +1182,24 @@ class testMainClass:
1075
1182
  # --- Init of mockResponses tests functions------------------------------------
1076
1183
  # -----------------------------------------------------------------------------
1077
1184
  await self.run_static_tests('response', exchange_name, test)
1185
+ return True
1078
1186
 
1079
1187
  async def run_broker_id_tests(self):
1080
1188
  # -----------------------------------------------------------------------------
1081
1189
  # --- Init of brokerId tests functions-----------------------------------------
1082
1190
  # -----------------------------------------------------------------------------
1083
- promises = [self.test_binance(), self.test_okx(), self.test_cryptocom(), self.test_bybit(), self.test_kucoin(), self.test_kucoinfutures(), self.test_bitget(), self.test_mexc(), self.test_htx(), self.test_woo(), self.test_bitmart(), self.test_coinex(), self.test_bingx(), self.test_phemex(), self.test_blofin(), self.test_hyperliquid(), self.test_coinbaseinternational(), self.test_coinbase_advanced(), self.test_woofi_pro(), self.test_oxfun(), self.test_xt(), self.test_vertex(), self.test_paradex(), self.test_hashkey(), self.test_coincatch()]
1191
+ promises = [self.test_binance(), self.test_okx(), self.test_cryptocom(), self.test_bybit(), self.test_kucoin(), self.test_kucoinfutures(), self.test_bitget(), self.test_mexc(), self.test_htx(), self.test_woo(), self.test_bitmart(), self.test_coinex(), self.test_bingx(), self.test_phemex(), self.test_blofin(), self.test_coinbaseinternational(), self.test_coinbase_advanced(), self.test_woofi_pro(), self.test_oxfun(), self.test_xt(), self.test_vertex(), self.test_paradex(), self.test_hashkey(), self.test_coincatch(), self.test_defx(), self.test_cryptomus(), self.test_derive(), self.test_mode_trade()]
1084
1192
  await asyncio.gather(*promises)
1085
1193
  success_message = '[' + self.lang + '][TEST_SUCCESS] brokerId tests passed.'
1086
1194
  dump('[INFO]' + success_message)
1087
1195
  exit_script(0)
1196
+ return True
1088
1197
 
1089
1198
  async def test_binance(self):
1090
1199
  exchange = self.init_offline_exchange('binance')
1091
- spot_id = 'x-R4BD3S82'
1200
+ spot_id = 'x-TKT5PX2F'
1201
+ swap_id = 'x-cvBPrNm9'
1202
+ inverse_swap_id = 'x-xcKtGhcu'
1092
1203
  spot_order_request = None
1093
1204
  try:
1094
1205
  await exchange.create_order('BTC/USDT', 'limit', 'buy', 1, 20000)
@@ -1097,7 +1208,6 @@ class testMainClass:
1097
1208
  client_order_id = spot_order_request['newClientOrderId']
1098
1209
  spot_id_string = str(spot_id)
1099
1210
  assert client_order_id.startswith(spot_id_string), 'binance - spot clientOrderId: ' + client_order_id + ' does not start with spotId' + spot_id_string
1100
- swap_id = 'x-xcKtGhcu'
1101
1211
  swap_order_request = None
1102
1212
  try:
1103
1213
  await exchange.create_order('BTC/USDT:USDT', 'limit', 'buy', 1, 20000)
@@ -1108,11 +1218,35 @@ class testMainClass:
1108
1218
  await exchange.create_order('BTC/USD:BTC', 'limit', 'buy', 1, 20000)
1109
1219
  except Exception as e:
1110
1220
  swap_inverse_order_request = self.urlencoded_to_dict(exchange.last_request_body)
1221
+ # linear swap
1111
1222
  client_order_id_swap = swap_order_request['newClientOrderId']
1112
1223
  swap_id_string = str(swap_id)
1113
1224
  assert client_order_id_swap.startswith(swap_id_string), 'binance - swap clientOrderId: ' + client_order_id_swap + ' does not start with swapId' + swap_id_string
1225
+ # inverse swap
1114
1226
  client_order_id_inverse = swap_inverse_order_request['newClientOrderId']
1115
- assert client_order_id_inverse.startswith(swap_id_string), 'binance - swap clientOrderIdInverse: ' + client_order_id_inverse + ' does not start with swapId' + swap_id_string
1227
+ assert client_order_id_inverse.startswith(inverse_swap_id), 'binance - swap clientOrderIdInverse: ' + client_order_id_inverse + ' does not start with swapId' + inverse_swap_id
1228
+ create_orders_request = None
1229
+ try:
1230
+ orders = [{
1231
+ 'symbol': 'BTC/USDT:USDT',
1232
+ 'type': 'limit',
1233
+ 'side': 'sell',
1234
+ 'amount': 1,
1235
+ 'price': 100000,
1236
+ }, {
1237
+ 'symbol': 'BTC/USDT:USDT',
1238
+ 'type': 'market',
1239
+ 'side': 'buy',
1240
+ 'amount': 1,
1241
+ }]
1242
+ await exchange.create_orders(orders)
1243
+ except Exception as e:
1244
+ create_orders_request = self.urlencoded_to_dict(exchange.last_request_body)
1245
+ batch_orders = create_orders_request['batchOrders']
1246
+ for i in range(0, len(batch_orders)):
1247
+ current = batch_orders[i]
1248
+ current_client_order_id = current['newClientOrderId']
1249
+ assert current_client_order_id.startswith(swap_id_string), 'binance createOrders - clientOrderId: ' + current_client_order_id + ' does not start with swapId' + swap_id_string
1116
1250
  if not is_sync():
1117
1251
  await close(exchange)
1118
1252
  return True
@@ -1276,7 +1410,7 @@ class testMainClass:
1276
1410
  try:
1277
1411
  await exchange.create_order('BTC/USDT', 'limit', 'buy', 1, 20000)
1278
1412
  except Exception as e:
1279
- spot_order_request = self.urlencoded_to_dict(exchange.last_request_body)
1413
+ spot_order_request = json_parse(exchange.last_request_body)
1280
1414
  broker_id = spot_order_request['broker_id']
1281
1415
  id_string = str(id)
1282
1416
  assert broker_id.startswith(id_string), 'woo - broker_id: ' + broker_id + ' does not start with id: ' + id_string
@@ -1338,6 +1472,7 @@ class testMainClass:
1338
1472
  assert req_headers['X-SOURCE-KEY'] == id, 'bingx - id: ' + id + ' not in headers.'
1339
1473
  if not is_sync():
1340
1474
  await close(exchange)
1475
+ return True
1341
1476
 
1342
1477
  async def test_phemex(self):
1343
1478
  exchange = self.init_offline_exchange('phemex')
@@ -1352,6 +1487,7 @@ class testMainClass:
1352
1487
  assert client_order_id.startswith(id_string), 'phemex - clOrdID: ' + client_order_id + ' does not start with id: ' + id_string
1353
1488
  if not is_sync():
1354
1489
  await close(exchange)
1490
+ return True
1355
1491
 
1356
1492
  async def test_blofin(self):
1357
1493
  exchange = self.init_offline_exchange('blofin')
@@ -1366,20 +1502,24 @@ class testMainClass:
1366
1502
  assert broker_id.startswith(id_string), 'blofin - brokerId: ' + broker_id + ' does not start with id: ' + id_string
1367
1503
  if not is_sync():
1368
1504
  await close(exchange)
1505
+ return True
1369
1506
 
1370
- async def test_hyperliquid(self):
1371
- exchange = self.init_offline_exchange('hyperliquid')
1372
- id = '1'
1373
- request = None
1374
- try:
1375
- await exchange.create_order('SOL/USDC:USDC', 'limit', 'buy', 1, 100)
1376
- except Exception as e:
1377
- request = json_parse(exchange.last_request_body)
1378
- broker_id = str((request['action']['brokerCode']))
1379
- assert broker_id == id, 'hyperliquid - brokerId: ' + broker_id + ' does not start with id: ' + id
1380
- if not is_sync():
1381
- await close(exchange)
1382
-
1507
+ # async testHyperliquid () {
1508
+ # const exchange = this.initOfflineExchange ('hyperliquid');
1509
+ # const id = '1';
1510
+ # let request = undefined;
1511
+ # try {
1512
+ # await exchange.createOrder ('SOL/USDC:USDC', 'limit', 'buy', 1, 100);
1513
+ # } catch (e) {
1514
+ # request = jsonParse (exchange.last_request_body);
1515
+ # }
1516
+ # const brokerId = (request['action']['brokerCode']).toString ();
1517
+ # assert (brokerId === id, 'hyperliquid - brokerId: ' + brokerId + ' does not start with id: ' + id);
1518
+ # if (!isSync ()) {
1519
+ # await close (exchange);
1520
+ # }
1521
+ # return true;
1522
+ # }
1383
1523
  async def test_coinbaseinternational(self):
1384
1524
  exchange = self.init_offline_exchange('coinbaseinternational')
1385
1525
  exchange.options['portfolio'] = 'random'
@@ -1556,3 +1696,67 @@ class testMainClass:
1556
1696
  if not is_sync():
1557
1697
  await close(exchange)
1558
1698
  return True
1699
+
1700
+ async def test_defx(self):
1701
+ exchange = self.init_offline_exchange('defx')
1702
+ req_headers = None
1703
+ try:
1704
+ await exchange.create_order('DOGE/USDC:USDC', 'limit', 'buy', 100, 1)
1705
+ except Exception as e:
1706
+ # we expect an error here, we're only interested in the headers
1707
+ req_headers = exchange.last_request_headers
1708
+ id = 'ccxt'
1709
+ assert req_headers['X-DEFX-SOURCE'] == id, 'defx - id: ' + id + ' not in headers.'
1710
+ if not is_sync():
1711
+ await close(exchange)
1712
+ return True
1713
+
1714
+ async def test_cryptomus(self):
1715
+ exchange = self.init_offline_exchange('cryptomus')
1716
+ request = None
1717
+ try:
1718
+ await exchange.create_order('BTC/USDT', 'limit', 'sell', 1, 20000)
1719
+ except Exception as e:
1720
+ request = json_parse(exchange.last_request_body)
1721
+ tag = 'ccxt'
1722
+ assert request['tag'] == tag, 'cryptomus - tag: ' + tag + ' not in request.'
1723
+ if not is_sync():
1724
+ await close(exchange)
1725
+ return True
1726
+
1727
+ async def test_derive(self):
1728
+ exchange = self.init_offline_exchange('derive')
1729
+ id = '0x0ad42b8e602c2d3d475ae52d678cf63d84ab2749'
1730
+ assert exchange.options['id'] == id, 'derive - id: ' + id + ' not in options'
1731
+ request = None
1732
+ try:
1733
+ params = {
1734
+ 'subaccount_id': 1234,
1735
+ 'max_fee': 10,
1736
+ 'deriveWalletAddress': '0x0ad42b8e602c2d3d475ae52d678cf63d84ab2749',
1737
+ }
1738
+ exchange.walletAddress = '0x0ad42b8e602c2d3d475ae52d678cf63d84ab2749'
1739
+ exchange.privateKey = '0x7b77bb7b20e92bbb85f2a22b330b896959229a5790e35f2f290922de3fb22ad5'
1740
+ await exchange.create_order('LBTC/USDC', 'limit', 'sell', 0.01, 3000, params)
1741
+ except Exception as e:
1742
+ request = json_parse(exchange.last_request_body)
1743
+ assert request['referral_code'] == id, 'derive - referral_code: ' + id + ' not in request.'
1744
+ if not is_sync():
1745
+ await close(exchange)
1746
+ return True
1747
+
1748
+ async def test_mode_trade(self):
1749
+ exchange = self.init_offline_exchange('modetrade')
1750
+ exchange.secret = 'secretsecretsecretsecretsecretsecretsecrets'
1751
+ id = 'CCXTMODE'
1752
+ await exchange.load_markets()
1753
+ request = None
1754
+ try:
1755
+ await exchange.create_order('BTC/USDC:USDC', 'limit', 'buy', 1, 20000)
1756
+ except Exception as e:
1757
+ request = json_parse(exchange.last_request_body)
1758
+ broker_id = request['order_tag']
1759
+ assert broker_id == id, 'modetrade - id: ' + id + ' different from broker_id: ' + broker_id
1760
+ if not is_sync():
1761
+ await close(exchange)
1762
+ return True