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_sync.py CHANGED
@@ -9,7 +9,6 @@ class testMainClass:
9
9
  request_tests = False
10
10
  ws_tests = False
11
11
  response_tests = False
12
- static_tests = False
13
12
  info = False
14
13
  verbose = False
15
14
  debug = False
@@ -47,16 +46,16 @@ class testMainClass:
47
46
  if self.request_tests and self.response_tests:
48
47
  self.run_static_request_tests(exchange_id, symbol_argv)
49
48
  self.run_static_response_tests(exchange_id, symbol_argv)
50
- return
49
+ return True
51
50
  if self.response_tests:
52
51
  self.run_static_response_tests(exchange_id, symbol_argv)
53
- return
52
+ return True
54
53
  if self.request_tests:
55
54
  self.run_static_request_tests(exchange_id, symbol_argv) # symbol here is the testname
56
- return
55
+ return True
57
56
  if self.id_tests:
58
57
  self.run_broker_id_tests()
59
- return
58
+ return True
60
59
  new_line = '\n'
61
60
  dump(new_line + '' + new_line + '' + '[INFO] TESTING ', self.ext, {
62
61
  'exchange': exchange_id,
@@ -101,6 +100,7 @@ class testMainClass:
101
100
  self.test_files = get_test_files_sync(properties, self.ws_tests)
102
101
  else:
103
102
  self.test_files = get_test_files(properties, self.ws_tests)
103
+ return True
104
104
 
105
105
  def load_credentials_from_env(self, exchange):
106
106
  exchange_id = exchange.id
@@ -123,8 +123,12 @@ class testMainClass:
123
123
  keys_local = get_root_dir() + 'keys.local.json'
124
124
  keys_global_exists = io_file_exists(keys_global)
125
125
  keys_local_exists = io_file_exists(keys_local)
126
- global_settings = io_file_read(keys_global) if keys_global_exists else {}
127
- local_settings = io_file_read(keys_local) if keys_local_exists else {}
126
+ global_settings = {}
127
+ if keys_global_exists:
128
+ global_settings = io_file_read(keys_global)
129
+ local_settings = {}
130
+ if keys_local_exists:
131
+ local_settings = io_file_read(keys_local)
128
132
  all_settings = exchange.deep_extend(global_settings, local_settings)
129
133
  exchange_settings = exchange.safe_value(all_settings, exchange_id, {})
130
134
  if exchange_settings:
@@ -175,19 +179,20 @@ class testMainClass:
175
179
  exchange.options['checksum'] = False
176
180
  # todo: temporary skip for php
177
181
  if 'OrderBook' in method_name and self.ext == 'php':
178
- return
182
+ return True
179
183
  skipped_properties_for_method = self.get_skips(exchange, method_name)
180
184
  is_load_markets = (method_name == 'loadMarkets')
181
185
  is_fetch_currencies = (method_name == 'fetchCurrencies')
182
186
  is_proxy_test = (method_name == self.proxy_test_file_name)
187
+ is_feature_test = (method_name == 'features')
183
188
  # 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)
184
189
  if not is_public and (method_name in self.checked_public_tests) and not is_fetch_currencies:
185
- return
190
+ return True
186
191
  skip_message = None
187
192
  supported_by_exchange = (method_name in exchange.has) and exchange.has[method_name]
188
193
  if not is_load_markets and (len(self.only_specific_tests) > 0 and not exchange.in_array(method_name, self.only_specific_tests)):
189
194
  skip_message = '[INFO] IGNORED_TEST'
190
- elif not is_load_markets and not supported_by_exchange and not is_proxy_test:
195
+ elif not is_load_markets and not supported_by_exchange and not is_proxy_test and not is_feature_test:
191
196
  skip_message = '[INFO] UNSUPPORTED_TEST' # keep it aligned with the longest message
192
197
  elif isinstance(skipped_properties_for_method, str):
193
198
  skip_message = '[INFO] SKIPPED_TEST'
@@ -200,7 +205,7 @@ class testMainClass:
200
205
  if skip_message:
201
206
  if self.info:
202
207
  dump(self.add_padding(skip_message, 25), name, method_name)
203
- return
208
+ return True
204
209
  if self.info:
205
210
  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"
206
211
  dump(self.add_padding('[INFO] TESTING', 25), name, method_name, args_stringified)
@@ -213,7 +218,7 @@ class testMainClass:
213
218
  # add to the list of successed tests
214
219
  if is_public:
215
220
  self.checked_public_tests[method_name] = True
216
- return
221
+ return True
217
222
 
218
223
  def get_skips(self, exchange, method_name):
219
224
  final_skips = {}
@@ -282,10 +287,10 @@ class testMainClass:
282
287
  is_on_maintenance = (isinstance(e, OnMaintenance))
283
288
  is_exchange_not_available = (isinstance(e, ExchangeNotAvailable))
284
289
  should_fail = None
285
- return_success = None
290
+ ret_success = None
286
291
  if is_load_markets:
287
292
  # if "loadMarkets" does not succeed, we must return "false" to caller method, to stop tests continual
288
- return_success = False
293
+ ret_success = False
289
294
  # we might not break exchange tests, if exchange is on maintenance at this moment
290
295
  if is_on_maintenance:
291
296
  should_fail = False
@@ -296,20 +301,19 @@ class testMainClass:
296
301
  if is_exchange_not_available and not is_on_maintenance:
297
302
  # break exchange tests if "ExchangeNotAvailable" exception is thrown, but it's not maintenance
298
303
  should_fail = True
299
- return_success = False
304
+ ret_success = False
300
305
  else:
301
306
  # in all other cases of OperationFailed, show Warning, but don't mark test as failed
302
307
  should_fail = False
303
- return_success = True
308
+ ret_success = True
304
309
  # output the message
305
310
  fail_type = '[TEST_FAILURE]' if should_fail else '[TEST_WARNING]'
306
311
  dump(fail_type, 'Method could not be tested due to a repeated Network/Availability issues', ' | ', exchange.id, method_name, args_stringified, exception_message(e))
307
- return return_success
312
+ return ret_success
308
313
  else:
309
314
  # wait and retry again
310
315
  # (increase wait time on every retry)
311
316
  exchange.sleep((i + 1) * 1000)
312
- continue
313
317
  else:
314
318
  # if it's loadMarkets, then fail test, because it's mandatory for tests
315
319
  if is_load_markets:
@@ -333,6 +337,7 @@ class testMainClass:
333
337
 
334
338
  def run_public_tests(self, exchange, symbol):
335
339
  tests = {
340
+ 'features': [],
336
341
  'fetchCurrencies': [],
337
342
  'fetchTicker': [symbol],
338
343
  'fetchTickers': [symbol],
@@ -340,7 +345,6 @@ class testMainClass:
340
345
  'fetchOHLCV': [symbol],
341
346
  'fetchTrades': [symbol],
342
347
  'fetchOrderBook': [symbol],
343
- 'fetchL2OrderBook': [symbol],
344
348
  'fetchOrderBooks': [],
345
349
  'fetchBidsAsks': [],
346
350
  'fetchStatus': [],
@@ -372,6 +376,7 @@ class testMainClass:
372
376
  tests['fetchPremiumIndexOHLCV'] = [symbol]
373
377
  self.public_tests = tests
374
378
  self.run_tests(exchange, tests, True)
379
+ return True
375
380
 
376
381
  def run_tests(self, exchange, tests, is_public_test):
377
382
  test_names = list(tests.keys())
@@ -396,6 +401,7 @@ class testMainClass:
396
401
  dump('[TEST_FAILURE]', exchange.id, test_prefix_string, 'Failed methods : ' + errors_string)
397
402
  if self.info:
398
403
  dump(self.add_padding('[INFO] END ' + test_prefix_string + ' ' + exchange.id, 25))
404
+ return True
399
405
 
400
406
  def load_exchange(self, exchange):
401
407
  result = self.test_safe('loadMarkets', exchange, [], True)
@@ -516,11 +522,12 @@ class testMainClass:
516
522
  if exchange.has['swap'] and swap_symbol is not None:
517
523
  exchange.options['defaultType'] = 'swap'
518
524
  self.run_private_tests(exchange, swap_symbol)
525
+ return True
519
526
 
520
527
  def run_private_tests(self, exchange, symbol):
521
528
  if not exchange.check_required_credentials(False):
522
529
  dump('[INFO] Skipping private tests', 'Keys not found')
523
- return
530
+ return True
524
531
  code = self.get_exchange_code(exchange)
525
532
  # if (exchange.deepExtendedTest) {
526
533
  # test ('InvalidNonce', exchange, symbol);
@@ -557,6 +564,8 @@ class testMainClass:
557
564
  'fetchBorrowRateHistory': [code],
558
565
  'fetchLedgerEntry': [code],
559
566
  }
567
+ if get_cli_arg_value('--fundedTests'):
568
+ tests['createOrder'] = [symbol]
560
569
  if self.ws_tests:
561
570
  tests = {
562
571
  'watchBalance': [code],
@@ -588,14 +597,14 @@ class testMainClass:
588
597
  proxy_test_name = self.proxy_test_file_name
589
598
  # todo: temporary skip for sync py
590
599
  if self.ext == 'py' and is_sync():
591
- return
600
+ return True
592
601
  # try proxy several times
593
602
  max_retries = 3
594
603
  exception = None
595
604
  for j in range(0, max_retries):
596
605
  try:
597
606
  self.test_method(proxy_test_name, exchange, [], True)
598
- return # if successfull, then end the test
607
+ return True # if successfull, then end the test
599
608
  except Exception as e:
600
609
  exception = e
601
610
  exchange.sleep(j * 1000)
@@ -604,12 +613,39 @@ class testMainClass:
604
613
  error_message = '[TEST_FAILURE] Failed ' + proxy_test_name + ' : ' + exception_message(exception)
605
614
  # temporary comment the below, because c# transpilation failure
606
615
  # throw new Exchange Error (errorMessage.toString ());
607
- dump('[TEST_WARNING]' + str(error_message))
616
+ dump('[TEST_WARNING]' + error_message)
617
+ return True
618
+
619
+ def check_constructor(self, exchange):
620
+ # todo: this might be moved in base tests later
621
+ if exchange.id == 'binance':
622
+ assert exchange.hostname is None or exchange.hostname == '', 'binance.com hostname should be empty'
623
+ assert exchange.urls['api']['public'] == 'https://api.binance.com/api/v3', 'https://api.binance.com/api/v3 does not match: ' + exchange.urls['api']['public']
624
+ assert ('lending/union/account' in exchange.api['sapi']['get']), 'SAPI should contain the endpoint lending/union/account, ' + json_stringify(exchange.api['sapi']['get'])
625
+ elif exchange.id == 'binanceus':
626
+ assert exchange.hostname == 'binance.us', 'binance.us hostname does not match ' + exchange.hostname
627
+ assert exchange.urls['api']['public'] == 'https://api.binance.us/api/v3', 'https://api.binance.us/api/v3 does not match: ' + exchange.urls['api']['public']
628
+
629
+ def test_return_response_headers(self, exchange):
630
+ if exchange.id != 'binance':
631
+ return False # this test is only for binance exchange for now
632
+ exchange.return_response_headers = True
633
+ ticker = exchange.fetch_ticker('BTC/USDT')
634
+ info = ticker['info']
635
+ headers = info['responseHeaders']
636
+ headers_keys = list(headers.keys())
637
+ assert len(headers_keys) > 0, 'Response headers should not be empty'
638
+ header_values = list(headers.values())
639
+ assert len(header_values) > 0, 'Response headers values should not be empty'
640
+ exchange.return_response_headers = False
641
+ return True
608
642
 
609
643
  def start_test(self, exchange, symbol):
610
644
  # we do not need to test aliases
611
645
  if exchange.alias:
612
- return
646
+ return True
647
+ self.check_constructor(exchange)
648
+ # this.testReturnResponseHeaders (exchange);
613
649
  if self.sandbox or get_exchange_prop(exchange, 'sandbox'):
614
650
  exchange.set_sandbox_mode(True)
615
651
  try:
@@ -617,7 +653,7 @@ class testMainClass:
617
653
  if not result:
618
654
  if not is_sync():
619
655
  close(exchange)
620
- return
656
+ return True
621
657
  # if (exchange.id === 'binance') {
622
658
  # # 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
623
659
  # # this.testProxies (exchange);
@@ -709,7 +745,7 @@ class testMainClass:
709
745
  result[key] = value
710
746
  return result
711
747
 
712
- def assert_new_and_stored_output(self, exchange, skip_keys, new_output, stored_output, strict_type_check=True, asserting_key=None):
748
+ def assert_new_and_stored_output_inner(self, exchange, skip_keys, new_output, stored_output, strict_type_check=True, asserting_key=None):
713
749
  if is_null_value(new_output) and is_null_value(stored_output):
714
750
  return True
715
751
  if not new_output and not stored_output:
@@ -740,8 +776,8 @@ class testMainClass:
740
776
  self.assert_new_and_stored_output(exchange, skip_keys, new_item, stored_item, strict_type_check)
741
777
  else:
742
778
  # built-in types like strings, numbers, booleans
743
- 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
744
- sanitized_stored_output = None if (not stored_output) else stored_output
779
+ 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
780
+ sanitized_stored_output = None if (is_null_value(stored_output)) else stored_output
745
781
  new_output_string = str(sanitized_new_output) if sanitized_new_output else 'undefined'
746
782
  stored_output_string = str(sanitized_stored_output) if sanitized_stored_output else 'undefined'
747
783
  message_error = 'output value mismatch:' + new_output_string + ' != ' + stored_output_string
@@ -762,7 +798,7 @@ class testMainClass:
762
798
  is_string = is_computed_string or is_stored_string
763
799
  is_undefined = is_computed_undefined or is_stored_undefined # undefined is a perfetly valid value
764
800
  if is_boolean or is_string or is_undefined:
765
- if self.lang == 'C#':
801
+ if (self.lang == 'C#') or (self.lang == 'GO'):
766
802
  # tmp c# number comparsion
767
803
  is_number = False
768
804
  try:
@@ -791,6 +827,27 @@ class testMainClass:
791
827
  self.assert_static_error(numeric_new_output == numeric_stored_output, message_error, stored_output, new_output, asserting_key)
792
828
  return True # c# requ
793
829
 
830
+ def assert_new_and_stored_output(self, exchange, skip_keys, new_output, stored_output, strict_type_check=True, asserting_key=None):
831
+ res = True
832
+ try:
833
+ res = self.assert_new_and_stored_output_inner(exchange, skip_keys, new_output, stored_output, strict_type_check, asserting_key)
834
+ except Exception as e:
835
+ if self.info:
836
+ error_message = self.var_to_string(new_output) + '(calculated)' + ' != ' + self.var_to_string(stored_output) + '(stored)'
837
+ dump('[TEST_FAILURE_DETAIL]' + error_message)
838
+ raise e
839
+ return res
840
+
841
+ def var_to_string(self, obj=None):
842
+ new_string = None
843
+ if obj is None:
844
+ new_string = 'undefined'
845
+ elif is_null_value(obj):
846
+ new_string = 'null'
847
+ else:
848
+ new_string = json_stringify(obj)
849
+ return new_string
850
+
794
851
  def assert_static_request_output(self, exchange, type, skip_keys, stored_url, request_url, stored_output, new_output):
795
852
  if stored_url != request_url:
796
853
  # remove the host part from the url
@@ -808,11 +865,11 @@ class testMainClass:
808
865
  if (stored_url_query is None) and (new_url_query is None):
809
866
  # might be a get request without any query parameters
810
867
  # example: https://api.gateio.ws/api/v4/delivery/usdt/positions
811
- return
868
+ return True
812
869
  stored_url_params = self.urlencoded_to_dict(stored_url_query)
813
870
  new_url_params = self.urlencoded_to_dict(new_url_query)
814
871
  self.assert_new_and_stored_output(exchange, skip_keys, new_url_params, stored_url_params)
815
- return
872
+ return True
816
873
  if type == 'json' and (stored_output is not None) and (new_output is not None):
817
874
  if isinstance(stored_output, str):
818
875
  stored_output = json_parse(stored_output)
@@ -829,6 +886,7 @@ class testMainClass:
829
886
  stored_output = self.urlencoded_to_dict(stored_output)
830
887
  new_output = self.urlencoded_to_dict(new_output)
831
888
  self.assert_new_and_stored_output(exchange, skip_keys, new_output, stored_output)
889
+ return True
832
890
 
833
891
  def assert_static_response_output(self, exchange, skip_keys, computed_result, stored_result):
834
892
  self.assert_new_and_stored_output(exchange, skip_keys, computed_result, stored_result, False)
@@ -849,6 +907,8 @@ class testMainClass:
849
907
  def test_request_statically(self, exchange, method, data, type, skip_keys):
850
908
  output = None
851
909
  request_url = None
910
+ if self.info:
911
+ dump('[INFO] STATIC REQUEST TEST:', method, ':', data['description'])
852
912
  try:
853
913
  if not is_sync():
854
914
  call_exchange_method_dynamically(exchange, method, self.sanitize_data_input(data['input']))
@@ -864,12 +924,15 @@ class testMainClass:
864
924
  self.assert_static_request_output(exchange, type, skip_keys, data['url'], request_url, call_output, output)
865
925
  except Exception as e:
866
926
  self.request_tests_failed = True
867
- error_message = '[' + self.lang + '][STATIC_REQUEST]' + '[' + exchange.id + ']' + '[' + method + ']' + '[' + data['description'] + ']' + str(e)
927
+ error_message = '[' + self.lang + '][STATIC_REQUEST]' + '[' + exchange.id + ']' + '[' + method + ']' + '[' + data['description'] + ']' + exception_message(e)
868
928
  dump('[TEST_FAILURE]' + error_message)
929
+ return True
869
930
 
870
931
  def test_response_statically(self, exchange, method, skip_keys, data):
871
932
  expected_result = exchange.safe_value(data, 'parsedResponse')
872
933
  mocked_exchange = set_fetch_response(exchange, data['httpResponse'])
934
+ if self.info:
935
+ dump('[INFO] STATIC RESPONSE TEST:', method, ':', data['description'])
873
936
  try:
874
937
  if not is_sync():
875
938
  unified_result = call_exchange_method_dynamically(exchange, method, self.sanitize_data_input(data['input']))
@@ -879,13 +942,15 @@ class testMainClass:
879
942
  self.assert_static_response_output(mocked_exchange, skip_keys, unified_result_sync, expected_result)
880
943
  except Exception as e:
881
944
  self.response_tests_failed = True
882
- error_message = '[' + self.lang + '][STATIC_RESPONSE]' + '[' + exchange.id + ']' + '[' + method + ']' + '[' + data['description'] + ']' + str(e)
945
+ error_message = '[' + self.lang + '][STATIC_RESPONSE]' + '[' + exchange.id + ']' + '[' + method + ']' + '[' + data['description'] + ']' + exception_message(e)
883
946
  dump('[TEST_FAILURE]' + error_message)
884
947
  set_fetch_response(exchange, None) # reset state
948
+ return True
885
949
 
886
950
  def init_offline_exchange(self, exchange_name):
887
951
  markets = self.load_markets_from_file(exchange_name)
888
952
  currencies = self.load_currencies_from_file(exchange_name)
953
+ # we add "proxy" 2 times to intentionally trigger InvalidProxySettings
889
954
  exchange = init_exchange(exchange_name, {
890
955
  'markets': markets,
891
956
  'currencies': currencies,
@@ -900,7 +965,8 @@ class testMainClass:
900
965
  'privateKey': '0xff3bdd43534543d421f05aec535965b5050ad6ac15345435345435453495e771',
901
966
  'uid': 'uid',
902
967
  'token': 'token',
903
- 'accountId': 'accountId',
968
+ 'login': 'login',
969
+ 'accountId': '12345',
904
970
  'accounts': [{
905
971
  'id': 'myAccount',
906
972
  'code': 'USDT',
@@ -916,7 +982,8 @@ class testMainClass:
916
982
  'leverageBrackets': {},
917
983
  },
918
984
  })
919
- exchange.currencies = currencies # not working in python if assigned in the config dict
985
+ exchange.currencies = currencies
986
+ # not working in python if assigned in the config dict
920
987
  return exchange
921
988
 
922
989
  def test_exchange_request_statically(self, exchange_name, exchange_data, test_name=None):
@@ -936,6 +1003,9 @@ class testMainClass:
936
1003
  wallet_address = exchange.safe_string(exchange_data, 'walletAddress')
937
1004
  if wallet_address:
938
1005
  exchange.walletAddress = str(wallet_address)
1006
+ accounts = exchange.safe_list(exchange_data, 'accounts')
1007
+ if accounts:
1008
+ exchange.accounts = accounts
939
1009
  # exchange.options = exchange.deepExtend (exchange.options, globalOptions); # custom options to be used in the tests
940
1010
  exchange.extend_exchange_options(global_options)
941
1011
  methods = exchange.safe_value(exchange_data, 'methods', {})
@@ -961,12 +1031,14 @@ class testMainClass:
961
1031
  is_disabled_c_sharp = exchange.safe_bool(result, 'disabledCS', False)
962
1032
  if is_disabled_c_sharp and (self.lang == 'C#'):
963
1033
  continue
1034
+ is_disabled_go = exchange.safe_bool(result, 'disabledGO', False)
1035
+ if is_disabled_go and (self.lang == 'GO'):
1036
+ continue
964
1037
  type = exchange.safe_string(exchange_data, 'outputType')
965
1038
  skip_keys = exchange.safe_value(exchange_data, 'skipKeys', [])
966
1039
  self.test_request_statically(exchange, method, result, type, skip_keys)
967
1040
  # reset options
968
- # exchange.options = exchange.deepExtend (oldExchangeOptions, {});
969
- exchange.extend_exchange_options(exchange.deep_extend(old_exchange_options, {}))
1041
+ exchange.options = exchange.convert_to_safe_dictionary(exchange.deep_extend(old_exchange_options, {}))
970
1042
  if not is_sync():
971
1043
  close(exchange)
972
1044
  return True # in c# methods that will be used with promiseAll need to return something
@@ -1012,6 +1084,9 @@ class testMainClass:
1012
1084
  continue
1013
1085
  if (test_name is not None) and (test_name != description):
1014
1086
  continue
1087
+ is_disabled_go = exchange.safe_bool(result, 'disabledGO', False)
1088
+ if is_disabled_go and (self.lang == 'GO'):
1089
+ continue
1015
1090
  skip_keys = exchange.safe_value(exchange_data, 'skipKeys', [])
1016
1091
  self.test_response_statically(exchange, method, skip_keys, result)
1017
1092
  # reset options
@@ -1034,14 +1109,35 @@ class testMainClass:
1034
1109
  sum = exchange.sum(sum, results_length)
1035
1110
  return sum
1036
1111
 
1112
+ def check_if_exchange_is_disabled(self, exchange_name, exchange_data):
1113
+ exchange = init_exchange('Exchange', {})
1114
+ is_disabled_py = exchange.safe_bool(exchange_data, 'disabledPy', False)
1115
+ if is_disabled_py and (self.lang == 'PY'):
1116
+ dump('[TEST_WARNING] Exchange ' + exchange_name + ' is disabled in python')
1117
+ return True
1118
+ is_disabled_php = exchange.safe_bool(exchange_data, 'disabledPHP', False)
1119
+ if is_disabled_php and (self.lang == 'PHP'):
1120
+ dump('[TEST_WARNING] Exchange ' + exchange_name + ' is disabled in php')
1121
+ return True
1122
+ is_disabled_c_sharp = exchange.safe_bool(exchange_data, 'disabledCS', False)
1123
+ if is_disabled_c_sharp and (self.lang == 'C#'):
1124
+ dump('[TEST_WARNING] Exchange ' + exchange_name + ' is disabled in c#')
1125
+ return True
1126
+ is_disabled_go = exchange.safe_bool(exchange_data, 'disabledGO', False)
1127
+ if is_disabled_go and (self.lang == 'GO'):
1128
+ dump('[TEST_WARNING] Exchange ' + exchange_name + ' is disabled in go')
1129
+ return True
1130
+ return False
1131
+
1037
1132
  def run_static_request_tests(self, target_exchange=None, test_name=None):
1038
1133
  self.run_static_tests('request', target_exchange, test_name)
1134
+ return True
1039
1135
 
1040
1136
  def run_static_tests(self, type, target_exchange=None, test_name=None):
1041
1137
  folder = get_root_dir() + './ts/src/test/static/' + type + '/'
1042
1138
  static_data = self.load_static_data(folder, target_exchange)
1043
1139
  if static_data is None:
1044
- return
1140
+ return True
1045
1141
  exchanges = list(static_data.keys())
1046
1142
  exchange = init_exchange('Exchange', {}) # tmp to do the calculations until we have the ast-transpiler transpiling this code
1047
1143
  promises = []
@@ -1053,13 +1149,24 @@ class testMainClass:
1053
1149
  for i in range(0, len(exchanges)):
1054
1150
  exchange_name = exchanges[i]
1055
1151
  exchange_data = static_data[exchange_name]
1152
+ disabled = self.check_if_exchange_is_disabled(exchange_name, exchange_data)
1153
+ if disabled:
1154
+ continue
1056
1155
  number_of_tests = self.get_number_of_tests_from_exchange(exchange, exchange_data, test_name)
1057
1156
  sum = exchange.sum(sum, number_of_tests)
1058
1157
  if type == 'request':
1059
1158
  promises.append(self.test_exchange_request_statically(exchange_name, exchange_data, test_name))
1060
1159
  else:
1061
1160
  promises.append(self.test_exchange_response_statically(exchange_name, exchange_data, test_name))
1062
- (promises)
1161
+ try:
1162
+ (promises)
1163
+ except Exception as e:
1164
+ if type == 'request':
1165
+ self.request_tests_failed = True
1166
+ else:
1167
+ self.response_tests_failed = True
1168
+ error_message = '[' + self.lang + '][STATIC_REQUEST]' + exception_message(e)
1169
+ dump('[TEST_FAILURE]' + error_message)
1063
1170
  if self.request_tests_failed or self.response_tests_failed:
1064
1171
  exit_script(1)
1065
1172
  else:
@@ -1072,20 +1179,24 @@ class testMainClass:
1072
1179
  # --- Init of mockResponses tests functions------------------------------------
1073
1180
  # -----------------------------------------------------------------------------
1074
1181
  self.run_static_tests('response', exchange_name, test)
1182
+ return True
1075
1183
 
1076
1184
  def run_broker_id_tests(self):
1077
1185
  # -----------------------------------------------------------------------------
1078
1186
  # --- Init of brokerId tests functions-----------------------------------------
1079
1187
  # -----------------------------------------------------------------------------
1080
- 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()]
1188
+ 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()]
1081
1189
  (promises)
1082
1190
  success_message = '[' + self.lang + '][TEST_SUCCESS] brokerId tests passed.'
1083
1191
  dump('[INFO]' + success_message)
1084
1192
  exit_script(0)
1193
+ return True
1085
1194
 
1086
1195
  def test_binance(self):
1087
1196
  exchange = self.init_offline_exchange('binance')
1088
- spot_id = 'x-R4BD3S82'
1197
+ spot_id = 'x-TKT5PX2F'
1198
+ swap_id = 'x-cvBPrNm9'
1199
+ inverse_swap_id = 'x-xcKtGhcu'
1089
1200
  spot_order_request = None
1090
1201
  try:
1091
1202
  exchange.create_order('BTC/USDT', 'limit', 'buy', 1, 20000)
@@ -1094,7 +1205,6 @@ class testMainClass:
1094
1205
  client_order_id = spot_order_request['newClientOrderId']
1095
1206
  spot_id_string = str(spot_id)
1096
1207
  assert client_order_id.startswith(spot_id_string), 'binance - spot clientOrderId: ' + client_order_id + ' does not start with spotId' + spot_id_string
1097
- swap_id = 'x-xcKtGhcu'
1098
1208
  swap_order_request = None
1099
1209
  try:
1100
1210
  exchange.create_order('BTC/USDT:USDT', 'limit', 'buy', 1, 20000)
@@ -1105,11 +1215,35 @@ class testMainClass:
1105
1215
  exchange.create_order('BTC/USD:BTC', 'limit', 'buy', 1, 20000)
1106
1216
  except Exception as e:
1107
1217
  swap_inverse_order_request = self.urlencoded_to_dict(exchange.last_request_body)
1218
+ # linear swap
1108
1219
  client_order_id_swap = swap_order_request['newClientOrderId']
1109
1220
  swap_id_string = str(swap_id)
1110
1221
  assert client_order_id_swap.startswith(swap_id_string), 'binance - swap clientOrderId: ' + client_order_id_swap + ' does not start with swapId' + swap_id_string
1222
+ # inverse swap
1111
1223
  client_order_id_inverse = swap_inverse_order_request['newClientOrderId']
1112
- assert client_order_id_inverse.startswith(swap_id_string), 'binance - swap clientOrderIdInverse: ' + client_order_id_inverse + ' does not start with swapId' + swap_id_string
1224
+ assert client_order_id_inverse.startswith(inverse_swap_id), 'binance - swap clientOrderIdInverse: ' + client_order_id_inverse + ' does not start with swapId' + inverse_swap_id
1225
+ create_orders_request = None
1226
+ try:
1227
+ orders = [{
1228
+ 'symbol': 'BTC/USDT:USDT',
1229
+ 'type': 'limit',
1230
+ 'side': 'sell',
1231
+ 'amount': 1,
1232
+ 'price': 100000,
1233
+ }, {
1234
+ 'symbol': 'BTC/USDT:USDT',
1235
+ 'type': 'market',
1236
+ 'side': 'buy',
1237
+ 'amount': 1,
1238
+ }]
1239
+ exchange.create_orders(orders)
1240
+ except Exception as e:
1241
+ create_orders_request = self.urlencoded_to_dict(exchange.last_request_body)
1242
+ batch_orders = create_orders_request['batchOrders']
1243
+ for i in range(0, len(batch_orders)):
1244
+ current = batch_orders[i]
1245
+ current_client_order_id = current['newClientOrderId']
1246
+ assert current_client_order_id.startswith(swap_id_string), 'binance createOrders - clientOrderId: ' + current_client_order_id + ' does not start with swapId' + swap_id_string
1113
1247
  if not is_sync():
1114
1248
  close(exchange)
1115
1249
  return True
@@ -1273,7 +1407,7 @@ class testMainClass:
1273
1407
  try:
1274
1408
  exchange.create_order('BTC/USDT', 'limit', 'buy', 1, 20000)
1275
1409
  except Exception as e:
1276
- spot_order_request = self.urlencoded_to_dict(exchange.last_request_body)
1410
+ spot_order_request = json_parse(exchange.last_request_body)
1277
1411
  broker_id = spot_order_request['broker_id']
1278
1412
  id_string = str(id)
1279
1413
  assert broker_id.startswith(id_string), 'woo - broker_id: ' + broker_id + ' does not start with id: ' + id_string
@@ -1335,6 +1469,7 @@ class testMainClass:
1335
1469
  assert req_headers['X-SOURCE-KEY'] == id, 'bingx - id: ' + id + ' not in headers.'
1336
1470
  if not is_sync():
1337
1471
  close(exchange)
1472
+ return True
1338
1473
 
1339
1474
  def test_phemex(self):
1340
1475
  exchange = self.init_offline_exchange('phemex')
@@ -1349,6 +1484,7 @@ class testMainClass:
1349
1484
  assert client_order_id.startswith(id_string), 'phemex - clOrdID: ' + client_order_id + ' does not start with id: ' + id_string
1350
1485
  if not is_sync():
1351
1486
  close(exchange)
1487
+ return True
1352
1488
 
1353
1489
  def test_blofin(self):
1354
1490
  exchange = self.init_offline_exchange('blofin')
@@ -1363,20 +1499,24 @@ class testMainClass:
1363
1499
  assert broker_id.startswith(id_string), 'blofin - brokerId: ' + broker_id + ' does not start with id: ' + id_string
1364
1500
  if not is_sync():
1365
1501
  close(exchange)
1502
+ return True
1366
1503
 
1367
- def test_hyperliquid(self):
1368
- exchange = self.init_offline_exchange('hyperliquid')
1369
- id = '1'
1370
- request = None
1371
- try:
1372
- exchange.create_order('SOL/USDC:USDC', 'limit', 'buy', 1, 100)
1373
- except Exception as e:
1374
- request = json_parse(exchange.last_request_body)
1375
- broker_id = str((request['action']['brokerCode']))
1376
- assert broker_id == id, 'hyperliquid - brokerId: ' + broker_id + ' does not start with id: ' + id
1377
- if not is_sync():
1378
- close(exchange)
1379
-
1504
+ # testHyperliquid () {
1505
+ # const exchange = this.initOfflineExchange ('hyperliquid');
1506
+ # const id = '1';
1507
+ # let request = undefined;
1508
+ # try {
1509
+ # exchange.createOrder ('SOL/USDC:USDC', 'limit', 'buy', 1, 100);
1510
+ # } catch (e) {
1511
+ # request = jsonParse (exchange.last_request_body);
1512
+ # }
1513
+ # const brokerId = (request['action']['brokerCode']).toString ();
1514
+ # assert (brokerId === id, 'hyperliquid - brokerId: ' + brokerId + ' does not start with id: ' + id);
1515
+ # if (!isSync ()) {
1516
+ # close (exchange);
1517
+ # }
1518
+ # return true;
1519
+ # }
1380
1520
  def test_coinbaseinternational(self):
1381
1521
  exchange = self.init_offline_exchange('coinbaseinternational')
1382
1522
  exchange.options['portfolio'] = 'random'
@@ -1553,3 +1693,67 @@ class testMainClass:
1553
1693
  if not is_sync():
1554
1694
  close(exchange)
1555
1695
  return True
1696
+
1697
+ def test_defx(self):
1698
+ exchange = self.init_offline_exchange('defx')
1699
+ req_headers = None
1700
+ try:
1701
+ exchange.create_order('DOGE/USDC:USDC', 'limit', 'buy', 100, 1)
1702
+ except Exception as e:
1703
+ # we expect an error here, we're only interested in the headers
1704
+ req_headers = exchange.last_request_headers
1705
+ id = 'ccxt'
1706
+ assert req_headers['X-DEFX-SOURCE'] == id, 'defx - id: ' + id + ' not in headers.'
1707
+ if not is_sync():
1708
+ close(exchange)
1709
+ return True
1710
+
1711
+ def test_cryptomus(self):
1712
+ exchange = self.init_offline_exchange('cryptomus')
1713
+ request = None
1714
+ try:
1715
+ exchange.create_order('BTC/USDT', 'limit', 'sell', 1, 20000)
1716
+ except Exception as e:
1717
+ request = json_parse(exchange.last_request_body)
1718
+ tag = 'ccxt'
1719
+ assert request['tag'] == tag, 'cryptomus - tag: ' + tag + ' not in request.'
1720
+ if not is_sync():
1721
+ close(exchange)
1722
+ return True
1723
+
1724
+ def test_derive(self):
1725
+ exchange = self.init_offline_exchange('derive')
1726
+ id = '0x0ad42b8e602c2d3d475ae52d678cf63d84ab2749'
1727
+ assert exchange.options['id'] == id, 'derive - id: ' + id + ' not in options'
1728
+ request = None
1729
+ try:
1730
+ params = {
1731
+ 'subaccount_id': 1234,
1732
+ 'max_fee': 10,
1733
+ 'deriveWalletAddress': '0x0ad42b8e602c2d3d475ae52d678cf63d84ab2749',
1734
+ }
1735
+ exchange.walletAddress = '0x0ad42b8e602c2d3d475ae52d678cf63d84ab2749'
1736
+ exchange.privateKey = '0x7b77bb7b20e92bbb85f2a22b330b896959229a5790e35f2f290922de3fb22ad5'
1737
+ exchange.create_order('LBTC/USDC', 'limit', 'sell', 0.01, 3000, params)
1738
+ except Exception as e:
1739
+ request = json_parse(exchange.last_request_body)
1740
+ assert request['referral_code'] == id, 'derive - referral_code: ' + id + ' not in request.'
1741
+ if not is_sync():
1742
+ close(exchange)
1743
+ return True
1744
+
1745
+ def test_mode_trade(self):
1746
+ exchange = self.init_offline_exchange('modetrade')
1747
+ exchange.secret = 'secretsecretsecretsecretsecretsecretsecrets'
1748
+ id = 'CCXTMODE'
1749
+ exchange.load_markets()
1750
+ request = None
1751
+ try:
1752
+ exchange.create_order('BTC/USDC:USDC', 'limit', 'buy', 1, 20000)
1753
+ except Exception as e:
1754
+ request = json_parse(exchange.last_request_body)
1755
+ broker_id = request['order_tag']
1756
+ assert broker_id == id, 'modetrade - id: ' + id + ' different from broker_id: ' + broker_id
1757
+ if not is_sync():
1758
+ close(exchange)
1759
+ return True