ccxt 4.2.77__py2.py3-none-any.whl → 4.4.48__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 (546) hide show
  1. ccxt/__init__.py +36 -14
  2. ccxt/abstract/alpaca.py +4 -0
  3. ccxt/abstract/bigone.py +1 -1
  4. ccxt/abstract/binance.py +112 -48
  5. ccxt/abstract/binancecoinm.py +112 -48
  6. ccxt/abstract/binanceus.py +147 -83
  7. ccxt/abstract/binanceusdm.py +112 -48
  8. ccxt/abstract/bingx.py +133 -78
  9. ccxt/abstract/bitbank.py +5 -0
  10. ccxt/abstract/bitfinex.py +136 -65
  11. ccxt/abstract/bitfinex1.py +69 -0
  12. ccxt/abstract/bitflyer.py +1 -0
  13. ccxt/abstract/bitget.py +8 -1
  14. ccxt/abstract/bitmart.py +13 -1
  15. ccxt/abstract/bitopro.py +1 -0
  16. ccxt/abstract/bitpanda.py +0 -12
  17. ccxt/abstract/bitrue.py +3 -3
  18. ccxt/abstract/bitstamp.py +26 -3
  19. ccxt/abstract/blofin.py +24 -0
  20. ccxt/abstract/btcbox.py +1 -0
  21. ccxt/abstract/bybit.py +29 -14
  22. ccxt/abstract/cex.py +28 -29
  23. ccxt/abstract/coinbase.py +6 -0
  24. ccxt/abstract/coinbaseadvanced.py +94 -0
  25. ccxt/abstract/{coinbasepro.py → coinbaseexchange.py} +1 -0
  26. ccxt/abstract/coinbaseinternational.py +1 -1
  27. ccxt/abstract/coincatch.py +94 -0
  28. ccxt/abstract/coinex.py +233 -123
  29. ccxt/abstract/coinmetro.py +1 -0
  30. ccxt/abstract/cryptocom.py +14 -0
  31. ccxt/abstract/defx.py +69 -0
  32. ccxt/abstract/deribit.py +1 -0
  33. ccxt/abstract/digifinex.py +1 -0
  34. ccxt/abstract/ellipx.py +25 -0
  35. ccxt/abstract/gate.py +20 -0
  36. ccxt/abstract/gateio.py +20 -0
  37. ccxt/abstract/gemini.py +1 -0
  38. ccxt/abstract/hashkey.py +67 -0
  39. ccxt/abstract/hyperliquid.py +1 -1
  40. ccxt/abstract/independentreserve.py +6 -0
  41. ccxt/abstract/kraken.py +4 -3
  42. ccxt/abstract/krakenfutures.py +4 -0
  43. ccxt/abstract/kucoin.py +24 -0
  44. ccxt/abstract/kucoinfutures.py +34 -0
  45. ccxt/abstract/luno.py +2 -0
  46. ccxt/abstract/mexc.py +4 -0
  47. ccxt/abstract/myokx.py +340 -0
  48. ccxt/abstract/oceanex.py +5 -0
  49. ccxt/abstract/okx.py +30 -0
  50. ccxt/abstract/onetrading.py +0 -12
  51. ccxt/abstract/oxfun.py +34 -0
  52. ccxt/abstract/paradex.py +40 -0
  53. ccxt/abstract/phemex.py +1 -0
  54. ccxt/abstract/upbit.py +4 -0
  55. ccxt/abstract/vertex.py +19 -0
  56. ccxt/abstract/whitebit.py +31 -1
  57. ccxt/abstract/woo.py +6 -2
  58. ccxt/abstract/woofipro.py +119 -0
  59. ccxt/abstract/xt.py +153 -0
  60. ccxt/abstract/zonda.py +6 -0
  61. ccxt/ace.py +164 -60
  62. ccxt/alpaca.py +727 -63
  63. ccxt/ascendex.py +395 -249
  64. ccxt/async_support/__init__.py +36 -14
  65. ccxt/async_support/ace.py +164 -60
  66. ccxt/async_support/alpaca.py +727 -63
  67. ccxt/async_support/ascendex.py +396 -249
  68. ccxt/async_support/base/exchange.py +531 -155
  69. ccxt/async_support/base/ws/aiohttp_client.py +28 -5
  70. ccxt/async_support/base/ws/cache.py +3 -2
  71. ccxt/async_support/base/ws/client.py +26 -5
  72. ccxt/async_support/base/ws/fast_client.py +4 -3
  73. ccxt/async_support/base/ws/functions.py +1 -1
  74. ccxt/async_support/base/ws/future.py +40 -31
  75. ccxt/async_support/base/ws/order_book_side.py +3 -0
  76. ccxt/async_support/bequant.py +1 -1
  77. ccxt/async_support/bigone.py +329 -202
  78. ccxt/async_support/binance.py +3030 -1087
  79. ccxt/async_support/binancecoinm.py +2 -1
  80. ccxt/async_support/binanceus.py +12 -1
  81. ccxt/async_support/binanceusdm.py +3 -1
  82. ccxt/async_support/bingx.py +3104 -880
  83. ccxt/async_support/bit2c.py +119 -38
  84. ccxt/async_support/bitbank.py +215 -76
  85. ccxt/async_support/bitbns.py +124 -53
  86. ccxt/async_support/bitfinex.py +3236 -1078
  87. ccxt/async_support/bitfinex1.py +1711 -0
  88. ccxt/async_support/bitflyer.py +238 -49
  89. ccxt/async_support/bitget.py +1513 -563
  90. ccxt/async_support/bithumb.py +199 -65
  91. ccxt/async_support/bitmart.py +1320 -435
  92. ccxt/async_support/bitmex.py +308 -111
  93. ccxt/async_support/bitopro.py +256 -96
  94. ccxt/async_support/bitrue.py +365 -233
  95. ccxt/async_support/bitso.py +201 -89
  96. ccxt/async_support/bitstamp.py +438 -269
  97. ccxt/async_support/bitteam.py +179 -73
  98. ccxt/async_support/bitvavo.py +180 -70
  99. ccxt/async_support/bl3p.py +92 -25
  100. ccxt/async_support/blockchaincom.py +193 -79
  101. ccxt/async_support/blofin.py +392 -148
  102. ccxt/async_support/btcalpha.py +161 -55
  103. ccxt/async_support/btcbox.py +250 -34
  104. ccxt/async_support/btcmarkets.py +232 -85
  105. ccxt/async_support/btcturk.py +159 -60
  106. ccxt/async_support/bybit.py +2231 -1193
  107. ccxt/async_support/cex.py +1409 -1329
  108. ccxt/async_support/coinbase.py +1454 -287
  109. ccxt/async_support/coinbaseadvanced.py +17 -0
  110. ccxt/async_support/{coinbasepro.py → coinbaseexchange.py} +233 -99
  111. ccxt/async_support/coinbaseinternational.py +428 -88
  112. ccxt/async_support/coincatch.py +5152 -0
  113. ccxt/async_support/coincheck.py +121 -38
  114. ccxt/async_support/coinex.py +4020 -3339
  115. ccxt/async_support/coinlist.py +273 -116
  116. ccxt/async_support/coinmate.py +204 -97
  117. ccxt/async_support/coinmetro.py +203 -110
  118. ccxt/async_support/coinone.py +142 -68
  119. ccxt/async_support/coinsph.py +206 -89
  120. ccxt/async_support/coinspot.py +137 -62
  121. ccxt/async_support/cryptocom.py +515 -185
  122. ccxt/async_support/currencycom.py +203 -85
  123. ccxt/async_support/defx.py +2066 -0
  124. ccxt/async_support/delta.py +404 -109
  125. ccxt/async_support/deribit.py +557 -323
  126. ccxt/async_support/digifinex.py +340 -223
  127. ccxt/async_support/ellipx.py +1826 -0
  128. ccxt/async_support/exmo.py +259 -128
  129. ccxt/async_support/gate.py +1472 -463
  130. ccxt/async_support/gemini.py +206 -84
  131. ccxt/async_support/hashkey.py +4164 -0
  132. ccxt/async_support/hitbtc.py +334 -178
  133. ccxt/async_support/hollaex.py +134 -83
  134. ccxt/async_support/htx.py +1095 -563
  135. ccxt/async_support/huobijp.py +105 -56
  136. ccxt/async_support/hyperliquid.py +1633 -268
  137. ccxt/async_support/idex.py +148 -95
  138. ccxt/async_support/independentreserve.py +236 -31
  139. ccxt/async_support/indodax.py +165 -62
  140. ccxt/async_support/kraken.py +871 -354
  141. ccxt/async_support/krakenfutures.py +324 -100
  142. ccxt/async_support/kucoin.py +917 -357
  143. ccxt/async_support/kucoinfutures.py +1004 -149
  144. ccxt/async_support/kuna.py +138 -106
  145. ccxt/async_support/latoken.py +135 -79
  146. ccxt/async_support/lbank.py +290 -113
  147. ccxt/async_support/luno.py +112 -62
  148. ccxt/async_support/lykke.py +104 -55
  149. ccxt/async_support/mercado.py +36 -29
  150. ccxt/async_support/mexc.py +995 -429
  151. ccxt/async_support/myokx.py +43 -0
  152. ccxt/async_support/ndax.py +163 -82
  153. ccxt/async_support/novadax.py +121 -75
  154. ccxt/async_support/oceanex.py +175 -59
  155. ccxt/async_support/okcoin.py +222 -163
  156. ccxt/async_support/okx.py +1776 -454
  157. ccxt/async_support/onetrading.py +132 -414
  158. ccxt/async_support/oxfun.py +2832 -0
  159. ccxt/async_support/p2b.py +79 -51
  160. ccxt/async_support/paradex.py +2017 -0
  161. ccxt/async_support/paymium.py +56 -32
  162. ccxt/async_support/phemex.py +572 -196
  163. ccxt/async_support/poloniex.py +218 -95
  164. ccxt/async_support/poloniexfutures.py +260 -92
  165. ccxt/async_support/probit.py +143 -110
  166. ccxt/async_support/timex.py +123 -70
  167. ccxt/async_support/tokocrypto.py +129 -93
  168. ccxt/async_support/tradeogre.py +39 -25
  169. ccxt/async_support/upbit.py +322 -113
  170. ccxt/async_support/vertex.py +2983 -0
  171. ccxt/async_support/wavesexchange.py +227 -173
  172. ccxt/async_support/wazirx.py +145 -65
  173. ccxt/async_support/whitebit.py +533 -138
  174. ccxt/async_support/woo.py +1137 -296
  175. ccxt/async_support/woofipro.py +2716 -0
  176. ccxt/async_support/xt.py +4628 -0
  177. ccxt/async_support/yobit.py +160 -92
  178. ccxt/async_support/zaif.py +80 -33
  179. ccxt/async_support/zonda.py +140 -69
  180. ccxt/base/errors.py +51 -20
  181. ccxt/base/exchange.py +1722 -480
  182. ccxt/base/precise.py +10 -0
  183. ccxt/base/types.py +223 -4
  184. ccxt/bequant.py +1 -1
  185. ccxt/bigone.py +329 -202
  186. ccxt/binance.py +3030 -1087
  187. ccxt/binancecoinm.py +2 -1
  188. ccxt/binanceus.py +12 -1
  189. ccxt/binanceusdm.py +3 -1
  190. ccxt/bingx.py +3104 -880
  191. ccxt/bit2c.py +119 -38
  192. ccxt/bitbank.py +215 -76
  193. ccxt/bitbns.py +124 -53
  194. ccxt/bitfinex.py +3235 -1078
  195. ccxt/bitfinex1.py +1710 -0
  196. ccxt/bitflyer.py +238 -49
  197. ccxt/bitget.py +1513 -563
  198. ccxt/bithumb.py +198 -65
  199. ccxt/bitmart.py +1320 -435
  200. ccxt/bitmex.py +308 -111
  201. ccxt/bitopro.py +256 -96
  202. ccxt/bitrue.py +365 -233
  203. ccxt/bitso.py +201 -89
  204. ccxt/bitstamp.py +438 -269
  205. ccxt/bitteam.py +179 -73
  206. ccxt/bitvavo.py +180 -70
  207. ccxt/bl3p.py +92 -25
  208. ccxt/blockchaincom.py +193 -79
  209. ccxt/blofin.py +392 -148
  210. ccxt/btcalpha.py +161 -55
  211. ccxt/btcbox.py +250 -34
  212. ccxt/btcmarkets.py +232 -85
  213. ccxt/btcturk.py +159 -60
  214. ccxt/bybit.py +2231 -1193
  215. ccxt/cex.py +1408 -1329
  216. ccxt/coinbase.py +1454 -287
  217. ccxt/coinbaseadvanced.py +17 -0
  218. ccxt/{coinbasepro.py → coinbaseexchange.py} +233 -99
  219. ccxt/coinbaseinternational.py +428 -88
  220. ccxt/coincatch.py +5152 -0
  221. ccxt/coincheck.py +121 -38
  222. ccxt/coinex.py +4020 -3339
  223. ccxt/coinlist.py +273 -116
  224. ccxt/coinmate.py +204 -97
  225. ccxt/coinmetro.py +203 -110
  226. ccxt/coinone.py +142 -68
  227. ccxt/coinsph.py +206 -89
  228. ccxt/coinspot.py +137 -62
  229. ccxt/cryptocom.py +515 -185
  230. ccxt/currencycom.py +203 -85
  231. ccxt/defx.py +2065 -0
  232. ccxt/delta.py +404 -109
  233. ccxt/deribit.py +557 -323
  234. ccxt/digifinex.py +340 -223
  235. ccxt/ellipx.py +1826 -0
  236. ccxt/exmo.py +259 -128
  237. ccxt/gate.py +1472 -463
  238. ccxt/gemini.py +206 -84
  239. ccxt/hashkey.py +4164 -0
  240. ccxt/hitbtc.py +334 -178
  241. ccxt/hollaex.py +134 -83
  242. ccxt/htx.py +1095 -563
  243. ccxt/huobijp.py +105 -56
  244. ccxt/hyperliquid.py +1632 -268
  245. ccxt/idex.py +148 -95
  246. ccxt/independentreserve.py +235 -31
  247. ccxt/indodax.py +165 -62
  248. ccxt/kraken.py +871 -354
  249. ccxt/krakenfutures.py +324 -100
  250. ccxt/kucoin.py +917 -357
  251. ccxt/kucoinfutures.py +1004 -149
  252. ccxt/kuna.py +138 -106
  253. ccxt/latoken.py +135 -79
  254. ccxt/lbank.py +290 -113
  255. ccxt/luno.py +112 -62
  256. ccxt/lykke.py +104 -55
  257. ccxt/mercado.py +36 -29
  258. ccxt/mexc.py +994 -429
  259. ccxt/myokx.py +43 -0
  260. ccxt/ndax.py +163 -82
  261. ccxt/novadax.py +121 -75
  262. ccxt/oceanex.py +175 -59
  263. ccxt/okcoin.py +222 -163
  264. ccxt/okx.py +1776 -454
  265. ccxt/onetrading.py +132 -414
  266. ccxt/oxfun.py +2831 -0
  267. ccxt/p2b.py +79 -51
  268. ccxt/paradex.py +2017 -0
  269. ccxt/paymium.py +56 -32
  270. ccxt/phemex.py +572 -196
  271. ccxt/poloniex.py +218 -95
  272. ccxt/poloniexfutures.py +260 -92
  273. ccxt/pro/__init__.py +29 -5
  274. ccxt/pro/alpaca.py +32 -17
  275. ccxt/pro/ascendex.py +62 -14
  276. ccxt/pro/bequant.py +4 -0
  277. ccxt/pro/binance.py +1596 -329
  278. ccxt/pro/binancecoinm.py +1 -0
  279. ccxt/pro/binanceus.py +2 -9
  280. ccxt/pro/binanceusdm.py +2 -0
  281. ccxt/pro/bingx.py +527 -134
  282. ccxt/pro/bitcoincom.py +4 -1
  283. ccxt/pro/bitfinex.py +731 -266
  284. ccxt/pro/bitfinex1.py +635 -0
  285. ccxt/pro/bitget.py +726 -357
  286. ccxt/pro/bithumb.py +380 -0
  287. ccxt/pro/bitmart.py +138 -39
  288. ccxt/pro/bitmex.py +199 -40
  289. ccxt/pro/bitopro.py +25 -13
  290. ccxt/pro/bitrue.py +31 -32
  291. ccxt/pro/bitstamp.py +7 -6
  292. ccxt/pro/bitvavo.py +203 -81
  293. ccxt/pro/blockchaincom.py +30 -17
  294. ccxt/pro/blofin.py +692 -0
  295. ccxt/pro/bybit.py +791 -82
  296. ccxt/pro/cex.py +99 -51
  297. ccxt/pro/coinbase.py +220 -30
  298. ccxt/{async_support/hitbtc3.py → pro/coinbaseadvanced.py} +5 -5
  299. ccxt/pro/{coinbasepro.py → coinbaseexchange.py} +19 -19
  300. ccxt/pro/coinbaseinternational.py +193 -30
  301. ccxt/pro/coincatch.py +1464 -0
  302. ccxt/pro/coincheck.py +11 -6
  303. ccxt/pro/coinex.py +965 -665
  304. ccxt/pro/coinone.py +17 -10
  305. ccxt/pro/cryptocom.py +446 -66
  306. ccxt/pro/currencycom.py +11 -10
  307. ccxt/pro/defx.py +832 -0
  308. ccxt/pro/deribit.py +167 -31
  309. ccxt/pro/exmo.py +252 -20
  310. ccxt/pro/gate.py +729 -64
  311. ccxt/pro/gemini.py +44 -26
  312. ccxt/pro/hashkey.py +802 -0
  313. ccxt/pro/hitbtc.py +208 -103
  314. ccxt/pro/hollaex.py +25 -9
  315. ccxt/pro/htx.py +83 -39
  316. ccxt/pro/huobijp.py +17 -16
  317. ccxt/pro/hyperliquid.py +502 -31
  318. ccxt/pro/idex.py +28 -13
  319. ccxt/pro/independentreserve.py +21 -16
  320. ccxt/pro/kraken.py +298 -51
  321. ccxt/pro/krakenfutures.py +166 -75
  322. ccxt/pro/kucoin.py +395 -77
  323. ccxt/pro/kucoinfutures.py +400 -99
  324. ccxt/pro/lbank.py +52 -31
  325. ccxt/pro/luno.py +12 -10
  326. ccxt/pro/mexc.py +400 -50
  327. ccxt/pro/myokx.py +28 -0
  328. ccxt/pro/ndax.py +25 -12
  329. ccxt/pro/okcoin.py +28 -9
  330. ccxt/pro/okx.py +935 -124
  331. ccxt/pro/onetrading.py +41 -24
  332. ccxt/pro/oxfun.py +1054 -0
  333. ccxt/pro/p2b.py +100 -24
  334. ccxt/pro/paradex.py +352 -0
  335. ccxt/pro/phemex.py +92 -33
  336. ccxt/pro/poloniex.py +128 -49
  337. ccxt/pro/poloniexfutures.py +53 -32
  338. ccxt/pro/probit.py +92 -85
  339. ccxt/pro/upbit.py +401 -8
  340. ccxt/pro/vertex.py +943 -0
  341. ccxt/pro/wazirx.py +46 -28
  342. ccxt/pro/whitebit.py +65 -12
  343. ccxt/pro/woo.py +437 -65
  344. ccxt/pro/woofipro.py +1271 -0
  345. ccxt/pro/xt.py +1067 -0
  346. ccxt/probit.py +143 -110
  347. ccxt/static_dependencies/__init__.py +1 -1
  348. ccxt/static_dependencies/lark/__init__.py +38 -0
  349. ccxt/static_dependencies/lark/__pyinstaller/__init__.py +6 -0
  350. ccxt/static_dependencies/lark/__pyinstaller/hook-lark.py +14 -0
  351. ccxt/static_dependencies/lark/ast_utils.py +59 -0
  352. ccxt/static_dependencies/lark/common.py +86 -0
  353. ccxt/static_dependencies/lark/exceptions.py +292 -0
  354. ccxt/static_dependencies/lark/grammar.py +130 -0
  355. ccxt/static_dependencies/lark/grammars/__init__.py +0 -0
  356. ccxt/static_dependencies/lark/indenter.py +143 -0
  357. ccxt/static_dependencies/lark/lark.py +658 -0
  358. ccxt/static_dependencies/lark/lexer.py +678 -0
  359. ccxt/static_dependencies/lark/load_grammar.py +1428 -0
  360. ccxt/static_dependencies/lark/parse_tree_builder.py +391 -0
  361. ccxt/static_dependencies/lark/parser_frontends.py +257 -0
  362. ccxt/static_dependencies/lark/parsers/__init__.py +0 -0
  363. ccxt/static_dependencies/lark/parsers/cyk.py +340 -0
  364. ccxt/static_dependencies/lark/parsers/earley.py +314 -0
  365. ccxt/static_dependencies/lark/parsers/earley_common.py +42 -0
  366. ccxt/static_dependencies/lark/parsers/earley_forest.py +801 -0
  367. ccxt/static_dependencies/lark/parsers/grammar_analysis.py +203 -0
  368. ccxt/static_dependencies/lark/parsers/lalr_analysis.py +332 -0
  369. ccxt/static_dependencies/lark/parsers/lalr_interactive_parser.py +158 -0
  370. ccxt/static_dependencies/lark/parsers/lalr_parser.py +122 -0
  371. ccxt/static_dependencies/lark/parsers/lalr_parser_state.py +110 -0
  372. ccxt/static_dependencies/lark/parsers/xearley.py +165 -0
  373. ccxt/static_dependencies/lark/py.typed +0 -0
  374. ccxt/static_dependencies/lark/reconstruct.py +107 -0
  375. ccxt/static_dependencies/lark/tools/__init__.py +70 -0
  376. ccxt/static_dependencies/lark/tools/nearley.py +202 -0
  377. ccxt/static_dependencies/lark/tools/serialize.py +32 -0
  378. ccxt/static_dependencies/lark/tools/standalone.py +196 -0
  379. ccxt/static_dependencies/lark/tree.py +267 -0
  380. ccxt/static_dependencies/lark/tree_matcher.py +186 -0
  381. ccxt/static_dependencies/lark/tree_templates.py +180 -0
  382. ccxt/static_dependencies/lark/utils.py +343 -0
  383. ccxt/static_dependencies/lark/visitors.py +596 -0
  384. ccxt/static_dependencies/marshmallow/__init__.py +81 -0
  385. ccxt/static_dependencies/marshmallow/base.py +65 -0
  386. ccxt/static_dependencies/marshmallow/class_registry.py +94 -0
  387. ccxt/static_dependencies/marshmallow/decorators.py +231 -0
  388. ccxt/static_dependencies/marshmallow/error_store.py +60 -0
  389. ccxt/static_dependencies/marshmallow/exceptions.py +71 -0
  390. ccxt/static_dependencies/marshmallow/fields.py +2114 -0
  391. ccxt/static_dependencies/marshmallow/orderedset.py +89 -0
  392. ccxt/static_dependencies/marshmallow/py.typed +0 -0
  393. ccxt/static_dependencies/marshmallow/schema.py +1228 -0
  394. ccxt/static_dependencies/marshmallow/types.py +12 -0
  395. ccxt/static_dependencies/marshmallow/utils.py +378 -0
  396. ccxt/static_dependencies/marshmallow/validate.py +678 -0
  397. ccxt/static_dependencies/marshmallow/warnings.py +2 -0
  398. ccxt/static_dependencies/marshmallow_dataclass/__init__.py +1047 -0
  399. ccxt/static_dependencies/marshmallow_dataclass/collection_field.py +51 -0
  400. ccxt/static_dependencies/marshmallow_dataclass/lazy_class_attribute.py +45 -0
  401. ccxt/static_dependencies/marshmallow_dataclass/mypy.py +71 -0
  402. ccxt/static_dependencies/marshmallow_dataclass/py.typed +0 -0
  403. ccxt/static_dependencies/marshmallow_dataclass/typing.py +14 -0
  404. ccxt/static_dependencies/marshmallow_dataclass/union_field.py +82 -0
  405. ccxt/static_dependencies/marshmallow_oneofschema/__init__.py +1 -0
  406. ccxt/static_dependencies/marshmallow_oneofschema/one_of_schema.py +193 -0
  407. ccxt/static_dependencies/marshmallow_oneofschema/py.typed +0 -0
  408. ccxt/static_dependencies/starknet/__init__.py +0 -0
  409. ccxt/static_dependencies/starknet/cairo/__init__.py +0 -0
  410. ccxt/static_dependencies/starknet/cairo/data_types.py +123 -0
  411. ccxt/static_dependencies/starknet/cairo/deprecated_parse/__init__.py +0 -0
  412. ccxt/static_dependencies/starknet/cairo/deprecated_parse/cairo_types.py +77 -0
  413. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser.py +46 -0
  414. ccxt/static_dependencies/starknet/cairo/deprecated_parse/parser_transformer.py +138 -0
  415. ccxt/static_dependencies/starknet/cairo/felt.py +64 -0
  416. ccxt/static_dependencies/starknet/cairo/type_parser.py +121 -0
  417. ccxt/static_dependencies/starknet/cairo/v1/__init__.py +0 -0
  418. ccxt/static_dependencies/starknet/cairo/v1/type_parser.py +59 -0
  419. ccxt/static_dependencies/starknet/cairo/v2/__init__.py +0 -0
  420. ccxt/static_dependencies/starknet/cairo/v2/type_parser.py +77 -0
  421. ccxt/static_dependencies/starknet/ccxt_utils.py +7 -0
  422. ccxt/static_dependencies/starknet/common.py +15 -0
  423. ccxt/static_dependencies/starknet/constants.py +39 -0
  424. ccxt/static_dependencies/starknet/hash/__init__.py +0 -0
  425. ccxt/static_dependencies/starknet/hash/address.py +79 -0
  426. ccxt/static_dependencies/starknet/hash/compiled_class_hash_objects.py +111 -0
  427. ccxt/static_dependencies/starknet/hash/selector.py +16 -0
  428. ccxt/static_dependencies/starknet/hash/storage.py +12 -0
  429. ccxt/static_dependencies/starknet/hash/utils.py +78 -0
  430. ccxt/static_dependencies/starknet/models/__init__.py +0 -0
  431. ccxt/static_dependencies/starknet/models/typed_data.py +45 -0
  432. ccxt/static_dependencies/starknet/serialization/__init__.py +24 -0
  433. ccxt/static_dependencies/starknet/serialization/_calldata_reader.py +40 -0
  434. ccxt/static_dependencies/starknet/serialization/_context.py +142 -0
  435. ccxt/static_dependencies/starknet/serialization/data_serializers/__init__.py +10 -0
  436. ccxt/static_dependencies/starknet/serialization/data_serializers/_common.py +82 -0
  437. ccxt/static_dependencies/starknet/serialization/data_serializers/array_serializer.py +43 -0
  438. ccxt/static_dependencies/starknet/serialization/data_serializers/bool_serializer.py +37 -0
  439. ccxt/static_dependencies/starknet/serialization/data_serializers/byte_array_serializer.py +66 -0
  440. ccxt/static_dependencies/starknet/serialization/data_serializers/cairo_data_serializer.py +71 -0
  441. ccxt/static_dependencies/starknet/serialization/data_serializers/enum_serializer.py +71 -0
  442. ccxt/static_dependencies/starknet/serialization/data_serializers/felt_serializer.py +50 -0
  443. ccxt/static_dependencies/starknet/serialization/data_serializers/named_tuple_serializer.py +58 -0
  444. ccxt/static_dependencies/starknet/serialization/data_serializers/option_serializer.py +43 -0
  445. ccxt/static_dependencies/starknet/serialization/data_serializers/output_serializer.py +40 -0
  446. ccxt/static_dependencies/starknet/serialization/data_serializers/payload_serializer.py +72 -0
  447. ccxt/static_dependencies/starknet/serialization/data_serializers/struct_serializer.py +36 -0
  448. ccxt/static_dependencies/starknet/serialization/data_serializers/tuple_serializer.py +36 -0
  449. ccxt/static_dependencies/starknet/serialization/data_serializers/uint256_serializer.py +76 -0
  450. ccxt/static_dependencies/starknet/serialization/data_serializers/uint_serializer.py +100 -0
  451. ccxt/static_dependencies/starknet/serialization/data_serializers/unit_serializer.py +32 -0
  452. ccxt/static_dependencies/starknet/serialization/errors.py +10 -0
  453. ccxt/static_dependencies/starknet/serialization/factory.py +229 -0
  454. ccxt/static_dependencies/starknet/serialization/function_serialization_adapter.py +110 -0
  455. ccxt/static_dependencies/starknet/serialization/tuple_dataclass.py +59 -0
  456. ccxt/static_dependencies/starknet/utils/__init__.py +0 -0
  457. ccxt/static_dependencies/starknet/utils/constructor_args_translator.py +86 -0
  458. ccxt/static_dependencies/starknet/utils/iterable.py +13 -0
  459. ccxt/static_dependencies/starknet/utils/schema.py +13 -0
  460. ccxt/static_dependencies/starknet/utils/typed_data.py +182 -0
  461. ccxt/static_dependencies/starkware/__init__.py +0 -0
  462. ccxt/static_dependencies/starkware/crypto/__init__.py +0 -0
  463. ccxt/static_dependencies/starkware/crypto/fast_pedersen_hash.py +50 -0
  464. ccxt/static_dependencies/starkware/crypto/math_utils.py +78 -0
  465. ccxt/static_dependencies/starkware/crypto/signature.py +2344 -0
  466. ccxt/static_dependencies/starkware/crypto/utils.py +63 -0
  467. ccxt/static_dependencies/sympy/__init__.py +0 -0
  468. ccxt/static_dependencies/sympy/core/__init__.py +0 -0
  469. ccxt/static_dependencies/sympy/core/intfunc.py +35 -0
  470. ccxt/static_dependencies/sympy/external/__init__.py +0 -0
  471. ccxt/static_dependencies/sympy/external/gmpy.py +345 -0
  472. ccxt/static_dependencies/sympy/external/importtools.py +187 -0
  473. ccxt/static_dependencies/sympy/external/ntheory.py +637 -0
  474. ccxt/static_dependencies/sympy/external/pythonmpq.py +341 -0
  475. ccxt/static_dependencies/typing_inspect/__init__.py +0 -0
  476. ccxt/static_dependencies/typing_inspect/typing_inspect.py +851 -0
  477. ccxt/test/{test_async.py → tests_async.py} +456 -391
  478. ccxt/test/tests_helpers.py +285 -0
  479. ccxt/test/tests_init.py +39 -0
  480. ccxt/test/{test_sync.py → tests_sync.py} +456 -393
  481. ccxt/timex.py +123 -70
  482. ccxt/tokocrypto.py +129 -93
  483. ccxt/tradeogre.py +39 -25
  484. ccxt/upbit.py +322 -113
  485. ccxt/vertex.py +2983 -0
  486. ccxt/wavesexchange.py +227 -173
  487. ccxt/wazirx.py +145 -65
  488. ccxt/whitebit.py +533 -138
  489. ccxt/woo.py +1137 -296
  490. ccxt/woofipro.py +2716 -0
  491. ccxt/xt.py +4627 -0
  492. ccxt/yobit.py +159 -92
  493. ccxt/zaif.py +80 -33
  494. ccxt/zonda.py +140 -69
  495. ccxt-4.4.48.dist-info/LICENSE.txt +21 -0
  496. ccxt-4.4.48.dist-info/METADATA +646 -0
  497. ccxt-4.4.48.dist-info/RECORD +669 -0
  498. {ccxt-4.2.77.dist-info → ccxt-4.4.48.dist-info}/WHEEL +1 -1
  499. ccxt/abstract/bitbay.py +0 -47
  500. ccxt/abstract/bitfinex2.py +0 -139
  501. ccxt/abstract/hitbtc3.py +0 -115
  502. ccxt/async_support/bitbay.py +0 -17
  503. ccxt/async_support/bitfinex2.py +0 -3496
  504. ccxt/async_support/flowbtc.py +0 -34
  505. ccxt/bitbay.py +0 -17
  506. ccxt/bitfinex2.py +0 -3496
  507. ccxt/flowbtc.py +0 -34
  508. ccxt/hitbtc3.py +0 -16
  509. ccxt/pro/bitfinex2.py +0 -1081
  510. ccxt/test/base/__init__.py +0 -28
  511. ccxt/test/base/test_account.py +0 -26
  512. ccxt/test/base/test_balance.py +0 -56
  513. ccxt/test/base/test_borrow_interest.py +0 -35
  514. ccxt/test/base/test_borrow_rate.py +0 -32
  515. ccxt/test/base/test_calculate_fee.py +0 -51
  516. ccxt/test/base/test_crypto.py +0 -127
  517. ccxt/test/base/test_currency.py +0 -76
  518. ccxt/test/base/test_datetime.py +0 -103
  519. ccxt/test/base/test_decimal_to_precision.py +0 -392
  520. ccxt/test/base/test_deep_extend.py +0 -68
  521. ccxt/test/base/test_deposit_withdrawal.py +0 -50
  522. ccxt/test/base/test_exchange_datetime_functions.py +0 -76
  523. ccxt/test/base/test_funding_rate_history.py +0 -29
  524. ccxt/test/base/test_last_price.py +0 -32
  525. ccxt/test/base/test_ledger_entry.py +0 -45
  526. ccxt/test/base/test_ledger_item.py +0 -48
  527. ccxt/test/base/test_leverage_tier.py +0 -33
  528. ccxt/test/base/test_margin_mode.py +0 -24
  529. ccxt/test/base/test_margin_modification.py +0 -35
  530. ccxt/test/base/test_market.py +0 -190
  531. ccxt/test/base/test_number.py +0 -411
  532. ccxt/test/base/test_ohlcv.py +0 -32
  533. ccxt/test/base/test_open_interest.py +0 -32
  534. ccxt/test/base/test_order.py +0 -64
  535. ccxt/test/base/test_order_book.py +0 -63
  536. ccxt/test/base/test_position.py +0 -60
  537. ccxt/test/base/test_shared_methods.py +0 -345
  538. ccxt/test/base/test_status.py +0 -24
  539. ccxt/test/base/test_throttle.py +0 -126
  540. ccxt/test/base/test_ticker.py +0 -86
  541. ccxt/test/base/test_trade.py +0 -47
  542. ccxt/test/base/test_trading_fee.py +0 -26
  543. ccxt/test/base/test_transaction.py +0 -39
  544. ccxt-4.2.77.dist-info/METADATA +0 -626
  545. ccxt-4.2.77.dist-info/RECORD +0 -534
  546. {ccxt-4.2.77.dist-info → ccxt-4.4.48.dist-info}/top_level.txt +0 -0
@@ -6,9 +6,10 @@
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.exmo import ImplicitAPI
8
8
  import hashlib
9
- from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
9
+ from ccxt.base.types import Balances, Currencies, Currency, DepositAddress, Int, MarginModification, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFees, Transaction
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
+ from ccxt.base.errors import AuthenticationError
12
13
  from ccxt.base.errors import PermissionDenied
13
14
  from ccxt.base.errors import ArgumentsRequired
14
15
  from ccxt.base.errors import BadRequest
@@ -18,7 +19,6 @@ from ccxt.base.errors import OrderNotFound
18
19
  from ccxt.base.errors import RateLimitExceeded
19
20
  from ccxt.base.errors import OnMaintenance
20
21
  from ccxt.base.errors import InvalidNonce
21
- from ccxt.base.errors import AuthenticationError
22
22
  from ccxt.base.decimal_to_precision import TICK_SIZE
23
23
  from ccxt.base.precise import Precise
24
24
 
@@ -30,7 +30,7 @@ class exmo(Exchange, ImplicitAPI):
30
30
  'id': 'exmo',
31
31
  'name': 'EXMO',
32
32
  'countries': ['LT'], # Lithuania
33
- 'rateLimit': 350, # once every 350 ms ≈ 180 requests per minute ≈ 3 requests per second
33
+ 'rateLimit': 100, # 10 requests per 1 second
34
34
  'version': 'v1.1',
35
35
  'has': {
36
36
  'CORS': None,
@@ -43,6 +43,9 @@ class exmo(Exchange, ImplicitAPI):
43
43
  'cancelOrder': True,
44
44
  'cancelOrders': False,
45
45
  'createDepositAddress': False,
46
+ 'createMarketBuyOrder': True,
47
+ 'createMarketBuyOrderWithCost': True,
48
+ 'createMarketOrderWithCost': True,
46
49
  'createOrder': True,
47
50
  'createStopLimitOrder': True,
48
51
  'createStopMarketOrder': True,
@@ -54,6 +57,8 @@ class exmo(Exchange, ImplicitAPI):
54
57
  'fetchCurrencies': True,
55
58
  'fetchDeposit': True,
56
59
  'fetchDepositAddress': True,
60
+ 'fetchDepositAddresses': False,
61
+ 'fetchDepositAddressesByNetwork': False,
57
62
  'fetchDeposits': True,
58
63
  'fetchDepositsWithdrawals': True,
59
64
  'fetchDepositWithdrawFee': 'emulated',
@@ -74,7 +79,12 @@ class exmo(Exchange, ImplicitAPI):
74
79
  'fetchOrderBook': True,
75
80
  'fetchOrderBooks': True,
76
81
  'fetchOrderTrades': True,
82
+ 'fetchPosition': False,
83
+ 'fetchPositionHistory': False,
77
84
  'fetchPositionMode': False,
85
+ 'fetchPositions': False,
86
+ 'fetchPositionsHistory': False,
87
+ 'fetchPositionsRisk': False,
78
88
  'fetchPremiumIndexOHLCV': False,
79
89
  'fetchTicker': True,
80
90
  'fetchTickers': True,
@@ -216,6 +226,7 @@ class exmo(Exchange, ImplicitAPI):
216
226
  'precisionMode': TICK_SIZE,
217
227
  'exceptions': {
218
228
  'exact': {
229
+ '140333': InvalidOrder, # {"error":{"code":140333,"msg":"The number of characters after the point in the price exceeds the maximum number '8\u003e6'"}}
219
230
  '140434': BadRequest,
220
231
  '40005': AuthenticationError, # Authorization error, incorrect signature
221
232
  '40009': InvalidNonce, #
@@ -245,7 +256,7 @@ class exmo(Exchange, ImplicitAPI):
245
256
  async def modify_margin_helper(self, symbol: str, amount, type, params={}):
246
257
  await self.load_markets()
247
258
  market = self.market(symbol)
248
- request = {
259
+ request: dict = {
249
260
  'position_id': market['id'],
250
261
  'quantity': amount,
251
262
  }
@@ -265,24 +276,29 @@ class exmo(Exchange, ImplicitAPI):
265
276
  margin['amount'] = amount
266
277
  return margin
267
278
 
268
- def parse_margin_modification(self, data, market: Market = None):
279
+ def parse_margin_modification(self, data: dict, market: Market = None) -> MarginModification:
269
280
  #
270
281
  # {}
271
282
  #
272
283
  return {
273
284
  'info': data,
285
+ 'symbol': self.safe_symbol(None, market),
274
286
  'type': None,
287
+ 'marginMode': 'isolated',
275
288
  'amount': None,
276
- 'code': self.safe_value(market, 'quote'),
277
- 'symbol': self.safe_symbol(None, market),
278
289
  'total': None,
290
+ 'code': self.safe_value(market, 'quote'),
279
291
  'status': 'ok',
292
+ 'timestamp': None,
293
+ 'datetime': None,
280
294
  }
281
295
 
282
- async def reduce_margin(self, symbol: str, amount, params={}):
296
+ async def reduce_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
283
297
  """
284
298
  remove margin from a position
285
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#eebf9f25-0289-4946-9482-89872c738449
299
+
300
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#eebf9f25-0289-4946-9482-89872c738449
301
+
286
302
  :param str symbol: unified market symbol
287
303
  :param float amount: the amount of margin to remove
288
304
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -290,10 +306,12 @@ class exmo(Exchange, ImplicitAPI):
290
306
  """
291
307
  return await self.modify_margin_helper(symbol, amount, 'reduce', params)
292
308
 
293
- async def add_margin(self, symbol: str, amount, params={}):
309
+ async def add_margin(self, symbol: str, amount: float, params={}) -> MarginModification:
294
310
  """
295
311
  add margin
296
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#143ef808-79ca-4e49-9e79-a60ea4d8c0e3
312
+
313
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#143ef808-79ca-4e49-9e79-a60ea4d8c0e3
314
+
297
315
  :param str symbol: unified market symbol
298
316
  :param float amount: amount of margin to add
299
317
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -301,11 +319,13 @@ class exmo(Exchange, ImplicitAPI):
301
319
  """
302
320
  return await self.modify_margin_helper(symbol, amount, 'add', params)
303
321
 
304
- async def fetch_trading_fees(self, params={}):
322
+ async def fetch_trading_fees(self, params={}) -> TradingFees:
305
323
  """
306
324
  fetch the trading fees for multiple markets
307
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#90927062-256c-4b03-900f-2b99131f9a54
308
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#7de7e75c-5833-45a8-b937-c2276d235aaa
325
+
326
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#90927062-256c-4b03-900f-2b99131f9a54
327
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#7de7e75c-5833-45a8-b937-c2276d235aaa
328
+
309
329
  :param dict [params]: extra parameters specific to the exchange API endpoint
310
330
  :returns dict: a dictionary of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>` indexed by market symbols
311
331
  """
@@ -351,7 +371,7 @@ class exmo(Exchange, ImplicitAPI):
351
371
  # }
352
372
  #
353
373
  pairs = self.safe_value(response, 'pairs', [])
354
- result = {}
374
+ result: dict = {}
355
375
  for i in range(0, len(pairs)):
356
376
  pair = pairs[i]
357
377
  marketId = self.safe_string(pair, 'name')
@@ -388,7 +408,7 @@ class exmo(Exchange, ImplicitAPI):
388
408
  # },
389
409
  # }
390
410
  #
391
- result = {}
411
+ result: dict = {}
392
412
  for i in range(0, len(self.symbols)):
393
413
  symbol = self.symbols[i]
394
414
  market = self.market(symbol)
@@ -420,11 +440,13 @@ class exmo(Exchange, ImplicitAPI):
420
440
  raise ExchangeError(self.id + ' parseFixedFloatValue() detected an unsupported non-zero percentage-based fee ' + input)
421
441
  return result
422
442
 
423
- async def fetch_transaction_fees(self, codes: List[str] = None, params={}):
443
+ async def fetch_transaction_fees(self, codes: Strings = None, params={}):
424
444
  """
425
- * @deprecated
445
+ @deprecated
426
446
  please use fetchDepositWithdrawFees instead
427
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#4190035d-24b1-453d-833b-37e0a52f88e2
447
+
448
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#4190035d-24b1-453d-833b-37e0a52f88e2
449
+
428
450
  :param str[]|None codes: list of unified currency codes
429
451
  :param dict [params]: extra parameters specific to the exchange API endpoint
430
452
  :returns dict: a list of `transaction fees structures <https://docs.ccxt.com/#/?id=fees-structure>`
@@ -465,7 +487,7 @@ class exmo(Exchange, ImplicitAPI):
465
487
  # ],
466
488
  # }
467
489
  #
468
- result = {}
490
+ result: dict = {}
469
491
  cryptoListKeys = list(cryptoList.keys())
470
492
  for i in range(0, len(cryptoListKeys)):
471
493
  code = cryptoListKeys[i]
@@ -492,7 +514,9 @@ class exmo(Exchange, ImplicitAPI):
492
514
  async def fetch_deposit_withdraw_fees(self, codes: Strings = None, params={}):
493
515
  """
494
516
  fetch deposit and withdraw fees
495
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#4190035d-24b1-453d-833b-37e0a52f88e2
517
+
518
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#4190035d-24b1-453d-833b-37e0a52f88e2
519
+
496
520
  :param str[]|None codes: list of unified currency codes
497
521
  :param dict [params]: extra parameters specific to the exchange API endpoint
498
522
  :returns dict: a list of `transaction fees structures <https://docs.ccxt.com/#/?id=fees-structure>`
@@ -571,11 +595,13 @@ class exmo(Exchange, ImplicitAPI):
571
595
  }
572
596
  return self.assign_default_deposit_withdraw_fees(result)
573
597
 
574
- async def fetch_currencies(self, params={}):
598
+ async def fetch_currencies(self, params={}) -> Currencies:
575
599
  """
576
600
  fetches all available currencies on an exchange
577
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#7cdf0ca8-9ff6-4cf3-aa33-bcec83155c49
578
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#4190035d-24b1-453d-833b-37e0a52f88e2
601
+
602
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#7cdf0ca8-9ff6-4cf3-aa33-bcec83155c49
603
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#4190035d-24b1-453d-833b-37e0a52f88e2
604
+
579
605
  :param dict [params]: extra parameters specific to the exchange API endpoint
580
606
  :returns dict: an associative dictionary of currencies
581
607
  """
@@ -614,7 +640,7 @@ class exmo(Exchange, ImplicitAPI):
614
640
  # ],
615
641
  # }
616
642
  #
617
- result = {}
643
+ result: dict = {}
618
644
  for i in range(0, len(currencyList)):
619
645
  currency = currencyList[i]
620
646
  currencyId = self.safe_string(currency, 'name')
@@ -622,7 +648,7 @@ class exmo(Exchange, ImplicitAPI):
622
648
  providers = self.safe_value(cryptoList, currencyId)
623
649
  active = False
624
650
  type = 'crypto'
625
- limits = {
651
+ limits: dict = {
626
652
  'deposit': {
627
653
  'min': None,
628
654
  'max': None,
@@ -683,10 +709,12 @@ class exmo(Exchange, ImplicitAPI):
683
709
  }
684
710
  return result
685
711
 
686
- async def fetch_markets(self, params={}):
712
+ async def fetch_markets(self, params={}) -> List[Market]:
687
713
  """
688
714
  retrieves data on all markets for exmo
689
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#7de7e75c-5833-45a8-b937-c2276d235aaa
715
+
716
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#7de7e75c-5833-45a8-b937-c2276d235aaa
717
+
690
718
  :param dict [params]: extra parameters specific to the exchange API endpoint
691
719
  :returns dict[]: an array of objects representing market data
692
720
  """
@@ -706,7 +734,7 @@ class exmo(Exchange, ImplicitAPI):
706
734
  # },
707
735
  # }
708
736
  #
709
- marginPairsDict = {}
737
+ marginPairsDict: dict = {}
710
738
  if self.check_required_credentials(False):
711
739
  marginPairs = await self.privatePostMarginPairList(params)
712
740
  #
@@ -810,40 +838,48 @@ class exmo(Exchange, ImplicitAPI):
810
838
  async def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
811
839
  """
812
840
  fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
813
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#65eeb949-74e5-4631-9184-c38387fe53e8
841
+
842
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#65eeb949-74e5-4631-9184-c38387fe53e8
843
+
814
844
  :param str symbol: unified symbol of the market to fetch OHLCV data for
815
845
  :param str timeframe: the length of time each candle represents
816
846
  :param int [since]: timestamp in ms of the earliest candle to fetch
817
847
  :param int [limit]: the maximum amount of candles to fetch
818
848
  :param dict [params]: extra parameters specific to the exchange API endpoint
849
+ :param int [params.until]: timestamp in ms of the latest candle to fetch
819
850
  :returns int[][]: A list of candles ordered, open, high, low, close, volume
820
851
  """
821
852
  await self.load_markets()
822
853
  market = self.market(symbol)
823
- request = {
854
+ until = self.safe_integer_product(params, 'until', 0.001)
855
+ untilIsDefined = (until is not None)
856
+ request: dict = {
824
857
  'symbol': market['id'],
825
858
  'resolution': self.safe_string(self.timeframes, timeframe, timeframe),
826
859
  }
827
- options = self.safe_value(self.options, 'fetchOHLCV')
828
- maxLimit = self.safe_integer(options, 'maxLimit', 3000)
860
+ maxLimit = 3000
829
861
  duration = self.parse_timeframe(timeframe)
830
- now = self.milliseconds()
862
+ now = self.parse_to_int(self.milliseconds() / 1000)
831
863
  if since is None:
864
+ to = min(until, now) if untilIsDefined else now
832
865
  if limit is None:
833
866
  limit = 1000 # cap default at generous amount
834
- if limit > maxLimit:
835
- limit = maxLimit # avoid exception
836
- request['from'] = self.parse_to_int(now / 1000) - limit * duration - 1
837
- request['to'] = self.parse_to_int(now / 1000)
867
+ else:
868
+ limit = min(limit, maxLimit)
869
+ request['from'] = to - (limit * duration) - 1
870
+ request['to'] = to
838
871
  else:
839
872
  request['from'] = self.parse_to_int(since / 1000) - 1
840
- if limit is None:
841
- request['to'] = self.parse_to_int(now / 1000)
873
+ if untilIsDefined:
874
+ request['to'] = min(until, now)
842
875
  else:
843
- if limit > maxLimit:
844
- raise BadRequest(self.id + ' fetchOHLCV() will serve ' + str(maxLimit) + ' candles at most')
845
- to = self.sum(since, limit * duration * 1000)
846
- request['to'] = self.parse_to_int(to / 1000)
876
+ if limit is None:
877
+ limit = maxLimit
878
+ else:
879
+ limit = min(limit, maxLimit)
880
+ to = self.sum(since, limit * duration)
881
+ request['to'] = min(to, now)
882
+ params = self.omit(params, 'until')
847
883
  response = await self.publicGetCandlesHistory(self.extend(request, params))
848
884
  #
849
885
  # {
@@ -854,7 +890,7 @@ class exmo(Exchange, ImplicitAPI):
854
890
  # ]
855
891
  # }
856
892
  #
857
- candles = self.safe_value(response, 'candles', [])
893
+ candles = self.safe_list(response, 'candles', [])
858
894
  return self.parse_ohlcvs(candles, market, timeframe, since, limit)
859
895
 
860
896
  def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
@@ -878,7 +914,7 @@ class exmo(Exchange, ImplicitAPI):
878
914
  ]
879
915
 
880
916
  def parse_balance(self, response) -> Balances:
881
- result = {'info': response}
917
+ result: dict = {'info': response}
882
918
  wallets = self.safe_value(response, 'wallets')
883
919
  if wallets is not None:
884
920
  currencyIds = list(wallets.keys())
@@ -909,8 +945,10 @@ class exmo(Exchange, ImplicitAPI):
909
945
  async def fetch_balance(self, params={}) -> Balances:
910
946
  """
911
947
  query for balance and get the amount of funds available for trading or funds locked in orders
912
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#59c5160f-27a1-4d9a-8cfb-7979c7ffaac6
913
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#c8388df7-1f9f-4d41-81c4-5a387d171dc6
948
+
949
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#59c5160f-27a1-4d9a-8cfb-7979c7ffaac6
950
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#c8388df7-1f9f-4d41-81c4-5a387d171dc6
951
+
914
952
  :param dict [params]: extra parameters specific to the exchange API endpoint
915
953
  :param str [params.marginMode]: *isolated* fetches the isolated margin balance
916
954
  :returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
@@ -953,7 +991,9 @@ class exmo(Exchange, ImplicitAPI):
953
991
  async def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
954
992
  """
955
993
  fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
956
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#c60c51a8-e683-4f45-a000-820723d37871
994
+
995
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#c60c51a8-e683-4f45-a000-820723d37871
996
+
957
997
  :param str symbol: unified symbol of the market to fetch the order book for
958
998
  :param int [limit]: the maximum amount of order book entries to return
959
999
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -961,19 +1001,21 @@ class exmo(Exchange, ImplicitAPI):
961
1001
  """
962
1002
  await self.load_markets()
963
1003
  market = self.market(symbol)
964
- request = {
1004
+ request: dict = {
965
1005
  'pair': market['id'],
966
1006
  }
967
1007
  if limit is not None:
968
1008
  request['limit'] = limit
969
1009
  response = await self.publicGetOrderBook(self.extend(request, params))
970
- result = self.safe_value(response, market['id'])
1010
+ result = self.safe_dict(response, market['id'])
971
1011
  return self.parse_order_book(result, market['symbol'], None, 'bid', 'ask')
972
1012
 
973
1013
  async def fetch_order_books(self, symbols: Strings = None, limit: Int = None, params={}):
974
1014
  """
975
1015
  fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data for multiple markets
976
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#c60c51a8-e683-4f45-a000-820723d37871
1016
+
1017
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#c60c51a8-e683-4f45-a000-820723d37871
1018
+
977
1019
  :param str[]|None symbols: list of unified market symbols, all symbols fetched if None, default is None
978
1020
  :param int [limit]: max number of entries per orderbook to return, default is None
979
1021
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -990,13 +1032,13 @@ class exmo(Exchange, ImplicitAPI):
990
1032
  else:
991
1033
  ids = self.market_ids(symbols)
992
1034
  ids = ','.join(ids)
993
- request = {
1035
+ request: dict = {
994
1036
  'pair': ids,
995
1037
  }
996
1038
  if limit is not None:
997
1039
  request['limit'] = limit
998
1040
  response = await self.publicGetOrderBook(self.extend(request, params))
999
- result = {}
1041
+ result: dict = {}
1000
1042
  marketIds = list(response.keys())
1001
1043
  for i in range(0, len(marketIds)):
1002
1044
  marketId = marketIds[i]
@@ -1004,7 +1046,7 @@ class exmo(Exchange, ImplicitAPI):
1004
1046
  result[symbol] = self.parse_order_book(response[marketId], symbol, None, 'bid', 'ask')
1005
1047
  return result
1006
1048
 
1007
- def parse_ticker(self, ticker, market: Market = None) -> Ticker:
1049
+ def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
1008
1050
  #
1009
1051
  # {
1010
1052
  # "buy_price":"0.00002996",
@@ -1047,7 +1089,9 @@ class exmo(Exchange, ImplicitAPI):
1047
1089
  async def fetch_tickers(self, symbols: Strings = None, params={}) -> Tickers:
1048
1090
  """
1049
1091
  fetches price tickers for multiple markets, statistical information calculated over the past 24 hours for each market
1050
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#4c8e6459-3503-4361-b012-c34bb9f7e385
1092
+
1093
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#4c8e6459-3503-4361-b012-c34bb9f7e385
1094
+
1051
1095
  :param str[]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
1052
1096
  :param dict [params]: extra parameters specific to the exchange API endpoint
1053
1097
  :returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
@@ -1070,7 +1114,7 @@ class exmo(Exchange, ImplicitAPI):
1070
1114
  # }
1071
1115
  # }
1072
1116
  #
1073
- result = {}
1117
+ result: dict = {}
1074
1118
  marketIds = list(response.keys())
1075
1119
  for i in range(0, len(marketIds)):
1076
1120
  marketId = marketIds[i]
@@ -1083,7 +1127,9 @@ class exmo(Exchange, ImplicitAPI):
1083
1127
  async def fetch_ticker(self, symbol: str, params={}) -> Ticker:
1084
1128
  """
1085
1129
  fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
1086
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#4c8e6459-3503-4361-b012-c34bb9f7e385
1130
+
1131
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#4c8e6459-3503-4361-b012-c34bb9f7e385
1132
+
1087
1133
  :param str symbol: unified symbol of the market to fetch the ticker for
1088
1134
  :param dict [params]: extra parameters specific to the exchange API endpoint
1089
1135
  :returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
@@ -1093,7 +1139,7 @@ class exmo(Exchange, ImplicitAPI):
1093
1139
  market = self.market(symbol)
1094
1140
  return self.parse_ticker(response[market['id']], market)
1095
1141
 
1096
- def parse_trade(self, trade, market: Market = None) -> Trade:
1142
+ def parse_trade(self, trade: dict, market: Market = None) -> Trade:
1097
1143
  #
1098
1144
  # fetchTrades(public)
1099
1145
  #
@@ -1183,7 +1229,9 @@ class exmo(Exchange, ImplicitAPI):
1183
1229
  async def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
1184
1230
  """
1185
1231
  get the list of most recent trades for a particular symbol
1186
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#5a5a9c0d-cf17-47f6-9d62-6d4404ebd5ac
1232
+
1233
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#5a5a9c0d-cf17-47f6-9d62-6d4404ebd5ac
1234
+
1187
1235
  :param str symbol: unified symbol of the market to fetch trades for
1188
1236
  :param int [since]: timestamp in ms of the earliest trade to fetch
1189
1237
  :param int [limit]: the maximum amount of trades to fetch
@@ -1192,7 +1240,7 @@ class exmo(Exchange, ImplicitAPI):
1192
1240
  """
1193
1241
  await self.load_markets()
1194
1242
  market = self.market(symbol)
1195
- request = {
1243
+ request: dict = {
1196
1244
  'pair': market['id'],
1197
1245
  }
1198
1246
  response = await self.publicGetTrades(self.extend(request, params))
@@ -1218,20 +1266,22 @@ class exmo(Exchange, ImplicitAPI):
1218
1266
  # ]
1219
1267
  # }
1220
1268
  #
1221
- data = self.safe_value(response, market['id'], [])
1269
+ data = self.safe_list(response, market['id'], [])
1222
1270
  return self.parse_trades(data, market, since, limit)
1223
1271
 
1224
1272
  async def fetch_my_trades(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1225
1273
  """
1226
1274
  fetch all trades made by the user
1227
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#b8d8d9af-4f46-46a1-939b-ad261d79f452 # spot
1228
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#f4b1aaf8-399f-403b-ab5e-4926d967a106 # margin
1275
+
1276
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#b8d8d9af-4f46-46a1-939b-ad261d79f452 # spot
1277
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#f4b1aaf8-399f-403b-ab5e-4926d967a106 # margin
1278
+
1229
1279
  :param str symbol: a symbol is required but it can be a single string, or a non-empty array
1230
1280
  :param int [since]: the earliest time in ms to fetch trades for
1231
1281
  :param int [limit]: *required for margin orders* the maximum number of trades structures to retrieve
1232
1282
  :param dict [params]: extra parameters specific to the exchange API endpoint
1233
- *
1234
- * EXCHANGE SPECIFIC PARAMETERS
1283
+
1284
+ EXCHANGE SPECIFIC PARAMETERS
1235
1285
  :param int [params.offset]: last deal offset, default = 0
1236
1286
  :returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
1237
1287
  """
@@ -1247,7 +1297,7 @@ class exmo(Exchange, ImplicitAPI):
1247
1297
  isSpot = marginMode != 'isolated'
1248
1298
  if limit is None:
1249
1299
  limit = 100
1250
- request = {}
1300
+ request: dict = {}
1251
1301
  if isSpot:
1252
1302
  request['pair'] = pair
1253
1303
  else:
@@ -1313,21 +1363,70 @@ class exmo(Exchange, ImplicitAPI):
1313
1363
  result = self.array_concat(result, trades)
1314
1364
  return self.filter_by_since_limit(result, since, limit)
1315
1365
 
1366
+ async def create_market_order_with_cost(self, symbol: str, side: OrderSide, cost: float, params={}):
1367
+ """
1368
+ create a market order by providing the symbol, side and cost
1369
+
1370
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#80daa469-ec59-4d0a-b229-6a311d8dd1cd
1371
+
1372
+ :param str symbol: unified symbol of the market to create an order in
1373
+ :param str side: 'buy' or 'sell'
1374
+ :param float cost: how much you want to trade in units of the quote currency
1375
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1376
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1377
+ """
1378
+ await self.load_markets()
1379
+ params = self.extend(params, {'cost': cost})
1380
+ return await self.create_order(symbol, 'market', side, cost, None, params)
1381
+
1382
+ async def create_market_buy_order_with_cost(self, symbol: str, cost: float, params={}):
1383
+ """
1384
+ create a market buy order by providing the symbol and cost
1385
+
1386
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#80daa469-ec59-4d0a-b229-6a311d8dd1cd
1387
+
1388
+ :param str symbol: unified symbol of the market to create an order in
1389
+ :param float cost: how much you want to trade in units of the quote currency
1390
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1391
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1392
+ """
1393
+ await self.load_markets()
1394
+ params = self.extend(params, {'cost': cost})
1395
+ return await self.create_order(symbol, 'market', 'buy', cost, None, params)
1396
+
1397
+ async def create_market_sell_order_with_cost(self, symbol: str, cost: float, params={}):
1398
+ """
1399
+ create a market sell order by providing the symbol and cost
1400
+
1401
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#80daa469-ec59-4d0a-b229-6a311d8dd1cd
1402
+
1403
+ :param str symbol: unified symbol of the market to create an order in
1404
+ :param float cost: how much you want to trade in units of the quote currency
1405
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1406
+ :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1407
+ """
1408
+ await self.load_markets()
1409
+ params = self.extend(params, {'cost': cost})
1410
+ return await self.create_order(symbol, 'market', 'sell', cost, None, params)
1411
+
1316
1412
  async def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
1317
1413
  """
1318
1414
  create a trade order
1319
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#80daa469-ec59-4d0a-b229-6a311d8dd1cd
1320
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#de6f4321-eeac-468c-87f7-c4ad7062e265 # stop market
1321
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#3561b86c-9ff1-436e-8e68-ac926b7eb523 # margin
1415
+
1416
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#80daa469-ec59-4d0a-b229-6a311d8dd1cd
1417
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#de6f4321-eeac-468c-87f7-c4ad7062e265 # stop market
1418
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#3561b86c-9ff1-436e-8e68-ac926b7eb523 # margin
1419
+
1322
1420
  :param str symbol: unified symbol of the market to create an order in
1323
1421
  :param str type: 'market' or 'limit'
1324
1422
  :param str side: 'buy' or 'sell'
1325
1423
  :param float amount: how much of currency you want to trade in units of base currency
1326
- :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
1424
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
1327
1425
  :param dict [params]: extra parameters specific to the exchange API endpoint
1328
- :param float [params.stopPrice]: the price at which a trigger order is triggered at
1426
+ :param float [params.triggerPrice]: the price at which a trigger order is triggered at
1329
1427
  :param str [params.timeInForce]: *spot only* 'fok', 'ioc' or 'post_only'
1330
1428
  :param boolean [params.postOnly]: *spot only* True for post only orders
1429
+ :param float [params.cost]: *spot only* *market orders only* the cost of the order in the quote currency for market orders
1331
1430
  :returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1332
1431
  """
1333
1432
  await self.load_markets()
@@ -1338,11 +1437,12 @@ class exmo(Exchange, ImplicitAPI):
1338
1437
  if marginMode == 'cross':
1339
1438
  raise BadRequest(self.id + ' only supports isolated margin')
1340
1439
  isSpot = (marginMode != 'isolated')
1341
- triggerPrice = self.safe_number_n(params, ['triggerPrice', 'stopPrice', 'stop_price'])
1342
- request = {
1440
+ triggerPrice = self.safe_string_n(params, ['triggerPrice', 'stopPrice', 'stop_price'])
1441
+ cost = self.safe_string(params, 'cost')
1442
+ request: dict = {
1343
1443
  'pair': market['id'],
1344
1444
  # 'leverage': 2,
1345
- 'quantity': self.amount_to_precision(market['symbol'], amount),
1445
+ # 'quantity': self.amount_to_precision(market['symbol'], amount),
1346
1446
  # spot - buy, sell, market_buy, market_sell, market_buy_total, market_sell_total
1347
1447
  # margin - limit_buy, limit_sell, market_buy, market_sell, stop_buy, stop_sell, stop_limit_buy, stop_limit_sell, trailing_stop_buy, trailing_stop_sell
1348
1448
  # 'stop_price': self.price_to_precision(symbol, stopPrice),
@@ -1351,6 +1451,10 @@ class exmo(Exchange, ImplicitAPI):
1351
1451
  # 'client_id': 123, # optional, must be a positive integer
1352
1452
  # 'comment': '', # up to 50 latin symbols, whitespaces, underscores
1353
1453
  }
1454
+ if cost is None:
1455
+ request['quantity'] = self.amount_to_precision(market['symbol'], amount)
1456
+ else:
1457
+ request['quantity'] = self.cost_to_precision(market['symbol'], cost)
1354
1458
  clientOrderId = self.safe_value_2(params, 'client_id', 'clientOrderId')
1355
1459
  if clientOrderId is not None:
1356
1460
  clientOrderId = self.safe_integer_2(params, 'client_id', 'clientOrderId')
@@ -1361,7 +1465,7 @@ class exmo(Exchange, ImplicitAPI):
1361
1465
  leverage = self.safe_number(params, 'leverage')
1362
1466
  if not isSpot and (leverage is None):
1363
1467
  raise ArgumentsRequired(self.id + ' createOrder requires an extra param params["leverage"] for margin orders')
1364
- params = self.omit(params, ['stopPrice', 'stop_price', 'triggerPrice', 'timeInForce', 'client_id', 'clientOrderId'])
1468
+ params = self.omit(params, ['stopPrice', 'stop_price', 'triggerPrice', 'timeInForce', 'client_id', 'clientOrderId', 'cost'])
1365
1469
  if price is not None:
1366
1470
  request['price'] = self.price_to_precision(market['symbol'], price)
1367
1471
  response = None
@@ -1382,7 +1486,8 @@ class exmo(Exchange, ImplicitAPI):
1382
1486
  if type == 'limit':
1383
1487
  request['type'] = side
1384
1488
  elif type == 'market':
1385
- request['type'] = 'market_' + side
1489
+ marketSuffix = '_total' if (cost is not None) else ''
1490
+ request['type'] = 'market_' + side + marketSuffix
1386
1491
  if isPostOnly:
1387
1492
  request['exec_type'] = 'post_only'
1388
1493
  elif timeInForce is not None:
@@ -1408,9 +1513,11 @@ class exmo(Exchange, ImplicitAPI):
1408
1513
  async def cancel_order(self, id: str, symbol: Str = None, params={}):
1409
1514
  """
1410
1515
  cancels an open order
1411
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#1f710d4b-75bc-4b65-ad68-006f863a3f26
1412
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#a4d0aae8-28f7-41ac-94fd-c4030130453d # stop market
1413
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#705dfec5-2b35-4667-862b-faf54eca6209 # margin
1516
+
1517
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#1f710d4b-75bc-4b65-ad68-006f863a3f26
1518
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#a4d0aae8-28f7-41ac-94fd-c4030130453d # stop market
1519
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#705dfec5-2b35-4667-862b-faf54eca6209 # margin
1520
+
1414
1521
  :param str id: order id
1415
1522
  :param str symbol: not used by exmo cancelOrder()
1416
1523
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -1419,8 +1526,8 @@ class exmo(Exchange, ImplicitAPI):
1419
1526
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1420
1527
  """
1421
1528
  await self.load_markets()
1422
- request = {}
1423
- stop = self.safe_value_2(params, 'trigger', 'stop')
1529
+ request: dict = {}
1530
+ trigger = self.safe_value_2(params, 'trigger', 'stop')
1424
1531
  params = self.omit(params, ['trigger', 'stop'])
1425
1532
  marginMode = None
1426
1533
  marginMode, params = self.handle_margin_mode_and_params('cancelOrder', params)
@@ -1434,7 +1541,7 @@ class exmo(Exchange, ImplicitAPI):
1434
1541
  # {}
1435
1542
  #
1436
1543
  else:
1437
- if stop:
1544
+ if trigger:
1438
1545
  request['parent_order_id'] = id
1439
1546
  response = await self.privatePostStopMarketOrderCancel(self.extend(request, params))
1440
1547
  #
@@ -1454,13 +1561,16 @@ class exmo(Exchange, ImplicitAPI):
1454
1561
  async def fetch_order(self, id: str, symbol: Str = None, params={}):
1455
1562
  """
1456
1563
  *spot only* fetches information on an order made by the user
1457
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#cf27781e-28e5-4b39-a52d-3110f5d22459 # spot
1564
+
1565
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#cf27781e-28e5-4b39-a52d-3110f5d22459 # spot
1566
+
1567
+ :param str id: order id
1458
1568
  :param str symbol: not used by exmo fetchOrder
1459
1569
  :param dict [params]: extra parameters specific to the exchange API endpoint
1460
1570
  :returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
1461
1571
  """
1462
1572
  await self.load_markets()
1463
- request = {
1573
+ request: dict = {
1464
1574
  'order_id': str(id),
1465
1575
  }
1466
1576
  response = await self.privatePostOrderTrades(self.extend(request, params))
@@ -1492,8 +1602,10 @@ class exmo(Exchange, ImplicitAPI):
1492
1602
  async def fetch_order_trades(self, id: str, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1493
1603
  """
1494
1604
  fetch all the trades made from a single order
1495
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#cf27781e-28e5-4b39-a52d-3110f5d22459 # spot
1496
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#00810661-9119-46c5-aec5-55abe9cb42c7 # margin
1605
+
1606
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#cf27781e-28e5-4b39-a52d-3110f5d22459 # spot
1607
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#00810661-9119-46c5-aec5-55abe9cb42c7 # margin
1608
+
1497
1609
  :param str id: order id
1498
1610
  :param str symbol: unified market symbol
1499
1611
  :param int [since]: the earliest time in ms to fetch trades for
@@ -1509,7 +1621,7 @@ class exmo(Exchange, ImplicitAPI):
1509
1621
  market = None
1510
1622
  if symbol is not None:
1511
1623
  market = self.market(symbol)
1512
- request = {
1624
+ request: dict = {
1513
1625
  'order_id': str(id),
1514
1626
  }
1515
1627
  response = None
@@ -1558,14 +1670,16 @@ class exmo(Exchange, ImplicitAPI):
1558
1670
  # ]
1559
1671
  # }
1560
1672
  #
1561
- trades = self.safe_value(response, 'trades')
1673
+ trades = self.safe_list(response, 'trades')
1562
1674
  return self.parse_trades(trades, market, since, limit)
1563
1675
 
1564
1676
  async def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
1565
1677
  """
1566
1678
  fetch all unfilled currently open orders
1567
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#0e135370-daa4-4689-8acd-b6876dee9ba1 # spot open orders
1568
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#a7cfd4f0-476e-4675-b33f-22a46902f245 # margin
1679
+
1680
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#0e135370-daa4-4689-8acd-b6876dee9ba1 # spot open orders
1681
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#a7cfd4f0-476e-4675-b33f-22a46902f245 # margin
1682
+
1569
1683
  :param str symbol: unified market symbol
1570
1684
  :param int [since]: the earliest time in ms to fetch open orders for
1571
1685
  :param int [limit]: the maximum number of open orders structures to retrieve
@@ -1650,7 +1764,7 @@ class exmo(Exchange, ImplicitAPI):
1650
1764
  def parse_status(self, status):
1651
1765
  if status is None:
1652
1766
  return None
1653
- statuses = {
1767
+ statuses: dict = {
1654
1768
  'cancel_started': 'canceled',
1655
1769
  }
1656
1770
  if status.find('cancel') >= 0:
@@ -1658,7 +1772,7 @@ class exmo(Exchange, ImplicitAPI):
1658
1772
  return self.safe_string(statuses, status, status)
1659
1773
 
1660
1774
  def parse_side(self, orderType):
1661
- side = {
1775
+ side: dict = {
1662
1776
  'limit_buy': 'buy',
1663
1777
  'limit_sell': 'sell',
1664
1778
  'market_buy': 'buy',
@@ -1676,7 +1790,7 @@ class exmo(Exchange, ImplicitAPI):
1676
1790
  }
1677
1791
  return self.safe_string(side, orderType, orderType)
1678
1792
 
1679
- def parse_order(self, order, market: Market = None) -> Order:
1793
+ def parse_order(self, order: dict, market: Market = None) -> Order:
1680
1794
  #
1681
1795
  # fetchOrders, fetchOpenOrders, fetchClosedOrders, fetchCanceledOrders
1682
1796
  #
@@ -1798,7 +1912,6 @@ class exmo(Exchange, ImplicitAPI):
1798
1912
  'postOnly': None,
1799
1913
  'side': side,
1800
1914
  'price': price,
1801
- 'stopPrice': triggerPrice,
1802
1915
  'triggerPrice': triggerPrice,
1803
1916
  'cost': cost,
1804
1917
  'amount': amount,
@@ -1813,8 +1926,10 @@ class exmo(Exchange, ImplicitAPI):
1813
1926
  async def fetch_canceled_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
1814
1927
  """
1815
1928
  fetches information on multiple canceled orders made by the user
1816
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#1d2524dd-ae6d-403a-a067-77b50d13fbe5 # margin
1817
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#a51be1d0-af5f-44e4-99d7-f7b04c6067d0 # spot canceled orders
1929
+
1930
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#1d2524dd-ae6d-403a-a067-77b50d13fbe5 # margin
1931
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#a51be1d0-af5f-44e4-99d7-f7b04c6067d0 # spot canceled orders
1932
+
1818
1933
  :param str symbol: unified market symbol of the market orders were made in
1819
1934
  :param int [since]: timestamp in ms of the earliest order, default is None
1820
1935
  :param int [limit]: max number of orders to return, default is None
@@ -1833,7 +1948,7 @@ class exmo(Exchange, ImplicitAPI):
1833
1948
  if symbol is not None:
1834
1949
  marketInner = self.market(symbol)
1835
1950
  symbol = marketInner['symbol']
1836
- request = {
1951
+ request: dict = {
1837
1952
  'limit': limit,
1838
1953
  }
1839
1954
  request['offset'] = limit if (since is not None) else 0
@@ -1900,18 +2015,20 @@ class exmo(Exchange, ImplicitAPI):
1900
2015
  async def edit_order(self, id: str, symbol: str, type: OrderType, side: OrderSide, amount: Num = None, price: Num = None, params={}):
1901
2016
  """
1902
2017
  *margin only* edit a trade order
1903
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#f27ee040-c75f-4b59-b608-d05bd45b7899 # margin
2018
+
2019
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#f27ee040-c75f-4b59-b608-d05bd45b7899 # margin
2020
+
1904
2021
  :param str id: order id
1905
2022
  :param str symbol: unified CCXT market symbol
1906
2023
  :param str type: not used by exmo editOrder
1907
2024
  :param str side: not used by exmo editOrder
1908
2025
  :param float [amount]: how much of the currency you want to trade in units of the base currency
1909
- :param float [price]: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
2026
+ :param float [price]: the price at which the order is to be fulfilled, in units of the quote currency, ignored in market orders
1910
2027
  :param dict [params]: extra parameters specific to the exchange API endpoint
1911
2028
  :param float [params.triggerPrice]: stop price for stop-market and stop-limit orders
1912
2029
  :param str params['marginMode']: must be set to isolated
1913
- *
1914
- * EXCHANGE SPECIFIC PARAMETERS
2030
+
2031
+ EXCHANGE SPECIFIC PARAMETERS
1915
2032
  :param int [params.distance]: distance for trailing stop orders
1916
2033
  :param int [params.expire]: expiration timestamp in UTC timezone for the order. order will not be expired if expire is 0
1917
2034
  :param str [params.comment]: optional comment for order. up to 50 latin symbols, whitespaces, underscores
@@ -1925,7 +2042,7 @@ class exmo(Exchange, ImplicitAPI):
1925
2042
  raise BadRequest(self.id + ' editOrder() can only be used for isolated margin orders')
1926
2043
  triggerPrice = self.safe_number_n(params, ['triggerPrice', 'stopPrice', 'stop_price'])
1927
2044
  params = self.omit(params, ['triggerPrice', 'stopPrice'])
1928
- request = {
2045
+ request: dict = {
1929
2046
  'order_id': id, # id of the open order
1930
2047
  }
1931
2048
  if amount is not None:
@@ -1937,10 +2054,12 @@ class exmo(Exchange, ImplicitAPI):
1937
2054
  response = await self.privatePostMarginUserOrderUpdate(self.extend(request, params))
1938
2055
  return self.parse_order(response)
1939
2056
 
1940
- async def fetch_deposit_address(self, code: str, params={}):
2057
+ async def fetch_deposit_address(self, code: str, params={}) -> DepositAddress:
1941
2058
  """
1942
2059
  fetch the deposit address for a currency associated with self account
1943
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#c8f9ced9-7ab6-4383-a6a4-bc54469ba60e
2060
+
2061
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#c8f9ced9-7ab6-4383-a6a4-bc54469ba60e
2062
+
1944
2063
  :param str code: unified currency code
1945
2064
  :param dict [params]: extra parameters specific to the exchange API endpoint
1946
2065
  :returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
@@ -1964,11 +2083,11 @@ class exmo(Exchange, ImplicitAPI):
1964
2083
  tag = addressAndTag[1]
1965
2084
  self.check_address(address)
1966
2085
  return {
2086
+ 'info': response,
1967
2087
  'currency': code,
2088
+ 'network': None,
1968
2089
  'address': address,
1969
2090
  'tag': tag,
1970
- 'network': None,
1971
- 'info': response,
1972
2091
  }
1973
2092
 
1974
2093
  def get_market_from_trades(self, trades):
@@ -1979,10 +2098,12 @@ class exmo(Exchange, ImplicitAPI):
1979
2098
  return self.markets[symbols[0]]
1980
2099
  return None
1981
2100
 
1982
- async def withdraw(self, code: str, amount: float, address, tag=None, params={}):
2101
+ async def withdraw(self, code: str, amount: float, address: str, tag=None, params={}) -> Transaction:
1983
2102
  """
1984
2103
  make a withdrawal
1985
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#3ab9c34d-ad58-4f87-9c57-2e2ea88a8325
2104
+
2105
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#3ab9c34d-ad58-4f87-9c57-2e2ea88a8325
2106
+
1986
2107
  :param str code: unified currency code
1987
2108
  :param float amount: the amount to withdraw
1988
2109
  :param str address: the address to withdraw to
@@ -1993,7 +2114,7 @@ class exmo(Exchange, ImplicitAPI):
1993
2114
  tag, params = self.handle_withdraw_tag_and_params(tag, params)
1994
2115
  await self.load_markets()
1995
2116
  currency = self.currency(code)
1996
- request = {
2117
+ request: dict = {
1997
2118
  'amount': amount,
1998
2119
  'currency': currency['id'],
1999
2120
  'address': address,
@@ -2009,8 +2130,8 @@ class exmo(Exchange, ImplicitAPI):
2009
2130
  response = await self.privatePostWithdrawCrypt(self.extend(request, params))
2010
2131
  return self.parse_transaction(response, currency)
2011
2132
 
2012
- def parse_transaction_status(self, status):
2013
- statuses = {
2133
+ def parse_transaction_status(self, status: Str):
2134
+ statuses: dict = {
2014
2135
  'transferred': 'ok',
2015
2136
  'paid': 'ok',
2016
2137
  'pending': 'pending',
@@ -2019,7 +2140,7 @@ class exmo(Exchange, ImplicitAPI):
2019
2140
  }
2020
2141
  return self.safe_string(statuses, status, status)
2021
2142
 
2022
- def parse_transaction(self, transaction, currency: Currency = None) -> Transaction:
2143
+ def parse_transaction(self, transaction: dict, currency: Currency = None) -> Transaction:
2023
2144
  #
2024
2145
  # fetchDepositsWithdrawals
2025
2146
  #
@@ -2146,7 +2267,9 @@ class exmo(Exchange, ImplicitAPI):
2146
2267
  async def fetch_deposits_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
2147
2268
  """
2148
2269
  fetch history of deposits and withdrawals
2149
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#31e69a33-4849-4e6a-b4b4-6d574238f6a7
2270
+
2271
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#31e69a33-4849-4e6a-b4b4-6d574238f6a7
2272
+
2150
2273
  :param str [code]: unified currency code for the currency of the deposit/withdrawals, default is None
2151
2274
  :param int [since]: timestamp in ms of the earliest deposit/withdrawal, default is None
2152
2275
  :param int [limit]: max number of deposit/withdrawals to return, default is None
@@ -2154,7 +2277,7 @@ class exmo(Exchange, ImplicitAPI):
2154
2277
  :returns dict: a list of `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
2155
2278
  """
2156
2279
  await self.load_markets()
2157
- request = {}
2280
+ request: dict = {}
2158
2281
  if since is not None:
2159
2282
  request['date'] = self.parse_to_int(since / 1000)
2160
2283
  currency = None
@@ -2196,7 +2319,9 @@ class exmo(Exchange, ImplicitAPI):
2196
2319
  async def fetch_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
2197
2320
  """
2198
2321
  fetch all withdrawals made from an account
2199
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#97f1becd-7aad-4e0e-babe-7bbe09e33706
2322
+
2323
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#97f1becd-7aad-4e0e-babe-7bbe09e33706
2324
+
2200
2325
  :param str code: unified currency code
2201
2326
  :param int [since]: the earliest time in ms to fetch withdrawals for
2202
2327
  :param int [limit]: the maximum number of withdrawals structures to retrieve
@@ -2205,7 +2330,7 @@ class exmo(Exchange, ImplicitAPI):
2205
2330
  """
2206
2331
  await self.load_markets()
2207
2332
  currency = None
2208
- request = {
2333
+ request: dict = {
2209
2334
  'type': 'withdraw',
2210
2335
  }
2211
2336
  if limit is not None:
@@ -2240,13 +2365,15 @@ class exmo(Exchange, ImplicitAPI):
2240
2365
  # "count": 23
2241
2366
  # }
2242
2367
  #
2243
- items = self.safe_value(response, 'items', [])
2368
+ items = self.safe_list(response, 'items', [])
2244
2369
  return self.parse_transactions(items, currency, since, limit)
2245
2370
 
2246
2371
  async def fetch_withdrawal(self, id: str, code: Str = None, params={}):
2247
2372
  """
2248
2373
  fetch data on a currency withdrawal via the withdrawal id
2249
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#97f1becd-7aad-4e0e-babe-7bbe09e33706
2374
+
2375
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#97f1becd-7aad-4e0e-babe-7bbe09e33706
2376
+
2250
2377
  :param str id: withdrawal id
2251
2378
  :param str code: unified currency code of the currency withdrawn, default is None
2252
2379
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -2254,7 +2381,7 @@ class exmo(Exchange, ImplicitAPI):
2254
2381
  """
2255
2382
  await self.load_markets()
2256
2383
  currency = None
2257
- request = {
2384
+ request: dict = {
2258
2385
  'order_id': id,
2259
2386
  'type': 'withdraw',
2260
2387
  }
@@ -2289,13 +2416,15 @@ class exmo(Exchange, ImplicitAPI):
2289
2416
  # }
2290
2417
  #
2291
2418
  items = self.safe_value(response, 'items', [])
2292
- first = self.safe_value(items, 0, {})
2419
+ first = self.safe_dict(items, 0, {})
2293
2420
  return self.parse_transaction(first, currency)
2294
2421
 
2295
2422
  async def fetch_deposit(self, id=None, code: Str = None, params={}):
2296
2423
  """
2297
2424
  fetch information on a deposit
2298
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#97f1becd-7aad-4e0e-babe-7bbe09e33706
2425
+
2426
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#97f1becd-7aad-4e0e-babe-7bbe09e33706
2427
+
2299
2428
  :param str id: deposit id
2300
2429
  :param str code: unified currency code, default is None
2301
2430
  :param dict [params]: extra parameters specific to the exchange API endpoint
@@ -2303,7 +2432,7 @@ class exmo(Exchange, ImplicitAPI):
2303
2432
  """
2304
2433
  await self.load_markets()
2305
2434
  currency = None
2306
- request = {
2435
+ request: dict = {
2307
2436
  'order_id': id,
2308
2437
  'type': 'deposit',
2309
2438
  }
@@ -2338,13 +2467,15 @@ class exmo(Exchange, ImplicitAPI):
2338
2467
  # }
2339
2468
  #
2340
2469
  items = self.safe_value(response, 'items', [])
2341
- first = self.safe_value(items, 0, {})
2470
+ first = self.safe_dict(items, 0, {})
2342
2471
  return self.parse_transaction(first, currency)
2343
2472
 
2344
2473
  async def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
2345
2474
  """
2346
2475
  fetch all deposits made to an account
2347
- :see: https://documenter.getpostman.com/view/10287440/SzYXWKPi#97f1becd-7aad-4e0e-babe-7bbe09e33706
2476
+
2477
+ https://documenter.getpostman.com/view/10287440/SzYXWKPi#97f1becd-7aad-4e0e-babe-7bbe09e33706
2478
+
2348
2479
  :param str code: unified currency code
2349
2480
  :param int [since]: the earliest time in ms to fetch deposits for
2350
2481
  :param int [limit]: the maximum number of deposits structures to retrieve
@@ -2353,7 +2484,7 @@ class exmo(Exchange, ImplicitAPI):
2353
2484
  """
2354
2485
  await self.load_markets()
2355
2486
  currency = None
2356
- request = {
2487
+ request: dict = {
2357
2488
  'type': 'deposit',
2358
2489
  }
2359
2490
  if limit is not None:
@@ -2388,7 +2519,7 @@ class exmo(Exchange, ImplicitAPI):
2388
2519
  # "count": 23
2389
2520
  # }
2390
2521
  #
2391
- items = self.safe_value(response, 'items', [])
2522
+ items = self.safe_list(response, 'items', [])
2392
2523
  return self.parse_transactions(items, currency, since, limit)
2393
2524
 
2394
2525
  def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
@@ -2413,7 +2544,7 @@ class exmo(Exchange, ImplicitAPI):
2413
2544
  def nonce(self):
2414
2545
  return self.milliseconds()
2415
2546
 
2416
- def handle_errors(self, httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody):
2547
+ def handle_errors(self, httpCode: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
2417
2548
  if response is None:
2418
2549
  return None # fallback to default error handler
2419
2550
  if ('error' in response) and not ('result' in response):